@elevasis/core 0.22.0 → 0.24.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/dist/index.d.ts +3214 -2501
- package/dist/index.js +3112 -1222
- package/dist/knowledge/index.d.ts +1108 -1264
- package/dist/knowledge/index.js +112 -9
- package/dist/organization-model/index.d.ts +3214 -2501
- package/dist/organization-model/index.js +3112 -1222
- package/dist/test-utils/index.d.ts +985 -1103
- package/dist/test-utils/index.js +2464 -1165
- package/package.json +5 -5
- package/src/README.md +14 -14
- package/src/__tests__/publish.test.ts +24 -24
- package/src/__tests__/template-core-compatibility.test.ts +9 -80
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +2389 -2121
- package/src/_gen/__tests__/scaffold-contracts.test.ts +30 -30
- package/src/auth/multi-tenancy/credentials/__tests__/encryption.test.ts +217 -217
- package/src/auth/multi-tenancy/credentials/server/encryption.ts +69 -69
- package/src/auth/multi-tenancy/credentials/server/kek-loader.ts +37 -37
- package/src/auth/multi-tenancy/index.ts +26 -26
- package/src/auth/multi-tenancy/invitations/api-schemas.ts +104 -104
- package/src/auth/multi-tenancy/memberships/api-schemas.ts +143 -143
- package/src/auth/multi-tenancy/memberships/index.ts +26 -26
- package/src/auth/multi-tenancy/memberships/membership.ts +130 -130
- package/src/auth/multi-tenancy/organizations/__tests__/api-schemas.test.ts +194 -194
- package/src/auth/multi-tenancy/organizations/api-schemas.ts +136 -136
- package/src/auth/multi-tenancy/permissions.test.ts +42 -42
- package/src/auth/multi-tenancy/permissions.ts +123 -123
- package/src/auth/multi-tenancy/role-management/api-schemas.ts +78 -78
- package/src/auth/multi-tenancy/role-management/index.ts +16 -16
- package/src/auth/multi-tenancy/theme-presets.ts +45 -45
- package/src/auth/multi-tenancy/types.ts +57 -57
- package/src/auth/multi-tenancy/users/api-schemas.ts +165 -165
- package/src/business/README.md +2 -2
- package/src/business/acquisition/activity-events.test.ts +250 -250
- package/src/business/acquisition/activity-events.ts +93 -93
- package/src/business/acquisition/api-schemas.test.ts +1883 -1843
- package/src/business/acquisition/api-schemas.ts +1493 -1500
- package/src/business/acquisition/build-templates.test.ts +240 -240
- package/src/business/acquisition/build-templates.ts +83 -41
- package/src/business/acquisition/crm-next-action.test.ts +262 -262
- package/src/business/acquisition/crm-next-action.ts +220 -220
- package/src/business/acquisition/crm-priority.test.ts +216 -216
- package/src/business/acquisition/crm-priority.ts +349 -349
- package/src/business/acquisition/crm-state-actions.test.ts +153 -151
- package/src/business/acquisition/deal-ownership.test.ts +351 -351
- package/src/business/acquisition/deal-ownership.ts +120 -120
- package/src/business/acquisition/derive-actions.test.ts +129 -104
- package/src/business/acquisition/derive-actions.ts +74 -84
- package/src/business/acquisition/index.ts +171 -170
- package/src/business/acquisition/ontology-validation.ts +309 -0
- package/src/business/acquisition/stateful.ts +30 -30
- package/src/business/acquisition/types.ts +396 -392
- package/src/business/clients/api-schemas.test.ts +115 -115
- package/src/business/clients/api-schemas.ts +158 -158
- package/src/business/clients/index.ts +1 -1
- package/src/business/crm/api-schemas.ts +40 -40
- package/src/business/crm/index.ts +1 -1
- package/src/business/deals/api-schemas.ts +87 -87
- package/src/business/deals/index.ts +1 -1
- package/src/business/index.ts +5 -5
- package/src/business/projects/types.ts +144 -144
- package/src/commands/queue/types/task.ts +15 -15
- package/src/execution/core/runner-types.ts +61 -61
- package/src/execution/core/sse-executions.ts +7 -7
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -10
- package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -16
- package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -4
- package/src/execution/engine/agent/core/types.ts +25 -25
- package/src/execution/engine/agent/index.ts +6 -6
- package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -24
- package/src/execution/engine/index.ts +443 -443
- package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +298 -298
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.test.ts +55 -55
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +107 -107
- package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.test.ts +48 -48
- package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.ts +99 -99
- package/src/execution/engine/tools/integration/server/adapters/apollo/index.ts +1 -1
- package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +363 -363
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.test.ts +162 -162
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.test.ts +316 -316
- package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.test.ts +18 -18
- package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.ts +194 -194
- package/src/execution/engine/tools/integration/server/adapters/clickup/index.ts +7 -7
- package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +204 -204
- package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +105 -105
- package/src/execution/engine/tools/integration/server/adapters/google-calendar/google-calendar-adapter.ts +428 -428
- package/src/execution/engine/tools/integration/server/adapters/google-calendar/index.ts +2 -2
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/__tests__/google-sheets.integration.test.ts +261 -261
- package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1474 -1474
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +103 -103
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.test.ts +88 -88
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +141 -141
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +76 -76
- package/src/execution/engine/tools/integration/server/adapters/signature-api/signature-api-tools.ts +182 -182
- package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +310 -310
- package/src/execution/engine/tools/integration/service.test.ts +239 -239
- package/src/execution/engine/tools/integration/service.ts +172 -172
- package/src/execution/engine/tools/integration/tool.ts +255 -255
- package/src/execution/engine/tools/lead-service-types.ts +1005 -1005
- package/src/execution/engine/tools/messages.ts +43 -43
- package/src/execution/engine/tools/platform/acquisition/company-tools.ts +7 -7
- package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +6 -6
- package/src/execution/engine/tools/platform/acquisition/list-tools.ts +6 -6
- package/src/execution/engine/tools/platform/acquisition/types.ts +280 -280
- package/src/execution/engine/tools/platform/email/types.ts +97 -97
- package/src/execution/engine/tools/registry.ts +704 -704
- package/src/execution/engine/tools/tool-maps.ts +831 -831
- package/src/execution/engine/tools/types.ts +234 -234
- package/src/execution/engine/workflow/types.ts +202 -202
- package/src/execution/external/__tests__/api-schemas.test.ts +127 -127
- package/src/execution/external/api-schemas.ts +40 -40
- package/src/execution/external/index.ts +1 -1
- package/src/index.ts +18 -18
- package/src/integrations/credentials/__tests__/api-schemas.test.ts +420 -420
- package/src/integrations/credentials/api-schemas.ts +146 -146
- package/src/integrations/credentials/schemas.ts +200 -200
- package/src/integrations/oauth/__tests__/provider-registry.test.ts +7 -7
- package/src/integrations/oauth/provider-registry.ts +74 -74
- package/src/integrations/oauth/server/credentials.ts +43 -43
- package/src/integrations/webhook-endpoints/__tests__/api-schemas.test.ts +327 -327
- package/src/integrations/webhook-endpoints/api-schemas.ts +103 -103
- package/src/integrations/webhook-endpoints/types.ts +58 -58
- package/src/knowledge/README.md +33 -32
- package/src/knowledge/__tests__/queries.test.ts +633 -541
- package/src/knowledge/format.ts +100 -99
- package/src/knowledge/index.ts +5 -5
- package/src/knowledge/published.ts +5 -5
- package/src/knowledge/queries.ts +274 -222
- package/src/operations/activities/api-schemas.ts +80 -80
- package/src/operations/activities/types.ts +64 -64
- package/src/organization-model/README.md +149 -109
- package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
- package/src/organization-model/__tests__/defaults.test.ts +168 -194
- package/src/organization-model/__tests__/domains/actions.test.ts +78 -0
- package/src/organization-model/__tests__/domains/customers.test.ts +48 -44
- package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
- package/src/organization-model/__tests__/domains/goals.test.ts +110 -96
- package/src/organization-model/__tests__/domains/identity.test.ts +4 -3
- package/src/organization-model/__tests__/domains/navigation.test.ts +222 -166
- package/src/organization-model/__tests__/domains/offerings.test.ts +83 -88
- package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
- package/src/organization-model/__tests__/domains/resource-mappings.test.ts +30 -30
- package/src/organization-model/__tests__/domains/resources.test.ts +396 -175
- package/src/organization-model/__tests__/domains/roles.test.ts +463 -402
- package/src/organization-model/__tests__/domains/statuses.test.ts +13 -10
- package/src/organization-model/__tests__/domains/systems.test.ts +209 -193
- package/src/organization-model/__tests__/flatten-additive-merge.test.ts +362 -0
- package/src/organization-model/__tests__/foundation.test.ts +47 -75
- package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
- package/src/organization-model/__tests__/graph.test.ts +1336 -149
- package/src/organization-model/__tests__/icons.test.ts +10 -1
- package/src/organization-model/__tests__/knowledge.test.ts +418 -61
- package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
- package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +103 -94
- package/src/organization-model/__tests__/recursive-system-schema.test.ts +549 -0
- package/src/organization-model/__tests__/resolve.test.ts +303 -42
- package/src/organization-model/__tests__/schema.test.ts +863 -153
- package/src/organization-model/__tests__/surface-projection.test.ts +284 -174
- package/src/organization-model/catalogs/lead-gen.ts +144 -0
- package/src/organization-model/content-kinds/config.ts +36 -0
- package/src/organization-model/content-kinds/index.ts +78 -0
- package/src/organization-model/content-kinds/pipeline.ts +68 -0
- package/src/organization-model/content-kinds/registry.ts +44 -0
- package/src/organization-model/content-kinds/status.ts +71 -0
- package/src/organization-model/content-kinds/template.ts +83 -0
- package/src/organization-model/content-kinds/types.ts +117 -0
- package/src/organization-model/contracts.ts +27 -17
- package/src/organization-model/defaults.ts +489 -107
- package/src/organization-model/domains/actions.ts +333 -0
- package/src/organization-model/domains/customers.ts +10 -7
- package/src/organization-model/domains/entities.ts +144 -0
- package/src/organization-model/domains/goals.ts +9 -6
- package/src/organization-model/domains/knowledge.ts +128 -54
- package/src/organization-model/domains/navigation.ts +139 -416
- package/src/organization-model/domains/offerings.ts +15 -10
- package/src/organization-model/domains/policies.ts +102 -0
- package/src/organization-model/domains/projects.ts +6 -40
- package/src/organization-model/domains/prospecting.ts +395 -514
- package/src/organization-model/domains/resources.ts +173 -81
- package/src/organization-model/domains/roles.ts +96 -93
- package/src/organization-model/domains/sales.test.ts +218 -218
- package/src/organization-model/domains/sales.ts +380 -589
- package/src/organization-model/domains/shared.ts +8 -8
- package/src/organization-model/domains/statuses.ts +298 -89
- package/src/organization-model/domains/systems.ts +240 -38
- package/src/organization-model/foundation.ts +35 -48
- package/src/organization-model/graph/build.ts +1035 -279
- package/src/organization-model/graph/index.ts +4 -4
- package/src/organization-model/graph/link.ts +10 -10
- package/src/organization-model/graph/schema.ts +77 -56
- package/src/organization-model/graph/types.ts +75 -56
- package/src/organization-model/helpers.ts +312 -59
- package/src/organization-model/icons.ts +78 -66
- package/src/organization-model/index.ts +129 -16
- package/src/organization-model/migration-helpers.ts +252 -0
- package/src/organization-model/ontology.ts +661 -0
- package/src/organization-model/organization-graph.mdx +110 -89
- package/src/organization-model/organization-model.mdx +226 -171
- package/src/organization-model/published.ts +295 -139
- package/src/organization-model/resolve.ts +139 -21
- package/src/organization-model/schema.ts +841 -301
- package/src/organization-model/surface-projection.ts +212 -218
- package/src/organization-model/types.ts +181 -90
- package/src/platform/api/types.ts +38 -38
- package/src/platform/constants/versions.ts +3 -3
- package/src/platform/index.ts +23 -23
- package/src/platform/registry/__tests__/command-view.test.ts +5 -7
- package/src/platform/registry/__tests__/resource-link.test.ts +35 -30
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +17 -32
- package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
- package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2051
- package/src/platform/registry/__tests__/validation.test.ts +1347 -1343
- package/src/platform/registry/command-view.ts +10 -10
- package/src/platform/registry/index.ts +103 -103
- package/src/platform/registry/resource-link.ts +32 -32
- package/src/platform/registry/resource-registry.ts +890 -878
- package/src/platform/registry/serialization.ts +295 -295
- package/src/platform/registry/serialized-types.ts +166 -166
- package/src/platform/registry/stats-types.ts +68 -68
- package/src/platform/registry/types.ts +425 -425
- package/src/platform/registry/validation.ts +745 -743
- package/src/platform/utils/__tests__/validation.test.ts +1084 -1084
- package/src/platform/utils/validation.ts +425 -425
- package/src/projects/api-schemas.test.ts +39 -39
- package/src/projects/api-schemas.ts +291 -291
- package/src/reference/_generated/contracts.md +2389 -2121
- package/src/reference/glossary.md +76 -76
- package/src/scaffold-registry/__tests__/index.test.ts +206 -206
- package/src/scaffold-registry/__tests__/schema.test.ts +166 -166
- package/src/scaffold-registry/index.ts +392 -392
- package/src/scaffold-registry/schema.ts +243 -243
- package/src/server.ts +289 -289
- package/src/supabase/database.types.ts +3153 -3093
- package/src/test-utils/README.md +37 -37
- package/src/test-utils/entities.ts +108 -108
- package/src/test-utils/fixtures/memberships.ts +82 -82
- package/src/test-utils/index.ts +12 -12
- package/src/test-utils/organization-model.ts +65 -65
- package/src/test-utils/published.ts +6 -6
- package/src/test-utils/rls/RLSTestContext.ts +588 -588
- package/src/test-utils/test-utils.test.ts +44 -49
- package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
- package/src/organization-model/domains/features.ts +0 -31
- package/src/organization-model/domains/operations.ts +0 -85
|
@@ -15,19 +15,20 @@ describe('ProductSchema — positive parse', () => {
|
|
|
15
15
|
it('accepts a fully-populated product', () => {
|
|
16
16
|
const result = ProductSchema.safeParse({
|
|
17
17
|
id: 'product-starter-plan',
|
|
18
|
+
order: 10,
|
|
18
19
|
name: 'Starter Plan',
|
|
19
20
|
description: 'Full-service automation for small teams.',
|
|
20
21
|
pricingModel: 'subscription',
|
|
21
22
|
price: 299,
|
|
22
23
|
currency: 'USD',
|
|
23
24
|
targetSegmentIds: ['seg-smb'],
|
|
24
|
-
deliveryFeatureId: 'crm'
|
|
25
|
+
deliveryFeatureId: 'sales.crm'
|
|
25
26
|
})
|
|
26
27
|
expect(result.success).toBe(true)
|
|
27
28
|
})
|
|
28
29
|
|
|
29
|
-
it('accepts a minimal product — only id required', () => {
|
|
30
|
-
const result = ProductSchema.safeParse({ id: 'product-minimal' })
|
|
30
|
+
it('accepts a minimal product — only id and order required', () => {
|
|
31
|
+
const result = ProductSchema.safeParse({ id: 'product-minimal', order: 10 })
|
|
31
32
|
expect(result.success).toBe(true)
|
|
32
33
|
if (result.success) {
|
|
33
34
|
expect(result.data.id).toBe('product-minimal')
|
|
@@ -44,6 +45,7 @@ describe('ProductSchema — positive parse', () => {
|
|
|
44
45
|
it('trims whitespace from id and name', () => {
|
|
45
46
|
const result = ProductSchema.safeParse({
|
|
46
47
|
id: ' product-trim ',
|
|
48
|
+
order: 10,
|
|
47
49
|
name: ' Trimmed Name '
|
|
48
50
|
})
|
|
49
51
|
expect(result.success).toBe(true)
|
|
@@ -56,6 +58,7 @@ describe('ProductSchema — positive parse', () => {
|
|
|
56
58
|
it('accepts price of 0 (free tier)', () => {
|
|
57
59
|
const result = ProductSchema.safeParse({
|
|
58
60
|
id: 'product-free',
|
|
61
|
+
order: 10,
|
|
59
62
|
pricingModel: 'subscription',
|
|
60
63
|
price: 0
|
|
61
64
|
})
|
|
@@ -68,7 +71,7 @@ describe('ProductSchema — positive parse', () => {
|
|
|
68
71
|
it('accepts all four pricing model values', () => {
|
|
69
72
|
const models = ['one-time', 'subscription', 'usage-based', 'custom'] as const
|
|
70
73
|
for (const pricingModel of models) {
|
|
71
|
-
const result = ProductSchema.safeParse({ id: `product-${pricingModel}`, pricingModel })
|
|
74
|
+
const result = ProductSchema.safeParse({ id: `product-${pricingModel}`, order: 10, pricingModel })
|
|
72
75
|
expect(result.success).toBe(true)
|
|
73
76
|
}
|
|
74
77
|
})
|
|
@@ -80,7 +83,7 @@ describe('ProductSchema — positive parse', () => {
|
|
|
80
83
|
|
|
81
84
|
describe('ProductSchema — default values', () => {
|
|
82
85
|
it('pricingModel defaults to "custom"', () => {
|
|
83
|
-
const result = ProductSchema.safeParse({ id: 'product-defaults' })
|
|
86
|
+
const result = ProductSchema.safeParse({ id: 'product-defaults', order: 10 })
|
|
84
87
|
expect(result.success).toBe(true)
|
|
85
88
|
if (result.success) {
|
|
86
89
|
expect(result.data.pricingModel).toBe('custom')
|
|
@@ -88,7 +91,7 @@ describe('ProductSchema — default values', () => {
|
|
|
88
91
|
})
|
|
89
92
|
|
|
90
93
|
it('price defaults to 0', () => {
|
|
91
|
-
const result = ProductSchema.safeParse({ id: 'product-defaults' })
|
|
94
|
+
const result = ProductSchema.safeParse({ id: 'product-defaults', order: 10 })
|
|
92
95
|
expect(result.success).toBe(true)
|
|
93
96
|
if (result.success) {
|
|
94
97
|
expect(result.data.price).toBe(0)
|
|
@@ -96,7 +99,7 @@ describe('ProductSchema — default values', () => {
|
|
|
96
99
|
})
|
|
97
100
|
|
|
98
101
|
it('currency defaults to "USD"', () => {
|
|
99
|
-
const result = ProductSchema.safeParse({ id: 'product-defaults' })
|
|
102
|
+
const result = ProductSchema.safeParse({ id: 'product-defaults', order: 10 })
|
|
100
103
|
expect(result.success).toBe(true)
|
|
101
104
|
if (result.success) {
|
|
102
105
|
expect(result.data.currency).toBe('USD')
|
|
@@ -104,7 +107,7 @@ describe('ProductSchema — default values', () => {
|
|
|
104
107
|
})
|
|
105
108
|
|
|
106
109
|
it('targetSegmentIds defaults to empty array', () => {
|
|
107
|
-
const result = ProductSchema.safeParse({ id: 'product-defaults' })
|
|
110
|
+
const result = ProductSchema.safeParse({ id: 'product-defaults', order: 10 })
|
|
108
111
|
expect(result.success).toBe(true)
|
|
109
112
|
if (result.success) {
|
|
110
113
|
expect(result.data.targetSegmentIds).toEqual([])
|
|
@@ -112,7 +115,7 @@ describe('ProductSchema — default values', () => {
|
|
|
112
115
|
})
|
|
113
116
|
|
|
114
117
|
it('deliveryFeatureId defaults to undefined (field is optional)', () => {
|
|
115
|
-
const result = ProductSchema.safeParse({ id: 'product-defaults' })
|
|
118
|
+
const result = ProductSchema.safeParse({ id: 'product-defaults', order: 10 })
|
|
116
119
|
expect(result.success).toBe(true)
|
|
117
120
|
if (result.success) {
|
|
118
121
|
expect(result.data.deliveryFeatureId).toBeUndefined()
|
|
@@ -126,37 +129,37 @@ describe('ProductSchema — default values', () => {
|
|
|
126
129
|
|
|
127
130
|
describe('ProductSchema — negative parse', () => {
|
|
128
131
|
it('rejects missing id', () => {
|
|
129
|
-
const result = ProductSchema.safeParse({ name: 'No ID Product' })
|
|
132
|
+
const result = ProductSchema.safeParse({ order: 10, name: 'No ID Product' })
|
|
130
133
|
expect(result.success).toBe(false)
|
|
131
134
|
})
|
|
132
135
|
|
|
133
136
|
it('rejects empty string id', () => {
|
|
134
|
-
const result = ProductSchema.safeParse({ id: '' })
|
|
137
|
+
const result = ProductSchema.safeParse({ id: '', order: 10 })
|
|
135
138
|
expect(result.success).toBe(false)
|
|
136
139
|
})
|
|
137
140
|
|
|
138
141
|
it('rejects whitespace-only id (trims to empty string)', () => {
|
|
139
|
-
const result = ProductSchema.safeParse({ id: ' ' })
|
|
142
|
+
const result = ProductSchema.safeParse({ id: ' ', order: 10 })
|
|
140
143
|
expect(result.success).toBe(false)
|
|
141
144
|
})
|
|
142
145
|
|
|
143
146
|
it('rejects an unknown pricingModel value', () => {
|
|
144
|
-
const result = ProductSchema.safeParse({ id: 'product-bad-model', pricingModel: 'freemium' })
|
|
147
|
+
const result = ProductSchema.safeParse({ id: 'product-bad-model', order: 10, pricingModel: 'freemium' })
|
|
145
148
|
expect(result.success).toBe(false)
|
|
146
149
|
})
|
|
147
150
|
|
|
148
151
|
it('rejects price below 0', () => {
|
|
149
|
-
const result = ProductSchema.safeParse({ id: 'product-negative-price', price: -1 })
|
|
152
|
+
const result = ProductSchema.safeParse({ id: 'product-negative-price', order: 10, price: -1 })
|
|
150
153
|
expect(result.success).toBe(false)
|
|
151
154
|
})
|
|
152
155
|
|
|
153
156
|
it('rejects price as a string', () => {
|
|
154
|
-
const result = ProductSchema.safeParse({ id: 'product-string-price', price: '299' })
|
|
157
|
+
const result = ProductSchema.safeParse({ id: 'product-string-price', order: 10, price: '299' })
|
|
155
158
|
expect(result.success).toBe(false)
|
|
156
159
|
})
|
|
157
160
|
|
|
158
161
|
it('rejects targetSegmentIds as a non-array value', () => {
|
|
159
|
-
const result = ProductSchema.safeParse({ id: 'product-bad-segments', targetSegmentIds: 'seg-a' })
|
|
162
|
+
const result = ProductSchema.safeParse({ id: 'product-bad-segments', order: 10, targetSegmentIds: 'seg-a' })
|
|
160
163
|
expect(result.success).toBe(false)
|
|
161
164
|
})
|
|
162
165
|
})
|
|
@@ -189,34 +192,34 @@ describe('PricingModelSchema — enum', () => {
|
|
|
189
192
|
// ---------------------------------------------------------------------------
|
|
190
193
|
|
|
191
194
|
describe('OfferingsDomainSchema — structural', () => {
|
|
192
|
-
it('accepts an empty products
|
|
193
|
-
const result = OfferingsDomainSchema.safeParse({
|
|
195
|
+
it('accepts an empty products record', () => {
|
|
196
|
+
const result = OfferingsDomainSchema.safeParse({})
|
|
194
197
|
expect(result.success).toBe(true)
|
|
195
198
|
})
|
|
196
199
|
|
|
197
|
-
it('defaults products to empty
|
|
200
|
+
it('defaults products to empty record when omitted', () => {
|
|
198
201
|
const result = OfferingsDomainSchema.safeParse({})
|
|
199
202
|
expect(result.success).toBe(true)
|
|
200
203
|
if (result.success) {
|
|
201
|
-
expect(result.data
|
|
204
|
+
expect(result.data).toEqual({})
|
|
202
205
|
}
|
|
203
206
|
})
|
|
204
207
|
|
|
205
208
|
it('accepts multiple valid products', () => {
|
|
206
209
|
const result = OfferingsDomainSchema.safeParse({
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
{ id: 'product-b', name: 'Product B', pricingModel: 'one-time', price: 999 }
|
|
210
|
-
]
|
|
210
|
+
'product-a': { id: 'product-a', order: 10, name: 'Product A', pricingModel: 'subscription' },
|
|
211
|
+
'product-b': { id: 'product-b', order: 20, name: 'Product B', pricingModel: 'one-time', price: 999 }
|
|
211
212
|
})
|
|
212
213
|
expect(result.success).toBe(true)
|
|
213
214
|
if (result.success) {
|
|
214
|
-
expect(result.data
|
|
215
|
+
expect(Object.keys(result.data)).toHaveLength(2)
|
|
215
216
|
}
|
|
216
217
|
})
|
|
217
218
|
|
|
218
|
-
it('rejects
|
|
219
|
-
const result = OfferingsDomainSchema.safeParse({
|
|
219
|
+
it('rejects a record where entry id does not match map key', () => {
|
|
220
|
+
const result = OfferingsDomainSchema.safeParse({
|
|
221
|
+
'product-a': { id: 'product-b', order: 10, name: 'Mismatched' }
|
|
222
|
+
})
|
|
220
223
|
expect(result.success).toBe(false)
|
|
221
224
|
})
|
|
222
225
|
|
|
@@ -238,17 +241,16 @@ describe('resolveOrganizationModel — offerings cross-ref (targetSegmentIds)',
|
|
|
238
241
|
expect(() =>
|
|
239
242
|
resolveOrganizationModel({
|
|
240
243
|
customers: {
|
|
241
|
-
|
|
244
|
+
'seg-agencies': { id: 'seg-agencies', order: 10, name: 'SMB Agencies' }
|
|
242
245
|
},
|
|
243
246
|
offerings: {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
]
|
|
247
|
+
'product-starter': {
|
|
248
|
+
id: 'product-starter',
|
|
249
|
+
order: 10,
|
|
250
|
+
name: 'Starter Plan',
|
|
251
|
+
pricingModel: 'subscription',
|
|
252
|
+
targetSegmentIds: ['seg-agencies']
|
|
253
|
+
}
|
|
252
254
|
}
|
|
253
255
|
})
|
|
254
256
|
).not.toThrow()
|
|
@@ -257,14 +259,13 @@ describe('resolveOrganizationModel — offerings cross-ref (targetSegmentIds)',
|
|
|
257
259
|
it('throws when targetSegmentIds references a non-existent segment', () => {
|
|
258
260
|
expect(() =>
|
|
259
261
|
resolveOrganizationModel({
|
|
260
|
-
customers: {
|
|
262
|
+
customers: {},
|
|
261
263
|
offerings: {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
]
|
|
264
|
+
'product-bad-ref': {
|
|
265
|
+
id: 'product-bad-ref',
|
|
266
|
+
order: 10,
|
|
267
|
+
targetSegmentIds: ['nonexistent-segment']
|
|
268
|
+
}
|
|
268
269
|
}
|
|
269
270
|
})
|
|
270
271
|
).toThrow()
|
|
@@ -274,14 +275,13 @@ describe('resolveOrganizationModel — offerings cross-ref (targetSegmentIds)',
|
|
|
274
275
|
let errorMessage = ''
|
|
275
276
|
try {
|
|
276
277
|
resolveOrganizationModel({
|
|
277
|
-
customers: {
|
|
278
|
+
customers: {},
|
|
278
279
|
offerings: {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
]
|
|
280
|
+
'product-path-check': {
|
|
281
|
+
id: 'product-path-check',
|
|
282
|
+
order: 10,
|
|
283
|
+
targetSegmentIds: ['ghost-segment']
|
|
284
|
+
}
|
|
285
285
|
}
|
|
286
286
|
})
|
|
287
287
|
} catch (e) {
|
|
@@ -294,7 +294,7 @@ describe('resolveOrganizationModel — offerings cross-ref (targetSegmentIds)',
|
|
|
294
294
|
expect(() =>
|
|
295
295
|
resolveOrganizationModel({
|
|
296
296
|
offerings: {
|
|
297
|
-
|
|
297
|
+
'product-no-targets': { id: 'product-no-targets', order: 10, targetSegmentIds: [] }
|
|
298
298
|
}
|
|
299
299
|
})
|
|
300
300
|
).not.toThrow()
|
|
@@ -304,16 +304,12 @@ describe('resolveOrganizationModel — offerings cross-ref (targetSegmentIds)',
|
|
|
304
304
|
expect(() =>
|
|
305
305
|
resolveOrganizationModel({
|
|
306
306
|
customers: {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
{ id: 'seg-b', name: 'Segment B' }
|
|
310
|
-
]
|
|
307
|
+
'seg-a': { id: 'seg-a', order: 10, name: 'Segment A' },
|
|
308
|
+
'seg-b': { id: 'seg-b', order: 20, name: 'Segment B' }
|
|
311
309
|
},
|
|
312
310
|
offerings: {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
{ id: 'product-2', targetSegmentIds: ['seg-a', 'seg-b'] }
|
|
316
|
-
]
|
|
311
|
+
'product-1': { id: 'product-1', order: 10, targetSegmentIds: ['seg-a'] },
|
|
312
|
+
'product-2': { id: 'product-2', order: 20, targetSegmentIds: ['seg-a', 'seg-b'] }
|
|
317
313
|
}
|
|
318
314
|
})
|
|
319
315
|
).not.toThrow()
|
|
@@ -325,48 +321,45 @@ describe('resolveOrganizationModel — offerings cross-ref (targetSegmentIds)',
|
|
|
325
321
|
// ---------------------------------------------------------------------------
|
|
326
322
|
|
|
327
323
|
describe('resolveOrganizationModel — offerings cross-ref (deliveryFeatureId)', () => {
|
|
328
|
-
it('passes when deliveryFeatureId references a declared
|
|
329
|
-
// 'crm' is in DEFAULT_ORGANIZATION_MODEL.
|
|
324
|
+
it('passes when deliveryFeatureId references a declared system', () => {
|
|
325
|
+
// 'sales.crm' is in DEFAULT_ORGANIZATION_MODEL.systems
|
|
330
326
|
expect(() =>
|
|
331
327
|
resolveOrganizationModel({
|
|
332
328
|
offerings: {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
]
|
|
329
|
+
'product-with-delivery': {
|
|
330
|
+
id: 'product-with-delivery',
|
|
331
|
+
order: 10,
|
|
332
|
+
deliveryFeatureId: 'sales.crm'
|
|
333
|
+
}
|
|
339
334
|
}
|
|
340
335
|
})
|
|
341
336
|
).not.toThrow()
|
|
342
337
|
})
|
|
343
338
|
|
|
344
|
-
it('throws when deliveryFeatureId references a non-existent
|
|
339
|
+
it('throws when deliveryFeatureId references a non-existent system', () => {
|
|
345
340
|
expect(() =>
|
|
346
341
|
resolveOrganizationModel({
|
|
347
342
|
offerings: {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
]
|
|
343
|
+
'product-bad-delivery': {
|
|
344
|
+
id: 'product-bad-delivery',
|
|
345
|
+
order: 10,
|
|
346
|
+
deliveryFeatureId: 'nonexistent-feature'
|
|
347
|
+
}
|
|
354
348
|
}
|
|
355
349
|
})
|
|
356
350
|
).toThrow()
|
|
357
351
|
})
|
|
358
352
|
|
|
359
|
-
it('throws with a message referencing the unknown
|
|
353
|
+
it('throws with a message referencing the unknown system id', () => {
|
|
360
354
|
let errorMessage = ''
|
|
361
355
|
try {
|
|
362
356
|
resolveOrganizationModel({
|
|
363
357
|
offerings: {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
]
|
|
358
|
+
'product-delivery-path': {
|
|
359
|
+
id: 'product-delivery-path',
|
|
360
|
+
order: 10,
|
|
361
|
+
deliveryFeatureId: 'ghost-feature'
|
|
362
|
+
}
|
|
370
363
|
}
|
|
371
364
|
})
|
|
372
365
|
} catch (e) {
|
|
@@ -379,7 +372,7 @@ describe('resolveOrganizationModel — offerings cross-ref (deliveryFeatureId)',
|
|
|
379
372
|
expect(() =>
|
|
380
373
|
resolveOrganizationModel({
|
|
381
374
|
offerings: {
|
|
382
|
-
|
|
375
|
+
'product-no-delivery': { id: 'product-no-delivery', order: 10 }
|
|
383
376
|
}
|
|
384
377
|
})
|
|
385
378
|
).not.toThrow()
|
|
@@ -392,28 +385,30 @@ describe('resolveOrganizationModel — offerings cross-ref (deliveryFeatureId)',
|
|
|
392
385
|
|
|
393
386
|
describe('resolveOrganizationModel — offerings domain integration', () => {
|
|
394
387
|
it('merges partial offerings override and preserves empty products default', () => {
|
|
395
|
-
const model = resolveOrganizationModel({ offerings: {
|
|
396
|
-
expect(model.offerings
|
|
388
|
+
const model = resolveOrganizationModel({ offerings: {} })
|
|
389
|
+
expect(Object.keys(model.offerings)).toHaveLength(0)
|
|
397
390
|
})
|
|
398
391
|
|
|
399
392
|
it('omitting offerings key entirely resolves to default empty products', () => {
|
|
400
393
|
const model = resolveOrganizationModel({})
|
|
401
394
|
expect(model.offerings).toBeDefined()
|
|
402
|
-
expect(model.offerings
|
|
395
|
+
expect(Object.keys(model.offerings)).toHaveLength(0)
|
|
403
396
|
})
|
|
404
397
|
|
|
405
398
|
it('does not bleed offerings changes into other top-level domains', () => {
|
|
406
399
|
const model = resolveOrganizationModel({
|
|
407
400
|
customers: {
|
|
408
|
-
|
|
401
|
+
'seg-isolation': { id: 'seg-isolation', order: 10 }
|
|
409
402
|
},
|
|
410
403
|
offerings: {
|
|
411
|
-
|
|
404
|
+
'product-isolation': { id: 'product-isolation', order: 10, targetSegmentIds: ['seg-isolation'] }
|
|
412
405
|
}
|
|
413
406
|
})
|
|
414
407
|
expect(model.identity).toBeDefined()
|
|
415
408
|
expect(model.customers).toBeDefined()
|
|
416
|
-
expect(model.
|
|
409
|
+
expect(model.systems).toBeDefined()
|
|
410
|
+
// Phase 4 (D8): model.navigation removed from top-level OM.
|
|
417
411
|
expect(model.navigation).toBeDefined()
|
|
412
|
+
expect(model.knowledge).toBeDefined()
|
|
418
413
|
})
|
|
419
414
|
})
|