@contractspec/example.saas-boilerplate 3.7.6 → 3.8.2

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 (143) hide show
  1. package/.turbo/turbo-build.log +39 -27
  2. package/AGENTS.md +50 -27
  3. package/CHANGELOG.md +36 -0
  4. package/README.md +65 -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 +1147 -869
  11. package/dist/browser/project/index.js +209 -209
  12. package/dist/browser/project/project.event.js +1 -1
  13. package/dist/browser/saas-boilerplate.feature.js +208 -0
  14. package/dist/browser/ui/SaasDashboard.js +356 -105
  15. package/dist/browser/ui/SaasDashboard.visualizations.js +249 -0
  16. package/dist/browser/ui/SaasProjectList.js +7 -7
  17. package/dist/browser/ui/SaasSettingsPanel.js +12 -12
  18. package/dist/browser/ui/hooks/index.js +2 -2
  19. package/dist/browser/ui/hooks/useProjectList.js +1 -1
  20. package/dist/browser/ui/hooks/useProjectMutations.js +1 -1
  21. package/dist/browser/ui/index.js +790 -521
  22. package/dist/browser/ui/modals/CreateProjectModal.js +10 -10
  23. package/dist/browser/ui/modals/ProjectActionsModal.js +13 -13
  24. package/dist/browser/ui/modals/index.js +23 -23
  25. package/dist/browser/ui/renderers/index.js +341 -115
  26. package/dist/browser/ui/renderers/project-list.markdown.js +229 -3
  27. package/dist/browser/ui/renderers/project-list.renderer.js +7 -7
  28. package/dist/browser/visualizations/catalog.js +155 -0
  29. package/dist/browser/visualizations/index.js +217 -0
  30. package/dist/browser/visualizations/selectors.js +210 -0
  31. package/dist/handlers/index.d.ts +2 -2
  32. package/dist/index.d.ts +5 -4
  33. package/dist/index.js +1147 -869
  34. package/dist/node/billing/billing.event.js +1 -1
  35. package/dist/node/billing/index.js +1 -1
  36. package/dist/node/index.js +1147 -869
  37. package/dist/node/project/index.js +209 -209
  38. package/dist/node/project/project.event.js +1 -1
  39. package/dist/node/saas-boilerplate.feature.js +208 -0
  40. package/dist/node/ui/SaasDashboard.js +356 -105
  41. package/dist/node/ui/SaasDashboard.visualizations.js +249 -0
  42. package/dist/node/ui/SaasProjectList.js +7 -7
  43. package/dist/node/ui/SaasSettingsPanel.js +12 -12
  44. package/dist/node/ui/hooks/index.js +2 -2
  45. package/dist/node/ui/hooks/useProjectList.js +1 -1
  46. package/dist/node/ui/hooks/useProjectMutations.js +1 -1
  47. package/dist/node/ui/index.js +790 -521
  48. package/dist/node/ui/modals/CreateProjectModal.js +10 -10
  49. package/dist/node/ui/modals/ProjectActionsModal.js +13 -13
  50. package/dist/node/ui/modals/index.js +23 -23
  51. package/dist/node/ui/renderers/index.js +341 -115
  52. package/dist/node/ui/renderers/project-list.markdown.js +229 -3
  53. package/dist/node/ui/renderers/project-list.renderer.js +7 -7
  54. package/dist/node/visualizations/catalog.js +155 -0
  55. package/dist/node/visualizations/index.js +217 -0
  56. package/dist/node/visualizations/selectors.js +210 -0
  57. package/dist/presentations/index.d.ts +1 -1
  58. package/dist/project/index.d.ts +7 -7
  59. package/dist/project/index.js +209 -209
  60. package/dist/project/project.event.js +1 -1
  61. package/dist/saas-boilerplate.feature.js +208 -0
  62. package/dist/settings/index.d.ts +1 -1
  63. package/dist/ui/SaasDashboard.js +356 -105
  64. package/dist/ui/SaasDashboard.visualizations.d.ts +5 -0
  65. package/dist/ui/SaasDashboard.visualizations.js +250 -0
  66. package/dist/ui/SaasProjectList.js +7 -7
  67. package/dist/ui/SaasSettingsPanel.js +12 -12
  68. package/dist/ui/hooks/index.d.ts +2 -2
  69. package/dist/ui/hooks/index.js +2 -2
  70. package/dist/ui/hooks/useProjectList.d.ts +5 -0
  71. package/dist/ui/hooks/useProjectList.js +1 -1
  72. package/dist/ui/hooks/useProjectMutations.d.ts +8 -0
  73. package/dist/ui/hooks/useProjectMutations.js +1 -1
  74. package/dist/ui/index.d.ts +4 -4
  75. package/dist/ui/index.js +790 -521
  76. package/dist/ui/modals/CreateProjectModal.js +10 -10
  77. package/dist/ui/modals/ProjectActionsModal.js +13 -13
  78. package/dist/ui/modals/index.js +23 -23
  79. package/dist/ui/renderers/index.d.ts +1 -1
  80. package/dist/ui/renderers/index.js +341 -115
  81. package/dist/ui/renderers/project-list.markdown.js +229 -3
  82. package/dist/ui/renderers/project-list.renderer.d.ts +1 -1
  83. package/dist/ui/renderers/project-list.renderer.js +7 -7
  84. package/dist/visualizations/catalog.d.ts +11 -0
  85. package/dist/visualizations/catalog.js +156 -0
  86. package/dist/visualizations/index.d.ts +2 -0
  87. package/dist/visualizations/index.js +218 -0
  88. package/dist/visualizations/selectors.d.ts +8 -0
  89. package/dist/visualizations/selectors.js +211 -0
  90. package/dist/visualizations/selectors.test.d.ts +1 -0
  91. package/package.json +70 -14
  92. package/src/billing/billing.entity.ts +132 -132
  93. package/src/billing/billing.enum.ts +9 -9
  94. package/src/billing/billing.event.ts +71 -71
  95. package/src/billing/billing.handler.ts +87 -87
  96. package/src/billing/billing.operations.ts +158 -158
  97. package/src/billing/billing.presentation.ts +45 -45
  98. package/src/billing/billing.schema.ts +76 -76
  99. package/src/billing/index.ts +43 -48
  100. package/src/dashboard/dashboard.presentation.ts +45 -45
  101. package/src/dashboard/index.ts +2 -2
  102. package/src/docs/saas-boilerplate.docblock.ts +43 -43
  103. package/src/example.ts +32 -32
  104. package/src/handlers/index.ts +9 -9
  105. package/src/handlers/saas.handlers.ts +250 -249
  106. package/src/index.ts +41 -41
  107. package/src/presentations/index.ts +18 -20
  108. package/src/project/index.ts +45 -50
  109. package/src/project/project.entity.ts +68 -68
  110. package/src/project/project.enum.ts +8 -8
  111. package/src/project/project.event.ts +79 -79
  112. package/src/project/project.handler.ts +103 -103
  113. package/src/project/project.operations.ts +236 -236
  114. package/src/project/project.presentation.ts +46 -46
  115. package/src/project/project.schema.ts +90 -90
  116. package/src/saas-boilerplate.feature.ts +103 -100
  117. package/src/seeders/index.ts +20 -20
  118. package/src/settings/index.ts +2 -3
  119. package/src/settings/settings.entity.ts +65 -65
  120. package/src/settings/settings.enum.ts +4 -4
  121. package/src/shared/mock-data.ts +92 -92
  122. package/src/shared/overlay-types.ts +23 -23
  123. package/src/tests/operations.test-spec.ts +96 -96
  124. package/src/ui/SaasDashboard.tsx +278 -270
  125. package/src/ui/SaasDashboard.visualizations.tsx +41 -0
  126. package/src/ui/SaasProjectList.tsx +90 -90
  127. package/src/ui/SaasSettingsPanel.tsx +84 -84
  128. package/src/ui/hooks/index.ts +3 -3
  129. package/src/ui/hooks/useProjectList.ts +69 -68
  130. package/src/ui/hooks/useProjectMutations.ts +144 -143
  131. package/src/ui/index.ts +8 -12
  132. package/src/ui/modals/CreateProjectModal.tsx +154 -154
  133. package/src/ui/modals/ProjectActionsModal.tsx +321 -321
  134. package/src/ui/overlays/demo-overlays.ts +49 -49
  135. package/src/ui/renderers/index.ts +5 -4
  136. package/src/ui/renderers/project-list.markdown.ts +229 -205
  137. package/src/ui/renderers/project-list.renderer.tsx +14 -13
  138. package/src/visualizations/catalog.ts +153 -0
  139. package/src/visualizations/index.ts +2 -0
  140. package/src/visualizations/selectors.test.ts +25 -0
  141. package/src/visualizations/selectors.ts +85 -0
  142. package/tsconfig.json +7 -8
  143. package/tsdown.config.js +7 -3
@@ -1,147 +1,147 @@
1
1
  import { defineSchemaModel, ScalarTypeEnum } from '@contractspec/lib.schema';
2
2
  import {
3
- ProjectStatusSchemaEnum,
4
- ProjectStatusFilterEnum,
3
+ ProjectStatusFilterEnum,
4
+ ProjectStatusSchemaEnum,
5
5
  } from './project.enum';
6
6
 
7
7
  /**
8
8
  * A project within an organization.
9
9
  */
10
10
  export const ProjectModel = defineSchemaModel({
11
- name: 'Project',
12
- description: 'A project within an organization',
13
- fields: {
14
- id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
15
- name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
16
- description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
17
- slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
18
- organizationId: {
19
- type: ScalarTypeEnum.String_unsecure(),
20
- isOptional: false,
21
- },
22
- createdBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
23
- status: { type: ProjectStatusSchemaEnum, isOptional: false },
24
- isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: false },
25
- tags: {
26
- type: ScalarTypeEnum.String_unsecure(),
27
- isArray: true,
28
- isOptional: false,
29
- },
30
- createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
31
- updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
32
- },
11
+ name: 'Project',
12
+ description: 'A project within an organization',
13
+ fields: {
14
+ id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
15
+ name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
16
+ description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
17
+ slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
18
+ organizationId: {
19
+ type: ScalarTypeEnum.String_unsecure(),
20
+ isOptional: false,
21
+ },
22
+ createdBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
23
+ status: { type: ProjectStatusSchemaEnum, isOptional: false },
24
+ isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: false },
25
+ tags: {
26
+ type: ScalarTypeEnum.String_unsecure(),
27
+ isArray: true,
28
+ isOptional: false,
29
+ },
30
+ createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
31
+ updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
32
+ },
33
33
  });
34
34
 
35
35
  /**
36
36
  * Input for creating a project.
37
37
  */
38
38
  export const CreateProjectInputModel = defineSchemaModel({
39
- name: 'CreateProjectInput',
40
- description: 'Input for creating a project',
41
- fields: {
42
- name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
43
- description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
44
- slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
45
- isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: true },
46
- tags: {
47
- type: ScalarTypeEnum.String_unsecure(),
48
- isArray: true,
49
- isOptional: true,
50
- },
51
- },
39
+ name: 'CreateProjectInput',
40
+ description: 'Input for creating a project',
41
+ fields: {
42
+ name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
43
+ description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
44
+ slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
45
+ isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: true },
46
+ tags: {
47
+ type: ScalarTypeEnum.String_unsecure(),
48
+ isArray: true,
49
+ isOptional: true,
50
+ },
51
+ },
52
52
  });
53
53
 
54
54
  /**
55
55
  * Input for updating a project.
56
56
  */
57
57
  export const UpdateProjectInputModel = defineSchemaModel({
58
- name: 'UpdateProjectInput',
59
- description: 'Input for updating a project',
60
- fields: {
61
- projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
62
- name: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
63
- description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
64
- slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
65
- isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: true },
66
- tags: {
67
- type: ScalarTypeEnum.String_unsecure(),
68
- isArray: true,
69
- isOptional: true,
70
- },
71
- status: { type: ProjectStatusSchemaEnum, isOptional: true },
72
- },
58
+ name: 'UpdateProjectInput',
59
+ description: 'Input for updating a project',
60
+ fields: {
61
+ projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
62
+ name: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
63
+ description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
64
+ slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
65
+ isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: true },
66
+ tags: {
67
+ type: ScalarTypeEnum.String_unsecure(),
68
+ isArray: true,
69
+ isOptional: true,
70
+ },
71
+ status: { type: ProjectStatusSchemaEnum, isOptional: true },
72
+ },
73
73
  });
74
74
 
75
75
  /**
76
76
  * Input for getting a project.
77
77
  */
78
78
  export const GetProjectInputModel = defineSchemaModel({
79
- name: 'GetProjectInput',
80
- fields: {
81
- projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
82
- },
79
+ name: 'GetProjectInput',
80
+ fields: {
81
+ projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
82
+ },
83
83
  });
84
84
 
85
85
  /**
86
86
  * Input for deleting a project.
87
87
  */
88
88
  export const DeleteProjectInputModel = defineSchemaModel({
89
- name: 'DeleteProjectInput',
90
- fields: {
91
- projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
92
- },
89
+ name: 'DeleteProjectInput',
90
+ fields: {
91
+ projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
92
+ },
93
93
  });
94
94
 
95
95
  /**
96
96
  * Output for delete operation.
97
97
  */
98
98
  export const DeleteProjectOutputModel = defineSchemaModel({
99
- name: 'DeleteProjectOutput',
100
- fields: {
101
- success: { type: ScalarTypeEnum.Boolean(), isOptional: false },
102
- },
99
+ name: 'DeleteProjectOutput',
100
+ fields: {
101
+ success: { type: ScalarTypeEnum.Boolean(), isOptional: false },
102
+ },
103
103
  });
104
104
 
105
105
  /**
106
106
  * Payload for project deleted event.
107
107
  */
108
108
  export const ProjectDeletedPayloadModel = defineSchemaModel({
109
- name: 'ProjectDeletedPayload',
110
- fields: {
111
- projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
112
- },
109
+ name: 'ProjectDeletedPayload',
110
+ fields: {
111
+ projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
112
+ },
113
113
  });
114
114
 
115
115
  /**
116
116
  * Input for listing projects.
117
117
  */
118
118
  export const ListProjectsInputModel = defineSchemaModel({
119
- name: 'ListProjectsInput',
120
- description: 'Input for listing projects',
121
- fields: {
122
- status: { type: ProjectStatusFilterEnum, isOptional: true },
123
- search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
124
- limit: {
125
- type: ScalarTypeEnum.Int_unsecure(),
126
- isOptional: true,
127
- defaultValue: 20,
128
- },
129
- offset: {
130
- type: ScalarTypeEnum.Int_unsecure(),
131
- isOptional: true,
132
- defaultValue: 0,
133
- },
134
- },
119
+ name: 'ListProjectsInput',
120
+ description: 'Input for listing projects',
121
+ fields: {
122
+ status: { type: ProjectStatusFilterEnum, isOptional: true },
123
+ search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
124
+ limit: {
125
+ type: ScalarTypeEnum.Int_unsecure(),
126
+ isOptional: true,
127
+ defaultValue: 20,
128
+ },
129
+ offset: {
130
+ type: ScalarTypeEnum.Int_unsecure(),
131
+ isOptional: true,
132
+ defaultValue: 0,
133
+ },
134
+ },
135
135
  });
136
136
 
137
137
  /**
138
138
  * Output for listing projects.
139
139
  */
140
140
  export const ListProjectsOutputModel = defineSchemaModel({
141
- name: 'ListProjectsOutput',
142
- description: 'Output for listing projects',
143
- fields: {
144
- projects: { type: ProjectModel, isArray: true, isOptional: false },
145
- total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
146
- },
141
+ name: 'ListProjectsOutput',
142
+ description: 'Output for listing projects',
143
+ fields: {
144
+ projects: { type: ProjectModel, isArray: true, isOptional: false },
145
+ total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
146
+ },
147
147
  });
@@ -4,121 +4,124 @@
4
4
  * Defines the feature module for the SaaS application foundation.
5
5
  */
6
6
  import { defineFeature } from '@contractspec/lib.contracts-spec';
7
+ import { SaasVisualizationRefs } from './visualizations';
7
8
 
8
9
  /**
9
10
  * SaaS Boilerplate feature module that bundles project management,
10
11
  * billing, and settings operations into an installable feature.
11
12
  */
12
13
  export const SaasBoilerplateFeature = defineFeature({
13
- meta: {
14
- key: 'saas-boilerplate',
15
- title: 'SaaS Boilerplate',
16
- description:
17
- 'SaaS application foundation with projects, billing, and settings',
18
- domain: 'saas',
19
- owners: ['@saas-team'],
20
- tags: ['saas', 'projects', 'billing'],
21
- stability: 'experimental',
22
- version: '1.0.0',
23
- },
14
+ meta: {
15
+ key: 'saas-boilerplate',
16
+ title: 'SaaS Boilerplate',
17
+ description:
18
+ 'SaaS application foundation with projects, billing, and settings',
19
+ domain: 'saas',
20
+ owners: ['@saas-team'],
21
+ tags: ['saas', 'projects', 'billing'],
22
+ stability: 'experimental',
23
+ version: '1.0.0',
24
+ },
24
25
 
25
- // All contract operations included in this feature
26
- operations: [
27
- // Project operations
28
- { key: 'saas.project.create', version: '1.0.0' },
29
- { key: 'saas.project.get', version: '1.0.0' },
30
- { key: 'saas.project.update', version: '1.0.0' },
31
- { key: 'saas.project.delete', version: '1.0.0' },
32
- { key: 'saas.project.list', version: '1.0.0' },
26
+ // All contract operations included in this feature
27
+ operations: [
28
+ // Project operations
29
+ { key: 'saas.project.create', version: '1.0.0' },
30
+ { key: 'saas.project.get', version: '1.0.0' },
31
+ { key: 'saas.project.update', version: '1.0.0' },
32
+ { key: 'saas.project.delete', version: '1.0.0' },
33
+ { key: 'saas.project.list', version: '1.0.0' },
33
34
 
34
- // Billing operations
35
- { key: 'saas.billing.subscription.get', version: '1.0.0' },
36
- { key: 'saas.billing.usage.record', version: '1.0.0' },
37
- { key: 'saas.billing.usage.summary', version: '1.0.0' },
38
- { key: 'saas.billing.feature.check', version: '1.0.0' },
39
- ],
35
+ // Billing operations
36
+ { key: 'saas.billing.subscription.get', version: '1.0.0' },
37
+ { key: 'saas.billing.usage.record', version: '1.0.0' },
38
+ { key: 'saas.billing.usage.summary', version: '1.0.0' },
39
+ { key: 'saas.billing.feature.check', version: '1.0.0' },
40
+ ],
40
41
 
41
- // Events emitted by this feature
42
- events: [
43
- // Project events
44
- { key: 'project.created', version: '1.0.0' },
45
- { key: 'project.updated', version: '1.0.0' },
46
- { key: 'project.deleted', version: '1.0.0' },
47
- { key: 'project.archived', version: '1.0.0' },
42
+ // Events emitted by this feature
43
+ events: [
44
+ // Project events
45
+ { key: 'project.created', version: '1.0.0' },
46
+ { key: 'project.updated', version: '1.0.0' },
47
+ { key: 'project.deleted', version: '1.0.0' },
48
+ { key: 'project.archived', version: '1.0.0' },
48
49
 
49
- // Billing events
50
- { key: 'billing.usage.recorded', version: '1.0.0' },
51
- { key: 'billing.subscription.changed', version: '1.0.0' },
52
- { key: 'billing.limit.reached', version: '1.0.0' },
53
- ],
50
+ // Billing events
51
+ { key: 'billing.usage.recorded', version: '1.0.0' },
52
+ { key: 'billing.subscription.changed', version: '1.0.0' },
53
+ { key: 'billing.limit.reached', version: '1.0.0' },
54
+ ],
54
55
 
55
- // Presentations associated with this feature
56
- presentations: [
57
- { key: 'saas.dashboard', version: '1.0.0' },
58
- { key: 'saas.project.list', version: '1.0.0' },
59
- { key: 'saas.project.detail', version: '1.0.0' },
60
- { key: 'saas.billing.subscription', version: '1.0.0' },
61
- { key: 'saas.billing.usage', version: '1.0.0' },
62
- { key: 'saas.settings', version: '1.0.0' },
63
- ],
56
+ // Presentations associated with this feature
57
+ presentations: [
58
+ { key: 'saas.dashboard', version: '1.0.0' },
59
+ { key: 'saas.project.list', version: '1.0.0' },
60
+ { key: 'saas.project.detail', version: '1.0.0' },
61
+ { key: 'saas.billing.subscription', version: '1.0.0' },
62
+ { key: 'saas.billing.usage', version: '1.0.0' },
63
+ { key: 'saas.settings', version: '1.0.0' },
64
+ ],
64
65
 
65
- // Link operations to their primary presentations
66
- opToPresentation: [
67
- {
68
- op: { key: 'saas.project.list', version: '1.0.0' },
69
- pres: { key: 'saas.project.list', version: '1.0.0' },
70
- },
71
- {
72
- op: { key: 'saas.project.get', version: '1.0.0' },
73
- pres: { key: 'saas.project.detail', version: '1.0.0' },
74
- },
75
- {
76
- op: { key: 'saas.billing.subscription.get', version: '1.0.0' },
77
- pres: { key: 'saas.billing.subscription', version: '1.0.0' },
78
- },
79
- {
80
- op: { key: 'saas.billing.usage.summary', version: '1.0.0' },
81
- pres: { key: 'saas.billing.usage', version: '1.0.0' },
82
- },
83
- ],
66
+ // Link operations to their primary presentations
67
+ opToPresentation: [
68
+ {
69
+ op: { key: 'saas.project.list', version: '1.0.0' },
70
+ pres: { key: 'saas.project.list', version: '1.0.0' },
71
+ },
72
+ {
73
+ op: { key: 'saas.project.get', version: '1.0.0' },
74
+ pres: { key: 'saas.project.detail', version: '1.0.0' },
75
+ },
76
+ {
77
+ op: { key: 'saas.billing.subscription.get', version: '1.0.0' },
78
+ pres: { key: 'saas.billing.subscription', version: '1.0.0' },
79
+ },
80
+ {
81
+ op: { key: 'saas.billing.usage.summary', version: '1.0.0' },
82
+ pres: { key: 'saas.billing.usage', version: '1.0.0' },
83
+ },
84
+ ],
84
85
 
85
- // Target requirements for multi-surface rendering
86
- presentationsTargets: [
87
- { key: 'saas.dashboard', version: '1.0.0', targets: ['react', 'markdown'] },
88
- {
89
- key: 'saas.project.list',
90
- version: '1.0.0',
91
- targets: ['react', 'markdown', 'application/json'],
92
- },
93
- {
94
- key: 'saas.billing.subscription',
95
- version: '1.0.0',
96
- targets: ['react', 'markdown'],
97
- },
98
- {
99
- key: 'saas.billing.usage',
100
- version: '1.0.0',
101
- targets: ['react', 'markdown'],
102
- },
103
- ],
86
+ // Target requirements for multi-surface rendering
87
+ presentationsTargets: [
88
+ { key: 'saas.dashboard', version: '1.0.0', targets: ['react', 'markdown'] },
89
+ {
90
+ key: 'saas.project.list',
91
+ version: '1.0.0',
92
+ targets: ['react', 'markdown', 'application/json'],
93
+ },
94
+ {
95
+ key: 'saas.billing.subscription',
96
+ version: '1.0.0',
97
+ targets: ['react', 'markdown'],
98
+ },
99
+ {
100
+ key: 'saas.billing.usage',
101
+ version: '1.0.0',
102
+ targets: ['react', 'markdown'],
103
+ },
104
+ ],
104
105
 
105
- // Capability requirements
106
- capabilities: {
107
- requires: [
108
- { key: 'identity', version: '1.0.0' },
109
- { key: 'audit-trail', version: '1.0.0' },
110
- { key: 'notifications', version: '1.0.0' },
111
- ],
112
- },
106
+ visualizations: SaasVisualizationRefs,
113
107
 
114
- telemetry: [{ key: 'saas-boilerplate.telemetry', version: '1.0.0' }],
108
+ // Capability requirements
109
+ capabilities: {
110
+ requires: [
111
+ { key: 'identity', version: '1.0.0' },
112
+ { key: 'audit-trail', version: '1.0.0' },
113
+ { key: 'notifications', version: '1.0.0' },
114
+ ],
115
+ },
115
116
 
116
- jobs: [{ key: 'saas-boilerplate.job.usage-recording', version: '1.0.0' }],
117
+ telemetry: [{ key: 'saas-boilerplate.telemetry', version: '1.0.0' }],
117
118
 
118
- docs: [
119
- 'docs.examples.saas-boilerplate.goal',
120
- 'docs.examples.saas-boilerplate.usage',
121
- 'docs.examples.saas-boilerplate.reference',
122
- 'docs.examples.saas-boilerplate.constraints',
123
- ],
119
+ jobs: [{ key: 'saas-boilerplate.job.usage-recording', version: '1.0.0' }],
120
+
121
+ docs: [
122
+ 'docs.examples.saas-boilerplate.goal',
123
+ 'docs.examples.saas-boilerplate.usage',
124
+ 'docs.examples.saas-boilerplate.reference',
125
+ 'docs.examples.saas-boilerplate.constraints',
126
+ ],
124
127
  });
@@ -1,28 +1,28 @@
1
1
  import type { DatabasePort } from '@contractspec/lib.runtime-sandbox';
2
2
 
3
3
  export async function seedSaasBoilerplate(params: {
4
- projectId: string;
5
- db: DatabasePort;
4
+ projectId: string;
5
+ db: DatabasePort;
6
6
  }) {
7
- const { projectId, db } = params;
7
+ const { projectId, db } = params;
8
8
 
9
- const existing = await db.query(
10
- `SELECT COUNT(*) as count FROM saas_project WHERE "projectId" = $1`,
11
- [projectId]
12
- );
13
- if ((existing.rows[0]?.count as number) > 0) return;
9
+ const existing = await db.query(
10
+ `SELECT COUNT(*) as count FROM saas_project WHERE "projectId" = $1`,
11
+ [projectId]
12
+ );
13
+ if ((existing.rows[0]?.count as number) > 0) return;
14
14
 
15
- await db.execute(
16
- `INSERT INTO saas_project (id, "projectId", "organizationId", name, description, status, tier)
15
+ await db.execute(
16
+ `INSERT INTO saas_project (id, "projectId", "organizationId", name, description, status, tier)
17
17
  VALUES ($1, $2, $3, $4, $5, $6, $7)`,
18
- [
19
- 'saas_proj_1',
20
- projectId,
21
- 'org_demo',
22
- 'Demo Project',
23
- 'A demo SaaS project',
24
- 'ACTIVE',
25
- 'PRO',
26
- ]
27
- );
18
+ [
19
+ 'saas_proj_1',
20
+ projectId,
21
+ 'org_demo',
22
+ 'Demo Project',
23
+ 'A demo SaaS project',
24
+ 'ACTIVE',
25
+ 'PRO',
26
+ ]
27
+ );
28
28
  }
@@ -2,8 +2,7 @@
2
2
  * Settings domain - application, organization, and user settings.
3
3
  */
4
4
 
5
+ // Entities
6
+ export { FeatureFlagEntity, SettingsEntity } from './settings.entity';
5
7
  // Enums
6
8
  export { SettingsScopeEnum } from './settings.enum';
7
-
8
- // Entities
9
- export { SettingsEntity, FeatureFlagEntity } from './settings.entity';