@nebulr-group/bridge-cli 0.4.4 → 0.5.1-beta.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 +67 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +13 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/auth/logout.command.d.ts +10 -3
- package/dist/commands/auth/logout.command.d.ts.map +1 -1
- package/dist/commands/auth/logout.command.js +58 -18
- package/dist/commands/auth/logout.command.js.map +1 -1
- package/dist/commands/auth/status.command.d.ts +4 -0
- package/dist/commands/auth/status.command.d.ts.map +1 -1
- package/dist/commands/auth/status.command.js +50 -19
- package/dist/commands/auth/status.command.js.map +1 -1
- package/dist/commands/auth/use.command.d.ts +17 -0
- package/dist/commands/auth/use.command.d.ts.map +1 -0
- package/dist/commands/auth/use.command.js +47 -0
- package/dist/commands/auth/use.command.js.map +1 -0
- package/dist/commands/auth.command.d.ts +1 -0
- package/dist/commands/auth.command.d.ts.map +1 -1
- package/dist/commands/auth.command.js +3 -0
- package/dist/commands/auth.command.js.map +1 -1
- package/dist/commands/setup.command.d.ts +60 -0
- package/dist/commands/setup.command.d.ts.map +1 -1
- package/dist/commands/setup.command.js +129 -28
- package/dist/commands/setup.command.js.map +1 -1
- package/dist/commands/stripe.command.d.ts +36 -0
- package/dist/commands/stripe.command.d.ts.map +1 -1
- package/dist/commands/stripe.command.js +70 -14
- package/dist/commands/stripe.command.js.map +1 -1
- package/dist/config.d.ts +20 -13
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +120 -32
- package/dist/config.js.map +1 -1
- package/dist/credentials.d.ts +68 -5
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +202 -11
- package/dist/credentials.js.map +1 -1
- package/dist/prompts/billing/master.md +3 -0
- package/package.json +1 -1
package/dist/credentials.d.ts
CHANGED
|
@@ -20,6 +20,21 @@ export interface StoredCredentials {
|
|
|
20
20
|
/** Optional human-friendly label set via `bridge auth login --label`. */
|
|
21
21
|
label?: string;
|
|
22
22
|
}
|
|
23
|
+
/** Current on-disk shape. See the module docstring for why it is a map. */
|
|
24
|
+
export interface CredentialsFile {
|
|
25
|
+
version: 2;
|
|
26
|
+
/** App id of the credential commands use by default. `null` when empty. */
|
|
27
|
+
active: string | null;
|
|
28
|
+
/** All stored credentials, keyed by `app.id`. */
|
|
29
|
+
credentials: Record<string, StoredCredentials>;
|
|
30
|
+
}
|
|
31
|
+
/** One entry, as `bridge auth status` and the selector logic see it. */
|
|
32
|
+
export interface CredentialEntry {
|
|
33
|
+
/** The map key — always `creds.app.id`. */
|
|
34
|
+
key: string;
|
|
35
|
+
creds: StoredCredentials;
|
|
36
|
+
isActive: boolean;
|
|
37
|
+
}
|
|
23
38
|
/**
|
|
24
39
|
* Returns the absolute path to the credentials file based on the current
|
|
25
40
|
* environment. Does not create directories or files — pure path resolution.
|
|
@@ -37,17 +52,65 @@ export interface StoredCredentials {
|
|
|
37
52
|
*/
|
|
38
53
|
export declare function credentialsPath(): string;
|
|
39
54
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
55
|
+
* Read the whole store, migrating a v1 file in memory. `null` if no file.
|
|
56
|
+
*
|
|
57
|
+
* Throws if the file exists but is unreadable or malformed — a corrupt store is
|
|
58
|
+
* not the same as an absent one, and silently treating it as absent would make
|
|
59
|
+
* `bridge auth status` report "not logged in" to somebody who very much is.
|
|
60
|
+
*/
|
|
61
|
+
export declare function readCredentialsFile(): CredentialsFile | null;
|
|
62
|
+
/**
|
|
63
|
+
* The credential commands act on by default: the active one.
|
|
64
|
+
*
|
|
65
|
+
* Kept with its original name and signature because every existing caller wants
|
|
66
|
+
* exactly this, and because "which credential is in force" is a question with
|
|
67
|
+
* one answer whether the file holds one app or ten.
|
|
42
68
|
*/
|
|
43
69
|
export declare function readCredentials(): StoredCredentials | null;
|
|
70
|
+
/** Every stored credential, active one first, then by app name. */
|
|
71
|
+
export declare function listCredentials(): CredentialEntry[];
|
|
72
|
+
/** Raised when a selector matches nothing, or matches more than one entry. */
|
|
73
|
+
export declare class CredentialSelectorError extends Error {
|
|
74
|
+
constructor(message: string);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Find one stored credential by label, app id, or app name.
|
|
78
|
+
*
|
|
79
|
+
* Label first: users think in environments, not in 24-character object ids, and
|
|
80
|
+
* `--label` exists precisely so they can name one. App id is exact and always
|
|
81
|
+
* works. App name is last because two apps may share one.
|
|
82
|
+
*
|
|
83
|
+
* An ambiguous selector is an ERROR, never a first match. Picking one of two
|
|
84
|
+
* candidate apps silently is the whole failure mode this ticket is about.
|
|
85
|
+
*/
|
|
86
|
+
export declare function findCredential(selector: string): CredentialEntry;
|
|
44
87
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
88
|
+
* Upsert a credential by app id and make it active.
|
|
89
|
+
*
|
|
90
|
+
* Same name and signature as before: `bridge auth login` still ends with one
|
|
91
|
+
* call, and still leaves the app it just authorised in force.
|
|
47
92
|
*/
|
|
48
93
|
export declare function writeCredentials(creds: StoredCredentials): void;
|
|
94
|
+
/** Point the persisted default at an already-stored credential. Offline. */
|
|
95
|
+
export declare function setActiveCredential(key: string): void;
|
|
96
|
+
/** Persist the store atomically with mode 0600, dir 0700. */
|
|
97
|
+
export declare function writeCredentialsFile(file: CredentialsFile): void;
|
|
49
98
|
/**
|
|
50
|
-
* Deletes the
|
|
99
|
+
* Remove ONE credential. Deletes the file entirely when it was the last.
|
|
100
|
+
*
|
|
101
|
+
* Returns the remaining count so a caller can tell the user what is left.
|
|
102
|
+
* Removing the active one moves `active` to another entry rather than leaving a
|
|
103
|
+
* dangling pointer — with credentials still stored, "logged out of everything"
|
|
104
|
+
* would be a lie.
|
|
105
|
+
*/
|
|
106
|
+
export declare function removeCredential(key: string): number;
|
|
107
|
+
/** Delete the whole credentials file. No-op if it does not exist. */
|
|
108
|
+
export declare function deleteAllCredentials(): void;
|
|
109
|
+
/**
|
|
110
|
+
* Back-compat alias for the single-app era: remove the active credential.
|
|
111
|
+
*
|
|
112
|
+
* @deprecated Prefer `removeCredential(key)` or `deleteAllCredentials()`, which
|
|
113
|
+
* say which of the two things they do.
|
|
51
114
|
*/
|
|
52
115
|
export declare function deleteCredentials(): void;
|
|
53
116
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,GAAG,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,qCAAqC;IACrC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,2EAA2E;IAC3E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAChD;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,iBAAiB,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAQxC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,eAAe,GAAG,IAAI,CAyB5D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,IAAI,iBAAiB,GAAG,IAAI,CAU1D;AAED,mEAAmE;AACnE,wBAAgB,eAAe,IAAI,eAAe,EAAE,CASnD;AAED,8EAA8E;AAC9E,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAmChE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAK/D;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAOrD;AAED,6DAA6D;AAC7D,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA4BhE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWpD;AAED,qEAAqE;AACrE,wBAAgB,oBAAoB,IAAI,IAAI,CAQ3C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAOxC;AAsBD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,GAAE,IAAiB,GAAG,OAAO,CAInF"}
|
package/dist/credentials.js
CHANGED
|
@@ -10,6 +10,34 @@
|
|
|
10
10
|
* 2. `~/.config/bridge/credentials.json` otherwise
|
|
11
11
|
*
|
|
12
12
|
* File mode: 0600 (owner read/write only). Containing dir created with 0700.
|
|
13
|
+
*
|
|
14
|
+
* ## The file holds MANY apps (TBP-628)
|
|
15
|
+
*
|
|
16
|
+
* It used to hold exactly one. Anyone running the same product as several apps
|
|
17
|
+
* — one appId per environment — had to `logout` + `login` through the browser
|
|
18
|
+
* to move between them, even though the token they already held had days left
|
|
19
|
+
* on it. Worse, nothing in a read command's output said which app answered, so
|
|
20
|
+
* a session holding a prod token could run `role list` believing it described
|
|
21
|
+
* local, and the next step would have rewritten production roles.
|
|
22
|
+
*
|
|
23
|
+
* So the on-disk shape is now a map keyed by app id, plus a pointer at the
|
|
24
|
+
* active one:
|
|
25
|
+
*
|
|
26
|
+
* ```json
|
|
27
|
+
* {
|
|
28
|
+
* "version": 2,
|
|
29
|
+
* "active": "606b4416fabdc800087d09ec",
|
|
30
|
+
* "credentials": { "606b4416fabdc800087d09ec": { …StoredCredentials } }
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Keyed by app id, not by label: the label is optional and user-chosen, so it
|
|
35
|
+
* is a fine way to SELECT a credential and a bad way to key one.
|
|
36
|
+
*
|
|
37
|
+
* A v1 file (a bare `StoredCredentials` object) is migrated on read, in memory
|
|
38
|
+
* only. Reading never rewrites the file — a read command must not mutate state
|
|
39
|
+
* another process is reading. The v2 shape is persisted the next time
|
|
40
|
+
* something writes.
|
|
13
41
|
*/
|
|
14
42
|
import * as fs from 'node:fs';
|
|
15
43
|
import * as path from 'node:path';
|
|
@@ -39,10 +67,13 @@ export function credentialsPath() {
|
|
|
39
67
|
return path.join(base, '.config', 'bridge', 'credentials.json');
|
|
40
68
|
}
|
|
41
69
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
70
|
+
* Read the whole store, migrating a v1 file in memory. `null` if no file.
|
|
71
|
+
*
|
|
72
|
+
* Throws if the file exists but is unreadable or malformed — a corrupt store is
|
|
73
|
+
* not the same as an absent one, and silently treating it as absent would make
|
|
74
|
+
* `bridge auth status` report "not logged in" to somebody who very much is.
|
|
44
75
|
*/
|
|
45
|
-
export function
|
|
76
|
+
export function readCredentialsFile() {
|
|
46
77
|
const filePath = credentialsPath();
|
|
47
78
|
if (!fs.existsSync(filePath))
|
|
48
79
|
return null;
|
|
@@ -54,16 +85,120 @@ export function readCredentials() {
|
|
|
54
85
|
catch {
|
|
55
86
|
throw new Error(`Credentials file at ${filePath} is not valid JSON.`);
|
|
56
87
|
}
|
|
57
|
-
|
|
58
|
-
|
|
88
|
+
// v2 — the current shape.
|
|
89
|
+
if (isCredentialsFile(parsed))
|
|
90
|
+
return parsed;
|
|
91
|
+
// v1 — a bare StoredCredentials object. Migrate in memory; do NOT write.
|
|
92
|
+
if (isStoredCredentials(parsed)) {
|
|
93
|
+
return {
|
|
94
|
+
version: 2,
|
|
95
|
+
active: parsed.app.id,
|
|
96
|
+
credentials: { [parsed.app.id]: parsed },
|
|
97
|
+
};
|
|
59
98
|
}
|
|
60
|
-
|
|
99
|
+
throw new Error(`Credentials file at ${filePath} is missing required fields.`);
|
|
61
100
|
}
|
|
62
101
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
102
|
+
* The credential commands act on by default: the active one.
|
|
103
|
+
*
|
|
104
|
+
* Kept with its original name and signature because every existing caller wants
|
|
105
|
+
* exactly this, and because "which credential is in force" is a question with
|
|
106
|
+
* one answer whether the file holds one app or ten.
|
|
107
|
+
*/
|
|
108
|
+
export function readCredentials() {
|
|
109
|
+
const file = readCredentialsFile();
|
|
110
|
+
if (!file)
|
|
111
|
+
return null;
|
|
112
|
+
if (file.active && file.credentials[file.active])
|
|
113
|
+
return file.credentials[file.active];
|
|
114
|
+
// A pointer at a credential that is gone. Fall back to the only entry if
|
|
115
|
+
// there is exactly one — otherwise there is no defensible default, and
|
|
116
|
+
// guessing would pick an app on the user's behalf, which is the failure this
|
|
117
|
+
// ticket exists to stop.
|
|
118
|
+
const keys = Object.keys(file.credentials);
|
|
119
|
+
return keys.length === 1 ? file.credentials[keys[0]] : null;
|
|
120
|
+
}
|
|
121
|
+
/** Every stored credential, active one first, then by app name. */
|
|
122
|
+
export function listCredentials() {
|
|
123
|
+
const file = readCredentialsFile();
|
|
124
|
+
if (!file)
|
|
125
|
+
return [];
|
|
126
|
+
return Object.entries(file.credentials)
|
|
127
|
+
.map(([key, creds]) => ({ key, creds, isActive: key === file.active }))
|
|
128
|
+
.sort((a, b) => {
|
|
129
|
+
if (a.isActive !== b.isActive)
|
|
130
|
+
return a.isActive ? -1 : 1;
|
|
131
|
+
return a.creds.app.name.localeCompare(b.creds.app.name);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/** Raised when a selector matches nothing, or matches more than one entry. */
|
|
135
|
+
export class CredentialSelectorError extends Error {
|
|
136
|
+
constructor(message) {
|
|
137
|
+
super(message);
|
|
138
|
+
this.name = 'CredentialSelectorError';
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Find one stored credential by label, app id, or app name.
|
|
143
|
+
*
|
|
144
|
+
* Label first: users think in environments, not in 24-character object ids, and
|
|
145
|
+
* `--label` exists precisely so they can name one. App id is exact and always
|
|
146
|
+
* works. App name is last because two apps may share one.
|
|
147
|
+
*
|
|
148
|
+
* An ambiguous selector is an ERROR, never a first match. Picking one of two
|
|
149
|
+
* candidate apps silently is the whole failure mode this ticket is about.
|
|
150
|
+
*/
|
|
151
|
+
export function findCredential(selector) {
|
|
152
|
+
const needle = selector.trim();
|
|
153
|
+
if (!needle)
|
|
154
|
+
throw new CredentialSelectorError('Empty profile selector.');
|
|
155
|
+
const entries = listCredentials();
|
|
156
|
+
if (entries.length === 0) {
|
|
157
|
+
throw new CredentialSelectorError('No stored credentials. Run `bridge auth login` first.');
|
|
158
|
+
}
|
|
159
|
+
const lower = needle.toLowerCase();
|
|
160
|
+
const byLabel = entries.filter((e) => e.creds.label?.toLowerCase() === lower);
|
|
161
|
+
const byId = entries.filter((e) => e.key === needle);
|
|
162
|
+
const byName = entries.filter((e) => e.creds.app.name.toLowerCase() === lower);
|
|
163
|
+
for (const [what, matches] of [
|
|
164
|
+
['label', byLabel],
|
|
165
|
+
['app id', byId],
|
|
166
|
+
['app name', byName],
|
|
167
|
+
]) {
|
|
168
|
+
if (matches.length === 1)
|
|
169
|
+
return matches[0];
|
|
170
|
+
if (matches.length > 1) {
|
|
171
|
+
throw new CredentialSelectorError(`"${needle}" matches ${matches.length} stored credentials by ${what} ` +
|
|
172
|
+
`(${matches.map((m) => m.key).join(', ')}). Select by app id instead.`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
throw new CredentialSelectorError(`No stored credential matches "${needle}". Known: ` +
|
|
176
|
+
entries.map((e) => e.creds.label ?? e.creds.app.name).join(', ') +
|
|
177
|
+
'. Run `bridge auth status` to see them all.');
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Upsert a credential by app id and make it active.
|
|
181
|
+
*
|
|
182
|
+
* Same name and signature as before: `bridge auth login` still ends with one
|
|
183
|
+
* call, and still leaves the app it just authorised in force.
|
|
65
184
|
*/
|
|
66
185
|
export function writeCredentials(creds) {
|
|
186
|
+
const file = readCredentialsFileOrEmpty();
|
|
187
|
+
file.credentials[creds.app.id] = creds;
|
|
188
|
+
file.active = creds.app.id;
|
|
189
|
+
writeCredentialsFile(file);
|
|
190
|
+
}
|
|
191
|
+
/** Point the persisted default at an already-stored credential. Offline. */
|
|
192
|
+
export function setActiveCredential(key) {
|
|
193
|
+
const file = readCredentialsFileOrEmpty();
|
|
194
|
+
if (!file.credentials[key]) {
|
|
195
|
+
throw new CredentialSelectorError(`No stored credential with app id ${key}.`);
|
|
196
|
+
}
|
|
197
|
+
file.active = key;
|
|
198
|
+
writeCredentialsFile(file);
|
|
199
|
+
}
|
|
200
|
+
/** Persist the store atomically with mode 0600, dir 0700. */
|
|
201
|
+
export function writeCredentialsFile(file) {
|
|
67
202
|
const filePath = credentialsPath();
|
|
68
203
|
const dir = path.dirname(filePath);
|
|
69
204
|
// Create dir with restrictive perms. mkdirSync `mode` is masked by umask, so
|
|
@@ -80,7 +215,7 @@ export function writeCredentials(creds) {
|
|
|
80
215
|
const tmpPath = `${filePath}.${process.pid}.tmp`;
|
|
81
216
|
const fd = fs.openSync(tmpPath, 'w', 0o600);
|
|
82
217
|
try {
|
|
83
|
-
fs.writeFileSync(fd, JSON.stringify(
|
|
218
|
+
fs.writeFileSync(fd, JSON.stringify(file, null, 2) + '\n');
|
|
84
219
|
}
|
|
85
220
|
finally {
|
|
86
221
|
fs.closeSync(fd);
|
|
@@ -94,9 +229,28 @@ export function writeCredentials(creds) {
|
|
|
94
229
|
fs.renameSync(tmpPath, filePath);
|
|
95
230
|
}
|
|
96
231
|
/**
|
|
97
|
-
* Deletes the
|
|
232
|
+
* Remove ONE credential. Deletes the file entirely when it was the last.
|
|
233
|
+
*
|
|
234
|
+
* Returns the remaining count so a caller can tell the user what is left.
|
|
235
|
+
* Removing the active one moves `active` to another entry rather than leaving a
|
|
236
|
+
* dangling pointer — with credentials still stored, "logged out of everything"
|
|
237
|
+
* would be a lie.
|
|
98
238
|
*/
|
|
99
|
-
export function
|
|
239
|
+
export function removeCredential(key) {
|
|
240
|
+
const file = readCredentialsFileOrEmpty();
|
|
241
|
+
delete file.credentials[key];
|
|
242
|
+
const remaining = Object.keys(file.credentials);
|
|
243
|
+
if (remaining.length === 0) {
|
|
244
|
+
deleteAllCredentials();
|
|
245
|
+
return 0;
|
|
246
|
+
}
|
|
247
|
+
if (file.active === key)
|
|
248
|
+
file.active = remaining[0];
|
|
249
|
+
writeCredentialsFile(file);
|
|
250
|
+
return remaining.length;
|
|
251
|
+
}
|
|
252
|
+
/** Delete the whole credentials file. No-op if it does not exist. */
|
|
253
|
+
export function deleteAllCredentials() {
|
|
100
254
|
const filePath = credentialsPath();
|
|
101
255
|
try {
|
|
102
256
|
fs.unlinkSync(filePath);
|
|
@@ -107,6 +261,43 @@ export function deleteCredentials() {
|
|
|
107
261
|
throw err;
|
|
108
262
|
}
|
|
109
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Back-compat alias for the single-app era: remove the active credential.
|
|
266
|
+
*
|
|
267
|
+
* @deprecated Prefer `removeCredential(key)` or `deleteAllCredentials()`, which
|
|
268
|
+
* say which of the two things they do.
|
|
269
|
+
*/
|
|
270
|
+
export function deleteCredentials() {
|
|
271
|
+
const file = readCredentialsFileOrEmpty();
|
|
272
|
+
if (file.active) {
|
|
273
|
+
removeCredential(file.active);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
deleteAllCredentials();
|
|
277
|
+
}
|
|
278
|
+
/** The store, or an empty one — for the write paths, which create on demand. */
|
|
279
|
+
function readCredentialsFileOrEmpty() {
|
|
280
|
+
try {
|
|
281
|
+
return readCredentialsFile() ?? { version: 2, active: null, credentials: {} };
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// A corrupt file must not wedge `login` — overwriting it is how the user
|
|
285
|
+
// gets unstuck, and the token in it is unusable anyway.
|
|
286
|
+
return { version: 2, active: null, credentials: {} };
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function isCredentialsFile(value) {
|
|
290
|
+
if (!value || typeof value !== 'object')
|
|
291
|
+
return false;
|
|
292
|
+
const v = value;
|
|
293
|
+
if (v.version !== 2)
|
|
294
|
+
return false;
|
|
295
|
+
if (v.active !== null && typeof v.active !== 'string')
|
|
296
|
+
return false;
|
|
297
|
+
if (!v.credentials || typeof v.credentials !== 'object')
|
|
298
|
+
return false;
|
|
299
|
+
return Object.values(v.credentials).every(isStoredCredentials);
|
|
300
|
+
}
|
|
110
301
|
/**
|
|
111
302
|
* True if the credentials' `expiresAt` is in the past relative to `now`.
|
|
112
303
|
*/
|
package/dist/credentials.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -127,6 +127,9 @@ If any plan will have a price, connect Stripe **before** setting prices (so each
|
|
|
127
127
|
bridge stripe status
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
+
If it reports `webhookHealthy: false`, checkout still works but subscription changes, cancellations
|
|
131
|
+
and payment failures will not sync. Tell the developer and follow the repair hint in `message`.
|
|
132
|
+
|
|
130
133
|
If not connected, ask the developer for their Stripe keys (from `dashboard.stripe.com/apikeys`):
|
|
131
134
|
|
|
132
135
|
```bash
|