sonamu 0.2.48 → 0.2.50

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/types.ts","../src/api/code-converters.ts","../src/api/decorators.ts","../src/exceptions/so-exceptions.ts","../src/utils/utils.ts","../src/entity/entity.ts","../src/entity/entity-manager.ts","../src/api/sonamu.ts","../src/api/caster.ts","../src/syncer/syncer.ts","../src/utils/lodash-able.ts","../src/templates/generated.template.ts","../src/templates/base-template.ts","../src/templates/init_types.template.ts","../src/templates/entity.template.ts","../src/templates/view_list.template.ts","../src/templates/model.template.ts","../src/templates/model_test.template.ts","../src/templates/service.template.ts","../src/templates/view_form.template.ts","../src/templates/view_id_all_select.template.ts","../src/templates/view_id_async_select.template.ts","../src/templates/view_enums_dropdown.template.ts","../src/templates/view_enums_select.template.ts","../src/templates/view_enums_buttonset.template.ts","../src/templates/view_search_input.template.ts","../src/templates/view_list_columns.template.ts","../src/templates/generated_http.template.ts","../src/templates/generated_sso.template.ts","../src/utils/controller.ts","../src/database/db.ts","../src/database/base-model.ts","../src/database/upsert-builder.ts","../src/database/_batch_update.ts","../src/utils/sql-parser.ts","../src/database/knex-plugins/knex-on-duplicate-update.ts","../src/entity/migrator.ts","../src/testing/fixture-manager.ts"],"names":["ApiParamType","z","api","_","chalk","glob","inflection","path","fs","ts","entity","prettier","key","options","target","p","knex","table","qb","joins","parsedQuery","rows","originalSQL","originalBindings","cacheKey","cacheTtl","cachedData","fields","prop","DateTime","equal","execSync","answer","files","matched","field","id","args"],"mappings":"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","sourcesContent":["import { Knex } from \"knex\";\nimport { z } from \"zod\";\n\n/* \n Enums\n*/\nexport type EnumsLabel<T extends string, L extends \"ko\" | \"en\"> = {\n [key in T]: { [lang in L]: string };\n};\nexport type EnumsLabelKo<T extends string> = EnumsLabel<T, \"ko\">;\n\n/*\n Custom Scalars\n*/\nexport const SQLDateTimeString = z\n .string()\n .regex(/([0-9]{4}-[0-9]{2}-[0-9]{2}( [0-9]{2}:[0-9]{2}:[0-9]{2})*)$/, {\n message: \"잘못된 SQLDate 타입\",\n })\n .min(10)\n .max(19)\n .describe(\"SQLDateTimeString\");\nexport type SQLDateTimeString = z.infer<typeof SQLDateTimeString>;\n\n/*\n Utility Types\n*/\nexport function zArrayable<T extends z.ZodTypeAny>(\n shape: T\n): z.ZodUnion<[T, z.ZodArray<T, \"many\">]> {\n return z.union([shape, shape.array()]);\n}\nexport type DistributiveOmit<T, K extends keyof any> = T extends any\n ? Omit<T, K>\n : never;\n\n/*\n Model-Defintion\n*/\nexport type CommonProp = {\n name: string;\n nullable?: boolean;\n toFilter?: true;\n desc?: string;\n dbDefault?: string;\n};\nexport type IntegerProp = CommonProp & {\n type: \"integer\";\n unsigned?: true;\n};\nexport type BigIntegerProp = CommonProp & {\n type: \"bigInteger\";\n unsigned?: true;\n};\nexport type TextProp = CommonProp & {\n type: \"text\";\n textType: \"text\" | \"mediumtext\" | \"longtext\";\n};\nexport type StringProp = CommonProp & {\n type: \"string\";\n length: number;\n};\nexport type EnumProp = CommonProp & {\n type: \"enum\";\n length: number;\n id: string;\n};\nexport type FloatProp = CommonProp & {\n type: \"float\";\n unsigned?: true;\n precision: number;\n scale: number;\n};\nexport type DoubleProp = CommonProp & {\n type: \"double\";\n unsigned?: true;\n precision: number;\n scale: number;\n};\nexport type DecimalProp = CommonProp & {\n type: \"decimal\";\n unsigned?: true;\n precision: number;\n scale: number;\n};\nexport type BooleanProp = CommonProp & {\n type: \"boolean\";\n};\nexport type DateProp = CommonProp & {\n type: \"date\";\n};\nexport type DateTimeProp = CommonProp & {\n type: \"dateTime\";\n};\nexport type TimeProp = CommonProp & {\n type: \"time\";\n};\nexport type TimestampProp = CommonProp & {\n type: \"timestamp\";\n};\nexport type JsonProp = CommonProp & {\n type: \"json\";\n id: string;\n};\nexport type UuidProp = CommonProp & {\n type: \"uuid\";\n};\nexport type VirtualProp = CommonProp & {\n type: \"virtual\";\n id: string;\n};\n\nexport type RelationType =\n | \"HasMany\"\n | \"BelongsToOne\"\n | \"ManyToMany\"\n | \"OneToOne\";\nexport type RelationOn =\n | \"CASCADE\"\n | \"SET NULL\"\n | \"NO ACTION\"\n | \"SET DEFAULT\"\n | \"RESTRICT\";\ntype _RelationProp = {\n type: \"relation\";\n name: string;\n with: string;\n nullable?: boolean;\n toFilter?: true;\n desc?: string;\n};\nexport type OneToOneRelationProp = _RelationProp & {\n relationType: \"OneToOne\";\n customJoinClause?: string;\n} & (\n | {\n hasJoinColumn: true;\n onUpdate: RelationOn;\n onDelete: RelationOn;\n }\n | {\n hasJoinColumn: false;\n }\n );\nexport type BelongsToOneRelationProp = _RelationProp & {\n relationType: \"BelongsToOne\";\n customJoinClause?: string;\n onUpdate: RelationOn;\n onDelete: RelationOn;\n};\nexport type HasManyRelationProp = _RelationProp & {\n relationType: \"HasMany\";\n joinColumn: string;\n fromColumn?: string;\n};\nexport type ManyToManyRelationProp = _RelationProp & {\n relationType: \"ManyToMany\";\n joinTable: `${string}__${string}`;\n onUpdate: RelationOn;\n onDelete: RelationOn;\n};\nexport type RelationProp =\n | OneToOneRelationProp\n | BelongsToOneRelationProp\n | HasManyRelationProp\n | ManyToManyRelationProp;\n\nexport type EntityProp =\n | IntegerProp\n | BigIntegerProp\n | TextProp\n | StringProp\n | FloatProp\n | DoubleProp\n | DecimalProp\n | BooleanProp\n | DateProp\n | DateTimeProp\n | TimeProp\n | TimestampProp\n | JsonProp\n | UuidProp\n | EnumProp\n | VirtualProp\n | RelationProp;\n\nexport type EntityIndex = {\n type: \"index\" | \"unique\";\n columns: string[];\n name?: string;\n};\nexport type EntityJson = {\n id: string;\n parentId?: string;\n table: string;\n title?: string;\n props: EntityProp[];\n indexes: EntityIndex[];\n subsets: {\n [subset: string]: string[];\n };\n enums: {\n [enumId: string]: {\n [key: string]: string;\n };\n };\n};\nexport type EntitySubsetRow = {\n field: string;\n has: {\n [key: string]: boolean;\n };\n children: EntitySubsetRow[];\n prefixes: string[];\n relationEntity?: string;\n isOpen?: boolean;\n};\nexport type FlattenSubsetRow = Omit<EntitySubsetRow, \"children\">;\n\n// SMD Legacy\nexport type SMDInput<T extends string> = {\n id: string;\n parentId?: string;\n table?: string;\n title?: string;\n props?: EntityProp[];\n indexes?: EntityIndex[];\n subsets?: {\n [subset: string]: T[];\n };\n};\n\n/*\n PropNode\n*/\n\nexport type EntityPropNode =\n | {\n nodeType: \"plain\";\n prop: EntityProp;\n }\n | {\n nodeType: \"object\" | \"array\";\n prop?: EntityProp;\n children: EntityPropNode[];\n };\n\n/*\n Prop Type Guards\n*/\nexport function isIntegerProp(p: any): p is IntegerProp {\n return p?.type === \"integer\";\n}\nexport function isBigIntegerProp(p: any): p is BigIntegerProp {\n return p?.type === \"bigInteger\";\n}\nexport function isTextProp(p: any): p is TextProp {\n return p?.type === \"text\";\n}\nexport function isStringProp(p: any): p is StringProp {\n return p?.type === \"string\";\n}\nexport function isEnumProp(p: any): p is EnumProp {\n return p?.type === \"enum\";\n}\nexport function isFloatProp(p: any): p is FloatProp {\n return p?.type === \"float\";\n}\nexport function isDoubleProp(p: any): p is DoubleProp {\n return p?.type === \"double\";\n}\nexport function isDecimalProp(p: any): p is DecimalProp {\n return p?.type === \"decimal\";\n}\nexport function isBooleanProp(p: any): p is BooleanProp {\n return p?.type === \"boolean\";\n}\nexport function isDateProp(p: any): p is DateProp {\n return p?.type === \"date\";\n}\nexport function isDateTimeProp(p: any): p is DateTimeProp {\n return p?.type === \"dateTime\";\n}\nexport function isTimeProp(p: any): p is TimeProp {\n return p?.type === \"time\";\n}\nexport function isTimestampProp(p: any): p is TimestampProp {\n return p?.type === \"timestamp\";\n}\nexport function isJsonProp(p: any): p is JsonProp {\n return p?.type === \"json\";\n}\nexport function isUuidProp(p: any): p is UuidProp {\n return p?.type === \"uuid\";\n}\nexport function isVirtualProp(p: any): p is VirtualProp {\n return p?.type === \"virtual\";\n}\nexport function isRelationProp(p: any): p is RelationProp {\n return p?.type === \"relation\";\n}\nexport function isOneToOneRelationProp(p: any): p is OneToOneRelationProp {\n return p?.relationType === \"OneToOne\";\n}\nexport function isBelongsToOneRelationProp(\n p: any\n): p is BelongsToOneRelationProp {\n return p?.relationType === \"BelongsToOne\";\n}\nexport function isHasManyRelationProp(p: any): p is HasManyRelationProp {\n return p?.relationType === \"HasMany\";\n}\nexport function isManyToManyRelationProp(p: any): p is ManyToManyRelationProp {\n return p?.relationType === \"ManyToMany\";\n}\n\ntype JoinClause =\n | {\n from: string;\n to: string;\n }\n | {\n custom: string;\n };\nexport function isCustomJoinClause(p: any): p is { custom: string } {\n return p?.custom;\n}\n\n/* 서브셋 */\ntype SubsetLoader = {\n as: string;\n table: string;\n manyJoin: {\n fromTable: string;\n fromCol: string;\n idField: string;\n toTable: string;\n toCol: string;\n through?: {\n table: string;\n fromCol: string;\n toCol: string;\n };\n };\n oneJoins: ({\n as: string;\n join: \"inner\" | \"outer\";\n table: string;\n } & JoinClause)[];\n select: (string | Knex.Raw)[];\n loaders?: SubsetLoader[];\n};\nexport type SubsetQuery = {\n select: (string | Knex.Raw)[];\n virtual: string[];\n joins: ({\n as: string;\n join: \"inner\" | \"outer\";\n table: string;\n } & JoinClause)[];\n loaders: SubsetLoader[];\n};\n\n/* BaseModel */\nexport const SonamuQueryMode = z.enum([\"both\", \"list\", \"count\"]);\nexport type SonamuQueryMode = z.infer<typeof SonamuQueryMode>;\n\n/* Knex Migration */\nexport type KnexError = {\n code: string;\n errno: number;\n sql: string;\n sqlMessage: string;\n sqlState: string;\n};\nexport function isKnexError(e: any): e is KnexError {\n return e.code && e.sqlMessage && e.sqlState;\n}\n\nexport type KnexColumnType =\n | \"string\"\n | \"text\"\n | \"smalltext\"\n | \"mediumtext\"\n | \"longtext\"\n | \"integer\"\n | \"bigInteger\"\n | \"decimal\"\n | \"timestamp\"\n | \"boolean\"\n | \"foreign\"\n | \"uuid\"\n | \"json\"\n | \"float\"\n | \"date\"\n | \"time\"\n | \"dateTime\";\nexport type MigrationColumn = {\n name: string;\n type: KnexColumnType;\n nullable: boolean;\n unsigned?: boolean;\n length?: number;\n defaultTo?: string;\n precision?: number;\n scale?: number;\n};\nexport type MigrationIndex = {\n columns: string[];\n type: \"unique\" | \"index\";\n};\nexport type MigrationForeign = {\n columns: string[];\n to: string;\n onUpdate: RelationOn;\n onDelete: RelationOn;\n};\nexport type MigrationJoinTable = {\n table: string;\n indexes: MigrationIndex[];\n columns: MigrationColumn[];\n foreigns: MigrationForeign[];\n};\nexport type MigrationSet = {\n table: string;\n columns: MigrationColumn[];\n indexes: MigrationIndex[];\n foreigns: MigrationForeign[];\n};\nexport type MigrationSetAndJoinTable = MigrationSet & {\n joinTables: MigrationJoinTable[];\n};\nexport type GenMigrationCode = {\n title: string;\n table: string;\n type: \"normal\" | \"foreign\";\n formatted: string | null;\n};\n\n/* Api */\nexport type ApiParam = {\n name: string;\n type: ApiParamType;\n optional: boolean;\n defaultDef?: string;\n};\nexport namespace ApiParamType {\n export type Object = {\n t: \"object\";\n props: ApiParam[];\n };\n export type Union = {\n t: \"union\";\n types: ApiParamType[];\n };\n export type Intersection = {\n t: \"intersection\";\n types: ApiParamType[];\n };\n export type StringLiteral = {\n t: \"string-literal\";\n value: string;\n };\n export type NumericLiteral = {\n t: \"numeric-literal\";\n value: number;\n };\n export type Array = {\n t: \"array\";\n elementsType: ApiParamType;\n };\n export type Ref = {\n t: \"ref\";\n id: string;\n args?: ApiParamType[];\n };\n export type IndexedAccess = {\n t: \"indexed-access\";\n object: ApiParamType;\n index: ApiParamType;\n };\n export type TupleType = {\n t: \"tuple-type\";\n elements: ApiParamType[];\n };\n export type Pick = Ref & {\n t: \"ref\";\n id: \"Pick\";\n };\n export type Omit = Ref & {\n t: \"ref\";\n id: \"Omit\";\n };\n export type Partial = Ref & {\n t: \"ref\";\n id: \"Partial\";\n };\n export type Promise = Ref & {\n t: \"ref\";\n id: \"Promise\";\n };\n export type Context = Ref & {\n t: \"ref\";\n id: \"Context\";\n };\n export type TypeParam = {\n t: \"type-param\";\n id: string;\n constraint?: ApiParamType;\n };\n\n export function isObject(v: any): v is ApiParamType.Object {\n return v?.t === \"object\";\n }\n export function isUnion(v: any): v is ApiParamType.Union {\n return v?.t === \"union\";\n }\n export function isIntersection(v: any): v is ApiParamType.Intersection {\n return v?.t === \"intersection\";\n }\n export function isStringLiteral(v: any): v is ApiParamType.StringLiteral {\n return v?.t === \"string-literal\";\n }\n export function isNumericLiteral(v: any): v is ApiParamType.NumericLiteral {\n return v?.t === \"numeric-literal\";\n }\n export function isArray(v: any): v is ApiParamType.Array {\n return v?.t === \"array\";\n }\n export function isRef(v: any): v is ApiParamType.Ref {\n return v?.t === \"ref\";\n }\n export function isIndexedAccess(v: any): v is ApiParamType.IndexedAccess {\n return v?.t === \"indexed-access\";\n }\n export function isTupleType(v: any): v is ApiParamType.TupleType {\n return v?.t === \"tuple-type\";\n }\n export function isPick(v: any): v is ApiParamType.Pick {\n return v?.t === \"ref\" && v.id === \"Pick\";\n }\n export function isOmit(v: any): v is ApiParamType.Omit {\n return v?.t === \"ref\" && v.id === \"Omit\";\n }\n export function isPartial(v: any): v is ApiParamType.Partial {\n return v?.t === \"ref\" && v.id === \"Partial\";\n }\n export function isPromise(v: any): v is ApiParamType.Promise {\n return v?.t === \"ref\" && v.id === \"Promise\";\n }\n export function isContext(v: any): v is ApiParamType.Context {\n return v?.t === \"ref\" && v.id === \"Context\";\n }\n export function isRefKnex(v: any): v is ApiParamType.Ref {\n return v?.t === \"ref\" && v.id === \"Knex\";\n }\n export function isTypeParam(v: any): v is ApiParamType.TypeParam {\n return v?.t === \"type-param\";\n }\n}\nexport type ApiParamType =\n | \"string\"\n | \"number\"\n | \"boolean\"\n | \"null\"\n | \"undefined\"\n | \"void\"\n | \"any\"\n | \"unknown\"\n | \"true\"\n | \"false\"\n | ApiParamType.StringLiteral\n | ApiParamType.NumericLiteral\n | ApiParamType.Object\n | ApiParamType.Union\n | ApiParamType.Intersection\n | ApiParamType.Array\n | ApiParamType.Ref\n | ApiParamType.IndexedAccess\n | ApiParamType.TypeParam\n | ApiParamType.TupleType;\n\n/* Template */\n// 셀프 참조 타입이므로 Zod 생략하고 직접 정의\nexport const RenderingNode = z.any();\nexport type RenderingNode = {\n name: string;\n label: string;\n renderType:\n | \"string-plain\"\n | \"string-image\"\n | \"string-datetime\"\n | \"string-date\"\n | \"number-plain\"\n | \"number-id\"\n | \"number-fk_id\"\n | \"boolean\"\n | \"enums\"\n | \"array\"\n | \"array-images\"\n | \"object\"\n | \"object-pick\"\n | \"record\";\n zodType: z.ZodTypeAny;\n element?: RenderingNode;\n children?: RenderingNode[];\n config?: {\n picked: string;\n };\n optional?: boolean;\n nullable?: boolean;\n};\n\nexport const TemplateOptions = z.object({\n entity: z.object({\n entityId: z.string(),\n parentId: z.string().optional(),\n title: z.string(),\n table: z.string().optional(),\n props: z.array(z.object({})).optional(),\n indexes: z.array(z.object({})).optional(),\n subsets: z.object({}).optional(),\n enums: z.object({}).optional(),\n }),\n init_types: z.object({\n entityId: z.string(),\n }),\n generated: z.object({}),\n generated_sso: z.object({}),\n generated_http: z.object({\n entityId: z.string(),\n }),\n model: z.object({\n entityId: z.string(),\n defaultSearchField: z.string(),\n defaultOrderBy: z.string(),\n }),\n model_test: z.object({\n entityId: z.string(),\n }),\n bridge: z.object({\n entityId: z.string(),\n }),\n service: z.object({\n entityId: z.string(),\n }),\n view_list: z.object({\n entityId: z.string(),\n extra: z.unknown(),\n }),\n view_list_columns: z.object({\n entityId: z.string(),\n columns: z\n .object({\n name: z.string(),\n label: z.string(),\n tc: z.string(),\n })\n .array(),\n columnImports: z.string(),\n }),\n view_search_input: z.object({\n entityId: z.string(),\n }),\n view_form: z.object({\n entityId: z.string(),\n }),\n view_id_all_select: z.object({\n entityId: z.string(),\n }),\n view_id_async_select: z.object({\n entityId: z.string(),\n textField: z.string(),\n }),\n view_enums_select: z.object({\n entityId: z.string(),\n enumId: z.string(),\n }),\n view_enums_dropdown: z.object({\n entityId: z.string(),\n enumId: z.string(),\n }),\n view_enums_buttonset: z.object({\n entityId: z.string(),\n enumId: z.string(),\n }),\n});\nexport type TemplateOptions = z.infer<typeof TemplateOptions>;\n\nexport const TemplateKey = z.enum([\n \"entity\",\n \"init_types\",\n \"generated\",\n \"generated_sso\",\n \"generated_http\",\n \"model\",\n \"model_test\",\n \"bridge\",\n \"service\",\n \"view_list\",\n \"view_list_columns\",\n \"view_search_input\",\n \"view_form\",\n \"view_id_all_select\",\n \"view_id_async_select\",\n \"view_enums_select\",\n \"view_enums_dropdown\",\n \"view_enums_buttonset\",\n]);\nexport type TemplateKey = z.infer<typeof TemplateKey>;\n\nexport const GenerateOptions = z.object({\n overwrite: z.boolean().optional(),\n});\nexport type GenerateOptions = z.infer<typeof GenerateOptions>;\n\nexport const PathAndCode = z.object({\n path: z.string(),\n code: z.string(),\n});\nexport type PathAndCode = z.infer<typeof PathAndCode>;\n\nexport type FixtureSearchOptions = {\n entityId: string;\n field: string;\n value: string;\n searchType: \"equals\" | \"like\";\n};\n\nexport type FixtureRecord = {\n fixtureId: string;\n entityId: string;\n id: number;\n columns: {\n [key: string]: {\n prop: EntityProp;\n value: any;\n };\n };\n fetchedRecords: string[];\n belongsRecords: string[];\n target?: FixtureRecord; // Import 대상 DB 레코드(id가 같은)\n unique?: FixtureRecord; // Import 대상 DB 레코드(unique key가 같은)\n override?: boolean;\n};\n\nexport type FixtureImportResult = {\n entityId: string;\n data: {\n [key: string]: any;\n };\n};\n","import { z, ZodRecord } from \"zod\";\nimport {\n ApiParam,\n ApiParamType,\n isBelongsToOneRelationProp,\n isBigIntegerProp,\n isBooleanProp,\n isDateProp,\n isDateTimeProp,\n isDecimalProp,\n isDoubleProp,\n isEnumProp,\n isFloatProp,\n isIntegerProp,\n isJsonProp,\n isOneToOneRelationProp,\n isRelationProp,\n isStringProp,\n isTextProp,\n isTimeProp,\n isTimestampProp,\n isUuidProp,\n isVirtualProp,\n EntityProp,\n EntityPropNode,\n TextProp,\n} from \"../types/types\";\nimport { ExtendedApi } from \"./decorators\";\n\n/*\n ExtendedApi 에서 ZodObject 리턴\n*/\nexport function getZodObjectFromApi(\n api: ExtendedApi,\n references: {\n [id: string]: z.ZodObject<any>;\n } = {}\n) {\n if (api.typeParameters?.length > 0) {\n api.typeParameters.map((typeParam) => {\n if (typeParam.constraint) {\n let zodType = getZodTypeFromApiParamType(\n typeParam.constraint,\n references\n );\n (references[typeParam.id] as any) = zodType;\n }\n });\n }\n\n const ReqType = getZodObjectFromApiParams(\n api.parameters.filter(\n (param) =>\n !ApiParamType.isContext(param.type) &&\n !ApiParamType.isRefKnex(param.type)\n ),\n references\n );\n return ReqType;\n}\n\n/*\n ZodObject를 통해 ApiParam 리턴\n*/\nexport function getZodObjectFromApiParams(\n apiParams: ApiParam[],\n references: {\n [id: string]: z.ZodObject<any>;\n } = {}\n): z.ZodObject<{}, \"strip\", z.ZodTypeAny, {}, {}> {\n return z.object(\n apiParams.reduce((r, param) => {\n let zodType = getZodTypeFromApiParamType(param.type, references);\n if (param.optional) {\n zodType = zodType.optional();\n }\n return {\n ...r,\n [param.name]: zodType,\n };\n }, {})\n );\n}\n\n/*\n ApiParamType으로 ZodType 컨버팅\n*/\nexport function getZodTypeFromApiParamType(\n paramType: ApiParamType,\n references: {\n [id: string]: z.ZodObject<any>;\n }\n): z.ZodType<unknown> {\n switch (paramType) {\n case \"string\":\n return z.string();\n case \"number\":\n return z.number();\n case \"boolean\":\n return z.boolean();\n default:\n const advType = paramType as { t: string };\n switch (advType.t) {\n case \"string-literal\":\n case \"numeric-literal\":\n return z.literal((advType as any).value);\n case \"object\":\n const objType = paramType as { t: string; props: ApiParam[] };\n return getZodObjectFromApiParams(objType.props);\n case \"array\":\n const arrType = paramType as {\n t: string;\n elementsType: ApiParamType;\n };\n return z.array(\n getZodTypeFromApiParamType(arrType.elementsType, references)\n );\n case \"ref\":\n const refType = paramType as {\n t: string;\n id: string;\n args?: ApiParamType[];\n };\n\n // 객체 키 관리 유틸리티\n if ([\"Pick\", \"Omit\"].includes(refType.id)) {\n if (refType.args?.length !== 2) {\n throw new Error(`잘못된 ${refType.id}`);\n }\n const [obj, literalOrUnion] = refType.args!.map((arg) =>\n getZodTypeFromApiParamType(arg, references)\n ) as [z.ZodObject<any>, z.ZodUnion<any> | z.ZodLiteral<string>];\n let keys: string[] = [];\n if (literalOrUnion instanceof z.ZodUnion) {\n keys = literalOrUnion._def.options.map(\n (option: { _def: { value: string } }) => option._def.value\n );\n } else {\n keys = [(literalOrUnion as z.ZodLiteral<string>)._def.value];\n }\n const keyRecord = keys.reduce((result, key) => {\n return {\n ...result,\n [key]: true,\n };\n }, {} as any);\n\n if (refType.id === \"Pick\") {\n if (obj.pick) {\n return obj.pick(keyRecord);\n }\n } else {\n if (obj.omit) {\n return obj.omit(keyRecord);\n }\n }\n }\n if ([\"Partial\"].includes(refType.id)) {\n if (refType.args?.length !== 1) {\n throw new Error(`잘못된 ${refType.id}`);\n }\n const obj = getZodTypeFromApiParamType(refType.args[0], references);\n return (obj as any).partial();\n }\n\n const reference = references[refType.id];\n if (reference === undefined) {\n return z.string();\n // throw new Error(`ref 참조 불가 ${refType.id}`);\n }\n return reference;\n case \"union\":\n const unionType = paramType as {\n t: string;\n types: ApiParamType[];\n };\n return z.union(\n unionType.types.map((type) =>\n getZodTypeFromApiParamType(type, references)\n ) as any\n );\n case \"intersection\":\n const intersectionType = paramType as {\n t: string;\n types: ApiParamType[];\n };\n return intersectionType.types.reduce((result, type, index) => {\n const resolvedType = getZodTypeFromApiParamType(type, references);\n if (index === 0) {\n return resolvedType;\n } else {\n return z.intersection(result as any, resolvedType);\n }\n }, z.unknown() as any) as any;\n case \"tuple-type\":\n const tupleType = paramType as ApiParamType.TupleType;\n return z.tuple(\n tupleType.elements.map((elem) =>\n getZodTypeFromApiParamType(elem, references)\n ) as any\n );\n }\n return z.unknown();\n }\n}\n\nexport function propNodeToZodTypeDef(\n propNode: EntityPropNode,\n injectImportKeys: string[]\n): string {\n if (propNode.nodeType === \"plain\") {\n return propToZodTypeDef(propNode.prop, injectImportKeys);\n } else if (propNode.nodeType === \"array\") {\n return [\n propNode.prop ? `${propNode.prop.name}: ` : \"\",\n \"z.array(z.object({\",\n propNode.children\n .map((childPropNode) =>\n propNodeToZodTypeDef(childPropNode, injectImportKeys)\n )\n .join(\"\\n\"),\n \"\",\n \"})),\",\n ].join(\"\\n\");\n } else if (propNode.nodeType === \"object\") {\n return [\n propNode.prop ? `${propNode.prop.name}: ` : \"\",\n \"z.object({\",\n propNode.children\n .map((childPropNode) =>\n propNodeToZodTypeDef(childPropNode, injectImportKeys)\n )\n .join(\"\\n\"),\n \"\",\n `})${propNode.prop && propNode.prop.nullable ? \".nullable()\" : \"\"},`,\n ].join(\"\\n\");\n } else {\n throw Error;\n }\n}\n\nexport function getTextTypeLength(textType: TextProp[\"textType\"]): number {\n switch (textType) {\n case \"text\":\n return 1024 * 64 - 1;\n case \"mediumtext\":\n return 1024 * 1024 * 16 - 1;\n case \"longtext\":\n return 1024 * 1024 * 1024 * 4 - 1;\n }\n}\n\nexport function propToZodTypeDef(\n prop: EntityProp,\n injectImportKeys: string[]\n): string {\n let stmt: string;\n if (isIntegerProp(prop)) {\n stmt = `${prop.name}: z.number().int()`;\n } else if (isBigIntegerProp(prop)) {\n stmt = `${prop.name}: z.bigint()`;\n } else if (isTextProp(prop)) {\n stmt = `${prop.name}: z.string().max(${getTextTypeLength(prop.textType)})`;\n } else if (isEnumProp(prop)) {\n stmt = `${prop.name}: ${prop.id}`;\n injectImportKeys.push(prop.id);\n } else if (isStringProp(prop)) {\n stmt = `${prop.name}: z.string().max(${prop.length})`;\n } else if (isDecimalProp(prop)) {\n stmt = `${prop.name}: z.string()`;\n } else if (isFloatProp(prop) || isDoubleProp(prop)) {\n stmt = `${prop.name}: z.number()`;\n } else if (isBooleanProp(prop)) {\n stmt = `${prop.name}: z.boolean()`;\n } else if (isDateProp(prop)) {\n stmt = `${prop.name}: z.string().length(10)`;\n } else if (isTimeProp(prop)) {\n stmt = `${prop.name}: z.string().length(8)`;\n } else if (isDateTimeProp(prop)) {\n stmt = `${prop.name}: SQLDateTimeString`;\n } else if (isTimestampProp(prop)) {\n stmt = `${prop.name}: SQLDateTimeString`;\n } else if (isJsonProp(prop)) {\n stmt = `${prop.name}: ${prop.id}`;\n injectImportKeys.push(prop.id);\n } else if (isUuidProp(prop)) {\n stmt = `${prop.name}: z.string().uuid()`;\n } else if (isVirtualProp(prop)) {\n stmt = `${prop.name}: ${prop.id}`;\n injectImportKeys.push(prop.id);\n } else if (isRelationProp(prop)) {\n if (\n isBelongsToOneRelationProp(prop) ||\n (isOneToOneRelationProp(prop) && prop.hasJoinColumn)\n ) {\n stmt = `${prop.name}_id: z.number().int()`;\n } else {\n // 그외 relation 케이스 제외\n return `// ${prop.name}: ${prop.relationType} ${prop.with}`;\n }\n } else {\n return \"// unable to resolve\";\n }\n\n if ((prop as { unsigned?: boolean }).unsigned) {\n stmt += \".nonnegative()\";\n }\n if (prop.nullable) {\n stmt += \".nullable()\";\n }\n\n return stmt + \",\";\n}\n\nexport function zodTypeToZodCode(\n zt: z.ZodFirstPartySchemaTypes | z.ZodObject<any>\n): string {\n switch (zt._def.typeName) {\n case \"ZodString\":\n return \"z.string()\";\n case \"ZodNumber\":\n return \"z.number()\";\n case \"ZodBoolean\":\n return \"z.boolean()\";\n case \"ZodBigInt\":\n return \"z.bigint()\";\n case \"ZodDate\":\n return \"z.date()\";\n case \"ZodNull\":\n return \"z.null()\";\n case \"ZodUndefined\":\n return \"z.undefined()\";\n case \"ZodAny\":\n return \"z.any()\";\n case \"ZodUnknown\":\n return \"z.unknown()\";\n case \"ZodNever\":\n return \"z.never()\";\n case \"ZodNullable\":\n return zodTypeToZodCode(zt._def.innerType) + \".nullable()\";\n case \"ZodDefault\":\n return (\n zodTypeToZodCode(zt._def.innerType) +\n `.default(${zt._def.defaultValue()})`\n );\n case \"ZodRecord\":\n return `z.record(${zodTypeToZodCode(zt._def.keyType)}, ${zodTypeToZodCode(\n zt._def.valueType\n )})`;\n case \"ZodLiteral\":\n if (typeof zt._def.value === \"string\") {\n return `z.literal(\"${zt._def.value}\")`;\n } else {\n return `z.literal(${zt._def.value})`;\n }\n case \"ZodUnion\":\n return `z.union([${zt._def.options\n .map((option: z.ZodTypeAny) => zodTypeToZodCode(option))\n .join(\",\")}])`;\n case \"ZodEnum\":\n return `z.enum([${zt._def.values\n .map((val: string) => `\"${val}\"`)\n .join(\", \")}])`;\n case \"ZodArray\":\n return `z.array(${zodTypeToZodCode(zt._def.type)})`;\n case \"ZodObject\":\n const shape = (zt as any).shape;\n return [\n \"z.object({\",\n ...Object.keys(shape).map(\n (key) => `${key}: ${zodTypeToZodCode(shape[key])},`\n ),\n \"})\",\n ].join(\"\\n\");\n case \"ZodOptional\":\n return zodTypeToZodCode(zt._def.innerType) + \".optional()\";\n default:\n throw new Error(`처리되지 않은 ZodType ${zt._def.typeName}`);\n }\n}\n\nexport function apiParamToTsCode(\n params: ApiParam[],\n injectImportKeys: string[]\n): string {\n return params\n .map((param) => {\n return `${param.name}${\n param.optional && !param.defaultDef ? \"?\" : \"\"\n }: ${apiParamTypeToTsType(param.type, injectImportKeys)}${\n param.defaultDef ? `= ${param.defaultDef}` : \"\"\n }`;\n })\n .join(\", \");\n}\n\nexport function apiParamTypeToTsType(\n paramType: ApiParamType,\n injectImportKeys: string[]\n): string {\n if (\n [\n \"string\",\n \"number\",\n \"boolean\",\n \"true\",\n \"false\",\n \"null\",\n \"undefined\",\n \"void\",\n \"any\",\n \"unknown\",\n ].includes(paramType as string)\n ) {\n return paramType as string;\n } else if (ApiParamType.isObject(paramType)) {\n return `{ ${apiParamToTsCode(paramType.props, injectImportKeys)} }`;\n } else if (ApiParamType.isStringLiteral(paramType)) {\n return `\"${paramType.value}\"`;\n } else if (ApiParamType.isNumericLiteral(paramType)) {\n return String(paramType.value);\n } else if (ApiParamType.isUnion(paramType)) {\n return paramType.types\n .map((type) => apiParamTypeToTsType(type, injectImportKeys))\n .join(\" | \");\n } else if (ApiParamType.isIntersection(paramType)) {\n return paramType.types\n .map((type) => apiParamTypeToTsType(type, injectImportKeys))\n .join(\" & \");\n } else if (ApiParamType.isArray(paramType)) {\n return (\n apiParamTypeToTsType(paramType.elementsType, injectImportKeys) + \"[]\"\n );\n } else if (ApiParamType.isRef(paramType)) {\n if (\n [\"Pick\", \"Omit\", \"Promise\", \"Partial\"].includes(paramType.id) === false\n ) {\n // importKeys 인젝션\n injectImportKeys.push(paramType.id);\n }\n if (paramType.args === undefined || paramType.args.length === 0) {\n return paramType.id;\n } else {\n return `${paramType.id}<${paramType.args\n .map((arg) => apiParamTypeToTsType(arg, injectImportKeys))\n .join(\",\")}>`;\n }\n } else if (ApiParamType.isIndexedAccess(paramType)) {\n return `${apiParamTypeToTsType(\n paramType.object,\n injectImportKeys\n )}[${apiParamTypeToTsType(paramType.index, injectImportKeys)}]`;\n } else if (ApiParamType.isTupleType(paramType)) {\n return `[ ${paramType.elements.map((elem) =>\n apiParamTypeToTsType(elem, injectImportKeys)\n )} ]`;\n } else if (ApiParamType.isTypeParam(paramType)) {\n return `<${paramType.id}${\n paramType.constraint\n ? ` extends ${apiParamTypeToTsType(\n paramType.constraint,\n injectImportKeys\n )}`\n : \"\"\n }>`;\n } else {\n throw new Error(`resolve 불가 ApiParamType ${paramType}`);\n }\n}\n\nexport function unwrapPromiseOnce(paramType: ApiParamType) {\n if (ApiParamType.isPromise(paramType)) {\n return paramType.args![0];\n } else {\n return paramType;\n }\n}\n\nexport function serializeZodType(zt: z.ZodTypeAny): any {\n switch (zt._def.typeName) {\n case \"ZodObject\":\n return {\n type: \"object\",\n shape: Object.keys((zt as z.ZodObject<any>).shape).reduce(\n (result, key) => {\n return {\n ...result,\n [key]: serializeZodType((zt as z.ZodObject<any>).shape[key]),\n };\n },\n {}\n ),\n };\n case \"ZodArray\":\n return {\n type: \"array\",\n element: serializeZodType(zt._def.type),\n };\n case \"ZodEnum\":\n return {\n type: \"enum\",\n values: zt._def.values,\n };\n case \"ZodString\":\n return {\n type: \"string\",\n checks: zt._def.checks,\n };\n case \"ZodNumber\":\n return {\n type: \"number\",\n checks: zt._def.checks,\n };\n case \"ZodBoolean\":\n return {\n type: \"boolean\",\n };\n case \"ZodNullable\":\n return {\n ...serializeZodType(zt._def.innerType),\n nullable: true,\n };\n case \"ZodOptional\":\n return {\n ...serializeZodType(zt._def.innerType),\n optional: true,\n };\n case \"ZodAny\":\n return {\n type: \"any\",\n };\n case \"ZodRecord\":\n return {\n type: \"record\",\n keyType: serializeZodType((zt as ZodRecord)._def.keyType),\n valueType: serializeZodType((zt as ZodRecord)._def.valueType),\n };\n case \"ZodUnion\":\n return {\n type: \"union\",\n options: (zt._def as z.ZodUnionDef).options.map((option) =>\n serializeZodType(option)\n ),\n };\n default:\n throw new Error(\n `Serialize 로직이 정의되지 않은 ZodType: ${zt._def.typeName}`\n );\n }\n}\n\nexport function zodTypeToTsTypeDef(\n zt: z.ZodFirstPartySchemaTypes | z.ZodObject<any>\n): string {\n if (zt._def.description) {\n return zt._def.description;\n }\n\n switch (zt._def.typeName) {\n case \"ZodString\":\n return \"string\";\n case \"ZodNumber\":\n return \"number\";\n case \"ZodBoolean\":\n return \"boolean\";\n case \"ZodBigInt\":\n return \"bigint\";\n case \"ZodDate\":\n return \"date\";\n case \"ZodNull\":\n return \"null\";\n case \"ZodUndefined\":\n return \"undefined\";\n case \"ZodAny\":\n return \"any\";\n case \"ZodUnknown\":\n return \"unknown\";\n case \"ZodNever\":\n return \"never\";\n case \"ZodNullable\":\n return zodTypeToTsTypeDef(zt._def.innerType) + \" | null\";\n case \"ZodDefault\":\n return zodTypeToTsTypeDef(zt._def.innerType);\n case \"ZodRecord\":\n return `{ [ key: ${zodTypeToTsTypeDef(\n zt._def.keyType\n )} ]: ${zodTypeToTsTypeDef(zt._def.valueType)}}`;\n case \"ZodLiteral\":\n if (typeof zt._def.value === \"string\") {\n return `\"${zt._def.value}\"`;\n } else {\n return `${zt._def.value}`;\n }\n case \"ZodUnion\":\n return `${zt._def.options\n .map((option: z.ZodTypeAny) => zodTypeToTsTypeDef(option))\n .join(\" | \")}`;\n case \"ZodEnum\":\n return `${zt._def.values.map((val: string) => `\"${val}\"`).join(\" | \")}`;\n case \"ZodArray\":\n return `${zodTypeToTsTypeDef(zt._def.type)}[]`;\n case \"ZodObject\":\n const shape = (zt as any).shape;\n return [\n \"{\",\n ...Object.keys(shape).map((key) => {\n if (shape[key]._def.typeName === \"ZodOptional\") {\n return `${key}?: ${zodTypeToTsTypeDef(shape[key]._def.innerType)},`;\n } else {\n return `${key}: ${zodTypeToTsTypeDef(shape[key])},`;\n }\n }),\n \"}\",\n ].join(\"\\n\");\n case \"ZodOptional\":\n return zodTypeToTsTypeDef(zt._def.innerType) + \" | undefined\";\n default:\n throw new Error(`처리되지 않은 ZodType ${zt._def.typeName}`);\n }\n}\n","import { HTTPMethods } from \"fastify\";\nimport inflection from \"inflection\";\nimport { ApiParam, ApiParamType } from \"../types/types\";\n\nexport type ServiceClient =\n | \"axios\"\n | \"axios-multipart\"\n | \"swr\"\n | \"socketio\"\n | \"window-fetch\";\nexport type ApiDecoratorOptions = {\n httpMethod?: HTTPMethods;\n contentType?:\n | \"text/plain\"\n | \"text/html\"\n | \"text/xml\"\n | \"application/json\"\n | \"application/octet-stream\";\n clients?: ServiceClient[];\n path?: string;\n resourceName?: string;\n guards?: string[];\n description?: string;\n};\nexport const registeredApis: {\n modelName: string;\n methodName: string;\n path: string;\n options: ApiDecoratorOptions;\n}[] = [];\nexport type ExtendedApi = {\n modelName: string;\n methodName: string;\n path: string;\n options: ApiDecoratorOptions;\n typeParameters: ApiParamType.TypeParam[];\n parameters: ApiParam[];\n returnType: ApiParamType;\n};\n\nexport function api(options: ApiDecoratorOptions = {}) {\n options = {\n httpMethod: \"GET\",\n contentType: \"application/json\",\n clients: [\"axios\"],\n ...options,\n };\n\n return function (target: Object, propertyKey: string) {\n const modelName = target.constructor.name.match(/(.+)Class$/)![1];\n const methodName = propertyKey;\n const defaultPath = `/${inflection.camelize(\n modelName.replace(/Model$/, \"\"),\n true\n )}/${inflection.camelize(propertyKey, true)}`;\n\n const api = {\n modelName,\n methodName,\n path: options.path ?? defaultPath,\n options,\n };\n registeredApis.push(api);\n };\n}\n","export abstract class SoException extends Error {\n constructor(\n public readonly statusCode: number,\n public message: string,\n public payload?: unknown\n ) {\n super(message);\n }\n}\n\nexport function isSoException(err: any): err is SoException {\n return err.statusCode !== undefined;\n}\n\n/*\n\t잘못된 매개변수 등 요청사항에 문제가 있는 경우\n*/\nexport class BadRequestException extends SoException {\n constructor(\n public message = \"Bad Request\",\n public payload?: unknown\n ) {\n super(400, message, payload);\n }\n}\n\n/*\n\t로그인이 반드시 필요한 케이스에 로그아웃 상태인 경우 / 접근 권한이 없는 요청시\n*/\nexport class UnauthorizedException extends SoException {\n constructor(\n public message = \"Unauthorized\",\n public payload?: unknown\n ) {\n super(401, message, payload);\n }\n}\n\n/*\n\t존재하지 않는 레코드에 접근시\n*/\nexport class NotFoundException extends SoException {\n constructor(\n public message = \"Not Found\",\n public payload?: unknown\n ) {\n super(404, message, payload);\n }\n}\n\n/*\n\t현재 상태에서 처리가 불가능한 케이스\n*/\nexport class ServiceUnavailableException extends SoException {\n constructor(\n public message = \"Service Unavailable\",\n public payload?: unknown\n ) {\n super(503, message, payload);\n }\n}\n\n/*\n\t내부 처리 로직 (외부 API 콜 포함) 오류 발생시\n*/\nexport class InternalServerErrorException extends SoException {\n constructor(\n public message = \"Internal Server Error\",\n public payload?: unknown\n ) {\n super(500, message, payload);\n }\n}\n\n/*\n\t이미 처리함\n*/\nexport class AlreadyProcessedException extends SoException {\n constructor(\n public message = \"Already Processed\",\n public payload?: unknown\n ) {\n super(541, message, payload);\n }\n}\n\n/*\n\t중복 허용하지 않는 케이스에 중복 요청\n*/\nexport class DuplicateRowException extends SoException {\n constructor(\n public message = \"Duplicate Row\",\n public payload?: unknown\n ) {\n super(542, message, payload);\n }\n}\n\n/*\n\t뭔가를 하려고 했으나 대상이 없음\n*/\nexport class TargetNotFoundException extends SoException {\n constructor(\n public message = \"Target Not Found\",\n public payload?: unknown\n ) {\n super(520, message, payload);\n }\n}\n","import path from \"path\";\nimport glob from \"glob\";\nimport fs from \"fs-extra\";\n\nexport function globAsync(pathPattern: string): Promise<string[]> {\n return new Promise((resolve, reject) => {\n glob(path.resolve(pathPattern), (err, files) => {\n if (err) {\n reject(err);\n } else {\n resolve(files);\n }\n });\n });\n}\nexport async function importMultiple(\n filePaths: string[],\n doRefresh: boolean = false\n): Promise<{ filePath: string; imported: any }[]> {\n const results: { filePath: string; imported: any }[] = [];\n\n for (const filePath of filePaths) {\n const importPath = \"./\" + path.relative(__dirname, filePath);\n if (doRefresh) {\n delete require.cache[require.resolve(importPath)];\n }\n const imported = await import(importPath);\n results.push({\n filePath,\n imported,\n });\n }\n\n return results;\n}\nexport async function findAppRootPath() {\n const apiRootPath = await findApiRootPath();\n return apiRootPath.split(path.sep).slice(0, -1).join(path.sep);\n}\n\nexport async function findApiRootPath() {\n const basePath = require.main?.path ?? __dirname;\n let dir = path.dirname(basePath);\n if (dir.includes(\"/.yarn/\")) {\n dir = dir.split(\"/.yarn/\")[0];\n }\n do {\n if (fs.existsSync(path.join(dir, \"/package.json\"))) {\n return dir.split(path.sep).join(path.sep);\n }\n dir = dir.split(path.sep).slice(0, -1).join(path.sep);\n } while (dir.split(path.sep).length > 1);\n throw new Error(\"Cannot find AppRoot using Sonamu -2\");\n}\n\nexport function nonNullable<T>(value: T): value is NonNullable<T> {\n return value !== null && value !== undefined;\n}\n","import _ from \"lodash\";\nimport { EntityManager as EntityManager } from \"./entity-manager\";\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 EntityJson,\n EntitySubsetRow,\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 prettier from \"prettier\";\nimport { nonNullable } from \"../utils/utils\";\n\nexport class Entity {\n id: string;\n parentId?: string;\n table: string;\n title: string;\n names: {\n parentFs: string;\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 [enumId: string]: z.ZodEnum<any>;\n } = {};\n enumLabels: {\n [enumId: string]: {\n [key: string]: string;\n };\n } = {};\n\n constructor({\n id,\n parentId,\n table,\n title,\n props,\n indexes,\n subsets,\n enums,\n }: EntityJson) {\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 // enums\n this.enumLabels = enums ?? {};\n this.enums = Object.fromEntries(\n Object.entries(this.enumLabels).map(([key, enumLabel]) => {\n return [\n key,\n z.enum(\n Object.keys(enumLabel) as unknown as readonly [string, ...string[]]\n ),\n ];\n })\n );\n\n // names\n this.names = {\n parentFs: inflection\n .dasherize(inflection.underscore(parentId ?? id))\n .toLowerCase(),\n fs: inflection.dasherize(inflection.underscore(id)).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 relEntity = EntityManager.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 = relEntity.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: relEntity.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 loaders: loader.loaders,\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 = relEntity.resolveSubsetQuery(\"\", relFields);\n\n let manyJoin: SubsetQuery[\"loaders\"][number][\"manyJoin\"];\n if (isHasManyRelationProp(relation)) {\n const fromCol = relation?.fromColumn ?? \"id\";\n manyJoin = {\n fromTable: this.table,\n fromCol,\n idField: prefix === \"\" ? `${fromCol}` : `${prefix}__${fromCol}`,\n toTable: relEntity.table,\n toCol: relation.joinColumn,\n };\n } else if (isManyToManyRelationProp(relation)) {\n const [table1, table2] = relation.joinTable.split(\"__\");\n const throughTables = (() => {\n // 동일 테이블 릴레이션인 경우\n if (this.table === relEntity.table) {\n if (table1 === this.table) {\n return {\n fromCol: `${inflection.singularize(table1)}_id`,\n toCol: `${inflection.singularize(table2)}_id`,\n };\n } else {\n return {\n fromCol: `${inflection.singularize(table2)}_id`,\n toCol: `${inflection.singularize(table1)}_id`,\n };\n }\n } else {\n // 서로 다른 테이블인 경우 릴레이션 테이블 유지\n return {\n fromCol: `${inflection.singularize(this.table)}_id`,\n toCol: `${inflection.singularize(relEntity.table)}_id`,\n };\n }\n })();\n\n manyJoin = {\n fromTable: this.table,\n fromCol: \"id\",\n idField: prefix === \"\" ? `id` : `${prefix}__id`,\n through: {\n table: relation.joinTable,\n ...throughTables,\n },\n toTable: relEntity.table,\n toCol: \"id\",\n };\n } else {\n throw new Error();\n }\n\n r.loaders.push({\n as: groupKey,\n table: relEntity.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[] 을 EntityPropNode[] 로 변환\n */\n fieldExprsToPropNodes(\n fieldExprs: string[],\n entity: Entity = 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 = entity.props.find((p) => p.name === propName);\n if (prop === undefined) {\n console.log({ propName, groups });\n throw new Error(`${entity.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 = entity.propsDict[key];\n if (!isRelationProp(prop)) {\n throw new Error(`잘못된 FieldExpr ${key}.${group[0]}`);\n }\n const relEntity = EntityManager.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 = relEntity.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, relEntity);\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 = EntityManager.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 getTableColumns(): string[] {\n return this.props\n .map((prop) => {\n if (prop.type === \"relation\") {\n if (\n prop.relationType === \"BelongsToOne\" ||\n (prop.relationType === \"OneToOne\" && prop.hasJoinColumn === true)\n ) {\n return `${prop.name}_id`;\n } else {\n return null;\n }\n }\n return prop.name;\n })\n .filter(nonNullable);\n }\n\n registerModulePaths() {\n const basePath = `${this.names.parentFs}`;\n\n // base-scheme\n EntityManager.setModulePath(`${this.id}BaseSchema`, `sonamu.generated`);\n\n // subset\n if (Object.keys(this.subsets).length > 0) {\n EntityManager.setModulePath(`${this.id}SubsetKey`, `sonamu.generated`);\n EntityManager.setModulePath(\n `${this.id}SubsetMapping`,\n `sonamu.generated`\n );\n Object.keys(this.subsets).map((subsetKey) => {\n EntityManager.setModulePath(\n `${this.id}Subset${subsetKey.toUpperCase()}`,\n `sonamu.generated`\n );\n });\n }\n\n // enums\n Object.keys(this.enumLabels).map((enumId) => {\n EntityManager.setModulePath(enumId, `sonamu.generated`);\n });\n\n // types\n const typesModulePath = `${basePath}/${this.names.parentFs}.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 EntityManager.setModulePath(key, typesModulePath);\n return {\n ...result,\n [key]: t[key],\n };\n }, {});\n });\n }\n }\n\n registerTableSpecs(): void {\n const uniqueIndexes = this.indexes.filter((idx) => idx.type === \"unique\");\n\n EntityManager.setTableSpec({\n name: this.table,\n uniqueIndexes,\n });\n }\n\n toJson(): EntityJson {\n return {\n id: this.id,\n parentId: this.parentId,\n table: this.table,\n title: this.title,\n props: this.props,\n indexes: this.indexes,\n subsets: this.subsets,\n enums: this.enumLabels,\n };\n }\n\n async save(): Promise<void> {\n // sort: subsets\n const subsetRows = this.getSubsetRows();\n this.subsets = Object.fromEntries(\n Object.entries(this.subsets).map(([subsetKey]) => {\n return [\n subsetKey,\n this.subsetRowsToSubsetFields(subsetRows, subsetKey),\n ];\n })\n );\n\n // save\n const jsonPath = path.join(\n Sonamu.apiRootPath,\n `src/application/${this.names.parentFs}/${this.names.fs}.entity.json`\n );\n const json = this.toJson();\n fs.writeFileSync(\n jsonPath,\n await prettier.format(JSON.stringify(json), {\n parser: \"json\",\n })\n );\n\n // reload\n await EntityManager.register(json);\n }\n\n getSubsetRows(\n _subsets?: { [key: string]: string[] },\n prefixes: string[] = []\n ): EntitySubsetRow[] {\n if (prefixes.length > 10) {\n return [];\n }\n\n const subsets = _subsets ?? this.subsets;\n const subsetKeys = Object.keys(subsets);\n const allFields = _.uniq(subsetKeys.map((key) => subsets[key]).flat());\n\n return this.props.map((prop) => {\n if (\n prop.type === \"relation\" &&\n allFields.find((f) =>\n f.startsWith([...prefixes, prop.name].join(\".\") + \".\")\n )\n ) {\n const relEntity = EntityManager.get(prop.with);\n const children = relEntity.getSubsetRows(subsets, [\n ...prefixes,\n `${prop.name}`,\n ]);\n\n return {\n field: prop.name,\n children,\n relationEntity: prop.with,\n prefixes,\n isOpen: children.length > 0,\n has: Object.fromEntries(\n subsetKeys.map((subsetKey) => {\n return [\n subsetKey,\n children.every((child) => child.has[subsetKey] === true),\n ];\n })\n ),\n };\n }\n\n return {\n field: prop.name,\n children: [],\n relationEntity: prop.type === \"relation\" ? prop.with : undefined,\n prefixes,\n has: Object.fromEntries(\n subsetKeys.map((subsetKey) => {\n const subsetFields = subsets[subsetKey];\n const has = subsetFields.some((f) => {\n const field = [...prefixes, prop.name].join(\".\");\n return f === field || f.startsWith(field + \".\");\n });\n return [subsetKey, has];\n })\n ),\n };\n });\n }\n\n subsetRowsToSubsetFields(\n subsetRows: EntitySubsetRow[],\n subsetKey: string\n ): string[] {\n return subsetRows\n .map((subsetRow) => {\n if (subsetRow.children.length > 0) {\n return this.subsetRowsToSubsetFields(subsetRow.children, subsetKey);\n } else if (subsetRow.has[subsetKey]) {\n return subsetRow.prefixes.concat(subsetRow.field).join(\".\");\n } else {\n return null;\n }\n })\n .filter(nonNullable)\n .flat();\n }\n\n async createProp(prop: EntityProp, at?: number): Promise<void> {\n if (!at) {\n this.props.push(prop);\n } else {\n this.props.splice(at, 0, prop);\n }\n await this.save();\n }\n\n analyzeSubsetField(subsetField: string): {\n entityId: string;\n propName: string;\n }[] {\n const arr = subsetField.split(\".\");\n\n let entityId = this.id;\n const result: {\n entityId: string;\n propName: string;\n }[] = [];\n for (let i = 0; i < arr.length; i++) {\n const propName = arr[i];\n result.push({\n entityId,\n propName,\n });\n\n const prop = EntityManager.get(entityId).props.find(\n (p) => p.name === propName\n );\n if (!prop) {\n throw new Error(`${entityId}의 잘못된 서브셋키 ${subsetField}`);\n }\n if (isRelationProp(prop)) {\n entityId = prop.with;\n }\n }\n return result;\n }\n\n async modifyProp(newProp: EntityProp, at: number): Promise<void> {\n // 이전 프롭 이름 저장\n const oldName = this.props[at].name;\n\n // 저장할 엔티티\n const entities: Entity[] = [this];\n\n // 이름이 바뀐 경우\n if (oldName !== newProp.name) {\n // 전체 엔티티에서 현재 수정된 프롭을 참조하고 있는 모든 서브셋필드 찾아서 수정\n const allEntityIds = EntityManager.getAllIds();\n for (const relEntityId of allEntityIds) {\n const relEntity = EntityManager.get(relEntityId);\n const relEntitySubsetKeys = Object.keys(relEntity.subsets);\n for (const subsetKey of relEntitySubsetKeys) {\n const subset = relEntity.subsets[subsetKey];\n\n // 서브셋 필드를 순회하며, 엔티티-프롭 단위로 분석한 후 현재 엔티티-프롭과 일치하는 경우 수정 처리\n const modifiedSubsetFields = subset.map((subsetField) => {\n const analyzed = relEntity.analyzeSubsetField(subsetField);\n const modified = analyzed.map((a) =>\n a.propName === oldName && a.entityId === this.id\n ? {\n ...a,\n propName: newProp.name,\n }\n : a\n );\n // 분석한 필드를 다시 서브셋 필드로 복구\n return modified.map((a) => a.propName).join(\".\");\n });\n\n if (subset.join(\",\") !== modifiedSubsetFields.join(\",\")) {\n relEntity.subsets[subsetKey] = modifiedSubsetFields;\n entities.push(relEntity);\n }\n }\n }\n }\n\n // 프롭 수정\n this.props[at] = newProp;\n\n await Promise.all(entities.map(async (entity) => entity.save()));\n }\n\n async delProp(at: number): Promise<void> {\n // 이전 프롭 이름 저장\n const oldName = this.props[at].name;\n\n // 저장할 엔티티\n const entities: Entity[] = [this];\n\n // 전체 엔티티에서 현재 삭제된 프롭을 참조하고 있는 모든 서브셋필드 찾아서 제외\n const allEntityIds = EntityManager.getAllIds();\n for (const relEntityId of allEntityIds) {\n const relEntity = EntityManager.get(relEntityId);\n const relEntitySubsetKeys = Object.keys(relEntity.subsets);\n for (const subsetKey of relEntitySubsetKeys) {\n const subset = relEntity.subsets[subsetKey];\n // 서브셋 필드를 순회하며, 엔티티-프롭 단위로 분석한 후 현재 엔티티-프롭과 일치하는 경우 이후의 필드를 제외\n const modifiedSubsetFields = subset\n .map((subsetField) => {\n const analyzed = relEntity.analyzeSubsetField(subsetField);\n if (\n analyzed.find(\n (a) => a.propName === oldName && a.entityId === this.id\n )\n ) {\n return null;\n } else {\n return subsetField;\n }\n })\n .filter(nonNullable);\n\n if (subset.join(\",\") !== modifiedSubsetFields.join(\",\")) {\n relEntity.subsets[subsetKey] = modifiedSubsetFields;\n entities.push(relEntity);\n }\n }\n }\n\n // 현재 엔티티의 인덱스에서 제외\n EntityManager.get(this.id).indexes.map((index) => {\n index.columns = index.columns.filter((col) => col !== oldName);\n });\n\n // 프롭 삭제\n this.props.splice(at, 1);\n\n await Promise.all(entities.map(async (entity) => entity.save()));\n }\n\n getEntityIdFromSubsetField(subsetField: string): string {\n if (subsetField.includes(\".\") === false) {\n return this.id;\n }\n\n // 서브셋 필드의 마지막은 프롭이므로 제외\n const arr = subsetField.split(\".\").slice(0, -1);\n\n // 서브셋 필드를 내려가면서 마지막으로 relation된 엔티티를 찾음\n const lastEntityId = arr.reduce((entityId, field) => {\n const relProp = EntityManager.get(entityId).props.find(\n (p) => p.name === field\n );\n if (!relProp || relProp.type !== \"relation\") {\n console.debug({ arr, thisId: this.id, entityId, field });\n throw new Error(`잘못된 서브셋키 ${subsetField}`);\n }\n return relProp.with;\n }, this.id);\n return lastEntityId;\n }\n\n async moveProp(at: number, to: number): Promise<void> {\n const prop = this.props[at];\n const newProps = [...this.props];\n newProps.splice(to, 0, prop);\n newProps.splice(at < to ? at : at + 1, 1);\n this.props = newProps;\n\n await this.save();\n }\n}\n","import chalk from \"chalk\";\nimport glob from \"glob\";\nimport inflection from \"inflection\";\nimport _ from \"lodash\";\nimport path from \"path\";\nimport { Entity } from \"./entity\";\nimport { EntityJson } from \"../types/types\";\nimport { Sonamu } from \"../api/sonamu\";\nimport fs from \"fs-extra\";\n\nexport type EntityNamesRecord = Record<\n | \"fs\"\n | \"fsPlural\"\n | \"camel\"\n | \"camelPlural\"\n | \"capital\"\n | \"capitalPlural\"\n | \"upper\"\n | \"constant\",\n string\n>;\ntype TableSpec = {\n name: string;\n uniqueIndexes: { name?: string; columns: string[] }[];\n};\nclass EntityManagerClass {\n private entities: Map<string, Entity> = 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 // 경로 전달받아 모든 entity.json 파일 로드\n async autoload(doSilent: boolean = false) {\n if (this.isAutoloaded) {\n return;\n }\n const pathPattern = path.join(\n Sonamu.apiRootPath,\n \"/src/application/**/*.entity.json\"\n );\n !doSilent && console.log(chalk.yellow(`autoload ${pathPattern}`));\n\n return new Promise((resolve) => {\n glob.glob(path.resolve(pathPattern!), (_err, files) => {\n Promise.all(\n files.map(async (file) => {\n this.register(JSON.parse(fs.readFileSync(file).toString()));\n })\n ).then(() => {\n resolve(\"ok\");\n this.isAutoloaded = true;\n });\n });\n });\n }\n\n async reload(doSilent: boolean = false) {\n console.log(\"reload\");\n this.entities.clear();\n this.modulePaths.clear();\n this.tableSpecs.clear();\n this.isAutoloaded = false;\n\n const sonamuPath = path.join(\n Sonamu.apiRootPath,\n \"dist/application/sonamu.generated.js\"\n );\n if (require.cache[sonamuPath]) {\n delete require.cache[sonamuPath];\n }\n\n return this.autoload(doSilent);\n }\n\n register(json: EntityJson): void {\n const entity = new Entity(json);\n this.entities.set(json.id, entity);\n }\n\n get(entityId: string): Entity {\n const entity = this.entities.get(entityId);\n if (entity === undefined) {\n throw new Error(`존재하지 않는 Entity 요청 ${entityId}`);\n }\n\n return entity;\n }\n\n exists(entityId: string): boolean {\n const entity = this.entities.get(entityId);\n return entity !== undefined;\n }\n\n getAllIds(): string[] {\n return Array.from(EntityManager.entities.keys());\n }\n\n getAllParentIds(): string[] {\n return this.getAllIds().filter((entityId) => {\n const entity = this.get(entityId);\n return entity.parentId === undefined;\n });\n }\n\n getChildrenIds(parentId: string): string[] {\n return this.getAllIds().filter((entityId) => {\n const entity = this.get(entityId);\n return entity.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(entityId: string): EntityNamesRecord {\n // entityId가 단복수 동형 단어인 경우 List 붙여서 생성\n const pluralized =\n inflection.pluralize(entityId) === entityId\n ? `${entityId}List`\n : inflection.pluralize(entityId);\n\n return {\n fs: inflection.dasherize(inflection.underscore(entityId)).toLowerCase(),\n fsPlural: inflection\n .dasherize(inflection.underscore(pluralized))\n .toLowerCase(),\n camel: inflection.camelize(entityId, true),\n camelPlural: inflection.camelize(pluralized, true),\n capital: entityId,\n capitalPlural: pluralized,\n upper: entityId.toUpperCase(),\n constant: inflection.underscore(entityId).toUpperCase(),\n };\n }\n}\n\nexport const EntityManager = new EntityManagerClass();\n","import chalk from \"chalk\";\nimport { FastifyInstance, FastifyReply, FastifyRequest } from \"fastify\";\nimport { IncomingMessage, Server, ServerResponse } from \"http\";\nimport { ZodError } from \"zod\";\nimport { getZodObjectFromApi } from \"./code-converters\";\nimport { Context } from \"./context\";\nimport { BadRequestException } from \"../exceptions/so-exceptions\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport { fastifyCaster } from \"./caster\";\nimport { ApiParam, ApiParamType } from \"../types/types\";\nimport { Syncer } from \"../syncer/syncer\";\nimport { isLocal, isTest } from \"../utils/controller\";\nimport { DB, SonamuDBConfig } from \"../database/db\";\nimport { BaseModel } from \"../database/base-model\";\nimport { findApiRootPath } from \"../utils/utils\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { ApiDecoratorOptions } from \"./decorators\";\nimport { attachOnDuplicateUpdate } from \"../database/knex-plugins/knex-on-duplicate-update\";\n\nexport type SonamuConfig = {\n api: {\n dir: string;\n };\n sync: {\n targets: string[];\n };\n route: {\n prefix: string;\n };\n};\nexport type SonamuSecrets = {\n [key: string]: string;\n};\ntype SonamuFastifyConfig = {\n contextProvider: (\n defaultContext: Pick<Context, \"headers\" | \"reply\">,\n request: FastifyRequest,\n reply: FastifyReply\n ) => Context;\n guardHandler: (\n guard: string,\n request: FastifyRequest,\n api: {\n typeParameters: ApiParamType.TypeParam[];\n parameters: ApiParam[];\n returnType: ApiParamType;\n modelName: string;\n methodName: string;\n path: string;\n options: ApiDecoratorOptions;\n }\n ) => void;\n cache?: {\n get: (key: string) => Promise<unknown | null>;\n put: (key: string, value: unknown, ttl?: number) => Promise<void>;\n resolveKey: (\n path: string,\n reqBody: {\n [key: string]: unknown;\n }\n ) =>\n | {\n cache: false;\n }\n | {\n cache: true;\n key: string;\n ttl?: number;\n };\n };\n};\nclass SonamuClass {\n public isInitialized: boolean = false;\n\n private _apiRootPath: string | null = null;\n set apiRootPath(apiRootPath: string) {\n this._apiRootPath = apiRootPath;\n }\n get apiRootPath(): string {\n if (this._apiRootPath === null) {\n throw new Error(\"Sonamu has not been initialized\");\n }\n return this._apiRootPath!;\n }\n get appRootPath(): string {\n return this.apiRootPath.split(path.sep).slice(0, -1).join(path.sep);\n }\n\n private _dbConfig: SonamuDBConfig | null = null;\n set dbConfig(dbConfig: SonamuDBConfig) {\n this._dbConfig = dbConfig;\n }\n get dbConfig(): SonamuDBConfig {\n if (this._dbConfig === null) {\n throw new Error(\"Sonamu has not been initialized\");\n }\n return this._dbConfig!;\n }\n\n private _syncer: Syncer | null = null;\n set syncer(syncer: Syncer) {\n this._syncer = syncer;\n }\n get syncer(): Syncer {\n if (this._syncer === null) {\n throw new Error(\"Sonamu has not been initialized\");\n }\n return this._syncer!;\n }\n\n private _config: SonamuConfig | null = null;\n set config(config: SonamuConfig) {\n this._config = config;\n }\n get config(): SonamuConfig {\n if (this._config === null) {\n throw new Error(\"Sonamu has not been initialized\");\n }\n return this._config;\n }\n\n private _secrets: SonamuSecrets | null = null;\n set secrets(secrets: SonamuSecrets) {\n this._secrets = secrets;\n }\n get secrets(): SonamuSecrets | null {\n return this._secrets;\n }\n\n async init(\n doSilent: boolean = false,\n enableSync: boolean = true,\n apiRootPath?: string\n ) {\n if (this.isInitialized) {\n return;\n }\n !doSilent && console.time(chalk.cyan(\"Sonamu.init\"));\n\n this.apiRootPath = apiRootPath ?? (await findApiRootPath());\n const configPath = path.join(this.apiRootPath, \"sonamu.config.json\");\n const secretsPath = path.join(this.apiRootPath, \"sonamu.secrets.json\");\n if (fs.existsSync(configPath) === false) {\n throw new Error(`Cannot find sonamu.config.json in ${configPath}`);\n }\n this.config = JSON.parse(\n fs.readFileSync(configPath).toString()\n ) as SonamuConfig;\n if (fs.existsSync(secretsPath)) {\n this.secrets = JSON.parse(\n fs.readFileSync(secretsPath).toString()\n ) as SonamuSecrets;\n }\n\n // DB 로드\n this.dbConfig = await DB.readKnexfile();\n !doSilent && console.log(chalk.green(\"DB Config Loaded!\"));\n attachOnDuplicateUpdate();\n\n // Entity 로드\n await EntityManager.autoload(doSilent);\n\n // Syncer\n this.syncer = new Syncer();\n\n // Autoload: Models / Types / APIs\n await this.syncer.autoloadModels();\n await this.syncer.autoloadTypes();\n await this.syncer.autoloadApis();\n\n if (isLocal() && !isTest() && enableSync) {\n await this.syncer.sync();\n\n fetch(\"http://127.0.0.1:57001/api/reload\", {\n method: \"GET\",\n }).catch((e) =>\n console.log(chalk.dim(`Failed to reload Sonamu UI: ${e.message}`))\n );\n }\n\n this.isInitialized = true;\n !doSilent && console.timeEnd(chalk.cyan(\"Sonamu.init\"));\n }\n\n async withFastify(\n server: FastifyInstance<Server, IncomingMessage, ServerResponse>,\n config: SonamuFastifyConfig,\n options?: { enableSync?: boolean; doSilent?: boolean }\n ) {\n if (this.isInitialized === false) {\n await this.init(options?.doSilent, options?.enableSync);\n }\n\n // 전체 라우팅 리스트\n server.get(\n `${this.config.route.prefix}/routes`,\n async (_request, _reply): Promise<any> => {\n return this.syncer.apis;\n }\n );\n\n // Healthcheck API\n server.get(\n `${this.config.route.prefix}/healthcheck`,\n async (_request, _reply): Promise<string> => {\n return \"ok\";\n }\n );\n\n // API 라우팅 등록\n this.syncer.apis.map((api) => {\n // model\n if (this.syncer.models[api.modelName] === undefined) {\n throw new Error(`정의되지 않은 모델에 접근 ${api.modelName}`);\n }\n const model = this.syncer.models[api.modelName];\n\n // 파라미터 정보로 zod 스키마 빌드\n const ReqType = getZodObjectFromApi(api, this.syncer.types);\n\n // route\n server.route({\n method: api.options.httpMethod!,\n url: this.config.route.prefix + api.path,\n handler: async (request, reply): Promise<unknown> => {\n (api.options.guards ?? []).every((guard) =>\n config.guardHandler(guard, request, api)\n );\n\n // request 파싱\n const which = api.options.httpMethod === \"GET\" ? \"query\" : \"body\";\n let reqBody: {\n [key: string]: unknown;\n };\n try {\n reqBody = fastifyCaster(ReqType).parse(request[which] ?? {});\n } catch (e) {\n if (e instanceof ZodError) {\n // TODO: BadRequest 에러 핸들링 (ZodError issues를 humanize하여 출력하는 로직 필요)\n throw new BadRequestException(\n `${(e as ZodError).issues[0].message}`,\n e.errors\n );\n } else {\n throw e;\n }\n }\n\n // Content-Type\n reply.type(api.options.contentType ?? \"application/json\");\n\n // 캐시\n const { cacheKey, cacheTtl, cachedData } = await (async () => {\n if (config.cache) {\n const cacheKeyRes = config.cache.resolveKey(api.path, reqBody);\n if (cacheKeyRes.cache === false) {\n return { cacheKey: null, cachedData: null };\n }\n\n const cacheKey = cacheKeyRes.key;\n const cacheTtl = cacheKeyRes.ttl;\n const cachedData = await config.cache.get(cacheKey);\n return { cacheKey, cacheTtl, cachedData };\n }\n return { cacheKey: null, cachedData: null };\n })();\n if (cachedData !== null) {\n return cachedData;\n }\n\n // 결과\n const result = await (model as any)[api.methodName].apply(\n model,\n api.parameters.map((param) => {\n // Context 인젝션\n if (ApiParamType.isContext(param.type)) {\n return config.contextProvider(\n {\n headers: request.headers,\n reply,\n },\n request,\n reply\n );\n } else {\n return reqBody[param.name];\n }\n })\n );\n reply.type(api.options.contentType ?? \"application/json\");\n\n // 캐시 키 있는 경우 갱신 후 저장\n if (config.cache && cacheKey) {\n await config.cache.put(cacheKey, result, cacheTtl);\n }\n return result;\n },\n }); // END server.route\n });\n }\n\n async destroy(): Promise<void> {\n await BaseModel.destroy();\n }\n}\nexport const Sonamu = new SonamuClass();\n","import { z } from \"zod\";\n\n// optional, nullable 무관하게 ZodNumber 체크\nfunction isZodNumberAnyway(zodType: z.ZodType<any>) {\n if (zodType instanceof z.ZodNumber) {\n return true;\n } else if (\n zodType instanceof z.ZodNullable &&\n zodType._def.innerType instanceof z.ZodNumber\n ) {\n return true;\n } else if (\n zodType instanceof z.ZodOptional &&\n zodType._def.innerType instanceof z.ZodNumber\n ) {\n } else if (\n zodType instanceof z.ZodOptional &&\n zodType._def.innerType instanceof z.ZodOptional &&\n zodType._type.def.innerType instanceof z.ZodNumber\n ) {\n return true;\n }\n\n return false;\n}\n\n// ZodType을 이용해 raw를 Type Coercing\nexport function caster(zodType: z.ZodType<any>, raw: any): any {\n if (isZodNumberAnyway(zodType) && typeof raw === \"string\") {\n // number\n return Number(raw);\n } else if (\n zodType instanceof z.ZodUnion &&\n zodType.options.some((opt: z.ZodType<any>) => isZodNumberAnyway(opt))\n ) {\n // zArrayable Number 케이스 처리\n if (Array.isArray(raw)) {\n const numType = zodType.options.find(\n (opt: z.ZodType<any>) => opt instanceof z.ZodNumber\n );\n return raw.map((elem: any) => caster(numType, elem));\n } else {\n return Number(raw);\n }\n } else if (\n zodType instanceof z.ZodBoolean &&\n (raw === \"true\" || raw === \"false\")\n ) {\n // boolean\n return raw === \"true\";\n } else if (\n raw !== null &&\n Array.isArray(raw) &&\n zodType instanceof z.ZodArray\n ) {\n // array\n return raw.map((elem: any) => caster(zodType.element, elem));\n } else if (\n zodType instanceof z.ZodObject &&\n typeof raw === \"object\" &&\n raw !== null\n ) {\n // object\n return Object.keys(raw).reduce((r, rawKey) => {\n r[rawKey] = caster(zodType.shape[rawKey], raw[rawKey]);\n return r;\n }, {} as any);\n } else if (zodType instanceof z.ZodOptional) {\n // optional\n return caster(zodType._def.innerType, raw);\n } else if (zodType instanceof z.ZodNullable) {\n // nullable\n return caster(zodType._def.innerType, raw);\n } else {\n // 나머지는 처리 안함\n return raw;\n }\n}\n\nexport function fastifyCaster(schema: z.ZodObject<any>) {\n return z.preprocess((raw: any) => {\n return caster(schema, raw);\n }, schema);\n}\n","import path, { dirname } from \"path\";\nimport { globAsync, importMultiple } from \"../utils/utils\";\nimport fs from \"fs-extra\";\nimport crypto from \"crypto\";\nimport equal from \"fast-deep-equal\";\nimport _ from \"lodash\";\nimport inflection from \"inflection\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport ts from \"typescript\";\nimport {\n ApiParam,\n ApiParamType,\n isBelongsToOneRelationProp,\n isBigIntegerProp,\n isBooleanProp,\n isDateProp,\n isDateTimeProp,\n isDecimalProp,\n isDoubleProp,\n isEnumProp,\n isFloatProp,\n isIntegerProp,\n isJsonProp,\n isOneToOneRelationProp,\n isRelationProp,\n isStringProp,\n isTextProp,\n isTimeProp,\n isTimestampProp,\n isUuidProp,\n isVirtualProp,\n EntityProp,\n EntityPropNode,\n SQLDateTimeString,\n} from \"../types/types\";\nimport {\n ApiDecoratorOptions,\n registeredApis,\n ExtendedApi,\n} from \"../api/decorators\";\nimport { z } from \"zod\";\nimport chalk from \"chalk\";\nimport {\n TemplateKey,\n PathAndCode,\n TemplateOptions,\n GenerateOptions,\n RenderingNode,\n} from \"../types/types\";\nimport {\n AlreadyProcessedException,\n BadRequestException,\n ServiceUnavailableException,\n} from \"../exceptions/so-exceptions\";\nimport { wrapIf } from \"../utils/lodash-able\";\nimport { getTextTypeLength } from \"../api/code-converters\";\nimport { Template } from \"../templates/base-template\";\nimport { Template__generated } from \"../templates/generated.template\";\nimport { Template__init_types } from \"../templates/init_types.template\";\nimport { Template__entity } from \"../templates/entity.template\";\nimport { Template__model } from \"../templates/model.template\";\nimport { Template__model_test } from \"../templates/model_test.template\";\nimport { Template__service } from \"../templates/service.template\";\nimport { Template__view_form } from \"../templates/view_form.template\";\nimport { Template__view_list } from \"../templates/view_list.template\";\nimport prettier from \"prettier\";\nimport { Template__view_id_all_select } from \"../templates/view_id_all_select.template\";\nimport { Template__view_id_async_select } from \"../templates/view_id_async_select.template\";\nimport { Template__view_enums_dropdown } from \"../templates/view_enums_dropdown.template\";\nimport { Template__view_enums_select } from \"../templates/view_enums_select.template\";\nimport { Template__view_enums_buttonset } from \"../templates/view_enums_buttonset.template\";\nimport { Template__view_search_input } from \"../templates/view_search_input.template\";\nimport { Template__view_list_columns } from \"../templates/view_list_columns.template\";\nimport { Template__generated_http } from \"../templates/generated_http.template\";\nimport { Sonamu } from \"../api/sonamu\";\nimport { execSync } from \"child_process\";\nimport { Template__generated_sso } from \"../templates/generated_sso.template\";\n\ntype FileType = \"model\" | \"types\" | \"functions\" | \"generated\" | \"entity\";\ntype GlobPattern = {\n [key in FileType]: string;\n};\ntype PathAndChecksum = {\n path: string;\n checksum: string;\n};\ntype DiffGroups = {\n [key in FileType]: string[];\n};\nexport type RenderedTemplate = {\n target: string;\n path: string;\n body: string;\n importKeys: string[];\n customHeaders?: string[];\n preTemplates?: {\n key: TemplateKey;\n options: TemplateOptions[TemplateKey];\n }[];\n};\n\nexport class Syncer {\n apis: {\n typeParameters: ApiParamType.TypeParam[];\n parameters: ApiParam[];\n returnType: ApiParamType;\n modelName: string;\n methodName: string;\n path: string;\n options: ApiDecoratorOptions;\n }[] = [];\n types: { [typeName: string]: z.ZodObject<any> } = {};\n models: { [modelName: string]: unknown } = {};\n\n get checksumsPath(): string {\n return path.join(Sonamu.apiRootPath, \"/.so-checksum\");\n }\n public constructor() {}\n\n async sync(): Promise<void> {\n const { targets } = Sonamu.config.sync;\n\n // 트리거와 무관하게 shared 분배\n await Promise.all(\n targets.map(async (target) => {\n const srcCodePath = path\n .join(__dirname, `../shared/${target}.shared.ts.txt`)\n .replace(\"/dist/\", \"/src/\");\n if (!fs.existsSync(srcCodePath)) {\n return;\n }\n\n const dstCodePath = path.join(\n Sonamu.appRootPath,\n target,\n \"src/services/sonamu.shared.ts\"\n );\n\n const srcChecksum = await this.getChecksumOfFile(srcCodePath);\n const dstChecksum = await (async () => {\n if (fs.existsSync(dstCodePath) === false) {\n return \"\";\n }\n return this.getChecksumOfFile(dstCodePath);\n })();\n\n if (srcChecksum === dstChecksum) {\n return;\n }\n fs.writeFileSync(dstCodePath, fs.readFileSync(srcCodePath));\n })\n );\n\n // 현재 checksums\n let currentChecksums = await this.getCurrentChecksums();\n // 이전 checksums\n const previousChecksums = await this.getPreviousChecksums();\n\n // 비교\n const isSame = equal(currentChecksums, previousChecksums);\n if (isSame) {\n const msg = \"Every files are synced!\";\n const margin = (process.stdout.columns - msg.length) / 2;\n console.log(\n chalk.black.bgGreen(\" \".repeat(margin) + msg + \" \".repeat(margin))\n );\n return;\n }\n\n // 변경된 파일 찾기\n const diff = _.differenceWith(\n currentChecksums,\n previousChecksums,\n _.isEqual\n );\n const diffFiles = diff.map((r) => r.path);\n console.log(\"Changed Files: \", diffFiles);\n\n // 다른 부분 찾아 액션\n const diffGroups = _.groupBy(diffFiles, (r) => {\n const matched = r.match(\n /\\.(model|types|functions|entity|generated)\\.[tj]s/\n );\n return matched![1];\n }) as unknown as DiffGroups;\n\n // 변경된 파일들을 타입별로 분리하여 각 타입별 액션 처리\n const diffTypes = Object.keys(diffGroups);\n\n // 트리거: entity, types\n // 액션: 스키마 생성\n if (diffTypes.includes(\"entity\") || diffTypes.includes(\"types\")) {\n console.log(\"// 액션: 스키마 생성\");\n await this.actionGenerateSchemas();\n\n // generated 싱크까지 동시에 처리 후 체크섬 갱신\n diffGroups[\"generated\"] = _.uniq([\n ...(diffGroups[\"generated\"] ?? []),\n \"/src/application/sonamu.generated.ts\",\n ]);\n diffTypes.push(\"generated\");\n currentChecksums = await this.getCurrentChecksums();\n }\n\n // 트리거: types, enums, generated 변경시\n // 액션: 파일 싱크 types, enums, generated\n if (\n diffTypes.includes(\"types\") ||\n diffTypes.includes(\"functions\") ||\n diffTypes.includes(\"generated\")\n ) {\n console.log(\"// 액션: 파일 싱크 types / functions / generated\");\n\n const tsPaths = _.uniq(\n [\n ...(diffGroups[\"types\"] ?? []),\n ...(diffGroups[\"functions\"] ?? []),\n ...(diffGroups[\"generated\"] ?? []),\n ].map((p) => p.replace(\"/dist/\", \"/src/\").replace(\".js\", \".ts\"))\n );\n await this.actionSyncFilesToTargets(tsPaths);\n }\n\n // 트리거: model\n if (diffTypes.includes(\"model\")) {\n const entityIds = this.getEntityIdFromPath(diffGroups[\"model\"]);\n console.log(\"// 액션: 서비스 생성\");\n await this.actionGenerateServices(entityIds);\n console.log(\"// 액션: HTTP파일 생성\");\n await this.actionGenerateHttps(entityIds);\n }\n\n // 저장\n await this.saveChecksums(currentChecksums);\n }\n\n getEntityIdFromPath(filePaths: string[]): string[] {\n return _.uniq(\n filePaths.map((p) => {\n const matched = p.match(/application\\/(.+)\\//);\n return inflection.camelize(matched![1].replace(/\\-/g, \"_\"));\n })\n );\n }\n\n async actionGenerateSchemas(): Promise<string[]> {\n return (\n await Promise.all([\n this.generateTemplate(\"generated_sso\", {}, { overwrite: true }),\n this.generateTemplate(\"generated\", {}, { overwrite: true }),\n ])\n )\n .flat()\n .flat();\n }\n\n async actionGenerateServices(entityIds: string[]): Promise<string[]> {\n return (\n await Promise.all(\n entityIds.map(async (entityId) =>\n this.generateTemplate(\n \"service\",\n {\n entityId,\n },\n {\n overwrite: true,\n }\n )\n )\n )\n )\n .flat()\n .flat();\n }\n\n async actionGenerateHttps(entityIds: string[]): Promise<string[]> {\n return (\n await Promise.all(\n entityIds.map(async (entityId) =>\n this.generateTemplate(\n \"generated_http\",\n {\n entityId,\n },\n {\n overwrite: true,\n }\n )\n )\n )\n )\n .flat()\n .flat();\n }\n\n async copyFileWithReplaceCoreToShared(fromPath: string, toPath: string) {\n if (!fs.existsSync(fromPath)) {\n return;\n }\n\n const oldFileContent = fs.readFileSync(fromPath).toString();\n\n const newFileContent = (() => {\n const nfc = oldFileContent.replace(\n /from \"sonamu\"/g,\n `from \"src/services/sonamu.shared\"`\n );\n\n if (toPath.includes(\"/web/\")) {\n return nfc.replace(/from \"lodash\";/g, `from \"lodash-es\";`);\n } else {\n return nfc;\n }\n })();\n return fs.writeFile(toPath, newFileContent);\n }\n\n async actionSyncFilesToTargets(tsPaths: string[]): Promise<string[]> {\n const { targets } = Sonamu.config.sync;\n const { dir: apiDir } = Sonamu.config.api;\n const { appRootPath } = Sonamu;\n\n return (\n await Promise.all(\n targets.map(async (target) =>\n Promise.all(\n tsPaths.map(async (src) => {\n const realSrc = Sonamu.apiRootPath + src;\n const dst = realSrc\n .replace(`/${apiDir}/`, `/${target}/`)\n .replace(\"/application/\", \"/services/\");\n const dir = dirname(dst);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n console.log(\n \"COPIED \",\n chalk.blue(dst.replace(appRootPath + \"/\", \"\"))\n );\n await this.copyFileWithReplaceCoreToShared(realSrc, dst);\n return dst;\n })\n )\n )\n )\n ).flat();\n }\n\n async getCurrentChecksums(): Promise<PathAndChecksum[]> {\n const PatternGroup: GlobPattern = {\n /* 원본 체크 */\n entity: Sonamu.apiRootPath + \"/src/application/**/*.entity.json\",\n types: Sonamu.apiRootPath + \"/src/application/**/*.types.ts\",\n generated: Sonamu.apiRootPath + \"/src/application/sonamu.generated.ts\",\n functions: Sonamu.apiRootPath + \"/src/application/**/*.functions.ts\",\n /* compiled-JS 체크 */\n model: Sonamu.apiRootPath + \"/dist/application/**/*.model.js\",\n };\n\n const filePaths = (\n await Promise.all(\n Object.entries(PatternGroup).map(async ([_fileType, pattern]) => {\n return globAsync(pattern);\n })\n )\n )\n .flat()\n .sort();\n\n const fileChecksums: {\n path: string;\n checksum: string;\n }[] = await Promise.all(\n filePaths.map(async (filePath) => {\n return {\n path: filePath.substring(Sonamu.apiRootPath.length),\n checksum: await this.getChecksumOfFile(filePath),\n };\n })\n );\n return fileChecksums;\n }\n\n async getPreviousChecksums(): Promise<PathAndChecksum[]> {\n if (fs.existsSync(this.checksumsPath) === false) {\n return [];\n }\n\n const previousChecksums = (await fs.readJSON(\n this.checksumsPath\n )) as PathAndChecksum[];\n return previousChecksums;\n }\n\n async saveChecksums(checksums: PathAndChecksum[]): Promise<void> {\n await fs.writeJSON(this.checksumsPath, checksums, {\n spaces: 2,\n });\n console.debug(\"checksum saved\", this.checksumsPath);\n }\n\n async getChecksumOfFile(filePath: string): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const hash = crypto.createHash(\"sha1\");\n const input = fs.createReadStream(filePath);\n input.on(\"error\", reject);\n input.on(\"data\", function (chunk: any) {\n hash.update(chunk);\n });\n input.on(\"close\", function () {\n resolve(hash.digest(\"hex\"));\n });\n });\n }\n\n async readApisFromFile(filePath: string) {\n const sourceFile = ts.createSourceFile(\n filePath,\n fs.readFileSync(filePath).toString(),\n ts.ScriptTarget.Latest\n );\n\n const methods: Omit<ExtendedApi, \"path\" | \"options\">[] = [];\n let modelName: string = \"UnknownModel\";\n let methodName: string = \"unknownMethod\";\n const visitor = (node: ts.Node) => {\n if (ts.isClassDeclaration(node)) {\n if (node.name && ts.isIdentifier(node.name)) {\n modelName = node.name.escapedText.toString().replace(/Class$/, \"\");\n }\n }\n if (ts.isMethodDeclaration(node)) {\n if (ts.isIdentifier(node.name)) {\n methodName = node.name.escapedText.toString();\n }\n\n const typeParameters: ApiParamType.TypeParam[] = (\n node.typeParameters ?? []\n ).map((typeParam) => {\n const tp = typeParam as ts.TypeParameterDeclaration;\n\n return {\n t: \"type-param\",\n id: tp.name.escapedText.toString(),\n constraint: tp.constraint\n ? this.resolveTypeNode(tp.constraint)\n : undefined,\n };\n });\n const parameters: ApiParam[] = node.parameters.map(\n (paramDec, index) => {\n const defaultDef = this.printNode(paramDec.initializer, sourceFile);\n\n // 기본값이 있는 경우 paramDec.type가 undefined로 나옴\n\n return this.resolveParamDec(\n {\n name: paramDec.name,\n type: paramDec.type as ts.TypeNode,\n optional:\n paramDec.questionToken !== undefined ||\n paramDec.initializer !== undefined,\n defaultDef,\n },\n index\n );\n }\n );\n if (node.type === undefined) {\n throw new Error(\n `리턴 타입이 기재되지 않은 메소드 ${modelName}.${methodName}`\n );\n }\n const returnType = this.resolveTypeNode(node.type!);\n\n methods.push({\n modelName,\n methodName,\n typeParameters,\n parameters,\n returnType,\n });\n }\n ts.forEachChild(node, visitor);\n };\n visitor(sourceFile);\n\n if (methods.length === 0) {\n return [];\n }\n\n // 현재 파일의 등록된 API 필터\n const currentModelApis = registeredApis.filter((api) => {\n return methods.find(\n (method) =>\n method.modelName === api.modelName &&\n method.methodName === api.methodName\n );\n });\n\n // 등록된 API에 현재 메소드 타입 정보 확장\n const extendedApis = currentModelApis.map((api) => {\n const foundMethod = methods.find(\n (method) =>\n method.modelName === api.modelName &&\n method.methodName === api.methodName\n );\n return {\n ...api,\n typeParameters: foundMethod!.typeParameters,\n parameters: foundMethod!.parameters,\n returnType: foundMethod!.returnType,\n };\n });\n return extendedApis;\n }\n\n resolveTypeNode(typeNode: ts.TypeNode): ApiParamType {\n switch (typeNode?.kind) {\n case ts.SyntaxKind.AnyKeyword:\n return \"any\";\n case ts.SyntaxKind.UnknownKeyword:\n return \"unknown\";\n case ts.SyntaxKind.StringKeyword:\n return \"string\";\n case ts.SyntaxKind.NumberKeyword:\n return \"number\";\n case ts.SyntaxKind.BooleanKeyword:\n return \"boolean\";\n case ts.SyntaxKind.UndefinedKeyword:\n return \"undefined\";\n case ts.SyntaxKind.NullKeyword:\n return \"null\";\n case ts.SyntaxKind.VoidKeyword:\n return \"void\";\n case ts.SyntaxKind.LiteralType:\n const literal = (typeNode as ts.LiteralTypeNode).literal;\n if (ts.isStringLiteral(literal)) {\n return {\n t: \"string-literal\",\n value: literal.text,\n };\n } else if (ts.isNumericLiteral(literal)) {\n return {\n t: \"numeric-literal\",\n value: Number(literal.text),\n };\n } else {\n if (literal.kind === ts.SyntaxKind.NullKeyword) {\n return \"null\";\n } else if (literal.kind === ts.SyntaxKind.UndefinedKeyword) {\n return \"undefined\";\n } else if (literal.kind === ts.SyntaxKind.TrueKeyword) {\n return \"true\";\n } else if (literal.kind === ts.SyntaxKind.FalseKeyword) {\n return \"false\";\n }\n throw new Error(\"알 수 없는 리터럴\");\n }\n case ts.SyntaxKind.ArrayType:\n const arrNode = typeNode as ts.ArrayTypeNode;\n return {\n t: \"array\",\n elementsType: this.resolveTypeNode(arrNode.elementType),\n };\n case ts.SyntaxKind.TypeLiteral:\n const literalNode = typeNode as ts.TypeLiteralNode;\n return {\n t: \"object\",\n props: literalNode.members.map((member) => {\n if (ts.isIndexSignatureDeclaration(member)) {\n const res = this.resolveParamDec({\n name: member.parameters[0].name as ts.Identifier,\n type: member.parameters[0].type as ts.TypeNode,\n });\n\n return this.resolveParamDec({\n name: {\n escapedText: `[${res.name}${res.optional ? \"?\" : \"\"}: ${\n res.type\n }]`,\n } as ts.Identifier,\n type: member.type as ts.TypeNode,\n });\n } else {\n return this.resolveParamDec({\n name: (member as ts.PropertySignature).name as ts.Identifier,\n type: (member as ts.PropertySignature).type as ts.TypeNode,\n optional:\n (member as ts.PropertySignature).questionToken !== undefined,\n });\n }\n }),\n };\n case ts.SyntaxKind.TypeReference:\n return {\n t: \"ref\",\n id: (\n (typeNode as ts.TypeReferenceNode).typeName as ts.Identifier\n ).escapedText.toString(),\n args: (typeNode as ts.TypeReferenceNode).typeArguments?.map(\n (typeArg) => this.resolveTypeNode(typeArg)\n ),\n };\n case ts.SyntaxKind.UnionType:\n return {\n t: \"union\",\n types: (typeNode as ts.UnionTypeNode).types.map((type) =>\n this.resolveTypeNode(type)\n ),\n };\n case ts.SyntaxKind.IntersectionType:\n return {\n t: \"intersection\",\n types: (typeNode as ts.IntersectionTypeNode).types.map((type) =>\n this.resolveTypeNode(type)\n ),\n };\n case ts.SyntaxKind.IndexedAccessType:\n return {\n t: \"indexed-access\",\n object: this.resolveTypeNode(\n (typeNode as ts.IndexedAccessTypeNode).objectType\n ),\n index: this.resolveTypeNode(\n (typeNode as ts.IndexedAccessTypeNode).indexType\n ),\n };\n case ts.SyntaxKind.TupleType:\n if (ts.isTupleTypeNode(typeNode)) {\n return {\n t: \"tuple-type\",\n elements: typeNode.elements.map((elem) =>\n this.resolveTypeNode(elem)\n ),\n };\n }\n break;\n case undefined:\n throw new Error(`typeNode undefined`);\n }\n\n console.debug(typeNode);\n throw new Error(`알 수 없는 SyntaxKind ${typeNode.kind}`);\n }\n\n resolveParamDec = (\n paramDec: {\n name: ts.BindingName;\n type: ts.TypeNode;\n optional?: boolean;\n defaultDef?: string;\n },\n index: number = 0\n ): ApiParam => {\n const name = paramDec.name as ts.Identifier;\n const type = this.resolveTypeNode(paramDec.type);\n\n if (name === undefined) {\n console.log({ name, type, paramDec });\n }\n\n return {\n name: name.escapedText ? name.escapedText.toString() : `nonameAt${index}`,\n type,\n optional: paramDec.optional === true,\n defaultDef: paramDec?.defaultDef,\n };\n };\n\n printNode(\n node: ts.Node | undefined,\n sourceFile: ts.SourceFile\n ): string | undefined {\n if (node === undefined) {\n return undefined;\n }\n\n const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n return printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);\n }\n\n async autoloadApis() {\n const pathPattern = path.join(\n Sonamu.apiRootPath,\n \"/src/application/**/*.model.ts\"\n );\n // console.debug(chalk.yellow(`autoload:APIs @ ${pathPattern}`));\n\n const filePaths = await globAsync(pathPattern);\n const result = await Promise.all(\n filePaths.map((filePath) => this.readApisFromFile(filePath))\n );\n this.apis = result.flat();\n return this.apis;\n }\n\n async autoloadModels(): Promise<{ [modelName: string]: unknown }> {\n const pathPattern = path.join(\n Sonamu.apiRootPath,\n \"dist/application/**/*.model.js\"\n );\n // console.debug(chalk.yellow(`autoload:models @ ${pathPattern}`));\n\n const filePaths = (await globAsync(pathPattern)).filter((path) => {\n // src 디렉터리 내에 있는 해당 파일이 존재할 경우에만 로드\n // 삭제된 파일이지만 dist에 남아있는 경우 BaseSchema undefined 에러 방지\n const srcPath = path.replace(\"/dist/\", \"/src/\").replace(\".js\", \".ts\");\n return fs.existsSync(srcPath);\n });\n const modules = await importMultiple(filePaths);\n const functions = modules\n .map(({ imported }) => Object.entries(imported))\n .flat();\n this.models = Object.fromEntries(\n functions.filter(([name]) => name.endsWith(\"Model\"))\n );\n return this.models;\n }\n\n async autoloadTypes(\n doRefresh: boolean = false\n ): Promise<{ [typeName: string]: z.ZodObject<any> }> {\n if (!doRefresh && Object.keys(this.types).length > 0) {\n return this.types;\n }\n\n const pathPatterns = [\n path.join(Sonamu.apiRootPath, \"/dist/application/**/*.types.js\"),\n path.join(Sonamu.apiRootPath, \"/dist/application/**/*.generated.js\"),\n ];\n // console.debug(chalk.magenta(`autoload:types @ ${pathPatterns.join(\"\\n\")}`));\n\n const filePaths = (\n await Promise.all(pathPatterns.map((pattern) => globAsync(pattern)))\n )\n .flat()\n .filter((path) => {\n // src 디렉터리 내에 있는 해당 파일이 존재할 경우에만 로드\n // 삭제된 파일이지만 dist에 남아있는 경우 BaseSchema undefined 에러 방지\n const srcPath = path.replace(\"/dist/\", \"/src/\").replace(\".js\", \".ts\");\n return fs.existsSync(srcPath);\n });\n const modules = await importMultiple(filePaths, doRefresh);\n const functions = modules\n .map(({ imported }) => Object.entries(imported))\n .flat();\n this.types = Object.fromEntries(\n functions.filter(([, f]) => f instanceof z.ZodType)\n ) as typeof this.types;\n return this.types;\n }\n\n getTemplate(key: TemplateKey): Template {\n if (key === \"entity\") {\n return new Template__entity();\n } else if (key === \"init_types\") {\n return new Template__init_types();\n } else if (key === \"generated\") {\n return new Template__generated();\n } else if (key === \"generated_sso\") {\n return new Template__generated_sso();\n } else if (key === \"generated_http\") {\n return new Template__generated_http();\n } else if (key === \"model\") {\n return new Template__model();\n } else if (key === \"model_test\") {\n return new Template__model_test();\n } else if (key === \"service\") {\n return new Template__service();\n } else if (key === \"view_list\") {\n return new Template__view_list();\n } else if (key === \"view_list_columns\") {\n return new Template__view_list_columns();\n } else if (key === \"view_search_input\") {\n return new Template__view_search_input();\n } else if (key === \"view_form\") {\n return new Template__view_form();\n } else if (key === \"view_id_all_select\") {\n return new Template__view_id_all_select();\n } else if (key === \"view_id_async_select\") {\n return new Template__view_id_async_select();\n } else if (key === \"view_enums_select\") {\n return new Template__view_enums_select();\n } else if (key === \"view_enums_dropdown\") {\n return new Template__view_enums_dropdown();\n } else if (key === \"view_enums_buttonset\") {\n return new Template__view_enums_buttonset();\n } else {\n throw new BadRequestException(`잘못된 템플릿 키 ${key}`);\n }\n }\n\n async renderTemplate<T extends keyof TemplateOptions>(\n key: T,\n options: TemplateOptions[T]\n ): Promise<PathAndCode[]> {\n const template: Template = this.getTemplate(key);\n\n let extra: unknown[] = [];\n if (\n [\"service\", \"generated_http\", \"model\", \"view_list\", \"view_form\"].includes(\n key\n )\n ) {\n const entityId = (options as TemplateOptions[\"service\"]).entityId;\n\n if (key === \"service\" || key === \"generated_http\") {\n // service 필요 정보 (API 리스트)\n const entity = EntityManager.get(entityId!);\n const modelTsPath = `${path.join(\n Sonamu.apiRootPath,\n \"/src/application\"\n )}/${entity.names.fs}/${entity.names.fs}.model.ts`;\n extra = [await this.readApisFromFile(modelTsPath)];\n } else if (key === \"view_list\" || key === \"model\") {\n // view_list 필요 정보 (컬럼 노드, 리스트파라미터 노드)\n const columnsNode = await this.getColumnsNode(entityId, \"A\");\n const listParamsZodType = await this.getZodTypeById(\n `${entityId}ListParams`\n );\n const listParamsNode = this.zodTypeToRenderingNode(listParamsZodType);\n extra = [columnsNode, listParamsNode];\n } else if (key === \"view_form\") {\n // view_form 필요 정보 (세이브파라미터 노드)\n const saveParamsZodType = await this.getZodTypeById(\n `${entityId}SaveParams`\n );\n const saveParamsNode = this.zodTypeToRenderingNode(saveParamsZodType);\n extra = [saveParamsNode];\n }\n }\n\n const rendered = await template.render(options, ...extra);\n const resolved = await this.resolveRenderedTemplate(key, rendered);\n\n let preTemplateResolved: PathAndCode[] = [];\n if (rendered.preTemplates) {\n preTemplateResolved = (\n await Promise.all(\n rendered.preTemplates.map(({ key, options }) => {\n return this.renderTemplate(key, options);\n })\n )\n ).flat();\n }\n\n return [resolved, ...preTemplateResolved];\n }\n\n async resolveRenderedTemplate(\n key: TemplateKey,\n result: RenderedTemplate\n ): Promise<PathAndCode> {\n const { target, path: filePath, body, importKeys, customHeaders } = result;\n\n // import 할 대상의 대상 path 추출\n const importDefs = importKeys\n .reduce(\n (r, importKey) => {\n const modulePath = EntityManager.getModulePath(importKey);\n let importPath = modulePath;\n if (modulePath.includes(\"/\") || modulePath.includes(\".\")) {\n importPath = wrapIf(\n path.relative(path.dirname(filePath), modulePath),\n (p) => [p.startsWith(\".\") === false, \"./\" + p]\n );\n }\n\n // 같은 파일에서 import 하는 경우 keys 로 나열 처리\n const existsOne = r.find(\n (importDef) => importDef.from === importPath\n );\n if (existsOne) {\n existsOne.keys = _.uniq(existsOne.keys.concat(importKey));\n } else {\n r.push({\n keys: [importKey],\n from: importPath,\n });\n }\n return r;\n },\n [] as {\n keys: string[];\n from: string;\n }[]\n )\n // 셀프 참조 방지\n .filter(\n (importDef) =>\n filePath.endsWith(importDef.from.replace(\"./\", \"\") + \".ts\") === false\n );\n\n // 커스텀 헤더 포함하여 헤더 생성\n const header = [\n ...(customHeaders ?? []),\n ...importDefs.map(\n (importDef) =>\n `import { ${importDef.keys.join(\", \")} } from '${importDef.from}'`\n ),\n ].join(\"\\n\");\n\n const formatted = await (async () => {\n if (key === \"generated_http\") {\n return [header, body].join(\"\\n\\n\");\n } else {\n return prettier.format([header, body].join(\"\\n\\n\"), {\n parser: key === \"entity\" ? \"json\" : \"typescript\",\n });\n }\n })();\n\n return {\n path: target + \"/\" + filePath,\n code: formatted,\n };\n }\n\n async writeCodeToPath(pathAndCode: PathAndCode): Promise<string[]> {\n const { targets } = Sonamu.config.sync;\n const { appRootPath } = Sonamu;\n const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;\n\n const dstFilePaths = _.uniq(\n targets.map((target) => filePath.replace(\"/:target/\", `/${target}/`))\n );\n return await Promise.all(\n dstFilePaths.map(async (dstFilePath) => {\n const dir = path.dirname(dstFilePath);\n if (fs.existsSync(dir) === false) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(dstFilePath, pathAndCode.code);\n console.log(\n \"GENERATED \",\n chalk.blue(dstFilePath.replace(appRootPath + \"/\", \"\"))\n );\n return dstFilePath;\n })\n );\n }\n\n async generateTemplate(\n key: TemplateKey,\n templateOptions: any,\n _generateOptions?: GenerateOptions\n ) {\n const generateOptions = {\n overwrite: false,\n ..._generateOptions,\n };\n\n // 키 children\n const keys: TemplateKey[] = [key];\n\n // 템플릿 렌더\n const pathAndCodes = (\n await Promise.all(\n keys.map(async (key) => {\n return await this.renderTemplate(key, templateOptions);\n })\n )\n ).flat();\n\n const filteredPathAndCodes: PathAndCode[] = (() => {\n if (generateOptions.overwrite === true) {\n return pathAndCodes;\n } else {\n return pathAndCodes.filter((pathAndCode) => {\n const { targets } = Sonamu.config.sync;\n const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;\n const dstFilePaths = targets.map((target) =>\n filePath.replace(\"/:target/\", `/${target}/`)\n );\n return dstFilePaths.every(\n (dstPath) => fs.existsSync(dstPath) === false\n );\n });\n }\n })();\n if (filteredPathAndCodes.length === 0) {\n throw new AlreadyProcessedException(\n \"이미 경로에 모든 파일이 존재합니다.\"\n );\n }\n\n return Promise.all(\n filteredPathAndCodes.map((pathAndCode) =>\n this.writeCodeToPath(pathAndCode)\n )\n );\n }\n\n checkExistsGenCode(\n entityId: string,\n templateKey: TemplateKey,\n enumId?: string\n ): { subPath: string; fullPath: string; isExists: boolean } {\n const { target, path: genPath } = this.getTemplate(\n templateKey\n ).getTargetAndPath(EntityManager.getNamesFromId(entityId), enumId);\n\n const fullPath = path.join(Sonamu.appRootPath, target, genPath);\n const subPath = path.join(target, genPath);\n return {\n subPath,\n fullPath,\n isExists: fs.existsSync(fullPath),\n };\n }\n\n checkExists(\n entityId: string,\n enums: {\n [name: string]: z.ZodEnum<any>;\n }\n ): Record<`${TemplateKey}${string}`, boolean> {\n const keys: TemplateKey[] = TemplateKey.options;\n const names = EntityManager.getNamesFromId(entityId);\n const enumsKeys = Object.keys(enums).filter(\n (name) => name !== names.constant\n );\n\n return keys.reduce((result, key) => {\n const tpl = this.getTemplate(key);\n if (key.startsWith(\"view_enums\")) {\n enumsKeys.map((componentId) => {\n const { target, path: p } = tpl.getTargetAndPath(names, componentId);\n result[`${key}__${componentId}`] = fs.existsSync(\n path.join(Sonamu.appRootPath, target, p)\n );\n });\n return result;\n }\n\n const { target, path: p } = tpl.getTargetAndPath(names);\n const { targets } = Sonamu.config.sync;\n if (target.includes(\":target\")) {\n targets.map((t) => {\n result[`${key}__${t}`] = fs.existsSync(\n path.join(Sonamu.appRootPath, target.replace(\":target\", t), p)\n );\n });\n } else {\n result[key] = fs.existsSync(path.join(Sonamu.appRootPath, target, p));\n }\n\n return result;\n }, {} as Record<`${TemplateKey}${string}`, boolean>);\n }\n\n async getZodTypeById(zodTypeId: string): Promise<z.ZodTypeAny> {\n const modulePath = EntityManager.getModulePath(zodTypeId);\n const moduleAbsPath = path.join(\n Sonamu.apiRootPath,\n \"dist\",\n \"application\",\n modulePath + \".js\"\n );\n const importPath = \"./\" + path.relative(__dirname, moduleAbsPath);\n const imported = await import(importPath);\n\n if (!imported[zodTypeId]) {\n throw new Error(`존재하지 않는 zodTypeId ${zodTypeId}`);\n }\n return imported[zodTypeId].describe(zodTypeId);\n }\n\n async propNodeToZodType(propNode: EntityPropNode): Promise<z.ZodTypeAny> {\n if (propNode.nodeType === \"plain\") {\n return this.propToZodType(propNode.prop);\n } else if (propNode.nodeType === \"array\") {\n if (propNode.prop === undefined) {\n throw new Error();\n } else if (propNode.children.length > 0) {\n return (\n await this.propNodeToZodType({\n ...propNode,\n nodeType: \"object\",\n })\n ).array();\n } else {\n const innerType = await this.propToZodType(propNode.prop);\n if (propNode.prop.nullable === true) {\n return z.array(innerType).nullable();\n } else {\n return z.array(innerType);\n }\n }\n } else if (propNode.nodeType === \"object\") {\n const obj = await propNode.children.reduce(\n async (promise, childPropNode) => {\n const result = await promise;\n result[childPropNode.prop!.name] = await this.propNodeToZodType(\n childPropNode\n );\n return result;\n },\n {} as any\n );\n\n if (propNode.prop?.nullable === true) {\n return z.object(obj).nullable();\n } else {\n return z.object(obj);\n }\n } else {\n throw Error;\n }\n }\n async propToZodType(prop: EntityProp): Promise<z.ZodTypeAny> {\n let zodType: z.ZodTypeAny = z.unknown();\n if (isIntegerProp(prop)) {\n zodType = z.number().int();\n } else if (isBigIntegerProp(prop)) {\n zodType = z.bigint();\n } else if (isTextProp(prop)) {\n zodType = z.string().max(getTextTypeLength(prop.textType));\n } else if (isEnumProp(prop)) {\n zodType = await this.getZodTypeById(prop.id);\n } else if (isStringProp(prop)) {\n zodType = z.string().max(prop.length);\n } else if (isFloatProp(prop) || isDoubleProp(prop)) {\n zodType = z.number();\n } else if (isDecimalProp(prop)) {\n zodType = z.string();\n } else if (isBooleanProp(prop)) {\n zodType = z.boolean();\n } else if (isDateProp(prop)) {\n zodType = z.string().length(10);\n } else if (isTimeProp(prop)) {\n zodType = z.string().length(8);\n } else if (isDateTimeProp(prop)) {\n zodType = SQLDateTimeString;\n } else if (isTimestampProp(prop)) {\n zodType = SQLDateTimeString;\n } else if (isJsonProp(prop)) {\n zodType = await this.getZodTypeById(prop.id);\n } else if (isUuidProp(prop)) {\n zodType = z.string().uuid();\n } else if (isVirtualProp(prop)) {\n zodType = await this.getZodTypeById(prop.id);\n } else if (isRelationProp(prop)) {\n if (\n isBelongsToOneRelationProp(prop) ||\n (isOneToOneRelationProp(prop) && prop.hasJoinColumn)\n ) {\n zodType = z.number().int();\n }\n } else {\n throw new Error(`prop을 zodType으로 변환하는데 실패 ${prop}}`);\n }\n\n if ((prop as { unsigned?: boolean }).unsigned) {\n zodType = (zodType as z.ZodNumber).nonnegative();\n }\n if (prop.nullable) {\n zodType = zodType.nullable();\n }\n\n return zodType;\n }\n\n resolveRenderType(\n key: string,\n zodType: z.ZodTypeAny\n ): RenderingNode[\"renderType\"] {\n if (zodType instanceof z.ZodString) {\n if (key.includes(\"img\") || key.includes(\"image\")) {\n return \"string-image\";\n } else if (zodType.description === \"SQLDateTimeString\") {\n return \"string-datetime\";\n } else if (key.endsWith(\"date\")) {\n return \"string-date\";\n } else {\n return \"string-plain\";\n }\n } else if (zodType instanceof z.ZodNumber) {\n if (key === \"id\") {\n return \"number-id\";\n } else if (key.endsWith(\"_id\")) {\n return \"number-fk_id\";\n } else {\n return \"number-plain\";\n }\n } else if (zodType instanceof z.ZodBoolean) {\n return \"boolean\";\n } else if (zodType instanceof z.ZodEnum) {\n return \"enums\";\n } else if (zodType instanceof z.ZodRecord) {\n return \"record\";\n } else if (zodType instanceof z.ZodAny || zodType instanceof z.ZodUnknown) {\n return \"string-plain\";\n } else if (zodType instanceof z.ZodUnion) {\n return \"string-plain\";\n } else if (zodType instanceof z.ZodLiteral) {\n return \"string-plain\";\n } else {\n throw new Error(`타입 파싱 불가 ${key} ${zodType._def.typeName}`);\n }\n }\n zodTypeToRenderingNode(\n zodType: z.ZodTypeAny,\n baseKey: string = \"root\"\n ): RenderingNode {\n const def = {\n name: baseKey,\n label: inflection.camelize(baseKey, false),\n zodType,\n };\n if (zodType instanceof z.ZodObject) {\n const columnKeys = Object.keys(zodType.shape);\n const children = columnKeys.map((key) => {\n const innerType = zodType.shape[key];\n return this.zodTypeToRenderingNode(innerType, key);\n });\n return {\n ...def,\n renderType: \"object\",\n children,\n };\n } else if (zodType instanceof z.ZodArray) {\n const innerType = zodType._def.type;\n if (innerType instanceof z.ZodString && baseKey.includes(\"images\")) {\n return {\n ...def,\n renderType: \"array-images\",\n };\n }\n return {\n ...def,\n renderType: \"array\",\n element: this.zodTypeToRenderingNode(innerType, baseKey),\n };\n } else if (zodType instanceof z.ZodUnion) {\n const optionNodes = zodType._def.options.map((opt: z.ZodTypeAny) =>\n this.zodTypeToRenderingNode(opt, baseKey)\n );\n // TODO: ZodUnion이 들어있는 경우 핸들링\n return optionNodes[0];\n } else if (zodType instanceof z.ZodOptional) {\n return {\n ...this.zodTypeToRenderingNode(zodType._def.innerType, baseKey),\n optional: true,\n };\n } else if (zodType instanceof z.ZodNullable) {\n return {\n ...this.zodTypeToRenderingNode(zodType._def.innerType, baseKey),\n nullable: true,\n };\n } else {\n return {\n ...def,\n renderType: this.resolveRenderType(baseKey, zodType),\n };\n }\n }\n\n async getColumnsNode(\n entityId: string,\n subsetKey: string\n ): Promise<RenderingNode> {\n const entity = await EntityManager.get(entityId);\n const subsetA = entity.subsets[subsetKey];\n if (subsetA === undefined) {\n throw new ServiceUnavailableException(\"SubsetA 가 없습니다.\");\n }\n const propNodes = entity.fieldExprsToPropNodes(subsetA);\n const rootPropNode: EntityPropNode = {\n nodeType: \"object\",\n children: propNodes,\n };\n\n const columnsZodType = (await this.propNodeToZodType(\n rootPropNode\n )) as z.ZodObject<any>;\n\n const columnsNode = this.zodTypeToRenderingNode(columnsZodType);\n columnsNode.children = columnsNode.children!.map((child) => {\n if (child.renderType === \"object\") {\n const pickedCol = child.children!.find((cc) =>\n [\"title\", \"name\"].includes(cc.name)\n );\n if (pickedCol) {\n return {\n ...child,\n renderType: \"object-pick\",\n config: {\n picked: pickedCol.name,\n },\n };\n } else {\n return child;\n }\n } else if (\n child.renderType === \"array\" &&\n child.element &&\n child.element.renderType === \"object\"\n ) {\n const pickedCol = child.element!.children!.find((cc) =>\n [\"title\", \"name\"].includes(cc.name)\n );\n if (pickedCol) {\n return {\n ...child,\n element: {\n ...child.element,\n renderType: \"object-pick\",\n config: {\n picked: pickedCol.name,\n },\n },\n };\n } else {\n return child;\n }\n }\n return child;\n });\n\n return columnsNode;\n }\n\n async createEntity(\n form: Omit<TemplateOptions[\"entity\"], \"title\"> & { title?: string }\n ) {\n if (!/^[A-Z][a-zA-Z0-9]*$/.test(form.entityId)) {\n throw new BadRequestException(\"entityId는 CamelCase 형식이어야 합니다.\");\n }\n\n await this.generateTemplate(\"entity\", form);\n\n // reload entities\n await EntityManager.reload();\n\n // generate schemas\n await this.actionGenerateSchemas();\n\n // generate types\n if (form.parentId === undefined) {\n await this.generateTemplate(\"init_types\", {\n entityId: form.entityId,\n });\n }\n }\n\n async delEntity(entityId: string): Promise<{ delPaths: string[] }> {\n const entity = EntityManager.get(entityId);\n\n const delPaths = (() => {\n if (entity.parentId) {\n return [\n `${Sonamu.apiRootPath}/src/application/${entity.names.parentFs}/${entity.names.fs}.entity.json`,\n ];\n } else {\n return [\n `${Sonamu.apiRootPath}/src/application/${entity.names.fs}`,\n `${Sonamu.apiRootPath}/dist/application/${entity.names.fs}`,\n ...Sonamu.config.sync.targets\n .map((target) => [\n `${Sonamu.appRootPath}/${target}/src/services/${entity.names.fs}`,\n ])\n .flat(),\n ];\n }\n })(); // iife\n\n for await (const delPath of delPaths) {\n if (fs.existsSync(delPath)) {\n console.log(chalk.red(`DELETE ${delPath}`));\n execSync(`rm -rf ${delPath}`);\n } else {\n console.log(chalk.yellow(`NOT_EXISTS ${delPath}`));\n }\n }\n\n // reload entities\n await EntityManager.reload();\n\n return { delPaths };\n }\n}\n","export function wrapIf(\n source: string,\n predicate: (str: string) => [boolean, string]\n): string {\n const [ok, wrapped] = predicate(source);\n return ok ? wrapped : source;\n}\n","import _ from \"lodash\";\nimport { TemplateOptions } from \"../types/types\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport { Entity } from \"../entity/entity\";\nimport { EntityPropNode } from \"../types/types\";\nimport { propNodeToZodTypeDef, zodTypeToZodCode } from \"../api/code-converters\";\nimport { Template } from \"./base-template\";\nimport { nonNullable } from \"../utils/utils\";\nimport { Sonamu } from \"../api\";\n\nexport type SourceCode = {\n label: string;\n lines: string[];\n importKeys: string[];\n};\nexport class Template__generated extends Template {\n constructor() {\n super(\"generated\");\n }\n\n getTargetAndPath() {\n const { dir } = Sonamu.config.api;\n\n return {\n target: `${dir}/src/application`,\n path: `sonamu.generated.ts`,\n };\n }\n\n render({}: TemplateOptions[\"generated\"]) {\n const entityIds = EntityManager.getAllIds();\n const entities = entityIds.map((id) => EntityManager.get(id));\n\n // 전체 SourceCode 생성\n const sourceCodes = entities\n .map((entity) => {\n return [\n this.getEnumsSourceCode(entity),\n this.getBaseSchemaSourceCode(entity),\n this.getBaseListParamsSourceCode(entity),\n this.getSubsetSourceCode(entity),\n ].filter(nonNullable);\n })\n .flat();\n\n // Sort\n const LABEL_KEY_ORDER = [\n \"Enums\",\n \"BaseSchema\",\n \"BaseListParams\",\n \"Subsets\",\n \"SubsetQueries\",\n ];\n sourceCodes.sort((a, b) => {\n const [aKey] = a.label.split(\":\");\n const [bKey] = b.label.split(\":\");\n const aIndex = LABEL_KEY_ORDER.indexOf(aKey);\n const bIndex = LABEL_KEY_ORDER.indexOf(bKey);\n if (aIndex > bIndex) {\n return 1;\n } else if (aIndex < bIndex) {\n return -1;\n } else {\n return 0;\n }\n });\n\n const sourceCode = sourceCodes.reduce(\n (result, ts) => {\n if (ts === null) {\n return result;\n }\n return {\n lines: [...result!.lines, `// ${ts.label}`, ...ts.lines, \"\"],\n importKeys: _.uniq([...result!.importKeys, ...ts.importKeys]),\n };\n },\n {\n lines: [],\n importKeys: [],\n } as Omit<SourceCode, \"label\">\n );\n\n // .types.ts의 타입을 참조하는 경우 순환참조(상호참조)가 발생하므로 타입을 가져와 인라인 처리\n const allTypeKeys = entities\n .map((entity) => Object.keys(entity.types))\n .flat();\n const cdImportKeys = sourceCode.importKeys.filter((importKey) =>\n allTypeKeys.includes(importKey)\n );\n if (cdImportKeys.length > 0) {\n const customScalarLines = cdImportKeys\n .map((importKey) => {\n const entity = entities.find((entity) => entity.types[importKey]);\n if (!entity) {\n throw new Error(`ZodType not found ${importKey}`);\n }\n const zodType = entity.types[importKey]!;\n\n return [\n `// CustomScalar: ${importKey}`,\n `const ${importKey} = ${zodTypeToZodCode(zodType)};`,\n `type ${importKey} = z.infer<typeof ${importKey}>`,\n \"\",\n ];\n })\n .flat();\n sourceCode.lines = [...customScalarLines, ...sourceCode.lines];\n sourceCode.importKeys = sourceCode.importKeys.filter(\n (importKey) => !cdImportKeys.includes(importKey)\n );\n }\n\n const body = sourceCode.lines.join(\"\\n\");\n\n // import\n const sonamuImports = [\n \"zArrayable\",\n \"SQLDateTimeString\",\n \"SubsetQuery\",\n \"SonamuQueryMode\",\n ].filter((mod) => body.includes(mod));\n\n return {\n ...this.getTargetAndPath(),\n body,\n importKeys: sourceCode.importKeys,\n customHeaders: [\n `import { z } from 'zod';`,\n `import { ${sonamuImports.join(\",\")} } from \"sonamu\";`,\n ],\n };\n }\n\n getEnumsSourceCode(entity: Entity): SourceCode | null {\n if (Object.keys(entity.enumLabels).length === 0) {\n return null;\n }\n return {\n label: `Enums: ${entity.id}`,\n lines: [\n ...Object.entries(entity.enumLabels)\n .filter(([_, enumLabel]) => Object.keys(enumLabel).length > 0)\n .map(([enumId, enumLabel]) => [\n `export const ${enumId} = z.enum([${Object.keys(enumLabel).map(\n (el) => `\"${el}\"`\n )}]).describe(\"${enumId}\");`,\n `export type ${enumId} = z.infer<typeof ${enumId}>`,\n `export const ${enumId}Label = ${JSON.stringify(enumLabel)}`,\n ])\n .flat(),\n ],\n importKeys: [],\n };\n }\n\n getBaseSchemaSourceCode(\n entity: Entity,\n importKeys: string[] = []\n ): SourceCode {\n const schemaName = `${entity.names.module}BaseSchema`;\n const propNode: EntityPropNode = {\n nodeType: \"object\",\n children: entity.props.map((prop) => {\n return {\n nodeType: \"plain\",\n prop,\n };\n }),\n };\n\n const schemaBody = propNodeToZodTypeDef(propNode, importKeys);\n\n const lines = [\n `export const ${schemaName} = ${schemaBody}`,\n `export type ${schemaName} = z.infer<typeof ${schemaName}>`,\n ];\n\n return {\n label: `BaseSchema: ${entity.id}`,\n importKeys,\n lines,\n };\n }\n\n getBaseListParamsSourceCode(entity: Entity): SourceCode | null {\n // Prop 없는 MD인 경우 생성 제외\n if (entity.props.length === 0) {\n return null;\n } else if (entity.parentId !== undefined) {\n return null;\n }\n\n const schemaName = `${entity.names.module}BaseListParams`;\n\n const filterProps = entity.props.filter((prop) => prop.toFilter === true);\n\n const propNodes: EntityPropNode[] = filterProps.map((prop) => {\n return {\n nodeType: \"plain\" as const,\n prop,\n children: [],\n };\n });\n\n const importKeys: string[] = [];\n const filterBody = propNodes\n .map((propNode) => propNodeToZodTypeDef(propNode, importKeys))\n .join(\"\\n\");\n\n const schemaBody = `\nz.object({\n num: z.number().int().nonnegative(),\n page: z.number().int().min(1),\n search: ${entity.id}SearchField,\n keyword: z.string(),\n orderBy: ${entity.id}OrderBy,\n queryMode: SonamuQueryMode,\n id: zArrayable(z.number().int().positive()),${filterBody}\n}).partial();\n`.trim();\n\n const lines = [\n `export const ${schemaName} = ${schemaBody}`,\n `export type ${schemaName} = z.infer<typeof ${schemaName}>`,\n ];\n\n return {\n label: `BaseListParams: ${entity.id}`,\n importKeys,\n lines,\n };\n }\n\n getSubsetSourceCode(entity: Entity): SourceCode | null {\n if (Object.keys(entity.subsets).length == 0) {\n return null;\n } else if (entity.parentId !== undefined) {\n return null;\n }\n\n const subsetKeys = Object.keys(entity.subsets);\n const importKeys: string[] = [];\n const lines: string[] = [\n ...subsetKeys\n .map((subsetKey) => {\n // 서브셋에서 FieldExpr[] 가져옴\n const fieldExprs = entity.subsets[subsetKey];\n\n // FieldExpr[]로 EntityPropNode[] 가져옴\n const propNodes = entity.fieldExprsToPropNodes(fieldExprs);\n const schemaName = `${entity.names.module}Subset${subsetKey}`;\n const propNode: EntityPropNode = {\n nodeType: \"object\",\n children: propNodes,\n };\n\n // EntityPropNode[]로 ZodTypeDef(string)을 가져옴\n const body = propNodeToZodTypeDef(propNode, importKeys);\n\n return [\n `export const ${schemaName} = ${body}`,\n `export type ${schemaName} = z.infer<typeof ${schemaName}>`,\n ];\n })\n .flat(),\n `export type ${entity.names.module}SubsetMapping = {`,\n ...subsetKeys.map(\n (subsetKey) =>\n ` ${subsetKey}: ${entity.names.module}Subset${subsetKey};`\n ),\n \"}\",\n `export const ${entity.names.module}SubsetKey = z.enum([${subsetKeys\n .map((k) => `\"${k}\"`)\n .join(\",\")}]);`,\n `export type ${entity.names.module}SubsetKey = z.infer<typeof ${entity.names.module}SubsetKey>`,\n \"\",\n ];\n\n return {\n label: `Subsets: ${entity.id}`,\n lines,\n importKeys: _.uniq(importKeys),\n };\n }\n}\n","import { TemplateKey, TemplateOptions } from \"../types/types\";\nimport { EntityNamesRecord } from \"../entity/entity-manager\";\nimport { RenderedTemplate } from \"../syncer/syncer\";\n\nexport abstract class Template {\n constructor(public key: TemplateKey) {}\n public abstract render(\n options: TemplateOptions[TemplateKey],\n ...extra: unknown[]\n ): RenderedTemplate | Promise<RenderedTemplate>;\n\n public abstract getTargetAndPath(\n names?: EntityNamesRecord,\n ...extra: unknown[]\n ): {\n target: string;\n path: string;\n };\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\nimport { Sonamu } from \"../api\";\n\nexport class Template__init_types extends Template {\n constructor() {\n super(\"init_types\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n const { dir } = Sonamu.config.api;\n\n return {\n target: `${dir}/src/application`,\n path: `${names.fs}/${names.fs}.types.ts`,\n };\n }\n\n render({ entityId }: TemplateOptions[\"init_types\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n\n const hasCreatedAt =\n EntityManager.get(entityId).props.find(\n (prop) => prop.name === \"created_at\"\n ) !== undefined;\n\n return {\n ...this.getTargetAndPath(names),\n body: `\nimport { z } from \"zod\";\nimport { ${entityId}BaseSchema, ${entityId}BaseListParams } from \"../sonamu.generated\";\n\n// ${entityId} - ListParams\nexport const ${entityId}ListParams = ${entityId}BaseListParams;\nexport type ${entityId}ListParams = z.infer<typeof ${entityId}ListParams>;\n\n// ${entityId} - SaveParams\nexport const ${entityId}SaveParams = ${entityId}BaseSchema.partial({ id: true${\n hasCreatedAt ? \", created_at: true\" : \"\"\n } });\nexport type ${entityId}SaveParams = z.infer<typeof ${entityId}SaveParams>;\n\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\nimport { Sonamu } from \"../api\";\n\nexport class Template__entity extends Template {\n constructor() {\n super(\"entity\");\n }\n\n getTargetAndPath(names: EntityNamesRecord, parentNames?: EntityNamesRecord) {\n const { dir } = Sonamu.config.api;\n\n return {\n target: `${dir}/src/application`,\n path: `${(parentNames ?? names).fs}/${names.fs}.entity.json`,\n };\n }\n\n render(options: TemplateOptions[\"entity\"]) {\n const { entityId, title, parentId, table } = options;\n const names = EntityManager.getNamesFromId(entityId);\n\n const parent = (() => {\n if (parentId) {\n return {\n names: EntityManager.getNamesFromId(parentId),\n entity: EntityManager.get(parentId),\n };\n } else {\n return null;\n }\n })();\n\n return {\n ...this.getTargetAndPath(names, parent?.names ?? names),\n body: JSON.stringify({\n id: entityId,\n title: title ?? entityId,\n parentId,\n table: table ?? names.fsPlural.replace(/\\-/g, \"_\"),\n props: options.props?.length\n ? options.props\n : [\n { name: \"id\", type: \"integer\", unsigned: true, desc: \"ID\" },\n ...(parent\n ? [\n {\n type: \"relation\",\n name: parent.names.camel,\n relationType: \"BelongsToOne\",\n with: parentId,\n onUpdate: \"CASCADE\",\n onDelete: \"CASCADE\",\n desc: parent.entity.title,\n },\n ]\n : []),\n {\n name: \"created_at\",\n type: \"timestamp\",\n desc: \"등록일시\",\n dbDefault: \"CURRENT_TIMESTAMP\",\n },\n ],\n indexes: [...(options.indexes ?? [])],\n subsets: options.subsets ?? {\n ...(parentId\n ? {}\n : {\n A: [\"id\", \"created_at\"],\n }),\n },\n enums: options.enums ?? {\n ...(parentId\n ? {}\n : {\n [`${names.capital}OrderBy`]: {\n \"id-desc\": \"ID최신순\",\n },\n [`${names.capital}SearchField`]: { id: \"ID\" },\n }),\n },\n }).trim(),\n importKeys: [],\n };\n }\n}\n","import inflection from \"inflection\";\nimport _ from \"lodash\";\nimport { z } from \"zod\";\nimport { RenderingNode, TemplateKey, TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { isEnumProp, isRelationProp, RelationProp } from \"../types/types\";\nimport { RenderedTemplate } from \"../syncer/syncer\";\nimport { Template } from \"./base-template\";\n\nexport class Template__view_list extends Template {\n constructor() {\n super(\"view_list\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n return {\n target: \"web/src/pages/admin\",\n path: `${names.fsPlural}/index.tsx`,\n };\n }\n\n wrapTc(\n body: string,\n key: string,\n collapsing: boolean = true,\n className: string = \"\"\n ) {\n return `<Table.Cell key=\"${key}\"${collapsing ? \" collapsing\" : \"\"}${\n className ? ` className={\\`${className}\\`}` : \"\"\n }>${body}</Table.Cell>`;\n }\n\n renderColumn(\n entityId: string,\n col: RenderingNode,\n names: EntityNamesRecord,\n parentObj: string = \"row\",\n withoutName: boolean = false\n ): string {\n const colName = withoutName ? `${parentObj}` : `${parentObj}.${col.name}`;\n\n switch (col.renderType) {\n case \"string-plain\":\n case \"string-date\":\n case \"number-id\":\n return `<>{${colName}}</>`;\n case \"number-fk_id\":\n const relPropFk = getRelationPropFromColName(\n entityId,\n col.name.replace(\"_id\", \"\")\n );\n return `<>${relPropFk.with}#{${colName}}</>`;\n case \"string-image\":\n return `<>{${\n col.nullable ? `${colName} && ` : \"\"\n }<img src={${colName}} />}</>`;\n case \"string-datetime\":\n if (col.nullable) {\n return `<span className=\"text-tiny\">{${colName} === null ? '-' : dateF(${colName})}</span>`;\n } else {\n return `<span className=\"text-tiny\">{dateF(${colName})}</span>`;\n }\n case \"boolean\":\n return `<>{${colName} ? <Label color='green' circular>O</Label> : <Label color='grey' circular>X</Label> }</>`;\n case \"enums\":\n const { id: enumId } = getEnumInfoFromColName(entityId, col.name);\n return `<>{${\n col.nullable ? `${colName} && ` : \"\"\n }${enumId}Label[${colName}]}</>`;\n case \"array-images\":\n return `<>{ ${colName}.map(r => ${\n col.nullable ? `r && ` : \"\"\n }<img src={r} />) }</>`;\n case \"number-plain\":\n return `<>{${col.nullable ? `${colName} && ` : \"\"}numF(${colName})}</>`;\n case \"object\":\n return `<>{/* object ${colName} */}</>`;\n case \"object-pick\":\n const pickedChild = col.children!.find(\n (child) => child.name === col.config?.picked\n );\n if (!pickedChild) {\n throw new Error(`object-pick 선택 실패 (오브젝트: ${col.name})`);\n }\n return this.renderColumn(\n entityId,\n pickedChild,\n names,\n `${colName}${col.nullable ? \"?\" : \"\"}`\n );\n case \"array\":\n return `<>{ /* array ${colName} */ }</>`;\n default:\n throw new Error(`렌더 불가 컬럼 ${col.renderType}`);\n }\n }\n\n renderColumnImport(\n entityId: string,\n col: RenderingNode,\n names: EntityNamesRecord\n ): (string | null)[] {\n if (col.renderType === \"enums\") {\n const { id: enumId } = getEnumInfoFromColName(names.capital, col.name);\n return [\n `import { ${enumId}Label } from 'src/services/sonamu.generated';`,\n ];\n } else if (col.renderType === \"object\") {\n try {\n const relProp = getRelationPropFromColName(entityId, col.name);\n const result = col.children!.map((child) => {\n entityId = relProp.with;\n names = EntityManager.getNamesFromId(relProp.with);\n return this.renderColumnImport(entityId, child, names);\n });\n return _.flattenDeep(result);\n } catch {\n return [null];\n }\n } else if (col.renderType === \"array\") {\n return this.renderColumnImport(entityId, col.element!, names);\n }\n\n return [null];\n }\n\n renderFilterImport(\n entityId: string,\n col: RenderingNode,\n names: EntityNamesRecord\n ) {\n if (col.name === \"search\") {\n return `import { ${names.capital}SearchInput } from \"src/components/${names.fs}/${names.capital}SearchInput\";`;\n } else if (col.renderType === \"enums\") {\n if (col.name === \"orderBy\") {\n const componentId = `${names.capital}${inflection.camelize(col.name)}Select`;\n return `import { ${componentId} } from \"src/components/${names.fs}/${componentId}\";`;\n } else {\n try {\n const { id, targetEntityNames: targetMDNames } =\n getEnumInfoFromColName(entityId, col.name);\n const componentId = `${id}Select`;\n return `import { ${componentId} } from \"src/components/${targetMDNames.fs}/${componentId}\";`;\n } catch {\n return \"\";\n }\n }\n } else if (col.renderType === \"number-fk_id\") {\n try {\n const relProp = getRelationPropFromColName(\n entityId,\n col.name.replace(\"_id\", \"\")\n );\n const targetNames = EntityManager.getNamesFromId(relProp.with);\n const componentId = `${relProp.with}IdAsyncSelect`;\n return `import { ${componentId} } from \"src/components/${targetNames.fs}/${componentId}\";`;\n } catch {\n return \"\";\n }\n } else {\n throw new Error(\n `렌더 불가능한 필터 임포트 ${col.name} ${col.renderType}`\n );\n }\n }\n\n renderFilter(entityId: string, col: RenderingNode, names: EntityNamesRecord) {\n if (col.name === \"search\") {\n return \"\";\n }\n\n const isClearable = col.optional === true && col.name !== \"orderBy\";\n let componentId: string;\n if (col.renderType === \"enums\") {\n if (col.name === \"orderBy\") {\n componentId = `${names.capital}${inflection.camelize(col.name)}Select`;\n } else {\n try {\n const { id } = getEnumInfoFromColName(entityId, col.name);\n componentId = `${id}Select`;\n } catch {\n return \"\";\n }\n }\n return `<${componentId} {...register('${col.name}')} ${\n isClearable ? \"clearable\" : \"\"\n } />`;\n } else if (col.renderType === \"number-fk_id\") {\n try {\n const relProp = getRelationPropFromColName(\n entityId,\n col.name.replace(\"_id\", \"\")\n );\n componentId = `${relProp.with}IdAsyncSelect`;\n return `<${componentId} {...register('${col.name}')} ${\n isClearable ? \"clearable\" : \"\"\n } subset=\"A\" />`;\n } catch {\n return \"\";\n }\n } else {\n throw new Error(\n `렌더 불가능한 필터 임포트 ${col.name} ${col.renderType}`\n );\n }\n }\n\n getDefault(columns: RenderingNode[]): {\n orderBy: string;\n search: string;\n } {\n const def = {\n orderBy: \"id-desc\",\n search: \"title\",\n };\n const orderByZodType = columns.find(\n (col) => col.name === \"orderBy\"\n )?.zodType;\n if (orderByZodType && orderByZodType instanceof z.ZodEnum) {\n def.orderBy = Object.keys(orderByZodType.Enum)[0];\n }\n const searchZodType = columns.find((col) => col.name === \"search\")?.zodType;\n if (searchZodType && searchZodType instanceof z.ZodEnum) {\n def.search = Object.keys(searchZodType.Enum)[0];\n }\n return def;\n }\n\n render(\n { entityId }: TemplateOptions[\"view_list\"],\n columnsNode: RenderingNode,\n listParamsNode: RenderingNode\n ) {\n const names = EntityManager.getNamesFromId(entityId);\n const entity = EntityManager.get(entityId);\n\n // 실제 리스트 컬럼\n const columns = (columnsNode.children as RenderingNode[])\n .filter((col) => col.name !== \"id\")\n .map((col) => {\n const propCandidate = entity.props.find((p) => p.name === col.name);\n return {\n name: col.name,\n label: propCandidate?.desc ?? col.label,\n tc: `(row) => ${this.renderColumn(entityId, col, names)}`,\n };\n });\n\n // 필터 컬럼\n const filterColumns = (listParamsNode.children as RenderingNode[])\n .filter(\n (col) =>\n col.name !== \"id\" &&\n col.name !== \"queryMode\" &&\n ([\"enums\", \"number-id\"].includes(col.renderType) ||\n col.name.endsWith(\"_id\"))\n )\n // orderBy가 가장 뒤로 오게 순서 조정\n .sort((a) => {\n return a.name == \"orderBy\" ? 1 : -1;\n });\n\n // 필터 컬럼을 프리 템플릿으로 설정\n const preTemplates: RenderedTemplate[\"preTemplates\"] = [];\n for (let col of filterColumns) {\n let key: TemplateKey;\n let targetEntityId = entityId;\n let enumId: string | undefined;\n\n if (col.renderType === \"enums\") {\n if (col.name === \"search\") {\n key = \"view_enums_dropdown\";\n enumId = `${names.capital}SearchField`;\n targetEntityId = names.capital;\n } else {\n key = \"view_enums_select\";\n try {\n const { targetEntityNames, id } = getEnumInfoFromColName(\n entityId,\n col.name\n );\n targetEntityId = targetEntityNames.capital;\n enumId = id;\n } catch {\n continue;\n }\n }\n } else {\n key = \"view_id_async_select\";\n try {\n const relProp = getRelationPropFromColName(\n entityId,\n col.name.replace(\"_id\", \"\")\n );\n targetEntityId = relProp.with;\n } catch {\n continue;\n }\n }\n\n preTemplates.push({\n key,\n options: {\n entityId: targetEntityId,\n enumId,\n },\n });\n }\n\n // 리스트 컬럼\n const columnImports = _.uniq(\n columnsNode\n .children!.map((col) => {\n return this.renderColumnImport(entityId, col, names);\n })\n .flat()\n .filter((col) => col !== null)\n ).join(\"\\n\");\n\n // SearchInput\n preTemplates!.push({\n key: \"view_search_input\",\n options: {\n entityId,\n },\n });\n\n // 디폴트 파라미터\n const def = this.getDefault(filterColumns);\n\n return {\n ...this.getTargetAndPath(names),\n body: `\nimport React from 'react';\nimport { Link } from 'react-router-dom';\nimport {\n Breadcrumb,\n Checkbox,\n Pagination,\n Segment,\n Table,\n TableRow,\n Message,\n Transition,\n Button,\n Label,\n} from 'semantic-ui-react';\nimport classNames from 'classnames';\nimport { DateTime } from \"luxon\";\nimport { DelButton, EditButton, AppBreadcrumbs, AddButton, useSelection, useListParams, SonamuCol, numF, dateF, datetimeF } from '@sonamu-kit/react-sui';\n\nimport { ${names.capital}SubsetA } from \"src/services/sonamu.generated\";\nimport { ${names.capital}Service } from 'src/services/${names.fs}/${\n names.fs\n }.service';\nimport { ${names.capital}ListParams } from 'src/services/${names.fs}/${\n names.fs\n }.types';\n${columnImports}\n${filterColumns\n .map((col) => {\n return this.renderFilterImport(entityId, col, names);\n })\n .join(\"\\n\")}\n\ntype ${names.capital}ListProps = {};\nexport default function ${names.capital}List({}: ${names.capital}ListProps) {\n // 리스트 필터\n const { listParams, register } = useListParams(${names.capital}ListParams, {\n num: 12,\n page: 1,\n orderBy: '${def.orderBy}',\n search: '${def.search}',\n });\n\n // 리스트 쿼리\n const { data, mutate, error, isLoading } = ${names.capital}Service.use${\n names.capitalPlural\n }('A', listParams);\n const { rows, total } = data ?? {};\n\n // 삭제\n const confirmDel = (ids: number[]) => {\n const answer = confirm('삭제하시겠습니까?');\n if (!answer) {\n return;\n }\n\n ${names.capital}Service.del(ids).then(() => {\n mutate();\n });\n };\n\n // 일괄 삭제\n const confirmDelSelected = () => {\n const answer = confirm(\\`\\${selectedKeys.length}건을 일괄 삭제하시겠습니까?\\`);\n if (!answer) {\n return;\n }\n\n ${names.capital}Service.del(selectedKeys).then(() => {\n mutate();\n });\n };\n\n // 현재 경로와 타이틀\n const PAGE = {\n route: '/admin/${names.fsPlural}',\n title: '${entity.title ?? names.capital}',\n };\n\n // 선택\n const {\n getSelected,\n isAllSelected,\n selectedKeys,\n toggle,\n selectAll,\n deselectAll,\n handleCheckboxClick,\n } = useSelection((rows ?? []).map((row) => row.id));\n\n // 컬럼\n const columns:SonamuCol<${names.capital}SubsetA>[] = [${columns\n .map((col) => {\n return [\n `{ label: \"${col.label}\",`,\n `tc: ${col.tc}, `,\n `collapsing: ${[\"Title\", \"Name\"].includes(col.label) === false}, }`,\n ].join(\"\\n\");\n })\n .join(\",\\n\")}];\n\n return (\n <div className=\"list ${names.fsPlural}-index\">\n <div className=\"top-nav\">\n <div className=\"header-row\">\n <div className=\"header\">{PAGE.title}</div>\n <AppBreadcrumbs>\n <Breadcrumb.Section active>{PAGE.title}</Breadcrumb.Section>\n </AppBreadcrumbs>\n <${names.capital}SearchInput\n input={register('keyword')}\n dropdown={register('search')}\n />\n </div>\n <div className=\"filters-row\">\n ${filterColumns\n .map((col) => {\n return this.renderFilter(entityId, col, names);\n })\n .join(\"&nbsp;\\n\")}\n </div>\n </div>\n\n <Segment basic padded className=\"contents-segment\" loading={isLoading}>\n <div className=\"buttons-row\">\n <div className={classNames('count', { hidden: isLoading })}>\n {total} 건\n </div>\n <div className=\"buttons\">\n <AddButton currentRoute={PAGE.route} icon=\"write\" label=\"추가\" />\n </div>\n </div>\n\n <Table\n celled\n compact\n selectable\n className={classNames({ hidden: total === undefined || total === 0 })}\n >\n <Table.Header>\n <TableRow>\n <Table.HeaderCell collapsing>\n <Checkbox\n label=\"ID\"\n checked={isAllSelected}\n onChange={isAllSelected ? deselectAll : selectAll}\n />\n </Table.HeaderCell>\n {\n /* Header */\n columns.map((col, index) => col.th ?? <Table.HeaderCell key={index} collapsing={col.collapsing}>{ col.label }</Table.HeaderCell>)\n }\n <Table.HeaderCell>관리</Table.HeaderCell>\n </TableRow>\n </Table.Header>\n <Table.Body>\n {rows &&\n rows.map((row, rowIndex) => (\n <Table.Row key={row.id}>\n <Table.Cell>\n <Checkbox\n label={row.id}\n checked={getSelected(row.id)}\n onChange={() => toggle(row.id)}\n onClick={(e) =>\n handleCheckboxClick(e, rowIndex)\n }\n />\n </Table.Cell>\n {\n /* Body */\n columns.map((col, colIndex) => (\n <Table.Cell key={colIndex} collapsing={col.collapsing} className={col.className}>\n {col.tc(row, rowIndex)}\n </Table.Cell>\n ))\n }\n <Table.Cell collapsing>\n <EditButton\n as={Link}\n to={\\`\\${PAGE.route}/form?id=\\${row.id}\\`}\n state={{ from: PAGE.route }}\n />\n <DelButton onClick={() => confirmDel([row.id])} />\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n <div\n className={classNames('pagination-row', {\n hidden: (total ?? 0) === 0,\n })}\n >\n <Pagination\n totalPages={Math.ceil((total ?? 0) / (listParams.num ?? 24))}\n {...register('page')}\n />\n </div>\n </Segment>\n\n <div className=\"fixed-menu\">\n <Transition\n visible={selectedKeys.length > 0}\n animation=\"slide left\"\n duration={500}\n >\n <Message size=\"small\" color=\"violet\" className=\"text-center\">\n <span className=\"px-4\">{selectedKeys.length}개 선택됨</span>\n <Button size=\"tiny\" color=\"violet\" onClick={() => deselectAll()}>\n 선택 해제\n </Button>\n <Button size=\"tiny\" color=\"red\" onClick={confirmDelSelected}>\n 일괄 삭제\n </Button>\n </Message>\n </Transition>\n </div>\n </div>\n );\n}\n `.trim(),\n importKeys: [],\n preTemplates,\n };\n }\n}\n\nexport function getEnumInfoFromColName(\n entityId: string,\n colName: string\n): {\n id: string;\n targetEntityNames: EntityNamesRecord;\n targetEntityId: string;\n title: string;\n} {\n const baseEntity = EntityManager.get(entityId);\n const prop = baseEntity.props.find((p) => p.name === colName);\n if (prop && isEnumProp(prop)) {\n return {\n id: prop.id,\n targetEntityId: entityId,\n targetEntityNames: EntityManager.getNamesFromId(entityId),\n title: prop.desc ?? prop.id,\n };\n } else {\n const idCandidate = inflection.camelize(\n inflection.underscore(entityId) + \"_\" + inflection.underscore(colName),\n false\n );\n try {\n const targetEntityNames = EntityManager.getNamesFromId(entityId);\n return {\n id: idCandidate,\n targetEntityId: entityId,\n targetEntityNames: targetEntityNames,\n title: idCandidate,\n };\n } catch {}\n throw new Error(`찾을 수 없는 EnumProp ${colName}`);\n }\n}\n\nexport function getRelationPropFromColName(\n entityId: string,\n colName: string\n): RelationProp {\n const baseEntity = EntityManager.get(entityId);\n const relProp = baseEntity.props.find((prop) => prop.name === colName);\n if (isRelationProp(relProp)) {\n const relEntity = EntityManager.get(relProp.with);\n if (relEntity.parentId !== undefined) {\n throw new Error(\"Only parent entities can be used as relation props\");\n }\n return relProp;\n } else {\n throw new Error(`찾을 수 없는 Relation ${colName}`);\n }\n}\n","import { RenderingNode, TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\nimport { Template__view_list } from \"./view_list.template\";\nimport { Sonamu } from \"../api\";\n\nexport class Template__model extends Template {\n constructor() {\n super(\"model\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n const { dir } = Sonamu.config.api;\n\n return {\n target: `${dir}/src/application`,\n path: `${names.fs}/${names.fs}.model.ts`,\n };\n }\n\n render(\n { entityId }: TemplateOptions[\"model\"],\n _columnsNode: RenderingNode,\n listParamsNode: RenderingNode\n ) {\n const names = EntityManager.getNamesFromId(entityId);\n const entity = EntityManager.get(entityId);\n\n const vlTpl = new Template__view_list();\n if (listParamsNode?.children === undefined) {\n throw new Error(`listParamsNode가 없습니다. ${entityId}`);\n }\n const def = vlTpl.getDefault(listParamsNode.children);\n\n return {\n ...this.getTargetAndPath(names),\n body: `\nimport { BaseModelClass, ListResult, asArray, NotFoundException, BadRequestException, api } from 'sonamu';\nimport {\n ${entityId}SubsetKey,\n ${entityId}SubsetMapping,\n} from \"../sonamu.generated\";\nimport {\n ${names.camel}SubsetQueries,\n} from \"../sonamu.generated.sso\";\nimport { ${entityId}ListParams, ${entityId}SaveParams } from \"./${names.fs}.types\";\n\n/*\n ${entityId} Model\n*/\nclass ${entityId}ModelClass extends BaseModelClass {\n modelName = \"${entityId}\";\n\n @api({ httpMethod: \"GET\", clients: [\"axios\", \"swr\"], resourceName: \"${entityId}\" })\n async findById<T extends ${entityId}SubsetKey>(\n subset: T,\n id: number\n ): Promise<${entityId}SubsetMapping[T]> {\n const { rows } = await this.findMany(subset, {\n id,\n num: 1,\n page: 1,\n });\n if (rows.length == 0) {\n throw new NotFoundException(\\`존재하지 않는 ${names.capital} ID \\${id}\\`);\n }\n\n return rows[0];\n }\n\n async findOne<T extends ${entityId}SubsetKey>(\n subset: T,\n listParams: ${entityId}ListParams\n ): Promise<${entityId}SubsetMapping[T] | null> {\n const { rows } = await this.findMany(subset, {\n ...listParams,\n num: 1,\n page: 1,\n });\n\n return rows[0] ?? null;\n }\n\n @api({ httpMethod: \"GET\", clients: [\"axios\", \"swr\"], resourceName: \"${names.capitalPlural}\" })\n async findMany<T extends ${entityId}SubsetKey>(\n subset: T,\n params: ${entityId}ListParams = {}\n ): Promise<ListResult<${entityId}SubsetMapping[T]>> {\n // params with defaults\n params = {\n num: 24,\n page: 1,\n search: \"${def.search}\",\n orderBy: \"${def.orderBy}\",\n ...params,\n };\n\n // build queries\n let { rows, total } = await this.runSubsetQuery({\n subset,\n params,\n subsetQuery: ${names.camel}SubsetQueries[subset],\n build: ({ qb }) => {\n // id\n if (params.id) {\n qb.whereIn(\"${entity.table}.id\", asArray(params.id));\n }\n\n // search-keyword\n if (params.search && params.keyword && params.keyword.length > 0) {\n if (params.search === \"id\") {\n qb.where(\"${entity.table}.id\", params.keyword);\n // } else if (params.search === \"field\") {\n // qb.where(\"${entity.table}.field\", \"like\", \\`%\\${params.keyword}%\\`);\n } else {\n throw new BadRequestException(\n \\`구현되지 않은 검색 필드 \\${params.search}\\`\n );\n }\n }\n\n // orderBy\n if (params.orderBy) {\n // default orderBy\n const [orderByField, orderByDirec] = params.orderBy.split(\"-\");\n qb.orderBy(\"${entity.table}.\" + orderByField, orderByDirec);\n }\n\n return qb;\n },\n debug: false,\n });\n\n return {\n rows,\n total,\n };\n }\n\n @api({ httpMethod: \"POST\" })\n async save(\n spa: ${entityId}SaveParams[]\n ): Promise<number[]> {\n const wdb = this.getDB(\"w\");\n const ub = this.getUpsertBuilder();\n\n // register\n spa.map((sp) => {\n ub.register(\"${entity.table}\", sp);\n });\n\n // transaction\n return wdb.transaction(async (trx) => {\n const ids = await ub.upsert(trx, \"${entity.table}\");\n\n return ids;\n });\n }\n\n @api({ httpMethod: \"POST\", guards: [ \"admin\" ] })\n async del(ids: number[]): Promise<number> {\n const wdb = this.getDB(\"w\");\n\n // transaction\n await wdb.transaction(async (trx) => {\n return trx(\"${entity.table}\").whereIn(\"${entity.table}.id\", ids).delete();\n });\n\n return ids.length;\n }\n}\n\nexport const ${entityId}Model = new ${entityId}ModelClass();\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\nimport { Sonamu } from \"../api\";\n\nexport class Template__model_test extends Template {\n constructor() {\n super(\"model_test\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n const { dir } = Sonamu.config.api;\n\n return {\n target: `${dir}/src/application`,\n path: `${names.fs}/${names.fs}.model.test.ts`,\n };\n }\n\n render({ entityId }: TemplateOptions[\"model_test\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n\n return {\n ...this.getTargetAndPath(names),\n body: `\nimport { describe, test, expect } from \"vitest\";\nimport { bootstrap } from '../../testing/bootstrap';\n\nbootstrap([]);\ndescribe.skip(\"${entityId}ModelTest\", () => {\n test(\"Query\", async () => {\n expect(true).toBe(true);\n });\n});\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import inflection from \"inflection\";\nimport _ from \"lodash\";\nimport { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { ApiParamType, ApiParam } from \"../types/types\";\nimport {\n apiParamTypeToTsType,\n apiParamToTsCode,\n unwrapPromiseOnce,\n} from \"../api/code-converters\";\nimport { ExtendedApi } from \"../api/decorators\";\nimport { Template } from \"./base-template\";\nimport { Sonamu } from \"../api/sonamu\";\n\nexport class Template__service extends Template {\n constructor() {\n super(\"service\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n return {\n target: \":target/src/services\",\n path: `${names.fs}/${names.fs}.service.ts`,\n };\n }\n\n render({ entityId }: TemplateOptions[\"service\"], apis: ExtendedApi[]) {\n const names = EntityManager.getNamesFromId(entityId);\n\n // 서비스 TypeSource\n const { lines, importKeys } = this.getTypeSource(apis);\n\n // AxiosProgressEvent 있는지 확인\n const hasAxiosProgressEvent = apis.find((api) =>\n (api.options.clients ?? []).includes(\"axios-multipart\")\n );\n\n return {\n ...this.getTargetAndPath(names),\n body: lines.join(\"\\n\"),\n importKeys: importKeys.filter(\n (key) => [\"ListResult\"].includes(key) === false\n ),\n customHeaders: [\n `import { z } from 'zod';`,\n `import qs from \"qs\";`,\n `import useSWR, { SWRResponse } from \"swr\";`,\n `import { fetch, ListResult, SWRError, SwrOptions, handleConditional, swrPostFetcher } from '../sonamu.shared';`,\n ...(hasAxiosProgressEvent\n ? [`import { AxiosProgressEvent } from 'axios';`]\n : []),\n ],\n };\n }\n\n getTypeSource(apis: ExtendedApi[]): {\n lines: string[];\n importKeys: string[];\n } {\n const importKeys: string[] = [];\n\n // 제네릭에서 선언한 타입, importKeys에서 제외 필요\n let typeParamNames: string[] = [];\n\n const groups = _.groupBy(apis, (api) => api.modelName);\n const body = Object.keys(groups)\n .map((modelName) => {\n const methods = groups[modelName];\n const methodCodes = methods\n .map((api) => {\n // 컨텍스트 제외된 파라미터 리스트\n const paramsWithoutContext = api.parameters.filter(\n (param) =>\n !ApiParamType.isContext(param.type) &&\n !ApiParamType.isRefKnex(param.type)\n );\n\n // 파라미터 타입 정의\n const typeParamsDef = api.typeParameters\n .map((typeParam) => {\n return apiParamTypeToTsType(typeParam, importKeys);\n })\n .join(\", \");\n typeParamNames = typeParamNames.concat(\n api.typeParameters.map((typeParam) => typeParam.id)\n );\n\n // 파라미터 정의\n const paramsDef = apiParamToTsCode(\n paramsWithoutContext,\n importKeys\n );\n\n // 리턴 타입 정의\n const returnTypeDef = apiParamTypeToTsType(\n unwrapPromiseOnce(api.returnType),\n importKeys\n );\n\n // 페이로드 데이터 정의\n const payloadDef = `{ ${paramsWithoutContext\n .map((param) => param.name)\n .join(\", \")} }`;\n\n return _.sortBy(api.options.clients, (client) =>\n client === \"swr\" ? 0 : 1\n )\n .map((client) => {\n const apiBaseUrl = `${Sonamu.config.route.prefix}${api.path}`;\n switch (client) {\n case \"axios\":\n return this.renderAxios(\n api,\n apiBaseUrl,\n typeParamsDef,\n paramsDef,\n returnTypeDef,\n payloadDef\n );\n case \"axios-multipart\":\n return this.renderAxiosMultipart(\n api,\n apiBaseUrl,\n typeParamsDef,\n paramsDef,\n returnTypeDef,\n paramsWithoutContext\n );\n case \"swr\":\n return this.renderSwr(\n api,\n apiBaseUrl,\n typeParamsDef,\n paramsDef,\n returnTypeDef,\n payloadDef\n );\n case \"window-fetch\":\n return this.renderWindowFetch(\n api,\n apiBaseUrl,\n typeParamsDef,\n paramsDef,\n payloadDef\n );\n case \"socketio\":\n default:\n return `// Not supported ${inflection.camelize(client, true)} yet.`;\n }\n })\n .join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n return `export namespace ${modelName.replace(/Model$/, \"Service\")} {\n${methodCodes}\n}`;\n })\n .join(\"\\n\\n\");\n\n return {\n lines: [body],\n importKeys: _.difference(_.uniq(importKeys), typeParamNames),\n };\n }\n\n renderAxios(\n api: ExtendedApi,\n apiBaseUrl: string,\n typeParamsDef: string,\n paramsDef: string,\n returnTypeDef: string,\n payloadDef: string\n ) {\n const methodNameAxios = api.options.resourceName\n ? \"get\" + inflection.camelize(api.options.resourceName)\n : api.methodName;\n\n if (api.options.httpMethod === \"GET\") {\n return `\nexport async function ${methodNameAxios}${typeParamsDef}(${paramsDef}): Promise<${returnTypeDef}> {\n return fetch({\n method: \"GET\",\n url: \\`${apiBaseUrl}?\\${qs.stringify(${payloadDef})}\\`,\n });\n}\n `.trim();\n } else {\n return `\nexport async function ${methodNameAxios}${typeParamsDef}(${paramsDef}): Promise<${returnTypeDef}> {\n return fetch({\n method: '${api.options.httpMethod}',\n url: \\`${apiBaseUrl}\\`,\n data: ${payloadDef},\n });\n}\n `.trim();\n }\n }\n\n renderAxiosMultipart(\n api: ExtendedApi,\n apiBaseUrl: string,\n typeParamsDef: string,\n paramsDef: string,\n returnTypeDef: string,\n paramsWithoutContext: ApiParam[]\n ) {\n const formDataDef = [\n 'formData.append(\"file\", file);',\n ...paramsWithoutContext.map(\n (param) => `formData.append('${param.name}', String(${param.name}));`\n ),\n ].join(\"\\n\");\n\n const paramsDefComma = paramsDef !== \"\" ? \", \" : \"\";\n return `\nexport async function ${api.methodName}${typeParamsDef}(\n ${paramsDef}${paramsDefComma}\n file: File,\n onUploadProgress?: (pe:AxiosProgressEvent) => void\n ): Promise<${returnTypeDef}> {\n const formData = new FormData();\n ${formDataDef}\n return fetch({\n method: 'POST',\n url: \\`${apiBaseUrl}\\`,\n headers: {\n \"Content-Type\": \"multipart/form-data\",\n },\n onUploadProgress,\n data: formData,\n });\n }\n `.trim();\n }\n\n renderSwr(\n api: ExtendedApi,\n apiBaseUrl: string,\n typeParamsDef: string,\n paramsDef: string,\n returnTypeDef: string,\n payloadDef: string\n ) {\n const methodNameSwr = api.options.resourceName\n ? \"use\" + inflection.camelize(api.options.resourceName)\n : \"use\" + inflection.camelize(api.methodName);\n return ` export function ${inflection.camelize(\n methodNameSwr,\n true\n )}${typeParamsDef}(${[paramsDef, \"swrOptions?: SwrOptions\"]\n .filter((p) => p !== \"\")\n .join(\",\")}, ): SWRResponse<${returnTypeDef}, SWRError> {\n return useSWR(handleConditional([\n \\`${apiBaseUrl}\\`,\n ${payloadDef},\n ], swrOptions?.conditional)${\n api.options.httpMethod === \"POST\" ? \", swrPostFetcher\" : \"\"\n });\n }`;\n }\n\n renderWindowFetch(\n api: ExtendedApi,\n apiBaseUrl: string,\n typeParamsDef: string,\n paramsDef: string,\n payloadDef: string\n ) {\n return `\nexport async function ${api.methodName}${typeParamsDef}(${paramsDef}): Promise<Response> {\n return window.fetch(\\`${apiBaseUrl}?\\${qs.stringify(${payloadDef})}\\`);\n}\n `.trim();\n }\n}\n","import inflection from \"inflection\";\nimport { z } from \"zod\";\nimport { RenderingNode, TemplateKey, TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { RenderedTemplate } from \"../syncer/syncer\";\nimport { Template } from \"./base-template\";\nimport {\n getEnumInfoFromColName,\n getRelationPropFromColName,\n} from \"./view_list.template\";\nimport _ from \"lodash\";\n\nexport class Template__view_form extends Template {\n constructor() {\n super(\"view_form\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n return {\n target: \"web/src/pages/admin\",\n path: `${names.fsPlural}/form.tsx`,\n };\n }\n\n wrapFC(body: string, label?: string): string {\n return [\n `<Form.Field>${label ? `\\n <label>${label}</label>` : \"\"}`,\n body,\n `</Form.Field>`,\n ].join(\"\\n\");\n }\n wrapFG(body: string, label?: string): string {\n return [\n `<Form.Group widths=\"equal\">`,\n this.wrapFC(body, label),\n `</Form.Group>`,\n ].join(\"\\n\");\n }\n\n renderColumnImport(entityId: string, col: RenderingNode) {\n if (col.renderType === \"enums\") {\n const { id, targetEntityNames } = getEnumInfoFromColName(\n entityId,\n col.name\n );\n const componentId = `${id}Select`;\n return `import { ${componentId} } from \"src/components/${targetEntityNames.fs}/${componentId}\";`;\n } else if (col.renderType === \"number-fk_id\") {\n try {\n const relProp = getRelationPropFromColName(\n entityId,\n col.name.replace(\"_id\", \"\")\n );\n const targetNames = EntityManager.getNamesFromId(relProp.with);\n const componentId = `${relProp.with}IdAsyncSelect`;\n return `import { ${componentId} } from \"src/components/${targetNames.fs}/${componentId}\";`;\n } catch {\n return \"\";\n }\n } else {\n throw new Error(`렌더 불가능한 임포트 ${col.name} ${col.renderType}`);\n }\n }\n\n renderColumn(\n entityId: string,\n col: RenderingNode,\n names: EntityNamesRecord,\n parent: string = \"\"\n ): string {\n let regExpr: string = \"\";\n regExpr = `{...register(\\`${parent}${col.name}\\`)}`;\n\n switch (col.renderType) {\n case \"string-plain\":\n if (\n col.zodType instanceof z.ZodString &&\n (col.zodType.maxLength ?? 0) <= 512\n ) {\n return `<Input placeholder=\"${col.label}\" ${regExpr} />`;\n } else {\n return `<TextArea rows={8} placeholder=\"${col.label}\" ${regExpr} />`;\n }\n case \"string-datetime\":\n return `<SQLDateTimeInput ${regExpr} />`;\n case \"string-date\":\n return `<SQLDateInput ${regExpr} />`;\n case \"number-id\":\n return `<input type=\"hidden\" ${regExpr} />`;\n case \"number-plain\":\n return `<NumberInput placeholder=\"${col.label}\" ${regExpr} />`;\n case \"boolean\":\n return `<BooleanToggle ${regExpr} />`;\n case \"string-image\":\n return `<ImageUploader multiple={false} ${regExpr} />`;\n case \"array-images\":\n return `<ImageUploader multiple={true} ${regExpr} maxSize={5} />`;\n case \"enums\":\n try {\n let enumId: string;\n if (col.name === \"orderBy\") {\n enumId = `${names.capital}${inflection.camelize(col.name)}Select`;\n } else {\n const { id } = getEnumInfoFromColName(entityId, col.name);\n enumId = `${id}Select`;\n }\n return `<${enumId} ${regExpr} ${\n col.optional || col.nullable ? \"clearable\" : \"\"\n } textPrefix=\"\" />`;\n } catch {\n return `<>찾을 수 없는 Enum ${col.name}</>`;\n }\n case \"number-fk_id\":\n try {\n const relProp = getRelationPropFromColName(\n entityId,\n col.name.replace(\"_id\", \"\")\n );\n const fkId = `${relProp.with}IdAsyncSelect`;\n return `<${fkId} {...register('${col.name}')} ${\n col.optional || col.nullable ? \"clearable\" : \"\"\n } subset=\"A\" />`;\n } catch {\n return `<Input ${regExpr} />`;\n }\n case \"array\":\n return `<>${col.name} array</>`;\n case \"object\":\n return `<>${col.name} object</>`;\n default:\n throw new Error(\n `대응 불가능한 렌더 타입 ${col.renderType} on ${col.name}`\n );\n }\n }\n\n resolveDefaultValue(columns: RenderingNode[]): object {\n return columns.reduce(\n (result, col) => {\n if (col.optional) {\n return result;\n }\n\n let value: unknown;\n if (col.nullable === true) {\n value = null;\n } else if (col.zodType instanceof z.ZodNumber) {\n value = 0;\n } else if (col.zodType instanceof z.ZodEnum) {\n value = Object.keys(col.zodType.Enum)[0];\n } else if (col.zodType instanceof z.ZodBoolean) {\n value = false;\n } else if (col.zodType instanceof z.ZodString) {\n if (col.renderType === \"string-datetime\") {\n value = \"now()\";\n } else {\n value = \"\";\n }\n } else if (col.zodType instanceof z.ZodArray) {\n value = [];\n } else if (col.zodType instanceof z.ZodObject) {\n value = {};\n }\n\n result[col.name] = value;\n return result;\n },\n {} as { [key: string]: unknown }\n );\n }\n\n render(\n { entityId }: TemplateOptions[\"view_form\"],\n saveParamsNode: RenderingNode\n ) {\n const entity = EntityManager.get(entityId);\n const names = EntityManager.getNamesFromId(entityId);\n const columns = (saveParamsNode.children as RenderingNode[])\n .filter((col) => col.name !== \"id\")\n .map((col) => {\n const propCandidate = entity.props.find(\n (prop) => prop.name === col.name\n );\n col.label = propCandidate?.desc ?? col.label;\n return col;\n });\n\n const defaultValue = this.resolveDefaultValue(columns);\n\n // 프리 템플릿\n const preTemplates: RenderedTemplate[\"preTemplates\"] = (\n columns as RenderingNode[]\n )\n .filter((col) => {\n if (col.name === \"id\") {\n return false;\n } else if (col.name.endsWith(\"_id\") || col.renderType === \"number-id\") {\n try {\n getRelationPropFromColName(entityId, col.name.replace(\"_id\", \"\"));\n return true;\n } catch {\n return false;\n }\n } else if (col.renderType === \"enums\") {\n try {\n getEnumInfoFromColName(entityId, col.name);\n return true;\n } catch {\n return false;\n }\n }\n return false;\n })\n .map((col) => {\n let key: TemplateKey;\n let targetMdId = entityId;\n let enumId: string | undefined;\n if (col.renderType === \"enums\") {\n key = \"view_enums_select\";\n const { targetEntityNames: targetMDNames, id } =\n getEnumInfoFromColName(entityId, col.name);\n targetMdId = targetMDNames.capital;\n enumId = id;\n } else {\n key = \"view_id_async_select\";\n const relProp = getRelationPropFromColName(\n entityId,\n col.name.replace(\"_id\", \"\")\n );\n targetMdId = relProp.with;\n }\n\n return {\n key: key as TemplateKey,\n options: {\n entityId: targetMdId,\n node: col,\n enumId,\n },\n };\n })\n .filter((preTemplate) => {\n if (preTemplate.key === \"view_id_async_select\") {\n try {\n EntityManager.get(preTemplate.options.entityId);\n return true;\n } catch {\n return false;\n }\n }\n return true;\n });\n\n return {\n ...this.getTargetAndPath(names),\n body: `\nimport React, { useEffect, useState, Dispatch, SetStateAction, forwardRef, Ref, useImperativeHandle, useCallback } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport {\n Button,\n Checkbox,\n Form,\n Header,\n Input,\n Segment,\n TextArea,\n Label,\n} from 'semantic-ui-react';\nimport { DateTime } from \"luxon\";\n\nimport { BackLink, LinkInput, NumberInput, BooleanToggle, SQLDateTimeInput, SQLDateInput, useTypeForm, useGoBack } from \"@sonamu-kit/react-sui\";\nimport { defaultCatch } from 'src/services/sonamu.shared';\nimport { ImageUploader } from 'src/admin-common/ImageUploader';\nimport { useCommonModal } from \"src/admin-common/CommonModal\";\n\nimport { ${names.capital}SaveParams } from 'src/services/${names.fs}/${\n names.fs\n }.types';\nimport { ${names.capital}Service } from 'src/services/${names.fs}/${\n names.fs\n }.service';\nimport { ${names.capital}SubsetA } from 'src/services/sonamu.generated';\n${_.uniq(\n columns\n .filter((col) => [\"number-fk_id\", \"enums\"].includes(col.renderType))\n .map((col) => {\n return this.renderColumnImport(entityId, col);\n })\n).join(\"\\n\")}\n\nexport default function ${names.capitalPlural}FormPage() {\n // 라우팅 searchParams\n const [searchParams] = useSearchParams();\n const query = {\n id: searchParams.get('id') ?? undefined,\n };\n\n return <${\n names.capitalPlural\n }Form id={query?.id ? Number(query.id) : undefined} />;\n}\ntype ${names.capitalPlural}FormProps = {\n id?: number;\n mode?: 'page' | 'modal';\n};\nexport function ${names.capitalPlural}Form({ id, mode }: ${\n names.capitalPlural\n }FormProps) {\n // 편집시 기존 row\n const [row, setRow] = useState<${names.capital}SubsetA | undefined>();\n\n // ${names.capital}SaveParams 폼\n const { form, setForm, register } = useTypeForm(${\n names.capital\n }SaveParams, ${JSON.stringify(defaultValue).replace(\n /\"now\\(\\)\"/g,\n \"DateTime.local().toSQL()!.slice(0, 19)\"\n )});\n\n // 수정일 때 기존 row 콜\n useEffect(() => {\n if (id) {\n ${names.capital}Service.get${names.capital}('A', id).then((row) => {\n setRow(row);\n setForm({\n ...row,\n ${columns\n .filter((col) => col.renderType === \"number-fk_id\")\n .map((col) => {\n if (col.nullable) {\n return `${col.name}: row.${col.name.replace(\n \"_id\",\n \"?.id\"\n )} ?? null`;\n } else {\n return `${col.name}: row.${col.name.replace(\"_id\", \".id\")}`;\n }\n })\n .join(\",\\n\")}\n });\n });\n }\n }, [id]);\n\n // CommonModal\n const { doneModal, closeModal } = useCommonModal();\n\n // 저장\n const { goBack } = useGoBack();\n const handleSubmit = useCallback(() => {\n ${names.capital}Service.save([form]).then(([id]) => {\n if( mode === 'modal' ) {\n doneModal();\n } else {\n goBack('/admin/${names.fsPlural}');\n }\n }).catch(defaultCatch);\n }, [ form, mode, id ]);\n\n // 페이지\n const PAGE = {\n title: \\`${\n entity.title ?? names.capital\n }\\${id ? \\`#\\${id} 수정\\` : ' 등록'}\\`,\n }\n\n return (\n <div className=\"form\">\n <Segment padded basic>\n <Segment padded color=\"grey\">\n <div className=\"header-row\">\n <Header>\n {PAGE.title}\n </Header>\n { mode !== 'modal' && <div className=\"buttons\">\n <BackLink primary size=\"tiny\" to=\"/admin/${\n names.fsPlural\n }\" content=\"목록\" icon=\"list\" />\n </div>}\n </div>\n <Form>\n ${columns\n .map((col) => {\n if (col.name === \"created_at\") {\n return `{form.id && (${this.wrapFG(\n `<div className=\"p-8px\">{form.${col.name}}</div>`,\n \"등록일시\"\n )})}`;\n } else {\n return this.wrapFG(\n this.renderColumn(entityId, col, names),\n (() => {\n if (col.label.endsWith(\"Id\")) {\n try {\n const entity = EntityManager.get(\n col.label.replace(\"Id\", \"\")\n );\n return entity.title ?? col.label;\n } catch {\n return col.label;\n }\n }\n return col.label;\n })()\n );\n }\n })\n .join(\"\\n\")}\n <Segment basic textAlign=\"center\">\n <Button type=\"submit\" primary onClick={handleSubmit} content=\"저장\" icon=\"save\" />\n </Segment>\n </Form>\n </Segment>\n </Segment>\n </div>\n );\n};\n `.trim(),\n importKeys: [],\n preTemplates,\n };\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\n\nexport class Template__view_id_all_select extends Template {\n constructor() {\n super(\"view_id_all_select\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n return {\n target: \"web/src/components\",\n path: `${names.fs}/${names.capital}IdAllSelect.tsx`,\n };\n }\n\n render({ entityId }: TemplateOptions[\"view_id_all_select\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n\n return {\n ...this.getTargetAndPath(names),\n body: `\n/*\nview_id_all_select\n${JSON.stringify({\n key: this.key,\n options: entityId,\n})}\n*/\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\n\nexport class Template__view_id_async_select extends Template {\n constructor() {\n super(\"view_id_async_select\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n return {\n target: \"web/src/components\",\n path: `${names.fs}/${names.capital}IdAsyncSelect.tsx`,\n };\n }\n\n render({ entityId, textField }: TemplateOptions[\"view_id_async_select\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n\n const entity = EntityManager.get(entityId);\n if (!textField) {\n const pickedProp = entity.props.find((prop) =>\n [\"name\", \"title\"].includes(prop.name)\n );\n if (pickedProp) {\n textField = pickedProp.name;\n } else {\n const candidateProp = entity.props.find(\n (prop) => prop.type === \"string\"\n );\n if (candidateProp) {\n textField = candidateProp.name;\n } else {\n console.log(\"textField 찾을 수 없음\");\n }\n }\n }\n\n return {\n ...this.getTargetAndPath(names),\n body: `\nimport React, { useState, useEffect, SyntheticEvent } from \"react\";\nimport { DropdownProps, DropdownItemProps, DropdownOnSearchChangeData, Dropdown } from \"semantic-ui-react\";\nimport { ${names.capital}SubsetKey, ${\n names.capital\n }SubsetMapping } from \"src/services/sonamu.generated\";\nimport { ${names.capital}Service } from \"src/services/${names.fs}/${\n names.fs\n }.service\";\nimport { ${names.capital}ListParams } from \"src/services/${names.fs}/${\n names.fs\n }.types\";\n\nexport function ${names.capital}IdAsyncSelect<T extends ${\n names.capital\n }SubsetKey>(\n { subset, baseListParams, textField, valueField, ...props }: DropdownProps & {\n subset: T;\n baseListParams?: ${names.capital}ListParams;\n textField${textField ? \"?\" : \"\"}: keyof ${names.capital}SubsetMapping[T];\n valueField?: keyof ${names.capital}SubsetMapping[T];\n },\n) {\n const [options, setOptions] = useState<DropdownItemProps[]>([]);\n const [listParams, setListParams] = useState<${names.capital}ListParams>(\n baseListParams ?? {},\n );\n\n const { data, error } = ${names.capital}Service.use${\n names.capitalPlural\n }(subset, listParams);\n const { rows: ${names.camelPlural}, total } = data ?? {};\n\n useEffect(() => {\n setOptions(\n (${names.camelPlural} ?? []).map((${names.camel}) => {\n return {\n key: ${names.camel}.id,\n value: ${names.camel}[valueField ?? 'id'] as string | number,\n text: String(${names.camel}[textField${\n textField ? ` ?? '${textField}'` : \"\"\n }]),\n };\n }),\n );\n }, [${names.camelPlural}]);\n\n useEffect(() => {\n setListParams({\n ...listParams,\n ...baseListParams,\n });\n }, [baseListParams]);\n\n const handleSearchChange = (\n e: SyntheticEvent<HTMLElement, Event>,\n data: DropdownOnSearchChangeData,\n ) => {\n setListParams({\n ...listParams,\n keyword: data.searchQuery,\n });\n };\n\n return (\n <Dropdown\n placeholder=\"${entity.title ?? names.constant}\"\n selection\n options={options}\n onSearchChange={handleSearchChange}\n disabled={!${names.camelPlural}}\n loading={!${names.camelPlural}}\n selectOnBlur={false}\n {...props}\n />\n );\n}\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\nimport inflection from \"inflection\";\n\nexport class Template__view_enums_dropdown extends Template {\n constructor() {\n super(\"view_enums_dropdown\");\n }\n\n getTargetAndPath(names: EntityNamesRecord, enumId: string) {\n return {\n target: \"web/src/components\",\n path: `${names.fs}/${enumId}Dropdown.tsx`,\n };\n }\n\n render({ entityId, enumId }: TemplateOptions[\"view_enums_dropdown\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n const label = getLabel(entityId, enumId);\n\n return {\n ...this.getTargetAndPath(names, enumId),\n body: `\nimport React from 'react';\nimport {\n Dropdown,\n DropdownProps,\n} from 'semantic-ui-react';\n\nimport { ${enumId}Label } from 'src/services/sonamu.generated';\n\nexport function ${enumId}Dropdown(props: DropdownProps) {\n const options = Object.entries(${enumId}Label).map(([key, label]) => {\n return {\n key,\n value: key,\n text: \"${label}: \" + label,\n };\n });\n return (\n <Dropdown\n className=\"label\"\n options={options}\n {...props}\n />\n );\n}\n `.trim(),\n importKeys: [],\n };\n }\n}\n\nexport function getLabel(entityId: string, enumId: string): string {\n if (enumId.endsWith(\"OrderBy\")) {\n return \"정렬\";\n } else if (enumId.endsWith(\"SearchField\")) {\n return \"검색\";\n } else {\n const enumProp = EntityManager.get(entityId).props.find(\n (prop) => `${entityId}${inflection.camelize(prop.name)}` === enumId\n );\n if (enumProp && enumProp.desc) {\n return enumProp.desc;\n }\n return enumId;\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\nimport { getLabel } from \"./view_enums_dropdown.template\";\n\nexport class Template__view_enums_select extends Template {\n constructor() {\n super(\"view_enums_select\");\n }\n\n getTargetAndPath(names: EntityNamesRecord, enumId: string) {\n return {\n target: \"web/src/components\",\n path: `${names.fs}/${enumId}Select.tsx`,\n };\n }\n\n render({ entityId, enumId }: TemplateOptions[\"view_enums_select\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n const label = getLabel(entityId, enumId);\n\n return {\n ...this.getTargetAndPath(names, enumId),\n body: `\nimport React from 'react';\nimport {\n Dropdown,\n DropdownProps,\n} from 'semantic-ui-react';\n\nimport { ${enumId}, ${enumId}Label } from 'src/services/sonamu.generated';\n\nexport type ${enumId}SelectProps = {\n placeholder?: string;\n textPrefix?: string;\n} & DropdownProps;\nexport function ${enumId}Select({placeholder, textPrefix, ...props}: ${enumId}SelectProps) {\n const typeOptions = ${enumId}.options.map((key) => ({\n key,\n value: key,\n text: (textPrefix ?? '${label}: ') + ${enumId}Label[key],\n }));\n\n return (\n <Dropdown\n placeholder={placeholder ?? \"${label}\"}\n selection\n options={typeOptions}\n selectOnBlur={false}\n {...props}\n />\n );\n}\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\n\nexport class Template__view_enums_buttonset extends Template {\n constructor() {\n super(\"view_enums_buttonset\");\n }\n\n getTargetAndPath(names: EntityNamesRecord, componentId: string) {\n return {\n target: \"web/src/components\",\n path: `${names.fs}/${componentId}ButtonSet.tsx`,\n };\n }\n\n render({ entityId, enumId }: TemplateOptions[\"view_enums_buttonset\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n\n return {\n ...this.getTargetAndPath(names, enumId),\n body: `\n/*\nview_enums_buttonset\n${JSON.stringify({\n key: this.key,\n options: entityId,\n})}\n*/\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\n\nexport class Template__view_search_input extends Template {\n constructor() {\n super(\"view_search_input\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n return {\n target: \"web/src/components\",\n path: `${names.fs}/${names.capital}SearchInput.tsx`,\n };\n }\n\n render({ entityId }: TemplateOptions[\"view_search_input\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n\n return {\n ...this.getTargetAndPath(names),\n body: `\nimport React from \"react\";\nimport { useState } from \"react\";\nimport { DropdownProps, Input, InputProps } from \"semantic-ui-react\";\nimport { ${names.capital}SearchFieldDropdown } from \"src/components/${names.fs}/${names.capital}SearchFieldDropdown\";\n\nexport function ${names.capital}SearchInput({\n input: { value: inputValue, onChange: inputOnChange, ...inputProps },\n dropdown: dropdownProps,\n}: {\n input: InputProps;\n dropdown: DropdownProps;\n}) {\n const [keyword, setKeyword] = useState<string>(inputValue ?? '');\n\n const handleKeyDown = (e: { key: string }) => {\n if (inputOnChange && e.key === 'Enter') {\n inputOnChange(e as any, {\n value: keyword,\n });\n }\n };\n\n return (\n <Input\n size=\"small\"\n placeholder=\"검색...\"\n style={{ margin: 0 }}\n label={<${names.capital}SearchFieldDropdown {...dropdownProps} />}\n labelPosition=\"left\"\n action={{\n icon: 'search',\n onClick: () => handleKeyDown({ key: 'Enter' }),\n }}\n {...inputProps}\n value={keyword}\n onChange={(e, { value }) => setKeyword(value)}\n onKeyDown={handleKeyDown}\n />\n );\n}\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import { TemplateOptions } from \"../types/types\";\nimport { EntityManager, EntityNamesRecord } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\n\nexport class Template__view_list_columns extends Template {\n constructor() {\n super(\"view_list_columns\");\n }\n\n getTargetAndPath(names: EntityNamesRecord) {\n return {\n target: \"web/src/pages/admin\",\n path: `${names.fsPlural}/_columns.tsx`,\n };\n }\n\n // 컬럼\n render({\n entityId,\n columns,\n columnImports,\n }: TemplateOptions[\"view_list_columns\"]) {\n const names = EntityManager.getNamesFromId(entityId);\n\n return {\n ...this.getTargetAndPath(names),\n body: `\nimport React from 'react';\nimport {\n Segment,\n Table,\n TableRow,\n Button,\n Label,\n} from 'semantic-ui-react';\nimport { DateTime } from \"luxon\";\nimport { TFColumn } from \"src/typeframe/iso-types\";\nimport { ${names.capital}SubsetA } from \"src/services/${names.fs}/${\n names.fs\n }.generated\";\n${columnImports}\n\nconst columns: { [key in Exclude<keyof ${\n names.capital\n }SubsetA, 'id'>]: TFColumn<${names.capital}SubsetA> } = {${columns\n .map((col) => {\n return [\n `${col.name}: { label: \"${col.label}\",`,\n `tc: ${col.tc}, `,\n `collapsing: ${[\"Title\", \"Name\"].includes(col.label) === false}, }`,\n ].join(\"\\n\");\n })\n .join(\",\\n\")}};\nexport default columns;\n `.trim(),\n importKeys: [],\n };\n }\n}\n","import qs from \"qs\";\nimport { z } from \"zod\";\nimport { TemplateOptions } from \"../types/types\";\nimport { getZodObjectFromApi } from \"../api/code-converters\";\nimport { ExtendedApi } from \"../api/decorators\";\nimport { Template } from \"./base-template\";\nimport prettier from \"prettier\";\nimport { Sonamu } from \"../api/sonamu\";\n\nexport class Template__generated_http extends Template {\n constructor() {\n super(\"generated_http\");\n }\n\n getTargetAndPath() {\n const { dir } = Sonamu.config.api;\n\n return {\n target: `${dir}/src/application`,\n path: `sonamu.generated.http`,\n };\n }\n\n async render({}: TemplateOptions[\"generated_http\"]) {\n const {\n syncer: { types, apis },\n config: {\n route: { prefix },\n },\n } = Sonamu;\n\n const lines = await Promise.all(\n apis.map(async (api) => {\n const reqObject = this.resolveApiParams(api, types);\n\n const dataLines = await (async () => {\n if ((api.options.httpMethod ?? \"GET\") === \"GET\") {\n return {\n querystring: [\n qs\n .stringify(reqObject, { encode: false })\n .split(\"&\")\n .join(\"\\n\\t&\"),\n ],\n body: [],\n };\n } else {\n return {\n querystring: [],\n body: [\n \"\",\n await prettier.format(JSON.stringify(reqObject), {\n parser: \"json\",\n }),\n ],\n };\n }\n })();\n\n return [\n [\n `${api.options.httpMethod ?? \"GET\"} {{baseUrl}}${prefix}${api.path}`,\n ...dataLines.querystring,\n ].join(\"\\n\\t?\"),\n `Content-Type: ${api.options.contentType ?? \"application/json\"}`,\n ...dataLines.body,\n ].join(\"\\n\");\n })\n );\n\n return {\n ...this.getTargetAndPath(),\n body: lines.join(\"\\n\\n###\\n\\n\"),\n importKeys: [],\n };\n }\n\n zodTypeToReqDefault(zodType: z.ZodType<unknown>, name: string): unknown {\n if (zodType instanceof z.ZodObject) {\n return Object.fromEntries(\n Object.keys(zodType.shape).map((key) => [\n key,\n this.zodTypeToReqDefault(zodType.shape[key], key),\n ])\n );\n } else if (zodType instanceof z.ZodArray) {\n return [this.zodTypeToReqDefault(zodType.element, name)];\n } else if (zodType instanceof z.ZodString) {\n if (name.endsWith(\"_at\") || name.endsWith(\"_date\") || name === \"range\") {\n return \"2000-01-01\";\n } else {\n return name.toUpperCase();\n }\n } else if (zodType instanceof z.ZodNumber) {\n if (name === \"num\") {\n return 24;\n }\n return zodType.minValue ?? 0;\n } else if (zodType instanceof z.ZodBoolean) {\n return false;\n } else if (zodType instanceof z.ZodEnum) {\n return zodType.options[0];\n } else if (zodType instanceof z.ZodOptional) {\n return this.zodTypeToReqDefault(zodType._def.innerType, name);\n } else if (zodType instanceof z.ZodNullable) {\n return null;\n } else if (zodType instanceof z.ZodUnion) {\n return this.zodTypeToReqDefault(zodType._def.options[0], name);\n } else if (zodType instanceof z.ZodUnknown) {\n return \"unknown\";\n } else if (zodType instanceof z.ZodTuple) {\n return zodType._def.items.map((item: any) =>\n this.zodTypeToReqDefault(item, name)\n );\n } else {\n // console.log(zodType);\n return `unknown-${zodType._type}`;\n }\n }\n\n resolveApiParams(\n api: ExtendedApi,\n references: { [typeName: string]: z.ZodObject<any> }\n ): { [key: string]: unknown } {\n const reqType = getZodObjectFromApi(api, references);\n return this.zodTypeToReqDefault(reqType, \"unknownName\") as {\n [key: string]: unknown;\n };\n }\n}\n","import { SubsetQuery, TemplateOptions } from \"../types/types\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport { Template } from \"./base-template\";\nimport inflection from \"inflection\";\nimport { SourceCode } from \"./generated.template\";\nimport _ from \"lodash\";\nimport { nonNullable } from \"../utils/utils\";\nimport { Sonamu } from \"../api\";\n\nexport class Template__generated_sso extends Template {\n constructor() {\n super(\"generated_sso\");\n }\n\n getTargetAndPath() {\n const { dir } = Sonamu.config.api;\n\n return {\n target: `${dir}/src/application`,\n path: `sonamu.generated.sso.ts`,\n };\n }\n\n render({}: TemplateOptions[\"generated_sso\"]) {\n const entityIds = EntityManager.getAllIds();\n const entities = entityIds.map((id) => EntityManager.get(id));\n\n const sourceCodes: SourceCode[] = entities\n .map((entity) => {\n if (\n entity.parentId !== undefined ||\n Object.keys(entity.subsets).length === 0\n ) {\n return null;\n }\n const subsetKeys = Object.keys(entity.subsets);\n const subsetQueryObject = subsetKeys.reduce(\n (r, subsetKey) => {\n const subsetQuery = entity.getSubsetQuery(subsetKey);\n r[subsetKey] = subsetQuery;\n return r;\n },\n {} as {\n [key: string]: SubsetQuery;\n }\n );\n\n const subsetKeyTypeName = `${entity.names.module}SubsetKey`;\n return {\n label: `SubsetQuery: ${entity.id}`,\n lines: [\n `export const ${inflection.camelize(\n entity.id,\n true\n )}SubsetQueries:{ [key in ${subsetKeyTypeName}]: SubsetQuery} = ${JSON.stringify(\n subsetQueryObject\n )};`,\n \"\",\n ],\n importKeys: [subsetKeyTypeName],\n };\n })\n .filter(nonNullable);\n\n const sourceCode = sourceCodes.reduce(\n (result, ts) => {\n if (ts === null) {\n return result;\n }\n return {\n lines: [...result!.lines, `// ${ts.label}`, ...ts.lines, \"\"],\n importKeys: _.uniq([...result!.importKeys, ...ts.importKeys]),\n };\n },\n {\n lines: [],\n importKeys: [],\n } as Omit<SourceCode, \"label\">\n );\n\n return {\n ...this.getTargetAndPath(),\n body: sourceCode.lines.join(\"\\n\"),\n importKeys: sourceCode.importKeys,\n customHeaders: [`import { SubsetQuery } from \"sonamu\";`],\n };\n }\n}\n","export function isLocal(): boolean {\n return process.env.LR === undefined || process.env.LR === \"local\";\n}\nexport function isRemote(): boolean {\n return process.env.LR === \"remote\";\n}\nexport function isInDocker(): boolean {\n return process.env.LR !== undefined;\n}\nexport function isDaemonServer(): boolean {\n return process.env.NODE_TYPE === \"daemon\";\n}\nexport function isDevelopment(): boolean {\n return isRemote() && process.env.NODE_ENV === \"development\";\n}\nexport function isStaging(): boolean {\n return isRemote() && process.env.NODE_ENV === \"staging\";\n}\nexport function isProduction(): boolean {\n return isRemote() && process.env.NODE_ENV === \"production\";\n}\nexport function isTest(): boolean {\n return isLocal() && process.env.NODE_ENV === \"test\";\n}\n","export type DBPreset = \"w\" | \"r\";\nimport knex, { Knex } from \"knex\";\nimport path from \"path\";\nimport { Sonamu } from \"../api\";\nimport { ServiceUnavailableException } from \"../exceptions/so-exceptions\";\n\nexport type SonamuDBConfig = {\n development_master: Knex.Config;\n development_slave: Knex.Config;\n test: Knex.Config;\n fixture_local: Knex.Config;\n fixture_remote: Knex.Config;\n production_master: Knex.Config;\n production_slave: Knex.Config;\n};\n\nclass DBClass {\n private wdb?: Knex;\n private rdb?: Knex;\n\n async readKnexfile(): Promise<SonamuDBConfig> {\n const dbConfigPath: string = path.join(\n Sonamu.apiRootPath,\n \"/dist/configs/db.js\"\n );\n try {\n const knexfileModule = await import(dbConfigPath);\n return knexfileModule.default as SonamuDBConfig;\n } catch {}\n\n throw new ServiceUnavailableException(\n `DB설정 파일을 찾을 수 없습니다. ${dbConfigPath}`\n );\n }\n\n getDB(which: DBPreset): Knex {\n const dbConfig = Sonamu.dbConfig;\n\n const instanceName = which === \"w\" ? \"wdb\" : \"rdb\";\n\n if (!this[instanceName]) {\n let config: Knex.Config;\n switch (process.env.NODE_ENV ?? \"development\") {\n case \"development\":\n case \"staging\":\n config =\n which === \"w\"\n ? dbConfig[\"development_master\"]\n : dbConfig[\"development_slave\"] ?? dbConfig[\"development_master\"];\n break;\n case \"production\":\n config =\n which === \"w\"\n ? dbConfig[\"production_master\"]\n : dbConfig[\"production_slave\"] ?? dbConfig[\"production_master\"];\n break;\n case \"test\":\n config = dbConfig[\"test\"];\n break;\n default:\n throw new Error(\n `현재 ENV ${process.env.NODE_ENV}에는 설정 가능한 DB설정이 없습니다.`\n );\n }\n this[instanceName] = knex(config);\n }\n\n return this[instanceName]!;\n }\n\n async destroy(): Promise<void> {\n if (this.wdb !== undefined) {\n await this.wdb.destroy();\n this.wdb = undefined;\n }\n if (this.rdb !== undefined) {\n await this.rdb.destroy();\n this.rdb = undefined;\n }\n }\n}\nexport const DB = new DBClass();\n","import { DateTime } from \"luxon\";\nimport { Knex } from \"knex\";\nimport _ from \"lodash\";\nimport { DBPreset, DB } from \"./db\";\nimport { isCustomJoinClause, SubsetQuery } from \"../types/types\";\nimport { BaseListParams } from \"../utils/model\";\nimport inflection from \"inflection\";\nimport chalk from \"chalk\";\nimport { UpsertBuilder } from \"./upsert-builder\";\nimport SqlParser from \"node-sql-parser\";\nimport { getTableName, getTableNamesFromWhere } from \"../utils/sql-parser\";\n\nexport class BaseModelClass {\n public modelName: string = \"Unknown\";\n\n /* DB 인스턴스 get, destroy */\n getDB(which: DBPreset): Knex {\n return DB.getDB(which);\n }\n async destroy() {\n return DB.destroy();\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 async getInsertedIds(\n wdb: Knex,\n rows: any[],\n tableName: string,\n unqKeyFields: string[],\n chunkSize: number = 500\n ) {\n if (!wdb) {\n wdb = this.getDB(\"w\");\n }\n\n let unqKeys: string[];\n let whereInField: any, selectField: string;\n if (unqKeyFields.length > 1) {\n whereInField = wdb.raw(`CONCAT_WS('_', '${unqKeyFields.join(\",\")}')`);\n selectField = `${whereInField} as tmpUid`;\n unqKeys = rows.map((row) =>\n unqKeyFields.map((field) => row[field]).join(\"_\")\n );\n } else {\n whereInField = unqKeyFields[0];\n selectField = unqKeyFields[0];\n unqKeys = rows.map((row) => row[unqKeyFields[0]]);\n }\n const chunks = _.chunk(unqKeys, chunkSize);\n\n let resultIds: number[] = [];\n for (let chunk of chunks) {\n const dbRows = await wdb(tableName)\n .select(\"id\", wdb.raw(selectField))\n .whereIn(whereInField, chunk);\n resultIds = resultIds.concat(\n dbRows.map((dbRow: any) => parseInt(dbRow.id))\n );\n }\n\n return resultIds;\n }\n\n async useLoaders(db: Knex, rows: any[], loaders: SubsetQuery[\"loaders\"]) {\n if (loaders.length === 0) {\n return rows;\n }\n\n for (let loader of loaders) {\n let subQ: any;\n let subRows: any[];\n let toCol: string;\n\n const fromIds = rows.map((row) => row[loader.manyJoin.idField]);\n\n if (loader.manyJoin.through === undefined) {\n // HasMany\n const idColumn = `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`;\n subQ = db(loader.manyJoin.toTable)\n .whereIn(idColumn, fromIds)\n .select([...loader.select, idColumn]);\n\n // HasMany에서 OneJoin이 있는 경우\n loader.oneJoins.map((join) => {\n if (join.join == \"inner\") {\n subQ.innerJoin(\n `${join.table} as ${join.as}`,\n this.getJoinClause(db, join)\n );\n } else if (join.join == \"outer\") {\n subQ.leftOuterJoin(\n `${join.table} as ${join.as}`,\n this.getJoinClause(db, join)\n );\n }\n });\n toCol = loader.manyJoin.toCol;\n } else {\n // ManyToMany\n const idColumn = `${loader.manyJoin.through.table}.${loader.manyJoin.through.fromCol}`;\n subQ = db(loader.manyJoin.through.table)\n .join(\n loader.manyJoin.toTable,\n `${loader.manyJoin.through.table}.${loader.manyJoin.through.toCol}`,\n `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`\n )\n .whereIn(idColumn, fromIds)\n .select(_.uniq([...loader.select, idColumn]));\n\n // ManyToMany에서 OneJoin이 있는 경우\n loader.oneJoins.map((join) => {\n if (join.join == \"inner\") {\n subQ.innerJoin(\n `${join.table} as ${join.as}`,\n this.getJoinClause(db, join)\n );\n } else if (join.join == \"outer\") {\n subQ.leftOuterJoin(\n `${join.table} as ${join.as}`,\n this.getJoinClause(db, join)\n );\n }\n });\n toCol = loader.manyJoin.through.fromCol;\n }\n subRows = await subQ;\n\n if (loader.loaders) {\n // 추가 -Many 케이스가 있는 경우 recursion 처리\n subRows = await this.useLoaders(db, subRows, loader.loaders);\n }\n\n // 불러온 row들을 참조ID 기준으로 분류 배치\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 return rows;\n }\n\n hydrate<T>(rows: T[]): T[] {\n return rows.map((row: any) => {\n // nullable relation인 경우 관련된 필드가 전부 null로 생성되는 것 방지하는 코드\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 return r;\n } else {\n r[field] = row[field];\n return r;\n }\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 _.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 nullKeys.map((nullKey) => (hydrated[nullKey] = null));\n\n return hydrated;\n });\n }\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: Knex.QueryBuilder;\n db: Knex;\n select: (string | Knex.Raw)[];\n joins: SubsetQuery[\"joins\"];\n virtual: string[];\n }) => Knex.QueryBuilder;\n baseTable?: string;\n debug?: boolean | \"list\" | \"count\";\n db?: Knex;\n optimizeCountQuery?: boolean;\n }): Promise<{\n rows: any[];\n total?: number | undefined;\n subsetQuery: SubsetQuery;\n qb: Knex.QueryBuilder;\n }> {\n const db = _db ?? this.getDB(subset.startsWith(\"A\") ? \"w\" : \"r\");\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: db.from(baseTable),\n db,\n select,\n joins,\n virtual,\n });\n\n const applyJoinClause = (\n qb: Knex.QueryBuilder,\n joins: SubsetQuery[\"joins\"]\n ) => {\n joins.map((join) => {\n if (join.join == \"inner\") {\n qb.innerJoin(\n `${join.table} as ${join.as}`,\n this.getJoinClause(db, join)\n );\n } else if (join.join == \"outer\") {\n qb.leftOuterJoin(\n `${join.table} as ${join.as}`,\n this.getJoinClause(db, join)\n );\n }\n });\n };\n\n // countQuery\n const total = await (async () => {\n if (queryMode === \"list\") {\n return undefined;\n }\n\n const clonedQb = qb.clone().clear(\"order\").clear(\"offset\").clear(\"limit\");\n const parser = new SqlParser.Parser();\n\n // optmizeCountQuery가 true인 경우 다른 clause에 영향을 주지 않는 모든 join을 제외함\n if (optimizeCountQuery) {\n const parsedQuery = parser.astify(clonedQb.toQuery());\n const tables = getTableNamesFromWhere(parsedQuery);\n // where절에 사용되는 테이블의 조인을 위해 사용되는 테이블\n const needToJoin = _.uniq(\n tables.flatMap((table) =>\n table.split(\"__\").map((t) => inflection.pluralize(t))\n )\n );\n applyJoinClause(\n clonedQb,\n joins.filter((j) => needToJoin.includes(j.table))\n );\n } else {\n applyJoinClause(clonedQb, joins);\n }\n\n const parsedQuery = parser.astify(clonedQb.toQuery());\n const q = Array.isArray(parsedQuery) ? parsedQuery[0] : parsedQuery;\n if (q.type !== \"select\") {\n throw new Error(\"Invalid query\");\n }\n\n const countQuery =\n q.distinct !== null\n ? clonedQb\n .clear(\"select\")\n .select(\n db.raw(\n `COUNT(DISTINCT \\`${getTableName(q.columns[0].expr)}\\`.\\`${q.columns[0].expr.column}\\`) as total`\n )\n )\n .first()\n : clonedQb.clear(\"select\").count(\"*\", { as: \"total\" }).first();\n const countRow: { total?: number } = await countQuery;\n\n // debug: countQuery\n if (debug === true || debug === \"count\") {\n console.debug(\n \"DEBUG: count query\",\n chalk.blue(countQuery.toQuery().toString())\n );\n }\n\n return countRow?.total ?? 0;\n })();\n\n // listQuery\n const rows = await (async () => {\n if (queryMode === \"count\") {\n return [];\n }\n\n // limit, offset\n if (params.num !== 0) {\n qb.limit(params.num!);\n qb.offset(params.num! * (params.page! - 1));\n }\n\n // select, rows\n const listQuery = qb.clone().select(select);\n\n // join\n applyJoinClause(listQuery, joins);\n\n let rows = await listQuery;\n // debug: listQuery\n if (debug === true || debug === \"list\") {\n console.debug(\n \"DEBUG: list query\",\n chalk.blue(listQuery.toQuery().toString())\n );\n }\n\n rows = await this.useLoaders(db, rows, loaders);\n rows = this.hydrate(rows);\n return rows;\n })();\n\n return { rows, total, subsetQuery, qb };\n }\n\n getJoinClause(\n db: Knex<any, unknown>,\n join: SubsetQuery[\"joins\"][number]\n ): Knex.Raw<any> {\n if (!isCustomJoinClause(join)) {\n return db.raw(`${join.from} = ${join.to}`);\n } else {\n return db.raw(join.custom);\n }\n }\n\n getUpsertBuilder(): UpsertBuilder {\n return new UpsertBuilder();\n }\n}\nexport const BaseModel = new BaseModelClass();\n","import { v4 as uuidv4 } from \"uuid\";\nimport _ from \"lodash\";\nimport { Knex } from \"knex\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport { nonNullable } from \"../utils/utils\";\nimport { RowWithId, batchUpdate } from \"./_batch_update\";\n\ntype TableData = {\n references: Set<string>;\n rows: any[];\n uniqueIndexes: { name?: string; columns: string[] }[];\n uniquesMap: Map<string, string>;\n};\nexport type UBRef = {\n uuid: string;\n of: string;\n use?: string;\n};\nexport function isRefField(field: any): field is UBRef {\n return (\n field !== undefined &&\n field !== null &&\n field.of !== undefined &&\n field.uuid !== undefined\n );\n}\n\nexport class UpsertBuilder {\n tables: Map<string, TableData>;\n constructor() {\n this.tables = new Map();\n }\n\n getTable(tableName: string): TableData {\n const table = this.tables.get(tableName);\n if (table === undefined) {\n const tableSpec = (() => {\n try {\n return EntityManager.getTableSpec(tableName);\n } catch {\n return null;\n }\n })();\n\n this.tables.set(tableName, {\n references: new Set(),\n rows: [],\n uniqueIndexes: tableSpec?.uniqueIndexes ?? [],\n uniquesMap: new Map<string, string>(),\n });\n }\n\n return this.tables.get(tableName)!;\n }\n\n hasTable(tableName: string): boolean {\n return this.tables.has(tableName);\n }\n\n register<T extends string>(\n tableName: string,\n row: {\n [key in T]?:\n | UBRef\n | string\n | number\n | boolean\n | bigint\n | null\n | object\n | unknown;\n }\n ): UBRef {\n const table = this.getTable(tableName);\n\n // 해당 테이블의 unique 인덱스를 순회하며 키 생성\n const uniqueKeys = table.uniqueIndexes\n .map((unqIndex) => {\n const uniqueKeyArray = unqIndex.columns.map((unqCol) => {\n const val = row[unqCol as keyof typeof row];\n if (isRefField(val)) {\n return val.uuid;\n } else {\n return row[unqCol as keyof typeof row] ?? uuidv4(); // nullable인 경우 uuid로 랜덤값 삽입\n }\n });\n\n // 값이 모두 null인 경우 키 생성 패스\n if (uniqueKeyArray.length === 0) {\n return null;\n }\n return uniqueKeyArray.join(\"---delimiter--\");\n })\n .filter(nonNullable);\n\n // uuid 생성 로직\n const uuid: string = (() => {\n // 키를 순회하여 이미 존재하는 키가 있는지 확인\n if (uniqueKeys.length > 0) {\n for (const uniqueKey of uniqueKeys) {\n if (table.uniquesMap.has(uniqueKey)) {\n return table.uniquesMap.get(uniqueKey)!; // 이미 has 체크를 했으므로 undefined 불가능\n }\n }\n }\n\n // 찾을 수 없는 경우 생성\n return uuidv4();\n })();\n\n // 모든 유니크키에 대해 유니크맵에 uuid 저장\n if (uniqueKeys.length > 0) {\n for (const uniqueKey of uniqueKeys) {\n table.uniquesMap.set(uniqueKey, uuid);\n }\n }\n\n // 이 테이블에 사용된 RefField를 순회하여, 현재 테이블 정보에 어떤 필드를 참조하는지 추가\n // 이 정보를 나중에 치환할 때 사용\n row = Object.keys(row).reduce((r, rowKey) => {\n const rowValue = row[rowKey as keyof typeof row];\n\n if (isRefField(rowValue)) {\n rowValue.use ??= \"id\";\n table.references.add(rowValue.of + \".\" + rowValue.use);\n r[rowKey] = rowValue;\n } else if (typeof rowValue === \"object\") {\n // object인 경우 JSON으로 변환\n r[rowKey] = rowValue === null ? null : JSON.stringify(rowValue);\n } else {\n r[rowKey] = rowValue;\n }\n return r;\n }, {} as any);\n\n table.rows.push({\n uuid,\n ...row,\n });\n\n return {\n of: tableName,\n uuid: (row as { uuid?: string }).uuid ?? uuid,\n };\n }\n\n async upsert(\n wdb: Knex,\n tableName: string,\n chunkSize?: number\n ): Promise<number[]> {\n return this.upsertOrInsert(wdb, tableName, \"upsert\", chunkSize);\n }\n async insertOnly(\n wdb: Knex,\n tableName: string,\n chunkSize?: number\n ): Promise<number[]> {\n return this.upsertOrInsert(wdb, tableName, \"insert\", chunkSize);\n }\n\n async upsertOrInsert(\n wdb: Knex,\n tableName: string,\n mode: \"upsert\" | \"insert\",\n chunkSize?: number\n ): Promise<number[]> {\n if (this.hasTable(tableName) === false) {\n return [];\n }\n\n const table = this.tables.get(tableName);\n if (table === undefined) {\n throw new Error(`존재하지 않는 테이블 ${tableName}에 upsert 요청`);\n } else if (table.rows.length === 0) {\n throw new Error(`${tableName}에 upsert 할 데이터가 없습니다.`);\n }\n\n if (\n table.rows.some((row) =>\n Object.entries(row).some(\n ([, value]) => isRefField(value) && value.of !== tableName\n )\n )\n ) {\n throw new Error(`${tableName} 해결되지 않은 참조가 있습니다.`);\n }\n\n // 전체 테이블 순회하여 현재 테이블 참조하는 모든 테이블 추출\n const { references, refTables } = Array.from(this.tables).reduce(\n (r, [, table]) => {\n const reference = Array.from(table.references.values()).find((ref) =>\n ref.includes(tableName + \".\")\n );\n if (reference) {\n r.references.push(reference);\n r.refTables.push(table);\n }\n\n return r;\n },\n {\n references: [] as string[],\n refTables: [] as TableData[],\n }\n );\n const extractFields = _.uniq(references).map(\n (reference) => reference.split(\".\")[1]\n );\n\n // 내부 참조 있는 경우 필터하여 분리\n const groups = _.groupBy(table.rows, (row) =>\n Object.entries(row).some(([, value]) => isRefField(value))\n ? \"selfRef\"\n : \"normal\"\n );\n const normalRows = groups.normal ?? [];\n const selfRefRows = groups.selfRef ?? [];\n\n const chunks = chunkSize ? _.chunk(normalRows, chunkSize) : [normalRows];\n const uuidMap = new Map<string, any>();\n\n for (const chunk of chunks) {\n const q = wdb.insert(chunk).into(tableName);\n if (mode === \"insert\") {\n await q;\n } else if (mode === \"upsert\") {\n await q.onDuplicateUpdate.apply(q, Object.keys(normalRows[0]));\n }\n\n // upsert된 row들을 다시 조회하여 uuidMap에 저장\n const uuids = chunk.map((row) => row.uuid);\n const upsertedRows = await wdb(tableName)\n .select(_.uniq([\"uuid\", \"id\", ...extractFields]))\n .whereIn(\"uuid\", uuids);\n upsertedRows.forEach((row: any) => {\n uuidMap.set(row.uuid, row);\n });\n }\n\n // 해당 테이블 참조를 실제 밸류로 변경\n refTables.map((table) => {\n table.rows = table.rows.map((row) => {\n Object.keys(row).map((key) => {\n const prop = row[key];\n if (isRefField(prop) && prop.of === tableName) {\n const parent = uuidMap.get(prop.uuid);\n if (parent === undefined) {\n console.error(prop);\n throw new Error(\n `존재하지 않는 uuid ${prop.uuid} -- in ${tableName}`\n );\n }\n row[key] = parent[prop.use ?? \"id\"];\n }\n });\n return row;\n });\n });\n\n const allIds = Array.from(uuidMap.values()).map((row) => row.id);\n\n // 자기 참조가 있는 경우 재귀적으로 upsert\n if (selfRefRows.length > 0) {\n // 처리된 데이터를 제외하고 다시 upsert\n table.rows = selfRefRows;\n const selfRefIds = await this.upsert(wdb, tableName, chunkSize);\n allIds.push(...selfRefIds);\n }\n\n return allIds;\n }\n\n async updateBatch(\n wdb: Knex,\n tableName: string,\n options?: {\n chunkSize?: number;\n where?: string | string[];\n }\n ): Promise<void> {\n options = _.defaults(options, {\n chunkSize: 500,\n where: \"id\",\n });\n\n if (this.hasTable(tableName) === false) {\n return;\n }\n const table = this.tables.get(tableName)!;\n if (table.rows.length === 0) {\n return;\n }\n\n const whereColumns = Array.isArray(options.where)\n ? options.where\n : [options.where ?? \"id\"];\n const rows = table.rows.map((_row) => {\n const { uuid, ...row } = _row;\n return row as RowWithId<string>;\n });\n\n await batchUpdate(wdb, tableName, whereColumns, rows, options.chunkSize);\n }\n}\n","/*\n 아래의 링크에서 참고해서 가져온 소스코드\n https://github.com/knex/knex/issues/5716\n*/\n\nimport { Knex } from \"knex\";\n\nexport type RowWithId<Id extends string> = {\n [key in Id]: any;\n} & Record<string, any>;\n\n/**\n * Batch update rows in a table. Technically its a patch since it only updates the specified columns. Any omitted columns will not be affected\n * @param knex\n * @param tableName\n * @param ids\n * @param rows\n * @param chunkSize\n * @param trx\n */\nexport async function batchUpdate<Id extends string>(\n knex: Knex,\n tableName: string,\n ids: Id[],\n rows: RowWithId<Id>[],\n chunkSize = 50,\n trx: Knex.Transaction | null = null\n) {\n const chunks: RowWithId<Id>[][] = [];\n for (let i = 0; i < rows.length; i += chunkSize) {\n chunks.push(rows.slice(i, i + chunkSize));\n }\n\n const executeUpdate = async (\n chunk: RowWithId<Id>[],\n transaction: Knex.Transaction\n ) => {\n const sql = generateBatchUpdateSQL(knex, tableName, chunk, ids);\n return knex.raw(sql).transacting(transaction);\n };\n\n if (trx) {\n for (const chunk of chunks) {\n await executeUpdate(chunk, trx);\n }\n } else {\n await knex.transaction(async (newTrx) => {\n for (const chunk of chunks) {\n await executeUpdate(chunk, newTrx);\n }\n });\n }\n}\n\n/**\n * Generate a set of unique keys in a data array\n *\n * Example:\n * [ { a: 1, b: 2 }, { a: 3, c: 4 } ] => Set([ \"a\", \"b\", \"c\" ])\n * @param data\n */\nfunction generateKeySetFromData(data: Record<string, any>[]) {\n const keySet: Set<string> = new Set();\n for (const row of data) {\n for (const key of Object.keys(row)) {\n keySet.add(key);\n }\n }\n return keySet;\n}\n\nfunction generateBatchUpdateSQL<Id extends string>(\n knex: Knex,\n tableName: string,\n data: Record<string, any>[],\n identifiers: Id[]\n) {\n const keySet = generateKeySetFromData(data);\n const bindings = [];\n\n const invalidIdentifiers = identifiers.filter((id) => !keySet.has(id));\n if (invalidIdentifiers.length > 0) {\n throw new Error(\n `Invalid identifiers: ${invalidIdentifiers.join(\", \")}. Identifiers must exist in the data`\n );\n }\n\n const cases = [];\n for (const key of keySet) {\n if (identifiers.includes(key as Id)) continue;\n\n const rows = [];\n for (const row of data) {\n if (Object.hasOwnProperty.call(row, key)) {\n const whereClause = identifiers\n .map((id) => `\\`${id}\\` = ?`)\n .join(\" AND \");\n rows.push(`WHEN (${whereClause}) THEN ?`);\n bindings.push(...identifiers.map((i) => row[i]), row[key]);\n }\n }\n\n const whenThen = rows.join(\" \");\n cases.push(`\\`${key}\\` = CASE ${whenThen} ELSE \\`${key}\\` END`);\n }\n\n const whereInClauses = identifiers\n .map((col) => `${col} IN (${data.map(() => \"?\").join(\", \")})`)\n .join(\" AND \");\n\n const whereInBindings = identifiers.flatMap((col) =>\n data.map((row) => row[col])\n );\n\n const sql = knex.raw(\n `UPDATE \\`${tableName}\\` SET ${cases.join(\", \")} WHERE ${whereInClauses}`,\n [...bindings, ...whereInBindings]\n );\n\n return sql.toQuery();\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","import knex from \"knex\";\n\nexport function attachOnDuplicateUpdate() {\n try {\n knex.QueryBuilder.extend(\"onDuplicateUpdate\", function (...columns) {\n if (columns.length === 0) {\n // 업데이트 할 컬럼이 없으면 onDuplicateUpdate 구문 처리 패스\n const { sql: originalSQL, bindings: originalBindings } = this.toSQL();\n return this.client.raw(originalSQL, originalBindings);\n }\n\n const { placeholders, bindings } = columns.reduce(\n (result, column) => {\n if (typeof column === \"string\") {\n result.placeholders.push(`?? = Values(??)`);\n result.bindings.push(column, column);\n } else if (column && typeof column === \"object\") {\n Object.keys(column).forEach((key) => {\n result.placeholders.push(`?? = ?`);\n result.bindings.push(key, column[key]);\n });\n } else {\n throw new Error(\n \"onDuplicateUpdate error: expected column name to be string or object.\"\n );\n }\n\n return result;\n },\n { placeholders: [], bindings: [] }\n );\n\n const { sql: originalSQL, bindings: originalBindings } = this.toSQL();\n\n const newBindings = [...originalBindings, ...bindings];\n\n return this.client.raw(\n `${originalSQL} ON DUPLICATE KEY UPDATE ${placeholders.join(\", \")}`,\n newBindings\n );\n });\n } catch {\n // ignored\n }\n}\n","import _ from \"lodash\";\nimport knex, { Knex } from \"knex\";\nimport prettier from \"prettier\";\nimport chalk from \"chalk\";\nimport { DateTime } from \"luxon\";\nimport fs from \"fs-extra\";\nimport equal from \"fast-deep-equal\";\nimport inflection from \"inflection\";\nimport prompts from \"prompts\";\nimport { execSync } from \"child_process\";\nimport path from \"path\";\n\nimport {\n GenMigrationCode,\n isBelongsToOneRelationProp,\n isHasManyRelationProp,\n isManyToManyRelationProp,\n isOneToOneRelationProp,\n isRelationProp,\n isVirtualProp,\n isStringProp,\n KnexColumnType,\n MigrationColumn,\n MigrationForeign,\n MigrationIndex,\n MigrationJoinTable,\n MigrationSet,\n MigrationSetAndJoinTable,\n isDecimalProp,\n isFloatProp,\n isTextProp,\n isEnumProp,\n isIntegerProp,\n isKnexError,\n RelationOn,\n} from \"../types/types\";\nimport { EntityManager } from \"./entity-manager\";\nimport { Entity } from \"./entity\";\nimport { Sonamu } from \"../api\";\nimport { ServiceUnavailableException } from \"../exceptions/so-exceptions\";\n\ntype MigratorMode = \"dev\" | \"deploy\";\nexport type MigratorOptions = {\n readonly mode: MigratorMode;\n};\ntype MigrationCode = {\n name: string;\n path: string;\n};\ntype ConnString = `${\"mysql2\"}://${string}@${string}:${number}/${string}`; // mysql2://account@host:port/database\nexport type MigrationStatus = {\n codes: MigrationCode[];\n conns: {\n name: string;\n connKey: string;\n connString: ConnString;\n currentVersion: string;\n status: string | number;\n pending: string[];\n }[];\n preparedCodes: GenMigrationCode[];\n};\n\nexport class Migrator {\n readonly mode: MigratorMode;\n\n targets: {\n compare?: Knex;\n pending: Knex;\n shadow: Knex;\n apply: Knex[];\n };\n\n constructor(options: MigratorOptions) {\n this.mode = options.mode;\n const { dbConfig } = Sonamu;\n\n if (this.mode === \"dev\") {\n const devDB = knex(dbConfig.development_master);\n const testDB = knex(dbConfig.test);\n const fixtureLocalDB = knex(dbConfig.fixture_local);\n\n const applyDBs = [devDB, testDB, fixtureLocalDB];\n if (\n (dbConfig.fixture_local.connection as Knex.MySql2ConnectionConfig)\n .host !==\n (dbConfig.fixture_remote.connection as Knex.MySql2ConnectionConfig)\n .host ||\n (dbConfig.fixture_local.connection as Knex.MySql2ConnectionConfig)\n .database !==\n (dbConfig.fixture_remote.connection as Knex.MySql2ConnectionConfig)\n .database\n ) {\n const fixtureRemoteDB = knex(dbConfig.fixture_remote);\n applyDBs.push(fixtureRemoteDB);\n }\n\n this.targets = {\n compare: devDB,\n pending: devDB,\n shadow: testDB,\n apply: applyDBs,\n };\n } else if (this.mode === \"deploy\") {\n const productionDB = knex(Sonamu.dbConfig.production_master);\n const testDB = knex(Sonamu.dbConfig.test);\n\n this.targets = {\n pending: productionDB,\n shadow: testDB,\n apply: [productionDB],\n };\n } else {\n throw new Error(`잘못된 모드 ${this.mode} 입력`);\n }\n }\n\n async getMigrationCodes(): Promise<{\n normal: MigrationCode[];\n onlyTs: MigrationCode[];\n onlyJs: MigrationCode[];\n }> {\n const srcMigrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n const distMigrationsDir = `${Sonamu.apiRootPath}/dist/migrations`;\n\n if (fs.existsSync(srcMigrationsDir) === false) {\n fs.mkdirSync(srcMigrationsDir, {\n recursive: true,\n });\n }\n if (fs.existsSync(distMigrationsDir) === false) {\n fs.mkdirSync(distMigrationsDir, {\n recursive: true,\n });\n }\n const srcMigrations = fs\n .readdirSync(srcMigrationsDir)\n .filter((f) => f.endsWith(\".ts\"))\n .map((f) => f.split(\".\")[0]);\n const distMigrations = fs\n .readdirSync(distMigrationsDir)\n .filter((f) => f.endsWith(\".js\"))\n .map((f) => f.split(\".\")[0]);\n\n const normal = _.intersection(srcMigrations, distMigrations)\n .map((filename) => {\n return {\n name: filename,\n path: path.join(srcMigrationsDir, filename) + \".ts\",\n };\n })\n .sort((a, b) => (a > b ? 1 : -1));\n\n const onlyTs = _.difference(srcMigrations, distMigrations).map(\n (filename) => {\n return {\n name: filename,\n path: path.join(srcMigrationsDir, filename) + \".ts\",\n };\n }\n );\n\n const onlyJs = _.difference(distMigrations, srcMigrations).map(\n (filename) => {\n return {\n name: filename,\n path: path.join(distMigrationsDir, filename) + \".js\",\n };\n }\n );\n\n return {\n normal,\n onlyTs,\n onlyJs,\n };\n }\n\n async getStatus(): Promise<MigrationStatus> {\n const { normal, onlyTs, onlyJs } = await this.getMigrationCodes();\n if (onlyTs.length > 0) {\n console.debug({ onlyTs });\n throw new ServiceUnavailableException(\n `There is an un-compiled TS migration files.\\nPlease compile them first.\\n\\n${onlyTs\n .map((f) => f.name)\n .join(\"\\n\")}`\n );\n }\n if (onlyJs.length > 0) {\n console.debug({ onlyJs });\n await Promise.all(\n onlyJs.map(async (f) => {\n execSync(\n `rm -f ${f.path.replace(\"/src/\", \"/dist/\").replace(\".ts\", \".js\")}`\n );\n })\n );\n }\n\n const connKeys = Object.keys(Sonamu.dbConfig).filter(\n (key) => key.endsWith(\"_slave\") === false\n ) as (keyof typeof Sonamu.dbConfig)[];\n\n const statuses = await Promise.all(\n connKeys.map(async (connKey) => {\n const knexOptions = Sonamu.dbConfig[connKey];\n const tConn = knex(knexOptions);\n\n const status = await (async () => {\n try {\n return await tConn.migrate.status();\n } catch (err) {\n return \"error\";\n }\n })();\n const pending = await (async () => {\n try {\n const [, fdList] = await tConn.migrate.list();\n return fdList.map((fd: { file: string }) =>\n fd.file.replace(\".js\", \"\")\n );\n } catch (err) {\n return [];\n }\n })();\n const currentVersion = await (async () => {\n try {\n return tConn.migrate.currentVersion();\n } catch (err) {\n return \"error\";\n }\n })();\n\n const connection =\n knexOptions.connection as Knex.MySql2ConnectionConfig;\n\n await tConn.destroy();\n\n return {\n name: connKey.replace(\"_master\", \"\"),\n connKey,\n connString: `${knexOptions.client}://${connection.user ?? \"\"}@${\n connection.host\n }:${connection.port ?? 3306}/${connection.database}` as ConnString,\n currentVersion,\n status,\n pending,\n };\n })\n );\n\n const preparedCodes: GenMigrationCode[] = await (async () => {\n const status0conn = statuses.find((status) => status.status === 0);\n if (status0conn === undefined) {\n return [];\n }\n\n const compareDBconn = knex(Sonamu.dbConfig[status0conn.connKey]);\n const genCodes = await this.compareMigrations(compareDBconn);\n\n await compareDBconn.destroy();\n\n return genCodes;\n })();\n\n return {\n conns: statuses,\n codes: normal,\n preparedCodes,\n };\n /*\n TS/JS 코드 컴파일 상태 확인\n 1. 원본 파일 없는 JS파일이 존재하는 경우: 삭제\n 2. 컴파일 되지 않은 TS파일이 존재하는 경우: throw 쳐서 데브 서버 오픈 요청\n\n DB 마이그레이션 상태 확인\n 1. 전체 DB설정에 대해서 현재 마이그레이션 상태 확인\n - connKey: string\n - status: number\n - currentVersion: string\n - list: { file: string; directory: string }[]\n\n */\n }\n\n async runAction(\n action: \"latest\" | \"rollback\",\n targets: string[]\n ): Promise<\n {\n connKey: string;\n batchNo: number;\n applied: string[];\n }[]\n > {\n // get uniq knex configs\n const configs = _.uniqBy(\n targets\n .map((target) => ({\n connKey: target,\n options: Sonamu.dbConfig[target as keyof typeof Sonamu.dbConfig],\n }))\n .filter((c) => c.options !== undefined),\n ({ options }) =>\n `${(options.connection as Knex.MySql2ConnectionConfig).host}:${\n (options.connection as Knex.MySql2ConnectionConfig).port ?? 3306\n }/${(options.connection as Knex.MySql2ConnectionConfig).database}`\n );\n\n // get connections\n const conns = await Promise.all(\n configs.map(async (config) => ({\n connKey: config.connKey,\n knex: knex(config.options),\n }))\n );\n\n // action\n const result = await (async () => {\n switch (action) {\n case \"latest\":\n return Promise.all(\n conns.map(async ({ connKey, knex }) => {\n const [batchNo, applied] = await knex.migrate.latest();\n return {\n connKey,\n batchNo,\n applied,\n };\n })\n );\n case \"rollback\":\n return Promise.all(\n conns.map(async ({ connKey, knex }) => {\n const [batchNo, applied] = await knex.migrate.rollback();\n return {\n connKey,\n batchNo,\n applied,\n };\n })\n );\n }\n })();\n\n // destroy\n await Promise.all(\n conns.map(({ knex }) => {\n return knex.destroy();\n })\n );\n\n return result;\n }\n\n async delCodes(codeNames: string[]): Promise<number> {\n const { conns } = await this.getStatus();\n if (\n conns.some((conn) => {\n return codeNames.some(\n (codeName) => conn.pending.includes(codeName) === false\n );\n })\n ) {\n throw new Error(\n \"You cannot delete a migration file if there is already applied.\"\n );\n }\n\n const delFiles = codeNames\n .map((codeName) => [\n `${Sonamu.apiRootPath}/src/migrations/${codeName}.ts`,\n `${Sonamu.apiRootPath}/dist/migrations/${codeName}.js`,\n ])\n .flat();\n\n const res = await Promise.all(\n delFiles.map((delFile) => {\n if (fs.existsSync(delFile)) {\n console.log(chalk.red(`DELETE: ${delFile}`));\n fs.unlinkSync(delFile);\n return delFiles.includes(\".ts\") ? 1 : 0;\n }\n return 0;\n })\n );\n return _.sum(res);\n }\n\n async generatePreparedCodes(): Promise<number> {\n const { preparedCodes } = await this.getStatus();\n if (preparedCodes.length === 0) {\n console.log(chalk.green(\"\\n현재 모두 싱크된 상태입니다.\"));\n return 0;\n }\n\n // 실제 코드 생성\n const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n preparedCodes\n .filter((pcode) => pcode.formatted)\n .map((pcode, index) => {\n const dateTag = DateTime.local()\n .plus({ seconds: index })\n .toFormat(\"yyyyMMddHHmmss\");\n const filePath = `${migrationsDir}/${dateTag}_${pcode.title}.ts`;\n fs.writeFileSync(filePath, pcode.formatted!);\n console.log(chalk.green(`MIGRTAION CREATED ${filePath}`));\n });\n\n return preparedCodes.length;\n }\n\n async clearPendingList(): Promise<void> {\n const [, pendingList] = (await this.targets.pending.migrate.list()) as [\n unknown,\n {\n file: string;\n directory: string;\n }[],\n ];\n const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n const delList = pendingList.map((df) => {\n return path.join(migrationsDir, df.file).replace(\".js\", \".ts\");\n });\n for (let p of delList) {\n if (fs.existsSync(p)) {\n fs.unlinkSync(p);\n }\n }\n await this.cleanUpDist(true);\n }\n\n async check(): Promise<void> {\n const codes = await this.compareMigrations(this.targets.compare!);\n if (codes.length === 0) {\n console.log(chalk.green(\"\\n현재 모두 싱크된 상태입니다.\"));\n return;\n }\n\n // 현재 생성된 코드 표기\n console.table(codes, [\"type\", \"title\"]);\n console.log(codes[0]);\n }\n\n async run(): Promise<void> {\n // pending 마이그레이션 확인\n const [, pendingList] = await this.targets.pending.migrate.list();\n if (pendingList.length > 0) {\n console.log(\n chalk.red(\"pending 된 마이그레이션이 존재합니다.\"),\n pendingList.map((pending: any) => pending.file)\n );\n\n // pending이 있는 경우 Shadow DB 테스트 진행 여부 컨펌\n const answer = await prompts({\n type: \"confirm\",\n name: \"value\",\n message: \"Shadow DB 테스트를 진행하시겠습니까?\",\n initial: true,\n });\n if (answer.value === false) {\n return;\n }\n\n console.time(chalk.blue(\"Migrator - runShadowTest\"));\n await this.runShadowTest();\n console.timeEnd(chalk.blue(\"Migrator - runShadowTest\"));\n await Promise.all(\n this.targets.apply.map(async (applyDb) => {\n const label = chalk.green(\n `APPLIED ${\n applyDb.client.connectionSettings.host\n } ${applyDb.client.database()}`\n );\n console.time(label);\n const [,] = await applyDb.migrate.latest();\n console.timeEnd(label);\n })\n );\n }\n\n // MD-DB간 비교하여 코드 생성 리턴\n const codes = await this.compareMigrations(this.targets.compare!);\n if (codes.length === 0) {\n console.log(chalk.green(\"\\n현재 모두 싱크된 상태입니다.\"));\n return;\n }\n\n // 현재 생성된 코드 표기\n console.table(codes, [\"type\", \"title\"]);\n\n /* DEBUG: 디버깅용 코드\n codes.map((code) => console.log(code.formatted));\n process.exit();\n */\n\n // 실제 파일 생성 프롬프트\n const answer = await prompts({\n type: \"confirm\",\n name: \"value\",\n message: \"마이그레이션 코드를 생성하시겠습니까?\",\n initial: false,\n });\n if (answer.value === false) {\n return;\n }\n\n // 실제 코드 생성\n const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n codes\n .filter((code) => code.formatted)\n .map((code, index) => {\n const dateTag = DateTime.local()\n .plus({ seconds: index })\n .toFormat(\"yyyyMMddHHmmss\");\n const filePath = `${migrationsDir}/${dateTag}_${code.title}.ts`;\n fs.writeFileSync(filePath, code.formatted!);\n console.log(chalk.green(`MIGRTAION CREATED ${filePath}`));\n });\n }\n\n async rollback() {\n console.time(chalk.red(\"rollback:\"));\n const rollbackAllResult = await Promise.all(\n this.targets.apply.map(async (db) => {\n await db.migrate.forceFreeMigrationsLock();\n return db.migrate.rollback(undefined, false);\n })\n );\n console.dir({ rollbackAllResult }, { depth: null });\n console.timeEnd(chalk.red(\"rollback:\"));\n }\n\n async cleanUpDist(force: boolean = false): Promise<void> {\n const files = ([\"src\", \"dist\"] as const).reduce(\n (r, which) => {\n const migrationPath = path.join(\n Sonamu.apiRootPath,\n which,\n \"migrations\"\n );\n if (fs.existsSync(migrationPath) === false) {\n fs.mkdirSync(migrationPath, {\n recursive: true,\n });\n }\n const files = fs\n .readdirSync(migrationPath)\n .filter((filename) => filename.startsWith(\".\") === false);\n r[which] = files;\n return r;\n },\n {\n src: [] as string[],\n dist: [] as string[],\n }\n );\n\n const diffOnSrc = _.differenceBy(\n files.src,\n files.dist,\n (filename) => filename.split(\".\")[0]\n );\n if (diffOnSrc.length > 0) {\n throw new Error(\n \"컴파일 되지 않은 파일이 있습니다.\\n\" + diffOnSrc.join(\"\\n\")\n );\n }\n\n const diffOnDist = _.differenceBy(\n files.dist,\n files.src,\n (filename) => filename.split(\".\")[0]\n );\n if (diffOnDist.length > 0) {\n console.log(chalk.red(\"원본 ts파일을 찾을 수 없는 js파일이 있습니다.\"));\n console.log(diffOnDist);\n\n if (!force) {\n const answer = await prompts({\n type: \"confirm\",\n name: \"value\",\n message: \"삭제를 진행하시겠습니까?\",\n initial: true,\n });\n if (answer.value === false) {\n return;\n }\n }\n\n const filesToRm = diffOnDist.map((filename) => {\n return path.join(Sonamu.apiRootPath, \"dist\", \"migrations\", filename);\n });\n filesToRm.map((filePath) => {\n fs.unlinkSync(filePath);\n });\n console.log(chalk.green(`${filesToRm.length}건 삭제되었습니다!`));\n }\n }\n\n async runShadowTest(): Promise<\n {\n connKey: string;\n batchNo: number;\n applied: string[];\n }[]\n > {\n // ShadowDB 생성 후 테스트 진행\n const tdb = knex(Sonamu.dbConfig.test);\n const tdbConn = Sonamu.dbConfig.test.connection as Knex.ConnectionConfig;\n const shadowDatabase = tdbConn.database + \"__migration_shadow\";\n const tmpSqlPath = `/tmp/${shadowDatabase}.sql`;\n\n // 테스트DB 덤프 후 Database명 치환\n console.log(\n chalk.magenta(`${tdbConn.database}의 데이터 ${tmpSqlPath}로 덤프`)\n );\n execSync(\n `mysqldump -h${tdbConn.host} -u${tdbConn.user} -p'${tdbConn.password}' ${tdbConn.database} --single-transaction --no-create-db --triggers > ${tmpSqlPath};`\n );\n execSync(\n `sed -i'' -e 's/\\`${tdbConn.database}\\`/\\`${shadowDatabase}\\`/g' ${tmpSqlPath};`\n );\n\n // 기존 ShadowDB 리셋\n console.log(chalk.magenta(`${shadowDatabase} 리셋`));\n await tdb.raw(`DROP DATABASE IF EXISTS \\`${shadowDatabase}\\`;`);\n await tdb.raw(`CREATE DATABASE \\`${shadowDatabase}\\`;`);\n\n // ShadowDB 테이블 + 데이터 생성\n console.log(chalk.magenta(`${shadowDatabase} 데이터베이스 생성`));\n execSync(\n `mysql -h${tdbConn.host} -u${tdbConn.user} -p'${tdbConn.password}' ${shadowDatabase} < ${tmpSqlPath};`\n );\n\n // tdb 연결 종료\n await tdb.destroy();\n\n // shadow db 테스트 진행\n const sdb = knex({\n ...Sonamu.dbConfig.test,\n connection: {\n ...tdbConn,\n database: shadowDatabase,\n password: tdbConn.password,\n },\n });\n\n try {\n const [batchNo, applied] = await sdb.migrate.latest();\n console.log(chalk.green(\"Shadow DB 테스트에 성공했습니다!\"), {\n batchNo,\n applied,\n });\n\n // 생성한 Shadow DB 삭제\n console.log(chalk.magenta(`${shadowDatabase} 삭제`));\n await sdb.raw(`DROP DATABASE IF EXISTS \\`${shadowDatabase}\\`;`);\n\n return [\n {\n connKey: \"shadow\",\n batchNo,\n applied,\n },\n ];\n } catch (e) {\n console.error(e);\n throw new ServiceUnavailableException(\"Shadow DB 테스트 진행 중 에러\");\n } finally {\n await sdb.destroy();\n }\n }\n\n async resetAll() {\n const answer = await prompts({\n type: \"confirm\",\n name: \"value\",\n message: \"모든 DB를 롤백하고 전체 마이그레이션 파일을 삭제하시겠습니까?\",\n initial: false,\n });\n if (answer.value === false) {\n return;\n }\n\n console.time(chalk.red(\"rollback-all:\"));\n const rollbackAllResult = await Promise.all(\n this.targets.apply.map(async (db) => {\n await db.migrate.forceFreeMigrationsLock();\n return db.migrate.rollback(undefined, true);\n })\n );\n console.log({ rollbackAllResult });\n console.timeEnd(chalk.red(\"rollback-all:\"));\n\n const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n console.time(chalk.red(\"delete migration files\"));\n execSync(`rm -f ${migrationsDir}/*`);\n execSync(`rm -f ${migrationsDir.replace(\"/src/\", \"/dist/\")}/*`);\n console.timeEnd(chalk.red(\"delete migration files\"));\n }\n\n async compareMigrations(compareDB: Knex): Promise<GenMigrationCode[]> {\n // MD 순회하여 싱크\n const entityIds = EntityManager.getAllIds();\n\n // 조인테이블 포함하여 MD에서 MigrationSet 추출\n const entitySetsWithJoinTable = entityIds\n .filter((entityId) => {\n const entity = EntityManager.get(entityId);\n return entity.props.length > 0;\n })\n .map((entityId) => {\n const entity = EntityManager.get(entityId);\n return this.getMigrationSetFromMD(entity);\n });\n\n // 조인테이블만 추출\n const joinTables = _.uniqBy(\n entitySetsWithJoinTable.map((entitySet) => entitySet.joinTables).flat(),\n (joinTable) => {\n return joinTable.table;\n }\n );\n\n // 조인테이블 포함하여 MigrationSet 배열\n const entitySets: MigrationSet[] = [\n ...entitySetsWithJoinTable,\n ...joinTables,\n ];\n\n let codes: GenMigrationCode[] = (\n await Promise.all(\n entitySets.map(async (entitySet) => {\n const dbSet = await this.getMigrationSetFromDB(\n compareDB,\n entitySet.table\n );\n if (dbSet === null) {\n // 기존 테이블 없음, 새로 테이블 생성\n return [\n await this.generateCreateCode_ColumnAndIndexes(\n entitySet.table,\n entitySet.columns,\n entitySet.indexes\n ),\n ...(await this.generateCreateCode_Foreign(\n entitySet.table,\n entitySet.foreigns\n )),\n ];\n }\n\n // 기존 테이블 존재하는 케이스\n const alterCodes: (GenMigrationCode | GenMigrationCode[] | null)[] =\n await Promise.all(\n ([\"columnsAndIndexes\", \"foreigns\"] as const).map((key) => {\n // 배열 원소의 순서가 달라서 불일치가 발생하는걸 방지하기 위해 각 항목별로 정렬 처리 후 비교\n if (key === \"columnsAndIndexes\") {\n const replaceColumnDefaultTo = (col: MigrationColumn) => {\n // float인 경우 기본값을 0으로 지정하는 경우 \"0.00\"으로 변환되는 케이스 대응\n if (\n col.type === \"float\" &&\n col.defaultTo &&\n String(col.defaultTo).includes('\"') === false\n ) {\n col.defaultTo = `\"${Number(col.defaultTo).toFixed(\n col.scale ?? 2\n )}\"`;\n }\n // string인 경우 기본값이 빈 스트링인 경우 대응\n if (col.type === \"string\" && col.defaultTo === \"\") {\n col.defaultTo = '\"\"';\n }\n return col;\n };\n const entityColumns = _.sortBy(\n entitySet.columns,\n (a) => a.name\n ).map(replaceColumnDefaultTo);\n const dbColumns = _.sortBy(dbSet.columns, (a) => a.name).map(\n replaceColumnDefaultTo\n );\n\n /* 디버깅용 코드, 특정 컬럼에서 불일치 발생할 때 확인\n const entityColumn = entitySet.columns.find(\n (col) => col.name === \"price_krw\"\n );\n const dbColumn = dbSet.columns.find(\n (col) => col.name === \"price_krw\"\n );\n console.debug({ entityColumn, dbColumn });\n */\n\n const entityIndexes = _.sortBy(entitySet.indexes, (a) =>\n [\n a.type,\n ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1)),\n ].join(\"-\")\n );\n const dbIndexes = _.sortBy(dbSet.indexes, (a) =>\n [\n a.type,\n ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1)),\n ].join(\"-\")\n );\n\n const isEqualColumns = equal(entityColumns, dbColumns);\n const isEqualIndexes = equal(entityIndexes, dbIndexes);\n if (isEqualColumns && isEqualIndexes) {\n return null;\n } else {\n // this.showMigrationSet(\"MD\", entitySet);\n // this.showMigrationSet(\"DB\", dbSet);\n return this.generateAlterCode_ColumnAndIndexes(\n entitySet.table,\n entityColumns,\n entityIndexes,\n dbColumns,\n dbIndexes\n );\n }\n } else {\n const replaceNoActionOnMySQL = (f: MigrationForeign) => {\n // MySQL에서 RESTRICT와 NO ACTION은 동일함\n const { onDelete, onUpdate } = f;\n return {\n ...f,\n onUpdate:\n onUpdate === \"RESTRICT\" ? \"NO ACTION\" : onUpdate,\n onDelete:\n onDelete === \"RESTRICT\" ? \"NO ACTION\" : onDelete,\n };\n };\n\n const entityForeigns = _.sortBy(entitySet.foreigns, (a) =>\n [a.to, ...a.columns].join(\"-\")\n ).map((f) => replaceNoActionOnMySQL(f));\n const dbForeigns = _.sortBy(dbSet.foreigns, (a) =>\n [a.to, ...a.columns].join(\"-\")\n ).map((f) => replaceNoActionOnMySQL(f));\n\n if (equal(entityForeigns, dbForeigns) === false) {\n // console.dir({ entityForeigns, dbForeigns }, { depth: null });\n return this.generateAlterCode_Foreigns(\n entitySet.table,\n entityForeigns,\n dbForeigns\n );\n }\n }\n return null;\n })\n );\n if (alterCodes.every((alterCode) => alterCode === null)) {\n return null;\n } else {\n return alterCodes.filter((alterCode) => alterCode !== null).flat();\n }\n })\n )\n )\n .flat()\n .filter((code) => code !== null) as GenMigrationCode[];\n\n /*\n normal 타입이 앞으로, foreign 이 뒤로\n */\n codes.sort((codeA, codeB) => {\n if (codeA.type === \"foreign\" && codeB.type == \"normal\") {\n return 1;\n } else if (codeA.type === \"normal\" && codeB.type === \"foreign\") {\n return -1;\n } else {\n return 0;\n }\n });\n\n return codes;\n }\n\n /*\n 기존 테이블 정보 읽어서 MigrationSet 형식으로 리턴\n */\n async getMigrationSetFromDB(\n compareDB: Knex,\n table: string\n ): Promise<MigrationSet | null> {\n let dbColumns: DBColumn[], dbIndexes: DBIndex[], dbForeigns: DBForeign[];\n try {\n [dbColumns, dbIndexes, dbForeigns] = await this.readTable(\n compareDB,\n table\n );\n } catch (e: unknown) {\n if (isKnexError(e) && e.code === \"ER_NO_SUCH_TABLE\") {\n return null;\n }\n console.error(e);\n return null;\n }\n\n const columns: MigrationColumn[] = dbColumns.map((dbColumn) => {\n const dbColType = this.resolveDBColType(dbColumn.Type, dbColumn.Field);\n return {\n name: dbColumn.Field,\n nullable: dbColumn.Null !== \"NO\",\n ...dbColType,\n ...(() => {\n if (dbColumn.Default !== null) {\n return {\n defaultTo: dbColumn.Default,\n };\n }\n return {};\n })(),\n };\n });\n\n const dbIndexesGroup = _.groupBy(\n dbIndexes.filter(\n (dbIndex) =>\n dbIndex.Key_name !== \"PRIMARY\" &&\n !dbForeigns.find(\n (dbForeign) => dbForeign.keyName === dbIndex.Key_name\n )\n ),\n (dbIndex) => dbIndex.Key_name\n );\n\n // indexes 처리\n const indexes: MigrationIndex[] = Object.keys(dbIndexesGroup).map(\n (keyName) => {\n const currentIndexes = dbIndexesGroup[keyName];\n return {\n type: currentIndexes[0].Non_unique === 1 ? \"index\" : \"unique\",\n columns: currentIndexes.map(\n (currentIndex) => currentIndex.Column_name\n ),\n };\n }\n );\n // console.log(table);\n // console.table(dbIndexes);\n // console.table(dbForeigns);\n\n // foreigns 처리\n const foreigns: MigrationForeign[] = dbForeigns.map((dbForeign) => {\n return {\n columns: [dbForeign.from],\n to: `${dbForeign.referencesTable}.${dbForeign.referencesField}`,\n onUpdate: dbForeign.onUpdate as RelationOn,\n onDelete: dbForeign.onDelete as RelationOn,\n };\n });\n\n return {\n table,\n columns,\n indexes,\n foreigns,\n };\n }\n\n resolveDBColType(\n colType: string,\n colField: string\n ): Pick<\n MigrationColumn,\n \"type\" | \"unsigned\" | \"length\" | \"precision\" | \"scale\"\n > {\n let [rawType, unsigned] = colType.split(\" \");\n const matched = rawType.match(/\\(([0-9]+)\\)/);\n let length;\n if (matched !== null && matched[1]) {\n rawType = rawType.replace(/\\(([0-9]+)\\)/, \"\");\n length = parseInt(matched[1]);\n }\n\n if (rawType === \"char\" && colField === \"uuid\") {\n return {\n type: \"uuid\",\n };\n }\n\n switch (rawType) {\n case \"int\":\n return {\n type: \"integer\",\n unsigned: unsigned === \"unsigned\",\n };\n case \"varchar\":\n // case \"char\":\n return {\n type: \"string\",\n ...(length !== undefined && {\n length,\n }),\n };\n case \"text\":\n case \"mediumtext\":\n case \"longtext\":\n case \"timestamp\":\n case \"json\":\n case \"date\":\n case \"time\":\n return {\n type: rawType,\n };\n case \"datetime\":\n return {\n type: \"dateTime\",\n };\n case \"tinyint\":\n return {\n type: \"boolean\",\n };\n default:\n // decimal 처리\n if (rawType.startsWith(\"decimal\")) {\n const [, precision, scale] =\n rawType.match(/decimal\\(([0-9]+),([0-9]+)\\)/) ?? [];\n return {\n type: \"decimal\",\n precision: parseInt(precision),\n scale: parseInt(scale),\n ...(unsigned === \"unsigned\" && {\n unsigned: true,\n }),\n };\n } else if (rawType.startsWith(\"float\")) {\n const [, precision, scale] =\n rawType.match(/float\\(([0-9]+),([0-9]+)\\)/) ?? [];\n return {\n type: \"float\",\n precision: parseInt(precision),\n scale: parseInt(scale),\n ...(unsigned === \"unsigned\" && {\n unsigned: true,\n }),\n };\n }\n throw new Error(`resolve 불가능한 DB컬럼 타입 ${colType} ${rawType}`);\n }\n }\n\n /*\n 기존 테이블 읽어서 cols, indexes 반환\n */\n async readTable(\n compareDB: Knex,\n tableName: string\n ): Promise<[DBColumn[], DBIndex[], DBForeign[]]> {\n // 테이블 정보\n try {\n const [_cols] = (await compareDB.raw(\n `SHOW FIELDS FROM ${tableName}`\n )) as [DBColumn[]];\n const cols = _cols.map((col) => ({\n ...col,\n // Default 값은 숫자나 MySQL Expression이 아닌 경우 \"\"로 감싸줌\n ...(col.Default !== null && {\n Default:\n col.Default.replace(/[0-9]+/g, \"\").length > 0 &&\n col.Extra !== \"DEFAULT_GENERATED\"\n ? `\"${col.Default}\"`\n : col.Default,\n }),\n }));\n\n const [indexes] = await compareDB.raw(`SHOW INDEX FROM ${tableName}`);\n const [[row]] = await compareDB.raw(`SHOW CREATE TABLE ${tableName}`);\n const ddl = row[\"Create Table\"];\n const matched = ddl.match(/CONSTRAINT .+/g);\n const foreignKeys = (matched ?? []).map((line: string) => {\n // 해당 라인을 정규식으로 파싱\n const matched = line.match(\n /CONSTRAINT `(.+)` FOREIGN KEY \\(`(.+)`\\) REFERENCES `(.+)` \\(`(.+)`\\)( ON [A-Z ]+)*/\n );\n if (!matched) {\n throw new Error(`인식할 수 없는 FOREIGN KEY CONSTRAINT ${line}`);\n }\n const [, keyName, from, referencesTable, referencesField, onClause] =\n matched;\n // console.debug({ tableName, line, onClause });\n\n const [onUpdateFull, _onUpdate] =\n (onClause ?? \"\").match(/ON UPDATE ([A-Z ]+)$/) ?? [];\n const onUpdate = _onUpdate ?? \"NO ACTION\";\n\n const onDelete =\n (onClause ?? \"\")\n .replace(onUpdateFull ?? \"\", \"\")\n .match(/ON DELETE ([A-Z ]+) /)?.[1] ?? \"NO ACTION\";\n\n return {\n keyName,\n from,\n referencesTable,\n referencesField,\n onDelete,\n onUpdate,\n };\n });\n return [cols, indexes, foreignKeys];\n } catch (e) {\n throw e;\n }\n }\n\n /*\n MD 내용 읽어서 MigrationSetAndJoinTable 추출\n */\n getMigrationSetFromMD(entity: Entity): MigrationSetAndJoinTable {\n const migrationSet: MigrationSetAndJoinTable = entity.props.reduce(\n (r, prop) => {\n // virtual 필드 제외\n if (isVirtualProp(prop)) {\n return r;\n }\n // HasMany 케이스는 아무 처리도 하지 않음\n if (isHasManyRelationProp(prop)) {\n return r;\n }\n\n // 일반 컬럼\n if (!isRelationProp(prop)) {\n // type resolve\n let type: KnexColumnType;\n if (isTextProp(prop)) {\n type = prop.textType;\n } else if (isEnumProp(prop)) {\n type = \"string\";\n } else {\n type = prop.type as KnexColumnType;\n }\n\n const column = {\n name: prop.name,\n type,\n ...(isIntegerProp(prop) && { unsigned: prop.unsigned === true }),\n ...((isStringProp(prop) || isEnumProp(prop)) && {\n length: prop.length,\n }),\n nullable: prop.nullable === true,\n ...(() => {\n if (prop.dbDefault !== undefined) {\n return {\n defaultTo: prop.dbDefault,\n };\n }\n return {};\n })(),\n // Decimal, Float 타입의 경우 precision, scale 추가\n ...((isDecimalProp(prop) || isFloatProp(prop)) && {\n precision: prop.precision ?? 8,\n scale: prop.scale ?? 2,\n }),\n };\n\n r.columns.push(column);\n }\n\n if (isManyToManyRelationProp(prop)) {\n // ManyToMany 케이스\n const relMd = EntityManager.get(prop.with);\n const [table1, table2] = prop.joinTable.split(\"__\");\n const join = {\n from: `${entity.table}.id`,\n through: {\n from: `${prop.joinTable}.${inflection.singularize(table1)}_id`,\n to: `${prop.joinTable}.${inflection.singularize(table2)}_id`,\n onUpdate: prop.onUpdate,\n onDelete: prop.onDelete,\n },\n to: `${relMd.table}.id`,\n };\n const through = join.through;\n const fields = [through.from, through.to];\n r.joinTables.push({\n table: through.from.split(\".\")[0],\n indexes: [\n {\n type: \"unique\",\n columns: [\"uuid\"],\n },\n // 조인 테이블에 걸린 인덱스 찾아와서 연결\n ...entity.indexes\n .filter((index) =>\n index.columns.find((col) =>\n col.includes(prop.joinTable + \".\")\n )\n )\n .map((index) => ({\n ...index,\n columns: index.columns.map((col) =>\n col.replace(prop.joinTable + \".\", \"\")\n ),\n })),\n ],\n columns: [\n {\n name: \"id\",\n type: \"integer\",\n nullable: false,\n unsigned: true,\n },\n ...fields.map((field) => {\n return {\n name: field.split(\".\")[1],\n type: \"integer\",\n nullable: false,\n unsigned: true,\n } as MigrationColumn;\n }),\n {\n name: \"uuid\",\n nullable: true,\n type: \"uuid\",\n },\n ],\n foreigns: fields.map((field) => {\n return {\n columns: [field.split(\".\")[1]],\n to: through.to.includes(field) ? join.to : join.from,\n onUpdate: through.onUpdate,\n onDelete: through.onDelete,\n };\n }),\n });\n return r;\n } else if (\n isBelongsToOneRelationProp(prop) ||\n (isOneToOneRelationProp(prop) && prop.hasJoinColumn)\n ) {\n // -OneRelation 케이스\n const idColumnName = prop.name + \"_id\";\n r.columns.push({\n name: idColumnName,\n type: \"integer\",\n unsigned: true,\n nullable: prop.nullable ?? false,\n });\n r.foreigns.push({\n columns: [idColumnName],\n to: `${inflection.underscore(inflection.pluralize(prop.with)).toLowerCase()}.id`,\n onUpdate: prop.onUpdate,\n onDelete: prop.onDelete,\n });\n }\n\n return r;\n },\n {\n table: entity.table,\n columns: [] as MigrationColumn[],\n indexes: [] as MigrationIndex[],\n foreigns: [] as MigrationForeign[],\n joinTables: [] as MigrationJoinTable[],\n }\n );\n\n // indexes\n migrationSet.indexes = entity.indexes.filter((index) =>\n index.columns.find((col) => col.includes(\".\") === false)\n );\n\n // uuid\n migrationSet.columns = migrationSet.columns.concat({\n name: \"uuid\",\n nullable: true,\n type: \"uuid\",\n } as MigrationColumn);\n migrationSet.indexes = migrationSet.indexes.concat({\n type: \"unique\",\n columns: [\"uuid\"],\n } as MigrationIndex);\n\n return migrationSet;\n }\n\n /*\n MigrationColumn[] 읽어서 컬럼 정의하는 구문 생성\n*/\n genColumnDefinitions(columns: MigrationColumn[]): string[] {\n return columns.map((column) => {\n const chains: string[] = [];\n if (column.name === \"id\") {\n return `table.increments().primary();`;\n }\n\n if (column.type === \"float\" || column.type === \"decimal\") {\n chains.push(\n `${column.type}('${column.name}', ${column.precision}, ${column.scale})`\n );\n } else {\n // type, length\n let columnType = column.type;\n let extraType: string | undefined;\n if (columnType.includes(\"text\") && columnType !== \"text\") {\n extraType = columnType;\n columnType = \"text\";\n }\n chains.push(\n `${column.type}('${column.name}'${\n column.length ? `, ${column.length}` : \"\"\n }${extraType ? `, '${extraType}'` : \"\"})`\n );\n }\n if (column.unsigned) {\n chains.push(\"unsigned()\");\n }\n\n // nullable\n chains.push(column.nullable ? \"nullable()\" : \"notNullable()\");\n\n // defaultTo\n if (column.defaultTo !== undefined) {\n if (\n typeof column.defaultTo === \"string\" &&\n column.defaultTo.startsWith(`\"`)\n ) {\n chains.push(`defaultTo(${column.defaultTo})`);\n } else {\n chains.push(`defaultTo(knex.raw('${column.defaultTo}'))`);\n }\n }\n\n return `table.${chains.join(\".\")};`;\n });\n }\n\n /*\n MigrationIndex[] 읽어서 인덱스/유니크 정의하는 구문 생성\n*/\n genIndexDefinitions(indexes: MigrationIndex[]): string[] {\n if (indexes.length === 0) {\n return [];\n }\n const lines = _.uniq(\n indexes.reduce((r, index) => {\n r.push(\n `table.${index.type}([${index.columns\n .map((col) => `'${col}'`)\n .join(\",\")}])`\n );\n return r;\n }, [] as string[])\n );\n return lines;\n }\n\n /*\n MigrationForeign[] 읽어서 외부키 constraint 정의하는 구문 생성\n */\n genForeignDefinitions(\n table: string,\n foreigns: MigrationForeign[]\n ): { up: string[]; down: string[] } {\n return foreigns.reduce(\n (r, foreign) => {\n const columnsStringQuote = foreign.columns\n .map((col) => `'${col.replace(`${table}.`, \"\")}'`)\n .join(\",\");\n r.up.push(\n `table.foreign('${foreign.columns.join(\",\")}')\n .references('${foreign.to}')\n .onUpdate('${foreign.onUpdate}')\n .onDelete('${foreign.onDelete}')`\n );\n r.down.push(`table.dropForeign([${columnsStringQuote}])`);\n return r;\n },\n {\n up: [] as string[],\n down: [] as string[],\n }\n );\n }\n\n /*\n 테이블 생성하는 케이스 - 컬럼/인덱스 생성\n */\n async generateCreateCode_ColumnAndIndexes(\n table: string,\n columns: MigrationColumn[],\n indexes: MigrationIndex[]\n ): Promise<GenMigrationCode> {\n // 컬럼, 인덱스 처리\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `return knex.schema.createTable(\"${table}\", (table) => {`,\n \"// columns\",\n ...this.genColumnDefinitions(columns),\n \"\",\n \"// indexes\",\n ...this.genIndexDefinitions(indexes),\n \"});\",\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n ` return knex.schema.dropTable(\"${table}\");`,\n \"}\",\n ];\n return {\n table,\n type: \"normal\",\n title: `create__${table}`,\n formatted: await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n }),\n };\n }\n /*\n 테이블 생성하는 케이스 - FK 생성\n*/\n async generateCreateCode_Foreign(\n table: string,\n foreigns: MigrationForeign[]\n ): Promise<GenMigrationCode[]> {\n if (foreigns.length === 0) {\n return [];\n }\n\n const { up, down } = this.genForeignDefinitions(table, foreigns);\n if (up.length === 0 && down.length === 0) {\n console.log(\"fk 가 뭔가 다릅니다\");\n return [];\n }\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n \"// create fk\",\n ...up,\n \"});\",\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n \"// drop fk\",\n ...down,\n \"});\",\n \"}\",\n ];\n\n const foreignKeysString = foreigns\n .map((foreign) => foreign.columns.join(\"_\"))\n .join(\"_\");\n return [\n {\n table,\n type: \"foreign\",\n title: `foreign__${table}__${foreignKeysString}`,\n formatted: await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n }),\n },\n ];\n }\n\n /*\n 마이그레이션 컬럼 배열 비교용 코드\n */\n showMigrationSet(which: string, migrationSet: MigrationSet): void {\n const { columns, indexes, foreigns } = migrationSet;\n const styledChalk =\n which === \"MD\" ? chalk.bgGreen.black : chalk.bgBlue.black;\n console.log(\n styledChalk(\n `${which} ${migrationSet.table} Columns\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`\n )\n );\n console.table(\n columns.map((column) => {\n return {\n ..._.pick(column, [\n \"name\",\n \"type\",\n \"nullable\",\n \"unsigned\",\n \"length\",\n \"defaultTo\",\n \"precision\",\n \"scale\",\n ]),\n };\n }),\n [\n \"name\",\n \"type\",\n \"nullable\",\n \"unsigned\",\n \"length\",\n \"defaultTo\",\n \"precision\",\n \"scale\",\n ]\n );\n\n if (indexes.length > 0) {\n console.log(\n styledChalk(\n `${which} ${migrationSet.table} Indexes\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`\n )\n );\n console.table(\n indexes.map((index) => {\n return {\n ..._.pick(index, [\"type\", \"columns\", \"name\"]),\n };\n })\n );\n }\n\n if (foreigns.length > 0) {\n console.log(\n chalk.bgMagenta.black(\n `${which} ${migrationSet.table} Foreigns\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`\n )\n );\n console.table(\n foreigns.map((foreign) => {\n return {\n ..._.pick(foreign, [\"columns\", \"to\", \"onUpdate\", \"onDelete\"]),\n };\n })\n );\n }\n }\n\n async generateAlterCode_ColumnAndIndexes(\n table: string,\n entityColumns: MigrationColumn[],\n entityIndexes: MigrationIndex[],\n dbColumns: MigrationColumn[],\n dbIndexes: MigrationIndex[]\n ): Promise<GenMigrationCode[]> {\n /*\n 세부 비교 후 다른점 찾아서 코드 생성\n\n 1. 컬럼갯수 다름: MD에 있으나, DB에 없다면 추가\n 2. 컬럼갯수 다름: MD에 없으나, DB에 있다면 삭제\n 3. 그외 컬럼(컬럼 갯수가 동일하거나, 다른 경우 동일한 컬럼끼리) => alter\n 4. 다른거 다 동일하고 index만 변경되는 경우\n\n ** 컬럼명을 변경하는 경우는 따로 핸들링하지 않음\n => drop/add 형태의 마이그레이션 코드가 생성되는데, 수동으로 rename 코드로 수정하여 처리\n */\n\n // 각 컬럼 이름 기준으로 add, drop, alter 여부 확인\n const alterColumnsTo = this.getAlterColumnsTo(entityColumns, dbColumns);\n\n // 추출된 컬럼들을 기준으로 각각 라인 생성\n const alterColumnLinesTo = this.getAlterColumnLinesTo(\n alterColumnsTo,\n entityColumns\n );\n\n // 인덱스의 add, drop 여부 확인\n const alterIndexesTo = this.getAlterIndexesTo(entityIndexes, dbIndexes);\n\n // 추출된 인덱스들을 기준으로 각각 라인 생성\n const alterIndexLinesTo = this.getAlterIndexLinesTo(\n alterIndexesTo,\n alterColumnsTo\n );\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...(alterColumnsTo.add.length > 0 ? alterColumnLinesTo.add.up : []),\n ...(alterColumnsTo.drop.length > 0 ? alterColumnLinesTo.drop.up : []),\n ...(alterColumnsTo.alter.length > 0 ? alterColumnLinesTo.alter.up : []),\n ...(alterIndexesTo.add.length > 0 ? alterIndexLinesTo.add.up : []),\n ...(alterIndexesTo.drop.length > 0 ? alterIndexLinesTo.drop.up : []),\n \"})\",\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...(alterColumnsTo.add.length > 0 ? alterColumnLinesTo.add.down : []),\n ...(alterColumnsTo.drop.length > 0 ? alterColumnLinesTo.drop.down : []),\n ...(alterColumnsTo.alter.length > 0 ? alterColumnLinesTo.alter.down : []),\n ...(alterIndexLinesTo.add.down.length > 0\n ? alterIndexLinesTo.add.down\n : []),\n ...(alterIndexLinesTo.drop.down.length > 0\n ? alterIndexLinesTo.drop.down\n : []),\n \"})\",\n \"}\",\n ];\n\n const formatted = await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n });\n\n const title = [\n \"alter\",\n table,\n ...([\"add\", \"drop\", \"alter\"] as const)\n .map((action) => {\n const len = alterColumnsTo[action].length;\n if (len > 0) {\n return action + len;\n }\n return null;\n })\n .filter((part) => part !== null),\n ].join(\"_\");\n\n return [\n {\n table,\n title,\n formatted,\n type: \"normal\",\n },\n ];\n }\n\n getAlterColumnsTo(\n entityColumns: MigrationColumn[],\n dbColumns: MigrationColumn[]\n ) {\n const columnsTo = {\n add: [] as MigrationColumn[],\n drop: [] as MigrationColumn[],\n alter: [] as MigrationColumn[],\n };\n\n // 컬럼명 기준 비교\n const extraColumns = {\n db: _.differenceBy(dbColumns, entityColumns, (col) => col.name),\n entity: _.differenceBy(entityColumns, dbColumns, (col) => col.name),\n };\n if (extraColumns.entity.length > 0) {\n columnsTo.add = columnsTo.add.concat(extraColumns.entity);\n }\n if (extraColumns.db.length > 0) {\n columnsTo.drop = columnsTo.drop.concat(extraColumns.db);\n }\n\n // 동일 컬럼명의 세부 필드 비교\n const sameDbColumns = _.intersectionBy(\n dbColumns,\n entityColumns,\n (col) => col.name\n );\n const sameMdColumns = _.intersectionBy(\n entityColumns,\n dbColumns,\n (col) => col.name\n );\n columnsTo.alter = _.differenceWith(sameDbColumns, sameMdColumns, (a, b) =>\n equal(a, b)\n );\n\n return columnsTo;\n }\n\n getAlterColumnLinesTo(\n columnsTo: ReturnType<Migrator[\"getAlterColumnsTo\"]>,\n entityColumns: MigrationColumn[]\n ) {\n let linesTo = {\n add: {\n up: [] as string[],\n down: [] as string[],\n },\n drop: {\n up: [] as string[],\n down: [] as string[],\n },\n alter: {\n up: [] as string[],\n down: [] as string[],\n },\n };\n\n linesTo.add = {\n up: [\"// add\", ...this.genColumnDefinitions(columnsTo.add)],\n down: [\n \"// rollback - add\",\n `table.dropColumns(${columnsTo.add\n .map((col) => `'${col.name}'`)\n .join(\", \")})`,\n ],\n };\n linesTo.drop = {\n up: [\n \"// drop\",\n `table.dropColumns(${columnsTo.drop\n .map((col) => `'${col.name}'`)\n .join(\", \")})`,\n ],\n down: [\n \"// rollback - drop\",\n ...this.genColumnDefinitions(columnsTo.drop),\n ],\n };\n linesTo.alter = columnsTo.alter.reduce(\n (r, dbColumn) => {\n const entityColumn = entityColumns.find(\n (col) => col.name == dbColumn.name\n );\n if (entityColumn === undefined) {\n return r;\n }\n\n // 컬럼 변경사항\n const columnDiffUp = _.difference(\n this.genColumnDefinitions([entityColumn]),\n this.genColumnDefinitions([dbColumn])\n );\n const columnDiffDown = _.difference(\n this.genColumnDefinitions([dbColumn]),\n this.genColumnDefinitions([entityColumn])\n );\n if (columnDiffUp.length > 0) {\n r.up = [\n ...r.up,\n \"// alter column\",\n ...columnDiffUp.map((l) => l.replace(\";\", \"\") + \".alter();\"),\n ];\n r.down = [\n ...r.down,\n \"// rollback - alter column\",\n ...columnDiffDown.map((l) => l.replace(\";\", \"\") + \".alter();\"),\n ];\n }\n\n return r;\n },\n {\n up: [] as string[],\n down: [] as string[],\n }\n );\n\n return linesTo;\n }\n\n getAlterIndexesTo(\n entityIndexes: MigrationIndex[],\n dbIndexes: MigrationIndex[]\n ) {\n // 인덱스 비교\n let indexesTo = {\n add: [] as MigrationIndex[],\n drop: [] as MigrationIndex[],\n };\n const extraIndexes = {\n db: _.differenceBy(dbIndexes, entityIndexes, (col) =>\n [col.type, col.columns.join(\"-\")].join(\"//\")\n ),\n entity: _.differenceBy(entityIndexes, dbIndexes, (col) =>\n [col.type, col.columns.join(\"-\")].join(\"//\")\n ),\n };\n if (extraIndexes.entity.length > 0) {\n indexesTo.add = indexesTo.add.concat(extraIndexes.entity);\n }\n if (extraIndexes.db.length > 0) {\n indexesTo.drop = indexesTo.drop.concat(extraIndexes.db);\n }\n\n return indexesTo;\n }\n\n getAlterIndexLinesTo(\n indexesTo: ReturnType<Migrator[\"getAlterIndexesTo\"]>,\n columnsTo: ReturnType<Migrator[\"getAlterColumnsTo\"]>\n ) {\n let linesTo = {\n add: {\n up: [] as string[],\n down: [] as string[],\n },\n drop: {\n up: [] as string[],\n down: [] as string[],\n },\n };\n\n // 인덱스가 추가되는 경우, 컬럼과 같이 추가된 케이스에는 drop에서 제외해야함!\n linesTo.add = {\n up: [\"// add indexes\", ...this.genIndexDefinitions(indexesTo.add)],\n down: [\n \"// rollback - add indexes\",\n ...indexesTo.add\n .filter(\n (index) =>\n index.columns.every((colName) =>\n columnsTo.add.map((col) => col.name).includes(colName)\n ) === false\n )\n .map(\n (index) =>\n `table.drop${inflection.capitalize(index.type)}([${index.columns\n .map((columnName) => `'${columnName}'`)\n .join(\",\")}])`\n ),\n ],\n };\n // 인덱스가 삭제되는 경우, 컬럼과 같이 삭제된 케이스에는 drop에서 제외해야함!\n linesTo.drop = {\n up: [\n ...indexesTo.drop\n .filter(\n (index) =>\n index.columns.every((colName) =>\n columnsTo.drop.map((col) => col.name).includes(colName)\n ) === false\n )\n .map(\n (index) =>\n `table.drop${inflection.capitalize(index.type)}([${index.columns\n .map((columnName) => `'${columnName}'`)\n .join(\",\")}])`\n ),\n ],\n down: [\n \"// rollback - drop indexes\",\n ...this.genIndexDefinitions(indexesTo.drop),\n ],\n };\n\n return linesTo;\n }\n\n async generateAlterCode_Foreigns(\n table: string,\n entityForeigns: MigrationForeign[],\n dbForeigns: MigrationForeign[]\n ): Promise<GenMigrationCode[]> {\n // console.log({ entityForeigns, dbForeigns });\n\n const getKey = (mf: MigrationForeign): string => {\n return [mf.columns.join(\"-\"), mf.to].join(\"///\");\n };\n const fkTo = entityForeigns.reduce(\n (result, entityF) => {\n const matchingDbF = dbForeigns.find(\n (dbF) => getKey(entityF) === getKey(dbF)\n );\n if (!matchingDbF) {\n result.add.push(entityF);\n return result;\n }\n\n if (equal(entityF, matchingDbF) === false) {\n result.alterSrc.push(matchingDbF);\n result.alterDst.push(entityF);\n return result;\n }\n return result;\n },\n {\n add: [] as MigrationForeign[],\n alterSrc: [] as MigrationForeign[],\n alterDst: [] as MigrationForeign[],\n }\n );\n\n const linesTo = {\n add: this.genForeignDefinitions(table, fkTo.add),\n alterSrc: this.genForeignDefinitions(table, fkTo.alterSrc),\n alterDst: this.genForeignDefinitions(table, fkTo.alterDst),\n };\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...linesTo.add.up,\n ...linesTo.alterSrc.down,\n ...linesTo.alterDst.up,\n \"})\",\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...linesTo.add.down,\n ...linesTo.alterDst.down,\n ...linesTo.alterSrc.up,\n \"})\",\n \"}\",\n ];\n\n const formatted = await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n });\n\n const title = [\n \"alter\",\n table,\n \"foreigns\",\n // TODO 바뀌는 부분\n ].join(\"_\");\n\n return [\n {\n table,\n title,\n formatted,\n type: \"normal\",\n },\n ];\n }\n\n async destroy(): Promise<void> {\n await Promise.all(\n this.targets.apply.map((db) => {\n return db.destroy();\n })\n );\n }\n}\n\ntype DBColumn = {\n Field: string;\n Type: string;\n Null: string;\n Key: string;\n Default: string | null;\n Extra: string;\n};\ntype DBIndex = {\n Table: string;\n Non_unique: number;\n Key_name: string;\n Seq_in_index: number;\n Column_name: string;\n Collation: string | null;\n Cardinality: number | null;\n Sub_part: number | null;\n Packed: string | null;\n Null: string;\n Index_type: string;\n Comment: string;\n Index_comment: string;\n Visible: string;\n Expression: string | null;\n};\ntype DBForeign = {\n keyName: string;\n from: string;\n referencesTable: string;\n referencesField: string;\n onDelete: string;\n onUpdate: string;\n};\n","import chalk from \"chalk\";\nimport knex, { Knex } from \"knex\";\nimport _ from \"lodash\";\nimport { Sonamu } from \"../api\";\nimport { BaseModel } from \"../database/base-model\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport {\n EntityProp,\n FixtureImportResult,\n FixtureRecord,\n FixtureSearchOptions,\n ManyToManyRelationProp,\n isBelongsToOneRelationProp,\n isHasManyRelationProp,\n isManyToManyRelationProp,\n isOneToOneRelationProp,\n isRelationProp,\n isVirtualProp,\n} from \"../types/types\";\nimport { Entity } from \"../entity/entity\";\nimport inflection from \"inflection\";\nimport { SonamuDBConfig } from \"../database/db\";\nimport { readFileSync, writeFileSync } from \"fs\";\n\nexport class FixtureManagerClass {\n private _tdb: Knex | null = null;\n set tdb(tdb: Knex) {\n this._tdb = tdb;\n }\n get tdb(): Knex {\n if (this._tdb === null) {\n throw new Error(\"FixtureManager has not been initialized\");\n }\n return this._tdb;\n }\n\n private _fdb: Knex | null = null;\n set fdb(fdb: Knex) {\n this._fdb = fdb;\n }\n get fdb(): Knex {\n if (this._fdb === null) {\n throw new Error(\"FixtureManager has not been initialized\");\n }\n return this._fdb;\n }\n\n private dependencyGraph: Map<\n string,\n {\n fixtureId: string;\n entityId: string;\n dependencies: Set<string>;\n }\n > = new Map();\n\n init() {\n if (this._tdb !== null) {\n return;\n }\n if (Sonamu.dbConfig.test && Sonamu.dbConfig.production_master) {\n const tConn = Sonamu.dbConfig.test.connection as Knex.ConnectionConfig & {\n port?: number;\n };\n const pConn = Sonamu.dbConfig.production_master\n .connection as Knex.ConnectionConfig & { port?: number };\n if (\n `${tConn.host ?? \"localhost\"}:${tConn.port ?? 3306}/${\n tConn.database\n }` ===\n `${pConn.host ?? \"localhost\"}:${pConn.port ?? 3306}/${pConn.database}`\n ) {\n throw new Error(\n `테스트DB와 프로덕션DB에 동일한 데이터베이스가 사용되었습니다.`\n );\n }\n }\n\n this.tdb = knex(Sonamu.dbConfig.test);\n this.fdb = knex(Sonamu.dbConfig.fixture_local);\n }\n\n async cleanAndSeed(usingTables?: string[]) {\n const tableNames = await (async () => {\n if (usingTables) {\n return usingTables;\n }\n\n const [tables] = await this.tdb.raw(\n \"SHOW TABLE STATUS WHERE Engine IS NOT NULL\"\n );\n return tables.map((tableInfo: any) => tableInfo[\"Name\"] as string);\n })();\n\n await this.tdb.raw(`SET FOREIGN_KEY_CHECKS = 0`);\n for await (let tableName of tableNames) {\n if (tableName == \"migrations\") {\n continue;\n }\n\n const [[fdbChecksumRow]] = await this.fdb.raw(\n `CHECKSUM TABLE ${tableName}`\n );\n const fdbChecksum = fdbChecksumRow[\"Checksum\"];\n\n const [[tdbChecksumRow]] = await this.tdb.raw(\n `CHECKSUM TABLE ${tableName}`\n );\n const tdbChecksum = tdbChecksumRow[\"Checksum\"];\n\n if (fdbChecksum !== tdbChecksum) {\n await this.tdb(tableName).truncate();\n const rawQuery = `INSERT INTO ${\n (Sonamu.dbConfig.test.connection as Knex.ConnectionConfig).database\n }.${tableName}\n SELECT * FROM ${\n (\n Sonamu.dbConfig.fixture_local\n .connection as Knex.ConnectionConfig\n ).database\n }.${tableName}`;\n await this.tdb.raw(rawQuery);\n }\n }\n await this.tdb.raw(`SET FOREIGN_KEY_CHECKS = 1`);\n\n // console.timeEnd(\"FIXTURE-CleanAndSeed\");\n }\n\n async getChecksum(db: Knex, tableName: string) {\n const [[checksumRow]] = await db.raw(`CHECKSUM TABLE ${tableName}`);\n return checksumRow.Checksum;\n }\n\n async sync() {\n const frdb = knex(Sonamu.dbConfig.fixture_remote);\n\n const [tables] = await this.fdb.raw(\n \"SHOW TABLE STATUS WHERE Engine IS NOT NULL\"\n );\n const tableNames: string[] = tables.map(\n (table: any) => table.Name as string\n );\n\n console.log(chalk.magenta(\"SYNC...\"));\n await Promise.all(\n tableNames.map(async (tableName) => {\n if (tableName.startsWith(\"knex_migrations\")) {\n return;\n }\n\n const remoteChecksum = await this.getChecksum(frdb, tableName);\n const localChecksum = await this.getChecksum(this.fdb, tableName);\n\n if (remoteChecksum !== localChecksum) {\n await this.fdb.transaction(async (transaction) => {\n await transaction.raw(`SET FOREIGN_KEY_CHECKS = 0`);\n await transaction(tableName).truncate();\n\n const rows = await frdb(tableName);\n if (rows.length === 0) {\n return;\n }\n\n console.log(chalk.blue(tableName), rows.length);\n await transaction\n .insert(\n rows.map((row) => {\n Object.keys(row).map((key) => {\n if (Array.isArray(row[key])) {\n row[key] = JSON.stringify(row[key]);\n }\n });\n return row;\n })\n )\n .into(tableName);\n console.log(\"OK\");\n await transaction.raw(`SET FOREIGN_KEY_CHECKS = 1`);\n });\n }\n })\n );\n console.log(chalk.magenta(\"DONE!\"));\n\n await frdb.destroy();\n }\n\n async importFixture(entityId: string, ids: number[]) {\n const queries = _.uniq(\n (\n await Promise.all(\n ids.map(async (id) => {\n return await this.getImportQueries(entityId, \"id\", id);\n })\n )\n ).flat()\n );\n\n const wdb = BaseModel.getDB(\"w\");\n for (let query of queries) {\n const [rsh] = await wdb.raw(query);\n console.log({\n query,\n info: rsh.info,\n });\n }\n }\n\n async getImportQueries(\n entityId: string,\n field: string,\n id: number\n ): Promise<string[]> {\n console.log({ entityId, field, id });\n const entity = EntityManager.get(entityId);\n const wdb = BaseModel.getDB(\"w\");\n\n // 여기서 실DB의 row 가져옴\n const [row] = await wdb(entity.table).where(field, id).limit(1);\n if (row === undefined) {\n throw new Error(`${entityId}#${id} row를 찾을 수 없습니다.`);\n }\n\n // 픽스쳐DB, 실DB\n const fixtureDatabase = (Sonamu.dbConfig.fixture_remote.connection as any)\n .database;\n const realDatabase = (Sonamu.dbConfig.production_master.connection as any)\n .database;\n\n const selfQuery = `INSERT IGNORE INTO \\`${fixtureDatabase}\\`.\\`${entity.table}\\` (SELECT * FROM \\`${realDatabase}\\`.\\`${entity.table}\\` WHERE \\`id\\` = ${id})`;\n\n const args = Object.entries(entity.relations)\n .filter(\n ([, relation]) =>\n isBelongsToOneRelationProp(relation) ||\n (isOneToOneRelationProp(relation) &&\n relation.customJoinClause === undefined)\n )\n .map(([, relation]) => {\n /*\n BelongsToOne인 경우\n Category / 'id' / row[category_id] 호출\n OneToOne에 joinColumn === true 인 경우\n Profile / 'id' / row[profile_id] 호출\n OneToOne에 joinColumn === false 인 경우\n Profile / 'profile_id' / row['id'] 호출\n */\n let field: string;\n let id: number;\n if (isOneToOneRelationProp(relation) && !relation.hasJoinColumn) {\n field = `${relation.name}_id`;\n id = row[\"id\"];\n } else {\n field = \"id\";\n id = row[`${relation.name}_id`];\n }\n return {\n entityId: relation.with,\n field,\n id,\n };\n })\n .filter((arg) => arg.id !== null);\n\n const relQueries = await Promise.all(\n args.map(async (args) => {\n return this.getImportQueries(args.entityId, args.field, args.id);\n })\n );\n\n return [..._.uniq(relQueries.reverse().flat()), selfQuery];\n }\n\n async destory() {\n if (this._tdb) {\n await this._tdb.destroy();\n this._tdb = null;\n }\n if (this._fdb) {\n await this._fdb.destroy();\n this._fdb = null;\n }\n await BaseModel.destroy();\n }\n\n async getFixtures(\n sourceDBName: keyof SonamuDBConfig,\n targetDBName: keyof SonamuDBConfig,\n searchOptions: FixtureSearchOptions\n ) {\n const sourceDB = knex(Sonamu.dbConfig[sourceDBName]);\n const targetDB = knex(Sonamu.dbConfig[targetDBName]);\n const { entityId, field, value, searchType } = searchOptions;\n\n const entity = EntityManager.get(entityId);\n const column =\n entity.props.find((prop) => prop.name === field)?.type === \"relation\"\n ? `${field}_id`\n : field;\n\n let query = sourceDB(entity.table);\n if (searchType === \"equals\") {\n query = query.where(column, value);\n } else if (searchType === \"like\") {\n query = query.where(column, \"like\", `%${value}%`);\n }\n\n const rows = await query;\n if (rows.length === 0) {\n throw new Error(\"No records found\");\n }\n\n const fixtures: FixtureRecord[] = [];\n for (const row of rows) {\n const initialRecordsLength = fixtures.length;\n const newRecords = await this.createFixtureRecord(entity, row);\n fixtures.push(...newRecords);\n const currentFixtureRecord = fixtures.find(\n (r) => r.fixtureId === `${entityId}#${row.id}`\n );\n\n if (currentFixtureRecord) {\n // 현재 fixture로부터 생성된 fetchedRecords 설정\n currentFixtureRecord.fetchedRecords = fixtures\n .filter((r) => r.fixtureId !== currentFixtureRecord.fixtureId)\n .slice(initialRecordsLength)\n .map((r) => r.fixtureId);\n }\n }\n\n for await (const fixture of fixtures) {\n const entity = EntityManager.get(fixture.entityId);\n\n // targetDB에 해당 레코드가 존재하는지 확인\n const row = await targetDB(entity.table).where(\"id\", fixture.id).first();\n if (row) {\n const [record] = await this.createFixtureRecord(entity, row, {\n singleRecord: true,\n _db: targetDB,\n });\n fixture.target = record;\n continue;\n }\n\n // targetDB에 해당 레코드가 존재하지 않는 경우, unique 제약을 위반하는지 확인\n const uniqueRow = await this.checkUniqueViolation(\n targetDB,\n entity,\n fixture\n );\n if (uniqueRow) {\n const [record] = await this.createFixtureRecord(entity, uniqueRow, {\n singleRecord: true,\n _db: targetDB,\n });\n fixture.unique = record;\n }\n }\n\n return fixtures;\n }\n\n async createFixtureRecord(\n entity: Entity,\n row: any,\n options?: {\n singleRecord?: boolean;\n _db?: Knex;\n },\n visitedEntities = new Set<string>()\n ): Promise<FixtureRecord[]> {\n const fixtureId = `${entity.id}#${row.id}`;\n if (visitedEntities.has(fixtureId)) {\n return [];\n }\n visitedEntities.add(fixtureId);\n\n const records: FixtureRecord[] = [];\n const record: FixtureRecord = {\n fixtureId,\n entityId: entity.id,\n id: row.id,\n columns: {},\n fetchedRecords: [],\n belongsRecords: [],\n };\n\n for (const prop of entity.props) {\n if (isVirtualProp(prop)) {\n continue;\n }\n\n record.columns[prop.name] = {\n prop: prop,\n value: row[prop.name],\n };\n\n const db = options?._db ?? BaseModel.getDB(\"w\");\n if (isManyToManyRelationProp(prop)) {\n const relatedEntity = EntityManager.get(prop.with);\n const throughTable = prop.joinTable;\n const fromColumn = `${inflection.singularize(entity.table)}_id`;\n const toColumn = `${inflection.singularize(relatedEntity.table)}_id`;\n\n const relatedIds = await db(throughTable)\n .where(fromColumn, row.id)\n .pluck(toColumn);\n record.columns[prop.name].value = relatedIds;\n } else if (isHasManyRelationProp(prop)) {\n const relatedEntity = EntityManager.get(prop.with);\n const relatedIds = await db(relatedEntity.table)\n .where(prop.joinColumn, row.id)\n .pluck(\"id\");\n record.columns[prop.name].value = relatedIds;\n } else if (isOneToOneRelationProp(prop) && !prop.hasJoinColumn) {\n const relatedEntity = EntityManager.get(prop.with);\n const relatedProp = relatedEntity.props.find(\n (p) => p.type === \"relation\" && p.with === entity.id\n );\n if (relatedProp) {\n const relatedRow = await db(relatedEntity.table)\n .where(\"id\", row.id)\n .first();\n record.columns[prop.name].value = relatedRow?.id;\n }\n } else if (isRelationProp(prop)) {\n const relatedId = row[`${prop.name}_id`];\n record.columns[prop.name].value = relatedId;\n if (relatedId) {\n record.belongsRecords.push(`${prop.with}#${relatedId}`);\n }\n if (!options?.singleRecord && relatedId) {\n const relatedEntity = EntityManager.get(prop.with);\n const relatedRow = await db(relatedEntity.table)\n .where(\"id\", relatedId)\n .first();\n if (relatedRow) {\n const newRecords = await this.createFixtureRecord(\n relatedEntity,\n relatedRow,\n options,\n visitedEntities\n );\n records.push(...newRecords);\n }\n }\n }\n }\n\n records.push(record);\n return records;\n }\n\n async insertFixtures(\n dbName: keyof SonamuDBConfig,\n _fixtures: FixtureRecord[]\n ) {\n const fixtures = _.uniqBy(_fixtures, (f) => f.fixtureId);\n\n this.buildDependencyGraph(fixtures);\n const insertionOrder = this.getInsertionOrder();\n const db = knex(Sonamu.dbConfig[dbName]);\n\n await db.transaction(async (trx) => {\n await trx.raw(`SET FOREIGN_KEY_CHECKS = 0`);\n\n for (const fixtureId of insertionOrder) {\n const fixture = fixtures.find((f) => f.fixtureId === fixtureId)!;\n const result = await this.insertFixture(trx, fixture);\n if (result.id !== fixture.id) {\n // ID가 변경된 경우, 다른 fixture에서 참조하는 경우가 찾아서 수정\n console.log(\n chalk.yellow(\n `Unique constraint violation: ${fixture.entityId}#${fixture.id} -> ${fixture.entityId}#${result.id}`\n )\n );\n fixtures.forEach((f) => {\n Object.values(f.columns).forEach((column) => {\n if (\n column.prop.type === \"relation\" &&\n column.prop.with === result.entityId &&\n column.value === fixture.id\n ) {\n column.value = result.id;\n }\n });\n });\n fixture.id = result.id;\n }\n }\n\n for (const fixtureId of insertionOrder) {\n const fixture = fixtures.find((f) => f.fixtureId === fixtureId)!;\n await this.handleManyToManyRelations(trx, fixture, fixtures);\n }\n await trx.raw(`SET FOREIGN_KEY_CHECKS = 1`);\n });\n\n const records: FixtureImportResult[] = [];\n\n for await (const r of fixtures) {\n const entity = EntityManager.get(r.entityId);\n const record = await db(entity.table).where(\"id\", r.id).first();\n records.push({\n entityId: r.entityId,\n data: record,\n });\n }\n\n return _.uniqBy(records, (r) => `${r.entityId}#${r.data.id}`);\n }\n\n private getInsertionOrder() {\n const visited = new Set<string>();\n const order: string[] = [];\n const tempVisited = new Set<string>();\n\n const visit = (fixtureId: string) => {\n if (visited.has(fixtureId)) return;\n if (tempVisited.has(fixtureId)) {\n console.warn(`Circular dependency detected involving: ${fixtureId}`);\n return;\n }\n\n tempVisited.add(fixtureId);\n\n const node = this.dependencyGraph.get(fixtureId)!;\n const entity = EntityManager.get(node.entityId);\n\n for (const depId of node.dependencies) {\n const depNode = this.dependencyGraph.get(depId)!;\n\n // BelongsToOne 관계이면서 nullable이 아닌 경우 먼저 방문\n const relationProp = entity.props.find(\n (prop) =>\n isRelationProp(prop) &&\n (isBelongsToOneRelationProp(prop) ||\n (isOneToOneRelationProp(prop) && prop.hasJoinColumn)) &&\n prop.with === depNode.entityId\n );\n if (relationProp && !relationProp.nullable) {\n visit(depId);\n }\n }\n\n tempVisited.delete(fixtureId);\n visited.add(fixtureId);\n order.push(fixtureId);\n };\n\n for (const fixtureId of this.dependencyGraph.keys()) {\n visit(fixtureId);\n }\n\n // circular dependency로 인해 방문되지 않은 fixtureId 추가\n for (const fixtureId of this.dependencyGraph.keys()) {\n if (!visited.has(fixtureId)) {\n order.push(fixtureId);\n }\n }\n\n return order;\n }\n\n private prepareInsertData(fixture: FixtureRecord) {\n const insertData: any = {};\n for (const [propName, column] of Object.entries(fixture.columns)) {\n if (isVirtualProp(column.prop)) {\n continue;\n }\n\n const prop = column.prop as EntityProp;\n if (!isRelationProp(prop)) {\n if (prop.type === \"json\") {\n insertData[propName] = JSON.stringify(column.value);\n } else {\n insertData[propName] = column.value;\n }\n } else if (\n isBelongsToOneRelationProp(prop) ||\n (isOneToOneRelationProp(prop) && prop.hasJoinColumn)\n ) {\n insertData[`${propName}_id`] = column.value;\n }\n }\n return insertData;\n }\n\n private buildDependencyGraph(fixtures: FixtureRecord[]) {\n this.dependencyGraph.clear();\n\n // 1. 노드 추가\n for (const fixture of fixtures) {\n this.dependencyGraph.set(fixture.fixtureId, {\n fixtureId: fixture.fixtureId,\n entityId: fixture.entityId,\n dependencies: new Set(),\n });\n }\n\n // 2. 의존성 추가\n for (const fixture of fixtures) {\n const node = this.dependencyGraph.get(fixture.fixtureId)!;\n\n for (const [, column] of Object.entries(fixture.columns)) {\n const prop = column.prop as EntityProp;\n\n if (isRelationProp(prop)) {\n if (\n isBelongsToOneRelationProp(prop) ||\n (isOneToOneRelationProp(prop) && prop.hasJoinColumn)\n ) {\n const relatedFixtureId = `${prop.with}#${column.value}`;\n if (this.dependencyGraph.has(relatedFixtureId)) {\n node.dependencies.add(relatedFixtureId);\n }\n } else if (isManyToManyRelationProp(prop)) {\n // ManyToMany 관계의 경우 양방향 의존성 추가\n const relatedIds = column.value as number[];\n for (const relatedId of relatedIds) {\n const relatedFixtureId = `${prop.with}#${relatedId}`;\n if (this.dependencyGraph.has(relatedFixtureId)) {\n node.dependencies.add(relatedFixtureId);\n this.dependencyGraph\n .get(relatedFixtureId)!\n .dependencies.add(fixture.fixtureId);\n }\n }\n }\n }\n }\n }\n }\n\n private async insertFixture(db: Knex, fixture: FixtureRecord) {\n const insertData = this.prepareInsertData(fixture);\n const entity = EntityManager.get(fixture.entityId);\n\n try {\n const uniqueFound = await this.checkUniqueViolation(db, entity, fixture);\n if (uniqueFound) {\n return {\n entityId: fixture.entityId,\n id: uniqueFound.id,\n };\n }\n\n const found = await db(entity.table).where(\"id\", fixture.id).first();\n if (found && !fixture.override) {\n return {\n entityId: fixture.entityId,\n id: found.id,\n };\n }\n\n const q = db.insert(insertData).into(entity.table);\n await q.onDuplicateUpdate.apply(q, Object.keys(insertData));\n return {\n entityId: fixture.entityId,\n id: fixture.id,\n };\n } catch (err) {\n console.log(err);\n throw err;\n }\n }\n\n private async handleManyToManyRelations(\n db: Knex,\n fixture: FixtureRecord,\n fixtures: FixtureRecord[]\n ) {\n for (const [, column] of Object.entries(fixture.columns)) {\n const prop = column.prop as EntityProp;\n if (isManyToManyRelationProp(prop)) {\n const joinTable = (prop as ManyToManyRelationProp).joinTable;\n const relatedIds = column.value as number[];\n\n for (const relatedId of relatedIds) {\n if (\n !fixtures.find((f) => f.fixtureId === `${prop.with}#${relatedId}`)\n ) {\n continue;\n }\n\n const entity = EntityManager.get(fixture.entityId);\n const relatedEntity = EntityManager.get(prop.with);\n if (!entity || !relatedEntity) {\n throw new Error(\n `Entity not found: ${fixture.entityId}, ${prop.with}`\n );\n }\n\n const [found] = await db(joinTable)\n .where({\n [`${inflection.singularize(entity.table)}_id`]: fixture.id,\n [`${inflection.singularize(relatedEntity.table)}_id`]: relatedId,\n })\n .limit(1);\n if (found) {\n continue;\n }\n\n const newIds = await db(joinTable).insert({\n [`${inflection.singularize(entity.table)}_id`]: fixture.id,\n [`${inflection.singularize(relatedEntity.table)}_id`]: relatedId,\n });\n console.log(\n chalk.green(\n `Inserted into ${joinTable}: ${entity.table}(${fixture.id}) - ${relatedEntity.table}(${relatedId}) ID: ${newIds}`\n )\n );\n }\n }\n }\n }\n\n async addFixtureLoader(code: string) {\n const path = Sonamu.apiRootPath + \"/src/testing/fixture.ts\";\n let content = readFileSync(path).toString();\n\n const fixtureLoaderStart = content.indexOf(\"const fixtureLoader = {\");\n const fixtureLoaderEnd = content.indexOf(\"};\", fixtureLoaderStart);\n\n if (fixtureLoaderStart !== -1 && fixtureLoaderEnd !== -1) {\n const newContent =\n content.slice(0, fixtureLoaderEnd) +\n \" \" +\n code +\n \"\\n\" +\n content.slice(fixtureLoaderEnd);\n\n writeFileSync(path, newContent);\n } else {\n throw new Error(\"Failed to find fixtureLoader in fixture.ts\");\n }\n }\n\n // 해당 픽스쳐의 값으로 유니크 제약에 위배되는 레코드가 있는지 확인\n private async checkUniqueViolation(\n db: Knex,\n entity: Entity,\n fixture: FixtureRecord\n ) {\n const uniqueIndexes = entity.indexes.filter((i) => i.type === \"unique\");\n if (uniqueIndexes.length === 0) {\n return null;\n }\n\n let uniqueQuery = db(entity.table);\n for (const index of uniqueIndexes) {\n // 컬럼 중 하나라도 null이면 유니크 제약을 위반하지 않기 때문에 해당 인덱스는 무시\n if (\n index.columns.some(\n (column) => fixture.columns[column.split(\"_id\")[0]].value === null\n )\n ) {\n continue;\n }\n\n uniqueQuery = uniqueQuery.orWhere((qb) => {\n for (const column of index.columns) {\n const field = column.split(\"_id\")[0];\n\n if (Array.isArray(fixture.columns[field].value)) {\n qb.whereIn(column, fixture.columns[field].value);\n } else {\n qb.andWhere(column, fixture.columns[field].value);\n }\n }\n });\n }\n const [uniqueFound] = await uniqueQuery;\n return uniqueFound;\n }\n}\nexport const FixtureManager = new FixtureManagerClass();\n"]}