@pikku/cli 0.12.0 → 0.12.2
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-DRJQtv3c.js +676 -0
- package/console-app/index.html +6 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +30 -3
- package/dist/.pikku/agent/pikku-agent-types.gen.js +13 -0
- package/dist/.pikku/agent/pikku-agent-wirings-meta.gen.js +2 -2
- package/dist/.pikku/agent/pikku-agent-wirings.gen.d.ts +1 -1
- package/dist/.pikku/agent/pikku-agent-wirings.gen.js +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/channel/pikku-channels-meta.gen.js +2 -2
- package/dist/.pikku/channel/pikku-channels.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channels.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +77 -3
- 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 +2 -2
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +280 -10
- 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 +14 -11
- package/dist/.pikku/function/pikku-function-types.gen.js +25 -13
- package/dist/.pikku/function/pikku-functions-meta.gen.js +2 -2
- package/dist/.pikku/function/pikku-functions-meta.gen.json +426 -93
- package/dist/.pikku/function/pikku-functions.gen.js +5 -3
- 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 +2 -2
- 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/mcp/pikku-mcp-wirings-meta.gen.js +2 -2
- package/dist/.pikku/mcp/pikku-mcp-wirings.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-wirings.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +2 -2
- 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/pikku-websocket.gen.d.ts +1 -1
- package/dist/.pikku/pikku-websocket.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/queue/pikku-queue-workers-wirings-meta.gen.js +2 -2
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-remote-rpc-workers.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +2 -2
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +16 -2
- 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/scheduler/pikku-schedulers-wirings-meta.gen.js +2 -2
- package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +15 -3
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuGatewayOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuNewAddonInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuNewFunctionInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuNewMiddlewareInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuNewPermissionInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuNewWiringInput.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 +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +2 -2
- 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 +236 -9
- package/dist/src/functions/commands/all.js +13 -8
- package/dist/src/functions/commands/enable.d.ts +4 -0
- package/dist/src/functions/commands/enable.js +39 -0
- package/dist/src/functions/commands/info.d.ts +9 -0
- package/dist/src/functions/commands/info.js +283 -0
- package/dist/src/functions/commands/new-addon.d.ts +34 -0
- package/dist/src/functions/commands/new-addon.js +636 -0
- package/dist/src/functions/commands/new-function.d.ts +10 -0
- package/dist/src/functions/commands/new-function.js +79 -0
- package/dist/src/functions/commands/new-middleware.d.ts +10 -0
- package/dist/src/functions/commands/new-middleware.js +48 -0
- package/dist/src/functions/commands/new-permission.d.ts +10 -0
- package/dist/src/functions/commands/new-permission.js +45 -0
- package/dist/src/functions/commands/new-wiring.d.ts +10 -0
- package/dist/src/functions/commands/new-wiring.js +102 -0
- package/dist/src/functions/commands/pikku-command-bootstrap.js +11 -40
- package/dist/src/functions/commands/versions-check.js +85 -3
- package/dist/src/functions/commands/versions-update.js +1 -1
- package/dist/src/functions/runtimes/fetch/index.js +2 -1
- package/dist/src/functions/runtimes/nextjs/pikku-command-nextjs.js +4 -1
- package/dist/src/functions/runtimes/nextjs/serialize-nextjs-backend-wrapper.js +0 -4
- package/dist/src/functions/runtimes/websocket/pikku-command-websocket-typed.js +2 -1
- package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent-types.js +3 -2
- package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent.js +5 -5
- package/dist/src/functions/wirings/ai-agent/pikku-command-public-agent.js +3 -5
- package/dist/src/functions/wirings/ai-agent/serialize-agent-map.d.ts +1 -1
- package/dist/src/functions/wirings/ai-agent/serialize-ai-agent-types.d.ts +1 -1
- package/dist/src/functions/wirings/ai-agent/serialize-ai-agent-types.js +48 -3
- package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +30 -52
- package/dist/src/functions/wirings/channels/pikku-channels.js +1 -1
- package/dist/src/functions/wirings/channels/pikku-command-channel-types.js +2 -2
- package/dist/src/functions/wirings/channels/pikku-command-channels.js +1 -1
- package/dist/src/functions/wirings/channels/serialize-typed-channel-map.d.ts +4 -4
- package/dist/src/functions/wirings/cli/pikku-command-cli.js +1 -1
- package/dist/src/functions/wirings/cli/serialize-channel-cli-client.d.ts +2 -2
- package/dist/src/functions/wirings/cli/serialize-channel-cli.d.ts +1 -1
- package/dist/src/functions/wirings/cli/serialize-local-cli-bootstrap.d.ts +1 -1
- package/dist/src/functions/wirings/console/pikku-command-console-functions.js +4 -5
- package/dist/src/functions/wirings/console/pikku-command-nodes-meta.js +2 -2
- package/dist/src/functions/wirings/console/serialize-console-functions.d.ts +1 -1
- package/dist/src/functions/wirings/console/serialize-console-functions.js +18 -157
- package/dist/src/functions/wirings/functions/pikku-command-addon-types.d.ts +1 -0
- package/dist/src/functions/wirings/functions/pikku-command-addon-types.js +33 -0
- package/dist/src/functions/wirings/functions/pikku-command-function-types-split.js +1 -1
- package/dist/src/functions/wirings/functions/pikku-command-function-types.js +4 -4
- package/dist/src/functions/wirings/functions/pikku-command-functions.js +8 -14
- package/dist/src/functions/wirings/functions/schemas.js +1 -1
- package/dist/src/functions/wirings/functions/serialize-addon-types.d.ts +1 -0
- package/dist/src/functions/wirings/functions/{serialize-external-types.js → serialize-addon-types.js} +16 -15
- package/dist/src/functions/wirings/functions/serialize-function-imports.d.ts +3 -3
- package/dist/src/functions/wirings/functions/serialize-function-imports.js +3 -3
- package/dist/src/functions/wirings/functions/serialize-function-types.js +28 -14
- package/dist/src/functions/wirings/functions/serialize-pikku-types-hub.d.ts +1 -1
- package/dist/src/functions/wirings/functions/serialize-pikku-types-hub.js +2 -2
- package/dist/src/functions/wirings/gateway/pikku-command-gateway.d.ts +1 -0
- package/dist/src/functions/wirings/gateway/pikku-command-gateway.js +22 -0
- package/dist/src/functions/wirings/http/pikku-command-http-routes.js +1 -1
- package/dist/src/functions/wirings/http/pikku-http-routes.js +1 -1
- package/dist/src/functions/wirings/http/serialize-typed-http-map.d.ts +3 -3
- package/dist/src/functions/wirings/mcp/pikku-command-mcp-json.js +1 -1
- package/dist/src/functions/wirings/mcp/pikku-command-mcp.js +1 -1
- package/dist/src/functions/wirings/package/pikku-command-package.js +5 -5
- package/dist/src/functions/wirings/package/serialize-package.js +2 -2
- package/dist/src/functions/wirings/permissions/pikku-command-permissions.js +0 -5
- package/dist/src/functions/wirings/queue/pikku-command-queue-service.js +2 -1
- package/dist/src/functions/wirings/queue/serialize-queue-map.d.ts +2 -2
- package/dist/src/functions/wirings/queue/serialize-queue-meta.d.ts +1 -1
- package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.js +3 -5
- package/dist/src/functions/wirings/rpc/pikku-command-remote-rpc.js +3 -5
- package/dist/src/functions/wirings/rpc/pikku-command-rpc-client.js +2 -1
- package/dist/src/functions/wirings/rpc/pikku-command-rpc-map.js +6 -6
- package/dist/src/functions/wirings/rpc/pikku-command-rpc.js +2 -4
- package/dist/src/functions/wirings/rpc/serialize-public-rpc.js +25 -16
- package/dist/src/functions/wirings/rpc/serialize-rpc-wrapper.js +43 -7
- package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.d.ts +8 -3
- package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.js +41 -31
- package/dist/src/functions/wirings/scheduler/serialize-scheduler-meta.d.ts +1 -1
- package/dist/src/functions/wirings/secrets/serialize-secrets-types.d.ts +2 -2
- package/dist/src/functions/wirings/triggers/serialize-trigger-meta.d.ts +1 -1
- package/dist/src/functions/wirings/triggers/serialize-trigger-meta.js +2 -2
- package/dist/src/functions/wirings/variables/serialize-variables-types.d.ts +2 -2
- package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +5 -12
- package/dist/src/functions/wirings/workflow/serialize-workflow-map.d.ts +2 -2
- package/dist/src/functions/wirings/workflow/serialize-workflow-meta.js +2 -2
- package/dist/src/services/cli-logger-forwarder.service.d.ts +4 -3
- package/dist/src/services/cli-logger.service.d.ts +3 -2
- package/dist/src/services.d.ts +4 -3
- package/dist/src/services.js +14 -3
- package/dist/src/utils/check-required-types.d.ts +1 -1
- package/dist/src/utils/contract-versions.d.ts +1 -1
- package/dist/src/utils/file-writer.d.ts +6 -1
- package/dist/src/utils/file-writer.js +14 -1
- package/dist/src/utils/generate-bootstrap-file.d.ts +2 -2
- package/dist/src/utils/openapi/codegen.d.ts +19 -0
- package/dist/src/utils/openapi/codegen.js +288 -0
- package/dist/src/utils/openapi/naming.d.ts +30 -0
- package/dist/src/utils/openapi/naming.js +167 -0
- package/dist/src/utils/openapi/parse-openapi.d.ts +36 -0
- package/dist/src/utils/openapi/parse-openapi.js +196 -0
- package/dist/src/utils/openapi/zod-codegen.d.ts +53 -0
- package/dist/src/utils/openapi/zod-codegen.js +251 -0
- package/dist/src/utils/pikku-cli-config.d.ts +2 -2
- package/dist/src/utils/pikku-cli-config.js +51 -30
- package/dist/src/utils/pikku-files-and-methods.d.ts +1 -1
- package/dist/src/utils/pikku-files-and-methods.js +1 -1
- package/dist/src/utils/serialize-import-map.d.ts +2 -2
- package/dist/src/utils/serialize-import-map.js +1 -1
- package/dist/src/utils/serialize-meta-ts.js +1 -1
- package/dist/src/utils/serialize-schemas.d.ts +2 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/console-app/assets/index-C19L3UJu.js +0 -637
- package/dist/src/functions/wirings/functions/pikku-command-external-types.d.ts +0 -1
- package/dist/src/functions/wirings/functions/pikku-command-external-types.js +0 -33
- package/dist/src/functions/wirings/functions/serialize-external-types.d.ts +0 -1
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses OpenAPI YAML/JSON specs, resolves $ref pointers, and produces a normalized IR.
|
|
3
|
+
*/
|
|
4
|
+
import { readFile } from 'fs/promises';
|
|
5
|
+
import { parse as parseYAML } from 'yaml';
|
|
6
|
+
/**
|
|
7
|
+
* Read and parse an OpenAPI spec from a file path.
|
|
8
|
+
* Supports both YAML (.yaml, .yml) and JSON (.json) files.
|
|
9
|
+
*/
|
|
10
|
+
export async function parseOpenAPISpec(filePath) {
|
|
11
|
+
const content = await readFile(filePath, 'utf-8');
|
|
12
|
+
let doc;
|
|
13
|
+
if (filePath.endsWith('.json')) {
|
|
14
|
+
doc = JSON.parse(content);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
doc = parseYAML(content);
|
|
18
|
+
}
|
|
19
|
+
// Resolve all $ref pointers in-place
|
|
20
|
+
resolveRefs(doc, doc);
|
|
21
|
+
const info = {
|
|
22
|
+
title: doc.info?.title ?? 'Unknown API',
|
|
23
|
+
version: doc.info?.version ?? '1.0.0',
|
|
24
|
+
description: doc.info?.description,
|
|
25
|
+
};
|
|
26
|
+
const baseUrl = extractBaseUrl(doc);
|
|
27
|
+
const authType = detectAuthType(doc);
|
|
28
|
+
// Extract component schemas
|
|
29
|
+
const componentSchemas = {};
|
|
30
|
+
if (doc.components?.schemas) {
|
|
31
|
+
for (const [name, schema] of Object.entries(doc.components.schemas)) {
|
|
32
|
+
componentSchemas[name] = schema;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Extract operations
|
|
36
|
+
const operations = [];
|
|
37
|
+
if (doc.paths) {
|
|
38
|
+
for (const [path, pathItem] of Object.entries(doc.paths)) {
|
|
39
|
+
// Shared parameters at the path level
|
|
40
|
+
const sharedParams = pathItem.parameters ?? [];
|
|
41
|
+
for (const method of ['get', 'post', 'put', 'patch', 'delete']) {
|
|
42
|
+
const op = pathItem[method];
|
|
43
|
+
if (!op)
|
|
44
|
+
continue;
|
|
45
|
+
const allParams = [...sharedParams, ...(op.parameters ?? [])];
|
|
46
|
+
operations.push({
|
|
47
|
+
operationId: op.operationId,
|
|
48
|
+
method,
|
|
49
|
+
path,
|
|
50
|
+
summary: op.summary,
|
|
51
|
+
description: op.description,
|
|
52
|
+
tags: op.tags ?? [],
|
|
53
|
+
pathParams: extractParams(allParams, 'path'),
|
|
54
|
+
queryParams: extractParams(allParams, 'query'),
|
|
55
|
+
requestBody: extractRequestBody(op),
|
|
56
|
+
responseSchema: extractResponseSchema(op),
|
|
57
|
+
responseDescription: extractResponseDescription(op),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { info, baseUrl, authType, operations, componentSchemas };
|
|
63
|
+
}
|
|
64
|
+
/** Recursively resolve $ref pointers in-place */
|
|
65
|
+
function resolveRefs(node, root) {
|
|
66
|
+
if (node === null || typeof node !== 'object')
|
|
67
|
+
return node;
|
|
68
|
+
if (Array.isArray(node)) {
|
|
69
|
+
for (let i = 0; i < node.length; i++) {
|
|
70
|
+
node[i] = resolveRefs(node[i], root);
|
|
71
|
+
}
|
|
72
|
+
return node;
|
|
73
|
+
}
|
|
74
|
+
if (typeof node.$ref === 'string') {
|
|
75
|
+
const resolved = resolveRefPath(node.$ref, root);
|
|
76
|
+
if (resolved && typeof resolved === 'object') {
|
|
77
|
+
// Merge any sibling properties (like description overrides)
|
|
78
|
+
const { $ref, ...siblings } = node;
|
|
79
|
+
const result = { ...resolved, ...siblings };
|
|
80
|
+
// Don't recurse infinitely — mark as resolved
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
return node;
|
|
84
|
+
}
|
|
85
|
+
for (const key of Object.keys(node)) {
|
|
86
|
+
node[key] = resolveRefs(node[key], root);
|
|
87
|
+
}
|
|
88
|
+
return node;
|
|
89
|
+
}
|
|
90
|
+
function resolveRefPath(ref, root) {
|
|
91
|
+
if (!ref.startsWith('#/'))
|
|
92
|
+
return undefined;
|
|
93
|
+
const parts = ref.slice(2).split('/');
|
|
94
|
+
let current = root;
|
|
95
|
+
for (const part of parts) {
|
|
96
|
+
const decoded = part.replace(/~1/g, '/').replace(/~0/g, '~');
|
|
97
|
+
if (current == null || typeof current !== 'object')
|
|
98
|
+
return undefined;
|
|
99
|
+
current = current[decoded];
|
|
100
|
+
}
|
|
101
|
+
return current;
|
|
102
|
+
}
|
|
103
|
+
function extractBaseUrl(doc) {
|
|
104
|
+
// OpenAPI 3.x
|
|
105
|
+
if (doc.servers && doc.servers.length > 0) {
|
|
106
|
+
return doc.servers[0].url ?? '';
|
|
107
|
+
}
|
|
108
|
+
// Swagger 2.x
|
|
109
|
+
if (doc.host) {
|
|
110
|
+
const scheme = doc.schemes?.[0] ?? 'https';
|
|
111
|
+
const basePath = doc.basePath ?? '';
|
|
112
|
+
return `${scheme}://${doc.host}${basePath}`;
|
|
113
|
+
}
|
|
114
|
+
return '';
|
|
115
|
+
}
|
|
116
|
+
function detectAuthType(doc) {
|
|
117
|
+
const securitySchemes = doc.components?.securitySchemes ?? doc.securityDefinitions ?? {};
|
|
118
|
+
for (const scheme of Object.values(securitySchemes)) {
|
|
119
|
+
if (scheme.type === 'oauth2')
|
|
120
|
+
return 'oauth2';
|
|
121
|
+
if (scheme.type === 'http' && scheme.scheme === 'bearer')
|
|
122
|
+
return 'bearer';
|
|
123
|
+
if (scheme.type === 'apiKey')
|
|
124
|
+
return 'apiKey';
|
|
125
|
+
}
|
|
126
|
+
return 'none';
|
|
127
|
+
}
|
|
128
|
+
function extractParams(params, location) {
|
|
129
|
+
return params
|
|
130
|
+
.filter((p) => p.in === location)
|
|
131
|
+
.map((p) => ({
|
|
132
|
+
name: p.name,
|
|
133
|
+
required: p.required ?? location === 'path',
|
|
134
|
+
schema: (p.schema ?? { type: 'string' }),
|
|
135
|
+
description: p.description,
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
function extractRequestBody(op) {
|
|
139
|
+
const body = op.requestBody;
|
|
140
|
+
if (!body)
|
|
141
|
+
return undefined;
|
|
142
|
+
const content = body.content;
|
|
143
|
+
if (!content)
|
|
144
|
+
return undefined;
|
|
145
|
+
// Prefer JSON
|
|
146
|
+
const jsonContent = content['application/json'];
|
|
147
|
+
if (jsonContent?.schema)
|
|
148
|
+
return jsonContent.schema;
|
|
149
|
+
// Fallback to first content type
|
|
150
|
+
const firstKey = Object.keys(content)[0];
|
|
151
|
+
if (firstKey && content[firstKey]?.schema) {
|
|
152
|
+
return content[firstKey].schema;
|
|
153
|
+
}
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
function extractResponseDescription(op) {
|
|
157
|
+
const responses = op.responses;
|
|
158
|
+
if (!responses)
|
|
159
|
+
return undefined;
|
|
160
|
+
for (const code of ['200', '201', '202']) {
|
|
161
|
+
const resp = responses[code];
|
|
162
|
+
if (resp?.description)
|
|
163
|
+
return resp.description;
|
|
164
|
+
}
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
function extractResponseSchema(op) {
|
|
168
|
+
const responses = op.responses;
|
|
169
|
+
if (!responses)
|
|
170
|
+
return undefined;
|
|
171
|
+
// Look for 2xx responses in order of preference
|
|
172
|
+
for (const code of ['200', '201', '202', '204']) {
|
|
173
|
+
const resp = responses[code];
|
|
174
|
+
if (!resp)
|
|
175
|
+
continue;
|
|
176
|
+
const content = resp.content;
|
|
177
|
+
if (!content)
|
|
178
|
+
continue;
|
|
179
|
+
const jsonContent = content['application/json'];
|
|
180
|
+
if (jsonContent?.schema)
|
|
181
|
+
return jsonContent.schema;
|
|
182
|
+
const firstKey = Object.keys(content)[0];
|
|
183
|
+
if (firstKey && content[firstKey]?.schema) {
|
|
184
|
+
return content[firstKey].schema;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Fallback: any 2xx
|
|
188
|
+
for (const [code, resp] of Object.entries(responses)) {
|
|
189
|
+
if (code.startsWith('2') && resp.content) {
|
|
190
|
+
const jsonContent = resp.content['application/json'];
|
|
191
|
+
if (jsonContent?.schema)
|
|
192
|
+
return jsonContent.schema;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts OpenAPI schemas into Zod code strings.
|
|
3
|
+
*
|
|
4
|
+
* Chaining order: base → refinements → .nullable() → .optional() → .default() → .describe()
|
|
5
|
+
*/
|
|
6
|
+
export interface OpenAPISchema {
|
|
7
|
+
type?: string;
|
|
8
|
+
format?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
enum?: unknown[];
|
|
11
|
+
items?: OpenAPISchema;
|
|
12
|
+
properties?: Record<string, OpenAPISchema>;
|
|
13
|
+
required?: string[];
|
|
14
|
+
nullable?: boolean;
|
|
15
|
+
default?: unknown;
|
|
16
|
+
minimum?: number;
|
|
17
|
+
maximum?: number;
|
|
18
|
+
exclusiveMinimum?: number;
|
|
19
|
+
exclusiveMaximum?: number;
|
|
20
|
+
minLength?: number;
|
|
21
|
+
maxLength?: number;
|
|
22
|
+
pattern?: string;
|
|
23
|
+
minItems?: number;
|
|
24
|
+
maxItems?: number;
|
|
25
|
+
oneOf?: OpenAPISchema[];
|
|
26
|
+
anyOf?: OpenAPISchema[];
|
|
27
|
+
allOf?: OpenAPISchema[];
|
|
28
|
+
additionalProperties?: boolean | OpenAPISchema;
|
|
29
|
+
$ref?: string;
|
|
30
|
+
readOnly?: boolean;
|
|
31
|
+
writeOnly?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface ZodCodegenContext {
|
|
34
|
+
/** Map from component schema name to its Zod variable name */
|
|
35
|
+
schemaRefs: Map<string, string>;
|
|
36
|
+
/** Track which refs are actually used */
|
|
37
|
+
usedRefs: Set<string>;
|
|
38
|
+
/** Indent level for readability */
|
|
39
|
+
indent: number;
|
|
40
|
+
}
|
|
41
|
+
export declare function createContext(schemaRefs?: Map<string, string>): ZodCodegenContext;
|
|
42
|
+
/**
|
|
43
|
+
* Convert a single OpenAPI schema to a Zod expression string.
|
|
44
|
+
* Does NOT include .optional() — that's handled at the property level based on `required`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function schemaToZod(schema: OpenAPISchema, ctx: ZodCodegenContext, opts?: {
|
|
47
|
+
optional?: boolean;
|
|
48
|
+
}): string;
|
|
49
|
+
/**
|
|
50
|
+
* Generate the Zod variable name for a component schema.
|
|
51
|
+
* e.g. "PaginatedResponse" → "PaginatedResponseSchema"
|
|
52
|
+
*/
|
|
53
|
+
export declare function schemaVarName(name: string): string;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts OpenAPI schemas into Zod code strings.
|
|
3
|
+
*
|
|
4
|
+
* Chaining order: base → refinements → .nullable() → .optional() → .default() → .describe()
|
|
5
|
+
*/
|
|
6
|
+
export function createContext(schemaRefs) {
|
|
7
|
+
return {
|
|
8
|
+
schemaRefs: schemaRefs ?? new Map(),
|
|
9
|
+
usedRefs: new Set(),
|
|
10
|
+
indent: 0,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Convert a single OpenAPI schema to a Zod expression string.
|
|
15
|
+
* Does NOT include .optional() — that's handled at the property level based on `required`.
|
|
16
|
+
*/
|
|
17
|
+
export function schemaToZod(schema, ctx, opts = {}) {
|
|
18
|
+
let code = schemaToZodBase(schema, ctx);
|
|
19
|
+
// Refinements
|
|
20
|
+
code = applyRefinements(code, schema);
|
|
21
|
+
// Nullable
|
|
22
|
+
if (schema.nullable) {
|
|
23
|
+
code += '.nullable()';
|
|
24
|
+
}
|
|
25
|
+
// Optional
|
|
26
|
+
if (opts.optional) {
|
|
27
|
+
code += '.optional()';
|
|
28
|
+
}
|
|
29
|
+
// Default
|
|
30
|
+
if (schema.default !== undefined) {
|
|
31
|
+
code += `.default(${JSON.stringify(schema.default)})`;
|
|
32
|
+
}
|
|
33
|
+
// Description
|
|
34
|
+
if (schema.description) {
|
|
35
|
+
code += `.describe(${JSON.stringify(schema.description)})`;
|
|
36
|
+
}
|
|
37
|
+
return code;
|
|
38
|
+
}
|
|
39
|
+
function schemaToZodBase(schema, ctx) {
|
|
40
|
+
// Handle $ref
|
|
41
|
+
if (schema.$ref) {
|
|
42
|
+
const refName = schema.$ref.split('/').pop();
|
|
43
|
+
const zodName = ctx.schemaRefs.get(refName);
|
|
44
|
+
if (zodName) {
|
|
45
|
+
ctx.usedRefs.add(refName);
|
|
46
|
+
return zodName;
|
|
47
|
+
}
|
|
48
|
+
// Unknown ref — fallback to z.unknown()
|
|
49
|
+
return 'z.unknown()';
|
|
50
|
+
}
|
|
51
|
+
// Handle allOf — merge into single object
|
|
52
|
+
if (schema.allOf && schema.allOf.length > 0) {
|
|
53
|
+
return handleAllOf(schema.allOf, ctx);
|
|
54
|
+
}
|
|
55
|
+
// Handle oneOf/anyOf — union
|
|
56
|
+
if (schema.oneOf && schema.oneOf.length > 0) {
|
|
57
|
+
return handleUnion(schema.oneOf, ctx);
|
|
58
|
+
}
|
|
59
|
+
if (schema.anyOf && schema.anyOf.length > 0) {
|
|
60
|
+
return handleUnion(schema.anyOf, ctx);
|
|
61
|
+
}
|
|
62
|
+
// Handle enum
|
|
63
|
+
if (schema.enum && schema.enum.length > 0) {
|
|
64
|
+
return handleEnum(schema.enum);
|
|
65
|
+
}
|
|
66
|
+
// Handle by type
|
|
67
|
+
switch (schema.type) {
|
|
68
|
+
case 'string':
|
|
69
|
+
return handleString(schema);
|
|
70
|
+
case 'integer':
|
|
71
|
+
return 'z.number().int()';
|
|
72
|
+
case 'number':
|
|
73
|
+
return 'z.number()';
|
|
74
|
+
case 'boolean':
|
|
75
|
+
return 'z.boolean()';
|
|
76
|
+
case 'array':
|
|
77
|
+
return handleArray(schema, ctx);
|
|
78
|
+
case 'object':
|
|
79
|
+
return handleObject(schema, ctx);
|
|
80
|
+
default:
|
|
81
|
+
// No type specified but has properties — treat as object
|
|
82
|
+
if (schema.properties) {
|
|
83
|
+
return handleObject(schema, ctx);
|
|
84
|
+
}
|
|
85
|
+
return 'z.unknown()';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function handleString(schema) {
|
|
89
|
+
switch (schema.format) {
|
|
90
|
+
case 'uuid':
|
|
91
|
+
return 'z.string().uuid()';
|
|
92
|
+
case 'date-time':
|
|
93
|
+
return 'z.string().datetime()';
|
|
94
|
+
case 'date':
|
|
95
|
+
return 'z.string().date()';
|
|
96
|
+
case 'email':
|
|
97
|
+
return 'z.string().email()';
|
|
98
|
+
case 'uri':
|
|
99
|
+
case 'url':
|
|
100
|
+
return 'z.string().url()';
|
|
101
|
+
default:
|
|
102
|
+
return 'z.string()';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function handleEnum(values) {
|
|
106
|
+
// If all values are strings, use z.enum
|
|
107
|
+
if (values.every((v) => typeof v === 'string')) {
|
|
108
|
+
const enumValues = values.map((v) => JSON.stringify(v)).join(', ');
|
|
109
|
+
return `z.enum([${enumValues}])`;
|
|
110
|
+
}
|
|
111
|
+
// Mixed types — use z.union of z.literal
|
|
112
|
+
const literals = values.map((v) => `z.literal(${JSON.stringify(v)})`).join(', ');
|
|
113
|
+
return `z.union([${literals}])`;
|
|
114
|
+
}
|
|
115
|
+
function handleArray(schema, ctx) {
|
|
116
|
+
const itemsZod = schema.items
|
|
117
|
+
? schemaToZodBase(schema.items, ctx)
|
|
118
|
+
: 'z.unknown()';
|
|
119
|
+
return `z.array(${itemsZod})`;
|
|
120
|
+
}
|
|
121
|
+
function indent(ctx) {
|
|
122
|
+
return ' '.repeat(ctx.indent);
|
|
123
|
+
}
|
|
124
|
+
function handleObject(schema, ctx) {
|
|
125
|
+
if (!schema.properties || Object.keys(schema.properties).length === 0) {
|
|
126
|
+
// Object with no defined properties
|
|
127
|
+
if (schema.additionalProperties) {
|
|
128
|
+
const valueSchema = typeof schema.additionalProperties === 'object'
|
|
129
|
+
? schemaToZod(schema.additionalProperties, ctx)
|
|
130
|
+
: 'z.unknown()';
|
|
131
|
+
return `z.record(z.string(), ${valueSchema})`;
|
|
132
|
+
}
|
|
133
|
+
return 'z.record(z.string(), z.unknown())';
|
|
134
|
+
}
|
|
135
|
+
const inner = { ...ctx, indent: ctx.indent + 1 };
|
|
136
|
+
const pad = indent(inner);
|
|
137
|
+
const closePad = indent(ctx);
|
|
138
|
+
const requiredSet = new Set(schema.required ?? []);
|
|
139
|
+
const entries = [];
|
|
140
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
141
|
+
const isOptional = !requiredSet.has(key);
|
|
142
|
+
const propZod = schemaToZod(propSchema, inner, { optional: isOptional });
|
|
143
|
+
entries.push(`${pad}${safeKey(key)}: ${propZod},`);
|
|
144
|
+
}
|
|
145
|
+
return `z.object({\n${entries.join('\n')}\n${closePad}})`;
|
|
146
|
+
}
|
|
147
|
+
function handleAllOf(schemas, ctx) {
|
|
148
|
+
// Collect all properties from all schemas
|
|
149
|
+
const mergedProps = {};
|
|
150
|
+
const mergedRequired = [];
|
|
151
|
+
for (const sub of schemas) {
|
|
152
|
+
if (sub.$ref) {
|
|
153
|
+
const refName = sub.$ref.split('/').pop();
|
|
154
|
+
const zodName = ctx.schemaRefs.get(refName);
|
|
155
|
+
if (zodName) {
|
|
156
|
+
ctx.usedRefs.add(refName);
|
|
157
|
+
// If it's a pure ref in an allOf, we'd need to merge/extend
|
|
158
|
+
// For simplicity, if we have refs mixed with objects, use .merge()
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (sub.properties) {
|
|
162
|
+
Object.assign(mergedProps, sub.properties);
|
|
163
|
+
}
|
|
164
|
+
if (sub.required) {
|
|
165
|
+
mergedRequired.push(...sub.required);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// If we have only refs, use .merge()
|
|
169
|
+
const refSchemas = schemas.filter((s) => s.$ref);
|
|
170
|
+
const objSchemas = schemas.filter((s) => !s.$ref && (s.properties || s.type === 'object'));
|
|
171
|
+
if (refSchemas.length > 0 && objSchemas.length === 0) {
|
|
172
|
+
const parts = refSchemas.map((s) => {
|
|
173
|
+
const refName = s.$ref.split('/').pop();
|
|
174
|
+
ctx.usedRefs.add(refName);
|
|
175
|
+
return ctx.schemaRefs.get(refName) || 'z.object({})';
|
|
176
|
+
});
|
|
177
|
+
if (parts.length === 1)
|
|
178
|
+
return parts[0];
|
|
179
|
+
return parts.reduce((acc, part) => `${acc}.merge(${part})`);
|
|
180
|
+
}
|
|
181
|
+
// Otherwise, merge into a single object
|
|
182
|
+
if (Object.keys(mergedProps).length > 0) {
|
|
183
|
+
return handleObject({
|
|
184
|
+
type: 'object',
|
|
185
|
+
properties: mergedProps,
|
|
186
|
+
required: [...new Set(mergedRequired)],
|
|
187
|
+
}, ctx);
|
|
188
|
+
}
|
|
189
|
+
// Fallback
|
|
190
|
+
return 'z.unknown()';
|
|
191
|
+
}
|
|
192
|
+
function handleUnion(schemas, ctx) {
|
|
193
|
+
const members = schemas.map((s) => schemaToZodBase(s, ctx));
|
|
194
|
+
if (members.length === 1)
|
|
195
|
+
return members[0];
|
|
196
|
+
return `z.union([${members.join(', ')}])`;
|
|
197
|
+
}
|
|
198
|
+
function applyRefinements(code, schema) {
|
|
199
|
+
let result = code;
|
|
200
|
+
// String refinements
|
|
201
|
+
if (schema.type === 'string' || (!schema.type && !schema.format)) {
|
|
202
|
+
if (schema.minLength !== undefined) {
|
|
203
|
+
result += `.min(${schema.minLength})`;
|
|
204
|
+
}
|
|
205
|
+
if (schema.maxLength !== undefined) {
|
|
206
|
+
result += `.max(${schema.maxLength})`;
|
|
207
|
+
}
|
|
208
|
+
if (schema.pattern) {
|
|
209
|
+
result += `.regex(new RegExp(${JSON.stringify(schema.pattern)}))`;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// Number refinements
|
|
213
|
+
if (schema.type === 'number' || schema.type === 'integer') {
|
|
214
|
+
if (schema.minimum !== undefined) {
|
|
215
|
+
result += `.min(${schema.minimum})`;
|
|
216
|
+
}
|
|
217
|
+
if (schema.maximum !== undefined) {
|
|
218
|
+
result += `.max(${schema.maximum})`;
|
|
219
|
+
}
|
|
220
|
+
if (schema.exclusiveMinimum !== undefined) {
|
|
221
|
+
result += `.gt(${schema.exclusiveMinimum})`;
|
|
222
|
+
}
|
|
223
|
+
if (schema.exclusiveMaximum !== undefined) {
|
|
224
|
+
result += `.lt(${schema.exclusiveMaximum})`;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Array refinements
|
|
228
|
+
if (schema.type === 'array') {
|
|
229
|
+
if (schema.minItems !== undefined) {
|
|
230
|
+
result += `.min(${schema.minItems})`;
|
|
231
|
+
}
|
|
232
|
+
if (schema.maxItems !== undefined) {
|
|
233
|
+
result += `.max(${schema.maxItems})`;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
238
|
+
/** Ensure property keys are safe identifiers, or quote them */
|
|
239
|
+
function safeKey(key) {
|
|
240
|
+
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) {
|
|
241
|
+
return key;
|
|
242
|
+
}
|
|
243
|
+
return JSON.stringify(key);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Generate the Zod variable name for a component schema.
|
|
247
|
+
* e.g. "PaginatedResponse" → "PaginatedResponseSchema"
|
|
248
|
+
*/
|
|
249
|
+
export function schemaVarName(name) {
|
|
250
|
+
return name.endsWith('Schema') ? name : `${name}Schema`;
|
|
251
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PikkuCLIConfig } from '../../types/config.js';
|
|
2
|
-
import { CLILogger } from '../services/cli-logger.service.js';
|
|
1
|
+
import type { PikkuCLIConfig } from '../../types/config.js';
|
|
2
|
+
import type { CLILogger } from '../services/cli-logger.service.js';
|
|
3
3
|
export declare const getPikkuCLIConfig: (logger: CLILogger, configFile: string | undefined, requiredFields: Array<keyof PikkuCLIConfig>, exitProcess?: boolean) => Promise<PikkuCLIConfig>;
|
|
4
4
|
export declare const validateCLIConfig: (cliConfig: PikkuCLIConfig, required: Array<keyof PikkuCLIConfig>) => void;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { join, dirname, resolve, isAbsolute } from 'path';
|
|
2
2
|
import { readdir, readFile } from 'fs/promises';
|
|
3
|
-
const
|
|
4
|
-
'nextBackendFile',
|
|
5
|
-
'nextHTTPFile',
|
|
3
|
+
const CLIENT_FILE_KEYS = [
|
|
6
4
|
'fetchFile',
|
|
7
5
|
'websocketFile',
|
|
8
6
|
'rpcWiringsFile',
|
|
9
7
|
'queueWiringsFile',
|
|
10
8
|
'mcpJsonFile',
|
|
9
|
+
'nextBackendFile',
|
|
10
|
+
'nextHTTPFile',
|
|
11
11
|
];
|
|
12
12
|
export const getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields, exitProcess = false) => {
|
|
13
13
|
const config = await _getPikkuCLIConfig(logger, configFile, requiredFields, exitProcess);
|
|
@@ -38,10 +38,6 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
38
38
|
...extendedConfig.packageMappings,
|
|
39
39
|
...config.packageMappings,
|
|
40
40
|
},
|
|
41
|
-
externalPackages: {
|
|
42
|
-
...extendedConfig.externalPackages,
|
|
43
|
-
...config.externalPackages,
|
|
44
|
-
},
|
|
45
41
|
ignoreFiles: config.ignoreFiles ??
|
|
46
42
|
extendedConfig.ignoreFiles ?? [
|
|
47
43
|
'**/*.test.ts',
|
|
@@ -62,7 +58,6 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
62
58
|
...config,
|
|
63
59
|
configDir,
|
|
64
60
|
packageMappings: config.packageMappings || {},
|
|
65
|
-
externalPackages: config.externalPackages || {},
|
|
66
61
|
rootDir: config.rootDir
|
|
67
62
|
? resolve(configDir, config.rootDir)
|
|
68
63
|
: configDir,
|
|
@@ -126,6 +121,11 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
126
121
|
if (!result.httpTypesFile) {
|
|
127
122
|
result.httpTypesFile = join(httpDir, 'pikku-http-types.gen.ts');
|
|
128
123
|
}
|
|
124
|
+
// Gateways
|
|
125
|
+
const gatewayDir = join(result.outDir, 'gateway');
|
|
126
|
+
if (!result.gatewaysWiringFile) {
|
|
127
|
+
result.gatewaysWiringFile = join(gatewayDir, 'pikku-gateway-wirings.gen.ts');
|
|
128
|
+
}
|
|
129
129
|
// Channels/WebSocket
|
|
130
130
|
if (!result.channelsWiringFile) {
|
|
131
131
|
result.channelsWiringFile = join(channelDir, 'pikku-channels.gen.ts');
|
|
@@ -142,7 +142,7 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
142
142
|
if (!result.channelsTypesFile) {
|
|
143
143
|
result.channelsTypesFile = join(channelDir, 'pikku-channel-types.gen.ts');
|
|
144
144
|
}
|
|
145
|
-
// RPC (internal and
|
|
145
|
+
// RPC (internal and addon)
|
|
146
146
|
if (!result.rpcInternalWiringMetaFile) {
|
|
147
147
|
result.rpcInternalWiringMetaFile = join(rpcDir, 'pikku-rpc-wirings-meta.internal.gen.ts');
|
|
148
148
|
}
|
|
@@ -155,12 +155,31 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
155
155
|
if (!result.rpcMapDeclarationFile) {
|
|
156
156
|
result.rpcMapDeclarationFile = join(rpcDir, 'pikku-rpc-wirings-map.gen.d.ts');
|
|
157
157
|
}
|
|
158
|
-
// RPC
|
|
159
|
-
if (!result.
|
|
160
|
-
result.
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
158
|
+
// Remote RPC workers file (auto-derived)
|
|
159
|
+
if (!result.remoteRpcWorkersFile) {
|
|
160
|
+
result.remoteRpcWorkersFile = join(rpcDir, 'pikku-remote-rpc-workers.gen.ts');
|
|
161
|
+
}
|
|
162
|
+
// Derive feature file paths from scaffold.pikkuDir when enabled
|
|
163
|
+
if (result.scaffold?.rpc ||
|
|
164
|
+
result.scaffold?.agent ||
|
|
165
|
+
result.scaffold?.console ||
|
|
166
|
+
result.scaffold?.workflow) {
|
|
167
|
+
const pikkuDir = result.scaffold.pikkuDir ?? 'pikku';
|
|
168
|
+
const resolvedPikkuDir = isAbsolute(pikkuDir)
|
|
169
|
+
? pikkuDir
|
|
170
|
+
: join(result.rootDir, pikkuDir);
|
|
171
|
+
if (result.scaffold.rpc && !result.publicRpcFile) {
|
|
172
|
+
result.publicRpcFile = join(resolvedPikkuDir, 'rpc.wiring.gen.ts');
|
|
173
|
+
}
|
|
174
|
+
if (result.scaffold.agent && !result.publicAgentFile) {
|
|
175
|
+
result.publicAgentFile = join(resolvedPikkuDir, 'agent.wiring.gen.ts');
|
|
176
|
+
}
|
|
177
|
+
if (result.scaffold.console && !result.consoleFunctionsFile) {
|
|
178
|
+
result.consoleFunctionsFile = join(resolvedPikkuDir, 'console.gen.ts');
|
|
179
|
+
}
|
|
180
|
+
if (result.scaffold.workflow && !result.workflowWorkersFile) {
|
|
181
|
+
result.workflowWorkersFile = join(resolvedPikkuDir, 'workflows.gen.ts');
|
|
182
|
+
}
|
|
164
183
|
}
|
|
165
184
|
const triggerDir = join(result.outDir, 'trigger');
|
|
166
185
|
if (!result.triggersTypesFile) {
|
|
@@ -263,9 +282,6 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
263
282
|
if (!result.mcpWiringsFile) {
|
|
264
283
|
result.mcpWiringsFile = join(mcpDir, 'pikku-mcp-wirings.gen.ts');
|
|
265
284
|
}
|
|
266
|
-
if (!result.mcpJsonFile) {
|
|
267
|
-
result.mcpJsonFile = join(mcpDir, 'pikku-mcp.gen.json');
|
|
268
|
-
}
|
|
269
285
|
if (!result.mcpTypesFile) {
|
|
270
286
|
result.mcpTypesFile = join(mcpDir, 'pikku-mcp-types.gen.ts');
|
|
271
287
|
}
|
|
@@ -309,13 +325,12 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
309
325
|
if (!result.nodeTypesFile) {
|
|
310
326
|
result.nodeTypesFile = join(consoleDir, 'pikku-node-types.gen.ts');
|
|
311
327
|
}
|
|
312
|
-
|
|
313
|
-
const externalDir = join(result.outDir, 'external');
|
|
328
|
+
const addonDir = join(result.outDir, 'addon');
|
|
314
329
|
if (!result.packageFile) {
|
|
315
|
-
result.packageFile = join(
|
|
330
|
+
result.packageFile = join(addonDir, 'pikku-package.gen.ts');
|
|
316
331
|
}
|
|
317
|
-
if (!result.
|
|
318
|
-
result.
|
|
332
|
+
if (!result.addonTypesFile) {
|
|
333
|
+
result.addonTypesFile = join(addonDir, 'pikku-addon-types.gen.ts');
|
|
319
334
|
}
|
|
320
335
|
// Secrets (typed wrapper for SecretService)
|
|
321
336
|
const secretsDir = join(result.outDir, 'secrets');
|
|
@@ -346,21 +361,27 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
346
361
|
if (objectKey.endsWith('File') ||
|
|
347
362
|
objectKey.endsWith('Directory') ||
|
|
348
363
|
objectKey.endsWith('Dir')) {
|
|
349
|
-
const relativeTo = CONFIG_DIR_FILES.includes(objectKey)
|
|
350
|
-
? result.configDir
|
|
351
|
-
: result.rootDir;
|
|
352
364
|
// Only normalize string values to avoid corrupting nested objects
|
|
353
365
|
if (result[objectKey] && typeof result[objectKey] === 'string') {
|
|
354
366
|
if (!isAbsolute(result[objectKey])) {
|
|
355
|
-
result[objectKey] = join(
|
|
367
|
+
result[objectKey] = join(result.rootDir, result[objectKey]);
|
|
356
368
|
}
|
|
357
369
|
}
|
|
358
370
|
}
|
|
359
371
|
}
|
|
372
|
+
// Resolve clientFiles paths relative to configDir
|
|
373
|
+
if (result.clientFiles) {
|
|
374
|
+
for (const key of CLIENT_FILE_KEYS) {
|
|
375
|
+
const val = result.clientFiles[key];
|
|
376
|
+
if (val && typeof val === 'string' && !isAbsolute(val)) {
|
|
377
|
+
result.clientFiles[key] = join(result.configDir, val);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
360
381
|
if (!isAbsolute(result.tsconfig)) {
|
|
361
382
|
result.tsconfig = join(result.rootDir, result.tsconfig);
|
|
362
383
|
}
|
|
363
|
-
if (result.
|
|
384
|
+
if (result.addon) {
|
|
364
385
|
const packageJsonPath = join(result.rootDir, 'package.json');
|
|
365
386
|
try {
|
|
366
387
|
const packageJsonContent = await readFile(packageJsonPath, 'utf-8');
|
|
@@ -370,10 +391,10 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
|
|
|
370
391
|
packageJson.name.trim() === '') {
|
|
371
392
|
throw new Error(`package.json at ${packageJsonPath} is missing a valid "name" field`);
|
|
372
393
|
}
|
|
373
|
-
result.
|
|
394
|
+
result.addonName = packageJson.name;
|
|
374
395
|
}
|
|
375
396
|
catch (e) {
|
|
376
|
-
throw new Error(`
|
|
397
|
+
throw new Error(`addon is true but could not read or parse package.json at ${packageJsonPath}: ${e.message}`);
|
|
377
398
|
}
|
|
378
399
|
}
|
|
379
400
|
return result;
|