@open-mercato/cli 0.6.7-develop.6863.1.61001cf9a8 → 0.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -4
- package/build.mjs +7 -24
- package/dist/agentic/claude-code/hooks/entity-migration-check.ts +88 -32
- package/dist/agentic/codex/enforcement-rules.md +16 -2
- package/dist/agentic/cursor/hooks/entity-migration-check.mjs +50 -19
- package/dist/agentic/cursor/rules/entity-guard.mdc +21 -9
- package/dist/agentic/cursor/rules/generated-guard.mdc +5 -3
- package/dist/agentic/cursor/rules/open-mercato.mdc +29 -3
- package/dist/agentic/guides/cache.md +45 -0
- package/dist/agentic/guides/core.md +453 -0
- package/dist/agentic/guides/events.md +117 -0
- package/dist/agentic/guides/module-facts.json +3833 -115419
- package/dist/agentic/guides/module-system.md +127 -12
- package/dist/agentic/guides/modules/ai_assistant.md +28 -227
- package/dist/agentic/guides/modules/api_docs.md +2 -58
- package/dist/agentic/guides/modules/api_keys.md +7 -92
- package/dist/agentic/guides/modules/attachments.md +14 -119
- package/dist/agentic/guides/modules/audit_logs.md +10 -131
- package/dist/agentic/guides/modules/auth.md +33 -276
- package/dist/agentic/guides/modules/business_rules.md +14 -149
- package/dist/agentic/guides/modules/catalog.md +43 -475
- package/dist/agentic/guides/modules/channel_gmail.md +3 -82
- package/dist/agentic/guides/modules/channel_imap.md +3 -82
- package/dist/agentic/guides/modules/checkout.md +27 -299
- package/dist/agentic/guides/modules/communication_channels.md +33 -315
- package/dist/agentic/guides/modules/configs.md +8 -104
- package/dist/agentic/guides/modules/content.md +2 -57
- package/dist/agentic/guides/modules/currencies.md +17 -152
- package/dist/agentic/guides/modules/customer_accounts.md +45 -387
- package/dist/agentic/guides/modules/customers.md +85 -746
- package/dist/agentic/guides/modules/dashboards.md +10 -155
- package/dist/agentic/guides/modules/data_sync.md +16 -149
- package/dist/agentic/guides/modules/dictionaries.md +12 -107
- package/dist/agentic/guides/modules/directory.md +15 -148
- package/dist/agentic/guides/modules/entities.md +13 -145
- package/dist/agentic/guides/modules/events.md +2 -59
- package/dist/agentic/guides/modules/feature_toggles.md +9 -119
- package/dist/agentic/guides/modules/gateway_stripe.md +4 -92
- package/dist/agentic/guides/modules/generators.md +2 -45
- package/dist/agentic/guides/modules/inbox_ops.md +27 -207
- package/dist/agentic/guides/modules/integrations.md +16 -146
- package/dist/agentic/guides/modules/messages.md +24 -223
- package/dist/agentic/guides/modules/notifications.md +8 -96
- package/dist/agentic/guides/modules/onboarding.md +6 -77
- package/dist/agentic/guides/modules/payment_gateways.md +21 -164
- package/dist/agentic/guides/modules/perspectives.md +7 -77
- package/dist/agentic/guides/modules/planner.md +18 -136
- package/dist/agentic/guides/modules/portal.md +2 -93
- package/dist/agentic/guides/modules/progress.md +14 -104
- package/dist/agentic/guides/modules/query_index.md +15 -154
- package/dist/agentic/guides/modules/record_locks.md +21 -206
- package/dist/agentic/guides/modules/resources.md +30 -197
- package/dist/agentic/guides/modules/sales.md +84 -678
- package/dist/agentic/guides/modules/scheduler.md +14 -133
- package/dist/agentic/guides/modules/search.md +6 -170
- package/dist/agentic/guides/modules/security.md +35 -294
- package/dist/agentic/guides/modules/shipping_carriers.md +18 -134
- package/dist/agentic/guides/modules/sso.md +26 -151
- package/dist/agentic/guides/modules/staff.md +57 -369
- package/dist/agentic/guides/modules/storage_s3.md +5 -95
- package/dist/agentic/guides/modules/sync_akeneo.md +3 -85
- package/dist/agentic/guides/modules/sync_excel.md +6 -75
- package/dist/agentic/guides/modules/system_status_overlays.md +2 -60
- package/dist/agentic/guides/modules/translations.md +10 -104
- package/dist/agentic/guides/modules/webhooks.md +24 -203
- package/dist/agentic/guides/modules/wms.md +46 -441
- package/dist/agentic/guides/modules/workflows.md +43 -302
- package/dist/agentic/guides/queue.md +53 -0
- package/dist/agentic/guides/search.md +115 -0
- package/dist/agentic/guides/shared.md +108 -0
- package/dist/agentic/guides/ui.md +347 -0
- package/dist/agentic/shared/AGENTS.md.template +311 -124
- package/dist/agentic/shared/ai/agentic.config.json +0 -2
- package/dist/agentic/shared/ai/lessons.md +3 -26
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +27 -0
- package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +0 -4
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +241 -20
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +260 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +601 -16
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +146 -0
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +310 -14
- package/dist/agentic/shared/ai/skills/om-help/SKILL.md +97 -15
- package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +84 -0
- package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +193 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +152 -33
- package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +708 -24
- package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +34 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +762 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +820 -20
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +50 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +97 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +843 -19
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +271 -0
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +63 -15
- package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +467 -16
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +101 -0
- package/dist/agentic/shared/ai/skills/tiers.json +21 -143
- package/dist/agentic/shared/ai/skills/tiers.schema.json +40 -52
- package/dist/agentic/shared/ai/specs/README.md +3 -4
- package/dist/agentic/shared/ai/specs/SPEC-000-template.md +10 -226
- package/dist/agentic/shared/ai/trackers/github.md +4 -108
- package/dist/agentic/shared/scripts/install-skills.sh +694 -4
- package/dist/bin.js +1 -13
- package/dist/bin.js.map +2 -2
- package/dist/lib/__integration__/TC-INT-008.spec.js +8 -88
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-init.js +3 -13
- package/dist/lib/agentic-init.js.map +2 -2
- package/dist/lib/agentic-setup.js +186 -418
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/extensions/injection-widgets.js +0 -20
- package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
- package/dist/lib/generators/module-facts-discovery.js +7 -41
- package/dist/lib/generators/module-facts-discovery.js.map +2 -2
- package/dist/lib/generators/module-facts.js +45 -1387
- package/dist/lib/generators/module-facts.js.map +3 -3
- package/dist/lib/generators/module-registry.js +5 -11
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/resolver.js +0 -2
- package/dist/lib/resolver.js.map +2 -2
- package/dist/lib/testing/integration.js +0 -5
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +1 -23
- package/dist/mercato.js.map +2 -2
- package/package.json +11 -13
- package/src/bin.ts +1 -33
- package/src/lib/__integration__/TC-INT-008.spec.ts +9 -107
- package/src/lib/__tests__/agentic-init.test.ts +5 -41
- package/src/lib/agentic-init.ts +3 -15
- package/src/lib/agentic-setup.ts +224 -530
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +2 -88
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +0 -1
- package/src/lib/generators/__tests__/module-facts.discovery.test.ts +10 -54
- package/src/lib/generators/__tests__/module-subset.test.ts +0 -18
- package/src/lib/generators/extensions/injection-widgets.ts +0 -51
- package/src/lib/generators/module-facts-discovery.ts +7 -58
- package/src/lib/generators/module-facts.ts +46 -1851
- package/src/lib/generators/module-registry.ts +6 -16
- package/src/lib/resolver.ts +0 -3
- package/src/lib/testing/__tests__/integration.test.ts +0 -4
- package/src/lib/testing/integration.ts +0 -5
- package/src/mercato.ts +1 -26
- package/dist/agentic/guides/ai-workflows.md +0 -76
- package/dist/agentic/guides/architecture.md +0 -107
- package/dist/agentic/guides/backend-ui.md +0 -80
- package/dist/agentic/guides/contracts.md +0 -92
- package/dist/agentic/guides/extensions.md +0 -121
- package/dist/agentic/guides/framework-extension-points.md +0 -36
- package/dist/agentic/guides/integrations.md +0 -81
- package/dist/agentic/guides/modules/design_system.md +0 -102
- package/dist/agentic/guides/spec-delivery.md +0 -22
- package/dist/agentic/guides/testing-debugging.md +0 -80
- package/dist/agentic/guides/upstream/AGENTS.md +0 -298
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +0 -316
- package/dist/agentic/guides/upstream/manifest.json +0 -8
- package/dist/agentic/shared/ai/harness/README.md +0 -50
- package/dist/agentic/shared/ai/harness/RELEASE.md +0 -57
- package/dist/agentic/shared/ai/harness/cases.json +0 -13680
- package/dist/agentic/shared/ai/harness/cases.schema.json +0 -133
- package/dist/agentic/shared/ai/harness/fixtures/index.json +0 -49
- package/dist/agentic/shared/ai/harness/fixtures/seeds.json +0 -162
- package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +0 -21
- package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +0 -96
- package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +0 -172
- package/dist/agentic/shared/ai/harness/release-matrix.json +0 -158
- package/dist/agentic/shared/ai/harness/release-result.schema.json +0 -219
- package/dist/agentic/shared/ai/harness/result.schema.json +0 -76
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +0 -12
- package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +0 -73
- package/dist/agentic/shared/ai/harness/validators.json +0 -78
- package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +0 -2121
- package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +0 -1096
- package/dist/agentic/shared/ai/lessons/_template.md +0 -16
- package/dist/agentic/shared/ai/review-checklist.md +0 -36
- package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +0 -21
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +0 -98
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +0 -16
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +0 -53
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +0 -13
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +0 -11
- package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +0 -30
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +0 -12
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +0 -13
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +0 -14
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +0 -28
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +0 -12
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +0 -22
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +0 -12
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +0 -19
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +0 -19
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +0 -13
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +0 -14
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +0 -10
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +0 -17
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +0 -29
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +0 -100
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +0 -16
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +0 -17
- package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +0 -25
- package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +0 -11
- package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +0 -13
- package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +0 -18
- package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +0 -20
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +0 -33
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +0 -40
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +0 -27
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +0 -24
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +0 -16
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +0 -14
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +0 -15
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +0 -12
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +0 -34
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +0 -4
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +0 -11
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +0 -31
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +0 -39
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +0 -43
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +0 -11
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +0 -19
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +0 -172
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +0 -12
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +0 -83
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +0 -21
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +0 -11
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +0 -22
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +0 -13
- package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +0 -41
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +0 -19
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +0 -44
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +0 -39
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +0 -20
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +0 -57
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +0 -11
- package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +0 -486
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +0 -18
- package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +0 -27
- package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +0 -13
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +0 -41
- package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +0 -11
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +0 -15
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +0 -16
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +0 -14
- package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +0 -187
- package/dist/agentic/shared/scripts/check-lessons.mjs +0 -178
- package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +0 -2958
- package/dist/agentic/shared/scripts/execution-sandbox.mjs +0 -329
- package/dist/agentic/shared/scripts/framework-context.mjs +0 -888
- package/dist/agentic/shared/scripts/install-skills.mjs +0 -1029
- package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +0 -222
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +0 -1774
- package/dist/lib/generators/module-extension-facts.js +0 -1840
- package/dist/lib/generators/module-extension-facts.js.map +0 -7
- package/dist/lib/generators/module-fact-sources.js +0 -70
- package/dist/lib/generators/module-fact-sources.js.map +0 -7
- package/dist/lib/generators/module-override-targets.js +0 -688
- package/dist/lib/generators/module-override-targets.js.map +0 -7
- package/dist/lib/load-env.js +0 -24
- package/dist/lib/load-env.js.map +0 -7
- package/dist/lib/telemetry-init.js +0 -358
- package/dist/lib/telemetry-init.js.map +0 -7
- package/src/lib/__tests__/agentic-setup.ownership.test.ts +0 -386
- package/src/lib/__tests__/injection-widget-id-validation.test.ts +0 -184
- package/src/lib/__tests__/load-env.test.ts +0 -65
- package/src/lib/__tests__/telemetry-init.test.ts +0 -298
- package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +0 -92
- package/src/lib/generators/__tests__/module-extension-activations.test.ts +0 -762
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +0 -404
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +0 -108
- package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +0 -561
- package/src/lib/generators/__tests__/module-facts.source-links.test.ts +0 -119
- package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +0 -149
- package/src/lib/generators/__tests__/module-override-targets.test.ts +0 -304
- package/src/lib/generators/module-extension-facts.ts +0 -2365
- package/src/lib/generators/module-fact-sources.ts +0 -108
- package/src/lib/generators/module-override-targets.ts +0 -863
- package/src/lib/load-env.ts +0 -30
- package/src/lib/telemetry-init.ts +0 -461
|
@@ -2,23 +2,6 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import ts from "typescript-js";
|
|
4
4
|
import { toSnake } from "../utils.js";
|
|
5
|
-
import { extractCommandIdsFromSource } from "./module-registry.js";
|
|
6
|
-
import { MODULE_CODE_EXTENSIONS } from "./scanner.js";
|
|
7
|
-
import {
|
|
8
|
-
assertNoUnresolvedExtensionTargets,
|
|
9
|
-
correlateIncomingExtensions,
|
|
10
|
-
correlateModuleExtensionFacts,
|
|
11
|
-
extractActivationTargetOwners,
|
|
12
|
-
extractKnownApiRouteIds,
|
|
13
|
-
extractKnownCommandIds,
|
|
14
|
-
extractModuleExtensionFacts,
|
|
15
|
-
renderFrameworkExtensionPointsMarkdown,
|
|
16
|
-
withModuleExtensionFactExtractionCache
|
|
17
|
-
} from "./module-extension-facts.js";
|
|
18
|
-
import {
|
|
19
|
-
collectModuleOverrideTargets
|
|
20
|
-
} from "./module-override-targets.js";
|
|
21
|
-
import { buildFactSourceLookup } from "./module-fact-sources.js";
|
|
22
5
|
function readSourceFile(filePath) {
|
|
23
6
|
if (!fs.existsSync(filePath)) return null;
|
|
24
7
|
const source = fs.readFileSync(filePath, "utf8");
|
|
@@ -84,38 +67,10 @@ function collectCustomFieldEntityIds(ceFilePath) {
|
|
|
84
67
|
if (!ceFilePath) return result;
|
|
85
68
|
const sourceFile = readSourceFile(ceFilePath);
|
|
86
69
|
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
70
|
const visit = (node) => {
|
|
113
71
|
if (ts.isObjectLiteralExpression(node)) {
|
|
114
|
-
const
|
|
115
|
-
if (
|
|
116
|
-
const id = readEntityId(initializer);
|
|
117
|
-
if (id) result.add(id);
|
|
118
|
-
}
|
|
72
|
+
const id = readStringPropertyInitializer(node, "id");
|
|
73
|
+
if (id && id.includes(":")) result.add(id);
|
|
119
74
|
}
|
|
120
75
|
node.forEachChild(visit);
|
|
121
76
|
};
|
|
@@ -257,11 +212,7 @@ function extractEvents(eventsFilePath) {
|
|
|
257
212
|
category: category ?? null,
|
|
258
213
|
entity: entity ?? null
|
|
259
214
|
};
|
|
260
|
-
const clientBroadcast = readBooleanPropertyInitializer(element, "clientBroadcast");
|
|
261
|
-
const portalBroadcast = readBooleanPropertyInitializer(element, "portalBroadcast");
|
|
262
215
|
if (label !== void 0) fact.label = label;
|
|
263
|
-
if (clientBroadcast !== void 0) fact.clientBroadcast = clientBroadcast;
|
|
264
|
-
if (portalBroadcast !== void 0) fact.portalBroadcast = portalBroadcast;
|
|
265
216
|
facts.push(fact);
|
|
266
217
|
}
|
|
267
218
|
return facts;
|
|
@@ -351,9 +302,9 @@ function parseApiRouteEntry(entryLiteral) {
|
|
|
351
302
|
}
|
|
352
303
|
}
|
|
353
304
|
}
|
|
354
|
-
return { path: routePath, methods, auth
|
|
305
|
+
return { path: routePath, methods, auth };
|
|
355
306
|
}
|
|
356
|
-
function extractApiRoutes(moduleId, registrySource, registryDescription,
|
|
307
|
+
function extractApiRoutes(moduleId, registrySource, registryDescription, warnings) {
|
|
357
308
|
if (registrySource == null) {
|
|
358
309
|
warnings.push(`[module-facts] module registry unavailable (${registryDescription}); API route auth omitted for ${moduleId}`);
|
|
359
310
|
return [];
|
|
@@ -377,7 +328,7 @@ function extractApiRoutes(moduleId, registrySource, registryDescription, routeSo
|
|
|
377
328
|
const route = parseApiRouteEntry(element);
|
|
378
329
|
if (route && !seenPaths.has(route.path)) {
|
|
379
330
|
seenPaths.add(route.path);
|
|
380
|
-
routes.push(
|
|
331
|
+
routes.push(route);
|
|
381
332
|
}
|
|
382
333
|
}
|
|
383
334
|
}
|
|
@@ -525,195 +476,31 @@ function extractCli(cliFilePath, warnings) {
|
|
|
525
476
|
function listSourceFilesRecursive(directory) {
|
|
526
477
|
const files = [];
|
|
527
478
|
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
528
|
-
if (entry.name === "__tests__" || entry.name === "
|
|
479
|
+
if (entry.name === "__tests__" || entry.name === "node_modules") continue;
|
|
529
480
|
const fullPath = path.join(directory, entry.name);
|
|
530
481
|
if (entry.isDirectory()) {
|
|
531
482
|
files.push(...listSourceFilesRecursive(fullPath));
|
|
532
|
-
} else if (/\.tsx?$/.test(entry.name) && !entry.name.endsWith(".d.ts")
|
|
483
|
+
} else if (/\.tsx?$/.test(entry.name) && !entry.name.endsWith(".d.ts")) {
|
|
533
484
|
files.push(fullPath);
|
|
534
485
|
}
|
|
535
486
|
}
|
|
536
487
|
return files;
|
|
537
488
|
}
|
|
538
|
-
function
|
|
539
|
-
|
|
540
|
-
}
|
|
541
|
-
function toPortableSourcePath(moduleRoot, sourceRoot, filePath) {
|
|
542
|
-
const relativePath = path.relative(moduleRoot, filePath).split(path.sep).join("/");
|
|
543
|
-
return path.posix.join(sourceRoot, relativePath);
|
|
544
|
-
}
|
|
545
|
-
function sourceHasDefaultExport(sourceFile) {
|
|
546
|
-
return sourceFile.statements.some((statement) => {
|
|
547
|
-
if (ts.isExportAssignment(statement) && !statement.isExportEquals) return true;
|
|
548
|
-
if (!ts.isFunctionDeclaration(statement) && !ts.isClassDeclaration(statement)) return false;
|
|
549
|
-
return statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword) ?? false;
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
function readRouteMetadataPath(sourceFile) {
|
|
553
|
-
const metadata = findObjectLiteralDeclaration(sourceFile, "metadata");
|
|
554
|
-
return metadata ? readStringPropertyInitializer(metadata, "path") ?? null : null;
|
|
555
|
-
}
|
|
556
|
-
function extractApiRouteSourcePaths(moduleId, moduleRoot, sourceRoot) {
|
|
557
|
-
const apiRoot = path.join(moduleRoot, "api");
|
|
558
|
-
const sources = /* @__PURE__ */ new Map();
|
|
559
|
-
if (!fs.existsSync(apiRoot)) return sources;
|
|
560
|
-
const methodDirectories = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete"]);
|
|
561
|
-
for (const filePath of listSourceFilesRecursive(apiRoot)) {
|
|
562
|
-
const relativePath = path.relative(apiRoot, filePath).split(path.sep).join("/");
|
|
563
|
-
const segments = relativePath.split("/");
|
|
564
|
-
const fileName = segments.pop();
|
|
565
|
-
const fileStem = fileName.replace(/\.tsx?$/, "");
|
|
566
|
-
let routeSegments;
|
|
567
|
-
if (fileStem === "route") {
|
|
568
|
-
routeSegments = segments;
|
|
569
|
-
} else if (segments[0] && methodDirectories.has(segments[0].toLowerCase())) {
|
|
570
|
-
routeSegments = [...segments.slice(1), fileStem];
|
|
571
|
-
} else {
|
|
572
|
-
routeSegments = [...segments, fileStem];
|
|
573
|
-
}
|
|
574
|
-
const defaultPath = `/${[moduleId, ...routeSegments].filter(Boolean).join("/")}`;
|
|
575
|
-
const sourceFile = readSourceFile(filePath);
|
|
576
|
-
const routePath = sourceFile ? readRouteMetadataPath(sourceFile) ?? defaultPath : defaultPath;
|
|
577
|
-
sources.set(routePath, toPortableSourcePath(moduleRoot, sourceRoot, filePath));
|
|
578
|
-
}
|
|
579
|
-
return sources;
|
|
580
|
-
}
|
|
581
|
-
function extractModulePages(moduleId, moduleRoot, sourceRoot, surface) {
|
|
582
|
-
const pageRoot = path.join(moduleRoot, surface);
|
|
583
|
-
if (!fs.existsSync(pageRoot)) return [];
|
|
584
|
-
const pages = [];
|
|
585
|
-
const seen = /* @__PURE__ */ new Set();
|
|
586
|
-
for (const filePath of listSourceFilesRecursive(pageRoot)) {
|
|
587
|
-
if (!filePath.endsWith(".tsx")) continue;
|
|
588
|
-
const relativePath = path.relative(pageRoot, filePath).split(path.sep).join("/");
|
|
589
|
-
const segments = relativePath.split("/");
|
|
590
|
-
const fileName = segments.pop();
|
|
591
|
-
const fileStem = fileName.replace(/\.tsx$/, "");
|
|
592
|
-
const isModernPage = fileStem === "page";
|
|
593
|
-
if (!isModernPage && (fileStem === "meta" || fileStem.endsWith(".meta") || /^[A-Z]/.test(fileStem))) continue;
|
|
594
|
-
const sourceFile = readSourceFile(filePath);
|
|
595
|
-
if (!sourceFile || !sourceHasDefaultExport(sourceFile)) continue;
|
|
596
|
-
const routeSegments = isModernPage ? segments : [...segments, fileStem];
|
|
597
|
-
const routePath = surface === "frontend" ? `/${routeSegments.filter(Boolean).join("/")}` : isModernPage ? `/backend/${routeSegments.join("/") || moduleId}` : `/backend/${routeSegments[0] === moduleId ? routeSegments.filter(Boolean).join("/") : [moduleId, ...routeSegments].filter(Boolean).join("/")}`;
|
|
598
|
-
if (seen.has(routePath)) continue;
|
|
599
|
-
seen.add(routePath);
|
|
600
|
-
const metadataFilePath = resolvePageMetadataFile(path.dirname(filePath));
|
|
601
|
-
const metadataSourceFile = metadataFilePath ? readSourceFile(metadataFilePath) : sourceFile;
|
|
602
|
-
const metadata = metadataSourceFile ? readPageMetadata(metadataSourceFile) : void 0;
|
|
603
|
-
pages.push({
|
|
604
|
-
path: routePath,
|
|
605
|
-
sourcePath: toPortableSourcePath(moduleRoot, sourceRoot, filePath),
|
|
606
|
-
...metadataFilePath ? { metadataSourcePath: toPortableSourcePath(moduleRoot, sourceRoot, metadataFilePath) } : {},
|
|
607
|
-
...metadata ? { metadata } : {}
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
return pages.sort((left, right) => left.path.localeCompare(right.path));
|
|
611
|
-
}
|
|
612
|
-
function findAncestorVariableDeclaration(node) {
|
|
613
|
-
let current = node.parent;
|
|
614
|
-
while (current) {
|
|
615
|
-
if (ts.isVariableDeclaration(current)) return current;
|
|
616
|
-
current = current.parent;
|
|
617
|
-
}
|
|
618
|
-
return null;
|
|
619
|
-
}
|
|
620
|
-
function findAncestorCallExpression(node) {
|
|
621
|
-
let current = node.parent;
|
|
622
|
-
while (current) {
|
|
623
|
-
if (ts.isCallExpression(current)) return current;
|
|
624
|
-
if (ts.isVariableDeclaration(current) || ts.isStatement(current)) return null;
|
|
625
|
-
current = current.parent;
|
|
626
|
-
}
|
|
627
|
-
return null;
|
|
628
|
-
}
|
|
629
|
-
function extractNamedAiFacts(filePaths, moduleRoot, sourceRoot, propertyName) {
|
|
630
|
-
const facts = [];
|
|
631
|
-
const seen = /* @__PURE__ */ new Set();
|
|
632
|
-
for (const filePath of filePaths) {
|
|
633
|
-
const sourceFile = readSourceFile(filePath);
|
|
634
|
-
if (!sourceFile) continue;
|
|
635
|
-
const initializers = buildVariableInitializerMap(sourceFile);
|
|
636
|
-
const readDefinitionValue = (objectLiteral) => {
|
|
637
|
-
const initializer = getObjectPropertyInitializer(objectLiteral, propertyName);
|
|
638
|
-
if (!initializer) return void 0;
|
|
639
|
-
const resolved = unwrapExpression(initializer);
|
|
640
|
-
if (ts.isStringLiteralLike(resolved)) return resolved.text;
|
|
641
|
-
if (ts.isIdentifier(resolved)) {
|
|
642
|
-
const declarationInitializer = initializers.get(resolved.text);
|
|
643
|
-
if (declarationInitializer) {
|
|
644
|
-
const declarationValue = unwrapExpression(declarationInitializer);
|
|
645
|
-
if (ts.isStringLiteralLike(declarationValue)) return declarationValue.text;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
return void 0;
|
|
649
|
-
};
|
|
650
|
-
const visit = (node) => {
|
|
651
|
-
if (ts.isObjectLiteralExpression(node)) {
|
|
652
|
-
const value = readDefinitionValue(node);
|
|
653
|
-
if (value && !seen.has(value)) {
|
|
654
|
-
const declaration = findAncestorVariableDeclaration(node);
|
|
655
|
-
const declarationName = declaration && ts.isIdentifier(declaration.name) ? declaration.name.text : "";
|
|
656
|
-
const declarationType = declaration?.type?.getText(sourceFile) ?? "";
|
|
657
|
-
const call = findAncestorCallExpression(node);
|
|
658
|
-
const callee = call?.expression.getText(sourceFile) ?? "";
|
|
659
|
-
const isDefinition = propertyName === "name" ? /AiTool/.test(declarationType) || /tool$/i.test(declarationName) || /AiTool/.test(callee) : /AiAgentDefinition/.test(declarationType) || /agent$/i.test(declarationName) || /defineAiAgent/.test(callee);
|
|
660
|
-
if (isDefinition) {
|
|
661
|
-
seen.add(value);
|
|
662
|
-
facts.push({
|
|
663
|
-
value,
|
|
664
|
-
sourcePath: toPortableSourcePath(moduleRoot, sourceRoot, filePath)
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
node.forEachChild(visit);
|
|
670
|
-
};
|
|
671
|
-
sourceFile.forEachChild(visit);
|
|
672
|
-
}
|
|
673
|
-
return facts.sort((left, right) => left.value.localeCompare(right.value));
|
|
674
|
-
}
|
|
675
|
-
function extractAiTools(moduleRoot, sourceRoot) {
|
|
676
|
-
const files = /* @__PURE__ */ new Set();
|
|
677
|
-
const rootFile = resolveConventionFile(moduleRoot, "ai-tools");
|
|
678
|
-
if (rootFile) files.add(rootFile);
|
|
679
|
-
const toolsDirectory = path.join(moduleRoot, "ai-tools");
|
|
680
|
-
if (fs.existsSync(toolsDirectory)) {
|
|
681
|
-
for (const filePath of listSourceFilesRecursive(toolsDirectory)) files.add(filePath);
|
|
682
|
-
}
|
|
683
|
-
return extractNamedAiFacts([...files], moduleRoot, sourceRoot, "name").map((fact) => ({ name: fact.value, sourcePath: fact.sourcePath }));
|
|
684
|
-
}
|
|
685
|
-
function extractAiAgents(moduleRoot, sourceRoot) {
|
|
686
|
-
const agentsFile = resolveConventionFile(moduleRoot, "ai-agents");
|
|
687
|
-
if (!agentsFile) return [];
|
|
688
|
-
return extractNamedAiFacts([agentsFile], moduleRoot, sourceRoot, "id").map((fact) => ({ id: fact.value, sourcePath: fact.sourcePath }));
|
|
689
|
-
}
|
|
690
|
-
function extractTableIds(moduleRoot) {
|
|
691
|
-
if (!fs.existsSync(moduleRoot)) return [];
|
|
489
|
+
function extractTableIds(backendDir) {
|
|
490
|
+
if (!fs.existsSync(backendDir)) return [];
|
|
692
491
|
const tableIds = [];
|
|
693
492
|
const seen = /* @__PURE__ */ new Set();
|
|
694
|
-
const
|
|
695
|
-
const current = unwrapExpression(expression);
|
|
696
|
-
if (ts.isStringLiteralLike(current)) return [current.text];
|
|
697
|
-
if (ts.isConditionalExpression(current)) {
|
|
698
|
-
return [
|
|
699
|
-
...collectLiteralValues(current.whenTrue),
|
|
700
|
-
...collectLiteralValues(current.whenFalse)
|
|
701
|
-
];
|
|
702
|
-
}
|
|
703
|
-
return [];
|
|
704
|
-
};
|
|
705
|
-
for (const filePath of listSourceFilesRecursive(moduleRoot)) {
|
|
493
|
+
for (const filePath of listSourceFilesRecursive(backendDir)) {
|
|
706
494
|
const sourceFile = readSourceFile(filePath);
|
|
707
495
|
if (!sourceFile) continue;
|
|
708
496
|
const visit = (node) => {
|
|
709
497
|
if (ts.isPropertyAssignment(node)) {
|
|
710
498
|
const propertyName = getPropertyName(node);
|
|
711
|
-
if (propertyName === "tableId" || propertyName === "extensionTableId") {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
}
|
|
499
|
+
if ((propertyName === "tableId" || propertyName === "extensionTableId") && ts.isStringLiteralLike(node.initializer)) {
|
|
500
|
+
const value = node.initializer.text;
|
|
501
|
+
if (value && !seen.has(value)) {
|
|
502
|
+
seen.add(value);
|
|
503
|
+
tableIds.push(value);
|
|
717
504
|
}
|
|
718
505
|
}
|
|
719
506
|
}
|
|
@@ -738,587 +525,12 @@ function extractModuleMeta(indexFilePath) {
|
|
|
738
525
|
description: readStringPropertyInitializer(metadata, "description") ?? null
|
|
739
526
|
};
|
|
740
527
|
}
|
|
741
|
-
function nodeLine(sourceFile, node) {
|
|
742
|
-
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
743
|
-
}
|
|
744
|
-
function readPropertyNameText(name) {
|
|
745
|
-
if (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) return name.text;
|
|
746
|
-
return void 0;
|
|
747
|
-
}
|
|
748
|
-
function readMethodBearingPropertyNames(objectLiteral) {
|
|
749
|
-
const names = [];
|
|
750
|
-
for (const property of objectLiteral.properties) {
|
|
751
|
-
if (ts.isMethodDeclaration(property)) {
|
|
752
|
-
const name = readPropertyNameText(property.name);
|
|
753
|
-
if (name) names.push(name);
|
|
754
|
-
continue;
|
|
755
|
-
}
|
|
756
|
-
if (ts.isPropertyAssignment(property)) {
|
|
757
|
-
const name = readPropertyNameText(property.name);
|
|
758
|
-
if (!name) continue;
|
|
759
|
-
const initializer = unwrapExpression(property.initializer);
|
|
760
|
-
if (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) names.push(name);
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
return names.sort((left, right) => left.localeCompare(right));
|
|
764
|
-
}
|
|
765
|
-
function readObjectKeyNames(objectLiteral) {
|
|
766
|
-
const names = [];
|
|
767
|
-
for (const property of objectLiteral.properties) {
|
|
768
|
-
const name = getPropertyName(property);
|
|
769
|
-
if (name) names.push(name);
|
|
770
|
-
}
|
|
771
|
-
return names.sort((left, right) => left.localeCompare(right));
|
|
772
|
-
}
|
|
773
|
-
function mapDiRegistrationKind(base) {
|
|
774
|
-
switch (base) {
|
|
775
|
-
case "asFunction":
|
|
776
|
-
return "function";
|
|
777
|
-
case "asClass":
|
|
778
|
-
return "class";
|
|
779
|
-
case "asValue":
|
|
780
|
-
return "value";
|
|
781
|
-
case "aliasTo":
|
|
782
|
-
return "alias";
|
|
783
|
-
default:
|
|
784
|
-
return null;
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
function readDiChainMetadata(initializer) {
|
|
788
|
-
const result = {};
|
|
789
|
-
let current = unwrapExpression(initializer);
|
|
790
|
-
while (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {
|
|
791
|
-
const method = current.expression.name.text;
|
|
792
|
-
if ((method === "singleton" || method === "scoped" || method === "transient") && !result.lifetime) {
|
|
793
|
-
result.lifetime = method;
|
|
794
|
-
} else if (method === "proxy" && !result.injectionMode) {
|
|
795
|
-
result.injectionMode = "proxy";
|
|
796
|
-
} else if (method === "classic" && !result.injectionMode) {
|
|
797
|
-
result.injectionMode = "classic";
|
|
798
|
-
}
|
|
799
|
-
current = unwrapExpression(current.expression.expression);
|
|
800
|
-
}
|
|
801
|
-
return result;
|
|
802
|
-
}
|
|
803
|
-
function readDiProviderSymbol(initializer, kind) {
|
|
804
|
-
let current = unwrapExpression(initializer);
|
|
805
|
-
while (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {
|
|
806
|
-
current = unwrapExpression(current.expression.expression);
|
|
807
|
-
}
|
|
808
|
-
if (!ts.isCallExpression(current)) return void 0;
|
|
809
|
-
const argument = current.arguments[0];
|
|
810
|
-
if (!argument) return void 0;
|
|
811
|
-
if (kind === "value") return void 0;
|
|
812
|
-
if (kind === "alias" && ts.isStringLiteralLike(argument)) return argument.text;
|
|
813
|
-
if ((kind === "function" || kind === "class") && ts.isIdentifier(argument)) return argument.text;
|
|
814
|
-
return void 0;
|
|
815
|
-
}
|
|
816
|
-
function extractDiRegistrationFacts(diFilePath, sourcePath) {
|
|
817
|
-
if (!diFilePath) return { facts: [], unresolvedTokens: [] };
|
|
818
|
-
const sourceFile = readSourceFile(diFilePath);
|
|
819
|
-
if (!sourceFile) return { facts: [], unresolvedTokens: [] };
|
|
820
|
-
const facts = [];
|
|
821
|
-
const unresolvedTokens = [];
|
|
822
|
-
const visit = (node) => {
|
|
823
|
-
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "register") {
|
|
824
|
-
const argument = node.arguments[0];
|
|
825
|
-
if (argument && ts.isObjectLiteralExpression(argument)) {
|
|
826
|
-
for (const property of argument.properties) {
|
|
827
|
-
if (!ts.isPropertyAssignment(property)) continue;
|
|
828
|
-
const token = getPropertyName(property);
|
|
829
|
-
if (!token) continue;
|
|
830
|
-
const kind = mapDiRegistrationKind(detectAwilixRegistrationKind(property.initializer));
|
|
831
|
-
if (!kind) {
|
|
832
|
-
if (!unresolvedTokens.includes(token)) unresolvedTokens.push(token);
|
|
833
|
-
continue;
|
|
834
|
-
}
|
|
835
|
-
const chain = readDiChainMetadata(property.initializer);
|
|
836
|
-
const providerSymbol = readDiProviderSymbol(property.initializer, kind);
|
|
837
|
-
facts.push({
|
|
838
|
-
token,
|
|
839
|
-
registrationKind: kind,
|
|
840
|
-
...providerSymbol ? { providerSymbol } : {},
|
|
841
|
-
...chain.lifetime ? { lifetime: chain.lifetime } : {},
|
|
842
|
-
...chain.injectionMode ? { injectionMode: chain.injectionMode } : {},
|
|
843
|
-
source: { sourcePath, exportName: token, line: nodeLine(sourceFile, property) }
|
|
844
|
-
});
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
node.forEachChild(visit);
|
|
849
|
-
};
|
|
850
|
-
sourceFile.forEachChild(visit);
|
|
851
|
-
return { facts, unresolvedTokens };
|
|
852
|
-
}
|
|
853
|
-
function deriveLegacyDiTokens(facts) {
|
|
854
|
-
const tokens = [];
|
|
855
|
-
const seen = /* @__PURE__ */ new Set();
|
|
856
|
-
for (const fact of facts) {
|
|
857
|
-
if (fact.registrationKind !== "function" && fact.registrationKind !== "class") continue;
|
|
858
|
-
if (seen.has(fact.token)) continue;
|
|
859
|
-
seen.add(fact.token);
|
|
860
|
-
tokens.push(fact.token);
|
|
861
|
-
}
|
|
862
|
-
return tokens;
|
|
863
|
-
}
|
|
864
|
-
function dedupeOwnedContractFacts(facts) {
|
|
865
|
-
const byId = /* @__PURE__ */ new Map();
|
|
866
|
-
for (const fact of facts) {
|
|
867
|
-
const existing = byId.get(fact.id);
|
|
868
|
-
if (!existing) {
|
|
869
|
-
byId.set(fact.id, fact);
|
|
870
|
-
continue;
|
|
871
|
-
}
|
|
872
|
-
if (fact.source.sourcePath.localeCompare(existing.source.sourcePath) < 0) byId.set(fact.id, fact);
|
|
873
|
-
}
|
|
874
|
-
return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
875
|
-
}
|
|
876
|
-
const PAGE_CONTEXT_VALUES = /* @__PURE__ */ new Set(["main", "admin", "settings", "profile"]);
|
|
877
|
-
function readAliasedStringProperty(metadata, preferred, fallback) {
|
|
878
|
-
return readStringPropertyInitializer(metadata, preferred) ?? readStringPropertyInitializer(metadata, fallback);
|
|
879
|
-
}
|
|
880
|
-
function readNumericProperty(metadata, propertyName) {
|
|
881
|
-
const initializer = getObjectPropertyInitializer(metadata, propertyName);
|
|
882
|
-
if (!initializer || !ts.isNumericLiteral(initializer)) return void 0;
|
|
883
|
-
return Number(initializer.text);
|
|
884
|
-
}
|
|
885
|
-
function readPageMetadata(sourceFile) {
|
|
886
|
-
const metadata = findObjectLiteralDeclaration(sourceFile, "metadata");
|
|
887
|
-
if (!metadata) return void 0;
|
|
888
|
-
const result = {};
|
|
889
|
-
const requireAuth = readBooleanPropertyInitializer(metadata, "requireAuth");
|
|
890
|
-
if (requireAuth !== void 0) result.requireAuth = requireAuth;
|
|
891
|
-
const requireCustomerAuth = readBooleanPropertyInitializer(metadata, "requireCustomerAuth");
|
|
892
|
-
if (requireCustomerAuth !== void 0) result.requireCustomerAuth = requireCustomerAuth;
|
|
893
|
-
const requireFeatures = readStringArrayPropertyInitializer(metadata, "requireFeatures");
|
|
894
|
-
if (requireFeatures && requireFeatures.length > 0) result.requireFeatures = requireFeatures;
|
|
895
|
-
const requireCustomerFeatures = readStringArrayPropertyInitializer(metadata, "requireCustomerFeatures");
|
|
896
|
-
if (requireCustomerFeatures && requireCustomerFeatures.length > 0) {
|
|
897
|
-
result.requireCustomerFeatures = requireCustomerFeatures;
|
|
898
|
-
}
|
|
899
|
-
const navHidden = readBooleanPropertyInitializer(metadata, "navHidden");
|
|
900
|
-
if (navHidden !== void 0) result.navHidden = navHidden;
|
|
901
|
-
const navGroup = readAliasedStringProperty(metadata, "pageGroup", "group");
|
|
902
|
-
if (navGroup) result.navGroup = navGroup;
|
|
903
|
-
const navGroupKey = readAliasedStringProperty(metadata, "pageGroupKey", "groupKey");
|
|
904
|
-
if (navGroupKey) result.navGroupKey = navGroupKey;
|
|
905
|
-
const navOrder = readNumericProperty(metadata, "pageOrder") ?? readNumericProperty(metadata, "order");
|
|
906
|
-
if (navOrder !== void 0) result.navOrder = navOrder;
|
|
907
|
-
const pageContext = readStringPropertyInitializer(metadata, "pageContext");
|
|
908
|
-
if (pageContext && PAGE_CONTEXT_VALUES.has(pageContext)) {
|
|
909
|
-
result.pageContext = pageContext;
|
|
910
|
-
}
|
|
911
|
-
return Object.keys(result).length > 0 ? result : void 0;
|
|
912
|
-
}
|
|
913
|
-
function resolvePageMetadataFile(pageDirectory) {
|
|
914
|
-
for (const baseName of ["page.meta", "meta"]) {
|
|
915
|
-
for (const extension of MODULE_CODE_EXTENSIONS) {
|
|
916
|
-
const candidate = path.join(pageDirectory, `${baseName}${extension}`);
|
|
917
|
-
if (fs.existsSync(candidate)) return candidate;
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
return null;
|
|
921
|
-
}
|
|
922
|
-
function extractModuleMetadataContract(indexFilePath, moduleId, sourcePath) {
|
|
923
|
-
if (!indexFilePath || !sourcePath) return null;
|
|
924
|
-
const sourceFile = readSourceFile(indexFilePath);
|
|
925
|
-
if (!sourceFile) return null;
|
|
926
|
-
const metadata = findObjectLiteralDeclaration(sourceFile, "metadata");
|
|
927
|
-
if (!metadata) return null;
|
|
928
|
-
const facts = {};
|
|
929
|
-
const name = readStringPropertyInitializer(metadata, "name");
|
|
930
|
-
if (name) facts.name = name;
|
|
931
|
-
const version = readStringPropertyInitializer(metadata, "version");
|
|
932
|
-
if (version) facts.version = version;
|
|
933
|
-
const requires = readStringArrayPropertyInitializer(metadata, "requires");
|
|
934
|
-
if (requires && requires.length > 0) facts.requires = requires;
|
|
935
|
-
const ejectable = readBooleanPropertyInitializer(metadata, "ejectable");
|
|
936
|
-
if (ejectable !== void 0) facts.ejectable = ejectable;
|
|
937
|
-
return {
|
|
938
|
-
kind: "module-metadata",
|
|
939
|
-
id: moduleId,
|
|
940
|
-
source: { sourcePath, exportName: "metadata", line: nodeLine(sourceFile, metadata) },
|
|
941
|
-
...Object.keys(facts).length > 0 ? { metadata: facts } : {}
|
|
942
|
-
};
|
|
943
|
-
}
|
|
944
|
-
function extractCommandContractCandidates(moduleId, moduleRoot, sourceRoot) {
|
|
945
|
-
const commandsRoot = path.join(moduleRoot, "commands");
|
|
946
|
-
if (!fs.existsSync(commandsRoot)) return [];
|
|
947
|
-
const candidates = [];
|
|
948
|
-
for (const filePath of listSourceFilesRecursive(commandsRoot)) {
|
|
949
|
-
if (path.basename(filePath).replace(/\.tsx?$/, "") === "interceptors") continue;
|
|
950
|
-
const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
|
|
951
|
-
for (const id of extractCommandIdsFromSource(filePath)) candidates.push({ id, sourcePath });
|
|
952
|
-
}
|
|
953
|
-
return candidates;
|
|
954
|
-
}
|
|
955
|
-
function deriveWorkerId(moduleId, workersRoot, filePath) {
|
|
956
|
-
const relativePath = path.relative(workersRoot, filePath).split(path.sep).join("/");
|
|
957
|
-
const segments = relativePath.split("/");
|
|
958
|
-
const fileName = segments.pop();
|
|
959
|
-
const fileStem = fileName.replace(/\.tsx?$/, "");
|
|
960
|
-
return [moduleId, "workers", ...segments, fileStem].filter(Boolean).join(":");
|
|
961
|
-
}
|
|
962
|
-
function readResolvedStringProperty(objectLiteral, propertyName, initializers) {
|
|
963
|
-
const initializer = getObjectPropertyInitializer(objectLiteral, propertyName);
|
|
964
|
-
if (!initializer) return void 0;
|
|
965
|
-
const resolved = unwrapExpression(initializer);
|
|
966
|
-
if (ts.isStringLiteralLike(resolved)) return resolved.text;
|
|
967
|
-
if (ts.isIdentifier(resolved)) {
|
|
968
|
-
const declaration = initializers.get(resolved.text);
|
|
969
|
-
if (declaration) {
|
|
970
|
-
const declarationValue = unwrapExpression(declaration);
|
|
971
|
-
if (ts.isStringLiteralLike(declarationValue)) return declarationValue.text;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
return void 0;
|
|
975
|
-
}
|
|
976
|
-
function extractWorkerContracts(moduleId, moduleRoot, sourceRoot) {
|
|
977
|
-
const workersRoot = path.join(moduleRoot, "workers");
|
|
978
|
-
if (!fs.existsSync(workersRoot)) return { facts: [], unresolved: [] };
|
|
979
|
-
const facts = [];
|
|
980
|
-
const unresolved = [];
|
|
981
|
-
for (const filePath of listSourceFilesRecursive(workersRoot)) {
|
|
982
|
-
const sourceFile = readSourceFile(filePath);
|
|
983
|
-
if (!sourceFile) continue;
|
|
984
|
-
const metadata = findObjectLiteralDeclaration(sourceFile, "metadata");
|
|
985
|
-
if (!metadata) continue;
|
|
986
|
-
const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
|
|
987
|
-
const source = { sourcePath, exportName: "metadata", line: nodeLine(sourceFile, metadata) };
|
|
988
|
-
const initializers = buildVariableInitializerMap(sourceFile);
|
|
989
|
-
const workerId = readResolvedStringProperty(metadata, "id", initializers) ?? deriveWorkerId(moduleId, workersRoot, filePath);
|
|
990
|
-
const hasQueueProperty = getObjectPropertyInitializer(metadata, "queue") !== void 0;
|
|
991
|
-
const queue = readResolvedStringProperty(metadata, "queue", initializers);
|
|
992
|
-
if (!hasQueueProperty) {
|
|
993
|
-
unresolved.push({ code: "unresolved-static-contract", kind: "worker", id: workerId, source });
|
|
994
|
-
continue;
|
|
995
|
-
}
|
|
996
|
-
const workerMetadata = {};
|
|
997
|
-
if (queue) workerMetadata.queue = queue;
|
|
998
|
-
else unresolved.push({ code: "unresolved-static-contract", kind: "worker", id: workerId, source });
|
|
999
|
-
const name = readResolvedStringProperty(metadata, "name", initializers);
|
|
1000
|
-
if (name) workerMetadata.name = name;
|
|
1001
|
-
const concurrencyInitializer = getObjectPropertyInitializer(metadata, "concurrency");
|
|
1002
|
-
if (concurrencyInitializer && ts.isNumericLiteral(concurrencyInitializer)) {
|
|
1003
|
-
workerMetadata.concurrency = Number(concurrencyInitializer.text);
|
|
1004
|
-
}
|
|
1005
|
-
facts.push({
|
|
1006
|
-
kind: "worker",
|
|
1007
|
-
id: workerId,
|
|
1008
|
-
source,
|
|
1009
|
-
...Object.keys(workerMetadata).length > 0 ? { metadata: workerMetadata } : {}
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
|
-
return { facts: dedupeOwnedContractFacts(facts), unresolved };
|
|
1013
|
-
}
|
|
1014
|
-
function extractPageMiddlewareContracts(moduleRoot, sourceRoot) {
|
|
1015
|
-
const facts = [];
|
|
1016
|
-
const unresolved = [];
|
|
1017
|
-
for (const surface of ["backend", "frontend"]) {
|
|
1018
|
-
const filePath = resolveConventionFile(path.join(moduleRoot, surface), "middleware");
|
|
1019
|
-
if (!filePath) continue;
|
|
1020
|
-
const sourceFile = readSourceFile(filePath);
|
|
1021
|
-
if (!sourceFile) continue;
|
|
1022
|
-
const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
|
|
1023
|
-
const middlewareArray = findArrayLiteralDeclaration(sourceFile, "middleware") ?? (() => {
|
|
1024
|
-
const defaultExport = findDefaultExportExpression(sourceFile);
|
|
1025
|
-
return defaultExport ? unwrapArrayLiteral(defaultExport) : null;
|
|
1026
|
-
})();
|
|
1027
|
-
if (!middlewareArray) continue;
|
|
1028
|
-
let index = 0;
|
|
1029
|
-
for (const element of middlewareArray.elements) {
|
|
1030
|
-
if (!ts.isObjectLiteralExpression(element)) continue;
|
|
1031
|
-
const middlewareId = readStringPropertyInitializer(element, "id");
|
|
1032
|
-
if (!middlewareId) {
|
|
1033
|
-
unresolved.push({
|
|
1034
|
-
code: "unresolved-static-contract",
|
|
1035
|
-
kind: "page-middleware",
|
|
1036
|
-
id: `${sourcePath}#${index}`,
|
|
1037
|
-
source: { sourcePath, line: nodeLine(sourceFile, element) }
|
|
1038
|
-
});
|
|
1039
|
-
index += 1;
|
|
1040
|
-
continue;
|
|
1041
|
-
}
|
|
1042
|
-
const metadata = { surface };
|
|
1043
|
-
const mode = readStringPropertyInitializer(element, "mode");
|
|
1044
|
-
if (mode) metadata.mode = mode;
|
|
1045
|
-
const priorityInitializer = getObjectPropertyInitializer(element, "priority");
|
|
1046
|
-
if (priorityInitializer && ts.isNumericLiteral(priorityInitializer)) {
|
|
1047
|
-
metadata.priority = Number(priorityInitializer.text);
|
|
1048
|
-
}
|
|
1049
|
-
facts.push({
|
|
1050
|
-
kind: "page-middleware",
|
|
1051
|
-
id: middlewareId,
|
|
1052
|
-
source: { sourcePath, exportName: "middleware", line: nodeLine(sourceFile, element) },
|
|
1053
|
-
metadata
|
|
1054
|
-
});
|
|
1055
|
-
index += 1;
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
return { facts: dedupeOwnedContractFacts(facts), unresolved };
|
|
1059
|
-
}
|
|
1060
|
-
function extractSetupContract(moduleId, setupFilePath, sourcePath) {
|
|
1061
|
-
if (!setupFilePath || !sourcePath) return null;
|
|
1062
|
-
const sourceFile = readSourceFile(setupFilePath);
|
|
1063
|
-
if (!sourceFile) return null;
|
|
1064
|
-
const setupObject = findObjectLiteralDeclaration(sourceFile, "setup") ?? (() => {
|
|
1065
|
-
const defaultExport = findDefaultExportExpression(sourceFile);
|
|
1066
|
-
if (!defaultExport) return null;
|
|
1067
|
-
const unwrapped = unwrapExpression(defaultExport);
|
|
1068
|
-
return ts.isObjectLiteralExpression(unwrapped) ? unwrapped : null;
|
|
1069
|
-
})();
|
|
1070
|
-
if (!setupObject) return null;
|
|
1071
|
-
const hooks = readMethodBearingPropertyNames(setupObject);
|
|
1072
|
-
const metadata = {};
|
|
1073
|
-
if (hooks.length > 0) metadata.hooks = hooks;
|
|
1074
|
-
const roleFeatures = getObjectPropertyInitializer(setupObject, "defaultRoleFeatures");
|
|
1075
|
-
if (roleFeatures && ts.isObjectLiteralExpression(roleFeatures)) {
|
|
1076
|
-
const roles = readObjectKeyNames(roleFeatures);
|
|
1077
|
-
if (roles.length > 0) metadata.roles = roles;
|
|
1078
|
-
}
|
|
1079
|
-
const customerRoleFeatures = getObjectPropertyInitializer(setupObject, "defaultCustomerRoleFeatures");
|
|
1080
|
-
if (customerRoleFeatures && ts.isObjectLiteralExpression(customerRoleFeatures)) {
|
|
1081
|
-
const customerRoles = readObjectKeyNames(customerRoleFeatures);
|
|
1082
|
-
if (customerRoles.length > 0) metadata.customerRoles = customerRoles;
|
|
1083
|
-
}
|
|
1084
|
-
return {
|
|
1085
|
-
kind: "setup",
|
|
1086
|
-
id: `${moduleId}:setup`,
|
|
1087
|
-
source: { sourcePath, exportName: "setup", line: nodeLine(sourceFile, setupObject) },
|
|
1088
|
-
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
1089
|
-
};
|
|
1090
|
-
}
|
|
1091
|
-
function extractEncryptionContracts(encryptionFilePath, sourcePath) {
|
|
1092
|
-
if (!encryptionFilePath || !sourcePath) return [];
|
|
1093
|
-
const sourceFile = readSourceFile(encryptionFilePath);
|
|
1094
|
-
if (!sourceFile) return [];
|
|
1095
|
-
const mapsArray = findArrayLiteralDeclaration(sourceFile, "defaultEncryptionMaps") ?? findArrayLiteralDeclaration(sourceFile, "encryptionMaps");
|
|
1096
|
-
if (!mapsArray) return [];
|
|
1097
|
-
const facts = [];
|
|
1098
|
-
for (const element of mapsArray.elements) {
|
|
1099
|
-
if (!ts.isObjectLiteralExpression(element)) continue;
|
|
1100
|
-
const entityId = readStringPropertyInitializer(element, "entityId");
|
|
1101
|
-
if (!entityId) continue;
|
|
1102
|
-
const fieldsInitializer = getObjectPropertyInitializer(element, "fields");
|
|
1103
|
-
const fields = [];
|
|
1104
|
-
if (fieldsInitializer) {
|
|
1105
|
-
const fieldsArray = unwrapArrayLiteral(fieldsInitializer);
|
|
1106
|
-
if (fieldsArray) {
|
|
1107
|
-
for (const fieldElement of fieldsArray.elements) {
|
|
1108
|
-
if (!ts.isObjectLiteralExpression(fieldElement)) continue;
|
|
1109
|
-
const field = readStringPropertyInitializer(fieldElement, "field");
|
|
1110
|
-
if (field) fields.push(field);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
facts.push({
|
|
1115
|
-
kind: "encryption",
|
|
1116
|
-
id: entityId,
|
|
1117
|
-
source: { sourcePath, exportName: "defaultEncryptionMaps", line: nodeLine(sourceFile, element) },
|
|
1118
|
-
...fields.length > 0 ? { metadata: { fields: fields.sort((left, right) => left.localeCompare(right)) } } : {}
|
|
1119
|
-
});
|
|
1120
|
-
}
|
|
1121
|
-
return dedupeOwnedContractFacts(facts);
|
|
1122
|
-
}
|
|
1123
|
-
function extractCustomEntityContracts(ceFilePath, sourcePath) {
|
|
1124
|
-
if (!ceFilePath || !sourcePath) return [];
|
|
1125
|
-
const entityIds = [...collectCustomFieldEntityIds(ceFilePath)].sort((left, right) => left.localeCompare(right));
|
|
1126
|
-
return entityIds.map((id) => ({
|
|
1127
|
-
kind: "custom-entity",
|
|
1128
|
-
id,
|
|
1129
|
-
source: { sourcePath, exportName: "default" }
|
|
1130
|
-
}));
|
|
1131
|
-
}
|
|
1132
|
-
const AI_OVERRIDE_EXPORTS = [
|
|
1133
|
-
{ exportName: "aiAgentOverrides", target: "agent" },
|
|
1134
|
-
{ exportName: "aiToolOverrides", target: "tool" }
|
|
1135
|
-
];
|
|
1136
|
-
function extractAiExtensionContracts(moduleRoot, sourceRoot) {
|
|
1137
|
-
const facts = [];
|
|
1138
|
-
const sources = [
|
|
1139
|
-
{ basename: "ai-agents", relativeDir: "." },
|
|
1140
|
-
{ basename: "ai-tools", relativeDir: "." },
|
|
1141
|
-
{ basename: "ai-agents.extensions", relativeDir: "." },
|
|
1142
|
-
{ basename: "ai-tools.extensions", relativeDir: "." }
|
|
1143
|
-
];
|
|
1144
|
-
for (const entry of sources) {
|
|
1145
|
-
const filePath = resolveConventionFile(path.join(moduleRoot, entry.relativeDir), entry.basename);
|
|
1146
|
-
if (!filePath) continue;
|
|
1147
|
-
const sourceFile = readSourceFile(filePath);
|
|
1148
|
-
if (!sourceFile) continue;
|
|
1149
|
-
const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
|
|
1150
|
-
const extensionsArray = findArrayLiteralDeclaration(sourceFile, "aiAgentExtensions");
|
|
1151
|
-
if (extensionsArray) {
|
|
1152
|
-
for (const element of extensionsArray.elements) {
|
|
1153
|
-
const objectLiteral = ts.isObjectLiteralExpression(element) ? element : ts.isCallExpression(element) && element.arguments[0] && ts.isObjectLiteralExpression(element.arguments[0]) ? element.arguments[0] : null;
|
|
1154
|
-
if (!objectLiteral) continue;
|
|
1155
|
-
const targetAgentId = readStringPropertyInitializer(objectLiteral, "targetAgentId");
|
|
1156
|
-
if (!targetAgentId) continue;
|
|
1157
|
-
facts.push({
|
|
1158
|
-
kind: "ai-extension",
|
|
1159
|
-
id: `agent-extension:${targetAgentId}`,
|
|
1160
|
-
source: { sourcePath, exportName: "aiAgentExtensions", line: nodeLine(sourceFile, objectLiteral) },
|
|
1161
|
-
metadata: { target: "agent", mode: "extension", targetAgentId }
|
|
1162
|
-
});
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
for (const { exportName, target } of AI_OVERRIDE_EXPORTS) {
|
|
1166
|
-
const overridesObject = findObjectLiteralDeclaration(sourceFile, exportName);
|
|
1167
|
-
if (!overridesObject) continue;
|
|
1168
|
-
for (const property of overridesObject.properties) {
|
|
1169
|
-
const overrideId = getPropertyName(property);
|
|
1170
|
-
if (!overrideId) continue;
|
|
1171
|
-
facts.push({
|
|
1172
|
-
kind: "ai-extension",
|
|
1173
|
-
id: `${target}-override:${overrideId}`,
|
|
1174
|
-
source: { sourcePath, exportName, line: nodeLine(sourceFile, property) },
|
|
1175
|
-
metadata: { target, mode: "override", overrideKey: overrideId }
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
return dedupeOwnedContractFacts(facts);
|
|
1181
|
-
}
|
|
1182
|
-
function extractGeneratorPluginContracts(moduleRoot, sourceRoot) {
|
|
1183
|
-
const filePath = resolveConventionFile(moduleRoot, "generators");
|
|
1184
|
-
if (!filePath) return { facts: [], unresolved: [] };
|
|
1185
|
-
const sourceFile = readSourceFile(filePath);
|
|
1186
|
-
if (!sourceFile) return { facts: [], unresolved: [] };
|
|
1187
|
-
const pluginsArray = findArrayLiteralDeclaration(sourceFile, "generatorPlugins");
|
|
1188
|
-
if (!pluginsArray) return { facts: [], unresolved: [] };
|
|
1189
|
-
const sourcePath = toPortableSourcePath(moduleRoot, sourceRoot, filePath);
|
|
1190
|
-
const initializers = buildVariableInitializerMap(sourceFile);
|
|
1191
|
-
const facts = [];
|
|
1192
|
-
const unresolved = [];
|
|
1193
|
-
let index = 0;
|
|
1194
|
-
for (const element of pluginsArray.elements) {
|
|
1195
|
-
const objectLiteral = resolveToObjectLiteral(element, initializers);
|
|
1196
|
-
if (!objectLiteral) {
|
|
1197
|
-
index += 1;
|
|
1198
|
-
continue;
|
|
1199
|
-
}
|
|
1200
|
-
const pluginId = readStringPropertyInitializer(objectLiteral, "id");
|
|
1201
|
-
if (!pluginId) {
|
|
1202
|
-
unresolved.push({
|
|
1203
|
-
code: "unresolved-static-contract",
|
|
1204
|
-
kind: "generator-plugin",
|
|
1205
|
-
id: `${sourcePath}#${index}`,
|
|
1206
|
-
source: { sourcePath, exportName: "generatorPlugins", line: nodeLine(sourceFile, objectLiteral) }
|
|
1207
|
-
});
|
|
1208
|
-
index += 1;
|
|
1209
|
-
continue;
|
|
1210
|
-
}
|
|
1211
|
-
const metadata = {};
|
|
1212
|
-
const conventionFile = readStringPropertyInitializer(objectLiteral, "conventionFile");
|
|
1213
|
-
if (conventionFile) metadata.conventionFile = conventionFile;
|
|
1214
|
-
const outputFileName = readStringPropertyInitializer(objectLiteral, "outputFileName");
|
|
1215
|
-
if (outputFileName) metadata.outputFileName = outputFileName;
|
|
1216
|
-
facts.push({
|
|
1217
|
-
kind: "generator-plugin",
|
|
1218
|
-
id: pluginId,
|
|
1219
|
-
source: { sourcePath, exportName: "generatorPlugins", line: nodeLine(sourceFile, objectLiteral) },
|
|
1220
|
-
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
1221
|
-
});
|
|
1222
|
-
index += 1;
|
|
1223
|
-
}
|
|
1224
|
-
return { facts: dedupeOwnedContractFacts(facts), unresolved };
|
|
1225
|
-
}
|
|
1226
|
-
function compareSourceRefs(left, right) {
|
|
1227
|
-
return left.sourcePath.localeCompare(right.sourcePath) || (left.line ?? 0) - (right.line ?? 0) || (left.exportName ?? "").localeCompare(right.exportName ?? "");
|
|
1228
|
-
}
|
|
1229
|
-
function sameSourceRef(left, right) {
|
|
1230
|
-
return left.sourcePath === right.sourcePath && (left.line ?? null) === (right.line ?? null) && (left.exportName ?? null) === (right.exportName ?? null);
|
|
1231
|
-
}
|
|
1232
|
-
function provenanceCandidateOrderKey(candidate) {
|
|
1233
|
-
if (candidate.source) {
|
|
1234
|
-
return JSON.stringify([
|
|
1235
|
-
0,
|
|
1236
|
-
candidate.source.sourcePath,
|
|
1237
|
-
candidate.source.line ?? 0,
|
|
1238
|
-
candidate.source.exportName ?? ""
|
|
1239
|
-
]);
|
|
1240
|
-
}
|
|
1241
|
-
return JSON.stringify([1, candidate.factRef?.factSection ?? "", candidate.factRef?.factKey ?? ""]);
|
|
1242
|
-
}
|
|
1243
|
-
function buildProvenanceIndex(candidates) {
|
|
1244
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
1245
|
-
for (const candidate of candidates) {
|
|
1246
|
-
const key = JSON.stringify([candidate.kind, candidate.id]);
|
|
1247
|
-
const group = grouped.get(key) ?? [];
|
|
1248
|
-
group.push(candidate);
|
|
1249
|
-
grouped.set(key, group);
|
|
1250
|
-
}
|
|
1251
|
-
const factSources = [];
|
|
1252
|
-
const diagnostics = [];
|
|
1253
|
-
for (const group of grouped.values()) {
|
|
1254
|
-
const sorted = [...group].sort(
|
|
1255
|
-
(left, right) => provenanceCandidateOrderKey(left).localeCompare(provenanceCandidateOrderKey(right))
|
|
1256
|
-
);
|
|
1257
|
-
const canonical = sorted[0];
|
|
1258
|
-
factSources.push(
|
|
1259
|
-
canonical.factRef ? {
|
|
1260
|
-
kind: canonical.kind,
|
|
1261
|
-
id: canonical.id,
|
|
1262
|
-
factRef: {
|
|
1263
|
-
factSection: canonical.factRef.factSection,
|
|
1264
|
-
...canonical.factRef.factKey === canonical.id ? {} : { factKey: canonical.factRef.factKey }
|
|
1265
|
-
}
|
|
1266
|
-
} : {
|
|
1267
|
-
kind: canonical.kind,
|
|
1268
|
-
id: canonical.id,
|
|
1269
|
-
source: { sourcePath: canonical.source.sourcePath }
|
|
1270
|
-
}
|
|
1271
|
-
);
|
|
1272
|
-
const canonicalKey = provenanceCandidateOrderKey(canonical);
|
|
1273
|
-
for (const rejected of sorted.slice(1)) {
|
|
1274
|
-
if (provenanceCandidateOrderKey(rejected) === canonicalKey) continue;
|
|
1275
|
-
diagnostics.push({
|
|
1276
|
-
code: "duplicate-source",
|
|
1277
|
-
kind: rejected.kind,
|
|
1278
|
-
id: rejected.id,
|
|
1279
|
-
...rejected.source ? { source: rejected.source } : {}
|
|
1280
|
-
});
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
factSources.sort(
|
|
1284
|
-
(left, right) => left.kind.localeCompare(right.kind) || left.id.localeCompare(right.id)
|
|
1285
|
-
);
|
|
1286
|
-
diagnostics.sort(
|
|
1287
|
-
(left, right) => left.code.localeCompare(right.code) || left.kind.localeCompare(right.kind) || left.id.localeCompare(right.id) || compareSourceRefs(left.source ?? { sourcePath: "" }, right.source ?? { sourcePath: "" })
|
|
1288
|
-
);
|
|
1289
|
-
return { factSources, diagnostics };
|
|
1290
|
-
}
|
|
1291
|
-
function buildOwnedContracts(families) {
|
|
1292
|
-
const result = {};
|
|
1293
|
-
for (const [kind, facts] of families) {
|
|
1294
|
-
if (facts.length === 0) continue;
|
|
1295
|
-
result[kind] = facts.map((fact) => ({
|
|
1296
|
-
...fact,
|
|
1297
|
-
source: {
|
|
1298
|
-
sourcePath: fact.source.sourcePath,
|
|
1299
|
-
...fact.source.line ? { line: fact.source.line } : {}
|
|
1300
|
-
}
|
|
1301
|
-
}));
|
|
1302
|
-
}
|
|
1303
|
-
return Object.keys(result).length > 0 ? result : void 0;
|
|
1304
|
-
}
|
|
1305
|
-
const CONTRIBUTION_KIND_TO_SOURCE_KIND = {
|
|
1306
|
-
subscriber: "subscriber"
|
|
1307
|
-
};
|
|
1308
|
-
const REGISTRY_TO_SOURCE_KIND = {
|
|
1309
|
-
vector: "vector",
|
|
1310
|
-
integration: "integration",
|
|
1311
|
-
payment: "integration",
|
|
1312
|
-
shipping: "integration",
|
|
1313
|
-
currency: "integration"
|
|
1314
|
-
};
|
|
1315
528
|
function extractModuleFacts(options) {
|
|
1316
|
-
const { moduleId, coreVersion = null
|
|
529
|
+
const { moduleId, coreVersion = null } = options;
|
|
1317
530
|
const moduleRoot = options.moduleRoot ?? (options.coreSrcRoot ? path.join(options.coreSrcRoot, moduleId) : null);
|
|
1318
531
|
if (!moduleRoot) {
|
|
1319
532
|
throw new Error(`[internal] extractModuleFacts requires moduleRoot or coreSrcRoot for module "${moduleId}"`);
|
|
1320
533
|
}
|
|
1321
|
-
const sourceRoot = toPortableSourceRoot(moduleId, sourcePackage);
|
|
1322
534
|
const entitiesFilePath = resolveConventionFile(path.join(moduleRoot, "data"), "entities") ?? resolveConventionFile(path.join(moduleRoot, "db"), "entities") ?? resolveConventionFile(path.join(moduleRoot, "data"), "schema");
|
|
1323
535
|
const ceFilePath = resolveConventionFile(moduleRoot, "ce");
|
|
1324
536
|
const eventsFilePath = resolveConventionFile(moduleRoot, "events");
|
|
@@ -1328,9 +540,7 @@ function extractModuleFacts(options) {
|
|
|
1328
540
|
const notificationsFilePath = resolveConventionFile(moduleRoot, "notifications");
|
|
1329
541
|
const cliFilePath = resolveConventionFile(moduleRoot, "cli");
|
|
1330
542
|
const indexFilePath = resolveConventionFile(moduleRoot, "index");
|
|
1331
|
-
const
|
|
1332
|
-
const encryptionFilePath = resolveConventionFile(moduleRoot, "encryption");
|
|
1333
|
-
const portableOf = (filePath) => filePath ? toPortableSourcePath(moduleRoot, sourceRoot, filePath) : null;
|
|
543
|
+
const backendDir = path.join(moduleRoot, "backend");
|
|
1334
544
|
const warnings = [];
|
|
1335
545
|
const { title, description } = extractModuleMeta(indexFilePath);
|
|
1336
546
|
const customFieldEntityIds = collectCustomFieldEntityIds(ceFilePath);
|
|
@@ -1338,224 +548,20 @@ function extractModuleFacts(options) {
|
|
|
1338
548
|
const events = extractEvents(eventsFilePath);
|
|
1339
549
|
const aclFeatures = extractAclFeatures(aclFilePath);
|
|
1340
550
|
const { source: registrySource, description: registryDescription } = resolveRegistrySource(options);
|
|
1341
|
-
const
|
|
1342
|
-
const
|
|
1343
|
-
const diRegistrations = extractDiRegistrationFacts(diFilePath, portableOf(diFilePath) ?? "");
|
|
1344
|
-
const diTokens = deriveLegacyDiTokens(diRegistrations.facts);
|
|
1345
|
-
for (const legacyToken of extractDiTokens(diFilePath)) {
|
|
1346
|
-
if (!diTokens.includes(legacyToken)) diTokens.push(legacyToken);
|
|
1347
|
-
}
|
|
551
|
+
const apiRoutes = extractApiRoutes(moduleId, registrySource, registryDescription, warnings);
|
|
552
|
+
const diTokens = extractDiTokens(diFilePath);
|
|
1348
553
|
const searchEntities = extractSearchEntities(searchFilePath, warnings);
|
|
1349
554
|
const notifications = extractNotifications(notificationsFilePath, warnings);
|
|
1350
555
|
const cli = extractCli(cliFilePath, warnings);
|
|
1351
|
-
const cliCommands = cliFilePath ? cli.map((command) => ({
|
|
1352
|
-
command,
|
|
1353
|
-
sourcePath: toPortableSourcePath(moduleRoot, sourceRoot, cliFilePath)
|
|
1354
|
-
})) : [];
|
|
1355
|
-
const backendPages = extractModulePages(moduleId, moduleRoot, sourceRoot, "backend");
|
|
1356
|
-
const frontendPages = extractModulePages(moduleId, moduleRoot, sourceRoot, "frontend");
|
|
1357
|
-
const aiTools = extractAiTools(moduleRoot, sourceRoot);
|
|
1358
|
-
const aiAgents = extractAiAgents(moduleRoot, sourceRoot);
|
|
1359
556
|
const hostTokens = {
|
|
1360
557
|
entityIds: extractHostEntityIds(entities),
|
|
1361
|
-
tableIds: extractTableIds(
|
|
1362
|
-
};
|
|
1363
|
-
const extensionSurfaces = extractModuleExtensionFacts({
|
|
1364
|
-
moduleId,
|
|
1365
|
-
moduleRoot,
|
|
1366
|
-
sourceRoot,
|
|
1367
|
-
entities,
|
|
1368
|
-
events,
|
|
1369
|
-
apiRoutes,
|
|
1370
|
-
searchEntities,
|
|
1371
|
-
notifications,
|
|
1372
|
-
aiTools,
|
|
1373
|
-
aiAgents
|
|
1374
|
-
});
|
|
1375
|
-
const indexSourcePath = portableOf(indexFilePath);
|
|
1376
|
-
const diSourcePath = portableOf(diFilePath);
|
|
1377
|
-
const moduleMetadataFact = extractModuleMetadataContract(indexFilePath, moduleId, indexSourcePath);
|
|
1378
|
-
const commandCandidates = extractCommandContractCandidates(moduleId, moduleRoot, sourceRoot);
|
|
1379
|
-
const commandFacts = dedupeOwnedContractFacts(
|
|
1380
|
-
commandCandidates.map((candidate) => ({
|
|
1381
|
-
kind: "command",
|
|
1382
|
-
id: candidate.id,
|
|
1383
|
-
source: { sourcePath: candidate.sourcePath }
|
|
1384
|
-
}))
|
|
1385
|
-
);
|
|
1386
|
-
const workers = extractWorkerContracts(moduleId, moduleRoot, sourceRoot);
|
|
1387
|
-
const pageMiddleware = extractPageMiddlewareContracts(moduleRoot, sourceRoot);
|
|
1388
|
-
const setupFact = extractSetupContract(moduleId, setupFilePath, portableOf(setupFilePath));
|
|
1389
|
-
const encryptionFacts = extractEncryptionContracts(encryptionFilePath, portableOf(encryptionFilePath));
|
|
1390
|
-
const customEntityFacts = extractCustomEntityContracts(ceFilePath, portableOf(ceFilePath));
|
|
1391
|
-
const aiExtensionFacts = extractAiExtensionContracts(moduleRoot, sourceRoot);
|
|
1392
|
-
const generatorPlugins = extractGeneratorPluginContracts(moduleRoot, sourceRoot);
|
|
1393
|
-
const diContractFacts = dedupeOwnedContractFacts(
|
|
1394
|
-
diRegistrations.facts.map((fact) => ({
|
|
1395
|
-
kind: "di-registration",
|
|
1396
|
-
id: fact.token,
|
|
1397
|
-
source: fact.source,
|
|
1398
|
-
metadata: {
|
|
1399
|
-
registrationKind: fact.registrationKind,
|
|
1400
|
-
...fact.providerSymbol ? { providerSymbol: fact.providerSymbol } : {},
|
|
1401
|
-
...fact.lifetime ? { lifetime: fact.lifetime } : {},
|
|
1402
|
-
...fact.injectionMode ? { injectionMode: fact.injectionMode } : {}
|
|
1403
|
-
}
|
|
1404
|
-
}))
|
|
1405
|
-
);
|
|
1406
|
-
const ownedContracts = buildOwnedContracts([
|
|
1407
|
-
["module-metadata", moduleMetadataFact ? [moduleMetadataFact] : []],
|
|
1408
|
-
["command", commandFacts],
|
|
1409
|
-
["worker", workers.facts],
|
|
1410
|
-
["page-middleware", pageMiddleware.facts],
|
|
1411
|
-
["setup", setupFact ? [setupFact] : []],
|
|
1412
|
-
["encryption", encryptionFacts],
|
|
1413
|
-
["di-registration", diContractFacts],
|
|
1414
|
-
["custom-entity", customEntityFacts],
|
|
1415
|
-
["ai-extension", aiExtensionFacts],
|
|
1416
|
-
["generator-plugin", generatorPlugins.facts]
|
|
1417
|
-
]);
|
|
1418
|
-
const provenanceCandidates = [];
|
|
1419
|
-
const pushSource = (kind, id, source) => {
|
|
1420
|
-
provenanceCandidates.push({ kind, id, source });
|
|
1421
|
-
};
|
|
1422
|
-
const pushRef = (kind, id, source, factSection, factKey) => {
|
|
1423
|
-
provenanceCandidates.push({ kind, id, source, factRef: { factSection, factKey } });
|
|
1424
|
-
};
|
|
1425
|
-
const pushOwnedRefs = (kind, facts2) => {
|
|
1426
|
-
for (const fact of facts2) pushRef(kind, fact.id, fact.source, `ownedContracts.${kind}`, fact.id);
|
|
558
|
+
tableIds: extractTableIds(backendDir)
|
|
1427
559
|
};
|
|
1428
|
-
|
|
1429
|
-
pushRef(
|
|
1430
|
-
"module-metadata",
|
|
1431
|
-
moduleId,
|
|
1432
|
-
moduleMetadataFact.source,
|
|
1433
|
-
"ownedContracts.module-metadata",
|
|
1434
|
-
moduleMetadataFact.id
|
|
1435
|
-
);
|
|
1436
|
-
}
|
|
1437
|
-
if (entitiesFilePath) {
|
|
1438
|
-
const entitiesSourcePath = portableOf(entitiesFilePath);
|
|
1439
|
-
for (const entity of entities) {
|
|
1440
|
-
pushSource("entity", entity.id, { sourcePath: entitiesSourcePath, exportName: entity.class });
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
if (eventsFilePath) {
|
|
1444
|
-
const eventsSourcePath = portableOf(eventsFilePath);
|
|
1445
|
-
for (const event of events) pushSource("event", event.id, { sourcePath: eventsSourcePath, exportName: "events" });
|
|
1446
|
-
}
|
|
1447
|
-
if (aclFilePath) {
|
|
1448
|
-
const aclSourcePath = portableOf(aclFilePath);
|
|
1449
|
-
for (const feature of aclFeatures) pushSource("acl-feature", feature, { sourcePath: aclSourcePath, exportName: "features" });
|
|
1450
|
-
}
|
|
1451
|
-
for (const route of apiRoutes) {
|
|
1452
|
-
if (route.sourcePath) {
|
|
1453
|
-
pushRef("api-route", route.path, { sourcePath: route.sourcePath }, "apiRoutes", route.path);
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
if (searchFilePath) {
|
|
1457
|
-
const searchSourcePath = portableOf(searchFilePath);
|
|
1458
|
-
for (const entityId of searchEntities) pushSource("search", entityId, { sourcePath: searchSourcePath, exportName: "searchConfig" });
|
|
1459
|
-
}
|
|
1460
|
-
if (notificationsFilePath) {
|
|
1461
|
-
const notificationsSourcePath = portableOf(notificationsFilePath);
|
|
1462
|
-
for (const id of notifications) pushSource("notification", id, { sourcePath: notificationsSourcePath });
|
|
1463
|
-
}
|
|
1464
|
-
for (const command of cliCommands) {
|
|
1465
|
-
pushRef("cli-command", command.command, { sourcePath: command.sourcePath }, "cliCommands", command.command);
|
|
1466
|
-
}
|
|
1467
|
-
for (const page of backendPages) {
|
|
1468
|
-
pushRef("backend-page", page.path, { sourcePath: page.sourcePath }, "backendPages", page.path);
|
|
1469
|
-
}
|
|
1470
|
-
for (const page of frontendPages) {
|
|
1471
|
-
pushRef("frontend-page", page.path, { sourcePath: page.sourcePath }, "frontendPages", page.path);
|
|
1472
|
-
}
|
|
1473
|
-
for (const tool of aiTools) pushRef("ai-tool", tool.name, { sourcePath: tool.sourcePath }, "aiTools", tool.name);
|
|
1474
|
-
for (const agent of aiAgents) pushRef("ai-agent", agent.id, { sourcePath: agent.sourcePath }, "aiAgents", agent.id);
|
|
1475
|
-
for (const candidate of commandCandidates) {
|
|
1476
|
-
pushRef("command", candidate.id, { sourcePath: candidate.sourcePath }, "ownedContracts.command", candidate.id);
|
|
1477
|
-
}
|
|
1478
|
-
pushOwnedRefs("worker", workers.facts);
|
|
1479
|
-
pushOwnedRefs("page-middleware", pageMiddleware.facts);
|
|
1480
|
-
if (setupFact) pushOwnedRefs("setup", [setupFact]);
|
|
1481
|
-
pushOwnedRefs("encryption", encryptionFacts);
|
|
1482
|
-
for (const fact of diRegistrations.facts) {
|
|
1483
|
-
pushRef("di-registration", fact.token, fact.source, "ownedContracts.di-registration", fact.token);
|
|
1484
|
-
}
|
|
1485
|
-
pushOwnedRefs("custom-entity", customEntityFacts);
|
|
1486
|
-
pushOwnedRefs("ai-extension", aiExtensionFacts);
|
|
1487
|
-
pushOwnedRefs("generator-plugin", generatorPlugins.facts);
|
|
1488
|
-
const contributionRef = (contributionId) => ({
|
|
1489
|
-
factSection: "extensionSurfaces.contributions",
|
|
1490
|
-
factKey: contributionId
|
|
1491
|
-
});
|
|
1492
|
-
for (const contribution of extensionSurfaces.contributions) {
|
|
1493
|
-
const contributionSource = {
|
|
1494
|
-
sourcePath: contribution.source.path,
|
|
1495
|
-
...contribution.source.symbol ? { exportName: contribution.source.symbol } : {}
|
|
1496
|
-
};
|
|
1497
|
-
const ref = contributionRef(contribution.id);
|
|
1498
|
-
if (contribution.kind === "subscriber") {
|
|
1499
|
-
pushRef("subscriber", contribution.id, contributionSource, ref.factSection, ref.factKey);
|
|
1500
|
-
continue;
|
|
1501
|
-
}
|
|
1502
|
-
if (contribution.kind === "specialized-registry") {
|
|
1503
|
-
const details = contribution.details;
|
|
1504
|
-
const sourceKind = details.registry ? REGISTRY_TO_SOURCE_KIND[details.registry] : void 0;
|
|
1505
|
-
if (sourceKind) {
|
|
1506
|
-
pushRef(
|
|
1507
|
-
sourceKind,
|
|
1508
|
-
details.registryId ?? contribution.id,
|
|
1509
|
-
contributionSource,
|
|
1510
|
-
ref.factSection,
|
|
1511
|
-
ref.factKey
|
|
1512
|
-
);
|
|
1513
|
-
}
|
|
1514
|
-
continue;
|
|
1515
|
-
}
|
|
1516
|
-
const mapped = CONTRIBUTION_KIND_TO_SOURCE_KIND[contribution.kind];
|
|
1517
|
-
if (mapped) pushRef(mapped, contribution.id, contributionSource, ref.factSection, ref.factKey);
|
|
1518
|
-
}
|
|
1519
|
-
for (const host of extensionSurfaces.hosts) {
|
|
1520
|
-
provenanceCandidates.push({
|
|
1521
|
-
kind: "extension-host",
|
|
1522
|
-
id: host.key,
|
|
1523
|
-
...host.source.kind === "fact-ref" ? {} : { source: { sourcePath: host.source.path } },
|
|
1524
|
-
factRef: { factSection: "extensionSurfaces.hosts", factKey: host.key }
|
|
1525
|
-
});
|
|
1526
|
-
}
|
|
1527
|
-
for (const contribution of extensionSurfaces.contributions) {
|
|
1528
|
-
pushRef(
|
|
1529
|
-
"extension-contribution",
|
|
1530
|
-
contribution.id,
|
|
1531
|
-
{ sourcePath: contribution.source.path },
|
|
1532
|
-
"extensionSurfaces.contributions",
|
|
1533
|
-
contribution.id
|
|
1534
|
-
);
|
|
1535
|
-
}
|
|
1536
|
-
const provenance = buildProvenanceIndex(provenanceCandidates);
|
|
1537
|
-
const factDiagnostics = [
|
|
1538
|
-
...provenance.diagnostics,
|
|
1539
|
-
...workers.unresolved,
|
|
1540
|
-
...pageMiddleware.unresolved,
|
|
1541
|
-
...generatorPlugins.unresolved,
|
|
1542
|
-
...diRegistrations.unresolvedTokens.map((token) => ({
|
|
1543
|
-
code: "unresolved-static-contract",
|
|
1544
|
-
kind: "di-registration",
|
|
1545
|
-
id: token,
|
|
1546
|
-
...diSourcePath ? { source: { sourcePath: diSourcePath, exportName: token } } : {}
|
|
1547
|
-
}))
|
|
1548
|
-
].sort(
|
|
1549
|
-
(left, right) => left.code.localeCompare(right.code) || left.kind.localeCompare(right.kind) || left.id.localeCompare(right.id)
|
|
1550
|
-
);
|
|
1551
|
-
const facts = {
|
|
560
|
+
return {
|
|
1552
561
|
module: moduleId,
|
|
1553
562
|
title,
|
|
1554
563
|
description,
|
|
1555
564
|
coreVersion,
|
|
1556
|
-
sourcePackage,
|
|
1557
|
-
sourceVersion,
|
|
1558
|
-
sourceRoot,
|
|
1559
565
|
entities,
|
|
1560
566
|
events,
|
|
1561
567
|
aclFeatures,
|
|
@@ -1565,54 +571,33 @@ function extractModuleFacts(options) {
|
|
|
1565
571
|
hostTokens,
|
|
1566
572
|
notifications,
|
|
1567
573
|
cli,
|
|
1568
|
-
backendPages,
|
|
1569
|
-
frontendPages,
|
|
1570
|
-
cliCommands,
|
|
1571
|
-
aiTools,
|
|
1572
|
-
aiAgents,
|
|
1573
|
-
extensionSurfaces,
|
|
1574
|
-
...provenance.factSources.length > 0 ? { factSources: provenance.factSources } : {},
|
|
1575
|
-
...ownedContracts ? { ownedContracts } : {},
|
|
1576
|
-
...factDiagnostics.length > 0 ? { factDiagnostics } : {},
|
|
1577
574
|
warnings
|
|
1578
575
|
};
|
|
1579
|
-
const overrides = collectModuleOverrideTargets(facts, buildFactSourceLookup(facts));
|
|
1580
|
-
if (overrides.overrideTargets.length > 0) facts.overrideTargets = overrides.overrideTargets;
|
|
1581
|
-
if (overrides.overrideTargetDiagnostics.length > 0) {
|
|
1582
|
-
facts.overrideTargetDiagnostics = overrides.overrideTargetDiagnostics;
|
|
1583
|
-
}
|
|
1584
|
-
return facts;
|
|
1585
576
|
}
|
|
1586
577
|
const EMPTY_SECTION_MARKER = "_none_";
|
|
1587
|
-
function renderVersionStamp(coreVersion
|
|
1588
|
-
if (sourcePackage) {
|
|
1589
|
-
return `<!-- generated from ${sourcePackage} ${sourceVersion || "<unknown>"}; core ${coreVersion || "<unknown>"} \u2014 R1 staleness stamp -->`;
|
|
1590
|
-
}
|
|
578
|
+
function renderVersionStamp(coreVersion) {
|
|
1591
579
|
const version = coreVersion && coreVersion.length > 0 ? coreVersion : "<unknown>";
|
|
1592
580
|
return `<!-- generated from @open-mercato/core ${version} \u2014 R1 staleness stamp -->`;
|
|
1593
581
|
}
|
|
1594
|
-
function renderEntitiesSection(entities
|
|
582
|
+
function renderEntitiesSection(entities) {
|
|
1595
583
|
if (entities.length === 0) return `## Entities
|
|
1596
584
|
|
|
1597
585
|
${EMPTY_SECTION_MARKER}`;
|
|
1598
|
-
const header = "| Entity ID | Class | Table | Editable | CustomFields |
|
|
1599
|
-
const divider = "
|
|
586
|
+
const header = "| Entity ID | Class | Table | Editable | CustomFields |";
|
|
587
|
+
const divider = "|---|---|---|---|---|";
|
|
1600
588
|
const rows = entities.map(
|
|
1601
|
-
(entity) => `| ${entity.id} | ${entity.class} | ${entity.table} | ${entity.editable ? "yes" : "no"} | ${entity.customFields ? "yes" : "no"}
|
|
589
|
+
(entity) => `| ${entity.id} | ${entity.class} | ${entity.table} | ${entity.editable ? "yes" : "no"} | ${entity.customFields ? "yes" : "no"} |`
|
|
1602
590
|
);
|
|
1603
591
|
return ["## Entities", "", header, divider, ...rows].join("\n");
|
|
1604
592
|
}
|
|
1605
|
-
function renderEventsSection(events
|
|
593
|
+
function renderEventsSection(events) {
|
|
1606
594
|
const heading = `## Events (${events.length})`;
|
|
1607
595
|
if (events.length === 0) return `${heading}
|
|
1608
596
|
|
|
1609
597
|
${EMPTY_SECTION_MARKER}`;
|
|
1610
|
-
const header = "| ID | Category | Entity |
|
|
1611
|
-
const divider = "
|
|
1612
|
-
const rows = events.map((event) => {
|
|
1613
|
-
const transports = [event.clientBroadcast ? "client" : null, event.portalBroadcast ? "portal" : null].filter((value) => value !== null);
|
|
1614
|
-
return `| ${event.id} | ${event.category ?? "\u2014"} | ${event.entity ?? "\u2014"} | ${transports.join(", ") || "\u2014"} | ${renderLookedUpSource(lookup, "event", event.id)} |`;
|
|
1615
|
-
});
|
|
598
|
+
const header = "| ID | Category | Entity |";
|
|
599
|
+
const divider = "|---|---|---|";
|
|
600
|
+
const rows = events.map((event) => `| ${event.id} | ${event.category ?? "\u2014"} | ${event.entity ?? "\u2014"} |`);
|
|
1616
601
|
return [heading, "", header, divider, ...rows].join("\n");
|
|
1617
602
|
}
|
|
1618
603
|
function renderInlineListSection(heading, values) {
|
|
@@ -1623,57 +608,6 @@ ${EMPTY_SECTION_MARKER}`;
|
|
|
1623
608
|
|
|
1624
609
|
${values.join(" \xB7 ")}`;
|
|
1625
610
|
}
|
|
1626
|
-
function renderSourceLinkedListSection(heading, values, lookup, kind, idColumnLabel) {
|
|
1627
|
-
if (values.length === 0) return `${heading}
|
|
1628
|
-
|
|
1629
|
-
${EMPTY_SECTION_MARKER}`;
|
|
1630
|
-
const rows = values.map((value) => `| ${value} | ${renderLookedUpSource(lookup, kind, value)} |`);
|
|
1631
|
-
return [heading, "", `| ${idColumnLabel} | Source |`, "|---|---|", ...rows].join("\n");
|
|
1632
|
-
}
|
|
1633
|
-
function renderSourceLink(sourcePath) {
|
|
1634
|
-
return `[${sourcePath}](../../../${sourcePath})`;
|
|
1635
|
-
}
|
|
1636
|
-
function renderSourceRefLink(source) {
|
|
1637
|
-
const anchor = source.line ? `#L${source.line}` : "";
|
|
1638
|
-
const label = source.line ? `${source.sourcePath}:${source.line}` : source.sourcePath;
|
|
1639
|
-
return `[${label}](../../../${source.sourcePath}${anchor})`;
|
|
1640
|
-
}
|
|
1641
|
-
function renderLookedUpSource(lookup, kind, id) {
|
|
1642
|
-
const source = lookup(kind, id);
|
|
1643
|
-
return source ? renderSourceRefLink(source) : "\u2014";
|
|
1644
|
-
}
|
|
1645
|
-
function renderSafeScalar(value) {
|
|
1646
|
-
if (value === void 0 || value === null) return "\u2014";
|
|
1647
|
-
if (Array.isArray(value)) return value.length > 0 ? value.map((entry) => String(entry)).join(", ") : "\u2014";
|
|
1648
|
-
return String(value);
|
|
1649
|
-
}
|
|
1650
|
-
function renderOwnedContractMetadata(metadata) {
|
|
1651
|
-
if (!metadata) return "\u2014";
|
|
1652
|
-
const keys = Object.keys(metadata).sort((left, right) => left.localeCompare(right));
|
|
1653
|
-
if (keys.length === 0) return "\u2014";
|
|
1654
|
-
return keys.map((key) => `${key}=${renderSafeScalar(metadata[key])}`).join("; ");
|
|
1655
|
-
}
|
|
1656
|
-
function renderOwnedContractSection(heading, facts) {
|
|
1657
|
-
if (!facts || facts.length === 0) return "";
|
|
1658
|
-
const rows = facts.map(
|
|
1659
|
-
(fact) => `| ${fact.id} | ${renderOwnedContractMetadata(fact.metadata)} | ${renderSourceRefLink(fact.source)} |`
|
|
1660
|
-
);
|
|
1661
|
-
return [heading, "", "| ID | Metadata | Source |", "|---|---|---|", ...rows].join("\n");
|
|
1662
|
-
}
|
|
1663
|
-
function renderDiRegistrationsSection(facts) {
|
|
1664
|
-
if (!facts || facts.length === 0) return "";
|
|
1665
|
-
const rows = facts.map((fact) => {
|
|
1666
|
-
const metadata = fact.metadata ?? {};
|
|
1667
|
-
return `| ${fact.id} | ${renderSafeScalar(metadata.registrationKind)} | ${renderSafeScalar(metadata.lifetime)} | ${renderSafeScalar(metadata.injectionMode)} | ${renderSafeScalar(metadata.providerSymbol)} | ${renderSourceRefLink(fact.source)} |`;
|
|
1668
|
-
});
|
|
1669
|
-
return [
|
|
1670
|
-
"## DI registrations (rich)",
|
|
1671
|
-
"",
|
|
1672
|
-
"| Token | Kind | Lifetime | Injection | Provider | Source |",
|
|
1673
|
-
"|---|---|---|---|---|---|",
|
|
1674
|
-
...rows
|
|
1675
|
-
].join("\n");
|
|
1676
|
-
}
|
|
1677
611
|
function describeAuthRule(rule) {
|
|
1678
612
|
if (!rule) return "public";
|
|
1679
613
|
if (rule.requireFeatures && rule.requireFeatures.length > 0) return rule.requireFeatures.join(", ");
|
|
@@ -1696,246 +630,42 @@ function renderApiRoutesSection(routes) {
|
|
|
1696
630
|
if (routes.length === 0) return `## API routes
|
|
1697
631
|
|
|
1698
632
|
${EMPTY_SECTION_MARKER}`;
|
|
1699
|
-
const header = "| Path | Methods | Auth (per-method requireFeatures) |
|
|
1700
|
-
const divider = "
|
|
633
|
+
const header = "| Path | Methods | Auth (per-method requireFeatures) |";
|
|
634
|
+
const divider = "|---|---|---|";
|
|
1701
635
|
const rows = routes.map(
|
|
1702
|
-
(route) => `| ${route.path} | ${route.methods.join(" ")} | ${renderApiRouteAuthCell(route)}
|
|
636
|
+
(route) => `| ${route.path} | ${route.methods.join(" ")} | ${renderApiRouteAuthCell(route)} |`
|
|
1703
637
|
);
|
|
1704
638
|
return ["## API routes", "", header, divider, ...rows].join("\n");
|
|
1705
639
|
}
|
|
1706
|
-
function renderLinkedFactsSection(heading, facts) {
|
|
1707
|
-
if (facts.length === 0) return `${heading}
|
|
1708
|
-
|
|
1709
|
-
${EMPTY_SECTION_MARKER}`;
|
|
1710
|
-
const rows = facts.map((fact) => `| ${fact.label} | ${renderSourceLink(fact.sourcePath)} |`);
|
|
1711
|
-
return [heading, "", "| ID / path | Source |", "|---|---|", ...rows].join("\n");
|
|
1712
|
-
}
|
|
1713
640
|
function renderHostTokensSection(hostTokens) {
|
|
1714
641
|
const entityIdsLine = hostTokens.entityIds.length > 0 ? hostTokens.entityIds.join(" \xB7 ") : EMPTY_SECTION_MARKER;
|
|
1715
642
|
const tableIdsLine = hostTokens.tableIds.length > 0 ? hostTokens.tableIds.join(" \xB7 ") : EMPTY_SECTION_MARKER;
|
|
1716
643
|
return ["## Host extension points", "", `- Entity IDs: ${entityIdsLine}`, `- Table IDs: ${tableIdsLine}`].join("\n");
|
|
1717
644
|
}
|
|
1718
|
-
function renderExtensionHostContext(host) {
|
|
1719
|
-
return host.contextContract ?? host.runtimeContract ?? host.scopeContract ?? "\u2014";
|
|
1720
|
-
}
|
|
1721
|
-
function renderExtensionHostSource(host) {
|
|
1722
|
-
if (host.source.kind === "fact-ref") return `${host.source.factSection}:${host.source.factKey}`;
|
|
1723
|
-
return renderSourceRefLink({ sourcePath: host.source.path });
|
|
1724
|
-
}
|
|
1725
|
-
function renderExtensionHostsSection(extensionSurfaces) {
|
|
1726
|
-
const boundHosts = extensionSurfaces.hosts.filter((host) => host.bound);
|
|
1727
|
-
if (boundHosts.length === 0) return `## UMES hosts
|
|
1728
|
-
|
|
1729
|
-
${EMPTY_SECTION_MARKER}`;
|
|
1730
|
-
const rows = boundHosts.map(
|
|
1731
|
-
(host) => `| ${host.id} | ${host.family} | ${host.capabilities.join(", ") || "\u2014"} | ${renderExtensionHostContext(host)} | ${host.stability.toUpperCase()} | ${renderExtensionHostSource(host)} |`
|
|
1732
|
-
);
|
|
1733
|
-
return [
|
|
1734
|
-
"## UMES hosts",
|
|
1735
|
-
"",
|
|
1736
|
-
"| ID / pattern | Family | Supports | Context | Stability | Source |",
|
|
1737
|
-
"|---|---|---|---|---|---|",
|
|
1738
|
-
...rows
|
|
1739
|
-
].join("\n");
|
|
1740
|
-
}
|
|
1741
|
-
function compactContributionDetails(contribution) {
|
|
1742
|
-
const details = contribution.details;
|
|
1743
|
-
return Object.keys(details).sort((left, right) => left.localeCompare(right)).flatMap((key) => {
|
|
1744
|
-
const value = details[key];
|
|
1745
|
-
if (value === void 0) return [];
|
|
1746
|
-
if (Array.isArray(value)) return [`${key}=${value.join(",") || "none"}`];
|
|
1747
|
-
if (value && typeof value === "object") {
|
|
1748
|
-
const nested = Object.keys(value).sort((left, right) => left.localeCompare(right)).map((nestedKey) => {
|
|
1749
|
-
const nestedValue = value[nestedKey];
|
|
1750
|
-
return `${nestedKey}:${Array.isArray(nestedValue) ? nestedValue.join(",") : String(nestedValue)}`;
|
|
1751
|
-
});
|
|
1752
|
-
return [`${key}={${nested.join(";")}}`];
|
|
1753
|
-
}
|
|
1754
|
-
return [`${key}=${String(value)}`];
|
|
1755
|
-
}).join("; ");
|
|
1756
|
-
}
|
|
1757
|
-
function renderExtensionContributionsSection(extensionSurfaces) {
|
|
1758
|
-
if (extensionSurfaces.contributions.length === 0) return `## UMES contributions
|
|
1759
|
-
|
|
1760
|
-
${EMPTY_SECTION_MARKER}`;
|
|
1761
|
-
const rows = extensionSurfaces.contributions.map((contribution) => {
|
|
1762
|
-
const targets = contribution.targets.map((entry) => entry.id).join(", ");
|
|
1763
|
-
const resolution = contribution.targets.map((entry) => entry.resolution).join(", ");
|
|
1764
|
-
const phases = [...contribution.phases ?? [], ...contribution.operations ?? []].join(", ") || "\u2014";
|
|
1765
|
-
const source = renderSourceRefLink({ sourcePath: contribution.source.path });
|
|
1766
|
-
return `| ${contribution.id} | ${contribution.kind} | ${targets || "\u2014"} | ${phases} | ${compactContributionDetails(contribution)} | ${resolution || "\u2014"} | ${source} |`;
|
|
1767
|
-
});
|
|
1768
|
-
return [
|
|
1769
|
-
"## UMES contributions",
|
|
1770
|
-
"",
|
|
1771
|
-
"| ID | Kind | Target | Phase / operations | Contract | Resolution | Source |",
|
|
1772
|
-
"|---|---|---|---|---|---|---|",
|
|
1773
|
-
...rows
|
|
1774
|
-
].join("\n");
|
|
1775
|
-
}
|
|
1776
|
-
function renderExtensionDiagnosticsSection(extensionSurfaces) {
|
|
1777
|
-
const unbound = extensionSurfaces.hosts.filter((host) => !host.bound);
|
|
1778
|
-
if (unbound.length === 0 && extensionSurfaces.unresolved.length === 0) return "";
|
|
1779
|
-
const diagnostics = [
|
|
1780
|
-
...unbound.map((host) => `- unbound-helper: ${host.id}`),
|
|
1781
|
-
...extensionSurfaces.unresolved.map((entry) => `- ${entry.reason}: ${entry.key} (${entry.source.path})`)
|
|
1782
|
-
];
|
|
1783
|
-
return ["## UMES diagnostics", "", ...diagnostics].join("\n");
|
|
1784
|
-
}
|
|
1785
|
-
function renderExtensionTargetRef(target) {
|
|
1786
|
-
const method = target.method ? ` ${target.method}` : "";
|
|
1787
|
-
const owner = target.moduleId ? ` @${target.moduleId}` : "";
|
|
1788
|
-
return `${target.kind}:${target.id}${method}${owner}`;
|
|
1789
|
-
}
|
|
1790
|
-
function renderActivationBindingsSection(extensionSurfaces) {
|
|
1791
|
-
const activations = extensionSurfaces.activations ?? [];
|
|
1792
|
-
if (activations.length === 0) return `## Active extension bindings
|
|
1793
|
-
|
|
1794
|
-
${EMPTY_SECTION_MARKER}`;
|
|
1795
|
-
const rows = activations.map((activation) => {
|
|
1796
|
-
const phases = activation.phases && activation.phases.length > 0 ? activation.phases.join(", ") : "\u2014";
|
|
1797
|
-
const source = activation.source ? renderSourceRefLink(activation.source) : "\u2014";
|
|
1798
|
-
const bridge = activation.bridge ? `${activation.bridge.factSection}:${activation.bridge.factKey}` : "\u2014";
|
|
1799
|
-
return `| ${activation.id} | ${activation.kind} | ${renderExtensionTargetRef(activation.host)} | ${activation.contributionKinds.join(", ") || "\u2014"} | ${phases} | ${bridge} | ${source} |`;
|
|
1800
|
-
});
|
|
1801
|
-
return [
|
|
1802
|
-
"## Active extension bindings",
|
|
1803
|
-
"",
|
|
1804
|
-
"| Activation | Kind | Host | Contribution kinds | Phases | Bridge | Source |",
|
|
1805
|
-
"|---|---|---|---|---|---|---|",
|
|
1806
|
-
...rows
|
|
1807
|
-
].join("\n");
|
|
1808
|
-
}
|
|
1809
|
-
function renderIncomingContributionsSection(extensionSurfaces) {
|
|
1810
|
-
const incoming = extensionSurfaces.incoming ?? [];
|
|
1811
|
-
if (incoming.length === 0) return `## Incoming installed contributions
|
|
1812
|
-
|
|
1813
|
-
${EMPTY_SECTION_MARKER}`;
|
|
1814
|
-
const rows = incoming.map((entry) => {
|
|
1815
|
-
const activation = entry.activationId ?? "\u2014";
|
|
1816
|
-
const source = entry.source ? renderSourceRefLink(entry.source) : "\u2014";
|
|
1817
|
-
return `| ${entry.contributorModuleId} | ${entry.contributionKind} | ${renderExtensionTargetRef(entry.target)} | ${entry.resolution} | ${activation} | ${entry.contributionId} \xB7 ${source} |`;
|
|
1818
|
-
});
|
|
1819
|
-
return [
|
|
1820
|
-
"## Incoming installed contributions",
|
|
1821
|
-
"",
|
|
1822
|
-
"| Contributor | Kind | Target | Resolution | Activation | Contribution \xB7 Source |",
|
|
1823
|
-
"|---|---|---|---|---|---|",
|
|
1824
|
-
...rows
|
|
1825
|
-
].join("\n");
|
|
1826
|
-
}
|
|
1827
|
-
function renderContributionResolutionsSection(extensionSurfaces, lookup) {
|
|
1828
|
-
const resolutions = extensionSurfaces.contributionResolutions ?? [];
|
|
1829
|
-
if (resolutions.length === 0) return `## Contribution resolutions
|
|
1830
|
-
|
|
1831
|
-
${EMPTY_SECTION_MARKER}`;
|
|
1832
|
-
const rows = resolutions.map((resolution) => {
|
|
1833
|
-
const activations = resolution.activationIds.length > 0 ? resolution.activationIds.join(", ") : "\u2014";
|
|
1834
|
-
const source = renderLookedUpSource(lookup, "extension-contribution", resolution.contributionId);
|
|
1835
|
-
return `| ${resolution.contributionId} | ${renderExtensionTargetRef(resolution.target)} | ${resolution.resolution} | ${activations} | ${source} |`;
|
|
1836
|
-
});
|
|
1837
|
-
return [
|
|
1838
|
-
"## Contribution resolutions",
|
|
1839
|
-
"",
|
|
1840
|
-
"| Contribution | Target | Resolution | Activations | Source |",
|
|
1841
|
-
"|---|---|---|---|---|",
|
|
1842
|
-
...rows
|
|
1843
|
-
].join("\n");
|
|
1844
|
-
}
|
|
1845
|
-
function renderOverrideTargetPath(target) {
|
|
1846
|
-
let display = "overrides";
|
|
1847
|
-
for (let index = 0; index < target.path.length; index += 1) {
|
|
1848
|
-
const segment = target.path[index];
|
|
1849
|
-
const isKeyedTerminal = target.key !== void 0 && index === target.path.length - 1;
|
|
1850
|
-
display += isKeyedTerminal ? `[${JSON.stringify(segment)}]` : `.${segment}`;
|
|
1851
|
-
}
|
|
1852
|
-
return display;
|
|
1853
|
-
}
|
|
1854
|
-
function renderOverrideTargetsSection(targets) {
|
|
1855
|
-
if (!targets || targets.length === 0) return `## Exact override targets
|
|
1856
|
-
|
|
1857
|
-
${EMPTY_SECTION_MARKER}`;
|
|
1858
|
-
const header = "| Domain | Path / key | Supported modes | Referenced fact | Source |";
|
|
1859
|
-
const divider = "|---|---|---|---|---|";
|
|
1860
|
-
const rows = targets.map((target) => {
|
|
1861
|
-
const path2 = `\`${renderOverrideTargetPath(target)}\``;
|
|
1862
|
-
const modes = target.modes.join(", ") || "\u2014";
|
|
1863
|
-
const fact = `${target.factRef.factSection}:${target.factRef.factKey}`;
|
|
1864
|
-
return `| ${target.domain} | ${path2} | ${modes} | ${fact} | ${renderSourceRefLink(target.source)} |`;
|
|
1865
|
-
});
|
|
1866
|
-
return ["## Exact override targets", "", header, divider, ...rows].join("\n");
|
|
1867
|
-
}
|
|
1868
645
|
function renderModuleFactsMarkdown(facts) {
|
|
1869
|
-
const extensionSurfaces = facts.extensionSurfaces ?? { hosts: [], contributions: [], unresolved: [] };
|
|
1870
|
-
const lookup = buildFactSourceLookup(facts);
|
|
1871
646
|
const sections = [
|
|
1872
647
|
`# ${facts.module} \u2014 module facts (generated, do not edit)`,
|
|
1873
|
-
renderVersionStamp(facts.coreVersion
|
|
1874
|
-
`Source root: ${renderSourceLink(facts.sourceRoot)}`,
|
|
648
|
+
renderVersionStamp(facts.coreVersion),
|
|
1875
649
|
"",
|
|
1876
|
-
renderEntitiesSection(facts.entities
|
|
650
|
+
renderEntitiesSection(facts.entities),
|
|
1877
651
|
"",
|
|
1878
|
-
renderEventsSection(facts.events
|
|
652
|
+
renderEventsSection(facts.events),
|
|
1879
653
|
"",
|
|
1880
|
-
|
|
1881
|
-
`## ACL features (${facts.aclFeatures.length})`,
|
|
1882
|
-
facts.aclFeatures,
|
|
1883
|
-
lookup,
|
|
1884
|
-
"acl-feature",
|
|
1885
|
-
"Feature"
|
|
1886
|
-
),
|
|
654
|
+
renderInlineListSection(`## ACL features (${facts.aclFeatures.length})`, facts.aclFeatures),
|
|
1887
655
|
"",
|
|
1888
656
|
renderApiRoutesSection(facts.apiRoutes),
|
|
1889
657
|
"",
|
|
1890
|
-
|
|
1891
|
-
"",
|
|
1892
|
-
renderLinkedFactsSection("## Frontend pages", facts.frontendPages.map((page) => ({ label: page.path, sourcePath: page.sourcePath }))),
|
|
1893
|
-
"",
|
|
1894
|
-
renderSourceLinkedListSection("## DI service tokens", facts.diTokens, lookup, "di-registration", "Token"),
|
|
658
|
+
renderInlineListSection("## DI service tokens", facts.diTokens),
|
|
1895
659
|
"",
|
|
1896
|
-
|
|
660
|
+
renderInlineListSection("## Search entities", facts.searchEntities),
|
|
1897
661
|
"",
|
|
1898
662
|
renderHostTokensSection(facts.hostTokens),
|
|
1899
663
|
"",
|
|
1900
|
-
|
|
1901
|
-
"",
|
|
1902
|
-
renderExtensionContributionsSection(extensionSurfaces),
|
|
1903
|
-
"",
|
|
1904
|
-
renderActivationBindingsSection(extensionSurfaces),
|
|
664
|
+
renderInlineListSection("## Notifications", facts.notifications),
|
|
1905
665
|
"",
|
|
1906
|
-
|
|
1907
|
-
"",
|
|
1908
|
-
renderContributionResolutionsSection(extensionSurfaces, lookup),
|
|
1909
|
-
"",
|
|
1910
|
-
renderExtensionDiagnosticsSection(extensionSurfaces),
|
|
1911
|
-
"",
|
|
1912
|
-
renderSourceLinkedListSection("## Notifications", facts.notifications, lookup, "notification", "Notification ID"),
|
|
1913
|
-
"",
|
|
1914
|
-
renderLinkedFactsSection("## CLI commands", facts.cliCommands.map((command) => ({ label: command.command, sourcePath: command.sourcePath }))),
|
|
1915
|
-
"",
|
|
1916
|
-
renderLinkedFactsSection("## AI tools / MCP capabilities", facts.aiTools.map((tool) => ({ label: tool.name, sourcePath: tool.sourcePath }))),
|
|
1917
|
-
"",
|
|
1918
|
-
renderLinkedFactsSection("## AI agents", facts.aiAgents.map((agent) => ({ label: agent.id, sourcePath: agent.sourcePath }))),
|
|
1919
|
-
"",
|
|
1920
|
-
renderOverrideTargetsSection(facts.overrideTargets),
|
|
666
|
+
renderInlineListSection("## CLI", facts.cli),
|
|
1921
667
|
""
|
|
1922
668
|
];
|
|
1923
|
-
const owned = facts.ownedContracts ?? {};
|
|
1924
|
-
const ownedSections = [
|
|
1925
|
-
renderOwnedContractSection("## Owned contract \u2014 module metadata", owned["module-metadata"]),
|
|
1926
|
-
renderOwnedContractSection("## Domain commands", owned.command),
|
|
1927
|
-
renderOwnedContractSection("## Workers", owned.worker),
|
|
1928
|
-
renderOwnedContractSection("## Page middleware", owned["page-middleware"]),
|
|
1929
|
-
renderOwnedContractSection("## Setup", owned.setup),
|
|
1930
|
-
renderOwnedContractSection("## Encryption", owned.encryption),
|
|
1931
|
-
renderDiRegistrationsSection(owned["di-registration"]),
|
|
1932
|
-
renderOwnedContractSection("## Custom entities", owned["custom-entity"]),
|
|
1933
|
-
renderOwnedContractSection("## AI extensions", owned["ai-extension"]),
|
|
1934
|
-
renderOwnedContractSection("## Generator plugins", owned["generator-plugin"])
|
|
1935
|
-
].filter((section) => section.length > 0);
|
|
1936
|
-
for (const section of ownedSections) {
|
|
1937
|
-
sections.push(section, "");
|
|
1938
|
-
}
|
|
1939
669
|
return sections.join("\n");
|
|
1940
670
|
}
|
|
1941
671
|
function toModuleFactsJsonEntry(facts) {
|
|
@@ -1943,35 +673,15 @@ function toModuleFactsJsonEntry(facts) {
|
|
|
1943
673
|
title: facts.title,
|
|
1944
674
|
description: facts.description,
|
|
1945
675
|
coreVersion: facts.coreVersion,
|
|
1946
|
-
sourcePackage: facts.sourcePackage,
|
|
1947
|
-
sourceVersion: facts.sourceVersion,
|
|
1948
|
-
sourceRoot: facts.sourceRoot,
|
|
1949
676
|
entities: facts.entities,
|
|
1950
|
-
events: facts.events.map((event) => ({
|
|
1951
|
-
id: event.id,
|
|
1952
|
-
category: event.category,
|
|
1953
|
-
entity: event.entity,
|
|
1954
|
-
...event.clientBroadcast !== void 0 ? { clientBroadcast: event.clientBroadcast } : {},
|
|
1955
|
-
...event.portalBroadcast !== void 0 ? { portalBroadcast: event.portalBroadcast } : {}
|
|
1956
|
-
})),
|
|
677
|
+
events: facts.events.map((event) => ({ id: event.id, category: event.category, entity: event.entity })),
|
|
1957
678
|
aclFeatures: facts.aclFeatures,
|
|
1958
679
|
apiRoutes: facts.apiRoutes,
|
|
1959
680
|
diTokens: facts.diTokens,
|
|
1960
681
|
searchEntities: facts.searchEntities,
|
|
1961
682
|
hostTokens: facts.hostTokens,
|
|
1962
683
|
notifications: facts.notifications,
|
|
1963
|
-
cli: facts.cli
|
|
1964
|
-
backendPages: facts.backendPages,
|
|
1965
|
-
frontendPages: facts.frontendPages,
|
|
1966
|
-
cliCommands: facts.cliCommands,
|
|
1967
|
-
aiTools: facts.aiTools,
|
|
1968
|
-
aiAgents: facts.aiAgents,
|
|
1969
|
-
...facts.extensionSurfaces ? { extensionSurfaces: facts.extensionSurfaces } : {},
|
|
1970
|
-
...facts.factSources && facts.factSources.length > 0 ? { factSources: facts.factSources } : {},
|
|
1971
|
-
...facts.ownedContracts && Object.keys(facts.ownedContracts).length > 0 ? { ownedContracts: facts.ownedContracts } : {},
|
|
1972
|
-
...facts.factDiagnostics && facts.factDiagnostics.length > 0 ? { factDiagnostics: facts.factDiagnostics } : {},
|
|
1973
|
-
...facts.overrideTargets && facts.overrideTargets.length > 0 ? { overrideTargets: facts.overrideTargets } : {},
|
|
1974
|
-
...facts.overrideTargetDiagnostics && facts.overrideTargetDiagnostics.length > 0 ? { overrideTargetDiagnostics: facts.overrideTargetDiagnostics } : {}
|
|
684
|
+
cli: facts.cli
|
|
1975
685
|
};
|
|
1976
686
|
}
|
|
1977
687
|
function buildModuleFactsJsonObject(factsByModule) {
|
|
@@ -1986,9 +696,6 @@ function renderModuleFactsJson(factsByModule) {
|
|
|
1986
696
|
`;
|
|
1987
697
|
}
|
|
1988
698
|
function extractAllModuleFacts(options) {
|
|
1989
|
-
return withModuleExtensionFactExtractionCache(() => extractAllModuleFactsWithCache(options));
|
|
1990
|
-
}
|
|
1991
|
-
function extractAllModuleFactsWithCache(options) {
|
|
1992
699
|
const sources = options.sources ? [...options.sources] : options.coreSrcRoot ? (options.moduleIds ?? []).map((moduleId) => ({
|
|
1993
700
|
moduleId,
|
|
1994
701
|
moduleRoot: path.join(options.coreSrcRoot, moduleId)
|
|
@@ -2001,63 +708,14 @@ function extractAllModuleFactsWithCache(options) {
|
|
|
2001
708
|
moduleId: source.moduleId,
|
|
2002
709
|
moduleRoot: source.moduleRoot,
|
|
2003
710
|
coreVersion: options.coreVersion ?? null,
|
|
2004
|
-
sourcePackage: source.from ?? null,
|
|
2005
|
-
sourceVersion: source.packageVersion ?? null,
|
|
2006
711
|
registryPath: options.registryPath ?? null,
|
|
2007
712
|
registrySource: options.registrySource ?? null
|
|
2008
713
|
});
|
|
2009
714
|
factsByModule[source.moduleId] = facts;
|
|
715
|
+
markdownByModule[source.moduleId] = renderModuleFactsMarkdown(facts);
|
|
2010
716
|
warnings.push(...facts.warnings);
|
|
2011
717
|
}
|
|
2012
|
-
|
|
2013
|
-
Object.entries(factsByModule).map(([moduleId, facts]) => [
|
|
2014
|
-
moduleId,
|
|
2015
|
-
facts.extensionSurfaces ?? { hosts: [], contributions: [], unresolved: [] }
|
|
2016
|
-
])
|
|
2017
|
-
);
|
|
2018
|
-
const correlated = correlateModuleExtensionFacts({
|
|
2019
|
-
surfacesByModule,
|
|
2020
|
-
entityIds: new Set(Object.values(factsByModule).flatMap((facts) => facts.entities.map((entity) => entity.id))),
|
|
2021
|
-
eventIds: new Set(Object.values(factsByModule).flatMap((facts) => facts.events.map((event) => event.id))),
|
|
2022
|
-
apiRoutes: /* @__PURE__ */ new Set([
|
|
2023
|
-
...Object.values(factsByModule).flatMap((facts) => facts.apiRoutes.map((route) => route.path)),
|
|
2024
|
-
...sources.flatMap((source) => extractKnownApiRouteIds(source.moduleId, source.moduleRoot))
|
|
2025
|
-
]),
|
|
2026
|
-
commandIds: new Set(sources.flatMap((source) => extractKnownCommandIds(source.moduleId, source.moduleRoot)))
|
|
2027
|
-
});
|
|
2028
|
-
assertNoUnresolvedExtensionTargets(correlated);
|
|
2029
|
-
const apiRouteOwners = /* @__PURE__ */ new Map();
|
|
2030
|
-
const commandOwners = /* @__PURE__ */ new Map();
|
|
2031
|
-
for (const source of [...sources].sort((left, right) => left.moduleId.localeCompare(right.moduleId))) {
|
|
2032
|
-
const facts = factsByModule[source.moduleId];
|
|
2033
|
-
const sourceRoot = facts ? facts.sourceRoot : source.moduleId;
|
|
2034
|
-
const owners = extractActivationTargetOwners({
|
|
2035
|
-
moduleId: source.moduleId,
|
|
2036
|
-
moduleRoot: source.moduleRoot,
|
|
2037
|
-
sourceRoot
|
|
2038
|
-
});
|
|
2039
|
-
for (const route of owners.apiRoutes) {
|
|
2040
|
-
if (!apiRouteOwners.has(route.id)) {
|
|
2041
|
-
apiRouteOwners.set(route.id, { moduleId: source.moduleId, source: route.source, bridges: route.bridges });
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2044
|
-
for (const command of owners.commands) {
|
|
2045
|
-
if (!commandOwners.has(command.id)) commandOwners.set(command.id, { moduleId: source.moduleId, source: command.source });
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
const withIncoming = correlateIncomingExtensions({
|
|
2049
|
-
surfacesByModule: correlated,
|
|
2050
|
-
apiRouteOwners,
|
|
2051
|
-
commandOwners
|
|
2052
|
-
});
|
|
2053
|
-
for (const moduleId of Object.keys(factsByModule).sort((left, right) => left.localeCompare(right))) {
|
|
2054
|
-
factsByModule[moduleId].extensionSurfaces = withIncoming[moduleId];
|
|
2055
|
-
markdownByModule[moduleId] = renderModuleFactsMarkdown(factsByModule[moduleId]);
|
|
2056
|
-
warnings.push(...correlated[moduleId].unresolved.map(
|
|
2057
|
-
(entry) => `[module-facts] ${moduleId} ${entry.reason}: ${entry.key} (${entry.source.path})`
|
|
2058
|
-
));
|
|
2059
|
-
}
|
|
2060
|
-
return { factsByModule, markdownByModule, warnings, frameworkMarkdown: renderFrameworkExtensionPointsMarkdown() };
|
|
718
|
+
return { factsByModule, markdownByModule, warnings };
|
|
2061
719
|
}
|
|
2062
720
|
export {
|
|
2063
721
|
buildModuleFactsJsonObject,
|