@bleedingdev/modern-js-create 3.2.0-ultramodern.116 → 3.2.0-ultramodern.118
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 -125
- package/dist/cjs/create-package-root.cjs +1 -1
- package/dist/cjs/index.cjs +12 -606
- package/dist/cjs/locale/en.cjs +13 -20
- package/dist/cjs/locale/zh.cjs +13 -20
- package/dist/cjs/ultramodern-workspace.cjs +16 -19
- package/dist/esm/create-package-root.js +1 -1
- package/dist/esm/index.js +14 -607
- package/dist/esm/locale/en.js +13 -20
- package/dist/esm/locale/zh.js +13 -20
- package/dist/esm/ultramodern-workspace.js +17 -17
- package/dist/esm-node/create-package-root.js +1 -1
- package/dist/esm-node/index.js +14 -607
- package/dist/esm-node/locale/en.js +13 -20
- package/dist/esm-node/locale/zh.js +13 -20
- package/dist/esm-node/ultramodern-workspace.js +17 -17
- package/dist/types/locale/en.d.ts +0 -7
- package/dist/types/locale/index.d.ts +0 -14
- package/dist/types/locale/zh.d.ts +0 -7
- package/dist/types/ultramodern-workspace.d.ts +0 -1
- package/package.json +4 -5
- package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +22 -6
- package/template-workspace/AGENTS.md +7 -3
- package/template-workspace/README.md.handlebars +5 -1
- package/template-workspace/lefthook.yml +18 -4
- package/template/.agents/skills-lock.json +0 -34
- package/template/.browserslistrc +0 -4
- package/template/.codex/hooks.json +0 -16
- package/template/.github/renovate.json +0 -53
- package/template/.github/workflows/ultramodern-gates.yml.handlebars +0 -54
- package/template/.gitignore.handlebars +0 -30
- package/template/.mise.toml.handlebars +0 -2
- package/template/.nvmrc +0 -2
- package/template/AGENTS.md +0 -23
- package/template/README.md +0 -111
- package/template/api/effect/index.ts.handlebars +0 -34
- package/template/api/lambda/hello.ts.handlebars +0 -6
- package/template/config/favicon.svg +0 -5
- package/template/config/public/assets/ultramodern-logo.svg +0 -6
- package/template/config/public/locales/cs/translation.json +0 -44
- package/template/config/public/locales/en/translation.json +0 -44
- package/template/lefthook.yml +0 -10
- package/template/modern.config.ts.handlebars +0 -78
- package/template/oxfmt.config.ts +0 -15
- package/template/oxlint.config.ts +0 -19
- package/template/package.json.handlebars +0 -69
- package/template/pnpm-workspace.yaml +0 -34
- package/template/postcss.config.mjs.handlebars +0 -6
- package/template/rstest.config.mts +0 -5
- package/template/scripts/bootstrap-agent-skills.mjs +0 -228
- package/template/scripts/check-i18n-strings.mjs +0 -3
- package/template/scripts/validate-ultramodern.mjs.handlebars +0 -658
- package/template/shared/effect/api.ts.handlebars +0 -17
- package/template/src/modern-app-env.d.ts +0 -3
- package/template/src/modern.runtime.ts.handlebars +0 -23
- package/template/src/routes/[lang]/page.tsx.handlebars +0 -209
- package/template/src/routes/index.css.handlebars +0 -266
- package/template/src/routes/layout.tsx.handlebars +0 -10
- package/template/tailwind.config.ts.handlebars +0 -10
- package/template/tests/tsconfig.json +0 -7
- package/template/tests/ultramodern.contract.test.ts.handlebars +0 -163
- package/template/tsconfig.json +0 -121
package/dist/esm/index.js
CHANGED
|
@@ -1,58 +1,15 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
-
import node_crypto from "node:crypto";
|
|
3
2
|
import node_fs from "node:fs";
|
|
4
3
|
import node_path from "node:path";
|
|
5
4
|
import node_readline from "node:readline";
|
|
6
5
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { getLocaleLanguage } from "@modern-js/i18n-utils/language-detector";
|
|
8
6
|
import { resolveCreatePackageRoot } from "./create-package-root.js";
|
|
9
7
|
import { i18n, localeKeys } from "./locale/index.js";
|
|
10
|
-
import { BLEEDINGDEV_CREATE_PACKAGE, BLEEDINGDEV_FRAMEWORK_VERSION_ENV, BLEEDINGDEV_PACKAGE_NAME_PREFIX, BLEEDINGDEV_PACKAGE_SCOPE,
|
|
11
|
-
import {
|
|
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";
|
|
12
10
|
const src_dirname = node_path.dirname(fileURLToPath(import.meta.url));
|
|
13
11
|
const createPackageRoot = resolveCreatePackageRoot(src_dirname);
|
|
14
|
-
const templateDir = node_path.join(createPackageRoot, 'template');
|
|
15
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.-]+)?$/;
|
|
16
|
-
const semverTagPattern = /^v?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?$/;
|
|
17
|
-
const sha1Pattern = /^[0-9a-f]{40}$/;
|
|
18
|
-
const sha256Pattern = /^[0-9a-f]{64}$/;
|
|
19
|
-
const templateIdPattern = /^[a-z0-9][a-z0-9._-]*$/;
|
|
20
|
-
const packageNamePattern = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/;
|
|
21
|
-
const TANSTACK_ROUTER_VERSION = '1.170.15';
|
|
22
|
-
const TAILWIND_VERSION = '4.3.0';
|
|
23
|
-
const TAILWIND_POSTCSS_VERSION = '4.3.0';
|
|
24
|
-
const PNPM_VERSION = '11.5.2';
|
|
25
|
-
const I18NEXT_VERSION = '26.3.1';
|
|
26
|
-
const REACT_VERSION = '^19.2.7';
|
|
27
|
-
const REACT_DOM_VERSION = '^19.2.7';
|
|
28
|
-
const REACT_I18NEXT_VERSION = '17.0.8';
|
|
29
|
-
const EFFECT_TSGO_VERSION = '0.14.0';
|
|
30
|
-
const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260606.1';
|
|
31
|
-
const HAPPY_DOM_VERSION = '^20.10.1';
|
|
32
|
-
const RSTEST_CORE_VERSION = '0.10.3';
|
|
33
|
-
const OXFMT_VERSION = '0.53.0';
|
|
34
|
-
const OXLINT_VERSION = '1.68.0';
|
|
35
|
-
const POSTCSS_VERSION = '^8.5.15';
|
|
36
|
-
const ULTRACITE_VERSION = '7.8.1';
|
|
37
|
-
const TYPES_REACT_VERSION = '^19.2.17';
|
|
38
|
-
const TYPES_REACT_DOM_VERSION = '^19.2.3';
|
|
39
|
-
const requiredDeniedPaths = [
|
|
40
|
-
'.git/**',
|
|
41
|
-
'.npmrc',
|
|
42
|
-
'.yarnrc',
|
|
43
|
-
'.env',
|
|
44
|
-
'.env.*',
|
|
45
|
-
'node_modules/**',
|
|
46
|
-
'dist/**'
|
|
47
|
-
];
|
|
48
|
-
const requiredLifecycleDeniedScripts = [
|
|
49
|
-
'preinstall',
|
|
50
|
-
'install',
|
|
51
|
-
'prepare'
|
|
52
|
-
];
|
|
53
|
-
const requiredLifecycleAllowedScripts = [
|
|
54
|
-
'postinstall'
|
|
55
|
-
];
|
|
56
13
|
const LEGACY_MODERN_JS_FLAG = '--legacy-modern-js';
|
|
57
14
|
const LEGACY_MODERN_JS_CONFIRMATION = 'USE LEGACY MODERN.JS';
|
|
58
15
|
function getOptionValue(args, names) {
|
|
@@ -69,327 +26,12 @@ const detectLanguage = ()=>{
|
|
|
69
26
|
'--lang',
|
|
70
27
|
'-l'
|
|
71
28
|
]);
|
|
72
|
-
if (
|
|
73
|
-
const detectedLang = getLocaleLanguage();
|
|
74
|
-
if ('zh' === detectedLang) return 'zh';
|
|
29
|
+
if ('zh' === lang) return 'zh';
|
|
75
30
|
return 'en';
|
|
76
31
|
};
|
|
77
32
|
i18n.changeLanguage({
|
|
78
33
|
locale: detectLanguage()
|
|
79
34
|
});
|
|
80
|
-
function detectRouterFramework() {
|
|
81
|
-
const args = process.argv.slice(2);
|
|
82
|
-
if (args.includes('--tanstack')) return 'tanstack';
|
|
83
|
-
const routerValue = getOptionValue(args, [
|
|
84
|
-
'--router',
|
|
85
|
-
'-r'
|
|
86
|
-
]);
|
|
87
|
-
if (!routerValue || 'tanstack' === routerValue) return 'tanstack';
|
|
88
|
-
if ('react-router' === routerValue) return 'react-router';
|
|
89
|
-
console.error(i18n.t(localeKeys.error.invalidRouter, {
|
|
90
|
-
router: routerValue
|
|
91
|
-
}));
|
|
92
|
-
process.exit(1);
|
|
93
|
-
}
|
|
94
|
-
function detectBffRuntime() {
|
|
95
|
-
const args = process.argv.slice(2);
|
|
96
|
-
const runtimeValue = getOptionValue(args, [
|
|
97
|
-
'--bff-runtime'
|
|
98
|
-
]);
|
|
99
|
-
if (!runtimeValue) return 'effect';
|
|
100
|
-
if ('hono' === runtimeValue || 'effect' === runtimeValue) return runtimeValue;
|
|
101
|
-
console.error(i18n.t(localeKeys.error.invalidBffRuntime, {
|
|
102
|
-
runtime: runtimeValue
|
|
103
|
-
}));
|
|
104
|
-
process.exit(1);
|
|
105
|
-
}
|
|
106
|
-
function renderTemplate(template, data) {
|
|
107
|
-
const tagRegex = /\{\{(~?)(#if|#unless|\/if|\/unless)(?:\s+(\w+))?(~?)\}\}/g;
|
|
108
|
-
function renderConditionals(startIndex, expectedClose) {
|
|
109
|
-
let rendered = '';
|
|
110
|
-
let cursor = startIndex;
|
|
111
|
-
tagRegex.lastIndex = startIndex;
|
|
112
|
-
while(true){
|
|
113
|
-
const match = tagRegex.exec(template);
|
|
114
|
-
if (!match) return {
|
|
115
|
-
rendered: rendered + template.slice(cursor),
|
|
116
|
-
nextIndex: template.length
|
|
117
|
-
};
|
|
118
|
-
const [raw, , tag, condition, rightTrim] = match;
|
|
119
|
-
const tagIndex = match.index;
|
|
120
|
-
rendered += template.slice(cursor, tagIndex);
|
|
121
|
-
cursor = tagIndex + raw.length;
|
|
122
|
-
if ('#if' === tag || '#unless' === tag) {
|
|
123
|
-
const kind = '#if' === tag ? 'if' : 'unless';
|
|
124
|
-
const innerResult = renderConditionals(cursor, kind);
|
|
125
|
-
cursor = innerResult.nextIndex;
|
|
126
|
-
tagRegex.lastIndex = cursor;
|
|
127
|
-
const conditionValue = Boolean(data[condition ?? '']);
|
|
128
|
-
const shouldInclude = 'if' === kind ? conditionValue : !conditionValue;
|
|
129
|
-
if (shouldInclude) rendered += innerResult.rendered;
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if ('/if' === tag || '/unless' === tag) {
|
|
133
|
-
const kind = '/if' === tag ? 'if' : 'unless';
|
|
134
|
-
if (expectedClose === kind) {
|
|
135
|
-
let nextIndex = cursor;
|
|
136
|
-
if ('~' === rightTrim) {
|
|
137
|
-
const trailingWhitespace = /^\s*/u.exec(template.slice(nextIndex));
|
|
138
|
-
nextIndex += trailingWhitespace?.[0].length ?? 0;
|
|
139
|
-
}
|
|
140
|
-
return {
|
|
141
|
-
rendered,
|
|
142
|
-
nextIndex
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
rendered += raw;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
let result = renderConditionals(0).rendered;
|
|
150
|
-
const varRegex = /\{\{(\w+)\}\}/g;
|
|
151
|
-
result = result.replace(varRegex, (match, key)=>{
|
|
152
|
-
const value = data[key];
|
|
153
|
-
return null != value ? String(value) : match;
|
|
154
|
-
});
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
function normalizePathForManifest(filePath) {
|
|
158
|
-
return filePath.split(node_path.sep).join('/');
|
|
159
|
-
}
|
|
160
|
-
function isUnsafeRelativePath(filePath) {
|
|
161
|
-
return 0 === filePath.length || node_path.isAbsolute(filePath) || filePath.startsWith('/') || /^[A-Za-z]:[\\/]/.test(filePath) || filePath.split(/[\\/]+/).includes('..');
|
|
162
|
-
}
|
|
163
|
-
function hashFile(filePath) {
|
|
164
|
-
return node_crypto.createHash('sha256').update(node_fs.readFileSync(filePath)).digest('hex');
|
|
165
|
-
}
|
|
166
|
-
function getTemplateFiles(dir) {
|
|
167
|
-
const files = [];
|
|
168
|
-
function collect(currentDir) {
|
|
169
|
-
const entries = node_fs.readdirSync(currentDir, {
|
|
170
|
-
withFileTypes: true
|
|
171
|
-
}).sort((a, b)=>a.name.localeCompare(b.name));
|
|
172
|
-
for (const entry of entries){
|
|
173
|
-
const entryPath = node_path.join(currentDir, entry.name);
|
|
174
|
-
if (entry.isDirectory()) collect(entryPath);
|
|
175
|
-
else if (entry.isFile()) files.push(normalizePathForManifest(node_path.relative(dir, entryPath)));
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
collect(dir);
|
|
179
|
-
return files;
|
|
180
|
-
}
|
|
181
|
-
function hashTemplateTree(dir) {
|
|
182
|
-
const hash = node_crypto.createHash('sha256');
|
|
183
|
-
for (const relativePath of getTemplateFiles(dir)){
|
|
184
|
-
const fileHash = hashFile(node_path.join(dir, relativePath));
|
|
185
|
-
hash.update(relativePath);
|
|
186
|
-
hash.update('\0');
|
|
187
|
-
hash.update(fileHash);
|
|
188
|
-
hash.update('\0');
|
|
189
|
-
}
|
|
190
|
-
return hash.digest('hex');
|
|
191
|
-
}
|
|
192
|
-
function createBuiltinTemplateManifest(version) {
|
|
193
|
-
return {
|
|
194
|
-
schemaVersion: 1,
|
|
195
|
-
template: {
|
|
196
|
-
id: 'modernjs-ultramodern-app',
|
|
197
|
-
version,
|
|
198
|
-
displayName: 'Modern.js Ultramodern App',
|
|
199
|
-
description: 'Repository-owned Modern.js application scaffold with UltraModern preset defaults.',
|
|
200
|
-
compatibilityLane: 'ultramodern-mv',
|
|
201
|
-
minimumModernVersion: version
|
|
202
|
-
},
|
|
203
|
-
source: {
|
|
204
|
-
type: 'builtin',
|
|
205
|
-
name: 'modernjs-ultramodern-app',
|
|
206
|
-
repositoryPath: 'packages/toolkit/create/template'
|
|
207
|
-
},
|
|
208
|
-
integrity: {
|
|
209
|
-
checksums: [
|
|
210
|
-
{
|
|
211
|
-
algorithm: 'sha256',
|
|
212
|
-
value: hashTemplateTree(templateDir),
|
|
213
|
-
scope: 'source-tree'
|
|
214
|
-
}
|
|
215
|
-
],
|
|
216
|
-
provenance: {
|
|
217
|
-
kind: 'repo-local',
|
|
218
|
-
issuer: '@modern-js/create',
|
|
219
|
-
subject: 'packages/toolkit/create/template'
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
|
-
materialization: {
|
|
223
|
-
targetRoot: 'generated-project-root',
|
|
224
|
-
allowedPaths: [
|
|
225
|
-
'.agents/**',
|
|
226
|
-
'.browserslistrc',
|
|
227
|
-
'.codex/**',
|
|
228
|
-
'.github/**',
|
|
229
|
-
'.gitignore',
|
|
230
|
-
'.mise.toml',
|
|
231
|
-
'.modernjs/**',
|
|
232
|
-
'.nvmrc',
|
|
233
|
-
'AGENTS.md',
|
|
234
|
-
'README.md',
|
|
235
|
-
'api/**',
|
|
236
|
-
'config/**',
|
|
237
|
-
'lefthook.yml',
|
|
238
|
-
'modern.config.ts',
|
|
239
|
-
'oxfmt.config.ts',
|
|
240
|
-
'oxlint.config.ts',
|
|
241
|
-
'package.json',
|
|
242
|
-
'pnpm-workspace.yaml',
|
|
243
|
-
'postcss.config.mjs',
|
|
244
|
-
'rstest.config.mts',
|
|
245
|
-
"scripts/**",
|
|
246
|
-
'shared/**',
|
|
247
|
-
'src/**',
|
|
248
|
-
'tailwind.config.ts',
|
|
249
|
-
'tests/**',
|
|
250
|
-
'tsconfig.json'
|
|
251
|
-
],
|
|
252
|
-
deniedPaths: requiredDeniedPaths,
|
|
253
|
-
overwritePolicy: 'deny-existing'
|
|
254
|
-
},
|
|
255
|
-
lifecyclePolicy: {
|
|
256
|
-
denyByDefault: true,
|
|
257
|
-
deniedScripts: requiredLifecycleDeniedScripts,
|
|
258
|
-
allowedScripts: requiredLifecycleAllowedScripts,
|
|
259
|
-
requiresExplicitOptIn: true
|
|
260
|
-
},
|
|
261
|
-
validation: {
|
|
262
|
-
schemaValidation: true,
|
|
263
|
-
sourceValidation: [
|
|
264
|
-
'source-type-supported',
|
|
265
|
-
'checksum-verified',
|
|
266
|
-
'provenance-present'
|
|
267
|
-
],
|
|
268
|
-
materializationValidation: [
|
|
269
|
-
'path-boundary-allowlist',
|
|
270
|
-
'path-boundary-denylist',
|
|
271
|
-
'no-path-traversal',
|
|
272
|
-
'no-absolute-paths',
|
|
273
|
-
'overwrite-policy-enforced'
|
|
274
|
-
],
|
|
275
|
-
postMaterializationValidation: [
|
|
276
|
-
'ultramodern-contract-check',
|
|
277
|
-
'agent-skill-postinstall-allowed',
|
|
278
|
-
'github-workflow-security-enforced',
|
|
279
|
-
'package-source-retained',
|
|
280
|
-
'pnpm-11-policy-enforced',
|
|
281
|
-
'rstest-smoke-tests',
|
|
282
|
-
'template-manifest-retained'
|
|
283
|
-
],
|
|
284
|
-
expectedCommands: [
|
|
285
|
-
'mise install',
|
|
286
|
-
'pnpm install',
|
|
287
|
-
'pnpm test',
|
|
288
|
-
'pnpm run ultramodern:check'
|
|
289
|
-
]
|
|
290
|
-
}
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
function assertTemplateManifest(condition, message) {
|
|
294
|
-
if (!condition) throw new Error(`Template manifest validation failed: ${message}`);
|
|
295
|
-
}
|
|
296
|
-
function assertSafeManifestPath(filePath, label) {
|
|
297
|
-
assertTemplateManifest(!isUnsafeRelativePath(filePath), `${label} is unsafe`);
|
|
298
|
-
}
|
|
299
|
-
function validateTemplateSource(source) {
|
|
300
|
-
const sourceType = source.type;
|
|
301
|
-
assertTemplateManifest('builtin' === sourceType || 'npm' === sourceType || 'git' === sourceType || 'local' === sourceType, `unsupported source type "${source.type}"`);
|
|
302
|
-
if ('builtin' === source.type) {
|
|
303
|
-
assertTemplateManifest(templateIdPattern.test(source.name), 'builtin source name must be a template id');
|
|
304
|
-
if (source.repositoryPath) assertSafeManifestPath(source.repositoryPath, 'builtin repositoryPath');
|
|
305
|
-
}
|
|
306
|
-
if ('npm' === source.type) {
|
|
307
|
-
assertTemplateManifest(packageNamePattern.test(source.packageName), 'npm packageName must be exact package metadata');
|
|
308
|
-
assertTemplateManifest(semverPattern.test(source.version), 'npm source version must be an exact semver');
|
|
309
|
-
assertTemplateManifest(sha256Pattern.test(source.tarballSha256), 'npm source tarballSha256 must be sha256 hex');
|
|
310
|
-
}
|
|
311
|
-
if ('git' === source.type) {
|
|
312
|
-
assertTemplateManifest(sha1Pattern.test(source.checkoutSha), 'git checkoutSha must pin a commit');
|
|
313
|
-
if ('sha' === source.ref.kind) assertTemplateManifest(sha1Pattern.test(source.ref.sha), 'git sha ref must be pinned to a commit');
|
|
314
|
-
else {
|
|
315
|
-
assertTemplateManifest(semverTagPattern.test(source.ref.tag), 'git tag ref must be a semver tag');
|
|
316
|
-
assertTemplateManifest(sha1Pattern.test(source.ref.tagSha), 'git tag ref must include the resolved tag sha');
|
|
317
|
-
}
|
|
318
|
-
if (source.subdirectory) assertSafeManifestPath(source.subdirectory, 'git subdirectory');
|
|
319
|
-
}
|
|
320
|
-
if ('local' === source.type) {
|
|
321
|
-
assertSafeManifestPath(source.path, 'local source path');
|
|
322
|
-
assertTemplateManifest(true !== source.allowOutsideWorkspace, 'local source cannot allow outside workspace materialization');
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
function validateTemplateManifest(manifest) {
|
|
326
|
-
assertTemplateManifest(1 === manifest.schemaVersion, 'schemaVersion must be 1');
|
|
327
|
-
assertTemplateManifest(templateIdPattern.test(manifest.template.id), 'template.id must be a template id');
|
|
328
|
-
assertTemplateManifest(semverPattern.test(manifest.template.version), 'template.version must be exact semver');
|
|
329
|
-
assertTemplateManifest('ultramodern-mv' === manifest.template.compatibilityLane || 'ultramodern-shell' === manifest.template.compatibilityLane || 'ultramodern-remote' === manifest.template.compatibilityLane, 'template.compatibilityLane is unsupported');
|
|
330
|
-
if (manifest.template.minimumModernVersion) assertTemplateManifest(semverPattern.test(manifest.template.minimumModernVersion), 'template.minimumModernVersion must be exact semver');
|
|
331
|
-
validateTemplateSource(manifest.source);
|
|
332
|
-
assertTemplateManifest(manifest.integrity.checksums.length > 0, 'integrity.checksums must not be empty');
|
|
333
|
-
for (const checksum of manifest.integrity.checksums){
|
|
334
|
-
assertTemplateManifest('sha256' === checksum.algorithm, 'checksum algorithm must be sha256');
|
|
335
|
-
assertTemplateManifest(sha256Pattern.test(checksum.value), 'checksum value must be sha256 hex');
|
|
336
|
-
assertTemplateManifest('manifest' === checksum.scope || 'source-archive' === checksum.scope || 'source-tree' === checksum.scope || 'lockfile' === checksum.scope, 'checksum scope is unsupported');
|
|
337
|
-
}
|
|
338
|
-
assertTemplateManifest(manifest.integrity.provenance.kind && manifest.integrity.provenance.issuer && manifest.integrity.provenance.subject, 'provenance kind, issuer, and subject are required');
|
|
339
|
-
if (manifest.integrity.lockfile) {
|
|
340
|
-
assertSafeManifestPath(manifest.integrity.lockfile.path, 'lockfile path');
|
|
341
|
-
assertTemplateManifest(sha256Pattern.test(manifest.integrity.lockfile.sha256), 'lockfile sha256 must be sha256 hex');
|
|
342
|
-
}
|
|
343
|
-
assertTemplateManifest('generated-project-root' === manifest.materialization.targetRoot || 'workspace-package-root' === manifest.materialization.targetRoot, 'materialization.targetRoot is unsupported');
|
|
344
|
-
assertTemplateManifest(manifest.materialization.allowedPaths.length > 0, 'materialization.allowedPaths must not be empty');
|
|
345
|
-
for (const allowedPath of manifest.materialization.allowedPaths)assertSafeManifestPath(allowedPath.replace(/\/\*\*$/, '/placeholder'), 'allowed path');
|
|
346
|
-
for (const deniedPath of manifest.materialization.deniedPaths)assertSafeManifestPath(deniedPath.replace(/\/\*\*$/, '/placeholder'), 'denied path');
|
|
347
|
-
for (const deniedPath of requiredDeniedPaths)assertTemplateManifest(manifest.materialization.deniedPaths.includes(deniedPath), `materialization.deniedPaths must include ${deniedPath}`);
|
|
348
|
-
assertTemplateManifest(!manifest.materialization.overwritePolicy || 'deny-existing' === manifest.materialization.overwritePolicy || 'allow-generated-only' === manifest.materialization.overwritePolicy, 'materialization.overwritePolicy is unsupported');
|
|
349
|
-
assertTemplateManifest(true === manifest.lifecyclePolicy.denyByDefault, 'lifecyclePolicy.denyByDefault must be true');
|
|
350
|
-
for (const scriptName of requiredLifecycleDeniedScripts)assertTemplateManifest(manifest.lifecyclePolicy.deniedScripts.includes(scriptName), `lifecyclePolicy.deniedScripts must include ${scriptName}`);
|
|
351
|
-
assertTemplateManifest(JSON.stringify(manifest.lifecyclePolicy.allowedScripts) === JSON.stringify(requiredLifecycleAllowedScripts), 'lifecyclePolicy.allowedScripts must only allow generated postinstall');
|
|
352
|
-
assertTemplateManifest(true === manifest.validation.schemaValidation, 'validation.schemaValidation must be true');
|
|
353
|
-
for (const token of [
|
|
354
|
-
'source-type-supported',
|
|
355
|
-
'checksum-verified',
|
|
356
|
-
'provenance-present'
|
|
357
|
-
])assertTemplateManifest(manifest.validation.sourceValidation.includes(token), `validation.sourceValidation must include ${token}`);
|
|
358
|
-
for (const token of [
|
|
359
|
-
'path-boundary-allowlist',
|
|
360
|
-
'path-boundary-denylist',
|
|
361
|
-
'no-path-traversal',
|
|
362
|
-
'no-absolute-paths',
|
|
363
|
-
'overwrite-policy-enforced'
|
|
364
|
-
])assertTemplateManifest(manifest.validation.materializationValidation.includes(token), `validation.materializationValidation must include ${token}`);
|
|
365
|
-
assertTemplateManifest(manifest.validation.postMaterializationValidation.includes('template-manifest-retained'), 'validation.postMaterializationValidation must retain manifest evidence');
|
|
366
|
-
}
|
|
367
|
-
function matchesManifestPattern(pattern, relativePath) {
|
|
368
|
-
if (pattern.endsWith('/**')) {
|
|
369
|
-
const prefix = pattern.slice(0, -3);
|
|
370
|
-
return relativePath === prefix || relativePath.startsWith(`${prefix}/`);
|
|
371
|
-
}
|
|
372
|
-
if (pattern.endsWith('.*')) {
|
|
373
|
-
const prefix = pattern.slice(0, -1);
|
|
374
|
-
return relativePath.startsWith(prefix);
|
|
375
|
-
}
|
|
376
|
-
return relativePath === pattern;
|
|
377
|
-
}
|
|
378
|
-
function canMaterializePath(manifest, relativePath) {
|
|
379
|
-
if (isUnsafeRelativePath(relativePath)) throw new Error(`Unsafe template path rejected: ${relativePath}`);
|
|
380
|
-
if (manifest.materialization.deniedPaths.some((pattern)=>matchesManifestPattern(pattern, relativePath))) return false;
|
|
381
|
-
if (!manifest.materialization.allowedPaths.some((pattern)=>matchesManifestPattern(pattern, relativePath))) throw new Error(`Template path is not allowed by manifest: ${relativePath}`);
|
|
382
|
-
return true;
|
|
383
|
-
}
|
|
384
|
-
function writeTemplateManifestEvidence(targetDir, manifest) {
|
|
385
|
-
const evidencePath = node_path.join(targetDir, '.modernjs', 'mv-template-manifest.json');
|
|
386
|
-
const evidenceRelativePath = normalizePathForManifest(node_path.relative(targetDir, evidencePath));
|
|
387
|
-
if (!canMaterializePath(manifest, evidenceRelativePath)) throw new Error('Template manifest evidence path is denied by manifest');
|
|
388
|
-
node_fs.mkdirSync(node_path.dirname(evidencePath), {
|
|
389
|
-
recursive: true
|
|
390
|
-
});
|
|
391
|
-
node_fs.writeFileSync(evidencePath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
392
|
-
}
|
|
393
35
|
function readCreatePackageJson() {
|
|
394
36
|
const createPackageJson = node_path.join(createPackageRoot, 'package.json');
|
|
395
37
|
return JSON.parse(node_fs.readFileSync(createPackageJson, 'utf-8'));
|
|
@@ -420,31 +62,19 @@ function showHelp() {
|
|
|
420
62
|
console.log(i18n.t(localeKeys.help.optionHelp));
|
|
421
63
|
console.log(i18n.t(localeKeys.help.optionVersion));
|
|
422
64
|
console.log(i18n.t(localeKeys.help.optionLang));
|
|
423
|
-
console.log(i18n.t(localeKeys.help.optionRouter));
|
|
424
|
-
if (localeKeys.help.optionBff) console.log(i18n.t(localeKeys.help.optionBff));
|
|
425
|
-
if (localeKeys.help.optionBffRuntime) console.log(i18n.t(localeKeys.help.optionBffRuntime));
|
|
426
65
|
if (localeKeys.help.optionTailwind) console.log(i18n.t(localeKeys.help.optionTailwind));
|
|
427
|
-
if (localeKeys.help.optionWorkspace) console.log(i18n.t(localeKeys.help.optionWorkspace));
|
|
428
|
-
if (localeKeys.help.optionUltramodernWorkspace) console.log(i18n.t(localeKeys.help.optionUltramodernWorkspace));
|
|
429
66
|
if (localeKeys.help.optionUltramodernPackageSource) console.log(i18n.t(localeKeys.help.optionUltramodernPackageSource));
|
|
430
67
|
if (localeKeys.help.optionUltramodernPackageScope) console.log(i18n.t(localeKeys.help.optionUltramodernPackageScope));
|
|
431
68
|
if (localeKeys.help.optionUltramodernPackageNamePrefix) console.log(i18n.t(localeKeys.help.optionUltramodernPackageNamePrefix));
|
|
432
69
|
if (localeKeys.help.optionVertical) console.log(i18n.t(localeKeys.help.optionVertical));
|
|
433
70
|
if (localeKeys.help.optionLegacyModernJs) console.log(i18n.t(localeKeys.help.optionLegacyModernJs));
|
|
434
|
-
console.log(i18n.t(localeKeys.help.optionSub));
|
|
435
71
|
console.log('');
|
|
436
72
|
console.log(i18n.t(localeKeys.help.examples));
|
|
437
73
|
console.log(i18n.t(localeKeys.help.example1));
|
|
438
74
|
console.log(i18n.t(localeKeys.help.example2));
|
|
439
|
-
console.log(i18n.t(localeKeys.help.example3));
|
|
440
75
|
if (localeKeys.help.example4) console.log(i18n.t(localeKeys.help.example4));
|
|
441
76
|
if (localeKeys.help.example5) console.log(i18n.t(localeKeys.help.example5));
|
|
442
77
|
if (localeKeys.help.example6) console.log(i18n.t(localeKeys.help.example6));
|
|
443
|
-
if (localeKeys.help.example7) console.log(i18n.t(localeKeys.help.example7));
|
|
444
|
-
if (localeKeys.help.example8) console.log(i18n.t(localeKeys.help.example8));
|
|
445
|
-
if (localeKeys.help.example9) console.log(i18n.t(localeKeys.help.example9));
|
|
446
|
-
if (localeKeys.help.example10) console.log(i18n.t(localeKeys.help.example10));
|
|
447
|
-
if (localeKeys.help.example11) console.log(i18n.t(localeKeys.help.example11));
|
|
448
78
|
if (localeKeys.help.example12) console.log(i18n.t(localeKeys.help.example12));
|
|
449
79
|
console.log('');
|
|
450
80
|
console.log(i18n.t(localeKeys.help.moreInfo));
|
|
@@ -502,12 +132,6 @@ function delegateLegacyModernJsSetup(args) {
|
|
|
502
132
|
});
|
|
503
133
|
throw new Error('Legacy Modern.js setup requires pnpm or npx to run @modern-js/create.');
|
|
504
134
|
}
|
|
505
|
-
function detectSubprojectFlag() {
|
|
506
|
-
const args = process.argv.slice(2);
|
|
507
|
-
if (args.includes('--sub') || args.includes('-s')) return true;
|
|
508
|
-
if (args.includes('--no-sub')) return false;
|
|
509
|
-
return null;
|
|
510
|
-
}
|
|
511
135
|
function detectTailwindFlag() {
|
|
512
136
|
const args = process.argv.slice(2);
|
|
513
137
|
return !args.includes('--no-tailwind');
|
|
@@ -517,10 +141,6 @@ function detectExplicitTailwindFlag() {
|
|
|
517
141
|
if (args.includes('--no-tailwind')) return false;
|
|
518
142
|
if (args.includes('--tailwind')) return true;
|
|
519
143
|
}
|
|
520
|
-
function detectWorkspaceProtocolFlag() {
|
|
521
|
-
const args = process.argv.slice(2);
|
|
522
|
-
return args.includes('--workspace');
|
|
523
|
-
}
|
|
524
144
|
function detectVerticalFlag() {
|
|
525
145
|
const args = process.argv.slice(2);
|
|
526
146
|
if (args.some((arg)=>arg.startsWith('--vertical='))) {
|
|
@@ -529,10 +149,6 @@ function detectVerticalFlag() {
|
|
|
529
149
|
}
|
|
530
150
|
return args.includes('--vertical');
|
|
531
151
|
}
|
|
532
|
-
function detectUltramodernWorkspaceFlag() {
|
|
533
|
-
const args = process.argv.slice(2);
|
|
534
|
-
return args.includes(ULTRAMODERN_WORKSPACE_FLAG);
|
|
535
|
-
}
|
|
536
152
|
function detectUltramodernPackageSource(args, defaultPackageVersion, createPackage) {
|
|
537
153
|
const bleedingDevDefaults = isBleedingDevCreatePackage(createPackage);
|
|
538
154
|
const strategy = getOptionValue(args, [
|
|
@@ -613,14 +229,6 @@ function resolveInstallBackedPackageSource(args, createPackage, packageSource) {
|
|
|
613
229
|
]) ?? packageSource.aliasPackageNamePrefix ?? (aliasScope ? BLEEDINGDEV_PACKAGE_NAME_PREFIX : void 0)
|
|
614
230
|
};
|
|
615
231
|
}
|
|
616
|
-
function resolveSingleAppPackageSource(args, createPackage, packageSource, useWorkspaceProtocol) {
|
|
617
|
-
if (useWorkspaceProtocol) return {
|
|
618
|
-
...packageSource,
|
|
619
|
-
strategy: 'workspace',
|
|
620
|
-
modernPackageVersion: WORKSPACE_PACKAGE_VERSION
|
|
621
|
-
};
|
|
622
|
-
return resolveInstallBackedPackageSource(args, createPackage, packageSource);
|
|
623
|
-
}
|
|
624
232
|
function resolveWorkspacePackageSource(args, createPackage, packageSource) {
|
|
625
233
|
if (hasExplicitUltramodernPackageSource(args, 'workspace')) return {
|
|
626
234
|
...packageSource,
|
|
@@ -629,23 +237,6 @@ function resolveWorkspacePackageSource(args, createPackage, packageSource) {
|
|
|
629
237
|
};
|
|
630
238
|
return resolveInstallBackedPackageSource(args, createPackage, packageSource);
|
|
631
239
|
}
|
|
632
|
-
function createSingleAppPackageSourceEvidence(packageSource) {
|
|
633
|
-
return {
|
|
634
|
-
schemaVersion: 1,
|
|
635
|
-
preset: 'presetUltramodern',
|
|
636
|
-
strategy: packageSource.strategy,
|
|
637
|
-
modernPackages: createModernPackagesMetadata(ULTRAMODERN_SINGLE_APP_MODERN_PACKAGES, packageSource, {
|
|
638
|
-
includeAliases: 'install' === packageSource.strategy
|
|
639
|
-
})
|
|
640
|
-
};
|
|
641
|
-
}
|
|
642
|
-
function writeSingleAppPackageSourceEvidence(targetDir, packageSource) {
|
|
643
|
-
const evidencePath = node_path.join(targetDir, '.modernjs', 'ultramodern-package-source.json');
|
|
644
|
-
node_fs.mkdirSync(node_path.dirname(evidencePath), {
|
|
645
|
-
recursive: true
|
|
646
|
-
});
|
|
647
|
-
node_fs.writeFileSync(evidencePath, `${JSON.stringify(createSingleAppPackageSourceEvidence(packageSource), null, 2)}\n`);
|
|
648
|
-
}
|
|
649
240
|
function runSetupCommand(command, args, options = {}) {
|
|
650
241
|
return execFileSync(command, args, {
|
|
651
242
|
cwd: options.cwd,
|
|
@@ -745,9 +336,6 @@ async function getProjectName() {
|
|
|
745
336
|
const optionWithValue = new Set([
|
|
746
337
|
'--lang',
|
|
747
338
|
'-l',
|
|
748
|
-
'--router',
|
|
749
|
-
'-r',
|
|
750
|
-
'--bff-runtime',
|
|
751
339
|
'--ultramodern-package-source',
|
|
752
340
|
'--ultramodern-package-version',
|
|
753
341
|
'--ultramodern-package-registry',
|
|
@@ -759,17 +347,11 @@ async function getProjectName() {
|
|
|
759
347
|
'-h',
|
|
760
348
|
'--version',
|
|
761
349
|
'-v',
|
|
762
|
-
'--sub',
|
|
763
|
-
'-s',
|
|
764
|
-
'--no-sub',
|
|
765
|
-
'--tanstack',
|
|
766
|
-
'--bff',
|
|
767
350
|
'--tailwind',
|
|
768
351
|
'--no-tailwind',
|
|
769
352
|
'--workspace',
|
|
770
353
|
'--vertical',
|
|
771
|
-
LEGACY_MODERN_JS_FLAG
|
|
772
|
-
ULTRAMODERN_WORKSPACE_FLAG
|
|
354
|
+
LEGACY_MODERN_JS_FLAG
|
|
773
355
|
]);
|
|
774
356
|
const positionalArgs = [];
|
|
775
357
|
for(let i = 0; i < args.length; i++){
|
|
@@ -779,7 +361,7 @@ async function getProjectName() {
|
|
|
779
361
|
i += 1;
|
|
780
362
|
continue;
|
|
781
363
|
}
|
|
782
|
-
if (!(arg.startsWith('--lang=') || arg.startsWith('--
|
|
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);
|
|
783
365
|
}
|
|
784
366
|
}
|
|
785
367
|
if (positionalArgs.length > 1) {
|
|
@@ -841,7 +423,7 @@ async function main() {
|
|
|
841
423
|
const dim = '\x1b[2m\x1b[3m';
|
|
842
424
|
const reset = '\x1b[0m';
|
|
843
425
|
console.log(`${i18n.t(localeKeys.message.success)}\n`);
|
|
844
|
-
console.log(`${dim} pnpm
|
|
426
|
+
console.log(`${dim} pnpm check${reset}\n`);
|
|
845
427
|
return;
|
|
846
428
|
}
|
|
847
429
|
if (node_fs.existsSync(targetDir)) {
|
|
@@ -853,111 +435,15 @@ async function main() {
|
|
|
853
435
|
process.exit(1);
|
|
854
436
|
}
|
|
855
437
|
}
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
generateUltramodernWorkspace({
|
|
860
|
-
targetDir,
|
|
861
|
-
packageName: generatedPackageName,
|
|
862
|
-
modernVersion: version,
|
|
863
|
-
enableTailwind: detectTailwindFlag(),
|
|
864
|
-
packageSource
|
|
865
|
-
});
|
|
866
|
-
initializeGeneratedGitRepository(targetDir);
|
|
867
|
-
const dim = '\x1b[2m\x1b[3m';
|
|
868
|
-
const reset = '\x1b[0m';
|
|
869
|
-
console.log(`${i18n.t(localeKeys.message.success)}\n`);
|
|
870
|
-
console.log(i18n.t(localeKeys.message.nextSteps));
|
|
871
|
-
if (!useCurrentDir) console.log(`${dim} ${i18n.t(localeKeys.message.step1, {
|
|
872
|
-
projectName
|
|
873
|
-
})}${reset}`);
|
|
874
|
-
console.log(`${dim} ${i18n.t(localeKeys.message.step2)}${reset}`);
|
|
875
|
-
console.log(`${dim} pnpm ultramodern:check${reset}`);
|
|
876
|
-
console.log(`${dim} ${i18n.t(localeKeys.message.step3)}${reset}\n`);
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
const subprojectFlag = detectSubprojectFlag();
|
|
880
|
-
const isSubproject = true === subprojectFlag;
|
|
881
|
-
const routerFramework = detectRouterFramework();
|
|
882
|
-
const bffRuntime = detectBffRuntime();
|
|
883
|
-
const enableTailwind = detectTailwindFlag();
|
|
884
|
-
const useWorkspaceProtocol = detectWorkspaceProtocolFlag();
|
|
885
|
-
const packageSource = resolveSingleAppPackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage), useWorkspaceProtocol);
|
|
886
|
-
const templateManifest = createBuiltinTemplateManifest('install' === packageSource.strategy ? packageSource.modernPackageVersion : version);
|
|
887
|
-
validateTemplateManifest(templateManifest);
|
|
888
|
-
copyTemplate(templateDir, targetDir, {
|
|
438
|
+
const packageSource = resolveWorkspacePackageSource(args, createPackage, detectUltramodernPackageSource(args, ultramodernPackageVersion, createPackage));
|
|
439
|
+
generateUltramodernWorkspace({
|
|
440
|
+
targetDir,
|
|
889
441
|
packageName: generatedPackageName,
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
adapterRstestVersion: modernPackageSpecifier('@modern-js/adapter-rstest', packageSource),
|
|
894
|
-
codeToolsVersion: modernPackageSpecifier('@modern-js/code-tools', packageSource),
|
|
895
|
-
createVersion: modernPackageSpecifier('@modern-js/create', packageSource),
|
|
896
|
-
tsconfigVersion: modernPackageSpecifier('@modern-js/tsconfig', packageSource),
|
|
897
|
-
pluginTanstackVersion: modernPackageSpecifier('@modern-js/plugin-tanstack', packageSource),
|
|
898
|
-
pluginBffVersion: modernPackageSpecifier('@modern-js/plugin-bff', packageSource),
|
|
899
|
-
pluginI18nVersion: modernPackageSpecifier('@modern-js/plugin-i18n', packageSource),
|
|
900
|
-
tanstackRouterVersion: TANSTACK_ROUTER_VERSION,
|
|
901
|
-
i18nextVersion: I18NEXT_VERSION,
|
|
902
|
-
reactVersion: REACT_VERSION,
|
|
903
|
-
reactDomVersion: REACT_DOM_VERSION,
|
|
904
|
-
reactI18nextVersion: REACT_I18NEXT_VERSION,
|
|
905
|
-
effectTsgoVersion: EFFECT_TSGO_VERSION,
|
|
906
|
-
typescriptNativePreviewVersion: TYPESCRIPT_NATIVE_PREVIEW_VERSION,
|
|
907
|
-
rstestCoreVersion: RSTEST_CORE_VERSION,
|
|
908
|
-
happyDomVersion: HAPPY_DOM_VERSION,
|
|
909
|
-
oxfmtVersion: OXFMT_VERSION,
|
|
910
|
-
oxlintVersion: OXLINT_VERSION,
|
|
911
|
-
postcssVersion: POSTCSS_VERSION,
|
|
912
|
-
ultraciteVersion: ULTRACITE_VERSION,
|
|
913
|
-
typesReactVersion: TYPES_REACT_VERSION,
|
|
914
|
-
typesReactDomVersion: TYPES_REACT_DOM_VERSION,
|
|
915
|
-
tailwindVersion: TAILWIND_VERSION,
|
|
916
|
-
tailwindPostcssVersion: TAILWIND_POSTCSS_VERSION,
|
|
917
|
-
pnpmVersion: PNPM_VERSION,
|
|
918
|
-
isSubproject,
|
|
919
|
-
routerFramework,
|
|
920
|
-
bffRuntime,
|
|
921
|
-
enableTailwind,
|
|
922
|
-
templateManifest
|
|
442
|
+
modernVersion: version,
|
|
443
|
+
enableTailwind: detectTailwindFlag(),
|
|
444
|
+
packageSource
|
|
923
445
|
});
|
|
924
|
-
|
|
925
|
-
const packageJson = JSON.parse(node_fs.readFileSync(targetPackageJson, 'utf-8'));
|
|
926
|
-
packageJson.name = generatedPackageName;
|
|
927
|
-
packageJson.modernjs = {
|
|
928
|
-
...packageJson.modernjs ?? {},
|
|
929
|
-
preset: 'presetUltramodern',
|
|
930
|
-
packageSource: {
|
|
931
|
-
strategy: packageSource.strategy,
|
|
932
|
-
config: './.modernjs/ultramodern-package-source.json'
|
|
933
|
-
}
|
|
934
|
-
};
|
|
935
|
-
if (isSubproject) {
|
|
936
|
-
delete packageJson['lint-staged'];
|
|
937
|
-
delete packageJson['simple-git-hooks'];
|
|
938
|
-
if (packageJson.scripts) {
|
|
939
|
-
delete packageJson.scripts.prepare;
|
|
940
|
-
delete packageJson.scripts['skills:install'];
|
|
941
|
-
delete packageJson.scripts['skills:check'];
|
|
942
|
-
delete packageJson.scripts.postinstall;
|
|
943
|
-
}
|
|
944
|
-
if (packageJson.devDependencies) {
|
|
945
|
-
delete packageJson.devDependencies['lint-staged'];
|
|
946
|
-
delete packageJson.devDependencies.lefthook;
|
|
947
|
-
delete packageJson.devDependencies['simple-git-hooks'];
|
|
948
|
-
}
|
|
949
|
-
node_fs.rmSync(node_path.join(targetDir, '.codex'), {
|
|
950
|
-
recursive: true,
|
|
951
|
-
force: true
|
|
952
|
-
});
|
|
953
|
-
node_fs.rmSync(node_path.join(targetDir, 'lefthook.yml'), {
|
|
954
|
-
force: true
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
node_fs.writeFileSync(targetPackageJson, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
958
|
-
writeTemplateManifestEvidence(targetDir, templateManifest);
|
|
959
|
-
writeSingleAppPackageSourceEvidence(targetDir, packageSource);
|
|
960
|
-
if (!isSubproject) initializeGeneratedGitRepository(targetDir);
|
|
446
|
+
initializeGeneratedGitRepository(targetDir);
|
|
961
447
|
const dim = '\x1b[2m\x1b[3m';
|
|
962
448
|
const reset = '\x1b[0m';
|
|
963
449
|
console.log(`${i18n.t(localeKeys.message.success)}\n`);
|
|
@@ -966,88 +452,9 @@ async function main() {
|
|
|
966
452
|
projectName
|
|
967
453
|
})}${reset}`);
|
|
968
454
|
console.log(`${dim} ${i18n.t(localeKeys.message.step2)}${reset}`);
|
|
455
|
+
console.log(`${dim} pnpm check${reset}`);
|
|
969
456
|
console.log(`${dim} ${i18n.t(localeKeys.message.step3)}${reset}\n`);
|
|
970
457
|
}
|
|
971
|
-
function copyTemplate(src, dest, options) {
|
|
972
|
-
node_fs.mkdirSync(dest, {
|
|
973
|
-
recursive: true
|
|
974
|
-
});
|
|
975
|
-
const excludeInSubproject = [
|
|
976
|
-
'.agents',
|
|
977
|
-
'.github',
|
|
978
|
-
'.gitignore.handlebars',
|
|
979
|
-
'AGENTS.md',
|
|
980
|
-
'.npmrc',
|
|
981
|
-
'.nvmrc'
|
|
982
|
-
];
|
|
983
|
-
function copyRecursive(srcDir, destDir) {
|
|
984
|
-
const entries = node_fs.readdirSync(srcDir, {
|
|
985
|
-
withFileTypes: true
|
|
986
|
-
});
|
|
987
|
-
for (const entry of entries){
|
|
988
|
-
if (options.isSubproject && excludeInSubproject.includes(entry.name)) continue;
|
|
989
|
-
const srcPath = node_path.join(srcDir, entry.name);
|
|
990
|
-
let destPath = node_path.join(destDir, entry.name);
|
|
991
|
-
const sourceRelativePath = normalizePathForManifest(node_path.relative(src, srcPath));
|
|
992
|
-
const finalRelativePath = normalizePathForManifest(sourceRelativePath.replace(/\.handlebars$/, ''));
|
|
993
|
-
if (!(!canMaterializePath(options.templateManifest, finalRelativePath) || entry.isDirectory() && options.templateManifest.materialization.deniedPaths.some((pattern)=>matchesManifestPattern(pattern, finalRelativePath)))) if (entry.isDirectory()) {
|
|
994
|
-
node_fs.mkdirSync(destPath, {
|
|
995
|
-
recursive: true
|
|
996
|
-
});
|
|
997
|
-
copyRecursive(srcPath, destPath);
|
|
998
|
-
} else if (entry.name.endsWith('.handlebars')) {
|
|
999
|
-
const templateContent = node_fs.readFileSync(srcPath, 'utf-8');
|
|
1000
|
-
const rendered = renderTemplate(templateContent, {
|
|
1001
|
-
packageName: options.packageName,
|
|
1002
|
-
version: options.version,
|
|
1003
|
-
runtimeVersion: options.runtimeVersion,
|
|
1004
|
-
appToolsVersion: options.appToolsVersion,
|
|
1005
|
-
adapterRstestVersion: options.adapterRstestVersion,
|
|
1006
|
-
codeToolsVersion: options.codeToolsVersion,
|
|
1007
|
-
createVersion: options.createVersion,
|
|
1008
|
-
tsconfigVersion: options.tsconfigVersion,
|
|
1009
|
-
pluginTanstackVersion: options.pluginTanstackVersion,
|
|
1010
|
-
pluginBffVersion: options.pluginBffVersion,
|
|
1011
|
-
pluginI18nVersion: options.pluginI18nVersion,
|
|
1012
|
-
tanstackRouterVersion: options.tanstackRouterVersion,
|
|
1013
|
-
i18nextVersion: options.i18nextVersion,
|
|
1014
|
-
reactVersion: options.reactVersion,
|
|
1015
|
-
reactDomVersion: options.reactDomVersion,
|
|
1016
|
-
reactI18nextVersion: options.reactI18nextVersion,
|
|
1017
|
-
effectTsgoVersion: options.effectTsgoVersion,
|
|
1018
|
-
typescriptNativePreviewVersion: options.typescriptNativePreviewVersion,
|
|
1019
|
-
rstestCoreVersion: options.rstestCoreVersion,
|
|
1020
|
-
happyDomVersion: options.happyDomVersion,
|
|
1021
|
-
oxfmtVersion: options.oxfmtVersion,
|
|
1022
|
-
oxlintVersion: options.oxlintVersion,
|
|
1023
|
-
postcssVersion: options.postcssVersion,
|
|
1024
|
-
ultraciteVersion: options.ultraciteVersion,
|
|
1025
|
-
typesReactVersion: options.typesReactVersion,
|
|
1026
|
-
typesReactDomVersion: options.typesReactDomVersion,
|
|
1027
|
-
tailwindVersion: options.tailwindVersion,
|
|
1028
|
-
tailwindPostcssVersion: options.tailwindPostcssVersion,
|
|
1029
|
-
pnpmVersion: options.pnpmVersion,
|
|
1030
|
-
isSubproject: options.isSubproject,
|
|
1031
|
-
isTanstackRouter: 'tanstack' === options.routerFramework,
|
|
1032
|
-
enableBff: 'none' !== options.bffRuntime,
|
|
1033
|
-
useEffectBff: 'effect' === options.bffRuntime,
|
|
1034
|
-
useHonoBff: 'hono' === options.bffRuntime,
|
|
1035
|
-
bffRuntime: options.bffRuntime,
|
|
1036
|
-
enableTailwind: options.enableTailwind,
|
|
1037
|
-
routerRuntimeImport: 'tanstack' === options.routerFramework ? '@modern-js/plugin-tanstack/runtime' : '@modern-js/runtime/router'
|
|
1038
|
-
});
|
|
1039
|
-
if (0 === rendered.trim().length) continue;
|
|
1040
|
-
destPath = destPath.replace(/\.handlebars$/, '');
|
|
1041
|
-
if ('deny-existing' === options.templateManifest.materialization.overwritePolicy && node_fs.existsSync(destPath)) throw new Error(`Template refused to overwrite existing file: ${finalRelativePath}`);
|
|
1042
|
-
node_fs.writeFileSync(destPath, rendered, 'utf-8');
|
|
1043
|
-
} else {
|
|
1044
|
-
if ('deny-existing' === options.templateManifest.materialization.overwritePolicy && node_fs.existsSync(destPath)) throw new Error(`Template refused to overwrite existing file: ${finalRelativePath}`);
|
|
1045
|
-
node_fs.copyFileSync(srcPath, destPath);
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
copyRecursive(src, dest);
|
|
1050
|
-
}
|
|
1051
458
|
main().catch((error)=>{
|
|
1052
459
|
console.error(i18n.t(localeKeys.error.createFailed), error);
|
|
1053
460
|
process.exit(1);
|