@bleedingdev/modern-js-create 3.2.0-ultramodern.12 → 3.2.0-ultramodern.120

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 (75) hide show
  1. package/README.md +146 -74
  2. package/bin/run.js +0 -0
  3. package/dist/cjs/create-package-root.cjs +65 -0
  4. package/dist/cjs/index.cjs +498 -0
  5. package/dist/cjs/locale/en.cjs +94 -0
  6. package/dist/cjs/locale/index.cjs +50 -0
  7. package/dist/cjs/locale/zh.cjs +94 -0
  8. package/dist/cjs/ultramodern-package-source.cjs +135 -0
  9. package/dist/cjs/ultramodern-workspace.cjs +6797 -0
  10. package/dist/esm/create-package-root.js +16 -0
  11. package/dist/esm/index.js +461 -0
  12. package/dist/esm/locale/en.js +56 -0
  13. package/dist/esm/locale/index.js +9 -0
  14. package/dist/esm/locale/zh.js +56 -0
  15. package/dist/esm/ultramodern-package-source.js +63 -0
  16. package/dist/esm/ultramodern-workspace.js +6738 -0
  17. package/dist/esm-node/create-package-root.js +17 -0
  18. package/dist/esm-node/index.js +462 -0
  19. package/dist/esm-node/locale/en.js +57 -0
  20. package/dist/esm-node/locale/index.js +10 -0
  21. package/dist/esm-node/locale/zh.js +57 -0
  22. package/dist/esm-node/ultramodern-package-source.js +64 -0
  23. package/dist/esm-node/ultramodern-workspace.js +6739 -0
  24. package/dist/types/create-package-root.d.ts +1 -0
  25. package/dist/types/locale/en.d.ts +7 -7
  26. package/dist/types/locale/index.d.ts +111 -2
  27. package/dist/types/locale/zh.d.ts +7 -7
  28. package/dist/types/ultramodern-package-source.d.ts +28 -0
  29. package/dist/types/ultramodern-workspace.d.ts +12 -3
  30. package/package.json +33 -15
  31. package/template-workspace/.agents/agent-reference-repos.json +24 -0
  32. package/template-workspace/.agents/skills-lock.json +19 -0
  33. package/template-workspace/.codex/hooks.json +16 -0
  34. package/template-workspace/.github/renovate.json +29 -0
  35. package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +70 -0
  36. package/template-workspace/.gitignore.handlebars +5 -0
  37. package/template-workspace/.mise.toml.handlebars +2 -0
  38. package/template-workspace/AGENTS.md +43 -11
  39. package/template-workspace/README.md.handlebars +116 -11
  40. package/template-workspace/lefthook.yml +24 -0
  41. package/template-workspace/oxfmt.config.ts +1 -0
  42. package/template-workspace/oxlint.config.ts +1 -0
  43. package/template-workspace/pnpm-workspace.yaml +31 -8
  44. package/template-workspace/scripts/bootstrap-agent-skills.mjs +204 -21
  45. package/template-workspace/scripts/setup-agent-reference-repos.mjs +370 -0
  46. package/dist/index.js +0 -2626
  47. package/template/.agents/skills-lock.json +0 -34
  48. package/template/.browserslistrc +0 -4
  49. package/template/.github/workflows/ultramodern-gates.yml.handlebars +0 -30
  50. package/template/.gitignore.handlebars +0 -30
  51. package/template/.nvmrc +0 -2
  52. package/template/AGENTS.md +0 -25
  53. package/template/README.md +0 -79
  54. package/template/api/effect/index.ts.handlebars +0 -23
  55. package/template/api/lambda/hello.ts.handlebars +0 -6
  56. package/template/config/public/locales/cs/translation.json +0 -39
  57. package/template/config/public/locales/en/translation.json +0 -39
  58. package/template/modern.config.ts.handlebars +0 -53
  59. package/template/oxfmt.config.ts +0 -8
  60. package/template/oxlint.config.ts +0 -12
  61. package/template/package.json.handlebars +0 -67
  62. package/template/postcss.config.mjs.handlebars +0 -6
  63. package/template/scripts/bootstrap-agent-skills.mjs +0 -95
  64. package/template/scripts/check-i18n-strings.mjs +0 -83
  65. package/template/scripts/validate-ultramodern.mjs.handlebars +0 -178
  66. package/template/shared/effect/api.ts.handlebars +0 -17
  67. package/template/src/modern-app-env.d.ts +0 -1
  68. package/template/src/modern.runtime.ts.handlebars +0 -23
  69. package/template/src/routes/index.css.handlebars +0 -129
  70. package/template/src/routes/layout.tsx.handlebars +0 -9
  71. package/template/src/routes/page.tsx.handlebars +0 -155
  72. package/template/tailwind.config.ts.handlebars +0 -10
  73. package/template/tsconfig.json +0 -120
  74. package/template-workspace/scripts/check-i18n-strings.mjs +0 -83
  75. package/template-workspace/scripts/validate-ultramodern-workspace.mjs.handlebars +0 -433
@@ -0,0 +1,16 @@
1
+ import node_fs from "node:fs";
2
+ import node_path from "node:path";
3
+ function resolveCreatePackageRoot(fromDir) {
4
+ const candidates = [
5
+ fromDir,
6
+ node_path.resolve(fromDir, '..'),
7
+ node_path.resolve(fromDir, '..', '..')
8
+ ];
9
+ const seen = new Set();
10
+ for (const candidate of candidates)if (!seen.has(candidate)) {
11
+ seen.add(candidate);
12
+ if (node_fs.existsSync(node_path.join(candidate, 'package.json')) && node_fs.existsSync(node_path.join(candidate, 'template-workspace'))) return candidate;
13
+ }
14
+ throw new Error('Unable to resolve create package root');
15
+ }
16
+ export { resolveCreatePackageRoot };
@@ -0,0 +1,461 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import node_fs from "node:fs";
3
+ import node_path from "node:path";
4
+ import node_readline from "node:readline";
5
+ import { fileURLToPath } from "node:url";
6
+ import { resolveCreatePackageRoot } from "./create-package-root.js";
7
+ import { i18n, localeKeys } from "./locale/index.js";
8
+ import { BLEEDINGDEV_CREATE_PACKAGE, BLEEDINGDEV_FRAMEWORK_VERSION_ENV, BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE, WORKSPACE_PACKAGE_VERSION } from "./ultramodern-package-source.js";
9
+ import { addUltramodernVertical, generateUltramodernWorkspace } from "./ultramodern-workspace.js";
10
+ const src_dirname = node_path.dirname(fileURLToPath(import.meta.url));
11
+ const createPackageRoot = resolveCreatePackageRoot(src_dirname);
12
+ const semverPattern = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
13
+ const LEGACY_MODERN_JS_FLAG = '--legacy-modern-js';
14
+ const LEGACY_MODERN_JS_CONFIRMATION = 'USE LEGACY MODERN.JS';
15
+ function getOptionValue(args, names) {
16
+ for (const name of names){
17
+ const prefix = `${name}=`;
18
+ const byEquals = args.find((arg)=>arg.startsWith(prefix));
19
+ if (byEquals) return byEquals.slice(prefix.length);
20
+ const index = args.findIndex((arg)=>arg === name);
21
+ if (-1 !== index && args[index + 1] && !args[index + 1].startsWith('-')) return args[index + 1];
22
+ }
23
+ }
24
+ const detectLanguage = ()=>{
25
+ const lang = getOptionValue(process.argv.slice(2), [
26
+ '--lang',
27
+ '-l'
28
+ ]);
29
+ if ('zh' === lang) return 'zh';
30
+ return 'en';
31
+ };
32
+ i18n.changeLanguage({
33
+ locale: detectLanguage()
34
+ });
35
+ function readCreatePackageJson() {
36
+ const createPackageJson = node_path.join(createPackageRoot, 'package.json');
37
+ return JSON.parse(node_fs.readFileSync(createPackageJson, 'utf-8'));
38
+ }
39
+ function isBleedingDevCreatePackage(createPackage) {
40
+ return createPackage.name === BLEEDINGDEV_CREATE_PACKAGE;
41
+ }
42
+ function getBleedingDevFrameworkVersion(createPackage, fallbackVersion) {
43
+ const frameworkVersion = createPackage.ultramodern?.frameworkVersion;
44
+ return 'string' == typeof frameworkVersion && frameworkVersion.length > 0 ? frameworkVersion : fallbackVersion;
45
+ }
46
+ function showVersion() {
47
+ const createPackage = readCreatePackageJson();
48
+ const version = createPackage.version || 'unknown';
49
+ console.log(i18n.t(localeKeys.version.message, {
50
+ version
51
+ }));
52
+ process.exit(0);
53
+ }
54
+ function showHelp() {
55
+ console.log(i18n.t(localeKeys.help.title));
56
+ console.log(i18n.t(localeKeys.help.description));
57
+ console.log('');
58
+ console.log(i18n.t(localeKeys.help.usage));
59
+ console.log(i18n.t(localeKeys.help.usageExample));
60
+ console.log('');
61
+ console.log(i18n.t(localeKeys.help.options));
62
+ console.log(i18n.t(localeKeys.help.optionHelp));
63
+ console.log(i18n.t(localeKeys.help.optionVersion));
64
+ console.log(i18n.t(localeKeys.help.optionLang));
65
+ if (localeKeys.help.optionTailwind) console.log(i18n.t(localeKeys.help.optionTailwind));
66
+ if (localeKeys.help.optionUltramodernPackageSource) console.log(i18n.t(localeKeys.help.optionUltramodernPackageSource));
67
+ if (localeKeys.help.optionUltramodernPackageScope) console.log(i18n.t(localeKeys.help.optionUltramodernPackageScope));
68
+ if (localeKeys.help.optionUltramodernPackageNamePrefix) console.log(i18n.t(localeKeys.help.optionUltramodernPackageNamePrefix));
69
+ if (localeKeys.help.optionVertical) console.log(i18n.t(localeKeys.help.optionVertical));
70
+ if (localeKeys.help.optionLegacyModernJs) console.log(i18n.t(localeKeys.help.optionLegacyModernJs));
71
+ console.log('');
72
+ console.log(i18n.t(localeKeys.help.examples));
73
+ console.log(i18n.t(localeKeys.help.example1));
74
+ console.log(i18n.t(localeKeys.help.example2));
75
+ if (localeKeys.help.example4) console.log(i18n.t(localeKeys.help.example4));
76
+ if (localeKeys.help.example5) console.log(i18n.t(localeKeys.help.example5));
77
+ if (localeKeys.help.example6) console.log(i18n.t(localeKeys.help.example6));
78
+ if (localeKeys.help.example12) console.log(i18n.t(localeKeys.help.example12));
79
+ console.log('');
80
+ console.log(i18n.t(localeKeys.help.moreInfo));
81
+ console.log('');
82
+ process.exit(0);
83
+ }
84
+ function promptInput(question) {
85
+ const rl = node_readline.createInterface({
86
+ input: process.stdin,
87
+ output: process.stdout
88
+ });
89
+ return new Promise((resolve)=>{
90
+ rl.question(question, (answer)=>{
91
+ rl.close();
92
+ resolve(answer.trim());
93
+ });
94
+ });
95
+ }
96
+ function detectLegacyModernJsFlag(args) {
97
+ if (args.some((arg)=>arg.startsWith(`${LEGACY_MODERN_JS_FLAG}=`))) {
98
+ console.error(`${LEGACY_MODERN_JS_FLAG} does not accept a value.`);
99
+ process.exit(1);
100
+ }
101
+ return args.includes(LEGACY_MODERN_JS_FLAG);
102
+ }
103
+ function stripLegacyModernJsArgs(args) {
104
+ return args.filter((arg)=>arg !== LEGACY_MODERN_JS_FLAG);
105
+ }
106
+ async function confirmLegacyModernJsSetup() {
107
+ console.error('');
108
+ console.error(i18n.t(localeKeys.message.legacyModernJsWarning));
109
+ console.error('');
110
+ const answer = await promptInput(i18n.t(localeKeys.prompt.legacyModernJsConfirmation, {
111
+ confirmation: LEGACY_MODERN_JS_CONFIRMATION
112
+ }));
113
+ if (answer !== LEGACY_MODERN_JS_CONFIRMATION) {
114
+ console.error(i18n.t(localeKeys.error.legacyModernJsNotConfirmed));
115
+ process.exit(1);
116
+ }
117
+ }
118
+ function delegateLegacyModernJsSetup(args) {
119
+ const forwardedArgs = stripLegacyModernJsArgs(args);
120
+ if (commandExists('pnpm')) return void runSetupCommand('pnpm', [
121
+ 'dlx',
122
+ '@modern-js/create',
123
+ ...forwardedArgs
124
+ ], {
125
+ stdio: 'inherit'
126
+ });
127
+ if (commandExists('npx')) return void runSetupCommand('npx', [
128
+ '@modern-js/create',
129
+ ...forwardedArgs
130
+ ], {
131
+ stdio: 'inherit'
132
+ });
133
+ throw new Error('Legacy Modern.js setup requires pnpm or npx to run @modern-js/create.');
134
+ }
135
+ function detectTailwindFlag() {
136
+ const args = process.argv.slice(2);
137
+ return !args.includes('--no-tailwind');
138
+ }
139
+ function detectExplicitTailwindFlag() {
140
+ const args = process.argv.slice(2);
141
+ if (args.includes('--no-tailwind')) return false;
142
+ if (args.includes('--tailwind')) return true;
143
+ }
144
+ function detectVerticalFlag() {
145
+ const args = process.argv.slice(2);
146
+ if (args.some((arg)=>arg.startsWith('--vertical='))) {
147
+ console.error('--vertical does not accept a value. Use: create <name> --vertical');
148
+ process.exit(1);
149
+ }
150
+ return args.includes('--vertical');
151
+ }
152
+ function detectUltramodernPackageSource(args, defaultPackageVersion, createPackage) {
153
+ const bleedingDevDefaults = isBleedingDevCreatePackage(createPackage);
154
+ const strategy = getOptionValue(args, [
155
+ '--ultramodern-package-source'
156
+ ]) ?? (bleedingDevDefaults ? 'install' : 'workspace');
157
+ if ('workspace' !== strategy && 'install' !== strategy) {
158
+ console.error('--ultramodern-package-source must be "workspace" or "install"');
159
+ process.exit(1);
160
+ }
161
+ const packageSourceStrategy = strategy;
162
+ const explicitRegistry = getOptionValue(args, [
163
+ '--ultramodern-package-registry'
164
+ ]);
165
+ const aliasScope = getOptionValue(args, [
166
+ '--ultramodern-package-scope'
167
+ ]) ?? (bleedingDevDefaults && 'install' === packageSourceStrategy && !explicitRegistry ? BLEEDINGDEV_PACKAGE_SCOPE : void 0);
168
+ return {
169
+ strategy: packageSourceStrategy,
170
+ modernPackageVersion: getOptionValue(args, [
171
+ '--ultramodern-package-version'
172
+ ]) ?? defaultPackageVersion,
173
+ registry: explicitRegistry,
174
+ aliasScope,
175
+ aliasPackageNamePrefix: getOptionValue(args, [
176
+ '--ultramodern-package-name-prefix'
177
+ ]) ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
178
+ };
179
+ }
180
+ function hasExplicitUltramodernPackageSource(args, value) {
181
+ const configuredValue = getOptionValue(args, [
182
+ '--ultramodern-package-source'
183
+ ]);
184
+ return value ? configuredValue === value : void 0 !== configuredValue;
185
+ }
186
+ function readBleedingDevFrameworkVersionFromRegistry() {
187
+ const envVersion = process.env[BLEEDINGDEV_FRAMEWORK_VERSION_ENV]?.trim();
188
+ if (envVersion) {
189
+ if (!semverPattern.test(envVersion)) {
190
+ console.error(`${BLEEDINGDEV_FRAMEWORK_VERSION_ENV} must be a valid semver version`);
191
+ process.exit(1);
192
+ }
193
+ return envVersion;
194
+ }
195
+ try {
196
+ const rawVersion = runSetupCommand('npm', [
197
+ 'view',
198
+ `${BLEEDINGDEV_CREATE_PACKAGE}@latest`,
199
+ 'ultramodern.frameworkVersion',
200
+ '--json'
201
+ ]).trim();
202
+ const version = JSON.parse(rawVersion);
203
+ if ('string' == typeof version && semverPattern.test(version)) return version;
204
+ } catch {}
205
+ console.error([
206
+ `Could not resolve ${BLEEDINGDEV_CREATE_PACKAGE}@latest ultramodern.frameworkVersion.`,
207
+ 'Pass --workspace to use local workspace protocol dependencies,',
208
+ 'or pass --ultramodern-package-version with the exact BleedingDev framework cohort.'
209
+ ].join(' '));
210
+ process.exit(1);
211
+ }
212
+ function resolveInstallBackedPackageSource(args, createPackage, packageSource) {
213
+ const explicitVersion = getOptionValue(args, [
214
+ '--ultramodern-package-version'
215
+ ]);
216
+ const explicitRegistry = getOptionValue(args, [
217
+ '--ultramodern-package-registry'
218
+ ]);
219
+ const aliasScope = getOptionValue(args, [
220
+ '--ultramodern-package-scope'
221
+ ]) ?? packageSource.aliasScope ?? (explicitRegistry ? void 0 : BLEEDINGDEV_PACKAGE_SCOPE);
222
+ return {
223
+ ...packageSource,
224
+ strategy: 'install',
225
+ modernPackageVersion: explicitVersion ?? (isBleedingDevCreatePackage(createPackage) ? packageSource.modernPackageVersion : readBleedingDevFrameworkVersionFromRegistry()),
226
+ aliasScope,
227
+ aliasPackageNamePrefix: getOptionValue(args, [
228
+ '--ultramodern-package-name-prefix'
229
+ ]) ?? packageSource.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
230
+ };
231
+ }
232
+ function resolveWorkspacePackageSource(args, createPackage, packageSource) {
233
+ if (hasExplicitUltramodernPackageSource(args, 'workspace')) return {
234
+ ...packageSource,
235
+ strategy: 'workspace',
236
+ modernPackageVersion: WORKSPACE_PACKAGE_VERSION
237
+ };
238
+ return resolveInstallBackedPackageSource(args, createPackage, packageSource);
239
+ }
240
+ function runSetupCommand(command, args, options = {}) {
241
+ return execFileSync(command, args, {
242
+ cwd: options.cwd,
243
+ encoding: 'utf-8',
244
+ stdio: options.stdio ?? [
245
+ 'ignore',
246
+ 'pipe',
247
+ 'pipe'
248
+ ]
249
+ });
250
+ }
251
+ function commandExists(command) {
252
+ try {
253
+ runSetupCommand(command, [
254
+ '--version'
255
+ ], {
256
+ stdio: 'ignore'
257
+ });
258
+ return true;
259
+ } catch {
260
+ return false;
261
+ }
262
+ }
263
+ function installGitForGeneratedProject() {
264
+ if (commandExists('git')) return;
265
+ const runShell = (script)=>runSetupCommand('sh', [
266
+ '-lc',
267
+ script
268
+ ], {
269
+ stdio: 'inherit'
270
+ });
271
+ const sudo = 'function' == typeof process.getuid && 0 === process.getuid() ? '' : 'sudo ';
272
+ if (commandExists('brew')) runSetupCommand('brew', [
273
+ 'install',
274
+ 'git'
275
+ ], {
276
+ stdio: 'inherit'
277
+ });
278
+ else if ('linux' === process.platform && commandExists('apt-get')) runShell(`${sudo}apt-get update && ${sudo}apt-get install -y git`);
279
+ else if ('linux' === process.platform && commandExists('dnf')) runShell(`${sudo}dnf install -y git`);
280
+ else if ('linux' === process.platform && commandExists('yum')) runShell(`${sudo}yum install -y git`);
281
+ else if ('linux' === process.platform && commandExists('apk')) runShell('apk add --no-cache git');
282
+ if (!commandExists('git')) throw new Error('Git is required for UltraModern setup. Install git and rerun create, or run pnpm skills:install after installing git.');
283
+ }
284
+ function isInsideGitWorkTree(targetDir) {
285
+ try {
286
+ return 'true' === runSetupCommand('git', [
287
+ 'rev-parse',
288
+ '--is-inside-work-tree'
289
+ ], {
290
+ cwd: targetDir
291
+ }).trim();
292
+ } catch {
293
+ return false;
294
+ }
295
+ }
296
+ function initializeGeneratedGitRepository(targetDir) {
297
+ installGitForGeneratedProject();
298
+ if (isInsideGitWorkTree(targetDir)) return;
299
+ try {
300
+ runSetupCommand('git', [
301
+ 'init',
302
+ '-b',
303
+ 'main'
304
+ ], {
305
+ cwd: targetDir,
306
+ stdio: 'inherit'
307
+ });
308
+ } catch {
309
+ runSetupCommand('git', [
310
+ 'init'
311
+ ], {
312
+ cwd: targetDir,
313
+ stdio: 'inherit'
314
+ });
315
+ runSetupCommand('git', [
316
+ 'branch',
317
+ '-M',
318
+ 'main'
319
+ ], {
320
+ cwd: targetDir,
321
+ stdio: 'inherit'
322
+ });
323
+ }
324
+ }
325
+ function isDirectoryEmpty(dirPath) {
326
+ if (!node_fs.existsSync(dirPath)) return false;
327
+ try {
328
+ const files = node_fs.readdirSync(dirPath);
329
+ return 0 === files.length;
330
+ } catch {
331
+ return false;
332
+ }
333
+ }
334
+ async function getProjectName() {
335
+ const args = process.argv.slice(2);
336
+ const optionWithValue = new Set([
337
+ '--lang',
338
+ '-l',
339
+ '--ultramodern-package-source',
340
+ '--ultramodern-package-version',
341
+ '--ultramodern-package-registry',
342
+ '--ultramodern-package-scope',
343
+ '--ultramodern-package-name-prefix'
344
+ ]);
345
+ const optionWithoutValue = new Set([
346
+ '--help',
347
+ '-h',
348
+ '--version',
349
+ '-v',
350
+ '--tailwind',
351
+ '--no-tailwind',
352
+ '--workspace',
353
+ '--vertical',
354
+ LEGACY_MODERN_JS_FLAG
355
+ ]);
356
+ const positionalArgs = [];
357
+ for(let i = 0; i < args.length; i++){
358
+ const arg = args[i];
359
+ if (!optionWithoutValue.has(arg)) {
360
+ if (optionWithValue.has(arg)) {
361
+ i += 1;
362
+ continue;
363
+ }
364
+ if (!(arg.startsWith('--lang=') || arg.startsWith('--ultramodern-package-source=') || arg.startsWith('--ultramodern-package-version=') || arg.startsWith('--ultramodern-package-registry=') || arg.startsWith('--ultramodern-package-scope=') || arg.startsWith('--ultramodern-package-name-prefix='))) positionalArgs.push(arg);
365
+ }
366
+ }
367
+ if (positionalArgs.length > 1) {
368
+ console.error(`Unexpected positional argument: ${positionalArgs[1]}`);
369
+ process.exit(1);
370
+ }
371
+ const projectNameArg = positionalArgs[0];
372
+ if (projectNameArg) {
373
+ if ('.' === projectNameArg) return {
374
+ name: node_path.basename(process.cwd()),
375
+ useCurrentDir: true
376
+ };
377
+ return {
378
+ name: projectNameArg,
379
+ useCurrentDir: false
380
+ };
381
+ }
382
+ const currentDir = process.cwd();
383
+ if (isDirectoryEmpty(currentDir)) return {
384
+ name: node_path.basename(currentDir),
385
+ useCurrentDir: true
386
+ };
387
+ const projectName = await promptInput(i18n.t(localeKeys.prompt.projectName));
388
+ if (!projectName) {
389
+ console.error(i18n.t(localeKeys.error.projectNameEmpty));
390
+ process.exit(1);
391
+ }
392
+ return {
393
+ name: projectName,
394
+ useCurrentDir: false
395
+ };
396
+ }
397
+ async function main() {
398
+ const args = process.argv.slice(2);
399
+ if (args.includes('--help') || args.includes('-h')) return void showHelp();
400
+ if (args.includes('--version') || args.includes('-v')) return void showVersion();
401
+ if (detectLegacyModernJsFlag(args)) {
402
+ await confirmLegacyModernJsSetup();
403
+ delegateLegacyModernJsSetup(args);
404
+ return;
405
+ }
406
+ console.log(`\n${i18n.t(localeKeys.message.welcome)}\n`);
407
+ const { name: projectName, useCurrentDir } = await getProjectName();
408
+ const targetDir = useCurrentDir ? process.cwd() : node_path.isAbsolute(projectName) ? projectName : node_path.resolve(process.cwd(), projectName);
409
+ const generatedPackageName = useCurrentDir || node_path.isAbsolute(projectName) ? node_path.basename(targetDir) : projectName;
410
+ const createPackage = readCreatePackageJson();
411
+ const version = createPackage.version || 'latest';
412
+ const ultramodernPackageVersion = isBleedingDevCreatePackage(createPackage) ? getBleedingDevFrameworkVersion(createPackage, version) : version;
413
+ const addVertical = detectVerticalFlag();
414
+ if (addVertical) {
415
+ const overridePackageSource = args.some((arg)=>arg.startsWith('--ultramodern-package-')) ? detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage) : void 0;
416
+ addUltramodernVertical({
417
+ workspaceRoot: process.cwd(),
418
+ name: generatedPackageName,
419
+ modernVersion: version,
420
+ enableTailwind: detectExplicitTailwindFlag(),
421
+ packageSource: overridePackageSource
422
+ });
423
+ const dim = '\x1b[2m\x1b[3m';
424
+ const reset = '\x1b[0m';
425
+ console.log(`${i18n.t(localeKeys.message.success)}\n`);
426
+ console.log(`${dim} pnpm check${reset}\n`);
427
+ return;
428
+ }
429
+ if (node_fs.existsSync(targetDir)) {
430
+ const files = node_fs.readdirSync(targetDir);
431
+ if (files.length > 0) {
432
+ console.error(i18n.t(localeKeys.error.directoryExists, {
433
+ projectName
434
+ }));
435
+ process.exit(1);
436
+ }
437
+ }
438
+ const packageSource = resolveWorkspacePackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage));
439
+ generateUltramodernWorkspace({
440
+ targetDir,
441
+ packageName: generatedPackageName,
442
+ modernVersion: version,
443
+ enableTailwind: detectTailwindFlag(),
444
+ packageSource
445
+ });
446
+ initializeGeneratedGitRepository(targetDir);
447
+ const dim = '\x1b[2m\x1b[3m';
448
+ const reset = '\x1b[0m';
449
+ console.log(`${i18n.t(localeKeys.message.success)}\n`);
450
+ console.log(i18n.t(localeKeys.message.nextSteps));
451
+ if (!useCurrentDir) console.log(`${dim} ${i18n.t(localeKeys.message.step1, {
452
+ projectName
453
+ })}${reset}`);
454
+ console.log(`${dim} ${i18n.t(localeKeys.message.step2)}${reset}`);
455
+ console.log(`${dim} pnpm check${reset}`);
456
+ console.log(`${dim} ${i18n.t(localeKeys.message.step3)}${reset}\n`);
457
+ }
458
+ main().catch((error)=>{
459
+ console.error(i18n.t(localeKeys.error.createFailed), error);
460
+ process.exit(1);
461
+ });
@@ -0,0 +1,56 @@
1
+ const EN_LOCALE = {
2
+ prompt: {
3
+ projectName: 'Please enter project name: ',
4
+ legacyModernJsConfirmation: 'Type "{confirmation}" to continue with the original Modern.js setup: '
5
+ },
6
+ error: {
7
+ projectNameEmpty: 'Error: Project name cannot be empty',
8
+ directoryExists: 'Error: Directory "{projectName}" already exists and is not empty',
9
+ legacyModernJsNotConfirmed: 'Aborted. UltraModern.js remains the default unattended setup.',
10
+ createFailed: 'Error creating project:'
11
+ },
12
+ message: {
13
+ welcome: '🚀 Welcome to UltraModern.js',
14
+ success: '✨ Created successfully!',
15
+ nextSteps: '📋 Next steps:',
16
+ step1: 'cd {projectName}',
17
+ step2: 'pnpm install',
18
+ step3: 'pnpm dev',
19
+ legacyModernJsWarning: "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nBRUTAL WARNING: YOU ARE OPTING OUT OF ULTRAMODERN.JS DEFAULTS.\nThe unattended default is the best UltraModern.js configuration:\na structured SuperApp workspace, presetUltramodern, TanStack Router,\nEffect BFF, Tailwind CSS v4, and the BleedingDev package cohort.\nThe original Modern.js setup is a dangerous opt-in path.\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
20
+ },
21
+ help: {
22
+ title: '🚀 UltraModern.js Project Creator',
23
+ description: 'Create a new UltraModern.js SuperApp workspace with the full quality baseline by default',
24
+ usage: '📖 Usage:',
25
+ usageExample: ' pnpm dlx @bleedingdev/modern-js-create [project-name] [options]',
26
+ options: '⚙️ Options:',
27
+ optionHelp: ' -h, --help Display this help message',
28
+ optionVersion: ' -v, --version Display version information',
29
+ optionLang: ' -l, --lang Set the language (en default; zh opt-in)',
30
+ optionTailwind: ' --no-tailwind Disable default Tailwind CSS v4 workspace styling',
31
+ optionWorkspace: ' --workspace Use workspace protocol for @modern-js dependencies (for local monorepo testing)',
32
+ optionUltramodernPackageSource: ' --ultramodern-package-source Select UltraModern package source (workspace or install; BleedingDev defaults to install aliases)',
33
+ optionUltramodernPackageScope: ' --ultramodern-package-scope Publish scope for npm alias installs (for example bleedingdev)',
34
+ optionUltramodernPackageNamePrefix: ' --ultramodern-package-name-prefix Prefix for npm alias package names (default: modern-js-)',
35
+ optionVertical: ' --vertical Mutate the current existing UltraModern workspace and wire a MicroVertical named <project-name>',
36
+ optionLegacyModernJs: ' --legacy-modern-js Opt into the original Modern.js setup after a large warning and typed confirmation',
37
+ examples: '💡 Examples:',
38
+ example1: ' pnpm dlx @bleedingdev/modern-js-create my-workspace',
39
+ example2: ' pnpm dlx @bleedingdev/modern-js-create my-workspace --lang zh',
40
+ example3: ' pnpm dlx @bleedingdev/modern-js-create my-workspace --no-tailwind',
41
+ example4: ' pnpm dlx @bleedingdev/modern-js-create --help',
42
+ example5: ' pnpm dlx @bleedingdev/modern-js-create .',
43
+ example6: ' pnpm dlx @bleedingdev/modern-js-create my-workspace --workspace',
44
+ example7: '',
45
+ example8: '',
46
+ example9: '',
47
+ example10: '',
48
+ example11: '',
49
+ example12: ' pnpm dlx @bleedingdev/modern-js-create catalog --vertical',
50
+ moreInfo: '📚 Learn more: https://modernjs.dev'
51
+ },
52
+ version: {
53
+ message: '@bleedingdev/modern-js-create version: {version}'
54
+ }
55
+ };
56
+ export { EN_LOCALE };
@@ -0,0 +1,9 @@
1
+ import { I18n } from "@modern-js/i18n-utils";
2
+ import { EN_LOCALE } from "./en.js";
3
+ import { ZH_LOCALE } from "./zh.js";
4
+ const i18n = new I18n();
5
+ const localeKeys = i18n.init('en', {
6
+ zh: ZH_LOCALE,
7
+ en: EN_LOCALE
8
+ });
9
+ export { i18n, localeKeys };
@@ -0,0 +1,56 @@
1
+ const ZH_LOCALE = {
2
+ prompt: {
3
+ projectName: '请输入项目名称: ',
4
+ legacyModernJsConfirmation: '输入 "{confirmation}" 以继续使用原始 Modern.js 初始化: '
5
+ },
6
+ error: {
7
+ projectNameEmpty: '错误: 项目名称不能为空',
8
+ directoryExists: '错误: 目录 "{projectName}" 已存在且不为空',
9
+ legacyModernJsNotConfirmed: '已中止。UltraModern.js 仍是默认的免交互初始化方案。',
10
+ createFailed: '创建项目时出错:'
11
+ },
12
+ message: {
13
+ welcome: '🚀 欢迎使用 UltraModern.js',
14
+ success: '✨ 创建成功!',
15
+ nextSteps: '📋 下一步:',
16
+ step1: 'cd {projectName}',
17
+ step2: 'pnpm install',
18
+ step3: 'pnpm dev',
19
+ legacyModernJsWarning: "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n严重警告:你正在退出 ULTRAMODERN.JS 默认配置。\n免交互默认值是最佳 UltraModern.js 配置:\n结构化 SuperApp 工作区、presetUltramodern、TanStack Router、\nEffect BFF、Tailwind CSS v4,以及 BleedingDev 包版本队列。\n原始 Modern.js 初始化是危险的显式选择路径。\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
20
+ },
21
+ help: {
22
+ title: '🚀 UltraModern.js 项目创建工具',
23
+ description: '默认创建带完整质量基线的 UltraModern.js SuperApp 工作区',
24
+ usage: '📖 用法:',
25
+ usageExample: ' pnpm dlx @bleedingdev/modern-js-create [项目名称] [选项]',
26
+ options: '⚙️ 选项:',
27
+ optionHelp: ' -h, --help 显示帮助信息',
28
+ optionVersion: ' -v, --version 显示版本信息',
29
+ optionLang: ' -l, --lang 设置语言 (默认 en;zh 需显式选择)',
30
+ optionTailwind: ' --no-tailwind 禁用默认 Tailwind CSS v4 工作区样式',
31
+ optionWorkspace: ' --workspace 对 @modern-js 依赖使用 workspace 协议(用于本地 monorepo 联调)',
32
+ optionUltramodernPackageSource: ' --ultramodern-package-source 选择 UltraModern 依赖来源(workspace 或 install;BleedingDev 默认使用 install alias)',
33
+ optionUltramodernPackageScope: ' --ultramodern-package-scope npm alias 安装使用的发布 scope(例如 bleedingdev)',
34
+ optionUltramodernPackageNamePrefix: ' --ultramodern-package-name-prefix npm alias 包名前缀(默认:modern-js-)',
35
+ optionVertical: ' --vertical 修改当前已有的 UltraModern 工作区,并接入名为 <项目名称> 的 MicroVertical',
36
+ optionLegacyModernJs: ' --legacy-modern-js 在大型警告和输入确认后,选择原始 Modern.js 初始化',
37
+ examples: '💡 示例:',
38
+ example1: ' pnpm dlx @bleedingdev/modern-js-create my-workspace',
39
+ example2: ' pnpm dlx @bleedingdev/modern-js-create my-workspace --lang zh',
40
+ example3: ' pnpm dlx @bleedingdev/modern-js-create my-workspace --no-tailwind',
41
+ example4: ' pnpm dlx @bleedingdev/modern-js-create --help',
42
+ example5: ' pnpm dlx @bleedingdev/modern-js-create .',
43
+ example6: ' pnpm dlx @bleedingdev/modern-js-create my-workspace --workspace',
44
+ example7: '',
45
+ example8: '',
46
+ example9: '',
47
+ example10: '',
48
+ example11: '',
49
+ example12: ' pnpm dlx @bleedingdev/modern-js-create catalog --vertical',
50
+ moreInfo: '📚 更多信息: https://modernjs.dev'
51
+ },
52
+ version: {
53
+ message: '@bleedingdev/modern-js-create 版本: {version}'
54
+ }
55
+ };
56
+ export { ZH_LOCALE };
@@ -0,0 +1,63 @@
1
+ const WORKSPACE_PACKAGE_VERSION = 'workspace:*';
2
+ const BLEEDINGDEV_CREATE_PACKAGE = '@bleedingdev/modern-js-create';
3
+ const BLEEDINGDEV_PACKAGE_SCOPE = 'bleedingdev';
4
+ const BLEEDINGDEV_PACKAGE_NAME_PREFIX = 'modern-js-';
5
+ const BLEEDINGDEV_FRAMEWORK_VERSION_ENV = 'MODERN_CREATE_ULTRAMODERN_FRAMEWORK_VERSION';
6
+ const ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES = [
7
+ '@modern-js/create',
8
+ '@modern-js/code-tools',
9
+ '@modern-js/runtime',
10
+ '@modern-js/app-tools',
11
+ '@modern-js/tsconfig',
12
+ '@modern-js/plugin-i18n',
13
+ '@modern-js/plugin-tanstack',
14
+ '@modern-js/plugin-bff',
15
+ '@modern-js/adapter-rstest'
16
+ ];
17
+ const ULTRAMODERN_WORKSPACE_MODERN_PACKAGES = [
18
+ '@modern-js/create',
19
+ '@modern-js/code-tools',
20
+ '@modern-js/app-tools',
21
+ '@modern-js/plugin-bff',
22
+ '@modern-js/plugin-i18n',
23
+ '@modern-js/plugin-tanstack',
24
+ '@modern-js/runtime'
25
+ ];
26
+ function modernPackageVersion(packageSource) {
27
+ return 'install' === packageSource.strategy ? packageSource.modernPackageVersion : WORKSPACE_PACKAGE_VERSION;
28
+ }
29
+ function modernAliasPackageName(packageName, packageSource) {
30
+ if (!packageSource.aliasScope) return packageName;
31
+ const scope = packageSource.aliasScope.replace(/^@/, '');
32
+ const unscopedName = packageName.split('/').at(-1);
33
+ return `@${scope}/${packageSource.aliasPackageNamePrefix ?? ''}${unscopedName}`;
34
+ }
35
+ function modernPackageSpecifier(packageName, packageSource) {
36
+ if ('install' !== packageSource.strategy) return WORKSPACE_PACKAGE_VERSION;
37
+ if (!packageSource.aliasScope) return packageSource.modernPackageVersion;
38
+ return `npm:${modernAliasPackageName(packageName, packageSource)}@${packageSource.modernPackageVersion}`;
39
+ }
40
+ function modernPackageAliases(packageNames, packageSource) {
41
+ if (!packageSource.aliasScope) return;
42
+ return Object.fromEntries(packageNames.map((packageName)=>[
43
+ packageName,
44
+ modernAliasPackageName(packageName, packageSource)
45
+ ]));
46
+ }
47
+ function createModernPackagesMetadata(packageNames, packageSource, options = {}) {
48
+ const includeAliases = options.includeAliases ?? Boolean(packageSource.aliasScope);
49
+ const aliases = includeAliases ? modernPackageAliases(packageNames, packageSource) : void 0;
50
+ return {
51
+ packages: [
52
+ ...packageNames
53
+ ],
54
+ specifier: modernPackageVersion(packageSource),
55
+ ...packageSource.registry ? {
56
+ registry: packageSource.registry
57
+ } : {},
58
+ ...aliases ? {
59
+ aliases
60
+ } : {}
61
+ };
62
+ }
63
+ export { BLEEDINGDEV_CREATE_PACKAGE, BLEEDINGDEV_FRAMEWORK_VERSION_ENV, BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE, ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, ULTRAMODERN_WORKSPACE_MODERN_PACKAGES, WORKSPACE_PACKAGE_VERSION, createModernPackagesMetadata, modernAliasPackageName, modernPackageAliases, modernPackageSpecifier, modernPackageVersion };