@mieweb/pulsevault 0.0.2 → 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 (70) hide show
  1. package/CHANGELOG.md +184 -0
  2. package/LICENSE +15 -39
  3. package/OPERATIONS.md +223 -0
  4. package/PROTOCOL.md +312 -0
  5. package/README.md +532 -122
  6. package/augment.d.ts +1 -0
  7. package/augment.js +3 -0
  8. package/core.d.ts +1 -0
  9. package/core.js +7 -0
  10. package/dist/app.d.ts +90 -34
  11. package/dist/app.d.ts.map +1 -1
  12. package/dist/app.js +23 -33
  13. package/dist/app.js.map +1 -1
  14. package/dist/augment.d.ts +14 -7
  15. package/dist/augment.d.ts.map +1 -1
  16. package/dist/augment.js.map +1 -1
  17. package/dist/core.d.ts +108 -0
  18. package/dist/core.d.ts.map +1 -0
  19. package/dist/core.js +431 -0
  20. package/dist/core.js.map +1 -0
  21. package/dist/lib/authorize.d.ts +19 -0
  22. package/dist/lib/authorize.d.ts.map +1 -0
  23. package/dist/lib/authorize.js +2 -0
  24. package/dist/lib/authorize.js.map +1 -0
  25. package/dist/lib/capability-token.d.ts +80 -0
  26. package/dist/lib/capability-token.d.ts.map +1 -0
  27. package/dist/lib/capability-token.js +126 -0
  28. package/dist/lib/capability-token.js.map +1 -0
  29. package/dist/lib/checksum.d.ts +45 -0
  30. package/dist/lib/checksum.d.ts.map +1 -0
  31. package/dist/lib/checksum.js +102 -0
  32. package/dist/lib/checksum.js.map +1 -0
  33. package/dist/lib/deeplinks.d.ts +37 -21
  34. package/dist/lib/deeplinks.d.ts.map +1 -1
  35. package/dist/lib/deeplinks.js +54 -13
  36. package/dist/lib/deeplinks.js.map +1 -1
  37. package/dist/lib/magic.d.ts +30 -5
  38. package/dist/lib/magic.d.ts.map +1 -1
  39. package/dist/lib/magic.js +51 -14
  40. package/dist/lib/magic.js.map +1 -1
  41. package/dist/lib/options.d.ts +39 -0
  42. package/dist/lib/options.d.ts.map +1 -0
  43. package/dist/lib/options.js +103 -0
  44. package/dist/lib/options.js.map +1 -0
  45. package/dist/lib/pulsevaultTus.d.ts +52 -26
  46. package/dist/lib/pulsevaultTus.d.ts.map +1 -1
  47. package/dist/lib/pulsevaultTus.js +111 -43
  48. package/dist/lib/pulsevaultTus.js.map +1 -1
  49. package/dist/lib/request.d.ts +24 -0
  50. package/dist/lib/request.d.ts.map +1 -0
  51. package/dist/lib/request.js +16 -0
  52. package/dist/lib/request.js.map +1 -0
  53. package/dist/lib/uuid.d.ts.map +1 -1
  54. package/dist/lib/uuid.js +1 -1
  55. package/dist/lib/uuid.js.map +1 -1
  56. package/dist/routes/pulsevault.d.ts +18 -16
  57. package/dist/routes/pulsevault.d.ts.map +1 -1
  58. package/dist/routes/pulsevault.js +120 -251
  59. package/dist/routes/pulsevault.js.map +1 -1
  60. package/dist/storage/local.d.ts +31 -10
  61. package/dist/storage/local.d.ts.map +1 -1
  62. package/dist/storage/local.js +166 -82
  63. package/dist/storage/local.js.map +1 -1
  64. package/dist/storage/s3.d.ts +109 -0
  65. package/dist/storage/s3.d.ts.map +1 -0
  66. package/dist/storage/s3.js +432 -0
  67. package/dist/storage/s3.js.map +1 -0
  68. package/dist/storage/types.d.ts +69 -17
  69. package/dist/storage/types.d.ts.map +1 -1
  70. package/package.json +35 -7
@@ -1,51 +1,101 @@
1
- import { FileStore } from "@tus/file-store";
2
- import fs from "node:fs/promises";
3
- import path from "node:path";
4
- const SIDECAR_NAME = ".pulsevault.json";
1
+ import { FileStore } from '@tus/file-store';
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
5
4
  const SIDECAR_VERSION = 1;
5
+ /** Hidden directory inside workspaceRoot that holds per-upload sidecar files. */
6
+ const PULSEVAULT_META_DIR = '.pulsevault';
7
+ /** Default cap on the in-memory metadata cache before evicting the oldest entry. */
8
+ const DEFAULT_META_CACHE_LIMIT = 10_000;
9
+ /** Map a file extension to the `Content-Type` the GET route should return. */
10
+ function extToContentType(ext) {
11
+ switch (ext) {
12
+ case '.mp4':
13
+ return 'video/mp4';
14
+ case '.zip':
15
+ return 'application/zip';
16
+ case '.srt':
17
+ return 'application/x-subrip';
18
+ default:
19
+ return 'application/octet-stream';
20
+ }
21
+ }
22
+ /** Project a `Sidecar` into the shape kept in the in-memory cache. */
23
+ function sidecarToCachedMeta(sidecar, ready) {
24
+ return {
25
+ ext: sidecar.ext,
26
+ ready,
27
+ kind: sidecar.kind ?? 'video',
28
+ relatedTo: sidecar.relatedTo,
29
+ checksum: sidecar.checksum,
30
+ };
31
+ }
6
32
  export function createLocalStorage(opts) {
7
33
  const workspaceRoot = path.resolve(opts.workspaceDir);
8
34
  const datastore = new FileStore({ directory: workspaceRoot });
9
- // Metadata cache keyed by videoid. Populated eagerly on reserve and lazily
10
- // from the sidecar on cache-miss — so we never do a workspace-wide scan at
11
- // boot and never do a per-request readdir on the GET hot path.
35
+ const metaCacheLimit = opts.metaCacheLimit ?? DEFAULT_META_CACHE_LIMIT;
36
+ // Metadata cache keyed by artifactId. Populated eagerly on reserve and
37
+ // lazily from the sidecar on cache-miss — so we never do a workspace-wide
38
+ // scan at boot and never do a per-request readdir on the GET hot path.
39
+ // Bounded with simple insertion-order eviction (a `Map` preserves insertion
40
+ // order, and re-setting a key moves it to the end) so a long-running server
41
+ // doesn't grow this unboundedly; a cache miss just costs an extra disk read.
12
42
  const metaCache = new Map();
13
- const videoDir = (videoid) => path.join(workspaceRoot, videoid);
14
- const sidecarPath = (videoid) => path.join(videoDir(videoid), SIDECAR_NAME);
15
- const videoRelPath = (videoid, ext) => `video/${videoid}${ext}`;
16
- const writeSidecar = async (videoid, sidecar) => {
43
+ const cacheSet = (artifactId, meta) => {
44
+ // Re-inserting moves the key to the end of iteration order, so eviction
45
+ // below always drops the actual least-recently-set entry.
46
+ metaCache.delete(artifactId);
47
+ metaCache.set(artifactId, meta);
48
+ if (metaCache.size > metaCacheLimit) {
49
+ const oldest = metaCache.keys().next().value;
50
+ if (oldest !== undefined)
51
+ metaCache.delete(oldest);
52
+ }
53
+ };
54
+ /** Absolute path to the hidden metadata directory. */
55
+ const sidecarDir = () => path.join(workspaceRoot, PULSEVAULT_META_DIR);
56
+ /** Absolute path to the sidecar JSON for a given artifactId. */
57
+ const sidecarPath = (artifactId) => path.join(sidecarDir(), `${artifactId}.json`);
58
+ /** Relative path (from workspaceRoot) to the artifact bytes. */
59
+ const artifactRelPath = (artifactId, kind, ext) => `${kind}/${artifactId}${ext}`;
60
+ const writeSidecar = async (artifactId, sidecar) => {
17
61
  // Atomic tmp + rename so a crash mid-write can never leave a truncated
18
62
  // JSON blob that `loadMeta` would then treat as corrupt.
19
- const finalPath = sidecarPath(videoid);
63
+ const finalPath = sidecarPath(artifactId);
20
64
  const tmpPath = `${finalPath}.tmp`;
21
- await fs.writeFile(tmpPath, JSON.stringify(sidecar), "utf8");
65
+ await fs.mkdir(sidecarDir(), { recursive: true });
66
+ await fs.writeFile(tmpPath, JSON.stringify(sidecar), 'utf8');
22
67
  await fs.rename(tmpPath, finalPath);
23
68
  };
24
- const readSidecar = async (videoid) => {
69
+ const readSidecar = async (artifactId) => {
25
70
  let raw;
26
71
  try {
27
- raw = await fs.readFile(sidecarPath(videoid), "utf8");
72
+ raw = await fs.readFile(sidecarPath(artifactId), 'utf8');
28
73
  }
29
74
  catch (err) {
30
- if (err?.code === "ENOENT")
75
+ if (err?.code === 'ENOENT')
31
76
  return null;
32
77
  throw err;
33
78
  }
34
79
  try {
35
80
  const parsed = JSON.parse(raw);
36
- if (typeof parsed.ext !== "string")
81
+ if (typeof parsed.ext !== 'string')
37
82
  return null;
38
- if (typeof parsed.filename !== "string")
83
+ if (typeof parsed.filename !== 'string')
39
84
  return null;
40
85
  // Older sidecars (pre-status) are treated as ready so an in-place
41
86
  // upgrade doesn't hide finalized uploads. New uploads always write a
42
87
  // `status` field explicitly.
43
- const status = parsed.status === "uploading" ? "uploading" : "ready";
88
+ const status = parsed.status === 'uploading' ? 'uploading' : 'ready';
89
+ // Older sidecars without `kind` default to `"video"` — no migration.
90
+ const kind = parsed.kind === 'project' ? 'project' : parsed.kind === 'captions' ? 'captions' : 'video';
44
91
  return {
45
92
  version: SIDECAR_VERSION,
46
93
  ext: parsed.ext,
47
94
  filename: parsed.filename,
48
95
  status,
96
+ kind,
97
+ relatedTo: typeof parsed.relatedTo === 'string' ? parsed.relatedTo : undefined,
98
+ checksum: typeof parsed.checksum === 'string' ? parsed.checksum : undefined,
49
99
  };
50
100
  }
51
101
  catch {
@@ -54,104 +104,135 @@ export function createLocalStorage(opts) {
54
104
  return null;
55
105
  }
56
106
  };
57
- const loadMeta = async (videoid) => {
58
- const cached = metaCache.get(videoid);
107
+ const loadMeta = async (artifactId) => {
108
+ const cached = metaCache.get(artifactId);
59
109
  if (cached)
60
110
  return cached;
61
- const sidecar = await readSidecar(videoid);
111
+ const sidecar = await readSidecar(artifactId);
62
112
  if (!sidecar)
63
113
  return null;
64
- const meta = {
65
- ext: sidecar.ext,
66
- ready: sidecar.status === "ready",
67
- };
68
- metaCache.set(videoid, meta);
114
+ const meta = sidecarToCachedMeta(sidecar, sidecar.status === 'ready');
115
+ cacheSet(artifactId, meta);
69
116
  return meta;
70
117
  };
71
118
  const initialize = async () => {
72
- await fs.mkdir(workspaceRoot, { recursive: true });
119
+ await fs.mkdir(sidecarDir(), { recursive: true });
120
+ // @tus/file-store creates `workspaceRoot` with mode 0777 if it doesn't already exist;
121
+ // tighten it so the upload tree isn't world-writable under a permissive umask.
122
+ await fs.chmod(workspaceRoot, 0o750).catch(() => { });
73
123
  };
74
- const reserveUpload = async ({ videoid, filename, ext, }) => {
75
- // Collision guard: if an upload (in-progress or ready) already exists
76
- // for this videoid, refuse the new upload rather than letting
77
- // @tus/file-store silently reset the metadata sidecar to offset 0 and
78
- // overwrite the file chunk-by-chunk on subsequent PATCHes. Translates
79
- // to HTTP 409 via @tus/server's error path.
80
- const meta = await loadMeta(videoid);
81
- if (meta) {
82
- throw Object.assign(new Error(`videoid ${videoid} already has an upload`), { statusCode: 409, status_code: 409 });
83
- }
84
- const dir = videoDir(videoid);
85
- await fs.mkdir(path.join(dir, "video"), { recursive: true });
86
- await writeSidecar(videoid, {
124
+ const reserveUpload = async ({ artifactId, filename, ext, kind, relatedTo, checksum, }) => {
125
+ await fs.mkdir(path.join(workspaceRoot, kind), { recursive: true });
126
+ await fs.mkdir(sidecarDir(), { recursive: true });
127
+ const sidecar = {
87
128
  version: SIDECAR_VERSION,
88
129
  ext,
89
130
  filename,
90
- status: "uploading",
91
- });
92
- metaCache.set(videoid, { ext, ready: false });
131
+ status: 'uploading',
132
+ kind,
133
+ relatedTo,
134
+ checksum,
135
+ };
136
+ // Collision guard: `wx` fails atomically with EEXIST if a sidecar already exists for
137
+ // this artifactId, rather than the previous read-then-write (`loadMeta` then
138
+ // `writeSidecar`) which left a window for two concurrent/retried requests to both pass
139
+ // the check before either had written — letting the second silently clobber the first's
140
+ // sidecar and race @tus/file-store's own offset tracking. Translates to HTTP 409 via
141
+ // @tus/server's error path, same as before.
142
+ try {
143
+ await fs.writeFile(sidecarPath(artifactId), JSON.stringify(sidecar), { flag: 'wx' });
144
+ }
145
+ catch (err) {
146
+ if (err?.code !== 'EEXIST')
147
+ throw err;
148
+ // A file already exists at this path, but `readSidecar` treats a malformed/corrupt
149
+ // one as absent (e.g. debris from a crash mid-write) — re-check before deciding this
150
+ // is a genuine collision rather than debris that's safe to overwrite.
151
+ const existing = await readSidecar(artifactId);
152
+ if (existing) {
153
+ throw Object.assign(new Error(`artifactId ${artifactId} already has an upload`), {
154
+ statusCode: 409,
155
+ status_code: 409,
156
+ });
157
+ }
158
+ await writeSidecar(artifactId, sidecar);
159
+ }
160
+ cacheSet(artifactId, { ext, ready: false, kind, relatedTo, checksum });
93
161
  // @tus/file-store joins this onto its configured `directory`, so the
94
- // actual file lands at `<workspaceRoot>/<videoid>/video/<videoid><ext>`.
95
- return `${videoid}/${videoRelPath(videoid, ext)}`;
162
+ // actual file lands at `<workspaceRoot>/<kind>/<artifactId><ext>`.
163
+ return artifactRelPath(artifactId, kind, ext);
96
164
  };
97
- const resolve = async (videoid) => {
98
- const meta = await loadMeta(videoid);
165
+ const resolve = async (artifactId) => {
166
+ const meta = await loadMeta(artifactId);
99
167
  // Only serve ready uploads. In-progress uploads stay hidden — a client
100
168
  // GETting mid-upload would otherwise receive a truncated file.
101
169
  if (!meta || !meta.ready)
102
170
  return null;
103
- const root = videoDir(videoid);
104
- const relFile = videoRelPath(videoid, meta.ext);
171
+ const relFile = artifactRelPath(artifactId, meta.kind, meta.ext);
105
172
  try {
106
- const stat = await fs.stat(path.join(root, relFile));
173
+ const stat = await fs.stat(path.join(workspaceRoot, relFile));
107
174
  if (!stat.isFile())
108
175
  return null;
109
176
  }
110
177
  catch (err) {
111
- if (err?.code === "ENOENT")
178
+ if (err?.code === 'ENOENT')
112
179
  return null;
113
180
  throw err;
114
181
  }
115
- return { kind: "stream", root, filename: relFile };
182
+ return {
183
+ kind: 'stream',
184
+ root: workspaceRoot,
185
+ filename: relFile,
186
+ contentType: extToContentType(meta.ext),
187
+ };
116
188
  };
117
- const markReady = async (videoid) => {
118
- const sidecar = await readSidecar(videoid);
189
+ const markReady = async (artifactId) => {
190
+ const sidecar = await readSidecar(artifactId);
119
191
  if (!sidecar) {
120
- // No sidecar means no `reserveUpload` happened for this videoid — this
121
- // is a contract violation by the caller, not a recoverable state.
122
- throw new Error(`markReady: no sidecar for videoid ${videoid} (was reserveUpload called?)`);
192
+ // No sidecar means no `reserveUpload` happened for this artifactId —
193
+ // this is a contract violation by the caller, not a recoverable state.
194
+ throw new Error(`markReady: no sidecar for artifactId ${artifactId} (was reserveUpload called?)`);
123
195
  }
124
- if (sidecar.status === "ready") {
196
+ if (sidecar.status === 'ready') {
125
197
  // Idempotent: already ready is fine, keep the cache consistent.
126
- metaCache.set(videoid, { ext: sidecar.ext, ready: true });
198
+ cacheSet(artifactId, sidecarToCachedMeta(sidecar, true));
127
199
  return;
128
200
  }
129
- await writeSidecar(videoid, { ...sidecar, status: "ready" });
130
- metaCache.set(videoid, { ext: sidecar.ext, ready: true });
201
+ await writeSidecar(artifactId, { ...sidecar, status: 'ready' });
202
+ cacheSet(artifactId, sidecarToCachedMeta(sidecar, true));
131
203
  };
132
- const remove = async (videoid) => {
133
- const dir = videoDir(videoid);
134
- // Drop from cache before the rm so a racing `resolve` that arrives after
135
- // the rm but before the cache eviction can't hand back a stale path.
136
- metaCache.delete(videoid);
137
- try {
138
- // Note: no `force: true` — we want ENOENT to surface so the caller
139
- // (the DELETE route) can distinguish "removed something" from "nothing
140
- // to remove" and return 204 vs 404 accordingly.
141
- await fs.rm(dir, { recursive: true });
142
- return true;
143
- }
144
- catch (err) {
145
- if (err?.code === "ENOENT")
146
- return false;
147
- throw err;
148
- }
204
+ const remove = async (artifactId) => {
205
+ const meta = await loadMeta(artifactId);
206
+ // Drop from cache before rm so a racing `resolve` arriving after the
207
+ // rm but before cache eviction can't hand back a stale path.
208
+ metaCache.delete(artifactId);
209
+ if (!meta)
210
+ return false;
211
+ const artifactPath = path.join(workspaceRoot, meta.kind, `${artifactId}${meta.ext}`);
212
+ await Promise.all([
213
+ fs.rm(artifactPath, { force: true }),
214
+ fs.rm(`${artifactPath}.json`, { force: true }),
215
+ fs.rm(sidecarPath(artifactId), { force: true }),
216
+ ]);
217
+ return true;
149
218
  };
150
- const getLocalPath = async (videoid) => {
151
- const meta = await loadMeta(videoid);
219
+ const getLocalPath = async (artifactId) => {
220
+ const meta = await loadMeta(artifactId);
152
221
  if (!meta)
153
222
  return null;
154
- return path.join(workspaceRoot, videoid, "video", `${videoid}${meta.ext}`);
223
+ return path.join(workspaceRoot, meta.kind, `${artifactId}${meta.ext}`);
224
+ };
225
+ const getKind = async (artifactId) => {
226
+ const meta = await loadMeta(artifactId);
227
+ return meta ? meta.kind : null;
228
+ };
229
+ const getRelatedTo = async (artifactId) => {
230
+ const meta = await loadMeta(artifactId);
231
+ return meta?.relatedTo ?? null;
232
+ };
233
+ const getChecksum = async (artifactId) => {
234
+ const meta = await loadMeta(artifactId);
235
+ return meta?.checksum ?? null;
155
236
  };
156
237
  return {
157
238
  datastore,
@@ -162,6 +243,9 @@ export function createLocalStorage(opts) {
162
243
  markReady,
163
244
  remove,
164
245
  getLocalPath,
246
+ getKind,
247
+ getRelatedTo,
248
+ getChecksum,
165
249
  };
166
250
  }
167
251
  //# sourceMappingURL=local.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import type { S3ClientConfig } from '@aws-sdk/client-s3';
2
+ import type { PulseVaultStorage, UploadKind } from './types.js';
3
+ export type S3StorageOptions = {
4
+ /** Target bucket. Must already exist (the integrator provisions it). */
5
+ bucket: string;
6
+ /**
7
+ * Custom S3 endpoint. Set this for Cloudflare R2 or any S3-compatible store
8
+ * (e.g. `https://<account-id>.r2.cloudflarestorage.com`). Omit for AWS S3.
9
+ */
10
+ endpoint?: string;
11
+ /**
12
+ * AWS region. Required for AWS S3; for R2 use `"auto"`. When omitted and an
13
+ * `endpoint` is set this defaults to `"auto"`; otherwise the SDK resolves it
14
+ * from the environment.
15
+ */
16
+ region?: string;
17
+ /**
18
+ * Access key id. Optional — when both `accessKeyId` and `secretAccessKey`
19
+ * are omitted the AWS SDK default credential chain is used (env vars, IAM
20
+ * role, etc.). Never hard-code keys; read them from env in your app.
21
+ */
22
+ accessKeyId?: string;
23
+ /** Secret access key. See `accessKeyId`. */
24
+ secretAccessKey?: string;
25
+ /** Optional STS session token for temporary credentials. */
26
+ sessionToken?: string;
27
+ /**
28
+ * Use path-style addressing (`<endpoint>/<bucket>/<key>`) instead of
29
+ * virtual-host style. Defaults to `true` whenever a custom `endpoint` is set
30
+ * (R2 and most S3-compatible stores need it).
31
+ */
32
+ forcePathStyle?: boolean;
33
+ /** Presigned playback URL TTL in seconds. Defaults to 900 (15 minutes). */
34
+ presignTtlSeconds?: number;
35
+ /**
36
+ * Preferred multipart part size in bytes, forwarded to `@tus/s3-store`. Must
37
+ * be >= 5 MiB. When omitted, `@tus/s3-store` computes an optimal size.
38
+ */
39
+ partSize?: number;
40
+ /**
41
+ * Max number of entries kept in the in-memory metadata cache before the
42
+ * oldest (by insertion order) is evicted. A cache miss falls back to a
43
+ * bucket read, so eviction only costs an extra request, not correctness.
44
+ * Defaults to 10,000.
45
+ */
46
+ metaCacheLimit?: number;
47
+ /**
48
+ * Advanced escape hatch: extra `S3ClientConfig` fields merged into the
49
+ * client used for both playback presigning and the underlying TUS datastore
50
+ * (e.g. checksum flags for S3-compatible stores). Values here win over the
51
+ * fields derived from the options above.
52
+ */
53
+ clientConfig?: Partial<S3ClientConfig>;
54
+ };
55
+ /**
56
+ * S3 / Cloudflare R2 storage adapter. Uploads stream into the bucket via S3
57
+ * multipart upload (`@tus/s3-store`); playback is served by redirecting the
58
+ * client to a short-lived presigned GET URL, so bytes never flow back through
59
+ * the app server.
60
+ */
61
+ export type S3Storage = PulseVaultStorage & {
62
+ /** The bucket this adapter writes to. */
63
+ readonly bucket: string;
64
+ /**
65
+ * Ranged GET of the first `n` bytes of a finalized upload, or `null` if the
66
+ * artifactId is unknown. Used by `createS3Mp4Sniffer` to validate the
67
+ * payload without downloading the whole object.
68
+ */
69
+ readHeader(artifactId: string, n: number): Promise<Buffer | null>;
70
+ /**
71
+ * Full GET of a finalized upload's bytes, or `null` if the artifactId is
72
+ * unknown. Used by `createS3ChecksumValidator` — unlike `readHeader`, this
73
+ * downloads the whole object, so it's only worth using for an explicit,
74
+ * opt-in integrity check, not on every upload by default.
75
+ */
76
+ readAll(artifactId: string): Promise<Buffer | null>;
77
+ /**
78
+ * Streams a finalized upload's bytes through a hash digest, returning the
79
+ * hex digest, or `null` if the artifactId is unknown. The streaming
80
+ * counterpart to `readAll` — used by `createS3ChecksumValidator` so
81
+ * checksum verification never has to hold an entire (potentially
82
+ * multi-gigabyte) object in memory as one `Buffer`.
83
+ */
84
+ digestAll(artifactId: string, algorithm: 'sha256' | 'sha1' | 'md5'): Promise<string | null>;
85
+ /** Artifact kind for a known artifactId, or `null`. Satisfies `getKind`. */
86
+ getKind(artifactId: string): Promise<UploadKind | null>;
87
+ /** Satisfies the optional `PulseVaultStorage.getRelatedTo` contract. */
88
+ getRelatedTo(artifactId: string): Promise<string | null>;
89
+ /** Satisfies the optional `PulseVaultStorage.getChecksum` contract. */
90
+ getChecksum(artifactId: string): Promise<string | null>;
91
+ };
92
+ /**
93
+ * Build an S3/R2-backed storage adapter.
94
+ *
95
+ * Async because it lazily imports the optional `@aws-sdk/*` and
96
+ * `@tus/s3-store` packages — `await` it before registering the plugin:
97
+ *
98
+ * ```ts
99
+ * const storage = await createS3Storage({
100
+ * bucket: "pulse-videos",
101
+ * endpoint: `https://${ACCOUNT}.r2.cloudflarestorage.com`,
102
+ * accessKeyId: process.env.R2_ACCESS_KEY,
103
+ * secretAccessKey: process.env.R2_SECRET_KEY,
104
+ * });
105
+ * await app.register(pulseVault, { storage, prefix: "/pulsevault", maxUploadSize: Infinity });
106
+ * ```
107
+ */
108
+ export declare function createS3Storage(opts: S3StorageOptions): Promise<S3Storage>;
109
+ //# sourceMappingURL=s3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../src/storage/s3.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAEV,iBAAiB,EAEjB,UAAU,EACX,MAAM,YAAY,CAAC;AAwEpB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CACxC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG;IAC1C,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClE;;;;;OAKG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACpD;;;;;;OAMG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5F,4EAA4E;IAC5E,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACxD,wEAAwE;IACxE,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzD,uEAAuE;IACvE,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACzD,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAqVhF"}