@contractspec/example.crm-pipeline 1.57.0 → 1.59.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 (259) hide show
  1. package/.turbo/turbo-build.log +148 -164
  2. package/.turbo/turbo-prebuild.log +1 -0
  3. package/CHANGELOG.md +39 -0
  4. package/dist/browser/crm-pipeline.feature.js +75 -0
  5. package/dist/browser/deal/deal.enum.js +18 -0
  6. package/dist/browser/deal/deal.operation.js +396 -0
  7. package/dist/browser/deal/deal.schema.js +141 -0
  8. package/dist/browser/deal/deal.test-spec.js +58 -0
  9. package/dist/browser/deal/index.js +408 -0
  10. package/dist/browser/docs/crm-pipeline.docblock.js +113 -0
  11. package/dist/browser/docs/index.js +113 -0
  12. package/dist/browser/entities/company.entity.js +52 -0
  13. package/dist/browser/entities/contact.entity.js +66 -0
  14. package/dist/browser/entities/deal.entity.js +107 -0
  15. package/dist/browser/entities/index.js +343 -0
  16. package/dist/browser/entities/task.entity.js +99 -0
  17. package/dist/browser/events/contact.event.js +31 -0
  18. package/dist/browser/events/deal.event.js +101 -0
  19. package/dist/browser/events/index.js +158 -0
  20. package/dist/browser/events/task.event.js +28 -0
  21. package/dist/browser/example.js +39 -0
  22. package/dist/browser/handlers/crm.handlers.js +160 -0
  23. package/dist/browser/handlers/deal.handlers.js +293 -0
  24. package/dist/browser/handlers/index.js +456 -0
  25. package/dist/browser/handlers/mock-data.js +165 -0
  26. package/dist/browser/index.js +3279 -0
  27. package/dist/browser/operations/index.js +407 -0
  28. package/dist/browser/presentations/dashboard.presentation.js +52 -0
  29. package/dist/browser/presentations/index.js +284 -0
  30. package/dist/browser/presentations/pipeline.presentation.js +233 -0
  31. package/dist/browser/seeders/index.js +22 -0
  32. package/dist/browser/shared/overlay-types.js +0 -0
  33. package/dist/browser/ui/CrmDashboard.js +1325 -0
  34. package/dist/browser/ui/CrmDealCard.js +50 -0
  35. package/dist/browser/ui/CrmPipelineBoard.js +160 -0
  36. package/dist/browser/ui/hooks/index.js +186 -0
  37. package/dist/browser/ui/hooks/useDealList.js +84 -0
  38. package/dist/browser/ui/hooks/useDealMutations.js +100 -0
  39. package/dist/browser/ui/index.js +1972 -0
  40. package/dist/browser/ui/modals/CreateDealModal.js +211 -0
  41. package/dist/browser/ui/modals/DealActionsModal.js +428 -0
  42. package/dist/browser/ui/modals/index.js +638 -0
  43. package/dist/browser/ui/overlays/demo-overlays.js +55 -0
  44. package/dist/browser/ui/overlays/index.js +55 -0
  45. package/dist/browser/ui/renderers/index.js +827 -0
  46. package/dist/browser/ui/renderers/pipeline.markdown.js +564 -0
  47. package/dist/browser/ui/renderers/pipeline.renderer.js +264 -0
  48. package/dist/crm-pipeline.feature.d.ts +1 -6
  49. package/dist/crm-pipeline.feature.d.ts.map +1 -1
  50. package/dist/crm-pipeline.feature.js +74 -164
  51. package/dist/deal/deal.enum.d.ts +2 -7
  52. package/dist/deal/deal.enum.d.ts.map +1 -1
  53. package/dist/deal/deal.enum.js +16 -22
  54. package/dist/deal/deal.operation.d.ts +444 -450
  55. package/dist/deal/deal.operation.d.ts.map +1 -1
  56. package/dist/deal/deal.operation.js +390 -263
  57. package/dist/deal/deal.schema.d.ts +251 -256
  58. package/dist/deal/deal.schema.d.ts.map +1 -1
  59. package/dist/deal/deal.schema.js +131 -275
  60. package/dist/deal/deal.test-spec.d.ts +2 -7
  61. package/dist/deal/deal.test-spec.d.ts.map +1 -1
  62. package/dist/deal/deal.test-spec.js +56 -62
  63. package/dist/deal/index.d.ts +7 -4
  64. package/dist/deal/index.d.ts.map +1 -0
  65. package/dist/deal/index.js +408 -4
  66. package/dist/docs/crm-pipeline.docblock.d.ts +2 -1
  67. package/dist/docs/crm-pipeline.docblock.d.ts.map +1 -0
  68. package/dist/docs/crm-pipeline.docblock.js +45 -51
  69. package/dist/docs/index.d.ts +2 -1
  70. package/dist/docs/index.d.ts.map +1 -0
  71. package/dist/docs/index.js +114 -1
  72. package/dist/entities/company.entity.d.ts +27 -32
  73. package/dist/entities/company.entity.d.ts.map +1 -1
  74. package/dist/entities/company.entity.js +51 -61
  75. package/dist/entities/contact.entity.d.ts +31 -36
  76. package/dist/entities/contact.entity.d.ts.map +1 -1
  77. package/dist/entities/contact.entity.js +65 -76
  78. package/dist/entities/deal.entity.d.ts +52 -57
  79. package/dist/entities/deal.entity.d.ts.map +1 -1
  80. package/dist/entities/deal.entity.js +104 -116
  81. package/dist/entities/index.d.ts +6 -10
  82. package/dist/entities/index.d.ts.map +1 -1
  83. package/dist/entities/index.js +342 -31
  84. package/dist/entities/task.entity.d.ts +42 -47
  85. package/dist/entities/task.entity.d.ts.map +1 -1
  86. package/dist/entities/task.entity.js +95 -124
  87. package/dist/events/contact.event.d.ts +21 -27
  88. package/dist/events/contact.event.d.ts.map +1 -1
  89. package/dist/events/contact.event.js +29 -42
  90. package/dist/events/deal.event.d.ts +100 -106
  91. package/dist/events/deal.event.d.ts.map +1 -1
  92. package/dist/events/deal.event.js +93 -163
  93. package/dist/events/index.d.ts +4 -4
  94. package/dist/events/index.d.ts.map +1 -0
  95. package/dist/events/index.js +158 -4
  96. package/dist/events/task.event.d.ts +21 -27
  97. package/dist/events/task.event.d.ts.map +1 -1
  98. package/dist/events/task.event.js +26 -42
  99. package/dist/example.d.ts +2 -6
  100. package/dist/example.d.ts.map +1 -1
  101. package/dist/example.js +38 -50
  102. package/dist/handlers/crm.handlers.d.ts +80 -78
  103. package/dist/handlers/crm.handlers.d.ts.map +1 -1
  104. package/dist/handlers/crm.handlers.js +155 -166
  105. package/dist/handlers/deal.handlers.d.ts +58 -63
  106. package/dist/handlers/deal.handlers.d.ts.map +1 -1
  107. package/dist/handlers/deal.handlers.js +279 -105
  108. package/dist/handlers/index.d.ts +10 -4
  109. package/dist/handlers/index.d.ts.map +1 -0
  110. package/dist/handlers/index.js +456 -4
  111. package/dist/handlers/mock-data.d.ts +38 -41
  112. package/dist/handlers/mock-data.d.ts.map +1 -1
  113. package/dist/handlers/mock-data.js +162 -184
  114. package/dist/index.d.ts +13 -42
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +3277 -53
  117. package/dist/node/crm-pipeline.feature.js +75 -0
  118. package/dist/node/deal/deal.enum.js +18 -0
  119. package/dist/node/deal/deal.operation.js +396 -0
  120. package/dist/node/deal/deal.schema.js +141 -0
  121. package/dist/node/deal/deal.test-spec.js +58 -0
  122. package/dist/node/deal/index.js +408 -0
  123. package/dist/node/docs/crm-pipeline.docblock.js +113 -0
  124. package/dist/node/docs/index.js +113 -0
  125. package/dist/node/entities/company.entity.js +52 -0
  126. package/dist/node/entities/contact.entity.js +66 -0
  127. package/dist/node/entities/deal.entity.js +107 -0
  128. package/dist/node/entities/index.js +343 -0
  129. package/dist/node/entities/task.entity.js +99 -0
  130. package/dist/node/events/contact.event.js +31 -0
  131. package/dist/node/events/deal.event.js +101 -0
  132. package/dist/node/events/index.js +158 -0
  133. package/dist/node/events/task.event.js +28 -0
  134. package/dist/node/example.js +39 -0
  135. package/dist/node/handlers/crm.handlers.js +160 -0
  136. package/dist/node/handlers/deal.handlers.js +293 -0
  137. package/dist/node/handlers/index.js +456 -0
  138. package/dist/node/handlers/mock-data.js +165 -0
  139. package/dist/node/index.js +3279 -0
  140. package/dist/node/operations/index.js +407 -0
  141. package/dist/node/presentations/dashboard.presentation.js +52 -0
  142. package/dist/node/presentations/index.js +284 -0
  143. package/dist/node/presentations/pipeline.presentation.js +233 -0
  144. package/dist/node/seeders/index.js +22 -0
  145. package/dist/node/shared/overlay-types.js +0 -0
  146. package/dist/node/ui/CrmDashboard.js +1325 -0
  147. package/dist/node/ui/CrmDealCard.js +50 -0
  148. package/dist/node/ui/CrmPipelineBoard.js +160 -0
  149. package/dist/node/ui/hooks/index.js +186 -0
  150. package/dist/node/ui/hooks/useDealList.js +84 -0
  151. package/dist/node/ui/hooks/useDealMutations.js +100 -0
  152. package/dist/node/ui/index.js +1972 -0
  153. package/dist/node/ui/modals/CreateDealModal.js +211 -0
  154. package/dist/node/ui/modals/DealActionsModal.js +428 -0
  155. package/dist/node/ui/modals/index.js +638 -0
  156. package/dist/node/ui/overlays/demo-overlays.js +55 -0
  157. package/dist/node/ui/overlays/index.js +55 -0
  158. package/dist/node/ui/renderers/index.js +827 -0
  159. package/dist/node/ui/renderers/pipeline.markdown.js +564 -0
  160. package/dist/node/ui/renderers/pipeline.renderer.js +264 -0
  161. package/dist/operations/index.d.ts +2 -5
  162. package/dist/operations/index.d.ts.map +1 -0
  163. package/dist/operations/index.js +407 -5
  164. package/dist/presentations/dashboard.presentation.d.ts +2 -7
  165. package/dist/presentations/dashboard.presentation.d.ts.map +1 -1
  166. package/dist/presentations/dashboard.presentation.js +51 -60
  167. package/dist/presentations/index.d.ts +3 -3
  168. package/dist/presentations/index.d.ts.map +1 -0
  169. package/dist/presentations/index.js +284 -3
  170. package/dist/presentations/pipeline.presentation.d.ts +4 -9
  171. package/dist/presentations/pipeline.presentation.d.ts.map +1 -1
  172. package/dist/presentations/pipeline.presentation.js +228 -116
  173. package/dist/seeders/index.d.ts +4 -8
  174. package/dist/seeders/index.d.ts.map +1 -1
  175. package/dist/seeders/index.js +21 -45
  176. package/dist/shared/overlay-types.d.ts +25 -28
  177. package/dist/shared/overlay-types.d.ts.map +1 -1
  178. package/dist/shared/overlay-types.js +1 -0
  179. package/dist/ui/CrmDashboard.d.ts +1 -6
  180. package/dist/ui/CrmDashboard.d.ts.map +1 -1
  181. package/dist/ui/CrmDashboard.js +1318 -296
  182. package/dist/ui/CrmDealCard.d.ts +8 -12
  183. package/dist/ui/CrmDealCard.d.ts.map +1 -1
  184. package/dist/ui/CrmDealCard.js +47 -45
  185. package/dist/ui/CrmPipelineBoard.d.ts +11 -20
  186. package/dist/ui/CrmPipelineBoard.d.ts.map +1 -1
  187. package/dist/ui/CrmPipelineBoard.js +157 -94
  188. package/dist/ui/hooks/index.d.ts +3 -3
  189. package/dist/ui/hooks/index.d.ts.map +1 -0
  190. package/dist/ui/hooks/index.js +185 -4
  191. package/dist/ui/hooks/useDealList.d.ts +28 -32
  192. package/dist/ui/hooks/useDealList.d.ts.map +1 -1
  193. package/dist/ui/hooks/useDealList.js +81 -90
  194. package/dist/ui/hooks/useDealMutations.d.ts +18 -22
  195. package/dist/ui/hooks/useDealMutations.d.ts.map +1 -1
  196. package/dist/ui/hooks/useDealMutations.js +97 -155
  197. package/dist/ui/index.d.ts +8 -14
  198. package/dist/ui/index.d.ts.map +1 -0
  199. package/dist/ui/index.js +1973 -15
  200. package/dist/ui/modals/CreateDealModal.d.ts +19 -29
  201. package/dist/ui/modals/CreateDealModal.d.ts.map +1 -1
  202. package/dist/ui/modals/CreateDealModal.js +209 -180
  203. package/dist/ui/modals/DealActionsModal.d.ts +31 -44
  204. package/dist/ui/modals/DealActionsModal.d.ts.map +1 -1
  205. package/dist/ui/modals/DealActionsModal.js +424 -367
  206. package/dist/ui/modals/index.d.ts +3 -3
  207. package/dist/ui/modals/index.d.ts.map +1 -0
  208. package/dist/ui/modals/index.js +638 -3
  209. package/dist/ui/overlays/demo-overlays.d.ts +10 -8
  210. package/dist/ui/overlays/demo-overlays.d.ts.map +1 -1
  211. package/dist/ui/overlays/demo-overlays.js +54 -66
  212. package/dist/ui/overlays/index.d.ts +2 -2
  213. package/dist/ui/overlays/index.d.ts.map +1 -0
  214. package/dist/ui/overlays/index.js +56 -3
  215. package/dist/ui/renderers/index.d.ts +3 -3
  216. package/dist/ui/renderers/index.d.ts.map +1 -0
  217. package/dist/ui/renderers/index.js +827 -3
  218. package/dist/ui/renderers/pipeline.markdown.d.ts +12 -11
  219. package/dist/ui/renderers/pipeline.markdown.d.ts.map +1 -1
  220. package/dist/ui/renderers/pipeline.markdown.js +560 -114
  221. package/dist/ui/renderers/pipeline.renderer.d.ts +9 -7
  222. package/dist/ui/renderers/pipeline.renderer.d.ts.map +1 -1
  223. package/dist/ui/renderers/pipeline.renderer.js +261 -24
  224. package/package.json +476 -90
  225. package/tsdown.config.js +1 -2
  226. package/.turbo/turbo-build$colon$bundle.log +0 -164
  227. package/dist/crm-pipeline.feature.js.map +0 -1
  228. package/dist/deal/deal.enum.js.map +0 -1
  229. package/dist/deal/deal.operation.js.map +0 -1
  230. package/dist/deal/deal.schema.js.map +0 -1
  231. package/dist/deal/deal.test-spec.js.map +0 -1
  232. package/dist/docs/crm-pipeline.docblock.js.map +0 -1
  233. package/dist/entities/company.entity.js.map +0 -1
  234. package/dist/entities/contact.entity.js.map +0 -1
  235. package/dist/entities/deal.entity.js.map +0 -1
  236. package/dist/entities/index.js.map +0 -1
  237. package/dist/entities/task.entity.js.map +0 -1
  238. package/dist/events/contact.event.js.map +0 -1
  239. package/dist/events/deal.event.js.map +0 -1
  240. package/dist/events/task.event.js.map +0 -1
  241. package/dist/example.js.map +0 -1
  242. package/dist/handlers/crm.handlers.js.map +0 -1
  243. package/dist/handlers/deal.handlers.js.map +0 -1
  244. package/dist/handlers/mock-data.js.map +0 -1
  245. package/dist/index.js.map +0 -1
  246. package/dist/presentations/dashboard.presentation.js.map +0 -1
  247. package/dist/presentations/pipeline.presentation.js.map +0 -1
  248. package/dist/seeders/index.js.map +0 -1
  249. package/dist/ui/CrmDashboard.js.map +0 -1
  250. package/dist/ui/CrmDealCard.js.map +0 -1
  251. package/dist/ui/CrmPipelineBoard.js.map +0 -1
  252. package/dist/ui/hooks/useDealList.js.map +0 -1
  253. package/dist/ui/hooks/useDealMutations.js.map +0 -1
  254. package/dist/ui/modals/CreateDealModal.js.map +0 -1
  255. package/dist/ui/modals/DealActionsModal.js.map +0 -1
  256. package/dist/ui/overlays/demo-overlays.js.map +0 -1
  257. package/dist/ui/renderers/pipeline.markdown.js.map +0 -1
  258. package/dist/ui/renderers/pipeline.renderer.js.map +0 -1
  259. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,396 @@
1
+ // src/deal/deal.enum.ts
2
+ import { defineEnum } from "@contractspec/lib.schema";
3
+ var DealStatusEnum = defineEnum("DealStatus", [
4
+ "OPEN",
5
+ "WON",
6
+ "LOST",
7
+ "STALE"
8
+ ]);
9
+ var DealStatusFilterEnum = defineEnum("DealStatusFilter", [
10
+ "OPEN",
11
+ "WON",
12
+ "LOST",
13
+ "all"
14
+ ]);
15
+
16
+ // src/deal/deal.schema.ts
17
+ import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
18
+ var DealModel = defineSchemaModel({
19
+ name: "Deal",
20
+ description: "A deal in the CRM pipeline",
21
+ fields: {
22
+ id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
23
+ name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
24
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
25
+ currency: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
26
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
27
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
28
+ status: { type: DealStatusEnum, isOptional: false },
29
+ contactId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
30
+ companyId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
31
+ ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
32
+ expectedCloseDate: { type: ScalarTypeEnum.DateTime(), isOptional: true },
33
+ createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
34
+ updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
35
+ }
36
+ });
37
+ var CreateDealInputModel = defineSchemaModel({
38
+ name: "CreateDealInput",
39
+ description: "Input for creating a deal",
40
+ fields: {
41
+ name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
42
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
43
+ currency: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
44
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
45
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
46
+ contactId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
47
+ companyId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
48
+ expectedCloseDate: { type: ScalarTypeEnum.DateTime(), isOptional: true }
49
+ }
50
+ });
51
+ var MoveDealInputModel = defineSchemaModel({
52
+ name: "MoveDealInput",
53
+ description: "Input for moving a deal to another stage",
54
+ fields: {
55
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
56
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
57
+ position: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true }
58
+ }
59
+ });
60
+ var DealMovedPayloadModel = defineSchemaModel({
61
+ name: "DealMovedPayload",
62
+ fields: {
63
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
64
+ fromStage: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
65
+ toStage: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
66
+ }
67
+ });
68
+ var WinDealInputModel = defineSchemaModel({
69
+ name: "WinDealInput",
70
+ description: "Input for marking a deal as won",
71
+ fields: {
72
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
73
+ wonSource: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
74
+ notes: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
75
+ }
76
+ });
77
+ var DealWonPayloadModel = defineSchemaModel({
78
+ name: "DealWonPayload",
79
+ fields: {
80
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
81
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false }
82
+ }
83
+ });
84
+ var LoseDealInputModel = defineSchemaModel({
85
+ name: "LoseDealInput",
86
+ description: "Input for marking a deal as lost",
87
+ fields: {
88
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
89
+ lostReason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
90
+ notes: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
91
+ }
92
+ });
93
+ var DealLostPayloadModel = defineSchemaModel({
94
+ name: "DealLostPayload",
95
+ fields: {
96
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
97
+ reason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
98
+ }
99
+ });
100
+ var ListDealsInputModel = defineSchemaModel({
101
+ name: "ListDealsInput",
102
+ description: "Input for listing deals",
103
+ fields: {
104
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
105
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
106
+ status: { type: DealStatusFilterEnum, isOptional: true },
107
+ ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
108
+ search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
109
+ limit: {
110
+ type: ScalarTypeEnum.Int_unsecure(),
111
+ isOptional: true,
112
+ defaultValue: 20
113
+ },
114
+ offset: {
115
+ type: ScalarTypeEnum.Int_unsecure(),
116
+ isOptional: true,
117
+ defaultValue: 0
118
+ }
119
+ }
120
+ });
121
+ var ListDealsOutputModel = defineSchemaModel({
122
+ name: "ListDealsOutput",
123
+ description: "Output for listing deals",
124
+ fields: {
125
+ deals: { type: DealModel, isArray: true, isOptional: false },
126
+ total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
127
+ totalValue: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false }
128
+ }
129
+ });
130
+
131
+ // src/deal/deal.operation.ts
132
+ import {
133
+ defineCommand,
134
+ defineQuery
135
+ } from "@contractspec/lib.contracts/operations";
136
+ var OWNERS = ["@example.crm-pipeline"];
137
+ var CreateDealContract = defineCommand({
138
+ meta: {
139
+ key: "crm.deal.create",
140
+ version: "1.0.0",
141
+ stability: "stable",
142
+ owners: [...OWNERS],
143
+ tags: ["crm", "deal", "create"],
144
+ description: "Create a new deal in the pipeline.",
145
+ goal: "Allow sales reps to create new opportunities.",
146
+ context: "Deal creation UI, quick add."
147
+ },
148
+ io: {
149
+ input: CreateDealInputModel,
150
+ output: DealModel
151
+ },
152
+ policy: {
153
+ auth: "user"
154
+ },
155
+ sideEffects: {
156
+ emits: [
157
+ {
158
+ key: "deal.created",
159
+ version: "1.0.0",
160
+ when: "Deal is created",
161
+ payload: DealModel
162
+ }
163
+ ],
164
+ audit: ["deal.created"]
165
+ },
166
+ acceptance: {
167
+ scenarios: [
168
+ {
169
+ key: "create-deal-happy-path",
170
+ given: ["User is authenticated"],
171
+ when: ["User creates a deal with valid data"],
172
+ then: ["Deal is created", "DealCreated event is emitted"]
173
+ }
174
+ ],
175
+ examples: [
176
+ {
177
+ key: "create-basic-deal",
178
+ input: {
179
+ title: "Big Corp Q3 License",
180
+ stageId: "stage-lead",
181
+ value: 50000,
182
+ companyId: "comp-123"
183
+ },
184
+ output: {
185
+ id: "deal-789",
186
+ title: "Big Corp Q3 License",
187
+ status: "open"
188
+ }
189
+ }
190
+ ]
191
+ }
192
+ });
193
+ var MoveDealContract = defineCommand({
194
+ meta: {
195
+ key: "crm.deal.move",
196
+ version: "1.0.0",
197
+ stability: "stable",
198
+ owners: [...OWNERS],
199
+ tags: ["crm", "deal", "move", "kanban"],
200
+ description: "Move a deal to a different stage.",
201
+ goal: "Allow drag-and-drop stage movement in Kanban.",
202
+ context: "Pipeline Kanban view."
203
+ },
204
+ io: {
205
+ input: MoveDealInputModel,
206
+ output: DealModel
207
+ },
208
+ policy: {
209
+ auth: "user"
210
+ },
211
+ sideEffects: {
212
+ emits: [
213
+ {
214
+ key: "deal.moved",
215
+ version: "1.0.0",
216
+ when: "Deal stage changed",
217
+ payload: DealMovedPayloadModel
218
+ }
219
+ ],
220
+ audit: ["deal.moved"]
221
+ },
222
+ acceptance: {
223
+ scenarios: [
224
+ {
225
+ key: "move-deal-happy-path",
226
+ given: ["Deal exists in stage A"],
227
+ when: ["User moves deal to stage B"],
228
+ then: ["Deal stage is updated", "DealMoved event is emitted"]
229
+ }
230
+ ],
231
+ examples: [
232
+ {
233
+ key: "move-to-negotiation",
234
+ input: { dealId: "deal-789", targetStageId: "stage-negotiation" },
235
+ output: {
236
+ id: "deal-789",
237
+ stageId: "stage-negotiation",
238
+ movedAt: "2025-01-15T10:00:00Z"
239
+ }
240
+ }
241
+ ]
242
+ }
243
+ });
244
+ var WinDealContract = defineCommand({
245
+ meta: {
246
+ key: "crm.deal.win",
247
+ version: "1.0.0",
248
+ stability: "stable",
249
+ owners: [...OWNERS],
250
+ tags: ["crm", "deal", "won"],
251
+ description: "Mark a deal as won.",
252
+ goal: "Close a deal as successful.",
253
+ context: "Deal closing flow."
254
+ },
255
+ io: {
256
+ input: WinDealInputModel,
257
+ output: DealModel
258
+ },
259
+ policy: {
260
+ auth: "user"
261
+ },
262
+ sideEffects: {
263
+ emits: [
264
+ {
265
+ key: "deal.won",
266
+ version: "1.0.0",
267
+ when: "Deal is won",
268
+ payload: DealWonPayloadModel
269
+ }
270
+ ],
271
+ audit: ["deal.won"]
272
+ },
273
+ acceptance: {
274
+ scenarios: [
275
+ {
276
+ key: "win-deal-happy-path",
277
+ given: ["Deal is open"],
278
+ when: ["User marks deal as won"],
279
+ then: ["Deal status becomes WON", "DealWon event is emitted"]
280
+ }
281
+ ],
282
+ examples: [
283
+ {
284
+ key: "mark-won",
285
+ input: {
286
+ dealId: "deal-789",
287
+ actualValue: 52000,
288
+ note: "Signed contract attached"
289
+ },
290
+ output: {
291
+ id: "deal-789",
292
+ status: "won",
293
+ closedAt: "2025-01-20T14:30:00Z"
294
+ }
295
+ }
296
+ ]
297
+ }
298
+ });
299
+ var LoseDealContract = defineCommand({
300
+ meta: {
301
+ key: "crm.deal.lose",
302
+ version: "1.0.0",
303
+ stability: "stable",
304
+ owners: [...OWNERS],
305
+ tags: ["crm", "deal", "lost"],
306
+ description: "Mark a deal as lost.",
307
+ goal: "Close a deal as unsuccessful.",
308
+ context: "Deal closing flow."
309
+ },
310
+ io: {
311
+ input: LoseDealInputModel,
312
+ output: DealModel
313
+ },
314
+ policy: {
315
+ auth: "user"
316
+ },
317
+ sideEffects: {
318
+ emits: [
319
+ {
320
+ key: "deal.lost",
321
+ version: "1.0.0",
322
+ when: "Deal is lost",
323
+ payload: DealLostPayloadModel
324
+ }
325
+ ],
326
+ audit: ["deal.lost"]
327
+ },
328
+ acceptance: {
329
+ scenarios: [
330
+ {
331
+ key: "lose-deal-happy-path",
332
+ given: ["Deal is open"],
333
+ when: ["User marks deal as lost"],
334
+ then: ["Deal status becomes LOST", "DealLost event is emitted"]
335
+ }
336
+ ],
337
+ examples: [
338
+ {
339
+ key: "mark-lost",
340
+ input: {
341
+ dealId: "deal-789",
342
+ reason: "competitor",
343
+ note: "Went with cheaper option"
344
+ },
345
+ output: {
346
+ id: "deal-789",
347
+ status: "lost",
348
+ closedAt: "2025-01-21T09:00:00Z"
349
+ }
350
+ }
351
+ ]
352
+ }
353
+ });
354
+ var ListDealsContract = defineQuery({
355
+ meta: {
356
+ key: "crm.deal.list",
357
+ version: "1.0.0",
358
+ stability: "stable",
359
+ owners: [...OWNERS],
360
+ tags: ["crm", "deal", "list"],
361
+ description: "List deals with filters.",
362
+ goal: "Show pipeline, deal lists, dashboards.",
363
+ context: "Pipeline view, deal list."
364
+ },
365
+ io: {
366
+ input: ListDealsInputModel,
367
+ output: ListDealsOutputModel
368
+ },
369
+ policy: {
370
+ auth: "user"
371
+ },
372
+ acceptance: {
373
+ scenarios: [
374
+ {
375
+ key: "list-deals-happy-path",
376
+ given: ["User has access to deals"],
377
+ when: ["User lists deals"],
378
+ then: ["List of deals is returned"]
379
+ }
380
+ ],
381
+ examples: [
382
+ {
383
+ key: "list-filter-stage",
384
+ input: { stageId: "stage-lead", limit: 20 },
385
+ output: { items: [], total: 5, hasMore: false }
386
+ }
387
+ ]
388
+ }
389
+ });
390
+ export {
391
+ WinDealContract,
392
+ MoveDealContract,
393
+ LoseDealContract,
394
+ ListDealsContract,
395
+ CreateDealContract
396
+ };
@@ -0,0 +1,141 @@
1
+ // src/deal/deal.enum.ts
2
+ import { defineEnum } from "@contractspec/lib.schema";
3
+ var DealStatusEnum = defineEnum("DealStatus", [
4
+ "OPEN",
5
+ "WON",
6
+ "LOST",
7
+ "STALE"
8
+ ]);
9
+ var DealStatusFilterEnum = defineEnum("DealStatusFilter", [
10
+ "OPEN",
11
+ "WON",
12
+ "LOST",
13
+ "all"
14
+ ]);
15
+
16
+ // src/deal/deal.schema.ts
17
+ import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
18
+ var DealModel = defineSchemaModel({
19
+ name: "Deal",
20
+ description: "A deal in the CRM pipeline",
21
+ fields: {
22
+ id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
23
+ name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
24
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
25
+ currency: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
26
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
27
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
28
+ status: { type: DealStatusEnum, isOptional: false },
29
+ contactId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
30
+ companyId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
31
+ ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
32
+ expectedCloseDate: { type: ScalarTypeEnum.DateTime(), isOptional: true },
33
+ createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
34
+ updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
35
+ }
36
+ });
37
+ var CreateDealInputModel = defineSchemaModel({
38
+ name: "CreateDealInput",
39
+ description: "Input for creating a deal",
40
+ fields: {
41
+ name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
42
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
43
+ currency: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
44
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
45
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
46
+ contactId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
47
+ companyId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
48
+ expectedCloseDate: { type: ScalarTypeEnum.DateTime(), isOptional: true }
49
+ }
50
+ });
51
+ var MoveDealInputModel = defineSchemaModel({
52
+ name: "MoveDealInput",
53
+ description: "Input for moving a deal to another stage",
54
+ fields: {
55
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
56
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
57
+ position: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true }
58
+ }
59
+ });
60
+ var DealMovedPayloadModel = defineSchemaModel({
61
+ name: "DealMovedPayload",
62
+ fields: {
63
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
64
+ fromStage: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
65
+ toStage: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
66
+ }
67
+ });
68
+ var WinDealInputModel = defineSchemaModel({
69
+ name: "WinDealInput",
70
+ description: "Input for marking a deal as won",
71
+ fields: {
72
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
73
+ wonSource: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
74
+ notes: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
75
+ }
76
+ });
77
+ var DealWonPayloadModel = defineSchemaModel({
78
+ name: "DealWonPayload",
79
+ fields: {
80
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
81
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false }
82
+ }
83
+ });
84
+ var LoseDealInputModel = defineSchemaModel({
85
+ name: "LoseDealInput",
86
+ description: "Input for marking a deal as lost",
87
+ fields: {
88
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
89
+ lostReason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
90
+ notes: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
91
+ }
92
+ });
93
+ var DealLostPayloadModel = defineSchemaModel({
94
+ name: "DealLostPayload",
95
+ fields: {
96
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
97
+ reason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
98
+ }
99
+ });
100
+ var ListDealsInputModel = defineSchemaModel({
101
+ name: "ListDealsInput",
102
+ description: "Input for listing deals",
103
+ fields: {
104
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
105
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
106
+ status: { type: DealStatusFilterEnum, isOptional: true },
107
+ ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
108
+ search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
109
+ limit: {
110
+ type: ScalarTypeEnum.Int_unsecure(),
111
+ isOptional: true,
112
+ defaultValue: 20
113
+ },
114
+ offset: {
115
+ type: ScalarTypeEnum.Int_unsecure(),
116
+ isOptional: true,
117
+ defaultValue: 0
118
+ }
119
+ }
120
+ });
121
+ var ListDealsOutputModel = defineSchemaModel({
122
+ name: "ListDealsOutput",
123
+ description: "Output for listing deals",
124
+ fields: {
125
+ deals: { type: DealModel, isArray: true, isOptional: false },
126
+ total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
127
+ totalValue: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false }
128
+ }
129
+ });
130
+ export {
131
+ WinDealInputModel,
132
+ MoveDealInputModel,
133
+ LoseDealInputModel,
134
+ ListDealsOutputModel,
135
+ ListDealsInputModel,
136
+ DealWonPayloadModel,
137
+ DealMovedPayloadModel,
138
+ DealModel,
139
+ DealLostPayloadModel,
140
+ CreateDealInputModel
141
+ };
@@ -0,0 +1,58 @@
1
+ // src/deal/deal.test-spec.ts
2
+ import { defineTestSpec } from "@contractspec/lib.contracts";
3
+ var dealListTest = defineTestSpec({
4
+ meta: {
5
+ key: "test.crm.deal.list",
6
+ version: "1.0.0",
7
+ owners: ["@example.crm-pipeline"],
8
+ description: "Test for listing deals",
9
+ stability: "stable",
10
+ tags: ["test"]
11
+ },
12
+ target: {
13
+ type: "operation",
14
+ operation: { key: "crm.deal.list", version: "1.0.0" }
15
+ },
16
+ scenarios: [
17
+ {
18
+ key: "success",
19
+ when: { operation: { key: "crm.deal.list" } },
20
+ then: [{ type: "expectOutput", match: {} }]
21
+ },
22
+ {
23
+ key: "error",
24
+ when: { operation: { key: "crm.deal.list" } },
25
+ then: [{ type: "expectError" }]
26
+ }
27
+ ]
28
+ });
29
+ var dealMoveTest = defineTestSpec({
30
+ meta: {
31
+ key: "test.crm.deal.move",
32
+ version: "1.0.0",
33
+ owners: ["@example.crm-pipeline"],
34
+ description: "Test for moving deal",
35
+ stability: "stable",
36
+ tags: ["test"]
37
+ },
38
+ target: {
39
+ type: "operation",
40
+ operation: { key: "crm.deal.move", version: "1.0.0" }
41
+ },
42
+ scenarios: [
43
+ {
44
+ key: "success",
45
+ when: { operation: { key: "crm.deal.move" } },
46
+ then: [{ type: "expectOutput", match: {} }]
47
+ },
48
+ {
49
+ key: "error",
50
+ when: { operation: { key: "crm.deal.move" } },
51
+ then: [{ type: "expectError" }]
52
+ }
53
+ ]
54
+ });
55
+ export {
56
+ dealMoveTest,
57
+ dealListTest
58
+ };