vite-code-generator 0.1.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/README.md +95 -0
- package/bin/vite-gen.js +4 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +124 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/generator/crud.d.ts +8 -0
- package/dist/generator/crud.d.ts.map +1 -0
- package/dist/generator/crud.js +33 -0
- package/dist/generator/crud.js.map +1 -0
- package/dist/generator/hello-world.d.ts +3 -0
- package/dist/generator/hello-world.d.ts.map +1 -0
- package/dist/generator/hello-world.js +162 -0
- package/dist/generator/hello-world.js.map +1 -0
- package/dist/generator/index.d.ts +9 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +26 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/naming.d.ts +20 -0
- package/dist/generator/naming.d.ts.map +1 -0
- package/dist/generator/naming.js +42 -0
- package/dist/generator/naming.js.map +1 -0
- package/dist/generator/registry.d.ts +5 -0
- package/dist/generator/registry.d.ts.map +1 -0
- package/dist/generator/registry.js +20 -0
- package/dist/generator/registry.js.map +1 -0
- package/dist/generator/resource-api.d.ts +3 -0
- package/dist/generator/resource-api.d.ts.map +1 -0
- package/dist/generator/resource-api.js +143 -0
- package/dist/generator/resource-api.js.map +1 -0
- package/dist/generator/resource-hooks.d.ts +7 -0
- package/dist/generator/resource-hooks.d.ts.map +1 -0
- package/dist/generator/resource-hooks.js +248 -0
- package/dist/generator/resource-hooks.js.map +1 -0
- package/dist/generator/resource-page.d.ts +3 -0
- package/dist/generator/resource-page.d.ts.map +1 -0
- package/dist/generator/resource-page.js +280 -0
- package/dist/generator/resource-page.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# vite-code-generator
|
|
2
|
+
|
|
3
|
+
CLI that scaffolds Vite + TypeScript projects and generates code from named templates.
|
|
4
|
+
|
|
5
|
+
## Install / run
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run build
|
|
10
|
+
npx vite-gen create my-app
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# list templates and their flags
|
|
17
|
+
vite-gen list
|
|
18
|
+
|
|
19
|
+
# create with the default hello-world template
|
|
20
|
+
vite-gen create my-app
|
|
21
|
+
|
|
22
|
+
# pick a template and pass dynamic flags
|
|
23
|
+
vite-gen create my-app --template hello-world --greeting "Hi there" --title "My App"
|
|
24
|
+
|
|
25
|
+
# same flags via generic --flag (useful for future templates)
|
|
26
|
+
vite-gen create my-app -t hello-world -f greeting=Hi -f title=MyApp
|
|
27
|
+
|
|
28
|
+
# custom output directory
|
|
29
|
+
vite-gen create my-app --out-dir ./apps/my-app
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Resource hooks
|
|
33
|
+
|
|
34
|
+
Pass the **PascalCase singular** type name (e.g. `Resource`, not `resource`). Writes to `src/hooks/query-hooks/`.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# all hooks, single-record mutations (default)
|
|
38
|
+
vite-gen create Resource -t resource-hooks
|
|
39
|
+
|
|
40
|
+
# bulk mutations (arrays)
|
|
41
|
+
vite-gen create Resource -t resource-hooks --variant bulk
|
|
42
|
+
|
|
43
|
+
# only some hooks
|
|
44
|
+
vite-gen create User -t resource-hooks --hooks list,show,create
|
|
45
|
+
|
|
46
|
+
# irregular plural
|
|
47
|
+
vite-gen create Person -t resource-hooks --plural People
|
|
48
|
+
|
|
49
|
+
# write into an existing app root
|
|
50
|
+
vite-gen create Resource -t resource-hooks --out-dir ../gyst-tracker-web
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`--hooks` accepts: `list`, `show`, `create`, `update`, `delete`, or `all` (default).
|
|
54
|
+
|
|
55
|
+
### Resource API
|
|
56
|
+
|
|
57
|
+
Same naming rules. Writes to `src/api/<plural>.api.ts`.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# all methods, single-record body (default)
|
|
61
|
+
vite-gen create Condition -t resource-api
|
|
62
|
+
|
|
63
|
+
# bulk create/update/delete (matches conditions-style APIs)
|
|
64
|
+
vite-gen create Condition -t resource-api --variant bulk
|
|
65
|
+
|
|
66
|
+
# only some methods
|
|
67
|
+
vite-gen create Condition -t resource-api --methods list,show,create
|
|
68
|
+
|
|
69
|
+
# custom route path
|
|
70
|
+
vite-gen create Condition -t resource-api --variant bulk --path conditions
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`--methods` accepts: `list`, `show`, `create`, `update`, `delete`, or `all` (default).
|
|
74
|
+
|
|
75
|
+
### Resource page
|
|
76
|
+
|
|
77
|
+
Pass the **PascalCase singular** type name. Requires `--dir` for the parent folder. Creates a **plural** folder with page, CSS module, and form.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
vite-gen create Role -t resource-page --dir src/pages
|
|
81
|
+
# → src/pages/Roles/RolesPage.tsx
|
|
82
|
+
# → src/pages/Roles/RolesPage.module.css
|
|
83
|
+
# → src/pages/Roles/components/RoleForm.tsx
|
|
84
|
+
|
|
85
|
+
# irregular plural
|
|
86
|
+
vite-gen create Person -t resource-page --dir src/pages --plural People
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Form fields: `display_name` and `name` (name auto-filled via `toSnakeCase` from display_name on create).
|
|
90
|
+
|
|
91
|
+
## Adding a template
|
|
92
|
+
|
|
93
|
+
1. Create a `TemplateDefinition` in `src/generator/` (see `hello-world.ts` / `resource-hooks.ts`).
|
|
94
|
+
2. Register it in `src/generator/registry.ts`.
|
|
95
|
+
3. Rebuild. Template-specific flags declared on the definition are wired into the CLI automatically.
|
package/bin/vite-gen.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,wBAAgB,SAAS,IAAI,OAAO,CA4HnC;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1D"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { generateProject, getTemplate, listTemplates } from '../generator/index.js';
|
|
4
|
+
function collectFlag(value, previous) {
|
|
5
|
+
const eq = value.indexOf('=');
|
|
6
|
+
if (eq === -1) {
|
|
7
|
+
throw new Error(`Invalid --flag value "${value}". Use key=value (e.g. greeting=Hi).`);
|
|
8
|
+
}
|
|
9
|
+
const key = value.slice(0, eq).trim();
|
|
10
|
+
const val = value.slice(eq + 1);
|
|
11
|
+
if (!key) {
|
|
12
|
+
throw new Error(`Invalid --flag value "${value}". Key cannot be empty.`);
|
|
13
|
+
}
|
|
14
|
+
return { ...previous, [key]: val };
|
|
15
|
+
}
|
|
16
|
+
export function createCli() {
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.name('vite-gen')
|
|
20
|
+
.description('Generate Vite TypeScript projects and code from templates')
|
|
21
|
+
.version('0.1.0');
|
|
22
|
+
program
|
|
23
|
+
.command('list')
|
|
24
|
+
.description('List available templates')
|
|
25
|
+
.action(() => {
|
|
26
|
+
const templates = listTemplates();
|
|
27
|
+
if (templates.length === 0) {
|
|
28
|
+
console.log('No templates registered.');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const t of templates) {
|
|
32
|
+
const kind = t.kind ?? 'project';
|
|
33
|
+
console.log(`${t.name.padEnd(18)} [${kind}] ${t.description}`);
|
|
34
|
+
if (t.flags?.length) {
|
|
35
|
+
for (const flag of t.flags) {
|
|
36
|
+
const def = flag.defaultValue !== undefined && flag.defaultValue !== ''
|
|
37
|
+
? ` (default: ${String(flag.defaultValue)})`
|
|
38
|
+
: '';
|
|
39
|
+
console.log(` --${flag.name}${def}: ${flag.description}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
program
|
|
45
|
+
.command('create')
|
|
46
|
+
.description('Create from a template (project scaffold or generated files)')
|
|
47
|
+
.argument('<name>', 'project name, or PascalCase singular resource name for file templates')
|
|
48
|
+
.option('-t, --template <name>', 'template to use', 'hello-world')
|
|
49
|
+
.option('-o, --out-dir <path>', 'output directory (project: ./<name>; file templates: .)')
|
|
50
|
+
.option('-f, --flag <key=value>', 'template-specific flag (repeatable)', collectFlag, {})
|
|
51
|
+
.action(async (name, opts) => {
|
|
52
|
+
const template = getTemplate(opts.template);
|
|
53
|
+
if (!template) {
|
|
54
|
+
const available = listTemplates().map((t) => t.name).join(', ');
|
|
55
|
+
console.error(`Unknown template "${opts.template}". Available: ${available}`);
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const flags = {};
|
|
60
|
+
for (const def of template.flags ?? []) {
|
|
61
|
+
flags[def.name] = def.defaultValue;
|
|
62
|
+
}
|
|
63
|
+
Object.assign(flags, opts.flag);
|
|
64
|
+
const kind = template.kind ?? 'project';
|
|
65
|
+
const outDir = opts.outDir
|
|
66
|
+
? path.resolve(opts.outDir)
|
|
67
|
+
: kind === 'file'
|
|
68
|
+
? process.cwd()
|
|
69
|
+
: path.resolve(process.cwd(), name);
|
|
70
|
+
try {
|
|
71
|
+
const target = await generateProject({
|
|
72
|
+
projectName: name,
|
|
73
|
+
outDir,
|
|
74
|
+
template: opts.template,
|
|
75
|
+
flags,
|
|
76
|
+
});
|
|
77
|
+
if (kind === 'file') {
|
|
78
|
+
console.log(`Generated ${opts.template} for ${name} in ${target}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log(`Created ${opts.template} project at ${target}`);
|
|
82
|
+
console.log(`\n cd ${path.relative(process.cwd(), target) || '.'}`);
|
|
83
|
+
console.log(' npm install');
|
|
84
|
+
console.log(' npm run dev\n');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
console.error(err instanceof Error ? err.message : err);
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
// Register known template flags as first-class create options so
|
|
93
|
+
// `vite-gen create my-app --greeting "Hi"` works without --flag.
|
|
94
|
+
const createCmd = program.commands.find((c) => c.name() === 'create');
|
|
95
|
+
if (createCmd) {
|
|
96
|
+
for (const template of listTemplates()) {
|
|
97
|
+
for (const flag of template.flags ?? []) {
|
|
98
|
+
const optionName = `--${flag.name} <value>`;
|
|
99
|
+
if (!createCmd.options.some((o) => o.long === `--${flag.name}`)) {
|
|
100
|
+
createCmd.option(optionName, flag.description);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
createCmd.hook('preAction', (_thisCommand, actionCommand) => {
|
|
105
|
+
const opts = actionCommand.opts();
|
|
106
|
+
const flagBag = opts.flag ?? {};
|
|
107
|
+
for (const template of listTemplates()) {
|
|
108
|
+
for (const flag of template.flags ?? []) {
|
|
109
|
+
const value = opts[flag.name];
|
|
110
|
+
if (typeof value === 'string') {
|
|
111
|
+
flagBag[flag.name] = value;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
actionCommand.setOptionValue('flag', flagBag);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return program;
|
|
119
|
+
}
|
|
120
|
+
export async function runCli(argv) {
|
|
121
|
+
const program = createCli();
|
|
122
|
+
await program.parseAsync(argv);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const CRUD_KINDS: readonly ["list", "show", "create", "update", "delete"];
|
|
2
|
+
export type CrudKind = (typeof CRUD_KINDS)[number];
|
|
3
|
+
export type ResourceVariant = 'single' | 'bulk';
|
|
4
|
+
export declare function parseCrudKinds(raw: string | boolean | undefined, label?: string): Set<CrudKind>;
|
|
5
|
+
export declare function parseVariant(raw: string | boolean | undefined): ResourceVariant;
|
|
6
|
+
/** PascalCase → snake_case path segment, e.g. PricingConfigs → pricing_configs */
|
|
7
|
+
export declare function toSnakeCase(pascal: string): string;
|
|
8
|
+
//# sourceMappingURL=crud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.d.ts","sourceRoot":"","sources":["../../src/generator/crud.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,yDAA0D,CAAC;AAClF,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEhD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,EACjC,KAAK,SAAW,GACf,GAAG,CAAC,QAAQ,CAAC,CAqBf;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,eAAe,CAI/E;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKlD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const CRUD_KINDS = ['list', 'show', 'create', 'update', 'delete'];
|
|
2
|
+
export function parseCrudKinds(raw, label = 'method') {
|
|
3
|
+
const value = typeof raw === 'string' ? raw.trim() : '';
|
|
4
|
+
if (!value || value === 'all') {
|
|
5
|
+
return new Set(CRUD_KINDS);
|
|
6
|
+
}
|
|
7
|
+
const parts = value.split(',').map((p) => p.trim().toLowerCase()).filter(Boolean);
|
|
8
|
+
if (parts.length === 0) {
|
|
9
|
+
return new Set(CRUD_KINDS);
|
|
10
|
+
}
|
|
11
|
+
const selected = new Set();
|
|
12
|
+
for (const part of parts) {
|
|
13
|
+
if (!CRUD_KINDS.includes(part)) {
|
|
14
|
+
throw new Error(`Unknown ${label} "${part}". Valid: ${CRUD_KINDS.join(', ')}, or all`);
|
|
15
|
+
}
|
|
16
|
+
selected.add(part);
|
|
17
|
+
}
|
|
18
|
+
return selected;
|
|
19
|
+
}
|
|
20
|
+
export function parseVariant(raw) {
|
|
21
|
+
const value = typeof raw === 'string' ? raw.trim().toLowerCase() : 'single';
|
|
22
|
+
if (value === 'single' || value === 'bulk')
|
|
23
|
+
return value;
|
|
24
|
+
throw new Error(`Unknown variant "${String(raw)}". Valid: single, bulk`);
|
|
25
|
+
}
|
|
26
|
+
/** PascalCase → snake_case path segment, e.g. PricingConfigs → pricing_configs */
|
|
27
|
+
export function toSnakeCase(pascal) {
|
|
28
|
+
return pascal
|
|
29
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
30
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')
|
|
31
|
+
.toLowerCase();
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=crud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud.js","sourceRoot":"","sources":["../../src/generator/crud.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAIlF,MAAM,UAAU,cAAc,CAC5B,GAAiC,EACjC,KAAK,GAAG,QAAQ;IAEhB,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QAC9B,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAY,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAE,UAAgC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,KAAK,IAAI,aAAa,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CACtE,CAAC;QACJ,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,IAAgB,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAiC;IAC5D,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC5E,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACzD,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;AAC3E,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,MAAM;SACV,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,sBAAsB,EAAE,OAAO,CAAC;SACxC,WAAW,EAAE,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hello-world.d.ts","sourceRoot":"","sources":["../../src/generator/hello-world.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,kBAAkB,EAAgB,MAAM,aAAa,CAAC;AAgJrF,eAAO,MAAM,kBAAkB,EAAE,kBAqChC,CAAC"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
function packageJson(name) {
|
|
2
|
+
return `${JSON.stringify({
|
|
3
|
+
name,
|
|
4
|
+
private: true,
|
|
5
|
+
version: '0.0.0',
|
|
6
|
+
type: 'module',
|
|
7
|
+
scripts: {
|
|
8
|
+
dev: 'vite',
|
|
9
|
+
build: 'tsc && vite build',
|
|
10
|
+
preview: 'vite preview',
|
|
11
|
+
},
|
|
12
|
+
devDependencies: {
|
|
13
|
+
typescript: '~5.8.2',
|
|
14
|
+
vite: '^6.2.0',
|
|
15
|
+
},
|
|
16
|
+
}, null, 2)}\n`;
|
|
17
|
+
}
|
|
18
|
+
function tsconfig() {
|
|
19
|
+
return `${JSON.stringify({
|
|
20
|
+
compilerOptions: {
|
|
21
|
+
target: 'ES2022',
|
|
22
|
+
useDefineForClassFields: true,
|
|
23
|
+
module: 'ESNext',
|
|
24
|
+
lib: ['ES2022', 'DOM', 'DOM.Iterable'],
|
|
25
|
+
skipLibCheck: true,
|
|
26
|
+
moduleResolution: 'bundler',
|
|
27
|
+
allowImportingTsExtensions: true,
|
|
28
|
+
isolatedModules: true,
|
|
29
|
+
moduleDetection: 'force',
|
|
30
|
+
noEmit: true,
|
|
31
|
+
strict: true,
|
|
32
|
+
noUnusedLocals: true,
|
|
33
|
+
noUnusedParameters: true,
|
|
34
|
+
noFallthroughCasesInSwitch: true,
|
|
35
|
+
noUncheckedSideEffectImports: true,
|
|
36
|
+
},
|
|
37
|
+
include: ['src'],
|
|
38
|
+
}, null, 2)}\n`;
|
|
39
|
+
}
|
|
40
|
+
function viteConfig() {
|
|
41
|
+
return `import { defineConfig } from 'vite';
|
|
42
|
+
|
|
43
|
+
export default defineConfig({
|
|
44
|
+
// https://vite.dev/config/
|
|
45
|
+
});
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
function indexHtml(projectName, title) {
|
|
49
|
+
return `<!doctype html>
|
|
50
|
+
<html lang="en">
|
|
51
|
+
<head>
|
|
52
|
+
<meta charset="UTF-8" />
|
|
53
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
54
|
+
<title>${title || projectName}</title>
|
|
55
|
+
</head>
|
|
56
|
+
<body>
|
|
57
|
+
<div id="app"></div>
|
|
58
|
+
<script type="module" src="/src/main.ts"></script>
|
|
59
|
+
</body>
|
|
60
|
+
</html>
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
function mainTs(greeting) {
|
|
64
|
+
return `import './style.css';
|
|
65
|
+
|
|
66
|
+
const app = document.querySelector<HTMLDivElement>('#app');
|
|
67
|
+
|
|
68
|
+
if (app) {
|
|
69
|
+
app.innerHTML = \`
|
|
70
|
+
<h1>${greeting}</h1>
|
|
71
|
+
<p>Edit <code>src/main.ts</code> and save to reload.</p>
|
|
72
|
+
\`;
|
|
73
|
+
}
|
|
74
|
+
`;
|
|
75
|
+
}
|
|
76
|
+
function styleCss() {
|
|
77
|
+
return `:root {
|
|
78
|
+
font-family: system-ui, sans-serif;
|
|
79
|
+
line-height: 1.5;
|
|
80
|
+
color: #213547;
|
|
81
|
+
background-color: #ffffff;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
body {
|
|
85
|
+
margin: 0;
|
|
86
|
+
min-height: 100vh;
|
|
87
|
+
display: flex;
|
|
88
|
+
place-items: center;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#app {
|
|
92
|
+
max-width: 40rem;
|
|
93
|
+
margin: 0 auto;
|
|
94
|
+
padding: 2rem;
|
|
95
|
+
text-align: center;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
code {
|
|
99
|
+
font-family: ui-monospace, monospace;
|
|
100
|
+
background: #f4f4f5;
|
|
101
|
+
padding: 0.15em 0.4em;
|
|
102
|
+
border-radius: 4px;
|
|
103
|
+
}
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
function gitignore() {
|
|
107
|
+
return `node_modules
|
|
108
|
+
dist
|
|
109
|
+
dist-ssr
|
|
110
|
+
*.local
|
|
111
|
+
.DS_Store
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
114
|
+
function readme(projectName) {
|
|
115
|
+
return `# ${projectName}
|
|
116
|
+
|
|
117
|
+
Generated with \`vite-code-generator\` (hello-world template).
|
|
118
|
+
|
|
119
|
+
## Scripts
|
|
120
|
+
|
|
121
|
+
\`\`\`bash
|
|
122
|
+
npm install
|
|
123
|
+
npm run dev
|
|
124
|
+
\`\`\`
|
|
125
|
+
`;
|
|
126
|
+
}
|
|
127
|
+
export const helloWorldTemplate = {
|
|
128
|
+
name: 'hello-world',
|
|
129
|
+
description: 'Minimal Vite + TypeScript hello world app',
|
|
130
|
+
kind: 'project',
|
|
131
|
+
flags: [
|
|
132
|
+
{
|
|
133
|
+
name: 'greeting',
|
|
134
|
+
description: 'Text shown in the page heading',
|
|
135
|
+
defaultValue: 'Hello World',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: 'title',
|
|
139
|
+
description: 'HTML document title',
|
|
140
|
+
defaultValue: '',
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
resolveFiles(context) {
|
|
144
|
+
const greeting = typeof context.flags.greeting === 'string' && context.flags.greeting.length > 0
|
|
145
|
+
? context.flags.greeting
|
|
146
|
+
: 'Hello World';
|
|
147
|
+
const title = typeof context.flags.title === 'string' && context.flags.title.length > 0
|
|
148
|
+
? context.flags.title
|
|
149
|
+
: context.projectName;
|
|
150
|
+
return [
|
|
151
|
+
{ path: 'package.json', content: packageJson(context.projectName) },
|
|
152
|
+
{ path: 'tsconfig.json', content: tsconfig() },
|
|
153
|
+
{ path: 'vite.config.ts', content: viteConfig() },
|
|
154
|
+
{ path: 'index.html', content: indexHtml(context.projectName, title) },
|
|
155
|
+
{ path: 'src/main.ts', content: mainTs(greeting) },
|
|
156
|
+
{ path: 'src/style.css', content: styleCss() },
|
|
157
|
+
{ path: '.gitignore', content: gitignore() },
|
|
158
|
+
{ path: 'README.md', content: readme(context.projectName) },
|
|
159
|
+
];
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=hello-world.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hello-world.js","sourceRoot":"","sources":["../../src/generator/hello-world.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type GenerateOptions = {
|
|
2
|
+
projectName: string;
|
|
3
|
+
outDir: string;
|
|
4
|
+
template: string;
|
|
5
|
+
flags?: Record<string, string | boolean | undefined>;
|
|
6
|
+
};
|
|
7
|
+
export { getTemplate, listTemplates, registerTemplate } from './registry.js';
|
|
8
|
+
export declare function generateProject(options: GenerateOptions): Promise<string>;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;CACtD,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE7E,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B/E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getTemplate, listTemplates } from './registry.js';
|
|
4
|
+
export { getTemplate, listTemplates, registerTemplate } from './registry.js';
|
|
5
|
+
export async function generateProject(options) {
|
|
6
|
+
const template = getTemplate(options.template);
|
|
7
|
+
if (!template) {
|
|
8
|
+
const available = listTemplates()
|
|
9
|
+
.map((t) => t.name)
|
|
10
|
+
.join(', ');
|
|
11
|
+
throw new Error(`Unknown template "${options.template}". Available: ${available || '(none)'}`);
|
|
12
|
+
}
|
|
13
|
+
const targetDir = path.resolve(options.outDir);
|
|
14
|
+
const context = {
|
|
15
|
+
projectName: options.projectName,
|
|
16
|
+
flags: options.flags ?? {},
|
|
17
|
+
};
|
|
18
|
+
const files = template.resolveFiles(context);
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
const filePath = path.join(targetDir, file.path);
|
|
21
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
22
|
+
await writeFile(filePath, file.content, 'utf8');
|
|
23
|
+
}
|
|
24
|
+
return targetDir;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAU3D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE7E,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAwB;IAC5D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,SAAS,GAAG,aAAa,EAAE;aAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CACb,qBAAqB,OAAO,CAAC,QAAQ,iBAAiB,SAAS,IAAI,QAAQ,EAAE,CAC9E,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAoB;QAC/B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;KAC3B,CAAC;IAEF,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAE7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ResourceNames = {
|
|
2
|
+
/** PascalCase singular, e.g. Resource */
|
|
3
|
+
singular: string;
|
|
4
|
+
/** PascalCase plural, e.g. Resources */
|
|
5
|
+
plural: string;
|
|
6
|
+
/** camelCase singular, e.g. resource */
|
|
7
|
+
singularCamel: string;
|
|
8
|
+
/** camelCase plural, e.g. resources */
|
|
9
|
+
pluralCamel: string;
|
|
10
|
+
/** SCREAMING_SNAKE singular, e.g. RESOURCE */
|
|
11
|
+
singularConst: string;
|
|
12
|
+
/** SCREAMING_SNAKE plural, e.g. RESOURCES */
|
|
13
|
+
pluralConst: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Derive naming variants from a PascalCase singular resource name.
|
|
17
|
+
* Example: Resource → resource, Resources, resources, RESOURCE, RESOURCES
|
|
18
|
+
*/
|
|
19
|
+
export declare function deriveResourceNames(singularPascal: string, pluralOverride?: string): ResourceNames;
|
|
20
|
+
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/generator/naming.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC1B,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAsBF;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,MAAM,GACtB,aAAa,CAqBf"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
function toCamelCase(pascal) {
|
|
2
|
+
if (!pascal)
|
|
3
|
+
return pascal;
|
|
4
|
+
return pascal[0].toLowerCase() + pascal.slice(1);
|
|
5
|
+
}
|
|
6
|
+
function toScreamingSnake(pascal) {
|
|
7
|
+
return pascal
|
|
8
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
9
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')
|
|
10
|
+
.toUpperCase();
|
|
11
|
+
}
|
|
12
|
+
function defaultPlural(singular) {
|
|
13
|
+
if (singular.endsWith('s'))
|
|
14
|
+
return singular;
|
|
15
|
+
if (singular.endsWith('y') && singular.length > 1 && !/[aeiou]y$/i.test(singular)) {
|
|
16
|
+
return `${singular.slice(0, -1)}ies`;
|
|
17
|
+
}
|
|
18
|
+
return `${singular}s`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Derive naming variants from a PascalCase singular resource name.
|
|
22
|
+
* Example: Resource → resource, Resources, resources, RESOURCE, RESOURCES
|
|
23
|
+
*/
|
|
24
|
+
export function deriveResourceNames(singularPascal, pluralOverride) {
|
|
25
|
+
const singular = singularPascal.trim();
|
|
26
|
+
if (!singular || singular !== singular[0].toUpperCase() + singular.slice(1) || !/^[A-Z][A-Za-z0-9]*$/.test(singular)) {
|
|
27
|
+
throw new Error(`Resource name must be PascalCase singular (e.g. Resource, User). Got "${singularPascal}".`);
|
|
28
|
+
}
|
|
29
|
+
const plural = (pluralOverride?.trim() || defaultPlural(singular));
|
|
30
|
+
if (!/^[A-Z][A-Za-z0-9]*$/.test(plural)) {
|
|
31
|
+
throw new Error(`Plural name must be PascalCase (e.g. Resources). Got "${plural}".`);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
singular,
|
|
35
|
+
plural,
|
|
36
|
+
singularCamel: toCamelCase(singular),
|
|
37
|
+
pluralCamel: toCamelCase(plural),
|
|
38
|
+
singularConst: toScreamingSnake(singular),
|
|
39
|
+
pluralConst: toScreamingSnake(plural),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/generator/naming.ts"],"names":[],"mappings":"AAeA,SAAS,WAAW,CAAC,MAAc;IACjC,IAAI,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IAC3B,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc;IACtC,OAAO,MAAM;SACV,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,sBAAsB,EAAE,OAAO,CAAC;SACxC,WAAW,EAAE,CAAC;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5C,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClF,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACvC,CAAC;IACD,OAAO,GAAG,QAAQ,GAAG,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,cAAsB,EACtB,cAAuB;IAEvB,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrH,MAAM,IAAI,KAAK,CACb,yEAAyE,cAAc,IAAI,CAC5F,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,yDAAyD,MAAM,IAAI,CAAC,CAAC;IACvF,CAAC;IAED,OAAO;QACL,QAAQ;QACR,MAAM;QACN,aAAa,EAAE,WAAW,CAAC,QAAQ,CAAC;QACpC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC;QAChC,aAAa,EAAE,gBAAgB,CAAC,QAAQ,CAAC;QACzC,WAAW,EAAE,gBAAgB,CAAC,MAAM,CAAC;KACtC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TemplateDefinition } from '../types.js';
|
|
2
|
+
export declare function listTemplates(): TemplateDefinition[];
|
|
3
|
+
export declare function getTemplate(name: string): TemplateDefinition | undefined;
|
|
4
|
+
export declare function registerTemplate(template: TemplateDefinition): void;
|
|
5
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/generator/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAatD,wBAAgB,aAAa,IAAI,kBAAkB,EAAE,CAEpD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAExE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAEnE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { helloWorldTemplate } from './hello-world.js';
|
|
2
|
+
import { resourceApiTemplate } from './resource-api.js';
|
|
3
|
+
import { resourceHooksTemplate } from './resource-hooks.js';
|
|
4
|
+
import { resourcePageTemplate } from './resource-page.js';
|
|
5
|
+
const templates = {
|
|
6
|
+
[helloWorldTemplate.name]: helloWorldTemplate,
|
|
7
|
+
[resourceApiTemplate.name]: resourceApiTemplate,
|
|
8
|
+
[resourceHooksTemplate.name]: resourceHooksTemplate,
|
|
9
|
+
[resourcePageTemplate.name]: resourcePageTemplate,
|
|
10
|
+
};
|
|
11
|
+
export function listTemplates() {
|
|
12
|
+
return Object.values(templates);
|
|
13
|
+
}
|
|
14
|
+
export function getTemplate(name) {
|
|
15
|
+
return templates[name];
|
|
16
|
+
}
|
|
17
|
+
export function registerTemplate(template) {
|
|
18
|
+
templates[template.name] = template;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/generator/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,SAAS,GAAuC;IACpD,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,kBAAkB;IAC7C,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,mBAAmB;IAC/C,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,qBAAqB;IACnD,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,oBAAoB;CAClD,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAA4B;IAC3D,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-api.d.ts","sourceRoot":"","sources":["../../src/generator/resource-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,kBAAkB,EAAgB,MAAM,aAAa,CAAC;AAqHrF,eAAO,MAAM,mBAAmB,EAAE,kBAgDjC,CAAC"}
|