sonamu 0.2.54 → 0.2.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/base-model-BzMJ2E_I.d.mts +43 -0
  2. package/dist/base-model-CWRKUX49.d.ts +43 -0
  3. package/dist/bin/cli.js +118 -89
  4. package/dist/bin/cli.js.map +1 -1
  5. package/dist/bin/cli.mjs +74 -45
  6. package/dist/bin/cli.mjs.map +1 -1
  7. package/dist/chunk-4K2F3SOM.mjs +231 -0
  8. package/dist/chunk-4K2F3SOM.mjs.map +1 -0
  9. package/dist/chunk-6SP5N5ND.mjs +1579 -0
  10. package/dist/chunk-6SP5N5ND.mjs.map +1 -0
  11. package/dist/chunk-EUP6N7EK.js +1579 -0
  12. package/dist/chunk-EUP6N7EK.js.map +1 -0
  13. package/dist/chunk-HVVCQLAU.mjs +280 -0
  14. package/dist/chunk-HVVCQLAU.mjs.map +1 -0
  15. package/dist/chunk-N6N3LENC.js +231 -0
  16. package/dist/chunk-N6N3LENC.js.map +1 -0
  17. package/dist/chunk-UAG3SKFM.js +280 -0
  18. package/dist/chunk-UAG3SKFM.js.map +1 -0
  19. package/dist/{chunk-JOHF7PK4.js → chunk-WJGRXAXE.js} +5301 -5623
  20. package/dist/chunk-WJGRXAXE.js.map +1 -0
  21. package/dist/{chunk-L4KELCY7.mjs → chunk-ZFLQLW37.mjs} +5252 -5574
  22. package/dist/chunk-ZFLQLW37.mjs.map +1 -0
  23. package/dist/database/drivers/knex/base-model.d.mts +16 -0
  24. package/dist/database/drivers/knex/base-model.d.ts +16 -0
  25. package/dist/database/drivers/knex/base-model.js +55 -0
  26. package/dist/database/drivers/knex/base-model.js.map +1 -0
  27. package/dist/database/drivers/knex/base-model.mjs +56 -0
  28. package/dist/database/drivers/knex/base-model.mjs.map +1 -0
  29. package/dist/database/drivers/kysely/base-model.d.mts +22 -0
  30. package/dist/database/drivers/kysely/base-model.d.ts +22 -0
  31. package/dist/database/drivers/kysely/base-model.js +64 -0
  32. package/dist/database/drivers/kysely/base-model.js.map +1 -0
  33. package/dist/database/drivers/kysely/base-model.mjs +65 -0
  34. package/dist/database/drivers/kysely/base-model.mjs.map +1 -0
  35. package/dist/index.d.mts +226 -931
  36. package/dist/index.d.ts +226 -931
  37. package/dist/index.js +13 -26
  38. package/dist/index.js.map +1 -1
  39. package/dist/index.mjs +18 -31
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/model-CAH_4oQh.d.mts +1042 -0
  42. package/dist/model-CAH_4oQh.d.ts +1042 -0
  43. package/package.json +1 -1
  44. package/src/api/code-converters.ts +1 -1
  45. package/src/entity/migrator.ts +3 -0
  46. package/src/types/types.ts +1 -0
  47. package/dist/chunk-JOHF7PK4.js.map +0 -1
  48. package/dist/chunk-L4KELCY7.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/cli.ts","../../src/smd/smd-manager.ts","../../src/smd/smd.ts"],"sourcesContent":["/* Global Begin */\nimport chalk from \"chalk\";\nconsole.log(chalk.bgBlue(`BEGIN ${new Date()}`));\n\nimport dotenv from \"dotenv\";\ndotenv.config();\n\nimport path from \"path\";\nimport { BaseModel } from \"../database/base-model\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport { Migrator } from \"../entity/migrator\";\nimport { FixtureManager } from \"../testing/fixture-manager\";\nimport { tsicli } from \"tsicli\";\nimport { execSync } from \"child_process\";\nimport fs from \"fs-extra\";\nimport { Sonamu } from \"../api\";\nimport knex, { Knex } from \"knex\";\nimport inflection from \"inflection\";\nimport prettier from \"prettier\";\nimport { SMDManager } from \"../smd/smd-manager\";\nimport process from \"process\";\n\nlet migrator: Migrator;\n\nasync function bootstrap() {\n await Sonamu.init(false, false);\n\n await tsicli(process.argv, {\n types: {\n \"#entityId\": {\n type: \"autocomplete\",\n name: \"#entityId\",\n message: \"Please input #entityId\",\n choices: EntityManager.getAllParentIds().map((entityId) => ({\n title: entityId,\n value: entityId,\n })),\n },\n \"#recordIds\": \"number[]\",\n \"#name\": \"string\",\n },\n args: [\n [\"fixture\", \"init\"],\n [\"fixture\", \"import\", \"#entityId\", \"#recordIds\"],\n [\"fixture\", \"sync\"],\n [\"migrate\", \"run\"],\n [\"migrate\", \"check\"],\n [\"migrate\", \"rollback\"],\n [\"migrate\", \"reset\"],\n [\"migrate\", \"clear\"],\n [\"stub\", \"practice\", \"#name\"],\n [\"stub\", \"entity\", \"#name\"],\n [\"scaffold\", \"model\", \"#entityId\"],\n [\"scaffold\", \"model_test\", \"#entityId\"],\n [\"scaffold\", \"view_list\", \"#entityId\"],\n [\"scaffold\", \"view_form\", \"#entityId\"],\n [\"ui\"],\n [\"smd_migration\"],\n ],\n runners: {\n migrate_run,\n migrate_check,\n migrate_rollback,\n migrate_clear,\n migrate_reset,\n fixture_init,\n fixture_import,\n fixture_sync,\n stub_practice,\n stub_entity,\n scaffold_model,\n scaffold_model_test,\n ui,\n // scaffold_view_list,\n // scaffold_view_form,\n smd_migration,\n },\n });\n}\nbootstrap().finally(async () => {\n if (migrator) {\n await migrator.destroy();\n }\n await FixtureManager.destory();\n await BaseModel.destroy();\n\n /* Global End */\n console.log(chalk.bgBlue(`END ${new Date()}\\n`));\n});\n\nasync function setupMigrator() {\n // migrator\n migrator = new Migrator({\n mode: \"dev\",\n });\n}\n\nasync function setupFixtureManager() {\n FixtureManager.init();\n}\n\nasync function migrate_run() {\n await setupMigrator();\n\n await migrator.cleanUpDist();\n await migrator.run();\n}\n\nasync function migrate_check() {\n await setupMigrator();\n\n await migrator.cleanUpDist();\n await migrator.check();\n}\n\nasync function migrate_rollback() {\n await setupMigrator();\n\n await migrator.rollback();\n}\n\nasync function migrate_clear() {\n await setupMigrator();\n\n await migrator.clearPendingList();\n}\n\nasync function migrate_reset() {\n await setupMigrator();\n\n await migrator.resetAll();\n}\n\nasync function fixture_init() {\n const srcConfig = Sonamu.dbConfig.development_master;\n const targets = [\n {\n label: \"(REMOTE) Fixture DB\",\n config: Sonamu.dbConfig.fixture_remote,\n },\n {\n label: \"(LOCAL) Fixture DB\",\n config: Sonamu.dbConfig.fixture_local,\n toSkip: (() => {\n const remoteConn = Sonamu.dbConfig.fixture_remote\n .connection as Knex.ConnectionConfig;\n const localConn = Sonamu.dbConfig.fixture_local\n .connection as Knex.ConnectionConfig;\n return (\n remoteConn.host === localConn.host &&\n remoteConn.database === localConn.database\n );\n })(),\n },\n {\n label: \"(LOCAL) Testing DB\",\n config: Sonamu.dbConfig.test,\n },\n ] as {\n label: string;\n config: Knex.Config;\n toSkip?: boolean;\n }[];\n\n // 1. 기준DB 스키마를 덤프\n console.log(\"DUMP...\");\n const dumpFilename = `/tmp/sonamu-fixture-init-${Date.now()}.sql`;\n const srcConn = srcConfig.connection as Knex.ConnectionConfig;\n const migrationsDump = `/tmp/sonamu-fixture-init-migrations-${Date.now()}.sql`;\n execSync(\n `mysqldump -h${srcConn.host} -u${srcConn.user} -p${srcConn.password} --single-transaction -d --no-create-db --triggers ${srcConn.database} > ${dumpFilename}`\n );\n execSync(\n `mysqldump -h${srcConn.host} -u${srcConn.user} -p${srcConn.password} --single-transaction --no-create-db --triggers ${srcConn.database} knex_migrations knex_migrations_lock > ${migrationsDump}`\n );\n\n // 2. 대상DB 각각에 대하여 존재여부 확인 후 붓기\n for await (const { label, config, toSkip } of targets) {\n const conn = config.connection as Knex.ConnectionConfig;\n\n if (toSkip === true) {\n console.log(chalk.red(`${label}: Skipped!`));\n continue;\n }\n\n const db = knex({\n ...config,\n connection: {\n ...((config.connection ?? {}) as Knex.ConnectionConfig),\n database: undefined,\n },\n });\n const [[row]] = await db.raw(`SHOW DATABASES LIKE \"${conn.database}\"`);\n if (row) {\n console.log(\n chalk.yellow(`${label}: Database \"${conn.database}\" Already exists`)\n );\n await db.destroy();\n continue;\n }\n\n console.log(`SYNC to ${label}...`);\n const mysqlCmd = `mysql -h${conn.host} -u${conn.user} -p${conn.password}`;\n execSync(`${mysqlCmd} -e 'DROP DATABASE IF EXISTS \\`${conn.database}\\`'`);\n execSync(`${mysqlCmd} -e 'CREATE DATABASE \\`${conn.database}\\`'`);\n execSync(`${mysqlCmd} ${conn.database} < ${dumpFilename}`);\n execSync(`${mysqlCmd} ${conn.database} < ${migrationsDump}`);\n\n await db.destroy();\n }\n}\n\nasync function fixture_import(entityId: string, recordIds: number[]) {\n await setupFixtureManager();\n\n await FixtureManager.importFixture(entityId, recordIds);\n await FixtureManager.sync();\n}\n\nasync function fixture_sync() {\n await setupFixtureManager();\n\n await FixtureManager.sync();\n}\n\nasync function stub_practice(name: string) {\n const practiceDir = path.join(Sonamu.apiRootPath, \"src\", \"practices\");\n const fileNames = fs.readdirSync(practiceDir);\n\n const maxSeqNo = (() => {\n if (fs.existsSync(practiceDir) === false) {\n fs.mkdirSync(practiceDir, { recursive: true });\n }\n\n const filteredSeqs = fileNames\n .filter(\n (fileName) => fileName.startsWith(\"p\") && fileName.endsWith(\".ts\")\n )\n .map((fileName) => {\n const [, seqNo] = fileName.match(/^p([0-9]+)\\-/) ?? [\"0\", \"0\"];\n return parseInt(seqNo);\n })\n .sort((a, b) => b - a);\n\n if (filteredSeqs.length > 0) {\n return filteredSeqs[0];\n }\n\n return 0;\n })();\n\n const currentSeqNo = maxSeqNo + 1;\n const fileName = `p${currentSeqNo}-${name}.ts`;\n const dstPath = path.join(practiceDir, fileName);\n\n const code = [\n `import { BaseModel } from \"sonamu\";`,\n \"\",\n `console.clear();`,\n `console.log(\"${fileName}\");`,\n \"\",\n `async function bootstrap() {`,\n ` // TODO`,\n `}`,\n `bootstrap().finally(async () => {`,\n `await BaseModel.destroy();`,\n `});`,\n ].join(\"\\n\");\n fs.writeFileSync(dstPath, code);\n\n execSync(`code ${dstPath}`);\n\n const runCode = `yarn node -r source-map-support/register dist/practices/${fileName.replace(\n \".ts\",\n \".js\"\n )}`;\n console.log(`${chalk.blue(runCode)} copied to clipboard.`);\n execSync(`echo \"${runCode}\" | pbcopy`);\n}\n\nasync function stub_entity(entityId: string) {\n await Sonamu.syncer.createEntity({ entityId });\n}\n\nasync function scaffold_model(entityId: string) {\n await Sonamu.syncer.generateTemplate(\"model\", {\n entityId,\n });\n}\n\nasync function scaffold_model_test(entityId: string) {\n await Sonamu.syncer.generateTemplate(\"model_test\", {\n entityId,\n });\n}\n\nasync function ui() {\n try {\n const sonamuUI: {\n startServers: (appRootPath: string) => void;\n } = await import(\"@sonamu-kit/ui\" as string);\n sonamuUI.startServers(Sonamu.apiRootPath);\n } catch (e: unknown) {\n if (e instanceof Error && e.message.includes(\"isn't declared\")) {\n console.log(`You need to install ${chalk.blue(`@sonamu-kit/ui`)} first.`);\n return;\n }\n throw e;\n }\n}\n\nasync function smd_migration() {\n await SMDManager.autoload();\n const smdIds = SMDManager.getAllIds();\n\n function enumLabelsToEntityEnums(\n entityId: string,\n enumLabels: {\n [enumName: string]: { [name: string]: { ko: string } };\n }\n ): { [enumName: string]: { [name: string]: string } } {\n return Object.fromEntries(\n Object.entries(enumLabels).map(([enumLabelName, enumLabel]) => {\n const enumName =\n entityId + inflection.camelize(enumLabelName.toLowerCase(), false);\n return [\n enumName,\n Object.fromEntries(\n Object.entries(enumLabel).map(([name, { ko }]) => [name, ko])\n ),\n ];\n })\n );\n }\n for await (const smdId of smdIds) {\n const smd = SMDManager.get(smdId);\n const entityJson = {\n id: smd.id,\n ...(smd.parentId && { parentId: smd.parentId }),\n title: smd.title,\n props: smd.props,\n indexes: smd.indexes,\n subsets: smd.subsets,\n enums: enumLabelsToEntityEnums(smd.id, smd.enumLabels),\n };\n\n const parentNames = SMDManager.getNamesFromId(smd.parentId ?? smd.id);\n const names = SMDManager.getNamesFromId(smd.id);\n const dstPath = path.join(\n Sonamu.apiRootPath,\n \"src\",\n \"application\",\n parentNames.fs,\n `${names.fs}.entity.json`\n );\n\n const formatted = await prettier.format(JSON.stringify(entityJson), {\n parser: \"json\",\n });\n fs.writeFileSync(dstPath, formatted);\n console.log(chalk.blue(`CREATED: ${dstPath}`));\n\n // smd.ts, enums.ts, genereated.ts 삭제 (트랜스파일 된 js파일도 삭제)\n const srcSmdPath = path.join(\n Sonamu.apiRootPath,\n \"src\",\n \"application\",\n parentNames.fs,\n `${names.fs}.smd.ts`\n );\n const dstSmdPath = srcSmdPath\n .replace(\"/src/\", \"/dist/\")\n .replace(/\\.ts$/, \".js\");\n const srcEnumsPath = path.join(\n Sonamu.apiRootPath,\n \"src\",\n \"application\",\n parentNames.fs,\n `${names.fs}.enums.ts`\n );\n const dstEnumsPath = srcEnumsPath\n .replace(\"/src/\", \"/dist/\")\n .replace(/\\.ts$/, \".js\");\n const srcGeneratedPath = path.join(\n Sonamu.apiRootPath,\n \"src\",\n \"application\",\n parentNames.fs,\n `${names.fs}.generated.ts`\n );\n const dstGeneratedPath = srcGeneratedPath\n .replace(\"/src/\", \"/dist/\")\n .replace(/\\.ts$/, \".js\");\n\n [\n srcSmdPath,\n dstSmdPath,\n srcEnumsPath,\n dstEnumsPath,\n ...Sonamu.config.sync.targets.map((target) =>\n srcEnumsPath\n .replace(Sonamu.apiRootPath, path.join(Sonamu.appRootPath, target))\n .replace(\"/src/application/\", \"/src/services/\")\n ),\n srcGeneratedPath,\n dstGeneratedPath,\n ].map((p) => {\n if (fs.existsSync(p) === false) {\n console.log(chalk.yellow(`NOT FOUND: ${p}`));\n return;\n }\n fs.unlinkSync(p);\n console.log(chalk.red(`DELETED: ${p}`));\n });\n }\n\n // Entity로 reload\n console.log(\"Entity로 다시 로드합니다.\");\n EntityManager.isAutoloaded = false;\n await EntityManager.autoload();\n\n // Entity를 통해 generated.ts 재생성\n const entityIds = EntityManager.getAllParentIds();\n for await (const entityId of entityIds) {\n await Sonamu.syncer.generateTemplate(\"generated\", { entityId });\n }\n}\n","import chalk from \"chalk\";\nimport glob from \"glob\";\nimport inflection from \"inflection\";\nimport _ from \"lodash\";\nimport path from \"path\";\nimport { SMD } from \"./smd\";\nimport { SMDInput } from \"../types/types\";\nimport { Sonamu } from \"../api/sonamu\";\nimport { EntityNamesRecord } from \"../entity/entity-manager\";\n\ntype TableSpec = {\n name: string;\n uniqueColumns: string[];\n};\nclass SMDManagerClass {\n private SMDs: Map<string, SMD> = new Map();\n public modulePaths: Map<string, string> = new Map();\n private tableSpecs: Map<string, TableSpec> = new Map();\n public isAutoloaded: boolean = false;\n\n // 경로 전달받아 모든 SMD 파일 로드\n async autoload(doSilent: boolean = false) {\n if (this.isAutoloaded) {\n return;\n }\n const pathPattern = path.join(\n Sonamu.apiRootPath,\n \"/dist/application/**/*.smd.js\"\n );\n !doSilent && console.log(chalk.yellow(`autoload ${pathPattern}`));\n\n return new Promise((resolve) => {\n glob.glob(path.resolve(pathPattern!), (_err, files) => {\n const importPaths = files.map((filePath) =>\n path.relative(__dirname, filePath)\n );\n Promise.all(\n importPaths.map(async (importPath) => {\n const imported = await import(importPath);\n Object.values(imported).map((smdInput) =>\n this.register(smdInput as SMDInput<string>)\n );\n return imported;\n })\n ).then(() => {\n resolve(\"ok\");\n this.isAutoloaded = true;\n });\n });\n });\n }\n\n register(smdInput: SMDInput<string>): void {\n const smd = new SMD(smdInput);\n this.SMDs.set(smdInput.id, smd);\n }\n\n get(smdId: string): SMD {\n const smd = this.SMDs.get(smdId);\n if (smd === undefined) {\n throw new Error(`존재하지 않는 SMD 요청 ${smdId}`);\n }\n\n return smd;\n }\n\n exists(smdId: string): boolean {\n const smd = this.SMDs.get(smdId);\n return smd !== undefined;\n }\n\n getAllIds(): string[] {\n return Array.from(SMDManager.SMDs.keys());\n }\n\n getAllParentIds(): string[] {\n return this.getAllIds().filter((smdId) => {\n const smd = this.get(smdId);\n return smd.parentId === undefined;\n });\n }\n\n getChildrenIds(parentId: string): string[] {\n return this.getAllIds().filter((smdId) => {\n const smd = this.get(smdId);\n return smd.parentId === parentId;\n });\n }\n\n setModulePath(key: string, modulePath: string): void {\n // console.debug(chalk.cyan(`setModulePath :: ${key} :: ${modulePath}`));\n this.modulePaths.set(key, modulePath);\n }\n\n getModulePath(key: string): string {\n const modulePath = this.modulePaths.get(key);\n if (modulePath === undefined) {\n throw new Error(`존재하지 않는 모듈 패스 요청 ${key}`);\n }\n\n return modulePath;\n }\n\n setTableSpec(tableSpec: TableSpec) {\n this.tableSpecs.set(tableSpec.name, tableSpec);\n }\n\n getTableSpec(key: string): TableSpec {\n const tableSpec = this.tableSpecs.get(key);\n if (tableSpec === undefined) {\n throw new Error(`존재하지 않는 테이블 스펙 요청 ${key}`);\n }\n\n return tableSpec;\n }\n\n getNamesFromId(smdId: string): EntityNamesRecord {\n // entityId가 단복수 동형 단어인 경우 List 붙여서 생성\n const pluralized =\n inflection.pluralize(smdId) === smdId\n ? `${smdId}List`\n : inflection.pluralize(smdId);\n\n return {\n fs: inflection.dasherize(inflection.underscore(smdId)).toLowerCase(),\n fsPlural: inflection\n .dasherize(inflection.underscore(pluralized))\n .toLowerCase(),\n camel: inflection.camelize(smdId, true),\n camelPlural: inflection.camelize(pluralized, true),\n capital: smdId,\n capitalPlural: pluralized,\n upper: smdId.toUpperCase(),\n constant: inflection.underscore(smdId).toUpperCase(),\n };\n }\n}\n\nexport const SMDManager = new SMDManagerClass();\n","import _ from \"lodash\";\nimport {\n EntityProp,\n RelationProp,\n isRelationProp,\n SubsetQuery,\n isVirtualProp,\n isBelongsToOneRelationProp,\n isOneToOneRelationProp,\n isHasManyRelationProp,\n isManyToManyRelationProp,\n EntityPropNode,\n isEnumProp,\n StringProp,\n EntityIndex,\n EnumsLabelKo,\n SMDInput,\n} from \"../types/types\";\nimport inflection from \"inflection\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { z } from \"zod\";\nimport { Sonamu } from \"../api/sonamu\";\nimport { SMDManager } from \"./smd-manager\";\n\nexport class SMD {\n id: string;\n parentId?: string;\n table: string;\n title: string;\n names: {\n fs: string;\n module: string;\n };\n props: EntityProp[];\n propsDict: {\n [key: string]: EntityProp;\n };\n relations: {\n [key: string]: RelationProp;\n };\n indexes: EntityIndex[];\n subsets: {\n [key: string]: string[];\n };\n types: {\n [name: string]: z.ZodTypeAny;\n } = {};\n enums: {\n [name: string]: z.ZodEnum<any>;\n } = {};\n enumLabels: {\n [name: string]: EnumsLabelKo<string>;\n } = {};\n\n constructor({\n id,\n parentId,\n table,\n title,\n props,\n indexes,\n subsets,\n }: SMDInput<any>) {\n // id\n this.id = id;\n this.parentId = parentId;\n this.title = title ?? this.id;\n this.table = table ?? inflection.underscore(inflection.pluralize(id));\n\n // props\n if (props) {\n this.props = props.map((prop) => {\n if (isEnumProp(prop)) {\n if (prop.id.includes(\"$Model\")) {\n prop.id = prop.id.replace(\"$Model\", id);\n }\n }\n return prop;\n });\n this.propsDict = props.reduce((result, prop) => {\n return {\n ...result,\n [prop.name]: prop,\n };\n }, {});\n\n // relations\n this.relations = props\n .filter((prop) => isRelationProp(prop))\n .reduce((result, prop) => {\n return {\n ...result,\n [prop.name]: prop,\n };\n }, {});\n } else {\n this.props = [];\n this.propsDict = {};\n this.relations = {};\n }\n\n // indexes\n this.indexes = indexes ?? [];\n\n // subsets\n this.subsets = subsets ?? {};\n\n // names\n this.names = {\n fs:\n parentId === undefined\n ? inflection.dasherize(inflection.underscore(id)).toLowerCase()\n : inflection.dasherize(parentId).toLowerCase(),\n module: id,\n };\n\n this.registerModulePaths();\n this.registerTableSpecs();\n }\n\n /*\n subset SELECT/JOIN/LOADER 결과 리턴\n */\n getSubsetQuery(subsetKey: string): SubsetQuery {\n const subset = this.subsets[subsetKey];\n\n const result: SubsetQuery = this.resolveSubsetQuery(\"\", subset);\n return result;\n }\n\n /*\n */\n resolveSubsetQuery(\n prefix: string,\n fields: string[],\n isAlreadyOuterJoined: boolean = false\n ): SubsetQuery {\n // prefix 치환 (prefix는 ToOneRelation이 복수로 붙은 경우 모두 __로 변경됨)\n prefix = prefix.replace(/\\./g, \"__\");\n\n // 서브셋을 1뎁스만 분리하여 그룹핑\n const subsetGroup = _.groupBy(fields, (field) => {\n if (field.includes(\".\")) {\n const [rel] = field.split(\".\");\n return rel;\n } else {\n return \"\";\n }\n });\n\n const result = Object.keys(subsetGroup).reduce(\n (r, groupKey) => {\n const fields = subsetGroup[groupKey];\n // 현재 테이블 필드셋은 select, virtual에 추가하고 리턴\n if (groupKey === \"\") {\n const realFields = fields.filter(\n (field) => !isVirtualProp(this.propsDict[field])\n );\n const virtualFields = fields.filter((field) =>\n isVirtualProp(this.propsDict[field])\n );\n\n if (prefix === \"\") {\n // 현재 테이블인 경우\n r.select = r.select.concat(\n realFields.map((field) => `${this.table}.${field}`)\n );\n r.virtual = r.virtual.concat(virtualFields);\n } else {\n // 넘어온 테이블인 경우\n r.select = r.select.concat(\n realFields.map(\n (field) => `${prefix}.${field} as ${prefix}__${field}`\n )\n );\n }\n\n return r;\n }\n\n const relation = this.relations[groupKey];\n if (relation === undefined) {\n throw new Error(`존재하지 않는 relation 참조 ${groupKey}`);\n }\n const relSMD = SMDManager.get(relation.with);\n\n if (\n isOneToOneRelationProp(relation) ||\n isBelongsToOneRelationProp(relation)\n ) {\n // -One Relation: JOIN 으로 처리\n const relFields = fields.map((field) =>\n field.split(\".\").slice(1).join(\".\")\n );\n\n // -One Relation에서 id 필드만 참조하는 경우 릴레이션 넘기지 않고 리턴\n if (relFields.length === 1 && relFields[0] === \"id\") {\n if (prefix === \"\") {\n r.select = r.select.concat(`${this.table}.${groupKey}_id`);\n } else {\n r.select = r.select.concat(\n `${prefix}.${groupKey}_id as ${prefix}__${groupKey}_id`\n );\n }\n return r;\n }\n\n // innerOrOuter\n const innerOrOuter = (() => {\n if (isAlreadyOuterJoined) {\n return \"outer\";\n }\n\n if (isOneToOneRelationProp(relation)) {\n if (\n relation.hasJoinColumn === true &&\n (relation.nullable ?? false) === false\n ) {\n return \"inner\";\n } else {\n return \"outer\";\n }\n } else {\n if (relation.nullable) {\n return \"outer\";\n } else {\n return \"inner\";\n }\n }\n })();\n const relSubsetQuery = relSMD.resolveSubsetQuery(\n `${prefix !== \"\" ? prefix + \".\" : \"\"}${groupKey}`,\n relFields,\n innerOrOuter === \"outer\"\n );\n r.select = r.select.concat(relSubsetQuery.select);\n r.virtual = r.virtual.concat(relSubsetQuery.virtual);\n\n const joinAs = prefix === \"\" ? groupKey : prefix + \"__\" + groupKey;\n const fromTable = prefix === \"\" ? this.table : prefix;\n\n let joinClause;\n if (relation.customJoinClause) {\n joinClause = {\n custom: relation.customJoinClause,\n };\n } else {\n let from, to;\n if (isOneToOneRelationProp(relation)) {\n if (relation.hasJoinColumn) {\n from = `${fromTable}.${relation.name}_id`;\n to = `${joinAs}.id`;\n } else {\n from = `${fromTable}.id`;\n to = `${joinAs}.${inflection.underscore(\n this.names.fs.replace(/\\-/g, \"_\")\n )}_id`;\n }\n } else {\n from = `${fromTable}.${relation.name}_id`;\n to = `${joinAs}.id`;\n }\n joinClause = {\n from,\n to,\n };\n }\n\n r.joins.push({\n as: joinAs,\n join: innerOrOuter,\n table: relSMD.table,\n ...joinClause,\n });\n\n // BelongsToOne 밑에 HasMany가 붙은 경우\n if (relSubsetQuery.loaders.length > 0) {\n const convertedLoaders = relSubsetQuery.loaders.map((loader) => {\n const newAs = [groupKey, loader.as].join(\"__\");\n return {\n as: newAs,\n table: loader.table,\n manyJoin: loader.manyJoin,\n oneJoins: loader.oneJoins,\n select: loader.select,\n };\n });\n\n r.loaders = [...r.loaders, ...convertedLoaders];\n }\n\n r.joins = r.joins.concat(relSubsetQuery.joins);\n } else if (\n isHasManyRelationProp(relation) ||\n isManyToManyRelationProp(relation)\n ) {\n // -Many Relation: Loader 로 처리\n const relFields = fields.map((field) =>\n field.split(\".\").slice(1).join(\".\")\n );\n const relSubsetQuery = relSMD.resolveSubsetQuery(\"\", relFields);\n\n let manyJoin: SubsetQuery[\"loaders\"][number][\"manyJoin\"];\n if (isHasManyRelationProp(relation)) {\n manyJoin = {\n fromTable: this.table,\n fromCol: \"id\",\n idField: prefix === \"\" ? `id` : `${prefix}__id`,\n toTable: relSMD.table,\n toCol: relation.joinColumn,\n };\n } else if (isManyToManyRelationProp(relation)) {\n const [table1, table2] = relation.joinTable.split(\"__\");\n\n manyJoin = {\n fromTable: this.table,\n fromCol: \"id\",\n idField: prefix === \"\" ? `id` : `${prefix}__id`,\n through: {\n table: relation.joinTable,\n fromCol: `${inflection.singularize(table1)}_id`,\n toCol: `${inflection.singularize(table2)}_id`,\n },\n toTable: relSMD.table,\n toCol: \"id\",\n };\n } else {\n throw new Error();\n }\n\n r.loaders.push({\n as: groupKey,\n table: relSMD.table,\n manyJoin,\n oneJoins: relSubsetQuery.joins,\n select: relSubsetQuery.select,\n loaders: relSubsetQuery.loaders,\n });\n }\n\n return r;\n },\n {\n select: [],\n virtual: [],\n joins: [],\n loaders: [],\n } as SubsetQuery\n );\n return result;\n }\n\n /*\n FieldExpr[] 을 SMDPropNode[] 로 변환\n */\n fieldExprsToPropNodes(\n fieldExprs: string[],\n smd: SMD = this\n ): EntityPropNode[] {\n const groups = fieldExprs.reduce(\n (result, fieldExpr) => {\n let key, value, elseExpr;\n if (fieldExpr.includes(\".\")) {\n [key, ...elseExpr] = fieldExpr.split(\".\");\n value = elseExpr.join(\".\");\n } else {\n key = \"\";\n value = fieldExpr;\n }\n result[key] = (result[key] ?? []).concat(value);\n\n return result;\n },\n {} as {\n [k: string]: string[];\n }\n );\n\n return Object.keys(groups)\n .map((key) => {\n const group = groups[key];\n\n // 일반 prop 처리\n if (key === \"\") {\n return group.map((propName) => {\n // uuid 개별 처리\n if (propName === \"uuid\") {\n return {\n nodeType: \"plain\" as const,\n prop: {\n type: \"string\",\n name: \"uuid\",\n length: 128,\n } as StringProp,\n children: [],\n };\n }\n\n const prop = smd.propsDict[propName];\n if (prop === undefined) {\n throw new Error(`${this.id} -- 잘못된 FieldExpr ${propName}`);\n }\n return {\n nodeType: \"plain\" as const,\n prop,\n children: [],\n };\n });\n }\n\n // relation prop 처리\n const prop = smd.propsDict[key];\n if (!isRelationProp(prop)) {\n throw new Error(`잘못된 FieldExpr ${key}.${group[0]}`);\n }\n const relSMD = SMDManager.get(prop.with);\n\n // relation -One 에 id 필드 하나인 경우\n if (isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)) {\n if (group.length == 1 && (group[0] === \"id\" || group[0] == \"id?\")) {\n // id 하나만 있는지 체크해서, 하나만 있으면 상위 prop으로 id를 리턴\n const idProp = relSMD.propsDict.id;\n return {\n nodeType: \"plain\" as const,\n prop: {\n ...idProp,\n name: key + \"_id\",\n nullable: prop.nullable,\n },\n children: [],\n };\n }\n }\n\n // -One 그외의 경우 object로 리턴\n // -Many의 경우 array로 리턴\n // Recursive 로 뎁스 처리\n const children = this.fieldExprsToPropNodes(group, relSMD);\n const nodeType =\n isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)\n ? (\"object\" as const)\n : (\"array\" as const);\n\n return {\n prop,\n children,\n nodeType,\n };\n })\n .flat();\n }\n\n getFieldExprs(\n prefix = \"\",\n maxDepth: number = 3,\n froms: string[] = []\n ): string[] {\n return this.props\n .map((prop) => {\n const propName = [prefix, prop.name].filter((v) => v !== \"\").join(\".\");\n if (propName === prefix) {\n return null;\n }\n if (isRelationProp(prop)) {\n if (maxDepth < 0) {\n return null;\n }\n if (froms.includes(prop.with)) {\n // 역방향 relation인 경우 제외\n return null;\n }\n // 정방향 relation인 경우 recursive 콜\n const relMd = SMDManager.get(prop.with);\n return relMd.getFieldExprs(propName, maxDepth - 1, [\n ...froms,\n this.id,\n ]);\n }\n return propName;\n })\n .flat()\n .filter((f) => f !== null) as string[];\n }\n\n registerModulePaths() {\n const basePath = `${this.names.fs}`;\n\n // base-scheme\n SMDManager.setModulePath(\n `${this.id}BaseSchema`,\n `${basePath}/${this.names.fs}.generated`\n );\n\n // subset\n if (Object.keys(this.subsets).length > 0) {\n SMDManager.setModulePath(\n `${this.id}SubsetKey`,\n `${basePath}/${this.names.fs}.generated`\n );\n SMDManager.setModulePath(\n `${this.id}SubsetMapping`,\n `${basePath}/${this.names.fs}.generated`\n );\n Object.keys(this.subsets).map((subsetKey) => {\n SMDManager.setModulePath(\n `${this.id}Subset${subsetKey.toUpperCase()}`,\n `${basePath}/${this.names.fs}.generated`\n );\n });\n }\n\n // types\n const typesModulePath = `${basePath}/${this.names.fs}.types`;\n const typesFileDistPath = path.join(\n Sonamu.apiRootPath,\n `dist/application/${typesModulePath}.js`\n );\n\n if (fs.existsSync(typesFileDistPath)) {\n const importPath = path.relative(__dirname, typesFileDistPath);\n import(importPath).then((t) => {\n this.types = Object.keys(t).reduce((result, key) => {\n SMDManager.setModulePath(key, typesModulePath);\n return {\n ...result,\n [key]: t[key],\n };\n }, {});\n });\n }\n\n // enums\n const enumsModulePath = `${basePath}/${this.names.fs}.enums`;\n const enumsFileDistPath = path.join(\n Sonamu.apiRootPath,\n `/dist/application/${enumsModulePath}.js`\n );\n if (fs.existsSync(enumsFileDistPath)) {\n const importPath = path.relative(__dirname, enumsFileDistPath);\n import(importPath).then((t) => {\n this.enums = Object.keys(t).reduce((result, key) => {\n SMDManager.setModulePath(key, enumsModulePath);\n\n // Enum Labels 별도 처리\n if (key === inflection.underscore(this.id).toUpperCase()) {\n this.enumLabels = t[key];\n }\n return {\n ...result,\n [key]: t[key],\n };\n }, {});\n });\n }\n }\n\n registerTableSpecs(): void {\n const uniqueColumns = _.uniq(\n this.indexes\n .filter((idx) => idx.type === \"unique\")\n .map((idx) => idx.columns)\n .flat()\n );\n\n SMDManager.setTableSpec({\n name: this.table,\n uniqueColumns,\n });\n }\n}\n"],"mappings":"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","names":["chalk","path","fs","inflection","inflection","path","fields","prop","path","inflection","chalk","path","fs","fileName","inflection"]}
1
+ {"version":3,"sources":["../../src/bin/cli.ts","../../src/smd/smd-manager.ts","../../src/smd/smd.ts"],"sourcesContent":["/* Global Begin */\nimport chalk from \"chalk\";\nconsole.log(chalk.bgBlue(`BEGIN ${new Date()}`));\n\nimport dotenv from \"dotenv\";\ndotenv.config();\n\nimport path from \"path\";\nimport { tsicli } from \"tsicli\";\nimport { execSync } from \"child_process\";\nimport fs from \"fs-extra\";\nimport inflection from \"inflection\";\nimport prettier from \"prettier\";\nimport process from \"process\";\nimport _ from \"lodash\";\nimport { Sonamu } from \"../api\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport { Migrator } from \"../entity/migrator\";\nimport { FixtureManager } from \"../testing/fixture-manager\";\nimport { SMDManager } from \"../smd/smd-manager\";\nimport { DB } from \"../database/db\";\nimport {\n KnexConfig,\n KyselyConfig,\n SonamuKnexDBConfig,\n SonamuKyselyDBConfig,\n} from \"../database/types\";\nimport { KnexClient } from \"../database/drivers/knex/client\";\nimport { KyselyClient } from \"../database/drivers/kysely/client\";\n\nlet migrator: Migrator;\n\nasync function bootstrap() {\n await Sonamu.init(false, false);\n\n await tsicli(process.argv, {\n types: {\n \"#entityId\": {\n type: \"autocomplete\",\n name: \"#entityId\",\n message: \"Please input #entityId\",\n choices: EntityManager.getAllParentIds().map((entityId) => ({\n title: entityId,\n value: entityId,\n })),\n },\n \"#recordIds\": \"number[]\",\n \"#name\": \"string\",\n },\n args: [\n [\"fixture\", \"init\"],\n [\"fixture\", \"import\", \"#entityId\", \"#recordIds\"],\n [\"fixture\", \"sync\"],\n [\"migrate\", \"run\"],\n [\"migrate\", \"check\"],\n [\"migrate\", \"rollback\"],\n [\"migrate\", \"reset\"],\n [\"migrate\", \"clear\"],\n [\"migrate\", \"status\"],\n [\"stub\", \"practice\", \"#name\"],\n [\"stub\", \"entity\", \"#name\"],\n [\"scaffold\", \"model\", \"#entityId\"],\n [\"scaffold\", \"model_test\", \"#entityId\"],\n [\"scaffold\", \"view_list\", \"#entityId\"],\n [\"scaffold\", \"view_form\", \"#entityId\"],\n [\"ui\"],\n [\"smd_migration\"],\n ],\n runners: {\n migrate_run,\n migrate_check,\n migrate_rollback,\n migrate_clear,\n migrate_reset,\n migrate_status,\n fixture_init,\n fixture_import,\n fixture_sync,\n stub_practice,\n stub_entity,\n scaffold_model,\n scaffold_model_test,\n ui,\n // scaffold_view_list,\n // scaffold_view_form,\n smd_migration,\n },\n });\n}\nbootstrap().finally(async () => {\n if (migrator) {\n await migrator.destroy();\n }\n await FixtureManager.destory();\n\n /* Global End */\n console.log(chalk.bgBlue(`END ${new Date()}\\n`));\n});\n\nasync function setupMigrator() {\n // migrator\n migrator = new Migrator({\n mode: \"dev\",\n });\n}\n\nasync function setupFixtureManager() {\n FixtureManager.init();\n}\n\nasync function migrate_run() {\n await setupMigrator();\n\n await migrator.cleanUpDist();\n await migrator.run();\n}\n\nasync function migrate_check() {\n await setupMigrator();\n\n await migrator.cleanUpDist();\n await migrator.check();\n}\n\nasync function migrate_status() {\n await setupMigrator();\n\n const status = await migrator.getStatus();\n // status;\n console.log(status);\n}\n\nasync function migrate_rollback() {\n await setupMigrator();\n\n await migrator.rollback();\n}\n\nasync function migrate_clear() {\n await setupMigrator();\n\n await migrator.clearPendingList();\n}\n\nasync function migrate_reset() {\n await setupMigrator();\n\n await migrator.resetAll();\n}\n\nasync function fixture_init() {\n const _db = DB.getClient(\"development_master\");\n const srcConn = _db.connectionInfo;\n\n const targets = [\n {\n label: \"(REMOTE) Fixture DB\",\n connKey: \"fixture_remote\",\n },\n {\n label: \"(LOCAL) Fixture DB\",\n connKey: \"fixture_local\",\n },\n {\n label: \"(LOCAL) Testing DB\",\n connKey: \"test\",\n },\n ] as {\n label: string;\n connKey: keyof SonamuKnexDBConfig | keyof SonamuKyselyDBConfig;\n }[];\n\n // 1. 기준DB 스키마를 덤프\n console.log(\"DUMP...\");\n const dumpFilename = `/tmp/sonamu-fixture-init-${Date.now()}.sql`;\n const migrationsDump = `/tmp/sonamu-fixture-init-migrations-${Date.now()}.sql`;\n execSync(\n `mysqldump -h${srcConn.host} -P${srcConn.port} -u${srcConn.user} -p${srcConn.password} --single-transaction -d --no-create-db --triggers ${srcConn.database} > ${dumpFilename}`\n );\n\n // 2. 마이그레이션 테이블이 존재하면 덤프\n const dbClient = DB.baseConfig!.client;\n const migrationTable = DB.migrationTable;\n const [migrations] = await _db.raw<{ count: number }>(\n \"SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = ? AND table_name = ?\",\n [srcConn.database, migrationTable]\n );\n if (migrations.count > 0) {\n execSync(\n `mysqldump -h${srcConn.host} -P${srcConn.port} -u${srcConn.user} -p${srcConn.password} --single-transaction --no-create-db --triggers ${srcConn.database} ${migrationTable} ${migrationTable}_lock > ${migrationsDump}`\n );\n }\n\n // 2. 대상DB 각각에 대하여 존재여부 확인 후 붓기\n for await (const { label, connKey } of targets) {\n const config = DB.connectionInfo[connKey];\n\n if (\n label === \"(LOCAL) Fixture DB\" &&\n targets.find(\n (t) =>\n t.label === \"(REMOTE) Fixture DB\" &&\n DB.connectionInfo[t.connKey].host === config.host &&\n DB.connectionInfo[t.connKey].database === config.database\n )\n ) {\n console.log(chalk.red(`${label}: Skipped!`));\n continue;\n }\n\n const db = (() => {\n if (dbClient === \"knex\") {\n const config = _.cloneDeep(DB.fullConfig[connKey]) as KnexConfig;\n config.connection.database = undefined;\n return new KnexClient(config);\n } else {\n const config = _.cloneDeep(DB.fullConfig[connKey]) as KyselyConfig;\n config.database = undefined;\n return new KyselyClient(config);\n }\n })();\n\n const [row] = await db.raw(`SHOW DATABASES LIKE \"${config.database}\"`);\n if (row) {\n console.log(\n chalk.yellow(`${label}: Database \"${config.database}\" Already exists`)\n );\n await db.destroy();\n continue;\n }\n\n console.log(`SYNC to ${label}...`);\n const mysqlCmd = `mysql -h${config.host} -P${srcConn.port} -u${config.user} -p${config.password}`;\n execSync(`${mysqlCmd} -e 'DROP DATABASE IF EXISTS \\`${config.database}\\`'`);\n execSync(`${mysqlCmd} -e 'CREATE DATABASE \\`${config.database}\\`'`);\n execSync(`${mysqlCmd} ${config.database} < ${dumpFilename}`);\n if (fs.existsSync(migrationsDump)) {\n execSync(`${mysqlCmd} ${config.database} < ${migrationsDump}`);\n }\n\n await db.destroy();\n }\n}\n\nasync function fixture_import(entityId: string, recordIds: number[]) {\n await setupFixtureManager();\n\n await FixtureManager.importFixture(entityId, recordIds);\n await FixtureManager.sync();\n}\n\nasync function fixture_sync() {\n await setupFixtureManager();\n\n await FixtureManager.sync();\n}\n\nasync function stub_practice(name: string) {\n const practiceDir = path.join(Sonamu.apiRootPath, \"src\", \"practices\");\n const fileNames = fs.readdirSync(practiceDir);\n\n const maxSeqNo = (() => {\n if (fs.existsSync(practiceDir) === false) {\n fs.mkdirSync(practiceDir, { recursive: true });\n }\n\n const filteredSeqs = fileNames\n .filter(\n (fileName) => fileName.startsWith(\"p\") && fileName.endsWith(\".ts\")\n )\n .map((fileName) => {\n const [, seqNo] = fileName.match(/^p([0-9]+)\\-/) ?? [\"0\", \"0\"];\n return parseInt(seqNo);\n })\n .sort((a, b) => b - a);\n\n if (filteredSeqs.length > 0) {\n return filteredSeqs[0];\n }\n\n return 0;\n })();\n\n const currentSeqNo = maxSeqNo + 1;\n const fileName = `p${currentSeqNo}-${name}.ts`;\n const dstPath = path.join(practiceDir, fileName);\n\n // FIXME\n const code = [\n `import { BaseModel } from \"sonamu\";`,\n \"\",\n `console.clear();`,\n `console.log(\"${fileName}\");`,\n \"\",\n `async function bootstrap() {`,\n ` // TODO`,\n `}`,\n `bootstrap().finally(async () => {`,\n `await BaseModel.destroy();`,\n `});`,\n ].join(\"\\n\");\n fs.writeFileSync(dstPath, code);\n\n execSync(`code ${dstPath}`);\n\n const runCode = `yarn node -r source-map-support/register dist/practices/${fileName.replace(\n \".ts\",\n \".js\"\n )}`;\n console.log(`${chalk.blue(runCode)} copied to clipboard.`);\n execSync(`echo \"${runCode}\" | pbcopy`);\n}\n\nasync function stub_entity(entityId: string) {\n await Sonamu.syncer.createEntity({ entityId });\n}\n\nasync function scaffold_model(entityId: string) {\n await Sonamu.syncer.generateTemplate(\"model\", {\n entityId,\n });\n}\n\nasync function scaffold_model_test(entityId: string) {\n await Sonamu.syncer.generateTemplate(\"model_test\", {\n entityId,\n });\n}\n\nasync function ui() {\n try {\n const sonamuUI: {\n startServers: (appRootPath: string) => void;\n } = await import(\"@sonamu-kit/ui\" as string);\n sonamuUI.startServers(Sonamu.apiRootPath);\n } catch (e: unknown) {\n if (e instanceof Error && e.message.includes(\"isn't declared\")) {\n console.log(`You need to install ${chalk.blue(`@sonamu-kit/ui`)} first.`);\n return;\n }\n throw e;\n }\n}\n\nasync function smd_migration() {\n await SMDManager.autoload();\n const smdIds = SMDManager.getAllIds();\n\n function enumLabelsToEntityEnums(\n entityId: string,\n enumLabels: {\n [enumName: string]: { [name: string]: { ko: string } };\n }\n ): { [enumName: string]: { [name: string]: string } } {\n return Object.fromEntries(\n Object.entries(enumLabels).map(([enumLabelName, enumLabel]) => {\n const enumName =\n entityId + inflection.camelize(enumLabelName.toLowerCase(), false);\n return [\n enumName,\n Object.fromEntries(\n Object.entries(enumLabel).map(([name, { ko }]) => [name, ko])\n ),\n ];\n })\n );\n }\n for await (const smdId of smdIds) {\n const smd = SMDManager.get(smdId);\n const entityJson = {\n id: smd.id,\n ...(smd.parentId && { parentId: smd.parentId }),\n title: smd.title,\n props: smd.props,\n indexes: smd.indexes,\n subsets: smd.subsets,\n enums: enumLabelsToEntityEnums(smd.id, smd.enumLabels),\n };\n\n const parentNames = SMDManager.getNamesFromId(smd.parentId ?? smd.id);\n const names = SMDManager.getNamesFromId(smd.id);\n const dstPath = path.join(\n Sonamu.apiRootPath,\n \"src\",\n \"application\",\n parentNames.fs,\n `${names.fs}.entity.json`\n );\n\n const formatted = await prettier.format(JSON.stringify(entityJson), {\n parser: \"json\",\n });\n fs.writeFileSync(dstPath, formatted);\n console.log(chalk.blue(`CREATED: ${dstPath}`));\n\n // smd.ts, enums.ts, genereated.ts 삭제 (트랜스파일 된 js파일도 삭제)\n const srcSmdPath = path.join(\n Sonamu.apiRootPath,\n \"src\",\n \"application\",\n parentNames.fs,\n `${names.fs}.smd.ts`\n );\n const dstSmdPath = srcSmdPath\n .replace(\"/src/\", \"/dist/\")\n .replace(/\\.ts$/, \".js\");\n const srcEnumsPath = path.join(\n Sonamu.apiRootPath,\n \"src\",\n \"application\",\n parentNames.fs,\n `${names.fs}.enums.ts`\n );\n const dstEnumsPath = srcEnumsPath\n .replace(\"/src/\", \"/dist/\")\n .replace(/\\.ts$/, \".js\");\n const srcGeneratedPath = path.join(\n Sonamu.apiRootPath,\n \"src\",\n \"application\",\n parentNames.fs,\n `${names.fs}.generated.ts`\n );\n const dstGeneratedPath = srcGeneratedPath\n .replace(\"/src/\", \"/dist/\")\n .replace(/\\.ts$/, \".js\");\n\n [\n srcSmdPath,\n dstSmdPath,\n srcEnumsPath,\n dstEnumsPath,\n ...Sonamu.config.sync.targets.map((target) =>\n srcEnumsPath\n .replace(Sonamu.apiRootPath, path.join(Sonamu.appRootPath, target))\n .replace(\"/src/application/\", \"/src/services/\")\n ),\n srcGeneratedPath,\n dstGeneratedPath,\n ].map((p) => {\n if (fs.existsSync(p) === false) {\n console.log(chalk.yellow(`NOT FOUND: ${p}`));\n return;\n }\n fs.unlinkSync(p);\n console.log(chalk.red(`DELETED: ${p}`));\n });\n }\n\n // Entity로 reload\n console.log(\"Entity로 다시 로드합니다.\");\n EntityManager.isAutoloaded = false;\n await EntityManager.autoload();\n\n // Entity를 통해 generated.ts 재생성\n const entityIds = EntityManager.getAllParentIds();\n for await (const entityId of entityIds) {\n await Sonamu.syncer.generateTemplate(\"generated\", { entityId });\n }\n}\n","import chalk from \"chalk\";\nimport glob from \"glob\";\nimport inflection from \"inflection\";\nimport _ from \"lodash\";\nimport path from \"path\";\nimport { SMD } from \"./smd\";\nimport { SMDInput } from \"../types/types\";\nimport { Sonamu } from \"../api/sonamu\";\nimport { EntityNamesRecord } from \"../entity/entity-manager\";\n\ntype TableSpec = {\n name: string;\n uniqueColumns: string[];\n};\nclass SMDManagerClass {\n private SMDs: Map<string, SMD> = new Map();\n public modulePaths: Map<string, string> = new Map();\n private tableSpecs: Map<string, TableSpec> = new Map();\n public isAutoloaded: boolean = false;\n\n // 경로 전달받아 모든 SMD 파일 로드\n async autoload(doSilent: boolean = false) {\n if (this.isAutoloaded) {\n return;\n }\n const pathPattern = path.join(\n Sonamu.apiRootPath,\n \"/dist/application/**/*.smd.js\"\n );\n !doSilent && console.log(chalk.yellow(`autoload ${pathPattern}`));\n\n return new Promise((resolve) => {\n glob.glob(path.resolve(pathPattern!), (_err, files) => {\n const importPaths = files.map((filePath) =>\n path.relative(__dirname, filePath)\n );\n Promise.all(\n importPaths.map(async (importPath) => {\n const imported = await import(importPath);\n Object.values(imported).map((smdInput) =>\n this.register(smdInput as SMDInput<string>)\n );\n return imported;\n })\n ).then(() => {\n resolve(\"ok\");\n this.isAutoloaded = true;\n });\n });\n });\n }\n\n register(smdInput: SMDInput<string>): void {\n const smd = new SMD(smdInput);\n this.SMDs.set(smdInput.id, smd);\n }\n\n get(smdId: string): SMD {\n const smd = this.SMDs.get(smdId);\n if (smd === undefined) {\n throw new Error(`존재하지 않는 SMD 요청 ${smdId}`);\n }\n\n return smd;\n }\n\n exists(smdId: string): boolean {\n const smd = this.SMDs.get(smdId);\n return smd !== undefined;\n }\n\n getAllIds(): string[] {\n return Array.from(SMDManager.SMDs.keys());\n }\n\n getAllParentIds(): string[] {\n return this.getAllIds().filter((smdId) => {\n const smd = this.get(smdId);\n return smd.parentId === undefined;\n });\n }\n\n getChildrenIds(parentId: string): string[] {\n return this.getAllIds().filter((smdId) => {\n const smd = this.get(smdId);\n return smd.parentId === parentId;\n });\n }\n\n setModulePath(key: string, modulePath: string): void {\n // console.debug(chalk.cyan(`setModulePath :: ${key} :: ${modulePath}`));\n this.modulePaths.set(key, modulePath);\n }\n\n getModulePath(key: string): string {\n const modulePath = this.modulePaths.get(key);\n if (modulePath === undefined) {\n throw new Error(`존재하지 않는 모듈 패스 요청 ${key}`);\n }\n\n return modulePath;\n }\n\n setTableSpec(tableSpec: TableSpec) {\n this.tableSpecs.set(tableSpec.name, tableSpec);\n }\n\n getTableSpec(key: string): TableSpec {\n const tableSpec = this.tableSpecs.get(key);\n if (tableSpec === undefined) {\n throw new Error(`존재하지 않는 테이블 스펙 요청 ${key}`);\n }\n\n return tableSpec;\n }\n\n getNamesFromId(smdId: string): EntityNamesRecord {\n // entityId가 단복수 동형 단어인 경우 List 붙여서 생성\n const pluralized =\n inflection.pluralize(smdId) === smdId\n ? `${smdId}List`\n : inflection.pluralize(smdId);\n\n return {\n fs: inflection.dasherize(inflection.underscore(smdId)).toLowerCase(),\n fsPlural: inflection\n .dasherize(inflection.underscore(pluralized))\n .toLowerCase(),\n camel: inflection.camelize(smdId, true),\n camelPlural: inflection.camelize(pluralized, true),\n capital: smdId,\n capitalPlural: pluralized,\n upper: smdId.toUpperCase(),\n constant: inflection.underscore(smdId).toUpperCase(),\n };\n }\n}\n\nexport const SMDManager = new SMDManagerClass();\n","import _ from \"lodash\";\nimport {\n EntityProp,\n RelationProp,\n isRelationProp,\n SubsetQuery,\n isVirtualProp,\n isBelongsToOneRelationProp,\n isOneToOneRelationProp,\n isHasManyRelationProp,\n isManyToManyRelationProp,\n EntityPropNode,\n isEnumProp,\n StringProp,\n EntityIndex,\n EnumsLabelKo,\n SMDInput,\n} from \"../types/types\";\nimport inflection from \"inflection\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { z } from \"zod\";\nimport { Sonamu } from \"../api/sonamu\";\nimport { SMDManager } from \"./smd-manager\";\n\nexport class SMD {\n id: string;\n parentId?: string;\n table: string;\n title: string;\n names: {\n fs: string;\n module: string;\n };\n props: EntityProp[];\n propsDict: {\n [key: string]: EntityProp;\n };\n relations: {\n [key: string]: RelationProp;\n };\n indexes: EntityIndex[];\n subsets: {\n [key: string]: string[];\n };\n types: {\n [name: string]: z.ZodTypeAny;\n } = {};\n enums: {\n [name: string]: z.ZodEnum<any>;\n } = {};\n enumLabels: {\n [name: string]: EnumsLabelKo<string>;\n } = {};\n\n constructor({\n id,\n parentId,\n table,\n title,\n props,\n indexes,\n subsets,\n }: SMDInput<any>) {\n // id\n this.id = id;\n this.parentId = parentId;\n this.title = title ?? this.id;\n this.table = table ?? inflection.underscore(inflection.pluralize(id));\n\n // props\n if (props) {\n this.props = props.map((prop) => {\n if (isEnumProp(prop)) {\n if (prop.id.includes(\"$Model\")) {\n prop.id = prop.id.replace(\"$Model\", id);\n }\n }\n return prop;\n });\n this.propsDict = props.reduce((result, prop) => {\n return {\n ...result,\n [prop.name]: prop,\n };\n }, {});\n\n // relations\n this.relations = props\n .filter((prop) => isRelationProp(prop))\n .reduce((result, prop) => {\n return {\n ...result,\n [prop.name]: prop,\n };\n }, {});\n } else {\n this.props = [];\n this.propsDict = {};\n this.relations = {};\n }\n\n // indexes\n this.indexes = indexes ?? [];\n\n // subsets\n this.subsets = subsets ?? {};\n\n // names\n this.names = {\n fs:\n parentId === undefined\n ? inflection.dasherize(inflection.underscore(id)).toLowerCase()\n : inflection.dasherize(parentId).toLowerCase(),\n module: id,\n };\n\n this.registerModulePaths();\n this.registerTableSpecs();\n }\n\n /*\n subset SELECT/JOIN/LOADER 결과 리턴\n */\n getSubsetQuery(subsetKey: string): SubsetQuery {\n const subset = this.subsets[subsetKey];\n\n const result: SubsetQuery = this.resolveSubsetQuery(\"\", subset);\n return result;\n }\n\n /*\n */\n resolveSubsetQuery(\n prefix: string,\n fields: string[],\n isAlreadyOuterJoined: boolean = false\n ): SubsetQuery {\n // prefix 치환 (prefix는 ToOneRelation이 복수로 붙은 경우 모두 __로 변경됨)\n prefix = prefix.replace(/\\./g, \"__\");\n\n // 서브셋을 1뎁스만 분리하여 그룹핑\n const subsetGroup = _.groupBy(fields, (field) => {\n if (field.includes(\".\")) {\n const [rel] = field.split(\".\");\n return rel;\n } else {\n return \"\";\n }\n });\n\n const result = Object.keys(subsetGroup).reduce(\n (r, groupKey) => {\n const fields = subsetGroup[groupKey];\n // 현재 테이블 필드셋은 select, virtual에 추가하고 리턴\n if (groupKey === \"\") {\n const realFields = fields.filter(\n (field) => !isVirtualProp(this.propsDict[field])\n );\n const virtualFields = fields.filter((field) =>\n isVirtualProp(this.propsDict[field])\n );\n\n if (prefix === \"\") {\n // 현재 테이블인 경우\n r.select = r.select.concat(\n realFields.map((field) => `${this.table}.${field}`)\n );\n r.virtual = r.virtual.concat(virtualFields);\n } else {\n // 넘어온 테이블인 경우\n r.select = r.select.concat(\n realFields.map(\n (field) => `${prefix}.${field} as ${prefix}__${field}`\n )\n );\n }\n\n return r;\n }\n\n const relation = this.relations[groupKey];\n if (relation === undefined) {\n throw new Error(`존재하지 않는 relation 참조 ${groupKey}`);\n }\n const relSMD = SMDManager.get(relation.with);\n\n if (\n isOneToOneRelationProp(relation) ||\n isBelongsToOneRelationProp(relation)\n ) {\n // -One Relation: JOIN 으로 처리\n const relFields = fields.map((field) =>\n field.split(\".\").slice(1).join(\".\")\n );\n\n // -One Relation에서 id 필드만 참조하는 경우 릴레이션 넘기지 않고 리턴\n if (relFields.length === 1 && relFields[0] === \"id\") {\n if (prefix === \"\") {\n r.select = r.select.concat(`${this.table}.${groupKey}_id`);\n } else {\n r.select = r.select.concat(\n `${prefix}.${groupKey}_id as ${prefix}__${groupKey}_id`\n );\n }\n return r;\n }\n\n // innerOrOuter\n const innerOrOuter = (() => {\n if (isAlreadyOuterJoined) {\n return \"outer\";\n }\n\n if (isOneToOneRelationProp(relation)) {\n if (\n relation.hasJoinColumn === true &&\n (relation.nullable ?? false) === false\n ) {\n return \"inner\";\n } else {\n return \"outer\";\n }\n } else {\n if (relation.nullable) {\n return \"outer\";\n } else {\n return \"inner\";\n }\n }\n })();\n const relSubsetQuery = relSMD.resolveSubsetQuery(\n `${prefix !== \"\" ? prefix + \".\" : \"\"}${groupKey}`,\n relFields,\n innerOrOuter === \"outer\"\n );\n r.select = r.select.concat(relSubsetQuery.select);\n r.virtual = r.virtual.concat(relSubsetQuery.virtual);\n\n const joinAs = prefix === \"\" ? groupKey : prefix + \"__\" + groupKey;\n const fromTable = prefix === \"\" ? this.table : prefix;\n\n let joinClause;\n if (relation.customJoinClause) {\n joinClause = {\n custom: relation.customJoinClause,\n };\n } else {\n let from, to;\n if (isOneToOneRelationProp(relation)) {\n if (relation.hasJoinColumn) {\n from = `${fromTable}.${relation.name}_id`;\n to = `${joinAs}.id`;\n } else {\n from = `${fromTable}.id`;\n to = `${joinAs}.${inflection.underscore(\n this.names.fs.replace(/\\-/g, \"_\")\n )}_id`;\n }\n } else {\n from = `${fromTable}.${relation.name}_id`;\n to = `${joinAs}.id`;\n }\n joinClause = {\n from,\n to,\n };\n }\n\n r.joins.push({\n as: joinAs,\n join: innerOrOuter,\n table: relSMD.table,\n ...joinClause,\n });\n\n // BelongsToOne 밑에 HasMany가 붙은 경우\n if (relSubsetQuery.loaders.length > 0) {\n const convertedLoaders = relSubsetQuery.loaders.map((loader) => {\n const newAs = [groupKey, loader.as].join(\"__\");\n return {\n as: newAs,\n table: loader.table,\n manyJoin: loader.manyJoin,\n oneJoins: loader.oneJoins,\n select: loader.select,\n };\n });\n\n r.loaders = [...r.loaders, ...convertedLoaders];\n }\n\n r.joins = r.joins.concat(relSubsetQuery.joins);\n } else if (\n isHasManyRelationProp(relation) ||\n isManyToManyRelationProp(relation)\n ) {\n // -Many Relation: Loader 로 처리\n const relFields = fields.map((field) =>\n field.split(\".\").slice(1).join(\".\")\n );\n const relSubsetQuery = relSMD.resolveSubsetQuery(\"\", relFields);\n\n let manyJoin: SubsetQuery[\"loaders\"][number][\"manyJoin\"];\n if (isHasManyRelationProp(relation)) {\n manyJoin = {\n fromTable: this.table,\n fromCol: \"id\",\n idField: prefix === \"\" ? `id` : `${prefix}__id`,\n toTable: relSMD.table,\n toCol: relation.joinColumn,\n };\n } else if (isManyToManyRelationProp(relation)) {\n const [table1, table2] = relation.joinTable.split(\"__\");\n\n manyJoin = {\n fromTable: this.table,\n fromCol: \"id\",\n idField: prefix === \"\" ? `id` : `${prefix}__id`,\n through: {\n table: relation.joinTable,\n fromCol: `${inflection.singularize(table1)}_id`,\n toCol: `${inflection.singularize(table2)}_id`,\n },\n toTable: relSMD.table,\n toCol: \"id\",\n };\n } else {\n throw new Error();\n }\n\n r.loaders.push({\n as: groupKey,\n table: relSMD.table,\n manyJoin,\n oneJoins: relSubsetQuery.joins,\n select: relSubsetQuery.select,\n loaders: relSubsetQuery.loaders,\n });\n }\n\n return r;\n },\n {\n select: [],\n virtual: [],\n joins: [],\n loaders: [],\n } as SubsetQuery\n );\n return result;\n }\n\n /*\n FieldExpr[] 을 SMDPropNode[] 로 변환\n */\n fieldExprsToPropNodes(\n fieldExprs: string[],\n smd: SMD = this\n ): EntityPropNode[] {\n const groups = fieldExprs.reduce(\n (result, fieldExpr) => {\n let key, value, elseExpr;\n if (fieldExpr.includes(\".\")) {\n [key, ...elseExpr] = fieldExpr.split(\".\");\n value = elseExpr.join(\".\");\n } else {\n key = \"\";\n value = fieldExpr;\n }\n result[key] = (result[key] ?? []).concat(value);\n\n return result;\n },\n {} as {\n [k: string]: string[];\n }\n );\n\n return Object.keys(groups)\n .map((key) => {\n const group = groups[key];\n\n // 일반 prop 처리\n if (key === \"\") {\n return group.map((propName) => {\n // uuid 개별 처리\n if (propName === \"uuid\") {\n return {\n nodeType: \"plain\" as const,\n prop: {\n type: \"string\",\n name: \"uuid\",\n length: 128,\n } as StringProp,\n children: [],\n };\n }\n\n const prop = smd.propsDict[propName];\n if (prop === undefined) {\n throw new Error(`${this.id} -- 잘못된 FieldExpr ${propName}`);\n }\n return {\n nodeType: \"plain\" as const,\n prop,\n children: [],\n };\n });\n }\n\n // relation prop 처리\n const prop = smd.propsDict[key];\n if (!isRelationProp(prop)) {\n throw new Error(`잘못된 FieldExpr ${key}.${group[0]}`);\n }\n const relSMD = SMDManager.get(prop.with);\n\n // relation -One 에 id 필드 하나인 경우\n if (isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)) {\n if (group.length == 1 && (group[0] === \"id\" || group[0] == \"id?\")) {\n // id 하나만 있는지 체크해서, 하나만 있으면 상위 prop으로 id를 리턴\n const idProp = relSMD.propsDict.id;\n return {\n nodeType: \"plain\" as const,\n prop: {\n ...idProp,\n name: key + \"_id\",\n nullable: prop.nullable,\n },\n children: [],\n };\n }\n }\n\n // -One 그외의 경우 object로 리턴\n // -Many의 경우 array로 리턴\n // Recursive 로 뎁스 처리\n const children = this.fieldExprsToPropNodes(group, relSMD);\n const nodeType =\n isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)\n ? (\"object\" as const)\n : (\"array\" as const);\n\n return {\n prop,\n children,\n nodeType,\n };\n })\n .flat();\n }\n\n getFieldExprs(\n prefix = \"\",\n maxDepth: number = 3,\n froms: string[] = []\n ): string[] {\n return this.props\n .map((prop) => {\n const propName = [prefix, prop.name].filter((v) => v !== \"\").join(\".\");\n if (propName === prefix) {\n return null;\n }\n if (isRelationProp(prop)) {\n if (maxDepth < 0) {\n return null;\n }\n if (froms.includes(prop.with)) {\n // 역방향 relation인 경우 제외\n return null;\n }\n // 정방향 relation인 경우 recursive 콜\n const relMd = SMDManager.get(prop.with);\n return relMd.getFieldExprs(propName, maxDepth - 1, [\n ...froms,\n this.id,\n ]);\n }\n return propName;\n })\n .flat()\n .filter((f) => f !== null) as string[];\n }\n\n registerModulePaths() {\n const basePath = `${this.names.fs}`;\n\n // base-scheme\n SMDManager.setModulePath(\n `${this.id}BaseSchema`,\n `${basePath}/${this.names.fs}.generated`\n );\n\n // subset\n if (Object.keys(this.subsets).length > 0) {\n SMDManager.setModulePath(\n `${this.id}SubsetKey`,\n `${basePath}/${this.names.fs}.generated`\n );\n SMDManager.setModulePath(\n `${this.id}SubsetMapping`,\n `${basePath}/${this.names.fs}.generated`\n );\n Object.keys(this.subsets).map((subsetKey) => {\n SMDManager.setModulePath(\n `${this.id}Subset${subsetKey.toUpperCase()}`,\n `${basePath}/${this.names.fs}.generated`\n );\n });\n }\n\n // types\n const typesModulePath = `${basePath}/${this.names.fs}.types`;\n const typesFileDistPath = path.join(\n Sonamu.apiRootPath,\n `dist/application/${typesModulePath}.js`\n );\n\n if (fs.existsSync(typesFileDistPath)) {\n const importPath = path.relative(__dirname, typesFileDistPath);\n import(importPath).then((t) => {\n this.types = Object.keys(t).reduce((result, key) => {\n SMDManager.setModulePath(key, typesModulePath);\n return {\n ...result,\n [key]: t[key],\n };\n }, {});\n });\n }\n\n // enums\n const enumsModulePath = `${basePath}/${this.names.fs}.enums`;\n const enumsFileDistPath = path.join(\n Sonamu.apiRootPath,\n `/dist/application/${enumsModulePath}.js`\n );\n if (fs.existsSync(enumsFileDistPath)) {\n const importPath = path.relative(__dirname, enumsFileDistPath);\n import(importPath).then((t) => {\n this.enums = Object.keys(t).reduce((result, key) => {\n SMDManager.setModulePath(key, enumsModulePath);\n\n // Enum Labels 별도 처리\n if (key === inflection.underscore(this.id).toUpperCase()) {\n this.enumLabels = t[key];\n }\n return {\n ...result,\n [key]: t[key],\n };\n }, {});\n });\n }\n }\n\n registerTableSpecs(): void {\n const uniqueColumns = _.uniq(\n this.indexes\n .filter((idx) => idx.type === \"unique\")\n .map((idx) => idx.columns)\n .flat()\n );\n\n SMDManager.setTableSpec({\n name: this.table,\n uniqueColumns,\n });\n }\n}\n"],"mappings":"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","names":["chalk","path","fs","inflection","_","inflection","path","fields","prop","path","inflection","chalk","config","_","fs","path","fileName","inflection"]}
@@ -0,0 +1,231 @@
1
+ import {
2
+ DB
3
+ } from "./chunk-ZFLQLW37.mjs";
4
+
5
+ // src/database/base-model.ts
6
+ import { DateTime } from "luxon";
7
+ import _2 from "lodash";
8
+ import SqlParser from "node-sql-parser";
9
+ import chalk from "chalk";
10
+ import inflection from "inflection";
11
+
12
+ // src/utils/sql-parser.ts
13
+ import _ from "lodash";
14
+ function getTableName(expr) {
15
+ if ("table" in expr && expr.table !== null) {
16
+ return typeof expr.table === "string" ? expr.table : expr.table.value;
17
+ }
18
+ return null;
19
+ }
20
+ function getTableNamesFromWhere(ast) {
21
+ const extractTableNames = (where) => {
22
+ if (where === null || !(where.type === "binary_expr" && "left" in where)) {
23
+ return [];
24
+ }
25
+ const extractTableName = (expr) => {
26
+ if (expr.type === "column_ref") {
27
+ const table = getTableName(expr);
28
+ return table ? [table] : [];
29
+ } else if (expr.type === "binary_expr" && "left" in expr) {
30
+ return extractTableNames(expr);
31
+ }
32
+ return [];
33
+ };
34
+ return [...extractTableName(where.left), ...extractTableName(where.right)];
35
+ };
36
+ return _.uniq(
37
+ (Array.isArray(ast) ? ast : [ast]).flatMap(
38
+ (a) => a.type === "select" || a.type === "update" || a.type === "delete" ? extractTableNames(a.where) : []
39
+ )
40
+ );
41
+ }
42
+
43
+ // src/database/base-model.ts
44
+ var BaseModelClassAbstract = class {
45
+ modelName = "Unknown";
46
+ async runSubsetQuery({
47
+ params,
48
+ baseTable,
49
+ subset,
50
+ subsetQuery,
51
+ build,
52
+ debug,
53
+ db: _db,
54
+ optimizeCountQuery
55
+ }) {
56
+ const db = _db ?? DB.getDB(subset.startsWith("A") ? "w" : "r");
57
+ const dbClient = DB.toClient(db);
58
+ baseTable = baseTable ?? inflection.pluralize(inflection.underscore(this.modelName));
59
+ const queryMode = params.queryMode ?? (params.id !== void 0 ? "list" : "both");
60
+ const { select, virtual, joins, loaders } = subsetQuery;
61
+ const _qb = build({
62
+ qb: dbClient.from(baseTable).qb,
63
+ db,
64
+ select,
65
+ joins,
66
+ virtual
67
+ });
68
+ dbClient.qb = _qb;
69
+ const qb = dbClient;
70
+ const total = await (async () => {
71
+ if (queryMode === "list") return void 0;
72
+ const clonedQb = qb.clone().clearQueryParts(["order", "offset", "limit"]).clearSelect().select(`${baseTable}.id`);
73
+ const parser = new SqlParser.Parser();
74
+ if (optimizeCountQuery) {
75
+ const parsedQuery2 = parser.astify(clonedQb.sql);
76
+ const tables = getTableNamesFromWhere(parsedQuery2);
77
+ const needToJoin = _2.uniq(
78
+ tables.flatMap(
79
+ (table) => table.split("__").map((t) => inflection.pluralize(t))
80
+ )
81
+ );
82
+ this.applyJoins(
83
+ clonedQb,
84
+ joins.filter((j) => needToJoin.includes(j.table))
85
+ );
86
+ } else {
87
+ this.applyJoins(clonedQb, joins);
88
+ }
89
+ const parsedQuery = parser.astify(clonedQb.sql);
90
+ const q = Array.isArray(parsedQuery) ? parsedQuery[0] : parsedQuery;
91
+ if (q.type !== "select") {
92
+ throw new Error("Invalid query");
93
+ }
94
+ const countColumn = `${getTableName(q.columns[0].expr)}.${q.columns[0].expr.column}`;
95
+ clonedQb.clearSelect().count(countColumn, "total").first();
96
+ if (q.distinct) {
97
+ clonedQb.distinct(countColumn);
98
+ }
99
+ if (debug === true || debug === "count") {
100
+ console.debug("DEBUG: count query", chalk.blue(clonedQb.sql));
101
+ }
102
+ const [{ total: total2 }] = await clonedQb.execute();
103
+ return total2;
104
+ })();
105
+ const rows = await (async () => {
106
+ if (queryMode === "count") return [];
107
+ let listQb = qb;
108
+ if (params.num !== 0) {
109
+ listQb = listQb.limit(params.num).offset(params.num * (params.page - 1));
110
+ }
111
+ listQb.select(select);
112
+ listQb = this.applyJoins(listQb, joins);
113
+ if (debug === true || debug === "list") {
114
+ console.debug("DEBUG: list query", chalk.blue(listQb.sql));
115
+ }
116
+ let rows2 = await listQb.execute();
117
+ rows2 = await this.useLoaders(dbClient, rows2, loaders);
118
+ return this.hydrate(rows2);
119
+ })();
120
+ return {
121
+ rows,
122
+ total,
123
+ subsetQuery,
124
+ qb: dbClient.qb
125
+ };
126
+ }
127
+ async useLoaders(db, rows, loaders) {
128
+ if (loaders.length === 0) return rows;
129
+ for (const loader of loaders) {
130
+ const fromIds = rows.map((row) => row[loader.manyJoin.idField]);
131
+ if (!fromIds.length) continue;
132
+ let subRows;
133
+ let toCol;
134
+ if (loader.manyJoin.through === void 0) {
135
+ const { subQ, col } = await this.buildHasManyQuery(db, loader, fromIds);
136
+ subRows = await subQ.execute();
137
+ toCol = col;
138
+ } else {
139
+ const { subQ, col } = await this.buildManyToManyQuery(
140
+ db,
141
+ loader,
142
+ fromIds
143
+ );
144
+ subRows = await subQ.execute();
145
+ toCol = col;
146
+ }
147
+ if (loader.loaders) {
148
+ subRows = await this.useLoaders(db, subRows, loader.loaders);
149
+ }
150
+ const subRowGroups = _2.groupBy(subRows, toCol);
151
+ rows = rows.map((row) => {
152
+ row[loader.as] = (subRowGroups[row[loader.manyJoin.idField]] ?? []).map(
153
+ (r) => _2.omit(r, toCol)
154
+ );
155
+ return row;
156
+ });
157
+ }
158
+ return rows;
159
+ }
160
+ async buildHasManyQuery(db, loader, fromIds) {
161
+ const idColumn = `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`;
162
+ let qb = db.from(loader.manyJoin.toTable);
163
+ db.where([idColumn, "in", fromIds]).select([...loader.select, idColumn]);
164
+ qb = this.applyJoins(qb, loader.oneJoins);
165
+ return {
166
+ subQ: qb,
167
+ col: loader.manyJoin.toCol
168
+ };
169
+ }
170
+ async buildManyToManyQuery(db, loader, fromIds) {
171
+ if (!loader.manyJoin.through)
172
+ throw new Error("Through table info missing for many-to-many relation");
173
+ const idColumn = `${loader.manyJoin.through.table}.${loader.manyJoin.through.fromCol}`;
174
+ let qb = db.from(loader.manyJoin.through.table);
175
+ const throughTable = loader.manyJoin.through.table;
176
+ const targetTable = loader.manyJoin.toTable;
177
+ qb = this.applyJoins(qb, [
178
+ {
179
+ join: "inner",
180
+ table: targetTable,
181
+ as: targetTable,
182
+ from: `${throughTable}.${loader.manyJoin.through.toCol}`,
183
+ to: `${targetTable}.${loader.manyJoin.toCol}`
184
+ }
185
+ ]);
186
+ qb.where([idColumn, "in", fromIds]).select([...loader.select, idColumn]);
187
+ qb = this.applyJoins(qb, loader.oneJoins);
188
+ return {
189
+ subQ: qb,
190
+ col: loader.manyJoin.through.fromCol
191
+ };
192
+ }
193
+ myNow(timestamp) {
194
+ const dt = timestamp === void 0 ? DateTime.local() : DateTime.fromSeconds(timestamp);
195
+ return dt.toFormat("yyyy-MM-dd HH:mm:ss");
196
+ }
197
+ hydrate(rows) {
198
+ return rows.map((row) => {
199
+ const nestedKeys = Object.keys(row).filter((key) => key.includes("__"));
200
+ const groups = _2.groupBy(nestedKeys, (key) => key.split("__")[0]);
201
+ const nullKeys = Object.keys(groups).filter(
202
+ (key) => groups[key].length > 1 && groups[key].every((field) => row[field] === null)
203
+ );
204
+ const hydrated = Object.keys(row).reduce((r, field) => {
205
+ if (!field.includes("__")) {
206
+ if (Array.isArray(row[field]) && _2.isObject(row[field][0])) {
207
+ r[field] = this.hydrate(row[field]);
208
+ } else {
209
+ r[field] = row[field];
210
+ }
211
+ return r;
212
+ }
213
+ const parts = field.split("__");
214
+ const objPath = parts[0] + parts.slice(1).map((part) => `[${part}]`).join("");
215
+ _2.set(
216
+ r,
217
+ objPath,
218
+ row[field] && Array.isArray(row[field]) && _2.isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]
219
+ );
220
+ return r;
221
+ }, {});
222
+ nullKeys.forEach((nullKey) => hydrated[nullKey] = null);
223
+ return hydrated;
224
+ });
225
+ }
226
+ };
227
+
228
+ export {
229
+ BaseModelClassAbstract
230
+ };
231
+ //# sourceMappingURL=chunk-4K2F3SOM.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/database/base-model.ts","../src/utils/sql-parser.ts"],"sourcesContent":["// base-model.ts\nimport { DateTime } from \"luxon\";\nimport _ from \"lodash\";\nimport SqlParser from \"node-sql-parser\";\nimport chalk from \"chalk\";\nimport inflection from \"inflection\";\nimport { BaseListParams } from \"../utils/model\";\nimport { DBPreset, DriverSpec, DatabaseDriver } from \"./types\";\nimport { SubsetQuery } from \"../types/types\";\nimport { getTableName, getTableNamesFromWhere } from \"../utils/sql-parser\";\nimport { DB } from \"./db\";\n\nexport abstract class BaseModelClassAbstract<D extends DatabaseDriver> {\n public modelName: string = \"Unknown\";\n\n protected abstract applyJoins(\n qb: DriverSpec[D][\"adapter\"],\n joins: SubsetQuery[\"joins\"]\n ): DriverSpec[D][\"adapter\"];\n protected abstract executeCountQuery(\n qb: DriverSpec[D][\"queryBuilder\"]\n ): Promise<number>;\n\n abstract getDB(which: DBPreset): DriverSpec[D][\"core\"];\n abstract destroy(): Promise<void>;\n\n async runSubsetQuery<T extends BaseListParams, U extends string>({\n params,\n baseTable,\n subset,\n subsetQuery,\n build,\n debug,\n db: _db,\n optimizeCountQuery,\n }: {\n subset: U;\n params: T;\n subsetQuery: SubsetQuery;\n build: (buildParams: {\n qb: DriverSpec[D][\"queryBuilder\"];\n db: DriverSpec[D][\"core\"];\n select: SubsetQuery[\"select\"];\n joins: SubsetQuery[\"joins\"];\n virtual: string[];\n }) => DriverSpec[D][\"queryBuilder\"];\n baseTable?: DriverSpec[D][\"table\"];\n debug?: boolean | \"list\" | \"count\";\n db?: DriverSpec[D][\"core\"];\n optimizeCountQuery?: boolean;\n }): Promise<{\n rows: any[];\n total?: number;\n subsetQuery: SubsetQuery;\n qb: DriverSpec[D][\"queryBuilder\"];\n }> {\n const db = _db ?? DB.getDB(subset.startsWith(\"A\") ? \"w\" : \"r\");\n const dbClient = DB.toClient(db);\n baseTable =\n baseTable ?? inflection.pluralize(inflection.underscore(this.modelName));\n const queryMode =\n params.queryMode ?? (params.id !== undefined ? \"list\" : \"both\");\n\n const { select, virtual, joins, loaders } = subsetQuery;\n const _qb = build({\n qb: dbClient.from(baseTable).qb,\n db,\n select,\n joins,\n virtual,\n });\n dbClient.qb = _qb;\n const qb = dbClient;\n\n const total = await (async () => {\n if (queryMode === \"list\") return undefined;\n\n const clonedQb = qb\n .clone()\n .clearQueryParts([\"order\", \"offset\", \"limit\"])\n .clearSelect()\n .select(`${baseTable}.id`);\n const parser = new SqlParser.Parser();\n\n if (optimizeCountQuery) {\n const parsedQuery = parser.astify(clonedQb.sql);\n const tables = getTableNamesFromWhere(parsedQuery);\n const needToJoin = _.uniq(\n tables.flatMap((table) =>\n table.split(\"__\").map((t) => inflection.pluralize(t))\n )\n );\n\n this.applyJoins(\n clonedQb,\n joins.filter((j) => needToJoin.includes(j.table))\n );\n } else {\n this.applyJoins(clonedQb, joins);\n }\n\n const parsedQuery = parser.astify(clonedQb.sql);\n const q = Array.isArray(parsedQuery) ? parsedQuery[0] : parsedQuery;\n\n if (q.type !== \"select\") {\n throw new Error(\"Invalid query\");\n }\n\n const countColumn = `${getTableName(q.columns[0].expr)}.${q.columns[0].expr.column}`;\n clonedQb.clearSelect().count(countColumn, \"total\").first();\n if (q.distinct) {\n clonedQb.distinct(countColumn);\n }\n\n if (debug === true || debug === \"count\") {\n console.debug(\"DEBUG: count query\", chalk.blue(clonedQb.sql));\n }\n\n const [{ total }] = await clonedQb.execute();\n return total;\n })();\n\n const rows = await (async () => {\n if (queryMode === \"count\") return [];\n\n let listQb = qb;\n if (params.num !== 0) {\n listQb = listQb\n .limit(params.num!)\n .offset(params.num! * (params.page! - 1));\n }\n\n listQb.select(select);\n listQb = this.applyJoins(listQb, joins);\n\n if (debug === true || debug === \"list\") {\n console.debug(\"DEBUG: list query\", chalk.blue(listQb.sql));\n }\n\n let rows = await listQb.execute();\n rows = await this.useLoaders(dbClient, rows, loaders);\n return this.hydrate(rows);\n })();\n\n return {\n rows,\n total,\n subsetQuery,\n qb: dbClient.qb,\n };\n }\n\n async useLoaders(\n db: DriverSpec[D][\"adapter\"],\n rows: any[],\n loaders: SubsetQuery[\"loaders\"]\n ): Promise<any[]> {\n if (loaders.length === 0) return rows;\n\n for (const loader of loaders) {\n const fromIds = rows.map((row) => row[loader.manyJoin.idField]);\n\n if (!fromIds.length) continue;\n\n let subRows: any[];\n let toCol: string;\n\n if (loader.manyJoin.through === undefined) {\n // HasMany\n const { subQ, col } = await this.buildHasManyQuery(db, loader, fromIds);\n subRows = await subQ.execute();\n toCol = col;\n } else {\n // ManyToMany\n const { subQ, col } = await this.buildManyToManyQuery(\n db,\n loader,\n fromIds\n );\n subRows = await subQ.execute();\n toCol = col;\n }\n\n if (loader.loaders) {\n subRows = await this.useLoaders(db, subRows, loader.loaders);\n }\n\n // Group and assign loaded rows\n const subRowGroups = _.groupBy(subRows, toCol);\n rows = rows.map((row) => {\n row[loader.as] = (subRowGroups[row[loader.manyJoin.idField]] ?? []).map(\n (r) => _.omit(r, toCol)\n );\n return row;\n });\n }\n\n return rows;\n }\n\n protected async buildHasManyQuery(\n db: DriverSpec[D][\"adapter\"],\n loader: SubsetQuery[\"loaders\"][number],\n fromIds: any[]\n ) {\n const idColumn = `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`;\n let qb = db.from(loader.manyJoin.toTable);\n\n db.where([idColumn, \"in\", fromIds]).select([...loader.select, idColumn]);\n qb = this.applyJoins(qb, loader.oneJoins);\n\n return {\n subQ: qb,\n col: loader.manyJoin.toCol,\n };\n }\n\n protected async buildManyToManyQuery(\n db: DriverSpec[D][\"adapter\"],\n loader: SubsetQuery[\"loaders\"][number],\n fromIds: any[]\n ) {\n if (!loader.manyJoin.through)\n throw new Error(\"Through table info missing for many-to-many relation\");\n\n const idColumn = `${loader.manyJoin.through.table}.${loader.manyJoin.through.fromCol}`;\n let qb = db.from(loader.manyJoin.through.table);\n\n const throughTable = loader.manyJoin.through.table;\n const targetTable = loader.manyJoin.toTable;\n\n qb = this.applyJoins(qb, [\n {\n join: \"inner\",\n table: targetTable,\n as: targetTable,\n from: `${throughTable}.${loader.manyJoin.through.toCol}`,\n to: `${targetTable}.${loader.manyJoin.toCol}`,\n },\n ]);\n\n qb.where([idColumn, \"in\", fromIds]).select([...loader.select, idColumn]);\n qb = this.applyJoins(qb, loader.oneJoins);\n\n return {\n subQ: qb,\n col: loader.manyJoin.through.fromCol,\n };\n }\n\n myNow(timestamp?: number): string {\n const dt: DateTime =\n timestamp === undefined\n ? DateTime.local()\n : DateTime.fromSeconds(timestamp);\n return dt.toFormat(\"yyyy-MM-dd HH:mm:ss\");\n }\n\n hydrate<T>(rows: T[]): T[] {\n return rows.map((row: any) => {\n const nestedKeys = Object.keys(row).filter((key) => key.includes(\"__\"));\n const groups = _.groupBy(nestedKeys, (key) => key.split(\"__\")[0]);\n const nullKeys = Object.keys(groups).filter(\n (key) =>\n groups[key].length > 1 &&\n groups[key].every((field) => row[field] === null)\n );\n\n const hydrated = Object.keys(row).reduce((r, field) => {\n if (!field.includes(\"__\")) {\n if (Array.isArray(row[field]) && _.isObject(row[field][0])) {\n r[field] = this.hydrate(row[field]);\n } else {\n r[field] = row[field];\n }\n return r;\n }\n\n const parts = field.split(\"__\");\n const objPath =\n parts[0] +\n parts\n .slice(1)\n .map((part) => `[${part}]`)\n .join(\"\");\n\n _.set(\n r,\n objPath,\n row[field] && Array.isArray(row[field]) && _.isObject(row[field][0])\n ? this.hydrate(row[field])\n : row[field]\n );\n\n return r;\n }, {} as any);\n\n nullKeys.forEach((nullKey) => (hydrated[nullKey] = null));\n return hydrated;\n });\n }\n}\n","import _ from \"lodash\";\nimport { AST, ColumnRef, Expr, ExpressionValue, Select } from \"node-sql-parser\";\n\nexport function getTableName(expr: ColumnRef) {\n if (\"table\" in expr && expr.table !== null) {\n return typeof expr.table === \"string\"\n ? expr.table\n : (expr.table as { type: string; value: string }).value;\n }\n return null;\n}\n\n// where 조건에 사용된 테이블명을 추출\nexport function getTableNamesFromWhere(ast: AST | AST[]): string[] {\n const extractTableNames = (where: Select[\"where\"]): string[] => {\n if (where === null || !(where.type === \"binary_expr\" && \"left\" in where)) {\n return [];\n }\n\n const extractTableName = (expr: Expr | ExpressionValue): string[] => {\n if (expr.type === \"column_ref\") {\n const table = getTableName(expr as ColumnRef);\n return table ? [table] : [];\n } else if (expr.type === \"binary_expr\" && \"left\" in expr) {\n return extractTableNames(expr);\n }\n return [];\n };\n\n return [...extractTableName(where.left), ...extractTableName(where.right)];\n };\n\n return _.uniq(\n (Array.isArray(ast) ? ast : [ast]).flatMap((a) =>\n a.type === \"select\" || a.type === \"update\" || a.type === \"delete\"\n ? extractTableNames(a.where)\n : []\n )\n );\n}\n"],"mappings":";;;;;AACA,SAAS,gBAAgB;AACzB,OAAOA,QAAO;AACd,OAAO,eAAe;AACtB,OAAO,WAAW;AAClB,OAAO,gBAAgB;;;ACLvB,OAAO,OAAO;AAGP,SAAS,aAAa,MAAiB;AAC5C,MAAI,WAAW,QAAQ,KAAK,UAAU,MAAM;AAC1C,WAAO,OAAO,KAAK,UAAU,WACzB,KAAK,QACJ,KAAK,MAA0C;AAAA,EACtD;AACA,SAAO;AACT;AAGO,SAAS,uBAAuB,KAA4B;AACjE,QAAM,oBAAoB,CAAC,UAAqC;AAC9D,QAAI,UAAU,QAAQ,EAAE,MAAM,SAAS,iBAAiB,UAAU,QAAQ;AACxE,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,mBAAmB,CAAC,SAA2C;AACnE,UAAI,KAAK,SAAS,cAAc;AAC9B,cAAM,QAAQ,aAAa,IAAiB;AAC5C,eAAO,QAAQ,CAAC,KAAK,IAAI,CAAC;AAAA,MAC5B,WAAW,KAAK,SAAS,iBAAiB,UAAU,MAAM;AACxD,eAAO,kBAAkB,IAAI;AAAA,MAC/B;AACA,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,CAAC,GAAG,iBAAiB,MAAM,IAAI,GAAG,GAAG,iBAAiB,MAAM,KAAK,CAAC;AAAA,EAC3E;AAEA,SAAO,EAAE;AAAA,KACN,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG;AAAA,MAAQ,CAAC,MAC1C,EAAE,SAAS,YAAY,EAAE,SAAS,YAAY,EAAE,SAAS,WACrD,kBAAkB,EAAE,KAAK,IACzB,CAAC;AAAA,IACP;AAAA,EACF;AACF;;;AD3BO,IAAe,yBAAf,MAAgE;AAAA,EAC9D,YAAoB;AAAA,EAa3B,MAAM,eAA2D;AAAA,IAC/D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,IAAI;AAAA,IACJ;AAAA,EACF,GAoBG;AACD,UAAM,KAAK,OAAO,GAAG,MAAM,OAAO,WAAW,GAAG,IAAI,MAAM,GAAG;AAC7D,UAAM,WAAW,GAAG,SAAS,EAAE;AAC/B,gBACE,aAAa,WAAW,UAAU,WAAW,WAAW,KAAK,SAAS,CAAC;AACzE,UAAM,YACJ,OAAO,cAAc,OAAO,OAAO,SAAY,SAAS;AAE1D,UAAM,EAAE,QAAQ,SAAS,OAAO,QAAQ,IAAI;AAC5C,UAAM,MAAM,MAAM;AAAA,MAChB,IAAI,SAAS,KAAK,SAAS,EAAE;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,aAAS,KAAK;AACd,UAAM,KAAK;AAEX,UAAM,QAAQ,OAAO,YAAY;AAC/B,UAAI,cAAc,OAAQ,QAAO;AAEjC,YAAM,WAAW,GACd,MAAM,EACN,gBAAgB,CAAC,SAAS,UAAU,OAAO,CAAC,EAC5C,YAAY,EACZ,OAAO,GAAG,SAAS,KAAK;AAC3B,YAAM,SAAS,IAAI,UAAU,OAAO;AAEpC,UAAI,oBAAoB;AACtB,cAAMC,eAAc,OAAO,OAAO,SAAS,GAAG;AAC9C,cAAM,SAAS,uBAAuBA,YAAW;AACjD,cAAM,aAAaC,GAAE;AAAA,UACnB,OAAO;AAAA,YAAQ,CAAC,UACd,MAAM,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,WAAW,UAAU,CAAC,CAAC;AAAA,UACtD;AAAA,QACF;AAEA,aAAK;AAAA,UACH;AAAA,UACA,MAAM,OAAO,CAAC,MAAM,WAAW,SAAS,EAAE,KAAK,CAAC;AAAA,QAClD;AAAA,MACF,OAAO;AACL,aAAK,WAAW,UAAU,KAAK;AAAA,MACjC;AAEA,YAAM,cAAc,OAAO,OAAO,SAAS,GAAG;AAC9C,YAAM,IAAI,MAAM,QAAQ,WAAW,IAAI,YAAY,CAAC,IAAI;AAExD,UAAI,EAAE,SAAS,UAAU;AACvB,cAAM,IAAI,MAAM,eAAe;AAAA,MACjC;AAEA,YAAM,cAAc,GAAG,aAAa,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,KAAK,MAAM;AAClF,eAAS,YAAY,EAAE,MAAM,aAAa,OAAO,EAAE,MAAM;AACzD,UAAI,EAAE,UAAU;AACd,iBAAS,SAAS,WAAW;AAAA,MAC/B;AAEA,UAAI,UAAU,QAAQ,UAAU,SAAS;AACvC,gBAAQ,MAAM,sBAAsB,MAAM,KAAK,SAAS,GAAG,CAAC;AAAA,MAC9D;AAEA,YAAM,CAAC,EAAE,OAAAC,OAAM,CAAC,IAAI,MAAM,SAAS,QAAQ;AAC3C,aAAOA;AAAA,IACT,GAAG;AAEH,UAAM,OAAO,OAAO,YAAY;AAC9B,UAAI,cAAc,QAAS,QAAO,CAAC;AAEnC,UAAI,SAAS;AACb,UAAI,OAAO,QAAQ,GAAG;AACpB,iBAAS,OACN,MAAM,OAAO,GAAI,EACjB,OAAO,OAAO,OAAQ,OAAO,OAAQ,EAAE;AAAA,MAC5C;AAEA,aAAO,OAAO,MAAM;AACpB,eAAS,KAAK,WAAW,QAAQ,KAAK;AAEtC,UAAI,UAAU,QAAQ,UAAU,QAAQ;AACtC,gBAAQ,MAAM,qBAAqB,MAAM,KAAK,OAAO,GAAG,CAAC;AAAA,MAC3D;AAEA,UAAIC,QAAO,MAAM,OAAO,QAAQ;AAChC,MAAAA,QAAO,MAAM,KAAK,WAAW,UAAUA,OAAM,OAAO;AACpD,aAAO,KAAK,QAAQA,KAAI;AAAA,IAC1B,GAAG;AAEH,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,IAAI,SAAS;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAM,WACJ,IACA,MACA,SACgB;AAChB,QAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,eAAW,UAAU,SAAS;AAC5B,YAAM,UAAU,KAAK,IAAI,CAAC,QAAQ,IAAI,OAAO,SAAS,OAAO,CAAC;AAE9D,UAAI,CAAC,QAAQ,OAAQ;AAErB,UAAI;AACJ,UAAI;AAEJ,UAAI,OAAO,SAAS,YAAY,QAAW;AAEzC,cAAM,EAAE,MAAM,IAAI,IAAI,MAAM,KAAK,kBAAkB,IAAI,QAAQ,OAAO;AACtE,kBAAU,MAAM,KAAK,QAAQ;AAC7B,gBAAQ;AAAA,MACV,OAAO;AAEL,cAAM,EAAE,MAAM,IAAI,IAAI,MAAM,KAAK;AAAA,UAC/B;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,kBAAU,MAAM,KAAK,QAAQ;AAC7B,gBAAQ;AAAA,MACV;AAEA,UAAI,OAAO,SAAS;AAClB,kBAAU,MAAM,KAAK,WAAW,IAAI,SAAS,OAAO,OAAO;AAAA,MAC7D;AAGA,YAAM,eAAeF,GAAE,QAAQ,SAAS,KAAK;AAC7C,aAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,YAAI,OAAO,EAAE,KAAK,aAAa,IAAI,OAAO,SAAS,OAAO,CAAC,KAAK,CAAC,GAAG;AAAA,UAClE,CAAC,MAAMA,GAAE,KAAK,GAAG,KAAK;AAAA,QACxB;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAgB,kBACd,IACA,QACA,SACA;AACA,UAAM,WAAW,GAAG,OAAO,SAAS,OAAO,IAAI,OAAO,SAAS,KAAK;AACpE,QAAI,KAAK,GAAG,KAAK,OAAO,SAAS,OAAO;AAExC,OAAG,MAAM,CAAC,UAAU,MAAM,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,OAAO,QAAQ,QAAQ,CAAC;AACvE,SAAK,KAAK,WAAW,IAAI,OAAO,QAAQ;AAExC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,OAAO,SAAS;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAgB,qBACd,IACA,QACA,SACA;AACA,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI,MAAM,sDAAsD;AAExE,UAAM,WAAW,GAAG,OAAO,SAAS,QAAQ,KAAK,IAAI,OAAO,SAAS,QAAQ,OAAO;AACpF,QAAI,KAAK,GAAG,KAAK,OAAO,SAAS,QAAQ,KAAK;AAE9C,UAAM,eAAe,OAAO,SAAS,QAAQ;AAC7C,UAAM,cAAc,OAAO,SAAS;AAEpC,SAAK,KAAK,WAAW,IAAI;AAAA,MACvB;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,IAAI;AAAA,QACJ,MAAM,GAAG,YAAY,IAAI,OAAO,SAAS,QAAQ,KAAK;AAAA,QACtD,IAAI,GAAG,WAAW,IAAI,OAAO,SAAS,KAAK;AAAA,MAC7C;AAAA,IACF,CAAC;AAED,OAAG,MAAM,CAAC,UAAU,MAAM,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,OAAO,QAAQ,QAAQ,CAAC;AACvE,SAAK,KAAK,WAAW,IAAI,OAAO,QAAQ;AAExC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,OAAO,SAAS,QAAQ;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,WAA4B;AAChC,UAAM,KACJ,cAAc,SACV,SAAS,MAAM,IACf,SAAS,YAAY,SAAS;AACpC,WAAO,GAAG,SAAS,qBAAqB;AAAA,EAC1C;AAAA,EAEA,QAAW,MAAgB;AACzB,WAAO,KAAK,IAAI,CAAC,QAAa;AAC5B,YAAM,aAAa,OAAO,KAAK,GAAG,EAAE,OAAO,CAAC,QAAQ,IAAI,SAAS,IAAI,CAAC;AACtE,YAAM,SAASA,GAAE,QAAQ,YAAY,CAAC,QAAQ,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAChE,YAAM,WAAW,OAAO,KAAK,MAAM,EAAE;AAAA,QACnC,CAAC,QACC,OAAO,GAAG,EAAE,SAAS,KACrB,OAAO,GAAG,EAAE,MAAM,CAAC,UAAU,IAAI,KAAK,MAAM,IAAI;AAAA,MACpD;AAEA,YAAM,WAAW,OAAO,KAAK,GAAG,EAAE,OAAO,CAAC,GAAG,UAAU;AACrD,YAAI,CAAC,MAAM,SAAS,IAAI,GAAG;AACzB,cAAI,MAAM,QAAQ,IAAI,KAAK,CAAC,KAAKA,GAAE,SAAS,IAAI,KAAK,EAAE,CAAC,CAAC,GAAG;AAC1D,cAAE,KAAK,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC;AAAA,UACpC,OAAO;AACL,cAAE,KAAK,IAAI,IAAI,KAAK;AAAA,UACtB;AACA,iBAAO;AAAA,QACT;AAEA,cAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,cAAM,UACJ,MAAM,CAAC,IACP,MACG,MAAM,CAAC,EACP,IAAI,CAAC,SAAS,IAAI,IAAI,GAAG,EACzB,KAAK,EAAE;AAEZ,QAAAA,GAAE;AAAA,UACA;AAAA,UACA;AAAA,UACA,IAAI,KAAK,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,KAAKA,GAAE,SAAS,IAAI,KAAK,EAAE,CAAC,CAAC,IAC/D,KAAK,QAAQ,IAAI,KAAK,CAAC,IACvB,IAAI,KAAK;AAAA,QACf;AAEA,eAAO;AAAA,MACT,GAAG,CAAC,CAAQ;AAEZ,eAAS,QAAQ,CAAC,YAAa,SAAS,OAAO,IAAI,IAAK;AACxD,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;","names":["_","parsedQuery","_","total","rows"]}