@danceroutine/tango-codegen 1.4.0 → 1.5.0
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/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +4 -3
- package/dist/commands/loadProjectModule.d.ts +15 -0
- package/dist/commands/runGenerateRelationsCommand.d.ts +11 -0
- package/dist/commands-CFAq4wXC.js +297 -0
- package/dist/commands-CFAq4wXC.js.map +1 -0
- package/dist/frameworks/index.js +1 -1
- package/dist/{frameworks-Dfcrg0ZQ.js → frameworks-CLOeazGj.js} +22 -3
- package/dist/frameworks-CLOeazGj.js.map +1 -0
- package/dist/generators/index.d.ts +2 -0
- package/dist/generators/index.js +3 -2
- package/dist/generators/relations/generateRelationRegistryArtifacts.d.ts +15 -0
- package/dist/generators/relations/index.d.ts +5 -0
- package/dist/generators/relations/writeRelationRegistryArtifacts.d.ts +16 -0
- package/dist/{generators-C9UeakCq.js → generators-DuAuGNR2.js} +6 -2
- package/dist/{generators-C9UeakCq.js.map → generators-DuAuGNR2.js.map} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -4
- package/dist/relations-uMuViSQC.js +76 -0
- package/dist/relations-uMuViSQC.js.map +1 -0
- package/package.json +7 -3
- package/dist/commands-lJSW2Kuf.js +0 -187
- package/dist/commands-lJSW2Kuf.js.map +0 -1
- package/dist/frameworks-Dfcrg0ZQ.js.map +0 -1
package/dist/commands/index.d.ts
CHANGED
|
@@ -2,3 +2,5 @@
|
|
|
2
2
|
* Domain boundary barrel: centralizes this subdomain's public contract.
|
|
3
3
|
*/
|
|
4
4
|
export { registerCodegenCommands } from './registerCodegenCommands';
|
|
5
|
+
export { loadProjectModule } from './loadProjectModule';
|
|
6
|
+
export { runGenerateRelationsCommand, withGenerateRelationsCommand } from './runGenerateRelationsCommand';
|
package/dist/commands/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import
|
|
1
|
+
import "../relations-uMuViSQC.js";
|
|
2
|
+
import "../frameworks-CLOeazGj.js";
|
|
3
|
+
import { loadProjectModule, registerCodegenCommands, runGenerateRelationsCommand, withGenerateRelationsCommand } from "../commands-CFAq4wXC.js";
|
|
3
4
|
|
|
4
|
-
export { registerCodegenCommands };
|
|
5
|
+
export { loadProjectModule, registerCodegenCommands, runGenerateRelationsCommand, withGenerateRelationsCommand };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ModelRegistry } from '@danceroutine/tango-schema';
|
|
2
|
+
type ProjectModuleLoadResult = {
|
|
3
|
+
loaded: Record<string, unknown>;
|
|
4
|
+
modelTypeAccessors: Record<string, string>;
|
|
5
|
+
registry: ModelRegistry;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Load a Tango app module and discover model export accessors suitable for
|
|
9
|
+
* generated ambient type references.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadProjectModule(modulePath: string, options?: {
|
|
12
|
+
projectRoot?: string;
|
|
13
|
+
outputDir?: string;
|
|
14
|
+
}): Promise<ProjectModuleLoadResult>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Argv } from 'yargs';
|
|
2
|
+
type GenerateRelationsCommandArgs = {
|
|
3
|
+
models: string;
|
|
4
|
+
outDir: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Generate the app-local ambient relation registry from a finalized model graph.
|
|
8
|
+
*/
|
|
9
|
+
export declare function runGenerateRelationsCommand({ models, outDir }: GenerateRelationsCommandArgs): Promise<void>;
|
|
10
|
+
export declare function withGenerateRelationsCommand(parser: Argv): Argv;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { __export } from "./chunk-BkvOhyD0.js";
|
|
2
|
+
import { writeRelationRegistryArtifacts } from "./relations-uMuViSQC.js";
|
|
3
|
+
import { FrameworkScaffoldRegistry, PACKAGE_MANAGER, SCAFFOLD_DATABASE_DIALECT, SUPPORTED_FRAMEWORK, scaffoldProject } from "./frameworks-CLOeazGj.js";
|
|
4
|
+
import { GENERATED_RELATION_REGISTRY_DIRNAME, GENERATED_RELATION_REGISTRY_METADATA_FILENAME, GENERATED_RELATION_REGISTRY_TYPES_FILENAME, ModelRegistry } from "@danceroutine/tango-schema";
|
|
5
|
+
import { extname, relative, resolve as resolve$1, resolve as resolve$2 } from "node:path";
|
|
6
|
+
import { getLogger, getLogger as getLogger$1, getLogger as getLogger$2 } from "@danceroutine/tango-core";
|
|
7
|
+
import { basename, basename as basename$1, join, resolve, resolve as resolve$3 } from "path/posix";
|
|
8
|
+
import { spawnSync } from "child_process";
|
|
9
|
+
import { pathToFileURL } from "node:url";
|
|
10
|
+
import { createJiti } from "jiti";
|
|
11
|
+
import { readFile, readdir } from "fs/promises";
|
|
12
|
+
|
|
13
|
+
//#region src/commands/runInstall.ts
|
|
14
|
+
function runInstall(packageManager, cwd) {
|
|
15
|
+
const argsByPackageManager = {
|
|
16
|
+
pnpm: ["install"],
|
|
17
|
+
npm: ["install"],
|
|
18
|
+
yarn: ["install"],
|
|
19
|
+
bun: ["install"]
|
|
20
|
+
};
|
|
21
|
+
const result = spawnSync(packageManager, [...argsByPackageManager[packageManager]], {
|
|
22
|
+
cwd,
|
|
23
|
+
stdio: "inherit",
|
|
24
|
+
env: process.env
|
|
25
|
+
});
|
|
26
|
+
if (result.status !== 0) throw new Error(`Dependency install failed with ${packageManager}. Exit code: ${String(result.status ?? "unknown")}.`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/commands/runNewCommand.ts
|
|
31
|
+
async function runNewCommand({ path, name, framework, packageManager, dialect, install, force, seed: includeSeed }) {
|
|
32
|
+
const registry = FrameworkScaffoldRegistry.createDefault();
|
|
33
|
+
const strategy = registry.get(framework);
|
|
34
|
+
const requestedPath = path ?? name ?? "tango-app";
|
|
35
|
+
const projectName = name ?? basename$1(requestedPath);
|
|
36
|
+
const targetDir = resolve$3(process.cwd(), requestedPath);
|
|
37
|
+
const context = {
|
|
38
|
+
projectName,
|
|
39
|
+
targetDir,
|
|
40
|
+
framework,
|
|
41
|
+
packageManager,
|
|
42
|
+
dialect,
|
|
43
|
+
includeSeed
|
|
44
|
+
};
|
|
45
|
+
await scaffoldProject(context, strategy, { force });
|
|
46
|
+
if (install) runInstall(packageManager, targetDir);
|
|
47
|
+
const logger$1 = getLogger$2("tango.codegen");
|
|
48
|
+
logger$1.info(`Scaffold complete: ${targetDir}`);
|
|
49
|
+
logger$1.info(`Framework: ${strategy.name}`);
|
|
50
|
+
logger$1.info(`Run next: cd ${targetDir} && ${packageManager} run dev`);
|
|
51
|
+
}
|
|
52
|
+
function withNewCommand(parser) {
|
|
53
|
+
return parser.command("new [name]", "Bootstrap a new Tango project", (builder) => builder.positional("name", {
|
|
54
|
+
type: "string",
|
|
55
|
+
describe: "Project name (used as directory when --path is omitted)."
|
|
56
|
+
}).option("framework", {
|
|
57
|
+
type: "string",
|
|
58
|
+
choices: Object.values(SUPPORTED_FRAMEWORK),
|
|
59
|
+
demandOption: true,
|
|
60
|
+
describe: "Host framework scaffold to generate."
|
|
61
|
+
}).option("path", {
|
|
62
|
+
type: "string",
|
|
63
|
+
describe: "Target directory for generated project files."
|
|
64
|
+
}).option("package-manager", {
|
|
65
|
+
type: "string",
|
|
66
|
+
choices: Object.values(PACKAGE_MANAGER),
|
|
67
|
+
default: PACKAGE_MANAGER.PNPM,
|
|
68
|
+
describe: "Package manager used for follow-up instructions and optional install."
|
|
69
|
+
}).option("dialect", {
|
|
70
|
+
type: "string",
|
|
71
|
+
choices: Object.values(SCAFFOLD_DATABASE_DIALECT),
|
|
72
|
+
default: SCAFFOLD_DATABASE_DIALECT.SQLITE,
|
|
73
|
+
describe: "Database dialect default for generated config."
|
|
74
|
+
}).option("install", {
|
|
75
|
+
type: "boolean",
|
|
76
|
+
default: false,
|
|
77
|
+
describe: "Install dependencies after scaffolding."
|
|
78
|
+
}).option("force", {
|
|
79
|
+
type: "boolean",
|
|
80
|
+
default: false,
|
|
81
|
+
describe: "Allow writing into a non-empty target directory."
|
|
82
|
+
}).option("seed", {
|
|
83
|
+
type: "boolean",
|
|
84
|
+
default: true,
|
|
85
|
+
describe: "Include seed/bootstrap sample artifacts when supported by the framework strategy."
|
|
86
|
+
}), async ({ name, framework, path, packageManager, dialect, install, force, seed }) => {
|
|
87
|
+
await runNewCommand({
|
|
88
|
+
name,
|
|
89
|
+
framework,
|
|
90
|
+
path,
|
|
91
|
+
packageManager,
|
|
92
|
+
dialect,
|
|
93
|
+
install,
|
|
94
|
+
force,
|
|
95
|
+
seed
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/commands/loadProjectModule.ts
|
|
102
|
+
const TS_EXTENSIONS = new Set([
|
|
103
|
+
".ts",
|
|
104
|
+
".tsx",
|
|
105
|
+
".mts",
|
|
106
|
+
".cts"
|
|
107
|
+
]);
|
|
108
|
+
function isTypeScriptModule(modulePath) {
|
|
109
|
+
return TS_EXTENSIONS.has(extname(modulePath).toLowerCase());
|
|
110
|
+
}
|
|
111
|
+
function isModelLike(value) {
|
|
112
|
+
return typeof value === "object" && value !== null && "metadata" in value && typeof value.metadata?.key === "string";
|
|
113
|
+
}
|
|
114
|
+
function toImportSpecifier(absoluteModulePath, outputDir) {
|
|
115
|
+
const relativePath = relative(outputDir, absoluteModulePath).replaceAll("\\", "/");
|
|
116
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
117
|
+
}
|
|
118
|
+
function collectModelTypeAccessors(loaded, importSpecifier, accessors = new Map()) {
|
|
119
|
+
const models = [];
|
|
120
|
+
const registerAccessor = (model, accessor) => {
|
|
121
|
+
models.push(model);
|
|
122
|
+
const existing = accessors.get(model.metadata.key);
|
|
123
|
+
if (!existing || accessor.length < existing.length) accessors.set(model.metadata.key, accessor);
|
|
124
|
+
};
|
|
125
|
+
const inspectValue = (value, accessorSegments) => {
|
|
126
|
+
if (isModelLike(value)) {
|
|
127
|
+
const accessor = accessorSegments.map((segment) => `[${JSON.stringify(segment)}]`).join("");
|
|
128
|
+
registerAccessor(value, `typeof import(${JSON.stringify(importSpecifier)})${accessor}`);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (typeof value !== "object" || value === null) return;
|
|
132
|
+
for (const [key, nested] of Object.entries(value)) if (isModelLike(nested)) {
|
|
133
|
+
const accessor = [...accessorSegments, key].map((segment) => `[${JSON.stringify(segment)}]`).join("");
|
|
134
|
+
registerAccessor(nested, `typeof import(${JSON.stringify(importSpecifier)})${accessor}`);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
for (const [key, value] of Object.entries(loaded)) inspectValue(value, [key]);
|
|
138
|
+
return {
|
|
139
|
+
accessors: Object.fromEntries(accessors),
|
|
140
|
+
models
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async function loadProjectModule(modulePath, options) {
|
|
144
|
+
const projectRoot = options?.projectRoot ?? process.cwd();
|
|
145
|
+
const absoluteModulePath = resolve$2(projectRoot, modulePath);
|
|
146
|
+
const outputDir = options?.outputDir ?? resolve$2(projectRoot, ".tango");
|
|
147
|
+
const registry = new ModelRegistry();
|
|
148
|
+
const executeImport = async () => {
|
|
149
|
+
if (isTypeScriptModule(absoluteModulePath)) {
|
|
150
|
+
const jiti = createJiti(resolve$2(projectRoot, "tango.config.ts"), {
|
|
151
|
+
interopDefault: true,
|
|
152
|
+
moduleCache: false
|
|
153
|
+
});
|
|
154
|
+
return await jiti.import(absoluteModulePath);
|
|
155
|
+
}
|
|
156
|
+
return await import(pathToFileURL(absoluteModulePath).href);
|
|
157
|
+
};
|
|
158
|
+
const loaded = await ModelRegistry.runWithRegistry(registry, executeImport);
|
|
159
|
+
const collected = collectModelTypeAccessors(loaded, toImportSpecifier(absoluteModulePath, outputDir));
|
|
160
|
+
const effectiveRegistry = registry.values().length > 0 ? registry : collected.models.length > 0 ? ModelRegistry.getOwner(collected.models[0]) : registry;
|
|
161
|
+
return {
|
|
162
|
+
loaded,
|
|
163
|
+
modelTypeAccessors: collected.accessors,
|
|
164
|
+
registry: effectiveRegistry
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/commands/runGenerateRelationsCommand.ts
|
|
170
|
+
const logger = getLogger$1("tango.codegen");
|
|
171
|
+
async function runGenerateRelationsCommand({ models, outDir }) {
|
|
172
|
+
const outputDir = resolve$1(process.cwd(), outDir);
|
|
173
|
+
const { registry, modelTypeAccessors } = await loadProjectModule(models, { outputDir });
|
|
174
|
+
const written = await writeRelationRegistryArtifacts({
|
|
175
|
+
registry,
|
|
176
|
+
modelTypeAccessors,
|
|
177
|
+
outputDir
|
|
178
|
+
});
|
|
179
|
+
logger.info(`Generated relation registry: ${written.typesFilepath}`);
|
|
180
|
+
logger.info(`Generated relation metadata: ${written.metadataFilepath}`);
|
|
181
|
+
}
|
|
182
|
+
function withGenerateRelationsCommand(parser) {
|
|
183
|
+
return parser.command("relations", "Generate app-local ambient relation typing from Tango models", (builder) => builder.option("models", {
|
|
184
|
+
type: "string",
|
|
185
|
+
demandOption: true,
|
|
186
|
+
describe: "Path to the module exporting Tango Model definitions."
|
|
187
|
+
}).option("out-dir", {
|
|
188
|
+
type: "string",
|
|
189
|
+
default: GENERATED_RELATION_REGISTRY_DIRNAME,
|
|
190
|
+
describe: `Directory that receives ${GENERATED_RELATION_REGISTRY_TYPES_FILENAME} and ${GENERATED_RELATION_REGISTRY_METADATA_FILENAME}.`
|
|
191
|
+
}), async ({ models, outDir }) => {
|
|
192
|
+
await runGenerateRelationsCommand({
|
|
193
|
+
models,
|
|
194
|
+
outDir
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region src/commands/runInitCommand.ts
|
|
201
|
+
async function detectPackageManager(targetDir) {
|
|
202
|
+
try {
|
|
203
|
+
const entries = await readdir(targetDir);
|
|
204
|
+
if (entries.includes("pnpm-lock.yaml")) return PACKAGE_MANAGER.PNPM;
|
|
205
|
+
if (entries.includes("package-lock.json")) return PACKAGE_MANAGER.NPM;
|
|
206
|
+
if (entries.includes("yarn.lock")) return PACKAGE_MANAGER.YARN;
|
|
207
|
+
if (entries.includes("bun.lockb") || entries.includes("bun.lock")) return PACKAGE_MANAGER.BUN;
|
|
208
|
+
} catch {}
|
|
209
|
+
return PACKAGE_MANAGER.PNPM;
|
|
210
|
+
}
|
|
211
|
+
async function runInitCommand({ framework, path, dialect, skipExisting, force }) {
|
|
212
|
+
const registry = FrameworkScaffoldRegistry.createDefault();
|
|
213
|
+
const strategy = registry.get(framework);
|
|
214
|
+
const targetDir = resolve(process.cwd(), path);
|
|
215
|
+
let projectName = basename(targetDir);
|
|
216
|
+
try {
|
|
217
|
+
const pkgPath = join(targetDir, "package.json");
|
|
218
|
+
const raw = await readFile(pkgPath, "utf8");
|
|
219
|
+
const pkg = JSON.parse(raw);
|
|
220
|
+
if (typeof pkg.name === "string" && pkg.name.length > 0) projectName = pkg.name;
|
|
221
|
+
} catch {}
|
|
222
|
+
const packageManager = await detectPackageManager(targetDir);
|
|
223
|
+
const context = {
|
|
224
|
+
projectName,
|
|
225
|
+
targetDir,
|
|
226
|
+
framework,
|
|
227
|
+
packageManager,
|
|
228
|
+
dialect,
|
|
229
|
+
includeSeed: true
|
|
230
|
+
};
|
|
231
|
+
await scaffoldProject(context, strategy, {
|
|
232
|
+
mode: "init",
|
|
233
|
+
skipExisting,
|
|
234
|
+
force
|
|
235
|
+
});
|
|
236
|
+
const logger$1 = getLogger("tango.codegen");
|
|
237
|
+
logger$1.info(`Tango init complete: ${targetDir}`);
|
|
238
|
+
logger$1.info(`Install dependencies: ${strategy.getTangoInstallOneLiner(packageManager, context)}`);
|
|
239
|
+
if (framework === SUPPORTED_FRAMEWORK.EXPRESS) logger$1.info("Mount Tango: import { registerTango } from './src/tango.js'; await registerTango(app);");
|
|
240
|
+
if (framework === SUPPORTED_FRAMEWORK.NUXT) logger$1.info("Wire Tango handlers: register Nitro serverHandlers in nuxt.config.ts and export NuxtAdapter-backed handlers from server/tango/.");
|
|
241
|
+
}
|
|
242
|
+
function withInitCommand(parser) {
|
|
243
|
+
return parser.command("init", "Add Tango to an existing project (only Tango-layer files)", (builder) => builder.option("framework", {
|
|
244
|
+
type: "string",
|
|
245
|
+
choices: Object.values(SUPPORTED_FRAMEWORK),
|
|
246
|
+
demandOption: true,
|
|
247
|
+
describe: "Host framework (express, next, or nuxt)."
|
|
248
|
+
}).option("path", {
|
|
249
|
+
type: "string",
|
|
250
|
+
default: ".",
|
|
251
|
+
describe: "Target directory (default: current directory)."
|
|
252
|
+
}).option("dialect", {
|
|
253
|
+
type: "string",
|
|
254
|
+
choices: Object.values(SCAFFOLD_DATABASE_DIALECT),
|
|
255
|
+
default: SCAFFOLD_DATABASE_DIALECT.SQLITE,
|
|
256
|
+
describe: "Database dialect for generated config."
|
|
257
|
+
}).option("skip-existing", {
|
|
258
|
+
type: "boolean",
|
|
259
|
+
default: true,
|
|
260
|
+
describe: "Do not overwrite existing files."
|
|
261
|
+
}).option("force", {
|
|
262
|
+
type: "boolean",
|
|
263
|
+
default: false,
|
|
264
|
+
describe: "Overwrite existing files when set."
|
|
265
|
+
}), async ({ framework, path, dialect, skipExisting, force }) => {
|
|
266
|
+
await runInitCommand({
|
|
267
|
+
framework,
|
|
268
|
+
path,
|
|
269
|
+
dialect,
|
|
270
|
+
skipExisting,
|
|
271
|
+
force
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region src/commands/registerCodegenCommands.ts
|
|
278
|
+
function registerCodegenCommands(parser) {
|
|
279
|
+
const withTopLevelNew = withNewCommand(parser);
|
|
280
|
+
const withTopLevelInit = withInitCommand(withTopLevelNew);
|
|
281
|
+
const withTopLevelRelations = withGenerateRelationsCommand(withTopLevelInit);
|
|
282
|
+
return withTopLevelRelations.command("codegen <command>", "Code generation command group", (builder) => withGenerateRelationsCommand(withInitCommand(withNewCommand(builder))));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
//#endregion
|
|
286
|
+
//#region src/commands/index.ts
|
|
287
|
+
var commands_exports = {};
|
|
288
|
+
__export(commands_exports, {
|
|
289
|
+
loadProjectModule: () => loadProjectModule,
|
|
290
|
+
registerCodegenCommands: () => registerCodegenCommands,
|
|
291
|
+
runGenerateRelationsCommand: () => runGenerateRelationsCommand,
|
|
292
|
+
withGenerateRelationsCommand: () => withGenerateRelationsCommand
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
//#endregion
|
|
296
|
+
export { commands_exports, loadProjectModule, registerCodegenCommands, runGenerateRelationsCommand, withGenerateRelationsCommand };
|
|
297
|
+
//# sourceMappingURL=commands-CFAq4wXC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands-CFAq4wXC.js","names":["packageManager: PackageManager","cwd: string","argsByPackageManager: Record<PackageManager, readonly string[]>","context: FrameworkScaffoldContext","parser: Argv","modulePath: string","value: unknown","absoluteModulePath: string","outputDir: string","loaded: Record<string, unknown>","importSpecifier: string","accessors: Map<string, string>","models: ModelLike[]","model: ModelLike","accessor: string","accessorSegments: readonly string[]","options?: { projectRoot?: string; outputDir?: string }","parser: Argv","targetDir: string","context: FrameworkScaffoldContext","parser: Argv","parser: Argv"],"sources":["../src/commands/runInstall.ts","../src/commands/runNewCommand.ts","../src/commands/loadProjectModule.ts","../src/commands/runGenerateRelationsCommand.ts","../src/commands/runInitCommand.ts","../src/commands/registerCodegenCommands.ts","../src/commands/index.ts"],"sourcesContent":["import { spawnSync } from 'child_process';\nimport type { PackageManager } from '../frameworks';\n\nexport function runInstall(packageManager: PackageManager, cwd: string): void {\n const argsByPackageManager: Record<PackageManager, readonly string[]> = {\n pnpm: ['install'],\n npm: ['install'],\n yarn: ['install'],\n bun: ['install'],\n };\n\n const result = spawnSync(packageManager, [...argsByPackageManager[packageManager]], {\n cwd,\n stdio: 'inherit',\n env: process.env,\n });\n\n if (result.status !== 0) {\n throw new Error(\n `Dependency install failed with ${packageManager}. Exit code: ${String(result.status ?? 'unknown')}.`\n );\n }\n}\n","import { getLogger } from '@danceroutine/tango-core';\nimport { basename, resolve } from 'path/posix';\nimport {\n type SupportedFramework,\n type PackageManager,\n FrameworkScaffoldRegistry,\n type FrameworkScaffoldContext,\n scaffoldProject,\n} from '../frameworks';\nimport {\n PACKAGE_MANAGER,\n SCAFFOLD_DATABASE_DIALECT,\n SUPPORTED_FRAMEWORK,\n type ScaffoldDatabaseDialect,\n} from '../frameworks/contracts/FrameworkScaffoldStrategy';\nimport { runInstall } from './runInstall';\nimport type { Argv } from 'yargs';\n\ntype NewCommandArgs = {\n name?: string;\n framework: SupportedFramework;\n path?: string;\n packageManager: PackageManager;\n dialect: ScaffoldDatabaseDialect;\n install: boolean;\n force: boolean;\n seed: boolean;\n};\nexport async function runNewCommand({\n path,\n name,\n framework,\n packageManager,\n dialect,\n install,\n force,\n seed: includeSeed,\n}: NewCommandArgs): Promise<void> {\n const registry = FrameworkScaffoldRegistry.createDefault();\n const strategy = registry.get(framework)!;\n\n const requestedPath = path ?? name ?? 'tango-app';\n const projectName = name ?? basename(requestedPath);\n const targetDir = resolve(process.cwd(), requestedPath);\n\n const context: FrameworkScaffoldContext = {\n projectName,\n targetDir,\n framework,\n packageManager,\n dialect,\n includeSeed,\n };\n\n await scaffoldProject(context, strategy, { force });\n\n if (install) {\n runInstall(packageManager, targetDir);\n }\n\n const logger = getLogger('tango.codegen');\n logger.info(`Scaffold complete: ${targetDir}`);\n logger.info(`Framework: ${strategy.name}`);\n logger.info(`Run next: cd ${targetDir} && ${packageManager} run dev`);\n}\nexport function withNewCommand(parser: Argv): Argv {\n return parser.command(\n 'new [name]',\n 'Bootstrap a new Tango project',\n (builder) =>\n builder\n .positional('name', {\n type: 'string',\n describe: 'Project name (used as directory when --path is omitted).',\n })\n .option('framework', {\n type: 'string',\n choices: Object.values(SUPPORTED_FRAMEWORK),\n demandOption: true,\n describe: 'Host framework scaffold to generate.',\n })\n .option('path', {\n type: 'string',\n describe: 'Target directory for generated project files.',\n })\n .option('package-manager', {\n type: 'string',\n choices: Object.values(PACKAGE_MANAGER),\n default: PACKAGE_MANAGER.PNPM,\n describe: 'Package manager used for follow-up instructions and optional install.',\n })\n .option('dialect', {\n type: 'string',\n choices: Object.values(SCAFFOLD_DATABASE_DIALECT),\n default: SCAFFOLD_DATABASE_DIALECT.SQLITE,\n describe: 'Database dialect default for generated config.',\n })\n .option('install', {\n type: 'boolean',\n default: false,\n describe: 'Install dependencies after scaffolding.',\n })\n .option('force', {\n type: 'boolean',\n default: false,\n describe: 'Allow writing into a non-empty target directory.',\n })\n .option('seed', {\n type: 'boolean',\n default: true,\n describe: 'Include seed/bootstrap sample artifacts when supported by the framework strategy.',\n }),\n async ({ name, framework, path, packageManager, dialect, install, force, seed }) => {\n await runNewCommand({\n name,\n framework,\n path,\n packageManager,\n dialect,\n install,\n force,\n seed,\n });\n }\n );\n}\n","import { extname, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { createJiti } from 'jiti';\nimport { ModelRegistry } from '@danceroutine/tango-schema';\n\nconst TS_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts']);\n\ntype ProjectModuleLoadResult = {\n loaded: Record<string, unknown>;\n modelTypeAccessors: Record<string, string>;\n registry: ModelRegistry;\n};\n\ntype ModelLike = { metadata: { key: string } };\ntype CollectedModelAccessors = {\n accessors: Record<string, string>;\n models: ModelLike[];\n};\n\nfunction isTypeScriptModule(modulePath: string): boolean {\n return TS_EXTENSIONS.has(extname(modulePath).toLowerCase());\n}\n\nfunction isModelLike(value: unknown): value is ModelLike {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'metadata' in value &&\n typeof (value as { metadata?: { key?: unknown } }).metadata?.key === 'string'\n );\n}\n\nfunction toImportSpecifier(absoluteModulePath: string, outputDir: string): string {\n const relativePath = relative(outputDir, absoluteModulePath).replaceAll('\\\\', '/');\n return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;\n}\n\nfunction collectModelTypeAccessors(\n loaded: Record<string, unknown>,\n importSpecifier: string,\n accessors: Map<string, string> = new Map()\n): CollectedModelAccessors {\n const models: ModelLike[] = [];\n\n const registerAccessor = (model: ModelLike, accessor: string): void => {\n models.push(model);\n const existing = accessors.get(model.metadata.key);\n if (!existing || accessor.length < existing.length) {\n accessors.set(model.metadata.key, accessor);\n }\n };\n\n const inspectValue = (value: unknown, accessorSegments: readonly string[]): void => {\n if (isModelLike(value)) {\n const accessor = accessorSegments.map((segment) => `[${JSON.stringify(segment)}]`).join('');\n registerAccessor(value, `typeof import(${JSON.stringify(importSpecifier)})${accessor}`);\n return;\n }\n\n if (typeof value !== 'object' || value === null) {\n return;\n }\n\n for (const [key, nested] of Object.entries(value)) {\n if (isModelLike(nested)) {\n const accessor = [...accessorSegments, key].map((segment) => `[${JSON.stringify(segment)}]`).join('');\n registerAccessor(nested, `typeof import(${JSON.stringify(importSpecifier)})${accessor}`);\n }\n }\n };\n\n for (const [key, value] of Object.entries(loaded)) {\n inspectValue(value, [key]);\n }\n\n return {\n accessors: Object.fromEntries(accessors),\n models,\n };\n}\n\n/**\n * Load a Tango app module and discover model export accessors suitable for\n * generated ambient type references.\n */\nexport async function loadProjectModule(\n modulePath: string,\n options?: { projectRoot?: string; outputDir?: string }\n): Promise<ProjectModuleLoadResult> {\n const projectRoot = options?.projectRoot ?? process.cwd();\n const absoluteModulePath = resolve(projectRoot, modulePath);\n const outputDir = options?.outputDir ?? resolve(projectRoot, '.tango');\n const registry = new ModelRegistry();\n\n const executeImport = async (): Promise<Record<string, unknown>> => {\n if (isTypeScriptModule(absoluteModulePath)) {\n const jiti = createJiti(resolve(projectRoot, 'tango.config.ts'), {\n interopDefault: true,\n moduleCache: false,\n });\n return (await jiti.import<Record<string, unknown>>(absoluteModulePath)) as Record<string, unknown>;\n }\n\n return (await import(pathToFileURL(absoluteModulePath).href)) as Record<string, unknown>;\n };\n\n const loaded = await ModelRegistry.runWithRegistry(registry, executeImport);\n const collected = collectModelTypeAccessors(loaded, toImportSpecifier(absoluteModulePath, outputDir));\n const effectiveRegistry =\n registry.values().length > 0\n ? registry\n : collected.models.length > 0\n ? (ModelRegistry.getOwner(collected.models[0] as never) as ModelRegistry)\n : registry;\n\n return {\n loaded,\n modelTypeAccessors: collected.accessors,\n registry: effectiveRegistry,\n };\n}\n","import { resolve } from 'node:path';\nimport { getLogger } from '@danceroutine/tango-core';\nimport {\n GENERATED_RELATION_REGISTRY_DIRNAME,\n GENERATED_RELATION_REGISTRY_METADATA_FILENAME,\n GENERATED_RELATION_REGISTRY_TYPES_FILENAME,\n} from '@danceroutine/tango-schema';\nimport type { Argv } from 'yargs';\nimport { writeRelationRegistryArtifacts } from '../generators/relations';\nimport { loadProjectModule } from './loadProjectModule';\n\nconst logger = getLogger('tango.codegen');\n\ntype GenerateRelationsCommandArgs = {\n models: string;\n outDir: string;\n};\n\n/**\n * Generate the app-local ambient relation registry from a finalized model graph.\n */\nexport async function runGenerateRelationsCommand({ models, outDir }: GenerateRelationsCommandArgs): Promise<void> {\n const outputDir = resolve(process.cwd(), outDir);\n const { registry, modelTypeAccessors } = await loadProjectModule(models, { outputDir });\n const written = await writeRelationRegistryArtifacts({\n registry,\n modelTypeAccessors,\n outputDir,\n });\n\n logger.info(`Generated relation registry: ${written.typesFilepath}`);\n logger.info(`Generated relation metadata: ${written.metadataFilepath}`);\n}\n\nexport function withGenerateRelationsCommand(parser: Argv): Argv {\n return parser.command(\n 'relations',\n 'Generate app-local ambient relation typing from Tango models',\n (builder) =>\n builder\n .option('models', {\n type: 'string',\n demandOption: true,\n describe: 'Path to the module exporting Tango Model definitions.',\n })\n .option('out-dir', {\n type: 'string',\n default: GENERATED_RELATION_REGISTRY_DIRNAME,\n describe: `Directory that receives ${GENERATED_RELATION_REGISTRY_TYPES_FILENAME} and ${GENERATED_RELATION_REGISTRY_METADATA_FILENAME}.`,\n }),\n async ({ models, outDir }) => {\n await runGenerateRelationsCommand({\n models,\n outDir,\n });\n }\n );\n}\n","import { getLogger } from '@danceroutine/tango-core';\nimport { readdir, readFile } from 'fs/promises';\nimport { resolve, basename, join } from 'path/posix';\nimport {\n type PackageManager,\n type SupportedFramework,\n FrameworkScaffoldRegistry,\n type FrameworkScaffoldContext,\n scaffoldProject,\n} from '../frameworks';\nimport {\n PACKAGE_MANAGER,\n SCAFFOLD_DATABASE_DIALECT,\n type ScaffoldDatabaseDialect,\n SUPPORTED_FRAMEWORK,\n} from '../frameworks/contracts/FrameworkScaffoldStrategy';\nimport type { Argv } from 'yargs';\n\nasync function detectPackageManager(targetDir: string): Promise<PackageManager> {\n try {\n const entries = await readdir(targetDir);\n if (entries.includes('pnpm-lock.yaml')) return PACKAGE_MANAGER.PNPM;\n if (entries.includes('package-lock.json')) return PACKAGE_MANAGER.NPM;\n if (entries.includes('yarn.lock')) return PACKAGE_MANAGER.YARN;\n if (entries.includes('bun.lockb') || entries.includes('bun.lock')) return PACKAGE_MANAGER.BUN;\n } catch {\n // ENOENT or other: fall through to default\n }\n return PACKAGE_MANAGER.PNPM;\n}\ntype InitCommandArgs = {\n framework: SupportedFramework;\n path: string;\n dialect: ScaffoldDatabaseDialect;\n skipExisting: boolean;\n force: boolean;\n};\nexport async function runInitCommand({\n framework,\n path,\n dialect,\n skipExisting,\n force,\n}: InitCommandArgs): Promise<void> {\n const registry = FrameworkScaffoldRegistry.createDefault();\n const strategy = registry.get(framework)!;\n const targetDir = resolve(process.cwd(), path);\n\n let projectName = basename(targetDir);\n try {\n const pkgPath = join(targetDir, 'package.json');\n const raw = await readFile(pkgPath, 'utf8');\n const pkg = JSON.parse(raw) as { name?: string };\n if (typeof pkg.name === 'string' && pkg.name.length > 0) {\n projectName = pkg.name;\n }\n } catch {\n // no package.json or invalid: keep basename\n }\n\n const packageManager = await detectPackageManager(targetDir);\n\n const context: FrameworkScaffoldContext = {\n projectName,\n targetDir,\n framework,\n packageManager,\n dialect,\n includeSeed: true,\n };\n\n await scaffoldProject(context, strategy, {\n mode: 'init',\n skipExisting,\n force,\n });\n\n const logger = getLogger('tango.codegen');\n logger.info(`Tango init complete: ${targetDir}`);\n logger.info(`Install dependencies: ${strategy.getTangoInstallOneLiner(packageManager, context)}`);\n if (framework === SUPPORTED_FRAMEWORK.EXPRESS) {\n logger.info(\"Mount Tango: import { registerTango } from './src/tango.js'; await registerTango(app);\");\n }\n if (framework === SUPPORTED_FRAMEWORK.NUXT) {\n logger.info(\n 'Wire Tango handlers: register Nitro serverHandlers in nuxt.config.ts and export NuxtAdapter-backed handlers from server/tango/.'\n );\n }\n}\nexport function withInitCommand(parser: Argv): Argv {\n return parser.command(\n 'init',\n 'Add Tango to an existing project (only Tango-layer files)',\n (builder) =>\n builder\n .option('framework', {\n type: 'string',\n choices: Object.values(SUPPORTED_FRAMEWORK),\n demandOption: true,\n describe: 'Host framework (express, next, or nuxt).',\n })\n .option('path', {\n type: 'string',\n default: '.',\n describe: 'Target directory (default: current directory).',\n })\n .option('dialect', {\n type: 'string',\n choices: Object.values(SCAFFOLD_DATABASE_DIALECT),\n default: SCAFFOLD_DATABASE_DIALECT.SQLITE,\n describe: 'Database dialect for generated config.',\n })\n .option('skip-existing', {\n type: 'boolean',\n default: true,\n describe: 'Do not overwrite existing files.',\n })\n .option('force', {\n type: 'boolean',\n default: false,\n describe: 'Overwrite existing files when set.',\n }),\n async ({ framework, path, dialect, skipExisting, force }) => {\n await runInitCommand({\n framework,\n path,\n dialect,\n skipExisting,\n force,\n });\n }\n );\n}\n","import type { Argv } from 'yargs';\nimport { withNewCommand } from './runNewCommand';\nimport { withGenerateRelationsCommand } from './runGenerateRelationsCommand';\nimport { withInitCommand } from './runInitCommand';\n\n/**\n * Register Tango project scaffolding commands on an existing CLI parser.\n */\nexport function registerCodegenCommands(parser: Argv): Argv {\n const withTopLevelNew = withNewCommand(parser);\n const withTopLevelInit = withInitCommand(withTopLevelNew);\n const withTopLevelRelations = withGenerateRelationsCommand(withTopLevelInit);\n return withTopLevelRelations.command('codegen <command>', 'Code generation command group', (builder) =>\n withGenerateRelationsCommand(withInitCommand(withNewCommand(builder)))\n );\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { registerCodegenCommands } from './registerCodegenCommands';\nexport { loadProjectModule } from './loadProjectModule';\nexport { runGenerateRelationsCommand, withGenerateRelationsCommand } from './runGenerateRelationsCommand';\n"],"mappings":"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"}
|
package/dist/frameworks/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { ExpressScaffoldStrategy, FrameworkScaffoldRegistry, FrameworkScaffoldStrategy, NextScaffoldStrategy, NuxtScaffoldStrategy, SCAFFOLD_TEMPLATE_CATEGORY, ScaffoldTemplateDescriptor, scaffoldProject } from "../frameworks-
|
|
1
|
+
import { ExpressScaffoldStrategy, FrameworkScaffoldRegistry, FrameworkScaffoldStrategy, NextScaffoldStrategy, NuxtScaffoldStrategy, SCAFFOLD_TEMPLATE_CATEGORY, ScaffoldTemplateDescriptor, scaffoldProject } from "../frameworks-CLOeazGj.js";
|
|
2
2
|
|
|
3
3
|
export { ExpressScaffoldStrategy, FrameworkScaffoldRegistry, FrameworkScaffoldStrategy, NextScaffoldStrategy, NuxtScaffoldStrategy, SCAFFOLD_TEMPLATE_CATEGORY, ScaffoldTemplateDescriptor, scaffoldProject };
|
|
@@ -31,7 +31,7 @@ var ScaffoldTemplateDescriptor = class {
|
|
|
31
31
|
//#endregion
|
|
32
32
|
//#region package.json
|
|
33
33
|
var name = "@danceroutine/tango-codegen";
|
|
34
|
-
var version$1 = "1.
|
|
34
|
+
var version$1 = "1.5.0";
|
|
35
35
|
var description = "CLI for generating repositories, types, migrations, and OpenAPI specs for Tango";
|
|
36
36
|
var type = "module";
|
|
37
37
|
var main = "./dist/index.js";
|
|
@@ -83,14 +83,18 @@ var repository = {
|
|
|
83
83
|
};
|
|
84
84
|
var dependencies = {
|
|
85
85
|
"@danceroutine/tango-core": "workspace:*",
|
|
86
|
+
"@danceroutine/tango-schema": "workspace:*",
|
|
87
|
+
"jiti": "^2.6.1",
|
|
86
88
|
"yargs": "^17.7.2"
|
|
87
89
|
};
|
|
88
90
|
var devDependencies = {
|
|
91
|
+
"@danceroutine/tango-testing": "workspace:*",
|
|
89
92
|
"@types/yargs": "^17.0.33",
|
|
90
93
|
"@types/node": "^22.9.0",
|
|
91
94
|
"tsdown": "^0.4.0",
|
|
92
95
|
"typescript": "^5.6.3",
|
|
93
|
-
"vitest": "^4.0.6"
|
|
96
|
+
"vitest": "^4.0.6",
|
|
97
|
+
"zod": "^4.0.0"
|
|
94
98
|
};
|
|
95
99
|
var package_default = {
|
|
96
100
|
name,
|
|
@@ -248,6 +252,7 @@ var PackageJsonTemplateBuilder$2 = class extends TemplateBuilder {
|
|
|
248
252
|
typecheck: "tsc --noEmit",
|
|
249
253
|
"setup:schema": "node -e \"require('node:fs').mkdirSync('./.data',{recursive:true})\" && tango migrate --config ./tango.config.ts",
|
|
250
254
|
"make:migrations": "tango make:migrations --config ./tango.config.ts --models ./src/models/index.ts --name \"\${npm_config_name:-manual_change}\"",
|
|
255
|
+
"codegen:relations": "tango codegen relations --models ./src/models/index.ts",
|
|
251
256
|
prebootstrap: "node -e \"require('node:fs').mkdirSync('./.data',{recursive:true})\" && tango migrate --config ./tango.config.ts",
|
|
252
257
|
bootstrap: "tsx src/bootstrap.ts"
|
|
253
258
|
},
|
|
@@ -649,10 +654,13 @@ ${context.packageManager} run make:migrations --name initial
|
|
|
649
654
|
${context.packageManager} run dev
|
|
650
655
|
\`\`\`
|
|
651
656
|
|
|
657
|
+
\`make:migrations\` also refreshes the generated relation registry for the scaffolded model module. If you later change relation metadata without needing a new migration file, run \`${context.packageManager} run codegen:relations\`.
|
|
658
|
+
|
|
652
659
|
## Scripts
|
|
653
660
|
|
|
654
661
|
- \`${context.packageManager} run dev\`
|
|
655
662
|
- \`${context.packageManager} run make:migrations --name add_field\`
|
|
663
|
+
- \`${context.packageManager} run codegen:relations\`
|
|
656
664
|
- \`${context.packageManager} run setup:schema\`
|
|
657
665
|
- \`${context.packageManager} run bootstrap\`
|
|
658
666
|
- \`${context.packageManager} run typecheck\`
|
|
@@ -673,6 +681,7 @@ ${context.packageManager} run dev
|
|
|
673
681
|
- \`src/openapi.ts\` OpenAPI document generation
|
|
674
682
|
- \`src/bootstrap.ts\` seed utility for a larger demo dataset
|
|
675
683
|
- \`migrations/\` checked-in Tango migrations
|
|
684
|
+
- \`.tango/\` generated relation typing artifacts
|
|
676
685
|
`;
|
|
677
686
|
}
|
|
678
687
|
};
|
|
@@ -757,6 +766,7 @@ var PackageJsonTemplateBuilder$1 = class extends TemplateBuilder {
|
|
|
757
766
|
typecheck: "tsc --noEmit",
|
|
758
767
|
"setup:schema": "node -e \"require('node:fs').mkdirSync('./.data',{recursive:true})\" && tango migrate --config ./tango.config.ts",
|
|
759
768
|
"make:migrations": "tango make:migrations --config ./tango.config.ts --models ./src/lib/models/index.ts --name \"\${npm_config_name:-manual_change}\"",
|
|
769
|
+
"codegen:relations": "tango codegen relations --models ./src/lib/models/index.ts",
|
|
760
770
|
prebootstrap: "node -e \"require('node:fs').mkdirSync('./.data',{recursive:true})\" && tango migrate --config ./tango.config.ts",
|
|
761
771
|
bootstrap: "tsx scripts/bootstrap.ts"
|
|
762
772
|
},
|
|
@@ -1205,10 +1215,13 @@ ${context.packageManager} run make:migrations --name initial
|
|
|
1205
1215
|
${context.packageManager} run dev
|
|
1206
1216
|
\`\`\`
|
|
1207
1217
|
|
|
1218
|
+
\`make:migrations\` also refreshes the generated relation registry for the scaffolded model module. If you later change relation metadata without needing a new migration file, run \`${context.packageManager} run codegen:relations\`.
|
|
1219
|
+
|
|
1208
1220
|
## Scripts
|
|
1209
1221
|
|
|
1210
1222
|
- \`${context.packageManager} run dev\`
|
|
1211
1223
|
- \`${context.packageManager} run make:migrations --name add_field\`
|
|
1224
|
+
- \`${context.packageManager} run codegen:relations\`
|
|
1212
1225
|
- \`${context.packageManager} run setup:schema\`
|
|
1213
1226
|
- \`${context.packageManager} run bootstrap\`
|
|
1214
1227
|
- \`${context.packageManager} run typecheck\`
|
|
@@ -1230,6 +1243,7 @@ ${context.packageManager} run dev
|
|
|
1230
1243
|
- \`src/lib/openapi.ts\` OpenAPI document generation
|
|
1231
1244
|
- \`scripts/bootstrap.ts\` seed utility for a larger demo dataset
|
|
1232
1245
|
- \`migrations/\` checked-in Tango migrations
|
|
1246
|
+
- \`.tango/\` generated relation typing artifacts
|
|
1233
1247
|
`;
|
|
1234
1248
|
}
|
|
1235
1249
|
};
|
|
@@ -1291,6 +1305,7 @@ var PackageJsonTemplateBuilder = class extends TemplateBuilder {
|
|
|
1291
1305
|
typecheck: "NUXT_TELEMETRY_DISABLED=1 nuxt typecheck",
|
|
1292
1306
|
"setup:schema": "pnpm exec tango migrate --config ./tango.config.ts",
|
|
1293
1307
|
"make:migrations": "pnpm exec tango make:migrations --config ./tango.config.ts --models ./lib/models/index.ts --name \"\${npm_config_name:-manual_change}\"",
|
|
1308
|
+
"codegen:relations": "pnpm exec tango codegen relations --models ./lib/models/index.ts",
|
|
1294
1309
|
prebootstrap: "pnpm run setup:schema",
|
|
1295
1310
|
bootstrap: "tsx scripts/bootstrap.ts"
|
|
1296
1311
|
},
|
|
@@ -1725,10 +1740,13 @@ ${context.packageManager} run make:migrations --name initial
|
|
|
1725
1740
|
${context.packageManager} run dev
|
|
1726
1741
|
\`\`\`
|
|
1727
1742
|
|
|
1743
|
+
\`make:migrations\` also refreshes the generated relation registry for the scaffolded model module. If you later change relation metadata without needing a new migration file, run \`${context.packageManager} run codegen:relations\`.
|
|
1744
|
+
|
|
1728
1745
|
## Scripts
|
|
1729
1746
|
|
|
1730
1747
|
- \`${context.packageManager} run dev\`
|
|
1731
1748
|
- \`${context.packageManager} run make:migrations --name add_field\`
|
|
1749
|
+
- \`${context.packageManager} run codegen:relations\`
|
|
1732
1750
|
- \`${context.packageManager} run setup:schema\`
|
|
1733
1751
|
- \`${context.packageManager} run bootstrap\`
|
|
1734
1752
|
- \`${context.packageManager} run typecheck\`
|
|
@@ -1751,6 +1769,7 @@ ${context.packageManager} run dev
|
|
|
1751
1769
|
- \`lib/openapi.ts\` OpenAPI document generation
|
|
1752
1770
|
- \`scripts/bootstrap.ts\` seed utility for a larger demo dataset
|
|
1753
1771
|
- \`migrations/\` checked-in Tango migrations
|
|
1772
|
+
- \`.tango/\` generated relation typing artifacts
|
|
1754
1773
|
`;
|
|
1755
1774
|
}
|
|
1756
1775
|
};
|
|
@@ -1886,4 +1905,4 @@ __export(frameworks_exports, {
|
|
|
1886
1905
|
|
|
1887
1906
|
//#endregion
|
|
1888
1907
|
export { ExpressScaffoldStrategy, FrameworkScaffoldRegistry, FrameworkScaffoldStrategy, NextScaffoldStrategy, NuxtScaffoldStrategy, PACKAGE_MANAGER, SCAFFOLD_DATABASE_DIALECT, SCAFFOLD_TEMPLATE_CATEGORY, SUPPORTED_FRAMEWORK, ScaffoldTemplateDescriptor, frameworks_exports, scaffoldProject };
|
|
1889
|
-
//# sourceMappingURL=frameworks-
|
|
1908
|
+
//# sourceMappingURL=frameworks-CLOeazGj.js.map
|