@pikku/cli 0.12.15 → 0.12.16
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/cli.schema.json +1 -1
- package/console-app/assets/index-CzMWJFqj.js +700 -0
- 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 +16 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -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 +68 -5
- 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 +16 -19
- package/dist/.pikku/function/pikku-function-types.gen.js +15 -19
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +190 -107
- package/dist/.pikku/function/pikku-functions.gen.js +6 -2
- 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-meta.gen.json +18 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +2 -2
- package/dist/.pikku/http/pikku-http-wirings.gen.js +3 -3
- 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 +3 -10
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -18
- package/dist/.pikku/pikku-meta-service.gen.d.ts +7 -0
- package/dist/.pikku/pikku-meta-service.gen.js +9 -0
- 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 +5 -1
- 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 +15 -7
- package/dist/.pikku/schemas/schemas/DeployApplyInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/DeployPlanInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuNewAddonInput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuWorkflowRoutesOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/RemoteRPCHandlerInput.schema.json +1 -0
- 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/pikku-workflow-types.gen.d.ts +3 -24
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -14
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/src/cli.wiring.js +63 -4
- package/dist/src/deploy/analyzer/analyzer.d.ts +16 -0
- package/dist/src/deploy/analyzer/analyzer.js +557 -0
- package/dist/src/deploy/analyzer/index.d.ts +3 -0
- package/dist/src/deploy/analyzer/index.js +1 -0
- package/dist/src/deploy/analyzer/manifest.d.ts +112 -0
- package/dist/src/deploy/analyzer/manifest.js +8 -0
- package/dist/src/deploy/build-pipeline.d.ts +39 -0
- package/dist/src/deploy/build-pipeline.js +209 -0
- package/dist/src/deploy/bundler/bundler.d.ts +30 -0
- package/dist/src/deploy/bundler/bundler.js +196 -0
- package/dist/src/deploy/bundler/dep-extractor.d.ts +35 -0
- package/dist/src/deploy/bundler/dep-extractor.js +213 -0
- package/dist/src/deploy/bundler/index.d.ts +3 -0
- package/dist/src/deploy/bundler/index.js +2 -0
- package/dist/src/deploy/bundler/types.d.ts +21 -0
- package/dist/src/deploy/bundler/types.js +5 -0
- package/dist/src/deploy/codegen/index.d.ts +2 -0
- package/dist/src/deploy/codegen/index.js +1 -0
- package/dist/src/deploy/codegen/per-unit-codegen.d.ts +44 -0
- package/dist/src/deploy/codegen/per-unit-codegen.js +216 -0
- package/dist/src/deploy/plan/executor.d.ts +9 -0
- package/dist/src/deploy/plan/executor.js +49 -0
- package/dist/src/deploy/plan/formatter.d.ts +4 -0
- package/dist/src/deploy/plan/formatter.js +114 -0
- package/dist/src/deploy/plan/index.d.ts +5 -0
- package/dist/src/deploy/plan/index.js +3 -0
- package/dist/src/deploy/plan/planner.d.ts +4 -0
- package/dist/src/deploy/plan/planner.js +220 -0
- package/dist/src/deploy/plan/provider.d.ts +30 -0
- package/dist/src/deploy/plan/provider.js +1 -0
- package/dist/src/deploy/plan/types.d.ts +29 -0
- package/dist/src/deploy/plan/types.js +1 -0
- package/dist/src/deploy/provider-adapter.d.ts +111 -0
- package/dist/src/deploy/provider-adapter.js +10 -0
- package/dist/src/functions/commands/all.js +6 -2
- package/dist/src/functions/commands/deploy-apply.d.ts +22 -0
- package/dist/src/functions/commands/deploy-apply.js +206 -0
- package/dist/src/functions/commands/deploy-info.d.ts +1 -0
- package/dist/src/functions/commands/deploy-info.js +122 -0
- package/dist/src/functions/commands/deploy-plan.d.ts +10 -0
- package/dist/src/functions/commands/deploy-plan.js +96 -0
- package/dist/src/functions/commands/enable.js +1 -1
- package/dist/src/functions/commands/new-addon.d.ts +3 -0
- package/dist/src/functions/commands/new-addon.js +68 -2
- package/dist/src/functions/commands/pikku-command-bootstrap.js +30 -20
- package/dist/src/functions/runtimes/nextjs/pikku-command-nextjs.js +7 -3
- package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent.js +7 -5
- package/dist/src/functions/wirings/channels/pikku-channels.js +3 -0
- package/dist/src/functions/wirings/channels/pikku-command-channels.js +3 -0
- package/dist/src/functions/wirings/cli/pikku-command-cli.js +3 -0
- package/dist/src/functions/wirings/cli/serialize-channel-cli.js +2 -2
- package/dist/src/functions/wirings/console/serialize-console-functions.js +2 -2
- package/dist/src/functions/wirings/functions/pikku-command-services.d.ts +1 -1
- package/dist/src/functions/wirings/functions/pikku-command-services.js +9 -2
- package/dist/src/functions/wirings/functions/serialize-function-imports.js +5 -3
- package/dist/src/functions/wirings/functions/serialize-function-types.js +17 -19
- package/dist/src/functions/wirings/http/pikku-command-http-routes.js +3 -0
- package/dist/src/functions/wirings/http/pikku-http-routes.js +3 -0
- package/dist/src/functions/wirings/mcp/pikku-command-mcp.js +6 -0
- package/dist/src/functions/wirings/package/pikku-command-package.js +1 -1
- package/dist/src/functions/wirings/package/serialize-package.d.ts +1 -1
- package/dist/src/functions/wirings/package/serialize-package.js +5 -2
- package/dist/src/functions/wirings/queue/pikku-command-queue.js +4 -0
- package/dist/src/functions/wirings/queue/pikku-queue.js +4 -0
- package/dist/src/functions/wirings/queue/serialize-queue-map.js +4 -1
- package/dist/src/functions/wirings/rpc/pikku-command-rpc.js +10 -3
- package/dist/src/functions/wirings/rpc/serialize-public-rpc.js +5 -27
- package/dist/src/functions/wirings/rpc/serialize-remote-rpc.js +11 -14
- package/dist/src/functions/wirings/rpc/serialize-rpc-wrapper.js +28 -3
- package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.js +15 -5
- package/dist/src/functions/wirings/scheduler/pikku-command-scheduler.js +4 -0
- package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.d.ts +1 -0
- package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.js +21 -0
- package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +10 -9
- package/dist/src/functions/wirings/workflow/serialize-workflow-map.d.ts +6 -1
- package/dist/src/functions/wirings/workflow/serialize-workflow-map.js +42 -5
- package/dist/src/functions/wirings/workflow/serialize-workflow-registration.d.ts +1 -1
- package/dist/src/functions/wirings/workflow/serialize-workflow-registration.js +3 -2
- package/dist/src/functions/wirings/workflow/serialize-workflow-routes.d.ts +4 -0
- package/dist/src/functions/wirings/workflow/serialize-workflow-routes.js +139 -0
- package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +4 -51
- package/dist/src/scaffold/rpc-remote.gen.d.ts +10 -0
- package/dist/src/scaffold/rpc-remote.gen.js +22 -0
- package/dist/src/services.js +12 -7
- package/dist/src/utils/pikku-cli-config.d.ts +1 -1
- package/dist/src/utils/pikku-cli-config.js +30 -28
- package/dist/src/utils/strip-verbose-meta.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -4
- package/console-app/assets/index-robZPL3O.js +0 -672
- package/dist/src/functions/wirings/workflow/serialize-workflow-workers.d.ts +0 -4
- package/dist/src/functions/wirings/workflow/serialize-workflow-workers.js +0 -47
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts external dependency information from esbuild metafiles.
|
|
3
|
+
*
|
|
4
|
+
* Parses esbuild's metafile JSON to find all node_modules references,
|
|
5
|
+
* then resolves their exact versions from the project's package.json
|
|
6
|
+
* and/or yarn.lock to produce a minimal package.json.
|
|
7
|
+
*/
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
/**
|
|
11
|
+
* Extracts bare package names from esbuild metafile imports.
|
|
12
|
+
*
|
|
13
|
+
* When esbuild runs with `packages: 'external'`, external imports appear
|
|
14
|
+
* in the metafile's outputs[].imports array with `external: true`.
|
|
15
|
+
* This function collects all unique package names from those imports.
|
|
16
|
+
*/
|
|
17
|
+
export function extractExternalPackages(metafile) {
|
|
18
|
+
const packages = new Set();
|
|
19
|
+
for (const output of Object.values(metafile.outputs)) {
|
|
20
|
+
for (const imp of output.imports) {
|
|
21
|
+
if (!imp.external)
|
|
22
|
+
continue;
|
|
23
|
+
const pkgName = parsePackageName(imp.path);
|
|
24
|
+
if (pkgName) {
|
|
25
|
+
packages.add(pkgName);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return packages;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parses a bare import specifier into a package name.
|
|
33
|
+
*
|
|
34
|
+
* Handles scoped packages (`@scope/pkg`) and deep imports (`pkg/sub/path`).
|
|
35
|
+
* Returns null for relative imports or other non-package specifiers.
|
|
36
|
+
*/
|
|
37
|
+
export function parsePackageName(specifier) {
|
|
38
|
+
if (specifier.startsWith('.') || specifier.startsWith('/')) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
// Skip Node.js builtins (node:fs, crypto, etc.)
|
|
42
|
+
if (specifier.startsWith('node:')) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const builtins = new Set([
|
|
46
|
+
'assert', 'buffer', 'child_process', 'cluster', 'console', 'constants',
|
|
47
|
+
'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'http2',
|
|
48
|
+
'https', 'inspector', 'module', 'net', 'os', 'path', 'perf_hooks',
|
|
49
|
+
'process', 'punycode', 'querystring', 'readline', 'repl', 'stream',
|
|
50
|
+
'string_decoder', 'sys', 'timers', 'tls', 'tty', 'url', 'util',
|
|
51
|
+
'v8', 'vm', 'wasi', 'worker_threads', 'zlib',
|
|
52
|
+
]);
|
|
53
|
+
if (builtins.has(specifier.split('/')[0])) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
// Scoped package: @scope/pkg or @scope/pkg/sub
|
|
57
|
+
if (specifier.startsWith('@')) {
|
|
58
|
+
const parts = specifier.split('/');
|
|
59
|
+
if (parts.length < 2)
|
|
60
|
+
return null;
|
|
61
|
+
return `${parts[0]}/${parts[1]}`;
|
|
62
|
+
}
|
|
63
|
+
// Regular package: pkg or pkg/sub/path
|
|
64
|
+
return specifier.split('/')[0];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Reads the project's package.json to build a version lookup map.
|
|
68
|
+
*/
|
|
69
|
+
async function readProjectDependencies(projectDir) {
|
|
70
|
+
const dependencies = {};
|
|
71
|
+
const devDependencies = {};
|
|
72
|
+
// Walk up the directory tree to find all package.json files
|
|
73
|
+
// (handles monorepo setups where deps are in the root package.json)
|
|
74
|
+
let dir = projectDir;
|
|
75
|
+
for (let i = 0; i < 10; i++) {
|
|
76
|
+
try {
|
|
77
|
+
const pkgJsonPath = join(dir, 'package.json');
|
|
78
|
+
const content = await readFile(pkgJsonPath, 'utf-8');
|
|
79
|
+
const pkg = JSON.parse(content);
|
|
80
|
+
// Don't overwrite — closest package.json wins
|
|
81
|
+
for (const [k, v] of Object.entries(pkg.dependencies ?? {})) {
|
|
82
|
+
if (!(k in dependencies))
|
|
83
|
+
dependencies[k] = v;
|
|
84
|
+
}
|
|
85
|
+
for (const [k, v] of Object.entries(pkg.devDependencies ?? {})) {
|
|
86
|
+
if (!(k in devDependencies))
|
|
87
|
+
devDependencies[k] = v;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// No package.json at this level
|
|
92
|
+
}
|
|
93
|
+
const parent = join(dir, '..');
|
|
94
|
+
if (parent === dir)
|
|
95
|
+
break;
|
|
96
|
+
dir = parent;
|
|
97
|
+
}
|
|
98
|
+
return { dependencies, devDependencies };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Attempts to read a version from yarn.lock for a given package.
|
|
102
|
+
*
|
|
103
|
+
* Yarn classic and yarn berry have different lock file formats.
|
|
104
|
+
* This function handles the yarn berry format (YAML-ish) used by Yarn 4+.
|
|
105
|
+
*/
|
|
106
|
+
async function readYarnLockVersions(projectDir) {
|
|
107
|
+
const versions = new Map();
|
|
108
|
+
try {
|
|
109
|
+
const lockContent = await readFile(join(projectDir, 'yarn.lock'), 'utf-8');
|
|
110
|
+
// Yarn berry format: lines like ` version: "1.2.3"`
|
|
111
|
+
// preceded by a key line like `"pkg@npm:^1.0.0":`
|
|
112
|
+
const lines = lockContent.split('\n');
|
|
113
|
+
let currentPackages = [];
|
|
114
|
+
for (const line of lines) {
|
|
115
|
+
// Key line: "pkg@npm:^1.0.0, pkg@npm:^1.2.0":
|
|
116
|
+
// or: pkg@npm:^1.0.0:
|
|
117
|
+
if (!line.startsWith(' ') && line.endsWith(':')) {
|
|
118
|
+
currentPackages = parseYarnLockKeyLine(line);
|
|
119
|
+
}
|
|
120
|
+
// Version line: ` version: "1.2.3"` or ` version: 1.2.3`
|
|
121
|
+
const versionMatch = line.match(/^\s+version:\s+"?([^"\s]+)"?/);
|
|
122
|
+
if (versionMatch && currentPackages.length > 0) {
|
|
123
|
+
const version = versionMatch[1];
|
|
124
|
+
for (const pkg of currentPackages) {
|
|
125
|
+
versions.set(pkg, version);
|
|
126
|
+
}
|
|
127
|
+
currentPackages = [];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// yarn.lock not found or unreadable — fall back to package.json versions
|
|
133
|
+
}
|
|
134
|
+
return versions;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Parses a yarn.lock key line into package names.
|
|
138
|
+
*
|
|
139
|
+
* Example inputs:
|
|
140
|
+
* `"esbuild@npm:^0.25.0":` -> ["esbuild"]
|
|
141
|
+
* `"@scope/pkg@npm:^1.0.0, @scope/pkg@npm:^1.2.0":` -> ["@scope/pkg"]
|
|
142
|
+
*/
|
|
143
|
+
function parseYarnLockKeyLine(line) {
|
|
144
|
+
const cleaned = line.replace(/:$/, '').replace(/"/g, '');
|
|
145
|
+
const entries = cleaned.split(',').map((s) => s.trim());
|
|
146
|
+
const names = new Set();
|
|
147
|
+
for (const entry of entries) {
|
|
148
|
+
// Strip everything from @ that's part of version specifier
|
|
149
|
+
// e.g., "esbuild@npm:^0.25.0" -> "esbuild"
|
|
150
|
+
// e.g., "@scope/pkg@npm:^1.0.0" -> "@scope/pkg"
|
|
151
|
+
const atIndex = entry.startsWith('@')
|
|
152
|
+
? entry.indexOf('@', 1)
|
|
153
|
+
: entry.indexOf('@');
|
|
154
|
+
if (atIndex > 0) {
|
|
155
|
+
names.add(entry.substring(0, atIndex));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return [...names];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Resolves the exact version for a package, trying yarn.lock first,
|
|
162
|
+
* then falling back to the version range from package.json.
|
|
163
|
+
*/
|
|
164
|
+
function resolveVersion(packageName, projectDeps, yarnLockVersions) {
|
|
165
|
+
// Prefer exact version from yarn.lock
|
|
166
|
+
const locked = yarnLockVersions.get(packageName);
|
|
167
|
+
if (locked)
|
|
168
|
+
return locked;
|
|
169
|
+
// Fall back to package.json version (may be a range)
|
|
170
|
+
const fromDeps = projectDeps.dependencies[packageName];
|
|
171
|
+
if (fromDeps)
|
|
172
|
+
return fromDeps;
|
|
173
|
+
const fromDevDeps = projectDeps.devDependencies[packageName];
|
|
174
|
+
if (fromDevDeps)
|
|
175
|
+
return fromDevDeps;
|
|
176
|
+
// Last resort: use wildcard (will get latest on install)
|
|
177
|
+
console.warn(`Could not resolve version for package '${packageName}', defaulting to '*'`);
|
|
178
|
+
return '*';
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Given an esbuild metafile, extracts all external packages and resolves
|
|
182
|
+
* their versions from the project's dependency files.
|
|
183
|
+
*
|
|
184
|
+
* Returns a record of package name to exact version, suitable for
|
|
185
|
+
* writing into a minimal package.json.
|
|
186
|
+
*/
|
|
187
|
+
export async function extractDependencies(metafile, projectDir) {
|
|
188
|
+
const externalPackages = extractExternalPackages(metafile);
|
|
189
|
+
if (externalPackages.size === 0) {
|
|
190
|
+
return {};
|
|
191
|
+
}
|
|
192
|
+
const [projectDeps, yarnLockVersions] = await Promise.all([
|
|
193
|
+
readProjectDependencies(projectDir),
|
|
194
|
+
readYarnLockVersions(projectDir),
|
|
195
|
+
]);
|
|
196
|
+
const dependencies = {};
|
|
197
|
+
for (const pkg of [...externalPackages].sort()) {
|
|
198
|
+
dependencies[pkg] = resolveVersion(pkg, projectDeps, yarnLockVersions);
|
|
199
|
+
}
|
|
200
|
+
return dependencies;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Generates a minimal package.json content object for a unit bundle.
|
|
204
|
+
*/
|
|
205
|
+
export function generateMinimalPackageJson(unitName, dependencies) {
|
|
206
|
+
return {
|
|
207
|
+
name: unitName,
|
|
208
|
+
private: true,
|
|
209
|
+
type: 'module',
|
|
210
|
+
main: 'bundle.js',
|
|
211
|
+
dependencies,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { bundleUnits } from './bundler.js';
|
|
2
|
+
export { extractDependencies, extractExternalPackages, parsePackageName, generateMinimalPackageJson, } from './dep-extractor.js';
|
|
3
|
+
export type { BundleResult, BundleError, BundleOutput, DeploymentUnit, DeploymentUnitRole, } from './types.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the Pikku esbuild bundling pipeline.
|
|
3
|
+
* Imports DeploymentManifest from the analyzer — single source of truth.
|
|
4
|
+
*/
|
|
5
|
+
export type { DeploymentManifest, DeploymentUnit, DeploymentUnitRole, } from '../analyzer/manifest.js';
|
|
6
|
+
export interface BundleResult {
|
|
7
|
+
unitName: string;
|
|
8
|
+
bundlePath: string;
|
|
9
|
+
packageJsonPath: string;
|
|
10
|
+
metafilePath: string;
|
|
11
|
+
bundleSizeBytes: number;
|
|
12
|
+
externalPackages: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
export interface BundleError {
|
|
15
|
+
unitName: string;
|
|
16
|
+
error: string;
|
|
17
|
+
}
|
|
18
|
+
export interface BundleOutput {
|
|
19
|
+
results: BundleResult[];
|
|
20
|
+
errors: BundleError[];
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { generatePerUnitCodegen } from './per-unit-codegen.js';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-unit filtered codegen for the deploy pipeline.
|
|
3
|
+
*
|
|
4
|
+
* For each deployment unit, runs `pikku all` with --names and --outDir
|
|
5
|
+
* flags to produce a separate .pikku/ directory containing only the
|
|
6
|
+
* registrations needed by that unit.
|
|
7
|
+
*
|
|
8
|
+
* Uses --stateInput to avoid re-inspecting the codebase for each unit.
|
|
9
|
+
*/
|
|
10
|
+
import type { InspectorState } from '@pikku/inspector';
|
|
11
|
+
import type { DeploymentManifest } from '../analyzer/manifest.js';
|
|
12
|
+
export interface PerUnitCodegenOptions {
|
|
13
|
+
/** Root directory of the project (where pikku.config.json lives) */
|
|
14
|
+
projectDir: string;
|
|
15
|
+
/** The deployment manifest with all units */
|
|
16
|
+
manifest: DeploymentManifest;
|
|
17
|
+
/** The full (unfiltered) inspector state */
|
|
18
|
+
inspectorState: InspectorState;
|
|
19
|
+
/** Base output directory for deploy artifacts (defaults to <projectDir>/.deploy) */
|
|
20
|
+
deployDir?: string;
|
|
21
|
+
/** Path to pikku binary (auto-resolved if not provided) */
|
|
22
|
+
pikkuBin?: string;
|
|
23
|
+
/** Called for each unit as it starts/completes */
|
|
24
|
+
onProgress?: (unitName: string, status: 'start' | 'done' | 'error', error?: string) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface PerUnitCodegenResult {
|
|
27
|
+
/** Map of unit name -> path to the unit's .pikku directory */
|
|
28
|
+
unitPikkuDirs: Map<string, string>;
|
|
29
|
+
/** Units that failed codegen */
|
|
30
|
+
errors: Array<{
|
|
31
|
+
unitName: string;
|
|
32
|
+
error: string;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Runs filtered codegen for each deployment unit.
|
|
37
|
+
*
|
|
38
|
+
* For each unit:
|
|
39
|
+
* 1. Calls `pikku all --stateInput=<state-file> --names=<func-ids> --outDir=<unit-dir/.pikku> --silent`
|
|
40
|
+
* 2. This produces pikku-bootstrap.gen.ts (and all other codegen) filtered to only that unit's functions
|
|
41
|
+
*
|
|
42
|
+
* The inspector state is saved once to a temp file and reused across all units.
|
|
43
|
+
*/
|
|
44
|
+
export declare function generatePerUnitCodegen(options: PerUnitCodegenOptions): Promise<PerUnitCodegenResult>;
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-unit filtered codegen for the deploy pipeline.
|
|
3
|
+
*
|
|
4
|
+
* For each deployment unit, runs `pikku all` with --names and --outDir
|
|
5
|
+
* flags to produce a separate .pikku/ directory containing only the
|
|
6
|
+
* registrations needed by that unit.
|
|
7
|
+
*
|
|
8
|
+
* Uses --stateInput to avoid re-inspecting the codebase for each unit.
|
|
9
|
+
*/
|
|
10
|
+
import { execFile } from 'node:child_process';
|
|
11
|
+
import { writeFile, mkdir, rm } from 'node:fs/promises';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { tmpdir } from 'node:os';
|
|
14
|
+
import { randomBytes } from 'node:crypto';
|
|
15
|
+
import { promisify } from 'node:util';
|
|
16
|
+
import { serializeInspectorState } from '@pikku/inspector';
|
|
17
|
+
const execFileAsync = promisify(execFile);
|
|
18
|
+
/**
|
|
19
|
+
* Resolve the pikku CLI binary path.
|
|
20
|
+
*
|
|
21
|
+
* Since deploy-apply runs inside the pikku process, we can find the binary
|
|
22
|
+
* by looking at process.argv[1] (the script being executed).
|
|
23
|
+
*/
|
|
24
|
+
function resolvePikkuBin() {
|
|
25
|
+
return process.argv[1];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Collect the full set of filter names for a deployment unit.
|
|
29
|
+
*
|
|
30
|
+
* The --names filter matches against different identifier types depending
|
|
31
|
+
* on the metadata being filtered (function names, agent names, channel
|
|
32
|
+
* names, etc.). For a unit to get its complete metadata, we need to
|
|
33
|
+
* include both the function IDs and any wiring-level names (e.g. agent
|
|
34
|
+
* names, channel names) that reference those functions.
|
|
35
|
+
*/
|
|
36
|
+
function collectFilterNames(unit, manifest, inspectorState) {
|
|
37
|
+
const names = new Set(unit.functionIds);
|
|
38
|
+
// Include catch-all scaffold routes based on unit contents
|
|
39
|
+
const functionsMeta = inspectorState.functions.meta;
|
|
40
|
+
const hasExposed = unit.functionIds.some((id) => functionsMeta[id]?.expose);
|
|
41
|
+
const hasRemote = unit.functionIds.some((id) => functionsMeta[id]?.remote);
|
|
42
|
+
if (hasExposed) {
|
|
43
|
+
// Include the RPC catch-all scaffold function + route
|
|
44
|
+
names.add('rpcCaller');
|
|
45
|
+
names.add('/rpc/:rpcName');
|
|
46
|
+
names.add('http:post:/rpc/:rpcName');
|
|
47
|
+
}
|
|
48
|
+
if (hasRemote) {
|
|
49
|
+
// Include the remote RPC scaffold function + route
|
|
50
|
+
names.add('remoteRPCHandler');
|
|
51
|
+
names.add('/remote/rpc/:rpcName');
|
|
52
|
+
names.add('http:post:/remote/rpc/:rpcName');
|
|
53
|
+
}
|
|
54
|
+
switch (unit.role) {
|
|
55
|
+
case 'agent': {
|
|
56
|
+
const agentDef = manifest.agents.find((a) => a.unitName === unit.name);
|
|
57
|
+
if (agentDef) {
|
|
58
|
+
names.add(agentDef.name);
|
|
59
|
+
// Include agent catch-all routes
|
|
60
|
+
names.add('agentCaller');
|
|
61
|
+
names.add('agentStreamCaller');
|
|
62
|
+
names.add('agentApproveCaller');
|
|
63
|
+
names.add('agentResumeCaller');
|
|
64
|
+
// Include RPC catch-all for agent tool dispatch
|
|
65
|
+
names.add('/rpc/:rpcName');
|
|
66
|
+
for (const id of agentDef.toolFunctionIds)
|
|
67
|
+
names.add(id);
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case 'mcp': {
|
|
72
|
+
for (const mcp of manifest.mcpEndpoints) {
|
|
73
|
+
if (mcp.unitName === unit.name) {
|
|
74
|
+
for (const id of mcp.toolFunctionIds)
|
|
75
|
+
names.add(id);
|
|
76
|
+
for (const id of mcp.resourceFunctionIds)
|
|
77
|
+
names.add(id);
|
|
78
|
+
for (const id of mcp.promptFunctionIds)
|
|
79
|
+
names.add(id);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case 'channel': {
|
|
85
|
+
const channelDef = manifest.channels.find((c) => c.unitName === unit.name);
|
|
86
|
+
if (channelDef) {
|
|
87
|
+
names.add(channelDef.name);
|
|
88
|
+
for (const id of channelDef.functionIds)
|
|
89
|
+
names.add(id);
|
|
90
|
+
}
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case 'function': {
|
|
94
|
+
// For function units, include queue/scheduler names from handlers
|
|
95
|
+
for (const handler of unit.handlers) {
|
|
96
|
+
if (handler.type === 'queue')
|
|
97
|
+
names.add(handler.queueName);
|
|
98
|
+
if (handler.type === 'scheduled')
|
|
99
|
+
names.add(handler.taskName);
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case 'workflow': {
|
|
104
|
+
const wfDef = manifest.workflows.find((w) => w.orchestratorUnit === unit.name);
|
|
105
|
+
if (wfDef) {
|
|
106
|
+
names.add(wfDef.pikkuFuncId);
|
|
107
|
+
names.add(wfDef.name);
|
|
108
|
+
// Include workflow scaffold functions + catch-all routes
|
|
109
|
+
names.add('workflowStarter');
|
|
110
|
+
names.add('workflowRunner');
|
|
111
|
+
names.add('workflowStatusChecker');
|
|
112
|
+
names.add('workflowStatusStream');
|
|
113
|
+
names.add('graphStarter');
|
|
114
|
+
names.add('/workflow/:workflowName/start');
|
|
115
|
+
names.add('/workflow/:workflowName/run');
|
|
116
|
+
names.add('/workflow/:workflowName/status/:runId');
|
|
117
|
+
names.add('/workflow/:workflowName/status/:runId/stream');
|
|
118
|
+
names.add('/workflow/:workflowName/graph/:nodeId');
|
|
119
|
+
names.add('http:post:/workflow/:workflowName/start');
|
|
120
|
+
names.add('http:post:/workflow/:workflowName/run');
|
|
121
|
+
names.add('http:get:/workflow/:workflowName/status/:runId');
|
|
122
|
+
names.add('http:get:/workflow/:workflowName/status/:runId/stream');
|
|
123
|
+
names.add('http:post:/workflow/:workflowName/graph/:nodeId');
|
|
124
|
+
// Queue names for orchestrator and step workers
|
|
125
|
+
const toKebab = (s) => s.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
126
|
+
names.add(`wf-orchestrator-${toKebab(wfDef.name)}`);
|
|
127
|
+
for (const step of wfDef.steps) {
|
|
128
|
+
if (step.functionId) {
|
|
129
|
+
names.add(step.functionId);
|
|
130
|
+
names.add(`wf-step-${toKebab(step.functionId)}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
default:
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
return [...names];
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Runs filtered codegen for each deployment unit.
|
|
143
|
+
*
|
|
144
|
+
* For each unit:
|
|
145
|
+
* 1. Calls `pikku all --stateInput=<state-file> --names=<func-ids> --outDir=<unit-dir/.pikku> --silent`
|
|
146
|
+
* 2. This produces pikku-bootstrap.gen.ts (and all other codegen) filtered to only that unit's functions
|
|
147
|
+
*
|
|
148
|
+
* The inspector state is saved once to a temp file and reused across all units.
|
|
149
|
+
*/
|
|
150
|
+
export async function generatePerUnitCodegen(options) {
|
|
151
|
+
const { projectDir, manifest, inspectorState, onProgress } = options;
|
|
152
|
+
const baseDir = options.deployDir ?? join(projectDir, '.deploy');
|
|
153
|
+
const pikkuBin = options.pikkuBin ?? resolvePikkuBin();
|
|
154
|
+
const unitPikkuDirs = new Map();
|
|
155
|
+
const errors = [];
|
|
156
|
+
// Create a temp file for the serialized inspector state
|
|
157
|
+
const stateFileName = `pikku-state-${randomBytes(8).toString('hex')}.json`;
|
|
158
|
+
const stateFilePath = join(tmpdir(), stateFileName);
|
|
159
|
+
try {
|
|
160
|
+
// Serialize and write the inspector state once
|
|
161
|
+
const serialized = serializeInspectorState(inspectorState);
|
|
162
|
+
await writeFile(stateFilePath, JSON.stringify(serialized), 'utf-8');
|
|
163
|
+
// Generate codegen for each unit
|
|
164
|
+
for (const unit of manifest.units) {
|
|
165
|
+
const filterNames = collectFilterNames(unit, manifest, inspectorState);
|
|
166
|
+
if (filterNames.length === 0) {
|
|
167
|
+
errors.push({
|
|
168
|
+
unitName: unit.name,
|
|
169
|
+
error: 'Unit has no function IDs — skipping codegen',
|
|
170
|
+
});
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
onProgress?.(unit.name, 'start');
|
|
174
|
+
const unitDir = join(baseDir, unit.name);
|
|
175
|
+
const unitPikkuDir = join(unitDir, '.pikku');
|
|
176
|
+
await mkdir(unitDir, { recursive: true });
|
|
177
|
+
const namesArg = filterNames.join(',');
|
|
178
|
+
try {
|
|
179
|
+
await execFileAsync(process.execPath, // node binary
|
|
180
|
+
[
|
|
181
|
+
pikkuBin,
|
|
182
|
+
'all',
|
|
183
|
+
`--stateInput=${stateFilePath}`,
|
|
184
|
+
`--names=${namesArg}`,
|
|
185
|
+
`--outDir=${unitPikkuDir}`,
|
|
186
|
+
'--silent',
|
|
187
|
+
], {
|
|
188
|
+
cwd: projectDir,
|
|
189
|
+
timeout: 60_000,
|
|
190
|
+
env: {
|
|
191
|
+
...process.env,
|
|
192
|
+
// Prevent recursive deploy or watch behavior
|
|
193
|
+
PIKKU_DEPLOY_CODEGEN: '1',
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
unitPikkuDirs.set(unit.name, unitPikkuDir);
|
|
197
|
+
onProgress?.(unit.name, 'done');
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
201
|
+
errors.push({ unitName: unit.name, error: message });
|
|
202
|
+
onProgress?.(unit.name, 'error', message);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
// Clean up the temp state file
|
|
208
|
+
try {
|
|
209
|
+
await rm(stateFilePath, { force: true });
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// Ignore cleanup errors
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return { unitPikkuDirs, errors };
|
|
216
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DeploymentManifest } from '../analyzer/manifest.js';
|
|
2
|
+
import type { DeployProvider } from './provider.js';
|
|
3
|
+
import type { ApplyResult, DeploymentPlan, PlanChange } from './types.js';
|
|
4
|
+
type ProgressStatus = 'start' | 'done' | 'error';
|
|
5
|
+
interface ApplyOptions {
|
|
6
|
+
onProgress?: (change: PlanChange, status: ProgressStatus, error?: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function applyPlan(plan: DeploymentPlan, manifest: DeploymentManifest, provider: DeployProvider, options?: ApplyOptions): Promise<ApplyResult>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Execution order for resource creation */
|
|
2
|
+
const CREATE_ORDER = [
|
|
3
|
+
'queue',
|
|
4
|
+
'unit',
|
|
5
|
+
'scheduled-task',
|
|
6
|
+
'secret',
|
|
7
|
+
'variable',
|
|
8
|
+
];
|
|
9
|
+
function sortByOrder(changes, order) {
|
|
10
|
+
const fallback = order.length;
|
|
11
|
+
return [...changes].sort((a, b) => {
|
|
12
|
+
const ai = order.indexOf(a.resourceType);
|
|
13
|
+
const bi = order.indexOf(b.resourceType);
|
|
14
|
+
return (ai === -1 ? fallback : ai) - (bi === -1 ? fallback : bi);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export async function applyPlan(plan, manifest, provider, options) {
|
|
18
|
+
const results = [];
|
|
19
|
+
const { onProgress } = options ?? {};
|
|
20
|
+
// Group by action
|
|
21
|
+
const creates = plan.changes.filter((c) => c.action === 'create');
|
|
22
|
+
const updates = plan.changes.filter((c) => c.action === 'update');
|
|
23
|
+
const drains = plan.changes.filter((c) => c.action === 'drain');
|
|
24
|
+
const deletes = plan.changes.filter((c) => c.action === 'delete');
|
|
25
|
+
// Execute in order: create -> update -> secrets/variables -> drain -> delete
|
|
26
|
+
const ordered = [
|
|
27
|
+
...sortByOrder(creates, CREATE_ORDER),
|
|
28
|
+
...sortByOrder(updates, CREATE_ORDER),
|
|
29
|
+
...drains,
|
|
30
|
+
...sortByOrder(deletes, [...CREATE_ORDER].reverse()),
|
|
31
|
+
];
|
|
32
|
+
for (const change of ordered) {
|
|
33
|
+
onProgress?.(change, 'start');
|
|
34
|
+
try {
|
|
35
|
+
await provider.applyChange(change, manifest);
|
|
36
|
+
onProgress?.(change, 'done');
|
|
37
|
+
results.push({ change, status: 'done' });
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
41
|
+
onProgress?.(change, 'error', message);
|
|
42
|
+
results.push({ change, status: 'error', error: message });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
applied: results,
|
|
47
|
+
success: results.every((r) => r.status === 'done'),
|
|
48
|
+
};
|
|
49
|
+
}
|