joist-codegen 2.3.0-next.65 → 2.3.0-next.66
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.
- package/build/generate.cjs +1 -0
- package/build/generate.cjs.map +1 -1
- package/build/generate.js +2 -1
- package/build/generate.js.map +1 -1
- package/build/generateEntityCodegenFile.cjs +7 -8
- package/build/generateEntityCodegenFile.cjs.map +1 -1
- package/build/generateEntityCodegenFile.d.cts.map +1 -1
- package/build/generateEntityCodegenFile.d.mts.map +1 -1
- package/build/generateEntityCodegenFile.js +7 -8
- package/build/generateEntityCodegenFile.js.map +1 -1
- package/build/generateMetadataFile.cjs +58 -58
- package/build/generateMetadataFile.cjs.map +1 -1
- package/build/generateMetadataFile.d.cts +3 -1
- package/build/generateMetadataFile.d.cts.map +1 -1
- package/build/generateMetadataFile.d.mts +3 -1
- package/build/generateMetadataFile.d.mts.map +1 -1
- package/build/generateMetadataFile.js +59 -60
- package/build/generateMetadataFile.js.map +1 -1
- package/build/symbols.cjs +10 -0
- package/build/symbols.cjs.map +1 -1
- package/build/symbols.d.cts +6 -1
- package/build/symbols.d.cts.map +1 -1
- package/build/symbols.d.mts +6 -1
- package/build/symbols.d.mts.map +1 -1
- package/build/symbols.js +6 -1
- package/build/symbols.js.map +1 -1
- package/package.json +2 -2
package/build/generate.cjs
CHANGED
|
@@ -75,6 +75,7 @@ async function generateFiles(config, dbMeta) {
|
|
|
75
75
|
em: EntityManager;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
${entities.map((meta) => require_generateMetadataFile.generateColumnDeclarations(config, dbMeta, meta))}
|
|
78
79
|
${entities.map((meta) => require_generateMetadataFile.generateMetadataFile(config, dbMeta, meta))}
|
|
79
80
|
|
|
80
81
|
export const allMetadata = [${entities.map((meta) => meta.entity.metaName).join(", ")}];
|
package/build/generate.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.cjs","names":["createRequire","syncDocs","loadEntityDocs","findAllEntityScopes","generateEntityCodegenFile","generateEntityFile","generateEntityTestFile","merge","tableToEntityName","generateEnumFile","generatePgEnumFile","imp","setRuntimeConfig","def","JoistEntityManager","Entity","getIdType","generateMetadataFile","configureMetadata","generateEntitiesFile","generateFactoriesFiles","generateMetadataDocsFile","readdir"],"sources":["../src/generate.ts"],"sourcesContent":["import { readdir } from \"fs/promises\";\nimport { createRequire } from \"node:module\";\n\nimport { type CodegenFile, code, def, imp } from \"ts-poet\";\n\nimport { generateMetadataDocsFile, loadEntityDocs, syncDocs } from \"./docs/index.ts\";\nimport { findAllEntityScopes } from \"./findEntityScopes.ts\";\nimport { generateEntitiesFile } from \"./generateEntitiesFile.ts\";\nimport { generateEntityCodegenFile, getIdType } from \"./generateEntityCodegenFile.ts\";\nimport { generateEntityFile } from \"./generateEntityFile.ts\";\nimport { generateEntityTestFile } from \"./generateEntityTestFile.ts\";\nimport { generateEnumFile } from \"./generateEnumFile.ts\";\nimport { generateFactoriesFiles } from \"./generateFactoriesFiles.ts\";\nimport { generateMetadataFile } from \"./generateMetadataFile.ts\";\nimport { generatePgEnumFile } from \"./generatePgEnumFile.ts\";\nimport { type Config, type DbMetadata } from \"./index.ts\";\nimport { Entity, JoistEntityManager, configureMetadata, setRuntimeConfig } from \"./symbols.ts\";\nimport { merge, tableToEntityName } from \"./utils.ts\";\n\nconst runtimeRequire = createRequire(import.meta.url);\n\nexport type DPrintOptions = Record<string, unknown>;\n\n/**\n * Provides an API for hooking into the codegen build step.\n */\nexport interface CodegenPlugin {\n run(config: Config, dbMeta: DbMetadata): Promise<CodegenFile>;\n}\n\n/** Generates our `${Entity}` and `${Entity}Codegen` files based on the `db` schema. */\nexport async function generateFiles(config: Config, dbMeta: DbMetadata): Promise<CodegenFile[]> {\n const { entities, enums, pgEnums } = dbMeta;\n const entityNames = entities.map((meta) => meta.entity.name);\n\n // Find existing entities so that, besides just using `overwrite: false`, we can completely\n // skip making test files except for the _first_ time we create an entity. This achieves\n // `.history`-like \"create once\" behavior without the need for the `.history` file.\n const files = await readExistingFiles(config);\n\n // Sync documentation: backfill .md from existing JSDocs, then sync MD -> JSDoc\n if (config.docs) {\n await syncDocs(config.entitiesDirectory, entityNames);\n }\n\n // Load the .md docs once (post-sync) to inject into codegen JSDocs and the runtime metadata-docs.ts\n const entityDocs =\n config.docs || config.outputDocs ? await loadEntityDocs(config.entitiesDirectory, entityNames) : {};\n\n const scopeMembersByEntity = await findAllEntityScopes(\n config,\n entities.map((meta) => meta.entity),\n );\n\n const entityFiles = entities\n .map((meta) => {\n const entityName = meta.entity.name;\n const hasEntityFile = files.includes(`${entityName}.ts`);\n return [\n {\n name: `./codegen/${entityName}Codegen.ts`,\n contents: generateEntityCodegenFile(\n config,\n dbMeta,\n meta,\n scopeMembersByEntity[entityName] ?? [],\n config.docs ? entityDocs[entityName] : undefined,\n ),\n overwrite: true,\n },\n ...(hasEntityFile\n ? []\n : [\n { name: `${entityName}.ts`, contents: generateEntityFile(config, meta), overwrite: false },\n { name: `${entityName}.test.ts`, contents: generateEntityTestFile(config, meta), overwrite: false },\n ]),\n ];\n })\n .reduce(merge, []);\n\n const enumFiles = Object.values(enums)\n .map((enumData) => {\n const enumName = tableToEntityName(config, enumData.table);\n return [\n {\n name: `./enums/${enumName}.ts`,\n contents: generateEnumFile(config, enumData, enumName),\n overwrite: true,\n },\n ];\n })\n .reduce(merge, []);\n const pgEnumFiles = Object.values(pgEnums)\n .map((enumData) => {\n return [\n {\n name: `./enums/${enumData.name}.ts`,\n contents: generatePgEnumFile(config, enumData),\n overwrite: true,\n },\n ];\n })\n .reduce(merge, []);\n\n const contextType = config.contextType ? imp(`t:${config.contextType}`) : \"{}\";\n const txnType = config.transactionType ? imp(`t:${config.transactionType}`) : \"unknown\";\n const maybeTagDelimiter =\n config.tagDelimiter === undefined\n ? code``\n : code`tagDelimiter: ${config.tagDelimiter === \"\" ? \"undefined\" : JSON.stringify(config.tagDelimiter)},`;\n\n const metadataFile: CodegenFile = {\n name: \"./codegen/metadata.ts\",\n contents: code`\n ${setRuntimeConfig}({\n temporal: ${config.temporal ? { timeZone: typeof config.temporal === \"boolean\" ? \"UTC\" : config.temporal.timeZone } : \"false\"},\n ${maybeTagDelimiter}\n });\n \n export class ${def(\"EntityManager\")} extends ${JoistEntityManager}<${contextType}, Entity, ${txnType}> {}\n\n export interface ${def(\"Entity\")} extends ${Entity} {\n id: ${getIdType(config)};\n em: EntityManager;\n }\n\n ${entities.map((meta) => generateMetadataFile(config, dbMeta, meta))}\n\n export const allMetadata = [${entities.map((meta) => meta.entity.metaName).join(\", \")}];\n ${configureMetadata}(allMetadata);\n `,\n overwrite: true,\n toStringOpts: { dprintOptions: { lineWidth: 400 } },\n };\n\n const enumsTables = Object.values(enums)\n .map(({ table }) => table)\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const entitiesFile: CodegenFile = {\n name: \"./entities.ts\",\n contents: generateEntitiesFile(config, entities, enumsTables, Object.values(pgEnums)),\n overwrite: true,\n toStringOpts: { dprintOptions: { \"module.sortExportDeclarations\": \"maintain\" } },\n };\n\n const factoriesFiles: CodegenFile[] = generateFactoriesFiles(entities);\n\n const esmExt = config.esm ? (config.allowImportingTsExtensions ? \".ts\" : \".js\") : \"\";\n const indexFile: CodegenFile = {\n name: \"./index.ts\",\n contents: code`export * from \"./entities${esmExt}\"`,\n overwrite: false,\n };\n\n // Look for modules to require and call the exported `.run(Config, DbMeta)` method\n const pluginFiles: CodegenFile[] = (\n await Promise.all(\n (config.codegenPlugins ?? []).map((p) => {\n const plugin = runtimeRequire(p) as CodegenPlugin;\n return plugin.run(config, dbMeta);\n }),\n )\n ).flat();\n\n // Generate metadata-docs.ts if enabled\n const docsFile = config.outputDocs ? generateMetadataDocsFile(dbMeta, entityDocs) : undefined;\n\n return [\n ...entityFiles,\n ...enumFiles,\n ...pgEnumFiles,\n entitiesFile,\n ...factoriesFiles,\n metadataFile,\n ...(docsFile ? [docsFile] : []),\n indexFile,\n ...pluginFiles,\n ];\n}\n\n/** Reads the `entitiesDirectory` but just ignores if it doesn't exist yet. */\nasync function readExistingFiles(config: Config): Promise<string[]> {\n try {\n return await readdir(config.entitiesDirectory);\n } catch (e) {\n return [];\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generate.cjs","names":["createRequire","syncDocs","loadEntityDocs","findAllEntityScopes","generateEntityCodegenFile","generateEntityFile","generateEntityTestFile","merge","tableToEntityName","generateEnumFile","generatePgEnumFile","imp","setRuntimeConfig","def","JoistEntityManager","Entity","getIdType","generateColumnDeclarations","generateMetadataFile","configureMetadata","generateEntitiesFile","generateFactoriesFiles","generateMetadataDocsFile","readdir"],"sources":["../src/generate.ts"],"sourcesContent":["import { readdir } from \"fs/promises\";\nimport { createRequire } from \"node:module\";\n\nimport { type CodegenFile, code, def, imp } from \"ts-poet\";\n\nimport { generateMetadataDocsFile, loadEntityDocs, syncDocs } from \"./docs/index.ts\";\nimport { findAllEntityScopes } from \"./findEntityScopes.ts\";\nimport { generateEntitiesFile } from \"./generateEntitiesFile.ts\";\nimport { generateEntityCodegenFile, getIdType } from \"./generateEntityCodegenFile.ts\";\nimport { generateEntityFile } from \"./generateEntityFile.ts\";\nimport { generateEntityTestFile } from \"./generateEntityTestFile.ts\";\nimport { generateEnumFile } from \"./generateEnumFile.ts\";\nimport { generateFactoriesFiles } from \"./generateFactoriesFiles.ts\";\nimport { generateColumnDeclarations, generateMetadataFile } from \"./generateMetadataFile.ts\";\nimport { generatePgEnumFile } from \"./generatePgEnumFile.ts\";\nimport { type Config, type DbMetadata } from \"./index.ts\";\nimport { Entity, JoistEntityManager, configureMetadata, setRuntimeConfig } from \"./symbols.ts\";\nimport { merge, tableToEntityName } from \"./utils.ts\";\n\nconst runtimeRequire = createRequire(import.meta.url);\n\nexport type DPrintOptions = Record<string, unknown>;\n\n/**\n * Provides an API for hooking into the codegen build step.\n */\nexport interface CodegenPlugin {\n run(config: Config, dbMeta: DbMetadata): Promise<CodegenFile>;\n}\n\n/** Generates our `${Entity}` and `${Entity}Codegen` files based on the `db` schema. */\nexport async function generateFiles(config: Config, dbMeta: DbMetadata): Promise<CodegenFile[]> {\n const { entities, enums, pgEnums } = dbMeta;\n const entityNames = entities.map((meta) => meta.entity.name);\n\n // Find existing entities so that, besides just using `overwrite: false`, we can completely\n // skip making test files except for the _first_ time we create an entity. This achieves\n // `.history`-like \"create once\" behavior without the need for the `.history` file.\n const files = await readExistingFiles(config);\n\n // Sync documentation: backfill .md from existing JSDocs, then sync MD -> JSDoc\n if (config.docs) {\n await syncDocs(config.entitiesDirectory, entityNames);\n }\n\n // Load the .md docs once (post-sync) to inject into codegen JSDocs and the runtime metadata-docs.ts\n const entityDocs =\n config.docs || config.outputDocs ? await loadEntityDocs(config.entitiesDirectory, entityNames) : {};\n\n const scopeMembersByEntity = await findAllEntityScopes(\n config,\n entities.map((meta) => meta.entity),\n );\n\n const entityFiles = entities\n .map((meta) => {\n const entityName = meta.entity.name;\n const hasEntityFile = files.includes(`${entityName}.ts`);\n return [\n {\n name: `./codegen/${entityName}Codegen.ts`,\n contents: generateEntityCodegenFile(\n config,\n dbMeta,\n meta,\n scopeMembersByEntity[entityName] ?? [],\n config.docs ? entityDocs[entityName] : undefined,\n ),\n overwrite: true,\n },\n ...(hasEntityFile\n ? []\n : [\n { name: `${entityName}.ts`, contents: generateEntityFile(config, meta), overwrite: false },\n { name: `${entityName}.test.ts`, contents: generateEntityTestFile(config, meta), overwrite: false },\n ]),\n ];\n })\n .reduce(merge, []);\n\n const enumFiles = Object.values(enums)\n .map((enumData) => {\n const enumName = tableToEntityName(config, enumData.table);\n return [\n {\n name: `./enums/${enumName}.ts`,\n contents: generateEnumFile(config, enumData, enumName),\n overwrite: true,\n },\n ];\n })\n .reduce(merge, []);\n const pgEnumFiles = Object.values(pgEnums)\n .map((enumData) => {\n return [\n {\n name: `./enums/${enumData.name}.ts`,\n contents: generatePgEnumFile(config, enumData),\n overwrite: true,\n },\n ];\n })\n .reduce(merge, []);\n\n const contextType = config.contextType ? imp(`t:${config.contextType}`) : \"{}\";\n const txnType = config.transactionType ? imp(`t:${config.transactionType}`) : \"unknown\";\n const maybeTagDelimiter =\n config.tagDelimiter === undefined\n ? code``\n : code`tagDelimiter: ${config.tagDelimiter === \"\" ? \"undefined\" : JSON.stringify(config.tagDelimiter)},`;\n\n const metadataFile: CodegenFile = {\n name: \"./codegen/metadata.ts\",\n contents: code`\n ${setRuntimeConfig}({\n temporal: ${config.temporal ? { timeZone: typeof config.temporal === \"boolean\" ? \"UTC\" : config.temporal.timeZone } : \"false\"},\n ${maybeTagDelimiter}\n });\n \n export class ${def(\"EntityManager\")} extends ${JoistEntityManager}<${contextType}, Entity, ${txnType}> {}\n\n export interface ${def(\"Entity\")} extends ${Entity} {\n id: ${getIdType(config)};\n em: EntityManager;\n }\n\n ${entities.map((meta) => generateColumnDeclarations(config, dbMeta, meta))}\n ${entities.map((meta) => generateMetadataFile(config, dbMeta, meta))}\n\n export const allMetadata = [${entities.map((meta) => meta.entity.metaName).join(\", \")}];\n ${configureMetadata}(allMetadata);\n `,\n overwrite: true,\n toStringOpts: { dprintOptions: { lineWidth: 400 } },\n };\n\n const enumsTables = Object.values(enums)\n .map(({ table }) => table)\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const entitiesFile: CodegenFile = {\n name: \"./entities.ts\",\n contents: generateEntitiesFile(config, entities, enumsTables, Object.values(pgEnums)),\n overwrite: true,\n toStringOpts: { dprintOptions: { \"module.sortExportDeclarations\": \"maintain\" } },\n };\n\n const factoriesFiles: CodegenFile[] = generateFactoriesFiles(entities);\n\n const esmExt = config.esm ? (config.allowImportingTsExtensions ? \".ts\" : \".js\") : \"\";\n const indexFile: CodegenFile = {\n name: \"./index.ts\",\n contents: code`export * from \"./entities${esmExt}\"`,\n overwrite: false,\n };\n\n // Look for modules to require and call the exported `.run(Config, DbMeta)` method\n const pluginFiles: CodegenFile[] = (\n await Promise.all(\n (config.codegenPlugins ?? []).map((p) => {\n const plugin = runtimeRequire(p) as CodegenPlugin;\n return plugin.run(config, dbMeta);\n }),\n )\n ).flat();\n\n // Generate metadata-docs.ts if enabled\n const docsFile = config.outputDocs ? generateMetadataDocsFile(dbMeta, entityDocs) : undefined;\n\n return [\n ...entityFiles,\n ...enumFiles,\n ...pgEnumFiles,\n entitiesFile,\n ...factoriesFiles,\n metadataFile,\n ...(docsFile ? [docsFile] : []),\n indexFile,\n ...pluginFiles,\n ];\n}\n\n/** Reads the `entitiesDirectory` but just ignores if it doesn't exist yet. */\nasync function readExistingFiles(config: Config): Promise<string[]> {\n try {\n return await readdir(config.entitiesDirectory);\n } catch (e) {\n return [];\n }\n}\n"],"mappings":"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"}
|
package/build/generate.js
CHANGED
|
@@ -9,7 +9,7 @@ import { generateEntityFile } from "./generateEntityFile.js";
|
|
|
9
9
|
import { generateEntityTestFile } from "./generateEntityTestFile.js";
|
|
10
10
|
import { generateEnumFile } from "./generateEnumFile.js";
|
|
11
11
|
import { generateFactoriesFiles } from "./generateFactoriesFiles.js";
|
|
12
|
-
import { generateMetadataFile } from "./generateMetadataFile.js";
|
|
12
|
+
import { generateColumnDeclarations, generateMetadataFile } from "./generateMetadataFile.js";
|
|
13
13
|
import { generatePgEnumFile } from "./generatePgEnumFile.js";
|
|
14
14
|
import "./index.js";
|
|
15
15
|
import { createRequire } from "node:module";
|
|
@@ -75,6 +75,7 @@ async function generateFiles(config, dbMeta) {
|
|
|
75
75
|
em: EntityManager;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
${entities.map((meta) => generateColumnDeclarations(config, dbMeta, meta))}
|
|
78
79
|
${entities.map((meta) => generateMetadataFile(config, dbMeta, meta))}
|
|
79
80
|
|
|
80
81
|
export const allMetadata = [${entities.map((meta) => meta.entity.metaName).join(", ")}];
|
package/build/generate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","names":[],"sources":["../src/generate.ts"],"sourcesContent":["import { readdir } from \"fs/promises\";\nimport { createRequire } from \"node:module\";\n\nimport { type CodegenFile, code, def, imp } from \"ts-poet\";\n\nimport { generateMetadataDocsFile, loadEntityDocs, syncDocs } from \"./docs/index.ts\";\nimport { findAllEntityScopes } from \"./findEntityScopes.ts\";\nimport { generateEntitiesFile } from \"./generateEntitiesFile.ts\";\nimport { generateEntityCodegenFile, getIdType } from \"./generateEntityCodegenFile.ts\";\nimport { generateEntityFile } from \"./generateEntityFile.ts\";\nimport { generateEntityTestFile } from \"./generateEntityTestFile.ts\";\nimport { generateEnumFile } from \"./generateEnumFile.ts\";\nimport { generateFactoriesFiles } from \"./generateFactoriesFiles.ts\";\nimport { generateMetadataFile } from \"./generateMetadataFile.ts\";\nimport { generatePgEnumFile } from \"./generatePgEnumFile.ts\";\nimport { type Config, type DbMetadata } from \"./index.ts\";\nimport { Entity, JoistEntityManager, configureMetadata, setRuntimeConfig } from \"./symbols.ts\";\nimport { merge, tableToEntityName } from \"./utils.ts\";\n\nconst runtimeRequire = createRequire(import.meta.url);\n\nexport type DPrintOptions = Record<string, unknown>;\n\n/**\n * Provides an API for hooking into the codegen build step.\n */\nexport interface CodegenPlugin {\n run(config: Config, dbMeta: DbMetadata): Promise<CodegenFile>;\n}\n\n/** Generates our `${Entity}` and `${Entity}Codegen` files based on the `db` schema. */\nexport async function generateFiles(config: Config, dbMeta: DbMetadata): Promise<CodegenFile[]> {\n const { entities, enums, pgEnums } = dbMeta;\n const entityNames = entities.map((meta) => meta.entity.name);\n\n // Find existing entities so that, besides just using `overwrite: false`, we can completely\n // skip making test files except for the _first_ time we create an entity. This achieves\n // `.history`-like \"create once\" behavior without the need for the `.history` file.\n const files = await readExistingFiles(config);\n\n // Sync documentation: backfill .md from existing JSDocs, then sync MD -> JSDoc\n if (config.docs) {\n await syncDocs(config.entitiesDirectory, entityNames);\n }\n\n // Load the .md docs once (post-sync) to inject into codegen JSDocs and the runtime metadata-docs.ts\n const entityDocs =\n config.docs || config.outputDocs ? await loadEntityDocs(config.entitiesDirectory, entityNames) : {};\n\n const scopeMembersByEntity = await findAllEntityScopes(\n config,\n entities.map((meta) => meta.entity),\n );\n\n const entityFiles = entities\n .map((meta) => {\n const entityName = meta.entity.name;\n const hasEntityFile = files.includes(`${entityName}.ts`);\n return [\n {\n name: `./codegen/${entityName}Codegen.ts`,\n contents: generateEntityCodegenFile(\n config,\n dbMeta,\n meta,\n scopeMembersByEntity[entityName] ?? [],\n config.docs ? entityDocs[entityName] : undefined,\n ),\n overwrite: true,\n },\n ...(hasEntityFile\n ? []\n : [\n { name: `${entityName}.ts`, contents: generateEntityFile(config, meta), overwrite: false },\n { name: `${entityName}.test.ts`, contents: generateEntityTestFile(config, meta), overwrite: false },\n ]),\n ];\n })\n .reduce(merge, []);\n\n const enumFiles = Object.values(enums)\n .map((enumData) => {\n const enumName = tableToEntityName(config, enumData.table);\n return [\n {\n name: `./enums/${enumName}.ts`,\n contents: generateEnumFile(config, enumData, enumName),\n overwrite: true,\n },\n ];\n })\n .reduce(merge, []);\n const pgEnumFiles = Object.values(pgEnums)\n .map((enumData) => {\n return [\n {\n name: `./enums/${enumData.name}.ts`,\n contents: generatePgEnumFile(config, enumData),\n overwrite: true,\n },\n ];\n })\n .reduce(merge, []);\n\n const contextType = config.contextType ? imp(`t:${config.contextType}`) : \"{}\";\n const txnType = config.transactionType ? imp(`t:${config.transactionType}`) : \"unknown\";\n const maybeTagDelimiter =\n config.tagDelimiter === undefined\n ? code``\n : code`tagDelimiter: ${config.tagDelimiter === \"\" ? \"undefined\" : JSON.stringify(config.tagDelimiter)},`;\n\n const metadataFile: CodegenFile = {\n name: \"./codegen/metadata.ts\",\n contents: code`\n ${setRuntimeConfig}({\n temporal: ${config.temporal ? { timeZone: typeof config.temporal === \"boolean\" ? \"UTC\" : config.temporal.timeZone } : \"false\"},\n ${maybeTagDelimiter}\n });\n \n export class ${def(\"EntityManager\")} extends ${JoistEntityManager}<${contextType}, Entity, ${txnType}> {}\n\n export interface ${def(\"Entity\")} extends ${Entity} {\n id: ${getIdType(config)};\n em: EntityManager;\n }\n\n ${entities.map((meta) => generateMetadataFile(config, dbMeta, meta))}\n\n export const allMetadata = [${entities.map((meta) => meta.entity.metaName).join(\", \")}];\n ${configureMetadata}(allMetadata);\n `,\n overwrite: true,\n toStringOpts: { dprintOptions: { lineWidth: 400 } },\n };\n\n const enumsTables = Object.values(enums)\n .map(({ table }) => table)\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const entitiesFile: CodegenFile = {\n name: \"./entities.ts\",\n contents: generateEntitiesFile(config, entities, enumsTables, Object.values(pgEnums)),\n overwrite: true,\n toStringOpts: { dprintOptions: { \"module.sortExportDeclarations\": \"maintain\" } },\n };\n\n const factoriesFiles: CodegenFile[] = generateFactoriesFiles(entities);\n\n const esmExt = config.esm ? (config.allowImportingTsExtensions ? \".ts\" : \".js\") : \"\";\n const indexFile: CodegenFile = {\n name: \"./index.ts\",\n contents: code`export * from \"./entities${esmExt}\"`,\n overwrite: false,\n };\n\n // Look for modules to require and call the exported `.run(Config, DbMeta)` method\n const pluginFiles: CodegenFile[] = (\n await Promise.all(\n (config.codegenPlugins ?? []).map((p) => {\n const plugin = runtimeRequire(p) as CodegenPlugin;\n return plugin.run(config, dbMeta);\n }),\n )\n ).flat();\n\n // Generate metadata-docs.ts if enabled\n const docsFile = config.outputDocs ? generateMetadataDocsFile(dbMeta, entityDocs) : undefined;\n\n return [\n ...entityFiles,\n ...enumFiles,\n ...pgEnumFiles,\n entitiesFile,\n ...factoriesFiles,\n metadataFile,\n ...(docsFile ? [docsFile] : []),\n indexFile,\n ...pluginFiles,\n ];\n}\n\n/** Reads the `entitiesDirectory` but just ignores if it doesn't exist yet. */\nasync function readExistingFiles(config: Config): Promise<string[]> {\n try {\n return await readdir(config.entitiesDirectory);\n } catch (e) {\n return [];\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generate.js","names":[],"sources":["../src/generate.ts"],"sourcesContent":["import { readdir } from \"fs/promises\";\nimport { createRequire } from \"node:module\";\n\nimport { type CodegenFile, code, def, imp } from \"ts-poet\";\n\nimport { generateMetadataDocsFile, loadEntityDocs, syncDocs } from \"./docs/index.ts\";\nimport { findAllEntityScopes } from \"./findEntityScopes.ts\";\nimport { generateEntitiesFile } from \"./generateEntitiesFile.ts\";\nimport { generateEntityCodegenFile, getIdType } from \"./generateEntityCodegenFile.ts\";\nimport { generateEntityFile } from \"./generateEntityFile.ts\";\nimport { generateEntityTestFile } from \"./generateEntityTestFile.ts\";\nimport { generateEnumFile } from \"./generateEnumFile.ts\";\nimport { generateFactoriesFiles } from \"./generateFactoriesFiles.ts\";\nimport { generateColumnDeclarations, generateMetadataFile } from \"./generateMetadataFile.ts\";\nimport { generatePgEnumFile } from \"./generatePgEnumFile.ts\";\nimport { type Config, type DbMetadata } from \"./index.ts\";\nimport { Entity, JoistEntityManager, configureMetadata, setRuntimeConfig } from \"./symbols.ts\";\nimport { merge, tableToEntityName } from \"./utils.ts\";\n\nconst runtimeRequire = createRequire(import.meta.url);\n\nexport type DPrintOptions = Record<string, unknown>;\n\n/**\n * Provides an API for hooking into the codegen build step.\n */\nexport interface CodegenPlugin {\n run(config: Config, dbMeta: DbMetadata): Promise<CodegenFile>;\n}\n\n/** Generates our `${Entity}` and `${Entity}Codegen` files based on the `db` schema. */\nexport async function generateFiles(config: Config, dbMeta: DbMetadata): Promise<CodegenFile[]> {\n const { entities, enums, pgEnums } = dbMeta;\n const entityNames = entities.map((meta) => meta.entity.name);\n\n // Find existing entities so that, besides just using `overwrite: false`, we can completely\n // skip making test files except for the _first_ time we create an entity. This achieves\n // `.history`-like \"create once\" behavior without the need for the `.history` file.\n const files = await readExistingFiles(config);\n\n // Sync documentation: backfill .md from existing JSDocs, then sync MD -> JSDoc\n if (config.docs) {\n await syncDocs(config.entitiesDirectory, entityNames);\n }\n\n // Load the .md docs once (post-sync) to inject into codegen JSDocs and the runtime metadata-docs.ts\n const entityDocs =\n config.docs || config.outputDocs ? await loadEntityDocs(config.entitiesDirectory, entityNames) : {};\n\n const scopeMembersByEntity = await findAllEntityScopes(\n config,\n entities.map((meta) => meta.entity),\n );\n\n const entityFiles = entities\n .map((meta) => {\n const entityName = meta.entity.name;\n const hasEntityFile = files.includes(`${entityName}.ts`);\n return [\n {\n name: `./codegen/${entityName}Codegen.ts`,\n contents: generateEntityCodegenFile(\n config,\n dbMeta,\n meta,\n scopeMembersByEntity[entityName] ?? [],\n config.docs ? entityDocs[entityName] : undefined,\n ),\n overwrite: true,\n },\n ...(hasEntityFile\n ? []\n : [\n { name: `${entityName}.ts`, contents: generateEntityFile(config, meta), overwrite: false },\n { name: `${entityName}.test.ts`, contents: generateEntityTestFile(config, meta), overwrite: false },\n ]),\n ];\n })\n .reduce(merge, []);\n\n const enumFiles = Object.values(enums)\n .map((enumData) => {\n const enumName = tableToEntityName(config, enumData.table);\n return [\n {\n name: `./enums/${enumName}.ts`,\n contents: generateEnumFile(config, enumData, enumName),\n overwrite: true,\n },\n ];\n })\n .reduce(merge, []);\n const pgEnumFiles = Object.values(pgEnums)\n .map((enumData) => {\n return [\n {\n name: `./enums/${enumData.name}.ts`,\n contents: generatePgEnumFile(config, enumData),\n overwrite: true,\n },\n ];\n })\n .reduce(merge, []);\n\n const contextType = config.contextType ? imp(`t:${config.contextType}`) : \"{}\";\n const txnType = config.transactionType ? imp(`t:${config.transactionType}`) : \"unknown\";\n const maybeTagDelimiter =\n config.tagDelimiter === undefined\n ? code``\n : code`tagDelimiter: ${config.tagDelimiter === \"\" ? \"undefined\" : JSON.stringify(config.tagDelimiter)},`;\n\n const metadataFile: CodegenFile = {\n name: \"./codegen/metadata.ts\",\n contents: code`\n ${setRuntimeConfig}({\n temporal: ${config.temporal ? { timeZone: typeof config.temporal === \"boolean\" ? \"UTC\" : config.temporal.timeZone } : \"false\"},\n ${maybeTagDelimiter}\n });\n \n export class ${def(\"EntityManager\")} extends ${JoistEntityManager}<${contextType}, Entity, ${txnType}> {}\n\n export interface ${def(\"Entity\")} extends ${Entity} {\n id: ${getIdType(config)};\n em: EntityManager;\n }\n\n ${entities.map((meta) => generateColumnDeclarations(config, dbMeta, meta))}\n ${entities.map((meta) => generateMetadataFile(config, dbMeta, meta))}\n\n export const allMetadata = [${entities.map((meta) => meta.entity.metaName).join(\", \")}];\n ${configureMetadata}(allMetadata);\n `,\n overwrite: true,\n toStringOpts: { dprintOptions: { lineWidth: 400 } },\n };\n\n const enumsTables = Object.values(enums)\n .map(({ table }) => table)\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const entitiesFile: CodegenFile = {\n name: \"./entities.ts\",\n contents: generateEntitiesFile(config, entities, enumsTables, Object.values(pgEnums)),\n overwrite: true,\n toStringOpts: { dprintOptions: { \"module.sortExportDeclarations\": \"maintain\" } },\n };\n\n const factoriesFiles: CodegenFile[] = generateFactoriesFiles(entities);\n\n const esmExt = config.esm ? (config.allowImportingTsExtensions ? \".ts\" : \".js\") : \"\";\n const indexFile: CodegenFile = {\n name: \"./index.ts\",\n contents: code`export * from \"./entities${esmExt}\"`,\n overwrite: false,\n };\n\n // Look for modules to require and call the exported `.run(Config, DbMeta)` method\n const pluginFiles: CodegenFile[] = (\n await Promise.all(\n (config.codegenPlugins ?? []).map((p) => {\n const plugin = runtimeRequire(p) as CodegenPlugin;\n return plugin.run(config, dbMeta);\n }),\n )\n ).flat();\n\n // Generate metadata-docs.ts if enabled\n const docsFile = config.outputDocs ? generateMetadataDocsFile(dbMeta, entityDocs) : undefined;\n\n return [\n ...entityFiles,\n ...enumFiles,\n ...pgEnumFiles,\n entitiesFile,\n ...factoriesFiles,\n metadataFile,\n ...(docsFile ? [docsFile] : []),\n indexFile,\n ...pluginFiles,\n ];\n}\n\n/** Reads the `entitiesDirectory` but just ignores if it doesn't exist yet. */\nasync function readExistingFiles(config: Config): Promise<string[]> {\n try {\n return await readdir(config.entitiesDirectory);\n } catch (e) {\n return [];\n }\n}\n"],"mappings":"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"}
|
|
@@ -62,7 +62,7 @@ function generateEntityCodegenFile(config, dbMeta, meta, scopeMembers = [], docs
|
|
|
62
62
|
const maybeBaseOpts = baseEntity ? ts_poet.code`extends ${baseEntity.entity.optsType}` : "";
|
|
63
63
|
const physical = meta.physicalMetadata ?? meta;
|
|
64
64
|
const sharedTable = meta.inheritanceType === "sti" && baseEntity;
|
|
65
|
-
const columns = sharedTable ? {} : generateColumnsType(physical
|
|
65
|
+
const columns = sharedTable ? {} : generateColumnsType(physical);
|
|
66
66
|
const maybeBaseColumns = sharedTable ? ts_poet.code`extends ${(0, ts_poet.imp)(`t:${baseEntity.name}Columns@./entities.ts`)}` : "";
|
|
67
67
|
const maybeBaseIdOpts = baseEntity ? ts_poet.code`extends ${(0, ts_poet.imp)("t:" + baseEntity.entity.idsOptsName + "@./entities.ts")}` : "";
|
|
68
68
|
const maybeBaseFilter = baseEntity ? ts_poet.code`extends ${(0, ts_poet.imp)("t:" + baseEntity.entity.filterName + "@./entities.ts")}` : "";
|
|
@@ -406,8 +406,8 @@ function generateFieldsType(meta, idType) {
|
|
|
406
406
|
* I.e. Comment.parent_book_id is an optional Book reference, not the CommentParent union.
|
|
407
407
|
* Polymorphic component writes remain unsupported, so their policies are conservative.
|
|
408
408
|
*/
|
|
409
|
-
function generateColumnsType(meta
|
|
410
|
-
const columns = { id: ts_poet.code`{
|
|
409
|
+
function generateColumnsType(meta) {
|
|
410
|
+
const columns = { id: ts_poet.code`{ type: ${require_symbols.IdOf}<${meta.entity.type}>; entity: ${meta.entity.type}; ${columnPolicyType(meta, meta.primaryKey)} }` };
|
|
411
411
|
for (const field of [
|
|
412
412
|
...meta.primitives,
|
|
413
413
|
...meta.enums,
|
|
@@ -415,15 +415,14 @@ function generateColumnsType(meta, idType) {
|
|
|
415
415
|
...meta.manyToOnes
|
|
416
416
|
]) {
|
|
417
417
|
const policy = columnPolicyType(meta, field);
|
|
418
|
-
if (field.kind === "primitive") columns[field.columnName] = ts_poet.code`{
|
|
419
|
-
else if (field.kind === "m2o") columns[field.columnName] = ts_poet.code`{
|
|
418
|
+
if (field.kind === "primitive") columns[field.columnName] = ts_poet.code`{ type: ${field.fieldType}; ${policy} }`;
|
|
419
|
+
else if (field.kind === "m2o") columns[field.columnName] = ts_poet.code`{ type: ${require_symbols.IdOf}<${field.otherEntity.type}>; entity: ${field.otherEntity.type}; ${policy} }`;
|
|
420
420
|
else {
|
|
421
421
|
const array = field.kind === "enum" && field.isArray ? "[]" : "";
|
|
422
|
-
|
|
423
|
-
columns[field.columnName] = ts_poet.code`{ kind: "enum"; type: ${field.enumType}${array}; ${native} ${policy} }`;
|
|
422
|
+
columns[field.columnName] = ts_poet.code`{ type: ${field.enumType}${array}; ${policy} }`;
|
|
424
423
|
}
|
|
425
424
|
}
|
|
426
|
-
for (const field of meta.polymorphics) for (const component of field.components) columns[component.columnName] = ts_poet.code`{
|
|
425
|
+
for (const field of meta.polymorphics) for (const component of field.components) columns[component.columnName] = ts_poet.code`{ type: ${require_symbols.IdOf}<${component.otherEntity.type}>; entity: ${component.otherEntity.type}; nullable: true; insert: "never"; update: false; }`;
|
|
427
426
|
return columns;
|
|
428
427
|
}
|
|
429
428
|
/** Emits SQL write policy without using ORM defaults or derived-field restrictions. */
|