@contractspec/example.saas-boilerplate 3.7.5 → 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.
Files changed (115) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/AGENTS.md +50 -27
  3. package/CHANGELOG.md +16 -0
  4. package/README.md +64 -144
  5. package/dist/billing/billing.event.js +1 -1
  6. package/dist/billing/index.d.ts +6 -6
  7. package/dist/billing/index.js +1 -1
  8. package/dist/browser/billing/billing.event.js +1 -1
  9. package/dist/browser/billing/index.js +1 -1
  10. package/dist/browser/index.js +931 -932
  11. package/dist/browser/project/index.js +209 -209
  12. package/dist/browser/project/project.event.js +1 -1
  13. package/dist/browser/ui/SaasDashboard.js +45 -45
  14. package/dist/browser/ui/SaasProjectList.js +7 -7
  15. package/dist/browser/ui/SaasSettingsPanel.js +12 -12
  16. package/dist/browser/ui/hooks/index.js +2 -2
  17. package/dist/browser/ui/hooks/useProjectList.js +1 -1
  18. package/dist/browser/ui/hooks/useProjectMutations.js +1 -1
  19. package/dist/browser/ui/index.js +483 -484
  20. package/dist/browser/ui/modals/CreateProjectModal.js +10 -10
  21. package/dist/browser/ui/modals/ProjectActionsModal.js +13 -13
  22. package/dist/browser/ui/modals/index.js +23 -23
  23. package/dist/browser/ui/renderers/index.js +112 -112
  24. package/dist/browser/ui/renderers/project-list.renderer.js +7 -7
  25. package/dist/handlers/index.d.ts +2 -2
  26. package/dist/index.d.ts +4 -4
  27. package/dist/index.js +931 -932
  28. package/dist/node/billing/billing.event.js +1 -1
  29. package/dist/node/billing/index.js +1 -1
  30. package/dist/node/index.js +931 -932
  31. package/dist/node/project/index.js +209 -209
  32. package/dist/node/project/project.event.js +1 -1
  33. package/dist/node/ui/SaasDashboard.js +45 -45
  34. package/dist/node/ui/SaasProjectList.js +7 -7
  35. package/dist/node/ui/SaasSettingsPanel.js +12 -12
  36. package/dist/node/ui/hooks/index.js +2 -2
  37. package/dist/node/ui/hooks/useProjectList.js +1 -1
  38. package/dist/node/ui/hooks/useProjectMutations.js +1 -1
  39. package/dist/node/ui/index.js +483 -484
  40. package/dist/node/ui/modals/CreateProjectModal.js +10 -10
  41. package/dist/node/ui/modals/ProjectActionsModal.js +13 -13
  42. package/dist/node/ui/modals/index.js +23 -23
  43. package/dist/node/ui/renderers/index.js +112 -112
  44. package/dist/node/ui/renderers/project-list.renderer.js +7 -7
  45. package/dist/presentations/index.d.ts +1 -1
  46. package/dist/project/index.d.ts +7 -7
  47. package/dist/project/index.js +209 -209
  48. package/dist/project/project.event.js +1 -1
  49. package/dist/settings/index.d.ts +1 -1
  50. package/dist/ui/SaasDashboard.js +45 -45
  51. package/dist/ui/SaasProjectList.js +7 -7
  52. package/dist/ui/SaasSettingsPanel.js +12 -12
  53. package/dist/ui/hooks/index.d.ts +2 -2
  54. package/dist/ui/hooks/index.js +2 -2
  55. package/dist/ui/hooks/useProjectList.d.ts +5 -0
  56. package/dist/ui/hooks/useProjectList.js +1 -1
  57. package/dist/ui/hooks/useProjectMutations.d.ts +8 -0
  58. package/dist/ui/hooks/useProjectMutations.js +1 -1
  59. package/dist/ui/index.d.ts +4 -4
  60. package/dist/ui/index.js +483 -484
  61. package/dist/ui/modals/CreateProjectModal.js +10 -10
  62. package/dist/ui/modals/ProjectActionsModal.js +13 -13
  63. package/dist/ui/modals/index.js +23 -23
  64. package/dist/ui/renderers/index.d.ts +1 -1
  65. package/dist/ui/renderers/index.js +112 -112
  66. package/dist/ui/renderers/project-list.renderer.d.ts +1 -1
  67. package/dist/ui/renderers/project-list.renderer.js +7 -7
  68. package/package.json +14 -14
  69. package/src/billing/billing.entity.ts +132 -132
  70. package/src/billing/billing.enum.ts +9 -9
  71. package/src/billing/billing.event.ts +71 -71
  72. package/src/billing/billing.handler.ts +87 -87
  73. package/src/billing/billing.operations.ts +158 -158
  74. package/src/billing/billing.presentation.ts +45 -45
  75. package/src/billing/billing.schema.ts +76 -76
  76. package/src/billing/index.ts +43 -48
  77. package/src/dashboard/dashboard.presentation.ts +45 -45
  78. package/src/dashboard/index.ts +2 -2
  79. package/src/docs/saas-boilerplate.docblock.ts +43 -43
  80. package/src/example.ts +32 -32
  81. package/src/handlers/index.ts +9 -9
  82. package/src/handlers/saas.handlers.ts +250 -249
  83. package/src/index.ts +40 -41
  84. package/src/presentations/index.ts +18 -20
  85. package/src/project/index.ts +45 -50
  86. package/src/project/project.entity.ts +68 -68
  87. package/src/project/project.enum.ts +8 -8
  88. package/src/project/project.event.ts +79 -79
  89. package/src/project/project.handler.ts +103 -103
  90. package/src/project/project.operations.ts +236 -236
  91. package/src/project/project.presentation.ts +46 -46
  92. package/src/project/project.schema.ts +90 -90
  93. package/src/saas-boilerplate.feature.ts +100 -100
  94. package/src/seeders/index.ts +20 -20
  95. package/src/settings/index.ts +2 -3
  96. package/src/settings/settings.entity.ts +65 -65
  97. package/src/settings/settings.enum.ts +4 -4
  98. package/src/shared/mock-data.ts +92 -92
  99. package/src/shared/overlay-types.ts +23 -23
  100. package/src/tests/operations.test-spec.ts +96 -96
  101. package/src/ui/SaasDashboard.tsx +270 -270
  102. package/src/ui/SaasProjectList.tsx +90 -90
  103. package/src/ui/SaasSettingsPanel.tsx +84 -84
  104. package/src/ui/hooks/index.ts +3 -3
  105. package/src/ui/hooks/useProjectList.ts +69 -68
  106. package/src/ui/hooks/useProjectMutations.ts +144 -143
  107. package/src/ui/index.ts +8 -12
  108. package/src/ui/modals/CreateProjectModal.tsx +154 -154
  109. package/src/ui/modals/ProjectActionsModal.tsx +321 -321
  110. package/src/ui/overlays/demo-overlays.ts +49 -49
  111. package/src/ui/renderers/index.ts +5 -4
  112. package/src/ui/renderers/project-list.markdown.ts +204 -204
  113. package/src/ui/renderers/project-list.renderer.tsx +14 -13
  114. package/tsconfig.json +7 -8
  115. 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.5",
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,31 +351,31 @@
351
351
  "dev": "contractspec-bun-build dev",
352
352
  "clean": "rimraf dist .turbo",
353
353
  "lint": "bun lint:fix",
354
- "lint:fix": "eslint src --fix",
355
- "lint:check": "eslint src",
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.5",
362
- "@contractspec/lib.jobs": "3.7.5",
363
- "@contractspec/module.audit-trail": "3.7.5",
364
- "@contractspec/module.notifications": "3.7.5",
365
- "@contractspec/lib.contracts-spec": "3.7.5",
366
- "@contractspec/lib.schema": "3.7.5",
367
- "@contractspec/lib.example-shared-ui": "6.0.5",
368
- "@contractspec/lib.design-system": "3.7.5",
369
- "@contractspec/lib.runtime-sandbox": "2.7.5",
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
+ "@contractspec/lib.schema": "3.7.6",
367
+ "@contractspec/lib.example-shared-ui": "6.0.7",
368
+ "@contractspec/lib.design-system": "3.8.0",
369
+ "@contractspec/lib.runtime-sandbox": "2.7.6",
370
370
  "react": "19.2.0",
371
371
  "react-dom": "19.2.0"
372
372
  },
373
373
  "devDependencies": {
374
- "@contractspec/tool.typescript": "3.7.5",
374
+ "@contractspec/tool.typescript": "3.7.6",
375
375
  "typescript": "^5.9.3",
376
376
  "@types/react": "^19.2.14",
377
377
  "@types/react-dom": "^19.2.2",
378
- "@contractspec/tool.bun": "3.7.5"
378
+ "@contractspec/tool.bun": "3.7.6"
379
379
  },
380
380
  "publishConfig": {
381
381
  "exports": {
@@ -1,158 +1,158 @@
1
1
  import {
2
- defineEntity,
3
- defineEntityEnum,
4
- field,
5
- index,
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
- name: 'SubscriptionStatus',
13
- values: ['TRIALING', 'ACTIVE', 'PAST_DUE', 'CANCELED', 'PAUSED'] as const,
14
- schema: 'saas_app',
15
- description: 'Status of a subscription.',
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
- 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],
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
- 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
- ],
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
- 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'])],
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
- 'TRIALING',
9
- 'ACTIVE',
10
- 'PAST_DUE',
11
- 'CANCELED',
12
- 'PAUSED',
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
- 'included',
20
- 'limit_available',
21
- 'limit_reached',
22
- 'not_in_plan',
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
- 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
- },
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
- 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
- },
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
- 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
- },
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
- 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,
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
- 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,
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
- 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,
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
  });