@opengeni/storage 0.2.75 → 0.2.87
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/dist/bounded-object-read.d.ts +76 -0
- package/dist/bounded-object-write.d.ts +53 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +798 -2
- package/dist/index.js.map +1 -1
- package/dist/object-storage-bounded.d.ts +21 -0
- package/package.json +3 -3
- package/src/bounded-object-read.ts +323 -0
- package/src/bounded-object-write.ts +269 -0
- package/src/index.ts +281 -0
- package/src/object-storage-bounded.ts +297 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version-pinned, bounded object reads for large trusted-server workloads.
|
|
3
|
+
*
|
|
4
|
+
* This surface deliberately deals in opaque references. Provider keys, bucket
|
|
5
|
+
* names, signed URLs, and provider diagnostics stay behind the backend
|
|
6
|
+
* callback and are never included in returned values or public errors.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_BOUNDED_OBJECT_CHUNK_BYTES: number;
|
|
9
|
+
export declare const MAX_BOUNDED_OBJECT_CHUNK_BYTES: number;
|
|
10
|
+
export type BoundedObjectReadErrorCode = "aborted" | "backend_failure" | "invalid_request" | "object_changed" | "object_missing" | "size_limit" | "truncated";
|
|
11
|
+
export declare class BoundedObjectReadError extends Error {
|
|
12
|
+
readonly code: BoundedObjectReadErrorCode;
|
|
13
|
+
constructor(code: BoundedObjectReadErrorCode);
|
|
14
|
+
}
|
|
15
|
+
export type VersionedObjectDescription = Readonly<{
|
|
16
|
+
byteSize: number;
|
|
17
|
+
/** Opaque provider generation/etag token. It never crosses this package. */
|
|
18
|
+
versionToken: string;
|
|
19
|
+
/**
|
|
20
|
+
* Explicit adapter assertion that the opaque reference resolves forever to
|
|
21
|
+
* this provider generation (for example a version id or immutable
|
|
22
|
+
* content-addressed object). Mutable raw keys must never set this flag.
|
|
23
|
+
*/
|
|
24
|
+
immutableReference: true;
|
|
25
|
+
contentType?: string;
|
|
26
|
+
}>;
|
|
27
|
+
export type VersionedObjectRange = Readonly<{
|
|
28
|
+
bytes: Uint8Array;
|
|
29
|
+
versionToken: string;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Provider adapter used by the range reader. Implementations should use a
|
|
33
|
+
* provider-native generation/version/If-Match condition whenever available.
|
|
34
|
+
* Returning a different version is treated as replacement, never as data.
|
|
35
|
+
*/
|
|
36
|
+
export interface VersionedRangeObjectBackend {
|
|
37
|
+
describe(input: {
|
|
38
|
+
opaqueReference: string;
|
|
39
|
+
signal?: AbortSignal;
|
|
40
|
+
}): Promise<VersionedObjectDescription | null>;
|
|
41
|
+
readRange(input: {
|
|
42
|
+
opaqueReference: string;
|
|
43
|
+
start: number;
|
|
44
|
+
endInclusive: number;
|
|
45
|
+
expectedVersionToken: string;
|
|
46
|
+
signal?: AbortSignal;
|
|
47
|
+
}): Promise<VersionedObjectRange | null>;
|
|
48
|
+
close?(input: {
|
|
49
|
+
opaqueReference: string;
|
|
50
|
+
}): void | Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
export interface BoundedObjectRead {
|
|
53
|
+
readonly byteSize: number;
|
|
54
|
+
readonly contentType: string | undefined;
|
|
55
|
+
/** A read handle is intentionally single-use. */
|
|
56
|
+
chunks(input?: {
|
|
57
|
+
chunkBytes?: number;
|
|
58
|
+
signal?: AbortSignal;
|
|
59
|
+
}): AsyncIterable<Uint8Array>;
|
|
60
|
+
/** Revalidate the immutable provider generation after all consumers finish. */
|
|
61
|
+
assertUnchanged(signal?: AbortSignal): Promise<void>;
|
|
62
|
+
close(): Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
export interface BoundedObjectReadPort {
|
|
65
|
+
open(input: {
|
|
66
|
+
opaqueReference: string;
|
|
67
|
+
maxBytes: number;
|
|
68
|
+
expectedByteSize?: number;
|
|
69
|
+
signal?: AbortSignal;
|
|
70
|
+
}): Promise<BoundedObjectRead>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Adds uniform limits, exact-range checks, replacement fencing, cancellation,
|
|
74
|
+
* and diagnostic scrubbing around a provider-specific range backend.
|
|
75
|
+
*/
|
|
76
|
+
export declare function createBoundedObjectReadPort(backend: VersionedRangeObjectBackend): BoundedObjectReadPort;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type BoundedObjectReadPort } from "./bounded-object-read.js";
|
|
2
|
+
export type BoundedObjectWriteErrorCode = "aborted" | "backend_failure" | "content_hash_mismatch" | "invalid_request" | "readback_mismatch" | "size_limit" | "truncated";
|
|
3
|
+
export declare class BoundedObjectWriteError extends Error {
|
|
4
|
+
readonly code: BoundedObjectWriteErrorCode;
|
|
5
|
+
constructor(code: BoundedObjectWriteErrorCode);
|
|
6
|
+
}
|
|
7
|
+
export interface ImmutableContentAddressedWriteSession {
|
|
8
|
+
write(chunk: Uint8Array, signal?: AbortSignal): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Atomically promotes staged bytes to an immutable content-addressed object.
|
|
11
|
+
* The returned reference must resolve forever to this exact generation.
|
|
12
|
+
*/
|
|
13
|
+
commit(input: {
|
|
14
|
+
byteSize: number;
|
|
15
|
+
contentHash: string;
|
|
16
|
+
contentType: string;
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
opaqueReference: string;
|
|
20
|
+
}>;
|
|
21
|
+
abort(): void | Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export interface ImmutableContentAddressedWriteBackend {
|
|
24
|
+
begin(input: {
|
|
25
|
+
contentType: string;
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
}): Promise<ImmutableContentAddressedWriteSession>;
|
|
28
|
+
}
|
|
29
|
+
export type BoundedImmutableObjectWriteResult = Readonly<{
|
|
30
|
+
opaqueReference: string;
|
|
31
|
+
byteSize: number;
|
|
32
|
+
contentHash: string;
|
|
33
|
+
contentType: string;
|
|
34
|
+
}>;
|
|
35
|
+
export interface BoundedImmutableObjectWritePort {
|
|
36
|
+
write(input: {
|
|
37
|
+
chunks: AsyncIterable<Uint8Array>;
|
|
38
|
+
contentType: string;
|
|
39
|
+
maxBytes: number;
|
|
40
|
+
expectedByteSize?: number;
|
|
41
|
+
expectedContentHash?: string;
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
}): Promise<BoundedImmutableObjectWriteResult>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Streams to provider staging, atomically promotes by digest, then streams the
|
|
47
|
+
* immutable object back and hashes it independently before returning its
|
|
48
|
+
* opaque reference. Neither direction accumulates the complete object.
|
|
49
|
+
*/
|
|
50
|
+
export declare function createBoundedImmutableObjectWritePort(input: {
|
|
51
|
+
backend: ImmutableContentAddressedWriteBackend;
|
|
52
|
+
readback: BoundedObjectReadPort;
|
|
53
|
+
}): BoundedImmutableObjectWritePort;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Settings } from "@opengeni/config";
|
|
2
2
|
import { type FileAsset } from "@opengeni/contracts";
|
|
3
|
+
export * from "./bounded-object-read.js";
|
|
4
|
+
export * from "./bounded-object-write.js";
|
|
5
|
+
export * from "./object-storage-bounded.js";
|
|
3
6
|
export declare const MAX_SINGLE_PUT_SIZE_BYTES = 5000000000;
|
|
4
7
|
export declare const UPLOAD_URL_TTL_SECONDS: number;
|
|
5
8
|
export declare const DOWNLOAD_URL_TTL_SECONDS: number;
|
|
@@ -7,6 +10,8 @@ export type ObjectHead = {
|
|
|
7
10
|
ContentLength?: number;
|
|
8
11
|
ContentType?: string;
|
|
9
12
|
Metadata?: Record<string, string>;
|
|
13
|
+
/** Opaque provider generation/etag used only for conditional internal reads. */
|
|
14
|
+
VersionToken?: string;
|
|
10
15
|
};
|
|
11
16
|
export type ObjectStorage = {
|
|
12
17
|
bucket: string;
|
|
@@ -46,6 +51,17 @@ export type ObjectStorage = {
|
|
|
46
51
|
bytes: Uint8Array;
|
|
47
52
|
contentType?: string;
|
|
48
53
|
} | null>;
|
|
54
|
+
/** Provider-versioned raw-key primitives used by bounded immutable adapters. */
|
|
55
|
+
headObject?: (key: string) => Promise<ObjectHead | null>;
|
|
56
|
+
getObjectRange?: (args: {
|
|
57
|
+
key: string;
|
|
58
|
+
start: number;
|
|
59
|
+
endInclusive: number;
|
|
60
|
+
expectedVersionToken: string;
|
|
61
|
+
}) => Promise<{
|
|
62
|
+
bytes: Uint8Array;
|
|
63
|
+
versionToken: string;
|
|
64
|
+
} | null>;
|
|
49
65
|
/**
|
|
50
66
|
* SERVER-SIDE authenticated direct PUT (no presign + browser fetch). For an
|
|
51
67
|
* in-process upload from a trusted holder of the storage credentials (e.g. the
|
|
@@ -64,6 +80,25 @@ export type ObjectStorage = {
|
|
|
64
80
|
body: Uint8Array;
|
|
65
81
|
sha256?: string | null;
|
|
66
82
|
}) => Promise<void>;
|
|
83
|
+
/** Atomic create-only raw PUT. Returns false when the key already exists. */
|
|
84
|
+
putObjectIfAbsent?: (args: {
|
|
85
|
+
key: string;
|
|
86
|
+
contentType: string;
|
|
87
|
+
body: Uint8Array;
|
|
88
|
+
sha256: string;
|
|
89
|
+
}) => Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Atomic create-only raw upload from a bounded asynchronous byte stream.
|
|
92
|
+
* Providers may buffer a small fixed number of chunks, never the whole body.
|
|
93
|
+
*/
|
|
94
|
+
putObjectStreamIfAbsent?: (args: {
|
|
95
|
+
key: string;
|
|
96
|
+
contentType: string;
|
|
97
|
+
chunks: AsyncIterable<Uint8Array>;
|
|
98
|
+
byteSize: number;
|
|
99
|
+
sha256: string;
|
|
100
|
+
signal?: AbortSignal;
|
|
101
|
+
}) => Promise<boolean>;
|
|
67
102
|
/**
|
|
68
103
|
* SERVER-SIDE authenticated delete of a single object by raw storage key.
|
|
69
104
|
* Idempotent: a missing key is a no-op (S3/GCS/Azure delete-by-key does not
|