@postman/sdk-config 0.8.0 → 0.10.1

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.
@@ -297,7 +297,7 @@ var retryConfigSchema = z.strictObject({
297
297
  maxDelayMs: z.number().nonnegative().default(5e3).describe("The maximum backoff delay between attempts, in milliseconds."),
298
298
  jitterMs: z.number().nonnegative().default(50).describe("The maximum random jitter added to retry delays, in milliseconds."),
299
299
  backoffFactor: z.number().positive().default(2).describe("The multiplier applied to the delay after each failed attempt."),
300
- methods: z.array(nonEmptyStringSchema).default(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).describe("HTTP methods that are eligible for retries."),
300
+ methods: z.array(nonEmptyStringSchema).default(["GET", "PUT", "DELETE", "HEAD", "OPTIONS"]).describe("HTTP methods that are eligible for retries."),
301
301
  maxRetryAfterDelayMs: z.number().nonnegative().default(6e4).describe("The longest Retry-After delay the client will honor, in milliseconds.")
302
302
  }).superRefine(validateRetryDelays);
303
303
  var constructorParameterSchema = z.strictObject({
@@ -323,6 +323,22 @@ var tokenRefreshConfigSchema = z.strictObject({
323
323
  });
324
324
  }
325
325
  });
326
+ var idempotencyKeyGenerationSchema = z.strictObject({
327
+ enabled: z.boolean().describe("Whether the client generates an idempotency key when the caller supplies none."),
328
+ headerName: nonEmptyStringSchema.optional().describe("The header that carries the generated key. Generators default to Idempotency-Key."),
329
+ methods: z.array(nonEmptyStringSchema).optional().describe("HTTP methods that receive a generated key. Generators default to POST and PUT.")
330
+ });
331
+ var userAgentConfigSchema = z.strictObject({
332
+ template: nonEmptyStringSchema.optional().describe(
333
+ "The User-Agent product token, resolved at generation time. Supports the {packageName}, {version}, {language}, {generatorVersion}, {organization}, and {apiName} placeholders."
334
+ ),
335
+ includePlatformInfo: z.boolean().optional().describe(
336
+ "Whether the User-Agent carries operating system, architecture, and runtime details, as `{product} ({os}; {arch}) {runtime}/{runtimeVersion}`."
337
+ ),
338
+ allowAppInfo: z.boolean().optional().describe(
339
+ "Whether callers can pass application info that is appended to the User-Agent as a `{name}/{version} ({comment})` product token."
340
+ )
341
+ });
326
342
  var clientOverrideShape = {
327
343
  retry: clientRetryOverrideSchema.optional().describe("Retry behavior for generated API requests."),
328
344
  responseHeaders: z.boolean().optional().describe("Whether generated operations expose HTTP response headers."),
@@ -335,7 +351,12 @@ var clientOverrideShape = {
335
351
  filePropertyStyle: parameterStyleSchema.optional().describe("Whether generated file properties are wrapped or passed inline."),
336
352
  useDefaultRequestParameterValues: z.boolean().optional().describe("Whether schema defaults are applied to omitted request parameters."),
337
353
  respectOptionalRequestBody: z.boolean().optional().describe("Whether an optional request body remains optional in generated methods."),
338
- tokenRefresh: tokenRefreshConfigSchema.optional().describe("Refresh-token behavior for the generated client.")
354
+ tokenRefresh: tokenRefreshConfigSchema.optional().describe("Refresh-token behavior for the generated client."),
355
+ idempotencyKeyGeneration: idempotencyKeyGenerationSchema.optional().describe("Automatic idempotency keys on eligible requests."),
356
+ userAgent: userAgentConfigSchema.optional().describe("The User-Agent header the generated client sends."),
357
+ offsetSemantics: z.enum(["item-index", "page-index"]).optional().describe(
358
+ "How an offset-paginated endpoint advances: by the number of items returned, or by one page."
359
+ )
339
360
  };
340
361
  var clientConfigOverrideSchema = z.strictObject(clientOverrideShape);
341
362
  var clientConfigSchema = z.strictObject({
@@ -650,8 +671,19 @@ function mapOutput(generator, language, index) {
650
671
  const outputPath = ["group", "generators", index, "outputMode"];
651
672
  const state = { consumedPaths: /* @__PURE__ */ new Set(), credentialDiagnostics: [] };
652
673
  if (generator.output) {
674
+ const downloadSnippets = mapDownloadSnippets(
675
+ generator.outputMode,
676
+ outputPath,
677
+ state,
678
+ language,
679
+ index
680
+ );
653
681
  return {
654
682
  output: sanitizeNormalizedOutput(generator.output, rawOutput, state, index),
683
+ ...optional(
684
+ "docs",
685
+ downloadSnippets === void 0 ? void 0 : { snippets: { enabled: downloadSnippets } }
686
+ ),
655
687
  unsupportedFields: state.credentialDiagnostics ?? []
656
688
  };
657
689
  }
@@ -667,7 +699,8 @@ function mapOutput(generator, language, index) {
667
699
  generator.outputMode,
668
700
  outputPath,
669
701
  state,
670
- index
702
+ index,
703
+ language
671
704
  );
672
705
  }
673
706
  if (!isObject(generator.outputMode) || typeof generator.outputMode.type !== "string") {
@@ -683,14 +716,22 @@ function mapOutput(generator, language, index) {
683
716
  consume(state, [...outputPath, "type"]);
684
717
  switch (output.type) {
685
718
  case "downloadFiles":
686
- return finishOutputMapping({ output: { delivery: "zip" } }, output, outputPath, state, index);
719
+ return finishOutputMapping(
720
+ { output: { delivery: "zip" } },
721
+ output,
722
+ outputPath,
723
+ state,
724
+ index,
725
+ language
726
+ );
687
727
  case "github":
688
728
  return finishOutputMapping(
689
729
  githubOutput(output, output.publishInfo, rawOutput, language, outputPath, state, index),
690
730
  output,
691
731
  outputPath,
692
732
  state,
693
- index
733
+ index,
734
+ language
694
735
  );
695
736
  case "githubV2": {
696
737
  if (!isObject(output.githubV2))
@@ -715,7 +756,8 @@ function mapOutput(generator, language, index) {
715
756
  output,
716
757
  outputPath,
717
758
  state,
718
- index
759
+ index,
760
+ language
719
761
  );
720
762
  }
721
763
  case "publishV2": {
@@ -735,7 +777,8 @@ function mapOutput(generator, language, index) {
735
777
  output,
736
778
  outputPath,
737
779
  state,
738
- index
780
+ index,
781
+ language
739
782
  );
740
783
  }
741
784
  case "publish": {
@@ -755,7 +798,8 @@ function mapOutput(generator, language, index) {
755
798
  output,
756
799
  outputPath,
757
800
  state,
758
- index
801
+ index,
802
+ language
759
803
  );
760
804
  }
761
805
  default:
@@ -1262,7 +1306,8 @@ function mapAuthors(value, sourcePath, state) {
1262
1306
  });
1263
1307
  return authors;
1264
1308
  }
1265
- function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
1309
+ function finishOutputMapping(mapping, outputMode, sourcePath, state, index, language) {
1310
+ const downloadSnippets = mapDownloadSnippets(outputMode, sourcePath, state, language, index);
1266
1311
  for (const path of collectLeafPaths(outputMode, sourcePath)) {
1267
1312
  if (path[path.length - 1] === "_visit") consume(state, path);
1268
1313
  }
@@ -1270,6 +1315,10 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
1270
1315
  const hasCredentials = unsupported.some((diagnostic) => isCredentialPath(diagnostic.path));
1271
1316
  return {
1272
1317
  ...mapping,
1318
+ ...optional(
1319
+ "docs",
1320
+ downloadSnippets === void 0 ? void 0 : { snippets: { enabled: downloadSnippets } }
1321
+ ),
1273
1322
  unsupportedFields: [
1274
1323
  ...state.credentialDiagnostics ?? [],
1275
1324
  ...hasCredentials ? [
@@ -1289,6 +1338,45 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
1289
1338
  ]
1290
1339
  };
1291
1340
  }
1341
+ function mapDownloadSnippets(value, sourcePath, state, language, index) {
1342
+ if (!isObject(value)) return void 0;
1343
+ const candidates = [];
1344
+ switch (value.type) {
1345
+ case "downloadFiles":
1346
+ case "github":
1347
+ candidates.push({ value, path: sourcePath });
1348
+ break;
1349
+ case "githubV2":
1350
+ if (isObject(value.githubV2)) {
1351
+ candidates.push({ value: value.githubV2, path: [...sourcePath, "githubV2"] });
1352
+ }
1353
+ break;
1354
+ case "publishV2":
1355
+ if (isObject(value.publishV2)) {
1356
+ candidates.push({ value: value.publishV2, path: [...sourcePath, "publishV2"] });
1357
+ }
1358
+ break;
1359
+ case "publish":
1360
+ if (isObject(value.registryOverrides)) {
1361
+ const registry = defaultRegistry(language, [...sourcePath, "registryOverrides"], index);
1362
+ const override = value.registryOverrides[registry];
1363
+ if (isObject(override)) {
1364
+ candidates.push({
1365
+ value: override,
1366
+ path: [...sourcePath, "registryOverrides", registry]
1367
+ });
1368
+ }
1369
+ }
1370
+ break;
1371
+ }
1372
+ let enabled;
1373
+ for (const candidate of candidates) {
1374
+ if (typeof candidate.value.downloadSnippets !== "boolean") continue;
1375
+ consume(state, [...candidate.path, "downloadSnippets"]);
1376
+ enabled = enabled === true || candidate.value.downloadSnippets;
1377
+ }
1378
+ return enabled;
1379
+ }
1292
1380
  function isCredentialPath(path) {
1293
1381
  const fields = path.filter((part) => typeof part === "string");
1294
1382
  const field = fields[fields.length - 1];
@@ -2212,11 +2300,12 @@ function mapFernConfigToSdkConfigV1(input) {
2212
2300
  generator,
2213
2301
  language,
2214
2302
  invocation,
2215
- ...outputMapping
2303
+ ...outputMapping,
2304
+ docs: { ...invocation.docs, ...outputMapping.docs }
2216
2305
  };
2217
2306
  });
2218
2307
  const clients = partitionSharedBlock(mapped.map(({ invocation }) => invocation.client));
2219
- const docs = partitionSharedBlock(mapped.map(({ invocation }) => invocation.docs));
2308
+ const docs = partitionSharedBlock(mapped.map(({ docs: docs2 }) => docs2));
2220
2309
  const generations = partitionSharedBlock(mapped.map(({ invocation }) => invocation.generation));
2221
2310
  const api = { ...input.api ?? {} };
2222
2311
  delete api.audiences;
@@ -2405,6 +2494,14 @@ function mapInvocation(generator, language, activeLanguages, index) {
2405
2494
  ...prefix,
2406
2495
  "config"
2407
2496
  ]);
2497
+ const apiWideIdempotency = idempotencyKeyGenerationFrom(
2498
+ generator.idempotencyKeyGenerationConfig,
2499
+ [...prefix, "idempotencyKeyGenerationConfig"],
2500
+ state
2501
+ );
2502
+ if (apiWideIdempotency && client.idempotencyKeyGeneration === void 0) {
2503
+ client.idempotencyKeyGeneration = apiWideIdempotency;
2504
+ }
2408
2505
  const rawGenerator = isObject(generator.raw) ? generator.raw : void 0;
2409
2506
  const smartCasing = typeof rawGenerator?.["smart-casing"] === "boolean" ? rawGenerator["smart-casing"] : generator.smartCasing === false ? false : void 0;
2410
2507
  const smartCasingDigitWordBoundary = typeof rawGenerator?.["smart-casing-digit-word-boundary"] === "boolean" ? rawGenerator["smart-casing-digit-word-boundary"] : generator.smartCasingDigitWordBoundary === true ? true : void 0;
@@ -2438,16 +2535,19 @@ function mapInvocation(generator, language, activeLanguages, index) {
2438
2535
  ...collectUnsupported(config, [...prefix, "config"], state),
2439
2536
  ...settings ? collectUnsupported(settings, [...prefix, "settings"], state) : [],
2440
2537
  ...isObject(generator.readme) ? collectUnsupported(generator.readme, [...prefix, "readme"], state) : [],
2441
- ...unsupportedResolvedFields(generator, index)
2538
+ ...unsupportedResolvedFields(generator, index, apiWideIdempotency !== void 0)
2442
2539
  ];
2443
2540
  return { client, docs, generation, package: packageConfig, targetGeneration, unsupportedFields };
2444
2541
  }
2445
- function unsupportedResolvedFields(generator, index) {
2542
+ function unsupportedResolvedFields(generator, index, idempotencyMapped) {
2446
2543
  const values = [
2447
2544
  ["automation", isDefaultAutomation(generator.automation) ? void 0 : generator.automation],
2448
2545
  ["containerImage", generator.containerImage],
2449
2546
  ["irVersionOverride", generator.irVersionOverride],
2450
- ["idempotencyKeyGenerationConfig", generator.idempotencyKeyGenerationConfig],
2547
+ [
2548
+ "idempotencyKeyGenerationConfig",
2549
+ idempotencyMapped ? void 0 : generator.idempotencyKeyGenerationConfig
2550
+ ],
2451
2551
  ["absolutePathToLocalSnippets", generator.absolutePathToLocalSnippets],
2452
2552
  [
2453
2553
  "disableExamples",
@@ -2480,7 +2580,8 @@ function resolvedFieldGuidance(field) {
2480
2580
  }
2481
2581
  if (field === "idempotencyKeyGenerationConfig") {
2482
2582
  return {
2483
- suggestedAction: "Preserve this orchestration setting outside SDK Config; public v1 has no idempotency-generation field."
2583
+ sdkConfigPath: ["client", "idempotencyKeyGeneration"],
2584
+ suggestedAction: "Use true, false, or an object with header-name and methods, or set client.idempotencyKeyGeneration manually."
2484
2585
  };
2485
2586
  }
2486
2587
  if (field === "generateFullProject") {
@@ -2495,6 +2596,20 @@ function resolvedFieldGuidance(field) {
2495
2596
  function isDefaultAutomation(value) {
2496
2597
  return isObject(value) && value.generate === true && value.upgrade === true && value.preview === true && value.verify === true;
2497
2598
  }
2599
+ var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
2600
+ function idempotencyKeyGenerationFrom(value, path, state) {
2601
+ if (typeof value === "boolean") {
2602
+ consume(state, path);
2603
+ return { enabled: value };
2604
+ }
2605
+ if (!isObject(value)) return void 0;
2606
+ const probe = { consumedPaths: /* @__PURE__ */ new Set() };
2607
+ const headerName = takeString(value, ["headerName"], probe, path);
2608
+ const methods = takeEnumArray(value, ["methods"], HTTP_METHODS, probe, path);
2609
+ if (probe.consumedPaths.size !== Object.keys(value).length) return void 0;
2610
+ consume(state, path);
2611
+ return { enabled: true, ...optional("headerName", headerName), ...optional("methods", methods) };
2612
+ }
2498
2613
  function mapCommonConfig(language, config, state, client, generation, packageConfig, basePath) {
2499
2614
  const inlinePath = takeBoolean(config, ["inlinePathParameters"], state, basePath);
2500
2615
  const inlineFile = takeBoolean(config, ["inlineFileProperties"], state, basePath);
@@ -2519,6 +2634,23 @@ function mapCommonConfig(language, config, state, client, generation, packageCon
2519
2634
  if (useDefaults !== void 0) client.useDefaultRequestParameterValues = useDefaults;
2520
2635
  const respectOptionalBody = takeBoolean(config, ["respectOptionalRequestBody"], state, basePath);
2521
2636
  if (respectOptionalBody !== void 0) client.respectOptionalRequestBody = respectOptionalBody;
2637
+ const idempotency = locate(config, ["autoGenerateIdempotencyKey"], basePath);
2638
+ const idempotencyKeyGeneration = idempotency && idempotencyKeyGenerationFrom(idempotency.value, idempotency.path, state);
2639
+ if (idempotencyKeyGeneration) client.idempotencyKeyGeneration = idempotencyKeyGeneration;
2640
+ const userAgent = compact({
2641
+ template: takeString(config, ["userAgent"], state, basePath),
2642
+ includePlatformInfo: takeBoolean(config, ["includePlatformHeaders"], state, basePath),
2643
+ allowAppInfo: takeBoolean(config, ["allowUserAgentAppInfo"], state, basePath)
2644
+ });
2645
+ if (Object.keys(userAgent).length) client.userAgent = userAgent;
2646
+ const offsetSemantics = takeEnum(
2647
+ config,
2648
+ ["offsetSemantics"],
2649
+ ["item-index", "page-index"],
2650
+ state,
2651
+ basePath
2652
+ );
2653
+ if (offsetSemantics !== void 0) client.offsetSemantics = offsetSemantics;
2522
2654
  const maxRetries = takeNumber(config, ["maxRetries"], state, basePath);
2523
2655
  const statusCodeProfile = takeEnum(
2524
2656
  config,
@@ -2536,7 +2668,10 @@ function mapCommonConfig(language, config, state, client, generation, packageCon
2536
2668
  const pythonClient = language === "python" ? takeObject(config, ["client"], state, basePath) : void 0;
2537
2669
  const typescriptNaming = language === "typescript" || language === "mcp" ? takeObject(config, ["naming"], state, basePath) : void 0;
2538
2670
  const directClientName = takeString(config, ["clientName", "clientClassName"], state, basePath);
2539
- const nestedClientName = pythonClient ? takeString(pythonClient.value, ["className"], state, pythonClient.path) : typescriptNaming ? takeString(typescriptNaming.value, ["client"], state, typescriptNaming.path) : void 0;
2671
+ const nestedClientName = pythonClient ? takeString(pythonClient.value, ["className"], state, pythonClient.path) : typescriptNaming ? takeString(typescriptNaming.value, ["client"], state, typescriptNaming.path) : language === "ruby" ? (
2672
+ // Fern's Ruby generator renames the root client class (`Auth0::Management`) with it.
2673
+ takeString(config, ["clientModuleName"], state, basePath)
2674
+ ) : void 0;
2540
2675
  const directExportedClientName = takeString(
2541
2676
  config,
2542
2677
  ["exportedClientName", "exportedClientClassName"],
@@ -2705,7 +2840,8 @@ function mapPython(config, state, packageConfig, basePath) {
2705
2840
  });
2706
2841
  }
2707
2842
  function mapJvm(language, config, state, packageConfig, basePath) {
2708
- const namespace = takeString(config, ["packageName", "packagePrefix"], state, basePath);
2843
+ const namespaceAliases = language === "java" ? ["packagePrefix"] : ["packageName", "packagePrefix"];
2844
+ const namespace = takeString(config, namespaceAliases, state, basePath);
2709
2845
  const groupId = takeString(config, ["group", "groupId"], state, basePath);
2710
2846
  const artifactId = takeString(config, ["artifact", "artifactId"], state, basePath);
2711
2847
  if (namespace !== void 0) packageConfig.namespace = namespace;
@@ -2807,6 +2943,8 @@ function mapComposerRequirements(manifest, state, packageConfig) {
2807
2943
  function mapRuby(config, state, packageConfig, basePath) {
2808
2944
  const moduleName = takeString(config, ["moduleName"], state, basePath);
2809
2945
  if (moduleName !== void 0) packageConfig.moduleName = moduleName;
2946
+ const packageName = takeString(config, ["package-name"], state, basePath);
2947
+ if (packageName !== void 0) packageConfig.packageName = packageName;
2810
2948
  return compact({ requirePaths: takeStringArray(config, ["requirePaths"], state, basePath) });
2811
2949
  }
2812
2950
  function mapRust(config, state, packageConfig, basePath) {