hzl-core 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/dist/__tests__/backup/backup-restore.test.d.ts +2 -0
- package/dist/__tests__/backup/backup-restore.test.d.ts.map +1 -0
- package/dist/__tests__/backup/backup-restore.test.js +200 -0
- package/dist/__tests__/backup/backup-restore.test.js.map +1 -0
- package/dist/__tests__/backup/import-export.test.d.ts +2 -0
- package/dist/__tests__/backup/import-export.test.d.ts.map +1 -0
- package/dist/__tests__/backup/import-export.test.js +341 -0
- package/dist/__tests__/backup/import-export.test.js.map +1 -0
- package/dist/__tests__/concurrency/stress.test.d.ts +2 -0
- package/dist/__tests__/concurrency/stress.test.d.ts.map +1 -0
- package/dist/__tests__/concurrency/stress.test.js +274 -0
- package/dist/__tests__/concurrency/stress.test.js.map +1 -0
- package/dist/__tests__/concurrency/worker.d.ts +2 -0
- package/dist/__tests__/concurrency/worker.d.ts.map +1 -0
- package/dist/__tests__/concurrency/worker.js +84 -0
- package/dist/__tests__/concurrency/worker.js.map +1 -0
- package/dist/__tests__/migrations/upgrade.test.d.ts +2 -0
- package/dist/__tests__/migrations/upgrade.test.d.ts.map +1 -0
- package/dist/__tests__/migrations/upgrade.test.js +203 -0
- package/dist/__tests__/migrations/upgrade.test.js.map +1 -0
- package/dist/__tests__/projections/rebuild-equivalence.test.d.ts +2 -0
- package/dist/__tests__/projections/rebuild-equivalence.test.d.ts.map +1 -0
- package/dist/__tests__/projections/rebuild-equivalence.test.js +276 -0
- package/dist/__tests__/projections/rebuild-equivalence.test.js.map +1 -0
- package/dist/__tests__/properties/invariants.test.d.ts +2 -0
- package/dist/__tests__/properties/invariants.test.d.ts.map +1 -0
- package/dist/__tests__/properties/invariants.test.js +314 -0
- package/dist/__tests__/properties/invariants.test.js.map +1 -0
- package/dist/db/connection.d.ts +13 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +52 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/connection.test.d.ts +2 -0
- package/dist/db/connection.test.d.ts.map +1 -0
- package/dist/db/connection.test.js +63 -0
- package/dist/db/connection.test.js.map +1 -0
- package/dist/db/migrations/v2.d.ts +2 -0
- package/dist/db/migrations/v2.d.ts.map +1 -0
- package/dist/db/migrations/v2.js +4 -0
- package/dist/db/migrations/v2.js.map +1 -0
- package/dist/db/migrations.d.ts +4 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +45 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/migrations.test.d.ts +2 -0
- package/dist/db/migrations.test.d.ts.map +1 -0
- package/dist/db/migrations.test.js +75 -0
- package/dist/db/migrations.test.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +114 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/events/store.d.ts +33 -0
- package/dist/events/store.d.ts.map +1 -0
- package/dist/events/store.js +81 -0
- package/dist/events/store.js.map +1 -0
- package/dist/events/store.test.d.ts +2 -0
- package/dist/events/store.test.d.ts.map +1 -0
- package/dist/events/store.test.js +138 -0
- package/dist/events/store.test.js.map +1 -0
- package/dist/events/types.d.ts +106 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +87 -0
- package/dist/events/types.js.map +1 -0
- package/dist/events/validation.test.d.ts +2 -0
- package/dist/events/validation.test.d.ts.map +1 -0
- package/dist/events/validation.test.js +83 -0
- package/dist/events/validation.test.js.map +1 -0
- package/dist/fixtures/sample-data.d.ts +16 -0
- package/dist/fixtures/sample-data.d.ts.map +1 -0
- package/dist/fixtures/sample-data.js +148 -0
- package/dist/fixtures/sample-data.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +102 -0
- package/dist/index.test.js.map +1 -0
- package/dist/projections/comments-checkpoints.d.ts +11 -0
- package/dist/projections/comments-checkpoints.d.ts.map +1 -0
- package/dist/projections/comments-checkpoints.js +33 -0
- package/dist/projections/comments-checkpoints.js.map +1 -0
- package/dist/projections/comments-checkpoints.test.d.ts +2 -0
- package/dist/projections/comments-checkpoints.test.d.ts.map +1 -0
- package/dist/projections/comments-checkpoints.test.js +72 -0
- package/dist/projections/comments-checkpoints.test.js.map +1 -0
- package/dist/projections/dependencies.d.ts +12 -0
- package/dist/projections/dependencies.d.ts.map +1 -0
- package/dist/projections/dependencies.js +39 -0
- package/dist/projections/dependencies.js.map +1 -0
- package/dist/projections/dependencies.test.d.ts +2 -0
- package/dist/projections/dependencies.test.d.ts.map +1 -0
- package/dist/projections/dependencies.test.js +97 -0
- package/dist/projections/dependencies.test.js.map +1 -0
- package/dist/projections/engine.d.ts +18 -0
- package/dist/projections/engine.d.ts.map +1 -0
- package/dist/projections/engine.js +56 -0
- package/dist/projections/engine.js.map +1 -0
- package/dist/projections/engine.test.d.ts +2 -0
- package/dist/projections/engine.test.d.ts.map +1 -0
- package/dist/projections/engine.test.js +92 -0
- package/dist/projections/engine.test.js.map +1 -0
- package/dist/projections/rebuild.d.ts +4 -0
- package/dist/projections/rebuild.d.ts.map +1 -0
- package/dist/projections/rebuild.js +26 -0
- package/dist/projections/rebuild.js.map +1 -0
- package/dist/projections/rebuild.test.d.ts +2 -0
- package/dist/projections/rebuild.test.d.ts.map +1 -0
- package/dist/projections/rebuild.test.js +59 -0
- package/dist/projections/rebuild.test.js.map +1 -0
- package/dist/projections/search.d.ts +11 -0
- package/dist/projections/search.d.ts.map +1 -0
- package/dist/projections/search.js +39 -0
- package/dist/projections/search.js.map +1 -0
- package/dist/projections/search.test.d.ts +2 -0
- package/dist/projections/search.test.d.ts.map +1 -0
- package/dist/projections/search.test.js +78 -0
- package/dist/projections/search.test.js.map +1 -0
- package/dist/projections/tags.d.ts +12 -0
- package/dist/projections/tags.d.ts.map +1 -0
- package/dist/projections/tags.js +41 -0
- package/dist/projections/tags.js.map +1 -0
- package/dist/projections/tags.test.d.ts +2 -0
- package/dist/projections/tags.test.d.ts.map +1 -0
- package/dist/projections/tags.test.js +69 -0
- package/dist/projections/tags.test.js.map +1 -0
- package/dist/projections/tasks-current.d.ts +14 -0
- package/dist/projections/tasks-current.d.ts.map +1 -0
- package/dist/projections/tasks-current.js +110 -0
- package/dist/projections/tasks-current.js.map +1 -0
- package/dist/projections/tasks-current.test.d.ts +2 -0
- package/dist/projections/tasks-current.test.d.ts.map +1 -0
- package/dist/projections/tasks-current.test.js +215 -0
- package/dist/projections/tasks-current.test.js.map +1 -0
- package/dist/projections/types.d.ts +13 -0
- package/dist/projections/types.d.ts.map +1 -0
- package/dist/projections/types.js +2 -0
- package/dist/projections/types.js.map +1 -0
- package/dist/services/backup-service.d.ts +16 -0
- package/dist/services/backup-service.d.ts.map +1 -0
- package/dist/services/backup-service.js +114 -0
- package/dist/services/backup-service.js.map +1 -0
- package/dist/services/search-service.d.ts +27 -0
- package/dist/services/search-service.d.ts.map +1 -0
- package/dist/services/search-service.js +33 -0
- package/dist/services/search-service.js.map +1 -0
- package/dist/services/search-service.test.d.ts +2 -0
- package/dist/services/search-service.test.d.ts.map +1 -0
- package/dist/services/search-service.test.js +66 -0
- package/dist/services/search-service.test.js.map +1 -0
- package/dist/services/task-service.d.ts +147 -0
- package/dist/services/task-service.d.ts.map +1 -0
- package/dist/services/task-service.js +442 -0
- package/dist/services/task-service.js.map +1 -0
- package/dist/services/task-service.test.d.ts +2 -0
- package/dist/services/task-service.test.d.ts.map +1 -0
- package/dist/services/task-service.test.js +399 -0
- package/dist/services/task-service.test.js.map +1 -0
- package/dist/services/validation-service.d.ts +29 -0
- package/dist/services/validation-service.d.ts.map +1 -0
- package/dist/services/validation-service.js +74 -0
- package/dist/services/validation-service.js.map +1 -0
- package/dist/services/validation-service.test.d.ts +2 -0
- package/dist/services/validation-service.test.d.ts.map +1 -0
- package/dist/services/validation-service.test.js +67 -0
- package/dist/services/validation-service.test.js.map +1 -0
- package/dist/utils/id.d.ts +3 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +12 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/id.test.d.ts +2 -0
- package/dist/utils/id.test.d.ts.map +1 -0
- package/dist/utils/id.test.js +24 -0
- package/dist/utils/id.test.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// packages/hzl-core/src/projections/engine.test.ts
|
|
2
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import { ProjectionEngine } from './engine.js';
|
|
5
|
+
import { runMigrations } from '../db/migrations.js';
|
|
6
|
+
import { EventStore } from '../events/store.js';
|
|
7
|
+
import { EventType } from '../events/types.js';
|
|
8
|
+
describe('ProjectionEngine', () => {
|
|
9
|
+
let db;
|
|
10
|
+
let eventStore;
|
|
11
|
+
let engine;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
db = new Database(':memory:');
|
|
14
|
+
runMigrations(db);
|
|
15
|
+
eventStore = new EventStore(db);
|
|
16
|
+
});
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
db.close();
|
|
19
|
+
});
|
|
20
|
+
it('registers and applies projectors', () => {
|
|
21
|
+
const applied = [];
|
|
22
|
+
const testProjector = {
|
|
23
|
+
name: 'test',
|
|
24
|
+
apply: (event) => { applied.push(event); },
|
|
25
|
+
};
|
|
26
|
+
engine = new ProjectionEngine(db);
|
|
27
|
+
engine.register(testProjector);
|
|
28
|
+
const event = eventStore.append({
|
|
29
|
+
task_id: 'TASK1',
|
|
30
|
+
type: EventType.TaskCreated,
|
|
31
|
+
data: { title: 'Test', project: 'inbox' },
|
|
32
|
+
});
|
|
33
|
+
engine.applyEvent(event);
|
|
34
|
+
expect(applied).toHaveLength(1);
|
|
35
|
+
expect(applied[0].event_id).toBe(event.event_id);
|
|
36
|
+
});
|
|
37
|
+
it('tracks projection state', () => {
|
|
38
|
+
const testProjector = {
|
|
39
|
+
name: 'test_state',
|
|
40
|
+
apply: () => { },
|
|
41
|
+
};
|
|
42
|
+
engine = new ProjectionEngine(db);
|
|
43
|
+
engine.register(testProjector);
|
|
44
|
+
const event = eventStore.append({
|
|
45
|
+
task_id: 'TASK1',
|
|
46
|
+
type: EventType.TaskCreated,
|
|
47
|
+
data: { title: 'Test', project: 'inbox' },
|
|
48
|
+
});
|
|
49
|
+
engine.applyEvent(event);
|
|
50
|
+
engine.updateProjectionState('test_state', event.rowid);
|
|
51
|
+
const state = engine.getProjectionState('test_state');
|
|
52
|
+
expect(state?.last_event_id).toBe(event.rowid);
|
|
53
|
+
});
|
|
54
|
+
it('applies multiple projectors in registration order', () => {
|
|
55
|
+
const order = [];
|
|
56
|
+
const projector1 = {
|
|
57
|
+
name: 'first',
|
|
58
|
+
apply: () => { order.push('first'); },
|
|
59
|
+
};
|
|
60
|
+
const projector2 = {
|
|
61
|
+
name: 'second',
|
|
62
|
+
apply: () => { order.push('second'); },
|
|
63
|
+
};
|
|
64
|
+
engine = new ProjectionEngine(db);
|
|
65
|
+
engine.register(projector1);
|
|
66
|
+
engine.register(projector2);
|
|
67
|
+
const event = eventStore.append({
|
|
68
|
+
task_id: 'TASK1',
|
|
69
|
+
type: EventType.TaskCreated,
|
|
70
|
+
data: { title: 'Test', project: 'inbox' },
|
|
71
|
+
});
|
|
72
|
+
engine.applyEvent(event);
|
|
73
|
+
expect(order).toEqual(['first', 'second']);
|
|
74
|
+
});
|
|
75
|
+
it('getEventsSince returns events after given id', () => {
|
|
76
|
+
engine = new ProjectionEngine(db);
|
|
77
|
+
const e1 = eventStore.append({
|
|
78
|
+
task_id: 'TASK1',
|
|
79
|
+
type: EventType.TaskCreated,
|
|
80
|
+
data: { title: 'Test 1', project: 'inbox' },
|
|
81
|
+
});
|
|
82
|
+
const e2 = eventStore.append({
|
|
83
|
+
task_id: 'TASK2',
|
|
84
|
+
type: EventType.TaskCreated,
|
|
85
|
+
data: { title: 'Test 2', project: 'inbox' },
|
|
86
|
+
});
|
|
87
|
+
const events = engine.getEventsSince(e1.rowid, 100);
|
|
88
|
+
expect(events).toHaveLength(1);
|
|
89
|
+
expect(events[0].event_id).toBe(e2.event_id);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=engine.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.test.js","sourceRoot":"","sources":["../../src/projections/engine.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuild.d.ts","sourceRoot":"","sources":["../../src/projections/rebuild.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,MAAM,EAAE,gBAAgB,GACvB,IAAI,CA2BN"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const BATCH_SIZE = 1000;
|
|
2
|
+
export function rebuildAllProjections(db, engine) {
|
|
3
|
+
const projectors = engine.getProjectors();
|
|
4
|
+
for (const projector of projectors) {
|
|
5
|
+
if (projector.reset) {
|
|
6
|
+
projector.reset(db);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
db.exec('DELETE FROM projection_state');
|
|
10
|
+
let lastId = 0;
|
|
11
|
+
while (true) {
|
|
12
|
+
const events = engine.getEventsSince(lastId, BATCH_SIZE);
|
|
13
|
+
if (events.length === 0)
|
|
14
|
+
break;
|
|
15
|
+
for (const event of events) {
|
|
16
|
+
engine.applyEvent(event);
|
|
17
|
+
lastId = event.rowid;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
for (const projector of projectors) {
|
|
21
|
+
if (lastId > 0) {
|
|
22
|
+
engine.updateProjectionState(projector.name, lastId);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=rebuild.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuild.js","sourceRoot":"","sources":["../../src/projections/rebuild.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,MAAM,UAAU,qBAAqB,CACnC,EAAqB,EACrB,MAAwB;IAExB,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;IAE1C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACpB,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,EAAE,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAExC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACzD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM;QAE/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACzB,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACf,MAAM,CAAC,qBAAqB,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuild.test.d.ts","sourceRoot":"","sources":["../../src/projections/rebuild.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// packages/hzl-core/src/projections/rebuild.test.ts
|
|
2
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import { rebuildAllProjections } from './rebuild.js';
|
|
5
|
+
import { ProjectionEngine } from './engine.js';
|
|
6
|
+
import { TasksCurrentProjector } from './tasks-current.js';
|
|
7
|
+
import { DependenciesProjector } from './dependencies.js';
|
|
8
|
+
import { TagsProjector } from './tags.js';
|
|
9
|
+
import { CommentsCheckpointsProjector } from './comments-checkpoints.js';
|
|
10
|
+
import { SearchProjector } from './search.js';
|
|
11
|
+
import { runMigrations } from '../db/migrations.js';
|
|
12
|
+
import { EventStore } from '../events/store.js';
|
|
13
|
+
import { EventType, TaskStatus } from '../events/types.js';
|
|
14
|
+
describe('rebuildAllProjections', () => {
|
|
15
|
+
let db;
|
|
16
|
+
let eventStore;
|
|
17
|
+
let engine;
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
db = new Database(':memory:');
|
|
20
|
+
runMigrations(db);
|
|
21
|
+
eventStore = new EventStore(db);
|
|
22
|
+
engine = new ProjectionEngine(db);
|
|
23
|
+
engine.register(new TasksCurrentProjector());
|
|
24
|
+
engine.register(new DependenciesProjector());
|
|
25
|
+
engine.register(new TagsProjector());
|
|
26
|
+
engine.register(new CommentsCheckpointsProjector());
|
|
27
|
+
engine.register(new SearchProjector());
|
|
28
|
+
});
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
db.close();
|
|
31
|
+
});
|
|
32
|
+
it('rebuilds all projections from events', () => {
|
|
33
|
+
const e1 = eventStore.append({
|
|
34
|
+
task_id: 'TASK1',
|
|
35
|
+
type: EventType.TaskCreated,
|
|
36
|
+
data: { title: 'Test', project: 'inbox', tags: ['tag1'], depends_on: ['DEP1'] },
|
|
37
|
+
});
|
|
38
|
+
engine.applyEvent(e1);
|
|
39
|
+
const e2 = eventStore.append({
|
|
40
|
+
task_id: 'TASK1',
|
|
41
|
+
type: EventType.StatusChanged,
|
|
42
|
+
data: { from: TaskStatus.Backlog, to: TaskStatus.Ready },
|
|
43
|
+
});
|
|
44
|
+
engine.applyEvent(e2);
|
|
45
|
+
// Manually corrupt projections
|
|
46
|
+
db.exec('DELETE FROM tasks_current');
|
|
47
|
+
db.exec('DELETE FROM task_tags');
|
|
48
|
+
db.exec('DELETE FROM task_dependencies');
|
|
49
|
+
// Rebuild
|
|
50
|
+
rebuildAllProjections(db, engine);
|
|
51
|
+
// Verify restoration
|
|
52
|
+
const task = db.prepare('SELECT * FROM tasks_current WHERE task_id = ?').get('TASK1');
|
|
53
|
+
expect(task.title).toBe('Test');
|
|
54
|
+
expect(task.status).toBe('ready');
|
|
55
|
+
const tags = db.prepare('SELECT tag FROM task_tags WHERE task_id = ?').all('TASK1');
|
|
56
|
+
expect(tags.map(t => t.tag)).toContain('tag1');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=rebuild.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuild.test.js","sourceRoot":"","sources":["../../src/projections/rebuild.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { PersistedEventEnvelope } from '../events/store.js';
|
|
3
|
+
import type { Projector } from './types.js';
|
|
4
|
+
export declare class SearchProjector implements Projector {
|
|
5
|
+
name: string;
|
|
6
|
+
apply(event: PersistedEventEnvelope, db: Database.Database): void;
|
|
7
|
+
reset(db: Database.Database): void;
|
|
8
|
+
private handleTaskCreated;
|
|
9
|
+
private handleTaskUpdated;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/projections/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,qBAAa,eAAgB,YAAW,SAAS;IAC/C,IAAI,SAAY;IAEhB,KAAK,CAAC,KAAK,EAAE,sBAAsB,EAAE,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI;IAWjE,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI;IAIlC,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,iBAAiB;CAgB1B"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { EventType } from '../events/types.js';
|
|
2
|
+
const SEARCHABLE_FIELDS = new Set(['title', 'description']);
|
|
3
|
+
export class SearchProjector {
|
|
4
|
+
name = 'search';
|
|
5
|
+
apply(event, db) {
|
|
6
|
+
switch (event.type) {
|
|
7
|
+
case EventType.TaskCreated:
|
|
8
|
+
this.handleTaskCreated(event, db);
|
|
9
|
+
break;
|
|
10
|
+
case EventType.TaskUpdated:
|
|
11
|
+
this.handleTaskUpdated(event, db);
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
reset(db) {
|
|
16
|
+
db.exec('DELETE FROM task_search');
|
|
17
|
+
}
|
|
18
|
+
handleTaskCreated(event, db) {
|
|
19
|
+
const data = event.data;
|
|
20
|
+
db.prepare(`
|
|
21
|
+
INSERT INTO task_search (task_id, title, description)
|
|
22
|
+
VALUES (?, ?, ?)
|
|
23
|
+
`).run(event.task_id, data.title, data.description ?? '');
|
|
24
|
+
}
|
|
25
|
+
handleTaskUpdated(event, db) {
|
|
26
|
+
const data = event.data;
|
|
27
|
+
if (!SEARCHABLE_FIELDS.has(data.field))
|
|
28
|
+
return;
|
|
29
|
+
const task = db.prepare('SELECT title, description FROM tasks_current WHERE task_id = ?').get(event.task_id);
|
|
30
|
+
if (!task)
|
|
31
|
+
return;
|
|
32
|
+
db.prepare('DELETE FROM task_search WHERE task_id = ?').run(event.task_id);
|
|
33
|
+
db.prepare(`
|
|
34
|
+
INSERT INTO task_search (task_id, title, description)
|
|
35
|
+
VALUES (?, ?, ?)
|
|
36
|
+
`).run(event.task_id, task.title, task.description ?? '');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/projections/search.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;AAE5D,MAAM,OAAO,eAAe;IAC1B,IAAI,GAAG,QAAQ,CAAC;IAEhB,KAAK,CAAC,KAA6B,EAAE,EAAqB;QACxD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,SAAS,CAAC,WAAW;gBACxB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAClC,MAAM;YACR,KAAK,SAAS,CAAC,WAAW;gBACxB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAClC,MAAM;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,EAAqB;QACzB,EAAE,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACrC,CAAC;IAEO,iBAAiB,CAAC,KAA6B,EAAE,EAAqB;QAC5E,MAAM,IAAI,GAAG,KAAK,CAAC,IAAW,CAAC;QAC/B,EAAE,CAAC,OAAO,CAAC;;;KAGV,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAEO,iBAAiB,CAAC,KAA6B,EAAE,EAAqB;QAC5E,MAAM,IAAI,GAAG,KAAK,CAAC,IAAW,CAAC;QAC/B,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO;QAE/C,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,gEAAgE,CACjE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAA8D,CAAC;QAElF,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3E,EAAE,CAAC,OAAO,CAAC;;;KAGV,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../../src/projections/search.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// packages/hzl-core/src/projections/search.test.ts
|
|
2
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import { SearchProjector } from './search.js';
|
|
5
|
+
import { TasksCurrentProjector } from './tasks-current.js';
|
|
6
|
+
import { runMigrations } from '../db/migrations.js';
|
|
7
|
+
import { EventStore } from '../events/store.js';
|
|
8
|
+
import { EventType } from '../events/types.js';
|
|
9
|
+
describe('SearchProjector', () => {
|
|
10
|
+
let db;
|
|
11
|
+
let eventStore;
|
|
12
|
+
let tasksProjector;
|
|
13
|
+
let searchProjector;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
db = new Database(':memory:');
|
|
16
|
+
runMigrations(db);
|
|
17
|
+
eventStore = new EventStore(db);
|
|
18
|
+
tasksProjector = new TasksCurrentProjector();
|
|
19
|
+
searchProjector = new SearchProjector();
|
|
20
|
+
});
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
db.close();
|
|
23
|
+
});
|
|
24
|
+
describe('task_created', () => {
|
|
25
|
+
it('indexes title and description', () => {
|
|
26
|
+
const event = eventStore.append({
|
|
27
|
+
task_id: 'TASK1',
|
|
28
|
+
type: EventType.TaskCreated,
|
|
29
|
+
data: {
|
|
30
|
+
title: 'Implement authentication',
|
|
31
|
+
project: 'inbox',
|
|
32
|
+
description: 'Add OAuth2 support',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
tasksProjector.apply(event, db);
|
|
36
|
+
searchProjector.apply(event, db);
|
|
37
|
+
const results = db.prepare("SELECT task_id FROM task_search WHERE task_search MATCH 'authentication'").all();
|
|
38
|
+
expect(results.map(r => r.task_id)).toContain('TASK1');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('task_updated', () => {
|
|
42
|
+
it('updates index when title changes', () => {
|
|
43
|
+
const createEvent = eventStore.append({
|
|
44
|
+
task_id: 'TASK1',
|
|
45
|
+
type: EventType.TaskCreated,
|
|
46
|
+
data: { title: 'Original title', project: 'inbox' },
|
|
47
|
+
});
|
|
48
|
+
tasksProjector.apply(createEvent, db);
|
|
49
|
+
searchProjector.apply(createEvent, db);
|
|
50
|
+
const updateEvent = eventStore.append({
|
|
51
|
+
task_id: 'TASK1',
|
|
52
|
+
type: EventType.TaskUpdated,
|
|
53
|
+
data: { field: 'title', new_value: 'Updated title' },
|
|
54
|
+
});
|
|
55
|
+
tasksProjector.apply(updateEvent, db);
|
|
56
|
+
searchProjector.apply(updateEvent, db);
|
|
57
|
+
const oldResults = db.prepare("SELECT task_id FROM task_search WHERE task_search MATCH 'Original'").all();
|
|
58
|
+
expect(oldResults).toHaveLength(0);
|
|
59
|
+
const newResults = db.prepare("SELECT task_id FROM task_search WHERE task_search MATCH 'Updated'").all();
|
|
60
|
+
expect(newResults.map(r => r.task_id)).toContain('TASK1');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('reset', () => {
|
|
64
|
+
it('clears search index', () => {
|
|
65
|
+
const event = eventStore.append({
|
|
66
|
+
task_id: 'TASK1',
|
|
67
|
+
type: EventType.TaskCreated,
|
|
68
|
+
data: { title: 'Test', project: 'inbox' },
|
|
69
|
+
});
|
|
70
|
+
tasksProjector.apply(event, db);
|
|
71
|
+
searchProjector.apply(event, db);
|
|
72
|
+
searchProjector.reset(db);
|
|
73
|
+
const count = db.prepare('SELECT COUNT(*) as cnt FROM task_search').get();
|
|
74
|
+
expect(count.cnt).toBe(0);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=search.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../src/projections/search.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { PersistedEventEnvelope } from '../events/store.js';
|
|
3
|
+
import type { Projector } from './types.js';
|
|
4
|
+
export declare class TagsProjector implements Projector {
|
|
5
|
+
name: string;
|
|
6
|
+
apply(event: PersistedEventEnvelope, db: Database.Database): void;
|
|
7
|
+
reset(db: Database.Database): void;
|
|
8
|
+
private handleTaskCreated;
|
|
9
|
+
private handleTaskUpdated;
|
|
10
|
+
private insertTags;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/projections/tags.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,qBAAa,aAAc,YAAW,SAAS;IAC7C,IAAI,SAAU;IAEd,KAAK,CAAC,KAAK,EAAE,sBAAsB,EAAE,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI;IAWjE,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI;IAIlC,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,UAAU;CAQnB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EventType } from '../events/types.js';
|
|
2
|
+
export class TagsProjector {
|
|
3
|
+
name = 'tags';
|
|
4
|
+
apply(event, db) {
|
|
5
|
+
switch (event.type) {
|
|
6
|
+
case EventType.TaskCreated:
|
|
7
|
+
this.handleTaskCreated(event, db);
|
|
8
|
+
break;
|
|
9
|
+
case EventType.TaskUpdated:
|
|
10
|
+
this.handleTaskUpdated(event, db);
|
|
11
|
+
break;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
reset(db) {
|
|
15
|
+
db.exec('DELETE FROM task_tags');
|
|
16
|
+
}
|
|
17
|
+
handleTaskCreated(event, db) {
|
|
18
|
+
const data = event.data;
|
|
19
|
+
const tags = data.tags;
|
|
20
|
+
if (!tags || tags.length === 0)
|
|
21
|
+
return;
|
|
22
|
+
this.insertTags(db, event.task_id, tags);
|
|
23
|
+
}
|
|
24
|
+
handleTaskUpdated(event, db) {
|
|
25
|
+
const data = event.data;
|
|
26
|
+
if (data.field !== 'tags')
|
|
27
|
+
return;
|
|
28
|
+
const newTags = data.new_value;
|
|
29
|
+
db.prepare('DELETE FROM task_tags WHERE task_id = ?').run(event.task_id);
|
|
30
|
+
if (newTags && newTags.length > 0) {
|
|
31
|
+
this.insertTags(db, event.task_id, newTags);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
insertTags(db, taskId, tags) {
|
|
35
|
+
const insertStmt = db.prepare('INSERT OR IGNORE INTO task_tags (task_id, tag) VALUES (?, ?)');
|
|
36
|
+
for (const tag of tags) {
|
|
37
|
+
insertStmt.run(taskId, tag);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/projections/tags.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,OAAO,aAAa;IACxB,IAAI,GAAG,MAAM,CAAC;IAEd,KAAK,CAAC,KAA6B,EAAE,EAAqB;QACxD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,SAAS,CAAC,WAAW;gBACxB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAClC,MAAM;YACR,KAAK,SAAS,CAAC,WAAW;gBACxB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAClC,MAAM;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,EAAqB;QACzB,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACnC,CAAC;IAEO,iBAAiB,CAAC,KAA6B,EAAE,EAAqB;QAC5E,MAAM,IAAI,GAAG,KAAK,CAAC,IAAW,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,IAA4B,CAAC;QAC/C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEvC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAEO,iBAAiB,CAAC,KAA6B,EAAE,EAAqB;QAC5E,MAAM,IAAI,GAAG,KAAK,CAAC,IAAW,CAAC;QAC/B,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM;YAAE,OAAO;QAElC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAqB,CAAC;QAC3C,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzE,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,EAAqB,EAAE,MAAc,EAAE,IAAc;QACtE,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAC3B,8DAA8D,CAC/D,CAAC;QACF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.test.d.ts","sourceRoot":"","sources":["../../src/projections/tags.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// packages/hzl-core/src/projections/tags.test.ts
|
|
2
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import { TagsProjector } from './tags.js';
|
|
5
|
+
import { runMigrations } from '../db/migrations.js';
|
|
6
|
+
import { EventStore } from '../events/store.js';
|
|
7
|
+
import { EventType } from '../events/types.js';
|
|
8
|
+
describe('TagsProjector', () => {
|
|
9
|
+
let db;
|
|
10
|
+
let eventStore;
|
|
11
|
+
let projector;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
db = new Database(':memory:');
|
|
14
|
+
runMigrations(db);
|
|
15
|
+
eventStore = new EventStore(db);
|
|
16
|
+
projector = new TagsProjector();
|
|
17
|
+
});
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
db.close();
|
|
20
|
+
});
|
|
21
|
+
describe('task_created with tags', () => {
|
|
22
|
+
it('inserts tag rows', () => {
|
|
23
|
+
const event = eventStore.append({
|
|
24
|
+
task_id: 'TASK1',
|
|
25
|
+
type: EventType.TaskCreated,
|
|
26
|
+
data: {
|
|
27
|
+
title: 'Test',
|
|
28
|
+
project: 'inbox',
|
|
29
|
+
tags: ['urgent', 'backend'],
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
projector.apply(event, db);
|
|
33
|
+
const tags = db.prepare('SELECT tag FROM task_tags WHERE task_id = ? ORDER BY tag').all('TASK1');
|
|
34
|
+
expect(tags.map(t => t.tag)).toEqual(['backend', 'urgent']);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('task_updated tags field', () => {
|
|
38
|
+
it('replaces all tags', () => {
|
|
39
|
+
const createEvent = eventStore.append({
|
|
40
|
+
task_id: 'TASK1',
|
|
41
|
+
type: EventType.TaskCreated,
|
|
42
|
+
data: { title: 'Test', project: 'inbox', tags: ['old1', 'old2'] },
|
|
43
|
+
});
|
|
44
|
+
projector.apply(createEvent, db);
|
|
45
|
+
const updateEvent = eventStore.append({
|
|
46
|
+
task_id: 'TASK1',
|
|
47
|
+
type: EventType.TaskUpdated,
|
|
48
|
+
data: { field: 'tags', new_value: ['new1', 'new2', 'new3'] },
|
|
49
|
+
});
|
|
50
|
+
projector.apply(updateEvent, db);
|
|
51
|
+
const tags = db.prepare('SELECT tag FROM task_tags WHERE task_id = ? ORDER BY tag').all('TASK1');
|
|
52
|
+
expect(tags.map(t => t.tag)).toEqual(['new1', 'new2', 'new3']);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('reset', () => {
|
|
56
|
+
it('clears all tag data', () => {
|
|
57
|
+
const event = eventStore.append({
|
|
58
|
+
task_id: 'TASK1',
|
|
59
|
+
type: EventType.TaskCreated,
|
|
60
|
+
data: { title: 'Test', project: 'inbox', tags: ['tag1'] },
|
|
61
|
+
});
|
|
62
|
+
projector.apply(event, db);
|
|
63
|
+
projector.reset(db);
|
|
64
|
+
const count = db.prepare('SELECT COUNT(*) as cnt FROM task_tags').get();
|
|
65
|
+
expect(count.cnt).toBe(0);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=tags.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.test.js","sourceRoot":"","sources":["../../src/projections/tags.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { PersistedEventEnvelope } from '../events/store.js';
|
|
3
|
+
import type { Projector } from './types.js';
|
|
4
|
+
export declare class TasksCurrentProjector implements Projector {
|
|
5
|
+
name: string;
|
|
6
|
+
apply(event: PersistedEventEnvelope, db: Database.Database): void;
|
|
7
|
+
reset(db: Database.Database): void;
|
|
8
|
+
private handleTaskCreated;
|
|
9
|
+
private handleStatusChanged;
|
|
10
|
+
private handleTaskMoved;
|
|
11
|
+
private handleTaskUpdated;
|
|
12
|
+
private handleTaskArchived;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=tasks-current.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks-current.d.ts","sourceRoot":"","sources":["../../src/projections/tasks-current.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,qBAAa,qBAAsB,YAAW,SAAS;IACrD,IAAI,SAAmB;IAEvB,KAAK,CAAC,KAAK,EAAE,sBAAsB,EAAE,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI;IAoBjE,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI;IAIlC,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,mBAAmB;IAgD3B,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,kBAAkB;CAS3B"}
|