@tanstack/cli 0.0.8 → 0.48.3

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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin.js +7 -0
  3. package/dist/cli.js +481 -0
  4. package/dist/command-line.js +174 -0
  5. package/dist/dev-watch.js +290 -0
  6. package/dist/file-syncer.js +148 -0
  7. package/dist/index.js +1 -0
  8. package/dist/mcp/api.js +31 -0
  9. package/dist/mcp/tools.js +250 -0
  10. package/dist/mcp/types.js +37 -0
  11. package/dist/mcp.js +121 -0
  12. package/dist/options.js +162 -0
  13. package/dist/types/bin.d.ts +2 -0
  14. package/dist/types/cli.d.ts +16 -0
  15. package/dist/types/command-line.d.ts +10 -0
  16. package/dist/types/dev-watch.d.ts +27 -0
  17. package/dist/types/file-syncer.d.ts +18 -0
  18. package/dist/types/index.d.ts +1 -0
  19. package/dist/types/mcp/api.d.ts +4 -0
  20. package/dist/types/mcp/tools.d.ts +2 -0
  21. package/dist/types/mcp/types.d.ts +217 -0
  22. package/dist/types/mcp.d.ts +6 -0
  23. package/dist/types/options.d.ts +8 -0
  24. package/dist/types/types.d.ts +25 -0
  25. package/dist/types/ui-environment.d.ts +2 -0
  26. package/dist/types/ui-prompts.d.ts +12 -0
  27. package/dist/types/utils.d.ts +8 -0
  28. package/dist/types.js +1 -0
  29. package/dist/ui-environment.js +52 -0
  30. package/dist/ui-prompts.js +244 -0
  31. package/dist/utils.js +30 -0
  32. package/package.json +46 -47
  33. package/src/bin.ts +6 -93
  34. package/src/cli.ts +692 -0
  35. package/src/command-line.ts +236 -0
  36. package/src/dev-watch.ts +430 -0
  37. package/src/file-syncer.ts +205 -0
  38. package/src/index.ts +1 -85
  39. package/src/mcp.ts +190 -0
  40. package/src/options.ts +260 -0
  41. package/src/types.ts +27 -0
  42. package/src/ui-environment.ts +74 -0
  43. package/src/ui-prompts.ts +322 -0
  44. package/src/utils.ts +38 -0
  45. package/tests/command-line.test.ts +304 -0
  46. package/tests/index.test.ts +9 -0
  47. package/tests/mcp.test.ts +225 -0
  48. package/tests/options.test.ts +304 -0
  49. package/tests/setupVitest.ts +6 -0
  50. package/tests/ui-environment.test.ts +97 -0
  51. package/tests/ui-prompts.test.ts +238 -0
  52. package/tsconfig.json +17 -0
  53. package/vitest.config.js +7 -0
  54. package/dist/bin.cjs +0 -769
  55. package/dist/bin.d.cts +0 -1
  56. package/dist/bin.d.mts +0 -1
  57. package/dist/bin.mjs +0 -768
  58. package/dist/fetch-CbFFGJEw.cjs +0 -3
  59. package/dist/fetch-DG5dLrsb.cjs +0 -522
  60. package/dist/fetch-DhlVXS6S.mjs +0 -390
  61. package/dist/fetch-I_OVg8JX.mjs +0 -3
  62. package/dist/index.cjs +0 -37
  63. package/dist/index.d.cts +0 -1172
  64. package/dist/index.d.mts +0 -1172
  65. package/dist/index.mjs +0 -4
  66. package/dist/template-Szi7-AZJ.mjs +0 -2202
  67. package/dist/template-lWrIZhCQ.cjs +0 -2314
  68. package/src/api/fetch.test.ts +0 -114
  69. package/src/api/fetch.ts +0 -278
  70. package/src/cache/index.ts +0 -89
  71. package/src/commands/create.ts +0 -470
  72. package/src/commands/mcp.test.ts +0 -152
  73. package/src/commands/mcp.ts +0 -211
  74. package/src/engine/compile-with-addons.test.ts +0 -302
  75. package/src/engine/compile.test.ts +0 -404
  76. package/src/engine/compile.ts +0 -569
  77. package/src/engine/config-file.test.ts +0 -118
  78. package/src/engine/config-file.ts +0 -61
  79. package/src/engine/custom-addons/integration.ts +0 -323
  80. package/src/engine/custom-addons/shared.test.ts +0 -98
  81. package/src/engine/custom-addons/shared.ts +0 -281
  82. package/src/engine/custom-addons/template.test.ts +0 -288
  83. package/src/engine/custom-addons/template.ts +0 -124
  84. package/src/engine/template.test.ts +0 -256
  85. package/src/engine/template.ts +0 -269
  86. package/src/engine/types.ts +0 -336
  87. package/src/parse-gitignore.d.ts +0 -5
  88. package/src/templates/base.ts +0 -883
@@ -0,0 +1,217 @@
1
+ import { z } from 'zod';
2
+ export declare const LibrarySchema: z.ZodObject<{
3
+ id: z.ZodString;
4
+ name: z.ZodString;
5
+ tagline: z.ZodString;
6
+ description: z.ZodOptional<z.ZodString>;
7
+ frameworks: z.ZodArray<z.ZodString, "many">;
8
+ latestVersion: z.ZodString;
9
+ latestBranch: z.ZodOptional<z.ZodString>;
10
+ availableVersions: z.ZodArray<z.ZodString, "many">;
11
+ repo: z.ZodString;
12
+ docsRoot: z.ZodOptional<z.ZodString>;
13
+ defaultDocs: z.ZodOptional<z.ZodString>;
14
+ docsUrl: z.ZodOptional<z.ZodString>;
15
+ githubUrl: z.ZodOptional<z.ZodString>;
16
+ }, "strip", z.ZodTypeAny, {
17
+ id: string;
18
+ name: string;
19
+ tagline: string;
20
+ frameworks: string[];
21
+ latestVersion: string;
22
+ availableVersions: string[];
23
+ repo: string;
24
+ description?: string | undefined;
25
+ latestBranch?: string | undefined;
26
+ docsRoot?: string | undefined;
27
+ defaultDocs?: string | undefined;
28
+ docsUrl?: string | undefined;
29
+ githubUrl?: string | undefined;
30
+ }, {
31
+ id: string;
32
+ name: string;
33
+ tagline: string;
34
+ frameworks: string[];
35
+ latestVersion: string;
36
+ availableVersions: string[];
37
+ repo: string;
38
+ description?: string | undefined;
39
+ latestBranch?: string | undefined;
40
+ docsRoot?: string | undefined;
41
+ defaultDocs?: string | undefined;
42
+ docsUrl?: string | undefined;
43
+ githubUrl?: string | undefined;
44
+ }>;
45
+ export declare const LibrariesResponseSchema: z.ZodObject<{
46
+ libraries: z.ZodArray<z.ZodObject<{
47
+ id: z.ZodString;
48
+ name: z.ZodString;
49
+ tagline: z.ZodString;
50
+ description: z.ZodOptional<z.ZodString>;
51
+ frameworks: z.ZodArray<z.ZodString, "many">;
52
+ latestVersion: z.ZodString;
53
+ latestBranch: z.ZodOptional<z.ZodString>;
54
+ availableVersions: z.ZodArray<z.ZodString, "many">;
55
+ repo: z.ZodString;
56
+ docsRoot: z.ZodOptional<z.ZodString>;
57
+ defaultDocs: z.ZodOptional<z.ZodString>;
58
+ docsUrl: z.ZodOptional<z.ZodString>;
59
+ githubUrl: z.ZodOptional<z.ZodString>;
60
+ }, "strip", z.ZodTypeAny, {
61
+ id: string;
62
+ name: string;
63
+ tagline: string;
64
+ frameworks: string[];
65
+ latestVersion: string;
66
+ availableVersions: string[];
67
+ repo: string;
68
+ description?: string | undefined;
69
+ latestBranch?: string | undefined;
70
+ docsRoot?: string | undefined;
71
+ defaultDocs?: string | undefined;
72
+ docsUrl?: string | undefined;
73
+ githubUrl?: string | undefined;
74
+ }, {
75
+ id: string;
76
+ name: string;
77
+ tagline: string;
78
+ frameworks: string[];
79
+ latestVersion: string;
80
+ availableVersions: string[];
81
+ repo: string;
82
+ description?: string | undefined;
83
+ latestBranch?: string | undefined;
84
+ docsRoot?: string | undefined;
85
+ defaultDocs?: string | undefined;
86
+ docsUrl?: string | undefined;
87
+ githubUrl?: string | undefined;
88
+ }>, "many">;
89
+ groups: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>;
90
+ groupNames: z.ZodRecord<z.ZodString, z.ZodString>;
91
+ }, "strip", z.ZodTypeAny, {
92
+ libraries: {
93
+ id: string;
94
+ name: string;
95
+ tagline: string;
96
+ frameworks: string[];
97
+ latestVersion: string;
98
+ availableVersions: string[];
99
+ repo: string;
100
+ description?: string | undefined;
101
+ latestBranch?: string | undefined;
102
+ docsRoot?: string | undefined;
103
+ defaultDocs?: string | undefined;
104
+ docsUrl?: string | undefined;
105
+ githubUrl?: string | undefined;
106
+ }[];
107
+ groups: Record<string, string[]>;
108
+ groupNames: Record<string, string>;
109
+ }, {
110
+ libraries: {
111
+ id: string;
112
+ name: string;
113
+ tagline: string;
114
+ frameworks: string[];
115
+ latestVersion: string;
116
+ availableVersions: string[];
117
+ repo: string;
118
+ description?: string | undefined;
119
+ latestBranch?: string | undefined;
120
+ docsRoot?: string | undefined;
121
+ defaultDocs?: string | undefined;
122
+ docsUrl?: string | undefined;
123
+ githubUrl?: string | undefined;
124
+ }[];
125
+ groups: Record<string, string[]>;
126
+ groupNames: Record<string, string>;
127
+ }>;
128
+ export declare const PartnerSchema: z.ZodObject<{
129
+ id: z.ZodString;
130
+ name: z.ZodString;
131
+ tagline: z.ZodOptional<z.ZodString>;
132
+ description: z.ZodString;
133
+ category: z.ZodString;
134
+ categoryLabel: z.ZodString;
135
+ libraries: z.ZodArray<z.ZodString, "many">;
136
+ url: z.ZodString;
137
+ }, "strip", z.ZodTypeAny, {
138
+ id: string;
139
+ name: string;
140
+ description: string;
141
+ libraries: string[];
142
+ category: string;
143
+ categoryLabel: string;
144
+ url: string;
145
+ tagline?: string | undefined;
146
+ }, {
147
+ id: string;
148
+ name: string;
149
+ description: string;
150
+ libraries: string[];
151
+ category: string;
152
+ categoryLabel: string;
153
+ url: string;
154
+ tagline?: string | undefined;
155
+ }>;
156
+ export declare const PartnersResponseSchema: z.ZodObject<{
157
+ partners: z.ZodArray<z.ZodObject<{
158
+ id: z.ZodString;
159
+ name: z.ZodString;
160
+ tagline: z.ZodOptional<z.ZodString>;
161
+ description: z.ZodString;
162
+ category: z.ZodString;
163
+ categoryLabel: z.ZodString;
164
+ libraries: z.ZodArray<z.ZodString, "many">;
165
+ url: z.ZodString;
166
+ }, "strip", z.ZodTypeAny, {
167
+ id: string;
168
+ name: string;
169
+ description: string;
170
+ libraries: string[];
171
+ category: string;
172
+ categoryLabel: string;
173
+ url: string;
174
+ tagline?: string | undefined;
175
+ }, {
176
+ id: string;
177
+ name: string;
178
+ description: string;
179
+ libraries: string[];
180
+ category: string;
181
+ categoryLabel: string;
182
+ url: string;
183
+ tagline?: string | undefined;
184
+ }>, "many">;
185
+ categories: z.ZodArray<z.ZodString, "many">;
186
+ categoryLabels: z.ZodRecord<z.ZodString, z.ZodString>;
187
+ }, "strip", z.ZodTypeAny, {
188
+ partners: {
189
+ id: string;
190
+ name: string;
191
+ description: string;
192
+ libraries: string[];
193
+ category: string;
194
+ categoryLabel: string;
195
+ url: string;
196
+ tagline?: string | undefined;
197
+ }[];
198
+ categories: string[];
199
+ categoryLabels: Record<string, string>;
200
+ }, {
201
+ partners: {
202
+ id: string;
203
+ name: string;
204
+ description: string;
205
+ libraries: string[];
206
+ category: string;
207
+ categoryLabel: string;
208
+ url: string;
209
+ tagline?: string | undefined;
210
+ }[];
211
+ categories: string[];
212
+ categoryLabels: Record<string, string>;
213
+ }>;
214
+ export type Library = z.infer<typeof LibrarySchema>;
215
+ export type LibrariesResponse = z.infer<typeof LibrariesResponseSchema>;
216
+ export type Partner = z.infer<typeof PartnerSchema>;
217
+ export type PartnersResponse = z.infer<typeof PartnersResponseSchema>;
@@ -0,0 +1,6 @@
1
+ export declare function runMCPServer(sse: boolean, { forcedAddOns, appName, name, }: {
2
+ forcedMode?: string;
3
+ forcedAddOns?: Array<string>;
4
+ appName?: string;
5
+ name?: string;
6
+ }): Promise<void>;
@@ -0,0 +1,8 @@
1
+ import type { Options } from '@tanstack/create';
2
+ import type { CliOptions } from './types.js';
3
+ export declare function promptForCreateOptions(cliOptions: CliOptions, { forcedAddOns, forcedMode, showDeploymentOptions, }: {
4
+ forcedAddOns?: Array<string>;
5
+ forcedMode?: string;
6
+ showDeploymentOptions?: boolean;
7
+ }): Promise<Required<Options> | undefined>;
8
+ export declare function promptForAddOns(): Promise<Array<string>>;
@@ -0,0 +1,25 @@
1
+ import type { PackageManager } from '@tanstack/create';
2
+ export type TemplateOptions = 'typescript' | 'javascript' | 'file-router';
3
+ export interface CliOptions {
4
+ template?: TemplateOptions;
5
+ framework?: string;
6
+ tailwind?: boolean;
7
+ packageManager?: PackageManager;
8
+ toolchain?: string | false;
9
+ deployment?: string;
10
+ projectName?: string;
11
+ git?: boolean;
12
+ addOns?: Array<string> | boolean;
13
+ listAddOns?: boolean;
14
+ addonDetails?: string;
15
+ mcp?: boolean;
16
+ mcpSse?: boolean;
17
+ starter?: string;
18
+ targetDir?: string;
19
+ interactive?: boolean;
20
+ ui?: boolean;
21
+ devWatch?: string;
22
+ install?: boolean;
23
+ addOnConfig?: string;
24
+ force?: boolean;
25
+ }
@@ -0,0 +1,2 @@
1
+ import type { Environment } from '@tanstack/create';
2
+ export declare function createUIEnvironment(appName: string, silent: boolean): Environment;
@@ -0,0 +1,12 @@
1
+ import type { PackageManager } from '@tanstack/create';
2
+ import type { Framework } from '@tanstack/create/dist/types/types.js';
3
+ export declare function getProjectName(): Promise<string>;
4
+ export declare function selectRouterType(): Promise<string>;
5
+ export declare function selectTypescript(): Promise<boolean>;
6
+ export declare function selectTailwind(): Promise<boolean>;
7
+ export declare function selectPackageManager(): Promise<PackageManager>;
8
+ export declare function selectAddOns(framework: Framework, mode: string, type: string, message: string, forcedAddOns?: Array<string>, allowMultiple?: boolean): Promise<Array<string>>;
9
+ export declare function selectGit(): Promise<boolean>;
10
+ export declare function selectToolchain(framework: Framework, toolchain?: string | false): Promise<string | undefined>;
11
+ export declare function promptForAddOnOptions(addOnIds: Array<string>, framework: Framework): Promise<Record<string, Record<string, any>>>;
12
+ export declare function selectDeployment(framework: Framework, deployment?: string): Promise<string | undefined>;
@@ -0,0 +1,8 @@
1
+ import type { TemplateOptions } from './types.js';
2
+ export declare function convertTemplateToMode(template: TemplateOptions): string;
3
+ export declare function sanitizePackageName(name: string): string;
4
+ export declare function getCurrentDirectoryName(): string;
5
+ export declare function validateProjectName(name: string): {
6
+ valid: boolean;
7
+ error: string;
8
+ };
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ import { cancel, confirm, intro, isCancel, log, outro, spinner, } from '@clack/prompts';
2
+ import chalk from 'chalk';
3
+ import { createDefaultEnvironment } from '@tanstack/create';
4
+ export function createUIEnvironment(appName, silent) {
5
+ const defaultEnvironment = createDefaultEnvironment();
6
+ let newEnvironment = {
7
+ ...defaultEnvironment,
8
+ appName,
9
+ };
10
+ if (!silent) {
11
+ newEnvironment = {
12
+ ...newEnvironment,
13
+ intro: (message) => {
14
+ intro(message);
15
+ },
16
+ outro: (message) => {
17
+ outro(message);
18
+ },
19
+ info: (title, message) => {
20
+ log.info(`${title ? chalk.red(title) : ''}${message ? '\n' + chalk.green(message) : ''}`);
21
+ },
22
+ error: (title, message) => {
23
+ log.error(`${title ? `${title}: ` : ''}${message ? '\n' + message : ''}`);
24
+ },
25
+ warn: (title, message) => {
26
+ log.warn(`${title ? `${title}: ` : ''}${message ? '\n' + message : ''}`);
27
+ },
28
+ confirm: async (message) => {
29
+ const shouldContinue = await confirm({
30
+ message,
31
+ });
32
+ if (isCancel(shouldContinue)) {
33
+ cancel('Operation cancelled.');
34
+ process.exit(0);
35
+ }
36
+ return shouldContinue;
37
+ },
38
+ spinner: () => {
39
+ const s = spinner();
40
+ return {
41
+ start: (message) => {
42
+ s.start(message);
43
+ },
44
+ stop: (message) => {
45
+ s.stop(message);
46
+ },
47
+ };
48
+ },
49
+ };
50
+ }
51
+ return newEnvironment;
52
+ }
@@ -0,0 +1,244 @@
1
+ import { cancel, confirm, isCancel, multiselect, note, select, text, } from '@clack/prompts';
2
+ import { DEFAULT_PACKAGE_MANAGER, SUPPORTED_PACKAGE_MANAGERS, getAllAddOns, } from '@tanstack/create';
3
+ import { validateProjectName } from './utils.js';
4
+ export async function getProjectName() {
5
+ const value = await text({
6
+ message: 'What would you like to name your project?',
7
+ defaultValue: 'my-app',
8
+ validate(value) {
9
+ if (!value) {
10
+ return 'Please enter a name';
11
+ }
12
+ const { valid, error } = validateProjectName(value);
13
+ if (!valid) {
14
+ return error;
15
+ }
16
+ },
17
+ });
18
+ if (isCancel(value)) {
19
+ cancel('Operation cancelled.');
20
+ process.exit(0);
21
+ }
22
+ return value;
23
+ }
24
+ export async function selectRouterType() {
25
+ const routerType = await select({
26
+ message: 'Select the router type:',
27
+ options: [
28
+ {
29
+ value: 'file-router',
30
+ label: 'File Router - File-based routing structure',
31
+ },
32
+ {
33
+ value: 'code-router',
34
+ label: 'Code Router - Traditional code-based routing',
35
+ },
36
+ ],
37
+ initialValue: 'file-router',
38
+ });
39
+ if (isCancel(routerType)) {
40
+ cancel('Operation cancelled.');
41
+ process.exit(0);
42
+ }
43
+ return routerType;
44
+ }
45
+ export async function selectTypescript() {
46
+ const typescriptEnable = await confirm({
47
+ message: 'Would you like to use TypeScript?',
48
+ initialValue: true,
49
+ });
50
+ if (isCancel(typescriptEnable)) {
51
+ cancel('Operation cancelled.');
52
+ process.exit(0);
53
+ }
54
+ return typescriptEnable;
55
+ }
56
+ export async function selectTailwind() {
57
+ const tailwind = await confirm({
58
+ message: 'Would you like to use Tailwind CSS?',
59
+ initialValue: true,
60
+ });
61
+ if (isCancel(tailwind)) {
62
+ cancel('Operation cancelled.');
63
+ process.exit(0);
64
+ }
65
+ return tailwind;
66
+ }
67
+ export async function selectPackageManager() {
68
+ const packageManager = await select({
69
+ message: 'Select package manager:',
70
+ options: SUPPORTED_PACKAGE_MANAGERS.map((pm) => ({
71
+ value: pm,
72
+ label: pm,
73
+ })),
74
+ initialValue: DEFAULT_PACKAGE_MANAGER,
75
+ });
76
+ if (isCancel(packageManager)) {
77
+ cancel('Operation cancelled.');
78
+ process.exit(0);
79
+ }
80
+ return packageManager;
81
+ }
82
+ // Track if we've shown the multiselect help text
83
+ let hasShownMultiselectHelp = false;
84
+ export async function selectAddOns(framework, mode, type, message, forcedAddOns = [], allowMultiple = true) {
85
+ const allAddOns = await getAllAddOns(framework, mode);
86
+ const addOns = allAddOns.filter((addOn) => addOn.type === type);
87
+ if (addOns.length === 0) {
88
+ return [];
89
+ }
90
+ // Show help text only once
91
+ if (!hasShownMultiselectHelp) {
92
+ note('Use ↑/↓ to navigate • Space to select/deselect • Enter to confirm', 'Keyboard Shortcuts');
93
+ hasShownMultiselectHelp = true;
94
+ }
95
+ if (allowMultiple) {
96
+ const value = await multiselect({
97
+ message,
98
+ options: addOns
99
+ .filter((addOn) => !forcedAddOns.includes(addOn.id))
100
+ .map((addOn) => ({
101
+ value: addOn.id,
102
+ label: addOn.name,
103
+ hint: addOn.description,
104
+ })),
105
+ required: false,
106
+ });
107
+ if (isCancel(value)) {
108
+ cancel('Operation cancelled.');
109
+ process.exit(0);
110
+ }
111
+ return value;
112
+ }
113
+ else {
114
+ const value = await select({
115
+ message,
116
+ options: [
117
+ {
118
+ value: 'none',
119
+ label: 'None',
120
+ },
121
+ ...addOns
122
+ .filter((addOn) => !forcedAddOns.includes(addOn.id))
123
+ .map((addOn) => ({
124
+ value: addOn.id,
125
+ label: addOn.name,
126
+ hint: addOn.description,
127
+ })),
128
+ ],
129
+ initialValue: 'none',
130
+ });
131
+ if (isCancel(value)) {
132
+ cancel('Operation cancelled.');
133
+ process.exit(0);
134
+ }
135
+ return value === 'none' ? [] : [value];
136
+ }
137
+ }
138
+ export async function selectGit() {
139
+ const git = await confirm({
140
+ message: 'Would you like to initialize a new git repository?',
141
+ initialValue: true,
142
+ });
143
+ if (isCancel(git)) {
144
+ cancel('Operation cancelled.');
145
+ process.exit(0);
146
+ }
147
+ return git;
148
+ }
149
+ export async function selectToolchain(framework, toolchain) {
150
+ if (toolchain === false) {
151
+ return undefined;
152
+ }
153
+ const toolchains = new Set();
154
+ for (const addOn of framework.getAddOns()) {
155
+ if (addOn.type === 'toolchain') {
156
+ toolchains.add(addOn);
157
+ if (toolchain && addOn.id === toolchain) {
158
+ return toolchain;
159
+ }
160
+ }
161
+ }
162
+ const tc = await select({
163
+ message: 'Select toolchain',
164
+ options: [
165
+ {
166
+ value: undefined,
167
+ label: 'None',
168
+ },
169
+ ...Array.from(toolchains).map((tc) => ({
170
+ value: tc.id,
171
+ label: tc.name,
172
+ })),
173
+ ],
174
+ initialValue: undefined,
175
+ });
176
+ if (isCancel(tc)) {
177
+ cancel('Operation cancelled.');
178
+ process.exit(0);
179
+ }
180
+ return tc;
181
+ }
182
+ export async function promptForAddOnOptions(addOnIds, framework) {
183
+ const addOnOptions = {};
184
+ for (const addOnId of addOnIds) {
185
+ const addOn = framework.getAddOns().find((a) => a.id === addOnId);
186
+ if (!addOn || !addOn.options)
187
+ continue;
188
+ addOnOptions[addOnId] = {};
189
+ for (const [optionName, option] of Object.entries(addOn.options)) {
190
+ if (option && typeof option === 'object' && 'type' in option) {
191
+ if (option.type === 'select') {
192
+ const selectOption = option;
193
+ const value = await select({
194
+ message: `${addOn.name}: ${selectOption.label}`,
195
+ options: selectOption.options.map((opt) => ({
196
+ value: opt.value,
197
+ label: opt.label,
198
+ })),
199
+ initialValue: selectOption.default,
200
+ });
201
+ if (isCancel(value)) {
202
+ cancel('Operation cancelled.');
203
+ process.exit(0);
204
+ }
205
+ addOnOptions[addOnId][optionName] = value;
206
+ }
207
+ // Future option types can be added here
208
+ }
209
+ }
210
+ }
211
+ return addOnOptions;
212
+ }
213
+ export async function selectDeployment(framework, deployment) {
214
+ const deployments = new Set();
215
+ let initialValue = undefined;
216
+ for (const addOn of framework
217
+ .getAddOns()
218
+ .sort((a, b) => a.name.localeCompare(b.name))) {
219
+ if (addOn.type === 'deployment') {
220
+ deployments.add(addOn);
221
+ if (deployment && addOn.id === deployment) {
222
+ return deployment;
223
+ }
224
+ if (addOn.default) {
225
+ initialValue = addOn.id;
226
+ }
227
+ }
228
+ }
229
+ const dp = await select({
230
+ message: 'Select deployment adapter',
231
+ options: [
232
+ ...Array.from(deployments).map((d) => ({
233
+ value: d.id,
234
+ label: d.name,
235
+ })),
236
+ ],
237
+ initialValue: initialValue,
238
+ });
239
+ if (isCancel(dp)) {
240
+ cancel('Operation cancelled.');
241
+ process.exit(0);
242
+ }
243
+ return dp;
244
+ }
package/dist/utils.js ADDED
@@ -0,0 +1,30 @@
1
+ import { basename } from 'node:path';
2
+ import validatePackageName from 'validate-npm-package-name';
3
+ export function convertTemplateToMode(template) {
4
+ if (template === 'typescript' || template === 'javascript') {
5
+ return 'code-router';
6
+ }
7
+ return 'file-router';
8
+ }
9
+ export function sanitizePackageName(name) {
10
+ return name
11
+ .toLowerCase()
12
+ .replace(/\s+/g, '-') // Replace spaces with hyphens
13
+ .replace(/_/g, '-') // Replace underscores with hyphens
14
+ .replace(/[^a-z0-9-]/g, '') // Remove invalid characters
15
+ .replace(/^[^a-z]+/, '') // Ensure it starts with a letter
16
+ .replace(/-+/g, '-') // Collapse multiple hyphens
17
+ .replace(/-$/, ''); // Remove trailing hyphen
18
+ }
19
+ export function getCurrentDirectoryName() {
20
+ return basename(process.cwd());
21
+ }
22
+ export function validateProjectName(name) {
23
+ const { validForNewPackages, validForOldPackages, errors, warnings } = validatePackageName(name);
24
+ const error = errors?.[0] || warnings?.[0];
25
+ return {
26
+ valid: validForNewPackages && validForOldPackages,
27
+ error: error?.replace(/name/g, 'Project name') ||
28
+ 'Project name does not meet npm package naming requirements',
29
+ };
30
+ }