poe-code 3.0.286 → 3.0.287

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-code",
3
- "version": "3.0.286",
3
+ "version": "3.0.287",
4
4
  "description": "CLI tool to configure Poe API for developer workflows.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -230,6 +230,9 @@ export type GeneratedPreflightBlock = {
230
230
  jsonParamName: string;
231
231
  nullParamName?: string;
232
232
  resolvedName: string;
233
+ definition: Extract<GeneratedParamDefinition, {
234
+ kind: "array";
235
+ }>;
233
236
  required: boolean;
234
237
  };
235
238
  interface SchemaOptionEntry {
@@ -870,6 +870,7 @@ function createArrayParam(options) {
870
870
  jsonParamName,
871
871
  ...(emitsNullHelper ? { nullParamName } : {}),
872
872
  resolvedName,
873
+ definition: directDefinition,
873
874
  required: !optional
874
875
  }
875
876
  ],
@@ -1386,11 +1387,13 @@ function createCommandFile(options) {
1386
1387
  const usesMultipartFileInputs = options.bodyMode === "multipart" &&
1387
1388
  options.multipartBinaryFields !== undefined &&
1388
1389
  options.multipartBinaryFields.length > 0;
1390
+ const usesArrayJsonValidation = options.preflightBlocks.some((block) => block.kind === "array");
1389
1391
  const usesBinaryOutput = options.responseMode === "binary";
1390
1392
  const usesRequestShapeVariable = usesMultipartFileInputs || usesBinaryOutput;
1391
1393
  const openApiImports = [
1392
1394
  "requestJson",
1393
1395
  "defineApiCommand",
1396
+ ...(usesArrayJsonValidation ? ["validateArrayJsonHelperValue"] : []),
1394
1397
  ...(usesMultipartFileInputs ? ["prepareMultipartFileInputs"] : []),
1395
1398
  ...(usesBinaryOutput ? ["writeBinaryResponseOutput"] : [])
1396
1399
  ];
@@ -19,4 +19,5 @@ export type { AuthProvider, CommandContributor, TokenSource } from "./auth/types
19
19
  export { bearerTokenAuth } from "./auth/bearer-token-auth.js";
20
20
  export type { BearerTokenAuthOptions } from "./auth/bearer-token-auth.js";
21
21
  export { HttpError, prepareMultipartFileInputs, requestJson, writeBinaryResponseOutput } from "./http.js";
22
+ export { validateArrayJsonHelperValue } from "./interpreter.js";
22
23
  export type { BinaryHttpResponse, HttpErrorRequest, HttpErrorResponse, HttpRequestOptions, QueryValue } from "./http.js";
@@ -10,3 +10,4 @@ export { renderOpenApiInspection } from "./render-inspection.js";
10
10
  export { commandsFromSpec, defineClientFromSpec, resolveOpenApiBaseUrl } from "./runtime.js";
11
11
  export { bearerTokenAuth } from "./auth/bearer-token-auth.js";
12
12
  export { HttpError, prepareMultipartFileInputs, requestJson, writeBinaryResponseOutput } from "./http.js";
13
+ export { validateArrayJsonHelperValue } from "./interpreter.js";
@@ -1,6 +1,12 @@
1
1
  import { type RequestSectionKey } from "./request-shape.js";
2
- import type { GeneratedPreflightBlock, GeneratedRequestField, GeneratedRequestLocation, GeneratedRequestSectionRenders } from "./generate.js";
2
+ import type { GeneratedParamDefinition, GeneratedPreflightBlock, GeneratedRequestField, GeneratedRequestLocation, GeneratedRequestSectionRenders } from "./generate.js";
3
+ type GeneratedArrayDefinition = GeneratedParamDefinition & {
4
+ kind: "array";
5
+ itemDefinition: GeneratedParamDefinition;
6
+ };
3
7
  export declare function renderPreflightBlock(block: GeneratedPreflightBlock): string[];
4
8
  export declare function executePreflightBlocks(blocks: ReadonlyArray<GeneratedPreflightBlock>, params: Readonly<Record<string, unknown>>): Record<string, unknown>;
9
+ export declare function validateArrayJsonHelperValue(value: unknown, definition: GeneratedArrayDefinition, jsonParamName: string): void;
5
10
  export declare function renderRequestShape(requestFields: ReadonlyArray<GeneratedRequestField>, sectionRenders: GeneratedRequestSectionRenders, optionalSections: ReadonlySet<GeneratedRequestLocation>): string[];
6
11
  export declare function buildRequestShape(requestFields: ReadonlyArray<GeneratedRequestField>, sectionRenders: GeneratedRequestSectionRenders, optionalSections: ReadonlySet<GeneratedRequestLocation>, params: Readonly<Record<string, unknown>>, resolvedValues: Readonly<Record<string, unknown>>): Partial<Record<RequestSectionKey, unknown>>;
12
+ export {};
@@ -86,6 +86,7 @@ const PREFLIGHT_BLOCK_OPERATIONS = {
86
86
  " if (!Array.isArray(parsedJson)) {",
87
87
  ` throw new UserError(${JSON.stringify(getInvalidArrayJsonMessage(block.jsonParamName, "Expected a JSON array."))});`,
88
88
  " }",
89
+ ` validateArrayJsonHelperValue(parsedJson, ${JSON.stringify(block.definition)}, ${JSON.stringify(block.jsonParamName)});`,
89
90
  ` ${block.resolvedName} = parsedJson;`,
90
91
  " }",
91
92
  ...(block.nullParamName === undefined
@@ -126,6 +127,7 @@ const PREFLIGHT_BLOCK_OPERATIONS = {
126
127
  if (!Array.isArray(parsedJson)) {
127
128
  throw new UserError(getInvalidArrayJsonMessage(block.jsonParamName, "Expected a JSON array."));
128
129
  }
130
+ validateArrayJsonHelperValue(parsedJson, block.definition, block.jsonParamName);
129
131
  resolved = parsedJson;
130
132
  }
131
133
  if (nullRequested) {
@@ -208,6 +210,107 @@ export function executePreflightBlocks(blocks, params) {
208
210
  }
209
211
  return resolvedValues;
210
212
  }
213
+ export function validateArrayJsonHelperValue(value, definition, jsonParamName) {
214
+ const issue = findDefinitionIssue(value, definition, []);
215
+ if (issue !== undefined) {
216
+ throw new UserError(getInvalidArrayJsonMessage(jsonParamName, issue));
217
+ }
218
+ }
219
+ function findDefinitionIssue(value, definition, path) {
220
+ if (value === null) {
221
+ return definition.nullable === true || definition.kind === "json"
222
+ ? undefined
223
+ : `Expected ${expectedDefinition(definition)} at ${formatJsonPath(path)}.`;
224
+ }
225
+ switch (definition.kind) {
226
+ case "array":
227
+ return findArrayDefinitionIssue(value, definition, path);
228
+ case "boolean":
229
+ return typeof value === "boolean"
230
+ ? undefined
231
+ : `Expected boolean at ${formatJsonPath(path)}.`;
232
+ case "enum":
233
+ return definition.enumValues.includes(value)
234
+ ? undefined
235
+ : `Expected one of ${definition.enumValues.join(", ")} at ${formatJsonPath(path)}.`;
236
+ case "json":
237
+ return undefined;
238
+ case "number":
239
+ return findNumberDefinitionIssue(value, definition, path);
240
+ case "string":
241
+ return findStringDefinitionIssue(value, definition, path);
242
+ }
243
+ }
244
+ function findArrayDefinitionIssue(value, definition, path) {
245
+ if (!Array.isArray(value)) {
246
+ return `Expected array at ${formatJsonPath(path)}.`;
247
+ }
248
+ if (definition.minItems !== undefined && value.length < definition.minItems) {
249
+ return `Expected array with at least ${definition.minItems} items at ${formatJsonPath(path)}.`;
250
+ }
251
+ if (definition.maxItems !== undefined && value.length > definition.maxItems) {
252
+ return `Expected array with at most ${definition.maxItems} items at ${formatJsonPath(path)}.`;
253
+ }
254
+ for (const [index, item] of value.entries()) {
255
+ const issue = findDefinitionIssue(item, definition.itemDefinition, [...path, String(index)]);
256
+ if (issue !== undefined) {
257
+ return issue;
258
+ }
259
+ }
260
+ return undefined;
261
+ }
262
+ function findNumberDefinitionIssue(value, definition, path) {
263
+ if (typeof value !== "number" || !Number.isFinite(value)) {
264
+ return `Expected ${definition.jsonType === "integer" ? "integer" : "number"} at ${formatJsonPath(path)}.`;
265
+ }
266
+ if (definition.jsonType === "integer" && !Number.isInteger(value)) {
267
+ return `Expected integer at ${formatJsonPath(path)}.`;
268
+ }
269
+ if (definition.minimum !== undefined && value < definition.minimum) {
270
+ return `Expected number greater than or equal to ${definition.minimum} at ${formatJsonPath(path)}.`;
271
+ }
272
+ if (definition.maximum !== undefined && value > definition.maximum) {
273
+ return `Expected number less than or equal to ${definition.maximum} at ${formatJsonPath(path)}.`;
274
+ }
275
+ return undefined;
276
+ }
277
+ function findStringDefinitionIssue(value, definition, path) {
278
+ if (typeof value !== "string") {
279
+ return `Expected string at ${formatJsonPath(path)}.`;
280
+ }
281
+ if (definition.minLength !== undefined && value.length < definition.minLength) {
282
+ return `Expected string with length at least ${definition.minLength} at ${formatJsonPath(path)}.`;
283
+ }
284
+ if (definition.maxLength !== undefined && value.length > definition.maxLength) {
285
+ return `Expected string with length at most ${definition.maxLength} at ${formatJsonPath(path)}.`;
286
+ }
287
+ if (definition.pattern !== undefined) {
288
+ const pattern = compileDefinitionPattern(definition.pattern);
289
+ if (pattern === undefined || !pattern.test(value)) {
290
+ return `Expected string matching pattern ${definition.pattern} at ${formatJsonPath(path)}.`;
291
+ }
292
+ }
293
+ return undefined;
294
+ }
295
+ function compileDefinitionPattern(pattern) {
296
+ try {
297
+ return new RegExp(pattern, "u");
298
+ }
299
+ catch {
300
+ return undefined;
301
+ }
302
+ }
303
+ function expectedDefinition(definition) {
304
+ return definition.kind === "number" && definition.jsonType === "integer"
305
+ ? "integer"
306
+ : definition.kind;
307
+ }
308
+ function formatJsonPath(path) {
309
+ if (path.length === 0) {
310
+ return "the JSON array";
311
+ }
312
+ return path.map((segment) => `[${segment}]`).join("");
313
+ }
211
314
  export function renderRequestShape(requestFields, sectionRenders, optionalSections) {
212
315
  const lines = [];
213
316
  for (const section of REQUEST_PARAM_SECTIONS) {