@pikku/core 0.9.11 → 0.10.0
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 +14 -0
- package/dist/errors/errors.d.ts +2 -0
- package/dist/errors/errors.js +6 -0
- package/dist/function/function-runner.d.ts +15 -9
- package/dist/function/function-runner.js +55 -37
- package/dist/function/functions.types.d.ts +67 -1
- package/dist/function/functions.types.js +43 -1
- package/dist/index.d.ts +2 -6
- package/dist/index.js +2 -6
- package/dist/middleware/auth-apikey.d.ts +19 -11
- package/dist/middleware/auth-apikey.js +33 -33
- package/dist/middleware/auth-bearer.d.ts +34 -7
- package/dist/middleware/auth-bearer.js +53 -36
- package/dist/middleware/auth-cookie.d.ts +30 -12
- package/dist/middleware/auth-cookie.js +51 -43
- package/dist/middleware/timeout.d.ts +6 -2
- package/dist/middleware/timeout.js +7 -9
- package/dist/middleware-runner.d.ts +46 -43
- package/dist/middleware-runner.js +100 -69
- package/dist/permissions.d.ts +82 -20
- package/dist/permissions.js +176 -62
- package/dist/pikku-state.d.ts +46 -1
- package/dist/pikku-state.js +16 -1
- package/dist/services/content-service.d.ts +2 -3
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.js +0 -1
- package/dist/services/local-content.d.ts +2 -4
- package/dist/types/core.types.d.ts +110 -4
- package/dist/types/core.types.js +44 -1
- package/dist/utils.d.ts +1 -1
- package/dist/wirings/channel/channel-handler.d.ts +2 -2
- package/dist/wirings/channel/channel-handler.js +16 -12
- package/dist/wirings/channel/channel-runner.d.ts +2 -2
- package/dist/wirings/channel/channel-runner.js +6 -24
- package/dist/wirings/channel/channel.types.d.ts +15 -14
- package/dist/wirings/channel/local/local-channel-runner.js +12 -12
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +7 -8
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +12 -0
- package/dist/wirings/cli/channel/cli-channel-runner.js +83 -0
- package/dist/wirings/cli/channel/index.d.ts +1 -0
- package/dist/wirings/cli/channel/index.js +1 -0
- package/dist/wirings/cli/cli-runner.d.ts +42 -0
- package/dist/wirings/cli/cli-runner.js +352 -0
- package/dist/wirings/cli/cli.types.d.ts +204 -0
- package/dist/wirings/cli/cli.types.js +1 -0
- package/dist/wirings/cli/command-parser.d.ts +19 -0
- package/dist/wirings/cli/command-parser.js +403 -0
- package/dist/wirings/cli/index.d.ts +5 -0
- package/dist/wirings/cli/index.js +5 -0
- package/dist/wirings/http/http-runner.d.ts +59 -10
- package/dist/wirings/http/http-runner.js +138 -131
- package/dist/wirings/http/http.types.d.ts +11 -10
- package/dist/wirings/http/index.d.ts +1 -1
- package/dist/wirings/http/index.js +1 -1
- package/dist/wirings/http/pikku-fetch-http-response.js +3 -1
- package/dist/wirings/http/routers/http-router.d.ts +0 -2
- package/dist/wirings/http/routers/path-to-regex.d.ts +1 -1
- package/dist/wirings/http/routers/path-to-regex.js +5 -34
- package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +1 -1
- package/dist/wirings/mcp/mcp-runner.d.ts +4 -5
- package/dist/wirings/mcp/mcp-runner.js +32 -34
- package/dist/wirings/mcp/mcp.types.d.ts +38 -14
- package/dist/wirings/queue/queue-runner.d.ts +2 -2
- package/dist/wirings/queue/queue-runner.js +25 -27
- package/dist/wirings/queue/queue.types.d.ts +6 -5
- package/dist/wirings/rpc/index.d.ts +1 -1
- package/dist/wirings/rpc/index.js +1 -1
- package/dist/wirings/rpc/rpc-runner.d.ts +6 -18
- package/dist/wirings/rpc/rpc-runner.js +13 -8
- package/dist/wirings/scheduler/scheduler-runner.d.ts +2 -2
- package/dist/wirings/scheduler/scheduler-runner.js +38 -35
- package/dist/wirings/scheduler/scheduler.types.d.ts +5 -4
- package/package.json +9 -7
- package/src/errors/errors.ts +6 -0
- package/src/factory-functions.test.ts +60 -1
- package/src/function/function-runner.test.ts +81 -26
- package/src/function/function-runner.ts +89 -57
- package/src/function/functions.types.ts +85 -2
- package/src/index.ts +6 -19
- package/src/middleware/auth-apikey.ts +42 -57
- package/src/middleware/auth-bearer.ts +66 -49
- package/src/middleware/auth-cookie.ts +63 -82
- package/src/middleware/timeout.ts +10 -14
- package/src/middleware-runner.test.ts +24 -16
- package/src/middleware-runner.ts +115 -87
- package/src/permissions.test.ts +26 -27
- package/src/permissions.ts +216 -104
- package/src/pikku-state.ts +79 -2
- package/src/services/content-service.ts +5 -4
- package/src/services/index.ts +0 -1
- package/src/services/local-content.ts +9 -4
- package/src/types/core.types.ts +143 -5
- package/src/utils.ts +1 -1
- package/src/wirings/channel/channel-handler.ts +18 -21
- package/src/wirings/channel/channel-runner.ts +19 -32
- package/src/wirings/channel/channel.types.ts +29 -16
- package/src/wirings/channel/local/local-channel-runner.ts +25 -15
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +15 -17
- package/src/wirings/cli/channel/cli-channel-runner.ts +123 -0
- package/src/wirings/cli/channel/index.ts +1 -0
- package/src/wirings/cli/cli-runner.test.ts +403 -0
- package/src/wirings/cli/cli-runner.ts +539 -0
- package/src/wirings/cli/cli.types.ts +350 -0
- package/src/wirings/cli/command-parser.test.ts +445 -0
- package/src/wirings/cli/command-parser.ts +504 -0
- package/src/wirings/cli/index.ts +13 -0
- package/src/wirings/http/http-runner.test.ts +8 -7
- package/src/wirings/http/http-runner.ts +165 -158
- package/src/wirings/http/http.types.ts +58 -11
- package/src/wirings/http/index.ts +7 -1
- package/src/wirings/http/pikku-fetch-http-response.ts +3 -1
- package/src/wirings/http/routers/http-router.ts +0 -2
- package/src/wirings/http/routers/path-to-regex.test.ts +4 -5
- package/src/wirings/http/routers/path-to-regex.ts +6 -43
- package/src/wirings/mcp/mcp-endpoint-registry.ts +1 -1
- package/src/wirings/mcp/mcp-runner.ts +58 -55
- package/src/wirings/mcp/mcp.types.ts +65 -14
- package/src/wirings/queue/queue-runner.ts +44 -47
- package/src/wirings/queue/queue.types.ts +10 -6
- package/src/wirings/rpc/index.ts +1 -1
- package/src/wirings/rpc/rpc-runner.ts +27 -9
- package/src/wirings/scheduler/scheduler-runner.ts +58 -56
- package/src/wirings/scheduler/scheduler.types.ts +10 -3
- package/tsconfig.tsbuildinfo +1 -1
package/src/types/core.types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Logger, LogLevel } from '../services/logger.js'
|
|
2
2
|
import { VariablesService } from '../services/variables-service.js'
|
|
3
3
|
import { SchemaService } from '../services/schema-service.js'
|
|
4
|
+
import { JWTService } from '../services/jwt-service.js'
|
|
4
5
|
import { PikkuHTTP } from '../wirings/http/http.types.js'
|
|
5
6
|
import { UserSessionService } from '../services/user-session-service.js'
|
|
6
7
|
import { PikkuChannel } from '../wirings/channel/channel.types.js'
|
|
@@ -8,6 +9,7 @@ import { PikkuRPC } from '../wirings/rpc/rpc-types.js'
|
|
|
8
9
|
import { PikkuMCP } from '../wirings/mcp/mcp.types.js'
|
|
9
10
|
import { PikkuScheduledTask } from '../wirings/scheduler/scheduler.types.js'
|
|
10
11
|
import { PikkuQueue } from '../wirings/queue/queue.types.js'
|
|
12
|
+
import { PikkuCLI } from '../wirings/cli/cli.types.js'
|
|
11
13
|
|
|
12
14
|
export enum PikkuWiringTypes {
|
|
13
15
|
http = 'http',
|
|
@@ -16,6 +18,7 @@ export enum PikkuWiringTypes {
|
|
|
16
18
|
rpc = 'rpc',
|
|
17
19
|
queue = 'queue',
|
|
18
20
|
mcp = 'mcp',
|
|
21
|
+
cli = 'cli',
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
export interface FunctionServicesMeta {
|
|
@@ -23,6 +26,48 @@ export interface FunctionServicesMeta {
|
|
|
23
26
|
services: string[]
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Metadata for middleware at any level
|
|
31
|
+
* - type: 'http' = HTTP route middleware group (references httpGroup in pikkuState)
|
|
32
|
+
* - type: 'tag' = Tag-based middleware group (references tagGroup in pikkuState)
|
|
33
|
+
* - type: 'wire' = Wire-level individual middleware
|
|
34
|
+
*/
|
|
35
|
+
export type MiddlewareMetadata =
|
|
36
|
+
| {
|
|
37
|
+
type: 'http'
|
|
38
|
+
route: string // Route pattern (e.g., '*' for all, '/api/*' for specific)
|
|
39
|
+
}
|
|
40
|
+
| {
|
|
41
|
+
type: 'tag'
|
|
42
|
+
tag: string // Tag name
|
|
43
|
+
}
|
|
44
|
+
| {
|
|
45
|
+
type: 'wire'
|
|
46
|
+
name: string
|
|
47
|
+
inline?: boolean // true if inline middleware
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Metadata for permissions at any level
|
|
52
|
+
* - type: 'http' = HTTP route permission group (references httpGroup in pikkuState)
|
|
53
|
+
* - type: 'tag' = Tag-based permission group (references tagGroup in pikkuState)
|
|
54
|
+
* - type: 'wire' = Wire-level individual permission
|
|
55
|
+
*/
|
|
56
|
+
export type PermissionMetadata =
|
|
57
|
+
| {
|
|
58
|
+
type: 'http'
|
|
59
|
+
route: string // Route pattern (e.g., '*' for all, '/api/*' for specific)
|
|
60
|
+
}
|
|
61
|
+
| {
|
|
62
|
+
type: 'tag'
|
|
63
|
+
tag: string // Tag name
|
|
64
|
+
}
|
|
65
|
+
| {
|
|
66
|
+
type: 'wire'
|
|
67
|
+
name: string
|
|
68
|
+
inline?: boolean // true if inline permission
|
|
69
|
+
}
|
|
70
|
+
|
|
26
71
|
export type FunctionRuntimeMeta = {
|
|
27
72
|
pikkuFuncName: string
|
|
28
73
|
inputSchemaName: string | null
|
|
@@ -39,6 +84,8 @@ export type FunctionMeta = FunctionRuntimeMeta &
|
|
|
39
84
|
tags: string[]
|
|
40
85
|
docs: PikkuDocs
|
|
41
86
|
isDirectFunction: boolean // true if it's pikkuFunc(fn), false if it's pikkuFunc({ func: fn })
|
|
87
|
+
middleware: MiddlewareMetadata[] // Function-level middleware
|
|
88
|
+
permissions: PermissionMetadata[] // Function-level permissions
|
|
42
89
|
}>
|
|
43
90
|
|
|
44
91
|
export type FunctionsRuntimeMeta = Record<string, FunctionRuntimeMeta>
|
|
@@ -103,6 +150,8 @@ export interface CoreUserSession {}
|
|
|
103
150
|
export interface CoreSingletonServices<Config extends CoreConfig = CoreConfig> {
|
|
104
151
|
/** The schema library used to validate data */
|
|
105
152
|
schema?: SchemaService
|
|
153
|
+
/** The JWT service used to encode and decode tokens */
|
|
154
|
+
jwt?: JWTService
|
|
106
155
|
/** The core configuration for the application. */
|
|
107
156
|
config: Config
|
|
108
157
|
/** The logger used by the application. */
|
|
@@ -121,6 +170,7 @@ export type PikkuInteraction<In = unknown, Out = unknown> = Partial<{
|
|
|
121
170
|
channel: PikkuChannel<unknown, Out>
|
|
122
171
|
scheduledTask: PikkuScheduledTask
|
|
123
172
|
queue: PikkuQueue
|
|
173
|
+
cli: PikkuCLI
|
|
124
174
|
}>
|
|
125
175
|
|
|
126
176
|
/**
|
|
@@ -137,16 +187,103 @@ export type CorePikkuMiddleware<
|
|
|
137
187
|
next: () => Promise<void>
|
|
138
188
|
) => Promise<void>
|
|
139
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Configuration object for creating middleware with metadata
|
|
192
|
+
*
|
|
193
|
+
* @template SingletonServices - The singleton services type
|
|
194
|
+
* @template UserSession - The user session type
|
|
195
|
+
*/
|
|
196
|
+
export type CorePikkuMiddlewareConfig<
|
|
197
|
+
SingletonServices extends CoreSingletonServices = CoreSingletonServices,
|
|
198
|
+
UserSession extends CoreUserSession = CoreUserSession,
|
|
199
|
+
> = {
|
|
200
|
+
/** The middleware function */
|
|
201
|
+
func: CorePikkuMiddleware<SingletonServices, UserSession>
|
|
202
|
+
/** Optional human-readable name for the middleware */
|
|
203
|
+
name?: string
|
|
204
|
+
/** Optional description of what the middleware does */
|
|
205
|
+
description?: string
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* A factory function that takes input and returns middleware
|
|
210
|
+
* Used when middleware needs configuration/input parameters
|
|
211
|
+
*/
|
|
212
|
+
export type CorePikkuMiddlewareFactory<
|
|
213
|
+
In = any,
|
|
214
|
+
SingletonServices extends CoreSingletonServices = CoreSingletonServices,
|
|
215
|
+
UserSession extends CoreUserSession = CoreUserSession,
|
|
216
|
+
> = (input: In) => CorePikkuMiddleware<SingletonServices, UserSession>
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* A group of middleware (combination of regular middleware and factories)
|
|
220
|
+
* Used with addMiddleware() and addHTTPMiddleware() to group related middleware together
|
|
221
|
+
*/
|
|
222
|
+
export type CorePikkuMiddlewareGroup<
|
|
223
|
+
SingletonServices extends CoreSingletonServices = CoreSingletonServices,
|
|
224
|
+
UserSession extends CoreUserSession = CoreUserSession,
|
|
225
|
+
> = Array<
|
|
226
|
+
| CorePikkuMiddleware<SingletonServices, UserSession>
|
|
227
|
+
| CorePikkuMiddlewareFactory<any, SingletonServices, UserSession>
|
|
228
|
+
>
|
|
229
|
+
|
|
140
230
|
/**
|
|
141
231
|
* Factory function for creating middleware with tree-shaking support
|
|
232
|
+
* Supports both direct function and configuration object syntax
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* // Direct function syntax
|
|
237
|
+
* export const logMiddleware = pikkuMiddleware(
|
|
238
|
+
* async ({ logger }, _interaction, next) => {
|
|
239
|
+
* logger.info('Request started')
|
|
240
|
+
* await next()
|
|
241
|
+
* }
|
|
242
|
+
* )
|
|
243
|
+
*
|
|
244
|
+
* // Configuration object syntax with metadata
|
|
245
|
+
* export const logMiddleware = pikkuMiddleware({
|
|
246
|
+
* name: 'Request Logger',
|
|
247
|
+
* description: 'Logs request information',
|
|
248
|
+
* func: async ({ logger }, _interaction, next) => {
|
|
249
|
+
* logger.info('Request started')
|
|
250
|
+
* await next()
|
|
251
|
+
* }
|
|
252
|
+
* })
|
|
253
|
+
* ```
|
|
142
254
|
*/
|
|
143
255
|
export const pikkuMiddleware = <
|
|
144
256
|
SingletonServices extends CoreSingletonServices = CoreSingletonServices,
|
|
145
257
|
UserSession extends CoreUserSession = CoreUserSession,
|
|
146
258
|
>(
|
|
147
|
-
middleware:
|
|
259
|
+
middleware:
|
|
260
|
+
| CorePikkuMiddleware<SingletonServices, UserSession>
|
|
261
|
+
| CorePikkuMiddlewareConfig<SingletonServices, UserSession>
|
|
148
262
|
): CorePikkuMiddleware<SingletonServices, UserSession> => {
|
|
149
|
-
return middleware
|
|
263
|
+
return typeof middleware === 'function' ? middleware : middleware.func
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Factory function for creating middleware factories
|
|
268
|
+
* Use this when your middleware needs configuration/input parameters
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* export const logMiddleware = pikkuMiddlewareFactory<LogOptions>(({
|
|
273
|
+
* message,
|
|
274
|
+
* level = 'info'
|
|
275
|
+
* }) => {
|
|
276
|
+
* return pikkuMiddleware(async ({ logger }, _interaction, next) => {
|
|
277
|
+
* logger[level](message)
|
|
278
|
+
* await next()
|
|
279
|
+
* })
|
|
280
|
+
* })
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
export const pikkuMiddlewareFactory = <In = any>(
|
|
284
|
+
factory: CorePikkuMiddlewareFactory<In>
|
|
285
|
+
): CorePikkuMiddlewareFactory<In> => {
|
|
286
|
+
return factory
|
|
150
287
|
}
|
|
151
288
|
|
|
152
289
|
/**
|
|
@@ -193,9 +330,10 @@ export type CreateSessionServices<
|
|
|
193
330
|
/**
|
|
194
331
|
* Defines a function type for creating config.
|
|
195
332
|
*/
|
|
196
|
-
export type CreateConfig<
|
|
197
|
-
|
|
198
|
-
|
|
333
|
+
export type CreateConfig<
|
|
334
|
+
Config extends CoreConfig,
|
|
335
|
+
RemainingArgs extends any[] = unknown[],
|
|
336
|
+
> = (variables?: VariablesService, ...args: RemainingArgs) => Promise<Config>
|
|
199
337
|
|
|
200
338
|
/**
|
|
201
339
|
* Represents the documentation for a route, including summary, description, tags, and errors.
|
package/src/utils.ts
CHANGED
|
@@ -41,7 +41,7 @@ export const isSerializable = (data: any): boolean => {
|
|
|
41
41
|
|
|
42
42
|
const EMPTY_ARRAY = Object.freeze([])
|
|
43
43
|
|
|
44
|
-
export const freezeDedupe = <T
|
|
44
|
+
export const freezeDedupe = <T>(
|
|
45
45
|
arr?: readonly T[] | T[] | undefined
|
|
46
46
|
): readonly T[] => {
|
|
47
47
|
if (!arr || arr.length === 0) return EMPTY_ARRAY
|
|
@@ -61,7 +61,6 @@ const validateAuth = (
|
|
|
61
61
|
|
|
62
62
|
export const processMessageHandlers = (
|
|
63
63
|
services: CoreServices,
|
|
64
|
-
session: CoreUserSession | undefined,
|
|
65
64
|
channelConfig: CoreChannel<any, any>,
|
|
66
65
|
channelHandler: PikkuChannelHandler
|
|
67
66
|
) => {
|
|
@@ -71,7 +70,6 @@ export const processMessageHandlers = (
|
|
|
71
70
|
const processMessage = async (
|
|
72
71
|
data: JSONValue,
|
|
73
72
|
onMessage: any,
|
|
74
|
-
session: CoreUserSession | undefined,
|
|
75
73
|
routingProperty?: string,
|
|
76
74
|
routerValue?: string
|
|
77
75
|
): Promise<unknown> => {
|
|
@@ -87,16 +85,16 @@ export const processMessageHandlers = (
|
|
|
87
85
|
return
|
|
88
86
|
}
|
|
89
87
|
|
|
90
|
-
const {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
88
|
+
const {
|
|
89
|
+
pikkuFuncName,
|
|
90
|
+
middleware: inheritedMiddleware,
|
|
91
|
+
permissions: inheritedPermissions,
|
|
92
|
+
} = getRouteMeta(channelConfig.name, routingProperty, routerValue)
|
|
95
93
|
|
|
96
|
-
const
|
|
97
|
-
typeof onMessage === 'function' ?
|
|
94
|
+
const wirePermissions =
|
|
95
|
+
typeof onMessage === 'function' ? undefined : onMessage.permissions
|
|
98
96
|
|
|
99
|
-
const
|
|
97
|
+
const wireMiddleware =
|
|
100
98
|
typeof onMessage === 'function' ? [] : onMessage.middleware
|
|
101
99
|
|
|
102
100
|
return await runPikkuFunc(
|
|
@@ -104,15 +102,19 @@ export const processMessageHandlers = (
|
|
|
104
102
|
channelConfig.name,
|
|
105
103
|
pikkuFuncName,
|
|
106
104
|
{
|
|
105
|
+
singletonServices: services,
|
|
107
106
|
getAllServices: () => ({
|
|
108
107
|
...services,
|
|
109
108
|
channel: channelHandler.getChannel(),
|
|
110
109
|
}),
|
|
111
|
-
data,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
data: () => data,
|
|
111
|
+
userSession: services.userSession,
|
|
112
|
+
inheritedMiddleware,
|
|
113
|
+
wireMiddleware,
|
|
114
|
+
inheritedPermissions,
|
|
115
|
+
wirePermissions,
|
|
115
116
|
tags: channelConfig.tags,
|
|
117
|
+
interaction: { channel: channelHandler.getChannel() },
|
|
116
118
|
}
|
|
117
119
|
)
|
|
118
120
|
}
|
|
@@ -133,7 +135,6 @@ export const processMessageHandlers = (
|
|
|
133
135
|
result = await processMessage(
|
|
134
136
|
messageData,
|
|
135
137
|
routes[routerValue],
|
|
136
|
-
session,
|
|
137
138
|
routingProperty,
|
|
138
139
|
routerValue
|
|
139
140
|
)
|
|
@@ -144,11 +145,7 @@ export const processMessageHandlers = (
|
|
|
144
145
|
// Default handler if no routes matched but json data was parsed
|
|
145
146
|
if (!processed && channelConfig.onMessage) {
|
|
146
147
|
processed = true
|
|
147
|
-
result = await processMessage(
|
|
148
|
-
messageData,
|
|
149
|
-
channelConfig.onMessage,
|
|
150
|
-
session
|
|
151
|
-
)
|
|
148
|
+
result = await processMessage(messageData, channelConfig.onMessage)
|
|
152
149
|
}
|
|
153
150
|
} catch (error) {
|
|
154
151
|
// Most likely a json error.. ignore
|
|
@@ -158,7 +155,7 @@ export const processMessageHandlers = (
|
|
|
158
155
|
// Default handler if no routes matched and json data wasn't parsed
|
|
159
156
|
if (!processed && channelConfig.onMessage) {
|
|
160
157
|
processed = true
|
|
161
|
-
result = await processMessage(rawData, channelConfig.onMessage
|
|
158
|
+
result = await processMessage(rawData, channelConfig.onMessage)
|
|
162
159
|
}
|
|
163
160
|
|
|
164
161
|
if (!processed) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NotFoundError } from '../../errors/errors.js'
|
|
2
2
|
import { addFunction } from '../../function/function-runner.js'
|
|
3
|
+
import { CorePikkuPermission } from '../../function/functions.types.js'
|
|
3
4
|
import { pikkuState } from '../../pikku-state.js'
|
|
4
5
|
import { coerceTopLevelDataFromSchema, validateSchema } from '../../schema.js'
|
|
5
6
|
import { UserSessionService } from '../../services/user-session-service.js'
|
|
@@ -19,11 +20,17 @@ import {
|
|
|
19
20
|
export const wireChannel = <
|
|
20
21
|
In,
|
|
21
22
|
Channel extends string,
|
|
23
|
+
PikkuPermission extends CorePikkuPermission<In>,
|
|
24
|
+
PikkuMiddleware extends CorePikkuMiddleware,
|
|
22
25
|
ChannelFunction,
|
|
23
|
-
ChannelFunctionSessionless,
|
|
24
|
-
PikkuPermission,
|
|
25
26
|
>(
|
|
26
|
-
channel: CoreChannel<
|
|
27
|
+
channel: CoreChannel<
|
|
28
|
+
In,
|
|
29
|
+
Channel,
|
|
30
|
+
PikkuPermission,
|
|
31
|
+
PikkuMiddleware,
|
|
32
|
+
ChannelFunction
|
|
33
|
+
>
|
|
27
34
|
) => {
|
|
28
35
|
// Get the channel metadata
|
|
29
36
|
const channelsMeta = pikkuState('channel', 'meta')
|
|
@@ -36,27 +43,20 @@ export const wireChannel = <
|
|
|
36
43
|
|
|
37
44
|
// Register onConnect function if provided
|
|
38
45
|
if (channel.onConnect && channelMeta.connect) {
|
|
39
|
-
addFunction(channelMeta.connect.pikkuFuncName,
|
|
40
|
-
func: channel.onConnect as any,
|
|
41
|
-
})
|
|
46
|
+
addFunction(channelMeta.connect.pikkuFuncName, channel.onConnect as any)
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
// Register onDisconnect function if provided
|
|
45
50
|
if (channel.onDisconnect && channelMeta.disconnect) {
|
|
46
|
-
addFunction(
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
addFunction(
|
|
52
|
+
channelMeta.disconnect.pikkuFuncName,
|
|
53
|
+
channel.onDisconnect as any
|
|
54
|
+
)
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
// Register onMessage function if provided
|
|
52
58
|
if (channel.onMessage && channelMeta.message?.pikkuFuncName) {
|
|
53
|
-
|
|
54
|
-
typeof channel.onMessage === 'function'
|
|
55
|
-
? channel.onMessage
|
|
56
|
-
: channel.onMessage.func
|
|
57
|
-
addFunction(channelMeta.message.pikkuFuncName, {
|
|
58
|
-
func: messageFunc,
|
|
59
|
-
})
|
|
59
|
+
addFunction(channelMeta.message.pikkuFuncName, channel.onMessage as any)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// Register functions in onMessageWiring
|
|
@@ -71,18 +71,8 @@ export const wireChannel = <
|
|
|
71
71
|
const wiringMeta = channelWirings[wiringKey]
|
|
72
72
|
if (!wiringMeta) return
|
|
73
73
|
|
|
74
|
-
// Extract the function from the handler
|
|
75
|
-
const wiringFunc =
|
|
76
|
-
typeof handler === 'function'
|
|
77
|
-
? { func: handler }
|
|
78
|
-
: {
|
|
79
|
-
func: handler.func,
|
|
80
|
-
auth: handler.auth,
|
|
81
|
-
permissions: handler.permissions,
|
|
82
|
-
}
|
|
83
|
-
|
|
84
74
|
// Register the function using the pikku name from metadata
|
|
85
|
-
addFunction(wiringMeta.pikkuFuncName,
|
|
75
|
+
addFunction(wiringMeta.pikkuFuncName, handler as any)
|
|
86
76
|
})
|
|
87
77
|
})
|
|
88
78
|
}
|
|
@@ -117,7 +107,6 @@ const getMatchingChannelConfig = (request: string) => {
|
|
|
117
107
|
channelConfig,
|
|
118
108
|
schemaName: channelMeta.input,
|
|
119
109
|
meta: channelMeta,
|
|
120
|
-
httpMiddleware: matchedPath.middleware,
|
|
121
110
|
}
|
|
122
111
|
}
|
|
123
112
|
|
|
@@ -133,7 +122,6 @@ export const openChannel = async ({
|
|
|
133
122
|
openingData: unknown
|
|
134
123
|
channelConfig: CoreChannel<unknown, any>
|
|
135
124
|
meta: ChannelMeta
|
|
136
|
-
httpMiddleware: CorePikkuMiddleware[] | undefined
|
|
137
125
|
}> => {
|
|
138
126
|
const matchingChannel = getMatchingChannelConfig(route)
|
|
139
127
|
if (!matchingChannel) {
|
|
@@ -141,8 +129,7 @@ export const openChannel = async ({
|
|
|
141
129
|
throw new NotFoundError(`Channel not found: ${route}`)
|
|
142
130
|
}
|
|
143
131
|
|
|
144
|
-
const { params, channelConfig, schemaName, meta
|
|
145
|
-
matchingChannel
|
|
132
|
+
const { params, channelConfig, schemaName, meta } = matchingChannel
|
|
146
133
|
|
|
147
134
|
const requiresSession = channelConfig.auth !== false
|
|
148
135
|
request?.setParams(params)
|
|
@@ -165,5 +152,5 @@ export const openChannel = async ({
|
|
|
165
152
|
)
|
|
166
153
|
}
|
|
167
154
|
|
|
168
|
-
return { openingData, channelConfig, meta
|
|
155
|
+
return { openingData, channelConfig, meta }
|
|
169
156
|
}
|
|
@@ -9,9 +9,13 @@ import {
|
|
|
9
9
|
CoreSingletonServices,
|
|
10
10
|
CreateSessionServices,
|
|
11
11
|
CorePikkuMiddleware,
|
|
12
|
+
MiddlewareMetadata,
|
|
13
|
+
PermissionMetadata,
|
|
12
14
|
} from '../../types/core.types.js'
|
|
13
15
|
import {
|
|
16
|
+
CorePermissionGroup,
|
|
14
17
|
CorePikkuFunction,
|
|
18
|
+
CorePikkuFunctionConfig,
|
|
15
19
|
CorePikkuFunctionSessionless,
|
|
16
20
|
CorePikkuPermission,
|
|
17
21
|
} from '../../function/functions.types.js'
|
|
@@ -35,6 +39,8 @@ export type RunChannelParams<ChannelData> = {
|
|
|
35
39
|
export interface ChannelMessageMeta {
|
|
36
40
|
pikkuFuncName: string
|
|
37
41
|
docs?: PikkuDocs
|
|
42
|
+
middleware?: MiddlewareMetadata[]
|
|
43
|
+
permissions?: PermissionMetadata[]
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
export interface ChannelMeta {
|
|
@@ -50,6 +56,8 @@ export interface ChannelMeta {
|
|
|
50
56
|
messageWirings: Record<string, Record<string, ChannelMessageMeta>>
|
|
51
57
|
docs?: PikkuDocs
|
|
52
58
|
tags?: string[]
|
|
59
|
+
middleware?: MiddlewareMetadata[] // Pre-resolved middleware chain (tag + explicit)
|
|
60
|
+
permissions?: PermissionMetadata[] // Pre-resolved permission chain (tag + explicit)
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
export type ChannelsMeta = Record<string, ChannelMeta>
|
|
@@ -57,28 +65,32 @@ export type ChannelsMeta = Record<string, ChannelMeta>
|
|
|
57
65
|
export type CoreChannel<
|
|
58
66
|
ChannelData,
|
|
59
67
|
Channel extends string,
|
|
60
|
-
ChannelConnect =
|
|
68
|
+
ChannelConnect = CorePikkuFunctionConfig<
|
|
61
69
|
| CorePikkuFunction<void, unknown, ChannelData>
|
|
62
70
|
| CorePikkuFunctionSessionless<void, unknown, ChannelData>,
|
|
63
|
-
|
|
71
|
+
CorePikkuPermission<void>,
|
|
72
|
+
CorePikkuMiddleware
|
|
73
|
+
>,
|
|
74
|
+
ChannelDisconnect = CorePikkuFunctionConfig<
|
|
64
75
|
| CorePikkuFunction<void, void, ChannelData>
|
|
65
76
|
| CorePikkuFunctionSessionless<void, void, ChannelData>,
|
|
66
|
-
|
|
77
|
+
CorePikkuPermission<void>,
|
|
78
|
+
CorePikkuMiddleware
|
|
79
|
+
>,
|
|
80
|
+
ChannelFunctionMessage = CorePikkuFunctionConfig<
|
|
67
81
|
| CorePikkuFunction<unknown, unknown, ChannelData>
|
|
68
82
|
| CorePikkuFunctionSessionless<unknown, unknown, ChannelData>,
|
|
83
|
+
CorePikkuPermission<unknown>,
|
|
84
|
+
CorePikkuMiddleware
|
|
85
|
+
>,
|
|
69
86
|
PikkuPermission = CorePikkuPermission<ChannelData>,
|
|
87
|
+
PikkuMiddleware = CorePikkuMiddleware,
|
|
70
88
|
> = {
|
|
71
89
|
name: string
|
|
72
90
|
route: Channel
|
|
73
91
|
onConnect?: ChannelConnect
|
|
74
92
|
onDisconnect?: ChannelDisconnect
|
|
75
|
-
onMessage?:
|
|
76
|
-
| {
|
|
77
|
-
func: ChannelFunctionMessage
|
|
78
|
-
permissions?: Record<string, PikkuPermission[] | PikkuPermission>
|
|
79
|
-
auth?: boolean
|
|
80
|
-
}
|
|
81
|
-
| ChannelFunctionMessage
|
|
93
|
+
onMessage?: ChannelFunctionMessage
|
|
82
94
|
onMessageWiring?: Record<
|
|
83
95
|
string,
|
|
84
96
|
Record<
|
|
@@ -86,13 +98,14 @@ export type CoreChannel<
|
|
|
86
98
|
| ChannelFunctionMessage
|
|
87
99
|
| {
|
|
88
100
|
func: ChannelFunctionMessage
|
|
89
|
-
permissions?:
|
|
101
|
+
permissions?: CorePermissionGroup<PikkuPermission>
|
|
90
102
|
auth?: boolean
|
|
103
|
+
middleware?: PikkuMiddleware[]
|
|
91
104
|
}
|
|
92
105
|
>
|
|
93
106
|
>
|
|
94
|
-
middleware?:
|
|
95
|
-
permissions?:
|
|
107
|
+
middleware?: PikkuMiddleware[]
|
|
108
|
+
permissions?: CorePermissionGroup<PikkuPermission>
|
|
96
109
|
auth?: boolean
|
|
97
110
|
docs?: Partial<{
|
|
98
111
|
description: string
|
|
@@ -103,16 +116,16 @@ export type CoreChannel<
|
|
|
103
116
|
tags?: string[]
|
|
104
117
|
}
|
|
105
118
|
|
|
106
|
-
export interface PikkuChannel<OpeningData, Out> {
|
|
119
|
+
export interface PikkuChannel<OpeningData, out Out> {
|
|
107
120
|
// The channel identifier
|
|
108
121
|
channelId: string
|
|
109
122
|
// The data the channel was created with. This could be query parameters
|
|
110
123
|
// or parameters in the url.
|
|
111
124
|
openingData: OpeningData
|
|
112
125
|
// The data to send. This will fail is the stream has been closed.
|
|
113
|
-
send
|
|
126
|
+
send(data: Out, isBinary?: boolean): Promise<void> | void
|
|
114
127
|
// This will close the channel.
|
|
115
|
-
close
|
|
128
|
+
close(): Promise<void> | void
|
|
116
129
|
// The current state of the channel
|
|
117
130
|
state: 'initial' | 'open' | 'closed'
|
|
118
131
|
}
|
|
@@ -8,7 +8,11 @@ import {
|
|
|
8
8
|
RunChannelParams,
|
|
9
9
|
} from '../channel.types.js'
|
|
10
10
|
import { PikkuLocalChannelHandler } from './local-channel-handler.js'
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
PikkuInteraction,
|
|
13
|
+
PikkuWiringTypes,
|
|
14
|
+
SessionServices,
|
|
15
|
+
} from '../../../types/core.types.js'
|
|
12
16
|
import { handleHTTPError } from '../../../handle-error.js'
|
|
13
17
|
import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js'
|
|
14
18
|
import { PikkuUserSessionService } from '../../../services/user-session-service.js'
|
|
@@ -42,9 +46,9 @@ export const runLocalChannel = async ({
|
|
|
42
46
|
route = http?.request?.path()
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
let openingData, channelConfig, meta
|
|
49
|
+
let openingData, channelConfig, meta
|
|
46
50
|
try {
|
|
47
|
-
;({ openingData, channelConfig, meta
|
|
51
|
+
;({ openingData, channelConfig, meta } = await openChannel({
|
|
48
52
|
channelId,
|
|
49
53
|
createSessionServices,
|
|
50
54
|
respondWith404,
|
|
@@ -86,17 +90,24 @@ export const runLocalChannel = async ({
|
|
|
86
90
|
)
|
|
87
91
|
}
|
|
88
92
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
const getAllServices = (channel: any, requiresAuth?: boolean) =>
|
|
94
|
+
rpcService.injectRPCService(
|
|
95
|
+
{
|
|
96
|
+
...singletonServices,
|
|
97
|
+
...sessionServices,
|
|
98
|
+
userSession,
|
|
99
|
+
},
|
|
100
|
+
interaction,
|
|
101
|
+
requiresAuth
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const interaction: PikkuInteraction = { channel }
|
|
94
105
|
|
|
95
106
|
channelHandler.registerOnOpen(() => {
|
|
96
107
|
if (channelConfig.onConnect && meta.connect) {
|
|
97
108
|
runPikkuFuncDirectly(
|
|
98
109
|
meta.connect.pikkuFuncName,
|
|
99
|
-
|
|
110
|
+
getAllServices(channel, false),
|
|
100
111
|
openingData
|
|
101
112
|
)
|
|
102
113
|
}
|
|
@@ -106,10 +117,11 @@ export const runLocalChannel = async ({
|
|
|
106
117
|
if (channelConfig.onDisconnect && meta.disconnect) {
|
|
107
118
|
runPikkuFuncDirectly(
|
|
108
119
|
meta.disconnect.pikkuFuncName,
|
|
109
|
-
|
|
120
|
+
getAllServices(channel, false),
|
|
110
121
|
openingData
|
|
111
122
|
)
|
|
112
123
|
}
|
|
124
|
+
|
|
113
125
|
if (sessionServices) {
|
|
114
126
|
await closeSessionServices(singletonServices.logger, sessionServices)
|
|
115
127
|
}
|
|
@@ -117,8 +129,7 @@ export const runLocalChannel = async ({
|
|
|
117
129
|
|
|
118
130
|
channelHandler.registerOnMessage(
|
|
119
131
|
processMessageHandlers(
|
|
120
|
-
|
|
121
|
-
session,
|
|
132
|
+
getAllServices(channel),
|
|
122
133
|
channelConfig as any,
|
|
123
134
|
channelHandler
|
|
124
135
|
)
|
|
@@ -147,9 +158,8 @@ export const runLocalChannel = async ({
|
|
|
147
158
|
},
|
|
148
159
|
{ http },
|
|
149
160
|
combineMiddleware(PikkuWiringTypes.channel, channelConfig.name, {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
httpMiddleware,
|
|
161
|
+
wireInheritedMiddleware: meta.middleware,
|
|
162
|
+
wireMiddleware: channelConfig.middleware,
|
|
153
163
|
}),
|
|
154
164
|
main
|
|
155
165
|
)
|