Created
August 4, 2023 13:11
-
-
Save jycouet/581e6c4060217d4008099eacd890bca0 to your computer and use it in GitHub Desktop.
[REMULT] - getEntityTypescriptPostgres (Draft 2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
existsSync, | |
lstatSync, | |
mkdir, | |
mkdirSync, | |
readdirSync, | |
rmdirSync, | |
unlinkSync, | |
writeFileSync | |
} from 'fs' | |
import { SqlDatabase, remult } from 'remult' | |
const deleteFolderRecursive = (path) => { | |
if (existsSync(path)) { | |
readdirSync(path).forEach((file) => { | |
const curPath = `${path}/${file}` | |
if (lstatSync(curPath).isDirectory()) { | |
// Recursive call for subdirectories | |
deleteFolderRecursive(curPath) | |
} else { | |
// Delete file | |
unlinkSync(curPath) | |
} | |
}) | |
// Delete empty directory | |
rmdirSync(path) | |
} else { | |
} | |
} | |
const toPascalCase = (str) => { | |
return str.replace(/[-_](\w)/g, (_, c) => c.toUpperCase()).replace(/^\w/, (c) => c.toUpperCase()) | |
} | |
export async function getEntitiesTypescriptPostgres() { | |
const command = SqlDatabase.getDb(remult).createCommand() | |
const result = await command.execute( | |
`SELECT table_name FROM information_schema.tables WHERE table_schema='public';` | |
) | |
deleteFolderRecursive('./src/shared') | |
mkdirSync('./src/shared') | |
const toIgnore = ['PgStatStatements', 'PgStatStatementsInfo', 'PrismaMigrations'] | |
result.rows.forEach(async (c) => { | |
const pascal = toPascalCase(c.table_name) | |
if (!toIgnore.includes(pascal)) { | |
try { | |
writeFileSync(`./src/shared/${pascal}.ts`, await getEntityTypescriptPostgres(c.table_name)) | |
} catch (error) { | |
console.error(error) | |
} | |
} | |
}) | |
} | |
export async function getEntityTypescriptPostgres(table: string, schema = 'public') { | |
const command = SqlDatabase.getDb(remult).createCommand() | |
const commandEnum = SqlDatabase.getDb(remult).createCommand() | |
let cols = '' | |
let enums = '' | |
let props = [] | |
props.push('allowApiCrud: true') | |
if (table.toLocaleLowerCase() != table) { | |
// props.push("dbName: '\"" + table + "\"'"); | |
} | |
let first: string = undefined! | |
for (const { | |
column_name, | |
column_default, | |
data_type, | |
datetime_precision, | |
character_maximum_length, | |
udt_name | |
} of ( | |
await command.execute( | |
`select * from INFORMATION_SCHEMA.COLUMNS where table_schema=${command.addParameterAndReturnSqlToken( | |
schema | |
)} and table_name=${command.addParameterAndReturnSqlToken(table)} | |
order by ordinal_position` | |
) | |
).rows) { | |
let decorator = '@Fields.string' | |
let decoratorArgs = '' | |
let type = '' | |
let defaultVal = "''" | |
switch (data_type) { | |
case 'decimal': | |
case 'real': | |
case 'int': | |
case 'integer': | |
case 'smallint': | |
case 'tinyint': | |
case 'bigint': | |
case 'float': | |
case 'numeric': | |
case 'NUMBER': | |
case 'money': | |
case 'double precision': | |
if (column_default?.startsWith('nextval')) { | |
decorator = '@Fields.autoIncrement' | |
type = 'number' | |
defaultVal = null | |
} else { | |
if (datetime_precision === 0) { | |
decorator = '@Fields.integer' | |
} else { | |
decorator = '@Fields.number' | |
} | |
defaultVal = '0' | |
} | |
break | |
case 'nchar': | |
case 'nvarchar': | |
case 'ntext': | |
case 'NVARCHAR2': | |
case 'text': | |
case 'varchar': | |
case 'VARCHAR2': | |
case 'character varying': | |
break | |
case 'char': | |
case 'CHAR': | |
if (character_maximum_length == 8 && column_default == "('00000000')") { | |
decorator = '@Fields.dateOnly' | |
type = 'Date' | |
} | |
break | |
case 'date': | |
case 'DATE': | |
case 'datetime': | |
case 'datetime2': | |
case 'timestamp without time zone': | |
if (column_name === 'createdAt') { | |
decorator = '@Fields.createdAt' | |
type = 'Date' | |
defaultVal = 'new Date()' | |
} else if (column_name === 'updatedAt') { | |
decorator = '@Fields.updatedAt' | |
type = 'Date' | |
defaultVal = 'new Date()' | |
} else { | |
decorator = '@Fields.date' | |
type = 'Date' | |
} | |
break | |
case 'bit': | |
case 'boolean': | |
decorator = '@Fields.boolean' | |
break | |
case 'ARRAY': | |
decorator = '@Fields.object' | |
defaultVal = '[]' | |
if (udt_name === '_permission_enum') { | |
type = 'permission_enum[]' | |
const local_udt_name = 'permission_enum' | |
const enumDef1 = await commandEnum.execute( | |
`SELECT t.typname, e.enumlabel | |
FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid | |
WHERE t.typname = '${local_udt_name}' | |
ORDER BY t.typname, e.enumlabel;` | |
) | |
// console.log(`enumDef`, enumDef.rows) | |
enums += `export enum ${local_udt_name} { | |
${enumDef1.rows.map((e) => e.enumlabel).join(',\n ')} | |
} | |
` | |
} | |
break | |
case 'USER-DEFINED': | |
decorator = '@Fields.object' | |
if (column_default === null) { | |
defaultVal = 'null' | |
} else { | |
defaultVal = udt_name + '.' + column_default.split("'")[1] | |
} | |
const enumDef2 = await commandEnum.execute( | |
`SELECT t.typname, e.enumlabel | |
FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid | |
WHERE t.typname = '${udt_name}' | |
ORDER BY t.typname, e.enumlabel;` | |
) | |
// console.log(`enumDef`, enumDef.rows) | |
enums += `export enum ${udt_name} { | |
${enumDef2.rows.map((e) => e.enumlabel).join(',\n ')} | |
} | |
` | |
break | |
default: | |
console.log('unmanaged', { | |
table, | |
column_name, | |
data_type, | |
character_maximum_length, | |
column_default, | |
udt_name | |
}) | |
break | |
} | |
if (column_name.toLocaleLowerCase() != column_name || column_name == 'order') | |
decoratorArgs = `{ dbName: '"${column_name}"' }` | |
if (!first) first = column_name | |
cols += '\n\n ' + decorator + `(${decoratorArgs})\n ` + column_name | |
if (type) { | |
// cols += '!' | |
cols += ': ' | |
cols += type | |
} | |
if (defaultVal) { | |
cols += ' = ' + defaultVal | |
} | |
} | |
// props.push(`defaultOrderBy: { ${first}: "asc" }`) | |
let r = | |
`import { Entity, Fields, EntityBase } from "remult"; | |
@Entity<${toPascalCase(table)}>("${table}", { \n ${props.join(',\n ')} \n}) | |
export class ${toPascalCase(table)} extends EntityBase {` + | |
cols + | |
'\n}'.replace(' ', '') + | |
` | |
${enums}` | |
return r | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment