@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
@@ -0,0 +1,447 @@
1
+ import { describe, test, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { authBearer } from './auth-bearer.js'
4
+ import { resetPikkuState } from '../pikku-state.js'
5
+ import { CoreUserSession } from '../types/core.types.js'
6
+ import { PikkuSessionService } from '../services/user-session-service.js'
7
+ import { InvalidSessionError } from '../errors/errors.js'
8
+
9
+ beforeEach(() => {
10
+ resetPikkuState()
11
+ })
12
+
13
+ const createMockHTTPRequest = (headers: Record<string, string> = {}) => ({
14
+ header: (name: string) => {
15
+ // Check both lowercase and exact case
16
+ return headers[name.toLowerCase()] || headers[name] || null
17
+ },
18
+ })
19
+
20
+ const createMockHTTPResponse = () => ({
21
+ cookie: () => {},
22
+ })
23
+
24
+ describe('authBearer middleware', () => {
25
+ test('should extract and decode JWT bearer token from Authorization header', async () => {
26
+ const mockUserSession: CoreUserSession = { userId: 'user123' }
27
+ const SessionService = new PikkuSessionService<CoreUserSession>()
28
+ const jwtService = {
29
+ encode: async () => 'token',
30
+ decode: async (token: string) => {
31
+ assert.equal(token, 'jwt-token')
32
+ return mockUserSession
33
+ },
34
+ }
35
+
36
+ const middleware = authBearer()
37
+ let nextCalled = false
38
+
39
+ await middleware(
40
+ { jwt: jwtService } as any,
41
+ {
42
+ session: SessionService,
43
+ http: {
44
+ request: createMockHTTPRequest({
45
+ authorization: 'Bearer jwt-token',
46
+ }),
47
+ response: createMockHTTPResponse(),
48
+ },
49
+ } as any,
50
+ async () => {
51
+ nextCalled = true
52
+ }
53
+ )
54
+
55
+ assert.equal(nextCalled, true)
56
+ assert.deepEqual(SessionService.get(), mockUserSession)
57
+ })
58
+
59
+ test('should handle case-insensitive Authorization header', async () => {
60
+ const mockUserSession: CoreUserSession = { userId: 'user456' }
61
+ const SessionService = new PikkuSessionService<CoreUserSession>()
62
+ const jwtService = {
63
+ encode: async () => 'token',
64
+ decode: async (token: string) => {
65
+ assert.equal(token, 'jwt-token-2')
66
+ return mockUserSession
67
+ },
68
+ }
69
+
70
+ const middleware = authBearer()
71
+ let nextCalled = false
72
+
73
+ await middleware(
74
+ { jwt: jwtService } as any,
75
+ {
76
+ session: SessionService,
77
+ http: {
78
+ request: createMockHTTPRequest({
79
+ Authorization: 'Bearer jwt-token-2',
80
+ }),
81
+ response: createMockHTTPResponse(),
82
+ },
83
+ } as any,
84
+ async () => {
85
+ nextCalled = true
86
+ }
87
+ )
88
+
89
+ assert.equal(nextCalled, true)
90
+ assert.deepEqual(SessionService.get(), mockUserSession)
91
+ })
92
+
93
+ test('should validate static token when token option is provided', async () => {
94
+ const mockUserSession: CoreUserSession = {
95
+ userId: 'static-user',
96
+ role: 'admin',
97
+ }
98
+ const SessionService = new PikkuSessionService<CoreUserSession>()
99
+ const jwtService = {
100
+ encode: async () => 'token',
101
+ decode: async () => {
102
+ // Should not be called in static token mode
103
+ assert.fail('JWT decode should not be called in static token mode')
104
+ return null
105
+ },
106
+ }
107
+
108
+ const middleware = authBearer({
109
+ token: {
110
+ value: 'my-static-token',
111
+ userSession: mockUserSession,
112
+ },
113
+ })
114
+ let nextCalled = false
115
+
116
+ await middleware(
117
+ { jwt: jwtService } as any,
118
+ {
119
+ session: SessionService,
120
+ http: {
121
+ request: createMockHTTPRequest({
122
+ authorization: 'Bearer my-static-token',
123
+ }),
124
+ response: createMockHTTPResponse(),
125
+ },
126
+ } as any,
127
+ async () => {
128
+ nextCalled = true
129
+ }
130
+ )
131
+
132
+ assert.equal(nextCalled, true)
133
+ assert.deepEqual(SessionService.get(), mockUserSession)
134
+ })
135
+
136
+ test('should throw InvalidSessionError when scheme is not Bearer', async () => {
137
+ const SessionService = new PikkuSessionService<CoreUserSession>()
138
+ const jwtService = {
139
+ encode: async () => 'token',
140
+ decode: async () => ({ userId: 'test' }),
141
+ }
142
+
143
+ const middleware = authBearer()
144
+
145
+ await assert.rejects(
146
+ async () => {
147
+ await middleware(
148
+ { jwt: jwtService } as any,
149
+ {
150
+ session: SessionService,
151
+ http: {
152
+ request: createMockHTTPRequest({
153
+ authorization: 'Basic some-token',
154
+ }),
155
+ response: createMockHTTPResponse(),
156
+ },
157
+ } as any,
158
+ async () => {}
159
+ )
160
+ },
161
+ (error: any) => {
162
+ assert(error instanceof InvalidSessionError)
163
+ return true
164
+ }
165
+ )
166
+ })
167
+
168
+ test('should throw InvalidSessionError when bearer token is missing', async () => {
169
+ const SessionService = new PikkuSessionService<CoreUserSession>()
170
+ const jwtService = {
171
+ encode: async () => 'token',
172
+ decode: async () => ({ userId: 'test' }),
173
+ }
174
+
175
+ const middleware = authBearer()
176
+
177
+ await assert.rejects(
178
+ async () => {
179
+ await middleware(
180
+ { jwt: jwtService } as any,
181
+ {
182
+ session: SessionService,
183
+ http: {
184
+ request: createMockHTTPRequest({
185
+ authorization: 'Bearer',
186
+ }),
187
+ response: createMockHTTPResponse(),
188
+ },
189
+ } as any,
190
+ async () => {}
191
+ )
192
+ },
193
+ (error: any) => {
194
+ assert(error instanceof InvalidSessionError)
195
+ return true
196
+ }
197
+ )
198
+ })
199
+
200
+ test('should throw InvalidSessionError when authorization header has no space', async () => {
201
+ const SessionService = new PikkuSessionService<CoreUserSession>()
202
+ const jwtService = {
203
+ encode: async () => 'token',
204
+ decode: async () => ({ userId: 'test' }),
205
+ }
206
+
207
+ const middleware = authBearer()
208
+
209
+ await assert.rejects(
210
+ async () => {
211
+ await middleware(
212
+ { jwt: jwtService } as any,
213
+ {
214
+ session: SessionService,
215
+ http: {
216
+ request: createMockHTTPRequest({
217
+ authorization: 'BearerToken',
218
+ }),
219
+ response: createMockHTTPResponse(),
220
+ },
221
+ } as any,
222
+ async () => {}
223
+ )
224
+ },
225
+ (error: any) => {
226
+ assert(error instanceof InvalidSessionError)
227
+ return true
228
+ }
229
+ )
230
+ })
231
+
232
+ test('should not set session when JWT decode returns null', async () => {
233
+ const SessionService = new PikkuSessionService<CoreUserSession>()
234
+ const jwtService = {
235
+ encode: async () => 'token',
236
+ decode: async () => null,
237
+ }
238
+
239
+ const middleware = authBearer()
240
+ let nextCalled = false
241
+
242
+ await middleware(
243
+ { jwt: jwtService } as any,
244
+ {
245
+ session: SessionService,
246
+ http: {
247
+ request: createMockHTTPRequest({
248
+ authorization: 'Bearer invalid-token',
249
+ }),
250
+ response: createMockHTTPResponse(),
251
+ },
252
+ } as any,
253
+ async () => {
254
+ nextCalled = true
255
+ }
256
+ )
257
+
258
+ assert.equal(nextCalled, true)
259
+ assert.equal(SessionService.get(), undefined)
260
+ })
261
+
262
+ test('should not set session when static token does not match', async () => {
263
+ const mockUserSession: CoreUserSession = { userId: 'static-user' }
264
+ const SessionService = new PikkuSessionService<CoreUserSession>()
265
+ const jwtService = {
266
+ encode: async () => 'token',
267
+ decode: async () => {
268
+ // Should not be called when static token is provided
269
+ assert.fail('JWT decode should not be called in static token mode')
270
+ return null
271
+ },
272
+ }
273
+
274
+ const middleware = authBearer({
275
+ token: {
276
+ value: 'correct-token',
277
+ userSession: mockUserSession,
278
+ },
279
+ })
280
+ let nextCalled = false
281
+
282
+ await middleware(
283
+ { jwt: jwtService } as any,
284
+ {
285
+ session: SessionService,
286
+ http: {
287
+ request: createMockHTTPRequest({
288
+ authorization: 'Bearer wrong-token',
289
+ }),
290
+ response: createMockHTTPResponse(),
291
+ },
292
+ } as any,
293
+ async () => {
294
+ nextCalled = true
295
+ }
296
+ )
297
+
298
+ assert.equal(nextCalled, true)
299
+ assert.equal(SessionService.get(), undefined)
300
+ })
301
+
302
+ test('should skip middleware when session already exists', async () => {
303
+ const existingSession: CoreUserSession = { userId: 'existing' }
304
+ const SessionService = new PikkuSessionService<CoreUserSession>()
305
+ SessionService.setInitial(existingSession)
306
+
307
+ let decodeCalled = false
308
+ const jwtService = {
309
+ encode: async () => 'token',
310
+ decode: async () => {
311
+ decodeCalled = true
312
+ return { userId: 'new' }
313
+ },
314
+ }
315
+
316
+ const middleware = authBearer()
317
+ let nextCalled = false
318
+
319
+ await middleware(
320
+ { jwt: jwtService } as any,
321
+ {
322
+ session: SessionService,
323
+ http: {
324
+ request: createMockHTTPRequest({
325
+ authorization: 'Bearer some-token',
326
+ }),
327
+ response: createMockHTTPResponse(),
328
+ },
329
+ } as any,
330
+ async () => {
331
+ nextCalled = true
332
+ }
333
+ )
334
+
335
+ assert.equal(nextCalled, true)
336
+ assert.equal(decodeCalled, false)
337
+ assert.deepEqual(SessionService.get(), existingSession)
338
+ })
339
+
340
+ test('should skip middleware when http.request is not available', async () => {
341
+ const SessionService = new PikkuSessionService<CoreUserSession>()
342
+ const jwtService = {
343
+ encode: async () => 'token',
344
+ decode: async () => ({ userId: 'test' }),
345
+ }
346
+
347
+ const middleware = authBearer()
348
+ let nextCalled = false
349
+
350
+ await middleware(
351
+ { jwt: jwtService } as any,
352
+ { session: SessionService } as any,
353
+ async () => {
354
+ nextCalled = true
355
+ }
356
+ )
357
+
358
+ assert.equal(nextCalled, true)
359
+ assert.equal(SessionService.get(), undefined)
360
+ })
361
+
362
+ test('should continue without session when authorization header is missing', async () => {
363
+ const SessionService = new PikkuSessionService<CoreUserSession>()
364
+ const jwtService = {
365
+ encode: async () => 'token',
366
+ decode: async () => ({ userId: 'test' }),
367
+ }
368
+
369
+ const middleware = authBearer()
370
+ let nextCalled = false
371
+
372
+ await middleware(
373
+ { jwt: jwtService } as any,
374
+ {
375
+ session: SessionService,
376
+ http: {
377
+ request: createMockHTTPRequest({}),
378
+ response: createMockHTTPResponse(),
379
+ },
380
+ } as any,
381
+ async () => {
382
+ nextCalled = true
383
+ }
384
+ )
385
+
386
+ assert.equal(nextCalled, true)
387
+ assert.equal(SessionService.get(), undefined)
388
+ })
389
+
390
+ test('should not decode when jwtService is not available in JWT mode', async () => {
391
+ const SessionService = new PikkuSessionService<CoreUserSession>()
392
+
393
+ const middleware = authBearer()
394
+ let nextCalled = false
395
+
396
+ await middleware(
397
+ { jwt: undefined } as any,
398
+ {
399
+ session: SessionService,
400
+ http: {
401
+ request: createMockHTTPRequest({
402
+ authorization: 'Bearer some-token',
403
+ }),
404
+ response: createMockHTTPResponse(),
405
+ },
406
+ } as any,
407
+ async () => {
408
+ nextCalled = true
409
+ }
410
+ )
411
+
412
+ assert.equal(nextCalled, true)
413
+ assert.equal(SessionService.get(), undefined)
414
+ })
415
+
416
+ test('should work in static token mode even when jwtService is not available', async () => {
417
+ const mockUserSession: CoreUserSession = { userId: 'static-user' }
418
+ const SessionService = new PikkuSessionService<CoreUserSession>()
419
+
420
+ const middleware = authBearer({
421
+ token: {
422
+ value: 'static-token',
423
+ userSession: mockUserSession,
424
+ },
425
+ })
426
+ let nextCalled = false
427
+
428
+ await middleware(
429
+ { jwt: undefined } as any,
430
+ {
431
+ session: SessionService,
432
+ http: {
433
+ request: createMockHTTPRequest({
434
+ authorization: 'Bearer static-token',
435
+ }),
436
+ response: createMockHTTPResponse(),
437
+ },
438
+ } as any,
439
+ async () => {
440
+ nextCalled = true
441
+ }
442
+ )
443
+
444
+ assert.equal(nextCalled, true)
445
+ assert.deepEqual(SessionService.get(), mockUserSession)
446
+ })
447
+ })
@@ -40,44 +40,38 @@ export const authBearer = pikkuMiddlewareFactory<{
40
40
  userSession: CoreUserSession
41
41
  }
42
42
  }>(({ token } = {}) =>
43
- pikkuMiddleware(
44
- async (
45
- { userSession: userSessionService, jwt: jwtService },
46
- { http },
47
- next
48
- ) => {
49
- // Skip if session already exists.
50
- if (!http?.request || userSessionService.get()) {
51
- return next()
52
- }
53
-
54
- const authHeader =
55
- http.request.header('authorization') ||
56
- http.request.header('Authorization')
43
+ pikkuMiddleware(async ({ jwt: jwtService }, { http, session }, next) => {
44
+ // Skip if session already exists.
45
+ if (!http?.request || !session || session.get()) {
46
+ return next()
47
+ }
57
48
 
58
- if (authHeader) {
59
- const [scheme, bearerToken] = authHeader.split(' ')
60
- if (scheme !== 'Bearer' || !bearerToken) {
61
- throw new InvalidSessionError()
62
- }
49
+ const authHeader =
50
+ http.request.header('authorization') ||
51
+ http.request.header('Authorization')
63
52
 
64
- let userSession: CoreUserSession | null = null
53
+ if (authHeader) {
54
+ const [scheme, bearerToken] = authHeader.split(' ')
55
+ if (scheme !== 'Bearer' || !bearerToken) {
56
+ throw new InvalidSessionError()
57
+ }
65
58
 
66
- // If static token provided, validate against it
67
- if (token && bearerToken === token.value) {
68
- userSession = token.userSession
69
- }
70
- // Otherwise, default to JWT decoding
71
- else if (jwtService && !token) {
72
- userSession = await jwtService.decode(bearerToken)
73
- }
59
+ let userSession: CoreUserSession | null = null
74
60
 
75
- if (userSession) {
76
- userSessionService.setInitial(userSession)
77
- }
61
+ // If static token provided, validate against it
62
+ if (token && bearerToken === token.value) {
63
+ userSession = token.userSession
64
+ }
65
+ // Otherwise, default to JWT decoding
66
+ else if (jwtService && !token) {
67
+ userSession = await jwtService.decode(bearerToken)
78
68
  }
79
69
 
80
- return next()
70
+ if (userSession) {
71
+ session.setInitial(userSession)
72
+ }
81
73
  }
82
- )
74
+
75
+ return next()
76
+ })
83
77
  )