@mikeatlast/ponder 0.16.1-fork.1

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 (619) hide show
  1. package/CHANGELOG.md +3415 -0
  2. package/README.md +186 -0
  3. package/dist/esm/bin/commands/codegen.js +46 -0
  4. package/dist/esm/bin/commands/codegen.js.map +1 -0
  5. package/dist/esm/bin/commands/createViews.js +196 -0
  6. package/dist/esm/bin/commands/createViews.js.map +1 -0
  7. package/dist/esm/bin/commands/dev.js +430 -0
  8. package/dist/esm/bin/commands/dev.js.map +1 -0
  9. package/dist/esm/bin/commands/list.js +148 -0
  10. package/dist/esm/bin/commands/list.js.map +1 -0
  11. package/dist/esm/bin/commands/prune.js +223 -0
  12. package/dist/esm/bin/commands/prune.js.map +1 -0
  13. package/dist/esm/bin/commands/serve.js +198 -0
  14. package/dist/esm/bin/commands/serve.js.map +1 -0
  15. package/dist/esm/bin/commands/start.js +253 -0
  16. package/dist/esm/bin/commands/start.js.map +1 -0
  17. package/dist/esm/bin/isolatedController.js +200 -0
  18. package/dist/esm/bin/isolatedController.js.map +1 -0
  19. package/dist/esm/bin/isolatedWorker.js +146 -0
  20. package/dist/esm/bin/isolatedWorker.js.map +1 -0
  21. package/dist/esm/bin/ponder.js +137 -0
  22. package/dist/esm/bin/ponder.js.map +1 -0
  23. package/dist/esm/bin/utils/codegen.js +25 -0
  24. package/dist/esm/bin/utils/codegen.js.map +1 -0
  25. package/dist/esm/bin/utils/exit.js +100 -0
  26. package/dist/esm/bin/utils/exit.js.map +1 -0
  27. package/dist/esm/build/config.js +745 -0
  28. package/dist/esm/build/config.js.map +1 -0
  29. package/dist/esm/build/factory.js +82 -0
  30. package/dist/esm/build/factory.js.map +1 -0
  31. package/dist/esm/build/index.js +567 -0
  32. package/dist/esm/build/index.js.map +1 -0
  33. package/dist/esm/build/plugin.js +53 -0
  34. package/dist/esm/build/plugin.js.map +1 -0
  35. package/dist/esm/build/pre.js +83 -0
  36. package/dist/esm/build/pre.js.map +1 -0
  37. package/dist/esm/build/schema.js +202 -0
  38. package/dist/esm/build/schema.js.map +1 -0
  39. package/dist/esm/build/stacktrace.js +137 -0
  40. package/dist/esm/build/stacktrace.js.map +1 -0
  41. package/dist/esm/client/index.js +441 -0
  42. package/dist/esm/client/index.js.map +1 -0
  43. package/dist/esm/config/address.js +2 -0
  44. package/dist/esm/config/address.js.map +1 -0
  45. package/dist/esm/config/eventFilter.js +2 -0
  46. package/dist/esm/config/eventFilter.js.map +1 -0
  47. package/dist/esm/config/index.js +2 -0
  48. package/dist/esm/config/index.js.map +1 -0
  49. package/dist/esm/config/utilityTypes.js +2 -0
  50. package/dist/esm/config/utilityTypes.js.map +1 -0
  51. package/dist/esm/database/actions.js +445 -0
  52. package/dist/esm/database/actions.js.map +1 -0
  53. package/dist/esm/database/index.js +604 -0
  54. package/dist/esm/database/index.js.map +1 -0
  55. package/dist/esm/database/queryBuilder.js +314 -0
  56. package/dist/esm/database/queryBuilder.js.map +1 -0
  57. package/dist/esm/drizzle/bigint.js +38 -0
  58. package/dist/esm/drizzle/bigint.js.map +1 -0
  59. package/dist/esm/drizzle/bytes.js +47 -0
  60. package/dist/esm/drizzle/bytes.js.map +1 -0
  61. package/dist/esm/drizzle/hex.js +40 -0
  62. package/dist/esm/drizzle/hex.js.map +1 -0
  63. package/dist/esm/drizzle/index.js +28 -0
  64. package/dist/esm/drizzle/index.js.map +1 -0
  65. package/dist/esm/drizzle/json.js +123 -0
  66. package/dist/esm/drizzle/json.js.map +1 -0
  67. package/dist/esm/drizzle/kit/index.js +927 -0
  68. package/dist/esm/drizzle/kit/index.js.map +1 -0
  69. package/dist/esm/drizzle/onchain.js +184 -0
  70. package/dist/esm/drizzle/onchain.js.map +1 -0
  71. package/dist/esm/drizzle/text.js +61 -0
  72. package/dist/esm/drizzle/text.js.map +1 -0
  73. package/dist/esm/graphql/graphiql.html.js +59 -0
  74. package/dist/esm/graphql/graphiql.html.js.map +1 -0
  75. package/dist/esm/graphql/index.js +934 -0
  76. package/dist/esm/graphql/index.js.map +1 -0
  77. package/dist/esm/graphql/json.js +42 -0
  78. package/dist/esm/graphql/json.js.map +1 -0
  79. package/dist/esm/graphql/middleware.js +83 -0
  80. package/dist/esm/graphql/middleware.js.map +1 -0
  81. package/dist/esm/index.js +9 -0
  82. package/dist/esm/index.js.map +1 -0
  83. package/dist/esm/indexing/addStackTrace.js +54 -0
  84. package/dist/esm/indexing/addStackTrace.js.map +1 -0
  85. package/dist/esm/indexing/client.js +675 -0
  86. package/dist/esm/indexing/client.js.map +1 -0
  87. package/dist/esm/indexing/index.js +663 -0
  88. package/dist/esm/indexing/index.js.map +1 -0
  89. package/dist/esm/indexing/profile.js +584 -0
  90. package/dist/esm/indexing/profile.js.map +1 -0
  91. package/dist/esm/indexing-store/cache.js +666 -0
  92. package/dist/esm/indexing-store/cache.js.map +1 -0
  93. package/dist/esm/indexing-store/index.js +461 -0
  94. package/dist/esm/indexing-store/index.js.map +1 -0
  95. package/dist/esm/indexing-store/profile.js +428 -0
  96. package/dist/esm/indexing-store/profile.js.map +1 -0
  97. package/dist/esm/indexing-store/utils.js +111 -0
  98. package/dist/esm/indexing-store/utils.js.map +1 -0
  99. package/dist/esm/internal/common.js +2 -0
  100. package/dist/esm/internal/common.js.map +1 -0
  101. package/dist/esm/internal/errors.js +300 -0
  102. package/dist/esm/internal/errors.js.map +1 -0
  103. package/dist/esm/internal/logger.js +178 -0
  104. package/dist/esm/internal/logger.js.map +1 -0
  105. package/dist/esm/internal/metrics.js +1049 -0
  106. package/dist/esm/internal/metrics.js.map +1 -0
  107. package/dist/esm/internal/options.js +73 -0
  108. package/dist/esm/internal/options.js.map +1 -0
  109. package/dist/esm/internal/shutdown.js +24 -0
  110. package/dist/esm/internal/shutdown.js.map +1 -0
  111. package/dist/esm/internal/telemetry.js +200 -0
  112. package/dist/esm/internal/telemetry.js.map +1 -0
  113. package/dist/esm/internal/types.js +2 -0
  114. package/dist/esm/internal/types.js.map +1 -0
  115. package/dist/esm/rpc/actions.js +988 -0
  116. package/dist/esm/rpc/actions.js.map +1 -0
  117. package/dist/esm/rpc/http.js +130 -0
  118. package/dist/esm/rpc/http.js.map +1 -0
  119. package/dist/esm/rpc/index.js +749 -0
  120. package/dist/esm/rpc/index.js.map +1 -0
  121. package/dist/esm/runtime/events.js +664 -0
  122. package/dist/esm/runtime/events.js.map +1 -0
  123. package/dist/esm/runtime/filter.js +476 -0
  124. package/dist/esm/runtime/filter.js.map +1 -0
  125. package/dist/esm/runtime/fragments.js +478 -0
  126. package/dist/esm/runtime/fragments.js.map +1 -0
  127. package/dist/esm/runtime/historical.js +954 -0
  128. package/dist/esm/runtime/historical.js.map +1 -0
  129. package/dist/esm/runtime/index.js +316 -0
  130. package/dist/esm/runtime/index.js.map +1 -0
  131. package/dist/esm/runtime/init.js +12 -0
  132. package/dist/esm/runtime/init.js.map +1 -0
  133. package/dist/esm/runtime/isolated.js +464 -0
  134. package/dist/esm/runtime/isolated.js.map +1 -0
  135. package/dist/esm/runtime/multichain.js +511 -0
  136. package/dist/esm/runtime/multichain.js.map +1 -0
  137. package/dist/esm/runtime/omnichain.js +546 -0
  138. package/dist/esm/runtime/omnichain.js.map +1 -0
  139. package/dist/esm/runtime/realtime.js +722 -0
  140. package/dist/esm/runtime/realtime.js.map +1 -0
  141. package/dist/esm/server/error.js +56 -0
  142. package/dist/esm/server/error.js.map +1 -0
  143. package/dist/esm/server/index.js +121 -0
  144. package/dist/esm/server/index.js.map +1 -0
  145. package/dist/esm/sync-historical/index.js +703 -0
  146. package/dist/esm/sync-historical/index.js.map +1 -0
  147. package/dist/esm/sync-realtime/bloom.js +76 -0
  148. package/dist/esm/sync-realtime/bloom.js.map +1 -0
  149. package/dist/esm/sync-realtime/index.js +918 -0
  150. package/dist/esm/sync-realtime/index.js.map +1 -0
  151. package/dist/esm/sync-store/encode.js +105 -0
  152. package/dist/esm/sync-store/encode.js.map +1 -0
  153. package/dist/esm/sync-store/index.js +885 -0
  154. package/dist/esm/sync-store/index.js.map +1 -0
  155. package/dist/esm/sync-store/migrations.js +1595 -0
  156. package/dist/esm/sync-store/migrations.js.map +1 -0
  157. package/dist/esm/sync-store/schema.js +181 -0
  158. package/dist/esm/sync-store/schema.js.map +1 -0
  159. package/dist/esm/types/db.js +2 -0
  160. package/dist/esm/types/db.js.map +1 -0
  161. package/dist/esm/types/eth.js +2 -0
  162. package/dist/esm/types/eth.js.map +1 -0
  163. package/dist/esm/types/utils.js +2 -0
  164. package/dist/esm/types/utils.js.map +1 -0
  165. package/dist/esm/types/virtual.js +2 -0
  166. package/dist/esm/types/virtual.js.map +1 -0
  167. package/dist/esm/ui/app.js +157 -0
  168. package/dist/esm/ui/app.js.map +1 -0
  169. package/dist/esm/ui/index.js +29 -0
  170. package/dist/esm/ui/index.js.map +1 -0
  171. package/dist/esm/ui/patch.js +140 -0
  172. package/dist/esm/ui/patch.js.map +1 -0
  173. package/dist/esm/utils/abi.js +55 -0
  174. package/dist/esm/utils/abi.js.map +1 -0
  175. package/dist/esm/utils/bigint.js +37 -0
  176. package/dist/esm/utils/bigint.js.map +1 -0
  177. package/dist/esm/utils/chains.js +21 -0
  178. package/dist/esm/utils/chains.js.map +1 -0
  179. package/dist/esm/utils/checkpoint.js +139 -0
  180. package/dist/esm/utils/checkpoint.js.map +1 -0
  181. package/dist/esm/utils/chunk.js +8 -0
  182. package/dist/esm/utils/chunk.js.map +1 -0
  183. package/dist/esm/utils/copy.js +129 -0
  184. package/dist/esm/utils/copy.js.map +1 -0
  185. package/dist/esm/utils/date.js +27 -0
  186. package/dist/esm/utils/date.js.map +1 -0
  187. package/dist/esm/utils/debug.js +2 -0
  188. package/dist/esm/utils/debug.js.map +1 -0
  189. package/dist/esm/utils/decodeAbiParameters.js +290 -0
  190. package/dist/esm/utils/decodeAbiParameters.js.map +1 -0
  191. package/dist/esm/utils/decodeEventLog.js +75 -0
  192. package/dist/esm/utils/decodeEventLog.js.map +1 -0
  193. package/dist/esm/utils/dedupe.js +29 -0
  194. package/dist/esm/utils/dedupe.js.map +1 -0
  195. package/dist/esm/utils/duplicates.js +19 -0
  196. package/dist/esm/utils/duplicates.js.map +1 -0
  197. package/dist/esm/utils/estimate.js +6 -0
  198. package/dist/esm/utils/estimate.js.map +1 -0
  199. package/dist/esm/utils/finality.js +38 -0
  200. package/dist/esm/utils/finality.js.map +1 -0
  201. package/dist/esm/utils/format.js +20 -0
  202. package/dist/esm/utils/format.js.map +1 -0
  203. package/dist/esm/utils/generators.js +121 -0
  204. package/dist/esm/utils/generators.js.map +1 -0
  205. package/dist/esm/utils/hash.js +11 -0
  206. package/dist/esm/utils/hash.js.map +1 -0
  207. package/dist/esm/utils/interval.js +171 -0
  208. package/dist/esm/utils/interval.js.map +1 -0
  209. package/dist/esm/utils/lowercase.js +7 -0
  210. package/dist/esm/utils/lowercase.js.map +1 -0
  211. package/dist/esm/utils/mutex.js +26 -0
  212. package/dist/esm/utils/mutex.js.map +1 -0
  213. package/dist/esm/utils/never.js +4 -0
  214. package/dist/esm/utils/never.js.map +1 -0
  215. package/dist/esm/utils/offset.js +101 -0
  216. package/dist/esm/utils/offset.js.map +1 -0
  217. package/dist/esm/utils/order.js +18 -0
  218. package/dist/esm/utils/order.js.map +1 -0
  219. package/dist/esm/utils/partition.js +46 -0
  220. package/dist/esm/utils/partition.js.map +1 -0
  221. package/dist/esm/utils/pg.js +175 -0
  222. package/dist/esm/utils/pg.js.map +1 -0
  223. package/dist/esm/utils/pglite.js +80 -0
  224. package/dist/esm/utils/pglite.js.map +1 -0
  225. package/dist/esm/utils/port.js +30 -0
  226. package/dist/esm/utils/port.js.map +1 -0
  227. package/dist/esm/utils/print.js +23 -0
  228. package/dist/esm/utils/print.js.map +1 -0
  229. package/dist/esm/utils/promiseAllSettledWithThrow.js +19 -0
  230. package/dist/esm/utils/promiseAllSettledWithThrow.js.map +1 -0
  231. package/dist/esm/utils/promiseWithResolvers.js +13 -0
  232. package/dist/esm/utils/promiseWithResolvers.js.map +1 -0
  233. package/dist/esm/utils/queue.js +150 -0
  234. package/dist/esm/utils/queue.js.map +1 -0
  235. package/dist/esm/utils/range.js +8 -0
  236. package/dist/esm/utils/range.js.map +1 -0
  237. package/dist/esm/utils/result.js +10 -0
  238. package/dist/esm/utils/result.js.map +1 -0
  239. package/dist/esm/utils/sql-parse.js +1326 -0
  240. package/dist/esm/utils/sql-parse.js.map +1 -0
  241. package/dist/esm/utils/timer.js +9 -0
  242. package/dist/esm/utils/timer.js.map +1 -0
  243. package/dist/esm/utils/truncate.js +15 -0
  244. package/dist/esm/utils/truncate.js.map +1 -0
  245. package/dist/esm/utils/wait.js +10 -0
  246. package/dist/esm/utils/wait.js.map +1 -0
  247. package/dist/esm/utils/zipper.js +67 -0
  248. package/dist/esm/utils/zipper.js.map +1 -0
  249. package/dist/types/bin/commands/codegen.d.ts +5 -0
  250. package/dist/types/bin/commands/codegen.d.ts.map +1 -0
  251. package/dist/types/bin/commands/createViews.d.ts +8 -0
  252. package/dist/types/bin/commands/createViews.d.ts.map +1 -0
  253. package/dist/types/bin/commands/dev.d.ts +5 -0
  254. package/dist/types/bin/commands/dev.d.ts.map +1 -0
  255. package/dist/types/bin/commands/list.d.ts +5 -0
  256. package/dist/types/bin/commands/list.d.ts.map +1 -0
  257. package/dist/types/bin/commands/prune.d.ts +5 -0
  258. package/dist/types/bin/commands/prune.d.ts.map +1 -0
  259. package/dist/types/bin/commands/serve.d.ts +5 -0
  260. package/dist/types/bin/commands/serve.d.ts.map +1 -0
  261. package/dist/types/bin/commands/start.d.ts +19 -0
  262. package/dist/types/bin/commands/start.d.ts.map +1 -0
  263. package/dist/types/bin/isolatedController.d.ts +13 -0
  264. package/dist/types/bin/isolatedController.d.ts.map +1 -0
  265. package/dist/types/bin/isolatedWorker.d.ts +9 -0
  266. package/dist/types/bin/isolatedWorker.d.ts.map +1 -0
  267. package/dist/types/bin/ponder.d.ts +37 -0
  268. package/dist/types/bin/ponder.d.ts.map +1 -0
  269. package/dist/types/bin/utils/codegen.d.ts +6 -0
  270. package/dist/types/bin/utils/codegen.d.ts.map +1 -0
  271. package/dist/types/bin/utils/exit.d.ts +10 -0
  272. package/dist/types/bin/utils/exit.d.ts.map +1 -0
  273. package/dist/types/build/config.d.ts +97 -0
  274. package/dist/types/build/config.d.ts.map +1 -0
  275. package/dist/types/build/factory.d.ts +15 -0
  276. package/dist/types/build/factory.d.ts.map +1 -0
  277. package/dist/types/build/index.d.ts +84 -0
  278. package/dist/types/build/index.d.ts.map +1 -0
  279. package/dist/types/build/plugin.d.ts +4 -0
  280. package/dist/types/build/plugin.d.ts.map +1 -0
  281. package/dist/types/build/pre.d.ts +29 -0
  282. package/dist/types/build/pre.d.ts.map +1 -0
  283. package/dist/types/build/schema.d.ts +20 -0
  284. package/dist/types/build/schema.d.ts.map +1 -0
  285. package/dist/types/build/stacktrace.d.ts +13 -0
  286. package/dist/types/build/stacktrace.d.ts.map +1 -0
  287. package/dist/types/client/index.d.ts +27 -0
  288. package/dist/types/client/index.d.ts.map +1 -0
  289. package/dist/types/config/address.d.ts +34 -0
  290. package/dist/types/config/address.d.ts.map +1 -0
  291. package/dist/types/config/eventFilter.d.ts +18 -0
  292. package/dist/types/config/eventFilter.d.ts.map +1 -0
  293. package/dist/types/config/index.d.ts +144 -0
  294. package/dist/types/config/index.d.ts.map +1 -0
  295. package/dist/types/config/utilityTypes.d.ts +43 -0
  296. package/dist/types/config/utilityTypes.d.ts.map +1 -0
  297. package/dist/types/database/actions.d.ts +99 -0
  298. package/dist/types/database/actions.d.ts.map +1 -0
  299. package/dist/types/database/index.d.ts +493 -0
  300. package/dist/types/database/index.d.ts.map +1 -0
  301. package/dist/types/database/queryBuilder.d.ts +65 -0
  302. package/dist/types/database/queryBuilder.d.ts.map +1 -0
  303. package/dist/types/drizzle/bigint.d.ts +25 -0
  304. package/dist/types/drizzle/bigint.d.ts.map +1 -0
  305. package/dist/types/drizzle/bytes.d.ts +31 -0
  306. package/dist/types/drizzle/bytes.d.ts.map +1 -0
  307. package/dist/types/drizzle/hex.d.ts +25 -0
  308. package/dist/types/drizzle/hex.d.ts.map +1 -0
  309. package/dist/types/drizzle/index.d.ts +6 -0
  310. package/dist/types/drizzle/index.d.ts.map +1 -0
  311. package/dist/types/drizzle/json.d.ts +51 -0
  312. package/dist/types/drizzle/json.d.ts.map +1 -0
  313. package/dist/types/drizzle/kit/index.d.ts +187 -0
  314. package/dist/types/drizzle/kit/index.d.ts.map +1 -0
  315. package/dist/types/drizzle/onchain.d.ts +298 -0
  316. package/dist/types/drizzle/onchain.d.ts.map +1 -0
  317. package/dist/types/drizzle/text.d.ts +29 -0
  318. package/dist/types/drizzle/text.d.ts.map +1 -0
  319. package/dist/types/graphql/graphiql.html.d.ts +2 -0
  320. package/dist/types/graphql/graphiql.html.d.ts.map +1 -0
  321. package/dist/types/graphql/index.d.ts +12 -0
  322. package/dist/types/graphql/index.d.ts.map +1 -0
  323. package/dist/types/graphql/json.d.ts +3 -0
  324. package/dist/types/graphql/json.d.ts.map +1 -0
  325. package/dist/types/graphql/middleware.d.ts +29 -0
  326. package/dist/types/graphql/middleware.d.ts.map +1 -0
  327. package/dist/types/index.d.ts +23 -0
  328. package/dist/types/index.d.ts.map +1 -0
  329. package/dist/types/indexing/addStackTrace.d.ts +3 -0
  330. package/dist/types/indexing/addStackTrace.d.ts.map +1 -0
  331. package/dist/types/indexing/client.d.ts +154 -0
  332. package/dist/types/indexing/client.d.ts.map +1 -0
  333. package/dist/types/indexing/index.d.ts +72 -0
  334. package/dist/types/indexing/index.d.ts.map +1 -0
  335. package/dist/types/indexing/profile.d.ts +16 -0
  336. package/dist/types/indexing/profile.d.ts.map +1 -0
  337. package/dist/types/indexing-store/cache.d.ts +115 -0
  338. package/dist/types/indexing-store/cache.d.ts.map +1 -0
  339. package/dist/types/indexing-store/index.d.ts +24 -0
  340. package/dist/types/indexing-store/index.d.ts.map +1 -0
  341. package/dist/types/indexing-store/profile.d.ts +7 -0
  342. package/dist/types/indexing-store/profile.d.ts.map +1 -0
  343. package/dist/types/indexing-store/utils.d.ts +19 -0
  344. package/dist/types/indexing-store/utils.d.ts.map +1 -0
  345. package/dist/types/internal/common.d.ts +15 -0
  346. package/dist/types/internal/common.d.ts.map +1 -0
  347. package/dist/types/internal/errors.d.ts +101 -0
  348. package/dist/types/internal/errors.d.ts.map +1 -0
  349. package/dist/types/internal/logger.d.ts +37 -0
  350. package/dist/types/internal/logger.d.ts.map +1 -0
  351. package/dist/types/internal/metrics.d.ts +120 -0
  352. package/dist/types/internal/metrics.d.ts.map +1 -0
  353. package/dist/types/internal/options.d.ts +62 -0
  354. package/dist/types/internal/options.d.ts.map +1 -0
  355. package/dist/types/internal/shutdown.d.ts +8 -0
  356. package/dist/types/internal/shutdown.d.ts.map +1 -0
  357. package/dist/types/internal/telemetry.d.ts +43 -0
  358. package/dist/types/internal/telemetry.d.ts.map +1 -0
  359. package/dist/types/internal/types.d.ts +443 -0
  360. package/dist/types/internal/types.d.ts.map +1 -0
  361. package/dist/types/rpc/actions.d.ts +360 -0
  362. package/dist/types/rpc/actions.d.ts.map +1 -0
  363. package/dist/types/rpc/http.d.ts +17 -0
  364. package/dist/types/rpc/http.d.ts.map +1 -0
  365. package/dist/types/rpc/index.d.ts +43 -0
  366. package/dist/types/rpc/index.d.ts.map +1 -0
  367. package/dist/types/runtime/events.d.ts +40 -0
  368. package/dist/types/runtime/events.d.ts.map +1 -0
  369. package/dist/types/runtime/filter.d.ts +96 -0
  370. package/dist/types/runtime/filter.d.ts.map +1 -0
  371. package/dist/types/runtime/fragments.d.ts +30 -0
  372. package/dist/types/runtime/fragments.d.ts.map +1 -0
  373. package/dist/types/runtime/historical.d.ts +123 -0
  374. package/dist/types/runtime/historical.d.ts.map +1 -0
  375. package/dist/types/runtime/index.d.ts +89 -0
  376. package/dist/types/runtime/index.d.ts.map +1 -0
  377. package/dist/types/runtime/init.d.ts +28 -0
  378. package/dist/types/runtime/init.d.ts.map +1 -0
  379. package/dist/types/runtime/isolated.d.ts +14 -0
  380. package/dist/types/runtime/isolated.d.ts.map +1 -0
  381. package/dist/types/runtime/multichain.d.ts +13 -0
  382. package/dist/types/runtime/multichain.d.ts.map +1 -0
  383. package/dist/types/runtime/omnichain.d.ts +23 -0
  384. package/dist/types/runtime/omnichain.d.ts.map +1 -0
  385. package/dist/types/runtime/realtime.d.ts +93 -0
  386. package/dist/types/runtime/realtime.d.ts.map +1 -0
  387. package/dist/types/server/error.d.ts +5 -0
  388. package/dist/types/server/error.d.ts.map +1 -0
  389. package/dist/types/server/index.d.ts +13 -0
  390. package/dist/types/server/index.d.ts.map +1 -0
  391. package/dist/types/sync-historical/index.d.ts +36 -0
  392. package/dist/types/sync-historical/index.d.ts.map +1 -0
  393. package/dist/types/sync-realtime/bloom.d.ts +18 -0
  394. package/dist/types/sync-realtime/bloom.d.ts.map +1 -0
  395. package/dist/types/sync-realtime/index.d.ts +48 -0
  396. package/dist/types/sync-realtime/index.d.ts.map +1 -0
  397. package/dist/types/sync-store/encode.d.ts +25 -0
  398. package/dist/types/sync-store/encode.d.ts.map +1 -0
  399. package/dist/types/sync-store/index.d.ts +135 -0
  400. package/dist/types/sync-store/index.d.ts.map +1 -0
  401. package/dist/types/sync-store/migrations.d.ts +8 -0
  402. package/dist/types/sync-store/migrations.d.ts.map +1 -0
  403. package/dist/types/sync-store/schema.d.ts +1828 -0
  404. package/dist/types/sync-store/schema.d.ts.map +1 -0
  405. package/dist/types/types/db.d.ts +213 -0
  406. package/dist/types/types/db.d.ts.map +1 -0
  407. package/dist/types/types/eth.d.ts +196 -0
  408. package/dist/types/types/eth.d.ts.map +1 -0
  409. package/dist/types/types/utils.d.ts +38 -0
  410. package/dist/types/types/utils.d.ts.map +1 -0
  411. package/dist/types/types/virtual.d.ts +99 -0
  412. package/dist/types/types/virtual.d.ts.map +1 -0
  413. package/dist/types/ui/app.d.ts +22 -0
  414. package/dist/types/ui/app.d.ts.map +1 -0
  415. package/dist/types/ui/index.d.ts +5 -0
  416. package/dist/types/ui/index.d.ts.map +1 -0
  417. package/dist/types/ui/patch.d.ts +7 -0
  418. package/dist/types/ui/patch.d.ts.map +1 -0
  419. package/dist/types/utils/abi.d.ts +23 -0
  420. package/dist/types/utils/abi.d.ts.map +1 -0
  421. package/dist/types/utils/bigint.d.ts +15 -0
  422. package/dist/types/utils/bigint.d.ts.map +1 -0
  423. package/dist/types/utils/chains.d.ts +42 -0
  424. package/dist/types/utils/chains.d.ts.map +1 -0
  425. package/dist/types/utils/checkpoint.d.ts +52 -0
  426. package/dist/types/utils/checkpoint.d.ts.map +1 -0
  427. package/dist/types/utils/chunk.d.ts +2 -0
  428. package/dist/types/utils/chunk.d.ts.map +1 -0
  429. package/dist/types/utils/copy.d.ts +16 -0
  430. package/dist/types/utils/copy.d.ts.map +1 -0
  431. package/dist/types/utils/date.d.ts +7 -0
  432. package/dist/types/utils/date.d.ts.map +1 -0
  433. package/dist/types/utils/debug.d.ts +105 -0
  434. package/dist/types/utils/debug.d.ts.map +1 -0
  435. package/dist/types/utils/decodeAbiParameters.d.ts +28 -0
  436. package/dist/types/utils/decodeAbiParameters.d.ts.map +1 -0
  437. package/dist/types/utils/decodeEventLog.d.ts +12 -0
  438. package/dist/types/utils/decodeEventLog.d.ts.map +1 -0
  439. package/dist/types/utils/dedupe.d.ts +20 -0
  440. package/dist/types/utils/dedupe.d.ts.map +1 -0
  441. package/dist/types/utils/duplicates.d.ts +7 -0
  442. package/dist/types/utils/duplicates.d.ts.map +1 -0
  443. package/dist/types/utils/estimate.d.ts +11 -0
  444. package/dist/types/utils/estimate.d.ts.map +1 -0
  445. package/dist/types/utils/finality.d.ts +12 -0
  446. package/dist/types/utils/finality.d.ts.map +1 -0
  447. package/dist/types/utils/format.d.ts +3 -0
  448. package/dist/types/utils/format.d.ts.map +1 -0
  449. package/dist/types/utils/generators.d.ts +42 -0
  450. package/dist/types/utils/generators.d.ts.map +1 -0
  451. package/dist/types/utils/hash.d.ts +11 -0
  452. package/dist/types/utils/hash.d.ts.map +1 -0
  453. package/dist/types/utils/interval.d.ts +53 -0
  454. package/dist/types/utils/interval.d.ts.map +1 -0
  455. package/dist/types/utils/lowercase.d.ts +5 -0
  456. package/dist/types/utils/lowercase.d.ts.map +1 -0
  457. package/dist/types/utils/mutex.d.ts +5 -0
  458. package/dist/types/utils/mutex.d.ts.map +1 -0
  459. package/dist/types/utils/never.d.ts +2 -0
  460. package/dist/types/utils/never.d.ts.map +1 -0
  461. package/dist/types/utils/offset.d.ts +8 -0
  462. package/dist/types/utils/offset.d.ts.map +1 -0
  463. package/dist/types/utils/order.d.ts +2 -0
  464. package/dist/types/utils/order.d.ts.map +1 -0
  465. package/dist/types/utils/partition.d.ts +22 -0
  466. package/dist/types/utils/partition.d.ts.map +1 -0
  467. package/dist/types/utils/pg.d.ts +8 -0
  468. package/dist/types/utils/pg.d.ts.map +1 -0
  469. package/dist/types/utils/pglite.d.ts +25 -0
  470. package/dist/types/utils/pglite.d.ts.map +1 -0
  471. package/dist/types/utils/port.d.ts +5 -0
  472. package/dist/types/utils/port.d.ts.map +1 -0
  473. package/dist/types/utils/print.d.ts +2 -0
  474. package/dist/types/utils/print.d.ts.map +1 -0
  475. package/dist/types/utils/promiseAllSettledWithThrow.d.ts +8 -0
  476. package/dist/types/utils/promiseAllSettledWithThrow.d.ts.map +1 -0
  477. package/dist/types/utils/promiseWithResolvers.d.ts +10 -0
  478. package/dist/types/utils/promiseWithResolvers.d.ts.map +1 -0
  479. package/dist/types/utils/queue.d.ts +33 -0
  480. package/dist/types/utils/queue.d.ts.map +1 -0
  481. package/dist/types/utils/range.d.ts +8 -0
  482. package/dist/types/utils/range.d.ts.map +1 -0
  483. package/dist/types/utils/result.d.ts +17 -0
  484. package/dist/types/utils/result.d.ts.map +1 -0
  485. package/dist/types/utils/sql-parse.d.ts +21 -0
  486. package/dist/types/utils/sql-parse.d.ts.map +1 -0
  487. package/dist/types/utils/timer.d.ts +6 -0
  488. package/dist/types/utils/timer.d.ts.map +1 -0
  489. package/dist/types/utils/truncate.d.ts +9 -0
  490. package/dist/types/utils/truncate.d.ts.map +1 -0
  491. package/dist/types/utils/wait.d.ts +6 -0
  492. package/dist/types/utils/wait.d.ts.map +1 -0
  493. package/dist/types/utils/zipper.d.ts +36 -0
  494. package/dist/types/utils/zipper.d.ts.map +1 -0
  495. package/package.json +114 -0
  496. package/src/bin/commands/codegen.ts +56 -0
  497. package/src/bin/commands/createViews.ts +318 -0
  498. package/src/bin/commands/dev.ts +490 -0
  499. package/src/bin/commands/list.ts +208 -0
  500. package/src/bin/commands/prune.ts +322 -0
  501. package/src/bin/commands/serve.ts +236 -0
  502. package/src/bin/commands/start.ts +319 -0
  503. package/src/bin/isolatedController.ts +300 -0
  504. package/src/bin/isolatedWorker.ts +192 -0
  505. package/src/bin/ponder.ts +208 -0
  506. package/src/bin/utils/codegen.ts +32 -0
  507. package/src/bin/utils/exit.ts +112 -0
  508. package/src/build/config.ts +1141 -0
  509. package/src/build/factory.ts +147 -0
  510. package/src/build/index.ts +790 -0
  511. package/src/build/plugin.ts +58 -0
  512. package/src/build/pre.ts +114 -0
  513. package/src/build/schema.ts +358 -0
  514. package/src/build/stacktrace.ts +137 -0
  515. package/src/client/index.ts +551 -0
  516. package/src/config/address.ts +45 -0
  517. package/src/config/eventFilter.ts +33 -0
  518. package/src/config/index.ts +240 -0
  519. package/src/config/utilityTypes.ts +152 -0
  520. package/src/database/actions.ts +873 -0
  521. package/src/database/index.ts +1029 -0
  522. package/src/database/queryBuilder.ts +537 -0
  523. package/src/drizzle/bigint.ts +57 -0
  524. package/src/drizzle/bytes.ts +68 -0
  525. package/src/drizzle/hex.ts +58 -0
  526. package/src/drizzle/index.ts +40 -0
  527. package/src/drizzle/json.ts +159 -0
  528. package/src/drizzle/kit/index.ts +1348 -0
  529. package/src/drizzle/onchain.ts +476 -0
  530. package/src/drizzle/text.ts +77 -0
  531. package/src/graphql/graphiql.html.ts +59 -0
  532. package/src/graphql/index.ts +1351 -0
  533. package/src/graphql/json.ts +62 -0
  534. package/src/graphql/middleware.ts +115 -0
  535. package/src/index.ts +139 -0
  536. package/src/indexing/addStackTrace.ts +69 -0
  537. package/src/indexing/client.ts +1184 -0
  538. package/src/indexing/index.ts +976 -0
  539. package/src/indexing/profile.ts +771 -0
  540. package/src/indexing-store/cache.ts +1057 -0
  541. package/src/indexing-store/index.ts +628 -0
  542. package/src/indexing-store/profile.ts +557 -0
  543. package/src/indexing-store/utils.ts +162 -0
  544. package/src/internal/common.ts +15 -0
  545. package/src/internal/errors.ts +228 -0
  546. package/src/internal/logger.ts +252 -0
  547. package/src/internal/metrics.ts +1030 -0
  548. package/src/internal/options.ts +130 -0
  549. package/src/internal/shutdown.ts +32 -0
  550. package/src/internal/telemetry.ts +303 -0
  551. package/src/internal/types.ts +611 -0
  552. package/src/rpc/actions.ts +1344 -0
  553. package/src/rpc/http.ts +164 -0
  554. package/src/rpc/index.ts +959 -0
  555. package/src/runtime/events.ts +875 -0
  556. package/src/runtime/filter.ts +705 -0
  557. package/src/runtime/fragments.ts +674 -0
  558. package/src/runtime/historical.ts +1522 -0
  559. package/src/runtime/index.ts +569 -0
  560. package/src/runtime/init.ts +49 -0
  561. package/src/runtime/isolated.ts +775 -0
  562. package/src/runtime/multichain.ts +860 -0
  563. package/src/runtime/omnichain.ts +920 -0
  564. package/src/runtime/realtime.ts +1164 -0
  565. package/src/server/error.ts +68 -0
  566. package/src/server/index.ts +173 -0
  567. package/src/sync-historical/index.ts +1065 -0
  568. package/src/sync-realtime/bloom.ts +102 -0
  569. package/src/sync-realtime/index.ts +1304 -0
  570. package/src/sync-store/encode.ts +153 -0
  571. package/src/sync-store/index.ts +1633 -0
  572. package/src/sync-store/migrations.ts +1801 -0
  573. package/src/sync-store/schema.ts +248 -0
  574. package/src/types/db.ts +292 -0
  575. package/src/types/eth.ts +216 -0
  576. package/src/types/utils.ts +47 -0
  577. package/src/types/virtual.ts +244 -0
  578. package/src/types.d.ts +38 -0
  579. package/src/ui/app.ts +207 -0
  580. package/src/ui/index.ts +37 -0
  581. package/src/ui/patch.ts +204 -0
  582. package/src/utils/abi.ts +103 -0
  583. package/src/utils/bigint.ts +41 -0
  584. package/src/utils/chains.ts +22 -0
  585. package/src/utils/checkpoint.ts +203 -0
  586. package/src/utils/chunk.ts +7 -0
  587. package/src/utils/copy.ts +151 -0
  588. package/src/utils/date.ts +26 -0
  589. package/src/utils/debug.ts +110 -0
  590. package/src/utils/decodeAbiParameters.ts +428 -0
  591. package/src/utils/decodeEventLog.ts +100 -0
  592. package/src/utils/dedupe.ts +32 -0
  593. package/src/utils/duplicates.ts +19 -0
  594. package/src/utils/estimate.ts +27 -0
  595. package/src/utils/finality.ts +40 -0
  596. package/src/utils/format.ts +22 -0
  597. package/src/utils/generators.ts +157 -0
  598. package/src/utils/hash.ts +22 -0
  599. package/src/utils/interval.ts +212 -0
  600. package/src/utils/lowercase.ts +6 -0
  601. package/src/utils/mutex.ts +33 -0
  602. package/src/utils/never.ts +3 -0
  603. package/src/utils/offset.ts +133 -0
  604. package/src/utils/order.ts +16 -0
  605. package/src/utils/partition.ts +53 -0
  606. package/src/utils/pg.ts +230 -0
  607. package/src/utils/pglite.ts +97 -0
  608. package/src/utils/port.ts +34 -0
  609. package/src/utils/print.ts +31 -0
  610. package/src/utils/promiseAllSettledWithThrow.ts +27 -0
  611. package/src/utils/promiseWithResolvers.ts +20 -0
  612. package/src/utils/queue.ts +258 -0
  613. package/src/utils/range.ts +8 -0
  614. package/src/utils/result.ts +26 -0
  615. package/src/utils/sql-parse.ts +1477 -0
  616. package/src/utils/timer.ts +8 -0
  617. package/src/utils/truncate.ts +15 -0
  618. package/src/utils/wait.ts +8 -0
  619. package/src/utils/zipper.ts +80 -0
@@ -0,0 +1,1351 @@
1
+ import type { QB } from "@/database/queryBuilder.js";
2
+ import { getPrimaryKeyColumns } from "@/drizzle/index.js";
3
+ import type { OnchainTable } from "@/drizzle/onchain.js";
4
+ import { normalizeColumn } from "@/indexing-store/utils.js";
5
+ import type { Schema, Status } from "@/internal/types.js";
6
+ import { decodeCheckpoint } from "@/utils/checkpoint.js";
7
+ import { never } from "@/utils/never.js";
8
+ import DataLoader from "dataloader";
9
+ import {
10
+ type Column,
11
+ Many,
12
+ One,
13
+ SQL,
14
+ type TableRelationalConfig,
15
+ and,
16
+ arrayContained,
17
+ arrayContains,
18
+ asc,
19
+ count,
20
+ createTableRelationsHelpers,
21
+ desc,
22
+ eq,
23
+ extractTablesRelationalConfig,
24
+ getTableColumns,
25
+ gt,
26
+ gte,
27
+ inArray,
28
+ is,
29
+ isNotNull,
30
+ isNull,
31
+ like,
32
+ lt,
33
+ lte,
34
+ ne,
35
+ not,
36
+ notInArray,
37
+ notLike,
38
+ or,
39
+ } from "drizzle-orm";
40
+ import {
41
+ PgBigInt53,
42
+ type PgColumn,
43
+ type PgEnum,
44
+ PgEnumColumn,
45
+ PgInteger,
46
+ PgSerial,
47
+ type PgTable,
48
+ PgView,
49
+ getViewConfig,
50
+ isPgEnum,
51
+ isPgView,
52
+ } from "drizzle-orm/pg-core";
53
+ import {
54
+ GraphQLBoolean,
55
+ GraphQLEnumType,
56
+ type GraphQLFieldConfig,
57
+ type GraphQLFieldConfigMap,
58
+ GraphQLFloat,
59
+ type GraphQLInputFieldConfigMap,
60
+ GraphQLInputObjectType,
61
+ type GraphQLInputType,
62
+ GraphQLInt,
63
+ GraphQLList,
64
+ GraphQLNonNull,
65
+ GraphQLObjectType,
66
+ type GraphQLOutputType,
67
+ type GraphQLResolveInfo,
68
+ GraphQLScalarType,
69
+ GraphQLSchema,
70
+ GraphQLString,
71
+ } from "graphql";
72
+ import superjson from "superjson";
73
+ import { GraphQLJSON } from "./json.js";
74
+
75
+ type Parent = Record<string, any>;
76
+ type Context = {
77
+ qb: QB<{ [key: string]: OnchainTable }>;
78
+ getDataLoader: ReturnType<typeof buildDataLoaderCache>;
79
+ };
80
+
81
+ type PluralArgs = {
82
+ where?: { [key: string]: number | string };
83
+ after?: string;
84
+ before?: string;
85
+ limit?: number;
86
+ offset?: number;
87
+ orderBy?: string;
88
+ orderDirection?: "asc" | "desc";
89
+ };
90
+
91
+ const DEFAULT_LIMIT = 50 as const;
92
+ const MAX_LIMIT = 1000 as const;
93
+
94
+ export function buildGraphQLSchema({
95
+ schema,
96
+ }: { schema: Schema }): GraphQLSchema {
97
+ const tablesConfig = extractTablesRelationalConfig(
98
+ schema,
99
+ createTableRelationsHelpers,
100
+ );
101
+
102
+ const tables = Object.values(tablesConfig.tables) as TableRelationalConfig[];
103
+
104
+ const views = Object.entries(schema).filter((el): el is [string, PgView] =>
105
+ isPgView(el[1]),
106
+ );
107
+
108
+ const enums = Object.entries(schema).filter(
109
+ (el): el is [string, PgEnum<[string, ...string[]]>] => isPgEnum(el[1]),
110
+ );
111
+ const enumTypes: Record<string, GraphQLEnumType> = {};
112
+ for (const [enumTsName, enumObject] of enums) {
113
+ // Note that this is keyed by enumName (the SQL name) because that's what is
114
+ // available on the PgEnumColumn type. See `columnToGraphQLCore` for context.
115
+ enumTypes[enumObject.enumName] = new GraphQLEnumType({
116
+ name: enumTsName,
117
+ values: enumObject.enumValues.reduce(
118
+ (acc: Record<string, {}>, cur) => ({ ...acc, [cur]: {} }),
119
+ {},
120
+ ),
121
+ });
122
+ }
123
+
124
+ const entityFilterTypes: Record<string, GraphQLInputObjectType> = {};
125
+ for (const table of tables) {
126
+ const filterType = new GraphQLInputObjectType({
127
+ name: `${table.tsName}Filter`,
128
+ fields: () => {
129
+ const filterFields: GraphQLInputFieldConfigMap = {
130
+ // Logical operators
131
+ AND: { type: new GraphQLList(filterType) },
132
+ OR: { type: new GraphQLList(filterType) },
133
+ };
134
+
135
+ for (const [columnName, column] of Object.entries(table.columns)) {
136
+ const type = columnToGraphQLCore(column, enumTypes);
137
+
138
+ // List fields => universal, plural
139
+ if (type instanceof GraphQLList) {
140
+ const baseType = innerType(type);
141
+
142
+ conditionSuffixes.universal.forEach((suffix) => {
143
+ filterFields[`${columnName}${suffix}`] = {
144
+ type: new GraphQLList(baseType),
145
+ };
146
+ });
147
+
148
+ conditionSuffixes.plural.forEach((suffix) => {
149
+ filterFields[`${columnName}${suffix}`] = { type: baseType };
150
+ });
151
+ }
152
+
153
+ // JSON => no filters.
154
+ // Boolean => universal and singular only.
155
+ // All other scalar => universal, singular, numeric OR string depending on type
156
+ if (
157
+ type instanceof GraphQLScalarType ||
158
+ type instanceof GraphQLEnumType
159
+ ) {
160
+ if (type.name === "JSON") continue;
161
+
162
+ conditionSuffixes.universal.forEach((suffix) => {
163
+ filterFields[`${columnName}${suffix}`] = {
164
+ type,
165
+ };
166
+ });
167
+
168
+ conditionSuffixes.singular.forEach((suffix) => {
169
+ filterFields[`${columnName}${suffix}`] = {
170
+ type: new GraphQLList(type),
171
+ };
172
+ });
173
+
174
+ if (["String", "ID"].includes(type.name)) {
175
+ conditionSuffixes.string.forEach((suffix) => {
176
+ filterFields[`${columnName}${suffix}`] = {
177
+ type: type,
178
+ };
179
+ });
180
+ }
181
+
182
+ if (["Int", "Float", "BigInt", "Numeric"].includes(type.name)) {
183
+ conditionSuffixes.numeric.forEach((suffix) => {
184
+ filterFields[`${columnName}${suffix}`] = {
185
+ type: type,
186
+ };
187
+ });
188
+ }
189
+ }
190
+ }
191
+
192
+ return filterFields;
193
+ },
194
+ });
195
+ entityFilterTypes[table.tsName] = filterType;
196
+ }
197
+
198
+ for (const [viewName, view] of views) {
199
+ const viewConfig = getViewConfig(view);
200
+ const filterType = new GraphQLInputObjectType({
201
+ name: `${viewName}Filter`,
202
+ fields: () => {
203
+ const filterFields: GraphQLInputFieldConfigMap = {
204
+ // Logical operators
205
+ AND: { type: new GraphQLList(filterType) },
206
+ OR: { type: new GraphQLList(filterType) },
207
+ };
208
+
209
+ for (const [columnName, column] of Object.entries(
210
+ viewConfig.selectedFields,
211
+ )) {
212
+ if (is(column, SQL.Aliased)) {
213
+ // Note: Aliased column filters are not supported by GraphQL because they don't have an associated type.
214
+ continue;
215
+ }
216
+ const type = columnToGraphQLCore(column as PgColumn, enumTypes);
217
+
218
+ // List fields => universal, plural
219
+ if (type instanceof GraphQLList) {
220
+ const baseType = innerType(type);
221
+
222
+ conditionSuffixes.universal.forEach((suffix) => {
223
+ filterFields[`${columnName}${suffix}`] = {
224
+ type: new GraphQLList(baseType),
225
+ };
226
+ });
227
+
228
+ conditionSuffixes.plural.forEach((suffix) => {
229
+ filterFields[`${columnName}${suffix}`] = { type: baseType };
230
+ });
231
+ }
232
+
233
+ // JSON => no filters.
234
+ // Boolean => universal and singular only.
235
+ // All other scalar => universal, singular, numeric OR string depending on type
236
+ if (
237
+ type instanceof GraphQLScalarType ||
238
+ type instanceof GraphQLEnumType
239
+ ) {
240
+ if (type.name === "JSON") continue;
241
+
242
+ conditionSuffixes.universal.forEach((suffix) => {
243
+ filterFields[`${columnName}${suffix}`] = {
244
+ type,
245
+ };
246
+ });
247
+
248
+ conditionSuffixes.singular.forEach((suffix) => {
249
+ filterFields[`${columnName}${suffix}`] = {
250
+ type: new GraphQLList(type),
251
+ };
252
+ });
253
+
254
+ if (["String", "ID"].includes(type.name)) {
255
+ conditionSuffixes.string.forEach((suffix) => {
256
+ filterFields[`${columnName}${suffix}`] = {
257
+ type: type,
258
+ };
259
+ });
260
+ }
261
+
262
+ if (["Int", "Float", "BigInt", "Numeric"].includes(type.name)) {
263
+ conditionSuffixes.numeric.forEach((suffix) => {
264
+ filterFields[`${columnName}${suffix}`] = {
265
+ type: type,
266
+ };
267
+ });
268
+ }
269
+ }
270
+ }
271
+
272
+ return filterFields;
273
+ },
274
+ });
275
+ entityFilterTypes[viewName] = filterType;
276
+ }
277
+
278
+ const entityTypes: Record<string, GraphQLObjectType<Parent, Context>> = {};
279
+ const entityPageTypes: Record<string, GraphQLObjectType> = {};
280
+
281
+ for (const table of tables) {
282
+ entityTypes[table.tsName] = new GraphQLObjectType({
283
+ name: table.tsName,
284
+ fields: () => {
285
+ const fieldConfigMap: GraphQLFieldConfigMap<Parent, Context> = {};
286
+
287
+ // Scalar fields
288
+ for (const [columnName, column] of Object.entries(table.columns)) {
289
+ const type = columnToGraphQLCore(column, enumTypes);
290
+ fieldConfigMap[columnName] = {
291
+ type: column.notNull ? new GraphQLNonNull(type) : type,
292
+ };
293
+ }
294
+
295
+ // Relations
296
+ const relations = Object.entries(table.relations);
297
+ for (const [relationName, relation] of relations) {
298
+ const referencedTable = tables.find(
299
+ (table) => table.dbName === relation.referencedTableName,
300
+ );
301
+ if (!referencedTable)
302
+ throw new Error(
303
+ `Internal error: Referenced table "${relation.referencedTableName}" not found`,
304
+ );
305
+
306
+ const referencedEntityType = entityTypes[referencedTable.tsName];
307
+ const referencedEntityPageType =
308
+ entityPageTypes[referencedTable.tsName];
309
+ const referencedEntityFilterType =
310
+ entityFilterTypes[referencedTable.tsName];
311
+ if (
312
+ referencedEntityType === undefined ||
313
+ referencedEntityPageType === undefined ||
314
+ referencedEntityFilterType === undefined
315
+ )
316
+ throw new Error(
317
+ `Internal error: Referenced entity types not found for table "${referencedTable.tsName}" `,
318
+ );
319
+
320
+ if (is(relation, One)) {
321
+ const fields = relation.config?.fields ?? [];
322
+ const references = relation.config?.references ?? [];
323
+
324
+ if (fields.length !== references.length) {
325
+ throw new Error(
326
+ "Internal error: Fields and references arrays must be the same length",
327
+ );
328
+ }
329
+
330
+ fieldConfigMap[relationName] = {
331
+ // Note: There is a `relation.isNullable` field here but it appears
332
+ // to be internal / incorrect. Until we have support for foreign
333
+ // key constraints, all `one` relations must be nullable.
334
+ type: referencedEntityType,
335
+ resolve: (parent, _args, context) => {
336
+ const loader = context.getDataLoader({
337
+ table: referencedTable,
338
+ });
339
+
340
+ const rowFragment: Record<string, unknown> = {};
341
+ for (let i = 0; i < references.length; i++) {
342
+ const referenceColumn = references[i]!;
343
+ const fieldColumn = fields[i]!;
344
+
345
+ const fieldColumnTsName = getColumnTsName(fieldColumn);
346
+ const referenceColumnTsName =
347
+ getColumnTsName(referenceColumn);
348
+
349
+ rowFragment[referenceColumnTsName] =
350
+ parent[fieldColumnTsName];
351
+ }
352
+ const encodedId = encodeRowFragment(rowFragment);
353
+
354
+ return loader.load(encodedId);
355
+ },
356
+ };
357
+ } else if (is(relation, Many)) {
358
+ // Search the relations of the referenced table for the corresponding `one` relation.
359
+ // If `relation.relationName` is not provided, use the first `one` relation that references this table.
360
+
361
+ let oneRelation: One | undefined;
362
+
363
+ // Note: can find the wrong relation if `relationName` is undefined.
364
+ // The first relation will be found.
365
+
366
+ if (relation.relationName !== undefined) {
367
+ for (const referencedRelation of Object.values(
368
+ referencedTable.relations,
369
+ )) {
370
+ if (
371
+ is(referencedRelation, One) &&
372
+ relation.relationName === referencedRelation.relationName
373
+ ) {
374
+ oneRelation = referencedRelation;
375
+ break;
376
+ }
377
+ }
378
+ }
379
+
380
+ if (oneRelation === undefined) {
381
+ for (const referencedRelation of Object.values(
382
+ referencedTable.relations,
383
+ )) {
384
+ if (
385
+ is(referencedRelation, One) &&
386
+ table.dbName === referencedRelation.referencedTableName
387
+ ) {
388
+ oneRelation = referencedRelation;
389
+ break;
390
+ }
391
+ }
392
+ }
393
+
394
+ if (oneRelation === undefined) {
395
+ throw new Error(
396
+ `Internal error: Relation "${relationName}" not found in table "${referencedTable.tsName}"`,
397
+ );
398
+ }
399
+
400
+ const fields = oneRelation.config?.fields ?? [];
401
+ const references = oneRelation.config?.references ?? [];
402
+
403
+ fieldConfigMap[relationName] = {
404
+ type: referencedEntityPageType,
405
+ args: {
406
+ where: { type: referencedEntityFilterType },
407
+ orderBy: { type: GraphQLString },
408
+ orderDirection: { type: GraphQLString },
409
+ before: { type: GraphQLString },
410
+ after: { type: GraphQLString },
411
+ limit: { type: GraphQLInt },
412
+ offset: { type: GraphQLInt },
413
+ },
414
+ resolve: (parent, args: PluralArgs, context, info) => {
415
+ const relationalConditions = [];
416
+ for (let i = 0; i < references.length; i++) {
417
+ const column = fields[i]!;
418
+ const value = parent[getColumnTsName(references[i]!)];
419
+ relationalConditions.push(eq(column, value));
420
+ }
421
+
422
+ const includeTotalCount = selectionIncludesField(
423
+ info,
424
+ "totalCount",
425
+ );
426
+
427
+ return executePluralQuery(
428
+ schema[referencedTable.tsName] as PgTable,
429
+ referencedTable.columns,
430
+ context.qb,
431
+ args,
432
+ includeTotalCount,
433
+ relationalConditions,
434
+ );
435
+ },
436
+ };
437
+ } else {
438
+ throw new Error(
439
+ `Internal error: Relation "${relationName}" is unsupported, expected One or Many`,
440
+ );
441
+ }
442
+ }
443
+
444
+ return fieldConfigMap;
445
+ },
446
+ });
447
+
448
+ entityPageTypes[table.tsName] = new GraphQLObjectType({
449
+ name: `${table.tsName}Page`,
450
+ fields: () => ({
451
+ items: {
452
+ type: new GraphQLNonNull(
453
+ new GraphQLList(new GraphQLNonNull(entityTypes[table.tsName]!)),
454
+ ),
455
+ },
456
+ pageInfo: { type: new GraphQLNonNull(GraphQLPageInfo) },
457
+ totalCount: { type: new GraphQLNonNull(GraphQLInt) },
458
+ }),
459
+ });
460
+ }
461
+
462
+ for (const [viewName, view] of views) {
463
+ entityTypes[viewName] = new GraphQLObjectType({
464
+ name: viewName,
465
+ fields: () => {
466
+ const fieldConfigMap: GraphQLFieldConfigMap<Parent, Context> = {};
467
+
468
+ const viewConfig = getViewConfig(view);
469
+
470
+ // Scalar fields
471
+ for (const [columnName, column] of Object.entries(
472
+ viewConfig.selectedFields,
473
+ )) {
474
+ if (is(column, SQL.Aliased)) {
475
+ fieldConfigMap[columnName] = { type: GraphQLJSON };
476
+ } else {
477
+ const type = columnToGraphQLCore(column as PgColumn, enumTypes);
478
+ fieldConfigMap[columnName] = {
479
+ type: (column as PgColumn).notNull
480
+ ? new GraphQLNonNull(type)
481
+ : type,
482
+ };
483
+ }
484
+ }
485
+
486
+ return fieldConfigMap;
487
+ },
488
+ });
489
+
490
+ entityPageTypes[viewName] = new GraphQLObjectType({
491
+ name: `${viewName}Page`,
492
+ fields: () => ({
493
+ items: {
494
+ type: new GraphQLNonNull(
495
+ new GraphQLList(new GraphQLNonNull(entityTypes[viewName]!)),
496
+ ),
497
+ },
498
+ pageInfo: { type: new GraphQLNonNull(GraphQLViewPageInfo) },
499
+ totalCount: { type: new GraphQLNonNull(GraphQLInt) },
500
+ }),
501
+ });
502
+ }
503
+
504
+ const queryFields: Record<string, GraphQLFieldConfig<Parent, Context>> = {};
505
+ for (const table of tables) {
506
+ const entityType = entityTypes[table.tsName]!;
507
+ const entityPageType = entityPageTypes[table.tsName]!;
508
+ const entityFilterType = entityFilterTypes[table.tsName]!;
509
+
510
+ const singularFieldName =
511
+ table.tsName.charAt(0).toLowerCase() + table.tsName.slice(1);
512
+ const pluralFieldName = `${singularFieldName}s`;
513
+
514
+ queryFields[singularFieldName] = {
515
+ type: entityType,
516
+ // Find the primary key columns and GraphQL core types and include them
517
+ // as arguments to the singular query type.
518
+ args: Object.fromEntries(
519
+ table.primaryKey.map((column) => [
520
+ getColumnTsName(column),
521
+ {
522
+ type: new GraphQLNonNull(
523
+ columnToGraphQLCore(column, enumTypes) as GraphQLInputType,
524
+ ),
525
+ },
526
+ ]),
527
+ ),
528
+ resolve: async (_parent, args, context) => {
529
+ const loader = context.getDataLoader({ table });
530
+
531
+ // The `args` object here should be a valid `where` argument that
532
+ // uses the `eq` shorthand for each primary key column.
533
+ const encodedId = encodeRowFragment(args);
534
+
535
+ return loader.load(encodedId);
536
+ },
537
+ };
538
+
539
+ queryFields[pluralFieldName] = {
540
+ type: new GraphQLNonNull(entityPageType),
541
+ args: {
542
+ where: { type: entityFilterType },
543
+ orderBy: { type: GraphQLString },
544
+ orderDirection: { type: GraphQLString },
545
+ before: { type: GraphQLString },
546
+ after: { type: GraphQLString },
547
+ limit: { type: GraphQLInt },
548
+ offset: { type: GraphQLInt },
549
+ },
550
+ resolve: async (_parent, args: PluralArgs, context, info) => {
551
+ const includeTotalCount = selectionIncludesField(info, "totalCount");
552
+
553
+ return executePluralQuery(
554
+ schema[table.tsName] as PgTable,
555
+ table.columns,
556
+ context.qb,
557
+ args,
558
+ includeTotalCount,
559
+ );
560
+ },
561
+ };
562
+ }
563
+ for (const [viewName, view] of views) {
564
+ const viewConfig = getViewConfig(view);
565
+ const entityPageType = entityPageTypes[viewName]!;
566
+ const entityFilterType = entityFilterTypes[viewName]!;
567
+
568
+ const singularFieldName =
569
+ viewName.charAt(0).toLowerCase() + viewName.slice(1);
570
+ const pluralFieldName = `${singularFieldName}s`;
571
+
572
+ queryFields[pluralFieldName] = {
573
+ type: new GraphQLNonNull(entityPageType),
574
+ args: {
575
+ where: { type: entityFilterType },
576
+ orderBy: { type: GraphQLString },
577
+ orderDirection: { type: GraphQLString },
578
+ limit: { type: GraphQLInt },
579
+ offset: { type: GraphQLInt },
580
+ },
581
+ resolve: async (_parent, args: PluralArgs, context, info) => {
582
+ const includeTotalCount = selectionIncludesField(info, "totalCount");
583
+
584
+ return executePluralQuery(
585
+ view,
586
+ viewConfig.selectedFields as Record<string, Column>,
587
+ context.qb,
588
+ args,
589
+ includeTotalCount,
590
+ );
591
+ },
592
+ };
593
+ }
594
+
595
+ queryFields._meta = {
596
+ type: GraphQLMeta,
597
+ resolve: async (_source, _args, context) => {
598
+ // Note: This is done to avoid non-browser compatible dependencies
599
+ const checkpoints = (await context.qb
600
+ .wrap({ label: "select_checkpoints" }, (db) =>
601
+ db.execute(
602
+ "SELECT chain_name, chain_id, latest_checkpoint, safe_checkpoint from _ponder_checkpoint",
603
+ ),
604
+ )
605
+ .then((res) => res.rows)) as {
606
+ chain_name: string;
607
+ chain_id: string;
608
+ latest_checkpoint: string;
609
+ safe_checkpoint: string;
610
+ }[];
611
+
612
+ const status: Status = {};
613
+ for (const {
614
+ chain_name,
615
+ chain_id,
616
+ latest_checkpoint,
617
+ } of checkpoints.sort((a, b) => (a.chain_id > b.chain_id ? 1 : -1))) {
618
+ status[chain_name] = {
619
+ id: Number(chain_id),
620
+ block: {
621
+ number: Number(decodeCheckpoint(latest_checkpoint).blockNumber),
622
+ timestamp: Number(
623
+ decodeCheckpoint(latest_checkpoint).blockTimestamp,
624
+ ),
625
+ },
626
+ };
627
+ }
628
+ return { status };
629
+ },
630
+ };
631
+
632
+ return new GraphQLSchema({
633
+ // Include these here so they are listed first in the printed schema.
634
+ types: [
635
+ GraphQLJSON,
636
+ GraphQLBigInt,
637
+ GraphQLPageInfo,
638
+ GraphQLViewPageInfo,
639
+ GraphQLMeta,
640
+ ],
641
+ query: new GraphQLObjectType({
642
+ name: "Query",
643
+ fields: queryFields,
644
+ }),
645
+ });
646
+ }
647
+
648
+ const GraphQLPageInfo = new GraphQLObjectType({
649
+ name: "PageInfo",
650
+ fields: {
651
+ hasNextPage: { type: new GraphQLNonNull(GraphQLBoolean) },
652
+ hasPreviousPage: { type: new GraphQLNonNull(GraphQLBoolean) },
653
+ startCursor: { type: GraphQLString },
654
+ endCursor: { type: GraphQLString },
655
+ },
656
+ });
657
+
658
+ const GraphQLViewPageInfo = new GraphQLObjectType({
659
+ name: "ViewPageInfo",
660
+ fields: {
661
+ hasNextPage: { type: new GraphQLNonNull(GraphQLBoolean) },
662
+ hasPreviousPage: { type: new GraphQLNonNull(GraphQLBoolean) },
663
+ },
664
+ });
665
+
666
+ const GraphQLBigInt = new GraphQLScalarType({
667
+ name: "BigInt",
668
+ serialize: (value) => String(value),
669
+ parseValue: (value) => BigInt(value as any),
670
+ parseLiteral: (value) => {
671
+ if (value.kind === "StringValue") {
672
+ return BigInt(value.value);
673
+ } else {
674
+ throw new Error(
675
+ `Invalid value kind provided for field of type BigInt: ${value.kind}. Expected: StringValue`,
676
+ );
677
+ }
678
+ },
679
+ });
680
+
681
+ const GraphQLNumeric = new GraphQLScalarType({
682
+ name: "Numeric",
683
+ serialize: (value) => String(value),
684
+ parseValue: (value) => String(value as any),
685
+ parseLiteral: (value) => {
686
+ if (value.kind === "StringValue") {
687
+ return String(value.value);
688
+ } else {
689
+ throw new Error(
690
+ `Invalid value kind provided for field of type BigInt: ${value.kind}. Expected: StringValue`,
691
+ );
692
+ }
693
+ },
694
+ });
695
+
696
+ const GraphQLMeta = new GraphQLObjectType({
697
+ name: "Meta",
698
+ fields: { status: { type: GraphQLJSON } },
699
+ });
700
+
701
+ const columnToGraphQLCore = (
702
+ column: Column,
703
+ enumTypes: Record<string, GraphQLEnumType>,
704
+ ): GraphQLOutputType => {
705
+ if (column.columnType === "PgEvmBigint") {
706
+ return GraphQLBigInt;
707
+ }
708
+
709
+ if (column.columnType === "PgNumeric") {
710
+ return GraphQLNumeric;
711
+ }
712
+
713
+ if (column instanceof PgEnumColumn) {
714
+ if (column.enum === undefined) {
715
+ throw new Error(
716
+ `Internal error: Expected enum column "${getColumnTsName(column)}" to have an "enum" property`,
717
+ );
718
+ }
719
+ const enumType = enumTypes[column.enum.enumName];
720
+ if (enumType === undefined) {
721
+ throw new Error(
722
+ `Internal error: Expected to find a GraphQL enum named "${column.enum.enumName}". This may happen if "${column.enum.enumName}" has not been exported from your Ponder schema`,
723
+ );
724
+ }
725
+
726
+ return enumType;
727
+ }
728
+
729
+ switch (column.dataType) {
730
+ case "boolean":
731
+ return GraphQLBoolean;
732
+ case "json":
733
+ return GraphQLJSON;
734
+ case "date":
735
+ return GraphQLString;
736
+ case "string":
737
+ return GraphQLString;
738
+ case "bigint":
739
+ return GraphQLBigInt;
740
+ case "number":
741
+ return is(column, PgInteger) ||
742
+ is(column, PgSerial) ||
743
+ is(column, PgBigInt53)
744
+ ? GraphQLInt
745
+ : GraphQLFloat;
746
+ case "buffer":
747
+ return new GraphQLList(new GraphQLNonNull(GraphQLInt));
748
+ case "array": {
749
+ if (column.columnType === "PgVector") {
750
+ return new GraphQLList(new GraphQLNonNull(GraphQLFloat));
751
+ }
752
+
753
+ if (column.columnType === "PgGeometry") {
754
+ return new GraphQLList(new GraphQLNonNull(GraphQLFloat));
755
+ }
756
+
757
+ const innerType = columnToGraphQLCore(
758
+ (column as any).baseColumn,
759
+ enumTypes,
760
+ );
761
+
762
+ return new GraphQLList(new GraphQLNonNull(innerType));
763
+ }
764
+ default:
765
+ throw new Error(`Type ${column.dataType} is not implemented`);
766
+ }
767
+ };
768
+
769
+ const innerType = (
770
+ type: GraphQLOutputType,
771
+ ): GraphQLScalarType | GraphQLEnumType => {
772
+ if (type instanceof GraphQLScalarType || type instanceof GraphQLEnumType)
773
+ return type;
774
+ if (type instanceof GraphQLList || type instanceof GraphQLNonNull)
775
+ return innerType(type.ofType);
776
+ throw new Error(`Type ${type.toString()} is not implemented`);
777
+ };
778
+
779
+ async function executePluralQuery(
780
+ relation: PgTable | PgView,
781
+ columns: Record<string, Column>,
782
+ qb: QB<{ [key: string]: OnchainTable }>,
783
+ args: PluralArgs,
784
+ includeTotalCount: boolean,
785
+ extraConditions: (SQL | undefined)[] = [],
786
+ ) {
787
+ const limit = args.limit ?? DEFAULT_LIMIT;
788
+ const offset = args.offset ?? 0;
789
+
790
+ if (limit > MAX_LIMIT) {
791
+ throw new Error(`Invalid limit. Got ${limit}, expected <=${MAX_LIMIT}.`);
792
+ }
793
+
794
+ const orderBySchema = buildOrderBySchema(relation, args);
795
+ const orderBy = orderBySchema.map(([columnName, direction]) => {
796
+ const column = columns[columnName];
797
+ if (column === undefined) {
798
+ throw new Error(
799
+ `Unknown column "${columnName}" used in orderBy argument`,
800
+ );
801
+ }
802
+ return direction === "asc" ? asc(column) : desc(column);
803
+ });
804
+ const orderByReversed = orderBySchema.map(([columnName, direction]) => {
805
+ const column = columns[columnName];
806
+ if (column === undefined) {
807
+ throw new Error(
808
+ `Unknown column "${columnName}" used in orderBy argument`,
809
+ );
810
+ }
811
+ return direction === "asc" ? desc(column) : asc(column);
812
+ });
813
+
814
+ const whereConditions = buildWhereConditions(args.where, columns);
815
+
816
+ const after = args.after ?? null;
817
+ const before = args.before ?? null;
818
+
819
+ if (after !== null && before !== null) {
820
+ throw new Error("Cannot specify both before and after cursors.");
821
+ }
822
+ if (after !== null && offset > 0) {
823
+ throw new Error("Cannot specify both after cursor and offset.");
824
+ }
825
+ if (before !== null && offset > 0) {
826
+ throw new Error("Cannot specify both before cursor and offset.");
827
+ }
828
+
829
+ let startCursor = null;
830
+ let endCursor = null;
831
+ let hasPreviousPage = false;
832
+ let hasNextPage = false;
833
+
834
+ const totalCountPromise = includeTotalCount
835
+ ? qb
836
+ .wrap((db) =>
837
+ db
838
+ .select({ count: count() })
839
+ .from(relation)
840
+ .where(and(...whereConditions, ...extraConditions)),
841
+ )
842
+ .then((rows) => rows[0]?.count ?? null)
843
+ : Promise.resolve(null);
844
+
845
+ // Neither cursors are specified, apply the order conditions and execute.
846
+ if (after === null && before === null) {
847
+ const [rows, totalCount] = await Promise.all([
848
+ qb.raw
849
+ .select()
850
+ .from(relation)
851
+ .where(and(...whereConditions, ...extraConditions))
852
+ .orderBy(...orderBy)
853
+ .limit(limit + 1)
854
+ .offset(offset),
855
+ totalCountPromise,
856
+ ]);
857
+
858
+ if (rows.length === limit + 1) {
859
+ rows.pop();
860
+ hasNextPage = true;
861
+ }
862
+
863
+ if (offset === 0) {
864
+ startCursor =
865
+ rows.length > 0 ? encodeCursor(orderBySchema, rows[0]!) : null;
866
+ endCursor =
867
+ rows.length > 0
868
+ ? encodeCursor(orderBySchema, rows[rows.length - 1]!)
869
+ : null;
870
+ } else {
871
+ hasPreviousPage = true;
872
+ }
873
+
874
+ return {
875
+ items: rows,
876
+ totalCount,
877
+ pageInfo: { hasNextPage, hasPreviousPage, startCursor, endCursor },
878
+ };
879
+ }
880
+
881
+ if (after !== null) {
882
+ // User specified an 'after' cursor.
883
+ const cursorObject = decodeCursor(after);
884
+ const cursorCondition = buildCursorCondition(
885
+ columns,
886
+ orderBySchema,
887
+ "after",
888
+ cursorObject,
889
+ );
890
+
891
+ const [rows, totalCount] = await Promise.all([
892
+ qb.raw
893
+ .select()
894
+ .from(relation)
895
+ .where(and(...whereConditions, cursorCondition, ...extraConditions))
896
+ .orderBy(...orderBy)
897
+ .limit(limit + 2)
898
+ .offset(offset),
899
+ totalCountPromise,
900
+ ]);
901
+
902
+ if (rows.length === 0) {
903
+ return {
904
+ items: rows,
905
+ totalCount,
906
+ pageInfo: { hasNextPage, hasPreviousPage, startCursor, endCursor },
907
+ };
908
+ }
909
+
910
+ // If the cursor of the first returned record equals the `after` cursor,
911
+ // `hasPreviousPage` is true. Remove that record.
912
+ if (encodeCursor(orderBySchema, rows[0]!) === after) {
913
+ rows.shift();
914
+ hasPreviousPage = true;
915
+ } else {
916
+ // Otherwise, remove the last record.
917
+ rows.pop();
918
+ }
919
+
920
+ // Now if the length of the records is still equal to limit + 1,
921
+ // there is a next page.
922
+ if (rows.length === limit + 1) {
923
+ rows.pop();
924
+ hasNextPage = true;
925
+ }
926
+
927
+ // Now calculate the cursors.
928
+ startCursor =
929
+ rows.length > 0 ? encodeCursor(orderBySchema, rows[0]!) : null;
930
+ endCursor =
931
+ rows.length > 0
932
+ ? encodeCursor(orderBySchema, rows[rows.length - 1]!)
933
+ : null;
934
+
935
+ return {
936
+ items: rows,
937
+ totalCount,
938
+ pageInfo: { hasNextPage, hasPreviousPage, startCursor, endCursor },
939
+ };
940
+ }
941
+
942
+ // User specified a 'before' cursor.
943
+ const cursorObject = decodeCursor(before!);
944
+ const cursorCondition = buildCursorCondition(
945
+ columns,
946
+ orderBySchema,
947
+ "before",
948
+ cursorObject,
949
+ );
950
+
951
+ // Reverse the order by conditions to get the previous page,
952
+ // then reverse the results back to the original order.
953
+ const [rows, totalCount] = await Promise.all([
954
+ qb.raw
955
+ .select()
956
+ .from(relation)
957
+ .where(and(...whereConditions, cursorCondition, ...extraConditions))
958
+ .orderBy(...orderByReversed)
959
+ .limit(limit + 2)
960
+ .offset(offset)
961
+ .then((rows) => rows.reverse()),
962
+ totalCountPromise,
963
+ ]);
964
+
965
+ if (rows.length === 0) {
966
+ return {
967
+ items: rows,
968
+ totalCount,
969
+ pageInfo: { hasNextPage, hasPreviousPage, startCursor, endCursor },
970
+ };
971
+ }
972
+
973
+ // If the cursor of the last returned record equals the `before` cursor,
974
+ // `hasNextPage` is true. Remove that record.
975
+ if (encodeCursor(orderBySchema, rows[rows.length - 1]!) === before) {
976
+ rows.pop();
977
+ hasNextPage = true;
978
+ } else {
979
+ // Otherwise, remove the first record.
980
+ rows.shift();
981
+ }
982
+
983
+ // Now if the length of the records is equal to limit + 1, we know
984
+ // there is a previous page.
985
+ if (rows.length === limit + 1) {
986
+ rows.shift();
987
+ hasPreviousPage = true;
988
+ }
989
+
990
+ // Now calculate the cursors.
991
+ startCursor = rows.length > 0 ? encodeCursor(orderBySchema, rows[0]!) : null;
992
+ endCursor =
993
+ rows.length > 0
994
+ ? encodeCursor(orderBySchema, rows[rows.length - 1]!)
995
+ : null;
996
+
997
+ return {
998
+ items: rows,
999
+ totalCount,
1000
+ pageInfo: { hasNextPage, hasPreviousPage, startCursor, endCursor },
1001
+ };
1002
+ }
1003
+
1004
+ const conditionSuffixes = {
1005
+ universal: ["", "_not"],
1006
+ singular: ["_in", "_not_in"],
1007
+ plural: ["_has", "_not_has"],
1008
+ numeric: ["_gt", "_lt", "_gte", "_lte"],
1009
+ string: [
1010
+ "_contains",
1011
+ "_not_contains",
1012
+ "_starts_with",
1013
+ "_ends_with",
1014
+ "_not_starts_with",
1015
+ "_not_ends_with",
1016
+ ],
1017
+ } as const;
1018
+
1019
+ const conditionSuffixesByLengthDesc = Object.values(conditionSuffixes)
1020
+ .flat()
1021
+ .sort((a, b) => b.length - a.length);
1022
+
1023
+ function buildWhereConditions(
1024
+ where: Record<string, any> | undefined,
1025
+ columns: Record<string, Column>,
1026
+ ) {
1027
+ const conditions: (SQL | undefined)[] = [];
1028
+
1029
+ if (where === undefined) return conditions;
1030
+
1031
+ for (const [whereKey, rawValue] of Object.entries(where)) {
1032
+ // Handle the `AND` and `OR` operators
1033
+ if (whereKey === "AND" || whereKey === "OR") {
1034
+ if (!Array.isArray(rawValue)) {
1035
+ throw new Error(
1036
+ `Invalid query: Expected an array for the ${whereKey} operator. Got: ${rawValue}`,
1037
+ );
1038
+ }
1039
+
1040
+ const nestedConditions = rawValue.flatMap((subWhere) =>
1041
+ buildWhereConditions(subWhere, columns),
1042
+ );
1043
+
1044
+ if (nestedConditions.length > 0) {
1045
+ conditions.push(
1046
+ whereKey === "AND"
1047
+ ? and(...nestedConditions)
1048
+ : or(...nestedConditions),
1049
+ );
1050
+ }
1051
+ continue;
1052
+ }
1053
+
1054
+ // Search for a valid filter suffix, traversing the list from longest to shortest
1055
+ // to avoid ambiguity between cases like `_not_in` and `_in`.
1056
+ const conditionSuffix = conditionSuffixesByLengthDesc.find((s) =>
1057
+ whereKey.endsWith(s),
1058
+ );
1059
+ if (conditionSuffix === undefined) {
1060
+ throw new Error(
1061
+ `Invariant violation: Condition suffix not found for where key ${whereKey}`,
1062
+ );
1063
+ }
1064
+
1065
+ // Remove the condition suffix and use the remaining string as the column name.
1066
+ const columnName = whereKey.slice(
1067
+ 0,
1068
+ whereKey.length - conditionSuffix.length,
1069
+ );
1070
+
1071
+ // Validate that the column name is present in the table.
1072
+ const column = columns[columnName];
1073
+ if (column === undefined) {
1074
+ throw new Error(
1075
+ `Invalid query: Where clause contains unknown column ${columnName}`,
1076
+ );
1077
+ }
1078
+
1079
+ switch (conditionSuffix) {
1080
+ case "":
1081
+ if (column.columnType === "PgArray") {
1082
+ conditions.push(
1083
+ and(
1084
+ arrayContains(column, rawValue),
1085
+ arrayContained(column, rawValue),
1086
+ ),
1087
+ );
1088
+ } else {
1089
+ if (rawValue === null) {
1090
+ conditions.push(isNull(column));
1091
+ } else {
1092
+ conditions.push(eq(column, rawValue));
1093
+ }
1094
+ }
1095
+ break;
1096
+ case "_not":
1097
+ if (column.columnType === "PgArray") {
1098
+ conditions.push(
1099
+ not(
1100
+ and(
1101
+ arrayContains(column, rawValue),
1102
+ arrayContained(column, rawValue),
1103
+ )!,
1104
+ ),
1105
+ );
1106
+ } else {
1107
+ if (rawValue === null) {
1108
+ conditions.push(isNotNull(column));
1109
+ } else {
1110
+ conditions.push(ne(column, rawValue));
1111
+ }
1112
+ }
1113
+ break;
1114
+ case "_in":
1115
+ conditions.push(inArray(column, rawValue));
1116
+ break;
1117
+ case "_not_in":
1118
+ conditions.push(notInArray(column, rawValue));
1119
+ break;
1120
+ case "_has":
1121
+ conditions.push(arrayContains(column, [rawValue]));
1122
+ break;
1123
+ case "_not_has":
1124
+ conditions.push(not(arrayContains(column, [rawValue])));
1125
+ break;
1126
+ case "_gt":
1127
+ conditions.push(gt(column, rawValue));
1128
+ break;
1129
+ case "_lt":
1130
+ conditions.push(lt(column, rawValue));
1131
+ break;
1132
+ case "_gte":
1133
+ conditions.push(gte(column, rawValue));
1134
+ break;
1135
+ case "_lte":
1136
+ conditions.push(lte(column, rawValue));
1137
+ break;
1138
+ case "_contains":
1139
+ conditions.push(like(column, `%${rawValue}%`));
1140
+ break;
1141
+ case "_not_contains":
1142
+ conditions.push(notLike(column, `%${rawValue}%`));
1143
+ break;
1144
+ case "_starts_with":
1145
+ conditions.push(like(column, `${rawValue}%`));
1146
+ break;
1147
+ case "_ends_with":
1148
+ conditions.push(like(column, `%${rawValue}`));
1149
+ break;
1150
+ case "_not_starts_with":
1151
+ conditions.push(notLike(column, `${rawValue}%`));
1152
+ break;
1153
+ case "_not_ends_with":
1154
+ conditions.push(notLike(column, `%${rawValue}`));
1155
+ break;
1156
+ default:
1157
+ never(conditionSuffix);
1158
+ }
1159
+ }
1160
+
1161
+ return conditions;
1162
+ }
1163
+
1164
+ function buildOrderBySchema(relation: PgTable | PgView, args: PluralArgs) {
1165
+ // If the user-provided order by does not include the ALL of the ID columns,
1166
+ // add any missing ID columns to the end of the order by clause (asc).
1167
+ // This ensures a consistent sort order to unblock cursor pagination.
1168
+ const userDirection = args.orderDirection ?? "asc";
1169
+ const userColumns: [string, "asc" | "desc"][] =
1170
+ args.orderBy !== undefined ? [[args.orderBy, userDirection]] : [];
1171
+
1172
+ if (is(relation, PgView)) {
1173
+ return userColumns;
1174
+ }
1175
+
1176
+ const pkColumns = getPrimaryKeyColumns(relation).map(({ js }) => [
1177
+ js,
1178
+ userDirection,
1179
+ ]);
1180
+
1181
+ const missingPkColumns = pkColumns.filter(
1182
+ (pkColumn) =>
1183
+ !userColumns.some((userColumn) => userColumn[0] === pkColumn[0]),
1184
+ ) as [string, "asc" | "desc"][];
1185
+ return [...userColumns, ...missingPkColumns];
1186
+ }
1187
+
1188
+ function encodeCursor(
1189
+ orderBySchema: [string, "asc" | "desc"][],
1190
+ row: { [k: string]: unknown },
1191
+ ): string {
1192
+ const cursorObject = Object.fromEntries(
1193
+ orderBySchema.map(([columnName, _]) => [columnName, row[columnName]]),
1194
+ );
1195
+ return encodeRowFragment(cursorObject);
1196
+ }
1197
+ function decodeCursor(cursor: string): { [k: string]: unknown } {
1198
+ return decodeRowFragment(cursor);
1199
+ }
1200
+
1201
+ function encodeRowFragment(rowFragment: { [k: string]: unknown }): string {
1202
+ return Buffer.from(superjson.stringify(rowFragment)).toString("base64");
1203
+ }
1204
+ function decodeRowFragment(encodedRowFragment: string): {
1205
+ [k: string]: unknown;
1206
+ } {
1207
+ return superjson.parse(Buffer.from(encodedRowFragment, "base64").toString());
1208
+ }
1209
+
1210
+ function buildCursorCondition(
1211
+ columns: Record<string, Column>,
1212
+ orderBySchema: [string, "asc" | "desc"][],
1213
+ direction: "after" | "before",
1214
+ cursorObject: { [k: string]: unknown },
1215
+ ): SQL | undefined {
1216
+ const cursorColumns = orderBySchema.map(([columnName, orderDirection]) => {
1217
+ const column = columns[columnName];
1218
+ if (column === undefined)
1219
+ throw new Error(
1220
+ `Unknown column "${columnName}" used in orderBy argument`,
1221
+ );
1222
+
1223
+ const value = cursorObject[columnName];
1224
+
1225
+ let comparator: typeof gt | typeof lt;
1226
+ let comparatorOrEquals: typeof gte | typeof lte;
1227
+ if (direction === "after") {
1228
+ [comparator, comparatorOrEquals] =
1229
+ orderDirection === "asc" ? [gt, gte] : [lt, lte];
1230
+ } else {
1231
+ [comparator, comparatorOrEquals] =
1232
+ orderDirection === "asc" ? [lt, lte] : [gt, gte];
1233
+ }
1234
+
1235
+ return { column, value, comparator, comparatorOrEquals };
1236
+ });
1237
+
1238
+ const buildCondition = (index: number): SQL | undefined => {
1239
+ if (index === cursorColumns.length - 1) {
1240
+ const { column, value, comparatorOrEquals } = cursorColumns[index]!;
1241
+ return comparatorOrEquals(column, value);
1242
+ }
1243
+
1244
+ const currentColumn = cursorColumns[index]!;
1245
+ const nextCondition = buildCondition(index + 1);
1246
+
1247
+ return or(
1248
+ currentColumn.comparator(currentColumn.column, currentColumn.value),
1249
+ and(eq(currentColumn.column, currentColumn.value), nextCondition),
1250
+ );
1251
+ };
1252
+
1253
+ return buildCondition(0);
1254
+ }
1255
+
1256
+ export function buildDataLoaderCache(qb: QB) {
1257
+ const dataLoaderMap = new Map<
1258
+ TableRelationalConfig,
1259
+ DataLoader<string, any> | undefined
1260
+ >();
1261
+ return ({ table }: { table: TableRelationalConfig }) => {
1262
+ const baseQuery = (qb as QB<{ [key: string]: OnchainTable }>).raw.query[
1263
+ table.tsName
1264
+ ];
1265
+ if (baseQuery === undefined)
1266
+ throw new Error(
1267
+ `Internal error: Unknown table "${table.tsName}" in data loader cache`,
1268
+ );
1269
+
1270
+ let dataLoader = dataLoaderMap.get(table);
1271
+ if (dataLoader === undefined) {
1272
+ dataLoader = new DataLoader(
1273
+ async (encodedIds) => {
1274
+ const decodedRowFragments = encodedIds.map(decodeRowFragment);
1275
+
1276
+ // The decoded row fragments should be valid `where` objects
1277
+ // which use the `eq` object shorthand for each primary key column.
1278
+ const idConditions = decodedRowFragments.map((decodedRowFragment) =>
1279
+ and(...buildWhereConditions(decodedRowFragment, table.columns)),
1280
+ );
1281
+
1282
+ const rows = await baseQuery.findMany({
1283
+ where: or(...idConditions),
1284
+ limit: encodedIds.length,
1285
+ });
1286
+
1287
+ // Now, we need to order the rows coming out of the database to match
1288
+ // the order of the IDs passed in. To accomplish this, we need to do
1289
+ // a comparison of the decoded row PK fragments with the database rows.
1290
+ // This is tricky because the decoded row PK fragments are not normalized,
1291
+ // so some comparisons will fail (eg for our PgHex column type).
1292
+ // To fix this, we need to normalize the values before doing the comparison.
1293
+ return (
1294
+ decodedRowFragments
1295
+ // Normalize the decoded row fragments
1296
+ .map((fragment) =>
1297
+ Object.fromEntries(
1298
+ Object.entries(fragment).map(([col, val]) => {
1299
+ const column = table.columns[col];
1300
+ if (column === undefined) {
1301
+ throw new Error(
1302
+ `Unknown column '${table.tsName}.${col}' used in dataloader row ID fragment`,
1303
+ );
1304
+ }
1305
+ return [col, normalizeColumn(column, val, false)];
1306
+ }),
1307
+ ),
1308
+ )
1309
+ // Find the database row corresponding to each normalized row fragment
1310
+ .map((fragment) =>
1311
+ rows.find((row) =>
1312
+ Object.entries(fragment).every(
1313
+ ([col, val]) => row[col] === val,
1314
+ ),
1315
+ ),
1316
+ )
1317
+ );
1318
+ },
1319
+ { maxBatchSize: 1_000 },
1320
+ );
1321
+ dataLoaderMap.set(table, dataLoader);
1322
+ }
1323
+
1324
+ return dataLoader;
1325
+ };
1326
+ }
1327
+
1328
+ function getColumnTsName(column: Column) {
1329
+ const tableColumns = getTableColumns(column.table);
1330
+ return Object.entries(tableColumns).find(
1331
+ ([_, c]) => c.name === column.name,
1332
+ )![0];
1333
+ }
1334
+
1335
+ /**
1336
+ * Returns `true` if the query includes a specific field.
1337
+ * Does not consider nested selections; only works one "layer" deep.
1338
+ */
1339
+ function selectionIncludesField(
1340
+ info: GraphQLResolveInfo,
1341
+ fieldName: string,
1342
+ ): boolean {
1343
+ for (const fieldNode of info.fieldNodes) {
1344
+ for (const selection of fieldNode.selectionSet?.selections ?? []) {
1345
+ if (selection.kind === "Field" && selection.name.value === fieldName) {
1346
+ return true;
1347
+ }
1348
+ }
1349
+ }
1350
+ return false;
1351
+ }