@dreamlake/dreamdb 0.5.1 → 0.5.2
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/LICENSE-APACHE +20 -0
- package/LICENSE-MIT +21 -0
- package/README.md +18 -3
- package/browser/dreamdb.d.ts +89 -0
- package/browser/dreamdb.js +1 -1
- package/browser/dreamdb_bg.js +392 -2
- package/browser/dreamdb_bg.wasm +0 -0
- package/browser/dreamdb_bg.wasm.d.ts +13 -2
- package/browser-extras.mjs +82 -7
- package/browser.mjs +7 -0
- package/index.d.ts +212 -2
- package/node/dreamdb.cjs +504 -4
- package/node/dreamdb.d.cts +134 -0
- package/node/dreamdb_bg.wasm +0 -0
- package/node/dreamdb_bg.wasm.d.ts +15 -2
- package/node.mjs +1 -1
- package/package.json +4 -2
- package/web/dreamdb.d.ts +102 -2
- package/web/dreamdb.js +399 -2
- package/web/dreamdb_bg.wasm +0 -0
- package/web/dreamdb_bg.wasm.d.ts +13 -2
- package/web.mjs +5 -0
package/browser-extras.mjs
CHANGED
|
@@ -37,6 +37,42 @@ class AuthoringUnavailable {
|
|
|
37
37
|
|
|
38
38
|
export { AuthoringUnavailable as Authoring }
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* `Writer.ingestCmaf` is Node-only, for the same reason `Authoring` is: it is
|
|
42
|
+
* gated behind the `write-full` feature, and the browser build is compiled
|
|
43
|
+
* with `write`.
|
|
44
|
+
*
|
|
45
|
+
* The shared declarations describe it on both ends (see build.sh, "types"), so
|
|
46
|
+
* a browser caller type-checks and would otherwise reach
|
|
47
|
+
* `writer.ingestCmaf is not a function` at runtime — a message that names
|
|
48
|
+
* neither the cause nor the fix. This replaces it with one that does.
|
|
49
|
+
*
|
|
50
|
+
* Applied to the prototype rather than declared as a method because `Writer`
|
|
51
|
+
* comes from the wasm module; there is no class here to extend.
|
|
52
|
+
*/
|
|
53
|
+
function installIngestCmafStub(Writer) {
|
|
54
|
+
if (!Writer || typeof Writer !== 'function') return Writer
|
|
55
|
+
if (typeof Writer.prototype.ingestCmaf === 'function') return Writer // full build
|
|
56
|
+
Object.defineProperty(Writer.prototype, 'ingestCmaf', {
|
|
57
|
+
configurable: true,
|
|
58
|
+
writable: true,
|
|
59
|
+
value: async function ingestCmaf() {
|
|
60
|
+
throw new Error(
|
|
61
|
+
'Writer.ingestCmaf is not available in the browser build of ' +
|
|
62
|
+
'@dreamlake/dreamdb. CMAF ingest takes the whole clip as one ' +
|
|
63
|
+
'argument, so peak memory is the entire source — and fragmenting a ' +
|
|
64
|
+
'multi-GB file inside a tab\'s 32-bit address space is not a ' +
|
|
65
|
+
'workflow this package pretends to support. Run it under Node (the ' +
|
|
66
|
+
'"node" export condition resolves to the full build), or fragment ' +
|
|
67
|
+
'ahead of time and append the fragments.',
|
|
68
|
+
)
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
return Writer
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { installIngestCmafStub }
|
|
75
|
+
|
|
40
76
|
/**
|
|
41
77
|
* A Backend (contract v2) that gets bytes over plain `fetch` and writes through
|
|
42
78
|
* short-lived presigned URLs minted by *your* server.
|
|
@@ -86,7 +122,7 @@ export class PresignedBackend {
|
|
|
86
122
|
* @param {object} o
|
|
87
123
|
* @param {string} o.readBase Base URL for reads.
|
|
88
124
|
* @param {(paths: string[], opts?: {ifMatch?: string}) => Promise<Record<string, {url: string, headers?: Record<string,string>}>>} o.mintPut
|
|
89
|
-
* @param {(path: string, opts: {ifMatch?: string, ifNoneMatchStar?: boolean}, bytes: Uint8Array) => Promise<{status
|
|
125
|
+
* @param {(path: string, opts: {ifMatch?: string, ifNoneMatchStar?: boolean}, bytes: Uint8Array) => Promise<{outcome?: string, status?: string, etag?: string}>} [o.commitRef]
|
|
90
126
|
* Server-side ref commit. Used when `refStrategy` is `'proxy'`.
|
|
91
127
|
* @param {'proxy'|'presign'} [o.refStrategy='proxy']
|
|
92
128
|
* How the 33-byte ref object is written. `'proxy'` posts it to your
|
|
@@ -119,15 +155,27 @@ export class PresignedBackend {
|
|
|
119
155
|
return this._readUrl ? this._readUrl(path) : `${this.readBase}/${path}`
|
|
120
156
|
}
|
|
121
157
|
|
|
122
|
-
/** v2 get: returns `{bytes, etag}`. Range is
|
|
158
|
+
/** v2 get: returns `{bytes, etag, totalLength}`. Range is half-open `[start, end)`. */
|
|
123
159
|
async get(path, range) {
|
|
124
160
|
const headers = {}
|
|
125
|
-
if (range)
|
|
161
|
+
if (range) {
|
|
162
|
+
if (!Number.isSafeInteger(range.start) || !Number.isSafeInteger(range.end) ||
|
|
163
|
+
range.start < 0 || range.end <= range.start) {
|
|
164
|
+
throw new Error(`GET ${path}: invalid half-open range [${range.start}, ${range.end})`)
|
|
165
|
+
}
|
|
166
|
+
// HTTP uses an inclusive end; the Backend contract uses an exclusive one.
|
|
167
|
+
headers.range = `bytes=${range.start}-${range.end - 1}`
|
|
168
|
+
}
|
|
126
169
|
const r = await fetch(this.#url(path), { headers })
|
|
127
170
|
if (!r.ok) throw new Error(`GET ${path}: ${r.status} ${r.statusText}`)
|
|
171
|
+
const contentRange = r.headers.get('content-range')
|
|
172
|
+
const rangeTotal = contentRange && /^bytes \d+-\d+\/(\d+)$/.exec(contentRange)?.[1]
|
|
173
|
+
const lengthText = range ? rangeTotal : r.headers.get('content-length')
|
|
174
|
+
const totalLength = lengthText == null ? undefined : Number(lengthText)
|
|
128
175
|
return {
|
|
129
176
|
bytes: new Uint8Array(await r.arrayBuffer()),
|
|
130
177
|
etag: normalizeEtag(r.headers.get('etag')),
|
|
178
|
+
totalLength: Number.isSafeInteger(totalLength) && totalLength >= 0 ? totalLength : undefined,
|
|
131
179
|
}
|
|
132
180
|
}
|
|
133
181
|
|
|
@@ -148,7 +196,12 @@ export class PresignedBackend {
|
|
|
148
196
|
// semantics differ per provider — so they get their own path.
|
|
149
197
|
const isRef = path.startsWith('refs/')
|
|
150
198
|
if (isRef && this.refStrategy === 'proxy') {
|
|
151
|
-
|
|
199
|
+
// `commitRef` is the CALLER's callback and its documented contract is the
|
|
200
|
+
// `{status}` string form, so it is normalised here rather than being
|
|
201
|
+
// broken. This is the ref path — the one where mistaking a refused CAS
|
|
202
|
+
// for a successful one loses a write — so it does not rely on the
|
|
203
|
+
// adapter's compatibility handling.
|
|
204
|
+
return normalizePutResult(await this.commitRef(path, opts, bytes), path)
|
|
152
205
|
}
|
|
153
206
|
|
|
154
207
|
const minted = await this.mintPut([path], opts.ifMatch ? { ifMatch: opts.ifMatch } : undefined)
|
|
@@ -167,11 +220,11 @@ export class PresignedBackend {
|
|
|
167
220
|
// someone else moved it, which is a conflict the caller must resolve.
|
|
168
221
|
if (r.status === 412 || r.status === 409) {
|
|
169
222
|
return opts.ifNoneMatchStar
|
|
170
|
-
? {
|
|
171
|
-
: {
|
|
223
|
+
? { outcome: 'alreadyExists' }
|
|
224
|
+
: { outcome: 'casFailed', etag: normalizeEtag(r.headers.get('etag')) }
|
|
172
225
|
}
|
|
173
226
|
if (!r.ok) throw new Error(`PUT ${path}: ${r.status} ${r.statusText}`)
|
|
174
|
-
return {
|
|
227
|
+
return { outcome: 'created', etag: normalizeEtag(r.headers.get('etag')) }
|
|
175
228
|
}
|
|
176
229
|
|
|
177
230
|
// No `delete`. It would need a signed DELETE URL, and the sign endpoint only
|
|
@@ -181,6 +234,28 @@ export class PresignedBackend {
|
|
|
181
234
|
// dropping a ref is an `Authoring` operation, which is Node-only.
|
|
182
235
|
}
|
|
183
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Normalise a caller-supplied put result into the tagged form.
|
|
239
|
+
*
|
|
240
|
+
* Accepts the documented `{status: 'created'|'exists'|'casFailed'}` and the
|
|
241
|
+
* tagged `{outcome}`; anything else is refused by name rather than silently
|
|
242
|
+
* treated as success, because the one thing a ref write must never do is report
|
|
243
|
+
* a refused CAS as a completed one.
|
|
244
|
+
*/
|
|
245
|
+
function normalizePutResult(r, path) {
|
|
246
|
+
if (r && typeof r.outcome === 'string') return r
|
|
247
|
+
const s = r && r.status
|
|
248
|
+
if (s === 'created') return { outcome: 'created', etag: r.etag }
|
|
249
|
+
if (s === 'exists' || s === 'alreadyExists') return { outcome: 'alreadyExists', etag: r.etag }
|
|
250
|
+
if (s === 'casFailed') return { outcome: 'casFailed', etag: r.etag }
|
|
251
|
+
if (s === 'notFound') return { outcome: 'notFound' }
|
|
252
|
+
if (typeof s === 'number') return r
|
|
253
|
+
throw new Error(
|
|
254
|
+
`commitRef(${path}) resolved an unrecognised result; expected ` +
|
|
255
|
+
`{outcome} or {status: 'created'|'exists'|'casFailed'}, got ${JSON.stringify(r)}`,
|
|
256
|
+
)
|
|
257
|
+
}
|
|
258
|
+
|
|
184
259
|
/**
|
|
185
260
|
* S3 quotes ETags and sometimes suffixes them (`W/"…"`, `"…-3"` for multipart).
|
|
186
261
|
* The conditional-write comparison is byte-exact, so a stray quote turns every
|
package/browser.mjs
CHANGED
|
@@ -2,3 +2,10 @@
|
|
|
2
2
|
// module and instantiated by the bundler; there is nothing to await.
|
|
3
3
|
export * from './browser/dreamdb.js'
|
|
4
4
|
export { ZERO_SPATIAL_KEY, PresignedBackend, Authoring } from './browser-extras.mjs'
|
|
5
|
+
|
|
6
|
+
// `ingestCmaf` is behind `write-full`, so it is absent here while the shared
|
|
7
|
+
// declarations describe it. Replace the bare `is not a function` with a
|
|
8
|
+
// message that names the reason and the fix.
|
|
9
|
+
import { Writer as _W } from './browser/dreamdb.js'
|
|
10
|
+
import { installIngestCmafStub as _stub } from './browser-extras.mjs'
|
|
11
|
+
_stub(_W)
|
package/index.d.ts
CHANGED
|
@@ -23,6 +23,14 @@ export class Authoring {
|
|
|
23
23
|
private constructor();
|
|
24
24
|
free(): void;
|
|
25
25
|
[Symbol.dispose](): void;
|
|
26
|
+
/**
|
|
27
|
+
* Add one fixed-shape typed-array Constant.
|
|
28
|
+
*
|
|
29
|
+
* `field` is the same `{name, kind:'array', ...}` descriptor accepted by
|
|
30
|
+
* `create`, with `trackKind:'constant'` and `objectKind:'constant'`.
|
|
31
|
+
* `payload` is a raw or NPY payload matching that declaration.
|
|
32
|
+
*/
|
|
33
|
+
addArrayConstant(field: any, payload: Uint8Array): Promise<void>;
|
|
26
34
|
/**
|
|
27
35
|
* Add an embedding column whose index artifacts already exist.
|
|
28
36
|
*
|
|
@@ -127,6 +135,15 @@ export class S3Backend {
|
|
|
127
135
|
* content is hash-addressed; refs are read fresh each page load anyway).
|
|
128
136
|
*/
|
|
129
137
|
get(path: string, _opts: any): Promise<Uint8Array>;
|
|
138
|
+
/**
|
|
139
|
+
* Stream `path` without first aggregating the response in wasm memory.
|
|
140
|
+
*
|
|
141
|
+
* Returning the length beside the browser stream satisfies the optional
|
|
142
|
+
* `Backend.getStream` contract. Older injected backends that implement
|
|
143
|
+
* only [`Self::get`] remain compatible, but cannot claim bounded memory
|
|
144
|
+
* for historical oversized inline Track reads.
|
|
145
|
+
*/
|
|
146
|
+
getStream(path: string): Promise<any>;
|
|
130
147
|
/**
|
|
131
148
|
* List object paths under `prefix`. Stub (returns empty); the current
|
|
132
149
|
* consumer read paths don't require listing.
|
|
@@ -142,6 +159,32 @@ export class Space {
|
|
|
142
159
|
private constructor();
|
|
143
160
|
free(): void;
|
|
144
161
|
[Symbol.dispose](): void;
|
|
162
|
+
/**
|
|
163
|
+
* The Space's human-readable description, or `undefined` when none is set.
|
|
164
|
+
*
|
|
165
|
+
* The read half of `Authoring.setDescription` (#129). It lives here rather
|
|
166
|
+
* than on `Authoring` because that type is `write-full` and so exists only
|
|
167
|
+
* in the Node build — a description is metadata a READER wants, and
|
|
168
|
+
* `Space` is the surface all three build targets share.
|
|
169
|
+
*
|
|
170
|
+
* `async` although `Dataset::description` is not: the value comes from the
|
|
171
|
+
* Dataset this Space opens lazily at the Manifest hash already pinned by
|
|
172
|
+
* this Space, so the first call may perform that open without re-resolving
|
|
173
|
+
* a source Ref.
|
|
174
|
+
*
|
|
175
|
+
* Deliberately routed through `Dataset::description` rather than read out
|
|
176
|
+
* of `self.manifest`'s registry, which would be shorter and would also
|
|
177
|
+
* serve the cached decoded Manifest. `Dataset::recover_meta` is not a prefix
|
|
178
|
+
* filter: it accepts the legacy `vortex.*` namespace as well as
|
|
179
|
+
* `dreamdb.*`, canonicalises, and drops structural keys. Matching
|
|
180
|
+
* `dreamdb.description` here would silently return nothing for a legacy
|
|
181
|
+
* Space whose description is on disk and readable from Rust — the exact
|
|
182
|
+
* defect `recover_meta`'s own comment records.
|
|
183
|
+
*
|
|
184
|
+
* `Option<String>` marshals to `string | undefined`, NOT to `""`. An unset
|
|
185
|
+
* description and an empty one stay distinguishable across the boundary.
|
|
186
|
+
*/
|
|
187
|
+
description(): Promise<string | undefined>;
|
|
145
188
|
/**
|
|
146
189
|
* Open a Space from a `.../refs/<name>` or `.../manifests/<hash>` URI,
|
|
147
190
|
* resolving the ref (if any) and loading the manifest. If `backend` is
|
|
@@ -221,18 +264,55 @@ export class Space {
|
|
|
221
264
|
* two-pass rerank + HotShard merge + tombstone suppression.
|
|
222
265
|
*/
|
|
223
266
|
queryVector(field: string, query: Float32Array, opts: any): Promise<Array<any>>;
|
|
267
|
+
/**
|
|
268
|
+
* Read an Event/Unbucketed or Continuous/TimeBatch typed-array field as
|
|
269
|
+
* `Map<anchorString, {values, shape, ...}>`.
|
|
270
|
+
*/
|
|
271
|
+
readArrayColumn(field: string): Promise<Map<any, any>>;
|
|
272
|
+
/**
|
|
273
|
+
* Read a typed-array Constant and decode it to a JS TypedArray plus its
|
|
274
|
+
* authoritative shape and semantic metadata.
|
|
275
|
+
*/
|
|
276
|
+
readArrayConstant(field: string): Promise<any>;
|
|
224
277
|
/**
|
|
225
278
|
* Read a scalar track as a `Map<anchorString, value>`. Single-anchor
|
|
226
279
|
* entries resolve from the track index; multi-anchor entries fetch (and
|
|
227
280
|
* de-dupe) their bucket and roaring-decode the anchor set.
|
|
228
281
|
*/
|
|
229
282
|
readScalarColumn(track: any, _opts: any): Promise<Map<any, any>>;
|
|
283
|
+
/**
|
|
284
|
+
* Fetch verified initialization and complete Fragments overlapping one
|
|
285
|
+
* item-relative half-open range. This materializes the selected bytes; it
|
|
286
|
+
* is not a streaming API.
|
|
287
|
+
*/
|
|
288
|
+
readVideoItemRange(field: string, itemKey: Uint8Array, relativeStartNs: bigint | number, relativeEndNs: bigint | number): Promise<VideoItemRead | undefined>;
|
|
230
289
|
/**
|
|
231
290
|
* Fetch a track object and return its `object_index` (array of CBOR
|
|
232
291
|
* entries). Inline indexes only — paged indexes are not resolved (matching
|
|
233
292
|
* dreamdb-ts, which also doesn't support them on this path).
|
|
234
293
|
*/
|
|
235
294
|
resolveObjectIndex(track: any): Promise<Array<any>>;
|
|
295
|
+
/**
|
|
296
|
+
* Semantic-cache capacity in bytes (spec/0006 §3.6). Default 1 GiB.
|
|
297
|
+
*/
|
|
298
|
+
semanticCacheCapacity(): Promise<number>;
|
|
299
|
+
/**
|
|
300
|
+
* Semantic-cache occupancy as `{ entries, bytesUsed, maxBytes }`.
|
|
301
|
+
*/
|
|
302
|
+
semanticCacheStats(): Promise<object>;
|
|
303
|
+
/**
|
|
304
|
+
* Set the semantic-cache capacity in bytes, evicting down to it before
|
|
305
|
+
* returning. Returns the bytes evicted. `0` disables the cache.
|
|
306
|
+
*
|
|
307
|
+
* An index whose accounted size exceeds the cap is not cached and is
|
|
308
|
+
* re-fetched on every query, reported honestly as a miss. The default is
|
|
309
|
+
* not raised globally to suit one corpus.
|
|
310
|
+
*
|
|
311
|
+
* Sizing is workload- and architecture-dependent, and figures measured on
|
|
312
|
+
* a 64-bit host do NOT carry over here: `usize` is 32 bits on `wasm32`, so
|
|
313
|
+
* every offset and length inside a decoded index accounts differently.
|
|
314
|
+
*/
|
|
315
|
+
setSemanticCacheCapacity(n_bytes: number): Promise<number>;
|
|
236
316
|
/**
|
|
237
317
|
* Base32 hash of the manifest's first timeline.
|
|
238
318
|
*/
|
|
@@ -245,6 +325,16 @@ export class Space {
|
|
|
245
325
|
* List resolved tracks from this manifest.
|
|
246
326
|
*/
|
|
247
327
|
tracks(): Array<any>;
|
|
328
|
+
/**
|
|
329
|
+
* Look up the logical VideoItem containing one absolute Timeline anchor
|
|
330
|
+
* without fetching media. Exact nanosecond values are returned as bigint.
|
|
331
|
+
*/
|
|
332
|
+
videoItemAt(field: string, anchorNs: bigint | number): Promise<VideoItemInfo | undefined>;
|
|
333
|
+
/**
|
|
334
|
+
* Look up one logical VideoItem by its stable opaque key without fetching
|
|
335
|
+
* initialization or Fragment bytes.
|
|
336
|
+
*/
|
|
337
|
+
videoItemByKey(field: string, itemKey: Uint8Array): Promise<VideoItemInfo | undefined>;
|
|
248
338
|
/**
|
|
249
339
|
* The base URL objects are fetched relative to (consumers build their own
|
|
250
340
|
* object URLs from this — e.g. `dreamdb-demo`'s track readers).
|
|
@@ -289,6 +379,50 @@ export class Writer {
|
|
|
289
379
|
* Tombstone records by anchor. Returns the new manifest hash.
|
|
290
380
|
*/
|
|
291
381
|
deleteRecords(anchors: BigUint64Array, reason?: string | null): Promise<string>;
|
|
382
|
+
/**
|
|
383
|
+
* Ingest a pre-fragmented CMAF (fragmented-MP4) video into a Video field
|
|
384
|
+
* as a `spec/0007` §5 media Track — the thing that makes a video Track
|
|
385
|
+
* time-seekable and MSE-playable rather than one opaque blob.
|
|
386
|
+
*
|
|
387
|
+
* ```js
|
|
388
|
+
* const out = await writer.ingestCmaf('video', initBytes, [
|
|
389
|
+
* [frag0, 0n, 2_000_000_000n],
|
|
390
|
+
* [frag1, 2_000_000_000n, 4_000_000_000n],
|
|
391
|
+
* ])
|
|
392
|
+
* ```
|
|
393
|
+
*
|
|
394
|
+
* - `init` is the initialization segment (`ftyp`+`moov`).
|
|
395
|
+
* - each fragment is `[Uint8Array, tStartNs, tEndNs]`, half-open, already
|
|
396
|
+
* offset to the timeline anchor the caller wants. Pass `bigint`s:
|
|
397
|
+
* wall-clock nanosecond anchors are far past `Number.MAX_SAFE_INTEGER`
|
|
398
|
+
* and a rounded `tStart` writes the fragment into a 60 s bucket that
|
|
399
|
+
* does not match the address it is indexed at.
|
|
400
|
+
*
|
|
401
|
+
* Calling it again on the SAME field APPENDS (one episode per call on a
|
|
402
|
+
* shared timeline) and reuses the track's existing init segment; a clip
|
|
403
|
+
* whose init differs — different codec, resolution, fps or audio config —
|
|
404
|
+
* is refused, because a Track carries exactly one init segment and the
|
|
405
|
+
* mismatch would produce fragments that decode against the wrong one.
|
|
406
|
+
*
|
|
407
|
+
* Returns `{field, modality, initHash, fragmentCount, coverage: [bigint,
|
|
408
|
+
* bigint], trackHash, manifestHash}`. `coverage` is `bigint` for the
|
|
409
|
+
* reason above; `fragmentCount` is the track's total after the append,
|
|
410
|
+
* not the number passed in.
|
|
411
|
+
*
|
|
412
|
+
* **Node only** (`write-full`). This takes every fragment's bytes as an
|
|
413
|
+
* argument, so peak memory is the whole clip; the native path form streams
|
|
414
|
+
* fragment-by-fragment off disk, which wasm32 cannot do because it has no
|
|
415
|
+
* filesystem. Fragmenting a multi-GB source inside a browser tab's 32-bit
|
|
416
|
+
* address space is not a workflow worth pretending to support.
|
|
417
|
+
*/
|
|
418
|
+
/**
|
|
419
|
+
* **Node only.** Gated behind the `write-full` feature, which the browser
|
|
420
|
+
* and web builds are not compiled with: CMAF ingest takes the whole clip as
|
|
421
|
+
* one argument, so peak memory is the entire source. Calling it in a browser
|
|
422
|
+
* throws with an explanation — see the stub in browser-extras.mjs. Typed on
|
|
423
|
+
* both ends, like `Authoring`, so shared code type-checks once.
|
|
424
|
+
*/
|
|
425
|
+
ingestCmaf(field: string, init: Uint8Array, fragments: CmafFragment[]): Promise<CmafIngestResult>;
|
|
292
426
|
/**
|
|
293
427
|
* Open a ref for writing.
|
|
294
428
|
*
|
|
@@ -428,6 +562,13 @@ export function timeAnchorHex(value: bigint): string;
|
|
|
428
562
|
*/
|
|
429
563
|
export function timeBucket(t_start: bigint, duration: string): bigint;
|
|
430
564
|
|
|
565
|
+
/**
|
|
566
|
+
* Decode one spec/0025 item using the same declaration and payload path as
|
|
567
|
+
* `Space.readArrayColumn`, without requiring storage IO. This is the SDK's
|
|
568
|
+
* pure conformance entry point for language-neutral vectors.
|
|
569
|
+
*/
|
|
570
|
+
export function typedArrayDecode(item_type: any, payload: Uint8Array): any;
|
|
571
|
+
|
|
431
572
|
/**
|
|
432
573
|
* Package version — useful for consumers to confirm which build is loaded.
|
|
433
574
|
*/
|
|
@@ -444,6 +585,62 @@ export function zeroSpatialKey(): string;
|
|
|
444
585
|
/** Zero spatial-key path segment for non-spatial (fragment) object addresses. */
|
|
445
586
|
export const ZERO_SPATIAL_KEY: string
|
|
446
587
|
|
|
588
|
+
/**
|
|
589
|
+
* One CMAF fragment for {@link Writer.ingestCmaf}: `[bytes, tStartNs, tEndNs)`,
|
|
590
|
+
* half-open, already offset to the timeline anchor you want.
|
|
591
|
+
*
|
|
592
|
+
* Pass `bigint`s. A `number` is accepted only while it is an exact
|
|
593
|
+
* non-negative integer at or below `Number.MAX_SAFE_INTEGER` and is rejected
|
|
594
|
+
* above it rather than rounded — wall-clock nanosecond anchors are ~1.7e18, and
|
|
595
|
+
* a rounded `tStart` files the fragment under a different 60 s bucket than the
|
|
596
|
+
* address it is indexed at.
|
|
597
|
+
*/
|
|
598
|
+
export type CmafFragment = [bytes: Uint8Array, tStartNs: bigint | number, tEndNs: bigint | number]
|
|
599
|
+
|
|
600
|
+
/** What {@link Writer.ingestCmaf} resolves to. */
|
|
601
|
+
export interface CmafIngestResult {
|
|
602
|
+
/** Schema field this Track materializes. */
|
|
603
|
+
field: string
|
|
604
|
+
/** Modality string, e.g. `video.h264`. */
|
|
605
|
+
modality: string
|
|
606
|
+
/** Base32 multihash of the initialization-segment object. */
|
|
607
|
+
initHash: string
|
|
608
|
+
/** Fragments in the Track *after* this call — not the number passed in. */
|
|
609
|
+
fragmentCount: number
|
|
610
|
+
/** Half-open `[tMin, tMax)` coverage of the whole Track, in ns. */
|
|
611
|
+
coverage: [bigint, bigint]
|
|
612
|
+
/** Base32 multihash of the new Track object. */
|
|
613
|
+
trackHash: string
|
|
614
|
+
/** Base32 multihash of the manifest this ingest published. */
|
|
615
|
+
manifestHash: string
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/** Stable metadata for one logical VideoItem. All times are exact bigint ns. */
|
|
619
|
+
export interface VideoItemInfo {
|
|
620
|
+
modality: string
|
|
621
|
+
itemKey: Uint8Array
|
|
622
|
+
tStartNs: bigint
|
|
623
|
+
durationNs: bigint
|
|
624
|
+
itemAddress: string
|
|
625
|
+
initAddress: string
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/** One complete Fragment selected by {@link Space.readVideoItemRange}. */
|
|
629
|
+
export interface VideoItemFragmentRead {
|
|
630
|
+
tStartNs: bigint
|
|
631
|
+
tEndNs: bigint
|
|
632
|
+
bytes: Uint8Array
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/** Materialized initialization plus complete Fragments for one relative range. */
|
|
636
|
+
export interface VideoItemRead {
|
|
637
|
+
item: VideoItemInfo
|
|
638
|
+
rangeStartNs: bigint
|
|
639
|
+
rangeEndNs: bigint
|
|
640
|
+
init: Uint8Array
|
|
641
|
+
fragments: VideoItemFragmentRead[]
|
|
642
|
+
}
|
|
643
|
+
|
|
447
644
|
/** A resolved manifest track (shape returned by `Space.tracks()`). */
|
|
448
645
|
export interface ResolvedTrack {
|
|
449
646
|
modality: string
|
|
@@ -475,11 +672,24 @@ export type PutStatus = 'created' | 'exists' | 'casFailed'
|
|
|
475
672
|
* CORS rule; without it the browser cannot read the header at all.
|
|
476
673
|
*/
|
|
477
674
|
export interface Backend {
|
|
478
|
-
/**
|
|
675
|
+
/** Half-open byte range `[start, end)`. Returning a bare Uint8Array is the accepted whole-object v1 shape. */
|
|
479
676
|
get(
|
|
480
677
|
path: string,
|
|
481
678
|
range?: { start: number; end: number },
|
|
482
|
-
): Promise<Uint8Array | { bytes: Uint8Array; etag?: string }>
|
|
679
|
+
): Promise<Uint8Array | { bytes: Uint8Array; etag?: string; totalLength?: number }>
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Optional bounded full-object stream. Without this method reads remain
|
|
683
|
+
* functional, but oversized historical inline Tracks use the unbounded v1
|
|
684
|
+
* compatibility path.
|
|
685
|
+
*/
|
|
686
|
+
getStream?(
|
|
687
|
+
path: string,
|
|
688
|
+
): Promise<ReadableStream<Uint8Array> | {
|
|
689
|
+
stream: ReadableStream<Uint8Array>
|
|
690
|
+
etag?: string
|
|
691
|
+
totalLength?: number
|
|
692
|
+
}>
|
|
483
693
|
|
|
484
694
|
head?(path: string): Promise<{ exists?: boolean; etag?: string; size?: number }>
|
|
485
695
|
|