@f0rbit/corpus 0.1.9 → 0.2.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.
- package/dist/backend/base.d.ts +23 -0
- package/dist/backend/base.d.ts.map +1 -0
- package/dist/backend/base.js +100 -0
- package/dist/backend/file.d.ts.map +1 -1
- package/dist/backend/file.js +38 -76
- package/dist/backend/memory.d.ts.map +1 -1
- package/dist/backend/memory.js +18 -69
- package/dist/backends.d.ts +1 -0
- package/dist/backends.d.ts.map +1 -1
- package/dist/backends.js +1 -0
- package/dist/cloudflare.d.ts +1 -0
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +1 -0
- package/dist/concurrency.d.ts +78 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +108 -0
- package/dist/index.d.ts +13 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -10
- package/dist/observations/index.d.ts +1 -1
- package/dist/observations/index.d.ts.map +1 -1
- package/dist/observations/storage.d.ts +33 -4
- package/dist/observations/storage.d.ts.map +1 -1
- package/dist/observations/storage.js +63 -43
- package/dist/result.d.ts +280 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +319 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +39 -6
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +47 -15
- package/package.json +1 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Concurrency
|
|
3
|
+
* @description Utilities for controlling concurrent async operations.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Semaphore for controlling concurrent operations.
|
|
7
|
+
*
|
|
8
|
+
* Limits the number of concurrent async operations by requiring
|
|
9
|
+
* callers to acquire a permit before proceeding. When all permits
|
|
10
|
+
* are taken, subsequent acquires wait until a permit is released.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const semaphore = new Semaphore(3) // Allow 3 concurrent operations
|
|
15
|
+
*
|
|
16
|
+
* async function rateLimitedFetch(url: string) {
|
|
17
|
+
* await semaphore.acquire()
|
|
18
|
+
* try {
|
|
19
|
+
* return await fetch(url)
|
|
20
|
+
* } finally {
|
|
21
|
+
* semaphore.release()
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* // Only 3 fetches will run concurrently
|
|
26
|
+
* await Promise.all(urls.map(rateLimitedFetch))
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export class Semaphore {
|
|
30
|
+
permits;
|
|
31
|
+
waiting = [];
|
|
32
|
+
constructor(permits) {
|
|
33
|
+
this.permits = permits;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Acquire a permit. Resolves immediately if available,
|
|
37
|
+
* otherwise waits until a permit is released.
|
|
38
|
+
*/
|
|
39
|
+
async acquire() {
|
|
40
|
+
if (this.permits > 0) {
|
|
41
|
+
this.permits--;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
return new Promise(resolve => {
|
|
45
|
+
this.waiting.push(resolve);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Release a permit, allowing the next waiting operation to proceed.
|
|
50
|
+
*/
|
|
51
|
+
release() {
|
|
52
|
+
const next = this.waiting.shift();
|
|
53
|
+
if (next) {
|
|
54
|
+
next();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.permits++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Map over array with controlled concurrency.
|
|
63
|
+
*
|
|
64
|
+
* Unlike Promise.all which starts all operations at once, this limits
|
|
65
|
+
* concurrent operations. Results are returned in the same order as inputs.
|
|
66
|
+
*
|
|
67
|
+
* @param items - Array of items to process
|
|
68
|
+
* @param mapper - Async function to apply to each item
|
|
69
|
+
* @param concurrency - Maximum number of concurrent operations
|
|
70
|
+
* @returns Array of results in the same order as inputs
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* // Process 100 items, but only 5 at a time
|
|
75
|
+
* const results = await parallel_map(
|
|
76
|
+
* urls,
|
|
77
|
+
* async (url, index) => {
|
|
78
|
+
* console.log(`Fetching ${index + 1}/${urls.length}`)
|
|
79
|
+
* return fetch(url).then(r => r.json())
|
|
80
|
+
* },
|
|
81
|
+
* 5
|
|
82
|
+
* )
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* // Use with AI APIs that have rate limits
|
|
88
|
+
* const summaries = await parallel_map(
|
|
89
|
+
* documents,
|
|
90
|
+
* doc => summarize(doc),
|
|
91
|
+
* 3 // Only 3 concurrent API calls
|
|
92
|
+
* )
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export const parallel_map = async (items, mapper, concurrency) => {
|
|
96
|
+
const semaphore = new Semaphore(concurrency);
|
|
97
|
+
const results = new Array(items.length);
|
|
98
|
+
await Promise.all(items.map(async (item, index) => {
|
|
99
|
+
await semaphore.acquire();
|
|
100
|
+
try {
|
|
101
|
+
results[index] = await mapper(item, index);
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
semaphore.release();
|
|
105
|
+
}
|
|
106
|
+
}));
|
|
107
|
+
return results;
|
|
108
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
export { create_corpus, create_store } from
|
|
2
|
-
export { create_memory_backend, type MemoryBackendOptions } from
|
|
3
|
-
export { create_file_backend, type FileBackendConfig } from
|
|
4
|
-
export { create_cloudflare_backend, type CloudflareBackendConfig } from
|
|
5
|
-
export { create_layered_backend, type LayeredBackendOptions } from
|
|
6
|
-
export { json_codec, text_codec, binary_codec, compute_hash, generate_version } from
|
|
7
|
-
export { corpus_snapshots, type CorpusSnapshotRow, type CorpusSnapshotInsert } from
|
|
8
|
-
export type { ContentType, ParentRef, SnapshotMeta, Snapshot, DataHandle, MetadataClient, DataClient, ListOpts, Backend, Codec, Store, StoreDefinition, DefineStoreOpts, DataKeyContext, PutOpts, CorpusBuilder, Corpus, CorpusError, Result, CorpusEvent, EventHandler, ObservationsClient, } from
|
|
9
|
-
export { ok, err, define_store } from
|
|
10
|
-
export
|
|
11
|
-
export {
|
|
1
|
+
export { create_corpus, create_store } from "./corpus";
|
|
2
|
+
export { create_memory_backend, type MemoryBackendOptions } from "./backend/memory";
|
|
3
|
+
export { create_file_backend, type FileBackendConfig } from "./backend/file";
|
|
4
|
+
export { create_cloudflare_backend, type CloudflareBackendConfig } from "./backend/cloudflare";
|
|
5
|
+
export { create_layered_backend, type LayeredBackendOptions } from "./backend/layered";
|
|
6
|
+
export { json_codec, text_codec, binary_codec, compute_hash, generate_version } from "./utils";
|
|
7
|
+
export { corpus_snapshots, type CorpusSnapshotRow, type CorpusSnapshotInsert } from "./schema";
|
|
8
|
+
export type { ContentType, ParentRef, SnapshotMeta, Snapshot, DataHandle, MetadataClient, DataClient, ListOpts, Backend, Codec, Parser, Store, StoreDefinition, DefineStoreOpts, DataKeyContext, PutOpts, CorpusBuilder, Corpus, CorpusError, Result, CorpusEvent, EventHandler, ObservationsClient, } from "./types";
|
|
9
|
+
export { ok, err, define_store } from "./types";
|
|
10
|
+
export { match, unwrap_or, unwrap, unwrap_err, try_catch, try_catch_async, fetch_result, pipe, to_nullable, to_fallback, null_on, fallback_on, format_error, type FetchError, type Pipe, } from "./result";
|
|
11
|
+
export { Semaphore, parallel_map } from "./concurrency";
|
|
12
|
+
export * from "./observations";
|
|
13
|
+
export { createCorpusInfra, CORPUS_MIGRATION_SQL, type CorpusInfra, type CorpusInfraConfig } from "./sst";
|
|
12
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEvD,OAAO,EAAE,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAEvF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE/F,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAE/F,YAAY,EACX,WAAW,EACX,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,cAAc,EACd,UAAU,EACV,QAAQ,EACR,OAAO,EACP,KAAK,EACL,MAAM,EACN,KAAK,EACL,eAAe,EACf,eAAe,EACf,cAAc,EACd,OAAO,EACP,aAAa,EACb,MAAM,EACN,WAAW,EACX,MAAM,EACN,WAAW,EACX,YAAY,EACZ,kBAAkB,GAClB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,EACN,KAAK,EACL,SAAS,EACT,MAAM,EACN,UAAU,EACV,SAAS,EACT,eAAe,EACf,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,WAAW,EACX,OAAO,EACP,WAAW,EACX,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,IAAI,GACT,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAExD,cAAc,gBAAgB,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export { create_corpus, create_store } from
|
|
2
|
-
export { create_memory_backend } from
|
|
3
|
-
export { create_file_backend } from
|
|
4
|
-
export { create_cloudflare_backend } from
|
|
5
|
-
export { create_layered_backend } from
|
|
6
|
-
export { json_codec, text_codec, binary_codec, compute_hash, generate_version } from
|
|
7
|
-
export { corpus_snapshots } from
|
|
8
|
-
export { ok, err, define_store } from
|
|
9
|
-
export
|
|
10
|
-
export {
|
|
1
|
+
export { create_corpus, create_store } from "./corpus";
|
|
2
|
+
export { create_memory_backend } from "./backend/memory";
|
|
3
|
+
export { create_file_backend } from "./backend/file";
|
|
4
|
+
export { create_cloudflare_backend } from "./backend/cloudflare";
|
|
5
|
+
export { create_layered_backend } from "./backend/layered";
|
|
6
|
+
export { json_codec, text_codec, binary_codec, compute_hash, generate_version } from "./utils";
|
|
7
|
+
export { corpus_snapshots } from "./schema";
|
|
8
|
+
export { ok, err, define_store } from "./types";
|
|
9
|
+
export { match, unwrap_or, unwrap, unwrap_err, try_catch, try_catch_async, fetch_result, pipe, to_nullable, to_fallback, null_on, fallback_on, format_error, } from "./result";
|
|
10
|
+
export { Semaphore, parallel_map } from "./concurrency";
|
|
11
|
+
export * from "./observations";
|
|
12
|
+
export { createCorpusInfra, CORPUS_MIGRATION_SQL } from "./sst";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
export * from './types';
|
|
6
6
|
export type { ObservationRow, ObservationInsert } from './schema';
|
|
7
7
|
export { corpus_observations } from './schema';
|
|
8
|
-
export type { ObservationsStorage, StorageQueryOpts, ObservationsCRUD } from './storage';
|
|
8
|
+
export type { ObservationsStorage, StorageQueryOpts, ObservationsCRUD, ObservationsAdapter, ObservationsCRUDBase, ObservationsCRUDOptimized } from './storage';
|
|
9
9
|
export { row_to_observation, row_to_meta, create_observation_row, filter_observation_rows, create_observations_storage } from './storage';
|
|
10
10
|
export { create_observations_client } from './client';
|
|
11
11
|
export * from './utils';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../observations/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../observations/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAA;AACvB,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAA;AAG9J,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAA;AACzI,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAA;AACrD,cAAc,SAAS,CAAA"}
|
|
@@ -58,7 +58,31 @@ export declare function create_observation_row(id: string, type_name: string, so
|
|
|
58
58
|
*/
|
|
59
59
|
export declare function filter_observation_rows(rows: ObservationRow[], opts?: StorageQueryOpts): ObservationRow[];
|
|
60
60
|
/**
|
|
61
|
-
*
|
|
61
|
+
* Base CRUD operations for observation storage backends.
|
|
62
|
+
* All backends must implement at minimum these operations.
|
|
63
|
+
*/
|
|
64
|
+
export type ObservationsCRUDBase = {
|
|
65
|
+
get_all: () => Promise<ObservationRow[]>;
|
|
66
|
+
set_all: (rows: ObservationRow[]) => Promise<void>;
|
|
67
|
+
get_one: (id: string) => Promise<ObservationRow | null>;
|
|
68
|
+
add_one: (row: ObservationRow) => Promise<Result<void, CorpusError>>;
|
|
69
|
+
remove_one: (id: string) => Promise<Result<boolean, CorpusError>>;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Optional optimized operations for backends with native query capabilities.
|
|
73
|
+
* When provided, these are used instead of loading all rows into memory.
|
|
74
|
+
*/
|
|
75
|
+
export type ObservationsCRUDOptimized = {
|
|
76
|
+
query: (opts: StorageQueryOpts) => AsyncIterable<ObservationRow>;
|
|
77
|
+
delete_by_source: (store_id: string, version: string, path?: string) => Promise<Result<number, CorpusError>>;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Storage adapter interface for observation backends.
|
|
81
|
+
* Backends provide base CRUD operations and optionally optimized operations.
|
|
82
|
+
*/
|
|
83
|
+
export type ObservationsAdapter = ObservationsCRUDBase & Partial<ObservationsCRUDOptimized>;
|
|
84
|
+
/**
|
|
85
|
+
* @deprecated Use ObservationsAdapter instead
|
|
62
86
|
*/
|
|
63
87
|
export type ObservationsCRUD = {
|
|
64
88
|
get_all: () => Promise<ObservationRow[]>;
|
|
@@ -68,8 +92,13 @@ export type ObservationsCRUD = {
|
|
|
68
92
|
remove_one: (id: string) => Promise<boolean>;
|
|
69
93
|
};
|
|
70
94
|
/**
|
|
71
|
-
* Create an ObservationsStorage from
|
|
72
|
-
*
|
|
95
|
+
* Create an ObservationsStorage from an adapter.
|
|
96
|
+
*
|
|
97
|
+
* Backends provide simple CRUD operations and optionally optimized query/delete operations.
|
|
98
|
+
* When optimized operations are not provided, falls back to loading all rows into memory.
|
|
99
|
+
*
|
|
100
|
+
* @param adapter - Storage adapter with base CRUD and optional optimized operations
|
|
101
|
+
* @returns ObservationsStorage interface for use with create_observations_client
|
|
73
102
|
*/
|
|
74
|
-
export declare function create_observations_storage(
|
|
103
|
+
export declare function create_observations_storage(adapter: ObservationsAdapter | ObservationsCRUD): ObservationsStorage;
|
|
75
104
|
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../observations/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../observations/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @description Raw storage interface and row conversion utilities for observations.
|
|
4
4
|
*/
|
|
5
5
|
import { ok } from '../types';
|
|
6
|
+
import { create_filter_pipeline } from '../utils';
|
|
6
7
|
/**
|
|
7
8
|
* Extract common fields from an observation row (everything except content).
|
|
8
9
|
* Used internally by row_to_observation and row_to_meta.
|
|
@@ -63,74 +64,93 @@ export function create_observation_row(id, type_name, source, content, opts) {
|
|
|
63
64
|
derived_from: opts.derived_from ? JSON.stringify(opts.derived_from) : null
|
|
64
65
|
};
|
|
65
66
|
}
|
|
67
|
+
const observation_filter_pipeline = create_filter_pipeline({
|
|
68
|
+
filters: [
|
|
69
|
+
{
|
|
70
|
+
key: 'type',
|
|
71
|
+
predicate: (r, type) => {
|
|
72
|
+
const types = Array.isArray(type) ? type : [type];
|
|
73
|
+
return types.includes(r.type);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{ key: 'source_store_id', predicate: (r, id) => r.source_store_id === id },
|
|
77
|
+
{ key: 'source_version', predicate: (r, version) => r.source_version === version },
|
|
78
|
+
{ key: 'source_prefix', predicate: (r, prefix) => r.source_version.startsWith(prefix) },
|
|
79
|
+
{ key: 'created_after', predicate: (r, after) => r.created_at > after },
|
|
80
|
+
{ key: 'created_before', predicate: (r, before) => r.created_at < before },
|
|
81
|
+
{ key: 'observed_after', predicate: (r, after) => r.observed_at !== null && r.observed_at > after },
|
|
82
|
+
{ key: 'observed_before', predicate: (r, before) => r.observed_at !== null && r.observed_at < before }
|
|
83
|
+
],
|
|
84
|
+
sort: (a, b) => b.created_at.localeCompare(a.created_at)
|
|
85
|
+
});
|
|
66
86
|
/**
|
|
67
87
|
* Filter and sort observation rows based on query options.
|
|
68
88
|
* Used by in-memory storage implementations (memory backend, file backend).
|
|
69
89
|
*/
|
|
70
90
|
export function filter_observation_rows(rows, opts = {}) {
|
|
71
|
-
|
|
72
|
-
if (opts.type) {
|
|
73
|
-
const types = Array.isArray(opts.type) ? opts.type : [opts.type];
|
|
74
|
-
filtered = filtered.filter(r => types.includes(r.type));
|
|
75
|
-
}
|
|
76
|
-
if (opts.source_store_id) {
|
|
77
|
-
filtered = filtered.filter(r => r.source_store_id === opts.source_store_id);
|
|
78
|
-
}
|
|
79
|
-
if (opts.source_version) {
|
|
80
|
-
filtered = filtered.filter(r => r.source_version === opts.source_version);
|
|
81
|
-
}
|
|
82
|
-
if (opts.source_prefix) {
|
|
83
|
-
filtered = filtered.filter(r => r.source_version.startsWith(opts.source_prefix));
|
|
84
|
-
}
|
|
85
|
-
if (opts.created_after) {
|
|
86
|
-
filtered = filtered.filter(r => r.created_at > opts.created_after);
|
|
87
|
-
}
|
|
88
|
-
if (opts.created_before) {
|
|
89
|
-
filtered = filtered.filter(r => r.created_at < opts.created_before);
|
|
90
|
-
}
|
|
91
|
-
if (opts.observed_after) {
|
|
92
|
-
filtered = filtered.filter(r => r.observed_at && r.observed_at > opts.observed_after);
|
|
93
|
-
}
|
|
94
|
-
if (opts.observed_before) {
|
|
95
|
-
filtered = filtered.filter(r => r.observed_at && r.observed_at < opts.observed_before);
|
|
96
|
-
}
|
|
97
|
-
filtered.sort((a, b) => b.created_at.localeCompare(a.created_at));
|
|
98
|
-
if (opts.limit) {
|
|
99
|
-
filtered = filtered.slice(0, opts.limit);
|
|
100
|
-
}
|
|
101
|
-
return filtered;
|
|
91
|
+
return observation_filter_pipeline(rows, opts);
|
|
102
92
|
}
|
|
103
93
|
/**
|
|
104
|
-
* Create an ObservationsStorage from
|
|
105
|
-
*
|
|
94
|
+
* Create an ObservationsStorage from an adapter.
|
|
95
|
+
*
|
|
96
|
+
* Backends provide simple CRUD operations and optionally optimized query/delete operations.
|
|
97
|
+
* When optimized operations are not provided, falls back to loading all rows into memory.
|
|
98
|
+
*
|
|
99
|
+
* @param adapter - Storage adapter with base CRUD and optional optimized operations
|
|
100
|
+
* @returns ObservationsStorage interface for use with create_observations_client
|
|
106
101
|
*/
|
|
107
|
-
export function create_observations_storage(
|
|
102
|
+
export function create_observations_storage(adapter) {
|
|
103
|
+
const wrap_add_one = async (row) => {
|
|
104
|
+
const result = await adapter.add_one(row);
|
|
105
|
+
if (result === undefined || result === null)
|
|
106
|
+
return ok(undefined);
|
|
107
|
+
if (typeof result === 'object' && 'ok' in result)
|
|
108
|
+
return result;
|
|
109
|
+
return ok(undefined);
|
|
110
|
+
};
|
|
111
|
+
const wrap_remove_one = async (id) => {
|
|
112
|
+
const result = await adapter.remove_one(id);
|
|
113
|
+
if (typeof result === 'boolean')
|
|
114
|
+
return ok(result);
|
|
115
|
+
if (typeof result === 'object' && 'ok' in result)
|
|
116
|
+
return result;
|
|
117
|
+
return ok(false);
|
|
118
|
+
};
|
|
108
119
|
return {
|
|
109
120
|
async put_row(row) {
|
|
110
|
-
await
|
|
121
|
+
const result = await wrap_add_one(row);
|
|
122
|
+
if (!result.ok)
|
|
123
|
+
return result;
|
|
111
124
|
return ok(row);
|
|
112
125
|
},
|
|
113
126
|
async get_row(id) {
|
|
114
|
-
const row = await
|
|
127
|
+
const row = await adapter.get_one(id);
|
|
115
128
|
return ok(row);
|
|
116
129
|
},
|
|
117
130
|
async *query_rows(opts = {}) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
131
|
+
if (adapter.query) {
|
|
132
|
+
yield* adapter.query(opts);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const rows = filter_observation_rows(await adapter.get_all(), opts);
|
|
136
|
+
for (const row of rows) {
|
|
137
|
+
yield row;
|
|
138
|
+
}
|
|
121
139
|
}
|
|
122
140
|
},
|
|
123
141
|
async delete_row(id) {
|
|
124
|
-
|
|
125
|
-
return ok(deleted);
|
|
142
|
+
return wrap_remove_one(id);
|
|
126
143
|
},
|
|
127
144
|
async delete_by_source(store_id, version, path) {
|
|
128
|
-
|
|
145
|
+
if (adapter.delete_by_source) {
|
|
146
|
+
return adapter.delete_by_source(store_id, version, path);
|
|
147
|
+
}
|
|
148
|
+
const rows = await adapter.get_all();
|
|
129
149
|
const toKeep = rows.filter(r => !(r.source_store_id === store_id &&
|
|
130
150
|
r.source_version === version &&
|
|
131
151
|
(path === undefined || r.source_path === path)));
|
|
132
152
|
const deleted = rows.length - toKeep.length;
|
|
133
|
-
await
|
|
153
|
+
await adapter.set_all(toKeep);
|
|
134
154
|
return ok(deleted);
|
|
135
155
|
}
|
|
136
156
|
};
|
package/dist/result.d.ts
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Result
|
|
3
|
+
* @description Extended utilities for working with Result types.
|
|
4
|
+
*
|
|
5
|
+
* Provides functional utilities for error handling without exceptions:
|
|
6
|
+
* - Pattern matching with `match`
|
|
7
|
+
* - Safe unwrapping with `unwrap_or`, `unwrap`, `unwrap_err`
|
|
8
|
+
* - Exception-to-Result conversion with `try_catch`, `try_catch_async`
|
|
9
|
+
* - Fetch wrapper with `fetch_result`
|
|
10
|
+
* - Composable pipelines with `pipe`
|
|
11
|
+
*/
|
|
12
|
+
import { type Result } from "./types";
|
|
13
|
+
/**
|
|
14
|
+
* Pattern match on a Result, extracting the value with appropriate handler.
|
|
15
|
+
*
|
|
16
|
+
* @param result - The Result to match on
|
|
17
|
+
* @param on_ok - Handler for success case
|
|
18
|
+
* @param on_err - Handler for error case
|
|
19
|
+
* @returns The return value of the matching handler
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const result = await fetchUser(id)
|
|
24
|
+
* const message = match(
|
|
25
|
+
* result,
|
|
26
|
+
* user => `Hello, ${user.name}!`,
|
|
27
|
+
* error => `Failed: ${error.message}`
|
|
28
|
+
* )
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const match: <T, E, R>(result: Result<T, E>, on_ok: (value: T) => R, on_err: (error: E) => R) => R;
|
|
32
|
+
/**
|
|
33
|
+
* Extract value from Result, returning default if error.
|
|
34
|
+
*
|
|
35
|
+
* @param result - The Result to unwrap
|
|
36
|
+
* @param default_value - Value to return if Result is an error
|
|
37
|
+
* @returns The success value or default
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* const users = unwrap_or(await fetchUsers(), [])
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare const unwrap_or: <T, E>(result: Result<T, E>, default_value: T) => T;
|
|
45
|
+
/**
|
|
46
|
+
* Extract value from Result, throwing if error.
|
|
47
|
+
* Use only when you're certain the Result is Ok, or in tests.
|
|
48
|
+
*
|
|
49
|
+
* @param result - The Result to unwrap
|
|
50
|
+
* @returns The success value
|
|
51
|
+
* @throws Error if Result is an error
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* // In tests
|
|
56
|
+
* const user = unwrap(await createUser(data))
|
|
57
|
+
* expect(user.name).toBe('Alice')
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare const unwrap: <T, E>(result: Result<T, E>) => T;
|
|
61
|
+
/**
|
|
62
|
+
* Extract error from Result, throwing if Ok.
|
|
63
|
+
* Use only when you're certain the Result is Err, or in tests.
|
|
64
|
+
*
|
|
65
|
+
* @param result - The Result to unwrap
|
|
66
|
+
* @returns The error value
|
|
67
|
+
* @throws Error if Result is Ok
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* // In tests
|
|
72
|
+
* const error = unwrap_err(await createUser(invalidData))
|
|
73
|
+
* expect(error.kind).toBe('validation_error')
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare const unwrap_err: <T, E>(result: Result<T, E>) => E;
|
|
77
|
+
/**
|
|
78
|
+
* Execute a function and convert exceptions to Result.
|
|
79
|
+
*
|
|
80
|
+
* @param fn - Function to execute
|
|
81
|
+
* @param on_error - Transform caught exception to error type
|
|
82
|
+
* @returns Result containing success value or transformed error
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const result = try_catch(
|
|
87
|
+
* () => JSON.parse(input),
|
|
88
|
+
* e => ({ kind: 'parse_error', message: format_error(e) })
|
|
89
|
+
* )
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export declare const try_catch: <T, E>(fn: () => T, on_error: (e: unknown) => E) => Result<T, E>;
|
|
93
|
+
/**
|
|
94
|
+
* Execute an async function and convert exceptions to Result.
|
|
95
|
+
*
|
|
96
|
+
* @param fn - Async function to execute
|
|
97
|
+
* @param on_error - Transform caught exception to error type
|
|
98
|
+
* @returns Promise of Result containing success value or transformed error
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* const result = await try_catch_async(
|
|
103
|
+
* () => db.query('SELECT * FROM users'),
|
|
104
|
+
* e => ({ kind: 'database_error', cause: e })
|
|
105
|
+
* )
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare const try_catch_async: <T, E>(fn: () => Promise<T>, on_error: (e: unknown) => E) => Promise<Result<T, E>>;
|
|
109
|
+
/**
|
|
110
|
+
* Error types for fetch operations.
|
|
111
|
+
*/
|
|
112
|
+
export type FetchError = {
|
|
113
|
+
type: "network";
|
|
114
|
+
cause: unknown;
|
|
115
|
+
} | {
|
|
116
|
+
type: "http";
|
|
117
|
+
status: number;
|
|
118
|
+
status_text: string;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Fetch wrapper that returns Result instead of throwing.
|
|
122
|
+
*
|
|
123
|
+
* @param input - URL or Request to fetch
|
|
124
|
+
* @param init - Fetch options
|
|
125
|
+
* @param on_error - Transform FetchError to your error type
|
|
126
|
+
* @param parse_body - Custom body parser (defaults to JSON)
|
|
127
|
+
* @returns Promise of Result with parsed response or error
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* const result = await fetch_result(
|
|
132
|
+
* 'https://api.example.com/users',
|
|
133
|
+
* { headers: { Authorization: `Bearer ${token}` } },
|
|
134
|
+
* e => e.type === 'http' ? `HTTP ${e.status}` : 'Network error'
|
|
135
|
+
* )
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export declare const fetch_result: <T, E>(input: string | URL | Request, init: RequestInit | undefined, on_error: (e: FetchError) => E, parse_body?: (response: Response) => Promise<T>) => Promise<Result<T, E>>;
|
|
139
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
140
|
+
/**
|
|
141
|
+
* A composable pipeline for chaining Result operations.
|
|
142
|
+
*
|
|
143
|
+
* All operations are lazy - nothing executes until `.result()` or `.unwrap_or()` is called.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* const user = await pipe(fetchUser(id))
|
|
148
|
+
* .map(user => user.profile)
|
|
149
|
+
* .flat_map(profile => fetchAvatar(profile.avatar_id))
|
|
150
|
+
* .map(avatar => avatar.url)
|
|
151
|
+
* .unwrap_or('/default-avatar.png')
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export type Pipe<T, E> = {
|
|
155
|
+
/** Transform the success value */
|
|
156
|
+
map: <U>(fn: (value: T) => U) => Pipe<U, E>;
|
|
157
|
+
/** Transform the success value with an async function */
|
|
158
|
+
map_async: <U>(fn: (value: T) => Promise<U>) => Pipe<U, E>;
|
|
159
|
+
/** Chain with another Result-returning operation */
|
|
160
|
+
flat_map: <U>(fn: (value: T) => MaybePromise<Result<U, E>>) => Pipe<U, E>;
|
|
161
|
+
/** Transform the error value */
|
|
162
|
+
map_err: <F>(fn: (error: E) => F) => Pipe<T, F>;
|
|
163
|
+
/** Execute side effect on success (logging, metrics) */
|
|
164
|
+
tap: (fn: (value: T) => MaybePromise<void>) => Pipe<T, E>;
|
|
165
|
+
/** Execute side effect on error */
|
|
166
|
+
tap_err: (fn: (error: E) => MaybePromise<void>) => Pipe<T, E>;
|
|
167
|
+
/** Extract value with fallback */
|
|
168
|
+
unwrap_or: (default_value: T) => Promise<T>;
|
|
169
|
+
/** Get the underlying Result */
|
|
170
|
+
result: () => Promise<Result<T, E>>;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Create a composable pipeline from a Result or Promise<Result>.
|
|
174
|
+
*
|
|
175
|
+
* @param initial - Starting Result value (sync or async)
|
|
176
|
+
* @returns A Pipe for chaining operations
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* // From existing Result
|
|
181
|
+
* const result = await pipe(ok(42))
|
|
182
|
+
* .map(n => n * 2)
|
|
183
|
+
* .result()
|
|
184
|
+
*
|
|
185
|
+
* // From async operation
|
|
186
|
+
* const user = await pipe(fetchUser(id))
|
|
187
|
+
* .flat_map(u => fetchProfile(u.id))
|
|
188
|
+
* .result()
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
export declare const pipe: {
|
|
192
|
+
<T, E>(initial: MaybePromise<Result<T, E>>): Pipe<T, E>;
|
|
193
|
+
ok<T>(value: T): Pipe<T, never>;
|
|
194
|
+
err<E>(error: E): Pipe<never, E>;
|
|
195
|
+
try<T, E>(fn: () => Promise<T>, on_error: (e: unknown) => E): Pipe<T, E>;
|
|
196
|
+
fetch<T, E>(input: string | URL | Request, init: RequestInit | undefined, on_error: (e: FetchError) => E, parse_body?: (response: Response) => Promise<T>): Pipe<T, E>;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Extract value from Result, returning null for any error.
|
|
200
|
+
* Use for "fetch single resource" patterns where not-found is expected.
|
|
201
|
+
*
|
|
202
|
+
* @param result - The Result to convert
|
|
203
|
+
* @returns The value or null
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```ts
|
|
207
|
+
* const user = to_nullable(await store.get(userId))
|
|
208
|
+
* if (!user) return <NotFound />
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
export declare const to_nullable: <T, E>(result: Result<T, E>) => T | null;
|
|
212
|
+
/**
|
|
213
|
+
* Extract value from Result, returning fallback for any error.
|
|
214
|
+
* Use for list endpoints where empty array is acceptable.
|
|
215
|
+
*
|
|
216
|
+
* @param result - The Result to convert
|
|
217
|
+
* @param fallback - Value to return on error
|
|
218
|
+
* @returns The value or fallback
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```ts
|
|
222
|
+
* const items = to_fallback(await store.list(), [])
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
export declare const to_fallback: <T, E>(result: Result<T, E>, fallback: T) => T;
|
|
226
|
+
/**
|
|
227
|
+
* Return null if error matches predicate, otherwise throw the error.
|
|
228
|
+
* Use for 404-as-null pattern specifically.
|
|
229
|
+
*
|
|
230
|
+
* @param result - The Result to check
|
|
231
|
+
* @param predicate - Returns true for expected errors (e.g., not_found)
|
|
232
|
+
* @returns The value or null for expected errors
|
|
233
|
+
* @throws The error if predicate returns false
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```ts
|
|
237
|
+
* const user = null_on(
|
|
238
|
+
* await store.get(id),
|
|
239
|
+
* e => e.kind === 'not_found'
|
|
240
|
+
* )
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
export declare const null_on: <T, E>(result: Result<T, E>, predicate: (error: E) => boolean) => T | null;
|
|
244
|
+
/**
|
|
245
|
+
* Return fallback if error matches predicate, otherwise throw.
|
|
246
|
+
*
|
|
247
|
+
* @param result - The Result to check
|
|
248
|
+
* @param predicate - Returns true for expected errors
|
|
249
|
+
* @param fallback - Value to return for expected errors
|
|
250
|
+
* @returns The value or fallback for expected errors
|
|
251
|
+
* @throws The error if predicate returns false
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* const count = fallback_on(
|
|
256
|
+
* await store.count(),
|
|
257
|
+
* e => e.kind === 'not_found',
|
|
258
|
+
* 0
|
|
259
|
+
* )
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export declare const fallback_on: <T, E>(result: Result<T, E>, predicate: (error: E) => boolean, fallback: T) => T;
|
|
263
|
+
/**
|
|
264
|
+
* Format an unknown error to a string message.
|
|
265
|
+
*
|
|
266
|
+
* @param e - Any error value
|
|
267
|
+
* @returns A string representation
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```ts
|
|
271
|
+
* try {
|
|
272
|
+
* riskyOperation()
|
|
273
|
+
* } catch (e) {
|
|
274
|
+
* console.error(format_error(e)) // Handles Error, string, or anything
|
|
275
|
+
* }
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
export declare const format_error: (e: unknown) => string;
|
|
279
|
+
export {};
|
|
280
|
+
//# sourceMappingURL=result.d.ts.map
|