@antasphere/chassis-cli 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +82 -0
- package/dist/commands/auth.d.ts +6 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +582 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/completion.d.ts +5 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +85 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/demo.d.ts +12 -0
- package/dist/commands/demo.d.ts.map +1 -0
- package/dist/commands/demo.js +210 -0
- package/dist/commands/demo.js.map +1 -0
- package/dist/commands/files.d.ts +21 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +178 -0
- package/dist/commands/files.js.map +1 -0
- package/dist/commands/projects.d.ts +38 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +386 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/teams.d.ts +46 -0
- package/dist/commands/teams.d.ts.map +1 -0
- package/dist/commands/teams.js +265 -0
- package/dist/commands/teams.js.map +1 -0
- package/dist/commands/workspaces.d.ts +22 -0
- package/dist/commands/workspaces.d.ts.map +1 -0
- package/dist/commands/workspaces.js +116 -0
- package/dist/commands/workspaces.js.map +1 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +54 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +152 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +456 -0
- package/dist/context.js.map +1 -0
- package/dist/identity.d.ts +36 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +18 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/kit.d.ts +46 -0
- package/dist/kit.d.ts.map +1 -0
- package/dist/kit.js +2 -0
- package/dist/kit.js.map +1 -0
- package/dist/open.d.ts +27 -0
- package/dist/open.d.ts.map +1 -0
- package/dist/open.js +45 -0
- package/dist/open.js.map +1 -0
- package/dist/owner-session.d.ts +34 -0
- package/dist/owner-session.d.ts.map +1 -0
- package/dist/owner-session.js +106 -0
- package/dist/owner-session.js.map +1 -0
- package/dist/program.d.ts +5 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +150 -0
- package/dist/program.js.map +1 -0
- package/dist/safe-write.d.ts +46 -0
- package/dist/safe-write.d.ts.map +1 -0
- package/dist/safe-write.js +127 -0
- package/dist/safe-write.js.map +1 -0
- package/dist/stdin.d.ts +4 -0
- package/dist/stdin.d.ts.map +1 -0
- package/dist/stdin.js +36 -0
- package/dist/stdin.js.map +1 -0
- package/dist/testing/index.d.ts +70 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +67 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/workspace.d.ts +79 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +139 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +43 -3
- package/src/commands/auth.ts +687 -0
- package/src/commands/completion.ts +102 -0
- package/src/commands/demo.ts +271 -0
- package/src/commands/files.ts +197 -0
- package/src/commands/projects.ts +460 -0
- package/src/commands/teams.ts +320 -0
- package/src/commands/workspaces.ts +140 -0
- package/src/config.ts +81 -0
- package/src/context.ts +616 -0
- package/src/identity.ts +48 -0
- package/src/index.ts +70 -0
- package/src/kit.ts +50 -0
- package/src/open.ts +48 -0
- package/src/owner-session.ts +152 -0
- package/src/program.ts +183 -0
- package/src/safe-write.ts +136 -0
- package/src/stdin.ts +39 -0
- package/src/testing/index.ts +129 -0
- package/src/workspace.ts +229 -0
- package/test/host/identity.test.ts +229 -0
- package/test/host/minimal-host.ts +16 -0
- package/test/host/minimal-tool.ts +40 -0
- package/test/suite/cli.test.ts +301 -0
- package/test/suite/config.test.ts +59 -0
- package/test/suite/demo.test.ts +467 -0
- package/test/suite/hub-profile-shared.test.ts +123 -0
- package/test/suite/login.test.ts +743 -0
- package/test/suite/logout.test.ts +247 -0
- package/test/suite/migration.test.ts +109 -0
- package/test/suite/open.test.ts +59 -0
- package/test/suite/profiles.test.ts +380 -0
- package/test/suite/projects.test.ts +550 -0
- package/test/suite/recovery.test.ts +348 -0
- package/test/suite/security.test.ts +199 -0
- package/test/suite/signin-fixtures.ts +204 -0
- package/test/suite/teams.test.ts +354 -0
- package/test/suite/whoami.test.ts +159 -0
- package/test/suite/workspace.test.ts +402 -0
- package/README.md +0 -3
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { type ChassisClient, type ClientOptions } from '@antasphere/chassis-sdk';
|
|
2
|
+
import type { Command } from 'commander';
|
|
3
|
+
import { CliUsageError, type CliIo as CoreCliIo, type ConnectOnDemandOptions, type ProfileSource } from '@antasphere/cli-core';
|
|
4
|
+
import type { CliConfig, CliConfigStore, CliProfile } from './config.js';
|
|
5
|
+
import type { CliIdentity } from './identity.js';
|
|
6
|
+
import { type CliWorkspace, type WorkspaceSelection, type WorkspaceSource } from './workspace.js';
|
|
7
|
+
export { CliUsageError } from '@antasphere/cli-core';
|
|
8
|
+
/**
|
|
9
|
+
* A refusal of the API that a command turned into a sentence (the project
|
|
10
|
+
* verbs do), thrown as the usage error it reads as, with the wire status
|
|
11
|
+
* kept: the runner adds what only it knows, the workspace a 404 was asked of.
|
|
12
|
+
*/
|
|
13
|
+
export declare class CliApiRefusal extends CliUsageError {
|
|
14
|
+
readonly status: number;
|
|
15
|
+
constructor(message: string, status: number);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The tool's I/O seam: cli-core's, plus an injectable stdin reader so the
|
|
19
|
+
* `--*-stdin` secret flags (stdin.ts) stay testable in-process. The bin
|
|
20
|
+
* leaves it unset and the default reads `process.stdin`.
|
|
21
|
+
*/
|
|
22
|
+
export interface CliIo extends CoreCliIo {
|
|
23
|
+
readStdin?: () => Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* `process.stdout` carries `isTTY`; a pipe does not. The only signal the
|
|
26
|
+
* CLI reads before opening a browser unasked (open.ts): a piped run is a
|
|
27
|
+
* script or an agent, and a browser popping up on a build agent is a bug.
|
|
28
|
+
*/
|
|
29
|
+
out: CoreCliIo['out'] & {
|
|
30
|
+
isTTY?: boolean;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The browser opener seam. The bin leaves it unset and the default spawns
|
|
34
|
+
* the platform command (open.ts); tests inject a recorder.
|
|
35
|
+
*/
|
|
36
|
+
openUrl?: (url: string) => void;
|
|
37
|
+
/**
|
|
38
|
+
* The wait seam. The bin leaves it unset and the default is a timer; tests
|
|
39
|
+
* inject a recorder, so a command that waits out a rate wall is tested
|
|
40
|
+
* without the wait.
|
|
41
|
+
*/
|
|
42
|
+
sleep?: (ms: number) => Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Strip terminal control sequences from human output.
|
|
46
|
+
*
|
|
47
|
+
* Almost everything the CLI prints in its human mode is content someone
|
|
48
|
+
* ELSE wrote: annotation bodies and author names from a share-link
|
|
49
|
+
* recipient, the titles of the tool's resources, form-response payloads, stored
|
|
50
|
+
* filenames, and server error messages. A terminal renders ANSI escapes in
|
|
51
|
+
* all of it — colours and cursor moves are the mild end; OSC 8 hyperlinks
|
|
52
|
+
* hide a URL behind friendly text, OSC 52 writes the user's clipboard, and
|
|
53
|
+
* a CSI sequence can scrub the line above so the owner never sees what the
|
|
54
|
+
* command really did.
|
|
55
|
+
*
|
|
56
|
+
* So the human sinks are wrapped (`ttySafeIo`) and everything they print
|
|
57
|
+
* loses C0 (except tab / LF / CR, which the tables and the CSV need), the
|
|
58
|
+
* 8-bit C1 introducers, and complete CSI/OSC/two-character escapes. `--json`
|
|
59
|
+
* output deliberately bypasses this: it is data, not display, and
|
|
60
|
+
* `JSON.stringify` already escapes every C0 byte.
|
|
61
|
+
*/
|
|
62
|
+
export declare function sanitizeForTty(s: string): string;
|
|
63
|
+
/** Wrap an io so every human write is sanitized (see sanitizeForTty). */
|
|
64
|
+
export declare function ttySafeIo(io: CliIo): CliIo;
|
|
65
|
+
export declare function setStdinApiKey(io: CliIo, key: string): void;
|
|
66
|
+
/** The key `--api-key-stdin` already read, if any. */
|
|
67
|
+
export declare function stdinApiKey(io: CliIo): string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* `--json` output goes to the RAW sink: machine output must stay
|
|
70
|
+
* byte-exact, and JSON.stringify already escapes the C0 range.
|
|
71
|
+
*/
|
|
72
|
+
export declare function printJson(io: CliIo, value: unknown): void;
|
|
73
|
+
/**
|
|
74
|
+
* Where this invocation's credential came from, in the order it resolves:
|
|
75
|
+
* the flag (or `--api-key-stdin`), the tool's key variable, the profile's own
|
|
76
|
+
* key (the tool's login), the key the hub exchange cached on the profile, a
|
|
77
|
+
* fresh hub exchange run by this very command, or nothing yet.
|
|
78
|
+
*/
|
|
79
|
+
export type CredentialSource = 'flag' | 'env' | 'profile' | 'hub-cache' | 'hub-exchange' | 'none';
|
|
80
|
+
export interface CliContext<TClient extends ChassisClient<string> = ChassisClient<string>> {
|
|
81
|
+
client: TClient;
|
|
82
|
+
baseUrl: string;
|
|
83
|
+
apiKey: string | undefined;
|
|
84
|
+
/** Where `apiKey` came from (`whoami` says it; the recovery reads it). */
|
|
85
|
+
credentialSource: CredentialSource;
|
|
86
|
+
json: boolean;
|
|
87
|
+
io: CliIo;
|
|
88
|
+
/**
|
|
89
|
+
* The profile this run selected (cli-core `selectProfile`: --profile, the
|
|
90
|
+
* instance URL, the active profile, the implicit `cloud` profile). Always
|
|
91
|
+
* named on a tool with a cloud URL; `profileCreated` says it is not on
|
|
92
|
+
* disk yet.
|
|
93
|
+
*/
|
|
94
|
+
profileName: string | undefined;
|
|
95
|
+
profileSource: ProfileSource | undefined;
|
|
96
|
+
profileCreated: boolean;
|
|
97
|
+
config: CliConfig;
|
|
98
|
+
/**
|
|
99
|
+
* What selects the workspace (workspace.ts), undefined = the server's
|
|
100
|
+
* default. Resolved here, APPLIED by `requireApiKey`: a name needs `/me`,
|
|
101
|
+
* and `resolveContext` is synchronous.
|
|
102
|
+
*/
|
|
103
|
+
workspaceSelection: WorkspaceSelection | undefined;
|
|
104
|
+
/** The id `requireApiKey` put on the client; undefined until then, or with no selection. */
|
|
105
|
+
workspaceId: string | undefined;
|
|
106
|
+
}
|
|
107
|
+
/** What `createContext` hands back: the context functions of ONE tool. */
|
|
108
|
+
export interface CliContextKit<TClient extends ChassisClient<string>> {
|
|
109
|
+
resolveProfile(config: CliConfig, requested: string | undefined): {
|
|
110
|
+
name: string | undefined;
|
|
111
|
+
profile: CliProfile | undefined;
|
|
112
|
+
};
|
|
113
|
+
resolveContext(cmd: Command, io: CliIo): CliContext<TClient>;
|
|
114
|
+
requireApiKey(ctx: CliContext<TClient>, opts?: {
|
|
115
|
+
workspace?: boolean;
|
|
116
|
+
}): Promise<string>;
|
|
117
|
+
workspaceSource(ctx: CliContext<TClient>): WorkspaceSource;
|
|
118
|
+
explainWorkspaceRefusal(io: CliIo, e: unknown): Promise<string | null>;
|
|
119
|
+
workspaceNotFoundHint(io: CliIo): string;
|
|
120
|
+
/** The instance a profile names: its `baseUrl`, else the tool's cloud URL. */
|
|
121
|
+
profileUrl(profile: CliProfile | undefined): string;
|
|
122
|
+
/** The `connectOnDemand` options of one context (the tool, the instance, the profile, the wire). */
|
|
123
|
+
connectOptions(ctx: CliContext<TClient>): ConnectOnDemandOptions;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The context functions, bound to one tool: its identity (identity.ts), the
|
|
127
|
+
* client it talks through, and the config and workspace functions already
|
|
128
|
+
* bound to the same identity.
|
|
129
|
+
*/
|
|
130
|
+
export declare function createContext<TClient extends ChassisClient<string>>(input: {
|
|
131
|
+
identity: CliIdentity;
|
|
132
|
+
createClient: (options: ClientOptions) => TClient;
|
|
133
|
+
config: Pick<CliConfigStore, 'loadConfig' | 'removeConnectKey'>;
|
|
134
|
+
workspace: CliWorkspace;
|
|
135
|
+
}): CliContextKit<TClient>;
|
|
136
|
+
/**
|
|
137
|
+
* `--all` for a cursor-paginated list: the first page, then every next page
|
|
138
|
+
* while the server hands a cursor, the rows in order. The one loop behind
|
|
139
|
+
* every `--all`; a server that repeats a cursor is stopped here, once.
|
|
140
|
+
*/
|
|
141
|
+
export declare function drainPages<T>(first: {
|
|
142
|
+
rows: T[];
|
|
143
|
+
nextCursor: string | null;
|
|
144
|
+
}, fetchPage: (cursor: string) => Promise<{
|
|
145
|
+
rows: T[];
|
|
146
|
+
nextCursor: string | null;
|
|
147
|
+
}>): Promise<T[]>;
|
|
148
|
+
/** Human-readable size (B / KB / MB) for the listing commands. */
|
|
149
|
+
export declare function fmtBytes(n: number): string;
|
|
150
|
+
/** Minimal aligned two-space table for human output. */
|
|
151
|
+
export declare function table(rows: string[][]): string;
|
|
152
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACnG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAIL,aAAa,EASb,KAAK,KAAK,IAAI,SAAS,EACvB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,aAAa;aAG5B,MAAM,EAAE,MAAM;gBAD9B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM;CAKjC;AAED;;;;GAIG;AACH,MAAM,WAAW,KAAM,SAAQ,SAAS;IACtC,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC;;;;OAIG;IACH,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,GAAG;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5C;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC;;;;OAIG;IACH,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAgBhD;AAKD,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,EAAE,EAAE,KAAK,GAAG,KAAK,CAY1C;AAQD,wBAAgB,cAAc,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,EAAE,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAEzD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAEzD;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,MAAM,CAAC;AAElG,MAAM,WAAW,UAAU,CAAC,OAAO,SAAS,aAAa,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC;IACvF,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,0EAA0E;IAC1E,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,KAAK,CAAC;IACV;;;;;OAKG;IACH,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IACzC,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,kBAAkB,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACnD,4FAA4F;IAC5F,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAeD,0EAA0E;AAC1E,MAAM,WAAW,aAAa,CAAC,OAAO,SAAS,aAAa,CAAC,MAAM,CAAC;IAClE,cAAc,CACZ,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B;QAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE,CAAC;IACjE,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAC7D,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzF,eAAe,CAAC,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC;IAC3D,uBAAuB,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvE,qBAAqB,CAAC,EAAE,EAAE,KAAK,GAAG,MAAM,CAAC;IACzC,8EAA8E;IAC9E,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IACpD,oGAAoG;IACpG,cAAc,CAAC,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC;CAClE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,SAAS,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE;IAC1E,QAAQ,EAAE,WAAW,CAAC;IACtB,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC;IAClD,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,GAAG,kBAAkB,CAAC,CAAC;IAChE,SAAS,EAAE,YAAY,CAAC;CACzB,GAAG,aAAa,CAAC,OAAO,CAAC,CAoVzB;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,KAAK,EAAE;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAC/C,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,GAC/E,OAAO,CAAC,CAAC,EAAE,CAAC,CAWd;AAED,kEAAkE;AAClE,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI1C;AAED,wDAAwD;AACxD,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAc9C"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
import { PlatformApiError } from '@antasphere/chassis-sdk';
|
|
2
|
+
import { activeHubProfile, CLOUD_PROFILE, CliAuthClient, CliUsageError, connectOnDemand, lookupConnectKey, printJson as corePrintJson, refreshConnectKey, resolveApiKey, resolveBaseUrl, sameInstance, selectProfile } from '@antasphere/cli-core';
|
|
3
|
+
import { isWorkspaceId, matchWorkspace } from './workspace.js';
|
|
4
|
+
// The injectable I/O seam, the usage-error class, and the resolution
|
|
5
|
+
// helpers live in @antasphere/cli-core (extracted from this CLI); re-exported
|
|
6
|
+
// so the command modules' imports stay unchanged.
|
|
7
|
+
export { CliUsageError } from '@antasphere/cli-core';
|
|
8
|
+
/**
|
|
9
|
+
* A refusal of the API that a command turned into a sentence (the project
|
|
10
|
+
* verbs do), thrown as the usage error it reads as, with the wire status
|
|
11
|
+
* kept: the runner adds what only it knows, the workspace a 404 was asked of.
|
|
12
|
+
*/
|
|
13
|
+
export class CliApiRefusal extends CliUsageError {
|
|
14
|
+
status;
|
|
15
|
+
constructor(message, status) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.status = status;
|
|
18
|
+
this.name = 'CliApiRefusal';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// ── Terminal-control sanitation ──────────────────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Strip terminal control sequences from human output.
|
|
24
|
+
*
|
|
25
|
+
* Almost everything the CLI prints in its human mode is content someone
|
|
26
|
+
* ELSE wrote: annotation bodies and author names from a share-link
|
|
27
|
+
* recipient, the titles of the tool's resources, form-response payloads, stored
|
|
28
|
+
* filenames, and server error messages. A terminal renders ANSI escapes in
|
|
29
|
+
* all of it — colours and cursor moves are the mild end; OSC 8 hyperlinks
|
|
30
|
+
* hide a URL behind friendly text, OSC 52 writes the user's clipboard, and
|
|
31
|
+
* a CSI sequence can scrub the line above so the owner never sees what the
|
|
32
|
+
* command really did.
|
|
33
|
+
*
|
|
34
|
+
* So the human sinks are wrapped (`ttySafeIo`) and everything they print
|
|
35
|
+
* loses C0 (except tab / LF / CR, which the tables and the CSV need), the
|
|
36
|
+
* 8-bit C1 introducers, and complete CSI/OSC/two-character escapes. `--json`
|
|
37
|
+
* output deliberately bypasses this: it is data, not display, and
|
|
38
|
+
* `JSON.stringify` already escapes every C0 byte.
|
|
39
|
+
*/
|
|
40
|
+
export function sanitizeForTty(s) {
|
|
41
|
+
/* eslint-disable no-control-regex -- matching control characters IS the job here. */
|
|
42
|
+
return (s
|
|
43
|
+
// OSC: ESC ] … terminated by BEL, ST (ESC \\) or the end of the string.
|
|
44
|
+
.replace(/\u001b\][\s\S]*?(?:\u0007|\u001b\\|$)/g, '')
|
|
45
|
+
// CSI: ESC [ params intermediates final.
|
|
46
|
+
.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, '')
|
|
47
|
+
// Any other two-character escape (charset switches, RIS, …).
|
|
48
|
+
.replace(/\u001b[@-Z\\-_]/g, '')
|
|
49
|
+
// Whatever is left: stray C0 (ESC included), DEL, and the 8-bit C1
|
|
50
|
+
// block whose 0x9b / 0x9d are CSI / OSC on their own. Tab (0x09),
|
|
51
|
+
// LF (0x0a) and CR (0x0d) survive — tables and CSV are built of them.
|
|
52
|
+
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, ''));
|
|
53
|
+
/* eslint-enable no-control-regex */
|
|
54
|
+
}
|
|
55
|
+
/** Raw sink behind a sanitizing one, so `--json` can still print verbatim. */
|
|
56
|
+
const rawSinks = new WeakMap();
|
|
57
|
+
/** Wrap an io so every human write is sanitized (see sanitizeForTty). */
|
|
58
|
+
export function ttySafeIo(io) {
|
|
59
|
+
const safe = {
|
|
60
|
+
...io,
|
|
61
|
+
// `isTTY` rides along: the open decision reads it through the wrapper.
|
|
62
|
+
out: {
|
|
63
|
+
write: (s) => io.out.write(sanitizeForTty(s)),
|
|
64
|
+
...(io.out.isTTY !== undefined ? { isTTY: io.out.isTTY } : {})
|
|
65
|
+
},
|
|
66
|
+
err: { write: (s) => io.err.write(sanitizeForTty(s)) }
|
|
67
|
+
};
|
|
68
|
+
rawSinks.set(safe, io);
|
|
69
|
+
return safe;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The `--api-key-stdin` value, parked against this invocation's io because
|
|
73
|
+
* `resolveContext` is synchronous and cannot read stdin itself.
|
|
74
|
+
*/
|
|
75
|
+
const stdinApiKeys = new WeakMap();
|
|
76
|
+
export function setStdinApiKey(io, key) {
|
|
77
|
+
stdinApiKeys.set(io, key);
|
|
78
|
+
}
|
|
79
|
+
/** The key `--api-key-stdin` already read, if any. */
|
|
80
|
+
export function stdinApiKey(io) {
|
|
81
|
+
return stdinApiKeys.get(io);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* `--json` output goes to the RAW sink: machine output must stay
|
|
85
|
+
* byte-exact, and JSON.stringify already escapes the C0 range.
|
|
86
|
+
*/
|
|
87
|
+
export function printJson(io, value) {
|
|
88
|
+
corePrintJson(rawSinks.get(io) ?? io, value);
|
|
89
|
+
}
|
|
90
|
+
/** The context whose selection reached the wire, for the runner's error path. */
|
|
91
|
+
const appliedContexts = new WeakMap();
|
|
92
|
+
/**
|
|
93
|
+
* The context functions, bound to one tool: its identity (identity.ts), the
|
|
94
|
+
* client it talks through, and the config and workspace functions already
|
|
95
|
+
* bound to the same identity.
|
|
96
|
+
*/
|
|
97
|
+
export function createContext(input) {
|
|
98
|
+
const { identity, createClient } = input;
|
|
99
|
+
const { loadConfig, removeConnectKey } = input.config;
|
|
100
|
+
const { describeSelection, explainRefusal, pickWorkspaceSelection } = input.workspace;
|
|
101
|
+
const unknownHint = `run \`${identity.bin} profiles\` to list them.`;
|
|
102
|
+
/** The named (or active) profile, erroring on an explicitly named missing one. */
|
|
103
|
+
function resolveProfile(config, requested) {
|
|
104
|
+
const { name, profile } = selectProfile({ config, requested, cloudUrl: identity.cloudUrl, unknownHint });
|
|
105
|
+
return { name, profile };
|
|
106
|
+
}
|
|
107
|
+
function profileUrl(profile) {
|
|
108
|
+
return profile?.baseUrl ?? identity.cloudUrl;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Backend + credential resolution, in its documented order:
|
|
112
|
+
*
|
|
113
|
+
* profile: --profile → the profile of --api-url / <PREFIX>_URL (made in
|
|
114
|
+
* memory, named for the host, when none is saved) → the active
|
|
115
|
+
* profile (`<bin> use`) → the implicit `cloud` profile
|
|
116
|
+
* base URL: --api-url (or --url) → <PREFIX>_URL → profile baseUrl → the
|
|
117
|
+
* tool's cloud URL
|
|
118
|
+
* API key: --api-key → <PREFIX>_API_KEY → profile apiKey
|
|
119
|
+
* → the hub-connect key cached on the profile (cloud instances)
|
|
120
|
+
* workspace: --org / --workspace → <PREFIX>_ORG / <PREFIX>_WORKSPACE
|
|
121
|
+
* → none (the server's default; workspace.ts)
|
|
122
|
+
*
|
|
123
|
+
* A profile is an instance (cli-core 0.5.0): a cached hub key is read only
|
|
124
|
+
* when the profile names the instance this request goes to, so a key
|
|
125
|
+
* minted for the cloud can never be sent to some other instance named by
|
|
126
|
+
* --api-url / <PREFIX>_URL. A self-hosted CLI names its instance once, as a
|
|
127
|
+
* profile; the cloud needs no flag at all.
|
|
128
|
+
*/
|
|
129
|
+
function resolveContext(cmd, io) {
|
|
130
|
+
const opts = cmd.optsWithGlobals();
|
|
131
|
+
const config = loadConfig(io.env);
|
|
132
|
+
const apiUrl = opts.apiUrl ?? opts.url ?? io.env[`${identity.envPrefix}_URL`];
|
|
133
|
+
const selected = selectProfile({
|
|
134
|
+
config,
|
|
135
|
+
requested: opts.profile,
|
|
136
|
+
apiUrl,
|
|
137
|
+
cloudUrl: identity.cloudUrl,
|
|
138
|
+
unknownHint
|
|
139
|
+
});
|
|
140
|
+
const { name: profileName, profile } = selected;
|
|
141
|
+
const baseUrl = resolveBaseUrl({
|
|
142
|
+
flag: apiUrl,
|
|
143
|
+
env: io.env,
|
|
144
|
+
envVar: `${identity.envPrefix}_URL`,
|
|
145
|
+
profile,
|
|
146
|
+
cloudUrl: identity.cloudUrl
|
|
147
|
+
});
|
|
148
|
+
// A profile's own key is sent only to the instance the profile names
|
|
149
|
+
// (verifier round 1, F5): `--profile a --api-url <b>` must never hand
|
|
150
|
+
// a's key to b, exactly as the connect cache below never does.
|
|
151
|
+
const sameProfileInstance = sameInstance(profileUrl(profile), baseUrl);
|
|
152
|
+
let apiKey = resolveApiKey({
|
|
153
|
+
flag: opts.apiKey ?? stdinApiKeys.get(io),
|
|
154
|
+
env: io.env,
|
|
155
|
+
envVar: `${identity.envPrefix}_API_KEY`,
|
|
156
|
+
profile: sameProfileInstance ? profile : undefined
|
|
157
|
+
});
|
|
158
|
+
let credentialSource = opts.apiKey !== undefined || stdinApiKeys.get(io) !== undefined
|
|
159
|
+
? 'flag'
|
|
160
|
+
: io.env[`${identity.envPrefix}_API_KEY`]
|
|
161
|
+
? 'env'
|
|
162
|
+
: apiKey
|
|
163
|
+
? 'profile'
|
|
164
|
+
: 'none';
|
|
165
|
+
if (!apiKey && sameProfileInstance) {
|
|
166
|
+
// No direct key: the connect cache's slot is the ACTIVE hub profile
|
|
167
|
+
// (what `antasphere login` stored) — org-independent by design. A key
|
|
168
|
+
// cached for ANOTHER account than the login now stored on that slot
|
|
169
|
+
// (`antasphere login --email other` since) is never served: it is the
|
|
170
|
+
// other person's credential (PRDCT-3032); connectForKey retires it.
|
|
171
|
+
const hub = activeHubProfile(io.env);
|
|
172
|
+
if (hub.name && !cachedForAnotherAccount(profile, hub.name, hub.profile?.email)) {
|
|
173
|
+
apiKey = lookupConnectKey(profile, hub.name);
|
|
174
|
+
}
|
|
175
|
+
if (apiKey)
|
|
176
|
+
credentialSource = 'hub-cache';
|
|
177
|
+
}
|
|
178
|
+
const fetchImpl = io.fetch ?? globalThis.fetch.bind(globalThis);
|
|
179
|
+
const ctx = {
|
|
180
|
+
client: createClient({ baseUrl, ...(apiKey ? { apiKey } : {}), fetch: fetchImpl }),
|
|
181
|
+
baseUrl,
|
|
182
|
+
apiKey,
|
|
183
|
+
credentialSource,
|
|
184
|
+
json: Boolean(opts.json),
|
|
185
|
+
io,
|
|
186
|
+
profileName,
|
|
187
|
+
profileSource: selected.source,
|
|
188
|
+
profileCreated: selected.created,
|
|
189
|
+
config,
|
|
190
|
+
workspaceSelection: pickWorkspaceSelection({
|
|
191
|
+
workspaceFlag: opts.workspace,
|
|
192
|
+
orgFlag: opts.org,
|
|
193
|
+
env: io.env
|
|
194
|
+
}),
|
|
195
|
+
workspaceId: undefined
|
|
196
|
+
};
|
|
197
|
+
if (credentialSource === 'hub-cache' && apiKey) {
|
|
198
|
+
// A cached key may have been revoked at the hub since it was minted
|
|
199
|
+
// (a swept membership, a logout elsewhere): the client's fetch recovers
|
|
200
|
+
// once, below, instead of stranding the person on a 401.
|
|
201
|
+
ctx.client = createClient({ baseUrl, apiKey, fetch: recoveringFetch(ctx, fetchImpl) });
|
|
202
|
+
}
|
|
203
|
+
return ctx;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The cached connect key on `slot` was minted for another Antasphere
|
|
207
|
+
* account than the one whose login the slot now holds. Both addresses must
|
|
208
|
+
* be known: a cache entry or a hub profile without one is trusted as before.
|
|
209
|
+
*/
|
|
210
|
+
function cachedForAnotherAccount(profile, slot, hubEmail) {
|
|
211
|
+
const cached = profile?.connectKeys?.[slot]?.email;
|
|
212
|
+
if (!cached || !hubEmail)
|
|
213
|
+
return false;
|
|
214
|
+
return cached.toLowerCase() !== hubEmail.toLowerCase();
|
|
215
|
+
}
|
|
216
|
+
const NO_KEY_MESSAGE = `An API key is required. Sign in (\`${identity.bin} login\`), pass --api-key, or set ` +
|
|
217
|
+
`${identity.envPrefix}_API_KEY.`;
|
|
218
|
+
/** The tool's own copy for the cli-core seam: the one-command login is the remedy. */
|
|
219
|
+
const MISSING_HUB_LOGIN_MESSAGE = `This ${identity.displayName} instance signs in through Antasphere. Run \`${identity.bin} login\` once ` +
|
|
220
|
+
`(or \`antasphere login\`), then retry — or pass --api-key <${identity.keyPrefix}_…> / set ` +
|
|
221
|
+
`${identity.envPrefix}_API_KEY.`;
|
|
222
|
+
function connectOptions(ctx) {
|
|
223
|
+
const { io } = ctx;
|
|
224
|
+
return {
|
|
225
|
+
tool: identity.tool,
|
|
226
|
+
toolBaseUrl: ctx.baseUrl,
|
|
227
|
+
// A profile with no baseUrl of its own is at the cloud URL (cli-core 0.5.0).
|
|
228
|
+
cloudUrl: identity.cloudUrl,
|
|
229
|
+
profileName: ctx.profileName ?? CLOUD_PROFILE,
|
|
230
|
+
env: io.env,
|
|
231
|
+
// Thread the injected fetch so the probe + exchange stay on the test
|
|
232
|
+
// harness wire (and any proxying the runner set up).
|
|
233
|
+
...(io.fetch ? { fetch: io.fetch } : {}),
|
|
234
|
+
notify: (line) => io.err.write(line),
|
|
235
|
+
messages: { missingHubLogin: MISSING_HUB_LOGIN_MESSAGE }
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* The stranded-key recovery (PRDCT-2947): a fetch that, on the FIRST 401
|
|
240
|
+
* answered to a key served from the connect cache, evicts that key, runs
|
|
241
|
+
* the hub exchange again (cli-core `refreshConnectKey`) and replays the
|
|
242
|
+
* request once with the new key. A second 401 stands. A hub refusal on the
|
|
243
|
+
* way (a restricted tool, a swept account) is the hub's own sentence, exit
|
|
244
|
+
* 3, through the runner. An instance that is no longer cloud recovers
|
|
245
|
+
* nothing and the 401 stands as it is.
|
|
246
|
+
*/
|
|
247
|
+
function recoveringFetch(ctx, base) {
|
|
248
|
+
let recovered = false;
|
|
249
|
+
return async (input, init) => {
|
|
250
|
+
const res = await base(input, init);
|
|
251
|
+
if (res.status !== 401 || recovered || ctx.credentialSource !== 'hub-cache')
|
|
252
|
+
return res;
|
|
253
|
+
recovered = true;
|
|
254
|
+
// A 401 under a workspace selection may be the SELECTION's refusal:
|
|
255
|
+
// the server answers a workspace the person does not belong to exactly
|
|
256
|
+
// like an unknown key (no oracle). Ask `/me` once without it; when the
|
|
257
|
+
// key answers there, it is alive and nothing is evicted, exchanged or
|
|
258
|
+
// replayed (verifier round 1, F2: a refused --org leaked a live key per
|
|
259
|
+
// command). The runner then explains the refusal.
|
|
260
|
+
if (ctx.workspaceId !== undefined && ctx.apiKey) {
|
|
261
|
+
const probe = await base(`${ctx.baseUrl}/api/v1/me`, {
|
|
262
|
+
headers: { authorization: `Bearer ${ctx.apiKey}` }
|
|
263
|
+
}).catch(() => null);
|
|
264
|
+
// Only a probe that ANSWERS 401 proves the key dead (verifier round 2,
|
|
265
|
+
// F10): a probe with no answer, or any other status, keeps the key and
|
|
266
|
+
// lets the 401 stand.
|
|
267
|
+
if (!probe || probe.status !== 401)
|
|
268
|
+
return res;
|
|
269
|
+
}
|
|
270
|
+
const outcome = await refreshConnectKey(connectOptions(ctx));
|
|
271
|
+
if (outcome.outcome === 'not_cloud')
|
|
272
|
+
return res;
|
|
273
|
+
ctx.apiKey = outcome.key;
|
|
274
|
+
ctx.credentialSource = 'hub-exchange';
|
|
275
|
+
ctx.io.err.write('The cached key was refused; signed in again through Antasphere.\n');
|
|
276
|
+
const headers = new Headers(init?.headers);
|
|
277
|
+
headers.set('authorization', `Bearer ${outcome.key}`);
|
|
278
|
+
return base(input, { ...init, headers });
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Requires an API key; throws a friendly message the runner turns into exit 1.
|
|
283
|
+
*
|
|
284
|
+
* When nothing resolved, this is the connect-on-demand seam (binding
|
|
285
|
+
* patterns §7, gcloud model), owned by @antasphere/cli-core since 0.3.0:
|
|
286
|
+
* if — and only if — discovery says the instance is an Antasphere-cloud
|
|
287
|
+
* one, the stored `antasphere login` credential is exchanged (hub → tool)
|
|
288
|
+
* for a USER-scoped tool-local API key, which is cached on the selected
|
|
289
|
+
* profile under the hub profile's name and used for this invocation — and
|
|
290
|
+
* served from that cache on every subsequent run (no re-exchange, no fresh
|
|
291
|
+
* mint). Self-hosted instances never take this branch: they get the
|
|
292
|
+
* classic error unchanged.
|
|
293
|
+
*/
|
|
294
|
+
async function requireApiKey(ctx, opts = {}) {
|
|
295
|
+
const key = ctx.apiKey ?? (await connectForKey(ctx));
|
|
296
|
+
if (opts.workspace !== false)
|
|
297
|
+
await applyWorkspace(ctx);
|
|
298
|
+
return key;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Put the selected workspace on the client (PRDCT-2419). Every signed-in
|
|
302
|
+
* command calls `requireApiKey`, so this is the one place the selection is
|
|
303
|
+
* applied and no command names it. An id is sent as it is (a workspace id
|
|
304
|
+
* or a hub organization id: the server maps the latter and fails closed on
|
|
305
|
+
* one that is not the person's, and `explainWorkspaceRefusal` says so); a
|
|
306
|
+
* name costs one `/me` to find its id. `workspaces` and `workspace default`
|
|
307
|
+
* pass `workspace: false`: they are how a person repairs a selection that
|
|
308
|
+
* no longer works, so they must answer when it does not.
|
|
309
|
+
*/
|
|
310
|
+
async function applyWorkspace(ctx) {
|
|
311
|
+
const selection = ctx.workspaceSelection;
|
|
312
|
+
if (!selection || ctx.workspaceId !== undefined)
|
|
313
|
+
return;
|
|
314
|
+
const id = isWorkspaceId(selection.value)
|
|
315
|
+
? selection.value
|
|
316
|
+
: matchWorkspace((await ctx.client.me()).workspaces, selection.value).id;
|
|
317
|
+
ctx.client.setWorkspace(id);
|
|
318
|
+
ctx.workspaceId = id;
|
|
319
|
+
appliedContexts.set(ctx.io, ctx);
|
|
320
|
+
}
|
|
321
|
+
/** How the workspace of this invocation was chosen (`whoami`). */
|
|
322
|
+
function workspaceSource(ctx) {
|
|
323
|
+
return ctx.workspaceSelection?.source ?? 'default';
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* The sentence for a refusal the SELECTION caused, or null (workspace.ts
|
|
327
|
+
* `explainRefusal`). Asks `/me` once WITHOUT the selection: when that
|
|
328
|
+
* answers, the key is good and the workspace is what was refused. Any
|
|
329
|
+
* failure of the probe means the plain error is the honest one.
|
|
330
|
+
*/
|
|
331
|
+
async function explainWorkspaceRefusal(io, e) {
|
|
332
|
+
const ctx = appliedContexts.get(io);
|
|
333
|
+
if (!ctx?.workspaceSelection || ctx.workspaceId === undefined || !ctx.apiKey)
|
|
334
|
+
return null;
|
|
335
|
+
if (!(e instanceof PlatformApiError))
|
|
336
|
+
return null;
|
|
337
|
+
if (e.code !== 'workspace_mismatch' && e.code !== 'invalid_api_key')
|
|
338
|
+
return null;
|
|
339
|
+
try {
|
|
340
|
+
const fetchImpl = io.fetch ?? globalThis.fetch.bind(globalThis);
|
|
341
|
+
const me = await createClient({ baseUrl: ctx.baseUrl, apiKey: ctx.apiKey, fetch: fetchImpl }).me();
|
|
342
|
+
return explainRefusal({
|
|
343
|
+
code: e.code,
|
|
344
|
+
status: e.status,
|
|
345
|
+
selection: ctx.workspaceSelection,
|
|
346
|
+
workspaceId: ctx.workspaceId,
|
|
347
|
+
me,
|
|
348
|
+
baseUrl: ctx.baseUrl
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* The hint for a 404 under a selection: a resource id (a linked folder's, a
|
|
357
|
+
* pasted one) lives in ONE workspace, and the same id asked of another is
|
|
358
|
+
* "not found" — true, and useless without the workspace that was asked.
|
|
359
|
+
*/
|
|
360
|
+
function workspaceNotFoundHint(io) {
|
|
361
|
+
const ctx = appliedContexts.get(io);
|
|
362
|
+
if (!ctx?.workspaceSelection || ctx.workspaceId === undefined)
|
|
363
|
+
return '';
|
|
364
|
+
const { workspaceSelection: selection } = ctx;
|
|
365
|
+
const noun = selection.kind === 'org' ? 'organization' : 'workspace';
|
|
366
|
+
return ` (looked in the ${noun} "${selection.value}", selected by ${describeSelection(selection)})`;
|
|
367
|
+
}
|
|
368
|
+
async function connectForKey(ctx) {
|
|
369
|
+
const { io } = ctx;
|
|
370
|
+
// The cached key of another account (the hub login on the slot changed)
|
|
371
|
+
// is revoked on its instance and forgotten before the exchange runs for
|
|
372
|
+
// the account now signed in (PRDCT-3032). Best effort: a dead key
|
|
373
|
+
// answers 401 and is forgotten all the same.
|
|
374
|
+
const hub = activeHubProfile(io.env);
|
|
375
|
+
if (ctx.profileName && hub.name) {
|
|
376
|
+
const profile = loadConfig(io.env).profiles[ctx.profileName];
|
|
377
|
+
if (cachedForAnotherAccount(profile, hub.name, hub.profile?.email)) {
|
|
378
|
+
const stale = profile?.connectKeys?.[hub.name];
|
|
379
|
+
if (stale) {
|
|
380
|
+
io.err.write(`The ${identity.displayName} key cached for ${stale.email ?? 'another Antasphere login'} is retired: ` +
|
|
381
|
+
`the Antasphere login is now ${hub.profile?.email ?? 'another account'}.\n`);
|
|
382
|
+
const auth = new CliAuthClient({
|
|
383
|
+
baseUrl: profileUrl(profile),
|
|
384
|
+
...(io.fetch ? { fetch: io.fetch } : {})
|
|
385
|
+
});
|
|
386
|
+
await auth.revoke(stale.apiKey).catch(() => undefined);
|
|
387
|
+
removeConnectKey(io.env, ctx.profileName, hub.name);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
const outcome = await connectOnDemand(connectOptions(ctx));
|
|
392
|
+
if (outcome.outcome === 'not_cloud') {
|
|
393
|
+
// Self-hosted / unreachable: the classic error, byte-identical.
|
|
394
|
+
throw new CliUsageError(NO_KEY_MESSAGE);
|
|
395
|
+
}
|
|
396
|
+
// The minted key becomes this invocation's credential.
|
|
397
|
+
ctx.apiKey = outcome.key;
|
|
398
|
+
ctx.credentialSource = outcome.cached ? 'hub-cache' : 'hub-exchange';
|
|
399
|
+
const fetchImpl = io.fetch ?? globalThis.fetch.bind(globalThis);
|
|
400
|
+
ctx.client = createClient({
|
|
401
|
+
baseUrl: ctx.baseUrl,
|
|
402
|
+
apiKey: outcome.key,
|
|
403
|
+
fetch: outcome.cached ? recoveringFetch(ctx, fetchImpl) : fetchImpl
|
|
404
|
+
});
|
|
405
|
+
return outcome.key;
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
resolveProfile,
|
|
409
|
+
resolveContext,
|
|
410
|
+
requireApiKey,
|
|
411
|
+
workspaceSource,
|
|
412
|
+
explainWorkspaceRefusal,
|
|
413
|
+
workspaceNotFoundHint,
|
|
414
|
+
profileUrl,
|
|
415
|
+
connectOptions
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* `--all` for a cursor-paginated list: the first page, then every next page
|
|
420
|
+
* while the server hands a cursor, the rows in order. The one loop behind
|
|
421
|
+
* every `--all`; a server that repeats a cursor is stopped here, once.
|
|
422
|
+
*/
|
|
423
|
+
export async function drainPages(first, fetchPage) {
|
|
424
|
+
const rows = [...first.rows];
|
|
425
|
+
const seen = new Set();
|
|
426
|
+
let cursor = first.nextCursor;
|
|
427
|
+
while (cursor && !seen.has(cursor)) {
|
|
428
|
+
seen.add(cursor);
|
|
429
|
+
const page = await fetchPage(cursor);
|
|
430
|
+
rows.push(...page.rows);
|
|
431
|
+
cursor = page.nextCursor;
|
|
432
|
+
}
|
|
433
|
+
return rows;
|
|
434
|
+
}
|
|
435
|
+
/** Human-readable size (B / KB / MB) for the listing commands. */
|
|
436
|
+
export function fmtBytes(n) {
|
|
437
|
+
if (n < 1024)
|
|
438
|
+
return `${n} B`;
|
|
439
|
+
if (n < 1024 * 1024)
|
|
440
|
+
return `${(n / 1024).toFixed(1)} KB`;
|
|
441
|
+
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
442
|
+
}
|
|
443
|
+
/** Minimal aligned two-space table for human output. */
|
|
444
|
+
export function table(rows) {
|
|
445
|
+
if (rows.length === 0)
|
|
446
|
+
return '';
|
|
447
|
+
const first = rows[0];
|
|
448
|
+
const widths = first.map((_, i) => Math.max(...rows.map((r) => (r[i] ?? '').length)));
|
|
449
|
+
return (rows
|
|
450
|
+
.map((r) => r
|
|
451
|
+
.map((cell, i) => (i === r.length - 1 ? cell : (cell ?? '').padEnd(widths[i] ?? 0)))
|
|
452
|
+
.join(' ')
|
|
453
|
+
.trimEnd())
|
|
454
|
+
.join('\n') + '\n');
|
|
455
|
+
}
|
|
456
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|