@fluojs/cli 1.1.0 → 3.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.
Files changed (137) hide show
  1. package/README.ko.md +183 -22
  2. package/README.md +186 -22
  3. package/dist/cli.d.ts +5 -4
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +128 -35
  6. package/dist/commands/diagnostics.d.ts +35 -0
  7. package/dist/commands/diagnostics.d.ts.map +1 -1
  8. package/dist/commands/diagnostics.js +60 -0
  9. package/dist/commands/generate.d.ts +1 -49
  10. package/dist/commands/generate.d.ts.map +1 -1
  11. package/dist/commands/generate.js +1 -214
  12. package/dist/commands/inspect.d.ts +5 -7
  13. package/dist/commands/inspect.d.ts.map +1 -1
  14. package/dist/commands/inspect.js +85 -65
  15. package/dist/commands/migrate.d.ts.map +1 -1
  16. package/dist/commands/migrate.js +27 -15
  17. package/dist/commands/migration-transform-tokens.d.ts +15 -0
  18. package/dist/commands/migration-transform-tokens.d.ts.map +1 -0
  19. package/dist/commands/migration-transform-tokens.js +41 -0
  20. package/dist/commands/new.d.ts +0 -6
  21. package/dist/commands/new.d.ts.map +1 -1
  22. package/dist/commands/new.js +42 -96
  23. package/dist/commands/output-path-safety.d.ts +14 -0
  24. package/dist/commands/output-path-safety.d.ts.map +1 -0
  25. package/dist/commands/output-path-safety.js +34 -0
  26. package/dist/commands/scripts.d.ts +1 -1
  27. package/dist/commands/scripts.d.ts.map +1 -1
  28. package/dist/commands/scripts.js +13 -7
  29. package/dist/commands/typegen-artifact.d.ts +54 -0
  30. package/dist/commands/typegen-artifact.d.ts.map +1 -0
  31. package/dist/commands/typegen-artifact.js +117 -0
  32. package/dist/commands/typegen-generation-child.d.ts +2 -0
  33. package/dist/commands/typegen-generation-child.d.ts.map +1 -0
  34. package/dist/commands/typegen-generation-child.js +59 -0
  35. package/dist/commands/typegen-generation-process.d.ts +46 -0
  36. package/dist/commands/typegen-generation-process.d.ts.map +1 -0
  37. package/dist/commands/typegen-generation-process.js +131 -0
  38. package/dist/commands/typegen-generation-protocol.d.ts +16 -0
  39. package/dist/commands/typegen-generation-protocol.d.ts.map +1 -0
  40. package/dist/commands/typegen-generation-protocol.js +35 -0
  41. package/dist/commands/typegen-isolated-source.d.ts +10 -0
  42. package/dist/commands/typegen-isolated-source.d.ts.map +1 -0
  43. package/dist/commands/typegen-isolated-source.js +75 -0
  44. package/dist/commands/typegen-options.d.ts +20 -0
  45. package/dist/commands/typegen-options.d.ts.map +1 -0
  46. package/dist/commands/typegen-options.js +71 -0
  47. package/dist/commands/typegen-source.d.ts +59 -0
  48. package/dist/commands/typegen-source.d.ts.map +1 -0
  49. package/dist/commands/typegen-source.js +183 -0
  50. package/dist/commands/typegen-watch.d.ts +46 -0
  51. package/dist/commands/typegen-watch.d.ts.map +1 -0
  52. package/dist/commands/typegen-watch.js +212 -0
  53. package/dist/commands/typegen.d.ts +29 -0
  54. package/dist/commands/typegen.d.ts.map +1 -0
  55. package/dist/commands/typegen.js +119 -0
  56. package/dist/dev-runner/node-restart-runner.d.ts +6 -0
  57. package/dist/dev-runner/node-restart-runner.d.ts.map +1 -1
  58. package/dist/dev-runner/node-restart-runner.js +64 -13
  59. package/dist/fixtures/inspect-react-app.module.d.ts +4 -0
  60. package/dist/fixtures/inspect-react-app.module.d.ts.map +1 -0
  61. package/dist/fixtures/inspect-react-app.module.js +32 -0
  62. package/dist/fixtures/typegen-react-app.module.d.ts +4 -0
  63. package/dist/fixtures/typegen-react-app.module.d.ts.map +1 -0
  64. package/dist/fixtures/typegen-react-app.module.js +33 -0
  65. package/dist/generate-command.d.ts +50 -0
  66. package/dist/generate-command.d.ts.map +1 -0
  67. package/dist/generate-command.js +214 -0
  68. package/dist/index.d.ts +6 -5
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +6 -5
  71. package/dist/new/install.js +1 -1
  72. package/dist/new/package-spec-resolver.d.ts.map +1 -1
  73. package/dist/new/package-spec-resolver.js +50 -59
  74. package/dist/new/prompt.d.ts +1 -0
  75. package/dist/new/prompt.d.ts.map +1 -1
  76. package/dist/new/prompt.js +40 -12
  77. package/dist/new/published-internal-dependencies.d.ts +20 -0
  78. package/dist/new/published-internal-dependencies.d.ts.map +1 -0
  79. package/dist/new/published-internal-dependencies.js +20 -0
  80. package/dist/new/react-vite-ssr-scaffold.d.ts +19 -0
  81. package/dist/new/react-vite-ssr-scaffold.d.ts.map +1 -0
  82. package/dist/new/react-vite-ssr-scaffold.js +108 -0
  83. package/dist/new/resolver.d.ts +2 -2
  84. package/dist/new/resolver.d.ts.map +1 -1
  85. package/dist/new/resolver.js +5 -1
  86. package/dist/new/scaffold.d.ts.map +1 -1
  87. package/dist/new/scaffold.js +177 -54
  88. package/dist/new/starter-profiles.d.ts +8 -4
  89. package/dist/new/starter-profiles.d.ts.map +1 -1
  90. package/dist/new/starter-profiles.js +52 -18
  91. package/dist/new/templates/react-vite-ssr/README.md.ejs +74 -0
  92. package/dist/new/templates/react-vite-ssr/playwright.config.ts.ejs +26 -0
  93. package/dist/new/templates/react-vite-ssr/src/app.test.ts.ejs +82 -0
  94. package/dist/new/templates/react-vite-ssr/src/app.ts.ejs +91 -0
  95. package/dist/new/templates/react-vite-ssr/src/entry-client.tsx.ejs +29 -0
  96. package/dist/new/templates/react-vite-ssr/src/entry-server.tsx.ejs +52 -0
  97. package/dist/new/templates/react-vite-ssr/src/load-manifest.test.ts.ejs +55 -0
  98. package/dist/new/templates/react-vite-ssr/src/load-manifest.ts.ejs +53 -0
  99. package/dist/new/templates/react-vite-ssr/src/main.ts.ejs +18 -0
  100. package/dist/new/templates/react-vite-ssr/src/page.tsx.ejs +43 -0
  101. package/dist/new/templates/react-vite-ssr/src/react-app.test.tsx.ejs +67 -0
  102. package/dist/new/templates/react-vite-ssr/src/react-app.tsx.ejs +46 -0
  103. package/dist/new/templates/react-vite-ssr/src/styles.css.ejs +25 -0
  104. package/dist/new/templates/react-vite-ssr/src/styles.d.ts.ejs +1 -0
  105. package/dist/new/templates/react-vite-ssr/tests/production-hydration.spec.ts.ejs +54 -0
  106. package/dist/new/templates/react-vite-ssr/tsconfig.json.ejs +16 -0
  107. package/dist/new/templates/react-vite-ssr/vite.client.config.ts.ejs +24 -0
  108. package/dist/new/templates/react-vite-ssr/vite.server.config.ts.ejs +17 -0
  109. package/dist/new/templates/react-vite-ssr/vitest.config.ts.ejs +10 -0
  110. package/dist/new/types.d.ts +4 -2
  111. package/dist/new/types.d.ts.map +1 -1
  112. package/dist/public-generate.d.ts +2 -0
  113. package/dist/public-generate.d.ts.map +1 -0
  114. package/dist/public-generate.js +1 -0
  115. package/dist/public-inspect.d.ts +13 -0
  116. package/dist/public-inspect.d.ts.map +1 -0
  117. package/dist/public-inspect.js +16 -0
  118. package/dist/public-new.d.ts +13 -0
  119. package/dist/public-new.d.ts.map +1 -0
  120. package/dist/public-new.js +16 -0
  121. package/dist/public-typegen.d.ts +14 -0
  122. package/dist/public-typegen.d.ts.map +1 -0
  123. package/dist/public-typegen.js +17 -0
  124. package/dist/run-cli.d.ts +2 -1
  125. package/dist/run-cli.d.ts.map +1 -1
  126. package/dist/studio/sidecar.d.ts.map +1 -1
  127. package/dist/studio/sidecar.js +106 -14
  128. package/dist/transforms/nestjs-migrate.d.ts +4 -1
  129. package/dist/transforms/nestjs-migrate.d.ts.map +1 -1
  130. package/dist/transforms/nestjs-migrate.js +625 -65
  131. package/dist/typegen-contract.d.ts +10 -0
  132. package/dist/typegen-contract.d.ts.map +1 -0
  133. package/dist/typegen-contract.js +9 -0
  134. package/dist/usage.d.ts +19 -0
  135. package/dist/usage.d.ts.map +1 -0
  136. package/dist/usage.js +178 -0
  137. package/package.json +19 -10
@@ -1,14 +1,13 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { dirname, join, resolve } from 'node:path';
3
- import * as clack from '@clack/prompts';
3
+ import { CliPromptCancelledError } from '../prompt-cancel.js';
4
4
  import { resolveBootstrapSchema } from './resolver.js';
5
5
  import { DOCUMENTED_MICROSERVICE_TRANSPORTS, getApplicationStarterProfiles } from './starter-profiles.js';
6
- import { CliPromptCancelledError } from '../prompt-cancel.js';
7
-
8
6
  /** Default package manager used when detection has no signal. */
9
7
  export const DEFAULT_PACKAGE_MANAGER = 'pnpm';
10
8
  const DEFAULT_INSTALL_DEPENDENCIES = true;
11
9
  const DEFAULT_INITIALIZE_GIT = false;
10
+ const CLACK_MISSING_MESSAGE = ['Interactive CLI commands require @clack/prompts, but it is not resolvable from this installation.', 'Install a version whose Node.js engine supports your current Node.js version and rerun the command.'].join('\n');
12
11
  const STARTER_SHAPE_CHOICES = [{
13
12
  label: 'Application',
14
13
  value: 'application'
@@ -19,6 +18,13 @@ const STARTER_SHAPE_CHOICES = [{
19
18
  label: 'Mixed',
20
19
  value: 'mixed'
21
20
  }];
21
+ const STARTER_CHOICES = [{
22
+ label: 'Standard backend',
23
+ value: 'standard'
24
+ }, {
25
+ label: 'React SSR + Vite',
26
+ value: 'react-vite-ssr'
27
+ }];
22
28
 
23
29
  /** Prompt contract used by the interactive `fluo new` wizard. */
24
30
 
@@ -33,7 +39,18 @@ function resolveCompletionMessage(completionMessage, answers) {
33
39
  function hasOwnValue(partial, key) {
34
40
  return partial[key] !== undefined;
35
41
  }
36
- function createBootstrapPrompter() {
42
+ async function loadClackPrompts() {
43
+ try {
44
+ return await import('@clack/prompts');
45
+ } catch (error) {
46
+ const code = typeof error === 'object' && error !== null && 'code' in error ? error.code : undefined;
47
+ if (code === 'MODULE_NOT_FOUND' || code === 'ERR_MODULE_NOT_FOUND') {
48
+ throw new Error(CLACK_MISSING_MESSAGE);
49
+ }
50
+ throw error;
51
+ }
52
+ }
53
+ async function createBootstrapPrompter(clack) {
37
54
  return {
38
55
  async confirm(message, defaultValue) {
39
56
  const result = await clack.confirm({
@@ -80,7 +97,8 @@ function createBootstrapPrompter() {
80
97
  }
81
98
  function shouldPromptForAnswers(partial, interactive) {
82
99
  const selectedRuntime = partial.runtime;
83
- return interactive && (!hasOwnValue(partial, 'projectName') || !hasOwnValue(partial, 'shape') || !hasOwnValue(partial, 'tooling') || !hasOwnValue(partial, 'packageManager') || !hasOwnValue(partial, 'installDependencies') || !hasOwnValue(partial, 'initializeGit') || partial.shape === 'application' && !hasOwnValue(partial, 'runtime') || partial.shape === 'application' && selectedRuntime === 'node' && !hasOwnValue(partial, 'platform') || partial.shape === 'microservice' && !hasOwnValue(partial, 'transport'));
100
+ const needsStarterSelection = !hasOwnValue(partial, 'starter') && !hasOwnValue(partial, 'shape') && !hasOwnValue(partial, 'runtime') && !hasOwnValue(partial, 'platform') && !hasOwnValue(partial, 'transport');
101
+ return interactive && (!hasOwnValue(partial, 'projectName') || needsStarterSelection || !hasOwnValue(partial, 'shape') || !hasOwnValue(partial, 'tooling') || !hasOwnValue(partial, 'packageManager') || !hasOwnValue(partial, 'installDependencies') || !hasOwnValue(partial, 'initializeGit') || partial.shape === 'application' && !hasOwnValue(partial, 'runtime') || partial.shape === 'application' && selectedRuntime === 'node' && !hasOwnValue(partial, 'platform') || partial.shape === 'microservice' && !hasOwnValue(partial, 'transport'));
84
102
  }
85
103
  async function resolveInteractiveBootstrapAnswers(partial, cwd, userAgent, prompt) {
86
104
  const answers = {
@@ -90,10 +108,17 @@ async function resolveInteractiveBootstrapAnswers(partial, cwd, userAgent, promp
90
108
  if (!answers.projectName) {
91
109
  answers.projectName = assertValidProjectName(await prompt.text('Project name'));
92
110
  }
93
- if (!answers.shape) {
111
+ if (!answers.starter) {
112
+ const hasSchemaSelection = answers.shape !== undefined || answers.runtime !== undefined || answers.platform !== undefined || answers.transport !== undefined;
113
+ answers.starter = hasSchemaSelection ? 'standard' : await prompt.select('Starter', STARTER_CHOICES, 'standard');
114
+ }
115
+ if (answers.starter === 'react-vite-ssr') {
116
+ Object.assign(answers, resolveBootstrapSchema(answers));
117
+ }
118
+ if (answers.starter === 'standard' && !answers.shape) {
94
119
  answers.shape = await prompt.select('Starter shape', STARTER_SHAPE_CHOICES, 'application');
95
120
  }
96
- if (answers.shape === 'application' && !answers.runtime) {
121
+ if (answers.starter === 'standard' && answers.shape === 'application' && !answers.runtime) {
97
122
  answers.runtime = await prompt.select('Runtime', [{
98
123
  label: 'Bun',
99
124
  value: 'bun'
@@ -108,7 +133,7 @@ async function resolveInteractiveBootstrapAnswers(partial, cwd, userAgent, promp
108
133
  value: 'node'
109
134
  }], 'node');
110
135
  }
111
- if (answers.shape === 'application' && !answers.platform) {
136
+ if (answers.starter === 'standard' && answers.shape === 'application' && !answers.platform) {
112
137
  if (answers.runtime === 'node') {
113
138
  const applicationProfiles = getApplicationStarterProfiles('node');
114
139
  answers.platform = await prompt.select('HTTP platform', applicationProfiles.map(profile => ({
@@ -119,7 +144,7 @@ async function resolveInteractiveBootstrapAnswers(partial, cwd, userAgent, promp
119
144
  answers.platform = answers.runtime;
120
145
  }
121
146
  }
122
- if (answers.shape === 'microservice' && !answers.transport) {
147
+ if (answers.starter === 'standard' && answers.shape === 'microservice' && !answers.transport) {
123
148
  answers.transport = await prompt.select('Microservice transport', DOCUMENTED_MICROSERVICE_TRANSPORTS.map(transport => ({
124
149
  label: transport,
125
150
  value: transport
@@ -251,6 +276,7 @@ export function resolveBootstrapAnswers(partial, cwd, userAgent) {
251
276
  packageManager: partial.packageManager ?? detectPackageManager(cwd, userAgent),
252
277
  ...schema,
253
278
  projectName,
279
+ starter: partial.starter ?? 'standard',
254
280
  targetDirectory: partial.targetDirectory ?? `./${projectName}`
255
281
  };
256
282
  }
@@ -269,15 +295,17 @@ export async function collectBootstrapAnswers(partial, cwd, userAgent, options =
269
295
  if (!shouldPromptForAnswers(partial, interactive)) {
270
296
  return resolveBootstrapAnswers(partial, cwd, userAgent);
271
297
  }
272
- const prompt = options.prompt ?? createBootstrapPrompter();
273
298
  const isInteractiveShell = options.prompt === undefined;
299
+ options.onInteractivePrompt?.();
300
+ const clack = isInteractiveShell ? await loadClackPrompts() : undefined;
301
+ const prompt = options.prompt ?? (await createBootstrapPrompter(clack ?? (await loadClackPrompts())));
274
302
  try {
275
303
  if (isInteractiveShell) {
276
- clack.intro('fluo new');
304
+ clack?.intro('fluo new');
277
305
  }
278
306
  const answers = await resolveInteractiveBootstrapAnswers(partial, cwd, userAgent, prompt);
279
307
  if (isInteractiveShell) {
280
- clack.outro(resolveCompletionMessage(options.completionMessage, answers));
308
+ clack?.outro(resolveCompletionMessage(options.completionMessage, answers));
281
309
  }
282
310
  return answers;
283
311
  } finally {
@@ -0,0 +1,20 @@
1
+ /** Per-package release ranges for all published starter dependencies except the generator CLI itself. */
2
+ export declare const PUBLISHED_INTERNAL_DEPENDENCIES: {
3
+ readonly "@fluojs/config": "^2.0.0";
4
+ readonly "@fluojs/core": "^2.0.0";
5
+ readonly "@fluojs/di": "^3.0.0";
6
+ readonly "@fluojs/http": "^3.0.0";
7
+ readonly "@fluojs/microservices": "^2.0.0";
8
+ readonly "@fluojs/platform-bun": "^3.0.0";
9
+ readonly "@fluojs/platform-cloudflare-workers": "^2.0.0";
10
+ readonly "@fluojs/platform-deno": "^2.0.0";
11
+ readonly "@fluojs/platform-express": "^2.0.0";
12
+ readonly "@fluojs/platform-fastify": "^2.0.0";
13
+ readonly "@fluojs/platform-nodejs": "^2.0.0";
14
+ readonly "@fluojs/react": "^0.2.0";
15
+ readonly "@fluojs/runtime": "^3.0.0";
16
+ readonly "@fluojs/testing": "^3.0.0";
17
+ readonly "@fluojs/validation": "^2.0.0";
18
+ readonly "@fluojs/vite": "^2.0.0";
19
+ };
20
+ //# sourceMappingURL=published-internal-dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"published-internal-dependencies.d.ts","sourceRoot":"","sources":["../../src/new/published-internal-dependencies.ts"],"names":[],"mappings":"AACA,yGAAyG;AACzG,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;CAiBlC,CAAC"}
@@ -0,0 +1,20 @@
1
+ // Generated by scripts/generate-published-internal-dependencies.mjs during the CLI build.
2
+ /** Per-package release ranges for all published starter dependencies except the generator CLI itself. */
3
+ export const PUBLISHED_INTERNAL_DEPENDENCIES = {
4
+ "@fluojs/config": "^2.0.0",
5
+ "@fluojs/core": "^2.0.0",
6
+ "@fluojs/di": "^3.0.0",
7
+ "@fluojs/http": "^3.0.0",
8
+ "@fluojs/microservices": "^2.0.0",
9
+ "@fluojs/platform-bun": "^3.0.0",
10
+ "@fluojs/platform-cloudflare-workers": "^2.0.0",
11
+ "@fluojs/platform-deno": "^2.0.0",
12
+ "@fluojs/platform-express": "^2.0.0",
13
+ "@fluojs/platform-fastify": "^2.0.0",
14
+ "@fluojs/platform-nodejs": "^2.0.0",
15
+ "@fluojs/react": "^0.2.0",
16
+ "@fluojs/runtime": "^3.0.0",
17
+ "@fluojs/testing": "^3.0.0",
18
+ "@fluojs/validation": "^2.0.0",
19
+ "@fluojs/vite": "^2.0.0"
20
+ };
@@ -0,0 +1,19 @@
1
+ import type { PackageManager } from './types.js';
2
+ type ReactViteSsrTemplateContext = {
3
+ readonly packageManager: PackageManager;
4
+ readonly projectName: string;
5
+ };
6
+ type ReactViteSsrScaffoldFile = {
7
+ content: string;
8
+ path: string;
9
+ };
10
+ /**
11
+ * Renders the React SSR + Vite starter template tree with explicit lifecycle commands.
12
+ *
13
+ * @param context Validated project and package-manager command values for template rendering.
14
+ * @param importMetaUrl Module URL used to locate packaged starter templates.
15
+ * @returns Generated scaffold files with rendered template content.
16
+ */
17
+ export declare function createReactViteSsrScaffoldFiles(context: ReactViteSsrTemplateContext, importMetaUrl?: string): ReactViteSsrScaffoldFile[];
18
+ export {};
19
+ //# sourceMappingURL=react-vite-ssr-scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-vite-ssr-scaffold.d.ts","sourceRoot":"","sources":["../../src/new/react-vite-ssr-scaffold.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAOjD,KAAK,2BAA2B,GAAG;IACjC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAmEF;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,2BAA2B,EACpC,aAAa,SAAkB,GAC9B,wBAAwB,EAAE,CAkB5B"}
@@ -0,0 +1,108 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const INSTALL_COMMAND_BY_PACKAGE_MANAGER = {
5
+ bun: 'bun install',
6
+ npm: 'npm install',
7
+ pnpm: 'pnpm install',
8
+ yarn: 'yarn install'
9
+ };
10
+ const RUN_PREFIX_BY_PACKAGE_MANAGER = {
11
+ bun: 'bun run',
12
+ npm: 'npm run',
13
+ pnpm: 'pnpm',
14
+ yarn: 'yarn'
15
+ };
16
+ const REACT_VITE_SSR_TEMPLATES = [{
17
+ outputPath: 'README.md',
18
+ templatePath: 'README.md.ejs'
19
+ }, {
20
+ outputPath: 'playwright.config.ts',
21
+ templatePath: 'playwright.config.ts.ejs'
22
+ }, {
23
+ outputPath: 'tsconfig.json',
24
+ templatePath: 'tsconfig.json.ejs'
25
+ }, {
26
+ outputPath: 'vite.client.config.ts',
27
+ templatePath: 'vite.client.config.ts.ejs'
28
+ }, {
29
+ outputPath: 'vite.server.config.ts',
30
+ templatePath: 'vite.server.config.ts.ejs'
31
+ }, {
32
+ outputPath: 'vitest.config.ts',
33
+ templatePath: 'vitest.config.ts.ejs'
34
+ }, {
35
+ outputPath: 'src/app.test.ts',
36
+ templatePath: 'src/app.test.ts.ejs'
37
+ }, {
38
+ outputPath: 'src/app.ts',
39
+ templatePath: 'src/app.ts.ejs'
40
+ }, {
41
+ outputPath: 'src/entry-client.tsx',
42
+ templatePath: 'src/entry-client.tsx.ejs'
43
+ }, {
44
+ outputPath: 'src/entry-server.tsx',
45
+ templatePath: 'src/entry-server.tsx.ejs'
46
+ }, {
47
+ outputPath: 'src/load-manifest.test.ts',
48
+ templatePath: 'src/load-manifest.test.ts.ejs'
49
+ }, {
50
+ outputPath: 'src/load-manifest.ts',
51
+ templatePath: 'src/load-manifest.ts.ejs'
52
+ }, {
53
+ outputPath: 'src/main.ts',
54
+ templatePath: 'src/main.ts.ejs'
55
+ }, {
56
+ outputPath: 'src/page.tsx',
57
+ templatePath: 'src/page.tsx.ejs'
58
+ }, {
59
+ outputPath: 'src/react-app.test.tsx',
60
+ templatePath: 'src/react-app.test.tsx.ejs'
61
+ }, {
62
+ outputPath: 'src/react-app.tsx',
63
+ templatePath: 'src/react-app.tsx.ejs'
64
+ }, {
65
+ outputPath: 'src/styles.css',
66
+ templatePath: 'src/styles.css.ejs'
67
+ }, {
68
+ outputPath: 'src/styles.d.ts',
69
+ templatePath: 'src/styles.d.ts.ejs'
70
+ }, {
71
+ outputPath: 'tests/production-hydration.spec.ts',
72
+ templatePath: 'tests/production-hydration.spec.ts.ejs'
73
+ }];
74
+ function resolveTemplateDirectory(importMetaUrl) {
75
+ return join(dirname(fileURLToPath(importMetaUrl)), 'templates', 'react-vite-ssr');
76
+ }
77
+ function createLifecycleCommands(packageManager) {
78
+ const runPrefix = RUN_PREFIX_BY_PACKAGE_MANAGER[packageManager];
79
+ const run = script => `${runPrefix} ${script}`;
80
+ return {
81
+ build: run('build'),
82
+ dev: run('dev'),
83
+ install: INSTALL_COMMAND_BY_PACKAGE_MANAGER[packageManager],
84
+ start: run('start'),
85
+ test: run('test'),
86
+ testBrowser: run('test:browser'),
87
+ typecheck: run('typecheck')
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Renders the React SSR + Vite starter template tree with explicit lifecycle commands.
93
+ *
94
+ * @param context Validated project and package-manager command values for template rendering.
95
+ * @param importMetaUrl Module URL used to locate packaged starter templates.
96
+ * @returns Generated scaffold files with rendered template content.
97
+ */
98
+ export function createReactViteSsrScaffoldFiles(context, importMetaUrl = import.meta.url) {
99
+ const templateDirectory = resolveTemplateDirectory(importMetaUrl);
100
+ const commands = createLifecycleCommands(context.packageManager);
101
+ return REACT_VITE_SSR_TEMPLATES.map(({
102
+ outputPath,
103
+ templatePath
104
+ }) => ({
105
+ content: readFileSync(join(templateDirectory, templatePath), 'utf8').replaceAll('<%= projectName %>', context.projectName).replaceAll('<%= installCommand %>', commands.install).replaceAll('<%= devCommand %>', commands.dev).replaceAll('<%= buildCommand %>', commands.build).replaceAll('<%= startCommand %>', commands.start).replaceAll('<%= testCommand %>', commands.test).replaceAll('<%= testBrowserCommand %>', commands.testBrowser).replaceAll('<%= typecheckCommand %>', commands.typecheck).replaceAll('<%= devCommandJson %>', JSON.stringify(commands.dev)).replaceAll('<%= startCommandJson %>', JSON.stringify(commands.start)),
106
+ path: outputPath
107
+ }));
108
+ }
@@ -1,6 +1,6 @@
1
- import type { BootstrapOptions, BootstrapSchema } from './types.js';
2
1
  import { type StarterProfile } from './starter-profiles.js';
3
- type BootstrapResolutionInput = Partial<BootstrapSchema> & Pick<Partial<BootstrapOptions>, 'packageManager'>;
2
+ import type { BootstrapOptions, BootstrapSchema } from './types.js';
3
+ type BootstrapResolutionInput = Partial<BootstrapSchema> & Pick<Partial<BootstrapOptions>, 'packageManager' | 'starter'>;
4
4
  /**
5
5
  * Shape-first compatibility baseline for `fluo new` until additional starter variants ship.
6
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/new/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAGhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAYL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAE/B,KAAK,wBAAwB,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,CAAC;AAE7G;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,eAA6C,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;IAC7C,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACnC,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;CACzB;AAyBD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,OAAO,CAAC,eAAe,CAAM,GAAG,eAAe,CAe9F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,GAAG,gBAAgB,GAAG,qBAAqB,CAkFhH"}
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/new/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EAOpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAGhB,MAAM,YAAY,CAAC;AAEpB,KAAK,wBAAwB,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,CAAC;AAEzH;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,eAA6C,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;IAC7C,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACnC,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;CACzB;AAyBD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,OAAO,CAAC,eAAe,CAAM,GAAG,eAAe,CAe9F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,GAAG,gBAAgB,GAAG,qBAAqB,CA0FhH"}
@@ -52,7 +52,8 @@ export function resolveBootstrapSchema(partial = {}) {
52
52
  */
53
53
  export function resolveBootstrapPlan(options) {
54
54
  const schema = resolveBootstrapSchema(options);
55
- const starterProfile = getStarterProfileFromSchema(schema);
55
+ const starter = options.starter ?? 'standard';
56
+ const starterProfile = getStarterProfileFromSchema(schema, starter);
56
57
  if (starterProfile) {
57
58
  return {
58
59
  dependencies: starterProfile.dependencies,
@@ -62,6 +63,9 @@ export function resolveBootstrapPlan(options) {
62
63
  };
63
64
  }
64
65
  const defaultProfile = getStarterProfileForShape(schema.shape);
66
+ if (starter === 'react-vite-ssr') {
67
+ throw new Error(`Unsupported react-vite-ssr starter schema "${schema.shape}/${schema.runtime}/${schema.transport}/${schema.platform}/${schema.tooling}/${schema.topology.mode}". ` + 'The React SSR + Vite starter requires application/node/http/fastify/standard/single-package.');
68
+ }
65
69
  if (schema.shape === 'microservice' && schema.transport === 'http') {
66
70
  throw new Error('Unsupported bootstrap schema "microservice/node/http/' + schema.platform + '/standard/single-package". ' + 'Microservice starters require a transport-aware microservice transport such as tcp, redis-streams, mqtt, grpc, nats, kafka, or rabbitmq.');
67
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/new/scaffold.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,YAAY,CAAC;AA8xEnE;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,gBAAgB,EACzB,aAAa,SAAkB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,6BAAuB,CAAC"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/new/scaffold.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,YAAY,CAAC;AAq5EnE;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,gBAAgB,EACzB,aAAa,SAAkB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,6BAAuB,CAAC"}