zozul-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 (139) hide show
  1. package/.env.example +44 -0
  2. package/.github/workflows/publish.yml +26 -0
  3. package/DEVELOPMENT.md +288 -0
  4. package/LICENSE +201 -0
  5. package/README.md +178 -0
  6. package/dist/cli/commands.d.ts +3 -0
  7. package/dist/cli/commands.d.ts.map +1 -0
  8. package/dist/cli/commands.js +307 -0
  9. package/dist/cli/commands.js.map +1 -0
  10. package/dist/cli/format.d.ts +5 -0
  11. package/dist/cli/format.d.ts.map +1 -0
  12. package/dist/cli/format.js +115 -0
  13. package/dist/cli/format.js.map +1 -0
  14. package/dist/context/index.d.ts +8 -0
  15. package/dist/context/index.d.ts.map +1 -0
  16. package/dist/context/index.js +37 -0
  17. package/dist/context/index.js.map +1 -0
  18. package/dist/dashboard/html.d.ts +17 -0
  19. package/dist/dashboard/html.d.ts.map +1 -0
  20. package/dist/dashboard/html.js +79 -0
  21. package/dist/dashboard/html.js.map +1 -0
  22. package/dist/dashboard/index.html +1245 -0
  23. package/dist/hooks/config.d.ts +19 -0
  24. package/dist/hooks/config.d.ts.map +1 -0
  25. package/dist/hooks/config.js +106 -0
  26. package/dist/hooks/config.js.map +1 -0
  27. package/dist/hooks/git.d.ts +6 -0
  28. package/dist/hooks/git.d.ts.map +1 -0
  29. package/dist/hooks/git.js +73 -0
  30. package/dist/hooks/git.js.map +1 -0
  31. package/dist/hooks/index.d.ts +4 -0
  32. package/dist/hooks/index.d.ts.map +1 -0
  33. package/dist/hooks/index.js +3 -0
  34. package/dist/hooks/index.js.map +1 -0
  35. package/dist/hooks/server.d.ts +16 -0
  36. package/dist/hooks/server.d.ts.map +1 -0
  37. package/dist/hooks/server.js +349 -0
  38. package/dist/hooks/server.js.map +1 -0
  39. package/dist/index.d.ts +3 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +6 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/otel/config.d.ts +36 -0
  44. package/dist/otel/config.d.ts.map +1 -0
  45. package/dist/otel/config.js +109 -0
  46. package/dist/otel/config.js.map +1 -0
  47. package/dist/otel/index.d.ts +4 -0
  48. package/dist/otel/index.d.ts.map +1 -0
  49. package/dist/otel/index.js +3 -0
  50. package/dist/otel/index.js.map +1 -0
  51. package/dist/otel/receiver.d.ts +10 -0
  52. package/dist/otel/receiver.d.ts.map +1 -0
  53. package/dist/otel/receiver.js +155 -0
  54. package/dist/otel/receiver.js.map +1 -0
  55. package/dist/parser/index.d.ts +4 -0
  56. package/dist/parser/index.d.ts.map +1 -0
  57. package/dist/parser/index.js +3 -0
  58. package/dist/parser/index.js.map +1 -0
  59. package/dist/parser/ingest.d.ts +20 -0
  60. package/dist/parser/ingest.d.ts.map +1 -0
  61. package/dist/parser/ingest.js +98 -0
  62. package/dist/parser/ingest.js.map +1 -0
  63. package/dist/parser/jsonl.d.ts +14 -0
  64. package/dist/parser/jsonl.d.ts.map +1 -0
  65. package/dist/parser/jsonl.js +202 -0
  66. package/dist/parser/jsonl.js.map +1 -0
  67. package/dist/parser/types.d.ts +81 -0
  68. package/dist/parser/types.d.ts.map +1 -0
  69. package/dist/parser/types.js +9 -0
  70. package/dist/parser/types.js.map +1 -0
  71. package/dist/parser/watcher.d.ts +16 -0
  72. package/dist/parser/watcher.d.ts.map +1 -0
  73. package/dist/parser/watcher.js +103 -0
  74. package/dist/parser/watcher.js.map +1 -0
  75. package/dist/pricing/index.d.ts +2 -0
  76. package/dist/pricing/index.d.ts.map +1 -0
  77. package/dist/pricing/index.js +37 -0
  78. package/dist/pricing/index.js.map +1 -0
  79. package/dist/service/index.d.ts +31 -0
  80. package/dist/service/index.d.ts.map +1 -0
  81. package/dist/service/index.js +252 -0
  82. package/dist/service/index.js.map +1 -0
  83. package/dist/storage/db.d.ts +75 -0
  84. package/dist/storage/db.d.ts.map +1 -0
  85. package/dist/storage/db.js +117 -0
  86. package/dist/storage/db.js.map +1 -0
  87. package/dist/storage/index.d.ts +4 -0
  88. package/dist/storage/index.d.ts.map +1 -0
  89. package/dist/storage/index.js +3 -0
  90. package/dist/storage/index.js.map +1 -0
  91. package/dist/storage/repo.d.ts +162 -0
  92. package/dist/storage/repo.d.ts.map +1 -0
  93. package/dist/storage/repo.js +472 -0
  94. package/dist/storage/repo.js.map +1 -0
  95. package/dist/sync/client.d.ts +24 -0
  96. package/dist/sync/client.d.ts.map +1 -0
  97. package/dist/sync/client.js +41 -0
  98. package/dist/sync/client.js.map +1 -0
  99. package/dist/sync/index.d.ts +18 -0
  100. package/dist/sync/index.d.ts.map +1 -0
  101. package/dist/sync/index.js +135 -0
  102. package/dist/sync/index.js.map +1 -0
  103. package/dist/sync/sync.test.d.ts +2 -0
  104. package/dist/sync/sync.test.d.ts.map +1 -0
  105. package/dist/sync/sync.test.js +412 -0
  106. package/dist/sync/sync.test.js.map +1 -0
  107. package/dist/sync/transform.d.ts +80 -0
  108. package/dist/sync/transform.d.ts.map +1 -0
  109. package/dist/sync/transform.js +90 -0
  110. package/dist/sync/transform.js.map +1 -0
  111. package/package.json +50 -0
  112. package/src/cli/commands.ts +332 -0
  113. package/src/cli/format.ts +133 -0
  114. package/src/context/index.ts +42 -0
  115. package/src/dashboard/html.ts +97 -0
  116. package/src/dashboard/index.html +1245 -0
  117. package/src/hooks/config.ts +119 -0
  118. package/src/hooks/git.ts +77 -0
  119. package/src/hooks/index.ts +7 -0
  120. package/src/hooks/server.ts +397 -0
  121. package/src/index.ts +6 -0
  122. package/src/otel/config.ts +141 -0
  123. package/src/otel/index.ts +8 -0
  124. package/src/otel/receiver.ts +183 -0
  125. package/src/parser/index.ts +3 -0
  126. package/src/parser/ingest.ts +119 -0
  127. package/src/parser/jsonl.ts +241 -0
  128. package/src/parser/types.ts +89 -0
  129. package/src/parser/watcher.ts +116 -0
  130. package/src/pricing/index.ts +51 -0
  131. package/src/service/index.ts +272 -0
  132. package/src/storage/db.ts +198 -0
  133. package/src/storage/index.ts +3 -0
  134. package/src/storage/repo.ts +601 -0
  135. package/src/sync/client.ts +63 -0
  136. package/src/sync/index.ts +207 -0
  137. package/src/sync/sync.test.ts +447 -0
  138. package/src/sync/transform.ts +184 -0
  139. package/tsconfig.json +19 -0
@@ -0,0 +1,8 @@
1
+ export interface TaskContext {
2
+ active: string[];
3
+ set_at: string;
4
+ }
5
+ export declare function getActiveContext(): TaskContext | null;
6
+ export declare function setActiveContext(tasks: string[]): TaskContext;
7
+ export declare function clearActiveContext(): void;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,IAAI,WAAW,GAAG,IAAI,CAerD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,CAO7D;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC"}
@@ -0,0 +1,37 @@
1
+ import path from "node:path";
2
+ import os from "node:os";
3
+ import fs from "node:fs";
4
+ const CONTEXT_PATH = path.join(os.homedir(), ".zozul", "context.json");
5
+ export function getActiveContext() {
6
+ if (!fs.existsSync(CONTEXT_PATH))
7
+ return null;
8
+ try {
9
+ const data = JSON.parse(fs.readFileSync(CONTEXT_PATH, "utf-8"));
10
+ // Support legacy single-string format
11
+ if (typeof data.active === "string") {
12
+ return { active: [data.active], set_at: data.set_at ?? "" };
13
+ }
14
+ if (Array.isArray(data.active) && data.active.length > 0) {
15
+ return { active: data.active, set_at: data.set_at ?? "" };
16
+ }
17
+ return null;
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ export function setActiveContext(tasks) {
24
+ const tags = tasks.map(t => t.trim()).filter(Boolean);
25
+ if (tags.length === 0)
26
+ throw new Error("At least one tag is required");
27
+ const ctx = { active: tags, set_at: new Date().toISOString() };
28
+ fs.mkdirSync(path.dirname(CONTEXT_PATH), { recursive: true });
29
+ fs.writeFileSync(CONTEXT_PATH, JSON.stringify(ctx, null, 2) + "\n");
30
+ return ctx;
31
+ }
32
+ export function clearActiveContext() {
33
+ if (fs.existsSync(CONTEXT_PATH)) {
34
+ fs.unlinkSync(CONTEXT_PATH);
35
+ }
36
+ }
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;AAOvE,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,sCAAsC;QACtC,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC9D,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzD,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAe;IAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACvE,MAAM,GAAG,GAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IAC5E,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ /** Local-only dashboard (no remote toggle). */
2
+ export declare function dashboardHtml(): string;
3
+ /**
4
+ * Dashboard with a Local / Remote toggle.
5
+ * When remote config is provided, the user can switch between local SQLite
6
+ * and the remote backend API via a toggle in the header.
7
+ * `mode` sets the initial active source.
8
+ */
9
+ export declare function dashboardHtmlWithToggle(remote: {
10
+ apiUrl: string;
11
+ apiKey: string;
12
+ }, mode?: "local" | "remote"): string;
13
+ /**
14
+ * Remote-only dashboard (no local API available).
15
+ */
16
+ export declare function remoteDashboardHtml(apiUrl: string, apiKey: string): string;
17
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/dashboard/html.ts"],"names":[],"mappings":"AAUA,+CAA+C;AAC/C,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,GAAE,OAAO,GAAG,QAAkB,GAAG,MAAM,CAoE9H;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1E"}
@@ -0,0 +1,79 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ function rawHtml() {
6
+ return readFileSync(join(__dirname, "index.html"), "utf-8");
7
+ }
8
+ /** Local-only dashboard (no remote toggle). */
9
+ export function dashboardHtml() {
10
+ return rawHtml();
11
+ }
12
+ /**
13
+ * Dashboard with a Local / Remote toggle.
14
+ * When remote config is provided, the user can switch between local SQLite
15
+ * and the remote backend API via a toggle in the header.
16
+ * `mode` sets the initial active source.
17
+ */
18
+ export function dashboardHtmlWithToggle(remote, mode = "local") {
19
+ const baseUrl = remote.apiUrl.replace(/\/+$/, "") + "/api/v1";
20
+ let html = rawHtml();
21
+ const configScript = `
22
+ <script>
23
+ const ZOZUL_CONFIG = {
24
+ remote: { baseUrl: ${JSON.stringify(baseUrl)}, apiKey: ${JSON.stringify(remote.apiKey)} },
25
+ mode: ${JSON.stringify(mode)},
26
+ };
27
+ </script>`;
28
+ html = html.replace("<script>\nlet chartInstances", configScript + "\n<script>\nlet chartInstances");
29
+ // Replace fetchJson to route based on active mode
30
+ html = html.replace(`async function fetchJson(path) {\n const res = await fetch(path);\n if (!res.ok) throw new Error(res.status + ' ' + path);\n return res.json();\n}`, `async function fetchJson(path) {
31
+ if (ZOZUL_CONFIG && ZOZUL_CONFIG.mode === 'remote') {
32
+ const url = ZOZUL_CONFIG.remote.baseUrl + path.replace('/api/', '/');
33
+ const res = await fetch(url, { headers: { 'X-API-Key': ZOZUL_CONFIG.remote.apiKey } });
34
+ if (!res.ok) throw new Error(res.status + ' ' + url);
35
+ return res.json();
36
+ }
37
+ const res = await fetch(path);
38
+ if (!res.ok) throw new Error(res.status + ' ' + path);
39
+ return res.json();
40
+ }`);
41
+ // Inject toggle button into the header-right div
42
+ const toggleHtml = `
43
+ <div style="display:flex;border:1px solid var(--border);border-radius:6px;overflow:hidden;font-size:12px">
44
+ <button id="src-local" onclick="switchSource('local')"
45
+ style="padding:4px 12px;border:none;cursor:pointer;font-size:12px;font-family:inherit;transition:all 0.15s">Local</button>
46
+ <button id="src-remote" onclick="switchSource('remote')"
47
+ style="padding:4px 12px;border:none;cursor:pointer;font-size:12px;font-family:inherit;transition:all 0.15s">Remote</button>
48
+ </div>`;
49
+ html = html.replace('<div class="header-right">', '<div class="header-right">' + toggleHtml);
50
+ // Inject switchSource function and initial toggle state
51
+ const switchScript = `
52
+ function switchSource(mode) {
53
+ ZOZUL_CONFIG.mode = mode;
54
+ const local = document.getElementById('src-local');
55
+ const remote = document.getElementById('src-remote');
56
+ const activeStyle = 'background:var(--accent);color:#fff;';
57
+ const inactiveStyle = 'background:var(--surface);color:var(--text-dim);';
58
+ local.style.cssText += (mode === 'local' ? activeStyle : inactiveStyle);
59
+ remote.style.cssText += (mode === 'remote' ? activeStyle : inactiveStyle);
60
+ document.title = 'zozul — ' + (mode === 'local' ? 'Local' : 'Remote') + ' Dashboard';
61
+ loadDashboard();
62
+ }
63
+
64
+ // Set initial toggle state on load
65
+ document.addEventListener('DOMContentLoaded', () => switchSource(ZOZUL_CONFIG.mode));
66
+ `;
67
+ // Must target the top-level bootstrap call (last occurrence), not the one inside manualRefresh()
68
+ const bootstrapCall = "loadDashboard().then(scheduleAutoRefresh);";
69
+ const lastIdx = html.lastIndexOf(bootstrapCall);
70
+ html = html.slice(0, lastIdx) + switchScript + "\n" + bootstrapCall + html.slice(lastIdx + bootstrapCall.length);
71
+ return html;
72
+ }
73
+ /**
74
+ * Remote-only dashboard (no local API available).
75
+ */
76
+ export function remoteDashboardHtml(apiUrl, apiKey) {
77
+ return dashboardHtmlWithToggle({ apiUrl, apiKey }, "remote");
78
+ }
79
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/dashboard/html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,SAAS,OAAO;IACd,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,EAAE,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAA0C,EAAE,OAA2B,OAAO;IACpH,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC;IAC9D,IAAI,IAAI,GAAG,OAAO,EAAE,CAAC;IAErB,MAAM,YAAY,GAAG;;;uBAGA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;UAC9E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;;UAEpB,CAAC;IAET,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,8BAA8B,EAAE,YAAY,GAAG,gCAAgC,CAAC,CAAC;IAErG,kDAAkD;IAClD,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,uJAAuJ,EACvJ;;;;;;;;;;EAUF,CACC,CAAC;IAEF,iDAAiD;IACjD,MAAM,UAAU,GAAG;;;;;;WAMV,CAAC;IAEV,IAAI,GAAG,IAAI,CAAC,OAAO,CACjB,4BAA4B,EAC5B,4BAA4B,GAAG,UAAU,CAC1C,CAAC;IAEF,wDAAwD;IACxD,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;CAetB,CAAC;IAEA,iGAAiG;IACjG,MAAM,aAAa,GAAG,4CAA4C,CAAC;IACnE,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IAChD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,YAAY,GAAG,IAAI,GAAG,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAEjH,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,MAAc;IAChE,OAAO,uBAAuB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC/D,CAAC"}