@agimon-ai/po 0.0.0-alpha.0 → 0.0.0-alpha.2

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.
@@ -2,7 +2,7 @@
2
2
  "version": 1,
3
3
  "packages": {
4
4
  "@agimon-ai/po": {
5
- "version": "0.0.0-alpha.0",
5
+ "version": "0.0.0-alpha.2",
6
6
  "dependencies": [
7
7
  "@agimon-ai/po-autostop",
8
8
  "@agimon-ai/po-cache",
@@ -22,7 +22,7 @@
22
22
  ]
23
23
  },
24
24
  "@agimon-ai/po-author": {
25
- "version": "0.0.0-alpha.0",
25
+ "version": "0.0.0-alpha.2",
26
26
  "dependencies": [
27
27
  "@agimon-ai/po-core",
28
28
  "@agimon-ai/po-minor-mode",
@@ -31,7 +31,7 @@
31
31
  ]
32
32
  },
33
33
  "@agimon-ai/po-autocompact": {
34
- "version": "0.0.0-alpha.0",
34
+ "version": "0.0.0-alpha.2",
35
35
  "dependencies": [
36
36
  "@agimon-ai/po-config",
37
37
  "@agimon-ai/po-core",
@@ -39,18 +39,25 @@
39
39
  ]
40
40
  },
41
41
  "@agimon-ai/po-autostop": {
42
- "version": "0.0.0-alpha.0",
42
+ "version": "0.0.0-alpha.2",
43
43
  "dependencies": [
44
44
  "@agimon-ai/po-core",
45
45
  "@agimon-ai/po-telemetry"
46
46
  ]
47
47
  },
48
+ "@agimon-ai/po-browse": {
49
+ "version": "0.0.1-alpha.0",
50
+ "dependencies": [
51
+ "@agimon-ai/po-core",
52
+ "@agimon-ai/po-web-components"
53
+ ]
54
+ },
48
55
  "@agimon-ai/po-build": {
49
- "version": "0.0.0-alpha.0",
56
+ "version": "0.0.0-alpha.2",
50
57
  "dependencies": []
51
58
  },
52
59
  "@agimon-ai/po-cache": {
53
- "version": "0.0.0-alpha.0",
60
+ "version": "0.0.0-alpha.2",
54
61
  "dependencies": [
55
62
  "@agimon-ai/po-config",
56
63
  "@agimon-ai/po-core",
@@ -58,7 +65,7 @@
58
65
  ]
59
66
  },
60
67
  "@agimon-ai/po-computer-use": {
61
- "version": "0.0.0-alpha.0",
68
+ "version": "0.0.0-alpha.2",
62
69
  "dependencies": [
63
70
  "@agimon-ai/po-config",
64
71
  "@agimon-ai/po-core",
@@ -68,7 +75,7 @@
68
75
  ]
69
76
  },
70
77
  "@agimon-ai/po-config": {
71
- "version": "0.0.0-alpha.0",
78
+ "version": "0.0.0-alpha.2",
72
79
  "dependencies": [
73
80
  "@agimon-ai/po-core",
74
81
  "@agimon-ai/po-telemetry",
@@ -76,14 +83,14 @@
76
83
  ]
77
84
  },
78
85
  "@agimon-ai/po-core": {
79
- "version": "0.0.0-alpha.0",
86
+ "version": "0.0.0-alpha.2",
80
87
  "dependencies": [
81
88
  "@agimon-ai/po-telemetry",
82
89
  "@agimon-ai/po-web-security"
83
90
  ]
84
91
  },
85
92
  "@agimon-ai/po-domain": {
86
- "version": "0.0.0-alpha.0",
93
+ "version": "0.0.0-alpha.2",
87
94
  "dependencies": [
88
95
  "@agimon-ai/po-config",
89
96
  "@agimon-ai/po-core",
@@ -92,7 +99,7 @@
92
99
  ]
93
100
  },
94
101
  "@agimon-ai/po-edit": {
95
- "version": "0.0.0-alpha.0",
102
+ "version": "0.0.0-alpha.2",
96
103
  "dependencies": [
97
104
  "@agimon-ai/po-core",
98
105
  "@agimon-ai/po-hashline",
@@ -101,7 +108,7 @@
101
108
  ]
102
109
  },
103
110
  "@agimon-ai/po-file-edit": {
104
- "version": "0.0.0-alpha.0",
111
+ "version": "0.0.0-alpha.2",
105
112
  "dependencies": [
106
113
  "@agimon-ai/po-config",
107
114
  "@agimon-ai/po-core",
@@ -111,7 +118,7 @@
111
118
  ]
112
119
  },
113
120
  "@agimon-ai/po-git": {
114
- "version": "0.0.0-alpha.0",
121
+ "version": "0.0.0-alpha.2",
115
122
  "dependencies": [
116
123
  "@agimon-ai/po-core",
117
124
  "@agimon-ai/po-session",
@@ -120,7 +127,7 @@
120
127
  ]
121
128
  },
122
129
  "@agimon-ai/po-goal": {
123
- "version": "0.0.0-alpha.0",
130
+ "version": "0.0.0-alpha.2",
124
131
  "dependencies": [
125
132
  "@agimon-ai/po-core",
126
133
  "@agimon-ai/po-minor-mode",
@@ -129,7 +136,7 @@
129
136
  ]
130
137
  },
131
138
  "@agimon-ai/po-grep": {
132
- "version": "0.0.0-alpha.0",
139
+ "version": "0.0.0-alpha.2",
133
140
  "dependencies": [
134
141
  "@agimon-ai/po-core",
135
142
  "@agimon-ai/po-hashline",
@@ -138,11 +145,11 @@
138
145
  ]
139
146
  },
140
147
  "@agimon-ai/po-hashline": {
141
- "version": "0.0.0-alpha.0",
148
+ "version": "0.0.0-alpha.2",
142
149
  "dependencies": []
143
150
  },
144
151
  "@agimon-ai/po-help": {
145
- "version": "0.0.0-alpha.0",
152
+ "version": "0.0.0-alpha.2",
146
153
  "dependencies": [
147
154
  "@agimon-ai/po-core",
148
155
  "@agimon-ai/po-minor-mode",
@@ -150,15 +157,22 @@
150
157
  ]
151
158
  },
152
159
  "@agimon-ai/po-hook": {
153
- "version": "0.0.0-alpha.0",
160
+ "version": "0.0.0-alpha.2",
154
161
  "dependencies": [
155
162
  "@agimon-ai/po-config",
156
163
  "@agimon-ai/po-core",
157
164
  "@agimon-ai/po-telemetry"
158
165
  ]
159
166
  },
167
+ "@agimon-ai/po-image-gen": {
168
+ "version": "0.0.0",
169
+ "dependencies": [
170
+ "@agimon-ai/po-core",
171
+ "@agimon-ai/po-web-components"
172
+ ]
173
+ },
160
174
  "@agimon-ai/po-log": {
161
- "version": "0.0.0-alpha.0",
175
+ "version": "0.0.0-alpha.2",
162
176
  "dependencies": [
163
177
  "@agimon-ai/po-core",
164
178
  "@agimon-ai/po-telemetry",
@@ -167,7 +181,7 @@
167
181
  ]
168
182
  },
169
183
  "@agimon-ai/po-loop": {
170
- "version": "0.0.0-alpha.0",
184
+ "version": "0.0.0-alpha.2",
171
185
  "dependencies": [
172
186
  "@agimon-ai/po-core",
173
187
  "@agimon-ai/po-minor-mode",
@@ -176,7 +190,7 @@
176
190
  ]
177
191
  },
178
192
  "@agimon-ai/po-major-mode": {
179
- "version": "0.0.0-alpha.0",
193
+ "version": "0.0.0-alpha.2",
180
194
  "dependencies": [
181
195
  "@agimon-ai/po-config",
182
196
  "@agimon-ai/po-core",
@@ -185,7 +199,7 @@
185
199
  ]
186
200
  },
187
201
  "@agimon-ai/po-mcp": {
188
- "version": "0.0.0-alpha.0",
202
+ "version": "0.0.0-alpha.2",
189
203
  "dependencies": [
190
204
  "@agimon-ai/po-config",
191
205
  "@agimon-ai/po-core",
@@ -194,33 +208,33 @@
194
208
  ]
195
209
  },
196
210
  "@agimon-ai/po-minor-mode": {
197
- "version": "0.0.0-alpha.0",
211
+ "version": "0.0.0-alpha.2",
198
212
  "dependencies": [
199
213
  "@agimon-ai/po-core",
200
214
  "@agimon-ai/po-telemetry"
201
215
  ]
202
216
  },
203
217
  "@agimon-ai/po-model-guidance": {
204
- "version": "0.0.0-alpha.0",
218
+ "version": "0.0.0-alpha.2",
205
219
  "dependencies": [
206
220
  "@agimon-ai/po-config",
207
221
  "@agimon-ai/po-core"
208
222
  ]
209
223
  },
210
224
  "@agimon-ai/po-native-components": {
211
- "version": "0.0.0-alpha.0",
225
+ "version": "0.0.0-alpha.2",
212
226
  "dependencies": [
213
227
  "@agimon-ai/po-web-components"
214
228
  ]
215
229
  },
216
230
  "@agimon-ai/po-notification": {
217
- "version": "0.0.0-alpha.0",
231
+ "version": "0.0.0-alpha.2",
218
232
  "dependencies": [
219
233
  "@agimon-ai/po-core"
220
234
  ]
221
235
  },
222
236
  "@agimon-ai/po-plan": {
223
- "version": "0.0.0-alpha.0",
237
+ "version": "0.0.0-alpha.2",
224
238
  "dependencies": [
225
239
  "@agimon-ai/po-config",
226
240
  "@agimon-ai/po-core",
@@ -231,7 +245,7 @@
231
245
  ]
232
246
  },
233
247
  "@agimon-ai/po-profile": {
234
- "version": "0.0.0-alpha.0",
248
+ "version": "0.0.0-alpha.2",
235
249
  "dependencies": [
236
250
  "@agimon-ai/po-config",
237
251
  "@agimon-ai/po-core",
@@ -240,7 +254,7 @@
240
254
  ]
241
255
  },
242
256
  "@agimon-ai/po-prompt": {
243
- "version": "0.0.0-alpha.0",
257
+ "version": "0.0.0-alpha.2",
244
258
  "dependencies": [
245
259
  "@agimon-ai/po-core",
246
260
  "@agimon-ai/po-web-components",
@@ -248,7 +262,7 @@
248
262
  ]
249
263
  },
250
264
  "@agimon-ai/po-read": {
251
- "version": "0.0.0-alpha.0",
265
+ "version": "0.0.0-alpha.2",
252
266
  "dependencies": [
253
267
  "@agimon-ai/po-config",
254
268
  "@agimon-ai/po-core",
@@ -258,7 +272,7 @@
258
272
  ]
259
273
  },
260
274
  "@agimon-ai/po-runner": {
261
- "version": "0.0.0-alpha.0",
275
+ "version": "0.0.0-alpha.2",
262
276
  "dependencies": [
263
277
  "@agimon-ai/po-core",
264
278
  "@agimon-ai/po-telemetry",
@@ -268,19 +282,19 @@
268
282
  ]
269
283
  },
270
284
  "@agimon-ai/po-sandbox": {
271
- "version": "0.0.0-alpha.0",
285
+ "version": "0.0.0-alpha.2",
272
286
  "dependencies": [
273
287
  "@agimon-ai/po-core"
274
288
  ]
275
289
  },
276
290
  "@agimon-ai/po-session": {
277
- "version": "0.0.0-alpha.0",
291
+ "version": "0.0.0-alpha.2",
278
292
  "dependencies": [
279
293
  "@agimon-ai/po-core"
280
294
  ]
281
295
  },
282
296
  "@agimon-ai/po-skill": {
283
- "version": "0.0.0-alpha.0",
297
+ "version": "0.0.0-alpha.2",
284
298
  "dependencies": [
285
299
  "@agimon-ai/po-config",
286
300
  "@agimon-ai/po-core",
@@ -290,7 +304,7 @@
290
304
  ]
291
305
  },
292
306
  "@agimon-ai/po-style-system": {
293
- "version": "0.0.0-alpha.0",
307
+ "version": "0.0.0-alpha.2",
294
308
  "dependencies": [
295
309
  "@agimon-ai/po-core",
296
310
  "@agimon-ai/po-web-components",
@@ -298,7 +312,7 @@
298
312
  ]
299
313
  },
300
314
  "@agimon-ai/po-task": {
301
- "version": "0.0.0-alpha.0",
315
+ "version": "0.0.0-alpha.2",
302
316
  "dependencies": [
303
317
  "@agimon-ai/po-core",
304
318
  "@agimon-ai/po-telemetry",
@@ -307,7 +321,7 @@
307
321
  ]
308
322
  },
309
323
  "@agimon-ai/po-team": {
310
- "version": "0.0.0-alpha.0",
324
+ "version": "0.0.0-alpha.2",
311
325
  "dependencies": [
312
326
  "@agimon-ai/po-cache",
313
327
  "@agimon-ai/po-config",
@@ -320,11 +334,11 @@
320
334
  ]
321
335
  },
322
336
  "@agimon-ai/po-telemetry": {
323
- "version": "0.0.0-alpha.0",
337
+ "version": "0.0.0-alpha.2",
324
338
  "dependencies": []
325
339
  },
326
340
  "@agimon-ai/po-template-advanced": {
327
- "version": "0.0.0-alpha.0",
341
+ "version": "0.0.0-alpha.2",
328
342
  "dependencies": [
329
343
  "@agimon-ai/po-core",
330
344
  "@agimon-ai/po-web-components",
@@ -332,7 +346,7 @@
332
346
  ]
333
347
  },
334
348
  "@agimon-ai/po-template-elegant": {
335
- "version": "0.0.0-alpha.0",
349
+ "version": "0.0.0-alpha.2",
336
350
  "dependencies": [
337
351
  "@agimon-ai/po-core",
338
352
  "@agimon-ai/po-web-components",
@@ -340,7 +354,7 @@
340
354
  ]
341
355
  },
342
356
  "@agimon-ai/po-ui": {
343
- "version": "0.0.0-alpha.0",
357
+ "version": "0.0.0-alpha.2",
344
358
  "dependencies": [
345
359
  "@agimon-ai/po-core",
346
360
  "@agimon-ai/po-hashline",
@@ -350,7 +364,7 @@
350
364
  ]
351
365
  },
352
366
  "@agimon-ai/po-user-feedback": {
353
- "version": "0.0.0-alpha.0",
367
+ "version": "0.0.0-alpha.2",
354
368
  "dependencies": [
355
369
  "@agimon-ai/po-core",
356
370
  "@agimon-ai/po-minor-mode",
@@ -358,7 +372,7 @@
358
372
  ]
359
373
  },
360
374
  "@agimon-ai/po-voice": {
361
- "version": "0.0.0-alpha.0",
375
+ "version": "0.0.0-alpha.2",
362
376
  "dependencies": [
363
377
  "@agimon-ai/po-config",
364
378
  "@agimon-ai/po-core",
@@ -371,23 +385,30 @@
371
385
  ]
372
386
  },
373
387
  "@agimon-ai/po-web-components": {
374
- "version": "0.0.0-alpha.0",
388
+ "version": "0.0.0-alpha.2",
375
389
  "dependencies": []
376
390
  },
377
391
  "@agimon-ai/po-web-dashboard": {
378
- "version": "0.0.0-alpha.0",
392
+ "version": "0.0.0-alpha.2",
379
393
  "dependencies": [
380
394
  "@agimon-ai/po-core",
381
395
  "@agimon-ai/po-web-components",
382
396
  "@agimon-ai/po-web-security"
383
397
  ]
384
398
  },
399
+ "@agimon-ai/po-web-search": {
400
+ "version": "0.0.0",
401
+ "dependencies": [
402
+ "@agimon-ai/po-core",
403
+ "@agimon-ai/po-web-components"
404
+ ]
405
+ },
385
406
  "@agimon-ai/po-web-security": {
386
- "version": "0.0.0-alpha.0",
407
+ "version": "0.0.0-alpha.2",
387
408
  "dependencies": []
388
409
  },
389
410
  "@agimon-ai/po-workflow": {
390
- "version": "0.0.0-alpha.0",
411
+ "version": "0.0.0-alpha.2",
391
412
  "dependencies": [
392
413
  "@agimon-ai/po-core",
393
414
  "@agimon-ai/po-minor-mode",
@@ -401,6 +422,7 @@
401
422
  "install": [
402
423
  "@agimon-ai/po-author",
403
424
  "@agimon-ai/po-autocompact",
425
+ "@agimon-ai/po-browse",
404
426
  "@agimon-ai/po-computer-use",
405
427
  "@agimon-ai/po-edit",
406
428
  "@agimon-ai/po-file-edit",
@@ -409,6 +431,7 @@
409
431
  "@agimon-ai/po-grep",
410
432
  "@agimon-ai/po-help",
411
433
  "@agimon-ai/po-hook",
434
+ "@agimon-ai/po-image-gen",
412
435
  "@agimon-ai/po-log",
413
436
  "@agimon-ai/po-loop",
414
437
  "@agimon-ai/po-mcp",
@@ -425,6 +448,7 @@
425
448
  "@agimon-ai/po-template-elegant",
426
449
  "@agimon-ai/po-user-feedback",
427
450
  "@agimon-ai/po-voice",
451
+ "@agimon-ai/po-web-search",
428
452
  "@agimon-ai/po-workflow"
429
453
  ]
430
454
  }
@@ -16,9 +16,9 @@ node_crypto = require_runtime.__toESM(node_crypto, 1);
16
16
  * Plugins are independent: a manifest names no other plugin, and the order
17
17
  * plugins install in is only a tiebreak (registrationOrder, then pluginId),
18
18
  * because every relation between two plugins resolves by name once all of
19
- * them are installed. A collision between two packages is a notice for the
20
- * sync log and the first package keeps the name; only a malformed block is an
21
- * error, which the scanner turns into a notice for that package alone.
19
+ * them are installed. Web copies keep distinct slots so each mount can select its
20
+ * own package; only repeated declarations of the same slot are dropped. Native
21
+ * plugins still share one pluginId registry. Malformed blocks are scan errors.
22
22
  *
23
23
  * The native app's poNative blocks share this exact shape, so the same
24
24
  * validation reads either field.
@@ -97,21 +97,22 @@ function compareCodeUnits(left, right) {
97
97
  }
98
98
  const byInstallOrder = (left, right) => left.registrationOrder - right.registrationOrder || compareCodeUnits(left.pluginId, right.pluginId) || compareCodeUnits(left.packageDir, right.packageDir);
99
99
  /**
100
- * The deterministic install order, (registrationOrder, pluginId), with the
101
- * cross-package collisions resolved by the browser client registry: the first
102
- * plugin keeps a shared pluginId and the later package is dropped with a notice.
100
+ * Deterministic install order with duplicate web slots removed. Different package
101
+ * copies survive the build; mount selection resolves shared pluginIds later.
102
+ * The native registry is still keyed by pluginId, so it keeps only the first copy.
103
103
  */
104
- function orderDeclaredPlugins(plugins, onNotice = () => void 0) {
104
+ function orderDeclaredPlugins(plugins, onNotice = () => void 0, field = "poWeb") {
105
105
  const sorted = [...plugins].sort(byInstallOrder);
106
- const byId = /* @__PURE__ */ new Map();
106
+ const byKey = /* @__PURE__ */ new Map();
107
107
  const kept = [];
108
108
  for (const plugin of sorted) {
109
- const holder = byId.get(plugin.pluginId);
109
+ const key = field === "poNative" ? plugin.pluginId : plugin.slot;
110
+ const holder = byKey.get(key);
110
111
  if (holder !== void 0) {
111
112
  onNotice(`web plugin '${plugin.pluginId}' from ${plugin.packageDir} is skipped: ${holder.packageDir} already declares it.`);
112
113
  continue;
113
114
  }
114
- byId.set(plugin.pluginId, plugin);
115
+ byKey.set(key, plugin);
115
116
  kept.push(plugin);
116
117
  }
117
118
  return kept;
@@ -1 +1 @@
1
- {"version":3,"file":"webPluginManifest.cjs","names":["fs","path","crypto"],"sources":["../../../../src/builders/web/webPluginManifest.ts"],"sourcesContent":["/**\n * The poWeb manifest vocabulary: how a package declares its web plugin in\n * package.json, validated and ordered; the filesystem is read only to name each\n * copy's slot by its real directory. The\n * scan adapter feeds this from real manifests; the sync bundler feeds it from\n * the installed composition's package roots.\n *\n * Plugins are independent: a manifest names no other plugin, and the order\n * plugins install in is only a tiebreak (registrationOrder, then pluginId),\n * because every relation between two plugins resolves by name once all of\n * them are installed. A collision between two packages is a notice for the\n * sync log and the first package keeps the name; only a malformed block is an\n * error, which the scanner turns into a notice for that package alone.\n *\n * The native app's poNative blocks share this exact shape, so the same\n * validation reads either field.\n */\n\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst PLUGIN_ID_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\n/** The order a plugin installs at when its manifest names none. */\nexport const DEFAULT_REGISTRATION_ORDER = 1000;\n\nexport interface WebPluginEntryDeclaration {\n /** Package-relative ./path to the source entry. */\n entry: string;\n}\n\nexport interface DeclaredWebPlugin {\n pluginId: string;\n /**\n * The registry name of this installed copy: the pluginId for a host plugin, otherwise\n * `${pluginId}.${first 8 hex of sha256(realpath(packageDir))}`, so two copies of one\n * pluginId installed from different directories never share a name.\n */\n slot: string;\n registrationOrder: number;\n packageDir: string;\n packageName: string;\n isHost: boolean;\n client: WebPluginEntryDeclaration;\n scopes: readonly ('global' | 'workspace' | 'session')[];\n}\n\n/** The package.json field a plugin block lives in: the browser cockpit's or the native app's. */\nexport type PluginManifestField = 'poWeb' | 'poNative';\n\nexport class WebPluginManifestError extends Error {\n constructor(packageDir: string, message: string, field: PluginManifestField = 'poWeb') {\n super(`${field} manifest in ${packageDir}: ${message}`);\n this.name = 'WebPluginManifestError';\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction normalizeEntry(\n packageDir: string,\n kind: string,\n value: unknown,\n field: PluginManifestField,\n): WebPluginEntryDeclaration {\n const raw = typeof value === 'string' ? { entry: value } : value;\n if (!isRecord(raw)) throw new WebPluginManifestError(packageDir, `${kind} must be a path or {entry}.`, field);\n const { entry } = raw;\n if (typeof entry !== 'string' || !entry.startsWith('./') || entry.includes('..')) {\n throw new WebPluginManifestError(\n packageDir,\n `${kind}.entry must be a package-relative ./path with no '..'.`,\n field,\n );\n }\n return { entry };\n}\n\nconst SLOT_HASH_LENGTH = 8;\n\n/** The slot of one installed plugin copy; see DeclaredWebPlugin.slot. */\nexport function pluginSlot(plugin: { pluginId: string; packageDir: string; isHost: boolean }): string {\n if (plugin.isHost) return plugin.pluginId;\n let directory: string;\n try {\n directory = fs.realpathSync(plugin.packageDir);\n } catch {\n // A directory that no longer exists has no real path; its resolved path still names it stably.\n directory = path.resolve(plugin.packageDir);\n }\n const digest = crypto.createHash('sha256').update(directory).digest('hex');\n return `${plugin.pluginId}.${digest.slice(0, SLOT_HASH_LENGTH)}`;\n}\n\n/** The field's value normalized to a list: one plugin object or an array of them. */\nexport function pluginBlocksOf(manifest: Record<string, unknown>, field: PluginManifestField = 'poWeb'): unknown[] {\n const value = manifest[field];\n if (value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\n/** Validates one manifest's blocks into declared plugins; throws WebPluginManifestError on bad shape. */\nexport function declaredPluginsOf(\n packageDir: string,\n manifest: Record<string, unknown>,\n isHost: boolean,\n field: PluginManifestField = 'poWeb',\n): DeclaredWebPlugin[] {\n const plugins: DeclaredWebPlugin[] = [];\n for (const block of pluginBlocksOf(manifest, field)) {\n if (!isRecord(block)) throw new WebPluginManifestError(packageDir, 'each block must be an object.', field);\n const { pluginId, registrationOrder = DEFAULT_REGISTRATION_ORDER, client, scopes } = block;\n if (\n !Array.isArray(scopes) ||\n scopes.length === 0 ||\n scopes.some((scope) => !['global', 'workspace', 'session'].includes(scope))\n ) {\n throw new WebPluginManifestError(\n packageDir,\n 'scopes must explicitly name global, workspace, or session; resync the plugin.',\n field,\n );\n }\n if (typeof pluginId !== 'string' || !PLUGIN_ID_PATTERN.test(pluginId)) {\n throw new WebPluginManifestError(packageDir, `pluginId '${String(pluginId)}' must be kebab-case.`, field);\n }\n if (!Number.isInteger(registrationOrder) || (registrationOrder as number) < 0) {\n throw new WebPluginManifestError(\n packageDir,\n `'${pluginId}' needs a non-negative integer registrationOrder.`,\n field,\n );\n }\n plugins.push({\n pluginId,\n slot: pluginSlot({ pluginId, packageDir, isHost }),\n registrationOrder: registrationOrder as number,\n packageDir,\n packageName: typeof manifest.name === 'string' ? manifest.name : packageDir,\n isHost,\n client: normalizeEntry(packageDir, 'client', client, field),\n scopes,\n });\n }\n return plugins;\n}\n\n/** Code-unit order, never the locale's: the same packages must order the same on every machine. */\nexport function compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nconst byInstallOrder = (left: DeclaredWebPlugin, right: DeclaredWebPlugin): number =>\n left.registrationOrder - right.registrationOrder ||\n compareCodeUnits(left.pluginId, right.pluginId) ||\n compareCodeUnits(left.packageDir, right.packageDir);\n\n/**\n * The deterministic install order, (registrationOrder, pluginId), with the\n * cross-package collisions resolved by the browser client registry: the first\n * plugin keeps a shared pluginId and the later package is dropped with a notice.\n */\nexport function orderDeclaredPlugins(\n plugins: readonly DeclaredWebPlugin[],\n onNotice: (message: string) => void = () => undefined,\n): DeclaredWebPlugin[] {\n const sorted = [...plugins].sort(byInstallOrder);\n const byId = new Map<string, DeclaredWebPlugin>();\n const kept: DeclaredWebPlugin[] = [];\n for (const plugin of sorted) {\n const holder = byId.get(plugin.pluginId);\n if (holder !== undefined) {\n onNotice(\n `web plugin '${plugin.pluginId}' from ${plugin.packageDir} is skipped: ${holder.packageDir} already declares it.`,\n );\n continue;\n }\n byId.set(plugin.pluginId, plugin);\n kept.push(plugin);\n }\n return kept;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAM,oBAAoB;;AAG1B,MAAa,6BAA6B;AA0B1C,IAAa,yBAAb,cAA4C,MAAM;CAChD,YAAY,YAAoB,SAAiB,QAA6B,SAAS;EACrF,MAAM,GAAG,MAAM,eAAe,WAAW,IAAI,SAAS;EACtD,KAAK,OAAO;CACd;AACF;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,eACP,YACA,MACA,OACA,OAC2B;CAC3B,MAAM,MAAM,OAAO,UAAU,WAAW,EAAE,OAAO,MAAM,IAAI;CAC3D,IAAI,CAAC,SAAS,GAAG,GAAG,MAAM,IAAI,uBAAuB,YAAY,GAAG,KAAK,8BAA8B,KAAK;CAC5G,MAAM,EAAE,UAAU;CAClB,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,WAAW,IAAI,KAAK,MAAM,SAAS,IAAI,GAC7E,MAAM,IAAI,uBACR,YACA,GAAG,KAAK,yDACR,KACF;CAEF,OAAO,EAAE,MAAM;AACjB;AAEA,MAAM,mBAAmB;;AAGzB,SAAgB,WAAW,QAA2E;CACpG,IAAI,OAAO,QAAQ,OAAO,OAAO;CACjC,IAAI;CACJ,IAAI;EACF,YAAYA,QAAAA,QAAG,aAAa,OAAO,UAAU;CAC/C,QAAQ;EAEN,YAAYC,UAAAA,QAAK,QAAQ,OAAO,UAAU;CAC5C;CACA,MAAM,SAASC,YAAAA,QAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,OAAO,KAAK;CACzE,OAAO,GAAG,OAAO,SAAS,GAAG,OAAO,MAAM,GAAG,gBAAgB;AAC/D;;AAGA,SAAgB,eAAe,UAAmC,QAA6B,SAAoB;CACjH,MAAM,QAAQ,SAAS;CACvB,IAAI,UAAU,KAAA,GAAW,OAAO,CAAC;CACjC,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAC9C;;AAGA,SAAgB,kBACd,YACA,UACA,QACA,QAA6B,SACR;CACrB,MAAM,UAA+B,CAAC;CACtC,KAAK,MAAM,SAAS,eAAe,UAAU,KAAK,GAAG;EACnD,IAAI,CAAC,SAAS,KAAK,GAAG,MAAM,IAAI,uBAAuB,YAAY,iCAAiC,KAAK;EACzG,MAAM,EAAE,UAAU,oBAAoB,4BAA4B,QAAQ,WAAW;EACrF,IACE,CAAC,MAAM,QAAQ,MAAM,KACrB,OAAO,WAAW,KAClB,OAAO,MAAM,UAAU,CAAC;GAAC;GAAU;GAAa;EAAS,CAAC,CAAC,SAAS,KAAK,CAAC,GAE1E,MAAM,IAAI,uBACR,YACA,iFACA,KACF;EAEF,IAAI,OAAO,aAAa,YAAY,CAAC,kBAAkB,KAAK,QAAQ,GAClE,MAAM,IAAI,uBAAuB,YAAY,aAAa,OAAO,QAAQ,EAAE,wBAAwB,KAAK;EAE1G,IAAI,CAAC,OAAO,UAAU,iBAAiB,KAAM,oBAA+B,GAC1E,MAAM,IAAI,uBACR,YACA,IAAI,SAAS,oDACb,KACF;EAEF,QAAQ,KAAK;GACX;GACA,MAAM,WAAW;IAAE;IAAU;IAAY;GAAO,CAAC;GAC9B;GACnB;GACA,aAAa,OAAO,SAAS,SAAS,WAAW,SAAS,OAAO;GACjE;GACA,QAAQ,eAAe,YAAY,UAAU,QAAQ,KAAK;GAC1D;EACF,CAAC;CACH;CACA,OAAO;AACT;;AAGA,SAAgB,iBAAiB,MAAc,OAAuB;CACpE,OAAO,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAChD;AAEA,MAAM,kBAAkB,MAAyB,UAC/C,KAAK,oBAAoB,MAAM,qBAC/B,iBAAiB,KAAK,UAAU,MAAM,QAAQ,KAC9C,iBAAiB,KAAK,YAAY,MAAM,UAAU;;;;;;AAOpD,SAAgB,qBACd,SACA,iBAA4C,KAAA,GACvB;CACrB,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,KAAK,cAAc;CAC/C,MAAM,uBAAO,IAAI,IAA+B;CAChD,MAAM,OAA4B,CAAC;CACnC,KAAK,MAAM,UAAU,QAAQ;EAC3B,MAAM,SAAS,KAAK,IAAI,OAAO,QAAQ;EACvC,IAAI,WAAW,KAAA,GAAW;GACxB,SACE,eAAe,OAAO,SAAS,SAAS,OAAO,WAAW,eAAe,OAAO,WAAW,sBAC7F;GACA;EACF;EACA,KAAK,IAAI,OAAO,UAAU,MAAM;EAChC,KAAK,KAAK,MAAM;CAClB;CACA,OAAO;AACT"}
1
+ {"version":3,"file":"webPluginManifest.cjs","names":["fs","path","crypto"],"sources":["../../../../src/builders/web/webPluginManifest.ts"],"sourcesContent":["/**\n * The poWeb manifest vocabulary: how a package declares its web plugin in\n * package.json, validated and ordered; the filesystem is read only to name each\n * copy's slot by its real directory. The\n * scan adapter feeds this from real manifests; the sync bundler feeds it from\n * the installed composition's package roots.\n *\n * Plugins are independent: a manifest names no other plugin, and the order\n * plugins install in is only a tiebreak (registrationOrder, then pluginId),\n * because every relation between two plugins resolves by name once all of\n * them are installed. Web copies keep distinct slots so each mount can select its\n * own package; only repeated declarations of the same slot are dropped. Native\n * plugins still share one pluginId registry. Malformed blocks are scan errors.\n *\n * The native app's poNative blocks share this exact shape, so the same\n * validation reads either field.\n */\n\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst PLUGIN_ID_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\n/** The order a plugin installs at when its manifest names none. */\nexport const DEFAULT_REGISTRATION_ORDER = 1000;\n\nexport interface WebPluginEntryDeclaration {\n /** Package-relative ./path to the source entry. */\n entry: string;\n}\n\nexport interface DeclaredWebPlugin {\n pluginId: string;\n /**\n * The registry name of this installed copy: the pluginId for a host plugin, otherwise\n * `${pluginId}.${first 8 hex of sha256(realpath(packageDir))}`, so two copies of one\n * pluginId installed from different directories never share a name.\n */\n slot: string;\n registrationOrder: number;\n packageDir: string;\n packageName: string;\n isHost: boolean;\n client: WebPluginEntryDeclaration;\n scopes: readonly ('global' | 'workspace' | 'session')[];\n}\n\n/** The package.json field a plugin block lives in: the browser cockpit's or the native app's. */\nexport type PluginManifestField = 'poWeb' | 'poNative';\n\nexport class WebPluginManifestError extends Error {\n constructor(packageDir: string, message: string, field: PluginManifestField = 'poWeb') {\n super(`${field} manifest in ${packageDir}: ${message}`);\n this.name = 'WebPluginManifestError';\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction normalizeEntry(\n packageDir: string,\n kind: string,\n value: unknown,\n field: PluginManifestField,\n): WebPluginEntryDeclaration {\n const raw = typeof value === 'string' ? { entry: value } : value;\n if (!isRecord(raw)) throw new WebPluginManifestError(packageDir, `${kind} must be a path or {entry}.`, field);\n const { entry } = raw;\n if (typeof entry !== 'string' || !entry.startsWith('./') || entry.includes('..')) {\n throw new WebPluginManifestError(\n packageDir,\n `${kind}.entry must be a package-relative ./path with no '..'.`,\n field,\n );\n }\n return { entry };\n}\n\nconst SLOT_HASH_LENGTH = 8;\n\n/** The slot of one installed plugin copy; see DeclaredWebPlugin.slot. */\nexport function pluginSlot(plugin: { pluginId: string; packageDir: string; isHost: boolean }): string {\n if (plugin.isHost) return plugin.pluginId;\n let directory: string;\n try {\n directory = fs.realpathSync(plugin.packageDir);\n } catch {\n // A directory that no longer exists has no real path; its resolved path still names it stably.\n directory = path.resolve(plugin.packageDir);\n }\n const digest = crypto.createHash('sha256').update(directory).digest('hex');\n return `${plugin.pluginId}.${digest.slice(0, SLOT_HASH_LENGTH)}`;\n}\n\n/** The field's value normalized to a list: one plugin object or an array of them. */\nexport function pluginBlocksOf(manifest: Record<string, unknown>, field: PluginManifestField = 'poWeb'): unknown[] {\n const value = manifest[field];\n if (value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\n/** Validates one manifest's blocks into declared plugins; throws WebPluginManifestError on bad shape. */\nexport function declaredPluginsOf(\n packageDir: string,\n manifest: Record<string, unknown>,\n isHost: boolean,\n field: PluginManifestField = 'poWeb',\n): DeclaredWebPlugin[] {\n const plugins: DeclaredWebPlugin[] = [];\n for (const block of pluginBlocksOf(manifest, field)) {\n if (!isRecord(block)) throw new WebPluginManifestError(packageDir, 'each block must be an object.', field);\n const { pluginId, registrationOrder = DEFAULT_REGISTRATION_ORDER, client, scopes } = block;\n if (\n !Array.isArray(scopes) ||\n scopes.length === 0 ||\n scopes.some((scope) => !['global', 'workspace', 'session'].includes(scope))\n ) {\n throw new WebPluginManifestError(\n packageDir,\n 'scopes must explicitly name global, workspace, or session; resync the plugin.',\n field,\n );\n }\n if (typeof pluginId !== 'string' || !PLUGIN_ID_PATTERN.test(pluginId)) {\n throw new WebPluginManifestError(packageDir, `pluginId '${String(pluginId)}' must be kebab-case.`, field);\n }\n if (!Number.isInteger(registrationOrder) || (registrationOrder as number) < 0) {\n throw new WebPluginManifestError(\n packageDir,\n `'${pluginId}' needs a non-negative integer registrationOrder.`,\n field,\n );\n }\n plugins.push({\n pluginId,\n slot: pluginSlot({ pluginId, packageDir, isHost }),\n registrationOrder: registrationOrder as number,\n packageDir,\n packageName: typeof manifest.name === 'string' ? manifest.name : packageDir,\n isHost,\n client: normalizeEntry(packageDir, 'client', client, field),\n scopes,\n });\n }\n return plugins;\n}\n\n/** Code-unit order, never the locale's: the same packages must order the same on every machine. */\nexport function compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nconst byInstallOrder = (left: DeclaredWebPlugin, right: DeclaredWebPlugin): number =>\n left.registrationOrder - right.registrationOrder ||\n compareCodeUnits(left.pluginId, right.pluginId) ||\n compareCodeUnits(left.packageDir, right.packageDir);\n\n/**\n * Deterministic install order with duplicate web slots removed. Different package\n * copies survive the build; mount selection resolves shared pluginIds later.\n * The native registry is still keyed by pluginId, so it keeps only the first copy.\n */\nexport function orderDeclaredPlugins(\n plugins: readonly DeclaredWebPlugin[],\n onNotice: (message: string) => void = () => undefined,\n field: PluginManifestField = 'poWeb',\n): DeclaredWebPlugin[] {\n const sorted = [...plugins].sort(byInstallOrder);\n const byKey = new Map<string, DeclaredWebPlugin>();\n const kept: DeclaredWebPlugin[] = [];\n for (const plugin of sorted) {\n const key = field === 'poNative' ? plugin.pluginId : plugin.slot;\n const holder = byKey.get(key);\n if (holder !== undefined) {\n onNotice(\n `web plugin '${plugin.pluginId}' from ${plugin.packageDir} is skipped: ${holder.packageDir} already declares it.`,\n );\n continue;\n }\n byKey.set(key, plugin);\n kept.push(plugin);\n }\n return kept;\n}\n"],"mappings":"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"}
@@ -9,9 +9,9 @@
9
9
  * Plugins are independent: a manifest names no other plugin, and the order
10
10
  * plugins install in is only a tiebreak (registrationOrder, then pluginId),
11
11
  * because every relation between two plugins resolves by name once all of
12
- * them are installed. A collision between two packages is a notice for the
13
- * sync log and the first package keeps the name; only a malformed block is an
14
- * error, which the scanner turns into a notice for that package alone.
12
+ * them are installed. Web copies keep distinct slots so each mount can select its
13
+ * own package; only repeated declarations of the same slot are dropped. Native
14
+ * plugins still share one pluginId registry. Malformed blocks are scan errors.
15
15
  *
16
16
  * The native app's poNative blocks share this exact shape, so the same
17
17
  * validation reads either field.
@@ -55,10 +55,10 @@ export declare function declaredPluginsOf(packageDir: string, manifest: Record<s
55
55
  /** Code-unit order, never the locale's: the same packages must order the same on every machine. */
56
56
  export declare function compareCodeUnits(left: string, right: string): number;
57
57
  /**
58
- * The deterministic install order, (registrationOrder, pluginId), with the
59
- * cross-package collisions resolved by the browser client registry: the first
60
- * plugin keeps a shared pluginId and the later package is dropped with a notice.
58
+ * Deterministic install order with duplicate web slots removed. Different package
59
+ * copies survive the build; mount selection resolves shared pluginIds later.
60
+ * The native registry is still keyed by pluginId, so it keeps only the first copy.
61
61
  */
62
- export declare function orderDeclaredPlugins(plugins: readonly DeclaredWebPlugin[], onNotice?: (message: string) => void): DeclaredWebPlugin[];
62
+ export declare function orderDeclaredPlugins(plugins: readonly DeclaredWebPlugin[], onNotice?: (message: string) => void, field?: PluginManifestField): DeclaredWebPlugin[];
63
63
  //#endregion
64
64
  //# sourceMappingURL=webPluginManifest.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webPluginManifest.d.mts","names":[],"sources":["../../../../src/builders/web/webPluginManifest.ts"],"mappings":";;;;;;;;;;;;;;;;;;;qBAyBa;iBAEI;;EAEf;;iBAGe;EACf;;;;;;EAMA;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR;;;YAIU;qBAEC,+BAA+B;EAC1C,YAAY,oBAAoB,iBAAiB,QAAO;;;wBAgC1C,WAAW;EAAU;EAAkB;EAAoB;;;wBAc3D,eAAe,UAAU,yBAAyB,QAAO;;wBAOzD,kBACd,oBACA,UAAU,yBACV,iBACA,QAAO,sBACN;;wBAyCa,iBAAiB,cAAc;;;;;;wBAc/B,qBACd,kBAAkB,qBAClB,YAAW,2BACV"}
1
+ {"version":3,"file":"webPluginManifest.d.mts","names":[],"sources":["../../../../src/builders/web/webPluginManifest.ts"],"mappings":";;;;;;;;;;;;;;;;;;;qBAyBa;iBAEI;;EAEf;;iBAGe;EACf;;;;;;EAMA;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR;;;YAIU;qBAEC,+BAA+B;EAC1C,YAAY,oBAAoB,iBAAiB,QAAO;;;wBAgC1C,WAAW;EAAU;EAAkB;EAAoB;;;wBAc3D,eAAe,UAAU,yBAAyB,QAAO;;wBAOzD,kBACd,oBACA,UAAU,yBACV,iBACA,QAAO,sBACN;;wBAyCa,iBAAiB,cAAc;;;;;;wBAc/B,qBACd,kBAAkB,qBAClB,YAAW,0BACX,QAAO,sBACN"}
@@ -12,9 +12,9 @@ import crypto from "node:crypto";
12
12
  * Plugins are independent: a manifest names no other plugin, and the order
13
13
  * plugins install in is only a tiebreak (registrationOrder, then pluginId),
14
14
  * because every relation between two plugins resolves by name once all of
15
- * them are installed. A collision between two packages is a notice for the
16
- * sync log and the first package keeps the name; only a malformed block is an
17
- * error, which the scanner turns into a notice for that package alone.
15
+ * them are installed. Web copies keep distinct slots so each mount can select its
16
+ * own package; only repeated declarations of the same slot are dropped. Native
17
+ * plugins still share one pluginId registry. Malformed blocks are scan errors.
18
18
  *
19
19
  * The native app's poNative blocks share this exact shape, so the same
20
20
  * validation reads either field.
@@ -93,21 +93,22 @@ function compareCodeUnits(left, right) {
93
93
  }
94
94
  const byInstallOrder = (left, right) => left.registrationOrder - right.registrationOrder || compareCodeUnits(left.pluginId, right.pluginId) || compareCodeUnits(left.packageDir, right.packageDir);
95
95
  /**
96
- * The deterministic install order, (registrationOrder, pluginId), with the
97
- * cross-package collisions resolved by the browser client registry: the first
98
- * plugin keeps a shared pluginId and the later package is dropped with a notice.
96
+ * Deterministic install order with duplicate web slots removed. Different package
97
+ * copies survive the build; mount selection resolves shared pluginIds later.
98
+ * The native registry is still keyed by pluginId, so it keeps only the first copy.
99
99
  */
100
- function orderDeclaredPlugins(plugins, onNotice = () => void 0) {
100
+ function orderDeclaredPlugins(plugins, onNotice = () => void 0, field = "poWeb") {
101
101
  const sorted = [...plugins].sort(byInstallOrder);
102
- const byId = /* @__PURE__ */ new Map();
102
+ const byKey = /* @__PURE__ */ new Map();
103
103
  const kept = [];
104
104
  for (const plugin of sorted) {
105
- const holder = byId.get(plugin.pluginId);
105
+ const key = field === "poNative" ? plugin.pluginId : plugin.slot;
106
+ const holder = byKey.get(key);
106
107
  if (holder !== void 0) {
107
108
  onNotice(`web plugin '${plugin.pluginId}' from ${plugin.packageDir} is skipped: ${holder.packageDir} already declares it.`);
108
109
  continue;
109
110
  }
110
- byId.set(plugin.pluginId, plugin);
111
+ byKey.set(key, plugin);
111
112
  kept.push(plugin);
112
113
  }
113
114
  return kept;
@@ -1 +1 @@
1
- {"version":3,"file":"webPluginManifest.mjs","names":[],"sources":["../../../../src/builders/web/webPluginManifest.ts"],"sourcesContent":["/**\n * The poWeb manifest vocabulary: how a package declares its web plugin in\n * package.json, validated and ordered; the filesystem is read only to name each\n * copy's slot by its real directory. The\n * scan adapter feeds this from real manifests; the sync bundler feeds it from\n * the installed composition's package roots.\n *\n * Plugins are independent: a manifest names no other plugin, and the order\n * plugins install in is only a tiebreak (registrationOrder, then pluginId),\n * because every relation between two plugins resolves by name once all of\n * them are installed. A collision between two packages is a notice for the\n * sync log and the first package keeps the name; only a malformed block is an\n * error, which the scanner turns into a notice for that package alone.\n *\n * The native app's poNative blocks share this exact shape, so the same\n * validation reads either field.\n */\n\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst PLUGIN_ID_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\n/** The order a plugin installs at when its manifest names none. */\nexport const DEFAULT_REGISTRATION_ORDER = 1000;\n\nexport interface WebPluginEntryDeclaration {\n /** Package-relative ./path to the source entry. */\n entry: string;\n}\n\nexport interface DeclaredWebPlugin {\n pluginId: string;\n /**\n * The registry name of this installed copy: the pluginId for a host plugin, otherwise\n * `${pluginId}.${first 8 hex of sha256(realpath(packageDir))}`, so two copies of one\n * pluginId installed from different directories never share a name.\n */\n slot: string;\n registrationOrder: number;\n packageDir: string;\n packageName: string;\n isHost: boolean;\n client: WebPluginEntryDeclaration;\n scopes: readonly ('global' | 'workspace' | 'session')[];\n}\n\n/** The package.json field a plugin block lives in: the browser cockpit's or the native app's. */\nexport type PluginManifestField = 'poWeb' | 'poNative';\n\nexport class WebPluginManifestError extends Error {\n constructor(packageDir: string, message: string, field: PluginManifestField = 'poWeb') {\n super(`${field} manifest in ${packageDir}: ${message}`);\n this.name = 'WebPluginManifestError';\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction normalizeEntry(\n packageDir: string,\n kind: string,\n value: unknown,\n field: PluginManifestField,\n): WebPluginEntryDeclaration {\n const raw = typeof value === 'string' ? { entry: value } : value;\n if (!isRecord(raw)) throw new WebPluginManifestError(packageDir, `${kind} must be a path or {entry}.`, field);\n const { entry } = raw;\n if (typeof entry !== 'string' || !entry.startsWith('./') || entry.includes('..')) {\n throw new WebPluginManifestError(\n packageDir,\n `${kind}.entry must be a package-relative ./path with no '..'.`,\n field,\n );\n }\n return { entry };\n}\n\nconst SLOT_HASH_LENGTH = 8;\n\n/** The slot of one installed plugin copy; see DeclaredWebPlugin.slot. */\nexport function pluginSlot(plugin: { pluginId: string; packageDir: string; isHost: boolean }): string {\n if (plugin.isHost) return plugin.pluginId;\n let directory: string;\n try {\n directory = fs.realpathSync(plugin.packageDir);\n } catch {\n // A directory that no longer exists has no real path; its resolved path still names it stably.\n directory = path.resolve(plugin.packageDir);\n }\n const digest = crypto.createHash('sha256').update(directory).digest('hex');\n return `${plugin.pluginId}.${digest.slice(0, SLOT_HASH_LENGTH)}`;\n}\n\n/** The field's value normalized to a list: one plugin object or an array of them. */\nexport function pluginBlocksOf(manifest: Record<string, unknown>, field: PluginManifestField = 'poWeb'): unknown[] {\n const value = manifest[field];\n if (value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\n/** Validates one manifest's blocks into declared plugins; throws WebPluginManifestError on bad shape. */\nexport function declaredPluginsOf(\n packageDir: string,\n manifest: Record<string, unknown>,\n isHost: boolean,\n field: PluginManifestField = 'poWeb',\n): DeclaredWebPlugin[] {\n const plugins: DeclaredWebPlugin[] = [];\n for (const block of pluginBlocksOf(manifest, field)) {\n if (!isRecord(block)) throw new WebPluginManifestError(packageDir, 'each block must be an object.', field);\n const { pluginId, registrationOrder = DEFAULT_REGISTRATION_ORDER, client, scopes } = block;\n if (\n !Array.isArray(scopes) ||\n scopes.length === 0 ||\n scopes.some((scope) => !['global', 'workspace', 'session'].includes(scope))\n ) {\n throw new WebPluginManifestError(\n packageDir,\n 'scopes must explicitly name global, workspace, or session; resync the plugin.',\n field,\n );\n }\n if (typeof pluginId !== 'string' || !PLUGIN_ID_PATTERN.test(pluginId)) {\n throw new WebPluginManifestError(packageDir, `pluginId '${String(pluginId)}' must be kebab-case.`, field);\n }\n if (!Number.isInteger(registrationOrder) || (registrationOrder as number) < 0) {\n throw new WebPluginManifestError(\n packageDir,\n `'${pluginId}' needs a non-negative integer registrationOrder.`,\n field,\n );\n }\n plugins.push({\n pluginId,\n slot: pluginSlot({ pluginId, packageDir, isHost }),\n registrationOrder: registrationOrder as number,\n packageDir,\n packageName: typeof manifest.name === 'string' ? manifest.name : packageDir,\n isHost,\n client: normalizeEntry(packageDir, 'client', client, field),\n scopes,\n });\n }\n return plugins;\n}\n\n/** Code-unit order, never the locale's: the same packages must order the same on every machine. */\nexport function compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nconst byInstallOrder = (left: DeclaredWebPlugin, right: DeclaredWebPlugin): number =>\n left.registrationOrder - right.registrationOrder ||\n compareCodeUnits(left.pluginId, right.pluginId) ||\n compareCodeUnits(left.packageDir, right.packageDir);\n\n/**\n * The deterministic install order, (registrationOrder, pluginId), with the\n * cross-package collisions resolved by the browser client registry: the first\n * plugin keeps a shared pluginId and the later package is dropped with a notice.\n */\nexport function orderDeclaredPlugins(\n plugins: readonly DeclaredWebPlugin[],\n onNotice: (message: string) => void = () => undefined,\n): DeclaredWebPlugin[] {\n const sorted = [...plugins].sort(byInstallOrder);\n const byId = new Map<string, DeclaredWebPlugin>();\n const kept: DeclaredWebPlugin[] = [];\n for (const plugin of sorted) {\n const holder = byId.get(plugin.pluginId);\n if (holder !== undefined) {\n onNotice(\n `web plugin '${plugin.pluginId}' from ${plugin.packageDir} is skipped: ${holder.packageDir} already declares it.`,\n );\n continue;\n }\n byId.set(plugin.pluginId, plugin);\n kept.push(plugin);\n }\n return kept;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"webPluginManifest.mjs","names":[],"sources":["../../../../src/builders/web/webPluginManifest.ts"],"sourcesContent":["/**\n * The poWeb manifest vocabulary: how a package declares its web plugin in\n * package.json, validated and ordered; the filesystem is read only to name each\n * copy's slot by its real directory. The\n * scan adapter feeds this from real manifests; the sync bundler feeds it from\n * the installed composition's package roots.\n *\n * Plugins are independent: a manifest names no other plugin, and the order\n * plugins install in is only a tiebreak (registrationOrder, then pluginId),\n * because every relation between two plugins resolves by name once all of\n * them are installed. Web copies keep distinct slots so each mount can select its\n * own package; only repeated declarations of the same slot are dropped. Native\n * plugins still share one pluginId registry. Malformed blocks are scan errors.\n *\n * The native app's poNative blocks share this exact shape, so the same\n * validation reads either field.\n */\n\nimport crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst PLUGIN_ID_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\n\n/** The order a plugin installs at when its manifest names none. */\nexport const DEFAULT_REGISTRATION_ORDER = 1000;\n\nexport interface WebPluginEntryDeclaration {\n /** Package-relative ./path to the source entry. */\n entry: string;\n}\n\nexport interface DeclaredWebPlugin {\n pluginId: string;\n /**\n * The registry name of this installed copy: the pluginId for a host plugin, otherwise\n * `${pluginId}.${first 8 hex of sha256(realpath(packageDir))}`, so two copies of one\n * pluginId installed from different directories never share a name.\n */\n slot: string;\n registrationOrder: number;\n packageDir: string;\n packageName: string;\n isHost: boolean;\n client: WebPluginEntryDeclaration;\n scopes: readonly ('global' | 'workspace' | 'session')[];\n}\n\n/** The package.json field a plugin block lives in: the browser cockpit's or the native app's. */\nexport type PluginManifestField = 'poWeb' | 'poNative';\n\nexport class WebPluginManifestError extends Error {\n constructor(packageDir: string, message: string, field: PluginManifestField = 'poWeb') {\n super(`${field} manifest in ${packageDir}: ${message}`);\n this.name = 'WebPluginManifestError';\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction normalizeEntry(\n packageDir: string,\n kind: string,\n value: unknown,\n field: PluginManifestField,\n): WebPluginEntryDeclaration {\n const raw = typeof value === 'string' ? { entry: value } : value;\n if (!isRecord(raw)) throw new WebPluginManifestError(packageDir, `${kind} must be a path or {entry}.`, field);\n const { entry } = raw;\n if (typeof entry !== 'string' || !entry.startsWith('./') || entry.includes('..')) {\n throw new WebPluginManifestError(\n packageDir,\n `${kind}.entry must be a package-relative ./path with no '..'.`,\n field,\n );\n }\n return { entry };\n}\n\nconst SLOT_HASH_LENGTH = 8;\n\n/** The slot of one installed plugin copy; see DeclaredWebPlugin.slot. */\nexport function pluginSlot(plugin: { pluginId: string; packageDir: string; isHost: boolean }): string {\n if (plugin.isHost) return plugin.pluginId;\n let directory: string;\n try {\n directory = fs.realpathSync(plugin.packageDir);\n } catch {\n // A directory that no longer exists has no real path; its resolved path still names it stably.\n directory = path.resolve(plugin.packageDir);\n }\n const digest = crypto.createHash('sha256').update(directory).digest('hex');\n return `${plugin.pluginId}.${digest.slice(0, SLOT_HASH_LENGTH)}`;\n}\n\n/** The field's value normalized to a list: one plugin object or an array of them. */\nexport function pluginBlocksOf(manifest: Record<string, unknown>, field: PluginManifestField = 'poWeb'): unknown[] {\n const value = manifest[field];\n if (value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\n/** Validates one manifest's blocks into declared plugins; throws WebPluginManifestError on bad shape. */\nexport function declaredPluginsOf(\n packageDir: string,\n manifest: Record<string, unknown>,\n isHost: boolean,\n field: PluginManifestField = 'poWeb',\n): DeclaredWebPlugin[] {\n const plugins: DeclaredWebPlugin[] = [];\n for (const block of pluginBlocksOf(manifest, field)) {\n if (!isRecord(block)) throw new WebPluginManifestError(packageDir, 'each block must be an object.', field);\n const { pluginId, registrationOrder = DEFAULT_REGISTRATION_ORDER, client, scopes } = block;\n if (\n !Array.isArray(scopes) ||\n scopes.length === 0 ||\n scopes.some((scope) => !['global', 'workspace', 'session'].includes(scope))\n ) {\n throw new WebPluginManifestError(\n packageDir,\n 'scopes must explicitly name global, workspace, or session; resync the plugin.',\n field,\n );\n }\n if (typeof pluginId !== 'string' || !PLUGIN_ID_PATTERN.test(pluginId)) {\n throw new WebPluginManifestError(packageDir, `pluginId '${String(pluginId)}' must be kebab-case.`, field);\n }\n if (!Number.isInteger(registrationOrder) || (registrationOrder as number) < 0) {\n throw new WebPluginManifestError(\n packageDir,\n `'${pluginId}' needs a non-negative integer registrationOrder.`,\n field,\n );\n }\n plugins.push({\n pluginId,\n slot: pluginSlot({ pluginId, packageDir, isHost }),\n registrationOrder: registrationOrder as number,\n packageDir,\n packageName: typeof manifest.name === 'string' ? manifest.name : packageDir,\n isHost,\n client: normalizeEntry(packageDir, 'client', client, field),\n scopes,\n });\n }\n return plugins;\n}\n\n/** Code-unit order, never the locale's: the same packages must order the same on every machine. */\nexport function compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nconst byInstallOrder = (left: DeclaredWebPlugin, right: DeclaredWebPlugin): number =>\n left.registrationOrder - right.registrationOrder ||\n compareCodeUnits(left.pluginId, right.pluginId) ||\n compareCodeUnits(left.packageDir, right.packageDir);\n\n/**\n * Deterministic install order with duplicate web slots removed. Different package\n * copies survive the build; mount selection resolves shared pluginIds later.\n * The native registry is still keyed by pluginId, so it keeps only the first copy.\n */\nexport function orderDeclaredPlugins(\n plugins: readonly DeclaredWebPlugin[],\n onNotice: (message: string) => void = () => undefined,\n field: PluginManifestField = 'poWeb',\n): DeclaredWebPlugin[] {\n const sorted = [...plugins].sort(byInstallOrder);\n const byKey = new Map<string, DeclaredWebPlugin>();\n const kept: DeclaredWebPlugin[] = [];\n for (const plugin of sorted) {\n const key = field === 'poNative' ? plugin.pluginId : plugin.slot;\n const holder = byKey.get(key);\n if (holder !== undefined) {\n onNotice(\n `web plugin '${plugin.pluginId}' from ${plugin.packageDir} is skipped: ${holder.packageDir} already declares it.`,\n );\n continue;\n }\n byKey.set(key, plugin);\n kept.push(plugin);\n }\n return kept;\n}\n"],"mappings":"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"}