gitsheets-axi 0.0.1

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 (99) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +116 -0
  3. package/dist/bin/gitsheets-axi.d.ts +3 -0
  4. package/dist/bin/gitsheets-axi.d.ts.map +1 -0
  5. package/dist/bin/gitsheets-axi.js +4 -0
  6. package/dist/bin/gitsheets-axi.js.map +1 -0
  7. package/dist/src/cli.d.ts +3 -0
  8. package/dist/src/cli.d.ts.map +1 -0
  9. package/dist/src/cli.js +105 -0
  10. package/dist/src/cli.js.map +1 -0
  11. package/dist/src/commands/attachment.d.ts +4 -0
  12. package/dist/src/commands/attachment.d.ts.map +1 -0
  13. package/dist/src/commands/attachment.js +356 -0
  14. package/dist/src/commands/attachment.js.map +1 -0
  15. package/dist/src/commands/check.d.ts +4 -0
  16. package/dist/src/commands/check.d.ts.map +1 -0
  17. package/dist/src/commands/check.js +136 -0
  18. package/dist/src/commands/check.js.map +1 -0
  19. package/dist/src/commands/delete.d.ts +4 -0
  20. package/dist/src/commands/delete.d.ts.map +1 -0
  21. package/dist/src/commands/delete.js +132 -0
  22. package/dist/src/commands/delete.js.map +1 -0
  23. package/dist/src/commands/diff.d.ts +4 -0
  24. package/dist/src/commands/diff.d.ts.map +1 -0
  25. package/dist/src/commands/diff.js +139 -0
  26. package/dist/src/commands/diff.js.map +1 -0
  27. package/dist/src/commands/home.d.ts +3 -0
  28. package/dist/src/commands/home.d.ts.map +1 -0
  29. package/dist/src/commands/home.js +71 -0
  30. package/dist/src/commands/home.js.map +1 -0
  31. package/dist/src/commands/infer.d.ts +4 -0
  32. package/dist/src/commands/infer.d.ts.map +1 -0
  33. package/dist/src/commands/infer.js +214 -0
  34. package/dist/src/commands/infer.js.map +1 -0
  35. package/dist/src/commands/init.d.ts +4 -0
  36. package/dist/src/commands/init.d.ts.map +1 -0
  37. package/dist/src/commands/init.js +172 -0
  38. package/dist/src/commands/init.js.map +1 -0
  39. package/dist/src/commands/migrate-config.d.ts +4 -0
  40. package/dist/src/commands/migrate-config.d.ts.map +1 -0
  41. package/dist/src/commands/migrate-config.js +161 -0
  42. package/dist/src/commands/migrate-config.js.map +1 -0
  43. package/dist/src/commands/normalize.d.ts +4 -0
  44. package/dist/src/commands/normalize.d.ts.map +1 -0
  45. package/dist/src/commands/normalize.js +142 -0
  46. package/dist/src/commands/normalize.js.map +1 -0
  47. package/dist/src/commands/patch.d.ts +4 -0
  48. package/dist/src/commands/patch.d.ts.map +1 -0
  49. package/dist/src/commands/patch.js +172 -0
  50. package/dist/src/commands/patch.js.map +1 -0
  51. package/dist/src/commands/push.d.ts +4 -0
  52. package/dist/src/commands/push.d.ts.map +1 -0
  53. package/dist/src/commands/push.js +112 -0
  54. package/dist/src/commands/push.js.map +1 -0
  55. package/dist/src/commands/query.d.ts +4 -0
  56. package/dist/src/commands/query.d.ts.map +1 -0
  57. package/dist/src/commands/query.js +141 -0
  58. package/dist/src/commands/query.js.map +1 -0
  59. package/dist/src/commands/read.d.ts +4 -0
  60. package/dist/src/commands/read.d.ts.map +1 -0
  61. package/dist/src/commands/read.js +149 -0
  62. package/dist/src/commands/read.js.map +1 -0
  63. package/dist/src/commands/sheets.d.ts +4 -0
  64. package/dist/src/commands/sheets.d.ts.map +1 -0
  65. package/dist/src/commands/sheets.js +142 -0
  66. package/dist/src/commands/sheets.js.map +1 -0
  67. package/dist/src/commands/upsert.d.ts +4 -0
  68. package/dist/src/commands/upsert.d.ts.map +1 -0
  69. package/dist/src/commands/upsert.js +137 -0
  70. package/dist/src/commands/upsert.js.map +1 -0
  71. package/dist/src/context.d.ts +17 -0
  72. package/dist/src/context.d.ts.map +1 -0
  73. package/dist/src/context.js +47 -0
  74. package/dist/src/context.js.map +1 -0
  75. package/dist/src/errors.d.ts +13 -0
  76. package/dist/src/errors.d.ts.map +1 -0
  77. package/dist/src/errors.js +58 -0
  78. package/dist/src/errors.js.map +1 -0
  79. package/dist/src/output/index.d.ts +3 -0
  80. package/dist/src/output/index.d.ts.map +1 -0
  81. package/dist/src/output/index.js +3 -0
  82. package/dist/src/output/index.js.map +1 -0
  83. package/dist/src/output/render.d.ts +28 -0
  84. package/dist/src/output/render.d.ts.map +1 -0
  85. package/dist/src/output/render.js +49 -0
  86. package/dist/src/output/render.js.map +1 -0
  87. package/dist/src/output/schema.d.ts +29 -0
  88. package/dist/src/output/schema.d.ts.map +1 -0
  89. package/dist/src/output/schema.js +51 -0
  90. package/dist/src/output/schema.js.map +1 -0
  91. package/dist/src/output/sheet-schema.d.ts +27 -0
  92. package/dist/src/output/sheet-schema.d.ts.map +1 -0
  93. package/dist/src/output/sheet-schema.js +114 -0
  94. package/dist/src/output/sheet-schema.js.map +1 -0
  95. package/dist/src/util/stdin.d.ts +7 -0
  96. package/dist/src/util/stdin.d.ts.map +1 -0
  97. package/dist/src/util/stdin.js +19 -0
  98. package/dist/src/util/stdin.js.map +1 -0
  99. package/package.json +55 -0
@@ -0,0 +1,142 @@
1
+ import { AxiError } from 'axi-sdk-js';
2
+ import { translateError } from '../errors.js';
3
+ import { renderListResponse, renderObject } from '../output/render.js';
4
+ import { computed, display, field } from '../output/schema.js';
5
+ import { countRecords } from '../output/sheet-schema.js';
6
+ import { Template } from 'gitsheets';
7
+ export const SHEETS_HELP = `usage: gitsheets-axi sheets [<subcommand>] [flags]
8
+ subcommands[2]:
9
+ list List sheets configured in this repository (default)
10
+ view <name> Show a single sheet's config + summary
11
+ examples:
12
+ gitsheets-axi sheets
13
+ gitsheets-axi sheets list
14
+ gitsheets-axi sheets view users
15
+ `;
16
+ export async function sheetsCommand(args, ctx) {
17
+ if (args.length === 1 && args[0] === '--help')
18
+ return SHEETS_HELP;
19
+ const sub = args[0] ?? 'list';
20
+ if (sub === 'list')
21
+ return sheetsList(ctx);
22
+ if (sub === 'view')
23
+ return sheetsView(args.slice(1), ctx);
24
+ if (sub === '--help')
25
+ return SHEETS_HELP;
26
+ throw new AxiError(`Unknown subcommand: ${sub}`, 'VALIDATION_ERROR', [
27
+ 'Subcommands: list, view',
28
+ ]);
29
+ }
30
+ async function sheetsList(ctx) {
31
+ const repo = await ctx.repo();
32
+ let sheets;
33
+ try {
34
+ sheets = await repo.openSheets();
35
+ }
36
+ catch (error) {
37
+ throw translateError(error);
38
+ }
39
+ const summaries = [];
40
+ for (const [name, sheet] of Object.entries(sheets)) {
41
+ let format = 'toml';
42
+ let root = '.';
43
+ let records = 0;
44
+ try {
45
+ const config = await sheet.readConfig();
46
+ format = config.format.type ?? 'toml';
47
+ root = config.root ?? '.';
48
+ records = await countRecords(sheet);
49
+ }
50
+ catch {
51
+ // skip count on malformed config
52
+ }
53
+ summaries.push({ name, format, records, root });
54
+ }
55
+ summaries.sort((a, b) => String(a['name']).localeCompare(String(b['name'])));
56
+ const help = summaries.length === 0
57
+ ? ['No sheets — add `.gitsheets/<name>.toml` to declare one']
58
+ : [
59
+ 'Run `gitsheets-axi sheets view <name>` to inspect a config',
60
+ 'Run `gitsheets-axi query <sheet>` to list records',
61
+ ];
62
+ return renderListResponse({
63
+ name: 'sheets',
64
+ items: summaries,
65
+ schema: [
66
+ field('name'),
67
+ display('format'),
68
+ computed('records', (item) => `${item['records']}`),
69
+ field('root'),
70
+ ],
71
+ suggestions: help,
72
+ emptyMessage: 'no sheets configured in this repository',
73
+ });
74
+ }
75
+ async function sheetsView(args, ctx) {
76
+ const name = args[0];
77
+ if (!name || name.startsWith('-')) {
78
+ throw new AxiError('sheets view requires a sheet name', 'VALIDATION_ERROR', [
79
+ 'Run `gitsheets-axi sheets view <name>`',
80
+ ]);
81
+ }
82
+ const repo = await ctx.repo();
83
+ let sheet;
84
+ try {
85
+ sheet = await repo.openSheet(name);
86
+ }
87
+ catch (error) {
88
+ throw translateError(error);
89
+ }
90
+ let config;
91
+ try {
92
+ config = await sheet.readConfig();
93
+ }
94
+ catch (error) {
95
+ throw translateError(error);
96
+ }
97
+ const template = Template.fromString(config.path);
98
+ const pathFields = template.getFieldNames();
99
+ const schemaProps = schemaPropertyList(config);
100
+ const records = await countRecords(sheet);
101
+ const output = {
102
+ sheet: {
103
+ name,
104
+ root: config.root ?? '.',
105
+ format: config.format.type ?? 'toml',
106
+ path: config.path,
107
+ records,
108
+ path_fields: pathFields.length > 0 ? pathFields.join(', ') : '(none)',
109
+ },
110
+ };
111
+ if (config.format.body) {
112
+ output['sheet']['body_field'] = config.format.body;
113
+ }
114
+ if (schemaProps.length > 0) {
115
+ output['schema'] = renderSchemaProperties(schemaProps);
116
+ }
117
+ output['help'] = [
118
+ `Run \`gitsheets-axi query ${name}\` to list records`,
119
+ `Run \`gitsheets-axi read ${name} <path>\` to view one record`,
120
+ ];
121
+ return renderObject(output);
122
+ }
123
+ function schemaPropertyList(config) {
124
+ const schema = config.schema;
125
+ if (!schema || typeof schema !== 'object')
126
+ return [];
127
+ const props = schema['properties'];
128
+ if (!props || typeof props !== 'object')
129
+ return [];
130
+ return Object.entries(props);
131
+ }
132
+ function renderSchemaProperties(props) {
133
+ // Flat name → "type [required]" map for token-efficient display.
134
+ const out = {};
135
+ for (const [name, schema] of props) {
136
+ const type = String(schema['type'] ?? 'any');
137
+ const format = schema['format'] ? ` (${String(schema['format'])})` : '';
138
+ out[name] = `${type}${format}`;
139
+ }
140
+ return out;
141
+ }
142
+ //# sourceMappingURL=sheets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheets.js","sourceRoot":"","sources":["../../../src/commands/sheets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { GitsheetsContext } from '../context.js';
2
+ export declare const UPSERT_HELP = "usage: gitsheets-axi upsert <sheet> [--data <json>] [--allow-missing-body] [--prefix p] [--message m]\nflags[4]:\n --data <json> Record JSON inline. If omitted, reads stdin.\n --allow-missing-body Content-typed sheets only \u2014 permit upsert without body field\n --prefix <p> Tenant sub-tree scope\n --message <m> Commit message (default: \"<sheet> upsert <path>\")\nexamples:\n gitsheets-axi upsert users --data '{\"slug\":\"jane\",\"email\":\"jane@x.org\"}'\n echo '{\"slug\":\"jane\",\"email\":\"jane@x.org\"}' | gitsheets-axi upsert users\nidempotency:\n Compares the canonical bytes the upsert would write against the\n existing blob at the rendered path. If identical, exits 0 with\n result: \"no-op\" and no commit is produced.\n";
3
+ export declare function upsertCommand(args: string[], ctx: GitsheetsContext): Promise<string>;
4
+ //# sourceMappingURL=upsert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/commands/upsert.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKtD,eAAO,MAAM,WAAW,swBAavB,CAAC;AA4DF,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,CAAC,CAqFjB"}
@@ -0,0 +1,137 @@
1
+ import { AxiError } from 'axi-sdk-js';
2
+ import { translateError } from '../errors.js';
3
+ import { renderObject } from '../output/render.js';
4
+ import { readStdin } from '../util/stdin.js';
5
+ export const UPSERT_HELP = `usage: gitsheets-axi upsert <sheet> [--data <json>] [--allow-missing-body] [--prefix p] [--message m]
6
+ flags[4]:
7
+ --data <json> Record JSON inline. If omitted, reads stdin.
8
+ --allow-missing-body Content-typed sheets only — permit upsert without body field
9
+ --prefix <p> Tenant sub-tree scope
10
+ --message <m> Commit message (default: "<sheet> upsert <path>")
11
+ examples:
12
+ gitsheets-axi upsert users --data '{"slug":"jane","email":"jane@x.org"}'
13
+ echo '{"slug":"jane","email":"jane@x.org"}' | gitsheets-axi upsert users
14
+ idempotency:
15
+ Compares the canonical bytes the upsert would write against the
16
+ existing blob at the rendered path. If identical, exits 0 with
17
+ result: "no-op" and no commit is produced.
18
+ `;
19
+ function parseUpsertFlags(args) {
20
+ const flags = {
21
+ sheet: '',
22
+ data: undefined,
23
+ allowMissingBody: false,
24
+ prefix: undefined,
25
+ message: undefined,
26
+ };
27
+ const positional = [];
28
+ for (let i = 0; i < args.length; i++) {
29
+ const arg = args[i];
30
+ if (arg === undefined)
31
+ continue;
32
+ const next = args[i + 1];
33
+ switch (arg) {
34
+ case '--data':
35
+ if (!next)
36
+ throw new AxiError('--data expects a JSON string', 'VALIDATION_ERROR');
37
+ flags.data = next;
38
+ i++;
39
+ break;
40
+ case '--allow-missing-body':
41
+ flags.allowMissingBody = true;
42
+ break;
43
+ case '--prefix':
44
+ if (!next)
45
+ throw new AxiError('--prefix expects a path', 'VALIDATION_ERROR');
46
+ flags.prefix = next;
47
+ i++;
48
+ break;
49
+ case '--message':
50
+ if (!next)
51
+ throw new AxiError('--message expects a string', 'VALIDATION_ERROR');
52
+ flags.message = next;
53
+ i++;
54
+ break;
55
+ default:
56
+ if (arg.startsWith('-')) {
57
+ throw new AxiError(`Unknown flag: ${arg}`, 'VALIDATION_ERROR', [
58
+ 'Run `gitsheets-axi upsert --help`',
59
+ ]);
60
+ }
61
+ positional.push(arg);
62
+ }
63
+ }
64
+ if (positional.length !== 1) {
65
+ throw new AxiError('upsert requires <sheet>', 'VALIDATION_ERROR', [
66
+ 'Example: gitsheets-axi upsert users --data \'{"slug":"jane"}\'',
67
+ ]);
68
+ }
69
+ flags.sheet = positional[0];
70
+ return flags;
71
+ }
72
+ export async function upsertCommand(args, ctx) {
73
+ if (args.length === 0 || (args.length === 1 && args[0] === '--help')) {
74
+ return UPSERT_HELP;
75
+ }
76
+ const flags = parseUpsertFlags(args);
77
+ const recordJson = flags.data ?? (await readStdin());
78
+ if (!recordJson.trim()) {
79
+ throw new AxiError('upsert needs a record — pass --data <json> or pipe JSON on stdin', 'VALIDATION_ERROR', ['Example: gitsheets-axi upsert users --data \'{"slug":"jane"}\'']);
80
+ }
81
+ let record;
82
+ try {
83
+ record = JSON.parse(recordJson);
84
+ }
85
+ catch (error) {
86
+ throw new AxiError(`Could not parse record JSON: ${error instanceof Error ? error.message : String(error)}`, 'INVALID_JSON', ['Ensure the input is a valid JSON object']);
87
+ }
88
+ if (!record || typeof record !== 'object' || Array.isArray(record)) {
89
+ throw new AxiError('Record must be a JSON object', 'VALIDATION_ERROR');
90
+ }
91
+ const repo = await ctx.repo();
92
+ let sheet;
93
+ try {
94
+ sheet = await repo.openSheet(flags.sheet, flags.prefix !== undefined ? { prefix: flags.prefix } : {});
95
+ }
96
+ catch (error) {
97
+ throw translateError(error);
98
+ }
99
+ const upsertOpts = flags.allowMissingBody ? { allowMissingBody: true } : {};
100
+ // Pre-flight idempotency check.
101
+ let willResult;
102
+ try {
103
+ willResult = await sheet.willChange(record, upsertOpts);
104
+ }
105
+ catch (error) {
106
+ throw translateError(error);
107
+ }
108
+ if (!willResult.changed) {
109
+ return renderObject({
110
+ result: 'no-op',
111
+ sheet: flags.sheet,
112
+ path: willResult.path,
113
+ hash: willResult.currentBlobHash ?? '',
114
+ });
115
+ }
116
+ // Carry through. willChange validated already; this re-validates inside
117
+ // upsert (cheap, idempotent at the validate layer). Future optimization
118
+ // could expose a "skip validation" path keyed off willChange's result.
119
+ const commitMessage = flags.message ?? `${flags.sheet} upsert ${willResult.path}`;
120
+ try {
121
+ const result = await repo.transact({ message: commitMessage }, async (tx) => {
122
+ const txSheet = tx.sheet(flags.sheet, flags.prefix !== undefined ? { prefix: flags.prefix } : {});
123
+ return txSheet.upsert(record, upsertOpts);
124
+ });
125
+ return renderObject({
126
+ result: 'committed',
127
+ sheet: flags.sheet,
128
+ path: result.value.path,
129
+ hash: result.value.blob.hash,
130
+ commit: result.commitHash,
131
+ });
132
+ }
133
+ catch (error) {
134
+ throw translateError(error);
135
+ }
136
+ }
137
+ //# sourceMappingURL=upsert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upsert.js","sourceRoot":"","sources":["../../../src/commands/upsert.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type Repository } from 'gitsheets';
2
+ /**
3
+ * Lazy gitsheets repo resolver. Opens the repo when a command actually needs
4
+ * it. Commands that operate without a repo (currently: none — even `home`
5
+ * shows the repo) call `requireRepo()` to surface a structured error when
6
+ * the cwd isn't inside a git repo.
7
+ */
8
+ export interface GitsheetsContext {
9
+ repo(): Promise<Repository>;
10
+ /**
11
+ * Returns `null` rather than throwing when the cwd isn't inside a git repo —
12
+ * `home` uses this to render a "no repo here" message instead of erroring.
13
+ */
14
+ tryRepo(): Promise<Repository | null>;
15
+ }
16
+ export declare function createContext(): GitsheetsContext;
17
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5B;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CACvC;AAED,wBAAgB,aAAa,IAAI,gBAAgB,CAgDhD"}
@@ -0,0 +1,47 @@
1
+ import { AxiError } from 'axi-sdk-js';
2
+ import { openRepo } from 'gitsheets';
3
+ export function createContext() {
4
+ let cached;
5
+ let cachedError;
6
+ async function load() {
7
+ if (cached !== undefined)
8
+ return cached;
9
+ if (cachedError !== undefined)
10
+ throw cachedError;
11
+ try {
12
+ cached = await openRepo();
13
+ return cached;
14
+ }
15
+ catch (error) {
16
+ cached = null;
17
+ cachedError = error;
18
+ throw error;
19
+ }
20
+ }
21
+ return {
22
+ async repo() {
23
+ try {
24
+ const result = await load();
25
+ if (!result) {
26
+ throw new AxiError('Not inside a git repository.', 'NOT_A_REPOSITORY', ['Run this command from a directory inside a gitsheets-managed git repository.']);
27
+ }
28
+ return result;
29
+ }
30
+ catch (error) {
31
+ if (error instanceof AxiError)
32
+ throw error;
33
+ // openRepo throws when there's no git repo. Translate.
34
+ throw new AxiError('Not inside a git repository.', 'NOT_A_REPOSITORY', ['Run this command from a directory inside a gitsheets-managed git repository.']);
35
+ }
36
+ },
37
+ async tryRepo() {
38
+ try {
39
+ return await load();
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ },
45
+ };
46
+ }
47
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAmB,MAAM,WAAW,CAAC;AAiBtD,MAAM,UAAU,aAAa;IAC3B,IAAI,MAAqC,CAAC;IAC1C,IAAI,WAAoB,CAAC;IAEzB,KAAK,UAAU,IAAI;QACjB,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;QACxC,IAAI,WAAW,KAAK,SAAS;YAAE,MAAM,WAAW,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,QAAQ,EAAE,CAAC;YAC1B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,IAAI,CAAC;YACd,WAAW,GAAG,KAAK,CAAC;YACpB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,CAAC,IAAI;YACR,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,MAAM,IAAI,QAAQ,CAChB,8BAA8B,EAC9B,kBAAkB,EAClB,CAAC,8EAA8E,CAAC,CACjF,CAAC;gBACJ,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,QAAQ;oBAAE,MAAM,KAAK,CAAC;gBAC3C,uDAAuD;gBACvD,MAAM,IAAI,QAAQ,CAChB,8BAA8B,EAC9B,kBAAkB,EAClB,CAAC,8EAA8E,CAAC,CACjF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,KAAK,CAAC,OAAO;YACX,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,EAAE,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { AxiError } from 'axi-sdk-js';
2
+ /**
3
+ * Translate a thrown gitsheets error into an AxiError. Centralizes the
4
+ * error→AXI code map so individual commands can `try { ... } catch (e)
5
+ * { throw translateError(e); }` once.
6
+ *
7
+ * The library throws structured `GitsheetsError` subclasses with stable
8
+ * codes. We map each to an AxiError code that aligns with AXI conventions
9
+ * + add tailored next-step suggestions so agents see actionable hints
10
+ * rather than bare error messages.
11
+ */
12
+ export declare function translateError(error: unknown): AxiError;
13
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAatC;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAiDvD"}
@@ -0,0 +1,58 @@
1
+ import { AxiError } from 'axi-sdk-js';
2
+ import { ConfigError, GitsheetsError, IndexError, NotFoundError, PathTemplateError, RefError, TransactionError, ValidationError, } from 'gitsheets';
3
+ /**
4
+ * Translate a thrown gitsheets error into an AxiError. Centralizes the
5
+ * error→AXI code map so individual commands can `try { ... } catch (e)
6
+ * { throw translateError(e); }` once.
7
+ *
8
+ * The library throws structured `GitsheetsError` subclasses with stable
9
+ * codes. We map each to an AxiError code that aligns with AXI conventions
10
+ * + add tailored next-step suggestions so agents see actionable hints
11
+ * rather than bare error messages.
12
+ */
13
+ export function translateError(error) {
14
+ if (error instanceof AxiError)
15
+ return error;
16
+ if (error instanceof ValidationError) {
17
+ const issues = formatValidationIssues(error.issues);
18
+ return new AxiError(`Record failed validation: ${issues[0] ?? 'unknown issue'}`, 'VALIDATION_FAILED', issues.slice(1).length > 0 ? issues.slice(1) : []);
19
+ }
20
+ if (error instanceof NotFoundError) {
21
+ return new AxiError(error.message, 'NOT_FOUND', []);
22
+ }
23
+ if (error instanceof ConfigError) {
24
+ return new AxiError(error.message, 'CONFIG_INVALID', [
25
+ 'Inspect `.gitsheets/<sheet>.toml` — the sheet config is malformed or missing.',
26
+ ]);
27
+ }
28
+ if (error instanceof IndexError) {
29
+ return new AxiError(error.message, 'INDEX_CONFLICT', []);
30
+ }
31
+ if (error instanceof PathTemplateError) {
32
+ return new AxiError(error.message, 'PATH_TEMPLATE_ERROR', [
33
+ 'Check the sheet config\'s `path` template against the record fields.',
34
+ ]);
35
+ }
36
+ if (error instanceof RefError) {
37
+ return new AxiError(error.message, 'REF_ERROR', []);
38
+ }
39
+ if (error instanceof TransactionError) {
40
+ return new AxiError(error.message, 'TRANSACTION_ERROR', []);
41
+ }
42
+ if (error instanceof GitsheetsError) {
43
+ return new AxiError(error.message, error.code.toUpperCase(), []);
44
+ }
45
+ if (error instanceof Error) {
46
+ return new AxiError(error.message, 'UNKNOWN_ERROR', []);
47
+ }
48
+ return new AxiError(String(error), 'UNKNOWN_ERROR', []);
49
+ }
50
+ function formatValidationIssues(issues) {
51
+ if (!issues || issues.length === 0)
52
+ return ['(no issue details)'];
53
+ return issues.map((issue) => {
54
+ const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';
55
+ return `${path}: ${issue.message}`;
56
+ });
57
+ }
58
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './schema.js';
2
+ export * from './render.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/output/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './schema.js';
2
+ export * from './render.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/output/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { FieldDef } from './schema.js';
2
+ /**
3
+ * Render a list of items as a TOON table.
4
+ *
5
+ * Output:
6
+ * <name>[N]{col1,col2,col3}:
7
+ * val1,val2,val3
8
+ * val1,val2,val3
9
+ */
10
+ export declare function renderList(name: string, items: Array<Record<string, unknown>>, schema: FieldDef[]): string;
11
+ export declare function renderObject(value: Record<string, unknown>): string;
12
+ export declare function renderHelp(suggestions: string[]): string;
13
+ export declare function joinBlocks(...blocks: string[]): string;
14
+ /**
15
+ * Compose a list response with optional header, summary, items, and help.
16
+ * Empty results collapse to a scalar message under the list's field name —
17
+ * matches the AXI "definitive empty state" convention.
18
+ */
19
+ export declare function renderListResponse(options: {
20
+ header?: Record<string, unknown>;
21
+ name: string;
22
+ items: Array<Record<string, unknown>>;
23
+ schema: FieldDef[];
24
+ summary?: Record<string, unknown>;
25
+ suggestions?: string[];
26
+ emptyMessage?: string;
27
+ }): string;
28
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/output/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACrC,MAAM,EAAE,QAAQ,EAAE,GACjB,MAAM,CAKR;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEnE;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAGxD;AAED,wBAAgB,UAAU,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtC,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,MAAM,CAoBT"}
@@ -0,0 +1,49 @@
1
+ import { encode } from '@toon-format/toon';
2
+ /**
3
+ * Render a list of items as a TOON table.
4
+ *
5
+ * Output:
6
+ * <name>[N]{col1,col2,col3}:
7
+ * val1,val2,val3
8
+ * val1,val2,val3
9
+ */
10
+ export function renderList(name, items, schema) {
11
+ const projected = items.map((item) => Object.fromEntries(schema.map((f) => [f.name, f.extract(item) ?? ''])));
12
+ return encode({ [name]: projected });
13
+ }
14
+ export function renderObject(value) {
15
+ return encode(value);
16
+ }
17
+ export function renderHelp(suggestions) {
18
+ if (suggestions.length === 0)
19
+ return '';
20
+ return encode({ help: suggestions });
21
+ }
22
+ export function joinBlocks(...blocks) {
23
+ return blocks.filter((b) => b.length > 0).join('\n');
24
+ }
25
+ /**
26
+ * Compose a list response with optional header, summary, items, and help.
27
+ * Empty results collapse to a scalar message under the list's field name —
28
+ * matches the AXI "definitive empty state" convention.
29
+ */
30
+ export function renderListResponse(options) {
31
+ const blocks = [];
32
+ if (options.header)
33
+ blocks.push(renderObject(options.header));
34
+ if (options.summary)
35
+ blocks.push(renderObject(options.summary));
36
+ if (options.items.length === 0) {
37
+ blocks.push(renderObject({
38
+ [options.name]: options.emptyMessage ?? `0 ${options.name} found`,
39
+ }));
40
+ }
41
+ else {
42
+ blocks.push(renderList(options.name, options.items, options.schema));
43
+ }
44
+ if (options.suggestions?.length) {
45
+ blocks.push(renderHelp(options.suggestions));
46
+ }
47
+ return joinBlocks(...blocks);
48
+ }
49
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/output/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI3C;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CACxB,IAAY,EACZ,KAAqC,EACrC,MAAkB;IAElB,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACnC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CACvE,CAAC;IACF,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAA8B;IACzD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,WAAqB;IAC9C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,OAAO,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAG,MAAgB;IAC5C,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAQlC;IACC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,CAAC,MAAM;QAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9D,IAAI,OAAO,CAAC,OAAO;QAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAEhE,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CACT,YAAY,CAAC;YACX,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,IAAI,KAAK,OAAO,CAAC,IAAI,QAAQ;SAClE,CAAC,CACH,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Schema builders for TOON table rendering. Each FieldDef projects from a
3
+ * source object (a gitsheets record or library response shape) onto a named
4
+ * column in the output table. Modeled after the gws-axi pattern.
5
+ *
6
+ * Usage:
7
+ * const schema = [
8
+ * field('slug'),
9
+ * truncated('title', 60),
10
+ * computed('size', (r) => Buffer.byteLength(String(r.body ?? ''), 'utf-8')),
11
+ * ];
12
+ * renderList('records', items, schema);
13
+ */
14
+ export interface FieldDef {
15
+ name: string;
16
+ extract: (item: Record<string, unknown>) => unknown;
17
+ }
18
+ export declare function field(name: string): FieldDef;
19
+ export declare function computed(name: string, fn: (item: Record<string, unknown>) => unknown): FieldDef;
20
+ /**
21
+ * Truncate a string to `max` chars with ellipsis. Pass-through for non-strings.
22
+ */
23
+ export declare function truncated(name: string, max: number, alias?: string): FieldDef;
24
+ /**
25
+ * Coerce a value to its display string. Empty for null/undefined; otherwise
26
+ * `String(value)`. Useful when a column might hold numbers, dates, or strings.
27
+ */
28
+ export declare function display(name: string, alias?: string): FieldDef;
29
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/output/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;CACrD;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAE5C;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,GAC7C,QAAQ,CAEV;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAS7E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAU9D"}