@pikku/cli 0.12.19 → 0.12.21
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/console-app/assets/{index-DAQHIRK3.js → index-DXLy-_D4.js} +181 -181
- package/console-app/index.html +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +6 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +32 -2
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +8 -2
- package/dist/.pikku/function/pikku-function-types.gen.js +4 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +223 -121
- package/dist/.pikku/function/pikku-functions.gen.js +13 -9
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +2 -1
- package/dist/.pikku/pikku-services.gen.js +1 -0
- package/dist/.pikku/pikku-types.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +15 -9
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +13 -7
- package/dist/.pikku/schemas/schemas/DevInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuCommandHTTPOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuCommandQueueOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/WorkflowRunStatus.schema.json +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/meta/allWorkflow.gen.json +623 -154
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/src/cli.wiring.js +32 -2
- package/dist/src/deploy/analyzer/manifest.d.ts +10 -0
- package/dist/src/deploy/build-pipeline.d.ts +2 -0
- package/dist/src/deploy/build-pipeline.js +44 -6
- package/dist/src/deploy/bundler/bundler.d.ts +2 -1
- package/dist/src/deploy/bundler/bundler.js +28 -5
- package/dist/src/deploy/bundler/dep-extractor.d.ts +5 -2
- package/dist/src/deploy/bundler/dep-extractor.js +103 -23
- package/dist/src/deploy/bundler/types.d.ts +5 -1
- package/dist/src/deploy/codegen/per-unit-codegen.d.ts +3 -1
- package/dist/src/deploy/codegen/per-unit-codegen.js +3 -1
- package/dist/src/deploy/plan/planner.js +25 -3
- package/dist/src/deploy/plan/provider.d.ts +2 -0
- package/dist/src/functions/commands/deploy-apply.js +6 -4
- package/dist/src/functions/commands/deploy-plan.js +7 -1
- package/dist/src/functions/commands/dev.d.ts +13 -0
- package/dist/src/functions/commands/dev.js +187 -0
- package/dist/src/functions/commands/pikku-command-summary.js +4 -1
- package/dist/src/functions/commands/versions-update.js +9 -3
- package/dist/src/functions/wirings/channels/pikku-command-channels.d.ts +1 -1
- package/dist/src/functions/wirings/channels/pikku-command-channels.js +1 -1
- package/dist/src/functions/wirings/console/pikku-command-console-functions.js +5 -1
- package/dist/src/functions/wirings/functions/serialize-function-types.js +31 -1
- package/dist/src/functions/wirings/http/pikku-command-http-routes.d.ts +1 -1
- package/dist/src/functions/wirings/http/pikku-command-http-routes.js +1 -1
- package/dist/src/functions/wirings/queue/pikku-command-queue-map.d.ts +1 -1
- package/dist/src/functions/wirings/queue/pikku-command-queue-map.js +1 -1
- package/dist/src/functions/wirings/queue/pikku-command-queue.d.ts +1 -1
- package/dist/src/functions/wirings/queue/pikku-command-queue.js +1 -1
- package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.js +5 -1
- package/dist/src/functions/wirings/rpc/pikku-command-remote-rpc.js +5 -1
- package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.js +16 -2
- package/dist/src/functions/wirings/workflow/serialize-workflow-routes.js +44 -2
- package/dist/src/functions/workflows/all.workflow.js +5 -10
- package/dist/src/scaffold/rpc-remote.gen.js +1 -1
- package/dist/src/scaffold/workflow-routes.gen.js +36 -4
- package/dist/src/services/cli-logger.service.d.ts +22 -2
- package/dist/src/services/cli-logger.service.js +97 -21
- package/dist/src/services.js +8 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -4
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +0 -10
- package/dist/.pikku/cli/pikku-cli-client.gen.js +0 -44
- /package/dist/.pikku/schemas/schemas/{PikkuChannelsOutput.schema.json → PikkuCommandChannelsOutput.schema.json} +0 -0
|
@@ -94,7 +94,6 @@ export async function resolveProvider(config, providerName) {
|
|
|
94
94
|
}
|
|
95
95
|
const ANSI = {
|
|
96
96
|
green: '\x1b[32m',
|
|
97
|
-
red: '\x1b[31m',
|
|
98
97
|
bold: '\x1b[1m',
|
|
99
98
|
reset: '\x1b[0m',
|
|
100
99
|
};
|
|
@@ -119,8 +118,12 @@ async function runDeploy(provider, providerDir, logger, resultFile) {
|
|
|
119
118
|
deployResult = await provider.deploy({
|
|
120
119
|
buildDir: providerDir,
|
|
121
120
|
logger,
|
|
122
|
-
onProgress: (
|
|
123
|
-
|
|
121
|
+
onProgress: (step, detail) => {
|
|
122
|
+
logger.info({
|
|
123
|
+
message: `[${step}] ${detail}`,
|
|
124
|
+
type: 'progress',
|
|
125
|
+
data: { progress: { step, detail } },
|
|
126
|
+
});
|
|
124
127
|
},
|
|
125
128
|
});
|
|
126
129
|
}
|
|
@@ -132,7 +135,6 @@ async function runDeploy(provider, providerDir, logger, resultFile) {
|
|
|
132
135
|
};
|
|
133
136
|
}
|
|
134
137
|
await writeResultFile(resultFile, deployResult);
|
|
135
|
-
console.log('');
|
|
136
138
|
if (deployResult.success) {
|
|
137
139
|
logger.info(`${ANSI.green}${ANSI.bold}Deployment complete.${ANSI.reset}`);
|
|
138
140
|
logger.info(` ${deployResult.workersDeployed?.length ?? 0} units deployed, ${deployResult.resourcesCreated?.length ?? 0} resources created`);
|
|
@@ -89,7 +89,13 @@ export const deployPlan = pikkuSessionlessFunc({
|
|
|
89
89
|
unitCount: result.bundled.length,
|
|
90
90
|
totalSizeBytes: totalSize,
|
|
91
91
|
errors: result.bundleErrors,
|
|
92
|
-
|
|
92
|
+
codegenErrors: result.codegenErrors,
|
|
93
|
+
summary: plan.summary,
|
|
94
|
+
changeCount: plan.changes.length,
|
|
95
|
+
artifacts: {
|
|
96
|
+
deploymentManifestPath: result.deploymentManifestPath,
|
|
97
|
+
infraPath: result.infraPath,
|
|
98
|
+
},
|
|
93
99
|
}, null, 2), 'utf-8');
|
|
94
100
|
}
|
|
95
101
|
},
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const dev: import("#pikku").PikkuFunctionConfig<{
|
|
2
|
+
port?: string;
|
|
3
|
+
watch?: boolean;
|
|
4
|
+
hmr?: boolean;
|
|
5
|
+
}, void, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<{
|
|
6
|
+
port?: string;
|
|
7
|
+
watch?: boolean;
|
|
8
|
+
hmr?: boolean;
|
|
9
|
+
}, void, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<{
|
|
10
|
+
port?: string;
|
|
11
|
+
watch?: boolean;
|
|
12
|
+
hmr?: boolean;
|
|
13
|
+
}, void, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { createServer } from 'http';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
|
+
import { Readable } from 'stream';
|
|
4
|
+
import { pikkuSessionlessFunc } from '#pikku';
|
|
5
|
+
import chokidar from 'chokidar';
|
|
6
|
+
import { pikkuDevReloader } from '@pikku/core/dev';
|
|
7
|
+
import { ConsoleLogger, InMemoryQueueService, InMemoryWorkflowService, InMemoryTriggerService, InMemoryAIRunStateService, } from '@pikku/core/services';
|
|
8
|
+
import { stopSingletonServices } from '@pikku/core';
|
|
9
|
+
import { pikkuState } from '@pikku/core/internal';
|
|
10
|
+
import { fetchData, PikkuFetchHTTPResponse, logRoutes, } from '@pikku/core/http';
|
|
11
|
+
import { compileAllSchemas } from '@pikku/core/schema';
|
|
12
|
+
import { pikkuWebsocketHandler } from '@pikku/ws';
|
|
13
|
+
import { WebSocketServer } from 'ws';
|
|
14
|
+
import { InMemorySchedulerService } from '@pikku/schedule';
|
|
15
|
+
function incomingMessageToRequest(req) {
|
|
16
|
+
const url = new URL(req.url || '/', 'http://localhost');
|
|
17
|
+
const method = req.method ? req.method.toUpperCase() : 'GET';
|
|
18
|
+
const headers = new Headers();
|
|
19
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
20
|
+
if (value) {
|
|
21
|
+
headers.set(key, Array.isArray(value) ? value.join(', ') : value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
let body = null;
|
|
25
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
26
|
+
body = Readable.toWeb(req);
|
|
27
|
+
}
|
|
28
|
+
return new Request(url.toString(), {
|
|
29
|
+
method,
|
|
30
|
+
headers,
|
|
31
|
+
body,
|
|
32
|
+
// @ts-ignore - duplex is needed for streaming body in Node.js
|
|
33
|
+
duplex: 'half',
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async function writeResponse(nodeRes, webResponse) {
|
|
37
|
+
const headers = {};
|
|
38
|
+
webResponse.headers.forEach((value, name) => {
|
|
39
|
+
const lower = name.toLowerCase();
|
|
40
|
+
if (lower === 'set-cookie') {
|
|
41
|
+
const existing = headers[lower];
|
|
42
|
+
if (Array.isArray(existing)) {
|
|
43
|
+
existing.push(value);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
headers[lower] = [value];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
headers[lower] = value;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
nodeRes.writeHead(webResponse.status, headers);
|
|
54
|
+
if (webResponse.body) {
|
|
55
|
+
const reader = webResponse.body.getReader();
|
|
56
|
+
try {
|
|
57
|
+
while (true) {
|
|
58
|
+
const { done, value } = await reader.read();
|
|
59
|
+
if (done)
|
|
60
|
+
break;
|
|
61
|
+
nodeRes.write(value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
reader.releaseLock();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
nodeRes.end();
|
|
69
|
+
}
|
|
70
|
+
export const dev = pikkuSessionlessFunc({
|
|
71
|
+
remote: true,
|
|
72
|
+
func: async ({ logger, config, getInspectorState }, { port, watch, hmr }, { rpc }) => {
|
|
73
|
+
const resolvedPort = parseInt(port || '3000', 10);
|
|
74
|
+
const hostname = 'localhost';
|
|
75
|
+
const enableWatch = watch !== false;
|
|
76
|
+
const enableHmr = hmr !== false;
|
|
77
|
+
await rpc.invoke('all');
|
|
78
|
+
const inspectorState = await getInspectorState(true);
|
|
79
|
+
const { pikkuConfigFactory, singletonServicesFactory } = inspectorState.filesAndMethods;
|
|
80
|
+
if (!pikkuConfigFactory || !singletonServicesFactory) {
|
|
81
|
+
logger.error('createConfig and createSingletonServices must be defined in your project');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const pikkuDir = resolve(config.rootDir, config.outDir);
|
|
85
|
+
const bootstrapPath = join(pikkuDir, 'pikku-bootstrap.gen.js');
|
|
86
|
+
await import(bootstrapPath);
|
|
87
|
+
const configModule = await import(pikkuConfigFactory.file);
|
|
88
|
+
const servicesModule = await import(singletonServicesFactory.file);
|
|
89
|
+
const userCreateConfig = configModule[pikkuConfigFactory.variable];
|
|
90
|
+
const userCreateSingletonServices = servicesModule[singletonServicesFactory.variable];
|
|
91
|
+
const userConfig = await userCreateConfig();
|
|
92
|
+
const schedulerService = new InMemorySchedulerService();
|
|
93
|
+
const inMemoryServices = {
|
|
94
|
+
logger: new ConsoleLogger(),
|
|
95
|
+
schedulerService,
|
|
96
|
+
queueService: new InMemoryQueueService(),
|
|
97
|
+
workflowService: new InMemoryWorkflowService(),
|
|
98
|
+
triggerService: new InMemoryTriggerService(),
|
|
99
|
+
aiRunStateService: new InMemoryAIRunStateService(),
|
|
100
|
+
};
|
|
101
|
+
const singletonServices = await userCreateSingletonServices(userConfig, inMemoryServices);
|
|
102
|
+
pikkuState(null, 'package', 'singletonServices', singletonServices);
|
|
103
|
+
compileAllSchemas(logger);
|
|
104
|
+
logRoutes(logger);
|
|
105
|
+
const server = createServer(async (req, res) => {
|
|
106
|
+
const request = incomingMessageToRequest(req);
|
|
107
|
+
const pikkuResponse = new PikkuFetchHTTPResponse();
|
|
108
|
+
await fetchData(request, pikkuResponse, { respondWith404: true });
|
|
109
|
+
const response = pikkuResponse.toResponse();
|
|
110
|
+
await writeResponse(res, response);
|
|
111
|
+
});
|
|
112
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
113
|
+
pikkuWebsocketHandler({ server, wss, logger });
|
|
114
|
+
await schedulerService.start();
|
|
115
|
+
await new Promise((resolve) => {
|
|
116
|
+
server.listen(resolvedPort, hostname, () => {
|
|
117
|
+
logger.info(`Dev server running at http://${hostname}:${resolvedPort}`);
|
|
118
|
+
resolve();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
let configWatcher;
|
|
122
|
+
let watcher;
|
|
123
|
+
process.once('SIGINT', async () => {
|
|
124
|
+
logger.info('Stopping dev server...');
|
|
125
|
+
try {
|
|
126
|
+
await stopSingletonServices();
|
|
127
|
+
await configWatcher?.close();
|
|
128
|
+
await watcher?.close();
|
|
129
|
+
await new Promise((resolve, reject) => wss.close((err) => (err ? reject(err) : resolve())));
|
|
130
|
+
await new Promise((resolve, reject) => server.close((err) => (err ? reject(err) : resolve())));
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
process.exit(0);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
if (enableHmr) {
|
|
137
|
+
await pikkuDevReloader({
|
|
138
|
+
srcDirectories: config.srcDirectories,
|
|
139
|
+
logger,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (enableWatch) {
|
|
143
|
+
const genIgnore = /\.gen\.tsx?$/;
|
|
144
|
+
configWatcher = chokidar.watch(config.srcDirectories, {
|
|
145
|
+
ignoreInitial: true,
|
|
146
|
+
ignored: genIgnore,
|
|
147
|
+
});
|
|
148
|
+
const generatorWatcher = () => {
|
|
149
|
+
watcher?.close();
|
|
150
|
+
logger.info(`• Watching directories: \n - ${config.srcDirectories.join('\n - ')}`);
|
|
151
|
+
watcher = chokidar.watch(config.srcDirectories, {
|
|
152
|
+
ignoreInitial: true,
|
|
153
|
+
ignored: genIgnore,
|
|
154
|
+
});
|
|
155
|
+
watcher.on('ready', async () => {
|
|
156
|
+
const handle = async () => {
|
|
157
|
+
try {
|
|
158
|
+
const start = Date.now();
|
|
159
|
+
await rpc.invoke('all');
|
|
160
|
+
logger.info({
|
|
161
|
+
message: `✓ Generated in ${Date.now() - start}ms`,
|
|
162
|
+
type: 'timing',
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
logger.error(`Error running watch: ${err}`);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
await handle();
|
|
170
|
+
let timeout;
|
|
171
|
+
const deduped = (_file) => {
|
|
172
|
+
if (timeout) {
|
|
173
|
+
clearTimeout(timeout);
|
|
174
|
+
}
|
|
175
|
+
timeout = setTimeout(handle, 10);
|
|
176
|
+
};
|
|
177
|
+
watcher?.on('change', deduped);
|
|
178
|
+
watcher?.on('add', deduped);
|
|
179
|
+
watcher?.on('unlink', deduped);
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
configWatcher.on('ready', generatorWatcher);
|
|
183
|
+
configWatcher.on('change', generatorWatcher);
|
|
184
|
+
}
|
|
185
|
+
await new Promise(() => { });
|
|
186
|
+
},
|
|
187
|
+
});
|
|
@@ -49,7 +49,10 @@ export const pikkuSummary = pikkuSessionlessFunc({
|
|
|
49
49
|
summary.set('workflowGraphs', workflowGraphsCount);
|
|
50
50
|
}
|
|
51
51
|
if (!logger.isSilent()) {
|
|
52
|
-
|
|
52
|
+
// Route through the logger so JSON mode emits a single NDJSON
|
|
53
|
+
// record instead of raw chalk-coloured text written directly to
|
|
54
|
+
// stdout (which would break NDJSON consumers).
|
|
55
|
+
logger.info({ message: summary.format(), type: 'summary' });
|
|
53
56
|
}
|
|
54
57
|
},
|
|
55
58
|
});
|
|
@@ -7,12 +7,18 @@ export const pikkuVersionsUpdate = pikkuSessionlessFunc({
|
|
|
7
7
|
const manifestPath = join(config.rootDir, 'versions.pikku.json');
|
|
8
8
|
const visitState = await getInspectorState();
|
|
9
9
|
if (!visitState.manifest.initial) {
|
|
10
|
-
|
|
10
|
+
logger.warn(`Run 'pikku versions init' to enable contract versioning.`);
|
|
11
|
+
return;
|
|
11
12
|
}
|
|
12
13
|
const immutabilityErrors = visitState.manifest.errors.filter((e) => e.code === ErrorCode.FUNCTION_VERSION_MODIFIED);
|
|
13
14
|
if (immutabilityErrors.length > 0) {
|
|
14
|
-
const
|
|
15
|
-
|
|
15
|
+
for (const e of immutabilityErrors) {
|
|
16
|
+
logger.critical(ErrorCode.FUNCTION_VERSION_MODIFIED, e.message);
|
|
17
|
+
}
|
|
18
|
+
if (logger.hasCriticalErrors()) {
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
return;
|
|
16
22
|
}
|
|
17
23
|
await saveManifest(manifestPath, visitState.manifest.current);
|
|
18
24
|
logger.debug(`Version manifest updated at ${manifestPath}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const pikkuCommandChannels: import("#pikku").PikkuFunctionConfig<void, boolean | undefined, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<void, boolean | undefined, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<void, boolean | undefined, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -4,7 +4,7 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
|
|
6
6
|
import { stripVerboseFields, hasVerboseFields, } from '../../../utils/strip-verbose-meta.js';
|
|
7
|
-
export const
|
|
7
|
+
export const pikkuCommandChannels = pikkuSessionlessFunc({
|
|
8
8
|
func: async ({ logger, config, getInspectorState }) => {
|
|
9
9
|
const visitState = await getInspectorState();
|
|
10
10
|
const { channelsWiringFile, channelsWiringMetaFile, channelsWiringMetaJsonFile, packageMappings, schema, } = config;
|
|
@@ -4,7 +4,11 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { serializeConsoleFunctions } from './serialize-console-functions.js';
|
|
6
6
|
export const pikkuConsoleFunctions = pikkuSessionlessFunc({
|
|
7
|
-
func: async ({ logger, config }) => {
|
|
7
|
+
func: async ({ logger, config, variables }) => {
|
|
8
|
+
const deployCodegenFlag = await variables.get('PIKKU_DEPLOY_CODEGEN');
|
|
9
|
+
if (deployCodegenFlag === '1') {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
8
12
|
if (config.scaffold?.console) {
|
|
9
13
|
const pathToPikkuTypes = getFileImportRelativePath(config.consoleFunctionsFile, config.typesDeclarationFile, config.packageMappings);
|
|
10
14
|
const pathToAgentTypes = getFileImportRelativePath(config.consoleFunctionsFile, config.agentTypesFile, config.packageMappings);
|
|
@@ -12,7 +12,7 @@ export const serializeFunctionTypes = (userSessionTypeImport, userSessionTypeNam
|
|
|
12
12
|
* Core function, middleware, and permission types for all wirings
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import type { CorePikkuMiddleware, CorePermissionGroup, PikkuWire, PickRequired } from '@pikku/core'
|
|
15
|
+
import type { CorePikkuMiddleware, CorePermissionGroup, ListInput, ListOutput, PikkuWire, PickRequired } from '@pikku/core'
|
|
16
16
|
import type { CorePikkuFunctionConfig, CorePikkuAuth, CorePikkuAuthConfig, CorePikkuPermission } from '@pikku/core/function'
|
|
17
17
|
import { pikkuAuth as pikkuAuthCore } from '@pikku/core/function'
|
|
18
18
|
import { addMiddleware as addMiddlewareCore, addPermission as addPermissionCore } from '@pikku/core/middleware'
|
|
@@ -338,10 +338,13 @@ export type PikkuFunctionConfigWithSchema<
|
|
|
338
338
|
RequiredWires extends keyof PikkuWire = never
|
|
339
339
|
> = {
|
|
340
340
|
name?: string
|
|
341
|
+
description?: string
|
|
341
342
|
tags?: string[]
|
|
342
343
|
expose?: boolean
|
|
343
344
|
mcp?: boolean
|
|
344
345
|
internal?: boolean
|
|
346
|
+
remote?: boolean
|
|
347
|
+
deploy?: 'serverless' | 'server' | 'auto'
|
|
345
348
|
approvalRequired?: boolean
|
|
346
349
|
approvalDescription?: InputSchema extends StandardSchemaV1 ? PikkuApprovalDescription<InferSchemaOutput<InputSchema>> : never
|
|
347
350
|
func: PikkuFunction<
|
|
@@ -415,6 +418,32 @@ export function pikkuFunc(func: any) {
|
|
|
415
418
|
return typeof func === 'function' ? { func } : func
|
|
416
419
|
}
|
|
417
420
|
|
|
421
|
+
export type PikkuListFunction<
|
|
422
|
+
F extends Record<string, unknown> = {},
|
|
423
|
+
Row = unknown,
|
|
424
|
+
S extends string = never
|
|
425
|
+
> =
|
|
426
|
+
| PikkuFunction<ListInput<F, S>, ListOutput<Row>, 'session' | 'rpc'>
|
|
427
|
+
| PikkuFunctionSessionless<
|
|
428
|
+
ListInput<F, S>,
|
|
429
|
+
ListOutput<Row>,
|
|
430
|
+
'session' | 'rpc'
|
|
431
|
+
>
|
|
432
|
+
|
|
433
|
+
export const pikkuListFunc = <
|
|
434
|
+
F extends Record<string, unknown> = {},
|
|
435
|
+
Row = unknown,
|
|
436
|
+
S extends string = never
|
|
437
|
+
>(
|
|
438
|
+
config: PikkuFunctionConfig<
|
|
439
|
+
ListInput<F, S>,
|
|
440
|
+
ListOutput<Row>,
|
|
441
|
+
'session' | 'rpc'
|
|
442
|
+
>
|
|
443
|
+
): PikkuFunctionConfig<ListInput<F, S>, ListOutput<Row>, 'session' | 'rpc'> => {
|
|
444
|
+
return pikkuFunc(config)
|
|
445
|
+
}
|
|
446
|
+
|
|
418
447
|
/**
|
|
419
448
|
* Configuration object for sessionless Pikku functions with Zod schema validation.
|
|
420
449
|
*/
|
|
@@ -430,6 +459,7 @@ export type PikkuFunctionSessionlessConfigWithSchema<
|
|
|
430
459
|
mcp?: boolean
|
|
431
460
|
internal?: boolean
|
|
432
461
|
remote?: boolean
|
|
462
|
+
deploy?: 'serverless' | 'server' | 'auto'
|
|
433
463
|
approvalRequired?: boolean
|
|
434
464
|
approvalDescription?: InputSchema extends StandardSchemaV1 ? PikkuApprovalDescription<InferSchemaOutput<InputSchema>> : never
|
|
435
465
|
func: PikkuFunctionSessionless<
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const pikkuCommandHTTP: import("#pikku").PikkuFunctionConfig<void, boolean | undefined, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<void, boolean | undefined, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<void, boolean | undefined, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -4,7 +4,7 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
|
|
6
6
|
import { stripVerboseFields, hasVerboseFields, } from '../../../utils/strip-verbose-meta.js';
|
|
7
|
-
export const
|
|
7
|
+
export const pikkuCommandHTTP = pikkuSessionlessFunc({
|
|
8
8
|
func: async ({ logger, config, getInspectorState }) => {
|
|
9
9
|
const visitState = await getInspectorState();
|
|
10
10
|
const { httpWiringsFile, httpWiringMetaFile, httpWiringMetaJsonFile, packageMappings, schema, } = config;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const pikkuCommandQueueMap: import("#pikku").PikkuFunctionConfig<void, void, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<void, void, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<void, void, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -2,7 +2,7 @@ import { pikkuSessionlessFunc } from '#pikku';
|
|
|
2
2
|
import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
3
3
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
4
4
|
import { serializeQueueMap } from './serialize-queue-map.js';
|
|
5
|
-
export const
|
|
5
|
+
export const pikkuCommandQueueMap = pikkuSessionlessFunc({
|
|
6
6
|
func: async ({ logger, config, getInspectorState }) => {
|
|
7
7
|
const { queueWorkers, functions, resolvedIOTypes } = await getInspectorState();
|
|
8
8
|
const { queueMapDeclarationFile, packageMappings } = config;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const pikkuCommandQueue: import("#pikku").PikkuFunctionConfig<void, boolean | undefined, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<void, boolean | undefined, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<void, boolean | undefined, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -5,7 +5,7 @@ import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-
|
|
|
5
5
|
import { serializeQueueMeta, serializeQueueMetaTS, } from './serialize-queue-meta.js';
|
|
6
6
|
import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
|
|
7
7
|
import { stripVerboseFields, hasVerboseFields, } from '../../../utils/strip-verbose-meta.js';
|
|
8
|
-
export const
|
|
8
|
+
export const pikkuCommandQueue = pikkuSessionlessFunc({
|
|
9
9
|
func: async ({ logger, config, getInspectorState }) => {
|
|
10
10
|
const visitState = await getInspectorState();
|
|
11
11
|
const { queueWorkersWiringFile, queueWorkersWiringMetaFile, queueWorkersWiringMetaJsonFile, packageMappings, schema, } = config;
|
|
@@ -4,7 +4,11 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { serializePublicRPC } from './serialize-public-rpc.js';
|
|
6
6
|
export const pikkuPublicRPC = pikkuSessionlessFunc({
|
|
7
|
-
func: async ({ logger, config }) => {
|
|
7
|
+
func: async ({ logger, config, variables }) => {
|
|
8
|
+
const deployCodegenFlag = await variables.get('PIKKU_DEPLOY_CODEGEN');
|
|
9
|
+
if (deployCodegenFlag === '1') {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
8
12
|
if (config.scaffold?.rpc) {
|
|
9
13
|
const pathToPikkuTypes = getFileImportRelativePath(config.publicRpcFile, config.typesDeclarationFile, config.packageMappings);
|
|
10
14
|
await writeFileInDir(logger, config.publicRpcFile, serializePublicRPC(pathToPikkuTypes, config.scaffold.rpc === 'auth', config.globalHTTPPrefix || ''));
|
|
@@ -4,7 +4,11 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { serializeRemoteRPC } from './serialize-remote-rpc.js';
|
|
6
6
|
export const pikkuRemoteRPC = pikkuSessionlessFunc({
|
|
7
|
-
func: async ({ logger, config }) => {
|
|
7
|
+
func: async ({ logger, config, variables }) => {
|
|
8
|
+
const deployCodegenFlag = await variables.get('PIKKU_DEPLOY_CODEGEN');
|
|
9
|
+
if (deployCodegenFlag === '1') {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
8
12
|
if (config.remoteRpcWorkersFile) {
|
|
9
13
|
const pathToPikkuTypes = getFileImportRelativePath(config.remoteRpcWorkersFile, config.typesDeclarationFile, config.packageMappings);
|
|
10
14
|
await writeFileInDir(logger, config.remoteRpcWorkersFile, serializeRemoteRPC(pathToPikkuTypes));
|
|
@@ -41,13 +41,13 @@ ${addonImports}
|
|
|
41
41
|
${mergedRPCMap}
|
|
42
42
|
|
|
43
43
|
export type RPCInvoke = <Name extends keyof FlattenedRPCMap>(
|
|
44
|
-
...args: FlattenedRPCMap[Name]['input'] extends
|
|
44
|
+
...args: IsVoidishInput<FlattenedRPCMap[Name]['input']> extends true
|
|
45
45
|
? [name: Name]
|
|
46
46
|
: [name: Name, data: FlattenedRPCMap[Name]['input']]
|
|
47
47
|
) => Promise<FlattenedRPCMap[Name]['output']>
|
|
48
48
|
|
|
49
49
|
export type RPCRemote = <Name extends keyof FlattenedRPCMap>(
|
|
50
|
-
...args: FlattenedRPCMap[Name]['input'] extends
|
|
50
|
+
...args: IsVoidishInput<FlattenedRPCMap[Name]['input']> extends true
|
|
51
51
|
? [name: Name]
|
|
52
52
|
: [name: Name, data: FlattenedRPCMap[Name]['input']]
|
|
53
53
|
) => Promise<FlattenedRPCMap[Name]['output']>
|
|
@@ -117,6 +117,13 @@ function generateMergedRPCMap(wireAddonDeclarations) {
|
|
|
117
117
|
return `
|
|
118
118
|
// No addon packages, use RPCMap directly
|
|
119
119
|
export type FlattenedRPCMap = RPCMap
|
|
120
|
+
|
|
121
|
+
type IsAny<T> = 0 extends (1 & T) ? true : false
|
|
122
|
+
type IsVoidishInput<T> = IsAny<T> extends true
|
|
123
|
+
? false
|
|
124
|
+
: [T] extends [void | null | undefined]
|
|
125
|
+
? true
|
|
126
|
+
: false
|
|
120
127
|
`;
|
|
121
128
|
}
|
|
122
129
|
// TypeScript utility to flatten namespaced RPC maps
|
|
@@ -131,6 +138,13 @@ export type FlattenedRPCMap =
|
|
|
131
138
|
RPCMap${Array.from(wireAddonDeclarations.keys())
|
|
132
139
|
.map((namespace) => ` & PrefixKeys<${toPascalCase(namespace)}RPCMap, '${namespace}'>`)
|
|
133
140
|
.join('')}
|
|
141
|
+
|
|
142
|
+
type IsAny<T> = 0 extends (1 & T) ? true : false
|
|
143
|
+
type IsVoidishInput<T> = IsAny<T> extends true
|
|
144
|
+
? false
|
|
145
|
+
: [T] extends [void | null | undefined]
|
|
146
|
+
? true
|
|
147
|
+
: false
|
|
134
148
|
`;
|
|
135
149
|
return utilityTypes;
|
|
136
150
|
}
|
|
@@ -25,7 +25,7 @@ export const workflowStarter = pikkuSessionlessFunc<
|
|
|
25
25
|
>({
|
|
26
26
|
auth: ${authFlag},
|
|
27
27
|
func: async (_services, { workflowName, data }, { rpc }) => {
|
|
28
|
-
return await rpc.startWorkflow(workflowName as any, data ?? {})
|
|
28
|
+
return await rpc.startWorkflow(workflowName as any, (data ?? {}) as any)
|
|
29
29
|
},
|
|
30
30
|
})
|
|
31
31
|
|
|
@@ -68,6 +68,7 @@ export const workflowStatusStream = pikkuSessionlessFunc<
|
|
|
68
68
|
|
|
69
69
|
const terminalStatuses = new Set(['completed', 'failed', 'cancelled'])
|
|
70
70
|
let lastHash = ''
|
|
71
|
+
let initSent = false
|
|
71
72
|
|
|
72
73
|
const poll = async () => {
|
|
73
74
|
const run = await workflowRunService.getRun(runId)
|
|
@@ -78,6 +79,26 @@ export const workflowStatusStream = pikkuSessionlessFunc<
|
|
|
78
79
|
|
|
79
80
|
const steps = await workflowRunService.getRunSteps(runId)
|
|
80
81
|
|
|
82
|
+
if (!initSent && run.deterministic) {
|
|
83
|
+
const statusByStep = new Map(
|
|
84
|
+
steps.map((s: { stepName: string; status: string }) => [
|
|
85
|
+
s.stepName,
|
|
86
|
+
s.status,
|
|
87
|
+
])
|
|
88
|
+
)
|
|
89
|
+
channel.send({
|
|
90
|
+
type: 'init',
|
|
91
|
+
deterministic: true,
|
|
92
|
+
steps: (run.plannedSteps ?? []).map(
|
|
93
|
+
(s: { stepName: string }) => ({
|
|
94
|
+
stepName: s.stepName,
|
|
95
|
+
status: statusByStep.get(s.stepName) ?? 'pending',
|
|
96
|
+
})
|
|
97
|
+
),
|
|
98
|
+
})
|
|
99
|
+
initSent = true
|
|
100
|
+
}
|
|
101
|
+
|
|
81
102
|
const hash = JSON.stringify({
|
|
82
103
|
s: run.status,
|
|
83
104
|
steps: steps.map((s: { stepName: string; status: string }) => [s.stepName, s.status]),
|
|
@@ -133,6 +154,7 @@ export const workflowStatusStreamFull = pikkuSessionlessFunc<
|
|
|
133
154
|
|
|
134
155
|
const terminalStatuses = new Set(['completed', 'failed', 'cancelled'])
|
|
135
156
|
let lastHash = ''
|
|
157
|
+
let initSent = false
|
|
136
158
|
|
|
137
159
|
const poll = async () => {
|
|
138
160
|
const run = await workflowRunService.getRun(runId)
|
|
@@ -143,6 +165,26 @@ export const workflowStatusStreamFull = pikkuSessionlessFunc<
|
|
|
143
165
|
|
|
144
166
|
const steps = await workflowRunService.getRunSteps(runId)
|
|
145
167
|
|
|
168
|
+
if (!initSent && run.deterministic) {
|
|
169
|
+
const statusByStep = new Map(
|
|
170
|
+
steps.map((s: { stepName: string; status: string }) => [
|
|
171
|
+
s.stepName,
|
|
172
|
+
s.status,
|
|
173
|
+
])
|
|
174
|
+
)
|
|
175
|
+
channel.send({
|
|
176
|
+
type: 'init',
|
|
177
|
+
deterministic: true,
|
|
178
|
+
steps: (run.plannedSteps ?? []).map(
|
|
179
|
+
(s: { stepName: string }) => ({
|
|
180
|
+
stepName: s.stepName,
|
|
181
|
+
status: statusByStep.get(s.stepName) ?? 'pending',
|
|
182
|
+
})
|
|
183
|
+
),
|
|
184
|
+
})
|
|
185
|
+
initSent = true
|
|
186
|
+
}
|
|
187
|
+
|
|
146
188
|
const hash = JSON.stringify({
|
|
147
189
|
s: run.status,
|
|
148
190
|
o: run.output,
|
|
@@ -193,7 +235,7 @@ export const graphStarter = pikkuSessionlessFunc<
|
|
|
193
235
|
>({
|
|
194
236
|
auth: ${authFlag},
|
|
195
237
|
func: async (_services, { workflowName, nodeId, data }, { rpc }) => {
|
|
196
|
-
return await rpc.startWorkflow(workflowName as any, data ?? {}, { startNode: nodeId })
|
|
238
|
+
return await rpc.startWorkflow(workflowName as any, (data ?? {}) as any, { startNode: nodeId })
|
|
197
239
|
},
|
|
198
240
|
})
|
|
199
241
|
|
|
@@ -128,7 +128,7 @@ export const allWorkflow = pikkuWorkflowComplexFunc({
|
|
|
128
128
|
}
|
|
129
129
|
if (!config.addon) {
|
|
130
130
|
const [http, scheduler, triggers] = await Promise.all([
|
|
131
|
-
workflow.do('HTTP', '
|
|
131
|
+
workflow.do('HTTP', 'pikkuCommandHTTP', null),
|
|
132
132
|
workflow.do('Scheduler', 'pikkuScheduler', null),
|
|
133
133
|
workflow.do('Trigger', 'pikkuTrigger', null),
|
|
134
134
|
]);
|
|
@@ -158,15 +158,15 @@ export const allWorkflow = pikkuWorkflowComplexFunc({
|
|
|
158
158
|
}
|
|
159
159
|
if (!config.addon) {
|
|
160
160
|
const [queues, channels, gateways, mcp, cli] = await Promise.all([
|
|
161
|
-
workflow.do('Queue', '
|
|
162
|
-
workflow.do('Channels', '
|
|
161
|
+
workflow.do('Queue', 'pikkuCommandQueue', null),
|
|
162
|
+
workflow.do('Channels', 'pikkuCommandChannels', null),
|
|
163
163
|
workflow.do('Gateway', 'pikkuGateway', null),
|
|
164
164
|
workflow.do('MCP', 'pikkuMCP', null),
|
|
165
165
|
workflow.do('CLI', 'pikkuCLI', null),
|
|
166
166
|
]);
|
|
167
167
|
if (queues) {
|
|
168
168
|
await Promise.all([
|
|
169
|
-
workflow.do('Queue map', '
|
|
169
|
+
workflow.do('Queue map', 'pikkuCommandQueueMap', null),
|
|
170
170
|
workflow.do('Queue service', 'pikkuQueueService', null),
|
|
171
171
|
]);
|
|
172
172
|
allImports.push(config.queueWorkersWiringMetaFile, config.queueWorkersWiringFile);
|
|
@@ -200,12 +200,7 @@ export const allWorkflow = pikkuWorkflowComplexFunc({
|
|
|
200
200
|
await workflow.do('OpenAPI re-inspect', async () => getInspectorState(true));
|
|
201
201
|
await workflow.do('OpenAPI', 'pikkuOpenAPI', null);
|
|
202
202
|
}
|
|
203
|
-
|
|
204
|
-
await workflow.do('Versions update', 'pikkuVersionsUpdate', null);
|
|
205
|
-
}
|
|
206
|
-
catch {
|
|
207
|
-
logger.warn(`Run 'pikku versions init' to enable contract versioning.`);
|
|
208
|
-
}
|
|
203
|
+
await workflow.do('Versions update', 'pikkuVersionsUpdate', null);
|
|
209
204
|
await workflow.do('Bootstrap', 'pikkuBootstrap', { allImports });
|
|
210
205
|
await workflow.do('Summary', 'pikkuSummary', null);
|
|
211
206
|
},
|