@contractspec/example.service-business-os 1.56.1 → 1.58.0

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 (155) hide show
  1. package/dist/browser/client/client.operations.js +72 -0
  2. package/dist/browser/client/client.schema.js +31 -0
  3. package/dist/browser/client/index.js +74 -0
  4. package/dist/browser/docs/index.js +96 -0
  5. package/dist/browser/docs/service-business-os.docblock.js +96 -0
  6. package/dist/browser/entities/index.js +246 -0
  7. package/dist/browser/events.js +135 -0
  8. package/dist/browser/example.js +39 -0
  9. package/dist/browser/handlers/index.js +5 -0
  10. package/dist/browser/index.js +752 -0
  11. package/dist/browser/invoice/index.js +77 -0
  12. package/dist/browser/invoice/invoice.operations.js +75 -0
  13. package/dist/browser/invoice/invoice.schema.js +34 -0
  14. package/dist/browser/job/index.js +175 -0
  15. package/dist/browser/job/job.operations.js +172 -0
  16. package/dist/browser/job/job.schema.js +41 -0
  17. package/dist/browser/operations/index.js +506 -0
  18. package/dist/browser/payment/index.js +69 -0
  19. package/dist/browser/payment/payment.operations.js +67 -0
  20. package/dist/browser/payment/payment.schema.js +30 -0
  21. package/dist/browser/presentations/index.js +13 -0
  22. package/dist/browser/presentations.js +172 -0
  23. package/dist/browser/quote/index.js +122 -0
  24. package/dist/browser/quote/quote.operations.js +119 -0
  25. package/dist/browser/quote/quote.schema.js +45 -0
  26. package/dist/browser/service-business-os.capability.js +28 -0
  27. package/dist/browser/service.feature.js +74 -0
  28. package/dist/client/client.operations.d.ts +54 -60
  29. package/dist/client/client.operations.d.ts.map +1 -1
  30. package/dist/client/client.operations.js +71 -51
  31. package/dist/client/client.schema.d.ts +54 -59
  32. package/dist/client/client.schema.d.ts.map +1 -1
  33. package/dist/client/client.schema.js +30 -75
  34. package/dist/client/index.d.ts +6 -3
  35. package/dist/client/index.d.ts.map +1 -0
  36. package/dist/client/index.js +74 -3
  37. package/dist/docs/index.d.ts +2 -1
  38. package/dist/docs/index.d.ts.map +1 -0
  39. package/dist/docs/index.js +97 -1
  40. package/dist/docs/service-business-os.docblock.d.ts +2 -1
  41. package/dist/docs/service-business-os.docblock.d.ts.map +1 -0
  42. package/dist/docs/service-business-os.docblock.js +52 -64
  43. package/dist/entities/index.d.ts +156 -161
  44. package/dist/entities/index.d.ts.map +1 -1
  45. package/dist/entities/index.js +236 -278
  46. package/dist/events.d.ts +253 -259
  47. package/dist/events.d.ts.map +1 -1
  48. package/dist/events.js +123 -217
  49. package/dist/example.d.ts +2 -6
  50. package/dist/example.d.ts.map +1 -1
  51. package/dist/example.js +37 -50
  52. package/dist/handlers/index.d.ts +11 -16
  53. package/dist/handlers/index.d.ts.map +1 -1
  54. package/dist/handlers/index.js +5 -5
  55. package/dist/index.d.ts +13 -18
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +752 -18
  58. package/dist/invoice/index.d.ts +6 -3
  59. package/dist/invoice/index.d.ts.map +1 -0
  60. package/dist/invoice/index.js +77 -3
  61. package/dist/invoice/invoice.operations.d.ts +54 -60
  62. package/dist/invoice/invoice.operations.d.ts.map +1 -1
  63. package/dist/invoice/invoice.operations.js +74 -55
  64. package/dist/invoice/invoice.schema.d.ts +54 -59
  65. package/dist/invoice/invoice.schema.d.ts.map +1 -1
  66. package/dist/invoice/invoice.schema.js +33 -75
  67. package/dist/job/index.d.ts +6 -3
  68. package/dist/job/index.d.ts.map +1 -0
  69. package/dist/job/index.js +175 -3
  70. package/dist/job/job.operations.d.ts +220 -226
  71. package/dist/job/job.operations.d.ts.map +1 -1
  72. package/dist/job/job.operations.js +167 -169
  73. package/dist/job/job.schema.d.ts +67 -72
  74. package/dist/job/job.schema.d.ts.map +1 -1
  75. package/dist/job/job.schema.js +39 -95
  76. package/dist/node/client/client.operations.js +72 -0
  77. package/dist/node/client/client.schema.js +31 -0
  78. package/dist/node/client/index.js +74 -0
  79. package/dist/node/docs/index.js +96 -0
  80. package/dist/node/docs/service-business-os.docblock.js +96 -0
  81. package/dist/node/entities/index.js +246 -0
  82. package/dist/node/events.js +135 -0
  83. package/dist/node/example.js +39 -0
  84. package/dist/node/handlers/index.js +5 -0
  85. package/dist/node/index.js +752 -0
  86. package/dist/node/invoice/index.js +77 -0
  87. package/dist/node/invoice/invoice.operations.js +75 -0
  88. package/dist/node/invoice/invoice.schema.js +34 -0
  89. package/dist/node/job/index.js +175 -0
  90. package/dist/node/job/job.operations.js +172 -0
  91. package/dist/node/job/job.schema.js +41 -0
  92. package/dist/node/operations/index.js +506 -0
  93. package/dist/node/payment/index.js +69 -0
  94. package/dist/node/payment/payment.operations.js +67 -0
  95. package/dist/node/payment/payment.schema.js +30 -0
  96. package/dist/node/presentations/index.js +13 -0
  97. package/dist/node/presentations.js +172 -0
  98. package/dist/node/quote/index.js +122 -0
  99. package/dist/node/quote/quote.operations.js +119 -0
  100. package/dist/node/quote/quote.schema.js +45 -0
  101. package/dist/node/service-business-os.capability.js +28 -0
  102. package/dist/node/service.feature.js +74 -0
  103. package/dist/operations/index.d.ts +6 -16
  104. package/dist/operations/index.d.ts.map +1 -0
  105. package/dist/operations/index.js +506 -16
  106. package/dist/payment/index.d.ts +6 -3
  107. package/dist/payment/index.d.ts.map +1 -0
  108. package/dist/payment/index.js +69 -3
  109. package/dist/payment/payment.operations.d.ts +50 -56
  110. package/dist/payment/payment.operations.d.ts.map +1 -1
  111. package/dist/payment/payment.operations.js +66 -51
  112. package/dist/payment/payment.schema.d.ts +50 -55
  113. package/dist/payment/payment.schema.d.ts.map +1 -1
  114. package/dist/payment/payment.schema.js +29 -71
  115. package/dist/presentations/index.d.ts +1 -4
  116. package/dist/presentations/index.d.ts.map +1 -1
  117. package/dist/presentations/index.js +13 -17
  118. package/dist/presentations.d.ts +7 -12
  119. package/dist/presentations.d.ts.map +1 -1
  120. package/dist/presentations.js +166 -172
  121. package/dist/quote/index.d.ts +6 -3
  122. package/dist/quote/index.d.ts.map +1 -0
  123. package/dist/quote/index.js +122 -3
  124. package/dist/quote/quote.operations.d.ts +120 -126
  125. package/dist/quote/quote.operations.d.ts.map +1 -1
  126. package/dist/quote/quote.operations.js +117 -96
  127. package/dist/quote/quote.schema.d.ts +83 -88
  128. package/dist/quote/quote.schema.d.ts.map +1 -1
  129. package/dist/quote/quote.schema.js +43 -111
  130. package/dist/service-business-os.capability.d.ts +2 -7
  131. package/dist/service-business-os.capability.d.ts.map +1 -1
  132. package/dist/service-business-os.capability.js +29 -29
  133. package/dist/service.feature.d.ts +1 -6
  134. package/dist/service.feature.d.ts.map +1 -1
  135. package/dist/service.feature.js +73 -164
  136. package/package.json +301 -64
  137. package/dist/client/client.operations.js.map +0 -1
  138. package/dist/client/client.schema.js.map +0 -1
  139. package/dist/docs/service-business-os.docblock.js.map +0 -1
  140. package/dist/entities/index.js.map +0 -1
  141. package/dist/events.js.map +0 -1
  142. package/dist/example.js.map +0 -1
  143. package/dist/handlers/index.js.map +0 -1
  144. package/dist/invoice/invoice.operations.js.map +0 -1
  145. package/dist/invoice/invoice.schema.js.map +0 -1
  146. package/dist/job/job.operations.js.map +0 -1
  147. package/dist/job/job.schema.js.map +0 -1
  148. package/dist/payment/payment.operations.js.map +0 -1
  149. package/dist/payment/payment.schema.js.map +0 -1
  150. package/dist/presentations/index.js.map +0 -1
  151. package/dist/presentations.js.map +0 -1
  152. package/dist/quote/quote.operations.js.map +0 -1
  153. package/dist/quote/quote.schema.js.map +0 -1
  154. package/dist/service-business-os.capability.js.map +0 -1
  155. package/dist/service.feature.js.map +0 -1
@@ -0,0 +1,752 @@
1
+ // src/client/client.schema.ts
2
+ import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
3
+ var ClientModel = defineSchemaModel({
4
+ name: "Client",
5
+ description: "Client profile",
6
+ fields: {
7
+ id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
8
+ name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
9
+ contactEmail: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
10
+ phone: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
11
+ orgId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
12
+ ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
13
+ createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
14
+ }
15
+ });
16
+ var CreateClientInputModel = defineSchemaModel({
17
+ name: "CreateClientInput",
18
+ description: "Input for creating a client",
19
+ fields: {
20
+ name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
21
+ contactEmail: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
22
+ phone: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
23
+ orgId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
24
+ ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
25
+ metadata: { type: ScalarTypeEnum.JSON(), isOptional: true }
26
+ }
27
+ });
28
+
29
+ // src/client/client.operations.ts
30
+ import { defineCommand } from "@contractspec/lib.contracts";
31
+ var OWNERS = ["@examples.service-business-os"];
32
+ var CreateClientContract = defineCommand({
33
+ meta: {
34
+ key: "service.client.create",
35
+ version: "1.0.0",
36
+ stability: "stable",
37
+ owners: [...OWNERS],
38
+ tags: ["service-business-os", "client", "create"],
39
+ description: "Create a new client.",
40
+ goal: "Onboard clients.",
41
+ context: "CRM."
42
+ },
43
+ io: {
44
+ input: CreateClientInputModel,
45
+ output: ClientModel
46
+ },
47
+ policy: { auth: "user" },
48
+ acceptance: {
49
+ scenarios: [
50
+ {
51
+ key: "create-client-happy-path",
52
+ given: ["User is authenticated"],
53
+ when: ["User creates a new client"],
54
+ then: ["Client is created"]
55
+ }
56
+ ],
57
+ examples: [
58
+ {
59
+ key: "create-basic",
60
+ input: {
61
+ name: "Acme Corp",
62
+ email: "contact@acme.com",
63
+ phone: "555-0123"
64
+ },
65
+ output: { id: "client-123", name: "Acme Corp" }
66
+ }
67
+ ]
68
+ }
69
+ });
70
+ // src/quote/quote.schema.ts
71
+ import { defineSchemaModel as defineSchemaModel2, ScalarTypeEnum as ScalarTypeEnum2 } from "@contractspec/lib.schema";
72
+ var QuoteModel = defineSchemaModel2({
73
+ name: "Quote",
74
+ description: "Quote/proposal",
75
+ fields: {
76
+ id: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
77
+ clientId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
78
+ title: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
79
+ description: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
80
+ amount: { type: ScalarTypeEnum2.Float_unsecure(), isOptional: false },
81
+ currency: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
82
+ status: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
83
+ validUntil: { type: ScalarTypeEnum2.DateTime(), isOptional: true },
84
+ createdAt: { type: ScalarTypeEnum2.DateTime(), isOptional: false }
85
+ }
86
+ });
87
+ var CreateQuoteInputModel = defineSchemaModel2({
88
+ name: "CreateQuoteInput",
89
+ description: "Input for creating a quote",
90
+ fields: {
91
+ clientId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
92
+ title: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
93
+ description: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
94
+ amount: { type: ScalarTypeEnum2.Float_unsecure(), isOptional: false },
95
+ currency: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true },
96
+ validUntil: { type: ScalarTypeEnum2.DateTime(), isOptional: true },
97
+ orgId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
98
+ ownerId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false }
99
+ }
100
+ });
101
+ var AcceptQuoteInputModel = defineSchemaModel2({
102
+ name: "AcceptQuoteInput",
103
+ description: "Input for accepting a quote",
104
+ fields: {
105
+ quoteId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
106
+ acceptedBy: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
107
+ notes: { type: ScalarTypeEnum2.String_unsecure(), isOptional: true }
108
+ }
109
+ });
110
+
111
+ // src/quote/quote.operations.ts
112
+ import { defineCommand as defineCommand2 } from "@contractspec/lib.contracts";
113
+ var OWNERS2 = ["@examples.service-business-os"];
114
+ var CreateQuoteContract = defineCommand2({
115
+ meta: {
116
+ key: "service.quote.create",
117
+ version: "1.0.0",
118
+ stability: "stable",
119
+ owners: [...OWNERS2],
120
+ tags: ["service-business-os", "quote", "create"],
121
+ description: "Create a quote/proposal.",
122
+ goal: "Quote clients.",
123
+ context: "Quote creation."
124
+ },
125
+ io: {
126
+ input: CreateQuoteInputModel,
127
+ output: QuoteModel
128
+ },
129
+ policy: { auth: "user" },
130
+ acceptance: {
131
+ scenarios: [
132
+ {
133
+ key: "create-quote-happy-path",
134
+ given: ["Client exists"],
135
+ when: ["User creates quote"],
136
+ then: ["Quote is created"]
137
+ }
138
+ ],
139
+ examples: [
140
+ {
141
+ key: "create-proposal",
142
+ input: {
143
+ clientId: "client-123",
144
+ items: [{ description: "Project A", price: 5000 }]
145
+ },
146
+ output: { id: "quote-123", status: "draft", total: 5000 }
147
+ }
148
+ ]
149
+ }
150
+ });
151
+ var AcceptQuoteContract = defineCommand2({
152
+ meta: {
153
+ key: "service.quote.accept",
154
+ version: "1.0.0",
155
+ stability: "stable",
156
+ owners: [...OWNERS2],
157
+ tags: ["service-business-os", "quote", "accept"],
158
+ description: "Accept a quote.",
159
+ goal: "Confirm quote.",
160
+ context: "Quote acceptance."
161
+ },
162
+ io: {
163
+ input: AcceptQuoteInputModel,
164
+ output: QuoteModel
165
+ },
166
+ policy: { auth: "user" },
167
+ acceptance: {
168
+ scenarios: [
169
+ {
170
+ key: "accept-quote-happy-path",
171
+ given: ["Quote is open"],
172
+ when: ["Client accepts quote"],
173
+ then: ["Quote status becomes ACCEPTED"]
174
+ }
175
+ ],
176
+ examples: [
177
+ {
178
+ key: "client-accepts",
179
+ input: { quoteId: "quote-123", signature: "John Doe" },
180
+ output: { id: "quote-123", status: "accepted" }
181
+ }
182
+ ]
183
+ }
184
+ });
185
+ // src/job/job.schema.ts
186
+ import { defineSchemaModel as defineSchemaModel3, ScalarTypeEnum as ScalarTypeEnum3 } from "@contractspec/lib.schema";
187
+ var JobModel = defineSchemaModel3({
188
+ name: "Job",
189
+ description: "Scheduled job",
190
+ fields: {
191
+ id: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
192
+ quoteId: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
193
+ clientId: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
194
+ title: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
195
+ status: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
196
+ scheduledAt: { type: ScalarTypeEnum3.DateTime(), isOptional: true },
197
+ completedAt: { type: ScalarTypeEnum3.DateTime(), isOptional: true },
198
+ assignedTo: { type: ScalarTypeEnum3.String_unsecure(), isOptional: true }
199
+ }
200
+ });
201
+ var ScheduleJobInputModel = defineSchemaModel3({
202
+ name: "ScheduleJobInput",
203
+ description: "Input for scheduling a job",
204
+ fields: {
205
+ quoteId: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
206
+ scheduledAt: { type: ScalarTypeEnum3.DateTime(), isOptional: false },
207
+ assignedTo: { type: ScalarTypeEnum3.String_unsecure(), isOptional: true },
208
+ location: { type: ScalarTypeEnum3.JSON(), isOptional: true },
209
+ title: { type: ScalarTypeEnum3.String_unsecure(), isOptional: true }
210
+ }
211
+ });
212
+ var CompleteJobInputModel = defineSchemaModel3({
213
+ name: "CompleteJobInput",
214
+ description: "Input for completing a job",
215
+ fields: {
216
+ jobId: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
217
+ completedAt: { type: ScalarTypeEnum3.DateTime(), isOptional: true },
218
+ notes: { type: ScalarTypeEnum3.String_unsecure(), isOptional: true }
219
+ }
220
+ });
221
+
222
+ // src/job/job.operations.ts
223
+ import { defineCommand as defineCommand3, defineQuery } from "@contractspec/lib.contracts";
224
+ import { defineSchemaModel as defineSchemaModel4, ScalarTypeEnum as ScalarTypeEnum4 } from "@contractspec/lib.schema";
225
+ var OWNERS3 = ["@examples.service-business-os"];
226
+ var ListJobsInputModel = defineSchemaModel4({
227
+ name: "ListJobsInput",
228
+ description: "Input for listing jobs",
229
+ fields: {
230
+ status: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
231
+ clientId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
232
+ limit: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: true },
233
+ offset: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: true }
234
+ }
235
+ });
236
+ var ListJobsOutputModel = defineSchemaModel4({
237
+ name: "ListJobsOutput",
238
+ description: "Output for listing jobs",
239
+ fields: {
240
+ jobs: { type: JobModel, isOptional: false, isList: true },
241
+ total: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: false }
242
+ }
243
+ });
244
+ var ListJobsOperation = defineQuery({
245
+ meta: {
246
+ key: "service.job.list",
247
+ version: "1.0.0",
248
+ stability: "stable",
249
+ owners: [...OWNERS3],
250
+ tags: ["service-business-os", "job", "list", "query"],
251
+ description: "List all jobs with filtering",
252
+ goal: "Retrieve list of jobs",
253
+ context: "Job management"
254
+ },
255
+ io: {
256
+ input: ListJobsInputModel,
257
+ output: ListJobsOutputModel
258
+ },
259
+ policy: { auth: "user" },
260
+ acceptance: {
261
+ scenarios: [
262
+ {
263
+ key: "list-jobs-happy-path",
264
+ given: ["Jobs exist"],
265
+ when: ["User lists jobs"],
266
+ then: ["List of jobs is returned"]
267
+ }
268
+ ],
269
+ examples: [
270
+ {
271
+ key: "list-active",
272
+ input: { status: "scheduled", limit: 10 },
273
+ output: { jobs: [], total: 5 }
274
+ }
275
+ ]
276
+ }
277
+ });
278
+ var ScheduleJobContract = defineCommand3({
279
+ meta: {
280
+ key: "service.job.schedule",
281
+ version: "1.0.0",
282
+ stability: "stable",
283
+ owners: [...OWNERS3],
284
+ tags: ["service-business-os", "job", "schedule"],
285
+ description: "Schedule a job.",
286
+ goal: "Schedule work.",
287
+ context: "Job scheduling."
288
+ },
289
+ io: {
290
+ input: ScheduleJobInputModel,
291
+ output: JobModel
292
+ },
293
+ policy: { auth: "user" },
294
+ acceptance: {
295
+ scenarios: [
296
+ {
297
+ key: "schedule-job-happy-path",
298
+ given: ["Client exists"],
299
+ when: ["User schedules job"],
300
+ then: ["Job is created with status SCHEDULED"]
301
+ }
302
+ ],
303
+ examples: [
304
+ {
305
+ key: "schedule-repair",
306
+ input: {
307
+ clientId: "client-123",
308
+ date: "2025-01-20T10:00:00Z",
309
+ type: "repair"
310
+ },
311
+ output: { id: "job-456", status: "scheduled" }
312
+ }
313
+ ]
314
+ }
315
+ });
316
+ var CompleteJobContract = defineCommand3({
317
+ meta: {
318
+ key: "service.job.complete",
319
+ version: "1.0.0",
320
+ stability: "stable",
321
+ owners: [...OWNERS3],
322
+ tags: ["service-business-os", "job", "complete"],
323
+ description: "Mark a job as complete.",
324
+ goal: "Record job completion.",
325
+ context: "Job management."
326
+ },
327
+ io: {
328
+ input: CompleteJobInputModel,
329
+ output: JobModel
330
+ },
331
+ policy: { auth: "user" },
332
+ acceptance: {
333
+ scenarios: [
334
+ {
335
+ key: "complete-job-happy-path",
336
+ given: ["Job is scheduled"],
337
+ when: ["User completes job"],
338
+ then: ["Job status becomes COMPLETED"]
339
+ }
340
+ ],
341
+ examples: [
342
+ {
343
+ key: "mark-complete",
344
+ input: { jobId: "job-456", notes: "Done successfully" },
345
+ output: { id: "job-456", status: "completed" }
346
+ }
347
+ ]
348
+ }
349
+ });
350
+ // src/invoice/invoice.schema.ts
351
+ import { defineSchemaModel as defineSchemaModel5, ScalarTypeEnum as ScalarTypeEnum5 } from "@contractspec/lib.schema";
352
+ var InvoiceModel = defineSchemaModel5({
353
+ name: "Invoice",
354
+ description: "Invoice issued for a job",
355
+ fields: {
356
+ id: { type: ScalarTypeEnum5.String_unsecure(), isOptional: false },
357
+ jobId: { type: ScalarTypeEnum5.String_unsecure(), isOptional: false },
358
+ invoiceNumber: {
359
+ type: ScalarTypeEnum5.String_unsecure(),
360
+ isOptional: false
361
+ },
362
+ amount: { type: ScalarTypeEnum5.Float_unsecure(), isOptional: false },
363
+ currency: { type: ScalarTypeEnum5.String_unsecure(), isOptional: false },
364
+ status: { type: ScalarTypeEnum5.String_unsecure(), isOptional: false },
365
+ dueDate: { type: ScalarTypeEnum5.DateTime(), isOptional: true },
366
+ issuedAt: { type: ScalarTypeEnum5.DateTime(), isOptional: true },
367
+ paidAt: { type: ScalarTypeEnum5.DateTime(), isOptional: true }
368
+ }
369
+ });
370
+ var IssueInvoiceInputModel = defineSchemaModel5({
371
+ name: "IssueInvoiceInput",
372
+ description: "Input for issuing an invoice",
373
+ fields: {
374
+ jobId: { type: ScalarTypeEnum5.String_unsecure(), isOptional: false },
375
+ dueDate: { type: ScalarTypeEnum5.DateTime(), isOptional: true },
376
+ notes: { type: ScalarTypeEnum5.String_unsecure(), isOptional: true },
377
+ lineItems: { type: ScalarTypeEnum5.JSON(), isOptional: true }
378
+ }
379
+ });
380
+
381
+ // src/invoice/invoice.operations.ts
382
+ import { defineCommand as defineCommand4 } from "@contractspec/lib.contracts";
383
+ var OWNERS4 = ["@examples.service-business-os"];
384
+ var IssueInvoiceContract = defineCommand4({
385
+ meta: {
386
+ key: "service.invoice.issue",
387
+ version: "1.0.0",
388
+ stability: "stable",
389
+ owners: [...OWNERS4],
390
+ tags: ["service-business-os", "invoice", "issue"],
391
+ description: "Issue an invoice for a job.",
392
+ goal: "Bill clients.",
393
+ context: "Billing."
394
+ },
395
+ io: {
396
+ input: IssueInvoiceInputModel,
397
+ output: InvoiceModel
398
+ },
399
+ policy: { auth: "user" },
400
+ acceptance: {
401
+ scenarios: [
402
+ {
403
+ key: "issue-invoice-happy-path",
404
+ given: ["Job is complete"],
405
+ when: ["User issues invoice"],
406
+ then: ["Invoice is created and sent"]
407
+ }
408
+ ],
409
+ examples: [
410
+ {
411
+ key: "issue-standard",
412
+ input: {
413
+ jobId: "job-123",
414
+ dueDate: "2025-02-01",
415
+ items: [{ description: "Service", amount: 100 }]
416
+ },
417
+ output: { id: "inv-456", status: "issued", total: 100 }
418
+ }
419
+ ]
420
+ }
421
+ });
422
+ // src/payment/payment.schema.ts
423
+ import { defineSchemaModel as defineSchemaModel6, ScalarTypeEnum as ScalarTypeEnum6 } from "@contractspec/lib.schema";
424
+ var PaymentModel = defineSchemaModel6({
425
+ name: "Payment",
426
+ description: "Payment applied to invoice",
427
+ fields: {
428
+ id: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
429
+ invoiceId: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
430
+ amount: { type: ScalarTypeEnum6.Float_unsecure(), isOptional: false },
431
+ currency: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
432
+ method: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
433
+ reference: { type: ScalarTypeEnum6.String_unsecure(), isOptional: true },
434
+ receivedAt: { type: ScalarTypeEnum6.DateTime(), isOptional: false }
435
+ }
436
+ });
437
+ var RecordPaymentInputModel = defineSchemaModel6({
438
+ name: "RecordPaymentInput",
439
+ description: "Input for recording a payment",
440
+ fields: {
441
+ invoiceId: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
442
+ amount: { type: ScalarTypeEnum6.Float_unsecure(), isOptional: false },
443
+ method: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
444
+ reference: { type: ScalarTypeEnum6.String_unsecure(), isOptional: true },
445
+ receivedAt: { type: ScalarTypeEnum6.DateTime(), isOptional: true }
446
+ }
447
+ });
448
+
449
+ // src/payment/payment.operations.ts
450
+ import { defineCommand as defineCommand5 } from "@contractspec/lib.contracts";
451
+ var OWNERS5 = ["@examples.service-business-os"];
452
+ var RecordPaymentContract = defineCommand5({
453
+ meta: {
454
+ key: "service.payment.record",
455
+ version: "1.0.0",
456
+ stability: "stable",
457
+ owners: [...OWNERS5],
458
+ tags: ["service-business-os", "payment", "record"],
459
+ description: "Record a payment.",
460
+ goal: "Track payments.",
461
+ context: "Billing."
462
+ },
463
+ io: {
464
+ input: RecordPaymentInputModel,
465
+ output: PaymentModel
466
+ },
467
+ policy: { auth: "user" },
468
+ acceptance: {
469
+ scenarios: [
470
+ {
471
+ key: "record-payment-happy-path",
472
+ given: ["Invoice exists"],
473
+ when: ["User records payment"],
474
+ then: ["Payment is recorded"]
475
+ }
476
+ ],
477
+ examples: [
478
+ {
479
+ key: "record-check",
480
+ input: { invoiceId: "inv-456", amount: 100, method: "check" },
481
+ output: { id: "pay-123", status: "completed" }
482
+ }
483
+ ]
484
+ }
485
+ });
486
+ // src/presentations.ts
487
+ import { definePresentation, StabilityEnum } from "@contractspec/lib.contracts";
488
+ var ServiceDashboardPresentation = definePresentation({
489
+ meta: {
490
+ key: "service-business-os.dashboard",
491
+ version: "1.0.0",
492
+ title: "Service Dashboard",
493
+ description: "Service business dashboard with overview metrics",
494
+ domain: "services",
495
+ owners: ["@service-os"],
496
+ tags: ["services", "dashboard"],
497
+ stability: StabilityEnum.Experimental,
498
+ goal: "Overview of service business metrics",
499
+ context: "Service home page"
500
+ },
501
+ source: {
502
+ type: "component",
503
+ framework: "react",
504
+ componentKey: "ServiceDashboard"
505
+ },
506
+ targets: ["react", "markdown"],
507
+ policy: {
508
+ flags: ["service.dashboard.enabled"]
509
+ }
510
+ });
511
+ var ClientListPresentation = definePresentation({
512
+ meta: {
513
+ key: "service-business-os.client.list",
514
+ version: "1.0.0",
515
+ title: "Client List",
516
+ description: "List of service clients",
517
+ domain: "services",
518
+ owners: ["@service-os"],
519
+ tags: ["services", "clients", "list"],
520
+ stability: StabilityEnum.Experimental,
521
+ goal: "Browse and manage service clients",
522
+ context: "Client management"
523
+ },
524
+ source: {
525
+ type: "component",
526
+ framework: "react",
527
+ componentKey: "ClientList"
528
+ },
529
+ targets: ["react", "markdown"],
530
+ policy: {
531
+ flags: ["service.clients.enabled"]
532
+ }
533
+ });
534
+ var QuoteListPresentation = definePresentation({
535
+ meta: {
536
+ key: "service-business-os.quote.list",
537
+ version: "1.0.0",
538
+ title: "Quote List",
539
+ description: "List of quotes with status",
540
+ domain: "services",
541
+ owners: ["@service-os"],
542
+ tags: ["services", "quotes", "list"],
543
+ stability: StabilityEnum.Experimental,
544
+ goal: "Track and manage quotes",
545
+ context: "Quote management"
546
+ },
547
+ source: {
548
+ type: "component",
549
+ framework: "react",
550
+ componentKey: "QuoteList"
551
+ },
552
+ targets: ["react", "markdown"],
553
+ policy: {
554
+ flags: ["service.quotes.enabled"]
555
+ }
556
+ });
557
+ var QuoteDetailPresentation = definePresentation({
558
+ meta: {
559
+ key: "service-business-os.quote.detail",
560
+ version: "1.0.0",
561
+ title: "Quote Details",
562
+ description: "Quote detail with line items",
563
+ domain: "services",
564
+ owners: ["@service-os"],
565
+ tags: ["services", "quote", "detail"],
566
+ stability: StabilityEnum.Experimental,
567
+ goal: "View and edit quote details",
568
+ context: "Quote inspection"
569
+ },
570
+ source: {
571
+ type: "component",
572
+ framework: "react",
573
+ componentKey: "QuoteDetail"
574
+ },
575
+ targets: ["react", "markdown"],
576
+ policy: {
577
+ flags: ["service.quotes.enabled"]
578
+ }
579
+ });
580
+ var JobBoardPresentation = definePresentation({
581
+ meta: {
582
+ key: "service-business-os.job.board",
583
+ version: "1.0.0",
584
+ title: "Job Board",
585
+ description: "Job board with kanban view",
586
+ domain: "services",
587
+ owners: ["@service-os"],
588
+ tags: ["services", "jobs", "board", "kanban"],
589
+ stability: StabilityEnum.Experimental,
590
+ goal: "Visual job management",
591
+ context: "Field service scheduling"
592
+ },
593
+ source: {
594
+ type: "component",
595
+ framework: "react",
596
+ componentKey: "JobBoard"
597
+ },
598
+ targets: ["react"],
599
+ policy: {
600
+ flags: ["service.jobs.enabled"]
601
+ }
602
+ });
603
+ var InvoiceListPresentation = definePresentation({
604
+ meta: {
605
+ key: "service-business-os.invoice.list",
606
+ version: "1.0.0",
607
+ title: "Invoice List",
608
+ description: "List of invoices with payment status",
609
+ domain: "services",
610
+ owners: ["@service-os"],
611
+ tags: ["services", "invoices", "list"],
612
+ stability: StabilityEnum.Experimental,
613
+ goal: "Track invoices and payments",
614
+ context: "Billing management"
615
+ },
616
+ source: {
617
+ type: "component",
618
+ framework: "react",
619
+ componentKey: "InvoiceList"
620
+ },
621
+ targets: ["react", "markdown"],
622
+ policy: {
623
+ flags: ["service.invoices.enabled"]
624
+ }
625
+ });
626
+ var PaymentListPresentation = definePresentation({
627
+ meta: {
628
+ key: "service-business-os.payment.list",
629
+ version: "1.0.0",
630
+ title: "Payment List",
631
+ description: "List of payments received",
632
+ domain: "services",
633
+ owners: ["@service-os"],
634
+ tags: ["services", "payments", "list"],
635
+ stability: StabilityEnum.Experimental,
636
+ goal: "Track received payments",
637
+ context: "Payment reconciliation"
638
+ },
639
+ source: {
640
+ type: "component",
641
+ framework: "react",
642
+ componentKey: "PaymentList"
643
+ },
644
+ targets: ["react", "markdown"],
645
+ policy: {
646
+ flags: ["service.payments.enabled"]
647
+ }
648
+ });
649
+
650
+ // src/service.feature.ts
651
+ import { defineFeature } from "@contractspec/lib.contracts";
652
+ var ServiceBusinessFeature = defineFeature({
653
+ meta: {
654
+ key: "service-business-os",
655
+ title: "Service Business OS",
656
+ description: "Quotes → jobs → invoices → payments for field services and agencies.",
657
+ domain: "services",
658
+ owners: ["@service-os"],
659
+ tags: ["services", "quotes", "jobs", "invoices", "payments"],
660
+ stability: "experimental",
661
+ version: "1.0.0"
662
+ },
663
+ operations: [
664
+ { key: "service.client.create", version: "1.0.0" },
665
+ { key: "service.quote.create", version: "1.0.0" },
666
+ { key: "service.quote.accept", version: "1.0.0" },
667
+ { key: "service.job.schedule", version: "1.0.0" },
668
+ { key: "service.job.complete", version: "1.0.0" },
669
+ { key: "service.invoice.issue", version: "1.0.0" },
670
+ { key: "service.payment.record", version: "1.0.0" },
671
+ { key: "service.job.list", version: "1.0.0" }
672
+ ],
673
+ events: [
674
+ { key: "service.quote.sent", version: "1.0.0" },
675
+ { key: "service.quote.accepted", version: "1.0.0" },
676
+ { key: "service.job.scheduled", version: "1.0.0" },
677
+ { key: "service.job.completed", version: "1.0.0" },
678
+ { key: "service.invoice.issued", version: "1.0.0" },
679
+ { key: "service.payment.received", version: "1.0.0" }
680
+ ],
681
+ presentations: [
682
+ { key: "service-business-os.dashboard", version: "1.0.0" },
683
+ { key: "service-business-os.client.list", version: "1.0.0" },
684
+ { key: "service-business-os.quote.list", version: "1.0.0" },
685
+ { key: "service-business-os.quote.detail", version: "1.0.0" },
686
+ { key: "service-business-os.job.board", version: "1.0.0" },
687
+ { key: "service-business-os.invoice.list", version: "1.0.0" },
688
+ { key: "service-business-os.payment.list", version: "1.0.0" }
689
+ ],
690
+ presentationsTargets: [
691
+ {
692
+ key: "service-business-os.dashboard",
693
+ version: "1.0.0",
694
+ targets: ["react", "markdown"]
695
+ },
696
+ {
697
+ key: "service-business-os.quote.list",
698
+ version: "1.0.0",
699
+ targets: ["react", "markdown"]
700
+ },
701
+ {
702
+ key: "service-business-os.invoice.list",
703
+ version: "1.0.0",
704
+ targets: ["react", "markdown"]
705
+ }
706
+ ],
707
+ capabilities: {
708
+ requires: [
709
+ { key: "identity", version: "1.0.0" },
710
+ { key: "audit-trail", version: "1.0.0" },
711
+ { key: "notifications", version: "1.0.0" },
712
+ { key: "files", version: "1.0.0" }
713
+ ],
714
+ provides: [
715
+ { key: "quotes", version: "1.0.0" },
716
+ { key: "jobs", version: "1.0.0" },
717
+ { key: "invoices", version: "1.0.0" }
718
+ ]
719
+ }
720
+ });
721
+ export {
722
+ ServiceDashboardPresentation,
723
+ ServiceBusinessFeature,
724
+ ScheduleJobInputModel,
725
+ ScheduleJobContract,
726
+ RecordPaymentInputModel,
727
+ RecordPaymentContract,
728
+ QuoteModel,
729
+ QuoteListPresentation,
730
+ QuoteDetailPresentation,
731
+ PaymentModel,
732
+ PaymentListPresentation,
733
+ ListJobsOutputModel,
734
+ ListJobsOperation,
735
+ ListJobsInputModel,
736
+ JobModel,
737
+ JobBoardPresentation,
738
+ IssueInvoiceInputModel,
739
+ IssueInvoiceContract,
740
+ InvoiceModel,
741
+ InvoiceListPresentation,
742
+ CreateQuoteInputModel,
743
+ CreateQuoteContract,
744
+ CreateClientInputModel,
745
+ CreateClientContract,
746
+ CompleteJobInputModel,
747
+ CompleteJobContract,
748
+ ClientModel,
749
+ ClientListPresentation,
750
+ AcceptQuoteInputModel,
751
+ AcceptQuoteContract
752
+ };