@postman/sdk-config 0.10.1 → 0.11.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/README.md +6 -0
- package/dist/index.cjs +697 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +683 -35
- package/dist/index.js.map +1 -1
- package/dist/sdk-config/index.cjs +649 -34
- package/dist/sdk-config/index.cjs.map +1 -1
- package/dist/sdk-config/index.d.cts +2 -2
- package/dist/sdk-config/index.d.ts +2 -2
- package/dist/sdk-config/index.js +642 -35
- package/dist/sdk-config/index.js.map +1 -1
- package/dist/sdk-config/v1/index.cjs +649 -34
- package/dist/sdk-config/v1/index.cjs.map +1 -1
- package/dist/sdk-config/v1/index.d.cts +2858 -2377
- package/dist/sdk-config/v1/index.d.ts +2858 -2377
- package/dist/sdk-config/v1/index.js +642 -35
- package/dist/sdk-config/v1/index.js.map +1 -1
- package/dist/sdk-config-ir/index.cjs +247 -4
- package/dist/sdk-config-ir/index.cjs.map +1 -1
- package/dist/sdk-config-ir/index.d.cts +2 -2
- package/dist/sdk-config-ir/index.d.ts +2 -2
- package/dist/sdk-config-ir/index.js +241 -5
- package/dist/sdk-config-ir/index.js.map +1 -1
- package/dist/sdk-config-ir/v1/index.cjs +247 -4
- package/dist/sdk-config-ir/v1/index.cjs.map +1 -1
- package/dist/sdk-config-ir/v1/index.d.cts +3109 -2960
- package/dist/sdk-config-ir/v1/index.d.ts +3109 -2960
- package/dist/sdk-config-ir/v1/index.js +241 -5
- package/dist/sdk-config-ir/v1/index.js.map +1 -1
- package/dist/{typescript-Chge0X4f.d.cts → typescript-CsAa1VSy.d.cts} +81 -1
- package/dist/{typescript-Chge0X4f.d.ts → typescript-CsAa1VSy.d.ts} +81 -1
- package/package.json +1 -1
- package/src/sdk-config/v1/README.md +183 -1
- package/src/sdk-config-ir/v1/README.md +29 -1
|
@@ -33,7 +33,7 @@ var jsonValueSchema = zod.z.lazy(
|
|
|
33
33
|
zod.z.record(zod.z.string(), jsonValueSchema)
|
|
34
34
|
])
|
|
35
35
|
);
|
|
36
|
-
zod.z.record(zod.z.string(), jsonValueSchema);
|
|
36
|
+
var jsonObjectSchema = zod.z.record(zod.z.string(), jsonValueSchema);
|
|
37
37
|
var hashAlgorithmSchema = zod.z.enum(["sha1", "sha256", "sha384", "sha512"]);
|
|
38
38
|
var encodingSchema = zod.z.enum(["base64", "hex"]);
|
|
39
39
|
var payloadComponentSchema = zod.z.enum(["body", "timestamp", "notification-url", "message-id"]);
|
|
@@ -131,13 +131,21 @@ var oauthScopeSchema = zod.z.strictObject({
|
|
|
131
131
|
name: nonEmptyStringSchema.describe("The OAuth scope value requested from the provider."),
|
|
132
132
|
description: zod.z.string().optional().describe("A description of the OAuth scope included in generated SDK documentation.")
|
|
133
133
|
});
|
|
134
|
+
var publicClientIdSchema = nonEmptyStringSchema.refine((value) => value.trim() === value, {
|
|
135
|
+
message: "must not have leading or trailing whitespace"
|
|
136
|
+
}).refine((value) => !value.includes("${"), {
|
|
137
|
+
message: "must be a literal public client ID, not an environment expression"
|
|
138
|
+
});
|
|
134
139
|
var oauthFlowSchema = zod.z.discriminatedUnion("type", [
|
|
135
140
|
zod.z.strictObject({
|
|
136
141
|
type: zod.z.literal("authorization-code").describe("Uses the OAuth authorization code flow."),
|
|
137
142
|
authorizationUrl: nonEmptyStringSchema.describe("The URL used to authorize the client."),
|
|
138
143
|
tokenUrl: nonEmptyStringSchema.describe("The URL used to exchange a code for tokens."),
|
|
139
144
|
refreshUrl: nonEmptyStringSchema.optional().describe("The URL used to refresh access tokens."),
|
|
140
|
-
scopes: zod.z.array(oauthScopeSchema).optional().describe("The scopes supported by this flow.")
|
|
145
|
+
scopes: zod.z.array(oauthScopeSchema).optional().describe("The scopes supported by this flow."),
|
|
146
|
+
clientId: publicClientIdSchema.optional().describe(
|
|
147
|
+
"The public, non-secret OAuth client ID that generated interactive login flows, such as CLI browser login with PKCE, send to the authorization and token endpoints. It is embedded verbatim in generated code, so it must never be a client secret."
|
|
148
|
+
)
|
|
141
149
|
}),
|
|
142
150
|
zod.z.strictObject({
|
|
143
151
|
type: zod.z.literal("client-credentials").describe("Uses the OAuth client credentials flow."),
|
|
@@ -453,8 +461,102 @@ var packageConfigSchema = zod.z.strictObject({
|
|
|
453
461
|
projectUrls: zod.z.array(projectUrlSchema).optional().describe("Labeled project links for package metadata."),
|
|
454
462
|
extraDependencies: zod.z.array(dependencySchema).optional().describe("Additional runtime dependencies added to the generated package."),
|
|
455
463
|
extraDevDependencies: zod.z.array(dependencySchema).optional().describe("Additional development dependencies added to the generated package."),
|
|
456
|
-
extraPeerDependencies: zod.z.array(dependencySchema).optional().describe("Additional peer dependencies added to the generated package.")
|
|
464
|
+
extraPeerDependencies: zod.z.array(dependencySchema).optional().describe("Additional peer dependencies added to the generated package."),
|
|
465
|
+
extraPeerDependenciesMeta: zod.z.record(nonEmptyStringSchema, jsonObjectSchema).optional().describe(
|
|
466
|
+
"npm peerDependenciesMeta entries keyed by peer dependency name, such as { optional: true }."
|
|
467
|
+
)
|
|
468
|
+
});
|
|
469
|
+
var GITHUB_ACTIONS_SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/;
|
|
470
|
+
var GITHUB_REPOSITORY_SLUG_PATTERN = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
471
|
+
var HOMEBREW_FORMULA_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
472
|
+
var githubActionsSecretNameSchema = zod.z.string({ error: "must be the name of a GitHub Actions secret" }).regex(GITHUB_ACTIONS_SECRET_NAME_PATTERN, {
|
|
473
|
+
error: "must be the name of a GitHub Actions secret: start with an uppercase letter and contain only A-Z, 0-9, or _. Secret values and ${...} expressions are not accepted."
|
|
474
|
+
}).refine((value) => value !== "GITHUB_TOKEN", {
|
|
475
|
+
error: "GITHUB_TOKEN cannot be used: it is the workflow's built-in token, scoped to the generated repository. Store the credential under a different secret name."
|
|
476
|
+
});
|
|
477
|
+
var githubRepositorySlugSchema = zod.z.string({ error: 'must be a GitHub repository in "<owner>/<repo>" form' }).regex(GITHUB_REPOSITORY_SLUG_PATTERN, {
|
|
478
|
+
error: 'must be a GitHub repository in "<owner>/<repo>" form, for example "acme/homebrew-tap"'
|
|
479
|
+
});
|
|
480
|
+
var homebrewFormulaNameSchema = zod.z.string({ error: "must be a Homebrew formula name" }).regex(HOMEBREW_FORMULA_NAME_PATTERN, {
|
|
481
|
+
error: "must be a Homebrew formula name: start with a lowercase letter and contain only a-z, 0-9, or -"
|
|
457
482
|
});
|
|
483
|
+
var cliDistributionGithubAppSchema = zod.z.strictObject({
|
|
484
|
+
appIdSecretName: githubActionsSecretNameSchema.describe(
|
|
485
|
+
"The name of the GitHub Actions secret holding the GitHub App ID or client ID."
|
|
486
|
+
),
|
|
487
|
+
privateKeySecretName: githubActionsSecretNameSchema.describe(
|
|
488
|
+
"The name of the GitHub Actions secret holding the GitHub App private key in PEM form."
|
|
489
|
+
)
|
|
490
|
+
});
|
|
491
|
+
var channelTokenSecretNameDescription = "The name of the GitHub Actions secret holding a token with write access to the channel repository. Takes precedence over githubApp for this channel.";
|
|
492
|
+
var cliDistributionHomebrewSchema = zod.z.strictObject({
|
|
493
|
+
tap: githubRepositorySlugSchema.describe(
|
|
494
|
+
'The Homebrew tap repository in "<owner>/<repo>" form that receives the formula.'
|
|
495
|
+
),
|
|
496
|
+
formula: homebrewFormulaNameSchema.optional().describe("The Homebrew formula name; the generator defaults it to the CLI binary name."),
|
|
497
|
+
tokenSecretName: githubActionsSecretNameSchema.optional().describe(channelTokenSecretNameDescription)
|
|
498
|
+
});
|
|
499
|
+
var cliDistributionScoopSchema = zod.z.strictObject({
|
|
500
|
+
bucket: githubRepositorySlugSchema.describe(
|
|
501
|
+
'The Scoop bucket repository in "<owner>/<repo>" form that receives the manifest.'
|
|
502
|
+
),
|
|
503
|
+
tokenSecretName: githubActionsSecretNameSchema.optional().describe(channelTokenSecretNameDescription)
|
|
504
|
+
});
|
|
505
|
+
var cliDistributionConfigSchema = zod.z.strictObject({
|
|
506
|
+
githubApp: cliDistributionGithubAppSchema.optional().describe(
|
|
507
|
+
"A GitHub App used to mint short-lived tokens for every channel without its own tokenSecretName."
|
|
508
|
+
),
|
|
509
|
+
homebrew: cliDistributionHomebrewSchema.optional().describe("Publishes a Homebrew formula to a tap repository on each tagged release."),
|
|
510
|
+
scoop: cliDistributionScoopSchema.optional().describe("Publishes a Scoop manifest to a bucket repository on each tagged release.")
|
|
511
|
+
}).superRefine((distribution, context) => {
|
|
512
|
+
if (distribution.homebrew !== void 0 || distribution.scoop !== void 0) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (distribution.githubApp !== void 0) {
|
|
516
|
+
context.addIssue({
|
|
517
|
+
code: "custom",
|
|
518
|
+
message: "githubApp requires at least one distribution channel: homebrew or scoop",
|
|
519
|
+
path: ["githubApp"]
|
|
520
|
+
});
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
context.addIssue({
|
|
524
|
+
code: "custom",
|
|
525
|
+
message: "distribution must configure at least one channel: homebrew or scoop"
|
|
526
|
+
});
|
|
527
|
+
});
|
|
528
|
+
var CLI_DISTRIBUTION_REQUIRES_GITHUB_DELIVERY_MESSAGE = 'distribution requires output.delivery "github": Homebrew and Scoop publish from a tagged GitHub Release produced by the generated release workflow. Set delivery to "github" or remove distribution.';
|
|
529
|
+
var CLI_PUBLISH_REQUIRES_GITHUB_DELIVERY_MESSAGE = 'package publication for target language "cli" requires output.delivery "github": the CLI generator publishes npm packages only from its generated GitHub workflow.';
|
|
530
|
+
var CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE = "CLI_DISTRIBUTION_NON_RELEASE_MODE";
|
|
531
|
+
var nonReleaseGithubModes = /* @__PURE__ */ new Set(["pull-request", "push", "commit"]);
|
|
532
|
+
function cliDistributionModeDiagnostic(output, outputPath) {
|
|
533
|
+
const mode = output?.github?.mode;
|
|
534
|
+
if (output?.distribution === void 0 || mode === void 0 || !nonReleaseGithubModes.has(mode)) {
|
|
535
|
+
return void 0;
|
|
536
|
+
}
|
|
537
|
+
return {
|
|
538
|
+
code: CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE,
|
|
539
|
+
severity: "warning",
|
|
540
|
+
path: [...outputPath, "github", "mode"],
|
|
541
|
+
reason: `GitHub mode "${mode}" does not create a release tag, so Homebrew and Scoop publish only after a semantic-version tag is pushed to the repository.`,
|
|
542
|
+
suggestedAction: 'Use mode "release" or "commit-and-release", or push a version tag after merging generated changes.'
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// src/sdk-config/v1/diagnostics.ts
|
|
547
|
+
function getSdkConfigV1Diagnostics(config) {
|
|
548
|
+
return config.targets.flatMap((target, targetIndex) => {
|
|
549
|
+
if (target.language !== "cli") {
|
|
550
|
+
return [];
|
|
551
|
+
}
|
|
552
|
+
const diagnostic = cliDistributionModeDiagnostic(target.output, [
|
|
553
|
+
"targets",
|
|
554
|
+
targetIndex,
|
|
555
|
+
"output"
|
|
556
|
+
]);
|
|
557
|
+
return diagnostic ? [diagnostic] : [];
|
|
558
|
+
});
|
|
559
|
+
}
|
|
458
560
|
var httpMethodSchema = zod.z.enum([
|
|
459
561
|
"GET",
|
|
460
562
|
"POST",
|
|
@@ -659,6 +761,17 @@ function stringValue(value) {
|
|
|
659
761
|
function stringArrayValue(value) {
|
|
660
762
|
return Array.isArray(value) && value.every((item) => typeof item === "string" && item.length > 0) ? value : void 0;
|
|
661
763
|
}
|
|
764
|
+
var canonicalLicenseTypes = {
|
|
765
|
+
mit: "MIT",
|
|
766
|
+
apache: "APACHE",
|
|
767
|
+
"apache-2.0": "APACHE",
|
|
768
|
+
"gpl-3.0": "GPL3",
|
|
769
|
+
"gpl-3.0-only": "GPL3",
|
|
770
|
+
unlicensed: "UNLICENSED"
|
|
771
|
+
};
|
|
772
|
+
function canonicalLicenseType(value) {
|
|
773
|
+
return canonicalLicenseTypes[value.trim().toLowerCase()];
|
|
774
|
+
}
|
|
662
775
|
function stableJson(value) {
|
|
663
776
|
return JSON.stringify(sortKeys(value));
|
|
664
777
|
}
|
|
@@ -669,6 +782,280 @@ function sortKeys(value) {
|
|
|
669
782
|
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => [key, sortKeys(child)])
|
|
670
783
|
);
|
|
671
784
|
}
|
|
785
|
+
var ALPHANUMERIC_PATTERN = /[A-Za-z0-9]/;
|
|
786
|
+
var ROOT_GROUP_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
787
|
+
var KEBAB_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
788
|
+
var DOTTED_COMMAND_PATH_PATTERN = /^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;
|
|
789
|
+
var FIELD_NAME_PATTERN = /^[A-Za-z0-9_.-]+$/;
|
|
790
|
+
var RESERVED_USER_AGENT_SUFFIX_FLAGS = /* @__PURE__ */ new Set([
|
|
791
|
+
"params",
|
|
792
|
+
"output",
|
|
793
|
+
"json",
|
|
794
|
+
"format",
|
|
795
|
+
"dry-run",
|
|
796
|
+
"base-url",
|
|
797
|
+
"page-all",
|
|
798
|
+
"page-limit",
|
|
799
|
+
"page-delay",
|
|
800
|
+
"no-pager",
|
|
801
|
+
"no-extract",
|
|
802
|
+
"no-retry",
|
|
803
|
+
"no-stream",
|
|
804
|
+
"quiet",
|
|
805
|
+
"query",
|
|
806
|
+
"help",
|
|
807
|
+
"debug",
|
|
808
|
+
"schema"
|
|
809
|
+
]);
|
|
810
|
+
var RESERVED_PROFILES_COMMAND_NAMES = /* @__PURE__ */ new Set([
|
|
811
|
+
"auth",
|
|
812
|
+
"completion",
|
|
813
|
+
"man",
|
|
814
|
+
"errors",
|
|
815
|
+
"generate-skills",
|
|
816
|
+
"help"
|
|
817
|
+
]);
|
|
818
|
+
var binaryNameSchema = nonEmptyStringSchema.regex(ALPHANUMERIC_PATTERN, {
|
|
819
|
+
message: "binaryName must contain at least one ASCII letter or digit"
|
|
820
|
+
});
|
|
821
|
+
var rootGroupSchema = zod.z.string().regex(ROOT_GROUP_PATTERN, {
|
|
822
|
+
message: "rootGroup must start with a lowercase letter and contain only lowercase letters, digits, hyphens, and underscores"
|
|
823
|
+
});
|
|
824
|
+
var userAgentSuffixFlagSchema = zod.z.string().superRefine((value, context) => {
|
|
825
|
+
if (value.startsWith("-")) {
|
|
826
|
+
context.addIssue({
|
|
827
|
+
code: "custom",
|
|
828
|
+
message: 'userAgentSuffixFlag must be the long flag name without the leading "--"'
|
|
829
|
+
});
|
|
830
|
+
} else if (!KEBAB_NAME_PATTERN.test(value)) {
|
|
831
|
+
context.addIssue({
|
|
832
|
+
code: "custom",
|
|
833
|
+
message: "userAgentSuffixFlag must start with a lowercase letter and contain only lowercase letters, digits, and hyphens"
|
|
834
|
+
});
|
|
835
|
+
} else if (RESERVED_USER_AGENT_SUFFIX_FLAGS.has(value)) {
|
|
836
|
+
context.addIssue({
|
|
837
|
+
code: "custom",
|
|
838
|
+
message: `userAgentSuffixFlag "${value}" collides with a built-in global flag`
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
});
|
|
842
|
+
var profilesCommandNameSchema = zod.z.string().superRefine((value, context) => {
|
|
843
|
+
if (!KEBAB_NAME_PATTERN.test(value)) {
|
|
844
|
+
context.addIssue({
|
|
845
|
+
code: "custom",
|
|
846
|
+
message: "profiles.commandName must start with a lowercase letter and contain only lowercase letters, digits, and hyphens"
|
|
847
|
+
});
|
|
848
|
+
} else if (RESERVED_PROFILES_COMMAND_NAMES.has(value)) {
|
|
849
|
+
context.addIssue({
|
|
850
|
+
code: "custom",
|
|
851
|
+
message: `profiles.commandName "${value}" collides with a built-in command group`
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
function dottedCommandPathSchema(field) {
|
|
856
|
+
return zod.z.string().regex(DOTTED_COMMAND_PATH_PATTERN, {
|
|
857
|
+
message: `${field} must be a dotted command path such as "iam.keys.create"`
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
function fieldNameMapSchema(field) {
|
|
861
|
+
const message = `${field} keys and values must be field names containing only [A-Za-z0-9_.-]`;
|
|
862
|
+
return zod.z.record(zod.z.string(), zod.z.string().regex(FIELD_NAME_PATTERN, { message })).superRefine((value, context) => {
|
|
863
|
+
for (const key of Object.keys(value)) {
|
|
864
|
+
if (!FIELD_NAME_PATTERN.test(key)) {
|
|
865
|
+
context.addIssue({ code: "custom", message, path: [key] });
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
var profilesProvisionOperationSchema = zod.z.strictObject({
|
|
871
|
+
operation: dottedCommandPathSchema("profiles.provisionOperation.operation").describe(
|
|
872
|
+
"The dotted command path of the operation that mints a profile credential."
|
|
873
|
+
),
|
|
874
|
+
credential: fieldNameMapSchema("profiles.provisionOperation.credential").refine((value) => Object.keys(value).length > 0, {
|
|
875
|
+
message: "profiles.provisionOperation.credential must map at least one credential field"
|
|
876
|
+
}).describe("Maps each stored credential field to the response field that supplies it."),
|
|
877
|
+
revokeParameters: fieldNameMapSchema("profiles.provisionOperation.revokeParameters").optional().describe("Maps each revoke-operation parameter to the response field that supplies it.")
|
|
878
|
+
});
|
|
879
|
+
var profilesConfigSchema = zod.z.strictObject({
|
|
880
|
+
enabled: zod.z.boolean().describe("Whether the CLI emits profile commands and the global --profile flag."),
|
|
881
|
+
commandName: profilesCommandNameSchema.optional().describe('The profile command group name. The generator defaults to "profiles".'),
|
|
882
|
+
revokeOperation: dottedCommandPathSchema("profiles.revokeOperation").optional().describe('The dotted command path called by "profiles remove --revoke".'),
|
|
883
|
+
provisionOperation: profilesProvisionOperationSchema.optional().describe('The operation called by "profiles create --provision" and its response mapping.')
|
|
884
|
+
});
|
|
885
|
+
var cliGenerationConfigSchema = zod.z.strictObject({
|
|
886
|
+
paginationParameters: zod.z.array(nonEmptyStringSchema).optional().describe("Request parameter names treated as pagination controls by the CLI."),
|
|
887
|
+
skills: zod.z.boolean().optional().describe("Whether the generated CLI includes skills that teach AI agents to invoke commands."),
|
|
888
|
+
binaryName: binaryNameSchema.optional().describe(
|
|
889
|
+
"The CLI executable name. The generator kebab-cases it and also uses it for the source directory and env-var prefix."
|
|
890
|
+
),
|
|
891
|
+
customCommands: zod.z.boolean().optional().describe("Whether hand-written command support is generated. The generator defaults to true."),
|
|
892
|
+
rootGroup: rootGroupSchema.optional().describe("A command group that every spec-derived command is nested under."),
|
|
893
|
+
profiles: profilesConfigSchema.optional().describe("Named profile command configuration."),
|
|
894
|
+
splitTypeCrates: zod.z.boolean().optional().describe("Whether generated types are split into one crate per API behind a facade crate."),
|
|
895
|
+
userAgentSuffixFlag: userAgentSuffixFlagSchema.optional().describe('The long flag name, without "--", that appends a product token to the User-Agent.')
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
// src/sdk-config/v1/fern-config-mapper-cli.ts
|
|
899
|
+
var CLI_GENERATION_FIELDS = [
|
|
900
|
+
"binaryName",
|
|
901
|
+
"customCommands",
|
|
902
|
+
"rootGroup",
|
|
903
|
+
"profiles",
|
|
904
|
+
"splitTypeCrates",
|
|
905
|
+
"userAgentSuffixFlag"
|
|
906
|
+
];
|
|
907
|
+
var PROFILES_FIELDS = ["enabled", "commandName", "revokeOperation"];
|
|
908
|
+
var PROVISION_OPERATION_FIELDS = ["operation", "credential", "revokeParameters"];
|
|
909
|
+
function mapCliGeneration(config, state, basePath, targetIndex) {
|
|
910
|
+
const generation = {};
|
|
911
|
+
for (const field of CLI_GENERATION_FIELDS) {
|
|
912
|
+
const raw = ownValue(config, field);
|
|
913
|
+
if (raw === void 0) continue;
|
|
914
|
+
const fieldPath = [...basePath, field];
|
|
915
|
+
const { value, consumedPaths } = field === "profiles" && isObject(raw) ? pickProfiles(raw, fieldPath) : { value: raw, consumedPaths: [fieldPath] };
|
|
916
|
+
const parsed = cliGenerationConfigSchema.shape[field].safeParse(value);
|
|
917
|
+
consumedPaths.forEach((path) => consume(state, path));
|
|
918
|
+
if (parsed.success) {
|
|
919
|
+
generation[field] = structuredClone(value);
|
|
920
|
+
continue;
|
|
921
|
+
}
|
|
922
|
+
const diagnostics = parsed.error.issues.map(
|
|
923
|
+
(issue) => invalidValueDiagnostic(field, fieldPath, issue.path, issue.message, targetIndex)
|
|
924
|
+
);
|
|
925
|
+
(state.valueDiagnostics ??= []).push(...diagnostics);
|
|
926
|
+
}
|
|
927
|
+
return generation;
|
|
928
|
+
}
|
|
929
|
+
function pickProfiles(profiles, path) {
|
|
930
|
+
const picked = pickKnown(profiles, PROFILES_FIELDS, path);
|
|
931
|
+
const provisionOperation = ownValue(profiles, "provisionOperation");
|
|
932
|
+
const provisionPath = [...path, "provisionOperation"];
|
|
933
|
+
if (isObject(provisionOperation)) {
|
|
934
|
+
const provision = pickKnown(provisionOperation, PROVISION_OPERATION_FIELDS, provisionPath);
|
|
935
|
+
picked.value.provisionOperation = provision.value;
|
|
936
|
+
picked.consumedPaths.push(...provision.consumedPaths);
|
|
937
|
+
} else if (provisionOperation !== void 0) {
|
|
938
|
+
picked.value.provisionOperation = provisionOperation;
|
|
939
|
+
picked.consumedPaths.push(provisionPath);
|
|
940
|
+
}
|
|
941
|
+
return { value: { enabled: false, ...picked.value }, consumedPaths: picked.consumedPaths };
|
|
942
|
+
}
|
|
943
|
+
function pickKnown(value, fields, path) {
|
|
944
|
+
const picked = {};
|
|
945
|
+
const consumedPaths = [];
|
|
946
|
+
for (const field of fields) {
|
|
947
|
+
const child = ownValue(value, field);
|
|
948
|
+
if (child === void 0) continue;
|
|
949
|
+
picked[field] = child;
|
|
950
|
+
consumedPaths.push([...path, field]);
|
|
951
|
+
}
|
|
952
|
+
return { value: picked, consumedPaths };
|
|
953
|
+
}
|
|
954
|
+
function ownValue(value, key) {
|
|
955
|
+
return Object.hasOwn(value, key) ? value[key] : void 0;
|
|
956
|
+
}
|
|
957
|
+
function invalidValueDiagnostic(field, fieldPath, issuePath, message, targetIndex) {
|
|
958
|
+
const relative = issuePath.map((part) => typeof part === "symbol" ? String(part) : part);
|
|
959
|
+
const sdkConfigField = ["targets", targetIndex, "generation", field];
|
|
960
|
+
return {
|
|
961
|
+
code: "FERN_CONFIG_VALUE_INVALID",
|
|
962
|
+
severity: "warning",
|
|
963
|
+
path: [...fieldPath, ...relative],
|
|
964
|
+
reason: `CLI setting ${field} was not migrated because SDK Config rejects it: ${message}`,
|
|
965
|
+
sdkConfigPath: [...sdkConfigField, ...relative],
|
|
966
|
+
suggestedAction: `Correct the value, then set ${sdkConfigField.join(".")} manually.`
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// src/sdk-config/v1/fern-config-mapper-cli-distribution.ts
|
|
971
|
+
var DISTRIBUTION_KEYS = {
|
|
972
|
+
githubApp: { appIdSecret: "appIdSecretName", privateKeySecret: "privateKeySecretName" },
|
|
973
|
+
homebrew: { tap: "tap", formula: "formula", tokenEnvironmentVariable: "tokenSecretName" },
|
|
974
|
+
scoop: { bucket: "bucket", tokenEnvironmentVariable: "tokenSecretName" }
|
|
975
|
+
};
|
|
976
|
+
function mapCliDistribution(config, state, basePath, targetIndex) {
|
|
977
|
+
if (!Object.hasOwn(config, "distribution")) return;
|
|
978
|
+
const raw = config.distribution;
|
|
979
|
+
const path = [...basePath, "distribution"];
|
|
980
|
+
const translated = isObject(raw) ? translateDistribution(raw, path) : { value: raw, consumedPaths: [path], legacyKeys: /* @__PURE__ */ new Map() };
|
|
981
|
+
const parsed = cliDistributionConfigSchema.safeParse(translated.value);
|
|
982
|
+
translated.consumedPaths.forEach((consumedPath) => consume(state, consumedPath));
|
|
983
|
+
if (parsed.success) {
|
|
984
|
+
state.cliDistribution = { value: parsed.data, path };
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
const diagnostics = parsed.error.issues.map(
|
|
988
|
+
(issue) => invalidDistributionDiagnostic(issue, path, translated.legacyKeys, targetIndex)
|
|
989
|
+
);
|
|
990
|
+
const reportedPaths = /* @__PURE__ */ new Set();
|
|
991
|
+
(state.valueDiagnostics ??= []).push(
|
|
992
|
+
...diagnostics.filter(({ path: diagnosticPath }) => {
|
|
993
|
+
const key = diagnosticPath.join(".");
|
|
994
|
+
if (reportedPaths.has(key)) return false;
|
|
995
|
+
reportedPaths.add(key);
|
|
996
|
+
return true;
|
|
997
|
+
})
|
|
998
|
+
);
|
|
999
|
+
}
|
|
1000
|
+
function translateDistribution(distribution, path) {
|
|
1001
|
+
const value = {};
|
|
1002
|
+
const consumedPaths = [];
|
|
1003
|
+
const legacyKeys = /* @__PURE__ */ new Map();
|
|
1004
|
+
for (const [block, keys] of Object.entries(DISTRIBUTION_KEYS)) {
|
|
1005
|
+
if (!Object.hasOwn(distribution, block)) continue;
|
|
1006
|
+
const blockValue = distribution[block];
|
|
1007
|
+
const blockPath = [...path, block];
|
|
1008
|
+
if (!isObject(blockValue)) {
|
|
1009
|
+
value[block] = blockValue;
|
|
1010
|
+
consumedPaths.push(blockPath);
|
|
1011
|
+
continue;
|
|
1012
|
+
}
|
|
1013
|
+
const translatedBlock = {};
|
|
1014
|
+
for (const [legacyKey, sdkConfigKey] of Object.entries(keys)) {
|
|
1015
|
+
if (!Object.hasOwn(blockValue, legacyKey)) continue;
|
|
1016
|
+
translatedBlock[sdkConfigKey] = blockValue[legacyKey];
|
|
1017
|
+
consumedPaths.push([...blockPath, legacyKey]);
|
|
1018
|
+
legacyKeys.set(`${block}.${sdkConfigKey}`, legacyKey);
|
|
1019
|
+
}
|
|
1020
|
+
value[block] = translatedBlock;
|
|
1021
|
+
}
|
|
1022
|
+
return { value, consumedPaths, legacyKeys };
|
|
1023
|
+
}
|
|
1024
|
+
function invalidDistributionDiagnostic(issue, path, legacyKeys, targetIndex) {
|
|
1025
|
+
const relative = issue.path.map((part) => typeof part === "symbol" ? String(part) : part);
|
|
1026
|
+
const [block, field] = relative;
|
|
1027
|
+
const legacyField = typeof block === "string" && typeof field === "string" ? legacyKeys.get(`${block}.${field}`) : void 0;
|
|
1028
|
+
const legacyRelative = typeof block === "string" && legacyField !== void 0 ? [block, legacyField] : relative;
|
|
1029
|
+
const sdkConfigField = ["targets", targetIndex, "output", "distribution"];
|
|
1030
|
+
return {
|
|
1031
|
+
code: "FERN_CONFIG_VALUE_INVALID",
|
|
1032
|
+
severity: "warning",
|
|
1033
|
+
path: [...path, ...legacyRelative],
|
|
1034
|
+
reason: `CLI distribution was not migrated because SDK Config rejects it: ${issue.message}`,
|
|
1035
|
+
sdkConfigPath: [...sdkConfigField, ...relative],
|
|
1036
|
+
suggestedAction: `Correct the value, then set ${sdkConfigField.join(".")} manually.`
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
function applyCliDistribution(output, pending, targetIndex) {
|
|
1040
|
+
if (pending === void 0) return { output, diagnostics: [] };
|
|
1041
|
+
if (output.delivery === "github") {
|
|
1042
|
+
return { output: { ...output, distribution: pending.value }, diagnostics: [] };
|
|
1043
|
+
}
|
|
1044
|
+
const outputPath = ["targets", targetIndex, "output"];
|
|
1045
|
+
return {
|
|
1046
|
+
output,
|
|
1047
|
+
diagnostics: [
|
|
1048
|
+
{
|
|
1049
|
+
code: "FERN_CLI_DISTRIBUTION_REQUIRES_GITHUB_OUTPUT",
|
|
1050
|
+
severity: "warning",
|
|
1051
|
+
path: pending.path,
|
|
1052
|
+
reason: `The CLI generator ignores distribution for "${output.delivery}" output, and SDK Config accepts distribution only with output.delivery "github", so it was not migrated`,
|
|
1053
|
+
sdkConfigPath: [...outputPath, "distribution"],
|
|
1054
|
+
suggestedAction: `Set ${outputPath.join(".")}.delivery to "github" for the CLI repository and add ${outputPath.join(".")}.distribution manually, or remove distribution.`
|
|
1055
|
+
}
|
|
1056
|
+
]
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
672
1059
|
|
|
673
1060
|
// src/sdk-config/v1/fern-config-mapper-output.ts
|
|
674
1061
|
function mapOutput(generator, language, index) {
|
|
@@ -879,11 +1266,10 @@ function githubOutput(value, publishInfo, rawOutput, language, sourcePath, state
|
|
|
879
1266
|
...optionalObject("package", { ...publication?.package, ...licensePackage })
|
|
880
1267
|
};
|
|
881
1268
|
}
|
|
882
|
-
var basicLicenseTypes = { mit: "MIT", apache: "APACHE" };
|
|
883
1269
|
function mapGithubLicense(value, sourcePath, state) {
|
|
884
1270
|
if (!isObject(value) || stringValue(value.type) !== "basic") return {};
|
|
885
1271
|
const id = stringValue(value.id);
|
|
886
|
-
const type = id ?
|
|
1272
|
+
const type = id ? canonicalLicenseType(id) : void 0;
|
|
887
1273
|
if (!type) return {};
|
|
888
1274
|
consume(state, [...sourcePath, "type"]);
|
|
889
1275
|
consume(state, [...sourcePath, "id"]);
|
|
@@ -1450,6 +1836,114 @@ function outputDiagnostic(path, index) {
|
|
|
1450
1836
|
suggestedAction: resolvedGuidance?.suggestedAction ?? "Review this output setting and preserve it outside SDK Config when no equivalent exists."
|
|
1451
1837
|
};
|
|
1452
1838
|
}
|
|
1839
|
+
|
|
1840
|
+
// src/sdk-config/v1/package.ts
|
|
1841
|
+
var sdkConfigV1DependencySchema = dependencySchema;
|
|
1842
|
+
var sdkConfigV1PackageConfigSchema = packageConfigSchema;
|
|
1843
|
+
|
|
1844
|
+
// src/sdk-config/v1/fern-config-mapper-package.ts
|
|
1845
|
+
var emailSchema = zod.z.email();
|
|
1846
|
+
function mapCliPackageIdentity(identity, state, targetIndex) {
|
|
1847
|
+
mapIdentityField(identity, "homepage", stringValue, state);
|
|
1848
|
+
mapIdentityField(identity, "keywords", (value) => stringArrayValue(value)?.slice(), state);
|
|
1849
|
+
mapCargoAuthors(identity, state, targetIndex);
|
|
1850
|
+
mapIdentityField(identity, "license", licenseValue, state);
|
|
1851
|
+
}
|
|
1852
|
+
function mapIdentityField(identity, field, read, state) {
|
|
1853
|
+
const located = locate(identity.value, [field], identity.path);
|
|
1854
|
+
const value = located && read(located.value);
|
|
1855
|
+
if (located && value !== void 0) addPackageFallback(state, field, value, located.path);
|
|
1856
|
+
}
|
|
1857
|
+
function mapLicenseFallback(config, aliases, state, basePath) {
|
|
1858
|
+
const located = locate(config, aliases, basePath);
|
|
1859
|
+
const license = located && licenseValue(located.value);
|
|
1860
|
+
if (located && license) addPackageFallback(state, "license", license, located.path);
|
|
1861
|
+
}
|
|
1862
|
+
function resolveTargetPackage(targetPackage, fallbacks, generator, delivery, index) {
|
|
1863
|
+
const diagnostics = [];
|
|
1864
|
+
for (const fallback of fallbacks) {
|
|
1865
|
+
applyFallback(targetPackage, fallback, index, diagnostics);
|
|
1866
|
+
}
|
|
1867
|
+
if (delivery !== "github") {
|
|
1868
|
+
applyMetadataLicense(targetPackage, generator.raw, index, diagnostics);
|
|
1869
|
+
}
|
|
1870
|
+
return diagnostics;
|
|
1871
|
+
}
|
|
1872
|
+
function applyFallback(targetPackage, { field, value, path }, index, diagnostics) {
|
|
1873
|
+
const existing = targetPackage[field];
|
|
1874
|
+
if (existing === void 0) {
|
|
1875
|
+
targetPackage[field] = value;
|
|
1876
|
+
} else if (stableJson(existing) !== stableJson(value)) {
|
|
1877
|
+
diagnostics.push({
|
|
1878
|
+
code: "FERN_PACKAGE_VALUE_CONFLICT",
|
|
1879
|
+
severity: "warning",
|
|
1880
|
+
path,
|
|
1881
|
+
reason: `Fern value conflicts with the package.${field} already migrated for this target, which is kept`,
|
|
1882
|
+
sdkConfigPath: ["targets", index, "package", field],
|
|
1883
|
+
suggestedAction: `Choose the intended value and set targets.${index}.package.${field} manually.`
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
function applyMetadataLicense(targetPackage, raw, index, diagnostics) {
|
|
1888
|
+
const metadata = isObject(raw) && isObject(raw.metadata) ? raw.metadata : void 0;
|
|
1889
|
+
if (metadata?.license === void 0 || metadata.license === null) return;
|
|
1890
|
+
const path = ["group", "generators", index, "metadata", "license"];
|
|
1891
|
+
const license = licenseValue(metadata.license);
|
|
1892
|
+
if (license) {
|
|
1893
|
+
applyFallback(targetPackage, { field: "license", value: license, path }, index, diagnostics);
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1896
|
+
diagnostics.push({
|
|
1897
|
+
code: "FERN_CONFIG_FIELD_UNSUPPORTED",
|
|
1898
|
+
severity: "warning",
|
|
1899
|
+
path,
|
|
1900
|
+
reason: isObject(metadata.license) ? "A custom license file cannot be migrated automatically" : "metadata.license is not a license identifier",
|
|
1901
|
+
sdkConfigPath: ["targets", index, "package", "license"],
|
|
1902
|
+
suggestedAction: `Set targets.${index}.package.license manually.`
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
function mapCargoAuthors(identity, state, targetIndex) {
|
|
1906
|
+
const located = locate(identity.value, ["authors"], identity.path);
|
|
1907
|
+
const entries = located && stringArrayValue(located.value);
|
|
1908
|
+
if (!located || !entries) return;
|
|
1909
|
+
consume(state, located.path);
|
|
1910
|
+
const authors = entries.map(parseCargoAuthor);
|
|
1911
|
+
const parsed = sdkConfigV1PackageConfigSchema.shape.authors.safeParse(authors);
|
|
1912
|
+
const invalid = parsed.success ? [] : [...new Set(parsed.error.issues.map((issue) => issue.path[0]))].filter(
|
|
1913
|
+
(index) => typeof index === "number"
|
|
1914
|
+
);
|
|
1915
|
+
if (invalid.length === 0) {
|
|
1916
|
+
addPackageFallback(state, "authors", authors, located.path);
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
const authorsPath = ["targets", targetIndex, "package", "authors"];
|
|
1920
|
+
(state.valueDiagnostics ??= []).push(
|
|
1921
|
+
...invalid.map((entry) => ({
|
|
1922
|
+
code: "FERN_CONFIG_VALUE_INVALID",
|
|
1923
|
+
severity: "warning",
|
|
1924
|
+
path: [...located.path, entry],
|
|
1925
|
+
reason: 'CLI packageIdentity.authors was not migrated because this entry is not "Name" or "Name <email>" with a valid email',
|
|
1926
|
+
sdkConfigPath: authorsPath,
|
|
1927
|
+
suggestedAction: `Correct the entry, then set ${authorsPath.join(".")} manually.`
|
|
1928
|
+
}))
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1931
|
+
function parseCargoAuthor(entry) {
|
|
1932
|
+
const trimmed = entry.trim();
|
|
1933
|
+
const match = /^(.*?)\s*<([^<>]*)>$/.exec(trimmed);
|
|
1934
|
+
if (!match) return { name: trimmed };
|
|
1935
|
+
const [, name = "", email = ""] = match;
|
|
1936
|
+
if (name !== "" && !emailSchema.safeParse(email).success) return { name: trimmed };
|
|
1937
|
+
return { name, email };
|
|
1938
|
+
}
|
|
1939
|
+
function licenseValue(value) {
|
|
1940
|
+
const license = stringValue(value)?.trim();
|
|
1941
|
+
return license ? { type: canonicalLicenseType(license) ?? license } : void 0;
|
|
1942
|
+
}
|
|
1943
|
+
function addPackageFallback(state, field, value, path) {
|
|
1944
|
+
consume(state, path);
|
|
1945
|
+
(state.packageFallbacks ??= []).push({ field, value, path });
|
|
1946
|
+
}
|
|
1453
1947
|
var OMIT = /* @__PURE__ */ Symbol("omit");
|
|
1454
1948
|
function inputJsonSchema(schema) {
|
|
1455
1949
|
return zod.z.toJSONSchema(schema, {
|
|
@@ -1707,7 +2201,16 @@ var sdkConfigV1PublishConfigSchema = zod.z.discriminatedUnion("registry", [
|
|
|
1707
2201
|
zod.z.strictObject({
|
|
1708
2202
|
registry: zod.z.literal("npm").describe("Publishes the package to an npm-compatible registry."),
|
|
1709
2203
|
token: nonEmptyStringSchema.optional().describe("The npm registry token, or an environment expression that resolves to it."),
|
|
2204
|
+
trustedPublishing: zod.z.boolean().optional().describe("Whether npm publication uses trusted publishing (OIDC) instead of a token."),
|
|
1710
2205
|
...commonPublishShape
|
|
2206
|
+
}).superRefine((publish, context) => {
|
|
2207
|
+
if (publish.trustedPublishing === true && publish.token !== void 0) {
|
|
2208
|
+
context.addIssue({
|
|
2209
|
+
code: "custom",
|
|
2210
|
+
message: "token must be omitted when trustedPublishing is true",
|
|
2211
|
+
path: ["token"]
|
|
2212
|
+
});
|
|
2213
|
+
}
|
|
1711
2214
|
}),
|
|
1712
2215
|
zod.z.strictObject({
|
|
1713
2216
|
registry: zod.z.literal("pypi").describe("Publishes the package to a PyPI-compatible registry."),
|
|
@@ -1785,10 +2288,29 @@ var sdkConfigV1OutputConfigSchema = zod.z.discriminatedUnion(
|
|
|
1785
2288
|
[filesOutputSchema, zipOutputSchema, githubDeliverySchema],
|
|
1786
2289
|
{ error: 'output.delivery must be one of "files", "zip", or "github"' }
|
|
1787
2290
|
);
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
2291
|
+
var cliDistributionShape = {
|
|
2292
|
+
distribution: cliDistributionConfigSchema.optional().describe(
|
|
2293
|
+
"CLI release channels published by the generated release workflow; credentials are GitHub Actions secret names."
|
|
2294
|
+
)
|
|
2295
|
+
};
|
|
2296
|
+
function rejectDistributionWithoutGithub(output, context) {
|
|
2297
|
+
if (output.distribution !== void 0) {
|
|
2298
|
+
context.addIssue({
|
|
2299
|
+
code: "custom",
|
|
2300
|
+
message: CLI_DISTRIBUTION_REQUIRES_GITHUB_DELIVERY_MESSAGE,
|
|
2301
|
+
path: ["distribution"]
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
var sdkConfigV1CliOutputConfigSchema = zod.z.discriminatedUnion(
|
|
2306
|
+
"delivery",
|
|
2307
|
+
[
|
|
2308
|
+
filesOutputSchema.extend(cliDistributionShape).superRefine(rejectDistributionWithoutGithub),
|
|
2309
|
+
zipOutputSchema.extend(cliDistributionShape).superRefine(rejectDistributionWithoutGithub),
|
|
2310
|
+
githubDeliverySchema.extend(cliDistributionShape)
|
|
2311
|
+
],
|
|
2312
|
+
{ error: 'output.delivery must be one of "files", "zip", or "github"' }
|
|
2313
|
+
);
|
|
1792
2314
|
var sdkConfigV1ReplayConfigSchema = zod.z.strictObject({
|
|
1793
2315
|
enabled: zod.z.boolean().describe("Whether regeneration reapplies customer-authored repository changes.")
|
|
1794
2316
|
});
|
|
@@ -1865,10 +2387,6 @@ var sdkConfigV1SourceConfigSchema = zod.z.strictObject({
|
|
|
1865
2387
|
seenIds.add(id);
|
|
1866
2388
|
});
|
|
1867
2389
|
});
|
|
1868
|
-
var cliGenerationConfigSchema = zod.z.strictObject({
|
|
1869
|
-
paginationParameters: zod.z.array(nonEmptyStringSchema).optional().describe("Request parameter names treated as pagination controls by the CLI."),
|
|
1870
|
-
skills: zod.z.boolean().optional().describe("Whether the generated CLI includes skills that teach AI agents to invoke commands.")
|
|
1871
|
-
});
|
|
1872
2390
|
var csharpGenerationConfigSchema = zod.z.strictObject({
|
|
1873
2391
|
useOptionalWrapper: zod.z.boolean().optional().describe("Whether optional values use an explicit Optional wrapper."),
|
|
1874
2392
|
simplifyObjectDictionaries: zod.z.boolean().optional().describe("Whether object schemas with arbitrary values use simplified dictionary types."),
|
|
@@ -2121,7 +2639,10 @@ var sdkConfigV1TargetSchema = zod.z.discriminatedUnion("language", [
|
|
|
2121
2639
|
zod.z.strictObject({
|
|
2122
2640
|
language: zod.z.literal("cli").describe("Generates a command-line interface."),
|
|
2123
2641
|
generation: sdkConfigV1GenerationConfigOverrideSchema.extend(cliGenerationConfigSchema.shape).optional().describe("Common and CLI-specific generation settings for this target."),
|
|
2124
|
-
...targetOverrideShape
|
|
2642
|
+
...targetOverrideShape,
|
|
2643
|
+
output: sdkConfigV1CliOutputConfigSchema.optional().describe(
|
|
2644
|
+
"Output configuration, including optional CLI distribution channels, that replaces the root output for this target."
|
|
2645
|
+
)
|
|
2125
2646
|
}),
|
|
2126
2647
|
zod.z.strictObject({
|
|
2127
2648
|
language: zod.z.literal("mcp").describe("Generates an MCP server."),
|
|
@@ -2138,7 +2659,7 @@ var sdkConfigV1TargetSchema = zod.z.discriminatedUnion("language", [
|
|
|
2138
2659
|
// src/sdk-config/v1/sdk-config-v1.ts
|
|
2139
2660
|
var SDK_CONFIG_V1_SCHEMA_VERSION = "sdk-config/v1";
|
|
2140
2661
|
var publishRegistryLanguages = {
|
|
2141
|
-
npm: ["typescript", "mcp"],
|
|
2662
|
+
npm: ["typescript", "mcp", "cli"],
|
|
2142
2663
|
pypi: ["python"],
|
|
2143
2664
|
maven: ["java", "kotlin"],
|
|
2144
2665
|
nuget: ["csharp"],
|
|
@@ -2215,6 +2736,13 @@ function validateTargetPublishing(target, targetIndex, globalPackage, globalOutp
|
|
|
2215
2736
|
});
|
|
2216
2737
|
return;
|
|
2217
2738
|
}
|
|
2739
|
+
if (target.language === "cli" && output.delivery !== "github") {
|
|
2740
|
+
context.addIssue({
|
|
2741
|
+
code: "custom",
|
|
2742
|
+
message: CLI_PUBLISH_REQUIRES_GITHUB_DELIVERY_MESSAGE,
|
|
2743
|
+
path: target.output ? ["targets", targetIndex, "output", "delivery"] : ["output", "delivery"]
|
|
2744
|
+
});
|
|
2745
|
+
}
|
|
2218
2746
|
validatePublishingIdentity(
|
|
2219
2747
|
{ ...globalPackage, ...target.package },
|
|
2220
2748
|
registry,
|
|
@@ -2327,16 +2855,28 @@ function mapFernConfigToSdkConfigV1(input) {
|
|
|
2327
2855
|
package: outputPackage,
|
|
2328
2856
|
generation: outputGeneration
|
|
2329
2857
|
}, index) => {
|
|
2858
|
+
const distribution = applyCliDistribution(output, invocation.cliDistribution, index);
|
|
2859
|
+
invocation.unsupportedFields.push(...distribution.diagnostics);
|
|
2330
2860
|
const target = {
|
|
2331
2861
|
language,
|
|
2332
|
-
output,
|
|
2862
|
+
output: distribution.output,
|
|
2333
2863
|
...optional("sdkName", generator.sdkName),
|
|
2334
2864
|
...optional("sdkVersion", generator.sdkVersion),
|
|
2335
2865
|
...optional("client", clients.targetOverrides[index]),
|
|
2336
2866
|
...optional("docs", docs.targetOverrides[index])
|
|
2337
2867
|
};
|
|
2338
|
-
|
|
2339
|
-
|
|
2868
|
+
const targetPackage = { ...invocation.package, ...outputPackage, ...generator.package };
|
|
2869
|
+
invocation.unsupportedFields.push(
|
|
2870
|
+
...resolveTargetPackage(
|
|
2871
|
+
targetPackage,
|
|
2872
|
+
invocation.packageFallbacks,
|
|
2873
|
+
generator,
|
|
2874
|
+
output.delivery,
|
|
2875
|
+
index
|
|
2876
|
+
)
|
|
2877
|
+
);
|
|
2878
|
+
if (Object.keys(targetPackage).length > 0 || outputPackage || generator.package) {
|
|
2879
|
+
target.package = targetPackage;
|
|
2340
2880
|
}
|
|
2341
2881
|
const targetGeneration = {
|
|
2342
2882
|
...generations.targetOverrides[index],
|
|
@@ -2518,10 +3058,14 @@ function mapInvocation(generator, language, activeLanguages, index) {
|
|
|
2518
3058
|
...optional("smartCasingDigitWordBoundary", smartCasingDigitWordBoundary)
|
|
2519
3059
|
};
|
|
2520
3060
|
}
|
|
2521
|
-
const targetGeneration = mapLanguageConfig(
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
3061
|
+
const targetGeneration = mapLanguageConfig(
|
|
3062
|
+
language,
|
|
3063
|
+
config,
|
|
3064
|
+
state,
|
|
3065
|
+
packageConfig,
|
|
3066
|
+
[...prefix, "config"],
|
|
3067
|
+
index
|
|
3068
|
+
);
|
|
2525
3069
|
mapPublishMetadata(generator.publishMetadata, packageConfig);
|
|
2526
3070
|
if (generator.keywords?.length) {
|
|
2527
3071
|
generation.reservedKeywords = [...generator.keywords];
|
|
@@ -2538,12 +3082,22 @@ function mapInvocation(generator, language, activeLanguages, index) {
|
|
|
2538
3082
|
}
|
|
2539
3083
|
const docs = mapReadme(generator.readme, language, activeLanguages, state, [...prefix, "readme"]);
|
|
2540
3084
|
const unsupportedFields = [
|
|
3085
|
+
...state.valueDiagnostics ?? [],
|
|
2541
3086
|
...collectUnsupported(config, [...prefix, "config"], state),
|
|
2542
3087
|
...settings ? collectUnsupported(settings, [...prefix, "settings"], state) : [],
|
|
2543
3088
|
...isObject(generator.readme) ? collectUnsupported(generator.readme, [...prefix, "readme"], state) : [],
|
|
2544
3089
|
...unsupportedResolvedFields(generator, index, apiWideIdempotency !== void 0)
|
|
2545
3090
|
];
|
|
2546
|
-
return {
|
|
3091
|
+
return {
|
|
3092
|
+
client,
|
|
3093
|
+
docs,
|
|
3094
|
+
generation,
|
|
3095
|
+
package: packageConfig,
|
|
3096
|
+
packageFallbacks: state.packageFallbacks ?? [],
|
|
3097
|
+
...optional("cliDistribution", state.cliDistribution),
|
|
3098
|
+
targetGeneration,
|
|
3099
|
+
unsupportedFields
|
|
3100
|
+
};
|
|
2547
3101
|
}
|
|
2548
3102
|
function unsupportedResolvedFields(generator, index, idempotencyMapped) {
|
|
2549
3103
|
const values = [
|
|
@@ -2733,6 +3287,7 @@ function mapCommonConfig(language, config, state, client, generation, packageCon
|
|
|
2733
3287
|
const packagePath = takeString(config, ["packagePath"], state, basePath);
|
|
2734
3288
|
if (packagePath !== void 0) generation.layout = { packagePath };
|
|
2735
3289
|
mapDependencies(config, state, packageConfig, basePath);
|
|
3290
|
+
mapPeerDependenciesMeta(config, state, packageConfig, basePath);
|
|
2736
3291
|
}
|
|
2737
3292
|
function mapTypescriptStreams(config, state, basePath) {
|
|
2738
3293
|
const responseType = takeEnum(config, ["streamType"], ["wrapper", "web"], state, basePath);
|
|
@@ -2746,7 +3301,7 @@ function mapTypescriptStreams(config, state, basePath) {
|
|
|
2746
3301
|
if (responseType === void 0 && fileResponseType === void 0) return void 0;
|
|
2747
3302
|
return { enabled: true, ...compact({ responseType, fileResponseType }) };
|
|
2748
3303
|
}
|
|
2749
|
-
function mapLanguageConfig(language, config, state, packageConfig, basePath) {
|
|
3304
|
+
function mapLanguageConfig(language, config, state, packageConfig, basePath, targetIndex) {
|
|
2750
3305
|
switch (language) {
|
|
2751
3306
|
case "typescript":
|
|
2752
3307
|
return mapTypescript(config, state, packageConfig, basePath);
|
|
@@ -2773,7 +3328,7 @@ function mapLanguageConfig(language, config, state, packageConfig, basePath) {
|
|
|
2773
3328
|
case "swift":
|
|
2774
3329
|
return mapSwift(config, state, basePath);
|
|
2775
3330
|
case "cli":
|
|
2776
|
-
return mapCli(config, state, packageConfig, basePath);
|
|
3331
|
+
return mapCli(config, state, packageConfig, basePath, targetIndex);
|
|
2777
3332
|
case "terraform":
|
|
2778
3333
|
return mapTerraform(config, state, packageConfig, basePath);
|
|
2779
3334
|
}
|
|
@@ -2790,6 +3345,7 @@ function mapTypescript(config, state, packageConfig, basePath) {
|
|
|
2790
3345
|
const packageManagerAtIndex = packageJsonPackageManager ? packageJsonPackageManager.indexOf("@", packageJsonPackageManager.startsWith("@") ? 1 : 0) : -1;
|
|
2791
3346
|
const packageManagerVersionPart = packageManagerAtIndex >= 0 ? packageJsonPackageManager?.slice(packageManagerAtIndex + 1).split("+")[0] : void 0;
|
|
2792
3347
|
const packageManagerVersion = packageManagerVersionPart || void 0;
|
|
3348
|
+
if (packageJsonManifest) liftPackageJsonDependencies(packageJsonManifest, state, packageConfig);
|
|
2793
3349
|
const serdeLayer = takeBoolean(config, ["serdeLayer"], state, basePath);
|
|
2794
3350
|
const noSerdeLayer = takeBoolean(config, ["noSerdeLayer"], state, basePath);
|
|
2795
3351
|
const fetchSupport = takeEnum(config, ["fetchSupport"], ["native"], state, basePath);
|
|
@@ -2959,6 +3515,7 @@ function mapRust(config, state, packageConfig, basePath) {
|
|
|
2959
3515
|
const description = takeString(config, ["packageDescription"], state, basePath);
|
|
2960
3516
|
const documentationUrl = takeString(config, ["packageDocumentation"], state, basePath);
|
|
2961
3517
|
Object.assign(packageConfig, compact({ packageName, repository, description, documentationUrl }));
|
|
3518
|
+
mapLicenseFallback(config, ["packageLicense"], state, basePath);
|
|
2962
3519
|
return compact({
|
|
2963
3520
|
dateTimeType: takeEnum(config, ["dateTimeType"], ["offset", "utc"], state, basePath),
|
|
2964
3521
|
capitalizeInitialisms: takeBoolean(config, ["capitalizeInitialisms"], state, basePath),
|
|
@@ -2972,7 +3529,7 @@ function mapSwift(config, state, basePath) {
|
|
|
2972
3529
|
nullableAsOptional: takeBoolean(config, ["nullableAsOptional"], state, basePath)
|
|
2973
3530
|
});
|
|
2974
3531
|
}
|
|
2975
|
-
function mapCli(config, state, packageConfig, basePath) {
|
|
3532
|
+
function mapCli(config, state, packageConfig, basePath, targetIndex) {
|
|
2976
3533
|
const identity = takeObject(config, ["packageIdentity"], state, basePath);
|
|
2977
3534
|
if (identity) {
|
|
2978
3535
|
Object.assign(
|
|
@@ -2983,10 +3540,13 @@ function mapCli(config, state, packageConfig, basePath) {
|
|
|
2983
3540
|
description: takeString(identity.value, ["description"], state, identity.path)
|
|
2984
3541
|
})
|
|
2985
3542
|
);
|
|
3543
|
+
mapCliPackageIdentity(identity, state, targetIndex);
|
|
2986
3544
|
}
|
|
3545
|
+
mapCliDistribution(config, state, basePath, targetIndex);
|
|
2987
3546
|
return compact({
|
|
2988
3547
|
paginationParameters: takeStringArray(config, ["paginationParameters"], state, basePath),
|
|
2989
|
-
skills: takeBoolean(config, ["skills"], state, basePath)
|
|
3548
|
+
skills: takeBoolean(config, ["skills"], state, basePath),
|
|
3549
|
+
...mapCliGeneration(config, state, basePath, targetIndex)
|
|
2990
3550
|
});
|
|
2991
3551
|
}
|
|
2992
3552
|
function mapTerraform(config, state, packageConfig, basePath) {
|
|
@@ -3070,6 +3630,48 @@ function mapDependencies(config, state, packageConfig, basePath) {
|
|
|
3070
3630
|
if (dependencies.length) packageConfig[field] = dependencies;
|
|
3071
3631
|
}
|
|
3072
3632
|
}
|
|
3633
|
+
function liftPackageJsonDependencies(manifest, state, packageConfig) {
|
|
3634
|
+
for (const [field, target] of [
|
|
3635
|
+
["dependencies", "extraDependencies"],
|
|
3636
|
+
["devDependencies", "extraDevDependencies"],
|
|
3637
|
+
["peerDependencies", "extraPeerDependencies"]
|
|
3638
|
+
]) {
|
|
3639
|
+
const located = takeObject(manifest.value, [field], state, manifest.path);
|
|
3640
|
+
if (!located) continue;
|
|
3641
|
+
const lifted = Object.entries(located.value).flatMap(
|
|
3642
|
+
([name, dependency]) => mapDependency(name, dependency, state, [...located.path, name])
|
|
3643
|
+
);
|
|
3644
|
+
if (lifted.length) packageConfig[target] = overrideByName(packageConfig[target] ?? [], lifted);
|
|
3645
|
+
}
|
|
3646
|
+
const meta = takeObject(manifest.value, ["peerDependenciesMeta"], state, manifest.path);
|
|
3647
|
+
if (!meta) return;
|
|
3648
|
+
const entries = peerDependenciesMetaEntries(meta, state);
|
|
3649
|
+
if (entries.length) {
|
|
3650
|
+
packageConfig.extraPeerDependenciesMeta = {
|
|
3651
|
+
...packageConfig.extraPeerDependenciesMeta,
|
|
3652
|
+
...Object.fromEntries(entries)
|
|
3653
|
+
};
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
function overrideByName(existing, overrides) {
|
|
3657
|
+
const byName = new Map(existing.map((dependency) => [dependency.name, dependency]));
|
|
3658
|
+
overrides.forEach((dependency) => byName.set(dependency.name, dependency));
|
|
3659
|
+
return [...byName.values()];
|
|
3660
|
+
}
|
|
3661
|
+
function mapPeerDependenciesMeta(config, state, packageConfig, basePath) {
|
|
3662
|
+
const located = takeObject(config, ["extraPeerDependenciesMeta"], state, basePath);
|
|
3663
|
+
if (!located) return;
|
|
3664
|
+
const entries = peerDependenciesMetaEntries(located, state);
|
|
3665
|
+
if (entries.length) packageConfig.extraPeerDependenciesMeta = Object.fromEntries(entries);
|
|
3666
|
+
}
|
|
3667
|
+
function peerDependenciesMetaEntries(located, state) {
|
|
3668
|
+
return Object.entries(located.value).flatMap(([name, value]) => {
|
|
3669
|
+
const parsed = jsonObjectSchema.safeParse(value);
|
|
3670
|
+
if (!parsed.success) return [];
|
|
3671
|
+
consume(state, [...located.path, name]);
|
|
3672
|
+
return [[name, parsed.data]];
|
|
3673
|
+
});
|
|
3674
|
+
}
|
|
3073
3675
|
function mapDependency(name, value, state, path) {
|
|
3074
3676
|
if (typeof value === "string" && value) {
|
|
3075
3677
|
consume(state, path);
|
|
@@ -3077,13 +3679,7 @@ function mapDependency(name, value, state, path) {
|
|
|
3077
3679
|
}
|
|
3078
3680
|
if (!isObject(value)) return [];
|
|
3079
3681
|
const version = takeString(value, ["version"], state, path);
|
|
3080
|
-
const
|
|
3081
|
-
const localPath = takeString(value, ["path"], state, path);
|
|
3082
|
-
const source = gitUrl ? {
|
|
3083
|
-
type: "git",
|
|
3084
|
-
url: gitUrl,
|
|
3085
|
-
...optional("ref", takeString(value, ["ref"], state, path))
|
|
3086
|
-
} : localPath ? { type: "path", path: localPath } : void 0;
|
|
3682
|
+
const source = takeDependencySource(value, state, path);
|
|
3087
3683
|
if (!version && !source) return [];
|
|
3088
3684
|
return [
|
|
3089
3685
|
{
|
|
@@ -3099,6 +3695,17 @@ function mapDependency(name, value, state, path) {
|
|
|
3099
3695
|
}
|
|
3100
3696
|
];
|
|
3101
3697
|
}
|
|
3698
|
+
function takeDependencySource(value, state, path) {
|
|
3699
|
+
const gitUrl = takeString(value, ["git"], state, path);
|
|
3700
|
+
if (gitUrl) {
|
|
3701
|
+
const ref = takeString(value, ["ref", "rev", "branch"], state, path);
|
|
3702
|
+
return { type: "git", url: gitUrl, ...optional("ref", ref) };
|
|
3703
|
+
}
|
|
3704
|
+
const localPath = takeString(value, ["path"], state, path);
|
|
3705
|
+
if (localPath) return { type: "path", path: localPath };
|
|
3706
|
+
const registry = takeString(value, ["registry"], state, path);
|
|
3707
|
+
return registry ? { type: "registry", registry } : void 0;
|
|
3708
|
+
}
|
|
3102
3709
|
function takeCustomSections(value, language, activeLanguages, state, basePath) {
|
|
3103
3710
|
const located = locate(value, ["customSections"], basePath);
|
|
3104
3711
|
if (!located || !Array.isArray(located.value)) return void 0;
|
|
@@ -3258,14 +3865,21 @@ function takeToolsets(value, aliases, state, basePath) {
|
|
|
3258
3865
|
}
|
|
3259
3866
|
|
|
3260
3867
|
exports.FernConfigMappingError = FernConfigMappingError;
|
|
3868
|
+
exports.SDK_CONFIG_V1_CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE = CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE;
|
|
3261
3869
|
exports.SDK_CONFIG_V1_SCHEMA_VERSION = SDK_CONFIG_V1_SCHEMA_VERSION;
|
|
3870
|
+
exports.getSdkConfigV1Diagnostics = getSdkConfigV1Diagnostics;
|
|
3262
3871
|
exports.mapFernConfigToSdkConfigV1 = mapFernConfigToSdkConfigV1;
|
|
3263
3872
|
exports.parseSdkConfigV1 = parseSdkConfigV1;
|
|
3264
3873
|
exports.parseSdkConfigV1ForConsumption = parseSdkConfigV1ForConsumption;
|
|
3265
3874
|
exports.sdkConfigV1ApiConfigSchema = sdkConfigV1ApiConfigSchema;
|
|
3266
3875
|
exports.sdkConfigV1AuthConfigSchema = sdkConfigV1AuthConfigSchema;
|
|
3267
3876
|
exports.sdkConfigV1AuthSchemeSchema = sdkConfigV1AuthSchemeSchema;
|
|
3877
|
+
exports.sdkConfigV1CliDistributionConfigSchema = cliDistributionConfigSchema;
|
|
3878
|
+
exports.sdkConfigV1CliDistributionGithubAppSchema = cliDistributionGithubAppSchema;
|
|
3879
|
+
exports.sdkConfigV1CliDistributionHomebrewSchema = cliDistributionHomebrewSchema;
|
|
3880
|
+
exports.sdkConfigV1CliDistributionScoopSchema = cliDistributionScoopSchema;
|
|
3268
3881
|
exports.sdkConfigV1CliGenerationConfigSchema = cliGenerationConfigSchema;
|
|
3882
|
+
exports.sdkConfigV1CliOutputConfigSchema = sdkConfigV1CliOutputConfigSchema;
|
|
3269
3883
|
exports.sdkConfigV1ClientConfigOverrideSchema = sdkConfigV1ClientConfigOverrideSchema;
|
|
3270
3884
|
exports.sdkConfigV1ClientConfigSchema = sdkConfigV1ClientConfigSchema;
|
|
3271
3885
|
exports.sdkConfigV1ComposerPackageNameSchema = composerPackageNameSchema;
|
|
@@ -3275,6 +3889,7 @@ exports.sdkConfigV1DocsConfigSchema = sdkConfigV1DocsConfigSchema;
|
|
|
3275
3889
|
exports.sdkConfigV1ExactSemverSchema = exactSemverSchema;
|
|
3276
3890
|
exports.sdkConfigV1GenerationConfigOverrideSchema = sdkConfigV1GenerationConfigOverrideSchema;
|
|
3277
3891
|
exports.sdkConfigV1GenerationConfigSchema = sdkConfigV1GenerationConfigSchema;
|
|
3892
|
+
exports.sdkConfigV1GithubActionsSecretNameSchema = githubActionsSecretNameSchema;
|
|
3278
3893
|
exports.sdkConfigV1GoGenerationConfigSchema = goGenerationConfigSchema;
|
|
3279
3894
|
exports.sdkConfigV1GoModulePathSchema = goModulePathSchema;
|
|
3280
3895
|
exports.sdkConfigV1JavaGenerationConfigSchema = javaGenerationConfigSchema;
|