@axtrabase/cli 0.1.2 → 0.1.4

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 (50) hide show
  1. package/README.md +39 -4
  2. package/dist/api-types.d.ts +39 -0
  3. package/dist/api-types.d.ts.map +1 -1
  4. package/dist/commands/config.d.ts.map +1 -1
  5. package/dist/commands/config.js +71 -20
  6. package/dist/commands/config.js.map +1 -1
  7. package/dist/commands/context.d.ts +62 -0
  8. package/dist/commands/context.d.ts.map +1 -1
  9. package/dist/commands/context.js +82 -6
  10. package/dist/commands/context.js.map +1 -1
  11. package/dist/commands/keys.js +16 -0
  12. package/dist/commands/keys.js.map +1 -1
  13. package/dist/commands/login.js +14 -0
  14. package/dist/commands/login.js.map +1 -1
  15. package/dist/commands/permissions.js +13 -3
  16. package/dist/commands/permissions.js.map +1 -1
  17. package/dist/commands/status.js +22 -3
  18. package/dist/commands/status.js.map +1 -1
  19. package/dist/commands/tables.js +69 -12
  20. package/dist/commands/tables.js.map +1 -1
  21. package/dist/config/environments.d.ts +43 -0
  22. package/dist/config/environments.d.ts.map +1 -0
  23. package/dist/config/environments.js +43 -0
  24. package/dist/config/environments.js.map +1 -0
  25. package/dist/config/resolve.d.ts +25 -4
  26. package/dist/config/resolve.d.ts.map +1 -1
  27. package/dist/config/resolve.js +59 -11
  28. package/dist/config/resolve.js.map +1 -1
  29. package/dist/config/store.d.ts +4 -2
  30. package/dist/config/store.d.ts.map +1 -1
  31. package/dist/config/store.js +1 -0
  32. package/dist/config/store.js.map +1 -1
  33. package/dist/exit-codes.d.ts.map +1 -1
  34. package/dist/exit-codes.js +8 -0
  35. package/dist/exit-codes.js.map +1 -1
  36. package/dist/generators/typescript.d.ts +15 -0
  37. package/dist/generators/typescript.d.ts.map +1 -1
  38. package/dist/generators/typescript.js +126 -11
  39. package/dist/generators/typescript.js.map +1 -1
  40. package/dist/prompt-masked.d.ts +3 -1
  41. package/dist/prompt-masked.d.ts.map +1 -1
  42. package/dist/prompt-masked.js +23 -2
  43. package/dist/prompt-masked.js.map +1 -1
  44. package/dist/report-error.d.ts +16 -1
  45. package/dist/report-error.d.ts.map +1 -1
  46. package/dist/report-error.js +45 -2
  47. package/dist/report-error.js.map +1 -1
  48. package/dist/version.d.ts +1 -1
  49. package/dist/version.js +1 -1
  50. package/package.json +11 -11
@@ -1,5 +1,20 @@
1
1
  import type { TableMetadataResponse } from "../api-types.js";
2
2
  /** Generates a single `export interface` for one table's columns, over metadata fetched via HTTP (never Dataverse directly). */
3
3
  export declare function generateInterface(table: TableMetadataResponse): string;
4
+ /**
5
+ * Create/update input types for one table.
6
+ *
7
+ * Requiredness alone is not enough to describe a column. Some columns are
8
+ * required on READ and impossible to WRITE — Dataverse's system columns
9
+ * (`createdbyyominame`, `owneridname`, `owningbusinessunitname` and
10
+ * friends) come back `isRequired: true` with `isWritable: false`. Emitting
11
+ * one interface for both directions made those mandatory in create
12
+ * payloads, so a caller building a create body from the generated types got
13
+ * a compiler demanding fields the API cannot accept.
14
+ *
15
+ * Read and write surfaces are therefore separate types, as Sprint #11 P1-8
16
+ * asks: preserve the contract rather than flatten it in either direction.
17
+ */
18
+ export declare function generateInputInterfaces(table: TableMetadataResponse): string;
4
19
  export declare function generateTypeScriptModule(tables: TableMetadataResponse[]): string;
5
20
  //# sourceMappingURL=typescript.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/generators/typescript.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA6C1E,gIAAgI;AAChI,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAItE;AAsBD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAGhF"}
1
+ {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../src/generators/typescript.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAsH1E,gIAAgI;AAChI,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAMtE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAe5E;AAuCD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAMhF"}
@@ -23,6 +23,10 @@ const TS_TYPE_BY_COLUMN_TYPE = {
23
23
  owner: "string",
24
24
  state: "number",
25
25
  status: "number",
26
+ // Dataverse serves File/Image content as a base64 string (or a file id) —
27
+ // never a structured object — over the Web API.
28
+ file: "string",
29
+ image: "string",
26
30
  unknown: "unknown"
27
31
  };
28
32
  function toPascalCase(logicalName) {
@@ -32,17 +36,108 @@ function toPascalCase(logicalName) {
32
36
  .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
33
37
  .join("");
34
38
  }
39
+ function tsTypeFor(column) {
40
+ return TS_TYPE_BY_COLUMN_TYPE[column.type] ?? "unknown";
41
+ }
42
+ /**
43
+ * Only an explicit `false` means not writable. Null or undefined means
44
+ * Dataverse did not say, and dropping a column on a guess would be a worse
45
+ * failure than keeping one that turns out to be read-only.
46
+ */
47
+ function isWritableColumn(column) {
48
+ return column.isWritable !== false;
49
+ }
50
+ function isLookup(column) {
51
+ return column.type === "lookup" || column.type === "owner";
52
+ }
53
+ /**
54
+ * Dataverse does not return a lookup under its own logical name. It returns
55
+ * the GUID as `_<logicalName>_value`, and the plain key is absent from the
56
+ * payload entirely. Emitting the plain name meant `record.adp_expensesubmission`
57
+ * was `undefined` on every row with a compiler that said it was fine — a
58
+ * silent failure on every lookup of every table, found by a clean-room test.
59
+ */
60
+ function readPropertyName(column) {
61
+ return isLookup(column) ? `_${column.logicalName}_value` : column.logicalName;
62
+ }
63
+ /**
64
+ * Writes bind to the navigation property: `"<nav>@odata.bind": "/<set>(<guid>)"`.
65
+ * The navigation name comes from the table's resolved many-to-one
66
+ * relationships; without one the logical name is the best available guess,
67
+ * which the generated header says plainly.
68
+ */
69
+ function writePropertyName(column, table) {
70
+ if (!isLookup(column))
71
+ return column.logicalName;
72
+ const relationship = (table.relationships ?? []).find((candidate) => candidate.kind === "many-to-one" && candidate.referencingColumn === column.logicalName);
73
+ return `"${relationship?.navigationName ?? column.logicalName}@odata.bind"`;
74
+ }
75
+ /**
76
+ * Read model. Requiredness is part of the schema contract, so it survives
77
+ * into the generated type: the primary key is always present, a
78
+ * Dataverse-required column is emitted as present and non-nullable, and
79
+ * everything else stays optional + nullable (a read need not return every
80
+ * column). Emitting required business fields as optional silently told
81
+ * every consumer a value might be absent when the platform guarantees it
82
+ * (Sprint #11 P1-8).
83
+ */
35
84
  function fieldLine(column) {
36
- const tsType = TS_TYPE_BY_COLUMN_TYPE[column.type] ?? "unknown";
37
- const optional = column.isPrimaryId ? "" : "?";
38
- const nullable = column.isPrimaryId ? "" : " | null";
39
- return ` ${column.logicalName}${optional}: ${tsType}${nullable};`;
85
+ // A lookup's _value property is not guaranteed present on a read that
86
+ // didn't select it, whatever the underlying column's required-ness says.
87
+ const alwaysPresent = (column.isPrimaryId || column.isRequired) && !isLookup(column);
88
+ const optional = alwaysPresent ? "" : "?";
89
+ const nullable = alwaysPresent ? "" : " | null";
90
+ return ` ${readPropertyName(column)}${optional}: ${tsTypeFor(column)}${nullable};`;
91
+ }
92
+ /** Create input: the primary key is server-assigned, so accept it, never demand it. */
93
+ function createFieldLine(column, table) {
94
+ // The primary key is server-assigned, and so is the owner: Dataverse gives
95
+ // a new record to the calling user when ownerid is omitted, even though the
96
+ // column is SystemRequired. Demanding either would force callers to supply
97
+ // something the platform already fills in.
98
+ const required = column.isRequired && !column.isPrimaryId && column.type !== "owner";
99
+ return ` ${writePropertyName(column, table)}${required ? "" : "?"}: ${tsTypeFor(column)};`;
100
+ }
101
+ /** Update input: same writable surface, every field optional — updates are partial. */
102
+ function updateFieldLine(column, table) {
103
+ return ` ${writePropertyName(column, table)}?: ${tsTypeFor(column)};`;
40
104
  }
41
105
  /** Generates a single `export interface` for one table's columns, over metadata fetched via HTTP (never Dataverse directly). */
42
106
  export function generateInterface(table) {
43
107
  const name = toPascalCase(table.logicalName);
44
108
  const lines = table.columns.map(fieldLine);
45
- return [`export interface ${name} {`, ...lines, `}`].join("\n");
109
+ // Dataverse's @odata.etag arrives on every record through the data plane;
110
+ // the type says so rather than pretending it isn't there.
111
+ return [`export interface ${name} {`, ' "@odata.etag"?: string;', ...lines, `}`].join("\n");
112
+ }
113
+ /**
114
+ * Create/update input types for one table.
115
+ *
116
+ * Requiredness alone is not enough to describe a column. Some columns are
117
+ * required on READ and impossible to WRITE — Dataverse's system columns
118
+ * (`createdbyyominame`, `owneridname`, `owningbusinessunitname` and
119
+ * friends) come back `isRequired: true` with `isWritable: false`. Emitting
120
+ * one interface for both directions made those mandatory in create
121
+ * payloads, so a caller building a create body from the generated types got
122
+ * a compiler demanding fields the API cannot accept.
123
+ *
124
+ * Read and write surfaces are therefore separate types, as Sprint #11 P1-8
125
+ * asks: preserve the contract rather than flatten it in either direction.
126
+ */
127
+ export function generateInputInterfaces(table) {
128
+ const name = toPascalCase(table.logicalName);
129
+ const writable = table.columns.filter(isWritableColumn);
130
+ return [
131
+ `export interface ${name}Create {`,
132
+ ...writable.map((column) => createFieldLine(column, table)),
133
+ `}`,
134
+ ``,
135
+ `export interface ${name}Update {`,
136
+ ...writable
137
+ .filter((column) => !column.isPrimaryId)
138
+ .map((column) => updateFieldLine(column, table)),
139
+ `}`
140
+ ].join("\n");
46
141
  }
47
142
  /**
48
143
  * The generated-file header states the known metadata gap explicitly
@@ -55,16 +150,36 @@ function generatedHeader(tableNames) {
55
150
  " * Generated by `axtrabase schema export --format typescript` — do not edit by hand.",
56
151
  ` * Tables: ${tableNames.join(", ")}`,
57
152
  " *",
58
- " * Known gaps (see `axtrabase context --json`'s metadataCapabilities):",
59
- " * - Incoming (one-to-many) relationships are not represented.",
60
- " * - Choice/option-set values are not represented — choice columns are typed",
61
- " * `number` (the underlying option value), not a literal union of known options.",
153
+ " * What these interfaces do NOT encode. AxtraBase resolves all of it —",
154
+ " * run `axtrabase tables describe <table>` to see it — it is simply not",
155
+ " * expressed in the generated types:",
156
+ " * - Relationships (many-to-one, one-to-many, many-to-many).",
157
+ " * - Choice option values: a choice column is typed `number` (the",
158
+ " * underlying option value), not a literal union of its known options.",
159
+ " *",
160
+ " * Lookups are not named after their column. Dataverse returns the GUID",
161
+ " * as `_<logicalName>_value` on read and accepts writes as",
162
+ " * `<navigationName>@odata.bind`; both forms are emitted below. Where no",
163
+ " * navigation name was resolved, the logical name is used and may need",
164
+ " * adjusting.",
165
+ " *",
166
+ " * Three types per table:",
167
+ " * - <Name> every column as read back; required columns present.",
168
+ " * - <Name>Create writable columns only; required-and-writable required.",
169
+ " * - <Name>Update writable columns only, all optional (partial update).",
170
+ " *",
171
+ " * Read-only columns (isWritable: false) are deliberately absent from the",
172
+ " * Create/Update types — several are required on read but rejected on",
173
+ " * write, so a single shared type would demand fields the API refuses.",
62
174
  " */",
63
175
  ""
64
176
  ].join("\n");
65
177
  }
66
178
  export function generateTypeScriptModule(tables) {
67
- const interfaces = tables.map((table) => generateInterface(table));
68
- return `${generatedHeader(tables.map((t) => t.logicalName))}\n${interfaces.join("\n\n")}\n`;
179
+ const blocks = tables.flatMap((table) => [
180
+ generateInterface(table),
181
+ generateInputInterfaces(table)
182
+ ]);
183
+ return `${generatedHeader(tables.map((t) => t.logicalName))}\n${blocks.join("\n\n")}\n`;
69
184
  }
70
185
  //# sourceMappingURL=typescript.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../src/generators/typescript.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,sBAAsB,GAA2B;IACrD,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;CACnB,CAAC;AAEF,SAAS,YAAY,CAAC,WAAmB;IACvC,OAAO,WAAW;SACf,KAAK,CAAC,OAAO,CAAC;SACd,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,MAAmB;IACpC,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;IAChE,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrD,OAAO,KAAK,MAAM,CAAC,WAAW,GAAG,QAAQ,KAAK,MAAM,GAAG,QAAQ,GAAG,CAAC;AACrE,CAAC;AAED,gIAAgI;AAChI,MAAM,UAAU,iBAAiB,CAAC,KAA4B;IAC5D,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3C,OAAO,CAAC,oBAAoB,IAAI,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,UAAoB;IAC3C,OAAO;QACL,KAAK;QACL,sFAAsF;QACtF,cAAc,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACrC,IAAI;QACJ,wEAAwE;QACxE,gEAAgE;QAChE,8EAA8E;QAC9E,oFAAoF;QACpF,KAAK;QACL,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAA+B;IACtE,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AAC9F,CAAC"}
1
+ {"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../src/generators/typescript.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,9 @@
4
4
  * brief §5 treats the token as sensitive from the moment it's entered).
5
5
  * Falls back to an unmasked `readline` prompt when stdin isn't a TTY (piped
6
6
  * input, most test environments) since there's no terminal to mask against
7
- * and raw mode isn't available there anyway.
7
+ * and raw mode isn't available there anyway. That fallback rejects with
8
+ * `AXTRA_CLI_NON_INTERACTIVE` if stdin closes without an answer, rather than
9
+ * hanging — see promptUnmasked.
8
10
  *
9
11
  * Control characters (Enter, Backspace, Ctrl-C, Ctrl-D) are matched via
10
12
  * `String.fromCharCode` rather than escape-sequence literals in this file's
@@ -1 +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"}
1
+ {"version":3,"file":"prompt-masked.d.ts","sourceRoot":"","sources":["../src/prompt-masked.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkDhE"}
@@ -1,4 +1,5 @@
1
1
  import { createInterface } from "node:readline";
2
+ import { CliError } from "./http/errors.js";
2
3
  const ENTER_CHARS = new Set(["\n", "\r"]);
3
4
  const BACKSPACE_CHARS = new Set([String.fromCharCode(127), "\b"]);
4
5
  const CTRL_C = String.fromCharCode(3);
@@ -9,7 +10,9 @@ const CTRL_D = String.fromCharCode(4);
9
10
  * brief §5 treats the token as sensitive from the moment it's entered).
10
11
  * Falls back to an unmasked `readline` prompt when stdin isn't a TTY (piped
11
12
  * input, most test environments) since there's no terminal to mask against
12
- * and raw mode isn't available there anyway.
13
+ * and raw mode isn't available there anyway. That fallback rejects with
14
+ * `AXTRA_CLI_NON_INTERACTIVE` if stdin closes without an answer, rather than
15
+ * hanging — see promptUnmasked.
13
16
  *
14
17
  * Control characters (Enter, Backspace, Ctrl-C, Ctrl-D) are matched via
15
18
  * `String.fromCharCode` rather than escape-sequence literals in this file's
@@ -64,12 +67,30 @@ export function promptMasked(promptText) {
64
67
  });
65
68
  }
66
69
  function promptUnmasked(promptText) {
67
- return new Promise((resolve) => {
70
+ return new Promise((resolve, reject) => {
68
71
  const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: false });
72
+ // readline's `question` callback only ever fires on a completed line, so
73
+ // a stdin that reaches EOF with nothing on it (an agent or CI job running
74
+ // `axtrabase login` with no terminal and no piped answer) would otherwise
75
+ // leave this promise pending forever — the command hung and the caller
76
+ // saw raw Node runtime output instead of an AxtraBase error. Settling on
77
+ // `close` makes that case deliberate. See Sprint #11 P1-10.
78
+ let answered = false;
69
79
  rl.question(promptText, (answer) => {
80
+ answered = true;
70
81
  rl.close();
71
82
  resolve(answer.trim());
72
83
  });
84
+ rl.on("close", () => {
85
+ if (answered)
86
+ return;
87
+ reject(new CliError("AXTRA_CLI_NON_INTERACTIVE", "axtrabase login needs an interactive terminal to accept a pasted CLI token, and stdin provided none.\n\n" +
88
+ "For an agent or CI environment, supply the token directly instead of logging in:\n" +
89
+ " export AXTRABASE_CLI_TOKEN=axcli_...\n\n" +
90
+ "The token is read fresh on every command and is never written to disk. " +
91
+ "Create one from the dashboard (`axtrabase config get dashboard-url` shows which environment you are on), " +
92
+ "and revoke it with `axtrabase logout --revoke` when the session is done.", { status: 0 }));
93
+ });
73
94
  });
74
95
  }
75
96
  //# sourceMappingURL=prompt-masked.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-masked.js","sourceRoot":"","sources":["../src/prompt-masked.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prompt-masked.js","sourceRoot":"","sources":["../src/prompt-masked.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
+ import { CliError } from "./http/errors.js";
1
2
  import { EXIT_CODES } from "./exit-codes.js";
2
3
  export interface ErrorReportOptions {
3
4
  json?: boolean;
4
- /** Prints the error's cause/stack to stderr — still never a raw secret (build brief §24: "redact secrets/tokens"). */
5
+ /** Prints diagnostics (origins, credential source, status, cause) to stderr — never a raw secret (build brief §24: "redact secrets/tokens"). */
5
6
  debug?: boolean;
7
+ /** The --api-url override, if the command was given one, so --debug reports the origin actually called. */
8
+ apiUrl?: string;
6
9
  }
7
10
  /**
8
11
  * The one place a caught error becomes CLI output + an exit code (build
@@ -12,6 +15,18 @@ export interface ErrorReportOptions {
12
15
  * per-command.
13
16
  */
14
17
  export declare function reportError(error: unknown, options?: ErrorReportOptions): never;
18
+ /**
19
+ * What --debug prints. It used to print only an error's `cause`, which an
20
+ * HTTP error response never has — so for a revoked token or a 403, the
21
+ * failures that most need diagnosing, --debug produced byte-identical output
22
+ * to running without it. A clean-room tester with a revoked first token then
23
+ * had to rule out an origin mismatch by hand, because the one fact that
24
+ * mattered — which origin the CLI just called — was never shown.
25
+ *
26
+ * Everything here is safe to paste into a bug report. The credential's
27
+ * SOURCE is shown; the credential itself never is.
28
+ */
29
+ export declare function debugDiagnostics(error: CliError, apiUrlFlag?: string): string;
15
30
  /** Wraps a command action so every command doesn't hand-roll the same try/catch; the action itself decides what --json/--debug values to pass through, since only it knows how to read the merged command options. */
16
31
  export declare function runWithErrorHandling(action: () => Promise<void>, options: ErrorReportOptions): Promise<void>;
17
32
  export { EXIT_CODES };
@@ -1 +1 @@
1
- {"version":3,"file":"report-error.d.ts","sourceRoot":"","sources":["../src/report-error.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAC;AAGnE,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,sHAAsH;IACtH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,kBAAuB,GAAG,KAAK,CA8BnF;AA4BD,sNAAsN;AACtN,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC3B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"report-error.d.ts","sourceRoot":"","sources":["../src/report-error.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAC;AAUnE,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gJAAgJ;IAChJ,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2GAA2G;IAC3G,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,kBAAuB,GAAG,KAAK,CA8BnF;AAuBD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CA2B7E;AAOD,sNAAsN;AACtN,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC3B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -2,6 +2,8 @@ import { AxtraBaseError } from "@axtrabase/sdk";
2
2
  import { CliError } from "./http/errors.js";
3
3
  import { EXIT_CODES, exitCodeForErrorCode } from "./exit-codes.js";
4
4
  import { printJson, printLine } from "./output/print.js";
5
+ import { resolveApiUrl, resolveDashboardUrl, resolveEnvironmentName, resolveToken } from "./config/resolve.js";
6
+ import { CLI_VERSION } from "./version.js";
5
7
  /**
6
8
  * The one place a caught error becomes CLI output + an exit code (build
7
9
  * brief §24). Every command's action calls this from its top-level catch —
@@ -33,8 +35,8 @@ export function reportError(error, options = {}) {
33
35
  printLine(cliError.requestId);
34
36
  }
35
37
  }
36
- if (options.debug && cliError.cause) {
37
- process.stderr.write(`${describeCause(cliError.cause)}\n`);
38
+ if (options.debug) {
39
+ process.stderr.write(`${debugDiagnostics(cliError, options.apiUrl)}\n`);
38
40
  }
39
41
  process.exit(exitCodeForErrorCode(cliError.code));
40
42
  }
@@ -59,6 +61,47 @@ function toCliError(error) {
59
61
  }
60
62
  return new CliError("AXTRA_CLI_UNEXPECTED_ERROR", "An unexpected error occurred.", { status: 0 });
61
63
  }
64
+ /**
65
+ * What --debug prints. It used to print only an error's `cause`, which an
66
+ * HTTP error response never has — so for a revoked token or a 403, the
67
+ * failures that most need diagnosing, --debug produced byte-identical output
68
+ * to running without it. A clean-room tester with a revoked first token then
69
+ * had to rule out an origin mismatch by hand, because the one fact that
70
+ * mattered — which origin the CLI just called — was never shown.
71
+ *
72
+ * Everything here is safe to paste into a bug report. The credential's
73
+ * SOURCE is shown; the credential itself never is.
74
+ */
75
+ export function debugDiagnostics(error, apiUrlFlag) {
76
+ const lines = ["", "--- debug ---", `cli version: ${CLI_VERSION}`];
77
+ const safely = (label, read) => {
78
+ try {
79
+ lines.push(`${label}${read()}`);
80
+ }
81
+ catch (resolveError) {
82
+ lines.push(`${label}(could not resolve: ${describeCause(resolveError)})`);
83
+ }
84
+ };
85
+ safely("environment: ", () => resolveEnvironmentName());
86
+ safely("api origin: ", () => resolveApiUrl(apiUrlFlag));
87
+ safely("dashboard: ", () => resolveDashboardUrl());
88
+ safely("cli credential:", () => {
89
+ const token = resolveToken();
90
+ if (!token)
91
+ return " none";
92
+ return token.source === "env"
93
+ ? " AXTRABASE_CLI_TOKEN (environment)"
94
+ : " stored credential file";
95
+ });
96
+ lines.push(`api key: ${process.env.AXTRABASE_API_KEY ? "AXTRABASE_API_KEY set" : "not set"}`);
97
+ lines.push(`http status: ${error.status || "(no response — network or local error)"}`);
98
+ lines.push(`error code: ${error.code}`);
99
+ if (error.requestId)
100
+ lines.push(`request id: ${error.requestId}`);
101
+ if (error.cause)
102
+ lines.push("cause:", describeCause(error.cause));
103
+ return lines.join("\n");
104
+ }
62
105
  function describeCause(cause) {
63
106
  if (cause instanceof Error)
64
107
  return cause.stack ?? cause.message;
@@ -1 +1 @@
1
- {"version":3,"file":"report-error.js","sourceRoot":"","sources":["../src/report-error.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report-error.js","sourceRoot":"","sources":["../src/report-error.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /** Bump alongside package.json's version — read at runtime for --version and the X-AxtraBase-Client User-Agent, same convention as @axtrabase/sdk's SDK_VERSION. */
2
- export declare const CLI_VERSION = "0.1.2";
2
+ export declare const CLI_VERSION = "0.1.4";
3
3
  export declare const CLI_CLIENT_NAME = "axtrabase-cli";
4
4
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  /** Bump alongside package.json's version — read at runtime for --version and the X-AxtraBase-Client User-Agent, same convention as @axtrabase/sdk's SDK_VERSION. */
2
- export const CLI_VERSION = "0.1.2";
2
+ export const CLI_VERSION = "0.1.4";
3
3
  export const CLI_CLIENT_NAME = "axtrabase-cli";
4
4
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axtrabase/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "The AxtraBase CLI — inspect an AxtraBase project's schema, permissions, and environment, and build against it without touching Dataverse directly.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -9,7 +9,7 @@
9
9
  "url": "git+https://github.com/erdhem/axtrabase.git",
10
10
  "directory": "packages/cli"
11
11
  },
12
- "homepage": "https://github.com/erdhem/axtrabase/tree/main/packages/cli#readme",
12
+ "homepage": "https://docs-stg.axtraxia.com/docs/cli/overview",
13
13
  "bugs": {
14
14
  "url": "https://github.com/erdhem/axtrabase/issues"
15
15
  },
@@ -32,15 +32,9 @@
32
32
  "files": [
33
33
  "dist"
34
34
  ],
35
- "scripts": {
36
- "build": "tsc -p tsconfig.build.json && chmod +x dist/index.js",
37
- "typecheck": "tsc -p tsconfig.json --noEmit",
38
- "test": "vitest run",
39
- "smoke-test": "bash scripts/pack-install-smoke-test.sh"
40
- },
41
35
  "dependencies": {
42
- "@axtrabase/sdk": "workspace:^",
43
- "commander": "^12.1.0"
36
+ "commander": "^12.1.0",
37
+ "@axtrabase/sdk": "^0.1.1"
44
38
  },
45
39
  "devDependencies": {
46
40
  "typescript": "^5.5.3",
@@ -48,5 +42,11 @@
48
42
  },
49
43
  "engines": {
50
44
  "node": ">=20.9.0"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc -p tsconfig.build.json && chmod +x dist/index.js",
48
+ "typecheck": "tsc -p tsconfig.json --noEmit",
49
+ "test": "vitest run",
50
+ "smoke-test": "bash scripts/pack-install-smoke-test.sh"
51
51
  }
52
- }
52
+ }