@postman/sdk-config 0.4.0 → 0.5.0

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.
@@ -34,6 +34,59 @@ var jsonValueSchema = zod.z.lazy(
34
34
  ])
35
35
  );
36
36
  zod.z.record(zod.z.string(), jsonValueSchema);
37
+ var hashAlgorithmSchema = zod.z.enum(["sha1", "sha256", "sha384", "sha512"]);
38
+ var encodingSchema = zod.z.enum(["base64", "hex"]);
39
+ var payloadComponentSchema = zod.z.enum(["body", "timestamp", "notification-url", "message-id"]);
40
+ var payloadFormatSchema = zod.z.strictObject({
41
+ components: zod.z.array(payloadComponentSchema).min(1),
42
+ delimiter: zod.z.string().optional(),
43
+ /**
44
+ * Set when the body is a form-encoded parameter map that must be canonicalized before signing:
45
+ * keys sorted, each key's values deduped and sorted, concatenated as key-value pairs.
46
+ */
47
+ bodySort: zod.z.literal("alphabetical").optional()
48
+ });
49
+ var timestampSchema = zod.z.strictObject({
50
+ header: nonEmptyStringSchema,
51
+ format: zod.z.enum(["unix-seconds", "unix-millis", "iso8601"]).optional(),
52
+ /** Replay window in seconds. */
53
+ tolerance: zod.z.number().positive().optional()
54
+ });
55
+ var bodyHashLocationSchema = zod.z.discriminatedUnion("type", [
56
+ zod.z.strictObject({
57
+ type: zod.z.literal("query-parameter"),
58
+ name: nonEmptyStringSchema
59
+ })
60
+ ]);
61
+ var bodyHashBindingSchema = zod.z.strictObject({
62
+ algorithm: hashAlgorithmSchema,
63
+ encoding: encodingSchema.optional(),
64
+ location: bodyHashLocationSchema
65
+ });
66
+ var urlNormalizationSchema = zod.z.strictObject({
67
+ /** Try the URL with and without an explicit default port. */
68
+ portVariants: zod.z.boolean().optional(),
69
+ /** Try the URL with the pre-RFC3986 query encoding (`+` for space, unescaped `*`). */
70
+ legacyQueryEncoding: zod.z.boolean().optional()
71
+ }).refine(
72
+ ({ portVariants, legacyQueryEncoding }) => portVariants === true || legacyQueryEncoding === true,
73
+ { message: "url normalization must enable at least one variant" }
74
+ );
75
+ var webhookSignatureSchema = zod.z.discriminatedUnion("type", [
76
+ zod.z.strictObject({
77
+ type: zod.z.literal("hmac"),
78
+ /** Request header carrying the signature. */
79
+ header: nonEmptyStringSchema,
80
+ algorithm: hashAlgorithmSchema.optional(),
81
+ encoding: encodingSchema.optional(),
82
+ /** Stripped from the header value before comparison, e.g. `sha256=`. */
83
+ signaturePrefix: zod.z.string().optional(),
84
+ payloadFormat: payloadFormatSchema.optional(),
85
+ timestamp: timestampSchema.optional(),
86
+ bodyHashBinding: bodyHashBindingSchema.optional(),
87
+ urlNormalization: urlNormalizationSchema.optional()
88
+ })
89
+ ]);
37
90
 
38
91
  // src/sdk-config-domain/v1/api.ts
39
92
  var authVariableSchema = zod.z.strictObject({
@@ -192,13 +245,19 @@ var apiConfigSchema = zod.z.strictObject({
192
245
  * Absent means all audiences. A present empty array selects no tagged audience: untagged nodes
193
246
  * remain included, while every audience-tagged node is excluded.
194
247
  */
195
- audiences: zod.z.array(nonEmptyStringSchema).optional()
248
+ audiences: zod.z.array(nonEmptyStringSchema).optional(),
249
+ /**
250
+ * How the API signs the webhooks it sends, enabling a generated verification helper. API-wide, and
251
+ * independent of whether any webhook is modeled — see {@link webhookSignatureSchema}.
252
+ */
253
+ webhookSignature: webhookSignatureSchema.optional()
196
254
  });
197
255
 
198
256
  // src/sdk-config/v1/api.ts
199
257
  var sdkConfigV1AuthSchemeSchema = authSchemeSchema;
200
258
  var sdkConfigV1AuthConfigSchema = authConfigSchema;
201
259
  var sdkConfigV1ApiConfigSchema = apiConfigSchema;
260
+ var sdkConfigV1WebhookSignatureSchema = webhookSignatureSchema;
202
261
  var retryOverrideShape = {
203
262
  enabled: zod.z.boolean().optional(),
204
263
  maxAttempts: zod.z.number().int().min(1).optional(),
@@ -581,7 +640,13 @@ function mapOutput(generator, language, index) {
581
640
  const raw = isObject(generator.raw) ? generator.raw : void 0;
582
641
  const rawOutput = raw && isObject(raw.output) ? raw.output : void 0;
583
642
  const outputPath = ["group", "generators", index, "outputMode"];
584
- const state = { consumedPaths: /* @__PURE__ */ new Set() };
643
+ const state = { consumedPaths: /* @__PURE__ */ new Set(), credentialDiagnostics: [] };
644
+ if (generator.output) {
645
+ return {
646
+ output: sanitizeNormalizedOutput(generator.output, rawOutput, state, index),
647
+ unsupportedFields: state.credentialDiagnostics ?? []
648
+ };
649
+ }
585
650
  if (rawOutput?.location === "local-file-system") {
586
651
  if (isObject(generator.outputMode)) consume(state, [...outputPath, "type"]);
587
652
  return finishOutputMapping(
@@ -613,7 +678,7 @@ function mapOutput(generator, language, index) {
613
678
  return finishOutputMapping({ output: { delivery: "zip" } }, output, outputPath, state, index);
614
679
  case "github":
615
680
  return finishOutputMapping(
616
- githubOutput(output, output.publishInfo, language, outputPath, state, index),
681
+ githubOutput(output, output.publishInfo, rawOutput, language, outputPath, state, index),
617
682
  output,
618
683
  outputPath,
619
684
  state,
@@ -633,6 +698,7 @@ function mapOutput(generator, language, index) {
633
698
  githubOutput(
634
699
  output.githubV2,
635
700
  output.githubV2.publishInfo,
701
+ rawOutput,
636
702
  language,
637
703
  githubPath,
638
704
  state,
@@ -647,6 +713,7 @@ function mapOutput(generator, language, index) {
647
713
  case "publishV2": {
648
714
  const publication = mapPublication(
649
715
  output.publishV2,
716
+ rawOutput,
650
717
  language,
651
718
  [...outputPath, "publishV2"],
652
719
  state,
@@ -666,6 +733,7 @@ function mapOutput(generator, language, index) {
666
733
  case "publish": {
667
734
  const publication = mapLegacyPublication(
668
735
  output.registryOverrides,
736
+ rawOutput,
669
737
  language,
670
738
  [...outputPath, "registryOverrides"],
671
739
  state,
@@ -692,7 +760,22 @@ function mapOutput(generator, language, index) {
692
760
  );
693
761
  }
694
762
  }
695
- function githubOutput(value, publishInfo, language, sourcePath, state, index) {
763
+ function sanitizeNormalizedOutput(output, rawOutput, state, index) {
764
+ const publish = output.publish ? sanitizePublishConfig(output.publish, output.publish, rawOutput, state, index) : void 0;
765
+ const publishShape = publish ? { publish } : {};
766
+ if (output.delivery !== "github") return { ...output, ...publishShape };
767
+ const { credentials, ...github } = output.github;
768
+ if (credentials) {
769
+ addCredentialDiagnostic(
770
+ state,
771
+ ["group", "generators", index, "output", "github", "credentials"],
772
+ ["targets", index, "output", "github", "credentials"],
773
+ "Normalized GitHub credentials have no raw environment-expression provenance"
774
+ );
775
+ }
776
+ return { ...output, github, ...publishShape };
777
+ }
778
+ function githubOutput(value, publishInfo, rawOutput, language, sourcePath, state, index) {
696
779
  const owner = stringValue(value.owner);
697
780
  const repo = stringValue(value.repo);
698
781
  if (!owner || !repo)
@@ -705,14 +788,22 @@ function githubOutput(value, publishInfo, language, sourcePath, state, index) {
705
788
  );
706
789
  consume(state, [...sourcePath, "owner"]);
707
790
  consume(state, [...sourcePath, "repo"]);
708
- const publication = publishInfo ? mapPublication(publishInfo, language, [...sourcePath, "publishInfo"], state, index) : void 0;
791
+ const publication = publishInfo ? mapPublication(publishInfo, rawOutput, language, [...sourcePath, "publishInfo"], state, index) : void 0;
709
792
  const type = stringValue(value.type);
710
793
  const reviewers = mapReviewers(value.reviewers, [...sourcePath, "reviewers"], state);
711
794
  if (type) consume(state, [...sourcePath, "type"]);
712
795
  if (typeof value.makePr === "boolean") consume(state, [...sourcePath, "makePr"]);
713
796
  if (stringValue(value.host)) consume(state, [...sourcePath, "host"]);
714
797
  if (stringValue(value.branch)) consume(state, [...sourcePath, "branch"]);
715
- const credentials = mapCredentials(value.credentials, [...sourcePath, "credentials"], state);
798
+ consumeCredentialObject(value.credentials, [...sourcePath, "credentials"], state);
799
+ if (isObject(value.credentials)) {
800
+ addCredentialDiagnostic(
801
+ state,
802
+ [...sourcePath, "credentials"],
803
+ ["targets", index, "output", "github", "credentials"],
804
+ "GitHub credentials cannot be traced safely to raw environment expressions"
805
+ );
806
+ }
716
807
  return {
717
808
  output: {
718
809
  delivery: "github",
@@ -721,57 +812,35 @@ function githubOutput(value, publishInfo, language, sourcePath, state, index) {
721
812
  ...optional("host", stringValue(value.host)),
722
813
  ...optional("branch", stringValue(value.branch)),
723
814
  mode: value.makePr === true || type === "pullRequest" ? "pull-request" : type === "push" ? "push" : "release",
724
- ...optional("reviewers", reviewers),
725
- ...optional("credentials", credentials)
815
+ ...optional("reviewers", reviewers)
726
816
  },
727
817
  ...publication ? { publish: publication.publish } : {}
728
818
  },
729
819
  ...optional("package", publication?.package)
730
820
  };
731
821
  }
732
- function mapCredentials(value, sourcePath, state) {
733
- if (!isObject(value)) return void 0;
734
- return credentialsFromObject(value, sourcePath, state);
735
- }
736
- function mapInlineCredentials(value, sourcePath, state) {
737
- const credentials = mapCredentials(value.credentials, [...sourcePath, "credentials"], state);
738
- if (credentials) return credentials;
739
- return credentialsFromObject(value, sourcePath, state);
740
- }
741
- function credentialsFromObject(value, sourcePath, state) {
742
- const credentials = {};
743
- const username = stringValue(value.username);
744
- const password = stringValue(value.password);
745
- const token = stringValue(value.token);
746
- const apiKey = stringValue(value.apiKey);
747
- if (username) {
748
- credentials.username = username;
749
- consume(state, [...sourcePath, "username"]);
822
+ function consumeCredentialObject(value, sourcePath, state) {
823
+ if (!isObject(value)) return;
824
+ for (const field of ["username", "password", "token", "apiKey"]) {
825
+ if (stringValue(value[field])) consume(state, [...sourcePath, field]);
750
826
  }
751
- if (password) {
752
- credentials.password = password;
753
- consume(state, [...sourcePath, "password"]);
827
+ }
828
+ function consumeResolvedCredentials(value, sourcePath, state) {
829
+ for (const field of ["username", "password", "token", "apiKey"]) {
830
+ if (stringValue(value[field])) {
831
+ consume(state, [...sourcePath, field]);
832
+ }
754
833
  }
755
- if (token) {
756
- credentials.token = token;
757
- consume(state, [...sourcePath, "token"]);
834
+ if (isObject(value.credentials)) {
835
+ for (const field of ["username", "password", "token", "apiKey"]) {
836
+ if (stringValue(value.credentials[field])) {
837
+ consume(state, [...sourcePath, "credentials", field]);
838
+ }
839
+ }
758
840
  }
759
- if (apiKey) {
760
- credentials.apiKey = apiKey;
761
- consume(state, [...sourcePath, "apiKey"]);
841
+ if (isObject(value.signature)) {
842
+ consume(state, [...sourcePath, "signature"]);
762
843
  }
763
- return Object.keys(credentials).length === 0 ? void 0 : credentials;
764
- }
765
- function mapMavenSignature(value, sourcePath, state) {
766
- if (!isObject(value)) return void 0;
767
- const keyId = stringValue(value.keyId);
768
- const password = stringValue(value.password);
769
- const secretKey = stringValue(value.secretKey);
770
- if (!keyId || !password || !secretKey) return void 0;
771
- consume(state, [...sourcePath, "keyId"]);
772
- consume(state, [...sourcePath, "password"]);
773
- consume(state, [...sourcePath, "secretKey"]);
774
- return { keyId, password, secretKey };
775
844
  }
776
845
  function mapReviewers(value, sourcePath, state) {
777
846
  if (Array.isArray(value)) {
@@ -800,7 +869,7 @@ function reviewerNames(value, expectedType, sourcePath, state) {
800
869
  });
801
870
  return names.length ? names : void 0;
802
871
  }
803
- function mapPublication(value, language, sourcePath, state, index) {
872
+ function mapPublication(value, rawOutput, language, sourcePath, state, index) {
804
873
  if (!isObject(value))
805
874
  fail(
806
875
  "FERN_PUBLICATION_INVALID",
@@ -816,13 +885,19 @@ function mapPublication(value, language, sourcePath, state, index) {
816
885
  const registry = publicationRegistry(type, language, [...sourcePath, "type"], index);
817
886
  const registryUrl = stringValue(nested.registryUrl);
818
887
  if (registryUrl) consume(state, [...nestedPath, "registryUrl"]);
819
- const credentials = mapInlineCredentials(nested, nestedPath, state);
888
+ consumeResolvedCredentials(nested, nestedPath, state);
889
+ const publish = sanitizePublishConfig(
890
+ compact({ registry, url: registryUrl }),
891
+ nested,
892
+ rawOutput,
893
+ state,
894
+ index
895
+ );
820
896
  if (registry === "maven") {
821
897
  const coordinate = stringValue(nested.coordinate);
822
- const signature = mapMavenSignature(nested.signature, [...nestedPath, "signature"], state);
823
898
  if (coordinate) consume(state, [...nestedPath, "coordinate"]);
824
899
  return {
825
- publish: compact({ registry, url: registryUrl, credentials, signature }),
900
+ publish,
826
901
  ...coordinate ? { package: mavenPackage(coordinate, [...nestedPath, "coordinate"], index) } : {}
827
902
  };
828
903
  }
@@ -831,15 +906,244 @@ function mapPublication(value, language, sourcePath, state, index) {
831
906
  if (packageName) consume(state, [...nestedPath, packageNameField]);
832
907
  const metadata = registry === "pypi" ? mapPypiMetadata(nested.pypiMetadata, nestedPath, state) : {};
833
908
  return {
834
- publish: compact({ registry, url: registryUrl, credentials }),
909
+ publish,
835
910
  ...packageName || Object.keys(metadata).length ? { package: { ...optional("packageName", packageName), ...metadata } } : {}
836
911
  };
837
912
  }
838
- function mapLegacyPublication(value, language, sourcePath, state, index) {
913
+ function sanitizePublishConfig(publish, resolvedPublication, rawOutput, state, index) {
914
+ const rawPublication = rawOutput?.location === publish.registry ? rawOutput : void 0;
915
+ const rawPath = ["group", "generators", index, "output"];
916
+ if (publish.registry === "npm" || publish.registry === "crates") {
917
+ const token = mapCredentialExpression(
918
+ rawPublication,
919
+ resolvedPublication,
920
+ "token",
921
+ rawPath,
922
+ state,
923
+ index
924
+ );
925
+ warnForUnexpectedCredentialFields(
926
+ rawPublication,
927
+ resolvedPublication,
928
+ ["token"],
929
+ rawPath,
930
+ state,
931
+ index
932
+ );
933
+ return compact({
934
+ registry: publish.registry,
935
+ url: publish.url,
936
+ releaseBranch: publish.releaseBranch,
937
+ tolerateRepublish: publish.tolerateRepublish,
938
+ token
939
+ });
940
+ }
941
+ if (publish.registry === "pypi") {
942
+ const { username, password } = mapPypiCredentialExpressions(
943
+ rawPublication,
944
+ resolvedPublication,
945
+ rawPath,
946
+ state,
947
+ index
948
+ );
949
+ warnForUnexpectedCredentialFields(
950
+ rawPublication,
951
+ resolvedPublication,
952
+ ["username", "password", "token"],
953
+ rawPath,
954
+ state,
955
+ index
956
+ );
957
+ return compact({
958
+ registry: publish.registry,
959
+ url: publish.url,
960
+ releaseBranch: publish.releaseBranch,
961
+ tolerateRepublish: publish.tolerateRepublish,
962
+ username,
963
+ password
964
+ });
965
+ }
966
+ if (publish.registry === "maven") {
967
+ const username = mapCredentialExpression(
968
+ rawPublication,
969
+ resolvedPublication,
970
+ "username",
971
+ rawPath,
972
+ state,
973
+ index
974
+ );
975
+ const password = mapCredentialExpression(
976
+ rawPublication,
977
+ resolvedPublication,
978
+ "password",
979
+ rawPath,
980
+ state,
981
+ index
982
+ );
983
+ const signature = mapMavenSignatureExpressions(
984
+ rawPublication?.signature,
985
+ resolvedPublication.signature,
986
+ [...rawPath, "signature"],
987
+ state,
988
+ index
989
+ );
990
+ warnForUnexpectedCredentialFields(
991
+ rawPublication,
992
+ resolvedPublication,
993
+ ["username", "password"],
994
+ rawPath,
995
+ state,
996
+ index,
997
+ true
998
+ );
999
+ return compact({
1000
+ registry: publish.registry,
1001
+ url: publish.url,
1002
+ releaseBranch: publish.releaseBranch,
1003
+ tolerateRepublish: publish.tolerateRepublish,
1004
+ username,
1005
+ password,
1006
+ signature
1007
+ });
1008
+ }
1009
+ warnForUnrepresentableCredentials(rawPublication, resolvedPublication, rawPath, state, index);
1010
+ return compact({
1011
+ registry: publish.registry,
1012
+ url: publish.url,
1013
+ releaseBranch: publish.releaseBranch,
1014
+ tolerateRepublish: publish.tolerateRepublish
1015
+ });
1016
+ }
1017
+ function mapLegacyPublication(value, rawOutput, language, sourcePath, state, index) {
839
1018
  const registry = defaultRegistry(language, sourcePath, index);
840
1019
  const overrides = isObject(value) ? value : {};
841
1020
  const override = isObject(overrides[registry]) ? overrides[registry] : {};
842
- return mapPublication(override, language, [...sourcePath, registry], state, index);
1021
+ return mapPublication(override, rawOutput, language, [...sourcePath, registry], state, index);
1022
+ }
1023
+ function mapCredentialExpression(rawPublication, resolvedPublication, field, rawPath, state, index) {
1024
+ const rawValue = rawPublication?.[field];
1025
+ if (isEnvironmentExpression(rawValue)) return rawValue;
1026
+ if (rawValue !== void 0 || hasResolvedCredential(resolvedPublication, field)) {
1027
+ addCredentialDiagnostic(
1028
+ state,
1029
+ [...rawPath, field],
1030
+ ["targets", index, "output", "publish", field],
1031
+ `Fern publishing ${field} is not an exact environment expression`
1032
+ );
1033
+ }
1034
+ return void 0;
1035
+ }
1036
+ function mapPypiCredentialExpressions(rawPublication, resolvedPublication, rawPath, state, index) {
1037
+ const rawToken = rawPublication?.token;
1038
+ if (isEnvironmentExpression(rawToken)) {
1039
+ return { username: "__token__", password: rawToken };
1040
+ }
1041
+ const resolvedUsesToken = resolvedCredentialValue(resolvedPublication, "username") === "__token__";
1042
+ if (rawToken !== void 0 || resolvedUsesToken) {
1043
+ addCredentialDiagnostic(
1044
+ state,
1045
+ [...rawPath, "token"],
1046
+ ["targets", index, "output", "publish", "password"],
1047
+ "Fern PyPI token is not an exact raw environment expression"
1048
+ );
1049
+ return {};
1050
+ }
1051
+ return {
1052
+ ...optional(
1053
+ "username",
1054
+ mapCredentialExpression(
1055
+ rawPublication,
1056
+ resolvedPublication,
1057
+ "username",
1058
+ rawPath,
1059
+ state,
1060
+ index
1061
+ )
1062
+ ),
1063
+ ...optional(
1064
+ "password",
1065
+ mapCredentialExpression(
1066
+ rawPublication,
1067
+ resolvedPublication,
1068
+ "password",
1069
+ rawPath,
1070
+ state,
1071
+ index
1072
+ )
1073
+ )
1074
+ };
1075
+ }
1076
+ function mapMavenSignatureExpressions(rawValue, resolvedValue, rawPath, state, index) {
1077
+ if (isObject(rawValue)) {
1078
+ const yamlValues = [rawValue["key-id"], rawValue.password, rawValue["secret-key"]];
1079
+ const projectedValues = [rawValue.keyId, rawValue.password, rawValue.secretKey];
1080
+ const values = yamlValues.every(isEnvironmentExpression) ? yamlValues : projectedValues.every(isEnvironmentExpression) ? projectedValues : void 0;
1081
+ if (values) {
1082
+ const [keyId, password, secretKey] = values;
1083
+ return { keyId, password, secretKey };
1084
+ }
1085
+ }
1086
+ if (rawValue !== void 0 || isObject(resolvedValue)) {
1087
+ addCredentialDiagnostic(
1088
+ state,
1089
+ rawPath,
1090
+ ["targets", index, "output", "publish", "signature"],
1091
+ "Maven signing credentials are incomplete or not exact environment expressions"
1092
+ );
1093
+ }
1094
+ return void 0;
1095
+ }
1096
+ function warnForUnrepresentableCredentials(rawPublication, resolvedPublication, rawPath, state, index) {
1097
+ const rawHasCredential = ["username", "password", "token", "apiKey"].some(
1098
+ (field) => rawPublication?.[field] !== void 0
1099
+ ) || rawPublication?.signature !== void 0;
1100
+ if (rawHasCredential || hasAnyResolvedCredential(resolvedPublication)) {
1101
+ addCredentialDiagnostic(
1102
+ state,
1103
+ rawPath,
1104
+ ["targets", index, "output", "publish"],
1105
+ "This registry does not support credentials in public SDK Config v1"
1106
+ );
1107
+ }
1108
+ }
1109
+ function warnForUnexpectedCredentialFields(rawPublication, resolvedPublication, allowedFields, rawPath, state, index, allowSignature = false) {
1110
+ const credentialFields = ["username", "password", "token", "apiKey"];
1111
+ const unexpectedFields = credentialFields.filter(
1112
+ (field) => !allowedFields.includes(field) && (rawPublication?.[field] !== void 0 || hasResolvedCredential(resolvedPublication, field))
1113
+ );
1114
+ const hasUnexpectedSignature = !allowSignature && (rawPublication?.signature !== void 0 || resolvedPublication.signature !== void 0);
1115
+ if (unexpectedFields.length > 0 || hasUnexpectedSignature) {
1116
+ addCredentialDiagnostic(
1117
+ state,
1118
+ rawPath,
1119
+ ["targets", index, "output", "publish"],
1120
+ "Fern publishing credentials or signing material include fields unsupported by this registry"
1121
+ );
1122
+ }
1123
+ }
1124
+ function hasResolvedCredential(value, field) {
1125
+ return resolvedCredentialValue(value, field) !== void 0;
1126
+ }
1127
+ function resolvedCredentialValue(value, field) {
1128
+ return stringValue(value[field]) ?? (isObject(value.credentials) ? stringValue(value.credentials[field]) : void 0);
1129
+ }
1130
+ function hasAnyResolvedCredential(value) {
1131
+ return ["username", "password", "token", "apiKey"].some(
1132
+ (field) => hasResolvedCredential(value, field)
1133
+ ) || value.signature !== void 0;
1134
+ }
1135
+ function isEnvironmentExpression(value) {
1136
+ return typeof value === "string" && /^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(value);
1137
+ }
1138
+ function addCredentialDiagnostic(state, path, sdkConfigPath, reason) {
1139
+ state.credentialDiagnostics?.push({
1140
+ code: "FERN_OUTPUT_CREDENTIAL_OMITTED",
1141
+ severity: "warning",
1142
+ path,
1143
+ reason,
1144
+ sdkConfigPath,
1145
+ suggestedAction: `Configure ${sdkConfigPath.join(".")} with an environment expression such as \${CREDENTIAL_ENV_VAR}.`
1146
+ });
843
1147
  }
844
1148
  function publicationRegistry(type, language, sourcePath, index) {
845
1149
  if (type === "postman") {
@@ -947,6 +1251,7 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
947
1251
  return {
948
1252
  ...mapping,
949
1253
  unsupportedFields: [
1254
+ ...state.credentialDiagnostics ?? [],
950
1255
  ...hasCredentials ? [
951
1256
  {
952
1257
  code: "FERN_OUTPUT_CREDENTIAL_UNSUPPORTED",
@@ -1176,12 +1481,6 @@ var sdkConfigV1PublishRegistrySchema = zod.z.enum([
1176
1481
  "go",
1177
1482
  "composer"
1178
1483
  ]);
1179
- var registryCredentialsSchema = zod.z.strictObject({
1180
- username: nonEmptyStringSchema.optional(),
1181
- password: nonEmptyStringSchema.optional(),
1182
- token: nonEmptyStringSchema.optional(),
1183
- apiKey: nonEmptyStringSchema.optional()
1184
- });
1185
1484
  var mavenSignatureSchema = zod.z.strictObject({
1186
1485
  keyId: nonEmptyStringSchema,
1187
1486
  password: nonEmptyStringSchema,
@@ -1189,23 +1488,35 @@ var mavenSignatureSchema = zod.z.strictObject({
1189
1488
  });
1190
1489
  var commonPublishShape = {
1191
1490
  url: nonEmptyStringSchema.optional(),
1192
- /** Raw registry credentials. These values can be sensitive and must be handled as secrets. */
1193
- credentials: registryCredentialsSchema.optional(),
1194
1491
  releaseBranch: nonEmptyStringSchema.optional(),
1195
1492
  tolerateRepublish: zod.z.boolean().optional()
1196
1493
  };
1197
1494
  var sdkConfigV1PublishConfigSchema = zod.z.discriminatedUnion("registry", [
1198
- zod.z.strictObject({ registry: zod.z.literal("npm"), ...commonPublishShape }),
1199
- zod.z.strictObject({ registry: zod.z.literal("pypi"), ...commonPublishShape }),
1495
+ zod.z.strictObject({
1496
+ registry: zod.z.literal("npm"),
1497
+ token: nonEmptyStringSchema.optional(),
1498
+ ...commonPublishShape
1499
+ }),
1500
+ zod.z.strictObject({
1501
+ registry: zod.z.literal("pypi"),
1502
+ username: nonEmptyStringSchema.optional(),
1503
+ password: nonEmptyStringSchema.optional(),
1504
+ ...commonPublishShape
1505
+ }),
1200
1506
  zod.z.strictObject({
1201
1507
  registry: zod.z.literal("maven"),
1202
- /** Raw Maven signing material. These values can be sensitive and must be handled as secrets. */
1508
+ username: nonEmptyStringSchema.optional(),
1509
+ password: nonEmptyStringSchema.optional(),
1203
1510
  signature: mavenSignatureSchema.optional(),
1204
1511
  ...commonPublishShape
1205
1512
  }),
1206
1513
  zod.z.strictObject({ registry: zod.z.literal("nuget"), ...commonPublishShape }),
1207
1514
  zod.z.strictObject({ registry: zod.z.literal("rubygems"), ...commonPublishShape }),
1208
- zod.z.strictObject({ registry: zod.z.literal("crates"), ...commonPublishShape }),
1515
+ zod.z.strictObject({
1516
+ registry: zod.z.literal("crates"),
1517
+ token: nonEmptyStringSchema.optional(),
1518
+ ...commonPublishShape
1519
+ }),
1209
1520
  zod.z.strictObject({ registry: zod.z.literal("go"), ...commonPublishShape }),
1210
1521
  zod.z.strictObject({ registry: zod.z.literal("composer"), ...commonPublishShape })
1211
1522
  ]);
@@ -1213,7 +1524,12 @@ var reviewersSchema = zod.z.strictObject({
1213
1524
  teams: zod.z.array(nonEmptyStringSchema).optional(),
1214
1525
  users: zod.z.array(nonEmptyStringSchema).optional()
1215
1526
  });
1216
- var githubCredentialsSchema = registryCredentialsSchema;
1527
+ var githubCredentialsSchema = zod.z.strictObject({
1528
+ username: nonEmptyStringSchema.optional(),
1529
+ password: nonEmptyStringSchema.optional(),
1530
+ token: nonEmptyStringSchema.optional(),
1531
+ apiKey: nonEmptyStringSchema.optional()
1532
+ });
1217
1533
  var githubOutputSchema = zod.z.strictObject({
1218
1534
  repository: nonEmptyStringSchema,
1219
1535
  host: nonEmptyStringSchema.optional(),
@@ -1730,7 +2046,7 @@ function mapFernConfigToSdkConfigV1(input) {
1730
2046
  const mapped = input.group.generators.map((generator, index) => {
1731
2047
  const language = languages[index];
1732
2048
  const invocation = mapInvocation(generator, language, activeLanguages, index);
1733
- const outputMapping = generator.output ? { output: generator.output, unsupportedFields: [] } : mapOutput(generator, language, index);
2049
+ const outputMapping = mapOutput(generator, language, index);
1734
2050
  return {
1735
2051
  generator,
1736
2052
  language,
@@ -1789,6 +2105,7 @@ function mapFernConfigToSdkConfigV1(input) {
1789
2105
  source: input.source,
1790
2106
  ...optional("sdkVersion", input.sdkVersion),
1791
2107
  ...optional("apiVersion", input.apiVersion),
2108
+ ...optional("replay", input.replay),
1792
2109
  ...optionalObject("api", api),
1793
2110
  ...optionalObject("client", clients.shared),
1794
2111
  ...optionalObject("docs", docs.shared),
@@ -2119,7 +2436,7 @@ function mapLanguageConfig(language, config, state, packageConfig, basePath) {
2119
2436
  case "rust":
2120
2437
  return mapRust(config, state, packageConfig, basePath);
2121
2438
  case "swift":
2122
- return compact({ moduleName: takeString(config, ["moduleName"], state, basePath) });
2439
+ return mapSwift(config, state, basePath);
2123
2440
  case "cli":
2124
2441
  return mapCli(config, state, packageConfig, basePath);
2125
2442
  case "terraform":
@@ -2286,6 +2603,12 @@ function mapRust(config, state, packageConfig, basePath) {
2286
2603
  defaultFeatures: takeStringArray(config, ["defaultFeatures"], state, basePath)
2287
2604
  });
2288
2605
  }
2606
+ function mapSwift(config, state, basePath) {
2607
+ return compact({
2608
+ moduleName: takeString(config, ["moduleName"], state, basePath),
2609
+ nullableAsOptional: takeBoolean(config, ["nullableAsOptional"], state, basePath)
2610
+ });
2611
+ }
2289
2612
  function mapCli(config, state, packageConfig, basePath) {
2290
2613
  const identity = takeObject(config, ["packageIdentity"], state, basePath);
2291
2614
  if (identity) {
@@ -2589,6 +2912,7 @@ exports.sdkConfigV1SwiftGenerationConfigSchema = swiftGenerationConfigSchema;
2589
2912
  exports.sdkConfigV1TargetSchema = sdkConfigV1TargetSchema;
2590
2913
  exports.sdkConfigV1TerraformGenerationConfigSchema = terraformGenerationConfigSchema;
2591
2914
  exports.sdkConfigV1TypescriptGenerationConfigSchema = typescriptGenerationConfigSchema;
2915
+ exports.sdkConfigV1WebhookSignatureSchema = sdkConfigV1WebhookSignatureSchema;
2592
2916
  exports.splitSdkConfigV1TargetGeneration = splitSdkConfigV1TargetGeneration;
2593
2917
  exports.validateSdkConfigV1 = validateSdkConfigV1;
2594
2918
  //# sourceMappingURL=index.cjs.map