@f0rbit/corpus 0.1.2 → 0.1.4
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/backend/cloudflare.d.ts +40 -0
- package/dist/backend/cloudflare.d.ts.map +1 -1
- package/dist/backend/cloudflare.js +40 -0
- package/dist/backend/file.d.ts +35 -0
- package/dist/backend/file.d.ts.map +1 -1
- package/dist/backend/file.js +35 -0
- package/dist/backend/layered.d.ts +46 -0
- package/dist/backend/layered.d.ts.map +1 -0
- package/dist/backend/layered.js +193 -0
- package/dist/backend/memory.d.ts +30 -0
- package/dist/backend/memory.d.ts.map +1 -1
- package/dist/backend/memory.js +30 -0
- package/dist/backends.d.ts +11 -0
- package/dist/backends.d.ts.map +1 -0
- package/dist/backends.js +9 -0
- package/dist/cloudflare.d.ts +2 -5
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +2 -5
- package/dist/codecs.d.ts +8 -0
- package/dist/codecs.d.ts.map +1 -0
- package/dist/codecs.js +6 -0
- package/dist/core.d.ts +9 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +7 -0
- package/dist/corpus.d.ts +68 -1
- package/dist/corpus.d.ts.map +1 -1
- package/dist/corpus.js +194 -1
- package/dist/index.d.ts +4 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/schema.d.ts +27 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +27 -0
- package/dist/sst.d.ts +38 -0
- package/dist/sst.d.ts.map +1 -1
- package/dist/sst.js +38 -0
- package/dist/types.d.ts +229 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +91 -2
- package/dist/utils.d.ts +133 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +174 -0
- package/package.json +5 -2
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Types
|
|
3
|
+
* @description Type definitions for the corpus library.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Error types that can occur during Corpus operations.
|
|
7
|
+
* @category Types
|
|
8
|
+
* @group Error Types
|
|
9
|
+
*
|
|
10
|
+
* Uses discriminated unions for type-safe error handling via the `kind` field:
|
|
11
|
+
* - `not_found` - Requested snapshot or data does not exist
|
|
12
|
+
* - `already_exists` - Attempted to create a snapshot that already exists
|
|
13
|
+
* - `storage_error` - Backend storage operation failed (includes cause and operation name)
|
|
14
|
+
* - `decode_error` - Failed to decode data using the store's codec
|
|
15
|
+
* - `encode_error` - Failed to encode data using the store's codec
|
|
16
|
+
* - `hash_mismatch` - Content hash verification failed (data corruption)
|
|
17
|
+
* - `invalid_config` - Configuration error during setup
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const result = await store.get('nonexistent')
|
|
22
|
+
* if (!result.ok) {
|
|
23
|
+
* switch (result.error.kind) {
|
|
24
|
+
* case 'not_found':
|
|
25
|
+
* console.log(`Version ${result.error.version} not found`)
|
|
26
|
+
* break
|
|
27
|
+
* case 'storage_error':
|
|
28
|
+
* console.log(`Storage failed during ${result.error.operation}:`, result.error.cause)
|
|
29
|
+
* break
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
1
34
|
export type CorpusError = {
|
|
2
35
|
kind: 'not_found';
|
|
3
36
|
store_id: string;
|
|
@@ -24,6 +57,11 @@ export type CorpusError = {
|
|
|
24
57
|
kind: 'invalid_config';
|
|
25
58
|
message: string;
|
|
26
59
|
};
|
|
60
|
+
/**
|
|
61
|
+
* A discriminated union representing either success or failure.
|
|
62
|
+
* @category Types
|
|
63
|
+
* @group Result Types
|
|
64
|
+
*/
|
|
27
65
|
export type Result<T, E = CorpusError> = {
|
|
28
66
|
ok: true;
|
|
29
67
|
value: T;
|
|
@@ -31,7 +69,46 @@ export type Result<T, E = CorpusError> = {
|
|
|
31
69
|
ok: false;
|
|
32
70
|
error: E;
|
|
33
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Creates a successful Result containing a value.
|
|
74
|
+
*
|
|
75
|
+
* @category Core
|
|
76
|
+
* @group Result Helpers
|
|
77
|
+
* @param value - The success value to wrap
|
|
78
|
+
* @returns A Result with `ok: true` and the value
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* function divide(a: number, b: number): Result<number, string> {
|
|
83
|
+
* if (b === 0) return err('Division by zero')
|
|
84
|
+
* return ok(a / b)
|
|
85
|
+
* }
|
|
86
|
+
*
|
|
87
|
+
* const result = divide(10, 2)
|
|
88
|
+
* if (result.ok) {
|
|
89
|
+
* console.log(result.value) // 5
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
34
93
|
export declare const ok: <T>(value: T) => Result<T, never>;
|
|
94
|
+
/**
|
|
95
|
+
* Creates a failed Result containing an error.
|
|
96
|
+
*
|
|
97
|
+
* @category Core
|
|
98
|
+
* @group Result Helpers
|
|
99
|
+
* @param error - The error to wrap
|
|
100
|
+
* @returns A Result with `ok: false` and the error
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* function parsePositive(s: string): Result<number, string> {
|
|
105
|
+
* const n = parseInt(s, 10)
|
|
106
|
+
* if (isNaN(n)) return err('Not a number')
|
|
107
|
+
* if (n <= 0) return err('Must be positive')
|
|
108
|
+
* return ok(n)
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
35
112
|
export declare const err: <E>(error: E) => Result<never, E>;
|
|
36
113
|
export type CorpusEvent = {
|
|
37
114
|
type: 'meta_get';
|
|
@@ -87,6 +164,32 @@ export type ParentRef = {
|
|
|
87
164
|
version: string;
|
|
88
165
|
role?: string;
|
|
89
166
|
};
|
|
167
|
+
/**
|
|
168
|
+
* Metadata about a stored snapshot (without the actual data).
|
|
169
|
+
*
|
|
170
|
+
* Key fields:
|
|
171
|
+
* - `store_id` - Which store this snapshot belongs to
|
|
172
|
+
* - `version` - Unique, time-sortable identifier for this snapshot
|
|
173
|
+
* - `content_hash` - SHA-256 hash of the encoded data (enables deduplication)
|
|
174
|
+
* - `data_key` - Key to retrieve the actual data from the backend
|
|
175
|
+
* - `parents` - Links to parent snapshots for building data lineage graphs
|
|
176
|
+
* - `tags` - Optional labels for filtering and organization
|
|
177
|
+
*
|
|
178
|
+
* @category Types
|
|
179
|
+
* @group Snapshot Types
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* const result = await store.put(data, {
|
|
183
|
+
* parents: [{ store_id: 'source', version: 'abc123' }],
|
|
184
|
+
* tags: ['draft', 'reviewed']
|
|
185
|
+
* })
|
|
186
|
+
*
|
|
187
|
+
* if (result.ok) {
|
|
188
|
+
* const meta = result.value
|
|
189
|
+
* console.log(`Stored ${meta.size_bytes} bytes as version ${meta.version}`)
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
90
193
|
export type SnapshotMeta = {
|
|
91
194
|
store_id: string;
|
|
92
195
|
version: string;
|
|
@@ -129,16 +232,83 @@ export type ListOpts = {
|
|
|
129
232
|
after?: Date;
|
|
130
233
|
tags?: string[];
|
|
131
234
|
};
|
|
235
|
+
/**
|
|
236
|
+
* Interface that storage backends implement.
|
|
237
|
+
*
|
|
238
|
+
* A Backend provides two clients:
|
|
239
|
+
* - `metadata` - For storing/retrieving snapshot metadata (versions, hashes, etc.)
|
|
240
|
+
* - `data` - For storing/retrieving the actual binary content
|
|
241
|
+
*
|
|
242
|
+
* Built-in backends:
|
|
243
|
+
* - `create_memory_backend()` - In-memory, ephemeral storage
|
|
244
|
+
* - `create_file_backend()` - Local filesystem persistence
|
|
245
|
+
* - `create_cloudflare_backend()` - Cloudflare D1 + R2
|
|
246
|
+
* - `create_layered_backend()` - Combines multiple backends
|
|
247
|
+
*
|
|
248
|
+
* @category Types
|
|
249
|
+
* @group Backend Types
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* // Custom backend implementation
|
|
253
|
+
* const myBackend: Backend = {
|
|
254
|
+
* metadata: { get, put, delete, list, get_latest, get_children, find_by_hash },
|
|
255
|
+
* data: { get, put, delete, exists },
|
|
256
|
+
* on_event: (event) => console.log('Event:', event.type)
|
|
257
|
+
* }
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
132
260
|
export type Backend = {
|
|
133
261
|
metadata: MetadataClient;
|
|
134
262
|
data: DataClient;
|
|
135
263
|
on_event?: EventHandler;
|
|
136
264
|
};
|
|
265
|
+
/**
|
|
266
|
+
* Serialization interface for encoding/decoding store data.
|
|
267
|
+
*
|
|
268
|
+
* A Codec converts between typed values and binary data:
|
|
269
|
+
* - `encode` - Converts a value to bytes for storage
|
|
270
|
+
* - `decode` - Converts bytes back to a typed value
|
|
271
|
+
* - `content_type` - MIME type stored in metadata
|
|
272
|
+
*
|
|
273
|
+
* Built-in codecs:
|
|
274
|
+
* - `json_codec(schema)` - JSON with Zod validation on decode
|
|
275
|
+
* - `text_codec()` - Plain UTF-8 text
|
|
276
|
+
* - `binary_codec()` - Raw binary pass-through
|
|
277
|
+
*
|
|
278
|
+
* @category Types
|
|
279
|
+
* @group Codec Types
|
|
280
|
+
* @example
|
|
281
|
+
* ```ts
|
|
282
|
+
* // Custom codec for MessagePack
|
|
283
|
+
* const msgpack_codec = <T>(schema: ZodSchema<T>): Codec<T> => ({
|
|
284
|
+
* content_type: 'application/msgpack',
|
|
285
|
+
* encode: (value) => encode(value),
|
|
286
|
+
* decode: (bytes) => schema.parse(decode(bytes))
|
|
287
|
+
* })
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
137
290
|
export type Codec<T> = {
|
|
138
291
|
content_type: ContentType;
|
|
139
292
|
encode: (value: T) => Uint8Array;
|
|
140
293
|
decode: (bytes: Uint8Array) => T;
|
|
141
294
|
};
|
|
295
|
+
/**
|
|
296
|
+
* A typed store for managing versioned data snapshots.
|
|
297
|
+
*
|
|
298
|
+
* Stores provide the main API for reading and writing data:
|
|
299
|
+
* - `put(data, opts?)` - Store a new snapshot, returns metadata with version
|
|
300
|
+
* - `get(version)` - Retrieve a specific snapshot by version
|
|
301
|
+
* - `get_latest()` - Get the most recent snapshot
|
|
302
|
+
* - `get_meta(version)` - Get just the metadata (without data)
|
|
303
|
+
* - `list(opts?)` - Iterate over snapshot metadata with filtering
|
|
304
|
+
* - `delete(version)` - Remove a snapshot's metadata
|
|
305
|
+
*
|
|
306
|
+
* Stores automatically deduplicate: storing the same content twice creates
|
|
307
|
+
* two metadata entries pointing to the same underlying data.
|
|
308
|
+
*
|
|
309
|
+
* @category Types
|
|
310
|
+
* @group Store Types
|
|
311
|
+
*/
|
|
142
312
|
export type Store<T> = {
|
|
143
313
|
readonly id: string;
|
|
144
314
|
readonly codec: Codec<T>;
|
|
@@ -154,12 +324,70 @@ export type PutOpts = {
|
|
|
154
324
|
invoked_at?: Date;
|
|
155
325
|
tags?: string[];
|
|
156
326
|
};
|
|
327
|
+
/**
|
|
328
|
+
* Context passed to data_key_fn for generating custom storage paths.
|
|
329
|
+
*/
|
|
330
|
+
export type DataKeyContext = {
|
|
331
|
+
store_id: string;
|
|
332
|
+
version: string;
|
|
333
|
+
content_hash: string;
|
|
334
|
+
tags?: string[];
|
|
335
|
+
};
|
|
157
336
|
export type StoreDefinition<Id extends string, T> = {
|
|
158
337
|
id: Id;
|
|
159
338
|
codec: Codec<T>;
|
|
160
339
|
description?: string;
|
|
340
|
+
/** Custom function to generate data_key (storage path). If not provided, uses `store_id/content_hash`. */
|
|
341
|
+
data_key_fn?: (ctx: DataKeyContext) => string;
|
|
342
|
+
};
|
|
343
|
+
export type DefineStoreOpts = {
|
|
344
|
+
description?: string;
|
|
345
|
+
/** Custom function to generate data_key (storage path). If not provided, uses `store_id/content_hash`. */
|
|
346
|
+
data_key_fn?: (ctx: DataKeyContext) => string;
|
|
161
347
|
};
|
|
162
|
-
|
|
348
|
+
/**
|
|
349
|
+
* Helper to define a type-safe store definition.
|
|
350
|
+
*
|
|
351
|
+
* The `id` becomes the key in `corpus.stores`, providing type-safe access
|
|
352
|
+
* to the store after building the corpus.
|
|
353
|
+
*
|
|
354
|
+
* @category Core
|
|
355
|
+
* @group Helpers
|
|
356
|
+
* @param id - Unique identifier for the store (becomes the key in corpus.stores)
|
|
357
|
+
* @param codec - Serialization codec for the store's data type
|
|
358
|
+
* @param opts - Optional configuration (description, custom data_key_fn)
|
|
359
|
+
* @returns A StoreDefinition to pass to `create_corpus().with_store()`
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* import { z } from 'zod'
|
|
364
|
+
*
|
|
365
|
+
* const PostSchema = z.object({
|
|
366
|
+
* title: z.string(),
|
|
367
|
+
* body: z.string(),
|
|
368
|
+
* published: z.boolean()
|
|
369
|
+
* })
|
|
370
|
+
*
|
|
371
|
+
* const posts = define_store('posts', json_codec(PostSchema), { description: 'Blog posts' })
|
|
372
|
+
*
|
|
373
|
+
* // With custom path generation based on tags
|
|
374
|
+
* const hansard = define_store('hansard', text_codec(), {
|
|
375
|
+
* data_key_fn: (ctx) => {
|
|
376
|
+
* const date = ctx.tags?.find(t => t.startsWith('date:'))?.slice(5) ?? 'unknown'
|
|
377
|
+
* return `australia-house/raw/${date}/${ctx.version}`
|
|
378
|
+
* }
|
|
379
|
+
* })
|
|
380
|
+
*
|
|
381
|
+
* const corpus = create_corpus()
|
|
382
|
+
* .with_backend(backend)
|
|
383
|
+
* .with_store(posts)
|
|
384
|
+
* .build()
|
|
385
|
+
*
|
|
386
|
+
* // Type-safe: corpus.stores.posts expects Post type
|
|
387
|
+
* await corpus.stores.posts.put({ title: 'Hello', body: '...', published: true })
|
|
388
|
+
* ```
|
|
389
|
+
*/
|
|
390
|
+
export declare function define_store<Id extends string, T>(id: Id, codec: Codec<T>, opts?: DefineStoreOpts | string): StoreDefinition<Id, T>;
|
|
163
391
|
export type CorpusBuilder<Stores extends Record<string, Store<any>> = {}> = {
|
|
164
392
|
with_backend: (backend: Backend) => CorpusBuilder<Stores>;
|
|
165
393
|
with_store: <Id extends string, T>(definition: StoreDefinition<Id, T>) => CorpusBuilder<Stores & Record<Id, Store<T>>>;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Types
|
|
3
|
+
* @description Type definitions for the corpus library.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Creates a successful Result containing a value.
|
|
7
|
+
*
|
|
8
|
+
* @category Core
|
|
9
|
+
* @group Result Helpers
|
|
10
|
+
* @param value - The success value to wrap
|
|
11
|
+
* @returns A Result with `ok: true` and the value
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* function divide(a: number, b: number): Result<number, string> {
|
|
16
|
+
* if (b === 0) return err('Division by zero')
|
|
17
|
+
* return ok(a / b)
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* const result = divide(10, 2)
|
|
21
|
+
* if (result.ok) {
|
|
22
|
+
* console.log(result.value) // 5
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
1
26
|
export const ok = (value) => ({ ok: true, value });
|
|
27
|
+
/**
|
|
28
|
+
* Creates a failed Result containing an error.
|
|
29
|
+
*
|
|
30
|
+
* @category Core
|
|
31
|
+
* @group Result Helpers
|
|
32
|
+
* @param error - The error to wrap
|
|
33
|
+
* @returns A Result with `ok: false` and the error
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* function parsePositive(s: string): Result<number, string> {
|
|
38
|
+
* const n = parseInt(s, 10)
|
|
39
|
+
* if (isNaN(n)) return err('Not a number')
|
|
40
|
+
* if (n <= 0) return err('Must be positive')
|
|
41
|
+
* return ok(n)
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
2
45
|
export const err = (error) => ({ ok: false, error });
|
|
3
|
-
|
|
4
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Helper to define a type-safe store definition.
|
|
48
|
+
*
|
|
49
|
+
* The `id` becomes the key in `corpus.stores`, providing type-safe access
|
|
50
|
+
* to the store after building the corpus.
|
|
51
|
+
*
|
|
52
|
+
* @category Core
|
|
53
|
+
* @group Helpers
|
|
54
|
+
* @param id - Unique identifier for the store (becomes the key in corpus.stores)
|
|
55
|
+
* @param codec - Serialization codec for the store's data type
|
|
56
|
+
* @param opts - Optional configuration (description, custom data_key_fn)
|
|
57
|
+
* @returns A StoreDefinition to pass to `create_corpus().with_store()`
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { z } from 'zod'
|
|
62
|
+
*
|
|
63
|
+
* const PostSchema = z.object({
|
|
64
|
+
* title: z.string(),
|
|
65
|
+
* body: z.string(),
|
|
66
|
+
* published: z.boolean()
|
|
67
|
+
* })
|
|
68
|
+
*
|
|
69
|
+
* const posts = define_store('posts', json_codec(PostSchema), { description: 'Blog posts' })
|
|
70
|
+
*
|
|
71
|
+
* // With custom path generation based on tags
|
|
72
|
+
* const hansard = define_store('hansard', text_codec(), {
|
|
73
|
+
* data_key_fn: (ctx) => {
|
|
74
|
+
* const date = ctx.tags?.find(t => t.startsWith('date:'))?.slice(5) ?? 'unknown'
|
|
75
|
+
* return `australia-house/raw/${date}/${ctx.version}`
|
|
76
|
+
* }
|
|
77
|
+
* })
|
|
78
|
+
*
|
|
79
|
+
* const corpus = create_corpus()
|
|
80
|
+
* .with_backend(backend)
|
|
81
|
+
* .with_store(posts)
|
|
82
|
+
* .build()
|
|
83
|
+
*
|
|
84
|
+
* // Type-safe: corpus.stores.posts expects Post type
|
|
85
|
+
* await corpus.stores.posts.put({ title: 'Hello', body: '...', published: true })
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export function define_store(id, codec, opts) {
|
|
89
|
+
// Support old signature: define_store(id, codec, description)
|
|
90
|
+
if (typeof opts === 'string') {
|
|
91
|
+
return { id, codec, description: opts };
|
|
92
|
+
}
|
|
93
|
+
return { id, codec, description: opts?.description, data_key_fn: opts?.data_key_fn };
|
|
5
94
|
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Utilities
|
|
3
|
+
* @description Utility functions for hashing, versioning, and codecs.
|
|
4
|
+
*/
|
|
5
|
+
import type { Codec } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Computes the SHA-256 hash of binary data.
|
|
8
|
+
* @category Utilities
|
|
9
|
+
* @group Hashing
|
|
10
|
+
*
|
|
11
|
+
* Returns a lowercase hexadecimal string (64 characters).
|
|
12
|
+
* Used internally for content-addressable storage and deduplication.
|
|
13
|
+
*
|
|
14
|
+
* @param data - The binary data to hash
|
|
15
|
+
* @returns A lowercase hex string of the SHA-256 hash
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const data = new TextEncoder().encode('Hello, world!')
|
|
20
|
+
* const hash = await compute_hash(data)
|
|
21
|
+
* // => '315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3'
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function compute_hash(data: Uint8Array): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Generates a unique, time-sortable version string.
|
|
27
|
+
*
|
|
28
|
+
* Format: base64url-encoded timestamp, with optional `.N` suffix when multiple
|
|
29
|
+
* versions are generated within the same millisecond.
|
|
30
|
+
*
|
|
31
|
+
* Versions sort lexicographically in chronological order, making them suitable
|
|
32
|
+
* for use as database keys where ordering matters.
|
|
33
|
+
*
|
|
34
|
+
* @category Utilities
|
|
35
|
+
* @group Versioning
|
|
36
|
+
* @returns A unique version string like `AZJx4vM` or `AZJx4vM.1`
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* const v1 = generate_version() // => 'AZJx4vM'
|
|
41
|
+
* const v2 = generate_version() // => 'AZJx4vM.1' (same millisecond)
|
|
42
|
+
* const v3 = generate_version() // => 'AZJx4vN' (next millisecond)
|
|
43
|
+
*
|
|
44
|
+
* // Versions sort chronologically
|
|
45
|
+
* [v3, v1, v2].sort() // => [v1, v2, v3]
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function generate_version(): string;
|
|
49
|
+
type ZodLike<T> = {
|
|
50
|
+
parse: (data: unknown) => T;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Creates a JSON codec with schema validation.
|
|
54
|
+
*
|
|
55
|
+
* Data is serialized to JSON on encode and validated against the schema on decode.
|
|
56
|
+
* Works with both Zod 3.x and 4.x (uses structural typing, not Zod imports).
|
|
57
|
+
*
|
|
58
|
+
* Note: Validation only happens on decode. Invalid data passed to encode will
|
|
59
|
+
* serialize but may fail validation when decoded later.
|
|
60
|
+
*
|
|
61
|
+
* @category Codecs
|
|
62
|
+
* @group Codec Factories
|
|
63
|
+
* @param schema - A Zod schema (or any object with a `parse` method)
|
|
64
|
+
* @returns A Codec for JSON serialization with validation
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { z } from 'zod'
|
|
69
|
+
*
|
|
70
|
+
* const UserSchema = z.object({
|
|
71
|
+
* id: z.string().uuid(),
|
|
72
|
+
* name: z.string(),
|
|
73
|
+
* createdAt: z.coerce.date()
|
|
74
|
+
* })
|
|
75
|
+
*
|
|
76
|
+
* const codec = json_codec(UserSchema)
|
|
77
|
+
* const users = define_store('users', codec)
|
|
78
|
+
*
|
|
79
|
+
* // Decoding validates and transforms data
|
|
80
|
+
* const bytes = codec.encode({ id: '...', name: 'Alice', createdAt: '2024-01-01' })
|
|
81
|
+
* const user = codec.decode(bytes) // createdAt is now a Date object
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function json_codec<T>(schema: ZodLike<T>): Codec<T>;
|
|
85
|
+
/**
|
|
86
|
+
* Creates a plain text codec using UTF-8 encoding.
|
|
87
|
+
*
|
|
88
|
+
* No validation is performed - any string can be encoded and any valid
|
|
89
|
+
* UTF-8 bytes can be decoded.
|
|
90
|
+
*
|
|
91
|
+
* @category Codecs
|
|
92
|
+
* @group Codec Factories
|
|
93
|
+
* @returns A Codec for plain text strings
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const notes = define_store('notes', text_codec())
|
|
98
|
+
*
|
|
99
|
+
* await corpus.stores.notes.put('Meeting notes for 2024-01-15...')
|
|
100
|
+
*
|
|
101
|
+
* const result = await corpus.stores.notes.get_latest()
|
|
102
|
+
* if (result.ok) {
|
|
103
|
+
* console.log(result.value.data) // string
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export declare function text_codec(): Codec<string>;
|
|
108
|
+
/**
|
|
109
|
+
* Creates a pass-through codec for raw binary data.
|
|
110
|
+
*
|
|
111
|
+
* No transformation is performed - bytes are stored and retrieved as-is.
|
|
112
|
+
* Use for images, PDFs, pre-serialized data, or any binary content.
|
|
113
|
+
*
|
|
114
|
+
* @category Codecs
|
|
115
|
+
* @group Codec Factories
|
|
116
|
+
* @returns A Codec for raw binary data
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* const images = define_store('images', binary_codec())
|
|
121
|
+
*
|
|
122
|
+
* // Store an image
|
|
123
|
+
* const imageData = await fetch('photo.png').then(r => r.arrayBuffer())
|
|
124
|
+
* await corpus.stores.images.put(new Uint8Array(imageData))
|
|
125
|
+
*
|
|
126
|
+
* // Store pre-serialized protobuf
|
|
127
|
+
* const protoBytes = MyMessage.encode(message).finish()
|
|
128
|
+
* await corpus.stores.images.put(protoBytes)
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export declare function binary_codec(): Codec<Uint8Array>;
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAIpE;AAKD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CA0BzC;AAGD,KAAK,OAAO,CAAC,CAAC,IAAI;IAAE,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,CAAC,CAAA;CAAE,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAM1D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC,CAM1C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,YAAY,IAAI,KAAK,CAAC,UAAU,CAAC,CAMhD"}
|