@levr-one/auth 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/config-watcher.d.ts +65 -0
- package/dist/config-watcher.d.ts.map +1 -0
- package/dist/config-watcher.js +140 -0
- package/dist/config-watcher.js.map +1 -0
- package/dist/config-watcher.test.d.ts +2 -0
- package/dist/config-watcher.test.d.ts.map +1 -0
- package/dist/config-watcher.test.js +116 -0
- package/dist/config-watcher.test.js.map +1 -0
- package/dist/config.d.ts +58 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +234 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +221 -0
- package/dist/config.test.js.map +1 -0
- package/dist/file-lock.d.ts +41 -0
- package/dist/file-lock.d.ts.map +1 -0
- package/dist/file-lock.js +110 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth-client.d.ts +156 -0
- package/dist/oauth-client.d.ts.map +1 -0
- package/dist/oauth-client.js +572 -0
- package/dist/oauth-client.js.map +1 -0
- package/dist/oauth-client.test.d.ts +2 -0
- package/dist/oauth-client.test.d.ts.map +1 -0
- package/dist/oauth-client.test.js +290 -0
- package/dist/oauth-client.test.js.map +1 -0
- package/dist/test-utils.d.ts +10 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +45 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/token-store.d.ts +78 -0
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +299 -0
- package/dist/token-store.js.map +1 -0
- package/dist/token-store.test.d.ts +2 -0
- package/dist/token-store.test.d.ts.map +1 -0
- package/dist/token-store.test.js +239 -0
- package/dist/token-store.test.js.map +1 -0
- package/dist/token-watcher.d.ts +82 -0
- package/dist/token-watcher.d.ts.map +1 -0
- package/dist/token-watcher.js +185 -0
- package/dist/token-watcher.js.map +1 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/workspace-store.d.ts +60 -0
- package/dist/workspace-store.d.ts.map +1 -0
- package/dist/workspace-store.js +147 -0
- package/dist/workspace-store.js.map +1 -0
- package/dist/workspace-store.test.d.ts +2 -0
- package/dist/workspace-store.test.d.ts.map +1 -0
- package/dist/workspace-store.test.js +169 -0
- package/dist/workspace-store.test.js.map +1 -0
- package/dist/workspaces.d.ts +60 -0
- package/dist/workspaces.d.ts.map +1 -0
- package/dist/workspaces.js +80 -0
- package/dist/workspaces.js.map +1 -0
- package/dist/workspaces.test.d.ts +2 -0
- package/dist/workspaces.test.d.ts.map +1 -0
- package/dist/workspaces.test.js +111 -0
- package/dist/workspaces.test.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
// Mock token-store so OAuthClient constructor doesn't hit disk
|
|
3
|
+
vi.mock('./token-store.js', () => ({
|
|
4
|
+
loadTokens: () => null,
|
|
5
|
+
saveTokens: vi.fn(),
|
|
6
|
+
clearTokens: vi.fn(),
|
|
7
|
+
restoreTokensFromBackup: () => false,
|
|
8
|
+
getTqDir: () => '/tmp/.tq',
|
|
9
|
+
}));
|
|
10
|
+
// Mock workspace-store so setTokens() can exercise saveWorkspace() without disk
|
|
11
|
+
vi.mock('./workspace-store.js', () => ({
|
|
12
|
+
saveWorkspace: vi.fn(),
|
|
13
|
+
loadWorkspace: () => null,
|
|
14
|
+
clearWorkspace: vi.fn(),
|
|
15
|
+
getWorkspaceFilePath: () => '/tmp/.tq/workspace.json',
|
|
16
|
+
}));
|
|
17
|
+
// Mock config so loadConfig() returns a deterministic value
|
|
18
|
+
vi.mock('./config.js', () => ({
|
|
19
|
+
loadConfig: () => ({
|
|
20
|
+
environment: 'staging',
|
|
21
|
+
apiUrl: 'https://api.test.com',
|
|
22
|
+
authUrl: 'https://api.test.com',
|
|
23
|
+
clientUrl: 'https://app.test.com',
|
|
24
|
+
oauthClientId: '2',
|
|
25
|
+
}),
|
|
26
|
+
}));
|
|
27
|
+
import { OAuthClient } from './oauth-client.js';
|
|
28
|
+
import { saveTokens } from './token-store.js';
|
|
29
|
+
import { saveWorkspace } from './workspace-store.js';
|
|
30
|
+
const mockFetch = vi.fn();
|
|
31
|
+
vi.stubGlobal('fetch', mockFetch);
|
|
32
|
+
const deviceResponse = {
|
|
33
|
+
device_code: 'dev-code-123',
|
|
34
|
+
user_code: 'ABCD-1234',
|
|
35
|
+
verification_uri: 'https://api.test.com/v1/oauth/device',
|
|
36
|
+
verification_uri_complete: 'https://api.test.com/v1/oauth/device?user_code=ABCD-1234',
|
|
37
|
+
expires_in: 300,
|
|
38
|
+
interval: 1,
|
|
39
|
+
};
|
|
40
|
+
const tokenResponse = {
|
|
41
|
+
access_token: 'access-123',
|
|
42
|
+
token_type: 'bearer',
|
|
43
|
+
expires_in: 86400,
|
|
44
|
+
refresh_token: 'refresh-456',
|
|
45
|
+
scope: 'read:own write:own',
|
|
46
|
+
};
|
|
47
|
+
describe('OAuthClient.authorizeDevice', () => {
|
|
48
|
+
let client;
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
vi.useFakeTimers();
|
|
51
|
+
client = new OAuthClient({
|
|
52
|
+
clientId: '2',
|
|
53
|
+
authServerUrl: 'https://api.test.com',
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
mockFetch.mockReset();
|
|
58
|
+
vi.useRealTimers();
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* Helper: start authorizeDevice(), advance fake timers until it resolves.
|
|
62
|
+
* Each tick advances past the polling interval so setTimeout unblocks.
|
|
63
|
+
*/
|
|
64
|
+
async function drainPolling(promise) {
|
|
65
|
+
// Advance in small increments, yielding to microtasks between each,
|
|
66
|
+
// so fetch mocks resolve and the while-loop progresses.
|
|
67
|
+
for (let i = 0; i < 20; i++) {
|
|
68
|
+
await vi.advanceTimersByTimeAsync(6_000);
|
|
69
|
+
}
|
|
70
|
+
return promise;
|
|
71
|
+
}
|
|
72
|
+
it('should request device code and return tokens on immediate approval', async () => {
|
|
73
|
+
mockFetch
|
|
74
|
+
.mockResolvedValueOnce({
|
|
75
|
+
ok: true,
|
|
76
|
+
json: () => Promise.resolve(deviceResponse),
|
|
77
|
+
})
|
|
78
|
+
.mockResolvedValueOnce({
|
|
79
|
+
ok: true,
|
|
80
|
+
json: () => Promise.resolve(tokenResponse),
|
|
81
|
+
});
|
|
82
|
+
const p = client.authorizeDevice();
|
|
83
|
+
await drainPolling(p);
|
|
84
|
+
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
85
|
+
const [deviceUrl, deviceOpts] = mockFetch.mock.calls[0];
|
|
86
|
+
expect(deviceUrl).toBe('https://api.test.com/v1/oauth/device/authorize');
|
|
87
|
+
expect(deviceOpts.body).toBeDefined();
|
|
88
|
+
expect(deviceOpts.body.toString()).toContain('client_id=2');
|
|
89
|
+
const [tokenUrl, tokenOpts] = mockFetch.mock.calls[1];
|
|
90
|
+
expect(tokenUrl).toBe('https://api.test.com/v1/oauth/token');
|
|
91
|
+
expect(tokenOpts.body).toBeDefined();
|
|
92
|
+
expect(tokenOpts.body.toString()).toContain('device_code=dev-code-123');
|
|
93
|
+
expect(saveTokens).toHaveBeenCalledWith(expect.objectContaining({
|
|
94
|
+
accessToken: 'access-123',
|
|
95
|
+
refreshToken: 'refresh-456',
|
|
96
|
+
}));
|
|
97
|
+
});
|
|
98
|
+
it('should poll on authorization_pending then succeed', async () => {
|
|
99
|
+
mockFetch
|
|
100
|
+
.mockResolvedValueOnce({
|
|
101
|
+
ok: true,
|
|
102
|
+
json: () => Promise.resolve(deviceResponse),
|
|
103
|
+
})
|
|
104
|
+
.mockResolvedValueOnce({
|
|
105
|
+
ok: false,
|
|
106
|
+
text: () => Promise.resolve(JSON.stringify({ error: 'authorization_pending' })),
|
|
107
|
+
})
|
|
108
|
+
.mockResolvedValueOnce({
|
|
109
|
+
ok: true,
|
|
110
|
+
json: () => Promise.resolve(tokenResponse),
|
|
111
|
+
});
|
|
112
|
+
const p = client.authorizeDevice();
|
|
113
|
+
await drainPolling(p);
|
|
114
|
+
expect(mockFetch).toHaveBeenCalledTimes(3);
|
|
115
|
+
expect(saveTokens).toHaveBeenCalled();
|
|
116
|
+
});
|
|
117
|
+
it('should increase interval on slow_down then succeed', async () => {
|
|
118
|
+
mockFetch
|
|
119
|
+
.mockResolvedValueOnce({
|
|
120
|
+
ok: true,
|
|
121
|
+
json: () => Promise.resolve(deviceResponse),
|
|
122
|
+
})
|
|
123
|
+
.mockResolvedValueOnce({
|
|
124
|
+
ok: false,
|
|
125
|
+
text: () => Promise.resolve(JSON.stringify({ error: 'slow_down' })),
|
|
126
|
+
})
|
|
127
|
+
.mockResolvedValueOnce({
|
|
128
|
+
ok: true,
|
|
129
|
+
json: () => Promise.resolve(tokenResponse),
|
|
130
|
+
});
|
|
131
|
+
const p = client.authorizeDevice();
|
|
132
|
+
await drainPolling(p);
|
|
133
|
+
expect(mockFetch).toHaveBeenCalledTimes(3);
|
|
134
|
+
});
|
|
135
|
+
it('should throw on access_denied', async () => {
|
|
136
|
+
mockFetch
|
|
137
|
+
.mockResolvedValueOnce({
|
|
138
|
+
ok: true,
|
|
139
|
+
json: () => Promise.resolve(deviceResponse),
|
|
140
|
+
})
|
|
141
|
+
.mockResolvedValueOnce({
|
|
142
|
+
ok: false,
|
|
143
|
+
text: () => Promise.resolve(JSON.stringify({ error: 'access_denied' })),
|
|
144
|
+
});
|
|
145
|
+
const p = client.authorizeDevice();
|
|
146
|
+
// Attach rejection handler before advancing timers to avoid unhandled rejection
|
|
147
|
+
const assertion = expect(p).rejects.toThrow('Authorization denied by user.');
|
|
148
|
+
await drainPolling(p).catch(() => { });
|
|
149
|
+
await assertion;
|
|
150
|
+
});
|
|
151
|
+
it('should throw on expired_token', async () => {
|
|
152
|
+
mockFetch
|
|
153
|
+
.mockResolvedValueOnce({
|
|
154
|
+
ok: true,
|
|
155
|
+
json: () => Promise.resolve(deviceResponse),
|
|
156
|
+
})
|
|
157
|
+
.mockResolvedValueOnce({
|
|
158
|
+
ok: false,
|
|
159
|
+
text: () => Promise.resolve(JSON.stringify({ error: 'expired_token' })),
|
|
160
|
+
});
|
|
161
|
+
const p = client.authorizeDevice();
|
|
162
|
+
const assertion = expect(p).rejects.toThrow('Device code expired');
|
|
163
|
+
await drainPolling(p).catch(() => { });
|
|
164
|
+
await assertion;
|
|
165
|
+
});
|
|
166
|
+
it('should handle non-JSON error response', async () => {
|
|
167
|
+
mockFetch
|
|
168
|
+
.mockResolvedValueOnce({
|
|
169
|
+
ok: true,
|
|
170
|
+
json: () => Promise.resolve(deviceResponse),
|
|
171
|
+
})
|
|
172
|
+
.mockResolvedValueOnce({
|
|
173
|
+
ok: false,
|
|
174
|
+
status: 502,
|
|
175
|
+
text: () => Promise.resolve('Bad Gateway'),
|
|
176
|
+
});
|
|
177
|
+
const p = client.authorizeDevice();
|
|
178
|
+
const assertion = expect(p).rejects.toThrow('Device flow polling failed');
|
|
179
|
+
await drainPolling(p).catch(() => { });
|
|
180
|
+
await assertion;
|
|
181
|
+
});
|
|
182
|
+
it('should throw when device authorize request fails', async () => {
|
|
183
|
+
mockFetch.mockResolvedValueOnce({
|
|
184
|
+
ok: false,
|
|
185
|
+
status: 400,
|
|
186
|
+
text: () => Promise.resolve('Bad Request'),
|
|
187
|
+
});
|
|
188
|
+
await expect(client.authorizeDevice()).rejects.toThrow('Device authorization request failed (400): Bad Request');
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
describe('OAuthClient.setTokens workspace persistence', () => {
|
|
192
|
+
let client;
|
|
193
|
+
beforeEach(() => {
|
|
194
|
+
vi.useFakeTimers();
|
|
195
|
+
vi.mocked(saveWorkspace).mockClear();
|
|
196
|
+
client = new OAuthClient({
|
|
197
|
+
clientId: '2',
|
|
198
|
+
authServerUrl: 'https://api.test.com',
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
afterEach(() => {
|
|
202
|
+
mockFetch.mockReset();
|
|
203
|
+
vi.useRealTimers();
|
|
204
|
+
});
|
|
205
|
+
it('persists workspace when device grant carries user.workspace_id', async () => {
|
|
206
|
+
const wsId = 'ws-device-abc';
|
|
207
|
+
mockFetch
|
|
208
|
+
.mockResolvedValueOnce({
|
|
209
|
+
ok: true,
|
|
210
|
+
json: () => Promise.resolve(deviceResponse),
|
|
211
|
+
})
|
|
212
|
+
.mockResolvedValueOnce({
|
|
213
|
+
ok: true,
|
|
214
|
+
json: () => Promise.resolve({
|
|
215
|
+
...tokenResponse,
|
|
216
|
+
user: { workspace_id: wsId },
|
|
217
|
+
// Backend includes workspaces[] in the grant response but
|
|
218
|
+
// tq-oauth does not cache it locally — left here to simulate
|
|
219
|
+
// the full payload without asserting anything on it.
|
|
220
|
+
workspaces: [
|
|
221
|
+
{
|
|
222
|
+
id: wsId,
|
|
223
|
+
name: 'My Workspace',
|
|
224
|
+
url_key: 'my-ws',
|
|
225
|
+
is_primary: true,
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
}),
|
|
229
|
+
});
|
|
230
|
+
const p = client.authorizeDevice();
|
|
231
|
+
for (let i = 0; i < 20; i++) {
|
|
232
|
+
await vi.advanceTimersByTimeAsync(6_000);
|
|
233
|
+
}
|
|
234
|
+
await p;
|
|
235
|
+
expect(saveWorkspace).toHaveBeenCalledTimes(1);
|
|
236
|
+
expect(saveWorkspace).toHaveBeenCalledWith(wsId);
|
|
237
|
+
});
|
|
238
|
+
it('does NOT persist workspace when grant omits user.workspace_id (refresh-like)', async () => {
|
|
239
|
+
mockFetch
|
|
240
|
+
.mockResolvedValueOnce({
|
|
241
|
+
ok: true,
|
|
242
|
+
json: () => Promise.resolve(deviceResponse),
|
|
243
|
+
})
|
|
244
|
+
.mockResolvedValueOnce({
|
|
245
|
+
ok: true,
|
|
246
|
+
json: () => Promise.resolve(tokenResponse),
|
|
247
|
+
});
|
|
248
|
+
const p = client.authorizeDevice();
|
|
249
|
+
for (let i = 0; i < 20; i++) {
|
|
250
|
+
await vi.advanceTimersByTimeAsync(6_000);
|
|
251
|
+
}
|
|
252
|
+
await p;
|
|
253
|
+
expect(saveWorkspace).not.toHaveBeenCalled();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
describe('OAuthClient.refresh workspace behavior', () => {
|
|
257
|
+
let client;
|
|
258
|
+
beforeEach(() => {
|
|
259
|
+
vi.mocked(saveWorkspace).mockClear();
|
|
260
|
+
client = new OAuthClient({
|
|
261
|
+
clientId: '2',
|
|
262
|
+
authServerUrl: 'https://api.test.com',
|
|
263
|
+
});
|
|
264
|
+
// Seed a refresh token so refresh() proceeds to the fetch call
|
|
265
|
+
client.setTokensFromStorage({
|
|
266
|
+
accessToken: 'expired-access',
|
|
267
|
+
refreshToken: 'refresh-seed',
|
|
268
|
+
expiresAt: Date.now() - 1000,
|
|
269
|
+
apiBaseUrl: 'https://api.test.com',
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
afterEach(() => {
|
|
273
|
+
mockFetch.mockReset();
|
|
274
|
+
});
|
|
275
|
+
it('refresh response without user field does NOT save workspace', async () => {
|
|
276
|
+
mockFetch.mockResolvedValueOnce({
|
|
277
|
+
ok: true,
|
|
278
|
+
json: () => Promise.resolve({
|
|
279
|
+
access_token: 'new-access',
|
|
280
|
+
token_type: 'bearer',
|
|
281
|
+
expires_in: 3600,
|
|
282
|
+
refresh_token: 'new-refresh',
|
|
283
|
+
scope: 'read:own',
|
|
284
|
+
}),
|
|
285
|
+
});
|
|
286
|
+
await client.refresh();
|
|
287
|
+
expect(saveWorkspace).not.toHaveBeenCalled();
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
//# sourceMappingURL=oauth-client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-client.test.js","sourceRoot":"","sources":["../src/oauth-client.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared test utilities for tq-oauth tests.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Temporarily simulate a non-test environment so loadConfig()
|
|
6
|
+
* exercises the config-file reading path. loadConfig() skips
|
|
7
|
+
* ~/.tq/config.json when VITEST/JEST env vars are set.
|
|
8
|
+
*/
|
|
9
|
+
export declare function withNonTestEnv<T>(fn: () => T): T;
|
|
10
|
+
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CA2BhD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared test utilities for tq-oauth tests.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Temporarily simulate a non-test environment so loadConfig()
|
|
6
|
+
* exercises the config-file reading path. loadConfig() skips
|
|
7
|
+
* ~/.tq/config.json when VITEST/JEST env vars are set.
|
|
8
|
+
*/
|
|
9
|
+
export function withNonTestEnv(fn) {
|
|
10
|
+
const saved = {
|
|
11
|
+
VITEST: process.env.VITEST,
|
|
12
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
13
|
+
JEST_WORKER_ID: process.env.JEST_WORKER_ID,
|
|
14
|
+
// DEV_TLS gates isLocalTlsMode() in config.ts. Clearing it forces the
|
|
15
|
+
// cert-file probe path, which deterministically returns false in the
|
|
16
|
+
// tmpDir filesystem the test harness uses.
|
|
17
|
+
DEV_TLS: process.env.DEV_TLS,
|
|
18
|
+
};
|
|
19
|
+
delete process.env.VITEST;
|
|
20
|
+
process.env.NODE_ENV = 'development';
|
|
21
|
+
delete process.env.JEST_WORKER_ID;
|
|
22
|
+
delete process.env.DEV_TLS;
|
|
23
|
+
try {
|
|
24
|
+
return fn();
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
if (saved.VITEST !== undefined)
|
|
28
|
+
process.env.VITEST = saved.VITEST;
|
|
29
|
+
else
|
|
30
|
+
delete process.env.VITEST;
|
|
31
|
+
if (saved.NODE_ENV !== undefined)
|
|
32
|
+
process.env.NODE_ENV = saved.NODE_ENV;
|
|
33
|
+
else
|
|
34
|
+
delete process.env.NODE_ENV;
|
|
35
|
+
if (saved.JEST_WORKER_ID !== undefined)
|
|
36
|
+
process.env.JEST_WORKER_ID = saved.JEST_WORKER_ID;
|
|
37
|
+
else
|
|
38
|
+
delete process.env.JEST_WORKER_ID;
|
|
39
|
+
if (saved.DEV_TLS !== undefined)
|
|
40
|
+
process.env.DEV_TLS = saved.DEV_TLS;
|
|
41
|
+
else
|
|
42
|
+
delete process.env.DEV_TLS;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=test-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAI,EAAW;IAC3C,MAAM,KAAK,GAAG;QACZ,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM;QAC1B,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ;QAC9B,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;QAC1C,sEAAsE;QACtE,qEAAqE;QACrE,2CAA2C;QAC3C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO;KAC7B,CAAC;IACF,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,aAAa,CAAC;IACrC,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAClC,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;;YAC7D,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;QAC/B,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;;YACnE,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjC,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS;YACpC,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;;YAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACvC,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;;YAChE,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;IAClC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure token storage for OAuth tokens
|
|
3
|
+
*
|
|
4
|
+
* Stores tokens in ~/.tq/oauth-tokens.json as a map keyed by backend URL:
|
|
5
|
+
* {
|
|
6
|
+
* "https://api.levr.now": { accessToken, refreshToken, expiresAt, apiBaseUrl },
|
|
7
|
+
* "http://localhost:8080": { ... }
|
|
8
|
+
* }
|
|
9
|
+
*
|
|
10
|
+
* Backward-compatible: if the file contains the legacy single-token format
|
|
11
|
+
* (flat object with accessToken at the top level), it is migrated in-place
|
|
12
|
+
* to the new map format on first read.
|
|
13
|
+
*/
|
|
14
|
+
import type { StoredTokens } from './types.js';
|
|
15
|
+
export type EnvName = 'local' | 'staging' | 'production';
|
|
16
|
+
/**
|
|
17
|
+
* Resolve an environment name from a backend URL.
|
|
18
|
+
* Returns undefined if the URL doesn't match any known preset.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveEnvFromUrl(url: string): EnvName | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a backend URL from an environment name.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveUrlFromEnv(env: EnvName): string;
|
|
25
|
+
/**
|
|
26
|
+
* Load the token for the current environment.
|
|
27
|
+
* Reads the config to determine which backend URL is active,
|
|
28
|
+
* then returns the matching entry from the token map.
|
|
29
|
+
*
|
|
30
|
+
* Falls back to first token in the map ONLY when no config exists
|
|
31
|
+
* (backward compat for first-time migration). When the user has
|
|
32
|
+
* explicitly set an environment, only that environment's token is returned.
|
|
33
|
+
*/
|
|
34
|
+
export declare function loadTokens(): StoredTokens | null;
|
|
35
|
+
/**
|
|
36
|
+
* Load tokens for a specific environment by name.
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadTokensForEnv(env: EnvName): StoredTokens | null;
|
|
39
|
+
/**
|
|
40
|
+
* Load tokens for an arbitrary backend URL (custom URL not in ENV_URLS).
|
|
41
|
+
*
|
|
42
|
+
* Used by the qinetic sync setup command, which needs to talk to a remote
|
|
43
|
+
* backend that may not be one of the named presets — the operator passes
|
|
44
|
+
* `--target <url>` and the CLI fetches the matching token entry by URL.
|
|
45
|
+
*/
|
|
46
|
+
export declare function loadTokensForUrl(url: string): StoredTokens | null;
|
|
47
|
+
/**
|
|
48
|
+
* Save tokens for the current environment.
|
|
49
|
+
* Upserts the entry keyed by the token's apiBaseUrl.
|
|
50
|
+
*/
|
|
51
|
+
export declare function saveTokens(tokens: StoredTokens): void;
|
|
52
|
+
/**
|
|
53
|
+
* Save tokens for a specific environment by name.
|
|
54
|
+
*/
|
|
55
|
+
export declare function saveTokensForEnv(env: EnvName, tokens: StoredTokens): void;
|
|
56
|
+
/**
|
|
57
|
+
* Clear stored tokens for the current environment.
|
|
58
|
+
* Moves the entire file to .bak before removing the entry.
|
|
59
|
+
*/
|
|
60
|
+
export declare function clearTokens(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Attempt to restore tokens from backup (.bak file)
|
|
63
|
+
* Returns true if backup was restored successfully.
|
|
64
|
+
*/
|
|
65
|
+
export declare function restoreTokensFromBackup(): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Check if token file exists and has any entries
|
|
68
|
+
*/
|
|
69
|
+
export declare function hasStoredTokens(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Get token file path (for debugging and watching)
|
|
72
|
+
*/
|
|
73
|
+
export declare function getTokenFilePath(): string;
|
|
74
|
+
/**
|
|
75
|
+
* Get TQ directory path
|
|
76
|
+
*/
|
|
77
|
+
export declare function getTqDir(): string;
|
|
78
|
+
//# sourceMappingURL=token-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../src/token-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;AAyBzD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAMlE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEtD;AAwDD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,IAAI,YAAY,GAAG,IAAI,CAmBhD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAMlE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAOjE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAUrD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAIzE;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CA6BlC;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAiCjD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CAEjC"}
|