@pikku/core 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -1
- package/dist/errors/errors.d.ts +1 -1
- package/dist/errors/errors.js +3 -3
- package/dist/function/function-runner.d.ts +6 -7
- package/dist/function/function-runner.js +35 -16
- package/dist/function/functions.types.d.ts +22 -30
- package/dist/function/functions.types.js +9 -6
- package/dist/handle-error.d.ts +1 -1
- package/dist/handle-error.js +1 -1
- package/dist/middleware/auth-apikey.js +3 -3
- package/dist/middleware/auth-bearer.js +3 -3
- package/dist/middleware/auth-cookie.js +5 -5
- package/dist/middleware/timeout.js +3 -2
- package/dist/middleware-runner.d.ts +3 -6
- package/dist/middleware-runner.js +11 -12
- package/dist/permissions.d.ts +6 -6
- package/dist/permissions.js +15 -16
- package/dist/services/user-session-service.d.ts +7 -3
- package/dist/services/user-session-service.js +8 -1
- package/dist/types/core.types.d.ts +29 -38
- package/dist/types/core.types.js +3 -14
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +3 -3
- package/dist/wirings/channel/channel-common.js +2 -3
- package/dist/wirings/channel/channel-handler.d.ts +3 -2
- package/dist/wirings/channel/channel-handler.js +6 -9
- package/dist/wirings/channel/channel-runner.d.ts +2 -2
- package/dist/wirings/channel/channel.types.d.ts +10 -5
- package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-runner.js +19 -26
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +41 -46
- package/dist/wirings/cli/cli-runner.d.ts +5 -5
- package/dist/wirings/cli/cli-runner.js +10 -28
- package/dist/wirings/cli/cli.types.d.ts +15 -11
- package/dist/wirings/http/http-runner.d.ts +6 -6
- package/dist/wirings/http/http-runner.js +25 -39
- package/dist/wirings/http/http.types.d.ts +5 -10
- package/dist/wirings/mcp/mcp-runner.d.ts +2 -2
- package/dist/wirings/mcp/mcp-runner.js +12 -19
- package/dist/wirings/mcp/mcp.types.d.ts +6 -0
- package/dist/wirings/queue/queue-runner.d.ts +3 -3
- package/dist/wirings/queue/queue-runner.js +7 -17
- package/dist/wirings/queue/queue.types.d.ts +4 -11
- package/dist/wirings/rpc/rpc-runner.d.ts +10 -8
- package/dist/wirings/rpc/rpc-runner.js +36 -47
- package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -3
- package/dist/wirings/scheduler/scheduler-runner.js +13 -24
- package/dist/wirings/scheduler/scheduler.types.d.ts +3 -8
- package/dist/wirings/workflow/index.d.ts +11 -2
- package/dist/wirings/workflow/index.js +10 -2
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +12 -4
- package/dist/wirings/workflow/pikku-workflow-service.js +61 -79
- package/dist/wirings/workflow/workflow-runner.d.ts +3 -4
- package/dist/wirings/workflow/workflow-runner.js +11 -14
- package/dist/wirings/workflow/workflow.types.d.ts +114 -29
- package/package.json +2 -2
- package/src/errors/errors.ts +3 -3
- package/src/factory-functions.test.ts +9 -36
- package/src/function/function-runner.test.ts +57 -68
- package/src/function/function-runner.ts +51 -28
- package/src/function/function-runner.ts.bak +188 -0
- package/src/function/functions.types.ts +68 -51
- package/src/handle-error.ts +1 -1
- package/src/middleware/auth-apikey.test.ts +360 -0
- package/src/middleware/auth-apikey.ts +3 -7
- package/src/middleware/auth-bearer.test.ts +447 -0
- package/src/middleware/auth-bearer.ts +27 -33
- package/src/middleware/auth-cookie.test.ts +525 -0
- package/src/middleware/auth-cookie.ts +6 -6
- package/src/middleware/timeout.ts +4 -2
- package/src/middleware-runner.test.ts +58 -127
- package/src/middleware-runner.ts +13 -16
- package/src/permissions.test.ts +41 -45
- package/src/permissions.ts +21 -21
- package/src/services/user-session-service.ts +14 -4
- package/src/types/core.types.ts +67 -55
- package/src/utils.ts +4 -4
- package/src/wirings/channel/channel-common.ts +4 -7
- package/src/wirings/channel/channel-handler.ts +16 -22
- package/src/wirings/channel/channel-runner.ts +2 -2
- package/src/wirings/channel/channel.types.ts +14 -11
- package/src/wirings/channel/local/local-channel-runner.test.ts +5 -3
- package/src/wirings/channel/local/local-channel-runner.ts +23 -38
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +51 -77
- package/src/wirings/cli/cli-runner.test.ts +7 -7
- package/src/wirings/cli/cli-runner.ts +24 -62
- package/src/wirings/cli/cli.types.ts +22 -16
- package/src/wirings/http/http-runner.test.ts +8 -8
- package/src/wirings/http/http-runner.ts +29 -56
- package/src/wirings/http/http.types.ts +5 -14
- package/src/wirings/mcp/mcp-runner.ts +23 -48
- package/src/wirings/mcp/mcp.types.ts +6 -0
- package/src/wirings/queue/queue-runner.test.ts +641 -0
- package/src/wirings/queue/queue-runner.ts +10 -32
- package/src/wirings/queue/queue.types.ts +4 -11
- package/src/wirings/rpc/rpc-runner.ts +41 -55
- package/src/wirings/scheduler/scheduler-runner.test.ts +627 -0
- package/src/wirings/scheduler/scheduler-runner.ts +24 -50
- package/src/wirings/scheduler/scheduler.types.ts +3 -9
- package/src/wirings/workflow/index.ts +24 -3
- package/src/wirings/workflow/pikku-workflow-service.ts +83 -93
- package/src/wirings/workflow/workflow-runner.ts +12 -25
- package/src/wirings/workflow/workflow.types.ts +144 -54
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
## 0.11.0
|
|
2
2
|
|
|
3
|
+
## 0.11.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4b811db: chore: updating all dependencies
|
|
8
|
+
- e12a00c: feat: adding initialSession to PikkuWire which is correctly typed (undefined / not depending on function type)
|
|
9
|
+
- 4579434: breaking: changing the signature of functions
|
|
10
|
+
- 28aeb7f: breaking: extract docs in the wiring meta
|
|
11
|
+
- ce902b1: feat: adding in pikkuSimpleWorkflowFunc
|
|
12
|
+
- 06e1a31: breaking: change session services to wire services
|
|
13
|
+
|
|
3
14
|
### Minor Changes
|
|
4
15
|
|
|
5
16
|
- Add workflow orchestration engine with step execution and retries
|
|
6
17
|
- Add scheduler service abstraction
|
|
7
18
|
- Remove file-based channel and eventhub stores
|
|
8
19
|
|
|
9
|
-
|
|
10
20
|
# @pikku/core
|
|
11
21
|
|
|
12
22
|
## 0.10.2
|
package/dist/errors/errors.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The server cannot or will not process the request due to client error (e.g., malformed request syntax).
|
|
3
3
|
*/
|
|
4
4
|
import { PikkuError } from './error-handler.js';
|
|
5
|
-
export declare class
|
|
5
|
+
export declare class InvalidMiddlewareWireError extends PikkuError {
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* The server cannot or will not process the request due to client error (e.g., malformed request syntax).
|
package/dist/errors/errors.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* The server cannot or will not process the request due to client error (e.g., malformed request syntax).
|
|
3
3
|
*/
|
|
4
4
|
import { addError, PikkuError } from './error-handler.js';
|
|
5
|
-
export class
|
|
5
|
+
export class InvalidMiddlewareWireError extends PikkuError {
|
|
6
6
|
}
|
|
7
|
-
addError(
|
|
7
|
+
addError(InvalidMiddlewareWireError, {
|
|
8
8
|
status: 500,
|
|
9
|
-
message: 'The middleware
|
|
9
|
+
message: 'The middleware wire is invalid for the current wiring type.',
|
|
10
10
|
});
|
|
11
11
|
/**
|
|
12
12
|
* The server cannot or will not process the request due to client error (e.g., malformed request syntax).
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { CoreServices, CoreUserSession, CorePikkuMiddleware, PikkuWiringTypes,
|
|
1
|
+
import { CoreServices, CoreUserSession, CorePikkuMiddleware, PikkuWiringTypes, PikkuWire, MiddlewareMetadata, PermissionMetadata, CoreSingletonServices, CreateWireServices } from '../types/core.types.js';
|
|
2
2
|
import { CorePermissionGroup, CorePikkuFunctionConfig, CorePikkuPermission } from './functions.types.js';
|
|
3
|
-
import {
|
|
3
|
+
import { SessionService } from '../services/user-session-service.js';
|
|
4
4
|
export declare const addFunction: (funcName: string, funcConfig: CorePikkuFunctionConfig<any, any>) => void;
|
|
5
|
-
export declare const runPikkuFuncDirectly: <In, Out>(funcName: string, allServices: CoreServices, data: In,
|
|
6
|
-
export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, {
|
|
5
|
+
export declare const runPikkuFuncDirectly: <In, Out>(funcName: string, allServices: CoreServices, wire: PikkuWire, data: In, userSession?: SessionService<CoreUserSession>) => Promise<Out>;
|
|
6
|
+
export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags, wire, }: {
|
|
7
7
|
singletonServices: CoreSingletonServices;
|
|
8
|
-
|
|
9
|
-
userSession?: UserSessionService<CoreUserSession>;
|
|
8
|
+
createWireServices?: CreateWireServices;
|
|
10
9
|
data: () => Promise<In> | In;
|
|
11
10
|
auth?: boolean;
|
|
12
11
|
inheritedMiddleware?: MiddlewareMetadata[];
|
|
@@ -15,5 +14,5 @@ export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTy
|
|
|
15
14
|
wirePermissions?: CorePermissionGroup | CorePikkuPermission[];
|
|
16
15
|
coerceDataFromSchema?: boolean;
|
|
17
16
|
tags?: string[];
|
|
18
|
-
|
|
17
|
+
wire: PikkuWire;
|
|
19
18
|
}) => Promise<Out>;
|
|
@@ -3,17 +3,24 @@ import { runPermissions } from '../permissions.js';
|
|
|
3
3
|
import { pikkuState } from '../pikku-state.js';
|
|
4
4
|
import { coerceTopLevelDataFromSchema, validateSchema } from '../schema.js';
|
|
5
5
|
import { ForbiddenError } from '../errors/errors.js';
|
|
6
|
+
import { rpcService } from '../wirings/rpc/rpc-runner.js';
|
|
7
|
+
import { closeWireServices } from '../utils.js';
|
|
6
8
|
export const addFunction = (funcName, funcConfig) => {
|
|
7
9
|
pikkuState('function', 'functions').set(funcName, funcConfig);
|
|
8
10
|
};
|
|
9
|
-
export const runPikkuFuncDirectly = async (funcName, allServices, data,
|
|
11
|
+
export const runPikkuFuncDirectly = async (funcName, allServices, wire, data, userSession) => {
|
|
10
12
|
const funcConfig = pikkuState('function', 'functions').get(funcName);
|
|
11
13
|
if (!funcConfig) {
|
|
12
14
|
throw new Error(`Function not found: ${funcName}`);
|
|
13
15
|
}
|
|
14
|
-
|
|
16
|
+
// Inject session into wire
|
|
17
|
+
const wireWithSession = {
|
|
18
|
+
...wire,
|
|
19
|
+
session: userSession,
|
|
20
|
+
};
|
|
21
|
+
return (await funcConfig.func(allServices, data, wireWithSession));
|
|
15
22
|
};
|
|
16
|
-
export const runPikkuFunc = async (wireType, wireId, funcName, {
|
|
23
|
+
export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags = [], wire, }) => {
|
|
17
24
|
const funcConfig = pikkuState('function', 'functions').get(funcName);
|
|
18
25
|
if (!funcConfig) {
|
|
19
26
|
throw new Error(`Function not found: ${funcName}`);
|
|
@@ -29,16 +36,21 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices,
|
|
|
29
36
|
];
|
|
30
37
|
// Helper function to run permissions and execute the function
|
|
31
38
|
const executeFunction = async () => {
|
|
32
|
-
const
|
|
39
|
+
const initialSession = wire.session?.freezeInitial();
|
|
40
|
+
const wireWithInitialSession = {
|
|
41
|
+
...wire,
|
|
42
|
+
initialSession,
|
|
43
|
+
};
|
|
33
44
|
if (wiringAuth === true || funcConfig.auth === true) {
|
|
34
45
|
// This means it was explicitly enabled in either wiring or function and has to be respected
|
|
35
|
-
if (!
|
|
46
|
+
if (!initialSession) {
|
|
36
47
|
throw new ForbiddenError('Authentication required');
|
|
37
48
|
}
|
|
38
49
|
}
|
|
39
50
|
if (wiringAuth === undefined && funcConfig.auth === undefined) {
|
|
40
51
|
// We always default to requiring auth unless explicitly disabled
|
|
41
|
-
if (!
|
|
52
|
+
if (!initialSession) {
|
|
53
|
+
// TODO: Critical, we need to figure out how to make this work with different wirings
|
|
42
54
|
// throw new ForbiddenError('Authentication required')
|
|
43
55
|
}
|
|
44
56
|
}
|
|
@@ -54,20 +66,30 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices,
|
|
|
54
66
|
coerceTopLevelDataFromSchema(inputSchemaName, actualData);
|
|
55
67
|
}
|
|
56
68
|
}
|
|
57
|
-
const allServices = await getAllServices(session);
|
|
58
|
-
// Run permissions check with combined permissions: inheritedPermissions (including tags) → wirePermissions → funcPermissions
|
|
59
69
|
await runPermissions(wireType, wireId, {
|
|
60
70
|
wireInheritedPermissions: mergedInheritedPermissions,
|
|
61
71
|
wirePermissions: wirePermissions,
|
|
62
72
|
funcInheritedPermissions: funcMeta.permissions,
|
|
63
73
|
funcPermissions: funcConfig.permissions,
|
|
64
|
-
|
|
74
|
+
services: singletonServices,
|
|
75
|
+
wire: { ...wireWithInitialSession, rpc: undefined },
|
|
65
76
|
data: actualData,
|
|
66
|
-
session,
|
|
67
77
|
});
|
|
68
|
-
|
|
78
|
+
const wireServices = await createWireServices?.(singletonServices, wireWithInitialSession);
|
|
79
|
+
try {
|
|
80
|
+
const services = { ...singletonServices, ...wireServices };
|
|
81
|
+
const rpc = rpcService.getContextRPCService(services, wireWithInitialSession);
|
|
82
|
+
return await funcConfig.func(services, actualData, {
|
|
83
|
+
...wireWithInitialSession,
|
|
84
|
+
rpc,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
if (wireServices) {
|
|
89
|
+
await closeWireServices(singletonServices.logger, wireServices);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
69
92
|
};
|
|
70
|
-
// Combine all middleware: inheritedMiddleware → wireMiddleware → funcMiddleware
|
|
71
93
|
const allMiddleware = combineMiddleware(wireType, wireId, {
|
|
72
94
|
wireInheritedMiddleware: inheritedMiddleware,
|
|
73
95
|
wireMiddleware,
|
|
@@ -75,10 +97,7 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices,
|
|
|
75
97
|
funcMiddleware: funcConfig.middleware,
|
|
76
98
|
});
|
|
77
99
|
if (allMiddleware.length > 0) {
|
|
78
|
-
return (await runMiddleware(
|
|
79
|
-
...singletonServices,
|
|
80
|
-
userSession,
|
|
81
|
-
}, interaction, allMiddleware, executeFunction));
|
|
100
|
+
return (await runMiddleware(singletonServices, wire, allMiddleware, executeFunction));
|
|
82
101
|
}
|
|
83
102
|
return (await executeFunction());
|
|
84
103
|
};
|
|
@@ -1,33 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import type { CoreServices, CoreSingletonServices, CoreUserSession, CorePikkuMiddleware, PikkuWire, PickRequired } from '../types/core.types.js';
|
|
2
|
+
import { Session } from 'inspector';
|
|
3
3
|
/**
|
|
4
4
|
* Represents a core API function that performs an operation using core services and a user session.
|
|
5
5
|
*
|
|
6
6
|
* @template In - The input type.
|
|
7
7
|
* @template Out - The output type.
|
|
8
|
-
* @template ChannelData - The channel data type.
|
|
9
8
|
* @template Services - The services type, defaults to `CoreServices`.
|
|
10
|
-
* @template
|
|
9
|
+
* @template Wire - The wire type, defaults to `PikkuWire<In, Out>`.
|
|
11
10
|
*/
|
|
12
|
-
export type CorePikkuFunction<In, Out,
|
|
13
|
-
channel?: PikkuChannel<unknown, Out> | undefined;
|
|
14
|
-
} : {
|
|
15
|
-
channel: PikkuChannel<ChannelData, Out>;
|
|
16
|
-
}), Session extends CoreUserSession = CoreUserSession> = (services: Services, data: In, session: Session) => ChannelData extends null ? Promise<Out> : Promise<Out> | Promise<void>;
|
|
11
|
+
export type CorePikkuFunction<In, Out, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, Out> = PikkuWire<In, Out, true, Session>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
|
|
17
12
|
/**
|
|
18
13
|
* Represents a core API function that can be used without a session.
|
|
19
14
|
*
|
|
20
15
|
* @template In - The input type.
|
|
21
16
|
* @template Out - The output type.
|
|
22
|
-
* @template ChannelData - The channel data type.
|
|
23
17
|
* @template Services - The services type, defaults to `CoreServices`.
|
|
24
|
-
* @template
|
|
18
|
+
* @template Wire - The wire type, defaults to `PikkuWire<In, Out>`.
|
|
25
19
|
*/
|
|
26
|
-
export type CorePikkuFunctionSessionless<In, Out,
|
|
27
|
-
channel?: PikkuChannel<unknown, Out> | undefined;
|
|
28
|
-
} : {
|
|
29
|
-
channel: PikkuChannel<ChannelData, Out>;
|
|
30
|
-
}), Session extends CoreUserSession = CoreUserSession> = (services: Services, data: In, session?: Session) => ChannelData extends null ? Promise<Out> : Promise<Out> | Promise<void>;
|
|
20
|
+
export type CorePikkuFunctionSessionless<In, Out, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, Out, false, CoreUserSession, any, any, any> = PikkuWire<In, Out, false, CoreUserSession, any, any, any>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
|
|
31
21
|
/**
|
|
32
22
|
* Represents a function that checks permissions for a given operation.
|
|
33
23
|
*
|
|
@@ -35,7 +25,7 @@ export type CorePikkuFunctionSessionless<In, Out, ChannelData extends unknown |
|
|
|
35
25
|
* @template Services - The services type, defaults to `CoreServices`.
|
|
36
26
|
* @template Session - The session type, defaults to `CoreUserSession`.
|
|
37
27
|
*/
|
|
38
|
-
export type CorePikkuPermission<In = any, Services extends CoreSingletonServices = CoreServices,
|
|
28
|
+
export type CorePikkuPermission<In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, never, false, CoreUserSession, any, never, never> = PikkuWire<In, never, false, CoreUserSession, never, never, never>> = (services: Services, data: In, wire: Wire) => Promise<boolean>;
|
|
39
29
|
/**
|
|
40
30
|
* Configuration object for creating a permission with metadata
|
|
41
31
|
*
|
|
@@ -43,9 +33,9 @@ export type CorePikkuPermission<In = any, Services extends CoreSingletonServices
|
|
|
43
33
|
* @template Services - The services type, defaults to `CoreServices`.
|
|
44
34
|
* @template Session - The session type, defaults to `CoreUserSession`.
|
|
45
35
|
*/
|
|
46
|
-
export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonServices = CoreServices,
|
|
36
|
+
export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, never, false, CoreUserSession> = PikkuWire<In, never, false, CoreUserSession>> = {
|
|
47
37
|
/** The permission function */
|
|
48
|
-
func: CorePikkuPermission<In, Services,
|
|
38
|
+
func: CorePikkuPermission<In, Services, Wire>;
|
|
49
39
|
/** Optional human-readable name for the permission */
|
|
50
40
|
name?: string;
|
|
51
41
|
/** Optional description of what the permission checks */
|
|
@@ -59,8 +49,9 @@ export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonSe
|
|
|
59
49
|
* ```typescript
|
|
60
50
|
* // Direct function syntax
|
|
61
51
|
* export const adminPermission = pikkuPermission(
|
|
62
|
-
* async ({ logger },
|
|
63
|
-
*
|
|
52
|
+
* async ({ logger }, _data, { session }) => {
|
|
53
|
+
* const currentSession = await session.get()
|
|
54
|
+
* return currentSession?.role === 'admin'
|
|
64
55
|
* }
|
|
65
56
|
* )
|
|
66
57
|
*
|
|
@@ -68,13 +59,14 @@ export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonSe
|
|
|
68
59
|
* export const adminPermission = pikkuPermission({
|
|
69
60
|
* name: 'Admin Permission',
|
|
70
61
|
* description: 'Checks if user has admin role',
|
|
71
|
-
* func: async ({ logger },
|
|
72
|
-
*
|
|
62
|
+
* func: async ({ logger }, _data, { session }) => {
|
|
63
|
+
* const currentSession = await session.get()
|
|
64
|
+
* return currentSession?.role === 'admin'
|
|
73
65
|
* }
|
|
74
66
|
* })
|
|
75
67
|
* ```
|
|
76
68
|
*/
|
|
77
|
-
export declare const pikkuPermission: <In = any, Services extends CoreSingletonServices = CoreServices,
|
|
69
|
+
export declare const pikkuPermission: <In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PickRequired<PikkuWire<In, never, false, CoreUserSession>, "session"> = PickRequired<PikkuWire<In, never, false, CoreUserSession>, "session">>(permission: CorePikkuPermission<In, Services, Wire> | CorePikkuPermissionConfig<In, Services, Wire>) => CorePikkuPermission<In, Services, Wire>;
|
|
78
70
|
/**
|
|
79
71
|
* A factory function that takes input and returns a permission
|
|
80
72
|
* Used when permissions need configuration/input parameters
|
|
@@ -83,7 +75,7 @@ export declare const pikkuPermission: <In = any, Services extends CoreSingletonS
|
|
|
83
75
|
* @template Services - The services type, defaults to `CoreServices`.
|
|
84
76
|
* @template Session - The session type, defaults to `CoreUserSession`.
|
|
85
77
|
*/
|
|
86
|
-
export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonServices = CoreServices,
|
|
78
|
+
export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, never, false, CoreUserSession> = PikkuWire<In, never, false, CoreUserSession>> = (input: In) => CorePikkuPermission<any, Services, Wire>;
|
|
87
79
|
/**
|
|
88
80
|
* Factory function for creating permission factories
|
|
89
81
|
* Use this when your permission needs configuration/input parameters
|
|
@@ -93,8 +85,9 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
|
|
|
93
85
|
* export const requireRole = pikkuPermissionFactory<{ role: string }>(({
|
|
94
86
|
* role
|
|
95
87
|
* }) => {
|
|
96
|
-
* return pikkuPermission(async ({ logger }, data, session) => {
|
|
97
|
-
*
|
|
88
|
+
* return pikkuPermission(async ({ logger }, data, { session }) => {
|
|
89
|
+
* const currentSession = await session.get()
|
|
90
|
+
* if (!currentSession || currentSession.role !== role) {
|
|
98
91
|
* logger.warn(`Permission denied: required role '${role}'`)
|
|
99
92
|
* return false
|
|
100
93
|
* }
|
|
@@ -105,14 +98,13 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
|
|
|
105
98
|
*/
|
|
106
99
|
export declare const pikkuPermissionFactory: <In = any>(factory: CorePikkuPermissionFactory<In>) => CorePikkuPermissionFactory<In>;
|
|
107
100
|
export type CorePermissionGroup<PikkuPermission = CorePikkuPermission<any>> = Record<string, PikkuPermission | PikkuPermission[]> | undefined;
|
|
108
|
-
export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any, any, any, any
|
|
101
|
+
export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any, any, any, any> | CorePikkuFunctionSessionless<any, any, any, any>, PikkuPermission extends CorePikkuPermission<any, any, any> = CorePikkuPermission<any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>> = {
|
|
109
102
|
name?: string;
|
|
103
|
+
tags?: string[];
|
|
110
104
|
expose?: boolean;
|
|
111
105
|
internal?: boolean;
|
|
112
106
|
func: PikkuFunction;
|
|
113
107
|
auth?: boolean;
|
|
114
108
|
permissions?: CorePermissionGroup<PikkuPermission>;
|
|
115
109
|
middleware?: PikkuMiddleware[];
|
|
116
|
-
tags?: string[];
|
|
117
|
-
docs?: PikkuDocs;
|
|
118
110
|
};
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* ```typescript
|
|
7
7
|
* // Direct function syntax
|
|
8
8
|
* export const adminPermission = pikkuPermission(
|
|
9
|
-
* async ({ logger },
|
|
10
|
-
*
|
|
9
|
+
* async ({ logger }, _data, { session }) => {
|
|
10
|
+
* const currentSession = await session.get()
|
|
11
|
+
* return currentSession?.role === 'admin'
|
|
11
12
|
* }
|
|
12
13
|
* )
|
|
13
14
|
*
|
|
@@ -15,8 +16,9 @@
|
|
|
15
16
|
* export const adminPermission = pikkuPermission({
|
|
16
17
|
* name: 'Admin Permission',
|
|
17
18
|
* description: 'Checks if user has admin role',
|
|
18
|
-
* func: async ({ logger },
|
|
19
|
-
*
|
|
19
|
+
* func: async ({ logger }, _data, { session }) => {
|
|
20
|
+
* const currentSession = await session.get()
|
|
21
|
+
* return currentSession?.role === 'admin'
|
|
20
22
|
* }
|
|
21
23
|
* })
|
|
22
24
|
* ```
|
|
@@ -33,8 +35,9 @@ export const pikkuPermission = (permission) => {
|
|
|
33
35
|
* export const requireRole = pikkuPermissionFactory<{ role: string }>(({
|
|
34
36
|
* role
|
|
35
37
|
* }) => {
|
|
36
|
-
* return pikkuPermission(async ({ logger }, data, session) => {
|
|
37
|
-
*
|
|
38
|
+
* return pikkuPermission(async ({ logger }, data, { session }) => {
|
|
39
|
+
* const currentSession = await session.get()
|
|
40
|
+
* if (!currentSession || currentSession.role !== role) {
|
|
38
41
|
* logger.warn(`Permission denied: required role '${role}'`)
|
|
39
42
|
* return false
|
|
40
43
|
* }
|
package/dist/handle-error.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { PikkuHTTP } from './wirings/http/http.types.js';
|
|
|
4
4
|
* Handle errors that occur during route processing
|
|
5
5
|
*
|
|
6
6
|
* @param {any} e - The error that occurred
|
|
7
|
-
* @param {PikkuHTTP | undefined} http - HTTP
|
|
7
|
+
* @param {PikkuHTTP | undefined} http - HTTP wire object
|
|
8
8
|
* @param {string} trackerId - Unique ID for tracking this error
|
|
9
9
|
* @param {Logger} logger - Logger service
|
|
10
10
|
* @param {number[]} logWarningsForStatusCodes - HTTP status codes to log as warnings
|
package/dist/handle-error.js
CHANGED
|
@@ -4,7 +4,7 @@ import { NotFoundError } from './errors/errors.js';
|
|
|
4
4
|
* Handle errors that occur during route processing
|
|
5
5
|
*
|
|
6
6
|
* @param {any} e - The error that occurred
|
|
7
|
-
* @param {PikkuHTTP | undefined} http - HTTP
|
|
7
|
+
* @param {PikkuHTTP | undefined} http - HTTP wire object
|
|
8
8
|
* @param {string} trackerId - Unique ID for tracking this error
|
|
9
9
|
* @param {Logger} logger - Logger service
|
|
10
10
|
* @param {number[]} logWarningsForStatusCodes - HTTP status codes to log as warnings
|
|
@@ -16,8 +16,8 @@ import { pikkuMiddleware, pikkuMiddlewareFactory } from '../types/core.types.js'
|
|
|
16
16
|
* ])
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
-
export const authAPIKey = pikkuMiddlewareFactory(({ source }) => pikkuMiddleware(async ({
|
|
20
|
-
if (!http?.request ||
|
|
19
|
+
export const authAPIKey = pikkuMiddlewareFactory(({ source }) => pikkuMiddleware(async ({ jwt: jwtService }, { http, session: SessionService }, next) => {
|
|
20
|
+
if (!http?.request || !SessionService || SessionService.get()) {
|
|
21
21
|
return next();
|
|
22
22
|
}
|
|
23
23
|
let apiKey = null;
|
|
@@ -30,7 +30,7 @@ export const authAPIKey = pikkuMiddlewareFactory(({ source }) => pikkuMiddleware
|
|
|
30
30
|
if (apiKey && jwtService) {
|
|
31
31
|
const userSession = await jwtService.decode(apiKey);
|
|
32
32
|
if (userSession) {
|
|
33
|
-
|
|
33
|
+
SessionService.setInitial(userSession);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
return next();
|
|
@@ -29,9 +29,9 @@ import { pikkuMiddleware, pikkuMiddlewareFactory, } from '../types/core.types.js
|
|
|
29
29
|
* ])
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
|
-
export const authBearer = pikkuMiddlewareFactory(({ token } = {}) => pikkuMiddleware(async ({
|
|
32
|
+
export const authBearer = pikkuMiddlewareFactory(({ token } = {}) => pikkuMiddleware(async ({ jwt: jwtService }, { http, session }, next) => {
|
|
33
33
|
// Skip if session already exists.
|
|
34
|
-
if (!http?.request ||
|
|
34
|
+
if (!http?.request || !session || session.get()) {
|
|
35
35
|
return next();
|
|
36
36
|
}
|
|
37
37
|
const authHeader = http.request.header('authorization') ||
|
|
@@ -51,7 +51,7 @@ export const authBearer = pikkuMiddlewareFactory(({ token } = {}) => pikkuMiddle
|
|
|
51
51
|
userSession = await jwtService.decode(bearerToken);
|
|
52
52
|
}
|
|
53
53
|
if (userSession) {
|
|
54
|
-
|
|
54
|
+
session.setInitial(userSession);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
return next();
|
|
@@ -28,8 +28,8 @@ import { getRelativeTimeOffsetFromNow, } from '../time-utils.js';
|
|
|
28
28
|
* ])
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
|
-
export const authCookie = pikkuMiddlewareFactory(({ name, options, expiresIn }) => pikkuMiddleware(async ({
|
|
32
|
-
if (!http?.request ||
|
|
31
|
+
export const authCookie = pikkuMiddlewareFactory(({ name, options, expiresIn }) => pikkuMiddleware(async ({ jwt: jwtService, logger }, { http, session: SessionService }, next) => {
|
|
32
|
+
if (!http?.request || !SessionService || SessionService.get()) {
|
|
33
33
|
return next();
|
|
34
34
|
}
|
|
35
35
|
// Try to decode session from cookie
|
|
@@ -37,7 +37,7 @@ export const authCookie = pikkuMiddlewareFactory(({ name, options, expiresIn })
|
|
|
37
37
|
if (cookieValue && jwtService) {
|
|
38
38
|
const userSession = await jwtService.decode(cookieValue);
|
|
39
39
|
if (userSession) {
|
|
40
|
-
|
|
40
|
+
SessionService.setInitial(userSession);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
await next();
|
|
@@ -45,8 +45,8 @@ export const authCookie = pikkuMiddlewareFactory(({ name, options, expiresIn })
|
|
|
45
45
|
if (!http?.response) {
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
|
-
if (
|
|
49
|
-
const session =
|
|
48
|
+
if (SessionService.sessionChanged) {
|
|
49
|
+
const session = SessionService.get();
|
|
50
50
|
if (jwtService) {
|
|
51
51
|
http.response.cookie(name, await jwtService.encode(expiresIn, session), {
|
|
52
52
|
...options,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { RequestTimeoutError } from '../errors/errors.js';
|
|
2
2
|
import { pikkuMiddleware, pikkuMiddlewareFactory } from '../types/core.types.js';
|
|
3
|
-
export const timeout = () => pikkuMiddlewareFactory(({ timeout }) => pikkuMiddleware(async (_services,
|
|
4
|
-
setTimeout(() => {
|
|
3
|
+
export const timeout = () => pikkuMiddlewareFactory(({ timeout }) => pikkuMiddleware(async (_services, _wire, next) => {
|
|
4
|
+
const timeoutId = setTimeout(() => {
|
|
5
5
|
throw new RequestTimeoutError();
|
|
6
6
|
}, timeout);
|
|
7
7
|
await next();
|
|
8
|
+
clearTimeout(timeoutId);
|
|
8
9
|
}));
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CoreSingletonServices, PikkuInteraction, CorePikkuMiddleware, CorePikkuMiddlewareGroup, PikkuWiringTypes, MiddlewareMetadata } from './types/core.types.js';
|
|
1
|
+
import { CoreSingletonServices, PikkuWire, CorePikkuMiddleware, CorePikkuMiddlewareGroup, PikkuWiringTypes, MiddlewareMetadata } from './types/core.types.js';
|
|
3
2
|
/**
|
|
4
3
|
* Runs a chain of middleware functions in sequence before executing the main function.
|
|
5
4
|
*
|
|
6
5
|
* @param services - An object containing services (e.g., singletonServices, userSession, etc.)
|
|
7
|
-
* @param
|
|
6
|
+
* @param wire - The wire context, e.g., { http }.
|
|
8
7
|
* @param middlewares - An array of middleware functions to run.
|
|
9
8
|
* @param main - The main function to execute after all middleware have run.
|
|
10
9
|
* @returns A promise resolving to the result of the main function.
|
|
@@ -17,9 +16,7 @@ import { CoreSingletonServices, PikkuInteraction, CorePikkuMiddleware, CorePikku
|
|
|
17
16
|
* async () => { return await runMain(); }
|
|
18
17
|
* );
|
|
19
18
|
*/
|
|
20
|
-
export declare const runMiddleware: <Middleware extends CorePikkuMiddleware>(services: CoreSingletonServices
|
|
21
|
-
userSession?: UserSessionService<any>;
|
|
22
|
-
}, interaction: PikkuInteraction, middlewares: readonly Middleware[], main?: () => Promise<unknown>) => Promise<unknown>;
|
|
19
|
+
export declare const runMiddleware: <Middleware extends CorePikkuMiddleware>(services: CoreSingletonServices, wire: PikkuWire, middlewares: readonly Middleware[], main?: () => Promise<unknown>) => Promise<unknown>;
|
|
23
20
|
/**
|
|
24
21
|
* Registers global middleware for a specific tag.
|
|
25
22
|
*
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { PikkuWiringTypes, } from './types/core.types.js';
|
|
2
1
|
import { pikkuState } from './pikku-state.js';
|
|
3
2
|
import { freezeDedupe } from './utils.js';
|
|
4
3
|
/**
|
|
5
4
|
* Runs a chain of middleware functions in sequence before executing the main function.
|
|
6
5
|
*
|
|
7
6
|
* @param services - An object containing services (e.g., singletonServices, userSession, etc.)
|
|
8
|
-
* @param
|
|
7
|
+
* @param wire - The wire context, e.g., { http }.
|
|
9
8
|
* @param middlewares - An array of middleware functions to run.
|
|
10
9
|
* @param main - The main function to execute after all middleware have run.
|
|
11
10
|
* @returns A promise resolving to the result of the main function.
|
|
@@ -18,12 +17,12 @@ import { freezeDedupe } from './utils.js';
|
|
|
18
17
|
* async () => { return await runMain(); }
|
|
19
18
|
* );
|
|
20
19
|
*/
|
|
21
|
-
export const runMiddleware = async (services,
|
|
20
|
+
export const runMiddleware = async (services, wire, middlewares, main) => {
|
|
22
21
|
// Deduplicate middleware using Set to avoid running the same middleware multiple times
|
|
23
22
|
let result;
|
|
24
23
|
const dispatch = async (index) => {
|
|
25
24
|
if (middlewares && index < middlewares.length) {
|
|
26
|
-
return await middlewares[index](services,
|
|
25
|
+
return await middlewares[index](services, wire, () => dispatch(index + 1));
|
|
27
26
|
}
|
|
28
27
|
else if (main) {
|
|
29
28
|
result = await main();
|
|
@@ -87,14 +86,14 @@ export const getMiddlewareByName = (name) => {
|
|
|
87
86
|
return middleware?.[0];
|
|
88
87
|
};
|
|
89
88
|
const middlewareCache = {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
89
|
+
http: {},
|
|
90
|
+
rpc: {},
|
|
91
|
+
channel: {},
|
|
92
|
+
queue: {},
|
|
93
|
+
scheduler: {},
|
|
94
|
+
mcp: {},
|
|
95
|
+
cli: {},
|
|
96
|
+
workflow: {},
|
|
98
97
|
};
|
|
99
98
|
/**
|
|
100
99
|
* Combines wiring-specific middleware with function-level middleware.
|
package/dist/permissions.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { CoreServices,
|
|
1
|
+
import { CoreServices, PikkuWiringTypes, PermissionMetadata, PikkuWire } from './types/core.types.js';
|
|
2
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.
|
|
6
6
|
* @param data - The data to be used in the permission validation functions.
|
|
7
|
-
* @param
|
|
7
|
+
* @param wire - The wire object containing request/response context and session.
|
|
8
8
|
* @returns A promise that resolves to void.
|
|
9
9
|
*/
|
|
10
|
-
export declare const verifyPermissions: (permissions: CorePermissionGroup, services: CoreServices, data: any,
|
|
10
|
+
export declare const verifyPermissions: <Out = any>(permissions: CorePermissionGroup, services: CoreServices, data: any, wire: PikkuWire<any, never, any, never, never, never>) => Promise<boolean>;
|
|
11
11
|
/**
|
|
12
12
|
* Registers a single permission function by name in the global permission store.
|
|
13
13
|
*
|
|
@@ -117,12 +117,12 @@ export declare const combinePermissions: (wireType: PikkuWiringTypes, uid: strin
|
|
|
117
117
|
* Runs permission checks using combined permissions from all sources.
|
|
118
118
|
* Combines permissions from wire and function levels, then validates them.
|
|
119
119
|
*/
|
|
120
|
-
export declare const runPermissions: (wireType: PikkuWiringTypes, uid: string, { wireInheritedPermissions, wirePermissions, funcInheritedPermissions, funcPermissions,
|
|
120
|
+
export declare const runPermissions: (wireType: PikkuWiringTypes, uid: string, { wireInheritedPermissions, wirePermissions, funcInheritedPermissions, funcPermissions, services, wire, data, }: {
|
|
121
121
|
wireInheritedPermissions?: PermissionMetadata[];
|
|
122
122
|
wirePermissions?: CorePermissionGroup | CorePikkuPermission[];
|
|
123
123
|
funcInheritedPermissions?: PermissionMetadata[];
|
|
124
124
|
funcPermissions?: CorePermissionGroup | CorePikkuPermission[];
|
|
125
|
-
|
|
125
|
+
services: CoreServices;
|
|
126
|
+
wire: PikkuWire<any, never, any, never, never, never>;
|
|
126
127
|
data: any;
|
|
127
|
-
session?: CoreUserSession;
|
|
128
128
|
}) => Promise<void>;
|