@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.
package/dist/index.cjs CHANGED
@@ -34,6 +34,59 @@ var jsonValueSchema = zod.z.lazy(
34
34
  ])
35
35
  );
36
36
  var jsonObjectSchema = 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"]);
750
- }
751
- if (password) {
752
- credentials.password = password;
753
- consume(state, [...sourcePath, "password"]);
754
- }
755
- if (token) {
756
- credentials.token = token;
757
- consume(state, [...sourcePath, "token"]);
758
- }
759
- if (apiKey) {
760
- credentials.apiKey = apiKey;
761
- consume(state, [...sourcePath, "apiKey"]);
762
- }
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 };
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]);
826
+ }
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
+ }
833
+ }
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
+ }
840
+ }
841
+ if (isObject(value.signature)) {
842
+ consume(state, [...sourcePath, "signature"]);
843
+ }
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) {
@@ -2721,7 +3044,7 @@ var credentialResolutionSchema = zod.z.enum([
2721
3044
  "resolved-by-orchestrator",
2722
3045
  "resolved-by-fiddle"
2723
3046
  ]);
2724
- var registryCredentialsSchema2 = zod.z.strictObject({
3047
+ var registryCredentialsSchema = zod.z.strictObject({
2725
3048
  username: nonEmptyStringSchema.optional(),
2726
3049
  password: nonEmptyStringSchema.optional(),
2727
3050
  token: nonEmptyStringSchema.optional(),
@@ -2732,7 +3055,7 @@ var commonPublishShape2 = {
2732
3055
  /** Reference to registry publishing credentials. */
2733
3056
  credentialsRef: nonEmptyStringSchema.optional(),
2734
3057
  /** Raw registry credentials. These values can be sensitive and must be handled as secrets. */
2735
- credentials: registryCredentialsSchema2.optional(),
3058
+ credentials: registryCredentialsSchema.optional(),
2736
3059
  /**
2737
3060
  * Registry-specific package version override. If omitted, the external publisher/orchestrator may
2738
3061
  * fall back to target.sdkVersion.
@@ -2837,7 +3160,7 @@ var githubOutputSchema2 = zod.z.strictObject({
2837
3160
  /** Reference to GitHub credentials. */
2838
3161
  credentialsRef: nonEmptyStringSchema.optional(),
2839
3162
  /** Raw GitHub credentials. These values can be sensitive and must be handled as secrets. */
2840
- credentials: registryCredentialsSchema2.optional(),
3163
+ credentials: registryCredentialsSchema.optional(),
2841
3164
  privateRepository: zod.z.boolean().optional(),
2842
3165
  /** GitHub license block scoped to repository delivery. */
2843
3166
  license: githubLicenseSchema.optional(),
@@ -3160,6 +3483,7 @@ exports.sdkConfigV1SwiftGenerationConfigSchema = swiftGenerationConfigSchema;
3160
3483
  exports.sdkConfigV1TargetSchema = sdkConfigV1TargetSchema;
3161
3484
  exports.sdkConfigV1TerraformGenerationConfigSchema = terraformGenerationConfigSchema;
3162
3485
  exports.sdkConfigV1TypescriptGenerationConfigSchema = typescriptGenerationConfigSchema;
3486
+ exports.sdkConfigV1WebhookSignatureSchema = sdkConfigV1WebhookSignatureSchema;
3163
3487
  exports.sourceConfigSchema = sourceConfigSchema;
3164
3488
  exports.sourceSpecConfigSchema = sourceSpecConfigSchema;
3165
3489
  exports.sourceSpecTypeSchema = sourceSpecTypeSchema;
@@ -3171,5 +3495,6 @@ exports.terraformGenerationConfigSchema = terraformGenerationConfigSchema;
3171
3495
  exports.typescriptGenerationConfigSchema = typescriptGenerationConfigSchema;
3172
3496
  exports.unsupportedFieldSchema = unsupportedFieldSchema;
3173
3497
  exports.validateSdkConfigV1 = validateSdkConfigV1;
3498
+ exports.webhookSignatureSchema = webhookSignatureSchema;
3174
3499
  //# sourceMappingURL=index.cjs.map
3175
3500
  //# sourceMappingURL=index.cjs.map