@evolu/common 7.4.1 → 8.0.0-next.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/README.md +4 -61
- package/dist/src/Array.d.ts +343 -102
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +181 -85
- package/dist/src/Assert.d.ts +57 -11
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +47 -11
- package/dist/src/BigInt.d.ts +6 -1
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -0
- package/dist/src/Brand.d.ts +40 -12
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Brand.js +5 -0
- package/dist/src/Buffer.d.ts +6 -1
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Buffer.js +7 -2
- package/dist/src/Cache.d.ts +10 -2
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +6 -0
- package/dist/src/Callbacks.d.ts +10 -7
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Callbacks.js +23 -13
- package/dist/src/Console.d.ts +361 -69
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +217 -117
- package/dist/src/Crypto.d.ts +70 -21
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +72 -27
- package/dist/src/Eq.d.ts +22 -2
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +21 -1
- package/dist/src/Error.d.ts +23 -12
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +27 -11
- package/dist/src/Function.d.ts +128 -56
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +118 -14
- package/dist/src/Identicon.d.ts +5 -0
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +6 -1
- package/dist/src/Lookup.d.ts +160 -0
- package/dist/src/Lookup.d.ts.map +1 -0
- package/dist/src/Lookup.js +192 -0
- package/dist/src/Microtask.d.ts +21 -0
- package/dist/src/Microtask.d.ts.map +1 -0
- package/dist/src/Microtask.js +37 -0
- package/dist/src/Number.d.ts +18 -4
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +23 -1
- package/dist/src/Object.d.ts +110 -5
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +108 -5
- package/dist/src/Option.d.ts +58 -0
- package/dist/src/Option.d.ts.map +1 -0
- package/dist/src/Option.js +43 -0
- package/dist/src/Order.d.ts +5 -0
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +8 -3
- package/dist/src/Platform.d.ts +36 -2
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +10 -6
- package/dist/src/Polyfills.d.ts +27 -0
- package/dist/src/Polyfills.d.ts.map +1 -0
- package/dist/src/Polyfills.js +299 -0
- package/dist/src/Random.d.ts +18 -7
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +9 -7
- package/dist/src/Redacted.d.ts +7 -4
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +5 -0
- package/dist/src/Ref.d.ts +31 -16
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +35 -7
- package/dist/src/RefCount.d.ts +62 -0
- package/dist/src/RefCount.d.ts.map +1 -0
- package/dist/src/RefCount.js +83 -0
- package/dist/src/Relation.d.ts +84 -29
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +83 -105
- package/dist/src/Resource.d.ts +263 -0
- package/dist/src/Resource.d.ts.map +1 -0
- package/dist/src/Resource.js +389 -0
- package/dist/src/Result.d.ts +390 -374
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +142 -70
- package/dist/src/Schedule.d.ts +953 -0
- package/dist/src/Schedule.d.ts.map +1 -0
- package/dist/src/Schedule.js +1199 -0
- package/dist/src/Set.d.ts +181 -0
- package/dist/src/Set.d.ts.map +1 -0
- package/dist/src/Set.js +137 -0
- package/dist/src/Skiplist.d.ts +6 -1
- package/dist/src/Skiplist.d.ts.map +1 -1
- package/dist/src/Skiplist.js +5 -0
- package/dist/src/Sqlite.d.ts +160 -60
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +290 -190
- package/dist/src/Store.d.ts +36 -28
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +55 -15
- package/dist/src/String.d.ts +5 -0
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +5 -0
- package/dist/src/Task.d.ts +2263 -423
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1488 -348
- package/dist/src/Test.d.ts +122 -0
- package/dist/src/Test.d.ts.map +1 -0
- package/dist/src/Test.js +66 -0
- package/dist/src/Time.d.ts +201 -48
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +190 -86
- package/dist/src/Tracer.d.ts +48 -0
- package/dist/src/Tracer.d.ts.map +1 -0
- package/dist/src/Tracer.js +6 -0
- package/dist/src/Type.d.ts +582 -209
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +362 -240
- package/dist/src/Types.d.ts +160 -6
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +22 -2
- package/dist/src/WebSocket.d.ts +113 -58
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +210 -118
- package/dist/src/Worker.d.ts +245 -60
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +220 -64
- package/dist/src/index.d.ts +25 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +19 -3
- package/dist/src/local-first/Db.d.ts +24 -213
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +622 -293
- package/dist/src/local-first/Error.d.ts +12 -0
- package/dist/src/local-first/Error.d.ts.map +1 -0
- package/dist/src/local-first/Error.js +6 -0
- package/dist/src/local-first/Evolu.d.ts +330 -285
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +472 -402
- package/dist/src/local-first/LocalAuth.d.ts +10 -10
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/LocalAuth.js +6 -1
- package/dist/src/local-first/Owner.d.ts +70 -27
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +27 -14
- package/dist/src/local-first/Protocol.d.ts +58 -50
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +253 -155
- package/dist/src/local-first/Query.d.ts +133 -43
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +139 -90
- package/dist/src/local-first/Relay.d.ts +18 -38
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +59 -171
- package/dist/src/local-first/Schema.d.ts +139 -144
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +78 -163
- package/dist/src/local-first/Shared.d.ts +125 -0
- package/dist/src/local-first/Shared.d.ts.map +1 -0
- package/dist/src/local-first/Shared.js +569 -0
- package/dist/src/local-first/Storage.d.ts +50 -53
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +121 -173
- package/dist/src/local-first/Timestamp.d.ts +28 -35
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +24 -25
- package/dist/src/local-first/index.d.ts +2 -15
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +2 -15
- package/package.json +36 -26
- package/src/Array.ts +467 -106
- package/src/Assert.ts +87 -12
- package/src/BigInt.ts +7 -1
- package/src/Brand.ts +41 -12
- package/src/Buffer.ts +10 -4
- package/src/Cache.ts +11 -2
- package/src/Callbacks.ts +33 -23
- package/src/Console.ts +567 -178
- package/src/Crypto.ts +111 -62
- package/src/Eq.ts +30 -3
- package/src/Error.ts +50 -34
- package/src/Function.ts +140 -68
- package/src/Identicon.ts +7 -1
- package/src/Lookup.ts +415 -0
- package/src/Microtask.ts +58 -0
- package/src/Number.ts +40 -7
- package/src/Object.ts +155 -16
- package/src/Option.ts +74 -0
- package/src/Order.ts +11 -3
- package/src/Platform.ts +43 -7
- package/src/Polyfills.ts +465 -0
- package/src/Random.ts +25 -11
- package/src/Redacted.ts +8 -4
- package/src/Ref.ts +72 -21
- package/src/RefCount.ts +170 -0
- package/src/Relation.ts +188 -136
- package/src/Resource.ts +864 -0
- package/src/Result.ts +548 -381
- package/src/Schedule.ts +1471 -0
- package/src/Set.ts +247 -0
- package/src/Skiplist.ts +7 -1
- package/src/Sqlite.ts +409 -304
- package/src/Store.ts +94 -48
- package/src/String.ts +6 -0
- package/src/Task.ts +3685 -740
- package/src/Test.ts +162 -0
- package/src/Time.ts +348 -145
- package/src/Tracer.ts +54 -0
- package/src/Type.ts +851 -430
- package/src/Types.ts +202 -7
- package/src/WebSocket.ts +311 -178
- package/src/Worker.ts +527 -147
- package/src/index.ts +74 -3
- package/src/local-first/Db.ts +871 -597
- package/src/local-first/Error.ts +17 -0
- package/src/local-first/Evolu.ts +884 -824
- package/src/local-first/LocalAuth.ts +10 -10
- package/src/local-first/Owner.ts +94 -42
- package/src/local-first/Protocol.ts +440 -303
- package/src/local-first/Query.ts +243 -194
- package/src/local-first/Relay.ts +91 -252
- package/src/local-first/Schema.ts +284 -394
- package/src/local-first/Shared.ts +932 -0
- package/src/local-first/Storage.ts +206 -277
- package/src/local-first/Timestamp.ts +38 -45
- package/src/local-first/index.ts +2 -16
- package/LICENSE +0 -21
- package/dist/src/Instances.d.ts +0 -34
- package/dist/src/Instances.d.ts.map +0 -1
- package/dist/src/Instances.js +0 -44
- package/dist/src/Resources.d.ts +0 -118
- package/dist/src/Resources.d.ts.map +0 -1
- package/dist/src/Resources.js +0 -197
- package/dist/src/local-first/Platform.d.ts +0 -25
- package/dist/src/local-first/Platform.d.ts.map +0 -1
- package/dist/src/local-first/Platform.js +0 -1
- package/dist/src/local-first/Public.d.ts +0 -22
- package/dist/src/local-first/Public.d.ts.map +0 -1
- package/dist/src/local-first/Public.js +0 -15
- package/dist/src/local-first/PublicKysely.d.ts +0 -148
- package/dist/src/local-first/PublicKysely.d.ts.map +0 -1
- package/dist/src/local-first/PublicKysely.js +0 -184
- package/dist/src/local-first/Sync.d.ts +0 -112
- package/dist/src/local-first/Sync.d.ts.map +0 -1
- package/dist/src/local-first/Sync.js +0 -526
- package/src/Instances.ts +0 -92
- package/src/Resources.ts +0 -367
- package/src/local-first/Platform.ts +0 -27
- package/src/local-first/Public.ts +0 -42
- package/src/local-first/PublicKysely.ts +0 -239
- package/src/local-first/Sync.ts +0 -949
|
@@ -1,29 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { Simplify } from "
|
|
1
|
+
/**
|
|
2
|
+
* Query helpers, execution, and caching.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { AliasableExpression, Expression, Simplify as KyselySimplify, RawBuilder, SelectQueryNode } from "kysely";
|
|
7
|
+
import type { Brand } from "../Brand.js";
|
|
8
|
+
import type { SqliteQueryString } from "../Sqlite.js";
|
|
9
|
+
import { SqliteValue } from "../Sqlite.js";
|
|
10
|
+
import type { Simplify } from "../Types.js";
|
|
11
|
+
import type { EvoluSchema } from "./Schema.js";
|
|
12
|
+
export { sql as kyselySql } from "kysely";
|
|
13
|
+
export type { NotNull as KyselyNotNull } from "kysely";
|
|
7
14
|
/**
|
|
8
15
|
* A type-safe SQL query.
|
|
9
16
|
*
|
|
10
17
|
* ### Example
|
|
11
18
|
*
|
|
12
19
|
* ```ts
|
|
13
|
-
* const
|
|
14
|
-
*
|
|
15
|
-
* );
|
|
20
|
+
* const createQuery = createQueryBuilder(Schema);
|
|
21
|
+
* const allTodos = createQuery((db) => db.selectFrom("todo").selectAll());
|
|
16
22
|
* type AllTodosRow = typeof allTodos.Row;
|
|
17
23
|
* ```
|
|
18
24
|
*/
|
|
19
|
-
export type Query<R extends Row = Row> =
|
|
25
|
+
export type Query<S extends EvoluSchema = EvoluSchema, R extends Row = Row> = SqliteQueryString & Brand<"Query"> & {
|
|
26
|
+
/** A shorthand for the query schema. */
|
|
27
|
+
Schema: S;
|
|
20
28
|
/**
|
|
21
29
|
* A shorthand for {@link InferRow}.
|
|
22
30
|
*
|
|
23
31
|
* ### Example
|
|
24
32
|
*
|
|
25
33
|
* ```ts
|
|
26
|
-
* const
|
|
34
|
+
* const createQuery = createQueryBuilder(Schema);
|
|
35
|
+
* const allTodos = createQuery((db) =>
|
|
27
36
|
* db.selectFrom("todo").selectAll(),
|
|
28
37
|
* );
|
|
29
38
|
* type AllTodosRow = typeof allTodos.Row;
|
|
@@ -31,47 +40,124 @@ export type Query<R extends Row = Row> = string & Brand<"Query"> & {
|
|
|
31
40
|
*/
|
|
32
41
|
Row: R;
|
|
33
42
|
};
|
|
34
|
-
|
|
35
|
-
* Evolu serializes {@link SqliteQuery} into a string to be easily used as a key
|
|
36
|
-
* and for comparison.
|
|
37
|
-
*/
|
|
38
|
-
export declare const serializeQuery: <R extends Row>(query: SqliteQuery) => Query<R>;
|
|
39
|
-
export declare const deserializeQuery: <R extends Row>(query: Query<R>) => SqliteQuery;
|
|
40
|
-
export type InferRow<T extends Query> = T extends Query<infer R> ? R : never;
|
|
43
|
+
export type InferRow<T extends Query> = T extends Query<any, infer R> ? R : never;
|
|
41
44
|
export interface Row {
|
|
42
45
|
readonly [key: string]: SqliteValue | Row | ReadonlyArray<Row>;
|
|
43
46
|
}
|
|
44
|
-
|
|
47
|
+
/**
|
|
48
|
+
* An improved Evolu version of Kysely's SQLite `jsonArrayFrom` helper.
|
|
49
|
+
*
|
|
50
|
+
* Kysely's `ParseJSONResultsPlugin` heuristically parses any result string that
|
|
51
|
+
* looks like JSON. Evolu instead prefixes JSON produced by these helpers with a
|
|
52
|
+
* per-runtime identifier and only parses values carrying that prefix, avoiding
|
|
53
|
+
* accidental parsing of ordinary string columns that merely happen to start
|
|
54
|
+
* with `{` or `[`.
|
|
55
|
+
*
|
|
56
|
+
* ### Example
|
|
57
|
+
*
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { evoluJsonArrayFrom } from "@evolu/common";
|
|
60
|
+
*
|
|
61
|
+
* const result = await db
|
|
62
|
+
* .selectFrom("person")
|
|
63
|
+
* .select((eb) => [
|
|
64
|
+
* "id",
|
|
65
|
+
* evoluJsonArrayFrom(
|
|
66
|
+
* eb
|
|
67
|
+
* .selectFrom("pet")
|
|
68
|
+
* .select(["pet.id as pet_id", "pet.name"])
|
|
69
|
+
* .whereRef("pet.owner_id", "=", "person.id")
|
|
70
|
+
* .orderBy("pet.name"),
|
|
71
|
+
* ).as("pets"),
|
|
72
|
+
* ])
|
|
73
|
+
* .execute();
|
|
74
|
+
*
|
|
75
|
+
* result[0]?.id;
|
|
76
|
+
* result[0]?.pets[0].pet_id;
|
|
77
|
+
* result[0]?.pets[0].name;
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare const evoluJsonArrayFrom: <O>(expr: SelectQueryBuilderExpression<O>) => RawBuilder<Array<KyselySimplify<O>>>;
|
|
81
|
+
/**
|
|
82
|
+
* An improved Evolu version of Kysely's SQLite `jsonObjectFrom` helper.
|
|
83
|
+
*
|
|
84
|
+
* Kysely's `ParseJSONResultsPlugin` heuristically parses any result string that
|
|
85
|
+
* looks like JSON. Evolu instead prefixes JSON produced by these helpers with a
|
|
86
|
+
* per-runtime identifier and only parses values carrying that prefix, avoiding
|
|
87
|
+
* accidental parsing of ordinary string columns that merely happen to start
|
|
88
|
+
* with `{` or `[`.
|
|
89
|
+
*
|
|
90
|
+
* The subquery must only return one row.
|
|
91
|
+
*
|
|
92
|
+
* ### Example
|
|
93
|
+
*
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { evoluJsonObjectFrom } from "@evolu/common";
|
|
96
|
+
*
|
|
97
|
+
* const result = await db
|
|
98
|
+
* .selectFrom("person")
|
|
99
|
+
* .select((eb) => [
|
|
100
|
+
* "id",
|
|
101
|
+
* evoluJsonObjectFrom(
|
|
102
|
+
* eb
|
|
103
|
+
* .selectFrom("pet")
|
|
104
|
+
* .select(["pet.id as pet_id", "pet.name"])
|
|
105
|
+
* .whereRef("pet.owner_id", "=", "person.id")
|
|
106
|
+
* .where("pet.is_favorite", "=", true),
|
|
107
|
+
* ).as("favorite_pet"),
|
|
108
|
+
* ])
|
|
109
|
+
* .execute();
|
|
110
|
+
*
|
|
111
|
+
* result[0]?.id;
|
|
112
|
+
* result[0]?.favorite_pet?.pet_id;
|
|
113
|
+
* result[0]?.favorite_pet?.name;
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare const evoluJsonObjectFrom: <O>(expr: SelectQueryBuilderExpression<O>) => RawBuilder<KyselySimplify<O> | null>;
|
|
117
|
+
/**
|
|
118
|
+
* An improved Evolu version of Kysely's SQLite `jsonBuildObject` helper.
|
|
119
|
+
*
|
|
120
|
+
* Kysely's `ParseJSONResultsPlugin` heuristically parses any result string that
|
|
121
|
+
* looks like JSON. Evolu instead prefixes JSON produced by these helpers with a
|
|
122
|
+
* per-runtime identifier and only parses values carrying that prefix, avoiding
|
|
123
|
+
* accidental parsing of ordinary string columns that merely happen to start
|
|
124
|
+
* with `{` or `[`.
|
|
125
|
+
*
|
|
126
|
+
* ### Example
|
|
127
|
+
*
|
|
128
|
+
* ```ts
|
|
129
|
+
* import { evoluJsonBuildObject, kyselySql } from "@evolu/common";
|
|
130
|
+
*
|
|
131
|
+
* const result = await db
|
|
132
|
+
* .selectFrom("person")
|
|
133
|
+
* .select((eb) => [
|
|
134
|
+
* "id",
|
|
135
|
+
* evoluJsonBuildObject({
|
|
136
|
+
* first: eb.ref("first_name"),
|
|
137
|
+
* last: eb.ref("last_name"),
|
|
138
|
+
* full: kyselySql<string>`first_name || ' ' || last_name`,
|
|
139
|
+
* }).as("name"),
|
|
140
|
+
* ])
|
|
141
|
+
* .execute();
|
|
142
|
+
*
|
|
143
|
+
* result[0]?.id;
|
|
144
|
+
* result[0]?.name.first;
|
|
145
|
+
* result[0]?.name.last;
|
|
146
|
+
* result[0]?.name.full;
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export declare const evoluJsonBuildObject: <O extends Record<string, Expression<unknown>>>(obj: O) => RawBuilder<KyselySimplify<{ [K in keyof O]: O[K] extends Expression<infer V> ? V : never; }>>;
|
|
150
|
+
export declare const getJsonObjectArgs: (node: SelectQueryNode, table: string) => Array<Expression<unknown> | string>;
|
|
45
151
|
/** Rows returned by a query. */
|
|
46
152
|
export type QueryRows<R extends Row = Row> = ReadonlyArray<Readonly<Simplify<R>>>;
|
|
47
|
-
export type Queries<R extends Row = Row> = ReadonlyArray<Query<R>>;
|
|
153
|
+
export type Queries<S extends EvoluSchema = EvoluSchema, R extends Row = Row> = ReadonlyArray<Query<S, R>>;
|
|
48
154
|
export type QueriesToQueryRows<Q extends Queries> = {
|
|
49
|
-
[P in keyof Q]: Q[P] extends Query<infer R> ? QueryRows<R> : never;
|
|
155
|
+
[P in keyof Q]: Q[P] extends Query<any, infer R> ? QueryRows<R> : never;
|
|
50
156
|
};
|
|
51
157
|
export type QueriesToQueryRowsPromises<Q extends Queries> = {
|
|
52
|
-
[P in keyof Q]: Q[P] extends Query<infer R> ? Promise<QueryRows<R>> : never;
|
|
158
|
+
[P in keyof Q]: Q[P] extends Query<any, infer R> ? Promise<QueryRows<R>> : never;
|
|
53
159
|
};
|
|
54
|
-
export type
|
|
55
|
-
export interface SubscribedQueries {
|
|
56
|
-
subscribe: (query: Query) => StoreSubscribe;
|
|
57
|
-
has: (query: Query) => boolean;
|
|
58
|
-
get: () => ReadonlyArray<Query>;
|
|
59
|
-
}
|
|
60
|
-
export declare const createSubscribedQueries: (rowsStore: Store<QueryRowsMap>) => SubscribedQueries;
|
|
61
|
-
export interface GetQueryRowsCacheDep {
|
|
62
|
-
readonly getQueryRowsCache: GetQueryRowsCache;
|
|
63
|
-
}
|
|
64
|
-
export type GetQueryRowsCache = (tabId: Id) => QueryRowsCache;
|
|
65
|
-
export interface QueryRowsCache {
|
|
66
|
-
readonly set: (queriesRows: ReadonlyArray<readonly [Query, ReadonlyArray<SqliteRow>]>) => void;
|
|
67
|
-
readonly get: () => QueryRowsMap;
|
|
68
|
-
}
|
|
69
|
-
export declare const createGetQueryRowsCache: () => GetQueryRowsCache;
|
|
70
|
-
export declare const loadQueries: (deps: GetQueryRowsCacheDep & SqliteDep) => (tabId: Id, queries: ReadonlyArray<Query>) => Result<ReadonlyArray<QueryPatches>, SqliteError>;
|
|
71
|
-
export interface QueryPatches {
|
|
72
|
-
readonly query: Query;
|
|
73
|
-
readonly patches: ReadonlyArray<Patch>;
|
|
74
|
-
}
|
|
160
|
+
export type RowsByQueryMap<S extends EvoluSchema = EvoluSchema> = ReadonlyMap<Query<S>, ReadonlyArray<Row>>;
|
|
75
161
|
export type Patch = ReplaceAllPatch | ReplaceAtPatch;
|
|
76
162
|
export interface ReplaceAllPatch {
|
|
77
163
|
readonly op: "replaceAll";
|
|
@@ -108,5 +194,9 @@ export declare const applyPatches: (patches: ReadonlyArray<Patch>, current: Read
|
|
|
108
194
|
* See: https://github.com/kysely-org/kysely/issues/1372#issuecomment-2702773948
|
|
109
195
|
*/
|
|
110
196
|
export declare const kyselyJsonIdentifier: string & Brand<"Id">;
|
|
197
|
+
interface SelectQueryBuilderExpression<O> extends AliasableExpression<O> {
|
|
198
|
+
get isSelectQueryBuilder(): true;
|
|
199
|
+
toOperationNode(): SelectQueryNode;
|
|
200
|
+
}
|
|
111
201
|
export declare const parseSqliteJsonArray: <T>(arr: ReadonlyArray<T>) => ReadonlyArray<T>;
|
|
112
202
|
//# sourceMappingURL=Query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../../../src/local-first/Query.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../../../src/local-first/Query.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,96 +1,134 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Query helpers, execution, and caching.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { AliasNode, ColumnNode, ExpressionWrapper, IdentifierNode, sql as kyselySqlBuilder, ReferenceNode, TableNode, ValueNode, } from "kysely";
|
|
2
7
|
import { createRandomBytes } from "../Crypto.js";
|
|
3
|
-
import { createRecord, isPlainObject
|
|
4
|
-
import {
|
|
5
|
-
import { eqSqliteValue, explainSqliteQueryPlan, } from "../Sqlite.js";
|
|
8
|
+
import { createRecord, isPlainObject } from "../Object.js";
|
|
9
|
+
import { eqSqliteValue, SqliteValue } from "../Sqlite.js";
|
|
6
10
|
import { createId, String } from "../Type.js";
|
|
11
|
+
export { sql as kyselySql } from "kysely";
|
|
7
12
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
13
|
+
* An improved Evolu version of Kysely's SQLite `jsonArrayFrom` helper.
|
|
14
|
+
*
|
|
15
|
+
* Kysely's `ParseJSONResultsPlugin` heuristically parses any result string that
|
|
16
|
+
* looks like JSON. Evolu instead prefixes JSON produced by these helpers with a
|
|
17
|
+
* per-runtime identifier and only parses values carrying that prefix, avoiding
|
|
18
|
+
* accidental parsing of ordinary string columns that merely happen to start
|
|
19
|
+
* with `{` or `[`.
|
|
20
|
+
*
|
|
21
|
+
* ### Example
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { evoluJsonArrayFrom } from "@evolu/common";
|
|
25
|
+
*
|
|
26
|
+
* const result = await db
|
|
27
|
+
* .selectFrom("person")
|
|
28
|
+
* .select((eb) => [
|
|
29
|
+
* "id",
|
|
30
|
+
* evoluJsonArrayFrom(
|
|
31
|
+
* eb
|
|
32
|
+
* .selectFrom("pet")
|
|
33
|
+
* .select(["pet.id as pet_id", "pet.name"])
|
|
34
|
+
* .whereRef("pet.owner_id", "=", "person.id")
|
|
35
|
+
* .orderBy("pet.name"),
|
|
36
|
+
* ).as("pets"),
|
|
37
|
+
* ])
|
|
38
|
+
* .execute();
|
|
39
|
+
*
|
|
40
|
+
* result[0]?.id;
|
|
41
|
+
* result[0]?.pets[0].pet_id;
|
|
42
|
+
* result[0]?.pets[0].name;
|
|
43
|
+
* ```
|
|
10
44
|
*/
|
|
11
|
-
export const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
45
|
+
export const evoluJsonArrayFrom = (expr) => kyselySqlBuilder `(select ${kyselySqlBuilder.lit(kyselyJsonIdentifier)} || coalesce(json_group_array(json_object(${kyselySqlBuilder.join(getSqliteJsonObjectArgs(expr.toOperationNode(), "agg"))})), '[]') from ${expr} as agg)`;
|
|
46
|
+
/**
|
|
47
|
+
* An improved Evolu version of Kysely's SQLite `jsonObjectFrom` helper.
|
|
48
|
+
*
|
|
49
|
+
* Kysely's `ParseJSONResultsPlugin` heuristically parses any result string that
|
|
50
|
+
* looks like JSON. Evolu instead prefixes JSON produced by these helpers with a
|
|
51
|
+
* per-runtime identifier and only parses values carrying that prefix, avoiding
|
|
52
|
+
* accidental parsing of ordinary string columns that merely happen to start
|
|
53
|
+
* with `{` or `[`.
|
|
54
|
+
*
|
|
55
|
+
* The subquery must only return one row.
|
|
56
|
+
*
|
|
57
|
+
* ### Example
|
|
58
|
+
*
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { evoluJsonObjectFrom } from "@evolu/common";
|
|
61
|
+
*
|
|
62
|
+
* const result = await db
|
|
63
|
+
* .selectFrom("person")
|
|
64
|
+
* .select((eb) => [
|
|
65
|
+
* "id",
|
|
66
|
+
* evoluJsonObjectFrom(
|
|
67
|
+
* eb
|
|
68
|
+
* .selectFrom("pet")
|
|
69
|
+
* .select(["pet.id as pet_id", "pet.name"])
|
|
70
|
+
* .whereRef("pet.owner_id", "=", "person.id")
|
|
71
|
+
* .where("pet.is_favorite", "=", true),
|
|
72
|
+
* ).as("favorite_pet"),
|
|
73
|
+
* ])
|
|
74
|
+
* .execute();
|
|
75
|
+
*
|
|
76
|
+
* result[0]?.id;
|
|
77
|
+
* result[0]?.favorite_pet?.pet_id;
|
|
78
|
+
* result[0]?.favorite_pet?.name;
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export const evoluJsonObjectFrom = (expr) => kyselySqlBuilder `(select ${kyselySqlBuilder.lit(kyselyJsonIdentifier)} || json_object(${kyselySqlBuilder.join(getSqliteJsonObjectArgs(expr.toOperationNode(), "obj"))}) from ${expr} as obj)`;
|
|
82
|
+
/**
|
|
83
|
+
* An improved Evolu version of Kysely's SQLite `jsonBuildObject` helper.
|
|
84
|
+
*
|
|
85
|
+
* Kysely's `ParseJSONResultsPlugin` heuristically parses any result string that
|
|
86
|
+
* looks like JSON. Evolu instead prefixes JSON produced by these helpers with a
|
|
87
|
+
* per-runtime identifier and only parses values carrying that prefix, avoiding
|
|
88
|
+
* accidental parsing of ordinary string columns that merely happen to start
|
|
89
|
+
* with `{` or `[`.
|
|
90
|
+
*
|
|
91
|
+
* ### Example
|
|
92
|
+
*
|
|
93
|
+
* ```ts
|
|
94
|
+
* import { evoluJsonBuildObject, kyselySql } from "@evolu/common";
|
|
95
|
+
*
|
|
96
|
+
* const result = await db
|
|
97
|
+
* .selectFrom("person")
|
|
98
|
+
* .select((eb) => [
|
|
99
|
+
* "id",
|
|
100
|
+
* evoluJsonBuildObject({
|
|
101
|
+
* first: eb.ref("first_name"),
|
|
102
|
+
* last: eb.ref("last_name"),
|
|
103
|
+
* full: kyselySql<string>`first_name || ' ' || last_name`,
|
|
104
|
+
* }).as("name"),
|
|
105
|
+
* ])
|
|
106
|
+
* .execute();
|
|
107
|
+
*
|
|
108
|
+
* result[0]?.id;
|
|
109
|
+
* result[0]?.name.first;
|
|
110
|
+
* result[0]?.name.last;
|
|
111
|
+
* result[0]?.name.full;
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export const evoluJsonBuildObject = (obj) => kyselySqlBuilder `${kyselySqlBuilder.lit(kyselyJsonIdentifier)} || json_object(${kyselySqlBuilder.join(Object.keys(obj).flatMap((k) => [kyselySqlBuilder.lit(k), obj[k]]))})`;
|
|
115
|
+
export const getJsonObjectArgs = (node, table) => {
|
|
116
|
+
const args = [];
|
|
117
|
+
for (const { selection: s } of node.selections ?? []) {
|
|
118
|
+
if (ReferenceNode.is(s) && ColumnNode.is(s.column)) {
|
|
119
|
+
args.push(colName(s.column.column.name), colRef(table, s.column.column.name));
|
|
69
120
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (!result.ok)
|
|
79
|
-
return result;
|
|
80
|
-
queriesRows.push([query, result.value.rows]);
|
|
81
|
-
if (sqlQuery.options?.logExplainQueryPlan) {
|
|
82
|
-
explainSqliteQueryPlan(deps)(sqlQuery);
|
|
121
|
+
else if (ColumnNode.is(s)) {
|
|
122
|
+
args.push(colName(s.column.name), colRef(table, s.column.name));
|
|
123
|
+
}
|
|
124
|
+
else if (AliasNode.is(s) && IdentifierNode.is(s.alias)) {
|
|
125
|
+
args.push(colName(s.alias.name), colRef(table, s.alias.name));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
throw new Error(`can't extract column names from the select query node`);
|
|
83
129
|
}
|
|
84
130
|
}
|
|
85
|
-
|
|
86
|
-
const previousState = queryRowsCache.get();
|
|
87
|
-
queryRowsCache.set(queriesRows);
|
|
88
|
-
const currentState = queryRowsCache.get();
|
|
89
|
-
const queryPatchesArray = queries.map((query) => ({
|
|
90
|
-
query,
|
|
91
|
-
patches: makePatches(previousState.get(query), currentState.get(query) ?? emptyRows),
|
|
92
|
-
}));
|
|
93
|
-
return ok(queryPatchesArray);
|
|
131
|
+
return args;
|
|
94
132
|
};
|
|
95
133
|
/**
|
|
96
134
|
* We detect only changes in the whole result and in-place edits. In the future,
|
|
@@ -100,8 +138,9 @@ export const loadQueries = (deps) => (tabId, queries) => {
|
|
|
100
138
|
* if necessary.
|
|
101
139
|
*/
|
|
102
140
|
export const makePatches = (previousRows, nextRows) => {
|
|
103
|
-
if (previousRows === undefined)
|
|
141
|
+
if (previousRows === undefined) {
|
|
104
142
|
return [{ op: "replaceAll", value: nextRows }];
|
|
143
|
+
}
|
|
105
144
|
// TODO: Detect prepend and append, it's cheap.
|
|
106
145
|
if (previousRows.length !== nextRows.length) {
|
|
107
146
|
return [{ op: "replaceAll", value: nextRows }];
|
|
@@ -149,9 +188,17 @@ export const applyPatches = (patches, current) => patches.reduce((next, patch) =
|
|
|
149
188
|
*
|
|
150
189
|
* See: https://github.com/kysely-org/kysely/issues/1372#issuecomment-2702773948
|
|
151
190
|
*/
|
|
152
|
-
export const kyselyJsonIdentifier = createId({
|
|
153
|
-
randomBytes: createRandomBytes(),
|
|
191
|
+
export const kyselyJsonIdentifier = /*#__PURE__*/ createId({
|
|
192
|
+
randomBytes: /*#__PURE__*/ createRandomBytes(),
|
|
154
193
|
});
|
|
194
|
+
const getSqliteJsonObjectArgs = (node, table) => {
|
|
195
|
+
try {
|
|
196
|
+
return getJsonObjectArgs(node, table);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
throw new Error("SQLite evoluJsonArrayFrom and evoluJsonObjectFrom can only handle explicit selections due to limitations of the json_object function. selectAll() is not allowed in the subquery.");
|
|
200
|
+
}
|
|
201
|
+
};
|
|
155
202
|
export const parseSqliteJsonArray = (arr) => {
|
|
156
203
|
const result = new Array(arr.length);
|
|
157
204
|
for (let i = 0; i < arr.length; ++i) {
|
|
@@ -161,7 +208,7 @@ export const parseSqliteJsonArray = (arr) => {
|
|
|
161
208
|
};
|
|
162
209
|
const parse = (obj) => {
|
|
163
210
|
if (String.is(obj) && obj.startsWith(kyselyJsonIdentifier)) {
|
|
164
|
-
return JSON.parse(obj.slice(kyselyJsonIdentifier.length));
|
|
211
|
+
return parse(JSON.parse(obj.slice(kyselyJsonIdentifier.length)));
|
|
165
212
|
}
|
|
166
213
|
if (Array.isArray(obj)) {
|
|
167
214
|
return parseSqliteJsonArray(obj);
|
|
@@ -178,3 +225,5 @@ const parseObject = (obj) => {
|
|
|
178
225
|
}
|
|
179
226
|
return result;
|
|
180
227
|
};
|
|
228
|
+
const colName = (col) => new ExpressionWrapper(ValueNode.createImmediate(col));
|
|
229
|
+
const colRef = (table, col) => new ExpressionWrapper(ReferenceNode.create(ColumnNode.create(col), TableNode.create(table)));
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
/**
|
|
2
|
+
* Relay server for data synchronization.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { TimingSafeEqualDep } from "../Crypto.js";
|
|
7
|
+
import type { SqliteDep } from "../Sqlite.js";
|
|
8
|
+
import { Name } from "../Type.js";
|
|
9
|
+
import { type Awaitable } from "../Types.js";
|
|
8
10
|
import { OwnerId } from "./Owner.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
export interface RelayConfig extends ConsoleConfig, StorageConfig {
|
|
11
|
+
import type { SqliteStorageDeps, Storage, StorageConfig } from "./Storage.js";
|
|
12
|
+
export interface RelayConfig extends StorageConfig {
|
|
12
13
|
/**
|
|
13
14
|
* The relay name.
|
|
14
15
|
*
|
|
15
16
|
* Implementations can use this for identification purposes (e.g., database
|
|
16
17
|
* file name, logging).
|
|
17
18
|
*/
|
|
18
|
-
readonly name?:
|
|
19
|
+
readonly name?: Name;
|
|
19
20
|
/**
|
|
20
21
|
* Optional callback to check if an {@link OwnerId} is allowed to access the
|
|
21
22
|
* relay. If this callback is not provided, all owners are allowed.
|
|
22
23
|
*
|
|
23
|
-
* The callback receives the {@link OwnerId} and returns a {@link
|
|
24
|
+
* The callback receives the {@link OwnerId} and returns a {@link Awaitable}
|
|
24
25
|
* boolean: `true` to allow access, or `false` to deny.
|
|
25
26
|
*
|
|
26
27
|
* The callback can be synchronous (for SQLite or in-memory checks) or
|
|
@@ -34,7 +35,7 @@ export interface RelayConfig extends ConsoleConfig, StorageConfig {
|
|
|
34
35
|
* relay access, not write permissions. Since all data is encrypted on the
|
|
35
36
|
* relay, OwnerId exposure is safe.
|
|
36
37
|
*
|
|
37
|
-
* Owners specify which relays to connect to via
|
|
38
|
+
* Owners specify which relays to connect to via `OwnerTransport`. In
|
|
38
39
|
* WebSocket-based implementations, this check occurs before accepting the
|
|
39
40
|
* connection, with the OwnerId typically extracted from the URL Path (e.g.,
|
|
40
41
|
* `ws://localhost:4000/<ownerId>`). The relay requires the URL to be in the
|
|
@@ -59,7 +60,7 @@ export interface RelayConfig extends ConsoleConfig, StorageConfig {
|
|
|
59
60
|
* Promise.resolve(ownerId === "6jy_2F4RT5qqeLgJ14_dnQ"),
|
|
60
61
|
* ```
|
|
61
62
|
*/
|
|
62
|
-
readonly isOwnerAllowed?: (ownerId: OwnerId) =>
|
|
63
|
+
readonly isOwnerAllowed?: (ownerId: OwnerId) => Awaitable<boolean>;
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* A completely interchangeable server for syncing and backing up encrypted data
|
|
@@ -70,29 +71,8 @@ export interface RelayConfig extends ConsoleConfig, StorageConfig {
|
|
|
70
71
|
* decentralization and infinite horizontal scalability with minimal
|
|
71
72
|
* infrastructure.
|
|
72
73
|
*/
|
|
73
|
-
export interface Relay extends
|
|
74
|
-
}
|
|
75
|
-
export declare const createRelaySqliteStorage: (deps: SqliteStorageDeps & TimingSafeEqualDep) => (config: CreateBaseSqliteStorageConfig) => Storage;
|
|
76
|
-
export declare const createRelayStorageTables: (deps: SqliteDep) => Result<void, SqliteError>;
|
|
77
|
-
export interface RelayLogger {
|
|
78
|
-
readonly started: (enableLogging: boolean, port: number) => void;
|
|
79
|
-
readonly storageError: (error: unknown) => void;
|
|
80
|
-
readonly upgradeSocketError: (error: Error) => void;
|
|
81
|
-
readonly invalidOrMissingOwnerIdInUrl: (url: string | undefined) => void;
|
|
82
|
-
readonly unauthorizedOwner: (ownerId: OwnerId) => void;
|
|
83
|
-
readonly connectionEstablished: (totalConnectionCount: number) => void;
|
|
84
|
-
readonly connectionWebSocketError: (error: Error) => void;
|
|
85
|
-
readonly relayOptionSubscribe: (ownerId: OwnerId, getSubscriberCount: LazyValue<number>) => void;
|
|
86
|
-
readonly relayOptionUnsubscribe: (ownerId: OwnerId, getSubscriberCount: LazyValue<number>) => void;
|
|
87
|
-
readonly relayOptionBroadcast: (ownerId: OwnerId, broadcastCount: number, subscriberCount: number) => void;
|
|
88
|
-
readonly messageLength: (messageLength: number) => void;
|
|
89
|
-
readonly applyProtocolMessageAsRelayError: (error: ProtocolInvalidDataError) => void;
|
|
90
|
-
readonly responseLength: (responseLength: number) => void;
|
|
91
|
-
readonly applyProtocolMessageAsRelayUnknownError: (error: unknown) => void;
|
|
92
|
-
readonly connectionClosed: (totalConnectionCount: number) => void;
|
|
93
|
-
readonly shuttingDown: () => void;
|
|
94
|
-
readonly webSocketServerDisposed: () => void;
|
|
95
|
-
readonly httpServerDisposed: () => void;
|
|
74
|
+
export interface Relay extends AsyncDisposable {
|
|
96
75
|
}
|
|
97
|
-
export declare const
|
|
76
|
+
export declare const createRelaySqliteStorage: (deps: SqliteStorageDeps & TimingSafeEqualDep) => (config: StorageConfig) => Storage;
|
|
77
|
+
export declare const createRelayStorageTables: (deps: SqliteDep) => void;
|
|
98
78
|
//# sourceMappingURL=Relay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../../src/local-first/Relay.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../../src/local-first/Relay.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,IAAI,EAAe,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,OAAO,EAIR,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAEV,iBAAiB,EACjB,OAAO,EACP,aAAa,EAEd,MAAM,cAAc,CAAC;AAStB,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;IAErB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC,OAAO,CAAC,CAAC;CACpE;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,KAAM,SAAQ,eAAe;CAAG;AAEjD,eAAO,MAAM,wBAAwB,GAClC,MAAM,iBAAiB,GAAG,kBAAkB,MAC5C,QAAQ,aAAa,KAAG,OA0LxB,CAAC;AAEJ,eAAO,MAAM,wBAAwB,GAAI,MAAM,SAAS,KAAG,IAuB1D,CAAC"}
|