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