@pikku/core 0.11.0 → 0.11.2

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 (184) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/errors/error-handler.js +3 -3
  3. package/dist/errors/errors.d.ts +1 -1
  4. package/dist/errors/errors.js +3 -3
  5. package/dist/function/function-runner.d.ts +8 -8
  6. package/dist/function/function-runner.js +88 -23
  7. package/dist/function/functions.types.d.ts +104 -33
  8. package/dist/function/functions.types.js +50 -7
  9. package/dist/handle-error.d.ts +1 -1
  10. package/dist/handle-error.js +1 -1
  11. package/dist/index.d.ts +6 -2
  12. package/dist/index.js +5 -2
  13. package/dist/middleware/auth-apikey.d.ts +1 -1
  14. package/dist/middleware/auth-apikey.js +3 -3
  15. package/dist/middleware/auth-bearer.d.ts +1 -1
  16. package/dist/middleware/auth-bearer.js +3 -3
  17. package/dist/middleware/auth-cookie.d.ts +1 -1
  18. package/dist/middleware/auth-cookie.js +5 -5
  19. package/dist/middleware/timeout.d.ts +1 -1
  20. package/dist/middleware/timeout.js +3 -2
  21. package/dist/middleware-runner.d.ts +6 -20
  22. package/dist/middleware-runner.js +19 -20
  23. package/dist/permissions.d.ts +6 -89
  24. package/dist/permissions.js +24 -81
  25. package/dist/pikku-state.d.ts +32 -104
  26. package/dist/pikku-state.js +140 -66
  27. package/dist/schema.d.ts +8 -6
  28. package/dist/schema.js +25 -13
  29. package/dist/services/user-session-service.d.ts +7 -3
  30. package/dist/services/user-session-service.js +8 -1
  31. package/dist/services/workflow-service.d.ts +38 -0
  32. package/dist/services/workflow-service.js +1 -0
  33. package/dist/types/core.types.d.ts +40 -41
  34. package/dist/types/core.types.js +4 -15
  35. package/dist/types/state.types.d.ts +135 -0
  36. package/dist/types/state.types.js +1 -0
  37. package/dist/utils.d.ts +9 -1
  38. package/dist/utils.js +48 -3
  39. package/dist/wirings/channel/channel-common.js +2 -3
  40. package/dist/wirings/channel/channel-handler.d.ts +3 -2
  41. package/dist/wirings/channel/channel-handler.js +7 -10
  42. package/dist/wirings/channel/channel-runner.d.ts +2 -2
  43. package/dist/wirings/channel/channel-runner.js +5 -5
  44. package/dist/wirings/channel/channel.types.d.ts +10 -5
  45. package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
  46. package/dist/wirings/channel/local/local-channel-runner.js +19 -26
  47. package/dist/wirings/channel/log-channels.js +1 -1
  48. package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
  49. package/dist/wirings/channel/serverless/serverless-channel-runner.js +43 -48
  50. package/dist/wirings/cli/channel/cli-channel-runner.js +3 -2
  51. package/dist/wirings/cli/cli-runner.d.ts +5 -5
  52. package/dist/wirings/cli/cli-runner.js +20 -38
  53. package/dist/wirings/cli/cli.types.d.ts +16 -11
  54. package/dist/wirings/forge-node/forge-node.types.d.ts +120 -0
  55. package/dist/wirings/forge-node/forge-node.types.js +38 -0
  56. package/dist/wirings/forge-node/index.d.ts +1 -0
  57. package/dist/wirings/forge-node/index.js +1 -0
  58. package/dist/wirings/http/http-runner.d.ts +8 -8
  59. package/dist/wirings/http/http-runner.js +46 -51
  60. package/dist/wirings/http/http.types.d.ts +19 -11
  61. package/dist/wirings/http/log-http-routes.js +1 -1
  62. package/dist/wirings/http/routers/path-to-regex.js +2 -2
  63. package/dist/wirings/mcp/mcp-runner.d.ts +2 -2
  64. package/dist/wirings/mcp/mcp-runner.js +33 -40
  65. package/dist/wirings/mcp/mcp.types.d.ts +6 -0
  66. package/dist/wirings/queue/queue-runner.d.ts +3 -3
  67. package/dist/wirings/queue/queue-runner.js +13 -23
  68. package/dist/wirings/queue/queue.types.d.ts +4 -11
  69. package/dist/wirings/rpc/index.d.ts +1 -1
  70. package/dist/wirings/rpc/index.js +1 -1
  71. package/dist/wirings/rpc/rpc-runner.d.ts +17 -16
  72. package/dist/wirings/rpc/rpc-runner.js +98 -61
  73. package/dist/wirings/rpc/rpc-types.d.ts +7 -0
  74. package/dist/wirings/scheduler/log-schedulers.js +1 -1
  75. package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -3
  76. package/dist/wirings/scheduler/scheduler-runner.js +18 -29
  77. package/dist/wirings/scheduler/scheduler.types.d.ts +3 -8
  78. package/dist/wirings/trigger/index.d.ts +2 -0
  79. package/dist/wirings/trigger/index.js +2 -0
  80. package/dist/wirings/trigger/trigger-runner.d.ts +29 -0
  81. package/dist/wirings/trigger/trigger-runner.js +57 -0
  82. package/dist/wirings/trigger/trigger.types.d.ts +42 -0
  83. package/dist/wirings/trigger/trigger.types.js +1 -0
  84. package/dist/wirings/workflow/dsl/index.d.ts +5 -0
  85. package/dist/wirings/workflow/dsl/index.js +4 -0
  86. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +286 -0
  87. package/dist/wirings/workflow/dsl/workflow-dsl.types.js +5 -0
  88. package/dist/wirings/workflow/dsl/workflow-runner.d.ts +5 -0
  89. package/dist/wirings/workflow/dsl/workflow-runner.js +22 -0
  90. package/dist/wirings/workflow/graph/graph-node.d.ts +122 -0
  91. package/dist/wirings/workflow/graph/graph-node.js +58 -0
  92. package/dist/wirings/workflow/graph/graph-runner.d.ts +35 -0
  93. package/dist/wirings/workflow/graph/graph-runner.js +452 -0
  94. package/dist/wirings/workflow/graph/index.d.ts +3 -0
  95. package/dist/wirings/workflow/graph/index.js +3 -0
  96. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +95 -0
  97. package/dist/wirings/workflow/graph/workflow-graph.types.js +15 -0
  98. package/dist/wirings/workflow/index.d.ts +7 -3
  99. package/dist/wirings/workflow/index.js +6 -3
  100. package/dist/wirings/workflow/pikku-workflow-service.d.ts +108 -10
  101. package/dist/wirings/workflow/pikku-workflow-service.js +274 -165
  102. package/dist/wirings/workflow/wire-workflow.d.ts +42 -0
  103. package/dist/wirings/workflow/wire-workflow.js +53 -0
  104. package/dist/wirings/workflow/workflow-utils.d.ts +23 -0
  105. package/dist/wirings/workflow/workflow-utils.js +66 -0
  106. package/dist/wirings/workflow/workflow.types.d.ts +135 -128
  107. package/package.json +11 -2
  108. package/src/errors/error-handler.ts +3 -3
  109. package/src/errors/errors.ts +3 -3
  110. package/src/factory-functions.test.ts +9 -36
  111. package/src/function/function-runner.test.ts +58 -69
  112. package/src/function/function-runner.ts +130 -37
  113. package/src/function/functions.types.ts +193 -54
  114. package/src/handle-error.ts +1 -1
  115. package/src/index.ts +10 -5
  116. package/src/middleware/auth-apikey.test.ts +360 -0
  117. package/src/middleware/auth-apikey.ts +3 -7
  118. package/src/middleware/auth-bearer.test.ts +447 -0
  119. package/src/middleware/auth-bearer.ts +27 -33
  120. package/src/middleware/auth-cookie.test.ts +525 -0
  121. package/src/middleware/auth-cookie.ts +6 -6
  122. package/src/middleware/timeout.ts +4 -2
  123. package/src/middleware-runner.test.ts +58 -127
  124. package/src/middleware-runner.ts +29 -25
  125. package/src/permissions.test.ts +68 -130
  126. package/src/permissions.ts +41 -100
  127. package/src/pikku-state.ts +156 -201
  128. package/src/schema.ts +42 -13
  129. package/src/services/user-session-service.ts +14 -4
  130. package/src/services/workflow-service.ts +74 -0
  131. package/src/types/core.types.ts +79 -58
  132. package/src/types/state.types.ts +195 -0
  133. package/src/utils.ts +59 -4
  134. package/src/wirings/channel/channel-common.ts +4 -7
  135. package/src/wirings/channel/channel-handler.ts +17 -23
  136. package/src/wirings/channel/channel-runner.ts +7 -7
  137. package/src/wirings/channel/channel.types.ts +14 -11
  138. package/src/wirings/channel/local/local-channel-runner.test.ts +8 -4
  139. package/src/wirings/channel/local/local-channel-runner.ts +23 -38
  140. package/src/wirings/channel/log-channels.ts +1 -1
  141. package/src/wirings/channel/serverless/serverless-channel-runner.ts +53 -79
  142. package/src/wirings/cli/channel/cli-channel-runner.ts +4 -3
  143. package/src/wirings/cli/cli-runner.test.ts +26 -26
  144. package/src/wirings/cli/cli-runner.ts +34 -71
  145. package/src/wirings/cli/cli.types.ts +23 -16
  146. package/src/wirings/forge-node/forge-node.types.ts +135 -0
  147. package/src/wirings/forge-node/index.ts +1 -0
  148. package/src/wirings/http/http-runner.test.ts +10 -10
  149. package/src/wirings/http/http-runner.ts +56 -66
  150. package/src/wirings/http/http.types.ts +19 -14
  151. package/src/wirings/http/log-http-routes.ts +1 -1
  152. package/src/wirings/http/routers/path-to-regex.test.ts +30 -19
  153. package/src/wirings/http/routers/path-to-regex.ts +2 -2
  154. package/src/wirings/mcp/mcp-runner.ts +44 -69
  155. package/src/wirings/mcp/mcp.types.ts +6 -0
  156. package/src/wirings/queue/queue-runner.test.ts +641 -0
  157. package/src/wirings/queue/queue-runner.ts +16 -38
  158. package/src/wirings/queue/queue.types.ts +4 -11
  159. package/src/wirings/rpc/index.ts +1 -1
  160. package/src/wirings/rpc/rpc-runner.ts +129 -77
  161. package/src/wirings/rpc/rpc-types.ts +8 -0
  162. package/src/wirings/scheduler/log-schedulers.ts +1 -1
  163. package/src/wirings/scheduler/scheduler-runner.test.ts +627 -0
  164. package/src/wirings/scheduler/scheduler-runner.ts +29 -55
  165. package/src/wirings/scheduler/scheduler.types.ts +3 -9
  166. package/src/wirings/trigger/index.ts +2 -0
  167. package/src/wirings/trigger/trigger-runner.ts +96 -0
  168. package/src/wirings/trigger/trigger.types.ts +56 -0
  169. package/src/wirings/workflow/dsl/index.ts +30 -0
  170. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +312 -0
  171. package/src/wirings/workflow/dsl/workflow-runner.ts +27 -0
  172. package/src/wirings/workflow/graph/graph-node.ts +227 -0
  173. package/src/wirings/workflow/graph/graph-runner.ts +694 -0
  174. package/src/wirings/workflow/graph/index.ts +3 -0
  175. package/src/wirings/workflow/graph/workflow-graph.types.ts +126 -0
  176. package/src/wirings/workflow/index.ts +60 -12
  177. package/src/wirings/workflow/pikku-workflow-service.ts +401 -195
  178. package/src/wirings/workflow/wire-workflow.ts +94 -0
  179. package/src/wirings/workflow/workflow-utils.ts +120 -0
  180. package/src/wirings/workflow/workflow.types.ts +167 -188
  181. package/tsconfig.tsbuildinfo +1 -1
  182. package/dist/wirings/workflow/workflow-runner.d.ts +0 -35
  183. package/dist/wirings/workflow/workflow-runner.js +0 -68
  184. package/src/wirings/workflow/workflow-runner.ts +0 -85
@@ -1,22 +1,39 @@
1
1
  import { describe, test, beforeEach } from 'node:test'
2
2
  import * as assert from 'node:assert'
3
+ import { addPermission, runPermissions } from './permissions.js'
4
+ import { pikkuState, resetPikkuState } from './pikku-state.js'
5
+ import { CoreServices, CoreUserSession } from './types/core.types.js'
3
6
  import {
4
- addPermission,
5
- getPermissionsForTags,
6
- runPermissions,
7
- } from './permissions.js'
8
- import { resetPikkuState } from './pikku-state.js'
9
- import {
10
- CoreServices,
11
- CoreUserSession,
12
- PikkuWiringTypes,
13
- } from './types/core.types.js'
14
- import { CorePermissionGroup } from './function/functions.types.js'
7
+ CorePermissionGroup,
8
+ CorePikkuPermission,
9
+ } from './function/functions.types.js'
15
10
 
16
11
  beforeEach(() => {
17
12
  resetPikkuState()
18
13
  })
19
14
 
15
+ // Test helper to get permissions for tags (not exported from core to keep it lean)
16
+ const getPermissionsForTags = (
17
+ tags?: string[]
18
+ ): (CorePermissionGroup | CorePikkuPermission)[] => {
19
+ if (!tags || tags.length === 0) {
20
+ return []
21
+ }
22
+ const permissionsStore = pikkuState(null, 'permissions', 'tagGroup')
23
+ const result: (CorePermissionGroup | CorePikkuPermission)[] = []
24
+ for (const tag of new Set(tags)) {
25
+ const tagPermissions = permissionsStore[tag]
26
+ if (tagPermissions) {
27
+ if (Array.isArray(tagPermissions)) {
28
+ result.push(...tagPermissions)
29
+ } else {
30
+ result.push(tagPermissions)
31
+ }
32
+ }
33
+ }
34
+ return result
35
+ }
36
+
20
37
  const mockServices: CoreServices = {
21
38
  logger: {
22
39
  info: () => {},
@@ -82,92 +99,13 @@ describe('addPermission', () => {
82
99
  })
83
100
  })
84
101
 
85
- describe('getPermissionsForTags', () => {
86
- test('should return empty array when no tags provided', () => {
87
- const permissions = getPermissionsForTags([])
88
- assert.deepEqual(permissions, [])
89
- })
90
-
91
- test('should return empty array when tags is undefined', () => {
92
- const permissions = getPermissionsForTags(undefined)
93
- assert.deepEqual(permissions, [])
94
- })
95
-
96
- test('should return permissions for single tag', () => {
97
- const mockPermission = async () => true
98
- addPermission('singleTestTag', [mockPermission])
99
-
100
- const permissions = getPermissionsForTags(['singleTestTag'])
101
- assert.equal(permissions.length, 1)
102
- assert.equal(permissions[0], mockPermission)
103
- })
104
-
105
- test('should return permissions for multiple tags', () => {
106
- const mockPermission1 = async () => true
107
- const mockPermission2 = async () => false
108
-
109
- addPermission('tag1', [mockPermission1])
110
- addPermission('tag2', [mockPermission2])
111
-
112
- const permissions = getPermissionsForTags(['tag1', 'tag2'])
113
- assert.equal(permissions.length, 2)
114
- assert.equal(permissions[0], mockPermission1)
115
- assert.equal(permissions[1], mockPermission2)
116
- })
117
-
118
- test('should handle array permissions correctly', () => {
119
- const mockPermission1 = async () => true
120
- const mockPermission2 = async () => false
121
-
122
- addPermission('arrayHandleTestTag', [mockPermission1, mockPermission2])
123
-
124
- const permissions = getPermissionsForTags(['arrayHandleTestTag'])
125
- assert.equal(permissions.length, 2)
126
- assert.equal(permissions[0], mockPermission1)
127
- assert.equal(permissions[1], mockPermission2)
128
- })
129
-
130
- test('should handle non-array permissions correctly', () => {
131
- const mockPermissionGroup: CorePermissionGroup = {
132
- permissions: [async () => true],
133
- }
134
-
135
- addPermission('objectHandleTestTag', mockPermissionGroup)
136
-
137
- const permissions = getPermissionsForTags(['objectHandleTestTag'])
138
- assert.equal(permissions.length, 1)
139
- assert.equal(permissions[0], mockPermissionGroup)
140
- })
141
-
142
- test('should deduplicate tags', () => {
143
- const mockPermission = async () => true
144
- addPermission('dedupeTestTag', [mockPermission])
145
-
146
- const permissions = getPermissionsForTags([
147
- 'dedupeTestTag',
148
- 'dedupeTestTag',
149
- ])
150
- assert.equal(permissions.length, 1)
151
- assert.equal(permissions[0], mockPermission)
152
- })
153
-
154
- test('should ignore non-existent tags', () => {
155
- const mockPermission = async () => true
156
- addPermission('existingTag', [mockPermission])
157
-
158
- const permissions = getPermissionsForTags(['existingTag', 'nonExistentTag'])
159
- assert.equal(permissions.length, 1)
160
- assert.equal(permissions[0], mockPermission)
161
- })
162
- })
163
-
164
102
  describe('runPermissions', () => {
165
103
  test('should pass when no permissions are defined', async () => {
166
104
  // Should not throw
167
- await runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
168
- allServices: mockServices,
105
+ await runPermissions('rpc', Math.random().toString(), {
106
+ services: mockServices,
107
+ wire: {},
169
108
  data: {},
170
- session: mockSession,
171
109
  })
172
110
  })
173
111
 
@@ -180,11 +118,11 @@ describe('runPermissions', () => {
180
118
 
181
119
  addPermission('wiringTag', [wiringTagPermission])
182
120
 
183
- await runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
121
+ await runPermissions('rpc', Math.random().toString(), {
184
122
  wireInheritedPermissions: [{ type: 'tag', tag: 'wiringTag' }],
185
- allServices: mockServices,
123
+ services: mockServices,
124
+ wire: {},
186
125
  data: {},
187
- session: mockSession,
188
126
  })
189
127
 
190
128
  assert.deepEqual(executionOrder, ['wiringTag'])
@@ -223,14 +161,14 @@ describe('runPermissions', () => {
223
161
  ],
224
162
  }
225
163
 
226
- await runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
164
+ await runPermissions('rpc', Math.random().toString(), {
227
165
  wireInheritedPermissions: [{ type: 'tag', tag: 'wiringTag' }],
228
166
  wirePermissions,
229
167
  funcInheritedPermissions: [{ type: 'tag', tag: 'funcTag' }],
230
168
  funcPermissions,
231
- allServices: mockServices,
169
+ services: mockServices,
170
+ wire: {},
232
171
  data: {},
233
- session: mockSession,
234
172
  })
235
173
 
236
174
  // Order: wireInheritedPermissions (wiringTag) → wirePermissions → funcInheritedPermissions (funcTag) → funcPermissions
@@ -249,11 +187,11 @@ describe('runPermissions', () => {
249
187
  addPermission('atLeastOneTestTag', [failingPermission, passingPermission])
250
188
 
251
189
  // Should not throw because at least one permission passes
252
- await runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
190
+ await runPermissions('rpc', Math.random().toString(), {
253
191
  wireInheritedPermissions: [{ type: 'tag', tag: 'atLeastOneTestTag' }],
254
- allServices: mockServices,
192
+ services: mockServices,
193
+ wire: {},
255
194
  data: {},
256
- session: mockSession,
257
195
  })
258
196
  })
259
197
 
@@ -264,11 +202,11 @@ describe('runPermissions', () => {
264
202
  addPermission('allFailTestTag', [failingPermission1, failingPermission2])
265
203
 
266
204
  await assert.rejects(
267
- runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
205
+ runPermissions('rpc', Math.random().toString(), {
268
206
  wireInheritedPermissions: [{ type: 'tag', tag: 'allFailTestTag' }],
269
- allServices: mockServices,
207
+ services: mockServices,
208
+ wire: {},
270
209
  data: {},
271
- session: mockSession,
272
210
  }),
273
211
  {
274
212
  message: 'Permission denied',
@@ -282,11 +220,11 @@ describe('runPermissions', () => {
282
220
  }
283
221
 
284
222
  await assert.rejects(
285
- runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
223
+ runPermissions('rpc', Math.random().toString(), {
286
224
  wirePermissions,
287
- allServices: mockServices,
225
+ services: mockServices,
226
+ wire: {},
288
227
  data: {},
289
- session: mockSession,
290
228
  }),
291
229
  {
292
230
  message: 'Permission denied',
@@ -300,11 +238,11 @@ describe('runPermissions', () => {
300
238
  addPermission('funcTag', [failingPermission])
301
239
 
302
240
  await assert.rejects(
303
- runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
241
+ runPermissions('rpc', Math.random().toString(), {
304
242
  funcInheritedPermissions: [{ type: 'tag', tag: 'funcTag' }],
305
- allServices: mockServices,
243
+ services: mockServices,
244
+ wire: {},
306
245
  data: {},
307
- session: mockSession,
308
246
  }),
309
247
  {
310
248
  message: 'Permission denied',
@@ -318,11 +256,11 @@ describe('runPermissions', () => {
318
256
  }
319
257
 
320
258
  await assert.rejects(
321
- runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
259
+ runPermissions('rpc', Math.random().toString(), {
322
260
  funcPermissions,
323
- allServices: mockServices,
261
+ services: mockServices,
262
+ wire: {},
324
263
  data: {},
325
- session: mockSession,
326
264
  }),
327
265
  {
328
266
  message: 'Permission denied',
@@ -350,12 +288,12 @@ describe('runPermissions', () => {
350
288
  }
351
289
 
352
290
  // Should NOT throw because at least one permission (wirePermissions) passes
353
- await runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
291
+ await runPermissions('rpc', Math.random().toString(), {
354
292
  wireInheritedPermissions: [{ type: 'tag', tag: 'failingWiringTag' }],
355
293
  wirePermissions,
356
- allServices: mockServices,
294
+ services: mockServices,
295
+ wire: {},
357
296
  data: {},
358
- session: mockSession,
359
297
  })
360
298
 
361
299
  // Both permissions should be evaluated
@@ -368,11 +306,11 @@ describe('runPermissions', () => {
368
306
  addPermission('arrayTestTag', arrayPermission)
369
307
 
370
308
  // Should not throw because verifyPermissions handles array properly
371
- await runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
309
+ await runPermissions('rpc', Math.random().toString(), {
372
310
  wireInheritedPermissions: [{ type: 'tag', tag: 'arrayTestTag' }],
373
- allServices: mockServices,
311
+ services: mockServices,
312
+ wire: {},
374
313
  data: {},
375
- session: mockSession,
376
314
  })
377
315
  })
378
316
 
@@ -384,23 +322,23 @@ describe('runPermissions', () => {
384
322
  addPermission('objectTestTag', permissionGroup)
385
323
 
386
324
  // Should not throw because verifyPermissions handles objects properly
387
- await runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
325
+ await runPermissions('rpc', Math.random().toString(), {
388
326
  wireInheritedPermissions: [{ type: 'tag', tag: 'objectTestTag' }],
389
- allServices: mockServices,
327
+ services: mockServices,
328
+ wire: {},
390
329
  data: {},
391
- session: mockSession,
392
330
  })
393
331
  })
394
332
 
395
333
  test('should pass correct parameters to permission functions', async () => {
396
334
  let receivedServices: any
335
+ let receivedWire: any
397
336
  let receivedData: any
398
- let receivedSession: any
399
337
 
400
- const testPermission = async (services: any, data: any, session: any) => {
338
+ const testPermission = async (services: any, data: any, wire: any) => {
401
339
  receivedServices = services
402
340
  receivedData = data
403
- receivedSession = session
341
+ receivedWire = wire
404
342
  return true
405
343
  }
406
344
 
@@ -408,15 +346,15 @@ describe('runPermissions', () => {
408
346
 
409
347
  addPermission('paramTestTag', [testPermission])
410
348
 
411
- await runPermissions(PikkuWiringTypes.rpc, Math.random().toString(), {
349
+ await runPermissions('rpc', Math.random().toString(), {
412
350
  wireInheritedPermissions: [{ type: 'tag', tag: 'paramTestTag' }],
413
- allServices: mockServices,
351
+ services: mockServices,
352
+ wire: {},
414
353
  data: testData,
415
- session: mockSession,
416
354
  })
417
355
 
418
356
  assert.equal(receivedServices, mockServices)
419
357
  assert.equal(receivedData, testData)
420
- assert.equal(receivedSession, mockSession)
358
+ assert.deepEqual(receivedWire, {})
421
359
  })
422
360
  })
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  CoreServices,
3
- CoreUserSession,
4
3
  PikkuWiringTypes,
5
4
  PermissionMetadata,
5
+ PikkuWire,
6
6
  } from './types/core.types.js'
7
7
  import {
8
8
  CorePermissionGroup,
@@ -16,14 +16,14 @@ import { freezeDedupe } from './utils.js'
16
16
  * This function validates permissions by iterating over permission groups and executing the corresponding permission functions. If all functions in at least one group return true, the permission is considered valid.
17
17
  * @param services - The core services required for permission validation.
18
18
  * @param data - The data to be used in the permission validation functions.
19
- * @param session - An optional user session for permission validation.
19
+ * @param wire - The wire object containing request/response context and session.
20
20
  * @returns A promise that resolves to void.
21
21
  */
22
- export const verifyPermissions = async (
22
+ const verifyPermissions = async <Out = any>(
23
23
  permissions: CorePermissionGroup,
24
24
  services: CoreServices,
25
25
  data: any,
26
- session?: CoreUserSession
26
+ wire: PikkuWire<any, never, any, never, never, never>
27
27
  ): Promise<boolean> => {
28
28
  if (!permissions) {
29
29
  return true
@@ -38,13 +38,13 @@ export const verifyPermissions = async (
38
38
  for (const funcs of permissionGroups) {
39
39
  if (funcs instanceof Array) {
40
40
  const permissioned = await Promise.all(
41
- funcs.map((func) => func(services, data, session))
41
+ funcs.map((func) => func(services, data, wire))
42
42
  )
43
43
  if (permissioned.every((result) => result)) {
44
44
  valid = true
45
45
  }
46
46
  } else {
47
- valid = await funcs(services, data, session)
47
+ valid = await funcs(services, data, wire as any)
48
48
  }
49
49
  if (valid) {
50
50
  return true
@@ -53,31 +53,6 @@ export const verifyPermissions = async (
53
53
  return false
54
54
  }
55
55
 
56
- /**
57
- * Registers a single permission function by name in the global permission store.
58
- *
59
- * This function is used by CLI-generated code to register permission functions
60
- * that can be referenced by name in metadata. It stores permissions in a special
61
- * namespace to avoid conflicts with tag-based permissions.
62
- *
63
- * @param {string} name - The unique name (pikkuFuncName) of the permission function.
64
- * @param {CorePikkuPermission} permission - The permission function to register.
65
- *
66
- * @example
67
- * ```typescript
68
- * // Called by CLI-generated pikku-permissions.gen.ts
69
- * registerPermission('adminPermission_src_permissions_ts_10_5', adminPermission)
70
- * registerPermission('readPermission_src_permissions_ts_20_10', readPermission)
71
- * ```
72
- */
73
- export const registerPermission = (
74
- name: string,
75
- permission: CorePikkuPermission<any>
76
- ) => {
77
- const permissionStore = pikkuState('misc', 'permissions')
78
- permissionStore[name] = [permission]
79
- }
80
-
81
56
  /**
82
57
  * Retrieves a registered permission function by its name.
83
58
  *
@@ -89,10 +64,8 @@ export const registerPermission = (
89
64
  *
90
65
  * @internal
91
66
  */
92
- export const getPermissionByName = (
93
- name: string
94
- ): CorePikkuPermission | undefined => {
95
- const permissionStore = pikkuState('misc', 'permissions')
67
+ const getPermissionByName = (name: string): CorePikkuPermission | undefined => {
68
+ const permissionStore = pikkuState(null, 'misc', 'permissions')
96
69
  const permission = permissionStore[name]
97
70
  if (Array.isArray(permission) && permission.length === 1) {
98
71
  return permission[0]
@@ -130,9 +103,10 @@ export const getPermissionByName = (
130
103
  */
131
104
  export const addPermission = (
132
105
  tag: string,
133
- permissions: CorePermissionGroup | CorePikkuPermission[]
106
+ permissions: CorePermissionGroup | CorePikkuPermission[],
107
+ packageName: string | null = null
134
108
  ): CorePermissionGroup | CorePikkuPermission[] => {
135
- const tagGroups = pikkuState('permissions', 'tagGroup')
109
+ const tagGroups = pikkuState(packageName, 'permissions', 'tagGroup')
136
110
  if (tagGroups[tag]) {
137
111
  throw new Error(
138
112
  `Permissions for tag '${tag}' already exist. Use a different tag or remove the existing permissions first.`
@@ -142,62 +116,18 @@ export const addPermission = (
142
116
  return permissions
143
117
  }
144
118
 
145
- const EMPTY: readonly (CorePermissionGroup | CorePikkuPermission)[] = []
146
-
147
- /**
148
- * Retrieves permissions for a given set of tags.
149
- *
150
- * This function looks up all permissions registered for any of the provided tags
151
- * and returns them as a flattened array.
152
- *
153
- * @param {string[]} tags - Array of tags to look up permissions for.
154
- * @returns {any[]} Array of permission functions that apply to the given tags.
155
- *
156
- * @example
157
- * ```typescript
158
- * // Get all permissions for tags 'api' and 'auth'
159
- * const permissions = getPermissionsForTags(['api', 'auth'])
160
- * ```
161
- */
162
- export const getPermissionsForTags = (
163
- tags?: string[]
164
- ): readonly (CorePermissionGroup | CorePikkuPermission)[] => {
165
- if (!tags || tags.length === 0) {
166
- return EMPTY
167
- }
168
-
169
- const permissionsStore = pikkuState('permissions', 'tagGroup')
170
- const applicablePermissions: Array<
171
- CorePermissionGroup | CorePikkuPermission
172
- > = []
173
-
174
- // Collect permissions for all matching tags
175
- for (const tag of new Set(tags)) {
176
- const tagPermissions = permissionsStore[tag]
177
- if (tagPermissions) {
178
- if (Array.isArray(tagPermissions)) {
179
- applicablePermissions.push(...tagPermissions)
180
- } else {
181
- applicablePermissions.push(tagPermissions)
182
- }
183
- }
184
- }
185
-
186
- return applicablePermissions
187
- }
188
-
189
119
  const combinedPermissionsCache: Record<
190
120
  PikkuWiringTypes,
191
121
  Record<string, readonly (CorePermissionGroup | CorePikkuPermission)[]>
192
122
  > = {
193
- [PikkuWiringTypes.http]: {},
194
- [PikkuWiringTypes.rpc]: {},
195
- [PikkuWiringTypes.channel]: {},
196
- [PikkuWiringTypes.queue]: {},
197
- [PikkuWiringTypes.scheduler]: {},
198
- [PikkuWiringTypes.mcp]: {},
199
- [PikkuWiringTypes.cli]: {},
200
- [PikkuWiringTypes.workflow]: {},
123
+ http: {},
124
+ rpc: {},
125
+ channel: {},
126
+ queue: {},
127
+ scheduler: {},
128
+ mcp: {},
129
+ cli: {},
130
+ workflow: {},
201
131
  }
202
132
 
203
133
  /**
@@ -224,7 +154,7 @@ const combinedPermissionsCache: Record<
224
154
  * })
225
155
  * ```
226
156
  */
227
- export const combinePermissions = (
157
+ const combinePermissions = (
228
158
  wireType: PikkuWiringTypes,
229
159
  uid: string,
230
160
  {
@@ -232,11 +162,13 @@ export const combinePermissions = (
232
162
  wirePermissions,
233
163
  funcInheritedPermissions,
234
164
  funcPermissions,
165
+ packageName = null,
235
166
  }: {
236
167
  wireInheritedPermissions?: PermissionMetadata[]
237
168
  wirePermissions?: CorePermissionGroup | CorePikkuPermission[]
238
169
  funcInheritedPermissions?: PermissionMetadata[]
239
170
  funcPermissions?: CorePermissionGroup | CorePikkuPermission[]
171
+ packageName?: string | null
240
172
  } = {}
241
173
  ): readonly (CorePermissionGroup | CorePikkuPermission)[] => {
242
174
  if (combinedPermissionsCache[wireType][uid]) {
@@ -250,7 +182,9 @@ export const combinePermissions = (
250
182
  for (const meta of wireInheritedPermissions) {
251
183
  if (meta.type === 'http') {
252
184
  // Look up HTTP permission group from pikkuState
253
- const group = pikkuState('permissions', 'httpGroup')[meta.route]
185
+ const group = pikkuState(packageName, 'permissions', 'httpGroup')[
186
+ meta.route
187
+ ]
254
188
  if (group) {
255
189
  if (Array.isArray(group)) {
256
190
  resolved.push(...group)
@@ -260,7 +194,9 @@ export const combinePermissions = (
260
194
  }
261
195
  } else if (meta.type === 'tag') {
262
196
  // Look up tag permission group from pikkuState
263
- const group = pikkuState('permissions', 'tagGroup')[meta.tag]
197
+ const group = pikkuState(packageName, 'permissions', 'tagGroup')[
198
+ meta.tag
199
+ ]
264
200
  if (group) {
265
201
  if (Array.isArray(group)) {
266
202
  resolved.push(...group)
@@ -292,7 +228,9 @@ export const combinePermissions = (
292
228
  for (const meta of funcInheritedPermissions) {
293
229
  if (meta.type === 'tag') {
294
230
  // Look up tag permission group from pikkuState
295
- const group = pikkuState('permissions', 'tagGroup')[meta.tag]
231
+ const group = pikkuState(packageName, 'permissions', 'tagGroup')[
232
+ meta.tag
233
+ ]
296
234
  if (group) {
297
235
  if (Array.isArray(group)) {
298
236
  resolved.push(...group)
@@ -335,17 +273,19 @@ export const runPermissions = async (
335
273
  wirePermissions,
336
274
  funcInheritedPermissions,
337
275
  funcPermissions,
338
- allServices,
276
+ services,
277
+ wire,
339
278
  data,
340
- session,
279
+ packageName = null,
341
280
  }: {
342
281
  wireInheritedPermissions?: PermissionMetadata[]
343
282
  wirePermissions?: CorePermissionGroup | CorePikkuPermission[]
344
283
  funcInheritedPermissions?: PermissionMetadata[]
345
284
  funcPermissions?: CorePermissionGroup | CorePikkuPermission[]
346
- allServices: CoreServices
285
+ services: CoreServices
286
+ wire: PikkuWire<any, never, any, never, never, never>
347
287
  data: any
348
- session?: CoreUserSession
288
+ packageName?: string | null
349
289
  }
350
290
  ) => {
351
291
  // Combine all permissions: wireInheritedPermissions → wirePermissions → funcInheritedPermissions → funcPermissions
@@ -354,6 +294,7 @@ export const runPermissions = async (
354
294
  wirePermissions,
355
295
  funcInheritedPermissions,
356
296
  funcPermissions,
297
+ packageName,
357
298
  })
358
299
 
359
300
  // Check all combined permissions - at least one must pass if any exist
@@ -362,9 +303,9 @@ export const runPermissions = async (
362
303
  for (const permission of allPermissions) {
363
304
  const result = await verifyPermissions(
364
305
  typeof permission === 'function' ? { permission } : permission,
365
- allServices,
306
+ services,
366
307
  data,
367
- session
308
+ wire
368
309
  )
369
310
  if (result) {
370
311
  permissioned = true
@@ -372,7 +313,7 @@ export const runPermissions = async (
372
313
  }
373
314
  }
374
315
  if (!permissioned) {
375
- allServices.logger.debug('Permission denied - combined permissions')
316
+ services.logger.debug('Permission denied - combined permissions')
376
317
  throw new ForbiddenError('Permission denied')
377
318
  }
378
319
  }