@atlasauth/cli 0.0.0-stage → 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/README.md +91 -2
- package/dist/args.d.ts +84 -0
- package/dist/args.js +76 -0
- package/dist/args.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +19 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/actions.d.ts +11 -0
- package/dist/commands/actions.js +120 -0
- package/dist/commands/actions.js.map +1 -0
- package/dist/commands/api-keys.d.ts +4 -0
- package/dist/commands/api-keys.js +81 -0
- package/dist/commands/api-keys.js.map +1 -0
- package/dist/commands/auth.d.ts +25 -0
- package/dist/commands/auth.js +94 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.js +716 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/orgs.d.ts +4 -0
- package/dist/commands/orgs.js +72 -0
- package/dist/commands/orgs.js.map +1 -0
- package/dist/commands/sessions.d.ts +4 -0
- package/dist/commands/sessions.js +28 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/shared.d.ts +32 -0
- package/dist/commands/shared.js +60 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/users.d.ts +4 -0
- package/dist/commands/users.js +87 -0
- package/dist/commands/users.js.map +1 -0
- package/dist/commands/webhooks.d.ts +4 -0
- package/dist/commands/webhooks.js +34 -0
- package/dist/commands/webhooks.js.map +1 -0
- package/dist/config-http.d.ts +27 -0
- package/dist/config-http.js +63 -0
- package/dist/config-http.js.map +1 -0
- package/dist/config.d.ts +48 -0
- package/dist/config.js +69 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +51 -0
- package/dist/context.js +27 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/help.d.ts +8 -0
- package/dist/help.js +114 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +21 -0
- package/dist/io.js +28 -0
- package/dist/io.js.map +1 -0
- package/dist/output.d.ts +41 -0
- package/dist/output.js +72 -0
- package/dist/output.js.map +1 -0
- package/dist/prompt.d.ts +15 -0
- package/dist/prompt.js +46 -0
- package/dist/prompt.js.map +1 -0
- package/dist/run.d.ts +12 -0
- package/dist/run.js +94 -0
- package/dist/run.js.map +1 -0
- package/dist/serialize.d.ts +31 -0
- package/dist/serialize.js +248 -0
- package/dist/serialize.js.map +1 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.js +21 -0
- package/dist/version.js.map +1 -0
- package/package.json +35 -3
package/dist/config.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryConfigStore = exports.FileConfigStore = void 0;
|
|
4
|
+
exports.defaultConfigPath = defaultConfigPath;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_os_1 = require("node:os");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
const EMPTY = { profiles: {} };
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the default config path: `$XDG_CONFIG_HOME/atlasauth/config.json`,
|
|
12
|
+
* falling back to `~/.config/atlasauth/config.json`. Honoring XDG keeps the CLI
|
|
13
|
+
* a good citizen on Linux while still working on macOS, where `~/.config` is
|
|
14
|
+
* the de-facto convention CLIs use.
|
|
15
|
+
*/
|
|
16
|
+
function defaultConfigPath(env = process.env) {
|
|
17
|
+
const base = env.XDG_CONFIG_HOME?.trim() || (0, node_path_1.join)((0, node_os_1.homedir)(), '.config');
|
|
18
|
+
return (0, node_path_1.join)(base, 'atlasauth', 'config.json');
|
|
19
|
+
}
|
|
20
|
+
/** The real store: a JSON file written with 0600 perms and a 0700 parent dir. */
|
|
21
|
+
class FileConfigStore {
|
|
22
|
+
path;
|
|
23
|
+
constructor(path) {
|
|
24
|
+
this.path = path;
|
|
25
|
+
}
|
|
26
|
+
load() {
|
|
27
|
+
let text;
|
|
28
|
+
try {
|
|
29
|
+
text = (0, node_fs_1.readFileSync)(this.path, 'utf8');
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Missing file is the first-run state, not an error.
|
|
33
|
+
return { profiles: {} };
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(text);
|
|
37
|
+
// Guard against a hand-corrupted file so every later `.profiles[...]` is safe.
|
|
38
|
+
return { active_profile: parsed.active_profile, profiles: parsed.profiles ?? {} };
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
throw new errors_1.CliError(`Config file at ${this.path} is not valid JSON. Fix or remove it, then run 'atlas login' again.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
save(config) {
|
|
45
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(this.path), { recursive: true, mode: 0o700 });
|
|
46
|
+
// Write THEN chmod: `mode` on writeFile is masked by umask and skipped
|
|
47
|
+
// entirely if the file already exists, so an explicit chmod is the only
|
|
48
|
+
// way to guarantee 0600 on every save.
|
|
49
|
+
(0, node_fs_1.writeFileSync)(this.path, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
|
|
50
|
+
(0, node_fs_1.chmodSync)(this.path, 0o600);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.FileConfigStore = FileConfigStore;
|
|
54
|
+
/** An in-memory store for tests that still want to exercise the resolve logic. */
|
|
55
|
+
class MemoryConfigStore {
|
|
56
|
+
path = '<memory>';
|
|
57
|
+
data;
|
|
58
|
+
constructor(initial = EMPTY) {
|
|
59
|
+
this.data = structuredClone(initial);
|
|
60
|
+
}
|
|
61
|
+
load() {
|
|
62
|
+
return structuredClone(this.data);
|
|
63
|
+
}
|
|
64
|
+
save(config) {
|
|
65
|
+
this.data = structuredClone(config);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.MemoryConfigStore = MemoryConfigStore;
|
|
69
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AA0CA,8CAGC;AA7CD,qCAA4E;AAC5E,qCAAkC;AAClC,yCAA0C;AAC1C,qCAAoC;AA+BpC,MAAM,KAAK,GAAe,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAE3C;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACpE,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,IAAA,gBAAI,EAAC,IAAA,iBAAO,GAAE,EAAE,SAAS,CAAC,CAAC;IACvE,OAAO,IAAA,gBAAI,EAAC,IAAI,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;AAChD,CAAC;AAED,iFAAiF;AACjF,MAAa,eAAe;IACL;IAArB,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAErC,IAAI;QACF,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,IAAA,sBAAY,EAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;YACrD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;YAC9C,+EAA+E;YAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACpF,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,iBAAQ,CAChB,kBAAkB,IAAI,CAAC,IAAI,qEAAqE,CACjG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAkB;QACrB,IAAA,mBAAS,EAAC,IAAA,mBAAO,EAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,uEAAuE;QACvE,wEAAwE;QACxE,uCAAuC;QACvC,IAAA,uBAAa,EAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClF,IAAA,mBAAS,EAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;CACF;AA9BD,0CA8BC;AAED,kFAAkF;AAClF,MAAa,iBAAiB;IACnB,IAAI,GAAG,UAAU,CAAC;IACnB,IAAI,CAAa;IACzB,YAAY,UAAsB,KAAK;QACrC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,IAAI;QACF,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,MAAkB;QACrB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;CACF;AAZD,8CAYC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type AtlasClient } from '@atlasauth/backend';
|
|
2
|
+
import { type ConfigStore } from './config';
|
|
3
|
+
import { type ConfigHttp } from './config-http';
|
|
4
|
+
import { type IO } from './io';
|
|
5
|
+
import { type Prompter } from './prompt';
|
|
6
|
+
/**
|
|
7
|
+
* The exact slice of the Backend API client this CLI drives. Narrowed from the
|
|
8
|
+
* full {@link AtlasClient} on purpose: it documents — and the typechecker
|
|
9
|
+
* enforces — that the command set maps only onto namespaces that really exist,
|
|
10
|
+
* and it keeps the fake a test injects small (five namespaces, not forty).
|
|
11
|
+
*/
|
|
12
|
+
export type ManagementClient = Pick<AtlasClient, 'users' | 'organizations' | 'apiKeys' | 'webhooks' | 'sessions' | 'actions'>;
|
|
13
|
+
/**
|
|
14
|
+
* Everything a command touches the outside world through, in one injectable
|
|
15
|
+
* bag. Production wires the real IO/config/prompt/client; every test builds
|
|
16
|
+
* this with fakes so a handler runs with no network, no TTY and no real
|
|
17
|
+
* `~/.config` file.
|
|
18
|
+
*/
|
|
19
|
+
export interface RunContext {
|
|
20
|
+
io: IO;
|
|
21
|
+
/** Process environment — read for `ATLAS_SECRET_KEY` / `ATLAS_API_URL`. */
|
|
22
|
+
env: NodeJS.ProcessEnv;
|
|
23
|
+
config: ConfigStore;
|
|
24
|
+
prompt: Prompter;
|
|
25
|
+
/** Builds the Backend API client from a resolved credential. */
|
|
26
|
+
makeClient: (opts: {
|
|
27
|
+
secretKey: string;
|
|
28
|
+
apiUrl: string;
|
|
29
|
+
}) => ManagementClient;
|
|
30
|
+
/**
|
|
31
|
+
* Builds the raw management-API HTTP client used by `atlas config` (the
|
|
32
|
+
* config-only `/v1` endpoints the typed client omits). Optional so existing
|
|
33
|
+
* contexts stay valid; the config command falls back to the real one.
|
|
34
|
+
*/
|
|
35
|
+
makeHttp?: (opts: {
|
|
36
|
+
secretKey: string;
|
|
37
|
+
apiUrl: string;
|
|
38
|
+
}) => ConfigHttp;
|
|
39
|
+
/**
|
|
40
|
+
* Read a file's text, for commands that take a path (`atlas actions deploy`
|
|
41
|
+
* / `test`). Injectable so a test drives them with an in-memory file instead
|
|
42
|
+
* of touching the disk. Defaults to reading UTF-8 off the real filesystem.
|
|
43
|
+
*/
|
|
44
|
+
readFile: (path: string) => string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The production context, with any piece overridable. Tests call this with a
|
|
48
|
+
* `config` pointed at a temp path and a `makeClient` returning a stub, so the
|
|
49
|
+
* same `run()` path is exercised end to end without side effects.
|
|
50
|
+
*/
|
|
51
|
+
export declare function defaultContext(overrides?: Partial<RunContext>): RunContext;
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultContext = defaultContext;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const backend_1 = require("@atlasauth/backend");
|
|
6
|
+
const config_1 = require("./config");
|
|
7
|
+
const config_http_1 = require("./config-http");
|
|
8
|
+
const io_1 = require("./io");
|
|
9
|
+
const prompt_1 = require("./prompt");
|
|
10
|
+
/**
|
|
11
|
+
* The production context, with any piece overridable. Tests call this with a
|
|
12
|
+
* `config` pointed at a temp path and a `makeClient` returning a stub, so the
|
|
13
|
+
* same `run()` path is exercised end to end without side effects.
|
|
14
|
+
*/
|
|
15
|
+
function defaultContext(overrides = {}) {
|
|
16
|
+
return {
|
|
17
|
+
io: (0, io_1.defaultIO)(),
|
|
18
|
+
env: process.env,
|
|
19
|
+
config: new config_1.FileConfigStore((0, config_1.defaultConfigPath)()),
|
|
20
|
+
prompt: (0, prompt_1.defaultPrompter)(),
|
|
21
|
+
makeClient: ({ secretKey, apiUrl }) => (0, backend_1.createAtlasClient)({ secretKey, apiUrl }),
|
|
22
|
+
makeHttp: ({ secretKey, apiUrl }) => (0, config_http_1.createConfigHttp)({ secretKey, apiUrl }),
|
|
23
|
+
readFile: (path) => (0, node_fs_1.readFileSync)(path, 'utf8'),
|
|
24
|
+
...overrides,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":";;AAmDA,wCAWC;AA9DD,qCAAuC;AACvC,gDAAyE;AACzE,qCAAgF;AAChF,+CAAkE;AAClE,6BAA0C;AAC1C,qCAA0D;AAyC1D;;;;GAIG;AACH,SAAgB,cAAc,CAAC,YAAiC,EAAE;IAChE,OAAO;QACL,EAAE,EAAE,IAAA,cAAS,GAAE;QACf,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,MAAM,EAAE,IAAI,wBAAe,CAAC,IAAA,0BAAiB,GAAE,CAAC;QAChD,MAAM,EAAE,IAAA,wBAAe,GAAE;QACzB,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAA,2BAAiB,EAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAC/E,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAA,8BAAgB,EAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAC5E,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,sBAAY,EAAC,IAAI,EAAE,MAAM,CAAC;QAC9C,GAAG,SAAS;KACb,CAAC;AACJ,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one error a command handler throws to abort with a clean, user-facing
|
|
3
|
+
* message and a chosen exit code. {@link run} catches it, prints `message` to
|
|
4
|
+
* stderr (no stack), and returns `exitCode` — so a bad flag or a missing key
|
|
5
|
+
* never dumps a stack trace at the terminal the way an uncaught throw would.
|
|
6
|
+
*
|
|
7
|
+
* API failures are NOT CliErrors: they arrive as `AtlasApiError` from
|
|
8
|
+
* `@atlasauth/backend` and {@link run} formats those separately so the stable
|
|
9
|
+
* error `code` and HTTP status survive to the user.
|
|
10
|
+
*/
|
|
11
|
+
export declare class CliError extends Error {
|
|
12
|
+
readonly name = "CliError";
|
|
13
|
+
readonly exitCode: number;
|
|
14
|
+
constructor(message: string, exitCode?: number);
|
|
15
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CliError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The one error a command handler throws to abort with a clean, user-facing
|
|
6
|
+
* message and a chosen exit code. {@link run} catches it, prints `message` to
|
|
7
|
+
* stderr (no stack), and returns `exitCode` — so a bad flag or a missing key
|
|
8
|
+
* never dumps a stack trace at the terminal the way an uncaught throw would.
|
|
9
|
+
*
|
|
10
|
+
* API failures are NOT CliErrors: they arrive as `AtlasApiError` from
|
|
11
|
+
* `@atlasauth/backend` and {@link run} formats those separately so the stable
|
|
12
|
+
* error `code` and HTTP status survive to the user.
|
|
13
|
+
*/
|
|
14
|
+
class CliError extends Error {
|
|
15
|
+
name = 'CliError';
|
|
16
|
+
exitCode;
|
|
17
|
+
constructor(message, exitCode = 1) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.exitCode = exitCode;
|
|
20
|
+
// Keep `instanceof CliError` working under down-level compile targets.
|
|
21
|
+
Object.setPrototypeOf(this, CliError.prototype);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.CliError = CliError;
|
|
25
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;GASG;AACH,MAAa,QAAS,SAAQ,KAAK;IACf,IAAI,GAAG,UAAU,CAAC;IAC3B,QAAQ,CAAS;IAE1B,YAAY,OAAe,EAAE,QAAQ,GAAG,CAAC;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,uEAAuE;QACvE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;CACF;AAVD,4BAUC"}
|
package/dist/help.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* All help text lives here as plain strings — the CLI's "docs" surface. Kept
|
|
3
|
+
* out of the handlers so the dispatch code stays about control flow and the
|
|
4
|
+
* copy can be read (and kept consistent) in one place.
|
|
5
|
+
*/
|
|
6
|
+
export declare const TOP_HELP = "atlas \u2014 manage an Atlas instance from the terminal\n\nUsage: atlas <command> [subcommand] [arguments] [options]\n\nCommands:\n login Authenticate and store a profile credential\n logout Remove a stored profile credential\n whoami Show the active profile and instance\n users list|get|create|delete\n orgs list|get|members\n api-keys list|create|revoke\n webhooks list\n sessions revoke\n config export|import Config-as-code: round-trip the instance's config\n actions list|deploy|test|logs\n\nGlobal options:\n --profile <name> Use a named profile (default: active, else \"default\")\n --json Emit raw JSON instead of a human table\n --limit <n> Page size for list commands that paginate\n --starting-after <cursor> Pagination cursor (from a prior page's hint)\n -h, --help Show this help, or help for a command\n -v, --version Print the version\n\nEnvironment overrides:\n ATLAS_SECRET_KEY Secret key to use instead of the stored one\n ATLAS_API_URL API URL to use instead of the stored one\n\nRun 'atlas <command> --help' for command-specific help.";
|
|
7
|
+
/** Per-command help, keyed by the resource word. */
|
|
8
|
+
export declare const COMMAND_HELP: Record<string, string>;
|
package/dist/help.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* All help text lives here as plain strings — the CLI's "docs" surface. Kept
|
|
4
|
+
* out of the handlers so the dispatch code stays about control flow and the
|
|
5
|
+
* copy can be read (and kept consistent) in one place.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.COMMAND_HELP = exports.TOP_HELP = void 0;
|
|
9
|
+
exports.TOP_HELP = `atlas — manage an Atlas instance from the terminal
|
|
10
|
+
|
|
11
|
+
Usage: atlas <command> [subcommand] [arguments] [options]
|
|
12
|
+
|
|
13
|
+
Commands:
|
|
14
|
+
login Authenticate and store a profile credential
|
|
15
|
+
logout Remove a stored profile credential
|
|
16
|
+
whoami Show the active profile and instance
|
|
17
|
+
users list|get|create|delete
|
|
18
|
+
orgs list|get|members
|
|
19
|
+
api-keys list|create|revoke
|
|
20
|
+
webhooks list
|
|
21
|
+
sessions revoke
|
|
22
|
+
config export|import Config-as-code: round-trip the instance's config
|
|
23
|
+
actions list|deploy|test|logs
|
|
24
|
+
|
|
25
|
+
Global options:
|
|
26
|
+
--profile <name> Use a named profile (default: active, else "default")
|
|
27
|
+
--json Emit raw JSON instead of a human table
|
|
28
|
+
--limit <n> Page size for list commands that paginate
|
|
29
|
+
--starting-after <cursor> Pagination cursor (from a prior page's hint)
|
|
30
|
+
-h, --help Show this help, or help for a command
|
|
31
|
+
-v, --version Print the version
|
|
32
|
+
|
|
33
|
+
Environment overrides:
|
|
34
|
+
ATLAS_SECRET_KEY Secret key to use instead of the stored one
|
|
35
|
+
ATLAS_API_URL API URL to use instead of the stored one
|
|
36
|
+
|
|
37
|
+
Run 'atlas <command> --help' for command-specific help.`;
|
|
38
|
+
/** Per-command help, keyed by the resource word. */
|
|
39
|
+
exports.COMMAND_HELP = {
|
|
40
|
+
login: `atlas login — authenticate and store a profile credential
|
|
41
|
+
|
|
42
|
+
Usage: atlas login [--profile <name>] [--url <api-url>] [--secret-key <sk_...>]
|
|
43
|
+
|
|
44
|
+
Prompts for an API URL and a secret key, validates the key with one Backend
|
|
45
|
+
call, then stores it (0600) under the profile. --url / --secret-key skip the
|
|
46
|
+
prompts for non-interactive setup.`,
|
|
47
|
+
logout: `atlas logout — remove a stored profile credential
|
|
48
|
+
|
|
49
|
+
Usage: atlas logout [--profile <name>]`,
|
|
50
|
+
whoami: `atlas whoami — show the active profile and instance
|
|
51
|
+
|
|
52
|
+
Usage: atlas whoami [--profile <name>] [--json]`,
|
|
53
|
+
users: `atlas users — manage users
|
|
54
|
+
|
|
55
|
+
Usage:
|
|
56
|
+
atlas users list [--limit <n>] [--starting-after <cursor>] [--json]
|
|
57
|
+
atlas users get <user-id> [--json]
|
|
58
|
+
atlas users create --email <address> [--first-name <n>] [--last-name <n>] [--password <p>] [--json]
|
|
59
|
+
atlas users delete <user-id> [--json]`,
|
|
60
|
+
orgs: `atlas orgs — manage organizations
|
|
61
|
+
|
|
62
|
+
Usage:
|
|
63
|
+
atlas orgs list [--limit <n>] [--starting-after <cursor>] [--json]
|
|
64
|
+
atlas orgs get <org-id> [--json]
|
|
65
|
+
atlas orgs members <org-id> [--json]`,
|
|
66
|
+
'api-keys': `atlas api-keys — manage end-user API keys
|
|
67
|
+
|
|
68
|
+
Usage:
|
|
69
|
+
atlas api-keys list [--subject-type <user|organization>] [--subject-id <id>] [--json]
|
|
70
|
+
atlas api-keys create --subject-type <user|organization> --subject-id <id> [--name <n>] [--json]
|
|
71
|
+
atlas api-keys revoke <api-key-id> [--json]`,
|
|
72
|
+
webhooks: `atlas webhooks — inspect webhook endpoints
|
|
73
|
+
|
|
74
|
+
Usage:
|
|
75
|
+
atlas webhooks list [--json]`,
|
|
76
|
+
sessions: `atlas sessions — manage sessions
|
|
77
|
+
|
|
78
|
+
Usage:
|
|
79
|
+
atlas sessions revoke <session-id> [--json]`,
|
|
80
|
+
config: `atlas config — config-as-code for an Atlas instance (the Auth0 deploy-cli peer)
|
|
81
|
+
|
|
82
|
+
Usage:
|
|
83
|
+
atlas config export [--dir <path>] [--format json|yaml]
|
|
84
|
+
atlas config import [--dir <path>] [--format json|yaml] [--dry-run] [--prune]
|
|
85
|
+
|
|
86
|
+
export Read the instance's current config (instance/auth config, OAuth clients
|
|
87
|
+
and providers, SSO connections, resource servers, JWT templates, roles,
|
|
88
|
+
webhook endpoints, billing plans, redirect URLs, org settings schema,
|
|
89
|
+
notification and email templates, org policies) and write a deterministic
|
|
90
|
+
directory tree — one file per resource type, keys sorted, SECRETS OMITTED.
|
|
91
|
+
|
|
92
|
+
import Diff the directory against live config and apply creates/updates
|
|
93
|
+
idempotently. A resource type with no file is left untouched.
|
|
94
|
+
--dry-run print the plan and apply nothing
|
|
95
|
+
--prune also delete live resources absent from the config
|
|
96
|
+
--dir config directory (default: ./atlas-config)
|
|
97
|
+
--format json (default) or yaml
|
|
98
|
+
|
|
99
|
+
Secrets never live on disk. Inject a credential at import with a \${ENV_VAR}
|
|
100
|
+
placeholder in a file (e.g. a provider "client_secret": "\${GOOGLE_SECRET}").`,
|
|
101
|
+
actions: `atlas actions — manage Actions (tenant code run in the auth pipeline)
|
|
102
|
+
|
|
103
|
+
Usage:
|
|
104
|
+
atlas actions list [--json]
|
|
105
|
+
atlas actions deploy <file> --trigger <post_login|pre_user_registration|post_user_registration> [--name <n>] [--json]
|
|
106
|
+
atlas actions test <file> [--trigger <t>] [--json]
|
|
107
|
+
atlas actions logs <action-id> [--json]
|
|
108
|
+
|
|
109
|
+
deploy uploads the file's code verbatim as a new action (created, not yet bound).
|
|
110
|
+
test runs the file OFFLINE through the @atlasauth/actions harness — no network,
|
|
111
|
+
no real users — and exits non-zero if the action throws. logs explains where an
|
|
112
|
+
action's execution history is recorded (Atlas has no live log-stream endpoint).`,
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=help.js.map
|
package/dist/help.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEU,QAAA,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDA4BgC,CAAC;AAEzD,oDAAoD;AACvC,QAAA,YAAY,GAA2B;IAClD,KAAK,EAAE;;;;;;mCAM0B;IAEjC,MAAM,EAAE;;uCAE6B;IAErC,MAAM,EAAE;;gDAEsC;IAE9C,KAAK,EAAE;;;;;;wCAM+B;IAEtC,IAAI,EAAE;;;;;uCAK+B;IAErC,UAAU,EAAE;;;;;8CAKgC;IAE5C,QAAQ,EAAE;;;+BAGmB;IAE7B,QAAQ,EAAE;;;8CAGkC;IAE5C,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;8EAoBoE;IAC5E,OAAO,EAAE;;;;;;;;;;;gFAWqE;CAC/E,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Library surface of `@atlasauth/cli`. The package ships a bin (`atlas`), but
|
|
3
|
+
* exporting the pieces lets the handlers be unit-tested with injected deps and
|
|
4
|
+
* lets another tool embed the CLI (e.g. `create-atlas-app`) without spawning a
|
|
5
|
+
* child process.
|
|
6
|
+
*/
|
|
7
|
+
export { run, type Handler } from './run';
|
|
8
|
+
export { defaultContext, type RunContext, type ManagementClient } from './context';
|
|
9
|
+
export { createConfigHttp, isNotFound, type ConfigHttp } from './config-http';
|
|
10
|
+
export { CliError } from './errors';
|
|
11
|
+
export { defaultIO, captureIO, type IO, type CaptureIO } from './io';
|
|
12
|
+
export { FileConfigStore, MemoryConfigStore, defaultConfigPath, type ConfigStore, type ConfigFile, type Profile, } from './config';
|
|
13
|
+
export { defaultPrompter, type Prompter } from './prompt';
|
|
14
|
+
export { getVersion } from './version';
|
|
15
|
+
export { login, logout, whoami } from './commands/auth';
|
|
16
|
+
export { users } from './commands/users';
|
|
17
|
+
export { orgs } from './commands/orgs';
|
|
18
|
+
export { apiKeys } from './commands/api-keys';
|
|
19
|
+
export { webhooks } from './commands/webhooks';
|
|
20
|
+
export { sessions } from './commands/sessions';
|
|
21
|
+
export { config } from './commands/config';
|
|
22
|
+
export { actions } from './commands/actions';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.actions = exports.config = exports.sessions = exports.webhooks = exports.apiKeys = exports.orgs = exports.users = exports.whoami = exports.logout = exports.login = exports.getVersion = exports.defaultPrompter = exports.defaultConfigPath = exports.MemoryConfigStore = exports.FileConfigStore = exports.captureIO = exports.defaultIO = exports.CliError = exports.isNotFound = exports.createConfigHttp = exports.defaultContext = exports.run = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Library surface of `@atlasauth/cli`. The package ships a bin (`atlas`), but
|
|
6
|
+
* exporting the pieces lets the handlers be unit-tested with injected deps and
|
|
7
|
+
* lets another tool embed the CLI (e.g. `create-atlas-app`) without spawning a
|
|
8
|
+
* child process.
|
|
9
|
+
*/
|
|
10
|
+
var run_1 = require("./run");
|
|
11
|
+
Object.defineProperty(exports, "run", { enumerable: true, get: function () { return run_1.run; } });
|
|
12
|
+
var context_1 = require("./context");
|
|
13
|
+
Object.defineProperty(exports, "defaultContext", { enumerable: true, get: function () { return context_1.defaultContext; } });
|
|
14
|
+
var config_http_1 = require("./config-http");
|
|
15
|
+
Object.defineProperty(exports, "createConfigHttp", { enumerable: true, get: function () { return config_http_1.createConfigHttp; } });
|
|
16
|
+
Object.defineProperty(exports, "isNotFound", { enumerable: true, get: function () { return config_http_1.isNotFound; } });
|
|
17
|
+
var errors_1 = require("./errors");
|
|
18
|
+
Object.defineProperty(exports, "CliError", { enumerable: true, get: function () { return errors_1.CliError; } });
|
|
19
|
+
var io_1 = require("./io");
|
|
20
|
+
Object.defineProperty(exports, "defaultIO", { enumerable: true, get: function () { return io_1.defaultIO; } });
|
|
21
|
+
Object.defineProperty(exports, "captureIO", { enumerable: true, get: function () { return io_1.captureIO; } });
|
|
22
|
+
var config_1 = require("./config");
|
|
23
|
+
Object.defineProperty(exports, "FileConfigStore", { enumerable: true, get: function () { return config_1.FileConfigStore; } });
|
|
24
|
+
Object.defineProperty(exports, "MemoryConfigStore", { enumerable: true, get: function () { return config_1.MemoryConfigStore; } });
|
|
25
|
+
Object.defineProperty(exports, "defaultConfigPath", { enumerable: true, get: function () { return config_1.defaultConfigPath; } });
|
|
26
|
+
var prompt_1 = require("./prompt");
|
|
27
|
+
Object.defineProperty(exports, "defaultPrompter", { enumerable: true, get: function () { return prompt_1.defaultPrompter; } });
|
|
28
|
+
var version_1 = require("./version");
|
|
29
|
+
Object.defineProperty(exports, "getVersion", { enumerable: true, get: function () { return version_1.getVersion; } });
|
|
30
|
+
// The individual command handlers, exported for direct testing/embedding.
|
|
31
|
+
var auth_1 = require("./commands/auth");
|
|
32
|
+
Object.defineProperty(exports, "login", { enumerable: true, get: function () { return auth_1.login; } });
|
|
33
|
+
Object.defineProperty(exports, "logout", { enumerable: true, get: function () { return auth_1.logout; } });
|
|
34
|
+
Object.defineProperty(exports, "whoami", { enumerable: true, get: function () { return auth_1.whoami; } });
|
|
35
|
+
var users_1 = require("./commands/users");
|
|
36
|
+
Object.defineProperty(exports, "users", { enumerable: true, get: function () { return users_1.users; } });
|
|
37
|
+
var orgs_1 = require("./commands/orgs");
|
|
38
|
+
Object.defineProperty(exports, "orgs", { enumerable: true, get: function () { return orgs_1.orgs; } });
|
|
39
|
+
var api_keys_1 = require("./commands/api-keys");
|
|
40
|
+
Object.defineProperty(exports, "apiKeys", { enumerable: true, get: function () { return api_keys_1.apiKeys; } });
|
|
41
|
+
var webhooks_1 = require("./commands/webhooks");
|
|
42
|
+
Object.defineProperty(exports, "webhooks", { enumerable: true, get: function () { return webhooks_1.webhooks; } });
|
|
43
|
+
var sessions_1 = require("./commands/sessions");
|
|
44
|
+
Object.defineProperty(exports, "sessions", { enumerable: true, get: function () { return sessions_1.sessions; } });
|
|
45
|
+
var config_2 = require("./commands/config");
|
|
46
|
+
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_2.config; } });
|
|
47
|
+
var actions_1 = require("./commands/actions");
|
|
48
|
+
Object.defineProperty(exports, "actions", { enumerable: true, get: function () { return actions_1.actions; } });
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,6BAA0C;AAAjC,0FAAA,GAAG,OAAA;AACZ,qCAAmF;AAA1E,yGAAA,cAAc,OAAA;AACvB,6CAA8E;AAArE,+GAAA,gBAAgB,OAAA;AAAE,yGAAA,UAAU,OAAA;AACrC,mCAAoC;AAA3B,kGAAA,QAAQ,OAAA;AACjB,2BAAqE;AAA5D,+FAAA,SAAS,OAAA;AAAE,+FAAA,SAAS,OAAA;AAC7B,mCAOkB;AANhB,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,2GAAA,iBAAiB,OAAA;AAKnB,mCAA0D;AAAjD,yGAAA,eAAe,OAAA;AACxB,qCAAuC;AAA9B,qGAAA,UAAU,OAAA;AAEnB,0EAA0E;AAC1E,wCAAwD;AAA/C,6FAAA,KAAK,OAAA;AAAE,8FAAA,MAAM,OAAA;AAAE,8FAAA,MAAM,OAAA;AAC9B,0CAAyC;AAAhC,8FAAA,KAAK,OAAA;AACd,wCAAuC;AAA9B,4FAAA,IAAI,OAAA;AACb,gDAA8C;AAArC,mGAAA,OAAO,OAAA;AAChB,gDAA+C;AAAtC,oGAAA,QAAQ,OAAA;AACjB,gDAA+C;AAAtC,oGAAA,QAAQ,OAAA;AACjB,4CAA2C;AAAlC,gGAAA,MAAM,OAAA;AACf,8CAA6C;AAApC,kGAAA,OAAO,OAAA"}
|
package/dist/io.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two sinks every command writes through, named so tests can capture
|
|
3
|
+
* output instead of spying on `console`. `out` is the data channel (tables,
|
|
4
|
+
* JSON, the answer a script would pipe); `err` is for diagnostics, prompts'
|
|
5
|
+
* echoes and error messages — exactly the stdout/stderr split a `--json`
|
|
6
|
+
* consumer relies on to parse stdout cleanly.
|
|
7
|
+
*/
|
|
8
|
+
export interface IO {
|
|
9
|
+
out(text: string): void;
|
|
10
|
+
err(text: string): void;
|
|
11
|
+
}
|
|
12
|
+
/** The real IO: a trailing newline is added so callers pass bare lines. */
|
|
13
|
+
export declare function defaultIO(stdout?: NodeJS.WriteStream, stderr?: NodeJS.WriteStream): IO;
|
|
14
|
+
/** An in-memory IO for tests, exposing the captured lines plus joined views. */
|
|
15
|
+
export interface CaptureIO extends IO {
|
|
16
|
+
readonly outLines: string[];
|
|
17
|
+
readonly errLines: string[];
|
|
18
|
+
stdout(): string;
|
|
19
|
+
stderr(): string;
|
|
20
|
+
}
|
|
21
|
+
export declare function captureIO(): CaptureIO;
|
package/dist/io.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultIO = defaultIO;
|
|
4
|
+
exports.captureIO = captureIO;
|
|
5
|
+
/** The real IO: a trailing newline is added so callers pass bare lines. */
|
|
6
|
+
function defaultIO(stdout = process.stdout, stderr = process.stderr) {
|
|
7
|
+
return {
|
|
8
|
+
out(text) {
|
|
9
|
+
stdout.write(text + '\n');
|
|
10
|
+
},
|
|
11
|
+
err(text) {
|
|
12
|
+
stderr.write(text + '\n');
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function captureIO() {
|
|
17
|
+
const outLines = [];
|
|
18
|
+
const errLines = [];
|
|
19
|
+
return {
|
|
20
|
+
outLines,
|
|
21
|
+
errLines,
|
|
22
|
+
out: (text) => void outLines.push(text),
|
|
23
|
+
err: (text) => void errLines.push(text),
|
|
24
|
+
stdout: () => outLines.join('\n'),
|
|
25
|
+
stderr: () => errLines.join('\n'),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=io.js.map
|
package/dist/io.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"io.js","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":";;AAaA,8BAYC;AAUD,8BAWC;AAlCD,2EAA2E;AAC3E,SAAgB,SAAS,CACvB,SAA6B,OAAO,CAAC,MAAM,EAC3C,SAA6B,OAAO,CAAC,MAAM;IAE3C,OAAO;QACL,GAAG,CAAC,IAAI;YACN,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,GAAG,CAAC,IAAI;YACN,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC;AACJ,CAAC;AAUD,SAAgB,SAAS;IACvB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,OAAO;QACL,QAAQ;QACR,QAAQ;QACR,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QACvC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QACvC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QACjC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;KAClC,CAAC;AACJ,CAAC"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { IO } from './io';
|
|
2
|
+
/**
|
|
3
|
+
* A single rendered column: a header plus a getter that pulls the raw value off
|
|
4
|
+
* a row. Getters (not keys) because a few columns are derived — a user's name
|
|
5
|
+
* joins first + last, a webhook's events join an array — and a getter keeps that
|
|
6
|
+
* shaping next to the column instead of forcing a pre-massaged row.
|
|
7
|
+
*/
|
|
8
|
+
export interface Column<T> {
|
|
9
|
+
header: string;
|
|
10
|
+
get: (row: T) => unknown;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Epoch-millisecond timestamp → ISO-8601, the form every Atlas `*_at` field
|
|
14
|
+
* takes on the wire. Blank for null (e.g. a user who never signed in) so the
|
|
15
|
+
* column stays readable rather than printing `1970-...`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function fmtTime(value: unknown): string;
|
|
18
|
+
/**
|
|
19
|
+
* Hand-rolled fixed-width table — the only "formatting library" this CLI has.
|
|
20
|
+
* Columns are padded to the widest cell (header included); a dashed rule sits
|
|
21
|
+
* under the header; trailing padding on the last column is trimmed so lines
|
|
22
|
+
* don't carry invisible whitespace. Empty input prints a friendly placeholder
|
|
23
|
+
* rather than a bare header with no rows.
|
|
24
|
+
*/
|
|
25
|
+
export declare function renderTable<T>(columns: Column<T>[], rows: T[]): string;
|
|
26
|
+
/** Pretty-print any value as the `--json` output on stdout. */
|
|
27
|
+
export declare function printJson(io: IO, value: unknown): void;
|
|
28
|
+
/**
|
|
29
|
+
* Print a cursor-paginated list as either raw JSON or a table, and — in table
|
|
30
|
+
* mode, when there is another page — a footer naming the exact flag to fetch
|
|
31
|
+
* it. Keeping the hint next to the data is what makes `--starting-after`
|
|
32
|
+
* discoverable without the user reading `--help`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function printList<T>(io: IO, opts: {
|
|
35
|
+
json: boolean;
|
|
36
|
+
columns: Column<T>[];
|
|
37
|
+
}, page: {
|
|
38
|
+
data: T[];
|
|
39
|
+
has_more?: boolean;
|
|
40
|
+
next_cursor?: string | null;
|
|
41
|
+
}, raw?: unknown): void;
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fmtTime = fmtTime;
|
|
4
|
+
exports.renderTable = renderTable;
|
|
5
|
+
exports.printJson = printJson;
|
|
6
|
+
exports.printList = printList;
|
|
7
|
+
/** Render a value as a table cell: null/undefined blank, arrays joined, objects JSON. */
|
|
8
|
+
function cell(value) {
|
|
9
|
+
if (value === null || value === undefined)
|
|
10
|
+
return '';
|
|
11
|
+
if (Array.isArray(value))
|
|
12
|
+
return value.map((v) => cell(v)).join(', ');
|
|
13
|
+
if (typeof value === 'object')
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
return String(value);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Epoch-millisecond timestamp → ISO-8601, the form every Atlas `*_at` field
|
|
19
|
+
* takes on the wire. Blank for null (e.g. a user who never signed in) so the
|
|
20
|
+
* column stays readable rather than printing `1970-...`.
|
|
21
|
+
*/
|
|
22
|
+
function fmtTime(value) {
|
|
23
|
+
if (value === null || value === undefined)
|
|
24
|
+
return '';
|
|
25
|
+
const n = Number(value);
|
|
26
|
+
if (!Number.isFinite(n))
|
|
27
|
+
return '';
|
|
28
|
+
return new Date(n).toISOString();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Hand-rolled fixed-width table — the only "formatting library" this CLI has.
|
|
32
|
+
* Columns are padded to the widest cell (header included); a dashed rule sits
|
|
33
|
+
* under the header; trailing padding on the last column is trimmed so lines
|
|
34
|
+
* don't carry invisible whitespace. Empty input prints a friendly placeholder
|
|
35
|
+
* rather than a bare header with no rows.
|
|
36
|
+
*/
|
|
37
|
+
function renderTable(columns, rows) {
|
|
38
|
+
if (rows.length === 0)
|
|
39
|
+
return '(no results)';
|
|
40
|
+
const matrix = rows.map((row) => columns.map((col) => cell(col.get(row))));
|
|
41
|
+
const widths = columns.map((col, i) => Math.max(col.header.length, ...matrix.map((r) => r[i].length)));
|
|
42
|
+
const pad = (text, width) => text.padEnd(width);
|
|
43
|
+
const line = (fields) => fields.map((f, i) => pad(f, widths[i])).join(' ').replace(/\s+$/, '');
|
|
44
|
+
const lines = [
|
|
45
|
+
line(columns.map((c) => c.header)),
|
|
46
|
+
line(widths.map((w) => '-'.repeat(w))),
|
|
47
|
+
...matrix.map((r) => line(r)),
|
|
48
|
+
];
|
|
49
|
+
return lines.join('\n');
|
|
50
|
+
}
|
|
51
|
+
/** Pretty-print any value as the `--json` output on stdout. */
|
|
52
|
+
function printJson(io, value) {
|
|
53
|
+
io.out(JSON.stringify(value, null, 2));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Print a cursor-paginated list as either raw JSON or a table, and — in table
|
|
57
|
+
* mode, when there is another page — a footer naming the exact flag to fetch
|
|
58
|
+
* it. Keeping the hint next to the data is what makes `--starting-after`
|
|
59
|
+
* discoverable without the user reading `--help`.
|
|
60
|
+
*/
|
|
61
|
+
function printList(io, opts, page, raw = page) {
|
|
62
|
+
if (opts.json) {
|
|
63
|
+
printJson(io, raw);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
io.out(renderTable(opts.columns, page.data));
|
|
67
|
+
if (page.has_more && page.next_cursor) {
|
|
68
|
+
io.out('');
|
|
69
|
+
io.out(`More results — fetch the next page with: --starting-after ${page.next_cursor}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
|
package/dist/prompt.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The interactive input seam for `atlas login`. An interface (not a direct
|
|
3
|
+
* `readline` call) so tests script answers without a TTY, and so `secret()`
|
|
4
|
+
* can hide the key no matter where it's wired.
|
|
5
|
+
*/
|
|
6
|
+
export interface Prompter {
|
|
7
|
+
/** A visible line of input, with an optional default shown in brackets. */
|
|
8
|
+
text(query: string, opts?: {
|
|
9
|
+
default?: string;
|
|
10
|
+
}): Promise<string>;
|
|
11
|
+
/** A hidden line of input — the terminal never echoes what's typed. */
|
|
12
|
+
secret(query: string): Promise<string>;
|
|
13
|
+
}
|
|
14
|
+
/** The real prompter, reading the TTY. Not exercised by unit tests (they inject). */
|
|
15
|
+
export declare function defaultPrompter(input?: NodeJS.ReadableStream, output?: NodeJS.WritableStream): Prompter;
|