@postman/sdk-config 0.9.0 → 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 +776 -44
- 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 +762 -45
- package/dist/index.js.map +1 -1
- package/dist/sdk-config/index.cjs +728 -44
- 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 +721 -45
- package/dist/sdk-config/index.js.map +1 -1
- package/dist/sdk-config/v1/index.cjs +728 -44
- 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 +721 -45
- 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
package/dist/index.js
CHANGED
|
@@ -125,13 +125,21 @@ var oauthScopeSchema = z.strictObject({
|
|
|
125
125
|
name: nonEmptyStringSchema.describe("The OAuth scope value requested from the provider."),
|
|
126
126
|
description: z.string().optional().describe("A description of the OAuth scope included in generated SDK documentation.")
|
|
127
127
|
});
|
|
128
|
+
var publicClientIdSchema = nonEmptyStringSchema.refine((value) => value.trim() === value, {
|
|
129
|
+
message: "must not have leading or trailing whitespace"
|
|
130
|
+
}).refine((value) => !value.includes("${"), {
|
|
131
|
+
message: "must be a literal public client ID, not an environment expression"
|
|
132
|
+
});
|
|
128
133
|
var oauthFlowSchema = z.discriminatedUnion("type", [
|
|
129
134
|
z.strictObject({
|
|
130
135
|
type: z.literal("authorization-code").describe("Uses the OAuth authorization code flow."),
|
|
131
136
|
authorizationUrl: nonEmptyStringSchema.describe("The URL used to authorize the client."),
|
|
132
137
|
tokenUrl: nonEmptyStringSchema.describe("The URL used to exchange a code for tokens."),
|
|
133
138
|
refreshUrl: nonEmptyStringSchema.optional().describe("The URL used to refresh access tokens."),
|
|
134
|
-
scopes: z.array(oauthScopeSchema).optional().describe("The scopes supported by this flow.")
|
|
139
|
+
scopes: z.array(oauthScopeSchema).optional().describe("The scopes supported by this flow."),
|
|
140
|
+
clientId: publicClientIdSchema.optional().describe(
|
|
141
|
+
"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."
|
|
142
|
+
)
|
|
135
143
|
}),
|
|
136
144
|
z.strictObject({
|
|
137
145
|
type: z.literal("client-credentials").describe("Uses the OAuth client credentials flow."),
|
|
@@ -447,8 +455,102 @@ var packageConfigSchema = z.strictObject({
|
|
|
447
455
|
projectUrls: z.array(projectUrlSchema).optional().describe("Labeled project links for package metadata."),
|
|
448
456
|
extraDependencies: z.array(dependencySchema).optional().describe("Additional runtime dependencies added to the generated package."),
|
|
449
457
|
extraDevDependencies: z.array(dependencySchema).optional().describe("Additional development dependencies added to the generated package."),
|
|
450
|
-
extraPeerDependencies: z.array(dependencySchema).optional().describe("Additional peer dependencies added to the generated package.")
|
|
458
|
+
extraPeerDependencies: z.array(dependencySchema).optional().describe("Additional peer dependencies added to the generated package."),
|
|
459
|
+
extraPeerDependenciesMeta: z.record(nonEmptyStringSchema, jsonObjectSchema).optional().describe(
|
|
460
|
+
"npm peerDependenciesMeta entries keyed by peer dependency name, such as { optional: true }."
|
|
461
|
+
)
|
|
462
|
+
});
|
|
463
|
+
var GITHUB_ACTIONS_SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/;
|
|
464
|
+
var GITHUB_REPOSITORY_SLUG_PATTERN = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
465
|
+
var HOMEBREW_FORMULA_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
466
|
+
var githubActionsSecretNameSchema = z.string({ error: "must be the name of a GitHub Actions secret" }).regex(GITHUB_ACTIONS_SECRET_NAME_PATTERN, {
|
|
467
|
+
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."
|
|
468
|
+
}).refine((value) => value !== "GITHUB_TOKEN", {
|
|
469
|
+
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."
|
|
470
|
+
});
|
|
471
|
+
var githubRepositorySlugSchema = z.string({ error: 'must be a GitHub repository in "<owner>/<repo>" form' }).regex(GITHUB_REPOSITORY_SLUG_PATTERN, {
|
|
472
|
+
error: 'must be a GitHub repository in "<owner>/<repo>" form, for example "acme/homebrew-tap"'
|
|
473
|
+
});
|
|
474
|
+
var homebrewFormulaNameSchema = z.string({ error: "must be a Homebrew formula name" }).regex(HOMEBREW_FORMULA_NAME_PATTERN, {
|
|
475
|
+
error: "must be a Homebrew formula name: start with a lowercase letter and contain only a-z, 0-9, or -"
|
|
476
|
+
});
|
|
477
|
+
var cliDistributionGithubAppSchema = z.strictObject({
|
|
478
|
+
appIdSecretName: githubActionsSecretNameSchema.describe(
|
|
479
|
+
"The name of the GitHub Actions secret holding the GitHub App ID or client ID."
|
|
480
|
+
),
|
|
481
|
+
privateKeySecretName: githubActionsSecretNameSchema.describe(
|
|
482
|
+
"The name of the GitHub Actions secret holding the GitHub App private key in PEM form."
|
|
483
|
+
)
|
|
484
|
+
});
|
|
485
|
+
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.";
|
|
486
|
+
var cliDistributionHomebrewSchema = z.strictObject({
|
|
487
|
+
tap: githubRepositorySlugSchema.describe(
|
|
488
|
+
'The Homebrew tap repository in "<owner>/<repo>" form that receives the formula.'
|
|
489
|
+
),
|
|
490
|
+
formula: homebrewFormulaNameSchema.optional().describe("The Homebrew formula name; the generator defaults it to the CLI binary name."),
|
|
491
|
+
tokenSecretName: githubActionsSecretNameSchema.optional().describe(channelTokenSecretNameDescription)
|
|
492
|
+
});
|
|
493
|
+
var cliDistributionScoopSchema = z.strictObject({
|
|
494
|
+
bucket: githubRepositorySlugSchema.describe(
|
|
495
|
+
'The Scoop bucket repository in "<owner>/<repo>" form that receives the manifest.'
|
|
496
|
+
),
|
|
497
|
+
tokenSecretName: githubActionsSecretNameSchema.optional().describe(channelTokenSecretNameDescription)
|
|
498
|
+
});
|
|
499
|
+
var cliDistributionConfigSchema = z.strictObject({
|
|
500
|
+
githubApp: cliDistributionGithubAppSchema.optional().describe(
|
|
501
|
+
"A GitHub App used to mint short-lived tokens for every channel without its own tokenSecretName."
|
|
502
|
+
),
|
|
503
|
+
homebrew: cliDistributionHomebrewSchema.optional().describe("Publishes a Homebrew formula to a tap repository on each tagged release."),
|
|
504
|
+
scoop: cliDistributionScoopSchema.optional().describe("Publishes a Scoop manifest to a bucket repository on each tagged release.")
|
|
505
|
+
}).superRefine((distribution, context) => {
|
|
506
|
+
if (distribution.homebrew !== void 0 || distribution.scoop !== void 0) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
if (distribution.githubApp !== void 0) {
|
|
510
|
+
context.addIssue({
|
|
511
|
+
code: "custom",
|
|
512
|
+
message: "githubApp requires at least one distribution channel: homebrew or scoop",
|
|
513
|
+
path: ["githubApp"]
|
|
514
|
+
});
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
context.addIssue({
|
|
518
|
+
code: "custom",
|
|
519
|
+
message: "distribution must configure at least one channel: homebrew or scoop"
|
|
520
|
+
});
|
|
451
521
|
});
|
|
522
|
+
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.';
|
|
523
|
+
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.';
|
|
524
|
+
var CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE = "CLI_DISTRIBUTION_NON_RELEASE_MODE";
|
|
525
|
+
var nonReleaseGithubModes = /* @__PURE__ */ new Set(["pull-request", "push", "commit"]);
|
|
526
|
+
function cliDistributionModeDiagnostic(output, outputPath) {
|
|
527
|
+
const mode = output?.github?.mode;
|
|
528
|
+
if (output?.distribution === void 0 || mode === void 0 || !nonReleaseGithubModes.has(mode)) {
|
|
529
|
+
return void 0;
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
code: CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE,
|
|
533
|
+
severity: "warning",
|
|
534
|
+
path: [...outputPath, "github", "mode"],
|
|
535
|
+
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.`,
|
|
536
|
+
suggestedAction: 'Use mode "release" or "commit-and-release", or push a version tag after merging generated changes.'
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/sdk-config/v1/diagnostics.ts
|
|
541
|
+
function getSdkConfigV1Diagnostics(config) {
|
|
542
|
+
return config.targets.flatMap((target, targetIndex) => {
|
|
543
|
+
if (target.language !== "cli") {
|
|
544
|
+
return [];
|
|
545
|
+
}
|
|
546
|
+
const diagnostic = cliDistributionModeDiagnostic(target.output, [
|
|
547
|
+
"targets",
|
|
548
|
+
targetIndex,
|
|
549
|
+
"output"
|
|
550
|
+
]);
|
|
551
|
+
return diagnostic ? [diagnostic] : [];
|
|
552
|
+
});
|
|
553
|
+
}
|
|
452
554
|
var httpMethodSchema = z.enum([
|
|
453
555
|
"GET",
|
|
454
556
|
"POST",
|
|
@@ -653,6 +755,17 @@ function stringValue(value) {
|
|
|
653
755
|
function stringArrayValue(value) {
|
|
654
756
|
return Array.isArray(value) && value.every((item) => typeof item === "string" && item.length > 0) ? value : void 0;
|
|
655
757
|
}
|
|
758
|
+
var canonicalLicenseTypes = {
|
|
759
|
+
mit: "MIT",
|
|
760
|
+
apache: "APACHE",
|
|
761
|
+
"apache-2.0": "APACHE",
|
|
762
|
+
"gpl-3.0": "GPL3",
|
|
763
|
+
"gpl-3.0-only": "GPL3",
|
|
764
|
+
unlicensed: "UNLICENSED"
|
|
765
|
+
};
|
|
766
|
+
function canonicalLicenseType(value) {
|
|
767
|
+
return canonicalLicenseTypes[value.trim().toLowerCase()];
|
|
768
|
+
}
|
|
656
769
|
function stableJson(value) {
|
|
657
770
|
return JSON.stringify(sortKeys(value));
|
|
658
771
|
}
|
|
@@ -663,6 +776,280 @@ function sortKeys(value) {
|
|
|
663
776
|
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => [key, sortKeys(child)])
|
|
664
777
|
);
|
|
665
778
|
}
|
|
779
|
+
var ALPHANUMERIC_PATTERN = /[A-Za-z0-9]/;
|
|
780
|
+
var ROOT_GROUP_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
781
|
+
var KEBAB_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
782
|
+
var DOTTED_COMMAND_PATH_PATTERN = /^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;
|
|
783
|
+
var FIELD_NAME_PATTERN = /^[A-Za-z0-9_.-]+$/;
|
|
784
|
+
var RESERVED_USER_AGENT_SUFFIX_FLAGS = /* @__PURE__ */ new Set([
|
|
785
|
+
"params",
|
|
786
|
+
"output",
|
|
787
|
+
"json",
|
|
788
|
+
"format",
|
|
789
|
+
"dry-run",
|
|
790
|
+
"base-url",
|
|
791
|
+
"page-all",
|
|
792
|
+
"page-limit",
|
|
793
|
+
"page-delay",
|
|
794
|
+
"no-pager",
|
|
795
|
+
"no-extract",
|
|
796
|
+
"no-retry",
|
|
797
|
+
"no-stream",
|
|
798
|
+
"quiet",
|
|
799
|
+
"query",
|
|
800
|
+
"help",
|
|
801
|
+
"debug",
|
|
802
|
+
"schema"
|
|
803
|
+
]);
|
|
804
|
+
var RESERVED_PROFILES_COMMAND_NAMES = /* @__PURE__ */ new Set([
|
|
805
|
+
"auth",
|
|
806
|
+
"completion",
|
|
807
|
+
"man",
|
|
808
|
+
"errors",
|
|
809
|
+
"generate-skills",
|
|
810
|
+
"help"
|
|
811
|
+
]);
|
|
812
|
+
var binaryNameSchema = nonEmptyStringSchema.regex(ALPHANUMERIC_PATTERN, {
|
|
813
|
+
message: "binaryName must contain at least one ASCII letter or digit"
|
|
814
|
+
});
|
|
815
|
+
var rootGroupSchema = z.string().regex(ROOT_GROUP_PATTERN, {
|
|
816
|
+
message: "rootGroup must start with a lowercase letter and contain only lowercase letters, digits, hyphens, and underscores"
|
|
817
|
+
});
|
|
818
|
+
var userAgentSuffixFlagSchema = z.string().superRefine((value, context) => {
|
|
819
|
+
if (value.startsWith("-")) {
|
|
820
|
+
context.addIssue({
|
|
821
|
+
code: "custom",
|
|
822
|
+
message: 'userAgentSuffixFlag must be the long flag name without the leading "--"'
|
|
823
|
+
});
|
|
824
|
+
} else if (!KEBAB_NAME_PATTERN.test(value)) {
|
|
825
|
+
context.addIssue({
|
|
826
|
+
code: "custom",
|
|
827
|
+
message: "userAgentSuffixFlag must start with a lowercase letter and contain only lowercase letters, digits, and hyphens"
|
|
828
|
+
});
|
|
829
|
+
} else if (RESERVED_USER_AGENT_SUFFIX_FLAGS.has(value)) {
|
|
830
|
+
context.addIssue({
|
|
831
|
+
code: "custom",
|
|
832
|
+
message: `userAgentSuffixFlag "${value}" collides with a built-in global flag`
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
});
|
|
836
|
+
var profilesCommandNameSchema = z.string().superRefine((value, context) => {
|
|
837
|
+
if (!KEBAB_NAME_PATTERN.test(value)) {
|
|
838
|
+
context.addIssue({
|
|
839
|
+
code: "custom",
|
|
840
|
+
message: "profiles.commandName must start with a lowercase letter and contain only lowercase letters, digits, and hyphens"
|
|
841
|
+
});
|
|
842
|
+
} else if (RESERVED_PROFILES_COMMAND_NAMES.has(value)) {
|
|
843
|
+
context.addIssue({
|
|
844
|
+
code: "custom",
|
|
845
|
+
message: `profiles.commandName "${value}" collides with a built-in command group`
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
function dottedCommandPathSchema(field) {
|
|
850
|
+
return z.string().regex(DOTTED_COMMAND_PATH_PATTERN, {
|
|
851
|
+
message: `${field} must be a dotted command path such as "iam.keys.create"`
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
function fieldNameMapSchema(field) {
|
|
855
|
+
const message = `${field} keys and values must be field names containing only [A-Za-z0-9_.-]`;
|
|
856
|
+
return z.record(z.string(), z.string().regex(FIELD_NAME_PATTERN, { message })).superRefine((value, context) => {
|
|
857
|
+
for (const key of Object.keys(value)) {
|
|
858
|
+
if (!FIELD_NAME_PATTERN.test(key)) {
|
|
859
|
+
context.addIssue({ code: "custom", message, path: [key] });
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
var profilesProvisionOperationSchema = z.strictObject({
|
|
865
|
+
operation: dottedCommandPathSchema("profiles.provisionOperation.operation").describe(
|
|
866
|
+
"The dotted command path of the operation that mints a profile credential."
|
|
867
|
+
),
|
|
868
|
+
credential: fieldNameMapSchema("profiles.provisionOperation.credential").refine((value) => Object.keys(value).length > 0, {
|
|
869
|
+
message: "profiles.provisionOperation.credential must map at least one credential field"
|
|
870
|
+
}).describe("Maps each stored credential field to the response field that supplies it."),
|
|
871
|
+
revokeParameters: fieldNameMapSchema("profiles.provisionOperation.revokeParameters").optional().describe("Maps each revoke-operation parameter to the response field that supplies it.")
|
|
872
|
+
});
|
|
873
|
+
var profilesConfigSchema = z.strictObject({
|
|
874
|
+
enabled: z.boolean().describe("Whether the CLI emits profile commands and the global --profile flag."),
|
|
875
|
+
commandName: profilesCommandNameSchema.optional().describe('The profile command group name. The generator defaults to "profiles".'),
|
|
876
|
+
revokeOperation: dottedCommandPathSchema("profiles.revokeOperation").optional().describe('The dotted command path called by "profiles remove --revoke".'),
|
|
877
|
+
provisionOperation: profilesProvisionOperationSchema.optional().describe('The operation called by "profiles create --provision" and its response mapping.')
|
|
878
|
+
});
|
|
879
|
+
var cliGenerationConfigSchema = z.strictObject({
|
|
880
|
+
paginationParameters: z.array(nonEmptyStringSchema).optional().describe("Request parameter names treated as pagination controls by the CLI."),
|
|
881
|
+
skills: z.boolean().optional().describe("Whether the generated CLI includes skills that teach AI agents to invoke commands."),
|
|
882
|
+
binaryName: binaryNameSchema.optional().describe(
|
|
883
|
+
"The CLI executable name. The generator kebab-cases it and also uses it for the source directory and env-var prefix."
|
|
884
|
+
),
|
|
885
|
+
customCommands: z.boolean().optional().describe("Whether hand-written command support is generated. The generator defaults to true."),
|
|
886
|
+
rootGroup: rootGroupSchema.optional().describe("A command group that every spec-derived command is nested under."),
|
|
887
|
+
profiles: profilesConfigSchema.optional().describe("Named profile command configuration."),
|
|
888
|
+
splitTypeCrates: z.boolean().optional().describe("Whether generated types are split into one crate per API behind a facade crate."),
|
|
889
|
+
userAgentSuffixFlag: userAgentSuffixFlagSchema.optional().describe('The long flag name, without "--", that appends a product token to the User-Agent.')
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
// src/sdk-config/v1/fern-config-mapper-cli.ts
|
|
893
|
+
var CLI_GENERATION_FIELDS = [
|
|
894
|
+
"binaryName",
|
|
895
|
+
"customCommands",
|
|
896
|
+
"rootGroup",
|
|
897
|
+
"profiles",
|
|
898
|
+
"splitTypeCrates",
|
|
899
|
+
"userAgentSuffixFlag"
|
|
900
|
+
];
|
|
901
|
+
var PROFILES_FIELDS = ["enabled", "commandName", "revokeOperation"];
|
|
902
|
+
var PROVISION_OPERATION_FIELDS = ["operation", "credential", "revokeParameters"];
|
|
903
|
+
function mapCliGeneration(config, state, basePath, targetIndex) {
|
|
904
|
+
const generation = {};
|
|
905
|
+
for (const field of CLI_GENERATION_FIELDS) {
|
|
906
|
+
const raw = ownValue(config, field);
|
|
907
|
+
if (raw === void 0) continue;
|
|
908
|
+
const fieldPath = [...basePath, field];
|
|
909
|
+
const { value, consumedPaths } = field === "profiles" && isObject(raw) ? pickProfiles(raw, fieldPath) : { value: raw, consumedPaths: [fieldPath] };
|
|
910
|
+
const parsed = cliGenerationConfigSchema.shape[field].safeParse(value);
|
|
911
|
+
consumedPaths.forEach((path) => consume(state, path));
|
|
912
|
+
if (parsed.success) {
|
|
913
|
+
generation[field] = structuredClone(value);
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
const diagnostics = parsed.error.issues.map(
|
|
917
|
+
(issue) => invalidValueDiagnostic(field, fieldPath, issue.path, issue.message, targetIndex)
|
|
918
|
+
);
|
|
919
|
+
(state.valueDiagnostics ??= []).push(...diagnostics);
|
|
920
|
+
}
|
|
921
|
+
return generation;
|
|
922
|
+
}
|
|
923
|
+
function pickProfiles(profiles, path) {
|
|
924
|
+
const picked = pickKnown(profiles, PROFILES_FIELDS, path);
|
|
925
|
+
const provisionOperation = ownValue(profiles, "provisionOperation");
|
|
926
|
+
const provisionPath = [...path, "provisionOperation"];
|
|
927
|
+
if (isObject(provisionOperation)) {
|
|
928
|
+
const provision = pickKnown(provisionOperation, PROVISION_OPERATION_FIELDS, provisionPath);
|
|
929
|
+
picked.value.provisionOperation = provision.value;
|
|
930
|
+
picked.consumedPaths.push(...provision.consumedPaths);
|
|
931
|
+
} else if (provisionOperation !== void 0) {
|
|
932
|
+
picked.value.provisionOperation = provisionOperation;
|
|
933
|
+
picked.consumedPaths.push(provisionPath);
|
|
934
|
+
}
|
|
935
|
+
return { value: { enabled: false, ...picked.value }, consumedPaths: picked.consumedPaths };
|
|
936
|
+
}
|
|
937
|
+
function pickKnown(value, fields, path) {
|
|
938
|
+
const picked = {};
|
|
939
|
+
const consumedPaths = [];
|
|
940
|
+
for (const field of fields) {
|
|
941
|
+
const child = ownValue(value, field);
|
|
942
|
+
if (child === void 0) continue;
|
|
943
|
+
picked[field] = child;
|
|
944
|
+
consumedPaths.push([...path, field]);
|
|
945
|
+
}
|
|
946
|
+
return { value: picked, consumedPaths };
|
|
947
|
+
}
|
|
948
|
+
function ownValue(value, key) {
|
|
949
|
+
return Object.hasOwn(value, key) ? value[key] : void 0;
|
|
950
|
+
}
|
|
951
|
+
function invalidValueDiagnostic(field, fieldPath, issuePath, message, targetIndex) {
|
|
952
|
+
const relative = issuePath.map((part) => typeof part === "symbol" ? String(part) : part);
|
|
953
|
+
const sdkConfigField = ["targets", targetIndex, "generation", field];
|
|
954
|
+
return {
|
|
955
|
+
code: "FERN_CONFIG_VALUE_INVALID",
|
|
956
|
+
severity: "warning",
|
|
957
|
+
path: [...fieldPath, ...relative],
|
|
958
|
+
reason: `CLI setting ${field} was not migrated because SDK Config rejects it: ${message}`,
|
|
959
|
+
sdkConfigPath: [...sdkConfigField, ...relative],
|
|
960
|
+
suggestedAction: `Correct the value, then set ${sdkConfigField.join(".")} manually.`
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// src/sdk-config/v1/fern-config-mapper-cli-distribution.ts
|
|
965
|
+
var DISTRIBUTION_KEYS = {
|
|
966
|
+
githubApp: { appIdSecret: "appIdSecretName", privateKeySecret: "privateKeySecretName" },
|
|
967
|
+
homebrew: { tap: "tap", formula: "formula", tokenEnvironmentVariable: "tokenSecretName" },
|
|
968
|
+
scoop: { bucket: "bucket", tokenEnvironmentVariable: "tokenSecretName" }
|
|
969
|
+
};
|
|
970
|
+
function mapCliDistribution(config, state, basePath, targetIndex) {
|
|
971
|
+
if (!Object.hasOwn(config, "distribution")) return;
|
|
972
|
+
const raw = config.distribution;
|
|
973
|
+
const path = [...basePath, "distribution"];
|
|
974
|
+
const translated = isObject(raw) ? translateDistribution(raw, path) : { value: raw, consumedPaths: [path], legacyKeys: /* @__PURE__ */ new Map() };
|
|
975
|
+
const parsed = cliDistributionConfigSchema.safeParse(translated.value);
|
|
976
|
+
translated.consumedPaths.forEach((consumedPath) => consume(state, consumedPath));
|
|
977
|
+
if (parsed.success) {
|
|
978
|
+
state.cliDistribution = { value: parsed.data, path };
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
const diagnostics = parsed.error.issues.map(
|
|
982
|
+
(issue) => invalidDistributionDiagnostic(issue, path, translated.legacyKeys, targetIndex)
|
|
983
|
+
);
|
|
984
|
+
const reportedPaths = /* @__PURE__ */ new Set();
|
|
985
|
+
(state.valueDiagnostics ??= []).push(
|
|
986
|
+
...diagnostics.filter(({ path: diagnosticPath }) => {
|
|
987
|
+
const key = diagnosticPath.join(".");
|
|
988
|
+
if (reportedPaths.has(key)) return false;
|
|
989
|
+
reportedPaths.add(key);
|
|
990
|
+
return true;
|
|
991
|
+
})
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
function translateDistribution(distribution, path) {
|
|
995
|
+
const value = {};
|
|
996
|
+
const consumedPaths = [];
|
|
997
|
+
const legacyKeys = /* @__PURE__ */ new Map();
|
|
998
|
+
for (const [block, keys] of Object.entries(DISTRIBUTION_KEYS)) {
|
|
999
|
+
if (!Object.hasOwn(distribution, block)) continue;
|
|
1000
|
+
const blockValue = distribution[block];
|
|
1001
|
+
const blockPath = [...path, block];
|
|
1002
|
+
if (!isObject(blockValue)) {
|
|
1003
|
+
value[block] = blockValue;
|
|
1004
|
+
consumedPaths.push(blockPath);
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
const translatedBlock = {};
|
|
1008
|
+
for (const [legacyKey, sdkConfigKey] of Object.entries(keys)) {
|
|
1009
|
+
if (!Object.hasOwn(blockValue, legacyKey)) continue;
|
|
1010
|
+
translatedBlock[sdkConfigKey] = blockValue[legacyKey];
|
|
1011
|
+
consumedPaths.push([...blockPath, legacyKey]);
|
|
1012
|
+
legacyKeys.set(`${block}.${sdkConfigKey}`, legacyKey);
|
|
1013
|
+
}
|
|
1014
|
+
value[block] = translatedBlock;
|
|
1015
|
+
}
|
|
1016
|
+
return { value, consumedPaths, legacyKeys };
|
|
1017
|
+
}
|
|
1018
|
+
function invalidDistributionDiagnostic(issue, path, legacyKeys, targetIndex) {
|
|
1019
|
+
const relative = issue.path.map((part) => typeof part === "symbol" ? String(part) : part);
|
|
1020
|
+
const [block, field] = relative;
|
|
1021
|
+
const legacyField = typeof block === "string" && typeof field === "string" ? legacyKeys.get(`${block}.${field}`) : void 0;
|
|
1022
|
+
const legacyRelative = typeof block === "string" && legacyField !== void 0 ? [block, legacyField] : relative;
|
|
1023
|
+
const sdkConfigField = ["targets", targetIndex, "output", "distribution"];
|
|
1024
|
+
return {
|
|
1025
|
+
code: "FERN_CONFIG_VALUE_INVALID",
|
|
1026
|
+
severity: "warning",
|
|
1027
|
+
path: [...path, ...legacyRelative],
|
|
1028
|
+
reason: `CLI distribution was not migrated because SDK Config rejects it: ${issue.message}`,
|
|
1029
|
+
sdkConfigPath: [...sdkConfigField, ...relative],
|
|
1030
|
+
suggestedAction: `Correct the value, then set ${sdkConfigField.join(".")} manually.`
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
function applyCliDistribution(output, pending, targetIndex) {
|
|
1034
|
+
if (pending === void 0) return { output, diagnostics: [] };
|
|
1035
|
+
if (output.delivery === "github") {
|
|
1036
|
+
return { output: { ...output, distribution: pending.value }, diagnostics: [] };
|
|
1037
|
+
}
|
|
1038
|
+
const outputPath = ["targets", targetIndex, "output"];
|
|
1039
|
+
return {
|
|
1040
|
+
output,
|
|
1041
|
+
diagnostics: [
|
|
1042
|
+
{
|
|
1043
|
+
code: "FERN_CLI_DISTRIBUTION_REQUIRES_GITHUB_OUTPUT",
|
|
1044
|
+
severity: "warning",
|
|
1045
|
+
path: pending.path,
|
|
1046
|
+
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`,
|
|
1047
|
+
sdkConfigPath: [...outputPath, "distribution"],
|
|
1048
|
+
suggestedAction: `Set ${outputPath.join(".")}.delivery to "github" for the CLI repository and add ${outputPath.join(".")}.distribution manually, or remove distribution.`
|
|
1049
|
+
}
|
|
1050
|
+
]
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
666
1053
|
|
|
667
1054
|
// src/sdk-config/v1/fern-config-mapper-output.ts
|
|
668
1055
|
function mapOutput(generator, language, index) {
|
|
@@ -671,8 +1058,19 @@ function mapOutput(generator, language, index) {
|
|
|
671
1058
|
const outputPath = ["group", "generators", index, "outputMode"];
|
|
672
1059
|
const state = { consumedPaths: /* @__PURE__ */ new Set(), credentialDiagnostics: [] };
|
|
673
1060
|
if (generator.output) {
|
|
1061
|
+
const downloadSnippets = mapDownloadSnippets(
|
|
1062
|
+
generator.outputMode,
|
|
1063
|
+
outputPath,
|
|
1064
|
+
state,
|
|
1065
|
+
language,
|
|
1066
|
+
index
|
|
1067
|
+
);
|
|
674
1068
|
return {
|
|
675
1069
|
output: sanitizeNormalizedOutput(generator.output, rawOutput, state, index),
|
|
1070
|
+
...optional(
|
|
1071
|
+
"docs",
|
|
1072
|
+
downloadSnippets === void 0 ? void 0 : { snippets: { enabled: downloadSnippets } }
|
|
1073
|
+
),
|
|
676
1074
|
unsupportedFields: state.credentialDiagnostics ?? []
|
|
677
1075
|
};
|
|
678
1076
|
}
|
|
@@ -688,7 +1086,8 @@ function mapOutput(generator, language, index) {
|
|
|
688
1086
|
generator.outputMode,
|
|
689
1087
|
outputPath,
|
|
690
1088
|
state,
|
|
691
|
-
index
|
|
1089
|
+
index,
|
|
1090
|
+
language
|
|
692
1091
|
);
|
|
693
1092
|
}
|
|
694
1093
|
if (!isObject(generator.outputMode) || typeof generator.outputMode.type !== "string") {
|
|
@@ -704,14 +1103,22 @@ function mapOutput(generator, language, index) {
|
|
|
704
1103
|
consume(state, [...outputPath, "type"]);
|
|
705
1104
|
switch (output.type) {
|
|
706
1105
|
case "downloadFiles":
|
|
707
|
-
return finishOutputMapping(
|
|
1106
|
+
return finishOutputMapping(
|
|
1107
|
+
{ output: { delivery: "zip" } },
|
|
1108
|
+
output,
|
|
1109
|
+
outputPath,
|
|
1110
|
+
state,
|
|
1111
|
+
index,
|
|
1112
|
+
language
|
|
1113
|
+
);
|
|
708
1114
|
case "github":
|
|
709
1115
|
return finishOutputMapping(
|
|
710
1116
|
githubOutput(output, output.publishInfo, rawOutput, language, outputPath, state, index),
|
|
711
1117
|
output,
|
|
712
1118
|
outputPath,
|
|
713
1119
|
state,
|
|
714
|
-
index
|
|
1120
|
+
index,
|
|
1121
|
+
language
|
|
715
1122
|
);
|
|
716
1123
|
case "githubV2": {
|
|
717
1124
|
if (!isObject(output.githubV2))
|
|
@@ -736,7 +1143,8 @@ function mapOutput(generator, language, index) {
|
|
|
736
1143
|
output,
|
|
737
1144
|
outputPath,
|
|
738
1145
|
state,
|
|
739
|
-
index
|
|
1146
|
+
index,
|
|
1147
|
+
language
|
|
740
1148
|
);
|
|
741
1149
|
}
|
|
742
1150
|
case "publishV2": {
|
|
@@ -756,7 +1164,8 @@ function mapOutput(generator, language, index) {
|
|
|
756
1164
|
output,
|
|
757
1165
|
outputPath,
|
|
758
1166
|
state,
|
|
759
|
-
index
|
|
1167
|
+
index,
|
|
1168
|
+
language
|
|
760
1169
|
);
|
|
761
1170
|
}
|
|
762
1171
|
case "publish": {
|
|
@@ -776,7 +1185,8 @@ function mapOutput(generator, language, index) {
|
|
|
776
1185
|
output,
|
|
777
1186
|
outputPath,
|
|
778
1187
|
state,
|
|
779
|
-
index
|
|
1188
|
+
index,
|
|
1189
|
+
language
|
|
780
1190
|
);
|
|
781
1191
|
}
|
|
782
1192
|
default:
|
|
@@ -850,11 +1260,10 @@ function githubOutput(value, publishInfo, rawOutput, language, sourcePath, state
|
|
|
850
1260
|
...optionalObject("package", { ...publication?.package, ...licensePackage })
|
|
851
1261
|
};
|
|
852
1262
|
}
|
|
853
|
-
var basicLicenseTypes = { mit: "MIT", apache: "APACHE" };
|
|
854
1263
|
function mapGithubLicense(value, sourcePath, state) {
|
|
855
1264
|
if (!isObject(value) || stringValue(value.type) !== "basic") return {};
|
|
856
1265
|
const id = stringValue(value.id);
|
|
857
|
-
const type = id ?
|
|
1266
|
+
const type = id ? canonicalLicenseType(id) : void 0;
|
|
858
1267
|
if (!type) return {};
|
|
859
1268
|
consume(state, [...sourcePath, "type"]);
|
|
860
1269
|
consume(state, [...sourcePath, "id"]);
|
|
@@ -1283,7 +1692,8 @@ function mapAuthors(value, sourcePath, state) {
|
|
|
1283
1692
|
});
|
|
1284
1693
|
return authors;
|
|
1285
1694
|
}
|
|
1286
|
-
function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
|
|
1695
|
+
function finishOutputMapping(mapping, outputMode, sourcePath, state, index, language) {
|
|
1696
|
+
const downloadSnippets = mapDownloadSnippets(outputMode, sourcePath, state, language, index);
|
|
1287
1697
|
for (const path of collectLeafPaths(outputMode, sourcePath)) {
|
|
1288
1698
|
if (path[path.length - 1] === "_visit") consume(state, path);
|
|
1289
1699
|
}
|
|
@@ -1291,6 +1701,10 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
|
|
|
1291
1701
|
const hasCredentials = unsupported.some((diagnostic) => isCredentialPath(diagnostic.path));
|
|
1292
1702
|
return {
|
|
1293
1703
|
...mapping,
|
|
1704
|
+
...optional(
|
|
1705
|
+
"docs",
|
|
1706
|
+
downloadSnippets === void 0 ? void 0 : { snippets: { enabled: downloadSnippets } }
|
|
1707
|
+
),
|
|
1294
1708
|
unsupportedFields: [
|
|
1295
1709
|
...state.credentialDiagnostics ?? [],
|
|
1296
1710
|
...hasCredentials ? [
|
|
@@ -1310,6 +1724,45 @@ function finishOutputMapping(mapping, outputMode, sourcePath, state, index) {
|
|
|
1310
1724
|
]
|
|
1311
1725
|
};
|
|
1312
1726
|
}
|
|
1727
|
+
function mapDownloadSnippets(value, sourcePath, state, language, index) {
|
|
1728
|
+
if (!isObject(value)) return void 0;
|
|
1729
|
+
const candidates = [];
|
|
1730
|
+
switch (value.type) {
|
|
1731
|
+
case "downloadFiles":
|
|
1732
|
+
case "github":
|
|
1733
|
+
candidates.push({ value, path: sourcePath });
|
|
1734
|
+
break;
|
|
1735
|
+
case "githubV2":
|
|
1736
|
+
if (isObject(value.githubV2)) {
|
|
1737
|
+
candidates.push({ value: value.githubV2, path: [...sourcePath, "githubV2"] });
|
|
1738
|
+
}
|
|
1739
|
+
break;
|
|
1740
|
+
case "publishV2":
|
|
1741
|
+
if (isObject(value.publishV2)) {
|
|
1742
|
+
candidates.push({ value: value.publishV2, path: [...sourcePath, "publishV2"] });
|
|
1743
|
+
}
|
|
1744
|
+
break;
|
|
1745
|
+
case "publish":
|
|
1746
|
+
if (isObject(value.registryOverrides)) {
|
|
1747
|
+
const registry = defaultRegistry(language, [...sourcePath, "registryOverrides"], index);
|
|
1748
|
+
const override = value.registryOverrides[registry];
|
|
1749
|
+
if (isObject(override)) {
|
|
1750
|
+
candidates.push({
|
|
1751
|
+
value: override,
|
|
1752
|
+
path: [...sourcePath, "registryOverrides", registry]
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
break;
|
|
1757
|
+
}
|
|
1758
|
+
let enabled;
|
|
1759
|
+
for (const candidate of candidates) {
|
|
1760
|
+
if (typeof candidate.value.downloadSnippets !== "boolean") continue;
|
|
1761
|
+
consume(state, [...candidate.path, "downloadSnippets"]);
|
|
1762
|
+
enabled = enabled === true || candidate.value.downloadSnippets;
|
|
1763
|
+
}
|
|
1764
|
+
return enabled;
|
|
1765
|
+
}
|
|
1313
1766
|
function isCredentialPath(path) {
|
|
1314
1767
|
const fields = path.filter((part) => typeof part === "string");
|
|
1315
1768
|
const field = fields[fields.length - 1];
|
|
@@ -1377,6 +1830,114 @@ function outputDiagnostic(path, index) {
|
|
|
1377
1830
|
suggestedAction: resolvedGuidance?.suggestedAction ?? "Review this output setting and preserve it outside SDK Config when no equivalent exists."
|
|
1378
1831
|
};
|
|
1379
1832
|
}
|
|
1833
|
+
|
|
1834
|
+
// src/sdk-config/v1/package.ts
|
|
1835
|
+
var sdkConfigV1DependencySchema = dependencySchema;
|
|
1836
|
+
var sdkConfigV1PackageConfigSchema = packageConfigSchema;
|
|
1837
|
+
|
|
1838
|
+
// src/sdk-config/v1/fern-config-mapper-package.ts
|
|
1839
|
+
var emailSchema = z.email();
|
|
1840
|
+
function mapCliPackageIdentity(identity, state, targetIndex) {
|
|
1841
|
+
mapIdentityField(identity, "homepage", stringValue, state);
|
|
1842
|
+
mapIdentityField(identity, "keywords", (value) => stringArrayValue(value)?.slice(), state);
|
|
1843
|
+
mapCargoAuthors(identity, state, targetIndex);
|
|
1844
|
+
mapIdentityField(identity, "license", licenseValue, state);
|
|
1845
|
+
}
|
|
1846
|
+
function mapIdentityField(identity, field, read, state) {
|
|
1847
|
+
const located = locate(identity.value, [field], identity.path);
|
|
1848
|
+
const value = located && read(located.value);
|
|
1849
|
+
if (located && value !== void 0) addPackageFallback(state, field, value, located.path);
|
|
1850
|
+
}
|
|
1851
|
+
function mapLicenseFallback(config, aliases, state, basePath) {
|
|
1852
|
+
const located = locate(config, aliases, basePath);
|
|
1853
|
+
const license = located && licenseValue(located.value);
|
|
1854
|
+
if (located && license) addPackageFallback(state, "license", license, located.path);
|
|
1855
|
+
}
|
|
1856
|
+
function resolveTargetPackage(targetPackage, fallbacks, generator, delivery, index) {
|
|
1857
|
+
const diagnostics = [];
|
|
1858
|
+
for (const fallback of fallbacks) {
|
|
1859
|
+
applyFallback(targetPackage, fallback, index, diagnostics);
|
|
1860
|
+
}
|
|
1861
|
+
if (delivery !== "github") {
|
|
1862
|
+
applyMetadataLicense(targetPackage, generator.raw, index, diagnostics);
|
|
1863
|
+
}
|
|
1864
|
+
return diagnostics;
|
|
1865
|
+
}
|
|
1866
|
+
function applyFallback(targetPackage, { field, value, path }, index, diagnostics) {
|
|
1867
|
+
const existing = targetPackage[field];
|
|
1868
|
+
if (existing === void 0) {
|
|
1869
|
+
targetPackage[field] = value;
|
|
1870
|
+
} else if (stableJson(existing) !== stableJson(value)) {
|
|
1871
|
+
diagnostics.push({
|
|
1872
|
+
code: "FERN_PACKAGE_VALUE_CONFLICT",
|
|
1873
|
+
severity: "warning",
|
|
1874
|
+
path,
|
|
1875
|
+
reason: `Fern value conflicts with the package.${field} already migrated for this target, which is kept`,
|
|
1876
|
+
sdkConfigPath: ["targets", index, "package", field],
|
|
1877
|
+
suggestedAction: `Choose the intended value and set targets.${index}.package.${field} manually.`
|
|
1878
|
+
});
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
function applyMetadataLicense(targetPackage, raw, index, diagnostics) {
|
|
1882
|
+
const metadata = isObject(raw) && isObject(raw.metadata) ? raw.metadata : void 0;
|
|
1883
|
+
if (metadata?.license === void 0 || metadata.license === null) return;
|
|
1884
|
+
const path = ["group", "generators", index, "metadata", "license"];
|
|
1885
|
+
const license = licenseValue(metadata.license);
|
|
1886
|
+
if (license) {
|
|
1887
|
+
applyFallback(targetPackage, { field: "license", value: license, path }, index, diagnostics);
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
diagnostics.push({
|
|
1891
|
+
code: "FERN_CONFIG_FIELD_UNSUPPORTED",
|
|
1892
|
+
severity: "warning",
|
|
1893
|
+
path,
|
|
1894
|
+
reason: isObject(metadata.license) ? "A custom license file cannot be migrated automatically" : "metadata.license is not a license identifier",
|
|
1895
|
+
sdkConfigPath: ["targets", index, "package", "license"],
|
|
1896
|
+
suggestedAction: `Set targets.${index}.package.license manually.`
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
function mapCargoAuthors(identity, state, targetIndex) {
|
|
1900
|
+
const located = locate(identity.value, ["authors"], identity.path);
|
|
1901
|
+
const entries = located && stringArrayValue(located.value);
|
|
1902
|
+
if (!located || !entries) return;
|
|
1903
|
+
consume(state, located.path);
|
|
1904
|
+
const authors = entries.map(parseCargoAuthor);
|
|
1905
|
+
const parsed = sdkConfigV1PackageConfigSchema.shape.authors.safeParse(authors);
|
|
1906
|
+
const invalid = parsed.success ? [] : [...new Set(parsed.error.issues.map((issue) => issue.path[0]))].filter(
|
|
1907
|
+
(index) => typeof index === "number"
|
|
1908
|
+
);
|
|
1909
|
+
if (invalid.length === 0) {
|
|
1910
|
+
addPackageFallback(state, "authors", authors, located.path);
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
const authorsPath = ["targets", targetIndex, "package", "authors"];
|
|
1914
|
+
(state.valueDiagnostics ??= []).push(
|
|
1915
|
+
...invalid.map((entry) => ({
|
|
1916
|
+
code: "FERN_CONFIG_VALUE_INVALID",
|
|
1917
|
+
severity: "warning",
|
|
1918
|
+
path: [...located.path, entry],
|
|
1919
|
+
reason: 'CLI packageIdentity.authors was not migrated because this entry is not "Name" or "Name <email>" with a valid email',
|
|
1920
|
+
sdkConfigPath: authorsPath,
|
|
1921
|
+
suggestedAction: `Correct the entry, then set ${authorsPath.join(".")} manually.`
|
|
1922
|
+
}))
|
|
1923
|
+
);
|
|
1924
|
+
}
|
|
1925
|
+
function parseCargoAuthor(entry) {
|
|
1926
|
+
const trimmed = entry.trim();
|
|
1927
|
+
const match = /^(.*?)\s*<([^<>]*)>$/.exec(trimmed);
|
|
1928
|
+
if (!match) return { name: trimmed };
|
|
1929
|
+
const [, name = "", email = ""] = match;
|
|
1930
|
+
if (name !== "" && !emailSchema.safeParse(email).success) return { name: trimmed };
|
|
1931
|
+
return { name, email };
|
|
1932
|
+
}
|
|
1933
|
+
function licenseValue(value) {
|
|
1934
|
+
const license = stringValue(value)?.trim();
|
|
1935
|
+
return license ? { type: canonicalLicenseType(license) ?? license } : void 0;
|
|
1936
|
+
}
|
|
1937
|
+
function addPackageFallback(state, field, value, path) {
|
|
1938
|
+
consume(state, path);
|
|
1939
|
+
(state.packageFallbacks ??= []).push({ field, value, path });
|
|
1940
|
+
}
|
|
1380
1941
|
var OMIT = /* @__PURE__ */ Symbol("omit");
|
|
1381
1942
|
function inputJsonSchema(schema) {
|
|
1382
1943
|
return z.toJSONSchema(schema, {
|
|
@@ -1646,7 +2207,16 @@ var sdkConfigV1PublishConfigSchema = z.discriminatedUnion("registry", [
|
|
|
1646
2207
|
z.strictObject({
|
|
1647
2208
|
registry: z.literal("npm").describe("Publishes the package to an npm-compatible registry."),
|
|
1648
2209
|
token: nonEmptyStringSchema.optional().describe("The npm registry token, or an environment expression that resolves to it."),
|
|
2210
|
+
trustedPublishing: z.boolean().optional().describe("Whether npm publication uses trusted publishing (OIDC) instead of a token."),
|
|
1649
2211
|
...commonPublishShape
|
|
2212
|
+
}).superRefine((publish, context) => {
|
|
2213
|
+
if (publish.trustedPublishing === true && publish.token !== void 0) {
|
|
2214
|
+
context.addIssue({
|
|
2215
|
+
code: "custom",
|
|
2216
|
+
message: "token must be omitted when trustedPublishing is true",
|
|
2217
|
+
path: ["token"]
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
1650
2220
|
}),
|
|
1651
2221
|
z.strictObject({
|
|
1652
2222
|
registry: z.literal("pypi").describe("Publishes the package to a PyPI-compatible registry."),
|
|
@@ -1724,10 +2294,29 @@ var sdkConfigV1OutputConfigSchema = z.discriminatedUnion(
|
|
|
1724
2294
|
[filesOutputSchema, zipOutputSchema, githubDeliverySchema],
|
|
1725
2295
|
{ error: 'output.delivery must be one of "files", "zip", or "github"' }
|
|
1726
2296
|
);
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
2297
|
+
var cliDistributionShape = {
|
|
2298
|
+
distribution: cliDistributionConfigSchema.optional().describe(
|
|
2299
|
+
"CLI release channels published by the generated release workflow; credentials are GitHub Actions secret names."
|
|
2300
|
+
)
|
|
2301
|
+
};
|
|
2302
|
+
function rejectDistributionWithoutGithub(output, context) {
|
|
2303
|
+
if (output.distribution !== void 0) {
|
|
2304
|
+
context.addIssue({
|
|
2305
|
+
code: "custom",
|
|
2306
|
+
message: CLI_DISTRIBUTION_REQUIRES_GITHUB_DELIVERY_MESSAGE,
|
|
2307
|
+
path: ["distribution"]
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
var sdkConfigV1CliOutputConfigSchema = z.discriminatedUnion(
|
|
2312
|
+
"delivery",
|
|
2313
|
+
[
|
|
2314
|
+
filesOutputSchema.extend(cliDistributionShape).superRefine(rejectDistributionWithoutGithub),
|
|
2315
|
+
zipOutputSchema.extend(cliDistributionShape).superRefine(rejectDistributionWithoutGithub),
|
|
2316
|
+
githubDeliverySchema.extend(cliDistributionShape)
|
|
2317
|
+
],
|
|
2318
|
+
{ error: 'output.delivery must be one of "files", "zip", or "github"' }
|
|
2319
|
+
);
|
|
1731
2320
|
var sdkConfigV1ReplayConfigSchema = z.strictObject({
|
|
1732
2321
|
enabled: z.boolean().describe("Whether regeneration reapplies customer-authored repository changes.")
|
|
1733
2322
|
});
|
|
@@ -1804,10 +2393,6 @@ var sdkConfigV1SourceConfigSchema = z.strictObject({
|
|
|
1804
2393
|
seenIds.add(id);
|
|
1805
2394
|
});
|
|
1806
2395
|
});
|
|
1807
|
-
var cliGenerationConfigSchema = z.strictObject({
|
|
1808
|
-
paginationParameters: z.array(nonEmptyStringSchema).optional().describe("Request parameter names treated as pagination controls by the CLI."),
|
|
1809
|
-
skills: z.boolean().optional().describe("Whether the generated CLI includes skills that teach AI agents to invoke commands.")
|
|
1810
|
-
});
|
|
1811
2396
|
var csharpGenerationConfigSchema = z.strictObject({
|
|
1812
2397
|
useOptionalWrapper: z.boolean().optional().describe("Whether optional values use an explicit Optional wrapper."),
|
|
1813
2398
|
simplifyObjectDictionaries: z.boolean().optional().describe("Whether object schemas with arbitrary values use simplified dictionary types."),
|
|
@@ -2060,7 +2645,10 @@ var sdkConfigV1TargetSchema = z.discriminatedUnion("language", [
|
|
|
2060
2645
|
z.strictObject({
|
|
2061
2646
|
language: z.literal("cli").describe("Generates a command-line interface."),
|
|
2062
2647
|
generation: sdkConfigV1GenerationConfigOverrideSchema.extend(cliGenerationConfigSchema.shape).optional().describe("Common and CLI-specific generation settings for this target."),
|
|
2063
|
-
...targetOverrideShape
|
|
2648
|
+
...targetOverrideShape,
|
|
2649
|
+
output: sdkConfigV1CliOutputConfigSchema.optional().describe(
|
|
2650
|
+
"Output configuration, including optional CLI distribution channels, that replaces the root output for this target."
|
|
2651
|
+
)
|
|
2064
2652
|
}),
|
|
2065
2653
|
z.strictObject({
|
|
2066
2654
|
language: z.literal("mcp").describe("Generates an MCP server."),
|
|
@@ -2077,7 +2665,7 @@ var sdkConfigV1TargetSchema = z.discriminatedUnion("language", [
|
|
|
2077
2665
|
// src/sdk-config/v1/sdk-config-v1.ts
|
|
2078
2666
|
var SDK_CONFIG_V1_SCHEMA_VERSION = "sdk-config/v1";
|
|
2079
2667
|
var publishRegistryLanguages = {
|
|
2080
|
-
npm: ["typescript", "mcp"],
|
|
2668
|
+
npm: ["typescript", "mcp", "cli"],
|
|
2081
2669
|
pypi: ["python"],
|
|
2082
2670
|
maven: ["java", "kotlin"],
|
|
2083
2671
|
nuget: ["csharp"],
|
|
@@ -2154,6 +2742,13 @@ function validateTargetPublishing(target, targetIndex, globalPackage, globalOutp
|
|
|
2154
2742
|
});
|
|
2155
2743
|
return;
|
|
2156
2744
|
}
|
|
2745
|
+
if (target.language === "cli" && output.delivery !== "github") {
|
|
2746
|
+
context.addIssue({
|
|
2747
|
+
code: "custom",
|
|
2748
|
+
message: CLI_PUBLISH_REQUIRES_GITHUB_DELIVERY_MESSAGE,
|
|
2749
|
+
path: target.output ? ["targets", targetIndex, "output", "delivery"] : ["output", "delivery"]
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2157
2752
|
validatePublishingIdentity(
|
|
2158
2753
|
{ ...globalPackage, ...target.package },
|
|
2159
2754
|
registry,
|
|
@@ -2245,11 +2840,12 @@ function mapFernConfigToSdkConfigV1(input) {
|
|
|
2245
2840
|
generator,
|
|
2246
2841
|
language,
|
|
2247
2842
|
invocation,
|
|
2248
|
-
...outputMapping
|
|
2843
|
+
...outputMapping,
|
|
2844
|
+
docs: { ...invocation.docs, ...outputMapping.docs }
|
|
2249
2845
|
};
|
|
2250
2846
|
});
|
|
2251
2847
|
const clients = partitionSharedBlock(mapped.map(({ invocation }) => invocation.client));
|
|
2252
|
-
const docs = partitionSharedBlock(mapped.map(({
|
|
2848
|
+
const docs = partitionSharedBlock(mapped.map(({ docs: docs2 }) => docs2));
|
|
2253
2849
|
const generations = partitionSharedBlock(mapped.map(({ invocation }) => invocation.generation));
|
|
2254
2850
|
const api = { ...input.api ?? {} };
|
|
2255
2851
|
delete api.audiences;
|
|
@@ -2265,16 +2861,28 @@ function mapFernConfigToSdkConfigV1(input) {
|
|
|
2265
2861
|
package: outputPackage,
|
|
2266
2862
|
generation: outputGeneration
|
|
2267
2863
|
}, index) => {
|
|
2864
|
+
const distribution = applyCliDistribution(output, invocation.cliDistribution, index);
|
|
2865
|
+
invocation.unsupportedFields.push(...distribution.diagnostics);
|
|
2268
2866
|
const target = {
|
|
2269
2867
|
language,
|
|
2270
|
-
output,
|
|
2868
|
+
output: distribution.output,
|
|
2271
2869
|
...optional("sdkName", generator.sdkName),
|
|
2272
2870
|
...optional("sdkVersion", generator.sdkVersion),
|
|
2273
2871
|
...optional("client", clients.targetOverrides[index]),
|
|
2274
2872
|
...optional("docs", docs.targetOverrides[index])
|
|
2275
2873
|
};
|
|
2276
|
-
|
|
2277
|
-
|
|
2874
|
+
const targetPackage = { ...invocation.package, ...outputPackage, ...generator.package };
|
|
2875
|
+
invocation.unsupportedFields.push(
|
|
2876
|
+
...resolveTargetPackage(
|
|
2877
|
+
targetPackage,
|
|
2878
|
+
invocation.packageFallbacks,
|
|
2879
|
+
generator,
|
|
2880
|
+
output.delivery,
|
|
2881
|
+
index
|
|
2882
|
+
)
|
|
2883
|
+
);
|
|
2884
|
+
if (Object.keys(targetPackage).length > 0 || outputPackage || generator.package) {
|
|
2885
|
+
target.package = targetPackage;
|
|
2278
2886
|
}
|
|
2279
2887
|
const targetGeneration = {
|
|
2280
2888
|
...generations.targetOverrides[index],
|
|
@@ -2456,10 +3064,14 @@ function mapInvocation(generator, language, activeLanguages, index) {
|
|
|
2456
3064
|
...optional("smartCasingDigitWordBoundary", smartCasingDigitWordBoundary)
|
|
2457
3065
|
};
|
|
2458
3066
|
}
|
|
2459
|
-
const targetGeneration = mapLanguageConfig(
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
3067
|
+
const targetGeneration = mapLanguageConfig(
|
|
3068
|
+
language,
|
|
3069
|
+
config,
|
|
3070
|
+
state,
|
|
3071
|
+
packageConfig,
|
|
3072
|
+
[...prefix, "config"],
|
|
3073
|
+
index
|
|
3074
|
+
);
|
|
2463
3075
|
mapPublishMetadata(generator.publishMetadata, packageConfig);
|
|
2464
3076
|
if (generator.keywords?.length) {
|
|
2465
3077
|
generation.reservedKeywords = [...generator.keywords];
|
|
@@ -2476,12 +3088,22 @@ function mapInvocation(generator, language, activeLanguages, index) {
|
|
|
2476
3088
|
}
|
|
2477
3089
|
const docs = mapReadme(generator.readme, language, activeLanguages, state, [...prefix, "readme"]);
|
|
2478
3090
|
const unsupportedFields = [
|
|
3091
|
+
...state.valueDiagnostics ?? [],
|
|
2479
3092
|
...collectUnsupported(config, [...prefix, "config"], state),
|
|
2480
3093
|
...settings ? collectUnsupported(settings, [...prefix, "settings"], state) : [],
|
|
2481
3094
|
...isObject(generator.readme) ? collectUnsupported(generator.readme, [...prefix, "readme"], state) : [],
|
|
2482
3095
|
...unsupportedResolvedFields(generator, index, apiWideIdempotency !== void 0)
|
|
2483
3096
|
];
|
|
2484
|
-
return {
|
|
3097
|
+
return {
|
|
3098
|
+
client,
|
|
3099
|
+
docs,
|
|
3100
|
+
generation,
|
|
3101
|
+
package: packageConfig,
|
|
3102
|
+
packageFallbacks: state.packageFallbacks ?? [],
|
|
3103
|
+
...optional("cliDistribution", state.cliDistribution),
|
|
3104
|
+
targetGeneration,
|
|
3105
|
+
unsupportedFields
|
|
3106
|
+
};
|
|
2485
3107
|
}
|
|
2486
3108
|
function unsupportedResolvedFields(generator, index, idempotencyMapped) {
|
|
2487
3109
|
const values = [
|
|
@@ -2671,6 +3293,7 @@ function mapCommonConfig(language, config, state, client, generation, packageCon
|
|
|
2671
3293
|
const packagePath = takeString(config, ["packagePath"], state, basePath);
|
|
2672
3294
|
if (packagePath !== void 0) generation.layout = { packagePath };
|
|
2673
3295
|
mapDependencies(config, state, packageConfig, basePath);
|
|
3296
|
+
mapPeerDependenciesMeta(config, state, packageConfig, basePath);
|
|
2674
3297
|
}
|
|
2675
3298
|
function mapTypescriptStreams(config, state, basePath) {
|
|
2676
3299
|
const responseType = takeEnum(config, ["streamType"], ["wrapper", "web"], state, basePath);
|
|
@@ -2684,7 +3307,7 @@ function mapTypescriptStreams(config, state, basePath) {
|
|
|
2684
3307
|
if (responseType === void 0 && fileResponseType === void 0) return void 0;
|
|
2685
3308
|
return { enabled: true, ...compact({ responseType, fileResponseType }) };
|
|
2686
3309
|
}
|
|
2687
|
-
function mapLanguageConfig(language, config, state, packageConfig, basePath) {
|
|
3310
|
+
function mapLanguageConfig(language, config, state, packageConfig, basePath, targetIndex) {
|
|
2688
3311
|
switch (language) {
|
|
2689
3312
|
case "typescript":
|
|
2690
3313
|
return mapTypescript(config, state, packageConfig, basePath);
|
|
@@ -2711,7 +3334,7 @@ function mapLanguageConfig(language, config, state, packageConfig, basePath) {
|
|
|
2711
3334
|
case "swift":
|
|
2712
3335
|
return mapSwift(config, state, basePath);
|
|
2713
3336
|
case "cli":
|
|
2714
|
-
return mapCli(config, state, packageConfig, basePath);
|
|
3337
|
+
return mapCli(config, state, packageConfig, basePath, targetIndex);
|
|
2715
3338
|
case "terraform":
|
|
2716
3339
|
return mapTerraform(config, state, packageConfig, basePath);
|
|
2717
3340
|
}
|
|
@@ -2728,6 +3351,7 @@ function mapTypescript(config, state, packageConfig, basePath) {
|
|
|
2728
3351
|
const packageManagerAtIndex = packageJsonPackageManager ? packageJsonPackageManager.indexOf("@", packageJsonPackageManager.startsWith("@") ? 1 : 0) : -1;
|
|
2729
3352
|
const packageManagerVersionPart = packageManagerAtIndex >= 0 ? packageJsonPackageManager?.slice(packageManagerAtIndex + 1).split("+")[0] : void 0;
|
|
2730
3353
|
const packageManagerVersion = packageManagerVersionPart || void 0;
|
|
3354
|
+
if (packageJsonManifest) liftPackageJsonDependencies(packageJsonManifest, state, packageConfig);
|
|
2731
3355
|
const serdeLayer = takeBoolean(config, ["serdeLayer"], state, basePath);
|
|
2732
3356
|
const noSerdeLayer = takeBoolean(config, ["noSerdeLayer"], state, basePath);
|
|
2733
3357
|
const fetchSupport = takeEnum(config, ["fetchSupport"], ["native"], state, basePath);
|
|
@@ -2784,7 +3408,8 @@ function mapPython(config, state, packageConfig, basePath) {
|
|
|
2784
3408
|
});
|
|
2785
3409
|
}
|
|
2786
3410
|
function mapJvm(language, config, state, packageConfig, basePath) {
|
|
2787
|
-
const
|
|
3411
|
+
const namespaceAliases = language === "java" ? ["packagePrefix"] : ["packageName", "packagePrefix"];
|
|
3412
|
+
const namespace = takeString(config, namespaceAliases, state, basePath);
|
|
2788
3413
|
const groupId = takeString(config, ["group", "groupId"], state, basePath);
|
|
2789
3414
|
const artifactId = takeString(config, ["artifact", "artifactId"], state, basePath);
|
|
2790
3415
|
if (namespace !== void 0) packageConfig.namespace = namespace;
|
|
@@ -2896,6 +3521,7 @@ function mapRust(config, state, packageConfig, basePath) {
|
|
|
2896
3521
|
const description = takeString(config, ["packageDescription"], state, basePath);
|
|
2897
3522
|
const documentationUrl = takeString(config, ["packageDocumentation"], state, basePath);
|
|
2898
3523
|
Object.assign(packageConfig, compact({ packageName, repository, description, documentationUrl }));
|
|
3524
|
+
mapLicenseFallback(config, ["packageLicense"], state, basePath);
|
|
2899
3525
|
return compact({
|
|
2900
3526
|
dateTimeType: takeEnum(config, ["dateTimeType"], ["offset", "utc"], state, basePath),
|
|
2901
3527
|
capitalizeInitialisms: takeBoolean(config, ["capitalizeInitialisms"], state, basePath),
|
|
@@ -2909,7 +3535,7 @@ function mapSwift(config, state, basePath) {
|
|
|
2909
3535
|
nullableAsOptional: takeBoolean(config, ["nullableAsOptional"], state, basePath)
|
|
2910
3536
|
});
|
|
2911
3537
|
}
|
|
2912
|
-
function mapCli(config, state, packageConfig, basePath) {
|
|
3538
|
+
function mapCli(config, state, packageConfig, basePath, targetIndex) {
|
|
2913
3539
|
const identity = takeObject(config, ["packageIdentity"], state, basePath);
|
|
2914
3540
|
if (identity) {
|
|
2915
3541
|
Object.assign(
|
|
@@ -2920,10 +3546,13 @@ function mapCli(config, state, packageConfig, basePath) {
|
|
|
2920
3546
|
description: takeString(identity.value, ["description"], state, identity.path)
|
|
2921
3547
|
})
|
|
2922
3548
|
);
|
|
3549
|
+
mapCliPackageIdentity(identity, state, targetIndex);
|
|
2923
3550
|
}
|
|
3551
|
+
mapCliDistribution(config, state, basePath, targetIndex);
|
|
2924
3552
|
return compact({
|
|
2925
3553
|
paginationParameters: takeStringArray(config, ["paginationParameters"], state, basePath),
|
|
2926
|
-
skills: takeBoolean(config, ["skills"], state, basePath)
|
|
3554
|
+
skills: takeBoolean(config, ["skills"], state, basePath),
|
|
3555
|
+
...mapCliGeneration(config, state, basePath, targetIndex)
|
|
2927
3556
|
});
|
|
2928
3557
|
}
|
|
2929
3558
|
function mapTerraform(config, state, packageConfig, basePath) {
|
|
@@ -3007,6 +3636,48 @@ function mapDependencies(config, state, packageConfig, basePath) {
|
|
|
3007
3636
|
if (dependencies.length) packageConfig[field] = dependencies;
|
|
3008
3637
|
}
|
|
3009
3638
|
}
|
|
3639
|
+
function liftPackageJsonDependencies(manifest, state, packageConfig) {
|
|
3640
|
+
for (const [field, target] of [
|
|
3641
|
+
["dependencies", "extraDependencies"],
|
|
3642
|
+
["devDependencies", "extraDevDependencies"],
|
|
3643
|
+
["peerDependencies", "extraPeerDependencies"]
|
|
3644
|
+
]) {
|
|
3645
|
+
const located = takeObject(manifest.value, [field], state, manifest.path);
|
|
3646
|
+
if (!located) continue;
|
|
3647
|
+
const lifted = Object.entries(located.value).flatMap(
|
|
3648
|
+
([name, dependency]) => mapDependency(name, dependency, state, [...located.path, name])
|
|
3649
|
+
);
|
|
3650
|
+
if (lifted.length) packageConfig[target] = overrideByName(packageConfig[target] ?? [], lifted);
|
|
3651
|
+
}
|
|
3652
|
+
const meta = takeObject(manifest.value, ["peerDependenciesMeta"], state, manifest.path);
|
|
3653
|
+
if (!meta) return;
|
|
3654
|
+
const entries = peerDependenciesMetaEntries(meta, state);
|
|
3655
|
+
if (entries.length) {
|
|
3656
|
+
packageConfig.extraPeerDependenciesMeta = {
|
|
3657
|
+
...packageConfig.extraPeerDependenciesMeta,
|
|
3658
|
+
...Object.fromEntries(entries)
|
|
3659
|
+
};
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
function overrideByName(existing, overrides) {
|
|
3663
|
+
const byName = new Map(existing.map((dependency) => [dependency.name, dependency]));
|
|
3664
|
+
overrides.forEach((dependency) => byName.set(dependency.name, dependency));
|
|
3665
|
+
return [...byName.values()];
|
|
3666
|
+
}
|
|
3667
|
+
function mapPeerDependenciesMeta(config, state, packageConfig, basePath) {
|
|
3668
|
+
const located = takeObject(config, ["extraPeerDependenciesMeta"], state, basePath);
|
|
3669
|
+
if (!located) return;
|
|
3670
|
+
const entries = peerDependenciesMetaEntries(located, state);
|
|
3671
|
+
if (entries.length) packageConfig.extraPeerDependenciesMeta = Object.fromEntries(entries);
|
|
3672
|
+
}
|
|
3673
|
+
function peerDependenciesMetaEntries(located, state) {
|
|
3674
|
+
return Object.entries(located.value).flatMap(([name, value]) => {
|
|
3675
|
+
const parsed = jsonObjectSchema.safeParse(value);
|
|
3676
|
+
if (!parsed.success) return [];
|
|
3677
|
+
consume(state, [...located.path, name]);
|
|
3678
|
+
return [[name, parsed.data]];
|
|
3679
|
+
});
|
|
3680
|
+
}
|
|
3010
3681
|
function mapDependency(name, value, state, path) {
|
|
3011
3682
|
if (typeof value === "string" && value) {
|
|
3012
3683
|
consume(state, path);
|
|
@@ -3014,13 +3685,7 @@ function mapDependency(name, value, state, path) {
|
|
|
3014
3685
|
}
|
|
3015
3686
|
if (!isObject(value)) return [];
|
|
3016
3687
|
const version = takeString(value, ["version"], state, path);
|
|
3017
|
-
const
|
|
3018
|
-
const localPath = takeString(value, ["path"], state, path);
|
|
3019
|
-
const source = gitUrl ? {
|
|
3020
|
-
type: "git",
|
|
3021
|
-
url: gitUrl,
|
|
3022
|
-
...optional("ref", takeString(value, ["ref"], state, path))
|
|
3023
|
-
} : localPath ? { type: "path", path: localPath } : void 0;
|
|
3688
|
+
const source = takeDependencySource(value, state, path);
|
|
3024
3689
|
if (!version && !source) return [];
|
|
3025
3690
|
return [
|
|
3026
3691
|
{
|
|
@@ -3036,6 +3701,17 @@ function mapDependency(name, value, state, path) {
|
|
|
3036
3701
|
}
|
|
3037
3702
|
];
|
|
3038
3703
|
}
|
|
3704
|
+
function takeDependencySource(value, state, path) {
|
|
3705
|
+
const gitUrl = takeString(value, ["git"], state, path);
|
|
3706
|
+
if (gitUrl) {
|
|
3707
|
+
const ref = takeString(value, ["ref", "rev", "branch"], state, path);
|
|
3708
|
+
return { type: "git", url: gitUrl, ...optional("ref", ref) };
|
|
3709
|
+
}
|
|
3710
|
+
const localPath = takeString(value, ["path"], state, path);
|
|
3711
|
+
if (localPath) return { type: "path", path: localPath };
|
|
3712
|
+
const registry = takeString(value, ["registry"], state, path);
|
|
3713
|
+
return registry ? { type: "registry", registry } : void 0;
|
|
3714
|
+
}
|
|
3039
3715
|
function takeCustomSections(value, language, activeLanguages, state, basePath) {
|
|
3040
3716
|
const located = locate(value, ["customSections"], basePath);
|
|
3041
3717
|
if (!located || !Array.isArray(located.value)) return void 0;
|
|
@@ -3224,6 +3900,15 @@ var compatibilityConfigSchema = z.strictObject({
|
|
|
3224
3900
|
legacyInput: legacyInputSchema.optional().describe("Original producer input retained only for migration debugging."),
|
|
3225
3901
|
unsupportedFields: z.array(unsupportedFieldSchema).optional().describe("Legacy fields that could not be represented in normalized configuration.")
|
|
3226
3902
|
});
|
|
3903
|
+
|
|
3904
|
+
// src/sdk-config-ir/v1/diagnostics.ts
|
|
3905
|
+
function getSdkConfigIrV1Diagnostics(config) {
|
|
3906
|
+
if (config.target.language !== "cli") {
|
|
3907
|
+
return [];
|
|
3908
|
+
}
|
|
3909
|
+
const diagnostic = cliDistributionModeDiagnostic(config.output, ["output"]);
|
|
3910
|
+
return diagnostic ? [diagnostic] : [];
|
|
3911
|
+
}
|
|
3227
3912
|
var generationAssetSchema = z.discriminatedUnion("type", [
|
|
3228
3913
|
z.strictObject({
|
|
3229
3914
|
type: z.literal("path").describe("Loads the generation asset from a relative path."),
|
|
@@ -3526,6 +4211,12 @@ var githubOutputSchema2 = z.strictObject({
|
|
|
3526
4211
|
/** Automatically merge the GitHub publishing PR. Defaults to false. */
|
|
3527
4212
|
autoMerge: z.boolean().default(false).describe("Whether the GitHub publisher automatically merges its pull request.")
|
|
3528
4213
|
});
|
|
4214
|
+
var distributionShape = {
|
|
4215
|
+
/** Valid only for `cli` targets with GitHub delivery; secret names only, never values. */
|
|
4216
|
+
distribution: cliDistributionConfigSchema.optional().describe(
|
|
4217
|
+
"CLI release channels published by the generated release workflow; credentials are GitHub Actions secret names."
|
|
4218
|
+
)
|
|
4219
|
+
};
|
|
3529
4220
|
var credentialResolutionShape = {
|
|
3530
4221
|
/** Where output credential references are resolved. */
|
|
3531
4222
|
credentialResolution: credentialResolutionSchema.default("refs-only").describe("Where output credential references are resolved.")
|
|
@@ -3534,18 +4225,21 @@ var filesOutputSchema2 = z.strictObject({
|
|
|
3534
4225
|
delivery: z.literal("files").describe("Writes the generated SDK to a directory."),
|
|
3535
4226
|
path: nonEmptyStringSchema.optional().describe("The destination directory for generated files."),
|
|
3536
4227
|
publish: publishConfigSchema.optional().describe("Optional package registry publication."),
|
|
4228
|
+
...distributionShape,
|
|
3537
4229
|
...credentialResolutionShape
|
|
3538
4230
|
});
|
|
3539
4231
|
var zipOutputSchema2 = z.strictObject({
|
|
3540
4232
|
delivery: z.literal("zip").describe("Packages the generated SDK as a ZIP archive."),
|
|
3541
4233
|
fileName: nonEmptyStringSchema.optional().describe("The generated ZIP archive file name."),
|
|
3542
4234
|
publish: publishConfigSchema.optional().describe("Optional package registry publication."),
|
|
4235
|
+
...distributionShape,
|
|
3543
4236
|
...credentialResolutionShape
|
|
3544
4237
|
});
|
|
3545
4238
|
var githubDeliverySchema2 = z.strictObject({
|
|
3546
4239
|
delivery: z.literal("github").describe("Delivers the generated SDK to GitHub."),
|
|
3547
4240
|
github: githubOutputSchema2.describe("GitHub repository delivery settings."),
|
|
3548
4241
|
publish: publishConfigSchema.optional().describe("Optional package registry publication."),
|
|
4242
|
+
...distributionShape,
|
|
3549
4243
|
...credentialResolutionShape
|
|
3550
4244
|
});
|
|
3551
4245
|
var outputConfigSchema = z.discriminatedUnion(
|
|
@@ -3630,7 +4324,7 @@ var targetConfigSchema = z.strictObject({
|
|
|
3630
4324
|
// src/sdk-config-ir/v1/sdk-config-ir-v1.ts
|
|
3631
4325
|
var SDK_CONFIG_IR_V1_SCHEMA_VERSION = "sdk-config-ir/v1";
|
|
3632
4326
|
var publishRegistryLanguages2 = {
|
|
3633
|
-
npm: ["typescript", "mcp"],
|
|
4327
|
+
npm: ["typescript", "mcp", "cli"],
|
|
3634
4328
|
pypi: ["python"],
|
|
3635
4329
|
maven: ["java", "kotlin"],
|
|
3636
4330
|
nuget: ["csharp"],
|
|
@@ -3685,6 +4379,28 @@ function validatePublishingIdentity2(packageConfig, registry, context) {
|
|
|
3685
4379
|
});
|
|
3686
4380
|
}
|
|
3687
4381
|
}
|
|
4382
|
+
function validateCliOutput(output, language, context) {
|
|
4383
|
+
if (output.distribution !== void 0 && language !== "cli") {
|
|
4384
|
+
context.addIssue({
|
|
4385
|
+
code: "custom",
|
|
4386
|
+
message: `output.distribution is supported only for target language "cli", not "${language}"`,
|
|
4387
|
+
path: ["output", "distribution"]
|
|
4388
|
+
});
|
|
4389
|
+
} else if (output.distribution !== void 0 && output.delivery !== "github") {
|
|
4390
|
+
context.addIssue({
|
|
4391
|
+
code: "custom",
|
|
4392
|
+
message: CLI_DISTRIBUTION_REQUIRES_GITHUB_DELIVERY_MESSAGE,
|
|
4393
|
+
path: ["output", "distribution"]
|
|
4394
|
+
});
|
|
4395
|
+
}
|
|
4396
|
+
if (language === "cli" && output.publish && output.delivery !== "github") {
|
|
4397
|
+
context.addIssue({
|
|
4398
|
+
code: "custom",
|
|
4399
|
+
message: CLI_PUBLISH_REQUIRES_GITHUB_DELIVERY_MESSAGE,
|
|
4400
|
+
path: ["output", "publish"]
|
|
4401
|
+
});
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
3688
4404
|
var sdkConfigIrV1Schema = z.strictObject({
|
|
3689
4405
|
schemaVersion: z.literal(SDK_CONFIG_IR_V1_SCHEMA_VERSION).describe("The version of the normalized SDK Config IR schema."),
|
|
3690
4406
|
source: sourceConfigSchema.describe("Materialized API descriptions consumed by generation."),
|
|
@@ -3746,6 +4462,7 @@ var sdkConfigIrV1Schema = z.strictObject({
|
|
|
3746
4462
|
});
|
|
3747
4463
|
}
|
|
3748
4464
|
}
|
|
4465
|
+
validateCliOutput(output, target.language, context);
|
|
3749
4466
|
if (compatibility?.legacyInput) {
|
|
3750
4467
|
const expectedKind = target.sourceOrigin === "postman" ? "postman-build-parameters" : "fern-generator-invocation";
|
|
3751
4468
|
if (compatibility.legacyInput.kind !== expectedKind) {
|
|
@@ -3785,6 +4502,6 @@ function parseSdkConfigIrV1ForConsumption(value) {
|
|
|
3785
4502
|
return parseSdkConfigIrV1(stripUnknownProperties(value, sdkConfigIrV1InputJsonSchema));
|
|
3786
4503
|
}
|
|
3787
4504
|
|
|
3788
|
-
export { FernConfigMappingError, SDK_CONFIG_IR_V1_SCHEMA_VERSION, SDK_CONFIG_V1_SCHEMA_VERSION, apiConfigSchema, apiImportSettingsSchema, authConfigSchema, authSchemeSchema, cliGenerationConfigSchema, clientConfigOverrideSchema, clientConfigSchema, clientRetryOverrideSchema, compatibilityConfigSchema, composerPackageNameSchema, csharpGenerationConfigSchema, dependencySchema, docsConfigSchema, exactSemverSchema, generationConfigSchema, goGenerationConfigSchema, goModulePathSchema, javaGenerationConfigSchema, jsonObjectSchema, jsonValueSchema, kotlinGenerationConfigSchema, languageGenerationConfigSchema, legacyInputSchema, mapFernConfigToSdkConfigV1, mcpAvailabilityStatuses, mcpGenerationConfigSchema, nonEmptyStringSchema, outputConfigSchema, packageConfigSchema, parseSdkConfigIrV1, parseSdkConfigIrV1ForConsumption, parseSdkConfigV1, parseSdkConfigV1ForConsumption, phpGenerationConfigSchema, publishConfigSchema, publishRegistrySchema, pythonGenerationConfigSchema, readmeCustomSectionSchema, readmeEndpointSchema, relativePathSchema, replayConfigSchema, rubyGenerationConfigSchema, rustGenerationConfigSchema, sdkConfigIrCapabilitySchema, sdkConfigIrV1Schema, sdkConfigV1ApiConfigSchema, sdkConfigV1AuthConfigSchema, sdkConfigV1AuthSchemeSchema, cliGenerationConfigSchema as sdkConfigV1CliGenerationConfigSchema, sdkConfigV1ClientConfigOverrideSchema, sdkConfigV1ClientConfigSchema, composerPackageNameSchema as sdkConfigV1ComposerPackageNameSchema, csharpGenerationConfigSchema as sdkConfigV1CsharpGenerationConfigSchema, sdkConfigV1DependencySchema, sdkConfigV1DocsConfigSchema, exactSemverSchema as sdkConfigV1ExactSemverSchema, sdkConfigV1GenerationConfigOverrideSchema, sdkConfigV1GenerationConfigSchema, goGenerationConfigSchema as sdkConfigV1GoGenerationConfigSchema, goModulePathSchema as sdkConfigV1GoModulePathSchema, javaGenerationConfigSchema as sdkConfigV1JavaGenerationConfigSchema, kotlinGenerationConfigSchema as sdkConfigV1KotlinGenerationConfigSchema, mcpGenerationConfigSchema as sdkConfigV1McpGenerationConfigSchema, nonEmptyStringSchema as sdkConfigV1NonEmptyStringSchema, sdkConfigV1OutputConfigSchema, sdkConfigV1PackageConfigSchema, phpGenerationConfigSchema as sdkConfigV1PhpGenerationConfigSchema, sdkConfigV1PublishConfigSchema, sdkConfigV1PublishRegistrySchema, pythonGenerationConfigSchema as sdkConfigV1PythonGenerationConfigSchema, sdkConfigV1ReadmeCustomSectionSchema, sdkConfigV1ReadmeEndpointSchema, relativePathSchema as sdkConfigV1RelativePathSchema, sdkConfigV1ReplayConfigSchema, rubyGenerationConfigSchema as sdkConfigV1RubyGenerationConfigSchema, rustGenerationConfigSchema as sdkConfigV1RustGenerationConfigSchema, sdkConfigV1Schema, sdkConfigV1SourceConfigSchema, sdkConfigV1SourceSpecSchema, swiftGenerationConfigSchema as sdkConfigV1SwiftGenerationConfigSchema, sdkConfigV1TargetSchema, terraformGenerationConfigSchema as sdkConfigV1TerraformGenerationConfigSchema, typescriptGenerationConfigSchema as sdkConfigV1TypescriptGenerationConfigSchema, sdkConfigV1WebhookSignatureSchema, serializeSdkConfigIrV1, sourceConfigSchema, sourceSpecConfigSchema, sourceSpecTypeSchema, splitSdkConfigV1TargetGeneration, swiftGenerationConfigSchema, targetConfigSchema, targetLanguageSchema, terraformGenerationConfigSchema, typescriptGenerationConfigSchema, unsupportedFieldSchema, validateSdkConfigV1, webhookSignatureSchema };
|
|
4505
|
+
export { CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE, FernConfigMappingError, SDK_CONFIG_IR_V1_SCHEMA_VERSION, CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE as SDK_CONFIG_V1_CLI_DISTRIBUTION_NON_RELEASE_MODE_CODE, SDK_CONFIG_V1_SCHEMA_VERSION, apiConfigSchema, apiImportSettingsSchema, authConfigSchema, authSchemeSchema, cliDistributionConfigSchema, cliDistributionGithubAppSchema, cliDistributionHomebrewSchema, cliDistributionScoopSchema, cliGenerationConfigSchema, clientConfigOverrideSchema, clientConfigSchema, clientRetryOverrideSchema, compatibilityConfigSchema, composerPackageNameSchema, csharpGenerationConfigSchema, dependencySchema, docsConfigSchema, exactSemverSchema, generationConfigSchema, getSdkConfigIrV1Diagnostics, getSdkConfigV1Diagnostics, githubActionsSecretNameSchema, goGenerationConfigSchema, goModulePathSchema, javaGenerationConfigSchema, jsonObjectSchema, jsonValueSchema, kotlinGenerationConfigSchema, languageGenerationConfigSchema, legacyInputSchema, mapFernConfigToSdkConfigV1, mcpAvailabilityStatuses, mcpGenerationConfigSchema, nonEmptyStringSchema, outputConfigSchema, packageConfigSchema, parseSdkConfigIrV1, parseSdkConfigIrV1ForConsumption, parseSdkConfigV1, parseSdkConfigV1ForConsumption, phpGenerationConfigSchema, publishConfigSchema, publishRegistrySchema, pythonGenerationConfigSchema, readmeCustomSectionSchema, readmeEndpointSchema, relativePathSchema, replayConfigSchema, rubyGenerationConfigSchema, rustGenerationConfigSchema, sdkConfigIrCapabilitySchema, sdkConfigIrV1Schema, sdkConfigV1ApiConfigSchema, sdkConfigV1AuthConfigSchema, sdkConfigV1AuthSchemeSchema, cliDistributionConfigSchema as sdkConfigV1CliDistributionConfigSchema, cliDistributionGithubAppSchema as sdkConfigV1CliDistributionGithubAppSchema, cliDistributionHomebrewSchema as sdkConfigV1CliDistributionHomebrewSchema, cliDistributionScoopSchema as sdkConfigV1CliDistributionScoopSchema, cliGenerationConfigSchema as sdkConfigV1CliGenerationConfigSchema, sdkConfigV1CliOutputConfigSchema, sdkConfigV1ClientConfigOverrideSchema, sdkConfigV1ClientConfigSchema, composerPackageNameSchema as sdkConfigV1ComposerPackageNameSchema, csharpGenerationConfigSchema as sdkConfigV1CsharpGenerationConfigSchema, sdkConfigV1DependencySchema, sdkConfigV1DocsConfigSchema, exactSemverSchema as sdkConfigV1ExactSemverSchema, sdkConfigV1GenerationConfigOverrideSchema, sdkConfigV1GenerationConfigSchema, githubActionsSecretNameSchema as sdkConfigV1GithubActionsSecretNameSchema, goGenerationConfigSchema as sdkConfigV1GoGenerationConfigSchema, goModulePathSchema as sdkConfigV1GoModulePathSchema, javaGenerationConfigSchema as sdkConfigV1JavaGenerationConfigSchema, kotlinGenerationConfigSchema as sdkConfigV1KotlinGenerationConfigSchema, mcpGenerationConfigSchema as sdkConfigV1McpGenerationConfigSchema, nonEmptyStringSchema as sdkConfigV1NonEmptyStringSchema, sdkConfigV1OutputConfigSchema, sdkConfigV1PackageConfigSchema, phpGenerationConfigSchema as sdkConfigV1PhpGenerationConfigSchema, sdkConfigV1PublishConfigSchema, sdkConfigV1PublishRegistrySchema, pythonGenerationConfigSchema as sdkConfigV1PythonGenerationConfigSchema, sdkConfigV1ReadmeCustomSectionSchema, sdkConfigV1ReadmeEndpointSchema, relativePathSchema as sdkConfigV1RelativePathSchema, sdkConfigV1ReplayConfigSchema, rubyGenerationConfigSchema as sdkConfigV1RubyGenerationConfigSchema, rustGenerationConfigSchema as sdkConfigV1RustGenerationConfigSchema, sdkConfigV1Schema, sdkConfigV1SourceConfigSchema, sdkConfigV1SourceSpecSchema, swiftGenerationConfigSchema as sdkConfigV1SwiftGenerationConfigSchema, sdkConfigV1TargetSchema, terraformGenerationConfigSchema as sdkConfigV1TerraformGenerationConfigSchema, typescriptGenerationConfigSchema as sdkConfigV1TypescriptGenerationConfigSchema, sdkConfigV1WebhookSignatureSchema, serializeSdkConfigIrV1, sourceConfigSchema, sourceSpecConfigSchema, sourceSpecTypeSchema, splitSdkConfigV1TargetGeneration, swiftGenerationConfigSchema, targetConfigSchema, targetLanguageSchema, terraformGenerationConfigSchema, typescriptGenerationConfigSchema, unsupportedFieldSchema, validateSdkConfigV1, webhookSignatureSchema };
|
|
3789
4506
|
//# sourceMappingURL=index.js.map
|
|
3790
4507
|
//# sourceMappingURL=index.js.map
|