@bleedingdev/modern-js-create 3.2.0-ultramodern.120 → 3.2.0-ultramodern.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -12
- package/dist/cjs/create-package-root.cjs +7 -9
- package/dist/cjs/index.cjs +74 -44
- package/dist/cjs/locale/en.cjs +6 -7
- package/dist/cjs/locale/zh.cjs +6 -7
- package/dist/cjs/ultramodern-workspace/add-vertical.cjs +337 -0
- package/dist/cjs/ultramodern-workspace/app-files.cjs +223 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +836 -0
- package/dist/cjs/ultramodern-workspace/demo-components.cjs +422 -0
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +222 -0
- package/dist/cjs/ultramodern-workspace/effect-api.cjs +952 -0
- package/dist/cjs/ultramodern-workspace/fs-io.cjs +191 -0
- package/dist/cjs/ultramodern-workspace/index.cjs +48 -0
- package/dist/cjs/ultramodern-workspace/locales.cjs +173 -0
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +487 -0
- package/dist/cjs/ultramodern-workspace/naming.cjs +161 -0
- package/dist/cjs/ultramodern-workspace/package-json.cjs +406 -0
- package/dist/cjs/ultramodern-workspace/package-source.cjs +59 -0
- package/dist/cjs/ultramodern-workspace/policy.cjs +248 -0
- package/dist/cjs/ultramodern-workspace/public-surface.cjs +268 -0
- package/dist/cjs/ultramodern-workspace/routes.cjs +375 -0
- package/dist/cjs/ultramodern-workspace/types.cjs +61 -0
- package/dist/cjs/ultramodern-workspace/versions.cjs +153 -0
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +153 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +175 -0
- package/dist/esm/create-package-root.js +7 -9
- package/dist/esm/index.js +72 -42
- package/dist/esm/locale/en.js +6 -7
- package/dist/esm/locale/zh.js +6 -7
- package/dist/esm/ultramodern-workspace/add-vertical.js +252 -0
- package/dist/esm/ultramodern-workspace/app-files.js +149 -0
- package/dist/esm/ultramodern-workspace/contracts.js +741 -0
- package/dist/esm/ultramodern-workspace/demo-components.js +363 -0
- package/dist/esm/ultramodern-workspace/descriptors.js +133 -0
- package/dist/esm/ultramodern-workspace/effect-api.js +854 -0
- package/dist/esm/ultramodern-workspace/fs-io.js +90 -0
- package/dist/esm/ultramodern-workspace/index.js +3 -0
- package/dist/esm/ultramodern-workspace/locales.js +122 -0
- package/dist/esm/ultramodern-workspace/module-federation.js +415 -0
- package/dist/esm/ultramodern-workspace/naming.js +71 -0
- package/dist/esm/ultramodern-workspace/package-json.js +338 -0
- package/dist/esm/ultramodern-workspace/package-source.js +21 -0
- package/dist/esm/ultramodern-workspace/policy.js +183 -0
- package/dist/esm/ultramodern-workspace/public-surface.js +183 -0
- package/dist/esm/ultramodern-workspace/routes.js +280 -0
- package/dist/esm/ultramodern-workspace/types.js +16 -0
- package/dist/esm/ultramodern-workspace/versions.js +34 -0
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +91 -0
- package/dist/esm/ultramodern-workspace/write-workspace.js +121 -0
- package/dist/esm-node/create-package-root.js +7 -9
- package/dist/esm-node/index.js +72 -42
- package/dist/esm-node/locale/en.js +6 -7
- package/dist/esm-node/locale/zh.js +6 -7
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +253 -0
- package/dist/esm-node/ultramodern-workspace/app-files.js +150 -0
- package/dist/esm-node/ultramodern-workspace/contracts.js +742 -0
- package/dist/esm-node/ultramodern-workspace/demo-components.js +364 -0
- package/dist/esm-node/ultramodern-workspace/descriptors.js +134 -0
- package/dist/esm-node/ultramodern-workspace/effect-api.js +855 -0
- package/dist/esm-node/ultramodern-workspace/fs-io.js +91 -0
- package/dist/esm-node/ultramodern-workspace/index.js +4 -0
- package/dist/esm-node/ultramodern-workspace/locales.js +123 -0
- package/dist/esm-node/ultramodern-workspace/module-federation.js +416 -0
- package/dist/esm-node/ultramodern-workspace/naming.js +72 -0
- package/dist/esm-node/ultramodern-workspace/package-json.js +339 -0
- package/dist/esm-node/ultramodern-workspace/package-source.js +22 -0
- package/dist/esm-node/ultramodern-workspace/policy.js +184 -0
- package/dist/esm-node/ultramodern-workspace/public-surface.js +184 -0
- package/dist/esm-node/ultramodern-workspace/routes.js +281 -0
- package/dist/esm-node/ultramodern-workspace/types.js +17 -0
- package/dist/esm-node/ultramodern-workspace/versions.js +35 -0
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +92 -0
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +122 -0
- package/dist/types/locale/en.d.ts +4 -5
- package/dist/types/locale/index.d.ts +8 -10
- package/dist/types/locale/zh.d.ts +4 -5
- package/dist/types/ultramodern-workspace/add-vertical.d.ts +19 -0
- package/dist/types/ultramodern-workspace/app-files.d.ts +14 -0
- package/dist/types/ultramodern-workspace/contracts.d.ts +21 -0
- package/dist/types/ultramodern-workspace/demo-components.d.ts +9 -0
- package/dist/types/ultramodern-workspace/descriptors.d.ts +39 -0
- package/dist/types/ultramodern-workspace/effect-api.d.ts +73 -0
- package/dist/types/ultramodern-workspace/fs-io.d.ts +18 -0
- package/dist/types/ultramodern-workspace/index.d.ts +4 -0
- package/dist/types/ultramodern-workspace/locales.d.ts +183 -0
- package/dist/types/ultramodern-workspace/module-federation.d.ts +16 -0
- package/dist/types/ultramodern-workspace/naming.d.ts +16 -0
- package/dist/types/ultramodern-workspace/package-json.d.ts +12 -0
- package/dist/types/ultramodern-workspace/package-source.d.ts +2 -0
- package/dist/types/ultramodern-workspace/policy.d.ts +60 -0
- package/dist/types/ultramodern-workspace/public-surface.d.ts +37 -0
- package/dist/types/ultramodern-workspace/routes.d.ts +25 -0
- package/dist/types/ultramodern-workspace/types.d.ts +95 -0
- package/dist/types/ultramodern-workspace/versions.d.ts +38 -0
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +10 -0
- package/dist/types/ultramodern-workspace/write-workspace.d.ts +4 -0
- package/package.json +4 -3
- package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +1 -4
- package/template-workspace/.mise.toml.handlebars +1 -0
- package/template-workspace/{AGENTS.md → AGENTS.md.handlebars} +12 -7
- package/template-workspace/README.md.handlebars +40 -24
- package/template-workspace/{pnpm-workspace.yaml → pnpm-workspace.yaml.handlebars} +2 -2
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +31 -51
- package/templates/app/shell-frame.tsx +49 -0
- package/templates/app/ultramodern-route-head.tsx.handlebars +142 -0
- package/templates/packages/shared-contracts-index.ts +466 -0
- package/templates/workspace-scripts/assert-mf-types.mjs.handlebars +69 -0
- package/templates/workspace-scripts/check-ultramodern-i18n-boundaries.mjs +9 -0
- package/templates/workspace-scripts/generate-public-surface-assets.mjs +529 -0
- package/templates/workspace-scripts/proof-cloudflare-version.mjs +125 -0
- package/templates/workspace-scripts/ultramodern-cloudflare-proof.mjs +851 -0
- package/templates/workspace-scripts/ultramodern-performance-readiness.config.mjs +7 -0
- package/templates/workspace-scripts/ultramodern-performance-readiness.mjs +223 -0
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +593 -0
- package/dist/cjs/ultramodern-workspace.cjs +0 -6797
- package/dist/esm/ultramodern-workspace.js +0 -6738
- package/dist/esm-node/ultramodern-workspace.js +0 -6739
- package/dist/types/ultramodern-workspace.d.ts +0 -29
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import node_fs from "node:fs";
|
|
2
|
+
import { createAppEnvDts, createAppRuntimeConfig, createAppStyles, createPostcssConfig, createSharedDesignTokensCss, createShellFrameComponent, createTailwindConfig } from "./app-files.js";
|
|
3
|
+
import { createDevelopmentOverlay, createGeneratedContract, createOwnership, createPackageSourceMetadata, createTemplateManifest, createTopology } from "./contracts.js";
|
|
4
|
+
import { createLayout, createRemoteEntry, createRemoteExposeComponent, createRemotePage, createShellPage, createShellRemoteComponents, remoteComponentOutputPath } from "./demo-components.js";
|
|
5
|
+
import { GENERATED_CONTRACT_PATH, appHasEffectApi, appI18nNamespace, createShellHost, sharedPackages, shellApp } from "./descriptors.js";
|
|
6
|
+
import { createEffectClient, createEffectServiceEntry, createEffectSharedApi, createShellEffectClient } from "./effect-api.js";
|
|
7
|
+
import { copyRootTemplate, writeFile, writeJson } from "./fs-io.js";
|
|
8
|
+
import { createAppPublicLocaleMessages } from "./locales.js";
|
|
9
|
+
import { createAppModernConfig, createRemoteModuleFederationConfig, createShellModuleFederationConfig, createUltramodernBuildModule } from "./module-federation.js";
|
|
10
|
+
import { assertUniqueTailwindPrefixes, relativeRootFor, toPackageScope } from "./naming.js";
|
|
11
|
+
import { createAppPackage, createPackageTsConfig, createRootPackageJson, createSharedContractsIndex, createSharedPackage, createTsConfigBase } from "./package-json.js";
|
|
12
|
+
import { resolvePackageSource } from "./package-source.js";
|
|
13
|
+
import { createPublicWebAppArtifacts } from "./public-surface.js";
|
|
14
|
+
import { NODE_FETCH_VERSION, NODE_VERSION, PNPM_VERSION, TANSTACK_ROUTER_VERSION } from "./versions.js";
|
|
15
|
+
import { writeGeneratedWorkspaceScripts } from "./workspace-scripts.js";
|
|
16
|
+
function writeApp(targetDir, scope, app, packageSource, enableTailwind, remotes = []) {
|
|
17
|
+
const resolvedApp = 'shell' === app.kind ? createShellHost(remotes) : app;
|
|
18
|
+
const publicWeb = createPublicWebAppArtifacts(resolvedApp);
|
|
19
|
+
const writeAppFile = (relativePath, content)=>{
|
|
20
|
+
writeFile(targetDir, `${resolvedApp.directory}/${relativePath}`, content);
|
|
21
|
+
};
|
|
22
|
+
writeJson(targetDir, `${resolvedApp.directory}/package.json`, createAppPackage(scope, resolvedApp, packageSource, enableTailwind, remotes));
|
|
23
|
+
writeJson(targetDir, `${resolvedApp.directory}/tsconfig.json`, createPackageTsConfig(resolvedApp.directory, appHasEffectApi(resolvedApp)));
|
|
24
|
+
writeFile(targetDir, `${resolvedApp.directory}/src/modern-app-env.d.ts`, createAppEnvDts(resolvedApp, remotes));
|
|
25
|
+
writeFile(targetDir, `${resolvedApp.directory}/src/ultramodern-build.ts`, createUltramodernBuildModule(scope, resolvedApp));
|
|
26
|
+
writeFile(targetDir, publicWeb.jsonLdHelperFile.path, publicWeb.jsonLdHelperFile.content);
|
|
27
|
+
writeFile(targetDir, publicWeb.routeMetadataFile.path, publicWeb.routeMetadataFile.content);
|
|
28
|
+
writeFile(targetDir, publicWeb.routeHeadFile.path, publicWeb.routeHeadFile.content);
|
|
29
|
+
writeFile(targetDir, `${resolvedApp.directory}/modern.config.ts`, createAppModernConfig(scope, resolvedApp));
|
|
30
|
+
writeFile(targetDir, `${resolvedApp.directory}/src/modern.runtime.ts`, createAppRuntimeConfig(resolvedApp, scope, remotes));
|
|
31
|
+
writeJson(targetDir, `${resolvedApp.directory}/locales/en/translation.json`, createAppPublicLocaleMessages(resolvedApp, 'en', remotes));
|
|
32
|
+
writeJson(targetDir, `${resolvedApp.directory}/locales/en/${appI18nNamespace(resolvedApp)}.json`, createAppPublicLocaleMessages(resolvedApp, 'en', remotes));
|
|
33
|
+
writeJson(targetDir, `${resolvedApp.directory}/locales/cs/translation.json`, createAppPublicLocaleMessages(resolvedApp, 'cs', remotes));
|
|
34
|
+
writeJson(targetDir, `${resolvedApp.directory}/locales/cs/${appI18nNamespace(resolvedApp)}.json`, createAppPublicLocaleMessages(resolvedApp, 'cs', remotes));
|
|
35
|
+
writeFile(targetDir, `${resolvedApp.directory}/src/routes/index.css`, createAppStyles(enableTailwind, scope, resolvedApp));
|
|
36
|
+
if (enableTailwind) {
|
|
37
|
+
writeFile(targetDir, `${resolvedApp.directory}/postcss.config.mjs`, createPostcssConfig());
|
|
38
|
+
writeFile(targetDir, `${resolvedApp.directory}/tailwind.config.ts`, createTailwindConfig());
|
|
39
|
+
}
|
|
40
|
+
writeFile(targetDir, `${resolvedApp.directory}/module-federation.config.ts`, 'shell' === resolvedApp.kind ? createShellModuleFederationConfig(scope, remotes) : createRemoteModuleFederationConfig(scope, resolvedApp, remotes));
|
|
41
|
+
writeAppFile('src/routes/layout.tsx', createLayout(resolvedApp.id));
|
|
42
|
+
writeAppFile('src/routes/[lang]/page.tsx', 'shell' === resolvedApp.kind ? createShellPage(remotes) : createRemotePage(resolvedApp));
|
|
43
|
+
for (const generatedFile of publicWeb.routeMetaFiles)writeFile(targetDir, generatedFile.path, generatedFile.content);
|
|
44
|
+
for (const generatedFile of publicWeb.routeAliasFiles)writeFile(targetDir, generatedFile.path, generatedFile.content);
|
|
45
|
+
if ('shell' === resolvedApp.kind) {
|
|
46
|
+
writeAppFile('src/routes/vertical-components.tsx', createShellRemoteComponents(scope, remotes));
|
|
47
|
+
writeAppFile('src/routes/shell-frame.tsx', createShellFrameComponent());
|
|
48
|
+
writeFile(targetDir, `${resolvedApp.directory}/src/effect/vertical-clients.ts`, createShellEffectClient(scope, remotes));
|
|
49
|
+
}
|
|
50
|
+
if (appHasEffectApi(resolvedApp)) {
|
|
51
|
+
writeFile(targetDir, `${resolvedApp.directory}/shared/effect/api.ts`, createEffectSharedApi(resolvedApp));
|
|
52
|
+
writeFile(targetDir, `${resolvedApp.directory}/api/effect/index.ts`, createEffectServiceEntry(resolvedApp, '../../shared/effect/api.ts'));
|
|
53
|
+
writeFile(targetDir, `${resolvedApp.directory}/src/effect/${resolvedApp.effectApi.stem}-client.ts`, createEffectClient(resolvedApp, '../../shared/effect/api'));
|
|
54
|
+
}
|
|
55
|
+
if ('vertical' === resolvedApp.kind) {
|
|
56
|
+
writeAppFile('src/federation-entry.tsx', createRemoteEntry(resolvedApp));
|
|
57
|
+
for (const expose of Object.keys(resolvedApp.exposes ?? {})){
|
|
58
|
+
const outputPath = remoteComponentOutputPath(resolvedApp, expose);
|
|
59
|
+
if (outputPath) writeAppFile(outputPath.slice(resolvedApp.directory.length + 1), createRemoteExposeComponent(resolvedApp, expose));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function writeSharedPackages(targetDir, scope) {
|
|
64
|
+
for (const sharedPackage of sharedPackages){
|
|
65
|
+
writeJson(targetDir, `${sharedPackage.directory}/package.json`, createSharedPackage(scope, sharedPackage.id, sharedPackage.description));
|
|
66
|
+
writeJson(targetDir, `${sharedPackage.directory}/tsconfig.json`, {
|
|
67
|
+
extends: `${relativeRootFor(sharedPackage.directory)}/tsconfig.base.json`,
|
|
68
|
+
include: [
|
|
69
|
+
'src'
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
writeFile(targetDir, 'packages/shared-contracts/src/index.ts', createSharedContractsIndex());
|
|
74
|
+
writeFile(targetDir, 'packages/shared-design-tokens/src/index.ts', `export const sharedDesignTokens = {
|
|
75
|
+
color: {
|
|
76
|
+
accent: '#2f8f68',
|
|
77
|
+
foreground: '#133225',
|
|
78
|
+
surface: '#f6fbf7',
|
|
79
|
+
},
|
|
80
|
+
} as const;
|
|
81
|
+
`);
|
|
82
|
+
writeFile(targetDir, 'packages/shared-design-tokens/src/tokens.css', createSharedDesignTokensCss());
|
|
83
|
+
}
|
|
84
|
+
function generateUltramodernWorkspace(options) {
|
|
85
|
+
const scope = toPackageScope(options.packageName);
|
|
86
|
+
const packageSource = resolvePackageSource(options);
|
|
87
|
+
const enableTailwind = false !== options.enableTailwind;
|
|
88
|
+
const initialVerticals = [];
|
|
89
|
+
assertUniqueTailwindPrefixes([
|
|
90
|
+
shellApp,
|
|
91
|
+
...initialVerticals
|
|
92
|
+
]);
|
|
93
|
+
node_fs.mkdirSync(options.targetDir, {
|
|
94
|
+
recursive: true
|
|
95
|
+
});
|
|
96
|
+
copyRootTemplate(options.targetDir, {
|
|
97
|
+
packageName: options.packageName,
|
|
98
|
+
packageScope: scope,
|
|
99
|
+
nodeVersion: NODE_VERSION,
|
|
100
|
+
pnpmVersion: PNPM_VERSION,
|
|
101
|
+
nodeFetchVersion: NODE_FETCH_VERSION,
|
|
102
|
+
tanstackRouterVersion: TANSTACK_ROUTER_VERSION,
|
|
103
|
+
tailwindEnabled: String(enableTailwind)
|
|
104
|
+
});
|
|
105
|
+
writeJson(options.targetDir, 'package.json', createRootPackageJson(scope, packageSource, initialVerticals));
|
|
106
|
+
writeJson(options.targetDir, 'tsconfig.base.json', createTsConfigBase());
|
|
107
|
+
writeJson(options.targetDir, 'topology/reference-topology.json', createTopology(scope, initialVerticals));
|
|
108
|
+
writeJson(options.targetDir, 'topology/ownership.json', createOwnership(scope, initialVerticals));
|
|
109
|
+
writeJson(options.targetDir, 'topology/local-overlays/development.json', createDevelopmentOverlay(initialVerticals));
|
|
110
|
+
writeJson(options.targetDir, '.modernjs/ultramodern-workspace-template-manifest.json', createTemplateManifest(options.modernVersion, packageSource));
|
|
111
|
+
writeJson(options.targetDir, '.modernjs/ultramodern-package-source.json', createPackageSourceMetadata(scope, packageSource));
|
|
112
|
+
writeJson(options.targetDir, GENERATED_CONTRACT_PATH, createGeneratedContract(scope, [
|
|
113
|
+
createShellHost(initialVerticals),
|
|
114
|
+
...initialVerticals
|
|
115
|
+
], enableTailwind));
|
|
116
|
+
writeApp(options.targetDir, scope, shellApp, packageSource, enableTailwind, initialVerticals);
|
|
117
|
+
for (const remote of initialVerticals)writeApp(options.targetDir, scope, remote, packageSource, enableTailwind, initialVerticals);
|
|
118
|
+
writeSharedPackages(options.targetDir, scope);
|
|
119
|
+
writeGeneratedWorkspaceScripts(options.targetDir, scope, enableTailwind, initialVerticals);
|
|
120
|
+
}
|
|
121
|
+
export { generateUltramodernWorkspace, writeApp, writeSharedPackages };
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import node_fs from "node:fs";
|
|
3
3
|
import node_path from "node:path";
|
|
4
|
+
const MAX_WALK_UP_LEVELS = 5;
|
|
4
5
|
function resolveCreatePackageRoot(fromDir) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
node_path.resolve(fromDir, '..'),
|
|
8
|
-
node_path.resolve(fromDir, '..', '..')
|
|
9
|
-
];
|
|
10
|
-
const seen = new Set();
|
|
11
|
-
for (const candidate of candidates)if (!seen.has(candidate)) {
|
|
12
|
-
seen.add(candidate);
|
|
6
|
+
let candidate = fromDir;
|
|
7
|
+
for(let level = 0; level <= MAX_WALK_UP_LEVELS; level++){
|
|
13
8
|
if (node_fs.existsSync(node_path.join(candidate, 'package.json')) && node_fs.existsSync(node_path.join(candidate, 'template-workspace'))) return candidate;
|
|
9
|
+
const parent = node_path.dirname(candidate);
|
|
10
|
+
if (parent === candidate) break;
|
|
11
|
+
candidate = parent;
|
|
14
12
|
}
|
|
15
|
-
throw new Error(
|
|
13
|
+
throw new Error(`Unable to resolve the @modern-js/create package root (a directory containing both package.json and template-workspace/) within ${MAX_WALK_UP_LEVELS} levels above ${fromDir}`);
|
|
16
14
|
}
|
|
17
15
|
export { resolveCreatePackageRoot };
|
package/dist/esm-node/index.js
CHANGED
|
@@ -7,12 +7,19 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { resolveCreatePackageRoot } from "./create-package-root.js";
|
|
8
8
|
import { i18n, localeKeys } from "./locale/index.js";
|
|
9
9
|
import { BLEEDINGDEV_CREATE_PACKAGE, BLEEDINGDEV_FRAMEWORK_VERSION_ENV, BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE, WORKSPACE_PACKAGE_VERSION } from "./ultramodern-package-source.js";
|
|
10
|
-
import { addUltramodernVertical, generateUltramodernWorkspace } from "./ultramodern-workspace.js";
|
|
10
|
+
import { addUltramodernVertical, generateUltramodernWorkspace } from "./ultramodern-workspace/index.js";
|
|
11
11
|
const src_dirname = node_path.dirname(fileURLToPath(import.meta.url));
|
|
12
12
|
const createPackageRoot = resolveCreatePackageRoot(src_dirname);
|
|
13
13
|
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.-]+)?$/;
|
|
14
14
|
const LEGACY_MODERN_JS_FLAG = '--legacy-modern-js';
|
|
15
15
|
const LEGACY_MODERN_JS_CONFIRMATION = 'USE LEGACY MODERN.JS';
|
|
16
|
+
const WORKSPACE_PROTOCOL_FLAG = '--workspace';
|
|
17
|
+
const BFF_FLAG = '--bff';
|
|
18
|
+
const BFF_RUNTIME_OPTION = '--bff-runtime';
|
|
19
|
+
const SUPPORTED_BFF_RUNTIMES = [
|
|
20
|
+
'effect'
|
|
21
|
+
];
|
|
22
|
+
const REGISTRY_LOOKUP_TIMEOUT_MS = 15000;
|
|
16
23
|
function getOptionValue(args, names) {
|
|
17
24
|
for (const name of names){
|
|
18
25
|
const prefix = `${name}=`;
|
|
@@ -46,8 +53,10 @@ function getBleedingDevFrameworkVersion(createPackage, fallbackVersion) {
|
|
|
46
53
|
}
|
|
47
54
|
function showVersion() {
|
|
48
55
|
const createPackage = readCreatePackageJson();
|
|
56
|
+
const name = createPackage.name || '@modern-js/create';
|
|
49
57
|
const version = createPackage.version || 'unknown';
|
|
50
58
|
console.log(i18n.t(localeKeys.version.message, {
|
|
59
|
+
name,
|
|
51
60
|
version
|
|
52
61
|
}));
|
|
53
62
|
process.exit(0);
|
|
@@ -63,20 +72,26 @@ function showHelp() {
|
|
|
63
72
|
console.log(i18n.t(localeKeys.help.optionHelp));
|
|
64
73
|
console.log(i18n.t(localeKeys.help.optionVersion));
|
|
65
74
|
console.log(i18n.t(localeKeys.help.optionLang));
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
console.log(i18n.t(localeKeys.help.optionTailwind));
|
|
76
|
+
console.log(i18n.t(localeKeys.help.optionBff));
|
|
77
|
+
console.log(i18n.t(localeKeys.help.optionBffRuntime));
|
|
78
|
+
console.log(i18n.t(localeKeys.help.optionWorkspace));
|
|
79
|
+
console.log(i18n.t(localeKeys.help.optionUltramodernPackageSource));
|
|
80
|
+
console.log(i18n.t(localeKeys.help.optionUltramodernPackageVersion));
|
|
81
|
+
console.log(i18n.t(localeKeys.help.optionUltramodernPackageRegistry));
|
|
82
|
+
console.log(i18n.t(localeKeys.help.optionUltramodernPackageScope));
|
|
83
|
+
console.log(i18n.t(localeKeys.help.optionUltramodernPackageNamePrefix));
|
|
84
|
+
console.log(i18n.t(localeKeys.help.optionVertical));
|
|
85
|
+
console.log(i18n.t(localeKeys.help.optionLegacyModernJs));
|
|
72
86
|
console.log('');
|
|
73
87
|
console.log(i18n.t(localeKeys.help.examples));
|
|
74
88
|
console.log(i18n.t(localeKeys.help.example1));
|
|
75
89
|
console.log(i18n.t(localeKeys.help.example2));
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
90
|
+
console.log(i18n.t(localeKeys.help.example3));
|
|
91
|
+
console.log(i18n.t(localeKeys.help.example4));
|
|
92
|
+
console.log(i18n.t(localeKeys.help.example5));
|
|
93
|
+
console.log(i18n.t(localeKeys.help.example6));
|
|
94
|
+
console.log(i18n.t(localeKeys.help.example7));
|
|
80
95
|
console.log('');
|
|
81
96
|
console.log(i18n.t(localeKeys.help.moreInfo));
|
|
82
97
|
console.log('');
|
|
@@ -133,6 +148,26 @@ function delegateLegacyModernJsSetup(args) {
|
|
|
133
148
|
});
|
|
134
149
|
throw new Error('Legacy Modern.js setup requires pnpm or npx to run @modern-js/create.');
|
|
135
150
|
}
|
|
151
|
+
function detectBffRuntime(args) {
|
|
152
|
+
if (args.some((arg)=>arg.startsWith(`${BFF_FLAG}=`))) {
|
|
153
|
+
console.error(`${BFF_FLAG} does not accept a value. Use: ${BFF_RUNTIME_OPTION} <runtime>`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
const runtimeRequested = args.some((arg)=>arg === BFF_RUNTIME_OPTION || arg.startsWith(`${BFF_RUNTIME_OPTION}=`));
|
|
157
|
+
if (!runtimeRequested) return 'effect';
|
|
158
|
+
const runtime = getOptionValue(args, [
|
|
159
|
+
BFF_RUNTIME_OPTION
|
|
160
|
+
]);
|
|
161
|
+
if (!runtime) {
|
|
162
|
+
console.error(`${BFF_RUNTIME_OPTION} requires a value (supported: ${SUPPORTED_BFF_RUNTIMES.join(', ')})`);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
if (!SUPPORTED_BFF_RUNTIMES.includes(runtime)) {
|
|
166
|
+
console.error(`Unsupported BFF runtime "${runtime}". UltraModern workspaces scaffold an Effect BFF for every MicroVertical (supported: ${SUPPORTED_BFF_RUNTIMES.join(', ')}).`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
return runtime;
|
|
170
|
+
}
|
|
136
171
|
function detectTailwindFlag() {
|
|
137
172
|
const args = process.argv.slice(2);
|
|
138
173
|
return !args.includes('--no-tailwind');
|
|
@@ -184,7 +219,7 @@ function hasExplicitUltramodernPackageSource(args, value) {
|
|
|
184
219
|
]);
|
|
185
220
|
return value ? configuredValue === value : void 0 !== configuredValue;
|
|
186
221
|
}
|
|
187
|
-
function readBleedingDevFrameworkVersionFromRegistry() {
|
|
222
|
+
function readBleedingDevFrameworkVersionFromRegistry(fallbackVersion) {
|
|
188
223
|
const envVersion = process.env[BLEEDINGDEV_FRAMEWORK_VERSION_ENV]?.trim();
|
|
189
224
|
if (envVersion) {
|
|
190
225
|
if (!semverPattern.test(envVersion)) {
|
|
@@ -199,16 +234,19 @@ function readBleedingDevFrameworkVersionFromRegistry() {
|
|
|
199
234
|
`${BLEEDINGDEV_CREATE_PACKAGE}@latest`,
|
|
200
235
|
'ultramodern.frameworkVersion',
|
|
201
236
|
'--json'
|
|
202
|
-
]
|
|
237
|
+
], {
|
|
238
|
+
timeoutMs: REGISTRY_LOOKUP_TIMEOUT_MS
|
|
239
|
+
}).trim();
|
|
203
240
|
const version = JSON.parse(rawVersion);
|
|
204
241
|
if ('string' == typeof version && semverPattern.test(version)) return version;
|
|
205
242
|
} catch {}
|
|
206
|
-
console.
|
|
207
|
-
`Could not resolve ${BLEEDINGDEV_CREATE_PACKAGE}@latest ultramodern.frameworkVersion.`,
|
|
208
|
-
|
|
243
|
+
console.warn([
|
|
244
|
+
`Could not resolve ${BLEEDINGDEV_CREATE_PACKAGE}@latest ultramodern.frameworkVersion from the npm registry.`,
|
|
245
|
+
`Falling back to the packaged framework version ${fallbackVersion}.`,
|
|
246
|
+
`Pass ${WORKSPACE_PROTOCOL_FLAG} to use local workspace protocol dependencies,`,
|
|
209
247
|
'or pass --ultramodern-package-version with the exact BleedingDev framework cohort.'
|
|
210
248
|
].join(' '));
|
|
211
|
-
|
|
249
|
+
return fallbackVersion;
|
|
212
250
|
}
|
|
213
251
|
function resolveInstallBackedPackageSource(args, createPackage, packageSource) {
|
|
214
252
|
const explicitVersion = getOptionValue(args, [
|
|
@@ -223,7 +261,7 @@ function resolveInstallBackedPackageSource(args, createPackage, packageSource) {
|
|
|
223
261
|
return {
|
|
224
262
|
...packageSource,
|
|
225
263
|
strategy: 'install',
|
|
226
|
-
modernPackageVersion: explicitVersion ?? (isBleedingDevCreatePackage(createPackage) ? packageSource.modernPackageVersion : readBleedingDevFrameworkVersionFromRegistry()),
|
|
264
|
+
modernPackageVersion: explicitVersion ?? (isBleedingDevCreatePackage(createPackage) ? packageSource.modernPackageVersion : readBleedingDevFrameworkVersionFromRegistry(packageSource.modernPackageVersion)),
|
|
227
265
|
aliasScope,
|
|
228
266
|
aliasPackageNamePrefix: getOptionValue(args, [
|
|
229
267
|
'--ultramodern-package-name-prefix'
|
|
@@ -231,7 +269,12 @@ function resolveInstallBackedPackageSource(args, createPackage, packageSource) {
|
|
|
231
269
|
};
|
|
232
270
|
}
|
|
233
271
|
function resolveWorkspacePackageSource(args, createPackage, packageSource) {
|
|
234
|
-
|
|
272
|
+
const workspaceProtocolRequested = args.includes(WORKSPACE_PROTOCOL_FLAG);
|
|
273
|
+
if (workspaceProtocolRequested && hasExplicitUltramodernPackageSource(args, 'install')) {
|
|
274
|
+
console.error(`${WORKSPACE_PROTOCOL_FLAG} conflicts with --ultramodern-package-source=install`);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
if (workspaceProtocolRequested || hasExplicitUltramodernPackageSource(args, 'workspace')) return {
|
|
235
278
|
...packageSource,
|
|
236
279
|
strategy: 'workspace',
|
|
237
280
|
modernPackageVersion: WORKSPACE_PACKAGE_VERSION
|
|
@@ -246,7 +289,8 @@ function runSetupCommand(command, args, options = {}) {
|
|
|
246
289
|
'ignore',
|
|
247
290
|
'pipe',
|
|
248
291
|
'pipe'
|
|
249
|
-
]
|
|
292
|
+
],
|
|
293
|
+
timeout: options.timeoutMs
|
|
250
294
|
});
|
|
251
295
|
}
|
|
252
296
|
function commandExists(command) {
|
|
@@ -261,26 +305,9 @@ function commandExists(command) {
|
|
|
261
305
|
return false;
|
|
262
306
|
}
|
|
263
307
|
}
|
|
264
|
-
function
|
|
308
|
+
function assertGitAvailableForGeneratedProject() {
|
|
265
309
|
if (commandExists('git')) return;
|
|
266
|
-
|
|
267
|
-
'-lc',
|
|
268
|
-
script
|
|
269
|
-
], {
|
|
270
|
-
stdio: 'inherit'
|
|
271
|
-
});
|
|
272
|
-
const sudo = 'function' == typeof process.getuid && 0 === process.getuid() ? '' : 'sudo ';
|
|
273
|
-
if (commandExists('brew')) runSetupCommand('brew', [
|
|
274
|
-
'install',
|
|
275
|
-
'git'
|
|
276
|
-
], {
|
|
277
|
-
stdio: 'inherit'
|
|
278
|
-
});
|
|
279
|
-
else if ('linux' === process.platform && commandExists('apt-get')) runShell(`${sudo}apt-get update && ${sudo}apt-get install -y git`);
|
|
280
|
-
else if ('linux' === process.platform && commandExists('dnf')) runShell(`${sudo}dnf install -y git`);
|
|
281
|
-
else if ('linux' === process.platform && commandExists('yum')) runShell(`${sudo}yum install -y git`);
|
|
282
|
-
else if ('linux' === process.platform && commandExists('apk')) runShell('apk add --no-cache git');
|
|
283
|
-
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.');
|
|
310
|
+
throw new Error('Git is required for UltraModern setup. Install git yourself (for example "brew install git" or "sudo apt-get install git") and rerun create. This tool never installs system packages on your behalf.');
|
|
284
311
|
}
|
|
285
312
|
function isInsideGitWorkTree(targetDir) {
|
|
286
313
|
try {
|
|
@@ -295,7 +322,7 @@ function isInsideGitWorkTree(targetDir) {
|
|
|
295
322
|
}
|
|
296
323
|
}
|
|
297
324
|
function initializeGeneratedGitRepository(targetDir) {
|
|
298
|
-
|
|
325
|
+
assertGitAvailableForGeneratedProject();
|
|
299
326
|
if (isInsideGitWorkTree(targetDir)) return;
|
|
300
327
|
try {
|
|
301
328
|
runSetupCommand('git', [
|
|
@@ -337,6 +364,7 @@ async function getProjectName() {
|
|
|
337
364
|
const optionWithValue = new Set([
|
|
338
365
|
'--lang',
|
|
339
366
|
'-l',
|
|
367
|
+
BFF_RUNTIME_OPTION,
|
|
340
368
|
'--ultramodern-package-source',
|
|
341
369
|
'--ultramodern-package-version',
|
|
342
370
|
'--ultramodern-package-registry',
|
|
@@ -350,7 +378,8 @@ async function getProjectName() {
|
|
|
350
378
|
'-v',
|
|
351
379
|
'--tailwind',
|
|
352
380
|
'--no-tailwind',
|
|
353
|
-
|
|
381
|
+
BFF_FLAG,
|
|
382
|
+
WORKSPACE_PROTOCOL_FLAG,
|
|
354
383
|
'--vertical',
|
|
355
384
|
LEGACY_MODERN_JS_FLAG
|
|
356
385
|
]);
|
|
@@ -362,7 +391,7 @@ async function getProjectName() {
|
|
|
362
391
|
i += 1;
|
|
363
392
|
continue;
|
|
364
393
|
}
|
|
365
|
-
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);
|
|
394
|
+
if (!(arg.startsWith('--lang=') || arg.startsWith(`${BFF_RUNTIME_OPTION}=`) || 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);
|
|
366
395
|
}
|
|
367
396
|
}
|
|
368
397
|
if (positionalArgs.length > 1) {
|
|
@@ -404,6 +433,7 @@ async function main() {
|
|
|
404
433
|
delegateLegacyModernJsSetup(args);
|
|
405
434
|
return;
|
|
406
435
|
}
|
|
436
|
+
detectBffRuntime(args);
|
|
407
437
|
console.log(`\n${i18n.t(localeKeys.message.welcome)}\n`);
|
|
408
438
|
const { name: projectName, useCurrentDir } = await getProjectName();
|
|
409
439
|
const targetDir = useCurrentDir ? process.cwd() : node_path.isAbsolute(projectName) ? projectName : node_path.resolve(process.cwd(), projectName);
|
|
@@ -29,8 +29,12 @@ const EN_LOCALE = {
|
|
|
29
29
|
optionVersion: ' -v, --version Display version information',
|
|
30
30
|
optionLang: ' -l, --lang Set the language (en default; zh opt-in)',
|
|
31
31
|
optionTailwind: ' --no-tailwind Disable default Tailwind CSS v4 workspace styling',
|
|
32
|
+
optionBff: ' --bff Keep the default Effect BFF scaffolding (every MicroVertical ships an Effect BFF)',
|
|
33
|
+
optionBffRuntime: ' --bff-runtime Select the BFF runtime for scaffolded MicroVerticals (supported: effect; default: effect)',
|
|
32
34
|
optionWorkspace: ' --workspace Use workspace protocol for @modern-js dependencies (for local monorepo testing)',
|
|
33
35
|
optionUltramodernPackageSource: ' --ultramodern-package-source Select UltraModern package source (workspace or install; BleedingDev defaults to install aliases)',
|
|
36
|
+
optionUltramodernPackageVersion: ' --ultramodern-package-version Pin the exact BleedingDev framework cohort for install package sources',
|
|
37
|
+
optionUltramodernPackageRegistry: ' --ultramodern-package-registry npm registry URL used for install package sources',
|
|
34
38
|
optionUltramodernPackageScope: ' --ultramodern-package-scope Publish scope for npm alias installs (for example bleedingdev)',
|
|
35
39
|
optionUltramodernPackageNamePrefix: ' --ultramodern-package-name-prefix Prefix for npm alias package names (default: modern-js-)',
|
|
36
40
|
optionVertical: ' --vertical Mutate the current existing UltraModern workspace and wire a MicroVertical named <project-name>',
|
|
@@ -42,16 +46,11 @@ const EN_LOCALE = {
|
|
|
42
46
|
example4: ' pnpm dlx @bleedingdev/modern-js-create --help',
|
|
43
47
|
example5: ' pnpm dlx @bleedingdev/modern-js-create .',
|
|
44
48
|
example6: ' pnpm dlx @bleedingdev/modern-js-create my-workspace --workspace',
|
|
45
|
-
example7: '',
|
|
46
|
-
example8: '',
|
|
47
|
-
example9: '',
|
|
48
|
-
example10: '',
|
|
49
|
-
example11: '',
|
|
50
|
-
example12: ' pnpm dlx @bleedingdev/modern-js-create catalog --vertical',
|
|
49
|
+
example7: ' pnpm dlx @bleedingdev/modern-js-create catalog --vertical',
|
|
51
50
|
moreInfo: '📚 Learn more: https://modernjs.dev'
|
|
52
51
|
},
|
|
53
52
|
version: {
|
|
54
|
-
message: '
|
|
53
|
+
message: '{name} version: {version}'
|
|
55
54
|
}
|
|
56
55
|
};
|
|
57
56
|
export { EN_LOCALE };
|
|
@@ -29,8 +29,12 @@ const ZH_LOCALE = {
|
|
|
29
29
|
optionVersion: ' -v, --version 显示版本信息',
|
|
30
30
|
optionLang: ' -l, --lang 设置语言 (默认 en;zh 需显式选择)',
|
|
31
31
|
optionTailwind: ' --no-tailwind 禁用默认 Tailwind CSS v4 工作区样式',
|
|
32
|
+
optionBff: ' --bff 保留默认的 Effect BFF 脚手架(每个 MicroVertical 自带 Effect BFF)',
|
|
33
|
+
optionBffRuntime: ' --bff-runtime 选择 MicroVertical 脚手架的 BFF 运行时(支持: effect;默认: effect)',
|
|
32
34
|
optionWorkspace: ' --workspace 对 @modern-js 依赖使用 workspace 协议(用于本地 monorepo 联调)',
|
|
33
35
|
optionUltramodernPackageSource: ' --ultramodern-package-source 选择 UltraModern 依赖来源(workspace 或 install;BleedingDev 默认使用 install alias)',
|
|
36
|
+
optionUltramodernPackageVersion: ' --ultramodern-package-version 为 install 依赖来源固定精确的 BleedingDev 框架版本',
|
|
37
|
+
optionUltramodernPackageRegistry: ' --ultramodern-package-registry install 依赖来源使用的 npm registry 地址',
|
|
34
38
|
optionUltramodernPackageScope: ' --ultramodern-package-scope npm alias 安装使用的发布 scope(例如 bleedingdev)',
|
|
35
39
|
optionUltramodernPackageNamePrefix: ' --ultramodern-package-name-prefix npm alias 包名前缀(默认:modern-js-)',
|
|
36
40
|
optionVertical: ' --vertical 修改当前已有的 UltraModern 工作区,并接入名为 <项目名称> 的 MicroVertical',
|
|
@@ -42,16 +46,11 @@ const ZH_LOCALE = {
|
|
|
42
46
|
example4: ' pnpm dlx @bleedingdev/modern-js-create --help',
|
|
43
47
|
example5: ' pnpm dlx @bleedingdev/modern-js-create .',
|
|
44
48
|
example6: ' pnpm dlx @bleedingdev/modern-js-create my-workspace --workspace',
|
|
45
|
-
example7: '',
|
|
46
|
-
example8: '',
|
|
47
|
-
example9: '',
|
|
48
|
-
example10: '',
|
|
49
|
-
example11: '',
|
|
50
|
-
example12: ' pnpm dlx @bleedingdev/modern-js-create catalog --vertical',
|
|
49
|
+
example7: ' pnpm dlx @bleedingdev/modern-js-create catalog --vertical',
|
|
51
50
|
moreInfo: '📚 更多信息: https://modernjs.dev'
|
|
52
51
|
},
|
|
53
52
|
version: {
|
|
54
|
-
message: '
|
|
53
|
+
message: '{name} 版本: {version}'
|
|
55
54
|
}
|
|
56
55
|
};
|
|
57
56
|
export { ZH_LOCALE };
|