@f0rbit/corpus 0.1.4 → 0.1.6

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 (62) hide show
  1. package/dist/backend/cloudflare.d.ts +1 -1
  2. package/dist/backend/cloudflare.d.ts.map +1 -1
  3. package/dist/backend/cloudflare.js +168 -58
  4. package/dist/backend/file.d.ts +1 -1
  5. package/dist/backend/file.d.ts.map +1 -1
  6. package/dist/backend/file.js +65 -67
  7. package/dist/backend/layered.d.ts.map +1 -1
  8. package/dist/backend/layered.js +67 -19
  9. package/dist/backend/memory.d.ts +2 -1
  10. package/dist/backend/memory.d.ts.map +1 -1
  11. package/dist/backend/memory.js +39 -53
  12. package/dist/corpus.d.ts +11 -0
  13. package/dist/corpus.d.ts.map +1 -1
  14. package/dist/corpus.js +52 -0
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1 -0
  18. package/dist/observations/client.d.ts +12 -0
  19. package/dist/observations/client.d.ts.map +1 -0
  20. package/dist/observations/client.js +115 -0
  21. package/dist/observations/index.d.ts +12 -0
  22. package/dist/observations/index.d.ts.map +1 -0
  23. package/dist/observations/index.js +11 -0
  24. package/dist/observations/schema.d.ts +267 -0
  25. package/dist/observations/schema.d.ts.map +1 -0
  26. package/dist/observations/schema.js +55 -0
  27. package/dist/observations/storage.d.ts +75 -0
  28. package/dist/observations/storage.d.ts.map +1 -0
  29. package/dist/observations/storage.js +137 -0
  30. package/dist/observations/types.d.ts +219 -0
  31. package/dist/observations/types.d.ts.map +1 -0
  32. package/dist/observations/types.js +40 -0
  33. package/dist/observations/utils.d.ts +183 -0
  34. package/dist/observations/utils.d.ts.map +1 -0
  35. package/dist/observations/utils.js +272 -0
  36. package/dist/sst.d.ts +1 -1
  37. package/dist/sst.d.ts.map +1 -1
  38. package/dist/sst.js +20 -0
  39. package/dist/types.d.ts +61 -0
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/utils.d.ts +38 -1
  42. package/dist/utils.d.ts.map +1 -1
  43. package/dist/utils.js +84 -0
  44. package/package.json +1 -1
  45. package/dist/codec.d.ts +0 -9
  46. package/dist/codec.d.ts.map +0 -1
  47. package/dist/codec.js +0 -21
  48. package/dist/codecs.d.ts +0 -8
  49. package/dist/codecs.d.ts.map +0 -1
  50. package/dist/codecs.js +0 -6
  51. package/dist/core.d.ts +0 -9
  52. package/dist/core.d.ts.map +0 -1
  53. package/dist/core.js +0 -7
  54. package/dist/hash.d.ts +0 -2
  55. package/dist/hash.d.ts.map +0 -1
  56. package/dist/hash.js +0 -5
  57. package/dist/store.d.ts +0 -3
  58. package/dist/store.d.ts.map +0 -1
  59. package/dist/store.js +0 -125
  60. package/dist/version.d.ts +0 -7
  61. package/dist/version.d.ts.map +0 -1
  62. package/dist/version.js +0 -31
@@ -0,0 +1,267 @@
1
+ /**
2
+ * @module ObservationSchema
3
+ * @description Database schema definitions for observations using Drizzle ORM.
4
+ */
5
+ /**
6
+ * Drizzle ORM schema for the corpus_observations table.
7
+ *
8
+ * Used by the Cloudflare backend with D1 (SQLite). Defines the table structure
9
+ * for storing observation metadata linking structured facts to versioned content.
10
+ *
11
+ * Columns:
12
+ * - `id` - Primary key (unique observation identifier)
13
+ * - `type` - Observation type name (e.g., 'entity_mention')
14
+ * - `source_store_id` + `source_version` - Points to the snapshot this observation is about
15
+ * - `source_path` - Optional JSONPath expression to specific element
16
+ * - `source_span_start` / `source_span_end` - Optional character range within text
17
+ * - `content` - JSON-encoded observation data
18
+ * - `confidence` - Optional confidence score (0.0 to 1.0)
19
+ * - `observed_at` - When the observation was made (ISO 8601)
20
+ * - `created_at` - When the record was stored (ISO 8601)
21
+ * - `derived_from` - Optional JSON array of SnapshotPointers for provenance
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { drizzle } from 'drizzle-orm/d1'
26
+ * import { corpus_observations } from 'corpus/observation-schema'
27
+ *
28
+ * const db = drizzle(env.D1)
29
+ * const rows = await db.select().from(corpus_observations).where(eq(corpus_observations.type, 'entity_mention'))
30
+ * ```
31
+ */
32
+ export declare const corpus_observations: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
33
+ name: "corpus_observations";
34
+ schema: undefined;
35
+ columns: {
36
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
37
+ name: "id";
38
+ tableName: "corpus_observations";
39
+ dataType: "string";
40
+ columnType: "SQLiteText";
41
+ data: string;
42
+ driverParam: string;
43
+ notNull: true;
44
+ hasDefault: false;
45
+ isPrimaryKey: true;
46
+ isAutoincrement: false;
47
+ hasRuntimeDefault: false;
48
+ enumValues: [string, ...string[]];
49
+ baseColumn: never;
50
+ identity: undefined;
51
+ generated: undefined;
52
+ }, {}, {
53
+ length: number | undefined;
54
+ }>;
55
+ type: import("drizzle-orm/sqlite-core").SQLiteColumn<{
56
+ name: "type";
57
+ tableName: "corpus_observations";
58
+ dataType: "string";
59
+ columnType: "SQLiteText";
60
+ data: string;
61
+ driverParam: string;
62
+ notNull: true;
63
+ hasDefault: false;
64
+ isPrimaryKey: false;
65
+ isAutoincrement: false;
66
+ hasRuntimeDefault: false;
67
+ enumValues: [string, ...string[]];
68
+ baseColumn: never;
69
+ identity: undefined;
70
+ generated: undefined;
71
+ }, {}, {
72
+ length: number | undefined;
73
+ }>;
74
+ source_store_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
75
+ name: "source_store_id";
76
+ tableName: "corpus_observations";
77
+ dataType: "string";
78
+ columnType: "SQLiteText";
79
+ data: string;
80
+ driverParam: string;
81
+ notNull: true;
82
+ hasDefault: false;
83
+ isPrimaryKey: false;
84
+ isAutoincrement: false;
85
+ hasRuntimeDefault: false;
86
+ enumValues: [string, ...string[]];
87
+ baseColumn: never;
88
+ identity: undefined;
89
+ generated: undefined;
90
+ }, {}, {
91
+ length: number | undefined;
92
+ }>;
93
+ source_version: import("drizzle-orm/sqlite-core").SQLiteColumn<{
94
+ name: "source_version";
95
+ tableName: "corpus_observations";
96
+ dataType: "string";
97
+ columnType: "SQLiteText";
98
+ data: string;
99
+ driverParam: string;
100
+ notNull: true;
101
+ hasDefault: false;
102
+ isPrimaryKey: false;
103
+ isAutoincrement: false;
104
+ hasRuntimeDefault: false;
105
+ enumValues: [string, ...string[]];
106
+ baseColumn: never;
107
+ identity: undefined;
108
+ generated: undefined;
109
+ }, {}, {
110
+ length: number | undefined;
111
+ }>;
112
+ source_path: import("drizzle-orm/sqlite-core").SQLiteColumn<{
113
+ name: "source_path";
114
+ tableName: "corpus_observations";
115
+ dataType: "string";
116
+ columnType: "SQLiteText";
117
+ data: string;
118
+ driverParam: string;
119
+ notNull: false;
120
+ hasDefault: false;
121
+ isPrimaryKey: false;
122
+ isAutoincrement: false;
123
+ hasRuntimeDefault: false;
124
+ enumValues: [string, ...string[]];
125
+ baseColumn: never;
126
+ identity: undefined;
127
+ generated: undefined;
128
+ }, {}, {
129
+ length: number | undefined;
130
+ }>;
131
+ source_span_start: import("drizzle-orm/sqlite-core").SQLiteColumn<{
132
+ name: "source_span_start";
133
+ tableName: "corpus_observations";
134
+ dataType: "string";
135
+ columnType: "SQLiteText";
136
+ data: string;
137
+ driverParam: string;
138
+ notNull: false;
139
+ hasDefault: false;
140
+ isPrimaryKey: false;
141
+ isAutoincrement: false;
142
+ hasRuntimeDefault: false;
143
+ enumValues: [string, ...string[]];
144
+ baseColumn: never;
145
+ identity: undefined;
146
+ generated: undefined;
147
+ }, {}, {
148
+ length: number | undefined;
149
+ }>;
150
+ source_span_end: import("drizzle-orm/sqlite-core").SQLiteColumn<{
151
+ name: "source_span_end";
152
+ tableName: "corpus_observations";
153
+ dataType: "string";
154
+ columnType: "SQLiteText";
155
+ data: string;
156
+ driverParam: string;
157
+ notNull: false;
158
+ hasDefault: false;
159
+ isPrimaryKey: false;
160
+ isAutoincrement: false;
161
+ hasRuntimeDefault: false;
162
+ enumValues: [string, ...string[]];
163
+ baseColumn: never;
164
+ identity: undefined;
165
+ generated: undefined;
166
+ }, {}, {
167
+ length: number | undefined;
168
+ }>;
169
+ content: import("drizzle-orm/sqlite-core").SQLiteColumn<{
170
+ name: "content";
171
+ tableName: "corpus_observations";
172
+ dataType: "string";
173
+ columnType: "SQLiteText";
174
+ data: string;
175
+ driverParam: string;
176
+ notNull: true;
177
+ hasDefault: false;
178
+ isPrimaryKey: false;
179
+ isAutoincrement: false;
180
+ hasRuntimeDefault: false;
181
+ enumValues: [string, ...string[]];
182
+ baseColumn: never;
183
+ identity: undefined;
184
+ generated: undefined;
185
+ }, {}, {
186
+ length: number | undefined;
187
+ }>;
188
+ confidence: import("drizzle-orm/sqlite-core").SQLiteColumn<{
189
+ name: "confidence";
190
+ tableName: "corpus_observations";
191
+ dataType: "number";
192
+ columnType: "SQLiteReal";
193
+ data: number;
194
+ driverParam: number;
195
+ notNull: false;
196
+ hasDefault: false;
197
+ isPrimaryKey: false;
198
+ isAutoincrement: false;
199
+ hasRuntimeDefault: false;
200
+ enumValues: undefined;
201
+ baseColumn: never;
202
+ identity: undefined;
203
+ generated: undefined;
204
+ }, {}, {}>;
205
+ observed_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
206
+ name: "observed_at";
207
+ tableName: "corpus_observations";
208
+ dataType: "string";
209
+ columnType: "SQLiteText";
210
+ data: string;
211
+ driverParam: string;
212
+ notNull: false;
213
+ hasDefault: false;
214
+ isPrimaryKey: false;
215
+ isAutoincrement: false;
216
+ hasRuntimeDefault: false;
217
+ enumValues: [string, ...string[]];
218
+ baseColumn: never;
219
+ identity: undefined;
220
+ generated: undefined;
221
+ }, {}, {
222
+ length: number | undefined;
223
+ }>;
224
+ created_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
225
+ name: "created_at";
226
+ tableName: "corpus_observations";
227
+ dataType: "string";
228
+ columnType: "SQLiteText";
229
+ data: string;
230
+ driverParam: string;
231
+ notNull: true;
232
+ hasDefault: false;
233
+ isPrimaryKey: false;
234
+ isAutoincrement: false;
235
+ hasRuntimeDefault: false;
236
+ enumValues: [string, ...string[]];
237
+ baseColumn: never;
238
+ identity: undefined;
239
+ generated: undefined;
240
+ }, {}, {
241
+ length: number | undefined;
242
+ }>;
243
+ derived_from: import("drizzle-orm/sqlite-core").SQLiteColumn<{
244
+ name: "derived_from";
245
+ tableName: "corpus_observations";
246
+ dataType: "string";
247
+ columnType: "SQLiteText";
248
+ data: string;
249
+ driverParam: string;
250
+ notNull: false;
251
+ hasDefault: false;
252
+ isPrimaryKey: false;
253
+ isAutoincrement: false;
254
+ hasRuntimeDefault: false;
255
+ enumValues: [string, ...string[]];
256
+ baseColumn: never;
257
+ identity: undefined;
258
+ generated: undefined;
259
+ }, {}, {
260
+ length: number | undefined;
261
+ }>;
262
+ };
263
+ dialect: "sqlite";
264
+ }>;
265
+ export type ObservationRow = typeof corpus_observations.$inferSelect;
266
+ export type ObservationInsert = typeof corpus_observations.$inferInsert;
267
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../observations/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0B7B,CAAA;AAEH,MAAM,MAAM,cAAc,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAA;AACpE,MAAM,MAAM,iBAAiB,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAA"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @module ObservationSchema
3
+ * @description Database schema definitions for observations using Drizzle ORM.
4
+ */
5
+ import { sqliteTable, text, real, index } from 'drizzle-orm/sqlite-core';
6
+ /**
7
+ * Drizzle ORM schema for the corpus_observations table.
8
+ *
9
+ * Used by the Cloudflare backend with D1 (SQLite). Defines the table structure
10
+ * for storing observation metadata linking structured facts to versioned content.
11
+ *
12
+ * Columns:
13
+ * - `id` - Primary key (unique observation identifier)
14
+ * - `type` - Observation type name (e.g., 'entity_mention')
15
+ * - `source_store_id` + `source_version` - Points to the snapshot this observation is about
16
+ * - `source_path` - Optional JSONPath expression to specific element
17
+ * - `source_span_start` / `source_span_end` - Optional character range within text
18
+ * - `content` - JSON-encoded observation data
19
+ * - `confidence` - Optional confidence score (0.0 to 1.0)
20
+ * - `observed_at` - When the observation was made (ISO 8601)
21
+ * - `created_at` - When the record was stored (ISO 8601)
22
+ * - `derived_from` - Optional JSON array of SnapshotPointers for provenance
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { drizzle } from 'drizzle-orm/d1'
27
+ * import { corpus_observations } from 'corpus/observation-schema'
28
+ *
29
+ * const db = drizzle(env.D1)
30
+ * const rows = await db.select().from(corpus_observations).where(eq(corpus_observations.type, 'entity_mention'))
31
+ * ```
32
+ */
33
+ export const corpus_observations = sqliteTable('corpus_observations', {
34
+ id: text('id').primaryKey(),
35
+ type: text('type').notNull(),
36
+ // Source pointer
37
+ source_store_id: text('source_store_id').notNull(),
38
+ source_version: text('source_version').notNull(),
39
+ source_path: text('source_path'),
40
+ source_span_start: text('source_span_start'),
41
+ source_span_end: text('source_span_end'),
42
+ // Content
43
+ content: text('content').notNull(),
44
+ confidence: real('confidence'),
45
+ // Timestamps
46
+ observed_at: text('observed_at'),
47
+ created_at: text('created_at').notNull(),
48
+ // Derivation lineage
49
+ derived_from: text('derived_from'),
50
+ }, (table) => ({
51
+ type_idx: index('idx_obs_type').on(table.type),
52
+ source_idx: index('idx_obs_source').on(table.source_store_id, table.source_version),
53
+ type_observed_idx: index('idx_obs_type_observed').on(table.type, table.observed_at),
54
+ type_source_idx: index('idx_obs_type_source').on(table.type, table.source_store_id),
55
+ }));
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @module ObservationsStorage
3
+ * @description Raw storage interface and row conversion utilities for observations.
4
+ */
5
+ import type { Result, CorpusError } from '../types';
6
+ import type { ObservationRow } from './schema';
7
+ import type { Observation, ObservationMeta, SnapshotPointer } from './types';
8
+ /**
9
+ * Query options for raw storage operations.
10
+ * Dates are ISO strings at the storage layer.
11
+ */
12
+ export type StorageQueryOpts = {
13
+ type?: string | string[];
14
+ source_store_id?: string;
15
+ source_version?: string;
16
+ source_prefix?: string;
17
+ created_after?: string;
18
+ created_before?: string;
19
+ observed_after?: string;
20
+ observed_before?: string;
21
+ limit?: number;
22
+ };
23
+ /**
24
+ * Raw storage adapter for observation rows.
25
+ * Backends implement this thin interface; all business logic lives in the client.
26
+ */
27
+ export type ObservationsStorage = {
28
+ /** Store a row. Returns the row on success. */
29
+ put_row: (row: ObservationRow) => Promise<Result<ObservationRow, CorpusError>>;
30
+ /** Get a row by ID. Returns null if not found. */
31
+ get_row: (id: string) => Promise<Result<ObservationRow | null, CorpusError>>;
32
+ /** Query rows with optional filters. */
33
+ query_rows: (opts?: StorageQueryOpts) => AsyncIterable<ObservationRow>;
34
+ /** Delete a row by ID. Returns true if deleted, false if not found. */
35
+ delete_row: (id: string) => Promise<Result<boolean, CorpusError>>;
36
+ /** Delete rows matching source. Returns count deleted. */
37
+ delete_by_source: (store_id: string, version: string, path?: string) => Promise<Result<number, CorpusError>>;
38
+ };
39
+ /**
40
+ * Convert a storage row to an Observation (includes content).
41
+ */
42
+ export declare function row_to_observation(row: ObservationRow): Observation;
43
+ /**
44
+ * Convert a storage row to ObservationMeta (excludes content).
45
+ */
46
+ export declare function row_to_meta(row: ObservationRow): ObservationMeta;
47
+ /**
48
+ * Create an ObservationRow from put options.
49
+ */
50
+ export declare function create_observation_row(id: string, type_name: string, source: SnapshotPointer, content: unknown, opts: {
51
+ confidence?: number;
52
+ observed_at?: Date;
53
+ derived_from?: SnapshotPointer[];
54
+ }): ObservationRow;
55
+ /**
56
+ * Filter and sort observation rows based on query options.
57
+ * Used by in-memory storage implementations (memory backend, file backend).
58
+ */
59
+ export declare function filter_observation_rows(rows: ObservationRow[], opts?: StorageQueryOpts): ObservationRow[];
60
+ /**
61
+ * Simple CRUD interface for observation storage backends.
62
+ */
63
+ export type ObservationsCRUD = {
64
+ get_all: () => Promise<ObservationRow[]>;
65
+ set_all: (rows: ObservationRow[]) => Promise<void>;
66
+ get_one: (id: string) => Promise<ObservationRow | null>;
67
+ add_one: (row: ObservationRow) => Promise<void>;
68
+ remove_one: (id: string) => Promise<boolean>;
69
+ };
70
+ /**
71
+ * Create an ObservationsStorage from simple CRUD operations.
72
+ * Used by memory and file backends.
73
+ */
74
+ export declare function create_observations_storage(crud: ObservationsCRUD): ObservationsStorage;
75
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../observations/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * @module ObservationsStorage
3
+ * @description Raw storage interface and row conversion utilities for observations.
4
+ */
5
+ import { ok } from '../types';
6
+ /**
7
+ * Extract common fields from an observation row (everything except content).
8
+ * Used internally by row_to_observation and row_to_meta.
9
+ */
10
+ function row_to_base(row) {
11
+ return {
12
+ id: row.id,
13
+ type: row.type,
14
+ source: {
15
+ store_id: row.source_store_id,
16
+ version: row.source_version,
17
+ ...(row.source_path && { path: row.source_path }),
18
+ ...(row.source_span_start && row.source_span_end && {
19
+ span: {
20
+ start: parseInt(row.source_span_start, 10),
21
+ end: parseInt(row.source_span_end, 10)
22
+ }
23
+ })
24
+ },
25
+ ...(row.confidence !== null && { confidence: row.confidence }),
26
+ ...(row.observed_at && { observed_at: new Date(row.observed_at) }),
27
+ created_at: new Date(row.created_at),
28
+ ...(row.derived_from && { derived_from: JSON.parse(row.derived_from) })
29
+ };
30
+ }
31
+ /**
32
+ * Convert a storage row to an Observation (includes content).
33
+ */
34
+ export function row_to_observation(row) {
35
+ return {
36
+ ...row_to_base(row),
37
+ content: JSON.parse(row.content)
38
+ };
39
+ }
40
+ /**
41
+ * Convert a storage row to ObservationMeta (excludes content).
42
+ */
43
+ export function row_to_meta(row) {
44
+ return row_to_base(row);
45
+ }
46
+ /**
47
+ * Create an ObservationRow from put options.
48
+ */
49
+ export function create_observation_row(id, type_name, source, content, opts) {
50
+ const now = new Date();
51
+ return {
52
+ id,
53
+ type: type_name,
54
+ source_store_id: source.store_id,
55
+ source_version: source.version,
56
+ source_path: source.path ?? null,
57
+ source_span_start: source.span?.start?.toString() ?? null,
58
+ source_span_end: source.span?.end?.toString() ?? null,
59
+ content: JSON.stringify(content),
60
+ confidence: opts.confidence ?? null,
61
+ observed_at: opts.observed_at?.toISOString() ?? null,
62
+ created_at: now.toISOString(),
63
+ derived_from: opts.derived_from ? JSON.stringify(opts.derived_from) : null
64
+ };
65
+ }
66
+ /**
67
+ * Filter and sort observation rows based on query options.
68
+ * Used by in-memory storage implementations (memory backend, file backend).
69
+ */
70
+ export function filter_observation_rows(rows, opts = {}) {
71
+ let filtered = rows;
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;
102
+ }
103
+ /**
104
+ * Create an ObservationsStorage from simple CRUD operations.
105
+ * Used by memory and file backends.
106
+ */
107
+ export function create_observations_storage(crud) {
108
+ return {
109
+ async put_row(row) {
110
+ await crud.add_one(row);
111
+ return ok(row);
112
+ },
113
+ async get_row(id) {
114
+ const row = await crud.get_one(id);
115
+ return ok(row);
116
+ },
117
+ async *query_rows(opts = {}) {
118
+ const rows = filter_observation_rows(await crud.get_all(), opts);
119
+ for (const row of rows) {
120
+ yield row;
121
+ }
122
+ },
123
+ async delete_row(id) {
124
+ const deleted = await crud.remove_one(id);
125
+ return ok(deleted);
126
+ },
127
+ async delete_by_source(store_id, version, path) {
128
+ const rows = await crud.get_all();
129
+ const toKeep = rows.filter(r => !(r.source_store_id === store_id &&
130
+ r.source_version === version &&
131
+ (path === undefined || r.source_path === path)));
132
+ const deleted = rows.length - toKeep.length;
133
+ await crud.set_all(toKeep);
134
+ return ok(deleted);
135
+ }
136
+ };
137
+ }