orizu 0.5.49 → 0.5.51
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/dist/account-directory.d.ts +2 -2
- package/dist/account-directory.d.ts.map +1 -1
- package/dist/account-directory.js +7 -32
- package/dist/auth-commands.d.ts.map +1 -1
- package/dist/auth-commands.js +32 -36
- package/dist/credentials-transaction.d.ts +7 -0
- package/dist/credentials-transaction.d.ts.map +1 -0
- package/dist/credentials-transaction.js +60 -0
- package/dist/credentials.d.ts +24 -1
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +202 -76
- package/dist/dataset-transfer-upload.d.ts.map +1 -1
- package/dist/dataset-transfer-upload.js +6 -1
- package/dist/directory-list-read.d.ts +37 -0
- package/dist/directory-list-read.d.ts.map +1 -0
- package/dist/directory-list-read.js +87 -0
- package/dist/hosted-boot.d.ts.map +1 -1
- package/dist/hosted-boot.js +59 -41
- package/dist/hosted-harness-opencode.d.ts +31 -0
- package/dist/hosted-harness-opencode.d.ts.map +1 -1
- package/dist/hosted-harness-opencode.js +45 -7
- package/dist/hosted-loop.d.ts +39 -2
- package/dist/hosted-loop.d.ts.map +1 -1
- package/dist/hosted-loop.js +127 -18
- package/dist/hosted-session-seed.d.ts +2 -0
- package/dist/hosted-session-seed.d.ts.map +1 -1
- package/dist/hosted-session-seed.js +27 -10
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +39 -234
- package/dist/keyboard-select.d.ts.map +1 -1
- package/dist/keyboard-select.js +23 -45
- package/dist/project-create-workflow.d.ts +18 -0
- package/dist/project-create-workflow.d.ts.map +1 -0
- package/dist/project-create-workflow.js +121 -0
- package/dist/self-update-command.d.ts +8 -0
- package/dist/self-update-command.d.ts.map +1 -0
- package/dist/self-update-command.js +390 -0
- package/dist/self-update.d.ts +29 -16
- package/dist/self-update.d.ts.map +1 -1
- package/dist/self-update.js +55 -244
- package/dist/setup-account.d.ts.map +1 -1
- package/dist/setup-account.js +4 -1
- package/dist/setup-and-skills-commands.d.ts.map +1 -1
- package/dist/setup-and-skills-commands.js +88 -102
- package/dist/skill-install-workflow.d.ts +23 -0
- package/dist/skill-install-workflow.d.ts.map +1 -0
- package/dist/skill-install-workflow.js +184 -0
- package/dist/skill-installer.d.ts +8 -3
- package/dist/skill-installer.d.ts.map +1 -1
- package/dist/skill-installer.js +26 -33
- package/dist/stored-session-requests.d.ts +27 -0
- package/dist/stored-session-requests.d.ts.map +1 -0
- package/dist/stored-session-requests.js +268 -0
- package/dist/terminal-key-session.d.ts +23 -0
- package/dist/terminal-key-session.d.ts.map +1 -0
- package/dist/terminal-key-session.js +74 -0
- package/package.json +1 -1
- package/src/account-directory.ts +8 -42
- package/src/auth-commands.ts +31 -35
- package/src/credentials-transaction.ts +73 -0
- package/src/credentials.ts +211 -89
- package/src/dataset-transfer-upload.ts +7 -1
- package/src/directory-list-read.ts +123 -0
- package/src/hosted-boot.ts +65 -43
- package/src/hosted-harness-opencode.ts +65 -9
- package/src/hosted-loop.ts +152 -18
- package/src/hosted-session-seed.ts +25 -8
- package/src/http.ts +39 -317
- package/src/keyboard-select.ts +18 -55
- package/src/project-create-workflow.ts +139 -0
- package/src/self-update-command.ts +419 -0
- package/src/self-update.ts +70 -266
- package/src/setup-account.ts +4 -1
- package/src/setup-and-skills-commands.ts +89 -121
- package/src/skill-install-workflow.ts +215 -0
- package/src/skill-installer.ts +31 -38
- package/src/stored-session-requests.ts +319 -0
- package/src/terminal-key-session.ts +88 -0
|
@@ -103,8 +103,8 @@ declare const TASK_STATUS_ACTION_LABELS: {
|
|
|
103
103
|
};
|
|
104
104
|
};
|
|
105
105
|
type AuthenticatedRequest = AuthenticatedRequestContext['fetch'];
|
|
106
|
-
declare function fetchTeams(request?: AuthenticatedRequest): Promise<Team[]>;
|
|
107
|
-
declare function fetchProjects(teamSlug?: string, request?: AuthenticatedRequest): Promise<Project[]>;
|
|
106
|
+
declare function fetchTeams(request?: AuthenticatedRequest, timeoutMs?: number): Promise<Team[]>;
|
|
107
|
+
declare function fetchProjects(teamSlug?: string, request?: AuthenticatedRequest, timeoutMs?: number): Promise<Project[]>;
|
|
108
108
|
declare function fetchTasks(project?: string, status?: string): Promise<Task[]>;
|
|
109
109
|
declare function fetchApps(project: string, status?: string): Promise<AppSummary[]>;
|
|
110
110
|
declare function fetchDatasets(project: string, status?: string): Promise<DatasetSummary[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-directory.d.ts","sourceRoot":"","sources":["../src/account-directory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"account-directory.d.ts","sourceRoot":"","sources":["../src/account-directory.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import { createInterface } from 'readline/promises';
|
|
|
4
4
|
import { isInteractiveTerminal, normalizeSlugInput, hasJsonFlag, getArg } from './command-line-arguments.js';
|
|
5
5
|
import { printLine, printError, printJson } from './cli-console-output.js';
|
|
6
6
|
import { sanitizeTerminalText, parseJsonResponse } from './json-response.js';
|
|
7
|
+
import { PROJECT_LIST, readDirectoryList, TEAM_LIST } from './directory-list-read.js';
|
|
7
8
|
import { authedFetch } from './http.js';
|
|
8
9
|
const TASK_STATUS_ACTION_LABELS = {
|
|
9
10
|
paused: {
|
|
@@ -48,23 +49,13 @@ async function promptSelect(title, items, label, options) {
|
|
|
48
49
|
rl.close();
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
|
-
async function fetchTeams(request = authedFetch) {
|
|
52
|
-
|
|
53
|
-
if (!response.ok) {
|
|
54
|
-
throw new Error(`Failed to fetch teams: ${await response.text()}`);
|
|
55
|
-
}
|
|
56
|
-
const data = await parseJsonResponse(response, 'Teams list');
|
|
57
|
-
return data.teams;
|
|
52
|
+
async function fetchTeams(request = authedFetch, timeoutMs) {
|
|
53
|
+
return await readDirectoryList(request, '/api/cli/teams', TEAM_LIST, timeoutMs);
|
|
58
54
|
}
|
|
59
|
-
async function fetchProjects(teamSlug, request = authedFetch) {
|
|
55
|
+
async function fetchProjects(teamSlug, request = authedFetch, timeoutMs) {
|
|
60
56
|
const normalizedTeamSlug = teamSlug ? normalizeSlugInput(teamSlug) : undefined;
|
|
61
57
|
const query = normalizedTeamSlug ? `?teamSlug=${encodeURIComponent(normalizedTeamSlug)}` : '';
|
|
62
|
-
|
|
63
|
-
if (!response.ok) {
|
|
64
|
-
throw new Error(`Failed to fetch projects: ${await response.text()}`);
|
|
65
|
-
}
|
|
66
|
-
const data = await parseJsonResponse(response, 'Projects list');
|
|
67
|
-
return data.projects;
|
|
58
|
+
return await readDirectoryList(request, `/api/cli/projects${query}`, PROJECT_LIST, timeoutMs);
|
|
68
59
|
}
|
|
69
60
|
async function fetchTasks(project, status = 'active') {
|
|
70
61
|
const params = new URLSearchParams();
|
|
@@ -115,24 +106,8 @@ async function createTeamOnServer(name, request = authedFetch) {
|
|
|
115
106
|
return await createTeamWithDeadline(name, request);
|
|
116
107
|
}
|
|
117
108
|
async function createProjectOnServer(teamSlug, name, request = authedFetch) {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
headers: { 'Content-Type': 'application/json' },
|
|
121
|
-
body: JSON.stringify({ teamSlug, name }),
|
|
122
|
-
});
|
|
123
|
-
if (!response.ok) {
|
|
124
|
-
throw new Error(`Failed to create project: ${await response.text()}`);
|
|
125
|
-
}
|
|
126
|
-
const data = await parseJsonResponse(response, 'Project create');
|
|
127
|
-
return {
|
|
128
|
-
id: data.project.id,
|
|
129
|
-
name: data.project.name,
|
|
130
|
-
slug: data.project.slug,
|
|
131
|
-
teamId: data.project.teamId || '',
|
|
132
|
-
teamName: data.project.teamName || data.project.teamSlug,
|
|
133
|
-
teamSlug: data.project.teamSlug,
|
|
134
|
-
role: data.project.role || 'admin',
|
|
135
|
-
};
|
|
109
|
+
const { createProjectWithDeadline } = await import('./project-create-workflow.js');
|
|
110
|
+
return await createProjectWithDeadline(teamSlug, name, request);
|
|
136
111
|
}
|
|
137
112
|
async function resolveProjectSelection(projectArg) {
|
|
138
113
|
projectArg = projectArg || process.env.ORIZU_PROJECT || null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-commands.d.ts","sourceRoot":"","sources":["../src/auth-commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth-commands.d.ts","sourceRoot":"","sources":["../src/auth-commands.ts"],"names":[],"mappings":"AA6BA,iBAAS,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAEnE;AAMD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAQD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,GAAG,CAwB5E;AA6BD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAgBtD;AAED,iBAAS,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzC;AA4BD,iBAAe,KAAK,CAAC,eAAe,CAAC,EAAE,MAAM,iBAoC5C;AAoHD,iBAAe,MAAM,kBAWpB;AAED,iBAAe,MAAM,CAAC,eAAe,CAAC,EAAE,MAAM,iBAwC7C;AAED,iBAAe,QAAQ,kBA0BtB;AAED,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA"}
|
package/dist/auth-commands.js
CHANGED
|
@@ -4,12 +4,11 @@ import { spawn } from 'child_process';
|
|
|
4
4
|
import { createServer } from 'http';
|
|
5
5
|
import { sanitizeTerminalText, parseJsonResponse } from './json-response.js';
|
|
6
6
|
import { isInteractiveTerminal, hasArg, hasJsonFlag, getArg } from './command-line-arguments.js';
|
|
7
|
-
import { getBaseUrl, resolveLoginTarget, resolveLogoutTarget, assertSecureTokenTransport, authedFetch,
|
|
8
|
-
import { hasResolvableAuth, rememberProcessSecret, saveServerCredentials, getServerCredentials,
|
|
7
|
+
import { getBaseUrl, resolveLoginTarget, resolveLogoutTarget, assertSecureTokenTransport, authedFetch, } from './http.js';
|
|
8
|
+
import { clearUnreadableServerCredentials, hasResolvableAuth, rememberProcessSecret, saveServerCredentials, getServerCredentials, resolveAuthTokenForBaseUrl, } from './credentials.js';
|
|
9
9
|
import { printJson, printLine, printLoginProgress } from './cli-console-output.js';
|
|
10
10
|
import { shouldUseHeadlessLogin, waitForHeadlessAuthorization } from './headless-login.js';
|
|
11
11
|
import { renderCliAuthBrowserPage } from './cli-auth-browser-page.js';
|
|
12
|
-
import { describeLogoutHttpFailure, describeLogoutTransportFailure } from './logout-diagnostic.js';
|
|
13
12
|
import { resolveProjectSelection } from './account-directory.js';
|
|
14
13
|
function isNodeError(error) {
|
|
15
14
|
return error instanceof Error;
|
|
@@ -102,6 +101,9 @@ function resolveAuthCallbackPort() {
|
|
|
102
101
|
}
|
|
103
102
|
return parsed;
|
|
104
103
|
}
|
|
104
|
+
function isCredentialsFileFailure(message) {
|
|
105
|
+
return message.startsWith('ORIZU_CREDENTIALS_READ_FAILED:') || message.startsWith('ORIZU_CREDENTIALS_WRITE_FAILED:');
|
|
106
|
+
}
|
|
105
107
|
async function login(baseUrlOverride) {
|
|
106
108
|
const target = baseUrlOverride !== undefined
|
|
107
109
|
? { baseUrl: baseUrlOverride, isDefault: false }
|
|
@@ -114,14 +116,15 @@ async function login(baseUrlOverride) {
|
|
|
114
116
|
loginData = await authenticateAtBaseUrl(baseUrl);
|
|
115
117
|
if (!loginData)
|
|
116
118
|
return;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
});
|
|
119
|
+
const apiKey = loginData.apiKey;
|
|
120
|
+
// Waits for the lock without freezing the CLI (ORI-2421).
|
|
121
|
+
const { withCredentialsTransaction } = await import('./credentials-transaction.js');
|
|
122
|
+
await withCredentialsTransaction(async () => saveServerCredentials(baseUrl, { credentialType: 'pat', apiKey }));
|
|
121
123
|
}
|
|
122
124
|
catch (error) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
126
|
+
// Reading or saving credentials.json is a disk problem, not a connection one.
|
|
127
|
+
if (target.isDefault && !isCredentialsFileFailure(detail)) {
|
|
125
128
|
throw new Error(`${detail} Check connectivity to https://app.orizu.ai, then retry \`orizu login\`.`, { cause: error });
|
|
126
129
|
}
|
|
127
130
|
throw error;
|
|
@@ -247,6 +250,15 @@ async function logout(baseUrlOverride) {
|
|
|
247
250
|
const { baseUrl, credentialBaseUrl } = resolveLogoutTarget(baseUrlOverride);
|
|
248
251
|
const credentials = getServerCredentials(credentialBaseUrl);
|
|
249
252
|
if (!credentials) {
|
|
253
|
+
// A saved sign-in this CLI cannot read is removed: it may be a pasted token (ORI-2675).
|
|
254
|
+
if (clearUnreadableServerCredentials(credentialBaseUrl)) {
|
|
255
|
+
if (hasJsonFlag()) {
|
|
256
|
+
printJson({ status: 'removed-unreadable', server: baseUrl });
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
printLine(`Removed the saved sign-in for ${sanitizeTerminalText(baseUrl)}, which this CLI could not read.`);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
250
262
|
if (hasJsonFlag()) {
|
|
251
263
|
printJson({ status: 'already-logged-out', server: baseUrl });
|
|
252
264
|
return;
|
|
@@ -254,35 +266,19 @@ async function logout(baseUrlOverride) {
|
|
|
254
266
|
printLine(`Already logged out for ${sanitizeTerminalText(baseUrl)}.`);
|
|
255
267
|
return;
|
|
256
268
|
}
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
try {
|
|
266
|
-
assertSecureTokenTransport(baseUrl);
|
|
267
|
-
const response = await fetch(`${baseUrl}/api/cli/auth/logout`, {
|
|
268
|
-
method: 'POST',
|
|
269
|
-
headers: {
|
|
270
|
-
'Content-Type': 'application/json',
|
|
271
|
-
Authorization: `Bearer ${authorizationToken}`,
|
|
272
|
-
},
|
|
273
|
-
body: 'refreshToken' in credentials
|
|
274
|
-
? JSON.stringify({ refreshToken: credentials.refreshToken })
|
|
275
|
-
: undefined,
|
|
276
|
-
...credentialRequestRedirectPolicy(),
|
|
277
|
-
});
|
|
278
|
-
if (!response.ok) {
|
|
279
|
-
remoteLogoutError = await describeLogoutHttpFailure(response, logoutSecrets);
|
|
269
|
+
const { storedLogout } = await import('./stored-session-requests.js');
|
|
270
|
+
const { remoteError: remoteLogoutError, localCredentialCleared } = await storedLogout(baseUrl, credentialBaseUrl, credentials);
|
|
271
|
+
// Another login saved for this server while logout was out is kept.
|
|
272
|
+
if (!localCredentialCleared && getServerCredentials(credentialBaseUrl)) {
|
|
273
|
+
if (hasJsonFlag()) {
|
|
274
|
+
printJson({ status: 'changed', server: baseUrl, remoteLogoutError });
|
|
275
|
+
process.exitCode = 1;
|
|
276
|
+
return;
|
|
280
277
|
}
|
|
278
|
+
if (remoteLogoutError)
|
|
279
|
+
console.warn(`Warning: remote logout failed: ${remoteLogoutError}`);
|
|
280
|
+
throw new Error(`ORIZU_CREDENTIALS_CHANGED: another login was saved for ${sanitizeTerminalText(baseUrl)} during logout; it was kept. Run orizu logout again to remove it.`);
|
|
281
281
|
}
|
|
282
|
-
catch (error) {
|
|
283
|
-
remoteLogoutError = describeLogoutTransportFailure(error, logoutSecrets);
|
|
284
|
-
}
|
|
285
|
-
clearServerCredentials(credentialBaseUrl);
|
|
286
282
|
if (hasJsonFlag()) {
|
|
287
283
|
printJson({ status: 'logged-out', server: baseUrl, remoteLogoutError });
|
|
288
284
|
return;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A credentials transaction whose wait for the lock stays responsive. The
|
|
3
|
+
* in-process rules are credentials.ts's: one holder per process, and nested
|
|
4
|
+
* writes only from the holder's own async context.
|
|
5
|
+
*/
|
|
6
|
+
export declare function withCredentialsTransaction<T>(operation: () => Promise<T>, signal?: AbortSignal | null): Promise<T>;
|
|
7
|
+
//# sourceMappingURL=credentials-transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials-transaction.d.ts","sourceRoot":"","sources":["../src/credentials-transaction.ts"],"names":[],"mappings":"AA8DA;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAC1B,OAAO,CAAC,CAAC,CAAC,CAEZ"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Waiting for the credentials lock without freezing the process (ORI-2421).
|
|
2
|
+
// Loaded only by stored-login code (refresh, logout, login), never on the
|
|
3
|
+
// ORIZU_TOKEN / ORIZU_TOKEN_FILE path, which must not load Effect.
|
|
4
|
+
import { Cause, Effect, Exit } from 'effect';
|
|
5
|
+
import { CREDENTIALS_LOCK_RETRY_MS, credentialsLockTimeoutError, credentialsLockTimeoutMs, releaseCredentialsLock, tryAcquireCredentialsLock, withCredentialsTransactionLockAsync, } from './credentials.js';
|
|
6
|
+
/**
|
|
7
|
+
* Try the lock, sleep, try again, until ORIZU_CREDENTIALS_LOCK_TIMEOUT_MS.
|
|
8
|
+
* Timers and stop handlers keep running while it waits, and `signal` stops
|
|
9
|
+
* the wait. A try is one synchronous step, so a stop never lands inside it.
|
|
10
|
+
* A lock a try takes is noted at once, and handed back if the run then ends
|
|
11
|
+
* any way other than returning it, wherever a stop lands.
|
|
12
|
+
*/
|
|
13
|
+
function acquireLock(signal) {
|
|
14
|
+
const timeoutMs = credentialsLockTimeoutMs();
|
|
15
|
+
const deadline = Date.now() + timeoutMs;
|
|
16
|
+
let taken = null;
|
|
17
|
+
const attempt = Effect.try({
|
|
18
|
+
try: () => (taken = tryAcquireCredentialsLock()),
|
|
19
|
+
catch: cause => cause instanceof Error ? cause : new Error(String(cause)),
|
|
20
|
+
});
|
|
21
|
+
const program = Effect.gen(function* () {
|
|
22
|
+
while (true) {
|
|
23
|
+
const lock = yield* attempt;
|
|
24
|
+
if (lock)
|
|
25
|
+
return lock;
|
|
26
|
+
const remainingMs = deadline - Date.now();
|
|
27
|
+
if (remainingMs <= 0)
|
|
28
|
+
return yield* Effect.fail(credentialsLockTimeoutError(timeoutMs));
|
|
29
|
+
yield* Effect.sleep(Math.min(CREDENTIALS_LOCK_RETRY_MS, remainingMs));
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return run(program, signal, () => {
|
|
33
|
+
if (!taken)
|
|
34
|
+
return;
|
|
35
|
+
try {
|
|
36
|
+
releaseCredentialsLock(taken);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// The stop or failure is what the caller needs to see.
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/** A stop by `signal` rejects with its reason, as an aborted fetch would. */
|
|
44
|
+
async function run(program, signal, onNotReturned) {
|
|
45
|
+
const exit = await Effect.runPromiseExit(program, signal ? { signal } : undefined);
|
|
46
|
+
if (Exit.isSuccess(exit))
|
|
47
|
+
return exit.value;
|
|
48
|
+
onNotReturned();
|
|
49
|
+
if (signal?.aborted && Cause.hasInterruptsOnly(exit.cause))
|
|
50
|
+
throw signal.reason;
|
|
51
|
+
throw Cause.squash(exit.cause);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A credentials transaction whose wait for the lock stays responsive. The
|
|
55
|
+
* in-process rules are credentials.ts's: one holder per process, and nested
|
|
56
|
+
* writes only from the holder's own async context.
|
|
57
|
+
*/
|
|
58
|
+
export function withCredentialsTransaction(operation, signal) {
|
|
59
|
+
return withCredentialsTransactionLockAsync(operation, () => acquireLock(signal));
|
|
60
|
+
}
|
package/dist/credentials.d.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { ServerCredentials, StoredCredentialsV2, StoredCredentialsV3 } from './types.js';
|
|
2
2
|
export declare function getConfigDir(): string;
|
|
3
|
+
export declare const CREDENTIALS_LOCK_RETRY_MS = 20;
|
|
4
|
+
export interface HeldCredentialsLock {
|
|
5
|
+
path: string;
|
|
6
|
+
metadata: string;
|
|
7
|
+
depth: number;
|
|
8
|
+
asyncOwner?: symbol;
|
|
9
|
+
released: Promise<void>;
|
|
10
|
+
resolveReleased: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function credentialsLockTimeoutMs(): number;
|
|
13
|
+
export declare function credentialsLockTimeoutError(timeoutMs: number): Error;
|
|
14
|
+
/**
|
|
15
|
+
* One try at the cross-process lock. Returns null when another owner holds
|
|
16
|
+
* it. The waits between tries belong to the caller: a blocking one below for
|
|
17
|
+
* synchronous writers, an Effect sleep in credentials-transaction.ts.
|
|
18
|
+
*/
|
|
19
|
+
export declare function tryAcquireCredentialsLock(): HeldCredentialsLock | null;
|
|
20
|
+
export declare function releaseCredentialsLock(lock: HeldCredentialsLock): void;
|
|
3
21
|
/**
|
|
4
22
|
* Runs a synchronous credentials transaction under the one process-wide and
|
|
5
23
|
* cross-process lock. Exported so real-process fixtures can hold the production
|
|
@@ -11,7 +29,7 @@ export declare function withCredentialsTransactionLock<T>(operation: () => T): T
|
|
|
11
29
|
* synchronous credential writes are admitted only from this transaction's
|
|
12
30
|
* async execution context; unrelated same-process work must wait or fail.
|
|
13
31
|
*/
|
|
14
|
-
export declare function withCredentialsTransactionLockAsync<T>(operation: () => Promise<T>): Promise<T>;
|
|
32
|
+
export declare function withCredentialsTransactionLockAsync<T>(operation: () => Promise<T>, acquire?: () => HeldCredentialsLock | Promise<HeldCredentialsLock>): Promise<T>;
|
|
15
33
|
export declare function loadCredentialsConfig(): StoredCredentialsV2 | StoredCredentialsV3 | null;
|
|
16
34
|
export declare function getServerCredentials(baseUrl: string): ServerCredentials | null;
|
|
17
35
|
export declare function saveServerCredentials(baseUrl: string, credentials: ServerCredentials): void;
|
|
@@ -63,5 +81,10 @@ export declare function hasResolvableAuth(baseUrl: string): boolean;
|
|
|
63
81
|
export declare function setActiveBaseUrl(baseUrl: string | null): void;
|
|
64
82
|
export declare function clearServerCredentialsIfCurrent(baseUrl: string, expected: ServerCredentials): boolean;
|
|
65
83
|
export declare function clearServerCredentials(baseUrl: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Remove a saved sign-in this CLI cannot read (it may be a pasted token).
|
|
86
|
+
* Returns false when there is none, or when it has become readable since.
|
|
87
|
+
*/
|
|
88
|
+
export declare function clearUnreadableServerCredentials(baseUrl: string): boolean;
|
|
66
89
|
export declare function clearCredentialsFile(): void;
|
|
67
90
|
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,iBAAiB,EAEjB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,iBAAiB,EAEjB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,YAAY,CAAA;AAYnB,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAQD,eAAO,MAAM,yBAAyB,KAAK,CAAA;AAU3C,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IACvB,eAAe,EAAE,MAAM,IAAI,CAAA;CAC5B;AAsBD,wBAAgB,wBAAwB,IAAI,MAAM,CAMjD;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAIpE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,mBAAmB,GAAG,IAAI,CA6CtE;AAcD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAWtE;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAgCvE;AAaD;;;;GAIG;AACH,wBAAsB,mCAAmC,CAAC,CAAC,EACzD,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAG3B,OAAO,GAAE,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAA0B,GACzF,OAAO,CAAC,CAAC,CAAC,CAyCZ;AAsHD,wBAAgB,qBAAqB,IAAI,mBAAmB,GAAG,mBAAmB,GAAG,IAAI,CA8BxF;AA0BD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAuB9E;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,QAepF;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,QAatF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAS3F;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,iBAAiB,GAC7B,OAAO,CAUT;AAmBD,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAMhD;AAED,uFAAuF;AACvF,wBAAgB,uBAAuB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyCxE;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,yBAAyB,IAAI,SAAS,MAAM,EAAE,CAE7D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CA0BrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAclE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAS1D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,QAMtD;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAWT;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAc/D;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAYzE;AAED,wBAAgB,oBAAoB,SAKnC"}
|