@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
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { closeWireServices } from '../../../utils.js';
|
|
2
2
|
import { processMessageHandlers } from '../channel-handler.js';
|
|
3
3
|
import { openChannel } from '../channel-runner.js';
|
|
4
|
-
import {
|
|
4
|
+
import { createHTTPWire } from '../../http/http-runner.js';
|
|
5
5
|
import { handleHTTPError } from '../../../handle-error.js';
|
|
6
|
-
import {
|
|
6
|
+
import { PikkuSessionService } from '../../../services/user-session-service.js';
|
|
7
7
|
import { pikkuState } from '../../../pikku-state.js';
|
|
8
8
|
import { PikkuFetchHTTPRequest } from '../../http/pikku-fetch-http-request.js';
|
|
9
9
|
import { runChannelLifecycleWithMiddleware } from '../channel-common.js';
|
|
10
|
-
import { rpcService } from '../../rpc/rpc-runner.js';
|
|
11
10
|
const getVariablesForChannel = ({ channelId, channelName, channelHandlerFactory, openingData, }) => {
|
|
12
11
|
const channels = pikkuState('channel', 'channels');
|
|
13
12
|
const channelConfig = channels.get(channelName);
|
|
@@ -27,16 +26,16 @@ const getVariablesForChannel = ({ channelId, channelName, channelHandlerFactory,
|
|
|
27
26
|
meta,
|
|
28
27
|
};
|
|
29
28
|
};
|
|
30
|
-
export const runChannelConnect = async ({ singletonServices, channelId, channelObject, request, response, route,
|
|
31
|
-
let
|
|
29
|
+
export const runChannelConnect = async ({ singletonServices, channelId, channelObject, request, response, route, createWireServices, channelStore, channelHandlerFactory, coerceDataFromSchema = true, logWarningsForStatusCodes = [], respondWith404 = true, bubbleErrors = false, }) => {
|
|
30
|
+
let wireServices;
|
|
32
31
|
let http;
|
|
33
32
|
if (request instanceof Request) {
|
|
34
|
-
http =
|
|
33
|
+
http = createHTTPWire(new PikkuFetchHTTPRequest(request), response);
|
|
35
34
|
}
|
|
36
|
-
const userSession = new
|
|
35
|
+
const userSession = new PikkuSessionService(channelStore, channelId);
|
|
37
36
|
const { channelConfig, openingData, meta } = await openChannel({
|
|
38
37
|
channelId,
|
|
39
|
-
|
|
38
|
+
createWireServices,
|
|
40
39
|
request,
|
|
41
40
|
route,
|
|
42
41
|
singletonServices,
|
|
@@ -55,23 +54,21 @@ export const runChannelConnect = async ({ singletonServices, channelId, channelO
|
|
|
55
54
|
channelHandlerFactory,
|
|
56
55
|
channelName: channelConfig.name,
|
|
57
56
|
});
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
const wire = { channel, session: userSession };
|
|
58
|
+
if (createWireServices) {
|
|
59
|
+
wireServices = await createWireServices(singletonServices, wire);
|
|
60
60
|
}
|
|
61
|
-
const
|
|
62
|
-
const getAllServices = (requiresAuth) => rpcService.injectRPCService({
|
|
61
|
+
const services = {
|
|
63
62
|
...singletonServices,
|
|
64
|
-
...
|
|
65
|
-
|
|
66
|
-
userSession,
|
|
67
|
-
}, interaction, requiresAuth);
|
|
63
|
+
...wireServices,
|
|
64
|
+
};
|
|
68
65
|
if (channelConfig.onConnect && meta.connect) {
|
|
69
66
|
await runChannelLifecycleWithMiddleware({
|
|
70
67
|
channelConfig,
|
|
71
68
|
meta: meta.connect,
|
|
72
69
|
lifecycleConfig: channelConfig.onConnect,
|
|
73
70
|
lifecycleType: 'connect',
|
|
74
|
-
services
|
|
71
|
+
services,
|
|
75
72
|
channel,
|
|
76
73
|
data: openingData,
|
|
77
74
|
});
|
|
@@ -82,13 +79,13 @@ export const runChannelConnect = async ({ singletonServices, channelId, channelO
|
|
|
82
79
|
handleHTTPError(e, http, channelId, singletonServices.logger, logWarningsForStatusCodes, respondWith404, bubbleErrors);
|
|
83
80
|
}
|
|
84
81
|
finally {
|
|
85
|
-
if (
|
|
86
|
-
await
|
|
82
|
+
if (wireServices) {
|
|
83
|
+
await closeWireServices(singletonServices.logger, wireServices);
|
|
87
84
|
}
|
|
88
85
|
}
|
|
89
86
|
};
|
|
90
87
|
export const runChannelDisconnect = async ({ singletonServices, ...params }) => {
|
|
91
|
-
let
|
|
88
|
+
let wireServices;
|
|
92
89
|
// Try to get channel from store. In serverless environments (especially with
|
|
93
90
|
// serverless-offline or worker threads), disconnect can be called multiple times
|
|
94
91
|
// or after the channel has already been cleaned up. If channel doesn't exist,
|
|
@@ -107,17 +104,16 @@ export const runChannelDisconnect = async ({ singletonServices, ...params }) =>
|
|
|
107
104
|
openingData,
|
|
108
105
|
channelName,
|
|
109
106
|
});
|
|
110
|
-
const userSession = new
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
const userSession = new PikkuSessionService(params.channelStore, params.channelId);
|
|
108
|
+
userSession.setInitial(session);
|
|
109
|
+
const wire = { channel, session: userSession };
|
|
110
|
+
if (!wireServices && params.createWireServices) {
|
|
111
|
+
wireServices = await params.createWireServices(singletonServices, wire);
|
|
113
112
|
}
|
|
114
|
-
const
|
|
115
|
-
const getAllServices = (requiresAuth) => rpcService.injectRPCService({
|
|
113
|
+
const services = {
|
|
116
114
|
...singletonServices,
|
|
117
|
-
...
|
|
118
|
-
|
|
119
|
-
userSession,
|
|
120
|
-
}, interaction, requiresAuth);
|
|
115
|
+
...wireServices,
|
|
116
|
+
};
|
|
121
117
|
if (channelConfig.onDisconnect && meta.disconnect) {
|
|
122
118
|
try {
|
|
123
119
|
await runChannelLifecycleWithMiddleware({
|
|
@@ -125,7 +121,7 @@ export const runChannelDisconnect = async ({ singletonServices, ...params }) =>
|
|
|
125
121
|
meta: meta.disconnect,
|
|
126
122
|
lifecycleConfig: channelConfig.onDisconnect,
|
|
127
123
|
lifecycleType: 'disconnect',
|
|
128
|
-
services
|
|
124
|
+
services,
|
|
129
125
|
channel,
|
|
130
126
|
});
|
|
131
127
|
}
|
|
@@ -134,32 +130,31 @@ export const runChannelDisconnect = async ({ singletonServices, ...params }) =>
|
|
|
134
130
|
}
|
|
135
131
|
}
|
|
136
132
|
await params.channelStore.removeChannels([channel.channelId]);
|
|
137
|
-
if (
|
|
138
|
-
await
|
|
133
|
+
if (wireServices) {
|
|
134
|
+
await closeWireServices(singletonServices.logger, wireServices);
|
|
139
135
|
}
|
|
140
136
|
};
|
|
141
137
|
export const runChannelMessage = async ({ singletonServices, ...params }, data) => {
|
|
142
|
-
let
|
|
138
|
+
let wireServices;
|
|
143
139
|
const { openingData, channelName, session } = await params.channelStore.getChannelAndSession(params.channelId);
|
|
144
140
|
const { channel, channelHandler, channelConfig } = getVariablesForChannel({
|
|
145
141
|
...params,
|
|
146
142
|
openingData,
|
|
147
143
|
channelName,
|
|
148
144
|
});
|
|
149
|
-
const userSession = new
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
const userSession = new PikkuSessionService(params.channelStore, params.channelId);
|
|
146
|
+
userSession.setInitial(session);
|
|
147
|
+
const wire = { channel, session: userSession };
|
|
148
|
+
if (params.createWireServices) {
|
|
149
|
+
wireServices = await params.createWireServices(singletonServices, wire);
|
|
152
150
|
}
|
|
153
|
-
const
|
|
154
|
-
const getAllServices = () => rpcService.injectRPCService({
|
|
151
|
+
const services = {
|
|
155
152
|
...singletonServices,
|
|
156
|
-
...
|
|
157
|
-
|
|
158
|
-
userSession,
|
|
159
|
-
}, interaction);
|
|
153
|
+
...wireServices,
|
|
154
|
+
};
|
|
160
155
|
let response;
|
|
161
156
|
try {
|
|
162
|
-
const onMessage = processMessageHandlers(
|
|
157
|
+
const onMessage = processMessageHandlers(services, channelConfig, channelHandler, userSession);
|
|
163
158
|
response = await onMessage(data);
|
|
164
159
|
}
|
|
165
160
|
catch (e) {
|
|
@@ -167,8 +162,8 @@ export const runChannelMessage = async ({ singletonServices, ...params }, data)
|
|
|
167
162
|
return { error: e.message || 'Unknown error' };
|
|
168
163
|
}
|
|
169
164
|
finally {
|
|
170
|
-
if (
|
|
171
|
-
await
|
|
165
|
+
if (wireServices) {
|
|
166
|
+
await closeWireServices(singletonServices.logger, wireServices);
|
|
172
167
|
}
|
|
173
168
|
}
|
|
174
169
|
return response;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CorePikkuMiddleware, CoreUserSession } from '../../types/core.types.js';
|
|
2
2
|
import { CoreCLI, CorePikkuCLIRender, CoreCLICommandConfig } from './cli.types.js';
|
|
3
|
-
import type { CoreSingletonServices, CoreServices,
|
|
3
|
+
import type { CoreSingletonServices, CoreServices, CreateWireServices, CreateConfig, CreateSingletonServices } from '../../types/core.types.js';
|
|
4
4
|
/**
|
|
5
5
|
* CLI command execution error - thrown when CLI execution fails
|
|
6
6
|
* Should be caught by the wrapper to call process.exit()
|
|
@@ -16,12 +16,12 @@ export declare const wireCLI: <Commands extends Record<string, CoreCLICommandCon
|
|
|
16
16
|
/**
|
|
17
17
|
* Executes a CLI command for a specific program
|
|
18
18
|
*/
|
|
19
|
-
export declare function runCLICommand({ program, commandPath, data, singletonServices,
|
|
19
|
+
export declare function runCLICommand({ program, commandPath, data, singletonServices, createWireServices, }: {
|
|
20
20
|
program: string;
|
|
21
21
|
commandPath: string[];
|
|
22
22
|
data: Record<string, any>;
|
|
23
23
|
singletonServices: CoreSingletonServices;
|
|
24
|
-
|
|
24
|
+
createWireServices?: CreateWireServices;
|
|
25
25
|
}): Promise<any>;
|
|
26
26
|
/**
|
|
27
27
|
* Factory function for CLI-specific renderers
|
|
@@ -33,10 +33,10 @@ export declare const pikkuCLIRender: <Data, Services extends CoreSingletonServic
|
|
|
33
33
|
*
|
|
34
34
|
* @throws {CLIError} When CLI execution fails - should be caught by wrapper to call process.exit()
|
|
35
35
|
*/
|
|
36
|
-
export declare function executeCLI({ programName, args, createConfig, createSingletonServices,
|
|
36
|
+
export declare function executeCLI({ programName, args, createConfig, createSingletonServices, createWireServices, }: {
|
|
37
37
|
programName: string;
|
|
38
38
|
args?: string[];
|
|
39
39
|
createConfig: CreateConfig<any, any>;
|
|
40
40
|
createSingletonServices: CreateSingletonServices<any, any>;
|
|
41
|
-
|
|
41
|
+
createWireServices?: CreateWireServices<any, any, any>;
|
|
42
42
|
}): Promise<void>;
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { NotFoundError } from '../../errors/errors.js';
|
|
2
2
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js';
|
|
3
3
|
import { pikkuState } from '../../pikku-state.js';
|
|
4
|
-
import {
|
|
5
|
-
import { closeSessionServices } from '../../utils.js';
|
|
6
|
-
import { rpcService } from '../rpc/rpc-runner.js';
|
|
7
|
-
import { PikkuUserSessionService } from '../../services/user-session-service.js';
|
|
4
|
+
import { PikkuSessionService } from '../../services/user-session-service.js';
|
|
8
5
|
import { LocalVariablesService } from '../../services/local-variables.js';
|
|
9
6
|
import { generateCommandHelp, parseCLIArguments } from './command-parser.js';
|
|
10
7
|
/**
|
|
@@ -157,7 +154,7 @@ function pluckCLIData(mergedData, funcName, availableOptions) {
|
|
|
157
154
|
/**
|
|
158
155
|
* Executes a CLI command for a specific program
|
|
159
156
|
*/
|
|
160
|
-
export async function runCLICommand({ program, commandPath, data, singletonServices,
|
|
157
|
+
export async function runCLICommand({ program, commandPath, data, singletonServices, createWireServices, }) {
|
|
161
158
|
// Get the command metadata to find the function name
|
|
162
159
|
const cliMeta = pikkuState('cli', 'meta');
|
|
163
160
|
const programMeta = cliMeta.programs?.[program];
|
|
@@ -217,39 +214,28 @@ export async function runCLICommand({ program, commandPath, data, singletonServi
|
|
|
217
214
|
},
|
|
218
215
|
state: 'open',
|
|
219
216
|
};
|
|
220
|
-
const userSession = new
|
|
221
|
-
|
|
222
|
-
const interaction = {
|
|
217
|
+
const userSession = new PikkuSessionService();
|
|
218
|
+
const wire = {
|
|
223
219
|
cli: {
|
|
224
220
|
program,
|
|
225
221
|
command: commandPath,
|
|
226
222
|
data: pluckedData,
|
|
227
223
|
channel,
|
|
228
224
|
},
|
|
229
|
-
|
|
230
|
-
const getAllServices = async (session) => {
|
|
231
|
-
// Create session-specific services for handling the command
|
|
232
|
-
sessionServices = await createSessionServices?.(singletonServices, interaction, session);
|
|
233
|
-
return rpcService.injectRPCService({
|
|
234
|
-
...singletonServices,
|
|
235
|
-
...sessionServices,
|
|
236
|
-
userSession,
|
|
237
|
-
channel,
|
|
238
|
-
}, interaction, false);
|
|
225
|
+
session: userSession,
|
|
239
226
|
};
|
|
240
227
|
try {
|
|
241
|
-
const result = await runPikkuFunc(
|
|
228
|
+
const result = await runPikkuFunc('cli', commandId, funcName, {
|
|
242
229
|
singletonServices,
|
|
243
|
-
|
|
230
|
+
createWireServices,
|
|
244
231
|
data: pluckedData,
|
|
245
232
|
auth: false,
|
|
246
|
-
userSession,
|
|
247
233
|
inheritedMiddleware: currentCommand.middleware,
|
|
248
234
|
wireMiddleware: allWireMiddleware,
|
|
249
235
|
inheritedPermissions: currentCommand.permissions,
|
|
250
236
|
wirePermissions: undefined,
|
|
251
237
|
tags: programData?.tags,
|
|
252
|
-
|
|
238
|
+
wire,
|
|
253
239
|
});
|
|
254
240
|
// Apply renderer one final time with the final output (if renderer exists)
|
|
255
241
|
if (renderer) {
|
|
@@ -260,10 +246,6 @@ export async function runCLICommand({ program, commandPath, data, singletonServi
|
|
|
260
246
|
finally {
|
|
261
247
|
// Close the channel
|
|
262
248
|
channel.close();
|
|
263
|
-
// Clean up session services
|
|
264
|
-
if (sessionServices) {
|
|
265
|
-
await closeSessionServices(singletonServices.logger, sessionServices);
|
|
266
|
-
}
|
|
267
249
|
}
|
|
268
250
|
}
|
|
269
251
|
/**
|
|
@@ -278,7 +260,7 @@ export const pikkuCLIRender = (renderer) => {
|
|
|
278
260
|
*
|
|
279
261
|
* @throws {CLIError} When CLI execution fails - should be caught by wrapper to call process.exit()
|
|
280
262
|
*/
|
|
281
|
-
export async function executeCLI({ programName, args, createConfig, createSingletonServices,
|
|
263
|
+
export async function executeCLI({ programName, args, createConfig, createSingletonServices, createWireServices, }) {
|
|
282
264
|
if (!args) {
|
|
283
265
|
throw new Error('CLI arguments are required, this is to satisfy release diffs');
|
|
284
266
|
}
|
|
@@ -333,7 +315,7 @@ export async function executeCLI({ programName, args, createConfig, createSingle
|
|
|
333
315
|
commandPath: parsed.commandPath,
|
|
334
316
|
data,
|
|
335
317
|
singletonServices,
|
|
336
|
-
|
|
318
|
+
createWireServices,
|
|
337
319
|
});
|
|
338
320
|
}
|
|
339
321
|
catch (error) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CorePikkuMiddleware, CoreSingletonServices, CoreUserSession,
|
|
1
|
+
import { CorePikkuMiddleware, CoreSingletonServices, CoreUserSession, CoreServices, MiddlewareMetadata, PermissionMetadata } from '../../types/core.types.js';
|
|
2
2
|
import { CorePikkuFunctionConfig, CorePikkuPermission, CorePikkuFunction, CorePikkuFunctionSessionless } from '../../function/functions.types.js';
|
|
3
3
|
import { PikkuChannel } from '../channel/channel.types.js';
|
|
4
4
|
/**
|
|
@@ -27,7 +27,7 @@ export interface CLIPositional {
|
|
|
27
27
|
variadic?: boolean;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* CLI
|
|
30
|
+
* CLI wire context
|
|
31
31
|
*/
|
|
32
32
|
export type PikkuCLI = {
|
|
33
33
|
program: string;
|
|
@@ -55,8 +55,9 @@ export interface CLICommandMeta {
|
|
|
55
55
|
positionals: CLIPositional[];
|
|
56
56
|
options: Record<string, CLIOption>;
|
|
57
57
|
renderName?: string;
|
|
58
|
+
summary?: string;
|
|
58
59
|
description?: string;
|
|
59
|
-
|
|
60
|
+
errors?: string[];
|
|
60
61
|
tags?: string[];
|
|
61
62
|
subcommands?: Record<string, CLICommandMeta>;
|
|
62
63
|
middleware?: MiddlewareMetadata[];
|
|
@@ -99,7 +100,7 @@ export type CorePikkuCLIRender<Data, Services extends CoreSingletonServices = Co
|
|
|
99
100
|
/**
|
|
100
101
|
* Extract input parameters from a Pikku function config type
|
|
101
102
|
*/
|
|
102
|
-
export type ExtractFunctionInput<Func> = Func extends CorePikkuFunctionConfig<infer FuncType, any, any> ? FuncType extends CorePikkuFunction<infer Input, any, any, any
|
|
103
|
+
export type ExtractFunctionInput<Func> = Func extends CorePikkuFunctionConfig<infer FuncType, any, any> ? FuncType extends CorePikkuFunction<infer Input, any, any, any> | CorePikkuFunctionSessionless<infer Input, any, any, any> ? Input : never : never;
|
|
103
104
|
/**
|
|
104
105
|
* Strip < > [ ] characters from a string
|
|
105
106
|
*/
|
|
@@ -131,12 +132,12 @@ export type ValidateParameters<Params extends string, Input> = AllParamsValid<Ex
|
|
|
131
132
|
/**
|
|
132
133
|
* Extract output type from a Pikku function config type
|
|
133
134
|
*/
|
|
134
|
-
export type ExtractFunctionOutput<Func> = Func extends CorePikkuFunctionConfig<infer FuncType, any, any> ? FuncType extends CorePikkuFunction<any, infer Output, any, any
|
|
135
|
+
export type ExtractFunctionOutput<Func> = Func extends CorePikkuFunctionConfig<infer FuncType, any, any> ? FuncType extends CorePikkuFunction<any, infer Output, any, any> | CorePikkuFunctionSessionless<any, infer Output, any, any> ? Output : never : never;
|
|
135
136
|
/**
|
|
136
137
|
* CLI command configuration that infers options from function input type.
|
|
137
138
|
* This is a helper type for creating type-safe CLI commands.
|
|
138
139
|
*/
|
|
139
|
-
export type CoreCLICommandConfig<FuncConfig, PikkuMiddleware extends CorePikkuMiddleware<any> = CorePikkuMiddleware<any>, PikkuCLIRender extends CorePikkuCLIRender<any, any, any> = CorePikkuCLIRender<any, any>, Params extends string = string> = {
|
|
140
|
+
export type CoreCLICommandConfig<FuncConfig, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>, PikkuCLIRender extends CorePikkuCLIRender<any, any, any> = CorePikkuCLIRender<any, any>, Params extends string = string> = {
|
|
140
141
|
parameters?: ValidateParameters<Params, ExtractFunctionInput<FuncConfig>>;
|
|
141
142
|
func?: FuncConfig;
|
|
142
143
|
description?: string;
|
|
@@ -157,7 +158,7 @@ export type CoreCLICommandConfig<FuncConfig, PikkuMiddleware extends CorePikkuMi
|
|
|
157
158
|
/**
|
|
158
159
|
* CLI command definition
|
|
159
160
|
*/
|
|
160
|
-
export interface CoreCLICommand<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any
|
|
161
|
+
export interface CoreCLICommand<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any> | CorePikkuFunctionSessionless<In, Out, any, any>>, PikkuPermission extends CorePikkuPermission<any, any, any>, PikkuMiddleware extends CorePikkuMiddleware, Options = any, Subcommands extends Record<string, CoreCLICommandConfig<any, any, any>> = Record<string, CoreCLICommandConfig<any, any, any>>> {
|
|
161
162
|
parameters?: string;
|
|
162
163
|
func: PikkuFunctionConfig;
|
|
163
164
|
render?: CorePikkuCLIRender<Out>;
|
|
@@ -166,18 +167,20 @@ export interface CoreCLICommand<In, Out, PikkuFunctionConfig extends CorePikkuFu
|
|
|
166
167
|
middleware?: PikkuMiddleware[];
|
|
167
168
|
permissions?: Record<string, PikkuPermission | PikkuPermission[]>;
|
|
168
169
|
auth?: boolean;
|
|
169
|
-
|
|
170
|
+
summary?: string;
|
|
171
|
+
errors?: string[];
|
|
172
|
+
tags?: string[];
|
|
170
173
|
subcommands?: Subcommands;
|
|
171
174
|
isDefault?: boolean;
|
|
172
175
|
}
|
|
173
176
|
/**
|
|
174
177
|
* Shorthand command definition (just a function)
|
|
175
178
|
*/
|
|
176
|
-
export type CLICommandShorthand<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any
|
|
179
|
+
export type CLICommandShorthand<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any> | CorePikkuFunctionSessionless<In, Out, any, any>>> = PikkuFunctionConfig;
|
|
177
180
|
/**
|
|
178
181
|
* Command definition (either full or shorthand)
|
|
179
182
|
*/
|
|
180
|
-
export type CLICommandDefinition<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any
|
|
183
|
+
export type CLICommandDefinition<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any> | CorePikkuFunctionSessionless<In, Out, any, any>>, PikkuPermission extends CorePikkuPermission<any, any, any>, PikkuMiddleware extends CorePikkuMiddleware, Options = any, Subcommands extends Record<string, CoreCLICommandConfig<any, any, any>> = Record<string, CoreCLICommandConfig<any, any, any>>> = CoreCLICommand<In, Out, PikkuFunctionConfig, PikkuPermission, PikkuMiddleware, Options, Subcommands> | CLICommandShorthand<In, Out, PikkuFunctionConfig>;
|
|
181
184
|
/**
|
|
182
185
|
* CLI wiring configuration
|
|
183
186
|
*/
|
|
@@ -188,7 +191,8 @@ export interface CoreCLI<Commands extends Record<string, CoreCLICommandConfig<an
|
|
|
188
191
|
options?: CLIOptions<Options>;
|
|
189
192
|
middleware?: PikkuMiddleware[];
|
|
190
193
|
render?: PikkuCLIRender;
|
|
191
|
-
|
|
194
|
+
summary?: string;
|
|
195
|
+
errors?: string[];
|
|
192
196
|
tags?: string[];
|
|
193
197
|
}
|
|
194
198
|
/**
|
|
@@ -79,16 +79,16 @@ export declare const addHTTPPermission: <PikkuPermission extends CorePikkuPermis
|
|
|
79
79
|
*/
|
|
80
80
|
export declare const wireHTTP: <In, Out, Route extends string, PikkuFunction extends CorePikkuFunction<In, Out> = CorePikkuFunction<In, Out>, PikkuFunctionSessionless extends CorePikkuFunctionSessionless<In, Out> = CorePikkuFunctionSessionless<In, Out>, PikkuPermissionGroup extends CorePikkuPermission<In> = CorePikkuPermission<In>, PikkuMiddleware extends CorePikkuMiddleware = CorePikkuMiddleware>(httpWiring: CoreHTTPFunctionWiring<In, Out, Route, PikkuFunction, PikkuFunctionSessionless, PikkuPermissionGroup, PikkuMiddleware>) => void;
|
|
81
81
|
/**
|
|
82
|
-
* Combines the request and response objects into a single HTTP
|
|
82
|
+
* Combines the request and response objects into a single HTTP wire object.
|
|
83
83
|
*
|
|
84
84
|
* This utility function creates an object that holds both the HTTP request and response,
|
|
85
85
|
* which simplifies passing these around through middleware and route execution.
|
|
86
86
|
*
|
|
87
87
|
* @param {PikkuHTTPRequest | undefined} request - The HTTP request object.
|
|
88
88
|
* @param {PikkuHTTPResponse | undefined} response - The HTTP response object.
|
|
89
|
-
* @returns {PikkuHTTP | undefined} The combined HTTP
|
|
89
|
+
* @returns {PikkuHTTP | undefined} The combined HTTP wire object or undefined if none provided.
|
|
90
90
|
*/
|
|
91
|
-
export declare const
|
|
91
|
+
export declare const createHTTPWire: (request: PikkuHTTPRequest | undefined, response: PikkuHTTPResponse | undefined) => PikkuHTTP | undefined;
|
|
92
92
|
/**
|
|
93
93
|
* Executes an HTTP route for a given Fetch API request.
|
|
94
94
|
*
|
|
@@ -123,11 +123,11 @@ export declare const pikkuFetch: <In, Out>(request: Request | PikkuHTTPRequest,
|
|
|
123
123
|
* middleware execution, error handling, and session service cleanup.
|
|
124
124
|
*
|
|
125
125
|
* This function does the following:
|
|
126
|
-
* - Wraps the incoming request and response into an HTTP
|
|
126
|
+
* - Wraps the incoming request and response into an HTTP wire object.
|
|
127
127
|
* - Determines the correct route based on HTTP method and path.
|
|
128
128
|
* - Executes middleware and the route handler.
|
|
129
129
|
* - Catches and handles errors, optionally bubbling them if configured.
|
|
130
|
-
* - Cleans up any
|
|
130
|
+
* - Cleans up any wire services created during processing.
|
|
131
131
|
*
|
|
132
132
|
* @template In Expected input data type.
|
|
133
133
|
* @template Out Expected output data type.
|
|
@@ -136,4 +136,4 @@ export declare const pikkuFetch: <In, Out>(request: Request | PikkuHTTPRequest,
|
|
|
136
136
|
* @param {RunHTTPWiringOptions & RunHTTPWiringParams} options - Options such as singleton services, session handling, and error configuration.
|
|
137
137
|
* @returns {Promise<Out | void>} The output from the route handler or void if an error occurred.
|
|
138
138
|
*/
|
|
139
|
-
export declare const fetchData: <In, Out>(request: Request | PikkuHTTPRequest, response: PikkuHTTPResponse, { singletonServices,
|
|
139
|
+
export declare const fetchData: <In, Out>(request: Request | PikkuHTTPRequest, response: PikkuHTTPResponse, { singletonServices, createWireServices, skipUserSession, respondWith404, logWarningsForStatusCodes, coerceDataFromSchema, bubbleErrors, generateRequestId, }: RunHTTPWiringOptions & RunHTTPWiringParams) => Promise<Out | void>;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { PikkuWiringTypes, } from '../../types/core.types.js';
|
|
2
1
|
import { NotFoundError } from '../../errors/errors.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { closeWireServices, createWeakUID, isSerializable, } from '../../utils.js';
|
|
3
|
+
import { PikkuSessionService } from '../../services/user-session-service.js';
|
|
5
4
|
import { handleHTTPError } from '../../handle-error.js';
|
|
6
5
|
import { pikkuState } from '../../pikku-state.js';
|
|
7
6
|
import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
|
|
8
7
|
import { PikkuFetchHTTPRequest } from './pikku-fetch-http-request.js';
|
|
9
8
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js';
|
|
10
|
-
import { rpcService } from '../rpc/rpc-runner.js';
|
|
11
9
|
import { httpRouter } from './routers/http-router.js';
|
|
12
10
|
/**
|
|
13
11
|
* Registers HTTP middleware for a specific route pattern.
|
|
@@ -135,16 +133,16 @@ const getMatchingRoute = (requestType, requestPath) => {
|
|
|
135
133
|
}
|
|
136
134
|
};
|
|
137
135
|
/**
|
|
138
|
-
* Combines the request and response objects into a single HTTP
|
|
136
|
+
* Combines the request and response objects into a single HTTP wire object.
|
|
139
137
|
*
|
|
140
138
|
* This utility function creates an object that holds both the HTTP request and response,
|
|
141
139
|
* which simplifies passing these around through middleware and route execution.
|
|
142
140
|
*
|
|
143
141
|
* @param {PikkuHTTPRequest | undefined} request - The HTTP request object.
|
|
144
142
|
* @param {PikkuHTTPResponse | undefined} response - The HTTP response object.
|
|
145
|
-
* @returns {PikkuHTTP | undefined} The combined HTTP
|
|
143
|
+
* @returns {PikkuHTTP | undefined} The combined HTTP wire object or undefined if none provided.
|
|
146
144
|
*/
|
|
147
|
-
export const
|
|
145
|
+
export const createHTTPWire = (request, response) => {
|
|
148
146
|
let http = undefined;
|
|
149
147
|
if (request || response) {
|
|
150
148
|
http = {};
|
|
@@ -172,17 +170,17 @@ export const createHTTPInteraction = (request, response) => {
|
|
|
172
170
|
*
|
|
173
171
|
* @param {Object} services - A collection of shared services and utilities.
|
|
174
172
|
* @param {Object} matchedRoute - Contains route details, URL parameters, and optional schema.
|
|
175
|
-
* @param {PikkuHTTP | undefined} http - The HTTP
|
|
173
|
+
* @param {PikkuHTTP | undefined} http - The HTTP wire object.
|
|
176
174
|
* @param {Object} options - Options for route execution (e.g., whether to coerce query strings to arrays).
|
|
177
|
-
* @returns {Promise<any>} An object containing the route handler result and
|
|
175
|
+
* @returns {Promise<any>} An object containing the route handler result and wire services (if any).
|
|
178
176
|
* @throws Throws errors like MissingSessionError or ForbiddenError on validation failures.
|
|
179
177
|
*/
|
|
180
178
|
const executeRoute = async (services, matchedRoute, http, options) => {
|
|
181
|
-
const userSession = new
|
|
179
|
+
const userSession = new PikkuSessionService();
|
|
182
180
|
const { params, route, meta } = matchedRoute;
|
|
183
|
-
const { singletonServices,
|
|
181
|
+
const { singletonServices, createWireServices, skipUserSession, requestId } = services;
|
|
184
182
|
const requiresSession = route.auth !== false;
|
|
185
|
-
let
|
|
183
|
+
let wireServices;
|
|
186
184
|
let result;
|
|
187
185
|
// Attach URL parameters to the request object
|
|
188
186
|
http?.request?.setParams(params);
|
|
@@ -219,23 +217,11 @@ const executeRoute = async (services, matchedRoute, http, options) => {
|
|
|
219
217
|
state: 'open',
|
|
220
218
|
};
|
|
221
219
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
// Create session-specific services for handling the request
|
|
225
|
-
sessionServices = await createSessionServices({ ...singletonServices, userSession, channel }, { http }, session);
|
|
226
|
-
return rpcService.injectRPCService({
|
|
227
|
-
...singletonServices,
|
|
228
|
-
...sessionServices,
|
|
229
|
-
http,
|
|
230
|
-
userSession,
|
|
231
|
-
channel,
|
|
232
|
-
}, interaction, route.auth);
|
|
233
|
-
};
|
|
234
|
-
result = await runPikkuFunc(PikkuWiringTypes.http, `${meta.method}:${meta.route}`, meta.pikkuFuncName, {
|
|
220
|
+
const wire = { http, channel, session: userSession };
|
|
221
|
+
result = await runPikkuFunc('http', `${meta.method}:${meta.route}`, meta.pikkuFuncName, {
|
|
235
222
|
singletonServices,
|
|
236
|
-
|
|
223
|
+
createWireServices,
|
|
237
224
|
auth: route.auth !== false,
|
|
238
|
-
userSession,
|
|
239
225
|
data,
|
|
240
226
|
inheritedMiddleware: meta.middleware,
|
|
241
227
|
wireMiddleware: route.middleware,
|
|
@@ -243,7 +229,7 @@ const executeRoute = async (services, matchedRoute, http, options) => {
|
|
|
243
229
|
wirePermissions: route.permissions,
|
|
244
230
|
coerceDataFromSchema: options.coerceDataFromSchema,
|
|
245
231
|
tags: route.tags,
|
|
246
|
-
|
|
232
|
+
wire,
|
|
247
233
|
});
|
|
248
234
|
// Respond with either a binary or JSON response based on configuration
|
|
249
235
|
if (route.returnsJSON === false) {
|
|
@@ -255,7 +241,7 @@ const executeRoute = async (services, matchedRoute, http, options) => {
|
|
|
255
241
|
http?.response?.status(200);
|
|
256
242
|
// TODO: Evaluate if the response stream should be explicitly ended.
|
|
257
243
|
// http?.response?.end()
|
|
258
|
-
return
|
|
244
|
+
return wireServices ? { result, wireServices } : { result };
|
|
259
245
|
};
|
|
260
246
|
/**
|
|
261
247
|
* Executes an HTTP route for a given Fetch API request.
|
|
@@ -299,11 +285,11 @@ export const pikkuFetch = async (request, params) => {
|
|
|
299
285
|
* middleware execution, error handling, and session service cleanup.
|
|
300
286
|
*
|
|
301
287
|
* This function does the following:
|
|
302
|
-
* - Wraps the incoming request and response into an HTTP
|
|
288
|
+
* - Wraps the incoming request and response into an HTTP wire object.
|
|
303
289
|
* - Determines the correct route based on HTTP method and path.
|
|
304
290
|
* - Executes middleware and the route handler.
|
|
305
291
|
* - Catches and handles errors, optionally bubbling them if configured.
|
|
306
|
-
* - Cleans up any
|
|
292
|
+
* - Cleans up any wire services created during processing.
|
|
307
293
|
*
|
|
308
294
|
* @template In Expected input data type.
|
|
309
295
|
* @template Out Expected output data type.
|
|
@@ -312,14 +298,14 @@ export const pikkuFetch = async (request, params) => {
|
|
|
312
298
|
* @param {RunHTTPWiringOptions & RunHTTPWiringParams} options - Options such as singleton services, session handling, and error configuration.
|
|
313
299
|
* @returns {Promise<Out | void>} The output from the route handler or void if an error occurred.
|
|
314
300
|
*/
|
|
315
|
-
export const fetchData = async (request, response, { singletonServices,
|
|
301
|
+
export const fetchData = async (request, response, { singletonServices, createWireServices, skipUserSession = false, respondWith404 = true, logWarningsForStatusCodes = [], coerceDataFromSchema = true, bubbleErrors = false, generateRequestId, }) => {
|
|
316
302
|
const requestId = request.getHeader?.('x-request-id') ||
|
|
317
303
|
generateRequestId?.() ||
|
|
318
304
|
createWeakUID();
|
|
319
|
-
let
|
|
305
|
+
let wireServices;
|
|
320
306
|
let result;
|
|
321
|
-
// Combine the request and response into one
|
|
322
|
-
const http =
|
|
307
|
+
// Combine the request and response into one wire object
|
|
308
|
+
const http = createHTTPWire(request instanceof Request ? new PikkuFetchHTTPRequest(request) : request, response);
|
|
323
309
|
const apiType = http.request.method();
|
|
324
310
|
const apiRoute = http.request.path();
|
|
325
311
|
// Locate the matching route based on the HTTP method and path
|
|
@@ -336,9 +322,9 @@ export const fetchData = async (request, response, { singletonServices, createSe
|
|
|
336
322
|
}
|
|
337
323
|
// Execute the matched route along with its middleware and session management
|
|
338
324
|
;
|
|
339
|
-
({ result,
|
|
325
|
+
({ result, wireServices } = await executeRoute({
|
|
340
326
|
singletonServices,
|
|
341
|
-
|
|
327
|
+
createWireServices,
|
|
342
328
|
skipUserSession,
|
|
343
329
|
requestId,
|
|
344
330
|
}, matchedRoute, http, { coerceDataFromSchema }));
|
|
@@ -350,8 +336,8 @@ export const fetchData = async (request, response, { singletonServices, createSe
|
|
|
350
336
|
}
|
|
351
337
|
finally {
|
|
352
338
|
// Clean up any session-specific services created during processing
|
|
353
|
-
if (
|
|
354
|
-
await
|
|
339
|
+
if (wireServices) {
|
|
340
|
+
await closeWireServices(singletonServices.logger, wireServices);
|
|
355
341
|
}
|
|
356
342
|
}
|
|
357
343
|
};
|