@pikku/core 0.8.2 → 0.9.1
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.
- package/CHANGELOG.md +13 -1
- package/dist/function/functions.types.d.ts +9 -9
- package/dist/handle-error.d.ts +1 -1
- package/dist/index.d.ts +11 -10
- package/dist/index.js +11 -10
- package/dist/pikku-state.d.ts +9 -9
- package/dist/services/user-session-service.d.ts +1 -1
- package/dist/types/core.types.d.ts +5 -5
- package/dist/types/core.types.js +9 -9
- package/dist/wirings/channel/channel-handler.d.ts +3 -0
- package/dist/{events → wirings}/channel/channel-handler.js +3 -3
- package/dist/wirings/channel/channel-runner.d.ts +14 -0
- package/dist/{events → wirings}/channel/channel-runner.js +13 -13
- package/dist/{events → wirings}/channel/channel.types.d.ts +7 -7
- package/dist/{events → wirings}/channel/eventhub-service.d.ts +4 -4
- package/dist/wirings/channel/eventhub-store.d.ts +5 -0
- package/dist/wirings/channel/local/local-channel-runner.d.ts +3 -0
- package/dist/{events → wirings}/channel/local/local-eventhub-service.d.ts +4 -4
- package/dist/{events → wirings}/channel/local/local-eventhub-service.js +1 -1
- package/dist/{events → wirings}/channel/serverless/serverless-channel-runner.d.ts +2 -2
- package/dist/{events → wirings}/http/http-runner.d.ts +12 -12
- package/dist/{events → wirings}/http/http-runner.js +15 -15
- package/dist/{events → wirings}/http/http.types.d.ts +32 -27
- package/dist/{events → wirings}/http/index.d.ts +1 -1
- package/dist/{events → wirings}/http/index.js +1 -1
- package/dist/{events → wirings}/mcp/mcp-runner.d.ts +4 -4
- package/dist/{events → wirings}/mcp/mcp-runner.js +3 -3
- package/dist/{events → wirings}/mcp/mcp.types.d.ts +7 -7
- package/dist/{events → wirings}/queue/index.d.ts +1 -1
- package/dist/{events → wirings}/queue/index.js +1 -1
- package/dist/{events → wirings}/queue/queue-runner.d.ts +2 -2
- package/dist/{events → wirings}/queue/queue-runner.js +1 -1
- package/dist/{events → wirings}/queue/queue.types.d.ts +3 -3
- package/dist/wirings/scheduler/index.d.ts +3 -0
- package/dist/wirings/scheduler/index.js +3 -0
- package/dist/{events → wirings}/scheduler/scheduler-runner.d.ts +2 -2
- package/dist/{events → wirings}/scheduler/scheduler-runner.js +1 -1
- package/dist/{events → wirings}/scheduler/scheduler.types.d.ts +3 -3
- package/package.json +9 -9
- package/src/function/functions.types.ts +13 -13
- package/src/handle-error.ts +1 -1
- package/src/index.ts +14 -13
- package/src/pikku-state.ts +11 -11
- package/src/services/user-session-service.ts +1 -1
- package/src/types/core.types.ts +5 -5
- package/src/{events → wirings}/channel/channel-handler.ts +5 -5
- package/src/{events → wirings}/channel/channel-runner.ts +18 -18
- package/src/{events → wirings}/channel/channel.types.ts +16 -16
- package/src/{events → wirings}/channel/eventhub-service.ts +12 -8
- package/src/wirings/channel/eventhub-store.ts +13 -0
- package/src/{events → wirings}/channel/local/local-channel-runner.test.ts +2 -2
- package/src/{events → wirings}/channel/local/local-channel-runner.ts +2 -2
- package/src/{events → wirings}/channel/local/local-eventhub-service.ts +16 -10
- package/src/{events → wirings}/channel/serverless/serverless-channel-runner.ts +2 -2
- package/src/{events → wirings}/http/http-runner.test.ts +4 -4
- package/src/{events → wirings}/http/http-runner.ts +32 -31
- package/src/{events → wirings}/http/http.types.ts +40 -35
- package/src/{events → wirings}/http/index.ts +1 -1
- package/src/{events → wirings}/mcp/mcp-runner.ts +10 -10
- package/src/{events → wirings}/mcp/mcp.types.ts +9 -7
- package/src/{events → wirings}/queue/index.ts +1 -1
- package/src/{events → wirings}/queue/queue-runner.ts +5 -5
- package/src/{events → wirings}/queue/queue.types.ts +3 -3
- package/src/{events → wirings}/scheduler/index.ts +1 -1
- package/src/{events → wirings}/scheduler/scheduler-runner.ts +4 -4
- package/src/{events → wirings}/scheduler/scheduler.types.ts +3 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/events/channel/channel-handler.d.ts +0 -3
- package/dist/events/channel/channel-runner.d.ts +0 -14
- package/dist/events/channel/eventhub-store.d.ts +0 -5
- package/dist/events/channel/local/local-channel-runner.d.ts +0 -3
- package/dist/events/scheduler/index.d.ts +0 -3
- package/dist/events/scheduler/index.js +0 -3
- package/src/events/channel/eventhub-store.ts +0 -8
- /package/dist/{events → wirings}/channel/channel-store.d.ts +0 -0
- /package/dist/{events → wirings}/channel/channel-store.js +0 -0
- /package/dist/{events → wirings}/channel/channel.types.js +0 -0
- /package/dist/{events → wirings}/channel/eventhub-service.js +0 -0
- /package/dist/{events → wirings}/channel/eventhub-store.js +0 -0
- /package/dist/{events → wirings}/channel/index.d.ts +0 -0
- /package/dist/{events → wirings}/channel/index.js +0 -0
- /package/dist/{events → wirings}/channel/local/index.d.ts +0 -0
- /package/dist/{events → wirings}/channel/local/index.js +0 -0
- /package/dist/{events → wirings}/channel/local/local-channel-handler.d.ts +0 -0
- /package/dist/{events → wirings}/channel/local/local-channel-handler.js +0 -0
- /package/dist/{events → wirings}/channel/local/local-channel-runner.js +0 -0
- /package/dist/{events → wirings}/channel/log-channels.d.ts +0 -0
- /package/dist/{events → wirings}/channel/log-channels.js +0 -0
- /package/dist/{events → wirings}/channel/pikku-abstract-channel-handler.d.ts +0 -0
- /package/dist/{events → wirings}/channel/pikku-abstract-channel-handler.js +0 -0
- /package/dist/{events → wirings}/channel/serverless/index.d.ts +0 -0
- /package/dist/{events → wirings}/channel/serverless/index.js +0 -0
- /package/dist/{events → wirings}/channel/serverless/serverless-channel-runner.js +0 -0
- /package/dist/{events → wirings}/http/http.types.js +0 -0
- /package/dist/{events → wirings}/http/log-http-routes.d.ts +0 -0
- /package/dist/{events → wirings}/http/log-http-routes.js +0 -0
- /package/dist/{events → wirings}/http/pikku-fetch-http-request.d.ts +0 -0
- /package/dist/{events → wirings}/http/pikku-fetch-http-request.js +0 -0
- /package/dist/{events → wirings}/http/pikku-fetch-http-response.d.ts +0 -0
- /package/dist/{events → wirings}/http/pikku-fetch-http-response.js +0 -0
- /package/dist/{events → wirings}/mcp/index.d.ts +0 -0
- /package/dist/{events → wirings}/mcp/index.js +0 -0
- /package/dist/{events → wirings}/mcp/mcp-endpoint-registry.d.ts +0 -0
- /package/dist/{events → wirings}/mcp/mcp-endpoint-registry.js +0 -0
- /package/dist/{events → wirings}/mcp/mcp.types.js +0 -0
- /package/dist/{events → wirings}/queue/queue.types.js +0 -0
- /package/dist/{events → wirings}/queue/register-queue-helper.d.ts +0 -0
- /package/dist/{events → wirings}/queue/register-queue-helper.js +0 -0
- /package/dist/{events → wirings}/queue/validate-worker-config.d.ts +0 -0
- /package/dist/{events → wirings}/queue/validate-worker-config.js +0 -0
- /package/dist/{events → wirings}/rpc/index.d.ts +0 -0
- /package/dist/{events → wirings}/rpc/index.js +0 -0
- /package/dist/{events → wirings}/rpc/rpc-runner.d.ts +0 -0
- /package/dist/{events → wirings}/rpc/rpc-runner.js +0 -0
- /package/dist/{events → wirings}/rpc/rpc-types.d.ts +0 -0
- /package/dist/{events → wirings}/rpc/rpc-types.js +0 -0
- /package/dist/{events → wirings}/scheduler/log-schedulers.d.ts +0 -0
- /package/dist/{events → wirings}/scheduler/log-schedulers.js +0 -0
- /package/dist/{events → wirings}/scheduler/scheduler.types.js +0 -0
- /package/src/{events → wirings}/channel/channel-store.ts +0 -0
- /package/src/{events → wirings}/channel/index.ts +0 -0
- /package/src/{events → wirings}/channel/local/index.ts +0 -0
- /package/src/{events → wirings}/channel/local/local-channel-handler.ts +0 -0
- /package/src/{events → wirings}/channel/local/local-eventhub-service.test.ts +0 -0
- /package/src/{events → wirings}/channel/log-channels.ts +0 -0
- /package/src/{events → wirings}/channel/pikku-abstract-channel-handler.test.ts +0 -0
- /package/src/{events → wirings}/channel/pikku-abstract-channel-handler.ts +0 -0
- /package/src/{events → wirings}/channel/serverless/index.ts +0 -0
- /package/src/{events → wirings}/http/log-http-routes.ts +0 -0
- /package/src/{events → wirings}/http/pikku-fetch-http-request.test.ts +0 -0
- /package/src/{events → wirings}/http/pikku-fetch-http-request.ts +0 -0
- /package/src/{events → wirings}/http/pikku-fetch-http-response.test.ts +0 -0
- /package/src/{events → wirings}/http/pikku-fetch-http-response.ts +0 -0
- /package/src/{events → wirings}/mcp/index.ts +0 -0
- /package/src/{events → wirings}/mcp/mcp-endpoint-registry.test.d.ts +0 -0
- /package/src/{events → wirings}/mcp/mcp-endpoint-registry.test.ts +0 -0
- /package/src/{events → wirings}/mcp/mcp-endpoint-registry.ts +0 -0
- /package/src/{events → wirings}/queue/register-queue-helper.ts +0 -0
- /package/src/{events → wirings}/queue/validate-worker-config.ts +0 -0
- /package/src/{events → wirings}/rpc/index.ts +0 -0
- /package/src/{events → wirings}/rpc/rpc-runner.ts +0 -0
- /package/src/{events → wirings}/rpc/rpc-types.ts +0 -0
- /package/src/{events → wirings}/scheduler/log-schedulers.ts +0 -0
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from '../../types/core.types.js'
|
|
6
6
|
import {
|
|
7
7
|
ChannelMessageMeta,
|
|
8
|
-
|
|
8
|
+
CoreChannel,
|
|
9
9
|
PikkuChannelHandler,
|
|
10
10
|
} from './channel.types.js'
|
|
11
11
|
import { pikkuState } from '../../pikku-state.js'
|
|
@@ -31,7 +31,7 @@ const getRouteMeta = (
|
|
|
31
31
|
`Channel ${channelName} requires a router value for ${routingProperty}`
|
|
32
32
|
)
|
|
33
33
|
}
|
|
34
|
-
const route = channelMeta.
|
|
34
|
+
const route = channelMeta.messageWirings[routingProperty]?.[routerValue]
|
|
35
35
|
if (!route) {
|
|
36
36
|
throw new Error(
|
|
37
37
|
`Channel ${channelName} has no route for ${routingProperty}:${routerValue}`
|
|
@@ -61,7 +61,7 @@ const validateAuth = (
|
|
|
61
61
|
export const processMessageHandlers = (
|
|
62
62
|
services: CoreServices,
|
|
63
63
|
session: CoreUserSession | undefined,
|
|
64
|
-
channelConfig:
|
|
64
|
+
channelConfig: CoreChannel<any, any>,
|
|
65
65
|
channelHandler: PikkuChannelHandler
|
|
66
66
|
) => {
|
|
67
67
|
const logger = services.logger
|
|
@@ -115,10 +115,10 @@ export const processMessageHandlers = (
|
|
|
115
115
|
let processed = false
|
|
116
116
|
|
|
117
117
|
// Route-specific handling
|
|
118
|
-
if (typeof rawData === 'string' && channelConfig.
|
|
118
|
+
if (typeof rawData === 'string' && channelConfig.onMessageWiring) {
|
|
119
119
|
try {
|
|
120
120
|
const messageData = JSON.parse(rawData)
|
|
121
|
-
const entries = Object.entries(channelConfig.
|
|
121
|
+
const entries = Object.entries(channelConfig.onMessageWiring)
|
|
122
122
|
for (const [routingProperty, routes] of entries) {
|
|
123
123
|
const routerValue = messageData[routingProperty]
|
|
124
124
|
if (routerValue && routes[routerValue]) {
|
|
@@ -5,7 +5,7 @@ import { coerceTopLevelDataFromSchema, validateSchema } from '../../schema.js'
|
|
|
5
5
|
import { UserSessionService } from '../../services/user-session-service.js'
|
|
6
6
|
import {
|
|
7
7
|
ChannelMeta,
|
|
8
|
-
|
|
8
|
+
CoreChannel,
|
|
9
9
|
RunChannelOptions,
|
|
10
10
|
RunChannelParams,
|
|
11
11
|
} from './channel.types.js'
|
|
@@ -15,14 +15,14 @@ import { match } from 'path-to-regexp'
|
|
|
15
15
|
* Adds a channel and registers all functions referenced in it using the
|
|
16
16
|
* function names already stored in the channel metadata
|
|
17
17
|
*/
|
|
18
|
-
export const
|
|
18
|
+
export const wireChannel = <
|
|
19
19
|
In,
|
|
20
20
|
Channel extends string,
|
|
21
21
|
ChannelFunction,
|
|
22
22
|
ChannelFunctionSessionless,
|
|
23
|
-
|
|
23
|
+
PikkuPermission,
|
|
24
24
|
>(
|
|
25
|
-
channel:
|
|
25
|
+
channel: CoreChannel<In, Channel, ChannelFunction, PikkuPermission>
|
|
26
26
|
) => {
|
|
27
27
|
// Get the channel metadata
|
|
28
28
|
const channelsMeta = pikkuState('channel', 'meta')
|
|
@@ -58,20 +58,20 @@ export const addChannel = <
|
|
|
58
58
|
})
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
// Register functions in
|
|
62
|
-
if (channel.
|
|
63
|
-
// Iterate through each channel in
|
|
64
|
-
Object.entries(channel.
|
|
65
|
-
const
|
|
66
|
-
if (!
|
|
61
|
+
// Register functions in onMessageWiring
|
|
62
|
+
if (channel.onMessageWiring && channelMeta.messageWirings) {
|
|
63
|
+
// Iterate through each channel in onMessageWiring
|
|
64
|
+
Object.entries(channel.onMessageWiring).forEach(([channelKey, wirings]) => {
|
|
65
|
+
const channelWirings = channelMeta.messageWirings[channelKey]
|
|
66
|
+
if (!channelWirings) return
|
|
67
67
|
|
|
68
|
-
// Iterate through each
|
|
69
|
-
Object.entries(
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
68
|
+
// Iterate through each wiring in the channel
|
|
69
|
+
Object.entries(wirings).forEach(([wiringKey, handler]) => {
|
|
70
|
+
const wiringMeta = channelWirings[wiringKey]
|
|
71
|
+
if (!wiringMeta) return
|
|
72
72
|
|
|
73
73
|
// Extract the function from the handler
|
|
74
|
-
const
|
|
74
|
+
const wiringFunc =
|
|
75
75
|
typeof handler === 'function'
|
|
76
76
|
? { func: handler }
|
|
77
77
|
: {
|
|
@@ -81,7 +81,7 @@ export const addChannel = <
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// Register the function using the pikku name from metadata
|
|
84
|
-
addFunction(
|
|
84
|
+
addFunction(wiringMeta.pikkuFuncName, wiringFunc)
|
|
85
85
|
})
|
|
86
86
|
})
|
|
87
87
|
}
|
|
@@ -122,12 +122,12 @@ export const openChannel = async ({
|
|
|
122
122
|
singletonServices,
|
|
123
123
|
coerceDataFromSchema = true,
|
|
124
124
|
request,
|
|
125
|
-
}: Pick<
|
|
125
|
+
}: Pick<CoreChannel<unknown, string>, 'route'> &
|
|
126
126
|
RunChannelParams<unknown> & {
|
|
127
127
|
userSession: UserSessionService<any>
|
|
128
128
|
} & RunChannelOptions): Promise<{
|
|
129
129
|
openingData: unknown
|
|
130
|
-
channelConfig:
|
|
130
|
+
channelConfig: CoreChannel<unknown, any>
|
|
131
131
|
meta: ChannelMeta
|
|
132
132
|
}> => {
|
|
133
133
|
const matchingChannel = getMatchingChannelConfig(route)
|
|
@@ -11,9 +11,9 @@ import {
|
|
|
11
11
|
PikkuMiddleware,
|
|
12
12
|
} from '../../types/core.types.js'
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
CorePikkuFunction,
|
|
15
|
+
CorePikkuFunctionSessionless,
|
|
16
|
+
CorePikkuPermission,
|
|
17
17
|
} from '../../function/functions.types.js'
|
|
18
18
|
|
|
19
19
|
export type RunChannelOptions = Partial<{
|
|
@@ -47,26 +47,26 @@ export interface ChannelMeta {
|
|
|
47
47
|
connect: ChannelMessageMeta | null
|
|
48
48
|
disconnect: ChannelMessageMeta | null
|
|
49
49
|
message: ChannelMessageMeta | null
|
|
50
|
-
|
|
50
|
+
messageWirings: Record<string, Record<string, ChannelMessageMeta>>
|
|
51
51
|
docs?: APIDocs
|
|
52
52
|
tags?: string[]
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
export type ChannelsMeta = Record<string, ChannelMeta>
|
|
56
56
|
|
|
57
|
-
export type
|
|
57
|
+
export type CoreChannel<
|
|
58
58
|
ChannelData,
|
|
59
59
|
Channel extends string,
|
|
60
60
|
ChannelConnect =
|
|
61
|
-
|
|
|
62
|
-
|
|
|
61
|
+
| CorePikkuFunction<void, unknown, ChannelData>
|
|
62
|
+
| CorePikkuFunctionSessionless<void, unknown, ChannelData>,
|
|
63
63
|
ChannelDisconnect =
|
|
64
|
-
|
|
|
65
|
-
|
|
|
64
|
+
| CorePikkuFunction<void, void, ChannelData>
|
|
65
|
+
| CorePikkuFunctionSessionless<void, void, ChannelData>,
|
|
66
66
|
ChannelFunctionMessage =
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
67
|
+
| CorePikkuFunction<unknown, unknown, ChannelData>
|
|
68
|
+
| CorePikkuFunctionSessionless<unknown, unknown, ChannelData>,
|
|
69
|
+
PikkuPermission = CorePikkuPermission<ChannelData>,
|
|
70
70
|
> = {
|
|
71
71
|
name: string
|
|
72
72
|
route: Channel
|
|
@@ -75,24 +75,24 @@ export type CoreAPIChannel<
|
|
|
75
75
|
onMessage?:
|
|
76
76
|
| {
|
|
77
77
|
func: ChannelFunctionMessage
|
|
78
|
-
permissions?: Record<string,
|
|
78
|
+
permissions?: Record<string, PikkuPermission[] | PikkuPermission>
|
|
79
79
|
auth?: boolean
|
|
80
80
|
}
|
|
81
81
|
| ChannelFunctionMessage
|
|
82
|
-
|
|
82
|
+
onMessageWiring?: Record<
|
|
83
83
|
string,
|
|
84
84
|
Record<
|
|
85
85
|
string,
|
|
86
86
|
| ChannelFunctionMessage
|
|
87
87
|
| {
|
|
88
88
|
func: ChannelFunctionMessage
|
|
89
|
-
permissions?: Record<string,
|
|
89
|
+
permissions?: Record<string, PikkuPermission[] | PikkuPermission>
|
|
90
90
|
auth?: boolean
|
|
91
91
|
}
|
|
92
92
|
>
|
|
93
93
|
>
|
|
94
94
|
middleware?: PikkuMiddleware[]
|
|
95
|
-
permissions?: Record<string,
|
|
95
|
+
permissions?: Record<string, PikkuPermission[] | PikkuPermission>
|
|
96
96
|
auth?: boolean
|
|
97
97
|
docs?: Partial<{
|
|
98
98
|
description: string
|
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Interface defining the methods of a EventHub Service.
|
|
3
3
|
*/
|
|
4
|
-
export interface EventHubService<
|
|
4
|
+
export interface EventHubService<Topics extends Record<string, any>> {
|
|
5
5
|
/**
|
|
6
6
|
* Subscribes a connection to a specific topic.
|
|
7
7
|
* @param topic - The topic to subscribe to.
|
|
8
8
|
* @param channelId - The unique ID of the connection to subscribe.
|
|
9
9
|
*/
|
|
10
|
-
subscribe
|
|
11
|
-
|
|
10
|
+
subscribe<T extends keyof Topics>(
|
|
11
|
+
topic: T,
|
|
12
|
+
channelId: string
|
|
13
|
+
): Promise<void> | void
|
|
12
14
|
/**
|
|
13
15
|
* Unsubscribes a connection from a specific topic.
|
|
14
16
|
* @param topic - The topic to unsubscribe from.
|
|
15
17
|
* @param channelId - The unique ID of the connection to unsubscribe.
|
|
16
18
|
*/
|
|
17
|
-
unsubscribe
|
|
18
|
-
|
|
19
|
+
unsubscribe<T extends keyof Topics>(
|
|
20
|
+
topic: T,
|
|
21
|
+
channelId: string
|
|
22
|
+
): Promise<void> | void
|
|
19
23
|
/**
|
|
20
24
|
* Sends data to all connections subscribed to a topic.
|
|
21
25
|
* @param topic - The topic to send data to.
|
|
22
26
|
* @param data - The data to send to the subscribers.
|
|
23
27
|
*/
|
|
24
|
-
publish(
|
|
25
|
-
topic:
|
|
28
|
+
publish<T extends keyof Topics>(
|
|
29
|
+
topic: T,
|
|
26
30
|
channelId: string | null,
|
|
27
|
-
data:
|
|
31
|
+
data: Topics[T],
|
|
28
32
|
isBinary?: boolean
|
|
29
33
|
): Promise<void> | void
|
|
30
34
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export abstract class EventHubStore<
|
|
2
|
+
EventTopics extends Record<string, any> = {},
|
|
3
|
+
> {
|
|
4
|
+
public abstract getChannelIdsForTopic(topic: string): Promise<string[]>
|
|
5
|
+
public abstract subscribe<T extends keyof EventTopics>(
|
|
6
|
+
topic: T,
|
|
7
|
+
channelId: string
|
|
8
|
+
): Promise<boolean>
|
|
9
|
+
public abstract unsubscribe<T extends keyof EventTopics>(
|
|
10
|
+
topic: T,
|
|
11
|
+
channelId: string
|
|
12
|
+
): Promise<boolean>
|
|
13
|
+
}
|
|
@@ -2,7 +2,7 @@ import { test, beforeEach, afterEach } from 'node:test'
|
|
|
2
2
|
import * as assert from 'node:assert/strict'
|
|
3
3
|
import { runLocalChannel } from './local-channel-runner.js'
|
|
4
4
|
import { pikkuState, resetPikkuState } from '../../../pikku-state.js'
|
|
5
|
-
import {
|
|
5
|
+
import { wireChannel } from '../channel-runner.js'
|
|
6
6
|
import {
|
|
7
7
|
HTTPMethod,
|
|
8
8
|
PikkuHTTPRequest,
|
|
@@ -133,7 +133,7 @@ test('runChannel should return a channel handler if channel matches and no auth
|
|
|
133
133
|
route: '/test-channel',
|
|
134
134
|
},
|
|
135
135
|
} as any)
|
|
136
|
-
|
|
136
|
+
wireChannel({
|
|
137
137
|
name: 'test',
|
|
138
138
|
route: '/test-channel',
|
|
139
139
|
auth: false,
|
|
@@ -3,7 +3,7 @@ import { createHTTPInteraction } from '../../http/http-runner.js'
|
|
|
3
3
|
import { closeSessionServices } from '../../../utils.js'
|
|
4
4
|
import { processMessageHandlers } from '../channel-handler.js'
|
|
5
5
|
import {
|
|
6
|
-
|
|
6
|
+
CoreChannel,
|
|
7
7
|
RunChannelOptions,
|
|
8
8
|
RunChannelParams,
|
|
9
9
|
} from '../channel.types.js'
|
|
@@ -28,7 +28,7 @@ export const runLocalChannel = async ({
|
|
|
28
28
|
coerceDataFromSchema = true,
|
|
29
29
|
logWarningsForStatusCodes = [],
|
|
30
30
|
bubbleErrors = false,
|
|
31
|
-
}: Partial<Pick<
|
|
31
|
+
}: Partial<Pick<CoreChannel<unknown, any>, 'route'>> &
|
|
32
32
|
RunChannelOptions &
|
|
33
33
|
RunChannelParams<unknown>): Promise<PikkuLocalChannelHandler | void> => {
|
|
34
34
|
let sessionServices: SessionServices<typeof singletonServices> | undefined
|
|
@@ -5,7 +5,7 @@ import { EventHubService } from '../eventhub-service.js'
|
|
|
5
5
|
* Implementation of the SubscriptionService interface.
|
|
6
6
|
* Manages subscriptions and publishes messages to subscribers.
|
|
7
7
|
*/
|
|
8
|
-
export class LocalEventHubService<Data =
|
|
8
|
+
export class LocalEventHubService<Data extends Record<string, any> = {}>
|
|
9
9
|
implements EventHubService<Data>
|
|
10
10
|
{
|
|
11
11
|
private channels = new Map<string, PikkuChannelHandler>()
|
|
@@ -13,7 +13,7 @@ export class LocalEventHubService<Data = unknown>
|
|
|
13
13
|
/**
|
|
14
14
|
* A map storing topics and their associated connection IDs.
|
|
15
15
|
*/
|
|
16
|
-
private subscriptions: Map<
|
|
16
|
+
private subscriptions: Map<keyof Data, Set<string>> = new Map()
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Subscribes a connection to a specific topic.
|
|
@@ -21,7 +21,10 @@ export class LocalEventHubService<Data = unknown>
|
|
|
21
21
|
* @param topic - The topic to subscribe to.
|
|
22
22
|
* @param channelId - The unique ID of the connection to subscribe.
|
|
23
23
|
*/
|
|
24
|
-
public subscribe
|
|
24
|
+
public subscribe<T extends keyof Data>(
|
|
25
|
+
topic: T,
|
|
26
|
+
channelId: string
|
|
27
|
+
): void | Promise<void> {
|
|
25
28
|
if (!this.subscriptions.has(topic)) {
|
|
26
29
|
this.subscriptions.set(topic, new Set())
|
|
27
30
|
}
|
|
@@ -34,12 +37,15 @@ export class LocalEventHubService<Data = unknown>
|
|
|
34
37
|
* @param topic - The topic to unsubscribe from.
|
|
35
38
|
* @param channelId - The unique ID of the connection to unsubscribe.
|
|
36
39
|
*/
|
|
37
|
-
public unsubscribe
|
|
40
|
+
public unsubscribe<T extends keyof Data>(
|
|
41
|
+
topic: T,
|
|
42
|
+
channelId: string
|
|
43
|
+
): void | Promise<void> {
|
|
38
44
|
const topicSubscriptions = this.subscriptions.get(topic)
|
|
39
45
|
if (topicSubscriptions) {
|
|
40
46
|
topicSubscriptions.delete(channelId)
|
|
41
47
|
if (topicSubscriptions.size === 0) {
|
|
42
|
-
this.subscriptions.delete(topic)
|
|
48
|
+
this.subscriptions.delete(topic)
|
|
43
49
|
}
|
|
44
50
|
}
|
|
45
51
|
}
|
|
@@ -49,12 +55,12 @@ export class LocalEventHubService<Data = unknown>
|
|
|
49
55
|
* @param topic - The topic to send data to.
|
|
50
56
|
* @param data - The data to send to the subscribers.
|
|
51
57
|
*/
|
|
52
|
-
public publish(
|
|
53
|
-
topic:
|
|
54
|
-
channelId: string,
|
|
55
|
-
data: Data,
|
|
58
|
+
public publish<T extends keyof Data>(
|
|
59
|
+
topic: T,
|
|
60
|
+
channelId: string | null,
|
|
61
|
+
data: Data[T],
|
|
56
62
|
isBinary?: boolean
|
|
57
|
-
): void {
|
|
63
|
+
): void | Promise<void> {
|
|
58
64
|
const subscribedChannelIds = this.subscriptions.get(topic)
|
|
59
65
|
if (!subscribedChannelIds) {
|
|
60
66
|
return
|
|
@@ -3,7 +3,7 @@ import { closeSessionServices } from '../../../utils.js'
|
|
|
3
3
|
import { processMessageHandlers } from '../channel-handler.js'
|
|
4
4
|
import { openChannel } from '../channel-runner.js'
|
|
5
5
|
import type {
|
|
6
|
-
|
|
6
|
+
CoreChannel,
|
|
7
7
|
RunChannelOptions,
|
|
8
8
|
RunChannelParams,
|
|
9
9
|
PikkuChannelHandlerFactory,
|
|
@@ -73,7 +73,7 @@ export const runChannelConnect = async ({
|
|
|
73
73
|
logWarningsForStatusCodes = [],
|
|
74
74
|
respondWith404 = true,
|
|
75
75
|
bubbleErrors = false,
|
|
76
|
-
}: Pick<
|
|
76
|
+
}: Pick<CoreChannel<unknown, any>, 'route'> &
|
|
77
77
|
RunChannelOptions &
|
|
78
78
|
RunServerlessChannelParams<unknown>) => {
|
|
79
79
|
let sessionServices: SessionServices | undefined
|
|
@@ -2,7 +2,7 @@ import { test, describe, beforeEach, afterEach } from 'node:test'
|
|
|
2
2
|
import * as assert from 'assert'
|
|
3
3
|
import { NotFoundError } from '../../errors/errors.js'
|
|
4
4
|
import { JSONValue, PikkuMiddleware } from '../../types/core.types.js'
|
|
5
|
-
import { fetch,
|
|
5
|
+
import { fetch, wireHTTP } from './http-runner.js'
|
|
6
6
|
import { pikkuState, resetPikkuState } from '../../pikku-state.js'
|
|
7
7
|
import {
|
|
8
8
|
PikkuMockRequest,
|
|
@@ -78,7 +78,7 @@ describe('fetch', () => {
|
|
|
78
78
|
const routeFunc = async () => ({ success: true })
|
|
79
79
|
setHTTPFunctionMap(routeFunc)
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
wireHTTP({
|
|
82
82
|
route: 'test',
|
|
83
83
|
method: 'get',
|
|
84
84
|
func: routeFunc,
|
|
@@ -98,7 +98,7 @@ describe('fetch', () => {
|
|
|
98
98
|
const routeFunc = async () => ({ success: true })
|
|
99
99
|
setHTTPFunctionMap(routeFunc)
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
wireHTTP({
|
|
102
102
|
route: 'test',
|
|
103
103
|
method: 'get',
|
|
104
104
|
func: routeFunc,
|
|
@@ -120,7 +120,7 @@ describe('fetch', () => {
|
|
|
120
120
|
throw error
|
|
121
121
|
}
|
|
122
122
|
setHTTPFunctionMap(routeFunc)
|
|
123
|
-
|
|
123
|
+
wireHTTP({
|
|
124
124
|
route: 'test',
|
|
125
125
|
method: 'get',
|
|
126
126
|
func: routeFunc,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
CoreHTTPFunctionWiring,
|
|
3
|
+
RunHTTPWiringOptions,
|
|
4
|
+
RunHTTPWiringParams,
|
|
5
5
|
PikkuHTTP,
|
|
6
6
|
PikkuHTTPRequest,
|
|
7
7
|
PikkuHTTPResponse,
|
|
8
|
-
|
|
8
|
+
HTTPWiringMeta,
|
|
9
9
|
HTTPMethod,
|
|
10
10
|
} from './http.types.js'
|
|
11
11
|
import {
|
|
@@ -87,48 +87,49 @@ export const addMiddleware = <APIMiddleware extends PikkuMiddleware>(
|
|
|
87
87
|
* @template In Expected input type.
|
|
88
88
|
* @template Out Expected output type.
|
|
89
89
|
* @template Route Route pattern as a string.
|
|
90
|
-
* @template
|
|
91
|
-
* @template
|
|
92
|
-
* @template
|
|
90
|
+
* @template PikkuFunction Type for the route handler function.
|
|
91
|
+
* @template PikkuFunctionSessionless Type for a sessionless handler.
|
|
92
|
+
* @template PikkuPermissionGroup Type representing required permissions.
|
|
93
93
|
* @template APIMiddleware Middleware type to be used with the route.
|
|
94
|
-
* @param {
|
|
94
|
+
* @param {CoreHTTPFunctionWiring<In, Out, Route, PikkuFunction, PikkuFunctionSessionless, PikkuPermission, APIMiddleware>} httpWiring - The HTTP wiring configuration object.
|
|
95
95
|
*/
|
|
96
|
-
export const
|
|
96
|
+
export const wireHTTP = <
|
|
97
97
|
In,
|
|
98
98
|
Out,
|
|
99
99
|
Route extends string,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
PikkuFunction,
|
|
101
|
+
PikkuFunctionSessionless,
|
|
102
|
+
PikkuPermissionGroup,
|
|
103
103
|
APIMiddleware,
|
|
104
104
|
>(
|
|
105
|
-
|
|
105
|
+
httpWiring: CoreHTTPFunctionWiring<
|
|
106
106
|
In,
|
|
107
107
|
Out,
|
|
108
108
|
Route,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
PikkuFunction,
|
|
110
|
+
PikkuFunctionSessionless,
|
|
111
|
+
PikkuPermissionGroup,
|
|
112
112
|
APIMiddleware
|
|
113
113
|
>
|
|
114
114
|
) => {
|
|
115
115
|
const httpMeta = pikkuState('http', 'meta')
|
|
116
116
|
const routeMeta = httpMeta.find(
|
|
117
|
-
(meta) =>
|
|
117
|
+
(meta) =>
|
|
118
|
+
meta.route === httpWiring.route && meta.method === httpWiring.method
|
|
118
119
|
)
|
|
119
120
|
if (!routeMeta) {
|
|
120
121
|
throw new Error('Route metadata not found')
|
|
121
122
|
}
|
|
122
123
|
addFunction(routeMeta.pikkuFuncName, {
|
|
123
|
-
func:
|
|
124
|
+
func: httpWiring.func,
|
|
124
125
|
})
|
|
125
126
|
const routes = pikkuState('http', 'routes')
|
|
126
|
-
if (!routes.has(
|
|
127
|
-
routes.set(
|
|
127
|
+
if (!routes.has(httpWiring.method)) {
|
|
128
|
+
routes.set(httpWiring.method, new Map())
|
|
128
129
|
}
|
|
129
130
|
pikkuState('http', 'routes')
|
|
130
|
-
.get(
|
|
131
|
-
?.set(
|
|
131
|
+
.get(httpWiring.method)
|
|
132
|
+
?.set(httpWiring.route, httpWiring as any)
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
/**
|
|
@@ -242,9 +243,9 @@ const executeRouteWithMiddleware = async (
|
|
|
242
243
|
matchedRoute: {
|
|
243
244
|
matchedPath: any
|
|
244
245
|
params: any
|
|
245
|
-
route:
|
|
246
|
+
route: CoreHTTPFunctionWiring<any, any, any>
|
|
246
247
|
middleware: any[]
|
|
247
|
-
meta:
|
|
248
|
+
meta: HTTPWiringMeta
|
|
248
249
|
},
|
|
249
250
|
http: PikkuHTTP,
|
|
250
251
|
options: {
|
|
@@ -290,7 +291,7 @@ const executeRouteWithMiddleware = async (
|
|
|
290
291
|
throw new MissingSessionError()
|
|
291
292
|
}
|
|
292
293
|
|
|
293
|
-
const data = http.request!.data()
|
|
294
|
+
const data = await http.request!.data()
|
|
294
295
|
|
|
295
296
|
const getAllServices = async () => {
|
|
296
297
|
let channel: PikkuChannel<unknown, unknown> | undefined
|
|
@@ -382,12 +383,12 @@ const executeRouteWithMiddleware = async (
|
|
|
382
383
|
* @template In Expected input data type.
|
|
383
384
|
* @template Out Expected output data type.
|
|
384
385
|
* @param {Request} request - The native Fetch API Request object.
|
|
385
|
-
* @param {
|
|
386
|
+
* @param {RunHTTPWiringOptions & RunHTTPWiringParams} params - Additional options including services and session management.
|
|
386
387
|
* @returns {Promise<Response>} A promise that resolves to a Fetch API Response object.
|
|
387
388
|
*/
|
|
388
389
|
export const fetch = async <In, Out>(
|
|
389
390
|
request: Request,
|
|
390
|
-
params:
|
|
391
|
+
params: RunHTTPWiringOptions & RunHTTPWiringParams
|
|
391
392
|
): Promise<Response> => {
|
|
392
393
|
const pikkuResponse = new PikkuFetchHTTPResponse()
|
|
393
394
|
await fetchData<In, Out>(request, pikkuResponse, params)
|
|
@@ -403,12 +404,12 @@ export const fetch = async <In, Out>(
|
|
|
403
404
|
* @template In Expected input data type.
|
|
404
405
|
* @template Out Expected output data type.
|
|
405
406
|
* @param {Request | PikkuHTTPRequest} request - The request object.
|
|
406
|
-
* @param {
|
|
407
|
+
* @param {RunHTTPWiringOptions & RunHTTPWiringParams} params - Execution options including services and session configuration.
|
|
407
408
|
* @returns {Promise<PikkuFetchHTTPResponse>} A promise that resolves to a PikkuFetchHTTPResponse object.
|
|
408
409
|
*/
|
|
409
410
|
export const pikkuFetch = async <In, Out>(
|
|
410
411
|
request: Request | PikkuHTTPRequest,
|
|
411
|
-
params:
|
|
412
|
+
params: RunHTTPWiringOptions & RunHTTPWiringParams
|
|
412
413
|
): Promise<PikkuFetchHTTPResponse> => {
|
|
413
414
|
const pikkuResponse = new PikkuFetchHTTPResponse()
|
|
414
415
|
await fetchData<In, Out>(request, pikkuResponse, params)
|
|
@@ -430,7 +431,7 @@ export const pikkuFetch = async <In, Out>(
|
|
|
430
431
|
* @template Out Expected output data type.
|
|
431
432
|
* @param {Request | PikkuHTTPRequest} request - The incoming HTTP request.
|
|
432
433
|
* @param {PikkuHTTPResponse} response - The response object to be populated.
|
|
433
|
-
* @param {
|
|
434
|
+
* @param {RunHTTPWiringOptions & RunHTTPWiringParams} options - Options such as singleton services, session handling, and error configuration.
|
|
434
435
|
* @returns {Promise<Out | void>} The output from the route handler or void if an error occurred.
|
|
435
436
|
*/
|
|
436
437
|
export const fetchData = async <In, Out>(
|
|
@@ -446,7 +447,7 @@ export const fetchData = async <In, Out>(
|
|
|
446
447
|
bubbleErrors = false,
|
|
447
448
|
generateRequestId,
|
|
448
449
|
ignoreMiddleware = false,
|
|
449
|
-
}:
|
|
450
|
+
}: RunHTTPWiringOptions & RunHTTPWiringParams
|
|
450
451
|
): Promise<Out | void> => {
|
|
451
452
|
const requestId =
|
|
452
453
|
(request as any).getHeader?.('x-request-id') ||
|