@giwonn/claude-daily-review 0.2.3 → 0.3.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.
- package/.claude-plugin/marketplace.json +29 -0
- package/.github/workflows/publish.yml +24 -0
- package/.github/workflows/update-marketplace.yml +28 -0
- package/docs/superpowers/plans/2026-03-28-claude-daily-review-plan.md +2130 -0
- package/docs/superpowers/plans/2026-03-28-no-build-refactor-plan.md +1158 -0
- package/docs/superpowers/plans/2026-03-28-storage-adapter-refactor-plan.md +2207 -0
- package/docs/superpowers/specs/2026-03-28-claude-daily-review-design.md +582 -0
- package/docs/superpowers/specs/2026-03-28-no-build-refactor-design.md +333 -0
- package/docs/superpowers/specs/2026-03-28-storage-adapter-refactor-design.md +365 -0
- package/hooks/hooks.json +3 -2
- package/hooks/on-stop.mjs +24 -0
- package/hooks/run-hook.cmd +27 -0
- package/hooks/session-start-check +27 -0
- package/lib/config.mjs +122 -0
- package/lib/github-auth.mjs +44 -0
- package/lib/github-storage.mjs +81 -0
- package/lib/merge.mjs +51 -0
- package/lib/periods.mjs +82 -0
- package/lib/raw-logger.mjs +19 -0
- package/lib/storage-cli.mjs +48 -0
- package/lib/storage.mjs +63 -0
- package/lib/types.d.ts +64 -0
- package/lib/vault.mjs +43 -0
- package/package.json +3 -23
- package/prompts/session-end.md +5 -5
- package/prompts/session-start.md +5 -5
- package/dist/on-session-start-check.js +0 -56
- package/dist/on-session-start-check.js.map +0 -1
- package/dist/on-stop.js +0 -274
- package/dist/on-stop.js.map +0 -1
- package/dist/storage-cli.js +0 -267
- package/dist/storage-cli.js.map +0 -1
package/dist/storage-cli.js
DELETED
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
-
var __esm = (fn, res) => function __init() {
|
|
4
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
-
};
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
// src/core/github-storage.ts
|
|
12
|
-
var github_storage_exports = {};
|
|
13
|
-
__export(github_storage_exports, {
|
|
14
|
-
GitHubStorageAdapter: () => GitHubStorageAdapter
|
|
15
|
-
});
|
|
16
|
-
var GitHubStorageAdapter;
|
|
17
|
-
var init_github_storage = __esm({
|
|
18
|
-
"src/core/github-storage.ts"() {
|
|
19
|
-
"use strict";
|
|
20
|
-
GitHubStorageAdapter = class {
|
|
21
|
-
constructor(owner, repo, token, basePath) {
|
|
22
|
-
this.owner = owner;
|
|
23
|
-
this.repo = repo;
|
|
24
|
-
this.token = token;
|
|
25
|
-
this.basePath = basePath;
|
|
26
|
-
this.baseUrl = `https://api.github.com/repos/${owner}/${repo}/contents`;
|
|
27
|
-
this.headers = {
|
|
28
|
-
Authorization: `Bearer ${token}`,
|
|
29
|
-
Accept: "application/vnd.github.v3+json",
|
|
30
|
-
"Content-Type": "application/json"
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
baseUrl;
|
|
34
|
-
headers;
|
|
35
|
-
getUrl(path) {
|
|
36
|
-
return `${this.baseUrl}/${this.basePath}/${path}`;
|
|
37
|
-
}
|
|
38
|
-
async getSha(path) {
|
|
39
|
-
const res = await fetch(this.getUrl(path), { method: "GET", headers: this.headers });
|
|
40
|
-
if (res.status === 404) return null;
|
|
41
|
-
const data = await res.json();
|
|
42
|
-
return data.sha || null;
|
|
43
|
-
}
|
|
44
|
-
async read(path) {
|
|
45
|
-
const res = await fetch(this.getUrl(path), { method: "GET", headers: this.headers });
|
|
46
|
-
if (res.status === 404) return null;
|
|
47
|
-
const data = await res.json();
|
|
48
|
-
const content = data.content;
|
|
49
|
-
return Buffer.from(content, "base64").toString("utf-8");
|
|
50
|
-
}
|
|
51
|
-
async write(path, content) {
|
|
52
|
-
const sha = await this.getSha(path);
|
|
53
|
-
const body = {
|
|
54
|
-
message: `update ${path}`,
|
|
55
|
-
content: Buffer.from(content).toString("base64")
|
|
56
|
-
};
|
|
57
|
-
if (sha) body.sha = sha;
|
|
58
|
-
const res = await fetch(this.getUrl(path), {
|
|
59
|
-
method: "PUT",
|
|
60
|
-
headers: this.headers,
|
|
61
|
-
body: JSON.stringify(body)
|
|
62
|
-
});
|
|
63
|
-
if (!res.ok && res.status === 409) {
|
|
64
|
-
const freshSha = await this.getSha(path);
|
|
65
|
-
if (freshSha) body.sha = freshSha;
|
|
66
|
-
await fetch(this.getUrl(path), {
|
|
67
|
-
method: "PUT",
|
|
68
|
-
headers: this.headers,
|
|
69
|
-
body: JSON.stringify(body)
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
async append(path, content) {
|
|
74
|
-
const existing = await this.read(path);
|
|
75
|
-
const newContent = existing ? existing + content : content;
|
|
76
|
-
await this.write(path, newContent);
|
|
77
|
-
}
|
|
78
|
-
async exists(path) {
|
|
79
|
-
const res = await fetch(this.getUrl(path), { method: "GET", headers: this.headers });
|
|
80
|
-
return res.status !== 404;
|
|
81
|
-
}
|
|
82
|
-
async list(dir) {
|
|
83
|
-
const res = await fetch(this.getUrl(dir), { method: "GET", headers: this.headers });
|
|
84
|
-
if (res.status === 404) return [];
|
|
85
|
-
const data = await res.json();
|
|
86
|
-
if (!Array.isArray(data)) return [];
|
|
87
|
-
return data.map((entry) => entry.name);
|
|
88
|
-
}
|
|
89
|
-
async mkdir(_dir) {
|
|
90
|
-
}
|
|
91
|
-
async isDirectory(path) {
|
|
92
|
-
const res = await fetch(this.getUrl(path), { method: "GET", headers: this.headers });
|
|
93
|
-
if (res.status === 404) return false;
|
|
94
|
-
const data = await res.json();
|
|
95
|
-
return Array.isArray(data);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// src/core/config.ts
|
|
102
|
-
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
103
|
-
import { dirname as dirname2, join as join2 } from "path";
|
|
104
|
-
|
|
105
|
-
// src/core/local-storage.ts
|
|
106
|
-
import {
|
|
107
|
-
readFileSync,
|
|
108
|
-
writeFileSync,
|
|
109
|
-
appendFileSync,
|
|
110
|
-
existsSync,
|
|
111
|
-
mkdirSync,
|
|
112
|
-
readdirSync,
|
|
113
|
-
statSync
|
|
114
|
-
} from "fs";
|
|
115
|
-
import { dirname, join } from "path";
|
|
116
|
-
var LocalStorageAdapter = class {
|
|
117
|
-
constructor(basePath) {
|
|
118
|
-
this.basePath = basePath;
|
|
119
|
-
}
|
|
120
|
-
resolve(path) {
|
|
121
|
-
return join(this.basePath, path);
|
|
122
|
-
}
|
|
123
|
-
async read(path) {
|
|
124
|
-
const full = this.resolve(path);
|
|
125
|
-
if (!existsSync(full)) return null;
|
|
126
|
-
return readFileSync(full, "utf-8");
|
|
127
|
-
}
|
|
128
|
-
async write(path, content) {
|
|
129
|
-
const full = this.resolve(path);
|
|
130
|
-
mkdirSync(dirname(full), { recursive: true });
|
|
131
|
-
writeFileSync(full, content, "utf-8");
|
|
132
|
-
}
|
|
133
|
-
async append(path, content) {
|
|
134
|
-
const full = this.resolve(path);
|
|
135
|
-
mkdirSync(dirname(full), { recursive: true });
|
|
136
|
-
appendFileSync(full, content, "utf-8");
|
|
137
|
-
}
|
|
138
|
-
async exists(path) {
|
|
139
|
-
return existsSync(this.resolve(path));
|
|
140
|
-
}
|
|
141
|
-
async list(dir) {
|
|
142
|
-
const full = this.resolve(dir);
|
|
143
|
-
if (!existsSync(full)) return [];
|
|
144
|
-
return readdirSync(full);
|
|
145
|
-
}
|
|
146
|
-
async mkdir(dir) {
|
|
147
|
-
mkdirSync(this.resolve(dir), { recursive: true });
|
|
148
|
-
}
|
|
149
|
-
async isDirectory(path) {
|
|
150
|
-
try {
|
|
151
|
-
return statSync(this.resolve(path)).isDirectory();
|
|
152
|
-
} catch {
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
// src/core/config.ts
|
|
159
|
-
function getConfigPath() {
|
|
160
|
-
const dataDir = process.env.CLAUDE_PLUGIN_DATA;
|
|
161
|
-
if (!dataDir) {
|
|
162
|
-
throw new Error("CLAUDE_PLUGIN_DATA environment variable is not set");
|
|
163
|
-
}
|
|
164
|
-
return join2(dataDir, "config.json");
|
|
165
|
-
}
|
|
166
|
-
function isOldConfig(raw) {
|
|
167
|
-
if (!raw || typeof raw !== "object") return false;
|
|
168
|
-
return "vaultPath" in raw && "reviewFolder" in raw;
|
|
169
|
-
}
|
|
170
|
-
function migrateOldConfig(old) {
|
|
171
|
-
return {
|
|
172
|
-
storage: {
|
|
173
|
-
type: "local",
|
|
174
|
-
local: {
|
|
175
|
-
basePath: join2(old.vaultPath, old.reviewFolder)
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
language: old.language,
|
|
179
|
-
periods: old.periods,
|
|
180
|
-
profile: old.profile
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
function loadConfig() {
|
|
184
|
-
const configPath = getConfigPath();
|
|
185
|
-
if (!existsSync2(configPath)) return null;
|
|
186
|
-
const raw = JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
187
|
-
if (isOldConfig(raw)) {
|
|
188
|
-
const migrated = migrateOldConfig(raw);
|
|
189
|
-
saveConfig(migrated);
|
|
190
|
-
return migrated;
|
|
191
|
-
}
|
|
192
|
-
return raw;
|
|
193
|
-
}
|
|
194
|
-
function saveConfig(config) {
|
|
195
|
-
const configPath = getConfigPath();
|
|
196
|
-
mkdirSync2(dirname2(configPath), { recursive: true });
|
|
197
|
-
writeFileSync2(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
198
|
-
}
|
|
199
|
-
async function createStorageAdapter(config) {
|
|
200
|
-
if (config.storage.type === "local") {
|
|
201
|
-
return new LocalStorageAdapter(config.storage.local.basePath);
|
|
202
|
-
}
|
|
203
|
-
if (config.storage.type === "github") {
|
|
204
|
-
const { GitHubStorageAdapter: GitHubStorageAdapter2 } = await Promise.resolve().then(() => (init_github_storage(), github_storage_exports));
|
|
205
|
-
const g = config.storage.github;
|
|
206
|
-
return new GitHubStorageAdapter2(g.owner, g.repo, g.token, g.basePath);
|
|
207
|
-
}
|
|
208
|
-
throw new Error(`Unknown storage type: ${config.storage.type}`);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// src/cli/storage-cli.ts
|
|
212
|
-
async function main() {
|
|
213
|
-
const [command, ...args] = process.argv.slice(2);
|
|
214
|
-
const config = loadConfig();
|
|
215
|
-
if (!config) {
|
|
216
|
-
process.stderr.write("config not found\n");
|
|
217
|
-
process.exit(1);
|
|
218
|
-
}
|
|
219
|
-
const storage = await createStorageAdapter(config);
|
|
220
|
-
switch (command) {
|
|
221
|
-
case "read": {
|
|
222
|
-
const content = await storage.read(args[0]);
|
|
223
|
-
if (content !== null) process.stdout.write(content);
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
case "write": {
|
|
227
|
-
let data = "";
|
|
228
|
-
process.stdin.setEncoding("utf-8");
|
|
229
|
-
for await (const chunk of process.stdin) {
|
|
230
|
-
data += chunk;
|
|
231
|
-
}
|
|
232
|
-
await storage.write(args[0], data);
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
case "append": {
|
|
236
|
-
let data = "";
|
|
237
|
-
process.stdin.setEncoding("utf-8");
|
|
238
|
-
for await (const chunk of process.stdin) {
|
|
239
|
-
data += chunk;
|
|
240
|
-
}
|
|
241
|
-
await storage.append(args[0], data);
|
|
242
|
-
break;
|
|
243
|
-
}
|
|
244
|
-
case "list": {
|
|
245
|
-
const entries = await storage.list(args[0]);
|
|
246
|
-
process.stdout.write(entries.join("\n") + "\n");
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
case "exists": {
|
|
250
|
-
const exists = await storage.exists(args[0]);
|
|
251
|
-
process.stdout.write(exists ? "true\n" : "false\n");
|
|
252
|
-
process.exit(exists ? 0 : 1);
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
default:
|
|
256
|
-
process.stderr.write(`Unknown command: ${command}
|
|
257
|
-
Usage: storage-cli <read|write|append|list|exists> <path>
|
|
258
|
-
`);
|
|
259
|
-
process.exit(1);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
main().catch((err) => {
|
|
263
|
-
process.stderr.write(`Error: ${err.message}
|
|
264
|
-
`);
|
|
265
|
-
process.exit(1);
|
|
266
|
-
});
|
|
267
|
-
//# sourceMappingURL=storage-cli.js.map
|
package/dist/storage-cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/github-storage.ts","../src/core/config.ts","../src/core/local-storage.ts","../src/cli/storage-cli.ts"],"sourcesContent":["import type { StorageAdapter } from \"./storage.js\";\n\nexport class GitHubStorageAdapter implements StorageAdapter {\n private baseUrl: string;\n private headers: Record<string, string>;\n\n constructor(\n private owner: string,\n private repo: string,\n private token: string,\n private basePath: string,\n ) {\n this.baseUrl = `https://api.github.com/repos/${owner}/${repo}/contents`;\n this.headers = {\n Authorization: `Bearer ${token}`,\n Accept: \"application/vnd.github.v3+json\",\n \"Content-Type\": \"application/json\",\n };\n }\n\n private getUrl(path: string): string {\n return `${this.baseUrl}/${this.basePath}/${path}`;\n }\n\n private async getSha(path: string): Promise<string | null> {\n const res = await fetch(this.getUrl(path), { method: \"GET\", headers: this.headers });\n if (res.status === 404) return null;\n const data = await res.json() as Record<string, unknown>;\n return (data.sha as string) || null;\n }\n\n async read(path: string): Promise<string | null> {\n const res = await fetch(this.getUrl(path), { method: \"GET\", headers: this.headers });\n if (res.status === 404) return null;\n const data = await res.json() as Record<string, unknown>;\n const content = data.content as string;\n return Buffer.from(content, \"base64\").toString(\"utf-8\");\n }\n\n async write(path: string, content: string): Promise<void> {\n const sha = await this.getSha(path);\n const body: Record<string, unknown> = {\n message: `update ${path}`,\n content: Buffer.from(content).toString(\"base64\"),\n };\n if (sha) body.sha = sha;\n\n const res = await fetch(this.getUrl(path), {\n method: \"PUT\",\n headers: this.headers,\n body: JSON.stringify(body),\n });\n\n if (!res.ok && res.status === 409) {\n const freshSha = await this.getSha(path);\n if (freshSha) body.sha = freshSha;\n await fetch(this.getUrl(path), {\n method: \"PUT\",\n headers: this.headers,\n body: JSON.stringify(body),\n });\n }\n }\n\n async append(path: string, content: string): Promise<void> {\n const existing = await this.read(path);\n const newContent = existing ? existing + content : content;\n await this.write(path, newContent);\n }\n\n async exists(path: string): Promise<boolean> {\n const res = await fetch(this.getUrl(path), { method: \"GET\", headers: this.headers });\n return res.status !== 404;\n }\n\n async list(dir: string): Promise<string[]> {\n const res = await fetch(this.getUrl(dir), { method: \"GET\", headers: this.headers });\n if (res.status === 404) return [];\n const data = await res.json() as Array<{ name: string }>;\n if (!Array.isArray(data)) return [];\n return data.map((entry) => entry.name);\n }\n\n async mkdir(_dir: string): Promise<void> {\n // GitHub creates directories implicitly when files are created\n }\n\n async isDirectory(path: string): Promise<boolean> {\n const res = await fetch(this.getUrl(path), { method: \"GET\", headers: this.headers });\n if (res.status === 404) return false;\n const data = await res.json();\n return Array.isArray(data);\n }\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport type { StorageAdapter } from \"./storage.js\";\nimport { LocalStorageAdapter } from \"./local-storage.js\";\n\nexport interface Profile {\n company: string;\n role: string;\n team: string;\n context: string;\n}\n\nexport interface Periods {\n daily: true;\n weekly: boolean;\n monthly: boolean;\n quarterly: boolean;\n yearly: boolean;\n}\n\nexport interface LocalStorageConfig {\n basePath: string;\n}\n\nexport interface GitHubStorageConfig {\n owner: string;\n repo: string;\n token: string;\n basePath: string;\n}\n\nexport interface StorageConfig {\n type: \"local\" | \"github\";\n local?: LocalStorageConfig;\n github?: GitHubStorageConfig;\n}\n\nexport interface Config {\n storage: StorageConfig;\n language: string;\n periods: Periods;\n profile: Profile;\n}\n\ninterface OldConfig {\n vaultPath: string;\n reviewFolder: string;\n language: string;\n periods: Periods;\n profile: Profile;\n}\n\nconst DEFAULT_PERIODS: Periods = {\n daily: true,\n weekly: true,\n monthly: true,\n quarterly: true,\n yearly: false,\n};\n\nconst DEFAULT_PROFILE: Profile = {\n company: \"\",\n role: \"\",\n team: \"\",\n context: \"\",\n};\n\nexport function getConfigPath(): string {\n const dataDir = process.env.CLAUDE_PLUGIN_DATA;\n if (!dataDir) {\n throw new Error(\"CLAUDE_PLUGIN_DATA environment variable is not set\");\n }\n return join(dataDir, \"config.json\");\n}\n\nfunction isOldConfig(raw: unknown): raw is OldConfig {\n if (!raw || typeof raw !== \"object\") return false;\n return \"vaultPath\" in raw && \"reviewFolder\" in raw;\n}\n\nfunction migrateOldConfig(old: OldConfig): Config {\n return {\n storage: {\n type: \"local\",\n local: {\n basePath: join(old.vaultPath, old.reviewFolder),\n },\n },\n language: old.language,\n periods: old.periods,\n profile: old.profile,\n };\n}\n\nexport function loadConfig(): Config | null {\n const configPath = getConfigPath();\n if (!existsSync(configPath)) return null;\n const raw = JSON.parse(readFileSync(configPath, \"utf-8\"));\n if (isOldConfig(raw)) {\n const migrated = migrateOldConfig(raw);\n saveConfig(migrated);\n return migrated;\n }\n return raw as Config;\n}\n\nexport function saveConfig(config: Config): void {\n const configPath = getConfigPath();\n mkdirSync(dirname(configPath), { recursive: true });\n writeFileSync(configPath, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\nexport function validateConfig(config: unknown): config is Config {\n if (!config || typeof config !== \"object\") return false;\n const c = config as Record<string, unknown>;\n if (!c.storage || typeof c.storage !== \"object\") return false;\n const s = c.storage as Record<string, unknown>;\n if (s.type !== \"local\" && s.type !== \"github\") return false;\n if (s.type === \"local\") {\n if (!s.local || typeof s.local !== \"object\") return false;\n const l = s.local as Record<string, unknown>;\n if (typeof l.basePath !== \"string\" || l.basePath === \"\") return false;\n }\n if (s.type === \"github\") {\n if (!s.github || typeof s.github !== \"object\") return false;\n const g = s.github as Record<string, unknown>;\n if (typeof g.owner !== \"string\" || !g.owner) return false;\n if (typeof g.repo !== \"string\" || !g.repo) return false;\n if (typeof g.token !== \"string\" || !g.token) return false;\n }\n return true;\n}\n\nexport function createDefaultLocalConfig(basePath: string): Config {\n return {\n storage: { type: \"local\", local: { basePath } },\n language: \"ko\",\n periods: { ...DEFAULT_PERIODS },\n profile: { ...DEFAULT_PROFILE },\n };\n}\n\nexport function createDefaultGitHubConfig(owner: string, repo: string, token: string): Config {\n return {\n storage: { type: \"github\", github: { owner, repo, token, basePath: \"daily-review\" } },\n language: \"ko\",\n periods: { ...DEFAULT_PERIODS },\n profile: { ...DEFAULT_PROFILE },\n };\n}\n\nexport async function createStorageAdapter(config: Config): Promise<StorageAdapter> {\n if (config.storage.type === \"local\") {\n return new LocalStorageAdapter(config.storage.local!.basePath);\n }\n if (config.storage.type === \"github\") {\n const { GitHubStorageAdapter } = await import(\"./github-storage.js\");\n const g = config.storage.github!;\n return new GitHubStorageAdapter(g.owner, g.repo, g.token, g.basePath);\n }\n throw new Error(`Unknown storage type: ${(config.storage as any).type}`);\n}\n","import {\n readFileSync,\n writeFileSync,\n appendFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n statSync,\n} from \"fs\";\nimport { dirname, join } from \"path\";\nimport type { StorageAdapter } from \"./storage.js\";\n\nexport class LocalStorageAdapter implements StorageAdapter {\n constructor(private basePath: string) {}\n\n private resolve(path: string): string {\n return join(this.basePath, path);\n }\n\n async read(path: string): Promise<string | null> {\n const full = this.resolve(path);\n if (!existsSync(full)) return null;\n return readFileSync(full, \"utf-8\");\n }\n\n async write(path: string, content: string): Promise<void> {\n const full = this.resolve(path);\n mkdirSync(dirname(full), { recursive: true });\n writeFileSync(full, content, \"utf-8\");\n }\n\n async append(path: string, content: string): Promise<void> {\n const full = this.resolve(path);\n mkdirSync(dirname(full), { recursive: true });\n appendFileSync(full, content, \"utf-8\");\n }\n\n async exists(path: string): Promise<boolean> {\n return existsSync(this.resolve(path));\n }\n\n async list(dir: string): Promise<string[]> {\n const full = this.resolve(dir);\n if (!existsSync(full)) return [];\n return readdirSync(full);\n }\n\n async mkdir(dir: string): Promise<void> {\n mkdirSync(this.resolve(dir), { recursive: true });\n }\n\n async isDirectory(path: string): Promise<boolean> {\n try {\n return statSync(this.resolve(path)).isDirectory();\n } catch {\n return false;\n }\n }\n}\n","// src/cli/storage-cli.ts\nimport { loadConfig, createStorageAdapter } from \"../core/config.js\";\n\nasync function main() {\n const [command, ...args] = process.argv.slice(2);\n const config = loadConfig();\n if (!config) {\n process.stderr.write(\"config not found\\n\");\n process.exit(1);\n }\n\n const storage = await createStorageAdapter(config);\n\n switch (command) {\n case \"read\": {\n const content = await storage.read(args[0]);\n if (content !== null) process.stdout.write(content);\n break;\n }\n case \"write\": {\n let data = \"\";\n process.stdin.setEncoding(\"utf-8\");\n for await (const chunk of process.stdin) {\n data += chunk;\n }\n await storage.write(args[0], data);\n break;\n }\n case \"append\": {\n let data = \"\";\n process.stdin.setEncoding(\"utf-8\");\n for await (const chunk of process.stdin) {\n data += chunk;\n }\n await storage.append(args[0], data);\n break;\n }\n case \"list\": {\n const entries = await storage.list(args[0]);\n process.stdout.write(entries.join(\"\\n\") + \"\\n\");\n break;\n }\n case \"exists\": {\n const exists = await storage.exists(args[0]);\n process.stdout.write(exists ? \"true\\n\" : \"false\\n\");\n process.exit(exists ? 0 : 1);\n break;\n }\n default:\n process.stderr.write(`Unknown command: ${command}\\nUsage: storage-cli <read|write|append|list|exists> <path>\\n`);\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n process.stderr.write(`Error: ${err.message}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":["readFileSync","writeFileSync","existsSync","mkdirSync","dirname","join","join","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","GitHubStorageAdapter"]}
|