@pikku/core 0.9.10 → 0.9.12-next.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 +12 -0
- package/dist/function/function-runner.d.ts +13 -8
- package/dist/function/function-runner.js +49 -37
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/middleware-runner.d.ts +61 -40
- package/dist/middleware-runner.js +118 -66
- package/dist/permissions.js +1 -0
- package/dist/pikku-state.d.ts +26 -1
- package/dist/pikku-state.js +10 -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/services/local-content.js +2 -2
- package/dist/types/core.types.d.ts +51 -2
- package/dist/types/core.types.js +21 -0
- package/dist/wirings/channel/channel-handler.d.ts +2 -2
- package/dist/wirings/channel/channel-handler.js +12 -9
- package/dist/wirings/channel/channel-runner.d.ts +0 -2
- package/dist/wirings/channel/channel-runner.js +2 -3
- package/dist/wirings/channel/channel.types.d.ts +5 -3
- 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 +80 -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 +32 -0
- package/dist/wirings/cli/cli-runner.js +328 -0
- package/dist/wirings/cli/cli.types.d.ts +177 -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 +373 -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 +29 -10
- package/dist/wirings/http/http-runner.js +103 -131
- package/dist/wirings/http/http.types.d.ts +10 -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-runner.d.ts +4 -5
- package/dist/wirings/mcp/mcp-runner.js +30 -34
- package/dist/wirings/mcp/mcp.types.d.ts +11 -8
- 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 +37 -35
- package/dist/wirings/scheduler/scheduler.types.d.ts +4 -3
- package/package.json +4 -3
- package/src/function/function-runner.test.ts +73 -23
- package/src/function/function-runner.ts +74 -55
- package/src/index.ts +8 -1
- package/src/middleware-runner.test.ts +24 -16
- package/src/middleware-runner.ts +136 -83
- package/src/permissions.ts +1 -0
- package/src/pikku-state.ts +47 -2
- package/src/services/content-service.ts +5 -4
- package/src/services/index.ts +0 -1
- package/src/services/local-content.ts +11 -6
- package/src/types/core.types.ts +74 -3
- package/src/wirings/channel/channel-handler.ts +9 -13
- package/src/wirings/channel/channel-runner.ts +2 -6
- package/src/wirings/channel/channel.types.ts +5 -1
- 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 +118 -0
- package/src/wirings/cli/channel/index.ts +1 -0
- package/src/wirings/cli/cli-runner.test.ts +382 -0
- package/src/wirings/cli/cli-runner.ts +503 -0
- package/src/wirings/cli/cli.types.ts +320 -0
- package/src/wirings/cli/command-parser.test.ts +440 -0
- package/src/wirings/cli/command-parser.ts +470 -0
- package/src/wirings/cli/index.ts +12 -0
- package/src/wirings/http/http-runner.test.ts +8 -7
- package/src/wirings/http/http-runner.ts +126 -159
- package/src/wirings/http/http.types.ts +56 -11
- package/src/wirings/http/index.ts +1 -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-runner.ts +56 -55
- package/src/wirings/mcp/mcp.types.ts +23 -8
- 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 +57 -56
- package/src/wirings/scheduler/scheduler.types.ts +9 -2
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import { CoreServices, CoreUserSession, CorePikkuMiddleware, PikkuWiringTypes } from '../types/core.types.js';
|
|
2
|
-
import { CorePermissionGroup,
|
|
3
|
-
|
|
1
|
+
import { CoreServices, CoreUserSession, CorePikkuMiddleware, PikkuWiringTypes, CoreSingletonServices, PikkuInteraction, MiddlewareMetadata } from '../types/core.types.js';
|
|
2
|
+
import { CorePermissionGroup, CorePikkuFunctionConfig } from './functions.types.js';
|
|
3
|
+
import { UserSessionService } from '../services/user-session-service.js';
|
|
4
|
+
export declare const addFunction: (funcName: string, funcConfig: CorePikkuFunctionConfig<any, any>) => void;
|
|
4
5
|
export declare const runPikkuFuncDirectly: <In, Out>(funcName: string, allServices: CoreServices, data: In, session?: CoreUserSession) => Promise<Out>;
|
|
5
|
-
export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, { getAllServices, data,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, { getAllServices, singletonServices, data, userSession, auth: wiringAuth, permissions: wiringPermissions, inheritedMiddleware, wireMiddleware, coerceDataFromSchema, tags, interaction, }: {
|
|
7
|
+
singletonServices: CoreSingletonServices;
|
|
8
|
+
getAllServices: (session?: CoreUserSession) => Promise<CoreServices> | CoreServices;
|
|
9
|
+
userSession?: UserSessionService<CoreUserSession>;
|
|
10
|
+
data: () => Promise<In> | In;
|
|
11
|
+
auth?: boolean;
|
|
9
12
|
permissions?: CorePermissionGroup;
|
|
10
|
-
|
|
13
|
+
inheritedMiddleware?: MiddlewareMetadata[];
|
|
14
|
+
wireMiddleware?: CorePikkuMiddleware[];
|
|
11
15
|
coerceDataFromSchema?: boolean;
|
|
12
16
|
tags?: string[];
|
|
17
|
+
interaction: PikkuInteraction;
|
|
13
18
|
}) => Promise<Out>;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { ForbiddenError } from '../errors/errors.js';
|
|
2
1
|
import { runMiddleware, combineMiddleware } from '../middleware-runner.js';
|
|
3
2
|
import { runPermissions } from '../permissions.js';
|
|
4
3
|
import { pikkuState } from '../pikku-state.js';
|
|
5
4
|
import { coerceTopLevelDataFromSchema, validateSchema } from '../schema.js';
|
|
5
|
+
import { ForbiddenError } from '../errors/errors.js';
|
|
6
6
|
export const addFunction = (funcName, funcConfig) => {
|
|
7
|
-
if (funcConfig instanceof Function) {
|
|
8
|
-
funcConfig = { func: funcConfig };
|
|
9
|
-
}
|
|
10
7
|
pikkuState('function', 'functions').set(funcName, funcConfig);
|
|
11
8
|
};
|
|
12
9
|
export const runPikkuFuncDirectly = async (funcName, allServices, data, session) => {
|
|
@@ -16,7 +13,7 @@ export const runPikkuFuncDirectly = async (funcName, allServices, data, session)
|
|
|
16
13
|
}
|
|
17
14
|
return (await funcConfig.func(allServices, data, session));
|
|
18
15
|
};
|
|
19
|
-
export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices, data,
|
|
16
|
+
export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices, singletonServices, data, userSession, auth: wiringAuth, permissions: wiringPermissions, inheritedMiddleware, wireMiddleware, coerceDataFromSchema, tags = [], interaction, }) => {
|
|
20
17
|
const funcConfig = pikkuState('function', 'functions').get(funcName);
|
|
21
18
|
if (!funcConfig) {
|
|
22
19
|
throw new Error(`Function not found: ${funcName}`);
|
|
@@ -25,42 +22,57 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices,
|
|
|
25
22
|
if (!funcMeta) {
|
|
26
23
|
throw new Error(`Function meta not found: ${funcName}`);
|
|
27
24
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// Coerce (top level) query string parameters or date objects if specified by the schema
|
|
37
|
-
if (coerceDataFromSchema) {
|
|
38
|
-
coerceTopLevelDataFromSchema(inputSchemaName, data);
|
|
25
|
+
// Helper function to run permissions and execute the function
|
|
26
|
+
const executeFunction = async () => {
|
|
27
|
+
const session = userSession?.get();
|
|
28
|
+
if (wiringAuth === true || funcConfig.auth === true) {
|
|
29
|
+
// This means it was explicitly enabled in either wiring or function and has to be respected
|
|
30
|
+
if (!session) {
|
|
31
|
+
throw new ForbiddenError('Authentication required');
|
|
32
|
+
}
|
|
39
33
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
data
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
if (wiringAuth === undefined && funcConfig.auth === undefined) {
|
|
35
|
+
// We always default to requiring auth unless explicitly disabled
|
|
36
|
+
if (!session) {
|
|
37
|
+
throw new ForbiddenError('Authentication required');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Evaluate the data from the lazy function
|
|
41
|
+
const actualData = await data();
|
|
42
|
+
// Validate and coerce data if schema is defined
|
|
43
|
+
const inputSchemaName = funcMeta.inputSchemaName;
|
|
44
|
+
if (inputSchemaName) {
|
|
45
|
+
// Validate request data against the defined schema, if any
|
|
46
|
+
await validateSchema(singletonServices.logger, singletonServices.schema, inputSchemaName, actualData);
|
|
47
|
+
// Coerce (top level) query string parameters or date objects if specified by the schema
|
|
48
|
+
if (coerceDataFromSchema) {
|
|
49
|
+
coerceTopLevelDataFromSchema(inputSchemaName, actualData);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const allServices = await getAllServices(session);
|
|
53
|
+
await runPermissions(wireType, wireId, {
|
|
54
|
+
wiringTags: tags,
|
|
55
|
+
wiringPermissions,
|
|
56
|
+
funcTags: funcConfig.tags,
|
|
57
|
+
funcPermissions: funcConfig.permissions,
|
|
58
|
+
allServices,
|
|
59
|
+
data: actualData,
|
|
60
|
+
session,
|
|
61
|
+
});
|
|
62
|
+
return await funcConfig.func(allServices, actualData, session);
|
|
63
|
+
};
|
|
64
|
+
// Combine all middleware: inheritedMiddleware → wireMiddleware → funcMiddleware
|
|
52
65
|
const allMiddleware = combineMiddleware(wireType, wireId, {
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
wireInheritedMiddleware: inheritedMiddleware,
|
|
67
|
+
wireMiddleware,
|
|
68
|
+
funcInheritedMiddleware: funcMeta.middleware,
|
|
55
69
|
funcMiddleware: funcConfig.middleware,
|
|
56
|
-
funcTags: funcConfig.tags,
|
|
57
70
|
});
|
|
58
71
|
if (allMiddleware.length > 0) {
|
|
59
|
-
return (await runMiddleware(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}, allMiddleware, async () => await funcConfig.func(allServices, data, session)));
|
|
72
|
+
return (await runMiddleware({
|
|
73
|
+
...singletonServices,
|
|
74
|
+
userSession,
|
|
75
|
+
}, interaction, allMiddleware, executeFunction));
|
|
64
76
|
}
|
|
65
|
-
return (await
|
|
77
|
+
return (await executeFunction());
|
|
66
78
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -16,15 +16,17 @@ export * from './wirings/scheduler/index.js';
|
|
|
16
16
|
export * from './wirings/rpc/index.js';
|
|
17
17
|
export * from './wirings/queue/index.js';
|
|
18
18
|
export * from './wirings/mcp/index.js';
|
|
19
|
+
export * from './wirings/cli/index.js';
|
|
19
20
|
export * from './errors/index.js';
|
|
20
21
|
export * from './middleware/index.js';
|
|
21
22
|
export * from './utils.js';
|
|
22
23
|
export * from './time-utils.js';
|
|
23
24
|
export { pikkuState } from './pikku-state.js';
|
|
24
|
-
export { addMiddleware,
|
|
25
|
+
export { runMiddleware, registerMiddleware, getMiddlewareByName, addMiddleware, } from './middleware-runner.js';
|
|
25
26
|
export { addPermission } from './permissions.js';
|
|
26
27
|
export { wireHTTP, addHTTPMiddleware } from './wirings/http/http-runner.js';
|
|
27
28
|
export { wireChannel } from './wirings/channel/channel-runner.js';
|
|
28
29
|
export { wireScheduler } from './wirings/scheduler/scheduler-runner.js';
|
|
29
30
|
export { wireQueueWorker } from './wirings/queue/queue-runner.js';
|
|
30
31
|
export { wireMCPResource, wireMCPTool, wireMCPPrompt, runMCPResource, runMCPTool, runMCPPrompt, getMCPTools, getMCPResources, getMCPPrompts, getMCPResourcesMeta, getMCPToolsMeta, getMCPPromptsMeta, } from './wirings/mcp/mcp-runner.js';
|
|
32
|
+
export { wireCLI, runCLICommand } from './wirings/cli/cli-runner.js';
|
package/dist/index.js
CHANGED
|
@@ -16,15 +16,17 @@ export * from './wirings/scheduler/index.js';
|
|
|
16
16
|
export * from './wirings/rpc/index.js';
|
|
17
17
|
export * from './wirings/queue/index.js';
|
|
18
18
|
export * from './wirings/mcp/index.js';
|
|
19
|
+
export * from './wirings/cli/index.js';
|
|
19
20
|
export * from './errors/index.js';
|
|
20
21
|
export * from './middleware/index.js';
|
|
21
22
|
export * from './utils.js';
|
|
22
23
|
export * from './time-utils.js';
|
|
23
24
|
export { pikkuState } from './pikku-state.js';
|
|
24
|
-
export { addMiddleware,
|
|
25
|
+
export { runMiddleware, registerMiddleware, getMiddlewareByName, addMiddleware, } from './middleware-runner.js';
|
|
25
26
|
export { addPermission } from './permissions.js';
|
|
26
27
|
export { wireHTTP, addHTTPMiddleware } from './wirings/http/http-runner.js';
|
|
27
28
|
export { wireChannel } from './wirings/channel/channel-runner.js';
|
|
28
29
|
export { wireScheduler } from './wirings/scheduler/scheduler-runner.js';
|
|
29
30
|
export { wireQueueWorker } from './wirings/queue/queue-runner.js';
|
|
30
31
|
export { wireMCPResource, wireMCPTool, wireMCPPrompt, runMCPResource, runMCPTool, runMCPPrompt, getMCPTools, getMCPResources, getMCPPrompts, getMCPResourcesMeta, getMCPToolsMeta, getMCPPromptsMeta, } from './wirings/mcp/mcp-runner.js';
|
|
32
|
+
export { wireCLI, runCLICommand } from './wirings/cli/cli-runner.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UserSessionService } from './services/user-session-service.js';
|
|
2
|
-
import { CoreSingletonServices, PikkuInteraction, CorePikkuMiddleware, PikkuWiringTypes } from './types/core.types.js';
|
|
2
|
+
import { CoreSingletonServices, PikkuInteraction, CorePikkuMiddleware, CorePikkuMiddlewareGroup, PikkuWiringTypes, MiddlewareMetadata } from './types/core.types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Runs a chain of middleware functions in sequence before executing the main function.
|
|
5
5
|
*
|
|
@@ -21,73 +21,94 @@ export declare const runMiddleware: <Middleware extends CorePikkuMiddleware>(ser
|
|
|
21
21
|
userSession?: UserSessionService<any>;
|
|
22
22
|
}, interaction: PikkuInteraction, middlewares: readonly Middleware[], main?: () => Promise<unknown>) => Promise<unknown>;
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* Registers global middleware for a specific tag.
|
|
25
25
|
*
|
|
26
|
-
* This function
|
|
27
|
-
* any wiring (HTTP, Channel, Queue, Scheduler, MCP) that includes the matching tag.
|
|
26
|
+
* This function registers middleware at runtime that will be applied to
|
|
27
|
+
* any wiring (HTTP, Channel, Queue, Scheduler, MCP, CLI) that includes the matching tag.
|
|
28
|
+
*
|
|
29
|
+
* For tree-shaking benefits, wrap in a factory function:
|
|
30
|
+
* `export const x = () => addMiddleware('tag', [...])`
|
|
31
|
+
*
|
|
32
|
+
* Accepts an array that can contain:
|
|
33
|
+
* - Direct middleware functions (CorePikkuMiddleware)
|
|
34
|
+
* - Factory middleware functions (CorePikkuMiddlewareFactory)
|
|
28
35
|
*
|
|
29
36
|
* @template PikkuMiddleware The middleware type.
|
|
30
37
|
* @param {string} tag - The tag that the middleware should apply to.
|
|
31
|
-
* @param {
|
|
38
|
+
* @param {CorePikkuMiddlewareGroup} middleware - Array of middleware for this tag.
|
|
32
39
|
*
|
|
33
|
-
* @
|
|
40
|
+
* @returns {CorePikkuMiddlewareGroup} The middleware array (for chaining/wrapping).
|
|
34
41
|
*
|
|
35
42
|
* @example
|
|
36
43
|
* ```typescript
|
|
37
|
-
* //
|
|
38
|
-
* addMiddleware('admin', [
|
|
44
|
+
* // Recommended: tree-shakeable
|
|
45
|
+
* export const adminMiddleware = () => addMiddleware('admin', [
|
|
46
|
+
* authMiddleware,
|
|
47
|
+
* loggingMiddleware({ level: 'info' })
|
|
48
|
+
* ])
|
|
39
49
|
*
|
|
40
|
-
* //
|
|
41
|
-
* addMiddleware('
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* addMiddleware('api', [loggingMiddleware])
|
|
50
|
+
* // Also works: no tree-shaking
|
|
51
|
+
* export const apiMiddleware = addMiddleware('api', [
|
|
52
|
+
* rateLimitMiddleware
|
|
53
|
+
* ])
|
|
45
54
|
* ```
|
|
46
55
|
*/
|
|
47
|
-
export declare const addMiddleware: <PikkuMiddleware extends CorePikkuMiddleware>(tag: string, middleware:
|
|
56
|
+
export declare const addMiddleware: <PikkuMiddleware extends CorePikkuMiddleware>(tag: string, middleware: CorePikkuMiddlewareGroup) => CorePikkuMiddlewareGroup;
|
|
48
57
|
/**
|
|
49
|
-
*
|
|
58
|
+
* Registers a single middleware function by name in the global middleware store.
|
|
50
59
|
*
|
|
51
|
-
* This function
|
|
52
|
-
*
|
|
60
|
+
* This function is used by CLI-generated code to register middleware functions
|
|
61
|
+
* that can be referenced by name in metadata. It stores middleware in a special
|
|
62
|
+
* namespace to avoid conflicts with tag-based middleware.
|
|
53
63
|
*
|
|
54
|
-
* @param {string
|
|
55
|
-
* @
|
|
64
|
+
* @param {string} name - The unique name (pikkuFuncName) of the middleware function.
|
|
65
|
+
* @param {CorePikkuMiddleware} middleware - The middleware function to register.
|
|
56
66
|
*
|
|
57
67
|
* @example
|
|
58
68
|
* ```typescript
|
|
59
|
-
* //
|
|
60
|
-
*
|
|
69
|
+
* // Called by CLI-generated pikku-middleware.gen.ts
|
|
70
|
+
* registerMiddleware('authMiddleware_src_middleware_ts_10_5', authMiddleware)
|
|
71
|
+
* registerMiddleware('loggingMiddleware_src_middleware_ts_20_10', loggingMiddleware)
|
|
61
72
|
* ```
|
|
62
73
|
*/
|
|
63
|
-
export declare const
|
|
74
|
+
export declare const registerMiddleware: (name: string, middleware: CorePikkuMiddleware) => void;
|
|
75
|
+
/**
|
|
76
|
+
* Retrieves a registered middleware function by its name.
|
|
77
|
+
*
|
|
78
|
+
* This function looks up middleware that was registered with registerMiddleware.
|
|
79
|
+
* It's used internally by the framework to resolve middleware references in metadata.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} name - The unique name (pikkuFuncName) of the middleware function.
|
|
82
|
+
* @returns {CorePikkuMiddleware | undefined} The middleware function, or undefined if not found.
|
|
83
|
+
*
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
export declare const getMiddlewareByName: (name: string) => CorePikkuMiddleware | undefined;
|
|
64
87
|
/**
|
|
65
|
-
* Combines
|
|
88
|
+
* Combines wiring-specific middleware with function-level middleware.
|
|
66
89
|
*
|
|
67
|
-
* This
|
|
68
|
-
*
|
|
90
|
+
* This function resolves middleware metadata into actual middleware functions and combines them.
|
|
91
|
+
* It filters out wire middleware without tags from inheritedMiddleware to avoid duplication
|
|
92
|
+
* (those are passed separately as wireMiddleware).
|
|
69
93
|
*
|
|
70
94
|
* @param {object} options - Configuration object for combining middleware.
|
|
71
|
-
* @param {
|
|
72
|
-
* @param {
|
|
73
|
-
* @param {
|
|
74
|
-
* @
|
|
75
|
-
* @returns {CorePikkuMiddleware[]} Combined array of tag-based and wiring-specific middleware.
|
|
95
|
+
* @param {MiddlewareMetadata[] | undefined} options.inheritedMiddleware - Metadata from wiring (HTTP + tags + wire with tags).
|
|
96
|
+
* @param {CorePikkuMiddleware[] | undefined} options.wireMiddleware - Inline wire middleware.
|
|
97
|
+
* @param {MiddlewareMetadata[] | undefined} options.funcMiddleware - Function middleware metadata.
|
|
98
|
+
* @returns {CorePikkuMiddleware[]} Combined array of resolved middleware.
|
|
76
99
|
*
|
|
77
100
|
* @example
|
|
78
101
|
* ```typescript
|
|
79
|
-
* const combined = combineMiddleware({
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* funcMiddleware:
|
|
83
|
-
* funcTags: funcConfig.tags
|
|
102
|
+
* const combined = combineMiddleware(wireType, wireId, {
|
|
103
|
+
* inheritedMiddleware: meta.middleware,
|
|
104
|
+
* wireMiddleware: [inlineMiddleware],
|
|
105
|
+
* funcMiddleware: funcMeta.middleware
|
|
84
106
|
* })
|
|
85
107
|
* ```
|
|
86
108
|
*/
|
|
87
|
-
export declare const combineMiddleware: (wireType: PikkuWiringTypes, uid: string, {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
109
|
+
export declare const combineMiddleware: (wireType: PikkuWiringTypes, uid: string, { wireInheritedMiddleware, wireMiddleware, funcInheritedMiddleware, funcMiddleware, }?: {
|
|
110
|
+
wireInheritedMiddleware?: MiddlewareMetadata[];
|
|
111
|
+
wireMiddleware?: CorePikkuMiddleware[];
|
|
112
|
+
funcInheritedMiddleware?: MiddlewareMetadata[];
|
|
91
113
|
funcMiddleware?: CorePikkuMiddleware[];
|
|
92
|
-
funcTags?: string[];
|
|
93
114
|
}) => readonly CorePikkuMiddleware[];
|
|
@@ -33,66 +33,79 @@ export const runMiddleware = async (services, interaction, middlewares, main) =>
|
|
|
33
33
|
return result;
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* Registers global middleware for a specific tag.
|
|
37
37
|
*
|
|
38
|
-
* This function
|
|
39
|
-
* any wiring (HTTP, Channel, Queue, Scheduler, MCP) that includes the matching tag.
|
|
38
|
+
* This function registers middleware at runtime that will be applied to
|
|
39
|
+
* any wiring (HTTP, Channel, Queue, Scheduler, MCP, CLI) that includes the matching tag.
|
|
40
|
+
*
|
|
41
|
+
* For tree-shaking benefits, wrap in a factory function:
|
|
42
|
+
* `export const x = () => addMiddleware('tag', [...])`
|
|
43
|
+
*
|
|
44
|
+
* Accepts an array that can contain:
|
|
45
|
+
* - Direct middleware functions (CorePikkuMiddleware)
|
|
46
|
+
* - Factory middleware functions (CorePikkuMiddlewareFactory)
|
|
40
47
|
*
|
|
41
48
|
* @template PikkuMiddleware The middleware type.
|
|
42
49
|
* @param {string} tag - The tag that the middleware should apply to.
|
|
43
|
-
* @param {
|
|
50
|
+
* @param {CorePikkuMiddlewareGroup} middleware - Array of middleware for this tag.
|
|
44
51
|
*
|
|
45
|
-
* @
|
|
52
|
+
* @returns {CorePikkuMiddlewareGroup} The middleware array (for chaining/wrapping).
|
|
46
53
|
*
|
|
47
54
|
* @example
|
|
48
55
|
* ```typescript
|
|
49
|
-
* //
|
|
50
|
-
* addMiddleware('admin', [
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
56
|
+
* // Recommended: tree-shakeable
|
|
57
|
+
* export const adminMiddleware = () => addMiddleware('admin', [
|
|
58
|
+
* authMiddleware,
|
|
59
|
+
* loggingMiddleware({ level: 'info' })
|
|
60
|
+
* ])
|
|
54
61
|
*
|
|
55
|
-
* //
|
|
56
|
-
* addMiddleware('api', [
|
|
62
|
+
* // Also works: no tree-shaking
|
|
63
|
+
* export const apiMiddleware = addMiddleware('api', [
|
|
64
|
+
* rateLimitMiddleware
|
|
65
|
+
* ])
|
|
57
66
|
* ```
|
|
58
67
|
*/
|
|
59
68
|
export const addMiddleware = (tag, middleware) => {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
throw new Error(`Middleware for tag '${tag}' already exists. Use a different tag or remove the existing middleware first.`);
|
|
64
|
-
}
|
|
65
|
-
middlewareStore[tag] = middleware;
|
|
69
|
+
const tagGroups = pikkuState('middleware', 'tagGroup');
|
|
70
|
+
tagGroups[tag] = middleware;
|
|
71
|
+
return middleware;
|
|
66
72
|
};
|
|
67
73
|
/**
|
|
68
|
-
*
|
|
74
|
+
* Registers a single middleware function by name in the global middleware store.
|
|
69
75
|
*
|
|
70
|
-
* This function
|
|
71
|
-
*
|
|
76
|
+
* This function is used by CLI-generated code to register middleware functions
|
|
77
|
+
* that can be referenced by name in metadata. It stores middleware in a special
|
|
78
|
+
* namespace to avoid conflicts with tag-based middleware.
|
|
72
79
|
*
|
|
73
|
-
* @param {string
|
|
74
|
-
* @
|
|
80
|
+
* @param {string} name - The unique name (pikkuFuncName) of the middleware function.
|
|
81
|
+
* @param {CorePikkuMiddleware} middleware - The middleware function to register.
|
|
75
82
|
*
|
|
76
83
|
* @example
|
|
77
84
|
* ```typescript
|
|
78
|
-
* //
|
|
79
|
-
*
|
|
85
|
+
* // Called by CLI-generated pikku-middleware.gen.ts
|
|
86
|
+
* registerMiddleware('authMiddleware_src_middleware_ts_10_5', authMiddleware)
|
|
87
|
+
* registerMiddleware('loggingMiddleware_src_middleware_ts_20_10', loggingMiddleware)
|
|
80
88
|
* ```
|
|
81
89
|
*/
|
|
82
|
-
export const
|
|
83
|
-
if (!tags || tags.length === 0) {
|
|
84
|
-
return [];
|
|
85
|
-
}
|
|
90
|
+
export const registerMiddleware = (name, middleware) => {
|
|
86
91
|
const middlewareStore = pikkuState('misc', 'middleware');
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
middlewareStore[name] = [middleware];
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Retrieves a registered middleware function by its name.
|
|
96
|
+
*
|
|
97
|
+
* This function looks up middleware that was registered with registerMiddleware.
|
|
98
|
+
* It's used internally by the framework to resolve middleware references in metadata.
|
|
99
|
+
*
|
|
100
|
+
* @param {string} name - The unique name (pikkuFuncName) of the middleware function.
|
|
101
|
+
* @returns {CorePikkuMiddleware | undefined} The middleware function, or undefined if not found.
|
|
102
|
+
*
|
|
103
|
+
* @internal
|
|
104
|
+
*/
|
|
105
|
+
export const getMiddlewareByName = (name) => {
|
|
106
|
+
const middlewareStore = pikkuState('misc', 'middleware');
|
|
107
|
+
const middleware = middlewareStore[name];
|
|
108
|
+
return middleware?.[0];
|
|
96
109
|
};
|
|
97
110
|
const middlewareCache = {
|
|
98
111
|
[PikkuWiringTypes.http]: {},
|
|
@@ -101,47 +114,86 @@ const middlewareCache = {
|
|
|
101
114
|
[PikkuWiringTypes.queue]: {},
|
|
102
115
|
[PikkuWiringTypes.scheduler]: {},
|
|
103
116
|
[PikkuWiringTypes.mcp]: {},
|
|
117
|
+
[PikkuWiringTypes.cli]: {},
|
|
104
118
|
};
|
|
105
119
|
/**
|
|
106
|
-
* Combines
|
|
120
|
+
* Combines wiring-specific middleware with function-level middleware.
|
|
107
121
|
*
|
|
108
|
-
* This
|
|
109
|
-
*
|
|
122
|
+
* This function resolves middleware metadata into actual middleware functions and combines them.
|
|
123
|
+
* It filters out wire middleware without tags from inheritedMiddleware to avoid duplication
|
|
124
|
+
* (those are passed separately as wireMiddleware).
|
|
110
125
|
*
|
|
111
126
|
* @param {object} options - Configuration object for combining middleware.
|
|
112
|
-
* @param {
|
|
113
|
-
* @param {
|
|
114
|
-
* @param {
|
|
115
|
-
* @
|
|
116
|
-
* @returns {CorePikkuMiddleware[]} Combined array of tag-based and wiring-specific middleware.
|
|
127
|
+
* @param {MiddlewareMetadata[] | undefined} options.inheritedMiddleware - Metadata from wiring (HTTP + tags + wire with tags).
|
|
128
|
+
* @param {CorePikkuMiddleware[] | undefined} options.wireMiddleware - Inline wire middleware.
|
|
129
|
+
* @param {MiddlewareMetadata[] | undefined} options.funcMiddleware - Function middleware metadata.
|
|
130
|
+
* @returns {CorePikkuMiddleware[]} Combined array of resolved middleware.
|
|
117
131
|
*
|
|
118
132
|
* @example
|
|
119
133
|
* ```typescript
|
|
120
|
-
* const combined = combineMiddleware({
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* funcMiddleware:
|
|
124
|
-
* funcTags: funcConfig.tags
|
|
134
|
+
* const combined = combineMiddleware(wireType, wireId, {
|
|
135
|
+
* inheritedMiddleware: meta.middleware,
|
|
136
|
+
* wireMiddleware: [inlineMiddleware],
|
|
137
|
+
* funcMiddleware: funcMeta.middleware
|
|
125
138
|
* })
|
|
126
139
|
* ```
|
|
127
140
|
*/
|
|
128
|
-
export const combineMiddleware = (wireType, uid, {
|
|
141
|
+
export const combineMiddleware = (wireType, uid, { wireInheritedMiddleware, wireMiddleware, funcInheritedMiddleware, funcMiddleware, } = {}) => {
|
|
129
142
|
if (middlewareCache[wireType][uid]) {
|
|
130
143
|
return middlewareCache[wireType][uid];
|
|
131
144
|
}
|
|
132
|
-
|
|
133
|
-
// 1
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
const resolved = [];
|
|
146
|
+
// 1. Resolve wire inherited middleware (HTTP + tag groups + individual wire middleware)
|
|
147
|
+
if (wireInheritedMiddleware) {
|
|
148
|
+
for (const meta of wireInheritedMiddleware) {
|
|
149
|
+
if (meta.type === 'http') {
|
|
150
|
+
// Look up HTTP middleware group from pikkuState
|
|
151
|
+
const group = pikkuState('middleware', 'httpGroup')[meta.route];
|
|
152
|
+
if (group) {
|
|
153
|
+
// At runtime, all factories should be resolved to middleware
|
|
154
|
+
resolved.push(...group);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else if (meta.type === 'tag') {
|
|
158
|
+
// Look up tag middleware group from pikkuState
|
|
159
|
+
const group = pikkuState('middleware', 'tagGroup')[meta.tag];
|
|
160
|
+
if (group) {
|
|
161
|
+
// At runtime, all factories should be resolved to middleware
|
|
162
|
+
resolved.push(...group);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else if (meta.type === 'wire') {
|
|
166
|
+
// Individual wire middleware (exported, not inline)
|
|
167
|
+
const middleware = getMiddlewareByName(meta.name);
|
|
168
|
+
if (middleware) {
|
|
169
|
+
resolved.push(middleware);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// 2. Add inline wire middleware
|
|
175
|
+
if (wireMiddleware) {
|
|
176
|
+
resolved.push(...wireMiddleware);
|
|
177
|
+
}
|
|
178
|
+
// 3. Resolve function inherited middleware (only tags, wire middleware already handled)
|
|
179
|
+
if (funcInheritedMiddleware) {
|
|
180
|
+
for (const meta of funcInheritedMiddleware) {
|
|
181
|
+
if (meta.type === 'tag') {
|
|
182
|
+
// Look up tag middleware group from pikkuState
|
|
183
|
+
const group = pikkuState('middleware', 'tagGroup')[meta.tag];
|
|
184
|
+
if (group) {
|
|
185
|
+
// At runtime, all factories should be resolved to middleware
|
|
186
|
+
resolved.push(...group);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Note: wire middleware is already handled in wireInheritedMiddleware
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// 4. Add inline function middleware
|
|
193
|
+
if (funcMiddleware) {
|
|
194
|
+
resolved.push(...funcMiddleware);
|
|
195
|
+
}
|
|
196
|
+
// Deduplicate and freeze
|
|
197
|
+
middlewareCache[wireType][uid] = freezeDedupe(resolved);
|
|
146
198
|
return middlewareCache[wireType][uid];
|
|
147
199
|
};
|
package/dist/permissions.js
CHANGED
package/dist/pikku-state.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ChannelsMeta, CoreChannel } from './wirings/channel/channel.types.js';
|
|
2
2
|
import { CoreHTTPFunctionWiring, HTTPMethod, HTTPWiringsMeta } from './wirings/http/http.types.js';
|
|
3
|
-
import { FunctionsMeta, CorePikkuMiddleware } from './types/core.types.js';
|
|
3
|
+
import { FunctionsMeta, CorePikkuMiddleware, CorePikkuMiddlewareGroup, FunctionServicesMeta } from './types/core.types.js';
|
|
4
4
|
import { CoreScheduledTask, ScheduledTasksMeta } from './wirings/scheduler/scheduler.types.js';
|
|
5
5
|
import { ErrorDetails, PikkuError } from './errors/error-handler.js';
|
|
6
6
|
import { CorePermissionGroup, CorePikkuFunctionConfig, CorePikkuPermission } from './function/functions.types.js';
|
|
7
7
|
import { queueWorkersMeta, CoreQueueWorker } from './wirings/queue/queue.types.js';
|
|
8
8
|
import { CoreMCPResource, CoreMCPTool, CoreMCPPrompt, MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from './wirings/mcp/mcp.types.js';
|
|
9
|
+
import { CLIProgramMeta, CLIProgramState } from './wirings/cli/cli.types.js';
|
|
9
10
|
interface PikkuState {
|
|
10
11
|
function: {
|
|
11
12
|
meta: FunctionsMeta;
|
|
@@ -44,6 +45,30 @@ interface PikkuState {
|
|
|
44
45
|
prompts: Map<string, CoreMCPPrompt>;
|
|
45
46
|
promptsMeta: MCPPromptMeta;
|
|
46
47
|
};
|
|
48
|
+
cli: {
|
|
49
|
+
meta: Record<string, CLIProgramMeta>;
|
|
50
|
+
programs: Record<string, CLIProgramState>;
|
|
51
|
+
};
|
|
52
|
+
middleware: {
|
|
53
|
+
tagGroup: Record<string, CorePikkuMiddlewareGroup>;
|
|
54
|
+
httpGroup: Record<string, CorePikkuMiddlewareGroup>;
|
|
55
|
+
tagGroupMeta: Record<string, {
|
|
56
|
+
exportName: string | null;
|
|
57
|
+
sourceFile: string;
|
|
58
|
+
position: number;
|
|
59
|
+
services: FunctionServicesMeta;
|
|
60
|
+
middlewareCount: number;
|
|
61
|
+
isFactory: boolean;
|
|
62
|
+
}>;
|
|
63
|
+
httpGroupMeta: Record<string, {
|
|
64
|
+
exportName: string | null;
|
|
65
|
+
sourceFile: string;
|
|
66
|
+
position: number;
|
|
67
|
+
services: FunctionServicesMeta;
|
|
68
|
+
middlewareCount: number;
|
|
69
|
+
isFactory: boolean;
|
|
70
|
+
}>;
|
|
71
|
+
};
|
|
47
72
|
misc: {
|
|
48
73
|
errors: Map<PikkuError, ErrorDetails>;
|
|
49
74
|
schemas: Map<string, any>;
|