@pikku/core 0.6.16 → 0.6.18

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 (92) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/channel/channel-handler.js +2 -2
  3. package/dist/channel/channel-runner.d.ts +2 -14
  4. package/dist/channel/channel-runner.js +5 -36
  5. package/dist/channel/channel-store.d.ts +9 -6
  6. package/dist/channel/index.d.ts +0 -1
  7. package/dist/channel/index.js +0 -1
  8. package/dist/channel/local/local-channel-runner.js +2 -2
  9. package/dist/channel/log-channels.js +2 -2
  10. package/dist/channel/serverless/serverless-channel-runner.js +8 -7
  11. package/dist/errors/error-handler.d.ts +1 -1
  12. package/dist/errors/error-handler.js +6 -14
  13. package/dist/errors/errors.d.ts +1 -1
  14. package/dist/errors/errors.js +2 -2
  15. package/dist/http/http-route-runner.d.ts +3 -23
  16. package/dist/http/http-route-runner.js +13 -82
  17. package/dist/http/index.d.ts +1 -1
  18. package/dist/http/index.js +1 -1
  19. package/dist/http/log-http-routes.js +2 -2
  20. package/dist/index.d.ts +2 -1
  21. package/dist/index.js +2 -1
  22. package/dist/middleware/auth-apikey.d.ts +15 -0
  23. package/dist/middleware/auth-apikey.js +36 -0
  24. package/dist/middleware/auth-bearer.d.ts +12 -0
  25. package/dist/middleware/auth-bearer.js +40 -0
  26. package/dist/middleware/auth-cookie.d.ts +16 -0
  27. package/dist/middleware/auth-cookie.js +43 -0
  28. package/dist/middleware/index.d.ts +3 -4
  29. package/dist/middleware/index.js +3 -4
  30. package/dist/middleware/timeout.d.ts +2 -0
  31. package/dist/middleware/timeout.js +10 -0
  32. package/dist/middleware-runner.d.ts +1 -1
  33. package/dist/pikku-state.d.ts +29 -0
  34. package/dist/pikku-state.js +30 -0
  35. package/dist/scheduler/index.d.ts +1 -1
  36. package/dist/scheduler/index.js +1 -1
  37. package/dist/scheduler/log-schedulers.js +2 -2
  38. package/dist/scheduler/scheduler-runner.d.ts +1 -11
  39. package/dist/scheduler/scheduler-runner.js +5 -33
  40. package/dist/schema.js +2 -2
  41. package/dist/services/jwt-service.d.ts +1 -10
  42. package/dist/services/user-session-service.d.ts +2 -2
  43. package/dist/services/user-session-service.js +6 -6
  44. package/dist/types/core.types.d.ts +3 -3
  45. package/lcov.info +814 -907
  46. package/package.json +2 -1
  47. package/src/channel/channel-handler.ts +2 -2
  48. package/src/channel/channel-runner.ts +4 -43
  49. package/src/channel/channel-store.ts +8 -11
  50. package/src/channel/index.ts +0 -1
  51. package/src/channel/local/local-channel-runner.test.ts +10 -20
  52. package/src/channel/local/local-channel-runner.ts +2 -2
  53. package/src/channel/log-channels.ts +2 -2
  54. package/src/channel/serverless/serverless-channel-runner.ts +10 -9
  55. package/src/errors/error-handler.ts +7 -18
  56. package/src/errors/errors.ts +2 -3
  57. package/src/handle-error.ts +0 -1
  58. package/src/http/http-route-runner.test.ts +3 -2
  59. package/src/http/http-route-runner.ts +18 -99
  60. package/src/http/index.ts +1 -6
  61. package/src/http/log-http-routes.ts +2 -2
  62. package/src/index.ts +2 -1
  63. package/src/middleware/auth-apikey.ts +65 -0
  64. package/src/middleware/auth-bearer.ts +65 -0
  65. package/src/middleware/auth-cookie.ts +76 -0
  66. package/src/middleware/index.ts +3 -4
  67. package/src/middleware/timeout.ts +13 -0
  68. package/src/middleware-runner.ts +1 -1
  69. package/src/pikku-state.ts +70 -0
  70. package/src/scheduler/index.ts +1 -7
  71. package/src/scheduler/log-schedulers.ts +2 -2
  72. package/src/scheduler/scheduler-runner.ts +6 -45
  73. package/src/schema.ts +2 -2
  74. package/src/services/jwt-service.ts +1 -12
  75. package/src/services/user-session-service.ts +8 -6
  76. package/src/types/core.types.ts +3 -6
  77. package/tsconfig.tsbuildinfo +1 -1
  78. package/dist/channel/eventhub-forwarder.d.ts +0 -17
  79. package/dist/channel/eventhub-forwarder.js +0 -1
  80. package/dist/middleware/auth-api-key.d.ts +0 -9
  81. package/dist/middleware/auth-api-key.js +0 -23
  82. package/dist/middleware/auth-cookie-middleware.d.ts +0 -11
  83. package/dist/middleware/auth-cookie-middleware.js +0 -36
  84. package/dist/middleware/auth-jwt-middleware.d.ts +0 -10
  85. package/dist/middleware/auth-jwt-middleware.js +0 -32
  86. package/dist/middleware/auth-query-middleware.d.ts +0 -10
  87. package/dist/middleware/auth-query-middleware.js +0 -21
  88. package/src/channel/eventhub-forwarder.ts +0 -25
  89. package/src/middleware/auth-api-key.ts +0 -32
  90. package/src/middleware/auth-cookie-middleware.ts +0 -54
  91. package/src/middleware/auth-jwt-middleware.ts +0 -47
  92. package/src/middleware/auth-query-middleware.ts +0 -33
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/core",
3
- "version": "0.6.16",
3
+ "version": "0.6.18",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "exports": {
20
20
  ".": "./dist/index.js",
21
+ "./middleware": "./dist/middleware/index.js",
21
22
  "./channel": "./dist/channel/index.js",
22
23
  "./channel/local": "./dist/channel/local/index.js",
23
24
  "./channel/serverless": "./dist/channel/serverless/index.js",
@@ -6,7 +6,7 @@ import {
6
6
  } from '../types/core.types.js'
7
7
  import { CoreAPIChannel, PikkuChannelHandler } from './channel.types.js'
8
8
  import { verifyPermissions } from '../permissions.js'
9
- import { getChannels } from './channel-runner.js'
9
+ import { pikkuState } from '../pikku-state.js'
10
10
 
11
11
  const validateSchema = (
12
12
  logger: CoreSingletonServices['logger'],
@@ -15,7 +15,7 @@ const validateSchema = (
15
15
  routingProperty?: string,
16
16
  routerValue?: string
17
17
  ) => {
18
- const { channelsMeta } = getChannels()
18
+ const channelsMeta = pikkuState('channel', 'meta')
19
19
  for (const channelMeta of channelsMeta) {
20
20
  if (routingProperty && routerValue) {
21
21
  const channelRoute =
@@ -1,46 +1,14 @@
1
1
  import { NotFoundError } from '../errors/errors.js'
2
+ import { pikkuState } from '../pikku-state.js'
2
3
  import { coerceQueryStringToArray, validateSchema } from '../schema.js'
3
4
  import { UserSessionService } from '../services/user-session-service.js'
4
5
  import {
5
6
  CoreAPIChannel,
6
- ChannelsMeta,
7
- CoreAPIChannels,
8
7
  RunChannelOptions,
9
8
  RunChannelParams,
10
9
  } from './channel.types.js'
11
10
  import { match } from 'path-to-regexp'
12
11
 
13
- if (!globalThis.pikku?.channels) {
14
- globalThis.pikku = globalThis.pikku || {}
15
- globalThis.pikku.channels = []
16
- globalThis.pikku.channelsMeta = []
17
- }
18
-
19
- const channels = (data?: any): CoreAPIChannels => {
20
- if (data) {
21
- globalThis.pikku.channels = data
22
- }
23
- return globalThis.pikku.channels
24
- }
25
-
26
- const channelsMeta = (data?: any): ChannelsMeta => {
27
- if (data) {
28
- globalThis.pikku.channelsMeta = data
29
- }
30
- return globalThis.pikku.channelsMeta
31
- }
32
-
33
- /**
34
- * Returns all the registered routes and associated metadata.
35
- * @internal
36
- */
37
- export const getChannels = () => {
38
- return {
39
- channels: channels(),
40
- channelsMeta: channelsMeta(),
41
- }
42
- }
43
-
44
12
  export const addChannel = <
45
13
  In,
46
14
  Channel extends string,
@@ -56,18 +24,12 @@ export const addChannel = <
56
24
  APIPermission
57
25
  >
58
26
  ) => {
59
- channels().push(channel as any)
60
- }
61
-
62
- /**
63
- * @ignore
64
- */
65
- export const setChannelsMeta = (_channelsMeta: ChannelsMeta) => {
66
- channelsMeta(_channelsMeta)
27
+ pikkuState('channel', 'channels').push(channel as any)
67
28
  }
68
29
 
69
30
  export const getMatchingChannelConfig = (request: string) => {
70
- const { channels, channelsMeta } = getChannels()
31
+ const channels = pikkuState('channel', 'channels')
32
+ const channelsMeta = pikkuState('channel', 'meta')
71
33
  for (const channelConfig of channels) {
72
34
  const cleanedRoute = channelConfig.route.replace(/^\/\//, '/')
73
35
  const cleanedRequest = request.replace(/^\/\//, '/')
@@ -96,7 +58,6 @@ export const openChannel = async ({
96
58
  singletonServices,
97
59
  coerceToArray = false,
98
60
  http,
99
- userSessionService,
100
61
  }: Pick<CoreAPIChannel<unknown, string>, 'route'> &
101
62
  Omit<RunChannelParams<unknown>, 'response' | 'request'> & {
102
63
  userSessionService?: UserSessionService<any>
@@ -1,32 +1,29 @@
1
1
  import { CoreUserSession } from '../types/core.types.js'
2
2
 
3
- export type Channel<
4
- ChannelType = unknown,
5
- OpeningData = unknown,
6
- UserSession extends CoreUserSession = CoreUserSession,
7
- > = {
3
+ export type Channel<ChannelType = unknown, OpeningData = unknown> = {
8
4
  channelId: string
9
5
  channelName: string
10
6
  channelObject?: ChannelType
11
7
  openingData?: OpeningData
12
- userSession?: UserSession
13
8
  }
14
9
 
15
10
  export abstract class ChannelStore<
16
11
  ChannelType = unknown,
17
12
  OpeningData = unknown,
18
13
  UserSession extends CoreUserSession = CoreUserSession,
19
- TypedChannel = Channel<ChannelType, OpeningData, UserSession>,
14
+ TypedChannel = Channel<ChannelType, OpeningData>,
20
15
  > {
21
16
  public abstract addChannel(
22
- channel: Channel<ChannelType, OpeningData, UserSession>
17
+ channel: Channel<ChannelType, OpeningData>
23
18
  ): Promise<void> | void
24
19
  public abstract removeChannels(channelId: string[]): Promise<void> | void
25
20
  public abstract setUserSession(
26
21
  channelId: string,
27
- userSession: any
22
+ userSession: UserSession | null
28
23
  ): Promise<void> | void
29
- public abstract getChannel(
24
+ public abstract getChannelAndSession(
30
25
  channelId: string
31
- ): Promise<TypedChannel> | TypedChannel
26
+ ):
27
+ | Promise<TypedChannel & { session: UserSession }>
28
+ | (TypedChannel & { session: UserSession })
32
29
  }
@@ -3,7 +3,6 @@ export * from './channel.types.js'
3
3
  export * from './log-channels.js'
4
4
  export * from './pikku-abstract-channel-handler.js'
5
5
  export * from './eventhub-service.js'
6
- export * from './eventhub-forwarder.js'
7
6
  export * from './eventhub-service.js'
8
7
  export * from './channel-store.js'
9
8
  export * from './eventhub-store.js'
@@ -4,6 +4,8 @@ import { JSONValue } from '../../types/core.types.js'
4
4
  import { PikkuHTTPAbstractRequest } from '../../http/pikku-http-abstract-request.js'
5
5
  import { PikkuHTTPAbstractResponse } from '../../http/pikku-http-abstract-response.js'
6
6
  import { runLocalChannel } from './local-channel-runner.js'
7
+ import { resetPikkuState } from '../../pikku-state.js'
8
+ import { addChannel } from '../channel-runner.js'
7
9
 
8
10
  /**
9
11
  * Minimal stubs for dependencies that runChannel expects.
@@ -49,28 +51,16 @@ class MockResponse extends PikkuHTTPAbstractResponse {
49
51
  }
50
52
 
51
53
  const mockCreateSessionServices = async () => ({ sessionServiceMock: true })
52
- function resetGlobalChannels(channels: any[] = [], channelsMeta: any[] = []) {
53
- // If necessary, reinitialize globalThis.pikku
54
- if (!globalThis.pikku) {
55
- globalThis.pikku = {}
56
- }
57
- globalThis.pikku.channels = channels
58
- globalThis.pikku.channelsMeta = channelsMeta
59
- globalThis.pikku.openChannels = new Map()
60
- }
61
54
 
62
55
  beforeEach(() => {
63
- resetGlobalChannels()
56
+ resetPikkuState()
64
57
  })
65
58
 
66
59
  afterEach(() => {
67
- resetGlobalChannels()
60
+ resetPikkuState()
68
61
  })
69
62
 
70
63
  test('runChannel should return undefined and 404 if no matching channel is found', async () => {
71
- // No channels configured
72
- resetGlobalChannels()
73
-
74
64
  const mockResponse = new MockResponse()
75
65
 
76
66
  const result = await runLocalChannel({
@@ -92,12 +82,12 @@ test('runChannel should return undefined and 404 if no matching channel is found
92
82
  })
93
83
 
94
84
  test('runChannel should return a channel handler if channel matches and no auth required', async () => {
95
- resetGlobalChannels([
96
- {
97
- route: '/test-channel',
98
- auth: false,
99
- },
100
- ])
85
+ resetPikkuState()
86
+ addChannel({
87
+ name: 'test',
88
+ route: '/test-channel',
89
+ auth: false,
90
+ })
101
91
 
102
92
  // Provide a fake channelPermissionService if needed
103
93
  const singletonServicesWithPerm = {
@@ -64,7 +64,7 @@ export const runLocalChannel = async ({
64
64
  const allServices = {
65
65
  ...singletonServices,
66
66
  ...sessionServices,
67
- userSessionService,
67
+ userSession: userSessionService,
68
68
  }
69
69
 
70
70
  channelHandler.registerOnOpen(() => {
@@ -101,7 +101,7 @@ export const runLocalChannel = async ({
101
101
  await runMiddleware(
102
102
  {
103
103
  ...singletonServices,
104
- userSessionService,
104
+ userSession: userSessionService,
105
105
  },
106
106
  { http },
107
107
  route.middleware || [],
@@ -1,12 +1,12 @@
1
+ import { pikkuState } from '../pikku-state.js'
1
2
  import { Logger } from '../services/index.js'
2
- import { getChannels } from './channel-runner.js'
3
3
 
4
4
  /**
5
5
  * Logs all the loaded channels.
6
6
  * @param logger - A logger for logging information.
7
7
  */
8
8
  export const logChannels = (logger: Logger) => {
9
- const { channels } = getChannels()
9
+ const channels = pikkuState('channel', 'channels')
10
10
  if (channels.length === 0) {
11
11
  logger.info('No channels added')
12
12
  return
@@ -1,7 +1,7 @@
1
1
  import { SessionServices } from '../../types/core.types.js'
2
2
  import { closeSessionServices } from '../../utils.js'
3
3
  import { processMessageHandlers } from '../channel-handler.js'
4
- import { getChannels, openChannel } from '../channel-runner.js'
4
+ import { openChannel } from '../channel-runner.js'
5
5
  import type {
6
6
  CoreAPIChannel,
7
7
  RunChannelOptions,
@@ -13,6 +13,7 @@ import { ChannelStore } from '../channel-store.js'
13
13
  import { handleError } from '../../handle-error.js'
14
14
  import { RemoteUserSessionService } from '../../services/user-session-service.js'
15
15
  import { runMiddleware } from '../../middleware-runner.js'
16
+ import { pikkuState } from '../../pikku-state.js'
16
17
 
17
18
  export interface RunServerlessChannelParams<ChannelData>
18
19
  extends RunChannelParams<ChannelData> {
@@ -32,7 +33,7 @@ const getVariablesForChannel = ({
32
33
  channelHandlerFactory: PikkuChannelHandlerFactory
33
34
  openingData?: unknown
34
35
  }) => {
35
- const { channels } = getChannels()
36
+ const channels = pikkuState('channel', 'channels')
36
37
  const channelConfig = channels.find(
37
38
  (channelConfig) => channelConfig.name === channelName
38
39
  )
@@ -129,7 +130,7 @@ export const runChannelConnect = async ({
129
130
  await runMiddleware(
130
131
  {
131
132
  ...singletonServices,
132
- userSessionService,
133
+ userSession: userSessionService,
133
134
  },
134
135
  { http },
135
136
  channelConfig.middleware || [],
@@ -142,8 +143,8 @@ export const runChannelDisconnect = async ({
142
143
  ...params
143
144
  }: RunServerlessChannelParams<unknown>): Promise<void> => {
144
145
  let sessionServices: SessionServices | undefined
145
- const { userSession, openingData, channelName } =
146
- await params.channelStore.getChannel(params.channelId)
146
+ const { openingData, channelName, session } =
147
+ await params.channelStore.getChannelAndSession(params.channelId)
147
148
  const { channel, channelConfig } = getVariablesForChannel({
148
149
  ...params,
149
150
  openingData,
@@ -153,7 +154,7 @@ export const runChannelDisconnect = async ({
153
154
  sessionServices = await params.createSessionServices(
154
155
  singletonServices,
155
156
  {},
156
- userSession
157
+ session
157
158
  )
158
159
  }
159
160
  await channelConfig.onDisconnect?.(
@@ -171,8 +172,8 @@ export const runChannelMessage = async (
171
172
  data: unknown
172
173
  ): Promise<unknown> => {
173
174
  let sessionServices: SessionServices | undefined
174
- const { userSession, openingData, channelName } =
175
- await params.channelStore.getChannel(params.channelId)
175
+ const { openingData, channelName, session } =
176
+ await params.channelStore.getChannelAndSession(params.channelId)
176
177
  const { channelHandler, channelConfig } = getVariablesForChannel({
177
178
  ...params,
178
179
  openingData,
@@ -182,7 +183,7 @@ export const runChannelMessage = async (
182
183
  sessionServices = await params.createSessionServices(
183
184
  singletonServices,
184
185
  {},
185
- userSession
186
+ session
186
187
  )
187
188
  }
188
189
  let response: unknown
@@ -1,3 +1,5 @@
1
+ import { pikkuState } from '../pikku-state.js'
2
+
1
3
  /**
2
4
  * Base class for custom errors.
3
5
  * @extends {Error}
@@ -21,19 +23,7 @@ export interface ErrorDetails {
21
23
  message: string
22
24
  }
23
25
 
24
- /**
25
- * Map of API errors to their details.
26
- */
27
- if (!globalThis.pikku?.apiErrors) {
28
- globalThis.pikku = globalThis.pikku || {}
29
- globalThis.pikku.apiErrors = new Map<any, ErrorDetails>([])
30
- }
31
-
32
- const apiErrors = (): Map<any, ErrorDetails> => {
33
- return globalThis.pikku.apiErrors
34
- }
35
-
36
- export const getErrors = () => apiErrors()
26
+ export const getErrors = () => pikkuState('errors', 'errors')
37
27
 
38
28
  /**
39
29
  * Adds an error to the API errors map.
@@ -41,7 +31,7 @@ export const getErrors = () => apiErrors()
41
31
  * @param details - The details of the error.
42
32
  */
43
33
  export const addError = (error: any, { status, message }: ErrorDetails) => {
44
- apiErrors().set(error, { status, message })
34
+ pikkuState('errors', 'errors').set(error, { status, message })
45
35
  }
46
36
 
47
37
  /**
@@ -64,11 +54,10 @@ export const addErrors = (
64
54
  export const getErrorResponse = (
65
55
  error: Error
66
56
  ): { status: number; message: string } | undefined => {
67
- const foundError = Array.from(apiErrors().entries()).find(
68
- ([e]) => e.name === error.constructor.name
69
- )
57
+ const errors = Array.from(pikkuState('errors', 'errors').entries())
58
+ const foundError = errors.find(([e]) => e.name === error.constructor.name)
70
59
  if (foundError) {
71
60
  return foundError[1]
72
61
  }
73
- return apiErrors().get(error)
62
+ return pikkuState('errors', 'errors').get(error)
74
63
  }
@@ -121,14 +121,13 @@ addError(ProxyAuthenticationRequiredError, {
121
121
  })
122
122
 
123
123
  /**
124
- * The server did not receive a timely response from an upstream server.
124
+ * The server request expired
125
125
  * @group Error
126
126
  */
127
127
  export class RequestTimeoutError extends PikkuError {}
128
128
  addError(RequestTimeoutError, {
129
129
  status: 408,
130
- message:
131
- 'The server did not receive a timely response from an upstream server.',
130
+ message: 'The request timeout has expired.',
132
131
  })
133
132
 
134
133
  /**
@@ -30,7 +30,6 @@ export const handleError = (
30
30
 
31
31
  // Get appropriate error response
32
32
  const errorResponse = getErrorResponse(e)
33
-
34
33
  if (errorResponse != null) {
35
34
  // Set status and response body
36
35
  http?.response?.setStatus(errorResponse.status)
@@ -4,7 +4,8 @@ import { NotFoundError } from '../errors/errors.js'
4
4
  import { PikkuHTTPAbstractRequest } from './pikku-http-abstract-request.js'
5
5
  import { PikkuHTTPAbstractResponse } from './pikku-http-abstract-response.js'
6
6
  import { JSONValue, PikkuMiddleware } from '../types/core.types.js'
7
- import { runHTTPRoute, clearRoutes, addRoute } from './http-route-runner.js'
7
+ import { runHTTPRoute, addRoute } from './http-route-runner.js'
8
+ import { resetPikkuState } from '../pikku-state.js'
8
9
 
9
10
  class PikkuTestRequest extends PikkuHTTPAbstractRequest {
10
11
  public getBody(): Promise<unknown> {
@@ -39,7 +40,7 @@ describe('runHTTPRoute', () => {
39
40
  let response: any
40
41
 
41
42
  beforeEach(() => {
42
- clearRoutes()
43
+ resetPikkuState()
43
44
 
44
45
  singletonServices = {
45
46
  logger: {
@@ -1,13 +1,11 @@
1
1
  import { verifyPermissions } from '../permissions.js'
2
2
  import {
3
3
  CoreHTTPFunctionRoute,
4
- HTTPRoutesMeta,
5
4
  RunRouteOptions,
6
5
  RunRouteParams,
7
6
  PikkuHTTP,
8
- HTTPRouteMiddleware,
9
7
  } from './http-routes.types.js'
10
- import { SessionServices } from '../types/core.types.js'
8
+ import { PikkuMiddleware, SessionServices } from '../types/core.types.js'
11
9
  import { match } from 'path-to-regexp'
12
10
  import { PikkuHTTPAbstractRequest } from './pikku-http-abstract-request.js'
13
11
  import { PikkuHTTPAbstractResponse } from './pikku-http-abstract-response.js'
@@ -24,59 +22,7 @@ import { coerceQueryStringToArray, validateSchema } from '../schema.js'
24
22
  import { LocalUserSessionService } from '../services/user-session-service.js'
25
23
  import { runMiddleware } from '../middleware-runner.js'
26
24
  import { handleError } from '../handle-error.js'
27
-
28
- /**
29
- * Initialize global state for HTTP routes and middleware if not already available
30
- */
31
- if (!globalThis.pikku?.httpRoutes) {
32
- globalThis.pikku = globalThis.pikku || {}
33
- globalThis.pikku.httpMiddleware = []
34
- globalThis.pikku.httpRoutes = []
35
- globalThis.pikku.httpRoutesMeta = []
36
- }
37
-
38
- /**
39
- * Get or set the global HTTP routes
40
- *
41
- * @param {CoreHTTPFunctionRoute<any, any, any>[]} [data] - Optional routes data to set
42
- * @returns {CoreHTTPFunctionRoute<any, any, any>[]} Current routes
43
- */
44
- const httpRoutes = (
45
- data?: CoreHTTPFunctionRoute<any, any, any>[]
46
- ): CoreHTTPFunctionRoute<any, any, any>[] => {
47
- if (data) {
48
- globalThis.pikku.httpRoutes = data
49
- }
50
- return globalThis.pikku.httpRoutes
51
- }
52
-
53
- /**
54
- * Get or set the global HTTP route metadata
55
- *
56
- * @param {HTTPRoutesMeta} [data] - Optional route metadata to set
57
- * @returns {HTTPRoutesMeta} Current route metadata
58
- */
59
- const httpRoutesMeta = (data?: HTTPRoutesMeta): HTTPRoutesMeta => {
60
- if (data) {
61
- globalThis.pikku.httpRoutesMeta = data
62
- }
63
- return globalThis.pikku.httpRoutesMeta
64
- }
65
-
66
- /**
67
- * Get or set the global HTTP middleware
68
- *
69
- * @param {HTTPRouteMiddleware[]} [data] - Optional middleware to set
70
- * @returns {HTTPRouteMiddleware[]} Current middleware
71
- */
72
- const httpMiddleware = (
73
- data?: HTTPRouteMiddleware[]
74
- ): HTTPRouteMiddleware[] => {
75
- if (data) {
76
- globalThis.pikku.httpMiddleware = data
77
- }
78
- return globalThis.pikku.httpMiddleware
79
- }
25
+ import { pikkuState } from '../pikku-state.js'
80
26
 
81
27
  /**
82
28
  * Add middleware to a specific route or globally
@@ -84,19 +30,19 @@ const httpMiddleware = (
84
30
  * @param {APIMiddleware[] | string} routeOrMiddleware - Route pattern to match or middleware array
85
31
  * @param {APIMiddleware} [middleware] - Middleware to add (required if first param is a string)
86
32
  */
87
- export const addMiddleware = <APIMiddleware>(
33
+ export const addMiddleware = <APIMiddleware extends PikkuMiddleware>(
88
34
  routeOrMiddleware: APIMiddleware[] | string,
89
- middleware?: APIMiddleware
35
+ middleware?: APIMiddleware[]
90
36
  ) => {
91
- if (typeof routeOrMiddleware === 'string') {
92
- globalThis.pikku.httpMiddleware.push({
37
+ if (typeof routeOrMiddleware === 'string' && middleware) {
38
+ pikkuState('http', 'middleware').push({
93
39
  route: routeOrMiddleware,
94
- middleware: middleware!,
40
+ middleware,
95
41
  })
96
42
  } else {
97
- globalThis.pikku.httpMiddleware.push({
43
+ pikkuState('http', 'middleware').push({
98
44
  route: '*',
99
- middleware: routeOrMiddleware,
45
+ middleware: routeOrMiddleware as any,
100
46
  })
101
47
  }
102
48
  }
@@ -125,37 +71,7 @@ export const addRoute = <
125
71
  APIMiddleware
126
72
  >
127
73
  ) => {
128
- httpRoutes().push(route as any)
129
- }
130
-
131
- /**
132
- * Remove all routes from the global registry
133
- */
134
- export const clearRoutes = () => {
135
- httpRoutes([])
136
- }
137
-
138
- /**
139
- * Set the HTTP routes metadata
140
- *
141
- * @param {HTTPRoutesMeta} routeMeta - Metadata for routes
142
- * @ignore
143
- */
144
- export const setHTTPRoutesMeta = (routeMeta: HTTPRoutesMeta) => {
145
- httpRoutesMeta(routeMeta)
146
- }
147
-
148
- /**
149
- * Returns all the registered routes and associated metadata
150
- *
151
- * @returns {Object} Object containing routes and routesMeta
152
- * @internal
153
- */
154
- export const getRoutes = () => {
155
- return {
156
- routes: httpRoutes(),
157
- routesMeta: httpRoutesMeta(),
158
- }
74
+ pikkuState('http', 'routes').push(route as any)
159
75
  }
160
76
 
161
77
  /**
@@ -166,7 +82,11 @@ export const getRoutes = () => {
166
82
  * @returns {Object | undefined} Matching route information or undefined if no match
167
83
  */
168
84
  const getMatchingRoute = (requestType: string, requestPath: string) => {
169
- for (const route of httpRoutes()) {
85
+ const routes = pikkuState('http', 'routes')
86
+ const middleware = pikkuState('http', 'middleware')
87
+ const routesMeta = pikkuState('http', 'meta')
88
+
89
+ for (const route of routes) {
170
90
  // Skip routes that don't match the request method
171
91
  if (route.method !== requestType.toLowerCase()) {
172
92
  continue
@@ -182,13 +102,13 @@ const getMatchingRoute = (requestType: string, requestPath: string) => {
182
102
 
183
103
  if (matchedPath) {
184
104
  // Get all middleware for this route
185
- const globalMiddleware = httpMiddleware()
105
+ const globalMiddleware = middleware
186
106
  .filter((m) => m.route === '*' || new RegExp(m.route).test(route.route))
187
107
  .map((m) => m.middleware)
188
108
  .flat()
189
109
 
190
110
  // Find schema for this route
191
- const schemaName = httpRoutesMeta().find(
111
+ const schemaName = routesMeta.find(
192
112
  (routeMeta) =>
193
113
  routeMeta.method === route.method && routeMeta.route === route.route
194
114
  )?.input
@@ -269,7 +189,6 @@ const executeRouteWithMiddleware = async (
269
189
  createSessionServices,
270
190
  skipUserSession,
271
191
  } = services
272
- const { coerceToArray } = options
273
192
 
274
193
  const requiresSession = route.auth !== false
275
194
  let sessionServices: any
@@ -318,7 +237,7 @@ const executeRouteWithMiddleware = async (
318
237
  data
319
238
  )
320
239
 
321
- if (coerceToArray && schemaName) {
240
+ if (options.coerceToArray && schemaName) {
322
241
  coerceQueryStringToArray(schemaName, data)
323
242
  }
324
243
 
package/src/http/index.ts CHANGED
@@ -4,11 +4,6 @@ export * from './pikku-http-abstract-response.js'
4
4
 
5
5
  export * from './log-http-routes.js'
6
6
 
7
- export {
8
- runHTTPRoute,
9
- getRoutes,
10
- setHTTPRoutesMeta,
11
- addRoute,
12
- } from './http-route-runner.js'
7
+ export { runHTTPRoute, addRoute } from './http-route-runner.js'
13
8
 
14
9
  export type * from './http-routes.types.js'
@@ -1,12 +1,12 @@
1
+ import { pikkuState } from '../pikku-state.js'
1
2
  import { Logger } from '../services/index.js'
2
- import { getRoutes } from './http-route-runner.js'
3
3
 
4
4
  /**
5
5
  * Logs all the loaded routes.
6
6
  * @param logger - A logger for logging information.
7
7
  */
8
8
  export const logRoutes = (logger: Logger) => {
9
- const { routes } = getRoutes()
9
+ const routes = pikkuState('http', 'routes')
10
10
  if (routes.length === 0) {
11
11
  logger.info('No routes added')
12
12
  return
package/src/index.ts CHANGED
@@ -12,7 +12,8 @@ export * from './scheduler/index.js'
12
12
  export * from './errors/index.js'
13
13
  export * from './middleware/index.js'
14
14
 
15
+ export { pikkuState } from './pikku-state.js'
15
16
  export { runMiddleware } from './middleware-runner.js'
16
- export { addRoute } from './http/http-route-runner.js'
17
+ export { addRoute, addMiddleware } from './http/http-route-runner.js'
17
18
  export { addChannel } from './channel/channel-runner.js'
18
19
  export { addScheduledTask } from './scheduler/scheduler-runner.js'