@arkiv-network/sdk 0.8.0-advanced.2 → 0.8.0-dev.2

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 (178) hide show
  1. package/README.md +0 -42
  2. package/dist/attr/index.cjs +33 -34
  3. package/dist/attr/index.d.cts +1 -1
  4. package/dist/attr/index.d.ts +1 -2
  5. package/dist/attr/index.js +1 -2
  6. package/dist/{attributes-Df9IsCVs.cjs → attr-BXTkpnoc.cjs} +13 -3
  7. package/dist/{attributes-BhY5DwJp.js → attr-tmyREHtw.js} +14 -4
  8. package/dist/attr-tmyREHtw.js.map +1 -0
  9. package/dist/chains/index.cjs +1 -1
  10. package/dist/chains/index.d.cts +3 -0
  11. package/dist/chains/index.d.cts.map +1 -1
  12. package/dist/chains/index.d.ts +3 -0
  13. package/dist/chains/index.d.ts.map +1 -1
  14. package/dist/chains/index.js +1 -1
  15. package/dist/{chains-BYRTTipa.cjs → chains-BfNQliHU.cjs} +3 -0
  16. package/dist/{chains-BJrZs6sG.js → chains-Du8tql7I.js} +4 -1
  17. package/dist/chains-Du8tql7I.js.map +1 -0
  18. package/dist/{arkivTransactions-NtGD6uk5.d.ts → changeOwnership-B0ar96ub.d.ts} +74 -123
  19. package/dist/changeOwnership-B0ar96ub.d.ts.map +1 -0
  20. package/dist/{arkivTransactions-D74gERHG.d.cts → changeOwnership-BofkLnXJ.d.cts} +74 -123
  21. package/dist/changeOwnership-BofkLnXJ.d.cts.map +1 -0
  22. package/dist/entity/index.cjs +9 -9
  23. package/dist/entity/index.d.cts +3 -3
  24. package/dist/entity/index.d.ts +4 -5
  25. package/dist/entity/index.js +5 -6
  26. package/dist/{entity-BYQR1uoe.js → entity-BIp_df9u.js} +1 -1
  27. package/dist/{entity-BYQR1uoe.js.map → entity-BIp_df9u.js.map} +1 -1
  28. package/dist/{key-D1Bh7MF0.js → entity-CniBgBSd.js} +31 -19
  29. package/dist/entity-CniBgBSd.js.map +1 -0
  30. package/dist/{key-WKhXnXuU.cjs → entity-DJ0Gml9c.cjs} +37 -19
  31. package/dist/{errors-LTe7bOYS.js → errors-D2E1GRjw.js} +2 -2
  32. package/dist/errors-D2E1GRjw.js.map +1 -0
  33. package/dist/{errors-BVbjKVMN.cjs → errors-DhV00966.cjs} +1 -1
  34. package/dist/{expiry-nDbCgZX4.d.ts → expiry-BxOlvVWC.d.ts} +1 -1
  35. package/dist/{expiry-nDbCgZX4.d.ts.map → expiry-BxOlvVWC.d.ts.map} +1 -1
  36. package/dist/{expiry-BELY2Kpw.cjs → expiry-CG9GhVXv.cjs} +1 -1
  37. package/dist/{expiry-BjpxZZQU.js → expiry-Cgdb_dbq.js} +2 -2
  38. package/dist/expiry-Cgdb_dbq.js.map +1 -0
  39. package/dist/expiry-DRV29F1r.d.cts.map +1 -1
  40. package/dist/{flags-CRjPpoh3.d.cts → flags-0Vl5rrHq.d.cts} +1 -1
  41. package/dist/{flags-CRjPpoh3.d.cts.map → flags-0Vl5rrHq.d.cts.map} +1 -1
  42. package/dist/{flags-kr276q6i.cjs → flags-DCD26uhe.cjs} +1 -1
  43. package/dist/{flags-DFBs2J94.js → flags-DUT2gHEU.js} +2 -2
  44. package/dist/{flags-DFBs2J94.js.map → flags-DUT2gHEU.js.map} +1 -1
  45. package/dist/{flags-5dTNRnow.d.ts → flags-wmcMoAnN.d.ts} +1 -1
  46. package/dist/{flags-5dTNRnow.d.ts.map → flags-wmcMoAnN.d.ts.map} +1 -1
  47. package/dist/{index-fX_XyqLp.d.ts → index-BGp2plHs.d.cts} +15 -13
  48. package/dist/index-BGp2plHs.d.cts.map +1 -0
  49. package/dist/{index-DHDud2hC.d.ts → index-BKB875Um.d.ts} +5 -7
  50. package/dist/{index-DHDud2hC.d.ts.map → index-BKB875Um.d.ts.map} +1 -1
  51. package/dist/{index-DvYvrkdk.d.ts → index-CIcHPx2j.d.cts} +110 -6
  52. package/dist/index-CIcHPx2j.d.cts.map +1 -0
  53. package/dist/{index-CV5zCdpa.d.cts → index-Cd2aaWme.d.ts} +13 -6
  54. package/dist/index-Cd2aaWme.d.ts.map +1 -0
  55. package/dist/{index-CA4V7Pdh.d.cts → index-ezMZ2-JH.d.ts} +15 -13
  56. package/dist/index-ezMZ2-JH.d.ts.map +1 -0
  57. package/dist/{index-BF7Mq9Is.d.cts → index-rINthNuU.d.cts} +5 -7
  58. package/dist/{index-BF7Mq9Is.d.cts.map → index-rINthNuU.d.cts.map} +1 -1
  59. package/dist/index.cjs +433 -139
  60. package/dist/index.d.cts +58 -164
  61. package/dist/index.d.cts.map +1 -1
  62. package/dist/index.d.ts +59 -166
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +376 -75
  65. package/dist/index.js.map +1 -1
  66. package/dist/{payload-CcUj85ys.d.ts → payload-CGvVPZQX.d.ts} +61 -2
  67. package/dist/payload-CGvVPZQX.d.ts.map +1 -0
  68. package/dist/{payload-Bz6651ax.js → payload-DE7wMztL.js} +28 -3
  69. package/dist/payload-DE7wMztL.js.map +1 -0
  70. package/dist/{payload-BNoud2KZ.d.cts → payload-Dfu30njp.d.cts} +60 -1
  71. package/dist/payload-Dfu30njp.d.cts.map +1 -0
  72. package/dist/{payload-KC14SDlN.cjs → payload-DqFweqiO.cjs} +27 -2
  73. package/dist/query/index.cjs +5 -7
  74. package/dist/query/index.d.cts +4 -4
  75. package/dist/query/index.d.ts +4 -5
  76. package/dist/query/index.js +5 -7
  77. package/dist/{queryBuilder-DM6AWCBa.js → queryBuilder-wvA8sn--.js} +169 -23
  78. package/dist/queryBuilder-wvA8sn--.js.map +1 -0
  79. package/dist/{queryBuilder-DbUMEZln.cjs → queryBuilder-zHGhDmaG.cjs} +215 -33
  80. package/dist/{selection-DPg0uyJf.d.cts → selection-Bv8_o-7i.d.cts} +76 -68
  81. package/dist/selection-Bv8_o-7i.d.cts.map +1 -0
  82. package/dist/{selection-C4UhsMOO.d.ts → selection-ox7zdtVm.d.ts} +76 -69
  83. package/dist/selection-ox7zdtVm.d.ts.map +1 -0
  84. package/dist/types/index.cjs +2 -2
  85. package/dist/types/index.d.cts +6 -6
  86. package/dist/types/index.d.ts +7 -8
  87. package/dist/types/index.js +2 -2
  88. package/dist/utils/index.cjs +3 -3
  89. package/dist/utils/index.d.cts +1 -1
  90. package/dist/utils/index.d.ts +2 -2
  91. package/dist/utils/index.js +3 -3
  92. package/package.json +1 -5
  93. package/src/actions/public/getEntity.ts +1 -0
  94. package/src/actions/public/predictEntityKeys.test.ts +17 -1
  95. package/src/actions/public/predictEntityKeys.ts +28 -14
  96. package/src/actions/public/query.ts +1 -5
  97. package/src/actions/wallet/createEntity.ts +7 -6
  98. package/src/actions/wallet/{mutateEntities.test.ts → executeBatch.test.ts} +7 -7
  99. package/src/actions/wallet/{mutateEntities.ts → executeBatch.ts} +26 -11
  100. package/src/actions/wallet/extendEntity.ts +1 -0
  101. package/src/actions/wallet/patchEntity.ts +3 -3
  102. package/src/attr/attributes.ts +8 -2
  103. package/src/attr/errors.ts +2 -2
  104. package/src/attr/types.ts +3 -3
  105. package/src/attr/values.ts +5 -1
  106. package/src/chains/localhost.ts +3 -0
  107. package/src/clients/createPublicClient.test.ts +1 -1
  108. package/src/clients/createPublicClient.ts +5 -5
  109. package/src/clients/createWalletClient.test.ts +2 -2
  110. package/src/clients/createWalletClient.ts +3 -5
  111. package/src/clients/decorators/arkivPublic.ts +13 -24
  112. package/src/clients/decorators/arkivWallet.ts +40 -47
  113. package/src/entity/create.test.ts +20 -1
  114. package/src/entity/errors.ts +4 -3
  115. package/src/entity/expiry.ts +1 -0
  116. package/src/entity/index.ts +2 -2
  117. package/src/entity/key.ts +23 -3
  118. package/src/entity/operations.ts +1 -0
  119. package/src/index.ts +0 -13
  120. package/src/query/engine.ts +0 -11
  121. package/src/query/errors.ts +1 -1
  122. package/src/query/expression.ts +14 -7
  123. package/src/query/queryBuilder.test.ts +1 -21
  124. package/src/query/queryBuilder.ts +3 -10
  125. package/src/types/index.ts +4 -4
  126. package/src/types/rpcSchema.ts +1 -0
  127. package/src/types/txParams.ts +8 -0
  128. package/src/utils/arkivTransactions.test.ts +7 -1
  129. package/src/utils/arkivTransactions.ts +114 -254
  130. package/src/utils/expirationTime.ts +39 -0
  131. package/src/utils/payload.ts +25 -0
  132. package/dist/actions/advanced/index.cjs +0 -13
  133. package/dist/actions/advanced/index.d.cts +0 -8
  134. package/dist/actions/advanced/index.d.ts +0 -9
  135. package/dist/actions/advanced/index.js +0 -9
  136. package/dist/advanced-8ZPTmmaN.js +0 -598
  137. package/dist/advanced-8ZPTmmaN.js.map +0 -1
  138. package/dist/advanced-fPImL6lW.cjs +0 -656
  139. package/dist/arkivTransactions-D74gERHG.d.cts.map +0 -1
  140. package/dist/arkivTransactions-NtGD6uk5.d.ts.map +0 -1
  141. package/dist/attributes-BhY5DwJp.js.map +0 -1
  142. package/dist/chains-BJrZs6sG.js.map +0 -1
  143. package/dist/codec-Car3KkFF.d.ts +0 -102
  144. package/dist/codec-Car3KkFF.d.ts.map +0 -1
  145. package/dist/entity-B7G8q_Eo.cjs +0 -0
  146. package/dist/entity-CD_qFF2M.js +0 -0
  147. package/dist/errors-LTe7bOYS.js.map +0 -1
  148. package/dist/expiry-BjpxZZQU.js.map +0 -1
  149. package/dist/index-B5j76711.d.ts +0 -184
  150. package/dist/index-B5j76711.d.ts.map +0 -1
  151. package/dist/index-CA4V7Pdh.d.cts.map +0 -1
  152. package/dist/index-CV5zCdpa.d.cts.map +0 -1
  153. package/dist/index-DvYvrkdk.d.ts.map +0 -1
  154. package/dist/index-EeUO0nnJ.d.cts +0 -184
  155. package/dist/index-EeUO0nnJ.d.cts.map +0 -1
  156. package/dist/index-fX_XyqLp.d.ts.map +0 -1
  157. package/dist/key-D1Bh7MF0.js.map +0 -1
  158. package/dist/logger-CVpvU8ik.js +0 -153
  159. package/dist/logger-CVpvU8ik.js.map +0 -1
  160. package/dist/logger-Cr15lPAQ.cjs +0 -188
  161. package/dist/payload-BNoud2KZ.d.cts.map +0 -1
  162. package/dist/payload-Bz6651ax.js.map +0 -1
  163. package/dist/payload-CcUj85ys.d.ts.map +0 -1
  164. package/dist/queryBuilder-DM6AWCBa.js.map +0 -1
  165. package/dist/selection-C4UhsMOO.d.ts.map +0 -1
  166. package/dist/selection-DPg0uyJf.d.cts.map +0 -1
  167. package/dist/types-Bu_ZwMbZ.js +0 -0
  168. package/dist/types-NRqymi6S.cjs +0 -0
  169. package/src/actions/advanced/advanced.test.ts +0 -258
  170. package/src/actions/advanced/buildMutation.ts +0 -104
  171. package/src/actions/advanced/getMutationResult.ts +0 -112
  172. package/src/actions/advanced/index.ts +0 -21
  173. package/src/actions/advanced/pingTransaction.ts +0 -43
  174. package/src/actions/advanced/sendMutation.ts +0 -59
  175. package/src/clients/decorators/arkivAdvanced.ts +0 -144
  176. /package/dist/{entity-B00Li04j.cjs → entity-B0t6sN7F.cjs} +0 -0
  177. /package/dist/{attr-DlmErkvR.cjs → types-Bx1EKe0v.js} +0 -0
  178. /package/dist/{attr-GcQKatub.js → types-CKPddlfS.cjs} +0 -0
@@ -1,184 +0,0 @@
1
- import { j as ArkivClient } from "./selection-DPg0uyJf.cjs";
2
- import { f as Operation } from "./index-CA4V7Pdh.cjs";
3
- import { c as TxParams, t as EntityMutationOps } from "./arkivTransactions-D74gERHG.cjs";
4
- import { Address, Hash, Hex, TransactionReceipt } from "viem";
5
-
6
- //#region src/actions/advanced/buildMutation.d.ts
7
- /** Options for the advanced-path builders ({@link buildMutation}, {@link sendMutation}). */
8
- type BuildMutationOptions = {
9
- /**
10
- * The chain head to resolve relative expiries against.
11
- *
12
- * Pass a block number you already hold — from a previous call, `getBlockTiming()`, or your own
13
- * tracking — and the build spends no RPC call at all. Without it, one `eth_blockNumber` is made,
14
- * and only when the batch actually needs the head (a relative lifetime or a `Date` deadline);
15
- * purely absolute `atBlock(n)` expiries never trigger it.
16
- *
17
- * Supplying it also buys back a check: absolute expiries are validated against it, so an
18
- * `atBlock(n)` already in the past throws {@link InvalidExpiryError} locally instead of
19
- * reverting on-chain. When the head is neither supplied nor fetched, that dead-on-arrival
20
- * check is skipped — the one local validation of the everyday path this path trades away.
21
- */
22
- currentBlock?: bigint;
23
- };
24
- /** What {@link buildMutation} hands back: the batch in every form a sender might want. */
25
- type BuildMutationReturnType = {
26
- /** The encoded batch, in engine order, for `writeContract`-style sends. */
27
- operations: Operation[];
28
- /** The Arkiv engine address the transaction must be sent to. */
29
- to: Address;
30
- /**
31
- * The full `execute(operations)` calldata. Sign a transaction carrying it offline (with your own
32
- * nonce, gas and fees) and the whole mutation costs exactly one `eth_sendRawTransaction`.
33
- */
34
- data: Hex;
35
- /**
36
- * How many operations of each kind went into the batch — which is how many events of each kind a
37
- * successful transaction emits, in batch order, for cross-checking a decoded result.
38
- */
39
- expected: {
40
- creates: number;
41
- patches: number;
42
- deletes: number;
43
- extensions: number;
44
- ownershipChanges: number;
45
- };
46
- };
47
- /**
48
- * Encodes a mutation batch without sending anything.
49
- *
50
- * This is the first step of the advanced path: it performs only local validation and encoding, so
51
- * it costs **zero RPC calls** when `options.currentBlock` is provided (or no expiry is relative),
52
- * and at most one `eth_blockNumber` otherwise. Send the result however you like: pass `operations`
53
- * to `writeContract`, or sign `{ to, data }` offline and push it with `eth_sendRawTransaction`.
54
- *
55
- * One check rides on knowing the head: an absolute `atBlock(n)` already in the past is rejected
56
- * locally only when the head is supplied or was fetched anyway. With neither, a dead-on-arrival
57
- * expiry encodes cleanly and the engine reverts it on-chain — see
58
- * {@link BuildMutationOptions.currentBlock}.
59
- *
60
- * @throws {InvalidExpiryError} If an expiry exceeds a protocol bound.
61
- * @throws {InvalidValueError} If an attribute value does not fit the type it names.
62
- * @throws {EmptyPatchError} If a patch has nothing to apply.
63
- */
64
- declare function buildMutation(client: ArkivClient, data: EntityMutationOps, options?: BuildMutationOptions): Promise<BuildMutationReturnType>;
65
- //#endregion
66
- //#region src/actions/advanced/getMutationResult.d.ts
67
- /**
68
- * A mined mutation, decoded from its receipt alone.
69
- *
70
- * Everything here comes out of the events the batch emitted, so no request context is needed to
71
- * read it — a process that holds nothing but the transaction hash gets the full picture. Arrays
72
- * are in batch order, which is the order the operations were applied in.
73
- */
74
- type MutationResult = {
75
- /** `success` means the whole batch applied; `reverted` means none of it did (arrays are empty). */
76
- status: "success" | "reverted";
77
- /** The transaction hash. */
78
- txHash: Hash;
79
- /** The block the transaction landed in. */
80
- blockNumber: bigint;
81
- /** The keys the engine minted for the created entities, in batch order. */
82
- createdEntities: Hex[];
83
- /** The block each created entity expires at, as the engine recorded it, in the same order. */
84
- createdExpiries: bigint[];
85
- /** The keys of the patched entities. */
86
- patchedEntities: Hex[];
87
- /** The keys of the deleted entities. */
88
- deletedEntities: Hex[];
89
- /** The keys of the extended entities. */
90
- extendedEntities: Hex[];
91
- /** The block each extended entity now expires at, in the same order. */
92
- extendedExpiries: bigint[];
93
- /** The keys of the entities handed to a new owner. */
94
- ownershipChanges: Hex[];
95
- /** The raw receipt, so nothing the chain said is lost. */
96
- receipt: TransactionReceipt;
97
- };
98
- /** Return type for {@link getMutationResult}: the decoded result, or still pending. */
99
- type GetMutationResultReturnType = MutationResult | {
100
- status: "pending";
101
- };
102
- /**
103
- * Decodes a receipt you already hold into a {@link MutationResult}. **Zero RPC calls.**
104
- *
105
- * The pure tail of the advanced path: if a receipt reached you some other way — your own
106
- * `waitForTransactionReceipt`, a webhook, a block watcher — this turns it into entity keys and
107
- * expiries without touching the network. Lenient by design: it reports what the events say,
108
- * without counting them against a request it never saw.
109
- */
110
- declare function decodeMutationResult(receipt: TransactionReceipt): MutationResult;
111
- /**
112
- * Fetches a transaction's receipt — once — and decodes what the mutation did.
113
- *
114
- * Exactly one `eth_getTransactionReceipt`, like `pingTransaction`, but the answer carries the
115
- * decoded entity events as well: created keys, recorded expiries, and the keys of everything
116
- * patched, deleted, extended or handed over. A transaction that is not mined yet comes back as
117
- * `{ status: "pending" }` — check `status` before reading the rest.
118
- *
119
- * No revert diagnosis is run: a `reverted` result reports the fact and the raw receipt, and
120
- * spending a `simulateContract` on the why is your call, not the SDK's.
121
- */
122
- declare function getMutationResult(client: ArkivClient, txHash: Hash): Promise<GetMutationResultReturnType>;
123
- //#endregion
124
- //#region src/actions/advanced/pingTransaction.d.ts
125
- /** Return type for {@link pingTransaction}. */
126
- type PingTransactionReturnType = {
127
- /** Not mined yet (or unknown to this node). Ping again later. */
128
- status: "pending";
129
- blockNumber?: undefined;
130
- } | {
131
- /** Mined. `success` means the whole batch applied; `reverted` means none of it did. */
132
- status: "success" | "reverted";
133
- /** The block the transaction landed in. */
134
- blockNumber: bigint;
135
- };
136
- /**
137
- * Asks the chain — once — whether a transaction has landed.
138
- *
139
- * Exactly one `eth_getTransactionReceipt`, never a poll: a transaction that is not mined yet comes
140
- * back as `{ status: "pending" }` rather than being waited on. This is the "ping" of the advanced
141
- * path — you own the schedule, the SDK owns nothing.
142
- *
143
- * When it reports `success` and you need the created keys or recorded expiries, spend the next
144
- * call on `getMutationResult` — or none at all, if you predicted the keys up front with
145
- * `predictEntityKeys`.
146
- */
147
- declare function pingTransaction(client: ArkivClient, txHash: Hash): Promise<PingTransactionReturnType>;
148
- //#endregion
149
- //#region src/actions/advanced/sendMutation.d.ts
150
- /** Options for {@link sendMutation}. */
151
- type SendMutationOptions = BuildMutationOptions & {
152
- /**
153
- * Transaction parameters. Supply `nonce`, `gas` and the fee fields and viem has nothing left to
154
- * look up — the send collapses to a single `eth_sendRawTransaction`.
155
- */
156
- txParams?: TxParams;
157
- };
158
- /** Return type for {@link sendMutation}. */
159
- type SendMutationReturnType = {
160
- /** The transaction hash. Poll it with `pingTransaction` / fetch it with `getMutationResult`. */
161
- txHash: Hash;
162
- /** The per-kind operation counts of the batch that was sent, for cross-checking the result. */
163
- expected: BuildMutationReturnType["expected"];
164
- };
165
- /**
166
- * Signs and sends a mutation batch, returning as soon as the transaction is submitted.
167
- *
168
- * The fire-and-forget half of the advanced path. Unlike `mutateEntities`, this does **not** wait
169
- * for a receipt, does not poll, and runs no revert diagnosis — it spends only what submitting
170
- * costs. With `options.currentBlock` and full `txParams` (nonce, gas, fees) that is exactly one
171
- * RPC call; each omitted piece adds only the lookup viem needs to fill it.
172
- *
173
- * Follow up separately, on your own schedule:
174
- * - `pingTransaction(txHash)` — one `eth_getTransactionReceipt`, tells you pending/success/reverted.
175
- * - `getMutationResult(txHash)` — the same single call, plus the decoded entity keys and expiries.
176
- *
177
- * @throws {EntityMutationError} If the node rejects the submission (the batch never made it into
178
- * the mempool) — in engine terms when the rejection decodes, with the node's message otherwise.
179
- * Anything after that — inclusion, success — is yours to check.
180
- */
181
- declare function sendMutation(client: ArkivClient, data: EntityMutationOps, options?: SendMutationOptions): Promise<SendMutationReturnType>;
182
- //#endregion
183
- export { pingTransaction as a, decodeMutationResult as c, BuildMutationReturnType as d, buildMutation as f, PingTransactionReturnType as i, getMutationResult as l, SendMutationReturnType as n, GetMutationResultReturnType as o, sendMutation as r, MutationResult as s, SendMutationOptions as t, BuildMutationOptions as u };
184
- //# sourceMappingURL=index-EeUO0nnJ.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-EeUO0nnJ.d.cts","names":[],"sources":["../src/actions/advanced/buildMutation.ts","../src/actions/advanced/getMutationResult.ts","../src/actions/advanced/pingTransaction.ts","../src/actions/advanced/sendMutation.ts"],"sourcesContent":[],"mappings":";;;;;;;KAeY,oBAAA;EAAA;AAkBZ;;;;;AAwCA;;;;;;;;;;AC1DY,KDkBA,uBAAA,GClBc;EAIhB;EAIS,UAAA,EDYL,SCZK,EAAA;EAIA;EAEA,EAAA,EDQb,OCRa;EAEC;;;;EAUR,IAAA,EDCJ,GCDI;EAUI;AA4BhB;;;EAGW,QAAA,EAAA;IAAR,OAAA,EAAA,MAAA;IAAO,OAAA,EAAA,MAAA;;;;EC1EE,CAAA;AAwBZ,CAAA;;;;;;;;;AClBA;AASA;AAuBA;;;;;;;iBH2BsB,aAAA,SACZ,mBACF,6BACG,uBACR,QAAQ;;;;;;;AA9DX;AAkBA;;AAIM,KCtBM,cAAA,GDsBN;EAKE;EAAG,MAAA,EAAA,SAAA,GAAA,UAAA;EA+BW;EACZ,MAAA,ECvDA,IDuDA;EACF;EACG,WAAA,EAAA,MAAA;EACA;EAAR,eAAA,ECtDgB,GDsDhB,EAAA;EAAO;;;mBClDS;EAZP;EAIF,eAAA,EAUS,GAVT,EAAA;EAIS;EAIA,gBAAA,EAIC,GAJD,EAAA;EAEA;EAEC,gBAAA,EAAA,MAAA,EAAA;EAIA;EAET,gBAAA,EAFS,GAET,EAAA;EAAkB;EAIjB,OAAA,EAJD,kBAIC;AAUZ,CAAA;AA4BA;AACU,KAvCE,2BAAA,GAA8B,cAuChC,GAAA;EACA,MAAA,EAAA,SAAA;CACC;;;;;;AC1EX;AAwBA;;AAEU,iBDiBM,oBAAA,CCjBN,OAAA,EDiBoC,kBCjBpC,CAAA,EDiByD,cCjBzD;;;;;;;ACpBV;AASA;AAuBA;;;AAGW,iBF8BW,iBAAA,CE9BX,MAAA,EF+BD,WE/BC,EAAA,MAAA,EFgCD,IEhCC,CAAA,EFiCR,OEjCQ,CFiCA,2BEjCA,CAAA;;;;KDzCC,yBAAA;;;EFOA,WAAA,CAAA,EAAA,SAAoB;AAkBhC,CAAA,GAAY;EAEE;EAER,MAAA,EAAA,SAAA,GAAA,UAAA;EAKE;EAAG,WAAA,EAAA,MAAA;AA+BX,CAAA;;;;;;;;;;AC1DA;;AAQmB,iBCSG,eAAA,CDTH,MAAA,ECUT,WDVS,EAAA,MAAA,ECWT,IDXS,CAAA,ECYhB,ODZgB,CCYR,yBDZQ,CAAA;;;;ADRP,KGDA,mBAAA,GAAsB,oBHCF,GAAA;EAkBpB;;;;EASD,QAAA,CAAA,EGvBE,QHuBF;AA+BX,CAAA;;AAEQ,KGpDI,sBAAA,GHoDJ;EACG;EACA,MAAA,EGpDD,IHoDC;EAAR;EAAO,QAAA,EGlDE,uBHkDF,CAAA,UAAA,CAAA;;;;AC9DV;;;;;;;;;AA0BA;AAUA;AA4BA;;;AAGW,iBEpCW,YAAA,CFoCX,MAAA,EEnCD,WFmCC,EAAA,IAAA,EElCH,iBFkCG,EAAA,OAAA,CAAA,EEjCA,mBFiCA,CAAA,EEhCR,OFgCQ,CEhCA,sBFgCA,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-fX_XyqLp.d.ts","names":[],"sources":["../src/entity/operations.ts","../src/entity/errors.ts","../src/entity/events.ts","../src/entity/key.ts","../src/entity/params.ts"],"sourcesContent":[],"mappings":";;;;;KAgDY,SAAA;;iBAEK;;;;;cCjDJ,kBAAA,SAA2B,KAAA;;AD+CxC;;cCvCa,yBAAA,SAAkC,KAAA;;AAR/C;AAQA;AAQa,cAAA,gBAAA,SAAyB,KAAA,CAAK;EAW9B,WAAA,CAAA,IAAA,EAAA,MAAoB;;;cAApB,mBAAA,SAA4B,KAAA;ECtB5B,WAAA,CAAA;AASb;;;;;;AFiCA;cE1Ca;;;EDLA,SAAA,MAAA,EAAA,SAAmB,CAAA;IAQnB,SAAA,IAAA,EAAA,SAA0B;IAQ1B,SAAA,IAAA,EAAiB,WAAA;IAWjB,SAAA,OAAA,EAAoB,IAAA;;;;ICtBpB,SAAA,OAMX,EAAA,IAAA;EAGU,CAAA,EAAA;;;;ICVC,SAA0B,IAAA,EAAA,OAAA;IAWvB,SAAU,IAAA,EAAA,eAAA;EA2BV,CAAA,CAAA;CACd,EAAA;EACA,SAAA,IAAA,EAAA,eAAA;EACA,SAAA,IAAA,EAAA,OAAA;EACA,SAAA,MAAA,EAAA,SAAA,CAAA;IAGO,SAAA,IAAA,EAAA,SAAA;IAUL,SAAA,IAAA,EAAA,WAAA;IAAG,SAAA,OAAA,EAAA,IAAA;;;;ICzDM,SAAA,OAA+B,EAAA,IAAA;EAG/B,CAAA,CAAA;AAQb,CAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KFCY,eAAA,WAA0B;;;;cCVzB;AH2Cb;;;;AC/CA;AAQA;AAQA;AAWA;;iBEZgB,UAAA,CAAA;ADDhB;;;;ACVA;AAWA;AA2BA;;AAEE,iBAFc,gBAAA,CAEd;EAAA,KAAA;EAAA,KAAA;EAAA,IAAA;EAAA;CAAA,EAAA;EACA;EACA,KAAA,EAGO,OAHP;EAGO;;;;;;EC/CI,IAAA,EAAA,MAAA;EAGA;EAQD,OAAA,EAAA,MAAA;ID8CR;;;;;;AHZQ,cI7CC,cJ+CO,EAAA,MAAA;;cI5CP;;EHLA,SAAA,KAAA,EAAA,CAAA;EAQA,SAAA,YAAA,EAAA,CAAA;EAQA,SAAA,iBAAiB,EAAA,CAAA;EAWjB,SAAA,MAAA,EAAA,CAAA;;KGdD,aAAA,WAAwB,4BAA4B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"key-D1Bh7MF0.js","names":[],"sources":["../src/entity/events.ts","../src/entity/key.ts"],"sourcesContent":["import { parseAbi } from \"viem\"\n\n/**\n * The events the engine emits: one per applied operation, in application order, so an off-chain\n * replica can replay a transaction operation by operation.\n */\nexport const ENTITY_EVENTS_ABI = parseAbi([\n \"event EntityCreated(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt, uint8 creationFlags)\",\n \"event EntityPatched(bytes32 indexed entityKey, address indexed owner)\",\n \"event ExpiryExtended(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt)\",\n \"event OwnershipTransferred(bytes32 indexed entityKey, address indexed previousOwner, address indexed newOwner)\",\n \"event EntityDeleted(bytes32 indexed entityKey, address indexed owner)\",\n])\n\n/** The name of each event in {@link ENTITY_EVENTS_ABI}. */\nexport type EntityEventName = (typeof ENTITY_EVENTS_ABI)[number][\"name\"]\n","import { type Address, encodePacked, type Hex, keccak256 } from \"viem\"\nimport { ARKIV_ADDRESS } from \"../consts\"\nimport { InvalidSaltError, NoRandomSourceError } from \"./errors\"\n\n/** The widest salt the `uint128` wire field carries. */\nexport const MAX_SALT = 2n ** 128n - 1n\n\n/**\n * A cryptographically random 128-bit salt — what {@link CreateEntityParameters.salt} defaults to.\n *\n * The salt exists for unpredictability, not uniqueness: the per-owner nonce already guarantees\n * distinct keys. Random bits mean only the creator can predict the key of an entity they are about\n * to create, so nobody else can reference or squat it in advance.\n *\n * @throws {NoRandomSourceError} If the runtime has no `crypto.getRandomValues`.\n */\nexport function randomSalt(): bigint {\n const source = globalThis.crypto\n if (typeof source?.getRandomValues !== \"function\") {\n throw new NoRandomSourceError()\n }\n const bytes = source.getRandomValues(new Uint8Array(16))\n let salt = 0n\n for (const byte of bytes) salt = (salt << 8n) | BigInt(byte)\n return salt\n}\n\n/** Validates a caller-supplied salt against the `uint128` wire field. */\nexport function validateSalt(salt: bigint): bigint {\n if (typeof salt !== \"bigint\" || salt < 0n || salt > MAX_SALT) {\n throw new InvalidSaltError(salt)\n }\n return salt\n}\n\n/**\n * The key an entity will be created with, derived exactly as the engine derives it:\n * `keccak256(domain ++ owner ++ nonce ++ salt)`.\n *\n * Deriving it client-side is what lets a batch compose: predict the key of a create, then have a\n * later operation in the same transaction reference it, or store it as a `key` attribute on a\n * sibling entity.\n */\nexport function predictEntityKey({\n owner,\n nonce,\n salt,\n chainId,\n}: {\n /** The account creating the entity. */\n owner: Address\n /**\n * The owner's entity-nonce at creation time. Each create in a batch consumes one, so the *n*th\n * create in a batch uses `nonce + n`.\n */\n nonce: bigint\n /** The salt the create will carry. */\n salt: bigint\n /** The chain the entity is being created on — half of the derivation domain. */\n chainId: number\n}): Hex {\n return keccak256(\n encodePacked(\n [\"uint256\", \"address\", \"address\", \"uint64\", \"uint128\"],\n [BigInt(chainId), ARKIV_ADDRESS, owner, nonce, validateSalt(salt)],\n ),\n )\n}\n"],"mappings":";;;;;;;;;AAMA,MAAa,oBAAoB,SAAS;CACxC;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;ACPF,MAAa,WAAW,MAAM,OAAO;;;;;;;;;;AAWrC,SAAgB,aAAqB;CACnC,MAAM,SAAS,WAAW;AAC1B,KAAI,OAAO,QAAQ,oBAAoB,WACrC,OAAM,IAAI,qBAAqB;CAEjC,MAAM,QAAQ,OAAO,gBAAgB,IAAI,WAAW,GAAG,CAAC;CACxD,IAAI,OAAO;AACX,MAAK,MAAM,QAAQ,MAAO,QAAQ,QAAQ,KAAM,OAAO,KAAK;AAC5D,QAAO;;;AAIT,SAAgB,aAAa,MAAsB;AACjD,KAAI,OAAO,SAAS,YAAY,OAAO,MAAM,OAAO,SAClD,OAAM,IAAI,iBAAiB,KAAK;AAElC,QAAO;;;;;;;;;;AAWT,SAAgB,iBAAiB,EAC/B,OACA,OACA,MACA,WAaM;AACN,QAAO,UACL,aACE;EAAC;EAAW;EAAW;EAAW;EAAU;EAAU,EACtD;EAAC,OAAO,QAAQ;EAAE;EAAe;EAAO;EAAO,aAAa,KAAK;EAAC,CACnE,CACF"}
@@ -1,153 +0,0 @@
1
- //#region src/errors.ts
2
- var EntityMutationError = class extends Error {
3
- constructor(message, options) {
4
- super(message, options);
5
- this.name = "EntityMutationError";
6
- }
7
- };
8
- var NoMoreResultsError = class extends Error {
9
- constructor() {
10
- super("No more results — the last page carried no cursor. Check hasNextPage() before next().");
11
- this.name = "NoMoreResultsError";
12
- }
13
- };
14
- var NoEntityFoundError = class extends Error {
15
- /** The key that matched nothing, when the lookup was by key. */
16
- entityKey;
17
- constructor(entityKey) {
18
- super(entityKey === void 0 ? "No entity found" : `No live entity with key ${entityKey}. It was never created, or it has been deleted or has expired.`);
19
- this.name = "NoEntityFoundError";
20
- this.entityKey = entityKey;
21
- }
22
- };
23
- var EmptyPatchError = class extends Error {
24
- entityKey;
25
- constructor(entityKey) {
26
- super(`The patch for entity ${entityKey} has nothing to apply. Pass "set" to write attributes, "unset" to remove them, or "payload"/"contentType" to replace the contents.`);
27
- this.name = "EmptyPatchError";
28
- this.entityKey = entityKey;
29
- }
30
- };
31
- var InvalidContentTypeError = class extends Error {
32
- constructor(contentType) {
33
- super(`Invalid content type "${contentType}". Must follow RFC 2045 MIME grammar and be lowercase only (e.g. "text/plain").`);
34
- this.name = "InvalidContentTypeError";
35
- }
36
- };
37
-
38
- //#endregion
39
- //#region src/utils/logger.ts
40
- const ROOT_NAMESPACE = "arkiv";
41
- function getDebugEnv() {
42
- if (typeof process !== "undefined") {
43
- const debugEnv = process?.env?.DEBUG;
44
- if (debugEnv) return debugEnv;
45
- }
46
- if (typeof globalThis !== "undefined" && "localStorage" in globalThis) try {
47
- return globalThis.localStorage?.getItem("DEBUG") || "";
48
- } catch {}
49
- return "";
50
- }
51
- function matchesPattern(namespace, pattern) {
52
- if (pattern === namespace) return true;
53
- if (pattern.endsWith("*")) {
54
- const prefix = pattern.slice(0, -1);
55
- return namespace.startsWith(prefix);
56
- }
57
- if (pattern.startsWith("-")) return !matchesPattern(namespace, pattern.slice(1));
58
- return false;
59
- }
60
- function isEnabled(namespace) {
61
- const debugEnv = getDebugEnv();
62
- if (!debugEnv) return false;
63
- const patterns = debugEnv.split(/[\s,]+/).filter((p) => p.length > 0);
64
- if (patterns.length === 0) return false;
65
- let enabled = false;
66
- for (const pattern of patterns) if (pattern.startsWith("-")) {
67
- if (matchesPattern(namespace, pattern)) return false;
68
- } else if (matchesPattern(namespace, pattern)) enabled = true;
69
- return enabled;
70
- }
71
- const enabledNamespaces = /* @__PURE__ */ new Set();
72
- const disabledNamespaces = /* @__PURE__ */ new Set();
73
- const COLOR_PALETTE = [
74
- "#0000FF",
75
- "#008000",
76
- "#FF0000",
77
- "#FF00FF",
78
- "#FFA500",
79
- "#800080",
80
- "#00CED1",
81
- "#FF1493",
82
- "#32CD32",
83
- "#1E90FF",
84
- "#FF4500",
85
- "#9370DB",
86
- "#00FA9A",
87
- "#FFD700",
88
- "#DC143C",
89
- "#00BFFF",
90
- "#FF69B4",
91
- "#20B2AA",
92
- "#DA70D6",
93
- "#4682B4"
94
- ];
95
- const isNode = typeof process !== "undefined" && process.versions?.node != null;
96
- const ANSI_COLORS = [
97
- "\x1B[94m",
98
- "\x1B[92m",
99
- "\x1B[91m",
100
- "\x1B[95m",
101
- "\x1B[93m",
102
- "\x1B[96m",
103
- "\x1B[35m",
104
- "\x1B[36m",
105
- "\x1B[32m",
106
- "\x1B[34m",
107
- "\x1B[33m",
108
- "\x1B[31m",
109
- "\x1B[90m",
110
- "\x1B[37m",
111
- "\x1B[1m"
112
- ];
113
- const ANSI_RESET = "\x1B[0m";
114
- const ANSI_BOLD = "\x1B[1m";
115
- const namespaceColors = /* @__PURE__ */ new Map();
116
- function getColorForNamespace(namespace) {
117
- const cachedColor = namespaceColors.get(namespace);
118
- if (cachedColor) return cachedColor;
119
- let hash = 0;
120
- for (let i = 0; i < namespace.length; i++) {
121
- const char = namespace.charCodeAt(i);
122
- hash = (hash << 5) - hash + char;
123
- hash = hash & hash;
124
- }
125
- const colorIndex = Math.abs(hash) % COLOR_PALETTE.length;
126
- const color = {
127
- css: COLOR_PALETTE[colorIndex] ?? "inherit",
128
- ansi: ANSI_COLORS[colorIndex % ANSI_COLORS.length] ?? ""
129
- };
130
- namespaceColors.set(namespace, color);
131
- return color;
132
- }
133
- function createDebugLogger(namespace) {
134
- const colors = getColorForNamespace(namespace);
135
- return (...args) => {
136
- const envEnabled = isEnabled(namespace);
137
- const progEnabled = enabledNamespaces.has(namespace) && !disabledNamespaces.has(namespace);
138
- if (envEnabled || progEnabled) if (isNode) {
139
- const coloredNamespace = `${ANSI_BOLD}${colors.ansi}${namespace}${ANSI_RESET}`;
140
- console.log(coloredNamespace, ...args);
141
- } else {
142
- const style1 = `color: ${colors.css}; font-weight: bold`;
143
- console.log(`%c${namespace}%c`, style1, "color: inherit; font-weight: normal", ...args);
144
- }
145
- };
146
- }
147
- const getLogger = (scope) => {
148
- return createDebugLogger(`${ROOT_NAMESPACE}:${scope}`);
149
- };
150
-
151
- //#endregion
152
- export { NoEntityFoundError as a, InvalidContentTypeError as i, EmptyPatchError as n, NoMoreResultsError as o, EntityMutationError as r, getLogger as t };
153
- //# sourceMappingURL=logger-CVpvU8ik.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger-CVpvU8ik.js","names":["enabledNamespaces: Set<string>","disabledNamespaces: Set<string>"],"sources":["../src/errors.ts","../src/utils/logger.ts"],"sourcesContent":["export class EntityMutationError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = \"EntityMutationError\"\n }\n}\nexport class NoMoreResultsError extends Error {\n constructor() {\n super(\"No more results — the last page carried no cursor. Check hasNextPage() before next().\")\n this.name = \"NoMoreResultsError\"\n }\n}\n\nexport class NoEntityFoundError extends Error {\n /** The key that matched nothing, when the lookup was by key. */\n readonly entityKey: string | undefined\n\n constructor(entityKey?: string) {\n super(\n entityKey === undefined\n ? \"No entity found\"\n : `No live entity with key ${entityKey}. It was never created, or it has been deleted or ` +\n \"has expired.\",\n )\n this.name = \"NoEntityFoundError\"\n this.entityKey = entityKey\n }\n}\n\nexport class EmptyPatchError extends Error {\n readonly entityKey: string\n\n constructor(entityKey: string) {\n super(\n `The patch for entity ${entityKey} has nothing to apply. Pass \"set\" to write attributes, ` +\n '\"unset\" to remove them, or \"payload\"/\"contentType\" to replace the contents.',\n )\n this.name = \"EmptyPatchError\"\n this.entityKey = entityKey\n }\n}\n\nexport class InvalidContentTypeError extends Error {\n constructor(contentType: string) {\n super(\n `Invalid content type \"${contentType}\". Must follow RFC 2045 MIME grammar and be lowercase only (e.g. \"text/plain\").`,\n )\n this.name = \"InvalidContentTypeError\"\n }\n}\n","const ROOT_NAMESPACE = \"arkiv\"\n\n// Debug logger type - returns a function that can be called to log messages\ntype DebugLogger = (...args: unknown[]) => void\n\n// Get DEBUG environment variable (works in both Node.js and browser)\nfunction getDebugEnv(): string {\n if (typeof process !== \"undefined\") {\n const debugEnv = process?.env?.DEBUG\n if (debugEnv) {\n return debugEnv\n }\n }\n // Browser: check localStorage\n if (typeof globalThis !== \"undefined\" && \"localStorage\" in globalThis) {\n try {\n const storage = (globalThis as { localStorage?: Storage }).localStorage\n return storage?.getItem(\"DEBUG\") || \"\"\n } catch {\n // localStorage might not be available\n }\n }\n return \"\"\n}\n\n// Parse debug patterns and check if a namespace matches\nfunction matchesPattern(namespace: string, pattern: string): boolean {\n // Exact match\n if (pattern === namespace) return true\n\n // Wildcard match: \"arkiv:*\" matches \"arkiv:query\", \"arkiv:rpc\", etc.\n if (pattern.endsWith(\"*\")) {\n const prefix = pattern.slice(0, -1)\n return namespace.startsWith(prefix)\n }\n\n // Negative match: \"-arkiv:query\" excludes \"arkiv:query\"\n if (pattern.startsWith(\"-\")) {\n const excludePattern = pattern.slice(1)\n return !matchesPattern(namespace, excludePattern)\n }\n\n return false\n}\n\n// Check if a namespace is enabled for debugging\nfunction isEnabled(namespace: string): boolean {\n const debugEnv = getDebugEnv()\n if (!debugEnv) return false\n\n // Split by comma/space and check each pattern\n const patterns = debugEnv.split(/[\\s,]+/).filter((p) => p.length > 0)\n\n // If no patterns, nothing is enabled\n if (patterns.length === 0) return false\n\n // Check if any pattern matches (or if explicitly excluded)\n let enabled = false\n for (const pattern of patterns) {\n if (pattern.startsWith(\"-\")) {\n // Exclude pattern - if it matches, disable\n if (matchesPattern(namespace, pattern)) {\n return false\n }\n } else if (matchesPattern(namespace, pattern)) {\n enabled = true\n }\n }\n\n return enabled\n}\n\n// Store enabled namespaces (for programmatic enable/disable)\nconst enabledNamespaces: Set<string> = new Set()\nconst disabledNamespaces: Set<string> = new Set()\n\n// Color palette for namespace coloring (distinct, readable colors)\nconst COLOR_PALETTE = [\n \"#0000FF\", // blue\n \"#008000\", // green\n \"#FF0000\", // red\n \"#FF00FF\", // magenta\n \"#FFA500\", // orange\n \"#800080\", // purple\n \"#00CED1\", // dark turquoise\n \"#FF1493\", // deep pink\n \"#32CD32\", // lime green\n \"#1E90FF\", // dodger blue\n \"#FF4500\", // orange red\n \"#9370DB\", // medium purple\n \"#00FA9A\", // medium spring green\n \"#FFD700\", // gold\n \"#DC143C\", // crimson\n \"#00BFFF\", // deep sky blue\n \"#FF69B4\", // hot pink\n \"#20B2AA\", // light sea green\n \"#DA70D6\", // orchid\n \"#4682B4\", // steel blue\n]\n\n// Detect if we're in Node.js (for ANSI colors) or browser (for CSS colors)\nconst isNode = typeof process !== \"undefined\" && process.versions?.node != null\n\n// ANSI color codes for Node.js (bright, distinct colors)\nconst ANSI_COLORS = [\n \"\\x1b[94m\", // bright blue\n \"\\x1b[92m\", // bright green\n \"\\x1b[91m\", // bright red\n \"\\x1b[95m\", // bright magenta\n \"\\x1b[93m\", // bright yellow\n \"\\x1b[96m\", // bright cyan\n \"\\x1b[35m\", // magenta\n \"\\x1b[36m\", // cyan\n \"\\x1b[32m\", // green\n \"\\x1b[34m\", // blue\n \"\\x1b[33m\", // yellow\n \"\\x1b[31m\", // red\n \"\\x1b[90m\", // bright black (gray)\n \"\\x1b[37m\", // white\n \"\\x1b[1m\", // bold (as a color option)\n]\n\nconst ANSI_RESET = \"\\x1b[0m\"\nconst ANSI_BOLD = \"\\x1b[1m\"\n\n// Cache colors for namespaces (same namespace = same color)\nconst namespaceColors = new Map<string, { css: string; ansi: string }>()\n\n// Generate a consistent color for a namespace based on its hash\nfunction getColorForNamespace(namespace: string): { css: string; ansi: string } {\n // Check cache first\n const cachedColor = namespaceColors.get(namespace)\n if (cachedColor) {\n return cachedColor\n }\n\n // Simple hash function to convert string to number\n let hash = 0\n for (let i = 0; i < namespace.length; i++) {\n const char = namespace.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32-bit integer\n }\n\n // Use absolute value and modulo to get index\n const colorIndex = Math.abs(hash) % COLOR_PALETTE.length\n const cssColor = COLOR_PALETTE[colorIndex] ?? \"inherit\"\n const ansiColor = ANSI_COLORS[colorIndex % ANSI_COLORS.length] ?? \"\"\n\n const color = { css: cssColor, ansi: ansiColor }\n\n // Cache the color\n namespaceColors.set(namespace, color)\n\n return color\n}\n\n// Create a debug logger function\nfunction createDebugLogger(namespace: string): DebugLogger {\n // Get the color for this namespace (consistent across calls)\n const colors = getColorForNamespace(namespace)\n\n return (...args: unknown[]) => {\n // Check if enabled via environment variable or programmatically\n const envEnabled = isEnabled(namespace)\n const progEnabled = enabledNamespaces.has(namespace) && !disabledNamespaces.has(namespace)\n\n if (envEnabled || progEnabled) {\n if (isNode) {\n // Node.js: use ANSI color codes\n const coloredNamespace = `${ANSI_BOLD}${colors.ansi}${namespace}${ANSI_RESET}`\n console.log(coloredNamespace, ...args)\n } else {\n // Browser: use CSS styling with %c\n // The format is: console.log(\"%cstyled%cnormal\", style1, style2, ...args)\n // This colors the namespace, then resets for the rest\n const style1 = `color: ${colors.css}; font-weight: bold`\n const style2 = \"color: inherit; font-weight: normal\"\n // Combine namespace with a space, then log with styles\n console.log(`%c${namespace}%c`, style1, style2, ...args)\n }\n }\n }\n}\n\nexport const getLogger = (scope: string): DebugLogger => {\n const namespace = `${ROOT_NAMESPACE}:${scope}`\n return createDebugLogger(namespace)\n}\n\nexport const enableDebug = (namespaces: string): void => {\n // Parse and add namespaces to enabled set\n const patterns = namespaces.split(/[\\s,]+/).filter((p) => p.length > 0)\n for (const pattern of patterns) {\n if (pattern.startsWith(\"-\")) {\n // Remove from enabled, add to disabled\n const namespace = pattern.slice(1)\n enabledNamespaces.delete(namespace)\n disabledNamespaces.add(namespace)\n } else {\n enabledNamespaces.add(pattern)\n disabledNamespaces.delete(pattern)\n }\n }\n}\n\nexport const disableDebug = (): void => {\n enabledNamespaces.clear()\n disabledNamespaces.clear()\n}\n"],"mappings":";AAAA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,YAAY,SAAiB,SAA+B;AAC1D,QAAM,SAAS,QAAQ;AACvB,OAAK,OAAO;;;AAGhB,IAAa,qBAAb,cAAwC,MAAM;CAC5C,cAAc;AACZ,QAAM,wFAAwF;AAC9F,OAAK,OAAO;;;AAIhB,IAAa,qBAAb,cAAwC,MAAM;;CAE5C,AAAS;CAET,YAAY,WAAoB;AAC9B,QACE,cAAc,SACV,oBACA,2BAA2B,UAAU,gEAE1C;AACD,OAAK,OAAO;AACZ,OAAK,YAAY;;;AAIrB,IAAa,kBAAb,cAAqC,MAAM;CACzC,AAAS;CAET,YAAY,WAAmB;AAC7B,QACE,wBAAwB,UAAU,oIAEnC;AACD,OAAK,OAAO;AACZ,OAAK,YAAY;;;AAIrB,IAAa,0BAAb,cAA6C,MAAM;CACjD,YAAY,aAAqB;AAC/B,QACE,yBAAyB,YAAY,iFACtC;AACD,OAAK,OAAO;;;;;;AC/ChB,MAAM,iBAAiB;AAMvB,SAAS,cAAsB;AAC7B,KAAI,OAAO,YAAY,aAAa;EAClC,MAAM,WAAW,SAAS,KAAK;AAC/B,MAAI,SACF,QAAO;;AAIX,KAAI,OAAO,eAAe,eAAe,kBAAkB,WACzD,KAAI;AAEF,SADiB,WAA0C,cAC3C,QAAQ,QAAQ,IAAI;SAC9B;AAIV,QAAO;;AAIT,SAAS,eAAe,WAAmB,SAA0B;AAEnE,KAAI,YAAY,UAAW,QAAO;AAGlC,KAAI,QAAQ,SAAS,IAAI,EAAE;EACzB,MAAM,SAAS,QAAQ,MAAM,GAAG,GAAG;AACnC,SAAO,UAAU,WAAW,OAAO;;AAIrC,KAAI,QAAQ,WAAW,IAAI,CAEzB,QAAO,CAAC,eAAe,WADA,QAAQ,MAAM,EAAE,CACU;AAGnD,QAAO;;AAIT,SAAS,UAAU,WAA4B;CAC7C,MAAM,WAAW,aAAa;AAC9B,KAAI,CAAC,SAAU,QAAO;CAGtB,MAAM,WAAW,SAAS,MAAM,SAAS,CAAC,QAAQ,MAAM,EAAE,SAAS,EAAE;AAGrE,KAAI,SAAS,WAAW,EAAG,QAAO;CAGlC,IAAI,UAAU;AACd,MAAK,MAAM,WAAW,SACpB,KAAI,QAAQ,WAAW,IAAI,EAEzB;MAAI,eAAe,WAAW,QAAQ,CACpC,QAAO;YAEA,eAAe,WAAW,QAAQ,CAC3C,WAAU;AAId,QAAO;;AAIT,MAAMA,oCAAiC,IAAI,KAAK;AAChD,MAAMC,qCAAkC,IAAI,KAAK;AAGjD,MAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAGD,MAAM,SAAS,OAAO,YAAY,eAAe,QAAQ,UAAU,QAAQ;AAG3E,MAAM,cAAc;CAClB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAM,aAAa;AACnB,MAAM,YAAY;AAGlB,MAAM,kCAAkB,IAAI,KAA4C;AAGxE,SAAS,qBAAqB,WAAkD;CAE9E,MAAM,cAAc,gBAAgB,IAAI,UAAU;AAClD,KAAI,YACF,QAAO;CAIT,IAAI,OAAO;AACX,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;EACzC,MAAM,OAAO,UAAU,WAAW,EAAE;AACpC,UAAQ,QAAQ,KAAK,OAAO;AAC5B,SAAO,OAAO;;CAIhB,MAAM,aAAa,KAAK,IAAI,KAAK,GAAG,cAAc;CAIlD,MAAM,QAAQ;EAAE,KAHC,cAAc,eAAe;EAGf,MAFb,YAAY,aAAa,YAAY,WAAW;EAElB;AAGhD,iBAAgB,IAAI,WAAW,MAAM;AAErC,QAAO;;AAIT,SAAS,kBAAkB,WAAgC;CAEzD,MAAM,SAAS,qBAAqB,UAAU;AAE9C,SAAQ,GAAG,SAAoB;EAE7B,MAAM,aAAa,UAAU,UAAU;EACvC,MAAM,cAAc,kBAAkB,IAAI,UAAU,IAAI,CAAC,mBAAmB,IAAI,UAAU;AAE1F,MAAI,cAAc,YAChB,KAAI,QAAQ;GAEV,MAAM,mBAAmB,GAAG,YAAY,OAAO,OAAO,YAAY;AAClE,WAAQ,IAAI,kBAAkB,GAAG,KAAK;SACjC;GAIL,MAAM,SAAS,UAAU,OAAO,IAAI;AAGpC,WAAQ,IAAI,KAAK,UAAU,KAAK,QAFjB,uCAEiC,GAAG,KAAK;;;;AAMhE,MAAa,aAAa,UAA+B;AAEvD,QAAO,kBADW,GAAG,eAAe,GAAG,QACJ"}
@@ -1,188 +0,0 @@
1
-
2
- //#region src/errors.ts
3
- var EntityMutationError = class extends Error {
4
- constructor(message, options) {
5
- super(message, options);
6
- this.name = "EntityMutationError";
7
- }
8
- };
9
- var NoMoreResultsError = class extends Error {
10
- constructor() {
11
- super("No more results — the last page carried no cursor. Check hasNextPage() before next().");
12
- this.name = "NoMoreResultsError";
13
- }
14
- };
15
- var NoEntityFoundError = class extends Error {
16
- /** The key that matched nothing, when the lookup was by key. */
17
- entityKey;
18
- constructor(entityKey) {
19
- super(entityKey === void 0 ? "No entity found" : `No live entity with key ${entityKey}. It was never created, or it has been deleted or has expired.`);
20
- this.name = "NoEntityFoundError";
21
- this.entityKey = entityKey;
22
- }
23
- };
24
- var EmptyPatchError = class extends Error {
25
- entityKey;
26
- constructor(entityKey) {
27
- super(`The patch for entity ${entityKey} has nothing to apply. Pass "set" to write attributes, "unset" to remove them, or "payload"/"contentType" to replace the contents.`);
28
- this.name = "EmptyPatchError";
29
- this.entityKey = entityKey;
30
- }
31
- };
32
- var InvalidContentTypeError = class extends Error {
33
- constructor(contentType) {
34
- super(`Invalid content type "${contentType}". Must follow RFC 2045 MIME grammar and be lowercase only (e.g. "text/plain").`);
35
- this.name = "InvalidContentTypeError";
36
- }
37
- };
38
-
39
- //#endregion
40
- //#region src/utils/logger.ts
41
- const ROOT_NAMESPACE = "arkiv";
42
- function getDebugEnv() {
43
- if (typeof process !== "undefined") {
44
- const debugEnv = process?.env?.DEBUG;
45
- if (debugEnv) return debugEnv;
46
- }
47
- if (typeof globalThis !== "undefined" && "localStorage" in globalThis) try {
48
- return globalThis.localStorage?.getItem("DEBUG") || "";
49
- } catch {}
50
- return "";
51
- }
52
- function matchesPattern(namespace, pattern) {
53
- if (pattern === namespace) return true;
54
- if (pattern.endsWith("*")) {
55
- const prefix = pattern.slice(0, -1);
56
- return namespace.startsWith(prefix);
57
- }
58
- if (pattern.startsWith("-")) return !matchesPattern(namespace, pattern.slice(1));
59
- return false;
60
- }
61
- function isEnabled(namespace) {
62
- const debugEnv = getDebugEnv();
63
- if (!debugEnv) return false;
64
- const patterns = debugEnv.split(/[\s,]+/).filter((p) => p.length > 0);
65
- if (patterns.length === 0) return false;
66
- let enabled = false;
67
- for (const pattern of patterns) if (pattern.startsWith("-")) {
68
- if (matchesPattern(namespace, pattern)) return false;
69
- } else if (matchesPattern(namespace, pattern)) enabled = true;
70
- return enabled;
71
- }
72
- const enabledNamespaces = /* @__PURE__ */ new Set();
73
- const disabledNamespaces = /* @__PURE__ */ new Set();
74
- const COLOR_PALETTE = [
75
- "#0000FF",
76
- "#008000",
77
- "#FF0000",
78
- "#FF00FF",
79
- "#FFA500",
80
- "#800080",
81
- "#00CED1",
82
- "#FF1493",
83
- "#32CD32",
84
- "#1E90FF",
85
- "#FF4500",
86
- "#9370DB",
87
- "#00FA9A",
88
- "#FFD700",
89
- "#DC143C",
90
- "#00BFFF",
91
- "#FF69B4",
92
- "#20B2AA",
93
- "#DA70D6",
94
- "#4682B4"
95
- ];
96
- const isNode = typeof process !== "undefined" && process.versions?.node != null;
97
- const ANSI_COLORS = [
98
- "\x1B[94m",
99
- "\x1B[92m",
100
- "\x1B[91m",
101
- "\x1B[95m",
102
- "\x1B[93m",
103
- "\x1B[96m",
104
- "\x1B[35m",
105
- "\x1B[36m",
106
- "\x1B[32m",
107
- "\x1B[34m",
108
- "\x1B[33m",
109
- "\x1B[31m",
110
- "\x1B[90m",
111
- "\x1B[37m",
112
- "\x1B[1m"
113
- ];
114
- const ANSI_RESET = "\x1B[0m";
115
- const ANSI_BOLD = "\x1B[1m";
116
- const namespaceColors = /* @__PURE__ */ new Map();
117
- function getColorForNamespace(namespace) {
118
- const cachedColor = namespaceColors.get(namespace);
119
- if (cachedColor) return cachedColor;
120
- let hash = 0;
121
- for (let i = 0; i < namespace.length; i++) {
122
- const char = namespace.charCodeAt(i);
123
- hash = (hash << 5) - hash + char;
124
- hash = hash & hash;
125
- }
126
- const colorIndex = Math.abs(hash) % COLOR_PALETTE.length;
127
- const color = {
128
- css: COLOR_PALETTE[colorIndex] ?? "inherit",
129
- ansi: ANSI_COLORS[colorIndex % ANSI_COLORS.length] ?? ""
130
- };
131
- namespaceColors.set(namespace, color);
132
- return color;
133
- }
134
- function createDebugLogger(namespace) {
135
- const colors = getColorForNamespace(namespace);
136
- return (...args) => {
137
- const envEnabled = isEnabled(namespace);
138
- const progEnabled = enabledNamespaces.has(namespace) && !disabledNamespaces.has(namespace);
139
- if (envEnabled || progEnabled) if (isNode) {
140
- const coloredNamespace = `${ANSI_BOLD}${colors.ansi}${namespace}${ANSI_RESET}`;
141
- console.log(coloredNamespace, ...args);
142
- } else {
143
- const style1 = `color: ${colors.css}; font-weight: bold`;
144
- console.log(`%c${namespace}%c`, style1, "color: inherit; font-weight: normal", ...args);
145
- }
146
- };
147
- }
148
- const getLogger = (scope) => {
149
- return createDebugLogger(`${ROOT_NAMESPACE}:${scope}`);
150
- };
151
-
152
- //#endregion
153
- Object.defineProperty(exports, 'EmptyPatchError', {
154
- enumerable: true,
155
- get: function () {
156
- return EmptyPatchError;
157
- }
158
- });
159
- Object.defineProperty(exports, 'EntityMutationError', {
160
- enumerable: true,
161
- get: function () {
162
- return EntityMutationError;
163
- }
164
- });
165
- Object.defineProperty(exports, 'InvalidContentTypeError', {
166
- enumerable: true,
167
- get: function () {
168
- return InvalidContentTypeError;
169
- }
170
- });
171
- Object.defineProperty(exports, 'NoEntityFoundError', {
172
- enumerable: true,
173
- get: function () {
174
- return NoEntityFoundError;
175
- }
176
- });
177
- Object.defineProperty(exports, 'NoMoreResultsError', {
178
- enumerable: true,
179
- get: function () {
180
- return NoMoreResultsError;
181
- }
182
- });
183
- Object.defineProperty(exports, 'getLogger', {
184
- enumerable: true,
185
- get: function () {
186
- return getLogger;
187
- }
188
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"payload-BNoud2KZ.d.cts","names":[],"sources":["../src/utils/expirationTime.ts","../src/utils/payload.ts"],"sourcesContent":[],"mappings":";;;;;;AAWA;AAkCA;;;;AAU4B,KA5ChB,eAAA,GA4CgB;EACE;EACE,OAAA,CAAA,EA5CpB,QA4CoB,GAAA,SAAA;CACF;;;;;;;;;;;;ACxD9B;AAIA;;;;;;;;;cDuCa;;;;;;;oCAOqB;oCACA;gCACJ;8BACF;gCACE;kCACE;gCACF;;;;;;;kCAQE;;;;;;;;qCAgBK,oBAAkB;;;;;;;;;;;;;iBAmBtC,gBAAgB,oBAAkB;;;;;;;;mBAclC;;;;iBCjHD,aAAA,gBAA6B;iBAI7B,eAAA,gBAA+B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"payload-Bz6651ax.js","names":[],"sources":["../src/utils/expirationTime.ts","../src/utils/payload.ts"],"sourcesContent":["import { InvalidExpiryError } from \"../entity/errors\"\nimport { type Expiry, type Lifetime, makeExpiry, toBlocks } from \"../entity/expiry\"\nimport { MAX_EXPIRES_AT } from \"../entity/params\"\n\n/**\n * The optional floor a deadline can carry.\n *\n * `atLeast` takes a duration — one of the `from*` helpers — and never another deadline, so\n * `atBlock(x, { atLeast: atBlock(y) })` does not compile. Two deadlines are not a thing the engine\n * can resolve.\n */\nexport type DeadlineOptions = {\n /** Live at least this long from now, even if the deadline is sooner. */\n atLeast?: Lifetime | undefined\n}\n\nfunction lifetimeOf(seconds: number): Lifetime {\n return makeExpiry(toBlocks(seconds), 0n) as Lifetime\n}\n\nfunction deadlineOf(expiresAt: bigint | Date, options?: DeadlineOptions): Expiry {\n return makeExpiry(options?.atLeast?.minLifetime ?? 0n, expiresAt)\n}\n\n/**\n * Builds the `expires` of a create or an extension.\n *\n * Every helper returns the `{ minLifetime, expiresAt }` pair the ABI carries, so what you write is\n * what goes on the wire. The `from*` helpers fill `minLifetime` and leave `expiresAt` at `0n`;\n * {@link ExpirationTime.atBlock} and {@link ExpirationTime.atDate} do the reverse. The engine takes\n * whichever comes later, which is why a deadline can also carry a floor.\n *\n * Values are plain data — no methods, no prototype — so they log, clone and compare like any other\n * object.\n *\n * @example The 90% case: a duration, and nothing else to think about.\n * await client.createEntity({ payload, contentType, expires: ExpirationTime.fromDays(30) })\n *\n * @example An exact block, or a wall-clock date.\n * expires: ExpirationTime.atBlock(1_200_000n)\n * expires: ExpirationTime.atDate(new Date(\"2027-01-01\"))\n *\n * @example A deadline that still guarantees a minimum life.\n * expires: ExpirationTime.atBlock(1_200_000n, { atLeast: ExpirationTime.fromDays(1) })\n */\nexport const ExpirationTime = {\n /**\n * A raw number of seconds. Must be a whole number of blocks' worth — see the other helpers, which\n * all produce one by construction.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.\n */\n fromSeconds: (seconds: number): Lifetime => lifetimeOf(seconds),\n fromMinutes: (minutes: number): Lifetime => lifetimeOf(minutes * 60),\n fromHours: (hours: number): Lifetime => lifetimeOf(hours * 60 * 60),\n fromDays: (days: number): Lifetime => lifetimeOf(days * 24 * 60 * 60),\n fromWeeks: (weeks: number): Lifetime => lifetimeOf(weeks * 7 * 24 * 60 * 60),\n fromMonths: (months: number): Lifetime => lifetimeOf(months * 30 * 24 * 60 * 60),\n fromYears: (years: number): Lifetime => lifetimeOf(years * 365 * 24 * 60 * 60),\n\n /**\n * A number of blocks, for callers who think in the chain's own unit. Always exact — there is no\n * conversion to be approximate about.\n *\n * @throws {InvalidExpiryError} If the count is not a positive whole number.\n */\n fromBlocks: (blocks: number): Lifetime => {\n if (!Number.isInteger(blocks) || blocks <= 0) {\n throw new InvalidExpiryError(\n `a lifetime must be a positive whole number of blocks, got ${blocks}`,\n )\n }\n return makeExpiry(BigInt(blocks), 0n) as Lifetime\n },\n\n /**\n * An absolute block height.\n *\n * @param block - The block the entity expires at.\n * @param options - Optionally, a floor: `{ atLeast: ExpirationTime.fromDays(1) }`.\n * @throws {InvalidExpiryError} If the height is negative.\n */\n atBlock: (block: bigint, options?: DeadlineOptions): Expiry => {\n if (typeof block !== \"bigint\" || block < 0n) {\n throw new InvalidExpiryError(`a deadline must be a non-negative block height, got ${block}`)\n }\n return deadlineOf(block, options)\n },\n\n /**\n * A wall-clock instant, placed against the block the transaction is built on.\n *\n * A date cannot land on a block boundary in general, so it rounds **up** to the next block: the\n * entity lives until at least the instant asked for. This is why a date is never rejected for\n * \"not being a whole number of blocks\" the way a duration is — it becomes a block height, not a\n * duration.\n *\n * @param date - When the entity should expire.\n * @param options - Optionally, a floor: `{ atLeast: ExpirationTime.fromDays(1) }`.\n * @throws {InvalidExpiryError} If the value is not a valid `Date`.\n */\n atDate: (date: Date, options?: DeadlineOptions): Expiry => {\n if (!(date instanceof Date) || Number.isNaN(date.getTime())) {\n throw new InvalidExpiryError(`a deadline must be a valid Date, got ${String(date)}`)\n }\n return deadlineOf(date, options)\n },\n\n /**\n * An entity that should never expire.\n *\n * This is `atBlock(MAX_EXPIRES_AT)` — the largest expiry the `uint64` field holds — and the\n * engine treats it as an ordinary deadline rather than a special case. There is no permanence\n * flag; a block height no chain will reach is what permanence is.\n */\n permanent: (): Expiry => deadlineOf(MAX_EXPIRES_AT),\n}\n","import { stringToBytes, toBytes } from \"viem\"\n\nexport function jsonToPayload(json: object): Uint8Array {\n return toBytes(JSON.stringify(json))\n}\n\nexport function stringToPayload(data: string): Uint8Array {\n // stringToBytes, not toBytes: toBytes hex-decodes hex-looking strings, which\n // would corrupt payloads like \"0xab\" instead of UTF-8 encoding them\n return stringToBytes(data)\n}\n"],"mappings":";;;;;AAgBA,SAAS,WAAW,SAA2B;AAC7C,QAAO,WAAW,SAAS,QAAQ,EAAE,GAAG;;AAG1C,SAAS,WAAW,WAA0B,SAAmC;AAC/E,QAAO,WAAW,SAAS,SAAS,eAAe,IAAI,UAAU;;;;;;;;;;;;;;;;;;;;;;;AAwBnE,MAAa,iBAAiB;CAO5B,cAAc,YAA8B,WAAW,QAAQ;CAC/D,cAAc,YAA8B,WAAW,UAAU,GAAG;CACpE,YAAY,UAA4B,WAAW,QAAQ,KAAK,GAAG;CACnE,WAAW,SAA2B,WAAW,OAAO,KAAK,KAAK,GAAG;CACrE,YAAY,UAA4B,WAAW,QAAQ,IAAI,KAAK,KAAK,GAAG;CAC5E,aAAa,WAA6B,WAAW,SAAS,KAAK,KAAK,KAAK,GAAG;CAChF,YAAY,UAA4B,WAAW,QAAQ,MAAM,KAAK,KAAK,GAAG;CAQ9E,aAAa,WAA6B;AACxC,MAAI,CAAC,OAAO,UAAU,OAAO,IAAI,UAAU,EACzC,OAAM,IAAI,mBACR,6DAA6D,SAC9D;AAEH,SAAO,WAAW,OAAO,OAAO,EAAE,GAAG;;CAUvC,UAAU,OAAe,YAAsC;AAC7D,MAAI,OAAO,UAAU,YAAY,QAAQ,GACvC,OAAM,IAAI,mBAAmB,uDAAuD,QAAQ;AAE9F,SAAO,WAAW,OAAO,QAAQ;;CAenC,SAAS,MAAY,YAAsC;AACzD,MAAI,EAAE,gBAAgB,SAAS,OAAO,MAAM,KAAK,SAAS,CAAC,CACzD,OAAM,IAAI,mBAAmB,wCAAwC,OAAO,KAAK,GAAG;AAEtF,SAAO,WAAW,MAAM,QAAQ;;CAUlC,iBAAyB,WAAW,eAAe;CACpD;;;;AClHD,SAAgB,cAAc,MAA0B;AACtD,QAAO,QAAQ,KAAK,UAAU,KAAK,CAAC;;AAGtC,SAAgB,gBAAgB,MAA0B;AAGxD,QAAO,cAAc,KAAK"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"payload-CcUj85ys.d.ts","names":[],"sources":["../src/utils/expirationTime.ts","../src/utils/payload.ts"],"sourcesContent":[],"mappings":";;;;;;AAWA;AAkCA;;;;AAU4B,KA5ChB,eAAA,GA4CgB;EACE;EACE,OAAA,CAAA,EA5CpB,QA4CoB,GAAA,SAAA;CACF;;;;;;;;;;;;ACxD9B;AAIA;;;;;;;;;cDuCa;;;;;;;oCAOqB;oCACA;gCACJ;8BACF;gCACE;kCACE;gCACF;;;;;;;kCAQE;;;;;;;;qCAgBK,oBAAkB;;;;;;;;;;;;;iBAmBtC,gBAAgB,oBAAkB;;;;;;;;mBAclC;;;;iBCjHD,aAAA,gBAA6B;iBAI7B,eAAA,gBAA+B"}