@bleedingdev/modern-js-create 3.4.0-ultramodern.2 → 3.4.0-ultramodern.3
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/cjs/ultramodern-workspace/contracts.cjs +2 -0
- package/dist/cjs/ultramodern-workspace/demo-components.cjs +9 -18
- package/dist/esm/ultramodern-workspace/contracts.js +2 -0
- package/dist/esm/ultramodern-workspace/demo-components.js +9 -18
- package/dist/esm-node/ultramodern-workspace/contracts.js +2 -0
- package/dist/esm-node/ultramodern-workspace/demo-components.js +9 -18
- package/package.json +3 -3
- package/template-workspace/pnpm-workspace.yaml.handlebars +8 -0
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +19 -2
- package/templates/app/shell-frame.tsx +1 -2
- package/templates/app/ultramodern-route-head.tsx.handlebars +3 -4
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +62 -0
|
@@ -719,6 +719,7 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
719
719
|
'pnpm-workspace.yaml',
|
|
720
720
|
"scripts/**",
|
|
721
721
|
'topology/**',
|
|
722
|
+
'tsconfig.json',
|
|
722
723
|
'tsconfig.base.json'
|
|
723
724
|
],
|
|
724
725
|
deniedPaths: [
|
|
@@ -783,6 +784,7 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
783
784
|
expectedCommands: [
|
|
784
785
|
'mise install',
|
|
785
786
|
'pnpm install',
|
|
787
|
+
'pnpm run typecheck',
|
|
786
788
|
'pnpm run i18n:boundaries',
|
|
787
789
|
'pnpm run contract:check',
|
|
788
790
|
'pnpm run performance:readiness'
|
|
@@ -49,8 +49,7 @@ import { VerticalShowcase } from '../vertical-components';
|
|
|
49
49
|
import { ultramodernUiMarker } from '../../ultramodern-build';
|
|
50
50
|
|
|
51
51
|
export default function ShellHome() {
|
|
52
|
-
const {
|
|
53
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
52
|
+
const { t } = useModernI18n();
|
|
54
53
|
|
|
55
54
|
return (
|
|
56
55
|
<ShellFrame>
|
|
@@ -123,8 +122,7 @@ const loadRemoteComponent = (specifier: string) =>
|
|
|
123
122
|
|
|
124
123
|
const createRemoteFallback = (specifier: string) =>
|
|
125
124
|
({ error }: { error: Error }) => {
|
|
126
|
-
const {
|
|
127
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
125
|
+
const { t } = useModernI18n();
|
|
128
126
|
const classification = classifyModuleFederationFallback(error);
|
|
129
127
|
const telemetry = createModuleFederationFallbackTelemetry({
|
|
130
128
|
appName: '${external_descriptors_cjs_namespaceObject.shellApp.id}',
|
|
@@ -206,8 +204,7 @@ const createHydratedRemote =
|
|
|
206
204
|
${hydratedExports}
|
|
207
205
|
|
|
208
206
|
export const Header = () => {
|
|
209
|
-
const {
|
|
210
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
207
|
+
const { t } = useModernI18n();
|
|
211
208
|
|
|
212
209
|
return (
|
|
213
210
|
<header className="${tw('flex min-w-0 flex-wrap items-center gap-x-8 gap-y-2 md:flex-1')}" data-modern-boundary-id="${external_descriptors_cjs_namespaceObject.shellApp.mfName}" data-modern-mf-expose="shell/Header">
|
|
@@ -217,8 +214,7 @@ const createHydratedRemote =
|
|
|
217
214
|
};
|
|
218
215
|
|
|
219
216
|
export const StatusBadge = () => {
|
|
220
|
-
const {
|
|
221
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
217
|
+
const { t } = useModernI18n();
|
|
222
218
|
|
|
223
219
|
return (
|
|
224
220
|
<span className="${tw('inline-flex h-10 shrink-0 items-center justify-center rounded-full border border-stone-900/15 bg-white px-4 text-sm font-extrabold text-stone-950 shadow-lg shadow-stone-900/5')}">
|
|
@@ -228,8 +224,7 @@ export const StatusBadge = () => {
|
|
|
228
224
|
};
|
|
229
225
|
|
|
230
226
|
export const VerticalShowcase = () => {
|
|
231
|
-
const {
|
|
232
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
227
|
+
const { t } = useModernI18n();
|
|
233
228
|
|
|
234
229
|
if (widgetCount === 0) {
|
|
235
230
|
return (
|
|
@@ -296,8 +291,7 @@ import { ultramodernUiMarker } from '../../ultramodern-build';
|
|
|
296
291
|
` : '';
|
|
297
292
|
return `${effectBffImport}
|
|
298
293
|
export default function ${(0, external_naming_cjs_namespaceObject.toPascalCase)(app.id)}Home() {
|
|
299
|
-
const {
|
|
300
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
294
|
+
const { language, supportedLanguages, t } = useModernI18n();
|
|
301
295
|
${effectBffState} return (
|
|
302
296
|
<main className="${tw('min-h-screen bg-um-canvas px-4 py-6 text-um-foreground sm:px-8')}">
|
|
303
297
|
<UltramodernRouteHead />
|
|
@@ -343,8 +337,7 @@ function createRemoteEntry(app) {
|
|
|
343
337
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
344
338
|
|
|
345
339
|
export default function ${(0, external_naming_cjs_namespaceObject.toPascalCase)(domain)}Route() {
|
|
346
|
-
const {
|
|
347
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
340
|
+
const { t } = useModernI18n();
|
|
348
341
|
|
|
349
342
|
return (
|
|
350
343
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="./Route">
|
|
@@ -362,8 +355,7 @@ function createRemoteWidget(app) {
|
|
|
362
355
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
363
356
|
|
|
364
357
|
export default function ${componentName}() {
|
|
365
|
-
const {
|
|
366
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
358
|
+
const { t } = useModernI18n();
|
|
367
359
|
|
|
368
360
|
return (
|
|
369
361
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="./Widget">
|
|
@@ -382,8 +374,7 @@ function createRemoteExposeComponent(app, expose) {
|
|
|
382
374
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
383
375
|
|
|
384
376
|
export default function ${componentName}() {
|
|
385
|
-
const {
|
|
386
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
377
|
+
const { t } = useModernI18n();
|
|
387
378
|
|
|
388
379
|
return (
|
|
389
380
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="${expose}">
|
|
@@ -668,6 +668,7 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
668
668
|
'pnpm-workspace.yaml',
|
|
669
669
|
"scripts/**",
|
|
670
670
|
'topology/**',
|
|
671
|
+
'tsconfig.json',
|
|
671
672
|
'tsconfig.base.json'
|
|
672
673
|
],
|
|
673
674
|
deniedPaths: [
|
|
@@ -732,6 +733,7 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
732
733
|
expectedCommands: [
|
|
733
734
|
'mise install',
|
|
734
735
|
'pnpm install',
|
|
736
|
+
'pnpm run typecheck',
|
|
735
737
|
'pnpm run i18n:boundaries',
|
|
736
738
|
'pnpm run contract:check',
|
|
737
739
|
'pnpm run performance:readiness'
|
|
@@ -10,8 +10,7 @@ import { VerticalShowcase } from '../vertical-components';
|
|
|
10
10
|
import { ultramodernUiMarker } from '../../ultramodern-build';
|
|
11
11
|
|
|
12
12
|
export default function ShellHome() {
|
|
13
|
-
const {
|
|
14
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
13
|
+
const { t } = useModernI18n();
|
|
15
14
|
|
|
16
15
|
return (
|
|
17
16
|
<ShellFrame>
|
|
@@ -84,8 +83,7 @@ const loadRemoteComponent = (specifier: string) =>
|
|
|
84
83
|
|
|
85
84
|
const createRemoteFallback = (specifier: string) =>
|
|
86
85
|
({ error }: { error: Error }) => {
|
|
87
|
-
const {
|
|
88
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
86
|
+
const { t } = useModernI18n();
|
|
89
87
|
const classification = classifyModuleFederationFallback(error);
|
|
90
88
|
const telemetry = createModuleFederationFallbackTelemetry({
|
|
91
89
|
appName: '${shellApp.id}',
|
|
@@ -167,8 +165,7 @@ const createHydratedRemote =
|
|
|
167
165
|
${hydratedExports}
|
|
168
166
|
|
|
169
167
|
export const Header = () => {
|
|
170
|
-
const {
|
|
171
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
168
|
+
const { t } = useModernI18n();
|
|
172
169
|
|
|
173
170
|
return (
|
|
174
171
|
<header className="${tw('flex min-w-0 flex-wrap items-center gap-x-8 gap-y-2 md:flex-1')}" data-modern-boundary-id="${shellApp.mfName}" data-modern-mf-expose="shell/Header">
|
|
@@ -178,8 +175,7 @@ const createHydratedRemote =
|
|
|
178
175
|
};
|
|
179
176
|
|
|
180
177
|
export const StatusBadge = () => {
|
|
181
|
-
const {
|
|
182
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
178
|
+
const { t } = useModernI18n();
|
|
183
179
|
|
|
184
180
|
return (
|
|
185
181
|
<span className="${tw('inline-flex h-10 shrink-0 items-center justify-center rounded-full border border-stone-900/15 bg-white px-4 text-sm font-extrabold text-stone-950 shadow-lg shadow-stone-900/5')}">
|
|
@@ -189,8 +185,7 @@ export const StatusBadge = () => {
|
|
|
189
185
|
};
|
|
190
186
|
|
|
191
187
|
export const VerticalShowcase = () => {
|
|
192
|
-
const {
|
|
193
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
188
|
+
const { t } = useModernI18n();
|
|
194
189
|
|
|
195
190
|
if (widgetCount === 0) {
|
|
196
191
|
return (
|
|
@@ -257,8 +252,7 @@ import { ultramodernUiMarker } from '../../ultramodern-build';
|
|
|
257
252
|
` : '';
|
|
258
253
|
return `${effectBffImport}
|
|
259
254
|
export default function ${toPascalCase(app.id)}Home() {
|
|
260
|
-
const {
|
|
261
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
255
|
+
const { language, supportedLanguages, t } = useModernI18n();
|
|
262
256
|
${effectBffState} return (
|
|
263
257
|
<main className="${tw('min-h-screen bg-um-canvas px-4 py-6 text-um-foreground sm:px-8')}">
|
|
264
258
|
<UltramodernRouteHead />
|
|
@@ -304,8 +298,7 @@ function createRemoteEntry(app) {
|
|
|
304
298
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
305
299
|
|
|
306
300
|
export default function ${toPascalCase(domain)}Route() {
|
|
307
|
-
const {
|
|
308
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
301
|
+
const { t } = useModernI18n();
|
|
309
302
|
|
|
310
303
|
return (
|
|
311
304
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="./Route">
|
|
@@ -323,8 +316,7 @@ function createRemoteWidget(app) {
|
|
|
323
316
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
324
317
|
|
|
325
318
|
export default function ${componentName}() {
|
|
326
|
-
const {
|
|
327
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
319
|
+
const { t } = useModernI18n();
|
|
328
320
|
|
|
329
321
|
return (
|
|
330
322
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="./Widget">
|
|
@@ -343,8 +335,7 @@ function createRemoteExposeComponent(app, expose) {
|
|
|
343
335
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
344
336
|
|
|
345
337
|
export default function ${componentName}() {
|
|
346
|
-
const {
|
|
347
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
338
|
+
const { t } = useModernI18n();
|
|
348
339
|
|
|
349
340
|
return (
|
|
350
341
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="${expose}">
|
|
@@ -669,6 +669,7 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
669
669
|
'pnpm-workspace.yaml',
|
|
670
670
|
"scripts/**",
|
|
671
671
|
'topology/**',
|
|
672
|
+
'tsconfig.json',
|
|
672
673
|
'tsconfig.base.json'
|
|
673
674
|
],
|
|
674
675
|
deniedPaths: [
|
|
@@ -733,6 +734,7 @@ function createTemplateManifest(modernVersion, packageSource) {
|
|
|
733
734
|
expectedCommands: [
|
|
734
735
|
'mise install',
|
|
735
736
|
'pnpm install',
|
|
737
|
+
'pnpm run typecheck',
|
|
736
738
|
'pnpm run i18n:boundaries',
|
|
737
739
|
'pnpm run contract:check',
|
|
738
740
|
'pnpm run performance:readiness'
|
|
@@ -11,8 +11,7 @@ import { VerticalShowcase } from '../vertical-components';
|
|
|
11
11
|
import { ultramodernUiMarker } from '../../ultramodern-build';
|
|
12
12
|
|
|
13
13
|
export default function ShellHome() {
|
|
14
|
-
const {
|
|
15
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
14
|
+
const { t } = useModernI18n();
|
|
16
15
|
|
|
17
16
|
return (
|
|
18
17
|
<ShellFrame>
|
|
@@ -85,8 +84,7 @@ const loadRemoteComponent = (specifier: string) =>
|
|
|
85
84
|
|
|
86
85
|
const createRemoteFallback = (specifier: string) =>
|
|
87
86
|
({ error }: { error: Error }) => {
|
|
88
|
-
const {
|
|
89
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
87
|
+
const { t } = useModernI18n();
|
|
90
88
|
const classification = classifyModuleFederationFallback(error);
|
|
91
89
|
const telemetry = createModuleFederationFallbackTelemetry({
|
|
92
90
|
appName: '${shellApp.id}',
|
|
@@ -168,8 +166,7 @@ const createHydratedRemote =
|
|
|
168
166
|
${hydratedExports}
|
|
169
167
|
|
|
170
168
|
export const Header = () => {
|
|
171
|
-
const {
|
|
172
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
169
|
+
const { t } = useModernI18n();
|
|
173
170
|
|
|
174
171
|
return (
|
|
175
172
|
<header className="${tw('flex min-w-0 flex-wrap items-center gap-x-8 gap-y-2 md:flex-1')}" data-modern-boundary-id="${shellApp.mfName}" data-modern-mf-expose="shell/Header">
|
|
@@ -179,8 +176,7 @@ const createHydratedRemote =
|
|
|
179
176
|
};
|
|
180
177
|
|
|
181
178
|
export const StatusBadge = () => {
|
|
182
|
-
const {
|
|
183
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
179
|
+
const { t } = useModernI18n();
|
|
184
180
|
|
|
185
181
|
return (
|
|
186
182
|
<span className="${tw('inline-flex h-10 shrink-0 items-center justify-center rounded-full border border-stone-900/15 bg-white px-4 text-sm font-extrabold text-stone-950 shadow-lg shadow-stone-900/5')}">
|
|
@@ -190,8 +186,7 @@ export const StatusBadge = () => {
|
|
|
190
186
|
};
|
|
191
187
|
|
|
192
188
|
export const VerticalShowcase = () => {
|
|
193
|
-
const {
|
|
194
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
189
|
+
const { t } = useModernI18n();
|
|
195
190
|
|
|
196
191
|
if (widgetCount === 0) {
|
|
197
192
|
return (
|
|
@@ -258,8 +253,7 @@ import { ultramodernUiMarker } from '../../ultramodern-build';
|
|
|
258
253
|
` : '';
|
|
259
254
|
return `${effectBffImport}
|
|
260
255
|
export default function ${toPascalCase(app.id)}Home() {
|
|
261
|
-
const {
|
|
262
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
256
|
+
const { language, supportedLanguages, t } = useModernI18n();
|
|
263
257
|
${effectBffState} return (
|
|
264
258
|
<main className="${tw('min-h-screen bg-um-canvas px-4 py-6 text-um-foreground sm:px-8')}">
|
|
265
259
|
<UltramodernRouteHead />
|
|
@@ -305,8 +299,7 @@ function createRemoteEntry(app) {
|
|
|
305
299
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
306
300
|
|
|
307
301
|
export default function ${toPascalCase(domain)}Route() {
|
|
308
|
-
const {
|
|
309
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
302
|
+
const { t } = useModernI18n();
|
|
310
303
|
|
|
311
304
|
return (
|
|
312
305
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="./Route">
|
|
@@ -324,8 +317,7 @@ function createRemoteWidget(app) {
|
|
|
324
317
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
325
318
|
|
|
326
319
|
export default function ${componentName}() {
|
|
327
|
-
const {
|
|
328
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
320
|
+
const { t } = useModernI18n();
|
|
329
321
|
|
|
330
322
|
return (
|
|
331
323
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="./Widget">
|
|
@@ -344,8 +336,7 @@ function createRemoteExposeComponent(app, expose) {
|
|
|
344
336
|
return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
|
|
345
337
|
|
|
346
338
|
export default function ${componentName}() {
|
|
347
|
-
const {
|
|
348
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
339
|
+
const { t } = useModernI18n();
|
|
349
340
|
|
|
350
341
|
return (
|
|
351
342
|
<section className="${tw('rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10')}" data-modern-boundary-id="${app.mfName}" data-modern-mf-expose="${expose}">
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
24
|
-
"version": "3.4.0-ultramodern.
|
|
24
|
+
"version": "3.4.0-ultramodern.3",
|
|
25
25
|
"types": "./dist/types/index.d.ts",
|
|
26
26
|
"main": "./dist/esm-node/index.js",
|
|
27
27
|
"bin": {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
],
|
|
76
76
|
"dependencies": {
|
|
77
77
|
"@modern-js/codesmith": "2.6.9",
|
|
78
|
-
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.4.0-ultramodern.
|
|
78
|
+
"@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.4.0-ultramodern.3"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@rslib/core": "0.23.0",
|
|
@@ -97,6 +97,6 @@
|
|
|
97
97
|
"test": "rm -rf dist && rslib build -c rslibconfig.mts && rstest --passWithNoTests"
|
|
98
98
|
},
|
|
99
99
|
"ultramodern": {
|
|
100
|
-
"frameworkVersion": "3.4.0-ultramodern.
|
|
100
|
+
"frameworkVersion": "3.4.0-ultramodern.3"
|
|
101
101
|
}
|
|
102
102
|
}
|
|
@@ -14,6 +14,14 @@ minimumReleaseAgeExclude:
|
|
|
14
14
|
- '@typescript/native-preview'
|
|
15
15
|
- '@typescript/native-preview-*'
|
|
16
16
|
- '@types/react'
|
|
17
|
+
- '@rsbuild/core'
|
|
18
|
+
- '@rsbuild/plugin-react'
|
|
19
|
+
- '@rsbuild/plugin-type-check'
|
|
20
|
+
- '@rspack/binding'
|
|
21
|
+
- '@rspack/binding-*'
|
|
22
|
+
- '@rspack/core'
|
|
23
|
+
- '@rspack/plugin-react-refresh'
|
|
24
|
+
- 'ts-checker-rspack-plugin'
|
|
17
25
|
trustPolicy: no-downgrade
|
|
18
26
|
trustPolicyIgnoreAfter: 1440
|
|
19
27
|
blockExoticSubdeps: true
|
|
@@ -20,13 +20,30 @@ const cloneTimeoutMs = Number.parseInt(
|
|
|
20
20
|
|
|
21
21
|
const readJson = filePath => JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
22
22
|
|
|
23
|
-
const
|
|
24
|
-
|
|
23
|
+
const commandOverrideEnv = {
|
|
24
|
+
gh: 'ULTRAMODERN_GH_BIN',
|
|
25
|
+
git: 'ULTRAMODERN_GIT_BIN',
|
|
26
|
+
lefthook: 'ULTRAMODERN_LEFTHOOK_BIN',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const resolveCommand = command => {
|
|
30
|
+
const overrideEnv = commandOverrideEnv[command];
|
|
31
|
+
return overrideEnv ? (process.env[overrideEnv] ?? command) : command;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const requiresCommandShell = command =>
|
|
35
|
+
process.platform === 'win32' && /\.(?:bat|cmd)$/iu.test(command);
|
|
36
|
+
|
|
37
|
+
const run = (command, args, options = {}) => {
|
|
38
|
+
const resolvedCommand = resolveCommand(command);
|
|
39
|
+
return execFileSync(resolvedCommand, args, {
|
|
25
40
|
cwd: options.cwd ?? root,
|
|
26
41
|
encoding: 'utf-8',
|
|
42
|
+
shell: requiresCommandShell(resolvedCommand),
|
|
27
43
|
stdio: options.stdio ?? ['ignore', 'pipe', 'pipe'],
|
|
28
44
|
timeout: options.timeout,
|
|
29
45
|
});
|
|
46
|
+
};
|
|
30
47
|
|
|
31
48
|
const commandExists = command => {
|
|
32
49
|
try {
|
|
@@ -7,8 +7,7 @@ interface ShellFrameProps {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export default function ShellFrame({ children }: ShellFrameProps) {
|
|
10
|
-
const {
|
|
11
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
10
|
+
const { language, t } = useModernI18n();
|
|
12
11
|
const { alternates } = useLocalizedLocation();
|
|
13
12
|
|
|
14
13
|
return (
|
|
@@ -104,8 +104,7 @@ const sanitiseJsonLd = (value: RouteJsonLd) =>
|
|
|
104
104
|
JSON.stringify(value).replaceAll('<', '\\u003c');
|
|
105
105
|
|
|
106
106
|
export const UltramodernRouteHead = () => {
|
|
107
|
-
const {
|
|
108
|
-
const t = i18nInstance['t'].bind(i18nInstance);
|
|
107
|
+
const { language, t } = useModernI18n();
|
|
109
108
|
const { canonical, alternates } = useLocalizedLocation();
|
|
110
109
|
const route = resolveRouteMetadata(canonical);
|
|
111
110
|
const title = route === undefined ? appName : t(route.titleKey);
|
|
@@ -116,7 +115,7 @@ export const UltramodernRouteHead = () => {
|
|
|
116
115
|
const jsonLd = route?.jsonLd;
|
|
117
116
|
|
|
118
117
|
return (
|
|
119
|
-
<Helmet htmlAttributes={{ lang:
|
|
118
|
+
<Helmet htmlAttributes={{ lang: language ?? fallbackLanguage }}>
|
|
120
119
|
<title>{title}</title>
|
|
121
120
|
<meta content={description} name="description" />
|
|
122
121
|
<meta content={indexable ? 'index, follow' : 'noindex, nofollow'} name="robots" />
|
|
@@ -140,7 +139,7 @@ export const UltramodernRouteHead = () => {
|
|
|
140
139
|
<meta content={description} property="og:description" />
|
|
141
140
|
<meta content={canonicalUrl} property="og:url" />
|
|
142
141
|
<meta content="website" property="og:type" />
|
|
143
|
-
<meta content={
|
|
142
|
+
<meta content={language ?? fallbackLanguage} property="og:locale" />
|
|
144
143
|
<meta content="summary_large_image" name="twitter:card" />
|
|
145
144
|
<meta content={title} name="twitter:title" />
|
|
146
145
|
<meta content={description} name="twitter:description" />
|
|
@@ -390,6 +390,67 @@ const assertMicroVerticalContractGraph = ({
|
|
|
390
390
|
);
|
|
391
391
|
}
|
|
392
392
|
};
|
|
393
|
+
const toPosixPath = value => value.split(path.sep).join('/');
|
|
394
|
+
const referenceFrom = (fromPath, toPath) => ({
|
|
395
|
+
path: toPosixPath(path.relative(fromPath, toPath)),
|
|
396
|
+
});
|
|
397
|
+
const sharedPackagePaths = [
|
|
398
|
+
'packages/shared-contracts',
|
|
399
|
+
'packages/shared-design-tokens',
|
|
400
|
+
];
|
|
401
|
+
const assertTsConfigReferenceGraph = () => {
|
|
402
|
+
const rootTsConfig = readJson('tsconfig.json');
|
|
403
|
+
const shellTsConfig = readJson('apps/shell-super-app/tsconfig.json');
|
|
404
|
+
const expectedRootReferences = [
|
|
405
|
+
...sharedPackagePaths,
|
|
406
|
+
'apps/shell-super-app',
|
|
407
|
+
...fullStackVerticals.map(vertical => vertical.path),
|
|
408
|
+
].map(referencePath => ({ path: referencePath }));
|
|
409
|
+
const expectedShellReferences = [
|
|
410
|
+
...sharedPackagePaths,
|
|
411
|
+
...fullStackVerticals.map(vertical => vertical.path),
|
|
412
|
+
].map(referencePath =>
|
|
413
|
+
referenceFrom('apps/shell-super-app', referencePath),
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
assertSameJson(
|
|
417
|
+
rootTsConfig.files,
|
|
418
|
+
[],
|
|
419
|
+
'tsconfig.json files',
|
|
420
|
+
'restore the generated root project-reference tsconfig',
|
|
421
|
+
);
|
|
422
|
+
assertSameJson(
|
|
423
|
+
rootTsConfig.references ?? [],
|
|
424
|
+
expectedRootReferences,
|
|
425
|
+
'tsconfig.json references',
|
|
426
|
+
'restore the generated root project-reference graph',
|
|
427
|
+
);
|
|
428
|
+
assertSameJson(
|
|
429
|
+
shellTsConfig.references ?? [],
|
|
430
|
+
expectedShellReferences,
|
|
431
|
+
'apps/shell-super-app/tsconfig.json references',
|
|
432
|
+
'restore the generated shell project-reference graph',
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
for (const vertical of fullStackVerticals) {
|
|
436
|
+
const verticalTsConfig = readJson(`${vertical.path}/tsconfig.json`);
|
|
437
|
+
const expectedVerticalReferences = [
|
|
438
|
+
...sharedPackagePaths,
|
|
439
|
+
...(vertical.verticalRefs ?? [])
|
|
440
|
+
.map(verticalRef =>
|
|
441
|
+
fullStackVerticals.find(candidate => candidate.id === verticalRef),
|
|
442
|
+
)
|
|
443
|
+
.filter(Boolean)
|
|
444
|
+
.map(referencedVertical => referencedVertical.path),
|
|
445
|
+
].map(referencePath => referenceFrom(vertical.path, referencePath));
|
|
446
|
+
assertSameJson(
|
|
447
|
+
verticalTsConfig.references ?? [],
|
|
448
|
+
expectedVerticalReferences,
|
|
449
|
+
`${vertical.path}/tsconfig.json references`,
|
|
450
|
+
'restore the generated MicroVertical project-reference graph',
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
};
|
|
393
454
|
const packageJsonFiles = startDir => {
|
|
394
455
|
const files = [];
|
|
395
456
|
const queue = [startDir];
|
|
@@ -734,6 +795,7 @@ assertMicroVerticalContractGraph({
|
|
|
734
795
|
overlay,
|
|
735
796
|
shellPackage,
|
|
736
797
|
});
|
|
798
|
+
assertTsConfigReferenceGraph();
|
|
737
799
|
|
|
738
800
|
assert(rootPackage.private === true, 'Root package must be private');
|
|
739
801
|
assert(typeof rootPackage.packageManager === 'string', 'Root must declare packageManager');
|