@danceroutine/tango-codegen 0.1.0 → 1.0.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/LICENSE +21 -0
- package/README.md +93 -0
- package/dist/chunk-BkvOhyD0.js +12 -0
- package/dist/{generators/repository → commands}/index.d.ts +1 -1
- package/dist/commands/index.js +4 -0
- package/dist/commands/registerCodegenCommands.d.ts +5 -0
- package/dist/commands/runInitCommand.d.ts +13 -0
- package/dist/commands/runInstall.d.ts +2 -0
- package/dist/commands/runNewCommand.d.ts +16 -0
- package/dist/commands-C2Xr9uRE.js +186 -0
- package/dist/commands-C2Xr9uRE.js.map +1 -0
- package/dist/frameworks/contracts/FrameworkScaffoldStrategy.d.ts +39 -0
- package/dist/frameworks/contracts/template/ScaffoldTemplate.d.ts +22 -0
- package/dist/frameworks/contracts/template/TemplateBuilder.d.ts +40 -0
- package/dist/frameworks/contracts/template/implementation/ScaffoldTemplateDescriptor.d.ts +10 -0
- package/dist/frameworks/index.d.ts +11 -0
- package/dist/frameworks/index.js +3 -0
- package/dist/frameworks/registry/FrameworkScaffoldRegistry.d.ts +23 -0
- package/dist/frameworks/scaffold/scaffoldProject.d.ts +17 -0
- package/dist/frameworks/strategies/express/ExpressScaffoldStrategy.d.ts +14 -0
- package/dist/frameworks/strategies/express/templates/appSource.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/bootstrap.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/models.d.ts +10 -0
- package/dist/frameworks/strategies/express/templates/openapi.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/packageJson.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/readme.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/serializers.d.ts +10 -0
- package/dist/frameworks/strategies/express/templates/tangoConfig.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/tangoRegister.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/tsconfig.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/tsconfigBuild.d.ts +6 -0
- package/dist/frameworks/strategies/express/templates/viewSet.d.ts +6 -0
- package/dist/frameworks/strategies/next/NextScaffoldStrategy.d.ts +14 -0
- package/dist/frameworks/strategies/next/templates/bootstrap.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/healthRoute.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/layout.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/models.d.ts +11 -0
- package/dist/frameworks/strategies/next/templates/openapi.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/openapiRoute.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/packageJson.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/page.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/readme.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/serializers.d.ts +10 -0
- package/dist/frameworks/strategies/next/templates/tangoConfig.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/todoRoute.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/tsconfig.d.ts +6 -0
- package/dist/frameworks/strategies/next/templates/viewSet.d.ts +6 -0
- package/dist/frameworks-Bp_9BOt2.js +1366 -0
- package/dist/frameworks-Bp_9BOt2.js.map +1 -0
- package/dist/generators/index.d.ts +0 -2
- package/dist/generators/index.js +2 -2
- package/dist/generators/migration/generateMigrationFromModels.d.ts +6 -0
- package/dist/generators/model/generateModelInterface.d.ts +3 -0
- package/dist/generators/viewset/generateViewSet.d.ts +3 -0
- package/dist/{generators-CDXkQAkq.js → generators-C9UeakCq.js} +18 -55
- package/dist/generators-C9UeakCq.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +4 -7
- package/dist/mappers/fieldType.d.ts +6 -0
- package/package.json +60 -48
- package/dist/generators/repository/generateRepository.d.ts +0 -1
- package/dist/generators-CDXkQAkq.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mappers/fieldType.js +0 -32
- package/dist/version.d.ts +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Pedro Del Moral Lopez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @danceroutine/tango-codegen
|
|
2
|
+
|
|
3
|
+
`@danceroutine/tango-codegen` generates Tango-oriented source files and project scaffolding.
|
|
4
|
+
|
|
5
|
+
This package automates the repetitive parts of bootstrapping a Tango application while keeping the generated output aligned with Tango's architecture.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add -D @danceroutine/tango-codegen
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Most application developers will use this package through `@danceroutine/tango-cli`, because the `tango new` workflow is composed there.
|
|
14
|
+
|
|
15
|
+
## What the package does
|
|
16
|
+
|
|
17
|
+
The package has two related jobs:
|
|
18
|
+
|
|
19
|
+
- scaffold full Tango applications for supported host frameworks
|
|
20
|
+
- expose programmatic generators and mapping helpers for Tango-shaped source code
|
|
21
|
+
|
|
22
|
+
The scaffold strategies are the primary public workflow. The lower-level generators are useful when you are building internal automation, editor tooling, or custom project bootstrapping around Tango conventions.
|
|
23
|
+
|
|
24
|
+
## Scaffolding a project
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
tango new my-app --framework express --package-manager pnpm --dialect sqlite
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Generated applications include:
|
|
31
|
+
|
|
32
|
+
- `tango.config.ts`
|
|
33
|
+
- model definitions that expose `Model.objects`
|
|
34
|
+
- adapter-backed CRUD resources
|
|
35
|
+
- migration scripts and seed/bootstrap wiring
|
|
36
|
+
- host-framework entrypoints that keep Tango-specific setup out of application glue
|
|
37
|
+
|
|
38
|
+
## Programmatic API example
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { generateMigrationFromModels, generateModelInterface, generateViewSet } from '@danceroutine/tango-codegen';
|
|
42
|
+
|
|
43
|
+
const modelSource = generateModelInterface({
|
|
44
|
+
name: 'Post',
|
|
45
|
+
fields: {
|
|
46
|
+
id: { type: 'serial', primaryKey: true },
|
|
47
|
+
title: { type: 'string' },
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const viewSetSource = generateViewSet('Post');
|
|
52
|
+
const migrationSource = generateMigrationFromModels([
|
|
53
|
+
{
|
|
54
|
+
name: 'Post',
|
|
55
|
+
fields: {
|
|
56
|
+
id: { type: 'serial', primaryKey: true },
|
|
57
|
+
title: { type: 'string' },
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Generated code should still be reviewed and adapted for the application.
|
|
64
|
+
|
|
65
|
+
## Public API
|
|
66
|
+
|
|
67
|
+
The root export includes:
|
|
68
|
+
|
|
69
|
+
- generators such as `generateModelInterface`, `generateMigrationFromModels`, and `generateViewSet`
|
|
70
|
+
- mapping helpers such as `mapFieldTypeToTS` and `normalizeFields`
|
|
71
|
+
- framework scaffolding types and helpers such as `FrameworkScaffoldRegistry` and `scaffoldProject`
|
|
72
|
+
- `registerCodegenCommands()`, which mounts the code-generation command tree into the shared CLI
|
|
73
|
+
|
|
74
|
+
You can import from the root for normal use, or drill into `domain`, `generators`, `mappers`, `frameworks`, and `commands` when you need a narrower boundary.
|
|
75
|
+
|
|
76
|
+
## Developer workflow
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pnpm --filter @danceroutine/tango-codegen build
|
|
80
|
+
pnpm --filter @danceroutine/tango-codegen typecheck
|
|
81
|
+
pnpm --filter @danceroutine/tango-codegen test
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Bugs and support
|
|
85
|
+
|
|
86
|
+
- Documentation: <https://tangowebframework.dev>
|
|
87
|
+
- CLI reference: <https://tangowebframework.dev/reference/cli-api>
|
|
88
|
+
- Architecture topic: <https://tangowebframework.dev/topics/architecture>
|
|
89
|
+
- Issue tracker: <https://github.com/danceroutine/tango/issues>
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type SupportedFramework } from '../frameworks';
|
|
2
|
+
import { type ScaffoldDatabaseDialect } from '../frameworks/contracts/FrameworkScaffoldStrategy';
|
|
3
|
+
import type { Argv } from 'yargs';
|
|
4
|
+
type InitCommandArgs = {
|
|
5
|
+
framework: SupportedFramework;
|
|
6
|
+
path: string;
|
|
7
|
+
dialect: ScaffoldDatabaseDialect;
|
|
8
|
+
skipExisting: boolean;
|
|
9
|
+
force: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function runInitCommand({ framework, path, dialect, skipExisting, force, }: InitCommandArgs): Promise<void>;
|
|
12
|
+
export declare function withInitCommand(parser: Argv): Argv;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type SupportedFramework, type PackageManager } from '../frameworks';
|
|
2
|
+
import { type ScaffoldDatabaseDialect } from '../frameworks/contracts/FrameworkScaffoldStrategy';
|
|
3
|
+
import type { Argv } from 'yargs';
|
|
4
|
+
type NewCommandArgs = {
|
|
5
|
+
name?: string;
|
|
6
|
+
framework: SupportedFramework;
|
|
7
|
+
path?: string;
|
|
8
|
+
packageManager: PackageManager;
|
|
9
|
+
dialect: ScaffoldDatabaseDialect;
|
|
10
|
+
install: boolean;
|
|
11
|
+
force: boolean;
|
|
12
|
+
seed: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function runNewCommand({ path, name, framework, packageManager, dialect, install, force, seed: includeSeed, }: NewCommandArgs): Promise<void>;
|
|
15
|
+
export declare function withNewCommand(parser: Argv): Argv;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { __export } from "./chunk-BkvOhyD0.js";
|
|
2
|
+
import { FrameworkScaffoldRegistry, PACKAGE_MANAGER, SCAFFOLD_DATABASE_DIALECT, SUPPORTED_FRAMEWORK, scaffoldProject } from "./frameworks-Bp_9BOt2.js";
|
|
3
|
+
import { getLogger, getLogger as getLogger$1 } from "@danceroutine/tango-core";
|
|
4
|
+
import { basename, basename as basename$1, join, resolve, resolve as resolve$1 } from "path/posix";
|
|
5
|
+
import { spawnSync } from "child_process";
|
|
6
|
+
import { readFile, readdir } from "fs/promises";
|
|
7
|
+
|
|
8
|
+
//#region src/commands/runInstall.ts
|
|
9
|
+
function runInstall(packageManager, cwd) {
|
|
10
|
+
const argsByPackageManager = {
|
|
11
|
+
pnpm: ["install"],
|
|
12
|
+
npm: ["install"],
|
|
13
|
+
yarn: ["install"],
|
|
14
|
+
bun: ["install"]
|
|
15
|
+
};
|
|
16
|
+
const result = spawnSync(packageManager, [...argsByPackageManager[packageManager]], {
|
|
17
|
+
cwd,
|
|
18
|
+
stdio: "inherit",
|
|
19
|
+
env: process.env
|
|
20
|
+
});
|
|
21
|
+
if (result.status !== 0) throw new Error(`Dependency install failed with ${packageManager}. Exit code: ${String(result.status ?? "unknown")}.`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/commands/runNewCommand.ts
|
|
26
|
+
async function runNewCommand({ path, name, framework, packageManager, dialect, install, force, seed: includeSeed }) {
|
|
27
|
+
const registry = FrameworkScaffoldRegistry.createDefault();
|
|
28
|
+
const strategy = registry.get(framework);
|
|
29
|
+
const requestedPath = path ?? name ?? "tango-app";
|
|
30
|
+
const projectName = name ?? basename$1(requestedPath);
|
|
31
|
+
const targetDir = resolve$1(process.cwd(), requestedPath);
|
|
32
|
+
const context = {
|
|
33
|
+
projectName,
|
|
34
|
+
targetDir,
|
|
35
|
+
framework,
|
|
36
|
+
packageManager,
|
|
37
|
+
dialect,
|
|
38
|
+
includeSeed
|
|
39
|
+
};
|
|
40
|
+
await scaffoldProject(context, strategy, { force });
|
|
41
|
+
if (install) runInstall(packageManager, targetDir);
|
|
42
|
+
const logger = getLogger$1("tango.codegen");
|
|
43
|
+
logger.info(`Scaffold complete: ${targetDir}`);
|
|
44
|
+
logger.info(`Framework: ${strategy.name}`);
|
|
45
|
+
logger.info(`Run next: cd ${targetDir} && ${packageManager} run dev`);
|
|
46
|
+
}
|
|
47
|
+
function withNewCommand(parser) {
|
|
48
|
+
return parser.command("new [name]", "Bootstrap a new Tango project", (builder) => builder.positional("name", {
|
|
49
|
+
type: "string",
|
|
50
|
+
describe: "Project name (used as directory when --path is omitted)."
|
|
51
|
+
}).option("framework", {
|
|
52
|
+
type: "string",
|
|
53
|
+
choices: Object.values(SUPPORTED_FRAMEWORK),
|
|
54
|
+
demandOption: true,
|
|
55
|
+
describe: "Host framework scaffold to generate."
|
|
56
|
+
}).option("path", {
|
|
57
|
+
type: "string",
|
|
58
|
+
describe: "Target directory for generated project files."
|
|
59
|
+
}).option("package-manager", {
|
|
60
|
+
type: "string",
|
|
61
|
+
choices: Object.values(PACKAGE_MANAGER),
|
|
62
|
+
default: PACKAGE_MANAGER.PNPM,
|
|
63
|
+
describe: "Package manager used for follow-up instructions and optional install."
|
|
64
|
+
}).option("dialect", {
|
|
65
|
+
type: "string",
|
|
66
|
+
choices: Object.values(SCAFFOLD_DATABASE_DIALECT),
|
|
67
|
+
default: SCAFFOLD_DATABASE_DIALECT.SQLITE,
|
|
68
|
+
describe: "Database dialect default for generated config."
|
|
69
|
+
}).option("install", {
|
|
70
|
+
type: "boolean",
|
|
71
|
+
default: false,
|
|
72
|
+
describe: "Install dependencies after scaffolding."
|
|
73
|
+
}).option("force", {
|
|
74
|
+
type: "boolean",
|
|
75
|
+
default: false,
|
|
76
|
+
describe: "Allow writing into a non-empty target directory."
|
|
77
|
+
}).option("seed", {
|
|
78
|
+
type: "boolean",
|
|
79
|
+
default: true,
|
|
80
|
+
describe: "Include seed/bootstrap sample artifacts when supported by the framework strategy."
|
|
81
|
+
}), async ({ name, framework, path, packageManager, dialect, install, force, seed }) => {
|
|
82
|
+
await runNewCommand({
|
|
83
|
+
name,
|
|
84
|
+
framework,
|
|
85
|
+
path,
|
|
86
|
+
packageManager,
|
|
87
|
+
dialect,
|
|
88
|
+
install,
|
|
89
|
+
force,
|
|
90
|
+
seed
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/commands/runInitCommand.ts
|
|
97
|
+
async function detectPackageManager(targetDir) {
|
|
98
|
+
try {
|
|
99
|
+
const entries = await readdir(targetDir);
|
|
100
|
+
if (entries.includes("pnpm-lock.yaml")) return PACKAGE_MANAGER.PNPM;
|
|
101
|
+
if (entries.includes("package-lock.json")) return PACKAGE_MANAGER.NPM;
|
|
102
|
+
if (entries.includes("yarn.lock")) return PACKAGE_MANAGER.YARN;
|
|
103
|
+
if (entries.includes("bun.lockb") || entries.includes("bun.lock")) return PACKAGE_MANAGER.BUN;
|
|
104
|
+
} catch {}
|
|
105
|
+
return PACKAGE_MANAGER.PNPM;
|
|
106
|
+
}
|
|
107
|
+
async function runInitCommand({ framework, path, dialect, skipExisting, force }) {
|
|
108
|
+
const registry = FrameworkScaffoldRegistry.createDefault();
|
|
109
|
+
const strategy = registry.get(framework);
|
|
110
|
+
const targetDir = resolve(process.cwd(), path);
|
|
111
|
+
let projectName = basename(targetDir);
|
|
112
|
+
try {
|
|
113
|
+
const pkgPath = join(targetDir, "package.json");
|
|
114
|
+
const raw = await readFile(pkgPath, "utf8");
|
|
115
|
+
const pkg = JSON.parse(raw);
|
|
116
|
+
if (typeof pkg.name === "string" && pkg.name.length > 0) projectName = pkg.name;
|
|
117
|
+
} catch {}
|
|
118
|
+
const packageManager = await detectPackageManager(targetDir);
|
|
119
|
+
const context = {
|
|
120
|
+
projectName,
|
|
121
|
+
targetDir,
|
|
122
|
+
framework,
|
|
123
|
+
packageManager,
|
|
124
|
+
dialect,
|
|
125
|
+
includeSeed: true
|
|
126
|
+
};
|
|
127
|
+
await scaffoldProject(context, strategy, {
|
|
128
|
+
mode: "init",
|
|
129
|
+
skipExisting,
|
|
130
|
+
force
|
|
131
|
+
});
|
|
132
|
+
const logger = getLogger("tango.codegen");
|
|
133
|
+
logger.info(`Tango init complete: ${targetDir}`);
|
|
134
|
+
logger.info(`Install dependencies: ${strategy.getTangoInstallOneLiner(packageManager, context)}`);
|
|
135
|
+
if (framework === SUPPORTED_FRAMEWORK.EXPRESS) logger.info("Mount Tango: import { registerTango } from './src/tango.js'; await registerTango(app);");
|
|
136
|
+
}
|
|
137
|
+
function withInitCommand(parser) {
|
|
138
|
+
return parser.command("init", "Add Tango to an existing project (only Tango-layer files)", (builder) => builder.option("framework", {
|
|
139
|
+
type: "string",
|
|
140
|
+
choices: Object.values(SUPPORTED_FRAMEWORK),
|
|
141
|
+
demandOption: true,
|
|
142
|
+
describe: "Host framework (express or next)."
|
|
143
|
+
}).option("path", {
|
|
144
|
+
type: "string",
|
|
145
|
+
default: ".",
|
|
146
|
+
describe: "Target directory (default: current directory)."
|
|
147
|
+
}).option("dialect", {
|
|
148
|
+
type: "string",
|
|
149
|
+
choices: Object.values(SCAFFOLD_DATABASE_DIALECT),
|
|
150
|
+
default: SCAFFOLD_DATABASE_DIALECT.SQLITE,
|
|
151
|
+
describe: "Database dialect for generated config."
|
|
152
|
+
}).option("skip-existing", {
|
|
153
|
+
type: "boolean",
|
|
154
|
+
default: true,
|
|
155
|
+
describe: "Do not overwrite existing files."
|
|
156
|
+
}).option("force", {
|
|
157
|
+
type: "boolean",
|
|
158
|
+
default: false,
|
|
159
|
+
describe: "Overwrite existing files when set."
|
|
160
|
+
}), async ({ framework, path, dialect, skipExisting, force }) => {
|
|
161
|
+
await runInitCommand({
|
|
162
|
+
framework,
|
|
163
|
+
path,
|
|
164
|
+
dialect,
|
|
165
|
+
skipExisting,
|
|
166
|
+
force
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/commands/registerCodegenCommands.ts
|
|
173
|
+
function registerCodegenCommands(parser) {
|
|
174
|
+
const withTopLevelNew = withNewCommand(parser);
|
|
175
|
+
const withTopLevelInit = withInitCommand(withTopLevelNew);
|
|
176
|
+
return withTopLevelInit.command("codegen <command>", "Code generation command group", (builder) => withInitCommand(withNewCommand(builder)));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/commands/index.ts
|
|
181
|
+
var commands_exports = {};
|
|
182
|
+
__export(commands_exports, { registerCodegenCommands: () => registerCodegenCommands });
|
|
183
|
+
|
|
184
|
+
//#endregion
|
|
185
|
+
export { commands_exports, registerCodegenCommands };
|
|
186
|
+
//# sourceMappingURL=commands-C2Xr9uRE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands-C2Xr9uRE.js","names":["packageManager: PackageManager","cwd: string","argsByPackageManager: Record<PackageManager, readonly string[]>","context: FrameworkScaffoldContext","parser: Argv","targetDir: string","context: FrameworkScaffoldContext","parser: Argv","parser: Argv"],"sources":["../src/commands/runInstall.ts","../src/commands/runNewCommand.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 { 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}\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 or next).',\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 { 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 return withTopLevelInit.command('codegen <command>', 'Code generation command group', (builder) =>\n withInitCommand(withNewCommand(builder))\n );\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { registerCodegenCommands } from './registerCodegenCommands';\n"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ScaffoldTemplate, type FrameworkScaffoldContext } from './template/ScaffoldTemplate';
|
|
2
|
+
import { TemplateBuilder } from './template/TemplateBuilder';
|
|
3
|
+
export declare const SUPPORTED_FRAMEWORK: {
|
|
4
|
+
readonly EXPRESS: "express";
|
|
5
|
+
readonly NEXT: "next";
|
|
6
|
+
};
|
|
7
|
+
export type SupportedFramework = (typeof SUPPORTED_FRAMEWORK)[keyof typeof SUPPORTED_FRAMEWORK];
|
|
8
|
+
export declare const PACKAGE_MANAGER: {
|
|
9
|
+
readonly PNPM: "pnpm";
|
|
10
|
+
readonly NPM: "npm";
|
|
11
|
+
readonly YARN: "yarn";
|
|
12
|
+
readonly BUN: "bun";
|
|
13
|
+
};
|
|
14
|
+
export type PackageManager = (typeof PACKAGE_MANAGER)[keyof typeof PACKAGE_MANAGER];
|
|
15
|
+
export declare const SCAFFOLD_DATABASE_DIALECT: {
|
|
16
|
+
readonly SQLITE: "sqlite";
|
|
17
|
+
readonly POSTGRES: "postgres";
|
|
18
|
+
};
|
|
19
|
+
export type ScaffoldDatabaseDialect = (typeof SCAFFOLD_DATABASE_DIALECT)[keyof typeof SCAFFOLD_DATABASE_DIALECT];
|
|
20
|
+
/**
|
|
21
|
+
* Base scaffold strategy contract and helpers for Tango framework scaffolds.
|
|
22
|
+
*
|
|
23
|
+
* Concrete strategies extend this class and assemble their template lists
|
|
24
|
+
* through the protected helpers below.
|
|
25
|
+
*/
|
|
26
|
+
export declare abstract class FrameworkScaffoldStrategy {
|
|
27
|
+
abstract readonly id: SupportedFramework;
|
|
28
|
+
abstract readonly name: string;
|
|
29
|
+
abstract readonly description: string;
|
|
30
|
+
/**
|
|
31
|
+
* One-liner to install Tango + dialect deps and Tango CLI, for init success message.
|
|
32
|
+
*/
|
|
33
|
+
getTangoInstallOneLiner(packageManager: PackageManager, context: FrameworkScaffoldContext): string;
|
|
34
|
+
abstract getTemplates(): readonly ScaffoldTemplate[];
|
|
35
|
+
protected addFrameworkTemplate(template: TemplateBuilder): ScaffoldTemplate;
|
|
36
|
+
protected addTangoTemplate(template: TemplateBuilder): ScaffoldTemplate;
|
|
37
|
+
protected addInitOnlyTemplate(template: TemplateBuilder): ScaffoldTemplate;
|
|
38
|
+
private createTemplate;
|
|
39
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SupportedFramework, PackageManager, ScaffoldDatabaseDialect } from '../FrameworkScaffoldStrategy';
|
|
2
|
+
export declare const SCAFFOLD_TEMPLATE_CATEGORY: {
|
|
3
|
+
readonly FRAMEWORK: "framework";
|
|
4
|
+
readonly TANGO: "tango";
|
|
5
|
+
readonly INIT_ONLY: "init-only";
|
|
6
|
+
};
|
|
7
|
+
export type ScaffoldTemplateCategory = (typeof SCAFFOLD_TEMPLATE_CATEGORY)[keyof typeof SCAFFOLD_TEMPLATE_CATEGORY];
|
|
8
|
+
export type ScaffoldMode = 'new' | 'init';
|
|
9
|
+
export type FrameworkScaffoldContext = {
|
|
10
|
+
projectName: string;
|
|
11
|
+
targetDir: string;
|
|
12
|
+
framework: SupportedFramework;
|
|
13
|
+
packageManager: PackageManager;
|
|
14
|
+
dialect: ScaffoldDatabaseDialect;
|
|
15
|
+
includeSeed: boolean;
|
|
16
|
+
};
|
|
17
|
+
export interface ScaffoldTemplate {
|
|
18
|
+
readonly path: string;
|
|
19
|
+
readonly category: ScaffoldTemplateCategory;
|
|
20
|
+
render(ctx: FrameworkScaffoldContext): string;
|
|
21
|
+
shouldEmit(mode: ScaffoldMode): boolean;
|
|
22
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { FrameworkScaffoldContext } from './ScaffoldTemplate';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for a context-bound template that the strategy's add* methods accept.
|
|
4
|
+
* Implemented by bound TemplateBuilder instances and by the return value of createStaticTemplate.
|
|
5
|
+
*/
|
|
6
|
+
export interface BoundTemplate {
|
|
7
|
+
getPath(): string;
|
|
8
|
+
build(): string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Base class for scaffold template builders. Subclasses override resolveTemplate().
|
|
12
|
+
* Use new WhateverBuilder().setContext(context) for registration with add* methods.
|
|
13
|
+
* Deps logic (getTangoDependencyEntries, getTangoDevDependencyEntries) and version live here.
|
|
14
|
+
*/
|
|
15
|
+
export declare abstract class TemplateBuilder implements BoundTemplate {
|
|
16
|
+
protected readonly name: string;
|
|
17
|
+
protected _context?: FrameworkScaffoldContext;
|
|
18
|
+
constructor(options: {
|
|
19
|
+
name: string;
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* One-liner to install Tango + dialect deps and Tango CLI (for init success message).
|
|
23
|
+
*/
|
|
24
|
+
static getTangoInstallOneLiner(packageManager: string, dialect: 'sqlite' | 'postgres', framework: 'express' | 'next'): string;
|
|
25
|
+
/**
|
|
26
|
+
* Shorthand for static content (no subclass needed). Returns a BoundTemplate that add* methods accept.
|
|
27
|
+
*/
|
|
28
|
+
static createStaticTemplate(fileName: string, template: string | (() => string)): TemplateBuilder;
|
|
29
|
+
/** Tango package version (semver range) for scaffolded dependency entries. */
|
|
30
|
+
private static getTangoVersion;
|
|
31
|
+
private static getTangoDependencyEntriesFor;
|
|
32
|
+
private static getTangoDevDependencyEntriesFor;
|
|
33
|
+
/** Bind context and return this for chaining. Use before passing to add* methods. */
|
|
34
|
+
setContext(context: FrameworkScaffoldContext): this;
|
|
35
|
+
getPath(): string;
|
|
36
|
+
protected abstract resolveTemplate(context: FrameworkScaffoldContext): string;
|
|
37
|
+
build(): string;
|
|
38
|
+
protected getTangoDependencyEntries(context: FrameworkScaffoldContext): Record<string, string>;
|
|
39
|
+
protected getTangoDevDependencyEntries(_context: FrameworkScaffoldContext): Record<string, string>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ScaffoldTemplate, type ScaffoldTemplateCategory, type FrameworkScaffoldContext, type ScaffoldMode } from '../ScaffoldTemplate';
|
|
2
|
+
import type { TemplateBuilder } from '../TemplateBuilder';
|
|
3
|
+
export declare class ScaffoldTemplateDescriptor implements ScaffoldTemplate {
|
|
4
|
+
readonly template: TemplateBuilder;
|
|
5
|
+
readonly category: ScaffoldTemplateCategory;
|
|
6
|
+
constructor(template: TemplateBuilder, category: ScaffoldTemplateCategory);
|
|
7
|
+
get path(): string;
|
|
8
|
+
render(ctx: FrameworkScaffoldContext): string;
|
|
9
|
+
shouldEmit(mode: ScaffoldMode): boolean;
|
|
10
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain boundary barrel: centralizes this subdomain's public contract.
|
|
3
|
+
*/
|
|
4
|
+
export { type FrameworkScaffoldContext, type ScaffoldMode, type ScaffoldTemplate, type ScaffoldTemplateCategory, SCAFFOLD_TEMPLATE_CATEGORY, } from './contracts/template/ScaffoldTemplate';
|
|
5
|
+
export type { PackageManager, ScaffoldDatabaseDialect as ScaffoldDialect, SupportedFramework, } from './contracts/FrameworkScaffoldStrategy';
|
|
6
|
+
export { FrameworkScaffoldStrategy } from './contracts/FrameworkScaffoldStrategy';
|
|
7
|
+
export { ScaffoldTemplateDescriptor } from './contracts/template/implementation/ScaffoldTemplateDescriptor';
|
|
8
|
+
export { FrameworkScaffoldRegistry } from './registry/FrameworkScaffoldRegistry';
|
|
9
|
+
export { ExpressScaffoldStrategy } from './strategies/express/ExpressScaffoldStrategy';
|
|
10
|
+
export { NextScaffoldStrategy } from './strategies/next/NextScaffoldStrategy';
|
|
11
|
+
export { scaffoldProject, type ScaffoldProjectOptions } from './scaffold/scaffoldProject';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { ExpressScaffoldStrategy, FrameworkScaffoldRegistry, FrameworkScaffoldStrategy, NextScaffoldStrategy, SCAFFOLD_TEMPLATE_CATEGORY, ScaffoldTemplateDescriptor, scaffoldProject } from "../frameworks-Bp_9BOt2.js";
|
|
2
|
+
|
|
3
|
+
export { ExpressScaffoldStrategy, FrameworkScaffoldRegistry, FrameworkScaffoldStrategy, NextScaffoldStrategy, SCAFFOLD_TEMPLATE_CATEGORY, ScaffoldTemplateDescriptor, scaffoldProject };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FrameworkScaffoldStrategy, type SupportedFramework } from '../contracts/FrameworkScaffoldStrategy';
|
|
2
|
+
/**
|
|
3
|
+
* Registry for framework scaffolding strategies keyed by framework id.
|
|
4
|
+
*/
|
|
5
|
+
export declare class FrameworkScaffoldRegistry {
|
|
6
|
+
private readonly strategies;
|
|
7
|
+
/**
|
|
8
|
+
* Create a registry preloaded with Tango's built-in framework scaffolds.
|
|
9
|
+
*/
|
|
10
|
+
static createDefault(): FrameworkScaffoldRegistry;
|
|
11
|
+
/**
|
|
12
|
+
* Register a strategy under its declared framework id.
|
|
13
|
+
*/
|
|
14
|
+
register(strategy: FrameworkScaffoldStrategy): void;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a strategy for a known framework id.
|
|
17
|
+
*/
|
|
18
|
+
get(id: SupportedFramework): FrameworkScaffoldStrategy | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* List all registered framework strategies in registration order.
|
|
21
|
+
*/
|
|
22
|
+
list(): readonly FrameworkScaffoldStrategy[];
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FrameworkScaffoldStrategy } from '../contracts/FrameworkScaffoldStrategy';
|
|
2
|
+
import type { FrameworkScaffoldContext, ScaffoldMode } from '../contracts/template/ScaffoldTemplate';
|
|
3
|
+
export type ScaffoldProjectOptions = {
|
|
4
|
+
force?: boolean;
|
|
5
|
+
/** 'new' = full scaffold; 'init' = only Tango + init-only files. Default 'new'. */
|
|
6
|
+
mode?: ScaffoldMode;
|
|
7
|
+
/** When true, do not overwrite existing files. Default true when mode === 'init', otherwise false. */
|
|
8
|
+
skipExisting?: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Write a framework scaffold into a target directory after basic safety checks.
|
|
12
|
+
*
|
|
13
|
+
* The selected strategy controls which files are created, while this helper
|
|
14
|
+
* owns directory validation and filesystem writes. With mode 'init', only
|
|
15
|
+
* Tango and init-only templates are emitted, and existing files can be skipped.
|
|
16
|
+
*/
|
|
17
|
+
export declare function scaffoldProject(context: FrameworkScaffoldContext, strategy: FrameworkScaffoldStrategy, options?: ScaffoldProjectOptions): Promise<void>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FrameworkScaffoldStrategy } from '../../contracts/FrameworkScaffoldStrategy';
|
|
2
|
+
import type { ScaffoldTemplate } from '../../contracts/template/ScaffoldTemplate';
|
|
3
|
+
/**
|
|
4
|
+
* Scaffold strategy for creating an Express-hosted Tango project.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ExpressScaffoldStrategy extends FrameworkScaffoldStrategy {
|
|
7
|
+
readonly id: "express";
|
|
8
|
+
readonly name = "Express";
|
|
9
|
+
readonly description = "Bootstrap a Tango application hosted by Express.";
|
|
10
|
+
/**
|
|
11
|
+
* Return the file templates needed for the generated Express project.
|
|
12
|
+
*/
|
|
13
|
+
getTemplates(): readonly ScaffoldTemplate[];
|
|
14
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TemplateBuilder } from '../../../contracts/template/TemplateBuilder';
|
|
2
|
+
import type { FrameworkScaffoldContext } from '../../../contracts/template/ScaffoldTemplate';
|
|
3
|
+
export declare class AppSourceTemplateBuilder extends TemplateBuilder {
|
|
4
|
+
constructor();
|
|
5
|
+
protected resolveTemplate(_context: FrameworkScaffoldContext): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TemplateBuilder } from '../../../contracts/template/TemplateBuilder';
|
|
2
|
+
import type { FrameworkScaffoldContext } from '../../../contracts/template/ScaffoldTemplate';
|
|
3
|
+
export declare class BootstrapTemplateBuilder extends TemplateBuilder {
|
|
4
|
+
constructor();
|
|
5
|
+
protected resolveTemplate(_context: FrameworkScaffoldContext): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TemplateBuilder } from '../../../contracts/template/TemplateBuilder';
|
|
2
|
+
import type { FrameworkScaffoldContext } from '../../../contracts/template/ScaffoldTemplate';
|
|
3
|
+
export declare class TodoModelTemplateBuilder extends TemplateBuilder {
|
|
4
|
+
constructor();
|
|
5
|
+
protected resolveTemplate(_context: FrameworkScaffoldContext): string;
|
|
6
|
+
}
|
|
7
|
+
export declare class ModelsBarrelTemplateBuilder extends TemplateBuilder {
|
|
8
|
+
constructor();
|
|
9
|
+
protected resolveTemplate(_context: FrameworkScaffoldContext): string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TemplateBuilder } from '../../../contracts/template/TemplateBuilder';
|
|
2
|
+
import type { FrameworkScaffoldContext } from '../../../contracts/template/ScaffoldTemplate';
|
|
3
|
+
export declare class OpenAPITemplateBuilder extends TemplateBuilder {
|
|
4
|
+
constructor();
|
|
5
|
+
protected resolveTemplate(_context: FrameworkScaffoldContext): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TemplateBuilder } from '../../../contracts/template/TemplateBuilder';
|
|
2
|
+
import type { FrameworkScaffoldContext } from '../../../contracts/template/ScaffoldTemplate';
|
|
3
|
+
export declare class PackageJsonTemplateBuilder extends TemplateBuilder {
|
|
4
|
+
constructor();
|
|
5
|
+
protected resolveTemplate(context: FrameworkScaffoldContext): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TemplateBuilder } from '../../../contracts/template/TemplateBuilder';
|
|
2
|
+
import type { FrameworkScaffoldContext } from '../../../contracts/template/ScaffoldTemplate';
|
|
3
|
+
export declare class ReadmeTemplateBuilder extends TemplateBuilder {
|
|
4
|
+
constructor();
|
|
5
|
+
protected resolveTemplate(context: FrameworkScaffoldContext): string;
|
|
6
|
+
}
|