0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-20 21:32:31 -05:00

feat: remove redundant fields and add TS type support in generated files

This commit is contained in:
Gao Sun 2021-07-04 21:17:55 +08:00
parent 266b520015
commit fca35e6933
6 changed files with 61 additions and 38 deletions

View file

@ -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<string, unknown>;
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);

View file

@ -0,0 +1,6 @@
export type OidcModelInstancePayload = {
[key: string]: unknown;
userCode?: string;
uid?: string;
grantId?: string;
};

View file

@ -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<typeof value> => Boolean(value))
.map<Table>(({ 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<Field>((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<GeneratedType>((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<TableWithType>(({ 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 }) =>

View file

@ -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<ParenthesesMatch> => {
const { matched, count, ...rest } = Object.values(value).reduce<{

View file

@ -1 +1,2 @@
export * from './foundations';
export * from './db-entries';

View file

@ -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')
);