@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.
Files changed (114) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/AGENTS.md +50 -27
  3. package/README.md +64 -144
  4. package/dist/billing/billing.event.js +1 -1
  5. package/dist/billing/index.d.ts +6 -6
  6. package/dist/billing/index.js +1 -1
  7. package/dist/browser/billing/billing.event.js +1 -1
  8. package/dist/browser/billing/index.js +1 -1
  9. package/dist/browser/index.js +931 -932
  10. package/dist/browser/project/index.js +209 -209
  11. package/dist/browser/project/project.event.js +1 -1
  12. package/dist/browser/ui/SaasDashboard.js +45 -45
  13. package/dist/browser/ui/SaasProjectList.js +7 -7
  14. package/dist/browser/ui/SaasSettingsPanel.js +12 -12
  15. package/dist/browser/ui/hooks/index.js +2 -2
  16. package/dist/browser/ui/hooks/useProjectList.js +1 -1
  17. package/dist/browser/ui/hooks/useProjectMutations.js +1 -1
  18. package/dist/browser/ui/index.js +483 -484
  19. package/dist/browser/ui/modals/CreateProjectModal.js +10 -10
  20. package/dist/browser/ui/modals/ProjectActionsModal.js +13 -13
  21. package/dist/browser/ui/modals/index.js +23 -23
  22. package/dist/browser/ui/renderers/index.js +112 -112
  23. package/dist/browser/ui/renderers/project-list.renderer.js +7 -7
  24. package/dist/handlers/index.d.ts +2 -2
  25. package/dist/index.d.ts +4 -4
  26. package/dist/index.js +931 -932
  27. package/dist/node/billing/billing.event.js +1 -1
  28. package/dist/node/billing/index.js +1 -1
  29. package/dist/node/index.js +931 -932
  30. package/dist/node/project/index.js +209 -209
  31. package/dist/node/project/project.event.js +1 -1
  32. package/dist/node/ui/SaasDashboard.js +45 -45
  33. package/dist/node/ui/SaasProjectList.js +7 -7
  34. package/dist/node/ui/SaasSettingsPanel.js +12 -12
  35. package/dist/node/ui/hooks/index.js +2 -2
  36. package/dist/node/ui/hooks/useProjectList.js +1 -1
  37. package/dist/node/ui/hooks/useProjectMutations.js +1 -1
  38. package/dist/node/ui/index.js +483 -484
  39. package/dist/node/ui/modals/CreateProjectModal.js +10 -10
  40. package/dist/node/ui/modals/ProjectActionsModal.js +13 -13
  41. package/dist/node/ui/modals/index.js +23 -23
  42. package/dist/node/ui/renderers/index.js +112 -112
  43. package/dist/node/ui/renderers/project-list.renderer.js +7 -7
  44. package/dist/presentations/index.d.ts +1 -1
  45. package/dist/project/index.d.ts +7 -7
  46. package/dist/project/index.js +209 -209
  47. package/dist/project/project.event.js +1 -1
  48. package/dist/settings/index.d.ts +1 -1
  49. package/dist/ui/SaasDashboard.js +45 -45
  50. package/dist/ui/SaasProjectList.js +7 -7
  51. package/dist/ui/SaasSettingsPanel.js +12 -12
  52. package/dist/ui/hooks/index.d.ts +2 -2
  53. package/dist/ui/hooks/index.js +2 -2
  54. package/dist/ui/hooks/useProjectList.d.ts +5 -0
  55. package/dist/ui/hooks/useProjectList.js +1 -1
  56. package/dist/ui/hooks/useProjectMutations.d.ts +8 -0
  57. package/dist/ui/hooks/useProjectMutations.js +1 -1
  58. package/dist/ui/index.d.ts +4 -4
  59. package/dist/ui/index.js +483 -484
  60. package/dist/ui/modals/CreateProjectModal.js +10 -10
  61. package/dist/ui/modals/ProjectActionsModal.js +13 -13
  62. package/dist/ui/modals/index.js +23 -23
  63. package/dist/ui/renderers/index.d.ts +1 -1
  64. package/dist/ui/renderers/index.js +112 -112
  65. package/dist/ui/renderers/project-list.renderer.d.ts +1 -1
  66. package/dist/ui/renderers/project-list.renderer.js +7 -7
  67. package/package.json +10 -10
  68. package/src/billing/billing.entity.ts +132 -132
  69. package/src/billing/billing.enum.ts +9 -9
  70. package/src/billing/billing.event.ts +71 -71
  71. package/src/billing/billing.handler.ts +87 -87
  72. package/src/billing/billing.operations.ts +158 -158
  73. package/src/billing/billing.presentation.ts +45 -45
  74. package/src/billing/billing.schema.ts +76 -76
  75. package/src/billing/index.ts +43 -48
  76. package/src/dashboard/dashboard.presentation.ts +45 -45
  77. package/src/dashboard/index.ts +2 -2
  78. package/src/docs/saas-boilerplate.docblock.ts +43 -43
  79. package/src/example.ts +32 -32
  80. package/src/handlers/index.ts +9 -9
  81. package/src/handlers/saas.handlers.ts +250 -249
  82. package/src/index.ts +40 -41
  83. package/src/presentations/index.ts +18 -20
  84. package/src/project/index.ts +45 -50
  85. package/src/project/project.entity.ts +68 -68
  86. package/src/project/project.enum.ts +8 -8
  87. package/src/project/project.event.ts +79 -79
  88. package/src/project/project.handler.ts +103 -103
  89. package/src/project/project.operations.ts +236 -236
  90. package/src/project/project.presentation.ts +46 -46
  91. package/src/project/project.schema.ts +90 -90
  92. package/src/saas-boilerplate.feature.ts +100 -100
  93. package/src/seeders/index.ts +20 -20
  94. package/src/settings/index.ts +2 -3
  95. package/src/settings/settings.entity.ts +65 -65
  96. package/src/settings/settings.enum.ts +4 -4
  97. package/src/shared/mock-data.ts +92 -92
  98. package/src/shared/overlay-types.ts +23 -23
  99. package/src/tests/operations.test-spec.ts +96 -96
  100. package/src/ui/SaasDashboard.tsx +270 -270
  101. package/src/ui/SaasProjectList.tsx +90 -90
  102. package/src/ui/SaasSettingsPanel.tsx +84 -84
  103. package/src/ui/hooks/index.ts +3 -3
  104. package/src/ui/hooks/useProjectList.ts +69 -68
  105. package/src/ui/hooks/useProjectMutations.ts +144 -143
  106. package/src/ui/index.ts +8 -12
  107. package/src/ui/modals/CreateProjectModal.tsx +154 -154
  108. package/src/ui/modals/ProjectActionsModal.tsx +321 -321
  109. package/src/ui/overlays/demo-overlays.ts +49 -49
  110. package/src/ui/renderers/index.ts +5 -4
  111. package/src/ui/renderers/project-list.markdown.ts +204 -204
  112. package/src/ui/renderers/project-list.renderer.tsx +14 -13
  113. package/tsconfig.json +7 -8
  114. 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.6",
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": "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.6",
362
- "@contractspec/lib.jobs": "3.7.6",
363
- "@contractspec/module.audit-trail": "3.7.6",
364
- "@contractspec/module.notifications": "3.7.6",
365
- "@contractspec/lib.contracts-spec": "3.7.6",
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.6",
368
- "@contractspec/lib.design-system": "3.7.6",
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
- 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
  });