@postman/sdk-config 0.4.0 → 0.4.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.
@@ -575,7 +575,13 @@ function mapOutput(generator, language, index) {
575
575
  const raw = isObject(generator.raw) ? generator.raw : void 0;
576
576
  const rawOutput = raw && isObject(raw.output) ? raw.output : void 0;
577
577
  const outputPath = ["group", "generators", index, "outputMode"];
578
- const state = { consumedPaths: /* @__PURE__ */ new Set() };
578
+ const state = { consumedPaths: /* @__PURE__ */ new Set(), credentialDiagnostics: [] };
579
+ if (generator.output) {
580
+ return {
581
+ output: sanitizeNormalizedOutput(generator.output, rawOutput, state, index),
582
+ unsupportedFields: state.credentialDiagnostics ?? []
583
+ };
584
+ }
579
585
  if (rawOutput?.location === "local-file-system") {
580
586
  if (isObject(generator.outputMode)) consume(state, [...outputPath, "type"]);
581
587
  return finishOutputMapping(
@@ -607,7 +613,7 @@ function mapOutput(generator, language, index) {
607
613
  return finishOutputMapping({ output: { delivery: "zip" } }, output, outputPath, state, index);
608
614
  case "github":
609
615
  return finishOutputMapping(
610
- githubOutput(output, output.publishInfo, language, outputPath, state, index),
616
+ githubOutput(output, output.publishInfo, rawOutput, language, outputPath, state, index),
611
617
  output,
612
618
  outputPath,
613
619
  state,
@@ -627,6 +633,7 @@ function mapOutput(generator, language, index) {
627
633
  githubOutput(
628
634
  output.githubV2,
629
635
  output.githubV2.publishInfo,
636
+ rawOutput,
630
637
  language,
631
638
  githubPath,
632
639
  state,
@@ -641,6 +648,7 @@ function mapOutput(generator, language, index) {
641
648
  case "publishV2": {
642
649
  const publication = mapPublication(
643
650
  output.publishV2,
651
+ rawOutput,
644
652
  language,
645
653
  [...outputPath, "publishV2"],
646
654
  state,
@@ -660,6 +668,7 @@ function mapOutput(generator, language, index) {
660
668
  case "publish": {
661
669
  const publication = mapLegacyPublication(
662
670
  output.registryOverrides,
671
+ rawOutput,
663
672
  language,
664
673
  [...outputPath, "registryOverrides"],
665
674
  state,
@@ -686,7 +695,22 @@ function mapOutput(generator, language, index) {
686
695
  );
687
696
  }
688
697
  }
689
- function githubOutput(value, publishInfo, language, sourcePath, state, index) {
698
+ function sanitizeNormalizedOutput(output, rawOutput, state, index) {
699
+ const publish = output.publish ? sanitizePublishConfig(output.publish, output.publish, rawOutput, state, index) : void 0;
700
+ const publishShape = publish ? { publish } : {};
701
+ if (output.delivery !== "github") return { ...output, ...publishShape };
702
+ const { credentials, ...github } = output.github;
703
+ if (credentials) {
704
+ addCredentialDiagnostic(
705
+ state,
706
+ ["group", "generators", index, "output", "github", "credentials"],
707
+ ["targets", index, "output", "github", "credentials"],
708
+ "Normalized GitHub credentials have no raw environment-expression provenance"
709
+ );
710
+ }
711
+ return { ...output, github, ...publishShape };
712
+ }
713
+ function githubOutput(value, publishInfo, rawOutput, language, sourcePath, state, index) {
690
714
  const owner = stringValue(value.owner);
691
715
  const repo = stringValue(value.repo);
692
716
  if (!owner || !repo)
@@ -699,14 +723,22 @@ function githubOutput(value, publishInfo, language, sourcePath, state, index) {
699
723
  );
700
724
  consume(state, [...sourcePath, "owner"]);
701
725
  consume(state, [...sourcePath, "repo"]);
702
- const publication = publishInfo ? mapPublication(publishInfo, language, [...sourcePath, "publishInfo"], state, index) : void 0;
726
+ const publication = publishInfo ? mapPublication(publishInfo, rawOutput, language, [...sourcePath, "publishInfo"], state, index) : void 0;
703
727
  const type = stringValue(value.type);
704
728
  const reviewers = mapReviewers(value.reviewers, [...sourcePath, "reviewers"], state);
705
729
  if (type) consume(state, [...sourcePath, "type"]);
706
730
  if (typeof value.makePr === "boolean") consume(state, [...sourcePath, "makePr"]);
707
731
  if (stringValue(value.host)) consume(state, [...sourcePath, "host"]);
708
732
  if (stringValue(value.branch)) consume(state, [...sourcePath, "branch"]);
709
- const credentials = mapCredentials(value.credentials, [...sourcePath, "credentials"], state);
733
+ consumeCredentialObject(value.credentials, [...sourcePath, "credentials"], state);
734
+ if (isObject(value.credentials)) {
735
+ addCredentialDiagnostic(
736
+ state,
737
+ [...sourcePath, "credentials"],
738
+ ["targets", index, "output", "github", "credentials"],
739
+ "GitHub credentials cannot be traced safely to raw environment expressions"
740
+ );
741
+ }
710
742
  return {
711
743
  output: {
712
744
  delivery: "github",
@@ -715,57 +747,35 @@ function githubOutput(value, publishInfo, language, sourcePath, state, index) {
715
747
  ...optional("host", stringValue(value.host)),
716
748
  ...optional("branch", stringValue(value.branch)),
717
749
  mode: value.makePr === true || type === "pullRequest" ? "pull-request" : type === "push" ? "push" : "release",
718
- ...optional("reviewers", reviewers),
719
- ...optional("credentials", credentials)
750
+ ...optional("reviewers", reviewers)
720
751
  },
721
752
  ...publication ? { publish: publication.publish } : {}
722
753
  },
723
754
  ...optional("package", publication?.package)
724
755
  };
725
756
  }
726
- function mapCredentials(value, sourcePath, state) {
727
- if (!isObject(value)) return void 0;
728
- return credentialsFromObject(value, sourcePath, state);
729
- }
730
- function mapInlineCredentials(value, sourcePath, state) {
731
- const credentials = mapCredentials(value.credentials, [...sourcePath, "credentials"], state);
732
- if (credentials) return credentials;
733
- return credentialsFromObject(value, sourcePath, state);
734
- }
735
- function credentialsFromObject(value, sourcePath, state) {
736
- const credentials = {};
737
- const username = stringValue(value.username);
738
- const password = stringValue(value.password);
739
- const token = stringValue(value.token);
740
- const apiKey = stringValue(value.apiKey);
741
- if (username) {
742
- credentials.username = username;
743
- consume(state, [...sourcePath, "username"]);
757
+ function consumeCredentialObject(value, sourcePath, state) {
758
+ if (!isObject(value)) return;
759
+ for (const field of ["username", "password", "token", "apiKey"]) {
760
+ if (stringValue(value[field])) consume(state, [...sourcePath, field]);
744
761
  }
745
- if (password) {
746
- credentials.password = password;
747
- consume(state, [...sourcePath, "password"]);
762
+ }
763
+ function consumeResolvedCredentials(value, sourcePath, state) {
764
+ for (const field of ["username", "password", "token", "apiKey"]) {
765
+ if (stringValue(value[field])) {
766
+ consume(state, [...sourcePath, field]);
767
+ }
748
768
  }
749
- if (token) {
750
- credentials.token = token;
751
- consume(state, [...sourcePath, "token"]);
769
+ if (isObject(value.credentials)) {
770
+ for (const field of ["username", "password", "token", "apiKey"]) {
771
+ if (stringValue(value.credentials[field])) {
772
+ consume(state, [...sourcePath, "credentials", field]);
773
+ }
774
+ }
752
775
  }
753
- if (apiKey) {
754
- credentials.apiKey = apiKey;
755
- consume(state, [...sourcePath, "apiKey"]);
776
+ if (isObject(value.signature)) {
777
+ consume(state, [...sourcePath, "signature"]);
756
778
  }
757
- return Object.keys(credentials).length === 0 ? void 0 : credentials;
758
- }
759
- function mapMavenSignature(value, sourcePath, state) {
760
- if (!isObject(value)) return void 0;
761
- const keyId = stringValue(value.keyId);
762
- const password = stringValue(value.password);
763
- const secretKey = stringValue(value.secretKey);
764
- if (!keyId || !password || !secretKey) return void 0;
765
- consume(state, [...sourcePath, "keyId"]);
766
- consume(state, [...sourcePath, "password"]);
767
- consume(state, [...sourcePath, "secretKey"]);
768
- return { keyId, password, secretKey };
769
779
  }
770
780
  function mapReviewers(value, sourcePath, state) {
771
781
  if (Array.isArray(value)) {
@@ -794,7 +804,7 @@ function reviewerNames(value, expectedType, sourcePath, state) {
794
804
  });
795
805
  return names.length ? names : void 0;
796
806
  }
797
- function mapPublication(value, language, sourcePath, state, index) {
807
+ function mapPublication(value, rawOutput, language, sourcePath, state, index) {
798
808
  if (!isObject(value))
799
809
  fail(
800
810
  "FERN_PUBLICATION_INVALID",
@@ -810,13 +820,19 @@ function mapPublication(value, language, sourcePath, state, index) {
810
820
  const registry = publicationRegistry(type, language, [...sourcePath, "type"], index);
811
821
  const registryUrl = stringValue(nested.registryUrl);
812
822
  if (registryUrl) consume(state, [...nestedPath, "registryUrl"]);
813
- const credentials = mapInlineCredentials(nested, nestedPath, state);
823
+ consumeResolvedCredentials(nested, nestedPath, state);
824
+ const publish = sanitizePublishConfig(
825
+ compact({ registry, url: registryUrl }),
826
+ nested,
827
+ rawOutput,
828
+ state,
829
+ index
830
+ );
814
831
  if (registry === "maven") {
815
832
  const coordinate = stringValue(nested.coordinate);
816
- const signature = mapMavenSignature(nested.signature, [...nestedPath, "signature"], state);
817
833
  if (coordinate) consume(state, [...nestedPath, "coordinate"]);
818
834
  return {
819
- publish: compact({ registry, url: registryUrl, credentials, signature }),
835
+ publish,
820
836
  ...coordinate ? { package: mavenPackage(coordinate, [...nestedPath, "coordinate"], index) } : {}
821
837
  };
822
838
  }
@@ -825,15 +841,244 @@ function mapPublication(value, language, sourcePath, state, index) {
825
841
  if (packageName) consume(state, [...nestedPath, packageNameField]);
826
842
  const metadata = registry === "pypi" ? mapPypiMetadata(nested.pypiMetadata, nestedPath, state) : {};
827
843
  return {
828
- publish: compact({ registry, url: registryUrl, credentials }),
844
+ publish,
829
845
  ...packageName || Object.keys(metadata).length ? { package: { ...optional("packageName", packageName), ...metadata } } : {}
830
846
  };
831
847
  }
832
- function mapLegacyPublication(value, language, sourcePath, state, index) {
848
+ function sanitizePublishConfig(publish, resolvedPublication, rawOutput, state, index) {
849
+ const rawPublication = rawOutput?.location === publish.registry ? rawOutput : void 0;
850
+ const rawPath = ["group", "generators", index, "output"];
851
+ if (publish.registry === "npm" || publish.registry === "crates") {
852
+ const token = mapCredentialExpression(
853
+ rawPublication,
854
+ resolvedPublication,
855
+ "token",
856
+ rawPath,
857
+ state,
858
+ index
859
+ );
860
+ warnForUnexpectedCredentialFields(
861
+ rawPublication,
862
+ resolvedPublication,
863
+ ["token"],
864
+ rawPath,
865
+ state,
866
+ index
867
+ );
868
+ return compact({
869
+ registry: publish.registry,
870
+ url: publish.url,
871
+ releaseBranch: publish.releaseBranch,
872
+ tolerateRepublish: publish.tolerateRepublish,
873
+ token
874
+ });
875
+ }
876
+ if (publish.registry === "pypi") {
877
+ const { username, password } = mapPypiCredentialExpressions(
878
+ rawPublication,
879
+ resolvedPublication,
880
+ rawPath,
881
+ state,
882
+ index
883
+ );
884
+ warnForUnexpectedCredentialFields(
885
+ rawPublication,
886
+ resolvedPublication,
887
+ ["username", "password", "token"],
888
+ rawPath,
889
+ state,
890
+ index
891
+ );
892
+ return compact({
893
+ registry: publish.registry,
894
+ url: publish.url,
895
+ releaseBranch: publish.releaseBranch,
896
+ tolerateRepublish: publish.tolerateRepublish,
897
+ username,
898
+ password
899
+ });
900
+ }
901
+ if (publish.registry === "maven") {
902
+ const username = mapCredentialExpression(
903
+ rawPublication,
904
+ resolvedPublication,
905
+ "username",
906
+ rawPath,
907
+ state,
908
+ index
909
+ );
910
+ const password = mapCredentialExpression(
911
+ rawPublication,
912
+ resolvedPublication,
913
+ "password",
914
+ rawPath,
915
+ state,
916
+ index
917
+ );
918
+ const signature = mapMavenSignatureExpressions(
919
+ rawPublication?.signature,
920
+ resolvedPublication.signature,
921
+ [...rawPath, "signature"],
922
+ state,
923
+ index
924
+ );
925
+ warnForUnexpectedCredentialFields(
926
+ rawPublication,
927
+ resolvedPublication,
928
+ ["username", "password"],
929
+ rawPath,
930
+ state,
931
+ index,
932
+ true
933
+ );
934
+ return compact({
935
+ registry: publish.registry,
936
+ url: publish.url,
937
+ releaseBranch: publish.releaseBranch,
938
+ tolerateRepublish: publish.tolerateRepublish,
939
+ username,
940
+ password,
941
+ signature
942
+ });
943
+ }
944
+ warnForUnrepresentableCredentials(rawPublication, resolvedPublication, rawPath, state, index);
945
+ return compact({
946
+ registry: publish.registry,
947
+ url: publish.url,
948
+ releaseBranch: publish.releaseBranch,
949
+ tolerateRepublish: publish.tolerateRepublish
950
+ });
951
+ }
952
+ function mapLegacyPublication(value, rawOutput, language, sourcePath, state, index) {
833
953
  const registry = defaultRegistry(language, sourcePath, index);
834
954
  const overrides = isObject(value) ? value : {};
835
955
  const override = isObject(overrides[registry]) ? overrides[registry] : {};
836
- return mapPublication(override, language, [...sourcePath, registry], state, index);
956
+ return mapPublication(override, rawOutput, language, [...sourcePath, registry], state, index);
957
+ }
958
+ function mapCredentialExpression(rawPublication, resolvedPublication, field, rawPath, state, index) {
959
+ const rawValue = rawPublication?.[field];
960
+ if (isEnvironmentExpression(rawValue)) return rawValue;
961
+ if (rawValue !== void 0 || hasResolvedCredential(resolvedPublication, field)) {
962
+ addCredentialDiagnostic(
963
+ state,
964
+ [...rawPath, field],
965
+ ["targets", index, "output", "publish", field],
966
+ `Fern publishing ${field} is not an exact environment expression`
967
+ );
968
+ }
969
+ return void 0;
970
+ }
971
+ function mapPypiCredentialExpressions(rawPublication, resolvedPublication, rawPath, state, index) {
972
+ const rawToken = rawPublication?.token;
973
+ if (isEnvironmentExpression(rawToken)) {
974
+ return { username: "__token__", password: rawToken };
975
+ }
976
+ const resolvedUsesToken = resolvedCredentialValue(resolvedPublication, "username") === "__token__";
977
+ if (rawToken !== void 0 || resolvedUsesToken) {
978
+ addCredentialDiagnostic(
979
+ state,
980
+ [...rawPath, "token"],
981
+ ["targets", index, "output", "publish", "password"],
982
+ "Fern PyPI token is not an exact raw environment expression"
983
+ );
984
+ return {};
985
+ }
986
+ return {
987
+ ...optional(
988
+ "username",
989
+ mapCredentialExpression(
990
+ rawPublication,
991
+ resolvedPublication,
992
+ "username",
993
+ rawPath,
994
+ state,
995
+ index
996
+ )
997
+ ),
998
+ ...optional(
999
+ "password",
1000
+ mapCredentialExpression(
1001
+ rawPublication,
1002
+ resolvedPublication,
1003
+ "password",
1004
+ rawPath,
1005
+ state,
1006
+ index
1007
+ )
1008
+ )
1009
+ };
1010
+ }
1011
+ function mapMavenSignatureExpressions(rawValue, resolvedValue, rawPath, state, index) {
1012
+ if (isObject(rawValue)) {
1013
+ const yamlValues = [rawValue["key-id"], rawValue.password, rawValue["secret-key"]];
1014
+ const projectedValues = [rawValue.keyId, rawValue.password, rawValue.secretKey];
1015
+ const values = yamlValues.every(isEnvironmentExpression) ? yamlValues : projectedValues.every(isEnvironmentExpression) ? projectedValues : void 0;
1016
+ if (values) {
1017
+ const [keyId, password, secretKey] = values;
1018
+ return { keyId, password, secretKey };
1019
+ }
1020
+ }
1021
+ if (rawValue !== void 0 || isObject(resolvedValue)) {
1022
+ addCredentialDiagnostic(
1023
+ state,
1024
+ rawPath,
1025
+ ["targets", index, "output", "publish", "signature"],
1026
+ "Maven signing credentials are incomplete or not exact environment expressions"
1027
+ );
1028
+ }
1029
+ return void 0;
1030
+ }
1031
+ function warnForUnrepresentableCredentials(rawPublication, resolvedPublication, rawPath, state, index) {
1032
+ const rawHasCredential = ["username", "password", "token", "apiKey"].some(
1033
+ (field) => rawPublication?.[field] !== void 0
1034
+ ) || rawPublication?.signature !== void 0;
1035
+ if (rawHasCredential || hasAnyResolvedCredential(resolvedPublication)) {
1036
+ addCredentialDiagnostic(
1037
+ state,
1038
+ rawPath,
1039
+ ["targets", index, "output", "publish"],
1040
+ "This registry does not support credentials in public SDK Config v1"
1041
+ );
1042
+ }
1043
+ }
1044
+ function warnForUnexpectedCredentialFields(rawPublication, resolvedPublication, allowedFields, rawPath, state, index, allowSignature = false) {
1045
+ const credentialFields = ["username", "password", "token", "apiKey"];
1046
+ const unexpectedFields = credentialFields.filter(
1047
+ (field) => !allowedFields.includes(field) && (rawPublication?.[field] !== void 0 || hasResolvedCredential(resolvedPublication, field))
1048
+ );
1049
+ const hasUnexpectedSignature = !allowSignature && (rawPublication?.signature !== void 0 || resolvedPublication.signature !== void 0);
1050
+ if (unexpectedFields.length > 0 || hasUnexpectedSignature) {
1051
+ addCredentialDiagnostic(
1052
+ state,
1053
+ rawPath,
1054
+ ["targets", index, "output", "publish"],
1055
+ "Fern publishing credentials or signing material include fields unsupported by this registry"
1056
+ );
1057
+ }
1058
+ }
1059
+ function hasResolvedCredential(value, field) {
1060
+ return resolvedCredentialValue(value, field) !== void 0;
1061
+ }
1062
+ function resolvedCredentialValue(value, field) {
1063
+ return stringValue(value[field]) ?? (isObject(value.credentials) ? stringValue(value.credentials[field]) : void 0);
1064
+ }
1065
+ function hasAnyResolvedCredential(value) {
1066
+ return ["username", "password", "token", "apiKey"].some(
1067
+ (field) => hasResolvedCredential(value, field)
1068
+ ) || value.signature !== void 0;
1069
+ }
1070
+ function isEnvironmentExpression(value) {
1071
+ return typeof value === "string" && /^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(value);
1072
+ }
1073
+ function addCredentialDiagnostic(state, path, sdkConfigPath, reason) {
1074
+ state.credentialDiagnostics?.push({
1075
+ code: "FERN_OUTPUT_CREDENTIAL_OMITTED",
1076
+ severity: "warning",
1077
+ path,
1078
+ reason,
1079
+ sdkConfigPath,
1080
+ suggestedAction: `Configure ${sdkConfigPath.join(".")} with an environment expression such as \${CREDENTIAL_ENV_VAR}.`
1081
+ });
837
1082
  }
838
1083
  function publicationRegistry(type, language, sourcePath, index) {
839
1084
  if (type === "postman") {
@@ -941,6 +1186,7 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
941
1186
  return {
942
1187
  ...mapping,
943
1188
  unsupportedFields: [
1189
+ ...state.credentialDiagnostics ?? [],
944
1190
  ...hasCredentials ? [
945
1191
  {
946
1192
  code: "FERN_OUTPUT_CREDENTIAL_UNSUPPORTED",
@@ -1170,12 +1416,6 @@ var sdkConfigV1PublishRegistrySchema = z.enum([
1170
1416
  "go",
1171
1417
  "composer"
1172
1418
  ]);
1173
- var registryCredentialsSchema = z.strictObject({
1174
- username: nonEmptyStringSchema.optional(),
1175
- password: nonEmptyStringSchema.optional(),
1176
- token: nonEmptyStringSchema.optional(),
1177
- apiKey: nonEmptyStringSchema.optional()
1178
- });
1179
1419
  var mavenSignatureSchema = z.strictObject({
1180
1420
  keyId: nonEmptyStringSchema,
1181
1421
  password: nonEmptyStringSchema,
@@ -1183,23 +1423,35 @@ var mavenSignatureSchema = z.strictObject({
1183
1423
  });
1184
1424
  var commonPublishShape = {
1185
1425
  url: nonEmptyStringSchema.optional(),
1186
- /** Raw registry credentials. These values can be sensitive and must be handled as secrets. */
1187
- credentials: registryCredentialsSchema.optional(),
1188
1426
  releaseBranch: nonEmptyStringSchema.optional(),
1189
1427
  tolerateRepublish: z.boolean().optional()
1190
1428
  };
1191
1429
  var sdkConfigV1PublishConfigSchema = z.discriminatedUnion("registry", [
1192
- z.strictObject({ registry: z.literal("npm"), ...commonPublishShape }),
1193
- z.strictObject({ registry: z.literal("pypi"), ...commonPublishShape }),
1430
+ z.strictObject({
1431
+ registry: z.literal("npm"),
1432
+ token: nonEmptyStringSchema.optional(),
1433
+ ...commonPublishShape
1434
+ }),
1435
+ z.strictObject({
1436
+ registry: z.literal("pypi"),
1437
+ username: nonEmptyStringSchema.optional(),
1438
+ password: nonEmptyStringSchema.optional(),
1439
+ ...commonPublishShape
1440
+ }),
1194
1441
  z.strictObject({
1195
1442
  registry: z.literal("maven"),
1196
- /** Raw Maven signing material. These values can be sensitive and must be handled as secrets. */
1443
+ username: nonEmptyStringSchema.optional(),
1444
+ password: nonEmptyStringSchema.optional(),
1197
1445
  signature: mavenSignatureSchema.optional(),
1198
1446
  ...commonPublishShape
1199
1447
  }),
1200
1448
  z.strictObject({ registry: z.literal("nuget"), ...commonPublishShape }),
1201
1449
  z.strictObject({ registry: z.literal("rubygems"), ...commonPublishShape }),
1202
- z.strictObject({ registry: z.literal("crates"), ...commonPublishShape }),
1450
+ z.strictObject({
1451
+ registry: z.literal("crates"),
1452
+ token: nonEmptyStringSchema.optional(),
1453
+ ...commonPublishShape
1454
+ }),
1203
1455
  z.strictObject({ registry: z.literal("go"), ...commonPublishShape }),
1204
1456
  z.strictObject({ registry: z.literal("composer"), ...commonPublishShape })
1205
1457
  ]);
@@ -1207,7 +1459,12 @@ var reviewersSchema = z.strictObject({
1207
1459
  teams: z.array(nonEmptyStringSchema).optional(),
1208
1460
  users: z.array(nonEmptyStringSchema).optional()
1209
1461
  });
1210
- var githubCredentialsSchema = registryCredentialsSchema;
1462
+ var githubCredentialsSchema = z.strictObject({
1463
+ username: nonEmptyStringSchema.optional(),
1464
+ password: nonEmptyStringSchema.optional(),
1465
+ token: nonEmptyStringSchema.optional(),
1466
+ apiKey: nonEmptyStringSchema.optional()
1467
+ });
1211
1468
  var githubOutputSchema = z.strictObject({
1212
1469
  repository: nonEmptyStringSchema,
1213
1470
  host: nonEmptyStringSchema.optional(),
@@ -1724,7 +1981,7 @@ function mapFernConfigToSdkConfigV1(input) {
1724
1981
  const mapped = input.group.generators.map((generator, index) => {
1725
1982
  const language = languages[index];
1726
1983
  const invocation = mapInvocation(generator, language, activeLanguages, index);
1727
- const outputMapping = generator.output ? { output: generator.output, unsupportedFields: [] } : mapOutput(generator, language, index);
1984
+ const outputMapping = mapOutput(generator, language, index);
1728
1985
  return {
1729
1986
  generator,
1730
1987
  language,
@@ -1783,6 +2040,7 @@ function mapFernConfigToSdkConfigV1(input) {
1783
2040
  source: input.source,
1784
2041
  ...optional("sdkVersion", input.sdkVersion),
1785
2042
  ...optional("apiVersion", input.apiVersion),
2043
+ ...optional("replay", input.replay),
1786
2044
  ...optionalObject("api", api),
1787
2045
  ...optionalObject("client", clients.shared),
1788
2046
  ...optionalObject("docs", docs.shared),