@beatzball/create-litro 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.
Files changed (100) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +185 -0
  3. package/README.md +89 -0
  4. package/dist/recipes/11ty-blog/recipe.config.d.ts +4 -0
  5. package/dist/recipes/11ty-blog/recipe.config.d.ts.map +1 -0
  6. package/dist/recipes/11ty-blog/recipe.config.js +9 -0
  7. package/dist/recipes/11ty-blog/recipe.config.js.map +1 -0
  8. package/dist/recipes/11ty-blog/recipe.config.ts +11 -0
  9. package/dist/recipes/11ty-blog/template/app.ts +18 -0
  10. package/dist/recipes/11ty-blog/template/content/_data/metadata.js +10 -0
  11. package/dist/recipes/11ty-blog/template/content/blog/blog.11tydata.json +1 -0
  12. package/dist/recipes/11ty-blog/template/content/blog/getting-started/index.md +66 -0
  13. package/dist/recipes/11ty-blog/template/content/blog/hello-world.md +39 -0
  14. package/dist/recipes/11ty-blog/template/litro.recipe.json +7 -0
  15. package/dist/recipes/11ty-blog/template/nitro.config.ts +60 -0
  16. package/dist/recipes/11ty-blog/template/package.json +26 -0
  17. package/dist/recipes/11ty-blog/template/pages/blog/[slug].ts +65 -0
  18. package/dist/recipes/11ty-blog/template/pages/blog/index.ts +43 -0
  19. package/dist/recipes/11ty-blog/template/pages/index.ts +58 -0
  20. package/dist/recipes/11ty-blog/template/pages/tags/[tag].ts +53 -0
  21. package/dist/recipes/11ty-blog/template/public/.gitkeep +0 -0
  22. package/dist/recipes/11ty-blog/template/server/api/hello.ts +6 -0
  23. package/dist/recipes/11ty-blog/template/server/api/posts.ts +8 -0
  24. package/dist/recipes/11ty-blog/template/server/middleware/vite-dev.ts +29 -0
  25. package/dist/recipes/11ty-blog/template/server/routes/[...].ts +55 -0
  26. package/dist/recipes/11ty-blog/template/tsconfig.json +14 -0
  27. package/dist/recipes/11ty-blog/template/vite.config.ts +19 -0
  28. package/dist/recipes/fullstack/recipe.config.d.ts +4 -0
  29. package/dist/recipes/fullstack/recipe.config.d.ts.map +1 -0
  30. package/dist/recipes/fullstack/recipe.config.js +8 -0
  31. package/dist/recipes/fullstack/recipe.config.js.map +1 -0
  32. package/dist/recipes/fullstack/recipe.config.ts +10 -0
  33. package/dist/recipes/fullstack/template/app.ts +20 -0
  34. package/dist/recipes/fullstack/template/nitro.config.ts +67 -0
  35. package/dist/recipes/fullstack/template/package.json +26 -0
  36. package/dist/recipes/fullstack/template/pages/blog/[slug].ts +43 -0
  37. package/dist/recipes/fullstack/template/pages/blog/index.ts +22 -0
  38. package/dist/recipes/fullstack/template/pages/index.ts +43 -0
  39. package/dist/recipes/fullstack/template/public/.gitkeep +0 -0
  40. package/dist/recipes/fullstack/template/server/api/hello.ts +6 -0
  41. package/dist/recipes/fullstack/template/server/middleware/vite-dev.ts +31 -0
  42. package/dist/recipes/fullstack/template/server/routes/[...].ts +59 -0
  43. package/dist/recipes/fullstack/template/tsconfig.json +14 -0
  44. package/dist/recipes/fullstack/template/vite.config.ts +15 -0
  45. package/dist/src/index.d.ts +17 -0
  46. package/dist/src/index.d.ts.map +1 -0
  47. package/dist/src/index.js +200 -0
  48. package/dist/src/index.js.map +1 -0
  49. package/dist/src/scaffold.d.ts +35 -0
  50. package/dist/src/scaffold.d.ts.map +1 -0
  51. package/dist/src/scaffold.js +166 -0
  52. package/dist/src/scaffold.js.map +1 -0
  53. package/dist/src/scaffold.test.d.ts +2 -0
  54. package/dist/src/scaffold.test.d.ts.map +1 -0
  55. package/dist/src/scaffold.test.js +204 -0
  56. package/dist/src/scaffold.test.js.map +1 -0
  57. package/dist/src/types.d.ts +23 -0
  58. package/dist/src/types.d.ts.map +1 -0
  59. package/dist/src/types.js +2 -0
  60. package/dist/src/types.js.map +1 -0
  61. package/dist/tsconfig.tsbuildinfo +1 -0
  62. package/package.json +28 -0
  63. package/recipes/11ty-blog/recipe.config.ts +11 -0
  64. package/recipes/11ty-blog/template/app.ts +18 -0
  65. package/recipes/11ty-blog/template/content/_data/metadata.js +10 -0
  66. package/recipes/11ty-blog/template/content/blog/blog.11tydata.json +1 -0
  67. package/recipes/11ty-blog/template/content/blog/getting-started/index.md +66 -0
  68. package/recipes/11ty-blog/template/content/blog/hello-world.md +39 -0
  69. package/recipes/11ty-blog/template/litro.recipe.json +7 -0
  70. package/recipes/11ty-blog/template/nitro.config.ts +60 -0
  71. package/recipes/11ty-blog/template/package.json +26 -0
  72. package/recipes/11ty-blog/template/pages/blog/[slug].ts +65 -0
  73. package/recipes/11ty-blog/template/pages/blog/index.ts +43 -0
  74. package/recipes/11ty-blog/template/pages/index.ts +58 -0
  75. package/recipes/11ty-blog/template/pages/tags/[tag].ts +53 -0
  76. package/recipes/11ty-blog/template/public/.gitkeep +0 -0
  77. package/recipes/11ty-blog/template/server/api/hello.ts +6 -0
  78. package/recipes/11ty-blog/template/server/api/posts.ts +8 -0
  79. package/recipes/11ty-blog/template/server/middleware/vite-dev.ts +29 -0
  80. package/recipes/11ty-blog/template/server/routes/[...].ts +55 -0
  81. package/recipes/11ty-blog/template/tsconfig.json +14 -0
  82. package/recipes/11ty-blog/template/vite.config.ts +19 -0
  83. package/recipes/fullstack/recipe.config.ts +10 -0
  84. package/recipes/fullstack/template/app.ts +20 -0
  85. package/recipes/fullstack/template/nitro.config.ts +67 -0
  86. package/recipes/fullstack/template/package.json +26 -0
  87. package/recipes/fullstack/template/pages/blog/[slug].ts +43 -0
  88. package/recipes/fullstack/template/pages/blog/index.ts +22 -0
  89. package/recipes/fullstack/template/pages/index.ts +43 -0
  90. package/recipes/fullstack/template/public/.gitkeep +0 -0
  91. package/recipes/fullstack/template/server/api/hello.ts +6 -0
  92. package/recipes/fullstack/template/server/middleware/vite-dev.ts +31 -0
  93. package/recipes/fullstack/template/server/routes/[...].ts +59 -0
  94. package/recipes/fullstack/template/tsconfig.json +14 -0
  95. package/recipes/fullstack/template/vite.config.ts +15 -0
  96. package/src/index.ts +229 -0
  97. package/src/scaffold.test.ts +228 -0
  98. package/src/scaffold.ts +202 -0
  99. package/src/types.ts +26 -0
  100. package/tsconfig.json +10 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "skipLibCheck": true,
8
+ "esModuleInterop": true,
9
+ "experimentalDecorators": true,
10
+ "useDefineForClassFields": false
11
+ },
12
+ "include": ["**/*.ts", "**/*.tsx"],
13
+ "exclude": ["node_modules", "dist", ".nitro"]
14
+ }
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from 'vite';
2
+
3
+ export default defineConfig({
4
+ build: {
5
+ outDir: 'dist/client',
6
+ rollupOptions: {
7
+ input: 'app.ts',
8
+ output: {
9
+ // Stable (non-hashed) entry filename so the HTML shell can always
10
+ // reference /_litro/app.js without knowing the content hash.
11
+ entryFileNames: '[name].js',
12
+ },
13
+ },
14
+ },
15
+ });
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * create-litro — Scaffolding CLI for Litro
4
+ *
5
+ * Usage:
6
+ * npm create litro
7
+ * npx create-litro
8
+ * npx create-litro <project-name> [--recipe <recipe>] [--mode <ssg|ssr>]
9
+ * npx create-litro --list-recipes
10
+ *
11
+ * Prompts for project name, recipe, and mode, then scaffolds a complete
12
+ * Litro project from the selected recipe template.
13
+ *
14
+ * No external dependencies — uses Node.js built-ins only.
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * create-litro — Scaffolding CLI for Litro
4
+ *
5
+ * Usage:
6
+ * npm create litro
7
+ * npx create-litro
8
+ * npx create-litro <project-name> [--recipe <recipe>] [--mode <ssg|ssr>]
9
+ * npx create-litro --list-recipes
10
+ *
11
+ * Prompts for project name, recipe, and mode, then scaffolds a complete
12
+ * Litro project from the selected recipe template.
13
+ *
14
+ * No external dependencies — uses Node.js built-ins only.
15
+ */
16
+ import { createInterface } from 'node:readline/promises';
17
+ import { stdin as input, stdout as output } from 'node:process';
18
+ import { existsSync } from 'node:fs';
19
+ import { join } from 'node:path';
20
+ import process from 'node:process';
21
+ import { listRecipes, loadRecipe, scaffold } from './scaffold.js';
22
+ // ---------------------------------------------------------------------------
23
+ // Prompt helpers
24
+ // ---------------------------------------------------------------------------
25
+ async function prompt(question, defaultVal = '') {
26
+ // If stdin is not a TTY (piped/redirected), use the default immediately.
27
+ if (!process.stdin.isTTY)
28
+ return defaultVal;
29
+ const rl = createInterface({ input, output });
30
+ const answer = await rl.question(defaultVal ? `${question} (${defaultVal}): ` : `${question}: `);
31
+ rl.close();
32
+ return answer.trim() || defaultVal;
33
+ }
34
+ async function promptSelect(question, choices, defaultVal) {
35
+ if (!process.stdin.isTTY)
36
+ return defaultVal ?? choices[0];
37
+ const lines = choices.map((c, i) => ` ${i + 1}. ${c}`).join('\n');
38
+ const defaultIdx = defaultVal ? choices.indexOf(defaultVal) + 1 : 1;
39
+ const rl = createInterface({ input, output });
40
+ // eslint-disable-next-line no-constant-condition
41
+ while (true) {
42
+ const answer = await rl.question(`${question}\n${lines}\n Choice (${defaultIdx}): `);
43
+ const trimmed = answer.trim();
44
+ if (trimmed === '') {
45
+ rl.close();
46
+ return choices[defaultIdx - 1];
47
+ }
48
+ const n = parseInt(trimmed, 10);
49
+ if (!isNaN(n) && n >= 1 && n <= choices.length) {
50
+ rl.close();
51
+ return choices[n - 1];
52
+ }
53
+ // Allow typing the value directly.
54
+ if (choices.includes(trimmed)) {
55
+ rl.close();
56
+ return trimmed;
57
+ }
58
+ process.stdout.write(` Please enter a number between 1 and ${choices.length}.\n`);
59
+ }
60
+ }
61
+ function parseArgs(argv) {
62
+ // argv = process.argv.slice(2)
63
+ let projectName;
64
+ let recipe;
65
+ let mode;
66
+ let listRecipesFlag = false;
67
+ for (let i = 0; i < argv.length; i++) {
68
+ const arg = argv[i];
69
+ if (arg === '--list-recipes') {
70
+ listRecipesFlag = true;
71
+ }
72
+ else if (arg === '--recipe' || arg === '-r') {
73
+ recipe = argv[++i];
74
+ }
75
+ else if (arg === '--mode' || arg === '-m') {
76
+ const val = argv[++i];
77
+ if (val === 'ssg' || val === 'ssr')
78
+ mode = val;
79
+ }
80
+ else if (!arg.startsWith('-') && projectName === undefined) {
81
+ projectName = arg;
82
+ }
83
+ }
84
+ return { projectName, recipe, mode, listRecipes: listRecipesFlag };
85
+ }
86
+ // ---------------------------------------------------------------------------
87
+ // Main
88
+ // ---------------------------------------------------------------------------
89
+ async function main() {
90
+ const args = parseArgs(process.argv.slice(2));
91
+ // --list-recipes: print available recipes and exit.
92
+ if (args.listRecipes) {
93
+ const recipes = await listRecipes();
94
+ if (recipes.length === 0) {
95
+ console.log('\n No recipes found.\n');
96
+ }
97
+ else {
98
+ console.log('\n Available recipes:\n');
99
+ for (const r of recipes) {
100
+ console.log(` ${r.name.padEnd(20)} ${r.displayName} — ${r.description}`);
101
+ }
102
+ console.log('');
103
+ }
104
+ return;
105
+ }
106
+ console.log('\n Welcome to Litro!\n');
107
+ // 1. Project name
108
+ const projectName = args.projectName ?? await prompt('Project name', 'my-litro-app');
109
+ // 2. Recipe selection
110
+ const recipes = await listRecipes();
111
+ let chosenRecipe;
112
+ if (args.recipe) {
113
+ const found = await loadRecipe(args.recipe);
114
+ if (!found) {
115
+ console.error(`\n Error: recipe "${args.recipe}" not found.\n`);
116
+ process.exit(1);
117
+ }
118
+ chosenRecipe = found;
119
+ }
120
+ else if (recipes.length === 0) {
121
+ console.error('\n Error: no recipes available.\n');
122
+ process.exit(1);
123
+ }
124
+ else if (recipes.length === 1) {
125
+ chosenRecipe = recipes[0];
126
+ }
127
+ else {
128
+ const displayNames = recipes.map((r) => `${r.name} — ${r.description}`);
129
+ const selected = await promptSelect('Select a recipe:', displayNames);
130
+ // Match back to the recipe by index in displayNames.
131
+ const idx = displayNames.indexOf(selected);
132
+ chosenRecipe = recipes[idx !== -1 ? idx : 0];
133
+ }
134
+ // 3. Mode selection (only if recipe supports both)
135
+ let mode;
136
+ if (chosenRecipe.mode === 'both') {
137
+ if (args.mode) {
138
+ mode = args.mode;
139
+ }
140
+ else {
141
+ const selected = await promptSelect('Deployment mode:', ['ssr — Server-side rendering (Node.js / edge)', 'ssg — Static site generation (CDN)'], 'ssr — Server-side rendering (Node.js / edge)');
142
+ mode = selected.startsWith('ssg') ? 'ssg' : 'ssr';
143
+ }
144
+ }
145
+ else {
146
+ mode = chosenRecipe.mode;
147
+ }
148
+ // 4. Recipe-specific options (prompt for any that are defined on the recipe)
149
+ const recipeOptions = {};
150
+ if (chosenRecipe.options && chosenRecipe.options.length > 0) {
151
+ for (const opt of chosenRecipe.options) {
152
+ if (opt.type === 'select' && opt.choices) {
153
+ const selected = await promptSelect(opt.prompt, opt.choices, opt.default);
154
+ recipeOptions[opt.key] = selected;
155
+ }
156
+ else if (opt.type === 'confirm') {
157
+ const answer = await prompt(`${opt.prompt} (y/n)`, opt.default ? 'y' : 'n');
158
+ recipeOptions[opt.key] = answer.toLowerCase().startsWith('y');
159
+ }
160
+ else {
161
+ // text
162
+ const answer = await prompt(opt.prompt, String(opt.default ?? ''));
163
+ recipeOptions[opt.key] = answer;
164
+ }
165
+ }
166
+ }
167
+ // 5. Validate target directory
168
+ const projectDir = join(process.cwd(), projectName);
169
+ if (existsSync(projectDir)) {
170
+ console.error(`\n Error: directory "${projectName}" already exists.\n`);
171
+ process.exit(1);
172
+ }
173
+ // 6. Scaffold
174
+ const options = {
175
+ projectName,
176
+ mode,
177
+ recipeOptions,
178
+ recipeVersion: '0.0.1',
179
+ };
180
+ await scaffold(chosenRecipe.name, options, projectDir);
181
+ console.log(`
182
+ Created ${projectName}
183
+
184
+ Next steps:
185
+
186
+ cd ${projectName}
187
+ npm install # or: pnpm install / yarn install
188
+ npm run dev # start dev server on http://localhost:3030
189
+
190
+ Commands:
191
+ npm run dev start development server
192
+ npm run build production build (Vite + Nitro)
193
+ npm run preview preview the production build
194
+ `);
195
+ }
196
+ main().catch((err) => {
197
+ console.error('[create-litro] Fatal error:', err);
198
+ process.exit(1);
199
+ });
200
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * scaffold.ts — Recipe-driven project scaffolding for create-litro.
3
+ *
4
+ * At runtime the compiled bin is dist/src/index.js and recipes live at
5
+ * dist/recipes/<name>/. This module resolves recipe directories relative to
6
+ * import.meta.url so it works regardless of CWD.
7
+ *
8
+ * No external dependencies — uses Node.js built-ins only.
9
+ */
10
+ import type { LitroRecipe } from './types.js';
11
+ export interface ScaffoldOptions {
12
+ projectName: string;
13
+ mode: 'ssg' | 'ssr';
14
+ recipeOptions?: Record<string, unknown>;
15
+ recipeVersion?: string;
16
+ }
17
+ /**
18
+ * Return `LitroRecipe` objects for all recipe directories found under
19
+ * dist/recipes/. Each recipe must have a `recipe.config.js` file that
20
+ * exports a default `LitroRecipe`.
21
+ */
22
+ export declare function listRecipes(): Promise<LitroRecipe[]>;
23
+ /**
24
+ * Load a single recipe by name. Returns null if not found.
25
+ */
26
+ export declare function loadRecipe(name: string): Promise<LitroRecipe | null>;
27
+ /**
28
+ * Scaffold a project from a recipe into `targetDir`.
29
+ *
30
+ * @param recipeName The recipe directory name (e.g. "fullstack").
31
+ * @param options Scaffold options (projectName, mode, etc.).
32
+ * @param targetDir Absolute path to the target project directory.
33
+ */
34
+ export declare function scaffold(recipeName: string, options: ScaffoldOptions, targetDir: string): Promise<void>;
35
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAgGD;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CA2B1D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAQ1E;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,eAAe,EACxB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAuBf"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * scaffold.ts — Recipe-driven project scaffolding for create-litro.
3
+ *
4
+ * At runtime the compiled bin is dist/src/index.js and recipes live at
5
+ * dist/recipes/<name>/. This module resolves recipe directories relative to
6
+ * import.meta.url so it works regardless of CWD.
7
+ *
8
+ * No external dependencies — uses Node.js built-ins only.
9
+ */
10
+ import { readdir, readFile, writeFile, mkdir, copyFile, stat } from 'node:fs/promises';
11
+ import { join, dirname, extname } from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ // ---------------------------------------------------------------------------
14
+ // Internal helpers
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Returns the absolute path to the dist/recipes/ directory.
18
+ *
19
+ * At runtime the compiled layout is:
20
+ * dist/
21
+ * src/scaffold.js ← this file
22
+ * recipes/<name>/ ← recipe configs + templates
23
+ *
24
+ * So we go one level up from the src/ output dir to find recipes/.
25
+ */
26
+ function recipesDir() {
27
+ // import.meta.url points to the current compiled file (dist/src/scaffold.js).
28
+ const thisFile = fileURLToPath(import.meta.url);
29
+ return join(dirname(thisFile), '..', 'recipes');
30
+ }
31
+ /** File extensions treated as binary — copied byte-for-byte, no interpolation. */
32
+ const BINARY_EXTENSIONS = new Set([
33
+ '.png', '.jpg', '.jpeg', '.gif', '.ico', '.webp',
34
+ '.svg', '.woff', '.woff2', '.ttf', '.eot', '.otf',
35
+ '.pdf', '.zip', '.gz', '.tar',
36
+ ]);
37
+ function isBinary(filePath) {
38
+ return BINARY_EXTENSIONS.has(extname(filePath).toLowerCase());
39
+ }
40
+ /**
41
+ * Replace `{{key}}` placeholders in `text` with values from `vars`.
42
+ * Unknown keys are left unchanged (the `{{key}}` literal remains).
43
+ */
44
+ function interpolate(text, vars) {
45
+ return text.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
46
+ return Object.prototype.hasOwnProperty.call(vars, key) ? vars[key] : `{{${key}}}`;
47
+ });
48
+ }
49
+ /**
50
+ * Build the interpolation variable map from ScaffoldOptions.
51
+ */
52
+ function buildVars(options) {
53
+ const vars = {
54
+ projectName: options.projectName,
55
+ mode: options.mode,
56
+ recipeVersion: options.recipeVersion ?? '0.0.0',
57
+ };
58
+ if (options.recipeOptions) {
59
+ for (const [k, v] of Object.entries(options.recipeOptions)) {
60
+ vars[k] = String(v);
61
+ }
62
+ }
63
+ return vars;
64
+ }
65
+ /**
66
+ * Recursively copy all files from `srcDir` to `destDir`, applying
67
+ * `{{placeholder}}` interpolation to text files.
68
+ */
69
+ async function copyTemplate(srcDir, destDir, vars) {
70
+ const entries = await readdir(srcDir, { withFileTypes: true });
71
+ for (const entry of entries) {
72
+ const srcPath = join(srcDir, entry.name);
73
+ const destPath = join(destDir, entry.name);
74
+ if (entry.isDirectory()) {
75
+ await mkdir(destPath, { recursive: true });
76
+ await copyTemplate(srcPath, destPath, vars);
77
+ }
78
+ else {
79
+ if (isBinary(entry.name)) {
80
+ await copyFile(srcPath, destPath);
81
+ }
82
+ else {
83
+ const raw = await readFile(srcPath, 'utf8');
84
+ const interpolated = interpolate(raw, vars);
85
+ await writeFile(destPath, interpolated, 'utf8');
86
+ }
87
+ }
88
+ }
89
+ }
90
+ // ---------------------------------------------------------------------------
91
+ // Public API
92
+ // ---------------------------------------------------------------------------
93
+ /**
94
+ * Return `LitroRecipe` objects for all recipe directories found under
95
+ * dist/recipes/. Each recipe must have a `recipe.config.js` file that
96
+ * exports a default `LitroRecipe`.
97
+ */
98
+ export async function listRecipes() {
99
+ const dir = recipesDir();
100
+ let entries;
101
+ try {
102
+ entries = await readdir(dir, { withFileTypes: true });
103
+ }
104
+ catch {
105
+ // No recipes directory — return empty list.
106
+ return [];
107
+ }
108
+ const recipes = [];
109
+ for (const entry of entries) {
110
+ if (!entry.isDirectory())
111
+ continue;
112
+ const configPath = join(dir, entry.name, 'recipe.config.js');
113
+ try {
114
+ // Dynamic import resolves relative to CWD when given an absolute path.
115
+ const mod = await import(configPath);
116
+ recipes.push(mod.default);
117
+ }
118
+ catch {
119
+ // Skip invalid/missing recipe configs silently.
120
+ }
121
+ }
122
+ return recipes;
123
+ }
124
+ /**
125
+ * Load a single recipe by name. Returns null if not found.
126
+ */
127
+ export async function loadRecipe(name) {
128
+ const configPath = join(recipesDir(), name, 'recipe.config.js');
129
+ try {
130
+ const mod = await import(configPath);
131
+ return mod.default;
132
+ }
133
+ catch {
134
+ return null;
135
+ }
136
+ }
137
+ /**
138
+ * Scaffold a project from a recipe into `targetDir`.
139
+ *
140
+ * @param recipeName The recipe directory name (e.g. "fullstack").
141
+ * @param options Scaffold options (projectName, mode, etc.).
142
+ * @param targetDir Absolute path to the target project directory.
143
+ */
144
+ export async function scaffold(recipeName, options, targetDir) {
145
+ const templateDir = join(recipesDir(), recipeName, 'template');
146
+ // Verify the template directory exists.
147
+ try {
148
+ const s = await stat(templateDir);
149
+ if (!s.isDirectory()) {
150
+ throw new Error(`Recipe template path is not a directory: ${templateDir}`);
151
+ }
152
+ }
153
+ catch (err) {
154
+ const nodeErr = err;
155
+ if (nodeErr.code === 'ENOENT') {
156
+ throw new Error(`Recipe "${recipeName}" not found (looked for ${templateDir})`);
157
+ }
158
+ throw err;
159
+ }
160
+ // Create the target directory.
161
+ await mkdir(targetDir, { recursive: true });
162
+ // Build interpolation variables and copy all files.
163
+ const vars = buildVars(options);
164
+ await copyTemplate(templateDir, targetDir, vars);
165
+ }
166
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/scaffold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scaffold.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.test.d.ts","sourceRoot":"","sources":["../../src/scaffold.test.ts"],"names":[],"mappings":""}