@memberjunction/cli 6.2.0-edge.5 → 6.2.0-edge.7

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.
Files changed (97) hide show
  1. package/README.md +95 -0
  2. package/dist/commands/agent/init.d.ts +5 -0
  3. package/dist/commands/agent/init.d.ts.map +1 -1
  4. package/dist/commands/agent/init.js +109 -0
  5. package/dist/commands/agent/init.js.map +1 -1
  6. package/dist/commands/ai/actions/run.d.ts.map +1 -1
  7. package/dist/commands/ai/actions/run.js +5 -1
  8. package/dist/commands/ai/actions/run.js.map +1 -1
  9. package/dist/commands/ai/agents/run.d.ts +1 -0
  10. package/dist/commands/ai/agents/run.d.ts.map +1 -1
  11. package/dist/commands/ai/agents/run.js +20 -6
  12. package/dist/commands/ai/agents/run.js.map +1 -1
  13. package/dist/commands/ai/prompts/run.d.ts.map +1 -1
  14. package/dist/commands/ai/prompts/run.js +5 -1
  15. package/dist/commands/ai/prompts/run.js.map +1 -1
  16. package/dist/commands/app/install.d.ts.map +1 -1
  17. package/dist/commands/app/install.js +17 -2
  18. package/dist/commands/app/install.js.map +1 -1
  19. package/dist/commands/app/upgrade.d.ts.map +1 -1
  20. package/dist/commands/app/upgrade.js +7 -1
  21. package/dist/commands/app/upgrade.js.map +1 -1
  22. package/dist/commands/dev/workspace/clean.d.ts +2 -1
  23. package/dist/commands/dev/workspace/clean.d.ts.map +1 -1
  24. package/dist/commands/dev/workspace/clean.js +4 -3
  25. package/dist/commands/dev/workspace/clean.js.map +1 -1
  26. package/dist/commands/dev/workspace/doctor.d.ts.map +1 -1
  27. package/dist/commands/dev/workspace/doctor.js +3 -2
  28. package/dist/commands/dev/workspace/doctor.js.map +1 -1
  29. package/dist/commands/dev/workspace/index.d.ts +2 -2
  30. package/dist/commands/dev/workspace/index.d.ts.map +1 -1
  31. package/dist/commands/dev/workspace/index.js +12 -9
  32. package/dist/commands/dev/workspace/index.js.map +1 -1
  33. package/dist/commands/dev/workspace/status.d.ts +1 -1
  34. package/dist/commands/dev/workspace/status.js +1 -1
  35. package/dist/commands/query/refresh.d.ts +25 -0
  36. package/dist/commands/query/refresh.d.ts.map +1 -0
  37. package/dist/commands/query/refresh.js +67 -0
  38. package/dist/commands/query/refresh.js.map +1 -0
  39. package/dist/commands/query/usage.d.ts +7 -0
  40. package/dist/commands/query/usage.d.ts.map +1 -0
  41. package/dist/commands/query/usage.js +10 -0
  42. package/dist/commands/query/usage.js.map +1 -0
  43. package/dist/commands/user/clone.d.ts.map +1 -1
  44. package/dist/commands/user/clone.js +1 -0
  45. package/dist/commands/user/clone.js.map +1 -1
  46. package/dist/init-templates/citizen-builder/.agents/skills/new-agent/SKILL.md +19 -6
  47. package/dist/init-templates/citizen-builder/.agents/skills/test-agent/SKILL.md +4 -1
  48. package/dist/init-templates/citizen-builder/.claude/skills/new-agent/SKILL.md +19 -6
  49. package/dist/init-templates/citizen-builder/.claude/skills/test-agent/SKILL.md +4 -1
  50. package/dist/init-templates/citizen-builder/.env.example +4 -2
  51. package/dist/init-templates/citizen-builder/AGENTS.md +136 -40
  52. package/dist/init-templates/citizen-builder/README.md +18 -5
  53. package/dist/init-templates/citizen-builder/docker-compose.yml +6 -5
  54. package/dist/init-templates/citizen-builder/metadata/.mj-sync.json +7 -4
  55. package/dist/init-templates/citizen-builder/metadata/agents/.customer-insight-agent.json +17 -13
  56. package/dist/init-templates/citizen-builder/metadata/prompts/.customer-insight-prompt.json +3 -1
  57. package/dist/init-templates/citizen-builder/metadata/prompts/templates/customer-insight.template.md +8 -0
  58. package/dist/init-templates/citizen-builder/scripts/docker-entrypoint.sh +140 -38
  59. package/dist/init-templates/citizen-builder/scripts/sync-metadata.sh +1 -1
  60. package/dist/lib/dev-workspace/build-output.d.ts +22 -0
  61. package/dist/lib/dev-workspace/build-output.d.ts.map +1 -0
  62. package/dist/lib/dev-workspace/build-output.js +146 -0
  63. package/dist/lib/dev-workspace/build-output.js.map +1 -0
  64. package/dist/lib/dev-workspace/build.d.ts +6 -6
  65. package/dist/lib/dev-workspace/build.d.ts.map +1 -1
  66. package/dist/lib/dev-workspace/build.js +59 -34
  67. package/dist/lib/dev-workspace/build.js.map +1 -1
  68. package/dist/lib/dev-workspace/clean.d.ts +19 -5
  69. package/dist/lib/dev-workspace/clean.d.ts.map +1 -1
  70. package/dist/lib/dev-workspace/clean.js +44 -12
  71. package/dist/lib/dev-workspace/clean.js.map +1 -1
  72. package/dist/lib/dev-workspace/detect.d.ts.map +1 -1
  73. package/dist/lib/dev-workspace/detect.js +0 -2
  74. package/dist/lib/dev-workspace/detect.js.map +1 -1
  75. package/dist/lib/dev-workspace/doctor.d.ts.map +1 -1
  76. package/dist/lib/dev-workspace/doctor.js +63 -5
  77. package/dist/lib/dev-workspace/doctor.js.map +1 -1
  78. package/dist/lib/dev-workspace/lockfile.d.ts +9 -1
  79. package/dist/lib/dev-workspace/lockfile.d.ts.map +1 -1
  80. package/dist/lib/dev-workspace/lockfile.js +19 -8
  81. package/dist/lib/dev-workspace/lockfile.js.map +1 -1
  82. package/dist/lib/dev-workspace/types.d.ts +40 -16
  83. package/dist/lib/dev-workspace/types.d.ts.map +1 -1
  84. package/dist/lib/dev-workspace/types.js +2 -2
  85. package/dist/lib/dev-workspace/write.d.ts +7 -2
  86. package/dist/lib/dev-workspace/write.d.ts.map +1 -1
  87. package/dist/lib/dev-workspace/write.js +7 -3
  88. package/dist/lib/dev-workspace/write.js.map +1 -1
  89. package/dist/lib/domain-profiles.d.ts.map +1 -1
  90. package/dist/lib/domain-profiles.js +4 -0
  91. package/dist/lib/domain-profiles.js.map +1 -1
  92. package/dist/lib/query-refresh.d.ts +23 -0
  93. package/dist/lib/query-refresh.d.ts.map +1 -0
  94. package/dist/lib/query-refresh.js +33 -0
  95. package/dist/lib/query-refresh.js.map +1 -0
  96. package/oclif.manifest.json +2615 -2471
  97. package/package.json +27 -26
@@ -58,31 +58,37 @@ if [ ! -f "$STATE_DIR/provisioned" ]; then
58
58
  echo "========================================================================"
59
59
 
60
60
  if [ ! -f "$STATE_DIR/core-installed" ]; then
61
- # Generate install configuration
62
- cat << EOF > /tmp/install.config.json
63
- {
64
- "PackageManager": "pnpm",
65
- "dbUrl": "$DB_HOST",
66
- "dbInstance": "",
67
- "dbTrustServerCertificate": "Y",
68
- "dbDatabase": "$DB_DATABASE",
69
- "dbPort": $DB_PORT,
70
- "codeGenLogin": "sa",
71
- "codeGenPwD": "$DB_PASSWORD",
72
- "mjAPILogin": "sa",
73
- "mjAPIPwD": "$DB_PASSWORD",
74
- "graphQLPort": 4000,
75
- "authType": "Local",
76
- "createNewUser": "Y",
77
- "userEmail": "admin@memberjunction.org",
78
- "userFirstName": "Admin",
79
- "userLastName": "User",
80
- "userName": "admin",
81
- "openAIAPIKey": "${AI_VENDOR_API_KEY__OpenAILLM:-}",
82
- "anthropicAPIKey": "${AI_VENDOR_API_KEY__AnthropicLLM:-}",
83
- "geminiAPIKey": "${AI_VENDOR_API_KEY__GeminiLLM:-}"
84
- }
85
- EOF
61
+ # Generate install configuration safely via JSON.stringify so special characters in passwords/keys are escaped
62
+ node -e "
63
+ const fs = require('fs');
64
+ const cfg = {
65
+ PackageManager: 'pnpm',
66
+ DatabaseHost: process.env.DB_HOST || 'sqlserver',
67
+ DatabasePort: Number(process.env.DB_PORT || 1433),
68
+ DatabaseName: process.env.DB_DATABASE || 'MemberJunction',
69
+ DatabaseTrustCert: true,
70
+ DatabaseAdminUser: 'sa',
71
+ DatabaseAdminPassword: process.env.DB_PASSWORD || '',
72
+ CodeGenUser: 'sa',
73
+ CodeGenPassword: process.env.DB_PASSWORD || '',
74
+ APIUser: 'sa',
75
+ APIPassword: process.env.DB_PASSWORD || '',
76
+ APIPort: 4000,
77
+ AuthProvider: 'local',
78
+ BaseEncryptionKey: process.env.MJ_BASE_ENCRYPTION_KEY || 'MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=',
79
+ CreateNewUser: {
80
+ Username: 'admin',
81
+ Email: 'admin@memberjunction.org',
82
+ FirstName: 'Admin',
83
+ LastName: 'User'
84
+ },
85
+ OpenAIKey: process.env.AI_VENDOR_API_KEY__OpenAILLM || '',
86
+ AnthropicKey: process.env.AI_VENDOR_API_KEY__AnthropicLLM || '',
87
+ GeminiKey: process.env.AI_VENDOR_API_KEY__GeminiLLM || '',
88
+ MistralKey: process.env.AI_VENDOR_API_KEY__MistralLLM || ''
89
+ };
90
+ fs.writeFileSync('/tmp/install.config.json', JSON.stringify(cfg, null, 2), { mode: 0o600 });
91
+ "
86
92
 
87
93
  # Install the release this workspace is pinned to (MJ_VERSION, the same release as the CLI
88
94
  # in this container). Without a tag, `mj install --yes` takes the newest stable GitHub
@@ -96,20 +102,17 @@ EOF
96
102
 
97
103
  # Execute headless install. Safe to retry: the installer checkpoints completed phases.
98
104
  mj install --yes --fast --config /tmp/install.config.json --dir /workspace "${INSTALL_TAG_ARGS[@]}"
105
+ rm -f /tmp/install.config.json
99
106
  touch "$STATE_DIR/core-installed"
100
107
  pnpm add -w @angular/compiler@21.2.22 2>/dev/null || true
101
108
  fi
102
109
 
103
110
  # Install Open App business context (More Cheese default or custom enterprise app)
111
+ # Note: GITHUB_TOKEN is read directly from the environment by OpenAppEngine's GitHubClient
104
112
  if [ ! -f "$STATE_DIR/app-installed" ]; then
105
113
  APP_URL="${OPEN_APP_INSTALL_URL:-https://github.com/MemberJunction/more-cheese}"
106
114
  echo "Installing business context Open App: $APP_URL..."
107
- if [ -n "$GITHUB_TOKEN" ]; then
108
- AUTH_APP_URL=$(echo "$APP_URL" | sed -E "s|https://github.com/|https://$GITHUB_TOKEN@github.com/|")
109
- mj app install "$AUTH_APP_URL"
110
- else
111
- mj app install "$APP_URL"
112
- fi
115
+ mj app install "$APP_URL"
113
116
  touch "$STATE_DIR/app-installed"
114
117
  fi
115
118
 
@@ -120,8 +123,8 @@ EOF
120
123
  || echo "WARNING: capabilities catalog generation failed, so the catalog may be missing or stale. Re-run scripts/generate-capabilities.sh."
121
124
  fi
122
125
 
123
- # Push starter metadata. --ci: never prompt (there is no terminal here) and exit non-zero
124
- # on error. Safe to repeat on a retry: mj sync push upserts.
126
+ # Push starter metadata. --ci: never prompt (there is no terminal here), create
127
+ # Template records for @file: prompt templates on first push, and exit non-zero on error.
125
128
  if [ -d "/work/metadata" ]; then
126
129
  mj sync push --dir /work/metadata --ci
127
130
  fi
@@ -156,10 +159,82 @@ if [ -f "apps/MJExplorer/package.json" ]; then
156
159
  "
157
160
  fi
158
161
 
162
+ # Ensure turbo.json passes through AI vendor API keys, DB settings, and MJ_DEV_AUTH_ENABLED to child processes
163
+ if [ -f "turbo.json" ]; then
164
+ node -e "
165
+ const fs = require('fs');
166
+ try {
167
+ const turbo = JSON.parse(fs.readFileSync('turbo.json', 'utf8'));
168
+ const passThrough = new Set(turbo.globalPassThroughEnv || []);
169
+ let changed = false;
170
+ for (const entry of ['AI_VENDOR_API_KEY__*', 'MJ_*', 'DB_*', 'CODEGEN_DB_*', 'GRAPHQL_*', 'OPEN_APP_*', 'GITHUB_TOKEN']) {
171
+ if (!passThrough.has(entry)) {
172
+ passThrough.add(entry);
173
+ changed = true;
174
+ }
175
+ }
176
+ if (changed) {
177
+ turbo.globalPassThroughEnv = Array.from(passThrough);
178
+ fs.writeFileSync('turbo.json', JSON.stringify(turbo, null, 2) + '\n');
179
+ }
180
+ } catch (e) {
181
+ console.warn('Notice: turbo.json check skipped:', e.message);
182
+ }
183
+ "
184
+ fi
185
+
186
+ # Sync container environment variables (API keys, encryption key, DB_USER, local dev auth) into workspace .env files
187
+ export MJ_DEV_AUTH_ENABLED="${MJ_DEV_AUTH_ENABLED:-true}"
188
+ node -e "
189
+ const fs = require('fs');
190
+ const upsertVar = (content, key, val) => {
191
+ const re = new RegExp('^' + key + '=.*$', 'm');
192
+ const line = key + '=' + JSON.stringify(String(val));
193
+ if (re.test(content)) return content.replace(re, () => line);
194
+ return content + (content.endsWith('\n') ? '' : '\n') + line + '\n';
195
+ };
196
+ const keysToSync = [
197
+ 'DB_HOST', 'DB_PORT', 'DB_DATABASE', 'DB_USERNAME', 'DB_PASSWORD',
198
+ 'MJ_BASE_ENCRYPTION_KEY', 'MJ_DEV_AUTH_ENABLED',
199
+ 'AI_VENDOR_API_KEY__OpenAILLM', 'AI_VENDOR_API_KEY__AnthropicLLM',
200
+ 'AI_VENDOR_API_KEY__GeminiLLM', 'AI_VENDOR_API_KEY__GroqLLM', 'AI_VENDOR_API_KEY__MistralLLM'
201
+ ];
202
+ for (const envFile of ['.env', 'apps/MJAPI/.env', 'packages/MJAPI/.env']) {
203
+ if (fs.existsSync(envFile)) {
204
+ let content = fs.readFileSync(envFile, 'utf8');
205
+ for (const k of keysToSync) {
206
+ const v = process.env[k];
207
+ if (v !== undefined && v !== '') {
208
+ content = upsertVar(content, k, v);
209
+ }
210
+ }
211
+ content = upsertVar(content, 'DB_USER', process.env.DB_USERNAME || 'sa');
212
+ fs.writeFileSync(envFile, content);
213
+ }
214
+ }
215
+ if (process.env.MJ_DEV_AUTH_ENABLED === 'true') {
216
+ for (const ngEnv of [
217
+ 'apps/MJExplorer/src/environments/environment.ts',
218
+ 'apps/MJExplorer/src/environments/environment.development.ts',
219
+ 'packages/MJExplorer/src/environments/environment.ts',
220
+ 'packages/MJExplorer/src/environments/environment.development.ts',
221
+ ]) {
222
+ if (fs.existsSync(ngEnv)) {
223
+ const src = fs.readFileSync(ngEnv, 'utf8');
224
+ const next = src.replace(/AUTH_TYPE:\s*['\"][^'\"]*['\"]/g, \"AUTH_TYPE: 'local'\");
225
+ if (next !== src) {
226
+ fs.writeFileSync(ngEnv, next);
227
+ }
228
+ }
229
+ }
230
+ }
231
+ "
232
+
159
233
  # Sanitize dynamicPackages.client so non-browser packages are not bundled into MJExplorer
160
234
  if [ -f "mj.config.cjs" ]; then
161
235
  node -e "
162
236
  const fs = require('fs');
237
+ const vm = require('vm');
163
238
  try {
164
239
  const config = require('./mj.config.cjs');
165
240
  if (config.dynamicPackages && Array.isArray(config.dynamicPackages.client)) {
@@ -173,10 +248,37 @@ if [ -f "mj.config.cjs" ]; then
173
248
  }
174
249
  });
175
250
  if (changed) {
176
- let code = fs.readFileSync('mj.config.cjs', 'utf8');
177
- const regex = /client:\s*\[[\s\S]*?\]\s*\},/m;
178
- code = code.replace(regex, 'client: ' + JSON.stringify(config.dynamicPackages.client, null, 2) + '\n },');
179
- fs.writeFileSync('mj.config.cjs', code);
251
+ const code = fs.readFileSync('mj.config.cjs', 'utf8');
252
+ const dynMatch = code.match(/dynamicPackages\s*:\s*\{/);
253
+ if (dynMatch && dynMatch.index !== undefined) {
254
+ const afterDyn = code.slice(dynMatch.index);
255
+ const clientRel = afterDyn.match(/client\s*:\s*\[/);
256
+ if (clientRel && clientRel.index !== undefined) {
257
+ const openPos = dynMatch.index + clientRel.index + clientRel[0].length - 1;
258
+ let depth = 1, pos = openPos + 1, inStr = null;
259
+ while (pos < code.length && depth > 0) {
260
+ const ch = code[pos];
261
+ if (inStr) {
262
+ if (ch === '\\\\') { pos += 2; continue; }
263
+ if (ch === inStr) inStr = null;
264
+ } else if (ch === '\"' || ch === \"'\" || ch === '\`') {
265
+ inStr = ch;
266
+ } else if (ch === '[') {
267
+ depth++;
268
+ } else if (ch === ']') {
269
+ depth--;
270
+ }
271
+ pos++;
272
+ }
273
+ if (depth === 0) {
274
+ const closePos = pos - 1;
275
+ const serialized = JSON.stringify(config.dynamicPackages.client, null, 2).replace(/\n/g, '\n ');
276
+ const updated = code.slice(0, openPos) + serialized + code.slice(closePos + 1);
277
+ vm.compileFunction(updated);
278
+ fs.writeFileSync('mj.config.cjs', updated);
279
+ }
280
+ }
281
+ }
180
282
  }
181
283
  }
182
284
  } catch (e) {
@@ -212,7 +314,7 @@ fi
212
314
  echo "========================================================================"
213
315
  echo " 🎉 MemberJunction Stack is Running!"
214
316
  echo " MJAPI: http://localhost:4000 (GraphQL & API)"
215
- echo " MJExplorer: http://localhost:4200 (Web Interface)"
317
+ echo " MJExplorer: http://localhost:4200 (Web Interface — Zero-Config Local Dev Auth active)"
216
318
  echo " Database: localhost:$DB_PORT (DB: $DB_DATABASE)"
217
319
  echo "========================================================================"
218
320
 
@@ -9,6 +9,6 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
9
9
  cd "$DIR"
10
10
 
11
11
  echo "Pushing metadata changes to MemberJunction database..."
12
- docker compose exec -T mj mj sync push --dir /work/metadata
12
+ docker compose exec -T mj mj sync push --dir /work/metadata "$@"
13
13
 
14
14
  echo "Metadata sync complete!"
@@ -0,0 +1,22 @@
1
+ import type { BuildOutputEntry, MemberPackageJson } from './types.js';
2
+ /**
3
+ * The entry file a package declares, relative to its directory, or null when it declares none.
4
+ * `main` first: it is what Node and the Angular builders resolve for every MJ package. Pure.
5
+ */
6
+ export declare function ResolveEntryFile(pkg: MemberPackageJson): string | null;
7
+ /**
8
+ * The output folder for a declared entry file: its first path segment (`dist/esm/index.js` →
9
+ * `dist`). Null when the entry sits at the package root or inside `src/` — such a package ships
10
+ * its source, so there is no build output to compare. Pure.
11
+ */
12
+ export declare function OutputDirOf(entryFile: string): string | null;
13
+ /**
14
+ * Reads the build state of every member package that has a `build` script and a `src/` folder.
15
+ *
16
+ * `memberNames` is passed in for the same reason {@link CollectClientPackageCensus} takes it:
17
+ * detection finds every Open App repo on disk, and an excluded sibling is not this workspace's
18
+ * concern. A package whose entry points into `src/` or sits at its root ships source and is left
19
+ * out — it has no output to go stale.
20
+ */
21
+ export declare function CollectBuildOutputCensus(parentDir: string, memberNames: readonly string[]): BuildOutputEntry[];
22
+ //# sourceMappingURL=build-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-output.d.ts","sourceRoot":"","sources":["../../../src/lib/dev-workspace/build-output.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAoB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAgCxF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAItE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM5D;AAuCD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAsB9G"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Build-output census for `mj dev workspace doctor`.
3
+ *
4
+ * SIDE EFFECTS: READ-ONLY filesystem access — `existsSync`, `readdirSync` and `statSync` under
5
+ * member package directories. Never writes, never spawns a build.
6
+ *
7
+ * Linking a member package into the workspace links its SOURCE folder, so a package whose output
8
+ * was never built, or was built before its last source edit, still resolves at install time. It
9
+ * fails only when a host imports it: a missing export, or "No form is registered for …" in
10
+ * Explorer. This census names those packages before anything starts (#5494).
11
+ *
12
+ * @module lib/dev-workspace/build-output
13
+ */
14
+ import { existsSync, readdirSync, statSync } from 'node:fs';
15
+ import path from 'node:path';
16
+ import { DetectCandidates } from './detect.js';
17
+ /** Where a package builds to when its package.json names no entry point. */
18
+ const DEFAULT_OUTPUT_DIR = 'dist';
19
+ /** Source folder whose files the output is compared against. */
20
+ const SOURCE_DIR = 'src';
21
+ /** Directories never descended into while finding the newest file. */
22
+ const SKIPPED_DIRS = new Set(['node_modules', '__tests__', '__mocks__']);
23
+ /** Test files: editing one does not make the build output stale. */
24
+ const TEST_FILE_PATTERN = /\.(spec|test)\.[cm]?[jt]sx?$/;
25
+ /**
26
+ * The root export's file from an `exports` field: a string, or the `.` entry of a conditions
27
+ * object, itself a string or a conditions object whose `import` / `default` / `require` is one.
28
+ * Any other shape returns null, and the caller falls back to `main` / `module`. Pure.
29
+ */
30
+ function rootExportPath(exportsField) {
31
+ if (typeof exportsField === 'string')
32
+ return exportsField;
33
+ if (exportsField === null || typeof exportsField !== 'object')
34
+ return null;
35
+ const root = exportsField['.'];
36
+ if (typeof root === 'string')
37
+ return root;
38
+ if (root === null || typeof root !== 'object')
39
+ return null;
40
+ for (const condition of ['import', 'default', 'require']) {
41
+ const target = root[condition];
42
+ if (typeof target === 'string')
43
+ return target;
44
+ }
45
+ return null;
46
+ }
47
+ /**
48
+ * The entry file a package declares, relative to its directory, or null when it declares none.
49
+ * `main` first: it is what Node and the Angular builders resolve for every MJ package. Pure.
50
+ */
51
+ export function ResolveEntryFile(pkg) {
52
+ const entry = pkg.main ?? pkg.module ?? rootExportPath(pkg.exports);
53
+ if (entry === undefined || entry === null || entry.length === 0)
54
+ return null;
55
+ return path.normalize(entry);
56
+ }
57
+ /**
58
+ * The output folder for a declared entry file: its first path segment (`dist/esm/index.js` →
59
+ * `dist`). Null when the entry sits at the package root or inside `src/` — such a package ships
60
+ * its source, so there is no build output to compare. Pure.
61
+ */
62
+ export function OutputDirOf(entryFile) {
63
+ const segments = entryFile.split(path.sep).filter((segment) => segment.length > 0 && segment !== '.');
64
+ if (segments.length < 2)
65
+ return null;
66
+ const first = segments[0];
67
+ if (first === '..' || first === SOURCE_DIR)
68
+ return null;
69
+ return first;
70
+ }
71
+ /**
72
+ * Newest modification time of any file under `dir`, skipping {@link SKIPPED_DIRS}, dot
73
+ * directories and (when `skipTests`) test files. Returns 0 for a missing or empty folder.
74
+ */
75
+ function newestFileTime(dir, skipTests) {
76
+ let newest = 0;
77
+ const pending = [dir];
78
+ for (let current = pending.pop(); current !== undefined; current = pending.pop()) {
79
+ let entries;
80
+ try {
81
+ entries = readdirSync(current, { withFileTypes: true });
82
+ }
83
+ catch {
84
+ continue;
85
+ }
86
+ for (const entry of entries) {
87
+ if (entry.isDirectory()) {
88
+ if (!SKIPPED_DIRS.has(entry.name) && !entry.name.startsWith('.'))
89
+ pending.push(path.join(current, entry.name));
90
+ continue;
91
+ }
92
+ if (!entry.isFile())
93
+ continue;
94
+ if (skipTests && TEST_FILE_PATTERN.test(entry.name))
95
+ continue;
96
+ newest = Math.max(newest, statSync(path.join(current, entry.name)).mtimeMs);
97
+ }
98
+ }
99
+ return newest;
100
+ }
101
+ /** Build state of one package directory with the given output folder and optional entry file. */
102
+ function readBuildState(packageDir, outputDir, entryFile) {
103
+ const outputPath = path.join(packageDir, outputDir);
104
+ const builtMarker = entryFile === null ? outputPath : path.join(packageDir, entryFile);
105
+ if (!existsSync(builtMarker))
106
+ return 'missing';
107
+ const newestOutput = newestFileTime(outputPath, false);
108
+ if (newestOutput === 0)
109
+ return 'missing';
110
+ return newestFileTime(path.join(packageDir, SOURCE_DIR), true) > newestOutput ? 'stale' : 'fresh';
111
+ }
112
+ /**
113
+ * Reads the build state of every member package that has a `build` script and a `src/` folder.
114
+ *
115
+ * `memberNames` is passed in for the same reason {@link CollectClientPackageCensus} takes it:
116
+ * detection finds every Open App repo on disk, and an excluded sibling is not this workspace's
117
+ * concern. A package whose entry points into `src/` or sits at its root ships source and is left
118
+ * out — it has no output to go stale.
119
+ */
120
+ export function CollectBuildOutputCensus(parentDir, memberNames) {
121
+ const inWorkspace = new Set(memberNames);
122
+ const entries = [];
123
+ for (const member of DetectCandidates(parentDir).filter((candidate) => inWorkspace.has(candidate.Name))) {
124
+ for (const pkg of member.Packages) {
125
+ const name = pkg.PackageJson.name;
126
+ if (name === undefined || name.length === 0 || pkg.PackageJson.scripts?.build === undefined)
127
+ continue;
128
+ const packageDir = path.join(member.Path, pkg.RelPath);
129
+ if (!existsSync(path.join(packageDir, SOURCE_DIR)))
130
+ continue;
131
+ const entryFile = ResolveEntryFile(pkg.PackageJson);
132
+ const outputDir = entryFile === null ? DEFAULT_OUTPUT_DIR : OutputDirOf(entryFile);
133
+ if (outputDir === null)
134
+ continue;
135
+ entries.push({
136
+ Package: name,
137
+ Repo: member.Name,
138
+ RelPath: pkg.RelPath,
139
+ OutputDir: outputDir,
140
+ State: readBuildState(packageDir, outputDir, entryFile),
141
+ });
142
+ }
143
+ }
144
+ return entries.sort((a, b) => (a.Package < b.Package ? -1 : a.Package > b.Package ? 1 : 0));
145
+ }
146
+ //# sourceMappingURL=build-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-output.js","sourceRoot":"","sources":["../../../src/lib/dev-workspace/build-output.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { CandidateRepo, DevDepConflict, DuplicateClientPackage, DuplicateFamilyPackage, DuplicateProviderLink, MemberPackageJson, OpenAppClientPackage, PackageExtension, RootPackageJsonResult, ShellPeerGap, TurboJsonResult, WorkspaceShell } from './types.js';
1
+ import type { CandidateRepo, DevDepConflict, DuplicateClientPackage, DuplicateFamilyPackage, DuplicateProviderLink, MemberPackageJson, OpenAppClientPackage, PackageExtension, RootPackageJsonResult, ShellPeerGap, WorkspaceShell } from './types.js';
2
2
  /** Build-scripts allowlist proven on the core-monorepo spike. */
3
3
  export declare const ONLY_BUILT_DEPENDENCIES: readonly string[];
4
4
  /**
@@ -65,6 +65,11 @@ export declare const PEER_DEPENDENCY_RULES: {
65
65
  export declare const FALLBACK_PNPM_PIN = "pnpm@10.33.0";
66
66
  /** The proven root-manifest devDependency baseline; fills gaps the union leaves. */
67
67
  export declare const BASELINE_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
68
+ /**
69
+ * The parent `build` script: pnpm's own recursion in dependency order, one package at a time, so
70
+ * no turbo.json has to act as root over the members' own (#4913).
71
+ */
72
+ export declare const PARENT_BUILD_SCRIPT = "pnpm -r --workspace-concurrency=1 run build";
68
73
  /**
69
74
  * The #3795 guard, made explicit for admitted app shells: every package an `--apps` glob
70
75
  * enumerates must have a name no other workspace package uses, or pnpm would silently pick one.
@@ -309,9 +314,4 @@ export declare const SENTINEL_MARKER = "mj dev workspace";
309
314
  * workspace must produce a byte-identical sentinel.
310
315
  */
311
316
  export declare function BuildSentinel(fileNames: readonly string[], memberNames: readonly string[]): string;
312
- /**
313
- * Picks the parent `turbo.json`: copied verbatim from the first member (sorted by
314
- * name) that carries one; a minimal proven config otherwise.
315
- */
316
- export declare function PickTurboJson(members: readonly CandidateRepo[]): TurboJsonResult;
317
317
  //# sourceMappingURL=build.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/lib/dev-workspace/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/lib/dev-workspace/build.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Pure content builders for the four generated workspace files.
2
+ * Pure content builders for the three generated workspace files.
3
3
  *
4
4
  * NO SIDE EFFECTS in this module: every function maps member metadata (already
5
5
  * loaded by `detect.ts`) to file content strings. Writing is `write.ts`'s job.
@@ -22,10 +22,12 @@
22
22
  * A package name two members both provide (every MJ-based app repo has a
23
23
  * `mj_generatedentities`) gets consumer-scoped `link:` overrides so each
24
24
  * member's own consumers keep its own copy — see {@link ResolveDuplicateProviderLinks}.
25
- * - package.json: private root manifest, pnpm `packageManager` pin, and the
26
- * devDependency union of member roots (highest version wins, every conflict
27
- * reported). No `pnpm` block — see pnpm-workspace.yaml above.
28
- * - turbo.json: copied verbatim from a member, with a minimal fallback.
25
+ * - package.json: private root manifest, pnpm `packageManager` pin, a `build`
26
+ * script ({@link PARENT_BUILD_SCRIPT}), and the devDependency union of member
27
+ * roots (highest version wins, every conflict reported). No `pnpm` block — see
28
+ * pnpm-workspace.yaml above.
29
+ * - No turbo.json (#4913): a member's copy at the parent makes turbo treat the
30
+ * parent as root, and MJ's own turbo.json then fails on its root-only keys.
29
31
  *
30
32
  * Why no hoist block: the 78-entry `public-hoist-pattern[]` set the manual setup
31
33
  * carried was written for the npm-hoisted era, when a library could import a
@@ -145,11 +147,11 @@ export const BASELINE_DEV_DEPENDENCIES = {
145
147
  turbo: '^2.5.0',
146
148
  'tsc-alias': '^1.8.16',
147
149
  };
148
- /** Minimal parent turbo.json used only when no member carries one. */
149
- const FALLBACK_TURBO_JSON = `${JSON.stringify({
150
- $schema: 'https://turbo.build/schema.json',
151
- tasks: { build: { dependsOn: ['^build'], outputs: ['dist/**', 'build/**'] } },
152
- }, null, 2)}\n`;
150
+ /**
151
+ * The parent `build` script: pnpm's own recursion in dependency order, one package at a time, so
152
+ * no turbo.json has to act as root over the members' own (#4913).
153
+ */
154
+ export const PARENT_BUILD_SCRIPT = 'pnpm -r --workspace-concurrency=1 run build';
153
155
  const GENERATED_HEADER = 'Generated by `mj dev workspace` — never commit to any repo; teardown = delete.';
154
156
  /** Quotes a YAML list entry the proven way: scoped names quoted, bare names not. */
155
157
  function yamlListEntry(name) {
@@ -552,6 +554,13 @@ export function IndexWorkspacePackages(members) {
552
554
  * contract `readJsonFile` already sets ("Unparseable JSON at <path>"). Without it a missing `name`
553
555
  * surfaced as `Cannot read properties of undefined (reading 'length')`, which names neither the
554
556
  * repo nor the file — and a developer may have a dozen of them.
557
+ *
558
+ * Also validates `platform`, when present, against the same three literals `runsInBrowser` below
559
+ * understands. `MjAppPackageEntry.platform` is a closed three-literal union, so the final
560
+ * `declared as MjAppPackageEntry[]` cast is a LIE unless this loop enforces it — an unvalidated
561
+ * typo like `"platform": "Node"` would satisfy the cast, fail every `=== 'node'`/`'browser'`/`'both'`
562
+ * comparison in `runsInBrowser`, and silently fall through its Node-only branch, dropping the
563
+ * package from the shell import set with no error (#4428).
555
564
  */
556
565
  function readDeclaredEntries(member, section) {
557
566
  const declared = member.MjAppJson?.packages?.[section];
@@ -568,33 +577,58 @@ function readDeclaredEntries(member, section) {
568
577
  if (typeof entry.name !== 'string') {
569
578
  throw new Error(`${where}[${index}] has no "name" string — a package entry must name its package`);
570
579
  }
580
+ const platform = entry.platform;
581
+ if (platform !== undefined && !VALID_PLATFORMS.includes(platform)) {
582
+ throw new Error(`${where}[${index}] has an invalid "platform" value ${JSON.stringify(platform)} — must be one of ${VALID_PLATFORMS.join(', ')}`);
583
+ }
571
584
  }
572
585
  return declared;
573
586
  }
587
+ /** The only valid values for a manifest package entry's `platform` field — see {@link runsInBrowser}. */
588
+ const VALID_PLATFORMS = ['node', 'browser', 'both'];
574
589
  /**
575
590
  * Every package a member declares that an app shell will be asked to import.
576
591
  *
577
592
  * This set mirrors the HOST's rule exactly, because the host is the only thing that decides what
578
593
  * the shell imports. `GetClientPackagesFromManifest`
579
594
  * (`packages/OpenApp/Engine/src/install/config-manager.ts`) builds the client dynamic-package list
580
- * as `[...packages.client, ...packages.shared]` with **no role test** — its own comment: "every
581
- * client/shared package is emitted regardless of startupExport — client entries are side-effect
582
- * imports" — and `mj codegen manifest --open-app-client-bootstrap` turns every enabled entry into
583
- * an import in the shell's generated class-registrations manifest, with no role field even present
584
- * on its entry type.
595
+ * as `[...packages.client, ...packages.shared]` minus anything whose platform excludes the
596
+ * browser, and `mj codegen manifest --open-app-client-bootstrap` turns every enabled entry into an
597
+ * import in the shell's generated class-registrations manifest.
585
598
  *
586
- * So there is deliberately no `role` filter here. An earlier revision kept only `role: 'bootstrap'`
587
- * on the premise that other roles "are imported normally"; the host contradicts that, and `role`
588
- * is a required seven-value enum whose `components` / `module` members are the documented Angular
589
- * roles. Anything narrower leaves a schema-valid package imported by the shell and linked by
590
- * nobody — the exact page-load-with-a-green-build failure this module exists to prevent (#4364).
599
+ * There is deliberately no `role` FILTER here beyond the platform rule. An earlier revision kept
600
+ * only `role: 'bootstrap'` on the premise that other roles "are imported normally"; the host
601
+ * contradicts that, and `role` is a required seven-value enum whose `components` / `module`
602
+ * members are the documented Angular roles. Anything narrower leaves a schema-valid package
603
+ * imported by the shell and linked by nobody — the page-load-with-a-green-build failure this
604
+ * module exists to prevent (#4364).
605
+ *
606
+ * The platform rule itself IS a role test, but a targeted one: it drops only what cannot run in a
607
+ * browser at all. Before it existed, a Node-only actions package declared `shared` was imported
608
+ * into the Angular bundle and the host could not build (#4428).
591
609
  *
592
610
  * `packages.server[]` is NOT here, and that is not an oversight: the host routes it to
593
611
  * `dynamicPackages.server`, a Node process that resolves importer-relative rather than from the
594
612
  * vite root, so it is not part of the shell's resolution problem.
595
613
  */
596
614
  function readShellImportedEntries(member) {
597
- return [...readDeclaredEntries(member, 'client'), ...readDeclaredEntries(member, 'shared')];
615
+ return [...readDeclaredEntries(member, 'client'), ...readDeclaredEntries(member, 'shared')].filter(runsInBrowser);
616
+ }
617
+ /**
618
+ * Whether a declared package may be imported by the app shell.
619
+ *
620
+ * DELIBERATE COPY of `ResolvePackagePlatform` / `PackageRunsOnTier` in
621
+ * `packages/OpenApp/Engine/src/manifest/package-platform.ts`, which is canonical;
622
+ * `packages/DynamicPackages/src/discover.ts` keeps a third copy. Importing the engine's version
623
+ * here would bind this command to that package's built `dist/`. Change one, change all three. The
624
+ * engine's `package-platform.test.ts` holds the canonical case list; this module's spec mirrors its
625
+ * cases by hand, because it cannot import the engine.
626
+ */
627
+ function runsInBrowser(pkg) {
628
+ // `readDeclaredEntries` has already rejected every `platform` other than absent or one of the
629
+ // three literals, so only `undefined` needs the role default here.
630
+ const platform = pkg.platform ?? (pkg.role === 'actions' ? 'node' : 'both');
631
+ return platform === 'both' || platform === 'browser';
598
632
  }
599
633
  export function CollectOpenAppClientPackages(members, workspacePackages) {
600
634
  const collected = new Map();
@@ -962,7 +996,9 @@ export function BuildRootPackageJson(parentDirName, members) {
962
996
  // which is the whole point of registering it.
963
997
  for (const name of Object.keys(clientDependencies))
964
998
  delete union.DevDependencies[name];
965
- const pins = DeriveLockfilePins(members.flatMap((m) => (m.Lockfile !== null && m.Lockfile.Kind !== 'unsupported' ? [{ Repo: m.Name, Lockfile: m.Lockfile }] : [])), new Set(family.Names));
999
+ const pins = DeriveLockfilePins(members.flatMap((m) => m.Lockfile !== null && m.Lockfile.Kind !== 'unsupported'
1000
+ ? [{ Repo: m.Name, Lockfile: m.Lockfile, IncludedImporters: new Set(['.', ...m.Packages.map((p) => p.RelPath)]) }]
1001
+ : []), new Set(family.Names));
966
1002
  const blocks = ResolveMemberPnpmBlocks(members);
967
1003
  const assembled = AssembleParentOverrides(pins.Pins, blocks.Overrides, family.Names, Object.keys(blocks.PatchedDependencies));
968
1004
  const duplicateLinks = ResolveDuplicateProviderLinks(members, family.Duplicates);
@@ -972,6 +1008,7 @@ export function BuildRootPackageJson(parentDirName, members) {
972
1008
  name: workspaceName(parentDirName),
973
1009
  private: true,
974
1010
  packageManager: Pin,
1011
+ scripts: { build: PARENT_BUILD_SCRIPT },
975
1012
  // Omitted entirely when empty, so a parent with no Open App member regenerates byte-identically.
976
1013
  ...(Object.keys(clientDependencies).length > 0 ? { dependencies: clientDependencies } : {}),
977
1014
  devDependencies: union.DevDependencies,
@@ -1038,16 +1075,4 @@ export function BuildSentinel(fileNames, memberNames) {
1038
1075
  };
1039
1076
  return `${JSON.stringify(sentinel, null, 2)}\n`;
1040
1077
  }
1041
- /**
1042
- * Picks the parent `turbo.json`: copied verbatim from the first member (sorted by
1043
- * name) that carries one; a minimal proven config otherwise.
1044
- */
1045
- export function PickTurboJson(members) {
1046
- for (const member of [...members].sort((a, b) => a.Name.localeCompare(b.Name))) {
1047
- if (member.TurboJson !== null) {
1048
- return { Content: member.TurboJson, Source: member.Name };
1049
- }
1050
- }
1051
- return { Content: FALLBACK_TURBO_JSON, Source: 'generator fallback' };
1052
- }
1053
1078
  //# sourceMappingURL=build.js.map