@open-mercato/cli 0.6.7 → 0.6.8-canary.320.1.bf889f49e4
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/AGENTS.md +6 -1
- 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 +86 -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 +6942 -0
- package/dist/agentic/guides/reference-modules/example.md +462 -0
- package/dist/agentic/guides/spec-delivery.md +56 -0
- package/dist/agentic/guides/testing-debugging.md +80 -0
- package/dist/agentic/guides/upstream/AGENTS.md +300 -0
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +334 -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 +59 -0
- package/dist/agentic/shared/ai/harness/cases.json +20596 -0
- package/dist/agentic/shared/ai/harness/cases.schema.json +196 -0
- package/dist/agentic/shared/ai/harness/design-system-inventory.json +6326 -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 +136 -0
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +22 -0
- package/dist/agentic/shared/ai/harness/source-link-inventory.json +1706 -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 +602 -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 +133 -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/2026-08-06-reference-module-activation.md +248 -0
- 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 +3812 -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 +1172 -0
- package/dist/bin.js +32 -34
- 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/cli-bootstrap-mode.js +32 -0
- package/dist/lib/cli-bootstrap-mode.js.map +7 -0
- package/dist/lib/dev-supervisor-manifest.js +105 -0
- package/dist/lib/dev-supervisor-manifest.js.map +7 -0
- package/dist/lib/generate-watch-events.js +15 -0
- package/dist/lib/generate-watch-events.js.map +2 -2
- package/dist/lib/generators/entity-ids.js +11 -24
- package/dist/lib/generators/entity-ids.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-di.js +10 -23
- package/dist/lib/generators/module-di.js.map +2 -2
- package/dist/lib/generators/module-entities.js +10 -23
- package/dist/lib/generators/module-entities.js.map +2 -2
- package/dist/lib/generators/module-extension-facts.js +1882 -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 +1913 -52
- package/dist/lib/generators/module-facts.js.map +3 -3
- package/dist/lib/generators/module-override-targets.js +712 -0
- package/dist/lib/generators/module-override-targets.js.map +7 -0
- package/dist/lib/generators/module-registry.js +405 -36
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/generators/route-manifest-shards.js +170 -0
- package/dist/lib/generators/route-manifest-shards.js.map +7 -0
- package/dist/lib/in-process-generate-watcher.js +12 -3
- package/dist/lib/in-process-generate-watcher.js.map +2 -2
- package/dist/lib/load-env.js +24 -0
- package/dist/lib/load-env.js.map +7 -0
- package/dist/lib/queue-worker-supervisor.js.map +2 -2
- package/dist/lib/resolver.js +28 -3
- 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/lib/utils.js +15 -8
- package/dist/lib/utils.js.map +2 -2
- package/dist/mercato.js +35 -9
- package/dist/mercato.js.map +2 -2
- package/package.json +13 -11
- package/src/__tests__/mercato.test.ts +144 -0
- package/src/bin.ts +60 -42
- 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__/cli-bootstrap-mode.test.ts +22 -0
- package/src/lib/__tests__/content-stable-writes.test.ts +74 -0
- package/src/lib/__tests__/dev-supervisor-manifest.test.ts +131 -0
- package/src/lib/__tests__/generate-watch-events.test.ts +76 -0
- package/src/lib/__tests__/in-process-generate-watcher.test.ts +52 -1
- 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__/queue-worker-supervisor.test.ts +33 -0
- package/src/lib/__tests__/resolver.enterprise.test.ts +50 -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/cli-bootstrap-mode.ts +31 -0
- package/src/lib/dev-supervisor-manifest.ts +142 -0
- package/src/lib/generate-watch-events.ts +14 -0
- package/src/lib/generators/__tests__/activation-adapter-coverage.test.ts +92 -0
- package/src/lib/generators/__tests__/entity-ids.test.ts +32 -0
- package/src/lib/generators/__tests__/helpers/override-target-diagnostic-fixtures.ts +150 -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.example-fact-coverage.test.ts +414 -0
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +108 -0
- package/src/lib/generators/__tests__/module-facts.local-reference.test.ts +393 -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.diagnostic-wiring.test.ts +92 -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-override-targets.unknown-mode.test.ts +117 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +266 -0
- package/src/lib/generators/__tests__/output-snapshots.test.ts +3 -3
- package/src/lib/generators/__tests__/route-manifest-shards.test.ts +62 -0
- package/src/lib/generators/entity-ids.ts +10 -26
- package/src/lib/generators/extensions/injection-widgets.ts +51 -0
- package/src/lib/generators/module-di.ts +9 -25
- package/src/lib/generators/module-entities.ts +9 -25
- package/src/lib/generators/module-extension-facts.ts +2472 -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 +2747 -138
- package/src/lib/generators/module-override-targets.ts +907 -0
- package/src/lib/generators/module-registry.ts +448 -35
- package/src/lib/generators/route-manifest-shards.ts +146 -0
- package/src/lib/in-process-generate-watcher.ts +13 -4
- package/src/lib/load-env.ts +30 -0
- package/src/lib/queue-worker-supervisor.ts +7 -2
- package/src/lib/resolver.ts +34 -3
- 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/lib/utils.ts +24 -16
- package/src/mercato.ts +46 -9
- 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
|
@@ -4,6 +4,12 @@ import { pathToFileURL } from 'node:url'
|
|
|
4
4
|
import { VariableDeclarationKind, type WriterFunction } from 'ts-morph'
|
|
5
5
|
import ts from 'typescript-js'
|
|
6
6
|
import type { ModuleEntry, PackageResolver } from '../resolver'
|
|
7
|
+
import {
|
|
8
|
+
DEV_SUPERVISOR_MANIFEST_FILE,
|
|
9
|
+
DEV_SUPERVISOR_MANIFEST_VERSION,
|
|
10
|
+
type DevSupervisorSchedulerStartStatus,
|
|
11
|
+
type DevSupervisorWorkerDescriptor,
|
|
12
|
+
} from '../dev-supervisor-manifest'
|
|
7
13
|
import {
|
|
8
14
|
calculateStructureChecksum,
|
|
9
15
|
toVar,
|
|
@@ -67,6 +73,12 @@ import {
|
|
|
67
73
|
} from './scanner'
|
|
68
74
|
import { loadGeneratorExtensions } from './extensions'
|
|
69
75
|
import type { ModuleScanContext, StandaloneConfigOptions } from './extension'
|
|
76
|
+
import {
|
|
77
|
+
renderRouteManifestShardOutputs,
|
|
78
|
+
renderRouteMetadataOutput,
|
|
79
|
+
routeManifestShardFilePattern,
|
|
80
|
+
type RouteManifestShardEntry,
|
|
81
|
+
} from './route-manifest-shards'
|
|
70
82
|
|
|
71
83
|
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
|
|
72
84
|
|
|
@@ -128,6 +140,10 @@ type CommandLoaderGenerationEntry = {
|
|
|
128
140
|
ids: string[]
|
|
129
141
|
}
|
|
130
142
|
|
|
143
|
+
type WorkerGenerationEntry = DevSupervisorWorkerDescriptor & {
|
|
144
|
+
importPath: string
|
|
145
|
+
}
|
|
146
|
+
|
|
131
147
|
type RuntimeApiMethodMetadata = {
|
|
132
148
|
requireAuth?: boolean
|
|
133
149
|
requireRoles?: string[]
|
|
@@ -144,6 +160,8 @@ type PageRouteGenerationResult = {
|
|
|
144
160
|
eagerRoutes: string[]
|
|
145
161
|
runtimeRoutes: string[]
|
|
146
162
|
manifestRoutes: string[]
|
|
163
|
+
manifestShardRoutes: RouteManifestShardEntry[]
|
|
164
|
+
metadataRoutes: RouteManifestShardEntry[]
|
|
147
165
|
routePatterns: string[]
|
|
148
166
|
}
|
|
149
167
|
|
|
@@ -173,6 +191,8 @@ type ApiRouteGenerationResult = {
|
|
|
173
191
|
eagerApis: string[]
|
|
174
192
|
runtimeApis: string[]
|
|
175
193
|
manifestApis: string[]
|
|
194
|
+
manifestShardApis: RouteManifestShardEntry[]
|
|
195
|
+
metadataApis: RouteManifestShardEntry[]
|
|
176
196
|
}
|
|
177
197
|
|
|
178
198
|
type SerializablePageMetadata = {
|
|
@@ -224,6 +244,8 @@ type SerializableWorkerMetadata = {
|
|
|
224
244
|
id?: string
|
|
225
245
|
queue?: string
|
|
226
246
|
concurrency?: number
|
|
247
|
+
lockDuration?: number
|
|
248
|
+
maxStalledCount?: number
|
|
227
249
|
}
|
|
228
250
|
|
|
229
251
|
type PageMetadataManifestLoadResult = {
|
|
@@ -1155,7 +1177,7 @@ function collectStringArrayElements(expr: ts.Expression, stringConstants: Map<st
|
|
|
1155
1177
|
return values
|
|
1156
1178
|
}
|
|
1157
1179
|
|
|
1158
|
-
function extractCommandIdsFromSource(sourcePath: string): string[] {
|
|
1180
|
+
export function extractCommandIdsFromSource(sourcePath: string): string[] {
|
|
1159
1181
|
const sourceText = fs.readFileSync(sourcePath, 'utf8')
|
|
1160
1182
|
const sourceFile = ts.createSourceFile(sourcePath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
|
|
1161
1183
|
const ids = new Set<string>()
|
|
@@ -1553,6 +1575,8 @@ function normalizeWorkerMetadata(raw: unknown): SerializableWorkerMetadata | nul
|
|
|
1553
1575
|
if (typeof source.id === 'string' && source.id.length > 0) normalized.id = source.id
|
|
1554
1576
|
if (typeof source.queue === 'string' && source.queue.length > 0) normalized.queue = source.queue
|
|
1555
1577
|
if (typeof source.concurrency === 'number') normalized.concurrency = source.concurrency
|
|
1578
|
+
if (typeof source.lockDuration === 'number') normalized.lockDuration = source.lockDuration
|
|
1579
|
+
if (typeof source.maxStalledCount === 'number') normalized.maxStalledCount = source.maxStalledCount
|
|
1556
1580
|
return Object.keys(normalized).length > 0 ? normalized : null
|
|
1557
1581
|
}
|
|
1558
1582
|
|
|
@@ -1627,12 +1651,16 @@ function discoverTranslations(roots: ModuleRoots): DiscoveredTranslation[] {
|
|
|
1627
1651
|
const locales = new Set<string>()
|
|
1628
1652
|
if (fs.existsSync(i18nCore)) {
|
|
1629
1653
|
for (const entry of fs.readdirSync(i18nCore, { withFileTypes: true })) {
|
|
1630
|
-
if (entry.isFile() &&
|
|
1654
|
+
if (entry.isFile() && /^[a-zA-Z0-9][a-zA-Z0-9_-]*\.json$/.test(entry.name)) {
|
|
1655
|
+
locales.add(entry.name.replace(/\.json$/, ''))
|
|
1656
|
+
}
|
|
1631
1657
|
}
|
|
1632
1658
|
}
|
|
1633
1659
|
if (fs.existsSync(i18nApp)) {
|
|
1634
1660
|
for (const entry of fs.readdirSync(i18nApp, { withFileTypes: true })) {
|
|
1635
|
-
if (entry.isFile() &&
|
|
1661
|
+
if (entry.isFile() && /^[a-zA-Z0-9][a-zA-Z0-9_-]*\.json$/.test(entry.name)) {
|
|
1662
|
+
locales.add(entry.name.replace(/\.json$/, ''))
|
|
1663
|
+
}
|
|
1636
1664
|
}
|
|
1637
1665
|
}
|
|
1638
1666
|
return Array.from(locales, (locale) => ({
|
|
@@ -1744,6 +1772,8 @@ async function processPageFiles(options: {
|
|
|
1744
1772
|
const eagerRoutes: string[] = []
|
|
1745
1773
|
const runtimeRoutes: string[] = []
|
|
1746
1774
|
const manifestRoutes: string[] = []
|
|
1775
|
+
const manifestShardRoutes: RouteManifestShardEntry[] = []
|
|
1776
|
+
const metadataRoutes: RouteManifestShardEntry[] = []
|
|
1747
1777
|
const routePatterns: string[] = []
|
|
1748
1778
|
|
|
1749
1779
|
// Next-style page.* files
|
|
@@ -1815,7 +1845,19 @@ async function processPageFiles(options: {
|
|
|
1815
1845
|
const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath)
|
|
1816
1846
|
eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
1817
1847
|
runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
1818
|
-
|
|
1848
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps} }`
|
|
1849
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`
|
|
1850
|
+
manifestRoutes.push(manifestDeclaration)
|
|
1851
|
+
manifestShardRoutes.push({
|
|
1852
|
+
path: routePath,
|
|
1853
|
+
declaration: manifestDeclaration,
|
|
1854
|
+
imports: manifestImportStatement ? [manifestImportStatement] : [],
|
|
1855
|
+
})
|
|
1856
|
+
metadataRoutes.push({
|
|
1857
|
+
path: routePath,
|
|
1858
|
+
declaration: metadataDeclaration,
|
|
1859
|
+
imports: manifestImportStatement ? [manifestImportStatement] : [],
|
|
1860
|
+
})
|
|
1819
1861
|
routePatterns.push(routePath)
|
|
1820
1862
|
}
|
|
1821
1863
|
|
|
@@ -1894,7 +1936,19 @@ async function processPageFiles(options: {
|
|
|
1894
1936
|
const manifestBaseProps = buildPageRouteManifestSpread(manifestMetaExpr, routePath)
|
|
1895
1937
|
eagerRoutes.push(`{ ${baseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
1896
1938
|
runtimeRoutes.push(`{ ${runtimeBaseProps}, Component: ${buildLazyRouteComponentExpression(importPath)} }`)
|
|
1897
|
-
|
|
1939
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps} }`
|
|
1940
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, ${manifestBaseProps}, load: async () => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod.default ?? mod) as any } }`
|
|
1941
|
+
manifestRoutes.push(manifestDeclaration)
|
|
1942
|
+
manifestShardRoutes.push({
|
|
1943
|
+
path: routePath,
|
|
1944
|
+
declaration: manifestDeclaration,
|
|
1945
|
+
imports: manifestImportStatement ? [manifestImportStatement] : [],
|
|
1946
|
+
})
|
|
1947
|
+
metadataRoutes.push({
|
|
1948
|
+
path: routePath,
|
|
1949
|
+
declaration: metadataDeclaration,
|
|
1950
|
+
imports: manifestImportStatement ? [manifestImportStatement] : [],
|
|
1951
|
+
})
|
|
1898
1952
|
routePatterns.push(routePath)
|
|
1899
1953
|
}
|
|
1900
1954
|
|
|
@@ -1902,6 +1956,8 @@ async function processPageFiles(options: {
|
|
|
1902
1956
|
eagerRoutes,
|
|
1903
1957
|
runtimeRoutes,
|
|
1904
1958
|
manifestRoutes,
|
|
1959
|
+
manifestShardRoutes,
|
|
1960
|
+
metadataRoutes,
|
|
1905
1961
|
routePatterns,
|
|
1906
1962
|
}
|
|
1907
1963
|
}
|
|
@@ -1918,12 +1974,14 @@ async function processApiRoutes(options: {
|
|
|
1918
1974
|
const apiApp = path.join(roots.appBase, 'api')
|
|
1919
1975
|
const apiPkg = path.join(roots.pkgBase, 'api')
|
|
1920
1976
|
if (!fs.existsSync(apiApp) && !fs.existsSync(apiPkg)) {
|
|
1921
|
-
return { eagerApis: [], runtimeApis: [], manifestApis: [] }
|
|
1977
|
+
return { eagerApis: [], runtimeApis: [], manifestApis: [], manifestShardApis: [], metadataApis: [] }
|
|
1922
1978
|
}
|
|
1923
1979
|
|
|
1924
1980
|
const eagerApis: string[] = []
|
|
1925
1981
|
const runtimeApis: string[] = []
|
|
1926
1982
|
const manifestApis: string[] = []
|
|
1983
|
+
const manifestShardApis: RouteManifestShardEntry[] = []
|
|
1984
|
+
const metadataApis: RouteManifestShardEntry[] = []
|
|
1927
1985
|
|
|
1928
1986
|
// route.* aggregations
|
|
1929
1987
|
const routeFiles = scanModuleDir(roots, SCAN_CONFIGS.apiRoutes)
|
|
@@ -1954,7 +2012,11 @@ async function processApiRoutes(options: {
|
|
|
1954
2012
|
eagerImports.push(buildImportStatement(`* as ${importName}`, importPath))
|
|
1955
2013
|
eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`)
|
|
1956
2014
|
runtimeApis.push(`{ path: ${toLiteral(resolvedPath)}, metadata: ${metadataLiteral}, handlers: { ${exportedMethods.map((method) => `${method}: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod as any).${method}(req, ctx) }`).join(', ')} } }`)
|
|
1957
|
-
|
|
2015
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(', ')}] }`
|
|
2016
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((method) => toLiteral(method)).join(', ')}], load: async () => ${buildDynamicImportExpression(importPath)} }`
|
|
2017
|
+
manifestApis.push(manifestDeclaration)
|
|
2018
|
+
manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
|
|
2019
|
+
metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
|
|
1958
2020
|
}
|
|
1959
2021
|
|
|
1960
2022
|
// Single files (plain scripts, not route.*, not tests, skip method dirs)
|
|
@@ -1986,7 +2048,11 @@ async function processApiRoutes(options: {
|
|
|
1986
2048
|
eagerImports.push(buildImportStatement(`* as ${importName}`, importPath))
|
|
1987
2049
|
eagerApis.push(`{ path: ((${importName} as any).metadata?.path ?? ${toLiteral(routePath)}), metadata: (${importName} as any).metadata, handlers: ${importName} as any${docsPart} }`)
|
|
1988
2050
|
runtimeApis.push(`{ path: ${toLiteral(resolvedPath)}, metadata: ${metadataLiteral}, handlers: { ${exportedMethods.map((entryMethod) => `${entryMethod}: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; return (mod as any).${entryMethod}(req, ctx) }`).join(', ')} } }`)
|
|
1989
|
-
|
|
2051
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(', ')}] }`
|
|
2052
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('route-file')}, path: ${toLiteral(resolvedPath)}, methods: [${exportedMethods.map((entryMethod) => toLiteral(entryMethod)).join(', ')}], load: async () => ${buildDynamicImportExpression(importPath)} }`
|
|
2053
|
+
manifestApis.push(manifestDeclaration)
|
|
2054
|
+
manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
|
|
2055
|
+
metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
|
|
1990
2056
|
}
|
|
1991
2057
|
|
|
1992
2058
|
// Legacy per-method
|
|
@@ -2028,7 +2094,11 @@ async function processApiRoutes(options: {
|
|
|
2028
2094
|
eagerImports.push(buildImportStatement(`${importName}, * as ${metaName}`, importPath))
|
|
2029
2095
|
eagerApis.push(`{ method: ${toLiteral(method)}, path: (${metaName}.metadata?.path ?? ${toLiteral(routePath)}), handler: ${importName}, metadata: ${metaName}.metadata${docsPart} }`)
|
|
2030
2096
|
runtimeApis.push(`{ method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, handler: async (req: Request, ctx?: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; const handler = ((mod as any).default ?? (mod as any).${method} ?? (mod as any).handler) as any; return handler(req, ctx) }, metadata: ${metadataLiteral} }`)
|
|
2031
|
-
|
|
2097
|
+
const metadataDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('legacy')}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}] }`
|
|
2098
|
+
const manifestDeclaration = `{ moduleId: ${toLiteral(modId)}, kind: ${toLiteral('legacy')}, method: ${toLiteral(method)}, path: ${toLiteral(resolvedPath)}, methods: [${toLiteral(method)}], load: async () => ${buildDynamicImportExpression(importPath)} }`
|
|
2099
|
+
manifestApis.push(manifestDeclaration)
|
|
2100
|
+
manifestShardApis.push({ path: resolvedPath, declaration: manifestDeclaration })
|
|
2101
|
+
metadataApis.push({ path: resolvedPath, declaration: metadataDeclaration })
|
|
2032
2102
|
}
|
|
2033
2103
|
}
|
|
2034
2104
|
|
|
@@ -2036,6 +2106,8 @@ async function processApiRoutes(options: {
|
|
|
2036
2106
|
eagerApis,
|
|
2037
2107
|
runtimeApis,
|
|
2038
2108
|
manifestApis,
|
|
2109
|
+
manifestShardApis,
|
|
2110
|
+
metadataApis,
|
|
2039
2111
|
}
|
|
2040
2112
|
}
|
|
2041
2113
|
|
|
@@ -2055,7 +2127,7 @@ function processWorkers(discovered: DiscoveredWorker[]): string[] {
|
|
|
2055
2127
|
for (const { id, importPath, metadata } of discovered) {
|
|
2056
2128
|
const workerId = metadata.id ?? id
|
|
2057
2129
|
workers.push(
|
|
2058
|
-
`{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
|
|
2130
|
+
`{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}${metadata.lockDuration === undefined ? '' : `, lockDuration: ${toLiteral(metadata.lockDuration)}`}${metadata.maxStalledCount === undefined ? '' : `, maxStalledCount: ${toLiteral(metadata.maxStalledCount)}`}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
|
|
2059
2131
|
)
|
|
2060
2132
|
}
|
|
2061
2133
|
return workers
|
|
@@ -2730,6 +2802,8 @@ function processWorkersAst(discovered: DiscoveredWorker[]): WriterFunction[] {
|
|
|
2730
2802
|
{ name: 'id', value: workerId },
|
|
2731
2803
|
{ name: 'queue', value: metadata.queue },
|
|
2732
2804
|
{ name: 'concurrency', value: metadata.concurrency ?? 1 },
|
|
2805
|
+
...(metadata.lockDuration === undefined ? [] : [{ name: 'lockDuration', value: metadata.lockDuration }]),
|
|
2806
|
+
...(metadata.maxStalledCount === undefined ? [] : [{ name: 'maxStalledCount', value: metadata.maxStalledCount }]),
|
|
2733
2807
|
{
|
|
2734
2808
|
name: 'handler',
|
|
2735
2809
|
value: callExpression(identifier('createLazyModuleWorker'), [
|
|
@@ -2745,6 +2819,24 @@ function processWorkersAst(discovered: DiscoveredWorker[]): WriterFunction[] {
|
|
|
2745
2819
|
return workers
|
|
2746
2820
|
}
|
|
2747
2821
|
|
|
2822
|
+
function collectWorkerGenerationEntries(
|
|
2823
|
+
discovered: DiscoveredWorker[],
|
|
2824
|
+
moduleId: string,
|
|
2825
|
+
): WorkerGenerationEntry[] {
|
|
2826
|
+
const workers: WorkerGenerationEntry[] = []
|
|
2827
|
+
for (const { id, importPath, metadata } of discovered) {
|
|
2828
|
+
if (!metadata.queue) continue
|
|
2829
|
+
workers.push({
|
|
2830
|
+
id: metadata.id ?? id,
|
|
2831
|
+
moduleId,
|
|
2832
|
+
queue: metadata.queue,
|
|
2833
|
+
concurrency: metadata.concurrency ?? 1,
|
|
2834
|
+
importPath,
|
|
2835
|
+
})
|
|
2836
|
+
}
|
|
2837
|
+
return workers
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2748
2840
|
function processTranslationsAst(options: {
|
|
2749
2841
|
discovered: DiscoveredTranslation[]
|
|
2750
2842
|
modId: string
|
|
@@ -2752,8 +2844,9 @@ function processTranslationsAst(options: {
|
|
|
2752
2844
|
pkgImportBase: string
|
|
2753
2845
|
imports: string[]
|
|
2754
2846
|
extraImports?: string[]
|
|
2847
|
+
localeOutputs?: Map<string, { imports: string[]; value: WriterFunction }>
|
|
2755
2848
|
}): GeneratedObjectEntry[] {
|
|
2756
|
-
const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports } = options
|
|
2849
|
+
const { discovered, modId, appImportBase, pkgImportBase, imports, extraImports, localeOutputs } = options
|
|
2757
2850
|
|
|
2758
2851
|
const translations: GeneratedObjectEntry[] = []
|
|
2759
2852
|
|
|
@@ -2762,45 +2855,236 @@ function processTranslationsAst(options: {
|
|
|
2762
2855
|
if (coreHas && appHas) {
|
|
2763
2856
|
const coreName = `T_${toVar(modId)}_${toVar(locale)}_C`
|
|
2764
2857
|
const appName = `T_${toVar(modId)}_${toVar(locale)}_A`
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2858
|
+
const localeImports = [
|
|
2859
|
+
buildImportStatement(coreName, `${pkgImportBase}/i18n/${locale}.json`),
|
|
2860
|
+
buildImportStatement(appName, `${appImportBase}/i18n/${locale}.json`),
|
|
2861
|
+
]
|
|
2862
|
+
imports.push(...localeImports)
|
|
2863
|
+
extraImports?.push(...localeImports)
|
|
2864
|
+
const value = objectLiteral([
|
|
2865
|
+
{ kind: 'spread', value: asExpression(identifier(coreName), 'unknown as Record<string, string>') },
|
|
2866
|
+
{ kind: 'spread', value: asExpression(identifier(appName), 'unknown as Record<string, string>') },
|
|
2867
|
+
])
|
|
2769
2868
|
translations.push({
|
|
2770
2869
|
name: JSON.stringify(locale),
|
|
2771
|
-
value
|
|
2772
|
-
{ kind: 'spread', value: asExpression(identifier(coreName), 'unknown as Record<string, string>') },
|
|
2773
|
-
{ kind: 'spread', value: asExpression(identifier(appName), 'unknown as Record<string, string>') },
|
|
2774
|
-
]),
|
|
2870
|
+
value,
|
|
2775
2871
|
})
|
|
2872
|
+
localeOutputs?.set(locale, { imports: localeImports, value })
|
|
2776
2873
|
continue
|
|
2777
2874
|
}
|
|
2778
2875
|
|
|
2779
2876
|
if (appHas) {
|
|
2780
2877
|
const appName = `T_${toVar(modId)}_${toVar(locale)}_A`
|
|
2781
|
-
|
|
2782
|
-
|
|
2878
|
+
const localeImports = [buildImportStatement(appName, `${appImportBase}/i18n/${locale}.json`)]
|
|
2879
|
+
imports.push(...localeImports)
|
|
2880
|
+
extraImports?.push(...localeImports)
|
|
2881
|
+
const value = asExpression(identifier(appName), 'unknown as Record<string, string>')
|
|
2783
2882
|
translations.push({
|
|
2784
2883
|
name: JSON.stringify(locale),
|
|
2785
|
-
value
|
|
2884
|
+
value,
|
|
2786
2885
|
})
|
|
2886
|
+
localeOutputs?.set(locale, { imports: localeImports, value })
|
|
2787
2887
|
continue
|
|
2788
2888
|
}
|
|
2789
2889
|
|
|
2790
2890
|
if (coreHas) {
|
|
2791
2891
|
const coreName = `T_${toVar(modId)}_${toVar(locale)}_C`
|
|
2792
|
-
|
|
2793
|
-
|
|
2892
|
+
const localeImports = [buildImportStatement(coreName, `${pkgImportBase}/i18n/${locale}.json`)]
|
|
2893
|
+
imports.push(...localeImports)
|
|
2894
|
+
extraImports?.push(...localeImports)
|
|
2895
|
+
const value = asExpression(identifier(coreName), 'unknown as Record<string, string>')
|
|
2794
2896
|
translations.push({
|
|
2795
2897
|
name: JSON.stringify(locale),
|
|
2796
|
-
value
|
|
2898
|
+
value,
|
|
2797
2899
|
})
|
|
2900
|
+
localeOutputs?.set(locale, { imports: localeImports, value })
|
|
2798
2901
|
}
|
|
2799
2902
|
}
|
|
2800
2903
|
|
|
2801
2904
|
return translations
|
|
2802
2905
|
}
|
|
2803
2906
|
|
|
2907
|
+
function sourceDeclaresCliCommand(filePath: string, commandName: string): boolean {
|
|
2908
|
+
let sourceText: string
|
|
2909
|
+
try {
|
|
2910
|
+
sourceText = fs.readFileSync(filePath, 'utf8')
|
|
2911
|
+
} catch {
|
|
2912
|
+
return false
|
|
2913
|
+
}
|
|
2914
|
+
const sourceFile = ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true)
|
|
2915
|
+
const declarations = new Map<string, ts.Expression>()
|
|
2916
|
+
for (const statement of sourceFile.statements) {
|
|
2917
|
+
if (!ts.isVariableStatement(statement)) continue
|
|
2918
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
2919
|
+
if (ts.isIdentifier(declaration.name) && declaration.initializer) {
|
|
2920
|
+
declarations.set(declaration.name.text, declaration.initializer)
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
|
|
2925
|
+
const expressionDeclaresCommand = (expression: ts.Expression, seen = new Set<string>()): boolean => {
|
|
2926
|
+
if (ts.isParenthesizedExpression(expression) || ts.isAsExpression(expression) || ts.isSatisfiesExpression(expression)) {
|
|
2927
|
+
return expressionDeclaresCommand(expression.expression, seen)
|
|
2928
|
+
}
|
|
2929
|
+
if (ts.isIdentifier(expression)) {
|
|
2930
|
+
if (seen.has(expression.text)) return false
|
|
2931
|
+
const initializer = declarations.get(expression.text)
|
|
2932
|
+
if (!initializer) return false
|
|
2933
|
+
const nextSeen = new Set(seen)
|
|
2934
|
+
nextSeen.add(expression.text)
|
|
2935
|
+
return expressionDeclaresCommand(initializer, nextSeen)
|
|
2936
|
+
}
|
|
2937
|
+
if (ts.isArrayLiteralExpression(expression)) {
|
|
2938
|
+
return expression.elements.some((element) => (
|
|
2939
|
+
ts.isSpreadElement(element)
|
|
2940
|
+
? expressionDeclaresCommand(element.expression, seen)
|
|
2941
|
+
: expressionDeclaresCommand(element, seen)
|
|
2942
|
+
))
|
|
2943
|
+
}
|
|
2944
|
+
if (!ts.isObjectLiteralExpression(expression)) return false
|
|
2945
|
+
return expression.properties.some((property) => {
|
|
2946
|
+
if (!ts.isPropertyAssignment(property)) return false
|
|
2947
|
+
const propertyName = ts.isIdentifier(property.name) || ts.isStringLiteralLike(property.name)
|
|
2948
|
+
? property.name.text
|
|
2949
|
+
: null
|
|
2950
|
+
return propertyName === 'command'
|
|
2951
|
+
&& (ts.isStringLiteralLike(property.initializer) || ts.isNoSubstitutionTemplateLiteral(property.initializer))
|
|
2952
|
+
&& property.initializer.text === commandName
|
|
2953
|
+
})
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
return sourceFile.statements.some((statement) => (
|
|
2957
|
+
ts.isExportAssignment(statement)
|
|
2958
|
+
&& !statement.isExportEquals
|
|
2959
|
+
&& expressionDeclaresCommand(statement.expression)
|
|
2960
|
+
))
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2963
|
+
function appDeclaresProgrammaticDevSupervisorOverrides(appDir: string): boolean {
|
|
2964
|
+
const srcDir = path.join(appDir, 'src')
|
|
2965
|
+
const pending = [srcDir]
|
|
2966
|
+
while (pending.length > 0) {
|
|
2967
|
+
const current = pending.pop()!
|
|
2968
|
+
let entries: fs.Dirent[]
|
|
2969
|
+
try {
|
|
2970
|
+
entries = fs.readdirSync(current, { withFileTypes: true })
|
|
2971
|
+
} catch {
|
|
2972
|
+
continue
|
|
2973
|
+
}
|
|
2974
|
+
for (const entry of entries) {
|
|
2975
|
+
const entryPath = path.join(current, entry.name)
|
|
2976
|
+
if (entry.isDirectory()) {
|
|
2977
|
+
if (entry.name !== '__tests__' && entry.name !== 'node_modules') pending.push(entryPath)
|
|
2978
|
+
continue
|
|
2979
|
+
}
|
|
2980
|
+
if (!/\.[cm]?tsx?$/.test(entry.name) || /(?:^|\.)test\.[cm]?tsx?$/.test(entry.name)) continue
|
|
2981
|
+
|
|
2982
|
+
let sourceText: string
|
|
2983
|
+
try {
|
|
2984
|
+
sourceText = fs.readFileSync(entryPath, 'utf8')
|
|
2985
|
+
} catch {
|
|
2986
|
+
continue
|
|
2987
|
+
}
|
|
2988
|
+
const sourceFile = ts.createSourceFile(entryPath, sourceText, ts.ScriptTarget.Latest, true)
|
|
2989
|
+
const directImports = new Set<string>()
|
|
2990
|
+
const namespaceImports = new Set<string>()
|
|
2991
|
+
for (const statement of sourceFile.statements) {
|
|
2992
|
+
if (
|
|
2993
|
+
!ts.isImportDeclaration(statement)
|
|
2994
|
+
|| !ts.isStringLiteralLike(statement.moduleSpecifier)
|
|
2995
|
+
|| statement.moduleSpecifier.text !== '@open-mercato/shared/modules/overrides'
|
|
2996
|
+
) continue
|
|
2997
|
+
const bindings = statement.importClause?.namedBindings
|
|
2998
|
+
if (bindings && ts.isNamespaceImport(bindings)) namespaceImports.add(bindings.name.text)
|
|
2999
|
+
if (bindings && ts.isNamedImports(bindings)) {
|
|
3000
|
+
for (const element of bindings.elements) {
|
|
3001
|
+
const importedName = element.propertyName?.text ?? element.name.text
|
|
3002
|
+
if (importedName === 'applyWorkerOverrides' || importedName === 'applyCliOverrides') {
|
|
3003
|
+
directImports.add(element.name.text)
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
let found = false
|
|
3009
|
+
const visit = (node: ts.Node): void => {
|
|
3010
|
+
if (found) return
|
|
3011
|
+
if (ts.isCallExpression(node)) {
|
|
3012
|
+
if (ts.isIdentifier(node.expression) && directImports.has(node.expression.text)) {
|
|
3013
|
+
found = true
|
|
3014
|
+
return
|
|
3015
|
+
}
|
|
3016
|
+
if (
|
|
3017
|
+
ts.isPropertyAccessExpression(node.expression)
|
|
3018
|
+
&& ts.isIdentifier(node.expression.expression)
|
|
3019
|
+
&& namespaceImports.has(node.expression.expression.text)
|
|
3020
|
+
&& ['applyWorkerOverrides', 'applyCliOverrides'].includes(node.expression.name.text)
|
|
3021
|
+
) {
|
|
3022
|
+
found = true
|
|
3023
|
+
return
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
ts.forEachChild(node, visit)
|
|
3027
|
+
}
|
|
3028
|
+
visit(sourceFile)
|
|
3029
|
+
if (found) return true
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
return false
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
function renderAstI18nLocaleRegistryFile(options: {
|
|
3036
|
+
fileName: string
|
|
3037
|
+
imports: string[]
|
|
3038
|
+
moduleEntries: WriterFunction[]
|
|
3039
|
+
}): string {
|
|
3040
|
+
const sourceFile = createGeneratedSourceFile(options.fileName)
|
|
3041
|
+
addAutoGeneratedComment(sourceFile, 'registry (locale-specific i18n version)')
|
|
3042
|
+
addImportSpec(sourceFile, {
|
|
3043
|
+
moduleSpecifier: '@open-mercato/shared/modules/registry',
|
|
3044
|
+
namedImports: [{ name: 'Module', isTypeOnly: true }],
|
|
3045
|
+
})
|
|
3046
|
+
addImportStatements(sourceFile, options.imports)
|
|
3047
|
+
sourceFile.addVariableStatement({
|
|
3048
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
3049
|
+
isExported: true,
|
|
3050
|
+
declarations: [{
|
|
3051
|
+
name: 'modules',
|
|
3052
|
+
type: 'Module[]',
|
|
3053
|
+
initializer: arrayLiteral(options.moduleEntries, writeValue),
|
|
3054
|
+
}],
|
|
3055
|
+
})
|
|
3056
|
+
sourceFile.addExportAssignment({
|
|
3057
|
+
isExportEquals: false,
|
|
3058
|
+
expression: 'modules',
|
|
3059
|
+
})
|
|
3060
|
+
return getSourceText(sourceFile)
|
|
3061
|
+
}
|
|
3062
|
+
|
|
3063
|
+
function buildI18nLocaleShardFileName(locale: string): string {
|
|
3064
|
+
const safeLocale = locale.replace(/[^a-zA-Z0-9_-]/g, '_')
|
|
3065
|
+
return `modules.i18n.${safeLocale}.generated.ts`
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3068
|
+
function renderI18nLocaleLoadersFile(locales: string[]): string {
|
|
3069
|
+
const cases = locales.map((locale) => {
|
|
3070
|
+
const moduleSpecifier = `./${buildI18nLocaleShardFileName(locale).replace(/\.ts$/, '')}`
|
|
3071
|
+
return ` case ${JSON.stringify(locale)}:\n return import(${JSON.stringify(moduleSpecifier)}).then((entry) => entry.modules)`
|
|
3072
|
+
}).join('\n')
|
|
3073
|
+
|
|
3074
|
+
return `// AUTO-GENERATED by mercato generate registry (locale-specific i18n loaders)\nimport type { Module } from '@open-mercato/shared/modules/registry'\n\nexport async function loadI18nModules(locale: string): Promise<Module[]> {\n switch (locale) {\n${cases ? `${cases}\n` : ''} default:\n return []\n }\n}\n`
|
|
3075
|
+
}
|
|
3076
|
+
|
|
3077
|
+
function removeStaleI18nLocaleShards(outputDir: string, expectedFileNames: Set<string>): void {
|
|
3078
|
+
if (!fs.existsSync(outputDir)) return
|
|
3079
|
+
for (const entry of fs.readdirSync(outputDir, { withFileTypes: true })) {
|
|
3080
|
+
if (!entry.isFile()) continue
|
|
3081
|
+
if (!/^modules\.i18n\..+\.generated\.(?:ts|checksum)$/.test(entry.name)) continue
|
|
3082
|
+
if (entry.name.startsWith('modules.i18n.loaders.generated.')) continue
|
|
3083
|
+
if (expectedFileNames.has(entry.name)) continue
|
|
3084
|
+
fs.unlinkSync(path.join(outputDir, entry.name))
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
|
|
2804
3088
|
function resolveConventionFile(
|
|
2805
3089
|
resolved: ResolvedFile | null,
|
|
2806
3090
|
prefix: string,
|
|
@@ -2881,6 +3165,10 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
2881
3165
|
const frontendRouteManifestDecls: string[] = []
|
|
2882
3166
|
const backendRouteManifestDecls: string[] = []
|
|
2883
3167
|
const apiRouteManifestDecls: string[] = []
|
|
3168
|
+
const backendRouteShardEntries: RouteManifestShardEntry[] = []
|
|
3169
|
+
const backendRouteMetadataEntries: RouteManifestShardEntry[] = []
|
|
3170
|
+
const apiRouteShardEntries: RouteManifestShardEntry[] = []
|
|
3171
|
+
const apiRouteMetadataEntries: RouteManifestShardEntry[] = []
|
|
2884
3172
|
// Mutable ref so extracted helper functions can increment the shared counter
|
|
2885
3173
|
const importIdRef = { value: 0 }
|
|
2886
3174
|
const requiresByModule = new Map<string, string[]>()
|
|
@@ -3059,6 +3347,10 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3059
3347
|
if (fields) fieldsImportName = fields.importName
|
|
3060
3348
|
}
|
|
3061
3349
|
|
|
3350
|
+
const integrationExports = integrationImportName
|
|
3351
|
+
? `(${integrationImportName} as unknown as { integrations?: import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]; integration?: import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition; bundles?: import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]; bundle?: import('@open-mercato/shared/modules/integrations/types').IntegrationBundle })`
|
|
3352
|
+
: null
|
|
3353
|
+
|
|
3062
3354
|
// 13. Pages: backend
|
|
3063
3355
|
{
|
|
3064
3356
|
const beApp = path.join(roots.appBase, 'backend')
|
|
@@ -3081,6 +3373,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3081
3373
|
backendRoutes.push(...generatedBackendRoutes.eagerRoutes)
|
|
3082
3374
|
runtimeBackendRoutes.push(...generatedBackendRoutes.runtimeRoutes)
|
|
3083
3375
|
backendRouteManifestDecls.push(...generatedBackendRoutes.manifestRoutes)
|
|
3376
|
+
backendRouteShardEntries.push(...generatedBackendRoutes.manifestShardRoutes)
|
|
3377
|
+
backendRouteMetadataEntries.push(...generatedBackendRoutes.metadataRoutes)
|
|
3084
3378
|
for (const pattern of generatedBackendRoutes.routePatterns) {
|
|
3085
3379
|
assertUniqueBackendRoutePattern(seenBackendRoutePatterns, modId, pattern)
|
|
3086
3380
|
}
|
|
@@ -3101,6 +3395,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3101
3395
|
apis.push(...generatedApis.eagerApis)
|
|
3102
3396
|
runtimeApis.push(...generatedApis.runtimeApis)
|
|
3103
3397
|
apiRouteManifestDecls.push(...generatedApis.manifestApis)
|
|
3398
|
+
apiRouteShardEntries.push(...generatedApis.manifestShardApis)
|
|
3399
|
+
apiRouteMetadataEntries.push(...generatedApis.metadataApis)
|
|
3104
3400
|
}
|
|
3105
3401
|
|
|
3106
3402
|
// 15. CLI
|
|
@@ -3167,8 +3463,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3167
3463
|
${dashboardWidgets.length ? `dashboardWidgets: [${dashboardWidgets.join(', ')}],` : ''}
|
|
3168
3464
|
${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ''}
|
|
3169
3465
|
${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ''}
|
|
3170
|
-
${
|
|
3171
|
-
${
|
|
3466
|
+
${integrationExports ? `integrations: ((${integrationExports}.integrations ?? (${integrationExports}.integration ? [${integrationExports}.integration] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
|
|
3467
|
+
${integrationExports ? `bundles: ((${integrationExports}.bundles ?? (${integrationExports}.bundle ? [${integrationExports}.bundle] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
|
|
3172
3468
|
}`)
|
|
3173
3469
|
runtimeModuleDecls.push(`{
|
|
3174
3470
|
id: ${toLiteral(modId)},
|
|
@@ -3185,8 +3481,8 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3185
3481
|
${customEntitiesImportName ? `customEntities: ((${customEntitiesImportName}.default ?? ${customEntitiesImportName}.entities) as any) || [],` : ''}
|
|
3186
3482
|
${setupImportName ? `setup: (${setupImportName}.default ?? ${setupImportName}.setup) || undefined,` : ''}
|
|
3187
3483
|
${encryptionImportName ? `defaultEncryptionMaps: ((${encryptionImportName}.default ?? ${encryptionImportName}.defaultEncryptionMaps) as import('@open-mercato/shared/modules/encryption').ModuleEncryptionMap[]) || [],` : ''}
|
|
3188
|
-
${
|
|
3189
|
-
${
|
|
3484
|
+
${integrationExports ? `integrations: ((${integrationExports}.integrations ?? (${integrationExports}.integration ? [${integrationExports}.integration] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationDefinition[]),` : ''}
|
|
3485
|
+
${integrationExports ? `bundles: ((${integrationExports}.bundles ?? (${integrationExports}.bundle ? [${integrationExports}.bundle] : [])) as import('@open-mercato/shared/modules/integrations/types').IntegrationBundle[]),` : ''}
|
|
3190
3486
|
}`)
|
|
3191
3487
|
}
|
|
3192
3488
|
|
|
@@ -3320,6 +3616,12 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3320
3616
|
exportName: 'apiRoutes',
|
|
3321
3617
|
entries: apiRouteManifestDecls,
|
|
3322
3618
|
})
|
|
3619
|
+
const routeManifestOutputs = [
|
|
3620
|
+
...renderRouteManifestShardOutputs('backend', backendRouteShardEntries),
|
|
3621
|
+
...renderRouteManifestShardOutputs('api', apiRouteShardEntries),
|
|
3622
|
+
renderRouteMetadataOutput('backend', backendRouteMetadataEntries),
|
|
3623
|
+
renderRouteMetadataOutput('api', apiRouteMetadataEntries),
|
|
3624
|
+
]
|
|
3323
3625
|
const legacySubscribersOutput = renderAstLegacyAliasFile({
|
|
3324
3626
|
fileName: 'subscribers.generated.ts',
|
|
3325
3627
|
exportName: 'moduleSubscribers',
|
|
@@ -3367,6 +3669,29 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3367
3669
|
writeGeneratedFile({ outFile: frontendRoutesOutFile, checksumFile: frontendRoutesChecksumFile, content: frontendRoutesOutput, structureChecksum, result, quiet })
|
|
3368
3670
|
writeGeneratedFile({ outFile: backendRoutesOutFile, checksumFile: backendRoutesChecksumFile, content: backendRoutesOutput, structureChecksum, result, quiet })
|
|
3369
3671
|
writeGeneratedFile({ outFile: apiRoutesOutFile, checksumFile: apiRoutesChecksumFile, content: apiRoutesOutput, structureChecksum, result, quiet })
|
|
3672
|
+
const expectedRouteManifestFiles = new Set(routeManifestOutputs.flatMap(({ fileName }) => [
|
|
3673
|
+
fileName,
|
|
3674
|
+
fileName.replace(/\.ts$/, '.checksum'),
|
|
3675
|
+
]))
|
|
3676
|
+
if (fs.existsSync(outputDir)) {
|
|
3677
|
+
for (const entry of fs.readdirSync(outputDir, { withFileTypes: true })) {
|
|
3678
|
+
if (!entry.isFile() || !routeManifestShardFilePattern.test(entry.name)) continue
|
|
3679
|
+
if (expectedRouteManifestFiles.has(entry.name)) continue
|
|
3680
|
+
const stalePath = path.join(outputDir, entry.name)
|
|
3681
|
+
fs.unlinkSync(stalePath)
|
|
3682
|
+
result.filesWritten.push(stalePath)
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
for (const routeOutput of routeManifestOutputs) {
|
|
3686
|
+
writeGeneratedFile({
|
|
3687
|
+
outFile: path.join(outputDir, routeOutput.fileName),
|
|
3688
|
+
checksumFile: path.join(outputDir, routeOutput.fileName.replace(/\.ts$/, '.checksum')),
|
|
3689
|
+
content: routeOutput.content,
|
|
3690
|
+
structureChecksum,
|
|
3691
|
+
result,
|
|
3692
|
+
quiet,
|
|
3693
|
+
})
|
|
3694
|
+
}
|
|
3370
3695
|
writeGeneratedFile({ outFile: legacySubscribersOutFile, checksumFile: legacySubscribersChecksumFile, content: legacySubscribersOutput, structureChecksum, result, quiet })
|
|
3371
3696
|
const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries)
|
|
3372
3697
|
writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet })
|
|
@@ -3403,14 +3728,14 @@ async function generateModuleRegistryFromDiscovery(options: ModuleRegistryRender
|
|
|
3403
3728
|
{
|
|
3404
3729
|
const bootstrapPlugins = [...pluginRegistry.values()].filter((p) => p.bootstrapRegistration)
|
|
3405
3730
|
const allEntryImports: string[] = [
|
|
3406
|
-
buildImportStatement(`{
|
|
3731
|
+
buildImportStatement(`{ backendRouteFacades }`, `./backend-route-shards.generated`),
|
|
3407
3732
|
buildImportStatement(`{ frontendRoutes }`, `./frontend-routes.generated`),
|
|
3408
3733
|
]
|
|
3409
3734
|
const allRegImports: string[] = [
|
|
3410
3735
|
`import { registerBackendRouteManifests, registerFrontendRouteManifests } from '@open-mercato/shared/modules/registry'`,
|
|
3411
3736
|
]
|
|
3412
3737
|
const allCalls: string[] = [
|
|
3413
|
-
`registerBackendRouteManifests(
|
|
3738
|
+
`registerBackendRouteManifests(backendRouteFacades)`,
|
|
3414
3739
|
`registerFrontendRouteManifests(frontendRoutes)`,
|
|
3415
3740
|
]
|
|
3416
3741
|
for (const plugin of bootstrapPlugins) {
|
|
@@ -3447,6 +3772,8 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
3447
3772
|
const bootstrapChecksumFile = path.join(outputDir, 'modules.bootstrap.generated.checksum')
|
|
3448
3773
|
const i18nOutFile = path.join(outputDir, 'modules.i18n.generated.ts')
|
|
3449
3774
|
const i18nChecksumFile = path.join(outputDir, 'modules.i18n.generated.checksum')
|
|
3775
|
+
const i18nLoadersOutFile = path.join(outputDir, 'modules.i18n.loaders.generated.ts')
|
|
3776
|
+
const i18nLoadersChecksumFile = path.join(outputDir, 'modules.i18n.loaders.generated.checksum')
|
|
3450
3777
|
const legacyOutFile = path.join(outputDir, 'bootstrap-modules.generated.ts')
|
|
3451
3778
|
const legacyChecksumFile = path.join(outputDir, 'bootstrap-modules.generated.checksum')
|
|
3452
3779
|
const enabledIdsOutFile = path.join(outputDir, 'enabled-module-ids.generated.ts')
|
|
@@ -3461,6 +3788,7 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
3461
3788
|
const moduleDecls: WriterFunction[] = []
|
|
3462
3789
|
const bootstrapModuleDecls: WriterFunction[] = []
|
|
3463
3790
|
const i18nModuleDecls: WriterFunction[] = []
|
|
3791
|
+
const i18nLocaleShards = new Map<string, { imports: string[]; moduleDecls: WriterFunction[] }>()
|
|
3464
3792
|
const importIdRef = { value: 0 }
|
|
3465
3793
|
const requiresByModule = new Map<string, string[]>()
|
|
3466
3794
|
const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
|
|
@@ -3474,6 +3802,7 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
3474
3802
|
const frontendRoutes: WriterFunction[] = []
|
|
3475
3803
|
const backendRoutes: WriterFunction[] = []
|
|
3476
3804
|
const translations: GeneratedObjectEntry[] = []
|
|
3805
|
+
const localeTranslations = new Map<string, { imports: string[]; value: WriterFunction }>()
|
|
3477
3806
|
const subscribers: WriterFunction[] = []
|
|
3478
3807
|
const workers: WriterFunction[] = []
|
|
3479
3808
|
let infoImportName: string | null = null
|
|
@@ -3602,9 +3931,24 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
3602
3931
|
pkgImportBase: imps.pkgBase,
|
|
3603
3932
|
imports,
|
|
3604
3933
|
extraImports: translationImports,
|
|
3934
|
+
localeOutputs: localeTranslations,
|
|
3605
3935
|
}))
|
|
3606
|
-
bootstrapImports.push(...translationImports)
|
|
3607
3936
|
i18nImports.push(...translationImports)
|
|
3937
|
+
for (const [locale, localeTranslation] of localeTranslations) {
|
|
3938
|
+
const shard = i18nLocaleShards.get(locale) ?? { imports: [], moduleDecls: [] }
|
|
3939
|
+
shard.imports.push(...localeTranslation.imports)
|
|
3940
|
+
shard.moduleDecls.push(objectLiteral([
|
|
3941
|
+
{ name: 'id', value: modId },
|
|
3942
|
+
{
|
|
3943
|
+
name: 'translations',
|
|
3944
|
+
value: objectLiteral([{
|
|
3945
|
+
name: JSON.stringify(locale),
|
|
3946
|
+
value: localeTranslation.value,
|
|
3947
|
+
}]),
|
|
3948
|
+
},
|
|
3949
|
+
]))
|
|
3950
|
+
i18nLocaleShards.set(locale, shard)
|
|
3951
|
+
}
|
|
3608
3952
|
|
|
3609
3953
|
subscribers.push(...processSubscribersAst(await discovered.getSubscribers()))
|
|
3610
3954
|
|
|
@@ -3720,7 +4064,9 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
3720
4064
|
}
|
|
3721
4065
|
|
|
3722
4066
|
moduleDecls.push(objectLiteral(routeAwareModuleEntries))
|
|
3723
|
-
bootstrapModuleDecls.push(objectLiteral(moduleEntries
|
|
4067
|
+
bootstrapModuleDecls.push(objectLiteral(moduleEntries.filter(
|
|
4068
|
+
(entry) => entry.kind === 'spread' || entry.name !== 'translations',
|
|
4069
|
+
)))
|
|
3724
4070
|
i18nModuleDecls.push(objectLiteral(i18nModuleEntries))
|
|
3725
4071
|
}
|
|
3726
4072
|
|
|
@@ -3777,6 +4123,41 @@ async function generateModuleRegistryAppFromDiscovery(options: ModuleRegistryRen
|
|
|
3777
4123
|
writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet })
|
|
3778
4124
|
writeGeneratedFile({ outFile: bootstrapOutFile, checksumFile: bootstrapChecksumFile, content: bootstrapOutput, structureChecksum, result, quiet })
|
|
3779
4125
|
writeGeneratedFile({ outFile: i18nOutFile, checksumFile: i18nChecksumFile, content: i18nOutput, structureChecksum, result, quiet })
|
|
4126
|
+
const i18nLocales = [...i18nLocaleShards.keys()].sort((a, b) => a.localeCompare(b))
|
|
4127
|
+
const shardFileNames = new Set<string>()
|
|
4128
|
+
const expectedShardArtifacts = new Set<string>()
|
|
4129
|
+
for (const locale of i18nLocales) {
|
|
4130
|
+
const fileName = buildI18nLocaleShardFileName(locale)
|
|
4131
|
+
if (shardFileNames.has(fileName)) {
|
|
4132
|
+
throw new Error(`Locale names produce the same generated i18n shard file: ${locale}`)
|
|
4133
|
+
}
|
|
4134
|
+
shardFileNames.add(fileName)
|
|
4135
|
+
expectedShardArtifacts.add(fileName)
|
|
4136
|
+
expectedShardArtifacts.add(fileName.replace(/\.ts$/, '.checksum'))
|
|
4137
|
+
const shard = i18nLocaleShards.get(locale)!
|
|
4138
|
+
const content = renderAstI18nLocaleRegistryFile({
|
|
4139
|
+
fileName,
|
|
4140
|
+
imports: shard.imports,
|
|
4141
|
+
moduleEntries: shard.moduleDecls,
|
|
4142
|
+
})
|
|
4143
|
+
writeGeneratedFile({
|
|
4144
|
+
outFile: path.join(outputDir, fileName),
|
|
4145
|
+
checksumFile: path.join(outputDir, fileName.replace(/\.ts$/, '.checksum')),
|
|
4146
|
+
content,
|
|
4147
|
+
structureChecksum,
|
|
4148
|
+
result,
|
|
4149
|
+
quiet,
|
|
4150
|
+
})
|
|
4151
|
+
}
|
|
4152
|
+
removeStaleI18nLocaleShards(outputDir, expectedShardArtifacts)
|
|
4153
|
+
writeGeneratedFile({
|
|
4154
|
+
outFile: i18nLoadersOutFile,
|
|
4155
|
+
checksumFile: i18nLoadersChecksumFile,
|
|
4156
|
+
content: renderI18nLocaleLoadersFile(i18nLocales),
|
|
4157
|
+
structureChecksum,
|
|
4158
|
+
result,
|
|
4159
|
+
quiet,
|
|
4160
|
+
})
|
|
3780
4161
|
writeGeneratedFile({ outFile: legacyOutFile, checksumFile: legacyChecksumFile, content: legacyOutput, structureChecksum, result, quiet })
|
|
3781
4162
|
|
|
3782
4163
|
const enabledIdsOutput = renderEnabledModuleIdsFile(enabled.map((entry) => entry.id))
|
|
@@ -3808,6 +4189,8 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
|
|
|
3808
4189
|
const legacyChecksumFile = path.join(outputDir, 'cli-modules.generated.checksum')
|
|
3809
4190
|
const commandLoadersOutFile = path.join(outputDir, 'command-loaders.generated.ts')
|
|
3810
4191
|
const commandLoadersChecksumFile = path.join(outputDir, 'command-loaders.generated.checksum')
|
|
4192
|
+
const devSupervisorOutFile = path.join(outputDir, DEV_SUPERVISOR_MANIFEST_FILE)
|
|
4193
|
+
const devSupervisorChecksumFile = path.join(outputDir, 'dev-supervisor.generated.checksum')
|
|
3811
4194
|
|
|
3812
4195
|
const enabled = discovery.enabled
|
|
3813
4196
|
const imports: string[] = []
|
|
@@ -3816,9 +4199,13 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
|
|
|
3816
4199
|
const importIdRef = { value: 0 }
|
|
3817
4200
|
const requiresByModule = new Map<string, string[]>()
|
|
3818
4201
|
const commandLoaderEntries: CommandLoaderGenerationEntry[] = []
|
|
4202
|
+
const devSupervisorWorkers: DevSupervisorWorkerDescriptor[] = []
|
|
4203
|
+
let schedulerStartStatus: DevSupervisorSchedulerStartStatus = 'missing-module'
|
|
4204
|
+
let requiresFullBootstrap = enabled.some((entry) => entry.devSupervisorRequiresFullBootstrap === true)
|
|
4205
|
+
|| appDeclaresProgrammaticDevSupervisorOverrides(resolver.getAppDir())
|
|
3819
4206
|
|
|
3820
4207
|
for (const discovered of discovery.modules) {
|
|
3821
|
-
const { modId,
|
|
4208
|
+
const { modId, imps, appImportBase } = discovered
|
|
3822
4209
|
commandLoaderEntries.push(...discovered.commandLoaderEntries)
|
|
3823
4210
|
|
|
3824
4211
|
let cliImportName: string | null = null
|
|
@@ -3910,11 +4297,20 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
|
|
|
3910
4297
|
|
|
3911
4298
|
// CLI
|
|
3912
4299
|
{
|
|
4300
|
+
if (modId === 'scheduler') schedulerStartStatus = 'missing-cli'
|
|
3913
4301
|
const cliResolved = discovered.resolve('cli.ts')
|
|
3914
4302
|
if (cliResolved) {
|
|
3915
4303
|
const importName = `CLI_${toVar(modId)}`
|
|
3916
4304
|
imports.push(buildImportStatement(importName, sanitizeGeneratedModuleSpecifier(cliResolved.importPath)))
|
|
3917
4305
|
cliImportName = importName
|
|
4306
|
+
if (modId === 'scheduler') {
|
|
4307
|
+
if (sourceDeclaresCliCommand(cliResolved.absolutePath, 'start')) {
|
|
4308
|
+
schedulerStartStatus = 'ok'
|
|
4309
|
+
} else {
|
|
4310
|
+
schedulerStartStatus = 'missing-command'
|
|
4311
|
+
requiresFullBootstrap = true
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
3918
4314
|
}
|
|
3919
4315
|
}
|
|
3920
4316
|
|
|
@@ -3931,7 +4327,10 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
|
|
|
3931
4327
|
subscribers.push(...processSubscribersAst(await discovered.getSubscribers()))
|
|
3932
4328
|
|
|
3933
4329
|
// Workers
|
|
3934
|
-
|
|
4330
|
+
const discoveredWorkers = await discovered.getWorkers()
|
|
4331
|
+
const workerGenerationEntries = collectWorkerGenerationEntries(discoveredWorkers, modId)
|
|
4332
|
+
workers.push(...processWorkersAst(discoveredWorkers))
|
|
4333
|
+
devSupervisorWorkers.push(...workerGenerationEntries.map(({ importPath: _importPath, ...worker }) => worker))
|
|
3935
4334
|
|
|
3936
4335
|
// Dashboard widgets
|
|
3937
4336
|
{
|
|
@@ -4096,6 +4495,20 @@ async function generateModuleRegistryCliFromDiscovery(options: ModuleRegistryRen
|
|
|
4096
4495
|
const structureChecksum = discovery.getStructureChecksum()
|
|
4097
4496
|
writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet })
|
|
4098
4497
|
writeGeneratedFile({ outFile: legacyOutFile, checksumFile: legacyChecksumFile, content: legacyOutput, structureChecksum, result, quiet })
|
|
4498
|
+
const devSupervisorOutput = `${JSON.stringify({
|
|
4499
|
+
version: DEV_SUPERVISOR_MANIFEST_VERSION,
|
|
4500
|
+
workers: devSupervisorWorkers,
|
|
4501
|
+
schedulerStartStatus,
|
|
4502
|
+
requiresFullBootstrap,
|
|
4503
|
+
}, null, 2)}\n`
|
|
4504
|
+
writeGeneratedFile({
|
|
4505
|
+
outFile: devSupervisorOutFile,
|
|
4506
|
+
checksumFile: devSupervisorChecksumFile,
|
|
4507
|
+
content: devSupervisorOutput,
|
|
4508
|
+
structureChecksum,
|
|
4509
|
+
result,
|
|
4510
|
+
quiet,
|
|
4511
|
+
})
|
|
4099
4512
|
const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries)
|
|
4100
4513
|
writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet })
|
|
4101
4514
|
|