@odoograph/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 (54) hide show
  1. package/README.md +118 -0
  2. package/dist/cache.d.ts +35 -0
  3. package/dist/cache.d.ts.map +1 -0
  4. package/dist/cache.js +108 -0
  5. package/dist/cache.js.map +1 -0
  6. package/dist/cache.test.d.ts +5 -0
  7. package/dist/cache.test.d.ts.map +1 -0
  8. package/dist/cache.test.js +54 -0
  9. package/dist/cache.test.js.map +1 -0
  10. package/dist/commands/gaps.d.ts +6 -0
  11. package/dist/commands/gaps.d.ts.map +1 -0
  12. package/dist/commands/gaps.js +87 -0
  13. package/dist/commands/gaps.js.map +1 -0
  14. package/dist/commands/graph.d.ts +6 -0
  15. package/dist/commands/graph.d.ts.map +1 -0
  16. package/dist/commands/graph.js +36 -0
  17. package/dist/commands/graph.js.map +1 -0
  18. package/dist/commands/lint.d.ts +6 -0
  19. package/dist/commands/lint.d.ts.map +1 -0
  20. package/dist/commands/lint.js +56 -0
  21. package/dist/commands/lint.js.map +1 -0
  22. package/dist/commands/parse.d.ts +6 -0
  23. package/dist/commands/parse.d.ts.map +1 -0
  24. package/dist/commands/parse.js +60 -0
  25. package/dist/commands/parse.js.map +1 -0
  26. package/dist/commands/workspace.d.ts +6 -0
  27. package/dist/commands/workspace.d.ts.map +1 -0
  28. package/dist/commands/workspace.js +113 -0
  29. package/dist/commands/workspace.js.map +1 -0
  30. package/dist/config.d.ts +36 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +104 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/config.test.d.ts +5 -0
  35. package/dist/config.test.d.ts.map +1 -0
  36. package/dist/config.test.js +76 -0
  37. package/dist/config.test.js.map +1 -0
  38. package/dist/index.d.ts +13 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +42 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/output.d.ts +27 -0
  43. package/dist/output.d.ts.map +1 -0
  44. package/dist/output.js +114 -0
  45. package/dist/output.js.map +1 -0
  46. package/dist/progress.d.ts +29 -0
  47. package/dist/progress.d.ts.map +1 -0
  48. package/dist/progress.js +65 -0
  49. package/dist/progress.js.map +1 -0
  50. package/dist/utils.d.ts +24 -0
  51. package/dist/utils.d.ts.map +1 -0
  52. package/dist/utils.js +104 -0
  53. package/dist/utils.js.map +1 -0
  54. package/package.json +53 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Terminal progress display
3
+ *
4
+ * Provides spinner and progress bar for long-running operations.
5
+ */
6
+ import ora from "ora";
7
+ /**
8
+ * Create a progress spinner
9
+ */
10
+ export function createProgress(initialText) {
11
+ const spinner = ora({
12
+ text: initialText,
13
+ spinner: "dots",
14
+ });
15
+ return {
16
+ start() {
17
+ spinner.start();
18
+ },
19
+ stop() {
20
+ spinner.stop();
21
+ },
22
+ succeed(text) {
23
+ spinner.succeed(text);
24
+ },
25
+ fail(text) {
26
+ spinner.fail(text);
27
+ },
28
+ get text() {
29
+ return spinner.text;
30
+ },
31
+ set text(value) {
32
+ spinner.text = value;
33
+ },
34
+ };
35
+ }
36
+ /**
37
+ * Format progress update for display
38
+ */
39
+ export function formatProgress(progress) {
40
+ switch (progress.type) {
41
+ case "scanning":
42
+ return `Scanning... found ${progress.found} files`;
43
+ case "parsing":
44
+ const pct = Math.round((progress.current / progress.total) * 100);
45
+ return `Parsing [${pct}%] ${progress.current}/${progress.total}: ${progress.file}`;
46
+ case "building":
47
+ return `Building: ${progress.phase}`;
48
+ case "rules":
49
+ const rulesPct = Math.round((progress.current / progress.total) * 100);
50
+ return `Running rules [${rulesPct}%] ${progress.current}/${progress.total}`;
51
+ case "complete":
52
+ return `Complete: ${progress.stats.modules} modules, ${progress.stats.models} models`;
53
+ default:
54
+ return "Processing...";
55
+ }
56
+ }
57
+ /**
58
+ * Create a progress handler that updates a spinner
59
+ */
60
+ export function createProgressHandler(spinner) {
61
+ return (progress) => {
62
+ spinner.text = formatProgress(progress);
63
+ };
64
+ }
65
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../src/progress.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,GAAiB,MAAM,KAAK,CAAC;AAcpC;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,MAAM,OAAO,GAAG,GAAG,CAAC;QAClB,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,MAAM;KAChB,CAAC,CAAC;IAEH,OAAO;QACL,KAAK;YACH,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QACD,IAAI;YACF,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;QACD,OAAO,CAAC,IAAa;YACnB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,IAAa;YAChB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,IAAI;YACN,OAAO,OAAO,CAAC,IAAI,CAAC;QACtB,CAAC;QACD,IAAI,IAAI,CAAC,KAAa;YACpB,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAkB;IAC/C,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,UAAU;YACb,OAAO,qBAAqB,QAAQ,CAAC,KAAK,QAAQ,CAAC;QAErD,KAAK,SAAS;YACZ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;YAClE,OAAO,YAAY,GAAG,MAAM,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAErF,KAAK,UAAU;YACb,OAAO,aAAa,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEvC,KAAK,OAAO;YACV,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;YACvE,OAAO,kBAAkB,QAAQ,MAAM,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAE9E,KAAK,UAAU;YACb,OAAO,aAAa,QAAQ,CAAC,KAAK,CAAC,OAAO,aAAa,QAAQ,CAAC,KAAK,CAAC,MAAM,SAAS,CAAC;QAExF;YACE,OAAO,eAAe,CAAC;IAC3B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAwB;IAExB,OAAO,CAAC,QAAkB,EAAE,EAAE;QAC5B,OAAO,CAAC,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Utility functions for the CLI
3
+ */
4
+ /**
5
+ * Walk a directory and return all lintable Odoo files
6
+ */
7
+ export declare function walkOdooFiles(dir: string): Promise<string[]>;
8
+ /**
9
+ * Check if a path is an Odoo module (has __manifest__.py or __openerp__.py)
10
+ */
11
+ export declare function isOdooModule(path: string): Promise<boolean>;
12
+ /**
13
+ * Find all Odoo modules in a directory (one level deep)
14
+ */
15
+ export declare function findOdooModules(addonsPath: string): Promise<string[]>;
16
+ /**
17
+ * Format bytes as human-readable string
18
+ */
19
+ export declare function formatBytes(bytes: number): string;
20
+ /**
21
+ * Format duration in milliseconds as human-readable string
22
+ */
23
+ export declare function formatDuration(ms: number): string;
24
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwBH;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBlE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOjE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmB3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAMjD"}
package/dist/utils.js ADDED
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Utility functions for the CLI
3
+ */
4
+ import { readdir } from "fs/promises";
5
+ import { join, extname } from "path";
6
+ /**
7
+ * File extensions that are lintable
8
+ */
9
+ const LINTABLE_EXTENSIONS = new Set([".py", ".xml", ".js"]);
10
+ /**
11
+ * Directories to skip when walking
12
+ */
13
+ const SKIP_DIRS = new Set([
14
+ "node_modules",
15
+ "__pycache__",
16
+ ".git",
17
+ ".hg",
18
+ ".svn",
19
+ "static",
20
+ "lib",
21
+ "vendor",
22
+ ]);
23
+ /**
24
+ * Walk a directory and return all lintable Odoo files
25
+ */
26
+ export async function walkOdooFiles(dir) {
27
+ const files = [];
28
+ async function walk(currentDir) {
29
+ const entries = await readdir(currentDir, { withFileTypes: true });
30
+ for (const entry of entries) {
31
+ const fullPath = join(currentDir, entry.name);
32
+ if (entry.isDirectory()) {
33
+ // Skip certain directories
34
+ if (!SKIP_DIRS.has(entry.name)) {
35
+ await walk(fullPath);
36
+ }
37
+ }
38
+ else if (entry.isFile()) {
39
+ const ext = extname(entry.name).toLowerCase();
40
+ if (LINTABLE_EXTENSIONS.has(ext)) {
41
+ files.push(fullPath);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ await walk(dir);
47
+ return files;
48
+ }
49
+ /**
50
+ * Check if a path is an Odoo module (has __manifest__.py or __openerp__.py)
51
+ */
52
+ export async function isOdooModule(path) {
53
+ try {
54
+ const entries = await readdir(path);
55
+ return entries.includes("__manifest__.py") || entries.includes("__openerp__.py");
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ /**
62
+ * Find all Odoo modules in a directory (one level deep)
63
+ */
64
+ export async function findOdooModules(addonsPath) {
65
+ const modules = [];
66
+ try {
67
+ const entries = await readdir(addonsPath, { withFileTypes: true });
68
+ for (const entry of entries) {
69
+ if (entry.isDirectory()) {
70
+ const modulePath = join(addonsPath, entry.name);
71
+ if (await isOdooModule(modulePath)) {
72
+ modules.push(modulePath);
73
+ }
74
+ }
75
+ }
76
+ }
77
+ catch {
78
+ // Directory doesn't exist or can't be read
79
+ }
80
+ return modules;
81
+ }
82
+ /**
83
+ * Format bytes as human-readable string
84
+ */
85
+ export function formatBytes(bytes) {
86
+ if (bytes < 1024)
87
+ return `${bytes} B`;
88
+ if (bytes < 1024 * 1024)
89
+ return `${(bytes / 1024).toFixed(1)} KB`;
90
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
91
+ }
92
+ /**
93
+ * Format duration in milliseconds as human-readable string
94
+ */
95
+ export function formatDuration(ms) {
96
+ if (ms < 1000)
97
+ return `${ms}ms`;
98
+ if (ms < 60000)
99
+ return `${(ms / 1000).toFixed(1)}s`;
100
+ const minutes = Math.floor(ms / 60000);
101
+ const seconds = Math.floor((ms % 60000) / 1000);
102
+ return `${minutes}m ${seconds}s`;
103
+ }
104
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@odoograph/cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI for Odoo module analysis - linting, gap detection, and workspace graph building",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "ograph": "./dist/index.js"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/odoograph/cli.git"
13
+ },
14
+ "homepage": "https://odoograph.com",
15
+ "bugs": {
16
+ "url": "https://github.com/odoograph/cli/issues"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "start": "node dist/index.js",
21
+ "dev": "tsc --watch",
22
+ "lint": "eslint src --ext ts",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest"
25
+ },
26
+ "keywords": [
27
+ "odoo",
28
+ "linting",
29
+ "analysis",
30
+ "cli",
31
+ "static-analysis"
32
+ ],
33
+ "author": "Solutions Unity Co.",
34
+ "license": "SEE LICENSE IN LICENSE",
35
+ "dependencies": {
36
+ "@odoograph/wasm": "*",
37
+ "commander": "^12.1.0",
38
+ "chalk": "^5.3.0",
39
+ "ora": "^8.1.1"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.0.0",
43
+ "typescript": "^5.7.0",
44
+ "vitest": "^2.1.0"
45
+ },
46
+ "engines": {
47
+ "node": ">=20.0.0"
48
+ },
49
+ "files": [
50
+ "dist"
51
+ ]
52
+ }
53
+