@open-mercato/cli 0.6.8-develop.6931.1.4a1e1c786b → 0.6.8-develop.6941.1.3c26284542
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 +64 -0
- package/build.mjs +57 -7
- package/dist/agentic/guides/backend-ui.md +7 -1
- package/dist/agentic/guides/module-facts.json +565 -224
- package/dist/agentic/guides/module-facts.v2.json +122933 -0
- package/dist/agentic/guides/modules/ai_assistant.md +2 -2
- package/dist/agentic/guides/modules/api_docs.md +2 -2
- package/dist/agentic/guides/modules/api_keys.md +2 -2
- package/dist/agentic/guides/modules/attachments.md +2 -2
- package/dist/agentic/guides/modules/audit_logs.md +2 -2
- package/dist/agentic/guides/modules/auth.md +2 -2
- package/dist/agentic/guides/modules/business_rules.md +2 -2
- package/dist/agentic/guides/modules/catalog.md +11 -4
- package/dist/agentic/guides/modules/channel_gmail.md +2 -2
- package/dist/agentic/guides/modules/channel_imap.md +2 -2
- package/dist/agentic/guides/modules/checkout.md +8 -2
- package/dist/agentic/guides/modules/communication_channels.md +6 -6
- package/dist/agentic/guides/modules/configs.md +2 -2
- package/dist/agentic/guides/modules/content.md +2 -2
- package/dist/agentic/guides/modules/currencies.md +2 -2
- package/dist/agentic/guides/modules/customer_accounts.md +2 -2
- package/dist/agentic/guides/modules/customers.md +8 -8
- package/dist/agentic/guides/modules/dashboards.md +12 -12
- package/dist/agentic/guides/modules/data_sync.md +4 -4
- package/dist/agentic/guides/modules/design_system.md +2 -2
- package/dist/agentic/guides/modules/dictionaries.md +2 -2
- package/dist/agentic/guides/modules/directory.md +2 -2
- package/dist/agentic/guides/modules/entities.md +3 -3
- package/dist/agentic/guides/modules/eudr.md +3 -3
- package/dist/agentic/guides/modules/events.md +2 -2
- package/dist/agentic/guides/modules/feature_toggles.md +2 -2
- package/dist/agentic/guides/modules/gateway_stripe.md +2 -2
- package/dist/agentic/guides/modules/generators.md +2 -2
- package/dist/agentic/guides/modules/inbox_ops.md +2 -2
- package/dist/agentic/guides/modules/integrations.md +5 -2
- package/dist/agentic/guides/modules/messages.md +2 -2
- package/dist/agentic/guides/modules/notifications.md +2 -2
- package/dist/agentic/guides/modules/onboarding.md +2 -2
- package/dist/agentic/guides/modules/payment_gateways.md +7 -3
- package/dist/agentic/guides/modules/perspectives.md +2 -2
- package/dist/agentic/guides/modules/planner.md +2 -2
- package/dist/agentic/guides/modules/portal.md +2 -2
- package/dist/agentic/guides/modules/progress.md +2 -2
- package/dist/agentic/guides/modules/query_index.md +2 -2
- package/dist/agentic/guides/modules/record_locks.md +3 -3
- package/dist/agentic/guides/modules/resources.md +2 -2
- package/dist/agentic/guides/modules/sales.md +13 -4
- package/dist/agentic/guides/modules/scheduler.md +2 -2
- package/dist/agentic/guides/modules/search.md +4 -4
- package/dist/agentic/guides/modules/security.md +3 -3
- package/dist/agentic/guides/modules/shipping_carriers.md +2 -2
- package/dist/agentic/guides/modules/sso.md +2 -2
- package/dist/agentic/guides/modules/staff.md +7 -4
- package/dist/agentic/guides/modules/storage_s3.md +2 -2
- package/dist/agentic/guides/modules/sync_akeneo.md +4 -4
- package/dist/agentic/guides/modules/sync_excel.md +2 -2
- package/dist/agentic/guides/modules/system_status_overlays.md +2 -2
- package/dist/agentic/guides/modules/translations.md +2 -2
- package/dist/agentic/guides/modules/webhooks.md +2 -2
- package/dist/agentic/guides/modules/wms.md +31 -4
- package/dist/agentic/guides/modules/workflows.md +2 -2
- package/dist/agentic/guides/reference-module-facts.json +8335 -0
- package/dist/agentic/guides/reference-modules/example.md +489 -0
- package/dist/agentic/guides/spec-delivery.md +34 -0
- package/dist/agentic/guides/testing-debugging.md +2 -1
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +3 -2
- package/dist/agentic/guides/upstream/manifest.json +2 -2
- package/dist/agentic/shared/AGENTS.md.template +10 -14
- package/dist/agentic/shared/ai/harness/README.md +4 -4
- package/dist/agentic/shared/ai/harness/RELEASE.md +4 -4
- package/dist/agentic/shared/ai/harness/cases.json +11350 -5088
- package/dist/agentic/shared/ai/harness/cases.schema.json +70 -7
- package/dist/agentic/shared/ai/harness/design-system-inventory.json +6697 -0
- package/dist/agentic/shared/ai/harness/fixtures/index.json +3 -1
- package/dist/agentic/shared/ai/harness/fixtures/seeds.json +4 -0
- package/dist/agentic/shared/ai/harness/knowledge-change.schema.json +228 -0
- package/dist/agentic/shared/ai/harness/release-matrix.json +9 -4
- package/dist/agentic/shared/ai/harness/result.schema.json +60 -0
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +10 -0
- package/dist/agentic/shared/ai/harness/source-link-inventory.json +3231 -0
- package/dist/agentic/shared/ai/harness/validators.json +8 -4
- package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +5 -2
- package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +3 -0
- package/dist/agentic/shared/ai/harness/writable-spec-oracles.mjs +879 -0
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.7-to-0.7.0/SKILL.md +102 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +15 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +6 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +4 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +2 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +2 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +3 -1
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +2 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +2 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +3 -3
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +1 -1
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/knowledge-change.md +133 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +11 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +1 -1
- package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +2 -2
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +14 -1
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +2 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +19 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +1 -4
- package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +24 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +3 -1
- package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +13 -0
- package/dist/agentic/shared/ai/skills/tiers.json +2 -1
- package/dist/agentic/shared/ai/specs/2026-08-06-reference-module-activation.md +248 -0
- package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +39 -2
- package/dist/agentic/shared/scripts/design-source-contract.mjs +108 -0
- package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +935 -28
- package/dist/agentic/shared/scripts/framework-context.mjs +4 -1
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +1 -1
- package/dist/agentic/shared/scripts/validate-knowledge-change.mjs +1511 -0
- package/dist/lib/__integration__/TC-INT-008.spec.js +1 -0
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-setup.js +9 -1
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/module-extension-facts.js +93 -26
- package/dist/lib/generators/module-extension-facts.js.map +3 -3
- package/dist/lib/generators/module-facts-discovery.js +23 -0
- package/dist/lib/generators/module-facts-discovery.js.map +2 -2
- package/dist/lib/generators/module-facts.js +969 -41
- package/dist/lib/generators/module-facts.js.map +2 -2
- package/dist/lib/generators/module-override-targets.js +35 -11
- package/dist/lib/generators/module-override-targets.js.map +2 -2
- package/dist/lib/generators/module-registry.js +105 -2
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/resolver.js +5 -0
- package/dist/lib/resolver.js.map +2 -2
- package/dist/lib/testing/integration-discovery.js +34 -0
- package/dist/lib/testing/integration-discovery.js.map +2 -2
- package/dist/lib/testing/integration.js +0 -2
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +4 -4
- package/dist/mercato.js.map +2 -2
- package/package.json +6 -6
- package/src/lib/__integration__/TC-INT-008.spec.ts +4 -2
- package/src/lib/__tests__/resolve-environment.test.ts +18 -0
- package/src/lib/agentic-setup.ts +10 -2
- package/src/lib/generators/__tests__/helpers/override-target-diagnostic-fixtures.ts +150 -0
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +290 -0
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +72 -7
- package/src/lib/generators/__tests__/module-facts.computed-di-token.test.ts +88 -0
- package/src/lib/generators/__tests__/module-facts.example-fact-coverage.test.ts +502 -0
- package/src/lib/generators/__tests__/module-facts.local-reference.test.ts +414 -0
- package/src/lib/generators/__tests__/module-facts.search-entity-id.test.ts +151 -0
- package/src/lib/generators/__tests__/module-facts.source-links.test.ts +42 -1
- package/src/lib/generators/__tests__/module-override-targets.diagnostic-wiring.test.ts +92 -0
- package/src/lib/generators/__tests__/module-override-targets.test.ts +24 -0
- package/src/lib/generators/__tests__/module-override-targets.unknown-mode.test.ts +117 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +60 -0
- package/src/lib/generators/module-extension-facts.ts +181 -25
- package/src/lib/generators/module-facts-discovery.ts +46 -0
- package/src/lib/generators/module-facts.ts +1330 -86
- package/src/lib/generators/module-override-targets.ts +70 -26
- package/src/lib/generators/module-registry.ts +135 -2
- package/src/lib/resolver.ts +6 -1
- package/src/lib/testing/__tests__/integration-discovery.test.ts +35 -0
- package/src/lib/testing/integration-discovery.ts +50 -0
- package/src/lib/testing/integration.ts +0 -2
- package/src/mercato.ts +3 -3
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import ts from "typescript-js";
|
|
5
|
+
import {
|
|
6
|
+
COMPONENT_OVERRIDE_MODES,
|
|
7
|
+
CRUD_FORM_EXTENSION_SURFACE_KEYS,
|
|
8
|
+
CRUD_FORM_LIFECYCLE_PHASES,
|
|
9
|
+
CRUD_FORM_OPERATIONS,
|
|
10
|
+
DATA_TABLE_EXTENSION_SURFACE_KEYS,
|
|
11
|
+
EXTENSION_HOST_ACTIVATIONS,
|
|
12
|
+
EXTENSION_HOST_CAPABILITIES,
|
|
13
|
+
EXTENSION_HOST_FAMILIES,
|
|
14
|
+
MODULE_EXTENSION_ACTIVATION_KINDS,
|
|
15
|
+
MODULE_EXTENSION_CONTRIBUTION_KINDS,
|
|
16
|
+
MODULE_EXTENSION_HOST_RESOLUTIONS,
|
|
17
|
+
MODULE_EXTENSION_RESOLUTIONS,
|
|
18
|
+
MODULE_EXTENSION_TARGET_KINDS,
|
|
19
|
+
MODULE_EXTENSION_TARGET_RESOLUTIONS,
|
|
20
|
+
MODULE_EXTENSION_UNRESOLVED_REASONS,
|
|
21
|
+
MODULE_SPECIALIZED_REGISTRIES
|
|
22
|
+
} from "@open-mercato/shared/modules/widgets/extension-points";
|
|
4
23
|
import { toSnake } from "../utils.js";
|
|
5
24
|
import { extractCommandIdsFromSource } from "./module-registry.js";
|
|
6
25
|
import { MODULE_CODE_EXTENSIONS } from "./scanner.js";
|
|
@@ -16,9 +35,55 @@ import {
|
|
|
16
35
|
withModuleExtensionFactExtractionCache
|
|
17
36
|
} from "./module-extension-facts.js";
|
|
18
37
|
import {
|
|
38
|
+
ALL_OVERRIDE_DOMAINS,
|
|
39
|
+
MODULE_OVERRIDE_MODES,
|
|
40
|
+
MODULE_OVERRIDE_TARGET_DIAGNOSTIC_CODES,
|
|
41
|
+
MODULE_OVERRIDE_TARGET_NOTES,
|
|
19
42
|
collectModuleOverrideTargets
|
|
20
43
|
} from "./module-override-targets.js";
|
|
21
44
|
import { buildFactSourceLookup } from "./module-fact-sources.js";
|
|
45
|
+
import { appendLocalReferenceModuleSource } from "./module-facts-discovery.js";
|
|
46
|
+
const MODULE_FACT_SOURCE_KINDS = [
|
|
47
|
+
"module-metadata",
|
|
48
|
+
"entity",
|
|
49
|
+
"event",
|
|
50
|
+
"acl-feature",
|
|
51
|
+
"api-route",
|
|
52
|
+
"di-registration",
|
|
53
|
+
"search",
|
|
54
|
+
"vector",
|
|
55
|
+
"notification",
|
|
56
|
+
"cli-command",
|
|
57
|
+
"backend-page",
|
|
58
|
+
"frontend-page",
|
|
59
|
+
"ai-tool",
|
|
60
|
+
"ai-agent",
|
|
61
|
+
"ai-extension",
|
|
62
|
+
"command",
|
|
63
|
+
"subscriber",
|
|
64
|
+
"worker",
|
|
65
|
+
"page-middleware",
|
|
66
|
+
"setup",
|
|
67
|
+
"encryption",
|
|
68
|
+
"custom-entity",
|
|
69
|
+
"integration",
|
|
70
|
+
"generator-plugin",
|
|
71
|
+
"extension-host",
|
|
72
|
+
"extension-contribution"
|
|
73
|
+
];
|
|
74
|
+
const MODULE_OWNED_CONTRACT_KINDS = [
|
|
75
|
+
"module-metadata",
|
|
76
|
+
"command",
|
|
77
|
+
"worker",
|
|
78
|
+
"page-middleware",
|
|
79
|
+
"setup",
|
|
80
|
+
"encryption",
|
|
81
|
+
"di-registration",
|
|
82
|
+
"custom-entity",
|
|
83
|
+
"ai-extension",
|
|
84
|
+
"generator-plugin"
|
|
85
|
+
];
|
|
86
|
+
const MODULE_FACT_DIAGNOSTIC_CODES = ["duplicate-source", "unresolved-static-contract"];
|
|
22
87
|
function readSourceFile(filePath) {
|
|
23
88
|
if (!fs.existsSync(filePath)) return null;
|
|
24
89
|
const source = fs.readFileSync(filePath, "utf8");
|
|
@@ -79,42 +144,45 @@ function classHasUpdatedAtColumn(node) {
|
|
|
79
144
|
}
|
|
80
145
|
return false;
|
|
81
146
|
}
|
|
147
|
+
function readStaticAccessPath(candidate) {
|
|
148
|
+
const access = unwrapExpression(candidate);
|
|
149
|
+
if (ts.isIdentifier(access)) return [access.text];
|
|
150
|
+
if (ts.isPropertyAccessExpression(access)) {
|
|
151
|
+
const parent = readStaticAccessPath(access.expression);
|
|
152
|
+
return parent ? [...parent, access.name.text] : null;
|
|
153
|
+
}
|
|
154
|
+
if (ts.isElementAccessExpression(access) && access.argumentExpression) {
|
|
155
|
+
const parent = readStaticAccessPath(access.expression);
|
|
156
|
+
const key = unwrapExpression(access.argumentExpression);
|
|
157
|
+
return parent && ts.isStringLiteralLike(key) ? [...parent, key.text] : null;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
function resolveEntityIdReference(expression, initializers, visitedIdentifiers = /* @__PURE__ */ new Set()) {
|
|
162
|
+
const current = unwrapExpression(expression);
|
|
163
|
+
if (ts.isStringLiteralLike(current)) return current.text;
|
|
164
|
+
const accessPath = readStaticAccessPath(current);
|
|
165
|
+
if (accessPath?.length === 3 && accessPath[0] === "E") {
|
|
166
|
+
return `${accessPath[1]}:${accessPath[2]}`;
|
|
167
|
+
}
|
|
168
|
+
if (initializers && ts.isIdentifier(current) && !visitedIdentifiers.has(current.text)) {
|
|
169
|
+
visitedIdentifiers.add(current.text);
|
|
170
|
+
const declaration = initializers.get(current.text);
|
|
171
|
+
if (declaration) return resolveEntityIdReference(declaration, initializers, visitedIdentifiers);
|
|
172
|
+
}
|
|
173
|
+
return void 0;
|
|
174
|
+
}
|
|
82
175
|
function collectCustomFieldEntityIds(ceFilePath) {
|
|
83
176
|
const result = /* @__PURE__ */ new Set();
|
|
84
177
|
if (!ceFilePath) return result;
|
|
85
178
|
const sourceFile = readSourceFile(ceFilePath);
|
|
86
179
|
if (!sourceFile) return result;
|
|
87
|
-
const readEntityId = (expression) => {
|
|
88
|
-
const current = unwrapExpression(expression);
|
|
89
|
-
if (ts.isStringLiteralLike(current)) {
|
|
90
|
-
return current.text.includes(":") ? current.text : void 0;
|
|
91
|
-
}
|
|
92
|
-
const readAccessPath = (candidate) => {
|
|
93
|
-
const access = unwrapExpression(candidate);
|
|
94
|
-
if (ts.isIdentifier(access)) return [access.text];
|
|
95
|
-
if (ts.isPropertyAccessExpression(access)) {
|
|
96
|
-
const parent = readAccessPath(access.expression);
|
|
97
|
-
return parent ? [...parent, access.name.text] : null;
|
|
98
|
-
}
|
|
99
|
-
if (ts.isElementAccessExpression(access) && access.argumentExpression) {
|
|
100
|
-
const parent = readAccessPath(access.expression);
|
|
101
|
-
const key = unwrapExpression(access.argumentExpression);
|
|
102
|
-
return parent && ts.isStringLiteralLike(key) ? [...parent, key.text] : null;
|
|
103
|
-
}
|
|
104
|
-
return null;
|
|
105
|
-
};
|
|
106
|
-
const accessPath = readAccessPath(current);
|
|
107
|
-
if (accessPath?.length === 3 && accessPath[0] === "E") {
|
|
108
|
-
return `${accessPath[1]}:${accessPath[2]}`;
|
|
109
|
-
}
|
|
110
|
-
return void 0;
|
|
111
|
-
};
|
|
112
180
|
const visit = (node) => {
|
|
113
181
|
if (ts.isObjectLiteralExpression(node)) {
|
|
114
182
|
const initializer = getObjectPropertyInitializer(node, "id");
|
|
115
183
|
if (initializer) {
|
|
116
|
-
const id =
|
|
117
|
-
if (id) result.add(id);
|
|
184
|
+
const id = resolveEntityIdReference(initializer);
|
|
185
|
+
if (id && id.includes(":")) result.add(id);
|
|
118
186
|
}
|
|
119
187
|
}
|
|
120
188
|
node.forEachChild(visit);
|
|
@@ -163,8 +231,29 @@ function getPropertyName(property) {
|
|
|
163
231
|
if (!name) return void 0;
|
|
164
232
|
if (ts.isIdentifier(name)) return name.text;
|
|
165
233
|
if (ts.isStringLiteralLike(name)) return name.text;
|
|
234
|
+
if (ts.isComputedPropertyName(name)) return resolveComputedPropertyKey(name.expression);
|
|
166
235
|
return void 0;
|
|
167
236
|
}
|
|
237
|
+
function resolveComputedPropertyKey(expression) {
|
|
238
|
+
if (ts.isStringLiteralLike(expression)) return expression.text;
|
|
239
|
+
if (ts.isAsExpression(expression) || ts.isSatisfiesExpression(expression)) {
|
|
240
|
+
return resolveComputedPropertyKey(expression.expression);
|
|
241
|
+
}
|
|
242
|
+
if (ts.isParenthesizedExpression(expression)) return resolveComputedPropertyKey(expression.expression);
|
|
243
|
+
if (!ts.isIdentifier(expression)) return void 0;
|
|
244
|
+
const sourceFile = expression.getSourceFile();
|
|
245
|
+
if (!sourceFile) return void 0;
|
|
246
|
+
let resolved;
|
|
247
|
+
const visit = (node) => {
|
|
248
|
+
if (resolved) return;
|
|
249
|
+
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.name.text === expression.text) {
|
|
250
|
+
if (node.initializer) resolved = resolveComputedPropertyKey(node.initializer);
|
|
251
|
+
}
|
|
252
|
+
node.forEachChild(visit);
|
|
253
|
+
};
|
|
254
|
+
sourceFile.forEachChild(visit);
|
|
255
|
+
return resolved;
|
|
256
|
+
}
|
|
168
257
|
function getObjectPropertyInitializer(objectLiteral, propertyName) {
|
|
169
258
|
for (const property of objectLiteral.properties) {
|
|
170
259
|
if (!ts.isPropertyAssignment(property)) continue;
|
|
@@ -454,15 +543,25 @@ function extractSearchEntities(searchFilePath, warnings) {
|
|
|
454
543
|
warnings.push(`[module-facts] searchConfig.entities is not an array literal: ${searchFilePath}`);
|
|
455
544
|
return [];
|
|
456
545
|
}
|
|
546
|
+
const initializers = buildVariableInitializerMap(sourceFile);
|
|
457
547
|
const entityIds = [];
|
|
458
548
|
const seen = /* @__PURE__ */ new Set();
|
|
459
549
|
for (const element of entitiesArray.elements) {
|
|
460
550
|
if (!ts.isObjectLiteralExpression(element)) continue;
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
551
|
+
const initializer = getObjectPropertyInitializer(element, "entityId");
|
|
552
|
+
const location = `${searchFilePath}:${nodeLine(sourceFile, element)}`;
|
|
553
|
+
if (!initializer) {
|
|
554
|
+
warnings.push(`[module-facts] searchConfig entity declares no entityId: ${location}`);
|
|
555
|
+
continue;
|
|
465
556
|
}
|
|
557
|
+
const entityId = resolveEntityIdReference(initializer, initializers);
|
|
558
|
+
if (!entityId) {
|
|
559
|
+
warnings.push(`[module-facts] searchConfig entityId is not statically resolvable: ${location}`);
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
if (seen.has(entityId)) continue;
|
|
563
|
+
seen.add(entityId);
|
|
564
|
+
entityIds.push(entityId);
|
|
466
565
|
}
|
|
467
566
|
return entityIds;
|
|
468
567
|
}
|
|
@@ -538,6 +637,15 @@ function listSourceFilesRecursive(directory) {
|
|
|
538
637
|
function toPortableSourceRoot(moduleId, sourcePackage) {
|
|
539
638
|
return path.posix.join("node_modules", sourcePackage ?? "@open-mercato/core", "src", "modules", moduleId);
|
|
540
639
|
}
|
|
640
|
+
function assertPortableSourceRoot(moduleId, portableSourceRoot) {
|
|
641
|
+
const invalid = portableSourceRoot.length === 0 || path.posix.isAbsolute(portableSourceRoot) || /^[A-Za-z]:/.test(portableSourceRoot) || portableSourceRoot.includes("\\") || portableSourceRoot.split("/").includes("..");
|
|
642
|
+
if (invalid) {
|
|
643
|
+
throw new Error(
|
|
644
|
+
`[module-facts] portableSourceRoot for module "${moduleId}" must be a relative POSIX app path, received "${portableSourceRoot}"`
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
return portableSourceRoot;
|
|
648
|
+
}
|
|
541
649
|
function toPortableSourcePath(moduleRoot, sourceRoot, filePath) {
|
|
542
650
|
const relativePath = path.relative(moduleRoot, filePath).split(path.sep).join("/");
|
|
543
651
|
return path.posix.join(sourceRoot, relativePath);
|
|
@@ -973,6 +1081,34 @@ function readResolvedStringProperty(objectLiteral, propertyName, initializers) {
|
|
|
973
1081
|
}
|
|
974
1082
|
return void 0;
|
|
975
1083
|
}
|
|
1084
|
+
function readImportedStringIdentifier(sourceFile, sourcePath, identifier) {
|
|
1085
|
+
for (const statement of sourceFile.statements) {
|
|
1086
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteralLike(statement.moduleSpecifier)) continue;
|
|
1087
|
+
const importClause = statement.importClause;
|
|
1088
|
+
const bindings = importClause?.namedBindings;
|
|
1089
|
+
if (!bindings || !ts.isNamedImports(bindings)) continue;
|
|
1090
|
+
const imported = bindings.elements.find((element) => element.name.text === identifier);
|
|
1091
|
+
if (!imported) continue;
|
|
1092
|
+
const request = statement.moduleSpecifier.text;
|
|
1093
|
+
if (!request.startsWith(".")) return void 0;
|
|
1094
|
+
const basePath = path.resolve(path.dirname(sourcePath), request);
|
|
1095
|
+
const candidates = [
|
|
1096
|
+
`${basePath}.ts`,
|
|
1097
|
+
`${basePath}.tsx`,
|
|
1098
|
+
path.join(basePath, "index.ts"),
|
|
1099
|
+
path.join(basePath, "index.tsx")
|
|
1100
|
+
];
|
|
1101
|
+
const importedPath = candidates.find((candidate) => fs.existsSync(candidate));
|
|
1102
|
+
if (!importedPath) return void 0;
|
|
1103
|
+
const importedSource = readSourceFile(importedPath);
|
|
1104
|
+
if (!importedSource) return void 0;
|
|
1105
|
+
const exportName = imported.propertyName?.text ?? imported.name.text;
|
|
1106
|
+
const declaration = importedSource.statements.filter(ts.isVariableStatement).flatMap((variable) => [...variable.declarationList.declarations]).find((candidate) => ts.isIdentifier(candidate.name) && candidate.name.text === exportName);
|
|
1107
|
+
const initializer = declaration?.initializer ? unwrapExpression(declaration.initializer) : null;
|
|
1108
|
+
return initializer && ts.isStringLiteralLike(initializer) ? initializer.text : void 0;
|
|
1109
|
+
}
|
|
1110
|
+
return void 0;
|
|
1111
|
+
}
|
|
976
1112
|
function extractWorkerContracts(moduleId, moduleRoot, sourceRoot) {
|
|
977
1113
|
const workersRoot = path.join(moduleRoot, "workers");
|
|
978
1114
|
if (!fs.existsSync(workersRoot)) return { facts: [], unresolved: [] };
|
|
@@ -988,7 +1124,8 @@ function extractWorkerContracts(moduleId, moduleRoot, sourceRoot) {
|
|
|
988
1124
|
const initializers = buildVariableInitializerMap(sourceFile);
|
|
989
1125
|
const workerId = readResolvedStringProperty(metadata, "id", initializers) ?? deriveWorkerId(moduleId, workersRoot, filePath);
|
|
990
1126
|
const hasQueueProperty = getObjectPropertyInitializer(metadata, "queue") !== void 0;
|
|
991
|
-
const
|
|
1127
|
+
const queueInitializer = getObjectPropertyInitializer(metadata, "queue");
|
|
1128
|
+
const queue = readResolvedStringProperty(metadata, "queue", initializers) ?? (queueInitializer && ts.isIdentifier(unwrapExpression(queueInitializer)) ? readImportedStringIdentifier(sourceFile, filePath, unwrapExpression(queueInitializer).text) : void 0);
|
|
992
1129
|
if (!hasQueueProperty) {
|
|
993
1130
|
unresolved.push({ code: "unresolved-static-contract", kind: "worker", id: workerId, source });
|
|
994
1131
|
continue;
|
|
@@ -1318,7 +1455,7 @@ function extractModuleFacts(options) {
|
|
|
1318
1455
|
if (!moduleRoot) {
|
|
1319
1456
|
throw new Error(`[internal] extractModuleFacts requires moduleRoot or coreSrcRoot for module "${moduleId}"`);
|
|
1320
1457
|
}
|
|
1321
|
-
const sourceRoot = toPortableSourceRoot(moduleId, sourcePackage);
|
|
1458
|
+
const sourceRoot = options.portableSourceRoot ? assertPortableSourceRoot(moduleId, options.portableSourceRoot) : toPortableSourceRoot(moduleId, sourcePackage);
|
|
1322
1459
|
const entitiesFilePath = resolveConventionFile(path.join(moduleRoot, "data"), "entities") ?? resolveConventionFile(path.join(moduleRoot, "db"), "entities") ?? resolveConventionFile(path.join(moduleRoot, "data"), "schema");
|
|
1323
1460
|
const ceFilePath = resolveConventionFile(moduleRoot, "ce");
|
|
1324
1461
|
const eventsFilePath = resolveConventionFile(moduleRoot, "events");
|
|
@@ -1370,7 +1507,8 @@ function extractModuleFacts(options) {
|
|
|
1370
1507
|
searchEntities,
|
|
1371
1508
|
notifications,
|
|
1372
1509
|
aiTools,
|
|
1373
|
-
aiAgents
|
|
1510
|
+
aiAgents,
|
|
1511
|
+
factsContractVersion: options.factsContractVersion ?? 2
|
|
1374
1512
|
});
|
|
1375
1513
|
const indexSourcePath = portableOf(indexFilePath);
|
|
1376
1514
|
const diSourcePath = portableOf(diFilePath);
|
|
@@ -1556,6 +1694,7 @@ function extractModuleFacts(options) {
|
|
|
1556
1694
|
sourcePackage,
|
|
1557
1695
|
sourceVersion,
|
|
1558
1696
|
sourceRoot,
|
|
1697
|
+
...options.sourceKind === "local-reference" ? { sourceKind: options.sourceKind } : {},
|
|
1559
1698
|
entities,
|
|
1560
1699
|
events,
|
|
1561
1700
|
aclFeatures,
|
|
@@ -1630,12 +1769,17 @@ ${EMPTY_SECTION_MARKER}`;
|
|
|
1630
1769
|
const rows = values.map((value) => `| ${value} | ${renderLookedUpSource(lookup, kind, value)} |`);
|
|
1631
1770
|
return [heading, "", `| ${idColumnLabel} | Source |`, "|---|---|", ...rows].join("\n");
|
|
1632
1771
|
}
|
|
1772
|
+
function isExactSourceFilePath(sourcePath) {
|
|
1773
|
+
return MODULE_CODE_EXTENSIONS.some((extension) => sourcePath.endsWith(extension));
|
|
1774
|
+
}
|
|
1633
1775
|
function renderSourceLink(sourcePath) {
|
|
1776
|
+
if (!isExactSourceFilePath(sourcePath)) return sourcePath;
|
|
1634
1777
|
return `[${sourcePath}](../../../${sourcePath})`;
|
|
1635
1778
|
}
|
|
1636
1779
|
function renderSourceRefLink(source) {
|
|
1637
1780
|
const anchor = source.line ? `#L${source.line}` : "";
|
|
1638
1781
|
const label = source.line ? `${source.sourcePath}:${source.line}` : source.sourcePath;
|
|
1782
|
+
if (!isExactSourceFilePath(source.sourcePath)) return label;
|
|
1639
1783
|
return `[${label}](../../../${source.sourcePath}${anchor})`;
|
|
1640
1784
|
}
|
|
1641
1785
|
function renderLookedUpSource(lookup, kind, id) {
|
|
@@ -1865,13 +2009,24 @@ ${EMPTY_SECTION_MARKER}`;
|
|
|
1865
2009
|
});
|
|
1866
2010
|
return ["## Exact override targets", "", header, divider, ...rows].join("\n");
|
|
1867
2011
|
}
|
|
1868
|
-
function
|
|
2012
|
+
function renderReferenceProjectionHeader(facts, fingerprints) {
|
|
2013
|
+
return [
|
|
2014
|
+
`# ${facts.module} \u2014 module facts (generated reference projection, do not edit)`,
|
|
2015
|
+
`<!-- generated from local reference ${facts.sourceRoot}; source-fingerprint ${fingerprints.sourceFingerprint}; taxonomy-fingerprint ${fingerprints.taxonomyFingerprint} \u2014 R1 staleness stamp -->`,
|
|
2016
|
+
`> Reference projection: \`${facts.module}\` is not selected by the current runtime. Its activations and exact override targets describe behavior only after opt-in in \`src/modules.ts\`.`,
|
|
2017
|
+
`Source root: ${renderSourceLink(facts.sourceRoot)}`
|
|
2018
|
+
];
|
|
2019
|
+
}
|
|
2020
|
+
function renderModuleFactsMarkdown(facts, referenceProjection) {
|
|
1869
2021
|
const extensionSurfaces = facts.extensionSurfaces ?? { hosts: [], contributions: [], unresolved: [] };
|
|
1870
2022
|
const lookup = buildFactSourceLookup(facts);
|
|
1871
|
-
const
|
|
2023
|
+
const header = facts.sourceKind === "local-reference" && referenceProjection ? renderReferenceProjectionHeader(facts, referenceProjection) : [
|
|
1872
2024
|
`# ${facts.module} \u2014 module facts (generated, do not edit)`,
|
|
1873
2025
|
renderVersionStamp(facts.coreVersion, facts.sourcePackage, facts.sourceVersion),
|
|
1874
|
-
`Source root: ${renderSourceLink(facts.sourceRoot)}
|
|
2026
|
+
`Source root: ${renderSourceLink(facts.sourceRoot)}`
|
|
2027
|
+
];
|
|
2028
|
+
const sections = [
|
|
2029
|
+
...header,
|
|
1875
2030
|
"",
|
|
1876
2031
|
renderEntitiesSection(facts.entities, lookup),
|
|
1877
2032
|
"",
|
|
@@ -1946,6 +2101,7 @@ function toModuleFactsJsonEntry(facts) {
|
|
|
1946
2101
|
sourcePackage: facts.sourcePackage,
|
|
1947
2102
|
sourceVersion: facts.sourceVersion,
|
|
1948
2103
|
sourceRoot: facts.sourceRoot,
|
|
2104
|
+
...facts.sourceKind === "local-reference" ? { sourceKind: facts.sourceKind } : {},
|
|
1949
2105
|
entities: facts.entities,
|
|
1950
2106
|
events: facts.events.map((event) => ({
|
|
1951
2107
|
id: event.id,
|
|
@@ -1985,10 +2141,169 @@ function renderModuleFactsJson(factsByModule) {
|
|
|
1985
2141
|
return `${JSON.stringify(buildModuleFactsJsonObject(factsByModule), null, 2)}
|
|
1986
2142
|
`;
|
|
1987
2143
|
}
|
|
2144
|
+
function assertPackageModuleFactsOnly(factsByModule) {
|
|
2145
|
+
const offenders = Object.values(factsByModule).filter((facts) => facts.sourceKind === "local-reference" || !facts.sourceRoot.startsWith("node_modules/")).map((facts) => `${facts.module} (${facts.sourceRoot})`).sort((left, right) => left.localeCompare(right));
|
|
2146
|
+
if (offenders.length > 0) {
|
|
2147
|
+
throw new Error(
|
|
2148
|
+
`[module-facts] normal package output must not contain app-local modules: ${offenders.join(", ")}`
|
|
2149
|
+
);
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
function sha256Hex(value) {
|
|
2153
|
+
return createHash("sha256").update(value).digest("hex");
|
|
2154
|
+
}
|
|
2155
|
+
function canonicalizeFingerprintValue(value, propertyName) {
|
|
2156
|
+
if (Array.isArray(value)) {
|
|
2157
|
+
const items = value.map((item) => {
|
|
2158
|
+
const canonical = canonicalizeFingerprintValue(item);
|
|
2159
|
+
return { canonical, text: JSON.stringify(canonical) ?? "" };
|
|
2160
|
+
});
|
|
2161
|
+
if (propertyName === "path") return items.map((item) => item.canonical);
|
|
2162
|
+
return items.sort((left, right) => left.text < right.text ? -1 : left.text > right.text ? 1 : 0).map((item) => item.canonical);
|
|
2163
|
+
}
|
|
2164
|
+
if (value !== null && typeof value === "object") {
|
|
2165
|
+
const record = value;
|
|
2166
|
+
const result = {};
|
|
2167
|
+
for (const key of Object.keys(record).sort((left, right) => left < right ? -1 : left > right ? 1 : 0)) {
|
|
2168
|
+
if (record[key] === void 0) continue;
|
|
2169
|
+
result[key] = canonicalizeFingerprintValue(record[key], key);
|
|
2170
|
+
}
|
|
2171
|
+
return result;
|
|
2172
|
+
}
|
|
2173
|
+
return value;
|
|
2174
|
+
}
|
|
2175
|
+
function canonicalFingerprintJson(value) {
|
|
2176
|
+
return JSON.stringify(canonicalizeFingerprintValue(value));
|
|
2177
|
+
}
|
|
2178
|
+
const REFERENCE_FINGERPRINT_SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set(["__tests__", "__integration__", "node_modules"]);
|
|
2179
|
+
function computeModuleSourceFingerprint(moduleRoot, portableSourceRoot) {
|
|
2180
|
+
assertPortableSourceRoot(path.basename(portableSourceRoot), portableSourceRoot);
|
|
2181
|
+
const records = [];
|
|
2182
|
+
const walk = (directory) => {
|
|
2183
|
+
const entries = fs.readdirSync(directory, { withFileTypes: true });
|
|
2184
|
+
for (const entry of entries) {
|
|
2185
|
+
const fullPath = path.join(directory, entry.name);
|
|
2186
|
+
if (entry.isDirectory()) {
|
|
2187
|
+
if (REFERENCE_FINGERPRINT_SKIPPED_DIRECTORIES.has(entry.name)) continue;
|
|
2188
|
+
walk(fullPath);
|
|
2189
|
+
continue;
|
|
2190
|
+
}
|
|
2191
|
+
if (!entry.isFile()) continue;
|
|
2192
|
+
records.push({
|
|
2193
|
+
path: toPortableSourcePath(moduleRoot, portableSourceRoot, fullPath),
|
|
2194
|
+
sha256: sha256Hex(fs.readFileSync(fullPath))
|
|
2195
|
+
});
|
|
2196
|
+
}
|
|
2197
|
+
};
|
|
2198
|
+
walk(moduleRoot);
|
|
2199
|
+
records.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
|
|
2200
|
+
return sha256Hex(canonicalFingerprintJson(records));
|
|
2201
|
+
}
|
|
2202
|
+
const TAXONOMY_EXCLUDED_SECTIONS = /* @__PURE__ */ new Set([
|
|
2203
|
+
"title",
|
|
2204
|
+
"description",
|
|
2205
|
+
"coreVersion",
|
|
2206
|
+
"sourcePackage",
|
|
2207
|
+
"sourceVersion",
|
|
2208
|
+
"sourceRoot",
|
|
2209
|
+
"sourceKind"
|
|
2210
|
+
]);
|
|
2211
|
+
function collectTaxonomyRecords(setName, value, records) {
|
|
2212
|
+
if (value === void 0) return;
|
|
2213
|
+
if (Array.isArray(value)) {
|
|
2214
|
+
for (const item of value) records.push({ setName, value: canonicalizeFingerprintValue(item) });
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
if (value !== null && typeof value === "object") {
|
|
2218
|
+
for (const [key, child] of Object.entries(value)) {
|
|
2219
|
+
collectTaxonomyRecords(`${setName}.${key}`, child, records);
|
|
2220
|
+
}
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2223
|
+
records.push({ setName, value });
|
|
2224
|
+
}
|
|
2225
|
+
function computeModuleTaxonomyFingerprint(entry) {
|
|
2226
|
+
const records = [];
|
|
2227
|
+
for (const [setName, value] of Object.entries(entry)) {
|
|
2228
|
+
if (TAXONOMY_EXCLUDED_SECTIONS.has(setName)) continue;
|
|
2229
|
+
collectTaxonomyRecords(setName, value, records);
|
|
2230
|
+
}
|
|
2231
|
+
const decorated = records.map((record) => ({ record, text: JSON.stringify(record.value) ?? "" })).sort(
|
|
2232
|
+
(left, right) => left.record.setName < right.record.setName ? -1 : left.record.setName > right.record.setName ? 1 : left.text < right.text ? -1 : left.text > right.text ? 1 : 0
|
|
2233
|
+
);
|
|
2234
|
+
return sha256Hex(JSON.stringify(decorated.map((item) => item.record)));
|
|
2235
|
+
}
|
|
2236
|
+
function renderReferenceModuleFactsJson(bundle) {
|
|
2237
|
+
const ordered = {};
|
|
2238
|
+
for (const moduleId of Object.keys(bundle).sort((left, right) => left < right ? -1 : left > right ? 1 : 0)) {
|
|
2239
|
+
ordered[moduleId] = bundle[moduleId];
|
|
2240
|
+
}
|
|
2241
|
+
return `${JSON.stringify(ordered, null, 2)}
|
|
2242
|
+
`;
|
|
2243
|
+
}
|
|
2244
|
+
function extractLocalReferenceModuleFacts(options) {
|
|
2245
|
+
const { reference } = options;
|
|
2246
|
+
if (reference.sourceKind !== "local-reference") {
|
|
2247
|
+
throw new Error(
|
|
2248
|
+
`[module-facts] reference source "${reference.moduleId}" must declare sourceKind "local-reference"`
|
|
2249
|
+
);
|
|
2250
|
+
}
|
|
2251
|
+
const portableSourceRoot = reference.portableSourceRoot;
|
|
2252
|
+
if (!portableSourceRoot) {
|
|
2253
|
+
throw new Error(`[module-facts] reference source "${reference.moduleId}" must declare portableSourceRoot`);
|
|
2254
|
+
}
|
|
2255
|
+
assertPortableSourceRoot(reference.moduleId, portableSourceRoot);
|
|
2256
|
+
const sources = appendLocalReferenceModuleSource(options.packageSources, reference);
|
|
2257
|
+
const activated = extractAllModuleFacts({
|
|
2258
|
+
sources,
|
|
2259
|
+
registryPath: options.registryPath ?? null,
|
|
2260
|
+
registrySource: options.registrySource ?? null,
|
|
2261
|
+
coreVersion: options.coreVersion ?? null,
|
|
2262
|
+
// The disposable projection collects rather than throws: an app-local module can name
|
|
2263
|
+
// a target whose classification is still missing from the shared extension reader, and
|
|
2264
|
+
// aborting there would delete the whole reference bundle instead of publishing the
|
|
2265
|
+
// exact gap. Normal package output keeps the strict default.
|
|
2266
|
+
unresolvedFirstPartyTargets: "collect"
|
|
2267
|
+
});
|
|
2268
|
+
const facts = activated.factsByModule[reference.moduleId];
|
|
2269
|
+
if (!facts) {
|
|
2270
|
+
throw new Error(`[module-facts] reference module "${reference.moduleId}" produced no facts`);
|
|
2271
|
+
}
|
|
2272
|
+
if (facts.sourceRoot !== portableSourceRoot) {
|
|
2273
|
+
throw new Error(
|
|
2274
|
+
`[module-facts] reference module "${reference.moduleId}" emitted non-portable source root "${facts.sourceRoot}"`
|
|
2275
|
+
);
|
|
2276
|
+
}
|
|
2277
|
+
const jsonEntry = toModuleFactsJsonEntry(facts);
|
|
2278
|
+
const fingerprints = {
|
|
2279
|
+
sourceFingerprint: computeModuleSourceFingerprint(reference.moduleRoot, portableSourceRoot),
|
|
2280
|
+
taxonomyFingerprint: computeModuleTaxonomyFingerprint(jsonEntry)
|
|
2281
|
+
};
|
|
2282
|
+
return {
|
|
2283
|
+
entry: {
|
|
2284
|
+
moduleId: reference.moduleId,
|
|
2285
|
+
projectionKind: "activated-reference",
|
|
2286
|
+
sourceKind: "local-reference",
|
|
2287
|
+
runtimeSelected: false,
|
|
2288
|
+
...fingerprints,
|
|
2289
|
+
factCoverage: activated.factCoverage ?? buildModuleFactCoverageLedger(),
|
|
2290
|
+
facts: jsonEntry
|
|
2291
|
+
},
|
|
2292
|
+
markdown: renderModuleFactsMarkdown(facts, fingerprints),
|
|
2293
|
+
warnings: activated.warnings,
|
|
2294
|
+
unresolvedTargets: activated.unresolvedFirstPartyTargets ?? []
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
function collectUnresolvedFirstPartyTargets(surfacesByModule) {
|
|
2298
|
+
return Object.entries(surfacesByModule).flatMap(
|
|
2299
|
+
([moduleId, surface]) => surface.unresolved.filter((entry) => entry.reason === "unresolved-first-party-target").map((entry) => `${moduleId}:${entry.key}`)
|
|
2300
|
+
).sort((left, right) => left.localeCompare(right));
|
|
2301
|
+
}
|
|
1988
2302
|
function extractAllModuleFacts(options) {
|
|
1989
2303
|
return withModuleExtensionFactExtractionCache(() => extractAllModuleFactsWithCache(options));
|
|
1990
2304
|
}
|
|
1991
2305
|
function extractAllModuleFactsWithCache(options) {
|
|
2306
|
+
const factCoverage = buildModuleFactCoverageLedger();
|
|
1992
2307
|
const sources = options.sources ? [...options.sources] : options.coreSrcRoot ? (options.moduleIds ?? []).map((moduleId) => ({
|
|
1993
2308
|
moduleId,
|
|
1994
2309
|
moduleRoot: path.join(options.coreSrcRoot, moduleId)
|
|
@@ -2004,7 +2319,10 @@ function extractAllModuleFactsWithCache(options) {
|
|
|
2004
2319
|
sourcePackage: source.from ?? null,
|
|
2005
2320
|
sourceVersion: source.packageVersion ?? null,
|
|
2006
2321
|
registryPath: options.registryPath ?? null,
|
|
2007
|
-
registrySource: options.registrySource ?? null
|
|
2322
|
+
registrySource: options.registrySource ?? null,
|
|
2323
|
+
...source.portableSourceRoot ? { portableSourceRoot: source.portableSourceRoot } : {},
|
|
2324
|
+
...source.sourceKind ? { sourceKind: source.sourceKind } : {},
|
|
2325
|
+
factsContractVersion: options.factsContractVersion ?? 2
|
|
2008
2326
|
});
|
|
2009
2327
|
factsByModule[source.moduleId] = facts;
|
|
2010
2328
|
warnings.push(...facts.warnings);
|
|
@@ -2023,9 +2341,11 @@ function extractAllModuleFactsWithCache(options) {
|
|
|
2023
2341
|
...Object.values(factsByModule).flatMap((facts) => facts.apiRoutes.map((route) => route.path)),
|
|
2024
2342
|
...sources.flatMap((source) => extractKnownApiRouteIds(source.moduleId, source.moduleRoot))
|
|
2025
2343
|
]),
|
|
2026
|
-
commandIds: new Set(sources.flatMap((source) => extractKnownCommandIds(source.moduleId, source.moduleRoot)))
|
|
2344
|
+
commandIds: new Set(sources.flatMap((source) => extractKnownCommandIds(source.moduleId, source.moduleRoot))),
|
|
2345
|
+
factsContractVersion: options.factsContractVersion ?? 2
|
|
2027
2346
|
});
|
|
2028
|
-
|
|
2347
|
+
const unresolvedFirstPartyTargets = collectUnresolvedFirstPartyTargets(correlated);
|
|
2348
|
+
if ((options.unresolvedFirstPartyTargets ?? "throw") === "throw") assertNoUnresolvedExtensionTargets(correlated);
|
|
2029
2349
|
const apiRouteOwners = /* @__PURE__ */ new Map();
|
|
2030
2350
|
const commandOwners = /* @__PURE__ */ new Map();
|
|
2031
2351
|
for (const source of [...sources].sort((left, right) => left.moduleId.localeCompare(right.moduleId))) {
|
|
@@ -2057,14 +2377,622 @@ function extractAllModuleFactsWithCache(options) {
|
|
|
2057
2377
|
(entry) => `[module-facts] ${moduleId} ${entry.reason}: ${entry.key} (${entry.source.path})`
|
|
2058
2378
|
));
|
|
2059
2379
|
}
|
|
2060
|
-
return {
|
|
2380
|
+
return {
|
|
2381
|
+
factsByModule,
|
|
2382
|
+
markdownByModule,
|
|
2383
|
+
warnings,
|
|
2384
|
+
frameworkMarkdown: renderFrameworkExtensionPointsMarkdown(),
|
|
2385
|
+
unresolvedFirstPartyTargets,
|
|
2386
|
+
factCoverage
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
const FACT_SOURCE_KIND_COVERAGE = {
|
|
2390
|
+
"module-metadata": { value: "module-metadata", status: "emitted-example", note: "example/index.ts ModuleInfo export" },
|
|
2391
|
+
entity: { value: "entity", status: "emitted-example", note: "example/data/entities.ts ORM entities" },
|
|
2392
|
+
event: { value: "event", status: "emitted-example", note: "example/events.ts typed event definitions" },
|
|
2393
|
+
"acl-feature": { value: "acl-feature", status: "emitted-example", note: "example/acl.ts RBAC features" },
|
|
2394
|
+
"api-route": {
|
|
2395
|
+
value: "api-route",
|
|
2396
|
+
status: "emitted-example",
|
|
2397
|
+
note: "example/api/**/route.ts; route facts are read from the generated module registry, not from module source",
|
|
2398
|
+
requiresGeneratedRegistry: true
|
|
2399
|
+
},
|
|
2400
|
+
"di-registration": { value: "di-registration", status: "emitted-example", note: "example/di.ts Awilix container.register" },
|
|
2401
|
+
search: { value: "search", status: "emitted-example", note: "example/search.ts indexed entity declaration" },
|
|
2402
|
+
vector: {
|
|
2403
|
+
value: "vector",
|
|
2404
|
+
status: "emitted-example",
|
|
2405
|
+
note: "example/vector.ts deterministic Todo vector declaration"
|
|
2406
|
+
},
|
|
2407
|
+
notification: { value: "notification", status: "emitted-example", note: "example/notifications.ts notification types" },
|
|
2408
|
+
"cli-command": { value: "cli-command", status: "emitted-example", note: "example/cli.ts module commands" },
|
|
2409
|
+
"backend-page": { value: "backend-page", status: "emitted-example", note: "example/backend/**/page.tsx admin pages" },
|
|
2410
|
+
"frontend-page": { value: "frontend-page", status: "emitted-example", note: "example/frontend/**/page.tsx portal pages" },
|
|
2411
|
+
"ai-tool": { value: "ai-tool", status: "emitted-example", note: "example/ai-tools.ts defineAiTool declarations" },
|
|
2412
|
+
"ai-agent": { value: "ai-agent", status: "emitted-example", note: "example/ai-agents.ts defineAiAgent declarations" },
|
|
2413
|
+
"ai-extension": { value: "ai-extension", status: "emitted-example", note: "example AI agent/tool override and extension records" },
|
|
2414
|
+
command: { value: "command", status: "emitted-example", note: "example/commands/todos.ts command handlers" },
|
|
2415
|
+
subscriber: { value: "subscriber", status: "emitted-example", note: "example/subscribers/*.ts event subscribers" },
|
|
2416
|
+
worker: { value: "worker", status: "emitted-example", note: "example/workers/*.ts queue workers" },
|
|
2417
|
+
"page-middleware": { value: "page-middleware", status: "emitted-example", note: "example/backend/middleware.ts page guard" },
|
|
2418
|
+
setup: { value: "setup", status: "emitted-example", note: "example/setup.ts tenant setup hooks" },
|
|
2419
|
+
encryption: { value: "encryption", status: "emitted-example", note: "example/encryption.ts field encryption map" },
|
|
2420
|
+
"custom-entity": { value: "custom-entity", status: "emitted-example", note: "example/ce.ts custom entity and field DSL" },
|
|
2421
|
+
integration: { value: "integration", status: "emitted-example", note: "example/lib/mock-*-adapter.ts integration registrations" },
|
|
2422
|
+
"generator-plugin": {
|
|
2423
|
+
value: "generator-plugin",
|
|
2424
|
+
status: "emitted-example",
|
|
2425
|
+
note: "example/generators.ts deterministic reference-index generator plugin"
|
|
2426
|
+
},
|
|
2427
|
+
"extension-host": { value: "extension-host", status: "emitted-example", note: "example/extension-points.ts declared hosts" },
|
|
2428
|
+
"extension-contribution": {
|
|
2429
|
+
value: "extension-contribution",
|
|
2430
|
+
status: "emitted-example",
|
|
2431
|
+
note: "example widget, DataTable, CrudForm, interceptor and enricher contributions"
|
|
2432
|
+
}
|
|
2433
|
+
};
|
|
2434
|
+
const OWNED_CONTRACT_KIND_COVERAGE = {
|
|
2435
|
+
"module-metadata": { value: "module-metadata", status: "emitted-example", note: "ModuleInfo owned contract" },
|
|
2436
|
+
command: { value: "command", status: "emitted-example", note: "example/commands/todos.ts" },
|
|
2437
|
+
worker: { value: "worker", status: "emitted-example", note: "example/workers/*.ts" },
|
|
2438
|
+
"page-middleware": { value: "page-middleware", status: "emitted-example", note: "example/backend/middleware.ts" },
|
|
2439
|
+
setup: { value: "setup", status: "emitted-example", note: "example/setup.ts" },
|
|
2440
|
+
encryption: { value: "encryption", status: "emitted-example", note: "example/encryption.ts" },
|
|
2441
|
+
"di-registration": {
|
|
2442
|
+
value: "di-registration",
|
|
2443
|
+
status: "emitted-example",
|
|
2444
|
+
note: "example/di.ts scoped Todo summary cache service consumed by a route"
|
|
2445
|
+
},
|
|
2446
|
+
"custom-entity": { value: "custom-entity", status: "emitted-example", note: "example/ce.ts" },
|
|
2447
|
+
"ai-extension": { value: "ai-extension", status: "emitted-example", note: "example AI override/extension record" },
|
|
2448
|
+
"generator-plugin": {
|
|
2449
|
+
value: "generator-plugin",
|
|
2450
|
+
status: "emitted-example",
|
|
2451
|
+
note: "example/generators.ts deterministic reference-index generator plugin"
|
|
2452
|
+
}
|
|
2453
|
+
};
|
|
2454
|
+
const OVERRIDE_DOMAIN_COVERAGE = {
|
|
2455
|
+
ai: { value: "ai", status: "emitted-example", note: "ai.agents, ai.tools and ai.extensions targets" },
|
|
2456
|
+
routes: { value: "routes", status: "emitted-example", note: "routes.api and routes.pages targets" },
|
|
2457
|
+
events: { value: "events", status: "emitted-example", note: "events.subscribers targets" },
|
|
2458
|
+
workers: { value: "workers", status: "emitted-example", note: "workers targets" },
|
|
2459
|
+
widgets: { value: "widgets", status: "emitted-example", note: "widgets.injection, .components and .dashboard targets" },
|
|
2460
|
+
notifications: { value: "notifications", status: "emitted-example", note: "notifications.types and notifications.handlers targets" },
|
|
2461
|
+
interceptors: { value: "interceptors", status: "emitted-example", note: "API interceptor targets" },
|
|
2462
|
+
commandInterceptors: { value: "commandInterceptors", status: "emitted-example", note: "command interceptor targets" },
|
|
2463
|
+
enrichers: { value: "enrichers", status: "emitted-example", note: "response enricher targets" },
|
|
2464
|
+
guards: { value: "guards", status: "emitted-example", note: "page-middleware guard targets" },
|
|
2465
|
+
cli: { value: "cli", status: "emitted-example", note: "CLI command targets" },
|
|
2466
|
+
setup: { value: "setup", status: "emitted-example", note: "setup hook and default-role targets" },
|
|
2467
|
+
acl: { value: "acl", status: "emitted-example", note: "acl.features targets" },
|
|
2468
|
+
di: { value: "di", status: "emitted-example", note: "DI token targets" },
|
|
2469
|
+
encryption: { value: "encryption", status: "emitted-example", note: "encryption.maps targets" },
|
|
2470
|
+
nav: {
|
|
2471
|
+
value: "nav",
|
|
2472
|
+
status: "framework-only",
|
|
2473
|
+
note: "nav.groupOrder is an app-level framework setting; no module target is ever emitted for it"
|
|
2474
|
+
}
|
|
2475
|
+
};
|
|
2476
|
+
const OVERRIDE_MODE_COVERAGE = {
|
|
2477
|
+
"disable-replace": {
|
|
2478
|
+
value: "disable-replace",
|
|
2479
|
+
status: "emitted-example",
|
|
2480
|
+
note: "default mode for most example override hosts"
|
|
2481
|
+
},
|
|
2482
|
+
replace: { value: "replace", status: "emitted-example", note: "the setup host replaces wholesale" },
|
|
2483
|
+
additive: { value: "additive", status: "emitted-example", note: "the ai.extensions host merges additively" }
|
|
2484
|
+
};
|
|
2485
|
+
const OVERRIDE_NOTE_COVERAGE = {
|
|
2486
|
+
"safe-metadata-only": {
|
|
2487
|
+
value: "safe-metadata-only",
|
|
2488
|
+
status: "emitted-example",
|
|
2489
|
+
note: "emitted on the metadata-only override target"
|
|
2490
|
+
},
|
|
2491
|
+
"page-middleware-not-mutation-guard": {
|
|
2492
|
+
value: "page-middleware-not-mutation-guard",
|
|
2493
|
+
status: "emitted-example",
|
|
2494
|
+
note: "emitted on the guards target so a page guard is not read as a mutation guard"
|
|
2495
|
+
}
|
|
2496
|
+
};
|
|
2497
|
+
const OVERRIDE_DIAGNOSTIC_COVERAGE = {
|
|
2498
|
+
"missing-owned-fact": {
|
|
2499
|
+
value: "missing-owned-fact",
|
|
2500
|
+
status: "currently-unbound",
|
|
2501
|
+
note: "reserved by the spec's closed diagnostic set; no adapter emits it today, so not even a broken fixture can produce it"
|
|
2502
|
+
},
|
|
2503
|
+
"missing-source": {
|
|
2504
|
+
value: "missing-source",
|
|
2505
|
+
status: "negative-fixture",
|
|
2506
|
+
note: "a fact whose provenance cannot be proven yields this and no target; activated canonical output emits none"
|
|
2507
|
+
},
|
|
2508
|
+
"unsupported-dynamic-key": {
|
|
2509
|
+
value: "unsupported-dynamic-key",
|
|
2510
|
+
status: "negative-fixture",
|
|
2511
|
+
note: "a key the runtime cannot address yields this and no target; activated canonical output emits none"
|
|
2512
|
+
},
|
|
2513
|
+
"unknown-framework-domain": {
|
|
2514
|
+
value: "unknown-framework-domain",
|
|
2515
|
+
status: "negative-fixture",
|
|
2516
|
+
note: "the framework catalog does not describe the dotted host at all"
|
|
2517
|
+
},
|
|
2518
|
+
"unknown-framework-mode": {
|
|
2519
|
+
value: "unknown-framework-mode",
|
|
2520
|
+
status: "negative-fixture",
|
|
2521
|
+
note: "the framework catalog describes the host but names an operation that is not a public mode"
|
|
2522
|
+
}
|
|
2523
|
+
};
|
|
2524
|
+
const CONTRIBUTION_KIND_COVERAGE = {
|
|
2525
|
+
widget: { value: "widget", status: "emitted-example", note: "example widget injection and dashboard registrations" },
|
|
2526
|
+
"data-table": { value: "data-table", status: "emitted-example", note: "example DataTable extension entries" },
|
|
2527
|
+
"crud-form": { value: "crud-form", status: "emitted-example", note: "example CrudForm field and lifecycle entries" },
|
|
2528
|
+
"component-override": { value: "component-override", status: "emitted-example", note: "example replace, wrapper and props component entries" },
|
|
2529
|
+
"response-enricher": { value: "response-enricher", status: "emitted-example", note: "example customer priority response enricher" },
|
|
2530
|
+
"api-interceptor": { value: "api-interceptor", status: "emitted-example", note: "example CRUD API interceptor entries" },
|
|
2531
|
+
"command-interceptor": { value: "command-interceptor", status: "emitted-example", note: "example command interceptor entries" },
|
|
2532
|
+
"mutation-guard": { value: "mutation-guard", status: "emitted-example", note: "example Todo mutation guard" },
|
|
2533
|
+
"entity-extension": { value: "entity-extension", status: "emitted-example", note: "example customer entity extension" },
|
|
2534
|
+
subscriber: { value: "subscriber", status: "emitted-example", note: "example synchronous and asynchronous subscribers" },
|
|
2535
|
+
"browser-reaction": { value: "browser-reaction", status: "emitted-example", note: "example client, portal and notification reactions" },
|
|
2536
|
+
"specialized-registry": { value: "specialized-registry", status: "emitted-example", note: "example notification, search, AI and mock adapter registries" },
|
|
2537
|
+
"module-override": { value: "module-override", status: "catalog-only", note: "app-owned configuration is not an outgoing module contribution" }
|
|
2538
|
+
};
|
|
2539
|
+
const ACTIVATION_KIND_COVERAGE = {
|
|
2540
|
+
"crud-response-enricher": { value: "crud-response-enricher", status: "currently-unbound", note: "example contributes a response enricher but owns no CRUD response call site for its customer target" },
|
|
2541
|
+
"query-enricher": { value: "query-enricher", status: "currently-unbound", note: "example contributes a query enricher but owns no query-engine call site for its customer target" },
|
|
2542
|
+
"mutation-guard": { value: "mutation-guard", status: "emitted-example", note: "Todo mutation-guard route bridge" },
|
|
2543
|
+
"api-interceptor-bridge": { value: "api-interceptor-bridge", status: "emitted-example", note: "CRUD route interceptor pipeline" },
|
|
2544
|
+
"command-interceptor-bridge": { value: "command-interceptor-bridge", status: "emitted-example", note: "exact Todo command bus target" },
|
|
2545
|
+
"widget-injection-consumer": { value: "widget-injection-consumer", status: "emitted-example", note: "bound injection host consumer" },
|
|
2546
|
+
"component-extension-consumer": { value: "component-extension-consumer", status: "emitted-example", note: "bound component handle consumer" },
|
|
2547
|
+
"dashboard-host-consumer": { value: "dashboard-host-consumer", status: "emitted-example", note: "framework dashboard registry consumer" }
|
|
2548
|
+
};
|
|
2549
|
+
const HOST_FAMILY_COVERAGE = {
|
|
2550
|
+
generic: { value: "generic", status: "emitted-example", note: "example headless injection host" },
|
|
2551
|
+
menu: { value: "menu", status: "framework-only", note: "framework menu hosts consumed by example widgets" },
|
|
2552
|
+
"data-table": { value: "data-table", status: "emitted-example", note: "example Todo DataTable host" },
|
|
2553
|
+
"crud-form": { value: "crud-form", status: "emitted-example", note: "example Todo CrudForm host" },
|
|
2554
|
+
detail: { value: "detail", status: "framework-only", note: "framework detail hosts consumed by example widgets" },
|
|
2555
|
+
"portal-page": { value: "portal-page", status: "framework-only", note: "framework portal host consumed by example widgets" },
|
|
2556
|
+
"component-handle": { value: "component-handle", status: "emitted-example", note: "example replaceable component host" },
|
|
2557
|
+
entity: { value: "entity", status: "emitted-example", note: "example entity fact-reference hosts" },
|
|
2558
|
+
"api-route": { value: "api-route", status: "framework-only", note: "API route hosts are owned by the target module and consumed by example interceptors" },
|
|
2559
|
+
command: { value: "command", status: "framework-only", note: "command hosts are owned by the target module and consumed by example interceptors" },
|
|
2560
|
+
event: { value: "event", status: "emitted-example", note: "example event fact-reference hosts" },
|
|
2561
|
+
"query-lifecycle": { value: "query-lifecycle", status: "emitted-example", note: "example Todo query lifecycle hosts" },
|
|
2562
|
+
dashboard: { value: "dashboard", status: "framework-only", note: "framework dashboard host consumed by example widgets" },
|
|
2563
|
+
notification: { value: "notification", status: "framework-only", note: "framework notification host consumed by the example registry" },
|
|
2564
|
+
integration: { value: "integration", status: "framework-only", note: "framework integration detail host consumed by example widgets" },
|
|
2565
|
+
"specialized-registry": { value: "specialized-registry", status: "framework-only", note: "framework-owned specialist registries accept example entries" },
|
|
2566
|
+
"module-override": { value: "module-override", status: "framework-only", note: "framework override catalog owns these hosts" }
|
|
2567
|
+
};
|
|
2568
|
+
const HOST_CAPABILITY_COVERAGE = {
|
|
2569
|
+
"render-widget": { value: "render-widget", status: "emitted-example", note: "example render widget host and contributions" },
|
|
2570
|
+
"headless-widget": { value: "headless-widget", status: "currently-unbound", note: "injection-table facts do not yet distinguish headless widget payloads" },
|
|
2571
|
+
"menu-item": { value: "menu-item", status: "currently-unbound", note: "injection-table facts do not yet distinguish menu item payloads" },
|
|
2572
|
+
"column-widget": { value: "column-widget", status: "emitted-example", note: "example DataTable column host" },
|
|
2573
|
+
"row-action": { value: "row-action", status: "emitted-example", note: "example DataTable row-action host" },
|
|
2574
|
+
"bulk-action": { value: "bulk-action", status: "emitted-example", note: "example DataTable bulk-action host" },
|
|
2575
|
+
"filter-widget": { value: "filter-widget", status: "emitted-example", note: "example DataTable filter host" },
|
|
2576
|
+
"toolbar-widget": { value: "toolbar-widget", status: "emitted-example", note: "example DataTable toolbar host" },
|
|
2577
|
+
"field-widget": { value: "field-widget", status: "emitted-example", note: "example CrudForm field host" },
|
|
2578
|
+
"lifecycle-handler": { value: "lifecycle-handler", status: "emitted-example", note: "example CrudForm lifecycle host" },
|
|
2579
|
+
"component-replacement": { value: "component-replacement", status: "emitted-example", note: "example replaceable DataTable, CrudForm and component hosts" },
|
|
2580
|
+
"response-enricher": { value: "response-enricher", status: "emitted-example", note: "example entity enricher host" },
|
|
2581
|
+
"query-enricher": { value: "query-enricher", status: "emitted-example", note: "example query-enricher host" },
|
|
2582
|
+
"api-interceptor": { value: "api-interceptor", status: "emitted-example", note: "example API interceptor contribution and route bridge" },
|
|
2583
|
+
"command-interceptor": { value: "command-interceptor", status: "emitted-example", note: "example command interceptor and exact command owner" },
|
|
2584
|
+
"mutation-guard": { value: "mutation-guard", status: "emitted-example", note: "example entity mutation guard host" },
|
|
2585
|
+
"entity-extension": { value: "entity-extension", status: "emitted-example", note: "example entity extension host" },
|
|
2586
|
+
"async-subscriber": { value: "async-subscriber", status: "emitted-example", note: "example event subscriber host" },
|
|
2587
|
+
"sync-subscriber": { value: "sync-subscriber", status: "emitted-example", note: "example synchronous event subscriber host" },
|
|
2588
|
+
"browser-client": { value: "browser-client", status: "emitted-example", note: "example client-broadcast event host" },
|
|
2589
|
+
"browser-portal": { value: "browser-portal", status: "emitted-example", note: "example portal-broadcast event host" },
|
|
2590
|
+
"registry-contribution": { value: "registry-contribution", status: "emitted-example", note: "example specialized registry contributions" },
|
|
2591
|
+
"module-override": { value: "module-override", status: "framework-only", note: "framework override hosts; app configuration is not a contribution" }
|
|
2592
|
+
};
|
|
2593
|
+
const HOST_ACTIVATION_COVERAGE = {
|
|
2594
|
+
always: { value: "always", status: "emitted-example", note: "always-active example declarations" },
|
|
2595
|
+
"host-opt-in": { value: "host-opt-in", status: "emitted-example", note: "example entity extension and response-enricher hosts" },
|
|
2596
|
+
"caller-opt-in": { value: "caller-opt-in", status: "emitted-example", note: "example query lifecycle and query enricher" },
|
|
2597
|
+
"feature-gated": { value: "feature-gated", status: "currently-unbound", note: "feature requirements are emitted but are not a distinct activation value" }
|
|
2598
|
+
};
|
|
2599
|
+
const TARGET_KIND_COVERAGE = {
|
|
2600
|
+
module: { value: "module", status: "emitted-example", note: "example module-scoped registry target" },
|
|
2601
|
+
entity: { value: "entity", status: "emitted-example", note: "example entity extension, enricher and guard targets" },
|
|
2602
|
+
"api-route": { value: "api-route", status: "emitted-example", note: "example API interceptor targets" },
|
|
2603
|
+
command: { value: "command", status: "emitted-example", note: "example exact and wildcard command targets" },
|
|
2604
|
+
"widget-spot": { value: "widget-spot", status: "emitted-example", note: "example injection targets" },
|
|
2605
|
+
component: { value: "component", status: "emitted-example", note: "example component override targets" },
|
|
2606
|
+
event: { value: "event", status: "emitted-example", note: "example subscriber targets" },
|
|
2607
|
+
notification: { value: "notification", status: "emitted-example", note: "example notification registry target" },
|
|
2608
|
+
wildcard: { value: "wildcard", status: "emitted-example", note: "example wildcard subscriber and interceptor targets" }
|
|
2609
|
+
};
|
|
2610
|
+
const HOST_RESOLUTION_COVERAGE = {
|
|
2611
|
+
exact: { value: "exact", status: "emitted-example", note: "example exact declared hosts" },
|
|
2612
|
+
pattern: { value: "pattern", status: "emitted-example", note: "example patterned host surfaces" },
|
|
2613
|
+
framework: { value: "framework", status: "framework-only", note: "framework catalog host identity" },
|
|
2614
|
+
"fact-ref": { value: "fact-ref", status: "emitted-example", note: "example entity, event and query fact-reference hosts" }
|
|
2615
|
+
};
|
|
2616
|
+
const TARGET_RESOLUTION_COVERAGE = {
|
|
2617
|
+
exact: { value: "exact", status: "emitted-example", note: "example exact target correlation" },
|
|
2618
|
+
pattern: { value: "pattern", status: "emitted-example", note: "example wildcard and patterned target correlation" },
|
|
2619
|
+
framework: { value: "framework", status: "emitted-example", note: "example contribution to a framework host" },
|
|
2620
|
+
"fact-ref": { value: "fact-ref", status: "emitted-example", note: "example contribution to a generated fact owner" },
|
|
2621
|
+
"optional-external": { value: "optional-external", status: "emitted-example", note: "example optional module target remains fail-soft" },
|
|
2622
|
+
unresolved: { value: "unresolved", status: "negative-fixture", note: "only malformed targets remain unresolved" }
|
|
2623
|
+
};
|
|
2624
|
+
const TOPOLOGY_RESOLUTION_COVERAGE = {
|
|
2625
|
+
bound: { value: "bound", status: "emitted-example", note: "example contribution reaches a verified runtime activation" },
|
|
2626
|
+
"capability-only": { value: "capability-only", status: "emitted-example", note: "declaration-backed capability without a separate caller activation" },
|
|
2627
|
+
"optional-target-missing": { value: "optional-target-missing", status: "emitted-example", note: "optional external target absent from the selected module set" },
|
|
2628
|
+
wildcard: { value: "wildcard", status: "emitted-example", note: "wildcard contribution resolves against selected targets" },
|
|
2629
|
+
unresolved: { value: "unresolved", status: "negative-fixture", note: "only malformed first-party targets remain unresolved" }
|
|
2630
|
+
};
|
|
2631
|
+
const SPECIALIZED_REGISTRY_COVERAGE = {
|
|
2632
|
+
notification: { value: "notification", status: "emitted-example", note: "example notification type registry" },
|
|
2633
|
+
integration: { value: "integration", status: "emitted-example", note: "example credential-free integration bundle identity" },
|
|
2634
|
+
search: { value: "search", status: "emitted-example", note: "example Todo search registry" },
|
|
2635
|
+
vector: { value: "vector", status: "emitted-example", note: "example deterministic Todo vector registry" },
|
|
2636
|
+
ai: { value: "ai", status: "emitted-example", note: "example AI tool and agent registries" },
|
|
2637
|
+
payment: { value: "payment", status: "emitted-example", note: "example mock payment descriptors" },
|
|
2638
|
+
shipping: { value: "shipping", status: "emitted-example", note: "example mock shipping registry identity" },
|
|
2639
|
+
currency: { value: "currency", status: "emitted-example", note: "example deterministic currency provider identity" },
|
|
2640
|
+
workflow: { value: "workflow", status: "emitted-example", note: "example event-triggered Todo workflow identity" }
|
|
2641
|
+
};
|
|
2642
|
+
const COMPONENT_MODE_COVERAGE = {
|
|
2643
|
+
replace: { value: "replace", status: "emitted-example", note: "example replacement component" },
|
|
2644
|
+
wrapper: { value: "wrapper", status: "emitted-example", note: "example decorating wrapper component" },
|
|
2645
|
+
props: { value: "props", status: "emitted-example", note: "example props-transform component" }
|
|
2646
|
+
};
|
|
2647
|
+
const FACT_DIAGNOSTIC_COVERAGE = {
|
|
2648
|
+
"duplicate-source": { value: "duplicate-source", status: "negative-fixture", note: "duplicate provenance fixture; canonical output emits none" },
|
|
2649
|
+
"unresolved-static-contract": { value: "unresolved-static-contract", status: "negative-fixture", note: "dynamic contract fixture; canonical output emits none" }
|
|
2650
|
+
};
|
|
2651
|
+
const UNRESOLVED_REASON_COVERAGE = {
|
|
2652
|
+
"unclassified-binding": { value: "unclassified-binding", status: "negative-fixture", note: "malformed extension declaration fixture" },
|
|
2653
|
+
"unbound-declaration": { value: "unbound-declaration", status: "negative-fixture", note: "declared host without a real caller fixture" },
|
|
2654
|
+
"dynamic-without-pattern": { value: "dynamic-without-pattern", status: "negative-fixture", note: "dynamic host without a declared pattern fixture" },
|
|
2655
|
+
"unresolved-first-party-target": { value: "unresolved-first-party-target", status: "negative-fixture", note: "broken first-party target fixture" }
|
|
2656
|
+
};
|
|
2657
|
+
const DATA_TABLE_SURFACE_COVERAGE = {
|
|
2658
|
+
header: { value: "header", status: "emitted-example", note: "bound Todo table header" },
|
|
2659
|
+
footer: { value: "footer", status: "emitted-example", note: "bound Todo table footer" },
|
|
2660
|
+
toolbar: { value: "toolbar", status: "emitted-example", note: "bound Todo table toolbar" },
|
|
2661
|
+
searchTrailing: { value: "searchTrailing", status: "emitted-example", note: "bound Todo table search trailing surface" },
|
|
2662
|
+
columns: { value: "columns", status: "emitted-example", note: "bound Todo table columns" },
|
|
2663
|
+
rowActions: { value: "rowActions", status: "emitted-example", note: "bound Todo table row actions" },
|
|
2664
|
+
bulkActions: { value: "bulkActions", status: "emitted-example", note: "bound Todo table bulk actions" },
|
|
2665
|
+
filters: { value: "filters", status: "emitted-example", note: "bound Todo table filters" },
|
|
2666
|
+
replacement: { value: "replacement", status: "emitted-example", note: "bound Todo table replacement" },
|
|
2667
|
+
emptyState: { value: "emptyState", status: "currently-unbound", note: "catalog-declared DataTable surface has no runtime host" }
|
|
2668
|
+
};
|
|
2669
|
+
const CRUD_FORM_SURFACE_COVERAGE = {
|
|
2670
|
+
base: { value: "base", status: "emitted-example", note: "bound Todo form base" },
|
|
2671
|
+
header: { value: "header", status: "emitted-example", note: "bound Todo form header" },
|
|
2672
|
+
fields: { value: "fields", status: "emitted-example", note: "bound Todo form fields" },
|
|
2673
|
+
replacement: { value: "replacement", status: "emitted-example", note: "bound Todo form replacement" },
|
|
2674
|
+
beforeFields: { value: "beforeFields", status: "currently-unbound", note: "catalog-declared CrudForm surface has no runtime host" },
|
|
2675
|
+
afterFields: { value: "afterFields", status: "currently-unbound", note: "catalog-declared CrudForm surface has no runtime host" },
|
|
2676
|
+
footer: { value: "footer", status: "currently-unbound", note: "catalog-declared CrudForm surface has no runtime host" },
|
|
2677
|
+
sidebar: { value: "sidebar", status: "currently-unbound", note: "catalog-declared CrudForm surface has no runtime host" },
|
|
2678
|
+
group: { value: "group", status: "currently-unbound", note: "catalog-declared CrudForm surface has no runtime host" },
|
|
2679
|
+
fieldBefore: { value: "fieldBefore", status: "currently-unbound", note: "catalog-declared CrudForm surface has no runtime host" },
|
|
2680
|
+
fieldAfter: { value: "fieldAfter", status: "currently-unbound", note: "catalog-declared CrudForm surface has no runtime host" }
|
|
2681
|
+
};
|
|
2682
|
+
const CRUD_FORM_LIFECYCLE_COVERAGE = {
|
|
2683
|
+
transformValidation: { value: "transformValidation", status: "emitted-example", note: "example Todo form lifecycle transformValidation" },
|
|
2684
|
+
transformDisplayData: { value: "transformDisplayData", status: "emitted-example", note: "example Todo form lifecycle transformDisplayData" },
|
|
2685
|
+
onBeforeNavigate: { value: "onBeforeNavigate", status: "emitted-example", note: "example Todo form lifecycle onBeforeNavigate" },
|
|
2686
|
+
onAppEvent: { value: "onAppEvent", status: "emitted-example", note: "example Todo form lifecycle onAppEvent" },
|
|
2687
|
+
onVisibilityChange: { value: "onVisibilityChange", status: "emitted-example", note: "example Todo form lifecycle onVisibilityChange" },
|
|
2688
|
+
onBeforeDelete: { value: "onBeforeDelete", status: "emitted-example", note: "example Todo form lifecycle onBeforeDelete" },
|
|
2689
|
+
onDelete: { value: "onDelete", status: "emitted-example", note: "example Todo form lifecycle onDelete" },
|
|
2690
|
+
onAfterDelete: { value: "onAfterDelete", status: "emitted-example", note: "example Todo form lifecycle onAfterDelete" },
|
|
2691
|
+
onDeleteError: { value: "onDeleteError", status: "emitted-example", note: "example Todo form lifecycle onDeleteError" },
|
|
2692
|
+
onFieldChange: { value: "onFieldChange", status: "emitted-example", note: "example Todo form lifecycle onFieldChange" },
|
|
2693
|
+
transformFormData: { value: "transformFormData", status: "emitted-example", note: "example Todo form lifecycle transformFormData" },
|
|
2694
|
+
onBeforeSave: { value: "onBeforeSave", status: "emitted-example", note: "example Todo form lifecycle onBeforeSave" },
|
|
2695
|
+
onSave: { value: "onSave", status: "emitted-example", note: "example Todo form lifecycle onSave" },
|
|
2696
|
+
onAfterSave: { value: "onAfterSave", status: "emitted-example", note: "example Todo form lifecycle onAfterSave" }
|
|
2697
|
+
};
|
|
2698
|
+
const CRUD_FORM_OPERATION_COVERAGE = {
|
|
2699
|
+
create: { value: "create", status: "emitted-example", note: "example Todo create lifecycle" },
|
|
2700
|
+
update: { value: "update", status: "currently-unbound", note: "example lifecycle contribution is currently registered for create only" },
|
|
2701
|
+
delete: { value: "delete", status: "currently-unbound", note: "example lifecycle contribution is currently registered for create only" }
|
|
2702
|
+
};
|
|
2703
|
+
function buildCoverageFamily(family, enumSource, values, coverage) {
|
|
2704
|
+
const rows = [];
|
|
2705
|
+
const missing = [];
|
|
2706
|
+
for (const value of values) {
|
|
2707
|
+
const row = coverage[value];
|
|
2708
|
+
if (!row) {
|
|
2709
|
+
missing.push(value);
|
|
2710
|
+
continue;
|
|
2711
|
+
}
|
|
2712
|
+
rows.push(row);
|
|
2713
|
+
}
|
|
2714
|
+
if (missing.length > 0) {
|
|
2715
|
+
throw new Error(
|
|
2716
|
+
`[module-facts] factCoverage family "${family}" has no row for: ${missing.join(", ")}. Add an explicit classification instead of leaving the value unclassified.`
|
|
2717
|
+
);
|
|
2718
|
+
}
|
|
2719
|
+
const extra = Object.keys(coverage).filter((value) => !values.includes(value));
|
|
2720
|
+
if (extra.length > 0) {
|
|
2721
|
+
throw new Error(
|
|
2722
|
+
`[module-facts] factCoverage family "${family}" classifies values absent from the enum: ${extra.join(", ")}.`
|
|
2723
|
+
);
|
|
2724
|
+
}
|
|
2725
|
+
return { family, enumSource, rows };
|
|
2726
|
+
}
|
|
2727
|
+
function buildModuleFactCoverageLedger() {
|
|
2728
|
+
return [
|
|
2729
|
+
buildCoverageFamily(
|
|
2730
|
+
"ModuleFactSourceKind",
|
|
2731
|
+
"packages/cli/src/lib/generators/module-facts.ts#MODULE_FACT_SOURCE_KINDS",
|
|
2732
|
+
MODULE_FACT_SOURCE_KINDS,
|
|
2733
|
+
FACT_SOURCE_KIND_COVERAGE
|
|
2734
|
+
),
|
|
2735
|
+
buildCoverageFamily(
|
|
2736
|
+
"ModuleOwnedContractKind",
|
|
2737
|
+
"packages/cli/src/lib/generators/module-facts.ts#MODULE_OWNED_CONTRACT_KINDS",
|
|
2738
|
+
MODULE_OWNED_CONTRACT_KINDS,
|
|
2739
|
+
OWNED_CONTRACT_KIND_COVERAGE
|
|
2740
|
+
),
|
|
2741
|
+
buildCoverageFamily(
|
|
2742
|
+
"ModuleOverrideDomain",
|
|
2743
|
+
"packages/cli/src/lib/generators/module-override-targets.ts#ALL_OVERRIDE_DOMAINS",
|
|
2744
|
+
ALL_OVERRIDE_DOMAINS,
|
|
2745
|
+
OVERRIDE_DOMAIN_COVERAGE
|
|
2746
|
+
),
|
|
2747
|
+
buildCoverageFamily(
|
|
2748
|
+
"ModuleOverrideMode",
|
|
2749
|
+
"packages/cli/src/lib/generators/module-override-targets.ts#MODULE_OVERRIDE_MODES",
|
|
2750
|
+
MODULE_OVERRIDE_MODES,
|
|
2751
|
+
OVERRIDE_MODE_COVERAGE
|
|
2752
|
+
),
|
|
2753
|
+
buildCoverageFamily(
|
|
2754
|
+
"ModuleOverrideTargetNote",
|
|
2755
|
+
"packages/cli/src/lib/generators/module-override-targets.ts#MODULE_OVERRIDE_TARGET_NOTES",
|
|
2756
|
+
MODULE_OVERRIDE_TARGET_NOTES,
|
|
2757
|
+
OVERRIDE_NOTE_COVERAGE
|
|
2758
|
+
),
|
|
2759
|
+
buildCoverageFamily(
|
|
2760
|
+
"ModuleOverrideTargetDiagnosticCode",
|
|
2761
|
+
"packages/cli/src/lib/generators/module-override-targets.ts#MODULE_OVERRIDE_TARGET_DIAGNOSTIC_CODES",
|
|
2762
|
+
MODULE_OVERRIDE_TARGET_DIAGNOSTIC_CODES,
|
|
2763
|
+
OVERRIDE_DIAGNOSTIC_COVERAGE
|
|
2764
|
+
),
|
|
2765
|
+
buildCoverageFamily(
|
|
2766
|
+
"ModuleExtensionContributionKind",
|
|
2767
|
+
"packages/shared/src/modules/widgets/extension-points.ts#MODULE_EXTENSION_CONTRIBUTION_KINDS",
|
|
2768
|
+
MODULE_EXTENSION_CONTRIBUTION_KINDS,
|
|
2769
|
+
CONTRIBUTION_KIND_COVERAGE
|
|
2770
|
+
),
|
|
2771
|
+
buildCoverageFamily(
|
|
2772
|
+
"ModuleExtensionActivationKind",
|
|
2773
|
+
"packages/shared/src/modules/widgets/extension-points.ts#MODULE_EXTENSION_ACTIVATION_KINDS",
|
|
2774
|
+
MODULE_EXTENSION_ACTIVATION_KINDS,
|
|
2775
|
+
ACTIVATION_KIND_COVERAGE
|
|
2776
|
+
),
|
|
2777
|
+
buildCoverageFamily(
|
|
2778
|
+
"ExtensionHostFamily",
|
|
2779
|
+
"packages/shared/src/modules/widgets/extension-points.ts#EXTENSION_HOST_FAMILIES",
|
|
2780
|
+
EXTENSION_HOST_FAMILIES,
|
|
2781
|
+
HOST_FAMILY_COVERAGE
|
|
2782
|
+
),
|
|
2783
|
+
buildCoverageFamily(
|
|
2784
|
+
"ExtensionHostCapability",
|
|
2785
|
+
"packages/shared/src/modules/widgets/extension-points.ts#EXTENSION_HOST_CAPABILITIES",
|
|
2786
|
+
EXTENSION_HOST_CAPABILITIES,
|
|
2787
|
+
HOST_CAPABILITY_COVERAGE
|
|
2788
|
+
),
|
|
2789
|
+
buildCoverageFamily(
|
|
2790
|
+
"ExtensionHostActivation",
|
|
2791
|
+
"packages/shared/src/modules/widgets/extension-points.ts#EXTENSION_HOST_ACTIVATIONS",
|
|
2792
|
+
EXTENSION_HOST_ACTIVATIONS,
|
|
2793
|
+
HOST_ACTIVATION_COVERAGE
|
|
2794
|
+
),
|
|
2795
|
+
buildCoverageFamily(
|
|
2796
|
+
"ModuleExtensionTargetKind",
|
|
2797
|
+
"packages/shared/src/modules/widgets/extension-points.ts#MODULE_EXTENSION_TARGET_KINDS",
|
|
2798
|
+
MODULE_EXTENSION_TARGET_KINDS,
|
|
2799
|
+
TARGET_KIND_COVERAGE
|
|
2800
|
+
),
|
|
2801
|
+
buildCoverageFamily(
|
|
2802
|
+
"ModuleExtensionHostResolution",
|
|
2803
|
+
"packages/shared/src/modules/widgets/extension-points.ts#MODULE_EXTENSION_HOST_RESOLUTIONS",
|
|
2804
|
+
MODULE_EXTENSION_HOST_RESOLUTIONS,
|
|
2805
|
+
HOST_RESOLUTION_COVERAGE
|
|
2806
|
+
),
|
|
2807
|
+
buildCoverageFamily(
|
|
2808
|
+
"ModuleExtensionTargetResolution",
|
|
2809
|
+
"packages/shared/src/modules/widgets/extension-points.ts#MODULE_EXTENSION_TARGET_RESOLUTIONS",
|
|
2810
|
+
MODULE_EXTENSION_TARGET_RESOLUTIONS,
|
|
2811
|
+
TARGET_RESOLUTION_COVERAGE
|
|
2812
|
+
),
|
|
2813
|
+
buildCoverageFamily(
|
|
2814
|
+
"ModuleExtensionResolution",
|
|
2815
|
+
"packages/shared/src/modules/widgets/extension-points.ts#MODULE_EXTENSION_RESOLUTIONS",
|
|
2816
|
+
MODULE_EXTENSION_RESOLUTIONS,
|
|
2817
|
+
TOPOLOGY_RESOLUTION_COVERAGE
|
|
2818
|
+
),
|
|
2819
|
+
buildCoverageFamily(
|
|
2820
|
+
"SpecializedRegistry",
|
|
2821
|
+
"packages/shared/src/modules/widgets/extension-points.ts#MODULE_SPECIALIZED_REGISTRIES",
|
|
2822
|
+
MODULE_SPECIALIZED_REGISTRIES,
|
|
2823
|
+
SPECIALIZED_REGISTRY_COVERAGE
|
|
2824
|
+
),
|
|
2825
|
+
buildCoverageFamily(
|
|
2826
|
+
"ComponentOverrideMode",
|
|
2827
|
+
"packages/shared/src/modules/widgets/extension-points.ts#COMPONENT_OVERRIDE_MODES",
|
|
2828
|
+
COMPONENT_OVERRIDE_MODES,
|
|
2829
|
+
COMPONENT_MODE_COVERAGE
|
|
2830
|
+
),
|
|
2831
|
+
buildCoverageFamily(
|
|
2832
|
+
"ModuleFactDiagnosticCode",
|
|
2833
|
+
"packages/cli/src/lib/generators/module-facts.ts#MODULE_FACT_DIAGNOSTIC_CODES",
|
|
2834
|
+
MODULE_FACT_DIAGNOSTIC_CODES,
|
|
2835
|
+
FACT_DIAGNOSTIC_COVERAGE
|
|
2836
|
+
),
|
|
2837
|
+
buildCoverageFamily(
|
|
2838
|
+
"ModuleExtensionUnresolvedReason",
|
|
2839
|
+
"packages/shared/src/modules/widgets/extension-points.ts#MODULE_EXTENSION_UNRESOLVED_REASONS",
|
|
2840
|
+
MODULE_EXTENSION_UNRESOLVED_REASONS,
|
|
2841
|
+
UNRESOLVED_REASON_COVERAGE
|
|
2842
|
+
),
|
|
2843
|
+
buildCoverageFamily(
|
|
2844
|
+
"DataTableExtensionSurface",
|
|
2845
|
+
"packages/shared/src/modules/widgets/extension-points.ts#DATA_TABLE_EXTENSION_SURFACE_KEYS",
|
|
2846
|
+
DATA_TABLE_EXTENSION_SURFACE_KEYS,
|
|
2847
|
+
DATA_TABLE_SURFACE_COVERAGE
|
|
2848
|
+
),
|
|
2849
|
+
buildCoverageFamily(
|
|
2850
|
+
"CrudFormExtensionSurface",
|
|
2851
|
+
"packages/shared/src/modules/widgets/extension-points.ts#CRUD_FORM_EXTENSION_SURFACE_KEYS",
|
|
2852
|
+
CRUD_FORM_EXTENSION_SURFACE_KEYS,
|
|
2853
|
+
CRUD_FORM_SURFACE_COVERAGE
|
|
2854
|
+
),
|
|
2855
|
+
buildCoverageFamily(
|
|
2856
|
+
"CrudFormLifecyclePhase",
|
|
2857
|
+
"packages/shared/src/modules/widgets/extension-points.ts#CRUD_FORM_LIFECYCLE_PHASES",
|
|
2858
|
+
CRUD_FORM_LIFECYCLE_PHASES,
|
|
2859
|
+
CRUD_FORM_LIFECYCLE_COVERAGE
|
|
2860
|
+
),
|
|
2861
|
+
buildCoverageFamily(
|
|
2862
|
+
"CrudFormOperation",
|
|
2863
|
+
"packages/shared/src/modules/widgets/extension-points.ts#CRUD_FORM_OPERATIONS",
|
|
2864
|
+
CRUD_FORM_OPERATIONS,
|
|
2865
|
+
CRUD_FORM_OPERATION_COVERAGE
|
|
2866
|
+
)
|
|
2867
|
+
];
|
|
2868
|
+
}
|
|
2869
|
+
function countModuleFactCoverage(facts) {
|
|
2870
|
+
const increment = (counts, value) => {
|
|
2871
|
+
counts[value] = (counts[value] ?? 0) + 1;
|
|
2872
|
+
};
|
|
2873
|
+
const factSourceKind = {};
|
|
2874
|
+
for (const entry of facts.factSources ?? []) {
|
|
2875
|
+
increment(factSourceKind, entry.kind);
|
|
2876
|
+
}
|
|
2877
|
+
const ownedContractKind = {};
|
|
2878
|
+
for (const [kind, list] of Object.entries(facts.ownedContracts ?? {})) {
|
|
2879
|
+
ownedContractKind[kind] = (list ?? []).length;
|
|
2880
|
+
}
|
|
2881
|
+
const overrideDomain = {};
|
|
2882
|
+
const overrideMode = {};
|
|
2883
|
+
const overrideNote = {};
|
|
2884
|
+
for (const target of facts.overrideTargets ?? []) {
|
|
2885
|
+
overrideDomain[target.domain] = (overrideDomain[target.domain] ?? 0) + 1;
|
|
2886
|
+
for (const mode of target.modes) overrideMode[mode] = (overrideMode[mode] ?? 0) + 1;
|
|
2887
|
+
for (const note of target.notes ?? []) overrideNote[note] = (overrideNote[note] ?? 0) + 1;
|
|
2888
|
+
}
|
|
2889
|
+
const overrideDiagnosticCode = {};
|
|
2890
|
+
for (const diagnostic of facts.overrideTargetDiagnostics ?? []) {
|
|
2891
|
+
increment(overrideDiagnosticCode, diagnostic.code);
|
|
2892
|
+
}
|
|
2893
|
+
const contributionKind = {};
|
|
2894
|
+
const activationKind = {};
|
|
2895
|
+
const hostFamily = {};
|
|
2896
|
+
const hostCapability = {};
|
|
2897
|
+
const hostActivation = {};
|
|
2898
|
+
const targetKind = {};
|
|
2899
|
+
const hostResolution = {};
|
|
2900
|
+
const targetResolution = {};
|
|
2901
|
+
const topologyResolution = {};
|
|
2902
|
+
const specializedRegistry = {};
|
|
2903
|
+
const componentMode = {};
|
|
2904
|
+
const factDiagnosticCode = {};
|
|
2905
|
+
const unresolvedReason = {};
|
|
2906
|
+
const dataTableSurface = {};
|
|
2907
|
+
const crudFormSurface = {};
|
|
2908
|
+
const crudFormLifecycle = {};
|
|
2909
|
+
const crudFormOperation = {};
|
|
2910
|
+
const surfaces = facts.extensionSurfaces;
|
|
2911
|
+
for (const host of surfaces?.hosts ?? []) {
|
|
2912
|
+
increment(hostFamily, host.family);
|
|
2913
|
+
increment(hostResolution, host.resolution);
|
|
2914
|
+
increment(hostActivation, host.activation ?? "always");
|
|
2915
|
+
for (const capability of host.capabilities) increment(hostCapability, capability);
|
|
2916
|
+
for (const phase of host.phases ?? []) increment(crudFormLifecycle, phase);
|
|
2917
|
+
for (const operation of host.operations ?? []) increment(crudFormOperation, operation);
|
|
2918
|
+
const [owner, surface] = host.key.split(".");
|
|
2919
|
+
if (owner === "todosTable" && surface) increment(dataTableSurface, surface);
|
|
2920
|
+
if (owner === "todoForm" && surface) increment(crudFormSurface, surface);
|
|
2921
|
+
}
|
|
2922
|
+
for (const contribution of surfaces?.contributions ?? []) {
|
|
2923
|
+
increment(contributionKind, contribution.kind);
|
|
2924
|
+
increment(hostActivation, contribution.activation ?? "always");
|
|
2925
|
+
for (const target of contribution.targets) increment(targetResolution, target.resolution);
|
|
2926
|
+
for (const operation of contribution.operations ?? []) increment(crudFormOperation, operation);
|
|
2927
|
+
if (contribution.kind === "specialized-registry") increment(specializedRegistry, contribution.details.registry);
|
|
2928
|
+
if (contribution.kind === "component-override") increment(componentMode, contribution.details.mode);
|
|
2929
|
+
if (contribution.kind === "widget") {
|
|
2930
|
+
if (contribution.details.payload === "headless") increment(hostCapability, "headless-widget");
|
|
2931
|
+
if (contribution.details.payload === "menu") increment(hostCapability, "menu-item");
|
|
2932
|
+
if (contribution.details.payload === "dashboard" || contribution.details.payload === "notification" || contribution.details.payload === "integration") {
|
|
2933
|
+
increment(hostCapability, "registry-contribution");
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
if (contribution.kind === "api-interceptor") increment(hostCapability, "api-interceptor");
|
|
2937
|
+
if (contribution.kind === "command-interceptor") increment(hostCapability, "command-interceptor");
|
|
2938
|
+
}
|
|
2939
|
+
for (const activation of surfaces?.activations ?? []) increment(activationKind, activation.kind);
|
|
2940
|
+
for (const resolution of surfaces?.contributionResolutions ?? []) {
|
|
2941
|
+
increment(targetKind, resolution.target.kind);
|
|
2942
|
+
increment(topologyResolution, resolution.resolution);
|
|
2943
|
+
for (const id of resolution.activationIds) {
|
|
2944
|
+
const kind = MODULE_EXTENSION_ACTIVATION_KINDS.find((candidate) => id.endsWith(`:${candidate}`));
|
|
2945
|
+
if (kind) increment(activationKind, kind);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
for (const diagnostic of facts.factDiagnostics ?? []) increment(factDiagnosticCode, diagnostic.code);
|
|
2949
|
+
for (const unresolved of surfaces?.unresolved ?? []) increment(unresolvedReason, unresolved.reason);
|
|
2950
|
+
return {
|
|
2951
|
+
ModuleFactSourceKind: factSourceKind,
|
|
2952
|
+
ModuleOwnedContractKind: ownedContractKind,
|
|
2953
|
+
ModuleOverrideDomain: overrideDomain,
|
|
2954
|
+
ModuleOverrideMode: overrideMode,
|
|
2955
|
+
ModuleOverrideTargetNote: overrideNote,
|
|
2956
|
+
ModuleOverrideTargetDiagnosticCode: overrideDiagnosticCode,
|
|
2957
|
+
ModuleExtensionContributionKind: contributionKind,
|
|
2958
|
+
ModuleExtensionActivationKind: activationKind,
|
|
2959
|
+
ExtensionHostFamily: hostFamily,
|
|
2960
|
+
ExtensionHostCapability: hostCapability,
|
|
2961
|
+
ExtensionHostActivation: hostActivation,
|
|
2962
|
+
ModuleExtensionTargetKind: targetKind,
|
|
2963
|
+
ModuleExtensionHostResolution: hostResolution,
|
|
2964
|
+
ModuleExtensionTargetResolution: targetResolution,
|
|
2965
|
+
ModuleExtensionResolution: topologyResolution,
|
|
2966
|
+
SpecializedRegistry: specializedRegistry,
|
|
2967
|
+
ComponentOverrideMode: componentMode,
|
|
2968
|
+
ModuleFactDiagnosticCode: factDiagnosticCode,
|
|
2969
|
+
ModuleExtensionUnresolvedReason: unresolvedReason,
|
|
2970
|
+
DataTableExtensionSurface: dataTableSurface,
|
|
2971
|
+
CrudFormExtensionSurface: crudFormSurface,
|
|
2972
|
+
CrudFormLifecyclePhase: crudFormLifecycle,
|
|
2973
|
+
CrudFormOperation: crudFormOperation
|
|
2974
|
+
};
|
|
2061
2975
|
}
|
|
2062
2976
|
export {
|
|
2977
|
+
MODULE_FACT_DIAGNOSTIC_CODES,
|
|
2978
|
+
MODULE_FACT_SOURCE_KINDS,
|
|
2979
|
+
MODULE_OWNED_CONTRACT_KINDS,
|
|
2980
|
+
assertPackageModuleFactsOnly,
|
|
2981
|
+
assertPortableSourceRoot,
|
|
2982
|
+
buildCoverageFamily,
|
|
2983
|
+
buildModuleFactCoverageLedger,
|
|
2063
2984
|
buildModuleFactsJsonObject,
|
|
2985
|
+
collectUnresolvedFirstPartyTargets,
|
|
2986
|
+
computeModuleSourceFingerprint,
|
|
2987
|
+
computeModuleTaxonomyFingerprint,
|
|
2988
|
+
countModuleFactCoverage,
|
|
2064
2989
|
extractAllModuleFacts,
|
|
2990
|
+
extractLocalReferenceModuleFacts,
|
|
2065
2991
|
extractModuleFacts,
|
|
2992
|
+
isExactSourceFilePath,
|
|
2066
2993
|
renderModuleFactsJson,
|
|
2067
2994
|
renderModuleFactsMarkdown,
|
|
2995
|
+
renderReferenceModuleFactsJson,
|
|
2068
2996
|
toModuleFactsJsonEntry
|
|
2069
2997
|
};
|
|
2070
2998
|
//# sourceMappingURL=module-facts.js.map
|