@sanity/cli 6.1.3 → 6.1.4
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 +79 -79
- package/dist/actions/auth/ensureAuthenticated.js +61 -0
- package/dist/actions/auth/ensureAuthenticated.js.map +1 -0
- package/dist/commands/init.js +28 -36
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp/configure.js +40 -12
- package/dist/commands/mcp/configure.js.map +1 -1
- package/dist/errors/LoginError.js +11 -0
- package/dist/errors/LoginError.js.map +1 -0
- package/dist/util/getErrorMessage.js +9 -0
- package/dist/util/getErrorMessage.js.map +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { getCliToken } from '@sanity/cli-core';
|
|
2
|
+
import { isHttpError } from '@sanity/client';
|
|
3
|
+
import { LoginError } from '../../errors/LoginError.js';
|
|
4
|
+
import { getCliUser } from '../../services/user.js';
|
|
5
|
+
import { getErrorMessage } from '../../util/getErrorMessage.js';
|
|
6
|
+
import { login } from './login/login.js';
|
|
7
|
+
/**
|
|
8
|
+
* Ensure the user is authenticated. Validates the current token via /users/me
|
|
9
|
+
* and triggers interactive login if the token is missing or invalid.
|
|
10
|
+
*
|
|
11
|
+
* @returns The authenticated user.
|
|
12
|
+
* @throws LoginError if interactive login fails or is cancelled.
|
|
13
|
+
* @throws Error if a network/server error occurs during validation.
|
|
14
|
+
* @internal
|
|
15
|
+
*/ export async function ensureAuthenticated(options) {
|
|
16
|
+
const user = await validateSession();
|
|
17
|
+
if (user) return user;
|
|
18
|
+
try {
|
|
19
|
+
await login({
|
|
20
|
+
output: options.output,
|
|
21
|
+
telemetry: options.telemetry
|
|
22
|
+
});
|
|
23
|
+
} catch (cause) {
|
|
24
|
+
throw new LoginError(getErrorMessage(cause), {
|
|
25
|
+
cause
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
return await getCliUser();
|
|
30
|
+
} catch (cause) {
|
|
31
|
+
if (isHttpError(cause) && (cause.statusCode === 401 || cause.statusCode === 403)) {
|
|
32
|
+
throw new LoginError(`Login succeeded but failed to verify session: ${getErrorMessage(cause)}`, {
|
|
33
|
+
cause
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
throw cause;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Validate the current CLI auth token by calling /users/me.
|
|
41
|
+
*
|
|
42
|
+
* Returns null only for auth failures (401/403). Re-throws network errors,
|
|
43
|
+
* timeouts, and server errors so callers can handle them appropriately
|
|
44
|
+
* instead of triggering an unnecessary re-login prompt.
|
|
45
|
+
*
|
|
46
|
+
* @returns The authenticated user if valid, null if invalid/missing.
|
|
47
|
+
* @internal
|
|
48
|
+
*/ export async function validateSession() {
|
|
49
|
+
const token = await getCliToken();
|
|
50
|
+
if (!token) return null;
|
|
51
|
+
try {
|
|
52
|
+
return await getCliUser();
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (isHttpError(error) && (error.statusCode === 401 || error.statusCode === 403)) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=ensureAuthenticated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/auth/ensureAuthenticated.ts"],"sourcesContent":["import {\n type CLITelemetryStore,\n getCliToken,\n type Output,\n type SanityOrgUser,\n} from '@sanity/cli-core'\nimport {isHttpError} from '@sanity/client'\n\nimport {LoginError} from '../../errors/LoginError.js'\nimport {getCliUser} from '../../services/user.js'\nimport {getErrorMessage} from '../../util/getErrorMessage.js'\nimport {login} from './login/login.js'\n\n/**\n * Ensure the user is authenticated. Validates the current token via /users/me\n * and triggers interactive login if the token is missing or invalid.\n *\n * @returns The authenticated user.\n * @throws LoginError if interactive login fails or is cancelled.\n * @throws Error if a network/server error occurs during validation.\n * @internal\n */\nexport async function ensureAuthenticated(options: {\n output: Output\n telemetry: CLITelemetryStore\n}): Promise<SanityOrgUser> {\n const user = await validateSession()\n if (user) return user\n\n try {\n await login({output: options.output, telemetry: options.telemetry})\n } catch (cause) {\n throw new LoginError(getErrorMessage(cause), {cause})\n }\n\n try {\n return await getCliUser()\n } catch (cause) {\n if (isHttpError(cause) && (cause.statusCode === 401 || cause.statusCode === 403)) {\n throw new LoginError(\n `Login succeeded but failed to verify session: ${getErrorMessage(cause)}`,\n {cause},\n )\n }\n throw cause\n }\n}\n\n/**\n * Validate the current CLI auth token by calling /users/me.\n *\n * Returns null only for auth failures (401/403). Re-throws network errors,\n * timeouts, and server errors so callers can handle them appropriately\n * instead of triggering an unnecessary re-login prompt.\n *\n * @returns The authenticated user if valid, null if invalid/missing.\n * @internal\n */\nexport async function validateSession(): Promise<SanityOrgUser | null> {\n const token = await getCliToken()\n if (!token) return null\n\n try {\n return await getCliUser()\n } catch (error) {\n if (isHttpError(error) && (error.statusCode === 401 || error.statusCode === 403)) {\n return null\n }\n throw error\n }\n}\n"],"names":["getCliToken","isHttpError","LoginError","getCliUser","getErrorMessage","login","ensureAuthenticated","options","user","validateSession","output","telemetry","cause","statusCode","token","error"],"mappings":"AAAA,SAEEA,WAAW,QAGN,mBAAkB;AACzB,SAAQC,WAAW,QAAO,iBAAgB;AAE1C,SAAQC,UAAU,QAAO,6BAA4B;AACrD,SAAQC,UAAU,QAAO,yBAAwB;AACjD,SAAQC,eAAe,QAAO,gCAA+B;AAC7D,SAAQC,KAAK,QAAO,mBAAkB;AAEtC;;;;;;;;CAQC,GACD,OAAO,eAAeC,oBAAoBC,OAGzC;IACC,MAAMC,OAAO,MAAMC;IACnB,IAAID,MAAM,OAAOA;IAEjB,IAAI;QACF,MAAMH,MAAM;YAACK,QAAQH,QAAQG,MAAM;YAAEC,WAAWJ,QAAQI,SAAS;QAAA;IACnE,EAAE,OAAOC,OAAO;QACd,MAAM,IAAIV,WAAWE,gBAAgBQ,QAAQ;YAACA;QAAK;IACrD;IAEA,IAAI;QACF,OAAO,MAAMT;IACf,EAAE,OAAOS,OAAO;QACd,IAAIX,YAAYW,UAAWA,CAAAA,MAAMC,UAAU,KAAK,OAAOD,MAAMC,UAAU,KAAK,GAAE,GAAI;YAChF,MAAM,IAAIX,WACR,CAAC,8CAA8C,EAAEE,gBAAgBQ,QAAQ,EACzE;gBAACA;YAAK;QAEV;QACA,MAAMA;IACR;AACF;AAEA;;;;;;;;;CASC,GACD,OAAO,eAAeH;IACpB,MAAMK,QAAQ,MAAMd;IACpB,IAAI,CAACc,OAAO,OAAO;IAEnB,IAAI;QACF,OAAO,MAAMX;IACf,EAAE,OAAOY,OAAO;QACd,IAAId,YAAYc,UAAWA,CAAAA,MAAMF,UAAU,KAAK,OAAOE,MAAMF,UAAU,KAAK,GAAE,GAAI;YAChF,OAAO;QACT;QACA,MAAME;IACR;AACF"}
|
package/dist/commands/init.js
CHANGED
|
@@ -10,6 +10,7 @@ import { isHttpError } from '@sanity/client';
|
|
|
10
10
|
import { frameworks } from '@vercel/frameworks';
|
|
11
11
|
import { execa } from 'execa';
|
|
12
12
|
import deburr from 'lodash-es/deburr.js';
|
|
13
|
+
import { validateSession } from '../actions/auth/ensureAuthenticated.js';
|
|
13
14
|
import { getProviderName } from '../actions/auth/getProviderName.js';
|
|
14
15
|
import { login } from '../actions/auth/login/login.js';
|
|
15
16
|
import { createDataset } from '../actions/dataset/create.js';
|
|
@@ -681,49 +682,40 @@ export class InitCommand extends SanityCommand {
|
|
|
681
682
|
}
|
|
682
683
|
// @todo do we actually need to be authenticated for init? check flags and determine.
|
|
683
684
|
async ensureAuthenticated() {
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
let user;
|
|
687
|
-
if (isAuthenticated) {
|
|
688
|
-
// It _appears_ we are authenticated, but the token might be invalid/expired,
|
|
689
|
-
// so we need to verify that we can actually make an authenticated request.
|
|
690
|
-
try {
|
|
691
|
-
user = await getCliUser();
|
|
692
|
-
} catch {
|
|
693
|
-
// assume that any error means that the token is invalid
|
|
694
|
-
isAuthenticated = false;
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
if (isAuthenticated) {
|
|
685
|
+
const user = await validateSession();
|
|
686
|
+
if (user) {
|
|
698
687
|
this._trace.log({
|
|
699
688
|
alreadyLoggedIn: true,
|
|
700
689
|
step: 'login'
|
|
701
690
|
});
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
this.
|
|
709
|
-
|
|
691
|
+
this.log(`${logSymbols.success} You are logged in as ${user.email} using ${getProviderName(user.provider)}`);
|
|
692
|
+
return {
|
|
693
|
+
user
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
if (this.isUnattended()) {
|
|
697
|
+
this.error('Must be logged in to run this command in unattended mode, run `sanity login`', {
|
|
698
|
+
exit: 1
|
|
710
699
|
});
|
|
711
|
-
try {
|
|
712
|
-
await login({
|
|
713
|
-
output: this.output,
|
|
714
|
-
telemetry: this._trace.newContext('login')
|
|
715
|
-
});
|
|
716
|
-
} catch (error) {
|
|
717
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
718
|
-
this.error(`Login failed: ${message}`, {
|
|
719
|
-
exit: 1
|
|
720
|
-
});
|
|
721
|
-
}
|
|
722
700
|
}
|
|
723
|
-
|
|
724
|
-
|
|
701
|
+
this._trace.log({
|
|
702
|
+
step: 'login'
|
|
703
|
+
});
|
|
704
|
+
try {
|
|
705
|
+
await login({
|
|
706
|
+
output: this.output,
|
|
707
|
+
telemetry: this._trace.newContext('login')
|
|
708
|
+
});
|
|
709
|
+
} catch (error) {
|
|
710
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
711
|
+
this.error(`Login failed: ${message}`, {
|
|
712
|
+
exit: 1
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
const loggedInUser = await getCliUser();
|
|
716
|
+
this.log(`${logSymbols.success} You are logged in as ${loggedInUser.email} using ${getProviderName(loggedInUser.provider)}`);
|
|
725
717
|
return {
|
|
726
|
-
user
|
|
718
|
+
user: loggedInUser
|
|
727
719
|
};
|
|
728
720
|
}
|
|
729
721
|
flagOrDefault(flag, defaultValue) {
|