@contractspec/example.saas-boilerplate 3.8.9 → 3.8.10

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 (156) hide show
  1. package/.turbo/turbo-build.log +156 -156
  2. package/CHANGELOG.md +20 -0
  3. package/dist/billing/billing.entity.js +1 -113
  4. package/dist/billing/billing.enum.js +1 -19
  5. package/dist/billing/billing.event.js +1 -90
  6. package/dist/billing/billing.handler.js +1 -148
  7. package/dist/billing/billing.operations.js +1 -278
  8. package/dist/billing/billing.presentation.js +1 -55
  9. package/dist/billing/billing.schema.js +1 -121
  10. package/dist/billing/index.js +1 -691
  11. package/dist/browser/billing/billing.entity.js +1 -113
  12. package/dist/browser/billing/billing.enum.js +1 -19
  13. package/dist/browser/billing/billing.event.js +1 -90
  14. package/dist/browser/billing/billing.handler.js +1 -148
  15. package/dist/browser/billing/billing.operations.js +1 -278
  16. package/dist/browser/billing/billing.presentation.js +1 -55
  17. package/dist/browser/billing/billing.schema.js +1 -121
  18. package/dist/browser/billing/index.js +1 -691
  19. package/dist/browser/dashboard/dashboard.presentation.js +1 -55
  20. package/dist/browser/dashboard/index.js +1 -55
  21. package/dist/browser/docs/index.js +5 -49
  22. package/dist/browser/docs/saas-boilerplate.docblock.js +5 -49
  23. package/dist/browser/example.js +1 -39
  24. package/dist/browser/handlers/index.js +2 -358
  25. package/dist/browser/handlers/saas.handlers.js +2 -134
  26. package/dist/browser/index.js +9 -3591
  27. package/dist/browser/presentations/index.js +1 -299
  28. package/dist/browser/project/index.js +1 -793
  29. package/dist/browser/project/project.entity.js +1 -77
  30. package/dist/browser/project/project.enum.js +1 -18
  31. package/dist/browser/project/project.event.js +1 -103
  32. package/dist/browser/project/project.handler.js +1 -178
  33. package/dist/browser/project/project.operations.js +1 -372
  34. package/dist/browser/project/project.presentation.js +1 -180
  35. package/dist/browser/project/project.schema.js +1 -134
  36. package/dist/browser/saas-boilerplate.feature.js +1 -304
  37. package/dist/browser/seeders/index.js +2 -20
  38. package/dist/browser/settings/index.js +1 -75
  39. package/dist/browser/settings/settings.entity.js +1 -74
  40. package/dist/browser/settings/settings.enum.js +1 -11
  41. package/dist/browser/shared/mock-data.js +1 -104
  42. package/dist/browser/tests/operations.test-spec.js +1 -112
  43. package/dist/browser/ui/SaasDashboard.js +1 -1239
  44. package/dist/browser/ui/SaasDashboard.visualizations.js +1 -249
  45. package/dist/browser/ui/SaasProjectList.js +1 -162
  46. package/dist/browser/ui/SaasSettingsPanel.js +1 -145
  47. package/dist/browser/ui/hooks/index.js +1 -159
  48. package/dist/browser/ui/hooks/useProjectList.js +1 -66
  49. package/dist/browser/ui/hooks/useProjectMutations.js +1 -91
  50. package/dist/browser/ui/index.js +5 -2077
  51. package/dist/browser/ui/modals/CreateProjectModal.js +1 -153
  52. package/dist/browser/ui/modals/ProjectActionsModal.js +1 -335
  53. package/dist/browser/ui/modals/index.js +1 -487
  54. package/dist/browser/ui/overlays/demo-overlays.js +1 -61
  55. package/dist/browser/ui/overlays/index.js +1 -61
  56. package/dist/browser/ui/renderers/index.js +5 -901
  57. package/dist/browser/ui/renderers/project-list.markdown.js +5 -725
  58. package/dist/browser/ui/renderers/project-list.renderer.js +1 -177
  59. package/dist/browser/visualizations/catalog.js +1 -155
  60. package/dist/browser/visualizations/index.js +1 -217
  61. package/dist/browser/visualizations/selectors.js +1 -210
  62. package/dist/dashboard/dashboard.presentation.js +1 -55
  63. package/dist/dashboard/index.js +1 -55
  64. package/dist/docs/index.js +5 -49
  65. package/dist/docs/saas-boilerplate.docblock.js +5 -49
  66. package/dist/example.js +1 -39
  67. package/dist/handlers/index.js +2 -358
  68. package/dist/handlers/saas.handlers.js +2 -134
  69. package/dist/index.js +9 -3591
  70. package/dist/node/billing/billing.entity.js +1 -113
  71. package/dist/node/billing/billing.enum.js +1 -19
  72. package/dist/node/billing/billing.event.js +1 -90
  73. package/dist/node/billing/billing.handler.js +1 -148
  74. package/dist/node/billing/billing.operations.js +1 -278
  75. package/dist/node/billing/billing.presentation.js +1 -55
  76. package/dist/node/billing/billing.schema.js +1 -121
  77. package/dist/node/billing/index.js +1 -691
  78. package/dist/node/dashboard/dashboard.presentation.js +1 -55
  79. package/dist/node/dashboard/index.js +1 -55
  80. package/dist/node/docs/index.js +5 -49
  81. package/dist/node/docs/saas-boilerplate.docblock.js +5 -49
  82. package/dist/node/example.js +1 -39
  83. package/dist/node/handlers/index.js +2 -358
  84. package/dist/node/handlers/saas.handlers.js +2 -134
  85. package/dist/node/index.js +9 -3591
  86. package/dist/node/presentations/index.js +1 -299
  87. package/dist/node/project/index.js +1 -793
  88. package/dist/node/project/project.entity.js +1 -77
  89. package/dist/node/project/project.enum.js +1 -18
  90. package/dist/node/project/project.event.js +1 -103
  91. package/dist/node/project/project.handler.js +1 -178
  92. package/dist/node/project/project.operations.js +1 -372
  93. package/dist/node/project/project.presentation.js +1 -180
  94. package/dist/node/project/project.schema.js +1 -134
  95. package/dist/node/saas-boilerplate.feature.js +1 -304
  96. package/dist/node/seeders/index.js +2 -20
  97. package/dist/node/settings/index.js +1 -75
  98. package/dist/node/settings/settings.entity.js +1 -74
  99. package/dist/node/settings/settings.enum.js +1 -11
  100. package/dist/node/shared/mock-data.js +1 -104
  101. package/dist/node/tests/operations.test-spec.js +1 -112
  102. package/dist/node/ui/SaasDashboard.js +1 -1239
  103. package/dist/node/ui/SaasDashboard.visualizations.js +1 -249
  104. package/dist/node/ui/SaasProjectList.js +1 -162
  105. package/dist/node/ui/SaasSettingsPanel.js +1 -145
  106. package/dist/node/ui/hooks/index.js +1 -159
  107. package/dist/node/ui/hooks/useProjectList.js +1 -66
  108. package/dist/node/ui/hooks/useProjectMutations.js +1 -91
  109. package/dist/node/ui/index.js +5 -2077
  110. package/dist/node/ui/modals/CreateProjectModal.js +1 -153
  111. package/dist/node/ui/modals/ProjectActionsModal.js +1 -335
  112. package/dist/node/ui/modals/index.js +1 -487
  113. package/dist/node/ui/overlays/demo-overlays.js +1 -61
  114. package/dist/node/ui/overlays/index.js +1 -61
  115. package/dist/node/ui/renderers/index.js +5 -901
  116. package/dist/node/ui/renderers/project-list.markdown.js +5 -725
  117. package/dist/node/ui/renderers/project-list.renderer.js +1 -177
  118. package/dist/node/visualizations/catalog.js +1 -155
  119. package/dist/node/visualizations/index.js +1 -217
  120. package/dist/node/visualizations/selectors.js +1 -210
  121. package/dist/presentations/index.js +1 -299
  122. package/dist/project/index.js +1 -793
  123. package/dist/project/project.entity.js +1 -77
  124. package/dist/project/project.enum.js +1 -18
  125. package/dist/project/project.event.js +1 -103
  126. package/dist/project/project.handler.js +1 -178
  127. package/dist/project/project.operations.js +1 -372
  128. package/dist/project/project.presentation.js +1 -180
  129. package/dist/project/project.schema.js +1 -134
  130. package/dist/saas-boilerplate.feature.js +1 -304
  131. package/dist/seeders/index.js +2 -20
  132. package/dist/settings/index.js +1 -75
  133. package/dist/settings/settings.entity.js +1 -74
  134. package/dist/settings/settings.enum.js +1 -11
  135. package/dist/shared/mock-data.js +1 -104
  136. package/dist/tests/operations.test-spec.js +1 -112
  137. package/dist/ui/SaasDashboard.js +1 -1239
  138. package/dist/ui/SaasDashboard.visualizations.js +1 -249
  139. package/dist/ui/SaasProjectList.js +1 -162
  140. package/dist/ui/SaasSettingsPanel.js +1 -145
  141. package/dist/ui/hooks/index.js +1 -159
  142. package/dist/ui/hooks/useProjectList.js +1 -66
  143. package/dist/ui/hooks/useProjectMutations.js +1 -91
  144. package/dist/ui/index.js +5 -2077
  145. package/dist/ui/modals/CreateProjectModal.js +1 -153
  146. package/dist/ui/modals/ProjectActionsModal.js +1 -335
  147. package/dist/ui/modals/index.js +1 -487
  148. package/dist/ui/overlays/demo-overlays.js +1 -61
  149. package/dist/ui/overlays/index.js +1 -61
  150. package/dist/ui/renderers/index.js +5 -901
  151. package/dist/ui/renderers/project-list.markdown.js +5 -725
  152. package/dist/ui/renderers/project-list.renderer.js +1 -177
  153. package/dist/visualizations/catalog.js +1 -155
  154. package/dist/visualizations/index.js +1 -217
  155. package/dist/visualizations/selectors.js +1 -210
  156. package/package.json +12 -12
@@ -1,793 +1 @@
1
- // src/shared/mock-data.ts
2
- var MOCK_PROJECTS = [
3
- {
4
- id: "proj-1",
5
- name: "Marketing Website",
6
- description: "Main company website redesign project",
7
- slug: "marketing-website",
8
- organizationId: "demo-org",
9
- createdBy: "user-1",
10
- status: "ACTIVE",
11
- isPublic: false,
12
- tags: ["marketing", "website", "redesign"],
13
- createdAt: new Date("2024-01-15T10:00:00Z"),
14
- updatedAt: new Date("2024-03-20T14:30:00Z")
15
- },
16
- {
17
- id: "proj-2",
18
- name: "Mobile App v2",
19
- description: "Next generation mobile application",
20
- slug: "mobile-app-v2",
21
- organizationId: "demo-org",
22
- createdBy: "user-2",
23
- status: "ACTIVE",
24
- isPublic: false,
25
- tags: ["mobile", "app", "v2"],
26
- createdAt: new Date("2024-02-01T09:00:00Z"),
27
- updatedAt: new Date("2024-04-05T11:15:00Z")
28
- },
29
- {
30
- id: "proj-3",
31
- name: "API Integration",
32
- description: "Third-party API integration project",
33
- slug: "api-integration",
34
- organizationId: "demo-org",
35
- createdBy: "user-1",
36
- status: "DRAFT",
37
- isPublic: false,
38
- tags: ["api", "integration"],
39
- createdAt: new Date("2024-03-10T08:00:00Z"),
40
- updatedAt: new Date("2024-03-10T08:00:00Z")
41
- },
42
- {
43
- id: "proj-4",
44
- name: "Analytics Dashboard",
45
- description: "Internal analytics and reporting dashboard",
46
- slug: "analytics-dashboard",
47
- organizationId: "demo-org",
48
- createdBy: "user-3",
49
- status: "ARCHIVED",
50
- isPublic: true,
51
- tags: ["analytics", "dashboard", "reporting"],
52
- createdAt: new Date("2023-10-01T12:00:00Z"),
53
- updatedAt: new Date("2024-02-28T16:45:00Z")
54
- }
55
- ];
56
- var MOCK_SUBSCRIPTION = {
57
- id: "sub-1",
58
- organizationId: "demo-org",
59
- planId: "pro",
60
- planName: "Professional",
61
- status: "ACTIVE",
62
- currentPeriodStart: new Date("2024-04-01T00:00:00Z"),
63
- currentPeriodEnd: new Date("2024-05-01T00:00:00Z"),
64
- limits: {
65
- projects: 25,
66
- users: 10,
67
- storage: 50,
68
- apiCalls: 1e5
69
- },
70
- usage: {
71
- projects: 4,
72
- users: 5,
73
- storage: 12.5,
74
- apiCalls: 45230
75
- }
76
- };
77
- var MOCK_USAGE_SUMMARY = {
78
- organizationId: "demo-org",
79
- period: "current_month",
80
- apiCalls: {
81
- total: 45230,
82
- limit: 1e5,
83
- percentUsed: 45.23
84
- },
85
- storage: {
86
- totalGb: 12.5,
87
- limitGb: 50,
88
- percentUsed: 25
89
- },
90
- activeProjects: 4,
91
- activeUsers: 5,
92
- breakdown: [
93
- { date: "2024-04-01", apiCalls: 3200, storageGb: 12.1 },
94
- { date: "2024-04-02", apiCalls: 2800, storageGb: 12.2 },
95
- { date: "2024-04-03", apiCalls: 4100, storageGb: 12.3 },
96
- { date: "2024-04-04", apiCalls: 3600, storageGb: 12.4 },
97
- { date: "2024-04-05", apiCalls: 3800, storageGb: 12.5 }
98
- ]
99
- };
100
-
101
- // src/project/project.handler.ts
102
- async function mockListProjectsHandler(input) {
103
- const { status, search, limit = 20, offset = 0 } = input;
104
- let filtered = [...MOCK_PROJECTS];
105
- if (status && status !== "all") {
106
- filtered = filtered.filter((p) => p.status === status);
107
- }
108
- if (search) {
109
- const q = search.toLowerCase();
110
- filtered = filtered.filter((p) => p.name.toLowerCase().includes(q) || p.description?.toLowerCase().includes(q) || p.tags.some((t) => t.toLowerCase().includes(q)));
111
- }
112
- filtered.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
113
- const total = filtered.length;
114
- const projects = filtered.slice(offset, offset + limit);
115
- return {
116
- projects,
117
- total
118
- };
119
- }
120
- async function mockGetProjectHandler(input) {
121
- const project = MOCK_PROJECTS.find((p) => p.id === input.projectId);
122
- if (!project) {
123
- throw new Error("NOT_FOUND");
124
- }
125
- return project;
126
- }
127
- async function mockCreateProjectHandler(input, context) {
128
- if (input.slug) {
129
- const exists = MOCK_PROJECTS.some((p) => p.slug === input.slug);
130
- if (exists) {
131
- throw new Error("SLUG_EXISTS");
132
- }
133
- }
134
- const now = new Date;
135
- return {
136
- id: `proj-${Date.now()}`,
137
- name: input.name,
138
- description: input.description,
139
- slug: input.slug ?? input.name.toLowerCase().replace(/\s+/g, "-"),
140
- organizationId: context.organizationId,
141
- createdBy: context.userId,
142
- status: "DRAFT",
143
- isPublic: input.isPublic ?? false,
144
- tags: input.tags ?? [],
145
- createdAt: now,
146
- updatedAt: now
147
- };
148
- }
149
- async function mockUpdateProjectHandler(input) {
150
- const project = MOCK_PROJECTS.find((p) => p.id === input.projectId);
151
- if (!project) {
152
- throw new Error("NOT_FOUND");
153
- }
154
- return {
155
- ...project,
156
- name: input.name ?? project.name,
157
- description: input.description ?? project.description,
158
- slug: input.slug ?? project.slug,
159
- isPublic: input.isPublic ?? project.isPublic,
160
- tags: input.tags ?? project.tags,
161
- status: input.status ?? project.status,
162
- updatedAt: new Date
163
- };
164
- }
165
- async function mockDeleteProjectHandler(input) {
166
- const project = MOCK_PROJECTS.find((p) => p.id === input.projectId);
167
- if (!project) {
168
- throw new Error("NOT_FOUND");
169
- }
170
- return { success: true };
171
- }
172
-
173
- // src/project/project.entity.ts
174
- import {
175
- defineEntity,
176
- defineEntityEnum,
177
- field,
178
- index
179
- } from "@contractspec/lib.schema";
180
- var ProjectStatusEnum = defineEntityEnum({
181
- name: "ProjectStatus",
182
- values: ["DRAFT", "ACTIVE", "ARCHIVED", "DELETED"],
183
- schema: "saas_app",
184
- description: "Status of a project."
185
- });
186
- var ProjectEntity = defineEntity({
187
- name: "Project",
188
- description: "A project belonging to an organization.",
189
- schema: "saas_app",
190
- map: "project",
191
- fields: {
192
- id: field.id({ description: "Unique project ID" }),
193
- name: field.string({ description: "Project name" }),
194
- description: field.string({
195
- isOptional: true,
196
- description: "Project description"
197
- }),
198
- slug: field.string({
199
- isOptional: true,
200
- description: "URL-friendly identifier"
201
- }),
202
- organizationId: field.foreignKey({ description: "Owning organization" }),
203
- createdBy: field.foreignKey({
204
- description: "User who created the project"
205
- }),
206
- status: field.enum("ProjectStatus", { default: "DRAFT" }),
207
- isPublic: field.boolean({
208
- default: false,
209
- description: "Whether project is publicly visible"
210
- }),
211
- settings: field.json({
212
- isOptional: true,
213
- description: "Project-specific settings"
214
- }),
215
- tags: field.string({ isArray: true, description: "Project tags" }),
216
- metadata: field.json({ isOptional: true }),
217
- createdAt: field.createdAt(),
218
- updatedAt: field.updatedAt(),
219
- archivedAt: field.dateTime({ isOptional: true })
220
- },
221
- indexes: [
222
- index.on(["organizationId", "status"]),
223
- index.on(["organizationId", "createdAt"]),
224
- index.unique(["organizationId", "slug"])
225
- ],
226
- enums: [ProjectStatusEnum]
227
- });
228
- var ProjectMemberEntity = defineEntity({
229
- name: "ProjectMember",
230
- description: "User access to a specific project.",
231
- schema: "saas_app",
232
- map: "project_member",
233
- fields: {
234
- id: field.id(),
235
- projectId: field.foreignKey(),
236
- userId: field.foreignKey(),
237
- role: field.string({
238
- description: "Role in project (owner, editor, viewer)"
239
- }),
240
- addedBy: field.string({ isOptional: true }),
241
- createdAt: field.createdAt()
242
- },
243
- indexes: [index.unique(["projectId", "userId"])]
244
- });
245
-
246
- // src/project/project.enum.ts
247
- import { defineEnum } from "@contractspec/lib.schema";
248
- var ProjectStatusSchemaEnum = defineEnum("ProjectStatus", [
249
- "DRAFT",
250
- "ACTIVE",
251
- "ARCHIVED",
252
- "DELETED"
253
- ]);
254
- var ProjectStatusFilterEnum = defineEnum("ProjectStatusFilter", [
255
- "DRAFT",
256
- "ACTIVE",
257
- "ARCHIVED",
258
- "all"
259
- ]);
260
-
261
- // src/project/project.event.ts
262
- import { defineEvent } from "@contractspec/lib.contracts-spec";
263
- import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
264
- var ProjectCreatedPayload = defineSchemaModel({
265
- name: "ProjectCreatedPayload",
266
- description: "Payload when a project is created",
267
- fields: {
268
- projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
269
- name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
270
- organizationId: {
271
- type: ScalarTypeEnum.String_unsecure(),
272
- isOptional: false
273
- },
274
- createdBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
275
- createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
276
- }
277
- });
278
- var ProjectUpdatedPayload = defineSchemaModel({
279
- name: "ProjectUpdatedPayload",
280
- description: "Payload when a project is updated",
281
- fields: {
282
- projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
283
- updatedFields: {
284
- type: ScalarTypeEnum.String_unsecure(),
285
- isArray: true,
286
- isOptional: false
287
- },
288
- updatedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
289
- updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
290
- }
291
- });
292
- var ProjectDeletedPayload = defineSchemaModel({
293
- name: "ProjectDeletedPayload",
294
- description: "Payload when a project is deleted",
295
- fields: {
296
- projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
297
- organizationId: {
298
- type: ScalarTypeEnum.String_unsecure(),
299
- isOptional: false
300
- },
301
- deletedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
302
- deletedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
303
- }
304
- });
305
- var ProjectArchivedPayload = defineSchemaModel({
306
- name: "ProjectArchivedPayload",
307
- description: "Payload when a project is archived",
308
- fields: {
309
- projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
310
- archivedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
311
- archivedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
312
- }
313
- });
314
- var ProjectCreatedEvent = defineEvent({
315
- meta: {
316
- key: "project.created",
317
- version: "1.0.0",
318
- description: "A new project has been created.",
319
- stability: "stable",
320
- owners: ["@saas-team"],
321
- tags: ["project", "created"]
322
- },
323
- payload: ProjectCreatedPayload
324
- });
325
- var ProjectUpdatedEvent = defineEvent({
326
- meta: {
327
- key: "project.updated",
328
- version: "1.0.0",
329
- description: "A project has been updated.",
330
- stability: "stable",
331
- owners: ["@saas-team"],
332
- tags: ["project", "updated"]
333
- },
334
- payload: ProjectUpdatedPayload
335
- });
336
- var ProjectDeletedEvent = defineEvent({
337
- meta: {
338
- key: "project.deleted",
339
- version: "1.0.0",
340
- description: "A project has been deleted.",
341
- stability: "stable",
342
- owners: ["@saas-team"],
343
- tags: ["project", "deleted"]
344
- },
345
- payload: ProjectDeletedPayload
346
- });
347
- var ProjectArchivedEvent = defineEvent({
348
- meta: {
349
- key: "project.archived",
350
- version: "1.0.0",
351
- description: "A project has been archived.",
352
- stability: "stable",
353
- owners: ["@saas-team"],
354
- tags: ["project", "archived"]
355
- },
356
- payload: ProjectArchivedPayload
357
- });
358
-
359
- // src/project/project.schema.ts
360
- import { defineSchemaModel as defineSchemaModel2, ScalarTypeEnum as ScalarTypeEnum2 } from "@contractspec/lib.schema";
361
- var ProjectModel = defineSchemaModel2({
362
- name: "Project",
363
- description: "A project within an organization",
364
- fields: {
365
- id: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
366
- name: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
367
- description: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
368
- slug: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
369
- organizationId: {
370
- type: ScalarTypeEnum2.String_unsecure(),
371
- isOptional: false
372
- },
373
- createdBy: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
374
- status: { type: ProjectStatusSchemaEnum, isOptional: false },
375
- isPublic: { type: ScalarTypeEnum2.Boolean(), isOptional: false },
376
- tags: {
377
- type: ScalarTypeEnum2.String_unsecure(),
378
- isArray: true,
379
- isOptional: false
380
- },
381
- createdAt: { type: ScalarTypeEnum2.DateTime(), isOptional: false },
382
- updatedAt: { type: ScalarTypeEnum2.DateTime(), isOptional: false }
383
- }
384
- });
385
- var CreateProjectInputModel = defineSchemaModel2({
386
- name: "CreateProjectInput",
387
- description: "Input for creating a project",
388
- fields: {
389
- name: { type: ScalarTypeEnum2.NonEmptyString(), isOptional: false },
390
- description: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
391
- slug: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
392
- isPublic: { type: ScalarTypeEnum2.Boolean(), isOptional: true },
393
- tags: {
394
- type: ScalarTypeEnum2.String_unsecure(),
395
- isArray: true,
396
- isOptional: true
397
- }
398
- }
399
- });
400
- var UpdateProjectInputModel = defineSchemaModel2({
401
- name: "UpdateProjectInput",
402
- description: "Input for updating a project",
403
- fields: {
404
- projectId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
405
- name: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
406
- description: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
407
- slug: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
408
- isPublic: { type: ScalarTypeEnum2.Boolean(), isOptional: true },
409
- tags: {
410
- type: ScalarTypeEnum2.String_unsecure(),
411
- isArray: true,
412
- isOptional: true
413
- },
414
- status: { type: ProjectStatusSchemaEnum, isOptional: true }
415
- }
416
- });
417
- var GetProjectInputModel = defineSchemaModel2({
418
- name: "GetProjectInput",
419
- fields: {
420
- projectId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false }
421
- }
422
- });
423
- var DeleteProjectInputModel = defineSchemaModel2({
424
- name: "DeleteProjectInput",
425
- fields: {
426
- projectId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false }
427
- }
428
- });
429
- var DeleteProjectOutputModel = defineSchemaModel2({
430
- name: "DeleteProjectOutput",
431
- fields: {
432
- success: { type: ScalarTypeEnum2.Boolean(), isOptional: false }
433
- }
434
- });
435
- var ProjectDeletedPayloadModel = defineSchemaModel2({
436
- name: "ProjectDeletedPayload",
437
- fields: {
438
- projectId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false }
439
- }
440
- });
441
- var ListProjectsInputModel = defineSchemaModel2({
442
- name: "ListProjectsInput",
443
- description: "Input for listing projects",
444
- fields: {
445
- status: { type: ProjectStatusFilterEnum, isOptional: true },
446
- search: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
447
- limit: {
448
- type: ScalarTypeEnum2.Int_unsecure(),
449
- isOptional: true,
450
- defaultValue: 20
451
- },
452
- offset: {
453
- type: ScalarTypeEnum2.Int_unsecure(),
454
- isOptional: true,
455
- defaultValue: 0
456
- }
457
- }
458
- });
459
- var ListProjectsOutputModel = defineSchemaModel2({
460
- name: "ListProjectsOutput",
461
- description: "Output for listing projects",
462
- fields: {
463
- projects: { type: ProjectModel, isArray: true, isOptional: false },
464
- total: { type: ScalarTypeEnum2.Int_unsecure(), isOptional: false }
465
- }
466
- });
467
-
468
- // src/project/project.operations.ts
469
- import {
470
- defineCommand,
471
- defineQuery
472
- } from "@contractspec/lib.contracts-spec/operations";
473
- var OWNERS = ["example.saas-boilerplate"];
474
- var CreateProjectContract = defineCommand({
475
- meta: {
476
- key: "saas.project.create",
477
- version: "1.0.0",
478
- stability: "stable",
479
- owners: [...OWNERS],
480
- tags: ["saas", "project", "create"],
481
- description: "Create a new project in the organization.",
482
- goal: "Allow users to create projects for organizing work.",
483
- context: "Called from project creation UI or API."
484
- },
485
- io: {
486
- input: CreateProjectInputModel,
487
- output: ProjectModel,
488
- errors: {
489
- SLUG_EXISTS: {
490
- description: "A project with this slug already exists",
491
- http: 409,
492
- gqlCode: "SLUG_EXISTS",
493
- when: "Slug is already taken in the organization"
494
- },
495
- LIMIT_REACHED: {
496
- description: "Project limit reached for this plan",
497
- http: 403,
498
- gqlCode: "LIMIT_REACHED",
499
- when: "Organization has reached project limit"
500
- }
501
- }
502
- },
503
- policy: {
504
- auth: "user"
505
- },
506
- sideEffects: {
507
- emits: [
508
- {
509
- key: "project.created",
510
- version: "1.0.0",
511
- when: "Project is created",
512
- payload: ProjectModel
513
- }
514
- ],
515
- audit: ["project.created"]
516
- },
517
- acceptance: {
518
- scenarios: [
519
- {
520
- key: "create-project-happy-path",
521
- given: ["User is authenticated"],
522
- when: ["User creates project"],
523
- then: ["Project is created", "ProjectCreated event is emitted"]
524
- }
525
- ],
526
- examples: [
527
- {
528
- key: "create-basic",
529
- input: { name: "Website Redesign", slug: "website-redesign" },
530
- output: { id: "proj-123", name: "Website Redesign", isArchived: false }
531
- }
532
- ]
533
- }
534
- });
535
- var GetProjectContract = defineQuery({
536
- meta: {
537
- key: "saas.project.get",
538
- version: "1.0.0",
539
- stability: "stable",
540
- owners: [...OWNERS],
541
- tags: ["saas", "project", "get"],
542
- description: "Get a project by ID.",
543
- goal: "Retrieve project details.",
544
- context: "Project detail page, API calls."
545
- },
546
- io: {
547
- input: GetProjectInputModel,
548
- output: ProjectModel,
549
- errors: {
550
- NOT_FOUND: {
551
- description: "Project not found",
552
- http: 404,
553
- gqlCode: "NOT_FOUND",
554
- when: "Project ID is invalid or user lacks access"
555
- }
556
- }
557
- },
558
- policy: {
559
- auth: "user"
560
- },
561
- acceptance: {
562
- scenarios: [
563
- {
564
- key: "get-project-happy-path",
565
- given: ["Project exists"],
566
- when: ["User requests project"],
567
- then: ["Project details are returned"]
568
- }
569
- ],
570
- examples: [
571
- {
572
- key: "get-existing",
573
- input: { projectId: "proj-123" },
574
- output: { id: "proj-123", name: "Website Redesign" }
575
- }
576
- ]
577
- }
578
- });
579
- var UpdateProjectContract = defineCommand({
580
- meta: {
581
- key: "saas.project.update",
582
- version: "1.0.0",
583
- stability: "stable",
584
- owners: [...OWNERS],
585
- tags: ["saas", "project", "update"],
586
- description: "Update project details.",
587
- goal: "Allow project owners/editors to modify project.",
588
- context: "Project settings page."
589
- },
590
- io: {
591
- input: UpdateProjectInputModel,
592
- output: ProjectModel
593
- },
594
- policy: {
595
- auth: "user"
596
- },
597
- sideEffects: {
598
- emits: [
599
- {
600
- key: "project.updated",
601
- version: "1.0.0",
602
- when: "Project is updated",
603
- payload: ProjectModel
604
- }
605
- ],
606
- audit: ["project.updated"]
607
- },
608
- acceptance: {
609
- scenarios: [
610
- {
611
- key: "update-project-happy-path",
612
- given: ["Project exists"],
613
- when: ["User updates description"],
614
- then: ["Project is updated", "ProjectUpdated event is emitted"]
615
- }
616
- ],
617
- examples: [
618
- {
619
- key: "update-desc",
620
- input: { projectId: "proj-123", description: "New description" },
621
- output: { id: "proj-123", description: "New description" }
622
- }
623
- ]
624
- }
625
- });
626
- var DeleteProjectContract = defineCommand({
627
- meta: {
628
- key: "saas.project.delete",
629
- version: "1.0.0",
630
- stability: "stable",
631
- owners: [...OWNERS],
632
- tags: ["saas", "project", "delete"],
633
- description: "Delete a project (soft delete).",
634
- goal: "Allow project owners to remove projects.",
635
- context: "Project settings page."
636
- },
637
- io: {
638
- input: DeleteProjectInputModel,
639
- output: DeleteProjectOutputModel
640
- },
641
- policy: {
642
- auth: "user"
643
- },
644
- sideEffects: {
645
- emits: [
646
- {
647
- key: "project.deleted",
648
- version: "1.0.0",
649
- when: "Project is deleted",
650
- payload: ProjectDeletedPayloadModel
651
- }
652
- ],
653
- audit: ["project.deleted"]
654
- },
655
- acceptance: {
656
- scenarios: [
657
- {
658
- key: "delete-project-happy-path",
659
- given: ["Project exists"],
660
- when: ["User deletes project"],
661
- then: ["Project is deleted", "ProjectDeleted event is emitted"]
662
- }
663
- ],
664
- examples: [
665
- {
666
- key: "delete-existing",
667
- input: { projectId: "proj-123" },
668
- output: { success: true }
669
- }
670
- ]
671
- }
672
- });
673
- var ListProjectsContract = defineQuery({
674
- meta: {
675
- key: "saas.project.list",
676
- version: "1.0.0",
677
- stability: "stable",
678
- owners: [...OWNERS],
679
- tags: ["saas", "project", "list"],
680
- description: "List projects in the organization.",
681
- goal: "Show all projects user has access to.",
682
- context: "Project list page, dashboard."
683
- },
684
- io: {
685
- input: ListProjectsInputModel,
686
- output: ListProjectsOutputModel
687
- },
688
- policy: {
689
- auth: "user"
690
- },
691
- acceptance: {
692
- scenarios: [
693
- {
694
- key: "list-projects-happy-path",
695
- given: ["Projects exist"],
696
- when: ["User lists projects"],
697
- then: ["List of projects is returned"]
698
- }
699
- ],
700
- examples: [
701
- {
702
- key: "list-all",
703
- input: { limit: 10 },
704
- output: { items: [], total: 5 }
705
- }
706
- ]
707
- }
708
- });
709
-
710
- // src/project/project.presentation.ts
711
- import {
712
- definePresentation,
713
- StabilityEnum
714
- } from "@contractspec/lib.contracts-spec";
715
- var ProjectListPresentation = definePresentation({
716
- meta: {
717
- key: "saas.project.list",
718
- version: "1.0.0",
719
- title: "Project List",
720
- description: "List view of projects with status, tags, and last updated info",
721
- domain: "saas-boilerplate",
722
- owners: ["@saas-team"],
723
- tags: ["project", "list", "dashboard"],
724
- stability: StabilityEnum.Beta,
725
- goal: "Browse and manage projects",
726
- context: "Project list page"
727
- },
728
- source: {
729
- type: "component",
730
- framework: "react",
731
- componentKey: "ProjectListView",
732
- props: ProjectModel
733
- },
734
- targets: ["react", "markdown", "application/json"],
735
- policy: {
736
- flags: ["saas.projects.enabled"]
737
- }
738
- });
739
- var ProjectDetailPresentation = definePresentation({
740
- meta: {
741
- key: "saas.project.detail",
742
- version: "1.0.0",
743
- title: "Project Details",
744
- description: "Detailed view of a project with settings and activity",
745
- domain: "saas-boilerplate",
746
- owners: ["@saas-team"],
747
- tags: ["project", "detail"],
748
- stability: StabilityEnum.Beta,
749
- goal: "View and edit project details",
750
- context: "Project detail page"
751
- },
752
- source: {
753
- type: "component",
754
- framework: "react",
755
- componentKey: "ProjectDetailView"
756
- },
757
- targets: ["react", "markdown"],
758
- policy: {
759
- flags: ["saas.projects.enabled"]
760
- }
761
- });
762
- export {
763
- mockUpdateProjectHandler,
764
- mockListProjectsHandler,
765
- mockGetProjectHandler,
766
- mockDeleteProjectHandler,
767
- mockCreateProjectHandler,
768
- UpdateProjectInputModel,
769
- UpdateProjectContract,
770
- ProjectUpdatedEvent,
771
- ProjectStatusSchemaEnum,
772
- ProjectStatusFilterEnum,
773
- ProjectStatusEnum,
774
- ProjectModel,
775
- ProjectMemberEntity,
776
- ProjectListPresentation,
777
- ProjectEntity,
778
- ProjectDetailPresentation,
779
- ProjectDeletedPayloadModel,
780
- ProjectDeletedEvent,
781
- ProjectCreatedEvent,
782
- ProjectArchivedEvent,
783
- ListProjectsOutputModel,
784
- ListProjectsInputModel,
785
- ListProjectsContract,
786
- GetProjectInputModel,
787
- GetProjectContract,
788
- DeleteProjectOutputModel,
789
- DeleteProjectInputModel,
790
- DeleteProjectContract,
791
- CreateProjectInputModel,
792
- CreateProjectContract
793
- };
1
+ var A=[{id:"proj-1",name:"Marketing Website",description:"Main company website redesign project",slug:"marketing-website",organizationId:"demo-org",createdBy:"user-1",status:"ACTIVE",isPublic:!1,tags:["marketing","website","redesign"],createdAt:new Date("2024-01-15T10:00:00Z"),updatedAt:new Date("2024-03-20T14:30:00Z")},{id:"proj-2",name:"Mobile App v2",description:"Next generation mobile application",slug:"mobile-app-v2",organizationId:"demo-org",createdBy:"user-2",status:"ACTIVE",isPublic:!1,tags:["mobile","app","v2"],createdAt:new Date("2024-02-01T09:00:00Z"),updatedAt:new Date("2024-04-05T11:15:00Z")},{id:"proj-3",name:"API Integration",description:"Third-party API integration project",slug:"api-integration",organizationId:"demo-org",createdBy:"user-1",status:"DRAFT",isPublic:!1,tags:["api","integration"],createdAt:new Date("2024-03-10T08:00:00Z"),updatedAt:new Date("2024-03-10T08:00:00Z")},{id:"proj-4",name:"Analytics Dashboard",description:"Internal analytics and reporting dashboard",slug:"analytics-dashboard",organizationId:"demo-org",createdBy:"user-3",status:"ARCHIVED",isPublic:!0,tags:["analytics","dashboard","reporting"],createdAt:new Date("2023-10-01T12:00:00Z"),updatedAt:new Date("2024-02-28T16:45:00Z")}],DH={id:"sub-1",organizationId:"demo-org",planId:"pro",planName:"Professional",status:"ACTIVE",currentPeriodStart:new Date("2024-04-01T00:00:00Z"),currentPeriodEnd:new Date("2024-05-01T00:00:00Z"),limits:{projects:25,users:10,storage:50,apiCalls:1e5},usage:{projects:4,users:5,storage:12.5,apiCalls:45230}},PH={organizationId:"demo-org",period:"current_month",apiCalls:{total:45230,limit:1e5,percentUsed:45.23},storage:{totalGb:12.5,limitGb:50,percentUsed:25},activeProjects:4,activeUsers:5,breakdown:[{date:"2024-04-01",apiCalls:3200,storageGb:12.1},{date:"2024-04-02",apiCalls:2800,storageGb:12.2},{date:"2024-04-03",apiCalls:4100,storageGb:12.3},{date:"2024-04-04",apiCalls:3600,storageGb:12.4},{date:"2024-04-05",apiCalls:3800,storageGb:12.5}]};async function r(L){let{status:k,search:U,limit:_=20,offset:V=0}=L,P=[...A];if(k&&k!=="all")P=P.filter((g)=>g.status===k);if(U){let g=U.toLowerCase();P=P.filter((B)=>B.name.toLowerCase().includes(g)||B.description?.toLowerCase().includes(g)||B.tags.some((o)=>o.toLowerCase().includes(g)))}P.sort((g,B)=>B.updatedAt.getTime()-g.updatedAt.getTime());let s=P.length;return{projects:P.slice(V,V+_),total:s}}async function T(L){let k=A.find((U)=>U.id===L.projectId);if(!k)throw Error("NOT_FOUND");return k}async function y(L,k){if(L.slug){if(A.some((V)=>V.slug===L.slug))throw Error("SLUG_EXISTS")}let U=new Date;return{id:`proj-${Date.now()}`,name:L.name,description:L.description,slug:L.slug??L.name.toLowerCase().replace(/\s+/g,"-"),organizationId:k.organizationId,createdBy:k.userId,status:"DRAFT",isPublic:L.isPublic??!1,tags:L.tags??[],createdAt:U,updatedAt:U}}async function f(L){let k=A.find((U)=>U.id===L.projectId);if(!k)throw Error("NOT_FOUND");return{...k,name:L.name??k.name,description:L.description??k.description,slug:L.slug??k.slug,isPublic:L.isPublic??k.isPublic,tags:L.tags??k.tags,status:L.status??k.status,updatedAt:new Date}}async function E(L){if(!A.find((U)=>U.id===L.projectId))throw Error("NOT_FOUND");return{success:!0}}import{defineEntity as C,defineEntityEnum as t,field as I,index as X}from"@contractspec/lib.schema";var R=t({name:"ProjectStatus",values:["DRAFT","ACTIVE","ARCHIVED","DELETED"],schema:"saas_app",description:"Status of a project."}),m=C({name:"Project",description:"A project belonging to an organization.",schema:"saas_app",map:"project",fields:{id:I.id({description:"Unique project ID"}),name:I.string({description:"Project name"}),description:I.string({isOptional:!0,description:"Project description"}),slug:I.string({isOptional:!0,description:"URL-friendly identifier"}),organizationId:I.foreignKey({description:"Owning organization"}),createdBy:I.foreignKey({description:"User who created the project"}),status:I.enum("ProjectStatus",{default:"DRAFT"}),isPublic:I.boolean({default:!1,description:"Whether project is publicly visible"}),settings:I.json({isOptional:!0,description:"Project-specific settings"}),tags:I.string({isArray:!0,description:"Project tags"}),metadata:I.json({isOptional:!0}),createdAt:I.createdAt(),updatedAt:I.updatedAt(),archivedAt:I.dateTime({isOptional:!0})},indexes:[X.on(["organizationId","status"]),X.on(["organizationId","createdAt"]),X.unique(["organizationId","slug"])],enums:[R]}),S=C({name:"ProjectMember",description:"User access to a specific project.",schema:"saas_app",map:"project_member",fields:{id:I.id(),projectId:I.foreignKey(),userId:I.foreignKey(),role:I.string({description:"Role in project (owner, editor, viewer)"}),addedBy:I.string({isOptional:!0}),createdAt:I.createdAt()},indexes:[X.unique(["projectId","userId"])]});import{defineEnum as b}from"@contractspec/lib.schema";var Y=b("ProjectStatus",["DRAFT","ACTIVE","ARCHIVED","DELETED"]),v=b("ProjectStatusFilter",["DRAFT","ACTIVE","ARCHIVED","all"]);import{defineEvent as Z}from"@contractspec/lib.contracts-spec";import{defineSchemaModel as $,ScalarTypeEnum as G}from"@contractspec/lib.schema";var d=$({name:"ProjectCreatedPayload",description:"Payload when a project is created",fields:{projectId:{type:G.String_unsecure(),isOptional:!1},name:{type:G.String_unsecure(),isOptional:!1},organizationId:{type:G.String_unsecure(),isOptional:!1},createdBy:{type:G.String_unsecure(),isOptional:!1},createdAt:{type:G.DateTime(),isOptional:!1}}}),u=$({name:"ProjectUpdatedPayload",description:"Payload when a project is updated",fields:{projectId:{type:G.String_unsecure(),isOptional:!1},updatedFields:{type:G.String_unsecure(),isArray:!0,isOptional:!1},updatedBy:{type:G.String_unsecure(),isOptional:!1},updatedAt:{type:G.DateTime(),isOptional:!1}}}),c=$({name:"ProjectDeletedPayload",description:"Payload when a project is deleted",fields:{projectId:{type:G.String_unsecure(),isOptional:!1},organizationId:{type:G.String_unsecure(),isOptional:!1},deletedBy:{type:G.String_unsecure(),isOptional:!1},deletedAt:{type:G.DateTime(),isOptional:!1}}}),i=$({name:"ProjectArchivedPayload",description:"Payload when a project is archived",fields:{projectId:{type:G.String_unsecure(),isOptional:!1},archivedBy:{type:G.String_unsecure(),isOptional:!1},archivedAt:{type:G.DateTime(),isOptional:!1}}}),p=Z({meta:{key:"project.created",version:"1.0.0",description:"A new project has been created.",stability:"stable",owners:["@saas-team"],tags:["project","created"]},payload:d}),l=Z({meta:{key:"project.updated",version:"1.0.0",description:"A project has been updated.",stability:"stable",owners:["@saas-team"],tags:["project","updated"]},payload:u}),n=Z({meta:{key:"project.deleted",version:"1.0.0",description:"A project has been deleted.",stability:"stable",owners:["@saas-team"],tags:["project","deleted"]},payload:c}),a=Z({meta:{key:"project.archived",version:"1.0.0",description:"A project has been archived.",stability:"stable",owners:["@saas-team"],tags:["project","archived"]},payload:i});import{defineSchemaModel as D,ScalarTypeEnum as H}from"@contractspec/lib.schema";var z=D({name:"Project",description:"A project within an organization",fields:{id:{type:H.String_unsecure(),isOptional:!1},name:{type:H.String_unsecure(),isOptional:!1},description:{type:H.String_unsecure(),isOptional:!0},slug:{type:H.String_unsecure(),isOptional:!0},organizationId:{type:H.String_unsecure(),isOptional:!1},createdBy:{type:H.String_unsecure(),isOptional:!1},status:{type:Y,isOptional:!1},isPublic:{type:H.Boolean(),isOptional:!1},tags:{type:H.String_unsecure(),isArray:!0,isOptional:!1},createdAt:{type:H.DateTime(),isOptional:!1},updatedAt:{type:H.DateTime(),isOptional:!1}}}),w=D({name:"CreateProjectInput",description:"Input for creating a project",fields:{name:{type:H.NonEmptyString(),isOptional:!1},description:{type:H.String_unsecure(),isOptional:!0},slug:{type:H.String_unsecure(),isOptional:!0},isPublic:{type:H.Boolean(),isOptional:!0},tags:{type:H.String_unsecure(),isArray:!0,isOptional:!0}}}),x=D({name:"UpdateProjectInput",description:"Input for updating a project",fields:{projectId:{type:H.String_unsecure(),isOptional:!1},name:{type:H.String_unsecure(),isOptional:!0},description:{type:H.String_unsecure(),isOptional:!0},slug:{type:H.String_unsecure(),isOptional:!0},isPublic:{type:H.Boolean(),isOptional:!0},tags:{type:H.String_unsecure(),isArray:!0,isOptional:!0},status:{type:Y,isOptional:!0}}}),Q=D({name:"GetProjectInput",fields:{projectId:{type:H.String_unsecure(),isOptional:!1}}}),q=D({name:"DeleteProjectInput",fields:{projectId:{type:H.String_unsecure(),isOptional:!1}}}),j=D({name:"DeleteProjectOutput",fields:{success:{type:H.Boolean(),isOptional:!1}}}),J=D({name:"ProjectDeletedPayload",fields:{projectId:{type:H.String_unsecure(),isOptional:!1}}}),K=D({name:"ListProjectsInput",description:"Input for listing projects",fields:{status:{type:v,isOptional:!0},search:{type:H.String_unsecure(),isOptional:!0},limit:{type:H.Int_unsecure(),isOptional:!0,defaultValue:20},offset:{type:H.Int_unsecure(),isOptional:!0,defaultValue:0}}}),N=D({name:"ListProjectsOutput",description:"Output for listing projects",fields:{projects:{type:z,isArray:!0,isOptional:!1},total:{type:H.Int_unsecure(),isOptional:!1}}});import{defineCommand as W,defineQuery as O}from"@contractspec/lib.contracts-spec/operations";var F=["example.saas-boilerplate"],e=W({meta:{key:"saas.project.create",version:"1.0.0",stability:"stable",owners:[...F],tags:["saas","project","create"],description:"Create a new project in the organization.",goal:"Allow users to create projects for organizing work.",context:"Called from project creation UI or API."},io:{input:w,output:z,errors:{SLUG_EXISTS:{description:"A project with this slug already exists",http:409,gqlCode:"SLUG_EXISTS",when:"Slug is already taken in the organization"},LIMIT_REACHED:{description:"Project limit reached for this plan",http:403,gqlCode:"LIMIT_REACHED",when:"Organization has reached project limit"}}},policy:{auth:"user"},sideEffects:{emits:[{key:"project.created",version:"1.0.0",when:"Project is created",payload:z}],audit:["project.created"]},acceptance:{scenarios:[{key:"create-project-happy-path",given:["User is authenticated"],when:["User creates project"],then:["Project is created","ProjectCreated event is emitted"]}],examples:[{key:"create-basic",input:{name:"Website Redesign",slug:"website-redesign"},output:{id:"proj-123",name:"Website Redesign",isArchived:!1}}]}}),HH=O({meta:{key:"saas.project.get",version:"1.0.0",stability:"stable",owners:[...F],tags:["saas","project","get"],description:"Get a project by ID.",goal:"Retrieve project details.",context:"Project detail page, API calls."},io:{input:Q,output:z,errors:{NOT_FOUND:{description:"Project not found",http:404,gqlCode:"NOT_FOUND",when:"Project ID is invalid or user lacks access"}}},policy:{auth:"user"},acceptance:{scenarios:[{key:"get-project-happy-path",given:["Project exists"],when:["User requests project"],then:["Project details are returned"]}],examples:[{key:"get-existing",input:{projectId:"proj-123"},output:{id:"proj-123",name:"Website Redesign"}}]}}),LH=W({meta:{key:"saas.project.update",version:"1.0.0",stability:"stable",owners:[...F],tags:["saas","project","update"],description:"Update project details.",goal:"Allow project owners/editors to modify project.",context:"Project settings page."},io:{input:x,output:z},policy:{auth:"user"},sideEffects:{emits:[{key:"project.updated",version:"1.0.0",when:"Project is updated",payload:z}],audit:["project.updated"]},acceptance:{scenarios:[{key:"update-project-happy-path",given:["Project exists"],when:["User updates description"],then:["Project is updated","ProjectUpdated event is emitted"]}],examples:[{key:"update-desc",input:{projectId:"proj-123",description:"New description"},output:{id:"proj-123",description:"New description"}}]}}),IH=W({meta:{key:"saas.project.delete",version:"1.0.0",stability:"stable",owners:[...F],tags:["saas","project","delete"],description:"Delete a project (soft delete).",goal:"Allow project owners to remove projects.",context:"Project settings page."},io:{input:q,output:j},policy:{auth:"user"},sideEffects:{emits:[{key:"project.deleted",version:"1.0.0",when:"Project is deleted",payload:J}],audit:["project.deleted"]},acceptance:{scenarios:[{key:"delete-project-happy-path",given:["Project exists"],when:["User deletes project"],then:["Project is deleted","ProjectDeleted event is emitted"]}],examples:[{key:"delete-existing",input:{projectId:"proj-123"},output:{success:!0}}]}}),kH=O({meta:{key:"saas.project.list",version:"1.0.0",stability:"stable",owners:[...F],tags:["saas","project","list"],description:"List projects in the organization.",goal:"Show all projects user has access to.",context:"Project list page, dashboard."},io:{input:K,output:N},policy:{auth:"user"},acceptance:{scenarios:[{key:"list-projects-happy-path",given:["Projects exist"],when:["User lists projects"],then:["List of projects is returned"]}],examples:[{key:"list-all",input:{limit:10},output:{items:[],total:5}}]}});import{definePresentation as h,StabilityEnum as M}from"@contractspec/lib.contracts-spec";var GH=h({meta:{key:"saas.project.list",version:"1.0.0",title:"Project List",description:"List view of projects with status, tags, and last updated info",domain:"saas-boilerplate",owners:["@saas-team"],tags:["project","list","dashboard"],stability:M.Beta,goal:"Browse and manage projects",context:"Project list page"},source:{type:"component",framework:"react",componentKey:"ProjectListView",props:z},targets:["react","markdown","application/json"],policy:{flags:["saas.projects.enabled"]}}),UH=h({meta:{key:"saas.project.detail",version:"1.0.0",title:"Project Details",description:"Detailed view of a project with settings and activity",domain:"saas-boilerplate",owners:["@saas-team"],tags:["project","detail"],stability:M.Beta,goal:"View and edit project details",context:"Project detail page"},source:{type:"component",framework:"react",componentKey:"ProjectDetailView"},targets:["react","markdown"],policy:{flags:["saas.projects.enabled"]}});export{f as mockUpdateProjectHandler,r as mockListProjectsHandler,T as mockGetProjectHandler,E as mockDeleteProjectHandler,y as mockCreateProjectHandler,x as UpdateProjectInputModel,LH as UpdateProjectContract,l as ProjectUpdatedEvent,Y as ProjectStatusSchemaEnum,v as ProjectStatusFilterEnum,R as ProjectStatusEnum,z as ProjectModel,S as ProjectMemberEntity,GH as ProjectListPresentation,m as ProjectEntity,UH as ProjectDetailPresentation,J as ProjectDeletedPayloadModel,n as ProjectDeletedEvent,p as ProjectCreatedEvent,a as ProjectArchivedEvent,N as ListProjectsOutputModel,K as ListProjectsInputModel,kH as ListProjectsContract,Q as GetProjectInputModel,HH as GetProjectContract,j as DeleteProjectOutputModel,q as DeleteProjectInputModel,IH as DeleteProjectContract,w as CreateProjectInputModel,e as CreateProjectContract};