@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.
@@ -303,7 +303,7 @@ var retryConfigSchema = zod.z.strictObject({
303
303
  maxDelayMs: zod.z.number().nonnegative().default(5e3).describe("The maximum backoff delay between attempts, in milliseconds."),
304
304
  jitterMs: zod.z.number().nonnegative().default(50).describe("The maximum random jitter added to retry delays, in milliseconds."),
305
305
  backoffFactor: zod.z.number().positive().default(2).describe("The multiplier applied to the delay after each failed attempt."),
306
- methods: zod.z.array(nonEmptyStringSchema).default(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).describe("HTTP methods that are eligible for retries."),
306
+ methods: zod.z.array(nonEmptyStringSchema).default(["GET", "PUT", "DELETE", "HEAD", "OPTIONS"]).describe("HTTP methods that are eligible for retries."),
307
307
  maxRetryAfterDelayMs: zod.z.number().nonnegative().default(6e4).describe("The longest Retry-After delay the client will honor, in milliseconds.")
308
308
  }).superRefine(validateRetryDelays);
309
309
  var constructorParameterSchema = zod.z.strictObject({
@@ -329,6 +329,22 @@ var tokenRefreshConfigSchema = zod.z.strictObject({
329
329
  });
330
330
  }
331
331
  });
332
+ var idempotencyKeyGenerationSchema = zod.z.strictObject({
333
+ enabled: zod.z.boolean().describe("Whether the client generates an idempotency key when the caller supplies none."),
334
+ headerName: nonEmptyStringSchema.optional().describe("The header that carries the generated key. Generators default to Idempotency-Key."),
335
+ methods: zod.z.array(nonEmptyStringSchema).optional().describe("HTTP methods that receive a generated key. Generators default to POST and PUT.")
336
+ });
337
+ var userAgentConfigSchema = zod.z.strictObject({
338
+ template: nonEmptyStringSchema.optional().describe(
339
+ "The User-Agent product token, resolved at generation time. Supports the {packageName}, {version}, {language}, {generatorVersion}, {organization}, and {apiName} placeholders."
340
+ ),
341
+ includePlatformInfo: zod.z.boolean().optional().describe(
342
+ "Whether the User-Agent carries operating system, architecture, and runtime details, as `{product} ({os}; {arch}) {runtime}/{runtimeVersion}`."
343
+ ),
344
+ allowAppInfo: zod.z.boolean().optional().describe(
345
+ "Whether callers can pass application info that is appended to the User-Agent as a `{name}/{version} ({comment})` product token."
346
+ )
347
+ });
332
348
  var clientOverrideShape = {
333
349
  retry: clientRetryOverrideSchema.optional().describe("Retry behavior for generated API requests."),
334
350
  responseHeaders: zod.z.boolean().optional().describe("Whether generated operations expose HTTP response headers."),
@@ -341,7 +357,12 @@ var clientOverrideShape = {
341
357
  filePropertyStyle: parameterStyleSchema.optional().describe("Whether generated file properties are wrapped or passed inline."),
342
358
  useDefaultRequestParameterValues: zod.z.boolean().optional().describe("Whether schema defaults are applied to omitted request parameters."),
343
359
  respectOptionalRequestBody: zod.z.boolean().optional().describe("Whether an optional request body remains optional in generated methods."),
344
- tokenRefresh: tokenRefreshConfigSchema.optional().describe("Refresh-token behavior for the generated client.")
360
+ tokenRefresh: tokenRefreshConfigSchema.optional().describe("Refresh-token behavior for the generated client."),
361
+ idempotencyKeyGeneration: idempotencyKeyGenerationSchema.optional().describe("Automatic idempotency keys on eligible requests."),
362
+ userAgent: userAgentConfigSchema.optional().describe("The User-Agent header the generated client sends."),
363
+ offsetSemantics: zod.z.enum(["item-index", "page-index"]).optional().describe(
364
+ "How an offset-paginated endpoint advances: by the number of items returned, or by one page."
365
+ )
345
366
  };
346
367
  var clientConfigOverrideSchema = zod.z.strictObject(clientOverrideShape);
347
368
  var clientConfigSchema = zod.z.strictObject({
@@ -656,8 +677,19 @@ function mapOutput(generator, language, index) {
656
677
  const outputPath = ["group", "generators", index, "outputMode"];
657
678
  const state = { consumedPaths: /* @__PURE__ */ new Set(), credentialDiagnostics: [] };
658
679
  if (generator.output) {
680
+ const downloadSnippets = mapDownloadSnippets(
681
+ generator.outputMode,
682
+ outputPath,
683
+ state,
684
+ language,
685
+ index
686
+ );
659
687
  return {
660
688
  output: sanitizeNormalizedOutput(generator.output, rawOutput, state, index),
689
+ ...optional(
690
+ "docs",
691
+ downloadSnippets === void 0 ? void 0 : { snippets: { enabled: downloadSnippets } }
692
+ ),
661
693
  unsupportedFields: state.credentialDiagnostics ?? []
662
694
  };
663
695
  }
@@ -673,7 +705,8 @@ function mapOutput(generator, language, index) {
673
705
  generator.outputMode,
674
706
  outputPath,
675
707
  state,
676
- index
708
+ index,
709
+ language
677
710
  );
678
711
  }
679
712
  if (!isObject(generator.outputMode) || typeof generator.outputMode.type !== "string") {
@@ -689,14 +722,22 @@ function mapOutput(generator, language, index) {
689
722
  consume(state, [...outputPath, "type"]);
690
723
  switch (output.type) {
691
724
  case "downloadFiles":
692
- return finishOutputMapping({ output: { delivery: "zip" } }, output, outputPath, state, index);
725
+ return finishOutputMapping(
726
+ { output: { delivery: "zip" } },
727
+ output,
728
+ outputPath,
729
+ state,
730
+ index,
731
+ language
732
+ );
693
733
  case "github":
694
734
  return finishOutputMapping(
695
735
  githubOutput(output, output.publishInfo, rawOutput, language, outputPath, state, index),
696
736
  output,
697
737
  outputPath,
698
738
  state,
699
- index
739
+ index,
740
+ language
700
741
  );
701
742
  case "githubV2": {
702
743
  if (!isObject(output.githubV2))
@@ -721,7 +762,8 @@ function mapOutput(generator, language, index) {
721
762
  output,
722
763
  outputPath,
723
764
  state,
724
- index
765
+ index,
766
+ language
725
767
  );
726
768
  }
727
769
  case "publishV2": {
@@ -741,7 +783,8 @@ function mapOutput(generator, language, index) {
741
783
  output,
742
784
  outputPath,
743
785
  state,
744
- index
786
+ index,
787
+ language
745
788
  );
746
789
  }
747
790
  case "publish": {
@@ -761,7 +804,8 @@ function mapOutput(generator, language, index) {
761
804
  output,
762
805
  outputPath,
763
806
  state,
764
- index
807
+ index,
808
+ language
765
809
  );
766
810
  }
767
811
  default:
@@ -1268,7 +1312,8 @@ function mapAuthors(value, sourcePath, state) {
1268
1312
  });
1269
1313
  return authors;
1270
1314
  }
1271
- function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
1315
+ function finishOutputMapping(mapping, outputMode, sourcePath, state, index, language) {
1316
+ const downloadSnippets = mapDownloadSnippets(outputMode, sourcePath, state, language, index);
1272
1317
  for (const path of collectLeafPaths(outputMode, sourcePath)) {
1273
1318
  if (path[path.length - 1] === "_visit") consume(state, path);
1274
1319
  }
@@ -1276,6 +1321,10 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
1276
1321
  const hasCredentials = unsupported.some((diagnostic) => isCredentialPath(diagnostic.path));
1277
1322
  return {
1278
1323
  ...mapping,
1324
+ ...optional(
1325
+ "docs",
1326
+ downloadSnippets === void 0 ? void 0 : { snippets: { enabled: downloadSnippets } }
1327
+ ),
1279
1328
  unsupportedFields: [
1280
1329
  ...state.credentialDiagnostics ?? [],
1281
1330
  ...hasCredentials ? [
@@ -1295,6 +1344,45 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
1295
1344
  ]
1296
1345
  };
1297
1346
  }
1347
+ function mapDownloadSnippets(value, sourcePath, state, language, index) {
1348
+ if (!isObject(value)) return void 0;
1349
+ const candidates = [];
1350
+ switch (value.type) {
1351
+ case "downloadFiles":
1352
+ case "github":
1353
+ candidates.push({ value, path: sourcePath });
1354
+ break;
1355
+ case "githubV2":
1356
+ if (isObject(value.githubV2)) {
1357
+ candidates.push({ value: value.githubV2, path: [...sourcePath, "githubV2"] });
1358
+ }
1359
+ break;
1360
+ case "publishV2":
1361
+ if (isObject(value.publishV2)) {
1362
+ candidates.push({ value: value.publishV2, path: [...sourcePath, "publishV2"] });
1363
+ }
1364
+ break;
1365
+ case "publish":
1366
+ if (isObject(value.registryOverrides)) {
1367
+ const registry = defaultRegistry(language, [...sourcePath, "registryOverrides"], index);
1368
+ const override = value.registryOverrides[registry];
1369
+ if (isObject(override)) {
1370
+ candidates.push({
1371
+ value: override,
1372
+ path: [...sourcePath, "registryOverrides", registry]
1373
+ });
1374
+ }
1375
+ }
1376
+ break;
1377
+ }
1378
+ let enabled;
1379
+ for (const candidate of candidates) {
1380
+ if (typeof candidate.value.downloadSnippets !== "boolean") continue;
1381
+ consume(state, [...candidate.path, "downloadSnippets"]);
1382
+ enabled = enabled === true || candidate.value.downloadSnippets;
1383
+ }
1384
+ return enabled;
1385
+ }
1298
1386
  function isCredentialPath(path) {
1299
1387
  const fields = path.filter((part) => typeof part === "string");
1300
1388
  const field = fields[fields.length - 1];
@@ -2218,11 +2306,12 @@ function mapFernConfigToSdkConfigV1(input) {
2218
2306
  generator,
2219
2307
  language,
2220
2308
  invocation,
2221
- ...outputMapping
2309
+ ...outputMapping,
2310
+ docs: { ...invocation.docs, ...outputMapping.docs }
2222
2311
  };
2223
2312
  });
2224
2313
  const clients = partitionSharedBlock(mapped.map(({ invocation }) => invocation.client));
2225
- const docs = partitionSharedBlock(mapped.map(({ invocation }) => invocation.docs));
2314
+ const docs = partitionSharedBlock(mapped.map(({ docs: docs2 }) => docs2));
2226
2315
  const generations = partitionSharedBlock(mapped.map(({ invocation }) => invocation.generation));
2227
2316
  const api = { ...input.api ?? {} };
2228
2317
  delete api.audiences;
@@ -2411,6 +2500,14 @@ function mapInvocation(generator, language, activeLanguages, index) {
2411
2500
  ...prefix,
2412
2501
  "config"
2413
2502
  ]);
2503
+ const apiWideIdempotency = idempotencyKeyGenerationFrom(
2504
+ generator.idempotencyKeyGenerationConfig,
2505
+ [...prefix, "idempotencyKeyGenerationConfig"],
2506
+ state
2507
+ );
2508
+ if (apiWideIdempotency && client.idempotencyKeyGeneration === void 0) {
2509
+ client.idempotencyKeyGeneration = apiWideIdempotency;
2510
+ }
2414
2511
  const rawGenerator = isObject(generator.raw) ? generator.raw : void 0;
2415
2512
  const smartCasing = typeof rawGenerator?.["smart-casing"] === "boolean" ? rawGenerator["smart-casing"] : generator.smartCasing === false ? false : void 0;
2416
2513
  const smartCasingDigitWordBoundary = typeof rawGenerator?.["smart-casing-digit-word-boundary"] === "boolean" ? rawGenerator["smart-casing-digit-word-boundary"] : generator.smartCasingDigitWordBoundary === true ? true : void 0;
@@ -2444,16 +2541,19 @@ function mapInvocation(generator, language, activeLanguages, index) {
2444
2541
  ...collectUnsupported(config, [...prefix, "config"], state),
2445
2542
  ...settings ? collectUnsupported(settings, [...prefix, "settings"], state) : [],
2446
2543
  ...isObject(generator.readme) ? collectUnsupported(generator.readme, [...prefix, "readme"], state) : [],
2447
- ...unsupportedResolvedFields(generator, index)
2544
+ ...unsupportedResolvedFields(generator, index, apiWideIdempotency !== void 0)
2448
2545
  ];
2449
2546
  return { client, docs, generation, package: packageConfig, targetGeneration, unsupportedFields };
2450
2547
  }
2451
- function unsupportedResolvedFields(generator, index) {
2548
+ function unsupportedResolvedFields(generator, index, idempotencyMapped) {
2452
2549
  const values = [
2453
2550
  ["automation", isDefaultAutomation(generator.automation) ? void 0 : generator.automation],
2454
2551
  ["containerImage", generator.containerImage],
2455
2552
  ["irVersionOverride", generator.irVersionOverride],
2456
- ["idempotencyKeyGenerationConfig", generator.idempotencyKeyGenerationConfig],
2553
+ [
2554
+ "idempotencyKeyGenerationConfig",
2555
+ idempotencyMapped ? void 0 : generator.idempotencyKeyGenerationConfig
2556
+ ],
2457
2557
  ["absolutePathToLocalSnippets", generator.absolutePathToLocalSnippets],
2458
2558
  [
2459
2559
  "disableExamples",
@@ -2486,7 +2586,8 @@ function resolvedFieldGuidance(field) {
2486
2586
  }
2487
2587
  if (field === "idempotencyKeyGenerationConfig") {
2488
2588
  return {
2489
- suggestedAction: "Preserve this orchestration setting outside SDK Config; public v1 has no idempotency-generation field."
2589
+ sdkConfigPath: ["client", "idempotencyKeyGeneration"],
2590
+ suggestedAction: "Use true, false, or an object with header-name and methods, or set client.idempotencyKeyGeneration manually."
2490
2591
  };
2491
2592
  }
2492
2593
  if (field === "generateFullProject") {
@@ -2501,6 +2602,20 @@ function resolvedFieldGuidance(field) {
2501
2602
  function isDefaultAutomation(value) {
2502
2603
  return isObject(value) && value.generate === true && value.upgrade === true && value.preview === true && value.verify === true;
2503
2604
  }
2605
+ var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
2606
+ function idempotencyKeyGenerationFrom(value, path, state) {
2607
+ if (typeof value === "boolean") {
2608
+ consume(state, path);
2609
+ return { enabled: value };
2610
+ }
2611
+ if (!isObject(value)) return void 0;
2612
+ const probe = { consumedPaths: /* @__PURE__ */ new Set() };
2613
+ const headerName = takeString(value, ["headerName"], probe, path);
2614
+ const methods = takeEnumArray(value, ["methods"], HTTP_METHODS, probe, path);
2615
+ if (probe.consumedPaths.size !== Object.keys(value).length) return void 0;
2616
+ consume(state, path);
2617
+ return { enabled: true, ...optional("headerName", headerName), ...optional("methods", methods) };
2618
+ }
2504
2619
  function mapCommonConfig(language, config, state, client, generation, packageConfig, basePath) {
2505
2620
  const inlinePath = takeBoolean(config, ["inlinePathParameters"], state, basePath);
2506
2621
  const inlineFile = takeBoolean(config, ["inlineFileProperties"], state, basePath);
@@ -2525,6 +2640,23 @@ function mapCommonConfig(language, config, state, client, generation, packageCon
2525
2640
  if (useDefaults !== void 0) client.useDefaultRequestParameterValues = useDefaults;
2526
2641
  const respectOptionalBody = takeBoolean(config, ["respectOptionalRequestBody"], state, basePath);
2527
2642
  if (respectOptionalBody !== void 0) client.respectOptionalRequestBody = respectOptionalBody;
2643
+ const idempotency = locate(config, ["autoGenerateIdempotencyKey"], basePath);
2644
+ const idempotencyKeyGeneration = idempotency && idempotencyKeyGenerationFrom(idempotency.value, idempotency.path, state);
2645
+ if (idempotencyKeyGeneration) client.idempotencyKeyGeneration = idempotencyKeyGeneration;
2646
+ const userAgent = compact({
2647
+ template: takeString(config, ["userAgent"], state, basePath),
2648
+ includePlatformInfo: takeBoolean(config, ["includePlatformHeaders"], state, basePath),
2649
+ allowAppInfo: takeBoolean(config, ["allowUserAgentAppInfo"], state, basePath)
2650
+ });
2651
+ if (Object.keys(userAgent).length) client.userAgent = userAgent;
2652
+ const offsetSemantics = takeEnum(
2653
+ config,
2654
+ ["offsetSemantics"],
2655
+ ["item-index", "page-index"],
2656
+ state,
2657
+ basePath
2658
+ );
2659
+ if (offsetSemantics !== void 0) client.offsetSemantics = offsetSemantics;
2528
2660
  const maxRetries = takeNumber(config, ["maxRetries"], state, basePath);
2529
2661
  const statusCodeProfile = takeEnum(
2530
2662
  config,
@@ -2542,7 +2674,10 @@ function mapCommonConfig(language, config, state, client, generation, packageCon
2542
2674
  const pythonClient = language === "python" ? takeObject(config, ["client"], state, basePath) : void 0;
2543
2675
  const typescriptNaming = language === "typescript" || language === "mcp" ? takeObject(config, ["naming"], state, basePath) : void 0;
2544
2676
  const directClientName = takeString(config, ["clientName", "clientClassName"], state, basePath);
2545
- const nestedClientName = pythonClient ? takeString(pythonClient.value, ["className"], state, pythonClient.path) : typescriptNaming ? takeString(typescriptNaming.value, ["client"], state, typescriptNaming.path) : void 0;
2677
+ const nestedClientName = pythonClient ? takeString(pythonClient.value, ["className"], state, pythonClient.path) : typescriptNaming ? takeString(typescriptNaming.value, ["client"], state, typescriptNaming.path) : language === "ruby" ? (
2678
+ // Fern's Ruby generator renames the root client class (`Auth0::Management`) with it.
2679
+ takeString(config, ["clientModuleName"], state, basePath)
2680
+ ) : void 0;
2546
2681
  const directExportedClientName = takeString(
2547
2682
  config,
2548
2683
  ["exportedClientName", "exportedClientClassName"],
@@ -2711,7 +2846,8 @@ function mapPython(config, state, packageConfig, basePath) {
2711
2846
  });
2712
2847
  }
2713
2848
  function mapJvm(language, config, state, packageConfig, basePath) {
2714
- const namespace = takeString(config, ["packageName", "packagePrefix"], state, basePath);
2849
+ const namespaceAliases = language === "java" ? ["packagePrefix"] : ["packageName", "packagePrefix"];
2850
+ const namespace = takeString(config, namespaceAliases, state, basePath);
2715
2851
  const groupId = takeString(config, ["group", "groupId"], state, basePath);
2716
2852
  const artifactId = takeString(config, ["artifact", "artifactId"], state, basePath);
2717
2853
  if (namespace !== void 0) packageConfig.namespace = namespace;
@@ -2813,6 +2949,8 @@ function mapComposerRequirements(manifest, state, packageConfig) {
2813
2949
  function mapRuby(config, state, packageConfig, basePath) {
2814
2950
  const moduleName = takeString(config, ["moduleName"], state, basePath);
2815
2951
  if (moduleName !== void 0) packageConfig.moduleName = moduleName;
2952
+ const packageName = takeString(config, ["package-name"], state, basePath);
2953
+ if (packageName !== void 0) packageConfig.packageName = packageName;
2816
2954
  return compact({ requirePaths: takeStringArray(config, ["requirePaths"], state, basePath) });
2817
2955
  }
2818
2956
  function mapRust(config, state, packageConfig, basePath) {