@fern-api/fern-api-dev 3.63.0 → 3.64.1-2-gd642956c498
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/cli.cjs +766 -606
- package/package.json +1 -1
package/cli.cjs
CHANGED
|
@@ -1426227,7 +1426227,7 @@ var AccessTokenPosthogManager = class {
|
|
|
1426227
1426227
|
properties: {
|
|
1426228
1426228
|
...event,
|
|
1426229
1426229
|
...event.properties,
|
|
1426230
|
-
version: "3.
|
|
1426230
|
+
version: "3.64.1-2-gd642956c498",
|
|
1426231
1426231
|
usingAccessToken: true
|
|
1426232
1426232
|
}
|
|
1426233
1426233
|
});
|
|
@@ -1426326,7 +1426326,7 @@ var UserPosthogManager = class {
|
|
|
1426326
1426326
|
distinctId: this.userId ?? await this.getPersistedDistinctId(),
|
|
1426327
1426327
|
event: "CLI",
|
|
1426328
1426328
|
properties: {
|
|
1426329
|
-
version: "3.
|
|
1426329
|
+
version: "3.64.1-2-gd642956c498",
|
|
1426330
1426330
|
...event,
|
|
1426331
1426331
|
...event.properties,
|
|
1426332
1426332
|
usingAccessToken: false,
|
|
@@ -1452279,56 +1452279,149 @@ ${description}`);
|
|
|
1452279
1452279
|
}
|
|
1452280
1452280
|
|
|
1452281
1452281
|
// ../cli-v2/lib/commands/auth/login/command.js
|
|
1452282
|
+
var LoginCommand = class {
|
|
1452283
|
+
async handle(context2, args) {
|
|
1452284
|
+
const useDeviceCodeFlow = args["device-code"];
|
|
1452285
|
+
if (!useDeviceCodeFlow) {
|
|
1452286
|
+
context2.stdout.info("\u{1F33F} Welcome to Fern!");
|
|
1452287
|
+
context2.stdout.info("");
|
|
1452288
|
+
context2.stdout.info("Opening browser to log in to Fern...");
|
|
1452289
|
+
context2.stdout.info(source_default.dim(" If the browser doesn't open, try: fern auth login --device-code"));
|
|
1452290
|
+
}
|
|
1452291
|
+
const taskContext = new TaskContextAdapter({ context: context2, logLevel: LogLevel2.Info });
|
|
1452292
|
+
const tokenResponse = await getTokenFromAuth0(taskContext, {
|
|
1452293
|
+
useDeviceCodeFlow,
|
|
1452294
|
+
forceReauth: true
|
|
1452295
|
+
});
|
|
1452296
|
+
await this.storeAndConfirmLogin(context2, tokenResponse);
|
|
1452297
|
+
}
|
|
1452298
|
+
async storeAndConfirmLogin(context2, tokenResponse) {
|
|
1452299
|
+
const { accessToken, idToken } = tokenResponse;
|
|
1452300
|
+
const payload = await verifyAndDecodeJwt(idToken);
|
|
1452301
|
+
if (payload == null) {
|
|
1452302
|
+
context2.stdout.error(`${Icons.error} Internal error; could not verify ID token`);
|
|
1452303
|
+
throw CliError.exit();
|
|
1452304
|
+
}
|
|
1452305
|
+
const email3 = payload.email;
|
|
1452306
|
+
if (email3 == null) {
|
|
1452307
|
+
context2.stdout.error(`${Icons.error} Internal error; ID token does not contain email claim`);
|
|
1452308
|
+
throw CliError.exit();
|
|
1452309
|
+
}
|
|
1452310
|
+
const { isNew, totalAccounts } = await context2.tokenService.login(email3, accessToken);
|
|
1452311
|
+
if (isNew) {
|
|
1452312
|
+
context2.stdout.info(`${Icons.success} Logged in as ${source_default.bold(email3)}`);
|
|
1452313
|
+
if (totalAccounts > 1) {
|
|
1452314
|
+
context2.stdout.info(source_default.dim(` Account added. You now have ${totalAccounts} accounts.`));
|
|
1452315
|
+
context2.stdout.info(source_default.dim(` Active account: ${email3}`));
|
|
1452316
|
+
} else {
|
|
1452317
|
+
context2.stdout.info(source_default.dim(" Account stored in ~/.fernrc"));
|
|
1452318
|
+
}
|
|
1452319
|
+
return;
|
|
1452320
|
+
}
|
|
1452321
|
+
context2.stdout.info(`${Icons.success} Logged in as ${source_default.bold(email3)}`);
|
|
1452322
|
+
}
|
|
1452323
|
+
};
|
|
1452282
1452324
|
function addLoginCommand(cli) {
|
|
1452283
|
-
|
|
1452325
|
+
const cmd = new LoginCommand();
|
|
1452326
|
+
command2(cli, "login", "Log in to Fern", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("device-code", {
|
|
1452284
1452327
|
type: "boolean",
|
|
1452285
1452328
|
default: false,
|
|
1452286
1452329
|
description: "Use device code flow (for environments where browser cannot open automatically)"
|
|
1452287
1452330
|
}).example("$0 auth login", "Log in via browser").example("$0 auth login --device-code", "Log in via device code"));
|
|
1452288
1452331
|
}
|
|
1452289
|
-
|
|
1452290
|
-
|
|
1452291
|
-
|
|
1452292
|
-
|
|
1452293
|
-
context2.
|
|
1452294
|
-
|
|
1452332
|
+
|
|
1452333
|
+
// ../cli-v2/lib/commands/auth/logout/command.js
|
|
1452334
|
+
var LogoutCommand = class {
|
|
1452335
|
+
async handle(context2, args) {
|
|
1452336
|
+
const accounts = await context2.tokenService.getAllAccountInfo();
|
|
1452337
|
+
if (accounts.length === 0) {
|
|
1452338
|
+
context2.stdout.warn(`${source_default.yellow("\u26A0")} You are not logged in to Fern.`);
|
|
1452339
|
+
context2.stdout.info("");
|
|
1452340
|
+
context2.stdout.info(source_default.dim(" To log in, run: fern auth login"));
|
|
1452341
|
+
return;
|
|
1452342
|
+
}
|
|
1452343
|
+
if (args.all) {
|
|
1452344
|
+
await this.handleLogoutAll(context2, accounts, args.force);
|
|
1452345
|
+
return;
|
|
1452346
|
+
}
|
|
1452347
|
+
if (args.user != null) {
|
|
1452348
|
+
await this.handleLogoutUser(context2, args.user);
|
|
1452349
|
+
return;
|
|
1452350
|
+
}
|
|
1452351
|
+
if (accounts.length === 1) {
|
|
1452352
|
+
const singleAccount = accounts[0];
|
|
1452353
|
+
if (singleAccount != null) {
|
|
1452354
|
+
await this.handleLogoutUser(context2, singleAccount.user);
|
|
1452355
|
+
}
|
|
1452356
|
+
return;
|
|
1452357
|
+
}
|
|
1452358
|
+
await this.handleLogoutInteractive(context2, accounts);
|
|
1452295
1452359
|
}
|
|
1452296
|
-
|
|
1452297
|
-
|
|
1452298
|
-
|
|
1452299
|
-
|
|
1452300
|
-
|
|
1452301
|
-
|
|
1452302
|
-
}
|
|
1452303
|
-
|
|
1452304
|
-
|
|
1452305
|
-
|
|
1452306
|
-
|
|
1452307
|
-
context2.stdout.
|
|
1452308
|
-
|
|
1452360
|
+
async handleLogoutAll(context2, accounts, force) {
|
|
1452361
|
+
if (force) {
|
|
1452362
|
+
await context2.tokenService.logoutAll();
|
|
1452363
|
+
context2.stdout.info(`${Icons.success} Logged out of all accounts`);
|
|
1452364
|
+
return;
|
|
1452365
|
+
}
|
|
1452366
|
+
context2.stdout.warn(`${source_default.yellow("\u26A0")} This will log out of all ${accounts.length} accounts:`);
|
|
1452367
|
+
for (const account of accounts) {
|
|
1452368
|
+
const activeMarker = account.isActive ? source_default.dim(" (active)") : "";
|
|
1452369
|
+
context2.stdout.info(` - ${account.user}${activeMarker}`);
|
|
1452370
|
+
}
|
|
1452371
|
+
context2.stdout.info("");
|
|
1452372
|
+
if (!context2.isTTY) {
|
|
1452373
|
+
context2.stdout.error(`${Icons.error} Use --force to skip confirmation in non-interactive mode`);
|
|
1452374
|
+
throw CliError.exit();
|
|
1452375
|
+
}
|
|
1452376
|
+
const { confirmed } = await lib_default3.prompt([
|
|
1452377
|
+
{
|
|
1452378
|
+
type: "confirm",
|
|
1452379
|
+
name: "confirmed",
|
|
1452380
|
+
message: "Continue?",
|
|
1452381
|
+
default: false
|
|
1452382
|
+
}
|
|
1452383
|
+
]);
|
|
1452384
|
+
if (!confirmed) {
|
|
1452385
|
+
context2.stdout.info("Cancelled.");
|
|
1452386
|
+
return;
|
|
1452387
|
+
}
|
|
1452388
|
+
await context2.tokenService.logoutAll();
|
|
1452389
|
+
context2.stdout.info(`${Icons.success} Logged out of all accounts`);
|
|
1452309
1452390
|
}
|
|
1452310
|
-
|
|
1452311
|
-
|
|
1452312
|
-
|
|
1452313
|
-
|
|
1452391
|
+
async handleLogoutUser(context2, user) {
|
|
1452392
|
+
const { removed, newActive } = await context2.tokenService.logout(user);
|
|
1452393
|
+
if (!removed) {
|
|
1452394
|
+
context2.stdout.error(`${Icons.error} Account not found: ${user}`);
|
|
1452395
|
+
throw CliError.exit();
|
|
1452396
|
+
}
|
|
1452397
|
+
context2.stdout.info(`${Icons.success} Logged out of ${source_default.bold(user)}`);
|
|
1452398
|
+
if (newActive != null) {
|
|
1452399
|
+
context2.stdout.info(source_default.dim(` Switched active account to ${newActive}`));
|
|
1452400
|
+
}
|
|
1452314
1452401
|
}
|
|
1452315
|
-
|
|
1452316
|
-
|
|
1452317
|
-
|
|
1452318
|
-
|
|
1452319
|
-
context2.stdout.info(source_default.dim(` Account added. You now have ${totalAccounts} accounts.`));
|
|
1452320
|
-
context2.stdout.info(source_default.dim(` Active account: ${email3}`));
|
|
1452321
|
-
} else {
|
|
1452322
|
-
context2.stdout.info(source_default.dim(" Account stored in ~/.fernrc"));
|
|
1452402
|
+
async handleLogoutInteractive(context2, accounts) {
|
|
1452403
|
+
if (!context2.isTTY) {
|
|
1452404
|
+
context2.stdout.error(`${Icons.error} Multiple accounts found. Use --user or --all in non-interactive mode.`);
|
|
1452405
|
+
throw CliError.exit();
|
|
1452323
1452406
|
}
|
|
1452324
|
-
|
|
1452407
|
+
const choices = accounts.map((account) => ({
|
|
1452408
|
+
name: account.isActive ? `${account.user} ${source_default.dim("(active)")}` : account.user,
|
|
1452409
|
+
value: account.user
|
|
1452410
|
+
}));
|
|
1452411
|
+
const { selectedUser } = await lib_default3.prompt([
|
|
1452412
|
+
{
|
|
1452413
|
+
type: "list",
|
|
1452414
|
+
name: "selectedUser",
|
|
1452415
|
+
message: "Select account to log out:",
|
|
1452416
|
+
choices
|
|
1452417
|
+
}
|
|
1452418
|
+
]);
|
|
1452419
|
+
await this.handleLogoutUser(context2, selectedUser);
|
|
1452325
1452420
|
}
|
|
1452326
|
-
|
|
1452327
|
-
}
|
|
1452328
|
-
|
|
1452329
|
-
// ../cli-v2/lib/commands/auth/logout/command.js
|
|
1452421
|
+
};
|
|
1452330
1452422
|
function addLogoutCommand(cli) {
|
|
1452331
|
-
|
|
1452423
|
+
const cmd = new LogoutCommand();
|
|
1452424
|
+
command2(cli, "logout", "Log out of Fern", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("user", {
|
|
1452332
1452425
|
type: "string",
|
|
1452333
1452426
|
description: "Log out of a specific account"
|
|
1452334
1452427
|
}).option("all", {
|
|
@@ -1452341,98 +1452434,110 @@ function addLogoutCommand(cli) {
|
|
|
1452341
1452434
|
description: "Skip confirmation prompt"
|
|
1452342
1452435
|
}));
|
|
1452343
1452436
|
}
|
|
1452344
|
-
|
|
1452345
|
-
|
|
1452346
|
-
|
|
1452347
|
-
|
|
1452348
|
-
|
|
1452349
|
-
|
|
1452350
|
-
|
|
1452351
|
-
|
|
1452352
|
-
|
|
1452353
|
-
|
|
1452354
|
-
|
|
1452355
|
-
}
|
|
1452356
|
-
if (args.user != null) {
|
|
1452357
|
-
await handleLogoutUser(context2, args.user);
|
|
1452358
|
-
return;
|
|
1452359
|
-
}
|
|
1452360
|
-
if (accounts.length === 1) {
|
|
1452361
|
-
const singleAccount = accounts[0];
|
|
1452362
|
-
if (singleAccount != null) {
|
|
1452363
|
-
await handleLogoutUser(context2, singleAccount.user);
|
|
1452437
|
+
|
|
1452438
|
+
// ../cli-v2/lib/constants.js
|
|
1452439
|
+
var FERN_TOKEN_ENV_VAR2 = "FERN_TOKEN";
|
|
1452440
|
+
|
|
1452441
|
+
// ../cli-v2/lib/commands/auth/status/command.js
|
|
1452442
|
+
var StatusCommand = class {
|
|
1452443
|
+
async handle(context2, args) {
|
|
1452444
|
+
const envToken = await getAccessToken();
|
|
1452445
|
+
if (envToken != null) {
|
|
1452446
|
+
await this.displayEnvTokenStatus(context2, envToken.value, args);
|
|
1452447
|
+
return;
|
|
1452364
1452448
|
}
|
|
1452365
|
-
|
|
1452366
|
-
|
|
1452367
|
-
|
|
1452368
|
-
}
|
|
1452369
|
-
|
|
1452370
|
-
|
|
1452371
|
-
|
|
1452372
|
-
|
|
1452373
|
-
|
|
1452374
|
-
|
|
1452375
|
-
|
|
1452376
|
-
|
|
1452377
|
-
|
|
1452378
|
-
|
|
1452379
|
-
|
|
1452380
|
-
|
|
1452381
|
-
|
|
1452382
|
-
|
|
1452449
|
+
const accounts = await context2.tokenService.getAllAccountInfo();
|
|
1452450
|
+
if (accounts.length === 0) {
|
|
1452451
|
+
if (args.json) {
|
|
1452452
|
+
context2.stdout.info(JSON.stringify({ accounts: [], activeAccount: null }, null, 2));
|
|
1452453
|
+
} else {
|
|
1452454
|
+
context2.stdout.warn(`${source_default.yellow("\u26A0")} You are not logged in to Fern.`);
|
|
1452455
|
+
context2.stdout.info("");
|
|
1452456
|
+
context2.stdout.info(source_default.dim(" To log in, run: fern auth login"));
|
|
1452457
|
+
}
|
|
1452458
|
+
return;
|
|
1452459
|
+
}
|
|
1452460
|
+
if (args.json) {
|
|
1452461
|
+
await this.displayJsonStatus(context2, accounts);
|
|
1452462
|
+
return;
|
|
1452463
|
+
}
|
|
1452464
|
+
if (args.active) {
|
|
1452465
|
+
const activeAccount = accounts.find((a10) => a10.isActive);
|
|
1452466
|
+
if (activeAccount != null) {
|
|
1452467
|
+
await this.displaySingleAccountStatus(context2, activeAccount);
|
|
1452468
|
+
}
|
|
1452469
|
+
return;
|
|
1452470
|
+
}
|
|
1452471
|
+
if (accounts.length === 1) {
|
|
1452472
|
+
const singleAccount = accounts[0];
|
|
1452473
|
+
if (singleAccount != null) {
|
|
1452474
|
+
await this.displaySingleAccountStatus(context2, singleAccount);
|
|
1452475
|
+
}
|
|
1452476
|
+
return;
|
|
1452477
|
+
}
|
|
1452478
|
+
await this.displayMultiAccountStatus(context2, accounts);
|
|
1452383
1452479
|
}
|
|
1452384
|
-
|
|
1452385
|
-
{
|
|
1452386
|
-
|
|
1452387
|
-
|
|
1452388
|
-
|
|
1452389
|
-
|
|
1452480
|
+
async displayEnvTokenStatus(context2, token, args) {
|
|
1452481
|
+
if (args.json) {
|
|
1452482
|
+
context2.stdout.info(JSON.stringify({
|
|
1452483
|
+
source: FERN_TOKEN_ENV_VAR2,
|
|
1452484
|
+
token: this.maskToken(token)
|
|
1452485
|
+
}, null, 2));
|
|
1452486
|
+
return;
|
|
1452390
1452487
|
}
|
|
1452391
|
-
|
|
1452392
|
-
|
|
1452393
|
-
context2.stdout.info(
|
|
1452394
|
-
|
|
1452488
|
+
context2.stdout.info(source_default.bold(`Using ${FERN_TOKEN_ENV_VAR2} environment variable`));
|
|
1452489
|
+
context2.stdout.info("");
|
|
1452490
|
+
context2.stdout.info(source_default.dim(` The ${FERN_TOKEN_ENV_VAR2} environment variable overrides stored accounts.`));
|
|
1452491
|
+
context2.stdout.info(source_default.dim(` To use stored accounts, unset ${FERN_TOKEN_ENV_VAR2}.`));
|
|
1452492
|
+
context2.stdout.info("");
|
|
1452395
1452493
|
}
|
|
1452396
|
-
|
|
1452397
|
-
|
|
1452398
|
-
|
|
1452399
|
-
|
|
1452400
|
-
|
|
1452401
|
-
|
|
1452402
|
-
|
|
1452403
|
-
|
|
1452494
|
+
async displaySingleAccountStatus(context2, account) {
|
|
1452495
|
+
context2.stdout.info(source_default.bold("Logged in to Fern"));
|
|
1452496
|
+
context2.stdout.info("");
|
|
1452497
|
+
context2.stdout.info(` Account: ${account.user}`);
|
|
1452498
|
+
const statusText = account.tokenInfo?.isExpired === true ? source_default.yellow("Expired") : source_default.green("Active");
|
|
1452499
|
+
context2.stdout.info(` Status: ${statusText}`);
|
|
1452500
|
+
if (account.tokenInfo != null) {
|
|
1452501
|
+
context2.stdout.info(` Expires: ${account.tokenInfo.expiresIn}`);
|
|
1452502
|
+
}
|
|
1452404
1452503
|
}
|
|
1452405
|
-
context2
|
|
1452406
|
-
|
|
1452407
|
-
context2.stdout.info(
|
|
1452504
|
+
async displayMultiAccountStatus(context2, accounts) {
|
|
1452505
|
+
context2.stdout.info(source_default.bold("Logged in to Fern"));
|
|
1452506
|
+
context2.stdout.info("");
|
|
1452507
|
+
const maxNameWidth = Math.max(...accounts.map((a10) => a10.user.length));
|
|
1452508
|
+
for (const account of accounts) {
|
|
1452509
|
+
const prefix2 = account.isActive ? source_default.cyan(">") : " ";
|
|
1452510
|
+
const statusText = account.tokenInfo?.isExpired === true ? source_default.yellow("Expired") : source_default.green("Active");
|
|
1452511
|
+
const expiryText = account.tokenInfo != null ? `expires ${account.tokenInfo.expiresIn}` : "";
|
|
1452512
|
+
const expiredHint = account.tokenInfo?.isExpired === true ? source_default.dim(" run: fern auth login") : "";
|
|
1452513
|
+
const paddedName = account.user.padEnd(maxNameWidth);
|
|
1452514
|
+
context2.stdout.info(` ${prefix2} ${paddedName} ${statusText} ${expiryText}${expiredHint}`);
|
|
1452515
|
+
}
|
|
1452408
1452516
|
}
|
|
1452409
|
-
|
|
1452410
|
-
|
|
1452411
|
-
|
|
1452412
|
-
|
|
1452413
|
-
|
|
1452517
|
+
async displayJsonStatus(context2, accounts) {
|
|
1452518
|
+
const activeAccount = accounts.find((a10) => a10.isActive);
|
|
1452519
|
+
const output2 = {
|
|
1452520
|
+
accounts: accounts.map((account) => ({
|
|
1452521
|
+
user: account.user,
|
|
1452522
|
+
active: account.isActive,
|
|
1452523
|
+
status: account.tokenInfo?.isExpired === true ? "expired" : "valid",
|
|
1452524
|
+
expiresAt: account.tokenInfo?.expiresAt?.toISOString() ?? null,
|
|
1452525
|
+
token: account.tokenInfo != null ? this.maskToken(account.tokenInfo.token) : null
|
|
1452526
|
+
})),
|
|
1452527
|
+
activeAccount: activeAccount?.user ?? null
|
|
1452528
|
+
};
|
|
1452529
|
+
context2.stdout.info(JSON.stringify(output2, null, 2));
|
|
1452414
1452530
|
}
|
|
1452415
|
-
|
|
1452416
|
-
|
|
1452417
|
-
|
|
1452418
|
-
}));
|
|
1452419
|
-
const { selectedUser } = await lib_default3.prompt([
|
|
1452420
|
-
{
|
|
1452421
|
-
type: "list",
|
|
1452422
|
-
name: "selectedUser",
|
|
1452423
|
-
message: "Select account to log out:",
|
|
1452424
|
-
choices
|
|
1452531
|
+
maskToken(token) {
|
|
1452532
|
+
if (token.length <= 10) {
|
|
1452533
|
+
return "***";
|
|
1452425
1452534
|
}
|
|
1452426
|
-
|
|
1452427
|
-
|
|
1452428
|
-
}
|
|
1452429
|
-
|
|
1452430
|
-
// ../cli-v2/lib/constants.js
|
|
1452431
|
-
var FERN_TOKEN_ENV_VAR2 = "FERN_TOKEN";
|
|
1452432
|
-
|
|
1452433
|
-
// ../cli-v2/lib/commands/auth/status/command.js
|
|
1452535
|
+
return `${token.slice(0, 4)}...${token.slice(-4)}`;
|
|
1452536
|
+
}
|
|
1452537
|
+
};
|
|
1452434
1452538
|
function addStatusCommand(cli) {
|
|
1452435
|
-
|
|
1452539
|
+
const cmd = new StatusCommand();
|
|
1452540
|
+
command2(cli, "status", "Show authentication status", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("json", {
|
|
1452436
1452541
|
type: "boolean",
|
|
1452437
1452542
|
default: false,
|
|
1452438
1452543
|
description: "Output as JSON"
|
|
@@ -1452442,252 +1452547,167 @@ function addStatusCommand(cli) {
|
|
|
1452442
1452547
|
description: "Show active account only"
|
|
1452443
1452548
|
}));
|
|
1452444
1452549
|
}
|
|
1452445
|
-
|
|
1452446
|
-
|
|
1452447
|
-
|
|
1452448
|
-
|
|
1452449
|
-
|
|
1452450
|
-
|
|
1452451
|
-
const accounts = await context2.tokenService.getAllAccountInfo();
|
|
1452452
|
-
if (accounts.length === 0) {
|
|
1452453
|
-
if (args.json) {
|
|
1452454
|
-
context2.stdout.info(JSON.stringify({ accounts: [], activeAccount: null }, null, 2));
|
|
1452455
|
-
} else {
|
|
1452550
|
+
|
|
1452551
|
+
// ../cli-v2/lib/commands/auth/switch/command.js
|
|
1452552
|
+
var SwitchCommand = class {
|
|
1452553
|
+
async handle(context2, args) {
|
|
1452554
|
+
const accounts = await context2.tokenService.getAllAccountInfo();
|
|
1452555
|
+
if (accounts.length === 0) {
|
|
1452456
1452556
|
context2.stdout.warn(`${source_default.yellow("\u26A0")} You are not logged in to Fern.`);
|
|
1452457
1452557
|
context2.stdout.info("");
|
|
1452458
1452558
|
context2.stdout.info(source_default.dim(" To log in, run: fern auth login"));
|
|
1452559
|
+
throw CliError.exit();
|
|
1452459
1452560
|
}
|
|
1452460
|
-
|
|
1452461
|
-
|
|
1452462
|
-
|
|
1452463
|
-
|
|
1452464
|
-
|
|
1452465
|
-
|
|
1452466
|
-
|
|
1452467
|
-
|
|
1452468
|
-
|
|
1452469
|
-
|
|
1452561
|
+
if (accounts.length === 1) {
|
|
1452562
|
+
const account = accounts[0];
|
|
1452563
|
+
if (account == null) {
|
|
1452564
|
+
context2.stdout.error(`${Icons.error} Internal error; no accounts found`);
|
|
1452565
|
+
throw CliError.exit();
|
|
1452566
|
+
}
|
|
1452567
|
+
context2.stdout.warn(`${source_default.yellow("\u26A0")} You only have one account logged in: ${source_default.bold(account.user)}`);
|
|
1452568
|
+
context2.stdout.info("");
|
|
1452569
|
+
context2.stdout.info(source_default.dim(" To add another account, run: fern auth login"));
|
|
1452570
|
+
return;
|
|
1452470
1452571
|
}
|
|
1452471
|
-
|
|
1452472
|
-
|
|
1452473
|
-
|
|
1452474
|
-
const singleAccount = accounts[0];
|
|
1452475
|
-
if (singleAccount != null) {
|
|
1452476
|
-
await displaySingleAccountStatus(context2, singleAccount);
|
|
1452572
|
+
if (args.user != null) {
|
|
1452573
|
+
await this.switchToUser(context2, args.user);
|
|
1452574
|
+
return;
|
|
1452477
1452575
|
}
|
|
1452478
|
-
|
|
1452479
|
-
|
|
1452480
|
-
|
|
1452481
|
-
|
|
1452482
|
-
|
|
1452483
|
-
|
|
1452484
|
-
|
|
1452485
|
-
|
|
1452486
|
-
token: maskToken(token)
|
|
1452487
|
-
}, null, 2));
|
|
1452488
|
-
return;
|
|
1452489
|
-
}
|
|
1452490
|
-
context2.stdout.info(source_default.bold(`Using ${FERN_TOKEN_ENV_VAR2} environment variable`));
|
|
1452491
|
-
context2.stdout.info("");
|
|
1452492
|
-
context2.stdout.info(source_default.dim(` The ${FERN_TOKEN_ENV_VAR2} environment variable overrides stored accounts.`));
|
|
1452493
|
-
context2.stdout.info(source_default.dim(` To use stored accounts, unset ${FERN_TOKEN_ENV_VAR2}.`));
|
|
1452494
|
-
context2.stdout.info("");
|
|
1452495
|
-
}
|
|
1452496
|
-
async function displaySingleAccountStatus(context2, account) {
|
|
1452497
|
-
context2.stdout.info(source_default.bold("Logged in to Fern"));
|
|
1452498
|
-
context2.stdout.info("");
|
|
1452499
|
-
context2.stdout.info(` Account: ${account.user}`);
|
|
1452500
|
-
const statusText = account.tokenInfo?.isExpired === true ? source_default.yellow("Expired") : source_default.green("Active");
|
|
1452501
|
-
context2.stdout.info(` Status: ${statusText}`);
|
|
1452502
|
-
if (account.tokenInfo != null) {
|
|
1452503
|
-
context2.stdout.info(` Expires: ${account.tokenInfo.expiresIn}`);
|
|
1452504
|
-
}
|
|
1452505
|
-
}
|
|
1452506
|
-
async function displayMultiAccountStatus(context2, accounts) {
|
|
1452507
|
-
context2.stdout.info(source_default.bold("Logged in to Fern"));
|
|
1452508
|
-
context2.stdout.info("");
|
|
1452509
|
-
const maxNameWidth = Math.max(...accounts.map((a10) => a10.user.length));
|
|
1452510
|
-
for (const account of accounts) {
|
|
1452511
|
-
const prefix2 = account.isActive ? source_default.cyan(">") : " ";
|
|
1452512
|
-
const statusText = account.tokenInfo?.isExpired === true ? source_default.yellow("Expired") : source_default.green("Active");
|
|
1452513
|
-
const expiryText = account.tokenInfo != null ? `expires ${account.tokenInfo.expiresIn}` : "";
|
|
1452514
|
-
const expiredHint = account.tokenInfo?.isExpired === true ? source_default.dim(" run: fern auth login") : "";
|
|
1452515
|
-
const paddedName = account.user.padEnd(maxNameWidth);
|
|
1452516
|
-
context2.stdout.info(` ${prefix2} ${paddedName} ${statusText} ${expiryText}${expiredHint}`);
|
|
1452517
|
-
}
|
|
1452518
|
-
}
|
|
1452519
|
-
async function displayJsonStatus(context2, accounts) {
|
|
1452520
|
-
const activeAccount = accounts.find((a10) => a10.isActive);
|
|
1452521
|
-
const output2 = {
|
|
1452522
|
-
accounts: accounts.map((account) => ({
|
|
1452523
|
-
user: account.user,
|
|
1452524
|
-
active: account.isActive,
|
|
1452525
|
-
status: account.tokenInfo?.isExpired === true ? "expired" : "valid",
|
|
1452526
|
-
expiresAt: account.tokenInfo?.expiresAt?.toISOString() ?? null,
|
|
1452527
|
-
token: account.tokenInfo != null ? maskToken(account.tokenInfo.token) : null
|
|
1452528
|
-
})),
|
|
1452529
|
-
activeAccount: activeAccount?.user ?? null
|
|
1452530
|
-
};
|
|
1452531
|
-
context2.stdout.info(JSON.stringify(output2, null, 2));
|
|
1452532
|
-
}
|
|
1452533
|
-
function maskToken(token) {
|
|
1452534
|
-
if (token.length <= 10) {
|
|
1452535
|
-
return "***";
|
|
1452536
|
-
}
|
|
1452537
|
-
return `${token.slice(0, 4)}...${token.slice(-4)}`;
|
|
1452538
|
-
}
|
|
1452539
|
-
|
|
1452540
|
-
// ../cli-v2/lib/commands/auth/switch/command.js
|
|
1452541
|
-
function addSwitchCommand(cli) {
|
|
1452542
|
-
command2(cli, "switch", "Switch active account", handleSwitch, (yargs) => yargs.option("user", {
|
|
1452543
|
-
type: "string",
|
|
1452544
|
-
description: "Switch to specific account"
|
|
1452545
|
-
}));
|
|
1452546
|
-
}
|
|
1452547
|
-
async function handleSwitch(context2, args) {
|
|
1452548
|
-
const accounts = await context2.tokenService.getAllAccountInfo();
|
|
1452549
|
-
if (accounts.length === 0) {
|
|
1452550
|
-
context2.stdout.warn(`${source_default.yellow("\u26A0")} You are not logged in to Fern.`);
|
|
1452551
|
-
context2.stdout.info("");
|
|
1452552
|
-
context2.stdout.info(source_default.dim(" To log in, run: fern auth login"));
|
|
1452553
|
-
throw CliError.exit();
|
|
1452576
|
+
if (accounts.length === 2) {
|
|
1452577
|
+
const otherAccount = accounts.find((a10) => !a10.isActive);
|
|
1452578
|
+
if (otherAccount != null) {
|
|
1452579
|
+
await this.switchToUser(context2, otherAccount.user);
|
|
1452580
|
+
}
|
|
1452581
|
+
return;
|
|
1452582
|
+
}
|
|
1452583
|
+
await this.handleInteractiveSwitch(context2, accounts);
|
|
1452554
1452584
|
}
|
|
1452555
|
-
|
|
1452556
|
-
|
|
1452557
|
-
|
|
1452558
|
-
context2.stdout.error(`${Icons.error} Internal error; no accounts found`);
|
|
1452585
|
+
async handleInteractiveSwitch(context2, accounts) {
|
|
1452586
|
+
if (!context2.isTTY) {
|
|
1452587
|
+
context2.stdout.error(`${Icons.error} Use --user to specify account in non-interactive mode`);
|
|
1452559
1452588
|
throw CliError.exit();
|
|
1452560
1452589
|
}
|
|
1452561
|
-
|
|
1452562
|
-
|
|
1452563
|
-
|
|
1452564
|
-
|
|
1452565
|
-
|
|
1452566
|
-
|
|
1452567
|
-
|
|
1452568
|
-
|
|
1452590
|
+
const choices = accounts.map((account) => ({
|
|
1452591
|
+
name: account.isActive ? `${account.user} ${source_default.dim("(current)")}` : account.user,
|
|
1452592
|
+
value: account.user,
|
|
1452593
|
+
disabled: account.isActive ? "(current)" : false
|
|
1452594
|
+
}));
|
|
1452595
|
+
const { selectedUser } = await lib_default3.prompt([
|
|
1452596
|
+
{
|
|
1452597
|
+
type: "list",
|
|
1452598
|
+
name: "selectedUser",
|
|
1452599
|
+
message: "Select account:",
|
|
1452600
|
+
choices
|
|
1452601
|
+
}
|
|
1452602
|
+
]);
|
|
1452603
|
+
await this.switchToUser(context2, selectedUser);
|
|
1452569
1452604
|
}
|
|
1452570
|
-
|
|
1452571
|
-
const
|
|
1452572
|
-
if (
|
|
1452573
|
-
|
|
1452605
|
+
async switchToUser(context2, user) {
|
|
1452606
|
+
const success2 = await context2.tokenService.switchAccount(user);
|
|
1452607
|
+
if (!success2) {
|
|
1452608
|
+
context2.stdout.error(`${Icons.error} Account not found: ${user}`);
|
|
1452609
|
+
throw CliError.exit();
|
|
1452574
1452610
|
}
|
|
1452575
|
-
|
|
1452576
|
-
}
|
|
1452577
|
-
await handleInteractiveSwitch(context2, accounts);
|
|
1452578
|
-
}
|
|
1452579
|
-
async function switchToUser(context2, user) {
|
|
1452580
|
-
const success2 = await context2.tokenService.switchAccount(user);
|
|
1452581
|
-
if (!success2) {
|
|
1452582
|
-
context2.stdout.error(`${Icons.error} Account not found: ${user}`);
|
|
1452583
|
-
throw CliError.exit();
|
|
1452611
|
+
context2.stdout.info(`${Icons.success} Switched to ${source_default.bold(user)}`);
|
|
1452584
1452612
|
}
|
|
1452585
|
-
|
|
1452586
|
-
|
|
1452587
|
-
|
|
1452588
|
-
|
|
1452589
|
-
|
|
1452590
|
-
|
|
1452591
|
-
}
|
|
1452592
|
-
const choices = accounts.map((account) => ({
|
|
1452593
|
-
name: account.isActive ? `${account.user} ${source_default.dim("(current)")}` : account.user,
|
|
1452594
|
-
value: account.user,
|
|
1452595
|
-
disabled: account.isActive ? "(current)" : false
|
|
1452613
|
+
};
|
|
1452614
|
+
function addSwitchCommand(cli) {
|
|
1452615
|
+
const cmd = new SwitchCommand();
|
|
1452616
|
+
command2(cli, "switch", "Switch active account", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("user", {
|
|
1452617
|
+
type: "string",
|
|
1452618
|
+
description: "Switch to specific account"
|
|
1452596
1452619
|
}));
|
|
1452597
|
-
const { selectedUser } = await lib_default3.prompt([
|
|
1452598
|
-
{
|
|
1452599
|
-
type: "list",
|
|
1452600
|
-
name: "selectedUser",
|
|
1452601
|
-
message: "Select account:",
|
|
1452602
|
-
choices
|
|
1452603
|
-
}
|
|
1452604
|
-
]);
|
|
1452605
|
-
await switchToUser(context2, selectedUser);
|
|
1452606
1452620
|
}
|
|
1452607
1452621
|
|
|
1452608
1452622
|
// ../cli-v2/lib/commands/auth/token/command.js
|
|
1452609
|
-
|
|
1452610
|
-
|
|
1452611
|
-
|
|
1452612
|
-
|
|
1452613
|
-
|
|
1452614
|
-
|
|
1452615
|
-
|
|
1452616
|
-
|
|
1452617
|
-
|
|
1452618
|
-
|
|
1452619
|
-
|
|
1452620
|
-
|
|
1452621
|
-
|
|
1452622
|
-
|
|
1452623
|
+
var TokenCommand = class {
|
|
1452624
|
+
async handle(context2, args) {
|
|
1452625
|
+
const orgId = await this.resolveOrganization(context2, args);
|
|
1452626
|
+
const token = await context2.getTokenOrPrompt();
|
|
1452627
|
+
if (token.type === "user") {
|
|
1452628
|
+
await createOrganizationIfDoesNotExist({
|
|
1452629
|
+
organization: orgId,
|
|
1452630
|
+
token,
|
|
1452631
|
+
context: new TaskContextAdapter({ context: context2 })
|
|
1452632
|
+
});
|
|
1452633
|
+
}
|
|
1452634
|
+
const venus = createVenusService({ token: token.value });
|
|
1452635
|
+
const response = await venus.registry.generateRegistryTokens({
|
|
1452636
|
+
organizationId: api_exports4.OrganizationId(orgId)
|
|
1452623
1452637
|
});
|
|
1452624
|
-
|
|
1452625
|
-
|
|
1452626
|
-
|
|
1452627
|
-
|
|
1452628
|
-
|
|
1452629
|
-
|
|
1452630
|
-
|
|
1452631
|
-
return;
|
|
1452632
|
-
}
|
|
1452633
|
-
response.error._visit({
|
|
1452634
|
-
organizationNotFoundError: () => {
|
|
1452635
|
-
process.stderr.write(`${Icons.error} Organization "${orgId}" was not found.
|
|
1452638
|
+
if (response.ok) {
|
|
1452639
|
+
process.stdout.write(response.body.npm.token);
|
|
1452640
|
+
return;
|
|
1452641
|
+
}
|
|
1452642
|
+
response.error._visit({
|
|
1452643
|
+
organizationNotFoundError: () => {
|
|
1452644
|
+
process.stderr.write(`${Icons.error} Organization "${orgId}" was not found.
|
|
1452636
1452645
|
`);
|
|
1452637
|
-
|
|
1452638
|
-
|
|
1452639
|
-
|
|
1452640
|
-
|
|
1452646
|
+
throw CliError.exit();
|
|
1452647
|
+
},
|
|
1452648
|
+
unauthorizedError: () => {
|
|
1452649
|
+
process.stderr.write(`${Icons.error} You do not have access to organization "${orgId}".
|
|
1452641
1452650
|
`);
|
|
1452642
|
-
|
|
1452643
|
-
|
|
1452644
|
-
|
|
1452645
|
-
|
|
1452651
|
+
throw CliError.exit();
|
|
1452652
|
+
},
|
|
1452653
|
+
_other: () => {
|
|
1452654
|
+
process.stderr.write(`${Icons.error} Failed to generate token.
|
|
1452646
1452655
|
|
|
1452647
1452656
|
Please contact support@buildwithfern.com for assistance.
|
|
1452648
1452657
|
`);
|
|
1452649
|
-
|
|
1452650
|
-
|
|
1452651
|
-
|
|
1452652
|
-
}
|
|
1452653
|
-
async function resolveOrganization({ context: context2, args }) {
|
|
1452654
|
-
if (args.org != null) {
|
|
1452655
|
-
return args.org;
|
|
1452658
|
+
throw CliError.exit();
|
|
1452659
|
+
}
|
|
1452660
|
+
});
|
|
1452656
1452661
|
}
|
|
1452657
|
-
|
|
1452658
|
-
|
|
1452659
|
-
|
|
1452660
|
-
|
|
1452661
|
-
|
|
1452662
|
+
async resolveOrganization(context2, args) {
|
|
1452663
|
+
if (args.org != null) {
|
|
1452664
|
+
return args.org;
|
|
1452665
|
+
}
|
|
1452666
|
+
try {
|
|
1452667
|
+
const workspace = await context2.loadWorkspaceOrThrow();
|
|
1452668
|
+
return workspace.org;
|
|
1452669
|
+
} catch {
|
|
1452670
|
+
process.stderr.write(`${Icons.error} No organization specified.
|
|
1452662
1452671
|
|
|
1452663
1452672
|
Run fern init or specify an organization with --org, then run this command again.
|
|
1452664
1452673
|
`);
|
|
1452665
|
-
|
|
1452674
|
+
throw CliError.exit();
|
|
1452675
|
+
}
|
|
1452666
1452676
|
}
|
|
1452677
|
+
};
|
|
1452678
|
+
function addTokenCommand(cli) {
|
|
1452679
|
+
const cmd = new TokenCommand();
|
|
1452680
|
+
command2(cli, "token", "Generate an organization access token (FERN_TOKEN)", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("org", {
|
|
1452681
|
+
type: "string",
|
|
1452682
|
+
description: "Organization to generate token for (defaults to organization in fern.yml)"
|
|
1452683
|
+
}).example("$0 auth token", "Generate token for workspace organization").example("$0 auth token --org acme", "Generate token for specific organization").example("export FERN_TOKEN=$($0 auth token)", "Export token to variable"));
|
|
1452667
1452684
|
}
|
|
1452668
1452685
|
|
|
1452669
1452686
|
// ../cli-v2/lib/commands/auth/whoami/command.js
|
|
1452687
|
+
var WhoamiCommand = class {
|
|
1452688
|
+
async handle(context2, args) {
|
|
1452689
|
+
const activeAccount = await context2.tokenService.getActiveAccountInfo();
|
|
1452690
|
+
if (activeAccount == null) {
|
|
1452691
|
+
context2.stdout.warn(`${source_default.yellow("\u26A0")} You are not logged in to Fern.`);
|
|
1452692
|
+
context2.stdout.info("");
|
|
1452693
|
+
context2.stdout.info(source_default.dim(" To log in, run: fern auth login"));
|
|
1452694
|
+
throw CliError.exit();
|
|
1452695
|
+
}
|
|
1452696
|
+
if (args.json) {
|
|
1452697
|
+
context2.stdout.info(JSON.stringify({ email: activeAccount.user }, null, 2));
|
|
1452698
|
+
return;
|
|
1452699
|
+
}
|
|
1452700
|
+
context2.stdout.info(source_default.bold(activeAccount.user));
|
|
1452701
|
+
}
|
|
1452702
|
+
};
|
|
1452670
1452703
|
function addWhoamiCommand(cli) {
|
|
1452671
|
-
|
|
1452704
|
+
const cmd = new WhoamiCommand();
|
|
1452705
|
+
command2(cli, "whoami", "Print the current user", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("json", {
|
|
1452672
1452706
|
type: "boolean",
|
|
1452673
1452707
|
default: false,
|
|
1452674
1452708
|
description: "Output as JSON"
|
|
1452675
1452709
|
}));
|
|
1452676
1452710
|
}
|
|
1452677
|
-
async function handleWhoami(context2, args) {
|
|
1452678
|
-
const activeAccount = await context2.tokenService.getActiveAccountInfo();
|
|
1452679
|
-
if (activeAccount == null) {
|
|
1452680
|
-
context2.stdout.warn(`${source_default.yellow("\u26A0")} You are not logged in to Fern.`);
|
|
1452681
|
-
context2.stdout.info("");
|
|
1452682
|
-
context2.stdout.info(source_default.dim(" To log in, run: fern auth login"));
|
|
1452683
|
-
throw CliError.exit();
|
|
1452684
|
-
}
|
|
1452685
|
-
if (args.json) {
|
|
1452686
|
-
context2.stdout.info(JSON.stringify({ email: activeAccount.user }, null, 2));
|
|
1452687
|
-
return;
|
|
1452688
|
-
}
|
|
1452689
|
-
context2.stdout.info(source_default.bold(activeAccount.user));
|
|
1452690
|
-
}
|
|
1452691
1452711
|
|
|
1452692
1452712
|
// ../cli-v2/lib/commands/auth/command.js
|
|
1452693
1452713
|
function addAuthCommand(cli) {
|
|
@@ -1552367,6 +1552387,20 @@ var ExampleConverter = class _ExampleConverter extends AbstractConverter {
|
|
|
1552367
1552387
|
}
|
|
1552368
1552388
|
});
|
|
1552369
1552389
|
const allOfResults = (resolvedSchema.allOf ?? []).map((subSchema, index3) => {
|
|
1552390
|
+
const resolvedSubSchema = this.context.resolveMaybeReference({
|
|
1552391
|
+
schemaOrReference: subSchema,
|
|
1552392
|
+
breadcrumbs: [...this.breadcrumbs, `allOf[${index3}]`],
|
|
1552393
|
+
skipErrorCollector: true
|
|
1552394
|
+
});
|
|
1552395
|
+
if (resolvedSubSchema && this.isConstraintOnlySchema(resolvedSubSchema)) {
|
|
1552396
|
+
return {
|
|
1552397
|
+
isValid: true,
|
|
1552398
|
+
coerced: false,
|
|
1552399
|
+
usedProvidedExample: this.example !== void 0,
|
|
1552400
|
+
validExample: this.example,
|
|
1552401
|
+
errors: []
|
|
1552402
|
+
};
|
|
1552403
|
+
}
|
|
1552370
1552404
|
const exampleConverter = new _ExampleConverter({
|
|
1552371
1552405
|
breadcrumbs: [...this.breadcrumbs, `allOf[${index3}]`],
|
|
1552372
1552406
|
context: this.context,
|
|
@@ -1552392,7 +1552426,7 @@ var ExampleConverter = class _ExampleConverter extends AbstractConverter {
|
|
|
1552392
1552426
|
}
|
|
1552393
1552427
|
}
|
|
1552394
1552428
|
const additionalPropertiesResults = [];
|
|
1552395
|
-
const definedPropertyKeys =
|
|
1552429
|
+
const definedPropertyKeys = this.collectAllPropertyKeys(resolvedSchema);
|
|
1552396
1552430
|
const additionalPropertyKeys = Object.keys(exampleObj).filter((key2) => !definedPropertyKeys.has(key2));
|
|
1552397
1552431
|
if (additionalPropertyKeys.length > 0) {
|
|
1552398
1552432
|
if (resolvedSchema.additionalProperties === false) {
|
|
@@ -1552688,12 +1552722,94 @@ var ExampleConverter = class _ExampleConverter extends AbstractConverter {
|
|
|
1552688
1552722
|
}
|
|
1552689
1552723
|
return void 0;
|
|
1552690
1552724
|
}
|
|
1552725
|
+
/**
|
|
1552726
|
+
* Checks if a schema is a "constraint-only" schema that only has validation constraints
|
|
1552727
|
+
* like 'required' but no actual structure (no type, properties, allOf, oneOf, anyOf, etc.).
|
|
1552728
|
+
* These schemas are used in allOf compositions to add constraints to the merged schema.
|
|
1552729
|
+
*/
|
|
1552730
|
+
isConstraintOnlySchema(schema2) {
|
|
1552731
|
+
if (schema2.type !== void 0 || schema2.properties !== void 0 || schema2.allOf !== void 0 || schema2.oneOf !== void 0 || schema2.anyOf !== void 0 || "items" in schema2 || schema2.additionalProperties !== void 0 || schema2.enum !== void 0 || schema2.const !== void 0) {
|
|
1552732
|
+
return false;
|
|
1552733
|
+
}
|
|
1552734
|
+
const constraintOnlyFields = /* @__PURE__ */ new Set([
|
|
1552735
|
+
"required",
|
|
1552736
|
+
"description",
|
|
1552737
|
+
"title",
|
|
1552738
|
+
"deprecated",
|
|
1552739
|
+
"readOnly",
|
|
1552740
|
+
"writeOnly",
|
|
1552741
|
+
"nullable",
|
|
1552742
|
+
"example",
|
|
1552743
|
+
"examples",
|
|
1552744
|
+
"default",
|
|
1552745
|
+
"minLength",
|
|
1552746
|
+
"maxLength",
|
|
1552747
|
+
"minimum",
|
|
1552748
|
+
"maximum",
|
|
1552749
|
+
"exclusiveMinimum",
|
|
1552750
|
+
"exclusiveMaximum",
|
|
1552751
|
+
"minItems",
|
|
1552752
|
+
"maxItems",
|
|
1552753
|
+
"uniqueItems",
|
|
1552754
|
+
"pattern",
|
|
1552755
|
+
"format"
|
|
1552756
|
+
]);
|
|
1552757
|
+
const schemaKeys = Object.keys(schema2);
|
|
1552758
|
+
return schemaKeys.length > 0 && schemaKeys.every((key2) => constraintOnlyFields.has(key2));
|
|
1552759
|
+
}
|
|
1552691
1552760
|
isDeprecatedProperty(property11) {
|
|
1552692
1552761
|
return property11 != null && "availability" in property11 && property11.availability === "deprecated";
|
|
1552693
1552762
|
}
|
|
1552694
1552763
|
isRequiredProperty({ key: key2, resolvedSchema }) {
|
|
1552695
1552764
|
return resolvedSchema.required?.includes(key2) ?? false;
|
|
1552696
1552765
|
}
|
|
1552766
|
+
/**
|
|
1552767
|
+
* Recursively collects all property keys from a schema, including properties
|
|
1552768
|
+
* from allOf, oneOf, and anyOf compositions.
|
|
1552769
|
+
*/
|
|
1552770
|
+
collectAllPropertyKeys(schema2, visited = /* @__PURE__ */ new Set()) {
|
|
1552771
|
+
const propertyKeys = /* @__PURE__ */ new Set();
|
|
1552772
|
+
if (schema2.properties) {
|
|
1552773
|
+
for (const key2 of Object.keys(schema2.properties)) {
|
|
1552774
|
+
propertyKeys.add(key2);
|
|
1552775
|
+
}
|
|
1552776
|
+
}
|
|
1552777
|
+
for (const subSchema of schema2.allOf ?? []) {
|
|
1552778
|
+
const resolved = this.context.resolveMaybeReference({
|
|
1552779
|
+
schemaOrReference: subSchema,
|
|
1552780
|
+
breadcrumbs: this.breadcrumbs,
|
|
1552781
|
+
skipErrorCollector: true
|
|
1552782
|
+
});
|
|
1552783
|
+
if (resolved) {
|
|
1552784
|
+
const refKey = this.context.isReferenceObject(subSchema) ? subSchema.$ref : JSON.stringify(resolved);
|
|
1552785
|
+
if (!visited.has(refKey)) {
|
|
1552786
|
+
visited.add(refKey);
|
|
1552787
|
+
const nestedKeys = this.collectAllPropertyKeys(resolved, visited);
|
|
1552788
|
+
for (const key2 of nestedKeys) {
|
|
1552789
|
+
propertyKeys.add(key2);
|
|
1552790
|
+
}
|
|
1552791
|
+
}
|
|
1552792
|
+
}
|
|
1552793
|
+
}
|
|
1552794
|
+
for (const subSchema of [...schema2.oneOf ?? [], ...schema2.anyOf ?? []]) {
|
|
1552795
|
+
const resolved = this.context.resolveMaybeReference({
|
|
1552796
|
+
schemaOrReference: subSchema,
|
|
1552797
|
+
breadcrumbs: this.breadcrumbs,
|
|
1552798
|
+
skipErrorCollector: true
|
|
1552799
|
+
});
|
|
1552800
|
+
if (resolved) {
|
|
1552801
|
+
const refKey = this.context.isReferenceObject(subSchema) ? subSchema.$ref : JSON.stringify(resolved);
|
|
1552802
|
+
if (!visited.has(refKey)) {
|
|
1552803
|
+
visited.add(refKey);
|
|
1552804
|
+
const nestedKeys = this.collectAllPropertyKeys(resolved, visited);
|
|
1552805
|
+
for (const key2 of nestedKeys) {
|
|
1552806
|
+
propertyKeys.add(key2);
|
|
1552807
|
+
}
|
|
1552808
|
+
}
|
|
1552809
|
+
}
|
|
1552810
|
+
}
|
|
1552811
|
+
return propertyKeys;
|
|
1552812
|
+
}
|
|
1552697
1552813
|
};
|
|
1552698
1552814
|
|
|
1552699
1552815
|
// ../api-importers/v3-importer-commons/lib/converters/schema/index.js
|
|
@@ -1554218,29 +1554334,23 @@ var SchemaConverter = class _SchemaConverter extends AbstractConverter {
|
|
|
1554218
1554334
|
const userSpecifiedExamples = {};
|
|
1554219
1554335
|
for (const [index3, example] of examples.entries()) {
|
|
1554220
1554336
|
const resolvedExample = this.context.resolveExample(example);
|
|
1554337
|
+
const exampleName = `${this.id}_example_${index3}`;
|
|
1554221
1554338
|
const convertedExample = this.generateOrValidateExample({
|
|
1554222
|
-
example: resolvedExample
|
|
1554339
|
+
example: resolvedExample,
|
|
1554340
|
+
exampleName
|
|
1554223
1554341
|
});
|
|
1554224
|
-
userSpecifiedExamples[
|
|
1554342
|
+
userSpecifiedExamples[exampleName] = convertedExample;
|
|
1554225
1554343
|
}
|
|
1554226
1554344
|
return userSpecifiedExamples;
|
|
1554227
1554345
|
}
|
|
1554228
|
-
generateOrValidateExample({ example
|
|
1554346
|
+
generateOrValidateExample({ example }) {
|
|
1554229
1554347
|
const exampleConverter = new ExampleConverter({
|
|
1554230
1554348
|
breadcrumbs: this.breadcrumbs,
|
|
1554231
1554349
|
context: this.context,
|
|
1554232
1554350
|
schema: this.schema,
|
|
1554233
1554351
|
example
|
|
1554234
1554352
|
});
|
|
1554235
|
-
const { validExample: convertedExample
|
|
1554236
|
-
if (!ignoreErrors) {
|
|
1554237
|
-
errors4.forEach((error49) => {
|
|
1554238
|
-
this.context.errorCollector.collect({
|
|
1554239
|
-
message: error49.message,
|
|
1554240
|
-
path: error49.path
|
|
1554241
|
-
});
|
|
1554242
|
-
});
|
|
1554243
|
-
}
|
|
1554353
|
+
const { validExample: convertedExample } = exampleConverter.convert();
|
|
1554244
1554354
|
return convertedExample;
|
|
1554245
1554355
|
}
|
|
1554246
1554356
|
};
|
|
@@ -1554506,7 +1554616,8 @@ var AbstractMediaTypeObjectConverter = class extends AbstractConverter {
|
|
|
1554506
1554616
|
v2Examples.userSpecifiedExamples[exampleName] = this.generateOrValidateExample({
|
|
1554507
1554617
|
schema: schema2,
|
|
1554508
1554618
|
example: resolvedExample,
|
|
1554509
|
-
exampleGenerationStrategy
|
|
1554619
|
+
exampleGenerationStrategy,
|
|
1554620
|
+
exampleName
|
|
1554510
1554621
|
});
|
|
1554511
1554622
|
} else {
|
|
1554512
1554623
|
v2Examples.userSpecifiedExamples[exampleName] = resolvedExample;
|
|
@@ -1554514,18 +1554625,19 @@ var AbstractMediaTypeObjectConverter = class extends AbstractConverter {
|
|
|
1554514
1554625
|
}
|
|
1554515
1554626
|
}
|
|
1554516
1554627
|
if (Object.keys(v2Examples.userSpecifiedExamples).length === 0 && schema2 != null) {
|
|
1554517
|
-
const
|
|
1554518
|
-
v2Examples.autogeneratedExamples[
|
|
1554628
|
+
const autoExampleName = camelCase_default(`${[...this.group, this.method].join("_")}_example`);
|
|
1554629
|
+
v2Examples.autogeneratedExamples[autoExampleName] = this.generateOrValidateExample({
|
|
1554519
1554630
|
schema: schema2,
|
|
1554520
1554631
|
example: void 0,
|
|
1554521
1554632
|
ignoreErrors: true,
|
|
1554522
1554633
|
generateOptionalProperties,
|
|
1554523
|
-
exampleGenerationStrategy
|
|
1554634
|
+
exampleGenerationStrategy,
|
|
1554635
|
+
exampleName: autoExampleName
|
|
1554524
1554636
|
});
|
|
1554525
1554637
|
}
|
|
1554526
1554638
|
return v2Examples;
|
|
1554527
1554639
|
}
|
|
1554528
|
-
generateOrValidateExample({ schema: schema2, example,
|
|
1554640
|
+
generateOrValidateExample({ schema: schema2, example, generateOptionalProperties, exampleGenerationStrategy }) {
|
|
1554529
1554641
|
const resolvedSchema = this.context.resolveMaybeReference({
|
|
1554530
1554642
|
schemaOrReference: schema2,
|
|
1554531
1554643
|
breadcrumbs: this.breadcrumbs,
|
|
@@ -1554546,15 +1554658,7 @@ var AbstractMediaTypeObjectConverter = class extends AbstractConverter {
|
|
|
1554546
1554658
|
generateOptionalProperties: generateOptionalProperties ?? false,
|
|
1554547
1554659
|
exampleGenerationStrategy
|
|
1554548
1554660
|
});
|
|
1554549
|
-
const { validExample: convertedExample
|
|
1554550
|
-
if (!ignoreErrors) {
|
|
1554551
|
-
errors4.forEach((error49) => {
|
|
1554552
|
-
this.context.errorCollector.collect({
|
|
1554553
|
-
message: error49.message,
|
|
1554554
|
-
path: error49.path
|
|
1554555
|
-
});
|
|
1554556
|
-
});
|
|
1554557
|
-
}
|
|
1554661
|
+
const { validExample: convertedExample } = exampleConverter.convert();
|
|
1554558
1554662
|
return convertedExample;
|
|
1554559
1554663
|
}
|
|
1554560
1554664
|
};
|
|
@@ -1554660,7 +1554764,8 @@ var AbstractParameterConverter = class extends AbstractConverter {
|
|
|
1554660
1554764
|
if (resolvedExample != null) {
|
|
1554661
1554765
|
v2Examples.userSpecifiedExamples[key2] = this.generateOrValidateExample({
|
|
1554662
1554766
|
schema: schema2,
|
|
1554663
|
-
example: resolvedExample
|
|
1554767
|
+
example: resolvedExample,
|
|
1554768
|
+
exampleName: key2
|
|
1554664
1554769
|
});
|
|
1554665
1554770
|
}
|
|
1554666
1554771
|
}
|
|
@@ -1554671,7 +1554776,8 @@ var AbstractParameterConverter = class extends AbstractConverter {
|
|
|
1554671
1554776
|
});
|
|
1554672
1554777
|
v2Examples.userSpecifiedExamples[parameterExampleName] = this.generateOrValidateExample({
|
|
1554673
1554778
|
schema: schema2,
|
|
1554674
|
-
example: parameterExample
|
|
1554779
|
+
example: parameterExample,
|
|
1554780
|
+
exampleName: parameterExampleName
|
|
1554675
1554781
|
});
|
|
1554676
1554782
|
}
|
|
1554677
1554783
|
if (Object.keys(v2Examples.userSpecifiedExamples).length === 0) {
|
|
@@ -1554679,27 +1554785,20 @@ var AbstractParameterConverter = class extends AbstractConverter {
|
|
|
1554679
1554785
|
v2Examples.autogeneratedExamples[exampleName] = this.generateOrValidateExample({
|
|
1554680
1554786
|
schema: schema2,
|
|
1554681
1554787
|
example: void 0,
|
|
1554682
|
-
ignoreErrors: true
|
|
1554788
|
+
ignoreErrors: true,
|
|
1554789
|
+
exampleName
|
|
1554683
1554790
|
});
|
|
1554684
1554791
|
}
|
|
1554685
1554792
|
return v2Examples;
|
|
1554686
1554793
|
}
|
|
1554687
|
-
generateOrValidateExample({ schema: schema2,
|
|
1554794
|
+
generateOrValidateExample({ schema: schema2, example }) {
|
|
1554688
1554795
|
const exampleConverter = new ExampleConverter({
|
|
1554689
1554796
|
breadcrumbs: this.breadcrumbs,
|
|
1554690
1554797
|
context: this.context,
|
|
1554691
1554798
|
schema: schema2,
|
|
1554692
1554799
|
example
|
|
1554693
1554800
|
});
|
|
1554694
|
-
const { validExample: convertedExample
|
|
1554695
|
-
if (!ignoreErrors) {
|
|
1554696
|
-
errors4.forEach((error49) => {
|
|
1554697
|
-
this.context.errorCollector.collect({
|
|
1554698
|
-
message: error49.message,
|
|
1554699
|
-
path: error49.path
|
|
1554700
|
-
});
|
|
1554701
|
-
});
|
|
1554702
|
-
}
|
|
1554801
|
+
const { validExample: convertedExample } = exampleConverter.convert();
|
|
1554703
1554802
|
return convertedExample;
|
|
1554704
1554803
|
}
|
|
1554705
1554804
|
/**
|
|
@@ -1555097,14 +1555196,64 @@ var ExampleValidator = class {
|
|
|
1555097
1555196
|
breadcrumbs: [],
|
|
1555098
1555197
|
skipErrorCollector: true
|
|
1555099
1555198
|
});
|
|
1555100
|
-
if (!schema2
|
|
1555199
|
+
if (!schema2) {
|
|
1555200
|
+
return false;
|
|
1555201
|
+
}
|
|
1555202
|
+
if (!schema2.properties && !schema2.allOf && !schema2.oneOf && !schema2.anyOf) {
|
|
1555101
1555203
|
return false;
|
|
1555102
1555204
|
}
|
|
1555103
1555205
|
const exampleObj = example;
|
|
1555104
|
-
const definedProperties =
|
|
1555206
|
+
const definedProperties = this.collectAllPropertyKeys(schema2);
|
|
1555105
1555207
|
const exampleProperties = Object.keys(exampleObj);
|
|
1555106
1555208
|
return exampleProperties.some((prop) => !definedProperties.has(prop));
|
|
1555107
1555209
|
}
|
|
1555210
|
+
/**
|
|
1555211
|
+
* Recursively collects all property keys from a schema, including properties
|
|
1555212
|
+
* from allOf, oneOf, and anyOf compositions.
|
|
1555213
|
+
*/
|
|
1555214
|
+
collectAllPropertyKeys(schema2, visited = /* @__PURE__ */ new Set()) {
|
|
1555215
|
+
const propertyKeys = /* @__PURE__ */ new Set();
|
|
1555216
|
+
if (schema2.properties) {
|
|
1555217
|
+
for (const key2 of Object.keys(schema2.properties)) {
|
|
1555218
|
+
propertyKeys.add(key2);
|
|
1555219
|
+
}
|
|
1555220
|
+
}
|
|
1555221
|
+
for (const subSchema of schema2.allOf ?? []) {
|
|
1555222
|
+
const resolved = this.context.resolveMaybeReference({
|
|
1555223
|
+
schemaOrReference: subSchema,
|
|
1555224
|
+
breadcrumbs: [],
|
|
1555225
|
+
skipErrorCollector: true
|
|
1555226
|
+
});
|
|
1555227
|
+
if (resolved) {
|
|
1555228
|
+
const refKey = this.context.isReferenceObject(subSchema) ? subSchema.$ref : JSON.stringify(resolved);
|
|
1555229
|
+
if (!visited.has(refKey)) {
|
|
1555230
|
+
visited.add(refKey);
|
|
1555231
|
+
const nestedKeys = this.collectAllPropertyKeys(resolved, visited);
|
|
1555232
|
+
for (const key2 of nestedKeys) {
|
|
1555233
|
+
propertyKeys.add(key2);
|
|
1555234
|
+
}
|
|
1555235
|
+
}
|
|
1555236
|
+
}
|
|
1555237
|
+
}
|
|
1555238
|
+
for (const subSchema of [...schema2.oneOf ?? [], ...schema2.anyOf ?? []]) {
|
|
1555239
|
+
const resolved = this.context.resolveMaybeReference({
|
|
1555240
|
+
schemaOrReference: subSchema,
|
|
1555241
|
+
breadcrumbs: [],
|
|
1555242
|
+
skipErrorCollector: true
|
|
1555243
|
+
});
|
|
1555244
|
+
if (resolved) {
|
|
1555245
|
+
const refKey = this.context.isReferenceObject(subSchema) ? subSchema.$ref : JSON.stringify(resolved);
|
|
1555246
|
+
if (!visited.has(refKey)) {
|
|
1555247
|
+
visited.add(refKey);
|
|
1555248
|
+
const nestedKeys = this.collectAllPropertyKeys(resolved, visited);
|
|
1555249
|
+
for (const key2 of nestedKeys) {
|
|
1555250
|
+
propertyKeys.add(key2);
|
|
1555251
|
+
}
|
|
1555252
|
+
}
|
|
1555253
|
+
}
|
|
1555254
|
+
}
|
|
1555255
|
+
return propertyKeys;
|
|
1555256
|
+
}
|
|
1555108
1555257
|
/**
|
|
1555109
1555258
|
* Validates human examples (from `examples` or `x-fern-examples`) in an OpenAPI spec
|
|
1555110
1555259
|
* Returns warnings for invalid examples (non-blocking)
|
|
@@ -1561678,13 +1561827,10 @@ var OSSWorkspace = class _OSSWorkspace extends BaseOpenAPIWorkspace {
|
|
|
1561678
1561827
|
const errorStats = errorCollector.getErrorStats();
|
|
1561679
1561828
|
const specInfo = errorCollector.relativeFilepathToSpec ? ` for ${errorCollector.relativeFilepathToSpec}` : "";
|
|
1561680
1561829
|
if (errorStats.numErrors > 0) {
|
|
1561681
|
-
context2.logger.log("error", `API validation${specInfo} completed with ${errorStats.numErrors} errors
|
|
1561682
|
-
} else if (errorStats.numWarnings > 0) {
|
|
1561830
|
+
context2.logger.log("error", `API validation${specInfo} completed with ${errorStats.numErrors} errors.`);
|
|
1561831
|
+
} else if (errorStats.numWarnings > 0 && logWarnings) {
|
|
1561683
1561832
|
context2.logger.log("warn", `API validation${specInfo} completed with ${errorStats.numWarnings} warnings.`);
|
|
1561684
|
-
} else {
|
|
1561685
|
-
context2.logger.log("info", `All checks passed when parsing OpenAPI${specInfo}.`);
|
|
1561686
1561833
|
}
|
|
1561687
|
-
context2.logger.log("info", "");
|
|
1561688
1561834
|
await errorCollector.logErrors({ logWarnings });
|
|
1561689
1561835
|
}
|
|
1561690
1561836
|
}
|
|
@@ -1562459,8 +1562605,37 @@ var ApiChecker = class {
|
|
|
1562459
1562605
|
};
|
|
1562460
1562606
|
|
|
1562461
1562607
|
// ../cli-v2/lib/commands/check/command.js
|
|
1562608
|
+
var CheckCommand = class {
|
|
1562609
|
+
async handle(context2, args) {
|
|
1562610
|
+
const workspace = await context2.loadWorkspaceOrThrow();
|
|
1562611
|
+
this.validateArgs(args, workspace);
|
|
1562612
|
+
const checker = new ApiChecker({
|
|
1562613
|
+
context: context2,
|
|
1562614
|
+
cliVersion: workspace.cliVersion
|
|
1562615
|
+
});
|
|
1562616
|
+
const checkResult = await checker.check({
|
|
1562617
|
+
workspace,
|
|
1562618
|
+
apiNames: args.api != null ? [args.api] : void 0,
|
|
1562619
|
+
strict: args.strict
|
|
1562620
|
+
});
|
|
1562621
|
+
const hasErrors = checkResult.invalidApis.size > 0;
|
|
1562622
|
+
const hasWarnings = checkResult.warningCount > 0;
|
|
1562623
|
+
if (hasErrors || args.strict && hasWarnings) {
|
|
1562624
|
+
throw CliError.exit();
|
|
1562625
|
+
}
|
|
1562626
|
+
}
|
|
1562627
|
+
validateArgs(args, workspace) {
|
|
1562628
|
+
if (args.api != null && workspace.apis[args.api] == null) {
|
|
1562629
|
+
const availableApis = Object.keys(workspace.apis).join(", ");
|
|
1562630
|
+
throw new CliError({
|
|
1562631
|
+
message: `API '${args.api}' not found. Available APIs: ${availableApis}`
|
|
1562632
|
+
});
|
|
1562633
|
+
}
|
|
1562634
|
+
}
|
|
1562635
|
+
};
|
|
1562462
1562636
|
function addCheckCommand(cli) {
|
|
1562463
|
-
|
|
1562637
|
+
const cmd = new CheckCommand();
|
|
1562638
|
+
command2(cli, "check", "Validate your API, docs, and SDK configuration", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("api", {
|
|
1562464
1562639
|
type: "string",
|
|
1562465
1562640
|
description: "Validate a specific API"
|
|
1562466
1562641
|
}).option("strict", {
|
|
@@ -1562469,32 +1562644,6 @@ function addCheckCommand(cli) {
|
|
|
1562469
1562644
|
default: false
|
|
1562470
1562645
|
}));
|
|
1562471
1562646
|
}
|
|
1562472
|
-
async function handleCheck(context2, args) {
|
|
1562473
|
-
const workspace = await context2.loadWorkspaceOrThrow();
|
|
1562474
|
-
validateArgs({ args, workspace });
|
|
1562475
|
-
const checker = new ApiChecker({
|
|
1562476
|
-
context: context2,
|
|
1562477
|
-
cliVersion: workspace.cliVersion
|
|
1562478
|
-
});
|
|
1562479
|
-
const checkResult = await checker.check({
|
|
1562480
|
-
workspace,
|
|
1562481
|
-
apiNames: args.api != null ? [args.api] : void 0,
|
|
1562482
|
-
strict: args.strict
|
|
1562483
|
-
});
|
|
1562484
|
-
const hasErrors = checkResult.invalidApis.size > 0;
|
|
1562485
|
-
const hasWarnings = checkResult.warningCount > 0;
|
|
1562486
|
-
if (hasErrors || args.strict && hasWarnings) {
|
|
1562487
|
-
throw CliError.exit();
|
|
1562488
|
-
}
|
|
1562489
|
-
}
|
|
1562490
|
-
function validateArgs({ args, workspace }) {
|
|
1562491
|
-
if (args.api != null && workspace.apis[args.api] == null) {
|
|
1562492
|
-
const availableApis = Object.keys(workspace.apis).join(", ");
|
|
1562493
|
-
throw new CliError({
|
|
1562494
|
-
message: `API '${args.api}' not found. Available APIs: ${availableApis}`
|
|
1562495
|
-
});
|
|
1562496
|
-
}
|
|
1562497
|
-
}
|
|
1562498
1562647
|
|
|
1562499
1562648
|
// ../cli-v2/lib/migrator/Migrator.js
|
|
1562500
1562649
|
var import_promises44 = require("fs/promises");
|
|
@@ -1563811,47 +1563960,50 @@ var Migrator = class {
|
|
|
1563811
1563960
|
};
|
|
1563812
1563961
|
|
|
1563813
1563962
|
// ../cli-v2/lib/commands/config/migrate/command.js
|
|
1563963
|
+
var MigrateCommand = class {
|
|
1563964
|
+
async handle(context2, args) {
|
|
1563965
|
+
const migrator = new Migrator({
|
|
1563966
|
+
cwd: context2.cwd,
|
|
1563967
|
+
logger: context2.stdout,
|
|
1563968
|
+
deleteOriginals: args.delete
|
|
1563969
|
+
});
|
|
1563970
|
+
const result = await migrator.migrate();
|
|
1563971
|
+
for (const warning of result.warnings) {
|
|
1563972
|
+
switch (warning.type) {
|
|
1563973
|
+
case "deprecated":
|
|
1563974
|
+
context2.stdout.warn(`Deprecated: ${warning.message}`);
|
|
1563975
|
+
break;
|
|
1563976
|
+
case "unsupported":
|
|
1563977
|
+
context2.stdout.warn(`Unsupported: ${warning.message}`);
|
|
1563978
|
+
break;
|
|
1563979
|
+
case "conflict":
|
|
1563980
|
+
context2.stderr.error(`Error: ${warning.message}`);
|
|
1563981
|
+
break;
|
|
1563982
|
+
case "info":
|
|
1563983
|
+
context2.stdout.info(warning.message);
|
|
1563984
|
+
break;
|
|
1563985
|
+
}
|
|
1563986
|
+
if (warning.suggestion != null) {
|
|
1563987
|
+
context2.stdout.info(` Suggestion: ${warning.suggestion}`);
|
|
1563988
|
+
}
|
|
1563989
|
+
}
|
|
1563990
|
+
if (result.success) {
|
|
1563991
|
+
if (result.outputPath != null) {
|
|
1563992
|
+
context2.stdout.debug(`Created: ${result.outputPath}`);
|
|
1563993
|
+
}
|
|
1563994
|
+
return;
|
|
1563995
|
+
}
|
|
1563996
|
+
throw new CliError({ message: "Migration failed" });
|
|
1563997
|
+
}
|
|
1563998
|
+
};
|
|
1563814
1563999
|
function addMigrateCommand(cli) {
|
|
1563815
|
-
|
|
1564000
|
+
const cmd = new MigrateCommand();
|
|
1564001
|
+
command2(cli, "migrate", "Migrate legacy configuration files to fern.yml", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("delete", {
|
|
1563816
1564002
|
type: "boolean",
|
|
1563817
1564003
|
description: "Keep original files after migration",
|
|
1563818
1564004
|
default: true
|
|
1563819
1564005
|
}));
|
|
1563820
1564006
|
}
|
|
1563821
|
-
async function handleMigrate(context2, args) {
|
|
1563822
|
-
const migrator = new Migrator({
|
|
1563823
|
-
cwd: context2.cwd,
|
|
1563824
|
-
logger: context2.stdout,
|
|
1563825
|
-
deleteOriginals: args.delete
|
|
1563826
|
-
});
|
|
1563827
|
-
const result = await migrator.migrate();
|
|
1563828
|
-
for (const warning of result.warnings) {
|
|
1563829
|
-
switch (warning.type) {
|
|
1563830
|
-
case "deprecated":
|
|
1563831
|
-
context2.stdout.warn(`Deprecated: ${warning.message}`);
|
|
1563832
|
-
break;
|
|
1563833
|
-
case "unsupported":
|
|
1563834
|
-
context2.stdout.warn(`Unsupported: ${warning.message}`);
|
|
1563835
|
-
break;
|
|
1563836
|
-
case "conflict":
|
|
1563837
|
-
context2.stderr.error(`Error: ${warning.message}`);
|
|
1563838
|
-
break;
|
|
1563839
|
-
case "info":
|
|
1563840
|
-
context2.stdout.info(warning.message);
|
|
1563841
|
-
break;
|
|
1563842
|
-
}
|
|
1563843
|
-
if (warning.suggestion != null) {
|
|
1563844
|
-
context2.stdout.info(` Suggestion: ${warning.suggestion}`);
|
|
1563845
|
-
}
|
|
1563846
|
-
}
|
|
1563847
|
-
if (result.success) {
|
|
1563848
|
-
if (result.outputPath != null) {
|
|
1563849
|
-
context2.stdout.debug(`Created: ${result.outputPath}`);
|
|
1563850
|
-
}
|
|
1563851
|
-
return;
|
|
1563852
|
-
}
|
|
1563853
|
-
throw new CliError({ message: "Migration failed" });
|
|
1563854
|
-
}
|
|
1563855
1564007
|
|
|
1563856
1564008
|
// ../cli-v2/lib/commands/config/command.js
|
|
1563857
1564009
|
function addConfigCommand(cli) {
|
|
@@ -1617448,6 +1617600,7 @@ var LocalTaskHandler = class {
|
|
|
1617448
1617600
|
await this.copyGeneratedFilesToDirectory(this.absolutePathToLocalOutput);
|
|
1617449
1617601
|
await this.runGitCommand(["add", "."], this.absolutePathToLocalOutput);
|
|
1617450
1617602
|
await this.runGitCommand(["reset", "--", ...fernIgnorePaths], this.absolutePathToLocalOutput);
|
|
1617603
|
+
await this.runGitCommand(["clean", "-fd", "--", ...fernIgnorePaths], this.absolutePathToLocalOutput);
|
|
1617451
1617604
|
await this.runGitCommand(["restore", "."], this.absolutePathToLocalOutput);
|
|
1617452
1617605
|
}
|
|
1617453
1617606
|
async copyGeneratedFilesWithFernIgnoreInTempRepo() {
|
|
@@ -1617467,6 +1617620,7 @@ var LocalTaskHandler = class {
|
|
|
1617467
1617620
|
await this.copyGeneratedFilesToDirectory(tmpOutputResolutionDir);
|
|
1617468
1617621
|
await this.runGitCommand(["add", "."], tmpOutputResolutionDir);
|
|
1617469
1617622
|
await this.runGitCommand(["reset", "--", ...fernIgnorePaths], tmpOutputResolutionDir);
|
|
1617623
|
+
await this.runGitCommand(["clean", "-fd", "--", ...fernIgnorePaths], tmpOutputResolutionDir);
|
|
1617470
1617624
|
await this.runGitCommand(["restore", "."], tmpOutputResolutionDir);
|
|
1617471
1617625
|
await (0, import_promises55.rm)(join4(tmpOutputResolutionDir, RelativeFilePath2.of(".git")), { recursive: true });
|
|
1617472
1617626
|
await (0, import_promises55.rm)(this.absolutePathToLocalOutput, { recursive: true });
|
|
@@ -1681062,8 +1681216,175 @@ ${source_default.dim(`Logs written to: ${logFilePath}`)}
|
|
|
1681062
1681216
|
};
|
|
1681063
1681217
|
|
|
1681064
1681218
|
// ../cli-v2/lib/commands/sdk/generate/command.js
|
|
1681219
|
+
var GenerateCommand = class {
|
|
1681220
|
+
async handle(context2, args) {
|
|
1681221
|
+
this.validateArgs(args);
|
|
1681222
|
+
const workspace = await context2.loadWorkspaceOrThrow();
|
|
1681223
|
+
if (workspace.sdks == null) {
|
|
1681224
|
+
throw new Error("No SDKs configured in fern.yml");
|
|
1681225
|
+
}
|
|
1681226
|
+
const targets2 = this.getTargets({
|
|
1681227
|
+
workspace,
|
|
1681228
|
+
groupName: args.group ?? workspace.sdks.defaultGroup,
|
|
1681229
|
+
targetName: args.target
|
|
1681230
|
+
});
|
|
1681231
|
+
const apisToCheck = [...new Set(targets2.map((t2) => t2.api))];
|
|
1681232
|
+
const checker = new ApiChecker({
|
|
1681233
|
+
context: context2,
|
|
1681234
|
+
cliVersion: workspace.cliVersion
|
|
1681235
|
+
});
|
|
1681236
|
+
const checkResult = await checker.check({
|
|
1681237
|
+
workspace,
|
|
1681238
|
+
apiNames: apisToCheck
|
|
1681239
|
+
});
|
|
1681240
|
+
const validTargets = targets2.filter((t2) => checkResult.validApis.has(t2.api));
|
|
1681241
|
+
if (validTargets.length === 0) {
|
|
1681242
|
+
throw CliError.exit();
|
|
1681243
|
+
}
|
|
1681244
|
+
const pipeline5 = new GeneratorPipeline({
|
|
1681245
|
+
context: context2,
|
|
1681246
|
+
cliVersion: workspace.cliVersion
|
|
1681247
|
+
});
|
|
1681248
|
+
const token = args.local ? void 0 : await context2.getTokenOrPrompt();
|
|
1681249
|
+
const runtime = args.local ? "local" : "remote";
|
|
1681250
|
+
const taskGroup = new TaskGroup({ context: context2 });
|
|
1681251
|
+
const skippedTargets = targets2.filter((t2) => checkResult.invalidApis.has(t2.api));
|
|
1681252
|
+
for (const target of skippedTargets) {
|
|
1681253
|
+
taskGroup.addTask({
|
|
1681254
|
+
id: target.name,
|
|
1681255
|
+
name: target.name,
|
|
1681256
|
+
status: "skipped",
|
|
1681257
|
+
skipReason: `API '${target.api}' has errors`
|
|
1681258
|
+
});
|
|
1681259
|
+
}
|
|
1681260
|
+
for (const target of validTargets) {
|
|
1681261
|
+
taskGroup.addTask({
|
|
1681262
|
+
id: target.name,
|
|
1681263
|
+
name: target.name
|
|
1681264
|
+
});
|
|
1681265
|
+
}
|
|
1681266
|
+
await taskGroup.start({
|
|
1681267
|
+
title: "Generating SDKs",
|
|
1681268
|
+
subtitle: `org: ${workspace.sdks.org}`
|
|
1681269
|
+
});
|
|
1681270
|
+
await Promise.all(validTargets.map(async (target) => {
|
|
1681271
|
+
const apiDefinition = workspace.apis[target.api];
|
|
1681272
|
+
if (apiDefinition == null) {
|
|
1681273
|
+
const message = `API '${target.api}' not found in workspace`;
|
|
1681274
|
+
taskGroup.updateTask({
|
|
1681275
|
+
id: target.name,
|
|
1681276
|
+
update: { status: "error", error: message }
|
|
1681277
|
+
});
|
|
1681278
|
+
return;
|
|
1681279
|
+
}
|
|
1681280
|
+
const task = taskGroup.getTask(target.name);
|
|
1681281
|
+
if (task == null) {
|
|
1681282
|
+
throw new Error(`Internal error; task '${target.name}' not found`);
|
|
1681283
|
+
}
|
|
1681284
|
+
taskGroup.updateTask({
|
|
1681285
|
+
id: target.name,
|
|
1681286
|
+
update: {
|
|
1681287
|
+
status: "running",
|
|
1681288
|
+
currentStep: `${target.image}:${target.version}`
|
|
1681289
|
+
}
|
|
1681290
|
+
});
|
|
1681291
|
+
const pipelineResult = await pipeline5.run({
|
|
1681292
|
+
organization: workspace.org,
|
|
1681293
|
+
ai: workspace.ai,
|
|
1681294
|
+
task,
|
|
1681295
|
+
target,
|
|
1681296
|
+
apiDefinition,
|
|
1681297
|
+
audiences: this.parseAudiences(args.audience),
|
|
1681298
|
+
runtime,
|
|
1681299
|
+
containerEngine: args["container-engine"] ?? "docker",
|
|
1681300
|
+
keepContainer: args["keep-container"],
|
|
1681301
|
+
preview: args.preview,
|
|
1681302
|
+
outputPath: args.output != null ? resolve5(context2.cwd, args.output) : void 0,
|
|
1681303
|
+
token,
|
|
1681304
|
+
version: args.version
|
|
1681305
|
+
});
|
|
1681306
|
+
if (!pipelineResult.success) {
|
|
1681307
|
+
taskGroup.updateTask({
|
|
1681308
|
+
id: target.name,
|
|
1681309
|
+
update: {
|
|
1681310
|
+
status: "error",
|
|
1681311
|
+
error: pipelineResult.error
|
|
1681312
|
+
}
|
|
1681313
|
+
});
|
|
1681314
|
+
return;
|
|
1681315
|
+
}
|
|
1681316
|
+
taskGroup.updateTask({
|
|
1681317
|
+
id: target.name,
|
|
1681318
|
+
update: {
|
|
1681319
|
+
status: "success",
|
|
1681320
|
+
output: pipelineResult.output
|
|
1681321
|
+
}
|
|
1681322
|
+
});
|
|
1681323
|
+
}));
|
|
1681324
|
+
const summary = taskGroup.complete({
|
|
1681325
|
+
successMessage: `Successfully generated ${this.maybePluralSdks(validTargets)}`,
|
|
1681326
|
+
errorMessage: `Failed to generate ${this.maybePluralSdks(validTargets)}`
|
|
1681327
|
+
});
|
|
1681328
|
+
if (summary.failedCount > 0) {
|
|
1681329
|
+
throw CliError.exit();
|
|
1681330
|
+
}
|
|
1681331
|
+
}
|
|
1681332
|
+
getTargets({ workspace, groupName, targetName }) {
|
|
1681333
|
+
const targets2 = workspace.sdks != null ? this.filterTargetsByGroup(workspace.sdks.targets, groupName) : [];
|
|
1681334
|
+
if (targetName != null) {
|
|
1681335
|
+
const filtered = targets2.filter((t2) => t2.name === targetName);
|
|
1681336
|
+
if (filtered.length === 0) {
|
|
1681337
|
+
throw new Error(`Target '${targetName}' not found`);
|
|
1681338
|
+
}
|
|
1681339
|
+
return filtered;
|
|
1681340
|
+
}
|
|
1681341
|
+
if (targets2.length === 0) {
|
|
1681342
|
+
if (groupName != null) {
|
|
1681343
|
+
throw new Error(`No targets found for group '${groupName}'`);
|
|
1681344
|
+
}
|
|
1681345
|
+
throw new Error("No targets configured in fern.yml");
|
|
1681346
|
+
}
|
|
1681347
|
+
return targets2;
|
|
1681348
|
+
}
|
|
1681349
|
+
/**
|
|
1681350
|
+
* Filter targets by group name. If no group is specified, returns all targets.
|
|
1681351
|
+
*/
|
|
1681352
|
+
filterTargetsByGroup(targets2, groupName) {
|
|
1681353
|
+
if (groupName == null) {
|
|
1681354
|
+
return targets2;
|
|
1681355
|
+
}
|
|
1681356
|
+
return targets2.filter((target) => target.groups?.includes(groupName));
|
|
1681357
|
+
}
|
|
1681358
|
+
parseAudiences(audiences) {
|
|
1681359
|
+
if (audiences == null || audiences.length === 0) {
|
|
1681360
|
+
return void 0;
|
|
1681361
|
+
}
|
|
1681362
|
+
return {
|
|
1681363
|
+
type: "select",
|
|
1681364
|
+
audiences
|
|
1681365
|
+
};
|
|
1681366
|
+
}
|
|
1681367
|
+
validateArgs(args) {
|
|
1681368
|
+
if (args.output != null && !args.preview) {
|
|
1681369
|
+
throw new Error("The --output flag can only be used with --preview");
|
|
1681370
|
+
}
|
|
1681371
|
+
if (args["container-engine"] != null && !args.local) {
|
|
1681372
|
+
throw new Error("The --container-engine flag can only be used with --local");
|
|
1681373
|
+
}
|
|
1681374
|
+
if (args.group != null && args.target != null) {
|
|
1681375
|
+
throw new Error("The --group and --target flags cannot be used together");
|
|
1681376
|
+
}
|
|
1681377
|
+
if (args.group == null && args.target == null) {
|
|
1681378
|
+
throw new Error("A --target or --group must be specified");
|
|
1681379
|
+
}
|
|
1681380
|
+
}
|
|
1681381
|
+
maybePluralSdks(targets2) {
|
|
1681382
|
+
return targets2.length === 1 ? "SDK" : "SDKs";
|
|
1681383
|
+
}
|
|
1681384
|
+
};
|
|
1681065
1681385
|
function addGenerateCommand(cli) {
|
|
1681066
|
-
|
|
1681386
|
+
const cmd = new GenerateCommand();
|
|
1681387
|
+
command2(cli, "generate", "Generate SDKs configured in fern.yml", (context2, args) => cmd.handle(context2, args), (yargs) => yargs.option("target", {
|
|
1681067
1681388
|
type: "string",
|
|
1681068
1681389
|
description: "The SDK target to generate"
|
|
1681069
1681390
|
}).option("group", {
|
|
@@ -1681100,167 +1681421,6 @@ function addGenerateCommand(cli) {
|
|
|
1681100
1681421
|
description: "The version to use for the generated packages (e.g. 1.0.0)"
|
|
1681101
1681422
|
}));
|
|
1681102
1681423
|
}
|
|
1681103
|
-
async function handleGenerate(context2, args) {
|
|
1681104
|
-
validateArgs2(args);
|
|
1681105
|
-
const workspace = await context2.loadWorkspaceOrThrow();
|
|
1681106
|
-
if (workspace.sdks == null) {
|
|
1681107
|
-
throw new Error("No SDKs configured in fern.yml");
|
|
1681108
|
-
}
|
|
1681109
|
-
const targets2 = getTargets({
|
|
1681110
|
-
workspace,
|
|
1681111
|
-
groupName: args.group ?? workspace.sdks.defaultGroup,
|
|
1681112
|
-
targetName: args.target
|
|
1681113
|
-
});
|
|
1681114
|
-
const apisToCheck = [...new Set(targets2.map((t2) => t2.api))];
|
|
1681115
|
-
const checker = new ApiChecker({
|
|
1681116
|
-
context: context2,
|
|
1681117
|
-
cliVersion: workspace.cliVersion
|
|
1681118
|
-
});
|
|
1681119
|
-
const checkResult = await checker.check({
|
|
1681120
|
-
workspace,
|
|
1681121
|
-
apiNames: apisToCheck
|
|
1681122
|
-
});
|
|
1681123
|
-
const validTargets = targets2.filter((t2) => checkResult.validApis.has(t2.api));
|
|
1681124
|
-
if (validTargets.length === 0) {
|
|
1681125
|
-
throw CliError.exit();
|
|
1681126
|
-
}
|
|
1681127
|
-
const pipeline5 = new GeneratorPipeline({
|
|
1681128
|
-
context: context2,
|
|
1681129
|
-
cliVersion: workspace.cliVersion
|
|
1681130
|
-
});
|
|
1681131
|
-
const token = args.local ? void 0 : await context2.getTokenOrPrompt();
|
|
1681132
|
-
const runtime = args.local ? "local" : "remote";
|
|
1681133
|
-
const taskGroup = new TaskGroup({ context: context2 });
|
|
1681134
|
-
const skippedTargets = targets2.filter((t2) => checkResult.invalidApis.has(t2.api));
|
|
1681135
|
-
for (const target of skippedTargets) {
|
|
1681136
|
-
taskGroup.addTask({
|
|
1681137
|
-
id: target.name,
|
|
1681138
|
-
name: target.name,
|
|
1681139
|
-
status: "skipped",
|
|
1681140
|
-
skipReason: `API '${target.api}' has errors`
|
|
1681141
|
-
});
|
|
1681142
|
-
}
|
|
1681143
|
-
for (const target of validTargets) {
|
|
1681144
|
-
taskGroup.addTask({
|
|
1681145
|
-
id: target.name,
|
|
1681146
|
-
name: target.name
|
|
1681147
|
-
});
|
|
1681148
|
-
}
|
|
1681149
|
-
await taskGroup.start({
|
|
1681150
|
-
title: "Generating SDKs",
|
|
1681151
|
-
subtitle: `org: ${workspace.sdks.org}`
|
|
1681152
|
-
});
|
|
1681153
|
-
await Promise.all(validTargets.map(async (target) => {
|
|
1681154
|
-
const apiDefinition = workspace.apis[target.api];
|
|
1681155
|
-
if (apiDefinition == null) {
|
|
1681156
|
-
const message = `API '${target.api}' not found in workspace`;
|
|
1681157
|
-
taskGroup.updateTask({
|
|
1681158
|
-
id: target.name,
|
|
1681159
|
-
update: { status: "error", error: message }
|
|
1681160
|
-
});
|
|
1681161
|
-
return;
|
|
1681162
|
-
}
|
|
1681163
|
-
const task = taskGroup.getTask(target.name);
|
|
1681164
|
-
if (task == null) {
|
|
1681165
|
-
throw new Error(`Internal error; task '${target.name}' not found`);
|
|
1681166
|
-
}
|
|
1681167
|
-
taskGroup.updateTask({
|
|
1681168
|
-
id: target.name,
|
|
1681169
|
-
update: {
|
|
1681170
|
-
status: "running",
|
|
1681171
|
-
currentStep: `${target.image}:${target.version}`
|
|
1681172
|
-
}
|
|
1681173
|
-
});
|
|
1681174
|
-
const pipelineResult = await pipeline5.run({
|
|
1681175
|
-
organization: workspace.org,
|
|
1681176
|
-
ai: workspace.ai,
|
|
1681177
|
-
task,
|
|
1681178
|
-
target,
|
|
1681179
|
-
apiDefinition,
|
|
1681180
|
-
audiences: parseAudiences2(args.audience),
|
|
1681181
|
-
runtime,
|
|
1681182
|
-
containerEngine: args["container-engine"] ?? "docker",
|
|
1681183
|
-
keepContainer: args["keep-container"] ?? false,
|
|
1681184
|
-
preview: args.preview ?? false,
|
|
1681185
|
-
outputPath: args.output != null ? resolve5(context2.cwd, args.output) : void 0,
|
|
1681186
|
-
token,
|
|
1681187
|
-
version: args.version
|
|
1681188
|
-
});
|
|
1681189
|
-
if (!pipelineResult.success) {
|
|
1681190
|
-
taskGroup.updateTask({
|
|
1681191
|
-
id: target.name,
|
|
1681192
|
-
update: {
|
|
1681193
|
-
status: "error",
|
|
1681194
|
-
error: pipelineResult.error
|
|
1681195
|
-
}
|
|
1681196
|
-
});
|
|
1681197
|
-
return;
|
|
1681198
|
-
}
|
|
1681199
|
-
taskGroup.updateTask({
|
|
1681200
|
-
id: target.name,
|
|
1681201
|
-
update: {
|
|
1681202
|
-
status: "success",
|
|
1681203
|
-
output: pipelineResult.output
|
|
1681204
|
-
}
|
|
1681205
|
-
});
|
|
1681206
|
-
}));
|
|
1681207
|
-
const summary = taskGroup.complete({
|
|
1681208
|
-
successMessage: `Successfully generated ${maybePluralSdks(validTargets)}`,
|
|
1681209
|
-
errorMessage: `Failed to generate ${maybePluralSdks(validTargets)}`
|
|
1681210
|
-
});
|
|
1681211
|
-
if (summary.failedCount > 0) {
|
|
1681212
|
-
throw CliError.exit();
|
|
1681213
|
-
}
|
|
1681214
|
-
}
|
|
1681215
|
-
function getTargets({ workspace, groupName, targetName }) {
|
|
1681216
|
-
const targets2 = workspace.sdks != null ? filterTargetsByGroup(workspace.sdks.targets, groupName) : [];
|
|
1681217
|
-
if (targetName != null) {
|
|
1681218
|
-
const filtered = targets2.filter((t2) => t2.name === targetName);
|
|
1681219
|
-
if (filtered.length === 0) {
|
|
1681220
|
-
throw new Error(`Target '${targetName}' not found`);
|
|
1681221
|
-
}
|
|
1681222
|
-
return filtered;
|
|
1681223
|
-
}
|
|
1681224
|
-
if (targets2.length === 0) {
|
|
1681225
|
-
if (groupName != null) {
|
|
1681226
|
-
throw new Error(`No targets found for group '${groupName}'`);
|
|
1681227
|
-
}
|
|
1681228
|
-
throw new Error("No targets configured in fern.yml");
|
|
1681229
|
-
}
|
|
1681230
|
-
return targets2;
|
|
1681231
|
-
}
|
|
1681232
|
-
function filterTargetsByGroup(targets2, groupName) {
|
|
1681233
|
-
if (groupName == null) {
|
|
1681234
|
-
return targets2;
|
|
1681235
|
-
}
|
|
1681236
|
-
return targets2.filter((target) => target.groups?.includes(groupName));
|
|
1681237
|
-
}
|
|
1681238
|
-
function parseAudiences2(audiences) {
|
|
1681239
|
-
if (audiences == null || audiences.length === 0) {
|
|
1681240
|
-
return void 0;
|
|
1681241
|
-
}
|
|
1681242
|
-
return {
|
|
1681243
|
-
type: "select",
|
|
1681244
|
-
audiences
|
|
1681245
|
-
};
|
|
1681246
|
-
}
|
|
1681247
|
-
function validateArgs2(args) {
|
|
1681248
|
-
if (args.output != null && !args.preview) {
|
|
1681249
|
-
throw new Error("The --output flag can only be used with --preview");
|
|
1681250
|
-
}
|
|
1681251
|
-
if (args["container-engine"] != null && !args.local) {
|
|
1681252
|
-
throw new Error("The --container-engine flag can only be used with --local");
|
|
1681253
|
-
}
|
|
1681254
|
-
if (args.group != null && args.target != null) {
|
|
1681255
|
-
throw new Error("The --group and --target flags cannot be used together");
|
|
1681256
|
-
}
|
|
1681257
|
-
if (args.group == null && args.target == null) {
|
|
1681258
|
-
throw new Error("A --target or --group must be specified");
|
|
1681259
|
-
}
|
|
1681260
|
-
}
|
|
1681261
|
-
function maybePluralSdks(targets2) {
|
|
1681262
|
-
return targets2.length === 1 ? "SDK" : "SDKs";
|
|
1681263
|
-
}
|
|
1681264
1681424
|
|
|
1681265
1681425
|
// ../cli-v2/lib/commands/sdk/command.js
|
|
1681266
1681426
|
function addSdkCommand(cli) {
|
|
@@ -1712107,7 +1712267,7 @@ var CliContext = class {
|
|
|
1712107
1712267
|
if (false) {
|
|
1712108
1712268
|
this.logger.error("CLI_VERSION is not defined");
|
|
1712109
1712269
|
}
|
|
1712110
|
-
return "3.
|
|
1712270
|
+
return "3.64.1-2-gd642956c498";
|
|
1712111
1712271
|
}
|
|
1712112
1712272
|
getCliName() {
|
|
1712113
1712273
|
if (false) {
|
|
@@ -1715221,7 +1715381,7 @@ var import_path56 = __toESM(require("path"), 1);
|
|
|
1715221
1715381
|
var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
|
|
1715222
1715382
|
var LOGS_FOLDER_NAME = "logs";
|
|
1715223
1715383
|
function getCliSource() {
|
|
1715224
|
-
const version7 = "3.
|
|
1715384
|
+
const version7 = "3.64.1-2-gd642956c498";
|
|
1715225
1715385
|
return `cli@${version7}`;
|
|
1715226
1715386
|
}
|
|
1715227
1715387
|
var DebugLogger = class {
|