@bleedingdev/modern-js-create 3.2.0-ultramodern.10 → 3.2.0-ultramodern.11

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 CHANGED
@@ -631,7 +631,7 @@ const remoteApps = [
631
631
  mfName: 'remoteCommerce',
632
632
  exposes: {
633
633
  './Route': './src/remote-entry.tsx',
634
- './Widget': './src/components/CommerceWidget.tsx'
634
+ './Widget': './src/components/commerce-widget.tsx'
635
635
  },
636
636
  ownership: {
637
637
  team: 'commerce-experience',
@@ -660,7 +660,7 @@ const remoteApps = [
660
660
  mfName: 'remoteIdentity',
661
661
  exposes: {
662
662
  './Route': './src/remote-entry.tsx',
663
- './Widget': './src/components/IdentityWidget.tsx'
663
+ './Widget': './src/components/identity-widget.tsx'
664
664
  },
665
665
  ownership: {
666
666
  team: 'identity-platform',
@@ -688,7 +688,7 @@ const remoteApps = [
688
688
  port: 3023,
689
689
  mfName: 'remoteDesignSystem',
690
690
  exposes: {
691
- './Button': './src/components/Button.tsx',
691
+ './Button': './src/components/button.tsx',
692
692
  './tokens': './src/tokens.ts'
693
693
  },
694
694
  ownership: {
@@ -943,6 +943,7 @@ function createRootPackageJson(scope, packageSource) {
943
943
  private: true,
944
944
  name: scope,
945
945
  version: '0.1.0',
946
+ type: 'module',
946
947
  packageManager: 'pnpm@11.1.2',
947
948
  scripts: {
948
949
  dev: `pnpm --parallel --filter ${ultramodern_workspace_packageName(scope, shellApp.packageSuffix)} --filter ${ultramodern_workspace_packageName(scope, 'remote-commerce')} --filter ${ultramodern_workspace_packageName(scope, 'remote-identity')} --filter ${ultramodern_workspace_packageName(scope, 'remote-design-system')} dev`,
@@ -956,7 +957,7 @@ function createRootPackageJson(scope, packageSource) {
956
957
  'format:check': 'oxfmt --check .',
957
958
  lint: 'oxlint .',
958
959
  'lint:fix': 'oxlint . --fix',
959
- typecheck: 'pnpm -r --filter ./apps/** --filter ./services/** --filter ./packages/** typecheck',
960
+ typecheck: `pnpm -r --filter "@${scope}/*" typecheck`,
960
961
  'skills:install': "node ./scripts/bootstrap-agent-skills.mjs",
961
962
  'skills:check': "node ./scripts/bootstrap-agent-skills.mjs --check",
962
963
  'ultramodern:check': "node ./scripts/validate-ultramodern-workspace.mjs",
@@ -991,7 +992,7 @@ function createRootPackageJson(scope, packageSource) {
991
992
  }
992
993
  };
993
994
  }
994
- function createTsConfigBase(scope) {
995
+ function createTsConfigBase() {
995
996
  return {
996
997
  compilerOptions: {
997
998
  target: 'ESNext',
@@ -1018,12 +1019,6 @@ function createTsConfigBase(scope) {
1018
1019
  noImplicitReturns: true,
1019
1020
  skipLibCheck: true,
1020
1021
  resolveJsonModule: true,
1021
- paths: Object.fromEntries(sharedPackages.map((sharedPackage)=>[
1022
- ultramodern_workspace_packageName(scope, sharedPackage.id),
1023
- [
1024
- `${sharedPackage.directory}/src/index.ts`
1025
- ]
1026
- ])),
1027
1022
  plugins: [
1028
1023
  {
1029
1024
  name: '@effect/language-service',
@@ -1051,20 +1046,6 @@ function createPackageTsConfig(packageDir, includeApi = false) {
1051
1046
  if (includeApi) include.push('api', 'shared');
1052
1047
  return {
1053
1048
  extends: `${relativeRootFor(packageDir)}/tsconfig.base.json`,
1054
- compilerOptions: {
1055
- baseUrl: '.',
1056
- paths: {
1057
- '@/*': [
1058
- './src/*'
1059
- ],
1060
- '@api/*': [
1061
- './api/*'
1062
- ],
1063
- '@shared/*': [
1064
- './shared/*'
1065
- ]
1066
- }
1067
- },
1068
1049
  include
1069
1050
  };
1070
1051
  }
@@ -1154,6 +1135,12 @@ const port = Number(process.env['${app.portEnv}'] ?? ${app.port});
1154
1135
  export default defineConfig(
1155
1136
  presetUltramodern(
1156
1137
  {
1138
+ output: {
1139
+ disableTsChecker: true,
1140
+ polyfill: 'off',
1141
+ splitRouteChunks: false,
1142
+ },
1143
+ plugins: [appTools(), tanstackRouterPlugin(), moduleFederationPlugin()],
1157
1144
  server: {
1158
1145
  port,
1159
1146
  ssr: {
@@ -1161,21 +1148,11 @@ export default defineConfig(
1161
1148
  moduleFederationAppSSR: true,
1162
1149
  },
1163
1150
  },
1164
- output: {
1165
- polyfill: 'off',
1166
- disableTsChecker: true,
1167
- splitRouteChunks: false,
1168
- },
1169
- plugins: [
1170
- appTools(),
1171
- tanstackRouterPlugin(),
1172
- moduleFederationPlugin(),
1173
- ],
1174
1151
  },
1175
1152
  {
1176
1153
  appId,
1177
- enableModuleFederationSSR: true,
1178
1154
  enableBffRequestId: true,
1155
+ enableModuleFederationSSR: true,
1179
1156
  enableTelemetryExporters: true,
1180
1157
  telemetryFailLoudStartup: false,
1181
1158
  },
@@ -1183,6 +1160,37 @@ export default defineConfig(
1183
1160
  );
1184
1161
  `;
1185
1162
  }
1163
+ function createSharedModuleFederationConfig() {
1164
+ return ` shared: {
1165
+ '@modern-js/runtime': {
1166
+ requiredVersion: runtimeVersion,
1167
+ singleton: true,
1168
+ treeShaking: false,
1169
+ },
1170
+ '@tanstack/react-router': {
1171
+ requiredVersion: dependencies['@tanstack/react-router'],
1172
+ singleton: true,
1173
+ treeShaking: false,
1174
+ },
1175
+ react: {
1176
+ requiredVersion: reactVersion,
1177
+ singleton: true,
1178
+ treeShaking: false,
1179
+ },
1180
+ 'react-dom': {
1181
+ requiredVersion: reactDomVersion,
1182
+ singleton: true,
1183
+ treeShaking: false,
1184
+ },
1185
+ }`;
1186
+ }
1187
+ function formatTsObjectLiteral(value) {
1188
+ const entries = Object.entries(value).sort(([left], [right])=>left.localeCompare(right));
1189
+ if (0 === entries.length) return '{}';
1190
+ return `{
1191
+ ${entries.map(([key, entryValue])=>` '${key}': '${entryValue}',`).join('\n')}
1192
+ }`;
1193
+ }
1186
1194
  function createShellModuleFederationConfig() {
1187
1195
  return `// @effect-diagnostics nodeBuiltinImport:off processEnv:off
1188
1196
  import { createRequire } from 'node:module';
@@ -1190,98 +1198,47 @@ import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
1190
1198
  import { dependencies } from './package.json';
1191
1199
 
1192
1200
  const require = createRequire(import.meta.url);
1193
- const runtimeVersion = (
1194
- require('@modern-js/runtime/package.json') as { version: string }
1195
- ).version;
1196
- const reactVersion = (require('react/package.json') as { version: string })
1197
- .version;
1198
- const reactDomVersion = (
1199
- require('react-dom/package.json') as { version: string }
1200
- ).version;
1201
+ const runtimeVersion = (require('@modern-js/runtime/package.json') as { version: string }).version;
1202
+ const reactVersion = (require('react/package.json') as { version: string }).version;
1203
+ const reactDomVersion = (require('react-dom/package.json') as { version: string }).version;
1201
1204
 
1202
1205
  export default createModuleFederationConfig({
1203
- name: '${shellApp.mfName}',
1204
1206
  dts: false,
1207
+ filename: 'remoteEntry.js',
1208
+ name: '${shellApp.mfName}',
1205
1209
  remotes: {
1206
1210
  commerce:
1207
1211
  process.env['REMOTE_COMMERCE_MF_MANIFEST'] ??
1208
1212
  'remoteCommerce@http://localhost:3021/mf-manifest.json',
1209
- identity:
1210
- process.env['REMOTE_IDENTITY_MF_MANIFEST'] ??
1211
- 'remoteIdentity@http://localhost:3022/mf-manifest.json',
1212
1213
  designSystem:
1213
1214
  process.env['REMOTE_DESIGN_SYSTEM_MF_MANIFEST'] ??
1214
1215
  'remoteDesignSystem@http://localhost:3023/mf-manifest.json',
1216
+ identity:
1217
+ process.env['REMOTE_IDENTITY_MF_MANIFEST'] ??
1218
+ 'remoteIdentity@http://localhost:3022/mf-manifest.json',
1215
1219
  },
1216
- shared: {
1217
- react: {
1218
- singleton: true,
1219
- requiredVersion: reactVersion,
1220
- treeShaking: false,
1221
- },
1222
- 'react-dom': {
1223
- singleton: true,
1224
- requiredVersion: reactDomVersion,
1225
- treeShaking: false,
1226
- },
1227
- '@tanstack/react-router': {
1228
- singleton: true,
1229
- requiredVersion: dependencies['@tanstack/react-router'],
1230
- treeShaking: false,
1231
- },
1232
- '@modern-js/runtime': {
1233
- singleton: true,
1234
- requiredVersion: runtimeVersion,
1235
- treeShaking: false,
1236
- },
1237
- },
1220
+ ${createSharedModuleFederationConfig()},
1238
1221
  });
1239
1222
  `;
1240
1223
  }
1241
1224
  function createRemoteModuleFederationConfig(app) {
1242
- const exposes = JSON.stringify(app.exposes ?? {}, null, 4).replace(/^/gm, ' ');
1225
+ const exposes = formatTsObjectLiteral(app.exposes ?? {});
1243
1226
  return `// @effect-diagnostics nodeBuiltinImport:off
1244
1227
  import { createRequire } from 'node:module';
1245
1228
  import { createModuleFederationConfig } from '@module-federation/modern-js-v3';
1246
1229
  import { dependencies } from './package.json';
1247
1230
 
1248
1231
  const require = createRequire(import.meta.url);
1249
- const runtimeVersion = (
1250
- require('@modern-js/runtime/package.json') as { version: string }
1251
- ).version;
1252
- const reactVersion = (require('react/package.json') as { version: string })
1253
- .version;
1254
- const reactDomVersion = (
1255
- require('react-dom/package.json') as { version: string }
1256
- ).version;
1232
+ const runtimeVersion = (require('@modern-js/runtime/package.json') as { version: string }).version;
1233
+ const reactVersion = (require('react/package.json') as { version: string }).version;
1234
+ const reactDomVersion = (require('react-dom/package.json') as { version: string }).version;
1257
1235
 
1258
1236
  export default createModuleFederationConfig({
1259
- name: '${app.mfName}',
1260
1237
  dts: false,
1261
- filename: 'remoteEntry.js',
1262
1238
  exposes: ${exposes},
1263
- shared: {
1264
- react: {
1265
- singleton: true,
1266
- requiredVersion: reactVersion,
1267
- treeShaking: false,
1268
- },
1269
- 'react-dom': {
1270
- singleton: true,
1271
- requiredVersion: reactDomVersion,
1272
- treeShaking: false,
1273
- },
1274
- '@tanstack/react-router': {
1275
- singleton: true,
1276
- requiredVersion: dependencies['@tanstack/react-router'],
1277
- treeShaking: false,
1278
- },
1279
- '@modern-js/runtime': {
1280
- singleton: true,
1281
- requiredVersion: runtimeVersion,
1282
- treeShaking: false,
1283
- },
1284
- },
1239
+ filename: 'remoteEntry.js',
1240
+ name: '${app.mfName}',
1241
+ ${createSharedModuleFederationConfig()},
1285
1242
  });
1286
1243
  `;
1287
1244
  }
@@ -1296,19 +1253,19 @@ const port = Number(process.env['${effectService.portEnv}'] ?? ${effectService.p
1296
1253
  export default defineConfig(
1297
1254
  presetUltramodern(
1298
1255
  {
1299
- server: {
1300
- port,
1301
- },
1302
1256
  bff: {
1303
- prefix: '/recommendations-api',
1304
- runtimeFramework: 'effect',
1305
1257
  effect: {
1306
1258
  openapi: {
1307
1259
  path: '/openapi.json',
1308
1260
  },
1309
1261
  },
1262
+ prefix: '/recommendations-api',
1263
+ runtimeFramework: 'effect',
1310
1264
  },
1311
1265
  plugins: [appTools(), bffPlugin()],
1266
+ server: {
1267
+ port,
1268
+ },
1312
1269
  },
1313
1270
  {
1314
1271
  appId,
@@ -1321,11 +1278,7 @@ export default defineConfig(
1321
1278
  `;
1322
1279
  }
1323
1280
  function createShellPage() {
1324
- return `const remotes = [
1325
- 'remote-commerce',
1326
- 'remote-identity',
1327
- 'remote-design-system',
1328
- ];
1281
+ return `const remotes = ['remote-commerce', 'remote-identity', 'remote-design-system'];
1329
1282
 
1330
1283
  export default function ShellHome() {
1331
1284
  return (
@@ -1333,7 +1286,7 @@ export default function ShellHome() {
1333
1286
  <h1>UltraModern SuperApp Shell</h1>
1334
1287
  <p data-testid="ultramodern-preset">presetUltramodern workspace</p>
1335
1288
  <ul>
1336
- {remotes.map(remote => (
1289
+ {remotes.map((remote) => (
1337
1290
  <li key={remote}>{remote}</li>
1338
1291
  ))}
1339
1292
  </ul>
@@ -1362,8 +1315,8 @@ export default function Layout({ children }: { children: ReactNode }) {
1362
1315
  `;
1363
1316
  }
1364
1317
  function createRemoteEntry(app) {
1365
- const componentName = 'remote-identity' === app.id ? 'IdentityWidget' : 'CommerceWidget';
1366
- return `export { default } from './components/${componentName}';
1318
+ const componentFile = 'remote-identity' === app.id ? 'identity-widget' : 'commerce-widget';
1319
+ return `export { default } from './components/${componentFile}';
1367
1320
  `;
1368
1321
  }
1369
1322
  function createRemoteWidget(app) {
@@ -1399,8 +1352,8 @@ export default function Button({ label = 'Design System Button' }: { label?: str
1399
1352
  function createDesignTokens() {
1400
1353
  return `export const designTokens = {
1401
1354
  color: {
1402
- foreground: '#133225',
1403
1355
  accent: '#2f8f68',
1356
+ foreground: '#133225',
1404
1357
  },
1405
1358
  radius: {
1406
1359
  control: '999px',
@@ -1421,9 +1374,7 @@ const recommendationSchema = Schema.Struct({
1421
1374
  title: Schema.String,
1422
1375
  });
1423
1376
 
1424
- export const recommendationsEffectApi = HttpApi.make(
1425
- 'RecommendationsEffectApi',
1426
- ).add(
1377
+ export const recommendationsEffectApi = HttpApi.make('RecommendationsEffectApi').add(
1427
1378
  HttpApiGroup.make('recommendations').add(
1428
1379
  HttpApiEndpoint.get('list', '/effect/recommendations', {
1429
1380
  success: Schema.Struct({
@@ -1446,7 +1397,7 @@ import { recommendationsEffectApi } from '../../shared/effect/api';
1446
1397
  const recommendationsLayer = HttpApiBuilder.group(
1447
1398
  recommendationsEffectApi,
1448
1399
  'recommendations',
1449
- handlers =>
1400
+ (handlers) =>
1450
1401
  handlers.handle('list', () =>
1451
1402
  Effect.succeed({
1452
1403
  items: [
@@ -1754,11 +1705,11 @@ function writeApp(targetDir, scope, app, packageSource) {
1754
1705
  writeFile(targetDir, `${app.directory}/src/routes/page.tsx`, 'shell' === app.kind ? createShellPage() : createRemotePage(app));
1755
1706
  if ('vertical' === app.kind) {
1756
1707
  writeFile(targetDir, `${app.directory}/src/remote-entry.tsx`, createRemoteEntry(app));
1757
- const widgetFile = 'remote-identity' === app.id ? 'IdentityWidget.tsx' : 'CommerceWidget.tsx';
1708
+ const widgetFile = 'remote-identity' === app.id ? 'identity-widget.tsx' : 'commerce-widget.tsx';
1758
1709
  writeFile(targetDir, `${app.directory}/src/components/${widgetFile}`, createRemoteWidget(app));
1759
1710
  }
1760
1711
  if ('horizontal-design-system' === app.kind) {
1761
- writeFile(targetDir, `${app.directory}/src/components/Button.tsx`, createDesignButton());
1712
+ writeFile(targetDir, `${app.directory}/src/components/button.tsx`, createDesignButton());
1762
1713
  writeFile(targetDir, `${app.directory}/src/tokens.ts`, createDesignTokens());
1763
1714
  }
1764
1715
  }
@@ -1785,27 +1736,27 @@ function writeSharedPackages(targetDir, scope) {
1785
1736
  });
1786
1737
  }
1787
1738
  writeFile(targetDir, 'packages/shared-contracts/src/index.ts', `export const ultramodernWorkspaceContract = {
1739
+ ownership: 'topology/ownership.json',
1788
1740
  preset: 'presetUltramodern',
1789
1741
  topology: 'topology/reference-topology.json',
1790
- ownership: 'topology/ownership.json',
1791
1742
  } as const;
1792
1743
  `);
1793
1744
  writeFile(targetDir, 'packages/shared-design-tokens/src/index.ts', `export const sharedDesignTokens = {
1794
1745
  color: {
1795
- surface: '#f6fbf7',
1796
- foreground: '#133225',
1797
1746
  accent: '#2f8f68',
1747
+ foreground: '#133225',
1748
+ surface: '#f6fbf7',
1798
1749
  },
1799
1750
  } as const;
1800
1751
  `);
1801
- writeFile(targetDir, 'packages/shared-effect-api/src/index.ts', `export type Recommendation = {
1752
+ writeFile(targetDir, 'packages/shared-effect-api/src/index.ts', `export interface Recommendation {
1802
1753
  id: string;
1803
1754
  title: string;
1804
- };
1755
+ }
1805
1756
 
1806
1757
  export const recommendationsApiContract = {
1807
- serviceId: '${effectService.id}',
1808
1758
  basePath: '/recommendations-api/effect/recommendations',
1759
+ serviceId: '${effectService.id}',
1809
1760
  } as const;
1810
1761
  `);
1811
1762
  }
@@ -1820,7 +1771,7 @@ function generateUltramodernWorkspace(options) {
1820
1771
  packageScope: scope
1821
1772
  });
1822
1773
  writeJson(options.targetDir, 'package.json', createRootPackageJson(scope, packageSource));
1823
- writeJson(options.targetDir, 'tsconfig.base.json', createTsConfigBase(scope));
1774
+ writeJson(options.targetDir, 'tsconfig.base.json', createTsConfigBase());
1824
1775
  writeJson(options.targetDir, 'topology/reference-topology.json', createTopology(scope));
1825
1776
  writeJson(options.targetDir, 'topology/ownership.json', createOwnership(scope));
1826
1777
  writeJson(options.targetDir, 'topology/local-overlays/development.json', createDevelopmentOverlay());
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "engines": {
22
22
  "node": ">=20"
23
23
  },
24
- "version": "3.2.0-ultramodern.10",
24
+ "version": "3.2.0-ultramodern.11",
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.8.0",
42
42
  "@typescript/native-preview": "7.0.0-dev.20260516.1",
43
43
  "tsx": "^4.22.0",
44
- "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.10"
44
+ "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.2.0-ultramodern.11"
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.10"
57
+ "frameworkVersion": "3.2.0-ultramodern.11"
58
58
  }
59
59
  }
@@ -1,7 +1,16 @@
1
- import { defineConfig } from "oxfmt";
2
- import ultracite from "ultracite/oxfmt";
1
+ import { defineConfig } from 'oxfmt';
2
+ import ultracite from 'ultracite/oxfmt';
3
3
 
4
4
  export default defineConfig({
5
5
  extends: [ultracite],
6
- ignorePatterns: ["dist", "node_modules", ".modern", ".modernjs", "**/routeTree.gen.ts"],
6
+ ignorePatterns: [
7
+ '.agents',
8
+ '**/*.json',
9
+ 'dist',
10
+ 'node_modules',
11
+ '.modern',
12
+ '.modernjs',
13
+ '**/routeTree.gen.ts',
14
+ ],
15
+ singleQuote: true,
7
16
  });
@@ -1,6 +1,6 @@
1
- import { defineConfig } from "oxlint";
2
- import core from "ultracite/oxlint/core";
3
- import react from "ultracite/oxlint/react";
1
+ import { defineConfig } from 'oxlint';
2
+ import core from 'ultracite/oxlint/core';
3
+ import react from 'ultracite/oxlint/react';
4
4
 
5
5
  export default defineConfig({
6
6
  env: {
@@ -8,5 +8,12 @@ export default defineConfig({
8
8
  node: true,
9
9
  },
10
10
  extends: [core, react],
11
- ignorePatterns: ["dist", "node_modules", ".modern", ".modernjs", "**/routeTree.gen.ts"],
11
+ ignorePatterns: [
12
+ '.agents',
13
+ 'dist',
14
+ 'node_modules',
15
+ '.modern',
16
+ '.modernjs',
17
+ '**/routeTree.gen.ts',
18
+ ],
12
19
  });
@@ -8,43 +8,37 @@ const lockPath = path.join(root, '.agents/skills-lock.json');
8
8
  const checkOnly = process.argv.includes('--check');
9
9
  const force = process.argv.includes('--force');
10
10
 
11
- function readJson(filePath) {
12
- return JSON.parse(fs.readFileSync(filePath, 'utf8'));
13
- }
11
+ const readJson = (filePath) => JSON.parse(fs.readFileSync(filePath, 'utf-8'));
14
12
 
15
- function run(command, args, options = {}) {
16
- return execFileSync(command, args, {
13
+ const run = (command, args, options = {}) =>
14
+ execFileSync(command, args, {
17
15
  cwd: options.cwd ?? root,
18
- encoding: 'utf8',
16
+ encoding: 'utf-8',
19
17
  stdio: options.stdio ?? ['ignore', 'pipe', 'pipe'],
20
18
  });
21
- }
22
19
 
23
- function cloneSource(source, targetDir) {
24
- const repo = source.repository.replace(/^https:\/\/github.com\//, '');
20
+ const cloneSource = (source, targetDir) => {
21
+ const repo = source.repository.replace(/^https:\/\/github.com\//u, '');
25
22
  try {
26
23
  run('gh', ['repo', 'clone', repo, targetDir, '--', '--depth', '1'], {
27
24
  stdio: 'inherit',
28
25
  });
29
- return;
30
26
  } catch {
31
27
  run('git', ['clone', '--depth', '1', source.repository, targetDir], {
32
28
  stdio: 'inherit',
33
29
  });
34
30
  }
35
- }
31
+ };
36
32
 
37
- function resolveSkillDir(sourceRoot, skillName) {
33
+ const resolveSkillDir = (sourceRoot, skillName) => {
38
34
  const candidates = [
39
35
  path.join(sourceRoot, skillName),
40
36
  path.join(sourceRoot, 'skills', skillName),
41
37
  path.join(sourceRoot, 'skills', 'engineering', skillName),
42
38
  path.join(sourceRoot, 'skills', 'productivity', skillName),
43
39
  ];
44
- return candidates.find(candidate =>
45
- fs.existsSync(path.join(candidate, 'SKILL.md')),
46
- );
47
- }
40
+ return candidates.find((candidate) => fs.existsSync(path.join(candidate, 'SKILL.md')));
41
+ };
48
42
 
49
43
  if (!fs.existsSync(lockPath)) {
50
44
  console.error('Missing .agents/skills-lock.json');
@@ -54,17 +48,14 @@ if (!fs.existsSync(lockPath)) {
54
48
  const lock = readJson(lockPath);
55
49
  const installDir = path.join(root, lock.installDir ?? '.agents/skills');
56
50
  const privateSources = (lock.sources ?? []).filter(
57
- source => source.install === 'clone-if-authorized',
51
+ (source) => source.install === 'clone-if-authorized',
58
52
  );
59
53
 
60
54
  if (checkOnly) {
61
- const missing = privateSources.flatMap(source =>
55
+ const missing = privateSources.flatMap((source) =>
62
56
  (source.baseline ?? [])
63
- .map(skill => skill.name)
64
- .filter(
65
- skillName =>
66
- !fs.existsSync(path.join(installDir, skillName, 'SKILL.md')),
67
- ),
57
+ .map((skill) => skill.name)
58
+ .filter((skillName) => !fs.existsSync(path.join(installDir, skillName, 'SKILL.md'))),
68
59
  );
69
60
  if (missing.length > 0) {
70
61
  console.warn(
@@ -85,9 +76,7 @@ for (const source of privateSources) {
85
76
  for (const skill of source.baseline ?? []) {
86
77
  const sourceSkillDir = resolveSkillDir(tempDir, skill.name);
87
78
  if (!sourceSkillDir) {
88
- throw new Error(
89
- `Skill ${skill.name} not found in ${source.repository}`,
90
- );
79
+ throw new Error(`Skill ${skill.name} not found in ${source.repository}`);
91
80
  }
92
81
  const targetSkillDir = path.join(installDir, skill.name);
93
82
  if (fs.existsSync(targetSkillDir)) {
@@ -95,12 +84,12 @@ for (const source of privateSources) {
95
84
  console.log(`Skipping existing ${skill.name}`);
96
85
  continue;
97
86
  }
98
- fs.rmSync(targetSkillDir, { recursive: true, force: true });
87
+ fs.rmSync(targetSkillDir, { force: true, recursive: true });
99
88
  }
100
89
  fs.cpSync(sourceSkillDir, targetSkillDir, { recursive: true });
101
90
  console.log(`Installed ${skill.name}`);
102
91
  }
103
92
  } finally {
104
- fs.rmSync(tempDir, { recursive: true, force: true });
93
+ fs.rmSync(tempDir, { force: true, recursive: true });
105
94
  }
106
95
  }
@@ -4,8 +4,7 @@ import path from 'node:path';
4
4
  const root = process.cwd();
5
5
  const packageScope = '{{packageScope}}';
6
6
  const tanstackVersion = '1.170.1';
7
- const rstackAgentSkillsCommit =
8
- '61c948b42512e223bad44b83af4080eba48b2677';
7
+ const rstackAgentSkillsCommit = '61c948b42512e223bad44b83af4080eba48b2677';
9
8
  const modernPackages = [
10
9
  '@modern-js/app-tools',
11
10
  '@modern-js/plugin-bff',
@@ -21,31 +20,18 @@ const baselineAgentSkills = [
21
20
  'rslib-modern-package',
22
21
  'rstest-best-practices',
23
22
  ];
24
- const privateAgentSkills = [
25
- 'plan-graph',
26
- 'dag',
27
- 'subagent-graph',
28
- 'helm',
29
- 'debugger-mode',
30
- ];
31
-
32
- function readText(relativePath) {
33
- return fs.readFileSync(path.join(root, relativePath), 'utf-8');
34
- }
23
+ const privateAgentSkills = ['plan-graph', 'dag', 'subagent-graph', 'helm', 'debugger-mode'];
35
24
 
36
- function readJson(relativePath) {
37
- return JSON.parse(readText(relativePath));
38
- }
39
-
40
- function assert(condition, message) {
25
+ const readText = (relativePath) => fs.readFileSync(path.join(root, relativePath), 'utf-8');
26
+ const readJson = (relativePath) => JSON.parse(readText(relativePath));
27
+ const assert = (condition, message) => {
41
28
  if (!condition) {
42
29
  throw new Error(message);
43
30
  }
44
- }
45
-
46
- function assertExists(relativePath) {
31
+ };
32
+ const assertExists = (relativePath) => {
47
33
  assert(fs.existsSync(path.join(root, relativePath)), `Missing ${relativePath}`);
48
- }
34
+ };
49
35
 
50
36
  const requiredPaths = [
51
37
  'AGENTS.md',
@@ -101,11 +87,9 @@ const rootPackage = readJson('package.json');
101
87
  const packageSource = readJson('.modernjs/ultramodern-package-source.json');
102
88
  const skillsLock = readJson('.agents/skills-lock.json');
103
89
  const expectedModernSpecifier =
104
- packageSource.strategy === 'install'
105
- ? packageSource.modernPackages?.specifier
106
- : 'workspace:*';
90
+ packageSource.strategy === 'install' ? packageSource.modernPackages?.specifier : 'workspace:*';
107
91
 
108
- function expectedModernDependency(packageName) {
92
+ const expectedModernDependency = (packageName) => {
109
93
  if (packageSource.strategy !== 'install') {
110
94
  return 'workspace:*';
111
95
  }
@@ -114,15 +98,14 @@ function expectedModernDependency(packageName) {
114
98
  return aliasPackageName
115
99
  ? `npm:${aliasPackageName}@${expectedModernSpecifier}`
116
100
  : expectedModernSpecifier;
117
- }
101
+ };
118
102
 
119
103
  assert(rootPackage.private === true, 'Root package must be private');
120
104
  assert(rootPackage.modernjs?.preset === 'presetUltramodern', 'Root must declare presetUltramodern');
121
105
  assert(rootPackage.packageManager === 'pnpm@11.1.2', 'Root must pin pnpm 11.1.2');
122
106
  assert(rootPackage.engines?.pnpm === '>=11.0.0', 'Root must require pnpm >=11');
123
107
  assert(
124
- rootPackage.modernjs?.packageSource?.config ===
125
- './.modernjs/ultramodern-package-source.json',
108
+ rootPackage.modernjs?.packageSource?.config === './.modernjs/ultramodern-package-source.json',
126
109
  'Root must point to the UltraModern package source metadata',
127
110
  );
128
111
  assert(
@@ -138,46 +121,38 @@ assert(
138
121
  'Generated shared packages must keep workspace:* links',
139
122
  );
140
123
  assert(
141
- modernPackages.every(packageName =>
124
+ modernPackages.every((packageName) =>
142
125
  packageSource.modernPackages?.packages?.includes(packageName),
143
126
  ),
144
127
  'Package source metadata must list all Modern runtime/tooling packages',
145
128
  );
146
129
  assert(
147
- expectedModernSpecifier &&
148
- packageSource.modernPackages?.specifier === expectedModernSpecifier,
130
+ expectedModernSpecifier && packageSource.modernPackages?.specifier === expectedModernSpecifier,
149
131
  'Package source metadata must provide a Modern package specifier',
150
132
  );
151
- assert(
152
- rootPackage.scripts?.['ultramodern:check'] ===
153
- 'node ./scripts/validate-ultramodern-workspace.mjs',
154
- 'Root must expose the ultramodern:check script',
155
- );
133
+
156
134
  const requiredRootScripts = {
157
135
  format: 'oxfmt .',
158
136
  'format:check': 'oxfmt --check .',
159
137
  lint: 'oxlint .',
160
138
  'lint:fix': 'oxlint . --fix',
161
- 'skills:install': 'node ./scripts/bootstrap-agent-skills.mjs',
162
139
  'skills:check': 'node ./scripts/bootstrap-agent-skills.mjs --check',
140
+ 'skills:install': 'node ./scripts/bootstrap-agent-skills.mjs',
141
+ typecheck: `pnpm -r --filter "@${packageScope}/*" typecheck`,
142
+ 'ultramodern:check': 'node ./scripts/validate-ultramodern-workspace.mjs',
163
143
  };
164
144
  for (const [scriptName, scriptCommand] of Object.entries(requiredRootScripts)) {
165
- assert(
166
- rootPackage.scripts?.[scriptName] === scriptCommand,
167
- `Root must expose ${scriptName}`,
168
- );
145
+ assert(rootPackage.scripts?.[scriptName] === scriptCommand, `Root must expose ${scriptName}`);
169
146
  }
147
+
170
148
  for (const dependency of [
171
149
  '@effect/tsgo',
172
150
  '@typescript/native-preview',
173
- 'oxlint',
174
151
  'oxfmt',
152
+ 'oxlint',
175
153
  'ultracite',
176
154
  ]) {
177
- assert(
178
- rootPackage.devDependencies?.[dependency],
179
- `Root must depend on ${dependency}`,
180
- );
155
+ assert(rootPackage.devDependencies?.[dependency], `Root must depend on ${dependency}`);
181
156
  }
182
157
 
183
158
  const agentsInstructions = readText('AGENTS.md');
@@ -200,17 +175,17 @@ assert(
200
175
  );
201
176
  for (const skillName of baselineAgentSkills) {
202
177
  assert(
203
- skillsLock.baseline?.some(skill => skill.name === skillName),
178
+ skillsLock.baseline?.some((skill) => skill.name === skillName),
204
179
  `Agent skills lock must include ${skillName}`,
205
180
  );
206
- const skillContent = readText(`.agents/skills/${skillName}/SKILL.md`);
207
181
  assert(
208
- skillContent.includes(`name: ${skillName}`),
182
+ readText(`.agents/skills/${skillName}/SKILL.md`).includes(`name: ${skillName}`),
209
183
  `${skillName} must contain matching skill metadata`,
210
184
  );
211
185
  }
186
+
212
187
  const privateSource = skillsLock.sources?.find(
213
- source => source.repository === 'https://github.com/TechsioCZ/skills',
188
+ (source) => source.repository === 'https://github.com/TechsioCZ/skills',
214
189
  );
215
190
  assert(
216
191
  privateSource?.install === 'clone-if-authorized',
@@ -218,7 +193,7 @@ assert(
218
193
  );
219
194
  for (const skillName of privateAgentSkills) {
220
195
  assert(
221
- privateSource.baseline?.some(skill => skill.name === skillName),
196
+ privateSource.baseline?.some((skill) => skill.name === skillName),
222
197
  `Agent skills lock must allowlist private skill ${skillName}`,
223
198
  );
224
199
  }
@@ -235,26 +210,30 @@ for (const packagePath of appPackagePaths) {
235
210
  assert(
236
211
  packageJson.dependencies?.['@modern-js/plugin-tanstack'] ===
237
212
  expectedModernDependency('@modern-js/plugin-tanstack'),
238
- `${packagePath} must depend on @modern-js/plugin-tanstack through ${expectedModernDependency('@modern-js/plugin-tanstack')}`,
213
+ `${packagePath} must use @modern-js/plugin-tanstack through ${expectedModernDependency(
214
+ '@modern-js/plugin-tanstack',
215
+ )}`,
239
216
  );
240
217
  assert(
241
218
  packageJson.dependencies?.['@modern-js/runtime'] ===
242
219
  expectedModernDependency('@modern-js/runtime'),
243
- `${packagePath} must depend on @modern-js/runtime through ${expectedModernDependency('@modern-js/runtime')}`,
220
+ `${packagePath} must use @modern-js/runtime through ${expectedModernDependency(
221
+ '@modern-js/runtime',
222
+ )}`,
244
223
  );
245
224
  assert(
246
225
  packageJson.devDependencies?.['@modern-js/app-tools'] ===
247
226
  expectedModernDependency('@modern-js/app-tools'),
248
- `${packagePath} must depend on @modern-js/app-tools through ${expectedModernDependency('@modern-js/app-tools')}`,
227
+ `${packagePath} must use @modern-js/app-tools through ${expectedModernDependency(
228
+ '@modern-js/app-tools',
229
+ )}`,
249
230
  );
250
231
  assert(
251
- packageJson.dependencies?.[`@${packageScope}/shared-contracts`] ===
252
- 'workspace:*',
232
+ packageJson.dependencies?.[`@${packageScope}/shared-contracts`] === 'workspace:*',
253
233
  `${packagePath} must link generated shared contracts through workspace:*`,
254
234
  );
255
235
  assert(
256
- packageJson.dependencies?.[`@${packageScope}/shared-design-tokens`] ===
257
- 'workspace:*',
236
+ packageJson.dependencies?.[`@${packageScope}/shared-design-tokens`] === 'workspace:*',
258
237
  `${packagePath} must link generated shared design tokens through workspace:*`,
259
238
  );
260
239
  assert(
@@ -280,56 +259,83 @@ for (const configPath of [
280
259
  const config = readText(configPath);
281
260
  assert(config.includes('presetUltramodern('), `${configPath} must use presetUltramodern`);
282
261
  assert(config.includes('tanstackRouterPlugin()'), `${configPath} must enable plugin-tanstack`);
283
- assert(config.includes('moduleFederationPlugin()'), `${configPath} must enable Module Federation`);
262
+ assert(
263
+ config.includes('moduleFederationPlugin()'),
264
+ `${configPath} must enable Module Federation`,
265
+ );
284
266
  }
285
267
 
286
268
  const shellMf = readText('apps/shell-super-app/module-federation.config.ts');
287
269
  assert(shellMf.includes("name: 'shellSuperApp'"), 'Shell MF config must name the shell');
288
- assert(shellMf.includes('remoteCommerce@http://localhost:3021/mf-manifest.json'), 'Shell must reference commerce remote');
289
- assert(shellMf.includes('remoteIdentity@http://localhost:3022/mf-manifest.json'), 'Shell must reference identity remote');
290
- assert(shellMf.includes('remoteDesignSystem@http://localhost:3023/mf-manifest.json'), 'Shell must reference design-system remote');
270
+ assert(
271
+ shellMf.includes('remoteCommerce@http://localhost:3021/mf-manifest.json'),
272
+ 'Shell must reference commerce remote',
273
+ );
274
+ assert(
275
+ shellMf.includes('remoteIdentity@http://localhost:3022/mf-manifest.json'),
276
+ 'Shell must reference identity remote',
277
+ );
278
+ assert(
279
+ shellMf.includes('remoteDesignSystem@http://localhost:3023/mf-manifest.json'),
280
+ 'Shell must reference design-system remote',
281
+ );
291
282
 
292
283
  const commerceMf = readText('apps/remotes/remote-commerce/module-federation.config.ts');
293
284
  assert(commerceMf.includes("name: 'remoteCommerce'"), 'Commerce remote MF name is missing');
294
- assert(commerceMf.includes('"./Widget"'), 'Commerce remote must expose a widget');
285
+ assert(commerceMf.includes("'./Widget'"), 'Commerce remote must expose a widget');
295
286
 
296
287
  const designMf = readText('apps/remotes/remote-design-system/module-federation.config.ts');
297
288
  assert(designMf.includes("name: 'remoteDesignSystem'"), 'Design-system remote MF name is missing');
298
- assert(designMf.includes('"./Button"'), 'Design-system remote must expose Button');
299
- assert(designMf.includes('"./tokens"'), 'Design-system remote must expose tokens');
289
+ assert(designMf.includes("'./Button'"), 'Design-system remote must expose Button');
290
+ assert(designMf.includes("'./tokens'"), 'Design-system remote must expose tokens');
300
291
 
301
292
  const servicePackage = readJson('services/service-recommendations-effect/package.json');
302
293
  assert(
303
294
  servicePackage.dependencies?.['@modern-js/runtime'] ===
304
295
  expectedModernDependency('@modern-js/runtime'),
305
- `Effect service must use @modern-js/runtime through ${expectedModernDependency('@modern-js/runtime')}`,
296
+ `Effect service must use @modern-js/runtime through ${expectedModernDependency(
297
+ '@modern-js/runtime',
298
+ )}`,
306
299
  );
307
300
  assert(
308
301
  servicePackage.devDependencies?.['@modern-js/app-tools'] ===
309
302
  expectedModernDependency('@modern-js/app-tools'),
310
- `Effect service must use @modern-js/app-tools through ${expectedModernDependency('@modern-js/app-tools')}`,
303
+ `Effect service must use @modern-js/app-tools through ${expectedModernDependency(
304
+ '@modern-js/app-tools',
305
+ )}`,
311
306
  );
312
307
  assert(
313
308
  servicePackage.devDependencies?.['@modern-js/plugin-bff'] ===
314
309
  expectedModernDependency('@modern-js/plugin-bff'),
315
- `Effect service must use @modern-js/plugin-bff through ${expectedModernDependency('@modern-js/plugin-bff')}`,
310
+ `Effect service must use @modern-js/plugin-bff through ${expectedModernDependency(
311
+ '@modern-js/plugin-bff',
312
+ )}`,
316
313
  );
317
314
  assert(
318
- servicePackage.dependencies?.[`@${packageScope}/shared-effect-api`] ===
319
- 'workspace:*',
315
+ servicePackage.dependencies?.[`@${packageScope}/shared-effect-api`] === 'workspace:*',
320
316
  'Effect service must link generated shared Effect API through workspace:*',
321
317
  );
322
318
 
323
319
  const serviceConfig = readText('services/service-recommendations-effect/modern.config.ts');
324
- assert(serviceConfig.includes("runtimeFramework: 'effect'"), 'Effect service must use Effect runtime');
320
+ assert(
321
+ serviceConfig.includes("runtimeFramework: 'effect'"),
322
+ 'Effect service must use Effect runtime',
323
+ );
325
324
  assert(serviceConfig.includes('bffPlugin()'), 'Effect service must enable bffPlugin');
326
325
 
327
326
  const serviceEntry = readText('services/service-recommendations-effect/api/effect/index.ts');
328
- assert(serviceEntry.includes('defineEffectBff'), 'Effect service must expose defineEffectBff placeholder');
329
- assert(serviceEntry.includes('recommendationsEffectApi'), 'Effect service must use shared recommendations API');
330
-
331
- const serviceApi = readText('services/service-recommendations-effect/shared/effect/api.ts');
332
- assert(serviceApi.includes('HttpApi.make'), 'Effect shared API placeholder must define HttpApi');
327
+ assert(
328
+ serviceEntry.includes('defineEffectBff'),
329
+ 'Effect service must expose defineEffectBff placeholder',
330
+ );
331
+ assert(
332
+ serviceEntry.includes('recommendationsEffectApi'),
333
+ 'Effect service must use shared recommendations API',
334
+ );
335
+ assert(
336
+ readText('services/service-recommendations-effect/shared/effect/api.ts').includes('HttpApi.make'),
337
+ 'Effect shared API placeholder must define HttpApi',
338
+ );
333
339
 
334
340
  const topology = readJson('topology/reference-topology.json');
335
341
  assert(topology.preset === 'presetUltramodern', 'Topology must reference presetUltramodern');
@@ -338,27 +344,26 @@ assert(topology.shell?.remoteRefs?.length === 3, 'Topology shell must reference
338
344
  assert(topology.remotes?.length === 3, 'Topology must contain three remotes');
339
345
  assert(
340
346
  topology.remotes.some(
341
- remote =>
342
- remote.id === 'remote-design-system' &&
343
- remote.kind === 'horizontal-design-system',
347
+ (remote) => remote.id === 'remote-design-system' && remote.kind === 'horizontal-design-system',
344
348
  ),
345
349
  'Topology must contain the horizontal design-system remote',
346
350
  );
347
- assert(topology.effectServices?.[0]?.runtime === 'effect', 'Topology must contain an Effect service');
351
+ assert(
352
+ topology.effectServices?.[0]?.runtime === 'effect',
353
+ 'Topology must contain an Effect service',
354
+ );
348
355
  assert(topology.sharedPackages?.length === 3, 'Topology must contain shared package placeholders');
349
356
 
350
357
  const ownership = readJson('topology/ownership.json');
351
358
  assert(
352
359
  ownership.owners?.some(
353
- owner =>
354
- owner.id === 'remote-commerce' &&
355
- owner.ownership?.team === 'commerce-experience',
360
+ (owner) => owner.id === 'remote-commerce' && owner.ownership?.team === 'commerce-experience',
356
361
  ),
357
362
  'Ownership metadata must retain commerce owner',
358
363
  );
359
364
  assert(
360
365
  ownership.owners?.some(
361
- owner =>
366
+ (owner) =>
362
367
  owner.id === 'service-recommendations-effect' &&
363
368
  owner.package === `@${packageScope}/service-recommendations-effect`,
364
369
  ),
@@ -379,18 +384,15 @@ assert(
379
384
  'Template manifest must retain the Rstack agent skills commit',
380
385
  );
381
386
  assert(
382
- baselineAgentSkills.every(skillName =>
383
- manifest.agentSkills?.baseline?.includes(skillName),
384
- ),
387
+ baselineAgentSkills.every((skillName) => manifest.agentSkills?.baseline?.includes(skillName)),
385
388
  'Template manifest must list every baseline agent skill',
386
389
  );
387
390
  assert(
388
- manifest.agentSkills?.privateSource?.repository ===
389
- 'https://github.com/TechsioCZ/skills',
391
+ manifest.agentSkills?.privateSource?.repository === 'https://github.com/TechsioCZ/skills',
390
392
  'Template manifest must retain the private TechsioCZ skill source',
391
393
  );
392
394
  assert(
393
- privateAgentSkills.every(skillName =>
395
+ privateAgentSkills.every((skillName) =>
394
396
  manifest.agentSkills?.privateSource?.baseline?.includes(skillName),
395
397
  ),
396
398
  'Template manifest must list every private agent skill allowlist entry',