@pikku/cli 0.12.2 → 0.12.3

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.
Files changed (110) hide show
  1. package/cli.schema.json +1 -1
  2. package/console-app/assets/index-Ci24-VT-.js +657 -0
  3. package/console-app/assets/{index-0Ui5UudO.css → index-DvrDbftC.css} +1 -1
  4. package/console-app/index.html +2 -2
  5. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  6. package/dist/.pikku/agent/pikku-agent-wirings-meta.gen.js +1 -1
  7. package/dist/.pikku/agent/pikku-agent-wirings.gen.d.ts +1 -1
  8. package/dist/.pikku/agent/pikku-agent-wirings.gen.js +1 -1
  9. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  10. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  11. package/dist/.pikku/channel/pikku-channels-meta.gen.js +1 -1
  12. package/dist/.pikku/channel/pikku-channels.gen.d.ts +1 -1
  13. package/dist/.pikku/channel/pikku-channels.gen.js +1 -1
  14. package/dist/.pikku/cli/pikku-cli-channel.d.ts +13 -1
  15. package/dist/.pikku/cli/pikku-cli-channel.js +17 -2
  16. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  17. package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
  18. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  19. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  20. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  21. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +12 -1
  22. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  23. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  24. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  25. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  26. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  27. package/dist/.pikku/function/pikku-function-types.gen.d.ts +30 -1
  28. package/dist/.pikku/function/pikku-function-types.gen.js +17 -1
  29. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  30. package/dist/.pikku/function/pikku-functions-meta.gen.json +114 -114
  31. package/dist/.pikku/function/pikku-functions.gen.js +1 -1
  32. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  33. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  34. package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
  35. package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
  36. package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
  37. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  38. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  39. package/dist/.pikku/mcp/pikku-mcp-wirings-meta.gen.js +1 -1
  40. package/dist/.pikku/mcp/pikku-mcp-wirings.gen.d.ts +1 -1
  41. package/dist/.pikku/mcp/pikku-mcp-wirings.gen.js +1 -1
  42. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  43. package/dist/.pikku/pikku-services.gen.d.ts +3 -1
  44. package/dist/.pikku/pikku-services.gen.js +2 -0
  45. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  46. package/dist/.pikku/pikku-types.gen.js +1 -1
  47. package/dist/.pikku/pikku-websocket.gen.d.ts +1 -1
  48. package/dist/.pikku/pikku-websocket.gen.js +1 -1
  49. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  50. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  51. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  52. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  53. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  54. package/dist/.pikku/rpc/pikku-remote-rpc-workers.gen.js +1 -1
  55. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  56. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  57. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  58. package/dist/.pikku/scheduler/pikku-schedulers-wirings-meta.gen.js +1 -1
  59. package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.d.ts +1 -1
  60. package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.js +1 -1
  61. package/dist/.pikku/schemas/register.gen.js +9 -9
  62. package/dist/.pikku/schemas/schemas/ConsoleCommandInput.schema.json +1 -1
  63. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  64. package/dist/.pikku/schemas/schemas/PikkuNewAddonInput.schema.json +1 -1
  65. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  66. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  67. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  68. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  69. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  70. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  71. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  72. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  73. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  74. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  75. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  76. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  77. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  78. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.d.ts +1 -1
  79. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  80. package/dist/src/cli.wiring.js +9 -0
  81. package/dist/src/functions/commands/all.js +33 -11
  82. package/dist/src/functions/commands/console.d.ts +3 -0
  83. package/dist/src/functions/commands/console.js +4 -2
  84. package/dist/src/functions/commands/new-addon.d.ts +3 -0
  85. package/dist/src/functions/commands/new-addon.js +8 -6
  86. package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +19 -0
  87. package/dist/src/functions/wirings/channels/pikku-command-channels-map.js +1 -1
  88. package/dist/src/functions/wirings/channels/serialize-typed-channel-map.d.ts +1 -1
  89. package/dist/src/functions/wirings/channels/serialize-typed-channel-map.js +7 -6
  90. package/dist/src/functions/wirings/cli/pikku-command-cli-entry.js +9 -1
  91. package/dist/src/functions/wirings/cli/serialize-channel-cli.js +35 -12
  92. package/dist/src/functions/wirings/console/pikku-command-node-types.js +2 -2
  93. package/dist/src/functions/wirings/console/pikku-command-nodes-meta.js +20 -11
  94. package/dist/src/functions/wirings/console/serialize-console-functions.js +1 -1
  95. package/dist/src/functions/wirings/functions/pikku-command-function-types-split.js +1 -1
  96. package/dist/src/functions/wirings/functions/serialize-addon-types.js +23 -1
  97. package/dist/src/functions/wirings/functions/serialize-function-types.js +38 -0
  98. package/dist/src/services.js +1 -1
  99. package/dist/src/utils/file-import-path.js +5 -2
  100. package/dist/src/utils/openapi/codegen.d.ts +1 -0
  101. package/dist/src/utils/openapi/codegen.js +214 -46
  102. package/dist/src/utils/openapi/parse-openapi.d.ts +25 -0
  103. package/dist/src/utils/openapi/parse-openapi.js +119 -9
  104. package/dist/src/utils/openapi/zod-codegen.d.ts +1 -53
  105. package/dist/src/utils/openapi/zod-codegen.js +1 -251
  106. package/dist/src/utils/pikku-cli-config.js +2 -2
  107. package/dist/src/utils/strip-verbose-meta.d.ts +2 -0
  108. package/dist/src/utils/strip-verbose-meta.js +34 -0
  109. package/package.json +4 -3
  110. package/console-app/assets/index-DRJQtv3c.js +0 -676
@@ -16,6 +16,15 @@ export async function parseOpenAPISpec(filePath) {
16
16
  else {
17
17
  doc = parseYAML(content);
18
18
  }
19
+ // Validate spec version
20
+ const specVersion = doc.openapi ?? doc.swagger;
21
+ if (!specVersion) {
22
+ throw new Error('Not a valid OpenAPI/Swagger spec: missing "openapi" or "swagger" version field.');
23
+ }
24
+ const major = String(specVersion).split('.')[0];
25
+ if (major !== '2' && major !== '3') {
26
+ throw new Error(`Unsupported spec version "${specVersion}". Only OpenAPI 3.x and Swagger 2.x are supported.`);
27
+ }
19
28
  // Resolve all $ref pointers in-place
20
29
  resolveRefs(doc, doc);
21
30
  const info = {
@@ -23,8 +32,11 @@ export async function parseOpenAPISpec(filePath) {
23
32
  version: doc.info?.version ?? '1.0.0',
24
33
  description: doc.info?.description,
25
34
  };
26
- const baseUrl = extractBaseUrl(doc);
35
+ const serverUrls = extractServerUrls(doc);
36
+ const baseUrl = serverUrls[0] ?? '';
27
37
  const authType = detectAuthType(doc);
38
+ const securitySchemes = extractSecuritySchemes(doc);
39
+ const tagDescriptions = extractTagDescriptions(doc);
28
40
  // Extract component schemas
29
41
  const componentSchemas = {};
30
42
  if (doc.components?.schemas) {
@@ -32,7 +44,7 @@ export async function parseOpenAPISpec(filePath) {
32
44
  componentSchemas[name] = schema;
33
45
  }
34
46
  }
35
- // Extract operations
47
+ // Extract operations (skip deprecated)
36
48
  const operations = [];
37
49
  if (doc.paths) {
38
50
  for (const [path, pathItem] of Object.entries(doc.paths)) {
@@ -42,7 +54,11 @@ export async function parseOpenAPISpec(filePath) {
42
54
  const op = pathItem[method];
43
55
  if (!op)
44
56
  continue;
57
+ // Skip deprecated operations
58
+ if (op.deprecated === true)
59
+ continue;
45
60
  const allParams = [...sharedParams, ...(op.parameters ?? [])];
61
+ const body = op.requestBody;
46
62
  operations.push({
47
63
  operationId: op.operationId,
48
64
  method,
@@ -52,14 +68,28 @@ export async function parseOpenAPISpec(filePath) {
52
68
  tags: op.tags ?? [],
53
69
  pathParams: extractParams(allParams, 'path'),
54
70
  queryParams: extractParams(allParams, 'query'),
71
+ headerParams: extractParams(allParams, 'header'),
55
72
  requestBody: extractRequestBody(op),
73
+ requestBodyDescription: body?.description,
74
+ requestBodyRequired: body?.required,
56
75
  responseSchema: extractResponseSchema(op),
57
76
  responseDescription: extractResponseDescription(op),
77
+ errorResponses: extractErrorResponses(op),
78
+ deprecated: false,
58
79
  });
59
80
  }
60
81
  }
61
82
  }
62
- return { info, baseUrl, authType, operations, componentSchemas };
83
+ return {
84
+ info,
85
+ baseUrl,
86
+ serverUrls,
87
+ authType,
88
+ operations,
89
+ componentSchemas,
90
+ securitySchemes,
91
+ tagDescriptions,
92
+ };
63
93
  }
64
94
  /** Recursively resolve $ref pointers in-place */
65
95
  function resolveRefs(node, root) {
@@ -100,18 +130,18 @@ function resolveRefPath(ref, root) {
100
130
  }
101
131
  return current;
102
132
  }
103
- function extractBaseUrl(doc) {
133
+ function extractServerUrls(doc) {
104
134
  // OpenAPI 3.x
105
135
  if (doc.servers && doc.servers.length > 0) {
106
- return doc.servers[0].url ?? '';
136
+ return doc.servers.map((s) => s.url).filter((url) => !!url);
107
137
  }
108
138
  // Swagger 2.x
109
139
  if (doc.host) {
110
- const scheme = doc.schemes?.[0] ?? 'https';
140
+ const schemes = doc.schemes?.length ? doc.schemes : ['https'];
111
141
  const basePath = doc.basePath ?? '';
112
- return `${scheme}://${doc.host}${basePath}`;
142
+ return schemes.map((scheme) => `${scheme}://${doc.host}${basePath}`);
113
143
  }
114
- return '';
144
+ return [];
115
145
  }
116
146
  function detectAuthType(doc) {
117
147
  const securitySchemes = doc.components?.securitySchemes ?? doc.securityDefinitions ?? {};
@@ -125,14 +155,31 @@ function detectAuthType(doc) {
125
155
  }
126
156
  return 'none';
127
157
  }
158
+ /**
159
+ * Build an OpenAPI schema object from v2-style parameter-level properties
160
+ * (type, enum, items, format, default) that aren't nested under `schema`.
161
+ */
162
+ function paramToSchema(p) {
163
+ const schema = { type: p.type ?? 'string' };
164
+ if (p.enum)
165
+ schema.enum = p.enum;
166
+ if (p.items)
167
+ schema.items = p.items;
168
+ if (p.format)
169
+ schema.format = p.format;
170
+ if (p.default !== undefined)
171
+ schema.default = p.default;
172
+ return schema;
173
+ }
128
174
  function extractParams(params, location) {
129
175
  return params
130
176
  .filter((p) => p.in === location)
131
177
  .map((p) => ({
132
178
  name: p.name,
133
179
  required: p.required ?? location === 'path',
134
- schema: (p.schema ?? { type: 'string' }),
180
+ schema: (p.schema ?? paramToSchema(p)),
135
181
  description: p.description,
182
+ example: p.example,
136
183
  }));
137
184
  }
138
185
  function extractRequestBody(op) {
@@ -194,3 +241,66 @@ function extractResponseSchema(op) {
194
241
  }
195
242
  return undefined;
196
243
  }
244
+ function extractErrorResponses(op) {
245
+ const responses = op.responses;
246
+ if (!responses)
247
+ return [];
248
+ const errors = [];
249
+ for (const [code, resp] of Object.entries(responses)) {
250
+ const statusCode = parseInt(code, 10);
251
+ if (isNaN(statusCode))
252
+ continue;
253
+ if (statusCode >= 400) {
254
+ errors.push({
255
+ statusCode,
256
+ description: resp.description ?? `Error ${statusCode}`,
257
+ });
258
+ }
259
+ }
260
+ return errors;
261
+ }
262
+ function extractSecuritySchemes(doc) {
263
+ const raw = doc.components?.securitySchemes ?? doc.securityDefinitions ?? {};
264
+ const result = {};
265
+ for (const [name, scheme] of Object.entries(raw)) {
266
+ const info = {
267
+ type: scheme.type === 'http' ? 'http' : scheme.type,
268
+ };
269
+ if (scheme.type === 'http') {
270
+ info.scheme = scheme.scheme;
271
+ info.bearerFormat = scheme.bearerFormat;
272
+ }
273
+ if (scheme.type === 'apiKey') {
274
+ info.name = scheme.name;
275
+ info.in = scheme.in;
276
+ }
277
+ if (scheme.type === 'oauth2') {
278
+ // Extract flows — prefer authorizationCode, then implicit, then clientCredentials
279
+ const flows = scheme.flows ?? {};
280
+ const flow = flows.authorizationCode ??
281
+ flows.implicit ??
282
+ flows.clientCredentials ??
283
+ flows.password;
284
+ if (flow) {
285
+ info.flows = {
286
+ authorizationUrl: flow.authorizationUrl,
287
+ tokenUrl: flow.tokenUrl,
288
+ scopes: flow.scopes,
289
+ };
290
+ }
291
+ }
292
+ result[name] = info;
293
+ }
294
+ return result;
295
+ }
296
+ function extractTagDescriptions(doc) {
297
+ const result = {};
298
+ if (Array.isArray(doc.tags)) {
299
+ for (const tag of doc.tags) {
300
+ if (tag.name && tag.description) {
301
+ result[tag.name] = tag.description;
302
+ }
303
+ }
304
+ }
305
+ return result;
306
+ }
@@ -1,53 +1 @@
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;
1
+ export { type OpenAPISchema, type ZodCodegenContext, createContext, schemaToZod, schemaVarName, } from '@pikku/openapi-to-zod-schema';
@@ -1,251 +1 @@
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
+ export { createContext, schemaToZod, schemaVarName, } from '@pikku/openapi-to-zod-schema';
@@ -319,8 +319,8 @@ const _getPikkuCLIConfig = async (logger, configFile = undefined, requiredFields
319
319
  result.cliTypesFile = join(cliDir, 'pikku-cli-types.gen.ts');
320
320
  }
321
321
  const consoleDir = join(result.outDir, 'console');
322
- if (!result.nodesMetaJsonFile) {
323
- result.nodesMetaJsonFile = join(consoleDir, 'pikku-nodes-meta.gen.json');
322
+ if (!result.addonMetaJsonFile) {
323
+ result.addonMetaJsonFile = join(consoleDir, 'pikku-addon-meta.gen.json');
324
324
  }
325
325
  if (!result.nodeTypesFile) {
326
326
  result.nodeTypesFile = join(consoleDir, 'pikku-node-types.gen.ts');
@@ -25,6 +25,8 @@
25
25
  * 2. Record of meta entries: { "entryName": { pikkuFuncId, description, tags, ... } }
26
26
  * -> Strips description, tags from each entry (one level deep only)
27
27
  * 3. CLI meta and others with complex nesting: preserved as-is except for pikkuFuncId entries
28
+ *
29
+ * Also strips addon namespace prefixes from pikkuFuncId values where packageName is present.
28
30
  */
29
31
  export declare function stripVerboseFields<T>(obj: T): T;
30
32
  /**
@@ -75,6 +75,35 @@ function hasVerboseShallow(obj, additionalFields) {
75
75
  }
76
76
  return false;
77
77
  }
78
+ /**
79
+ * Recursively strip addon namespace prefixes from pikkuFuncId values.
80
+ * When an entry has both pikkuFuncId (e.g. "swaggerPetstore:addPet") and packageName,
81
+ * the namespace prefix is redundant — strip it so runtime gets bare function names.
82
+ */
83
+ function stripAddonNamespacePrefixes(obj) {
84
+ if (obj === null || obj === undefined || typeof obj !== 'object')
85
+ return obj;
86
+ if (Array.isArray(obj))
87
+ return obj.map(stripAddonNamespacePrefixes);
88
+ const record = obj;
89
+ const result = {};
90
+ for (const [key, value] of Object.entries(record)) {
91
+ if (key === 'pikkuFuncId' &&
92
+ typeof value === 'string' &&
93
+ value.includes(':') &&
94
+ 'packageName' in record &&
95
+ record.packageName) {
96
+ result[key] = value.substring(value.indexOf(':') + 1);
97
+ }
98
+ else if (typeof value === 'object' && value !== null) {
99
+ result[key] = stripAddonNamespacePrefixes(value);
100
+ }
101
+ else {
102
+ result[key] = value;
103
+ }
104
+ }
105
+ return result;
106
+ }
78
107
  /**
79
108
  * Strip verbose fields from a meta object.
80
109
  *
@@ -84,8 +113,13 @@ function hasVerboseShallow(obj, additionalFields) {
84
113
  * 2. Record of meta entries: { "entryName": { pikkuFuncId, description, tags, ... } }
85
114
  * -> Strips description, tags from each entry (one level deep only)
86
115
  * 3. CLI meta and others with complex nesting: preserved as-is except for pikkuFuncId entries
116
+ *
117
+ * Also strips addon namespace prefixes from pikkuFuncId values where packageName is present.
87
118
  */
88
119
  export function stripVerboseFields(obj) {
120
+ return stripAddonNamespacePrefixes(_stripVerboseFieldsInner(obj));
121
+ }
122
+ function _stripVerboseFieldsInner(obj) {
89
123
  if (obj === null || obj === undefined || typeof obj !== 'object') {
90
124
  return obj;
91
125
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/cli",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "BUSL-1.1",
6
6
  "imports": {
@@ -25,8 +25,9 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@openapi-contrib/json-schema-to-openapi-schema": "^4.3.1",
28
- "@pikku/core": "^0.12.2",
29
- "@pikku/inspector": "^0.12.2",
28
+ "@pikku/core": "^0.12.3",
29
+ "@pikku/inspector": "^0.12.3",
30
+ "@pikku/openapi-to-zod-schema": "^0.12.2",
30
31
  "@types/cookie": "^1.0.0",
31
32
  "@types/json-schema": "^7.0.15",
32
33
  "chalk": "^5.6.2",