@pikku/core 0.9.4 → 0.9.5
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 +19 -0
- package/dist/function/function-runner.d.ts +1 -1
- package/dist/function/function-runner.js +22 -25
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/middleware-runner.d.ts +19 -11
- package/dist/middleware-runner.js +27 -13
- package/dist/permissions.d.ts +19 -3
- package/dist/permissions.js +61 -1
- package/dist/pikku-state.d.ts +2 -2
- package/dist/pikku-state.js +3 -3
- package/dist/types/core.types.d.ts +3 -4
- package/dist/wirings/channel/local/local-channel-runner.js +5 -2
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +5 -2
- package/dist/wirings/http/http-runner.js +9 -2
- package/dist/wirings/http/http.types.d.ts +4 -4
- package/dist/wirings/mcp/mcp-runner.js +8 -3
- package/dist/wirings/queue/queue-runner.js +9 -2
- package/dist/wirings/rpc/rpc-runner.d.ts +1 -2
- package/dist/wirings/scheduler/scheduler-runner.js +8 -3
- package/package.json +1 -1
- package/src/function/function-runner.test.ts +450 -0
- package/src/function/function-runner.ts +23 -43
- package/src/index.ts +6 -2
- package/src/middleware-runner.test.ts +329 -0
- package/src/middleware-runner.ts +38 -17
- package/src/permissions.test.ts +403 -42
- package/src/permissions.ts +115 -5
- package/src/pikku-state.ts +9 -5
- package/src/types/core.types.ts +3 -4
- package/src/wirings/channel/local/local-channel-runner.ts +5 -5
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +5 -5
- package/src/wirings/http/http-runner.ts +10 -2
- package/src/wirings/http/http.types.ts +4 -4
- package/src/wirings/mcp/mcp-runner.ts +8 -3
- package/src/wirings/queue/queue-runner.ts +12 -2
- package/src/wirings/scheduler/scheduler-runner.ts +10 -3
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
## 0.9.0
|
|
2
2
|
|
|
3
|
+
## 0.9.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7e1f5b3: feat: implement ordered middleware and permission execution system
|
|
8
|
+
|
|
9
|
+
## New Features
|
|
10
|
+
|
|
11
|
+
### Ordered Execution System
|
|
12
|
+
|
|
13
|
+
Both middleware and permissions now execute in a specific hierarchical order:
|
|
14
|
+
|
|
15
|
+
1. **Wiring Tags** - Tag-based middleware/permissions from wiring level (e.g., HTTP route tags)
|
|
16
|
+
2. **Wiring Middleware/Permissions** - Direct wiring-level middleware/permissions
|
|
17
|
+
3. **Function Middleware** - Function-level middleware
|
|
18
|
+
4. **Function Tags** - Tag-based middleware/permissions from function level
|
|
19
|
+
|
|
20
|
+
- b443405: feat: adding middleware and functions by tags
|
|
21
|
+
|
|
3
22
|
## 0.9.4
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -2,7 +2,7 @@ import { CoreServices, CoreUserSession, CorePikkuMiddleware } from '../types/cor
|
|
|
2
2
|
import { CorePermissionGroup, CorePikkuFunction, CorePikkuFunctionConfig, CorePikkuFunctionSessionless } from './functions.types.js';
|
|
3
3
|
export declare const addFunction: (funcName: string, funcConfig: CorePikkuFunctionConfig<any, any> | CorePikkuFunctionSessionless<any, any> | CorePikkuFunction<any, any>) => void;
|
|
4
4
|
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>(funcName: string, { getAllServices, data, session, permissions:
|
|
5
|
+
export declare const runPikkuFunc: <In = any, Out = any>(funcName: string, { getAllServices, data, session, permissions: wiringPermissions, middleware: wiringMiddleware, coerceDataFromSchema, tags, }: {
|
|
6
6
|
getAllServices: () => Promise<CoreServices> | CoreServices;
|
|
7
7
|
data: In;
|
|
8
8
|
session?: CoreUserSession;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ForbiddenError } from '../errors/errors.js';
|
|
2
|
-
import { runMiddleware } from '../middleware-runner.js';
|
|
3
|
-
import {
|
|
2
|
+
import { runMiddleware, combineMiddleware } from '../middleware-runner.js';
|
|
3
|
+
import { runPermissions } from '../permissions.js';
|
|
4
4
|
import { pikkuState } from '../pikku-state.js';
|
|
5
5
|
import { coerceTopLevelDataFromSchema, validateSchema } from '../schema.js';
|
|
6
6
|
export const addFunction = (funcName, funcConfig) => {
|
|
@@ -16,7 +16,7 @@ export const runPikkuFuncDirectly = async (funcName, allServices, data, session)
|
|
|
16
16
|
}
|
|
17
17
|
return (await funcConfig.func(allServices, data, session));
|
|
18
18
|
};
|
|
19
|
-
export const runPikkuFunc = async (funcName, { getAllServices, data, session, permissions:
|
|
19
|
+
export const runPikkuFunc = async (funcName, { getAllServices, data, session, permissions: wiringPermissions, middleware: wiringMiddleware, coerceDataFromSchema, tags = [], }) => {
|
|
20
20
|
const funcConfig = pikkuState('function', 'functions').get(funcName);
|
|
21
21
|
if (!funcConfig) {
|
|
22
22
|
throw new Error(`Function not found: ${funcName}`);
|
|
@@ -38,32 +38,29 @@ export const runPikkuFunc = async (funcName, { getAllServices, data, session, pe
|
|
|
38
38
|
coerceTopLevelDataFromSchema(inputSchemaName, data);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
if (
|
|
59
|
-
throw new ForbiddenError('Permission denied');
|
|
60
|
-
}
|
|
61
|
-
if (transportMiddleware || funcConfig.middleware) {
|
|
41
|
+
// Run permission checks in the specified order
|
|
42
|
+
await runPermissions({
|
|
43
|
+
wiringTags: tags,
|
|
44
|
+
wiringPermissions,
|
|
45
|
+
funcTags: funcConfig.tags,
|
|
46
|
+
funcPermissions: funcConfig.permissions,
|
|
47
|
+
allServices,
|
|
48
|
+
data,
|
|
49
|
+
session,
|
|
50
|
+
});
|
|
51
|
+
// Combine all middleware: wiring tags → wiring middleware → func middleware → func tags
|
|
52
|
+
const allMiddleware = combineMiddleware({
|
|
53
|
+
wiringTags: tags,
|
|
54
|
+
wiringMiddleware,
|
|
55
|
+
funcMiddleware: funcConfig.middleware,
|
|
56
|
+
funcTags: funcConfig.tags,
|
|
57
|
+
});
|
|
58
|
+
if (allMiddleware.length > 0) {
|
|
62
59
|
return (await runMiddleware(allServices, {
|
|
63
60
|
http: allServices.http,
|
|
64
61
|
mcp: allServices.mcp,
|
|
65
62
|
rpc: allServices.rpc,
|
|
66
|
-
},
|
|
63
|
+
}, allMiddleware, async () => await funcConfig.func(allServices, data, session)));
|
|
67
64
|
}
|
|
68
65
|
return (await funcConfig.func(allServices, data, session));
|
|
69
66
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -21,8 +21,8 @@ export * from './middleware/index.js';
|
|
|
21
21
|
export * from './time-utils.js';
|
|
22
22
|
export * from './utils.js';
|
|
23
23
|
export { pikkuState } from './pikku-state.js';
|
|
24
|
-
export { runMiddleware, addMiddleware,
|
|
25
|
-
export { addPermission, getPermissionsForTags } from './permissions.js';
|
|
24
|
+
export { runMiddleware, addMiddleware, combineMiddleware, } from './middleware-runner.js';
|
|
25
|
+
export { addPermission, getPermissionsForTags, runPermissions, } from './permissions.js';
|
|
26
26
|
export { wireHTTP, addHTTPMiddleware } from './wirings/http/http-runner.js';
|
|
27
27
|
export { wireChannel } from './wirings/channel/channel-runner.js';
|
|
28
28
|
export { wireScheduler } from './wirings/scheduler/scheduler-runner.js';
|
package/dist/index.js
CHANGED
|
@@ -21,8 +21,8 @@ export * from './middleware/index.js';
|
|
|
21
21
|
export * from './time-utils.js';
|
|
22
22
|
export * from './utils.js';
|
|
23
23
|
export { pikkuState } from './pikku-state.js';
|
|
24
|
-
export { runMiddleware, addMiddleware,
|
|
25
|
-
export { addPermission, getPermissionsForTags } from './permissions.js';
|
|
24
|
+
export { runMiddleware, addMiddleware, combineMiddleware, } from './middleware-runner.js';
|
|
25
|
+
export { addPermission, getPermissionsForTags, runPermissions, } from './permissions.js';
|
|
26
26
|
export { wireHTTP, addHTTPMiddleware } from './wirings/http/http-runner.js';
|
|
27
27
|
export { wireChannel } from './wirings/channel/channel-runner.js';
|
|
28
28
|
export { wireScheduler } from './wirings/scheduler/scheduler-runner.js';
|
|
@@ -62,23 +62,31 @@ export declare const addMiddleware: <PikkuMiddleware extends CorePikkuMiddleware
|
|
|
62
62
|
*/
|
|
63
63
|
export declare const getMiddlewareForTags: (tags?: string[]) => CorePikkuMiddleware[];
|
|
64
64
|
/**
|
|
65
|
-
* Combines tag-based middleware with wiring-specific middleware.
|
|
65
|
+
* Combines tag-based middleware with wiring-specific middleware and function-level middleware.
|
|
66
66
|
*
|
|
67
67
|
* This helper function gets middleware for tags and combines it with any
|
|
68
|
-
* wiring-specific middleware, avoiding the need for manual spreading.
|
|
68
|
+
* wiring-specific middleware and function-level middleware, avoiding the need for manual spreading.
|
|
69
69
|
*
|
|
70
|
-
* @param {
|
|
71
|
-
* @param {
|
|
70
|
+
* @param {object} options - Configuration object for combining middleware.
|
|
71
|
+
* @param {CorePikkuMiddleware[] | undefined} options.wiringMiddleware - Wiring-specific middleware.
|
|
72
|
+
* @param {string[] | undefined} options.wiringTags - Array of wiring-level tags to look up middleware for.
|
|
73
|
+
* @param {CorePikkuMiddleware[] | undefined} options.funcMiddleware - Function-level middleware.
|
|
74
|
+
* @param {string[] | undefined} options.funcTags - Array of function-level tags to look up middleware for.
|
|
72
75
|
* @returns {CorePikkuMiddleware[]} Combined array of tag-based and wiring-specific middleware.
|
|
73
76
|
*
|
|
74
77
|
* @example
|
|
75
78
|
* ```typescript
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
79
|
+
* const combined = combineMiddleware({
|
|
80
|
+
* wiringMiddleware: httpRoute.middleware,
|
|
81
|
+
* wiringTags: httpRoute.tags,
|
|
82
|
+
* funcMiddleware: funcConfig.middleware,
|
|
83
|
+
* funcTags: funcConfig.tags
|
|
84
|
+
* })
|
|
82
85
|
* ```
|
|
83
86
|
*/
|
|
84
|
-
export declare const
|
|
87
|
+
export declare const combineMiddleware: ({ wiringMiddleware, wiringTags, funcMiddleware, funcTags, }?: {
|
|
88
|
+
wiringMiddleware?: CorePikkuMiddleware[];
|
|
89
|
+
wiringTags?: string[];
|
|
90
|
+
funcMiddleware?: CorePikkuMiddleware[];
|
|
91
|
+
funcTags?: string[];
|
|
92
|
+
}) => CorePikkuMiddleware[];
|
|
@@ -94,26 +94,40 @@ export const getMiddlewareForTags = (tags) => {
|
|
|
94
94
|
return applicableMiddleware;
|
|
95
95
|
};
|
|
96
96
|
/**
|
|
97
|
-
* Combines tag-based middleware with wiring-specific middleware.
|
|
97
|
+
* Combines tag-based middleware with wiring-specific middleware and function-level middleware.
|
|
98
98
|
*
|
|
99
99
|
* This helper function gets middleware for tags and combines it with any
|
|
100
|
-
* wiring-specific middleware, avoiding the need for manual spreading.
|
|
100
|
+
* wiring-specific middleware and function-level middleware, avoiding the need for manual spreading.
|
|
101
101
|
*
|
|
102
|
-
* @param {
|
|
103
|
-
* @param {
|
|
102
|
+
* @param {object} options - Configuration object for combining middleware.
|
|
103
|
+
* @param {CorePikkuMiddleware[] | undefined} options.wiringMiddleware - Wiring-specific middleware.
|
|
104
|
+
* @param {string[] | undefined} options.wiringTags - Array of wiring-level tags to look up middleware for.
|
|
105
|
+
* @param {CorePikkuMiddleware[] | undefined} options.funcMiddleware - Function-level middleware.
|
|
106
|
+
* @param {string[] | undefined} options.funcTags - Array of function-level tags to look up middleware for.
|
|
104
107
|
* @returns {CorePikkuMiddleware[]} Combined array of tag-based and wiring-specific middleware.
|
|
105
108
|
*
|
|
106
109
|
* @example
|
|
107
110
|
* ```typescript
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
111
|
+
* const combined = combineMiddleware({
|
|
112
|
+
* wiringMiddleware: httpRoute.middleware,
|
|
113
|
+
* wiringTags: httpRoute.tags,
|
|
114
|
+
* funcMiddleware: funcConfig.middleware,
|
|
115
|
+
* funcTags: funcConfig.tags
|
|
116
|
+
* })
|
|
114
117
|
* ```
|
|
115
118
|
*/
|
|
116
|
-
export const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
export const combineMiddleware = ({ wiringMiddleware, wiringTags, funcMiddleware, funcTags, } = {}) => {
|
|
120
|
+
// Run middleware in specific order:
|
|
121
|
+
// 1) wiringTags middleware
|
|
122
|
+
// 2) wiringMiddleware
|
|
123
|
+
// 3) funcMiddleware
|
|
124
|
+
// 4) funcTags middleware
|
|
125
|
+
const wiringTaggedMiddleware = getMiddlewareForTags(wiringTags);
|
|
126
|
+
const funcTaggedMiddleware = getMiddlewareForTags(funcTags);
|
|
127
|
+
return [
|
|
128
|
+
...wiringTaggedMiddleware,
|
|
129
|
+
...(wiringMiddleware || []),
|
|
130
|
+
...(funcMiddleware || []),
|
|
131
|
+
...funcTaggedMiddleware,
|
|
132
|
+
];
|
|
119
133
|
};
|
package/dist/permissions.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CoreServices, CoreUserSession } from './types/core.types.js';
|
|
2
|
-
import { CorePermissionGroup } from './function/functions.types.js';
|
|
2
|
+
import { CorePermissionGroup, CorePikkuPermission } from './function/functions.types.js';
|
|
3
3
|
/**
|
|
4
4
|
* This function validates permissions by iterating over permission groups and executing the corresponding permission functions. If all functions in at least one group return true, the permission is considered valid.
|
|
5
5
|
* @param services - The core services required for permission validation.
|
|
@@ -31,7 +31,7 @@ export declare const verifyPermissions: (permissions: CorePermissionGroup, servi
|
|
|
31
31
|
* addPermission('api', [readPermission])
|
|
32
32
|
* ```
|
|
33
33
|
*/
|
|
34
|
-
export declare const addPermission: (tag: string, permissions:
|
|
34
|
+
export declare const addPermission: (tag: string, permissions: CorePermissionGroup | CorePikkuPermission[]) => void;
|
|
35
35
|
/**
|
|
36
36
|
* Retrieves permissions for a given set of tags.
|
|
37
37
|
*
|
|
@@ -47,4 +47,20 @@ export declare const addPermission: (tag: string, permissions: any[]) => void;
|
|
|
47
47
|
* const permissions = getPermissionsForTags(['api', 'auth'])
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
|
-
export declare const getPermissionsForTags: (tags?: string[]) =>
|
|
50
|
+
export declare const getPermissionsForTags: (tags?: string[]) => Array<CorePermissionGroup | CorePikkuPermission>;
|
|
51
|
+
/**
|
|
52
|
+
* Runs permission checks in the specified order:
|
|
53
|
+
* 1) wiring tag permissions - at least one must pass if any exist
|
|
54
|
+
* 2) wiring permissions - must pass if defined
|
|
55
|
+
* 3) function tag permissions - at least one must pass if any exist
|
|
56
|
+
* 4) function permissions - must pass if defined
|
|
57
|
+
*/
|
|
58
|
+
export declare const runPermissions: ({ wiringTags, wiringPermissions, funcTags, funcPermissions, allServices, data, session, }: {
|
|
59
|
+
wiringTags?: string[];
|
|
60
|
+
wiringPermissions?: CorePermissionGroup;
|
|
61
|
+
funcTags?: string[];
|
|
62
|
+
funcPermissions?: CorePermissionGroup;
|
|
63
|
+
allServices: CoreServices;
|
|
64
|
+
data: any;
|
|
65
|
+
session?: CoreUserSession;
|
|
66
|
+
}) => Promise<void>;
|
package/dist/permissions.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { pikkuState } from './pikku-state.js';
|
|
2
|
+
import { ForbiddenError } from './errors/errors.js';
|
|
2
3
|
/**
|
|
3
4
|
* This function validates permissions by iterating over permission groups and executing the corresponding permission functions. If all functions in at least one group return true, the permission is considered valid.
|
|
4
5
|
* @param services - The core services required for permission validation.
|
|
@@ -87,8 +88,67 @@ export const getPermissionsForTags = (tags) => {
|
|
|
87
88
|
for (const tag of new Set(tags)) {
|
|
88
89
|
const tagPermissions = permissionsStore[tag];
|
|
89
90
|
if (tagPermissions) {
|
|
90
|
-
|
|
91
|
+
if (Array.isArray(tagPermissions)) {
|
|
92
|
+
applicablePermissions.push(...tagPermissions);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
applicablePermissions.push(tagPermissions);
|
|
96
|
+
}
|
|
91
97
|
}
|
|
92
98
|
}
|
|
93
99
|
return applicablePermissions;
|
|
94
100
|
};
|
|
101
|
+
/**
|
|
102
|
+
* Runs permission checks in the specified order:
|
|
103
|
+
* 1) wiring tag permissions - at least one must pass if any exist
|
|
104
|
+
* 2) wiring permissions - must pass if defined
|
|
105
|
+
* 3) function tag permissions - at least one must pass if any exist
|
|
106
|
+
* 4) function permissions - must pass if defined
|
|
107
|
+
*/
|
|
108
|
+
export const runPermissions = async ({ wiringTags, wiringPermissions, funcTags, funcPermissions, allServices, data, session, }) => {
|
|
109
|
+
let permissioned = true;
|
|
110
|
+
// 1. Wiring tag permissions - at least one must pass if any exist
|
|
111
|
+
const wiringTaggedPermissions = getPermissionsForTags(wiringTags || []);
|
|
112
|
+
if (wiringTaggedPermissions.length > 0) {
|
|
113
|
+
permissioned = false; // Start false, need at least one to pass
|
|
114
|
+
for (const permissions of wiringTaggedPermissions) {
|
|
115
|
+
const result = await verifyPermissions(typeof permissions === 'function' ? { permissions } : permissions, allServices, data, session);
|
|
116
|
+
if (result) {
|
|
117
|
+
permissioned = true;
|
|
118
|
+
break; // At least one passed, we're good at this level
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!permissioned) {
|
|
122
|
+
throw new ForbiddenError('Permission denied - wiring tag permissions');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// 2. Wiring permissions - must pass if defined
|
|
126
|
+
if (wiringPermissions) {
|
|
127
|
+
permissioned = await verifyPermissions(wiringPermissions, allServices, data, session);
|
|
128
|
+
if (!permissioned) {
|
|
129
|
+
throw new ForbiddenError('Permission denied - wiring permissions');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// 3. Function tag permissions - at least one must pass if any exist
|
|
133
|
+
const funcTaggedPermissions = getPermissionsForTags(funcTags || []);
|
|
134
|
+
if (funcTaggedPermissions.length > 0) {
|
|
135
|
+
permissioned = false; // Start false, need at least one to pass
|
|
136
|
+
for (const permissions of funcTaggedPermissions) {
|
|
137
|
+
const result = await verifyPermissions(typeof permissions === 'function' ? { permissions } : permissions, allServices, data, session);
|
|
138
|
+
if (result) {
|
|
139
|
+
permissioned = true;
|
|
140
|
+
break; // At least one passed, we're good at this level
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!permissioned) {
|
|
144
|
+
throw new ForbiddenError('Permission denied - function tag permissions');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// 4. Function permissions - must pass if defined
|
|
148
|
+
if (funcPermissions) {
|
|
149
|
+
permissioned = await verifyPermissions(funcPermissions, allServices, data, session);
|
|
150
|
+
if (!permissioned) {
|
|
151
|
+
throw new ForbiddenError('Permission denied - function permissions');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
};
|
package/dist/pikku-state.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { CoreHTTPFunctionWiring, HTTPMethod, HTTPWiringsMeta } from './wirings/h
|
|
|
3
3
|
import { FunctionsMeta, CorePikkuMiddleware } 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
|
-
import { CorePikkuFunctionConfig } from './function/functions.types.js';
|
|
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
9
|
interface PikkuState {
|
|
@@ -50,7 +50,7 @@ interface PikkuState {
|
|
|
50
50
|
errors: Map<PikkuError, ErrorDetails>;
|
|
51
51
|
schemas: Map<string, any>;
|
|
52
52
|
middleware: Record<string, CorePikkuMiddleware[]>;
|
|
53
|
-
permissions: Record<string,
|
|
53
|
+
permissions: Record<string, CorePermissionGroup | CorePikkuPermission[]>;
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
export declare const resetPikkuState: () => void;
|
package/dist/pikku-state.js
CHANGED
|
@@ -35,9 +35,9 @@ export const resetPikkuState = () => {
|
|
|
35
35
|
},
|
|
36
36
|
misc: {
|
|
37
37
|
errors: globalThis.pikkuState?.misc?.errors || new Map(),
|
|
38
|
-
schemas:
|
|
39
|
-
middleware:
|
|
40
|
-
permissions:
|
|
38
|
+
schemas: new Map(),
|
|
39
|
+
middleware: {},
|
|
40
|
+
permissions: {},
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
43
|
};
|
|
@@ -92,14 +92,13 @@ export interface CoreSingletonServices<Config extends CoreConfig = CoreConfig> {
|
|
|
92
92
|
/**
|
|
93
93
|
* Represents different forms of interaction within Pikku and the outside world.
|
|
94
94
|
*/
|
|
95
|
-
export type PikkuInteraction = Partial<{
|
|
96
|
-
http: PikkuHTTP
|
|
95
|
+
export type PikkuInteraction<In = unknown, Out = unknown> = Partial<{
|
|
96
|
+
http: PikkuHTTP<In>;
|
|
97
97
|
mcp: PikkuMCP;
|
|
98
98
|
rpc: PikkuRPC;
|
|
99
|
-
channel: PikkuChannel<unknown,
|
|
99
|
+
channel: PikkuChannel<unknown, Out>;
|
|
100
100
|
scheduledTask: PikkuScheduledTask;
|
|
101
101
|
queue: PikkuQueue;
|
|
102
|
-
s: any;
|
|
103
102
|
}>;
|
|
104
103
|
/**
|
|
105
104
|
* A function that can wrap an interaction and be called before or after
|
|
@@ -4,7 +4,7 @@ import { closeSessionServices } from '../../../utils.js';
|
|
|
4
4
|
import { processMessageHandlers } from '../channel-handler.js';
|
|
5
5
|
import { PikkuLocalChannelHandler } from './local-channel-handler.js';
|
|
6
6
|
import { handleHTTPError } from '../../../handle-error.js';
|
|
7
|
-
import {
|
|
7
|
+
import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js';
|
|
8
8
|
import { PikkuUserSessionService } from '../../../services/user-session-service.js';
|
|
9
9
|
import { runPikkuFuncDirectly } from '../../../function/function-runner.js';
|
|
10
10
|
import { rpcService } from '../../rpc/rpc-runner.js';
|
|
@@ -77,6 +77,9 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
|
|
|
77
77
|
await runMiddleware({
|
|
78
78
|
...singletonServices,
|
|
79
79
|
userSession,
|
|
80
|
-
}, { http },
|
|
80
|
+
}, { http }, combineMiddleware({
|
|
81
|
+
wiringMiddleware: channelConfig.middleware,
|
|
82
|
+
wiringTags: channelConfig.tags,
|
|
83
|
+
}), main);
|
|
81
84
|
return channelHandler;
|
|
82
85
|
};
|
|
@@ -4,7 +4,7 @@ import { openChannel } from '../channel-runner.js';
|
|
|
4
4
|
import { createHTTPInteraction } from '../../http/http-runner.js';
|
|
5
5
|
import { handleHTTPError } from '../../../handle-error.js';
|
|
6
6
|
import { PikkuUserSessionService } from '../../../services/user-session-service.js';
|
|
7
|
-
import {
|
|
7
|
+
import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js';
|
|
8
8
|
import { pikkuState } from '../../../pikku-state.js';
|
|
9
9
|
import { PikkuFetchHTTPRequest } from '../../http/pikku-fetch-http-request.js';
|
|
10
10
|
import { runPikkuFuncDirectly } from '../../../function/function-runner.js';
|
|
@@ -76,7 +76,10 @@ export const runChannelConnect = async ({ singletonServices, channelId, channelO
|
|
|
76
76
|
await runMiddleware({
|
|
77
77
|
...singletonServices,
|
|
78
78
|
userSession,
|
|
79
|
-
}, { http },
|
|
79
|
+
}, { http }, combineMiddleware({
|
|
80
|
+
wiringMiddleware: channelConfig.middleware,
|
|
81
|
+
wiringTags: channelConfig.tags,
|
|
82
|
+
}), main);
|
|
80
83
|
};
|
|
81
84
|
export const runChannelDisconnect = async ({ singletonServices, ...params }) => {
|
|
82
85
|
let sessionServices;
|
|
@@ -2,7 +2,7 @@ import { match } from 'path-to-regexp';
|
|
|
2
2
|
import { MissingSessionError, NotFoundError } from '../../errors/errors.js';
|
|
3
3
|
import { closeSessionServices, createWeakUID, isSerializable, } from '../../utils.js';
|
|
4
4
|
import { PikkuUserSessionService, } from '../../services/user-session-service.js';
|
|
5
|
-
import {
|
|
5
|
+
import { combineMiddleware, runMiddleware } from '../../middleware-runner.js';
|
|
6
6
|
import { handleHTTPError } from '../../handle-error.js';
|
|
7
7
|
import { pikkuState } from '../../pikku-state.js';
|
|
8
8
|
import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
|
|
@@ -250,8 +250,15 @@ const executeRouteWithMiddleware = async (services, matchedRoute, http, options)
|
|
|
250
250
|
// TODO: Evaluate if the response stream should be explicitly ended.
|
|
251
251
|
// http?.response?.end()
|
|
252
252
|
};
|
|
253
|
+
// Get function config for middleware and tags
|
|
254
|
+
const funcConfig = pikkuState('function', 'functions').get(meta.pikkuFuncName);
|
|
253
255
|
// Execute middleware, then run the main logic
|
|
254
|
-
await runMiddleware({ ...singletonServices, userSession }, { http },
|
|
256
|
+
await runMiddleware({ ...singletonServices, userSession }, { http }, combineMiddleware({
|
|
257
|
+
wiringMiddleware: middleware,
|
|
258
|
+
wiringTags: route.tags,
|
|
259
|
+
funcMiddleware: funcConfig?.middleware,
|
|
260
|
+
funcTags: funcConfig?.tags,
|
|
261
|
+
}), runMain);
|
|
255
262
|
return sessionServices ? { result, sessionServices } : { result };
|
|
256
263
|
};
|
|
257
264
|
/**
|
|
@@ -46,8 +46,8 @@ export type CoreHTTPFunction = {
|
|
|
46
46
|
/**
|
|
47
47
|
* Represents a http interaction within Pikku, including a request and response.
|
|
48
48
|
*/
|
|
49
|
-
export interface PikkuHTTP {
|
|
50
|
-
request?: PikkuHTTPRequest
|
|
49
|
+
export interface PikkuHTTP<In = unknown> {
|
|
50
|
+
request?: PikkuHTTPRequest<In>;
|
|
51
51
|
response?: PikkuHTTPResponse;
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
@@ -169,12 +169,12 @@ export interface PikkuHTTPRequest<In = unknown> {
|
|
|
169
169
|
setParams(params: Record<string, string | string[] | undefined>): void;
|
|
170
170
|
query(): PikkuQuery;
|
|
171
171
|
}
|
|
172
|
-
export interface PikkuHTTPResponse {
|
|
172
|
+
export interface PikkuHTTPResponse<Out = unknown> {
|
|
173
173
|
status(code: number): this;
|
|
174
174
|
cookie(name: string, value: string | null, options: SerializeOptions): this;
|
|
175
175
|
header(name: string, value: string | string[]): this;
|
|
176
176
|
arrayBuffer(data: ArrayBuffer | ArrayBufferView | Blob | string | FormData | URLSearchParams | ReadableStream): this;
|
|
177
|
-
json(data:
|
|
177
|
+
json(data: Out): this;
|
|
178
178
|
redirect(location: string, status?: number): this;
|
|
179
179
|
close?: () => void;
|
|
180
180
|
setMode?: (mode: 'stream') => void;
|
|
@@ -4,7 +4,7 @@ import { pikkuState } from '../../pikku-state.js';
|
|
|
4
4
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js';
|
|
5
5
|
import { rpcService } from '../rpc/rpc-runner.js';
|
|
6
6
|
import { BadRequestError, NotFoundError } from '../../errors/errors.js';
|
|
7
|
-
import {
|
|
7
|
+
import { combineMiddleware, runMiddleware } from '../../middleware-runner.js';
|
|
8
8
|
export class MCPError extends Error {
|
|
9
9
|
error;
|
|
10
10
|
constructor(error) {
|
|
@@ -139,8 +139,13 @@ async function runMCPPikkuFunc(request, type, name, mcp, pikkuFuncName, { sessio
|
|
|
139
139
|
tags: mcp.tags,
|
|
140
140
|
});
|
|
141
141
|
};
|
|
142
|
-
|
|
143
|
-
await runMiddleware(singletonServices, { mcp: interaction },
|
|
142
|
+
const funcConfig = pikkuState('function', 'functions').get(pikkuFuncName);
|
|
143
|
+
await runMiddleware(singletonServices, { mcp: interaction }, combineMiddleware({
|
|
144
|
+
wiringMiddleware: mcp.middleware,
|
|
145
|
+
wiringTags: mcp.tags,
|
|
146
|
+
funcMiddleware: funcConfig?.middleware,
|
|
147
|
+
funcTags: funcConfig?.tags,
|
|
148
|
+
}), runMain);
|
|
144
149
|
return {
|
|
145
150
|
id: request.id,
|
|
146
151
|
result,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getErrorResponse, PikkuError } from '../../errors/error-handler.js';
|
|
2
2
|
import { pikkuState } from '../../pikku-state.js';
|
|
3
3
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js';
|
|
4
|
-
import {
|
|
4
|
+
import { combineMiddleware, runMiddleware } from '../../middleware-runner.js';
|
|
5
5
|
/**
|
|
6
6
|
* Error class for queue processor not found
|
|
7
7
|
*/
|
|
@@ -113,8 +113,15 @@ export async function runQueueJob({ singletonServices, createSessionServices, jo
|
|
|
113
113
|
});
|
|
114
114
|
logger.debug(`Successfully processed job ${job.id} in queue ${job.queueName}`);
|
|
115
115
|
};
|
|
116
|
+
// Get function config for middleware and tags
|
|
117
|
+
const funcConfig = pikkuState('function', 'functions').get(processorMeta.pikkuFuncName);
|
|
116
118
|
// Get middleware for tags and combine with queue-specific middleware
|
|
117
|
-
await runMiddleware(singletonServices, { queue },
|
|
119
|
+
await runMiddleware(singletonServices, { queue }, combineMiddleware({
|
|
120
|
+
wiringMiddleware: queueWorker.middleware,
|
|
121
|
+
wiringTags: queueWorker.tags,
|
|
122
|
+
funcMiddleware: funcConfig?.middleware,
|
|
123
|
+
funcTags: funcConfig?.tags,
|
|
124
|
+
}), runMain);
|
|
118
125
|
return result;
|
|
119
126
|
}
|
|
120
127
|
catch (error) {
|
|
@@ -13,13 +13,12 @@ export declare class PikkuRPCService {
|
|
|
13
13
|
};
|
|
14
14
|
logger: import("../../index.js").Logger;
|
|
15
15
|
variables: import("../../services/variables-service.js").VariablesService;
|
|
16
|
-
http?: import("../http/http.types.js").PikkuHTTP | undefined;
|
|
16
|
+
http?: import("../http/http.types.js").PikkuHTTP<unknown> | undefined;
|
|
17
17
|
mcp?: import("../mcp/mcp.types.js").PikkuMCP;
|
|
18
18
|
rpc?: import("./rpc-types.js").PikkuRPC;
|
|
19
19
|
channel?: import("../channel/channel.types.js").PikkuChannel<unknown, unknown>;
|
|
20
20
|
scheduledTask?: import("../scheduler/scheduler.types.js").PikkuScheduledTask | undefined;
|
|
21
21
|
queue?: import("../queue/queue.types.js").PikkuQueue | undefined;
|
|
22
|
-
s?: any;
|
|
23
22
|
userSession?: import("../../index.js").UserSessionService<import("../../types/core.types.js").CoreUserSession> | undefined;
|
|
24
23
|
};
|
|
25
24
|
}
|
|
@@ -3,7 +3,7 @@ import { closeSessionServices } from '../../utils.js';
|
|
|
3
3
|
import { pikkuState } from '../../pikku-state.js';
|
|
4
4
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js';
|
|
5
5
|
import { rpcService } from '../rpc/rpc-runner.js';
|
|
6
|
-
import {
|
|
6
|
+
import { combineMiddleware, runMiddleware } from '../../middleware-runner.js';
|
|
7
7
|
export const wireScheduler = (scheduledTask) => {
|
|
8
8
|
const meta = pikkuState('scheduler', 'meta');
|
|
9
9
|
const taskMeta = meta[scheduledTask.name];
|
|
@@ -70,8 +70,13 @@ export async function runScheduledTask({ name, session, singletonServices, creat
|
|
|
70
70
|
tags: task.tags,
|
|
71
71
|
});
|
|
72
72
|
};
|
|
73
|
-
|
|
74
|
-
await runMiddleware(singletonServices, { scheduledTask },
|
|
73
|
+
const funcConfig = pikkuState('function', 'functions').get(meta.pikkuFuncName);
|
|
74
|
+
await runMiddleware(singletonServices, { scheduledTask }, combineMiddleware({
|
|
75
|
+
wiringMiddleware: task.middleware,
|
|
76
|
+
wiringTags: task.tags,
|
|
77
|
+
funcMiddleware: funcConfig?.middleware,
|
|
78
|
+
funcTags: funcConfig?.tags,
|
|
79
|
+
}), runMain);
|
|
75
80
|
return result;
|
|
76
81
|
}
|
|
77
82
|
catch (e) {
|