@postman/sdk-config 0.0.4 → 0.1.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.
Files changed (36) hide show
  1. package/README.md +124 -101
  2. package/dist/index.cjs +2119 -282
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +3 -1
  5. package/dist/index.d.ts +3 -1
  6. package/dist/index.js +2080 -283
  7. package/dist/index.js.map +1 -1
  8. package/dist/sdk-config/index.cjs +2238 -0
  9. package/dist/sdk-config/index.cjs.map +1 -0
  10. package/dist/sdk-config/index.d.cts +3 -0
  11. package/dist/sdk-config/index.d.ts +3 -0
  12. package/dist/sdk-config/index.js +2196 -0
  13. package/dist/sdk-config/index.js.map +1 -0
  14. package/dist/sdk-config/v1/index.cjs +2238 -0
  15. package/dist/sdk-config/v1/index.cjs.map +1 -0
  16. package/dist/sdk-config/v1/index.d.cts +8644 -0
  17. package/dist/sdk-config/v1/index.d.ts +8644 -0
  18. package/dist/sdk-config/v1/index.js +2196 -0
  19. package/dist/sdk-config/v1/index.js.map +1 -0
  20. package/dist/sdk-config-ir/index.cjs +160 -25
  21. package/dist/sdk-config-ir/index.cjs.map +1 -1
  22. package/dist/sdk-config-ir/index.d.cts +2 -1
  23. package/dist/sdk-config-ir/index.d.ts +2 -1
  24. package/dist/sdk-config-ir/index.js +158 -26
  25. package/dist/sdk-config-ir/index.js.map +1 -1
  26. package/dist/sdk-config-ir/v1/index.cjs +160 -25
  27. package/dist/sdk-config-ir/v1/index.cjs.map +1 -1
  28. package/dist/sdk-config-ir/v1/index.d.cts +458 -428
  29. package/dist/sdk-config-ir/v1/index.d.ts +458 -428
  30. package/dist/sdk-config-ir/v1/index.js +158 -26
  31. package/dist/sdk-config-ir/v1/index.js.map +1 -1
  32. package/dist/typescript-DK97815_.d.cts +427 -0
  33. package/dist/typescript-DK97815_.d.ts +427 -0
  34. package/package.json +16 -3
  35. package/src/sdk-config/v1/README.md +135 -0
  36. package/src/sdk-config-ir/v1/README.md +44 -26
package/dist/index.cjs CHANGED
@@ -7,8 +7,12 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
7
 
8
8
  var semver__default = /*#__PURE__*/_interopDefault(semver);
9
9
 
10
- // src/sdk-config-ir/v1/api.ts
10
+ // src/sdk-config-domain/v1/api.ts
11
11
  var nonEmptyStringSchema = zod.z.string().min(1);
12
+ var relativePathSchema = nonEmptyStringSchema.refine(
13
+ (value) => !/^(?:[\\/]|[A-Za-z]:)/.test(value) && !value.split(/[\\/]/).some((segment) => segment === ".."),
14
+ { message: "must be a relative path without parent directory segments" }
15
+ );
12
16
  var exactSemverSchema = zod.z.string().refine(
13
17
  (value) => {
14
18
  if (value.trim() !== value || !/^\d/.test(value)) {
@@ -31,7 +35,7 @@ var jsonValueSchema = zod.z.lazy(
31
35
  );
32
36
  var jsonObjectSchema = zod.z.record(zod.z.string(), jsonValueSchema);
33
37
 
34
- // src/sdk-config-ir/v1/api.ts
38
+ // src/sdk-config-domain/v1/api.ts
35
39
  var authVariableSchema = zod.z.strictObject({
36
40
  name: nonEmptyStringSchema.optional(),
37
41
  environmentVariable: nonEmptyStringSchema.optional(),
@@ -181,8 +185,20 @@ var apiConfigSchema = zod.z.strictObject({
181
185
  environmentVariables: zod.z.array(environmentVariableSchema).default([]),
182
186
  defaultEnvironment: nonEmptyStringSchema.optional(),
183
187
  auth: authConfigSchema.optional(),
184
- headers: zod.z.array(headerSchema).optional()
188
+ headers: zod.z.array(headerSchema).optional(),
189
+ /**
190
+ * Selects the named `x-fern-audiences`.
191
+ *
192
+ * Absent means all audiences. A present empty array selects no tagged audience: untagged nodes
193
+ * remain included, while every audience-tagged node is excluded.
194
+ */
195
+ audiences: zod.z.array(nonEmptyStringSchema).optional()
185
196
  });
197
+
198
+ // src/sdk-config/v1/api.ts
199
+ var sdkConfigV1AuthSchemeSchema = authSchemeSchema;
200
+ var sdkConfigV1AuthConfigSchema = authConfigSchema;
201
+ var sdkConfigV1ApiConfigSchema = apiConfigSchema;
186
202
  var retryConfigSchema = zod.z.strictObject({
187
203
  enabled: zod.z.boolean().default(true),
188
204
  maxAttempts: zod.z.number().int().min(1).default(3),
@@ -235,178 +251,13 @@ var clientConfigSchema = zod.z.strictObject({
235
251
  pathParameterStyle: parameterStyleSchema.optional(),
236
252
  filePropertyStyle: parameterStyleSchema.optional(),
237
253
  useDefaultRequestParameterValues: zod.z.boolean().optional(),
254
+ respectOptionalRequestBody: zod.z.boolean().optional(),
238
255
  tokenRefresh: tokenRefreshConfigSchema.optional()
239
256
  });
240
- var unsupportedFieldSchema = zod.z.strictObject({
241
- source: zod.z.enum(["fern", "postman", "sdk-config-ir"]),
242
- path: zod.z.array(zod.z.union([nonEmptyStringSchema, zod.z.number().int().nonnegative()])).min(1),
243
- code: nonEmptyStringSchema.optional(),
244
- reason: nonEmptyStringSchema,
245
- severity: zod.z.enum(["error", "warning", "info"]),
246
- risk: zod.z.enum(["high", "medium", "low"]),
247
- owner: nonEmptyStringSchema,
248
- suggestedAction: nonEmptyStringSchema
249
- });
250
- var postmanLegacyInputSchema = zod.z.strictObject({
251
- kind: zod.z.literal("postman-build-parameters"),
252
- value: jsonObjectSchema
253
- });
254
- var fernLegacyInputSchema = zod.z.strictObject({
255
- kind: zod.z.literal("fern-generator-invocation"),
256
- value: jsonObjectSchema
257
- });
258
- var legacyInputSchema = zod.z.discriminatedUnion("kind", [
259
- postmanLegacyInputSchema,
260
- fernLegacyInputSchema
261
- ]);
262
- var compatibilityConfigSchema = zod.z.strictObject({
263
- outputProfile: zod.z.enum(["converged", "postman-legacy", "fern-legacy"]),
264
- legacyInput: legacyInputSchema.optional(),
265
- unsupportedFields: zod.z.array(unsupportedFieldSchema).optional()
266
- });
267
- var httpMethodSchema = zod.z.enum([
268
- "GET",
269
- "POST",
270
- "PUT",
271
- "PATCH",
272
- "DELETE",
273
- "HEAD",
274
- "OPTIONS",
275
- "TRACE",
276
- "CONNECT"
277
- ]);
278
- var readmeEndpointSchema = zod.z.strictObject({
279
- method: httpMethodSchema,
280
- path: nonEmptyStringSchema,
281
- stream: zod.z.boolean().optional()
282
- });
283
- var readmeConfigSchema = zod.z.strictObject({
284
- apiName: nonEmptyStringSchema.optional(),
285
- introduction: zod.z.string().optional(),
286
- apiReferenceLink: nonEmptyStringSchema.optional(),
287
- bannerLink: nonEmptyStringSchema.optional(),
288
- disabledSections: zod.z.array(nonEmptyStringSchema).optional(),
289
- defaultEndpoint: readmeEndpointSchema.optional(),
290
- features: zod.z.record(zod.z.string(), zod.z.array(readmeEndpointSchema)).optional()
291
- });
292
- var snippetsConfigSchema = zod.z.strictObject({
293
- enabled: zod.z.boolean(),
294
- format: zod.z.enum(["md", "json"]).optional(),
295
- outputPath: nonEmptyStringSchema.optional()
296
- });
297
- var docsConfigSchema = zod.z.strictObject({
298
- readme: readmeConfigSchema.optional(),
299
- snippets: snippetsConfigSchema.optional(),
300
- referenceBaseUrl: nonEmptyStringSchema.optional(),
301
- includeApiReference: zod.z.boolean().optional()
302
- });
303
- var cliGenerationConfigSchema = zod.z.strictObject({
304
- paginationParameters: zod.z.array(nonEmptyStringSchema).optional(),
305
- skills: zod.z.boolean().optional()
306
- });
307
- var csharpGenerationConfigSchema = zod.z.strictObject({
308
- useOptionalWrapper: zod.z.boolean().optional(),
309
- simplifyObjectDictionaries: zod.z.boolean().optional(),
310
- explicitNamespaces: zod.z.boolean().optional(),
311
- rootNamespaceForCoreClasses: zod.z.boolean().optional(),
312
- includeExceptionHandler: zod.z.boolean().optional()
313
- });
314
- var goGenerationConfigSchema = zod.z.strictObject({
315
- legacyComplexModels: zod.z.boolean().optional(),
316
- unionVersion: zod.z.enum(["v0", "v1"]).optional(),
317
- includeLegacyClientOptions: zod.z.boolean().optional()
318
- });
319
- var jvmGenerationConfigSchema = zod.z.strictObject({
320
- packageLayout: zod.z.enum(["flat", "nested"]).optional(),
321
- useLocalDateForDates: zod.z.boolean().optional(),
322
- collapseOptionalNullable: zod.z.boolean().optional(),
323
- gradleDistributionUrl: zod.z.string().min(1).optional(),
324
- gradlePluginManagement: zod.z.string().optional(),
325
- gradleCentralDependencyManagement: zod.z.boolean().optional()
326
- });
327
-
328
- // src/sdk-config-ir/v1/language/java.ts
329
- var javaGenerationConfigSchema = jvmGenerationConfigSchema.extend({
330
- includeKotlinSnippets: zod.z.boolean().optional()
331
- });
332
-
333
- // src/sdk-config-ir/v1/language/kotlin.ts
334
- var kotlinGenerationConfigSchema = jvmGenerationConfigSchema;
335
- var compilerOptionsSchema = zod.z.strictObject({
336
- target: nonEmptyStringSchema.optional(),
337
- module: nonEmptyStringSchema.optional(),
338
- lib: zod.z.array(nonEmptyStringSchema).optional()
339
- });
340
- var packageScriptSchema = zod.z.strictObject({
341
- name: nonEmptyStringSchema,
342
- command: nonEmptyStringSchema
343
- });
344
- var httpClientSchema = zod.z.strictObject({
345
- name: zod.z.enum(["axios", "fetch"])
346
- });
347
- var typescriptGenerationConfigSchema = zod.z.strictObject({
348
- typescriptVersion: nonEmptyStringSchema.optional(),
349
- zodVersion: nonEmptyStringSchema.optional(),
350
- compilerOptions: compilerOptionsSchema.optional(),
351
- httpClient: httpClientSchema.optional(),
352
- packageManager: zod.z.enum(["pnpm", "yarn"]).optional(),
353
- testFramework: zod.z.enum(["jest", "vitest"]).optional(),
354
- namingStrategy: zod.z.enum(["base", "originalPropertyNames"]).optional(),
355
- bundle: zod.z.boolean().optional(),
356
- exportClassDefault: zod.z.boolean().optional(),
357
- allowCustomFetcher: zod.z.boolean().optional(),
358
- useBrandedStringAliases: zod.z.boolean().optional(),
359
- useLegacyExports: zod.z.boolean().optional(),
360
- useBigInt: zod.z.boolean().optional(),
361
- serdeLayer: zod.z.boolean().optional(),
362
- scripts: zod.z.array(packageScriptSchema).optional()
363
- });
364
257
 
365
- // src/sdk-config-ir/v1/language/mcp.ts
366
- var mcpGenerationConfigSchema = typescriptGenerationConfigSchema;
367
- var phpGenerationConfigSchema = zod.z.strictObject({
368
- propertyAccess: zod.z.enum(["public", "private"]).optional(),
369
- generateClientInterfaces: zod.z.boolean().optional()
370
- });
371
- var pythonClientSchema = zod.z.strictObject({
372
- fileName: nonEmptyStringSchema.optional(),
373
- exportedFileName: nonEmptyStringSchema.optional()
374
- });
375
- var pydanticConfigSchema = zod.z.strictObject({
376
- versionCompatibility: zod.z.enum(["v1", "v2", "both", "v1-on-v2"]).optional(),
377
- frozen: zod.z.boolean().optional(),
378
- requireOptionalFields: zod.z.boolean().optional(),
379
- unionNaming: zod.z.enum(["v0", "v1"]).optional(),
380
- useFieldAliases: zod.z.boolean().optional()
381
- });
382
- var pythonGenerationConfigSchema = zod.z.strictObject({
383
- pythonVersion: nonEmptyStringSchema.optional(),
384
- pydanticVersion: nonEmptyStringSchema.optional(),
385
- pydantic: pydanticConfigSchema.optional(),
386
- client: pythonClientSchema.optional(),
387
- alwaysInitializeOptionals: zod.z.boolean().optional(),
388
- useTypedDictRequests: zod.z.boolean().optional()
389
- });
390
- var rubyGenerationConfigSchema = zod.z.strictObject({
391
- requirePaths: zod.z.array(nonEmptyStringSchema).optional()
392
- });
393
- var rustGenerationConfigSchema = zod.z.strictObject({
394
- /**
395
- * Rust type for datetime primitives. `offset` maps to `DateTime<FixedOffset>` and preserves the
396
- * timezone the payload carried; `utc` maps to `DateTime<Utc>` and normalizes to UTC.
397
- */
398
- dateTimeType: zod.z.enum(["offset", "utc"]).optional(),
399
- /** Uppercase common initialisms in generated names (`UserID` rather than `UserId`). */
400
- capitalizeInitialisms: zod.z.boolean().optional(),
401
- /** Cargo features, mapping a feature name to the dependencies or features it enables. */
402
- features: zod.z.record(zod.z.string(), zod.z.array(nonEmptyStringSchema)).optional(),
403
- /** Overrides which features make up Cargo's `default` feature set. */
404
- defaultFeatures: zod.z.array(nonEmptyStringSchema).optional()
405
- });
406
- var swiftGenerationConfigSchema = zod.z.strictObject({
407
- moduleName: nonEmptyStringSchema.optional()
408
- });
409
- var goModulePathSchema = nonEmptyStringSchema.regex(
258
+ // src/sdk-config/v1/client.ts
259
+ var sdkConfigV1ClientConfigSchema = clientConfigSchema;
260
+ var goModulePathSchema = relativePathSchema.regex(
410
261
  /^(?!.*(?:^|\/)\.{1,2}(?:\/|$))[A-Za-z0-9._~-]+(?:\/[A-Za-z0-9._~-]+)+$/,
411
262
  "Go module path must be a slash-delimited path using letters, numbers, dots, dashes, underscores, or tildes"
412
263
  );
@@ -484,96 +335,1965 @@ var packageConfigSchema = zod.z.strictObject({
484
335
  extraDevDependencies: zod.z.array(dependencySchema).optional(),
485
336
  extraPeerDependencies: zod.z.array(dependencySchema).optional()
486
337
  });
487
-
488
- // src/sdk-config-ir/v1/language/terraform.ts
489
- var planModifierSourceSchema = zod.z.discriminatedUnion("enabled", [
490
- zod.z.strictObject({ enabled: zod.z.literal(true), sourceDir: nonEmptyStringSchema }),
491
- zod.z.strictObject({ enabled: zod.z.literal(false) })
338
+ var httpMethodSchema = zod.z.enum([
339
+ "GET",
340
+ "POST",
341
+ "PUT",
342
+ "PATCH",
343
+ "DELETE",
344
+ "HEAD",
345
+ "OPTIONS",
346
+ "TRACE",
347
+ "CONNECT"
492
348
  ]);
493
- var planModifiersSchema = zod.z.strictObject({
494
- resources: planModifierSourceSchema,
495
- attributes: planModifierSourceSchema
496
- });
497
- var providerSchemaSchema = zod.z.strictObject({
498
- addressKey: nonEmptyStringSchema,
499
- authTokenKey: nonEmptyStringSchema
500
- });
501
- var terraformGenerationConfigSchema = zod.z.strictObject({
502
- providerName: nonEmptyStringSchema.optional(),
503
- providerVersion: nonEmptyStringSchema.optional(),
504
- providerModulePath: goModulePathSchema.optional(),
505
- mockAcceptance: zod.z.boolean().optional(),
506
- hideComputedDiff: zod.z.boolean().optional(),
507
- providerSchema: providerSchemaSchema.optional(),
508
- planModifiers: planModifiersSchema.optional()
509
- });
510
-
511
- // src/sdk-config-ir/v1/generation.ts
512
- var generationAssetSchema = zod.z.strictObject({
513
- type: zod.z.enum(["path", "url", "artifact"]),
514
- location: nonEmptyStringSchema
349
+ var readmeEndpointSchema = zod.z.strictObject({
350
+ method: httpMethodSchema,
351
+ path: nonEmptyStringSchema,
352
+ stream: zod.z.boolean().optional()
515
353
  });
516
- var hookDependencySchema = zod.z.strictObject({
517
- name: nonEmptyStringSchema,
518
- version: nonEmptyStringSchema,
519
- groupId: nonEmptyStringSchema.optional()
354
+ var readmeCustomSectionSchema = zod.z.strictObject({
355
+ title: nonEmptyStringSchema,
356
+ content: zod.z.string()
520
357
  });
521
- var hooksConfigSchema = zod.z.strictObject({
522
- enabled: zod.z.boolean(),
523
- source: generationAssetSchema.optional(),
524
- dependencies: zod.z.array(hookDependencySchema).optional()
358
+ var readmeConfigSchema = zod.z.strictObject({
359
+ apiName: nonEmptyStringSchema.optional(),
360
+ introduction: zod.z.string().optional(),
361
+ apiReferenceLink: nonEmptyStringSchema.optional(),
362
+ bannerLink: nonEmptyStringSchema.optional(),
363
+ disabledSections: zod.z.array(nonEmptyStringSchema).optional(),
364
+ customSections: zod.z.array(readmeCustomSectionSchema).optional(),
365
+ defaultEndpoint: readmeEndpointSchema.optional(),
366
+ features: zod.z.record(zod.z.string(), zod.z.array(readmeEndpointSchema)).optional()
525
367
  });
526
- var customCodeConfigSchema = zod.z.strictObject({
368
+ var snippetsConfigSchema = zod.z.strictObject({
527
369
  enabled: zod.z.boolean(),
528
- source: generationAssetSchema.optional(),
529
- conflictStrategy: zod.z.enum(["mark", "ours", "theirs"]).optional(),
530
- trackChanges: zod.z.boolean().optional(),
531
- previousBuildId: zod.z.number().int().positive().optional(),
532
- protectedFiles: zod.z.array(nonEmptyStringSchema).optional()
370
+ format: zod.z.enum(["md", "json"]).optional(),
371
+ outputPath: nonEmptyStringSchema.optional()
533
372
  });
534
- var workflowConfigSchema = zod.z.strictObject({
535
- path: nonEmptyStringSchema,
536
- outputName: nonEmptyStringSchema.optional()
373
+ var docsConfigSchema = zod.z.strictObject({
374
+ readme: readmeConfigSchema.optional(),
375
+ snippets: snippetsConfigSchema.optional(),
376
+ referenceBaseUrl: nonEmptyStringSchema.optional(),
377
+ includeApiReference: zod.z.boolean().optional()
537
378
  });
538
- var analyticsHeaderSchema = zod.z.union([
539
- zod.z.strictObject({ name: nonEmptyStringSchema, value: zod.z.string() }),
540
- zod.z.strictObject({ name: nonEmptyStringSchema, valueRef: nonEmptyStringSchema })
541
- ]);
542
- var analyticsConfigSchema = zod.z.strictObject({
543
- enabled: zod.z.boolean(),
544
- endpoint: nonEmptyStringSchema.optional(),
545
- exporter: zod.z.enum(["otlp-http", "console"]).optional(),
546
- headers: zod.z.array(analyticsHeaderSchema).optional(),
547
- batchSize: zod.z.number().int().positive().optional(),
548
- scheduledDelayMs: zod.z.number().nonnegative().optional(),
549
- exportTimeoutMs: zod.z.number().nonnegative().optional()
550
- }).superRefine(({ enabled, endpoint }, context) => {
551
- if (enabled && endpoint === void 0) {
552
- context.addIssue({
553
- code: "custom",
554
- message: "endpoint is required when analytics is enabled",
555
- path: ["endpoint"]
556
- });
379
+
380
+ // src/sdk-config/v1/docs.ts
381
+ var sdkConfigV1ReadmeEndpointSchema = readmeEndpointSchema;
382
+ var sdkConfigV1ReadmeCustomSectionSchema = readmeCustomSectionSchema;
383
+ var sdkConfigV1DocsConfigSchema = docsConfigSchema;
384
+
385
+ // src/sdk-config/v1/fern-config-mapper-types.ts
386
+ var FernConfigMappingError = class extends Error {
387
+ constructor(issues) {
388
+ super(issues.map(({ path, reason }) => `${path.join(".")}: ${reason}`).join("\n"));
389
+ this.issues = issues;
390
+ this.name = "FernConfigMappingError";
557
391
  }
558
- });
392
+ issues;
393
+ };
394
+
395
+ // src/sdk-config/v1/fern-config-mapper-helpers.ts
396
+ function fail(code, path, reason, suggestedAction, sdkConfigPath) {
397
+ throw new FernConfigMappingError([
398
+ {
399
+ code,
400
+ severity: "error",
401
+ path,
402
+ reason,
403
+ suggestedAction,
404
+ ...optional("sdkConfigPath", sdkConfigPath)
405
+ }
406
+ ]);
407
+ }
408
+ function takeTimeoutMs(value, state, basePath) {
409
+ const milliseconds = locate(value, ["defaultTimeout", "defaultTimeoutInMilliseconds"], basePath);
410
+ if (milliseconds && (milliseconds.value === "infinity" || isNonNegativeNumber(milliseconds.value))) {
411
+ consume(state, milliseconds.path);
412
+ return milliseconds.value;
413
+ }
414
+ const seconds = locate(
415
+ value,
416
+ ["defaultTimeoutInSeconds", "timeoutInSeconds", "timeout"],
417
+ basePath
418
+ );
419
+ if (seconds && (seconds.value === "infinity" || isNonNegativeNumber(seconds.value))) {
420
+ consume(state, seconds.path);
421
+ return seconds.value === "infinity" ? "infinity" : seconds.value * 1e3;
422
+ }
423
+ return void 0;
424
+ }
425
+ function locate(value, aliases, basePath) {
426
+ for (const [key, child] of Object.entries(value)) {
427
+ if (aliases.some((alias) => normalizeKey(alias) === normalizeKey(key))) {
428
+ return { value: child, path: [...basePath, key] };
429
+ }
430
+ }
431
+ return void 0;
432
+ }
433
+ function takeObject(value, aliases, _state, basePath) {
434
+ const located = locate(value, aliases, basePath);
435
+ return located && isObject(located.value) ? { value: located.value, path: located.path } : void 0;
436
+ }
437
+ function takeString(value, aliases, state, basePath) {
438
+ const located = locate(value, aliases, basePath);
439
+ if (!located || typeof located.value !== "string" || located.value.length === 0) return void 0;
440
+ consume(state, located.path);
441
+ return located.value;
442
+ }
443
+ function takeGoModulePath(value, aliases, state, basePath) {
444
+ const located = locate(value, aliases, basePath);
445
+ if (!located || !goModulePathSchema.safeParse(located.value).success) return void 0;
446
+ consume(state, located.path);
447
+ return located.value;
448
+ }
449
+ function takeBoolean(value, aliases, state, basePath) {
450
+ const located = locate(value, aliases, basePath);
451
+ if (!located || typeof located.value !== "boolean") return void 0;
452
+ consume(state, located.path);
453
+ return located.value;
454
+ }
455
+ function takeNumber(value, aliases, state, basePath) {
456
+ const located = locate(value, aliases, basePath);
457
+ if (!located || !isNonNegativeNumber(located.value) || !Number.isInteger(located.value))
458
+ return void 0;
459
+ consume(state, located.path);
460
+ return located.value;
461
+ }
462
+ function takeEnum(value, aliases, values, state, basePath) {
463
+ const located = locate(value, aliases, basePath);
464
+ if (!located || typeof located.value !== "string" || !values.includes(located.value))
465
+ return void 0;
466
+ consume(state, located.path);
467
+ return located.value;
468
+ }
469
+ function takeEnumArray(value, aliases, values, state, basePath) {
470
+ const located = locate(value, aliases, basePath);
471
+ if (!located || !Array.isArray(located.value) || located.value.some((item) => typeof item !== "string" || !values.includes(item)))
472
+ return void 0;
473
+ consume(state, located.path);
474
+ return located.value;
475
+ }
476
+ function takeStringArray(value, aliases, state, basePath) {
477
+ const located = locate(value, aliases, basePath);
478
+ const strings = located ? stringArrayValue(located.value) : void 0;
479
+ if (!located || !strings) return void 0;
480
+ consume(state, located.path);
481
+ return strings;
482
+ }
483
+ function takeStringArrayRecord(value, aliases, state, basePath) {
484
+ const located = locate(value, aliases, basePath);
485
+ if (!located || !isObject(located.value)) return void 0;
486
+ const entries = Object.entries(located.value);
487
+ if (entries.some(([, item]) => !stringArrayValue(item))) return void 0;
488
+ consume(state, located.path);
489
+ return Object.fromEntries(entries);
490
+ }
491
+ function collectUnsupported(value, basePath, state) {
492
+ return collectLeafPaths(value, basePath).filter((path) => {
493
+ const key = pathKey(path);
494
+ return ![...state.consumedPaths].some(
495
+ (consumed) => key === consumed || key.startsWith(`${consumed}.`)
496
+ );
497
+ }).map((path) => ({
498
+ code: "FERN_CONFIG_FIELD_UNSUPPORTED",
499
+ severity: "warning",
500
+ path,
501
+ reason: "Fern configuration field is not represented by SDK Config v1",
502
+ suggestedAction: "Review this value and set the closest SDK Config field manually, or preserve the setting outside SDK Config if no equivalent exists."
503
+ }));
504
+ }
505
+ function collectLeafPaths(value, path) {
506
+ if (Array.isArray(value))
507
+ return value.flatMap((item, index) => collectLeafPaths(item, [...path, index]));
508
+ if (isObject(value))
509
+ return Object.entries(value).flatMap(([key, child]) => collectLeafPaths(child, [...path, key]));
510
+ return value === void 0 ? [] : [path];
511
+ }
512
+ function consume(state, path) {
513
+ state.consumedPaths.add(pathKey(path));
514
+ }
515
+ function pathKey(path) {
516
+ return path.join(".");
517
+ }
518
+ function normalizeKey(value) {
519
+ return value.replace(/[-_]/g, "").toLowerCase();
520
+ }
521
+ function compact(value) {
522
+ return Object.fromEntries(Object.entries(value).filter(([, child]) => child !== void 0));
523
+ }
524
+ function optional(key, value) {
525
+ return value === void 0 ? {} : { [key]: value };
526
+ }
527
+ function isObject(value) {
528
+ return value !== null && typeof value === "object" && !Array.isArray(value);
529
+ }
530
+ function isNonNegativeNumber(value) {
531
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
532
+ }
533
+ function stringValue(value) {
534
+ return typeof value === "string" && value.length > 0 ? value : void 0;
535
+ }
536
+ function stringArrayValue(value) {
537
+ return Array.isArray(value) && value.every((item) => typeof item === "string" && item.length > 0) ? value : void 0;
538
+ }
539
+ function stableJson(value) {
540
+ return JSON.stringify(sortKeys(value));
541
+ }
542
+ function sortKeys(value) {
543
+ if (Array.isArray(value)) return value.map(sortKeys);
544
+ if (!isObject(value)) return value;
545
+ return Object.fromEntries(
546
+ Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => [key, sortKeys(child)])
547
+ );
548
+ }
549
+
550
+ // src/sdk-config/v1/fern-config-mapper-output.ts
551
+ function mapOutput(generator, language, index) {
552
+ const raw = isObject(generator.raw) ? generator.raw : void 0;
553
+ const rawOutput = raw && isObject(raw.output) ? raw.output : void 0;
554
+ const outputPath = ["group", "generators", index, "outputMode"];
555
+ const state = { consumedPaths: /* @__PURE__ */ new Set() };
556
+ if (rawOutput?.location === "local-file-system") {
557
+ if (isObject(generator.outputMode)) consume(state, [...outputPath, "type"]);
558
+ return finishOutputMapping(
559
+ {
560
+ output: {
561
+ delivery: "files",
562
+ ...typeof rawOutput.path === "string" && rawOutput.path ? { path: rawOutput.path } : {}
563
+ }
564
+ },
565
+ generator.outputMode,
566
+ outputPath,
567
+ state,
568
+ index
569
+ );
570
+ }
571
+ if (!isObject(generator.outputMode) || typeof generator.outputMode.type !== "string") {
572
+ fail(
573
+ "FERN_OUTPUT_REQUIRED",
574
+ ["group", "generators", index, "outputMode"],
575
+ `Cannot map output for Fern generator ${generator.name}`,
576
+ "Set generator.output to a public SDK Config output, or provide the resolved Fern outputMode.",
577
+ ["targets", index, "output"]
578
+ );
579
+ }
580
+ const output = generator.outputMode;
581
+ consume(state, [...outputPath, "type"]);
582
+ switch (output.type) {
583
+ case "downloadFiles":
584
+ return finishOutputMapping({ output: { delivery: "zip" } }, output, outputPath, state, index);
585
+ case "github":
586
+ return finishOutputMapping(
587
+ githubOutput(output, output.publishInfo, language, outputPath, state, index),
588
+ output,
589
+ outputPath,
590
+ state,
591
+ index
592
+ );
593
+ case "githubV2": {
594
+ if (!isObject(output.githubV2))
595
+ fail(
596
+ "FERN_GITHUB_OUTPUT_INVALID",
597
+ ["group", "generators", index, "outputMode", "githubV2"],
598
+ "Fern githubV2 output is missing its configuration",
599
+ 'Set target.output manually with delivery "github" and the intended repository.',
600
+ ["targets", index, "output"]
601
+ );
602
+ const githubPath = [...outputPath, "githubV2"];
603
+ return finishOutputMapping(
604
+ githubOutput(
605
+ output.githubV2,
606
+ output.githubV2.publishInfo,
607
+ language,
608
+ githubPath,
609
+ state,
610
+ index
611
+ ),
612
+ output,
613
+ outputPath,
614
+ state,
615
+ index
616
+ );
617
+ }
618
+ case "publishV2": {
619
+ const publication = mapPublication(
620
+ output.publishV2,
621
+ language,
622
+ [...outputPath, "publishV2"],
623
+ state,
624
+ index
625
+ );
626
+ return finishOutputMapping(
627
+ {
628
+ output: { delivery: "zip", publish: publication.publish },
629
+ ...optional("package", publication.package)
630
+ },
631
+ output,
632
+ outputPath,
633
+ state,
634
+ index
635
+ );
636
+ }
637
+ case "publish": {
638
+ const publication = mapLegacyPublication(
639
+ output.registryOverrides,
640
+ language,
641
+ [...outputPath, "registryOverrides"],
642
+ state,
643
+ index
644
+ );
645
+ return finishOutputMapping(
646
+ {
647
+ output: { delivery: "zip", publish: publication.publish },
648
+ ...optional("package", publication.package)
649
+ },
650
+ output,
651
+ outputPath,
652
+ state,
653
+ index
654
+ );
655
+ }
656
+ default:
657
+ fail(
658
+ "FERN_OUTPUT_UNSUPPORTED",
659
+ ["group", "generators", index, "outputMode", "type"],
660
+ `Unsupported Fern output mode "${output.type}"`,
661
+ "Choose the equivalent files, zip, or github SDK Config output manually.",
662
+ ["targets", index, "output"]
663
+ );
664
+ }
665
+ }
666
+ function githubOutput(value, publishInfo, language, sourcePath, state, index) {
667
+ const owner = stringValue(value.owner);
668
+ const repo = stringValue(value.repo);
669
+ if (!owner || !repo)
670
+ fail(
671
+ "FERN_GITHUB_REPOSITORY_REQUIRED",
672
+ sourcePath,
673
+ "Fern GitHub output requires owner and repo",
674
+ 'Set target.output.github.repository manually as "owner/repository".',
675
+ ["targets", index, "output", "github", "repository"]
676
+ );
677
+ consume(state, [...sourcePath, "owner"]);
678
+ consume(state, [...sourcePath, "repo"]);
679
+ const publication = publishInfo ? mapPublication(publishInfo, language, [...sourcePath, "publishInfo"], state, index) : void 0;
680
+ const type = stringValue(value.type);
681
+ const reviewers = mapReviewers(value.reviewers, [...sourcePath, "reviewers"], state);
682
+ if (type) consume(state, [...sourcePath, "type"]);
683
+ if (typeof value.makePr === "boolean") consume(state, [...sourcePath, "makePr"]);
684
+ if (stringValue(value.host)) consume(state, [...sourcePath, "host"]);
685
+ if (stringValue(value.branch)) consume(state, [...sourcePath, "branch"]);
686
+ return {
687
+ output: {
688
+ delivery: "github",
689
+ github: {
690
+ repository: `${owner}/${repo}`,
691
+ ...optional("host", stringValue(value.host)),
692
+ ...optional("branch", stringValue(value.branch)),
693
+ mode: value.makePr === true || type === "pullRequest" ? "pull-request" : type === "push" ? "push" : "release",
694
+ ...optional("reviewers", reviewers)
695
+ },
696
+ ...publication ? { publish: publication.publish } : {}
697
+ },
698
+ ...optional("package", publication?.package)
699
+ };
700
+ }
701
+ function mapReviewers(value, sourcePath, state) {
702
+ if (Array.isArray(value)) {
703
+ const teams2 = reviewerNames(value, "team", sourcePath, state);
704
+ const users2 = reviewerNames(value, "user", sourcePath, state);
705
+ return teams2 || users2 ? { ...optional("teams", teams2), ...optional("users", users2) } : void 0;
706
+ }
707
+ if (!isObject(value)) return void 0;
708
+ const teams = reviewerNames(value.teams, "team", [...sourcePath, "teams"], state);
709
+ const users = reviewerNames(value.users, "user", [...sourcePath, "users"], state);
710
+ return teams || users ? { ...optional("teams", teams), ...optional("users", users) } : void 0;
711
+ }
712
+ function reviewerNames(value, expectedType, sourcePath, state) {
713
+ if (!Array.isArray(value)) return void 0;
714
+ const names = value.flatMap((reviewer, index) => {
715
+ if (typeof reviewer === "string") {
716
+ consume(state, [...sourcePath, index]);
717
+ return [reviewer];
718
+ }
719
+ if (!isObject(reviewer) || reviewer.type !== expectedType || typeof reviewer.name !== "string") {
720
+ return [];
721
+ }
722
+ consume(state, [...sourcePath, index, "type"]);
723
+ consume(state, [...sourcePath, index, "name"]);
724
+ return [reviewer.name];
725
+ });
726
+ return names.length ? names : void 0;
727
+ }
728
+ function mapPublication(value, language, sourcePath, state, index) {
729
+ if (!isObject(value))
730
+ fail(
731
+ "FERN_PUBLICATION_INVALID",
732
+ sourcePath,
733
+ "Fern publication output is invalid",
734
+ "Set target.output.publish and target.package manually.",
735
+ ["targets", index, "output", "publish"]
736
+ );
737
+ const type = stringValue(value.type);
738
+ if (type) consume(state, [...sourcePath, "type"]);
739
+ const nested = type && isObject(value[type]) ? value[type] : value;
740
+ const nestedPath = nested === value ? sourcePath : [...sourcePath, type];
741
+ const registry = publicationRegistry(type, language, [...sourcePath, "type"], index);
742
+ const registryUrl = stringValue(nested.registryUrl);
743
+ if (registryUrl) consume(state, [...nestedPath, "registryUrl"]);
744
+ if (registry === "maven") {
745
+ const coordinate = stringValue(nested.coordinate);
746
+ if (coordinate) consume(state, [...nestedPath, "coordinate"]);
747
+ return {
748
+ publish: compact({ registry, url: registryUrl }),
749
+ ...coordinate ? { package: mavenPackage(coordinate, [...nestedPath, "coordinate"], index) } : {}
750
+ };
751
+ }
752
+ const packageNameField = stringValue(nested.packageName) ? "packageName" : "coordinate";
753
+ const packageName = stringValue(nested[packageNameField]);
754
+ if (packageName) consume(state, [...nestedPath, packageNameField]);
755
+ const metadata = registry === "pypi" ? mapPypiMetadata(nested.pypiMetadata, nestedPath, state) : {};
756
+ return {
757
+ publish: compact({ registry, url: registryUrl }),
758
+ ...packageName || Object.keys(metadata).length ? { package: { ...optional("packageName", packageName), ...metadata } } : {}
759
+ };
760
+ }
761
+ function mapLegacyPublication(value, language, sourcePath, state, index) {
762
+ const registry = defaultRegistry(language, sourcePath, index);
763
+ const overrides = isObject(value) ? value : {};
764
+ const override = isObject(overrides[registry]) ? overrides[registry] : {};
765
+ return mapPublication(override, language, [...sourcePath, registry], state, index);
766
+ }
767
+ function publicationRegistry(type, language, sourcePath, index) {
768
+ if (type === "postman") {
769
+ fail(
770
+ "FERN_POSTMAN_PUBLICATION_UNSUPPORTED",
771
+ sourcePath,
772
+ "Postman collection publication is not an SDK output",
773
+ "Remove this non-SDK target or convert it separately from the SDK Config document."
774
+ );
775
+ }
776
+ const normalized = type?.replace(/Override$/, "").toLowerCase();
777
+ if (normalized === "rubygems") return "rubygems";
778
+ if (normalized && ["npm", "pypi", "maven", "nuget", "crates"].includes(normalized)) {
779
+ return normalized;
780
+ }
781
+ if (normalized !== void 0) {
782
+ fail(
783
+ "FERN_PUBLICATION_UNSUPPORTED",
784
+ sourcePath,
785
+ `Unsupported Fern publication type "${type}"`,
786
+ "Set target.output.publish and target.package manually if SDK Config supports the registry.",
787
+ ["targets", index, "output", "publish"]
788
+ );
789
+ }
790
+ return defaultRegistry(language, sourcePath, index);
791
+ }
792
+ function defaultRegistry(language, sourcePath, index) {
793
+ const registries = {
794
+ typescript: "npm",
795
+ mcp: "npm",
796
+ python: "pypi",
797
+ java: "maven",
798
+ kotlin: "maven",
799
+ csharp: "nuget",
800
+ ruby: "rubygems",
801
+ rust: "crates",
802
+ go: "go",
803
+ php: "composer"
804
+ };
805
+ const registry = registries[language];
806
+ if (!registry)
807
+ fail(
808
+ "FERN_PUBLICATION_REGISTRY_REQUIRED",
809
+ sourcePath,
810
+ `No publication registry can be inferred for ${language}`,
811
+ "Set target.output.publish.registry manually.",
812
+ ["targets", index, "output", "publish", "registry"]
813
+ );
814
+ return registry;
815
+ }
816
+ function mavenPackage(coordinate, sourcePath, index) {
817
+ const parts = coordinate.split(":");
818
+ const [groupId, artifactId] = parts;
819
+ if (parts.length !== 2 || !groupId || !artifactId)
820
+ fail(
821
+ "FERN_MAVEN_COORDINATE_INVALID",
822
+ sourcePath,
823
+ `Invalid Maven coordinate ${coordinate}`,
824
+ "Set target.package.groupId and target.package.artifactId manually.",
825
+ ["targets", index, "package"]
826
+ );
827
+ return { groupId, artifactId };
828
+ }
829
+ function mapPypiMetadata(value, sourcePath, state) {
830
+ if (!isObject(value)) return {};
831
+ const metadataPath = [...sourcePath, "pypiMetadata"];
832
+ const description = stringValue(value.description);
833
+ const keywords = stringArrayValue(value.keywords);
834
+ const documentationUrl = stringValue(value.documentationLink);
835
+ const homepage = stringValue(value.homepageLink);
836
+ const authors = mapAuthors(value.authors, [...metadataPath, "authors"], state);
837
+ if (description) consume(state, [...metadataPath, "description"]);
838
+ if (keywords) consume(state, [...metadataPath, "keywords"]);
839
+ if (documentationUrl) consume(state, [...metadataPath, "documentationLink"]);
840
+ if (homepage) consume(state, [...metadataPath, "homepageLink"]);
841
+ return compact({ description, authors, keywords, documentationUrl, homepage });
842
+ }
843
+ function mapAuthors(value, sourcePath, state) {
844
+ if (!Array.isArray(value)) return void 0;
845
+ const authors = value.flatMap((author) => {
846
+ if (!isObject(author)) return [];
847
+ const name = stringValue(author.name);
848
+ const email = stringValue(author.email);
849
+ return name ? [{ name, ...optional("email", email) }] : [];
850
+ });
851
+ if (authors.length !== value.length) return void 0;
852
+ value.forEach((author, index) => {
853
+ consume(state, [...sourcePath, index, "name"]);
854
+ if (isObject(author) && stringValue(author.email)) {
855
+ consume(state, [...sourcePath, index, "email"]);
856
+ }
857
+ });
858
+ return authors;
859
+ }
860
+ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
861
+ for (const path of collectLeafPaths(outputMode, sourcePath)) {
862
+ if (path[path.length - 1] === "_visit") consume(state, path);
863
+ }
864
+ return {
865
+ ...mapping,
866
+ unsupportedFields: collectUnsupported(outputMode, sourcePath, state).map(
867
+ (diagnostic) => outputDiagnostic(diagnostic.path, index)
868
+ )
869
+ };
870
+ }
871
+ function outputDiagnostic(path, index) {
872
+ const fields = path.filter((part) => typeof part === "string");
873
+ const field = fields[fields.length - 1];
874
+ const credential = fields.some((part) => part === "credentials" || part === "signature") || ["apiKey", "keyId", "password", "secretKey", "token", "username"].includes(field ?? "");
875
+ if (credential) {
876
+ return {
877
+ code: "FERN_OUTPUT_CREDENTIAL_UNSUPPORTED",
878
+ severity: "warning",
879
+ path,
880
+ reason: "Fern output credentials and signatures are not represented by SDK Config v1",
881
+ suggestedAction: "Configure publication credentials and signing secrets outside SDK Config."
882
+ };
883
+ }
884
+ const guidance = {
885
+ directory: {
886
+ suggestedAction: "Preserve the GitHub output subdirectory outside SDK Config; public v1 has no repository subdirectory field."
887
+ },
888
+ license: {
889
+ sdkConfigPath: ["targets", index, "package", "license"],
890
+ suggestedAction: "Set target.package.license manually using portable license metadata."
891
+ },
892
+ id: {
893
+ sdkConfigPath: ["targets", index, "package", "license"],
894
+ suggestedAction: "Set target.package.license manually using portable license metadata."
895
+ },
896
+ contents: {
897
+ sdkConfigPath: ["targets", index, "package", "license"],
898
+ suggestedAction: "Set target.package.license manually without embedding license contents."
899
+ },
900
+ downloadSnippets: {
901
+ sdkConfigPath: ["docs", "snippets", "enabled"],
902
+ suggestedAction: "Set docs.snippets.enabled manually and choose a portable output path if needed."
903
+ },
904
+ version: {
905
+ sdkConfigPath: ["targets", index, "sdkVersion"],
906
+ suggestedAction: "Set target.sdkVersion manually if this output version identifies the SDK artifact."
907
+ },
908
+ description: {
909
+ sdkConfigPath: ["targets", index, "package", "description"],
910
+ suggestedAction: "Set target.package.description manually to a valid value."
911
+ },
912
+ authors: {
913
+ sdkConfigPath: ["targets", index, "package", "authors"],
914
+ suggestedAction: "Set target.package.authors manually using valid author metadata."
915
+ },
916
+ keywords: {
917
+ sdkConfigPath: ["targets", index, "package", "keywords"],
918
+ suggestedAction: "Set target.package.keywords manually using non-empty strings."
919
+ },
920
+ documentationLink: {
921
+ sdkConfigPath: ["targets", index, "package", "documentationUrl"],
922
+ suggestedAction: "Set target.package.documentationUrl manually to a valid URL."
923
+ },
924
+ homepageLink: {
925
+ sdkConfigPath: ["targets", index, "package", "homepage"],
926
+ suggestedAction: "Set target.package.homepage manually to a valid URL."
927
+ }
928
+ };
929
+ const fieldGuidance = field ? guidance[field] : void 0;
930
+ const resolvedGuidance = fields.includes("license") ? guidance.license : fieldGuidance;
931
+ return {
932
+ code: "FERN_OUTPUT_FIELD_UNSUPPORTED",
933
+ severity: "warning",
934
+ path,
935
+ reason: "Fern output field is not represented by SDK Config v1",
936
+ ...optional("sdkConfigPath", resolvedGuidance?.sdkConfigPath),
937
+ suggestedAction: resolvedGuidance?.suggestedAction ?? "Review this output setting and preserve it outside SDK Config when no equivalent exists."
938
+ };
939
+ }
940
+ var customerGenerationAssetSchema = zod.z.discriminatedUnion("type", [
941
+ zod.z.strictObject({ type: zod.z.literal("path"), location: relativePathSchema }),
942
+ zod.z.strictObject({ type: zod.z.literal("url"), location: nonEmptyStringSchema })
943
+ ]);
944
+ var hookDependencySchema = zod.z.strictObject({
945
+ name: nonEmptyStringSchema,
946
+ version: nonEmptyStringSchema,
947
+ groupId: nonEmptyStringSchema.optional()
948
+ });
949
+ var hooksConfigSchema = zod.z.strictObject({
950
+ enabled: zod.z.boolean(),
951
+ source: customerGenerationAssetSchema.optional(),
952
+ dependencies: zod.z.array(hookDependencySchema).optional()
953
+ });
954
+ var customCodeConfigSchema = zod.z.strictObject({
955
+ enabled: zod.z.boolean(),
956
+ source: customerGenerationAssetSchema.optional(),
957
+ conflictStrategy: zod.z.enum(["mark", "ours", "theirs"]).optional(),
958
+ trackChanges: zod.z.boolean().optional(),
959
+ protectedFiles: zod.z.array(nonEmptyStringSchema).optional()
960
+ });
961
+ var workflowConfigSchema = zod.z.strictObject({
962
+ path: relativePathSchema,
963
+ outputName: nonEmptyStringSchema.optional()
964
+ });
965
+ var analyticsHeaderSchema = zod.z.union([
966
+ zod.z.strictObject({ name: nonEmptyStringSchema, value: zod.z.string() }),
967
+ zod.z.strictObject({
968
+ name: nonEmptyStringSchema,
969
+ valueRef: nonEmptyStringSchema
970
+ })
971
+ ]);
972
+ var analyticsConfigSchema = zod.z.strictObject({
973
+ enabled: zod.z.boolean(),
974
+ endpoint: nonEmptyStringSchema.optional(),
975
+ exporter: zod.z.enum(["otlp-http", "console"]).optional(),
976
+ headers: zod.z.array(analyticsHeaderSchema).optional(),
977
+ batchSize: zod.z.number().int().positive().optional(),
978
+ scheduledDelayMs: zod.z.number().nonnegative().optional(),
979
+ exportTimeoutMs: zod.z.number().nonnegative().optional()
980
+ }).superRefine(({ enabled, endpoint }, context) => {
981
+ if (enabled && endpoint === void 0) {
982
+ context.addIssue({
983
+ code: "custom",
984
+ message: "endpoint is required when analytics is enabled",
985
+ path: ["endpoint"]
986
+ });
987
+ }
988
+ });
559
989
  var wireTestsSchema = zod.z.strictObject({
560
990
  enabled: zod.z.boolean(),
561
991
  exclusions: zod.z.array(nonEmptyStringSchema).optional(),
562
992
  fallbackToGeneratedErrorExamples: zod.z.boolean().optional(),
563
993
  fixtureSource: zod.z.enum(["synthetic", "recorded", "auto"]).optional()
564
994
  });
565
- var unitTestsSchema = zod.z.strictObject({
995
+ var unitTestsSchema = zod.z.strictObject({
996
+ enabled: zod.z.boolean(),
997
+ mode: zod.z.enum(["core-runtime", "schema-driven", "both"]).optional(),
998
+ exclusions: zod.z.array(nonEmptyStringSchema).optional()
999
+ });
1000
+ var streamsSchema = zod.z.strictObject({
1001
+ enabled: zod.z.boolean(),
1002
+ responseType: zod.z.enum(["wrapper", "native", "web"]).optional(),
1003
+ fileResponseType: zod.z.enum(["stream", "binary-response"]).optional(),
1004
+ defaultChunkSizeBytes: zod.z.number().int().positive().optional()
1005
+ });
1006
+ var namingConfigSchema = zod.z.strictObject({
1007
+ clientName: nonEmptyStringSchema.optional(),
1008
+ exportedClientName: nonEmptyStringSchema.optional(),
1009
+ environmentTypeName: nonEmptyStringSchema.optional(),
1010
+ apiErrorName: nonEmptyStringSchema.optional(),
1011
+ baseErrorName: nonEmptyStringSchema.optional(),
1012
+ pagerName: nonEmptyStringSchema.optional()
1013
+ });
1014
+ var layoutConfigSchema = zod.z.strictObject({
1015
+ outputDirectory: zod.z.enum(["project-root", "source-root"]).optional(),
1016
+ packagePath: nonEmptyStringSchema.optional()
1017
+ });
1018
+ var serializationConfigSchema = zod.z.strictObject({
1019
+ enumRepresentation: zod.z.enum(["enum", "union", "literal", "forward-compatible-enum", "language-default"]).optional(),
1020
+ additionalProperties: zod.z.enum(["allow", "forbid", "ignore", "language-default"]).optional(),
1021
+ inlineTypes: zod.z.boolean().optional(),
1022
+ omitUndefined: zod.z.boolean().optional()
1023
+ });
1024
+ var sdkConfigV1GenerationConfigSchema = zod.z.strictObject({
1025
+ includeWatermark: zod.z.boolean().default(false),
1026
+ ai: zod.z.boolean().default(false),
1027
+ includeOptionalSnippetParameters: zod.z.boolean().optional(),
1028
+ buildAllModels: zod.z.boolean().default(false),
1029
+ inferServiceNames: zod.z.boolean().default(false),
1030
+ includeDeprecatedOperations: zod.z.boolean().default(true),
1031
+ multipleResponses: zod.z.boolean().default(false),
1032
+ devContainer: zod.z.boolean().default(false),
1033
+ allowMockClient: zod.z.boolean().default(false),
1034
+ ignoreFiles: zod.z.array(nonEmptyStringSchema).optional(),
1035
+ reservedKeywords: zod.z.array(nonEmptyStringSchema).optional(),
1036
+ hooks: hooksConfigSchema.optional(),
1037
+ customCode: customCodeConfigSchema.optional(),
1038
+ workflows: zod.z.array(workflowConfigSchema).optional(),
1039
+ customQueryPaths: zod.z.array(relativePathSchema).optional(),
1040
+ analytics: analyticsConfigSchema.optional(),
1041
+ wireTests: wireTestsSchema.optional(),
1042
+ unitTests: unitTestsSchema.optional(),
1043
+ webSockets: zod.z.boolean().optional(),
1044
+ streams: streamsSchema.optional(),
1045
+ naming: namingConfigSchema.optional(),
1046
+ layout: layoutConfigSchema.optional(),
1047
+ serialization: serializationConfigSchema.optional()
1048
+ });
1049
+ var sdkConfigV1PublishRegistrySchema = zod.z.enum([
1050
+ "npm",
1051
+ "pypi",
1052
+ "maven",
1053
+ "nuget",
1054
+ "rubygems",
1055
+ "crates",
1056
+ "go",
1057
+ "composer"
1058
+ ]);
1059
+ var commonPublishShape = {
1060
+ url: nonEmptyStringSchema.optional(),
1061
+ releaseBranch: nonEmptyStringSchema.optional(),
1062
+ tolerateRepublish: zod.z.boolean().optional()
1063
+ };
1064
+ var sdkConfigV1PublishConfigSchema = zod.z.discriminatedUnion("registry", [
1065
+ zod.z.strictObject({ registry: zod.z.literal("npm"), ...commonPublishShape }),
1066
+ zod.z.strictObject({ registry: zod.z.literal("pypi"), ...commonPublishShape }),
1067
+ zod.z.strictObject({ registry: zod.z.literal("maven"), ...commonPublishShape }),
1068
+ zod.z.strictObject({ registry: zod.z.literal("nuget"), ...commonPublishShape }),
1069
+ zod.z.strictObject({ registry: zod.z.literal("rubygems"), ...commonPublishShape }),
1070
+ zod.z.strictObject({ registry: zod.z.literal("crates"), ...commonPublishShape }),
1071
+ zod.z.strictObject({ registry: zod.z.literal("go"), ...commonPublishShape }),
1072
+ zod.z.strictObject({ registry: zod.z.literal("composer"), ...commonPublishShape })
1073
+ ]);
1074
+ var reviewersSchema = zod.z.strictObject({
1075
+ teams: zod.z.array(nonEmptyStringSchema).optional(),
1076
+ users: zod.z.array(nonEmptyStringSchema).optional()
1077
+ });
1078
+ var githubOutputSchema = zod.z.strictObject({
1079
+ repository: nonEmptyStringSchema,
1080
+ host: nonEmptyStringSchema.optional(),
1081
+ branch: nonEmptyStringSchema.optional(),
1082
+ mode: zod.z.enum(["release", "pull-request", "push"]).optional(),
1083
+ reviewers: reviewersSchema.optional(),
1084
+ privateRepository: zod.z.boolean().optional()
1085
+ });
1086
+ var filesOutputSchema = zod.z.strictObject({
1087
+ delivery: zod.z.literal("files"),
1088
+ path: nonEmptyStringSchema.optional(),
1089
+ publish: sdkConfigV1PublishConfigSchema.optional()
1090
+ });
1091
+ var zipOutputSchema = zod.z.strictObject({
1092
+ delivery: zod.z.literal("zip"),
1093
+ fileName: nonEmptyStringSchema.optional(),
1094
+ publish: sdkConfigV1PublishConfigSchema.optional()
1095
+ });
1096
+ var githubDeliverySchema = zod.z.strictObject({
1097
+ delivery: zod.z.literal("github"),
1098
+ github: githubOutputSchema,
1099
+ publish: sdkConfigV1PublishConfigSchema.optional()
1100
+ });
1101
+ var sdkConfigV1OutputConfigSchema = zod.z.discriminatedUnion(
1102
+ "delivery",
1103
+ [filesOutputSchema, zipOutputSchema, githubDeliverySchema],
1104
+ { error: 'output.delivery must be one of "files", "zip", or "github"' }
1105
+ );
1106
+
1107
+ // src/sdk-config/v1/package.ts
1108
+ var sdkConfigV1DependencySchema = dependencySchema;
1109
+ var sdkConfigV1PackageConfigSchema = packageConfigSchema;
1110
+ var cliGenerationConfigSchema = zod.z.strictObject({
1111
+ paginationParameters: zod.z.array(nonEmptyStringSchema).optional(),
1112
+ skills: zod.z.boolean().optional()
1113
+ });
1114
+ var csharpGenerationConfigSchema = zod.z.strictObject({
1115
+ useOptionalWrapper: zod.z.boolean().optional(),
1116
+ simplifyObjectDictionaries: zod.z.boolean().optional(),
1117
+ explicitNamespaces: zod.z.boolean().optional(),
1118
+ rootNamespaceForCoreClasses: zod.z.boolean().optional(),
1119
+ includeExceptionHandler: zod.z.boolean().optional(),
1120
+ experimentalExplicitNullableOptional: zod.z.boolean().optional()
1121
+ });
1122
+ var goGenerationConfigSchema = zod.z.strictObject({
1123
+ legacyComplexModels: zod.z.boolean().optional(),
1124
+ /** Uppercase common initialisms in generated names (`UserID` rather than `UserId`). */
1125
+ smartCasing: zod.z.boolean().optional(),
1126
+ /** Overrides the fern root-client constructor independently from the client type name. */
1127
+ clientConstructorName: nonEmptyStringSchema.optional(),
1128
+ unionVersion: zod.z.enum(["v0", "v1"]).optional(),
1129
+ includeLegacyClientOptions: zod.z.boolean().optional()
1130
+ });
1131
+ var jvmGenerationConfigSchema = zod.z.strictObject({
1132
+ packageLayout: zod.z.enum(["flat", "nested"]).optional(),
1133
+ useLocalDateForDates: zod.z.boolean().optional(),
1134
+ collapseOptionalNullable: zod.z.boolean().optional(),
1135
+ gradleDistributionUrl: zod.z.string().min(1).optional(),
1136
+ gradlePluginManagement: zod.z.string().optional(),
1137
+ gradleCentralDependencyManagement: zod.z.boolean().optional(),
1138
+ /** Selects co-located async methods or a separate async client surface. */
1139
+ asyncStyle: zod.z.enum(["dedicated-client", "twin-methods"]).optional()
1140
+ });
1141
+
1142
+ // src/sdk-config-domain/v1/language/java.ts
1143
+ var javaGenerationConfigSchema = jvmGenerationConfigSchema.extend({
1144
+ includeKotlinSnippets: zod.z.boolean().optional()
1145
+ });
1146
+
1147
+ // src/sdk-config-domain/v1/language/kotlin.ts
1148
+ var kotlinGenerationConfigSchema = jvmGenerationConfigSchema;
1149
+ var compilerOptionsSchema = zod.z.strictObject({
1150
+ target: nonEmptyStringSchema.optional(),
1151
+ module: nonEmptyStringSchema.optional(),
1152
+ lib: zod.z.array(nonEmptyStringSchema).optional()
1153
+ });
1154
+ var packageScriptSchema = zod.z.strictObject({
1155
+ name: nonEmptyStringSchema,
1156
+ command: nonEmptyStringSchema
1157
+ });
1158
+ var httpClientSchema = zod.z.strictObject({
1159
+ name: zod.z.enum(["axios", "fetch"])
1160
+ });
1161
+ var typescriptGenerationConfigSchema = zod.z.strictObject({
1162
+ typescriptVersion: nonEmptyStringSchema.optional(),
1163
+ zodVersion: nonEmptyStringSchema.optional(),
1164
+ compilerOptions: compilerOptionsSchema.optional(),
1165
+ httpClient: httpClientSchema.optional(),
1166
+ packageManager: zod.z.enum(["pnpm", "yarn"]).optional(),
1167
+ testFramework: zod.z.enum(["jest", "vitest"]).optional(),
1168
+ namingStrategy: zod.z.enum(["base", "originalPropertyNames"]).optional(),
1169
+ bundle: zod.z.boolean().optional(),
1170
+ exportClassDefault: zod.z.boolean().optional(),
1171
+ allowCustomFetcher: zod.z.boolean().optional(),
1172
+ useBrandedStringAliases: zod.z.boolean().optional(),
1173
+ useLegacyExports: zod.z.boolean().optional(),
1174
+ useBigInt: zod.z.boolean().optional(),
1175
+ serdeLayer: zod.z.boolean().optional(),
1176
+ scripts: zod.z.array(packageScriptSchema).optional()
1177
+ });
1178
+
1179
+ // src/sdk-config-domain/v1/language/mcp.ts
1180
+ var mcpAvailabilityStatuses = [
1181
+ "IN_DEVELOPMENT",
1182
+ "PRE_RELEASE",
1183
+ "GENERAL_AVAILABILITY",
1184
+ "DEPRECATED",
1185
+ "ALPHA",
1186
+ "BETA",
1187
+ "PREVIEW",
1188
+ "LEGACY"
1189
+ ];
1190
+ var mcpToolFilterSchema = zod.z.strictObject({
1191
+ include: zod.z.array(nonEmptyStringSchema).optional(),
1192
+ exclude: zod.z.array(nonEmptyStringSchema).optional()
1193
+ });
1194
+ var mcpToolsetNameSchema = nonEmptyStringSchema.refine(
1195
+ (name) => name !== "default" && /^[a-z0-9-]+$/.test(name),
1196
+ 'toolset names must match [a-z0-9-]+ and cannot be "default"'
1197
+ );
1198
+ var mcpGenerationConfigSchema = typescriptGenerationConfigSchema.extend({
1199
+ serverName: nonEmptyStringSchema.optional(),
1200
+ serverDescription: nonEmptyStringSchema.optional(),
1201
+ excludeAvailability: zod.z.array(zod.z.enum(mcpAvailabilityStatuses)).optional(),
1202
+ tools: mcpToolFilterSchema.optional(),
1203
+ toolsets: zod.z.record(mcpToolsetNameSchema, mcpToolFilterSchema).optional()
1204
+ });
1205
+ var phpGenerationConfigSchema = zod.z.strictObject({
1206
+ propertyAccess: zod.z.enum(["public", "private"]).optional(),
1207
+ generateClientInterfaces: zod.z.boolean().optional()
1208
+ });
1209
+ var pythonClientSchema = zod.z.strictObject({
1210
+ fileName: nonEmptyStringSchema.optional(),
1211
+ exportedFileName: nonEmptyStringSchema.optional()
1212
+ });
1213
+ var pydanticConfigSchema = zod.z.strictObject({
1214
+ versionCompatibility: zod.z.enum(["v1", "v2", "both", "v1-on-v2"]).optional(),
1215
+ frozen: zod.z.boolean().optional(),
1216
+ requireOptionalFields: zod.z.boolean().optional(),
1217
+ unionNaming: zod.z.enum(["v0", "v1"]).optional(),
1218
+ useFieldAliases: zod.z.boolean().optional()
1219
+ });
1220
+ var pythonGenerationConfigSchema = zod.z.strictObject({
1221
+ pythonVersion: nonEmptyStringSchema.optional(),
1222
+ pydanticVersion: nonEmptyStringSchema.optional(),
1223
+ pydantic: pydanticConfigSchema.optional(),
1224
+ client: pythonClientSchema.optional(),
1225
+ alwaysInitializeOptionals: zod.z.boolean().optional(),
1226
+ useTypedDictRequests: zod.z.boolean().optional()
1227
+ });
1228
+ var rubyGenerationConfigSchema = zod.z.strictObject({
1229
+ requirePaths: zod.z.array(nonEmptyStringSchema).optional()
1230
+ });
1231
+ var rustGenerationConfigSchema = zod.z.strictObject({
1232
+ /**
1233
+ * Rust type for datetime primitives. `offset` maps to `DateTime<FixedOffset>` and preserves the
1234
+ * timezone the payload carried; `utc` maps to `DateTime<Utc>` and normalizes to UTC.
1235
+ */
1236
+ dateTimeType: zod.z.enum(["offset", "utc"]).optional(),
1237
+ /** Uppercase common initialisms in generated names (`UserID` rather than `UserId`). */
1238
+ capitalizeInitialisms: zod.z.boolean().optional(),
1239
+ /** Cargo features, mapping a feature name to the dependencies or features it enables. */
1240
+ features: zod.z.record(zod.z.string(), zod.z.array(nonEmptyStringSchema)).optional(),
1241
+ /** Overrides which features make up Cargo's `default` feature set. */
1242
+ defaultFeatures: zod.z.array(nonEmptyStringSchema).optional()
1243
+ });
1244
+ var swiftGenerationConfigSchema = zod.z.strictObject({
1245
+ moduleName: nonEmptyStringSchema.optional(),
1246
+ nullableAsOptional: zod.z.boolean().optional()
1247
+ });
1248
+ var planModifierSourceSchema = zod.z.discriminatedUnion("enabled", [
1249
+ zod.z.strictObject({ enabled: zod.z.literal(true), sourceDir: nonEmptyStringSchema }),
1250
+ zod.z.strictObject({ enabled: zod.z.literal(false) })
1251
+ ]);
1252
+ var planModifiersSchema = zod.z.strictObject({
1253
+ resources: planModifierSourceSchema,
1254
+ attributes: planModifierSourceSchema
1255
+ });
1256
+ var providerSchemaSchema = zod.z.strictObject({
1257
+ addressKey: nonEmptyStringSchema,
1258
+ authTokenKey: nonEmptyStringSchema
1259
+ });
1260
+ var terraformGenerationConfigSchema = zod.z.strictObject({
1261
+ providerName: nonEmptyStringSchema.optional(),
1262
+ providerVersion: nonEmptyStringSchema.optional(),
1263
+ providerModulePath: goModulePathSchema.optional(),
1264
+ mockAcceptance: zod.z.boolean().optional(),
1265
+ hideComputedDiff: zod.z.boolean().optional(),
1266
+ providerSchema: providerSchemaSchema.optional(),
1267
+ planModifiers: planModifiersSchema.optional()
1268
+ });
1269
+
1270
+ // src/sdk-config/v1/target.ts
1271
+ var targetOverrideShape = {
1272
+ generatorVersion: exactSemverSchema.optional(),
1273
+ sdkName: nonEmptyStringSchema.optional(),
1274
+ sdkVersion: nonEmptyStringSchema.optional(),
1275
+ package: sdkConfigV1PackageConfigSchema.optional(),
1276
+ output: sdkConfigV1OutputConfigSchema.optional()
1277
+ };
1278
+ var sdkConfigV1TargetSchema = zod.z.discriminatedUnion("language", [
1279
+ zod.z.strictObject({
1280
+ language: zod.z.literal("typescript"),
1281
+ generation: typescriptGenerationConfigSchema.optional(),
1282
+ ...targetOverrideShape
1283
+ }),
1284
+ zod.z.strictObject({
1285
+ language: zod.z.literal("python"),
1286
+ generation: pythonGenerationConfigSchema.optional(),
1287
+ ...targetOverrideShape
1288
+ }),
1289
+ zod.z.strictObject({
1290
+ language: zod.z.literal("java"),
1291
+ generation: javaGenerationConfigSchema.optional(),
1292
+ ...targetOverrideShape
1293
+ }),
1294
+ zod.z.strictObject({
1295
+ language: zod.z.literal("kotlin"),
1296
+ generation: kotlinGenerationConfigSchema.optional(),
1297
+ ...targetOverrideShape
1298
+ }),
1299
+ zod.z.strictObject({
1300
+ language: zod.z.literal("go"),
1301
+ generation: goGenerationConfigSchema.optional(),
1302
+ ...targetOverrideShape
1303
+ }),
1304
+ zod.z.strictObject({
1305
+ language: zod.z.literal("csharp"),
1306
+ generation: csharpGenerationConfigSchema.optional(),
1307
+ ...targetOverrideShape
1308
+ }),
1309
+ zod.z.strictObject({
1310
+ language: zod.z.literal("php"),
1311
+ generation: phpGenerationConfigSchema.optional(),
1312
+ ...targetOverrideShape
1313
+ }),
1314
+ zod.z.strictObject({
1315
+ language: zod.z.literal("ruby"),
1316
+ generation: rubyGenerationConfigSchema.optional(),
1317
+ ...targetOverrideShape
1318
+ }),
1319
+ zod.z.strictObject({
1320
+ language: zod.z.literal("rust"),
1321
+ generation: rustGenerationConfigSchema.optional(),
1322
+ ...targetOverrideShape
1323
+ }),
1324
+ zod.z.strictObject({
1325
+ language: zod.z.literal("swift"),
1326
+ generation: swiftGenerationConfigSchema.optional(),
1327
+ ...targetOverrideShape
1328
+ }),
1329
+ zod.z.strictObject({
1330
+ language: zod.z.literal("cli"),
1331
+ generation: cliGenerationConfigSchema.optional(),
1332
+ ...targetOverrideShape
1333
+ }),
1334
+ zod.z.strictObject({
1335
+ language: zod.z.literal("mcp"),
1336
+ generation: mcpGenerationConfigSchema.optional(),
1337
+ ...targetOverrideShape
1338
+ }),
1339
+ zod.z.strictObject({
1340
+ language: zod.z.literal("terraform"),
1341
+ generation: terraformGenerationConfigSchema.optional(),
1342
+ ...targetOverrideShape
1343
+ })
1344
+ ]);
1345
+
1346
+ // src/sdk-config/v1/sdk-config-v1.ts
1347
+ var SDK_CONFIG_V1_SCHEMA_VERSION = "sdk-config/v1";
1348
+ var publishRegistryLanguages = {
1349
+ npm: ["typescript", "mcp"],
1350
+ pypi: ["python"],
1351
+ maven: ["java", "kotlin"],
1352
+ nuget: ["csharp"],
1353
+ rubygems: ["ruby"],
1354
+ crates: ["rust"],
1355
+ go: ["go"],
1356
+ composer: ["php"]
1357
+ };
1358
+ var packageNameRegistries = /* @__PURE__ */ new Set([
1359
+ "npm",
1360
+ "pypi",
1361
+ "nuget",
1362
+ "rubygems",
1363
+ "crates",
1364
+ "composer"
1365
+ ]);
1366
+ function validatePublishingIdentity(packageConfig, registry, targetIndex, context) {
1367
+ const pathPrefix = ["targets", targetIndex, "package"];
1368
+ if (packageNameRegistries.has(registry) && !packageConfig.packageName) {
1369
+ context.addIssue({
1370
+ code: "custom",
1371
+ message: `packageName is required when publishing to "${registry}"`,
1372
+ path: [...pathPrefix, "packageName"]
1373
+ });
1374
+ }
1375
+ if (registry === "composer" && packageConfig.packageName) {
1376
+ const result = composerPackageNameSchema.safeParse(packageConfig.packageName);
1377
+ if (!result.success) {
1378
+ context.addIssue({
1379
+ code: "custom",
1380
+ message: result.error.issues[0]?.message ?? "Invalid Composer package name",
1381
+ path: [...pathPrefix, "packageName"]
1382
+ });
1383
+ }
1384
+ }
1385
+ if (registry === "go" && !packageConfig.modulePath) {
1386
+ context.addIssue({
1387
+ code: "custom",
1388
+ message: "modulePath is required when publishing a Go module",
1389
+ path: [...pathPrefix, "modulePath"]
1390
+ });
1391
+ }
1392
+ if (registry === "maven") {
1393
+ ["groupId", "artifactId"].forEach((field) => {
1394
+ if (!packageConfig[field]) {
1395
+ context.addIssue({
1396
+ code: "custom",
1397
+ message: `${field} is required when publishing to Maven`,
1398
+ path: [...pathPrefix, field]
1399
+ });
1400
+ }
1401
+ });
1402
+ }
1403
+ }
1404
+ function validateTargetPublishing(target, targetIndex, globalPackage, globalOutput, context) {
1405
+ const output = target.output ?? globalOutput;
1406
+ if (!output.publish) {
1407
+ return;
1408
+ }
1409
+ const registry = output.publish.registry;
1410
+ if (!publishRegistryLanguages[registry].some((language) => language === target.language)) {
1411
+ context.addIssue({
1412
+ code: "custom",
1413
+ message: `registry "${registry}" is not supported for target language "${target.language}"`,
1414
+ path: ["targets", targetIndex, target.output ? "output" : "language"]
1415
+ });
1416
+ return;
1417
+ }
1418
+ validatePublishingIdentity(
1419
+ { ...globalPackage, ...target.package },
1420
+ registry,
1421
+ targetIndex,
1422
+ context
1423
+ );
1424
+ }
1425
+ var sdkConfigV1Schema = zod.z.strictObject({
1426
+ schemaVersion: zod.z.literal(SDK_CONFIG_V1_SCHEMA_VERSION),
1427
+ sdkName: nonEmptyStringSchema,
1428
+ sdkVersion: nonEmptyStringSchema.default("1.0.0"),
1429
+ apiVersion: nonEmptyStringSchema.optional(),
1430
+ api: sdkConfigV1ApiConfigSchema,
1431
+ client: sdkConfigV1ClientConfigSchema,
1432
+ package: sdkConfigV1PackageConfigSchema,
1433
+ output: sdkConfigV1OutputConfigSchema,
1434
+ docs: sdkConfigV1DocsConfigSchema,
1435
+ generation: sdkConfigV1GenerationConfigSchema,
1436
+ targets: zod.z.array(sdkConfigV1TargetSchema).min(1)
1437
+ }).superRefine(({ output, package: globalPackage, targets }, context) => {
1438
+ const configuredLanguages = /* @__PURE__ */ new Set();
1439
+ targets.forEach((target, targetIndex) => {
1440
+ if (configuredLanguages.has(target.language)) {
1441
+ context.addIssue({
1442
+ code: "custom",
1443
+ message: `target language "${target.language}" must be unique`,
1444
+ path: ["targets", targetIndex, "language"]
1445
+ });
1446
+ }
1447
+ configuredLanguages.add(target.language);
1448
+ validateTargetPublishing(target, targetIndex, globalPackage, output, context);
1449
+ });
1450
+ });
1451
+ function parseSdkConfigV1(value) {
1452
+ return sdkConfigV1Schema.parse(value);
1453
+ }
1454
+
1455
+ // src/sdk-config/v1/fern-config-mapper.ts
1456
+ var generatorLanguages = {
1457
+ "fernapi/fern-typescript": "typescript",
1458
+ "fernapi/fern-typescript-sdk": "typescript",
1459
+ "fernapi/fern-typescript-node-sdk": "typescript",
1460
+ "fernapi/fern-typescript-browser-sdk": "typescript",
1461
+ "fernapi/fern-python-sdk": "python",
1462
+ "fernapi/fern-java-sdk": "java",
1463
+ "fernapi/fern-kotlin-sdk": "kotlin",
1464
+ "fernapi/fern-go-sdk": "go",
1465
+ "fernapi/fern-csharp-sdk": "csharp",
1466
+ "fernapi/fern-php-sdk": "php",
1467
+ "fernapi/fern-ruby-sdk": "ruby",
1468
+ "fernapi/fern-ruby-sdk-v2": "ruby",
1469
+ "fernapi/fern-rust-sdk": "rust",
1470
+ "fernapi/fern-swift-sdk": "swift",
1471
+ "fernapi/fern-cli": "cli",
1472
+ "fernapi/fern-cli-generator": "cli",
1473
+ "fernapi/fern-mcp-server": "mcp"
1474
+ };
1475
+ function mapFernConfigToSdkConfigV1(input) {
1476
+ if (input.group.generators.length === 0) {
1477
+ fail(
1478
+ "FERN_GENERATORS_REQUIRED",
1479
+ ["group", "generators"],
1480
+ "Fern generator group must contain at least one generator",
1481
+ "Select a Fern generator group containing at least one SDK generator."
1482
+ );
1483
+ }
1484
+ const mapped = input.group.generators.map((generator, index) => {
1485
+ const language = resolveLanguage(generator, index);
1486
+ const invocation = mapInvocation(generator, language, index);
1487
+ const outputMapping = generator.output ? { output: generator.output, unsupportedFields: [] } : mapOutput(generator, language, index);
1488
+ return {
1489
+ generator,
1490
+ language,
1491
+ invocation,
1492
+ ...outputMapping
1493
+ };
1494
+ });
1495
+ requireUniqueLanguages(mapped.map(({ language }) => language));
1496
+ const client = requireSharedBlock(
1497
+ mapped.map(({ invocation }) => invocation.client),
1498
+ "client",
1499
+ (value) => sdkConfigV1ClientConfigSchema.parse(value)
1500
+ );
1501
+ const docs = requireSharedBlock(
1502
+ mapped.map(({ invocation }) => invocation.docs),
1503
+ "docs",
1504
+ (value) => sdkConfigV1DocsConfigSchema.parse(value)
1505
+ );
1506
+ const generation = requireSharedBlock(
1507
+ mapped.map(({ invocation }) => invocation.generation),
1508
+ "generation",
1509
+ (value) => sdkConfigV1GenerationConfigSchema.parse(value)
1510
+ );
1511
+ const api = { ...input.api ?? {} };
1512
+ delete api.audiences;
1513
+ if (input.group.audiences.type === "select") {
1514
+ api.audiences = [...input.group.audiences.audiences];
1515
+ }
1516
+ const targets = mapped.map(
1517
+ ({ generator, invocation, language, output, package: outputPackage }, index) => {
1518
+ const target = {
1519
+ language,
1520
+ output,
1521
+ ...optional("sdkName", generator.sdkName),
1522
+ ...optional("sdkVersion", generator.sdkVersion)
1523
+ };
1524
+ if (Object.keys(invocation.package).length > 0 || outputPackage || generator.package) {
1525
+ target.package = { ...invocation.package, ...outputPackage, ...generator.package };
1526
+ }
1527
+ if (Object.keys(invocation.targetGeneration).length > 0) {
1528
+ target.generation = invocation.targetGeneration;
1529
+ }
1530
+ if (generator.version) {
1531
+ if (exactSemverSchema.safeParse(generator.version).success) {
1532
+ target.generatorVersion = generator.version;
1533
+ } else {
1534
+ invocation.unsupportedFields.push({
1535
+ code: "FERN_GENERATOR_VERSION_NOT_EXACT",
1536
+ severity: "warning",
1537
+ path: ["group", "generators", index, "version"],
1538
+ reason: "SDK Config requires an exact generator semantic version",
1539
+ sdkConfigPath: ["targets", index, "generatorVersion"],
1540
+ suggestedAction: "Resolve the Fern generator tag to an exact semantic version and set target.generatorVersion manually, or leave it omitted."
1541
+ });
1542
+ }
1543
+ }
1544
+ return target;
1545
+ }
1546
+ );
1547
+ const parsed = sdkConfigV1Schema.safeParse({
1548
+ schemaVersion: "sdk-config/v1",
1549
+ sdkName: input.apiName,
1550
+ ...optional("sdkVersion", input.sdkVersion),
1551
+ ...optional("apiVersion", input.apiVersion),
1552
+ api,
1553
+ client,
1554
+ package: {},
1555
+ output: mapped[0].output,
1556
+ docs,
1557
+ generation,
1558
+ targets
1559
+ });
1560
+ if (!parsed.success) {
1561
+ throw new FernConfigMappingError(
1562
+ parsed.error.issues.map((issue) => {
1563
+ const path = issue.path.map(
1564
+ (part) => typeof part === "symbol" ? part.description ?? part.toString() : part
1565
+ );
1566
+ return {
1567
+ code: "SDK_CONFIG_VALIDATION_FAILED",
1568
+ severity: "error",
1569
+ path: ["mappedSdkConfig", ...path],
1570
+ reason: issue.message,
1571
+ sdkConfigPath: path,
1572
+ suggestedAction: `Set ${path.join(".")} manually to a valid SDK Config v1 value.`
1573
+ };
1574
+ })
1575
+ );
1576
+ }
1577
+ return {
1578
+ sdkConfig: parsed.data,
1579
+ unsupportedFields: mapped.flatMap(({ invocation, unsupportedFields }) => [
1580
+ ...invocation.unsupportedFields,
1581
+ ...unsupportedFields
1582
+ ])
1583
+ };
1584
+ }
1585
+ function resolveLanguage(generator, index) {
1586
+ const language = generator.sdkLanguage ?? generatorLanguages[generator.name];
1587
+ if (!language || !isFernLanguage(language)) {
1588
+ fail(
1589
+ "FERN_SDK_LANGUAGE_REQUIRED",
1590
+ ["group", "generators", index, "name"],
1591
+ `Cannot determine an SDK language for Fern generator ${generator.name}`,
1592
+ "Set sdkLanguage explicitly if this custom generator produces one of the SDK Config v1 target languages.",
1593
+ ["targets", index, "language"]
1594
+ );
1595
+ }
1596
+ return language;
1597
+ }
1598
+ function isFernLanguage(value) {
1599
+ return [
1600
+ "typescript",
1601
+ "python",
1602
+ "java",
1603
+ "kotlin",
1604
+ "go",
1605
+ "csharp",
1606
+ "php",
1607
+ "ruby",
1608
+ "rust",
1609
+ "swift",
1610
+ "cli",
1611
+ "mcp",
1612
+ "terraform"
1613
+ ].includes(value);
1614
+ }
1615
+ function requireUniqueLanguages(languages) {
1616
+ const seen = /* @__PURE__ */ new Set();
1617
+ for (const language of languages) {
1618
+ if (seen.has(language)) {
1619
+ fail(
1620
+ "FERN_DUPLICATE_TARGET_LANGUAGE",
1621
+ ["group", "generators"],
1622
+ `SDK Config v1 cannot represent multiple Fern generators for language "${language}"`,
1623
+ "Create a separate SDK Config document for each generator that targets the same language.",
1624
+ ["targets"]
1625
+ );
1626
+ }
1627
+ seen.add(language);
1628
+ }
1629
+ }
1630
+ function requireSharedBlock(values, name, normalize) {
1631
+ const first = normalize(values[0]);
1632
+ const serialized = stableJson(first);
1633
+ if (values.some((value) => stableJson(normalize(value)) !== serialized)) {
1634
+ fail(
1635
+ "FERN_TARGET_SPECIFIC_SHARED_CONFIG",
1636
+ ["group", "generators"],
1637
+ `SDK Config v1 cannot represent target-specific Fern ${name} configuration`,
1638
+ `Choose one shared ${name} configuration manually or create separate SDK Config documents for the differing targets.`,
1639
+ [name]
1640
+ );
1641
+ }
1642
+ return first;
1643
+ }
1644
+ function mapInvocation(generator, language, index) {
1645
+ const prefix = ["group", "generators", index];
1646
+ const state = { consumedPaths: /* @__PURE__ */ new Set() };
1647
+ const config = isObject(generator.config) ? generator.config : {};
1648
+ const client = {};
1649
+ const generation = {};
1650
+ const packageConfig = {};
1651
+ mapCommonConfig(config, state, client, generation, packageConfig, [...prefix, "config"]);
1652
+ const targetGeneration = mapLanguageConfig(language, config, state, packageConfig, [
1653
+ ...prefix,
1654
+ "config"
1655
+ ]);
1656
+ mapPublishMetadata(generator.publishMetadata, packageConfig);
1657
+ if (language === "go" && generator.smartCasing !== void 0) {
1658
+ targetGeneration.smartCasing = generator.smartCasing;
1659
+ }
1660
+ if (generator.keywords?.length) {
1661
+ generation.reservedKeywords = [...generator.keywords];
1662
+ }
1663
+ const settings = isObject(generator.settings) ? generator.settings : void 0;
1664
+ if (settings) {
1665
+ const inlinePathParameters = takeBoolean(settings, ["inlinePathParameters"], state, [
1666
+ ...prefix,
1667
+ "settings"
1668
+ ]);
1669
+ if (inlinePathParameters !== void 0 && client.pathParameterStyle === void 0) {
1670
+ client.pathParameterStyle = inlinePathParameters ? "inline" : "wrapped";
1671
+ }
1672
+ }
1673
+ const docs = mapReadme(generator.readme, state, [...prefix, "readme"]);
1674
+ const unsupportedFields = [
1675
+ ...collectUnsupported(config, [...prefix, "config"], state),
1676
+ ...settings ? collectUnsupported(settings, [...prefix, "settings"], state) : [],
1677
+ ...isObject(generator.readme) ? collectUnsupported(generator.readme, [...prefix, "readme"], state) : [],
1678
+ ...unsupportedResolvedFields(generator, index, language)
1679
+ ];
1680
+ return { client, docs, generation, package: packageConfig, targetGeneration, unsupportedFields };
1681
+ }
1682
+ function unsupportedResolvedFields(generator, index, language) {
1683
+ const values = [
1684
+ ["automation", isDefaultAutomation(generator.automation) ? void 0 : generator.automation],
1685
+ ["containerImage", generator.containerImage],
1686
+ ["irVersionOverride", generator.irVersionOverride],
1687
+ ["idempotencyKeyGenerationConfig", generator.idempotencyKeyGenerationConfig],
1688
+ ["absolutePathToLocalSnippets", generator.absolutePathToLocalSnippets],
1689
+ [
1690
+ "smartCasingDigitWordBoundary",
1691
+ generator.smartCasingDigitWordBoundary === false ? void 0 : generator.smartCasingDigitWordBoundary
1692
+ ],
1693
+ [
1694
+ "disableExamples",
1695
+ generator.disableExamples === false ? void 0 : generator.disableExamples
1696
+ ],
1697
+ ["apiOverride", generator.apiOverride],
1698
+ ...language === "go" || generator.smartCasing === true ? [] : [["smartCasing", generator.smartCasing]]
1699
+ ];
1700
+ return values.flatMap(([field, value]) => {
1701
+ if (value === void 0) return [];
1702
+ const guidance = resolvedFieldGuidance(field);
1703
+ return [
1704
+ {
1705
+ code: "FERN_RESOLVED_FIELD_UNSUPPORTED",
1706
+ severity: "warning",
1707
+ path: ["group", "generators", index, field],
1708
+ reason: "Resolved Fern field is not represented by SDK Config v1",
1709
+ ...optional("sdkConfigPath", guidance.sdkConfigPath),
1710
+ suggestedAction: guidance.suggestedAction
1711
+ }
1712
+ ];
1713
+ });
1714
+ }
1715
+ function resolvedFieldGuidance(field) {
1716
+ if (field === "absolutePathToLocalSnippets") {
1717
+ return {
1718
+ sdkConfigPath: ["docs", "snippets", "outputPath"],
1719
+ suggestedAction: "Choose a portable relative snippet path and set docs.snippets.outputPath manually."
1720
+ };
1721
+ }
1722
+ if (field === "idempotencyKeyGenerationConfig") {
1723
+ return {
1724
+ suggestedAction: "Preserve this orchestration setting outside SDK Config; public v1 has no idempotency-generation field."
1725
+ };
1726
+ }
1727
+ return {
1728
+ suggestedAction: "Review this Fern setting and preserve it outside SDK Config, or set an equivalent SDK Config field manually if one is introduced."
1729
+ };
1730
+ }
1731
+ function isDefaultAutomation(value) {
1732
+ return isObject(value) && value.generate === true && value.upgrade === true && value.preview === true && value.verify === true;
1733
+ }
1734
+ function mapCommonConfig(config, state, client, generation, packageConfig, basePath) {
1735
+ const inlinePath = takeBoolean(config, ["inlinePathParameters"], state, basePath);
1736
+ const inlineFile = takeBoolean(config, ["inlineFileProperties"], state, basePath);
1737
+ const inlineRequest = takeBoolean(config, ["inlineRequestParams"], state, basePath);
1738
+ if (inlinePath !== void 0) client.pathParameterStyle = inlinePath ? "inline" : "wrapped";
1739
+ if (inlineFile !== void 0) client.filePropertyStyle = inlineFile ? "inline" : "wrapped";
1740
+ if (inlineRequest !== void 0)
1741
+ client.requestParameterStyle = inlineRequest ? "inline" : "wrapped";
1742
+ const timeoutMs = takeTimeoutMs(config, state, basePath);
1743
+ if (timeoutMs !== void 0) client.timeoutMs = timeoutMs;
1744
+ const skipValidation = takeBoolean(
1745
+ config,
1746
+ ["skipResponseValidation", "skipValidation"],
1747
+ state,
1748
+ basePath
1749
+ );
1750
+ if (skipValidation !== void 0) client.responseValidation = !skipValidation;
1751
+ const useDefaults = takeBoolean(config, ["useDefaultRequestParameterValues"], state, basePath);
1752
+ if (useDefaults !== void 0) client.useDefaultRequestParameterValues = useDefaults;
1753
+ const respectOptionalBody = takeBoolean(config, ["respectOptionalRequestBody"], state, basePath);
1754
+ if (respectOptionalBody !== void 0) client.respectOptionalRequestBody = respectOptionalBody;
1755
+ const maxRetries = takeNumber(config, ["maxRetries"], state, basePath);
1756
+ const statusCodeProfile = takeEnum(
1757
+ config,
1758
+ ["retryStatusCodes"],
1759
+ ["legacy", "recommended"],
1760
+ state,
1761
+ basePath
1762
+ );
1763
+ if (maxRetries !== void 0 || statusCodeProfile !== void 0) {
1764
+ client.retry = {
1765
+ ...maxRetries === void 0 ? {} : { maxAttempts: maxRetries + 1 },
1766
+ ...optional("statusCodeProfile", statusCodeProfile)
1767
+ };
1768
+ }
1769
+ const naming = compact({
1770
+ pagerName: takeString(
1771
+ config,
1772
+ ["customPagerName", "customPagerClassname", "customPagerClassName"],
1773
+ state,
1774
+ basePath
1775
+ ),
1776
+ clientName: takeString(config, ["clientName", "clientClassName"], state, basePath),
1777
+ exportedClientName: takeString(
1778
+ config,
1779
+ ["exportedClientName", "exportedClientClassName"],
1780
+ state,
1781
+ basePath
1782
+ ),
1783
+ environmentTypeName: takeString(
1784
+ config,
1785
+ ["environmentClassName", "environmentEnumName"],
1786
+ state,
1787
+ basePath
1788
+ ),
1789
+ apiErrorName: takeString(config, ["baseApiExceptionClassName"], state, basePath),
1790
+ baseErrorName: takeString(config, ["baseExceptionClassName"], state, basePath)
1791
+ });
1792
+ if (Object.keys(naming).length) generation.naming = naming;
1793
+ const wireTests = takeBoolean(config, ["enableWireTests", "generateWireTests"], state, basePath);
1794
+ if (wireTests !== void 0) generation.wireTests = { enabled: wireTests };
1795
+ const webSockets = takeBoolean(
1796
+ config,
1797
+ ["generateWebSocketClients", "shouldGenerateWebsocketClients", "enableWebsockets"],
1798
+ state,
1799
+ basePath
1800
+ );
1801
+ if (webSockets !== void 0) generation.webSockets = webSockets;
1802
+ const inlineTypes = takeBoolean(config, ["enableInlineTypes"], state, basePath);
1803
+ const omitUndefined = takeBoolean(config, ["omitUndefined"], state, basePath);
1804
+ const forwardEnums = takeBoolean(config, ["enableForwardCompatibleEnums"], state, basePath);
1805
+ const serialization = compact({
1806
+ inlineTypes,
1807
+ omitUndefined,
1808
+ enumRepresentation: forwardEnums === void 0 ? void 0 : forwardEnums ? "forward-compatible-enum" : "language-default"
1809
+ });
1810
+ if (Object.keys(serialization).length) generation.serialization = serialization;
1811
+ const namespace = takeString(config, ["namespace", "packagePrefix"], state, basePath);
1812
+ if (namespace !== void 0) packageConfig.namespace = namespace;
1813
+ const packagePath = takeString(config, ["packagePath"], state, basePath);
1814
+ if (packagePath !== void 0) generation.layout = { packagePath };
1815
+ mapDependencies(config, state, packageConfig, basePath);
1816
+ }
1817
+ function mapLanguageConfig(language, config, state, packageConfig, basePath) {
1818
+ switch (language) {
1819
+ case "typescript":
1820
+ return mapTypescript(config, state, packageConfig, basePath);
1821
+ case "mcp":
1822
+ return {
1823
+ ...mapTypescript(config, state, packageConfig, basePath),
1824
+ ...mapMcp(config, state, basePath)
1825
+ };
1826
+ case "python":
1827
+ return mapPython(config, state, packageConfig, basePath);
1828
+ case "java":
1829
+ case "kotlin":
1830
+ return mapJvm(language, config, state, packageConfig, basePath);
1831
+ case "go":
1832
+ return mapGo(config, state, packageConfig, basePath);
1833
+ case "csharp":
1834
+ return mapCsharp(config, state, packageConfig, basePath);
1835
+ case "php":
1836
+ return mapPhp(config, state, packageConfig, basePath);
1837
+ case "ruby":
1838
+ return mapRuby(config, state, packageConfig, basePath);
1839
+ case "rust":
1840
+ return mapRust(config, state, packageConfig, basePath);
1841
+ case "swift":
1842
+ return compact({ moduleName: takeString(config, ["moduleName"], state, basePath) });
1843
+ case "cli":
1844
+ return mapCli(config, state, packageConfig, basePath);
1845
+ case "terraform":
1846
+ return mapTerraform(config, state, packageConfig, basePath);
1847
+ }
1848
+ }
1849
+ function mapTypescript(config, state, packageConfig, basePath) {
1850
+ const packageJson = takeObject(config, ["packageJson"], state, basePath);
1851
+ const packageName = packageJson ? takeString(packageJson.value, ["name"], state, packageJson.path) : void 0;
1852
+ if (packageName !== void 0) packageConfig.packageName = packageName;
1853
+ const serdeLayer = takeBoolean(config, ["serdeLayer"], state, basePath);
1854
+ const noSerdeLayer = takeBoolean(config, ["noSerdeLayer"], state, basePath);
1855
+ return compact({
1856
+ typescriptVersion: takeString(config, ["typescriptVersion"], state, basePath),
1857
+ zodVersion: takeString(config, ["zodVersion"], state, basePath),
1858
+ packageManager: takeEnum(config, ["packageManager"], ["pnpm", "yarn"], state, basePath),
1859
+ testFramework: takeEnum(config, ["testFramework"], ["jest", "vitest"], state, basePath),
1860
+ bundle: takeBoolean(config, ["bundle"], state, basePath),
1861
+ exportClassDefault: takeBoolean(config, ["exportClassDefault"], state, basePath),
1862
+ allowCustomFetcher: takeBoolean(config, ["allowCustomFetcher"], state, basePath),
1863
+ useBrandedStringAliases: takeBoolean(config, ["useBrandedStringAliases"], state, basePath),
1864
+ useLegacyExports: takeBoolean(config, ["useLegacyExports"], state, basePath),
1865
+ useBigInt: takeBoolean(config, ["useBigInt"], state, basePath),
1866
+ serdeLayer: serdeLayer ?? (noSerdeLayer === void 0 ? void 0 : !noSerdeLayer)
1867
+ });
1868
+ }
1869
+ function mapPython(config, state, packageConfig, basePath) {
1870
+ const moduleName = takeString(config, ["packageName"], state, basePath);
1871
+ const packageName = takeString(config, ["pypiPackageName"], state, basePath);
1872
+ if (moduleName !== void 0) packageConfig.moduleName = moduleName;
1873
+ if (packageName !== void 0) packageConfig.packageName = packageName;
1874
+ return compact({
1875
+ pythonVersion: takeString(config, ["pythonVersion", "pyprojectPythonVersion"], state, basePath),
1876
+ pydanticVersion: takeString(config, ["pydanticVersion"], state, basePath),
1877
+ alwaysInitializeOptionals: takeBoolean(config, ["alwaysInitializeOptionals"], state, basePath),
1878
+ useTypedDictRequests: takeBoolean(config, ["useTypedDictRequests"], state, basePath)
1879
+ });
1880
+ }
1881
+ function mapJvm(language, config, state, packageConfig, basePath) {
1882
+ const namespace = takeString(config, ["packageName", "packagePrefix"], state, basePath);
1883
+ const groupId = takeString(config, ["group", "groupId"], state, basePath);
1884
+ const artifactId = takeString(config, ["artifact", "artifactId"], state, basePath);
1885
+ if (namespace !== void 0) packageConfig.namespace = namespace;
1886
+ if (groupId !== void 0) packageConfig.groupId = groupId;
1887
+ if (artifactId !== void 0) packageConfig.artifactId = artifactId;
1888
+ return compact({
1889
+ packageLayout: takeEnum(config, ["packageLayout"], ["flat", "nested"], state, basePath),
1890
+ useLocalDateForDates: takeBoolean(config, ["useLocalDateForDates"], state, basePath),
1891
+ collapseOptionalNullable: takeBoolean(config, ["collapseOptionalNullable"], state, basePath),
1892
+ gradleDistributionUrl: takeString(config, ["gradleDistributionUrl"], state, basePath),
1893
+ gradlePluginManagement: takeString(config, ["gradlePluginManagement"], state, basePath),
1894
+ gradleCentralDependencyManagement: takeBoolean(
1895
+ config,
1896
+ ["gradleCentralDependencyManagement"],
1897
+ state,
1898
+ basePath
1899
+ ),
1900
+ asyncStyle: takeEnum(
1901
+ config,
1902
+ ["asyncStyle"],
1903
+ ["dedicated-client", "twin-methods"],
1904
+ state,
1905
+ basePath
1906
+ ),
1907
+ ...language === "java" ? {
1908
+ includeKotlinSnippets: takeBoolean(config, ["includeKotlinSnippets"], state, basePath)
1909
+ } : {}
1910
+ });
1911
+ }
1912
+ function mapGo(config, state, packageConfig, basePath) {
1913
+ const module = takeObject(config, ["module"], state, basePath);
1914
+ const modulePath = module ? takeGoModulePath(module.value, ["path"], state, module.path) : void 0;
1915
+ const packageName = takeString(config, ["packageName"], state, basePath);
1916
+ if (modulePath !== void 0) packageConfig.modulePath = modulePath;
1917
+ if (packageName !== void 0) packageConfig.packageName = packageName;
1918
+ return compact({
1919
+ legacyComplexModels: takeBoolean(config, ["legacyComplexModels"], state, basePath),
1920
+ unionVersion: takeEnum(config, ["union"], ["v0", "v1"], state, basePath),
1921
+ includeLegacyClientOptions: takeBoolean(
1922
+ config,
1923
+ ["includeLegacyClientOptions"],
1924
+ state,
1925
+ basePath
1926
+ ),
1927
+ clientConstructorName: takeString(config, ["clientConstructorName"], state, basePath)
1928
+ });
1929
+ }
1930
+ function mapCsharp(config, state, packageConfig, basePath) {
1931
+ const packageName = takeString(config, ["packageId"], state, basePath);
1932
+ if (packageName !== void 0) packageConfig.packageName = packageName;
1933
+ return compact({
1934
+ useOptionalWrapper: takeBoolean(config, ["useOptionalWrapper"], state, basePath),
1935
+ simplifyObjectDictionaries: takeBoolean(
1936
+ config,
1937
+ ["simplifyObjectDictionaries"],
1938
+ state,
1939
+ basePath
1940
+ ),
1941
+ explicitNamespaces: takeBoolean(config, ["explicitNamespaces"], state, basePath),
1942
+ rootNamespaceForCoreClasses: takeBoolean(
1943
+ config,
1944
+ ["rootNamespaceForCoreClasses"],
1945
+ state,
1946
+ basePath
1947
+ ),
1948
+ includeExceptionHandler: takeBoolean(config, ["includeExceptionHandler"], state, basePath),
1949
+ experimentalExplicitNullableOptional: takeBoolean(
1950
+ config,
1951
+ ["experimentalExplicitNullableOptional"],
1952
+ state,
1953
+ basePath
1954
+ )
1955
+ });
1956
+ }
1957
+ function mapPhp(config, state, packageConfig, basePath) {
1958
+ const packageName = takeString(config, ["packageName"], state, basePath);
1959
+ if (packageName !== void 0) packageConfig.packageName = packageName;
1960
+ return compact({
1961
+ propertyAccess: takeEnum(config, ["propertyAccess"], ["public", "private"], state, basePath),
1962
+ generateClientInterfaces: takeBoolean(config, ["generateClientInterfaces"], state, basePath)
1963
+ });
1964
+ }
1965
+ function mapRuby(config, state, packageConfig, basePath) {
1966
+ const moduleName = takeString(config, ["moduleName"], state, basePath);
1967
+ if (moduleName !== void 0) packageConfig.moduleName = moduleName;
1968
+ return compact({ requirePaths: takeStringArray(config, ["requirePaths"], state, basePath) });
1969
+ }
1970
+ function mapRust(config, state, packageConfig, basePath) {
1971
+ const packageName = takeString(config, ["crateName"], state, basePath);
1972
+ const repository = takeString(config, ["packageRepository"], state, basePath);
1973
+ const description = takeString(config, ["packageDescription"], state, basePath);
1974
+ const documentationUrl = takeString(config, ["packageDocumentation"], state, basePath);
1975
+ Object.assign(packageConfig, compact({ packageName, repository, description, documentationUrl }));
1976
+ return compact({
1977
+ dateTimeType: takeEnum(config, ["dateTimeType"], ["offset", "utc"], state, basePath),
1978
+ capitalizeInitialisms: takeBoolean(config, ["capitalizeInitialisms"], state, basePath),
1979
+ features: takeStringArrayRecord(config, ["features"], state, basePath),
1980
+ defaultFeatures: takeStringArray(config, ["defaultFeatures"], state, basePath)
1981
+ });
1982
+ }
1983
+ function mapCli(config, state, packageConfig, basePath) {
1984
+ const identity = takeObject(config, ["packageIdentity"], state, basePath);
1985
+ if (identity) {
1986
+ Object.assign(
1987
+ packageConfig,
1988
+ compact({
1989
+ packageName: takeString(identity.value, ["name"], state, identity.path),
1990
+ repository: takeString(identity.value, ["repository"], state, identity.path),
1991
+ description: takeString(identity.value, ["description"], state, identity.path)
1992
+ })
1993
+ );
1994
+ }
1995
+ return compact({
1996
+ paginationParameters: takeStringArray(config, ["paginationParameters"], state, basePath),
1997
+ skills: takeBoolean(config, ["skills"], state, basePath)
1998
+ });
1999
+ }
2000
+ function mapTerraform(config, state, packageConfig, basePath) {
2001
+ const providerModulePath = takeString(
2002
+ config,
2003
+ ["providerModulePath", "providerGoModuleName"],
2004
+ state,
2005
+ basePath
2006
+ );
2007
+ if (providerModulePath !== void 0) packageConfig.modulePath = providerModulePath;
2008
+ return compact({
2009
+ providerName: takeString(config, ["providerName"], state, basePath),
2010
+ providerVersion: takeString(config, ["providerVersion"], state, basePath),
2011
+ providerModulePath,
2012
+ mockAcceptance: takeBoolean(config, ["mockAcceptance"], state, basePath),
2013
+ hideComputedDiff: takeBoolean(config, ["hideComputedDiff"], state, basePath)
2014
+ });
2015
+ }
2016
+ function mapMcp(config, state, basePath) {
2017
+ return compact({
2018
+ serverName: takeString(config, ["serverName"], state, basePath),
2019
+ serverDescription: takeString(config, ["serverDescription"], state, basePath),
2020
+ excludeAvailability: takeEnumArray(
2021
+ config,
2022
+ ["excludeAvailability"],
2023
+ [
2024
+ "IN_DEVELOPMENT",
2025
+ "PRE_RELEASE",
2026
+ "GENERAL_AVAILABILITY",
2027
+ "DEPRECATED",
2028
+ "ALPHA",
2029
+ "BETA",
2030
+ "PREVIEW",
2031
+ "LEGACY"
2032
+ ],
2033
+ state,
2034
+ basePath
2035
+ ),
2036
+ tools: takeToolFilter(config, ["tools"], state, basePath),
2037
+ toolsets: takeToolsets(config, ["toolsets"], state, basePath)
2038
+ });
2039
+ }
2040
+ function mapReadme(value, state, basePath) {
2041
+ if (!isObject(value)) return {};
2042
+ const readme = compact({
2043
+ apiName: takeString(value, ["apiName"], state, basePath),
2044
+ introduction: takeString(value, ["introduction"], state, basePath),
2045
+ apiReferenceLink: takeString(value, ["apiReferenceLink"], state, basePath),
2046
+ bannerLink: takeString(value, ["bannerLink"], state, basePath),
2047
+ disabledSections: takeStringArray(value, ["disabledSections"], state, basePath),
2048
+ customSections: takeCustomSections(value, state, basePath),
2049
+ defaultEndpoint: takeReadmeEndpoint(value, ["defaultEndpoint"], state, basePath),
2050
+ features: takeReadmeFeatures(value, state, basePath)
2051
+ });
2052
+ return Object.keys(readme).length ? { readme } : {};
2053
+ }
2054
+ function mapPublishMetadata(value, packageConfig) {
2055
+ if (!isObject(value)) return;
2056
+ const publisherName = stringValue(value.publisherName);
2057
+ const publisherEmail = stringValue(value.publisherEmail);
2058
+ Object.assign(
2059
+ packageConfig,
2060
+ compact({
2061
+ description: stringValue(value.packageDescription),
2062
+ documentationUrl: stringValue(value.referenceUrl),
2063
+ authors: publisherName ? [{ name: publisherName, ...optional("email", publisherEmail) }] : void 0
2064
+ })
2065
+ );
2066
+ }
2067
+ function mapDependencies(config, state, packageConfig, basePath) {
2068
+ for (const field of [
2069
+ "extraDependencies",
2070
+ "extraDevDependencies",
2071
+ "extraPeerDependencies"
2072
+ ]) {
2073
+ const located = takeObject(config, [field], state, basePath);
2074
+ if (!located) continue;
2075
+ const dependencies = Object.entries(located.value).flatMap(
2076
+ ([name, dependency]) => mapDependency(name, dependency, state, [...located.path, name])
2077
+ );
2078
+ if (dependencies.length) packageConfig[field] = dependencies;
2079
+ }
2080
+ }
2081
+ function mapDependency(name, value, state, path) {
2082
+ if (typeof value === "string" && value) {
2083
+ consume(state, path);
2084
+ return [{ name, version: value }];
2085
+ }
2086
+ if (!isObject(value)) return [];
2087
+ const version = takeString(value, ["version"], state, path);
2088
+ const gitUrl = takeString(value, ["git"], state, path);
2089
+ const localPath = takeString(value, ["path"], state, path);
2090
+ const source = gitUrl ? {
2091
+ type: "git",
2092
+ url: gitUrl,
2093
+ ...optional("ref", takeString(value, ["ref"], state, path))
2094
+ } : localPath ? { type: "path", path: localPath } : void 0;
2095
+ if (!version && !source) return [];
2096
+ return [
2097
+ {
2098
+ name,
2099
+ ...optional("version", version),
2100
+ ...optional("source", source),
2101
+ ...optional("packageName", takeString(value, ["package"], state, path)),
2102
+ ...optional("features", takeStringArray(value, ["features"], state, path)),
2103
+ ...optional("extras", takeStringArray(value, ["extras"], state, path)),
2104
+ ...optional("optional", takeBoolean(value, ["optional"], state, path)),
2105
+ ...optional("defaultFeatures", takeBoolean(value, ["defaultFeatures"], state, path)),
2106
+ ...optional("environmentMarker", takeString(value, ["python"], state, path))
2107
+ }
2108
+ ];
2109
+ }
2110
+ function takeCustomSections(value, state, basePath) {
2111
+ const located = locate(value, ["customSections"], basePath);
2112
+ if (!located || !Array.isArray(located.value)) return void 0;
2113
+ const sections = located.value.flatMap(
2114
+ (section) => isObject(section) && section.language === void 0 && typeof section.title === "string" && typeof section.content === "string" ? [{ title: section.title, content: section.content }] : []
2115
+ );
2116
+ if (sections.length !== located.value.length) return void 0;
2117
+ consume(state, located.path);
2118
+ return sections;
2119
+ }
2120
+ function takeReadmeEndpoint(value, aliases, state, basePath) {
2121
+ const located = locate(value, aliases, basePath);
2122
+ if (!located) return void 0;
2123
+ const endpoint = parseReadmeEndpoint(located.value);
2124
+ if (endpoint) consume(state, located.path);
2125
+ return endpoint;
2126
+ }
2127
+ function takeReadmeFeatures(value, state, basePath) {
2128
+ const located = locate(value, ["features"], basePath);
2129
+ if (!located || !isObject(located.value)) return void 0;
2130
+ const features = {};
2131
+ for (const [name, endpoints] of Object.entries(located.value)) {
2132
+ if (!Array.isArray(endpoints)) return void 0;
2133
+ const parsed = endpoints.map(parseReadmeEndpoint);
2134
+ if (parsed.some((endpoint) => !endpoint)) return void 0;
2135
+ features[name] = parsed;
2136
+ }
2137
+ consume(state, located.path);
2138
+ return features;
2139
+ }
2140
+ function parseReadmeEndpoint(value) {
2141
+ if (typeof value === "string") {
2142
+ const match = /^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS|TRACE|CONNECT)\s+(\/\S*)$/.exec(
2143
+ value.trim()
2144
+ );
2145
+ return match ? { method: match[1], path: match[2] } : void 0;
2146
+ }
2147
+ if (!isObject(value) || typeof value.method !== "string" || typeof value.path !== "string") {
2148
+ return void 0;
2149
+ }
2150
+ const method = value.method.toUpperCase();
2151
+ if (!["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "TRACE", "CONNECT"].includes(
2152
+ method
2153
+ )) {
2154
+ return void 0;
2155
+ }
2156
+ return {
2157
+ method,
2158
+ path: value.path,
2159
+ ...optional("stream", typeof value.stream === "boolean" ? value.stream : void 0)
2160
+ };
2161
+ }
2162
+ function takeToolFilter(value, aliases, state, basePath) {
2163
+ const located = takeObject(value, aliases, state, basePath);
2164
+ if (!located) return void 0;
2165
+ const filter = compact({
2166
+ include: stringArrayValue(located.value.include),
2167
+ exclude: stringArrayValue(located.value.exclude)
2168
+ });
2169
+ if (Object.keys(filter).length === 0 && Object.keys(located.value).length > 0) return void 0;
2170
+ consume(state, located.path);
2171
+ return filter;
2172
+ }
2173
+ function takeToolsets(value, aliases, state, basePath) {
2174
+ const located = takeObject(value, aliases, state, basePath);
2175
+ if (!located) return void 0;
2176
+ const entries = Object.entries(located.value).map(([name, filter]) => {
2177
+ if (name === "default" || !/^[a-z0-9-]+$/.test(name)) {
2178
+ fail(
2179
+ "FERN_MCP_TOOLSET_NAME_INVALID",
2180
+ [...located.path, name],
2181
+ `MCP toolset name "${name}" is not valid in SDK Config v1`,
2182
+ 'Rename the toolset to lowercase letters, numbers, or hyphens; "default" is reserved.',
2183
+ ["targets", basePath[2], "generation", "toolsets", name]
2184
+ );
2185
+ }
2186
+ if (!isObject(filter)) return void 0;
2187
+ return [
2188
+ name,
2189
+ compact({
2190
+ include: stringArrayValue(filter.include),
2191
+ exclude: stringArrayValue(filter.exclude)
2192
+ })
2193
+ ];
2194
+ });
2195
+ if (entries.some((entry) => !entry)) return void 0;
2196
+ consume(state, located.path);
2197
+ return Object.fromEntries(entries.filter((entry) => entry !== void 0));
2198
+ }
2199
+ var unsupportedFieldSchema = zod.z.strictObject({
2200
+ source: zod.z.enum(["fern", "postman", "sdk-config-ir"]),
2201
+ path: zod.z.array(zod.z.union([nonEmptyStringSchema, zod.z.number().int().nonnegative()])).min(1),
2202
+ code: nonEmptyStringSchema.optional(),
2203
+ reason: nonEmptyStringSchema,
2204
+ severity: zod.z.enum(["error", "warning", "info"]),
2205
+ risk: zod.z.enum(["high", "medium", "low"]),
2206
+ owner: nonEmptyStringSchema,
2207
+ suggestedAction: nonEmptyStringSchema
2208
+ });
2209
+ var postmanLegacyInputSchema = zod.z.strictObject({
2210
+ kind: zod.z.literal("postman-build-parameters"),
2211
+ value: jsonObjectSchema
2212
+ });
2213
+ var fernLegacyInputSchema = zod.z.strictObject({
2214
+ kind: zod.z.literal("fern-generator-invocation"),
2215
+ value: jsonObjectSchema
2216
+ });
2217
+ var legacyInputSchema = zod.z.discriminatedUnion("kind", [
2218
+ postmanLegacyInputSchema,
2219
+ fernLegacyInputSchema
2220
+ ]);
2221
+ var compatibilityConfigSchema = zod.z.strictObject({
2222
+ outputProfile: zod.z.enum(["converged", "postman-legacy", "fern-legacy"]),
2223
+ legacyInput: legacyInputSchema.optional(),
2224
+ unsupportedFields: zod.z.array(unsupportedFieldSchema).optional()
2225
+ });
2226
+ var generationAssetSchema = zod.z.discriminatedUnion("type", [
2227
+ zod.z.strictObject({ type: zod.z.literal("path"), location: relativePathSchema }),
2228
+ zod.z.strictObject({ type: zod.z.literal("url"), location: nonEmptyStringSchema }),
2229
+ zod.z.strictObject({ type: zod.z.literal("artifact"), location: nonEmptyStringSchema })
2230
+ ]);
2231
+ var hookDependencySchema2 = zod.z.strictObject({
2232
+ name: nonEmptyStringSchema,
2233
+ version: nonEmptyStringSchema,
2234
+ groupId: nonEmptyStringSchema.optional()
2235
+ });
2236
+ var hooksConfigSchema2 = zod.z.strictObject({
2237
+ enabled: zod.z.boolean(),
2238
+ source: generationAssetSchema.optional(),
2239
+ dependencies: zod.z.array(hookDependencySchema2).optional()
2240
+ });
2241
+ var customCodeConfigSchema2 = zod.z.strictObject({
2242
+ enabled: zod.z.boolean(),
2243
+ source: generationAssetSchema.optional(),
2244
+ conflictStrategy: zod.z.enum(["mark", "ours", "theirs"]).optional(),
2245
+ trackChanges: zod.z.boolean().optional(),
2246
+ previousBuildId: zod.z.number().int().positive().optional(),
2247
+ protectedFiles: zod.z.array(nonEmptyStringSchema).optional()
2248
+ });
2249
+ var workflowConfigSchema2 = zod.z.strictObject({
2250
+ path: relativePathSchema,
2251
+ outputName: nonEmptyStringSchema.optional()
2252
+ });
2253
+ var analyticsHeaderSchema2 = zod.z.union([
2254
+ zod.z.strictObject({ name: nonEmptyStringSchema, value: zod.z.string() }),
2255
+ zod.z.strictObject({ name: nonEmptyStringSchema, valueRef: nonEmptyStringSchema })
2256
+ ]);
2257
+ var analyticsConfigSchema2 = zod.z.strictObject({
2258
+ enabled: zod.z.boolean(),
2259
+ endpoint: nonEmptyStringSchema.optional(),
2260
+ exporter: zod.z.enum(["otlp-http", "console"]).optional(),
2261
+ headers: zod.z.array(analyticsHeaderSchema2).optional(),
2262
+ batchSize: zod.z.number().int().positive().optional(),
2263
+ scheduledDelayMs: zod.z.number().nonnegative().optional(),
2264
+ exportTimeoutMs: zod.z.number().nonnegative().optional()
2265
+ }).superRefine(({ enabled, endpoint }, context) => {
2266
+ if (enabled && endpoint === void 0) {
2267
+ context.addIssue({
2268
+ code: "custom",
2269
+ message: "endpoint is required when analytics is enabled",
2270
+ path: ["endpoint"]
2271
+ });
2272
+ }
2273
+ });
2274
+ var wireTestsSchema2 = zod.z.strictObject({
2275
+ enabled: zod.z.boolean(),
2276
+ exclusions: zod.z.array(nonEmptyStringSchema).optional(),
2277
+ fallbackToGeneratedErrorExamples: zod.z.boolean().optional(),
2278
+ fixtureSource: zod.z.enum(["synthetic", "recorded", "auto"]).optional()
2279
+ });
2280
+ var unitTestsSchema2 = zod.z.strictObject({
566
2281
  enabled: zod.z.boolean(),
567
2282
  mode: zod.z.enum(["core-runtime", "schema-driven", "both"]).optional(),
568
2283
  exclusions: zod.z.array(nonEmptyStringSchema).optional()
569
2284
  });
570
- var streamsSchema = zod.z.strictObject({
2285
+ var fernDefinitionMetadataSchema = zod.z.strictObject({
2286
+ definitionS3DownloadUrl: nonEmptyStringSchema,
2287
+ outputPath: nonEmptyStringSchema.optional(),
2288
+ cliVersion: nonEmptyStringSchema.optional()
2289
+ });
2290
+ var streamsSchema2 = zod.z.strictObject({
571
2291
  enabled: zod.z.boolean(),
572
2292
  responseType: zod.z.enum(["wrapper", "native", "web"]).optional(),
573
2293
  fileResponseType: zod.z.enum(["stream", "binary-response"]).optional(),
574
2294
  defaultChunkSizeBytes: zod.z.number().int().positive().optional()
575
2295
  });
576
- var namingConfigSchema = zod.z.strictObject({
2296
+ var namingConfigSchema2 = zod.z.strictObject({
577
2297
  clientName: nonEmptyStringSchema.optional(),
578
2298
  exportedClientName: nonEmptyStringSchema.optional(),
579
2299
  environmentTypeName: nonEmptyStringSchema.optional(),
@@ -581,11 +2301,11 @@ var namingConfigSchema = zod.z.strictObject({
581
2301
  baseErrorName: nonEmptyStringSchema.optional(),
582
2302
  pagerName: nonEmptyStringSchema.optional()
583
2303
  });
584
- var layoutConfigSchema = zod.z.strictObject({
2304
+ var layoutConfigSchema2 = zod.z.strictObject({
585
2305
  outputDirectory: zod.z.enum(["project-root", "source-root"]).optional(),
586
2306
  packagePath: nonEmptyStringSchema.optional()
587
2307
  });
588
- var serializationConfigSchema = zod.z.strictObject({
2308
+ var serializationConfigSchema2 = zod.z.strictObject({
589
2309
  enumRepresentation: zod.z.enum(["enum", "union", "literal", "forward-compatible-enum", "language-default"]).optional(),
590
2310
  additionalProperties: zod.z.enum(["allow", "forbid", "ignore", "language-default"]).optional(),
591
2311
  inlineTypes: zod.z.boolean().optional(),
@@ -618,19 +2338,30 @@ var generationConfigSchema = zod.z.strictObject({
618
2338
  devContainer: zod.z.boolean().default(false),
619
2339
  allowMockClient: zod.z.boolean().default(false),
620
2340
  ignoreFiles: zod.z.array(nonEmptyStringSchema).optional(),
2341
+ /**
2342
+ * Raw .fernignore file contents supplied to external publishers that need Fern ignore semantics.
2343
+ * This is separate from generation.ignoreFiles because raw contents preserve comments, ordering,
2344
+ * blank lines, and negation rules.
2345
+ */
2346
+ fernignoreContents: zod.z.string().optional(),
2347
+ /**
2348
+ * Optional Fern definition metadata for publisher paths that need to write definition or
2349
+ * mock-server support files. This is not required for core GitHub artifact publishing.
2350
+ */
2351
+ fernDefinitionMetadata: fernDefinitionMetadataSchema.optional(),
621
2352
  reservedKeywords: zod.z.array(nonEmptyStringSchema).optional(),
622
- hooks: hooksConfigSchema.optional(),
623
- customCode: customCodeConfigSchema.optional(),
624
- workflows: zod.z.array(workflowConfigSchema).optional(),
625
- customQueryPaths: zod.z.array(nonEmptyStringSchema).optional(),
626
- analytics: analyticsConfigSchema.optional(),
627
- wireTests: wireTestsSchema.optional(),
628
- unitTests: unitTestsSchema.optional(),
2353
+ hooks: hooksConfigSchema2.optional(),
2354
+ customCode: customCodeConfigSchema2.optional(),
2355
+ workflows: zod.z.array(workflowConfigSchema2).optional(),
2356
+ customQueryPaths: zod.z.array(relativePathSchema).optional(),
2357
+ analytics: analyticsConfigSchema2.optional(),
2358
+ wireTests: wireTestsSchema2.optional(),
2359
+ unitTests: unitTestsSchema2.optional(),
629
2360
  webSockets: zod.z.boolean().optional(),
630
- streams: streamsSchema.optional(),
631
- naming: namingConfigSchema.optional(),
632
- layout: layoutConfigSchema.optional(),
633
- serialization: serializationConfigSchema.optional(),
2361
+ streams: streamsSchema2.optional(),
2362
+ naming: namingConfigSchema2.optional(),
2363
+ layout: layoutConfigSchema2.optional(),
2364
+ serialization: serializationConfigSchema2.optional(),
634
2365
  language: languageGenerationConfigSchema.optional()
635
2366
  });
636
2367
  var publishRegistrySchema = zod.z.enum([
@@ -643,57 +2374,95 @@ var publishRegistrySchema = zod.z.enum([
643
2374
  "go",
644
2375
  "composer"
645
2376
  ]);
646
- var commonPublishShape = {
2377
+ var credentialResolutionSchema = zod.z.enum([
2378
+ "refs-only",
2379
+ "resolved-by-orchestrator",
2380
+ "resolved-by-fiddle"
2381
+ ]);
2382
+ var commonPublishShape2 = {
647
2383
  url: nonEmptyStringSchema.optional(),
2384
+ /**
2385
+ * Reference to registry publishing credentials. Raw tokens/passwords are intentionally not part of
2386
+ * SDK Config IR; the external publisher or orchestrator resolves this reference before use.
2387
+ */
648
2388
  credentialsRef: nonEmptyStringSchema.optional(),
649
2389
  releaseBranch: nonEmptyStringSchema.optional(),
650
2390
  tolerateRepublish: zod.z.boolean().optional()
651
2391
  };
652
2392
  var publishConfigSchema = zod.z.discriminatedUnion("registry", [
653
- zod.z.strictObject({ registry: zod.z.literal("npm"), ...commonPublishShape }),
654
- zod.z.strictObject({ registry: zod.z.literal("pypi"), ...commonPublishShape }),
655
- zod.z.strictObject({ registry: zod.z.literal("nuget"), ...commonPublishShape }),
656
- zod.z.strictObject({ registry: zod.z.literal("rubygems"), ...commonPublishShape }),
657
- zod.z.strictObject({ registry: zod.z.literal("crates"), ...commonPublishShape }),
658
- zod.z.strictObject({ registry: zod.z.literal("go"), ...commonPublishShape }),
659
- zod.z.strictObject({ registry: zod.z.literal("composer"), ...commonPublishShape }),
2393
+ zod.z.strictObject({ registry: zod.z.literal("npm"), ...commonPublishShape2 }),
2394
+ zod.z.strictObject({ registry: zod.z.literal("pypi"), ...commonPublishShape2 }),
2395
+ zod.z.strictObject({ registry: zod.z.literal("nuget"), ...commonPublishShape2 }),
2396
+ zod.z.strictObject({ registry: zod.z.literal("rubygems"), ...commonPublishShape2 }),
2397
+ zod.z.strictObject({ registry: zod.z.literal("crates"), ...commonPublishShape2 }),
2398
+ zod.z.strictObject({ registry: zod.z.literal("go"), ...commonPublishShape2 }),
2399
+ zod.z.strictObject({ registry: zod.z.literal("composer"), ...commonPublishShape2 }),
660
2400
  zod.z.strictObject({
661
2401
  registry: zod.z.literal("maven"),
2402
+ /**
2403
+ * Reference to Maven signing credentials. Raw signing keys are intentionally not part of SDK
2404
+ * Config IR; the external publisher or orchestrator resolves this reference before use.
2405
+ */
662
2406
  signingCredentialsRef: nonEmptyStringSchema.optional(),
663
- ...commonPublishShape
2407
+ ...commonPublishShape2
664
2408
  })
665
2409
  ]);
666
- var reviewersSchema = zod.z.strictObject({
2410
+ var reviewersSchema2 = zod.z.strictObject({
667
2411
  teams: zod.z.array(nonEmptyStringSchema).optional(),
668
2412
  users: zod.z.array(nonEmptyStringSchema).optional()
669
2413
  });
670
- var githubOutputSchema = zod.z.strictObject({
2414
+ var replayControlSchema = zod.z.strictObject({
2415
+ enabled: zod.z.boolean()
2416
+ });
2417
+ var githubOutputSchema2 = zod.z.strictObject({
671
2418
  repository: nonEmptyStringSchema,
672
2419
  host: nonEmptyStringSchema.optional(),
673
2420
  branch: nonEmptyStringSchema.optional(),
674
2421
  mode: zod.z.enum(["release", "pull-request", "push"]).optional(),
675
- reviewers: reviewersSchema.optional(),
2422
+ reviewers: reviewersSchema2.optional(),
2423
+ /**
2424
+ * Reference to GitHub credentials. Raw tokens are intentionally not part of SDK Config IR; the
2425
+ * external publisher or orchestrator resolves this reference before use.
2426
+ */
676
2427
  credentialsRef: nonEmptyStringSchema.optional(),
677
- privateRepository: zod.z.boolean().optional()
678
- });
679
- var filesOutputSchema = zod.z.strictObject({
2428
+ privateRepository: zod.z.boolean().optional(),
2429
+ /** GitHub replay control. If omitted, the external publisher applies its default behavior. */
2430
+ replay: replayControlSchema.optional(),
2431
+ /** Run GitHub publishing verification. Defaults to false to match current Fiddle job behavior. */
2432
+ verify: zod.z.boolean().default(false),
2433
+ /** Skip creating/updating a GitHub PR when no files changed. Defaults to false. */
2434
+ skipIfNoDiff: zod.z.boolean().default(false),
2435
+ /** Automatically merge the GitHub publishing PR. Defaults to false. */
2436
+ autoMerge: zod.z.boolean().default(false)
2437
+ });
2438
+ var credentialResolutionShape = {
2439
+ /**
2440
+ * Where output credential references are resolved. SDK Config IR carries refs only; raw resolved
2441
+ * credentials belong at the external publisher/orchestrator boundary, not in this config.
2442
+ */
2443
+ credentialResolution: credentialResolutionSchema.default("refs-only")
2444
+ };
2445
+ var filesOutputSchema2 = zod.z.strictObject({
680
2446
  delivery: zod.z.literal("files"),
681
2447
  path: nonEmptyStringSchema.optional(),
682
- publish: publishConfigSchema.optional()
2448
+ publish: publishConfigSchema.optional(),
2449
+ ...credentialResolutionShape
683
2450
  });
684
- var zipOutputSchema = zod.z.strictObject({
2451
+ var zipOutputSchema2 = zod.z.strictObject({
685
2452
  delivery: zod.z.literal("zip"),
686
2453
  fileName: nonEmptyStringSchema.optional(),
687
- publish: publishConfigSchema.optional()
2454
+ publish: publishConfigSchema.optional(),
2455
+ ...credentialResolutionShape
688
2456
  });
689
- var githubDeliverySchema = zod.z.strictObject({
2457
+ var githubDeliverySchema2 = zod.z.strictObject({
690
2458
  delivery: zod.z.literal("github"),
691
- github: githubOutputSchema,
692
- publish: publishConfigSchema.optional()
2459
+ github: githubOutputSchema2,
2460
+ publish: publishConfigSchema.optional(),
2461
+ ...credentialResolutionShape
693
2462
  });
694
2463
  var outputConfigSchema = zod.z.discriminatedUnion(
695
2464
  "delivery",
696
- [filesOutputSchema, zipOutputSchema, githubDeliverySchema],
2465
+ [filesOutputSchema2, zipOutputSchema2, githubDeliverySchema2],
697
2466
  {
698
2467
  error: 'output.delivery must be one of "files", "zip", or "github"'
699
2468
  }
@@ -709,7 +2478,8 @@ var apiImportSettingsSchema = zod.z.strictObject({
709
2478
  onlyIncludeReferencedSchemas: zod.z.boolean().optional(),
710
2479
  objectQueryParameters: zod.z.boolean().optional(),
711
2480
  typeDatesAsStrings: zod.z.boolean().optional(),
712
- groupMultiApiEnvironments: zod.z.boolean().optional()
2481
+ groupMultiApiEnvironments: zod.z.boolean().optional(),
2482
+ defaultIntegerFormat: zod.z.enum(["int32", "int64", "uint32", "uint64"]).optional()
713
2483
  });
714
2484
  var sourceSpecTypeSchema = zod.z.enum([
715
2485
  "openapi",
@@ -766,15 +2536,27 @@ var targetConfigSchema = zod.z.strictObject({
766
2536
  generatorVersion: exactSemverSchema.optional(),
767
2537
  sourceOrigin: zod.z.enum(["postman", "fern"]),
768
2538
  sdkName: nonEmptyStringSchema,
2539
+ /**
2540
+ * Stable Fern/Fiddle API identity for external publishing.
2541
+ * Producers must set this explicitly for GitHub or registry publishing; it is not inferred from
2542
+ * target.sdkName because SDK display names and Fern API names are not equivalent.
2543
+ */
2544
+ apiName: nonEmptyStringSchema.optional(),
769
2545
  organization: nonEmptyStringSchema.optional(),
2546
+ /**
2547
+ * Stable Fern/Fiddle organization identity for external publishing.
2548
+ * Producers must set this explicitly for GitHub or registry publishing; it is not inferred from
2549
+ * target.organization because source organization metadata is optional and may not match Fern.
2550
+ */
2551
+ organizationName: nonEmptyStringSchema.optional(),
770
2552
  sdkVersion: nonEmptyStringSchema.default("1.0.0"),
771
2553
  apiVersion: nonEmptyStringSchema.optional()
772
2554
  });
773
2555
 
774
2556
  // src/sdk-config-ir/v1/sdk-config-ir-v1.ts
775
2557
  var SDK_CONFIG_IR_V1_SCHEMA_VERSION = "sdk-config-ir/v1";
776
- var publishRegistryLanguages = {
777
- npm: ["typescript"],
2558
+ var publishRegistryLanguages2 = {
2559
+ npm: ["typescript", "mcp"],
778
2560
  pypi: ["python"],
779
2561
  maven: ["java", "kotlin"],
780
2562
  nuget: ["csharp"],
@@ -783,7 +2565,7 @@ var publishRegistryLanguages = {
783
2565
  go: ["go"],
784
2566
  composer: ["php"]
785
2567
  };
786
- var packageNameRegistries = /* @__PURE__ */ new Set([
2568
+ var packageNameRegistries2 = /* @__PURE__ */ new Set([
787
2569
  "npm",
788
2570
  "pypi",
789
2571
  "nuget",
@@ -791,8 +2573,8 @@ var packageNameRegistries = /* @__PURE__ */ new Set([
791
2573
  "crates",
792
2574
  "composer"
793
2575
  ]);
794
- function validatePublishingIdentity(packageConfig, registry, context) {
795
- if (packageNameRegistries.has(registry) && !packageConfig.packageName) {
2576
+ function validatePublishingIdentity2(packageConfig, registry, context) {
2577
+ if (packageNameRegistries2.has(registry) && !packageConfig.packageName) {
796
2578
  context.addIssue({
797
2579
  code: "custom",
798
2580
  message: `package.packageName is required when publishing to "${registry}"`,
@@ -842,6 +2624,21 @@ var sdkConfigIrV1Schema = zod.z.strictObject({
842
2624
  compatibility: compatibilityConfigSchema.optional()
843
2625
  }).superRefine(({ compatibility, generation, output, package: packageConfig, target }, context) => {
844
2626
  const configuredLanguages = Object.keys(generation.language ?? {});
2627
+ const requiresExternalPublishIdentity = output.delivery === "github" || output.publish !== void 0;
2628
+ if (requiresExternalPublishIdentity) {
2629
+ [
2630
+ ["apiName", "target.apiName is required for external publishing"],
2631
+ ["organizationName", "target.organizationName is required for external publishing"]
2632
+ ].forEach(([field, message]) => {
2633
+ if (!target[field]) {
2634
+ context.addIssue({
2635
+ code: "custom",
2636
+ message,
2637
+ path: ["target", field]
2638
+ });
2639
+ }
2640
+ });
2641
+ }
845
2642
  configuredLanguages.forEach((language) => {
846
2643
  if (language !== target.language) {
847
2644
  context.addIssue({
@@ -851,7 +2648,7 @@ var sdkConfigIrV1Schema = zod.z.strictObject({
851
2648
  });
852
2649
  }
853
2650
  });
854
- if (output.publish && !publishRegistryLanguages[output.publish.registry].some(
2651
+ if (output.publish && !publishRegistryLanguages2[output.publish.registry].some(
855
2652
  (language) => language === target.language
856
2653
  )) {
857
2654
  context.addIssue({
@@ -861,7 +2658,7 @@ var sdkConfigIrV1Schema = zod.z.strictObject({
861
2658
  });
862
2659
  }
863
2660
  if (output.publish) {
864
- validatePublishingIdentity(packageConfig, output.publish.registry, context);
2661
+ validatePublishingIdentity2(packageConfig, output.publish.registry, context);
865
2662
  }
866
2663
  if (compatibility?.legacyInput) {
867
2664
  const expectedKind = target.sourceOrigin === "postman" ? "postman-build-parameters" : "fern-generator-invocation";
@@ -878,7 +2675,9 @@ function parseSdkConfigIrV1(value) {
878
2675
  return sdkConfigIrV1Schema.parse(value);
879
2676
  }
880
2677
 
2678
+ exports.FernConfigMappingError = FernConfigMappingError;
881
2679
  exports.SDK_CONFIG_IR_V1_SCHEMA_VERSION = SDK_CONFIG_IR_V1_SCHEMA_VERSION;
2680
+ exports.SDK_CONFIG_V1_SCHEMA_VERSION = SDK_CONFIG_V1_SCHEMA_VERSION;
882
2681
  exports.apiConfigSchema = apiConfigSchema;
883
2682
  exports.apiImportSettingsSchema = apiImportSettingsSchema;
884
2683
  exports.authConfigSchema = authConfigSchema;
@@ -900,19 +2699,57 @@ exports.jsonValueSchema = jsonValueSchema;
900
2699
  exports.kotlinGenerationConfigSchema = kotlinGenerationConfigSchema;
901
2700
  exports.languageGenerationConfigSchema = languageGenerationConfigSchema;
902
2701
  exports.legacyInputSchema = legacyInputSchema;
2702
+ exports.mapFernConfigToSdkConfigV1 = mapFernConfigToSdkConfigV1;
2703
+ exports.mcpAvailabilityStatuses = mcpAvailabilityStatuses;
903
2704
  exports.mcpGenerationConfigSchema = mcpGenerationConfigSchema;
904
2705
  exports.nonEmptyStringSchema = nonEmptyStringSchema;
905
2706
  exports.outputConfigSchema = outputConfigSchema;
906
2707
  exports.packageConfigSchema = packageConfigSchema;
907
2708
  exports.parseSdkConfigIrV1 = parseSdkConfigIrV1;
2709
+ exports.parseSdkConfigV1 = parseSdkConfigV1;
908
2710
  exports.phpGenerationConfigSchema = phpGenerationConfigSchema;
909
2711
  exports.publishConfigSchema = publishConfigSchema;
910
2712
  exports.publishRegistrySchema = publishRegistrySchema;
911
2713
  exports.pythonGenerationConfigSchema = pythonGenerationConfigSchema;
2714
+ exports.readmeCustomSectionSchema = readmeCustomSectionSchema;
912
2715
  exports.readmeEndpointSchema = readmeEndpointSchema;
2716
+ exports.relativePathSchema = relativePathSchema;
913
2717
  exports.rubyGenerationConfigSchema = rubyGenerationConfigSchema;
914
2718
  exports.rustGenerationConfigSchema = rustGenerationConfigSchema;
915
2719
  exports.sdkConfigIrV1Schema = sdkConfigIrV1Schema;
2720
+ exports.sdkConfigV1ApiConfigSchema = sdkConfigV1ApiConfigSchema;
2721
+ exports.sdkConfigV1AuthConfigSchema = sdkConfigV1AuthConfigSchema;
2722
+ exports.sdkConfigV1AuthSchemeSchema = sdkConfigV1AuthSchemeSchema;
2723
+ exports.sdkConfigV1CliGenerationConfigSchema = cliGenerationConfigSchema;
2724
+ exports.sdkConfigV1ClientConfigSchema = sdkConfigV1ClientConfigSchema;
2725
+ exports.sdkConfigV1ComposerPackageNameSchema = composerPackageNameSchema;
2726
+ exports.sdkConfigV1CsharpGenerationConfigSchema = csharpGenerationConfigSchema;
2727
+ exports.sdkConfigV1DependencySchema = sdkConfigV1DependencySchema;
2728
+ exports.sdkConfigV1DocsConfigSchema = sdkConfigV1DocsConfigSchema;
2729
+ exports.sdkConfigV1ExactSemverSchema = exactSemverSchema;
2730
+ exports.sdkConfigV1GenerationConfigSchema = sdkConfigV1GenerationConfigSchema;
2731
+ exports.sdkConfigV1GoGenerationConfigSchema = goGenerationConfigSchema;
2732
+ exports.sdkConfigV1GoModulePathSchema = goModulePathSchema;
2733
+ exports.sdkConfigV1JavaGenerationConfigSchema = javaGenerationConfigSchema;
2734
+ exports.sdkConfigV1KotlinGenerationConfigSchema = kotlinGenerationConfigSchema;
2735
+ exports.sdkConfigV1McpGenerationConfigSchema = mcpGenerationConfigSchema;
2736
+ exports.sdkConfigV1NonEmptyStringSchema = nonEmptyStringSchema;
2737
+ exports.sdkConfigV1OutputConfigSchema = sdkConfigV1OutputConfigSchema;
2738
+ exports.sdkConfigV1PackageConfigSchema = sdkConfigV1PackageConfigSchema;
2739
+ exports.sdkConfigV1PhpGenerationConfigSchema = phpGenerationConfigSchema;
2740
+ exports.sdkConfigV1PublishConfigSchema = sdkConfigV1PublishConfigSchema;
2741
+ exports.sdkConfigV1PublishRegistrySchema = sdkConfigV1PublishRegistrySchema;
2742
+ exports.sdkConfigV1PythonGenerationConfigSchema = pythonGenerationConfigSchema;
2743
+ exports.sdkConfigV1ReadmeCustomSectionSchema = sdkConfigV1ReadmeCustomSectionSchema;
2744
+ exports.sdkConfigV1ReadmeEndpointSchema = sdkConfigV1ReadmeEndpointSchema;
2745
+ exports.sdkConfigV1RelativePathSchema = relativePathSchema;
2746
+ exports.sdkConfigV1RubyGenerationConfigSchema = rubyGenerationConfigSchema;
2747
+ exports.sdkConfigV1RustGenerationConfigSchema = rustGenerationConfigSchema;
2748
+ exports.sdkConfigV1Schema = sdkConfigV1Schema;
2749
+ exports.sdkConfigV1SwiftGenerationConfigSchema = swiftGenerationConfigSchema;
2750
+ exports.sdkConfigV1TargetSchema = sdkConfigV1TargetSchema;
2751
+ exports.sdkConfigV1TerraformGenerationConfigSchema = terraformGenerationConfigSchema;
2752
+ exports.sdkConfigV1TypescriptGenerationConfigSchema = typescriptGenerationConfigSchema;
916
2753
  exports.sourceConfigSchema = sourceConfigSchema;
917
2754
  exports.sourceSpecConfigSchema = sourceSpecConfigSchema;
918
2755
  exports.sourceSpecTypeSchema = sourceSpecTypeSchema;