@cipherstash/stack 0.16.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +225 -0
- package/README.md +2 -2
- package/dist/{chunk-CY5B4LIF.js → chunk-36AA7IBJ.js} +303 -204
- package/dist/chunk-36AA7IBJ.js.map +1 -0
- package/dist/{chunk-MD6742R6.js → chunk-4AVL4VZD.js} +1 -1
- package/dist/chunk-4AVL4VZD.js.map +1 -0
- package/dist/{chunk-4RNBI3UH.js → chunk-BNO32ZMV.js} +1 -1
- package/dist/chunk-BNO32ZMV.js.map +1 -0
- package/dist/{chunk-6FD7OBGM.js → chunk-HQANMV7R.js} +3 -3
- package/dist/chunk-HQANMV7R.js.map +1 -0
- package/dist/chunk-IADZCZEA.js +23 -0
- package/dist/chunk-IADZCZEA.js.map +1 -0
- package/dist/chunk-IBSK6P33.js +209 -0
- package/dist/chunk-IBSK6P33.js.map +1 -0
- package/dist/chunk-JSG2AMDI.js +17 -0
- package/dist/chunk-JSG2AMDI.js.map +1 -0
- package/dist/chunk-MP3SSDNN.js +4439 -0
- package/dist/chunk-MP3SSDNN.js.map +1 -0
- package/dist/chunk-OFQ555AX.js +191 -0
- package/dist/chunk-OFQ555AX.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-U66S7VIF.js +435 -0
- package/dist/chunk-U66S7VIF.js.map +1 -0
- package/dist/{client-C_7TF8EL.d.cts → client-DSGHBN-g.d.cts} +209 -72
- package/dist/{client-BLbA6aFD.d.ts → client-DfCrlHXh.d.ts} +209 -72
- package/dist/client.cjs +4103 -43
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +5 -5
- package/dist/client.d.ts +5 -5
- package/dist/client.js +3 -1
- package/dist/drizzle/index.cjs +4139 -77
- package/dist/drizzle/index.cjs.map +1 -1
- package/dist/drizzle/index.d.cts +33 -33
- package/dist/drizzle/index.d.ts +33 -33
- package/dist/drizzle/index.js +39 -33
- package/dist/drizzle/index.js.map +1 -1
- package/dist/dynamodb/index.cjs +31 -14
- package/dist/dynamodb/index.cjs.map +1 -1
- package/dist/dynamodb/index.d.cts +12 -12
- package/dist/dynamodb/index.d.ts +12 -12
- package/dist/dynamodb/index.js +16 -12
- package/dist/dynamodb/index.js.map +1 -1
- package/dist/encryption/index.cjs +4611 -257
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +3 -3
- package/dist/encryption/index.d.ts +3 -3
- package/dist/encryption/index.js +35 -7
- package/dist/encryption/v3.cjs +7791 -0
- package/dist/encryption/v3.cjs.map +1 -0
- package/dist/encryption/v3.d.cts +100 -0
- package/dist/encryption/v3.d.ts +100 -0
- package/dist/encryption/v3.js +161 -0
- package/dist/encryption/v3.js.map +1 -0
- package/dist/eql/v3/index.cjs +612 -0
- package/dist/eql/v3/index.cjs.map +1 -0
- package/dist/eql/v3/index.d.cts +71 -0
- package/dist/eql/v3/index.d.ts +71 -0
- package/dist/eql/v3/index.js +89 -0
- package/dist/eql/v3/index.js.map +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/identity/index.cjs +55 -35
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.d.cts +54 -30
- package/dist/identity/index.d.ts +54 -30
- package/dist/identity/index.js +9 -177
- package/dist/identity/index.js.map +1 -1
- package/dist/index.cjs +4625 -273
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -7
- package/dist/index.d.ts +18 -7
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/schema/index.cjs +4108 -44
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +3 -1
- package/dist/supabase/index.cjs +4500 -75
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +113 -34
- package/dist/supabase/index.d.ts +113 -34
- package/dist/supabase/index.js +350 -32
- package/dist/supabase/index.js.map +1 -1
- package/dist/table-CIH7jZ2h.d.ts +603 -0
- package/dist/table-DihEAlxG.d.cts +603 -0
- package/dist/{types-public-Dv-r6Ik0.d.ts → types-public-CpS5KjwX.d.cts} +209 -36
- package/dist/{types-public-Dv-r6Ik0.d.cts → types-public-CpS5KjwX.d.ts} +209 -36
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +2 -2
- package/dist/types-public.d.ts +2 -2
- package/dist/types-public.js +2 -1
- package/dist/wasm-inline.d.ts +1269 -0
- package/dist/wasm-inline.js +4594 -0
- package/dist/wasm-inline.js.map +1 -0
- package/package.json +63 -13
- package/dist/chunk-4RNBI3UH.js.map +0 -1
- package/dist/chunk-6FD7OBGM.js.map +0 -1
- package/dist/chunk-CY5B4LIF.js.map +0 -1
- package/dist/chunk-JDZ2QUUF.js +0 -381
- package/dist/chunk-JDZ2QUUF.js.map +0 -1
- package/dist/chunk-MD6742R6.js.map +0 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Result } from '@byteslice/result';
|
|
2
|
+
import { A as AnyV3Table, C as ColumnsOf, P as PlaintextForColumn, Q as QueryableColumnsOf, a as QueryTypesForColumn, V as V3ModelInput, b as V3EncryptedModel, c as V3DecryptedModel } from '../table-DihEAlxG.cjs';
|
|
3
|
+
export { d as AnyEncryptedV3Column, E as EncryptedBooleanColumn, e as EncryptedDateColumn, f as EncryptedDateEqColumn, g as EncryptedDateOrdColumn, h as EncryptedDateOrdOreColumn, i as EncryptedDoubleColumn, j as EncryptedDoubleEqColumn, k as EncryptedDoubleOrdColumn, l as EncryptedDoubleOrdOreColumn, m as EncryptedIntegerColumn, n as EncryptedIntegerEqColumn, o as EncryptedIntegerOrdColumn, p as EncryptedIntegerOrdOreColumn, q as EncryptedNumericColumn, r as EncryptedNumericEqColumn, s as EncryptedNumericOrdColumn, t as EncryptedNumericOrdOreColumn, u as EncryptedRealColumn, v as EncryptedRealEqColumn, w as EncryptedRealOrdColumn, x as EncryptedRealOrdOreColumn, y as EncryptedSmallintColumn, z as EncryptedSmallintEqColumn, B as EncryptedSmallintOrdColumn, D as EncryptedSmallintOrdOreColumn, F as EncryptedTable, G as EncryptedTextColumn, H as EncryptedTextEqColumn, I as EncryptedTextMatchColumn, J as EncryptedTextOrdColumn, K as EncryptedTextOrdOreColumn, L as EncryptedTextSearchColumn, M as EncryptedTimestampColumn, N as EncryptedTimestampEqColumn, O as EncryptedTimestampOrdColumn, R as EncryptedTimestampOrdOreColumn, S as EncryptedV3TableColumn, T as EqlTypeForColumn, U as InferEncrypted, W as InferPlaintext, X as QueryCapabilities, Y as TEXT_SEARCH_EQL_TYPE, Z as buildEncryptConfig, _ as encryptedTable } from '../table-DihEAlxG.cjs';
|
|
4
|
+
export { types } from '../eql/v3/index.cjs';
|
|
5
|
+
import { EncryptionError } from '../errors/index.cjs';
|
|
6
|
+
import { LockContextInput } from '../identity/index.cjs';
|
|
7
|
+
import { C as ClientConfig, E as EncryptedReturnType, a as Encrypted, B as BulkEncryptPayload, b as EncryptOptions, c as BulkDecryptPayload } from '../types-public-CpS5KjwX.cjs';
|
|
8
|
+
import { E as EncryptOperation, a as EncryptQueryOperation, b as EncryptModelOperation, B as BulkEncryptModelsOperation, D as DecryptOperation, c as BulkEncryptOperation, d as BulkDecryptOperation, e as EncryptionClient } from '../client-DSGHBN-g.cjs';
|
|
9
|
+
import '@cipherstash/protect-ffi';
|
|
10
|
+
import 'zod';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A strongly-typed view over an {@link EncryptionClient} for EQL v3 schemas.
|
|
14
|
+
*
|
|
15
|
+
* Every method derives its types from the concrete `table` / `column` builder
|
|
16
|
+
* arguments (which carry their branded types at the call site), so:
|
|
17
|
+
* - `encrypt` / `encryptQuery` pin the plaintext to the column's domain type
|
|
18
|
+
* (`text → string`, `timestamp → Date`, …);
|
|
19
|
+
* - `encryptQuery` additionally constrains `queryType` to the column's
|
|
20
|
+
* capabilities and rejects storage-only columns outright;
|
|
21
|
+
* - `encryptModel` / `bulkEncryptModels` validate schema-column fields against
|
|
22
|
+
* their inferred plaintext type (passthrough fields are untouched) and return
|
|
23
|
+
* a precise encrypted model;
|
|
24
|
+
* - `decryptModel` / `bulkDecryptModels` return the precise plaintext model,
|
|
25
|
+
* reconstructing `Date` values from the encrypt-config `cast_as`.
|
|
26
|
+
*
|
|
27
|
+
* @typeParam S - the tuple of registered v3 tables; `table` arguments must be a
|
|
28
|
+
* member of this tuple.
|
|
29
|
+
*/
|
|
30
|
+
interface TypedEncryptionClient<S extends readonly AnyV3Table[]> {
|
|
31
|
+
encrypt<Table extends S[number], Col extends ColumnsOf<Table>>(plaintext: PlaintextForColumn<Col>, opts: {
|
|
32
|
+
table: Table;
|
|
33
|
+
column: Col;
|
|
34
|
+
}): EncryptOperation;
|
|
35
|
+
encryptQuery<Table extends S[number], Col extends QueryableColumnsOf<Table>, QT extends QueryTypesForColumn<Col> = QueryTypesForColumn<Col>>(plaintext: PlaintextForColumn<Col>, opts: {
|
|
36
|
+
table: Table;
|
|
37
|
+
column: Col;
|
|
38
|
+
queryType?: QT;
|
|
39
|
+
returnType?: EncryptedReturnType;
|
|
40
|
+
}): EncryptQueryOperation;
|
|
41
|
+
encryptModel<Table extends S[number], T extends Record<string, unknown>>(input: V3ModelInput<Table, T>, table: Table): EncryptModelOperation<V3EncryptedModel<Table, T>>;
|
|
42
|
+
bulkEncryptModels<Table extends S[number], T extends Record<string, unknown>>(input: Array<V3ModelInput<Table, T>>, table: Table): BulkEncryptModelsOperation<V3EncryptedModel<Table, T>>;
|
|
43
|
+
/**
|
|
44
|
+
* Decrypt a single value. Cannot be strongly typed — a lone ciphertext carries
|
|
45
|
+
* no column identity — so it resolves to the FFI plaintext union unchanged.
|
|
46
|
+
*/
|
|
47
|
+
decrypt(encrypted: Encrypted): DecryptOperation;
|
|
48
|
+
/**
|
|
49
|
+
* Decrypt a model, returning the precise plaintext shape for `table`. `Date`
|
|
50
|
+
* columns are reconstructed from the encrypt-config `cast_as`.
|
|
51
|
+
*
|
|
52
|
+
* Pass `lockContext` to decrypt identity-bound data — the same context that
|
|
53
|
+
* was supplied at encrypt time must be provided here.
|
|
54
|
+
*
|
|
55
|
+
* Unlike the encrypt operations this returns a plain `Promise<Result<…>>`
|
|
56
|
+
* rather than a chainable operation, because it maps the resolved value.
|
|
57
|
+
*/
|
|
58
|
+
decryptModel<Table extends S[number], T extends Record<string, unknown>>(input: T, table: Table, lockContext?: LockContextInput): Promise<Result<V3DecryptedModel<Table, T>, EncryptionError>>;
|
|
59
|
+
bulkDecryptModels<Table extends S[number], T extends Record<string, unknown>>(input: Array<T>, table: Table, lockContext?: LockContextInput): Promise<Result<Array<V3DecryptedModel<Table, T>>, EncryptionError>>;
|
|
60
|
+
bulkEncrypt(plaintexts: BulkEncryptPayload, opts: EncryptOptions): BulkEncryptOperation;
|
|
61
|
+
bulkDecrypt(payloads: BulkDecryptPayload): BulkDecryptOperation;
|
|
62
|
+
getEncryptConfig(): ReturnType<EncryptionClient['getEncryptConfig']>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Wrap an already-built {@link EncryptionClient} in a {@link TypedEncryptionClient}
|
|
66
|
+
* for the given v3 schemas. Zero runtime cost for the encrypt/query paths (the
|
|
67
|
+
* underlying operations are returned unchanged); the decrypt-model paths add a
|
|
68
|
+
* per-column `Date` reconstruction step.
|
|
69
|
+
*
|
|
70
|
+
* The `schemas` are captured with a `const` type parameter so array-literal
|
|
71
|
+
* widening does not collapse per-table inference.
|
|
72
|
+
*/
|
|
73
|
+
declare function typedClient<const S extends readonly AnyV3Table[]>(client: EncryptionClient, ..._schemas: S): TypedEncryptionClient<S>;
|
|
74
|
+
/**
|
|
75
|
+
* Build a {@link TypedEncryptionClient} for EQL v3 schemas — the strongly-typed
|
|
76
|
+
* counterpart to {@link Encryption}. Mirrors its config, then retypes the client
|
|
77
|
+
* against the provided v3 `schemas`.
|
|
78
|
+
*
|
|
79
|
+
* The underlying client is created with `eqlVersion: 3` (protect-ffi 0.27+),
|
|
80
|
+
* so `encrypt` / `encryptModel` emit EQL v3 wire payloads for the
|
|
81
|
+
* per-capability `eql_v3` domains. Pass an explicit `config.eqlVersion` to
|
|
82
|
+
* override — e.g. `2` to write v2-wire from a v3 schema set during a
|
|
83
|
+
* migration.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* import { EncryptionV3, encryptedTable, types } from "@cipherstash/stack/v3"
|
|
88
|
+
*
|
|
89
|
+
* const users = encryptedTable("users", { email: types.TextSearch("email") })
|
|
90
|
+
* const client = await EncryptionV3({ schemas: [users] })
|
|
91
|
+
*
|
|
92
|
+
* await client.encrypt("a@b.com", { table: users, column: users.email })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
declare function EncryptionV3<const S extends readonly AnyV3Table[]>(config: {
|
|
96
|
+
schemas: S;
|
|
97
|
+
config?: ClientConfig;
|
|
98
|
+
}): Promise<TypedEncryptionClient<S>>;
|
|
99
|
+
|
|
100
|
+
export { AnyV3Table, ColumnsOf, EncryptionV3, PlaintextForColumn, QueryTypesForColumn, QueryableColumnsOf, type TypedEncryptionClient, V3DecryptedModel, V3EncryptedModel, V3ModelInput, typedClient };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Result } from '@byteslice/result';
|
|
2
|
+
import { A as AnyV3Table, C as ColumnsOf, P as PlaintextForColumn, Q as QueryableColumnsOf, a as QueryTypesForColumn, V as V3ModelInput, b as V3EncryptedModel, c as V3DecryptedModel } from '../table-CIH7jZ2h.js';
|
|
3
|
+
export { d as AnyEncryptedV3Column, E as EncryptedBooleanColumn, e as EncryptedDateColumn, f as EncryptedDateEqColumn, g as EncryptedDateOrdColumn, h as EncryptedDateOrdOreColumn, i as EncryptedDoubleColumn, j as EncryptedDoubleEqColumn, k as EncryptedDoubleOrdColumn, l as EncryptedDoubleOrdOreColumn, m as EncryptedIntegerColumn, n as EncryptedIntegerEqColumn, o as EncryptedIntegerOrdColumn, p as EncryptedIntegerOrdOreColumn, q as EncryptedNumericColumn, r as EncryptedNumericEqColumn, s as EncryptedNumericOrdColumn, t as EncryptedNumericOrdOreColumn, u as EncryptedRealColumn, v as EncryptedRealEqColumn, w as EncryptedRealOrdColumn, x as EncryptedRealOrdOreColumn, y as EncryptedSmallintColumn, z as EncryptedSmallintEqColumn, B as EncryptedSmallintOrdColumn, D as EncryptedSmallintOrdOreColumn, F as EncryptedTable, G as EncryptedTextColumn, H as EncryptedTextEqColumn, I as EncryptedTextMatchColumn, J as EncryptedTextOrdColumn, K as EncryptedTextOrdOreColumn, L as EncryptedTextSearchColumn, M as EncryptedTimestampColumn, N as EncryptedTimestampEqColumn, O as EncryptedTimestampOrdColumn, R as EncryptedTimestampOrdOreColumn, S as EncryptedV3TableColumn, T as EqlTypeForColumn, U as InferEncrypted, W as InferPlaintext, X as QueryCapabilities, Y as TEXT_SEARCH_EQL_TYPE, Z as buildEncryptConfig, _ as encryptedTable } from '../table-CIH7jZ2h.js';
|
|
4
|
+
export { types } from '../eql/v3/index.js';
|
|
5
|
+
import { EncryptionError } from '../errors/index.js';
|
|
6
|
+
import { LockContextInput } from '../identity/index.js';
|
|
7
|
+
import { C as ClientConfig, E as EncryptedReturnType, a as Encrypted, B as BulkEncryptPayload, b as EncryptOptions, c as BulkDecryptPayload } from '../types-public-CpS5KjwX.js';
|
|
8
|
+
import { E as EncryptOperation, a as EncryptQueryOperation, b as EncryptModelOperation, B as BulkEncryptModelsOperation, D as DecryptOperation, c as BulkEncryptOperation, d as BulkDecryptOperation, e as EncryptionClient } from '../client-DfCrlHXh.js';
|
|
9
|
+
import '@cipherstash/protect-ffi';
|
|
10
|
+
import 'zod';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A strongly-typed view over an {@link EncryptionClient} for EQL v3 schemas.
|
|
14
|
+
*
|
|
15
|
+
* Every method derives its types from the concrete `table` / `column` builder
|
|
16
|
+
* arguments (which carry their branded types at the call site), so:
|
|
17
|
+
* - `encrypt` / `encryptQuery` pin the plaintext to the column's domain type
|
|
18
|
+
* (`text → string`, `timestamp → Date`, …);
|
|
19
|
+
* - `encryptQuery` additionally constrains `queryType` to the column's
|
|
20
|
+
* capabilities and rejects storage-only columns outright;
|
|
21
|
+
* - `encryptModel` / `bulkEncryptModels` validate schema-column fields against
|
|
22
|
+
* their inferred plaintext type (passthrough fields are untouched) and return
|
|
23
|
+
* a precise encrypted model;
|
|
24
|
+
* - `decryptModel` / `bulkDecryptModels` return the precise plaintext model,
|
|
25
|
+
* reconstructing `Date` values from the encrypt-config `cast_as`.
|
|
26
|
+
*
|
|
27
|
+
* @typeParam S - the tuple of registered v3 tables; `table` arguments must be a
|
|
28
|
+
* member of this tuple.
|
|
29
|
+
*/
|
|
30
|
+
interface TypedEncryptionClient<S extends readonly AnyV3Table[]> {
|
|
31
|
+
encrypt<Table extends S[number], Col extends ColumnsOf<Table>>(plaintext: PlaintextForColumn<Col>, opts: {
|
|
32
|
+
table: Table;
|
|
33
|
+
column: Col;
|
|
34
|
+
}): EncryptOperation;
|
|
35
|
+
encryptQuery<Table extends S[number], Col extends QueryableColumnsOf<Table>, QT extends QueryTypesForColumn<Col> = QueryTypesForColumn<Col>>(plaintext: PlaintextForColumn<Col>, opts: {
|
|
36
|
+
table: Table;
|
|
37
|
+
column: Col;
|
|
38
|
+
queryType?: QT;
|
|
39
|
+
returnType?: EncryptedReturnType;
|
|
40
|
+
}): EncryptQueryOperation;
|
|
41
|
+
encryptModel<Table extends S[number], T extends Record<string, unknown>>(input: V3ModelInput<Table, T>, table: Table): EncryptModelOperation<V3EncryptedModel<Table, T>>;
|
|
42
|
+
bulkEncryptModels<Table extends S[number], T extends Record<string, unknown>>(input: Array<V3ModelInput<Table, T>>, table: Table): BulkEncryptModelsOperation<V3EncryptedModel<Table, T>>;
|
|
43
|
+
/**
|
|
44
|
+
* Decrypt a single value. Cannot be strongly typed — a lone ciphertext carries
|
|
45
|
+
* no column identity — so it resolves to the FFI plaintext union unchanged.
|
|
46
|
+
*/
|
|
47
|
+
decrypt(encrypted: Encrypted): DecryptOperation;
|
|
48
|
+
/**
|
|
49
|
+
* Decrypt a model, returning the precise plaintext shape for `table`. `Date`
|
|
50
|
+
* columns are reconstructed from the encrypt-config `cast_as`.
|
|
51
|
+
*
|
|
52
|
+
* Pass `lockContext` to decrypt identity-bound data — the same context that
|
|
53
|
+
* was supplied at encrypt time must be provided here.
|
|
54
|
+
*
|
|
55
|
+
* Unlike the encrypt operations this returns a plain `Promise<Result<…>>`
|
|
56
|
+
* rather than a chainable operation, because it maps the resolved value.
|
|
57
|
+
*/
|
|
58
|
+
decryptModel<Table extends S[number], T extends Record<string, unknown>>(input: T, table: Table, lockContext?: LockContextInput): Promise<Result<V3DecryptedModel<Table, T>, EncryptionError>>;
|
|
59
|
+
bulkDecryptModels<Table extends S[number], T extends Record<string, unknown>>(input: Array<T>, table: Table, lockContext?: LockContextInput): Promise<Result<Array<V3DecryptedModel<Table, T>>, EncryptionError>>;
|
|
60
|
+
bulkEncrypt(plaintexts: BulkEncryptPayload, opts: EncryptOptions): BulkEncryptOperation;
|
|
61
|
+
bulkDecrypt(payloads: BulkDecryptPayload): BulkDecryptOperation;
|
|
62
|
+
getEncryptConfig(): ReturnType<EncryptionClient['getEncryptConfig']>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Wrap an already-built {@link EncryptionClient} in a {@link TypedEncryptionClient}
|
|
66
|
+
* for the given v3 schemas. Zero runtime cost for the encrypt/query paths (the
|
|
67
|
+
* underlying operations are returned unchanged); the decrypt-model paths add a
|
|
68
|
+
* per-column `Date` reconstruction step.
|
|
69
|
+
*
|
|
70
|
+
* The `schemas` are captured with a `const` type parameter so array-literal
|
|
71
|
+
* widening does not collapse per-table inference.
|
|
72
|
+
*/
|
|
73
|
+
declare function typedClient<const S extends readonly AnyV3Table[]>(client: EncryptionClient, ..._schemas: S): TypedEncryptionClient<S>;
|
|
74
|
+
/**
|
|
75
|
+
* Build a {@link TypedEncryptionClient} for EQL v3 schemas — the strongly-typed
|
|
76
|
+
* counterpart to {@link Encryption}. Mirrors its config, then retypes the client
|
|
77
|
+
* against the provided v3 `schemas`.
|
|
78
|
+
*
|
|
79
|
+
* The underlying client is created with `eqlVersion: 3` (protect-ffi 0.27+),
|
|
80
|
+
* so `encrypt` / `encryptModel` emit EQL v3 wire payloads for the
|
|
81
|
+
* per-capability `eql_v3` domains. Pass an explicit `config.eqlVersion` to
|
|
82
|
+
* override — e.g. `2` to write v2-wire from a v3 schema set during a
|
|
83
|
+
* migration.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* import { EncryptionV3, encryptedTable, types } from "@cipherstash/stack/v3"
|
|
88
|
+
*
|
|
89
|
+
* const users = encryptedTable("users", { email: types.TextSearch("email") })
|
|
90
|
+
* const client = await EncryptionV3({ schemas: [users] })
|
|
91
|
+
*
|
|
92
|
+
* await client.encrypt("a@b.com", { table: users, column: users.email })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
declare function EncryptionV3<const S extends readonly AnyV3Table[]>(config: {
|
|
96
|
+
schemas: S;
|
|
97
|
+
config?: ClientConfig;
|
|
98
|
+
}): Promise<TypedEncryptionClient<S>>;
|
|
99
|
+
|
|
100
|
+
export { AnyV3Table, ColumnsOf, EncryptionV3, PlaintextForColumn, QueryTypesForColumn, QueryableColumnsOf, type TypedEncryptionClient, V3DecryptedModel, V3EncryptedModel, V3ModelInput, typedClient };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EncryptedTable,
|
|
3
|
+
buildEncryptConfig,
|
|
4
|
+
encryptedTable,
|
|
5
|
+
types
|
|
6
|
+
} from "../chunk-IBSK6P33.js";
|
|
7
|
+
import {
|
|
8
|
+
EncryptedBooleanColumn,
|
|
9
|
+
EncryptedDateColumn,
|
|
10
|
+
EncryptedDateEqColumn,
|
|
11
|
+
EncryptedDateOrdColumn,
|
|
12
|
+
EncryptedDateOrdOreColumn,
|
|
13
|
+
EncryptedDoubleColumn,
|
|
14
|
+
EncryptedDoubleEqColumn,
|
|
15
|
+
EncryptedDoubleOrdColumn,
|
|
16
|
+
EncryptedDoubleOrdOreColumn,
|
|
17
|
+
EncryptedIntegerColumn,
|
|
18
|
+
EncryptedIntegerEqColumn,
|
|
19
|
+
EncryptedIntegerOrdColumn,
|
|
20
|
+
EncryptedIntegerOrdOreColumn,
|
|
21
|
+
EncryptedNumericColumn,
|
|
22
|
+
EncryptedNumericEqColumn,
|
|
23
|
+
EncryptedNumericOrdColumn,
|
|
24
|
+
EncryptedNumericOrdOreColumn,
|
|
25
|
+
EncryptedRealColumn,
|
|
26
|
+
EncryptedRealEqColumn,
|
|
27
|
+
EncryptedRealOrdColumn,
|
|
28
|
+
EncryptedRealOrdOreColumn,
|
|
29
|
+
EncryptedSmallintColumn,
|
|
30
|
+
EncryptedSmallintEqColumn,
|
|
31
|
+
EncryptedSmallintOrdColumn,
|
|
32
|
+
EncryptedSmallintOrdOreColumn,
|
|
33
|
+
EncryptedTextColumn,
|
|
34
|
+
EncryptedTextEqColumn,
|
|
35
|
+
EncryptedTextMatchColumn,
|
|
36
|
+
EncryptedTextOrdColumn,
|
|
37
|
+
EncryptedTextOrdOreColumn,
|
|
38
|
+
EncryptedTextSearchColumn,
|
|
39
|
+
EncryptedTimestampColumn,
|
|
40
|
+
EncryptedTimestampEqColumn,
|
|
41
|
+
EncryptedTimestampOrdColumn,
|
|
42
|
+
EncryptedTimestampOrdOreColumn,
|
|
43
|
+
TEXT_SEARCH_EQL_TYPE
|
|
44
|
+
} from "../chunk-U66S7VIF.js";
|
|
45
|
+
import {
|
|
46
|
+
Encryption
|
|
47
|
+
} from "../chunk-36AA7IBJ.js";
|
|
48
|
+
import "../chunk-OFQ555AX.js";
|
|
49
|
+
import "../chunk-BNO32ZMV.js";
|
|
50
|
+
import "../chunk-MP3SSDNN.js";
|
|
51
|
+
import "../chunk-IADZCZEA.js";
|
|
52
|
+
import "../chunk-4AVL4VZD.js";
|
|
53
|
+
import "../chunk-JSG2AMDI.js";
|
|
54
|
+
import "../chunk-HQANMV7R.js";
|
|
55
|
+
import "../chunk-LBMC4D6D.js";
|
|
56
|
+
import "../chunk-PZ5AY32C.js";
|
|
57
|
+
|
|
58
|
+
// src/encryption/v3.ts
|
|
59
|
+
function rowReconstructor(table) {
|
|
60
|
+
const { columns } = table.build();
|
|
61
|
+
const propToDb = table.buildColumnKeyMap();
|
|
62
|
+
const dateProperties = Object.entries(propToDb).filter(([, dbName]) => {
|
|
63
|
+
const castAs = columns[dbName]?.cast_as;
|
|
64
|
+
return castAs === "date" || castAs === "timestamp";
|
|
65
|
+
}).map(([property]) => property);
|
|
66
|
+
return (row) => {
|
|
67
|
+
const out = { ...row };
|
|
68
|
+
for (const property of dateProperties) {
|
|
69
|
+
const value = out[property];
|
|
70
|
+
if (value == null) continue;
|
|
71
|
+
out[property] = new Date(value);
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function typedClient(client, ..._schemas) {
|
|
77
|
+
return {
|
|
78
|
+
encrypt: (plaintext, opts) => client.encrypt(plaintext, opts),
|
|
79
|
+
encryptQuery: (plaintext, opts) => client.encryptQuery(plaintext, opts),
|
|
80
|
+
encryptModel: (input, table) => client.encryptModel(input, table),
|
|
81
|
+
bulkEncryptModels: (input, table) => client.bulkEncryptModels(input, table),
|
|
82
|
+
decrypt: (encrypted) => client.decrypt(encrypted),
|
|
83
|
+
decryptModel: async (input, table, lockContext) => {
|
|
84
|
+
const op = client.decryptModel(input);
|
|
85
|
+
const result = await (lockContext ? op.withLockContext(lockContext) : op);
|
|
86
|
+
if (result.failure) return result;
|
|
87
|
+
return { data: rowReconstructor(table)(result.data) };
|
|
88
|
+
},
|
|
89
|
+
bulkDecryptModels: async (input, table, lockContext) => {
|
|
90
|
+
const op = client.bulkDecryptModels(input);
|
|
91
|
+
const result = await (lockContext ? op.withLockContext(lockContext) : op);
|
|
92
|
+
if (result.failure) return result;
|
|
93
|
+
const reconstruct = rowReconstructor(table);
|
|
94
|
+
return {
|
|
95
|
+
data: result.data.map(
|
|
96
|
+
(row) => reconstruct(row)
|
|
97
|
+
)
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
bulkEncrypt: (plaintexts, opts) => client.bulkEncrypt(plaintexts, opts),
|
|
101
|
+
bulkDecrypt: (payloads) => client.bulkDecrypt(payloads),
|
|
102
|
+
getEncryptConfig: () => client.getEncryptConfig()
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async function EncryptionV3(config) {
|
|
106
|
+
const client = await Encryption({
|
|
107
|
+
schemas: config.schemas,
|
|
108
|
+
// v3 schemas emit the EQL v3 wire format. Auto-detection in
|
|
109
|
+
// `Encryption` would resolve the same way (every v3 table carries the
|
|
110
|
+
// `buildColumnKeyMap` marker), but the version is set explicitly here
|
|
111
|
+
// so the contract doesn't hinge on duck-typing — while still honouring
|
|
112
|
+
// a caller's explicit override.
|
|
113
|
+
config: { ...config.config, eqlVersion: config.config?.eqlVersion ?? 3 }
|
|
114
|
+
});
|
|
115
|
+
return typedClient(client, ...config.schemas);
|
|
116
|
+
}
|
|
117
|
+
export {
|
|
118
|
+
EncryptedBooleanColumn,
|
|
119
|
+
EncryptedDateColumn,
|
|
120
|
+
EncryptedDateEqColumn,
|
|
121
|
+
EncryptedDateOrdColumn,
|
|
122
|
+
EncryptedDateOrdOreColumn,
|
|
123
|
+
EncryptedDoubleColumn,
|
|
124
|
+
EncryptedDoubleEqColumn,
|
|
125
|
+
EncryptedDoubleOrdColumn,
|
|
126
|
+
EncryptedDoubleOrdOreColumn,
|
|
127
|
+
EncryptedIntegerColumn,
|
|
128
|
+
EncryptedIntegerEqColumn,
|
|
129
|
+
EncryptedIntegerOrdColumn,
|
|
130
|
+
EncryptedIntegerOrdOreColumn,
|
|
131
|
+
EncryptedNumericColumn,
|
|
132
|
+
EncryptedNumericEqColumn,
|
|
133
|
+
EncryptedNumericOrdColumn,
|
|
134
|
+
EncryptedNumericOrdOreColumn,
|
|
135
|
+
EncryptedRealColumn,
|
|
136
|
+
EncryptedRealEqColumn,
|
|
137
|
+
EncryptedRealOrdColumn,
|
|
138
|
+
EncryptedRealOrdOreColumn,
|
|
139
|
+
EncryptedSmallintColumn,
|
|
140
|
+
EncryptedSmallintEqColumn,
|
|
141
|
+
EncryptedSmallintOrdColumn,
|
|
142
|
+
EncryptedSmallintOrdOreColumn,
|
|
143
|
+
EncryptedTable,
|
|
144
|
+
EncryptedTextColumn,
|
|
145
|
+
EncryptedTextEqColumn,
|
|
146
|
+
EncryptedTextMatchColumn,
|
|
147
|
+
EncryptedTextOrdColumn,
|
|
148
|
+
EncryptedTextOrdOreColumn,
|
|
149
|
+
EncryptedTextSearchColumn,
|
|
150
|
+
EncryptedTimestampColumn,
|
|
151
|
+
EncryptedTimestampEqColumn,
|
|
152
|
+
EncryptedTimestampOrdColumn,
|
|
153
|
+
EncryptedTimestampOrdOreColumn,
|
|
154
|
+
EncryptionV3,
|
|
155
|
+
TEXT_SEARCH_EQL_TYPE,
|
|
156
|
+
buildEncryptConfig,
|
|
157
|
+
encryptedTable,
|
|
158
|
+
typedClient,
|
|
159
|
+
types
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=v3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/encryption/v3.ts"],"sourcesContent":["import type { Result } from '@byteslice/result'\nimport type {\n AnyV3Table,\n ColumnsOf,\n PlaintextForColumn,\n QueryableColumnsOf,\n QueryTypesForColumn,\n V3DecryptedModel,\n V3EncryptedModel,\n V3ModelInput,\n} from '@/eql/v3'\nimport type { EncryptionError } from '@/errors'\nimport type { LockContextInput } from '@/identity'\nimport type {\n BulkDecryptPayload,\n BulkEncryptPayload,\n ClientConfig,\n Encrypted,\n EncryptedReturnType,\n EncryptOptions,\n} from '@/types'\nimport {\n type BulkDecryptOperation,\n type BulkEncryptModelsOperation,\n type BulkEncryptOperation,\n type DecryptOperation,\n Encryption,\n type EncryptionClient,\n type EncryptModelOperation,\n type EncryptOperation,\n type EncryptQueryOperation,\n} from './index'\n\n/**\n * A strongly-typed view over an {@link EncryptionClient} for EQL v3 schemas.\n *\n * Every method derives its types from the concrete `table` / `column` builder\n * arguments (which carry their branded types at the call site), so:\n * - `encrypt` / `encryptQuery` pin the plaintext to the column's domain type\n * (`text → string`, `timestamp → Date`, …);\n * - `encryptQuery` additionally constrains `queryType` to the column's\n * capabilities and rejects storage-only columns outright;\n * - `encryptModel` / `bulkEncryptModels` validate schema-column fields against\n * their inferred plaintext type (passthrough fields are untouched) and return\n * a precise encrypted model;\n * - `decryptModel` / `bulkDecryptModels` return the precise plaintext model,\n * reconstructing `Date` values from the encrypt-config `cast_as`.\n *\n * @typeParam S - the tuple of registered v3 tables; `table` arguments must be a\n * member of this tuple.\n */\nexport interface TypedEncryptionClient<S extends readonly AnyV3Table[]> {\n encrypt<Table extends S[number], Col extends ColumnsOf<Table>>(\n plaintext: PlaintextForColumn<Col>,\n opts: { table: Table; column: Col },\n ): EncryptOperation\n\n encryptQuery<\n Table extends S[number],\n Col extends QueryableColumnsOf<Table>,\n QT extends QueryTypesForColumn<Col> = QueryTypesForColumn<Col>,\n >(\n plaintext: PlaintextForColumn<Col>,\n opts: {\n table: Table\n column: Col\n queryType?: QT\n returnType?: EncryptedReturnType\n },\n ): EncryptQueryOperation\n\n encryptModel<Table extends S[number], T extends Record<string, unknown>>(\n input: V3ModelInput<Table, T>,\n table: Table,\n ): EncryptModelOperation<V3EncryptedModel<Table, T>>\n\n bulkEncryptModels<Table extends S[number], T extends Record<string, unknown>>(\n input: Array<V3ModelInput<Table, T>>,\n table: Table,\n ): BulkEncryptModelsOperation<V3EncryptedModel<Table, T>>\n\n /**\n * Decrypt a single value. Cannot be strongly typed — a lone ciphertext carries\n * no column identity — so it resolves to the FFI plaintext union unchanged.\n */\n decrypt(encrypted: Encrypted): DecryptOperation\n\n /**\n * Decrypt a model, returning the precise plaintext shape for `table`. `Date`\n * columns are reconstructed from the encrypt-config `cast_as`.\n *\n * Pass `lockContext` to decrypt identity-bound data — the same context that\n * was supplied at encrypt time must be provided here.\n *\n * Unlike the encrypt operations this returns a plain `Promise<Result<…>>`\n * rather than a chainable operation, because it maps the resolved value.\n */\n decryptModel<Table extends S[number], T extends Record<string, unknown>>(\n input: T,\n table: Table,\n lockContext?: LockContextInput,\n ): Promise<Result<V3DecryptedModel<Table, T>, EncryptionError>>\n\n bulkDecryptModels<Table extends S[number], T extends Record<string, unknown>>(\n input: Array<T>,\n table: Table,\n lockContext?: LockContextInput,\n ): Promise<Result<Array<V3DecryptedModel<Table, T>>, EncryptionError>>\n\n // Parity passthroughs — not v3-strengthened, delegated as-is.\n bulkEncrypt(\n plaintexts: BulkEncryptPayload,\n opts: EncryptOptions,\n ): BulkEncryptOperation\n bulkDecrypt(payloads: BulkDecryptPayload): BulkDecryptOperation\n getEncryptConfig(): ReturnType<EncryptionClient['getEncryptConfig']>\n}\n\n/**\n * Build a per-row reconstructor of `Date` values from the table's\n * encrypt-config `cast_as`. The FFI returns `JsPlaintext`\n * (string/number/boolean/…) with no `Date`, so those columns arrive as their\n * serialized form and are rebuilt here. Safe (idempotent) if the FFI ever\n * returns `Date` directly: `new Date(date)` is a no-op.\n *\n * A factory rather than a `(row, table)` function so the table config —\n * row-invariant, but non-trivial to build — is derived once per call site,\n * not once per row on the bulk path.\n *\n * NOTE: `bigint` reconstruction is intentionally absent — bigint domains are\n * omitted from the v3 SDK until the native FFI supports lossless bigint I/O.\n */\nfunction rowReconstructor(\n table: AnyV3Table,\n): (row: Record<string, unknown>) => Record<string, unknown> {\n // The decrypted row is keyed by JS property name, but `cast_as` lives on the\n // config keyed by DB name — bridge the two via the table's property→DB map.\n const { columns } = table.build()\n const propToDb = table.buildColumnKeyMap()\n // Only date/timestamp columns need per-row work; resolve them up front.\n // Both kinds decrypt to a JS `Date` — 'timestamp' additionally preserves\n // the time-of-day component through the FFI.\n const dateProperties = Object.entries(propToDb)\n .filter(([, dbName]) => {\n const castAs = columns[dbName]?.cast_as\n return castAs === 'date' || castAs === 'timestamp'\n })\n .map(([property]) => property)\n\n return (row) => {\n const out: Record<string, unknown> = { ...row }\n for (const property of dateProperties) {\n const value = out[property]\n if (value == null) continue\n out[property] = new Date(value as string | number | Date)\n }\n return out\n }\n}\n\n/**\n * Wrap an already-built {@link EncryptionClient} in a {@link TypedEncryptionClient}\n * for the given v3 schemas. Zero runtime cost for the encrypt/query paths (the\n * underlying operations are returned unchanged); the decrypt-model paths add a\n * per-column `Date` reconstruction step.\n *\n * The `schemas` are captured with a `const` type parameter so array-literal\n * widening does not collapse per-table inference.\n */\nexport function typedClient<const S extends readonly AnyV3Table[]>(\n client: EncryptionClient,\n ..._schemas: S\n): TypedEncryptionClient<S> {\n return {\n encrypt: (plaintext, opts) =>\n client.encrypt(plaintext as never, opts as never),\n encryptQuery: (plaintext, opts) =>\n client.encryptQuery(plaintext as never, opts as never),\n encryptModel: (input, table) =>\n client.encryptModel(input as never, table as never) as never,\n bulkEncryptModels: (input, table) =>\n client.bulkEncryptModels(input as never, table as never) as never,\n decrypt: (encrypted) => client.decrypt(encrypted),\n decryptModel: async (input, table, lockContext) => {\n const op = client.decryptModel(input as never)\n const result = await (lockContext ? op.withLockContext(lockContext) : op)\n if (result.failure) return result as never\n return { data: rowReconstructor(table)(result.data) } as never\n },\n bulkDecryptModels: async (input, table, lockContext) => {\n const op = client.bulkDecryptModels(input as never)\n const result = await (lockContext ? op.withLockContext(lockContext) : op)\n if (result.failure) return result as never\n const reconstruct = rowReconstructor(table)\n return {\n data: result.data.map((row) =>\n reconstruct(row as Record<string, unknown>),\n ),\n } as never\n },\n bulkEncrypt: (plaintexts, opts) => client.bulkEncrypt(plaintexts, opts),\n bulkDecrypt: (payloads) => client.bulkDecrypt(payloads),\n getEncryptConfig: () => client.getEncryptConfig(),\n } satisfies TypedEncryptionClient<S>\n}\n\n/**\n * Build a {@link TypedEncryptionClient} for EQL v3 schemas — the strongly-typed\n * counterpart to {@link Encryption}. Mirrors its config, then retypes the client\n * against the provided v3 `schemas`.\n *\n * The underlying client is created with `eqlVersion: 3` (protect-ffi 0.27+),\n * so `encrypt` / `encryptModel` emit EQL v3 wire payloads for the\n * per-capability `eql_v3` domains. Pass an explicit `config.eqlVersion` to\n * override — e.g. `2` to write v2-wire from a v3 schema set during a\n * migration.\n *\n * @example\n * ```typescript\n * import { EncryptionV3, encryptedTable, types } from \"@cipherstash/stack/v3\"\n *\n * const users = encryptedTable(\"users\", { email: types.TextSearch(\"email\") })\n * const client = await EncryptionV3({ schemas: [users] })\n *\n * await client.encrypt(\"a@b.com\", { table: users, column: users.email })\n * ```\n */\nexport async function EncryptionV3<\n const S extends readonly AnyV3Table[],\n>(config: {\n schemas: S\n config?: ClientConfig\n}): Promise<TypedEncryptionClient<S>> {\n const client = await Encryption({\n schemas: config.schemas as unknown as Parameters<\n typeof Encryption\n >[0]['schemas'],\n // v3 schemas emit the EQL v3 wire format. Auto-detection in\n // `Encryption` would resolve the same way (every v3 table carries the\n // `buildColumnKeyMap` marker), but the version is set explicitly here\n // so the contract doesn't hinge on duck-typing — while still honouring\n // a caller's explicit override.\n config: { ...config.config, eqlVersion: config.config?.eqlVersion ?? 3 },\n })\n return typedClient(client, ...config.schemas)\n}\n\n// Single import surface: re-export the v3 `types` namespace + table API + type\n// helpers so `@cipherstash/stack/v3` provides everything needed to author and\n// use a schema.\nexport * from '@/eql/v3'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoIA,SAAS,iBACP,OAC2D;AAG3D,QAAM,EAAE,QAAQ,IAAI,MAAM,MAAM;AAChC,QAAM,WAAW,MAAM,kBAAkB;AAIzC,QAAM,iBAAiB,OAAO,QAAQ,QAAQ,EAC3C,OAAO,CAAC,CAAC,EAAE,MAAM,MAAM;AACtB,UAAM,SAAS,QAAQ,MAAM,GAAG;AAChC,WAAO,WAAW,UAAU,WAAW;AAAA,EACzC,CAAC,EACA,IAAI,CAAC,CAAC,QAAQ,MAAM,QAAQ;AAE/B,SAAO,CAAC,QAAQ;AACd,UAAM,MAA+B,EAAE,GAAG,IAAI;AAC9C,eAAW,YAAY,gBAAgB;AACrC,YAAM,QAAQ,IAAI,QAAQ;AAC1B,UAAI,SAAS,KAAM;AACnB,UAAI,QAAQ,IAAI,IAAI,KAAK,KAA+B;AAAA,IAC1D;AACA,WAAO;AAAA,EACT;AACF;AAWO,SAAS,YACd,WACG,UACuB;AAC1B,SAAO;AAAA,IACL,SAAS,CAAC,WAAW,SACnB,OAAO,QAAQ,WAAoB,IAAa;AAAA,IAClD,cAAc,CAAC,WAAW,SACxB,OAAO,aAAa,WAAoB,IAAa;AAAA,IACvD,cAAc,CAAC,OAAO,UACpB,OAAO,aAAa,OAAgB,KAAc;AAAA,IACpD,mBAAmB,CAAC,OAAO,UACzB,OAAO,kBAAkB,OAAgB,KAAc;AAAA,IACzD,SAAS,CAAC,cAAc,OAAO,QAAQ,SAAS;AAAA,IAChD,cAAc,OAAO,OAAO,OAAO,gBAAgB;AACjD,YAAM,KAAK,OAAO,aAAa,KAAc;AAC7C,YAAM,SAAS,OAAO,cAAc,GAAG,gBAAgB,WAAW,IAAI;AACtE,UAAI,OAAO,QAAS,QAAO;AAC3B,aAAO,EAAE,MAAM,iBAAiB,KAAK,EAAE,OAAO,IAAI,EAAE;AAAA,IACtD;AAAA,IACA,mBAAmB,OAAO,OAAO,OAAO,gBAAgB;AACtD,YAAM,KAAK,OAAO,kBAAkB,KAAc;AAClD,YAAM,SAAS,OAAO,cAAc,GAAG,gBAAgB,WAAW,IAAI;AACtE,UAAI,OAAO,QAAS,QAAO;AAC3B,YAAM,cAAc,iBAAiB,KAAK;AAC1C,aAAO;AAAA,QACL,MAAM,OAAO,KAAK;AAAA,UAAI,CAAC,QACrB,YAAY,GAA8B;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,IACA,aAAa,CAAC,YAAY,SAAS,OAAO,YAAY,YAAY,IAAI;AAAA,IACtE,aAAa,CAAC,aAAa,OAAO,YAAY,QAAQ;AAAA,IACtD,kBAAkB,MAAM,OAAO,iBAAiB;AAAA,EAClD;AACF;AAuBA,eAAsB,aAEpB,QAGoC;AACpC,QAAM,SAAS,MAAM,WAAW;AAAA,IAC9B,SAAS,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQhB,QAAQ,EAAE,GAAG,OAAO,QAAQ,YAAY,OAAO,QAAQ,cAAc,EAAE;AAAA,EACzE,CAAC;AACD,SAAO,YAAY,QAAQ,GAAG,OAAO,OAAO;AAC9C;","names":[]}
|