@graview/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/LICENSE +96 -0
- package/README.md +35 -0
- package/dist/app.d.ts +294 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +49 -0
- package/dist/app.js.map +1 -0
- package/dist/arrange.d.ts +185 -0
- package/dist/arrange.d.ts.map +1 -0
- package/dist/arrange.js +456 -0
- package/dist/arrange.js.map +1 -0
- package/dist/beginning.d.ts +65 -0
- package/dist/beginning.d.ts.map +1 -0
- package/dist/beginning.js +94 -0
- package/dist/beginning.js.map +1 -0
- package/dist/bind.d.ts +42 -0
- package/dist/bind.d.ts.map +1 -0
- package/dist/bind.js +26 -0
- package/dist/bind.js.map +1 -0
- package/dist/city.d.ts +93 -0
- package/dist/city.d.ts.map +1 -0
- package/dist/city.js +160 -0
- package/dist/city.js.map +1 -0
- package/dist/cli/check/arrangement.d.ts +13 -0
- package/dist/cli/check/arrangement.d.ts.map +1 -0
- package/dist/cli/check/arrangement.js +63 -0
- package/dist/cli/check/arrangement.js.map +1 -0
- package/dist/cli/check/beginnings.d.ts +16 -0
- package/dist/cli/check/beginnings.d.ts.map +1 -0
- package/dist/cli/check/beginnings.js +53 -0
- package/dist/cli/check/beginnings.js.map +1 -0
- package/dist/cli/check/brand.d.ts +17 -0
- package/dist/cli/check/brand.d.ts.map +1 -0
- package/dist/cli/check/brand.js +153 -0
- package/dist/cli/check/brand.js.map +1 -0
- package/dist/cli/check/city.d.ts +17 -0
- package/dist/cli/check/city.d.ts.map +1 -0
- package/dist/cli/check/city.js +58 -0
- package/dist/cli/check/city.js.map +1 -0
- package/dist/cli/check/context.d.ts +50 -0
- package/dist/cli/check/context.d.ts.map +1 -0
- package/dist/cli/check/context.js +37 -0
- package/dist/cli/check/context.js.map +1 -0
- package/dist/cli/check/fields.d.ts +16 -0
- package/dist/cli/check/fields.d.ts.map +1 -0
- package/dist/cli/check/fields.js +237 -0
- package/dist/cli/check/fields.js.map +1 -0
- package/dist/cli/check/index.d.ts +14 -0
- package/dist/cli/check/index.d.ts.map +1 -0
- package/dist/cli/check/index.js +14 -0
- package/dist/cli/check/index.js.map +1 -0
- package/dist/cli/check/intelligence.d.ts +17 -0
- package/dist/cli/check/intelligence.d.ts.map +1 -0
- package/dist/cli/check/intelligence.js +136 -0
- package/dist/cli/check/intelligence.js.map +1 -0
- package/dist/cli/check/lenses.d.ts +17 -0
- package/dist/cli/check/lenses.d.ts.map +1 -0
- package/dist/cli/check/lenses.js +239 -0
- package/dist/cli/check/lenses.js.map +1 -0
- package/dist/cli/check/migrations.d.ts +16 -0
- package/dist/cli/check/migrations.d.ts.map +1 -0
- package/dist/cli/check/migrations.js +43 -0
- package/dist/cli/check/migrations.js.map +1 -0
- package/dist/cli/check/modules.d.ts +16 -0
- package/dist/cli/check/modules.d.ts.map +1 -0
- package/dist/cli/check/modules.js +123 -0
- package/dist/cli/check/modules.js.map +1 -0
- package/dist/cli/check/policy.d.ts +16 -0
- package/dist/cli/check/policy.d.ts.map +1 -0
- package/dist/cli/check/policy.js +90 -0
- package/dist/cli/check/policy.js.map +1 -0
- package/dist/cli/check/relations.d.ts +29 -0
- package/dist/cli/check/relations.d.ts.map +1 -0
- package/dist/cli/check/relations.js +279 -0
- package/dist/cli/check/relations.js.map +1 -0
- package/dist/cli/check/routes.d.ts +16 -0
- package/dist/cli/check/routes.d.ts.map +1 -0
- package/dist/cli/check/routes.js +31 -0
- package/dist/cli/check/routes.js.map +1 -0
- package/dist/cli/check/settings.d.ts +16 -0
- package/dist/cli/check/settings.d.ts.map +1 -0
- package/dist/cli/check/settings.js +81 -0
- package/dist/cli/check/settings.js.map +1 -0
- package/dist/cli/check.d.ts +36 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +76 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/create.d.ts +20 -0
- package/dist/cli/create.d.ts.map +1 -0
- package/dist/cli/create.js +251 -0
- package/dist/cli/create.js.map +1 -0
- package/dist/cli/describe.d.ts +35 -0
- package/dist/cli/describe.d.ts.map +1 -0
- package/dist/cli/describe.js +230 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/docs.d.ts +11 -0
- package/dist/cli/docs.d.ts.map +1 -0
- package/dist/cli/docs.js +152 -0
- package/dist/cli/docs.js.map +1 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +281 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/extend.d.ts +23 -0
- package/dist/extend.d.ts.map +1 -0
- package/dist/extend.js +53 -0
- package/dist/extend.js.map +1 -0
- package/dist/graph/diff.d.ts +31 -0
- package/dist/graph/diff.d.ts.map +1 -0
- package/dist/graph/diff.js +71 -0
- package/dist/graph/diff.js.map +1 -0
- package/dist/graph/graph.d.ts +69 -0
- package/dist/graph/graph.d.ts.map +1 -0
- package/dist/graph/graph.js +284 -0
- package/dist/graph/graph.js.map +1 -0
- package/dist/graph/primitives.d.ts +52 -0
- package/dist/graph/primitives.d.ts.map +1 -0
- package/dist/graph/primitives.js +62 -0
- package/dist/graph/primitives.js.map +1 -0
- package/dist/graph/tracked.d.ts +31 -0
- package/dist/graph/tracked.d.ts.map +1 -0
- package/dist/graph/tracked.js +69 -0
- package/dist/graph/tracked.js.map +1 -0
- package/dist/graph/types.d.ts +34 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +0 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/installation.d.ts +112 -0
- package/dist/installation.d.ts.map +1 -0
- package/dist/installation.js +193 -0
- package/dist/installation.js.map +1 -0
- package/dist/intelligence-bridge.d.ts +73 -0
- package/dist/intelligence-bridge.d.ts.map +1 -0
- package/dist/intelligence-bridge.js +31 -0
- package/dist/intelligence-bridge.js.map +1 -0
- package/dist/invariants/engine.d.ts +36 -0
- package/dist/invariants/engine.d.ts.map +1 -0
- package/dist/invariants/engine.js +88 -0
- package/dist/invariants/engine.js.map +1 -0
- package/dist/invariants/types.d.ts +75 -0
- package/dist/invariants/types.d.ts.map +1 -0
- package/dist/invariants/types.js +2 -0
- package/dist/invariants/types.js.map +1 -0
- package/dist/modules.d.ts +75 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +87 -0
- package/dist/modules.js.map +1 -0
- package/dist/mutations/decidable.d.ts +26 -0
- package/dist/mutations/decidable.d.ts.map +1 -0
- package/dist/mutations/decidable.js +39 -0
- package/dist/mutations/decidable.js.map +1 -0
- package/dist/mutations/define-mutation.d.ts +32 -0
- package/dist/mutations/define-mutation.d.ts.map +1 -0
- package/dist/mutations/define-mutation.js +181 -0
- package/dist/mutations/define-mutation.js.map +1 -0
- package/dist/mutations/derive-edits.d.ts +75 -0
- package/dist/mutations/derive-edits.d.ts.map +1 -0
- package/dist/mutations/derive-edits.js +240 -0
- package/dist/mutations/derive-edits.js.map +1 -0
- package/dist/mutations/form.d.ts +63 -0
- package/dist/mutations/form.d.ts.map +1 -0
- package/dist/mutations/form.js +113 -0
- package/dist/mutations/form.js.map +1 -0
- package/dist/mutations/node-ref.d.ts +83 -0
- package/dist/mutations/node-ref.d.ts.map +1 -0
- package/dist/mutations/node-ref.js +113 -0
- package/dist/mutations/node-ref.js.map +1 -0
- package/dist/mutations/types.d.ts +136 -0
- package/dist/mutations/types.d.ts.map +1 -0
- package/dist/mutations/types.js +2 -0
- package/dist/mutations/types.js.map +1 -0
- package/dist/ops/log.d.ts +35 -0
- package/dist/ops/log.d.ts.map +1 -0
- package/dist/ops/log.js +103 -0
- package/dist/ops/log.js.map +1 -0
- package/dist/ops/types.d.ts +52 -0
- package/dist/ops/types.d.ts.map +1 -0
- package/dist/ops/types.js +2 -0
- package/dist/ops/types.js.map +1 -0
- package/dist/ops/undo.d.ts +33 -0
- package/dist/ops/undo.d.ts.map +1 -0
- package/dist/ops/undo.js +65 -0
- package/dist/ops/undo.js.map +1 -0
- package/dist/permissions/policy.d.ts +68 -0
- package/dist/permissions/policy.d.ts.map +1 -0
- package/dist/permissions/policy.js +191 -0
- package/dist/permissions/policy.js.map +1 -0
- package/dist/permissions/types.d.ts +78 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/persistence/memory.d.ts +6 -0
- package/dist/persistence/memory.d.ts.map +1 -0
- package/dist/persistence/memory.js +31 -0
- package/dist/persistence/memory.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +59 -0
- package/dist/persistence/sqlite.d.ts.map +1 -0
- package/dist/persistence/sqlite.js +131 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/persistence/types.d.ts +22 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +2 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/presence.d.ts +38 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +50 -0
- package/dist/presence.js.map +1 -0
- package/dist/scaffold/domain.d.ts +8 -0
- package/dist/scaffold/domain.d.ts.map +1 -0
- package/dist/scaffold/domain.js +331 -0
- package/dist/scaffold/domain.js.map +1 -0
- package/dist/scaffold/index.d.ts +66 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +142 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/lens.d.ts +31 -0
- package/dist/scaffold/lens.d.ts.map +1 -0
- package/dist/scaffold/lens.js +176 -0
- package/dist/scaffold/lens.js.map +1 -0
- package/dist/scaffold/names.d.ts +44 -0
- package/dist/scaffold/names.d.ts.map +1 -0
- package/dist/scaffold/names.js +69 -0
- package/dist/scaffold/names.js.map +1 -0
- package/dist/scaffold/project.d.ts +41 -0
- package/dist/scaffold/project.d.ts.map +1 -0
- package/dist/scaffold/project.js +604 -0
- package/dist/scaffold/project.js.map +1 -0
- package/dist/scaffold/ui.d.ts +15 -0
- package/dist/scaffold/ui.d.ts.map +1 -0
- package/dist/scaffold/ui.js +536 -0
- package/dist/scaffold/ui.js.map +1 -0
- package/dist/schema/define-node.d.ts +132 -0
- package/dist/schema/define-node.d.ts.map +1 -0
- package/dist/schema/define-node.js +254 -0
- package/dist/schema/define-node.js.map +1 -0
- package/dist/schema/figures.d.ts +42 -0
- package/dist/schema/figures.d.ts.map +1 -0
- package/dist/schema/figures.js +220 -0
- package/dist/schema/figures.js.map +1 -0
- package/dist/schema/json-schema.d.ts +39 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +74 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/schema.d.ts +43 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +102 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/types.d.ts +201 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +2 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/search.d.ts +215 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +449 -0
- package/dist/search.js.map +1 -0
- package/dist/settings.d.ts +30 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +74 -0
- package/dist/settings.js.map +1 -0
- package/dist/store.d.ts +284 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +660 -0
- package/dist/store.js.map +1 -0
- package/dist/studio-door.d.ts +187 -0
- package/dist/studio-door.d.ts.map +1 -0
- package/dist/studio-door.js +20 -0
- package/dist/studio-door.js.map +1 -0
- package/dist/sync/conflict.d.ts +37 -0
- package/dist/sync/conflict.d.ts.map +1 -0
- package/dist/sync/conflict.js +56 -0
- package/dist/sync/conflict.js.map +1 -0
- package/dist/sync/engine.d.ts +118 -0
- package/dist/sync/engine.d.ts.map +1 -0
- package/dist/sync/engine.js +341 -0
- package/dist/sync/engine.js.map +1 -0
- package/dist/sync/google-calendar.d.ts +54 -0
- package/dist/sync/google-calendar.d.ts.map +1 -0
- package/dist/sync/google-calendar.js +167 -0
- package/dist/sync/google-calendar.js.map +1 -0
- package/dist/sync/types.d.ts +125 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +6 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/temporal/effectivity.d.ts +75 -0
- package/dist/temporal/effectivity.d.ts.map +1 -0
- package/dist/temporal/effectivity.js +89 -0
- package/dist/temporal/effectivity.js.map +1 -0
- package/dist/testing.d.ts +63 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +194 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme/contrast.d.ts +47 -0
- package/dist/theme/contrast.d.ts.map +1 -0
- package/dist/theme/contrast.js +172 -0
- package/dist/theme/contrast.js.map +1 -0
- package/dist/theme/derive.d.ts +81 -0
- package/dist/theme/derive.d.ts.map +1 -0
- package/dist/theme/derive.js +171 -0
- package/dist/theme/derive.js.map +1 -0
- package/dist/theme/kit.d.ts +106 -0
- package/dist/theme/kit.d.ts.map +1 -0
- package/dist/theme/kit.js +84 -0
- package/dist/theme/kit.js.map +1 -0
- package/dist/theme/palettes.d.ts +32 -0
- package/dist/theme/palettes.d.ts.map +1 -0
- package/dist/theme/palettes.js +96 -0
- package/dist/theme/palettes.js.map +1 -0
- package/dist/theme/types.d.ts +131 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +23 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/views/types.d.ts +89 -0
- package/dist/views/types.d.ts.map +1 -0
- package/dist/views/types.js +88 -0
- package/dist/views/types.js.map +1 -0
- package/dist/watched.d.ts +33 -0
- package/dist/watched.d.ts.map +1 -0
- package/dist/watched.js +50 -0
- package/dist/watched.js.map +1 -0
- package/dist/who.d.ts +26 -0
- package/dist/who.d.ts.map +1 -0
- package/dist/who.js +20 -0
- package/dist/who.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { PersistenceAdapter } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The slice of better-sqlite3 this adapter needs. Typed structurally so the
|
|
4
|
+
* package never has to import the native module, and so a Drizzle app can
|
|
5
|
+
* hand over its underlying client (`db.$client`) with no wrapper.
|
|
6
|
+
*/
|
|
7
|
+
export interface SqliteStatement {
|
|
8
|
+
all(...params: unknown[]): unknown[];
|
|
9
|
+
run(...params: unknown[]): unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface SqliteDatabase {
|
|
12
|
+
prepare(sql: string): SqliteStatement;
|
|
13
|
+
exec(sql: string): unknown;
|
|
14
|
+
transaction<T extends (...args: never[]) => unknown>(fn: T): T;
|
|
15
|
+
}
|
|
16
|
+
export interface SqliteAdapterOptions {
|
|
17
|
+
readonly database: SqliteDatabase;
|
|
18
|
+
/** Defaults match the household example's existing tables exactly. */
|
|
19
|
+
readonly nodeTable?: string;
|
|
20
|
+
readonly edgeTable?: string;
|
|
21
|
+
readonly opTable?: string;
|
|
22
|
+
/** Column holding the scope key (the household example: `household_id`). */
|
|
23
|
+
readonly scopeColumn?: string;
|
|
24
|
+
/** Creates the tables when absent. Off by default: never touch an app's schema. */
|
|
25
|
+
readonly createTables?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The Drizzle/SQLite table shapes this adapter reads and writes, for an app
|
|
29
|
+
* that wants to declare them in its own Drizzle schema:
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* export const graphNodes = sqliteTable("graph_nodes", {
|
|
33
|
+
* householdId: text("household_id").notNull(),
|
|
34
|
+
* id: text("id").notNull(),
|
|
35
|
+
* kind: text("kind").notNull(),
|
|
36
|
+
* data: text("data").notNull(),
|
|
37
|
+
* }, (t) => [primaryKey({ columns: [t.householdId, t.id] })]);
|
|
38
|
+
*
|
|
39
|
+
* export const graphEdges = sqliteTable("graph_edges", {
|
|
40
|
+
* householdId: text("household_id").notNull(),
|
|
41
|
+
* position: integer("position").notNull(),
|
|
42
|
+
* kind: text("kind").notNull(),
|
|
43
|
+
* fromId: text("from_id").notNull(),
|
|
44
|
+
* toId: text("to_id").notNull(),
|
|
45
|
+
* }, (t) => [primaryKey({ columns: [t.householdId, t.position] })]);
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare const SQLITE_TABLE_SHAPE: {
|
|
49
|
+
readonly nodes: readonly ["scope", "id", "kind", "data"];
|
|
50
|
+
readonly edges: readonly ["scope", "position", "kind", "from_id", "to_id"];
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Reads and writes an app's existing `graph_nodes` / `graph_edges` tables —
|
|
54
|
+
* the shape the household example already stores. `data` is schemaless JSON on disk and
|
|
55
|
+
* becomes a typed node on the way in, validated by the schema registry when
|
|
56
|
+
* the snapshot is loaded into a Graph.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createSqliteAdapter(options: SqliteAdapterOptions): PersistenceAdapter<string>;
|
|
59
|
+
//# sourceMappingURL=sqlite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/persistence/sqlite.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IACrC,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;CACpC;AACD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IACtC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,mFAAmF;IACnF,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,kBAAkB;;;CAGrB,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,GAC5B,kBAAkB,CAAC,MAAM,CAAC,CAmH5B"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Drizzle/SQLite table shapes this adapter reads and writes, for an app
|
|
3
|
+
* that wants to declare them in its own Drizzle schema:
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* export const graphNodes = sqliteTable("graph_nodes", {
|
|
7
|
+
* householdId: text("household_id").notNull(),
|
|
8
|
+
* id: text("id").notNull(),
|
|
9
|
+
* kind: text("kind").notNull(),
|
|
10
|
+
* data: text("data").notNull(),
|
|
11
|
+
* }, (t) => [primaryKey({ columns: [t.householdId, t.id] })]);
|
|
12
|
+
*
|
|
13
|
+
* export const graphEdges = sqliteTable("graph_edges", {
|
|
14
|
+
* householdId: text("household_id").notNull(),
|
|
15
|
+
* position: integer("position").notNull(),
|
|
16
|
+
* kind: text("kind").notNull(),
|
|
17
|
+
* fromId: text("from_id").notNull(),
|
|
18
|
+
* toId: text("to_id").notNull(),
|
|
19
|
+
* }, (t) => [primaryKey({ columns: [t.householdId, t.position] })]);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export const SQLITE_TABLE_SHAPE = {
|
|
23
|
+
nodes: ["scope", "id", "kind", "data"],
|
|
24
|
+
edges: ["scope", "position", "kind", "from_id", "to_id"],
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Reads and writes an app's existing `graph_nodes` / `graph_edges` tables —
|
|
28
|
+
* the shape the household example already stores. `data` is schemaless JSON on disk and
|
|
29
|
+
* becomes a typed node on the way in, validated by the schema registry when
|
|
30
|
+
* the snapshot is loaded into a Graph.
|
|
31
|
+
*/
|
|
32
|
+
export function createSqliteAdapter(options) {
|
|
33
|
+
const db = options.database;
|
|
34
|
+
const nodeTable = options.nodeTable ?? "graph_nodes";
|
|
35
|
+
const edgeTable = options.edgeTable ?? "graph_edges";
|
|
36
|
+
const opTable = options.opTable ?? "graview_ops";
|
|
37
|
+
const scope = options.scopeColumn ?? "household_id";
|
|
38
|
+
if (options.createTables) {
|
|
39
|
+
db.exec(`
|
|
40
|
+
CREATE TABLE IF NOT EXISTS ${nodeTable} (
|
|
41
|
+
${scope} TEXT NOT NULL, id TEXT NOT NULL,
|
|
42
|
+
kind TEXT NOT NULL, data TEXT NOT NULL,
|
|
43
|
+
PRIMARY KEY (${scope}, id)
|
|
44
|
+
);
|
|
45
|
+
CREATE TABLE IF NOT EXISTS ${edgeTable} (
|
|
46
|
+
${scope} TEXT NOT NULL, position INTEGER NOT NULL,
|
|
47
|
+
kind TEXT NOT NULL, from_id TEXT NOT NULL, to_id TEXT NOT NULL,
|
|
48
|
+
PRIMARY KEY (${scope}, position)
|
|
49
|
+
);
|
|
50
|
+
CREATE TABLE IF NOT EXISTS ${opTable} (
|
|
51
|
+
${scope} TEXT NOT NULL, seq INTEGER NOT NULL, data TEXT NOT NULL,
|
|
52
|
+
PRIMARY KEY (${scope}, seq)
|
|
53
|
+
);
|
|
54
|
+
`);
|
|
55
|
+
}
|
|
56
|
+
const selectNodes = db.prepare(`SELECT id, kind, data FROM ${nodeTable} WHERE ${scope} = ?`);
|
|
57
|
+
const selectEdges = db.prepare(`SELECT kind, from_id, to_id FROM ${edgeTable} WHERE ${scope} = ? ORDER BY position ASC`);
|
|
58
|
+
const deleteNodes = db.prepare(`DELETE FROM ${nodeTable} WHERE ${scope} = ?`);
|
|
59
|
+
const deleteEdges = db.prepare(`DELETE FROM ${edgeTable} WHERE ${scope} = ?`);
|
|
60
|
+
const insertNode = db.prepare(`INSERT INTO ${nodeTable} (${scope}, id, kind, data) VALUES (?, ?, ?, ?)`);
|
|
61
|
+
const insertEdge = db.prepare(`INSERT INTO ${edgeTable} (${scope}, position, kind, from_id, to_id) VALUES (?, ?, ?, ?, ?)`);
|
|
62
|
+
/**
|
|
63
|
+
* The op table is the framework's own, not the app's, so it is created on
|
|
64
|
+
* demand. The node and edge tables are the app's and are never touched
|
|
65
|
+
* unless `createTables` explicitly asks for them.
|
|
66
|
+
*/
|
|
67
|
+
let opTableReady = false;
|
|
68
|
+
function ensureOpTable() {
|
|
69
|
+
if (opTableReady)
|
|
70
|
+
return;
|
|
71
|
+
db.exec(`CREATE TABLE IF NOT EXISTS ${opTable} (
|
|
72
|
+
${scope} TEXT NOT NULL, seq INTEGER NOT NULL, data TEXT NOT NULL,
|
|
73
|
+
PRIMARY KEY (${scope}, seq)
|
|
74
|
+
)`);
|
|
75
|
+
opTableReady = true;
|
|
76
|
+
}
|
|
77
|
+
const write = db.transaction(((key, snapshot) => {
|
|
78
|
+
deleteEdges.run(key);
|
|
79
|
+
deleteNodes.run(key);
|
|
80
|
+
for (const node of snapshot.nodes) {
|
|
81
|
+
insertNode.run(key, node.id, node.kind, JSON.stringify(node));
|
|
82
|
+
}
|
|
83
|
+
snapshot.edges.forEach((edge, position) => {
|
|
84
|
+
insertEdge.run(key, position, edge.kind, edge.from, edge.to);
|
|
85
|
+
});
|
|
86
|
+
}));
|
|
87
|
+
return {
|
|
88
|
+
name: "sqlite",
|
|
89
|
+
async load(key) {
|
|
90
|
+
const nodeRows = selectNodes.all(key);
|
|
91
|
+
if (nodeRows.length === 0)
|
|
92
|
+
return null;
|
|
93
|
+
const edgeRows = selectEdges.all(key);
|
|
94
|
+
const nodes = nodeRows.map((row) => {
|
|
95
|
+
const parsed = JSON.parse(row.data);
|
|
96
|
+
// `id` and `kind` live in columns as well as the JSON blob; the
|
|
97
|
+
// columns win so a row is never internally inconsistent.
|
|
98
|
+
return { ...parsed, id: row.id, kind: row.kind };
|
|
99
|
+
});
|
|
100
|
+
const edges = edgeRows.map((row) => ({
|
|
101
|
+
kind: row.kind,
|
|
102
|
+
from: row.from_id,
|
|
103
|
+
to: row.to_id,
|
|
104
|
+
}));
|
|
105
|
+
return { nodes, edges };
|
|
106
|
+
},
|
|
107
|
+
async save(key, snapshot) {
|
|
108
|
+
write(key, snapshot);
|
|
109
|
+
},
|
|
110
|
+
async delete(key) {
|
|
111
|
+
deleteEdges.run(key);
|
|
112
|
+
deleteNodes.run(key);
|
|
113
|
+
},
|
|
114
|
+
async loadLog(key) {
|
|
115
|
+
ensureOpTable();
|
|
116
|
+
const rows = db
|
|
117
|
+
.prepare(`SELECT data FROM ${opTable} WHERE ${scope} = ? ORDER BY seq ASC`)
|
|
118
|
+
.all(key);
|
|
119
|
+
return rows.map((row) => JSON.parse(row.data));
|
|
120
|
+
},
|
|
121
|
+
async appendOps(key, ops) {
|
|
122
|
+
if (ops.length === 0)
|
|
123
|
+
return;
|
|
124
|
+
ensureOpTable();
|
|
125
|
+
const insert = db.prepare(`INSERT OR REPLACE INTO ${opTable} (${scope}, seq, data) VALUES (?, ?, ?)`);
|
|
126
|
+
for (const op of ops)
|
|
127
|
+
insert.run(key, op.seq, JSON.stringify(op));
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=sqlite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/persistence/sqlite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GraphSnapshot } from "../graph/types.js";
|
|
2
|
+
import type { Operation } from "../ops/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* The framework owns the reactive graph, invariants, diff and undo;
|
|
5
|
+
* persistence is pluggable underneath. One interface, so a memory adapter
|
|
6
|
+
* in a test and a SQLite adapter in production are interchangeable.
|
|
7
|
+
*/
|
|
8
|
+
export interface PersistenceAdapter<Scope = string> {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
/**
|
|
11
|
+
* Returns null when nothing has been stored for this scope. Note that a
|
|
12
|
+
* store of an EMPTY graph is indistinguishable from no store at all in a
|
|
13
|
+
* row-backed adapter — treat "null" as "no nodes", not as "never saved".
|
|
14
|
+
*/
|
|
15
|
+
load(scope: Scope): Promise<GraphSnapshot | null>;
|
|
16
|
+
save(scope: Scope, snapshot: GraphSnapshot): Promise<void>;
|
|
17
|
+
delete(scope: Scope): Promise<void>;
|
|
18
|
+
/** Optional: adapters that keep history append the log too. */
|
|
19
|
+
loadLog?(scope: Scope): Promise<Operation[]>;
|
|
20
|
+
appendOps?(scope: Scope, ops: readonly Operation[]): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/persistence/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,MAAM;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,+DAA+D;IAC/D,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC7C,SAAS,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/persistence/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface PresenceRobot {
|
|
2
|
+
/** What the robot stands at: a node id, `kind:<kind>`, or null for its dock. */
|
|
3
|
+
readonly at: string | null;
|
|
4
|
+
readonly mode: string;
|
|
5
|
+
}
|
|
6
|
+
export interface Presence {
|
|
7
|
+
/** `kind:id:session` — the op log's own reading of an author, so a figure and its edits agree. */
|
|
8
|
+
readonly participant: string;
|
|
9
|
+
/** What to call them. Absent for an anonymous viewer, who is counted rather than drawn. */
|
|
10
|
+
readonly name?: string;
|
|
11
|
+
readonly hue: number;
|
|
12
|
+
/** Where they are: `toUrl(view)`, the complete answer. */
|
|
13
|
+
readonly stop: string;
|
|
14
|
+
/** What they are hovering, when they have chosen to share it. */
|
|
15
|
+
readonly over?: string | null;
|
|
16
|
+
/** Their seat's robot, if it has a body somewhere. */
|
|
17
|
+
readonly robot?: PresenceRobot;
|
|
18
|
+
/** When they last said so, ISO. */
|
|
19
|
+
readonly at: string;
|
|
20
|
+
}
|
|
21
|
+
export interface PresenceChannel {
|
|
22
|
+
/** Say where you are. Called on every change and on every heartbeat. */
|
|
23
|
+
here(presence: Presence): void;
|
|
24
|
+
/** Told who else is here, every time that changes. Returns the way to stop listening. */
|
|
25
|
+
onWho(listener: (who: readonly Presence[]) => void): () => void;
|
|
26
|
+
/** Say you have gone, and stop. */
|
|
27
|
+
leave(): void;
|
|
28
|
+
}
|
|
29
|
+
/** How long a presence stands after its last word: three missed heartbeats at the poll's own pace. */
|
|
30
|
+
export declare const PRESENCE_TTL_MS = 2500;
|
|
31
|
+
/**
|
|
32
|
+
* The others as they are now: what arrived, minus what has gone quiet, minus
|
|
33
|
+
* yourself. Pure, so a test can ask what a viewer sees without a channel.
|
|
34
|
+
*/
|
|
35
|
+
export declare function foldPresence(known: ReadonlyMap<string, Presence>, arrived: readonly Presence[], now: number, ttlMs?: number, self?: string): Map<string, Presence>;
|
|
36
|
+
/** Two presences that would draw the same figure in the same place. */
|
|
37
|
+
export declare function samePresence(a: Presence | undefined, b: Presence | undefined): boolean;
|
|
38
|
+
//# sourceMappingURL=presence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,kGAAkG;IAClG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,mCAAmC;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,yFAAyF;IACzF,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,QAAQ,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAChE,mCAAmC;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,sGAAsG;AACtG,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,EACpC,OAAO,EAAE,SAAS,QAAQ,EAAE,EAC5B,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,MAAwB,EAC/B,IAAI,CAAC,EAAE,MAAM,GACZ,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAevB;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,GAAG,SAAS,EAAE,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAWtF"}
|
package/dist/presence.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHO IS WHERE — a fact about a person at a screen, not a change to the graph.
|
|
3
|
+
*
|
|
4
|
+
* Presence never enters the op log. It is a payload each viewer sends about
|
|
5
|
+
* itself — which stop it is on, what it is hovering, where its robot stands
|
|
6
|
+
* — and each viewer draws everybody else on ITS OWN map from those facts,
|
|
7
|
+
* so two windows of different sizes agree about who is at the tasks plot
|
|
8
|
+
* without agreeing about a single pixel. The channel that carries it is
|
|
9
|
+
* behind one interface with two implementations in `@graview/ship`: a
|
|
10
|
+
* BroadcastChannel between tabs of one origin, and two routes on the served
|
|
11
|
+
* store folded into the poll it already makes.
|
|
12
|
+
*/
|
|
13
|
+
/** How long a presence stands after its last word: three missed heartbeats at the poll's own pace. */
|
|
14
|
+
export const PRESENCE_TTL_MS = 2500;
|
|
15
|
+
/**
|
|
16
|
+
* The others as they are now: what arrived, minus what has gone quiet, minus
|
|
17
|
+
* yourself. Pure, so a test can ask what a viewer sees without a channel.
|
|
18
|
+
*/
|
|
19
|
+
export function foldPresence(known, arrived, now, ttlMs = PRESENCE_TTL_MS, self) {
|
|
20
|
+
const next = new Map();
|
|
21
|
+
for (const [participant, presence] of known) {
|
|
22
|
+
if (now - Date.parse(presence.at) < ttlMs)
|
|
23
|
+
next.set(participant, presence);
|
|
24
|
+
}
|
|
25
|
+
for (const presence of arrived) {
|
|
26
|
+
if (now - Date.parse(presence.at) >= ttlMs) {
|
|
27
|
+
next.delete(presence.participant);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const held = next.get(presence.participant);
|
|
31
|
+
if (!held || Date.parse(held.at) <= Date.parse(presence.at))
|
|
32
|
+
next.set(presence.participant, presence);
|
|
33
|
+
}
|
|
34
|
+
if (self !== undefined)
|
|
35
|
+
next.delete(self);
|
|
36
|
+
return next;
|
|
37
|
+
}
|
|
38
|
+
/** Two presences that would draw the same figure in the same place. */
|
|
39
|
+
export function samePresence(a, b) {
|
|
40
|
+
if (!a || !b)
|
|
41
|
+
return a === b;
|
|
42
|
+
return (a.participant === b.participant &&
|
|
43
|
+
a.name === b.name &&
|
|
44
|
+
a.hue === b.hue &&
|
|
45
|
+
a.stop === b.stop &&
|
|
46
|
+
(a.over ?? null) === (b.over ?? null) &&
|
|
47
|
+
(a.robot?.at ?? null) === (b.robot?.at ?? null) &&
|
|
48
|
+
(a.robot?.mode ?? null) === (b.robot?.mode ?? null));
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=presence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAiCH,sGAAsG;AACtG,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AAEpC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAoC,EACpC,OAA4B,EAC5B,GAAW,EACX,QAAgB,eAAe,EAC/B,IAAa;IAEb,MAAM,IAAI,GAAG,IAAI,GAAG,EAAoB,CAAC;IACzC,KAAK,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC;QAC5C,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,KAAK;YAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC7E,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAClC,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACxG,CAAC;IACD,IAAI,IAAI,KAAK,SAAS;QAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,CAAuB,EAAE,CAAuB;IAC3E,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,CACL,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,WAAW;QAC/B,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;QACjB,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG;QACf,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;QACjB,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC;QACrC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,IAAI,IAAI,CAAC;QAC/C,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,CACpD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Ids } from "./names.js";
|
|
2
|
+
export declare function schemaTs(ids: Ids): string;
|
|
3
|
+
export declare function mutationsTs(ids: Ids): string;
|
|
4
|
+
export declare function invariantsTs(ids: Ids): string;
|
|
5
|
+
export declare function brandTs(ids: Ids): string;
|
|
6
|
+
export declare function appTs(ids: Ids): string;
|
|
7
|
+
export declare function domainTest(ids: Ids): string;
|
|
8
|
+
//# sourceMappingURL=domain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../src/scaffold/domain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAgC,MAAM,YAAY,CAAC;AASpE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAsCzC;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAkF5C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAgD7C;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAqCxC;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAkDtC;AAID,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CA8D3C"}
|