@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,18 @@
1
+ /**
2
+ * --help-extra resolver and renderer.
3
+ *
4
+ * When --help-extra is passed, renders skill documentation for the command group.
5
+ *
6
+ * Strategy (hybrid):
7
+ * 1. Runtime primary: if skills/ directory is accessible, read and render full markdown.
8
+ * 2. Runtime fallback: use the built-in summary strings (works in compiled binaries).
9
+ *
10
+ * Skill map: command group → relevant skill files.
11
+ */
12
+ /**
13
+ * Show extended help for a command group.
14
+ *
15
+ * Writes to stdout (so it can be piped / paged).
16
+ */
17
+ export declare function showHelpExtra(group: string): Promise<void>;
18
+ //# sourceMappingURL=extra-help.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extra-help.d.ts","sourceRoot":"","sources":["../../src/help/extra-help.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA+JH;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ChE"}
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ /**
3
+ * --help-extra resolver and renderer.
4
+ *
5
+ * When --help-extra is passed, renders skill documentation for the command group.
6
+ *
7
+ * Strategy (hybrid):
8
+ * 1. Runtime primary: if skills/ directory is accessible, read and render full markdown.
9
+ * 2. Runtime fallback: use the built-in summary strings (works in compiled binaries).
10
+ *
11
+ * Skill map: command group → relevant skill files.
12
+ */
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.showHelpExtra = showHelpExtra;
18
+ const debug_1 = __importDefault(require("debug"));
19
+ const fs_1 = require("fs");
20
+ const path_1 = require("path");
21
+ const log = (0, debug_1.default)('odoo-cli:help');
22
+ const HELP_EXTRA_SKILLS = {
23
+ records: ['base/crud.md', 'base/search.md', 'base/domains.md', 'base/field-types.md'],
24
+ mail: ['mail/chatter.md'],
25
+ modules: ['base/modules.md'],
26
+ attendance: ['modules/timesheets.md'], // attendance is in hr module docs
27
+ timesheets: ['modules/timesheets.md'],
28
+ accounting: ['modules/accounting.md'],
29
+ url: ['base/connection.md'],
30
+ schema: ['base/introspection.md'],
31
+ state: [],
32
+ config: ['base/connection.md'],
33
+ };
34
+ const HELP_SUMMARIES = {
35
+ records: `
36
+ ## odoo records — Generic CRUD on any Odoo model
37
+
38
+ Search, get, create, update, and delete records on ANY Odoo model.
39
+
40
+ ### Examples
41
+
42
+ odoo records search crm.lead --fields id,name,stage_id --limit 20
43
+ odoo records get res.partner 42
44
+ odoo records create res.partner --data '{"name":"Acme Corp"}' --confirm
45
+ odoo records write crm.lead 42 --data '{"stage_id":5}' --confirm
46
+ odoo records delete crm.lead 42 --confirm
47
+
48
+ ### Domain syntax
49
+
50
+ --domain '[("active","=",True),("stage_id.name","=","Won")]'
51
+ --filter active=true --filter state=sale (simple AND equality)
52
+ --domain-file domain.json (from file)
53
+ --domain-file - (from stdin)
54
+
55
+ Run 'odoo schema fields <model>' to discover available fields.
56
+ `,
57
+ mail: `
58
+ ## odoo mail — Chatter messages and internal notes
59
+
60
+ Post messages on any record's chatter.
61
+
62
+ odoo mail note crm.lead 42 "Called customer" --confirm
63
+ odoo mail post sale.order 88 "Order shipped" --confirm
64
+ echo "Deployed: v1.2.3" | odoo mail note project.task 17 --message-file - --confirm
65
+
66
+ note: internal only (staff), post: public (notifies followers).
67
+ `,
68
+ modules: `
69
+ ## odoo modules — Install, upgrade, and list modules
70
+
71
+ odoo modules list --filter installed
72
+ odoo modules install hr_timesheet --confirm
73
+ odoo modules upgrade sale_management --confirm
74
+ odoo modules status sale_management (exits 3 if not found)
75
+
76
+ Scripting pattern:
77
+ if [ "$(odoo modules status sale)" = "installed" ]; then echo ready; fi
78
+ `,
79
+ timesheets: `
80
+ ## odoo timesheets — Time tracking
81
+
82
+ Timer workflow:
83
+ odoo timesheets start --task-id 42 --description "Feature work" --confirm
84
+ odoo timesheets stop --confirm
85
+ odoo timesheets running
86
+
87
+ Manual logging:
88
+ odoo timesheets log --task-id 42 --hours 1.5 --description "Review" --confirm
89
+ odoo timesheets log --task-id 42 --hours 1:30 --confirm
90
+ `,
91
+ attendance: `
92
+ ## odoo attendance — Clock in/out
93
+
94
+ odoo attendance clock-in --confirm
95
+ odoo attendance clock-out --confirm
96
+ odoo attendance status
97
+ odoo attendance list --from 2024-03-11 --to 2024-03-15
98
+ `,
99
+ accounting: `
100
+ ## odoo accounting — Read-only accounting queries (no mutations)
101
+
102
+ odoo accounting cash-accounts
103
+ odoo accounting cash-balance --as-of 2024-03-31
104
+ odoo accounting posted-moves --from 2024-01-01 --to 2024-03-31
105
+ odoo accounting trace-recon 42
106
+ odoo accounting days-to-pay 1042
107
+ `,
108
+ schema: `
109
+ ## odoo schema — Model and field introspection
110
+
111
+ odoo schema models --search sale
112
+ odoo schema fields crm.lead --type many2one
113
+ odoo schema describe res.partner
114
+ odoo schema codegen sale.order --out ./types/sale-order.ts
115
+ `,
116
+ url: `
117
+ ## odoo url — Generate record URLs
118
+
119
+ odoo url record crm.lead 42
120
+ odoo url portal sale.order 88
121
+ `,
122
+ config: `
123
+ ## odoo config — Connection management
124
+
125
+ odoo config check # verify credentials and show current user
126
+ odoo config show # show resolved config (password redacted)
127
+ `,
128
+ state: `
129
+ ## odoo state — State management ⚠ EXPERIMENTAL
130
+
131
+ Requires --experimental flag on all commands.
132
+
133
+ odoo state plan ./crm-stages.json --experimental
134
+ odoo state apply ./crm-stages.json --experimental --confirm
135
+
136
+ No extended docs available yet for this experimental feature.
137
+ `,
138
+ };
139
+ /**
140
+ * Resolve the skills directory relative to this package or the monorepo root.
141
+ */
142
+ function findSkillsDir() {
143
+ // Try: relative to this file (dev install in monorepo)
144
+ const candidates = [
145
+ // monorepo: packages/odoo-cli → ../../skills/odoo
146
+ (0, path_1.resolve)(__dirname, '..', '..', '..', '..', 'skills', 'odoo'),
147
+ // npm install: alongside package
148
+ (0, path_1.resolve)(__dirname, '..', 'skills', 'odoo'),
149
+ ];
150
+ for (const candidate of candidates) {
151
+ if ((0, fs_1.existsSync)(candidate)) {
152
+ log('Found skills dir: %s', candidate);
153
+ return candidate;
154
+ }
155
+ }
156
+ log('Skills directory not found, using built-in summaries');
157
+ return null;
158
+ }
159
+ /**
160
+ * Show extended help for a command group.
161
+ *
162
+ * Writes to stdout (so it can be piped / paged).
163
+ */
164
+ async function showHelpExtra(group) {
165
+ const skillFiles = HELP_EXTRA_SKILLS[group];
166
+ if (skillFiles === undefined) {
167
+ process.stdout.write(`No extended help available for '${group}'.\n`);
168
+ return;
169
+ }
170
+ if (skillFiles.length === 0) {
171
+ const summary = HELP_SUMMARIES[group];
172
+ if (summary) {
173
+ process.stdout.write(summary + '\n');
174
+ }
175
+ else {
176
+ process.stdout.write(`No extended help available for '${group}'.\n`);
177
+ }
178
+ return;
179
+ }
180
+ // Try to read full markdown files
181
+ const skillsDir = findSkillsDir();
182
+ if (skillsDir) {
183
+ let rendered = false;
184
+ for (const file of skillFiles) {
185
+ const fullPath = (0, path_1.join)(skillsDir, file);
186
+ if ((0, fs_1.existsSync)(fullPath)) {
187
+ try {
188
+ const content = (0, fs_1.readFileSync)(fullPath, 'utf8');
189
+ process.stdout.write(`\n${'─'.repeat(60)}\n`);
190
+ process.stdout.write(`# Skill: ${file}\n`);
191
+ process.stdout.write(`${'─'.repeat(60)}\n\n`);
192
+ process.stdout.write(content + '\n');
193
+ rendered = true;
194
+ }
195
+ catch (err) {
196
+ log('Could not read %s: %o', fullPath, err);
197
+ }
198
+ }
199
+ }
200
+ if (rendered)
201
+ return;
202
+ }
203
+ // Fallback: built-in summary
204
+ const summary = HELP_SUMMARIES[group] ?? `No extended help available for '${group}'.`;
205
+ process.stdout.write(summary + '\n');
206
+ }
207
+ //# sourceMappingURL=extra-help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extra-help.js","sourceRoot":"","sources":["../../src/help/extra-help.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Authentication middleware for odoo-cli.
3
+ *
4
+ * Creates an authenticated OdooClient from environment variables,
5
+ * optionally overriding with CLI flags (--url, --db, --user, --password).
6
+ *
7
+ * Priority: CLI flags > env vars
8
+ * CLI flags should be avoided in practice (shell history exposure).
9
+ */
10
+ import { OdooClient, type OdooClientConfig } from '@marcfargas/odoo-client';
11
+ export interface AuthFlags {
12
+ url?: string;
13
+ db?: string;
14
+ user?: string;
15
+ password?: string;
16
+ }
17
+ /**
18
+ * Build an OdooClientConfig from env vars + CLI flag overrides.
19
+ * Does NOT authenticate yet.
20
+ */
21
+ export declare function buildConfig(flags: AuthFlags): OdooClientConfig;
22
+ /**
23
+ * Create an authenticated OdooClient from env vars + CLI flag overrides.
24
+ *
25
+ * Throws CliAuthError if credentials are missing.
26
+ * Throws OdooAuthError if authentication fails (propagates from client).
27
+ */
28
+ export declare function createAuthClient(flags: AuthFlags): Promise<OdooClient>;
29
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAK5E,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,gBAAgB,CAyB9D;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAa5E"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ /**
3
+ * Authentication middleware for odoo-cli.
4
+ *
5
+ * Creates an authenticated OdooClient from environment variables,
6
+ * optionally overriding with CLI flags (--url, --db, --user, --password).
7
+ *
8
+ * Priority: CLI flags > env vars
9
+ * CLI flags should be avoided in practice (shell history exposure).
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.buildConfig = buildConfig;
16
+ exports.createAuthClient = createAuthClient;
17
+ const debug_1 = __importDefault(require("debug"));
18
+ const odoo_client_1 = require("@marcfargas/odoo-client");
19
+ const errors_1 = require("../output/errors");
20
+ const log = (0, debug_1.default)('odoo-cli:auth');
21
+ /**
22
+ * Build an OdooClientConfig from env vars + CLI flag overrides.
23
+ * Does NOT authenticate yet.
24
+ */
25
+ function buildConfig(flags) {
26
+ const url = flags.url || process.env['ODOO_URL'] || '';
27
+ const database = flags.db || process.env['ODOO_DB'] || process.env['ODOO_DATABASE'] || '';
28
+ const username = flags.user || process.env['ODOO_USERNAME'] || process.env['ODOO_USER'] || '';
29
+ const password = flags.password || process.env['ODOO_PASSWORD'] || '';
30
+ const missing = [];
31
+ if (!url)
32
+ missing.push('ODOO_URL');
33
+ if (!database)
34
+ missing.push('ODOO_DB');
35
+ if (!username)
36
+ missing.push('ODOO_USERNAME');
37
+ if (!password)
38
+ missing.push('ODOO_PASSWORD');
39
+ if (missing.length > 0) {
40
+ throw new errors_1.CliAuthError(`Missing Odoo credentials: ${missing.join(', ')}`, [
41
+ 'Set the following environment variables:',
42
+ ' ODOO_URL=https://mycompany.odoo.com',
43
+ ' ODOO_DB=mycompany',
44
+ ' ODOO_USERNAME=admin@example.com',
45
+ ' ODOO_PASSWORD=secret',
46
+ 'Or use --url, --db, --user, --password flags (avoid in CI — use env vars)',
47
+ ]);
48
+ }
49
+ log('Config: url=%s db=%s user=%s', url, database, username);
50
+ return { url, database, username, password };
51
+ }
52
+ /**
53
+ * Create an authenticated OdooClient from env vars + CLI flag overrides.
54
+ *
55
+ * Throws CliAuthError if credentials are missing.
56
+ * Throws OdooAuthError if authentication fails (propagates from client).
57
+ */
58
+ async function createAuthClient(flags) {
59
+ const config = buildConfig(flags);
60
+ const client = new odoo_client_1.OdooClient(config);
61
+ log('Authenticating as %s @ %s', config.username, config.url);
62
+ // Disable client-side safety guard — we handle confirmation ourselves
63
+ client.setSafetyContext(null);
64
+ await client.authenticate();
65
+ log('Authenticated successfully');
66
+ return client;
67
+ }
68
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;AAmBH,kCAyBC;AAQD,4CAaC;AA/DD,kDAA0B;AAC1B,yDAA4E;AAC5E,6CAAgD;AAEhD,MAAM,GAAG,GAAG,IAAA,eAAK,EAAC,eAAe,CAAC,CAAC;AASnC;;;GAGG;AACH,SAAgB,WAAW,CAAC,KAAgB;IAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IACvD,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IAC1F,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAC9F,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IAEtE,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACnC,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAE7C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,qBAAY,CAAC,6BAA6B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;YACxE,0CAA0C;YAC1C,uCAAuC;YACvC,qBAAqB;YACrB,mCAAmC;YACnC,wBAAwB;YACxB,2EAA2E;SAC5E,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,8BAA8B,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC7D,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAC/C,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,gBAAgB,CAAC,KAAgB;IACrD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,wBAAU,CAAC,MAAM,CAAC,CAAC;IAEtC,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAE9D,sEAAsE;IACtE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAE9B,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;IAC5B,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAElC,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Centralized parameter definitions for odoo-cli commands.
3
+ *
4
+ * ONE implementation for all shared flags:
5
+ * - --fields, --domain, --domain-json, --domain-file, --filter
6
+ * - --limit, --all, --offset, --page-size, --order
7
+ * - --format, --confirm, --dry-run, --context
8
+ * - Auth: --url, --db, --user, --password
9
+ *
10
+ * Commands compose these via Commander .addOption() calls.
11
+ * Never duplicate these definitions in individual command files.
12
+ */
13
+ import { Command, Option } from 'commander';
14
+ /** --url: Odoo base URL */
15
+ export declare const urlOption: () => Option;
16
+ /** --db: Database name */
17
+ export declare const dbOption: () => Option;
18
+ /** --user: Username */
19
+ export declare const userOption: () => Option;
20
+ /** --password: Password (use env var instead) */
21
+ export declare const passwordOption: () => Option;
22
+ /** All auth options as a group */
23
+ export declare function addAuthOptions(cmd: Command): Command;
24
+ /** --format: Output format */
25
+ export declare const formatOption: () => Option;
26
+ /** --fields: Comma-separated fields */
27
+ export declare const fieldsOption: () => Option;
28
+ /** --domain: Odoo domain filter */
29
+ export declare const domainOption: () => Option;
30
+ /** --domain-json: Strict JSON domain */
31
+ export declare const domainJsonOption: () => Option;
32
+ /** --domain-file: Read domain from file */
33
+ export declare const domainFileOption: () => Option;
34
+ /** --filter: Simple K=V equality shorthand — repeatable, values collected into array */
35
+ export declare const filterOption: () => Option;
36
+ /** --limit: Max records */
37
+ export declare const limitOption: (defaultVal?: number) => Option;
38
+ /** --all: Fetch all records (--limit 0 alias) */
39
+ export declare const allOption: () => Option;
40
+ /** --offset: Skip first N records */
41
+ export declare const offsetOption: () => Option;
42
+ /** --page-size: Paging chunk size */
43
+ export declare const pageSizeOption: () => Option;
44
+ /** --order: Sort order */
45
+ export declare const orderOption: () => Option;
46
+ /** --count: Print count instead of records */
47
+ export declare const countOption: () => Option;
48
+ /** --confirm: Required for WRITE/DESTRUCTIVE */
49
+ export declare const confirmOption: () => Option;
50
+ /** --dry-run: Preview without executing */
51
+ export declare const dryRunOption: () => Option;
52
+ /** --context: Extra Odoo context JSON */
53
+ export declare const contextOption: () => Option;
54
+ /** --no-color: Disable ANSI colors */
55
+ export declare const noColorOption: () => Option;
56
+ /** --quiet: Suppress stderr progress/warnings */
57
+ export declare const quietOption: () => Option;
58
+ /** --experimental: Required for experimental commands */
59
+ export declare const experimentalOption: () => Option;
60
+ /**
61
+ * Add search/filter options to a command.
62
+ * Used by: records search, records count, attendance list, timesheets list, etc.
63
+ */
64
+ export declare function addSearchOptions(cmd: Command): Command;
65
+ /**
66
+ * Add pagination options to a command.
67
+ */
68
+ export declare function addPaginationOptions(cmd: Command, defaultLimit?: number): Command;
69
+ /**
70
+ * Add output options (format + fields) to a command.
71
+ */
72
+ export declare function addOutputOptions(cmd: Command): Command;
73
+ /**
74
+ * Add write safety options to a command.
75
+ */
76
+ export declare function addWriteOptions(cmd: Command): Command;
77
+ /**
78
+ * Parse --fields value into an array of field names.
79
+ * Returns empty array if not specified (means "all fields").
80
+ */
81
+ export declare function parseFields(fields?: string): string[];
82
+ /**
83
+ * Resolve the effective limit.
84
+ * --all overrides --limit (sets to 0 = all).
85
+ */
86
+ export declare function resolveLimit(options: {
87
+ limit?: number;
88
+ all?: boolean;
89
+ }): number;
90
+ //# sourceMappingURL=common-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common-params.d.ts","sourceRoot":"","sources":["../../src/middleware/common-params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAI5C,2BAA2B;AAC3B,eAAO,MAAM,SAAS,cAA8D,CAAC;AAErF,0BAA0B;AAC1B,eAAO,MAAM,QAAQ,cAAgE,CAAC;AAEtF,uBAAuB;AACvB,eAAO,MAAM,UAAU,cAAqE,CAAC;AAE7F,iDAAiD;AACjD,eAAO,MAAM,cAAc,cACwE,CAAC;AAEpG,kCAAkC;AAClC,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAMpD;AAED,8BAA8B;AAC9B,eAAO,MAAM,YAAY,cAMrB,CAAC;AAEL,uCAAuC;AACvC,eAAO,MAAM,YAAY,cAC6C,CAAC;AAEvE,mCAAmC;AACnC,eAAO,MAAM,YAAY,cACuE,CAAC;AAEjG,wCAAwC;AACxC,eAAO,MAAM,gBAAgB,cACwD,CAAC;AAEtF,2CAA2C;AAC3C,eAAO,MAAM,gBAAgB,cACgD,CAAC;AAE9E,wFAAwF;AACxF,eAAO,MAAM,YAAY,cAGT,CAAC;AAEjB,2BAA2B;AAC3B,eAAO,MAAM,WAAW,GAAI,aAAY,MAAW,WAGb,CAAC;AAEvC,iDAAiD;AACjD,eAAO,MAAM,SAAS,cAAuE,CAAC;AAE9F,qCAAqC;AACrC,eAAO,MAAM,YAAY,cAGa,CAAC;AAEvC,qCAAqC;AACrC,eAAO,MAAM,cAAc,cAGW,CAAC;AAEvC,0BAA0B;AAC1B,eAAO,MAAM,WAAW,cAA0E,CAAC;AAEnG,8CAA8C;AAC9C,eAAO,MAAM,WAAW,cAAgE,CAAC;AAEzF,gDAAgD;AAChD,eAAO,MAAM,aAAa,cAC+D,CAAC;AAE1F,2CAA2C;AAC3C,eAAO,MAAM,YAAY,cACgE,CAAC;AAE1F,yCAAyC;AACzC,eAAO,MAAM,aAAa,cACiE,CAAC;AAE5F,sCAAsC;AACtC,eAAO,MAAM,aAAa,cAAwE,CAAC;AAEnG,iDAAiD;AACjD,eAAO,MAAM,WAAW,cAA2E,CAAC;AAEpG,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,cAC+D,CAAC;AAI/F;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAMtD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,GAAE,MAAW,GAAG,OAAO,CAOrF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAErD;AAID;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAMrD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAG/E"}
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ /**
3
+ * Centralized parameter definitions for odoo-cli commands.
4
+ *
5
+ * ONE implementation for all shared flags:
6
+ * - --fields, --domain, --domain-json, --domain-file, --filter
7
+ * - --limit, --all, --offset, --page-size, --order
8
+ * - --format, --confirm, --dry-run, --context
9
+ * - Auth: --url, --db, --user, --password
10
+ *
11
+ * Commands compose these via Commander .addOption() calls.
12
+ * Never duplicate these definitions in individual command files.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.experimentalOption = exports.quietOption = exports.noColorOption = exports.contextOption = exports.dryRunOption = exports.confirmOption = exports.countOption = exports.orderOption = exports.pageSizeOption = exports.offsetOption = exports.allOption = exports.limitOption = exports.filterOption = exports.domainFileOption = exports.domainJsonOption = exports.domainOption = exports.fieldsOption = exports.formatOption = exports.passwordOption = exports.userOption = exports.dbOption = exports.urlOption = void 0;
16
+ exports.addAuthOptions = addAuthOptions;
17
+ exports.addSearchOptions = addSearchOptions;
18
+ exports.addPaginationOptions = addPaginationOptions;
19
+ exports.addOutputOptions = addOutputOptions;
20
+ exports.addWriteOptions = addWriteOptions;
21
+ exports.parseFields = parseFields;
22
+ exports.resolveLimit = resolveLimit;
23
+ const commander_1 = require("commander");
24
+ // ── Option factories ─────────────────────────────────────────────────
25
+ /** --url: Odoo base URL */
26
+ const urlOption = () => new commander_1.Option('--url <url>', 'Odoo URL').env('ODOO_URL');
27
+ exports.urlOption = urlOption;
28
+ /** --db: Database name */
29
+ const dbOption = () => new commander_1.Option('--db <db>', 'Database name').env('ODOO_DB');
30
+ exports.dbOption = dbOption;
31
+ /** --user: Username */
32
+ const userOption = () => new commander_1.Option('--user <user>', 'Username').env('ODOO_USERNAME');
33
+ exports.userOption = userOption;
34
+ /** --password: Password (use env var instead) */
35
+ const passwordOption = () => new commander_1.Option('--password <password>', 'Password ⚠ use env instead').env('ODOO_PASSWORD').hideHelp();
36
+ exports.passwordOption = passwordOption;
37
+ /** All auth options as a group */
38
+ function addAuthOptions(cmd) {
39
+ return cmd
40
+ .addOption((0, exports.urlOption)())
41
+ .addOption((0, exports.dbOption)())
42
+ .addOption((0, exports.userOption)())
43
+ .addOption((0, exports.passwordOption)());
44
+ }
45
+ /** --format: Output format */
46
+ const formatOption = () => new commander_1.Option('--format <format>', 'Output format: json | table | csv | ndjson').choices([
47
+ 'json',
48
+ 'table',
49
+ 'csv',
50
+ 'ndjson',
51
+ ]);
52
+ exports.formatOption = formatOption;
53
+ /** --fields: Comma-separated fields */
54
+ const fieldsOption = () => new commander_1.Option('--fields <fields>', 'Comma-separated fields to include');
55
+ exports.fieldsOption = fieldsOption;
56
+ /** --domain: Odoo domain filter */
57
+ const domainOption = () => new commander_1.Option('--domain <domain>', 'Odoo domain filter (Python syntax): \'["name","=","Acme"]\'');
58
+ exports.domainOption = domainOption;
59
+ /** --domain-json: Strict JSON domain */
60
+ const domainJsonOption = () => new commander_1.Option('--domain-json <json>', 'Strict JSON domain: \'[["name","=","Acme"]]\'');
61
+ exports.domainJsonOption = domainJsonOption;
62
+ /** --domain-file: Read domain from file */
63
+ const domainFileOption = () => new commander_1.Option('--domain-file <file>', "Read domain from file ('-' for stdin)");
64
+ exports.domainFileOption = domainFileOption;
65
+ /** --filter: Simple K=V equality shorthand — repeatable, values collected into array */
66
+ const filterOption = () => new commander_1.Option('--filter <k=v>', "Simple equality filter (repeatable, AND'd)")
67
+ .argParser((val, prev = []) => [...prev, val])
68
+ .default([]);
69
+ exports.filterOption = filterOption;
70
+ /** --limit: Max records */
71
+ const limitOption = (defaultVal = 80) => new commander_1.Option('--limit <n>', `Max records (default: ${defaultVal}, 0 = all)`)
72
+ .default(defaultVal)
73
+ .argParser((v) => parseInt(v, 10));
74
+ exports.limitOption = limitOption;
75
+ /** --all: Fetch all records (--limit 0 alias) */
76
+ const allOption = () => new commander_1.Option('--all', 'Fetch all records (alias for --limit 0)');
77
+ exports.allOption = allOption;
78
+ /** --offset: Skip first N records */
79
+ const offsetOption = () => new commander_1.Option('--offset <n>', 'Skip first N records (default: 0)')
80
+ .default(0)
81
+ .argParser((v) => parseInt(v, 10));
82
+ exports.offsetOption = offsetOption;
83
+ /** --page-size: Paging chunk size */
84
+ const pageSizeOption = () => new commander_1.Option('--page-size <n>', 'Records per page when fetching all (default: 500)')
85
+ .default(500)
86
+ .argParser((v) => parseInt(v, 10));
87
+ exports.pageSizeOption = pageSizeOption;
88
+ /** --order: Sort order */
89
+ const orderOption = () => new commander_1.Option('--order <order>', 'Sort: "date_order desc,name asc"');
90
+ exports.orderOption = orderOption;
91
+ /** --count: Print count instead of records */
92
+ const countOption = () => new commander_1.Option('--count', 'Print count instead of records');
93
+ exports.countOption = countOption;
94
+ /** --confirm: Required for WRITE/DESTRUCTIVE */
95
+ const confirmOption = () => new commander_1.Option('--confirm', 'Confirm mutation (required for WRITE/DESTRUCTIVE operations)');
96
+ exports.confirmOption = confirmOption;
97
+ /** --dry-run: Preview without executing */
98
+ const dryRunOption = () => new commander_1.Option('--dry-run', 'Show RPC call without executing — does not require --confirm');
99
+ exports.dryRunOption = dryRunOption;
100
+ /** --context: Extra Odoo context JSON */
101
+ const contextOption = () => new commander_1.Option('--context <json>', 'Extra Odoo context: \'{"lang":"fr_FR","company_id":3}\'');
102
+ exports.contextOption = contextOption;
103
+ /** --no-color: Disable ANSI colors */
104
+ const noColorOption = () => new commander_1.Option('--no-color', 'Disable ANSI colors').env('NO_COLOR');
105
+ exports.noColorOption = noColorOption;
106
+ /** --quiet: Suppress stderr progress/warnings */
107
+ const quietOption = () => new commander_1.Option('-q, --quiet', 'Suppress stderr progress and warnings');
108
+ exports.quietOption = quietOption;
109
+ /** --experimental: Required for experimental commands */
110
+ const experimentalOption = () => new commander_1.Option('--experimental', 'Enable experimental features (required for `state` commands)');
111
+ exports.experimentalOption = experimentalOption;
112
+ // ── Option groups ────────────────────────────────────────────────────
113
+ /**
114
+ * Add search/filter options to a command.
115
+ * Used by: records search, records count, attendance list, timesheets list, etc.
116
+ */
117
+ function addSearchOptions(cmd) {
118
+ return cmd
119
+ .addOption((0, exports.domainOption)())
120
+ .addOption((0, exports.domainJsonOption)())
121
+ .addOption((0, exports.domainFileOption)())
122
+ .addOption((0, exports.filterOption)());
123
+ }
124
+ /**
125
+ * Add pagination options to a command.
126
+ */
127
+ function addPaginationOptions(cmd, defaultLimit = 80) {
128
+ return cmd
129
+ .addOption((0, exports.limitOption)(defaultLimit))
130
+ .addOption((0, exports.allOption)())
131
+ .addOption((0, exports.offsetOption)())
132
+ .addOption((0, exports.pageSizeOption)())
133
+ .addOption((0, exports.orderOption)());
134
+ }
135
+ /**
136
+ * Add output options (format + fields) to a command.
137
+ */
138
+ function addOutputOptions(cmd) {
139
+ return cmd.addOption((0, exports.formatOption)()).addOption((0, exports.fieldsOption)());
140
+ }
141
+ /**
142
+ * Add write safety options to a command.
143
+ */
144
+ function addWriteOptions(cmd) {
145
+ return cmd.addOption((0, exports.confirmOption)()).addOption((0, exports.dryRunOption)()).addOption((0, exports.contextOption)());
146
+ }
147
+ // ── Helpers ──────────────────────────────────────────────────────────
148
+ /**
149
+ * Parse --fields value into an array of field names.
150
+ * Returns empty array if not specified (means "all fields").
151
+ */
152
+ function parseFields(fields) {
153
+ if (!fields)
154
+ return [];
155
+ return fields
156
+ .split(',')
157
+ .map((f) => f.trim())
158
+ .filter(Boolean);
159
+ }
160
+ /**
161
+ * Resolve the effective limit.
162
+ * --all overrides --limit (sets to 0 = all).
163
+ */
164
+ function resolveLimit(options) {
165
+ if (options.all)
166
+ return 0;
167
+ return options.limit ?? 80;
168
+ }
169
+ //# sourceMappingURL=common-params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common-params.js","sourceRoot":"","sources":["../../src/middleware/common-params.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Safety enforcement middleware for odoo-cli.
3
+ *
4
+ * Every command has a safety level: READ | WRITE | DESTRUCTIVE.
5
+ *
6
+ * - READ: No requirements. Safe to run anywhere.
7
+ * - WRITE: Requires --confirm. Clear error if missing.
8
+ * - DESTRUCTIVE: Requires --confirm. Prints a DESTRUCTIVE warning.
9
+ *
10
+ * The CLI enforces safety at the command level, independently of the
11
+ * odoo-client safety guard (which uses a confirm callback). Here we
12
+ * use a simpler model: just check if the --confirm flag is present.
13
+ */
14
+ export type SafetyLevel = 'READ' | 'WRITE' | 'DESTRUCTIVE';
15
+ export interface SafetyOptions {
16
+ confirm?: boolean;
17
+ dryRun?: boolean;
18
+ }
19
+ /**
20
+ * Assert that a WRITE or DESTRUCTIVE operation has --confirm.
21
+ *
22
+ * Throws CliUsageError (exit 1) if --confirm is missing.
23
+ * In --dry-run mode, skips the check (we're not actually mutating).
24
+ */
25
+ export declare function requireConfirm(level: SafetyLevel, options: SafetyOptions, commandDescription: string): void;
26
+ /**
27
+ * Format a dry-run message to stderr showing what WOULD be called.
28
+ */
29
+ export declare function printDryRun(model: string, method: string, args: any[], kwargs?: Record<string, any>): void;
30
+ //# sourceMappingURL=safety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/middleware/safety.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,aAAa,EACtB,kBAAkB,EAAE,MAAM,GACzB,IAAI,CA0BN;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,GAAG,EAAE,EACX,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAC/B,IAAI,CAQN"}