@contractspec/example.crm-pipeline 3.7.6 → 3.7.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 (130) hide show
  1. package/.turbo/turbo-build.log +45 -42
  2. package/AGENTS.md +51 -33
  3. package/CHANGELOG.md +36 -0
  4. package/README.md +67 -148
  5. package/dist/browser/docs/crm-pipeline.docblock.js +1 -1
  6. package/dist/browser/docs/index.js +1 -1
  7. package/dist/browser/events/contact.event.js +1 -1
  8. package/dist/browser/events/deal.event.js +1 -1
  9. package/dist/browser/events/index.js +3 -3
  10. package/dist/browser/events/task.event.js +1 -1
  11. package/dist/browser/handlers/crm.handlers.js +13 -2
  12. package/dist/browser/handlers/index.js +13 -2
  13. package/dist/browser/index.js +680 -447
  14. package/dist/browser/ui/CrmDashboard.js +574 -352
  15. package/dist/browser/ui/CrmDealCard.js +5 -5
  16. package/dist/browser/ui/CrmPipelineBoard.js +13 -13
  17. package/dist/browser/ui/hooks/index.js +21 -10
  18. package/dist/browser/ui/hooks/useDealList.js +20 -9
  19. package/dist/browser/ui/hooks/useDealMutations.js +1 -1
  20. package/dist/browser/ui/index.js +683 -450
  21. package/dist/browser/ui/modals/CreateDealModal.js +12 -12
  22. package/dist/browser/ui/modals/DealActionsModal.js +21 -21
  23. package/dist/browser/ui/modals/index.js +33 -33
  24. package/dist/browser/ui/renderers/index.js +140 -118
  25. package/dist/browser/ui/renderers/pipeline.markdown.js +13 -2
  26. package/dist/browser/ui/renderers/pipeline.renderer.js +108 -97
  27. package/dist/browser/ui/tables/DealListTab.js +390 -0
  28. package/dist/deal/index.d.ts +2 -2
  29. package/dist/docs/crm-pipeline.docblock.js +1 -1
  30. package/dist/docs/index.js +1 -1
  31. package/dist/events/contact.event.js +1 -1
  32. package/dist/events/deal.event.js +1 -1
  33. package/dist/events/index.js +3 -3
  34. package/dist/events/task.event.js +1 -1
  35. package/dist/handlers/crm.handlers.d.ts +2 -0
  36. package/dist/handlers/crm.handlers.js +13 -2
  37. package/dist/handlers/index.d.ts +2 -2
  38. package/dist/handlers/index.js +13 -2
  39. package/dist/index.d.ts +3 -3
  40. package/dist/index.js +680 -447
  41. package/dist/node/docs/crm-pipeline.docblock.js +1 -1
  42. package/dist/node/docs/index.js +1 -1
  43. package/dist/node/events/contact.event.js +1 -1
  44. package/dist/node/events/deal.event.js +1 -1
  45. package/dist/node/events/index.js +3 -3
  46. package/dist/node/events/task.event.js +1 -1
  47. package/dist/node/handlers/crm.handlers.js +13 -2
  48. package/dist/node/handlers/index.js +13 -2
  49. package/dist/node/index.js +680 -447
  50. package/dist/node/ui/CrmDashboard.js +574 -352
  51. package/dist/node/ui/CrmDealCard.js +5 -5
  52. package/dist/node/ui/CrmPipelineBoard.js +13 -13
  53. package/dist/node/ui/hooks/index.js +21 -10
  54. package/dist/node/ui/hooks/useDealList.js +20 -9
  55. package/dist/node/ui/hooks/useDealMutations.js +1 -1
  56. package/dist/node/ui/index.js +683 -450
  57. package/dist/node/ui/modals/CreateDealModal.js +12 -12
  58. package/dist/node/ui/modals/DealActionsModal.js +21 -21
  59. package/dist/node/ui/modals/index.js +33 -33
  60. package/dist/node/ui/renderers/index.js +140 -118
  61. package/dist/node/ui/renderers/pipeline.markdown.js +13 -2
  62. package/dist/node/ui/renderers/pipeline.renderer.js +108 -97
  63. package/dist/node/ui/tables/DealListTab.js +390 -0
  64. package/dist/operations/index.d.ts +1 -1
  65. package/dist/ui/CrmDashboard.js +574 -352
  66. package/dist/ui/CrmDealCard.js +5 -5
  67. package/dist/ui/CrmPipelineBoard.js +13 -13
  68. package/dist/ui/hooks/index.d.ts +2 -2
  69. package/dist/ui/hooks/index.js +21 -10
  70. package/dist/ui/hooks/useDealList.d.ts +8 -2
  71. package/dist/ui/hooks/useDealList.js +20 -9
  72. package/dist/ui/hooks/useDealMutations.d.ts +9 -0
  73. package/dist/ui/hooks/useDealMutations.js +1 -1
  74. package/dist/ui/index.d.ts +3 -3
  75. package/dist/ui/index.js +683 -450
  76. package/dist/ui/modals/CreateDealModal.js +12 -12
  77. package/dist/ui/modals/DealActionsModal.js +21 -21
  78. package/dist/ui/modals/index.js +33 -33
  79. package/dist/ui/renderers/index.d.ts +1 -1
  80. package/dist/ui/renderers/index.js +140 -118
  81. package/dist/ui/renderers/pipeline.markdown.js +13 -2
  82. package/dist/ui/renderers/pipeline.renderer.d.ts +1 -1
  83. package/dist/ui/renderers/pipeline.renderer.js +108 -97
  84. package/dist/ui/tables/DealListTab.d.ts +20 -0
  85. package/dist/ui/tables/DealListTab.js +391 -0
  86. package/dist/ui/tables/DealListTab.smoke.test.d.ts +1 -0
  87. package/package.json +29 -14
  88. package/src/crm-pipeline.feature.ts +86 -86
  89. package/src/deal/deal.enum.ts +8 -8
  90. package/src/deal/deal.operation.ts +255 -255
  91. package/src/deal/deal.schema.ts +92 -92
  92. package/src/deal/deal.test-spec.ts +48 -48
  93. package/src/deal/index.ts +17 -19
  94. package/src/docs/crm-pipeline.docblock.ts +44 -44
  95. package/src/entities/company.entity.ts +52 -52
  96. package/src/entities/contact.entity.ts +67 -67
  97. package/src/entities/deal.entity.ts +134 -134
  98. package/src/entities/index.ts +27 -27
  99. package/src/entities/task.entity.ts +105 -105
  100. package/src/events/contact.event.ts +22 -22
  101. package/src/events/deal.event.ts +77 -77
  102. package/src/events/task.event.ts +19 -19
  103. package/src/example.ts +32 -32
  104. package/src/handlers/crm.handlers.ts +375 -357
  105. package/src/handlers/deal.handlers.ts +179 -179
  106. package/src/handlers/index.ts +18 -19
  107. package/src/handlers/mock-data.ts +167 -167
  108. package/src/index.ts +11 -11
  109. package/src/operations/index.ts +16 -16
  110. package/src/presentations/dashboard.presentation.ts +45 -45
  111. package/src/presentations/pipeline.presentation.ts +90 -90
  112. package/src/seeders/index.ts +26 -26
  113. package/src/shared/overlay-types.ts +23 -23
  114. package/src/ui/CrmDashboard.tsx +210 -279
  115. package/src/ui/CrmDealCard.tsx +64 -64
  116. package/src/ui/CrmPipelineBoard.tsx +105 -105
  117. package/src/ui/hooks/index.ts +3 -3
  118. package/src/ui/hooks/useDealList.ts +113 -85
  119. package/src/ui/hooks/useDealMutations.ts +151 -150
  120. package/src/ui/index.ts +5 -10
  121. package/src/ui/modals/CreateDealModal.tsx +217 -217
  122. package/src/ui/modals/DealActionsModal.tsx +390 -390
  123. package/src/ui/overlays/demo-overlays.ts +43 -43
  124. package/src/ui/renderers/index.ts +4 -3
  125. package/src/ui/renderers/pipeline.markdown.ts +165 -165
  126. package/src/ui/renderers/pipeline.renderer.tsx +17 -16
  127. package/src/ui/tables/DealListTab.smoke.test.tsx +149 -0
  128. package/src/ui/tables/DealListTab.tsx +276 -0
  129. package/tsconfig.json +7 -8
  130. package/tsdown.config.js +7 -3
@@ -5,150 +5,150 @@ import { DealStatusEnum, DealStatusFilterEnum } from './deal.enum';
5
5
  * A deal in the CRM pipeline.
6
6
  */
7
7
  export const DealModel = defineSchemaModel({
8
- name: 'Deal',
9
- description: 'A deal in the CRM pipeline',
10
- fields: {
11
- id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
12
- name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
13
- value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
14
- currency: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
15
- pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
16
- stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
17
- status: { type: DealStatusEnum, isOptional: false },
18
- contactId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
19
- companyId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
20
- ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
21
- expectedCloseDate: { type: ScalarTypeEnum.DateTime(), isOptional: true },
22
- createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
23
- updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
24
- },
8
+ name: 'Deal',
9
+ description: 'A deal in the CRM pipeline',
10
+ fields: {
11
+ id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
12
+ name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
13
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
14
+ currency: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
15
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
16
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
17
+ status: { type: DealStatusEnum, isOptional: false },
18
+ contactId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
19
+ companyId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
20
+ ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
21
+ expectedCloseDate: { type: ScalarTypeEnum.DateTime(), isOptional: true },
22
+ createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
23
+ updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
24
+ },
25
25
  });
26
26
 
27
27
  /**
28
28
  * Input for creating a deal.
29
29
  */
30
30
  export const CreateDealInputModel = defineSchemaModel({
31
- name: 'CreateDealInput',
32
- description: 'Input for creating a deal',
33
- fields: {
34
- name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
35
- value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
36
- currency: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
37
- pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
38
- stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
39
- contactId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
40
- companyId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
41
- expectedCloseDate: { type: ScalarTypeEnum.DateTime(), isOptional: true },
42
- },
31
+ name: 'CreateDealInput',
32
+ description: 'Input for creating a deal',
33
+ fields: {
34
+ name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
35
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
36
+ currency: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
37
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
38
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
39
+ contactId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
40
+ companyId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
41
+ expectedCloseDate: { type: ScalarTypeEnum.DateTime(), isOptional: true },
42
+ },
43
43
  });
44
44
 
45
45
  /**
46
46
  * Input for moving a deal to another stage.
47
47
  */
48
48
  export const MoveDealInputModel = defineSchemaModel({
49
- name: 'MoveDealInput',
50
- description: 'Input for moving a deal to another stage',
51
- fields: {
52
- dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
53
- stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
54
- position: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
55
- },
49
+ name: 'MoveDealInput',
50
+ description: 'Input for moving a deal to another stage',
51
+ fields: {
52
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
53
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
54
+ position: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
55
+ },
56
56
  });
57
57
 
58
58
  /**
59
59
  * Payload for deal moved event.
60
60
  */
61
61
  export const DealMovedPayloadModel = defineSchemaModel({
62
- name: 'DealMovedPayload',
63
- fields: {
64
- dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
65
- fromStage: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
66
- toStage: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
67
- },
62
+ name: 'DealMovedPayload',
63
+ fields: {
64
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
65
+ fromStage: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
66
+ toStage: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
67
+ },
68
68
  });
69
69
 
70
70
  /**
71
71
  * Input for marking a deal as won.
72
72
  */
73
73
  export const WinDealInputModel = defineSchemaModel({
74
- name: 'WinDealInput',
75
- description: 'Input for marking a deal as won',
76
- fields: {
77
- dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
78
- wonSource: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
79
- notes: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
80
- },
74
+ name: 'WinDealInput',
75
+ description: 'Input for marking a deal as won',
76
+ fields: {
77
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
78
+ wonSource: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
79
+ notes: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
80
+ },
81
81
  });
82
82
 
83
83
  /**
84
84
  * Payload for deal won event.
85
85
  */
86
86
  export const DealWonPayloadModel = defineSchemaModel({
87
- name: 'DealWonPayload',
88
- fields: {
89
- dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
90
- value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
91
- },
87
+ name: 'DealWonPayload',
88
+ fields: {
89
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
90
+ value: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
91
+ },
92
92
  });
93
93
 
94
94
  /**
95
95
  * Input for marking a deal as lost.
96
96
  */
97
97
  export const LoseDealInputModel = defineSchemaModel({
98
- name: 'LoseDealInput',
99
- description: 'Input for marking a deal as lost',
100
- fields: {
101
- dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
102
- lostReason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
103
- notes: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
104
- },
98
+ name: 'LoseDealInput',
99
+ description: 'Input for marking a deal as lost',
100
+ fields: {
101
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
102
+ lostReason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
103
+ notes: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
104
+ },
105
105
  });
106
106
 
107
107
  /**
108
108
  * Payload for deal lost event.
109
109
  */
110
110
  export const DealLostPayloadModel = defineSchemaModel({
111
- name: 'DealLostPayload',
112
- fields: {
113
- dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
114
- reason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
115
- },
111
+ name: 'DealLostPayload',
112
+ fields: {
113
+ dealId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
114
+ reason: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
115
+ },
116
116
  });
117
117
 
118
118
  /**
119
119
  * Input for listing deals.
120
120
  */
121
121
  export const ListDealsInputModel = defineSchemaModel({
122
- name: 'ListDealsInput',
123
- description: 'Input for listing deals',
124
- fields: {
125
- pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
126
- stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
127
- status: { type: DealStatusFilterEnum, isOptional: true },
128
- ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
129
- search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
130
- limit: {
131
- type: ScalarTypeEnum.Int_unsecure(),
132
- isOptional: true,
133
- defaultValue: 20,
134
- },
135
- offset: {
136
- type: ScalarTypeEnum.Int_unsecure(),
137
- isOptional: true,
138
- defaultValue: 0,
139
- },
140
- },
122
+ name: 'ListDealsInput',
123
+ description: 'Input for listing deals',
124
+ fields: {
125
+ pipelineId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
126
+ stageId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
127
+ status: { type: DealStatusFilterEnum, isOptional: true },
128
+ ownerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
129
+ search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
130
+ limit: {
131
+ type: ScalarTypeEnum.Int_unsecure(),
132
+ isOptional: true,
133
+ defaultValue: 20,
134
+ },
135
+ offset: {
136
+ type: ScalarTypeEnum.Int_unsecure(),
137
+ isOptional: true,
138
+ defaultValue: 0,
139
+ },
140
+ },
141
141
  });
142
142
 
143
143
  /**
144
144
  * Output for listing deals.
145
145
  */
146
146
  export const ListDealsOutputModel = defineSchemaModel({
147
- name: 'ListDealsOutput',
148
- description: 'Output for listing deals',
149
- fields: {
150
- deals: { type: DealModel, isArray: true, isOptional: false },
151
- total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
152
- totalValue: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
153
- },
147
+ name: 'ListDealsOutput',
148
+ description: 'Output for listing deals',
149
+ fields: {
150
+ deals: { type: DealModel, isArray: true, isOptional: false },
151
+ total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
152
+ totalValue: { type: ScalarTypeEnum.Float_unsecure(), isOptional: false },
153
+ },
154
154
  });
@@ -1,55 +1,55 @@
1
1
  import { defineTestSpec } from '@contractspec/lib.contracts-spec/tests';
2
2
 
3
3
  export const 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
- ],
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
28
  });
29
29
 
30
30
  export const dealMoveTest = defineTestSpec({
31
- meta: {
32
- key: 'test.crm.deal.move',
33
- version: '1.0.0',
34
- owners: ['@example.crm-pipeline'],
35
- description: 'Test for moving deal',
36
- stability: 'stable',
37
- tags: ['test'],
38
- },
39
- target: {
40
- type: 'operation',
41
- operation: { key: 'crm.deal.move', version: '1.0.0' },
42
- },
43
- scenarios: [
44
- {
45
- key: 'success',
46
- when: { operation: { key: 'crm.deal.move' } },
47
- then: [{ type: 'expectOutput', match: {} }],
48
- },
49
- {
50
- key: 'error',
51
- when: { operation: { key: 'crm.deal.move' } },
52
- then: [{ type: 'expectError' }],
53
- },
54
- ],
31
+ meta: {
32
+ key: 'test.crm.deal.move',
33
+ version: '1.0.0',
34
+ owners: ['@example.crm-pipeline'],
35
+ description: 'Test for moving deal',
36
+ stability: 'stable',
37
+ tags: ['test'],
38
+ },
39
+ target: {
40
+ type: 'operation',
41
+ operation: { key: 'crm.deal.move', version: '1.0.0' },
42
+ },
43
+ scenarios: [
44
+ {
45
+ key: 'success',
46
+ when: { operation: { key: 'crm.deal.move' } },
47
+ then: [{ type: 'expectOutput', match: {} }],
48
+ },
49
+ {
50
+ key: 'error',
51
+ when: { operation: { key: 'crm.deal.move' } },
52
+ then: [{ type: 'expectError' }],
53
+ },
54
+ ],
55
55
  });
package/src/deal/index.ts CHANGED
@@ -3,24 +3,22 @@
3
3
  */
4
4
 
5
5
  export { DealStatusEnum, DealStatusFilterEnum } from './deal.enum';
6
-
7
- export {
8
- DealModel,
9
- CreateDealInputModel,
10
- MoveDealInputModel,
11
- DealMovedPayloadModel,
12
- WinDealInputModel,
13
- DealWonPayloadModel,
14
- LoseDealInputModel,
15
- DealLostPayloadModel,
16
- ListDealsInputModel,
17
- ListDealsOutputModel,
18
- } from './deal.schema';
19
-
20
6
  export {
21
- CreateDealContract,
22
- MoveDealContract,
23
- WinDealContract,
24
- LoseDealContract,
25
- ListDealsContract,
7
+ CreateDealContract,
8
+ ListDealsContract,
9
+ LoseDealContract,
10
+ MoveDealContract,
11
+ WinDealContract,
26
12
  } from './deal.operation';
13
+ export {
14
+ CreateDealInputModel,
15
+ DealLostPayloadModel,
16
+ DealModel,
17
+ DealMovedPayloadModel,
18
+ DealWonPayloadModel,
19
+ ListDealsInputModel,
20
+ ListDealsOutputModel,
21
+ LoseDealInputModel,
22
+ MoveDealInputModel,
23
+ WinDealInputModel,
24
+ } from './deal.schema';
@@ -2,16 +2,16 @@ import type { DocBlock } from '@contractspec/lib.contracts-spec/docs';
2
2
  import { registerDocBlocks } from '@contractspec/lib.contracts-spec/docs';
3
3
 
4
4
  const crmPipelineDocBlocks: DocBlock[] = [
5
- {
6
- id: 'docs.examples.crm-pipeline.goal',
7
- title: 'CRM Pipeline — Goal',
8
- summary:
9
- 'Deals, stages, contacts, companies, and tasks with auditable stage movement.',
10
- kind: 'goal',
11
- visibility: 'public',
12
- route: '/docs/examples/crm-pipeline/goal',
13
- tags: ['crm', 'goal'],
14
- body: `## Why it matters
5
+ {
6
+ id: 'docs.examples.crm-pipeline.goal',
7
+ title: 'CRM Pipeline — Goal',
8
+ summary:
9
+ 'Deals, stages, contacts, companies, and tasks with auditable stage movement.',
10
+ kind: 'goal',
11
+ visibility: 'public',
12
+ route: '/docs/examples/crm-pipeline/goal',
13
+ tags: ['crm', 'goal'],
14
+ body: `## Why it matters
15
15
  - Regenerable CRM flow for deals/stages without code drift.
16
16
  - Ensures stage movement, tasks, and contacts stay aligned across surfaces.
17
17
 
@@ -22,16 +22,16 @@ const crmPipelineDocBlocks: DocBlock[] = [
22
22
  ## Success criteria
23
23
  - Stage/state changes emit events and remain declarative in spec.
24
24
  - PII (contacts) is scoped/redacted in presentations.`,
25
- },
26
- {
27
- id: 'docs.examples.crm-pipeline.usage',
28
- title: 'CRM Pipeline — Usage',
29
- summary: 'How to seed, extend, and regenerate the CRM pipeline.',
30
- kind: 'usage',
31
- visibility: 'public',
32
- route: '/docs/examples/crm-pipeline/usage',
33
- tags: ['crm', 'usage'],
34
- body: `## Setup
25
+ },
26
+ {
27
+ id: 'docs.examples.crm-pipeline.usage',
28
+ title: 'CRM Pipeline — Usage',
29
+ summary: 'How to seed, extend, and regenerate the CRM pipeline.',
30
+ kind: 'usage',
31
+ visibility: 'public',
32
+ route: '/docs/examples/crm-pipeline/usage',
33
+ tags: ['crm', 'usage'],
34
+ body: `## Setup
35
35
  1) Seed (if available) or create pipeline stages, deals, contacts, companies, tasks.
36
36
  2) Configure Notifications for stage changes/tasks; set policy.pii for contact data.
37
37
 
@@ -64,17 +64,17 @@ const crmPipelineDocBlocks: DocBlock[] = [
64
64
  4) Wire the generated handler into your existing router.
65
65
  5) Expand to events and presentations as you add surface areas.
66
66
  `,
67
- },
68
- {
69
- id: 'docs.examples.crm-pipeline.reference',
70
- title: 'CRM Pipeline — Reference',
71
- summary:
72
- 'Entities, contracts, events, and presentations for the CRM template.',
73
- kind: 'reference',
74
- visibility: 'public',
75
- route: '/docs/examples/crm-pipeline',
76
- tags: ['crm', 'reference'],
77
- body: `## Entities
67
+ },
68
+ {
69
+ id: 'docs.examples.crm-pipeline.reference',
70
+ title: 'CRM Pipeline — Reference',
71
+ summary:
72
+ 'Entities, contracts, events, and presentations for the CRM template.',
73
+ kind: 'reference',
74
+ visibility: 'public',
75
+ route: '/docs/examples/crm-pipeline',
76
+ tags: ['crm', 'reference'],
77
+ body: `## Entities
78
78
  - Contact, Company, Deal, Pipeline, Stage, Task.
79
79
 
80
80
  ## Contracts
@@ -84,22 +84,22 @@ const crmPipelineDocBlocks: DocBlock[] = [
84
84
  - deal.created, stage.moved, task.completed, contact.updated.
85
85
 
86
86
  ## Presentations
87
- - Pipelines/kanban, deal detail, contact/company profiles, task lists.
87
+ - Pipelines/kanban, deal detail, contact/company profiles, task lists, and a server-mode shared table for the deal list.
88
88
 
89
89
  ## Notes
90
90
  - Stage definitions should be declarative; enforce via spec and regeneration.
91
91
  - Use Notifications for deal/task updates; Audit Trail for state changes.`,
92
- },
93
- {
94
- id: 'docs.examples.crm-pipeline.constraints',
95
- title: 'CRM Pipeline — Constraints & Safety',
96
- summary:
97
- 'Internal guardrails for stages, PII, and regeneration semantics in the CRM template.',
98
- kind: 'reference',
99
- visibility: 'internal',
100
- route: '/docs/examples/crm-pipeline/constraints',
101
- tags: ['crm', 'constraints', 'internal'],
102
- body: `## Constraints
92
+ },
93
+ {
94
+ id: 'docs.examples.crm-pipeline.constraints',
95
+ title: 'CRM Pipeline — Constraints & Safety',
96
+ summary:
97
+ 'Internal guardrails for stages, PII, and regeneration semantics in the CRM template.',
98
+ kind: 'reference',
99
+ visibility: 'internal',
100
+ route: '/docs/examples/crm-pipeline/constraints',
101
+ tags: ['crm', 'constraints', 'internal'],
102
+ body: `## Constraints
103
103
  - Stage definitions/order must remain declarative; no imperative overrides in code.
104
104
  - Events to emit: deal.created, stage.moved, task.completed, contact.updated (minimum).
105
105
  - Regeneration should not alter stage semantics without explicit spec change.
@@ -112,7 +112,7 @@ const crmPipelineDocBlocks: DocBlock[] = [
112
112
  - Add fixtures for stage move rules and SLA/task changes.
113
113
  - Ensure Audit/Notifications remain wired for stage and task events.
114
114
  - Use Feature Flags for experimental stages/SLAs; default safe/off.`,
115
- },
115
+ },
116
116
  ];
117
117
 
118
118
  registerDocBlocks(crmPipelineDocBlocks);
@@ -1,77 +1,77 @@
1
1
  import {
2
- defineEntity,
3
- defineEntityEnum,
4
- field,
5
- index,
2
+ defineEntity,
3
+ defineEntityEnum,
4
+ field,
5
+ index,
6
6
  } from '@contractspec/lib.schema';
7
7
 
8
8
  /**
9
9
  * Company size enum.
10
10
  */
11
11
  export const CompanySizeEnum = defineEntityEnum({
12
- name: 'CompanySize',
13
- values: ['STARTUP', 'SMALL', 'MEDIUM', 'LARGE', 'ENTERPRISE'] as const,
14
- schema: 'crm',
15
- description: 'Size category of a company.',
12
+ name: 'CompanySize',
13
+ values: ['STARTUP', 'SMALL', 'MEDIUM', 'LARGE', 'ENTERPRISE'] as const,
14
+ schema: 'crm',
15
+ description: 'Size category of a company.',
16
16
  });
17
17
 
18
18
  /**
19
19
  * Company entity - organization/account.
20
20
  */
21
21
  export const CompanyEntity = defineEntity({
22
- name: 'Company',
23
- description: 'A company/organization in the CRM.',
24
- schema: 'crm',
25
- map: 'company',
26
- fields: {
27
- id: field.id({ description: 'Unique company ID' }),
22
+ name: 'Company',
23
+ description: 'A company/organization in the CRM.',
24
+ schema: 'crm',
25
+ map: 'company',
26
+ fields: {
27
+ id: field.id({ description: 'Unique company ID' }),
28
28
 
29
- // Basic info
30
- name: field.string({ description: 'Company name' }),
31
- domain: field.string({ isOptional: true, description: 'Website domain' }),
32
- website: field.url({ isOptional: true }),
29
+ // Basic info
30
+ name: field.string({ description: 'Company name' }),
31
+ domain: field.string({ isOptional: true, description: 'Website domain' }),
32
+ website: field.url({ isOptional: true }),
33
33
 
34
- // Industry
35
- industry: field.string({ isOptional: true }),
34
+ // Industry
35
+ industry: field.string({ isOptional: true }),
36
36
 
37
- // Size
38
- size: field.enum('CompanySize', { isOptional: true }),
39
- employeeCount: field.int({ isOptional: true }),
40
- annualRevenue: field.decimal({ isOptional: true }),
37
+ // Size
38
+ size: field.enum('CompanySize', { isOptional: true }),
39
+ employeeCount: field.int({ isOptional: true }),
40
+ annualRevenue: field.decimal({ isOptional: true }),
41
41
 
42
- // Ownership
43
- organizationId: field.foreignKey(),
44
- ownerId: field.foreignKey({ description: 'Account owner' }),
42
+ // Ownership
43
+ organizationId: field.foreignKey(),
44
+ ownerId: field.foreignKey({ description: 'Account owner' }),
45
45
 
46
- // Contact info
47
- phone: field.string({ isOptional: true }),
48
- email: field.email({ isOptional: true }),
46
+ // Contact info
47
+ phone: field.string({ isOptional: true }),
48
+ email: field.email({ isOptional: true }),
49
49
 
50
- // Address
51
- address: field.string({ isOptional: true }),
52
- city: field.string({ isOptional: true }),
53
- state: field.string({ isOptional: true }),
54
- country: field.string({ isOptional: true }),
55
- postalCode: field.string({ isOptional: true }),
50
+ // Address
51
+ address: field.string({ isOptional: true }),
52
+ city: field.string({ isOptional: true }),
53
+ state: field.string({ isOptional: true }),
54
+ country: field.string({ isOptional: true }),
55
+ postalCode: field.string({ isOptional: true }),
56
56
 
57
- // Social
58
- linkedInUrl: field.url({ isOptional: true }),
57
+ // Social
58
+ linkedInUrl: field.url({ isOptional: true }),
59
59
 
60
- // Notes
61
- description: field.string({ isOptional: true }),
62
- tags: field.string({ isArray: true }),
60
+ // Notes
61
+ description: field.string({ isOptional: true }),
62
+ tags: field.string({ isArray: true }),
63
63
 
64
- // Custom fields
65
- customFields: field.json({ isOptional: true }),
64
+ // Custom fields
65
+ customFields: field.json({ isOptional: true }),
66
66
 
67
- // Timestamps
68
- createdAt: field.createdAt(),
69
- updatedAt: field.updatedAt(),
67
+ // Timestamps
68
+ createdAt: field.createdAt(),
69
+ updatedAt: field.updatedAt(),
70
70
 
71
- // Relations
72
- contacts: field.hasMany('Contact'),
73
- deals: field.hasMany('Deal'),
74
- },
75
- indexes: [index.on(['organizationId', 'ownerId']), index.on(['domain'])],
76
- enums: [CompanySizeEnum],
71
+ // Relations
72
+ contacts: field.hasMany('Contact'),
73
+ deals: field.hasMany('Deal'),
74
+ },
75
+ indexes: [index.on(['organizationId', 'ownerId']), index.on(['domain'])],
76
+ enums: [CompanySizeEnum],
77
77
  });