@open-mercato/cli 0.6.8-develop.7099.1.7ba2771d06 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -7
- package/dist/agentic/guides/module-facts.json +598 -5508
- package/dist/agentic/guides/module-facts.v2.json +598 -5594
- package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
- package/dist/agentic/guides/modules/api_docs/index.md +1 -1
- package/dist/agentic/guides/modules/api_keys/exact-override-targets.md +0 -1
- package/dist/agentic/guides/modules/api_keys/index.md +2 -4
- package/dist/agentic/guides/modules/attachments/di-registrations-rich.md +5 -6
- package/dist/agentic/guides/modules/attachments/di-service-tokens.md +4 -5
- package/dist/agentic/guides/modules/attachments/exact-override-targets.md +5 -6
- package/dist/agentic/guides/modules/attachments/index.md +2 -2
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/di-registrations-rich.md +2 -3
- package/dist/agentic/guides/modules/auth/di-service-tokens.md +2 -3
- package/dist/agentic/guides/modules/auth/exact-override-targets.md +2 -3
- package/dist/agentic/guides/modules/auth/index.md +1 -1
- package/dist/agentic/guides/modules/business_rules/index.md +1 -1
- package/dist/agentic/guides/modules/catalog/incoming-installed-contributions.md +0 -3
- package/dist/agentic/guides/modules/catalog/index.md +2 -2
- package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
- package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
- package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
- package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
- package/dist/agentic/guides/modules/checkout/index.md +1 -1
- package/dist/agentic/guides/modules/communication_channels/di-registrations-rich.md +8 -9
- package/dist/agentic/guides/modules/communication_channels/exact-override-targets.md +8 -9
- package/dist/agentic/guides/modules/communication_channels/incoming-installed-contributions.md +0 -2
- package/dist/agentic/guides/modules/communication_channels/index.md +3 -3
- package/dist/agentic/guides/modules/configs/index.md +1 -1
- package/dist/agentic/guides/modules/content/index.md +1 -1
- package/dist/agentic/guides/modules/currencies/index.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
- package/dist/agentic/guides/modules/customers/active-extension-bindings.md +3 -6
- package/dist/agentic/guides/modules/customers/contribution-resolutions.md +0 -1
- package/dist/agentic/guides/modules/customers/events.md +1 -2
- package/dist/agentic/guides/modules/customers/incoming-installed-contributions.md +0 -7
- package/dist/agentic/guides/modules/customers/index.md +4 -4
- package/dist/agentic/guides/modules/customers/umes-contributions.md +0 -1
- package/dist/agentic/guides/modules/customers/umes-hosts.md +0 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/exact-override-targets.md +2 -2
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/workers.md +2 -2
- package/dist/agentic/guides/modules/design_system/index.md +1 -1
- package/dist/agentic/guides/modules/devices/index.md +1 -1
- package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
- package/dist/agentic/guides/modules/directory/exact-override-targets.md +0 -2
- package/dist/agentic/guides/modules/directory/index.md +3 -5
- package/dist/agentic/guides/modules/entities/index.md +1 -1
- package/dist/agentic/guides/modules/eudr/index.md +1 -1
- package/dist/agentic/guides/modules/events/index.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/exact-override-targets.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/workers.md +1 -1
- package/dist/agentic/guides/modules/generators/index.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
- package/dist/agentic/guides/modules/integrations/index.md +1 -1
- package/dist/agentic/guides/modules/messages/index.md +1 -1
- package/dist/agentic/guides/modules/notifications/index.md +1 -1
- package/dist/agentic/guides/modules/onboarding/index.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
- package/dist/agentic/guides/modules/perspectives/index.md +1 -1
- package/dist/agentic/guides/modules/planner/index.md +1 -1
- package/dist/agentic/guides/modules/portal/index.md +1 -1
- package/dist/agentic/guides/modules/progress/index.md +1 -1
- package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
- package/dist/agentic/guides/modules/query_index/index.md +1 -1
- package/dist/agentic/guides/modules/record_locks/index.md +1 -1
- package/dist/agentic/guides/modules/resources/index.md +1 -1
- package/dist/agentic/guides/modules/sales/active-extension-bindings.md +0 -1
- package/dist/agentic/guides/modules/sales/contribution-resolutions.md +0 -1
- package/dist/agentic/guides/modules/sales/exact-override-targets.md +4 -5
- package/dist/agentic/guides/modules/sales/host-extension-points.md +1 -1
- package/dist/agentic/guides/modules/sales/incoming-installed-contributions.md +0 -2
- package/dist/agentic/guides/modules/sales/index.md +3 -3
- package/dist/agentic/guides/modules/sales/setup.md +1 -1
- package/dist/agentic/guides/modules/sales/umes-contributions.md +0 -1
- package/dist/agentic/guides/modules/sales/umes-diagnostics.md +0 -1
- package/dist/agentic/guides/modules/sales/umes-hosts.md +0 -9
- package/dist/agentic/guides/modules/scheduler/cli-commands.md +0 -1
- package/dist/agentic/guides/modules/scheduler/exact-override-targets.md +1 -3
- package/dist/agentic/guides/modules/scheduler/index.md +2 -2
- package/dist/agentic/guides/modules/scheduler/workers.md +1 -2
- package/dist/agentic/guides/modules/search/index.md +1 -1
- package/dist/agentic/guides/modules/security/index.md +1 -1
- package/dist/agentic/guides/modules/security/owned-contract-module-metadata.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
- package/dist/agentic/guides/modules/sso/index.md +1 -1
- package/dist/agentic/guides/modules/staff/index.md +1 -1
- package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
- package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
- package/dist/agentic/guides/modules/translations/index.md +1 -1
- package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
- package/dist/agentic/guides/modules/webhooks/index.md +1 -1
- package/dist/agentic/guides/modules/wms/index.md +1 -1
- package/dist/agentic/guides/modules/workflows/index.md +1 -1
- package/dist/agentic/guides/reference-module-facts.json +2 -2
- package/dist/agentic/guides/reference-modules/example/index.md +1 -1
- package/dist/agentic/guides/upstream/manifest.json +1 -1
- package/dist/agentic/shared/AGENTS.md.template +3 -3
- package/dist/agentic/shared/ai/harness/README.md +2 -2
- package/dist/agentic/shared/ai/harness/RELEASE.md +6 -8
- package/dist/agentic/shared/ai/harness/cases.json +0 -83
- package/dist/agentic/shared/ai/harness/cases.schema.json +4 -4
- package/dist/agentic/shared/ai/harness/validators.json +1 -1
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.7-to-0.7.0/SKILL.md +12 -3
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +11 -37
- package/dist/lib/generators/ast/index.js +1 -4
- package/dist/lib/generators/ast/index.js.map +2 -2
- package/dist/lib/generators/ast/source-file.js +1 -8
- package/dist/lib/generators/ast/source-file.js.map +2 -2
- package/dist/lib/generators/ast/writers.js +1 -9
- package/dist/lib/generators/ast/writers.js.map +2 -2
- package/dist/lib/generators/module-registry.js +189 -424
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/generators/route-manifest-shards.js +1 -4
- package/dist/lib/generators/route-manifest-shards.js.map +2 -2
- package/dist/lib/spawn.js +2 -3
- package/dist/lib/spawn.js.map +2 -2
- package/dist/lib/testing/integration.js +24 -162
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +0 -14
- package/dist/mercato.js.map +2 -2
- package/package.json +7 -8
- package/src/lib/__tests__/spawn.test.ts +0 -23
- package/src/lib/generators/__tests__/metadata-extraction.test.ts +0 -44
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +8 -32
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -4
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +1 -1
- package/src/lib/generators/__tests__/module-subset.test.ts +72 -96
- package/src/lib/generators/__tests__/output-snapshots.test.ts +1 -1
- package/src/lib/generators/__tests__/route-manifest-shards.test.ts +0 -15
- package/src/lib/generators/__tests__/structural-contracts.test.ts +3 -7
- package/src/lib/generators/ast/index.ts +1 -2
- package/src/lib/generators/ast/source-file.ts +0 -13
- package/src/lib/generators/ast/writers.ts +1 -26
- package/src/lib/generators/module-registry.ts +227 -534
- package/src/lib/generators/route-manifest-shards.ts +1 -8
- package/src/lib/spawn.ts +4 -5
- package/src/lib/testing/__tests__/integration.test.ts +0 -435
- package/src/lib/testing/integration.ts +32 -254
- package/src/mercato.ts +0 -27
- package/dist/agentic/guides/modules/api_keys/di-registrations-rich.md +0 -11
- package/dist/agentic/guides/modules/api_keys/di-service-tokens.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/acl-features.md +0 -13
- package/dist/agentic/guides/modules/channel_discord/ai-agents.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/backend-pages.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/cli-commands.md +0 -13
- package/dist/agentic/guides/modules/channel_discord/contribution-resolutions.md +0 -14
- package/dist/agentic/guides/modules/channel_discord/di-registrations-rich.md +0 -12
- package/dist/agentic/guides/modules/channel_discord/exact-override-targets.md +0 -26
- package/dist/agentic/guides/modules/channel_discord/index.md +0 -22
- package/dist/agentic/guides/modules/channel_discord/owned-contract-module-metadata.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/setup.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/umes-contributions.md +0 -14
- package/dist/agentic/guides/modules/channel_discord/workers.md +0 -12
- package/dist/agentic/guides/modules/directory/di-registrations-rich.md +0 -12
- package/dist/agentic/guides/modules/directory/di-service-tokens.md +0 -12
- package/dist/agentic/guides/modules/documents/acl-features.md +0 -17
- package/dist/agentic/guides/modules/documents/backend-pages.md +0 -13
- package/dist/agentic/guides/modules/documents/contribution-resolutions.md +0 -27
- package/dist/agentic/guides/modules/documents/di-registrations-rich.md +0 -21
- package/dist/agentic/guides/modules/documents/domain-commands.md +0 -37
- package/dist/agentic/guides/modules/documents/encryption.md +0 -11
- package/dist/agentic/guides/modules/documents/entities.md +0 -21
- package/dist/agentic/guides/modules/documents/events.md +0 -25
- package/dist/agentic/guides/modules/documents/exact-override-targets.md +0 -39
- package/dist/agentic/guides/modules/documents/index.md +0 -25
- package/dist/agentic/guides/modules/documents/notifications.md +0 -13
- package/dist/agentic/guides/modules/documents/owned-contract-module-metadata.md +0 -11
- package/dist/agentic/guides/modules/documents/setup.md +0 -11
- package/dist/agentic/guides/modules/documents/umes-contributions.md +0 -27
- package/dist/agentic/guides/modules/documents/umes-hosts.md +0 -36
- package/src/__tests__/resolve-queue-abandon-hook.test.ts +0 -39
- package/src/lib/generators/__tests__/__snapshots__/bootstrap-registrations.test.ts.snap +0 -14
- package/src/lib/generators/__tests__/__snapshots__/command-loaders.test.ts.snap +0 -23
- package/src/lib/generators/__tests__/ast-writers-escaping.test.ts +0 -64
- package/src/lib/generators/__tests__/bootstrap-registrations.test.ts +0 -176
- package/src/lib/generators/__tests__/command-loaders.test.ts +0 -239
- package/src/lib/generators/__tests__/generated-registry-imports.test.ts +0 -128
- package/src/lib/generators/__tests__/registry-variant-parity.test.ts +0 -258
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
"@mikro-orm/decorators": "^7.1.8",
|
|
61
61
|
"@mikro-orm/migrations": "^7.1.8",
|
|
62
62
|
"@mikro-orm/postgresql": "^7.1.8",
|
|
63
|
-
"@open-mercato/queue": "0.
|
|
64
|
-
"@open-mercato/shared": "0.
|
|
65
|
-
"@open-mercato/telemetry": "0.
|
|
63
|
+
"@open-mercato/queue": "0.7.0",
|
|
64
|
+
"@open-mercato/shared": "0.7.0",
|
|
65
|
+
"@open-mercato/telemetry": "0.7.0",
|
|
66
66
|
"cross-spawn": "^7.0.6",
|
|
67
67
|
"pg": "8.22.0",
|
|
68
68
|
"semver": "^7.8.5",
|
|
@@ -73,10 +73,10 @@
|
|
|
73
73
|
"typescript-js": "npm:typescript@6.0.3"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
|
-
"@open-mercato/shared": "0.
|
|
76
|
+
"@open-mercato/shared": "0.7.0"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@open-mercato/shared": "0.
|
|
79
|
+
"@open-mercato/shared": "0.7.0",
|
|
80
80
|
"@types/jest": "^30.0.0",
|
|
81
81
|
"jest": "^30.4.2",
|
|
82
82
|
"ts-jest": "^29.4.12"
|
|
@@ -88,6 +88,5 @@
|
|
|
88
88
|
"type": "git",
|
|
89
89
|
"url": "https://github.com/open-mercato/open-mercato",
|
|
90
90
|
"directory": "packages/cli"
|
|
91
|
-
}
|
|
92
|
-
"stableVersion": "0.6.7"
|
|
91
|
+
}
|
|
93
92
|
}
|
|
@@ -39,26 +39,3 @@ describe('resolveSpawnCommand', () => {
|
|
|
39
39
|
)
|
|
40
40
|
})
|
|
41
41
|
})
|
|
42
|
-
|
|
43
|
-
describe('resolveSpawnCommand detached passthrough', () => {
|
|
44
|
-
// The whole process-group teardown in the ephemeral harness rests on this flag reaching `spawn`:
|
|
45
|
-
// without it the app tree stays in the runner's group and the negated-pid kill has nothing of its
|
|
46
|
-
// own to signal.
|
|
47
|
-
it('passes detached through on the POSIX branch', () => {
|
|
48
|
-
const result = resolveSpawnCommand('yarn', ['start'], { platform: 'linux', detached: true })
|
|
49
|
-
|
|
50
|
-
expect(result.spawnOptions).toEqual({ detached: true })
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('passes detached through on the Windows cmd branch', () => {
|
|
54
|
-
const result = resolveSpawnCommand('yarn.cmd', ['start'], { platform: 'win32', detached: true })
|
|
55
|
-
|
|
56
|
-
expect(result.spawnOptions).toEqual({ detached: true })
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it('omits detached entirely when the caller does not ask for it', () => {
|
|
60
|
-
expect(resolveSpawnCommand('yarn', ['start'], { platform: 'linux' }).spawnOptions).toEqual({})
|
|
61
|
-
expect(resolveSpawnCommand('yarn', ['start']).spawnOptions).not.toHaveProperty('detached')
|
|
62
|
-
expect(resolveSpawnCommand('yarn', ['start'], { platform: 'linux', detached: false }).spawnOptions).toEqual({})
|
|
63
|
-
})
|
|
64
|
-
})
|
|
@@ -4,7 +4,6 @@ import os from 'node:os'
|
|
|
4
4
|
import {
|
|
5
5
|
extractNamedObjectLiteralExport,
|
|
6
6
|
hasNamedExport,
|
|
7
|
-
namedObjectLiteralDeclaresProperty,
|
|
8
7
|
resolveNamedObjectExport,
|
|
9
8
|
} from '../module-registry'
|
|
10
9
|
|
|
@@ -219,46 +218,3 @@ describe('hasNamedExport', () => {
|
|
|
219
218
|
expect(hasNamedExport(file, 'metadata')).toBe(false)
|
|
220
219
|
})
|
|
221
220
|
})
|
|
222
|
-
|
|
223
|
-
describe('namedObjectLiteralDeclaresProperty', () => {
|
|
224
|
-
// A worker declaring `onJobAbandoned: someImportedFn` is the case that broke: the value resolvers
|
|
225
|
-
// cannot evaluate an imported identifier, so "is it declared" has to be answered from the syntax.
|
|
226
|
-
// Getting this wrong is silent — the generator simply never emits the hook.
|
|
227
|
-
it('sees a property whose value is an unresolvable identifier', () => {
|
|
228
|
-
const file = writeSource('worker.ts', `
|
|
229
|
-
import { failAbandonedRun } from '../lib/abandoned-run'
|
|
230
|
-
export const metadata = {
|
|
231
|
-
queue: 'data-sync-import',
|
|
232
|
-
concurrency: 5,
|
|
233
|
-
onJobAbandoned: failAbandonedRun,
|
|
234
|
-
}
|
|
235
|
-
`)
|
|
236
|
-
expect(namedObjectLiteralDeclaresProperty(file, 'metadata', 'onJobAbandoned')).toBe(true)
|
|
237
|
-
expect(extractNamedObjectLiteralExport(file, 'metadata')?.onJobAbandoned).toBeUndefined()
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
it('sees a property declared as an inline function', () => {
|
|
241
|
-
const file = writeSource('worker.ts', `
|
|
242
|
-
export const metadata = {
|
|
243
|
-
queue: 'q',
|
|
244
|
-
onJobAbandoned: async () => {},
|
|
245
|
-
}
|
|
246
|
-
`)
|
|
247
|
-
expect(namedObjectLiteralDeclaresProperty(file, 'metadata', 'onJobAbandoned')).toBe(true)
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
it('reports absence for a worker that declares no hook', () => {
|
|
251
|
-
const file = writeSource('worker.ts', `
|
|
252
|
-
export const metadata = { queue: 'q', concurrency: 1 }
|
|
253
|
-
`)
|
|
254
|
-
expect(namedObjectLiteralDeclaresProperty(file, 'metadata', 'onJobAbandoned')).toBe(false)
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
it('reports absence for a metadata export that is not an object literal', () => {
|
|
258
|
-
const file = writeSource('worker.ts', `
|
|
259
|
-
const base = buildMetadata()
|
|
260
|
-
export const metadata = base
|
|
261
|
-
`)
|
|
262
|
-
expect(namedObjectLiteralDeclaresProperty(file, 'metadata', 'onJobAbandoned')).toBe(false)
|
|
263
|
-
})
|
|
264
|
-
})
|
|
@@ -149,46 +149,22 @@ describe('module-facts BC resolve guard (T2)', () => {
|
|
|
149
149
|
// wms, staff, integrations and checkout were therefore invisible to every fact
|
|
150
150
|
// consumer — `integrations` published no contributions at all. Reading them costs
|
|
151
151
|
// ~28KB, which is the fix working, not drift.
|
|
152
|
-
// The additive EUDR
|
|
153
|
-
//
|
|
154
|
-
// shape.
|
|
152
|
+
// The additive EUDR module contributes its real routes, ACL, events,
|
|
153
|
+
// entities, and extension surfaces without changing the extraction shape.
|
|
155
154
|
//
|
|
156
155
|
// JSON cap raised a fifth time by the devices/push-notifications stack: the
|
|
157
156
|
// `devices` and `push_notifications` modules plus the `channel-fcm`,
|
|
158
157
|
// `channel-apns` and `channel-expo` provider packages add their own facts,
|
|
159
158
|
// provenance entries and override targets to every render. The
|
|
160
|
-
// `warranty_claims` module (see above)
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
// a schema or extraction change, this one tracks ordinary repo growth. The
|
|
165
|
-
// additive `channel_discord` module costs ~15.9KB JSON and ~9.2KB markdown
|
|
166
|
-
// (`channel_gmail` costs 6,886 / `channel_imap` 6,798; the difference is a
|
|
167
|
-
// gateway worker, a CLI command, a signed route and a subscriber, spread
|
|
168
|
-
// proportionally across overrideTargets, extensionSurfaces, factSources and
|
|
169
|
-
// ownedContracts — no duplicated payloads).
|
|
170
|
-
//
|
|
171
|
-
// The numbers below are MEASURED ON THE MERGED TREE, not transcribed from
|
|
172
|
-
// either side of the merge: neither side's cap covers the union. A cap that
|
|
173
|
-
// sits a fraction of a percent above the current measurement has stopped
|
|
174
|
-
// detecting blow-ups and started rejecting the next additive module of any
|
|
175
|
-
// size, whichever PR happens to add it — so keep bounded headroom over the
|
|
176
|
-
// measured size. A real blow-up here is multiplicative (a duplicated
|
|
177
|
-
// provenance payload, a contribution body copied per resolution), not one
|
|
178
|
-
// provider's worth of references.
|
|
179
|
-
expect(Buffer.byteLength(completeJson)).toBeLessThan(4_700_000)
|
|
180
|
-
// Measured on the merged tree (`yarn jest module-facts.bc-guard`):
|
|
181
|
-
// completeJson 4,120,374 · legacy delta 1,795,214 · markdown 1,558,590 ·
|
|
182
|
-
// directory markdown 1,709,511.
|
|
183
|
-
// The delta cap is raised alongside the JSON one for the same reason: at
|
|
184
|
-
// 1,800,000 it sat 0.27% above the measurement, which is not a guard.
|
|
185
|
-
expect(Buffer.byteLength(completeJson) - Buffer.byteLength(legacyJson)).toBeLessThan(2_050_000)
|
|
159
|
+
// `warranty_claims` module (see above) lands alongside it, so the cap
|
|
160
|
+
// absorbs both additions.
|
|
161
|
+
expect(Buffer.byteLength(completeJson)).toBeLessThan(4_000_000)
|
|
162
|
+
expect(Buffer.byteLength(completeJson) - Buffer.byteLength(legacyJson)).toBeLessThan(1_800_000)
|
|
186
163
|
// Markdown cap raised with the source-link contract: entities, events, ACL
|
|
187
164
|
// features, DI tokens, search entities, notifications, UMES hosts and UMES
|
|
188
165
|
// contributions all render a resolved Source cell, and contribution
|
|
189
|
-
// resolutions render as their own source-linked section
|
|
190
|
-
|
|
191
|
-
expect(markdownBytes).toBeLessThan(1_800_000)
|
|
166
|
+
// resolutions render as their own source-linked section.
|
|
167
|
+
expect(markdownBytes).toBeLessThan(1_750_000)
|
|
192
168
|
expect(directoryMarkdownBytes).toBeLessThan(2_050_000)
|
|
193
169
|
})
|
|
194
170
|
|
|
@@ -28,10 +28,7 @@ describe('module-facts customers fixture (T1 anti-drift guard)', () => {
|
|
|
28
28
|
})
|
|
29
29
|
|
|
30
30
|
it('locks customers events, acl, search, and notification surfaces', () => {
|
|
31
|
-
|
|
32
|
-
// sibling of the person_company_link CRUD events. Bump deliberately: this guard exists to
|
|
33
|
-
// make an event-surface change visible, not to be silenced.
|
|
34
|
-
expect(facts.events).toHaveLength(50)
|
|
31
|
+
expect(facts.events).toHaveLength(49)
|
|
35
32
|
expect(facts.aclFeatures).toHaveLength(21)
|
|
36
33
|
expect(facts.searchEntities).toEqual([
|
|
37
34
|
'customers:customer_person_profile',
|
|
@@ -103,6 +103,6 @@ describe('module-facts extension host extraction', () => {
|
|
|
103
103
|
])
|
|
104
104
|
|
|
105
105
|
const sales = extractModuleFacts({ moduleId: 'sales', coreSrcRoot })
|
|
106
|
-
expect(sales.hostTokens.tableIds).toEqual(['sales.orders', 'sales.
|
|
106
|
+
expect(sales.hostTokens.tableIds).toEqual(['sales.orders', 'sales.quotes'])
|
|
107
107
|
})
|
|
108
108
|
})
|
|
@@ -186,65 +186,65 @@ describe('generateModuleRegistry with module subsets', () => {
|
|
|
186
186
|
expect(output).toContain('export default modules')
|
|
187
187
|
})
|
|
188
188
|
|
|
189
|
-
it('
|
|
189
|
+
it('preserves exact legacy empty output format for the refactored registry files', async () => {
|
|
190
190
|
const resolver = createMockResolver(tmpDir, [])
|
|
191
191
|
const result = await generateModuleRegistry({ resolver, quiet: true })
|
|
192
192
|
|
|
193
193
|
expect(result.errors).toEqual([])
|
|
194
194
|
expect(readGenerated(tmpDir, 'modules.generated.ts')).toBe(dedent(`
|
|
195
195
|
// AUTO-GENERATED by mercato generate registry
|
|
196
|
-
import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from
|
|
196
|
+
import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from '@open-mercato/shared/modules/registry'
|
|
197
197
|
|
|
198
|
-
export const modules: Module[] = [
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
export
|
|
203
|
-
id: m.id,
|
|
204
|
-
...m.info || {}
|
|
205
|
-
}));
|
|
198
|
+
export const modules: Module[] = [
|
|
199
|
+
|
|
200
|
+
]
|
|
201
|
+
export const modulesInfo = modules.map(m => ({ id: m.id, ...(m.info || {}) }))
|
|
202
|
+
export default modules
|
|
206
203
|
`))
|
|
207
204
|
expect(readGenerated(tmpDir, 'modules.runtime.generated.ts')).toBe(dedent(`
|
|
208
205
|
// AUTO-GENERATED by mercato generate registry
|
|
209
|
-
import { createElement } from
|
|
210
|
-
import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from
|
|
211
|
-
|
|
212
|
-
export const modules: Module[] = [];
|
|
206
|
+
import { createElement } from 'react'
|
|
207
|
+
import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from '@open-mercato/shared/modules/registry'
|
|
213
208
|
|
|
214
|
-
export
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}));
|
|
209
|
+
export const modules: Module[] = [
|
|
210
|
+
|
|
211
|
+
]
|
|
212
|
+
export const modulesInfo = modules.map(m => ({ id: m.id, ...(m.info || {}) }))
|
|
213
|
+
export default modules
|
|
220
214
|
`))
|
|
221
215
|
expect(readGenerated(tmpDir, 'frontend-routes.generated.ts')).toBe(dedent(`
|
|
222
216
|
// AUTO-GENERATED by mercato generate registry
|
|
223
|
-
import { resolvePageRouteMetadata, type FrontendRouteManifestEntry } from
|
|
217
|
+
import { resolvePageRouteMetadata, type FrontendRouteManifestEntry } from '@open-mercato/shared/modules/registry'
|
|
224
218
|
|
|
225
|
-
export const frontendRoutes: FrontendRouteManifestEntry[] = [
|
|
219
|
+
export const frontendRoutes: FrontendRouteManifestEntry[] = [
|
|
220
|
+
|
|
221
|
+
]
|
|
226
222
|
|
|
227
|
-
export default frontendRoutes
|
|
223
|
+
export default frontendRoutes
|
|
228
224
|
`))
|
|
229
225
|
expect(readGenerated(tmpDir, 'backend-routes.generated.ts')).toBe(dedent(`
|
|
230
226
|
// AUTO-GENERATED by mercato generate registry
|
|
231
|
-
import { resolvePageRouteMetadata, type BackendRouteManifestEntry } from
|
|
227
|
+
import { resolvePageRouteMetadata, type BackendRouteManifestEntry } from '@open-mercato/shared/modules/registry'
|
|
232
228
|
|
|
233
|
-
export const backendRoutes: BackendRouteManifestEntry[] = [
|
|
229
|
+
export const backendRoutes: BackendRouteManifestEntry[] = [
|
|
230
|
+
|
|
231
|
+
]
|
|
234
232
|
|
|
235
|
-
export default backendRoutes
|
|
233
|
+
export default backendRoutes
|
|
236
234
|
`))
|
|
237
235
|
expect(readGenerated(tmpDir, 'api-routes.generated.ts')).toBe(dedent(`
|
|
238
236
|
// AUTO-GENERATED by mercato generate registry
|
|
239
|
-
import type { ApiRouteManifestEntry } from
|
|
237
|
+
import type { ApiRouteManifestEntry } from '@open-mercato/shared/modules/registry'
|
|
240
238
|
|
|
241
|
-
export const apiRoutes: ApiRouteManifestEntry[] = [
|
|
239
|
+
export const apiRoutes: ApiRouteManifestEntry[] = [
|
|
240
|
+
|
|
241
|
+
]
|
|
242
242
|
|
|
243
|
-
export default apiRoutes
|
|
243
|
+
export default apiRoutes
|
|
244
244
|
`))
|
|
245
245
|
})
|
|
246
246
|
|
|
247
|
-
it('
|
|
247
|
+
it('preserves exact legacy populated output format for the refactored registry files', async () => {
|
|
248
248
|
touchFile(
|
|
249
249
|
path.join(tmpDir, 'packages', 'core', 'src', 'modules', 'orders', 'index.ts'),
|
|
250
250
|
"export const metadata = { id: 'orders', label: 'Orders' }\n",
|
|
@@ -267,99 +267,75 @@ describe('generateModuleRegistry with module subsets', () => {
|
|
|
267
267
|
|
|
268
268
|
expect(result.errors).toEqual([])
|
|
269
269
|
const modulesGenerated = readGenerated(tmpDir, 'modules.generated.ts')
|
|
270
|
-
expect(modulesGenerated).toContain(`import { createElement } from
|
|
270
|
+
expect(modulesGenerated).toContain(`import { createElement } from 'react'`)
|
|
271
271
|
expect(modulesGenerated).toContain(`import * as I0_orders from "@open-mercato/core/modules/orders/index"`)
|
|
272
272
|
expect(modulesGenerated).not.toContain(`import C1_orders_index`)
|
|
273
273
|
expect(modulesGenerated).not.toContain(`import B5_orders_index`)
|
|
274
|
-
expect(modulesGenerated).
|
|
275
|
-
expect(modulesGenerated).
|
|
274
|
+
expect(modulesGenerated).toContain(`frontendRoutes: [{ pattern: "/"`)
|
|
275
|
+
expect(modulesGenerated).toContain(`backendRoutes: [{ pattern: "/backend/orders"`)
|
|
276
276
|
expect(modulesGenerated).toContain(`Component: async (props: any) => { const mod = await import("@open-mercato/core/modules/orders/frontend/page")`)
|
|
277
277
|
expect(modulesGenerated).toContain(`Component: async (props: any) => { const mod = await import("@open-mercato/core/modules/orders/backend/page")`)
|
|
278
|
-
expect(modulesGenerated).
|
|
279
|
-
expect(modulesGenerated).toContain(`{ path: ((R9_orders_orders as any).metadata?.path ?? "/orders/orders"), metadata: (R9_orders_orders as any).metadata, handlers: R9_orders_orders as any }`)
|
|
278
|
+
expect(modulesGenerated).toContain(`apis: [{ path: ((R9_orders_orders as any).metadata?.path ?? "/orders/orders"), metadata: (R9_orders_orders as any).metadata, handlers: R9_orders_orders as any }]`)
|
|
280
279
|
expect(readGenerated(tmpDir, 'modules.runtime.generated.ts')).toBe(dedent(`
|
|
281
280
|
// AUTO-GENERATED by mercato generate registry
|
|
282
|
-
import { createElement } from
|
|
283
|
-
import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from
|
|
284
|
-
import * as I0_orders from "@open-mercato/core/modules/orders/index"
|
|
285
|
-
import * as MRuntime3_orders_index from "@open-mercato/core/modules/orders/frontend/page"
|
|
286
|
-
import * as BMRuntime7_orders_index from "@open-mercato/core/modules/orders/backend/page"
|
|
281
|
+
import { createElement } from 'react'
|
|
282
|
+
import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from '@open-mercato/shared/modules/registry'
|
|
283
|
+
import * as I0_orders from "@open-mercato/core/modules/orders/index"
|
|
284
|
+
import * as MRuntime3_orders_index from "@open-mercato/core/modules/orders/frontend/page"
|
|
285
|
+
import * as BMRuntime7_orders_index from "@open-mercato/core/modules/orders/backend/page"
|
|
287
286
|
|
|
288
287
|
export const modules: Module[] = [
|
|
289
|
-
|
|
288
|
+
{
|
|
290
289
|
id: "orders",
|
|
291
290
|
info: I0_orders.metadata,
|
|
292
|
-
frontendRoutes: [
|
|
293
|
-
|
|
294
|
-
],
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
291
|
+
frontendRoutes: [{ pattern: "/", requireAuth: ((((MRuntime3_orders_index as any).metadata) as any))?.requireAuth, requireRoles: ((((MRuntime3_orders_index as any).metadata) as any))?.requireRoles, requireFeatures: ((((MRuntime3_orders_index as any).metadata) as any))?.requireFeatures, requireCustomerAuth: ((((MRuntime3_orders_index as any).metadata) as any))?.requireCustomerAuth, requireCustomerFeatures: ((((MRuntime3_orders_index as any).metadata) as any))?.requireCustomerFeatures, nav: ((((MRuntime3_orders_index as any).metadata) as any))?.nav, title: ((((MRuntime3_orders_index as any).metadata) as any))?.pageTitle ?? ((((MRuntime3_orders_index as any).metadata) as any))?.title, titleKey: ((((MRuntime3_orders_index as any).metadata) as any))?.pageTitleKey ?? ((((MRuntime3_orders_index as any).metadata) as any))?.titleKey, group: ((((MRuntime3_orders_index as any).metadata) as any))?.pageGroup ?? ((((MRuntime3_orders_index as any).metadata) as any))?.group, groupKey: ((((MRuntime3_orders_index as any).metadata) as any))?.pageGroupKey ?? ((((MRuntime3_orders_index as any).metadata) as any))?.groupKey, icon: ((((MRuntime3_orders_index as any).metadata) as any))?.icon, order: ((((MRuntime3_orders_index as any).metadata) as any))?.pageOrder ?? ((((MRuntime3_orders_index as any).metadata) as any))?.order, priority: ((((MRuntime3_orders_index as any).metadata) as any))?.pagePriority ?? ((((MRuntime3_orders_index as any).metadata) as any))?.priority, navHidden: ((((MRuntime3_orders_index as any).metadata) as any))?.navHidden, visible: ((((MRuntime3_orders_index as any).metadata) as any))?.visible, enabled: ((((MRuntime3_orders_index as any).metadata) as any))?.enabled, breadcrumb: ((((MRuntime3_orders_index as any).metadata) as any))?.breadcrumb, pageContext: ((((MRuntime3_orders_index as any).metadata) as any))?.pageContext, placement: ((((MRuntime3_orders_index as any).metadata) as any))?.placement, Component: async (props: any) => { const mod = await import("@open-mercato/core/modules/orders/frontend/page"); const Component = (mod.default ?? mod) as any; return createElement(Component, props) } }],
|
|
292
|
+
backendRoutes: [{ pattern: "/backend/orders", requireAuth: ((((BMRuntime7_orders_index as any).metadata) as any))?.requireAuth, requireRoles: ((((BMRuntime7_orders_index as any).metadata) as any))?.requireRoles, requireFeatures: ((((BMRuntime7_orders_index as any).metadata) as any))?.requireFeatures, requireCustomerAuth: ((((BMRuntime7_orders_index as any).metadata) as any))?.requireCustomerAuth, requireCustomerFeatures: ((((BMRuntime7_orders_index as any).metadata) as any))?.requireCustomerFeatures, nav: ((((BMRuntime7_orders_index as any).metadata) as any))?.nav, title: ((((BMRuntime7_orders_index as any).metadata) as any))?.pageTitle ?? ((((BMRuntime7_orders_index as any).metadata) as any))?.title, titleKey: ((((BMRuntime7_orders_index as any).metadata) as any))?.pageTitleKey ?? ((((BMRuntime7_orders_index as any).metadata) as any))?.titleKey, group: ((((BMRuntime7_orders_index as any).metadata) as any))?.pageGroup ?? ((((BMRuntime7_orders_index as any).metadata) as any))?.group, groupKey: ((((BMRuntime7_orders_index as any).metadata) as any))?.pageGroupKey ?? ((((BMRuntime7_orders_index as any).metadata) as any))?.groupKey, icon: ((((BMRuntime7_orders_index as any).metadata) as any))?.icon, order: ((((BMRuntime7_orders_index as any).metadata) as any))?.pageOrder ?? ((((BMRuntime7_orders_index as any).metadata) as any))?.order, priority: ((((BMRuntime7_orders_index as any).metadata) as any))?.pagePriority ?? ((((BMRuntime7_orders_index as any).metadata) as any))?.priority, navHidden: ((((BMRuntime7_orders_index as any).metadata) as any))?.navHidden, visible: ((((BMRuntime7_orders_index as any).metadata) as any))?.visible, enabled: ((((BMRuntime7_orders_index as any).metadata) as any))?.enabled, breadcrumb: ((((BMRuntime7_orders_index as any).metadata) as any))?.breadcrumb, pageContext: ((((BMRuntime7_orders_index as any).metadata) as any))?.pageContext, placement: ((((BMRuntime7_orders_index as any).metadata) as any))?.placement, Component: async (props: any) => { const mod = await import("@open-mercato/core/modules/orders/backend/page"); const Component = (mod.default ?? mod) as any; return createElement(Component, props) } }],
|
|
293
|
+
apis: [{ path: "/orders/orders", metadata: undefined, handlers: { GET: async (req: Request, ctx?: any) => { const mod = await import("@open-mercato/core/modules/orders/api/orders/route"); return (mod as any).GET(req, ctx) } } }],
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
customFieldSets: [],
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
302
305
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
export default modules
|
|
306
|
-
|
|
307
|
-
export const modulesInfo = modules.map((m) => ({
|
|
308
|
-
id: m.id,
|
|
309
|
-
...m.info || {}
|
|
310
|
-
}));
|
|
306
|
+
]
|
|
307
|
+
export const modulesInfo = modules.map(m => ({ id: m.id, ...(m.info || {}) }))
|
|
308
|
+
export default modules
|
|
311
309
|
`))
|
|
312
310
|
expect(readGenerated(tmpDir, 'frontend-routes.generated.ts')).toBe(dedent(`
|
|
313
311
|
// AUTO-GENERATED by mercato generate registry
|
|
314
|
-
import { resolvePageRouteMetadata, type FrontendRouteManifestEntry } from
|
|
312
|
+
import { resolvePageRouteMetadata, type FrontendRouteManifestEntry } from '@open-mercato/shared/modules/registry'
|
|
315
313
|
|
|
316
314
|
export const frontendRoutes: FrontendRouteManifestEntry[] = [
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
...resolvePageRouteMetadata("/", (undefined as any)),
|
|
320
|
-
load: async () => {
|
|
321
|
-
const mod = await import("@open-mercato/core/modules/orders/frontend/page");
|
|
322
|
-
return ((mod.default ?? mod) as any);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
];
|
|
315
|
+
{ moduleId: "orders", ...resolvePageRouteMetadata("/", (undefined as any)), load: async () => { const mod = await import("@open-mercato/core/modules/orders/frontend/page"); return (mod.default ?? mod) as any } }
|
|
316
|
+
]
|
|
326
317
|
|
|
327
|
-
export default frontendRoutes
|
|
318
|
+
export default frontendRoutes
|
|
328
319
|
`))
|
|
329
320
|
expect(readGenerated(tmpDir, 'backend-routes.generated.ts')).toBe(dedent(`
|
|
330
321
|
// AUTO-GENERATED by mercato generate registry
|
|
331
|
-
import { resolvePageRouteMetadata, type BackendRouteManifestEntry } from
|
|
322
|
+
import { resolvePageRouteMetadata, type BackendRouteManifestEntry } from '@open-mercato/shared/modules/registry'
|
|
332
323
|
|
|
333
324
|
export const backendRoutes: BackendRouteManifestEntry[] = [
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
...resolvePageRouteMetadata("/backend/orders", (undefined as any)),
|
|
337
|
-
load: async () => {
|
|
338
|
-
const mod = await import("@open-mercato/core/modules/orders/backend/page");
|
|
339
|
-
return ((mod.default ?? mod) as any);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
];
|
|
325
|
+
{ moduleId: "orders", ...resolvePageRouteMetadata("/backend/orders", (undefined as any)), load: async () => { const mod = await import("@open-mercato/core/modules/orders/backend/page"); return (mod.default ?? mod) as any } }
|
|
326
|
+
]
|
|
343
327
|
|
|
344
|
-
export default backendRoutes
|
|
328
|
+
export default backendRoutes
|
|
345
329
|
`))
|
|
346
330
|
expect(readGenerated(tmpDir, 'api-routes.generated.ts')).toBe(dedent(`
|
|
347
331
|
// AUTO-GENERATED by mercato generate registry
|
|
348
|
-
import type { ApiRouteManifestEntry } from
|
|
332
|
+
import type { ApiRouteManifestEntry } from '@open-mercato/shared/modules/registry'
|
|
349
333
|
|
|
350
334
|
export const apiRoutes: ApiRouteManifestEntry[] = [
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
kind: "route-file",
|
|
354
|
-
path: "/orders/orders",
|
|
355
|
-
methods: [
|
|
356
|
-
"GET"
|
|
357
|
-
],
|
|
358
|
-
load: async () => import("@open-mercato/core/modules/orders/api/orders/route")
|
|
359
|
-
}
|
|
360
|
-
];
|
|
335
|
+
{ moduleId: "orders", kind: "route-file", path: "/orders/orders", methods: ["GET"], load: async () => import("@open-mercato/core/modules/orders/api/orders/route") }
|
|
336
|
+
]
|
|
361
337
|
|
|
362
|
-
export default apiRoutes
|
|
338
|
+
export default apiRoutes
|
|
363
339
|
`))
|
|
364
340
|
})
|
|
365
341
|
|
|
@@ -599,7 +575,7 @@ export { POST, PUT, DELETE }
|
|
|
599
575
|
expect(result.errors).toEqual([])
|
|
600
576
|
const apiRoutes = readGenerated(tmpDir, 'api-routes.generated.ts')!
|
|
601
577
|
expect(apiRoutes).toContain('path: "/customers/people"')
|
|
602
|
-
expect(apiRoutes).
|
|
578
|
+
expect(apiRoutes).toContain('methods: ["GET", "POST", "PUT", "DELETE"]')
|
|
603
579
|
})
|
|
604
580
|
|
|
605
581
|
it('partitions API and backend loader graphs while preserving legacy manifests', async () => {
|
|
@@ -684,7 +660,7 @@ export const { metadata, GET, POST, PUT, DELETE } = crud
|
|
|
684
660
|
expect(result.errors).toEqual([])
|
|
685
661
|
const apiRoutes = readGenerated(tmpDir, 'api-routes.generated.ts')!
|
|
686
662
|
expect(apiRoutes).toContain('path: "/example/todos"')
|
|
687
|
-
expect(apiRoutes).
|
|
663
|
+
expect(apiRoutes).toContain('methods: ["GET", "POST", "PUT", "DELETE"]')
|
|
688
664
|
})
|
|
689
665
|
|
|
690
666
|
it('uses metadata.path in api route manifests when source import fails during generation', async () => {
|
|
@@ -1071,7 +1047,7 @@ export function GET() {
|
|
|
1071
1047
|
)
|
|
1072
1048
|
|
|
1073
1049
|
expect(output).toContain('@open-mercato/core/modules/customers/i18n/en.json')
|
|
1074
|
-
expect(output).
|
|
1050
|
+
expect(output).toContain(`'en':`)
|
|
1075
1051
|
})
|
|
1076
1052
|
})
|
|
1077
1053
|
|
|
@@ -832,7 +832,7 @@ describe('generator output compatibility', () => {
|
|
|
832
832
|
expect(content).toContain(`import { backendRouteFacades } from "./backend-route-shards.generated"`)
|
|
833
833
|
expect(content).toContain(`import { frontendRoutes } from "./frontend-routes.generated"`)
|
|
834
834
|
expect(content).toContain(
|
|
835
|
-
`import { registerBackendRouteManifests, registerFrontendRouteManifests } from
|
|
835
|
+
`import { registerBackendRouteManifests, registerFrontendRouteManifests } from '@open-mercato/shared/modules/registry'`,
|
|
836
836
|
)
|
|
837
837
|
expect(content).toMatch(/export function runBootstrapRegistrations\(\): void \{[\s\S]*registerBackendRouteManifests\(backendRouteFacades\)[\s\S]*\}/)
|
|
838
838
|
expect(content).toMatch(/export function runBootstrapRegistrations\(\): void \{[\s\S]*registerFrontendRouteManifests\(frontendRoutes\)[\s\S]*\}/)
|
|
@@ -47,21 +47,6 @@ describe('route manifest shards', () => {
|
|
|
47
47
|
expect(loader).toContain(`const ROUTE_SHARD_KEYS = ["customers","__dynamic","customers","__root"]`)
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
-
it('indents every line of a multi-line declaration inside the shard array', () => {
|
|
51
|
-
const declaration = ['{', ' moduleId: "customers",', ' path: "/customers"', '} as any'].join('\n')
|
|
52
|
-
const outputs = renderRouteManifestShardOutputs('api', [{ path: '/customers', declaration }])
|
|
53
|
-
const shard = outputs.find((entry) => entry.fileName.includes('route-shard.'))?.content ?? ''
|
|
54
|
-
|
|
55
|
-
expect(shard).toContain([
|
|
56
|
-
'export const routes: ApiRouteManifestEntry[] = [',
|
|
57
|
-
' {',
|
|
58
|
-
' moduleId: "customers",',
|
|
59
|
-
' path: "/customers"',
|
|
60
|
-
' } as any',
|
|
61
|
-
']',
|
|
62
|
-
].join('\n'))
|
|
63
|
-
})
|
|
64
|
-
|
|
65
50
|
it('renders metadata without load functions while retaining metadata imports', () => {
|
|
66
51
|
const output = renderRouteMetadataOutput('backend', [{
|
|
67
52
|
path: '/backend/settings',
|
|
@@ -186,7 +186,6 @@ function scaffoldFixture(): ModuleEntry[] {
|
|
|
186
186
|
touchFile(pkgModulePath('orders', 'subscribers', 'on-created.ts'), "export const metadata = { event: 'orders.order.created', persistent: true }\nexport default async function handler() {}\n")
|
|
187
187
|
touchFile(pkgModulePath('orders', 'subscribers', 'on-payment.ts'), "export const metadata = { event: 'payments.payment.completed', persistent: true }\nexport default async function handler() {}\n")
|
|
188
188
|
touchFile(pkgModulePath('orders', 'workers', 'sync-job.ts'), "export const metadata = { queue: 'orders.sync', concurrency: 2 }\nexport default async function handler() {}\n")
|
|
189
|
-
touchFile(pkgModulePath('orders', 'workers', 'safe-job.ts'), "export const metadata = { queue: 'orders.safe', schedulerSafe: true }\nexport default async function handler() {}\n")
|
|
190
189
|
touchFile(pkgModulePath('orders', 'widgets', 'dashboard', 'revenue', 'widget.tsx'), 'export default function RevenueWidget() { return null }\n')
|
|
191
190
|
touchFile(pkgModulePath('orders', 'widgets', 'injection', 'sidebar', 'widget.tsx'), 'export default function SidebarWidget() { return null }\n')
|
|
192
191
|
touchFile(pkgModulePath('orders', 'widgets', 'injection-table.ts'), `export const injectionTable = {\n 'crud-form:orders:sales_order:fields': [{ widgetId: 'orders.sidebar', kind: 'section', priority: 50 }],\n}\nexport default injectionTable\n`)
|
|
@@ -508,8 +507,8 @@ describe('modules.generated.ts', () => {
|
|
|
508
507
|
})
|
|
509
508
|
|
|
510
509
|
it('modules include translation locale keys', () => {
|
|
511
|
-
expect(content).
|
|
512
|
-
expect(content).
|
|
510
|
+
expect(content).toContain("'en':")
|
|
511
|
+
expect(content).toContain("'pl':")
|
|
513
512
|
})
|
|
514
513
|
|
|
515
514
|
it('modules include customFieldSets reference from ce.ts', () => {
|
|
@@ -636,7 +635,7 @@ describe('api-routes.generated.ts', () => {
|
|
|
636
635
|
|
|
637
636
|
it('products API route has all 4 methods', () => {
|
|
638
637
|
expect(content).toContain('path: "/products"')
|
|
639
|
-
expect(content).toMatch(/methods
|
|
638
|
+
expect(content).toMatch(/methods:.*GET.*POST.*PUT.*DELETE/)
|
|
640
639
|
})
|
|
641
640
|
|
|
642
641
|
it('keeps API handler imports lazy in route entries', () => {
|
|
@@ -1266,9 +1265,6 @@ describe('modules.bootstrap.generated.ts', () => {
|
|
|
1266
1265
|
expect(content).toContain('orders.order.created')
|
|
1267
1266
|
expect(content).toContain('setup:')
|
|
1268
1267
|
expect(content).toContain('features:')
|
|
1269
|
-
// worker metadata flags must survive into the registry the server registers
|
|
1270
|
-
expect(content).toContain("queue: \"orders.safe\"")
|
|
1271
|
-
expect(content).toContain('schedulerSafe: true')
|
|
1272
1268
|
|
|
1273
1269
|
expect(content).not.toContain('frontendRoutes:')
|
|
1274
1270
|
expect(content).not.toContain('backendRoutes:')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { addImportSpec, addImportSpecs, addImportStatement, addImportStatements, type GeneratedImportSpec } from './imports'
|
|
2
|
-
export { addAutoGeneratedComment, createGeneratedSourceFile, getSourceText
|
|
2
|
+
export { addAutoGeneratedComment, createGeneratedSourceFile, getSourceText } from './source-file'
|
|
3
3
|
export {
|
|
4
4
|
arrayLiteral,
|
|
5
5
|
assignmentStatement,
|
|
@@ -11,7 +11,6 @@ export {
|
|
|
11
11
|
callExpression,
|
|
12
12
|
conditionalExpression,
|
|
13
13
|
elementAccess,
|
|
14
|
-
escapeGeneratedJsonLiteral,
|
|
15
14
|
expressionStatement,
|
|
16
15
|
forOfStatement,
|
|
17
16
|
identifier,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { IndentationText, Project, type SourceFile } from 'ts-morph'
|
|
2
|
-
import { writeValue, type GeneratedValue } from './writers'
|
|
3
2
|
|
|
4
3
|
let sharedProject: Project | null = null
|
|
5
4
|
|
|
@@ -27,18 +26,6 @@ export function createGeneratedSourceFile(fileName: string): SourceFile {
|
|
|
27
26
|
return project.createSourceFile(fileName, '', { overwrite: true })
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
/**
|
|
31
|
-
* Renders a single generated value to source text, outside of any source file. Generators
|
|
32
|
-
* that hand a pre-rendered expression to a consumer expecting a string (route manifest
|
|
33
|
-
* shards) use this instead of concatenating the expression by hand, so the AST writers stay
|
|
34
|
-
* the one place an expression is constructed.
|
|
35
|
-
*/
|
|
36
|
-
export function renderGeneratedValue(value: GeneratedValue): string {
|
|
37
|
-
const writer = getProject().createWriter()
|
|
38
|
-
writeValue(writer, value)
|
|
39
|
-
return writer.toString()
|
|
40
|
-
}
|
|
41
|
-
|
|
42
29
|
export function addAutoGeneratedComment(sourceFile: SourceFile, generator: string): void {
|
|
43
30
|
sourceFile.insertText(0, `// AUTO-GENERATED by mercato generate ${generator}\n`)
|
|
44
31
|
}
|
|
@@ -22,31 +22,6 @@ export interface SpreadPropertyWriter {
|
|
|
22
22
|
export type GeneratedObjectEntry = ObjectPropertyWriter | SpreadPropertyWriter
|
|
23
23
|
export type StatementWriter = WriterFunction
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
* Escapes the characters that are legal inside a JSON string but hazardous inside a
|
|
27
|
-
* generated JavaScript source file: `<` and `>` so an emitted value can never close a
|
|
28
|
-
* surrounding script context, and U+2028 / U+2029 which older JavaScript parsers reject
|
|
29
|
-
* inside a string literal. The escape sequences denote the same runtime string, so this
|
|
30
|
-
* only ever changes the emitted text, never the emitted value.
|
|
31
|
-
*/
|
|
32
|
-
export function escapeGeneratedJsonLiteral(json: string): string {
|
|
33
|
-
return json
|
|
34
|
-
.replace(/</g, '\\u003c')
|
|
35
|
-
.replace(/>/g, '\\u003e')
|
|
36
|
-
.replace(/\u2028/g, '\\u2028')
|
|
37
|
-
.replace(/\u2029/g, '\\u2029')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The single point where a string value becomes source text on the AST path. The string
|
|
42
|
-
* paths that are still emitted as templates share the escaping step above rather than
|
|
43
|
-
* this function, because they also serialize objects, whose nested strings need the same
|
|
44
|
-
* hardening.
|
|
45
|
-
*/
|
|
46
|
-
export function stringLiteral(value: string): string {
|
|
47
|
-
return escapeGeneratedJsonLiteral(JSON.stringify(value))
|
|
48
|
-
}
|
|
49
|
-
|
|
50
25
|
export function writeLiteral(writer: CodeBlockWriter, value: Exclude<GeneratedValue, WriterFunction>): void {
|
|
51
26
|
if (value === undefined) {
|
|
52
27
|
writer.write('undefined')
|
|
@@ -59,7 +34,7 @@ export function writeLiteral(writer: CodeBlockWriter, value: Exclude<GeneratedVa
|
|
|
59
34
|
}
|
|
60
35
|
|
|
61
36
|
if (typeof value === 'string') {
|
|
62
|
-
writer.write(
|
|
37
|
+
writer.write(JSON.stringify(value))
|
|
63
38
|
return
|
|
64
39
|
}
|
|
65
40
|
|