squidcloudctl 3.0.7 → 3.0.8

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.
@@ -107,6 +107,7 @@ const OPTIONS = {
107
107
  ['--max-body <size>', 'Body cap like 512mb / 64mb'],
108
108
  ['--allow-ips <ips>', 'Comma-separated allowlist'],
109
109
  ],
110
+ 'fs webdav': [['--port <n>', 'WebDAV port (default 8099)']],
110
111
  'fs mount': [
111
112
  ['--mount <path>', 'FUSE mount point'],
112
113
  ['--webdav', 'Force WebDAV mode'],
@@ -154,30 +154,35 @@ async function fetchVaultKey(fileId) {
154
154
  }
155
155
  }
156
156
  async function getBridgeKey() {
157
- if (process.env.SQUIDCLOUD_API_KEY)
158
- return process.env.SQUIDCLOUD_API_KEY;
157
+ if (process.env.SQUIDCLOUD_API_KEY) {
158
+ const k = process.env.SQUIDCLOUD_API_KEY;
159
+ return k.startsWith('cb_') ? k : `cb_${k}`;
160
+ }
159
161
  const fs2 = await import('node:fs');
160
162
  const os2 = await import('node:os');
161
163
  const path2 = await import('node:path');
162
164
  const keyFile = path2.join(os2.homedir(), '.squidcloud', 'bridge-key.json');
163
165
  try {
164
166
  const cached = JSON.parse(fs2.readFileSync(keyFile, 'utf8'));
165
- if (cached?.key?.startsWith('cb_'))
166
- return cached.key;
167
+ const k = cached?.key ?? '';
168
+ if (k.startsWith('cb_'))
169
+ return k;
170
+ if (k.length >= 32)
171
+ return `cb_${k}`;
167
172
  }
168
173
  catch { }
169
174
  const created = await apiPost('/keys', {
170
175
  name: 'cli-bridge-' + new Date().toISOString().slice(0, 10),
171
176
  });
172
- const key = created?.raw_key;
173
- if (!key)
174
- throw new Error('Could not provision bridge key');
177
+ const raw = created?.raw_key;
178
+ if (!raw)
179
+ throw new Error('Could not provision a bridge API key');
175
180
  try {
176
181
  fs2.mkdirSync(path2.dirname(keyFile), { recursive: true });
177
- fs2.writeFileSync(keyFile, JSON.stringify({ key, id: created?.key?.id }), { mode: 0o600 });
182
+ fs2.writeFileSync(keyFile, JSON.stringify({ key: `cb_${raw}`, minted_at: Date.now() }), { mode: 0o600 });
178
183
  }
179
184
  catch { }
180
- return key;
185
+ return `cb_${raw}`;
181
186
  }
182
187
  function parseTags(rawTags) {
183
188
  let cur = rawTags;
@@ -381,6 +386,17 @@ export async function downloadFile(target, destPath, onProgress) {
381
386
  errors.push(`cluster: ${msg}`);
382
387
  }
383
388
  }
389
+ // ── Strategy C: SquidFS bridge (files written through the mount) ──
390
+ if (chunks.length > 0 && chunks.some((c) => c.repo !== 'b2')) {
391
+ try {
392
+ const apiKey = await getBridgeKey();
393
+ const urls = await bridgeResolve(apiKey, chunks.map((c) => ({ path: c.path, index: c.index, bucket: c.bucket })));
394
+ return await fetchDecryptWrite(urls, target, destPath, onProgress);
395
+ }
396
+ catch (e) {
397
+ errors.push(`squidfs-bridge: ${e instanceof Error ? e.message : String(e)}`);
398
+ }
399
+ }
384
400
  throw new Error(errors.join(' · ') || 'No downloadable strategy succeeded');
385
401
  }
386
402
  let byokCache;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squidcloudctl",
3
- "version": "3.0.7",
3
+ "version": "3.0.8",
4
4
  "description": "SquidCloud CLI (squidcloudctl) — encrypted storage, shares and secrets from your terminal",
5
5
  "main": "dist/bin/squidcloud.js",
6
6
  "bin": {