@cipherstash/stack 0.18.0 → 1.0.0-rc.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.
Files changed (111) hide show
  1. package/CHANGELOG.md +704 -0
  2. package/README.md +97 -79
  3. package/dist/adapter-kit.cjs +923 -0
  4. package/dist/adapter-kit.cjs.map +1 -0
  5. package/dist/adapter-kit.d.cts +82 -0
  6. package/dist/adapter-kit.d.ts +82 -0
  7. package/dist/adapter-kit.js +47 -0
  8. package/dist/adapter-kit.js.map +1 -0
  9. package/dist/base-operation-AOAIvsSB.d.cts +32 -0
  10. package/dist/base-operation-FXEzUXIq.d.ts +32 -0
  11. package/dist/{chunk-VPOTNP4K.js → chunk-3B5ZX3IS.js} +3 -1
  12. package/dist/chunk-3B5ZX3IS.js.map +1 -0
  13. package/dist/chunk-7333ZC6L.js +48 -0
  14. package/dist/chunk-7333ZC6L.js.map +1 -0
  15. package/dist/{chunk-XWPGAHBZ.js → chunk-BNO32ZMV.js} +1 -1
  16. package/dist/chunk-BNO32ZMV.js.map +1 -0
  17. package/dist/chunk-CLM7E4I6.js +4439 -0
  18. package/dist/chunk-CLM7E4I6.js.map +1 -0
  19. package/dist/{chunk-LLCCNKDL.js → chunk-HQANMV7R.js} +3 -3
  20. package/dist/{chunk-LLCCNKDL.js.map → chunk-HQANMV7R.js.map} +1 -1
  21. package/dist/chunk-JSG2AMDI.js +17 -0
  22. package/dist/chunk-JSG2AMDI.js.map +1 -0
  23. package/dist/chunk-OFQ555AX.js +191 -0
  24. package/dist/chunk-OFQ555AX.js.map +1 -0
  25. package/dist/chunk-PZ5AY32C.js +10 -0
  26. package/dist/chunk-PZ5AY32C.js.map +1 -0
  27. package/dist/chunk-V2Q3NYIH.js +494 -0
  28. package/dist/chunk-V2Q3NYIH.js.map +1 -0
  29. package/dist/chunk-X3JRXEIB.js +98 -0
  30. package/dist/chunk-X3JRXEIB.js.map +1 -0
  31. package/dist/{chunk-ZYOZHZMJ.js → chunk-ZTP5QJ27.js} +193 -169
  32. package/dist/chunk-ZTP5QJ27.js.map +1 -0
  33. package/dist/client.cjs +4124 -49
  34. package/dist/client.cjs.map +1 -1
  35. package/dist/client.d.cts +6 -5
  36. package/dist/client.d.ts +6 -5
  37. package/dist/client.js +3 -1
  38. package/dist/columns-D2_YzrCX.d.cts +622 -0
  39. package/dist/columns-rZc7fQHI.d.ts +622 -0
  40. package/dist/dynamodb/index.cjs +19 -12
  41. package/dist/dynamodb/index.cjs.map +1 -1
  42. package/dist/dynamodb/index.d.cts +3 -2
  43. package/dist/dynamodb/index.d.ts +3 -2
  44. package/dist/dynamodb/index.js +8 -10
  45. package/dist/dynamodb/index.js.map +1 -1
  46. package/dist/encryption/index.cjs +4496 -222
  47. package/dist/encryption/index.cjs.map +1 -1
  48. package/dist/encryption/index.d.cts +807 -6
  49. package/dist/encryption/index.d.ts +807 -6
  50. package/dist/encryption/index.js +15 -7
  51. package/dist/encryption/v3.cjs +7896 -0
  52. package/dist/encryption/v3.cjs.map +1 -0
  53. package/dist/encryption/v3.d.cts +103 -0
  54. package/dist/encryption/v3.d.ts +103 -0
  55. package/dist/encryption/v3.js +189 -0
  56. package/dist/encryption/v3.js.map +1 -0
  57. package/dist/eql/v3/index.cjs +663 -0
  58. package/dist/eql/v3/index.cjs.map +1 -0
  59. package/dist/eql/v3/index.d.cts +173 -0
  60. package/dist/eql/v3/index.d.ts +173 -0
  61. package/dist/eql/v3/index.js +99 -0
  62. package/dist/eql/v3/index.js.map +1 -0
  63. package/dist/errors/index.js +1 -0
  64. package/dist/identity/index.cjs +55 -35
  65. package/dist/identity/index.cjs.map +1 -1
  66. package/dist/identity/index.d.cts +54 -30
  67. package/dist/identity/index.d.ts +54 -30
  68. package/dist/identity/index.js +9 -177
  69. package/dist/identity/index.js.map +1 -1
  70. package/dist/index-BquA71_Y.d.ts +24 -0
  71. package/dist/index-fhWTOV0K.d.cts +24 -0
  72. package/dist/index.cjs +4547 -243
  73. package/dist/index.cjs.map +1 -1
  74. package/dist/index.d.cts +18 -19
  75. package/dist/index.d.ts +18 -19
  76. package/dist/index.js +20 -5
  77. package/dist/index.js.map +1 -1
  78. package/dist/schema/index.cjs +4128 -49
  79. package/dist/schema/index.cjs.map +1 -1
  80. package/dist/schema/index.d.cts +1 -1
  81. package/dist/schema/index.d.ts +1 -1
  82. package/dist/schema/index.js +3 -1
  83. package/dist/{types-public-BTxqjmtv.d.cts → types-public-QMjYNfQO.d.cts} +448 -251
  84. package/dist/{types-public-BTxqjmtv.d.ts → types-public-QMjYNfQO.d.ts} +448 -251
  85. package/dist/types-public.cjs.map +1 -1
  86. package/dist/types-public.d.cts +2 -2
  87. package/dist/types-public.d.ts +2 -2
  88. package/dist/types-public.js +2 -1
  89. package/dist/wasm-inline.d.ts +1643 -0
  90. package/dist/wasm-inline.js +4901 -0
  91. package/dist/wasm-inline.js.map +1 -0
  92. package/package.json +74 -52
  93. package/dist/chunk-VPOTNP4K.js.map +0 -1
  94. package/dist/chunk-XWPGAHBZ.js.map +0 -1
  95. package/dist/chunk-YWQXTZ5M.js +0 -383
  96. package/dist/chunk-YWQXTZ5M.js.map +0 -1
  97. package/dist/chunk-ZYOZHZMJ.js.map +0 -1
  98. package/dist/client-CIsfZ2zg.d.ts +0 -692
  99. package/dist/client-Dt98Rugc.d.cts +0 -692
  100. package/dist/drizzle/index.cjs +0 -1558
  101. package/dist/drizzle/index.cjs.map +0 -1
  102. package/dist/drizzle/index.d.cts +0 -358
  103. package/dist/drizzle/index.d.ts +0 -358
  104. package/dist/drizzle/index.js +0 -1215
  105. package/dist/drizzle/index.js.map +0 -1
  106. package/dist/supabase/index.cjs +0 -1526
  107. package/dist/supabase/index.cjs.map +0 -1
  108. package/dist/supabase/index.d.cts +0 -144
  109. package/dist/supabase/index.d.ts +0 -144
  110. package/dist/supabase/index.js +0 -899
  111. package/dist/supabase/index.js.map +0 -1
@@ -0,0 +1,103 @@
1
+ import { Result } from '@byteslice/result';
2
+ import { V as PlaintextForColumn, X as QueryTypesForColumn } from '../columns-D2_YzrCX.cjs';
3
+ export { A as AnyEncryptedV3Column, E as EncryptedBigintColumn, a as EncryptedBigintEqColumn, b as EncryptedBigintOrdColumn, c as EncryptedBigintOrdOreColumn, d 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 EncryptedJsonColumn, r as EncryptedNumericColumn, s as EncryptedNumericEqColumn, t as EncryptedNumericOrdColumn, u as EncryptedNumericOrdOreColumn, v as EncryptedRealColumn, w as EncryptedRealEqColumn, x as EncryptedRealOrdColumn, y as EncryptedRealOrdOreColumn, z as EncryptedSmallintColumn, B as EncryptedSmallintEqColumn, C as EncryptedSmallintOrdColumn, F as EncryptedSmallintOrdOreColumn, 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, P as EncryptedTimestampOrdOreColumn, R as EncryptedV3TableColumn, S as EqlTypeForColumn, T as JsonDocument, U as JsonValue, W as QueryCapabilities, Y as TEXT_SEARCH_EQL_TYPE } from '../columns-D2_YzrCX.cjs';
4
+ import { AnyV3Table, ColumnsOf, QueryableColumnsOf, V3ModelInput, V3EncryptedModel, V3DecryptedModel } from '../eql/v3/index.cjs';
5
+ export { EncryptedTable, InferEncrypted, InferPlaintext, buildEncryptConfig, encryptedTable, types } from '../eql/v3/index.cjs';
6
+ import { EncryptionError } from '../errors/index.cjs';
7
+ import { LockContextInput } from '../identity/index.cjs';
8
+ import { j as ClientConfig, x as EncryptedReturnType, S as ScalarQueryTerm, p as Encrypted, g as BulkEncryptPayload, n as EncryptOptions, e as BulkDecryptPayload } from '../types-public-QMjYNfQO.cjs';
9
+ import { EncryptOperation, EncryptQueryOperation, BatchEncryptQueryOperation, EncryptModelOperation, BulkEncryptModelsOperation, DecryptOperation, BulkEncryptOperation, BulkDecryptOperation, EncryptionClient } from './index.cjs';
10
+ import '@cipherstash/protect-ffi';
11
+ import 'zod';
12
+ import '../base-operation-AOAIvsSB.cjs';
13
+
14
+ /**
15
+ * A strongly-typed view over an {@link EncryptionClient} for EQL v3 schemas.
16
+ *
17
+ * Every method derives its types from the concrete `table` / `column` builder
18
+ * arguments (which carry their branded types at the call site), so:
19
+ * - `encrypt` / `encryptQuery` pin the plaintext to the column's domain type
20
+ * (`text → string`, `timestamp → Date`, …);
21
+ * - `encryptQuery` additionally constrains `queryType` to the column's
22
+ * capabilities and rejects storage-only columns outright;
23
+ * - `encryptModel` / `bulkEncryptModels` validate schema-column fields against
24
+ * their inferred plaintext type (passthrough fields are untouched) and return
25
+ * a precise encrypted model;
26
+ * - `decryptModel` / `bulkDecryptModels` return the precise plaintext model,
27
+ * reconstructing `Date` values from the encrypt-config `cast_as`.
28
+ *
29
+ * @typeParam S - the tuple of registered v3 tables; `table` arguments must be a
30
+ * member of this tuple.
31
+ */
32
+ interface TypedEncryptionClient<S extends readonly AnyV3Table[]> {
33
+ encrypt<Table extends S[number], Col extends ColumnsOf<Table>>(plaintext: PlaintextForColumn<Col>, opts: {
34
+ table: Table;
35
+ column: Col;
36
+ }): EncryptOperation;
37
+ encryptQuery<Table extends S[number], Col extends QueryableColumnsOf<Table>, QT extends QueryTypesForColumn<Col> = QueryTypesForColumn<Col>>(plaintext: PlaintextForColumn<Col>, opts: {
38
+ table: Table;
39
+ column: Col;
40
+ queryType?: QT;
41
+ returnType?: EncryptedReturnType;
42
+ }): EncryptQueryOperation;
43
+ /**
44
+ * Batch form: encrypt many query terms in one crossing. Mirrors the nominal
45
+ * {@link EncryptionClient} overload — the per-term columns are heterogeneous,
46
+ * so the terms are the base {@link ScalarQueryTerm} rather than a per-column
47
+ * narrowed type. Consumed by the Drizzle `inArray`/`notInArray` operators.
48
+ */
49
+ encryptQuery(terms: readonly ScalarQueryTerm[]): BatchEncryptQueryOperation;
50
+ encryptModel<Table extends S[number], T extends Record<string, unknown>>(input: V3ModelInput<Table, T>, table: Table): EncryptModelOperation<V3EncryptedModel<Table, T>>;
51
+ bulkEncryptModels<Table extends S[number], T extends Record<string, unknown>>(input: Array<V3ModelInput<Table, T>>, table: Table): BulkEncryptModelsOperation<V3EncryptedModel<Table, T>>;
52
+ /**
53
+ * Decrypt a single value. Cannot be strongly typed — a lone ciphertext carries
54
+ * no column identity — so it resolves to the FFI plaintext union unchanged.
55
+ */
56
+ decrypt(encrypted: Encrypted): DecryptOperation;
57
+ /**
58
+ * Decrypt a model, returning the precise plaintext shape for `table`. `Date`
59
+ * columns are reconstructed from the encrypt-config `cast_as`.
60
+ *
61
+ * Pass `lockContext` to decrypt identity-bound data — the same context that
62
+ * was supplied at encrypt time must be provided here.
63
+ *
64
+ * Unlike the encrypt operations this returns a plain `Promise<Result<…>>`
65
+ * rather than a chainable operation, because it maps the resolved value.
66
+ */
67
+ decryptModel<Table extends S[number], T extends Record<string, unknown>>(input: T, table: Table, lockContext?: LockContextInput): Promise<Result<V3DecryptedModel<Table, T>, EncryptionError>>;
68
+ bulkDecryptModels<Table extends S[number], T extends Record<string, unknown>>(input: Array<T>, table: Table, lockContext?: LockContextInput): Promise<Result<Array<V3DecryptedModel<Table, T>>, EncryptionError>>;
69
+ bulkEncrypt(plaintexts: BulkEncryptPayload, opts: EncryptOptions): BulkEncryptOperation;
70
+ bulkDecrypt(payloads: BulkDecryptPayload): BulkDecryptOperation;
71
+ getEncryptConfig(): ReturnType<EncryptionClient['getEncryptConfig']>;
72
+ }
73
+ /**
74
+ * Wrap an already-built {@link EncryptionClient} in a {@link TypedEncryptionClient}
75
+ * for the given v3 schemas. Zero runtime cost for the encrypt/query paths (the
76
+ * underlying operations are returned unchanged); the decrypt-model paths add a
77
+ * per-column `Date` reconstruction step.
78
+ *
79
+ * The `schemas` are captured with a `const` type parameter so array-literal
80
+ * widening does not collapse per-table inference.
81
+ */
82
+ declare function typedClient<const S extends readonly AnyV3Table[]>(client: EncryptionClient, ...schemas: S): TypedEncryptionClient<S>;
83
+ /**
84
+ * Build a {@link TypedEncryptionClient} for EQL v3 schemas — the strongly-typed
85
+ * counterpart to {@link Encryption}. Mirrors its config, then retypes the client
86
+ * against the provided v3 `schemas`.
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * import { EncryptionV3, encryptedTable, types } from "@cipherstash/stack/v3"
91
+ *
92
+ * const users = encryptedTable("users", { email: types.TextSearch("email") })
93
+ * const client = await EncryptionV3({ schemas: [users] })
94
+ *
95
+ * await client.encrypt("a@b.com", { table: users, column: users.email })
96
+ * ```
97
+ */
98
+ declare function EncryptionV3<const S extends readonly AnyV3Table[]>(config: {
99
+ schemas: S;
100
+ config?: ClientConfig;
101
+ }): Promise<TypedEncryptionClient<S>>;
102
+
103
+ export { AnyV3Table, ColumnsOf, EncryptionV3, PlaintextForColumn, QueryTypesForColumn, QueryableColumnsOf, type TypedEncryptionClient, V3DecryptedModel, V3EncryptedModel, V3ModelInput, typedClient };
@@ -0,0 +1,103 @@
1
+ import { Result } from '@byteslice/result';
2
+ import { V as PlaintextForColumn, X as QueryTypesForColumn } from '../columns-rZc7fQHI.js';
3
+ export { A as AnyEncryptedV3Column, E as EncryptedBigintColumn, a as EncryptedBigintEqColumn, b as EncryptedBigintOrdColumn, c as EncryptedBigintOrdOreColumn, d 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 EncryptedJsonColumn, r as EncryptedNumericColumn, s as EncryptedNumericEqColumn, t as EncryptedNumericOrdColumn, u as EncryptedNumericOrdOreColumn, v as EncryptedRealColumn, w as EncryptedRealEqColumn, x as EncryptedRealOrdColumn, y as EncryptedRealOrdOreColumn, z as EncryptedSmallintColumn, B as EncryptedSmallintEqColumn, C as EncryptedSmallintOrdColumn, F as EncryptedSmallintOrdOreColumn, 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, P as EncryptedTimestampOrdOreColumn, R as EncryptedV3TableColumn, S as EqlTypeForColumn, T as JsonDocument, U as JsonValue, W as QueryCapabilities, Y as TEXT_SEARCH_EQL_TYPE } from '../columns-rZc7fQHI.js';
4
+ import { AnyV3Table, ColumnsOf, QueryableColumnsOf, V3ModelInput, V3EncryptedModel, V3DecryptedModel } from '../eql/v3/index.js';
5
+ export { EncryptedTable, InferEncrypted, InferPlaintext, buildEncryptConfig, encryptedTable, types } from '../eql/v3/index.js';
6
+ import { EncryptionError } from '../errors/index.js';
7
+ import { LockContextInput } from '../identity/index.js';
8
+ import { j as ClientConfig, x as EncryptedReturnType, S as ScalarQueryTerm, p as Encrypted, g as BulkEncryptPayload, n as EncryptOptions, e as BulkDecryptPayload } from '../types-public-QMjYNfQO.js';
9
+ import { EncryptOperation, EncryptQueryOperation, BatchEncryptQueryOperation, EncryptModelOperation, BulkEncryptModelsOperation, DecryptOperation, BulkEncryptOperation, BulkDecryptOperation, EncryptionClient } from './index.js';
10
+ import '@cipherstash/protect-ffi';
11
+ import 'zod';
12
+ import '../base-operation-FXEzUXIq.js';
13
+
14
+ /**
15
+ * A strongly-typed view over an {@link EncryptionClient} for EQL v3 schemas.
16
+ *
17
+ * Every method derives its types from the concrete `table` / `column` builder
18
+ * arguments (which carry their branded types at the call site), so:
19
+ * - `encrypt` / `encryptQuery` pin the plaintext to the column's domain type
20
+ * (`text → string`, `timestamp → Date`, …);
21
+ * - `encryptQuery` additionally constrains `queryType` to the column's
22
+ * capabilities and rejects storage-only columns outright;
23
+ * - `encryptModel` / `bulkEncryptModels` validate schema-column fields against
24
+ * their inferred plaintext type (passthrough fields are untouched) and return
25
+ * a precise encrypted model;
26
+ * - `decryptModel` / `bulkDecryptModels` return the precise plaintext model,
27
+ * reconstructing `Date` values from the encrypt-config `cast_as`.
28
+ *
29
+ * @typeParam S - the tuple of registered v3 tables; `table` arguments must be a
30
+ * member of this tuple.
31
+ */
32
+ interface TypedEncryptionClient<S extends readonly AnyV3Table[]> {
33
+ encrypt<Table extends S[number], Col extends ColumnsOf<Table>>(plaintext: PlaintextForColumn<Col>, opts: {
34
+ table: Table;
35
+ column: Col;
36
+ }): EncryptOperation;
37
+ encryptQuery<Table extends S[number], Col extends QueryableColumnsOf<Table>, QT extends QueryTypesForColumn<Col> = QueryTypesForColumn<Col>>(plaintext: PlaintextForColumn<Col>, opts: {
38
+ table: Table;
39
+ column: Col;
40
+ queryType?: QT;
41
+ returnType?: EncryptedReturnType;
42
+ }): EncryptQueryOperation;
43
+ /**
44
+ * Batch form: encrypt many query terms in one crossing. Mirrors the nominal
45
+ * {@link EncryptionClient} overload — the per-term columns are heterogeneous,
46
+ * so the terms are the base {@link ScalarQueryTerm} rather than a per-column
47
+ * narrowed type. Consumed by the Drizzle `inArray`/`notInArray` operators.
48
+ */
49
+ encryptQuery(terms: readonly ScalarQueryTerm[]): BatchEncryptQueryOperation;
50
+ encryptModel<Table extends S[number], T extends Record<string, unknown>>(input: V3ModelInput<Table, T>, table: Table): EncryptModelOperation<V3EncryptedModel<Table, T>>;
51
+ bulkEncryptModels<Table extends S[number], T extends Record<string, unknown>>(input: Array<V3ModelInput<Table, T>>, table: Table): BulkEncryptModelsOperation<V3EncryptedModel<Table, T>>;
52
+ /**
53
+ * Decrypt a single value. Cannot be strongly typed — a lone ciphertext carries
54
+ * no column identity — so it resolves to the FFI plaintext union unchanged.
55
+ */
56
+ decrypt(encrypted: Encrypted): DecryptOperation;
57
+ /**
58
+ * Decrypt a model, returning the precise plaintext shape for `table`. `Date`
59
+ * columns are reconstructed from the encrypt-config `cast_as`.
60
+ *
61
+ * Pass `lockContext` to decrypt identity-bound data — the same context that
62
+ * was supplied at encrypt time must be provided here.
63
+ *
64
+ * Unlike the encrypt operations this returns a plain `Promise<Result<…>>`
65
+ * rather than a chainable operation, because it maps the resolved value.
66
+ */
67
+ decryptModel<Table extends S[number], T extends Record<string, unknown>>(input: T, table: Table, lockContext?: LockContextInput): Promise<Result<V3DecryptedModel<Table, T>, EncryptionError>>;
68
+ bulkDecryptModels<Table extends S[number], T extends Record<string, unknown>>(input: Array<T>, table: Table, lockContext?: LockContextInput): Promise<Result<Array<V3DecryptedModel<Table, T>>, EncryptionError>>;
69
+ bulkEncrypt(plaintexts: BulkEncryptPayload, opts: EncryptOptions): BulkEncryptOperation;
70
+ bulkDecrypt(payloads: BulkDecryptPayload): BulkDecryptOperation;
71
+ getEncryptConfig(): ReturnType<EncryptionClient['getEncryptConfig']>;
72
+ }
73
+ /**
74
+ * Wrap an already-built {@link EncryptionClient} in a {@link TypedEncryptionClient}
75
+ * for the given v3 schemas. Zero runtime cost for the encrypt/query paths (the
76
+ * underlying operations are returned unchanged); the decrypt-model paths add a
77
+ * per-column `Date` reconstruction step.
78
+ *
79
+ * The `schemas` are captured with a `const` type parameter so array-literal
80
+ * widening does not collapse per-table inference.
81
+ */
82
+ declare function typedClient<const S extends readonly AnyV3Table[]>(client: EncryptionClient, ...schemas: S): TypedEncryptionClient<S>;
83
+ /**
84
+ * Build a {@link TypedEncryptionClient} for EQL v3 schemas — the strongly-typed
85
+ * counterpart to {@link Encryption}. Mirrors its config, then retypes the client
86
+ * against the provided v3 `schemas`.
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * import { EncryptionV3, encryptedTable, types } from "@cipherstash/stack/v3"
91
+ *
92
+ * const users = encryptedTable("users", { email: types.TextSearch("email") })
93
+ * const client = await EncryptionV3({ schemas: [users] })
94
+ *
95
+ * await client.encrypt("a@b.com", { table: users, column: users.email })
96
+ * ```
97
+ */
98
+ declare function EncryptionV3<const S extends readonly AnyV3Table[]>(config: {
99
+ schemas: S;
100
+ config?: ClientConfig;
101
+ }): Promise<TypedEncryptionClient<S>>;
102
+
103
+ export { AnyV3Table, ColumnsOf, EncryptionV3, PlaintextForColumn, QueryTypesForColumn, QueryableColumnsOf, type TypedEncryptionClient, V3DecryptedModel, V3EncryptedModel, V3ModelInput, typedClient };
@@ -0,0 +1,189 @@
1
+ import {
2
+ EncryptedTable,
3
+ buildEncryptConfig,
4
+ encryptedTable
5
+ } from "../chunk-X3JRXEIB.js";
6
+ import {
7
+ DATE_LIKE_CASTS,
8
+ EncryptedBigintColumn,
9
+ EncryptedBigintEqColumn,
10
+ EncryptedBigintOrdColumn,
11
+ EncryptedBigintOrdOreColumn,
12
+ EncryptedBooleanColumn,
13
+ EncryptedDateColumn,
14
+ EncryptedDateEqColumn,
15
+ EncryptedDateOrdColumn,
16
+ EncryptedDateOrdOreColumn,
17
+ EncryptedDoubleColumn,
18
+ EncryptedDoubleEqColumn,
19
+ EncryptedDoubleOrdColumn,
20
+ EncryptedDoubleOrdOreColumn,
21
+ EncryptedIntegerColumn,
22
+ EncryptedIntegerEqColumn,
23
+ EncryptedIntegerOrdColumn,
24
+ EncryptedIntegerOrdOreColumn,
25
+ EncryptedJsonColumn,
26
+ EncryptedNumericColumn,
27
+ EncryptedNumericEqColumn,
28
+ EncryptedNumericOrdColumn,
29
+ EncryptedNumericOrdOreColumn,
30
+ EncryptedRealColumn,
31
+ EncryptedRealEqColumn,
32
+ EncryptedRealOrdColumn,
33
+ EncryptedRealOrdOreColumn,
34
+ EncryptedSmallintColumn,
35
+ EncryptedSmallintEqColumn,
36
+ EncryptedSmallintOrdColumn,
37
+ EncryptedSmallintOrdOreColumn,
38
+ EncryptedTextColumn,
39
+ EncryptedTextEqColumn,
40
+ EncryptedTextMatchColumn,
41
+ EncryptedTextOrdColumn,
42
+ EncryptedTextOrdOreColumn,
43
+ EncryptedTextSearchColumn,
44
+ EncryptedTimestampColumn,
45
+ EncryptedTimestampEqColumn,
46
+ EncryptedTimestampOrdColumn,
47
+ EncryptedTimestampOrdOreColumn,
48
+ TEXT_SEARCH_EQL_TYPE,
49
+ types
50
+ } from "../chunk-V2Q3NYIH.js";
51
+ import {
52
+ Encryption
53
+ } from "../chunk-ZTP5QJ27.js";
54
+ import "../chunk-OFQ555AX.js";
55
+ import "../chunk-BNO32ZMV.js";
56
+ import "../chunk-CLM7E4I6.js";
57
+ import "../chunk-7333ZC6L.js";
58
+ import "../chunk-3B5ZX3IS.js";
59
+ import "../chunk-JSG2AMDI.js";
60
+ import "../chunk-HQANMV7R.js";
61
+ import {
62
+ EncryptionErrorTypes
63
+ } from "../chunk-LBMC4D6D.js";
64
+ import "../chunk-PZ5AY32C.js";
65
+
66
+ // src/encryption/v3.ts
67
+ function rowReconstructor(table) {
68
+ const { columns } = table.build();
69
+ const propToDb = table.buildColumnKeyMap();
70
+ const dateProperties = Object.entries(propToDb).filter(([, dbName]) => {
71
+ const castAs = columns[dbName]?.cast_as;
72
+ return DATE_LIKE_CASTS.includes(castAs);
73
+ }).map(([property]) => property);
74
+ return (row) => {
75
+ const out = { ...row };
76
+ for (const property of dateProperties) {
77
+ const value = out[property];
78
+ if (value == null) continue;
79
+ out[property] = new Date(value);
80
+ }
81
+ return out;
82
+ };
83
+ }
84
+ function typedClient(client, ...schemas) {
85
+ const reconstructors = /* @__PURE__ */ new Map();
86
+ for (const table of schemas) {
87
+ reconstructors.set(table.tableName, rowReconstructor(table));
88
+ }
89
+ const unknownTableFailure = {
90
+ failure: {
91
+ type: EncryptionErrorTypes.DecryptionError,
92
+ message: "[eql/v3]: decryptModel received a table this client was not initialized with \u2014 pass a table given to EncryptionV3/typedClient"
93
+ }
94
+ };
95
+ function encryptQuery(plaintextOrTerms, opts) {
96
+ return client.encryptQuery(plaintextOrTerms, opts);
97
+ }
98
+ return {
99
+ encrypt: (plaintext, opts) => client.encrypt(plaintext, opts),
100
+ encryptQuery,
101
+ encryptModel: (input, table) => client.encryptModel(input, table),
102
+ bulkEncryptModels: (input, table) => client.bulkEncryptModels(input, table),
103
+ decrypt: (encrypted) => client.decrypt(encrypted),
104
+ decryptModel: async (input, table, lockContext) => {
105
+ const reconstruct = reconstructors.get(table.tableName);
106
+ if (!reconstruct) return unknownTableFailure;
107
+ const op = client.decryptModel(input);
108
+ const result = await (lockContext ? op.withLockContext(lockContext) : op);
109
+ if (result.failure) return result;
110
+ return { data: reconstruct(result.data) };
111
+ },
112
+ bulkDecryptModels: async (input, table, lockContext) => {
113
+ const reconstruct = reconstructors.get(table.tableName);
114
+ if (!reconstruct) return unknownTableFailure;
115
+ const op = client.bulkDecryptModels(input);
116
+ const result = await (lockContext ? op.withLockContext(lockContext) : op);
117
+ if (result.failure) return result;
118
+ return {
119
+ data: result.data.map(
120
+ (row) => reconstruct(row)
121
+ )
122
+ };
123
+ },
124
+ bulkEncrypt: (plaintexts, opts) => client.bulkEncrypt(plaintexts, opts),
125
+ bulkDecrypt: (payloads) => client.bulkDecrypt(payloads),
126
+ getEncryptConfig: () => client.getEncryptConfig()
127
+ };
128
+ }
129
+ async function EncryptionV3(config) {
130
+ const client = await Encryption({
131
+ schemas: config.schemas,
132
+ // Force the v3 EQL wire format. protect-ffi's newClient defaults to
133
+ // eqlVersion 2; a v2-mode client cannot resolve v3 concrete-type columns
134
+ // and fails every encrypt with "Cannot convert undefined or null to
135
+ // object". This is a v3-only invariant, so it overrides any user value.
136
+ config: { ...config.config, eqlVersion: 3 }
137
+ });
138
+ return typedClient(client, ...config.schemas);
139
+ }
140
+ export {
141
+ EncryptedBigintColumn,
142
+ EncryptedBigintEqColumn,
143
+ EncryptedBigintOrdColumn,
144
+ EncryptedBigintOrdOreColumn,
145
+ EncryptedBooleanColumn,
146
+ EncryptedDateColumn,
147
+ EncryptedDateEqColumn,
148
+ EncryptedDateOrdColumn,
149
+ EncryptedDateOrdOreColumn,
150
+ EncryptedDoubleColumn,
151
+ EncryptedDoubleEqColumn,
152
+ EncryptedDoubleOrdColumn,
153
+ EncryptedDoubleOrdOreColumn,
154
+ EncryptedIntegerColumn,
155
+ EncryptedIntegerEqColumn,
156
+ EncryptedIntegerOrdColumn,
157
+ EncryptedIntegerOrdOreColumn,
158
+ EncryptedJsonColumn,
159
+ EncryptedNumericColumn,
160
+ EncryptedNumericEqColumn,
161
+ EncryptedNumericOrdColumn,
162
+ EncryptedNumericOrdOreColumn,
163
+ EncryptedRealColumn,
164
+ EncryptedRealEqColumn,
165
+ EncryptedRealOrdColumn,
166
+ EncryptedRealOrdOreColumn,
167
+ EncryptedSmallintColumn,
168
+ EncryptedSmallintEqColumn,
169
+ EncryptedSmallintOrdColumn,
170
+ EncryptedSmallintOrdOreColumn,
171
+ EncryptedTable,
172
+ EncryptedTextColumn,
173
+ EncryptedTextEqColumn,
174
+ EncryptedTextMatchColumn,
175
+ EncryptedTextOrdColumn,
176
+ EncryptedTextOrdOreColumn,
177
+ EncryptedTextSearchColumn,
178
+ EncryptedTimestampColumn,
179
+ EncryptedTimestampEqColumn,
180
+ EncryptedTimestampOrdColumn,
181
+ EncryptedTimestampOrdOreColumn,
182
+ EncryptionV3,
183
+ TEXT_SEARCH_EQL_TYPE,
184
+ buildEncryptConfig,
185
+ encryptedTable,
186
+ typedClient,
187
+ types
188
+ };
189
+ //# 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 { DATE_LIKE_CASTS } from '@/eql/v3/columns'\nimport { type EncryptionError, EncryptionErrorTypes } from '@/errors'\nimport type { LockContextInput } from '@/identity'\nimport type {\n BulkDecryptPayload,\n BulkEncryptPayload,\n ClientConfig,\n Encrypted,\n EncryptedReturnType,\n EncryptOptions,\n ScalarQueryTerm,\n} from '@/types'\nimport {\n type BatchEncryptQueryOperation,\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 /**\n * Batch form: encrypt many query terms in one crossing. Mirrors the nominal\n * {@link EncryptionClient} overload — the per-term columns are heterogeneous,\n * so the terms are the base {@link ScalarQueryTerm} rather than a per-column\n * narrowed type. Consumed by the Drizzle `inArray`/`notInArray` operators.\n */\n encryptQuery(terms: readonly ScalarQueryTerm[]): BatchEncryptQueryOperation\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: only date-like casts need per-row reconstruction. `bigint` (int8)\n * needs none — protect-ffi 0.28 returns a native JS `bigint` on decrypt\n * (and bounds-checks/encodes it on encrypt), so those columns pass through\n * unchanged, exactly like `string`/`number`/`boolean`.\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-like columns need per-row work; resolve them up front.\n const dateProperties = Object.entries(propToDb)\n .filter(([, dbName]) => {\n const castAs = columns[dbName]?.cast_as\n // Date-like casts share one source of truth with the type-level\n // reconstruction (`PlaintextFromKind`) — see `DATE_LIKE_CASTS`.\n return (DATE_LIKE_CASTS as readonly string[]).includes(castAs as string)\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 // Precompute one row reconstructor per schema table at construction. This runs\n // each table's `build()` — which throws on duplicate DB column names — ONCE,\n // here, off the Result-returning decrypt path. `decryptModel`/\n // `bulkDecryptModels` therefore never call `build()` (whose throw would surface\n // as a promise rejection and break their `Promise<Result<…>>` contract) and no\n // longer rebuild the row-invariant config on every call.\n // Keyed by `tableName`, not table object identity: `AnyV3Table` is\n // structurally typed, so a table re-imported from another module (or rebuilt\n // after an HMR reload) satisfies `Table extends S[number]` yet is a different\n // object. Identity keying would fail those valid calls. `tableName` is the\n // semantic identity the FFI encrypt config and `build()` already key on.\n const reconstructors = new Map<\n string,\n (row: Record<string, unknown>) => Record<string, unknown>\n >()\n for (const table of schemas) {\n reconstructors.set(table.tableName, rowReconstructor(table))\n }\n\n // A table not among the schemas this client was initialized with has no\n // precomputed reconstructor. Return a Result failure rather than building one\n // inline, which could throw and reject the Result-shaped decrypt promise.\n const unknownTableFailure: { failure: EncryptionError } = {\n failure: {\n type: EncryptionErrorTypes.DecryptionError,\n message:\n '[eql/v3]: decryptModel received a table this client was not initialized with — pass a table given to EncryptionV3/typedClient',\n },\n }\n\n // Overloaded so the implementation is checked against BOTH forms directly —\n // no whole-value cast. The two public signatures mirror the interface member;\n // the hidden implementation signature is broad and forwards to the nominal\n // client (which routes to the batch operation when no `opts` are supplied).\n // Only the forwarded args are `as never`, exactly as the sibling wrappers\n // below: one forwarding body cannot re-derive the nominal client's per-column\n // signatures.\n function 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 function encryptQuery(\n terms: readonly ScalarQueryTerm[],\n ): BatchEncryptQueryOperation\n function encryptQuery(\n plaintextOrTerms: unknown,\n opts?: unknown,\n ): EncryptQueryOperation | BatchEncryptQueryOperation {\n return client.encryptQuery(plaintextOrTerms as never, opts as never)\n }\n\n return {\n encrypt: (plaintext, opts) =>\n client.encrypt(plaintext as never, opts as never),\n encryptQuery,\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 reconstruct = reconstructors.get(table.tableName)\n if (!reconstruct) return unknownTableFailure as never\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: reconstruct(result.data) } as never\n },\n bulkDecryptModels: async (input, table, lockContext) => {\n const reconstruct = reconstructors.get(table.tableName)\n if (!reconstruct) return unknownTableFailure as never\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 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 * @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 // Force the v3 EQL wire format. protect-ffi's newClient defaults to\n // eqlVersion 2; a v2-mode client cannot resolve v3 concrete-type columns\n // and fails every encrypt with \"Cannot convert undefined or null to\n // object\". This is a v3-only invariant, so it overrides any user value.\n config: { ...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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiJA,SAAS,iBACP,OAC2D;AAG3D,QAAM,EAAE,QAAQ,IAAI,MAAM,MAAM;AAChC,QAAM,WAAW,MAAM,kBAAkB;AAEzC,QAAM,iBAAiB,OAAO,QAAQ,QAAQ,EAC3C,OAAO,CAAC,CAAC,EAAE,MAAM,MAAM;AACtB,UAAM,SAAS,QAAQ,MAAM,GAAG;AAGhC,WAAQ,gBAAsC,SAAS,MAAgB;AAAA,EACzE,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,SACuB;AAY1B,QAAM,iBAAiB,oBAAI,IAGzB;AACF,aAAW,SAAS,SAAS;AAC3B,mBAAe,IAAI,MAAM,WAAW,iBAAiB,KAAK,CAAC;AAAA,EAC7D;AAKA,QAAM,sBAAoD;AAAA,IACxD,SAAS;AAAA,MACP,MAAM,qBAAqB;AAAA,MAC3B,SACE;AAAA,IACJ;AAAA,EACF;AAyBA,WAAS,aACP,kBACA,MACoD;AACpD,WAAO,OAAO,aAAa,kBAA2B,IAAa;AAAA,EACrE;AAEA,SAAO;AAAA,IACL,SAAS,CAAC,WAAW,SACnB,OAAO,QAAQ,WAAoB,IAAa;AAAA,IAClD;AAAA,IACA,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,cAAc,eAAe,IAAI,MAAM,SAAS;AACtD,UAAI,CAAC,YAAa,QAAO;AACzB,YAAM,KAAK,OAAO,aAAa,KAAc;AAC7C,YAAM,SAAS,OAAO,cAAc,GAAG,gBAAgB,WAAW,IAAI;AACtE,UAAI,OAAO,QAAS,QAAO;AAC3B,aAAO,EAAE,MAAM,YAAY,OAAO,IAAI,EAAE;AAAA,IAC1C;AAAA,IACA,mBAAmB,OAAO,OAAO,OAAO,gBAAgB;AACtD,YAAM,cAAc,eAAe,IAAI,MAAM,SAAS;AACtD,UAAI,CAAC,YAAa,QAAO;AACzB,YAAM,KAAK,OAAO,kBAAkB,KAAc;AAClD,YAAM,SAAS,OAAO,cAAc,GAAG,gBAAgB,WAAW,IAAI;AACtE,UAAI,OAAO,QAAS,QAAO;AAC3B,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;AAiBA,eAAsB,aAEpB,QAGoC;AACpC,QAAM,SAAS,MAAM,WAAW;AAAA,IAC9B,SAAS,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAOhB,QAAQ,EAAE,GAAG,OAAO,QAAQ,YAAY,EAAE;AAAA,EAC5C,CAAC;AACD,SAAO,YAAY,QAAQ,GAAG,OAAO,OAAO;AAC9C;","names":[]}