@bleedingdev/modern-js-create 3.2.0-ultramodern.83 → 3.2.0-ultramodern.84
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/dist/index.js +25 -9
- package/package.json +3 -3
- package/template/AGENTS.md +1 -1
- package/template/oxfmt.config.ts +8 -1
- package/template/oxlint.config.ts +8 -1
- package/template/package.json.handlebars +2 -2
- package/template/pnpm-workspace.yaml +8 -0
- package/template/rstest.config.mts +1 -3
- package/template/scripts/bootstrap-agent-skills.mjs +74 -0
- package/template/scripts/check-i18n-strings.mjs +12 -1
- package/template/scripts/validate-ultramodern.mjs.handlebars +23 -21
- package/template/src/routes/[lang]/page.tsx.handlebars +4 -8
- package/template/tailwind.config.ts.handlebars +1 -1
package/dist/index.js
CHANGED
|
@@ -619,6 +619,19 @@ function sortJsonValue(value) {
|
|
|
619
619
|
return value;
|
|
620
620
|
}
|
|
621
621
|
const ULTRAMODERN_WORKSPACE_FLAG = '--ultramodern-workspace';
|
|
622
|
+
const FIRST_VERTICAL_PORT = 4101;
|
|
623
|
+
const TAILWIND_PREFIX_DIGIT_WORDS = [
|
|
624
|
+
'zero',
|
|
625
|
+
'one',
|
|
626
|
+
'two',
|
|
627
|
+
'three',
|
|
628
|
+
'four',
|
|
629
|
+
'five',
|
|
630
|
+
'six',
|
|
631
|
+
'seven',
|
|
632
|
+
'eight',
|
|
633
|
+
'nine'
|
|
634
|
+
];
|
|
622
635
|
function isRecord(value) {
|
|
623
636
|
return null !== value && 'object' == typeof value && !Array.isArray(value);
|
|
624
637
|
}
|
|
@@ -1115,6 +1128,7 @@ function createTsConfigBase() {
|
|
|
1115
1128
|
verbatimModuleSyntax: true,
|
|
1116
1129
|
strict: true,
|
|
1117
1130
|
noEmit: true,
|
|
1131
|
+
allowImportingTsExtensions: true,
|
|
1118
1132
|
allowJs: true,
|
|
1119
1133
|
esModuleInterop: true,
|
|
1120
1134
|
noUncheckedIndexedAccess: true,
|
|
@@ -1228,6 +1242,7 @@ function createAppModernConfig(scope, app) {
|
|
|
1228
1242
|
const bffImport = appHasEffectApi(app) ? "import { bffPlugin } from '@modern-js/plugin-bff';\n" : '';
|
|
1229
1243
|
const bffConfig = appHasEffectApi(app) ? ` bff: {
|
|
1230
1244
|
effect: {
|
|
1245
|
+
entry: './api/effect/index',
|
|
1231
1246
|
openapi: {
|
|
1232
1247
|
path: '/openapi.json',
|
|
1233
1248
|
},
|
|
@@ -1916,9 +1931,9 @@ function createCssTokenImport(scope) {
|
|
|
1916
1931
|
return `@import '${ultramodern_workspace_packageName(scope, 'shared-design-tokens')}/tokens.css';\n`;
|
|
1917
1932
|
}
|
|
1918
1933
|
function createTailwindPrefix(raw) {
|
|
1919
|
-
const
|
|
1920
|
-
if (!
|
|
1921
|
-
return
|
|
1934
|
+
const normalized = raw.toLowerCase().replace(/[^a-z0-9]/gu, '');
|
|
1935
|
+
if (!normalized) throw new Error(`Cannot derive a Tailwind prefix from ${raw}`);
|
|
1936
|
+
return normalized.replace(/[0-9]/gu, (digit)=>TAILWIND_PREFIX_DIGIT_WORDS[Number(digit)]);
|
|
1922
1937
|
}
|
|
1923
1938
|
function tailwindPrefixForApp(app) {
|
|
1924
1939
|
if ('shell' === app.kind) return 'shell';
|
|
@@ -3450,7 +3465,7 @@ function createEffectServiceEntry(scope, service, contractImportPath = ultramode
|
|
|
3450
3465
|
HttpApiBuilder,
|
|
3451
3466
|
Layer,
|
|
3452
3467
|
} from '@modern-js/plugin-bff/effect-edge';
|
|
3453
|
-
import { ultramodernApiMarker } from '../../src/ultramodern-build';
|
|
3468
|
+
import { ultramodernApiMarker } from '../../src/ultramodern-build.ts';
|
|
3454
3469
|
import {
|
|
3455
3470
|
${apiExport},
|
|
3456
3471
|
${groupName}OperationContexts,
|
|
@@ -4693,6 +4708,7 @@ function createWorkspaceValidationScript(scope, enableTailwind, remotes = []) {
|
|
|
4693
4708
|
mfName: remote.mfName,
|
|
4694
4709
|
apiPrefix: remote.effectApi.prefix,
|
|
4695
4710
|
tailwindPrefix: tailwindPrefixForApp(remote),
|
|
4711
|
+
zephyrAlias: remoteDependencyAlias(remote),
|
|
4696
4712
|
packageName: ultramodern_workspace_packageName(scope, remote.packageSuffix),
|
|
4697
4713
|
exposes: Object.keys(remote.exposes ?? {}),
|
|
4698
4714
|
componentPaths: Object.keys(remote.exposes ?? {}).map((expose)=>remoteComponentOutputPath(remote, expose)).filter((componentPath)=>Boolean(componentPath)),
|
|
@@ -4881,7 +4897,7 @@ assert(generatedContract.cssFederation?.sharedDesignTokens?.ssr?.firstPaintRequi
|
|
|
4881
4897
|
const shellPackage = readJson('apps/shell-super-app/package.json');
|
|
4882
4898
|
const expectedZephyrDependencies = Object.fromEntries(
|
|
4883
4899
|
fullStackVerticals.map(vertical => [
|
|
4884
|
-
vertical.
|
|
4900
|
+
vertical.zephyrAlias,
|
|
4885
4901
|
\`\${vertical.packageName}@workspace:*\`,
|
|
4886
4902
|
]),
|
|
4887
4903
|
);
|
|
@@ -4925,7 +4941,7 @@ for (const vertical of fullStackVerticals) {
|
|
|
4925
4941
|
fullStackVerticals
|
|
4926
4942
|
.filter(candidate => vertical.verticalRefs.includes(candidate.id))
|
|
4927
4943
|
.map(candidate => [
|
|
4928
|
-
candidate.
|
|
4944
|
+
candidate.zephyrAlias,
|
|
4929
4945
|
\`\${candidate.packageName}@workspace:*\`,
|
|
4930
4946
|
]),
|
|
4931
4947
|
);
|
|
@@ -4968,7 +4984,7 @@ for (const vertical of fullStackVerticals) {
|
|
|
4968
4984
|
assert(contractEntry?.styling?.federation?.owner?.id === vertical.id, \`\${vertical.id} CSS federation owner is missing\`);
|
|
4969
4985
|
assert(contractEntry?.styling?.federation?.role === 'vertical-css', \`\${vertical.id} must own only vertical CSS\`);
|
|
4970
4986
|
assert(contractEntry?.styling?.federation?.rootSelector === \`[data-app-id="\${vertical.id}"]\`, \`\${vertical.id} CSS root selector is incorrect\`);
|
|
4971
|
-
assert(contractEntry?.styling?.federation?.classPrefix === \`\${vertical.
|
|
4987
|
+
assert(contractEntry?.styling?.federation?.classPrefix === \`\${vertical.tailwindPrefix}:\`, \`\${vertical.id} CSS class prefix is incorrect\`);
|
|
4972
4988
|
assert(contractEntry?.styling?.federation?.layers?.owned?.includes(\`ultramodern-vertical-\${vertical.domain}\`), \`\${vertical.id} vertical CSS layer is missing\`);
|
|
4973
4989
|
assert(!contractEntry?.styling?.federation?.layers?.owned?.includes('ultramodern-shell-base'), \`\${vertical.id} must not own shell base CSS\`);
|
|
4974
4990
|
assert(contractEntry?.styling?.federation?.entrypoints?.federationEntry === 'src/federation-entry.tsx', \`\${vertical.id} CSS contract must include federation entry\`);
|
|
@@ -5372,7 +5388,7 @@ function writeApp(targetDir, scope, app, packageSource, enableTailwind, remotes
|
|
|
5372
5388
|
}
|
|
5373
5389
|
if (appHasEffectApi(resolvedApp)) {
|
|
5374
5390
|
writeFile(targetDir, `${resolvedApp.directory}/shared/effect/api.ts`, createEffectSharedApi(resolvedApp));
|
|
5375
|
-
writeFile(targetDir, `${resolvedApp.directory}/api/effect/index.ts`, createEffectServiceEntry(scope, resolvedApp, '../../shared/effect/api'));
|
|
5391
|
+
writeFile(targetDir, `${resolvedApp.directory}/api/effect/index.ts`, createEffectServiceEntry(scope, resolvedApp, '../../shared/effect/api.ts'));
|
|
5376
5392
|
writeFile(targetDir, `${resolvedApp.directory}/src/effect/${resolvedApp.effectApi.stem}-client.ts`, createEffectClient(resolvedApp, '../../shared/effect/api'));
|
|
5377
5393
|
}
|
|
5378
5394
|
if ('vertical' === resolvedApp.kind) {
|
|
@@ -5462,7 +5478,7 @@ function assertValidVerticalName(name) {
|
|
|
5462
5478
|
}
|
|
5463
5479
|
function nextAvailablePort(ports) {
|
|
5464
5480
|
const numericPorts = Object.values(ports).filter((value)=>'number' == typeof value && Number.isFinite(value));
|
|
5465
|
-
return Math.max(
|
|
5481
|
+
return Math.max(FIRST_VERTICAL_PORT - 1, ...numericPorts) + 1;
|
|
5466
5482
|
}
|
|
5467
5483
|
function assertCanCreate(workspaceRoot, relativePath) {
|
|
5468
5484
|
if (node_fs.existsSync(node_path.join(workspaceRoot, relativePath))) throw new Error(`Refusing to overwrite existing path: ${relativePath}`);
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
24
|
-
"version": "3.2.0-ultramodern.
|
|
24
|
+
"version": "3.2.0-ultramodern.84",
|
|
25
25
|
"types": "./dist/types/index.d.ts",
|
|
26
26
|
"main": "./dist/index.js",
|
|
27
27
|
"bin": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@types/node": "^25.9.1",
|
|
42
42
|
"@typescript/native-preview": "7.0.0-dev.20260527.2",
|
|
43
43
|
"tsx": "^4.22.3",
|
|
44
|
-
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.
|
|
44
|
+
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.84"
|
|
45
45
|
},
|
|
46
46
|
"publishConfig": {
|
|
47
47
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -54,6 +54,6 @@
|
|
|
54
54
|
"start": "node ./dist/index.js"
|
|
55
55
|
},
|
|
56
56
|
"ultramodern": {
|
|
57
|
-
"frameworkVersion": "3.2.0-ultramodern.
|
|
57
|
+
"frameworkVersion": "3.2.0-ultramodern.84"
|
|
58
58
|
}
|
|
59
59
|
}
|
package/template/AGENTS.md
CHANGED
|
@@ -10,7 +10,7 @@ This project is generated for Codex-first UltraModern.js work.
|
|
|
10
10
|
- `pnpm i18n:check` rejects hardcoded user-visible JSX text.
|
|
11
11
|
- `pnpm ultramodern:check` verifies the generated contract.
|
|
12
12
|
- Generated Codex stop hooks and subagent-stop hooks run `pnpm format && pnpm lint:fix && pnpm ultramodern:check`.
|
|
13
|
-
- `postinstall` installs
|
|
13
|
+
- `postinstall` formats the generated tree, installs private orchestration skills when available, initializes a Git repository when needed, and installs `lefthook`. Generated `lefthook.yml` runs `pnpm format && pnpm lint:fix && pnpm ultramodern:check` on pre-commit; pre-push runs `pnpm ultramodern:check`.
|
|
14
14
|
|
|
15
15
|
## Internationalization
|
|
16
16
|
|
package/template/oxfmt.config.ts
CHANGED
|
@@ -3,6 +3,13 @@ import ultracite from 'ultracite/oxfmt';
|
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
5
|
extends: [ultracite],
|
|
6
|
-
ignorePatterns: [
|
|
6
|
+
ignorePatterns: [
|
|
7
|
+
'.agents',
|
|
8
|
+
'dist',
|
|
9
|
+
'node_modules',
|
|
10
|
+
'.modern',
|
|
11
|
+
'.modernjs',
|
|
12
|
+
'**/routeTree.gen.ts',
|
|
13
|
+
],
|
|
7
14
|
singleQuote: true,
|
|
8
15
|
});
|
|
@@ -8,5 +8,12 @@ export default defineConfig({
|
|
|
8
8
|
node: true,
|
|
9
9
|
},
|
|
10
10
|
extends: [core, react],
|
|
11
|
-
ignorePatterns: [
|
|
11
|
+
ignorePatterns: [
|
|
12
|
+
'.agents',
|
|
13
|
+
'dist',
|
|
14
|
+
'node_modules',
|
|
15
|
+
'.modern',
|
|
16
|
+
'.modernjs',
|
|
17
|
+
'**/routeTree.gen.ts',
|
|
18
|
+
],
|
|
12
19
|
});
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
{{#unless isSubproject}}
|
|
16
16
|
"skills:install": "node ./scripts/bootstrap-agent-skills.mjs",
|
|
17
17
|
"skills:check": "node ./scripts/bootstrap-agent-skills.mjs --check",
|
|
18
|
-
"postinstall": "node ./scripts/bootstrap-agent-skills.mjs
|
|
18
|
+
"postinstall": "oxfmt . && node ./scripts/bootstrap-agent-skills.mjs",
|
|
19
19
|
{{/unless}}
|
|
20
20
|
"ultramodern:check": "{{#unless isSubproject}}pnpm format:check && pnpm lint && {{/unless}}pnpm typecheck && pnpm i18n:check && pnpm test{{#unless isSubproject}} && pnpm skills:check{{/unless}} && node ./scripts/validate-ultramodern.mjs"{{#unless isSubproject}},
|
|
21
21
|
"format": "oxfmt .",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@modern-js/app-tools": "{{appToolsVersion}}",
|
|
42
42
|
{{#if enableBff}} "@modern-js/plugin-bff": "{{pluginBffVersion}}",
|
|
43
43
|
{{/if}} "@modern-js/tsconfig": "{{tsconfigVersion}}",
|
|
44
|
-
"@rstest/core": "0.10.
|
|
44
|
+
"@rstest/core": "0.10.3",
|
|
45
45
|
{{#if enableTailwind}}
|
|
46
46
|
"@tailwindcss/postcss": "^{{tailwindPostcssVersion}}",
|
|
47
47
|
{{/if}}
|
|
@@ -17,6 +17,76 @@ const run = (command, args, options = {}) =>
|
|
|
17
17
|
stdio: options.stdio ?? ['ignore', 'pipe', 'pipe'],
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
+
const commandExists = (command) => {
|
|
21
|
+
try {
|
|
22
|
+
run(command, ['--version'], { stdio: 'ignore' });
|
|
23
|
+
return true;
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const runShell = (script) =>
|
|
30
|
+
run('sh', ['-lc', script], {
|
|
31
|
+
stdio: 'inherit',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const installGit = () => {
|
|
35
|
+
if (commandExists('git')) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (commandExists('brew')) {
|
|
40
|
+
run('brew', ['install', 'git'], { stdio: 'inherit' });
|
|
41
|
+
} else if (process.platform === 'linux' && commandExists('apt-get')) {
|
|
42
|
+
const sudo = typeof process.getuid === 'function' && process.getuid() === 0 ? '' : 'sudo ';
|
|
43
|
+
runShell(`${sudo}apt-get update && ${sudo}apt-get install -y git`);
|
|
44
|
+
} else if (process.platform === 'linux' && commandExists('dnf')) {
|
|
45
|
+
const sudo = typeof process.getuid === 'function' && process.getuid() === 0 ? '' : 'sudo ';
|
|
46
|
+
runShell(`${sudo}dnf install -y git`);
|
|
47
|
+
} else if (process.platform === 'linux' && commandExists('yum')) {
|
|
48
|
+
const sudo = typeof process.getuid === 'function' && process.getuid() === 0 ? '' : 'sudo ';
|
|
49
|
+
runShell(`${sudo}yum install -y git`);
|
|
50
|
+
} else if (process.platform === 'linux' && commandExists('apk')) {
|
|
51
|
+
runShell('apk add --no-cache git');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!commandExists('git')) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
'Git is required for UltraModern setup. Install git and run pnpm skills:install again.',
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const isInsideGitWorkTree = () => {
|
|
62
|
+
try {
|
|
63
|
+
return run('git', ['rev-parse', '--is-inside-work-tree']).trim() === 'true';
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const initializeGitRepository = () => {
|
|
70
|
+
if (isInsideGitWorkTree()) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
run('git', ['init', '-b', 'main'], { stdio: 'inherit' });
|
|
76
|
+
} catch {
|
|
77
|
+
run('git', ['init'], { stdio: 'inherit' });
|
|
78
|
+
run('git', ['branch', '-M', 'main'], { stdio: 'inherit' });
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const installLefthook = () => {
|
|
83
|
+
try {
|
|
84
|
+
run('lefthook', ['install'], { stdio: 'inherit' });
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.warn(`Unable to install lefthook hooks: ${error.message}`);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
20
90
|
const removeTree = (dir) =>
|
|
21
91
|
fs.rmSync(dir, {
|
|
22
92
|
force: true,
|
|
@@ -98,6 +168,7 @@ if (checkOnly) {
|
|
|
98
168
|
}
|
|
99
169
|
|
|
100
170
|
fs.mkdirSync(installDir, { recursive: true });
|
|
171
|
+
installGit();
|
|
101
172
|
|
|
102
173
|
for (const source of [...requiredCloneSources, ...optionalCloneSources]) {
|
|
103
174
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ultramodern-skills-'));
|
|
@@ -133,3 +204,6 @@ for (const source of [...requiredCloneSources, ...optionalCloneSources]) {
|
|
|
133
204
|
removeTree(tempDir);
|
|
134
205
|
}
|
|
135
206
|
}
|
|
207
|
+
|
|
208
|
+
initializeGitRepository();
|
|
209
|
+
installLefthook();
|
|
@@ -30,6 +30,13 @@ const collectFiles = (directory) => {
|
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
const lineNumberForIndex = (content, index) => content.slice(0, index).split('\n').length;
|
|
33
|
+
const isCodeElementText = (content, index) => {
|
|
34
|
+
const tagStart = content.lastIndexOf('<', index);
|
|
35
|
+
if (tagStart === -1) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return /^<code(?:\s|>)/u.test(content.slice(tagStart, index));
|
|
39
|
+
};
|
|
33
40
|
const isIgnoredLine = (content, index) => {
|
|
34
41
|
const lineStart = content.lastIndexOf('\n', index) + 1;
|
|
35
42
|
const lineEnd = content.indexOf('\n', index);
|
|
@@ -58,7 +65,11 @@ for (const filePath of scanRoots.flatMap(collectFiles)) {
|
|
|
58
65
|
|
|
59
66
|
for (const match of content.matchAll(jsxTextPattern)) {
|
|
60
67
|
const text = match[1].replaceAll(/\s+/gu, ' ').trim();
|
|
61
|
-
if (
|
|
68
|
+
if (
|
|
69
|
+
text &&
|
|
70
|
+
!isIgnoredLine(content, match.index ?? 0) &&
|
|
71
|
+
!isCodeElementText(content, match.index ?? 0)
|
|
72
|
+
) {
|
|
62
73
|
violations.push({
|
|
63
74
|
filePath,
|
|
64
75
|
line: lineNumberForIndex(content, match.index ?? 0),
|
|
@@ -9,21 +9,19 @@ const packageSourcePath = path.resolve(
|
|
|
9
9
|
'.modernjs/ultramodern-package-source.json',
|
|
10
10
|
);
|
|
11
11
|
const readPnpmConfig = (key) => {
|
|
12
|
-
const env =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
12
|
+
const env = Object.fromEntries(
|
|
13
|
+
Object.entries(process.env).filter(
|
|
14
|
+
([envKey]) => !/^(?:npm|pnpm)_config_/iu.test(envKey),
|
|
15
|
+
),
|
|
16
|
+
);
|
|
18
17
|
const output = execFileSync('pnpm', ['config', 'get', key, '--json'], {
|
|
19
18
|
cwd: process.cwd(),
|
|
20
|
-
env,
|
|
21
19
|
encoding: 'utf-8',
|
|
20
|
+
env,
|
|
22
21
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
23
22
|
}).trim();
|
|
24
23
|
return output ? JSON.parse(output) : undefined;
|
|
25
24
|
};
|
|
26
|
-
const isSubproject = {{isSubproject}};
|
|
27
25
|
const enableTailwind = {{enableTailwind}};
|
|
28
26
|
const expectedPnpmVersion = '{{pnpmVersion}}';
|
|
29
27
|
const activePnpmVersion = execFileSync('pnpm', ['--version'], {
|
|
@@ -131,14 +129,13 @@ if (fs.existsSync(path.resolve(process.cwd(), 'src/routes/page.tsx'))) {
|
|
|
131
129
|
process.exit(1);
|
|
132
130
|
}
|
|
133
131
|
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
fs.existsSync(path.resolve(process.cwd(), 'tailwind.config.ts'))
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
132
|
+
if (
|
|
133
|
+
!enableTailwind &&
|
|
134
|
+
(fs.existsSync(path.resolve(process.cwd(), 'postcss.config.mjs')) ||
|
|
135
|
+
fs.existsSync(path.resolve(process.cwd(), 'tailwind.config.ts')))
|
|
136
|
+
) {
|
|
137
|
+
console.error('Tailwind config files must not be written when Tailwind is disabled');
|
|
138
|
+
process.exit(1);
|
|
142
139
|
}
|
|
143
140
|
|
|
144
141
|
{{#unless isSubproject}}
|
|
@@ -259,17 +256,19 @@ const skillsLock = JSON.parse(
|
|
|
259
256
|
);
|
|
260
257
|
{{/unless}}
|
|
261
258
|
const requiredScripts = {
|
|
262
|
-
'i18n:check': 'node ./scripts/check-i18n-strings.mjs',
|
|
263
|
-
test: 'rstest run',
|
|
264
259
|
{{#unless isSubproject}}
|
|
265
260
|
format: 'oxfmt .',
|
|
266
261
|
'format:check': 'oxfmt --check .',
|
|
262
|
+
{{/unless}}
|
|
263
|
+
'i18n:check': 'node ./scripts/check-i18n-strings.mjs',
|
|
264
|
+
{{#unless isSubproject}}
|
|
267
265
|
lint: 'oxlint .',
|
|
268
266
|
'lint:fix': 'oxlint . --fix',
|
|
267
|
+
postinstall: 'oxfmt . && node ./scripts/bootstrap-agent-skills.mjs',
|
|
269
268
|
'skills:check': 'node ./scripts/bootstrap-agent-skills.mjs --check',
|
|
270
269
|
'skills:install': 'node ./scripts/bootstrap-agent-skills.mjs',
|
|
271
|
-
postinstall: 'node ./scripts/bootstrap-agent-skills.mjs && (git rev-parse --is-inside-work-tree >/dev/null 2>&1 && lefthook install || true)',
|
|
272
270
|
{{/unless}}
|
|
271
|
+
test: 'rstest run',
|
|
273
272
|
};
|
|
274
273
|
|
|
275
274
|
for (const [scriptName, scriptCommand] of Object.entries(requiredScripts)) {
|
|
@@ -369,8 +368,11 @@ if (
|
|
|
369
368
|
console.error('pnpm allowBuilds must approve only the generated app build dependencies');
|
|
370
369
|
process.exit(1);
|
|
371
370
|
}
|
|
372
|
-
if (
|
|
373
|
-
|
|
371
|
+
if (
|
|
372
|
+
JSON.stringify(readPnpmConfig('onlyBuiltDependencies')) !==
|
|
373
|
+
JSON.stringify(['@swc/core', 'core-js', 'esbuild', 'lefthook', 'msgpackr-extract', 'sharp', 'workerd'])
|
|
374
|
+
) {
|
|
375
|
+
console.error('pnpm onlyBuiltDependencies must approve only the generated app build dependencies');
|
|
374
376
|
process.exit(1);
|
|
375
377
|
}
|
|
376
378
|
|
|
@@ -121,16 +121,12 @@ const Index = () => {
|
|
|
121
121
|
<p className="name">{t('home.name')}</p>
|
|
122
122
|
</div>
|
|
123
123
|
<p className="description{{#if enableTailwind}} text-emerald-700 font-semibold{{/if}}">
|
|
124
|
-
{t('home.description.intro')}
|
|
125
|
-
{
|
|
124
|
+
{t('home.description.intro')}{' '}
|
|
125
|
+
<code className="code">presetUltramodern(...)</code>{' '}
|
|
126
126
|
{t('home.description.afterPreset')}{' '}
|
|
127
|
-
<code className="code">modern.config.ts</code>
|
|
128
|
-
{/* i18n-ignore technical token */}
|
|
129
|
-
{' '}
|
|
127
|
+
<code className="code">modern.config.ts</code>{' '}
|
|
130
128
|
{t('home.description.afterConfig')}{' '}
|
|
131
|
-
<code className="code">pnpm run ultramodern:check</code>
|
|
132
|
-
{/* i18n-ignore technical token */}
|
|
133
|
-
{' '}
|
|
129
|
+
<code className="code">pnpm run ultramodern:check</code>{' '}
|
|
134
130
|
{t('home.description.end')}
|
|
135
131
|
</p>
|
|
136
132
|
{{#if useEffectBff}}
|