@bradygaster/squad-sdk 0.9.1 → 0.9.2-insider.1
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/README.md +340 -296
- package/dist/agents/history-shadow.d.ts +7 -5
- package/dist/agents/history-shadow.d.ts.map +1 -1
- package/dist/agents/history-shadow.js +69 -78
- package/dist/agents/history-shadow.js.map +1 -1
- package/dist/agents/index.d.ts +12 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +62 -9
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/lifecycle.d.ts +4 -0
- package/dist/agents/lifecycle.d.ts.map +1 -1
- package/dist/agents/lifecycle.js +6 -7
- package/dist/agents/lifecycle.js.map +1 -1
- package/dist/agents/onboarding.d.ts +4 -2
- package/dist/agents/onboarding.d.ts.map +1 -1
- package/dist/agents/onboarding.js +26 -16
- package/dist/agents/onboarding.js.map +1 -1
- package/dist/agents/personal.d.ts +2 -1
- package/dist/agents/personal.d.ts.map +1 -1
- package/dist/agents/personal.js +11 -12
- package/dist/agents/personal.js.map +1 -1
- package/dist/build/bundle.d.ts.map +1 -1
- package/dist/build/bundle.js +6 -6
- package/dist/build/bundle.js.map +1 -1
- package/dist/build/github-dist.js +42 -42
- package/dist/build/release.d.ts.map +1 -1
- package/dist/build/release.js +7 -5
- package/dist/build/release.js.map +1 -1
- package/dist/casting/index.d.ts.map +1 -1
- package/dist/casting/index.js +4 -3
- package/dist/casting/index.js.map +1 -1
- package/dist/config/agent-source.d.ts +5 -1
- package/dist/config/agent-source.d.ts.map +1 -1
- package/dist/config/agent-source.js +85 -41
- package/dist/config/agent-source.js.map +1 -1
- package/dist/config/init.d.ts +4 -3
- package/dist/config/init.d.ts.map +1 -1
- package/dist/config/init.js +257 -236
- package/dist/config/init.js.map +1 -1
- package/dist/config/legacy-fallback.d.ts +3 -2
- package/dist/config/legacy-fallback.d.ts.map +1 -1
- package/dist/config/legacy-fallback.js +16 -14
- package/dist/config/legacy-fallback.js.map +1 -1
- package/dist/config/models.d.ts +9 -6
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +35 -25
- package/dist/config/models.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/marketplace/packaging.d.ts.map +1 -1
- package/dist/marketplace/packaging.js +18 -16
- package/dist/marketplace/packaging.js.map +1 -1
- package/dist/multi-squad.d.ts.map +1 -1
- package/dist/multi-squad.js +10 -9
- package/dist/multi-squad.js.map +1 -1
- package/dist/platform/comms-file-log.d.ts.map +1 -1
- package/dist/platform/comms-file-log.js +7 -6
- package/dist/platform/comms-file-log.js.map +1 -1
- package/dist/platform/comms.d.ts.map +1 -1
- package/dist/platform/comms.js +6 -5
- package/dist/platform/comms.js.map +1 -1
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js +4 -3
- package/dist/platform/index.js.map +1 -1
- package/dist/ralph/capabilities.d.ts +30 -1
- package/dist/ralph/capabilities.d.ts.map +1 -1
- package/dist/ralph/capabilities.js +51 -6
- package/dist/ralph/capabilities.js.map +1 -1
- package/dist/ralph/index.d.ts +1 -1
- package/dist/ralph/index.d.ts.map +1 -1
- package/dist/ralph/index.js +4 -3
- package/dist/ralph/index.js.map +1 -1
- package/dist/ralph/rate-limiting.d.ts.map +1 -1
- package/dist/ralph/rate-limiting.js +4 -4
- package/dist/ralph/rate-limiting.js.map +1 -1
- package/dist/remote/bridge.d.ts.map +1 -1
- package/dist/remote/bridge.js +2 -2
- package/dist/remote/bridge.js.map +1 -1
- package/dist/resolution.d.ts +9 -0
- package/dist/resolution.d.ts.map +1 -1
- package/dist/resolution.js +39 -16
- package/dist/resolution.js.map +1 -1
- package/dist/roles/catalog.d.ts +1 -1
- package/dist/runtime/config.d.ts.map +1 -1
- package/dist/runtime/config.js +8 -7
- package/dist/runtime/config.js.map +1 -1
- package/dist/runtime/cross-squad.d.ts.map +1 -1
- package/dist/runtime/cross-squad.js +8 -7
- package/dist/runtime/cross-squad.js.map +1 -1
- package/dist/runtime/scheduler.d.ts.map +1 -1
- package/dist/runtime/scheduler.js +8 -8
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/squad-observer.d.ts.map +1 -1
- package/dist/runtime/squad-observer.js +7 -4
- package/dist/runtime/squad-observer.js.map +1 -1
- package/dist/sharing/consult.d.ts +1 -1
- package/dist/sharing/consult.d.ts.map +1 -1
- package/dist/sharing/consult.js +144 -142
- package/dist/sharing/consult.js.map +1 -1
- package/dist/sharing/export.d.ts.map +1 -1
- package/dist/sharing/export.js +16 -16
- package/dist/sharing/export.js.map +1 -1
- package/dist/sharing/import.d.ts.map +1 -1
- package/dist/sharing/import.js +13 -12
- package/dist/sharing/import.js.map +1 -1
- package/dist/skills/skill-loader.d.ts.map +1 -1
- package/dist/skills/skill-loader.js +10 -9
- package/dist/skills/skill-loader.js.map +1 -1
- package/dist/skills/skill-script-loader.d.ts.map +1 -1
- package/dist/skills/skill-script-loader.js +6 -4
- package/dist/skills/skill-script-loader.js.map +1 -1
- package/dist/skills/skill-source.d.ts +3 -1
- package/dist/skills/skill-source.d.ts.map +1 -1
- package/dist/skills/skill-source.js +18 -16
- package/dist/skills/skill-source.js.map +1 -1
- package/dist/state/collection-map.d.ts +43 -0
- package/dist/state/collection-map.d.ts.map +1 -0
- package/dist/state/collection-map.js +9 -0
- package/dist/state/collection-map.js.map +1 -0
- package/dist/state/collections.d.ts +102 -0
- package/dist/state/collections.d.ts.map +1 -0
- package/dist/state/collections.js +317 -0
- package/dist/state/collections.js.map +1 -0
- package/dist/state/domain-types.d.ts +122 -0
- package/dist/state/domain-types.d.ts.map +1 -0
- package/dist/state/domain-types.js +54 -0
- package/dist/state/domain-types.js.map +1 -0
- package/dist/state/handles.d.ts +16 -0
- package/dist/state/handles.d.ts.map +1 -0
- package/dist/state/handles.js +161 -0
- package/dist/state/handles.js.map +1 -0
- package/dist/state/index.d.ts +17 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +15 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/io/charter-io.d.ts +28 -0
- package/dist/state/io/charter-io.d.ts.map +1 -0
- package/dist/state/io/charter-io.js +94 -0
- package/dist/state/io/charter-io.js.map +1 -0
- package/dist/state/io/decisions-io.d.ts +42 -0
- package/dist/state/io/decisions-io.d.ts.map +1 -0
- package/dist/state/io/decisions-io.js +66 -0
- package/dist/state/io/decisions-io.js.map +1 -0
- package/dist/state/io/history-io.d.ts +37 -0
- package/dist/state/io/history-io.d.ts.map +1 -0
- package/dist/state/io/history-io.js +102 -0
- package/dist/state/io/history-io.js.map +1 -0
- package/dist/state/io/index.d.ts +19 -0
- package/dist/state/io/index.d.ts.map +1 -0
- package/dist/state/io/index.js +19 -0
- package/dist/state/io/index.js.map +1 -0
- package/dist/state/io/routing-io.d.ts +37 -0
- package/dist/state/io/routing-io.d.ts.map +1 -0
- package/dist/state/io/routing-io.js +99 -0
- package/dist/state/io/routing-io.js.map +1 -0
- package/dist/state/io/team-io.d.ts +46 -0
- package/dist/state/io/team-io.d.ts.map +1 -0
- package/dist/state/io/team-io.js +82 -0
- package/dist/state/io/team-io.js.map +1 -0
- package/dist/state/schema.d.ts +24 -0
- package/dist/state/schema.d.ts.map +1 -0
- package/dist/state/schema.js +41 -0
- package/dist/state/schema.js.map +1 -0
- package/dist/state/squad-state.d.ts +42 -0
- package/dist/state/squad-state.d.ts.map +1 -0
- package/dist/state/squad-state.js +68 -0
- package/dist/state/squad-state.js.map +1 -0
- package/dist/storage/fs-storage-provider.d.ts +60 -0
- package/dist/storage/fs-storage-provider.d.ts.map +1 -0
- package/dist/storage/fs-storage-provider.js +377 -0
- package/dist/storage/fs-storage-provider.js.map +1 -0
- package/dist/storage/in-memory-storage-provider.d.ts +46 -0
- package/dist/storage/in-memory-storage-provider.d.ts.map +1 -0
- package/dist/storage/in-memory-storage-provider.js +264 -0
- package/dist/storage/in-memory-storage-provider.js.map +1 -0
- package/dist/storage/index.d.ts +6 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/sqlite-storage-provider.d.ts +95 -0
- package/dist/storage/sqlite-storage-provider.d.ts.map +1 -0
- package/dist/storage/sqlite-storage-provider.js +383 -0
- package/dist/storage/sqlite-storage-provider.js.map +1 -0
- package/dist/storage/storage-error.d.ts +28 -0
- package/dist/storage/storage-error.d.ts.map +1 -0
- package/dist/storage/storage-error.js +35 -0
- package/dist/storage/storage-error.js.map +1 -0
- package/dist/storage/storage-provider.d.ts +161 -0
- package/dist/storage/storage-provider.d.ts.map +1 -0
- package/dist/storage/storage-provider.js +18 -0
- package/dist/storage/storage-provider.js.map +1 -0
- package/dist/streams/resolver.d.ts.map +1 -1
- package/dist/streams/resolver.js +6 -5
- package/dist/streams/resolver.js.map +1 -1
- package/dist/tools/index.d.ts +5 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +54 -15
- package/dist/tools/index.js.map +1 -1
- package/dist/upstream/resolver.d.ts +3 -2
- package/dist/upstream/resolver.d.ts.map +1 -1
- package/dist/upstream/resolver.js +33 -32
- package/dist/upstream/resolver.js.map +1 -1
- package/package.json +33 -1
- package/templates/casting/Futurama.json +9 -9
- package/templates/casting-history.json +4 -4
- package/templates/casting-policy.json +37 -37
- package/templates/casting-reference.md +104 -104
- package/templates/casting-registry.json +3 -3
- package/templates/ceremonies.md +41 -41
- package/templates/charter.md +53 -53
- package/templates/constraint-tracking.md +38 -38
- package/templates/cooperative-rate-limiting.md +229 -229
- package/templates/copilot-instructions.md +46 -46
- package/templates/history.md +10 -10
- package/templates/identity/now.md +9 -9
- package/templates/identity/wisdom.md +15 -15
- package/templates/issue-lifecycle.md +412 -412
- package/templates/keda-scaler.md +164 -164
- package/templates/machine-capabilities.md +74 -74
- package/templates/mcp-config.md +90 -90
- package/templates/multi-agent-format.md +28 -28
- package/templates/plugin-marketplace.md +49 -49
- package/templates/ralph-circuit-breaker.md +313 -313
- package/templates/raw-agent-output.md +37 -37
- package/templates/roster.md +60 -60
- package/templates/routing.md +39 -39
- package/templates/run-output.md +50 -50
- package/templates/schedule.json +19 -19
- package/templates/scribe-charter.md +123 -119
- package/templates/skill.md +24 -24
- package/templates/skills/agent-collaboration/SKILL.md +42 -42
- package/templates/skills/agent-conduct/SKILL.md +24 -24
- package/templates/skills/architectural-proposals/SKILL.md +151 -151
- package/templates/skills/ci-validation-gates/SKILL.md +84 -84
- package/templates/skills/cli-wiring/SKILL.md +47 -47
- package/templates/skills/client-compatibility/SKILL.md +89 -89
- package/templates/skills/cross-machine-coordination/SKILL.md +434 -0
- package/templates/skills/cross-squad/SKILL.md +114 -114
- package/templates/skills/distributed-mesh/SKILL.md +287 -287
- package/templates/skills/distributed-mesh/mesh.json.example +30 -30
- package/templates/skills/distributed-mesh/sync-mesh.ps1 +111 -111
- package/templates/skills/distributed-mesh/sync-mesh.sh +104 -104
- package/templates/skills/docs-standards/SKILL.md +71 -71
- package/templates/skills/economy-mode/SKILL.md +114 -114
- package/templates/skills/error-recovery/SKILL.md +99 -0
- package/templates/skills/external-comms/SKILL.md +329 -329
- package/templates/skills/gh-auth-isolation/SKILL.md +183 -183
- package/templates/skills/git-workflow/SKILL.md +204 -204
- package/templates/skills/github-multi-account/SKILL.md +95 -95
- package/templates/skills/history-hygiene/SKILL.md +36 -36
- package/templates/skills/humanizer/SKILL.md +105 -105
- package/templates/skills/init-mode/SKILL.md +102 -102
- package/templates/skills/iterative-retrieval/SKILL.md +165 -0
- package/templates/skills/model-selection/SKILL.md +117 -117
- package/templates/skills/nap/SKILL.md +24 -24
- package/templates/skills/notification-routing/SKILL.md +105 -0
- package/templates/skills/personal-squad/SKILL.md +57 -57
- package/templates/skills/pr-screenshots/SKILL.md +149 -0
- package/templates/skills/project-conventions/SKILL.md +56 -56
- package/templates/skills/ralph-two-pass-scan/SKILL.md +35 -0
- package/templates/skills/reflect/SKILL.md +229 -0
- package/templates/skills/release-process/SKILL.md +131 -423
- package/templates/skills/reskill/SKILL.md +92 -92
- package/templates/skills/retro-enforcement/SKILL.md +148 -0
- package/templates/skills/reviewer-protocol/SKILL.md +79 -79
- package/templates/skills/secret-handling/SKILL.md +200 -200
- package/templates/skills/session-recovery/SKILL.md +155 -155
- package/templates/skills/squad-conventions/SKILL.md +69 -69
- package/templates/skills/test-discipline/SKILL.md +37 -37
- package/templates/skills/tiered-memory/SKILL.md +234 -0
- package/templates/skills/windows-compatibility/SKILL.md +98 -74
- package/templates/{squad.agent.md → squad.agent.md.template} +57 -28
- package/templates/workflows/squad-ci.yml +24 -24
- package/templates/workflows/squad-docs.yml +54 -54
- package/templates/workflows/squad-heartbeat.yml +167 -171
- package/templates/workflows/squad-insider-release.yml +61 -61
- package/templates/workflows/squad-issue-assign.yml +161 -161
- package/templates/workflows/squad-label-enforce.yml +181 -181
- package/templates/workflows/squad-preview.yml +55 -55
- package/templates/workflows/squad-promote.yml +120 -120
- package/templates/workflows/squad-release.yml +77 -77
- package/templates/workflows/squad-triage.yml +260 -260
- package/templates/workflows/sync-squad-labels.yml +169 -169
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import { posix } from 'path';
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync as fsMkdirSync, renameSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
const DEFAULT_DB_PATH = '.squad/squad.db';
|
|
5
|
+
/**
|
|
6
|
+
* SQLiteStorageProvider -- cross-platform SQLite-backed StorageProvider using sql.js (WASM).
|
|
7
|
+
*
|
|
8
|
+
* Use this provider when you need a single-file, portable storage backend that
|
|
9
|
+
* works identically across Windows, Linux, and macOS without native compilation.
|
|
10
|
+
* It is ideal for desktop tools and CLI applications that need durable storage
|
|
11
|
+
* without external database dependencies.
|
|
12
|
+
*
|
|
13
|
+
* **Initialization:** You MUST call {@link init} before performing any read or
|
|
14
|
+
* write operations. Calling `init()` is safe to call multiple times; subsequent
|
|
15
|
+
* calls are no-ops that return the same initialization promise.
|
|
16
|
+
*
|
|
17
|
+
* **Concurrency:** This provider is designed for single-process access. Running
|
|
18
|
+
* multiple processes against the same database file simultaneously may cause
|
|
19
|
+
* data corruption because sql.js loads the entire DB into memory and persists
|
|
20
|
+
* it atomically on every write. Use file-level locking or a dedicated process
|
|
21
|
+
* if concurrent access is required.
|
|
22
|
+
*
|
|
23
|
+
* **Database location:** The database file defaults to `.squad/squad.db`
|
|
24
|
+
* relative to the working directory. The file and parent directories are
|
|
25
|
+
* created automatically on first write. Callers are responsible for deleting
|
|
26
|
+
* the file when it is no longer needed (e.g. in test cleanup).
|
|
27
|
+
*
|
|
28
|
+
* Schema: `files(path TEXT PRIMARY KEY, content TEXT, updated_at TEXT)`
|
|
29
|
+
*
|
|
30
|
+
* sql.js runs SQLite entirely in WASM -- no native compilation required.
|
|
31
|
+
* The WASM bundle is loaded lazily via dynamic `import('sql.js')` so it
|
|
32
|
+
* only impacts startup when this provider is actually instantiated.
|
|
33
|
+
*
|
|
34
|
+
* Sync methods work because sql.js operations are synchronous under the
|
|
35
|
+
* hood (WASM, not network). The DB must be initialized before sync calls.
|
|
36
|
+
*/
|
|
37
|
+
export class SQLiteStorageProvider {
|
|
38
|
+
dbPath;
|
|
39
|
+
db = null;
|
|
40
|
+
initPromise = null;
|
|
41
|
+
constructor(dbPath = DEFAULT_DB_PATH) {
|
|
42
|
+
this.dbPath = dbPath;
|
|
43
|
+
}
|
|
44
|
+
// ── Initialization ──────────────────────────────────────────────────────
|
|
45
|
+
/**
|
|
46
|
+
* Initialize the SQLite database, loading the WASM bundle and creating the
|
|
47
|
+
* schema if needed. **Must be called before any read/write operation.**
|
|
48
|
+
*
|
|
49
|
+
* Safe to call multiple times -- the first call performs initialization and
|
|
50
|
+
* subsequent calls return the same resolved promise (no extra work).
|
|
51
|
+
*
|
|
52
|
+
* If the database file already exists on disk it is loaded into memory;
|
|
53
|
+
* otherwise a fresh in-memory database is created and will be persisted on
|
|
54
|
+
* the first write.
|
|
55
|
+
*
|
|
56
|
+
* @throws If the sql.js WASM bundle cannot be loaded (e.g. missing dependency).
|
|
57
|
+
*/
|
|
58
|
+
async init() {
|
|
59
|
+
if (this.db)
|
|
60
|
+
return;
|
|
61
|
+
if (this.initPromise)
|
|
62
|
+
return this.initPromise;
|
|
63
|
+
this.initPromise = this.doInit();
|
|
64
|
+
return this.initPromise;
|
|
65
|
+
}
|
|
66
|
+
async doInit() {
|
|
67
|
+
const initSqlJs = (await import('sql.js')).default;
|
|
68
|
+
const SQL = await initSqlJs();
|
|
69
|
+
if (existsSync(this.dbPath)) {
|
|
70
|
+
const fileBuffer = readFileSync(this.dbPath);
|
|
71
|
+
this.db = new SQL.Database(fileBuffer);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.db = new SQL.Database();
|
|
75
|
+
}
|
|
76
|
+
this.db.run(`
|
|
77
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
78
|
+
path TEXT PRIMARY KEY,
|
|
79
|
+
content TEXT,
|
|
80
|
+
updated_at TEXT
|
|
81
|
+
)
|
|
82
|
+
`);
|
|
83
|
+
}
|
|
84
|
+
/** Throws if the DB has not been initialized (for sync methods). */
|
|
85
|
+
ensureDb() {
|
|
86
|
+
if (!this.db) {
|
|
87
|
+
throw new Error('SQLiteStorageProvider is not initialized. Call init() before using sync methods.');
|
|
88
|
+
}
|
|
89
|
+
return this.db;
|
|
90
|
+
}
|
|
91
|
+
/** Ensure the DB is ready (for async methods). */
|
|
92
|
+
async ready() {
|
|
93
|
+
await this.init();
|
|
94
|
+
return this.ensureDb();
|
|
95
|
+
}
|
|
96
|
+
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
97
|
+
/** Normalize a path to forward-slash POSIX form with no trailing slash. */
|
|
98
|
+
norm(p) {
|
|
99
|
+
return posix.normalize(p.replace(/\\/g, '/')).replace(/\/+$/, '');
|
|
100
|
+
}
|
|
101
|
+
/** Escape SQL LIKE wildcards so user-supplied paths are matched literally. */
|
|
102
|
+
escapeLike(value) {
|
|
103
|
+
return value.replace(/[%_]/g, char => `\\${char}`);
|
|
104
|
+
}
|
|
105
|
+
/** Persist the in-memory DB to disk (atomic write-then-rename). */
|
|
106
|
+
persist() {
|
|
107
|
+
const db = this.ensureDb();
|
|
108
|
+
const data = db.export();
|
|
109
|
+
const buffer = Buffer.from(data);
|
|
110
|
+
fsMkdirSync(dirname(this.dbPath), { recursive: true });
|
|
111
|
+
const tmpPath = this.dbPath + '.tmp';
|
|
112
|
+
writeFileSync(tmpPath, buffer);
|
|
113
|
+
renameSync(tmpPath, this.dbPath);
|
|
114
|
+
}
|
|
115
|
+
now() {
|
|
116
|
+
return new Date().toISOString();
|
|
117
|
+
}
|
|
118
|
+
// ── Async interface ─────────────────────────────────────────────────────
|
|
119
|
+
async read(filePath) {
|
|
120
|
+
await this.ready();
|
|
121
|
+
return this.readSync(filePath);
|
|
122
|
+
}
|
|
123
|
+
async write(filePath, data) {
|
|
124
|
+
await this.ready();
|
|
125
|
+
this.writeSync(filePath, data);
|
|
126
|
+
}
|
|
127
|
+
async append(filePath, data) {
|
|
128
|
+
await this.ready();
|
|
129
|
+
const key = this.norm(filePath);
|
|
130
|
+
const existing = this.readSync(filePath) ?? '';
|
|
131
|
+
this.internalWrite(key, existing + data);
|
|
132
|
+
}
|
|
133
|
+
async exists(filePath) {
|
|
134
|
+
await this.ready();
|
|
135
|
+
return this.existsSync(filePath);
|
|
136
|
+
}
|
|
137
|
+
async list(dirPath) {
|
|
138
|
+
await this.ready();
|
|
139
|
+
return this.listSync(dirPath);
|
|
140
|
+
}
|
|
141
|
+
async delete(filePath) {
|
|
142
|
+
await this.ready();
|
|
143
|
+
const db = this.ensureDb();
|
|
144
|
+
const key = this.norm(filePath);
|
|
145
|
+
db.run('DELETE FROM files WHERE path = ?', [key]);
|
|
146
|
+
this.persist();
|
|
147
|
+
}
|
|
148
|
+
async deleteDir(dirPath) {
|
|
149
|
+
await this.ready();
|
|
150
|
+
const db = this.ensureDb();
|
|
151
|
+
const dir = this.norm(dirPath);
|
|
152
|
+
db.run('DELETE FROM files WHERE path = ? OR path LIKE ? ESCAPE \'\\\'', [dir, `${this.escapeLike(dir)}/%`]);
|
|
153
|
+
this.persist();
|
|
154
|
+
}
|
|
155
|
+
// ── Sync interface ──────────────────────────────────────────────────────
|
|
156
|
+
readSync(filePath) {
|
|
157
|
+
const db = this.ensureDb();
|
|
158
|
+
const key = this.norm(filePath);
|
|
159
|
+
const stmt = db.prepare('SELECT content FROM files WHERE path = ?');
|
|
160
|
+
stmt.bind([key]);
|
|
161
|
+
if (stmt.step()) {
|
|
162
|
+
const row = stmt.getAsObject();
|
|
163
|
+
stmt.free();
|
|
164
|
+
return row.content;
|
|
165
|
+
}
|
|
166
|
+
stmt.free();
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
writeSync(filePath, data) {
|
|
170
|
+
const key = this.norm(filePath);
|
|
171
|
+
this.internalWrite(key, data);
|
|
172
|
+
}
|
|
173
|
+
existsSync(filePath) {
|
|
174
|
+
const db = this.ensureDb();
|
|
175
|
+
const key = this.norm(filePath);
|
|
176
|
+
// Exact file match OR directory prefix match
|
|
177
|
+
const stmt = db.prepare('SELECT 1 FROM files WHERE path = ? OR path LIKE ? ESCAPE \'\\\' LIMIT 1');
|
|
178
|
+
stmt.bind([key, `${this.escapeLike(key)}/%`]);
|
|
179
|
+
const found = stmt.step();
|
|
180
|
+
stmt.free();
|
|
181
|
+
return found;
|
|
182
|
+
}
|
|
183
|
+
listSync(dirPath) {
|
|
184
|
+
const db = this.ensureDb();
|
|
185
|
+
const dir = this.norm(dirPath);
|
|
186
|
+
const prefix = dir + '/';
|
|
187
|
+
const stmt = db.prepare('SELECT path FROM files WHERE path LIKE ? ESCAPE \'\\\'');
|
|
188
|
+
stmt.bind([`${this.escapeLike(dir)}/%`]);
|
|
189
|
+
const entries = new Set();
|
|
190
|
+
while (stmt.step()) {
|
|
191
|
+
const row = stmt.getAsObject();
|
|
192
|
+
const rest = row.path.slice(prefix.length);
|
|
193
|
+
const name = rest.split('/')[0];
|
|
194
|
+
entries.add(name);
|
|
195
|
+
}
|
|
196
|
+
stmt.free();
|
|
197
|
+
return [...entries];
|
|
198
|
+
}
|
|
199
|
+
// ── Phase 3 Wave 1 additions ────────────────────────────────────────────
|
|
200
|
+
async isDirectory(targetPath) {
|
|
201
|
+
await this.ready();
|
|
202
|
+
return this.isDirectorySync(targetPath);
|
|
203
|
+
}
|
|
204
|
+
async mkdir(_dirPath, _options) {
|
|
205
|
+
// SQLite provider stores files in a virtual tree — directories are implicit.
|
|
206
|
+
await this.ready();
|
|
207
|
+
}
|
|
208
|
+
async rename(oldPath, newPath) {
|
|
209
|
+
await this.ready();
|
|
210
|
+
const db = this.ensureDb();
|
|
211
|
+
const oldKey = this.norm(oldPath);
|
|
212
|
+
const newKey = this.norm(newPath);
|
|
213
|
+
const prefix = oldKey + '/';
|
|
214
|
+
// Collect rows to move
|
|
215
|
+
const stmt = db.prepare('SELECT path, content, updated_at FROM files WHERE path = ? OR path LIKE ? ESCAPE \'\\\'');
|
|
216
|
+
stmt.bind([oldKey, `${this.escapeLike(oldKey)}/%`]);
|
|
217
|
+
const rows = [];
|
|
218
|
+
while (stmt.step()) {
|
|
219
|
+
rows.push(stmt.getAsObject());
|
|
220
|
+
}
|
|
221
|
+
stmt.free();
|
|
222
|
+
if (rows.length === 0) {
|
|
223
|
+
const err = new Error(`ENOENT: no such file or directory, rename '${oldPath}'`);
|
|
224
|
+
err.code = 'ENOENT';
|
|
225
|
+
throw err;
|
|
226
|
+
}
|
|
227
|
+
// Delete old, insert new
|
|
228
|
+
for (const row of rows) {
|
|
229
|
+
const renamedPath = row.path === oldKey
|
|
230
|
+
? newKey
|
|
231
|
+
: newKey + row.path.slice(oldKey.length);
|
|
232
|
+
db.run('DELETE FROM files WHERE path = ?', [row.path]);
|
|
233
|
+
db.run('INSERT INTO files (path, content, updated_at) VALUES (?, ?, ?) ON CONFLICT(path) DO UPDATE SET content = excluded.content, updated_at = excluded.updated_at', [renamedPath, row.content, this.now()]);
|
|
234
|
+
}
|
|
235
|
+
this.persist();
|
|
236
|
+
}
|
|
237
|
+
async copy(srcPath, destPath) {
|
|
238
|
+
await this.ready();
|
|
239
|
+
const srcKey = this.norm(srcPath);
|
|
240
|
+
const content = this.readSync(srcPath);
|
|
241
|
+
if (content === undefined) {
|
|
242
|
+
const err = new Error(`ENOENT: no such file or directory, copy '${srcPath}'`);
|
|
243
|
+
err.code = 'ENOENT';
|
|
244
|
+
throw err;
|
|
245
|
+
}
|
|
246
|
+
this.internalWrite(this.norm(destPath), content);
|
|
247
|
+
}
|
|
248
|
+
async stat(targetPath) {
|
|
249
|
+
await this.ready();
|
|
250
|
+
const db = this.ensureDb();
|
|
251
|
+
const key = this.norm(targetPath);
|
|
252
|
+
// Check for exact file match
|
|
253
|
+
const stmt = db.prepare('SELECT content, updated_at FROM files WHERE path = ?');
|
|
254
|
+
stmt.bind([key]);
|
|
255
|
+
if (stmt.step()) {
|
|
256
|
+
const row = stmt.getAsObject();
|
|
257
|
+
stmt.free();
|
|
258
|
+
return {
|
|
259
|
+
size: Buffer.byteLength(row.content, 'utf-8'),
|
|
260
|
+
mtimeMs: new Date(row.updated_at).getTime(),
|
|
261
|
+
isDirectory: false,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
stmt.free();
|
|
265
|
+
// Check if it's a directory (has children)
|
|
266
|
+
const dirStmt = db.prepare('SELECT 1 FROM files WHERE path LIKE ? ESCAPE \'\\\' LIMIT 1');
|
|
267
|
+
dirStmt.bind([`${this.escapeLike(key)}/%`]);
|
|
268
|
+
const isDir = dirStmt.step();
|
|
269
|
+
dirStmt.free();
|
|
270
|
+
if (isDir) {
|
|
271
|
+
return { size: 0, mtimeMs: 0, isDirectory: true };
|
|
272
|
+
}
|
|
273
|
+
return undefined;
|
|
274
|
+
}
|
|
275
|
+
isDirectorySync(targetPath) {
|
|
276
|
+
const db = this.ensureDb();
|
|
277
|
+
const key = this.norm(targetPath);
|
|
278
|
+
// A path is a directory if it's not a file but has children
|
|
279
|
+
const fileStmt = db.prepare('SELECT 1 FROM files WHERE path = ?');
|
|
280
|
+
fileStmt.bind([key]);
|
|
281
|
+
const isFile = fileStmt.step();
|
|
282
|
+
fileStmt.free();
|
|
283
|
+
if (isFile)
|
|
284
|
+
return false;
|
|
285
|
+
const dirStmt = db.prepare('SELECT 1 FROM files WHERE path LIKE ? ESCAPE \'\\\' LIMIT 1');
|
|
286
|
+
dirStmt.bind([`${this.escapeLike(key)}/%`]);
|
|
287
|
+
const isDir = dirStmt.step();
|
|
288
|
+
dirStmt.free();
|
|
289
|
+
return isDir;
|
|
290
|
+
}
|
|
291
|
+
mkdirSync(_dirPath, _options) {
|
|
292
|
+
// SQLite provider stores files in a virtual tree — directories are implicit.
|
|
293
|
+
this.ensureDb();
|
|
294
|
+
}
|
|
295
|
+
statSync(targetPath) {
|
|
296
|
+
const db = this.ensureDb();
|
|
297
|
+
const key = this.norm(targetPath);
|
|
298
|
+
// Check for exact file match
|
|
299
|
+
const stmt = db.prepare('SELECT content, updated_at FROM files WHERE path = ?');
|
|
300
|
+
stmt.bind([key]);
|
|
301
|
+
if (stmt.step()) {
|
|
302
|
+
const row = stmt.getAsObject();
|
|
303
|
+
stmt.free();
|
|
304
|
+
return {
|
|
305
|
+
size: Buffer.byteLength(row.content, 'utf-8'),
|
|
306
|
+
mtimeMs: new Date(row.updated_at).getTime(),
|
|
307
|
+
isDirectory: false,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
stmt.free();
|
|
311
|
+
// Check if it's a directory (has children)
|
|
312
|
+
const dirStmt = db.prepare('SELECT 1 FROM files WHERE path LIKE ? ESCAPE \'\\\' LIMIT 1');
|
|
313
|
+
dirStmt.bind([`${this.escapeLike(key)}/%`]);
|
|
314
|
+
const isDir = dirStmt.step();
|
|
315
|
+
dirStmt.free();
|
|
316
|
+
if (isDir) {
|
|
317
|
+
return { size: 0, mtimeMs: 0, isDirectory: true };
|
|
318
|
+
}
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
appendSync(filePath, data) {
|
|
322
|
+
const key = this.norm(filePath);
|
|
323
|
+
const existing = this.readSync(filePath) ?? '';
|
|
324
|
+
this.internalWrite(key, existing + data);
|
|
325
|
+
}
|
|
326
|
+
deleteSync(filePath) {
|
|
327
|
+
const db = this.ensureDb();
|
|
328
|
+
const key = this.norm(filePath);
|
|
329
|
+
db.run('DELETE FROM files WHERE path = ?', [key]);
|
|
330
|
+
this.persist();
|
|
331
|
+
}
|
|
332
|
+
renameSync(oldPath, newPath) {
|
|
333
|
+
const db = this.ensureDb();
|
|
334
|
+
const oldKey = this.norm(oldPath);
|
|
335
|
+
const newKey = this.norm(newPath);
|
|
336
|
+
const prefix = oldKey + '/';
|
|
337
|
+
// Collect rows to move
|
|
338
|
+
const stmt = db.prepare('SELECT path, content, updated_at FROM files WHERE path = ? OR path LIKE ? ESCAPE \'\\\'');
|
|
339
|
+
stmt.bind([oldKey, `${this.escapeLike(oldKey)}/%`]);
|
|
340
|
+
const rows = [];
|
|
341
|
+
while (stmt.step()) {
|
|
342
|
+
rows.push(stmt.getAsObject());
|
|
343
|
+
}
|
|
344
|
+
stmt.free();
|
|
345
|
+
if (rows.length === 0) {
|
|
346
|
+
const err = new Error(`ENOENT: no such file or directory, rename '${oldPath}'`);
|
|
347
|
+
err.code = 'ENOENT';
|
|
348
|
+
throw err;
|
|
349
|
+
}
|
|
350
|
+
// Delete old, insert new
|
|
351
|
+
for (const row of rows) {
|
|
352
|
+
const renamedPath = row.path === oldKey
|
|
353
|
+
? newKey
|
|
354
|
+
: newKey + row.path.slice(oldKey.length);
|
|
355
|
+
db.run('DELETE FROM files WHERE path = ?', [row.path]);
|
|
356
|
+
db.run('INSERT INTO files (path, content, updated_at) VALUES (?, ?, ?) ON CONFLICT(path) DO UPDATE SET content = excluded.content, updated_at = excluded.updated_at', [renamedPath, row.content, this.now()]);
|
|
357
|
+
}
|
|
358
|
+
this.persist();
|
|
359
|
+
}
|
|
360
|
+
copySync(srcPath, destPath) {
|
|
361
|
+
const content = this.readSync(srcPath);
|
|
362
|
+
if (content === undefined) {
|
|
363
|
+
const err = new Error(`ENOENT: no such file or directory, copy '${srcPath}'`);
|
|
364
|
+
err.code = 'ENOENT';
|
|
365
|
+
throw err;
|
|
366
|
+
}
|
|
367
|
+
this.internalWrite(this.norm(destPath), content);
|
|
368
|
+
}
|
|
369
|
+
deleteDirSync(dirPath) {
|
|
370
|
+
const db = this.ensureDb();
|
|
371
|
+
const dir = this.norm(dirPath);
|
|
372
|
+
db.run('DELETE FROM files WHERE path = ? OR path LIKE ? ESCAPE \'\\\'', [dir, `${this.escapeLike(dir)}/%`]);
|
|
373
|
+
this.persist();
|
|
374
|
+
}
|
|
375
|
+
// ── Internal────────────────────────────────────────────────────────────
|
|
376
|
+
internalWrite(normalizedPath, data) {
|
|
377
|
+
const db = this.ensureDb();
|
|
378
|
+
db.run(`INSERT INTO files (path, content, updated_at) VALUES (?, ?, ?)
|
|
379
|
+
ON CONFLICT(path) DO UPDATE SET content = excluded.content, updated_at = excluded.updated_at`, [normalizedPath, data, this.now()]);
|
|
380
|
+
this.persist();
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=sqlite-storage-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-storage-provider.js","sourceRoot":"","sources":["../../src/storage/sqlite-storage-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitized storage error that strips internal filesystem paths from error messages.
|
|
3
|
+
*
|
|
4
|
+
* When a StorageProvider operation fails, the underlying OS error often contains
|
|
5
|
+
* absolute filesystem paths (e.g. `/home/user/.squad/data/file.txt`). Exposing
|
|
6
|
+
* these in logs or user-facing output leaks server internals. StorageError
|
|
7
|
+
* replaces the full path with just the basename so callers see *what* failed
|
|
8
|
+
* and *why* (the errno code) without revealing *where* on disk.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* // Thrown automatically by FSStorageProvider on failure:
|
|
13
|
+
* // StorageError: Storage read failed for "file.txt": ENOENT
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare class StorageError extends Error {
|
|
17
|
+
/** The errno code from the underlying OS/system error (e.g. `ENOENT`, `EACCES`, `UNKNOWN`). */
|
|
18
|
+
readonly code: string;
|
|
19
|
+
/** The storage operation that failed (e.g. `read`, `write`, `delete`, `rename`). */
|
|
20
|
+
readonly operation: string;
|
|
21
|
+
/**
|
|
22
|
+
* @param operation - The storage operation that failed (e.g. `read`, `write`).
|
|
23
|
+
* @param filePath - The original file path; only its basename is included in the message.
|
|
24
|
+
* @param cause - The underlying Node.js filesystem error.
|
|
25
|
+
*/
|
|
26
|
+
constructor(operation: string, filePath: string, cause: NodeJS.ErrnoException);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=storage-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-error.d.ts","sourceRoot":"","sources":["../../src/storage/storage-error.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,+FAA+F;IAC/F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B;;;;OAIG;gBACS,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,cAAc;CAO9E"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { basename } from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Sanitized storage error that strips internal filesystem paths from error messages.
|
|
4
|
+
*
|
|
5
|
+
* When a StorageProvider operation fails, the underlying OS error often contains
|
|
6
|
+
* absolute filesystem paths (e.g. `/home/user/.squad/data/file.txt`). Exposing
|
|
7
|
+
* these in logs or user-facing output leaks server internals. StorageError
|
|
8
|
+
* replaces the full path with just the basename so callers see *what* failed
|
|
9
|
+
* and *why* (the errno code) without revealing *where* on disk.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* // Thrown automatically by FSStorageProvider on failure:
|
|
14
|
+
* // StorageError: Storage read failed for "file.txt": ENOENT
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export class StorageError extends Error {
|
|
18
|
+
/** The errno code from the underlying OS/system error (e.g. `ENOENT`, `EACCES`, `UNKNOWN`). */
|
|
19
|
+
code;
|
|
20
|
+
/** The storage operation that failed (e.g. `read`, `write`, `delete`, `rename`). */
|
|
21
|
+
operation;
|
|
22
|
+
/**
|
|
23
|
+
* @param operation - The storage operation that failed (e.g. `read`, `write`).
|
|
24
|
+
* @param filePath - The original file path; only its basename is included in the message.
|
|
25
|
+
* @param cause - The underlying Node.js filesystem error.
|
|
26
|
+
*/
|
|
27
|
+
constructor(operation, filePath, cause) {
|
|
28
|
+
super(`Storage ${operation} failed for "${basename(filePath)}": ${cause.code ?? 'UNKNOWN'}`);
|
|
29
|
+
this.name = 'StorageError';
|
|
30
|
+
this.code = cause.code ?? 'UNKNOWN';
|
|
31
|
+
this.operation = operation;
|
|
32
|
+
this.cause = cause;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=storage-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-error.js","sourceRoot":"","sources":["../../src/storage/storage-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhC;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,+FAA+F;IACtF,IAAI,CAAS;IACtB,oFAAoF;IAC3E,SAAS,CAAS;IAE3B;;;;OAIG;IACH,YAAY,SAAiB,EAAE,QAAgB,EAAE,KAA4B;QAC3E,KAAK,CAAC,WAAW,SAAS,gBAAgB,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC;QAC7F,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StorageProvider — abstract I/O contract for squad-sdk.
|
|
3
|
+
*
|
|
4
|
+
* All persistent storage operations flow through this interface so that
|
|
5
|
+
* runtimes (Node fs, in-memory, cloud) can be swapped without touching
|
|
6
|
+
* business logic.
|
|
7
|
+
*
|
|
8
|
+
* Wave 1 ships FSStorageProvider (Node.js fs wrapper).
|
|
9
|
+
* Wave 2 will remove the synchronous methods; callers should migrate now.
|
|
10
|
+
*
|
|
11
|
+
* **Error handling note:** FSStorageProvider wraps OS errors in `StorageError`
|
|
12
|
+
* (with typed `.code` and `.operation`). InMemoryStorageProvider and
|
|
13
|
+
* SQLiteStorageProvider throw plain `Error` for invalid operations. Callers
|
|
14
|
+
* that need provider-agnostic error handling should catch `Error` and inspect
|
|
15
|
+
* `.code` only when the value is a `StorageError`.
|
|
16
|
+
*/
|
|
17
|
+
/** Metadata returned by stat(). */
|
|
18
|
+
export interface StorageStats {
|
|
19
|
+
/** File size in bytes. 0 for directories in virtual providers. */
|
|
20
|
+
size: number;
|
|
21
|
+
/** Last modification time as ms since epoch. */
|
|
22
|
+
mtimeMs: number;
|
|
23
|
+
/** True if the path is a directory. */
|
|
24
|
+
isDirectory: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface StorageProvider {
|
|
27
|
+
/**
|
|
28
|
+
* Read the full contents of a file as a UTF-8 string.
|
|
29
|
+
* Returns `undefined` if the file does not exist (ENOENT).
|
|
30
|
+
*/
|
|
31
|
+
read(filePath: string): Promise<string | undefined>;
|
|
32
|
+
/**
|
|
33
|
+
* Write data to a file, creating parent directories as needed.
|
|
34
|
+
* Overwrites any existing content.
|
|
35
|
+
*/
|
|
36
|
+
write(filePath: string, data: string): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Append data to a file, creating it (and parent dirs) if it does not exist.
|
|
39
|
+
*/
|
|
40
|
+
append(filePath: string, data: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Return `true` if the path exists (file or directory).
|
|
43
|
+
*
|
|
44
|
+
* ⚠️ TOCTOU WARNING: Do not use exists() as a guard before read/write.
|
|
45
|
+
* Between the exists() check and the subsequent operation, the file can
|
|
46
|
+
* be deleted, replaced, or swapped by another process. Instead, call
|
|
47
|
+
* read() directly and handle `undefined` (ENOENT) in the result.
|
|
48
|
+
*/
|
|
49
|
+
exists(filePath: string): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* Return the names (not full paths) of entries directly inside `dirPath`.
|
|
52
|
+
* Returns an empty array if the directory is empty or does not exist.
|
|
53
|
+
*/
|
|
54
|
+
list(dirPath: string): Promise<string[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Delete a file. No-op if the file does not exist (ENOENT).
|
|
57
|
+
*/
|
|
58
|
+
delete(filePath: string): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Recursively delete a directory and all its contents.
|
|
61
|
+
* No-op if the directory does not exist (ENOENT).
|
|
62
|
+
*/
|
|
63
|
+
deleteDir(dirPath: string): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Return `true` if the path exists and is a directory.
|
|
66
|
+
* Returns `false` for files or non-existent paths.
|
|
67
|
+
*/
|
|
68
|
+
isDirectory(targetPath: string): Promise<boolean>;
|
|
69
|
+
/**
|
|
70
|
+
* Create a directory. When `options.recursive` is true, creates parent
|
|
71
|
+
* directories as needed (like `mkdir -p`). No-op if the directory
|
|
72
|
+
* already exists.
|
|
73
|
+
*/
|
|
74
|
+
mkdir(dirPath: string, options?: {
|
|
75
|
+
recursive?: boolean;
|
|
76
|
+
}): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Atomically rename/move a file or directory.
|
|
79
|
+
* Throws StorageError if the source does not exist.
|
|
80
|
+
*/
|
|
81
|
+
rename(oldPath: string, newPath: string): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Copy a file from `srcPath` to `destPath`.
|
|
84
|
+
* Creates parent directories for `destPath` as needed.
|
|
85
|
+
* Overwrites `destPath` if it already exists.
|
|
86
|
+
* Throws StorageError if `srcPath` does not exist.
|
|
87
|
+
*/
|
|
88
|
+
copy(srcPath: string, destPath: string): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Return file/directory metadata, or `undefined` if the path does not exist.
|
|
91
|
+
*/
|
|
92
|
+
stat(targetPath: string): Promise<StorageStats | undefined>;
|
|
93
|
+
/**
|
|
94
|
+
* Synchronous read. Returns `undefined` on ENOENT.
|
|
95
|
+
* @deprecated Use read() instead. Migration: replace `const data = provider.readSync(path)` with `const data = await provider.read(path)`. Will be removed in Wave 2.
|
|
96
|
+
*/
|
|
97
|
+
readSync(filePath: string): string | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Synchronous write with recursive mkdir.
|
|
100
|
+
* @deprecated Use write() instead. Migration: replace `provider.writeSync(path, data)` with `await provider.write(path, data)`. Will be removed in Wave 2.
|
|
101
|
+
*/
|
|
102
|
+
writeSync(filePath: string, data: string): void;
|
|
103
|
+
/**
|
|
104
|
+
* Synchronous exists check.
|
|
105
|
+
* @deprecated Use exists() instead. Migration: replace `if (provider.existsSync(path))` with `if (await provider.exists(path))`. Will be removed in Wave 2.
|
|
106
|
+
*
|
|
107
|
+
* TOCTOU: Same race condition warning as exists(). Prefer read()
|
|
108
|
+
* with undefined check over exists() then read() patterns.
|
|
109
|
+
*/
|
|
110
|
+
existsSync(filePath: string): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Synchronous directory listing.
|
|
113
|
+
* Returns entry names directly inside dirPath.
|
|
114
|
+
* Returns empty array if directory does not exist.
|
|
115
|
+
* @deprecated Use list() instead. Migration: replace `const entries = provider.listSync(dir)` with `const entries = await provider.list(dir)`. Will be removed in Wave 2.
|
|
116
|
+
*/
|
|
117
|
+
listSync(dirPath: string): string[];
|
|
118
|
+
/**
|
|
119
|
+
* Synchronous directory check.
|
|
120
|
+
* @deprecated Use isDirectory() instead. Migration: replace `if (provider.isDirectorySync(path))` with `if (await provider.isDirectory(path))`. Will be removed in Wave 2.
|
|
121
|
+
*/
|
|
122
|
+
isDirectorySync(targetPath: string): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Synchronous directory creation.
|
|
125
|
+
* @deprecated Use mkdir() instead. Migration: replace `provider.mkdirSync(dir, { recursive: true })` with `await provider.mkdir(dir, { recursive: true })`. Will be removed in Wave 2.
|
|
126
|
+
*/
|
|
127
|
+
mkdirSync(dirPath: string, options?: {
|
|
128
|
+
recursive?: boolean;
|
|
129
|
+
}): void;
|
|
130
|
+
/**
|
|
131
|
+
* Synchronous stat. Returns undefined on ENOENT.
|
|
132
|
+
* @deprecated Use stat() instead. Migration: replace `const s = provider.statSync(path)` with `const s = await provider.stat(path)`. Will be removed in Wave 2.
|
|
133
|
+
*/
|
|
134
|
+
statSync(targetPath: string): StorageStats | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* Synchronous append with recursive mkdir.
|
|
137
|
+
* @deprecated Use append() instead. Migration: replace `provider.appendSync(path, data)` with `await provider.append(path, data)`. Will be removed in Wave 2.
|
|
138
|
+
*/
|
|
139
|
+
appendSync(filePath: string, data: string): void;
|
|
140
|
+
/**
|
|
141
|
+
* Synchronous delete. No-op if file does not exist (ENOENT).
|
|
142
|
+
* @deprecated Use delete() instead. Migration: replace `provider.deleteSync(path)` with `await provider.delete(path)`. Will be removed in Wave 2.
|
|
143
|
+
*/
|
|
144
|
+
deleteSync(filePath: string): void;
|
|
145
|
+
/**
|
|
146
|
+
* Synchronous rename/move.
|
|
147
|
+
* @deprecated Use rename() instead. Migration: replace `provider.renameSync(old, new)` with `await provider.rename(old, new)`. Will be removed in Wave 2.
|
|
148
|
+
*/
|
|
149
|
+
renameSync(oldPath: string, newPath: string): void;
|
|
150
|
+
/**
|
|
151
|
+
* Synchronous file copy with recursive mkdir for dest.
|
|
152
|
+
* @deprecated Use copy() instead. Migration: replace `provider.copySync(src, dest)` with `await provider.copy(src, dest)`. Will be removed in Wave 2.
|
|
153
|
+
*/
|
|
154
|
+
copySync(srcPath: string, destPath: string): void;
|
|
155
|
+
/**
|
|
156
|
+
* Synchronous recursive directory delete. No-op if dir does not exist (ENOENT).
|
|
157
|
+
* @deprecated Use deleteDir() instead. Migration: replace `provider.deleteDirSync(dir)` with `await provider.deleteDir(dir)`. Will be removed in Wave 2.
|
|
158
|
+
*/
|
|
159
|
+
deleteDirSync(dirPath: string): void;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=storage-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-provider.d.ts","sourceRoot":"","sources":["../../src/storage/storage-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StorageProvider — abstract I/O contract for squad-sdk.
|
|
3
|
+
*
|
|
4
|
+
* All persistent storage operations flow through this interface so that
|
|
5
|
+
* runtimes (Node fs, in-memory, cloud) can be swapped without touching
|
|
6
|
+
* business logic.
|
|
7
|
+
*
|
|
8
|
+
* Wave 1 ships FSStorageProvider (Node.js fs wrapper).
|
|
9
|
+
* Wave 2 will remove the synchronous methods; callers should migrate now.
|
|
10
|
+
*
|
|
11
|
+
* **Error handling note:** FSStorageProvider wraps OS errors in `StorageError`
|
|
12
|
+
* (with typed `.code` and `.operation`). InMemoryStorageProvider and
|
|
13
|
+
* SQLiteStorageProvider throw plain `Error` for invalid operations. Callers
|
|
14
|
+
* that need provider-agnostic error handling should catch `Error` and inspect
|
|
15
|
+
* `.code` only when the value is a `StorageError`.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=storage-provider.js.map
|