@doist/cli-core 0.17.0 → 0.19.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/CHANGELOG.md +12 -0
- package/README.md +33 -17
- package/dist/auth/errors.d.ts +1 -1
- package/dist/auth/errors.d.ts.map +1 -1
- package/dist/auth/flow.d.ts.map +1 -1
- package/dist/auth/flow.js +7 -8
- package/dist/auth/flow.js.map +1 -1
- package/dist/auth/index.d.ts +4 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +2 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/keyring/internal.d.ts +50 -0
- package/dist/auth/keyring/internal.d.ts.map +1 -0
- package/dist/auth/keyring/internal.js +48 -0
- package/dist/auth/keyring/internal.js.map +1 -0
- package/dist/auth/keyring/migrate.d.ts +19 -17
- package/dist/auth/keyring/migrate.d.ts.map +1 -1
- package/dist/auth/keyring/migrate.js +111 -49
- package/dist/auth/keyring/migrate.js.map +1 -1
- package/dist/auth/keyring/record-write.d.ts +13 -1
- package/dist/auth/keyring/record-write.d.ts.map +1 -1
- package/dist/auth/keyring/record-write.js +18 -0
- package/dist/auth/keyring/record-write.js.map +1 -1
- package/dist/auth/keyring/token-store.d.ts +7 -1
- package/dist/auth/keyring/token-store.d.ts.map +1 -1
- package/dist/auth/keyring/token-store.js +63 -34
- package/dist/auth/keyring/token-store.js.map +1 -1
- package/dist/auth/persist.d.ts +9 -1
- package/dist/auth/persist.d.ts.map +1 -1
- package/dist/auth/persist.js +20 -0
- package/dist/auth/persist.js.map +1 -1
- package/dist/auth/providers/pkce.d.ts +1 -1
- package/dist/auth/providers/pkce.d.ts.map +1 -1
- package/dist/auth/providers/pkce.js +89 -7
- package/dist/auth/providers/pkce.js.map +1 -1
- package/dist/auth/refresh.d.ts +49 -0
- package/dist/auth/refresh.d.ts.map +1 -0
- package/dist/auth/refresh.js +184 -0
- package/dist/auth/refresh.js.map +1 -0
- package/dist/auth/status.d.ts +12 -4
- package/dist/auth/status.d.ts.map +1 -1
- package/dist/auth/status.js +45 -5
- package/dist/auth/status.js.map +1 -1
- package/dist/auth/types.d.ts +17 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/package.json +9 -4
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
import { getErrorMessage } from '../../errors.js';
|
|
2
|
-
import {
|
|
2
|
+
import { readAccessTokenForRecord } from './internal.js';
|
|
3
|
+
import { buildSingleTokenRecord } from './record-write.js';
|
|
3
4
|
import { createSecureStore, DEFAULT_ACCOUNT_FOR_USER, SecureStoreUnavailableError, } from './secure-store.js';
|
|
4
5
|
const SKIP_REASON_MESSAGES = {
|
|
5
6
|
'identify-failed': 'could not identify user',
|
|
6
7
|
'legacy-keyring-unreachable': 'legacy credential is unreachable (keyring offline)',
|
|
8
|
+
'user-keyring-unreachable': 'per-user credential slot is unreachable (keyring offline)',
|
|
7
9
|
'user-record-write-failed': 'failed to update user records',
|
|
8
10
|
'marker-write-failed': 'failed to persist migration marker',
|
|
9
11
|
};
|
|
10
12
|
/**
|
|
11
13
|
* One-time migration of a v1 single-user auth state into a v2 multi-user
|
|
12
|
-
* shape. Best-effort: any failure
|
|
13
|
-
*
|
|
14
|
-
* fallback can keep serving the legacy token until the next attempt.
|
|
14
|
+
* shape. Best-effort: any failure leaves v1 untouched so the runtime
|
|
15
|
+
* fallback keeps serving the legacy token until the next attempt.
|
|
15
16
|
*
|
|
16
|
-
* Order
|
|
17
|
+
* Order is deliberate so the migration is one-way AND safe under retry:
|
|
17
18
|
*
|
|
18
|
-
* 1. `hasMigrated()` short-circuits
|
|
19
|
-
* 2. Read the v1 token (legacy keyring
|
|
20
|
-
* 3. `identifyAccount(token)` resolves the v2 `account
|
|
21
|
-
* 4. `
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
19
|
+
* 1. `hasMigrated()` short-circuits when the marker is set.
|
|
20
|
+
* 2. Read the v1 token (legacy keyring first, then plaintext).
|
|
21
|
+
* 3. `identifyAccount(token)` resolves the v2 `account`.
|
|
22
|
+
* 4. **Phase 1** — `ensureV2Record` writes a fallback-bearing record (or
|
|
23
|
+
* no-ops when a v2 record already exists).
|
|
24
|
+
* 5. **Phase 2** — when Phase 1 wrote: move the token to the per-user
|
|
25
|
+
* keyring slot and upsert the clean record. When Phase 1 didn't:
|
|
26
|
+
* verify the existing record is readable before retiring legacy.
|
|
27
|
+
* 6. Best-effort `setDefaultId(account.id)`.
|
|
28
|
+
* 7. `markMigrated()` — the one-way gate. Failure here surfaces as
|
|
29
|
+
* `skipped(marker-write-failed)` so the caller retries.
|
|
30
|
+
* 8. Best-effort legacy cleanup runs concurrently.
|
|
28
31
|
*/
|
|
29
32
|
export async function migrateLegacyAuth(options) {
|
|
30
33
|
const { serviceName, legacyAccount, userRecords, hasMigrated, markMigrated, loadLegacyPlaintextToken, identifyAccount, cleanupLegacyConfig, silent, } = options;
|
|
@@ -33,8 +36,6 @@ export async function migrateLegacyAuth(options) {
|
|
|
33
36
|
if (await hasMigrated()) {
|
|
34
37
|
return { status: 'already-migrated' };
|
|
35
38
|
}
|
|
36
|
-
// One legacy-keyring handle covers both the initial read and the
|
|
37
|
-
// post-success cleanup delete.
|
|
38
39
|
const legacyStore = createSecureStore({ serviceName, account: legacyAccount });
|
|
39
40
|
const legacyToken = await readLegacyToken(legacyStore, loadLegacyPlaintextToken);
|
|
40
41
|
if (legacyToken.kind === 'none')
|
|
@@ -49,28 +50,41 @@ export async function migrateLegacyAuth(options) {
|
|
|
49
50
|
catch (error) {
|
|
50
51
|
return skipped(silent, logPrefix, 'identify-failed', getErrorMessage(error));
|
|
51
52
|
}
|
|
52
|
-
|
|
53
|
-
// internally (writing to `fallbackToken` instead), so any error here is
|
|
54
|
-
// a non-keyring failure — typically a `userRecords.upsert` rejection.
|
|
53
|
+
let phase1;
|
|
55
54
|
try {
|
|
56
|
-
await
|
|
57
|
-
secureStore: createSecureStore({
|
|
58
|
-
serviceName,
|
|
59
|
-
account: accountForUser(account.id),
|
|
60
|
-
}),
|
|
61
|
-
userRecords,
|
|
62
|
-
account,
|
|
63
|
-
token: legacyToken.token,
|
|
64
|
-
});
|
|
55
|
+
phase1 = await ensureV2Record(userRecords, account, legacyToken.token);
|
|
65
56
|
}
|
|
66
57
|
catch (error) {
|
|
67
58
|
return skipped(silent, logPrefix, 'user-record-write-failed', getErrorMessage(error));
|
|
68
59
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
//
|
|
60
|
+
const userSlot = createSecureStore({
|
|
61
|
+
serviceName,
|
|
62
|
+
account: accountForUser(account.id),
|
|
63
|
+
});
|
|
64
|
+
// Run Phase 2 when EITHER Phase 1 just wrote the fallback record OR
|
|
65
|
+
// the existing record's fallback matches our legacy token — that's a
|
|
66
|
+
// prior-run Phase 1 we owe an upgrade. Other existing records are
|
|
67
|
+
// external state and get a readability check instead.
|
|
68
|
+
const isOurPriorPhase1 = !phase1.written && phase1.existing.fallbackToken?.trim() === legacyToken.token;
|
|
69
|
+
if (phase1.written || isOurPriorPhase1) {
|
|
70
|
+
const phase2Error = await runPhase2(userRecords, userSlot, account, legacyToken.token);
|
|
71
|
+
if (phase2Error) {
|
|
72
|
+
return skipped(silent, logPrefix, phase2Error.reason, phase2Error.detail);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// External record — cleaning up legacy is safe only if it can be
|
|
77
|
+
// read in the current environment.
|
|
78
|
+
const outcome = await readAccessTokenForRecord(phase1.existing, userSlot);
|
|
79
|
+
if (!outcome.ok) {
|
|
80
|
+
const reason = outcome.reason === 'slot-unavailable'
|
|
81
|
+
? 'user-keyring-unreachable'
|
|
82
|
+
: 'user-record-write-failed';
|
|
83
|
+
return skipped(silent, logPrefix, reason, outcome.detail);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Only promote when nothing is pinned — a retry must not overwrite a
|
|
87
|
+
// default the user chose between attempts.
|
|
74
88
|
try {
|
|
75
89
|
const existingDefault = await userRecords.getDefaultId();
|
|
76
90
|
if (!existingDefault) {
|
|
@@ -80,36 +94,84 @@ export async function migrateLegacyAuth(options) {
|
|
|
80
94
|
catch {
|
|
81
95
|
// best-effort
|
|
82
96
|
}
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
// `skipped` so the caller retries. Without this ordering, a later
|
|
86
|
-
// `logout` could let the next run re-migrate the stale v1 token.
|
|
97
|
+
// Marker BEFORE cleanup: the gate, not cleanup, is what prevents the
|
|
98
|
+
// next run from re-migrating after a later `logout`.
|
|
87
99
|
try {
|
|
88
100
|
await markMigrated();
|
|
89
101
|
}
|
|
90
102
|
catch (error) {
|
|
91
103
|
return skipped(silent, logPrefix, 'marker-write-failed', getErrorMessage(error));
|
|
92
104
|
}
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
// re-migration on the next run. The `Promise.resolve().then(...)`
|
|
97
|
-
// wrappers convert any *synchronous* throw from a consumer-supplied
|
|
98
|
-
// `cleanupLegacyConfig` (or an oddly-implemented `SecureStore`) into
|
|
99
|
-
// a rejected promise that `Promise.allSettled` can swallow.
|
|
105
|
+
// `Promise.resolve().then(...)` converts any *synchronous* throw from
|
|
106
|
+
// a consumer's `cleanupLegacyConfig` into a rejection that
|
|
107
|
+
// `allSettled` can swallow.
|
|
100
108
|
await Promise.allSettled([
|
|
101
109
|
Promise.resolve().then(() => legacyStore.deleteSecret()),
|
|
102
110
|
Promise.resolve().then(() => cleanupLegacyConfig?.()),
|
|
103
111
|
]);
|
|
104
112
|
if (!silent) {
|
|
105
|
-
//
|
|
106
|
-
// but consumers can legitimately use an email or other PII there.
|
|
107
|
-
// Callers that need richer telemetry can compose it from the
|
|
108
|
-
// returned `account`.
|
|
113
|
+
// Account id may carry PII (email, etc.) — keep it out of logs.
|
|
109
114
|
console.error(`${logPrefix}: migrated existing token to multi-user store.`);
|
|
110
115
|
}
|
|
111
116
|
return { status: 'migrated', account };
|
|
112
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Phase 1. Writes a `fallbackToken`-bearing record so a crash before
|
|
120
|
+
* Phase 2 still leaves a working credential. Returns `{ written: true }`
|
|
121
|
+
* when this call wrote, or `{ written: false, existing }` when a v2
|
|
122
|
+
* record already existed — the existing record is returned so callers
|
|
123
|
+
* decide whether to upgrade it (Phase 2 retry) or treat it as external
|
|
124
|
+
* state, without paying a second `list()`.
|
|
125
|
+
*/
|
|
126
|
+
async function ensureV2Record(userRecords, account, legacyToken) {
|
|
127
|
+
const record = buildSingleTokenRecord(account, legacyToken);
|
|
128
|
+
if (userRecords.tryInsert) {
|
|
129
|
+
const wrote = await userRecords.tryInsert(record);
|
|
130
|
+
if (wrote)
|
|
131
|
+
return { written: true };
|
|
132
|
+
const existing = (await userRecords.list()).find((r) => r.account.id === account.id);
|
|
133
|
+
if (!existing) {
|
|
134
|
+
throw new Error('tryInsert returned false but no matching record was listed');
|
|
135
|
+
}
|
|
136
|
+
return { written: false, existing };
|
|
137
|
+
}
|
|
138
|
+
// Non-atomic path. Narrow time-of-check, time-of-use race between
|
|
139
|
+
// `list()` and `upsert()`; acceptable for one-time migration since
|
|
140
|
+
// concurrent runs would write the same shape.
|
|
141
|
+
const all = await userRecords.list();
|
|
142
|
+
const existing = all.find((r) => r.account.id === account.id);
|
|
143
|
+
if (existing)
|
|
144
|
+
return { written: false, existing };
|
|
145
|
+
await userRecords.upsert(record);
|
|
146
|
+
return { written: true };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Phase 2: move the legacy token into the per-user keyring slot and
|
|
150
|
+
* upsert a clean (no `fallbackToken`) record. Inlined rather than
|
|
151
|
+
* delegating to `writeRecordWithKeyringFallback` so the offline-keyring
|
|
152
|
+
* branch doesn't double-upsert the same fallback record Phase 1 just
|
|
153
|
+
* wrote. Returns `null` on success (including the silently-handled
|
|
154
|
+
* SecureStoreUnavailable case); a skip descriptor when a non-keyring
|
|
155
|
+
* failure leaves the marker unset for retry.
|
|
156
|
+
*/
|
|
157
|
+
async function runPhase2(userRecords, userSlot, account, legacyToken) {
|
|
158
|
+
try {
|
|
159
|
+
await userSlot.setSecret(legacyToken);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
if (error instanceof SecureStoreUnavailableError) {
|
|
163
|
+
return null; // Phase 1 fallback record continues to serve reads.
|
|
164
|
+
}
|
|
165
|
+
return { reason: 'user-record-write-failed', detail: getErrorMessage(error) };
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
await userRecords.upsert(buildSingleTokenRecord(account));
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
return { reason: 'user-record-write-failed', detail: getErrorMessage(error) };
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
113
175
|
async function readLegacyToken(legacyStore, loadLegacyPlaintextToken) {
|
|
114
176
|
let keyringUnavailable = false;
|
|
115
177
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/auth/keyring/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/auth/keyring/migrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AuthAccount, TokenBundle } from '../types.js';
|
|
2
2
|
import { type SecureStore } from './secure-store.js';
|
|
3
|
-
import type { UserRecordStore } from './types.js';
|
|
3
|
+
import type { UserRecord, UserRecordStore } from './types.js';
|
|
4
4
|
type WriteRecordOptions<TAccount extends AuthAccount> = {
|
|
5
5
|
/** Per-account keyring slot, already configured by the caller (e.g. via `createSecureStore`). */
|
|
6
6
|
secureStore: SecureStore;
|
|
@@ -72,5 +72,17 @@ export declare function writeRecordWithKeyringFallback<TAccount extends AuthAcco
|
|
|
72
72
|
* error there must not dirty up a successful credential write.
|
|
73
73
|
*/
|
|
74
74
|
export declare function writeBundleWithKeyringFallback<TAccount extends AuthAccount>(options: WriteBundleOptions<TAccount>): Promise<WriteBundleResult>;
|
|
75
|
+
/**
|
|
76
|
+
* Build a `UserRecord` for an access-only credential (no refresh state).
|
|
77
|
+
* Used by `migrateLegacyAuth`'s Phase 1 / Phase 2 record writes; both call
|
|
78
|
+
* sites then agree on the explicit `hasRefreshToken: false` that lets
|
|
79
|
+
* future bundle-aware readers skip the refresh-slot IPC.
|
|
80
|
+
*
|
|
81
|
+
* `writeBundleWithKeyringFallback` builds its own record shape inline
|
|
82
|
+
* because the bundle path also carries expiry fields; the structural
|
|
83
|
+
* overlap is the `hasRefreshToken: false` + optional `fallbackToken`
|
|
84
|
+
* pair, which is what this helper isolates.
|
|
85
|
+
*/
|
|
86
|
+
export declare function buildSingleTokenRecord<TAccount extends AuthAccount>(account: TAccount, fallbackToken?: string): UserRecord<TAccount>;
|
|
75
87
|
export {};
|
|
76
88
|
//# sourceMappingURL=record-write.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-write.d.ts","sourceRoot":"","sources":["../../../src/auth/keyring/record-write.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,KAAK,WAAW,EAA+B,MAAM,mBAAmB,CAAA;AACjF,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"record-write.d.ts","sourceRoot":"","sources":["../../../src/auth/keyring/record-write.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,KAAK,WAAW,EAA+B,MAAM,mBAAmB,CAAA;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE7D,KAAK,kBAAkB,CAAC,QAAQ,SAAS,WAAW,IAAI;IACpD,iGAAiG;IACjG,WAAW,EAAE,WAAW,CAAA;IACxB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,WAAW,CAAA;IAC1B,WAAW,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;IACtC,OAAO,EAAE,QAAQ,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,iBAAiB,GAAG;IACrB,iKAAiK;IACjK,cAAc,EAAE,OAAO,CAAA;CAC1B,CAAA;AAED,KAAK,kBAAkB,CAAC,QAAQ,SAAS,WAAW,IAAI;IACpD,6CAA6C;IAC7C,WAAW,EAAE,WAAW,CAAA;IACxB,8CAA8C;IAC9C,YAAY,EAAE,WAAW,CAAA;IACzB,WAAW,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;IACtC,OAAO,EAAE,QAAQ,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;CACtB,CAAA;AAED,KAAK,iBAAiB,GAAG;IACrB,2GAA2G;IAC3G,oBAAoB,EAAE,OAAO,CAAA;IAC7B;;;;OAIG;IACH,qBAAqB,EAAE,OAAO,GAAG,SAAS,CAAA;CAC7C,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAsB,8BAA8B,CAAC,QAAQ,SAAS,WAAW,EAC7E,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,GACtC,OAAO,CAAC,iBAAiB,CAAC,CAe5B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,8BAA8B,CAAC,QAAQ,SAAS,WAAW,EAC7E,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,GACtC,OAAO,CAAC,iBAAiB,CAAC,CAgF5B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,SAAS,WAAW,EAC/D,OAAO,EAAE,QAAQ,EACjB,aAAa,CAAC,EAAE,MAAM,GACvB,UAAU,CAAC,QAAQ,CAAC,CAMtB"}
|
|
@@ -127,6 +127,24 @@ export async function writeBundleWithKeyringFallback(options) {
|
|
|
127
127
|
}
|
|
128
128
|
return { accessStoredSecurely, refreshStoredSecurely };
|
|
129
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Build a `UserRecord` for an access-only credential (no refresh state).
|
|
132
|
+
* Used by `migrateLegacyAuth`'s Phase 1 / Phase 2 record writes; both call
|
|
133
|
+
* sites then agree on the explicit `hasRefreshToken: false` that lets
|
|
134
|
+
* future bundle-aware readers skip the refresh-slot IPC.
|
|
135
|
+
*
|
|
136
|
+
* `writeBundleWithKeyringFallback` builds its own record shape inline
|
|
137
|
+
* because the bundle path also carries expiry fields; the structural
|
|
138
|
+
* overlap is the `hasRefreshToken: false` + optional `fallbackToken`
|
|
139
|
+
* pair, which is what this helper isolates.
|
|
140
|
+
*/
|
|
141
|
+
export function buildSingleTokenRecord(account, fallbackToken) {
|
|
142
|
+
return {
|
|
143
|
+
account,
|
|
144
|
+
...(fallbackToken ? { fallbackToken } : {}),
|
|
145
|
+
hasRefreshToken: false,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
130
148
|
const NOOP_SECURE_STORE = {
|
|
131
149
|
async getSecret() {
|
|
132
150
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-write.js","sourceRoot":"","sources":["../../../src/auth/keyring/record-write.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"record-write.js","sourceRoot":"","sources":["../../../src/auth/keyring/record-write.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AccountRef, AuthAccount, TokenBundle, TokenStore } from '../types.js';
|
|
1
|
+
import type { AccountRef, ActiveBundleSnapshot, AuthAccount, TokenBundle, TokenStore } from '../types.js';
|
|
2
2
|
import type { TokenStorageResult, UserRecordStore } from './types.js';
|
|
3
3
|
export type CreateKeyringTokenStoreOptions<TAccount extends AuthAccount> = {
|
|
4
4
|
/** Application identifier used for every keyring entry (e.g. `'todoist-cli'`). */
|
|
@@ -32,6 +32,12 @@ export type KeyringTokenStore<TAccount extends AuthAccount> = TokenStore<TAccoun
|
|
|
32
32
|
setBundle(account: TAccount, bundle: TokenBundle, options?: {
|
|
33
33
|
promoteDefault?: boolean;
|
|
34
34
|
}): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Override `activeBundle` as required (not optional) — the keyring store
|
|
37
|
+
* always knows how to read refresh state. Lets cli-core helpers
|
|
38
|
+
* (`refreshAccessToken`) call it without a non-null assertion.
|
|
39
|
+
*/
|
|
40
|
+
activeBundle(ref?: AccountRef): Promise<ActiveBundleSnapshot<TAccount> | null>;
|
|
35
41
|
/** Storage result from the most recent `set()` / `setBundle()` call, or `undefined` before any (and reset to `undefined` when the most recent write threw). */
|
|
36
42
|
getLastStorageResult(): TokenStorageResult | undefined;
|
|
37
43
|
/** Storage result from the most recent `clear()` call, or `undefined` before any (and reset to `undefined` when the most recent `clear()` threw or was a no-op). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../../src/auth/keyring/token-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../../src/auth/keyring/token-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,UAAU,EACV,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,UAAU,EACb,MAAM,aAAa,CAAA;AAepB,OAAO,KAAK,EAAE,kBAAkB,EAAc,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjF,MAAM,MAAM,8BAA8B,CAAC,QAAQ,SAAS,WAAW,IAAI;IACvE,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAA;IACnB,oFAAoF;IACpF,WAAW,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;IACtC;;;;OAIG;IACH,eAAe,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,KAAK,OAAO,CAAA;CACjE,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,WAAW,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG;IACjF;;;;OAIG;IACH,SAAS,CACL,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GACvC,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB;;;;OAIG;IACH,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAA;IAC9E,+JAA+J;IAC/J,oBAAoB,IAAI,kBAAkB,GAAG,SAAS,CAAA;IACtD,oKAAoK;IACpK,kBAAkB,IAAI,kBAAkB,GAAG,SAAS,CAAA;CACvD,CAAA;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,SAAS,WAAW,EAChE,OAAO,EAAE,8BAA8B,CAAC,QAAQ,CAAC,GAClD,iBAAiB,CAAC,QAAQ,CAAC,CAqT7B"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { CliError
|
|
1
|
+
import { CliError } from '../../errors.js';
|
|
2
2
|
import { accountNotFoundError } from '../user-flag.js';
|
|
3
|
+
import { readAccessTokenForRecord, readRefreshTokenForRecord, } from './internal.js';
|
|
3
4
|
import { writeBundleWithKeyringFallback, writeRecordWithKeyringFallback } from './record-write.js';
|
|
4
|
-
import { createSecureStore, DEFAULT_ACCOUNT_FOR_USER, SECURE_STORE_DESCRIPTION,
|
|
5
|
+
import { createSecureStore, DEFAULT_ACCOUNT_FOR_USER, SECURE_STORE_DESCRIPTION, } from './secure-store.js';
|
|
5
6
|
import { refreshAccountSlot } from './slot-naming.js';
|
|
6
7
|
const DEFAULT_MATCH_ACCOUNT = (account, ref) => account.id === ref || account.label === ref;
|
|
8
|
+
function accessReadError(outcome) {
|
|
9
|
+
const message = outcome.reason === 'slot-empty'
|
|
10
|
+
? `${SECURE_STORE_DESCRIPTION} returned no credential for the stored account; the keyring entry may have been removed externally.`
|
|
11
|
+
: outcome.reason === 'slot-unavailable'
|
|
12
|
+
? `${SECURE_STORE_DESCRIPTION} unavailable; could not read stored token (${outcome.detail})`
|
|
13
|
+
: `Access-slot read failed (${outcome.detail})`;
|
|
14
|
+
return new CliError('AUTH_STORE_READ_FAILED', message);
|
|
15
|
+
}
|
|
7
16
|
/**
|
|
8
17
|
* Multi-account `TokenStore` that keeps secrets in the OS credential manager
|
|
9
18
|
* and per-user metadata in the consumer's `UserRecordStore`. Falls back to a
|
|
@@ -131,43 +140,63 @@ export function createKeyringTokenStore(options) {
|
|
|
131
140
|
// best-effort
|
|
132
141
|
}
|
|
133
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Resolve the target record for `ref` (or the implicit default). Shared by
|
|
145
|
+
* `active` / `activeBundle`. The ref-only path skips `getDefaultId()` —
|
|
146
|
+
* `resolveTarget` never consults it when `ref` is supplied, so the extra
|
|
147
|
+
* read would be pure latency on every authenticated command.
|
|
148
|
+
*/
|
|
149
|
+
async function resolveRecord(ref) {
|
|
150
|
+
const snapshot = ref === undefined
|
|
151
|
+
? await readFullSnapshot()
|
|
152
|
+
: { records: await userRecords.list(), defaultId: null };
|
|
153
|
+
return resolveTarget(snapshot, ref);
|
|
154
|
+
}
|
|
134
155
|
return {
|
|
135
156
|
async active(ref) {
|
|
136
|
-
|
|
137
|
-
// touches it when `ref` is supplied, so the extra read would be
|
|
138
|
-
// pure latency on every authenticated command.
|
|
139
|
-
const snapshot = ref === undefined
|
|
140
|
-
? await readFullSnapshot()
|
|
141
|
-
: { records: await userRecords.list(), defaultId: null };
|
|
142
|
-
const record = resolveTarget(snapshot, ref);
|
|
157
|
+
const record = await resolveRecord(ref);
|
|
143
158
|
if (!record)
|
|
144
159
|
return null;
|
|
145
|
-
// Reads the access slot only. Refresh-state material lives in
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
160
|
+
// Reads the access slot only. Refresh-state material lives in the
|
|
161
|
+
// keyring + on the record, but `active()` stays cheap and returns
|
|
162
|
+
// the narrow snapshot shape — `activeBundle` lights up the refresh
|
|
163
|
+
// slot only when a caller actually needs it (silent refresh).
|
|
164
|
+
const outcome = await readAccessTokenForRecord(record, secureStoreFor(record.account));
|
|
165
|
+
if (outcome.ok)
|
|
166
|
+
return { token: outcome.token, account: record.account };
|
|
167
|
+
throw accessReadError(outcome);
|
|
168
|
+
},
|
|
169
|
+
async activeBundle(ref) {
|
|
170
|
+
const record = await resolveRecord(ref);
|
|
171
|
+
if (!record)
|
|
172
|
+
return null;
|
|
173
|
+
// Read both slots in parallel. The refresh side honours the
|
|
174
|
+
// `hasRefreshToken: false` gate inside `readRefreshTokenForRecord`,
|
|
175
|
+
// so an access-only record short-circuits without a refresh-slot
|
|
176
|
+
// IPC. Access-slot failures map to the same typed error as
|
|
177
|
+
// `active()`; a refresh-slot failure degrades silently — the
|
|
178
|
+
// bundle returns without `refreshToken` and the silent-refresh
|
|
179
|
+
// helper translates that to `AUTH_REFRESH_UNAVAILABLE`.
|
|
180
|
+
const [accessOutcome, refreshOutcome] = await Promise.all([
|
|
181
|
+
readAccessTokenForRecord(record, secureStoreFor(record.account)),
|
|
182
|
+
readRefreshTokenForRecord(record, refreshSecureStoreFor(record.account)),
|
|
183
|
+
]);
|
|
184
|
+
if (!accessOutcome.ok)
|
|
185
|
+
throw accessReadError(accessOutcome);
|
|
186
|
+
if (refreshOutcome.ok === false && refreshOutcome.reason === 'slot-error') {
|
|
187
|
+
throw new CliError('AUTH_STORE_READ_FAILED', `Refresh-slot read failed (${refreshOutcome.detail})`);
|
|
165
188
|
}
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
189
|
+
const bundle = {
|
|
190
|
+
accessToken: accessOutcome.token,
|
|
191
|
+
...(refreshOutcome.ok ? { refreshToken: refreshOutcome.token } : {}),
|
|
192
|
+
...(record.accessTokenExpiresAt !== undefined
|
|
193
|
+
? { accessTokenExpiresAt: record.accessTokenExpiresAt }
|
|
194
|
+
: {}),
|
|
195
|
+
...(record.refreshTokenExpiresAt !== undefined
|
|
196
|
+
? { refreshTokenExpiresAt: record.refreshTokenExpiresAt }
|
|
197
|
+
: {}),
|
|
198
|
+
};
|
|
199
|
+
return { account: record.account, bundle };
|
|
171
200
|
},
|
|
172
201
|
async set(account, token) {
|
|
173
202
|
// Reset the cached storage result up front so a caller that
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../../src/auth/keyring/token-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../../src/auth/keyring/token-store.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/persist.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthAccount, TokenBundle, TokenStore } from './types.js';
|
|
1
|
+
import type { AuthAccount, ExchangeResult, TokenBundle, TokenStore } from './types.js';
|
|
2
2
|
export type PersistBundleOptions<TAccount extends AuthAccount> = {
|
|
3
3
|
store: TokenStore<TAccount>;
|
|
4
4
|
account: TAccount;
|
|
@@ -19,5 +19,13 @@ export type PersistBundleOptions<TAccount extends AuthAccount> = {
|
|
|
19
19
|
* silent-refresh-safe selection (no re-pinning on background rotation)
|
|
20
20
|
* MUST implement `setBundle`.
|
|
21
21
|
*/
|
|
22
|
+
/**
|
|
23
|
+
* Build a `TokenBundle` from an `ExchangeResult`. `prev` carries the previous
|
|
24
|
+
* refresh token + its expiry forward when the server didn't reissue one (most
|
|
25
|
+
* don't on a refresh-grant). When the server DID return a new refresh token,
|
|
26
|
+
* its expiry is whatever the server gave (or unknown) — never the old token's,
|
|
27
|
+
* which would attach stale expiry metadata to a different credential.
|
|
28
|
+
*/
|
|
29
|
+
export declare function bundleFromExchange<TAccount extends AuthAccount>(exchange: ExchangeResult<TAccount>, prev?: TokenBundle): TokenBundle;
|
|
22
30
|
export declare function persistBundle<TAccount extends AuthAccount>(options: PersistBundleOptions<TAccount>): Promise<void>;
|
|
23
31
|
//# sourceMappingURL=persist.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/auth/persist.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/auth/persist.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEtF,MAAM,MAAM,oBAAoB,CAAC,QAAQ,SAAS,WAAW,IAAI;IAC7D,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC3B,OAAO,EAAE,QAAQ,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;IACnB,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B,CAAA;AAED;;;;;;;;;;;;GAYG;AACH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,SAAS,WAAW,EAC3D,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC,EAClC,IAAI,CAAC,EAAE,WAAW,GACnB,WAAW,CAYb;AAED,wBAAsB,aAAa,CAAC,QAAQ,SAAS,WAAW,EAC5D,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC,GACxC,OAAO,CAAC,IAAI,CAAC,CAqBf"}
|
package/dist/auth/persist.js
CHANGED
|
@@ -12,6 +12,26 @@ import { CliError, getErrorMessage } from '../errors.js';
|
|
|
12
12
|
* silent-refresh-safe selection (no re-pinning on background rotation)
|
|
13
13
|
* MUST implement `setBundle`.
|
|
14
14
|
*/
|
|
15
|
+
/**
|
|
16
|
+
* Build a `TokenBundle` from an `ExchangeResult`. `prev` carries the previous
|
|
17
|
+
* refresh token + its expiry forward when the server didn't reissue one (most
|
|
18
|
+
* don't on a refresh-grant). When the server DID return a new refresh token,
|
|
19
|
+
* its expiry is whatever the server gave (or unknown) — never the old token's,
|
|
20
|
+
* which would attach stale expiry metadata to a different credential.
|
|
21
|
+
*/
|
|
22
|
+
export function bundleFromExchange(exchange, prev) {
|
|
23
|
+
const rotatedRefresh = exchange.refreshToken !== undefined;
|
|
24
|
+
const refreshToken = exchange.refreshToken ?? prev?.refreshToken;
|
|
25
|
+
const refreshTokenExpiresAt = rotatedRefresh
|
|
26
|
+
? exchange.refreshTokenExpiresAt
|
|
27
|
+
: (exchange.refreshTokenExpiresAt ?? prev?.refreshTokenExpiresAt);
|
|
28
|
+
return {
|
|
29
|
+
accessToken: exchange.accessToken,
|
|
30
|
+
...(refreshToken !== undefined ? { refreshToken } : {}),
|
|
31
|
+
...(exchange.expiresAt !== undefined ? { accessTokenExpiresAt: exchange.expiresAt } : {}),
|
|
32
|
+
...(refreshTokenExpiresAt !== undefined ? { refreshTokenExpiresAt } : {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
15
35
|
export async function persistBundle(options) {
|
|
16
36
|
const { store, account, bundle, promoteDefault } = options;
|
|
17
37
|
try {
|
package/dist/auth/persist.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persist.js","sourceRoot":"","sources":["../../src/auth/persist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAWxD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAC/B,OAAuC;IAEvC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAA;IAC1D,IAAI,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAClB,6DAA6D;YAC7D,4DAA4D;YAC5D,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YAC1C,CAAC;iBAAM,CAAC;gBACJ,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,CAAC,CAAA;YAC9D,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;QAChD,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,QAAQ;YAAE,MAAM,KAAK,CAAA;QAC1C,MAAM,IAAI,QAAQ,CACd,yBAAyB,EACzB,4BAA4B,eAAe,CAAC,KAAK,CAAC,EAAE,CACvD,CAAA;IACL,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"persist.js","sourceRoot":"","sources":["../../src/auth/persist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAWxD;;;;;;;;;;;;GAYG;AACH;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAC9B,QAAkC,EAClC,IAAkB;IAElB,MAAM,cAAc,GAAG,QAAQ,CAAC,YAAY,KAAK,SAAS,CAAA;IAC1D,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,IAAI,IAAI,EAAE,YAAY,CAAA;IAChE,MAAM,qBAAqB,GAAG,cAAc;QACxC,CAAC,CAAC,QAAQ,CAAC,qBAAqB;QAChC,CAAC,CAAC,CAAC,QAAQ,CAAC,qBAAqB,IAAI,IAAI,EAAE,qBAAqB,CAAC,CAAA;IACrE,OAAO;QACH,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzF,GAAG,CAAC,qBAAqB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5E,CAAA;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAC/B,OAAuC;IAEvC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAA;IAC1D,IAAI,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAClB,6DAA6D;YAC7D,4DAA4D;YAC5D,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YAC1C,CAAC;iBAAM,CAAC;gBACJ,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,CAAC,CAAA;YAC9D,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;QAChD,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,QAAQ;YAAE,MAAM,KAAK,CAAA;QAC1C,MAAM,IAAI,QAAQ,CACd,yBAAyB,EACzB,4BAA4B,eAAe,CAAC,KAAK,CAAC,EAAE,CACvD,CAAA;IACL,CAAC;AACL,CAAC"}
|
|
@@ -7,7 +7,7 @@ import type { AuthAccount, AuthProvider, ValidateInput } from '../types.js';
|
|
|
7
7
|
export type PkceLazyString = string | ((ctx: {
|
|
8
8
|
handshake: Record<string, unknown>;
|
|
9
9
|
flags: Record<string, unknown>;
|
|
10
|
-
}) => string);
|
|
10
|
+
}) => string | Promise<string>);
|
|
11
11
|
export type PkceProviderOptions<TAccount extends AuthAccount = AuthAccount> = {
|
|
12
12
|
/** OAuth 2.0 authorize endpoint. Function form supports per-flow base URLs (Outline self-hosted). */
|
|
13
13
|
authorizeUrl: PkceLazyString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../../src/auth/providers/pkce.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../../src/auth/providers/pkce.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,WAAW,EACX,YAAY,EAMZ,aAAa,EAChB,MAAM,aAAa,CAAA;AAWpB;;;;GAIG;AACH,MAAM,MAAM,cAAc,GACpB,MAAM,GACN,CAAC,CAAC,GAAG,EAAE;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;AAErC,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,GAAG,WAAW,IAAI;IAC1E,qGAAqG;IACrG,YAAY,EAAE,cAAc,CAAA;IAC5B,2EAA2E;IAC3E,QAAQ,EAAE,cAAc,CAAA;IACxB,mFAAmF;IACnF,QAAQ,EAAE,cAAc,CAAA;IACxB,iGAAiG;IACjG,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,kBAAkB;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,0FAA0F;IAC1F,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IACrD,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAC3B,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,SAAS,WAAW,EAC3D,OAAO,EAAE,mBAAmB,CAAC,QAAQ,CAAC,GACvC,YAAY,CAAC,QAAQ,CAAC,CAsLxB"}
|