@vigilbase/cli 0.1.3 → 0.2.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/CLOUDFLARE.md +2 -0
- package/COMMANDS.md +43 -6
- package/LOCAL.md +731 -0
- package/README.md +58 -6
- package/dist/auth/device-auth.d.ts.map +1 -1
- package/dist/auth/device-auth.js +7 -3
- package/dist/auth/device-auth.js.map +1 -1
- package/dist/auth/index.d.ts +3 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +2 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/provider.d.ts +18 -0
- package/dist/auth/provider.d.ts.map +1 -0
- package/dist/auth/provider.js +62 -0
- package/dist/auth/provider.js.map +1 -0
- package/dist/auth/refresh.d.ts +10 -0
- package/dist/auth/refresh.d.ts.map +1 -0
- package/dist/auth/refresh.js +143 -0
- package/dist/auth/refresh.js.map +1 -0
- package/dist/auth/store.d.ts +27 -2
- package/dist/auth/store.d.ts.map +1 -1
- package/dist/auth/store.js +23 -8
- package/dist/auth/store.js.map +1 -1
- package/dist/auth/token-metadata.d.ts +10 -0
- package/dist/auth/token-metadata.d.ts.map +1 -0
- package/dist/auth/token-metadata.js +22 -0
- package/dist/auth/token-metadata.js.map +1 -0
- package/dist/auth/types.d.ts +8 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +40 -9
- package/dist/cli.js.map +1 -1
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +20 -8
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/helpers.d.ts +15 -0
- package/dist/commands/helpers.d.ts.map +1 -1
- package/dist/commands/helpers.js +2 -2
- package/dist/commands/helpers.js.map +1 -1
- package/dist/commands/index.d.ts +3 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +6 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/local.d.ts +30 -0
- package/dist/commands/local.d.ts.map +1 -0
- package/dist/commands/local.js +1520 -0
- package/dist/commands/local.js.map +1 -0
- package/dist/commands/public-tools.d.ts.map +1 -1
- package/dist/commands/public-tools.js +8 -4
- package/dist/commands/public-tools.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/config.d.ts +16 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +36 -4
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/format.d.ts.map +1 -1
- package/dist/lib/format.js +9 -0
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/help.d.ts +1 -1
- package/dist/lib/help.d.ts.map +1 -1
- package/dist/lib/help.js +9 -0
- package/dist/lib/help.js.map +1 -1
- package/dist/lib/network.d.ts.map +1 -1
- package/dist/lib/network.js +2 -1
- package/dist/lib/network.js.map +1 -1
- package/dist/lib/one-client.d.ts +3 -2
- package/dist/lib/one-client.d.ts.map +1 -1
- package/dist/lib/one-client.js +46 -2
- package/dist/lib/one-client.js.map +1 -1
- package/dist/lib/security-client.d.ts +1 -1
- package/dist/lib/tui.d.ts +309 -0
- package/dist/lib/tui.d.ts.map +1 -0
- package/dist/lib/tui.js +847 -0
- package/dist/lib/tui.js.map +1 -0
- package/dist/local/cloudflare-checkup/cf/allowlist.d.ts +95 -0
- package/dist/local/cloudflare-checkup/cf/allowlist.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/cf/allowlist.js +184 -0
- package/dist/local/cloudflare-checkup/cf/allowlist.js.map +1 -0
- package/dist/local/cloudflare-checkup/cf/auth-lifecycle.d.ts +113 -0
- package/dist/local/cloudflare-checkup/cf/auth-lifecycle.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/cf/auth-lifecycle.js +313 -0
- package/dist/local/cloudflare-checkup/cf/auth-lifecycle.js.map +1 -0
- package/dist/local/cloudflare-checkup/cf/child-env.d.ts +32 -0
- package/dist/local/cloudflare-checkup/cf/child-env.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/cf/child-env.js +81 -0
- package/dist/local/cloudflare-checkup/cf/child-env.js.map +1 -0
- package/dist/local/cloudflare-checkup/cf/install.d.ts +106 -0
- package/dist/local/cloudflare-checkup/cf/install.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/cf/install.js +309 -0
- package/dist/local/cloudflare-checkup/cf/install.js.map +1 -0
- package/dist/local/cloudflare-checkup/cf/locate.d.ts +44 -0
- package/dist/local/cloudflare-checkup/cf/locate.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/cf/locate.js +228 -0
- package/dist/local/cloudflare-checkup/cf/locate.js.map +1 -0
- package/dist/local/cloudflare-checkup/cf/run-cf.d.ts +89 -0
- package/dist/local/cloudflare-checkup/cf/run-cf.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/cf/run-cf.js +275 -0
- package/dist/local/cloudflare-checkup/cf/run-cf.js.map +1 -0
- package/dist/local/cloudflare-checkup/collector.d.ts +48 -0
- package/dist/local/cloudflare-checkup/collector.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/collector.js +296 -0
- package/dist/local/cloudflare-checkup/collector.js.map +1 -0
- package/dist/local/cloudflare-checkup/contract.d.ts +2793 -0
- package/dist/local/cloudflare-checkup/contract.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/contract.js +1614 -0
- package/dist/local/cloudflare-checkup/contract.js.map +1 -0
- package/dist/local/cloudflare-checkup/email-verification.d.ts +125 -0
- package/dist/local/cloudflare-checkup/email-verification.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/email-verification.js +212 -0
- package/dist/local/cloudflare-checkup/email-verification.js.map +1 -0
- package/dist/local/cloudflare-checkup/errors.d.ts +28 -0
- package/dist/local/cloudflare-checkup/errors.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/errors.js +99 -0
- package/dist/local/cloudflare-checkup/errors.js.map +1 -0
- package/dist/local/cloudflare-checkup/output.d.ts +24 -0
- package/dist/local/cloudflare-checkup/output.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/output.js +89 -0
- package/dist/local/cloudflare-checkup/output.js.map +1 -0
- package/dist/local/cloudflare-checkup/prompts.d.ts +41 -0
- package/dist/local/cloudflare-checkup/prompts.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/prompts.js +140 -0
- package/dist/local/cloudflare-checkup/prompts.js.map +1 -0
- package/dist/local/cloudflare-checkup/rate-budget.d.ts +42 -0
- package/dist/local/cloudflare-checkup/rate-budget.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/rate-budget.js +80 -0
- package/dist/local/cloudflare-checkup/rate-budget.js.map +1 -0
- package/dist/local/cloudflare-checkup/snapshot-file.d.ts +53 -0
- package/dist/local/cloudflare-checkup/snapshot-file.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/snapshot-file.js +186 -0
- package/dist/local/cloudflare-checkup/snapshot-file.js.map +1 -0
- package/dist/local/cloudflare-checkup/submit-client.d.ts +98 -0
- package/dist/local/cloudflare-checkup/submit-client.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/submit-client.js +349 -0
- package/dist/local/cloudflare-checkup/submit-client.js.map +1 -0
- package/dist/local/cloudflare-checkup/terminal-ui.d.ts +171 -0
- package/dist/local/cloudflare-checkup/terminal-ui.d.ts.map +1 -0
- package/dist/local/cloudflare-checkup/terminal-ui.js +404 -0
- package/dist/local/cloudflare-checkup/terminal-ui.js.map +1 -0
- package/package.json +8 -4
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cf authentication lifecycle and call scheduling (spec §F3, §F5).
|
|
3
|
+
*
|
|
4
|
+
* cf refreshes an OAuth token only once it has expired (`now >= expiry`), per
|
|
5
|
+
* process and without a lock, so concurrent cf processes near expiry could
|
|
6
|
+
* race a rotating refresh token. The scheduler therefore:
|
|
7
|
+
* - runs one serial `cf auth whoami` before any fan-out (it performs any due
|
|
8
|
+
* refresh and reports `expiresAt`; `tokenValid` is ignored, cf issue #21);
|
|
9
|
+
* - in profile and default modes, stops dispatching when `now ≥ expiresAt − 60 s`,
|
|
10
|
+
* lets in-flight calls drain (each is capped at 45 s), sleeps until
|
|
11
|
+
* `expiresAt + 1 s` and runs up to two serial `whoami` calls, then resumes.
|
|
12
|
+
* The first performs the single refresh; cf 1.0.0-beta.13 reads the
|
|
13
|
+
* credential file before its token getter refreshes, so that call prints the
|
|
14
|
+
* old (passed) expiry and a second serial `whoami` reads the new one;
|
|
15
|
+
* - on a 401 pauses dispatch, runs one serial `whoami` (plus the re-read when
|
|
16
|
+
* it reports a passed expiry) and retries once;
|
|
17
|
+
* - on a 429 pauses every worker for 30 s and retries once; a second 429
|
|
18
|
+
* aborts with CF_RATE_LIMITED;
|
|
19
|
+
* - retries 5xx, network errors and timeouts twice (after 1 s, then 3 s);
|
|
20
|
+
* - spends the request budget for every API call, including `whoami`.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
import { RECOMMENDED_CF_SCOPES } from '../contract.js';
|
|
24
|
+
import { LocalCheckupError, ENV_TOKEN_AUTH_HINT } from '../errors.js';
|
|
25
|
+
import { classifyCfStderr } from './run-cf.js';
|
|
26
|
+
export const PRE_EXPIRY_MARGIN_MS = 60_000;
|
|
27
|
+
export const RATE_LIMIT_PAUSE_MS = 30_000;
|
|
28
|
+
export const TRANSIENT_RETRY_DELAYS_MS = [1_000, 3_000];
|
|
29
|
+
export const MAX_CF_INVOCATIONS = 6_000;
|
|
30
|
+
const WhoamiSchema = z.object({
|
|
31
|
+
authenticated: z.boolean(),
|
|
32
|
+
scopes: z.array(z.string().max(128)).max(1_000).optional(),
|
|
33
|
+
expiresAt: z.union([z.string().max(64), z.number()]).optional(),
|
|
34
|
+
}).passthrough();
|
|
35
|
+
/** Reduce cf's whoami JSON; email, account names and the credential file path are dropped. */
|
|
36
|
+
export function parseWhoami(stdout) {
|
|
37
|
+
let raw;
|
|
38
|
+
try {
|
|
39
|
+
raw = JSON.parse(stdout);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const parsed = WhoamiSchema.safeParse(raw);
|
|
45
|
+
if (!parsed.success)
|
|
46
|
+
return null;
|
|
47
|
+
const summary = { authenticated: parsed.data.authenticated };
|
|
48
|
+
if (parsed.data.expiresAt !== undefined) {
|
|
49
|
+
const time = typeof parsed.data.expiresAt === 'number' ? parsed.data.expiresAt : Date.parse(parsed.data.expiresAt);
|
|
50
|
+
if (Number.isFinite(time))
|
|
51
|
+
summary.expiresAt = new Date(time).toISOString();
|
|
52
|
+
}
|
|
53
|
+
if (parsed.data.scopes)
|
|
54
|
+
summary.scopes = parsed.data.scopes.filter((scope) => /^[A-Za-z0-9_.:-]{1,64}$/.test(scope));
|
|
55
|
+
return summary;
|
|
56
|
+
}
|
|
57
|
+
export function isReadOnlyScope(scope) {
|
|
58
|
+
return /(?:^|[.:])read$/.test(scope) || scope === 'offline' || scope === 'offline_access';
|
|
59
|
+
}
|
|
60
|
+
export function authSourceFor(mode) {
|
|
61
|
+
return mode === 'profile' ? 'cf_profile' : mode === 'env' ? 'cf_env_token' : 'cf_default_profile';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Doctor's auth view. In env mode cf reports `scopes` and `expiresAt` from the
|
|
65
|
+
* active profile's stored OAuth file even while the API token is in use, so
|
|
66
|
+
* both are ignored: API token permissions cannot be introspected.
|
|
67
|
+
*/
|
|
68
|
+
export function doctorAuth(summary, mode, profile) {
|
|
69
|
+
const base = { source: authSourceFor(mode), profile: mode === 'profile' ? profile : null, authenticated: summary.authenticated };
|
|
70
|
+
if (mode === 'env' || !summary.scopes)
|
|
71
|
+
return { ...base, scopes: 'unknown' };
|
|
72
|
+
return {
|
|
73
|
+
...base,
|
|
74
|
+
...(summary.expiresAt ? { expiresAt: summary.expiresAt } : {}),
|
|
75
|
+
scopes: 'known',
|
|
76
|
+
missingRecommendedScopes: RECOMMENDED_CF_SCOPES.filter((scope) => !summary.scopes.includes(scope)),
|
|
77
|
+
writeScopeCount: summary.scopes.filter((scope) => !isReadOnlyScope(scope)).length,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function authRequiredError(mode, message) {
|
|
81
|
+
return new LocalCheckupError('CF_AUTH_REQUIRED', message ?? (mode === 'env'
|
|
82
|
+
? 'cf could not authenticate with the API token from this shell.'
|
|
83
|
+
: 'cf is not signed in for this checkup (the profile is missing or its login expired).'), mode === 'env' ? { hint: ENV_TOKEN_AUTH_HINT } : {});
|
|
84
|
+
}
|
|
85
|
+
/** Dispatch gate shared by every worker. */
|
|
86
|
+
export class CfScheduler {
|
|
87
|
+
options;
|
|
88
|
+
invocations = 0;
|
|
89
|
+
dispatched = 0;
|
|
90
|
+
inFlight = 0;
|
|
91
|
+
drainWaiters = [];
|
|
92
|
+
gate = null;
|
|
93
|
+
refreshing = null;
|
|
94
|
+
expiresAtMs;
|
|
95
|
+
preExpiryEnabled = true;
|
|
96
|
+
/** Dispatch sequence number when the first 429 paused the run. */
|
|
97
|
+
rateLimitPauseSeq = null;
|
|
98
|
+
abortError = null;
|
|
99
|
+
constructor(options) {
|
|
100
|
+
this.options = options;
|
|
101
|
+
}
|
|
102
|
+
get aborted() {
|
|
103
|
+
return this.abortError;
|
|
104
|
+
}
|
|
105
|
+
/** The serial whoami (re-read once if it refreshed) before fan-out. Throws CF_AUTH_REQUIRED when cf is not signed in. */
|
|
106
|
+
async start() {
|
|
107
|
+
let summary = await this.serialWhoami();
|
|
108
|
+
this.setExpiry(summary);
|
|
109
|
+
if (this.expiryHasPassed()) {
|
|
110
|
+
// This whoami refreshed an expired token but printed the pre-refresh expiry (see the header).
|
|
111
|
+
summary = await this.serialWhoami();
|
|
112
|
+
this.setExpiry(summary);
|
|
113
|
+
}
|
|
114
|
+
return summary;
|
|
115
|
+
}
|
|
116
|
+
/** Abort the run: no further dispatches, live children are killed. */
|
|
117
|
+
abort(error) {
|
|
118
|
+
if (this.abortError)
|
|
119
|
+
return;
|
|
120
|
+
this.abortError = error;
|
|
121
|
+
void this.options.terminateAll?.();
|
|
122
|
+
}
|
|
123
|
+
throwIfAborted() {
|
|
124
|
+
if (this.abortError)
|
|
125
|
+
throw this.abortError;
|
|
126
|
+
}
|
|
127
|
+
/** One cf API call with the §F5 retry policy. */
|
|
128
|
+
async call(argv, options = {}) {
|
|
129
|
+
let transientRetries = 0;
|
|
130
|
+
let authRetried = false;
|
|
131
|
+
let rateLimitRetried = false;
|
|
132
|
+
for (;;) {
|
|
133
|
+
const seq = await this.dispatch();
|
|
134
|
+
let result;
|
|
135
|
+
try {
|
|
136
|
+
result = await this.options.invoke(argv, options);
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
this.release();
|
|
140
|
+
}
|
|
141
|
+
this.throwIfAborted();
|
|
142
|
+
const failure = toFailure(result);
|
|
143
|
+
if (!failure)
|
|
144
|
+
return { ok: true, stdout: result.stdout };
|
|
145
|
+
if (failure.kind === 'http' && failure.status === 429) {
|
|
146
|
+
// The first 429 pauses every worker for 30 s; calls already in flight
|
|
147
|
+
// when it began join that pause and retry once. A 429 on a call
|
|
148
|
+
// dispatched after the pause, or a second 429 on the same call, aborts.
|
|
149
|
+
if (rateLimitRetried || (this.rateLimitPauseSeq !== null && seq > this.rateLimitPauseSeq)) {
|
|
150
|
+
const error = new LocalCheckupError('CF_RATE_LIMITED', 'Cloudflare rate-limited the collection twice (HTTP 429). No file was written.', { status: 429 });
|
|
151
|
+
this.abort(error);
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
rateLimitRetried = true;
|
|
155
|
+
if (this.rateLimitPauseSeq === null) {
|
|
156
|
+
this.rateLimitPauseSeq = this.dispatched;
|
|
157
|
+
await this.setGate(() => this.options.clock.sleep(RATE_LIMIT_PAUSE_MS));
|
|
158
|
+
}
|
|
159
|
+
else if (this.gate) {
|
|
160
|
+
await this.gate;
|
|
161
|
+
}
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if ((failure.kind === 'http' && failure.status === 401) || failure.kind === 'auth') {
|
|
165
|
+
if (authRetried)
|
|
166
|
+
return { ok: false, failure };
|
|
167
|
+
authRetried = true;
|
|
168
|
+
await this.refresh('reactive');
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const transient = failure.kind === 'timeout' || failure.kind === 'network' || (failure.kind === 'http' && failure.status >= 500);
|
|
172
|
+
if (transient && transientRetries < TRANSIENT_RETRY_DELAYS_MS.length) {
|
|
173
|
+
await this.options.clock.sleep(TRANSIENT_RETRY_DELAYS_MS[transientRetries]);
|
|
174
|
+
transientRetries++;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
return { ok: false, failure };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** Wait for a request slot and an open gate; returns the dispatch sequence number. */
|
|
181
|
+
async dispatch() {
|
|
182
|
+
this.throwIfAborted();
|
|
183
|
+
await this.options.budget.acquire();
|
|
184
|
+
for (;;) {
|
|
185
|
+
this.throwIfAborted();
|
|
186
|
+
if (this.gate) {
|
|
187
|
+
await this.gate;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (this.shouldRefreshBeforeExpiry()) {
|
|
191
|
+
void this.refresh('expiry');
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (this.invocations >= (this.options.maxInvocations ?? MAX_CF_INVOCATIONS)) {
|
|
195
|
+
const error = new LocalCheckupError('ACCOUNT_TOO_LARGE', 'Collection would exceed 6,000 cf requests; this account is too large for a local checkup.');
|
|
196
|
+
this.abort(error);
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
this.invocations++;
|
|
200
|
+
this.inFlight++;
|
|
201
|
+
return ++this.dispatched;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
release() {
|
|
205
|
+
this.inFlight--;
|
|
206
|
+
if (this.inFlight === 0) {
|
|
207
|
+
const waiters = this.drainWaiters;
|
|
208
|
+
this.drainWaiters = [];
|
|
209
|
+
for (const resolve of waiters)
|
|
210
|
+
resolve();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
drain() {
|
|
214
|
+
if (this.inFlight === 0)
|
|
215
|
+
return Promise.resolve();
|
|
216
|
+
return new Promise((resolve) => this.drainWaiters.push(resolve));
|
|
217
|
+
}
|
|
218
|
+
shouldRefreshBeforeExpiry() {
|
|
219
|
+
return this.options.authMode !== 'env' && this.preExpiryEnabled && this.expiresAtMs !== undefined &&
|
|
220
|
+
this.options.clock.now() >= this.expiresAtMs - PRE_EXPIRY_MARGIN_MS;
|
|
221
|
+
}
|
|
222
|
+
/** Close the dispatch gate until `work` (queued after any current gate) finishes. Failures abort the run. */
|
|
223
|
+
setGate(work) {
|
|
224
|
+
const previous = this.gate ?? Promise.resolve();
|
|
225
|
+
const gate = previous.then(work).catch((error) => {
|
|
226
|
+
this.abort(error instanceof Error ? error : new Error(String(error)));
|
|
227
|
+
}).finally(() => {
|
|
228
|
+
if (this.gate === gate)
|
|
229
|
+
this.gate = null;
|
|
230
|
+
});
|
|
231
|
+
this.gate = gate;
|
|
232
|
+
return gate;
|
|
233
|
+
}
|
|
234
|
+
/** Pause dispatch, drain in-flight calls, run up to two serial whoami calls, resume. */
|
|
235
|
+
refresh(reason) {
|
|
236
|
+
if (this.refreshing)
|
|
237
|
+
return this.refreshing;
|
|
238
|
+
const refreshing = this.setGate(async () => {
|
|
239
|
+
await this.drain();
|
|
240
|
+
if (reason === 'expiry' && this.expiresAtMs !== undefined) {
|
|
241
|
+
const wait = this.expiresAtMs + 1_000 - this.options.clock.now();
|
|
242
|
+
if (wait > 0)
|
|
243
|
+
await this.options.clock.sleep(wait);
|
|
244
|
+
}
|
|
245
|
+
const previous = this.expiresAtMs;
|
|
246
|
+
this.setExpiry(await this.serialWhoami());
|
|
247
|
+
// cf 1.0.0-beta.13 `auth whoami` reads the credential file before its token getter
|
|
248
|
+
// refreshes, so the whoami that performs the refresh prints the old expiry. Re-read once
|
|
249
|
+
// (also after a 401, so a passed expiry does not trigger a second pause straight away).
|
|
250
|
+
if (this.expiryHasPassed()) {
|
|
251
|
+
this.setExpiry(await this.serialWhoami());
|
|
252
|
+
}
|
|
253
|
+
// A refresh that did not move the expiry forward falls back to the reactive 401 path.
|
|
254
|
+
if (reason === 'expiry' && (this.expiresAtMs === undefined || this.expiresAtMs === previous ||
|
|
255
|
+
this.expiresAtMs - PRE_EXPIRY_MARGIN_MS <= this.options.clock.now())) {
|
|
256
|
+
this.preExpiryEnabled = false;
|
|
257
|
+
}
|
|
258
|
+
}).finally(() => {
|
|
259
|
+
if (this.refreshing === refreshing)
|
|
260
|
+
this.refreshing = null;
|
|
261
|
+
});
|
|
262
|
+
this.refreshing = refreshing;
|
|
263
|
+
return refreshing;
|
|
264
|
+
}
|
|
265
|
+
expiryHasPassed() {
|
|
266
|
+
return this.expiresAtMs !== undefined && this.expiresAtMs <= this.options.clock.now();
|
|
267
|
+
}
|
|
268
|
+
setExpiry(summary) {
|
|
269
|
+
if (this.options.authMode === 'env')
|
|
270
|
+
return;
|
|
271
|
+
const time = summary.expiresAt === undefined ? Number.NaN : Date.parse(summary.expiresAt);
|
|
272
|
+
this.expiresAtMs = Number.isFinite(time) ? time : undefined;
|
|
273
|
+
}
|
|
274
|
+
async serialWhoami() {
|
|
275
|
+
this.throwIfAborted();
|
|
276
|
+
await this.options.budget.acquire();
|
|
277
|
+
this.invocations++;
|
|
278
|
+
const result = await this.options.whoami();
|
|
279
|
+
if (result.exitCode === 0 && !result.timedOut && !result.stdoutTooLarge) {
|
|
280
|
+
const summary = parseWhoami(result.stdout);
|
|
281
|
+
if (!summary)
|
|
282
|
+
throw new LocalCheckupError('CF_ERROR', 'cf auth whoami printed unexpected output.');
|
|
283
|
+
if (!summary.authenticated)
|
|
284
|
+
throw authRequiredError(this.options.authMode);
|
|
285
|
+
return summary;
|
|
286
|
+
}
|
|
287
|
+
const failure = toFailure(result);
|
|
288
|
+
if (failure?.kind === 'auth' || (failure?.kind === 'http' && (failure.status === 401 || failure.status === 403))) {
|
|
289
|
+
throw authRequiredError(this.options.authMode);
|
|
290
|
+
}
|
|
291
|
+
if (failure?.kind === 'http' && failure.status === 429) {
|
|
292
|
+
throw new LocalCheckupError('CF_RATE_LIMITED', 'Cloudflare rate-limited cf auth whoami (HTTP 429).', { status: 429 });
|
|
293
|
+
}
|
|
294
|
+
throw new LocalCheckupError('CF_ERROR', 'cf auth whoami failed; Cloudflare could not be reached or returned an error.');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/** `null` for a clean exit; otherwise the classified failure. */
|
|
298
|
+
export function toFailure(result) {
|
|
299
|
+
if (result.stdoutTooLarge)
|
|
300
|
+
return { kind: 'output_too_large' };
|
|
301
|
+
if (result.timedOut)
|
|
302
|
+
return { kind: 'timeout' };
|
|
303
|
+
if (result.spawnFailed)
|
|
304
|
+
return { kind: 'cf_error' };
|
|
305
|
+
if (result.exitCode === 0)
|
|
306
|
+
return null;
|
|
307
|
+
const classified = classifyCfStderr(result.stderr);
|
|
308
|
+
if (classified.kind === 'node_unsupported') {
|
|
309
|
+
throw new LocalCheckupError('NODE_UNSUPPORTED', 'cf refused to run under this Node.js version.');
|
|
310
|
+
}
|
|
311
|
+
return classified;
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=auth-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-lifecycle.js","sourceRoot":"","sources":["../../../../src/local/cloudflare-checkup/cf/auth-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The environment every cf child process receives (spec §F3).
|
|
3
|
+
*
|
|
4
|
+
* This is the only source file that names the Cloudflare API token variable;
|
|
5
|
+
* everything else imports `CF_TOKEN_ENV` (enforced by the grep guard test).
|
|
6
|
+
* The child environment is built from an empty object: a fixed allowlist is
|
|
7
|
+
* copied by name without inspecting values, then fixed values are forced.
|
|
8
|
+
* Base-URL overrides (`CLOUDFLARE_API_BASE_URL`, `CF_API_BASE_URL`), other
|
|
9
|
+
* Cloudflare/Wrangler credentials, `VIGILBASE_*`, `NODE_OPTIONS`, `DEBUG`,
|
|
10
|
+
* npm config and agent-harness markers are therefore absent by construction.
|
|
11
|
+
* Scrubbing the base-URL variables is the primary control against redirecting
|
|
12
|
+
* the token; the dry-run preflight cannot detect it.
|
|
13
|
+
*/
|
|
14
|
+
export declare const CF_TOKEN_ENV = "CLOUDFLARE_API_TOKEN";
|
|
15
|
+
export declare const CF_ACCOUNT_ENV = "CLOUDFLARE_ACCOUNT_ID";
|
|
16
|
+
export type CfAuthMode = 'profile' | 'env' | 'default';
|
|
17
|
+
/** `api`: authenticated reads; `offline`: --version and --dry-run; `login`: interactive `cf auth create` / `cf auth delete`. */
|
|
18
|
+
export type ChildEnvPurpose = 'api' | 'offline' | 'login';
|
|
19
|
+
/** Presence only: the value is never read, printed or validated by the Vigilbase CLI. */
|
|
20
|
+
export declare function hasEnvToken(parent: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
|
|
21
|
+
export declare function buildChildEnv(parent: NodeJS.ProcessEnv, options: {
|
|
22
|
+
purpose: ChildEnvPurpose;
|
|
23
|
+
authMode: CfAuthMode;
|
|
24
|
+
accountId?: string;
|
|
25
|
+
platform?: NodeJS.Platform;
|
|
26
|
+
}): Record<string, string>;
|
|
27
|
+
/** Variable names (never values) a cf child would receive, for `--dry-run` output. */
|
|
28
|
+
export declare function childEnvVariableNames(parent: NodeJS.ProcessEnv, authMode: CfAuthMode, platform?: NodeJS.Platform): string[];
|
|
29
|
+
/** Shown in profile and default modes when the token variable is set in the parent shell. */
|
|
30
|
+
export declare function strippedTokenNotice(authMode: CfAuthMode): string;
|
|
31
|
+
export declare function missingEnvTokenMessage(): string;
|
|
32
|
+
//# sourceMappingURL=child-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-env.d.ts","sourceRoot":"","sources":["../../../../src/local/cloudflare-checkup/cf/child-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,YAAY,yBAAyB,CAAA;AAClD,eAAO,MAAM,cAAc,0BAA0B,CAAA;AAErD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,CAAA;AACtD,gIAAgI;AAChI,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,CAAA;AAwBzD,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,OAAO,CAG5G;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,CAAC,UAAU,EACzB,OAAO,EAAE;IAAE,OAAO,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,UAAU,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAAE,GAC1G,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBxB;AAED,sFAAsF;AACtF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,EAAE,CAI7I;AAED,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAEhE;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The environment every cf child process receives (spec §F3).
|
|
3
|
+
*
|
|
4
|
+
* This is the only source file that names the Cloudflare API token variable;
|
|
5
|
+
* everything else imports `CF_TOKEN_ENV` (enforced by the grep guard test).
|
|
6
|
+
* The child environment is built from an empty object: a fixed allowlist is
|
|
7
|
+
* copied by name without inspecting values, then fixed values are forced.
|
|
8
|
+
* Base-URL overrides (`CLOUDFLARE_API_BASE_URL`, `CF_API_BASE_URL`), other
|
|
9
|
+
* Cloudflare/Wrangler credentials, `VIGILBASE_*`, `NODE_OPTIONS`, `DEBUG`,
|
|
10
|
+
* npm config and agent-harness markers are therefore absent by construction.
|
|
11
|
+
* Scrubbing the base-URL variables is the primary control against redirecting
|
|
12
|
+
* the token; the dry-run preflight cannot detect it.
|
|
13
|
+
*/
|
|
14
|
+
export const CF_TOKEN_ENV = 'CLOUDFLARE_API_TOKEN';
|
|
15
|
+
export const CF_ACCOUNT_ENV = 'CLOUDFLARE_ACCOUNT_ID';
|
|
16
|
+
const PASSTHROUGH = [
|
|
17
|
+
'PATH', 'HOME', 'USER', 'LOGNAME', 'USERPROFILE', 'APPDATA', 'LOCALAPPDATA', 'SystemRoot', 'WINDIR',
|
|
18
|
+
'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_DATA_HOME', 'XDG_STATE_HOME', 'XDG_RUNTIME_DIR',
|
|
19
|
+
'TMPDIR', 'TMP', 'TEMP', 'LANG', 'LC_ALL', 'LC_CTYPE', 'TZ',
|
|
20
|
+
'HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY', 'http_proxy', 'https_proxy', 'no_proxy',
|
|
21
|
+
'NODE_EXTRA_CA_CERTS', 'SSL_CERT_FILE', 'SSL_CERT_DIR', 'DBUS_SESSION_BUS_ADDRESS', 'CLOUDFLARE_AUTH_USE_KEYRING',
|
|
22
|
+
];
|
|
23
|
+
/** Telemetry off, no update checks or prompts, no project-local delegation. */
|
|
24
|
+
const FORCED_TELEMETRY = { CF_SEND_TELEMETRY: 'false', DO_NOT_TRACK: '1', CF_DELEGATION: '1' };
|
|
25
|
+
const FORCED_NON_INTERACTIVE = { CI: '1', NO_COLOR: '1', FORCE_COLOR: '0', CF_QUIET: '1' };
|
|
26
|
+
function lookup(parent, platform) {
|
|
27
|
+
if (platform !== 'win32')
|
|
28
|
+
return (name) => parent[name];
|
|
29
|
+
// Windows variable names are case-insensitive (`Path`, `SystemRoot`).
|
|
30
|
+
const keys = new Map(Object.keys(parent).map((key) => [key.toUpperCase(), key]));
|
|
31
|
+
return (name) => {
|
|
32
|
+
const key = keys.get(name.toUpperCase());
|
|
33
|
+
return key === undefined ? undefined : parent[key];
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Presence only: the value is never read, printed or validated by the Vigilbase CLI. */
|
|
37
|
+
export function hasEnvToken(parent, platform = process.platform) {
|
|
38
|
+
const value = lookup(parent, platform)(CF_TOKEN_ENV);
|
|
39
|
+
return typeof value === 'string' && value.length > 0;
|
|
40
|
+
}
|
|
41
|
+
export function buildChildEnv(parent, options) {
|
|
42
|
+
const platform = options.platform ?? process.platform;
|
|
43
|
+
const get = lookup(parent, platform);
|
|
44
|
+
const env = {};
|
|
45
|
+
for (const name of PASSTHROUGH) {
|
|
46
|
+
const value = get(name);
|
|
47
|
+
if (typeof value === 'string')
|
|
48
|
+
env[name] = value;
|
|
49
|
+
}
|
|
50
|
+
Object.assign(env, FORCED_TELEMETRY);
|
|
51
|
+
if (options.purpose !== 'login')
|
|
52
|
+
Object.assign(env, FORCED_NON_INTERACTIVE);
|
|
53
|
+
if (options.accountId !== undefined) {
|
|
54
|
+
if (!/^[0-9a-f]{32}$/.test(options.accountId))
|
|
55
|
+
throw new Error('Invalid Cloudflare account ID for cf.');
|
|
56
|
+
env[CF_ACCOUNT_ENV] = options.accountId;
|
|
57
|
+
}
|
|
58
|
+
// Copied by name, only for authenticated reads in --cf-auth env mode. In
|
|
59
|
+
// profile and default modes it would outrank --profile, so it is stripped.
|
|
60
|
+
if (options.purpose === 'api' && options.authMode === 'env') {
|
|
61
|
+
const token = get(CF_TOKEN_ENV);
|
|
62
|
+
if (typeof token === 'string' && token.length > 0)
|
|
63
|
+
env[CF_TOKEN_ENV] = token;
|
|
64
|
+
}
|
|
65
|
+
return env;
|
|
66
|
+
}
|
|
67
|
+
/** Variable names (never values) a cf child would receive, for `--dry-run` output. */
|
|
68
|
+
export function childEnvVariableNames(parent, authMode, platform = process.platform) {
|
|
69
|
+
const names = Object.keys(buildChildEnv(parent, { purpose: 'api', authMode, accountId: '0'.repeat(32), platform }));
|
|
70
|
+
if (authMode === 'env' && !names.includes(CF_TOKEN_ENV))
|
|
71
|
+
names.push(CF_TOKEN_ENV);
|
|
72
|
+
return names.sort();
|
|
73
|
+
}
|
|
74
|
+
/** Shown in profile and default modes when the token variable is set in the parent shell. */
|
|
75
|
+
export function strippedTokenNotice(authMode) {
|
|
76
|
+
return `${CF_TOKEN_ENV} is set in this shell but is not passed to cf in --cf-auth ${authMode} mode (it would override the profile). Use --cf-auth env to collect with it.`;
|
|
77
|
+
}
|
|
78
|
+
export function missingEnvTokenMessage() {
|
|
79
|
+
return `--cf-auth env requires ${CF_TOKEN_ENV} in this shell. cf reads it itself; the Vigilbase CLI only passes it through by name.`;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=child-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-env.js","sourceRoot":"","sources":["../../../../src/local/cloudflare-checkup/cf/child-env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Vigilbase-managed install of Cloudflare's cf (spec "one command", decision 5).
|
|
3
|
+
*
|
|
4
|
+
* When no usable cf is found, the full flow may install the pinned release
|
|
5
|
+
* into `<configDir>/cf/<version>/` with the npm that ships with this Node:
|
|
6
|
+
*
|
|
7
|
+
* - npm runs as `process.execPath <npm-cli.js> install --prefix <staging> …`
|
|
8
|
+
* with no shell, from the fresh 0700 staging directory, with the user's
|
|
9
|
+
* environment (npm needs their npmrc, proxy and CA settings) minus every
|
|
10
|
+
* `CF_*` / `CLOUDFLARE_*` variable and, defensively, any variable whose
|
|
11
|
+
* value holds a session code, a verification token or `--email`. (npx 10
|
|
12
|
+
* passes arguments only in argv, not in the environment:
|
|
13
|
+
* `npm_lifecycle_script` is just the bin name.)
|
|
14
|
+
* - `--ignore-scripts`: cf runs `--version`, `--dry-run` and API reads without
|
|
15
|
+
* lifecycle scripts. `--omit=optional`: the optional dependencies are the
|
|
16
|
+
* workerd and sharp platform binaries (about 150 MB). In cf 1.0.0-beta.13
|
|
17
|
+
* they are loaded only by `--local` mode and the `workers`, `deploy` and
|
|
18
|
+
* `previews` command trees (static and dynamic import graph of
|
|
19
|
+
* `dist/*.mjs`), none of which the checkup runs; see LOCAL.md.
|
|
20
|
+
* - Integrity is pinned: after npm exits, the staging lockfile must record
|
|
21
|
+
* `node_modules/cf` at exactly the pinned version and npm `dist.integrity`,
|
|
22
|
+
* and the installed package.json must agree; otherwise the staging
|
|
23
|
+
* directory is deleted (CF_INSTALL_FAILED). Only then is it renamed into
|
|
24
|
+
* place, so a half-finished install is never used. `locateCf` still applies
|
|
25
|
+
* its identity checks to the result.
|
|
26
|
+
* - Ctrl-C while npm runs kills npm and removes the staging directory. Staging
|
|
27
|
+
* directories left by a crash or a closed terminal are removed by the next
|
|
28
|
+
* install once they are older than the npm timeout (a concurrent install is
|
|
29
|
+
* always younger), and by `logout`.
|
|
30
|
+
*/
|
|
31
|
+
import { type ChildProcess, type SpawnOptions } from 'node:child_process';
|
|
32
|
+
import { LocalCheckupError } from '../errors.js';
|
|
33
|
+
/** The cf release the CLI installs; `integrity` is npm's `dist.integrity` for it. */
|
|
34
|
+
export declare const MANAGED_CF: Readonly<{
|
|
35
|
+
version: "1.0.0-beta.13";
|
|
36
|
+
integrity: "sha512-dCjpzCJvjudIu8IQbXCJfy9diFoyHU84D/30K4lJp7jUaBgvjJypsMFzLqvUFOuwhF1ggR/igsLqXyehAOR2FQ==";
|
|
37
|
+
/** Measured `du` of the install without optional dependencies (darwin-arm64: 73 MB). */
|
|
38
|
+
approxSize: "about 75 MB";
|
|
39
|
+
}>;
|
|
40
|
+
export declare const NPM_INSTALL_TIMEOUT_MS: number;
|
|
41
|
+
export declare const NPM_STDERR_TAIL_LINES = 20;
|
|
42
|
+
export type SpawnFn = (command: string, args: readonly string[], options: SpawnOptions) => ChildProcess;
|
|
43
|
+
/** `<configDir>/cf`: every managed version, plus any leftover staging directory. */
|
|
44
|
+
export declare function managedCfRoot(configDir: string): string;
|
|
45
|
+
export declare function managedCfInstallDir(configDir: string, version?: string): string;
|
|
46
|
+
export declare function managedCfPackageDir(installDir: string): string;
|
|
47
|
+
/** The npm arguments after `process.execPath`. */
|
|
48
|
+
export declare function npmInstallArgv(npmCli: string, prefix: string, version?: string): string[];
|
|
49
|
+
/**
|
|
50
|
+
* The npm to run: `npm_execpath` when it names an existing `npm-cli.js` (or
|
|
51
|
+
* `npx-cli.js`, whose sibling is used), otherwise the npm bundled beside this
|
|
52
|
+
* Node. `null` when neither exists.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveNpmCli(options?: {
|
|
55
|
+
env: NodeJS.ProcessEnv;
|
|
56
|
+
execPath?: string;
|
|
57
|
+
platform?: NodeJS.Platform;
|
|
58
|
+
exists?: (target: string) => boolean;
|
|
59
|
+
}): string | null;
|
|
60
|
+
/** The user's environment minus Cloudflare variables and anything carrying a session code, token or `--email`. */
|
|
61
|
+
export declare function npmChildEnv(parent: NodeJS.ProcessEnv): Record<string, string>;
|
|
62
|
+
/**
|
|
63
|
+
* True when every lockfile npm wrote records `node_modules/cf` at the pinned
|
|
64
|
+
* version and integrity (at least one must exist), and the installed
|
|
65
|
+
* package.json has that version.
|
|
66
|
+
*/
|
|
67
|
+
export declare function verifyManagedInstall(installDir: string, pin?: {
|
|
68
|
+
version: string;
|
|
69
|
+
integrity: string;
|
|
70
|
+
}): Promise<boolean>;
|
|
71
|
+
/** The managed cf package directory when a verified install exists, else null. */
|
|
72
|
+
export declare function findManagedCf(configDir: string): Promise<string | null>;
|
|
73
|
+
/** Create `dir` 0700 if missing; refuse a symlink or non-directory in its place. */
|
|
74
|
+
export declare function ensurePrivateDir(dir: string): Promise<void>;
|
|
75
|
+
/** A CF_INSTALL_FAILED error that carries the redacted tail of npm's stderr. */
|
|
76
|
+
export declare class CfInstallError extends LocalCheckupError {
|
|
77
|
+
readonly npmOutput: string[];
|
|
78
|
+
constructor(message: string, npmOutput?: string[]);
|
|
79
|
+
}
|
|
80
|
+
/** The last lines of npm's stderr, dropping any line that could carry a registry credential. */
|
|
81
|
+
export declare function npmStderrTail(stderr: string, lines?: number): string[];
|
|
82
|
+
/** Remove `.staging-*` leftovers older than `maxAgeMs`; a younger one may belong to a concurrent install. */
|
|
83
|
+
export declare function removeStaleStaging(root: string, maxAgeMs?: number, now?: number): Promise<string[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Install the pinned cf into `<configDir>/cf/<version>/` and return its
|
|
86
|
+
* package directory. Throws CF_INSTALL_FAILED (a `CfInstallError`) when npm
|
|
87
|
+
* is missing or fails, or the result does not match the pin; the staging
|
|
88
|
+
* directory is always removed (on Ctrl-C too).
|
|
89
|
+
*/
|
|
90
|
+
export declare function installManagedCf(options: {
|
|
91
|
+
configDir: string;
|
|
92
|
+
env: NodeJS.ProcessEnv;
|
|
93
|
+
spawn?: SpawnFn;
|
|
94
|
+
npmCli?: string | null;
|
|
95
|
+
timeoutMs?: number;
|
|
96
|
+
/** Replace a verified install too (it was found but cf could not run). */
|
|
97
|
+
replace?: boolean;
|
|
98
|
+
/** Runs first on Ctrl-C during the install (the caller stops its spinner). */
|
|
99
|
+
onInterrupt?: () => void;
|
|
100
|
+
}): Promise<string>;
|
|
101
|
+
/** `logout`: remove every managed cf version (and any staging leftovers). */
|
|
102
|
+
export declare function removeManagedCf(configDir: string): Promise<{
|
|
103
|
+
path: string;
|
|
104
|
+
removed: boolean;
|
|
105
|
+
}>;
|
|
106
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../../src/local/cloudflare-checkup/cf/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAsB,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAI7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEhD,qFAAqF;AACrF,eAAO,MAAM,UAAU;;;IAGrB,wFAAwF;;EAExF,CAAA;AAEF,eAAO,MAAM,sBAAsB,QAAc,CAAA;AAMjD,eAAO,MAAM,qBAAqB,KAAK,CAAA;AAIvC,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,KAAK,YAAY,CAAA;AAEvG,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,MAA2B,GAAG,MAAM,CAEnG;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,kDAAkD;AAClD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAA2B,GAAG,MAAM,EAAE,CAE7G;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE;IACrC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAA;CACd,GAAG,MAAM,GAAG,IAAI,CAevC;AAED,kHAAkH;AAClH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU7E;AAcD;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAYzI;AAED,kFAAkF;AAClF,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAK7E;AAED,oFAAoF;AACpF,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUjE;AAED,gFAAgF;AAChF,qBAAa,cAAe,SAAQ,iBAAiB;IACnD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAA;gBAEhB,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,EAAO;CAItD;AAID,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAA8B,GAAG,MAAM,EAAE,CAK7F;AAsCD,6GAA6G;AAC7G,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAyB,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUvI;AAwBD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0ClB;AAED,6EAA6E;AAC7E,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAMpG"}
|