diff --git a/packages/schemas/src/db-entries/oidc-model-instance.ts b/packages/schemas/src/db-entries/oidc-model-instance.ts index a083c08eb..683952733 100644 --- a/packages/schemas/src/db-entries/oidc-model-instance.ts +++ b/packages/schemas/src/db-entries/oidc-model-instance.ts @@ -1,14 +1,13 @@ // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +import { OidcModelInstancePayload } from '../foundations'; + export type OidcModelInstanceDBEntry = { modelName: string; id: string; - payload: Record; + payload: OidcModelInstancePayload; expiresAt: number; consumedAt?: number; - userCode?: string; - uid?: string; - grantId?: string; }; export const OidcModelInstances = Object.freeze({ @@ -19,18 +18,6 @@ export const OidcModelInstances = Object.freeze({ payload: 'payload', expiresAt: 'expires_at', consumedAt: 'consumed_at', - userCode: 'user_code', - uid: 'uid', - grantId: 'grant_id', }, - fieldKeys: [ - 'modelName', - 'id', - 'payload', - 'expiresAt', - 'consumedAt', - 'userCode', - 'uid', - 'grantId', - ], + fieldKeys: ['modelName', 'id', 'payload', 'expiresAt', 'consumedAt'], } as const); diff --git a/packages/schemas/src/foundations.ts b/packages/schemas/src/foundations.ts new file mode 100644 index 000000000..4ba0d569c --- /dev/null +++ b/packages/schemas/src/foundations.ts @@ -0,0 +1,6 @@ +export type OidcModelInstancePayload = { + [key: string]: unknown; + userCode?: string; + uid?: string; + grantId?: string; +}; diff --git a/packages/schemas/src/gen/index.ts b/packages/schemas/src/gen/index.ts index 56b460f71..69a61efa6 100644 --- a/packages/schemas/src/gen/index.ts +++ b/packages/schemas/src/gen/index.ts @@ -12,6 +12,7 @@ type Field = { name: string; type?: string; customType?: string; + tsType?: string; required: boolean; isArray: boolean; }; @@ -56,8 +57,7 @@ const generate = async () => { .split(';') .map((value) => normalizeWhitespaces(value)); const tables = statements - .map((value) => value.toLowerCase()) - .filter((value) => value.startsWith('create table')) + .filter((value) => value.toLowerCase().startsWith('create table')) .map((value) => findFirstParentheses(value)) .filter((value): value is NonNullable => Boolean(value)) .map(({ prefix, body }) => { @@ -69,23 +69,35 @@ const generate = async () => { .map((value) => normalizeWhitespaces(value)) .filter((value) => ['primary', 'foreign', 'unique', 'exclude', 'check'].every( - (constraint) => !value.startsWith(constraint + ' ') + (constraint) => !value.toLowerCase().startsWith(constraint + ' ') ) ) .map((value) => { - const [name, type, ...rest] = value.split(' '); - assert(name && type, 'Missing column name or type: ' + value); + const [nameRaw, typeRaw, ...rest] = value.split(' '); + assert(nameRaw && typeRaw, 'Missing column name or type: ' + value); + const name = nameRaw.toLowerCase(); + const type = typeRaw.toLowerCase(); const restJoined = rest.join(' '); + const restLowercased = restJoined.toLowerCase(); // CAUTION: Only works for single dimension arrays - const isArray = Boolean(/\[.*]/.test(type)) || restJoined.includes('array'); - const required = restJoined.includes('not null'); + const isArray = Boolean(/\[.*]/.test(type)) || restLowercased.includes('array'); + const required = restLowercased.includes('not null'); const primitiveType = getType(type); + const tsType = /\/\* @use (.*) \*\//.exec(restJoined)?.[1]; + + assert( + !(!primitiveType && tsType), + `TS type can only be applied on primitive types, found ${ + tsType ?? 'N/A' + } over ${type}` + ); return { name, type: primitiveType, customType: conditional(!primitiveType && type), + tsType, isArray, required, }; @@ -116,11 +128,14 @@ const generate = async () => { const generatedDir = 'src/db-entries'; const generatedTypesFilename = 'custom-types'; + const tsTypesFilename = '../foundations'; const header = '// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n\n'; const getOutputFileName = (file: string) => pluralize(file.slice(0, -4).replace(/_/g, '-'), 1); await fs.rmdir(generatedDir, { recursive: true }); await fs.mkdir(generatedDir, { recursive: true }); + + // Postgres custom types const allTypes = generated .flatMap((data) => data[1].types) .map((type) => ({ @@ -149,13 +164,18 @@ const generate = async () => { // Generate DB entry types await Promise.all( generated.map(async ([file, { tables }]) => { + const tsTypes: string[] = []; const customTypes: string[] = []; const tableWithTypes = tables.map(({ fields, ...rest }) => ({ ...rest, - fields: fields.map(({ type, customType, ...rest }) => { - const finalType = type ?? allTypes.find(({ name }) => name === customType)?.tsName; + fields: fields.map(({ type, customType, tsType, ...rest }) => { + const finalType = + tsType ?? type ?? allTypes.find(({ name }) => name === customType)?.tsName; assert(finalType, `Type ${customType ?? 'N/A'} not found`); - if (type === undefined) { + + if (tsType) { + tsTypes.push(tsType); + } else if (type === undefined) { customTypes.push(finalType); } @@ -163,6 +183,17 @@ const generate = async () => { }), })); + const importTsTypes = conditionalString( + tsTypes.length > 0 && + [ + 'import {', + uniq(tsTypes) + .map((value) => ` ${value}`) + .join(',\n'), + `} from './${tsTypesFilename}';`, + ].join('\n') + '\n\n' + ); + const importTypes = conditionalString( customTypes.length > 0 && [ @@ -176,6 +207,7 @@ const generate = async () => { const content = header + + importTsTypes + importTypes + tableWithTypes .map(({ name, fields }) => diff --git a/packages/schemas/src/gen/utils.ts b/packages/schemas/src/gen/utils.ts index df199e032..9a1db0634 100644 --- a/packages/schemas/src/gen/utils.ts +++ b/packages/schemas/src/gen/utils.ts @@ -28,7 +28,7 @@ export const removeParentheses = (value: string) => } ).result; -type ParenthesesMatch = { body: string; prefix: string }; +export type ParenthesesMatch = { body: string; prefix: string }; export const findFirstParentheses = (value: string): Optional => { const { matched, count, ...rest } = Object.values(value).reduce<{ diff --git a/packages/schemas/src/index.ts b/packages/schemas/src/index.ts index a3e3629b1..5f8b52015 100644 --- a/packages/schemas/src/index.ts +++ b/packages/schemas/src/index.ts @@ -1 +1,2 @@ +export * from './foundations'; export * from './db-entries'; diff --git a/packages/schemas/tables/oidc_model_instances.sql b/packages/schemas/tables/oidc_model_instances.sql index 30335cd5d..0441cffa2 100644 --- a/packages/schemas/tables/oidc_model_instances.sql +++ b/packages/schemas/tables/oidc_model_instances.sql @@ -1,29 +1,26 @@ create table oidc_model_instances ( model_name varchar(64) not null, id varchar(128) not null, - payload jsonb not null, + payload jsonb /* @use OidcModelInstancePayload */ not null, expires_at bigint not null, consumed_at bigint, - user_code varchar(128), - uid varchar(128), - grant_id varchar(128), primary key (model_name, id) ); -create index oidc_model_instances__model_name_user_code +create index oidc_model_instances__model_name_payload_user_code on oidc_model_instances ( model_name, - user_code + (payload->>'userCode') ); -create index oidc_model_instances__model_name_uid +create index oidc_model_instances__model_name_payload_uid on oidc_model_instances ( model_name, - uid + (payload->>'uid') ); -create index oidc_model_instances__model_name_grant_id +create index oidc_model_instances__model_name_payload_grant_id on oidc_model_instances ( model_name, - grant_id + (payload->>'grantId') );