@pikku/core 0.6.21 → 0.6.23

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 (62) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/channel/channel-handler.d.ts +2 -2
  3. package/dist/channel/channel-handler.js +49 -26
  4. package/dist/channel/channel-runner.d.ts +3 -3
  5. package/dist/channel/channel-runner.js +5 -5
  6. package/dist/channel/channel.types.d.ts +12 -19
  7. package/dist/channel/local/local-channel-runner.d.ts +1 -1
  8. package/dist/channel/local/local-channel-runner.js +14 -8
  9. package/dist/channel/serverless/serverless-channel-runner.js +12 -7
  10. package/dist/handle-error.js +8 -6
  11. package/dist/http/http-route-runner.d.ts +75 -18
  12. package/dist/http/http-route-runner.js +148 -64
  13. package/dist/http/http-routes.types.d.ts +24 -9
  14. package/dist/http/incomingmessage-to-request-convertor.d.ts +1 -0
  15. package/dist/http/incomingmessage-to-request-convertor.js +1 -0
  16. package/dist/http/index.d.ts +4 -3
  17. package/dist/http/index.js +4 -3
  18. package/dist/http/{pikku-http-abstract-request.d.ts → pikku-fetch-http-request.d.ts} +14 -20
  19. package/dist/http/pikku-fetch-http-request.js +92 -0
  20. package/dist/http/pikku-fetch-http-response.d.ts +14 -0
  21. package/dist/http/pikku-fetch-http-response.js +59 -0
  22. package/dist/middleware/auth-apikey.js +4 -4
  23. package/dist/middleware/auth-bearer.js +4 -4
  24. package/dist/middleware/auth-cookie.js +16 -25
  25. package/dist/middleware-runner.d.ts +1 -1
  26. package/dist/pikku-request.d.ts +3 -3
  27. package/dist/pikku-request.js +5 -5
  28. package/dist/scheduler/scheduler-runner.d.ts +1 -1
  29. package/dist/services/user-session-service.d.ts +9 -14
  30. package/dist/services/user-session-service.js +22 -22
  31. package/dist/types/core.types.d.ts +1 -1
  32. package/dist/types/functions.types.d.ts +7 -2
  33. package/lcov.info +1529 -1412
  34. package/package.json +3 -4
  35. package/src/channel/channel-handler.ts +82 -29
  36. package/src/channel/channel-runner.ts +7 -7
  37. package/src/channel/channel.types.ts +19 -23
  38. package/src/channel/local/local-channel-runner.test.ts +68 -23
  39. package/src/channel/local/local-channel-runner.ts +23 -9
  40. package/src/channel/serverless/serverless-channel-runner.ts +15 -6
  41. package/src/handle-error.ts +8 -6
  42. package/src/http/http-route-runner.test.ts +13 -57
  43. package/src/http/http-route-runner.ts +173 -86
  44. package/src/http/http-routes.types.ts +26 -9
  45. package/src/http/incomingmessage-to-request-convertor.ts +0 -0
  46. package/src/http/index.ts +4 -5
  47. package/src/http/{pikku-http-abstract-request.ts → pikku-fetch-http-request.ts} +48 -39
  48. package/src/http/pikku-fetch-http-response.ts +70 -0
  49. package/src/middleware/auth-apikey.ts +4 -4
  50. package/src/middleware/auth-bearer.ts +4 -4
  51. package/src/middleware/auth-cookie.ts +20 -28
  52. package/src/middleware-runner.ts +1 -1
  53. package/src/pikku-request.ts +8 -4
  54. package/src/scheduler/scheduler-runner.ts +0 -2
  55. package/src/services/user-session-service.ts +26 -28
  56. package/src/types/core.types.ts +1 -1
  57. package/src/types/functions.types.ts +19 -4
  58. package/tsconfig.tsbuildinfo +1 -1
  59. package/dist/http/pikku-http-abstract-request.js +0 -76
  60. package/dist/http/pikku-http-abstract-response.d.ts +0 -58
  61. package/dist/http/pikku-http-abstract-response.js +0 -54
  62. package/src/http/pikku-http-abstract-response.ts +0 -79
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/core",
3
- "version": "0.6.21",
3
+ "version": "0.6.23",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",
@@ -23,8 +23,6 @@
23
23
  "./channel/local": "./dist/channel/local/index.js",
24
24
  "./channel/serverless": "./dist/channel/serverless/index.js",
25
25
  "./http": "./dist/http/index.js",
26
- "./http/pikku-http-abstract-response": "./dist/http/pikku-http-abstract-response.js",
27
- "./http/pikku-http-abstract-request": "./dist/http/pikku-http-abstract-request.js",
28
26
  "./errors": "./dist/errors/index.js",
29
27
  "./scheduler": "./dist/scheduler/index.js",
30
28
  "./services": "./dist/services/index.js",
@@ -35,7 +33,8 @@
35
33
  "@types/cookie": "^0.6.0",
36
34
  "@types/uuid": "^10.0.0",
37
35
  "cookie": "^1.0.1",
38
- "path-to-regexp": "^8.2.0"
36
+ "path-to-regexp": "^8.2.0",
37
+ "picoquery": "^2.4.0"
39
38
  },
40
39
  "devDependencies": {
41
40
  "@types/node": "^22.7.8",
@@ -4,38 +4,62 @@ import {
4
4
  JSONValue,
5
5
  CoreUserSession,
6
6
  } from '../types/core.types.js'
7
- import { CoreAPIChannel, PikkuChannelHandler } from './channel.types.js'
7
+ import {
8
+ ChannelMessageMeta,
9
+ CoreAPIChannel,
10
+ PikkuChannelHandler,
11
+ } from './channel.types.js'
8
12
  import { verifyPermissions } from '../permissions.js'
9
13
  import { pikkuState } from '../pikku-state.js'
10
14
 
11
- const validateSchema = (
12
- logger: CoreSingletonServices['logger'],
13
- data: JSONValue,
15
+ const getRouteMeta = (
14
16
  channelName: string,
15
17
  routingProperty?: string,
16
18
  routerValue?: string
17
- ) => {
19
+ ): ChannelMessageMeta => {
18
20
  const channelsMeta = pikkuState('channel', 'meta')
19
- for (const channelMeta of channelsMeta) {
20
- if (routingProperty && routerValue) {
21
- const channelRoute =
22
- channelMeta.messageRoutes[routingProperty]?.[routerValue]
23
- if (channelRoute) {
24
- const schemaNames = channelRoute.inputs
25
- if (schemaNames) {
26
- // TODO
27
- // loadSchema(schemaNames, logger)
28
- // validateJson(schemaNames, data)
29
- }
30
- return
31
- }
21
+ const channelMeta = channelsMeta.find(
22
+ (channelMeta) => channelMeta.name === channelName
23
+ )
24
+ if (!channelMeta) {
25
+ throw new Error(`Channel ${channelName} not found`)
26
+ }
27
+ if (!routingProperty) {
28
+ if (!channelMeta.message) {
29
+ throw new Error(`Channel ${channelName} has no default message route`)
32
30
  }
31
+ return channelMeta.message
32
+ }
33
+ if (!routerValue) {
34
+ throw new Error(
35
+ `Channel ${channelName} requires a router value for ${routingProperty}`
36
+ )
37
+ }
38
+ const route = channelMeta.messageRoutes[routingProperty]?.[routerValue]
39
+ if (!route) {
40
+ throw new Error(
41
+ `Channel ${channelName} has no route for ${routingProperty}:${routerValue}`
42
+ )
43
+ }
44
+ return route
45
+ }
46
+
47
+ const validateSchema = (
48
+ logger: CoreSingletonServices['logger'],
49
+ data: JSONValue,
50
+ channelRoute: ChannelMessageMeta
51
+ ) => {
52
+ const schemaNames = channelRoute.inputs
53
+ if (schemaNames) {
54
+ // TODO
55
+ // loadSchema(schemaNames, logger)
56
+ // validateJson(schemaNames, data)
33
57
  }
34
58
  }
35
59
 
36
60
  const validateAuth = (
37
61
  requiresSession: boolean,
38
- userSession: CoreUserSession | undefined,
62
+ session: CoreUserSession | undefined,
39
63
  onMessage: any
40
64
  ) => {
41
65
  const auth =
@@ -45,7 +69,7 @@ const validateAuth = (
45
69
  ? requiresSession
46
70
  : onMessage.auth
47
71
 
48
- if (auth && !userSession) {
72
+ if (auth && !session) {
49
73
  return false
50
74
  }
51
75
  return true
@@ -53,27 +77,41 @@ const validateAuth = (
53
77
 
54
78
  const validatePermissions = async (
55
79
  services: CoreServices,
56
- userSession: CoreUserSession | undefined,
80
+ session: CoreUserSession | undefined,
57
81
  onMessage: any,
58
82
  data: unknown
59
83
  ) => {
60
84
  const permissions =
61
85
  typeof onMessage === 'function' ? {} : onMessage.permissions
62
- return await verifyPermissions(permissions, services, data, userSession)
86
+ return await verifyPermissions(permissions, services, data, session)
63
87
  }
64
88
 
65
89
  const runFunction = async (
66
90
  services: CoreServices,
67
91
  channelHandler: PikkuChannelHandler,
92
+ channelMessageMeta: ChannelMessageMeta,
93
+ session: CoreUserSession | undefined,
68
94
  onMessage: any,
69
95
  data: unknown
70
96
  ) => {
71
97
  const func: any = typeof onMessage === 'function' ? onMessage : onMessage.func
72
- return await func(services, channelHandler.getChannel(), data)
98
+ if (channelMessageMeta.type?.toLowerCase().includes('function')) {
99
+ return await func(
100
+ {
101
+ ...services,
102
+ channel: channelHandler.getChannel(),
103
+ },
104
+ data,
105
+ session
106
+ )
107
+ } else {
108
+ return await func(services, channelHandler.getChannel(), data)
109
+ }
73
110
  }
74
111
 
75
112
  export const processMessageHandlers = (
76
113
  services: CoreServices,
114
+ session: CoreUserSession | undefined,
77
115
  channelConfig: CoreAPIChannel<any, any>,
78
116
  channelHandler: PikkuChannelHandler
79
117
  ) => {
@@ -83,6 +121,7 @@ export const processMessageHandlers = (
83
121
  const processMessage = async (
84
122
  data: JSONValue,
85
123
  onMessage: any,
124
+ session: CoreUserSession | undefined,
86
125
  routingProperty?: string,
87
126
  routerValue?: string
88
127
  ): Promise<unknown> => {
@@ -98,14 +137,16 @@ export const processMessageHandlers = (
98
137
  return
99
138
  }
100
139
 
101
- validateSchema(
102
- services.logger,
103
- data,
140
+ const routeMeta = getRouteMeta(
104
141
  channelConfig.name,
105
142
  routingProperty,
106
143
  routerValue
107
144
  )
108
145
 
146
+ if (routeMeta) {
147
+ await validateSchema(services.logger, data, routeMeta)
148
+ }
149
+
109
150
  const hasPermission = await validatePermissions(
110
151
  services,
111
152
  channelHandler,
@@ -118,7 +159,14 @@ export const processMessageHandlers = (
118
159
  )
119
160
  }
120
161
 
121
- return await runFunction(services, channelHandler, onMessage, data)
162
+ return await runFunction(
163
+ services,
164
+ channelHandler,
165
+ routeMeta,
166
+ session,
167
+ onMessage,
168
+ data
169
+ )
122
170
  }
123
171
 
124
172
  const onMessage = async (rawData): Promise<unknown> => {
@@ -137,6 +185,7 @@ export const processMessageHandlers = (
137
185
  result = await processMessage(
138
186
  messageData,
139
187
  routes[routerValue],
188
+ session,
140
189
  routingProperty,
141
190
  routerValue
142
191
  )
@@ -147,7 +196,11 @@ export const processMessageHandlers = (
147
196
  // Default handler if no routes matched but json data was parsed
148
197
  if (!processed && channelConfig.onMessage) {
149
198
  processed = true
150
- result = await processMessage(messageData, channelConfig.onMessage)
199
+ result = await processMessage(
200
+ messageData,
201
+ channelConfig.onMessage,
202
+ session
203
+ )
151
204
  }
152
205
  } catch (error) {
153
206
  // Most likely a json error.. ignore
@@ -157,7 +210,7 @@ export const processMessageHandlers = (
157
210
  // Default handler if no routes matched and json data wasn't parsed
158
211
  if (!processed && channelConfig.onMessage) {
159
212
  processed = true
160
- result = await processMessage(rawData, channelConfig.onMessage)
213
+ result = await processMessage(rawData, channelConfig.onMessage, session)
161
214
  }
162
215
 
163
216
  if (!processed) {
@@ -57,10 +57,10 @@ export const openChannel = async ({
57
57
  route,
58
58
  singletonServices,
59
59
  coerceToArray = false,
60
- http,
60
+ request,
61
61
  }: Pick<CoreAPIChannel<unknown, string>, 'route'> &
62
- Omit<RunChannelParams<unknown>, 'response' | 'request'> & {
63
- userSessionService?: UserSessionService<any>
62
+ RunChannelParams<unknown> & {
63
+ userSessionService: UserSessionService<any>
64
64
  } & RunChannelOptions): Promise<{
65
65
  openingData: unknown
66
66
  channelConfig: CoreAPIChannel<unknown, any>
@@ -74,19 +74,19 @@ export const openChannel = async ({
74
74
  const { params, channelConfig, schemaName } = matchingChannel
75
75
 
76
76
  const requiresSession = channelConfig.auth !== false
77
- http?.request?.setParams(params)
77
+ request?.setParams(params)
78
78
 
79
79
  singletonServices.logger.info(
80
80
  `Matched channel: ${channelConfig.name} | route: ${channelConfig.route} | auth: ${requiresSession.toString()}`
81
81
  )
82
82
 
83
83
  let openingData: any | undefined
84
- if (http?.request) {
85
- openingData = await http.request.getData()
84
+ if (request) {
85
+ openingData = await request.data()
86
86
  if (coerceToArray && schemaName) {
87
87
  coerceQueryStringToArray(schemaName, openingData)
88
88
  }
89
- validateSchema(
89
+ await validateSchema(
90
90
  singletonServices.logger,
91
91
  singletonServices.schemaService,
92
92
  schemaName,
@@ -1,10 +1,9 @@
1
1
  import { PikkuError } from '../errors/error-handler.js'
2
2
  import {
3
3
  HTTPFunctionMetaInputTypes,
4
- PikkuHTTP,
4
+ PikkuHTTPRequest,
5
+ PikkuHTTPResponse,
5
6
  } from '../http/http-routes.types.js'
6
- import { PikkuHTTPAbstractRequest } from '../http/pikku-http-abstract-request.js'
7
- import { PikkuHTTPAbstractResponse } from '../http/pikku-http-abstract-response.js'
8
7
  import {
9
8
  APIDocs,
10
9
  CoreServices,
@@ -12,9 +11,7 @@ import {
12
11
  CreateSessionServices,
13
12
  PikkuMiddleware,
14
13
  } from '../types/core.types.js'
15
- import { CoreAPIPermission } from '../types/functions.types.js'
16
- import { PikkuRequest } from '../pikku-request.js'
17
- import { PikkuResponse } from '../pikku-response.js'
14
+ import { CoreAPIFunction, CoreAPIPermission } from '../types/functions.types.js'
18
15
 
19
16
  export type RunChannelOptions = Partial<{
20
17
  skipUserSession: boolean
@@ -27,13 +24,17 @@ export type RunChannelOptions = Partial<{
27
24
  export type RunChannelParams<ChannelData> = {
28
25
  channelId: string
29
26
  singletonServices: CoreSingletonServices
30
- request?: PikkuRequest<ChannelData> | PikkuHTTPAbstractRequest<ChannelData>
31
- response?: PikkuResponse | PikkuHTTPAbstractResponse
32
- http?: PikkuHTTP
27
+ request?: PikkuHTTPRequest<ChannelData>
28
+ response?: PikkuHTTPResponse
33
29
  createSessionServices?: CreateSessionServices
34
30
  }
35
31
 
36
- export interface HandlerMeta {}
32
+ export interface ChannelMessageMeta {
33
+ inputs: string[] | null
34
+ outputs: string[] | null
35
+ docs?: APIDocs
36
+ type: null | string
37
+ }
37
38
 
38
39
  export interface ChannelMeta {
39
40
  name: string
@@ -44,17 +45,8 @@ export interface ChannelMeta {
44
45
  inputTypes?: HTTPFunctionMetaInputTypes
45
46
  connect: boolean
46
47
  disconnect: boolean
47
- message: { inputs: string[] | null; outputs: string[] | null } | null
48
- messageRoutes: Record<
49
- string,
50
- Record<
51
- string,
52
- {
53
- inputs: string[] | null
54
- outputs: string[] | null
55
- }
56
- >
57
- >
48
+ message: ChannelMessageMeta | null
49
+ messageRoutes: Record<string, Record<string, ChannelMessageMeta>>
58
50
  docs?: APIDocs
59
51
  tags?: string[]
60
52
  }
@@ -108,8 +100,12 @@ export type CoreAPIChannel<
108
100
  Channel extends string,
109
101
  ChannelFunctionConnection = CoreChannelConnection<ChannelData>,
110
102
  ChannelFunctionDisconnection = CoreChannelDisconnection<ChannelData>,
111
- ChannelFunctionDefaultMessage = CoreChannelMessage<unknown, unknown, unknown>,
112
- ChannelFunctionMessageRoute = CoreChannelMessage<unknown, unknown, unknown>,
103
+ ChannelFunctionDefaultMessage =
104
+ | CoreChannelMessage<unknown, unknown, unknown>
105
+ | CoreAPIFunction<unknown, unknown>,
106
+ ChannelFunctionMessageRoute =
107
+ | CoreChannelMessage<unknown, unknown, unknown>
108
+ | CoreAPIFunction<unknown, unknown>,
113
109
  APIPermission = CoreAPIPermission<ChannelData>,
114
110
  > = {
115
111
  name: string
@@ -1,11 +1,15 @@
1
1
  import { test, beforeEach, afterEach } from 'node:test'
2
2
  import * as assert from 'node:assert/strict'
3
- import { JSONValue } from '../../types/core.types.js'
4
- import { PikkuHTTPAbstractRequest } from '../../http/pikku-http-abstract-request.js'
5
- import { PikkuHTTPAbstractResponse } from '../../http/pikku-http-abstract-response.js'
6
3
  import { runLocalChannel } from './local-channel-runner.js'
7
4
  import { resetPikkuState } from '../../pikku-state.js'
8
5
  import { addChannel } from '../channel-runner.js'
6
+ import {
7
+ HTTPMethod,
8
+ PikkuHTTPRequest,
9
+ PikkuHTTPResponse,
10
+ PikkuQuery,
11
+ } from '../../http/http-routes.types.js'
12
+ import { SerializeOptions } from 'cookie'
9
13
 
10
14
  /**
11
15
  * Minimal stubs for dependencies that runChannel expects.
@@ -24,29 +28,69 @@ const mockSingletonServices = {
24
28
  } as any
25
29
 
26
30
  // Mock request and response objects
27
- class MockRequest extends PikkuHTTPAbstractRequest {
28
- public getBody(): Promise<unknown> {
31
+ export class PikkuMockRequest implements PikkuHTTPRequest {
32
+ private _params: Record<string, string | string[] | undefined> = {}
33
+
34
+ constructor(
35
+ private _route: string,
36
+ private _method: HTTPMethod
37
+ ) {}
38
+
39
+ method(): HTTPMethod {
40
+ return this._method
41
+ }
42
+ path(): string {
43
+ return this._route
44
+ }
45
+ json(): Promise<unknown> {
46
+ throw new Error('Method not implemented.')
47
+ }
48
+ arrayBuffer(): Promise<ArrayBuffer> {
29
49
  throw new Error('Method not implemented.')
30
50
  }
31
- public getHeader(headerName: string): string | undefined {
51
+ header(headerName: string): string | null {
52
+ throw new Error('Method not implemented.')
53
+ }
54
+ cookie(name?: string): string | null {
55
+ throw new Error('Method not implemented.')
56
+ }
57
+ params(): Partial<Record<string, string | string[]>> {
58
+ return this._params
59
+ }
60
+ setParams(params: Record<string, string | string[] | undefined>): void {
61
+ this._params = params
62
+ }
63
+ query(): PikkuQuery {
32
64
  throw new Error('Method not implemented.')
33
65
  }
34
- public async getData() {
66
+ public async data() {
35
67
  return { test: 'data' }
36
68
  }
37
69
  }
38
70
 
39
- class MockResponse extends PikkuHTTPAbstractResponse {
40
- public statusSet: boolean | undefined
41
- public ended: boolean | undefined
71
+ export class PikkuMockResponse implements PikkuHTTPResponse {
72
+ public _status: number | undefined
73
+
74
+ status(code: number): this {
75
+ this._status = code
76
+ return this
77
+ }
42
78
 
43
- public setJson(body: JSONValue): void {}
44
- public setResponse(response: string | Buffer): void {}
45
- public setStatus(code) {
46
- this.statusSet = code
79
+ cookie(name: string, value: string | null, options: SerializeOptions): this {
80
+ throw new Error('Method not implemented.')
47
81
  }
48
- public end() {
49
- this.ended = true
82
+ header(name: string, value: string | string[]): this {
83
+ throw new Error('Method not implemented.')
84
+ }
85
+ arrayBuffer(data: XMLHttpRequestBodyInit): this {
86
+ throw new Error('Method not implemented.')
87
+ }
88
+ json(data: unknown): this {
89
+ // We don't need to implement this for our test
90
+ return this
91
+ }
92
+ redirect(location: string, status?: number): this {
93
+ throw new Error('Method not implemented.')
50
94
  }
51
95
  }
52
96
 
@@ -61,14 +105,13 @@ afterEach(() => {
61
105
  })
62
106
 
63
107
  test('runChannel should return undefined and 404 if no matching channel is found', async () => {
64
- const mockResponse = new MockResponse()
108
+ const mockResponse = new PikkuMockResponse()
65
109
 
66
110
  const result = await runLocalChannel({
67
111
  singletonServices: mockSingletonServices,
68
112
  channelId: 'test-channel-id',
69
- request: new MockRequest('/non-existent-channel', 'get'),
113
+ request: new PikkuMockRequest('/non-existent-channel', 'get'),
70
114
  response: mockResponse,
71
- route: '/non-existent-channel',
72
115
  createSessionServices: mockCreateSessionServices,
73
116
  })
74
117
 
@@ -77,8 +120,8 @@ test('runChannel should return undefined and 404 if no matching channel is found
77
120
  undefined,
78
121
  'Should return undefined if no channel matches'
79
122
  )
80
- assert.equal(mockResponse.statusSet, 404, 'Should set response status to 404')
81
- assert.equal(mockResponse.ended, true, 'Should end the response')
123
+ assert.equal(mockResponse._status, 404, 'Should set response status to 404')
124
+ // assert.equal(mockResponse._ended, true, 'Should end the response')
82
125
  })
83
126
 
84
127
  test('runChannel should return a channel handler if channel matches and no auth required', async () => {
@@ -100,12 +143,14 @@ test('runChannel should return a channel handler if channel matches and no auth
100
143
  const result = await runLocalChannel({
101
144
  singletonServices: singletonServicesWithPerm,
102
145
  channelId: 'test-channel-id',
103
- request: new MockRequest('/test-channel', 'get'),
104
- response: new MockResponse(),
146
+ request: new PikkuMockRequest('/test-channel', 'get'),
147
+ response: new PikkuMockResponse(),
105
148
  route: '/test-channel',
106
149
  createSessionServices: mockCreateSessionServices,
107
150
  })
108
151
 
152
+ console.log(result)
153
+
109
154
  assert.ok(result, 'Should return a PikkuChannelHandler instance')
110
155
 
111
156
  // Simulate opening the channel
@@ -11,7 +11,8 @@ import { PikkuLocalChannelHandler } from './local-channel-handler.js'
11
11
  import { SessionServices } from '../../types/core.types.js'
12
12
  import { handleError } from '../../handle-error.js'
13
13
  import { runMiddleware } from '../../middleware-runner.js'
14
- import { LocalUserSessionService } from '../../services/user-session-service.js'
14
+ import { PikkuUserSessionService } from '../../services/user-session-service.js'
15
+ import { PikkuHTTP } from '../../http/http-routes.types.js'
15
16
 
16
17
  export const runLocalChannel = async ({
17
18
  singletonServices,
@@ -25,14 +26,19 @@ export const runLocalChannel = async ({
25
26
  coerceToArray = false,
26
27
  logWarningsForStatusCodes = [],
27
28
  bubbleErrors = false,
28
- }: Pick<CoreAPIChannel<unknown, any>, 'route'> &
29
+ }: Partial<Pick<CoreAPIChannel<unknown, any>, 'route'>> &
29
30
  RunChannelOptions &
30
31
  RunChannelParams<unknown>): Promise<PikkuLocalChannelHandler | void> => {
31
32
  let sessionServices: SessionServices<typeof singletonServices> | undefined
32
33
 
33
34
  let channelHandler: PikkuLocalChannelHandler | undefined
34
- const userSessionService = new LocalUserSessionService()
35
- const http = createHTTPInteraction(request, response)
35
+ const userSessionService = new PikkuUserSessionService()
36
+
37
+ let http: PikkuHTTP | undefined
38
+ if (request) {
39
+ http = createHTTPInteraction(request, response)
40
+ route = http?.request?.path()
41
+ }
36
42
 
37
43
  const main = async () => {
38
44
  try {
@@ -40,11 +46,13 @@ export const runLocalChannel = async ({
40
46
  channelId,
41
47
  createSessionServices,
42
48
  respondWith404,
43
- http,
49
+ request,
50
+ response,
44
51
  route,
45
52
  singletonServices,
46
53
  skipUserSession,
47
54
  coerceToArray,
55
+ userSessionService,
48
56
  })
49
57
 
50
58
  channelHandler = new PikkuLocalChannelHandler(
@@ -53,14 +61,15 @@ export const runLocalChannel = async ({
53
61
  openingData
54
62
  )
55
63
  const channel = channelHandler.getChannel()
56
- const userSession = await userSessionService.get()
64
+ const session = await userSessionService.get()
57
65
  if (createSessionServices) {
58
66
  sessionServices = await createSessionServices(
59
67
  singletonServices,
60
68
  { http },
61
- userSession
69
+ session
62
70
  )
63
71
  }
72
+
64
73
  const allServices = {
65
74
  ...singletonServices,
66
75
  ...sessionServices,
@@ -79,7 +88,12 @@ export const runLocalChannel = async ({
79
88
  })
80
89
 
81
90
  channelHandler.registerOnMessage(
82
- processMessageHandlers(allServices, channelConfig, channelHandler)
91
+ processMessageHandlers(
92
+ allServices,
93
+ session,
94
+ channelConfig,
95
+ channelHandler
96
+ )
83
97
  )
84
98
  } catch (e: any) {
85
99
  handleError(
@@ -101,7 +115,7 @@ export const runLocalChannel = async ({
101
115
  await runMiddleware(
102
116
  {
103
117
  ...singletonServices,
104
- userSession: userSessionService,
118
+ userSessionService,
105
119
  },
106
120
  { http },
107
121
  route.middleware || [],
@@ -11,9 +11,11 @@ import type {
11
11
  import { createHTTPInteraction } from '../../http/http-route-runner.js'
12
12
  import { ChannelStore } from '../channel-store.js'
13
13
  import { handleError } from '../../handle-error.js'
14
- import { RemoteUserSessionService } from '../../services/user-session-service.js'
14
+ import { PikkuUserSessionService } from '../../services/user-session-service.js'
15
15
  import { runMiddleware } from '../../middleware-runner.js'
16
16
  import { pikkuState } from '../../pikku-state.js'
17
+ import { PikkuFetchHTTPRequest } from '../../http/pikku-fetch-http-request.js'
18
+ import { PikkuHTTP } from '../../http/http-routes.types.js'
17
19
 
18
20
  export interface RunServerlessChannelParams<ChannelData>
19
21
  extends RunChannelParams<ChannelData> {
@@ -70,8 +72,13 @@ export const runChannelConnect = async ({
70
72
  RunChannelOptions &
71
73
  RunServerlessChannelParams<unknown>) => {
72
74
  let sessionServices: SessionServices | undefined
73
- const http = createHTTPInteraction(request, response)
74
- const userSessionService = new RemoteUserSessionService(
75
+
76
+ let http: PikkuHTTP | undefined
77
+ if (request instanceof Request) {
78
+ http = createHTTPInteraction(new PikkuFetchHTTPRequest(request), response)
79
+ }
80
+
81
+ const userSessionService = new PikkuUserSessionService(
75
82
  channelStore,
76
83
  channelId
77
84
  )
@@ -79,10 +86,11 @@ export const runChannelConnect = async ({
79
86
  const { channelConfig, openingData } = await openChannel({
80
87
  channelId,
81
88
  createSessionServices,
82
- http,
89
+ request,
83
90
  route,
84
91
  singletonServices,
85
92
  coerceToArray,
93
+ userSessionService,
86
94
  })
87
95
 
88
96
  const main = async () => {
@@ -109,7 +117,7 @@ export const runChannelConnect = async ({
109
117
  { ...singletonServices, ...sessionServices },
110
118
  channel
111
119
  )
112
- http?.response?.setStatus(101)
120
+ http?.response?.status(101)
113
121
  } catch (e: any) {
114
122
  handleError(
115
123
  e,
@@ -130,7 +138,7 @@ export const runChannelConnect = async ({
130
138
  await runMiddleware(
131
139
  {
132
140
  ...singletonServices,
133
- userSession: userSessionService,
141
+ userSessionService,
134
142
  },
135
143
  { http },
136
144
  channelConfig.middleware || [],
@@ -190,6 +198,7 @@ export const runChannelMessage = async (
190
198
  try {
191
199
  const onMessage = processMessageHandlers(
192
200
  { ...singletonServices, ...sessionServices },
201
+ session,
193
202
  channelConfig,
194
203
  channelHandler
195
204
  )