@pikku/core 0.9.10 → 0.9.12-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/function/function-runner.d.ts +13 -8
- package/dist/function/function-runner.js +49 -37
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/middleware-runner.d.ts +61 -40
- package/dist/middleware-runner.js +118 -66
- package/dist/permissions.js +1 -0
- package/dist/pikku-state.d.ts +26 -1
- package/dist/pikku-state.js +10 -1
- package/dist/services/content-service.d.ts +2 -3
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.js +0 -1
- package/dist/services/local-content.d.ts +2 -4
- package/dist/services/local-content.js +2 -2
- package/dist/types/core.types.d.ts +51 -2
- package/dist/types/core.types.js +21 -0
- package/dist/wirings/channel/channel-handler.d.ts +2 -2
- package/dist/wirings/channel/channel-handler.js +12 -9
- package/dist/wirings/channel/channel-runner.d.ts +0 -2
- package/dist/wirings/channel/channel-runner.js +2 -3
- package/dist/wirings/channel/channel.types.d.ts +5 -3
- package/dist/wirings/channel/local/local-channel-runner.js +12 -12
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +7 -8
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +12 -0
- package/dist/wirings/cli/channel/cli-channel-runner.js +80 -0
- package/dist/wirings/cli/channel/index.d.ts +1 -0
- package/dist/wirings/cli/channel/index.js +1 -0
- package/dist/wirings/cli/cli-runner.d.ts +32 -0
- package/dist/wirings/cli/cli-runner.js +328 -0
- package/dist/wirings/cli/cli.types.d.ts +177 -0
- package/dist/wirings/cli/cli.types.js +1 -0
- package/dist/wirings/cli/command-parser.d.ts +19 -0
- package/dist/wirings/cli/command-parser.js +373 -0
- package/dist/wirings/cli/index.d.ts +5 -0
- package/dist/wirings/cli/index.js +5 -0
- package/dist/wirings/http/http-runner.d.ts +29 -10
- package/dist/wirings/http/http-runner.js +103 -131
- package/dist/wirings/http/http.types.d.ts +10 -10
- package/dist/wirings/http/index.d.ts +1 -1
- package/dist/wirings/http/index.js +1 -1
- package/dist/wirings/http/pikku-fetch-http-response.js +3 -1
- package/dist/wirings/http/routers/http-router.d.ts +0 -2
- package/dist/wirings/http/routers/path-to-regex.d.ts +1 -1
- package/dist/wirings/http/routers/path-to-regex.js +5 -34
- package/dist/wirings/mcp/mcp-runner.d.ts +4 -5
- package/dist/wirings/mcp/mcp-runner.js +30 -34
- package/dist/wirings/mcp/mcp.types.d.ts +11 -8
- package/dist/wirings/queue/queue-runner.d.ts +2 -2
- package/dist/wirings/queue/queue-runner.js +25 -27
- package/dist/wirings/queue/queue.types.d.ts +6 -5
- package/dist/wirings/rpc/index.d.ts +1 -1
- package/dist/wirings/rpc/index.js +1 -1
- package/dist/wirings/rpc/rpc-runner.d.ts +6 -18
- package/dist/wirings/rpc/rpc-runner.js +13 -8
- package/dist/wirings/scheduler/scheduler-runner.d.ts +2 -2
- package/dist/wirings/scheduler/scheduler-runner.js +37 -35
- package/dist/wirings/scheduler/scheduler.types.d.ts +4 -3
- package/package.json +4 -3
- package/src/function/function-runner.test.ts +73 -23
- package/src/function/function-runner.ts +74 -55
- package/src/index.ts +8 -1
- package/src/middleware-runner.test.ts +24 -16
- package/src/middleware-runner.ts +136 -83
- package/src/permissions.ts +1 -0
- package/src/pikku-state.ts +47 -2
- package/src/services/content-service.ts +5 -4
- package/src/services/index.ts +0 -1
- package/src/services/local-content.ts +11 -6
- package/src/types/core.types.ts +74 -3
- package/src/wirings/channel/channel-handler.ts +9 -13
- package/src/wirings/channel/channel-runner.ts +2 -6
- package/src/wirings/channel/channel.types.ts +5 -1
- package/src/wirings/channel/local/local-channel-runner.ts +25 -15
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +15 -17
- package/src/wirings/cli/channel/cli-channel-runner.ts +118 -0
- package/src/wirings/cli/channel/index.ts +1 -0
- package/src/wirings/cli/cli-runner.test.ts +382 -0
- package/src/wirings/cli/cli-runner.ts +503 -0
- package/src/wirings/cli/cli.types.ts +320 -0
- package/src/wirings/cli/command-parser.test.ts +440 -0
- package/src/wirings/cli/command-parser.ts +470 -0
- package/src/wirings/cli/index.ts +12 -0
- package/src/wirings/http/http-runner.test.ts +8 -7
- package/src/wirings/http/http-runner.ts +126 -159
- package/src/wirings/http/http.types.ts +56 -11
- package/src/wirings/http/index.ts +1 -1
- package/src/wirings/http/pikku-fetch-http-response.ts +3 -1
- package/src/wirings/http/routers/http-router.ts +0 -2
- package/src/wirings/http/routers/path-to-regex.test.ts +4 -5
- package/src/wirings/http/routers/path-to-regex.ts +6 -43
- package/src/wirings/mcp/mcp-runner.ts +56 -55
- package/src/wirings/mcp/mcp.types.ts +23 -8
- package/src/wirings/queue/queue-runner.ts +44 -47
- package/src/wirings/queue/queue.types.ts +10 -6
- package/src/wirings/rpc/index.ts +1 -1
- package/src/wirings/rpc/rpc-runner.ts +27 -9
- package/src/wirings/scheduler/scheduler-runner.ts +57 -56
- package/src/wirings/scheduler/scheduler.types.ts +9 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses raw CLI arguments into structured data for a specific program
|
|
3
|
+
*/
|
|
4
|
+
export function parseCLIArguments(args, programName, allMeta) {
|
|
5
|
+
const result = {
|
|
6
|
+
program: programName,
|
|
7
|
+
commandPath: [],
|
|
8
|
+
positionals: {},
|
|
9
|
+
options: {},
|
|
10
|
+
errors: [],
|
|
11
|
+
};
|
|
12
|
+
const meta = allMeta[programName];
|
|
13
|
+
if (!meta) {
|
|
14
|
+
result.errors.push(`Program not found: ${programName}`);
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
let currentIndex = 0;
|
|
18
|
+
let currentMeta = meta;
|
|
19
|
+
// Parse command path (non-flag arguments at the beginning)
|
|
20
|
+
while (currentIndex < args.length && !args[currentIndex].startsWith('-')) {
|
|
21
|
+
const arg = args[currentIndex];
|
|
22
|
+
// Check if this is a known subcommand
|
|
23
|
+
if (currentMeta.commands && currentMeta.commands[arg]) {
|
|
24
|
+
result.commandPath.push(arg);
|
|
25
|
+
currentMeta = {
|
|
26
|
+
program: currentMeta.program,
|
|
27
|
+
commands: currentMeta.commands[arg].subcommands || {},
|
|
28
|
+
options: {
|
|
29
|
+
...currentMeta.options,
|
|
30
|
+
...currentMeta.commands[arg].options,
|
|
31
|
+
},
|
|
32
|
+
defaultRenderName: currentMeta.commands[arg].renderName || currentMeta.defaultRenderName,
|
|
33
|
+
};
|
|
34
|
+
currentIndex++;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Not a subcommand, must be a positional argument
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Get the final command metadata
|
|
42
|
+
const commandMeta = getCommandMeta(meta, result.commandPath);
|
|
43
|
+
if (!commandMeta) {
|
|
44
|
+
result.errors.push(`Unknown command: ${result.commandPath.join(' ')}`);
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
// Collect all available options (global + inherited)
|
|
48
|
+
const availableOptions = collectAvailableOptions(meta, result.commandPath);
|
|
49
|
+
// Parse remaining arguments as positionals and options
|
|
50
|
+
const positionalArgs = [];
|
|
51
|
+
const optionArgs = {};
|
|
52
|
+
while (currentIndex < args.length) {
|
|
53
|
+
const arg = args[currentIndex];
|
|
54
|
+
if (arg.startsWith('--')) {
|
|
55
|
+
// Long option
|
|
56
|
+
const equalIndex = arg.indexOf('=');
|
|
57
|
+
if (equalIndex > 0) {
|
|
58
|
+
// --option=value format
|
|
59
|
+
const key = arg.slice(2, equalIndex);
|
|
60
|
+
const optionDef = availableOptions[key];
|
|
61
|
+
// Unknown options are allowed for forward compatibility
|
|
62
|
+
const value = arg.slice(equalIndex + 1);
|
|
63
|
+
optionArgs[key] = parseOptionValue(value, optionDef);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// --option value format
|
|
67
|
+
const key = arg.slice(2);
|
|
68
|
+
const optionDef = availableOptions[key];
|
|
69
|
+
// Unknown options are allowed for forward compatibility
|
|
70
|
+
if (optionDef && optionDef.array) {
|
|
71
|
+
// Array option - collect all following non-flag values
|
|
72
|
+
currentIndex++;
|
|
73
|
+
const values = [];
|
|
74
|
+
while (currentIndex < args.length &&
|
|
75
|
+
!args[currentIndex].startsWith('-')) {
|
|
76
|
+
values.push(parseOptionValue(args[currentIndex], optionDef));
|
|
77
|
+
currentIndex++;
|
|
78
|
+
}
|
|
79
|
+
currentIndex--; // Back up one since we'll increment at loop end
|
|
80
|
+
optionArgs[key] = values;
|
|
81
|
+
}
|
|
82
|
+
else if (currentIndex + 1 < args.length &&
|
|
83
|
+
!args[currentIndex + 1].startsWith('-')) {
|
|
84
|
+
// Next arg is the value
|
|
85
|
+
currentIndex++;
|
|
86
|
+
optionArgs[key] = parseOptionValue(args[currentIndex], optionDef);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Boolean flag
|
|
90
|
+
optionArgs[key] = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else if (arg.startsWith('-') && arg.length > 1) {
|
|
95
|
+
// Short option(s)
|
|
96
|
+
for (let i = 1; i < arg.length; i++) {
|
|
97
|
+
const shortFlag = arg[i];
|
|
98
|
+
// Find the corresponding long option
|
|
99
|
+
const longOption = findLongOption(shortFlag, availableOptions);
|
|
100
|
+
if (longOption) {
|
|
101
|
+
// Check if this is the last character and there's a value
|
|
102
|
+
if (i === arg.length - 1 &&
|
|
103
|
+
currentIndex + 1 < args.length &&
|
|
104
|
+
!args[currentIndex + 1].startsWith('-')) {
|
|
105
|
+
currentIndex++;
|
|
106
|
+
optionArgs[longOption] = parseOptionValue(args[currentIndex], availableOptions[longOption]);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// Boolean flag
|
|
110
|
+
optionArgs[longOption] = true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
result.errors.push(`Unknown option: -${shortFlag}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Positional argument
|
|
120
|
+
positionalArgs.push(arg);
|
|
121
|
+
}
|
|
122
|
+
currentIndex++;
|
|
123
|
+
}
|
|
124
|
+
// Map positional arguments to named parameters
|
|
125
|
+
mapPositionalArguments(commandMeta.positionals, positionalArgs, result);
|
|
126
|
+
// Apply option defaults and validation
|
|
127
|
+
applyOptionDefaults(availableOptions, optionArgs, result);
|
|
128
|
+
result.options = optionArgs;
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Gets the command metadata for a given path
|
|
133
|
+
*/
|
|
134
|
+
function getCommandMeta(meta, path) {
|
|
135
|
+
if (path.length === 0) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
let current = meta.commands[path[0]];
|
|
139
|
+
if (!current) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
for (let i = 1; i < path.length; i++) {
|
|
143
|
+
if (!current.subcommands || !current.subcommands[path[i]]) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
current = current.subcommands[path[i]];
|
|
147
|
+
}
|
|
148
|
+
return current;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Collects all available options through the inheritance chain
|
|
152
|
+
*/
|
|
153
|
+
function collectAvailableOptions(meta, path) {
|
|
154
|
+
let options = { ...meta.options };
|
|
155
|
+
if (path.length === 0) {
|
|
156
|
+
return options;
|
|
157
|
+
}
|
|
158
|
+
// Walk through the command path, merging options
|
|
159
|
+
let current = meta.commands[path[0]];
|
|
160
|
+
if (current) {
|
|
161
|
+
options = { ...options, ...current.options };
|
|
162
|
+
for (let i = 1; i < path.length; i++) {
|
|
163
|
+
if (current.subcommands && current.subcommands[path[i]]) {
|
|
164
|
+
current = current.subcommands[path[i]];
|
|
165
|
+
options = { ...options, ...current.options };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return options;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Finds the long option name for a short flag
|
|
173
|
+
*/
|
|
174
|
+
function findLongOption(shortFlag, options) {
|
|
175
|
+
for (const [name, option] of Object.entries(options)) {
|
|
176
|
+
if (option.short === shortFlag) {
|
|
177
|
+
return name;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Parses an option value based on its definition
|
|
184
|
+
*/
|
|
185
|
+
function parseOptionValue(value, optionDef) {
|
|
186
|
+
if (!optionDef) {
|
|
187
|
+
// No definition, try to infer type
|
|
188
|
+
if (value === 'true')
|
|
189
|
+
return true;
|
|
190
|
+
if (value === 'false')
|
|
191
|
+
return false;
|
|
192
|
+
if (/^\d+$/.test(value))
|
|
193
|
+
return parseInt(value, 10);
|
|
194
|
+
if (/^\d*\.\d+$/.test(value))
|
|
195
|
+
return parseFloat(value);
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
// Use default type from option definition
|
|
199
|
+
const defaultValue = optionDef.default;
|
|
200
|
+
if (typeof defaultValue === 'boolean') {
|
|
201
|
+
return value === 'true' || value === '1' || value === 'yes';
|
|
202
|
+
}
|
|
203
|
+
if (typeof defaultValue === 'number') {
|
|
204
|
+
return parseFloat(value);
|
|
205
|
+
}
|
|
206
|
+
// Check choices
|
|
207
|
+
if (optionDef.choices && !optionDef.choices.includes(value)) {
|
|
208
|
+
// Invalid choice, but return anyway (validation will catch it)
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
return value;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Maps positional arguments to named parameters
|
|
215
|
+
*/
|
|
216
|
+
function mapPositionalArguments(positionalDefs, args, result) {
|
|
217
|
+
let argIndex = 0;
|
|
218
|
+
for (const def of positionalDefs) {
|
|
219
|
+
if (def.variadic) {
|
|
220
|
+
// Collect all remaining arguments
|
|
221
|
+
if (argIndex < args.length) {
|
|
222
|
+
result.positionals[def.name] = args.slice(argIndex);
|
|
223
|
+
argIndex = args.length;
|
|
224
|
+
}
|
|
225
|
+
else if (def.required) {
|
|
226
|
+
result.errors.push(`Missing required argument: ${def.name}`);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
result.positionals[def.name] = [];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
// Single argument
|
|
234
|
+
if (argIndex < args.length) {
|
|
235
|
+
result.positionals[def.name] = args[argIndex];
|
|
236
|
+
argIndex++;
|
|
237
|
+
}
|
|
238
|
+
else if (def.required) {
|
|
239
|
+
result.errors.push(`Missing required argument: ${def.name}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Check for extra positional arguments
|
|
244
|
+
if (argIndex < args.length) {
|
|
245
|
+
result.errors.push(`Unexpected arguments: ${args.slice(argIndex).join(' ')}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Applies option defaults and validates choices
|
|
250
|
+
*/
|
|
251
|
+
function applyOptionDefaults(optionDefs, options, result) {
|
|
252
|
+
for (const [name, def] of Object.entries(optionDefs)) {
|
|
253
|
+
// Apply default if not provided
|
|
254
|
+
if (!(name in options) && def.default !== undefined) {
|
|
255
|
+
options[name] = def.default;
|
|
256
|
+
}
|
|
257
|
+
// Check required
|
|
258
|
+
if (def.required && !(name in options)) {
|
|
259
|
+
result.errors.push(`Missing required option: --${name}`);
|
|
260
|
+
}
|
|
261
|
+
// Validate choices
|
|
262
|
+
if (def.choices && name in options) {
|
|
263
|
+
const value = options[name];
|
|
264
|
+
if (Array.isArray(value)) {
|
|
265
|
+
for (const v of value) {
|
|
266
|
+
if (!def.choices.includes(v)) {
|
|
267
|
+
result.errors.push(`Invalid value for --${name}: ${v}. Valid choices: ${def.choices.join(', ')}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else if (!def.choices.includes(value)) {
|
|
272
|
+
result.errors.push(`Invalid value for --${name}: ${value}. Valid choices: ${def.choices.join(', ')}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Generates help text for a command in a specific program
|
|
279
|
+
*/
|
|
280
|
+
export function generateCommandHelp(programName, allMeta, commandPath = []) {
|
|
281
|
+
const lines = [];
|
|
282
|
+
const meta = allMeta[programName];
|
|
283
|
+
if (!meta) {
|
|
284
|
+
return `Program not found: ${programName}`;
|
|
285
|
+
}
|
|
286
|
+
if (commandPath.length === 0) {
|
|
287
|
+
// Root help for the program
|
|
288
|
+
lines.push(`Usage: ${programName} <command> [options]`);
|
|
289
|
+
lines.push('');
|
|
290
|
+
lines.push('Commands:');
|
|
291
|
+
for (const [name, cmd] of Object.entries(meta.commands)) {
|
|
292
|
+
const desc = cmd.description || '';
|
|
293
|
+
lines.push(` ${name.padEnd(20)} ${desc}`);
|
|
294
|
+
}
|
|
295
|
+
if (Object.keys(meta.options).length > 0) {
|
|
296
|
+
lines.push('');
|
|
297
|
+
lines.push('Options:');
|
|
298
|
+
formatOptions(meta.options, lines);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
// Command-specific help
|
|
303
|
+
const commandMeta = getCommandMeta(meta, commandPath);
|
|
304
|
+
if (!commandMeta) {
|
|
305
|
+
return `Unknown command: ${commandPath.join(' ')}`;
|
|
306
|
+
}
|
|
307
|
+
// Usage line
|
|
308
|
+
let usage = `${programName} ${commandPath.join(' ')}`;
|
|
309
|
+
if (commandMeta.parameters) {
|
|
310
|
+
usage += ' ' + commandMeta.parameters;
|
|
311
|
+
}
|
|
312
|
+
lines.push(`Usage: ${usage} [options]`);
|
|
313
|
+
if (commandMeta.description) {
|
|
314
|
+
lines.push('');
|
|
315
|
+
lines.push(commandMeta.description);
|
|
316
|
+
}
|
|
317
|
+
// Positional arguments
|
|
318
|
+
if (commandMeta.positionals.length > 0) {
|
|
319
|
+
lines.push('');
|
|
320
|
+
lines.push('Arguments:');
|
|
321
|
+
for (const pos of commandMeta.positionals) {
|
|
322
|
+
const marker = pos.required ? '<required>' : '[optional]';
|
|
323
|
+
const variadic = pos.variadic ? '...' : '';
|
|
324
|
+
lines.push(` ${pos.name}${variadic} ${marker}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
// Subcommands
|
|
328
|
+
if (commandMeta.subcommands &&
|
|
329
|
+
Object.keys(commandMeta.subcommands).length > 0) {
|
|
330
|
+
lines.push('');
|
|
331
|
+
lines.push('Subcommands:');
|
|
332
|
+
for (const [name, sub] of Object.entries(commandMeta.subcommands)) {
|
|
333
|
+
const desc = sub.description || '';
|
|
334
|
+
lines.push(` ${name.padEnd(20)} ${desc}`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// Options
|
|
338
|
+
const availableOptions = collectAvailableOptions(meta, commandPath);
|
|
339
|
+
if (Object.keys(availableOptions).length > 0) {
|
|
340
|
+
lines.push('');
|
|
341
|
+
lines.push('Options:');
|
|
342
|
+
formatOptions(availableOptions, lines);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return lines.join('\n');
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Formats options for help text
|
|
349
|
+
*/
|
|
350
|
+
function formatOptions(options, lines) {
|
|
351
|
+
for (const [name, opt] of Object.entries(options)) {
|
|
352
|
+
let line = ' ';
|
|
353
|
+
if (opt.short) {
|
|
354
|
+
line += `-${opt.short}, `;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
line += ' ';
|
|
358
|
+
}
|
|
359
|
+
line += `--${name}`;
|
|
360
|
+
if (opt.default !== undefined && typeof opt.default !== 'boolean') {
|
|
361
|
+
line += ` <value>`;
|
|
362
|
+
}
|
|
363
|
+
line = line.padEnd(30);
|
|
364
|
+
line += opt.description || '';
|
|
365
|
+
if (opt.default !== undefined) {
|
|
366
|
+
line += ` (default: ${JSON.stringify(opt.default)})`;
|
|
367
|
+
}
|
|
368
|
+
if (opt.choices) {
|
|
369
|
+
line += ` [choices: ${opt.choices.join(', ')}]`;
|
|
370
|
+
}
|
|
371
|
+
lines.push(line);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * from './cli.types.js';
|
|
2
|
+
export * from './cli-runner.js';
|
|
3
|
+
export * from './command-parser.js';
|
|
4
|
+
export { wireCLI, runCLICommand, pikkuCLIRender, executeCLI, } from './cli-runner.js';
|
|
5
|
+
export { parseCLIArguments, generateCommandHelp } from './command-parser.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * from './cli.types.js';
|
|
2
|
+
export * from './cli-runner.js';
|
|
3
|
+
export * from './command-parser.js';
|
|
4
|
+
export { wireCLI, runCLICommand, pikkuCLIRender, executeCLI, } from './cli-runner.js';
|
|
5
|
+
export { parseCLIArguments, generateCommandHelp } from './command-parser.js';
|
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
import { CoreHTTPFunctionWiring, RunHTTPWiringOptions, RunHTTPWiringParams, PikkuHTTP, PikkuHTTPRequest, PikkuHTTPResponse } from './http.types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { CorePikkuFunction, CorePikkuFunctionSessionless, CorePikkuPermission } from '../../function/functions.types.js';
|
|
3
|
+
import { CorePikkuMiddleware, CorePikkuMiddlewareGroup } from '../../types/core.types.js';
|
|
3
4
|
import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
|
|
4
5
|
/**
|
|
5
|
-
* Registers middleware
|
|
6
|
+
* Registers HTTP middleware for a specific route pattern.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* This function registers middleware at runtime that will be applied to
|
|
9
|
+
* HTTP routes matching the specified pattern.
|
|
10
|
+
*
|
|
11
|
+
* For tree-shaking benefits, wrap in a factory function:
|
|
12
|
+
* `export const x = () => addHTTPMiddleware('pattern', [...])`
|
|
10
13
|
*
|
|
11
14
|
* @template PikkuMiddleware The middleware type.
|
|
12
|
-
* @param {
|
|
13
|
-
* @param {
|
|
15
|
+
* @param {string} pattern - Route pattern (e.g., '*' for all routes, '/api/*' for specific routes).
|
|
16
|
+
* @param {CorePikkuMiddlewareGroup} middleware - Array of middleware for this route pattern.
|
|
17
|
+
*
|
|
18
|
+
* @returns {CorePikkuMiddlewareGroup} The middleware array (for chaining/wrapping).
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // Recommended: tree-shakeable
|
|
23
|
+
* export const httpGlobal = () => addHTTPMiddleware('*', [
|
|
24
|
+
* corsMiddleware,
|
|
25
|
+
* loggingMiddleware
|
|
26
|
+
* ])
|
|
27
|
+
*
|
|
28
|
+
* // Also works: no tree-shaking
|
|
29
|
+
* export const apiMiddleware = addHTTPMiddleware('/api/*', [
|
|
30
|
+
* authMiddleware
|
|
31
|
+
* ])
|
|
32
|
+
* ```
|
|
14
33
|
*/
|
|
15
|
-
export declare const addHTTPMiddleware: <PikkuMiddleware extends CorePikkuMiddleware>(
|
|
34
|
+
export declare const addHTTPMiddleware: <PikkuMiddleware extends CorePikkuMiddleware>(pattern: string, middleware: CorePikkuMiddlewareGroup) => CorePikkuMiddlewareGroup;
|
|
16
35
|
/**
|
|
17
36
|
* Adds a new route to the global HTTP route registry.
|
|
18
37
|
*
|
|
@@ -28,7 +47,7 @@ export declare const addHTTPMiddleware: <PikkuMiddleware extends CorePikkuMiddle
|
|
|
28
47
|
* @template PikkuMiddleware Middleware type to be used with the route.
|
|
29
48
|
* @param {CoreHTTPFunctionWiring<In, Out, Route, PikkuFunction, PikkuFunctionSessionless, PikkuPermission, PikkuMiddleware>} httpWiring - The HTTP wiring configuration object.
|
|
30
49
|
*/
|
|
31
|
-
export declare const wireHTTP: <In, Out, Route extends string, PikkuFunction, PikkuFunctionSessionless,
|
|
50
|
+
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;
|
|
32
51
|
/**
|
|
33
52
|
* Combines the request and response objects into a single HTTP interaction object.
|
|
34
53
|
*
|
|
@@ -87,4 +106,4 @@ export declare const pikkuFetch: <In, Out>(request: Request | PikkuHTTPRequest,
|
|
|
87
106
|
* @param {RunHTTPWiringOptions & RunHTTPWiringParams} options - Options such as singleton services, session handling, and error configuration.
|
|
88
107
|
* @returns {Promise<Out | void>} The output from the route handler or void if an error occurred.
|
|
89
108
|
*/
|
|
90
|
-
export declare const fetchData: <In, Out>(request: Request | PikkuHTTPRequest, response: PikkuHTTPResponse, { singletonServices, createSessionServices, skipUserSession, respondWith404, logWarningsForStatusCodes, coerceDataFromSchema, bubbleErrors, generateRequestId,
|
|
109
|
+
export declare const fetchData: <In, Out>(request: Request | PikkuHTTPRequest, response: PikkuHTTPResponse, { singletonServices, createSessionServices, skipUserSession, respondWith404, logWarningsForStatusCodes, coerceDataFromSchema, bubbleErrors, generateRequestId, }: RunHTTPWiringOptions & RunHTTPWiringParams) => Promise<Out | void>;
|