@open-mercato/cli 0.6.7 → 0.6.8-canary.319.1.5b4be4bc52
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 +77 -4
- package/build.mjs +68 -11
- package/dist/agentic/claude-code/hooks/entity-migration-check.ts +32 -88
- package/dist/agentic/codex/enforcement-rules.md +2 -16
- package/dist/agentic/cursor/hooks/entity-migration-check.mjs +19 -50
- package/dist/agentic/cursor/rules/entity-guard.mdc +9 -21
- package/dist/agentic/cursor/rules/generated-guard.mdc +3 -5
- package/dist/agentic/cursor/rules/open-mercato.mdc +3 -29
- package/dist/agentic/guides/ai-workflows.md +76 -0
- package/dist/agentic/guides/architecture.md +107 -0
- package/dist/agentic/guides/backend-ui.md +84 -0
- package/dist/agentic/guides/contracts.md +92 -0
- package/dist/agentic/guides/extensions.md +121 -0
- package/dist/agentic/guides/framework-extension-points.md +36 -0
- package/dist/agentic/guides/integrations.md +81 -0
- package/dist/agentic/guides/module-facts.json +116757 -3951
- package/dist/agentic/guides/module-system.md +12 -127
- package/dist/agentic/guides/modules/ai_assistant.md +227 -28
- package/dist/agentic/guides/modules/api_docs.md +58 -2
- package/dist/agentic/guides/modules/api_keys.md +92 -7
- package/dist/agentic/guides/modules/attachments.md +119 -14
- package/dist/agentic/guides/modules/audit_logs.md +131 -10
- package/dist/agentic/guides/modules/auth.md +276 -33
- package/dist/agentic/guides/modules/business_rules.md +149 -14
- package/dist/agentic/guides/modules/catalog.md +482 -43
- package/dist/agentic/guides/modules/channel_gmail.md +82 -3
- package/dist/agentic/guides/modules/channel_imap.md +82 -3
- package/dist/agentic/guides/modules/checkout.md +305 -27
- package/dist/agentic/guides/modules/communication_channels.md +315 -33
- package/dist/agentic/guides/modules/configs.md +104 -8
- package/dist/agentic/guides/modules/content.md +57 -2
- package/dist/agentic/guides/modules/currencies.md +152 -17
- package/dist/agentic/guides/modules/customer_accounts.md +387 -45
- package/dist/agentic/guides/modules/customers.md +746 -85
- package/dist/agentic/guides/modules/dashboards.md +155 -10
- package/dist/agentic/guides/modules/data_sync.md +149 -16
- package/dist/agentic/guides/modules/design_system.md +102 -0
- package/dist/agentic/guides/modules/dictionaries.md +107 -12
- package/dist/agentic/guides/modules/directory.md +148 -15
- package/dist/agentic/guides/modules/entities.md +145 -13
- package/dist/agentic/guides/modules/events.md +59 -2
- package/dist/agentic/guides/modules/feature_toggles.md +119 -9
- package/dist/agentic/guides/modules/gateway_stripe.md +92 -4
- package/dist/agentic/guides/modules/generators.md +45 -2
- package/dist/agentic/guides/modules/inbox_ops.md +207 -27
- package/dist/agentic/guides/modules/integrations.md +149 -16
- package/dist/agentic/guides/modules/messages.md +223 -24
- package/dist/agentic/guides/modules/notifications.md +96 -8
- package/dist/agentic/guides/modules/onboarding.md +77 -6
- package/dist/agentic/guides/modules/payment_gateways.md +168 -21
- package/dist/agentic/guides/modules/perspectives.md +77 -7
- package/dist/agentic/guides/modules/planner.md +136 -18
- package/dist/agentic/guides/modules/portal.md +93 -2
- package/dist/agentic/guides/modules/progress.md +104 -14
- package/dist/agentic/guides/modules/query_index.md +154 -15
- package/dist/agentic/guides/modules/record_locks.md +206 -21
- package/dist/agentic/guides/modules/resources.md +197 -30
- package/dist/agentic/guides/modules/sales.md +687 -84
- package/dist/agentic/guides/modules/scheduler.md +133 -14
- package/dist/agentic/guides/modules/search.md +170 -6
- package/dist/agentic/guides/modules/security.md +294 -35
- package/dist/agentic/guides/modules/shipping_carriers.md +134 -18
- package/dist/agentic/guides/modules/sso.md +151 -26
- package/dist/agentic/guides/modules/staff.md +372 -57
- package/dist/agentic/guides/modules/storage_s3.md +95 -5
- package/dist/agentic/guides/modules/sync_akeneo.md +85 -3
- package/dist/agentic/guides/modules/sync_excel.md +75 -6
- package/dist/agentic/guides/modules/system_status_overlays.md +60 -2
- package/dist/agentic/guides/modules/translations.md +104 -10
- package/dist/agentic/guides/modules/webhooks.md +203 -24
- package/dist/agentic/guides/modules/wms.md +469 -47
- package/dist/agentic/guides/modules/workflows.md +302 -43
- package/dist/agentic/guides/reference-module-facts.json +6370 -0
- package/dist/agentic/guides/reference-modules/example.md +451 -0
- package/dist/agentic/guides/spec-delivery.md +42 -0
- package/dist/agentic/guides/testing-debugging.md +80 -0
- package/dist/agentic/guides/upstream/AGENTS.md +299 -0
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +316 -0
- package/dist/agentic/guides/upstream/manifest.json +8 -0
- package/dist/agentic/shared/AGENTS.md.template +120 -311
- package/dist/agentic/shared/ai/agentic.config.json +2 -0
- package/dist/agentic/shared/ai/harness/README.md +50 -0
- package/dist/agentic/shared/ai/harness/RELEASE.md +57 -0
- package/dist/agentic/shared/ai/harness/cases.json +15050 -0
- package/dist/agentic/shared/ai/harness/cases.schema.json +188 -0
- package/dist/agentic/shared/ai/harness/fixtures/index.json +51 -0
- package/dist/agentic/shared/ai/harness/fixtures/seeds.json +166 -0
- package/dist/agentic/shared/ai/harness/generated-code-review-policy.md +21 -0
- package/dist/agentic/shared/ai/harness/generated-code-review-response.schema.json +96 -0
- package/dist/agentic/shared/ai/harness/generated-code-review-result.schema.json +172 -0
- package/dist/agentic/shared/ai/harness/knowledge-change.schema.json +228 -0
- package/dist/agentic/shared/ai/harness/release-matrix.json +163 -0
- package/dist/agentic/shared/ai/harness/release-result.schema.json +219 -0
- package/dist/agentic/shared/ai/harness/result.schema.json +109 -0
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +22 -0
- package/dist/agentic/shared/ai/harness/target-validation-result.schema.json +73 -0
- package/dist/agentic/shared/ai/harness/validators.json +82 -0
- package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +2121 -0
- package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +1096 -0
- package/dist/agentic/shared/ai/harness/writable-spec-oracles.mjs +412 -0
- package/dist/agentic/shared/ai/lessons/_template.md +16 -0
- package/dist/agentic/shared/ai/lessons.md +26 -3
- package/dist/agentic/shared/ai/review-checklist.md +36 -0
- package/dist/agentic/shared/ai/skills/om-auto-implement-spec/SKILL.md +21 -0
- package/dist/agentic/shared/ai/skills/om-auto-review-pr/SKILL.md +4 -0
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.6-to-0.6.7/SKILL.md +98 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +21 -241
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +31 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +53 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +15 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/quality-states.md +11 -0
- package/dist/agentic/shared/ai/skills/om-build-workflow/SKILL.md +30 -0
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/activity-contracts.md +12 -0
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/durability-and-progress.md +13 -0
- package/dist/agentic/shared/ai/skills/om-build-workflow/references/workflow-design.md +14 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/SKILL.md +28 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/attachments-and-overrides.md +12 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/module-agents-and-tools.md +22 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/orchestrator-agents.md +12 -0
- package/dist/agentic/shared/ai/skills/om-create-ai-agent/references/surface-selector.md +19 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +17 -601
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +21 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +15 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +16 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/sensitive-data.md +10 -0
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +15 -310
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +19 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +31 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +100 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +16 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/knowledge-change.md +115 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/owner-selection.md +17 -0
- package/dist/agentic/shared/ai/skills/om-framework-context/SKILL.md +25 -0
- package/dist/agentic/shared/ai/skills/om-framework-context/references/resolver-procedure.md +11 -0
- package/dist/agentic/shared/ai/skills/om-framework-context/references/skew-and-escalation.md +13 -0
- package/dist/agentic/shared/ai/skills/om-help/SKILL.md +15 -97
- package/dist/agentic/shared/ai/skills/om-help/references/delivery-workflows.md +18 -0
- package/dist/agentic/shared/ai/skills/om-help/references/task-families.md +20 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/SKILL.md +33 -152
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/phases-and-gates.md +33 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/planning-and-progress.md +40 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/report-templates.md +27 -0
- package/dist/agentic/shared/ai/skills/om-implement-spec/references/spec-resolution.md +24 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +25 -708
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/package-and-activation.md +16 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +25 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/security-and-reliability.md +15 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/sync-and-files.md +12 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/SKILL.md +34 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/agents/openai.yaml +4 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/agentic-setup.md +11 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/input-normalization.md +31 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +39 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/report-template.md +43 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/rules.md +11 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +20 -820
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +32 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/business-one-shot-blueprints.md +172 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +14 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/discovery-surface-catalog.md +83 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +40 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/planning.md +11 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/runtime-cache-and-queues.md +22 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/verification.md +13 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/SKILL.md +41 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/agentic-setup.md +19 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/bundle-preparation.md +44 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/consent-and-review.md +39 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/publication.md +20 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/report-templates.md +57 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/references/rules.md +11 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +486 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +20 -843
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +42 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/mechanism-selector.md +27 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/read-write-roundtrip.md +13 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +43 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/verification.md +11 -0
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/SKILL.md +15 -63
- package/dist/agentic/shared/ai/skills/om-trim-unused-modules/references/dependency-and-redirect.md +15 -0
- package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +17 -467
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +29 -0
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/regression-oracles.md +14 -0
- package/dist/agentic/shared/ai/skills/tiers.json +143 -21
- package/dist/agentic/shared/ai/skills/tiers.schema.json +52 -40
- package/dist/agentic/shared/ai/specs/README.md +4 -3
- package/dist/agentic/shared/ai/specs/SPEC-000-template.md +226 -10
- package/dist/agentic/shared/ai/trackers/github.md +108 -4
- package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +224 -0
- package/dist/agentic/shared/scripts/check-lessons.mjs +178 -0
- package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +3585 -0
- package/dist/agentic/shared/scripts/execution-sandbox.mjs +329 -0
- package/dist/agentic/shared/scripts/framework-context.mjs +888 -0
- package/dist/agentic/shared/scripts/install-skills.mjs +1029 -0
- package/dist/agentic/shared/scripts/install-skills.sh +4 -694
- package/dist/agentic/shared/scripts/prepare-agent-harness-fixture.mjs +222 -0
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +1774 -0
- package/dist/agentic/shared/scripts/validate-knowledge-change.mjs +911 -0
- package/dist/bin.js +13 -1
- package/dist/bin.js.map +2 -2
- package/dist/lib/__integration__/TC-INT-008.spec.js +88 -8
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-init.js +13 -3
- package/dist/lib/agentic-init.js.map +2 -2
- package/dist/lib/agentic-setup.js +434 -186
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/extensions/injection-widgets.js +20 -0
- package/dist/lib/generators/extensions/injection-widgets.js.map +2 -2
- package/dist/lib/generators/module-extension-facts.js +1872 -0
- package/dist/lib/generators/module-extension-facts.js.map +7 -0
- package/dist/lib/generators/module-fact-sources.js +70 -0
- package/dist/lib/generators/module-fact-sources.js.map +7 -0
- package/dist/lib/generators/module-facts-discovery.js +64 -7
- package/dist/lib/generators/module-facts-discovery.js.map +2 -2
- package/dist/lib/generators/module-facts.js +1629 -52
- package/dist/lib/generators/module-facts.js.map +3 -3
- package/dist/lib/generators/module-override-targets.js +688 -0
- package/dist/lib/generators/module-override-targets.js.map +7 -0
- package/dist/lib/generators/module-registry.js +11 -5
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/load-env.js +24 -0
- package/dist/lib/load-env.js.map +7 -0
- package/dist/lib/resolver.js +2 -0
- package/dist/lib/resolver.js.map +2 -2
- package/dist/lib/telemetry-init.js +358 -0
- package/dist/lib/telemetry-init.js.map +7 -0
- package/dist/lib/testing/integration.js +5 -2
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +23 -1
- package/dist/mercato.js.map +2 -2
- package/package.json +13 -11
- package/src/bin.ts +33 -1
- package/src/lib/__integration__/TC-INT-008.spec.ts +107 -9
- package/src/lib/__tests__/agentic-init.test.ts +41 -5
- package/src/lib/__tests__/agentic-setup.ownership.test.ts +386 -0
- package/src/lib/__tests__/injection-widget-id-validation.test.ts +184 -0
- package/src/lib/__tests__/load-env.test.ts +65 -0
- package/src/lib/__tests__/telemetry-init.test.ts +298 -0
- package/src/lib/agentic-init.ts +15 -3
- package/src/lib/agentic-setup.ts +573 -222
- package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +92 -0
- package/src/lib/generators/__tests__/module-extension-activations.test.ts +762 -0
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +603 -0
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +139 -2
- package/src/lib/generators/__tests__/module-facts.computed-di-token.test.ts +88 -0
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -0
- package/src/lib/generators/__tests__/module-facts.discovery.test.ts +54 -10
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +108 -0
- package/src/lib/generators/__tests__/module-facts.local-reference.test.ts +391 -0
- package/src/lib/generators/__tests__/module-facts.owned-contracts.test.ts +561 -0
- package/src/lib/generators/__tests__/module-facts.search-entity-id.test.ts +151 -0
- package/src/lib/generators/__tests__/module-facts.source-links.test.ts +160 -0
- package/src/lib/generators/__tests__/module-override-targets.roundtrip.test.ts +149 -0
- package/src/lib/generators/__tests__/module-override-targets.test.ts +328 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +18 -0
- package/src/lib/generators/extensions/injection-widgets.ts +51 -0
- package/src/lib/generators/module-extension-facts.ts +2433 -0
- package/src/lib/generators/module-fact-sources.ts +108 -0
- package/src/lib/generators/module-facts-discovery.ts +104 -7
- package/src/lib/generators/module-facts.ts +2387 -138
- package/src/lib/generators/module-override-targets.ts +863 -0
- package/src/lib/generators/module-registry.ts +16 -6
- package/src/lib/load-env.ts +30 -0
- package/src/lib/resolver.ts +3 -0
- package/src/lib/telemetry-init.ts +461 -0
- package/src/lib/testing/__tests__/integration.test.ts +4 -0
- package/src/lib/testing/integration.ts +5 -2
- package/src/mercato.ts +26 -1
- package/dist/agentic/guides/cache.md +0 -45
- package/dist/agentic/guides/core.md +0 -453
- package/dist/agentic/guides/events.md +0 -117
- package/dist/agentic/guides/queue.md +0 -53
- package/dist/agentic/guides/search.md +0 -115
- package/dist/agentic/guides/shared.md +0 -108
- package/dist/agentic/guides/ui.md +0 -347
- package/dist/agentic/shared/ai/skills/om-auto-continue-pr-loop/SKILL.md +0 -27
- package/dist/agentic/shared/ai/skills/om-auto-create-pr-loop/SKILL.md +0 -27
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/ui-components.md +0 -260
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md +0 -146
- package/dist/agentic/shared/ai/skills/om-help/references/skills-catalog.md +0 -84
- package/dist/agentic/shared/ai/skills/om-help/references/workflow-sequences.md +0 -193
- package/dist/agentic/shared/ai/skills/om-integration-builder/STANDALONE.md +0 -34
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/adapter-contracts.md +0 -762
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/naming-conventions.md +0 -50
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/navigation-patterns.md +0 -97
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-contracts.md +0 -271
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnostic-commands.md +0 -101
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
-
import { extractAllModuleFacts } from '../module-facts'
|
|
3
|
+
import { extractAllModuleFacts, isExactSourceFilePath, renderModuleFactsJson } from '../module-facts'
|
|
4
4
|
import { discoverPackageModuleSources } from '../module-facts-discovery'
|
|
5
5
|
import { createResolver } from '../../resolver'
|
|
6
6
|
|
|
@@ -17,10 +17,131 @@ function isUnique(values: string[]): boolean {
|
|
|
17
17
|
return values.length === new Set(values).size
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
const MARKDOWN_LINK_TARGET = /\]\(\.\.\/\.\.\/\.\.\/([^)#]+)(?:#L\d+)?\)/g
|
|
21
|
+
|
|
22
|
+
function collectLinkTargets(markdown: string): string[] {
|
|
23
|
+
return [...markdown.matchAll(MARKDOWN_LINK_TARGET)].map((match) => match[1])
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
describe('module-facts BC resolve guard (T2)', () => {
|
|
21
27
|
const repoRoot = findRepoRoot()
|
|
22
28
|
const sources = discoverPackageModuleSources(createResolver(repoRoot))
|
|
23
|
-
const
|
|
29
|
+
const extractionStartedAt = process.cpuUsage()
|
|
30
|
+
const { factsByModule, markdownByModule, frameworkMarkdown } = extractAllModuleFacts({ sources })
|
|
31
|
+
const extractionCpuUsage = process.cpuUsage(extractionStartedAt)
|
|
32
|
+
const extractionCpuDurationMs = (extractionCpuUsage.user + extractionCpuUsage.system) / 1_000
|
|
33
|
+
|
|
34
|
+
it('emits complete, deterministic extension catalogs for every resolved module', () => {
|
|
35
|
+
const repeated = extractAllModuleFacts({ sources })
|
|
36
|
+
expect(renderModuleFactsJson(repeated.factsByModule)).toBe(renderModuleFactsJson(factsByModule))
|
|
37
|
+
expect(repeated.markdownByModule).toEqual(markdownByModule)
|
|
38
|
+
expect(repeated.frameworkMarkdown).toBe(frameworkMarkdown)
|
|
39
|
+
for (const facts of Object.values(factsByModule)) {
|
|
40
|
+
expect(facts.extensionSurfaces).toBeDefined()
|
|
41
|
+
expect(facts.extensionSurfaces?.unresolved).toEqual([])
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('keeps generated extension facts within bounded build-time and context budgets', () => {
|
|
46
|
+
const completeJson = renderModuleFactsJson(factsByModule)
|
|
47
|
+
const legacyJson = renderModuleFactsJson(Object.fromEntries(
|
|
48
|
+
Object.entries(factsByModule).map(([moduleId, facts]) => [moduleId, { ...facts, extensionSurfaces: undefined }]),
|
|
49
|
+
))
|
|
50
|
+
const markdownBytes = Object.values(markdownByModule)
|
|
51
|
+
.reduce((total, markdown) => total + Buffer.byteLength(markdown), Buffer.byteLength(frameworkMarkdown))
|
|
52
|
+
|
|
53
|
+
// Budget raised by the bidirectional-topology spec
|
|
54
|
+
// (2026-08-02-module-facts-extension-activation-and-incoming-index): the
|
|
55
|
+
// additive `activations`, cross-module `incoming`, and per-contribution
|
|
56
|
+
// `contributionResolutions` layers add ~210KB of compact references (no
|
|
57
|
+
// contribution payloads are duplicated). Incoming rows are cross-module only;
|
|
58
|
+
// resolution rows are required one-per-contribution by the spec's acceptance
|
|
59
|
+
// criteria and are the dominant term.
|
|
60
|
+
//
|
|
61
|
+
// JSON cap raised again by the exact-override-targets spec
|
|
62
|
+
// (2026-08-02-module-facts-exact-override-targets): the additive per-module
|
|
63
|
+
// `overrideTargets` project one exact key per real override entry (acl
|
|
64
|
+
// features, di tokens, subscribers, pages, workers, encryption, widgets,
|
|
65
|
+
// notifications, cli, setup, ai, interceptors/enrichers, page guards). These
|
|
66
|
+
// are required exhaustively by the spec's acceptance criteria; targets carry
|
|
67
|
+
// only compact structured path/key/factRef/source refs (no runtime values or
|
|
68
|
+
// contribution payloads). The delta cap is unchanged because `overrideTargets`
|
|
69
|
+
// live in both the complete and legacy renders (only `extensionSurfaces` is
|
|
70
|
+
// stripped for the legacy comparison).
|
|
71
|
+
//
|
|
72
|
+
// JSON cap raised a third time by the uniform provenance index
|
|
73
|
+
// (2026-08-02-module-facts-source-provenance-and-contract-inventory): every
|
|
74
|
+
// proven `(kind, id)` now reaches `factSources` (~630KB across the repo), so a
|
|
75
|
+
// consumer resolves any fact's origin through one lookup. Entries whose
|
|
76
|
+
// declaration site is already serialized inline (routes, pages, CLI commands,
|
|
77
|
+
// AI tools/agents, owned contracts, hosts, contributions) emit a typed
|
|
78
|
+
// `factRef` pointer instead of a duplicated source ref, and `factKey` is
|
|
79
|
+
// omitted when it equals the entry `id` — so the index costs references, never
|
|
80
|
+
// copied provenance payloads. The cap also covers the newly reachable
|
|
81
|
+
// framework-host activations (dashboard/menu/notification contributions now
|
|
82
|
+
// resolve as bound instead of silently falling back to capability-only).
|
|
83
|
+
// This is a blow-up detector, not a performance target. It measures CPU time
|
|
84
|
+
// for a whole-repo extraction, and CPU time for fixed work varies with the
|
|
85
|
+
// machine: the same extraction measures ~7.3s on a developer workstation and
|
|
86
|
+
// ~30.0s on a CI runner. At the previous 30s cap CI sat exactly on the line
|
|
87
|
+
// (an observed failure at 30,052.8ms), so the guard could not tell a genuine
|
|
88
|
+
// pathological regression from ordinary hardware variance and failed
|
|
89
|
+
// unrelated PRs at random. 90s keeps it meaningful — a real blow-up here is
|
|
90
|
+
// multiplicative, not a few percent — while leaving CI roughly 3x headroom.
|
|
91
|
+
expect(extractionCpuDurationMs).toBeLessThan(90_000)
|
|
92
|
+
// JSON cap raised a fourth time by the injection-table slot normalization:
|
|
93
|
+
// `extractInjectionTable` previously did `if (!Array.isArray(entries)) continue`,
|
|
94
|
+
// silently dropping every string and single-object slot form that
|
|
95
|
+
// `ModuleInjectionTable` allows. Twelve real contributions across catalog, sales,
|
|
96
|
+
// wms, staff, integrations and checkout were therefore invisible to every fact
|
|
97
|
+
// consumer — `integrations` published no contributions at all. Reading them costs
|
|
98
|
+
// ~28KB, which is the fix working, not drift.
|
|
99
|
+
expect(Buffer.byteLength(completeJson)).toBeLessThan(3_560_000)
|
|
100
|
+
expect(Buffer.byteLength(completeJson) - Buffer.byteLength(legacyJson)).toBeLessThan(1_800_000)
|
|
101
|
+
// Markdown cap raised with the source-link contract: entities, events, ACL
|
|
102
|
+
// features, DI tokens, search entities, notifications, UMES hosts and UMES
|
|
103
|
+
// contributions all render a resolved Source cell, and contribution
|
|
104
|
+
// resolutions render as their own source-linked section.
|
|
105
|
+
expect(markdownBytes).toBeLessThan(1_550_000)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('links every generated fact to an exact resolvable file, never a directory', () => {
|
|
109
|
+
const packageLinkRoot = path.join(repoRoot, 'node_modules', '@open-mercato')
|
|
110
|
+
const canCheckDisk = fs.existsSync(packageLinkRoot)
|
|
111
|
+
const nonExactTargets = new Set<string>()
|
|
112
|
+
const unresolvedTargets = new Set<string>()
|
|
113
|
+
let checkedTargets = 0
|
|
114
|
+
|
|
115
|
+
for (const markdown of Object.values(markdownByModule)) {
|
|
116
|
+
for (const target of collectLinkTargets(markdown)) {
|
|
117
|
+
checkedTargets += 1
|
|
118
|
+
if (!isExactSourceFilePath(target)) {
|
|
119
|
+
nonExactTargets.add(target)
|
|
120
|
+
continue
|
|
121
|
+
}
|
|
122
|
+
if (!canCheckDisk) continue
|
|
123
|
+
const absolute = path.join(repoRoot, target)
|
|
124
|
+
if (!fs.existsSync(absolute) || !fs.statSync(absolute).isFile()) unresolvedTargets.add(target)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
expect(checkedTargets).toBeGreaterThan(1_000)
|
|
129
|
+
expect([...nonExactTargets]).toEqual([])
|
|
130
|
+
expect([...unresolvedTargets]).toEqual([])
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('keeps directory-valued provenance readable as plain text', () => {
|
|
134
|
+
const frameworkHostMarkdowns = Object.values(markdownByModule)
|
|
135
|
+
.filter((markdown) => markdown.includes('packages/ui/src'))
|
|
136
|
+
expect(frameworkHostMarkdowns.length).toBeGreaterThan(0)
|
|
137
|
+
for (const markdown of frameworkHostMarkdowns) {
|
|
138
|
+
expect(markdown).not.toContain('(../../../packages/ui/src)')
|
|
139
|
+
}
|
|
140
|
+
for (const [moduleId, facts] of Object.entries(factsByModule)) {
|
|
141
|
+
expect(markdownByModule[moduleId]).toContain(`Source root: ${facts.sourceRoot}\n`)
|
|
142
|
+
expect(markdownByModule[moduleId]).not.toContain(`(../../../${facts.sourceRoot})`)
|
|
143
|
+
}
|
|
144
|
+
})
|
|
24
145
|
|
|
25
146
|
it('discovers a superset of the historical core modules', () => {
|
|
26
147
|
const discovered = new Set(Object.keys(factsByModule))
|
|
@@ -30,11 +151,27 @@ describe('module-facts BC resolve guard (T2)', () => {
|
|
|
30
151
|
expect(discovered.size).toBeGreaterThan(9)
|
|
31
152
|
})
|
|
32
153
|
|
|
154
|
+
it('keeps factory-built and generated-registry enricher contributions visible', () => {
|
|
155
|
+
expect(factsByModule.sales.extensionSurfaces?.contributions).toEqual(expect.arrayContaining([
|
|
156
|
+
expect.objectContaining({ id: 'sales.catalog-image:sales:sales_quote_line', kind: 'response-enricher' }),
|
|
157
|
+
expect.objectContaining({ id: 'sales.catalog-image:sales:sales_order_line', kind: 'response-enricher' }),
|
|
158
|
+
]))
|
|
159
|
+
expect(factsByModule.wms.extensionSurfaces?.contributions).toEqual(expect.arrayContaining([
|
|
160
|
+
expect.objectContaining({ id: 'wms.sales-order-inventory', kind: 'response-enricher' }),
|
|
161
|
+
]))
|
|
162
|
+
})
|
|
163
|
+
|
|
33
164
|
for (const source of sources) {
|
|
34
165
|
const moduleId = source.moduleId
|
|
35
166
|
describe(`${moduleId}`, () => {
|
|
36
167
|
const facts = factsByModule[moduleId]
|
|
37
168
|
|
|
169
|
+
it('stamps the exact providing package and version without removing coreVersion', () => {
|
|
170
|
+
expect(facts.sourcePackage).toBe(source.from ?? null)
|
|
171
|
+
expect(facts.sourceVersion).toBe(source.packageVersion ?? null)
|
|
172
|
+
expect(facts).toHaveProperty('coreVersion')
|
|
173
|
+
})
|
|
174
|
+
|
|
38
175
|
// Entity / search / host ids are colon-namespaced under the module by construction
|
|
39
176
|
// and convention; drift here means the builder or a module's data model broke.
|
|
40
177
|
it('colon-namespaces entity / search / host ids under the module and keeps ids unique', () => {
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { extractModuleFacts } from '../module-facts'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A DI token registered through a computed key must still reach module facts.
|
|
8
|
+
*
|
|
9
|
+
* `container.register({ [SERVICE_TOKEN]: asFunction(...) })` — reading the token from an
|
|
10
|
+
* exported const — is the idiomatic, type-safe registration. `getPropertyName` returned
|
|
11
|
+
* undefined for a `ts.ComputedPropertyName`, so the whole registration vanished with NO
|
|
12
|
+
* diagnostic: the unresolved-token path is only reached for a NAMED token whose Awilix kind
|
|
13
|
+
* is unrecognised, so a computed key failed silently rather than being reported.
|
|
14
|
+
*
|
|
15
|
+
* That produced a capability the inventory claimed and the extractor scored zero for. Found
|
|
16
|
+
* by an agent that ran the real extractor instead of trusting the row.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
function write(filePath: string, source: string): void {
|
|
20
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
21
|
+
fs.writeFileSync(filePath, source)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function factsFor(diSource: string): Array<{ id: string; metadata?: Record<string, unknown> }> {
|
|
25
|
+
const moduleRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'om-computed-di-'))
|
|
26
|
+
try {
|
|
27
|
+
write(path.join(moduleRoot, 'di.ts'), diSource)
|
|
28
|
+
const facts = extractModuleFacts({
|
|
29
|
+
moduleId: 'probe',
|
|
30
|
+
moduleRoot,
|
|
31
|
+
sourceRoot: 'src/modules/probe',
|
|
32
|
+
}) as { ownedContracts?: Record<string, Array<{ id: string; metadata?: Record<string, unknown> }>> }
|
|
33
|
+
return facts.ownedContracts?.['di-registration'] ?? []
|
|
34
|
+
} finally {
|
|
35
|
+
fs.rmSync(moduleRoot, { recursive: true, force: true })
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('module-facts DI registration with a computed token', () => {
|
|
40
|
+
it('resolves a token declared as a same-file const', () => {
|
|
41
|
+
const facts = factsFor(`
|
|
42
|
+
import { asFunction } from 'awilix'
|
|
43
|
+
export const PROBE_SERVICE = 'probeService' as const
|
|
44
|
+
export function register(container: any) {
|
|
45
|
+
container.register({ [PROBE_SERVICE]: asFunction(createProbeService).scoped() })
|
|
46
|
+
}
|
|
47
|
+
`)
|
|
48
|
+
|
|
49
|
+
expect(facts).toHaveLength(1)
|
|
50
|
+
expect(facts[0].id).toBe('probeService')
|
|
51
|
+
expect(facts[0].metadata).toMatchObject({ registrationKind: 'function', lifetime: 'scoped' })
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('resolves a token written as a computed string literal', () => {
|
|
55
|
+
const facts = factsFor(`
|
|
56
|
+
import { asValue } from 'awilix'
|
|
57
|
+
export function register(container: any) {
|
|
58
|
+
container.register({ ['literalToken']: asValue(42) })
|
|
59
|
+
}
|
|
60
|
+
`)
|
|
61
|
+
|
|
62
|
+
expect(facts.map((fact) => fact.id)).toEqual(['literalToken'])
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('still resolves plain identifier and string keys', () => {
|
|
66
|
+
const facts = factsFor(`
|
|
67
|
+
import { asValue } from 'awilix'
|
|
68
|
+
export function register(container: any) {
|
|
69
|
+
container.register({ plainKey: asValue(1), 'quotedKey': asValue(2) })
|
|
70
|
+
}
|
|
71
|
+
`)
|
|
72
|
+
|
|
73
|
+
expect(facts.map((fact) => fact.id).sort()).toEqual(['plainKey', 'quotedKey'])
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('leaves a genuinely dynamic token unresolved rather than inventing one', () => {
|
|
77
|
+
// A key the reader cannot know statically must NOT be guessed. Emitting a wrong token
|
|
78
|
+
// would be worse than emitting none.
|
|
79
|
+
const facts = factsFor(`
|
|
80
|
+
import { asValue } from 'awilix'
|
|
81
|
+
export function register(container: any, name: string) {
|
|
82
|
+
container.register({ [name]: asValue(1) })
|
|
83
|
+
}
|
|
84
|
+
`)
|
|
85
|
+
|
|
86
|
+
expect(facts).toEqual([])
|
|
87
|
+
})
|
|
88
|
+
})
|
|
@@ -52,6 +52,7 @@ describe('module-facts customers fixture (T1 anti-drift guard)', () => {
|
|
|
52
52
|
'customers.companies.list',
|
|
53
53
|
'customers.deals.list',
|
|
54
54
|
'customers.people.list',
|
|
55
|
+
'customers.todos.list',
|
|
55
56
|
])
|
|
56
57
|
expect(facts.hostTokens.entityIds).toEqual(['customers:customer_entity'])
|
|
57
58
|
expect(facts.diTokens).toEqual([])
|
|
@@ -4,11 +4,13 @@ import path from 'node:path'
|
|
|
4
4
|
import type { PackageResolver } from '../../resolver'
|
|
5
5
|
import { discoverPackageModuleSources, hasReadableModuleSource } from '../module-facts-discovery'
|
|
6
6
|
|
|
7
|
-
type FakePackage = { name: string; path: string; modulesPath: string }
|
|
7
|
+
type FakePackage = { name: string; version?: string | null; path: string; modulesPath: string }
|
|
8
|
+
type FakeModuleEntry = { id: string; from?: string }
|
|
8
9
|
|
|
9
|
-
function makeResolver(packages: FakePackage[]): PackageResolver {
|
|
10
|
+
function makeResolver(packages: FakePackage[], enabledModules: FakeModuleEntry[] = []): PackageResolver {
|
|
10
11
|
return {
|
|
11
12
|
discoverPackages: () => packages,
|
|
13
|
+
loadEnabledModules: () => enabledModules,
|
|
12
14
|
} as unknown as PackageResolver
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -62,27 +64,69 @@ describe('module-facts discovery (T1)', () => {
|
|
|
62
64
|
writeModule(path.join(pkgSrc, 'src', 'modules'), 'gamma', 'events.ts')
|
|
63
65
|
|
|
64
66
|
const resolver = makeResolver([
|
|
65
|
-
{ name: '@open-mercato/tagged', path: pkgSrc, modulesPath: path.join(pkgSrc, 'src', 'modules') },
|
|
67
|
+
{ name: '@open-mercato/tagged', version: '0.6.6', path: pkgSrc, modulesPath: path.join(pkgSrc, 'src', 'modules') },
|
|
66
68
|
])
|
|
67
69
|
|
|
68
70
|
const [source] = discoverPackageModuleSources(resolver)
|
|
69
|
-
expect(source).toMatchObject({
|
|
71
|
+
expect(source).toMatchObject({
|
|
72
|
+
moduleId: 'gamma',
|
|
73
|
+
from: '@open-mercato/tagged',
|
|
74
|
+
packageVersion: '0.6.6',
|
|
75
|
+
})
|
|
70
76
|
expect(source.moduleRoot).toBe(path.join(pkgSrc, 'src', 'modules', 'gamma'))
|
|
71
77
|
})
|
|
72
78
|
|
|
73
|
-
it('
|
|
79
|
+
it('fails closed on duplicate module ids and reports every provider independent of discovery order', () => {
|
|
74
80
|
const pkgA = path.join(tmp, 'dup-a')
|
|
75
81
|
writeModule(path.join(pkgA, 'src', 'modules'), 'shared', 'index.ts')
|
|
76
82
|
const pkgB = path.join(tmp, 'dup-b')
|
|
77
83
|
writeModule(path.join(pkgB, 'src', 'modules'), 'shared', 'index.ts')
|
|
78
84
|
|
|
79
|
-
const
|
|
85
|
+
const packages = [
|
|
80
86
|
{ name: '@open-mercato/dup-a', path: pkgA, modulesPath: path.join(pkgA, 'src', 'modules') },
|
|
81
87
|
{ name: '@open-mercato/dup-b', path: pkgB, modulesPath: path.join(pkgB, 'src', 'modules') },
|
|
82
|
-
]
|
|
88
|
+
]
|
|
89
|
+
const expected = '[module-facts] duplicate module id "shared" is provided by '
|
|
90
|
+
+ '@open-mercato/dup-a, @open-mercato/dup-b; src/modules.ts does not select a provider. '
|
|
91
|
+
+ 'Select exactly one matching provider in src/modules.ts.'
|
|
92
|
+
|
|
93
|
+
expect(() => discoverPackageModuleSources(makeResolver(packages))).toThrow(expected)
|
|
94
|
+
expect(() => discoverPackageModuleSources(makeResolver([...packages].reverse()))).toThrow(expected)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('uses the exact src/modules.ts provider even when package discovery order is reversed', () => {
|
|
98
|
+
const pkgA = path.join(tmp, 'selected-a')
|
|
99
|
+
writeModule(path.join(pkgA, 'src', 'modules'), 'shared', 'index.ts')
|
|
100
|
+
const pkgB = path.join(tmp, 'selected-b')
|
|
101
|
+
writeModule(path.join(pkgB, 'src', 'modules'), 'shared', 'index.ts')
|
|
102
|
+
|
|
103
|
+
const packages = [
|
|
104
|
+
{ name: '@open-mercato/selected-a', path: pkgA, modulesPath: path.join(pkgA, 'src', 'modules') },
|
|
105
|
+
{ name: '@open-mercato/selected-b', path: pkgB, modulesPath: path.join(pkgB, 'src', 'modules') },
|
|
106
|
+
]
|
|
107
|
+
const enabled = [{ id: 'shared', from: '@open-mercato/selected-b' }]
|
|
108
|
+
|
|
109
|
+
for (const discoveredPackages of [packages, [...packages].reverse()]) {
|
|
110
|
+
const sources = discoverPackageModuleSources(makeResolver(discoveredPackages, enabled))
|
|
111
|
+
expect(sources).toHaveLength(1)
|
|
112
|
+
expect(sources[0]).toMatchObject({ moduleId: 'shared', from: '@open-mercato/selected-b' })
|
|
113
|
+
expect(sources[0].moduleRoot).toBe(path.join(pkgB, 'src', 'modules', 'shared'))
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('explains that an omitted provider implicitly selects core', () => {
|
|
118
|
+
const pkgA = path.join(tmp, 'implicit-a')
|
|
119
|
+
writeModule(path.join(pkgA, 'src', 'modules'), 'shared', 'index.ts')
|
|
120
|
+
const pkgB = path.join(tmp, 'implicit-b')
|
|
121
|
+
writeModule(path.join(pkgB, 'src', 'modules'), 'shared', 'index.ts')
|
|
122
|
+
|
|
123
|
+
const packages = [
|
|
124
|
+
{ name: '@open-mercato/dup-a', path: pkgA, modulesPath: path.join(pkgA, 'src', 'modules') },
|
|
125
|
+
{ name: '@open-mercato/dup-b', path: pkgB, modulesPath: path.join(pkgB, 'src', 'modules') },
|
|
126
|
+
]
|
|
83
127
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
128
|
+
expect(() => discoverPackageModuleSources(makeResolver(packages, [{ id: 'shared' }]))).toThrow(
|
|
129
|
+
'src/modules.ts omits "from", which defaults to @open-mercato/core',
|
|
130
|
+
)
|
|
87
131
|
})
|
|
88
132
|
})
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { extractModuleFacts } from '../module-facts'
|
|
5
|
+
|
|
6
|
+
function findCoreSrcRoot(): string {
|
|
7
|
+
let dir = __dirname
|
|
8
|
+
for (let depth = 0; depth < 10; depth += 1) {
|
|
9
|
+
const candidate = path.join(dir, 'packages', 'core', 'src', 'modules')
|
|
10
|
+
if (fs.existsSync(candidate)) return candidate
|
|
11
|
+
dir = path.dirname(dir)
|
|
12
|
+
}
|
|
13
|
+
throw new Error('[internal] could not locate packages/core/src/modules from the test directory')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function write(filePath: string, source: string): void {
|
|
17
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
18
|
+
fs.writeFileSync(filePath, source)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('module-facts extension host extraction', () => {
|
|
22
|
+
const coreSrcRoot = findCoreSrcRoot()
|
|
23
|
+
|
|
24
|
+
it('resolves generated E.<module>.<entity> custom-field declarations from shipped modules', () => {
|
|
25
|
+
const expectedByModule: Record<string, string[]> = {
|
|
26
|
+
attachments: ['attachments:attachment'],
|
|
27
|
+
catalog: [
|
|
28
|
+
'catalog:catalog_product',
|
|
29
|
+
'catalog:catalog_product_variant',
|
|
30
|
+
'catalog:catalog_product_price',
|
|
31
|
+
],
|
|
32
|
+
sales: [
|
|
33
|
+
'sales:sales_order',
|
|
34
|
+
'sales:sales_order_line',
|
|
35
|
+
'sales:sales_order_adjustment',
|
|
36
|
+
'sales:sales_quote',
|
|
37
|
+
'sales:sales_quote_line',
|
|
38
|
+
'sales:sales_quote_adjustment',
|
|
39
|
+
'sales:sales_invoice',
|
|
40
|
+
'sales:sales_invoice_line',
|
|
41
|
+
'sales:sales_payment',
|
|
42
|
+
'sales:sales_payment_allocation',
|
|
43
|
+
'sales:sales_credit_memo',
|
|
44
|
+
'sales:sales_credit_memo_line',
|
|
45
|
+
'sales:sales_shipment',
|
|
46
|
+
'sales:sales_shipment_item',
|
|
47
|
+
'sales:sales_note',
|
|
48
|
+
],
|
|
49
|
+
staff: ['staff:staff_team_member'],
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const [moduleId, expected] of Object.entries(expectedByModule)) {
|
|
53
|
+
const facts = extractModuleFacts({ moduleId, coreSrcRoot })
|
|
54
|
+
expect(facts.entities.filter((entity) => entity.customFields).map((entity) => entity.id).sort()).toEqual(
|
|
55
|
+
[...expected].sort(),
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('discovers literal and conditional DataTable IDs outside backend while excluding test sources', () => {
|
|
61
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'module-facts-extension-hosts-'))
|
|
62
|
+
const moduleRoot = path.join(tmpRoot, 'alpha')
|
|
63
|
+
try {
|
|
64
|
+
write(
|
|
65
|
+
path.join(moduleRoot, 'data', 'entities.ts'),
|
|
66
|
+
`@Entity({ tableName: 'alpha_records' })\nexport class AlphaRecord { updatedAt?: Date }\n`,
|
|
67
|
+
)
|
|
68
|
+
write(
|
|
69
|
+
path.join(moduleRoot, 'ce.ts'),
|
|
70
|
+
`export const entities = [{ id: E.alpha.alpha_record, fields: [] }]\n`,
|
|
71
|
+
)
|
|
72
|
+
write(
|
|
73
|
+
path.join(moduleRoot, 'components', 'AlphaTable.tsx'),
|
|
74
|
+
`export const props = {
|
|
75
|
+
perspective: { tableId: kind === 'one' ? 'alpha.one' : 'alpha.two' },
|
|
76
|
+
extensionTableId: 'alpha.extension',
|
|
77
|
+
}\n`,
|
|
78
|
+
)
|
|
79
|
+
write(
|
|
80
|
+
path.join(moduleRoot, 'components', 'Noise.test.tsx'),
|
|
81
|
+
`export const noise = { tableId: 'alpha.test-noise' }\n`,
|
|
82
|
+
)
|
|
83
|
+
write(
|
|
84
|
+
path.join(moduleRoot, 'backend', '__tests__', 'noise.tsx'),
|
|
85
|
+
`export const noise = { extensionTableId: 'alpha.test-directory-noise' }\n`,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
const facts = extractModuleFacts({ moduleId: 'alpha', moduleRoot })
|
|
89
|
+
expect(facts.entities).toEqual([
|
|
90
|
+
expect.objectContaining({ id: 'alpha:alpha_record', customFields: true }),
|
|
91
|
+
])
|
|
92
|
+
expect(facts.hostTokens.tableIds).toEqual(['alpha.extension', 'alpha.one', 'alpha.two'])
|
|
93
|
+
} finally {
|
|
94
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true })
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('captures shipped component-level table hosts used by catalog and sales', () => {
|
|
99
|
+
const catalog = extractModuleFacts({ moduleId: 'catalog', coreSrcRoot })
|
|
100
|
+
expect(catalog.hostTokens.tableIds).toEqual([
|
|
101
|
+
'catalog.categories.list',
|
|
102
|
+
'catalog.products.list',
|
|
103
|
+
])
|
|
104
|
+
|
|
105
|
+
const sales = extractModuleFacts({ moduleId: 'sales', coreSrcRoot })
|
|
106
|
+
expect(sales.hostTokens.tableIds).toEqual(['sales.orders', 'sales.quotes'])
|
|
107
|
+
})
|
|
108
|
+
})
|