business-as-code 2.1.3 → 2.4.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 (235) hide show
  1. package/.turbo/turbo-build.log +4 -5
  2. package/CHANGELOG.md +53 -0
  3. package/README.md +2 -0
  4. package/dist/dollar.d.ts.map +1 -1
  5. package/dist/dollar.js +2 -2
  6. package/dist/dollar.js.map +1 -1
  7. package/dist/entities/organization.d.ts +4 -0
  8. package/dist/entities/organization.d.ts.map +1 -1
  9. package/dist/entities/organization.js +27 -18
  10. package/dist/entities/organization.js.map +1 -1
  11. package/dist/entities/planning.d.ts +87 -0
  12. package/dist/finance/account.d.ts +44 -0
  13. package/dist/finance/account.d.ts.map +1 -0
  14. package/dist/finance/account.js +6 -0
  15. package/dist/finance/account.js.map +1 -0
  16. package/dist/finance/authority.d.ts +78 -0
  17. package/dist/finance/authority.d.ts.map +1 -0
  18. package/dist/finance/authority.js +27 -0
  19. package/dist/finance/authority.js.map +1 -0
  20. package/dist/finance/card.d.ts +36 -0
  21. package/dist/finance/card.d.ts.map +1 -0
  22. package/dist/finance/card.js +6 -0
  23. package/dist/finance/card.js.map +1 -0
  24. package/dist/finance/identity.d.ts +30 -0
  25. package/dist/finance/identity.d.ts.map +1 -0
  26. package/dist/finance/identity.js +8 -0
  27. package/dist/finance/identity.js.map +1 -0
  28. package/dist/finance/index.d.ts +36 -0
  29. package/dist/finance/index.d.ts.map +1 -0
  30. package/dist/finance/index.js +22 -0
  31. package/dist/finance/index.js.map +1 -0
  32. package/dist/finance/ledger.d.ts +24 -0
  33. package/dist/finance/ledger.d.ts.map +1 -0
  34. package/dist/finance/ledger.js +8 -0
  35. package/dist/finance/ledger.js.map +1 -0
  36. package/dist/finance/merchant.d.ts +129 -0
  37. package/dist/finance/merchant.d.ts.map +1 -0
  38. package/dist/finance/merchant.js +21 -0
  39. package/dist/finance/merchant.js.map +1 -0
  40. package/dist/finance/outcome-contract.d.ts +139 -0
  41. package/dist/finance/outcome-contract.d.ts.map +1 -0
  42. package/dist/finance/outcome-contract.js +27 -0
  43. package/dist/finance/outcome-contract.js.map +1 -0
  44. package/dist/finance/port.d.ts +121 -0
  45. package/dist/finance/port.d.ts.map +1 -0
  46. package/dist/finance/port.js +10 -0
  47. package/dist/finance/port.js.map +1 -0
  48. package/dist/finance/pricing.d.ts +154 -0
  49. package/dist/finance/pricing.d.ts.map +1 -0
  50. package/dist/finance/pricing.js +79 -0
  51. package/dist/finance/pricing.js.map +1 -0
  52. package/dist/finance/proof-predicate.d.ts +92 -0
  53. package/dist/finance/proof-predicate.d.ts.map +1 -0
  54. package/dist/finance/proof-predicate.js +80 -0
  55. package/dist/finance/proof-predicate.js.map +1 -0
  56. package/dist/finance/refund.d.ts +44 -0
  57. package/dist/finance/refund.d.ts.map +1 -0
  58. package/dist/finance/refund.js +41 -0
  59. package/dist/finance/refund.js.map +1 -0
  60. package/dist/finance/sla.d.ts +25 -0
  61. package/dist/finance/sla.d.ts.map +1 -0
  62. package/dist/finance/sla.js +7 -0
  63. package/dist/finance/sla.js.map +1 -0
  64. package/dist/finance/types.d.ts +79 -0
  65. package/dist/finance/types.d.ts.map +1 -0
  66. package/dist/finance/types.js +8 -0
  67. package/dist/{canvas → finance}/types.js.map +1 -1
  68. package/dist/goals.d.ts +19 -0
  69. package/dist/goals.d.ts.map +1 -1
  70. package/dist/goals.js +81 -12
  71. package/dist/goals.js.map +1 -1
  72. package/dist/index.d.ts +12 -8
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +19 -7
  75. package/dist/index.js.map +1 -1
  76. package/dist/kpis.d.ts +19 -0
  77. package/dist/kpis.d.ts.map +1 -1
  78. package/dist/kpis.js +71 -6
  79. package/dist/kpis.js.map +1 -1
  80. package/dist/metrics.d.ts.map +1 -1
  81. package/dist/metrics.js +29 -24
  82. package/dist/metrics.js.map +1 -1
  83. package/dist/okrs.d.ts +34 -0
  84. package/dist/okrs.d.ts.map +1 -1
  85. package/dist/okrs.js +135 -13
  86. package/dist/okrs.js.map +1 -1
  87. package/dist/organization.d.ts.map +1 -1
  88. package/dist/organization.js +11 -11
  89. package/dist/organization.js.map +1 -1
  90. package/dist/process.d.ts.map +1 -1
  91. package/dist/process.js +13 -12
  92. package/dist/process.js.map +1 -1
  93. package/dist/product.d.ts.map +1 -1
  94. package/dist/product.js +9 -9
  95. package/dist/product.js.map +1 -1
  96. package/dist/queries.d.ts.map +1 -1
  97. package/dist/queries.js +194 -32
  98. package/dist/queries.js.map +1 -1
  99. package/dist/roles.d.ts +25 -31
  100. package/dist/roles.d.ts.map +1 -1
  101. package/dist/roles.js +37 -10
  102. package/dist/roles.js.map +1 -1
  103. package/dist/workflow.d.ts.map +1 -1
  104. package/dist/workflow.js +13 -12
  105. package/dist/workflow.js.map +1 -1
  106. package/package.json +20 -13
  107. package/src/dollar.ts +5 -2
  108. package/src/entities/organization.ts +31 -18
  109. package/src/finance/account.ts +48 -0
  110. package/src/finance/authority.ts +42 -0
  111. package/src/finance/card.ts +38 -0
  112. package/src/finance/identity.ts +31 -0
  113. package/src/finance/index.ts +117 -0
  114. package/src/finance/ledger.ts +26 -0
  115. package/src/finance/merchant.ts +127 -0
  116. package/src/finance/outcome-contract.ts +157 -0
  117. package/src/finance/port.ts +144 -0
  118. package/src/finance/pricing.ts +197 -0
  119. package/src/finance/proof-predicate.ts +106 -0
  120. package/src/finance/refund.ts +52 -0
  121. package/src/finance/sla.ts +33 -0
  122. package/src/finance/types.ts +75 -0
  123. package/src/goals.ts +78 -12
  124. package/src/index.ts +48 -18
  125. package/src/kpis.ts +62 -8
  126. package/src/metrics.ts +92 -79
  127. package/src/okrs.ts +120 -20
  128. package/src/organization.ts +12 -15
  129. package/src/process.ts +11 -12
  130. package/src/product.ts +8 -9
  131. package/src/queries.ts +238 -75
  132. package/src/roles.ts +62 -61
  133. package/src/workflow.ts +22 -15
  134. package/test/business.test.ts +282 -0
  135. package/test/dollar.test.ts +270 -0
  136. package/test/entities.test.ts +628 -0
  137. package/test/financials.test.ts +539 -0
  138. package/test/goals.test.ts +451 -0
  139. package/{src → test}/index.test.ts +1 -1
  140. package/test/kpis.test.ts +440 -0
  141. package/test/metrics.test.ts +744 -0
  142. package/test/okrs.test.ts +741 -0
  143. package/test/organization.test.ts +548 -0
  144. package/test/process.test.ts +503 -0
  145. package/test/product.test.ts +430 -0
  146. package/test/queries.test.ts +556 -0
  147. package/test/roles.test.ts +546 -0
  148. package/test/service.test.ts +450 -0
  149. package/test/types.test.ts +1141 -0
  150. package/test/vision.test.ts +214 -0
  151. package/test/workflow.test.ts +501 -0
  152. package/vitest.config.ts +47 -0
  153. package/LICENSE +0 -21
  154. package/dist/canvas/activities.d.ts +0 -19
  155. package/dist/canvas/activities.d.ts.map +0 -1
  156. package/dist/canvas/activities.js +0 -20
  157. package/dist/canvas/activities.js.map +0 -1
  158. package/dist/canvas/channels.d.ts +0 -20
  159. package/dist/canvas/channels.d.ts.map +0 -1
  160. package/dist/canvas/channels.js +0 -21
  161. package/dist/canvas/channels.js.map +0 -1
  162. package/dist/canvas/relationships.d.ts +0 -20
  163. package/dist/canvas/relationships.d.ts.map +0 -1
  164. package/dist/canvas/relationships.js +0 -21
  165. package/dist/canvas/relationships.js.map +0 -1
  166. package/dist/canvas/resources.d.ts +0 -20
  167. package/dist/canvas/resources.d.ts.map +0 -1
  168. package/dist/canvas/resources.js +0 -30
  169. package/dist/canvas/resources.js.map +0 -1
  170. package/dist/canvas/revenue.d.ts +0 -22
  171. package/dist/canvas/revenue.d.ts.map +0 -1
  172. package/dist/canvas/revenue.js +0 -30
  173. package/dist/canvas/revenue.js.map +0 -1
  174. package/dist/canvas/segments.d.ts +0 -20
  175. package/dist/canvas/segments.d.ts.map +0 -1
  176. package/dist/canvas/segments.js +0 -28
  177. package/dist/canvas/segments.js.map +0 -1
  178. package/dist/canvas/types.d.ts +0 -232
  179. package/dist/canvas/types.d.ts.map +0 -1
  180. package/dist/canvas/types.js +0 -8
  181. package/dist/canvas/value.d.ts +0 -20
  182. package/dist/canvas/value.d.ts.map +0 -1
  183. package/dist/canvas/value.js +0 -21
  184. package/dist/canvas/value.js.map +0 -1
  185. package/src/business.js +0 -108
  186. package/src/canvas/activities.ts +0 -32
  187. package/src/canvas/canvas.ts +0 -482
  188. package/src/canvas/channels.ts +0 -34
  189. package/src/canvas/costs.ts +0 -43
  190. package/src/canvas/economics.ts +0 -99
  191. package/src/canvas/index.ts +0 -206
  192. package/src/canvas/partnerships.ts +0 -34
  193. package/src/canvas/projections.ts +0 -141
  194. package/src/canvas/relationships.ts +0 -34
  195. package/src/canvas/resources.ts +0 -43
  196. package/src/canvas/revenue.ts +0 -56
  197. package/src/canvas/segments.ts +0 -42
  198. package/src/canvas/types.ts +0 -363
  199. package/src/canvas/value.ts +0 -34
  200. package/src/dollar.js +0 -106
  201. package/src/entities/assets.js +0 -322
  202. package/src/entities/business.js +0 -369
  203. package/src/entities/communication.js +0 -254
  204. package/src/entities/customers.js +0 -988
  205. package/src/entities/financials.js +0 -931
  206. package/src/entities/goals.js +0 -799
  207. package/src/entities/index.js +0 -197
  208. package/src/entities/legal.js +0 -300
  209. package/src/entities/market.js +0 -300
  210. package/src/entities/marketing.js +0 -1156
  211. package/src/entities/offerings.js +0 -726
  212. package/src/entities/operations.js +0 -786
  213. package/src/entities/organization.js +0 -806
  214. package/src/entities/partnerships.js +0 -299
  215. package/src/entities/planning.js +0 -270
  216. package/src/entities/projects.js +0 -348
  217. package/src/entities/risk.js +0 -292
  218. package/src/entities/sales.js +0 -1247
  219. package/src/financials.js +0 -296
  220. package/src/goals.js +0 -214
  221. package/src/index.js +0 -131
  222. package/src/index.test.js +0 -274
  223. package/src/kpis.js +0 -231
  224. package/src/metrics.js +0 -324
  225. package/src/okrs.js +0 -268
  226. package/src/organization.js +0 -172
  227. package/src/process.js +0 -240
  228. package/src/product.js +0 -144
  229. package/src/queries.js +0 -414
  230. package/src/roles.js +0 -254
  231. package/src/service.js +0 -139
  232. package/src/types.js +0 -4
  233. package/src/vision.js +0 -67
  234. package/src/workflow.js +0 -246
  235. package/tests/canvas.test.ts +0 -842
package/src/okrs.ts CHANGED
@@ -1,8 +1,106 @@
1
1
  /**
2
2
  * Objectives and Key Results (OKRs) management
3
+ *
4
+ * Uses org.ai OKR types for standardized OKR definitions across the ecosystem.
3
5
  */
4
6
 
5
7
  import type { OKRDefinition, KeyResult } from './types.js'
8
+ import type { OKR as OrgOKR, KeyResult as OrgKeyResult, OKRStatus, KeyResultStatus } from 'org.ai'
9
+
10
+ // Re-export org.ai OKR types for convenience
11
+ export type { OrgOKR, OrgKeyResult, OKRStatus, KeyResultStatus }
12
+
13
+ /**
14
+ * Convert a business-as-code KeyResult to an org.ai KeyResult
15
+ *
16
+ * @param kr - Business key result
17
+ * @param id - Optional identifier
18
+ * @returns org.ai KeyResult object
19
+ */
20
+ export function toOrgKeyResult(kr: KeyResult, id?: string): OrgKeyResult {
21
+ const result: OrgKeyResult = {
22
+ description: kr.description,
23
+ }
24
+ if (id !== undefined) result.id = id
25
+ if (kr.description) result.name = kr.description
26
+ if (kr.metric !== undefined) result.metric = kr.metric
27
+ if (kr.startValue !== undefined) result.startValue = kr.startValue
28
+ if (kr.targetValue !== undefined) {
29
+ result.targetValue = kr.targetValue
30
+ result.target = kr.targetValue
31
+ }
32
+ if (kr.currentValue !== undefined) {
33
+ result.currentValue = kr.currentValue
34
+ result.current = kr.currentValue
35
+ }
36
+ if (kr.unit !== undefined) result.unit = kr.unit
37
+ if (kr.progress !== undefined) result.progress = kr.progress
38
+ return result
39
+ }
40
+
41
+ /**
42
+ * Convert an org.ai KeyResult to a business-as-code KeyResult
43
+ *
44
+ * @param kr - org.ai KeyResult object
45
+ * @returns Business key result
46
+ */
47
+ export function fromOrgKeyResult(kr: OrgKeyResult): KeyResult {
48
+ const result: KeyResult = {
49
+ description: kr.description || kr.name || '',
50
+ metric: kr.metric || '',
51
+ targetValue: kr.targetValue ?? kr.target ?? 0,
52
+ }
53
+ if (kr.startValue !== undefined) result.startValue = kr.startValue
54
+ if (kr.currentValue !== undefined) result.currentValue = kr.currentValue
55
+ else if (kr.current !== undefined) result.currentValue = kr.current
56
+ if (kr.unit !== undefined) result.unit = kr.unit
57
+ if (kr.progress !== undefined) result.progress = kr.progress
58
+ return result
59
+ }
60
+
61
+ /**
62
+ * Convert a business-as-code OKRDefinition to an org.ai OKR
63
+ *
64
+ * @param definition - Business OKR definition
65
+ * @param id - Optional unique identifier
66
+ * @returns org.ai OKR object
67
+ */
68
+ export function toOrgOKR(definition: OKRDefinition, id?: string): OrgOKR {
69
+ const result: OrgOKR = {
70
+ objective: definition.objective,
71
+ keyResults: definition.keyResults?.map((kr, i) => toOrgKeyResult(kr, `${id}_kr_${i}`)) || [],
72
+ }
73
+ if (id !== undefined) result.id = id
74
+ if (definition.description !== undefined) result.description = definition.description
75
+ if (definition.owner !== undefined) result.owner = definition.owner
76
+ if (definition.period !== undefined) result.period = definition.period
77
+ if (definition.status !== undefined) result.status = definition.status as OKRStatus
78
+ result.progress = calculateOKRProgress(definition)
79
+ if (definition.confidence !== undefined) result.confidence = definition.confidence
80
+ if (definition.metadata !== undefined) result.metadata = definition.metadata
81
+ return result
82
+ }
83
+
84
+ /**
85
+ * Convert an org.ai OKR to a business-as-code OKRDefinition
86
+ *
87
+ * @param okr - org.ai OKR object
88
+ * @returns Business OKR definition
89
+ */
90
+ export function fromOrgOKR(okr: OrgOKR): OKRDefinition {
91
+ const result: OKRDefinition = {
92
+ objective: okr.objective,
93
+ keyResults: okr.keyResults.map(fromOrgKeyResult),
94
+ }
95
+ if (okr.description !== undefined) result.description = okr.description
96
+ if (okr.owner !== undefined) result.owner = okr.owner
97
+ if (okr.period !== undefined) result.period = okr.period
98
+ const st = okr.status
99
+ if (st !== undefined) result.status = st as NonNullable<OKRDefinition['status']>
100
+ if (okr.confidence !== undefined) result.confidence = okr.confidence
101
+ if (okr.metadata !== undefined) result.metadata = okr.metadata
102
+ return result
103
+ }
6
104
 
7
105
  /**
8
106
  * Define Objectives and Key Results for goal tracking
@@ -51,7 +149,7 @@ import type { OKRDefinition, KeyResult } from './types.js'
51
149
  * ```
52
150
  */
53
151
  export function okrs(definitions: OKRDefinition[]): OKRDefinition[] {
54
- return definitions.map(okr => validateAndNormalizeOKR(okr))
152
+ return definitions.map((okr) => validateAndNormalizeOKR(okr))
55
153
  }
56
154
 
57
155
  /**
@@ -70,18 +168,19 @@ function validateAndNormalizeOKR(okr: OKRDefinition): OKRDefinition {
70
168
  }
71
169
 
72
170
  // Calculate progress for key results if not set
73
- const keyResults = okr.keyResults?.map(kr => ({
171
+ const keyResults = okr.keyResults?.map((kr) => ({
74
172
  ...kr,
75
173
  progress: kr.progress ?? calculateKeyResultProgress(kr),
76
174
  }))
77
175
 
78
- return {
176
+ const result: OKRDefinition = {
79
177
  ...okr,
80
- keyResults,
81
178
  status: okr.status || 'not-started',
82
179
  confidence: okr.confidence ?? calculateConfidence(keyResults || []),
83
180
  metadata: okr.metadata || {},
84
181
  }
182
+ if (keyResults !== undefined) result.keyResults = keyResults
183
+ return result
85
184
  }
86
185
 
87
186
  /**
@@ -136,7 +235,7 @@ export function updateKeyResult(
136
235
  krDescription: string,
137
236
  currentValue: number
138
237
  ): OKRDefinition {
139
- const keyResults = okr.keyResults?.map(kr => {
238
+ const keyResults = okr.keyResults?.map((kr) => {
140
239
  if (kr.description === krDescription) {
141
240
  const updatedKR = { ...kr, currentValue }
142
241
  return {
@@ -148,24 +247,24 @@ export function updateKeyResult(
148
247
  })
149
248
 
150
249
  // Recalculate overall status and confidence
151
- const progress = calculateOKRProgress({ ...okr, keyResults })
250
+ const okrWithKeyResults: OKRDefinition = { ...okr }
251
+ if (keyResults !== undefined) okrWithKeyResults.keyResults = keyResults
252
+ const progress = calculateOKRProgress(okrWithKeyResults)
152
253
  const status = determineOKRStatus(progress, okr.confidence || 0)
153
254
 
154
- return {
255
+ const result: OKRDefinition = {
155
256
  ...okr,
156
- keyResults,
157
- status,
158
257
  confidence: calculateConfidence(keyResults || []),
159
258
  }
259
+ if (keyResults !== undefined) result.keyResults = keyResults
260
+ if (status !== undefined) result.status = status
261
+ return result
160
262
  }
161
263
 
162
264
  /**
163
265
  * Determine OKR status based on progress and confidence
164
266
  */
165
- function determineOKRStatus(
166
- progress: number,
167
- confidence: number
168
- ): OKRDefinition['status'] {
267
+ function determineOKRStatus(progress: number, confidence: number): OKRDefinition['status'] {
169
268
  if (progress === 0) return 'not-started'
170
269
  if (progress === 100) return 'completed'
171
270
  if (confidence < 50 || progress < 30) return 'at-risk'
@@ -199,21 +298,21 @@ export function getKeyResultsOnTrack(okr: OKRDefinition): KeyResult[] {
199
298
  * Get key results that are at risk
200
299
  */
201
300
  export function getKeyResultsAtRisk(okr: OKRDefinition): KeyResult[] {
202
- return okr.keyResults?.filter(kr => !isKeyResultOnTrack(kr)) || []
301
+ return okr.keyResults?.filter((kr) => !isKeyResultOnTrack(kr)) || []
203
302
  }
204
303
 
205
304
  /**
206
305
  * Get OKRs by owner
207
306
  */
208
307
  export function getOKRsByOwner(okrs: OKRDefinition[], owner: string): OKRDefinition[] {
209
- return okrs.filter(okr => okr.owner === owner)
308
+ return okrs.filter((okr) => okr.owner === owner)
210
309
  }
211
310
 
212
311
  /**
213
312
  * Get OKRs by period
214
313
  */
215
314
  export function getOKRsByPeriod(okrs: OKRDefinition[], period: string): OKRDefinition[] {
216
- return okrs.filter(okr => okr.period === period)
315
+ return okrs.filter((okr) => okr.period === period)
217
316
  }
218
317
 
219
318
  /**
@@ -223,7 +322,7 @@ export function getOKRsByStatus(
223
322
  okrs: OKRDefinition[],
224
323
  status: OKRDefinition['status']
225
324
  ): OKRDefinition[] {
226
- return okrs.filter(okr => okr.status === status)
325
+ return okrs.filter((okr) => okr.status === status)
227
326
  }
228
327
 
229
328
  /**
@@ -232,9 +331,10 @@ export function getOKRsByStatus(
232
331
  export function calculateSuccessRate(okrs: OKRDefinition[]): number {
233
332
  if (okrs.length === 0) return 0
234
333
 
235
- const avgProgress = okrs.reduce((sum, okr) => {
236
- return sum + calculateOKRProgress(okr)
237
- }, 0) / okrs.length
334
+ const avgProgress =
335
+ okrs.reduce((sum, okr) => {
336
+ return sum + calculateOKRProgress(okr)
337
+ }, 0) / okrs.length
238
338
 
239
339
  return avgProgress
240
340
  }
@@ -741,7 +741,7 @@ export function resolvePermissions(
741
741
  // Search through hierarchy
742
742
  for (const dept of org.departments || []) {
743
743
  for (const t of dept.teams || []) {
744
- const pos = t.positions?.find(p => p.id === positionId)
744
+ const pos = t.positions?.find((p) => p.id === positionId)
745
745
  if (pos) {
746
746
  position = pos
747
747
  team = t
@@ -755,7 +755,7 @@ export function resolvePermissions(
755
755
  // Also check standalone teams
756
756
  if (!position) {
757
757
  for (const t of org.teams || []) {
758
- const pos = t.positions?.find(p => p.id === positionId)
758
+ const pos = t.positions?.find((p) => p.id === positionId)
759
759
  if (pos) {
760
760
  position = pos
761
761
  team = t
@@ -767,7 +767,7 @@ export function resolvePermissions(
767
767
  if (!position) return null
768
768
 
769
769
  // Find the role
770
- const role = org.roles?.find(r => r.id === position.roleId)
770
+ const role = org.roles?.find((r) => r['id'] === position.roleId)
771
771
 
772
772
  // Build inheritance chain
773
773
  const inheritanceChain: string[] = []
@@ -803,16 +803,16 @@ export function resolvePermissions(
803
803
 
804
804
  // 4. Role permissions
805
805
  if (role?.permissions) {
806
- inheritanceChain.push(`role:${role.id}`)
806
+ inheritanceChain.push(`role:${role['id']}`)
807
807
  mergePermissions(permissions, role.permissions)
808
808
  }
809
809
 
810
810
  // 5. Role capabilities
811
- if (role?.canApprove) {
812
- canApprove.push(...role.canApprove)
811
+ if (role?.['canApprove']) {
812
+ canApprove.push(...role['canApprove'])
813
813
  }
814
- if (role?.canHandle) {
815
- canHandle.push(...role.canHandle)
814
+ if (role?.['canHandle']) {
815
+ canHandle.push(...role['canHandle'])
816
816
  }
817
817
 
818
818
  // 6. Position-specific permissions
@@ -867,7 +867,7 @@ export function getApprovalChainForRequest(
867
867
  requestType: string,
868
868
  amount?: number
869
869
  ): ApproverSpec[] {
870
- const chain = org.approvalChains?.find(c => c.type === requestType && c.active !== false)
870
+ const chain = org.approvalChains?.find((c) => c.type === requestType && c.active !== false)
871
871
  if (!chain) return []
872
872
 
873
873
  // Find the appropriate level based on amount
@@ -886,19 +886,16 @@ export function getApprovalChainForRequest(
886
886
  /**
887
887
  * Find manager for a position (follows reportsTo chain)
888
888
  */
889
- export function findManager(
890
- org: Organization,
891
- positionId: string
892
- ): Position | null {
889
+ export function findManager(org: Organization, positionId: string): Position | null {
893
890
  // Find the position
894
891
  for (const dept of org.departments || []) {
895
892
  for (const team of dept.teams || []) {
896
- const position = team.positions?.find(p => p.id === positionId)
893
+ const position = team.positions?.find((p) => p.id === positionId)
897
894
  if (position?.reportsTo) {
898
895
  // Find the manager position
899
896
  for (const d of org.departments || []) {
900
897
  for (const t of d.teams || []) {
901
- const manager = t.positions?.find(p => p.id === position.reportsTo)
898
+ const manager = t.positions?.find((p) => p.id === position.reportsTo)
902
899
  if (manager) return manager
903
900
  }
904
901
  }
package/src/process.ts CHANGED
@@ -89,7 +89,7 @@ export function getStepsByAutomationLevel(
89
89
  process: ProcessDefinition,
90
90
  level: ProcessStep['automationLevel']
91
91
  ): ProcessStep[] {
92
- return process.steps?.filter(step => step.automationLevel === level) || []
92
+ return process.steps?.filter((step) => step.automationLevel === level) || []
93
93
  }
94
94
 
95
95
  /**
@@ -160,7 +160,7 @@ export function calculateAutomationPercentage(process: ProcessDefinition): numbe
160
160
  if (!process.steps || process.steps.length === 0) return 0
161
161
 
162
162
  const automatedSteps = process.steps.filter(
163
- step => step.automationLevel === 'automated' || step.automationLevel === 'semi-automated'
163
+ (step) => step.automationLevel === 'automated' || step.automationLevel === 'semi-automated'
164
164
  ).length
165
165
 
166
166
  return (automatedSteps / process.steps.length) * 100
@@ -170,7 +170,7 @@ export function calculateAutomationPercentage(process: ProcessDefinition): numbe
170
170
  * Get metric by name
171
171
  */
172
172
  export function getMetric(process: ProcessDefinition, name: string): ProcessMetric | undefined {
173
- return process.metrics?.find(m => m.name === name)
173
+ return process.metrics?.find((m) => m.name === name)
174
174
  }
175
175
 
176
176
  /**
@@ -198,14 +198,13 @@ export function updateMetric(
198
198
  metricName: string,
199
199
  currentValue: number
200
200
  ): ProcessDefinition {
201
- const metrics = process.metrics?.map(m =>
201
+ const metrics = process.metrics?.map((m) =>
202
202
  m.name === metricName ? { ...m, current: currentValue } : m
203
203
  )
204
204
 
205
- return {
206
- ...process,
207
- metrics,
208
- }
205
+ const result: ProcessDefinition = { ...process }
206
+ if (metrics !== undefined) result.metrics = metrics
207
+ return result
209
208
  }
210
209
 
211
210
  /**
@@ -222,10 +221,10 @@ export function addStep(process: ProcessDefinition, step: ProcessStep): ProcessD
222
221
  * Remove step from process
223
222
  */
224
223
  export function removeStep(process: ProcessDefinition, stepOrder: number): ProcessDefinition {
225
- return {
226
- ...process,
227
- steps: process.steps?.filter(s => s.order !== stepOrder),
228
- }
224
+ const steps = process.steps?.filter((s) => s.order !== stepOrder)
225
+ const result: ProcessDefinition = { ...process }
226
+ if (steps !== undefined) result.steps = steps
227
+ return result
229
228
  }
230
229
 
231
230
  /**
package/src/product.ts CHANGED
@@ -82,7 +82,7 @@ export function getRoadmapByStatus(
82
82
  product: ProductDefinition,
83
83
  status: RoadmapItem['status']
84
84
  ): RoadmapItem[] {
85
- return product.roadmap?.filter(item => item.status === status) || []
85
+ return product.roadmap?.filter((item) => item.status === status) || []
86
86
  }
87
87
 
88
88
  /**
@@ -92,7 +92,7 @@ export function getRoadmapByPriority(
92
92
  product: ProductDefinition,
93
93
  priority: RoadmapItem['priority']
94
94
  ): RoadmapItem[] {
95
- return product.roadmap?.filter(item => item.priority === priority) || []
95
+ return product.roadmap?.filter((item) => item.priority === priority) || []
96
96
  }
97
97
 
98
98
  /**
@@ -102,7 +102,7 @@ export function getOverdueRoadmapItems(product: ProductDefinition): RoadmapItem[
102
102
  const now = new Date()
103
103
  return (
104
104
  product.roadmap?.filter(
105
- item =>
105
+ (item) =>
106
106
  item.targetDate &&
107
107
  item.targetDate < now &&
108
108
  item.status !== 'completed' &&
@@ -119,14 +119,13 @@ export function updateRoadmapItem(
119
119
  itemName: string,
120
120
  updates: Partial<RoadmapItem>
121
121
  ): ProductDefinition {
122
- const roadmap = product.roadmap?.map(item =>
122
+ const roadmap = product.roadmap?.map((item) =>
123
123
  item.name === itemName ? { ...item, ...updates } : item
124
124
  )
125
125
 
126
- return {
127
- ...product,
128
- roadmap,
129
- }
126
+ const result: ProductDefinition = { ...product }
127
+ if (roadmap !== undefined) result.roadmap = roadmap
128
+ return result
130
129
  }
131
130
 
132
131
  /**
@@ -145,7 +144,7 @@ export function addFeature(product: ProductDefinition, feature: string): Product
145
144
  export function removeFeature(product: ProductDefinition, feature: string): ProductDefinition {
146
145
  return {
147
146
  ...product,
148
- features: product.features?.filter(f => f !== feature) || [],
147
+ features: product.features?.filter((f) => f !== feature) || [],
149
148
  }
150
149
  }
151
150