@lightdash/cli 3.86.0 → 3.88.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.
Files changed (62) hide show
  1. package/README.md +18 -0
  2. package/dist/.tsbuildinfo.build +1 -1
  3. package/dist/agentConnections/agentTokenProvider.d.ts.map +1 -1
  4. package/dist/agentConnections/agentTokenProvider.js +9 -5
  5. package/dist/agentConnections/commandPolicy.d.ts.map +1 -1
  6. package/dist/agentConnections/commandPolicy.js +1 -0
  7. package/dist/agentConnections/initialToken.d.ts.map +1 -1
  8. package/dist/agentConnections/initialToken.js +2 -0
  9. package/dist/agentConnections/personalRecovery.js +1 -1
  10. package/dist/analytics/analytics.js +1 -1
  11. package/dist/config.d.ts +2 -0
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +19 -11
  14. package/dist/credentials.d.ts +5 -0
  15. package/dist/credentials.d.ts.map +1 -1
  16. package/dist/credentials.js +11 -2
  17. package/dist/handlers/apps/createApp.d.ts.map +1 -1
  18. package/dist/handlers/apps/createApp.js +1 -3
  19. package/dist/handlers/apps/preview.d.ts.map +1 -1
  20. package/dist/handlers/apps/preview.js +12 -10
  21. package/dist/handlers/apps/previewProxy.d.ts +1 -0
  22. package/dist/handlers/apps/previewProxy.d.ts.map +1 -1
  23. package/dist/handlers/apps/previewProxy.js +70 -44
  24. package/dist/handlers/dbt/apiClient.d.ts.map +1 -1
  25. package/dist/handlers/dbt/apiClient.js +20 -12
  26. package/dist/handlers/diagnostics.d.ts.map +1 -1
  27. package/dist/handlers/diagnostics.js +2 -1
  28. package/dist/handlers/download.d.ts.map +1 -1
  29. package/dist/handlers/download.js +4 -9
  30. package/dist/handlers/login/pat.d.ts.map +1 -1
  31. package/dist/handlers/login/pat.js +2 -0
  32. package/dist/handlers/login.d.ts.map +1 -1
  33. package/dist/handlers/login.js +8 -2
  34. package/dist/handlers/logout.d.ts +3 -0
  35. package/dist/handlers/logout.d.ts.map +1 -0
  36. package/dist/handlers/logout.js +67 -0
  37. package/dist/handlers/oauthLogin.d.ts +1 -1
  38. package/dist/handlers/oauthLogin.d.ts.map +1 -1
  39. package/dist/handlers/oauthLogin.js +64 -31
  40. package/dist/handlers/renameHandler.d.ts.map +1 -1
  41. package/dist/handlers/renameHandler.js +3 -3
  42. package/dist/handlers/slugUpdate.d.ts.map +1 -1
  43. package/dist/handlers/slugUpdate.js +3 -3
  44. package/dist/handlers/utils.d.ts.map +1 -1
  45. package/dist/handlers/utils.js +1 -0
  46. package/dist/index.js +6 -0
  47. package/dist/personalLogin/fixtures.d.ts +3 -0
  48. package/dist/personalLogin/fixtures.d.ts.map +1 -0
  49. package/dist/personalLogin/fixtures.js +20 -0
  50. package/dist/personalLogin/instanceKey.d.ts +2 -0
  51. package/dist/personalLogin/instanceKey.d.ts.map +1 -0
  52. package/dist/personalLogin/instanceKey.js +23 -0
  53. package/dist/personalLogin/schema.d.ts +28 -0
  54. package/dist/personalLogin/schema.d.ts.map +1 -0
  55. package/dist/personalLogin/schema.js +69 -0
  56. package/dist/personalLogin/store.d.ts +24 -0
  57. package/dist/personalLogin/store.d.ts.map +1 -0
  58. package/dist/personalLogin/store.js +124 -0
  59. package/dist/personalLogin/tokenProvider.d.ts +31 -0
  60. package/dist/personalLogin/tokenProvider.d.ts.map +1 -0
  61. package/dist/personalLogin/tokenProvider.js +180 -0
  62. package/package.json +3 -3
@@ -0,0 +1,24 @@
1
+ import { type PersonalLogin } from './schema';
2
+ export type RefreshJournal = {
3
+ attemptUuid: string;
4
+ generation: number;
5
+ };
6
+ export type LockedPersonalLoginStore = {
7
+ read: (instanceUrl: string) => Promise<PersonalLogin | null>;
8
+ save: (instanceUrl: string, login: PersonalLogin) => Promise<void>;
9
+ remove: (instanceUrl: string) => Promise<void>;
10
+ readJournal: (instanceUrl: string) => Promise<RefreshJournal | null>;
11
+ writeJournal: (instanceUrl: string, journal: RefreshJournal) => Promise<void>;
12
+ clearJournal: (instanceUrl: string) => Promise<void>;
13
+ };
14
+ export declare class PersonalLoginStore {
15
+ readonly filePath: string;
16
+ constructor(filePath?: string);
17
+ private readRoot;
18
+ read(instanceUrl: string): Promise<PersonalLogin | null>;
19
+ private journalPath;
20
+ withLock<T>(callback: (locked: LockedPersonalLoginStore) => Promise<T>): Promise<T>;
21
+ save(instanceUrl: string, login: PersonalLogin): Promise<void>;
22
+ remove(instanceUrl: string): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/personalLogin/store.ts"],"names":[],"mappings":"AAaA,OAAO,EAGH,KAAK,aAAa,EACrB,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,cAAc,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AACzE,MAAM,MAAM,wBAAwB,GAAG;IACnC,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC7D,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACrE,YAAY,EAAE,CACV,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,cAAc,KACtB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD,CAAC;AACF,qBAAa,kBAAkB;aAEP,QAAQ,EAAE,MAAM;IADpC,YACoB,QAAQ,GAAE,MAGzB,EACD;YAEU,QAAQ;IA8BhB,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAK7D;IAED,OAAO,CAAC,WAAW;IAOb,QAAQ,CAAC,CAAC,EACZ,QAAQ,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3D,OAAO,CAAC,CAAC,CAAC,CAmEZ;IAEK,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnE;IAEK,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/C;CACJ"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PersonalLoginStore = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const crypto_1 = require("crypto");
6
+ const fs_1 = require("fs");
7
+ const yaml = tslib_1.__importStar(require("js-yaml"));
8
+ const path_1 = tslib_1.__importDefault(require("path"));
9
+ const configLock_1 = require("../agentConnections/configLock");
10
+ const config_1 = require("../config");
11
+ const instanceKey_1 = require("./instanceKey");
12
+ const schema_1 = require("./schema");
13
+ class PersonalLoginStore {
14
+ filePath;
15
+ constructor(filePath = path_1.default.join(path_1.default.dirname(config_1.configFilePath), 'personal-logins.yaml')) {
16
+ this.filePath = filePath;
17
+ }
18
+ async readRoot() {
19
+ const contents = await (0, configLock_1.readPrivateFile)(this.filePath);
20
+ if (contents === null)
21
+ return new Map();
22
+ try {
23
+ const root = yaml.load(contents);
24
+ if (typeof root !== 'object' ||
25
+ root === null ||
26
+ !('version' in root) ||
27
+ root.version !== 1 ||
28
+ !('instances' in root) ||
29
+ typeof root.instances !== 'object' ||
30
+ root.instances === null ||
31
+ Array.isArray(root.instances) ||
32
+ Object.keys(root).some((key) => !['version', 'instances'].includes(key)))
33
+ throw (0, schema_1.invalidLogin)();
34
+ return new Map(Object.entries(root.instances).map(([url, login]) => {
35
+ if ((0, instanceKey_1.personalInstanceKey)(url) !== url)
36
+ throw (0, schema_1.invalidLogin)();
37
+ return [url, (0, schema_1.validatePersonalLogin)(login)];
38
+ }));
39
+ }
40
+ catch {
41
+ throw (0, schema_1.invalidLogin)();
42
+ }
43
+ }
44
+ async read(instanceUrl) {
45
+ return ((await this.readRoot()).get((0, instanceKey_1.personalInstanceKey)(instanceUrl)) ??
46
+ null);
47
+ }
48
+ journalPath(instanceUrl) {
49
+ const hash = (0, crypto_1.createHash)('sha256')
50
+ .update((0, instanceKey_1.personalInstanceKey)(instanceUrl))
51
+ .digest('hex');
52
+ return `${this.filePath}.${hash}.journal`;
53
+ }
54
+ async withLock(callback) {
55
+ await (0, configLock_1.privateDirectory)(path_1.default.dirname(this.filePath));
56
+ const release = await (0, configLock_1.acquireLock)(`${this.filePath}.lock`);
57
+ const writeRoot = async (root) => (0, configLock_1.atomicWrite)(this.filePath, yaml.dump({ version: 1, instances: Object.fromEntries(root) }));
58
+ try {
59
+ return await callback({
60
+ read: (url) => this.read(url),
61
+ save: async (url, login) => {
62
+ const root = await this.readRoot();
63
+ root.set((0, instanceKey_1.personalInstanceKey)(url), (0, schema_1.validatePersonalLogin)(login));
64
+ await writeRoot(root);
65
+ },
66
+ remove: async (url) => {
67
+ const root = await this.readRoot();
68
+ if (root.delete((0, instanceKey_1.personalInstanceKey)(url)))
69
+ await writeRoot(root);
70
+ },
71
+ readJournal: async (url) => {
72
+ const contents = await (0, configLock_1.readPrivateFile)(this.journalPath(url));
73
+ if (contents === null)
74
+ return null;
75
+ try {
76
+ const journal = JSON.parse(contents);
77
+ if (typeof journal !== 'object' ||
78
+ journal === null ||
79
+ !('attemptUuid' in journal) ||
80
+ typeof journal.attemptUuid !== 'string' ||
81
+ !/^[a-f0-9-]{36}$/i.test(journal.attemptUuid) ||
82
+ !('generation' in journal) ||
83
+ typeof journal.generation !== 'number' ||
84
+ !Number.isSafeInteger(journal.generation) ||
85
+ journal.generation < 1)
86
+ throw (0, schema_1.invalidLogin)();
87
+ return {
88
+ attemptUuid: journal.attemptUuid,
89
+ generation: journal.generation,
90
+ };
91
+ }
92
+ catch {
93
+ throw (0, schema_1.invalidLogin)();
94
+ }
95
+ },
96
+ writeJournal: (url, journal) => (0, configLock_1.atomicWrite)(this.journalPath(url), JSON.stringify(journal)),
97
+ clearJournal: async (url) => {
98
+ await fs_1.promises
99
+ .unlink(this.journalPath(url))
100
+ .catch((error) => {
101
+ if (!(0, configLock_1.isFsError)(error, 'ENOENT'))
102
+ throw new Error('Cannot clear the personal login refresh journal.');
103
+ });
104
+ },
105
+ });
106
+ }
107
+ finally {
108
+ await release();
109
+ }
110
+ }
111
+ async save(instanceUrl, login) {
112
+ await this.withLock(async (locked) => {
113
+ await locked.save(instanceUrl, login);
114
+ await locked.clearJournal(instanceUrl);
115
+ });
116
+ }
117
+ async remove(instanceUrl) {
118
+ await this.withLock(async (locked) => {
119
+ await locked.remove(instanceUrl);
120
+ await locked.clearJournal(instanceUrl);
121
+ });
122
+ }
123
+ }
124
+ exports.PersonalLoginStore = PersonalLoginStore;
@@ -0,0 +1,31 @@
1
+ import { type PersonalLogin } from './schema';
2
+ import { PersonalLoginStore } from './store';
3
+ export declare const freshLoginRequired = "Your CLI login needs a fresh `lightdash login`: the last token refresh did not complete.";
4
+ export declare const sessionExpired = "Your CLI session expired. Run `lightdash login` again.";
5
+ export declare const oauthHeaders: () => {
6
+ 'Content-Type': string;
7
+ 'User-Agent': string;
8
+ 'Proxy-Authorization'?: string | undefined;
9
+ };
10
+ type TokenResponse = {
11
+ access_token: string;
12
+ refresh_token: string;
13
+ token_type: string;
14
+ expires_in: number;
15
+ scope: string;
16
+ session_expires_in?: number;
17
+ };
18
+ export declare const parseTokenResponse: (value: unknown) => TokenResponse;
19
+ export declare const tokenExpiry: (response: TokenResponse, startedAt: number, dateHeader: string | null, deadline: number | null) => {
20
+ accessTokenIssuedAt: string;
21
+ accessTokenExpiresAt: string;
22
+ sessionExpiresAt: string;
23
+ };
24
+ export declare class PersonalLoginTokenProvider {
25
+ private readonly store;
26
+ constructor(store?: PersonalLoginStore);
27
+ getToken(instanceUrl: string, rejectedGeneration?: number | null): Promise<PersonalLogin>;
28
+ private markLoginRequired;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=tokenProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenProvider.d.ts","sourceRoot":"","sources":["../../src/personalLogin/tokenProvider.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAiC,MAAM,SAAS,CAAC;AAE5E,eAAO,MAAM,kBAAkB,6FAC+D,CAAC;AAC/F,eAAO,MAAM,cAAc,2DACiC,CAAC;AAC7D,eAAO,MAAM,YAAY;;;;CAMvB,CAAC;AACH,KAAK,aAAa,GAAG;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAoBF,eAAO,MAAM,kBAAkB,UAAW,OAAO,KAAG,aAWnD,CAAC;AACF,eAAO,MAAM,WAAW,aACV,aAAa,aACZ,MAAM,cACL,MAAM,GAAG,IAAI,YACf,MAAM,GAAG,IAAI;IAkBnB,mBAAmB;IACnB,oBAAoB;IACpB,gBAAgB;CAEvB,CAAC;AAEF,qBAAa,0BAA0B;IAE/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAD1B,YACqB,KAAK,GAAE,kBAA6C,EACrE;IAEE,QAAQ,CACV,WAAW,EAAE,MAAM,EACnB,kBAAkB,GAAE,MAAM,GAAG,IAAW,GACzC,OAAO,CAAC,aAAa,CAAC,CAuGxB;YAEa,iBAAiB;CAalC"}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PersonalLoginTokenProvider = exports.tokenExpiry = exports.parseTokenResponse = exports.oauthHeaders = exports.sessionExpired = exports.freshLoginRequired = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@lightdash/common");
6
+ const ajv_1 = tslib_1.__importDefault(require("ajv"));
7
+ const crypto_1 = require("crypto");
8
+ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
9
+ const env_1 = require("../env");
10
+ const instanceKey_1 = require("./instanceKey");
11
+ const store_1 = require("./store");
12
+ exports.freshLoginRequired = 'Your CLI login needs a fresh `lightdash login`: the last token refresh did not complete.';
13
+ exports.sessionExpired = 'Your CLI session expired. Run `lightdash login` again.';
14
+ const oauthHeaders = () => ({
15
+ 'Content-Type': 'application/x-www-form-urlencoded',
16
+ 'User-Agent': `lightdash-cli/${env_1.CLI_VERSION}`,
17
+ ...(process.env.LIGHTDASH_PROXY_AUTHORIZATION
18
+ ? { 'Proxy-Authorization': process.env.LIGHTDASH_PROXY_AUTHORIZATION }
19
+ : {}),
20
+ });
21
+ exports.oauthHeaders = oauthHeaders;
22
+ const seconds = { type: 'integer', minimum: 1, maximum: 2_147_483_647 };
23
+ const validateResponse = new ajv_1.default().compile({
24
+ type: 'object',
25
+ required: [
26
+ 'access_token',
27
+ 'refresh_token',
28
+ 'token_type',
29
+ 'expires_in',
30
+ 'scope',
31
+ ],
32
+ properties: {
33
+ access_token: { type: 'string', minLength: 1, maxLength: 16384 },
34
+ refresh_token: { type: 'string', minLength: 1, maxLength: 16384 },
35
+ token_type: { type: 'string', pattern: '^[Bb][Ee][Aa][Rr][Ee][Rr]$' },
36
+ expires_in: seconds,
37
+ session_expires_in: seconds,
38
+ scope: { type: 'string', maxLength: 16384 },
39
+ },
40
+ });
41
+ const parseTokenResponse = (value) => {
42
+ if (!validateResponse(value))
43
+ throw new Error(exports.freshLoginRequired);
44
+ const scopes = value.scope.split(' ');
45
+ if (scopes.length !== 2 ||
46
+ new Set(scopes).size !== 2 ||
47
+ !scopes.includes('read') ||
48
+ !scopes.includes('write'))
49
+ throw new Error(exports.freshLoginRequired);
50
+ return value;
51
+ };
52
+ exports.parseTokenResponse = parseTokenResponse;
53
+ const tokenExpiry = (response, startedAt, dateHeader, deadline) => {
54
+ const serverTime = dateHeader === null ? startedAt : Date.parse(dateHeader);
55
+ if (!Number.isFinite(serverTime))
56
+ throw new Error(exports.freshLoginRequired);
57
+ const issuedAt = Math.min(startedAt, serverTime);
58
+ const sessionExpiresAt = Math.min(deadline ?? Infinity, response.session_expires_in === undefined && deadline !== null
59
+ ? deadline
60
+ : issuedAt + (response.session_expires_in ?? 8 * 3600) * 1000);
61
+ const accessTokenExpiresAt = Math.min(issuedAt + response.expires_in * 1000, sessionExpiresAt);
62
+ if (Math.min(sessionExpiresAt, accessTokenExpiresAt) <= Date.now())
63
+ throw new Error(exports.sessionExpired);
64
+ return {
65
+ accessTokenIssuedAt: new Date(issuedAt).toISOString(),
66
+ accessTokenExpiresAt: new Date(accessTokenExpiresAt).toISOString(),
67
+ sessionExpiresAt: new Date(sessionExpiresAt).toISOString(),
68
+ };
69
+ };
70
+ exports.tokenExpiry = tokenExpiry;
71
+ class PersonalLoginTokenProvider {
72
+ store;
73
+ constructor(store = new store_1.PersonalLoginStore()) {
74
+ this.store = store;
75
+ }
76
+ async getToken(instanceUrl, rejectedGeneration = null) {
77
+ const instance = (0, instanceKey_1.personalInstanceKey)(instanceUrl);
78
+ return this.store.withLock(async (locked) => {
79
+ let login = await locked.read(instance);
80
+ if (login === null)
81
+ throw new common_1.AuthorizationError("Not logged in. Run 'lightdash login --help'");
82
+ const requireLogin = async (current) => {
83
+ await this.markLoginRequired(locked, instance, current);
84
+ throw new Error(exports.freshLoginRequired);
85
+ };
86
+ let journal;
87
+ try {
88
+ journal = await locked.readJournal(instance);
89
+ }
90
+ catch {
91
+ return requireLogin(login);
92
+ }
93
+ if (journal !== null) {
94
+ if (login.refreshState.kind === 'idle' &&
95
+ journal.attemptUuid ===
96
+ login.tokens.lastRefreshAttemptUuid &&
97
+ journal.generation + 1 === login.tokens.generation)
98
+ await locked.clearJournal(instance);
99
+ else
100
+ return requireLogin(login);
101
+ }
102
+ if (login.refreshState.kind !== 'idle')
103
+ return requireLogin(login);
104
+ if (Date.parse(login.sessionExpiresAt) <= Date.now())
105
+ throw new Error(exports.sessionExpired);
106
+ const remaining = Date.parse(login.tokens.accessTokenExpiresAt) - Date.now();
107
+ const lifetime = Date.parse(login.tokens.accessTokenExpiresAt) -
108
+ Date.parse(login.tokens.accessTokenIssuedAt);
109
+ if (remaining > Math.min(60_000, lifetime / 10) &&
110
+ rejectedGeneration !== login.tokens.generation)
111
+ return login;
112
+ const attemptUuid = (0, crypto_1.randomUUID)();
113
+ const startedAt = Date.now();
114
+ const pending = {
115
+ ...login,
116
+ refreshState: {
117
+ kind: 'in_progress',
118
+ attemptUuid,
119
+ startedAt: new Date(startedAt).toISOString(),
120
+ },
121
+ };
122
+ await locked.writeJournal(instance, {
123
+ attemptUuid,
124
+ generation: login.tokens.generation,
125
+ });
126
+ await locked.save(instance, pending);
127
+ try {
128
+ const response = await (0, node_fetch_1.default)(`${instance}/api/v1/oauth/token`, {
129
+ method: 'POST',
130
+ headers: (0, exports.oauthHeaders)(),
131
+ redirect: 'error',
132
+ signal: AbortSignal.timeout(15_000),
133
+ body: new URLSearchParams({
134
+ grant_type: 'refresh_token',
135
+ client_id: 'lightdash-cli',
136
+ refresh_token: login.tokens.refreshToken,
137
+ scope: login.tokens.scopes.join(' '),
138
+ }),
139
+ });
140
+ if (!response.ok)
141
+ throw new Error(exports.freshLoginRequired);
142
+ const value = await response.json();
143
+ const token = (0, exports.parseTokenResponse)(value);
144
+ if (token.refresh_token === login.tokens.refreshToken)
145
+ throw new Error(exports.freshLoginRequired);
146
+ const expiry = (0, exports.tokenExpiry)(token, startedAt, response.headers.get('date'), Date.parse(login.sessionExpiresAt));
147
+ login = {
148
+ ...login,
149
+ tokens: {
150
+ accessToken: token.access_token,
151
+ refreshToken: token.refresh_token,
152
+ accessTokenIssuedAt: expiry.accessTokenIssuedAt,
153
+ accessTokenExpiresAt: expiry.accessTokenExpiresAt,
154
+ scopes: token.scope.split(' '),
155
+ generation: login.tokens.generation + 1,
156
+ lastRefreshAttemptUuid: attemptUuid,
157
+ },
158
+ sessionExpiresAt: expiry.sessionExpiresAt,
159
+ refreshState: { kind: 'idle' },
160
+ };
161
+ await locked.save(instance, login);
162
+ }
163
+ catch {
164
+ return requireLogin(pending);
165
+ }
166
+ await locked.clearJournal(instance);
167
+ return login;
168
+ });
169
+ }
170
+ async markLoginRequired(locked, instance, login) {
171
+ await locked.save(instance, {
172
+ ...login,
173
+ refreshState: {
174
+ kind: 'login_required',
175
+ since: new Date().toISOString(),
176
+ },
177
+ });
178
+ }
179
+ }
180
+ exports.PersonalLoginTokenProvider = PersonalLoginTokenProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "3.86.0",
3
+ "version": "3.88.0",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -22,8 +22,8 @@
22
22
  "@actions/core": "1.11.1",
23
23
  "@aws-sdk/credential-providers": "3.995.0",
24
24
  "@casl/ability": "6.8.0",
25
- "@lightdash/common": "3.86.0",
26
- "@lightdash/warehouses": "3.86.0",
25
+ "@lightdash/common": "3.88.0",
26
+ "@lightdash/warehouses": "3.88.0",
27
27
  "@sidvind/better-ajv-errors": "7.0.0",
28
28
  "@types/columnify": "1.5.1",
29
29
  "ajv": "8.18.0",