@contractspec/example.saas-boilerplate 3.7.6 → 3.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/AGENTS.md +50 -27
- package/README.md +64 -144
- package/dist/billing/billing.event.js +1 -1
- package/dist/billing/index.d.ts +6 -6
- package/dist/billing/index.js +1 -1
- package/dist/browser/billing/billing.event.js +1 -1
- package/dist/browser/billing/index.js +1 -1
- package/dist/browser/index.js +931 -932
- package/dist/browser/project/index.js +209 -209
- package/dist/browser/project/project.event.js +1 -1
- package/dist/browser/ui/SaasDashboard.js +45 -45
- package/dist/browser/ui/SaasProjectList.js +7 -7
- package/dist/browser/ui/SaasSettingsPanel.js +12 -12
- package/dist/browser/ui/hooks/index.js +2 -2
- package/dist/browser/ui/hooks/useProjectList.js +1 -1
- package/dist/browser/ui/hooks/useProjectMutations.js +1 -1
- package/dist/browser/ui/index.js +483 -484
- package/dist/browser/ui/modals/CreateProjectModal.js +10 -10
- package/dist/browser/ui/modals/ProjectActionsModal.js +13 -13
- package/dist/browser/ui/modals/index.js +23 -23
- package/dist/browser/ui/renderers/index.js +112 -112
- package/dist/browser/ui/renderers/project-list.renderer.js +7 -7
- package/dist/handlers/index.d.ts +2 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +931 -932
- package/dist/node/billing/billing.event.js +1 -1
- package/dist/node/billing/index.js +1 -1
- package/dist/node/index.js +931 -932
- package/dist/node/project/index.js +209 -209
- package/dist/node/project/project.event.js +1 -1
- package/dist/node/ui/SaasDashboard.js +45 -45
- package/dist/node/ui/SaasProjectList.js +7 -7
- package/dist/node/ui/SaasSettingsPanel.js +12 -12
- package/dist/node/ui/hooks/index.js +2 -2
- package/dist/node/ui/hooks/useProjectList.js +1 -1
- package/dist/node/ui/hooks/useProjectMutations.js +1 -1
- package/dist/node/ui/index.js +483 -484
- package/dist/node/ui/modals/CreateProjectModal.js +10 -10
- package/dist/node/ui/modals/ProjectActionsModal.js +13 -13
- package/dist/node/ui/modals/index.js +23 -23
- package/dist/node/ui/renderers/index.js +112 -112
- package/dist/node/ui/renderers/project-list.renderer.js +7 -7
- package/dist/presentations/index.d.ts +1 -1
- package/dist/project/index.d.ts +7 -7
- package/dist/project/index.js +209 -209
- package/dist/project/project.event.js +1 -1
- package/dist/settings/index.d.ts +1 -1
- package/dist/ui/SaasDashboard.js +45 -45
- package/dist/ui/SaasProjectList.js +7 -7
- package/dist/ui/SaasSettingsPanel.js +12 -12
- package/dist/ui/hooks/index.d.ts +2 -2
- package/dist/ui/hooks/index.js +2 -2
- package/dist/ui/hooks/useProjectList.d.ts +5 -0
- package/dist/ui/hooks/useProjectList.js +1 -1
- package/dist/ui/hooks/useProjectMutations.d.ts +8 -0
- package/dist/ui/hooks/useProjectMutations.js +1 -1
- package/dist/ui/index.d.ts +4 -4
- package/dist/ui/index.js +483 -484
- package/dist/ui/modals/CreateProjectModal.js +10 -10
- package/dist/ui/modals/ProjectActionsModal.js +13 -13
- package/dist/ui/modals/index.js +23 -23
- package/dist/ui/renderers/index.d.ts +1 -1
- package/dist/ui/renderers/index.js +112 -112
- package/dist/ui/renderers/project-list.renderer.d.ts +1 -1
- package/dist/ui/renderers/project-list.renderer.js +7 -7
- package/package.json +10 -10
- package/src/billing/billing.entity.ts +132 -132
- package/src/billing/billing.enum.ts +9 -9
- package/src/billing/billing.event.ts +71 -71
- package/src/billing/billing.handler.ts +87 -87
- package/src/billing/billing.operations.ts +158 -158
- package/src/billing/billing.presentation.ts +45 -45
- package/src/billing/billing.schema.ts +76 -76
- package/src/billing/index.ts +43 -48
- package/src/dashboard/dashboard.presentation.ts +45 -45
- package/src/dashboard/index.ts +2 -2
- package/src/docs/saas-boilerplate.docblock.ts +43 -43
- package/src/example.ts +32 -32
- package/src/handlers/index.ts +9 -9
- package/src/handlers/saas.handlers.ts +250 -249
- package/src/index.ts +40 -41
- package/src/presentations/index.ts +18 -20
- package/src/project/index.ts +45 -50
- package/src/project/project.entity.ts +68 -68
- package/src/project/project.enum.ts +8 -8
- package/src/project/project.event.ts +79 -79
- package/src/project/project.handler.ts +103 -103
- package/src/project/project.operations.ts +236 -236
- package/src/project/project.presentation.ts +46 -46
- package/src/project/project.schema.ts +90 -90
- package/src/saas-boilerplate.feature.ts +100 -100
- package/src/seeders/index.ts +20 -20
- package/src/settings/index.ts +2 -3
- package/src/settings/settings.entity.ts +65 -65
- package/src/settings/settings.enum.ts +4 -4
- package/src/shared/mock-data.ts +92 -92
- package/src/shared/overlay-types.ts +23 -23
- package/src/tests/operations.test-spec.ts +96 -96
- package/src/ui/SaasDashboard.tsx +270 -270
- package/src/ui/SaasProjectList.tsx +90 -90
- package/src/ui/SaasSettingsPanel.tsx +84 -84
- package/src/ui/hooks/index.ts +3 -3
- package/src/ui/hooks/useProjectList.ts +69 -68
- package/src/ui/hooks/useProjectMutations.ts +144 -143
- package/src/ui/index.ts +8 -12
- package/src/ui/modals/CreateProjectModal.tsx +154 -154
- package/src/ui/modals/ProjectActionsModal.tsx +321 -321
- package/src/ui/overlays/demo-overlays.ts +49 -49
- package/src/ui/renderers/index.ts +5 -4
- package/src/ui/renderers/project-list.markdown.ts +204 -204
- package/src/ui/renderers/project-list.renderer.tsx +14 -13
- package/tsconfig.json +7 -8
- package/tsdown.config.js +7 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractspec/example.saas-boilerplate",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.7",
|
|
4
4
|
"description": "SaaS Boilerplate - Users, Orgs, Projects, Billing, Settings",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -351,21 +351,21 @@
|
|
|
351
351
|
"dev": "contractspec-bun-build dev",
|
|
352
352
|
"clean": "rimraf dist .turbo",
|
|
353
353
|
"lint": "bun lint:fix",
|
|
354
|
-
"lint:fix": "
|
|
355
|
-
"lint:check": "
|
|
354
|
+
"lint:fix": "biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .",
|
|
355
|
+
"lint:check": "biome check .",
|
|
356
356
|
"test": "bun test --pass-with-no-tests",
|
|
357
357
|
"prebuild": "contractspec-bun-build prebuild",
|
|
358
358
|
"typecheck": "tsc --noEmit"
|
|
359
359
|
},
|
|
360
360
|
"dependencies": {
|
|
361
|
-
"@contractspec/lib.identity-rbac": "3.7.
|
|
362
|
-
"@contractspec/lib.jobs": "3.7.
|
|
363
|
-
"@contractspec/module.audit-trail": "3.7.
|
|
364
|
-
"@contractspec/module.notifications": "3.7.
|
|
365
|
-
"@contractspec/lib.contracts-spec": "
|
|
361
|
+
"@contractspec/lib.identity-rbac": "3.7.7",
|
|
362
|
+
"@contractspec/lib.jobs": "3.7.7",
|
|
363
|
+
"@contractspec/module.audit-trail": "3.7.7",
|
|
364
|
+
"@contractspec/module.notifications": "3.7.7",
|
|
365
|
+
"@contractspec/lib.contracts-spec": "4.0.0",
|
|
366
366
|
"@contractspec/lib.schema": "3.7.6",
|
|
367
|
-
"@contractspec/lib.example-shared-ui": "6.0.
|
|
368
|
-
"@contractspec/lib.design-system": "3.
|
|
367
|
+
"@contractspec/lib.example-shared-ui": "6.0.7",
|
|
368
|
+
"@contractspec/lib.design-system": "3.8.0",
|
|
369
369
|
"@contractspec/lib.runtime-sandbox": "2.7.6",
|
|
370
370
|
"react": "19.2.0",
|
|
371
371
|
"react-dom": "19.2.0"
|
|
@@ -1,158 +1,158 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
defineEntity,
|
|
3
|
+
defineEntityEnum,
|
|
4
|
+
field,
|
|
5
|
+
index,
|
|
6
6
|
} from '@contractspec/lib.schema';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Subscription status enum for entities.
|
|
10
10
|
*/
|
|
11
11
|
export const SubscriptionStatusEnum = defineEntityEnum({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
name: 'SubscriptionStatus',
|
|
13
|
+
values: ['TRIALING', 'ACTIVE', 'PAST_DUE', 'CANCELED', 'PAUSED'] as const,
|
|
14
|
+
schema: 'saas_app',
|
|
15
|
+
description: 'Status of a subscription.',
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Subscription entity - organization subscription info.
|
|
20
20
|
*/
|
|
21
21
|
export const SubscriptionEntity = defineEntity({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
22
|
+
name: 'Subscription',
|
|
23
|
+
description: 'Organization subscription/plan information.',
|
|
24
|
+
schema: 'saas_app',
|
|
25
|
+
map: 'subscription',
|
|
26
|
+
fields: {
|
|
27
|
+
id: field.id(),
|
|
28
|
+
organizationId: field.foreignKey({ isUnique: true }),
|
|
29
|
+
|
|
30
|
+
// Plan info
|
|
31
|
+
planId: field.string({ description: 'Plan identifier' }),
|
|
32
|
+
planName: field.string({ description: 'Plan display name' }),
|
|
33
|
+
|
|
34
|
+
// Status
|
|
35
|
+
status: field.enum('SubscriptionStatus'),
|
|
36
|
+
|
|
37
|
+
// Billing cycle
|
|
38
|
+
currentPeriodStart: field.dateTime(),
|
|
39
|
+
currentPeriodEnd: field.dateTime(),
|
|
40
|
+
|
|
41
|
+
// Trial
|
|
42
|
+
trialEndsAt: field.dateTime({ isOptional: true }),
|
|
43
|
+
|
|
44
|
+
// Cancellation
|
|
45
|
+
cancelAtPeriodEnd: field.boolean({ default: false }),
|
|
46
|
+
canceledAt: field.dateTime({ isOptional: true }),
|
|
47
|
+
|
|
48
|
+
// External reference
|
|
49
|
+
stripeSubscriptionId: field.string({ isOptional: true }),
|
|
50
|
+
stripeCustomerId: field.string({ isOptional: true }),
|
|
51
|
+
|
|
52
|
+
// Metadata
|
|
53
|
+
metadata: field.json({ isOptional: true }),
|
|
54
|
+
|
|
55
|
+
// Timestamps
|
|
56
|
+
createdAt: field.createdAt(),
|
|
57
|
+
updatedAt: field.updatedAt(),
|
|
58
|
+
},
|
|
59
|
+
enums: [SubscriptionStatusEnum],
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* BillingUsage entity - track feature usage.
|
|
64
64
|
*/
|
|
65
65
|
export const BillingUsageEntity = defineEntity({
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
66
|
+
name: 'BillingUsage',
|
|
67
|
+
description: 'Track usage of metered features.',
|
|
68
|
+
schema: 'saas_app',
|
|
69
|
+
map: 'billing_usage',
|
|
70
|
+
fields: {
|
|
71
|
+
id: field.id(),
|
|
72
|
+
organizationId: field.foreignKey(),
|
|
73
|
+
|
|
74
|
+
// Feature
|
|
75
|
+
feature: field.string({
|
|
76
|
+
description: 'Feature being tracked (e.g., "api_calls", "storage_gb")',
|
|
77
|
+
}),
|
|
78
|
+
|
|
79
|
+
// Usage
|
|
80
|
+
quantity: field.int({ description: 'Usage quantity' }),
|
|
81
|
+
unit: field.string({
|
|
82
|
+
isOptional: true,
|
|
83
|
+
description: 'Unit of measurement',
|
|
84
|
+
}),
|
|
85
|
+
|
|
86
|
+
// Period
|
|
87
|
+
billingPeriod: field.string({
|
|
88
|
+
description: 'Billing period (e.g., "2024-01")',
|
|
89
|
+
}),
|
|
90
|
+
|
|
91
|
+
// Aggregation
|
|
92
|
+
recordedAt: field.dateTime({ description: 'When usage was recorded' }),
|
|
93
|
+
|
|
94
|
+
// Source
|
|
95
|
+
sourceId: field.string({
|
|
96
|
+
isOptional: true,
|
|
97
|
+
description: 'Source of usage (e.g., request ID)',
|
|
98
|
+
}),
|
|
99
|
+
sourceType: field.string({ isOptional: true }),
|
|
100
|
+
|
|
101
|
+
// Metadata
|
|
102
|
+
metadata: field.json({ isOptional: true }),
|
|
103
|
+
},
|
|
104
|
+
indexes: [
|
|
105
|
+
index.on(['organizationId', 'feature', 'billingPeriod']),
|
|
106
|
+
index.on(['organizationId', 'recordedAt']),
|
|
107
|
+
],
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
111
|
* UsageLimit entity - feature usage limits per plan.
|
|
112
112
|
*/
|
|
113
113
|
export const UsageLimitEntity = defineEntity({
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
114
|
+
name: 'UsageLimit',
|
|
115
|
+
description: 'Usage limits per plan/organization.',
|
|
116
|
+
schema: 'saas_app',
|
|
117
|
+
map: 'usage_limit',
|
|
118
|
+
fields: {
|
|
119
|
+
id: field.id(),
|
|
120
|
+
|
|
121
|
+
// Scope
|
|
122
|
+
planId: field.string({
|
|
123
|
+
isOptional: true,
|
|
124
|
+
description: 'Plan this limit applies to',
|
|
125
|
+
}),
|
|
126
|
+
organizationId: field.string({
|
|
127
|
+
isOptional: true,
|
|
128
|
+
description: 'Org-specific override',
|
|
129
|
+
}),
|
|
130
|
+
|
|
131
|
+
// Limit
|
|
132
|
+
feature: field.string({ description: 'Feature being limited' }),
|
|
133
|
+
limit: field.int({ description: 'Maximum allowed usage' }),
|
|
134
|
+
resetPeriod: field.string({
|
|
135
|
+
default: '"monthly"',
|
|
136
|
+
description: 'When limit resets',
|
|
137
|
+
}),
|
|
138
|
+
|
|
139
|
+
// Soft/hard limit
|
|
140
|
+
isSoftLimit: field.boolean({
|
|
141
|
+
default: false,
|
|
142
|
+
description: 'Whether to warn vs block',
|
|
143
|
+
}),
|
|
144
|
+
overage: field.boolean({
|
|
145
|
+
default: false,
|
|
146
|
+
description: 'Whether overage is allowed',
|
|
147
|
+
}),
|
|
148
|
+
overageRate: field.float({
|
|
149
|
+
isOptional: true,
|
|
150
|
+
description: 'Cost per unit over limit',
|
|
151
|
+
}),
|
|
152
|
+
|
|
153
|
+
// Timestamps
|
|
154
|
+
createdAt: field.createdAt(),
|
|
155
|
+
updatedAt: field.updatedAt(),
|
|
156
|
+
},
|
|
157
|
+
indexes: [index.unique(['planId', 'feature'])],
|
|
158
158
|
});
|
|
@@ -5,19 +5,19 @@ import { defineEnum } from '@contractspec/lib.schema';
|
|
|
5
5
|
* Note: Entity enum is defined separately in billing.entity.ts
|
|
6
6
|
*/
|
|
7
7
|
export const SubscriptionStatusSchemaEnum = defineEnum('SubscriptionStatus', [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
'TRIALING',
|
|
9
|
+
'ACTIVE',
|
|
10
|
+
'PAST_DUE',
|
|
11
|
+
'CANCELED',
|
|
12
|
+
'PAUSED',
|
|
13
13
|
]);
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Feature access reason enum.
|
|
17
17
|
*/
|
|
18
18
|
export const FeatureAccessReasonEnum = defineEnum('FeatureAccessReason', [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
'included',
|
|
20
|
+
'limit_available',
|
|
21
|
+
'limit_reached',
|
|
22
|
+
'not_in_plan',
|
|
23
23
|
]);
|
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
import { ScalarTypeEnum, defineSchemaModel } from '@contractspec/lib.schema';
|
|
2
1
|
import { defineEvent } from '@contractspec/lib.contracts-spec';
|
|
2
|
+
import { defineSchemaModel, ScalarTypeEnum } from '@contractspec/lib.schema';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Payload when feature usage is recorded.
|
|
6
6
|
*/
|
|
7
7
|
const UsageRecordedPayload = defineSchemaModel({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
name: 'UsageRecordedPayload',
|
|
9
|
+
description: 'Payload when feature usage is recorded',
|
|
10
|
+
fields: {
|
|
11
|
+
organizationId: {
|
|
12
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
13
|
+
isOptional: false,
|
|
14
|
+
},
|
|
15
|
+
feature: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
16
|
+
quantity: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
17
|
+
billingPeriod: {
|
|
18
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
19
|
+
isOptional: false,
|
|
20
|
+
},
|
|
21
|
+
recordedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
22
|
+
},
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Payload when usage limit is reached.
|
|
27
27
|
*/
|
|
28
28
|
const UsageLimitReachedPayload = defineSchemaModel({
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
name: 'UsageLimitReachedPayload',
|
|
30
|
+
description: 'Payload when usage limit is reached',
|
|
31
|
+
fields: {
|
|
32
|
+
organizationId: {
|
|
33
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
34
|
+
isOptional: false,
|
|
35
|
+
},
|
|
36
|
+
feature: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
37
|
+
limit: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
38
|
+
currentUsage: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
39
|
+
reachedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
40
|
+
},
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Payload when subscription status changes.
|
|
45
45
|
*/
|
|
46
46
|
const SubscriptionChangedPayload = defineSchemaModel({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
name: 'SubscriptionChangedPayload',
|
|
48
|
+
description: 'Payload when subscription status changes',
|
|
49
|
+
fields: {
|
|
50
|
+
organizationId: {
|
|
51
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
52
|
+
isOptional: false,
|
|
53
|
+
},
|
|
54
|
+
previousPlan: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
55
|
+
newPlan: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
56
|
+
previousStatus: {
|
|
57
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
58
|
+
isOptional: true,
|
|
59
|
+
},
|
|
60
|
+
newStatus: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
61
|
+
changedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
62
|
+
},
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Event: Feature usage has been recorded.
|
|
67
67
|
*/
|
|
68
68
|
export const UsageRecordedEvent = defineEvent({
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
meta: {
|
|
70
|
+
key: 'billing.usage.recorded',
|
|
71
|
+
version: '1.0.0',
|
|
72
|
+
description: 'Feature usage has been recorded.',
|
|
73
|
+
stability: 'stable',
|
|
74
|
+
owners: ['@saas-team'],
|
|
75
|
+
tags: ['billing', 'usage', 'recorded'],
|
|
76
|
+
},
|
|
77
|
+
payload: UsageRecordedPayload,
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
81
|
* Event: Usage limit has been reached for a feature.
|
|
82
82
|
*/
|
|
83
83
|
export const UsageLimitReachedEvent = defineEvent({
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
meta: {
|
|
85
|
+
key: 'billing.limit.reached',
|
|
86
|
+
version: '1.0.0',
|
|
87
|
+
description: 'Usage limit has been reached for a feature.',
|
|
88
|
+
stability: 'stable',
|
|
89
|
+
owners: ['@saas-team'],
|
|
90
|
+
tags: ['billing', 'limit', 'reached'],
|
|
91
|
+
},
|
|
92
|
+
payload: UsageLimitReachedPayload,
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
96
|
* Event: Subscription status has changed.
|
|
97
97
|
*/
|
|
98
98
|
export const SubscriptionChangedEvent = defineEvent({
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
99
|
+
meta: {
|
|
100
|
+
key: 'billing.subscription.changed',
|
|
101
|
+
version: '1.0.0',
|
|
102
|
+
description: 'Subscription status has changed.',
|
|
103
|
+
stability: 'stable',
|
|
104
|
+
owners: ['@saas-team'],
|
|
105
|
+
tags: ['billing', 'subscription', 'changed'],
|
|
106
|
+
},
|
|
107
|
+
payload: SubscriptionChangedPayload,
|
|
108
108
|
});
|