@marcfargas/odoo-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 (81) hide show
  1. package/dist/cli.d.ts +27 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +152 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/accounting.d.ts +16 -0
  6. package/dist/commands/accounting.d.ts.map +1 -0
  7. package/dist/commands/accounting.js +363 -0
  8. package/dist/commands/accounting.js.map +1 -0
  9. package/dist/commands/attendance.d.ts +14 -0
  10. package/dist/commands/attendance.d.ts.map +1 -0
  11. package/dist/commands/attendance.js +339 -0
  12. package/dist/commands/attendance.js.map +1 -0
  13. package/dist/commands/config.d.ts +12 -0
  14. package/dist/commands/config.d.ts.map +1 -0
  15. package/dist/commands/config.js +159 -0
  16. package/dist/commands/config.js.map +1 -0
  17. package/dist/commands/mail.d.ts +12 -0
  18. package/dist/commands/mail.d.ts.map +1 -0
  19. package/dist/commands/mail.js +236 -0
  20. package/dist/commands/mail.js.map +1 -0
  21. package/dist/commands/modules.d.ts +14 -0
  22. package/dist/commands/modules.d.ts.map +1 -0
  23. package/dist/commands/modules.js +351 -0
  24. package/dist/commands/modules.js.map +1 -0
  25. package/dist/commands/records.d.ts +15 -0
  26. package/dist/commands/records.d.ts.map +1 -0
  27. package/dist/commands/records.js +591 -0
  28. package/dist/commands/records.js.map +1 -0
  29. package/dist/commands/schema.d.ts +16 -0
  30. package/dist/commands/schema.d.ts.map +1 -0
  31. package/dist/commands/schema.js +381 -0
  32. package/dist/commands/schema.js.map +1 -0
  33. package/dist/commands/state.d.ts +14 -0
  34. package/dist/commands/state.d.ts.map +1 -0
  35. package/dist/commands/state.js +373 -0
  36. package/dist/commands/state.js.map +1 -0
  37. package/dist/commands/timesheets.d.ts +15 -0
  38. package/dist/commands/timesheets.d.ts.map +1 -0
  39. package/dist/commands/timesheets.js +453 -0
  40. package/dist/commands/timesheets.js.map +1 -0
  41. package/dist/commands/url.d.ts +12 -0
  42. package/dist/commands/url.d.ts.map +1 -0
  43. package/dist/commands/url.js +149 -0
  44. package/dist/commands/url.js.map +1 -0
  45. package/dist/help/extra-help.d.ts +18 -0
  46. package/dist/help/extra-help.d.ts.map +1 -0
  47. package/dist/help/extra-help.js +207 -0
  48. package/dist/help/extra-help.js.map +1 -0
  49. package/dist/middleware/auth.d.ts +29 -0
  50. package/dist/middleware/auth.d.ts.map +1 -0
  51. package/dist/middleware/auth.js +68 -0
  52. package/dist/middleware/auth.js.map +1 -0
  53. package/dist/middleware/common-params.d.ts +90 -0
  54. package/dist/middleware/common-params.d.ts.map +1 -0
  55. package/dist/middleware/common-params.js +169 -0
  56. package/dist/middleware/common-params.js.map +1 -0
  57. package/dist/middleware/safety.d.ts +30 -0
  58. package/dist/middleware/safety.d.ts.map +1 -0
  59. package/dist/middleware/safety.js +64 -0
  60. package/dist/middleware/safety.js.map +1 -0
  61. package/dist/output/errors.d.ts +69 -0
  62. package/dist/output/errors.d.ts.map +1 -0
  63. package/dist/output/errors.js +193 -0
  64. package/dist/output/errors.js.map +1 -0
  65. package/dist/output/formatter.d.ts +80 -0
  66. package/dist/output/formatter.d.ts.map +1 -0
  67. package/dist/output/formatter.js +285 -0
  68. package/dist/output/formatter.js.map +1 -0
  69. package/dist/output/stream-writer.d.ts +33 -0
  70. package/dist/output/stream-writer.d.ts.map +1 -0
  71. package/dist/output/stream-writer.js +74 -0
  72. package/dist/output/stream-writer.js.map +1 -0
  73. package/dist/parsing/domain-parser.d.ts +61 -0
  74. package/dist/parsing/domain-parser.d.ts.map +1 -0
  75. package/dist/parsing/domain-parser.js +427 -0
  76. package/dist/parsing/domain-parser.js.map +1 -0
  77. package/dist/parsing/json-arg.d.ts +48 -0
  78. package/dist/parsing/json-arg.d.ts.map +1 -0
  79. package/dist/parsing/json-arg.js +165 -0
  80. package/dist/parsing/json-arg.js.map +1 -0
  81. package/package.json +53 -0
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ /**
3
+ * Output formatter for odoo-cli.
4
+ *
5
+ * Formats: json | table | csv | ndjson
6
+ *
7
+ * Conventions:
8
+ * - stdout = data only (all formats write to stdout)
9
+ * - stderr = decorative messages, warnings (caller's responsibility)
10
+ * - Many2one fields [id, name]: expanded to two columns in table/csv
11
+ * - table warns above 5000 rows and suggests ndjson
12
+ * - ndjson: streams one JSON object per line
13
+ */
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.setNoColor = setNoColor;
19
+ exports.setQuiet = setQuiet;
20
+ exports.isQuiet = isQuiet;
21
+ exports.isNoColor = isNoColor;
22
+ exports.detectFormat = detectFormat;
23
+ exports.resolveFormat = resolveFormat;
24
+ exports.flattenRecord = flattenRecord;
25
+ exports.getColumns = getColumns;
26
+ exports.formatJson = formatJson;
27
+ exports.formatNdjson = formatNdjson;
28
+ exports.formatTable = formatTable;
29
+ exports.formatCsv = formatCsv;
30
+ exports.render = render;
31
+ exports.renderSingle = renderSingle;
32
+ exports.renderKeyValue = renderKeyValue;
33
+ exports.pagedSearchRead = pagedSearchRead;
34
+ const cli_table3_1 = __importDefault(require("cli-table3"));
35
+ const debug_1 = __importDefault(require("debug"));
36
+ const stream_writer_1 = require("./stream-writer");
37
+ const errors_1 = require("./errors");
38
+ const log = (0, debug_1.default)('odoo-cli:formatter');
39
+ // ── Global output flags ───────────────────────────────────────────────
40
+ let _noColor = false;
41
+ let _quiet = false;
42
+ /** Disable ANSI colors in table/CLI output. Called from cli.ts preAction hook. */
43
+ function setNoColor(v) {
44
+ _noColor = v;
45
+ }
46
+ /** Suppress stderr progress and warnings. Called from cli.ts preAction hook. */
47
+ function setQuiet(v) {
48
+ _quiet = v;
49
+ }
50
+ /** Whether quiet mode is active (used by other output modules). */
51
+ function isQuiet() {
52
+ return _quiet;
53
+ }
54
+ /** Whether no-color mode is active. */
55
+ function isNoColor() {
56
+ return _noColor || process.env.NO_COLOR !== undefined;
57
+ }
58
+ /**
59
+ * Detect the default output format.
60
+ * TTY → table, pipe → json.
61
+ */
62
+ function detectFormat() {
63
+ return process.stdout.isTTY ? 'table' : 'json';
64
+ }
65
+ /**
66
+ * Resolve the format from option string, falling back to auto-detect.
67
+ */
68
+ function resolveFormat(fmt) {
69
+ if (!fmt)
70
+ return detectFormat();
71
+ if (fmt === 'json' || fmt === 'table' || fmt === 'csv' || fmt === 'ndjson')
72
+ return fmt;
73
+ // invalid, fall back
74
+ return detectFormat();
75
+ }
76
+ // ── Many2one handling ─────────────────────────────────────────────────
77
+ /**
78
+ * Check if a value looks like a many2one tuple: [number, string] | false.
79
+ */
80
+ function isMany2one(value) {
81
+ if (value === false)
82
+ return true;
83
+ if (Array.isArray(value) && value.length === 2 && typeof value[0] === 'number')
84
+ return true;
85
+ return false;
86
+ }
87
+ /**
88
+ * Flatten many2one fields for table/csv output.
89
+ *
90
+ * Input record: { id: 1, partner_id: [7, "Marc"] }
91
+ * Output record: { id: 1, partner_id: 7, partner_id_name: "Marc" }
92
+ *
93
+ * For boolean false (no relation): partner_id → null, partner_id_name → ""
94
+ */
95
+ function flattenRecord(record) {
96
+ const out = {};
97
+ for (const [key, val] of Object.entries(record)) {
98
+ if (isMany2one(val)) {
99
+ if (val === false) {
100
+ out[key] = null;
101
+ out[`${key}_name`] = '';
102
+ }
103
+ else {
104
+ out[key] = val[0];
105
+ out[`${key}_name`] = val[1];
106
+ }
107
+ }
108
+ else {
109
+ out[key] = val;
110
+ }
111
+ }
112
+ return out;
113
+ }
114
+ /**
115
+ * Get column headers for a set of records, expanding many2one fields.
116
+ */
117
+ function getColumns(records) {
118
+ if (records.length === 0)
119
+ return [];
120
+ const first = records[0];
121
+ const cols = [];
122
+ for (const [key, val] of Object.entries(first)) {
123
+ if (isMany2one(val)) {
124
+ cols.push(key);
125
+ cols.push(`${key}_name`);
126
+ }
127
+ else {
128
+ cols.push(key);
129
+ }
130
+ }
131
+ return cols;
132
+ }
133
+ // ── Format renderers ─────────────────────────────────────────────────
134
+ /**
135
+ * Write JSON array to stdout.
136
+ */
137
+ async function formatJson(records) {
138
+ log('Formatting %d records as json', records.length);
139
+ await (0, stream_writer_1.writeStdout)(JSON.stringify(records, null, 2) + '\n');
140
+ }
141
+ /**
142
+ * Write ndjson to stdout — one JSON object per line.
143
+ */
144
+ async function formatNdjson(records) {
145
+ log('Formatting %d records as ndjson', records.length);
146
+ for (const record of records) {
147
+ await (0, stream_writer_1.writeStdout)(JSON.stringify(record) + '\n');
148
+ }
149
+ }
150
+ /**
151
+ * Write table to stdout.
152
+ * Warns at >5000 rows and suggests --format ndjson.
153
+ */
154
+ async function formatTable(records) {
155
+ log('Formatting %d records as table', records.length);
156
+ if (records.length === 0) {
157
+ process.stderr.write('(no records)\n');
158
+ return;
159
+ }
160
+ if (records.length > 5000) {
161
+ (0, errors_1.printWarning)(`${records.length} rows is large for table format — consider --format ndjson for streaming output`);
162
+ }
163
+ const flattened = records.map(flattenRecord);
164
+ const cols = getColumns(records);
165
+ const table = new cli_table3_1.default({
166
+ head: cols.map((c) => c.toUpperCase()),
167
+ style: { head: isNoColor() ? [] : ['cyan'] },
168
+ wordWrap: false,
169
+ });
170
+ for (const rec of flattened) {
171
+ table.push(cols.map((col) => formatCell(rec[col])));
172
+ }
173
+ await (0, stream_writer_1.writeStdout)(table.toString() + '\n');
174
+ }
175
+ /**
176
+ * Write CSV to stdout.
177
+ * Expands many2one fields to two columns.
178
+ */
179
+ async function formatCsv(records) {
180
+ log('Formatting %d records as csv', records.length);
181
+ if (records.length === 0)
182
+ return;
183
+ const cols = getColumns(records);
184
+ // Header
185
+ await (0, stream_writer_1.writeStdout)((0, stream_writer_1.toCsvRow)(cols) + '\n');
186
+ for (const record of records) {
187
+ const flat = flattenRecord(record);
188
+ await (0, stream_writer_1.writeStdout)((0, stream_writer_1.toCsvRow)(cols.map((c) => flat[c] ?? '')) + '\n');
189
+ }
190
+ }
191
+ /**
192
+ * Format a single cell value for table display.
193
+ */
194
+ function formatCell(value) {
195
+ if (value === null || value === undefined || value === false)
196
+ return '';
197
+ if (typeof value === 'boolean')
198
+ return value ? 'true' : 'false';
199
+ if (Array.isArray(value))
200
+ return JSON.stringify(value);
201
+ if (typeof value === 'object')
202
+ return JSON.stringify(value);
203
+ return String(value);
204
+ }
205
+ /**
206
+ * Master render function — routes to the appropriate formatter.
207
+ */
208
+ async function render(records, format) {
209
+ switch (format) {
210
+ case 'json':
211
+ return formatJson(records);
212
+ case 'ndjson':
213
+ return formatNdjson(records);
214
+ case 'csv':
215
+ return formatCsv(records);
216
+ case 'table':
217
+ default:
218
+ return formatTable(records);
219
+ }
220
+ }
221
+ /**
222
+ * Render a single record (e.g., `records get`).
223
+ * JSON outputs an object (not array). Table shows key/value pairs.
224
+ */
225
+ async function renderSingle(record, format) {
226
+ if (format === 'json') {
227
+ await (0, stream_writer_1.writeStdout)(JSON.stringify(record, null, 2) + '\n');
228
+ return;
229
+ }
230
+ if (format === 'ndjson') {
231
+ await (0, stream_writer_1.writeStdout)(JSON.stringify(record) + '\n');
232
+ return;
233
+ }
234
+ if (format === 'csv') {
235
+ // Single record as CSV
236
+ await formatCsv([record]);
237
+ return;
238
+ }
239
+ // table: key/value layout
240
+ const flat = flattenRecord(record);
241
+ const table = new cli_table3_1.default({
242
+ style: { head: ['cyan'] },
243
+ });
244
+ for (const [key, val] of Object.entries(flat)) {
245
+ table.push({ [key]: formatCell(val) });
246
+ }
247
+ await (0, stream_writer_1.writeStdout)(table.toString() + '\n');
248
+ }
249
+ /**
250
+ * Render a simple key/value config-style object (for `config show`).
251
+ */
252
+ async function renderKeyValue(data, format) {
253
+ if (format === 'json' || format === 'ndjson') {
254
+ await (0, stream_writer_1.writeStdout)(JSON.stringify(data, null, format === 'json' ? 2 : 0) + '\n');
255
+ return;
256
+ }
257
+ if (format === 'csv') {
258
+ await (0, stream_writer_1.writeStdout)((0, stream_writer_1.toCsvRow)(['key', 'value']) + '\n');
259
+ for (const [k, v] of Object.entries(data)) {
260
+ await (0, stream_writer_1.writeStdout)((0, stream_writer_1.toCsvRow)([k, v]) + '\n');
261
+ }
262
+ return;
263
+ }
264
+ // table
265
+ const table = new cli_table3_1.default({ style: { head: ['cyan'] } });
266
+ for (const [k, v] of Object.entries(data)) {
267
+ table.push({ [k]: v });
268
+ }
269
+ await (0, stream_writer_1.writeStdout)(table.toString() + '\n');
270
+ }
271
+ /**
272
+ * Paged search-read generator — fetches from Odoo in pages.
273
+ * Used by `records search --all`.
274
+ */
275
+ async function* pagedSearchRead(searchFn, pageSize = 500) {
276
+ for (let offset = 0;; offset += pageSize) {
277
+ const rows = await searchFn(offset, pageSize);
278
+ if (rows.length === 0)
279
+ break;
280
+ yield rows;
281
+ if (rows.length < pageSize)
282
+ break;
283
+ }
284
+ }
285
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Backpressure-safe incremental stdout writer.
3
+ *
4
+ * Used for streaming ndjson and csv output of large result sets
5
+ * without buffering everything in memory.
6
+ */
7
+ /**
8
+ * Write a string to stdout, handling backpressure.
9
+ *
10
+ * Returns a promise that resolves when the data has been flushed
11
+ * or the stream has drained.
12
+ */
13
+ export declare function writeStdout(data: string): Promise<void>;
14
+ /**
15
+ * Stream ndjson records — one JSON object per line.
16
+ * Memory-efficient for large result sets.
17
+ */
18
+ export declare function streamNdjson(records: Record<string, any>[]): Promise<void>;
19
+ /**
20
+ * Stream CSV rows incrementally.
21
+ * Caller is responsible for writing the header first.
22
+ */
23
+ export declare function streamCsvRows(rows: string[][], separator?: string): Promise<void>;
24
+ /**
25
+ * Escape a single CSV cell value.
26
+ * Wraps in quotes if the value contains comma, quote, or newline.
27
+ */
28
+ export declare function toCsvCell(value: unknown): string;
29
+ /**
30
+ * Format a row of values as a CSV line (no trailing newline).
31
+ */
32
+ export declare function toCsvRow(cells: unknown[], separator?: string): string;
33
+ //# sourceMappingURL=stream-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-writer.d.ts","sourceRoot":"","sources":["../../src/output/stream-writer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvD;AAgBD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhF;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,GAAE,MAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5F;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOhD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,CAE1E"}
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ /**
3
+ * Backpressure-safe incremental stdout writer.
4
+ *
5
+ * Used for streaming ndjson and csv output of large result sets
6
+ * without buffering everything in memory.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.writeStdout = writeStdout;
10
+ exports.streamNdjson = streamNdjson;
11
+ exports.streamCsvRows = streamCsvRows;
12
+ exports.toCsvCell = toCsvCell;
13
+ exports.toCsvRow = toCsvRow;
14
+ /**
15
+ * Write a string to stdout, handling backpressure.
16
+ *
17
+ * Returns a promise that resolves when the data has been flushed
18
+ * or the stream has drained.
19
+ */
20
+ function writeStdout(data) {
21
+ return writeToStream(process.stdout, data);
22
+ }
23
+ function writeToStream(stream, data) {
24
+ return new Promise((resolve, reject) => {
25
+ const ok = stream.write(data, 'utf8', (err) => {
26
+ if (err)
27
+ reject(err);
28
+ });
29
+ if (ok) {
30
+ resolve();
31
+ }
32
+ else {
33
+ stream.once('drain', resolve);
34
+ stream.once('error', reject);
35
+ }
36
+ });
37
+ }
38
+ /**
39
+ * Stream ndjson records — one JSON object per line.
40
+ * Memory-efficient for large result sets.
41
+ */
42
+ async function streamNdjson(records) {
43
+ for (const record of records) {
44
+ await writeStdout(JSON.stringify(record) + '\n');
45
+ }
46
+ }
47
+ /**
48
+ * Stream CSV rows incrementally.
49
+ * Caller is responsible for writing the header first.
50
+ */
51
+ async function streamCsvRows(rows, separator = ',') {
52
+ for (const row of rows) {
53
+ await writeStdout(toCsvRow(row, separator) + '\n');
54
+ }
55
+ }
56
+ /**
57
+ * Escape a single CSV cell value.
58
+ * Wraps in quotes if the value contains comma, quote, or newline.
59
+ */
60
+ function toCsvCell(value) {
61
+ const str = value === null || value === undefined ? '' : String(value);
62
+ // Must quote if contains delimiter, quote, or newlines
63
+ if (str.includes(',') || str.includes('"') || str.includes('\n') || str.includes('\r')) {
64
+ return '"' + str.replace(/"/g, '""') + '"';
65
+ }
66
+ return str;
67
+ }
68
+ /**
69
+ * Format a row of values as a CSV line (no trailing newline).
70
+ */
71
+ function toCsvRow(cells, separator = ',') {
72
+ return cells.map(toCsvCell).join(separator);
73
+ }
74
+ //# sourceMappingURL=stream-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-writer.js","sourceRoot":"","sources":["../../src/output/stream-writer.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAUH,kCAEC;AAoBD,oCAIC;AAMD,sCAIC;AAMD,8BAOC;AAKD,4BAEC;AA9DD;;;;;GAKG;AACH,SAAgB,WAAW,CAAC,IAAY;IACtC,OAAO,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,aAAa,CAAC,MAAgB,EAAE,IAAY;IACnD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YAC5C,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QACH,IAAI,EAAE,EAAE,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,YAAY,CAAC,OAA8B;IAC/D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,aAAa,CAAC,IAAgB,EAAE,YAAoB,GAAG;IAC3E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,WAAW,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,SAAS,CAAC,KAAc;IACtC,MAAM,GAAG,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,uDAAuD;IACvD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvF,OAAO,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC;IAC7C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,KAAgB,EAAE,YAAoB,GAAG;IAChE,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Odoo domain parser — tokenizer + recursive descent parser.
3
+ *
4
+ * Parses the Python-literal subset used in Odoo domain expressions:
5
+ *
6
+ * '[("stage_id.name","=","Won"),("active","=",True)]'
7
+ * '["|",("name","ilike","acme"),("ref","ilike","acme")]'
8
+ *
9
+ * Converts Python literals to JSON-compatible values:
10
+ * True → true
11
+ * False → false
12
+ * None → null
13
+ * (a,b) → [a, b] (tuples become arrays)
14
+ *
15
+ * Three input paths:
16
+ * parseDomainArg() - from --domain flag (Python literal syntax)
17
+ * parseDomainJson() - from --domain-json flag (strict JSON)
18
+ * parseFilterArgs() - from --filter K=V pairs (simple equality)
19
+ */
20
+ export declare class DomainParseError extends Error {
21
+ readonly position?: number | undefined;
22
+ readonly input?: string | undefined;
23
+ constructor(message: string, position?: number | undefined, input?: string | undefined);
24
+ }
25
+ /**
26
+ * Parse an Odoo domain string (Python literal syntax) into a JSON array.
27
+ *
28
+ * @example
29
+ * parseDomainArg('[("name","ilike","acme"),("active","=",True)]')
30
+ * // → [["name","ilike","acme"],["active","=",true]]
31
+ */
32
+ export declare function parseDomainArg(input: string): any[];
33
+ /**
34
+ * Parse a strict JSON domain string.
35
+ *
36
+ * @example
37
+ * parseDomainJson('[["name","ilike","acme"]]')
38
+ */
39
+ export declare function parseDomainJson(input: string): any[];
40
+ /**
41
+ * Parse --filter K=V pairs into domain terms.
42
+ *
43
+ * Type inference:
44
+ * "true"/"false" → boolean
45
+ * all-digit string → integer
46
+ * otherwise → string
47
+ *
48
+ * @example
49
+ * parseFilterArgs(['active=true', 'state=sale'])
50
+ * // → [['active','=',true],['state','=','sale']]
51
+ */
52
+ export declare function parseFilterArgs(filters: string[]): any[][];
53
+ /**
54
+ * Combine a base domain with filter terms (AND).
55
+ */
56
+ export declare function combineDomains(baseDomain: any[], filterTerms: any[][]): any[];
57
+ /**
58
+ * Read domain from a file path. '-' reads from stdin.
59
+ */
60
+ export declare function readDomainFile(filePath: string): Promise<any[]>;
61
+ //# sourceMappingURL=domain-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-parser.d.ts","sourceRoot":"","sources":["../../src/parsing/domain-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,qBAAa,gBAAiB,SAAQ,KAAK;aAGvB,QAAQ,CAAC,EAAE,MAAM;aACjB,KAAK,CAAC,EAAE,MAAM;gBAF9B,OAAO,EAAE,MAAM,EACC,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,KAAK,CAAC,EAAE,MAAM,YAAA;CASjC;AAsRD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,CAwBnD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,CAmBpD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,EAAE,EAAE,CAiB1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,CAG7E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CA0BrE"}