@rocicorp/zero 1.3.0 → 1.4.0-canary.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 (332) hide show
  1. package/out/analyze-query/src/analyze-cli.d.ts +24 -0
  2. package/out/analyze-query/src/analyze-cli.d.ts.map +1 -0
  3. package/out/analyze-query/src/analyze-cli.js +289 -0
  4. package/out/analyze-query/src/analyze-cli.js.map +1 -0
  5. package/out/analyze-query/src/bin-analyze.js +6 -6
  6. package/out/analyze-query/src/bin-transform.js +2 -2
  7. package/out/ast-to-zql/src/bin.js +1 -1
  8. package/out/shared/src/logging.d.ts.map +1 -1
  9. package/out/shared/src/logging.js +1 -1
  10. package/out/shared/src/logging.js.map +1 -1
  11. package/out/shared/src/options.d.ts.map +1 -1
  12. package/out/shared/src/options.js +1 -1
  13. package/out/shared/src/options.js.map +1 -1
  14. package/out/z2s/src/compiler.d.ts.map +1 -1
  15. package/out/z2s/src/compiler.js +4 -1
  16. package/out/z2s/src/compiler.js.map +1 -1
  17. package/out/z2s/src/sql.d.ts.map +1 -1
  18. package/out/z2s/src/sql.js +1 -0
  19. package/out/z2s/src/sql.js.map +1 -1
  20. package/out/zero/package.js +95 -89
  21. package/out/zero/package.js.map +1 -1
  22. package/out/zero/src/analyze.d.ts +2 -0
  23. package/out/zero/src/analyze.d.ts.map +1 -0
  24. package/out/zero/src/analyze.js +2 -0
  25. package/out/zero/src/bindings.js +1 -1
  26. package/out/zero/src/zero-cache-dev.js +1 -1
  27. package/out/zero/src/zero-cache-dev.js.map +1 -1
  28. package/out/zero/src/zero-out.js +1 -1
  29. package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
  30. package/out/zero-cache/src/auth/auth.js.map +1 -1
  31. package/out/zero-cache/src/auth/load-permissions.js +2 -2
  32. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  33. package/out/zero-cache/src/auth/write-authorizer.js +5 -14
  34. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  35. package/out/zero-cache/src/config/network.d.ts +1 -1
  36. package/out/zero-cache/src/config/network.d.ts.map +1 -1
  37. package/out/zero-cache/src/config/network.js +1 -1
  38. package/out/zero-cache/src/config/network.js.map +1 -1
  39. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  40. package/out/zero-cache/src/config/normalize.js.map +1 -1
  41. package/out/zero-cache/src/config/zero-config.d.ts +5 -0
  42. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  43. package/out/zero-cache/src/config/zero-config.js +16 -3
  44. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  45. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  46. package/out/zero-cache/src/db/lite-tables.js +3 -3
  47. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  48. package/out/zero-cache/src/db/transaction-pool.d.ts +43 -40
  49. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  50. package/out/zero-cache/src/db/transaction-pool.js +76 -56
  51. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  52. package/out/zero-cache/src/observability/events.d.ts.map +1 -1
  53. package/out/zero-cache/src/observability/events.js +1 -1
  54. package/out/zero-cache/src/observability/events.js.map +1 -1
  55. package/out/zero-cache/src/scripts/decommission.js +1 -1
  56. package/out/zero-cache/src/scripts/deploy-permissions.js +2 -2
  57. package/out/zero-cache/src/scripts/permissions.js +1 -1
  58. package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
  59. package/out/zero-cache/src/server/anonymous-otel-start.js +4 -4
  60. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  61. package/out/zero-cache/src/server/change-streamer.d.ts +1 -1
  62. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  63. package/out/zero-cache/src/server/change-streamer.js +27 -12
  64. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  65. package/out/zero-cache/src/server/logging.d.ts +1 -3
  66. package/out/zero-cache/src/server/logging.d.ts.map +1 -1
  67. package/out/zero-cache/src/server/logging.js +6 -3
  68. package/out/zero-cache/src/server/logging.js.map +1 -1
  69. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  70. package/out/zero-cache/src/server/main.js +26 -26
  71. package/out/zero-cache/src/server/main.js.map +1 -1
  72. package/out/zero-cache/src/server/mutator.js +4 -2
  73. package/out/zero-cache/src/server/mutator.js.map +1 -1
  74. package/out/zero-cache/src/server/otel-log-sink.d.ts.map +1 -1
  75. package/out/zero-cache/src/server/otel-log-sink.js +0 -2
  76. package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
  77. package/out/zero-cache/src/server/otel-start.d.ts +1 -1
  78. package/out/zero-cache/src/server/otel-start.d.ts.map +1 -1
  79. package/out/zero-cache/src/server/otel-start.js +7 -3
  80. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  81. package/out/zero-cache/src/server/reaper.js +6 -6
  82. package/out/zero-cache/src/server/reaper.js.map +1 -1
  83. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  84. package/out/zero-cache/src/server/replicator.js +5 -3
  85. package/out/zero-cache/src/server/replicator.js.map +1 -1
  86. package/out/zero-cache/src/server/runner/run-worker.js +2 -2
  87. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  88. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  89. package/out/zero-cache/src/server/syncer.js +13 -12
  90. package/out/zero-cache/src/server/syncer.js.map +1 -1
  91. package/out/zero-cache/src/server/worker-dispatcher.js +1 -1
  92. package/out/zero-cache/src/services/analyze.js +1 -1
  93. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +1 -1
  94. package/out/zero-cache/src/services/change-source/common/replica-schema.js +1 -1
  95. package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
  96. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +4 -1
  97. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  98. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  99. package/out/zero-cache/src/services/change-source/pg/change-source.js +19 -23
  100. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  101. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +58 -3
  102. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  103. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +209 -52
  104. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  105. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +2 -2
  106. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +24 -15
  107. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  108. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +35 -58
  109. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  110. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  111. package/out/zero-cache/src/services/change-source/pg/schema/init.js +2 -2
  112. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  113. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +1 -2
  114. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  115. package/out/zero-cache/src/services/change-source/pg/schema/published.js +15 -18
  116. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  117. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +1 -1
  118. package/out/zero-cache/src/services/change-source/protocol/current/data.js +1 -1
  119. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +1 -1
  120. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +1 -1
  121. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  122. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +1 -1
  123. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  124. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +5 -1
  125. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  126. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +10 -7
  127. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  128. package/out/zero-cache/src/services/change-streamer/replica-monitor.js +2 -2
  129. package/out/zero-cache/src/services/change-streamer/storer.d.ts +19 -2
  130. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  131. package/out/zero-cache/src/services/change-streamer/storer.js +70 -6
  132. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  133. package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
  134. package/out/zero-cache/src/services/heapz.js +1 -1
  135. package/out/zero-cache/src/services/heapz.js.map +1 -1
  136. package/out/zero-cache/src/services/life-cycle.d.ts +2 -1
  137. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  138. package/out/zero-cache/src/services/life-cycle.js +10 -7
  139. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  140. package/out/zero-cache/src/services/litestream/commands.d.ts +15 -4
  141. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  142. package/out/zero-cache/src/services/litestream/commands.js +40 -34
  143. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  144. package/out/zero-cache/src/services/mutagen/mutagen.js +3 -3
  145. package/out/zero-cache/src/services/mutagen/pusher.d.ts +28 -28
  146. package/out/zero-cache/src/services/replicator/change-processor.js +2 -2
  147. package/out/zero-cache/src/services/replicator/incremental-sync.js +1 -1
  148. package/out/zero-cache/src/services/replicator/schema/replication-state.js +1 -1
  149. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  150. package/out/zero-cache/src/services/replicator/write-worker.js +3 -3
  151. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  152. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  153. package/out/zero-cache/src/services/run-ast.js +3 -3
  154. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  155. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  156. package/out/zero-cache/src/services/statz.js +3 -3
  157. package/out/zero-cache/src/services/statz.js.map +1 -1
  158. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +1 -1
  159. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +2 -2
  160. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -1
  161. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  162. package/out/zero-cache/src/services/view-syncer/cvr-purger.js +1 -1
  163. package/out/zero-cache/src/services/view-syncer/cvr-store.js +3 -3
  164. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  165. package/out/zero-cache/src/services/view-syncer/cvr.js +1 -1
  166. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
  167. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +6 -16
  168. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  169. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +31 -39
  170. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  171. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
  172. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +4 -4
  173. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  174. package/out/zero-cache/src/services/view-syncer/snapshotter.js +2 -2
  175. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  176. package/out/zero-cache/src/services/view-syncer/view-syncer.js +6 -6
  177. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  178. package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
  179. package/out/zero-cache/src/types/profiler.js.map +1 -1
  180. package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
  181. package/out/zero-cache/src/types/row-key.js.map +1 -1
  182. package/out/zero-cache/src/types/streams.d.ts +1 -1
  183. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  184. package/out/zero-cache/src/types/streams.js.map +1 -1
  185. package/out/zero-cache/src/types/websocket-handoff.d.ts +1 -1
  186. package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
  187. package/out/zero-cache/src/types/websocket-handoff.js +1 -1
  188. package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
  189. package/out/zero-cache/src/workers/connection.d.ts +1 -1
  190. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  191. package/out/zero-cache/src/workers/connection.js.map +1 -1
  192. package/out/zero-cache/src/workers/mutator.js.map +1 -1
  193. package/out/zero-cache/src/workers/syncer.d.ts +1 -1
  194. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  195. package/out/zero-cache/src/workers/syncer.js +3 -3
  196. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  197. package/out/zero-client/src/client/bindings.js +1 -1
  198. package/out/zero-client/src/client/crud-impl.d.ts.map +1 -1
  199. package/out/zero-client/src/client/crud-impl.js +4 -13
  200. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  201. package/out/zero-client/src/client/inspector/inspector.d.ts +24 -0
  202. package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
  203. package/out/zero-client/src/client/inspector/inspector.js +28 -0
  204. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  205. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +9 -0
  206. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
  207. package/out/zero-client/src/client/inspector/lazy-inspector.js +28 -1
  208. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  209. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  210. package/out/zero-client/src/client/ivm-branch.js +4 -13
  211. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  212. package/out/zero-client/src/client/log-options.d.ts +1 -0
  213. package/out/zero-client/src/client/log-options.d.ts.map +1 -1
  214. package/out/zero-client/src/client/log-options.js +3 -2
  215. package/out/zero-client/src/client/log-options.js.map +1 -1
  216. package/out/zero-client/src/client/options.d.ts +13 -1
  217. package/out/zero-client/src/client/options.d.ts.map +1 -1
  218. package/out/zero-client/src/client/options.js.map +1 -1
  219. package/out/zero-client/src/client/version.js +1 -1
  220. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  221. package/out/zero-client/src/client/zero.js +2 -1
  222. package/out/zero-client/src/client/zero.js.map +1 -1
  223. package/out/zero-protocol/src/error.d.ts.map +1 -1
  224. package/out/zero-protocol/src/error.js +1 -1
  225. package/out/zero-protocol/src/error.js.map +1 -1
  226. package/out/zero-react/src/bindings.js +1 -1
  227. package/out/zero-solid/src/bindings.js +1 -1
  228. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  229. package/out/zero-solid/src/solid-view.js +14 -14
  230. package/out/zero-solid/src/solid-view.js.map +1 -1
  231. package/out/zql/src/builder/builder.d.ts.map +1 -1
  232. package/out/zql/src/builder/builder.js.map +1 -1
  233. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  234. package/out/zql/src/ivm/array-view.js +27 -2
  235. package/out/zql/src/ivm/array-view.js.map +1 -1
  236. package/out/zql/src/ivm/change-index-enum.d.ts +9 -0
  237. package/out/zql/src/ivm/change-index-enum.d.ts.map +1 -0
  238. package/out/zql/src/ivm/change-index.d.ts +5 -0
  239. package/out/zql/src/ivm/change-index.d.ts.map +1 -0
  240. package/out/zql/src/ivm/change-type-enum.d.ts +9 -0
  241. package/out/zql/src/ivm/change-type-enum.d.ts.map +1 -0
  242. package/out/zql/src/ivm/change-type.d.ts +5 -0
  243. package/out/zql/src/ivm/change-type.d.ts.map +1 -0
  244. package/out/zql/src/ivm/change.d.ts +20 -22
  245. package/out/zql/src/ivm/change.d.ts.map +1 -1
  246. package/out/zql/src/ivm/change.js +33 -0
  247. package/out/zql/src/ivm/change.js.map +1 -0
  248. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  249. package/out/zql/src/ivm/exists.js +27 -38
  250. package/out/zql/src/ivm/exists.js.map +1 -1
  251. package/out/zql/src/ivm/fan-in.d.ts +3 -2
  252. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  253. package/out/zql/src/ivm/fan-in.js.map +1 -1
  254. package/out/zql/src/ivm/fan-out.d.ts +1 -1
  255. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  256. package/out/zql/src/ivm/fan-out.js +1 -1
  257. package/out/zql/src/ivm/fan-out.js.map +1 -1
  258. package/out/zql/src/ivm/filter-operators.d.ts +3 -3
  259. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  260. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  261. package/out/zql/src/ivm/filter-push.d.ts.map +1 -1
  262. package/out/zql/src/ivm/filter-push.js +7 -7
  263. package/out/zql/src/ivm/filter-push.js.map +1 -1
  264. package/out/zql/src/ivm/filter.d.ts +1 -1
  265. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  266. package/out/zql/src/ivm/filter.js.map +1 -1
  267. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  268. package/out/zql/src/ivm/flipped-join.js +49 -58
  269. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  270. package/out/zql/src/ivm/join-utils.d.ts +2 -6
  271. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  272. package/out/zql/src/ivm/join-utils.js +25 -25
  273. package/out/zql/src/ivm/join-utils.js.map +1 -1
  274. package/out/zql/src/ivm/join.d.ts.map +1 -1
  275. package/out/zql/src/ivm/join.js +32 -51
  276. package/out/zql/src/ivm/join.js.map +1 -1
  277. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  278. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  279. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +5 -10
  280. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  281. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  282. package/out/zql/src/ivm/memory-source.js +52 -60
  283. package/out/zql/src/ivm/memory-source.js.map +1 -1
  284. package/out/zql/src/ivm/operator.d.ts +1 -1
  285. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  286. package/out/zql/src/ivm/operator.js +2 -4
  287. package/out/zql/src/ivm/operator.js.map +1 -1
  288. package/out/zql/src/ivm/push-accumulated.d.ts +3 -2
  289. package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
  290. package/out/zql/src/ivm/push-accumulated.js +98 -122
  291. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  292. package/out/zql/src/ivm/skip-yields.d.ts +4 -0
  293. package/out/zql/src/ivm/skip-yields.d.ts.map +1 -0
  294. package/out/zql/src/ivm/skip-yields.js +33 -0
  295. package/out/zql/src/ivm/skip-yields.js.map +1 -0
  296. package/out/zql/src/ivm/skip.d.ts +1 -1
  297. package/out/zql/src/ivm/skip.d.ts.map +1 -1
  298. package/out/zql/src/ivm/skip.js +2 -2
  299. package/out/zql/src/ivm/skip.js.map +1 -1
  300. package/out/zql/src/ivm/source-change-index-enum.d.ts +7 -0
  301. package/out/zql/src/ivm/source-change-index-enum.d.ts.map +1 -0
  302. package/out/zql/src/ivm/source-change-index.d.ts +5 -0
  303. package/out/zql/src/ivm/source-change-index.d.ts.map +1 -0
  304. package/out/zql/src/ivm/source.d.ts +11 -13
  305. package/out/zql/src/ivm/source.d.ts.map +1 -1
  306. package/out/zql/src/ivm/source.js +26 -0
  307. package/out/zql/src/ivm/source.js.map +1 -0
  308. package/out/zql/src/ivm/take.d.ts.map +1 -1
  309. package/out/zql/src/ivm/take.js +27 -50
  310. package/out/zql/src/ivm/take.js.map +1 -1
  311. package/out/zql/src/ivm/union-fan-in.d.ts +2 -1
  312. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  313. package/out/zql/src/ivm/union-fan-in.js +3 -3
  314. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  315. package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
  316. package/out/zql/src/ivm/union-fan-out.js +1 -1
  317. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  318. package/out/zql/src/ivm/view-apply-change.js +1 -1
  319. package/out/zql/src/planner/planner-debug.d.ts +2 -2
  320. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  321. package/out/zql/src/planner/planner-debug.js.map +1 -1
  322. package/out/zql/src/planner/planner-graph.d.ts +1 -1
  323. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  324. package/out/zql/src/planner/planner-graph.js.map +1 -1
  325. package/out/zqlite/src/internal/sql-inline.d.ts.map +1 -1
  326. package/out/zqlite/src/internal/sql-inline.js.map +1 -1
  327. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  328. package/out/zqlite/src/query-builder.js.map +1 -1
  329. package/out/zqlite/src/table-source.d.ts.map +1 -1
  330. package/out/zqlite/src/table-source.js +11 -11
  331. package/out/zqlite/src/table-source.js.map +1 -1
  332. package/package.json +99 -93
@@ -0,0 +1,24 @@
1
+ import '../../shared/src/dotenv.ts';
2
+ import type { Schema } from '../../zero-types/src/schema.ts';
3
+ export type AnalyzeCLIOptions = {
4
+ schema: Schema;
5
+ /** Defaults to `process.argv.slice(2)`. */
6
+ argv?: readonly string[] | undefined;
7
+ };
8
+ /**
9
+ * Entry point for a user's `cli.ts`. Parses argv, connects to a remote
10
+ * zero-cache by standing up an in-process Zero client (in-memory storage,
11
+ * no subscriptions), calls the inspector's `analyze-query` RPC, and
12
+ * renders the result. Intended to be called as:
13
+ *
14
+ * ```ts
15
+ * import {schema} from './schema.ts';
16
+ * import {runAnalyzeCLI} from '@rocicorp/zero/analyze';
17
+ * await runAnalyzeCLI({schema});
18
+ * ```
19
+ *
20
+ * @experimental This API is in progress and may change without notice.
21
+ * Exits the process with code 1 on error.
22
+ */
23
+ export declare function runAnalyzeCLI(opts: AnalyzeCLIOptions): Promise<void>;
24
+ //# sourceMappingURL=analyze-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-cli.d.ts","sourceRoot":"","sources":["../../../../analyze-query/src/analyze-cli.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,CAAC;AAcpC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAK3D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CACtC,CAAC;AAmHF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgG1E"}
@@ -0,0 +1,289 @@
1
+ import { valita_exports } from "../../shared/src/valita.js";
2
+ import { createBuilder } from "../../zql/src/query/create-builder.js";
3
+ import { Zero } from "../../zero-client/src/client/zero.js";
4
+ import "../../shared/src/dotenv.js";
5
+ import { logLevel, logOptions } from "../../otel/src/log-options.js";
6
+ import { colorConsole } from "../../shared/src/logging.js";
7
+ import { parseOptions } from "../../shared/src/options.js";
8
+ import { ZERO_ENV_VAR_PREFIX } from "../../zero-cache/src/config/zero-config.js";
9
+ import { Console } from "node:console";
10
+ import { styleText } from "node:util";
11
+ import { WebSocket } from "ws";
12
+ //#region ../analyze-query/src/analyze-cli.ts
13
+ var options = {
14
+ zeroCacheURL: {
15
+ type: valita_exports.string().optional(),
16
+ desc: ["URL of the remote zero-cache to analyze against.", "Accepts http(s):// or ws(s):// (ws(s) is the transport actually used)."]
17
+ },
18
+ adminPassword: {
19
+ type: valita_exports.string().optional(),
20
+ desc: ["Admin password for zero-cache.", "Required when the server is configured with one; ignored in dev mode."]
21
+ },
22
+ authToken: {
23
+ type: valita_exports.string().optional(),
24
+ desc: ["Raw JWT forwarded to zero-cache.", "Used server-side to fill permission variables for the query."]
25
+ },
26
+ cookie: {
27
+ type: valita_exports.string().optional(),
28
+ desc: [
29
+ "Cookie header value sent on the WebSocket upgrade request,",
30
+ "e.g. `session=abc; foo=bar`. Use this when zero-cache is behind",
31
+ "a proxy that resolves auth via cookies. Merged with --headers-json",
32
+ "(--cookie wins on conflict)."
33
+ ]
34
+ },
35
+ headersJson: {
36
+ type: valita_exports.string().optional(),
37
+ desc: [
38
+ "JSON object of arbitrary headers to send on the WebSocket upgrade",
39
+ "request, e.g. `{\"x-api-key\":\"...\"}`. Escape hatch for exotic auth",
40
+ "schemes; prefer --auth-token or --cookie when possible."
41
+ ]
42
+ },
43
+ userId: {
44
+ type: valita_exports.string().optional(),
45
+ desc: ["Optional userID to report to zero-cache.", "Has no functional effect on analysis; defaults to \"analyze-cli\"."]
46
+ },
47
+ ast: {
48
+ type: valita_exports.string().optional(),
49
+ desc: ["JSON-encoded AST. Exactly one of --ast / --query / --query-name is required.", "The AST is sent to the server verbatim — provide it in server (post-mapping) form."]
50
+ },
51
+ query: {
52
+ type: valita_exports.string().optional(),
53
+ desc: ["ZQL query in chain form, e.g. `issue.related(\"comments\").limit(10)`.", "Evaluated against the schema you pass to runAnalyzeCLI."]
54
+ },
55
+ queryName: {
56
+ type: valita_exports.string().optional(),
57
+ desc: ["Name of a server-registered custom (named) query.", "The server resolves the name + args via its registered query handler."]
58
+ },
59
+ queryArgs: {
60
+ type: valita_exports.string().optional(),
61
+ desc: ["JSON-encoded array of arguments for --query-name. Defaults to `[]`."]
62
+ },
63
+ outputVendedRows: {
64
+ type: valita_exports.boolean().default(false),
65
+ desc: ["Include the rows read from the replica to execute the query.", "Each row appears once per read."]
66
+ },
67
+ outputSyncedRows: {
68
+ type: valita_exports.boolean().default(false),
69
+ desc: ["Include the rows that would be synced to the client."]
70
+ },
71
+ log: {
72
+ ...logOptions,
73
+ level: logLevel.default("error")
74
+ }
75
+ };
76
+ var stderrConsole = new Console({
77
+ stdout: process.stderr,
78
+ stderr: process.stderr
79
+ });
80
+ var stderrLogSink = { log(level, context, ...args) {
81
+ const ctx = context ? Object.entries(context).map(([k, v]) => v === void 0 ? k : `${k}=${v}`) : [];
82
+ stderrConsole[level](...ctx, ...args);
83
+ } };
84
+ /**
85
+ * Entry point for a user's `cli.ts`. Parses argv, connects to a remote
86
+ * zero-cache by standing up an in-process Zero client (in-memory storage,
87
+ * no subscriptions), calls the inspector's `analyze-query` RPC, and
88
+ * renders the result. Intended to be called as:
89
+ *
90
+ * ```ts
91
+ * import {schema} from './schema.ts';
92
+ * import {runAnalyzeCLI} from '@rocicorp/zero/analyze';
93
+ * await runAnalyzeCLI({schema});
94
+ * ```
95
+ *
96
+ * @experimental This API is in progress and may change without notice.
97
+ * Exits the process with code 1 on error.
98
+ */
99
+ async function runAnalyzeCLI(opts) {
100
+ const config = parseOptions(options, {
101
+ argv: (opts.argv ?? process.argv.slice(2)).map((s) => s.replaceAll("\n", " ")),
102
+ envNamePrefix: ZERO_ENV_VAR_PREFIX,
103
+ description: [{
104
+ header: "analyze-query (remote)",
105
+ content: `Analyze a ZQL query against a remote zero-cache.
106
+
107
+ Connects to zero-cache's inspector protocol and reports the server-observed
108
+ row scans, SQLite query plans, and timings.`
109
+ }, {
110
+ header: "Examples",
111
+ content: ` tsx cli.ts --zero-cache-url=https://zero.example.com \\
112
+ --admin-password="$ZERO_ADMIN_PASSWORD" \\
113
+ --query='issue.related("comments").limit(10)'
114
+
115
+ tsx cli.ts --zero-cache-url=http://localhost:4848 \\
116
+ --ast='\\{"table": "issue", "limit": 5\\}'
117
+
118
+ tsx cli.ts --zero-cache-url=http://localhost:4848 \\
119
+ --query-name=issueList --query-args='[]'`
120
+ }]
121
+ });
122
+ if (!config.zeroCacheURL) {
123
+ colorConsole.error("--zero-cache-url is required. See --help for usage.");
124
+ process.exit(1);
125
+ }
126
+ const plan = buildQueryPlan(config);
127
+ const handshakeHeaders = resolveHandshakeHeaders(config);
128
+ if (Object.keys(handshakeHeaders).length > 0) installWebSocketHeaderShim(handshakeHeaders);
129
+ globalThis.TESTING ??= false;
130
+ const z = new Zero({
131
+ schema: opts.schema,
132
+ server: config.zeroCacheURL,
133
+ auth: config.authToken,
134
+ userID: config.userId ?? "analyze-cli",
135
+ kvStore: "mem",
136
+ logLevel: config.log.level,
137
+ logSink: stderrLogSink
138
+ });
139
+ let result;
140
+ try {
141
+ if (!await z.inspector.authenticate(config.adminPassword ?? "")) throw new Error("admin password rejected (or --admin-password is required)");
142
+ const rpcOptions = {
143
+ vendedRows: config.outputVendedRows,
144
+ syncedRows: config.outputSyncedRows
145
+ };
146
+ if (plan.kind === "ast") result = await z.inspector.analyzeServerAST(plan.ast, rpcOptions);
147
+ else if (plan.kind === "named") result = await z.inspector.analyzeNamedQuery(plan.name, plan.args, rpcOptions);
148
+ else {
149
+ const built = buildZqlQuery(plan.text, createBuilder(opts.schema));
150
+ result = await z.inspector.analyzeQuery(built, rpcOptions);
151
+ }
152
+ } catch (e) {
153
+ colorConsole.error(e instanceof Error ? e.message : String(e));
154
+ await z.close().catch(() => {});
155
+ process.exit(1);
156
+ }
157
+ renderResult(result, {
158
+ outputSyncedRows: config.outputSyncedRows,
159
+ outputVendedRows: config.outputVendedRows
160
+ });
161
+ await z.close();
162
+ }
163
+ function buildQueryPlan(config) {
164
+ const selectors = [
165
+ config.ast !== void 0 && "ast",
166
+ config.query !== void 0 && "query",
167
+ config.queryName !== void 0 && "queryName"
168
+ ].filter(Boolean);
169
+ if (selectors.length === 0) {
170
+ colorConsole.error("Exactly one of --ast / --query / --query-name is required.");
171
+ process.exit(1);
172
+ }
173
+ if (selectors.length > 1) {
174
+ colorConsole.error(`Only one of --ast / --query / --query-name may be provided; got: ${selectors.join(", ")}`);
175
+ process.exit(1);
176
+ }
177
+ if (config.ast !== void 0) return {
178
+ kind: "ast",
179
+ ast: JSON.parse(config.ast)
180
+ };
181
+ if (config.query !== void 0) return {
182
+ kind: "zql",
183
+ text: config.query
184
+ };
185
+ const args = config.queryArgs ? JSON.parse(config.queryArgs) : [];
186
+ return {
187
+ kind: "named",
188
+ name: config.queryName,
189
+ args
190
+ };
191
+ }
192
+ function buildZqlQuery(queryString, builder) {
193
+ return new Function("builder", `return builder.${queryString};`)(builder);
194
+ }
195
+ function resolveHandshakeHeaders(config) {
196
+ const headers = {};
197
+ if (config.headersJson !== void 0) {
198
+ let parsed;
199
+ try {
200
+ parsed = JSON.parse(config.headersJson);
201
+ } catch (e) {
202
+ colorConsole.error(`--headers-json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
203
+ process.exit(1);
204
+ }
205
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
206
+ colorConsole.error("--headers-json must be a JSON object.");
207
+ process.exit(1);
208
+ }
209
+ for (const [k, val] of Object.entries(parsed)) {
210
+ if (typeof val !== "string") {
211
+ colorConsole.error(`--headers-json values must be strings; got ${typeof val} for "${k}".`);
212
+ process.exit(1);
213
+ }
214
+ headers[k] = val;
215
+ }
216
+ }
217
+ if (config.cookie !== void 0) headers.cookie = config.cookie;
218
+ return headers;
219
+ }
220
+ function installWebSocketHeaderShim(headers) {
221
+ class HeaderInjectingWebSocket extends WebSocket {
222
+ constructor(url, protocols) {
223
+ super(url, protocols, { headers });
224
+ }
225
+ }
226
+ globalThis.WebSocket = HeaderInjectingWebSocket;
227
+ }
228
+ function renderResult(result, opts) {
229
+ if (opts.outputSyncedRows) {
230
+ colorConsole.log(styleText(["blue", "bold"], "=== Synced Rows: ===\n"));
231
+ for (const [table, rows] of Object.entries(result.syncedRows ?? {})) colorConsole.log(styleText("bold", table + ":"), rows);
232
+ }
233
+ colorConsole.log(styleText(["blue", "bold"], "=== Query Stats: ===\n"));
234
+ colorConsole.log(styleText("bold", "total synced rows:"), result.syncedRowCount);
235
+ const readRowCountsByQuery = result.readRowCountsByQuery ?? {};
236
+ let totalRowsRead = 0;
237
+ for (const table of Object.keys(readRowCountsByQuery).sort()) {
238
+ const counts = readRowCountsByQuery[table];
239
+ for (const n of Object.values(counts)) totalRowsRead += n;
240
+ colorConsole.log(styleText("bold", `${table} vended:`), counts);
241
+ }
242
+ colorConsole.log(styleText("bold", "Rows Read (into JS):"), colorRowsConsidered(totalRowsRead));
243
+ const duration = result.elapsed ?? result.end - result.start;
244
+ colorConsole.log(styleText("bold", "time:"), colorTime(duration), "ms");
245
+ if (opts.outputVendedRows) {
246
+ colorConsole.log(styleText(["blue", "bold"], "=== JS Row Scan Values: ===\n"));
247
+ for (const [table, rows] of Object.entries(result.readRows ?? {})) colorConsole.log(styleText("bold", `${table}:`), rows);
248
+ }
249
+ colorConsole.log(styleText(["blue", "bold"], "\n=== Rows Scanned (by SQLite): ===\n"));
250
+ const dbScansByQuery = result.dbScansByQuery ?? {};
251
+ let totalNVisit = 0;
252
+ for (const [table, queries] of Object.entries(dbScansByQuery)) {
253
+ colorConsole.log(styleText("bold", `${table}:`), queries);
254
+ for (const count of Object.values(queries)) totalNVisit += count;
255
+ }
256
+ colorConsole.log(styleText("bold", "total rows scanned:"), colorRowsConsidered(totalNVisit));
257
+ colorConsole.log(styleText(["blue", "bold"], "\n\n=== Query Plans: ===\n"));
258
+ const plans = result.sqlitePlans ?? {};
259
+ for (const [query, plan] of Object.entries(plans)) {
260
+ colorConsole.log(styleText("bold", "query"), query);
261
+ colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join("\n"));
262
+ colorConsole.log("\n");
263
+ }
264
+ if (result.warnings.length > 0) {
265
+ colorConsole.log(styleText(["yellow", "bold"], "=== Warnings: ===\n"));
266
+ for (const w of result.warnings) colorConsole.log(styleText("yellow", w));
267
+ }
268
+ }
269
+ function colorTime(duration) {
270
+ if (duration < 100) return styleText("green", duration.toFixed(2) + "ms");
271
+ else if (duration < 1e3) return styleText("yellow", duration.toFixed(2) + "ms");
272
+ return styleText("red", duration.toFixed(2) + "ms");
273
+ }
274
+ function colorRowsConsidered(n) {
275
+ if (n < 1e3) return styleText("green", n.toString());
276
+ else if (n < 1e4) return styleText("yellow", n.toString());
277
+ return styleText("red", n.toString());
278
+ }
279
+ function colorPlanRow(row, i) {
280
+ if (row.includes("SCAN")) {
281
+ if (i === 0) return styleText("yellow", row);
282
+ return styleText("red", row);
283
+ }
284
+ return styleText("green", row);
285
+ }
286
+ //#endregion
287
+ export { runAnalyzeCLI };
288
+
289
+ //# sourceMappingURL=analyze-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-cli.js","names":[],"sources":["../../../../analyze-query/src/analyze-cli.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport {Console} from 'node:console';\nimport {styleText} from 'node:util';\nimport type {LogSink} from '@rocicorp/logger';\nimport {WebSocket as NodeWebSocket} from 'ws';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {colorConsole} from '../../shared/src/logging.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {ZERO_ENV_VAR_PREFIX} from '../../zero-cache/src/config/zero-config.ts';\nimport {Zero} from '../../zero-client/src/client/zero.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {createBuilder} from '../../zql/src/query/create-builder.ts';\nimport type {AnyQuery} from '../../zql/src/query/query.ts';\nimport type {SchemaQuery} from '../../zql/src/query/schema-query.ts';\n\nexport type AnalyzeCLIOptions = {\n schema: Schema;\n /** Defaults to `process.argv.slice(2)`. */\n argv?: readonly string[] | undefined;\n};\n\nconst options = {\n zeroCacheURL: {\n type: v.string().optional(),\n desc: [\n 'URL of the remote zero-cache to analyze against.',\n 'Accepts http(s):// or ws(s):// (ws(s) is the transport actually used).',\n ],\n },\n adminPassword: {\n type: v.string().optional(),\n desc: [\n 'Admin password for zero-cache.',\n 'Required when the server is configured with one; ignored in dev mode.',\n ],\n },\n authToken: {\n type: v.string().optional(),\n desc: [\n 'Raw JWT forwarded to zero-cache.',\n 'Used server-side to fill permission variables for the query.',\n ],\n },\n cookie: {\n type: v.string().optional(),\n desc: [\n 'Cookie header value sent on the WebSocket upgrade request,',\n 'e.g. `session=abc; foo=bar`. Use this when zero-cache is behind',\n 'a proxy that resolves auth via cookies. Merged with --headers-json',\n '(--cookie wins on conflict).',\n ],\n },\n headersJson: {\n type: v.string().optional(),\n desc: [\n 'JSON object of arbitrary headers to send on the WebSocket upgrade',\n 'request, e.g. `{\"x-api-key\":\"...\"}`. Escape hatch for exotic auth',\n 'schemes; prefer --auth-token or --cookie when possible.',\n ],\n },\n userId: {\n type: v.string().optional(),\n desc: [\n 'Optional userID to report to zero-cache.',\n 'Has no functional effect on analysis; defaults to \"analyze-cli\".',\n ],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'JSON-encoded AST. Exactly one of --ast / --query / --query-name is required.',\n 'The AST is sent to the server verbatim — provide it in server (post-mapping) form.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n 'ZQL query in chain form, e.g. `issue.related(\"comments\").limit(10)`.',\n 'Evaluated against the schema you pass to runAnalyzeCLI.',\n ],\n },\n queryName: {\n type: v.string().optional(),\n desc: [\n 'Name of a server-registered custom (named) query.',\n 'The server resolves the name + args via its registered query handler.',\n ],\n },\n queryArgs: {\n type: v.string().optional(),\n desc: [\n 'JSON-encoded array of arguments for --query-name. Defaults to `[]`.',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Include the rows read from the replica to execute the query.',\n 'Each row appears once per read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: ['Include the rows that would be synced to the client.'],\n },\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\ntype QueryPlan =\n | {kind: 'ast'; ast: AST}\n | {kind: 'zql'; text: string}\n | {kind: 'named'; name: string; args: ReadonlyArray<unknown>};\n\n// Route all Zero client log output to stderr so stdout contains only the\n// analyze result. Shell redirection (`2>/dev/null`) can then cleanly silence\n// logs without affecting output.\nconst stderrConsole = new Console({\n stdout: process.stderr,\n stderr: process.stderr,\n});\nconst stderrLogSink: LogSink = {\n log(level, context, ...args) {\n const ctx = context\n ? Object.entries(context).map(([k, v]) =>\n v === undefined ? k : `${k}=${v}`,\n )\n : [];\n stderrConsole[level](...ctx, ...args);\n },\n};\n\n/**\n * Entry point for a user's `cli.ts`. Parses argv, connects to a remote\n * zero-cache by standing up an in-process Zero client (in-memory storage,\n * no subscriptions), calls the inspector's `analyze-query` RPC, and\n * renders the result. Intended to be called as:\n *\n * ```ts\n * import {schema} from './schema.ts';\n * import {runAnalyzeCLI} from '@rocicorp/zero/analyze';\n * await runAnalyzeCLI({schema});\n * ```\n *\n * @experimental This API is in progress and may change without notice.\n * Exits the process with code 1 on error.\n */\nexport async function runAnalyzeCLI(opts: AnalyzeCLIOptions): Promise<void> {\n const argv = (opts.argv ?? process.argv.slice(2)).map(s =>\n s.replaceAll('\\n', ' '),\n );\n\n const config = parseOptions(options, {\n argv,\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query (remote)',\n content: `Analyze a ZQL query against a remote zero-cache.\n\n Connects to zero-cache's inspector protocol and reports the server-observed\n row scans, SQLite query plans, and timings.`,\n },\n {\n header: 'Examples',\n content: ` tsx cli.ts --zero-cache-url=https://zero.example.com \\\\\n --admin-password=\"$ZERO_ADMIN_PASSWORD\" \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n tsx cli.ts --zero-cache-url=http://localhost:4848 \\\\\n --ast='\\\\{\"table\": \"issue\", \"limit\": 5\\\\}'\n\n tsx cli.ts --zero-cache-url=http://localhost:4848 \\\\\n --query-name=issueList --query-args='[]'`,\n },\n ],\n });\n\n if (!config.zeroCacheURL) {\n colorConsole.error('--zero-cache-url is required. See --help for usage.');\n process.exit(1);\n }\n\n const plan = buildQueryPlan(config);\n\n const handshakeHeaders = resolveHandshakeHeaders(config);\n if (Object.keys(handshakeHeaders).length > 0) {\n installWebSocketHeaderShim(handshakeHeaders);\n }\n\n // zero-client and replicache reference a build-time `TESTING` global that\n // bundlers replace with a boolean literal; under tsx there's no replacement,\n // so provide a runtime default.\n (globalThis as {TESTING?: boolean}).TESTING ??= false;\n\n const z = new Zero({\n schema: opts.schema,\n server: config.zeroCacheURL,\n auth: config.authToken,\n userID: config.userId ?? 'analyze-cli',\n kvStore: 'mem',\n logLevel: config.log.level,\n logSink: stderrLogSink,\n });\n\n let result: AnalyzeQueryResult;\n try {\n const authOk = await z.inspector.authenticate(config.adminPassword ?? '');\n if (!authOk) {\n throw new Error(\n 'admin password rejected (or --admin-password is required)',\n );\n }\n\n const rpcOptions = {\n vendedRows: config.outputVendedRows,\n syncedRows: config.outputSyncedRows,\n };\n\n if (plan.kind === 'ast') {\n result = await z.inspector.analyzeServerAST(plan.ast, rpcOptions);\n } else if (plan.kind === 'named') {\n result = await z.inspector.analyzeNamedQuery(\n plan.name,\n plan.args as ReadonlyArray<never>,\n rpcOptions,\n );\n } else {\n const built = buildZqlQuery(plan.text, createBuilder(opts.schema));\n result = await z.inspector.analyzeQuery(built, rpcOptions);\n }\n } catch (e) {\n colorConsole.error(e instanceof Error ? e.message : String(e));\n await z.close().catch(() => {});\n process.exit(1);\n }\n\n renderResult(result, {\n outputSyncedRows: config.outputSyncedRows,\n outputVendedRows: config.outputVendedRows,\n });\n\n await z.close();\n}\n\nfunction buildQueryPlan(config: {\n ast?: string | undefined;\n query?: string | undefined;\n queryName?: string | undefined;\n queryArgs?: string | undefined;\n}): QueryPlan {\n const selectors = [\n config.ast !== undefined && 'ast',\n config.query !== undefined && 'query',\n config.queryName !== undefined && 'queryName',\n ].filter(Boolean) as string[];\n\n if (selectors.length === 0) {\n colorConsole.error(\n 'Exactly one of --ast / --query / --query-name is required.',\n );\n process.exit(1);\n }\n if (selectors.length > 1) {\n colorConsole.error(\n `Only one of --ast / --query / --query-name may be provided; got: ${selectors.join(', ')}`,\n );\n process.exit(1);\n }\n\n if (config.ast !== undefined) {\n return {kind: 'ast', ast: JSON.parse(config.ast) as AST};\n }\n if (config.query !== undefined) {\n return {kind: 'zql', text: config.query};\n }\n const args = config.queryArgs\n ? (JSON.parse(config.queryArgs) as ReadonlyArray<unknown>)\n : [];\n return {kind: 'named', name: config.queryName as string, args};\n}\n\nfunction buildZqlQuery(\n queryString: string,\n builder: SchemaQuery<Schema>,\n): AnyQuery {\n const f = new Function('builder', `return builder.${queryString};`);\n return f(builder) as AnyQuery;\n}\n\nfunction resolveHandshakeHeaders(config: {\n cookie?: string | undefined;\n headersJson?: string | undefined;\n}): Record<string, string> {\n const headers: Record<string, string> = {};\n if (config.headersJson !== undefined) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(config.headersJson);\n } catch (e) {\n colorConsole.error(\n `--headers-json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`,\n );\n process.exit(1);\n }\n if (\n parsed === null ||\n typeof parsed !== 'object' ||\n Array.isArray(parsed)\n ) {\n colorConsole.error('--headers-json must be a JSON object.');\n process.exit(1);\n }\n for (const [k, val] of Object.entries(parsed)) {\n if (typeof val !== 'string') {\n colorConsole.error(\n `--headers-json values must be strings; got ${typeof val} for \"${k}\".`,\n );\n process.exit(1);\n }\n headers[k] = val;\n }\n }\n if (config.cookie !== undefined) {\n headers.cookie = config.cookie;\n }\n return headers;\n}\n\nfunction installWebSocketHeaderShim(headers: Record<string, string>): void {\n class HeaderInjectingWebSocket extends NodeWebSocket {\n constructor(url: string | URL, protocols?: string | string[]) {\n super(url, protocols, {headers});\n }\n }\n (globalThis as {WebSocket?: unknown}).WebSocket = HeaderInjectingWebSocket;\n}\n\nfunction renderResult(\n result: AnalyzeQueryResult,\n opts: {outputSyncedRows: boolean; outputVendedRows: boolean},\n) {\n if (opts.outputSyncedRows) {\n colorConsole.log(styleText(['blue', 'bold'], '=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(styleText('bold', table + ':'), rows);\n }\n }\n\n colorConsole.log(styleText(['blue', 'bold'], '=== Query Stats: ===\\n'));\n colorConsole.log(\n styleText('bold', 'total synced rows:'),\n result.syncedRowCount,\n );\n\n const readRowCountsByQuery = result.readRowCountsByQuery ?? {};\n let totalRowsRead = 0;\n for (const table of Object.keys(readRowCountsByQuery).sort()) {\n const counts = readRowCountsByQuery[table];\n for (const n of Object.values(counts)) {\n totalRowsRead += n;\n }\n colorConsole.log(styleText('bold', `${table} vended:`), counts);\n }\n colorConsole.log(\n styleText('bold', 'Rows Read (into JS):'),\n colorRowsConsidered(totalRowsRead),\n );\n const duration = result.elapsed ?? result.end - result.start;\n colorConsole.log(styleText('bold', 'time:'), colorTime(duration), 'ms');\n\n if (opts.outputVendedRows) {\n colorConsole.log(\n styleText(['blue', 'bold'], '=== JS Row Scan Values: ===\\n'),\n );\n for (const [table, rows] of Object.entries(result.readRows ?? {})) {\n colorConsole.log(styleText('bold', `${table}:`), rows);\n }\n }\n\n colorConsole.log(\n styleText(['blue', 'bold'], '\\n=== Rows Scanned (by SQLite): ===\\n'),\n );\n const dbScansByQuery = result.dbScansByQuery ?? {};\n let totalNVisit = 0;\n for (const [table, queries] of Object.entries(dbScansByQuery)) {\n colorConsole.log(styleText('bold', `${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n }\n colorConsole.log(\n styleText('bold', 'total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n );\n\n colorConsole.log(styleText(['blue', 'bold'], '\\n\\n=== Query Plans: ===\\n'));\n const plans = result.sqlitePlans ?? {};\n for (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(styleText('bold', 'query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n }\n\n if (result.warnings.length > 0) {\n colorConsole.log(styleText(['yellow', 'bold'], '=== Warnings: ===\\n'));\n for (const w of result.warnings) {\n colorConsole.log(styleText('yellow', w));\n }\n }\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return styleText('green', duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return styleText('yellow', duration.toFixed(2) + 'ms');\n }\n return styleText('red', duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return styleText('green', n.toString());\n } else if (n < 10000) {\n return styleText('yellow', n.toString());\n }\n return styleText('red', n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return styleText('yellow', row);\n }\n return styleText('red', row);\n }\n return styleText('green', row);\n}\n"],"mappings":"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"}
@@ -6,22 +6,22 @@ import { asQueryInternals } from "../../zql/src/query/query-internals.js";
6
6
  import { newQuery } from "../../zql/src/query/query-impl.js";
7
7
  import { clientToServer } from "../../zero-schema/src/name-mapper.js";
8
8
  import { QueryDelegateBase } from "../../zql/src/query/query-delegate-base.js";
9
- import { Database } from "../../zqlite/src/db.js";
10
- import { TableSource } from "../../zqlite/src/table-source.js";
11
9
  import "../../shared/src/dotenv.js";
12
10
  import { logLevel, logOptions } from "../../otel/src/log-options.js";
11
+ import { colorConsole, createLogContext } from "../../shared/src/logging.js";
13
12
  import { parseOptions } from "../../shared/src/options.js";
14
13
  import { Debug, runtimeDebugFlags } from "../../zql/src/builder/debug-delegate.js";
15
14
  import { getShardID, upstreamSchema } from "../../zero-cache/src/types/shards.js";
16
15
  import { ZERO_ENV_VAR_PREFIX, appOptions, shardOptions, zeroOptions } from "../../zero-cache/src/config/zero-config.js";
17
- import { colorConsole, createLogContext } from "../../shared/src/logging.js";
18
- import { pgClient } from "../../zero-cache/src/types/pg.js";
19
- import { deployPermissionsOptions, loadSchemaAndPermissions } from "../../zero-cache/src/scripts/permissions.js";
20
- import { computeZqlSpecs, mustGetTableSpec } from "../../zero-cache/src/db/lite-tables.js";
16
+ import { Database } from "../../zqlite/src/db.js";
17
+ import { TableSource } from "../../zqlite/src/table-source.js";
21
18
  import { astToZQL } from "../../ast-to-zql/src/ast-to-zql.js";
22
19
  import { formatOutput } from "../../ast-to-zql/src/format.js";
23
20
  import { testLogConfig } from "../../otel/src/test-log-config.js";
21
+ import { computeZqlSpecs, mustGetTableSpec } from "../../zero-cache/src/db/lite-tables.js";
22
+ import { deployPermissionsOptions, loadSchemaAndPermissions } from "../../zero-cache/src/scripts/permissions.js";
24
23
  import { runAst } from "../../zero-cache/src/services/run-ast.js";
24
+ import { pgClient } from "../../zero-cache/src/types/pg.js";
25
25
  import { explainQueries } from "./explain-queries.js";
26
26
  import { styleText } from "node:util";
27
27
  import fs from "node:fs";
@@ -4,11 +4,11 @@ import "../../shared/src/dotenv.js";
4
4
  import { parseOptions } from "../../shared/src/options.js";
5
5
  import { getShardID, upstreamSchema } from "../../zero-cache/src/types/shards.js";
6
6
  import { ZERO_ENV_VAR_PREFIX, appOptions, shardOptions } from "../../zero-cache/src/config/zero-config.js";
7
- import { pgClient } from "../../zero-cache/src/types/pg.js";
8
- import { loadSchemaAndPermissions } from "../../zero-cache/src/scripts/permissions.js";
9
7
  import { astToZQL } from "../../ast-to-zql/src/ast-to-zql.js";
10
8
  import { formatOutput } from "../../ast-to-zql/src/format.js";
9
+ import { loadSchemaAndPermissions } from "../../zero-cache/src/scripts/permissions.js";
11
10
  import { transformAndHashQuery } from "../../zero-cache/src/auth/read-authorizer.js";
11
+ import { pgClient } from "../../zero-cache/src/types/pg.js";
12
12
  import { LogContext, consoleLogSink } from "@rocicorp/logger";
13
13
  //#region ../analyze-query/src/bin-transform.ts
14
14
  var config = parseOptions({
@@ -2,9 +2,9 @@ import { valita_exports } from "../../shared/src/valita.js";
2
2
  import { mapAST } from "../../zero-protocol/src/ast.js";
3
3
  import { serverToClient } from "../../zero-schema/src/name-mapper.js";
4
4
  import { parseOptions } from "../../shared/src/options.js";
5
- import { loadSchemaAndPermissions } from "../../zero-cache/src/scripts/permissions.js";
6
5
  import { astToZQL } from "./ast-to-zql.js";
7
6
  import { formatOutput } from "./format.js";
7
+ import { loadSchemaAndPermissions } from "../../zero-cache/src/scripts/permissions.js";
8
8
  import process from "node:process";
9
9
  import { readFile } from "node:fs/promises";
10
10
  import { createInterface } from "node:readline";
@@ -1 +1 @@
1
- {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../../../shared/src/logging.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,UAAU,EACV,KAAK,QAAQ,EACb,KAAK,OAAO,EACb,MAAM,kBAAkB,CAAC;AAK1B,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB,CAAC;AAUF;;;GAGG;AACH,eAAO,MAAM,YAAY;mBACR,OAAO,EAAE;qBAGP,OAAO,EAAE;oBAGV,OAAO,EAAE;oBAGT,OAAO,EAAE;qBAGR,OAAO,EAAE;CAG3B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,OAQzB,CAAC;AA4BF,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAErD;AAED,wBAAgB,gBAAgB,CAC9B,EAAC,GAAG,EAAC,EAAE;IAAC,GAAG,EAAE,SAAS,CAAA;CAAC,EACvB,OAAO,KAAK,EACZ,IAAI,sDAAkB,GACrB,UAAU,CAOZ;AA0BD,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQ5D"}
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../../../shared/src/logging.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,UAAU,EACV,KAAK,QAAQ,EACb,KAAK,OAAO,EACb,MAAM,kBAAkB,CAAC;AAG1B,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB,CAAC;AAUF;;;GAGG;AACH,eAAO,MAAM,YAAY;mBACR,OAAO,EAAE;qBAGP,OAAO,EAAE;oBAGV,OAAO,EAAE;oBAGT,OAAO,EAAE;qBAGR,OAAO,EAAE;CAG3B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,OAQzB,CAAC;AA4BF,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAErD;AAED,wBAAgB,gBAAgB,CAC9B,EAAC,GAAG,EAAC,EAAE;IAAC,GAAG,EAAE,SAAS,CAAA;CAAC,EACvB,OAAO,KAAK,EACZ,IAAI,sDAAkB,GACrB,UAAU,CAOZ;AA0BD,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQ5D"}
@@ -1,7 +1,7 @@
1
1
  import { stringify } from "./bigint-json.js";
2
2
  import { LogContext } from "@rocicorp/logger";
3
- import { pid } from "node:process";
4
3
  import { styleText } from "node:util";
4
+ import { pid } from "node:process";
5
5
  //#region ../shared/src/logging.ts
6
6
  function style(color, args) {
7
7
  return styleText(color, args.join(" "));
@@ -1 +1 @@
1
- {"version":3,"file":"logging.js","names":[],"sources":["../../../../shared/src/logging.ts"],"sourcesContent":["/* oxlint-disable no-console */\nimport {\n type Context,\n LogContext,\n type LogLevel,\n type LogSink,\n} from '@rocicorp/logger';\nimport {pid} from 'node:process';\nimport {styleText} from 'node:util';\nimport {stringify} from './bigint-json.ts';\n\nexport type LogConfig = {\n level: LogLevel;\n format: 'text' | 'json';\n};\n\nfunction style(color: 'gray' | 'yellow' | 'red', args: unknown[]) {\n return styleText(color, args.join(' '));\n}\n\nconst COLOR_DEBUG = 'gray';\nconst COLOR_WARN = 'yellow';\nconst COLOR_ERROR = 'red';\n\n/**\n * Returns an object for writing colorized output to a provided console.\n * Note this should only be used when console is a TTY (i.e., Node).\n */\nexport const colorConsole = {\n log: (...args: unknown[]) => {\n console.log(...args);\n },\n debug: (...args: unknown[]) => {\n console.debug(style(COLOR_DEBUG, args));\n },\n info: (...args: unknown[]) => {\n console.info(...args);\n },\n warn: (...args: unknown[]) => {\n console.warn(style(COLOR_WARN, args));\n },\n error: (...args: unknown[]) => {\n console.error(style(COLOR_ERROR, args));\n },\n};\n\nexport const consoleSink: LogSink = {\n log(level, context, ...args) {\n colorConsole[level](\n toLocalIsoString(),\n stringifyContext(context),\n ...args.map(stringifyValue),\n );\n },\n};\n\nfunction toLocalIsoString(date = new Date()) {\n const tzo = -date.getTimezoneOffset();\n const sign = tzo >= 0 ? '+' : '-';\n const pad = (n: number, len = 2) => String(Math.abs(n)).padStart(len, '0');\n\n return (\n date.getFullYear() +\n '-' +\n pad(date.getMonth() + 1) +\n '-' +\n pad(date.getDate()) +\n 'T' +\n pad(date.getHours()) +\n ':' +\n pad(date.getMinutes()) +\n ':' +\n pad(date.getSeconds()) +\n '.' +\n pad(date.getMilliseconds(), 3) +\n sign +\n pad(tzo / 60) +\n ':' +\n pad(tzo % 60)\n );\n}\n\nexport function getLogSink(config: LogConfig): LogSink {\n return config.format === 'json' ? consoleJsonLogSink : consoleSink;\n}\n\nexport function createLogContext(\n {log}: {log: LogConfig},\n context = {},\n sink = getLogSink(log),\n): LogContext {\n const ctx = {pid, ...context};\n const lc = new LogContext(log.level, ctx, sink);\n // Emit a blank line to absorb random ANSI control code garbage that\n // for some reason gets prepended to the first log line in CloudWatch.\n lc.info?.('');\n return lc;\n}\n\nconst consoleJsonLogSink: LogSink = {\n log(level: LogLevel, context: Context | undefined, ...args: unknown[]): void {\n // If the last arg is an object or an Error, combine those fields into the message.\n const lastObj = errorOrObject(args.at(-1));\n if (lastObj) {\n args.pop();\n }\n const message = args.length\n ? {\n message: args.map(stringifyValue).join(' '),\n }\n : undefined;\n\n console[level](\n stringify({\n level: level.toUpperCase(),\n ...context,\n ...lastObj,\n ...message,\n }),\n );\n },\n};\n\nexport function errorOrObject(v: unknown): object | undefined {\n if (v instanceof Error) {\n return toErrorLogObject(v);\n }\n if (v && typeof v === 'object') {\n return v;\n }\n return undefined;\n}\n\nfunction toErrorLogObject(v: Error) {\n return {\n ...v, // some properties of Error subclasses may be enumerable\n name: v.name,\n errorMsg: v.message,\n stack: v.stack,\n ...('cause' in v ? {cause: errorOrObject(v.cause)} : null),\n };\n}\n\nfunction stringifyContext(context: Context | undefined): unknown[] {\n const args = [];\n for (const [k, v] of Object.entries(context ?? {})) {\n const arg = v === undefined ? k : `${k}=${v}`;\n args.push(arg);\n }\n return args;\n}\n\nfunction stringifyValue(v: unknown) {\n if (typeof v === 'string') {\n return v;\n }\n if (v instanceof Error) {\n return stringify(toErrorLogObject(v));\n }\n return stringify(v);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"logging.js","names":[],"sources":["../../../../shared/src/logging.ts"],"sourcesContent":["import {pid} from 'node:process';\nimport {styleText} from 'node:util';\n/* oxlint-disable no-console */\nimport {\n type Context,\n LogContext,\n type LogLevel,\n type LogSink,\n} from '@rocicorp/logger';\nimport {stringify} from './bigint-json.ts';\n\nexport type LogConfig = {\n level: LogLevel;\n format: 'text' | 'json';\n};\n\nfunction style(color: 'gray' | 'yellow' | 'red', args: unknown[]) {\n return styleText(color, args.join(' '));\n}\n\nconst COLOR_DEBUG = 'gray';\nconst COLOR_WARN = 'yellow';\nconst COLOR_ERROR = 'red';\n\n/**\n * Returns an object for writing colorized output to a provided console.\n * Note this should only be used when console is a TTY (i.e., Node).\n */\nexport const colorConsole = {\n log: (...args: unknown[]) => {\n console.log(...args);\n },\n debug: (...args: unknown[]) => {\n console.debug(style(COLOR_DEBUG, args));\n },\n info: (...args: unknown[]) => {\n console.info(...args);\n },\n warn: (...args: unknown[]) => {\n console.warn(style(COLOR_WARN, args));\n },\n error: (...args: unknown[]) => {\n console.error(style(COLOR_ERROR, args));\n },\n};\n\nexport const consoleSink: LogSink = {\n log(level, context, ...args) {\n colorConsole[level](\n toLocalIsoString(),\n stringifyContext(context),\n ...args.map(stringifyValue),\n );\n },\n};\n\nfunction toLocalIsoString(date = new Date()) {\n const tzo = -date.getTimezoneOffset();\n const sign = tzo >= 0 ? '+' : '-';\n const pad = (n: number, len = 2) => String(Math.abs(n)).padStart(len, '0');\n\n return (\n date.getFullYear() +\n '-' +\n pad(date.getMonth() + 1) +\n '-' +\n pad(date.getDate()) +\n 'T' +\n pad(date.getHours()) +\n ':' +\n pad(date.getMinutes()) +\n ':' +\n pad(date.getSeconds()) +\n '.' +\n pad(date.getMilliseconds(), 3) +\n sign +\n pad(tzo / 60) +\n ':' +\n pad(tzo % 60)\n );\n}\n\nexport function getLogSink(config: LogConfig): LogSink {\n return config.format === 'json' ? consoleJsonLogSink : consoleSink;\n}\n\nexport function createLogContext(\n {log}: {log: LogConfig},\n context = {},\n sink = getLogSink(log),\n): LogContext {\n const ctx = {pid, ...context};\n const lc = new LogContext(log.level, ctx, sink);\n // Emit a blank line to absorb random ANSI control code garbage that\n // for some reason gets prepended to the first log line in CloudWatch.\n lc.info?.('');\n return lc;\n}\n\nconst consoleJsonLogSink: LogSink = {\n log(level: LogLevel, context: Context | undefined, ...args: unknown[]): void {\n // If the last arg is an object or an Error, combine those fields into the message.\n const lastObj = errorOrObject(args.at(-1));\n if (lastObj) {\n args.pop();\n }\n const message = args.length\n ? {\n message: args.map(stringifyValue).join(' '),\n }\n : undefined;\n\n console[level](\n stringify({\n level: level.toUpperCase(),\n ...context,\n ...lastObj,\n ...message,\n }),\n );\n },\n};\n\nexport function errorOrObject(v: unknown): object | undefined {\n if (v instanceof Error) {\n return toErrorLogObject(v);\n }\n if (v && typeof v === 'object') {\n return v;\n }\n return undefined;\n}\n\nfunction toErrorLogObject(v: Error) {\n return {\n ...v, // some properties of Error subclasses may be enumerable\n name: v.name,\n errorMsg: v.message,\n stack: v.stack,\n ...('cause' in v ? {cause: errorOrObject(v.cause)} : null),\n };\n}\n\nfunction stringifyContext(context: Context | undefined): unknown[] {\n const args = [];\n for (const [k, v] of Object.entries(context ?? {})) {\n const arg = v === undefined ? k : `${k}=${v}`;\n args.push(arg);\n }\n return args;\n}\n\nfunction stringifyValue(v: unknown) {\n if (typeof v === 'string') {\n return v;\n }\n if (v instanceof Error) {\n return stringify(toErrorLogObject(v));\n }\n return stringify(v);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../../shared/src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAUrD,OAAO,KAAK,EACV,MAAM,EACN,KAAK,EACL,MAAM,EACN,OAAO,EACP,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC;AAEjC,YAAY,EAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAC,CAAC;AAiFhE;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,SAAK;;cAgC1E;AAeD,MAAM,MAAM,YAAY,GAAG;IACzB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,WAAW,CAAC,EAAE;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAElD,0BAA0B;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,0BAA0B;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAExB,0BAA0B;IAC1B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,sGAAsG;IACtG,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,4BAA4B;IAC5B,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB,iCAAiC;IACjC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,KAAK,CAAC;CACjD,CAAC;AAEF,wBAAgB,YAAY,CAAC,CAAC,SAAS,OAAO,EAC5C,UAAU,EAAE,CAAC,EACb,IAAI,GAAE,YAAiB,GACtB,MAAM,CAAC,CAAC,CAAC,CAEX;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,OAAO,EACpD,UAAU,EAAE,CAAC,EACb,IAAI,GAAE,YAAiB,GACtB;IAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAC,CA0KtE;AA6FD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAQ7D"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../../shared/src/options.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AASrD,OAAO,KAAK,EACV,MAAM,EACN,KAAK,EACL,MAAM,EACN,OAAO,EACP,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC;AAEjC,YAAY,EAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAC,CAAC;AAiFhE;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,SAAK;;cAgC1E;AAeD,MAAM,MAAM,YAAY,GAAG;IACzB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,WAAW,CAAC,EAAE;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAElD,0BAA0B;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,0BAA0B;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAExB,0BAA0B;IAC1B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,sGAAsG;IACtG,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,4BAA4B;IAC5B,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB,iCAAiC;IACjC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,KAAK,CAAC;CACjD,CAAC;AAEF,wBAAgB,YAAY,CAAC,CAAC,SAAS,OAAO,EAC5C,UAAU,EAAE,CAAC,EACb,IAAI,GAAE,YAAiB,GACtB,MAAM,CAAC,CAAC,CAAC,CAEX;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,OAAO,EACpD,UAAU,EAAE,CAAC,EACb,IAAI,GAAE,YAAiB,GACtB;IAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAC,CA0KtE;AA6FD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAQ7D"}
@@ -1,12 +1,12 @@
1
1
  import { assert } from "./asserts.js";
2
2
  import { deepPartial, instanceOfAbstractType, parse, testOptional, valita_exports } from "./valita.js";
3
3
  import { must } from "./must.js";
4
+ import { stripVTControlCharacters } from "node:util";
4
5
  import { template } from "chalk-template";
5
6
  import commandLineArgs from "command-line-args";
6
7
  import commandLineUsage from "command-line-usage";
7
8
  import { createDefu } from "defu";
8
9
  import { toKebabCase, toSnakeCase } from "kasi";
9
- import { stripVTControlCharacters } from "node:util";
10
10
  //#region ../shared/src/options.ts
11
11
  /**
12
12
  * Creates a defu instance that overrides arrays instead of merging them.
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","names":[],"sources":["../../../../shared/src/options.ts"],"sourcesContent":["import type {OptionalLogger} from '@rocicorp/logger';\nimport {template} from 'chalk-template';\nimport type {OptionDefinition} from 'command-line-args';\nimport commandLineArgs from 'command-line-args';\nimport commandLineUsage, {type Section} from 'command-line-usage';\nimport {createDefu} from 'defu';\nimport {toKebabCase, toSnakeCase} from 'kasi';\nimport {stripVTControlCharacters as stripAnsi} from 'node:util';\nimport {assert} from './asserts.ts';\nimport {must} from './must.ts';\nimport type {\n Config,\n Group,\n Option,\n Options,\n WrappedOptionType,\n} from './options-types.ts';\nimport * as v from './valita.ts';\n\nexport type {Config, Group, Option, Options, WrappedOptionType};\n\ntype Primitive = number | string | boolean;\ntype Value = Primitive | Array<Primitive>;\n\ntype RequiredOptionType =\n | v.Type<string>\n | v.Type<number>\n | v.Type<boolean>\n | v.Type<string[]>\n | v.Type<number[]>\n | v.Type<boolean[]>;\n\ntype OptionalOptionType =\n | v.Optional<string>\n | v.Optional<number>\n | v.Optional<boolean>\n | v.Optional<string[]>\n | v.Optional<number[]>\n | v.Optional<boolean[]>;\n\ntype OptionType = RequiredOptionType | OptionalOptionType;\n\n/**\n * Creates a defu instance that overrides arrays instead of merging them.\n */\nconst defu = createDefu((obj, key, value) => {\n if (!Array.isArray(value)) return;\n\n obj[key] = value;\n return true;\n});\n\n/**\n * Converts an Options instance into its corresponding {@link Config} schema.\n */\nfunction configSchema<T extends Options>(\n options: T,\n envNamePrefix: string,\n): v.Type<Config<T>> {\n function makeObjectType(options: Options | Group, group?: string) {\n return v.object(\n Object.fromEntries(\n Object.entries(options).map(\n ([name, value]): [string, OptionType | v.Type] => {\n const addErrorMessage = (t: OptionType) => {\n const {required} = getRequiredOrDefault(t);\n if (required) {\n // Adds an error message for required options that includes the\n // actual name of the option.\n const optionName = toSnakeCase(\n `${envNamePrefix}${group ? group + '_' : ''}${name}`,\n ).toUpperCase();\n return (t as v.Type<string>)\n .optional()\n .assert(\n val => val !== undefined,\n `Missing required option ${optionName}`,\n );\n }\n return t;\n };\n // OptionType\n if (v.instanceOfAbstractType(value)) {\n return [name, addErrorMessage(value)];\n }\n // WrappedOptionType\n const {type} = value;\n if (v.instanceOfAbstractType(type)) {\n return [name, addErrorMessage(type)];\n }\n // OptionGroup\n return [name, makeObjectType(value as Group, name)];\n },\n ),\n ),\n );\n }\n return makeObjectType(options) as v.Type<Config<T>>;\n}\n\n/**\n * Converts an Options instance into an \"env schema\", which is an object with\n * ENV names as its keys, mapped to optional or required string values\n * (corresponding to the optionality of the corresponding options).\n *\n * This is used as a format for encoding options for a multi-tenant version\n * of an app, with an envSchema for each tenant.\n */\nexport function envSchema<T extends Options>(options: T, envNamePrefix = '') {\n const fields: [string, v.Type<string> | v.Optional<string>][] = [];\n\n function addField(name: string, type: OptionType, group?: string) {\n const flag = group ? `${group}_${name}` : name;\n const env = toSnakeCase(`${envNamePrefix}${flag}`).toUpperCase();\n\n const {required} = getRequiredOrDefault(type);\n fields.push([env, required ? v.string() : v.string().optional()]);\n }\n\n function addFields(o: Options | Group, group?: string) {\n Object.entries(o).forEach(([name, value]) => {\n // OptionType\n if (v.instanceOfAbstractType(value)) {\n addField(name, value, group);\n return;\n }\n // WrappedOptionType\n const {type} = value;\n if (v.instanceOfAbstractType(type)) {\n addField(name, type, group);\n return;\n }\n // OptionGroup\n addFields(value as Group, name);\n });\n }\n\n addFields(options);\n\n return v.object(Object.fromEntries(fields));\n}\n\n// type TerminalType is not exported from badrap/valita\ntype TerminalType = Parameters<\n Parameters<v.Type<unknown>['toTerminals']>[0]\n>[0];\n\nfunction getRequiredOrDefault(type: OptionType) {\n const defaultResult = v.testOptional<Value>(undefined, type);\n return {\n required: !defaultResult.ok,\n defaultValue: defaultResult.ok ? defaultResult.value : undefined,\n };\n}\n\nexport type ParseOptions = {\n /** Defaults to process.argv.slice(2) */\n argv?: string[];\n\n envNamePrefix?: string;\n\n description?: {header: string; content: string}[];\n\n /** Defaults to `false` */\n allowUnknown?: boolean;\n\n /** Defaults to `false` */\n allowPartial?: boolean;\n\n /** Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n\n /** Defaults to `true`. */\n emitDeprecationWarnings?: boolean;\n\n /** Defaults to `true`. When false, excludes default values from both config and env return values. */\n includeDefaults?: boolean;\n\n /** Defaults to `console` */\n logger?: OptionalLogger;\n\n /** Defaults to `process.exit` */\n exit?: (code?: number | string | null) => never;\n};\n\nexport function parseOptions<T extends Options>(\n appOptions: T,\n opts: ParseOptions = {},\n): Config<T> {\n return parseOptionsAdvanced(appOptions, opts).config;\n}\n\nexport function parseOptionsAdvanced<T extends Options>(\n appOptions: T,\n opts: ParseOptions = {},\n): {config: Config<T>; env: Record<string, string>; unknown?: string[]} {\n const {\n argv = process.argv.slice(2),\n envNamePrefix = '',\n description = [],\n allowUnknown = false,\n allowPartial = false,\n env: processEnv = process.env,\n emitDeprecationWarnings = true,\n includeDefaults = true,\n logger = console,\n exit = process.exit,\n } = opts;\n // The main logic for converting a valita Type spec to an Option (i.e. flag) spec.\n function addOption(field: string, option: WrappedOptionType, group?: string) {\n const {type, desc = [], deprecated, alias, hidden} = option;\n\n // The group name is prepended to the flag name.\n const flag = group ? toKebabCase(`${group}-${field}`) : toKebabCase(field);\n\n const {required, defaultValue} = getRequiredOrDefault(type);\n let multiple = type.name === 'array';\n const literals = new Set<string>();\n const terminalTypes = new Set<string>();\n\n type.toTerminals(getTerminalTypes);\n\n function getTerminalTypes(t: TerminalType) {\n switch (t.name) {\n case 'undefined':\n case 'optional':\n break;\n case 'array': {\n multiple = true;\n t.prefix.forEach(t => t.toTerminals(getTerminalTypes));\n t.rest?.toTerminals(getTerminalTypes);\n t.suffix.forEach(t => t.toTerminals(getTerminalTypes));\n break;\n }\n case 'literal':\n literals.add(String(t.value));\n terminalTypes.add(typeof t.value);\n break;\n default:\n terminalTypes.add(t.name);\n break;\n }\n }\n const env = toSnakeCase(`${envNamePrefix}${flag}`).toUpperCase();\n if (terminalTypes.size > 1) {\n throw new TypeError(`${env} has mixed types ${[...terminalTypes]}`);\n }\n assert(terminalTypes.size === 1, 'Expected exactly one terminal type');\n const terminalType = [...terminalTypes][0];\n\n if (processEnv[env]) {\n if (multiple) {\n // Technically not water-tight; assumes values for the string[] flag don't contain commas.\n envArgv.push(`--${flag}`, ...processEnv[env].split(','));\n } else {\n envArgv.push(`--${flag}`, processEnv[env]);\n }\n }\n names.set(flag, {field, env});\n\n const spec = [\n (required\n ? '{italic required}'\n : defaultValue !== undefined\n ? `default: ${JSON.stringify(defaultValue)}`\n : 'optional') + '\\n',\n ];\n if (desc) {\n spec.push(...desc);\n }\n\n const typeLabel = [\n literals.size\n ? String(Array.from(literals, l => `{underline ${l}}`))\n : multiple\n ? `{underline ${terminalType}[]}`\n : `{underline ${terminalType}}`,\n ` ${env} env`,\n ];\n\n const opt = {\n name: flag,\n alias,\n type: valueParser(\n env,\n terminalType,\n logger,\n emitDeprecationWarnings ? deprecated : undefined,\n ),\n multiple,\n group,\n description: spec.join('\\n') + '\\n',\n typeLabel: typeLabel.join('\\n') + '\\n',\n hidden: hidden === undefined ? deprecated !== undefined : hidden,\n };\n optsWithoutDefaults.push(opt);\n optsWithDefaults.push({...opt, defaultValue});\n }\n\n const names = new Map<string, {field: string; env: string}>();\n const optsWithDefaults: DescribedOptionDefinition[] = [];\n const optsWithoutDefaults: DescribedOptionDefinition[] = [];\n const envArgv: string[] = [];\n\n try {\n for (const [name, val] of Object.entries(appOptions)) {\n const {type} = val as {type: unknown};\n if (v.instanceOfAbstractType(val)) {\n addOption(name, {type: val});\n } else if (v.instanceOfAbstractType(type)) {\n addOption(name, val as WrappedOptionType);\n } else {\n const group = name;\n for (const [name, option] of Object.entries(val as Group)) {\n const wrapped = v.instanceOfAbstractType(option)\n ? {type: option}\n : option;\n addOption(name, wrapped, group);\n }\n }\n }\n\n const [defaults, env1, unknown] = parseArgs(optsWithDefaults, argv, names);\n const [fromEnv, env2] = parseArgs(optsWithoutDefaults, envArgv, names);\n const [withoutDefaults, env3] = parseArgs(optsWithoutDefaults, argv, names);\n\n switch (unknown?.[0]) {\n case undefined:\n break;\n case '--help':\n case '-h':\n showUsage(optsWithDefaults, description, logger);\n exit(0);\n break;\n default:\n if (!allowUnknown) {\n logger.error?.('Invalid arguments:', unknown);\n showUsage(optsWithDefaults, description, logger);\n exit(0);\n }\n break;\n }\n\n const parsedArgs = includeDefaults\n ? defu(withoutDefaults, fromEnv, defaults)\n : defu(withoutDefaults, fromEnv);\n const env = includeDefaults\n ? {...env1, ...env2, ...env3}\n : {...env2, ...env3};\n\n let schema = configSchema(appOptions, envNamePrefix);\n if (allowPartial || !includeDefaults) {\n // TODO: Type configSchema() to return a v.ObjectType<...>\n schema = v.deepPartial(schema as v.ObjectType) as v.Type<Config<T>>;\n }\n return {\n config: v.parse(parsedArgs, schema),\n env,\n ...(unknown ? {unknown} : {}),\n };\n } catch (e) {\n logger.error?.(String(e));\n showUsage(optsWithDefaults, description, logger);\n throw e;\n }\n}\n\nfunction valueParser(\n optionName: string,\n typeName: string,\n logger: OptionalLogger,\n deprecated: string[] | undefined,\n) {\n return (input: string) => {\n if (deprecated) {\n logger.warn?.(\n template(\n `\\n${optionName} is deprecated:\\n` + deprecated.join('\\n') + '\\n',\n ),\n );\n }\n switch (typeName) {\n case 'string':\n return input;\n case 'boolean':\n return parseBoolean(optionName, input);\n case 'number': {\n const val = Number(input);\n if (Number.isNaN(val)) {\n throw new TypeError(`Invalid input for ${optionName}: \"${input}\"`);\n }\n return val;\n }\n default:\n // Should be impossible given the constraints of `Option`\n throw new TypeError(\n `${optionName} option has unsupported type ${typeName}`,\n );\n }\n };\n}\n\nfunction parseArgs(\n optionDefs: DescribedOptionDefinition[],\n argv: string[],\n names: Map<string, {field: string; env: string}>,\n) {\n function normalizeFlagValue(value: unknown) {\n // A --flag without value is parsed by commandLineArgs() to `null`,\n // but this is a common convention to set a boolean flag to true.\n return value === null ? true : value;\n }\n\n const {\n _all,\n _none: ungrouped,\n _unknown: unknown,\n ...config\n } = commandLineArgs(optionDefs, {\n argv,\n partial: true,\n });\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const result: Record<string, any> = {};\n const envObj: Record<string, string> = {};\n\n function addFlag(flagName: string, value: unknown, group?: string) {\n const {field, env} = must(names.get(flagName));\n const normalized = normalizeFlagValue(value);\n if (group) {\n result[group][field] = normalized;\n } else {\n result[field] = normalized;\n }\n envObj[env] = String(normalized);\n }\n\n for (const [flagName, value] of Object.entries(ungrouped ?? {})) {\n addFlag(flagName, value);\n }\n\n // Then handle (potentially) grouped flags\n for (const [name, value] of Object.entries(config)) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n addFlag(name, value); // Flag, not a group\n } else {\n const group = name;\n result[group] = {};\n for (const [flagName, flagValue] of Object.entries(value)) {\n addFlag(flagName, flagValue, group);\n }\n }\n }\n\n return [result, envObj, unknown] as const;\n}\n\nexport function flagToEnv(prefix: string, flag: string): string {\n return toSnakeCase(prefix + flag).toUpperCase();\n}\n\nexport function parseBoolean(optionName: string, input: string) {\n const bool = input.toLowerCase();\n if (['true', '1'].includes(bool)) {\n return true;\n } else if (['false', '0'].includes(bool)) {\n return false;\n }\n throw new TypeError(`Invalid input for ${optionName}: \"${input}\"`);\n}\n\nfunction showUsage(\n optionList: DescribedOptionDefinition[],\n description: {header: string; content: string}[] = [],\n logger: OptionalLogger = console,\n) {\n const hide: string[] = [];\n let leftWidth = 35;\n let rightWidth = 70;\n optionList.forEach(({name, typeLabel, description, hidden}) => {\n if (hidden) {\n hide.push(name);\n }\n const text = template(`${name} ${typeLabel ?? ''}`);\n const lines = stripAnsi(text).split('\\n');\n for (const l of lines) {\n leftWidth = Math.max(leftWidth, l.length + 2);\n }\n const desc = stripAnsi(template(description ?? '')).split('\\n');\n for (const l of desc) {\n rightWidth = Math.max(rightWidth, l.length + 2);\n }\n });\n\n const sections: Section[] = [\n {\n optionList,\n reverseNameOrder: true, // Display --flag-name before -alias\n hide,\n tableOptions: {\n columns: [\n {name: 'option', width: leftWidth},\n {name: 'description', width: rightWidth},\n ],\n noTrim: true,\n },\n },\n ];\n\n if (description) {\n sections.unshift(...description);\n }\n\n logger.info?.(commandLineUsage(sections));\n}\n\ntype DescribedOptionDefinition = OptionDefinition & {\n // Additional fields recognized by command-line-usage\n description?: string;\n typeLabel?: string | undefined;\n hidden?: boolean | undefined;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"options.js","names":[],"sources":["../../../../shared/src/options.ts"],"sourcesContent":["import {stripVTControlCharacters as stripAnsi} from 'node:util';\nimport type {OptionalLogger} from '@rocicorp/logger';\nimport {template} from 'chalk-template';\nimport type {OptionDefinition} from 'command-line-args';\nimport commandLineArgs from 'command-line-args';\nimport commandLineUsage, {type Section} from 'command-line-usage';\nimport {createDefu} from 'defu';\nimport {toKebabCase, toSnakeCase} from 'kasi';\nimport {assert} from './asserts.ts';\nimport {must} from './must.ts';\nimport type {\n Config,\n Group,\n Option,\n Options,\n WrappedOptionType,\n} from './options-types.ts';\nimport * as v from './valita.ts';\n\nexport type {Config, Group, Option, Options, WrappedOptionType};\n\ntype Primitive = number | string | boolean;\ntype Value = Primitive | Array<Primitive>;\n\ntype RequiredOptionType =\n | v.Type<string>\n | v.Type<number>\n | v.Type<boolean>\n | v.Type<string[]>\n | v.Type<number[]>\n | v.Type<boolean[]>;\n\ntype OptionalOptionType =\n | v.Optional<string>\n | v.Optional<number>\n | v.Optional<boolean>\n | v.Optional<string[]>\n | v.Optional<number[]>\n | v.Optional<boolean[]>;\n\ntype OptionType = RequiredOptionType | OptionalOptionType;\n\n/**\n * Creates a defu instance that overrides arrays instead of merging them.\n */\nconst defu = createDefu((obj, key, value) => {\n if (!Array.isArray(value)) return;\n\n obj[key] = value;\n return true;\n});\n\n/**\n * Converts an Options instance into its corresponding {@link Config} schema.\n */\nfunction configSchema<T extends Options>(\n options: T,\n envNamePrefix: string,\n): v.Type<Config<T>> {\n function makeObjectType(options: Options | Group, group?: string) {\n return v.object(\n Object.fromEntries(\n Object.entries(options).map(\n ([name, value]): [string, OptionType | v.Type] => {\n const addErrorMessage = (t: OptionType) => {\n const {required} = getRequiredOrDefault(t);\n if (required) {\n // Adds an error message for required options that includes the\n // actual name of the option.\n const optionName = toSnakeCase(\n `${envNamePrefix}${group ? group + '_' : ''}${name}`,\n ).toUpperCase();\n return (t as v.Type<string>)\n .optional()\n .assert(\n val => val !== undefined,\n `Missing required option ${optionName}`,\n );\n }\n return t;\n };\n // OptionType\n if (v.instanceOfAbstractType(value)) {\n return [name, addErrorMessage(value)];\n }\n // WrappedOptionType\n const {type} = value;\n if (v.instanceOfAbstractType(type)) {\n return [name, addErrorMessage(type)];\n }\n // OptionGroup\n return [name, makeObjectType(value as Group, name)];\n },\n ),\n ),\n );\n }\n return makeObjectType(options) as v.Type<Config<T>>;\n}\n\n/**\n * Converts an Options instance into an \"env schema\", which is an object with\n * ENV names as its keys, mapped to optional or required string values\n * (corresponding to the optionality of the corresponding options).\n *\n * This is used as a format for encoding options for a multi-tenant version\n * of an app, with an envSchema for each tenant.\n */\nexport function envSchema<T extends Options>(options: T, envNamePrefix = '') {\n const fields: [string, v.Type<string> | v.Optional<string>][] = [];\n\n function addField(name: string, type: OptionType, group?: string) {\n const flag = group ? `${group}_${name}` : name;\n const env = toSnakeCase(`${envNamePrefix}${flag}`).toUpperCase();\n\n const {required} = getRequiredOrDefault(type);\n fields.push([env, required ? v.string() : v.string().optional()]);\n }\n\n function addFields(o: Options | Group, group?: string) {\n Object.entries(o).forEach(([name, value]) => {\n // OptionType\n if (v.instanceOfAbstractType(value)) {\n addField(name, value, group);\n return;\n }\n // WrappedOptionType\n const {type} = value;\n if (v.instanceOfAbstractType(type)) {\n addField(name, type, group);\n return;\n }\n // OptionGroup\n addFields(value as Group, name);\n });\n }\n\n addFields(options);\n\n return v.object(Object.fromEntries(fields));\n}\n\n// type TerminalType is not exported from badrap/valita\ntype TerminalType = Parameters<\n Parameters<v.Type<unknown>['toTerminals']>[0]\n>[0];\n\nfunction getRequiredOrDefault(type: OptionType) {\n const defaultResult = v.testOptional<Value>(undefined, type);\n return {\n required: !defaultResult.ok,\n defaultValue: defaultResult.ok ? defaultResult.value : undefined,\n };\n}\n\nexport type ParseOptions = {\n /** Defaults to process.argv.slice(2) */\n argv?: string[];\n\n envNamePrefix?: string;\n\n description?: {header: string; content: string}[];\n\n /** Defaults to `false` */\n allowUnknown?: boolean;\n\n /** Defaults to `false` */\n allowPartial?: boolean;\n\n /** Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n\n /** Defaults to `true`. */\n emitDeprecationWarnings?: boolean;\n\n /** Defaults to `true`. When false, excludes default values from both config and env return values. */\n includeDefaults?: boolean;\n\n /** Defaults to `console` */\n logger?: OptionalLogger;\n\n /** Defaults to `process.exit` */\n exit?: (code?: number | string | null) => never;\n};\n\nexport function parseOptions<T extends Options>(\n appOptions: T,\n opts: ParseOptions = {},\n): Config<T> {\n return parseOptionsAdvanced(appOptions, opts).config;\n}\n\nexport function parseOptionsAdvanced<T extends Options>(\n appOptions: T,\n opts: ParseOptions = {},\n): {config: Config<T>; env: Record<string, string>; unknown?: string[]} {\n const {\n argv = process.argv.slice(2),\n envNamePrefix = '',\n description = [],\n allowUnknown = false,\n allowPartial = false,\n env: processEnv = process.env,\n emitDeprecationWarnings = true,\n includeDefaults = true,\n logger = console,\n exit = process.exit,\n } = opts;\n // The main logic for converting a valita Type spec to an Option (i.e. flag) spec.\n function addOption(field: string, option: WrappedOptionType, group?: string) {\n const {type, desc = [], deprecated, alias, hidden} = option;\n\n // The group name is prepended to the flag name.\n const flag = group ? toKebabCase(`${group}-${field}`) : toKebabCase(field);\n\n const {required, defaultValue} = getRequiredOrDefault(type);\n let multiple = type.name === 'array';\n const literals = new Set<string>();\n const terminalTypes = new Set<string>();\n\n type.toTerminals(getTerminalTypes);\n\n function getTerminalTypes(t: TerminalType) {\n switch (t.name) {\n case 'undefined':\n case 'optional':\n break;\n case 'array': {\n multiple = true;\n t.prefix.forEach(t => t.toTerminals(getTerminalTypes));\n t.rest?.toTerminals(getTerminalTypes);\n t.suffix.forEach(t => t.toTerminals(getTerminalTypes));\n break;\n }\n case 'literal':\n literals.add(String(t.value));\n terminalTypes.add(typeof t.value);\n break;\n default:\n terminalTypes.add(t.name);\n break;\n }\n }\n const env = toSnakeCase(`${envNamePrefix}${flag}`).toUpperCase();\n if (terminalTypes.size > 1) {\n throw new TypeError(`${env} has mixed types ${[...terminalTypes]}`);\n }\n assert(terminalTypes.size === 1, 'Expected exactly one terminal type');\n const terminalType = [...terminalTypes][0];\n\n if (processEnv[env]) {\n if (multiple) {\n // Technically not water-tight; assumes values for the string[] flag don't contain commas.\n envArgv.push(`--${flag}`, ...processEnv[env].split(','));\n } else {\n envArgv.push(`--${flag}`, processEnv[env]);\n }\n }\n names.set(flag, {field, env});\n\n const spec = [\n (required\n ? '{italic required}'\n : defaultValue !== undefined\n ? `default: ${JSON.stringify(defaultValue)}`\n : 'optional') + '\\n',\n ];\n if (desc) {\n spec.push(...desc);\n }\n\n const typeLabel = [\n literals.size\n ? String(Array.from(literals, l => `{underline ${l}}`))\n : multiple\n ? `{underline ${terminalType}[]}`\n : `{underline ${terminalType}}`,\n ` ${env} env`,\n ];\n\n const opt = {\n name: flag,\n alias,\n type: valueParser(\n env,\n terminalType,\n logger,\n emitDeprecationWarnings ? deprecated : undefined,\n ),\n multiple,\n group,\n description: spec.join('\\n') + '\\n',\n typeLabel: typeLabel.join('\\n') + '\\n',\n hidden: hidden === undefined ? deprecated !== undefined : hidden,\n };\n optsWithoutDefaults.push(opt);\n optsWithDefaults.push({...opt, defaultValue});\n }\n\n const names = new Map<string, {field: string; env: string}>();\n const optsWithDefaults: DescribedOptionDefinition[] = [];\n const optsWithoutDefaults: DescribedOptionDefinition[] = [];\n const envArgv: string[] = [];\n\n try {\n for (const [name, val] of Object.entries(appOptions)) {\n const {type} = val as {type: unknown};\n if (v.instanceOfAbstractType(val)) {\n addOption(name, {type: val});\n } else if (v.instanceOfAbstractType(type)) {\n addOption(name, val as WrappedOptionType);\n } else {\n const group = name;\n for (const [name, option] of Object.entries(val as Group)) {\n const wrapped = v.instanceOfAbstractType(option)\n ? {type: option}\n : option;\n addOption(name, wrapped, group);\n }\n }\n }\n\n const [defaults, env1, unknown] = parseArgs(optsWithDefaults, argv, names);\n const [fromEnv, env2] = parseArgs(optsWithoutDefaults, envArgv, names);\n const [withoutDefaults, env3] = parseArgs(optsWithoutDefaults, argv, names);\n\n switch (unknown?.[0]) {\n case undefined:\n break;\n case '--help':\n case '-h':\n showUsage(optsWithDefaults, description, logger);\n exit(0);\n break;\n default:\n if (!allowUnknown) {\n logger.error?.('Invalid arguments:', unknown);\n showUsage(optsWithDefaults, description, logger);\n exit(0);\n }\n break;\n }\n\n const parsedArgs = includeDefaults\n ? defu(withoutDefaults, fromEnv, defaults)\n : defu(withoutDefaults, fromEnv);\n const env = includeDefaults\n ? {...env1, ...env2, ...env3}\n : {...env2, ...env3};\n\n let schema = configSchema(appOptions, envNamePrefix);\n if (allowPartial || !includeDefaults) {\n // TODO: Type configSchema() to return a v.ObjectType<...>\n schema = v.deepPartial(schema as v.ObjectType) as v.Type<Config<T>>;\n }\n return {\n config: v.parse(parsedArgs, schema),\n env,\n ...(unknown ? {unknown} : {}),\n };\n } catch (e) {\n logger.error?.(String(e));\n showUsage(optsWithDefaults, description, logger);\n throw e;\n }\n}\n\nfunction valueParser(\n optionName: string,\n typeName: string,\n logger: OptionalLogger,\n deprecated: string[] | undefined,\n) {\n return (input: string) => {\n if (deprecated) {\n logger.warn?.(\n template(\n `\\n${optionName} is deprecated:\\n` + deprecated.join('\\n') + '\\n',\n ),\n );\n }\n switch (typeName) {\n case 'string':\n return input;\n case 'boolean':\n return parseBoolean(optionName, input);\n case 'number': {\n const val = Number(input);\n if (Number.isNaN(val)) {\n throw new TypeError(`Invalid input for ${optionName}: \"${input}\"`);\n }\n return val;\n }\n default:\n // Should be impossible given the constraints of `Option`\n throw new TypeError(\n `${optionName} option has unsupported type ${typeName}`,\n );\n }\n };\n}\n\nfunction parseArgs(\n optionDefs: DescribedOptionDefinition[],\n argv: string[],\n names: Map<string, {field: string; env: string}>,\n) {\n function normalizeFlagValue(value: unknown) {\n // A --flag without value is parsed by commandLineArgs() to `null`,\n // but this is a common convention to set a boolean flag to true.\n return value === null ? true : value;\n }\n\n const {\n _all,\n _none: ungrouped,\n _unknown: unknown,\n ...config\n } = commandLineArgs(optionDefs, {\n argv,\n partial: true,\n });\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const result: Record<string, any> = {};\n const envObj: Record<string, string> = {};\n\n function addFlag(flagName: string, value: unknown, group?: string) {\n const {field, env} = must(names.get(flagName));\n const normalized = normalizeFlagValue(value);\n if (group) {\n result[group][field] = normalized;\n } else {\n result[field] = normalized;\n }\n envObj[env] = String(normalized);\n }\n\n for (const [flagName, value] of Object.entries(ungrouped ?? {})) {\n addFlag(flagName, value);\n }\n\n // Then handle (potentially) grouped flags\n for (const [name, value] of Object.entries(config)) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n addFlag(name, value); // Flag, not a group\n } else {\n const group = name;\n result[group] = {};\n for (const [flagName, flagValue] of Object.entries(value)) {\n addFlag(flagName, flagValue, group);\n }\n }\n }\n\n return [result, envObj, unknown] as const;\n}\n\nexport function flagToEnv(prefix: string, flag: string): string {\n return toSnakeCase(prefix + flag).toUpperCase();\n}\n\nexport function parseBoolean(optionName: string, input: string) {\n const bool = input.toLowerCase();\n if (['true', '1'].includes(bool)) {\n return true;\n } else if (['false', '0'].includes(bool)) {\n return false;\n }\n throw new TypeError(`Invalid input for ${optionName}: \"${input}\"`);\n}\n\nfunction showUsage(\n optionList: DescribedOptionDefinition[],\n description: {header: string; content: string}[] = [],\n logger: OptionalLogger = console,\n) {\n const hide: string[] = [];\n let leftWidth = 35;\n let rightWidth = 70;\n optionList.forEach(({name, typeLabel, description, hidden}) => {\n if (hidden) {\n hide.push(name);\n }\n const text = template(`${name} ${typeLabel ?? ''}`);\n const lines = stripAnsi(text).split('\\n');\n for (const l of lines) {\n leftWidth = Math.max(leftWidth, l.length + 2);\n }\n const desc = stripAnsi(template(description ?? '')).split('\\n');\n for (const l of desc) {\n rightWidth = Math.max(rightWidth, l.length + 2);\n }\n });\n\n const sections: Section[] = [\n {\n optionList,\n reverseNameOrder: true, // Display --flag-name before -alias\n hide,\n tableOptions: {\n columns: [\n {name: 'option', width: leftWidth},\n {name: 'description', width: rightWidth},\n ],\n noTrim: true,\n },\n },\n ];\n\n if (description) {\n sections.unshift(...description);\n }\n\n logger.info?.(commandLineUsage(sections));\n}\n\ntype DescribedOptionDefinition = OptionDefinition & {\n // Additional fields recognized by command-line-usage\n description?: string;\n typeLabel?: string | undefined;\n hidden?: boolean | undefined;\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../../z2s/src/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAQ7C,OAAO,EAAC,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAExD,OAAO,KAAK,EACV,GAAG,EAEH,kBAAkB,EAElB,WAAW,EAEX,QAAQ,EACR,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AACxE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,2BAA2B,CAAC;AAUtD,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,YAAY,CAAC;IAErB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF,wBAAgB,OAAO,CACrB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,GAAG,EACR,MAAM,CAAC,EAAE,MAAM,GACd,QAAQ,CAgBV;AA4CD,wBAAgB,KAAK,CACnB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAC5B,QAAQ,CAWV;AAUD,wBAAgB,OAAO,CACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,QAAQ,GAAG,SAAS,EAC7B,KAAK,EAAE,KAAK,GACX,QAAQ,CAoBV;AA4LD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,SAAS,eAAe,EAAE,EACxC,cAAc,EAAE,SAAS,MAAM,EAAE,GAChC,CAAC,UAAU,EAAE,KAAK,KAAK,QAAQ,CAiBjC;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAgCV;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAMV;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAIV;AAmGD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,kBAAkB,GAC/B;IACD,IAAI,EAAE,QAAQ,CAAC;IACf,mBAAmB,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;CAC/D,CA2BA;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,kBAAkB,GAC/B;IACD;QACE,KAAK,EAAE,KAAK,CAAC;QACb,WAAW,EAAE,WAAW,CAAC;QACzB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;KAC3B;IACD;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,WAAW,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;KAAC;CACpE,CAsBA;AAwED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAMhE"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../../z2s/src/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAQ7C,OAAO,EAAC,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAExD,OAAO,KAAK,EACV,GAAG,EAEH,kBAAkB,EAElB,WAAW,EAEX,QAAQ,EACR,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AACxE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,2BAA2B,CAAC;AAUtD,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,YAAY,CAAC;IAErB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF,wBAAgB,OAAO,CACrB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,GAAG,EACR,MAAM,CAAC,EAAE,MAAM,GACd,QAAQ,CAgBV;AA4CD,wBAAgB,KAAK,CACnB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAC5B,QAAQ,CAWV;AAUD,wBAAgB,OAAO,CACrB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,QAAQ,GAAG,SAAS,EAC7B,KAAK,EAAE,KAAK,GACX,QAAQ,CAoBV;AA4LD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,SAAS,eAAe,EAAE,EACxC,cAAc,EAAE,SAAS,MAAM,EAAE,GAChC,CAAC,UAAU,EAAE,KAAK,KAAK,QAAQ,CAiBjC;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAgCV;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAMV;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,KAAK,GACX,QAAQ,CAIV;AAmGD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,kBAAkB,GAC/B;IACD,IAAI,EAAE,QAAQ,CAAC;IACf,mBAAmB,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;CAC/D,CA2BA;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,kBAAkB,GAC/B;IACD;QACE,KAAK,EAAE,KAAK,CAAC;QACb,WAAW,EAAE,WAAW,CAAC;QACzB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;KAC3B;IACD;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,WAAW,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;KAAC;CACpE,CAsBA;AAyED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAMhE"}