boundlessdb 0.1.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/CHANGELOG.md +89 -0
- package/LICENSE +21 -0
- package/README.md +545 -0
- package/dist/better-sqlite3-shim.d.ts +12 -0
- package/dist/better-sqlite3-shim.d.ts.map +1 -0
- package/dist/better-sqlite3-shim.js +18 -0
- package/dist/better-sqlite3-shim.js.map +1 -0
- package/dist/browser.d.ts +14 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +14 -0
- package/dist/browser.js.map +1 -0
- package/dist/config/extractor.d.ts +22 -0
- package/dist/config/extractor.d.ts.map +1 -0
- package/dist/config/extractor.js +132 -0
- package/dist/config/extractor.js.map +1 -0
- package/dist/config/validator.d.ts +14 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +94 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/event-store.browser.d.ts +61 -0
- package/dist/event-store.browser.d.ts.map +1 -0
- package/dist/event-store.browser.js +323 -0
- package/dist/event-store.browser.js.map +1 -0
- package/dist/event-store.d.ts +101 -0
- package/dist/event-store.d.ts.map +1 -0
- package/dist/event-store.js +249 -0
- package/dist/event-store.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/query-builder.d.ts +72 -0
- package/dist/query-builder.d.ts.map +1 -0
- package/dist/query-builder.js +84 -0
- package/dist/query-builder.js.map +1 -0
- package/dist/storage/interface.d.ts +48 -0
- package/dist/storage/interface.d.ts.map +1 -0
- package/dist/storage/interface.js +5 -0
- package/dist/storage/interface.js.map +1 -0
- package/dist/storage/memory.d.ts +27 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +94 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/postgres.d.ts +76 -0
- package/dist/storage/postgres.d.ts.map +1 -0
- package/dist/storage/postgres.js +346 -0
- package/dist/storage/postgres.js.map +1 -0
- package/dist/storage/sqlite.d.ts +47 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +249 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/storage/sqljs.d.ts +60 -0
- package/dist/storage/sqljs.d.ts.map +1 -0
- package/dist/storage/sqljs.js +354 -0
- package/dist/storage/sqljs.js.map +1 -0
- package/dist/types.d.ts +172 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +52 -0
- package/dist/types.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DCB Event Store - Browser Bundle Entry Point
|
|
3
|
+
*
|
|
4
|
+
* This file exports everything needed for browser usage with sql.js storage.
|
|
5
|
+
*/
|
|
6
|
+
export type { Event, EventWithMetadata, StoredEvent, Query, QueryCondition, UnconstrainedCondition, ConstrainedCondition, ConsistencyConfig, ConsistencyKeyDef, EventTypeConfig, ExtractedKey, AppendResult, ConflictResult, AppendCondition, EventStoreOptions, } from './types.js';
|
|
7
|
+
export { QueryResult, isConflict, isConstrainedCondition } from './types.js';
|
|
8
|
+
export { EventStore, createEventStore, type EventStoreConfig } from './event-store.browser.js';
|
|
9
|
+
export type { EventStorage, EventToStore } from './storage/interface.js';
|
|
10
|
+
export { InMemoryStorage } from './storage/memory.js';
|
|
11
|
+
export { SqlJsStorage, type SqlJsStorageOptions } from './storage/sqljs.js';
|
|
12
|
+
export { KeyExtractor, KeyExtractionError } from './config/extractor.js';
|
|
13
|
+
export { validateConfig, ConfigValidationError } from './config/validator.js';
|
|
14
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EAEV,KAAK,EACL,iBAAiB,EACjB,WAAW,EAEX,KAAK,EACL,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EAEpB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,YAAY,EAEZ,YAAY,EACZ,cAAc,EACd,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAG7E,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG/F,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG5E,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DCB Event Store - Browser Bundle Entry Point
|
|
3
|
+
*
|
|
4
|
+
* This file exports everything needed for browser usage with sql.js storage.
|
|
5
|
+
*/
|
|
6
|
+
export { QueryResult, isConflict, isConstrainedCondition } from './types.js';
|
|
7
|
+
// Event Store (browser version)
|
|
8
|
+
export { EventStore, createEventStore } from './event-store.browser.js';
|
|
9
|
+
export { InMemoryStorage } from './storage/memory.js';
|
|
10
|
+
export { SqlJsStorage } from './storage/sqljs.js';
|
|
11
|
+
// Config
|
|
12
|
+
export { KeyExtractor, KeyExtractionError } from './config/extractor.js';
|
|
13
|
+
export { validateConfig, ConfigValidationError } from './config/validator.js';
|
|
14
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyBH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAE7E,gCAAgC;AAChC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAyB,MAAM,0BAA0B,CAAC;AAI/F,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAA4B,MAAM,oBAAoB,CAAC;AAE5E,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key Extractor: Extracts consistency keys from events based on configuration
|
|
3
|
+
*/
|
|
4
|
+
import type { ConsistencyConfig, ExtractedKey, NewEvent, StoredEvent } from '../types.js';
|
|
5
|
+
export declare class KeyExtractionError extends Error {
|
|
6
|
+
readonly eventType: string;
|
|
7
|
+
readonly keyName: string;
|
|
8
|
+
readonly path: string;
|
|
9
|
+
constructor(eventType: string, keyName: string, path: string, message: string);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Extracts consistency keys from an event based on configuration
|
|
13
|
+
*/
|
|
14
|
+
export declare class KeyExtractor {
|
|
15
|
+
private readonly config;
|
|
16
|
+
constructor(config: ConsistencyConfig);
|
|
17
|
+
/**
|
|
18
|
+
* Extract all consistency keys from an event
|
|
19
|
+
*/
|
|
20
|
+
extract(event: NewEvent | StoredEvent): ExtractedKey[];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/config/extractor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,iBAAiB,EAEjB,YAAY,EACZ,QAAQ,EACR,WAAW,EACZ,MAAM,aAAa,CAAC;AAyErB,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,SAAS,EAAE,MAAM;aACjB,OAAO,EAAE,MAAM;aACf,IAAI,EAAE,MAAM;gBAFZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAKlB;AAED;;GAEG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,iBAAiB;IAEtD;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,GAAG,YAAY,EAAE;CAqEvD"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key Extractor: Extracts consistency keys from events based on configuration
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a dot-notation path in an object
|
|
6
|
+
* @example resolvePath({ data: { courseId: "cs101" } }, "data.courseId") => "cs101"
|
|
7
|
+
*/
|
|
8
|
+
function resolvePath(obj, path) {
|
|
9
|
+
const parts = path.split('.');
|
|
10
|
+
let current = obj;
|
|
11
|
+
for (const part of parts) {
|
|
12
|
+
if (current === null || current === undefined) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
if (typeof current !== 'object') {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
current = current[part];
|
|
19
|
+
}
|
|
20
|
+
return current;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Apply a transformation to a value
|
|
24
|
+
*/
|
|
25
|
+
function applyTransform(value, transform) {
|
|
26
|
+
if (!transform) {
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
switch (transform) {
|
|
30
|
+
case 'LOWER':
|
|
31
|
+
return value.toLowerCase();
|
|
32
|
+
case 'UPPER':
|
|
33
|
+
return value.toUpperCase();
|
|
34
|
+
case 'MONTH': {
|
|
35
|
+
// "2026-02-14" or "2026-02-14T10:30:00Z" → "2026-02"
|
|
36
|
+
const match = value.match(/^(\d{4}-\d{2})/);
|
|
37
|
+
if (!match) {
|
|
38
|
+
throw new Error(`Cannot extract MONTH from value: ${value}`);
|
|
39
|
+
}
|
|
40
|
+
return match[1];
|
|
41
|
+
}
|
|
42
|
+
case 'YEAR': {
|
|
43
|
+
// "2026-02-14" → "2026"
|
|
44
|
+
const match = value.match(/^(\d{4})/);
|
|
45
|
+
if (!match) {
|
|
46
|
+
throw new Error(`Cannot extract YEAR from value: ${value}`);
|
|
47
|
+
}
|
|
48
|
+
return match[1];
|
|
49
|
+
}
|
|
50
|
+
case 'DATE': {
|
|
51
|
+
// "2026-02-14T10:30:00Z" → "2026-02-14"
|
|
52
|
+
const match = value.match(/^(\d{4}-\d{2}-\d{2})/);
|
|
53
|
+
if (!match) {
|
|
54
|
+
throw new Error(`Cannot extract DATE from value: ${value}`);
|
|
55
|
+
}
|
|
56
|
+
return match[1];
|
|
57
|
+
}
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unknown transform: ${transform}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export class KeyExtractionError extends Error {
|
|
63
|
+
eventType;
|
|
64
|
+
keyName;
|
|
65
|
+
path;
|
|
66
|
+
constructor(eventType, keyName, path, message) {
|
|
67
|
+
super(`Key extraction failed for ${eventType}.${keyName} (path: ${path}): ${message}`);
|
|
68
|
+
this.eventType = eventType;
|
|
69
|
+
this.keyName = keyName;
|
|
70
|
+
this.path = path;
|
|
71
|
+
this.name = 'KeyExtractionError';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Extracts consistency keys from an event based on configuration
|
|
76
|
+
*/
|
|
77
|
+
export class KeyExtractor {
|
|
78
|
+
config;
|
|
79
|
+
constructor(config) {
|
|
80
|
+
this.config = config;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Extract all consistency keys from an event
|
|
84
|
+
*/
|
|
85
|
+
extract(event) {
|
|
86
|
+
const eventConfig = this.config.eventTypes[event.type];
|
|
87
|
+
// No configuration for this event type — no keys extracted
|
|
88
|
+
if (!eventConfig) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
const keys = [];
|
|
92
|
+
for (const keyDef of eventConfig.keys) {
|
|
93
|
+
const rawValue = resolvePath(event, keyDef.path);
|
|
94
|
+
// Handle null/undefined values
|
|
95
|
+
if (rawValue === null || rawValue === undefined) {
|
|
96
|
+
const handling = keyDef.nullHandling ?? 'error';
|
|
97
|
+
switch (handling) {
|
|
98
|
+
case 'skip':
|
|
99
|
+
continue;
|
|
100
|
+
case 'default':
|
|
101
|
+
if (keyDef.defaultValue === undefined) {
|
|
102
|
+
throw new KeyExtractionError(event.type, keyDef.name, keyDef.path, 'nullHandling is "default" but no defaultValue provided');
|
|
103
|
+
}
|
|
104
|
+
keys.push({ name: keyDef.name, value: keyDef.defaultValue });
|
|
105
|
+
continue;
|
|
106
|
+
case 'error':
|
|
107
|
+
default:
|
|
108
|
+
throw new KeyExtractionError(event.type, keyDef.name, keyDef.path, 'Path resolved to null/undefined');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Convert to string
|
|
112
|
+
let stringValue;
|
|
113
|
+
if (typeof rawValue === 'string') {
|
|
114
|
+
stringValue = rawValue;
|
|
115
|
+
}
|
|
116
|
+
else if (typeof rawValue === 'number' || typeof rawValue === 'bigint') {
|
|
117
|
+
stringValue = String(rawValue);
|
|
118
|
+
}
|
|
119
|
+
else if (typeof rawValue === 'boolean') {
|
|
120
|
+
stringValue = rawValue ? 'true' : 'false';
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
throw new KeyExtractionError(event.type, keyDef.name, keyDef.path, `Cannot convert value of type ${typeof rawValue} to string`);
|
|
124
|
+
}
|
|
125
|
+
// Apply transformation
|
|
126
|
+
const finalValue = applyTransform(stringValue, keyDef.transform);
|
|
127
|
+
keys.push({ name: keyDef.name, value: finalValue });
|
|
128
|
+
}
|
|
129
|
+
return keys;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/config/extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consistency Config Validator
|
|
3
|
+
*/
|
|
4
|
+
import type { ConsistencyConfig } from '../types.js';
|
|
5
|
+
export declare class ConfigValidationError extends Error {
|
|
6
|
+
readonly errors: string[];
|
|
7
|
+
constructor(errors: string[]);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Validate a full consistency configuration
|
|
11
|
+
* @throws ConfigValidationError if validation fails
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateConfig(config: ConsistencyConfig): void;
|
|
14
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/config/validator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAqB,MAAM,aAAa,CAAC;AAExE,qBAAa,qBAAsB,SAAQ,KAAK;aAE5B,MAAM,EAAE,MAAM,EAAE;gBAAhB,MAAM,EAAE,MAAM,EAAE;CAKnC;AAgED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CA6C9D"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consistency Config Validator
|
|
3
|
+
*/
|
|
4
|
+
export class ConfigValidationError extends Error {
|
|
5
|
+
errors;
|
|
6
|
+
constructor(errors) {
|
|
7
|
+
super(`Configuration validation failed:\n${errors.map(e => ` - ${e}`).join('\n')}`);
|
|
8
|
+
this.errors = errors;
|
|
9
|
+
this.name = 'ConfigValidationError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const VALID_TRANSFORMS = ['LOWER', 'UPPER', 'MONTH', 'YEAR', 'DATE'];
|
|
13
|
+
const VALID_NULL_HANDLING = ['error', 'skip', 'default'];
|
|
14
|
+
const KEY_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
15
|
+
const PATH_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*$/;
|
|
16
|
+
/**
|
|
17
|
+
* Validate a single key definition
|
|
18
|
+
*/
|
|
19
|
+
function validateKeyDef(eventType, keyDef, index) {
|
|
20
|
+
const errors = [];
|
|
21
|
+
const prefix = `eventTypes.${eventType}.keys[${index}]`;
|
|
22
|
+
// name: required, valid format
|
|
23
|
+
if (!keyDef.name) {
|
|
24
|
+
errors.push(`${prefix}.name is required`);
|
|
25
|
+
}
|
|
26
|
+
else if (!KEY_NAME_PATTERN.test(keyDef.name)) {
|
|
27
|
+
errors.push(`${prefix}.name "${keyDef.name}" must match pattern ${KEY_NAME_PATTERN}`);
|
|
28
|
+
}
|
|
29
|
+
// path: required, valid format
|
|
30
|
+
if (!keyDef.path) {
|
|
31
|
+
errors.push(`${prefix}.path is required`);
|
|
32
|
+
}
|
|
33
|
+
else if (!PATH_PATTERN.test(keyDef.path)) {
|
|
34
|
+
errors.push(`${prefix}.path "${keyDef.path}" must be a valid dot-notation path`);
|
|
35
|
+
}
|
|
36
|
+
// transform: optional, must be valid
|
|
37
|
+
if (keyDef.transform !== undefined) {
|
|
38
|
+
if (!VALID_TRANSFORMS.includes(keyDef.transform)) {
|
|
39
|
+
errors.push(`${prefix}.transform "${keyDef.transform}" must be one of: ${VALID_TRANSFORMS.join(', ')}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// nullHandling: optional, must be valid
|
|
43
|
+
if (keyDef.nullHandling !== undefined) {
|
|
44
|
+
if (!VALID_NULL_HANDLING.includes(keyDef.nullHandling)) {
|
|
45
|
+
errors.push(`${prefix}.nullHandling "${keyDef.nullHandling}" must be one of: ${VALID_NULL_HANDLING.join(', ')}`);
|
|
46
|
+
}
|
|
47
|
+
// If nullHandling is 'default', defaultValue must be provided
|
|
48
|
+
if (keyDef.nullHandling === 'default' && keyDef.defaultValue === undefined) {
|
|
49
|
+
errors.push(`${prefix}.defaultValue is required when nullHandling is "default"`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return errors;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate a full consistency configuration
|
|
56
|
+
* @throws ConfigValidationError if validation fails
|
|
57
|
+
*/
|
|
58
|
+
export function validateConfig(config) {
|
|
59
|
+
const errors = [];
|
|
60
|
+
// Basic structure check
|
|
61
|
+
if (!config || typeof config !== 'object') {
|
|
62
|
+
throw new ConfigValidationError(['Configuration must be an object']);
|
|
63
|
+
}
|
|
64
|
+
if (!config.eventTypes || typeof config.eventTypes !== 'object') {
|
|
65
|
+
throw new ConfigValidationError(['eventTypes must be an object']);
|
|
66
|
+
}
|
|
67
|
+
// Validate each event type
|
|
68
|
+
for (const [eventType, eventConfig] of Object.entries(config.eventTypes)) {
|
|
69
|
+
if (!eventConfig || typeof eventConfig !== 'object') {
|
|
70
|
+
errors.push(`eventTypes.${eventType} must be an object`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (!Array.isArray(eventConfig.keys)) {
|
|
74
|
+
errors.push(`eventTypes.${eventType}.keys must be an array`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// Check for duplicate key names within the same event type
|
|
78
|
+
const keyNames = new Set();
|
|
79
|
+
for (let i = 0; i < eventConfig.keys.length; i++) {
|
|
80
|
+
const keyDef = eventConfig.keys[i];
|
|
81
|
+
// Validate the key definition
|
|
82
|
+
errors.push(...validateKeyDef(eventType, keyDef, i));
|
|
83
|
+
// Check for duplicates
|
|
84
|
+
if (keyDef.name && keyNames.has(keyDef.name)) {
|
|
85
|
+
errors.push(`eventTypes.${eventType}.keys has duplicate key name "${keyDef.name}"`);
|
|
86
|
+
}
|
|
87
|
+
keyNames.add(keyDef.name);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (errors.length > 0) {
|
|
91
|
+
throw new ConfigValidationError(errors);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/config/validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-compatible EventStore
|
|
3
|
+
*/
|
|
4
|
+
import type { EventStorage } from './storage/interface.js';
|
|
5
|
+
import { QueryResult, type AppendCondition, type AppendResult, type ConflictResult, type Event, type EventStoreOptions, type EventWithMetadata, type Query } from './types.js';
|
|
6
|
+
export interface EventStoreConfig extends EventStoreOptions {
|
|
7
|
+
storage: EventStorage;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Browser-compatible DCB-native Event Store
|
|
11
|
+
*/
|
|
12
|
+
export declare class EventStore {
|
|
13
|
+
private readonly storage;
|
|
14
|
+
private readonly keyExtractor;
|
|
15
|
+
private readonly config;
|
|
16
|
+
private initPromise;
|
|
17
|
+
constructor(options: EventStoreConfig);
|
|
18
|
+
/**
|
|
19
|
+
* Ensure the store is initialized (for async operations)
|
|
20
|
+
*/
|
|
21
|
+
private ensureInitialized;
|
|
22
|
+
/**
|
|
23
|
+
* Check if config has changed since last run, reindex if needed
|
|
24
|
+
*/
|
|
25
|
+
private checkAndReindexIfNeeded;
|
|
26
|
+
/**
|
|
27
|
+
* Read events matching a query
|
|
28
|
+
*
|
|
29
|
+
* @typeParam E - Event union type for typed results
|
|
30
|
+
* @returns QueryResult with typed events and appendCondition
|
|
31
|
+
*/
|
|
32
|
+
read<E extends Event = Event>(query: Query): Promise<QueryResult<E>>;
|
|
33
|
+
/**
|
|
34
|
+
* Append events with optional consistency check
|
|
35
|
+
*
|
|
36
|
+
* @typeParam E - Event type for type checking
|
|
37
|
+
* @param events Events to append
|
|
38
|
+
* @param condition Consistency check - can be:
|
|
39
|
+
* - null: Skip consistency check (optimistic first write)
|
|
40
|
+
* - AppendCondition: { position, conditions } from a previous read
|
|
41
|
+
* @returns AppendResult on success, ConflictResult on conflict
|
|
42
|
+
*/
|
|
43
|
+
append<E extends Event = Event>(events: EventWithMetadata<E>[], condition: AppendCondition | null): Promise<AppendResult | ConflictResult<E>>;
|
|
44
|
+
/**
|
|
45
|
+
* Build conditions that cover the appended events
|
|
46
|
+
*/
|
|
47
|
+
private buildConditionsFromEvents;
|
|
48
|
+
/**
|
|
49
|
+
* Get the underlying storage (for advanced use cases)
|
|
50
|
+
*/
|
|
51
|
+
getStorage(): EventStorage;
|
|
52
|
+
/**
|
|
53
|
+
* Close the event store
|
|
54
|
+
*/
|
|
55
|
+
close(): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Factory function to create an event store
|
|
59
|
+
*/
|
|
60
|
+
export declare function createEventStore(options: EventStoreConfig): EventStore;
|
|
61
|
+
//# sourceMappingURL=event-store.browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-store.browser.d.ts","sourceRoot":"","sources":["../src/event-store.browser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EACL,WAAW,EAEX,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,EAGnB,KAAK,KAAK,EACV,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,KAAK,EAGX,MAAM,YAAY,CAAC;AA6DpB,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,WAAW,CAA8B;gBAErC,OAAO,EAAE,gBAAgB;IAqBrC;;OAEG;YACW,iBAAiB;IAM/B;;OAEG;YACW,uBAAuB;IA+DrC;;;;;OAKG;IACG,IAAI,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IA+B1E;;;;;;;;;OASG;IACG,MAAM,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,EAClC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAC9B,SAAS,EAAE,eAAe,GAAG,IAAI,GAChC,OAAO,CAAC,YAAY,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAkH5C;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA4BjC;;OAEG;IACH,UAAU,IAAI,YAAY;IAI1B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU,CAEtE"}
|