@bleedingdev/modern-js-create 3.2.0-ultramodern.18 → 3.2.0-ultramodern.19

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
@@ -556,6 +556,7 @@ const ultramodern_workspace_dirname = node_path.dirname(fileURLToPath(import.met
556
556
  const workspaceTemplateDir = node_path.resolve(ultramodern_workspace_dirname, '..', 'template-workspace');
557
557
  const TANSTACK_ROUTER_VERSION = '1.170.1';
558
558
  const MODULE_FEDERATION_VERSION = '2.4.0';
559
+ const ZEPHYR_MODERNJS_PLUGIN_VERSION = '1.1.1';
559
560
  const EFFECT_TSGO_VERSION = '0.7.3';
560
561
  const TYPESCRIPT_NATIVE_PREVIEW_VERSION = '7.0.0-dev.20260518.1';
561
562
  const OXLINT_VERSION = '1.65.0';
@@ -926,6 +927,7 @@ function appDependencies(scope, packageSource) {
926
927
  '@module-federation/modern-js-v3': MODULE_FEDERATION_VERSION,
927
928
  '@module-federation/runtime': MODULE_FEDERATION_VERSION,
928
929
  '@tanstack/react-router': TANSTACK_ROUTER_VERSION,
930
+ 'zephyr-modernjs-plugin': ZEPHYR_MODERNJS_PLUGIN_VERSION,
929
931
  [ultramodern_workspace_packageName(scope, 'shared-contracts')]: WORKSPACE_PACKAGE_VERSION,
930
932
  [ultramodern_workspace_packageName(scope, 'shared-design-tokens')]: WORKSPACE_PACKAGE_VERSION,
931
933
  i18next: I18NEXT_VERSION,
@@ -967,7 +969,10 @@ function createRootPackageJson(scope, packageSource) {
967
969
  typecheck: `pnpm -r --filter "@${scope}/*" typecheck`,
968
970
  'skills:install': "node ./scripts/bootstrap-agent-skills.mjs",
969
971
  'skills:check': "node ./scripts/bootstrap-agent-skills.mjs --check",
972
+ 'agents:refs:install': "node ./scripts/setup-agent-reference-repos.mjs",
973
+ 'agents:refs:check': "node ./scripts/setup-agent-reference-repos.mjs --check",
970
974
  'ultramodern:check': "node ./scripts/validate-ultramodern-workspace.mjs",
975
+ postinstall: "node ./scripts/setup-agent-reference-repos.mjs",
971
976
  check: 'pnpm format:check && pnpm lint && pnpm typecheck && pnpm i18n:check && pnpm skills:check && pnpm ultramodern:check'
972
977
  },
973
978
  engines: {
@@ -1136,6 +1141,7 @@ import { appTools, defineConfig, presetUltramodern } from '@modern-js/app-tools'
1136
1141
  import { i18nPlugin } from '@modern-js/plugin-i18n';
1137
1142
  import { tanstackRouterPlugin } from '@modern-js/plugin-tanstack';
1138
1143
  import { moduleFederationPlugin } from '@module-federation/modern-js-v3';
1144
+ import { withZephyr } from 'zephyr-modernjs-plugin';
1139
1145
 
1140
1146
  const appId = '${app.id}';
1141
1147
  const port = Number(process.env['${app.portEnv}'] ?? ${app.port});
@@ -1157,11 +1163,19 @@ export default defineConfig(
1157
1163
  {
1158
1164
  output: {
1159
1165
  disableTsChecker: true,
1166
+ distPath: {
1167
+ html: './',
1168
+ },
1160
1169
  polyfill: 'off',
1161
1170
  splitRouteChunks: false,
1162
1171
  },
1172
+ html: {
1173
+ outputStructure: 'flat',
1174
+ },
1163
1175
  plugins: [
1164
- appTools(),
1176
+ appTools({
1177
+ bundler: 'rspack',
1178
+ }),
1165
1179
  i18nPlugin({
1166
1180
  localeDetection: {
1167
1181
  fallbackLanguage: 'en',
@@ -1171,6 +1185,7 @@ export default defineConfig(
1171
1185
  }),
1172
1186
  tanstackRouterPlugin(),
1173
1187
  moduleFederationPlugin(),
1188
+ withZephyr(),
1174
1189
  ],
1175
1190
  server: {
1176
1191
  port,
@@ -1180,6 +1195,7 @@ export default defineConfig(
1180
1195
  },
1181
1196
  },
1182
1197
  source: {
1198
+ mainEntryName: 'index',
1183
1199
  globalVars: {
1184
1200
  ULTRAMODERN_SITE_URL: siteUrl,
1185
1201
  },
@@ -1856,6 +1872,7 @@ function createTemplateManifest(modernVersion, packageSource) {
1856
1872
  allowedPaths: [
1857
1873
  '.agents/**',
1858
1874
  '.github/**',
1875
+ '.gitignore',
1859
1876
  '.modernjs/**',
1860
1877
  'AGENTS.md',
1861
1878
  'README.md',
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "engines": {
22
22
  "node": ">=20"
23
23
  },
24
- "version": "3.2.0-ultramodern.18",
24
+ "version": "3.2.0-ultramodern.19",
25
25
  "types": "./dist/types/index.d.ts",
26
26
  "main": "./dist/index.js",
27
27
  "bin": {
@@ -0,0 +1,23 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "defaultEnabled": true,
4
+ "installDir": "repos",
5
+ "repositories": [
6
+ {
7
+ "id": "effect",
8
+ "name": "Effect",
9
+ "url": "https://github.com/Effect-TS/effect.git",
10
+ "ref": "main",
11
+ "path": "repos/effect",
12
+ "readOnly": true
13
+ },
14
+ {
15
+ "id": "ultramodern-js",
16
+ "name": "UltraModern.js",
17
+ "url": "https://github.com/BleedingDev/ultramodern.js.git",
18
+ "ref": "main-ultramodern",
19
+ "path": "repos/ultramodern.js",
20
+ "readOnly": true
21
+ }
22
+ ]
23
+ }
@@ -38,6 +38,15 @@ pnpm skills:install
38
38
 
39
39
  The installer copies only the allowlisted private skills from `.agents/skills-lock.json`: `plan-graph`, `dag`, `subagent-graph`, `helm`, and `debugger-mode`.
40
40
 
41
+ ## Agent Reference Repositories
42
+
43
+ The workspace installs read-only source snapshots under `repos/` by default during `pnpm install`. These repositories are reference material for coding agents, not application source:
44
+
45
+ - `repos/effect` from `Effect-TS/effect`.
46
+ - `repos/ultramodern.js` from `BleedingDev/ultramodern.js`.
47
+
48
+ Agents may read files under `repos/` to understand upstream patterns, APIs, and project conventions. Do not edit files under `repos/`, import from them, or make production code depend on them. To skip this setup, run installs with `ULTRAMODERN_SKIP_AGENT_REPOS=1`.
49
+
41
50
  ## Project Priorities
42
51
 
43
52
  - Keep `presetUltramodern` as the single preset.
@@ -19,6 +19,11 @@ Run the scaffold validator before adding business code:
19
19
  pnpm ultramodern:check
20
20
  ```
21
21
 
22
+ By default, `pnpm install` also prepares read-only agent reference repositories
23
+ under `repos/` for Effect and UltraModern.js source lookup. Disable this setup
24
+ with `ULTRAMODERN_SKIP_AGENT_REPOS=1 pnpm install`, or rerun it explicitly with
25
+ `pnpm agents:refs:install`.
26
+
22
27
  The topology and ownership metadata are generated under `topology/`. The
23
28
  workspace also ships `.github/workflows/ultramodern-workspace-gates.yml` and
24
29
  `.github/renovate.json` with read-only workflow permissions, commit-pinned
@@ -0,0 +1,217 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ const root = process.cwd();
6
+ const args = new Set(process.argv.slice(2));
7
+ const checkOnly = args.has('--check');
8
+ const configPath = path.join(root, '.agents', 'agent-reference-repos.json');
9
+ const manifestPath = path.join(root, '.modernjs', 'agent-reference-repos.json');
10
+ const tempRoot = path.join(root, '.modernjs', 'agent-reference-repos-tmp');
11
+
12
+ const truthy = value => /^(1|true|yes|on)$/i.test(String(value ?? ''));
13
+ const falsy = value => /^(0|false|no|off)$/i.test(String(value ?? ''));
14
+
15
+ const skipRequested =
16
+ truthy(process.env.ULTRAMODERN_SKIP_AGENT_REPOS) ||
17
+ falsy(process.env.ULTRAMODERN_AGENT_REPOS);
18
+ const required = truthy(process.env.ULTRAMODERN_AGENT_REPOS_REQUIRED);
19
+ const refresh = truthy(process.env.ULTRAMODERN_AGENT_REPOS_REFRESH);
20
+
21
+ const log = message => console.log(`[agent-reference-repos] ${message}`);
22
+ const warn = message => console.warn(`[agent-reference-repos] ${message}`);
23
+
24
+ function fail(message) {
25
+ if (required || checkOnly) {
26
+ throw new Error(message);
27
+ }
28
+ warn(message);
29
+ }
30
+
31
+ function readJson(filePath) {
32
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
33
+ }
34
+
35
+ function run(command, commandArgs, options = {}) {
36
+ const result = spawnSync(command, commandArgs, {
37
+ cwd: options.cwd ?? root,
38
+ encoding: 'utf-8',
39
+ stdio: options.stdio ?? ['ignore', 'pipe', 'pipe'],
40
+ timeout: options.timeout ?? 120000,
41
+ });
42
+
43
+ if (result.error) {
44
+ throw result.error;
45
+ }
46
+ if (result.status !== 0) {
47
+ const stderr = result.stderr?.trim();
48
+ throw new Error(
49
+ `${command} ${commandArgs.join(' ')} failed${
50
+ stderr ? `: ${stderr}` : ''
51
+ }`,
52
+ );
53
+ }
54
+ return result.stdout?.trim() ?? '';
55
+ }
56
+
57
+ function assertSafeRepoPath(relativePath) {
58
+ if (
59
+ typeof relativePath !== 'string' ||
60
+ relativePath.length === 0 ||
61
+ path.isAbsolute(relativePath) ||
62
+ relativePath.split(/[\\/]+/).includes('..') ||
63
+ !relativePath.startsWith('repos/')
64
+ ) {
65
+ throw new Error(`Unsafe reference repository path: ${relativePath}`);
66
+ }
67
+ }
68
+
69
+ function hasGit() {
70
+ const result = spawnSync('git', ['--version'], {
71
+ encoding: 'utf-8',
72
+ stdio: ['ignore', 'pipe', 'pipe'],
73
+ });
74
+ return result.status === 0;
75
+ }
76
+
77
+ function existingReference(targetPath, repo) {
78
+ const markerPath = path.join(targetPath, '.ultramodern-reference-repo.json');
79
+ if (!fs.existsSync(markerPath)) {
80
+ return undefined;
81
+ }
82
+ try {
83
+ const marker = readJson(markerPath);
84
+ if (marker.url === repo.url && marker.ref === repo.ref) {
85
+ return marker;
86
+ }
87
+ } catch {
88
+ return undefined;
89
+ }
90
+ return undefined;
91
+ }
92
+
93
+ function materializeRepository(repo) {
94
+ assertSafeRepoPath(repo.path);
95
+ const targetPath = path.join(root, repo.path);
96
+ const existing = existingReference(targetPath, repo);
97
+
98
+ if (existing && !refresh) {
99
+ log(`${repo.id} already present at ${repo.path} (${existing.commit})`);
100
+ return { ...existing, status: 'present' };
101
+ }
102
+
103
+ if (fs.existsSync(targetPath)) {
104
+ if (!refresh) {
105
+ fail(`${repo.path} exists but is not a managed reference repo`);
106
+ return undefined;
107
+ }
108
+ fs.rmSync(targetPath, { recursive: true, force: true });
109
+ }
110
+
111
+ if (checkOnly) {
112
+ fail(`${repo.path} is missing`);
113
+ return undefined;
114
+ }
115
+
116
+ fs.mkdirSync(tempRoot, { recursive: true });
117
+ const tempPath = fs.mkdtempSync(path.join(tempRoot, `${repo.id}-`));
118
+
119
+ try {
120
+ log(`cloning ${repo.name} from ${repo.url}#${repo.ref}`);
121
+ run(
122
+ 'git',
123
+ [
124
+ 'clone',
125
+ '--depth',
126
+ '1',
127
+ '--single-branch',
128
+ '--branch',
129
+ repo.ref,
130
+ '--filter=blob:none',
131
+ repo.url,
132
+ tempPath,
133
+ ],
134
+ { timeout: 300000 },
135
+ );
136
+ const commit = run('git', ['-C', tempPath, 'rev-parse', 'HEAD']);
137
+ fs.rmSync(path.join(tempPath, '.git'), { recursive: true, force: true });
138
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
139
+ fs.renameSync(tempPath, targetPath);
140
+
141
+ const marker = {
142
+ schemaVersion: 1,
143
+ id: repo.id,
144
+ name: repo.name,
145
+ url: repo.url,
146
+ ref: repo.ref,
147
+ commit,
148
+ path: repo.path,
149
+ readOnly: repo.readOnly !== false,
150
+ installedAt: new Date().toISOString(),
151
+ };
152
+ fs.writeFileSync(
153
+ path.join(targetPath, '.ultramodern-reference-repo.json'),
154
+ `${JSON.stringify(marker, null, 2)}\n`,
155
+ );
156
+ log(`${repo.id} installed at ${repo.path} (${commit})`);
157
+ return { ...marker, status: 'installed' };
158
+ } catch (error) {
159
+ fs.rmSync(tempPath, { recursive: true, force: true });
160
+ fail(`Could not install ${repo.id}: ${error.message}`);
161
+ return undefined;
162
+ }
163
+ }
164
+
165
+ function main() {
166
+ if (!fs.existsSync(configPath)) {
167
+ fail('Missing .agents/agent-reference-repos.json');
168
+ return;
169
+ }
170
+
171
+ const config = readJson(configPath);
172
+ const enabled = config.defaultEnabled !== false && !skipRequested;
173
+
174
+ if (!enabled) {
175
+ log('setup skipped; set ULTRAMODERN_SKIP_AGENT_REPOS=0 to enable it again');
176
+ return;
177
+ }
178
+
179
+ if (!hasGit()) {
180
+ fail('git is required to install agent reference repositories');
181
+ return;
182
+ }
183
+
184
+ const installed = [];
185
+ for (const repo of config.repositories ?? []) {
186
+ const result = materializeRepository(repo);
187
+ if (result) {
188
+ installed.push(result);
189
+ }
190
+ }
191
+
192
+ if (!checkOnly) {
193
+ fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
194
+ fs.writeFileSync(
195
+ manifestPath,
196
+ `${JSON.stringify(
197
+ {
198
+ schemaVersion: 1,
199
+ generatedAt: new Date().toISOString(),
200
+ installDir: config.installDir ?? 'repos',
201
+ repositories: installed,
202
+ },
203
+ null,
204
+ 2,
205
+ )}\n`,
206
+ );
207
+ }
208
+ }
209
+
210
+ try {
211
+ main();
212
+ } catch (error) {
213
+ console.error(`[agent-reference-repos] ${error.message}`);
214
+ process.exitCode = 1;
215
+ } finally {
216
+ fs.rmSync(tempRoot, { recursive: true, force: true });
217
+ }
@@ -36,6 +36,7 @@ const assertExists = (relativePath) => {
36
36
 
37
37
  const requiredPaths = [
38
38
  'AGENTS.md',
39
+ '.gitignore',
39
40
  'package.json',
40
41
  'pnpm-workspace.yaml',
41
42
  'tsconfig.base.json',
@@ -44,6 +45,7 @@ const requiredPaths = [
44
45
  '.github/renovate.json',
45
46
  '.github/workflows/ultramodern-workspace-gates.yml',
46
47
  '.agents/skills-lock.json',
48
+ '.agents/agent-reference-repos.json',
47
49
  '.agents/rstackjs-agent-skills-LICENSE',
48
50
  '.agents/skills/rsbuild-best-practices/SKILL.md',
49
51
  '.agents/skills/rspack-best-practices/SKILL.md',
@@ -61,6 +63,7 @@ const requiredPaths = [
61
63
  '.modernjs/ultramodern-workspace-template-manifest.json',
62
64
  '.modernjs/ultramodern-package-source.json',
63
65
  'scripts/bootstrap-agent-skills.mjs',
66
+ 'scripts/setup-agent-reference-repos.mjs',
64
67
  'scripts/check-i18n-strings.mjs',
65
68
  'apps/shell-super-app/package.json',
66
69
  'apps/shell-super-app/config/public/locales/en/translation.json',
@@ -122,6 +125,7 @@ for (const appDirectory of [
122
125
  const rootPackage = readJson('package.json');
123
126
  const packageSource = readJson('.modernjs/ultramodern-package-source.json');
124
127
  const skillsLock = readJson('.agents/skills-lock.json');
128
+ const agentReferenceRepos = readJson('.agents/agent-reference-repos.json');
125
129
  const pnpmWorkspace = readText('pnpm-workspace.yaml');
126
130
  const workflowContent = readText('.github/workflows/ultramodern-workspace-gates.yml');
127
131
  const renovateConfig = readJson('.github/renovate.json');
@@ -237,6 +241,9 @@ const requiredRootScripts = {
237
241
  'i18n:check': 'node ./scripts/check-i18n-strings.mjs',
238
242
  lint: 'oxlint .',
239
243
  'lint:fix': 'oxlint . --fix',
244
+ 'agents:refs:check': 'node ./scripts/setup-agent-reference-repos.mjs --check',
245
+ 'agents:refs:install': 'node ./scripts/setup-agent-reference-repos.mjs',
246
+ postinstall: 'node ./scripts/setup-agent-reference-repos.mjs',
240
247
  'skills:check': 'node ./scripts/bootstrap-agent-skills.mjs --check',
241
248
  'skills:install': 'node ./scripts/bootstrap-agent-skills.mjs',
242
249
  typecheck: `pnpm -r --filter "@${packageScope}/*" typecheck`,
@@ -274,6 +281,34 @@ assert(
274
281
  skillsLock.installDir === '.agents/skills',
275
282
  'Agent skills lock must use .agents/skills as installDir',
276
283
  );
284
+ assert(
285
+ agentReferenceRepos.defaultEnabled === true,
286
+ 'Agent reference repositories must be enabled by default',
287
+ );
288
+ assert(
289
+ agentReferenceRepos.repositories?.some(
290
+ (repo) =>
291
+ repo.id === 'effect' &&
292
+ repo.url === 'https://github.com/Effect-TS/effect.git' &&
293
+ repo.path === 'repos/effect',
294
+ ),
295
+ 'Agent reference repositories must include Effect',
296
+ );
297
+ assert(
298
+ agentReferenceRepos.repositories?.some(
299
+ (repo) =>
300
+ repo.id === 'ultramodern-js' &&
301
+ repo.url === 'https://github.com/BleedingDev/ultramodern.js.git' &&
302
+ repo.path === 'repos/ultramodern.js',
303
+ ),
304
+ 'Agent reference repositories must include UltraModern.js',
305
+ );
306
+ assert(
307
+ readText('scripts/setup-agent-reference-repos.mjs').includes(
308
+ 'ULTRAMODERN_SKIP_AGENT_REPOS',
309
+ ),
310
+ 'Agent reference repository setup must expose an opt-out environment variable',
311
+ );
277
312
  for (const skillName of baselineAgentSkills) {
278
313
  assert(
279
314
  skillsLock.baseline?.some((skill) => skill.name === skillName),
@@ -357,6 +392,10 @@ for (const packagePath of appPackagePaths) {
357
392
  packageJson.dependencies?.['@module-federation/modern-js-v3'] === '2.4.0',
358
393
  `${packagePath} must include the Module Federation plugin`,
359
394
  );
395
+ assert(
396
+ packageJson.dependencies?.['zephyr-modernjs-plugin'] === '1.1.1',
397
+ `${packagePath} must include the official Zephyr Modern.js plugin`,
398
+ );
360
399
  assert(
361
400
  packageJson.modernjs?.preset === 'presetUltramodern',
362
401
  `${packagePath} must keep presetUltramodern metadata`,
@@ -383,6 +422,27 @@ for (const configPath of [
383
422
  config.includes('moduleFederationPlugin()'),
384
423
  `${configPath} must enable Module Federation`,
385
424
  );
425
+ assert(
426
+ config.includes("from 'zephyr-modernjs-plugin'"),
427
+ `${configPath} must import the official Zephyr Modern.js plugin`,
428
+ );
429
+ assert(config.includes('withZephyr()'), `${configPath} must enable Zephyr through plugins`);
430
+ assert(
431
+ config.includes("bundler: 'rspack'"),
432
+ `${configPath} must keep appTools on the rspack bundler for Zephyr`,
433
+ );
434
+ assert(
435
+ config.includes("html: './'"),
436
+ `${configPath} must keep Modern.js output.distPath.html compatible with Zephyr`,
437
+ );
438
+ assert(
439
+ config.includes("outputStructure: 'flat'"),
440
+ `${configPath} must keep Modern.js HTML output flat for Zephyr`,
441
+ );
442
+ assert(
443
+ config.includes("mainEntryName: 'index'"),
444
+ `${configPath} must keep Modern.js source.mainEntryName compatible with Zephyr`,
445
+ );
386
446
  }
387
447
 
388
448
  for (const routePath of [