@axtrabase/cli 0.1.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.
Files changed (154) hide show
  1. package/README.md +130 -0
  2. package/dist/active-project.d.ts +12 -0
  3. package/dist/active-project.d.ts.map +1 -0
  4. package/dist/active-project.js +27 -0
  5. package/dist/active-project.js.map +1 -0
  6. package/dist/api-types.d.ts +187 -0
  7. package/dist/api-types.d.ts.map +1 -0
  8. package/dist/api-types.js +9 -0
  9. package/dist/api-types.js.map +1 -0
  10. package/dist/commands/config.d.ts +3 -0
  11. package/dist/commands/config.d.ts.map +1 -0
  12. package/dist/commands/config.js +98 -0
  13. package/dist/commands/config.js.map +1 -0
  14. package/dist/commands/connection.d.ts +3 -0
  15. package/dist/commands/connection.d.ts.map +1 -0
  16. package/dist/commands/connection.js +58 -0
  17. package/dist/commands/connection.js.map +1 -0
  18. package/dist/commands/context.d.ts +3 -0
  19. package/dist/commands/context.d.ts.map +1 -0
  20. package/dist/commands/context.js +128 -0
  21. package/dist/commands/context.js.map +1 -0
  22. package/dist/commands/docs.d.ts +11 -0
  23. package/dist/commands/docs.d.ts.map +1 -0
  24. package/dist/commands/docs.js +39 -0
  25. package/dist/commands/docs.js.map +1 -0
  26. package/dist/commands/keys.d.ts +3 -0
  27. package/dist/commands/keys.d.ts.map +1 -0
  28. package/dist/commands/keys.js +92 -0
  29. package/dist/commands/keys.js.map +1 -0
  30. package/dist/commands/login.d.ts +3 -0
  31. package/dist/commands/login.d.ts.map +1 -0
  32. package/dist/commands/login.js +68 -0
  33. package/dist/commands/login.js.map +1 -0
  34. package/dist/commands/logout.d.ts +12 -0
  35. package/dist/commands/logout.d.ts.map +1 -0
  36. package/dist/commands/logout.js +77 -0
  37. package/dist/commands/logout.js.map +1 -0
  38. package/dist/commands/openapi.d.ts +4 -0
  39. package/dist/commands/openapi.d.ts.map +1 -0
  40. package/dist/commands/openapi.js +40 -0
  41. package/dist/commands/openapi.js.map +1 -0
  42. package/dist/commands/organisations.d.ts +3 -0
  43. package/dist/commands/organisations.d.ts.map +1 -0
  44. package/dist/commands/organisations.js +64 -0
  45. package/dist/commands/organisations.js.map +1 -0
  46. package/dist/commands/permissions.d.ts +9 -0
  47. package/dist/commands/permissions.d.ts.map +1 -0
  48. package/dist/commands/permissions.js +61 -0
  49. package/dist/commands/permissions.js.map +1 -0
  50. package/dist/commands/projects.d.ts +3 -0
  51. package/dist/commands/projects.d.ts.map +1 -0
  52. package/dist/commands/projects.js +99 -0
  53. package/dist/commands/projects.js.map +1 -0
  54. package/dist/commands/requests.d.ts +3 -0
  55. package/dist/commands/requests.d.ts.map +1 -0
  56. package/dist/commands/requests.js +91 -0
  57. package/dist/commands/requests.js.map +1 -0
  58. package/dist/commands/schema.d.ts +3 -0
  59. package/dist/commands/schema.d.ts.map +1 -0
  60. package/dist/commands/schema.js +80 -0
  61. package/dist/commands/schema.js.map +1 -0
  62. package/dist/commands/status.d.ts +10 -0
  63. package/dist/commands/status.d.ts.map +1 -0
  64. package/dist/commands/status.js +46 -0
  65. package/dist/commands/status.js.map +1 -0
  66. package/dist/commands/tables.d.ts +3 -0
  67. package/dist/commands/tables.d.ts.map +1 -0
  68. package/dist/commands/tables.js +129 -0
  69. package/dist/commands/tables.js.map +1 -0
  70. package/dist/commands/whoami.d.ts +3 -0
  71. package/dist/commands/whoami.d.ts.map +1 -0
  72. package/dist/commands/whoami.js +41 -0
  73. package/dist/commands/whoami.js.map +1 -0
  74. package/dist/concurrency.d.ts +18 -0
  75. package/dist/concurrency.d.ts.map +1 -0
  76. package/dist/concurrency.js +32 -0
  77. package/dist/concurrency.js.map +1 -0
  78. package/dist/config/credentials.d.ts +17 -0
  79. package/dist/config/credentials.d.ts.map +1 -0
  80. package/dist/config/credentials.js +77 -0
  81. package/dist/config/credentials.js.map +1 -0
  82. package/dist/config/paths.d.ts +12 -0
  83. package/dist/config/paths.d.ts.map +1 -0
  84. package/dist/config/paths.js +20 -0
  85. package/dist/config/paths.js.map +1 -0
  86. package/dist/config/resolve.d.ts +22 -0
  87. package/dist/config/resolve.d.ts.map +1 -0
  88. package/dist/config/resolve.js +41 -0
  89. package/dist/config/resolve.js.map +1 -0
  90. package/dist/config/store.d.ts +24 -0
  91. package/dist/config/store.d.ts.map +1 -0
  92. package/dist/config/store.js +72 -0
  93. package/dist/config/store.js.map +1 -0
  94. package/dist/exit-codes.d.ts +18 -0
  95. package/dist/exit-codes.d.ts.map +1 -0
  96. package/dist/exit-codes.js +40 -0
  97. package/dist/exit-codes.js.map +1 -0
  98. package/dist/generators/typescript.d.ts +5 -0
  99. package/dist/generators/typescript.d.ts.map +1 -0
  100. package/dist/generators/typescript.js +70 -0
  101. package/dist/generators/typescript.js.map +1 -0
  102. package/dist/http/authenticated-client.d.ts +10 -0
  103. package/dist/http/authenticated-client.d.ts.map +1 -0
  104. package/dist/http/authenticated-client.js +24 -0
  105. package/dist/http/authenticated-client.js.map +1 -0
  106. package/dist/http/client.d.ts +42 -0
  107. package/dist/http/client.d.ts.map +1 -0
  108. package/dist/http/client.js +86 -0
  109. package/dist/http/client.js.map +1 -0
  110. package/dist/http/errors.d.ts +29 -0
  111. package/dist/http/errors.d.ts.map +1 -0
  112. package/dist/http/errors.js +21 -0
  113. package/dist/http/errors.js.map +1 -0
  114. package/dist/index.d.ts +3 -0
  115. package/dist/index.d.ts.map +1 -0
  116. package/dist/index.js +62 -0
  117. package/dist/index.js.map +1 -0
  118. package/dist/open-browser.d.ts +9 -0
  119. package/dist/open-browser.d.ts.map +1 -0
  120. package/dist/open-browser.js +32 -0
  121. package/dist/open-browser.js.map +1 -0
  122. package/dist/output/file-writer.d.ts +8 -0
  123. package/dist/output/file-writer.d.ts.map +1 -0
  124. package/dist/output/file-writer.js +28 -0
  125. package/dist/output/file-writer.js.map +1 -0
  126. package/dist/output/print.d.ts +15 -0
  127. package/dist/output/print.d.ts.map +1 -0
  128. package/dist/output/print.js +27 -0
  129. package/dist/output/print.js.map +1 -0
  130. package/dist/output/sanitize.d.ts +30 -0
  131. package/dist/output/sanitize.d.ts.map +1 -0
  132. package/dist/output/sanitize.js +40 -0
  133. package/dist/output/sanitize.js.map +1 -0
  134. package/dist/output/table.d.ts +9 -0
  135. package/dist/output/table.d.ts.map +1 -0
  136. package/dist/output/table.js +19 -0
  137. package/dist/output/table.js.map +1 -0
  138. package/dist/prompt-masked.d.ts +15 -0
  139. package/dist/prompt-masked.d.ts.map +1 -0
  140. package/dist/prompt-masked.js +75 -0
  141. package/dist/prompt-masked.js.map +1 -0
  142. package/dist/report-error.d.ts +18 -0
  143. package/dist/report-error.d.ts.map +1 -0
  144. package/dist/report-error.js +63 -0
  145. package/dist/report-error.js.map +1 -0
  146. package/dist/resolve-entity.d.ts +13 -0
  147. package/dist/resolve-entity.d.ts.map +1 -0
  148. package/dist/resolve-entity.js +18 -0
  149. package/dist/resolve-entity.js.map +1 -0
  150. package/dist/version.d.ts +4 -0
  151. package/dist/version.d.ts.map +1 -0
  152. package/dist/version.js +4 -0
  153. package/dist/version.js.map +1 -0
  154. package/package.json +51 -0
@@ -0,0 +1,24 @@
1
+ import { resolveApiUrl, resolveOrganisationId, resolveToken } from "../config/resolve.js";
2
+ import { ControlPlaneClient } from "./client.js";
3
+ import { CliError } from "./errors.js";
4
+ /** For the rare command that works whether or not the caller is logged in (none in v1, but keeps the option open) — never throws for a missing token. */
5
+ export function createControlPlaneClient(overrides = {}) {
6
+ return new ControlPlaneClient({
7
+ baseUrl: resolveApiUrl(overrides.apiUrl),
8
+ token: resolveToken()?.token,
9
+ organisationId: resolveOrganisationId(overrides.organisationId)
10
+ });
11
+ }
12
+ /** Every command that needs to act as a signed-in user calls this — throws a clear, exit-code-2 error rather than letting an unauthenticated request 401 confusingly deep inside a command. */
13
+ export function requireControlPlaneClient(overrides = {}) {
14
+ const resolved = resolveToken();
15
+ if (!resolved) {
16
+ throw new CliError("AXTRA_CLI_NOT_LOGGED_IN", "Not logged in. Run `axtrabase login`, or set AXTRABASE_CLI_TOKEN for non-interactive use.", { status: 0 });
17
+ }
18
+ return new ControlPlaneClient({
19
+ baseUrl: resolveApiUrl(overrides.apiUrl),
20
+ token: resolved.token,
21
+ organisationId: resolveOrganisationId(overrides.organisationId)
22
+ });
23
+ }
24
+ //# sourceMappingURL=authenticated-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticated-client.js","sourceRoot":"","sources":["../../src/http/authenticated-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOvC,yJAAyJ;AACzJ,MAAM,UAAU,wBAAwB,CAAC,YAA6B,EAAE;IACtE,OAAO,IAAI,kBAAkB,CAAC;QAC5B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC;QACxC,KAAK,EAAE,YAAY,EAAE,EAAE,KAAK;QAC5B,cAAc,EAAE,qBAAqB,CAAC,SAAS,CAAC,cAAc,CAAC;KAChE,CAAC,CAAC;AACL,CAAC;AAED,+LAA+L;AAC/L,MAAM,UAAU,yBAAyB,CAAC,YAA6B,EAAE;IACvE,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,QAAQ,CAChB,yBAAyB,EACzB,2FAA2F,EAC3F,EAAE,MAAM,EAAE,CAAC,EAAE,CACd,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,kBAAkB,CAAC;QAC5B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC;QACxC,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,cAAc,EAAE,qBAAqB,CAAC,SAAS,CAAC,cAAc,CAAC;KAChE,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,42 @@
1
+ export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
2
+ export interface RequestEnvelope<T> {
3
+ data: T;
4
+ meta: {
5
+ requestId: string;
6
+ nextCursor?: string | null;
7
+ };
8
+ }
9
+ export interface ControlPlaneClientOptions {
10
+ baseUrl: string;
11
+ /** Absent for the one command that doesn't need it yet: `login`, before a token exists. */
12
+ token?: string;
13
+ /** Sent as X-AxtraBase-Organisation-Id — see apps/api/src/session-auth.ts's requireSessionOrCliToken. */
14
+ organisationId?: string;
15
+ /** Mainly for tests — injects a fetch implementation instead of the global one. */
16
+ fetch?: typeof fetch;
17
+ }
18
+ /**
19
+ * A thin client for AxtraBase's *control plane* (`/api/v1/me`,
20
+ * `/api/v1/projects/*`, `/api/v1/organisations`, ...) — authenticated by a
21
+ * CLI token, never an API key. Deliberately separate from @axtrabase/sdk's
22
+ * `AxtraBase` class, which wraps only the Public Data API
23
+ * (`/api/v1/tables/*`) under a different auth scheme; the two are not
24
+ * interchangeable, so this isn't "the SDK with a different token."
25
+ * Mirrors the SDK's request/error conventions closely on purpose (build
26
+ * brief §42 — SDK + CLI cohesion).
27
+ */
28
+ export declare class ControlPlaneClient {
29
+ private readonly baseUrl;
30
+ private readonly token;
31
+ private readonly organisationId;
32
+ private readonly fetchImpl;
33
+ constructor(options: ControlPlaneClientOptions);
34
+ request<T>(method: HttpMethod, path: string, options?: {
35
+ query?: Record<string, string | undefined>;
36
+ body?: unknown;
37
+ }): Promise<RequestEnvelope<T>>;
38
+ get<T>(path: string, query?: Record<string, string | undefined>): Promise<RequestEnvelope<T>>;
39
+ post<T>(path: string, body?: unknown): Promise<RequestEnvelope<T>>;
40
+ delete<T>(path: string): Promise<RequestEnvelope<T>>;
41
+ }
42
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/http/client.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACzD;AAMD,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yGAAyG;IACzG,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAE7B,OAAO,EAAE,yBAAyB;IAOxC,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAO,GAC3E,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAiE9B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAI7F,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAIlE,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;CAGrD"}
@@ -0,0 +1,86 @@
1
+ import { CLI_CLIENT_NAME, CLI_VERSION } from "../version.js";
2
+ import { CliError } from "./errors.js";
3
+ /**
4
+ * A thin client for AxtraBase's *control plane* (`/api/v1/me`,
5
+ * `/api/v1/projects/*`, `/api/v1/organisations`, ...) — authenticated by a
6
+ * CLI token, never an API key. Deliberately separate from @axtrabase/sdk's
7
+ * `AxtraBase` class, which wraps only the Public Data API
8
+ * (`/api/v1/tables/*`) under a different auth scheme; the two are not
9
+ * interchangeable, so this isn't "the SDK with a different token."
10
+ * Mirrors the SDK's request/error conventions closely on purpose (build
11
+ * brief §42 — SDK + CLI cohesion).
12
+ */
13
+ export class ControlPlaneClient {
14
+ baseUrl;
15
+ token;
16
+ organisationId;
17
+ fetchImpl;
18
+ constructor(options) {
19
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
20
+ this.token = options.token;
21
+ this.organisationId = options.organisationId;
22
+ this.fetchImpl = options.fetch ?? fetch;
23
+ }
24
+ async request(method, path, options = {}) {
25
+ const url = new URL(`${this.baseUrl}${path}`);
26
+ for (const [key, value] of Object.entries(options.query ?? {})) {
27
+ if (value !== undefined)
28
+ url.searchParams.set(key, value);
29
+ }
30
+ const headers = {
31
+ "X-AxtraBase-Client": CLI_CLIENT_NAME,
32
+ "X-AxtraBase-CLI-Version": CLI_VERSION
33
+ };
34
+ if (this.token)
35
+ headers.Authorization = `Bearer ${this.token}`;
36
+ if (this.organisationId)
37
+ headers["X-AxtraBase-Organisation-Id"] = this.organisationId;
38
+ if (options.body !== undefined)
39
+ headers["Content-Type"] = "application/json";
40
+ let response;
41
+ try {
42
+ response = await this.fetchImpl(url, {
43
+ method,
44
+ headers,
45
+ body: options.body !== undefined ? JSON.stringify(options.body) : undefined
46
+ });
47
+ }
48
+ catch (error) {
49
+ throw new CliError("AXTRA_CLI_NETWORK_ERROR", error instanceof Error ? error.message : "Network request failed.", { status: 0, cause: error });
50
+ }
51
+ const headerRequestId = response.headers.get("x-axtrabase-request-id") ?? undefined;
52
+ const text = await response.text();
53
+ let json;
54
+ try {
55
+ json = text.length > 0 ? JSON.parse(text) : undefined;
56
+ }
57
+ catch (error) {
58
+ throw new CliError("AXTRA_CLI_INVALID_RESPONSE", "AxtraBase returned a response that could not be parsed as JSON.", { status: response.status, requestId: headerRequestId, cause: error });
59
+ }
60
+ if (!response.ok) {
61
+ const errorBody = json;
62
+ throw new CliError(errorBody?.error.code ?? "AXTRA_CLI_UNKNOWN_ERROR", errorBody?.error.message ?? `Request failed with status ${response.status}.`, { status: response.status, requestId: errorBody?.error.requestId ?? headerRequestId });
63
+ }
64
+ if (json === undefined) {
65
+ return { data: undefined, meta: { requestId: headerRequestId ?? "" } };
66
+ }
67
+ const envelope = json;
68
+ return {
69
+ data: envelope.data,
70
+ meta: {
71
+ requestId: envelope.meta?.requestId ?? headerRequestId ?? "",
72
+ nextCursor: envelope.meta?.nextCursor
73
+ }
74
+ };
75
+ }
76
+ get(path, query) {
77
+ return this.request("GET", path, { query });
78
+ }
79
+ post(path, body) {
80
+ return this.request("POST", path, { body });
81
+ }
82
+ delete(path) {
83
+ return this.request("DELETE", path);
84
+ }
85
+ }
86
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/http/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Every AxtraBase control-plane error code this CLI can surface. Kept as a
3
+ * plain `string` rather than importing @axtrabase/shared's `AxtraErrorCode`
4
+ * — this package is meant to be installable on its own (`npm install -g
5
+ * @axtrabase/cli`), same reasoning as @axtrabase/sdk's AxtraBaseErrorCode.
6
+ * `AXTRA_CLI_*` codes are this CLI's own (network/parse failures that never
7
+ * reached the server); everything else mirrors the server's documented
8
+ * error taxonomy (see docs/developer/errors.md).
9
+ */
10
+ export type CliErrorCode = string;
11
+ export interface CliErrorOptions {
12
+ status: number;
13
+ requestId?: string;
14
+ cause?: unknown;
15
+ }
16
+ /**
17
+ * Thrown for every non-2xx control-plane response and every network-level
18
+ * failure. Every catch site gets `.code`/`.status`/`.requestId` without
19
+ * parsing raw JSON — mirrors @axtrabase/sdk's AxtraBaseError so the two
20
+ * feel like one product to a caller moving between them.
21
+ */
22
+ export declare class CliError extends Error {
23
+ readonly code: CliErrorCode;
24
+ readonly status: number;
25
+ readonly requestId: string | undefined;
26
+ readonly cause: unknown;
27
+ constructor(code: CliErrorCode, message: string, options: CliErrorOptions);
28
+ }
29
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,SAAkB,KAAK,EAAE,OAAO,CAAC;gBAErB,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe;CAQ1E"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Thrown for every non-2xx control-plane response and every network-level
3
+ * failure. Every catch site gets `.code`/`.status`/`.requestId` without
4
+ * parsing raw JSON — mirrors @axtrabase/sdk's AxtraBaseError so the two
5
+ * feel like one product to a caller moving between them.
6
+ */
7
+ export class CliError extends Error {
8
+ code;
9
+ status;
10
+ requestId;
11
+ cause;
12
+ constructor(code, message, options) {
13
+ super(message);
14
+ this.name = "CliError";
15
+ this.code = code;
16
+ this.status = options.status;
17
+ this.requestId = options.requestId;
18
+ this.cause = options.cause;
19
+ }
20
+ }
21
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAiBA;;;;;GAKG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAe;IACnB,MAAM,CAAS;IACf,SAAS,CAAqB;IACrB,KAAK,CAAU;IAEjC,YAAY,IAAkB,EAAE,OAAe,EAAE,OAAwB;QACvE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ import { Command, CommanderError } from "commander";
3
+ import { registerConfigCommand } from "./commands/config.js";
4
+ import { registerConnectionCommand } from "./commands/connection.js";
5
+ import { registerContextCommand } from "./commands/context.js";
6
+ import { registerDocsCommand } from "./commands/docs.js";
7
+ import { registerKeysCommand } from "./commands/keys.js";
8
+ import { registerLoginCommand } from "./commands/login.js";
9
+ import { registerLogoutCommand } from "./commands/logout.js";
10
+ import { registerOpenApiCommand } from "./commands/openapi.js";
11
+ import { registerOrganisationsCommand } from "./commands/organisations.js";
12
+ import { registerPermissionsCommand } from "./commands/permissions.js";
13
+ import { registerProjectsCommand } from "./commands/projects.js";
14
+ import { registerRequestsCommand } from "./commands/requests.js";
15
+ import { registerSchemaCommand } from "./commands/schema.js";
16
+ import { registerStatusCommand } from "./commands/status.js";
17
+ import { registerTablesCommand } from "./commands/tables.js";
18
+ import { registerWhoamiCommand } from "./commands/whoami.js";
19
+ import { EXIT_CODES } from "./exit-codes.js";
20
+ import { CLI_VERSION } from "./version.js";
21
+ const program = new Command();
22
+ program
23
+ .name("axtrabase")
24
+ .description("Inspect an AxtraBase project's schema, permissions, and environment, then build against it " +
25
+ "through @axtrabase/sdk or the REST API — without touching Dataverse or Microsoft OAuth directly.")
26
+ .version(CLI_VERSION, "--version", "print the CLI version")
27
+ .option("--json", "machine-readable JSON output (stable field names, no ANSI)")
28
+ .option("--api-url <url>", "override the AxtraBase API origin for this call")
29
+ .option("--debug", "print additional diagnostics on error (never secrets)")
30
+ .exitOverride();
31
+ registerLoginCommand(program);
32
+ registerLogoutCommand(program);
33
+ registerWhoamiCommand(program);
34
+ registerOrganisationsCommand(program);
35
+ registerProjectsCommand(program);
36
+ registerConnectionCommand(program);
37
+ registerTablesCommand(program);
38
+ registerStatusCommand(program);
39
+ registerContextCommand(program);
40
+ registerSchemaCommand(program);
41
+ registerPermissionsCommand(program);
42
+ registerKeysCommand(program);
43
+ registerRequestsCommand(program);
44
+ registerConfigCommand(program);
45
+ registerDocsCommand(program);
46
+ registerOpenApiCommand(program);
47
+ try {
48
+ await program.parseAsync(process.argv);
49
+ }
50
+ catch (error) {
51
+ if (error instanceof CommanderError) {
52
+ // exitCode 0 means commander already printed help/version successfully
53
+ // — not a real failure. Anything else is malformed CLI usage (unknown
54
+ // command/option, missing required argument), which maps to this
55
+ // program's own INVALID_ARGUMENTS exit code rather than commander's
56
+ // default of 1, so scripts/agents get one consistent contract (see
57
+ // exit-codes.ts, build brief §23).
58
+ process.exit(error.exitCode === 0 ? 0 : EXIT_CODES.INVALID_ARGUMENTS);
59
+ }
60
+ throw error;
61
+ }
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Cross-platform "open a URL in the default browser," without adding an
3
+ * `open`/`opener` dependency for one call site (build brief §2: "zero
4
+ * unnecessary framework weight"). Best-effort — `login.ts` always prints the
5
+ * URL too, so a failure here never blocks the login flow, it just means the
6
+ * user copies the URL themselves.
7
+ */
8
+ export declare function openBrowser(url: string): boolean;
9
+ //# sourceMappingURL=open-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../src/open-browser.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAYhD"}
@@ -0,0 +1,32 @@
1
+ import { spawn } from "node:child_process";
2
+ /**
3
+ * Cross-platform "open a URL in the default browser," without adding an
4
+ * `open`/`opener` dependency for one call site (build brief §2: "zero
5
+ * unnecessary framework weight"). Best-effort — `login.ts` always prints the
6
+ * URL too, so a failure here never blocks the login flow, it just means the
7
+ * user copies the URL themselves.
8
+ */
9
+ export function openBrowser(url) {
10
+ try {
11
+ const { command, args } = commandForPlatform(url);
12
+ const child = spawn(command, args, { stdio: "ignore", detached: true });
13
+ child.on("error", () => {
14
+ // Swallowed deliberately — the caller already has a fallback path (print the URL).
15
+ });
16
+ child.unref();
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ function commandForPlatform(url) {
24
+ if (process.platform === "darwin")
25
+ return { command: "open", args: [url] };
26
+ if (process.platform === "win32") {
27
+ // cmd's `start` needs an empty title argument before the URL when the URL might contain characters cmd would otherwise misparse.
28
+ return { command: "cmd", args: ["/c", "start", "", url] };
29
+ }
30
+ return { command: "xdg-open", args: [url] };
31
+ }
32
+ //# sourceMappingURL=open-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../src/open-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACrB,mFAAmF;QACrF,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW;IACrC,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IAC3E,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,iIAAiI;QACjI,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;IAC5D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Never silently overwrites an existing file without --force (build brief
3
+ * §36), and writes atomically (write to a temp file, then rename) so a
4
+ * process interrupted mid-write never leaves a half-written schema/types
5
+ * file in place of a good one.
6
+ */
7
+ export declare function writeFileSafely(path: string, content: string, force: boolean): void;
8
+ //# sourceMappingURL=file-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-writer.d.ts","sourceRoot":"","sources":["../../src/output/file-writer.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAqBnF"}
@@ -0,0 +1,28 @@
1
+ import { existsSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { CliError } from "../http/errors.js";
3
+ /**
4
+ * Never silently overwrites an existing file without --force (build brief
5
+ * §36), and writes atomically (write to a temp file, then rename) so a
6
+ * process interrupted mid-write never leaves a half-written schema/types
7
+ * file in place of a good one.
8
+ */
9
+ export function writeFileSafely(path, content, force) {
10
+ if (existsSync(path) && !force) {
11
+ throw new CliError("AXTRA_CLI_FILE_EXISTS", `${path} already exists. Pass --force to overwrite it.`, { status: 0 });
12
+ }
13
+ const tmpPath = `${path}.axtrabase-tmp-${process.pid}`;
14
+ try {
15
+ writeFileSync(tmpPath, content, "utf8");
16
+ renameSync(tmpPath, path);
17
+ }
18
+ catch (error) {
19
+ try {
20
+ unlinkSync(tmpPath);
21
+ }
22
+ catch {
23
+ // Best-effort cleanup — the original error is what matters.
24
+ }
25
+ throw error;
26
+ }
27
+ }
28
+ //# sourceMappingURL=file-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/output/file-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe,EAAE,KAAc;IAC3E,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,IAAI,QAAQ,CAChB,uBAAuB,EACvB,GAAG,IAAI,gDAAgD,EACvD,EAAE,MAAM,EAAE,CAAC,EAAE,CACd,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,IAAI,kBAAkB,OAAO,CAAC,GAAG,EAAE,CAAC;IACvD,IAAI,CAAC;QACH,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACxC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,4DAA4D;QAC9D,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The JSON-output contract every command with `--json` follows (build brief
3
+ * §22): stdout carries only the machine-readable result, stable field
4
+ * ordering (the `data` shape is fixed per-command; JSON.stringify preserves
5
+ * insertion order for string keys), no ANSI, and a trailing newline so
6
+ * shells don't glue the next prompt onto the output.
7
+ */
8
+ export declare function printJson(data: unknown): void;
9
+ /** Progress/warnings never belong on stdout when --json is active — see build brief §22 ("stdout = machine-readable result only"). */
10
+ export declare function printProgress(message: string): void;
11
+ /** A sanitized single line of human-facing stdout output. */
12
+ export declare function printLine(line?: string): void;
13
+ /** A simple "Label: value" block for whoami/status-style output — deliberately not a table library, matching the build brief's "no unnecessary framework weight." */
14
+ export declare function printKeyValueBlock(rows: Array<[string, string]>): void;
15
+ //# sourceMappingURL=print.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print.d.ts","sourceRoot":"","sources":["../../src/output/print.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE7C;AAED,sIAAsI;AACtI,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAW,GAAG,IAAI,CAEjD;AAED,qKAAqK;AACrK,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAKtE"}
@@ -0,0 +1,27 @@
1
+ import { sanitizeForTerminal } from "./sanitize.js";
2
+ /**
3
+ * The JSON-output contract every command with `--json` follows (build brief
4
+ * §22): stdout carries only the machine-readable result, stable field
5
+ * ordering (the `data` shape is fixed per-command; JSON.stringify preserves
6
+ * insertion order for string keys), no ANSI, and a trailing newline so
7
+ * shells don't glue the next prompt onto the output.
8
+ */
9
+ export function printJson(data) {
10
+ process.stdout.write(`${JSON.stringify(data, null, 2)}\n`);
11
+ }
12
+ /** Progress/warnings never belong on stdout when --json is active — see build brief §22 ("stdout = machine-readable result only"). */
13
+ export function printProgress(message) {
14
+ process.stderr.write(`${message}\n`);
15
+ }
16
+ /** A sanitized single line of human-facing stdout output. */
17
+ export function printLine(line = "") {
18
+ process.stdout.write(`${sanitizeForTerminal(line)}\n`);
19
+ }
20
+ /** A simple "Label: value" block for whoami/status-style output — deliberately not a table library, matching the build brief's "no unnecessary framework weight." */
21
+ export function printKeyValueBlock(rows) {
22
+ const labelWidth = Math.max(...rows.map(([label]) => label.length));
23
+ for (const [label, value] of rows) {
24
+ printLine(`${label.padEnd(labelWidth)} ${value}`);
25
+ }
26
+ }
27
+ //# sourceMappingURL=print.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print.js","sourceRoot":"","sources":["../../src/output/print.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,IAAa;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,sIAAsI;AACtI,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE;IACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzD,CAAC;AAED,qKAAqK;AACrK,MAAM,UAAU,kBAAkB,CAAC,IAA6B;IAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpE,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QAClC,SAAS,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Strips terminal-dangerous control characters from a string before it is
3
+ * ever written directly to a human terminal — display names, table names,
4
+ * server-provided error messages, and the like are not trusted input (a
5
+ * maliciously named Dataverse table is a real, if unlikely, scenario) and
6
+ * must never be able to move the cursor, clear the screen, or otherwise
7
+ * spoof terminal output (build brief §35).
8
+ *
9
+ * Newline and tab are deliberately exempted: they're ordinary layout
10
+ * characters, not an escape mechanism, and this CLI's own multi-line
11
+ * guidance messages (e.g. "No active project.\n\nRun: ...") rely on real
12
+ * newlines surviving this function. ESC (which enables the entire ANSI/CSI
13
+ * escape family — cursor movement, screen clear, OSC title/hyperlink
14
+ * tricks) and bare carriage return (which can overwrite already-printed
15
+ * output in place) are exactly what this function exists to block, along
16
+ * with every other C0 control character and DEL.
17
+ *
18
+ * `--json` output is unaffected by this function and needs no separate
19
+ * sanitization: `JSON.stringify` already escapes every C0 control character
20
+ * in a string, so a raw escape byte can never reach a terminal through
21
+ * piped JSON either.
22
+ *
23
+ * Iterates by code point (not index) and compares numeric ranges rather
24
+ * than using a regex literal with raw control bytes embedded in it — a
25
+ * regex character class spelled out with actual control-character bytes in
26
+ * the source file is unreadable in editors/diffs and risks being treated as
27
+ * binary by tooling.
28
+ */
29
+ export declare function sanitizeForTerminal(value: string): string;
30
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/output/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUzD"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Strips terminal-dangerous control characters from a string before it is
3
+ * ever written directly to a human terminal — display names, table names,
4
+ * server-provided error messages, and the like are not trusted input (a
5
+ * maliciously named Dataverse table is a real, if unlikely, scenario) and
6
+ * must never be able to move the cursor, clear the screen, or otherwise
7
+ * spoof terminal output (build brief §35).
8
+ *
9
+ * Newline and tab are deliberately exempted: they're ordinary layout
10
+ * characters, not an escape mechanism, and this CLI's own multi-line
11
+ * guidance messages (e.g. "No active project.\n\nRun: ...") rely on real
12
+ * newlines surviving this function. ESC (which enables the entire ANSI/CSI
13
+ * escape family — cursor movement, screen clear, OSC title/hyperlink
14
+ * tricks) and bare carriage return (which can overwrite already-printed
15
+ * output in place) are exactly what this function exists to block, along
16
+ * with every other C0 control character and DEL.
17
+ *
18
+ * `--json` output is unaffected by this function and needs no separate
19
+ * sanitization: `JSON.stringify` already escapes every C0 control character
20
+ * in a string, so a raw escape byte can never reach a terminal through
21
+ * piped JSON either.
22
+ *
23
+ * Iterates by code point (not index) and compares numeric ranges rather
24
+ * than using a regex literal with raw control bytes embedded in it — a
25
+ * regex character class spelled out with actual control-character bytes in
26
+ * the source file is unreadable in editors/diffs and risks being treated as
27
+ * binary by tooling.
28
+ */
29
+ export function sanitizeForTerminal(value) {
30
+ const ALLOWED_CONTROL_CODE_POINTS = new Set([9, 10]); // tab, line feed
31
+ let result = "";
32
+ for (const char of value) {
33
+ const codePoint = char.codePointAt(0) ?? 0;
34
+ const isDangerousControlCharacter = (codePoint <= 0x1f && !ALLOWED_CONTROL_CODE_POINTS.has(codePoint)) || codePoint === 0x7f;
35
+ if (!isDangerousControlCharacter)
36
+ result += char;
37
+ }
38
+ return result;
39
+ }
40
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/output/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,iBAAiB;IACvE,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,2BAA2B,GAC/B,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,SAAS,KAAK,IAAI,CAAC;QAC3F,IAAI,CAAC,2BAA2B;YAAE,MAAM,IAAI,IAAI,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * A minimal fixed-width table renderer — deliberately not a table library
3
+ * (build brief §2: "zero unnecessary framework weight"). Every cell is
4
+ * sanitized before being measured/printed, so a malicious display name
5
+ * can't widen a column with a wide-looking escape sequence or otherwise
6
+ * corrupt the layout.
7
+ */
8
+ export declare function renderTable(headers: string[], rows: string[][]): string;
9
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/output/table.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAevE"}
@@ -0,0 +1,19 @@
1
+ import { sanitizeForTerminal } from "./sanitize.js";
2
+ /**
3
+ * A minimal fixed-width table renderer — deliberately not a table library
4
+ * (build brief §2: "zero unnecessary framework weight"). Every cell is
5
+ * sanitized before being measured/printed, so a malicious display name
6
+ * can't widen a column with a wide-looking escape sequence or otherwise
7
+ * corrupt the layout.
8
+ */
9
+ export function renderTable(headers, rows) {
10
+ const sanitizedHeaders = headers.map(sanitizeForTerminal);
11
+ const sanitizedRows = rows.map((row) => row.map(sanitizeForTerminal));
12
+ const widths = sanitizedHeaders.map((header, columnIndex) => Math.max(header.length, ...sanitizedRows.map((row) => (row[columnIndex] ?? "").length)));
13
+ const renderRow = (cells) => cells
14
+ .map((cell, index) => cell.padEnd(widths[index] ?? 0))
15
+ .join(" ")
16
+ .trimEnd();
17
+ return [renderRow(sanitizedHeaders), ...sanitizedRows.map(renderRow)].join("\n");
18
+ }
19
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/output/table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAiB,EAAE,IAAgB;IAC7D,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAEtE,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,CAC1D,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CACxF,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,KAAe,EAAU,EAAE,CAC5C,KAAK;SACF,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;SACrD,IAAI,CAAC,IAAI,CAAC;SACV,OAAO,EAAE,CAAC;IAEf,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Prompts for a secret on stdin, echoing `*` instead of the typed/pasted
3
+ * characters — used by `axtrabase login` for the pasted CLI token (build
4
+ * brief §5 treats the token as sensitive from the moment it's entered).
5
+ * Falls back to an unmasked `readline` prompt when stdin isn't a TTY (piped
6
+ * input, most test environments) since there's no terminal to mask against
7
+ * and raw mode isn't available there anyway.
8
+ *
9
+ * Control characters (Enter, Backspace, Ctrl-C, Ctrl-D) are matched via
10
+ * `String.fromCharCode` rather than escape-sequence literals in this file's
11
+ * source text — keeps the file plain, diffable ASCII instead of risking
12
+ * literal control bytes ending up embedded in the source.
13
+ */
14
+ export declare function promptMasked(promptText: string): Promise<string>;
15
+ //# sourceMappingURL=prompt-masked.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-masked.d.ts","sourceRoot":"","sources":["../src/prompt-masked.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkDhE"}