@open-mercato/cli 0.6.7-develop.6795.1.8a3f27921c → 0.6.7-develop.6814.1.0627c7e9f1
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/.turbo/turbo-build.log +1 -1
- package/build.mjs +1 -1
- package/dist/agentic/guides/module-facts.json +90266 -20749
- package/dist/agentic/guides/modules/ai_assistant.md +170 -60
- package/dist/agentic/guides/modules/api_docs.md +26 -1
- package/dist/agentic/guides/modules/api_keys.md +57 -17
- package/dist/agentic/guides/modules/attachments.md +72 -19
- package/dist/agentic/guides/modules/audit_logs.md +95 -29
- package/dist/agentic/guides/modules/auth.md +218 -83
- package/dist/agentic/guides/modules/business_rules.md +108 -34
- package/dist/agentic/guides/modules/catalog.md +386 -157
- package/dist/agentic/guides/modules/channel_gmail.md +55 -6
- package/dist/agentic/guides/modules/channel_imap.md +55 -6
- package/dist/agentic/guides/modules/checkout.md +254 -129
- package/dist/agentic/guides/modules/communication_channels.md +280 -109
- package/dist/agentic/guides/modules/configs.md +68 -11
- package/dist/agentic/guides/modules/content.md +26 -1
- package/dist/agentic/guides/modules/currencies.md +109 -44
- package/dist/agentic/guides/modules/customer_accounts.md +350 -156
- package/dist/agentic/guides/modules/customers.md +642 -294
- package/dist/agentic/guides/modules/dashboards.md +122 -28
- package/dist/agentic/guides/modules/data_sync.md +117 -37
- package/dist/agentic/guides/modules/design_system.md +36 -2
- package/dist/agentic/guides/modules/dictionaries.md +78 -20
- package/dist/agentic/guides/modules/directory.md +110 -45
- package/dist/agentic/guides/modules/entities.md +95 -38
- package/dist/agentic/guides/modules/events.md +31 -1
- package/dist/agentic/guides/modules/feature_toggles.md +79 -12
- package/dist/agentic/guides/modules/gateway_stripe.md +61 -6
- package/dist/agentic/guides/modules/generators.md +17 -1
- package/dist/agentic/guides/modules/inbox_ops.md +171 -60
- package/dist/agentic/guides/modules/integrations.md +116 -30
- package/dist/agentic/guides/modules/messages.md +187 -66
- package/dist/agentic/guides/modules/notifications.md +64 -9
- package/dist/agentic/guides/modules/onboarding.md +47 -8
- package/dist/agentic/guides/modules/payment_gateways.md +133 -48
- package/dist/agentic/guides/modules/perspectives.md +50 -12
- package/dist/agentic/guides/modules/planner.md +102 -32
- package/dist/agentic/guides/modules/portal.md +58 -15
- package/dist/agentic/guides/modules/progress.md +78 -30
- package/dist/agentic/guides/modules/query_index.md +115 -53
- package/dist/agentic/guides/modules/record_locks.md +178 -59
- package/dist/agentic/guides/modules/resources.md +155 -78
- package/dist/agentic/guides/modules/sales.md +620 -257
- package/dist/agentic/guides/modules/scheduler.md +95 -19
- package/dist/agentic/guides/modules/search.md +124 -20
- package/dist/agentic/guides/modules/security.md +251 -105
- package/dist/agentic/guides/modules/shipping_carriers.md +106 -37
- package/dist/agentic/guides/modules/sso.md +121 -49
- package/dist/agentic/guides/modules/staff.md +314 -126
- package/dist/agentic/guides/modules/storage_s3.md +55 -6
- package/dist/agentic/guides/modules/sync_akeneo.md +54 -4
- package/dist/agentic/guides/modules/sync_excel.md +49 -11
- package/dist/agentic/guides/modules/system_status_overlays.md +33 -5
- package/dist/agentic/guides/modules/translations.md +76 -21
- package/dist/agentic/guides/modules/webhooks.md +166 -82
- package/dist/agentic/guides/modules/wms.md +383 -223
- package/dist/agentic/guides/modules/workflows.md +248 -112
- package/dist/agentic/guides/upstream/AGENTS.md +1 -1
- package/dist/agentic/guides/upstream/manifest.json +2 -2
- package/dist/agentic/shared/AGENTS.md.template +6 -5
- package/dist/agentic/shared/ai/harness/cases.json +3 -0
- package/dist/agentic/shared/ai/lessons/_template.md +16 -0
- package/dist/agentic/shared/ai/lessons.md +26 -3
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +7 -6
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +4 -2
- package/dist/agentic/shared/scripts/check-lessons.mjs +178 -0
- package/dist/lib/agentic-setup.js +2 -2
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/module-extension-facts.js +652 -24
- package/dist/lib/generators/module-extension-facts.js.map +3 -3
- package/dist/lib/generators/module-fact-sources.js +70 -0
- package/dist/lib/generators/module-fact-sources.js.map +7 -0
- package/dist/lib/generators/module-facts.js +1001 -26
- package/dist/lib/generators/module-facts.js.map +3 -3
- package/dist/lib/generators/module-override-targets.js +688 -0
- package/dist/lib/generators/module-override-targets.js.map +7 -0
- package/dist/lib/testing/integration.js +5 -0
- package/dist/lib/testing/integration.js.map +2 -2
- package/package.json +5 -5
- package/src/lib/__tests__/agentic-setup.ownership.test.ts +6 -0
- package/src/lib/agentic-setup.ts +6 -2
- package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +92 -0
- package/src/lib/generators/__tests__/module-extension-activations.test.ts +762 -0
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +4 -2
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +37 -3
- package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +561 -0
- package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +149 -0
- package/src/lib/generators/__tests__/module-override-targets.test.ts +304 -0
- package/src/lib/generators/module-extension-facts.ts +923 -27
- package/src/lib/generators/module-fact-sources.ts +108 -0
- package/src/lib/generators/module-facts.ts +1360 -25
- package/src/lib/generators/module-override-targets.ts +863 -0
- package/src/lib/testing/__tests__/integration.test.ts +4 -0
- package/src/lib/testing/integration.ts +5 -0
|
@@ -0,0 +1,688 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { buildFactSourceLookup } from "./module-fact-sources.js";
|
|
3
|
+
import { getFrameworkOverrideModes } from "./module-extension-facts.js";
|
|
4
|
+
const OVERRIDE_MODES = getFrameworkOverrideModes();
|
|
5
|
+
function modesFor(dottedHost) {
|
|
6
|
+
const mode = OVERRIDE_MODES[dottedHost];
|
|
7
|
+
return mode ? [mode] : null;
|
|
8
|
+
}
|
|
9
|
+
function moduleIdOf(facts) {
|
|
10
|
+
const segments = facts.sourceRoot.split("/").filter(Boolean);
|
|
11
|
+
return segments[segments.length - 1] ?? "";
|
|
12
|
+
}
|
|
13
|
+
function computeOverrideTargetId(moduleId, domain, path) {
|
|
14
|
+
return crypto.createHash("sha1").update(JSON.stringify([moduleId, domain, path])).digest("hex").slice(0, 16);
|
|
15
|
+
}
|
|
16
|
+
function compareSourceRefs(left, right) {
|
|
17
|
+
return left.sourcePath.localeCompare(right.sourcePath) || (left.line ?? 0) - (right.line ?? 0) || (left.exportName ?? "").localeCompare(right.exportName ?? "");
|
|
18
|
+
}
|
|
19
|
+
function comparePaths(left, right) {
|
|
20
|
+
const length = Math.max(left.length, right.length);
|
|
21
|
+
for (let index = 0; index < length; index += 1) {
|
|
22
|
+
const leftSegment = left[index];
|
|
23
|
+
const rightSegment = right[index];
|
|
24
|
+
if (leftSegment === void 0) return -1;
|
|
25
|
+
if (rightSegment === void 0) return 1;
|
|
26
|
+
const compared = leftSegment.localeCompare(rightSegment);
|
|
27
|
+
if (compared !== 0) return compared;
|
|
28
|
+
}
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
function makeTarget(input) {
|
|
32
|
+
const modes = modesFor(input.dottedHost);
|
|
33
|
+
if (!modes) return null;
|
|
34
|
+
const target = {
|
|
35
|
+
id: computeOverrideTargetId(input.moduleId, input.domain, input.path),
|
|
36
|
+
domain: input.domain,
|
|
37
|
+
...input.key !== void 0 ? { key: input.key } : {},
|
|
38
|
+
path: input.path,
|
|
39
|
+
modes,
|
|
40
|
+
factRef: input.factRef,
|
|
41
|
+
source: input.source,
|
|
42
|
+
...input.notes && input.notes.length > 0 ? { notes: input.notes } : {}
|
|
43
|
+
};
|
|
44
|
+
return target;
|
|
45
|
+
}
|
|
46
|
+
function pushTarget(targets, diagnostics, input) {
|
|
47
|
+
const target = makeTarget(input);
|
|
48
|
+
if (target) {
|
|
49
|
+
targets.push(target);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
diagnostics.push({
|
|
53
|
+
code: "unknown-framework-domain",
|
|
54
|
+
moduleId: input.moduleId,
|
|
55
|
+
domain: input.domain,
|
|
56
|
+
candidatePath: input.path,
|
|
57
|
+
source: input.source
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function contributionSource(contribution) {
|
|
61
|
+
return {
|
|
62
|
+
sourcePath: contribution.source.path,
|
|
63
|
+
...contribution.source.symbol ? { exportName: contribution.source.symbol } : {}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function ownedSource(fact) {
|
|
67
|
+
return {
|
|
68
|
+
sourcePath: fact.source.sourcePath,
|
|
69
|
+
...fact.source.line ? { line: fact.source.line } : {}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function contributionsOfKind(facts, kind) {
|
|
73
|
+
const contributions = facts.extensionSurfaces?.contributions ?? [];
|
|
74
|
+
return contributions.filter(
|
|
75
|
+
(contribution) => contribution.kind === kind
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
function indexedFactSourcePath(resolveFactSource, kind, id) {
|
|
79
|
+
return resolveFactSource(kind, id)?.sourcePath ?? null;
|
|
80
|
+
}
|
|
81
|
+
const VALID_HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
|
|
82
|
+
function apiRouteOverrideKey(method, routePath) {
|
|
83
|
+
const upper = method.trim().toUpperCase();
|
|
84
|
+
if (!VALID_HTTP_METHODS.has(upper)) return null;
|
|
85
|
+
const withLead = routePath.startsWith("/") ? routePath : `/${routePath}`;
|
|
86
|
+
const publicPath = withLead.startsWith("/api/") || withLead === "/api" ? withLead : `/api${withLead}`;
|
|
87
|
+
const normalized = publicPath.replace(/\/+$/, "") || "/";
|
|
88
|
+
return `${upper} ${normalized}`;
|
|
89
|
+
}
|
|
90
|
+
function pageRouteOverrideKey(routePath) {
|
|
91
|
+
const trimmed = routePath.trim();
|
|
92
|
+
if (!trimmed) return null;
|
|
93
|
+
if (trimmed.startsWith("backend:") || trimmed.startsWith("frontend:")) return trimmed;
|
|
94
|
+
const withLead = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
95
|
+
const stripped = withLead.replace(/\/+$/, "") || "/";
|
|
96
|
+
if (stripped === "/frontend") return "frontend:/";
|
|
97
|
+
if (stripped.startsWith("/frontend/")) return `frontend:/${stripped.slice("/frontend/".length)}`;
|
|
98
|
+
if (stripped === "/backend" || stripped.startsWith("/backend/")) return `backend:${stripped}`;
|
|
99
|
+
return `frontend:${stripped}`;
|
|
100
|
+
}
|
|
101
|
+
const aiAdapter = {
|
|
102
|
+
domain: "ai",
|
|
103
|
+
run(facts) {
|
|
104
|
+
const moduleId = moduleIdOf(facts);
|
|
105
|
+
const targets = [];
|
|
106
|
+
const diagnostics = [];
|
|
107
|
+
for (const agent of facts.aiAgents) {
|
|
108
|
+
if (!agent.sourcePath) {
|
|
109
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "ai", candidatePath: ["ai", "agents", agent.id] });
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const path = ["ai", "agents", agent.id];
|
|
113
|
+
pushTarget(targets, diagnostics, {
|
|
114
|
+
moduleId,
|
|
115
|
+
domain: "ai",
|
|
116
|
+
path,
|
|
117
|
+
key: agent.id,
|
|
118
|
+
dottedHost: "ai.agents",
|
|
119
|
+
factRef: { factSection: "aiAgents", factKey: agent.id },
|
|
120
|
+
source: { sourcePath: agent.sourcePath }
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
for (const tool of facts.aiTools) {
|
|
124
|
+
if (!tool.sourcePath) {
|
|
125
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "ai", candidatePath: ["ai", "tools", tool.name] });
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const path = ["ai", "tools", tool.name];
|
|
129
|
+
pushTarget(targets, diagnostics, {
|
|
130
|
+
moduleId,
|
|
131
|
+
domain: "ai",
|
|
132
|
+
path,
|
|
133
|
+
key: tool.name,
|
|
134
|
+
dottedHost: "ai.tools",
|
|
135
|
+
factRef: { factSection: "aiTools", factKey: tool.name },
|
|
136
|
+
source: { sourcePath: tool.sourcePath }
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const aiFileContracts = facts.ownedContracts?.["ai-extension"] ?? [];
|
|
140
|
+
const additiveExtensions = [];
|
|
141
|
+
for (const fact of aiFileContracts) {
|
|
142
|
+
const metadata = fact.metadata ?? {};
|
|
143
|
+
if (metadata.mode !== "override") {
|
|
144
|
+
additiveExtensions.push(fact);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const overrideKey = typeof metadata.overrideKey === "string" ? metadata.overrideKey : null;
|
|
148
|
+
const target = metadata.target === "agent" ? "agents" : metadata.target === "tool" ? "tools" : null;
|
|
149
|
+
if (!overrideKey || !target) {
|
|
150
|
+
diagnostics.push({
|
|
151
|
+
code: "unsupported-dynamic-key",
|
|
152
|
+
moduleId,
|
|
153
|
+
domain: "ai",
|
|
154
|
+
candidatePath: ["ai", target ?? "extensions"],
|
|
155
|
+
source: ownedSource(fact)
|
|
156
|
+
});
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const path = ["ai", target, overrideKey];
|
|
160
|
+
pushTarget(targets, diagnostics, {
|
|
161
|
+
moduleId,
|
|
162
|
+
domain: "ai",
|
|
163
|
+
path,
|
|
164
|
+
key: overrideKey,
|
|
165
|
+
dottedHost: `ai.${target}`,
|
|
166
|
+
factRef: { factSection: "ownedContracts.ai-extension", factKey: fact.id },
|
|
167
|
+
source: ownedSource(fact)
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
if (additiveExtensions.length > 0) {
|
|
171
|
+
const anchor = [...additiveExtensions].sort((left, right) => left.id.localeCompare(right.id))[0];
|
|
172
|
+
pushTarget(targets, diagnostics, {
|
|
173
|
+
moduleId,
|
|
174
|
+
domain: "ai",
|
|
175
|
+
path: ["ai", "extensions"],
|
|
176
|
+
dottedHost: "ai.extensions",
|
|
177
|
+
factRef: { factSection: "ownedContracts.ai-extension", factKey: anchor.id },
|
|
178
|
+
source: ownedSource(anchor)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return { targets, diagnostics };
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const routesAdapter = {
|
|
185
|
+
domain: "routes",
|
|
186
|
+
run(facts) {
|
|
187
|
+
const moduleId = moduleIdOf(facts);
|
|
188
|
+
const targets = [];
|
|
189
|
+
const diagnostics = [];
|
|
190
|
+
for (const route of facts.apiRoutes) {
|
|
191
|
+
for (const method of route.methods) {
|
|
192
|
+
const key = apiRouteOverrideKey(method, route.path);
|
|
193
|
+
if (!key) {
|
|
194
|
+
diagnostics.push({ code: "unsupported-dynamic-key", moduleId, domain: "routes", candidatePath: ["routes", "api", `${method} ${route.path}`] });
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (!route.sourcePath) {
|
|
198
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "routes", candidatePath: ["routes", "api", key] });
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const path = ["routes", "api", key];
|
|
202
|
+
pushTarget(targets, diagnostics, {
|
|
203
|
+
moduleId,
|
|
204
|
+
domain: "routes",
|
|
205
|
+
path,
|
|
206
|
+
key,
|
|
207
|
+
dottedHost: "routes.api",
|
|
208
|
+
factRef: { factSection: "apiRoutes", factKey: route.path },
|
|
209
|
+
source: { sourcePath: route.sourcePath }
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const emitPage = (page, section) => {
|
|
214
|
+
const key = pageRouteOverrideKey(page.path);
|
|
215
|
+
if (!key) {
|
|
216
|
+
diagnostics.push({ code: "unsupported-dynamic-key", moduleId, domain: "routes", candidatePath: ["routes", "pages", page.path] });
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (!page.sourcePath) {
|
|
220
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "routes", candidatePath: ["routes", "pages", key] });
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const path = ["routes", "pages", key];
|
|
224
|
+
pushTarget(targets, diagnostics, {
|
|
225
|
+
moduleId,
|
|
226
|
+
domain: "routes",
|
|
227
|
+
path,
|
|
228
|
+
key,
|
|
229
|
+
dottedHost: "routes.pages",
|
|
230
|
+
factRef: { factSection: section, factKey: page.path },
|
|
231
|
+
source: { sourcePath: page.sourcePath }
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
for (const page of facts.backendPages) emitPage(page, "backendPages");
|
|
235
|
+
for (const page of facts.frontendPages) emitPage(page, "frontendPages");
|
|
236
|
+
return { targets, diagnostics };
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const eventsAdapter = {
|
|
240
|
+
domain: "events",
|
|
241
|
+
run(facts) {
|
|
242
|
+
const moduleId = moduleIdOf(facts);
|
|
243
|
+
const targets = [];
|
|
244
|
+
const diagnostics = [];
|
|
245
|
+
for (const contribution of contributionsOfKind(facts, "subscriber")) {
|
|
246
|
+
const subscriberId = contribution.details.subscriberId || contribution.id;
|
|
247
|
+
const path = ["events", "subscribers", subscriberId];
|
|
248
|
+
if (!contribution.source.path) {
|
|
249
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "events", candidatePath: path });
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
pushTarget(targets, diagnostics, {
|
|
253
|
+
moduleId,
|
|
254
|
+
domain: "events",
|
|
255
|
+
path,
|
|
256
|
+
key: subscriberId,
|
|
257
|
+
dottedHost: "events.subscribers",
|
|
258
|
+
factRef: { factSection: "extensionSurfaces.contributions", factKey: contribution.id },
|
|
259
|
+
source: contributionSource(contribution)
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
return { targets, diagnostics };
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const workersAdapter = {
|
|
266
|
+
domain: "workers",
|
|
267
|
+
run(facts) {
|
|
268
|
+
const moduleId = moduleIdOf(facts);
|
|
269
|
+
const targets = [];
|
|
270
|
+
const diagnostics = [];
|
|
271
|
+
for (const fact of facts.ownedContracts?.worker ?? []) {
|
|
272
|
+
const path = ["workers", fact.id];
|
|
273
|
+
if (!fact.source.sourcePath) {
|
|
274
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "workers", candidatePath: path });
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
pushTarget(targets, diagnostics, {
|
|
278
|
+
moduleId,
|
|
279
|
+
domain: "workers",
|
|
280
|
+
path,
|
|
281
|
+
key: fact.id,
|
|
282
|
+
dottedHost: "workers",
|
|
283
|
+
factRef: { factSection: "ownedContracts.worker", factKey: fact.id },
|
|
284
|
+
source: ownedSource(fact)
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
return { targets, diagnostics };
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
const widgetsAdapter = {
|
|
291
|
+
domain: "widgets",
|
|
292
|
+
run(facts) {
|
|
293
|
+
const moduleId = moduleIdOf(facts);
|
|
294
|
+
const targets = [];
|
|
295
|
+
const diagnostics = [];
|
|
296
|
+
const emitInjection = (registryKey, contribution) => {
|
|
297
|
+
const path = ["widgets", "injection", registryKey];
|
|
298
|
+
pushTarget(targets, diagnostics, {
|
|
299
|
+
moduleId,
|
|
300
|
+
domain: "widgets",
|
|
301
|
+
path,
|
|
302
|
+
key: registryKey,
|
|
303
|
+
dottedHost: "widgets.injection",
|
|
304
|
+
factRef: { factSection: "extensionSurfaces.contributions", factKey: contribution.id },
|
|
305
|
+
source: contributionSource(contribution)
|
|
306
|
+
});
|
|
307
|
+
};
|
|
308
|
+
for (const contribution of contributionsOfKind(facts, "widget")) {
|
|
309
|
+
const registryKey = contribution.details.registryKey;
|
|
310
|
+
if (!registryKey) {
|
|
311
|
+
diagnostics.push({ code: "unsupported-dynamic-key", moduleId, domain: "widgets", candidatePath: ["widgets", "injection", contribution.id] });
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
if (contribution.details.payload === "dashboard") {
|
|
315
|
+
const path = ["widgets", "dashboard", registryKey];
|
|
316
|
+
pushTarget(targets, diagnostics, {
|
|
317
|
+
moduleId,
|
|
318
|
+
domain: "widgets",
|
|
319
|
+
path,
|
|
320
|
+
key: registryKey,
|
|
321
|
+
dottedHost: "widgets.dashboard",
|
|
322
|
+
factRef: { factSection: "extensionSurfaces.contributions", factKey: contribution.id },
|
|
323
|
+
source: contributionSource(contribution)
|
|
324
|
+
});
|
|
325
|
+
} else {
|
|
326
|
+
emitInjection(registryKey, contribution);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
for (const contribution of [
|
|
330
|
+
...contributionsOfKind(facts, "data-table"),
|
|
331
|
+
...contributionsOfKind(facts, "crud-form")
|
|
332
|
+
]) {
|
|
333
|
+
const registryKey = contribution.id.split("@")[0];
|
|
334
|
+
if (!registryKey || registryKey === contribution.id) {
|
|
335
|
+
diagnostics.push({ code: "unsupported-dynamic-key", moduleId, domain: "widgets", candidatePath: ["widgets", "injection", contribution.id] });
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
emitInjection(registryKey, contribution);
|
|
339
|
+
}
|
|
340
|
+
for (const contribution of contributionsOfKind(facts, "component-override")) {
|
|
341
|
+
const componentId = contribution.details.handle;
|
|
342
|
+
const path = ["widgets", "components", componentId];
|
|
343
|
+
pushTarget(targets, diagnostics, {
|
|
344
|
+
moduleId,
|
|
345
|
+
domain: "widgets",
|
|
346
|
+
path,
|
|
347
|
+
key: componentId,
|
|
348
|
+
dottedHost: "widgets.components",
|
|
349
|
+
factRef: { factSection: "extensionSurfaces.contributions", factKey: contribution.id },
|
|
350
|
+
source: contributionSource(contribution)
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
return { targets, diagnostics };
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const notificationsAdapter = {
|
|
357
|
+
domain: "notifications",
|
|
358
|
+
run(facts, resolveFactSource) {
|
|
359
|
+
const moduleId = moduleIdOf(facts);
|
|
360
|
+
const targets = [];
|
|
361
|
+
const diagnostics = [];
|
|
362
|
+
const registrySources = /* @__PURE__ */ new Map();
|
|
363
|
+
for (const contribution of contributionsOfKind(facts, "specialized-registry")) {
|
|
364
|
+
if (contribution.details.registry !== "notification") continue;
|
|
365
|
+
registrySources.set(contribution.details.registryId, contributionSource(contribution));
|
|
366
|
+
}
|
|
367
|
+
for (const type of facts.notifications) {
|
|
368
|
+
const path = ["notifications", "types", type];
|
|
369
|
+
const indexedPath = indexedFactSourcePath(resolveFactSource, "notification", type);
|
|
370
|
+
const source = registrySources.get(type) ?? (indexedPath ? { sourcePath: indexedPath } : null);
|
|
371
|
+
if (!source) {
|
|
372
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "notifications", candidatePath: path });
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
pushTarget(targets, diagnostics, {
|
|
376
|
+
moduleId,
|
|
377
|
+
domain: "notifications",
|
|
378
|
+
path,
|
|
379
|
+
key: type,
|
|
380
|
+
dottedHost: "notifications.types",
|
|
381
|
+
factRef: { factSection: "notifications", factKey: type },
|
|
382
|
+
source
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
for (const contribution of contributionsOfKind(facts, "browser-reaction")) {
|
|
386
|
+
if (!contribution.details.transports.includes("notification-effect")) continue;
|
|
387
|
+
const overrideKey = contribution.details.overrideKey;
|
|
388
|
+
if (!overrideKey) {
|
|
389
|
+
diagnostics.push({
|
|
390
|
+
code: "unsupported-dynamic-key",
|
|
391
|
+
moduleId,
|
|
392
|
+
domain: "notifications",
|
|
393
|
+
candidatePath: ["notifications", "handlers"],
|
|
394
|
+
source: contributionSource(contribution)
|
|
395
|
+
});
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
pushTarget(targets, diagnostics, {
|
|
399
|
+
moduleId,
|
|
400
|
+
domain: "notifications",
|
|
401
|
+
path: ["notifications", "handlers", overrideKey],
|
|
402
|
+
key: overrideKey,
|
|
403
|
+
dottedHost: "notifications.handlers",
|
|
404
|
+
factRef: { factSection: "extensionSurfaces.contributions", factKey: contribution.id },
|
|
405
|
+
source: contributionSource(contribution)
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
return { targets, diagnostics };
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
function contributionIdAdapter(domain, kind, dottedHost) {
|
|
412
|
+
return {
|
|
413
|
+
domain,
|
|
414
|
+
run(facts) {
|
|
415
|
+
const moduleId = moduleIdOf(facts);
|
|
416
|
+
const targets = [];
|
|
417
|
+
const diagnostics = [];
|
|
418
|
+
for (const contribution of contributionsOfKind(facts, kind)) {
|
|
419
|
+
const path = [domain, contribution.id];
|
|
420
|
+
if (!contribution.source.path) {
|
|
421
|
+
diagnostics.push({ code: "missing-source", moduleId, domain, candidatePath: path });
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
pushTarget(targets, diagnostics, {
|
|
425
|
+
moduleId,
|
|
426
|
+
domain,
|
|
427
|
+
path,
|
|
428
|
+
key: contribution.id,
|
|
429
|
+
dottedHost,
|
|
430
|
+
factRef: { factSection: "extensionSurfaces.contributions", factKey: contribution.id },
|
|
431
|
+
source: contributionSource(contribution)
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
return { targets, diagnostics };
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
const interceptorsAdapter = contributionIdAdapter("interceptors", "api-interceptor", "interceptors");
|
|
439
|
+
const commandInterceptorsAdapter = contributionIdAdapter("commandInterceptors", "command-interceptor", "commandInterceptors");
|
|
440
|
+
const enrichersAdapter = contributionIdAdapter("enrichers", "response-enricher", "enrichers");
|
|
441
|
+
const guardsAdapter = {
|
|
442
|
+
domain: "guards",
|
|
443
|
+
run(facts) {
|
|
444
|
+
const moduleId = moduleIdOf(facts);
|
|
445
|
+
const targets = [];
|
|
446
|
+
const diagnostics = [];
|
|
447
|
+
for (const fact of facts.ownedContracts?.["page-middleware"] ?? []) {
|
|
448
|
+
const path = ["guards", fact.id];
|
|
449
|
+
if (!fact.source.sourcePath) {
|
|
450
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "guards", candidatePath: path });
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
pushTarget(targets, diagnostics, {
|
|
454
|
+
moduleId,
|
|
455
|
+
domain: "guards",
|
|
456
|
+
path,
|
|
457
|
+
key: fact.id,
|
|
458
|
+
dottedHost: "guards",
|
|
459
|
+
factRef: { factSection: "ownedContracts.page-middleware", factKey: fact.id },
|
|
460
|
+
source: ownedSource(fact),
|
|
461
|
+
notes: ["page-middleware-not-mutation-guard"]
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
return { targets, diagnostics };
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
const cliAdapter = {
|
|
468
|
+
domain: "cli",
|
|
469
|
+
run(facts) {
|
|
470
|
+
const moduleId = moduleIdOf(facts);
|
|
471
|
+
const targets = [];
|
|
472
|
+
const diagnostics = [];
|
|
473
|
+
for (const command of facts.cliCommands) {
|
|
474
|
+
const path = ["cli", command.command];
|
|
475
|
+
if (!command.sourcePath) {
|
|
476
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "cli", candidatePath: path });
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
pushTarget(targets, diagnostics, {
|
|
480
|
+
moduleId,
|
|
481
|
+
domain: "cli",
|
|
482
|
+
path,
|
|
483
|
+
key: command.command,
|
|
484
|
+
dottedHost: "cli",
|
|
485
|
+
factRef: { factSection: "cliCommands", factKey: command.command },
|
|
486
|
+
source: { sourcePath: command.sourcePath }
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
return { targets, diagnostics };
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
const SUPPORTED_SETUP_HOOKS = /* @__PURE__ */ new Set(["seedDefaults", "seedExamples", "onTenantCreated"]);
|
|
493
|
+
const setupAdapter = {
|
|
494
|
+
domain: "setup",
|
|
495
|
+
run(facts) {
|
|
496
|
+
const moduleId = moduleIdOf(facts);
|
|
497
|
+
const targets = [];
|
|
498
|
+
const diagnostics = [];
|
|
499
|
+
const setupFacts = facts.ownedContracts?.setup ?? [];
|
|
500
|
+
for (const fact of setupFacts) {
|
|
501
|
+
if (!fact.source.sourcePath) {
|
|
502
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "setup", candidatePath: ["setup"] });
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
const source = ownedSource(fact);
|
|
506
|
+
const properties = [];
|
|
507
|
+
const hooks = fact.metadata?.hooks;
|
|
508
|
+
if (Array.isArray(hooks)) {
|
|
509
|
+
for (const hook of hooks) {
|
|
510
|
+
if (typeof hook === "string" && SUPPORTED_SETUP_HOOKS.has(hook)) properties.push(hook);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const roles = fact.metadata?.roles;
|
|
514
|
+
if (Array.isArray(roles) && roles.length > 0) properties.push("defaultRoleFeatures");
|
|
515
|
+
const customerRoles = fact.metadata?.customerRoles;
|
|
516
|
+
if (Array.isArray(customerRoles) && customerRoles.length > 0) properties.push("defaultCustomerRoleFeatures");
|
|
517
|
+
for (const property of properties) {
|
|
518
|
+
const path = ["setup", property];
|
|
519
|
+
pushTarget(targets, diagnostics, {
|
|
520
|
+
moduleId,
|
|
521
|
+
domain: "setup",
|
|
522
|
+
path,
|
|
523
|
+
dottedHost: "setup",
|
|
524
|
+
factRef: { factSection: "ownedContracts.setup", factKey: fact.id },
|
|
525
|
+
source
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return { targets, diagnostics };
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
const aclAdapter = {
|
|
533
|
+
domain: "acl",
|
|
534
|
+
run(facts, resolveFactSource) {
|
|
535
|
+
const moduleId = moduleIdOf(facts);
|
|
536
|
+
const targets = [];
|
|
537
|
+
const diagnostics = [];
|
|
538
|
+
for (const feature of facts.aclFeatures) {
|
|
539
|
+
const path = ["acl", "features", feature];
|
|
540
|
+
const sourcePath = indexedFactSourcePath(resolveFactSource, "acl-feature", feature);
|
|
541
|
+
if (!sourcePath) {
|
|
542
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "acl", candidatePath: path });
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
pushTarget(targets, diagnostics, {
|
|
546
|
+
moduleId,
|
|
547
|
+
domain: "acl",
|
|
548
|
+
path,
|
|
549
|
+
key: feature,
|
|
550
|
+
dottedHost: "acl.features",
|
|
551
|
+
factRef: { factSection: "aclFeatures", factKey: feature },
|
|
552
|
+
source: { sourcePath }
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
return { targets, diagnostics };
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
const diAdapter = {
|
|
559
|
+
domain: "di",
|
|
560
|
+
run(facts) {
|
|
561
|
+
const moduleId = moduleIdOf(facts);
|
|
562
|
+
const targets = [];
|
|
563
|
+
const diagnostics = [];
|
|
564
|
+
for (const fact of facts.ownedContracts?.["di-registration"] ?? []) {
|
|
565
|
+
const path = ["di", fact.id];
|
|
566
|
+
if (!fact.source.sourcePath) {
|
|
567
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "di", candidatePath: path });
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
pushTarget(targets, diagnostics, {
|
|
571
|
+
moduleId,
|
|
572
|
+
domain: "di",
|
|
573
|
+
path,
|
|
574
|
+
key: fact.id,
|
|
575
|
+
dottedHost: "di",
|
|
576
|
+
factRef: { factSection: "ownedContracts.di-registration", factKey: fact.id },
|
|
577
|
+
source: ownedSource(fact),
|
|
578
|
+
notes: ["safe-metadata-only"]
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
return { targets, diagnostics };
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
const encryptionAdapter = {
|
|
585
|
+
domain: "encryption",
|
|
586
|
+
run(facts) {
|
|
587
|
+
const moduleId = moduleIdOf(facts);
|
|
588
|
+
const targets = [];
|
|
589
|
+
const diagnostics = [];
|
|
590
|
+
for (const fact of facts.ownedContracts?.encryption ?? []) {
|
|
591
|
+
const path = ["encryption", "maps", fact.id];
|
|
592
|
+
if (!fact.source.sourcePath) {
|
|
593
|
+
diagnostics.push({ code: "missing-source", moduleId, domain: "encryption", candidatePath: path });
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
pushTarget(targets, diagnostics, {
|
|
597
|
+
moduleId,
|
|
598
|
+
domain: "encryption",
|
|
599
|
+
path,
|
|
600
|
+
key: fact.id,
|
|
601
|
+
dottedHost: "encryption.maps",
|
|
602
|
+
factRef: { factSection: "ownedContracts.encryption", factKey: fact.id },
|
|
603
|
+
source: ownedSource(fact)
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
return { targets, diagnostics };
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
const navAdapter = {
|
|
610
|
+
domain: "nav",
|
|
611
|
+
frameworkOnly: true,
|
|
612
|
+
run() {
|
|
613
|
+
return { targets: [], diagnostics: [] };
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
const INTERNAL_ADAPTERS = [
|
|
617
|
+
aiAdapter,
|
|
618
|
+
routesAdapter,
|
|
619
|
+
eventsAdapter,
|
|
620
|
+
workersAdapter,
|
|
621
|
+
widgetsAdapter,
|
|
622
|
+
notificationsAdapter,
|
|
623
|
+
interceptorsAdapter,
|
|
624
|
+
commandInterceptorsAdapter,
|
|
625
|
+
enrichersAdapter,
|
|
626
|
+
guardsAdapter,
|
|
627
|
+
cliAdapter,
|
|
628
|
+
setupAdapter,
|
|
629
|
+
aclAdapter,
|
|
630
|
+
diAdapter,
|
|
631
|
+
encryptionAdapter,
|
|
632
|
+
navAdapter
|
|
633
|
+
];
|
|
634
|
+
const OVERRIDE_DOMAIN_PRESENCE = {
|
|
635
|
+
ai: true,
|
|
636
|
+
routes: true,
|
|
637
|
+
events: true,
|
|
638
|
+
workers: true,
|
|
639
|
+
widgets: true,
|
|
640
|
+
notifications: true,
|
|
641
|
+
interceptors: true,
|
|
642
|
+
commandInterceptors: true,
|
|
643
|
+
enrichers: true,
|
|
644
|
+
guards: true,
|
|
645
|
+
cli: true,
|
|
646
|
+
setup: true,
|
|
647
|
+
acl: true,
|
|
648
|
+
di: true,
|
|
649
|
+
encryption: true,
|
|
650
|
+
nav: true
|
|
651
|
+
};
|
|
652
|
+
const ALL_OVERRIDE_DOMAINS = Object.keys(OVERRIDE_DOMAIN_PRESENCE);
|
|
653
|
+
const MODULE_OVERRIDE_TARGET_ADAPTERS = INTERNAL_ADAPTERS.map((adapter) => ({
|
|
654
|
+
domain: adapter.domain,
|
|
655
|
+
...adapter.frameworkOnly ? { frameworkOnly: true } : {},
|
|
656
|
+
collect: (moduleFacts) => adapter.run(moduleFacts, buildFactSourceLookup(moduleFacts)).targets,
|
|
657
|
+
diagnose: (moduleFacts) => adapter.run(moduleFacts, buildFactSourceLookup(moduleFacts)).diagnostics
|
|
658
|
+
}));
|
|
659
|
+
function collectModuleOverrideTargets(facts, resolveFactSource = buildFactSourceLookup(facts)) {
|
|
660
|
+
const collected = [];
|
|
661
|
+
const diagnostics = [];
|
|
662
|
+
for (const adapter of INTERNAL_ADAPTERS) {
|
|
663
|
+
if (adapter.frameworkOnly) continue;
|
|
664
|
+
const result = adapter.run(facts, resolveFactSource);
|
|
665
|
+
collected.push(...result.targets);
|
|
666
|
+
diagnostics.push(...result.diagnostics);
|
|
667
|
+
}
|
|
668
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
669
|
+
for (const target of collected) {
|
|
670
|
+
const pathKey = `${target.domain} ${JSON.stringify(target.path)}`;
|
|
671
|
+
const existing = byPath.get(pathKey);
|
|
672
|
+
if (!existing || compareSourceRefs(target.source, existing.source) < 0) byPath.set(pathKey, target);
|
|
673
|
+
}
|
|
674
|
+
const overrideTargets = [...byPath.values()].sort(
|
|
675
|
+
(left, right) => left.domain.localeCompare(right.domain) || comparePaths(left.path, right.path) || compareSourceRefs(left.source, right.source)
|
|
676
|
+
);
|
|
677
|
+
const overrideTargetDiagnostics = diagnostics.sort(
|
|
678
|
+
(left, right) => left.moduleId.localeCompare(right.moduleId) || left.domain.localeCompare(right.domain) || left.code.localeCompare(right.code) || comparePaths(left.candidatePath ?? [], right.candidatePath ?? []) || compareSourceRefs(left.source ?? { sourcePath: "" }, right.source ?? { sourcePath: "" })
|
|
679
|
+
);
|
|
680
|
+
return { overrideTargets, overrideTargetDiagnostics };
|
|
681
|
+
}
|
|
682
|
+
export {
|
|
683
|
+
ALL_OVERRIDE_DOMAINS,
|
|
684
|
+
MODULE_OVERRIDE_TARGET_ADAPTERS,
|
|
685
|
+
collectModuleOverrideTargets,
|
|
686
|
+
computeOverrideTargetId
|
|
687
|
+
};
|
|
688
|
+
//# sourceMappingURL=module-override-targets.js.map
|