primitive-admin 1.2.0-alpha.0 → 1.2.0-alpha.10

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 (412) hide show
  1. package/README.md +108 -136
  2. package/assets/skill/skills/primitive-platform/SKILL.md +37 -4
  3. package/dist/bin/primitive.js +30 -35
  4. package/dist/bin/primitive.js.map +1 -1
  5. package/dist/src/commands/agent-sessions.d.ts +133 -0
  6. package/dist/src/commands/agent-sessions.js +792 -0
  7. package/dist/src/commands/agent-sessions.js.map +1 -0
  8. package/dist/src/commands/analytics.js +0 -148
  9. package/dist/src/commands/analytics.js.map +1 -1
  10. package/dist/src/commands/apps-children.d.ts +54 -0
  11. package/dist/src/commands/apps-children.js +631 -0
  12. package/dist/src/commands/apps-children.js.map +1 -0
  13. package/dist/src/commands/apps.d.ts +6 -0
  14. package/dist/src/commands/apps.js +131 -9
  15. package/dist/src/commands/apps.js.map +1 -1
  16. package/dist/src/commands/auth-sessions.d.ts +3 -3
  17. package/dist/src/commands/auth-sessions.js +117 -23
  18. package/dist/src/commands/auth-sessions.js.map +1 -1
  19. package/dist/src/commands/auth.js +460 -36
  20. package/dist/src/commands/auth.js.map +1 -1
  21. package/dist/src/commands/collections.js +316 -256
  22. package/dist/src/commands/collections.js.map +1 -1
  23. package/dist/src/commands/config.d.ts +1 -1
  24. package/dist/src/commands/config.js +60 -28
  25. package/dist/src/commands/config.js.map +1 -1
  26. package/dist/src/commands/connections.js +12 -17
  27. package/dist/src/commands/connections.js.map +1 -1
  28. package/dist/src/commands/database-type-configs.js +2 -76
  29. package/dist/src/commands/database-type-configs.js.map +1 -1
  30. package/dist/src/commands/databases.d.ts +9 -0
  31. package/dist/src/commands/databases.js +228 -566
  32. package/dist/src/commands/databases.js.map +1 -1
  33. package/dist/src/commands/db3-types.d.ts +15 -0
  34. package/dist/src/commands/db3-types.js +157 -0
  35. package/dist/src/commands/db3-types.js.map +1 -0
  36. package/dist/src/commands/db3.d.ts +12 -0
  37. package/dist/src/commands/db3.js +1052 -0
  38. package/dist/src/commands/db3.js.map +1 -0
  39. package/dist/src/commands/documents.d.ts +121 -2
  40. package/dist/src/commands/documents.js +1601 -1251
  41. package/dist/src/commands/documents.js.map +1 -1
  42. package/dist/src/commands/env.d.ts +9 -1
  43. package/dist/src/commands/env.js +164 -49
  44. package/dist/src/commands/env.js.map +1 -1
  45. package/dist/src/commands/function-trigger-commands.d.ts +28 -0
  46. package/dist/src/commands/function-trigger-commands.js +341 -0
  47. package/dist/src/commands/function-trigger-commands.js.map +1 -0
  48. package/dist/src/commands/functions.js +297 -24
  49. package/dist/src/commands/functions.js.map +1 -1
  50. package/dist/src/commands/groups.js +150 -49
  51. package/dist/src/commands/groups.js.map +1 -1
  52. package/dist/src/commands/guides.js +5 -5
  53. package/dist/src/commands/init.d.ts +7 -0
  54. package/dist/src/commands/init.js +23 -5
  55. package/dist/src/commands/init.js.map +1 -1
  56. package/dist/src/commands/integrations.js +14 -8
  57. package/dist/src/commands/integrations.js.map +1 -1
  58. package/dist/src/commands/metadata-category-configs.d.ts +2 -2
  59. package/dist/src/commands/metadata-category-configs.js +2 -2
  60. package/dist/src/commands/prompts.d.ts +7 -0
  61. package/dist/src/commands/prompts.js +48 -5
  62. package/dist/src/commands/prompts.js.map +1 -1
  63. package/dist/src/commands/scripts.d.ts +9 -17
  64. package/dist/src/commands/scripts.js +24 -479
  65. package/dist/src/commands/scripts.js.map +1 -1
  66. package/dist/src/commands/sessions.js +3 -8
  67. package/dist/src/commands/sessions.js.map +1 -1
  68. package/dist/src/commands/sync-app-settings.d.ts +36 -8
  69. package/dist/src/commands/sync-app-settings.js +109 -23
  70. package/dist/src/commands/sync-app-settings.js.map +1 -1
  71. package/dist/src/commands/sync.d.ts +436 -613
  72. package/dist/src/commands/sync.js +2604 -5977
  73. package/dist/src/commands/sync.js.map +1 -1
  74. package/dist/src/commands/tokens.js +4 -9
  75. package/dist/src/commands/tokens.js.map +1 -1
  76. package/dist/src/commands/users.js +77 -2
  77. package/dist/src/commands/users.js.map +1 -1
  78. package/dist/src/commands/workflows.d.ts +5 -83
  79. package/dist/src/commands/workflows.js +57 -2282
  80. package/dist/src/commands/workflows.js.map +1 -1
  81. package/dist/src/lib/aggregate-output.d.ts +25 -0
  82. package/dist/src/lib/aggregate-output.js +53 -0
  83. package/dist/src/lib/aggregate-output.js.map +1 -0
  84. package/dist/src/lib/api-client.d.ts +681 -581
  85. package/dist/src/lib/api-client.js +880 -851
  86. package/dist/src/lib/api-client.js.map +1 -1
  87. package/dist/src/lib/app-settings-descriptor.d.ts +47 -1
  88. package/dist/src/lib/app-settings-descriptor.js +114 -10
  89. package/dist/src/lib/app-settings-descriptor.js.map +1 -1
  90. package/dist/src/lib/auth-fixtures.d.ts +44 -0
  91. package/dist/src/lib/auth-fixtures.js +61 -0
  92. package/dist/src/lib/auth-fixtures.js.map +1 -0
  93. package/dist/src/lib/auth-flow.d.ts +41 -1
  94. package/dist/src/lib/auth-flow.js +70 -16
  95. package/dist/src/lib/auth-flow.js.map +1 -1
  96. package/dist/src/lib/block-layout.d.ts +12 -23
  97. package/dist/src/lib/block-layout.js +26 -92
  98. package/dist/src/lib/block-layout.js.map +1 -1
  99. package/dist/src/lib/block-selector.d.ts +2 -2
  100. package/dist/src/lib/block-selector.js +2 -2
  101. package/dist/src/lib/child-apps-local.d.ts +164 -0
  102. package/dist/src/lib/child-apps-local.js +258 -0
  103. package/dist/src/lib/child-apps-local.js.map +1 -0
  104. package/dist/src/lib/ci-session-request.d.ts +22 -0
  105. package/dist/src/lib/ci-session-request.js +51 -0
  106. package/dist/src/lib/ci-session-request.js.map +1 -0
  107. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +10 -8
  108. package/dist/src/lib/codegen-shared/generatedFiles.js +21 -15
  109. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
  110. package/dist/src/lib/codegen-shared/prettierStable.d.ts +1 -1
  111. package/dist/src/lib/codegen-shared/prettierStable.js +1 -1
  112. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +2 -2
  113. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +2 -2
  114. package/dist/src/lib/collection-export.d.ts +76 -15
  115. package/dist/src/lib/collection-export.js +116 -23
  116. package/dist/src/lib/collection-export.js.map +1 -1
  117. package/dist/src/lib/collection-principal.d.ts +22 -0
  118. package/dist/src/lib/collection-principal.js +35 -0
  119. package/dist/src/lib/collection-principal.js.map +1 -0
  120. package/dist/src/lib/config-object-descriptor.d.ts +3 -22
  121. package/dist/src/lib/config-object-descriptor.js +56 -291
  122. package/dist/src/lib/config-object-descriptor.js.map +1 -1
  123. package/dist/src/lib/config-payload.js +2 -3
  124. package/dist/src/lib/config-payload.js.map +1 -1
  125. package/dist/src/lib/config-surface.d.ts +5 -7
  126. package/dist/src/lib/config-surface.js +18 -40
  127. package/dist/src/lib/config-surface.js.map +1 -1
  128. package/dist/src/lib/connections-list.d.ts +10 -0
  129. package/dist/src/lib/connections-list.js +18 -0
  130. package/dist/src/lib/connections-list.js.map +1 -0
  131. package/dist/src/lib/credentials-home.d.ts +58 -0
  132. package/dist/src/lib/credentials-home.js +204 -0
  133. package/dist/src/lib/credentials-home.js.map +1 -0
  134. package/dist/src/lib/credentials-lock.d.ts +88 -0
  135. package/dist/src/lib/credentials-lock.js +302 -0
  136. package/dist/src/lib/credentials-lock.js.map +1 -0
  137. package/dist/src/lib/credentials-store.d.ts +179 -24
  138. package/dist/src/lib/credentials-store.js +712 -77
  139. package/dist/src/lib/credentials-store.js.map +1 -1
  140. package/dist/src/lib/csv.d.ts +8 -9
  141. package/dist/src/lib/csv.js +3 -4
  142. package/dist/src/lib/csv.js.map +1 -1
  143. package/dist/src/lib/custodian.d.ts +8 -0
  144. package/dist/src/lib/custodian.js +18 -0
  145. package/dist/src/lib/custodian.js.map +1 -0
  146. package/dist/src/lib/db-codegen/dbGenerator.js +5 -16
  147. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
  148. package/dist/src/lib/db-codegen/dbNaming.d.ts +5 -13
  149. package/dist/src/lib/db-codegen/dbNaming.js +5 -17
  150. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
  151. package/dist/src/lib/db-codegen/dbTemplates.d.ts +7 -56
  152. package/dist/src/lib/db-codegen/dbTemplates.js +25 -125
  153. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
  154. package/dist/src/lib/db-codegen/dbTsTypes.d.ts +2 -2
  155. package/dist/src/lib/db-codegen/dbTsTypes.js +2 -2
  156. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +67 -2
  157. package/dist/src/lib/db-codegen/dbTypeIR.js +13 -2
  158. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -1
  159. package/dist/src/lib/db3-export.d.ts +231 -0
  160. package/dist/src/lib/db3-export.js +510 -0
  161. package/dist/src/lib/db3-export.js.map +1 -0
  162. package/dist/src/lib/db3-index-output.d.ts +27 -0
  163. package/dist/src/lib/db3-index-output.js +49 -0
  164. package/dist/src/lib/db3-index-output.js.map +1 -0
  165. package/dist/src/lib/document-export-lookups.d.ts +31 -0
  166. package/dist/src/lib/document-export-lookups.js +53 -0
  167. package/dist/src/lib/document-export-lookups.js.map +1 -0
  168. package/dist/src/lib/document-export-permissions.d.ts +7 -5
  169. package/dist/src/lib/document-export-permissions.js +7 -5
  170. package/dist/src/lib/document-export-permissions.js.map +1 -1
  171. package/dist/src/lib/document-export-record-log.d.ts +57 -0
  172. package/dist/src/lib/document-export-record-log.js +215 -0
  173. package/dist/src/lib/document-export-record-log.js.map +1 -0
  174. package/dist/src/lib/document-ingest-artifact.d.ts +26 -2
  175. package/dist/src/lib/document-ingest-artifact.js +42 -8
  176. package/dist/src/lib/document-ingest-artifact.js.map +1 -1
  177. package/dist/src/lib/document-ingest-format2.d.ts +36 -0
  178. package/dist/src/lib/document-ingest-format2.js +78 -0
  179. package/dist/src/lib/document-ingest-format2.js.map +1 -0
  180. package/dist/src/lib/document-ingest-input.d.ts +9 -0
  181. package/dist/src/lib/document-ingest-input.js +28 -1
  182. package/dist/src/lib/document-ingest-input.js.map +1 -1
  183. package/dist/src/lib/document-ingest-rows.d.ts +16 -0
  184. package/dist/src/lib/document-ingest-rows.js +17 -0
  185. package/dist/src/lib/document-ingest-rows.js.map +1 -1
  186. package/dist/src/lib/document-ingest.d.ts +33 -1
  187. package/dist/src/lib/document-ingest.js +49 -0
  188. package/dist/src/lib/document-ingest.js.map +1 -1
  189. package/dist/src/lib/document-schema-rows.d.ts +42 -0
  190. package/dist/src/lib/document-schema-rows.js +53 -0
  191. package/dist/src/lib/document-schema-rows.js.map +1 -0
  192. package/dist/src/lib/env-resolver-core.d.ts +70 -2
  193. package/dist/src/lib/env-resolver-core.js +137 -20
  194. package/dist/src/lib/env-resolver-core.js.map +1 -1
  195. package/dist/src/lib/env-resolver.d.ts +14 -2
  196. package/dist/src/lib/env-resolver.js +32 -10
  197. package/dist/src/lib/env-resolver.js.map +1 -1
  198. package/dist/src/lib/function-authorize-check.d.ts +142 -0
  199. package/dist/src/lib/function-authorize-check.js +310 -0
  200. package/dist/src/lib/function-authorize-check.js.map +1 -0
  201. package/dist/src/lib/function-authorize-view.d.ts +15 -0
  202. package/dist/src/lib/function-authorize-view.js +50 -0
  203. package/dist/src/lib/function-authorize-view.js.map +1 -0
  204. package/dist/src/lib/function-bundle.d.ts +38 -18
  205. package/dist/src/lib/function-bundle.js +96 -35
  206. package/dist/src/lib/function-bundle.js.map +1 -1
  207. package/dist/src/lib/function-collect.d.ts +75 -12
  208. package/dist/src/lib/function-collect.js +427 -12
  209. package/dist/src/lib/function-collect.js.map +1 -1
  210. package/dist/src/lib/function-db-types.d.ts +29 -0
  211. package/dist/src/lib/function-db-types.js +117 -7
  212. package/dist/src/lib/function-db-types.js.map +1 -1
  213. package/dist/src/lib/function-document-types.d.ts +5 -3
  214. package/dist/src/lib/function-document-types.js +10 -14
  215. package/dist/src/lib/function-document-types.js.map +1 -1
  216. package/dist/src/lib/function-lint.d.ts +34 -0
  217. package/dist/src/lib/function-lint.js +112 -0
  218. package/dist/src/lib/function-lint.js.map +1 -0
  219. package/dist/src/lib/function-log-row.js +21 -2
  220. package/dist/src/lib/function-log-row.js.map +1 -1
  221. package/dist/src/lib/function-run.d.ts +16 -21
  222. package/dist/src/lib/function-run.js +37 -30
  223. package/dist/src/lib/function-run.js.map +1 -1
  224. package/dist/src/lib/function-schema-codegen.d.ts +1 -1
  225. package/dist/src/lib/function-schema-codegen.js +5 -5
  226. package/dist/src/lib/function-schema-codegen.js.map +1 -1
  227. package/dist/src/lib/function-source-roots.d.ts +67 -0
  228. package/dist/src/lib/function-source-roots.js +148 -0
  229. package/dist/src/lib/function-source-roots.js.map +1 -0
  230. package/dist/src/lib/function-sync.d.ts +108 -22
  231. package/dist/src/lib/function-sync.js +127 -39
  232. package/dist/src/lib/function-sync.js.map +1 -1
  233. package/dist/src/lib/function-trigger-listing.d.ts +11 -6
  234. package/dist/src/lib/function-trigger-listing.js +32 -11
  235. package/dist/src/lib/function-trigger-listing.js.map +1 -1
  236. package/dist/src/lib/function-typecheck.d.ts +37 -2
  237. package/dist/src/lib/function-typecheck.js +210 -28
  238. package/dist/src/lib/function-typecheck.js.map +1 -1
  239. package/dist/src/lib/function-versions.d.ts +2 -0
  240. package/dist/src/lib/function-versions.js +1 -0
  241. package/dist/src/lib/function-versions.js.map +1 -1
  242. package/dist/src/lib/generated-allowlist.js +0 -20
  243. package/dist/src/lib/generated-allowlist.js.map +1 -1
  244. package/dist/src/lib/generated-config-surfaces.d.ts +703 -201
  245. package/dist/src/lib/generated-config-surfaces.js +2335 -2033
  246. package/dist/src/lib/generated-config-surfaces.js.map +1 -1
  247. package/dist/src/lib/generated-sdk-types.d.ts +1 -1
  248. package/dist/src/lib/generated-sdk-types.js +1 -1
  249. package/dist/src/lib/generated-sdk-types.js.map +1 -1
  250. package/dist/src/lib/init-adopt.js +12 -3
  251. package/dist/src/lib/init-adopt.js.map +1 -1
  252. package/dist/src/lib/init-login-note.d.ts +13 -0
  253. package/dist/src/lib/init-login-note.js +22 -0
  254. package/dist/src/lib/init-login-note.js.map +1 -0
  255. package/dist/src/lib/json-value.d.ts +6 -0
  256. package/dist/src/lib/json-value.js +13 -0
  257. package/dist/src/lib/json-value.js.map +1 -0
  258. package/dist/src/lib/load-routes.d.ts +33 -0
  259. package/dist/src/lib/load-routes.js +35 -0
  260. package/dist/src/lib/load-routes.js.map +1 -0
  261. package/dist/src/lib/local-state.d.ts +38 -7
  262. package/dist/src/lib/local-state.js +172 -49
  263. package/dist/src/lib/local-state.js.map +1 -1
  264. package/dist/src/lib/local-test-cases.d.ts +5 -2
  265. package/dist/src/lib/local-test-cases.js +7 -4
  266. package/dist/src/lib/local-test-cases.js.map +1 -1
  267. package/dist/src/lib/log-inspection.d.ts +42 -4
  268. package/dist/src/lib/log-inspection.js +37 -5
  269. package/dist/src/lib/log-inspection.js.map +1 -1
  270. package/dist/src/lib/login-exchange-check.d.ts +18 -0
  271. package/dist/src/lib/login-exchange-check.js +27 -0
  272. package/dist/src/lib/login-exchange-check.js.map +1 -0
  273. package/dist/src/lib/login-scope-lines.d.ts +25 -0
  274. package/dist/src/lib/login-scope-lines.js +45 -0
  275. package/dist/src/lib/login-scope-lines.js.map +1 -0
  276. package/dist/src/lib/logout-admin-session.d.ts +2 -1
  277. package/dist/src/lib/logout-admin-session.js +7 -1
  278. package/dist/src/lib/logout-admin-session.js.map +1 -1
  279. package/dist/src/lib/object-status-filter.d.ts +9 -1
  280. package/dist/src/lib/object-status-filter.js +9 -1
  281. package/dist/src/lib/object-status-filter.js.map +1 -1
  282. package/dist/src/lib/output.js +2 -0
  283. package/dist/src/lib/output.js.map +1 -1
  284. package/dist/src/lib/paginate.d.ts +0 -5
  285. package/dist/src/lib/paginate.js +0 -5
  286. package/dist/src/lib/paginate.js.map +1 -1
  287. package/dist/src/lib/pin-refusal-hint.d.ts +12 -0
  288. package/dist/src/lib/pin-refusal-hint.js +35 -0
  289. package/dist/src/lib/pin-refusal-hint.js.map +1 -0
  290. package/dist/src/lib/primitive-env-plugin.d.ts +99 -0
  291. package/dist/src/lib/primitive-env-plugin.js +408 -0
  292. package/dist/src/lib/primitive-env-plugin.js.map +1 -0
  293. package/dist/src/lib/project-config.d.ts +7 -0
  294. package/dist/src/lib/project-config.js +22 -1
  295. package/dist/src/lib/project-config.js.map +1 -1
  296. package/dist/src/lib/project-login-apps.d.ts +8 -0
  297. package/dist/src/lib/project-login-apps.js +27 -0
  298. package/dist/src/lib/project-login-apps.js.map +1 -0
  299. package/dist/src/lib/prompt-schema-codegen.d.ts +10 -3
  300. package/dist/src/lib/prompt-schema-codegen.js +52 -11
  301. package/dist/src/lib/prompt-schema-codegen.js.map +1 -1
  302. package/dist/src/lib/pull-write.d.ts +31 -0
  303. package/dist/src/lib/pull-write.js +49 -0
  304. package/dist/src/lib/pull-write.js.map +1 -0
  305. package/dist/src/lib/push-failure-report.d.ts +45 -0
  306. package/dist/src/lib/push-failure-report.js +57 -0
  307. package/dist/src/lib/push-failure-report.js.map +1 -0
  308. package/dist/src/lib/records-verbs.d.ts +69 -0
  309. package/dist/src/lib/records-verbs.js +40 -0
  310. package/dist/src/lib/records-verbs.js.map +1 -0
  311. package/dist/src/lib/refresh-admin-credentials.d.ts +7 -0
  312. package/dist/src/lib/refresh-admin-credentials.js +16 -4
  313. package/dist/src/lib/refresh-admin-credentials.js.map +1 -1
  314. package/dist/src/lib/root-import-decision.d.ts +65 -0
  315. package/dist/src/lib/root-import-decision.js +109 -0
  316. package/dist/src/lib/root-import-decision.js.map +1 -0
  317. package/dist/src/lib/run-status.d.ts +1 -1
  318. package/dist/src/lib/run-status.generated.d.ts +2 -2
  319. package/dist/src/lib/run-status.generated.js +3 -1
  320. package/dist/src/lib/run-status.generated.js.map +1 -1
  321. package/dist/src/lib/run-status.js +1 -1
  322. package/dist/src/lib/schema-codegen/generated-schema-descriptor.d.ts +129 -0
  323. package/dist/src/lib/schema-codegen/generated-schema-descriptor.js +269 -0
  324. package/dist/src/lib/schema-codegen/generated-schema-descriptor.js.map +1 -0
  325. package/dist/src/lib/schema-codegen/naming.d.ts +35 -0
  326. package/dist/src/lib/schema-codegen/naming.js +83 -0
  327. package/dist/src/lib/schema-codegen/naming.js.map +1 -0
  328. package/dist/src/lib/schema-codegen/schemaToTs.d.ts +82 -0
  329. package/dist/src/lib/schema-codegen/schemaToTs.js +305 -0
  330. package/dist/src/lib/schema-codegen/schemaToTs.js.map +1 -0
  331. package/dist/src/lib/scope-request.d.ts +84 -0
  332. package/dist/src/lib/scope-request.js +235 -0
  333. package/dist/src/lib/scope-request.js.map +1 -0
  334. package/dist/src/lib/session-id.d.ts +9 -0
  335. package/dist/src/lib/session-id.js +28 -0
  336. package/dist/src/lib/session-id.js.map +1 -0
  337. package/dist/src/lib/snapshot-build-rows.d.ts +21 -0
  338. package/dist/src/lib/snapshot-build-rows.js +22 -0
  339. package/dist/src/lib/snapshot-build-rows.js.map +1 -1
  340. package/dist/src/lib/snapshot-build.js +8 -3
  341. package/dist/src/lib/snapshot-build.js.map +1 -1
  342. package/dist/src/lib/snapshots.d.ts +17 -1
  343. package/dist/src/lib/snapshots.js +50 -2
  344. package/dist/src/lib/snapshots.js.map +1 -1
  345. package/dist/src/lib/swift-codegen/agentGenerator.d.ts +6 -2
  346. package/dist/src/lib/swift-codegen/agentGenerator.js +57 -5
  347. package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -1
  348. package/dist/src/lib/swift-codegen/banners.d.ts +34 -7
  349. package/dist/src/lib/swift-codegen/banners.js +37 -7
  350. package/dist/src/lib/swift-codegen/banners.js.map +1 -1
  351. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +4 -3
  352. package/dist/src/lib/swift-codegen/dbGenerator.js +14 -117
  353. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
  354. package/dist/src/lib/swift-codegen/functionGenerator.d.ts +3 -3
  355. package/dist/src/lib/swift-codegen/functionGenerator.js +23 -18
  356. package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -1
  357. package/dist/src/lib/swift-codegen/generator.d.ts +5 -5
  358. package/dist/src/lib/swift-codegen/generator.js +35 -40
  359. package/dist/src/lib/swift-codegen/generator.js.map +1 -1
  360. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +3 -3
  361. package/dist/src/lib/swift-codegen/schemaToSwift.js +4 -4
  362. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -1
  363. package/dist/src/lib/swift-codegen/swiftKeys.d.ts +19 -0
  364. package/dist/src/lib/swift-codegen/swiftKeys.js +31 -0
  365. package/dist/src/lib/swift-codegen/swiftKeys.js.map +1 -0
  366. package/dist/src/lib/sync-paths.d.ts +35 -0
  367. package/dist/src/lib/sync-paths.js +57 -5
  368. package/dist/src/lib/sync-paths.js.map +1 -1
  369. package/dist/src/lib/sync-resource-types.d.ts +26 -26
  370. package/dist/src/lib/sync-resource-types.js +61 -189
  371. package/dist/src/lib/sync-resource-types.js.map +1 -1
  372. package/dist/src/lib/sync-selectors.d.ts +5 -1
  373. package/dist/src/lib/sync-selectors.js +23 -13
  374. package/dist/src/lib/sync-selectors.js.map +1 -1
  375. package/dist/src/lib/test-case-file-names.d.ts +3 -5
  376. package/dist/src/lib/test-case-file-names.js +3 -5
  377. package/dist/src/lib/test-case-file-names.js.map +1 -1
  378. package/dist/src/lib/toml-database-config.d.ts +15 -75
  379. package/dist/src/lib/toml-database-config.js +17 -306
  380. package/dist/src/lib/toml-database-config.js.map +1 -1
  381. package/dist/src/lib/transient-retry.d.ts +43 -0
  382. package/dist/src/lib/transient-retry.js +94 -0
  383. package/dist/src/lib/transient-retry.js.map +1 -0
  384. package/dist/src/lib/vars-override.d.ts +105 -0
  385. package/dist/src/lib/vars-override.js +143 -0
  386. package/dist/src/lib/vars-override.js.map +1 -0
  387. package/dist/src/lib/webhook-capture.d.ts +43 -0
  388. package/dist/src/lib/webhook-capture.js +91 -0
  389. package/dist/src/lib/webhook-capture.js.map +1 -0
  390. package/dist/src/lib/webhook-deliver.d.ts +18 -20
  391. package/dist/src/lib/webhook-deliver.js +34 -89
  392. package/dist/src/lib/webhook-deliver.js.map +1 -1
  393. package/dist/src/lib/webhook-test-run.d.ts +32 -0
  394. package/dist/src/lib/webhook-test-run.js +108 -0
  395. package/dist/src/lib/webhook-test-run.js.map +1 -0
  396. package/dist/src/lib/workflow-codegen/generator.d.ts +7 -7
  397. package/dist/src/lib/workflow-codegen/generator.js +16 -23
  398. package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
  399. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +6 -12
  400. package/dist/src/lib/workflow-codegen/invokerIR.js +4 -5
  401. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -1
  402. package/dist/src/lib/workflow-toml-validator.d.ts +2 -0
  403. package/dist/src/lib/workflow-toml-validator.js +28 -1
  404. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  405. package/dist/src/types/index.d.ts +30 -37
  406. package/dist/src/validators.d.ts +7 -55
  407. package/dist/src/validators.js +7 -53
  408. package/dist/src/validators.js.map +1 -1
  409. package/dist/src/vite.d.ts +17 -0
  410. package/dist/src/vite.js +18 -0
  411. package/dist/src/vite.js.map +1 -0
  412. package/package.json +20 -12
@@ -0,0 +1,1052 @@
1
+ import { ApiClient } from "../lib/api-client.js";
2
+ import { resolveAppId } from "../lib/config.js";
3
+ import { error, flushOutput, formatDate, formatTable, info, json, result as printResult, success } from "../lib/output.js";
4
+ import { confirmPrompt } from "../lib/confirm-prompt.js";
5
+ import { normalizeCliListEnvelope, wholeListEnvelope } from "../lib/paginate.js";
6
+ import { parseDataOption } from "../lib/data-input.js";
7
+ import { DB3_ROUTES } from "../lib/records-verbs.js";
8
+ import { DB3_LOAD_ROUTES } from "../lib/load-routes.js";
9
+ import { declarationOfSchemaAnswer, declaredModelNames, exportDb3, loadDb3Rows, pendingRegistrations, planDb3Import, readDb3Manifest, readExportedBlobs, resolvedTypeName, } from "../lib/db3-export.js";
10
+ import fs from "fs";
11
+ import path from "path";
12
+ import { db3IndexRefusalLines, db3IndexTableRows } from "../lib/db3-index-output.js";
13
+ import { parseCustodianOrExit } from "../lib/custodian.js";
14
+ import { pageCursorOption, pageLimitOption, parsePageLimit, printEmptyPage, printPageHint } from "../lib/list-options.js";
15
+ import { BULK_DATA_FILE_HELP, aggregateRecordsAction, bulkRecordsAction, countRecordsAction, deleteRecordAction, describeAction, describeRecordsFailure, displayTags, inspectAction, modelsAction, patchRecordAction, queryRecordsAction, saveRecordAction, schemaAction, statsAction, ingestAction, listIngestsAction, getIngestAction, abortIngestAction, listSnapshotsAction, getSnapshotAction, buildSnapshotAction, } from "./documents.js";
16
+ /**
17
+ * A refused index call: the server's sentence, its code and status, then one
18
+ * line per detail the code names (the duplicate keys, the origins keeping
19
+ * the index, the index a name belongs to, the stored format).
20
+ */
21
+ function refuse(err) {
22
+ error(describeRecordsFailure(err));
23
+ for (const line of db3IndexRefusalLines(err))
24
+ console.error(` ${line}`);
25
+ process.exit(1);
26
+ }
27
+ /** A refused db3 call: the server's sentence, its code and its status, then exit 1. */
28
+ function fail(err) {
29
+ error(describeRecordsFailure(err));
30
+ process.exit(1);
31
+ }
32
+ /** `on` or `off` as a boolean, or exit 1 naming `label` before any request. */
33
+ function parseOnOff(value, label) {
34
+ if (value === "on")
35
+ return true;
36
+ if (value === "off")
37
+ return false;
38
+ error(`${label} must be "on" or "off".`);
39
+ process.exit(1);
40
+ }
41
+ /** The lines a db3 is printed as: its id, title, custodian, sync and type. */
42
+ function printDb3(row) {
43
+ printResult("ID", row.id);
44
+ printResult("Title", row.title);
45
+ printResult("Custodian", row.custodian ?? "none");
46
+ printResult("Sync", row.sync === false ? "off" : "on");
47
+ printResult("Type", row.type ?? "none");
48
+ }
49
+ /**
50
+ * `primitive db3` (#4696, #4804): a db3's lifecycle (`create`, `get`,
51
+ * `list`, `delete`, `stats`), its sync, app access and custody, its indexes,
52
+ * and its records, schema and room through the `db3/:id/*` routes.
53
+ *
54
+ * The records, schema and inspect verbs are the `documents` verbs' twins:
55
+ * they share their action code (`./documents.ts`) through the db3 routes
56
+ * (`DB3_ROUTES`), take the same arguments and flags but `--document-format`
57
+ * (a db3 is format 3), and print what their twins print.
58
+ */
59
+ export function registerDb3Commands(program) {
60
+ const db3 = program
61
+ .command("db3")
62
+ .description("Work with db3s: create, read, list and delete them, their sync, app access and custody, indexes, records, schema and room");
63
+ // ---- Indexes ----
64
+ const indexes = db3.command("indexes").description("List, register and drop a db3's indexes");
65
+ indexes
66
+ .command("list")
67
+ .description("List a db3's indexes: declared and registered")
68
+ .argument("<db3-id>", "db3 ID")
69
+ .option("--app <app-id>", "App ID")
70
+ .option("--json", "Output as JSON")
71
+ .action(async (db3Id, options) => {
72
+ const resolvedAppId = resolveAppId(undefined, options);
73
+ const client = new ApiClient();
74
+ try {
75
+ const { indexes: list } = await client.listDb3Indexes(resolvedAppId, db3Id);
76
+ if (options.json) {
77
+ json(wholeListEnvelope(list));
78
+ return;
79
+ }
80
+ if (list.length === 0) {
81
+ info("No indexes on this db3.");
82
+ return;
83
+ }
84
+ console.log(formatTable(db3IndexTableRows(list), [
85
+ { header: "NAME", key: "name", flex: true },
86
+ { header: "MODEL", key: "model" },
87
+ { header: "FIELDS", key: "fields" },
88
+ { header: "UNIQUE", key: "unique" },
89
+ { header: "ORIGINS", key: "origins" },
90
+ ]));
91
+ }
92
+ catch (err) {
93
+ refuse(err);
94
+ }
95
+ });
96
+ indexes
97
+ .command("register")
98
+ .description("Register an index on a db3 model's field, or a named composite over several fields")
99
+ .argument("<db3-id>", "db3 ID")
100
+ .requiredOption("--model <model>", "Model name")
101
+ .requiredOption("--field <field>", "Field to index (repeat it for a composite unique index, which also needs --unique and --name)", (value, previous = []) => previous.concat(value))
102
+ .option("--unique", "Enforce that no two records share the key")
103
+ .option("--name <name>", "Name the index (idx_named_<model>_<name>)")
104
+ .option("--app <app-id>", "App ID")
105
+ .option("--json", "Output as JSON")
106
+ .action(async (db3Id, options) => {
107
+ const resolvedAppId = resolveAppId(undefined, options);
108
+ const fields = options.field;
109
+ const body = {
110
+ model: options.model,
111
+ ...(fields.length === 1 ? { field: fields[0] } : { fields }),
112
+ ...(options.unique ? { unique: true } : {}),
113
+ ...(options.name !== undefined ? { name: options.name } : {}),
114
+ };
115
+ const client = new ApiClient();
116
+ try {
117
+ const { index } = await client.registerDb3Index(resolvedAppId, db3Id, body);
118
+ if (options.json) {
119
+ json(index);
120
+ return;
121
+ }
122
+ success(`Registered ${index.name} on ${index.model} (${index.fields.join(", ")}${index.unique ? ", unique" : ""}).`);
123
+ }
124
+ catch (err) {
125
+ refuse(err);
126
+ }
127
+ });
128
+ indexes
129
+ .command("drop")
130
+ .description("Drop a db3 index you registered (one a declaration keeps stays)")
131
+ .argument("<db3-id>", "db3 ID")
132
+ .argument("<name>", "Index name, as `db3 indexes list` prints it")
133
+ .option("--app <app-id>", "App ID")
134
+ .option("-y, --yes", "Skip confirmation prompt")
135
+ .option("--json", "Output as JSON")
136
+ .action(async (db3Id, name, options) => {
137
+ const resolvedAppId = resolveAppId(undefined, options);
138
+ if (!options.yes) {
139
+ let confirmed;
140
+ try {
141
+ confirmed = await confirmPrompt(`Drop index ${name} from db3 ${db3Id}?`);
142
+ }
143
+ catch (err) {
144
+ error(err.message);
145
+ process.exit(1);
146
+ }
147
+ if (!confirmed) {
148
+ info("Cancelled.");
149
+ return;
150
+ }
151
+ }
152
+ const client = new ApiClient();
153
+ try {
154
+ const answer = await client.dropDb3Index(resolvedAppId, db3Id, name);
155
+ if (options.json) {
156
+ json(answer);
157
+ return;
158
+ }
159
+ success(`Dropped ${answer.name}.`);
160
+ }
161
+ catch (err) {
162
+ refuse(err);
163
+ }
164
+ });
165
+ // ---- Records: the `documents records` verbs' twins ----
166
+ const records = db3.command("records").description("Query and write a db3's records");
167
+ records
168
+ .command("query")
169
+ .description("Query records in a db3 model")
170
+ .argument("<db3-id>", "db3 ID")
171
+ .argument("<model-name>", "Model name to query")
172
+ .option("--app <app-id>", "App ID")
173
+ .option("--filter <json>", "Filter as JSON (e.g. '{\"status\":\"open\"}')")
174
+ .option("--filter-file <path>", "Read filter from a JSON or TOML file")
175
+ .option("--sort <json>", "Sort as JSON, e.g. '{\"createdAt\":-1}'; 1 ascending, -1 descending, key order is precedence; repeat it with --cursor")
176
+ .option("--limit <n>", "Records per page (default 100, max 10000)")
177
+ .option("--cursor <cursor>", "Pagination cursor from a previous query (valid only with the same --sort)")
178
+ .option("--include <json>", "Related records as a JSON array of include specs, e.g. '[{\"model\":\"customer\",\"type\":\"refersTo\",\"sourceField\":\"customerId\"}]'; answered as _related")
179
+ .option("--json", "Output as JSON")
180
+ .action(async (db3Id, modelName, options) => {
181
+ const resolvedAppId = resolveAppId(undefined, options);
182
+ await queryRecordsAction(DB3_ROUTES, resolvedAppId, db3Id, modelName, options);
183
+ });
184
+ records
185
+ .command("count")
186
+ .description("Count records in a db3 model")
187
+ .argument("<db3-id>", "db3 ID")
188
+ .argument("<model-name>", "Model name to count")
189
+ .option("--app <app-id>", "App ID")
190
+ .option("--filter <json>", "Filter as JSON (e.g. '{\"status\":\"open\"}')")
191
+ .option("--filter-file <path>", "Read filter from a JSON or TOML file")
192
+ .option("--json", "Output as JSON")
193
+ .action(async (db3Id, modelName, options) => {
194
+ const resolvedAppId = resolveAppId(undefined, options);
195
+ await countRecordsAction(DB3_ROUTES, resolvedAppId, db3Id, modelName, options);
196
+ });
197
+ records
198
+ .command("aggregate")
199
+ .description("Aggregate records in a db3 model (count/sum/avg/min/max, optional group-by)")
200
+ .argument("<db3-id>", "db3 ID")
201
+ .argument("<model-name>", "Model name")
202
+ .option("--app <app-id>", "App ID")
203
+ .requiredOption("--op <operation>", "Aggregate operation: count|sum|avg|min|max")
204
+ .option("--field <field>", "Field to aggregate (required for sum/avg/min/max)")
205
+ .option("--group-by <field>", "Group results by this field (repeatable)", (value, previous = []) => previous.concat(value), [])
206
+ .option("--filter <json>", "Filter as JSON")
207
+ .option("--filter-file <path>", "Read filter from a JSON or TOML file")
208
+ .option("--json", "Output as JSON")
209
+ .action(async (db3Id, modelName, options) => {
210
+ const resolvedAppId = resolveAppId(undefined, options);
211
+ await aggregateRecordsAction(DB3_ROUTES, resolvedAppId, db3Id, modelName, options);
212
+ });
213
+ records
214
+ .command("save")
215
+ .description("Create or replace a record in a db3 model")
216
+ .argument("<db3-id>", "db3 ID")
217
+ .argument("<model-name>", "Model name to write to")
218
+ .option("--app <app-id>", "App ID")
219
+ .option("--id <record-id>", "Record ID (a ULID is generated when omitted)")
220
+ .option("--data <json>", "Record fields as JSON (e.g. '{\"qty\":10}')")
221
+ .option("--data-file <file>", "Read record fields from a JSON file")
222
+ .option("--upsert-on <field>", "Update the record whose <field> matches instead of creating")
223
+ .option("--json", "Output as JSON")
224
+ .action(async (db3Id, modelName, options) => {
225
+ const data = parseDataOption(options, "record fields");
226
+ const resolvedAppId = resolveAppId(undefined, options);
227
+ await saveRecordAction(DB3_ROUTES, resolvedAppId, db3Id, modelName, data, options);
228
+ });
229
+ records
230
+ .command("patch")
231
+ .description("Merge fields into an existing record in a db3 model")
232
+ .argument("<db3-id>", "db3 ID")
233
+ .argument("<model-name>", "Model name")
234
+ .argument("<record-id>", "Record ID to patch")
235
+ .option("--app <app-id>", "App ID")
236
+ .option("--data <json>", "Fields to merge as JSON (e.g. '{\"status\":\"closed\"}')")
237
+ .option("--data-file <file>", "Read fields from a JSON file")
238
+ .option("--json", "Output as JSON")
239
+ .action(async (db3Id, modelName, recordId, options) => {
240
+ const data = parseDataOption(options, "fields to merge");
241
+ const resolvedAppId = resolveAppId(undefined, options);
242
+ await patchRecordAction(DB3_ROUTES, resolvedAppId, db3Id, modelName, recordId, data, options);
243
+ });
244
+ records
245
+ .command("delete")
246
+ .description("Delete a record from a db3 model")
247
+ .argument("<db3-id>", "db3 ID")
248
+ .argument("<model-name>", "Model name")
249
+ .argument("<record-id>", "Record ID to delete")
250
+ .option("--app <app-id>", "App ID")
251
+ .option("-y, --yes", "Skip confirmation prompt")
252
+ .option("--json", "Output as JSON")
253
+ .action(async (db3Id, modelName, recordId, options) => {
254
+ const resolvedAppId = resolveAppId(undefined, options);
255
+ await deleteRecordAction(DB3_ROUTES, resolvedAppId, db3Id, modelName, recordId, options);
256
+ });
257
+ records
258
+ .command("bulk")
259
+ .description("Apply an atomic create/patch/delete/upsert operations blob to a db3")
260
+ .argument("<db3-id>", "db3 ID")
261
+ .requiredOption("--data-file <file>", BULK_DATA_FILE_HELP)
262
+ .option("--app <app-id>", "App ID")
263
+ .option("-y, --yes", "Skip confirmation prompt")
264
+ .option("--json", "Output as JSON")
265
+ .action(async (db3Id, options) => {
266
+ await bulkRecordsAction(DB3_ROUTES, db3Id, options);
267
+ });
268
+ records
269
+ .command("models")
270
+ .description("List model names in a db3")
271
+ .argument("<db3-id>", "db3 ID")
272
+ .option("--app <app-id>", "App ID")
273
+ .option("--json", "Output as JSON")
274
+ .action(async (db3Id, options) => {
275
+ await modelsAction(DB3_ROUTES, db3Id, options);
276
+ });
277
+ records
278
+ .command("describe")
279
+ .description("Show a db3 model's fields and indexes")
280
+ .argument("<db3-id>", "db3 ID")
281
+ .argument("<model-name>", "Model name")
282
+ .option("--app <app-id>", "App ID")
283
+ .option("--json", "Output as JSON")
284
+ .action(async (db3Id, modelName, options) => {
285
+ await describeAction(DB3_ROUTES, db3Id, modelName, options);
286
+ });
287
+ records
288
+ .command("increment")
289
+ .description("Add to numeric fields of a record in a db3 model (a missing or non-numeric field starts at 0)")
290
+ .argument("<db3-id>", "db3 ID")
291
+ .argument("<model-name>", "Model name")
292
+ .argument("<record-id>", "Record ID")
293
+ .option("--app <app-id>", "App ID")
294
+ .option("--data <json>", "Each field's delta as JSON (e.g. '{\"qty\":2}')")
295
+ .option("--data-file <file>", "Read the deltas from a JSON file")
296
+ .option("--json", "Output as JSON")
297
+ .action(async (db3Id, modelName, recordId, options) => {
298
+ const fields = parseDataOption(options, "field deltas");
299
+ const resolvedAppId = resolveAppId(undefined, options);
300
+ try {
301
+ const answer = await new ApiClient().incrementDb3Record(resolvedAppId, db3Id, modelName, recordId, { fields });
302
+ if (options.json) {
303
+ json(answer);
304
+ return;
305
+ }
306
+ for (const [field, value] of Object.entries(answer.values ?? {}))
307
+ printResult(field, value);
308
+ }
309
+ catch (err) {
310
+ fail(err);
311
+ }
312
+ });
313
+ // ---- Schema and room: the `documents schema` and `documents inspect` twins ----
314
+ db3
315
+ .command("schema")
316
+ .description("Show a db3's models and fields as declared and observed, or export them as a schema.toml")
317
+ .argument("<db3-id>", "db3 ID")
318
+ .option("--app <app-id>", "App ID")
319
+ .option("--toml", "Print a schema.toml the client's schemaToml option and js-bao-codegen-v2 accept")
320
+ .option("--output <file>", "With --toml: write the TOML to this file (overwriting it) instead of stdout")
321
+ .option("--json", "Output the /schema answer as JSON")
322
+ .action(async (db3Id, options) => {
323
+ await schemaAction(DB3_ROUTES, db3Id, options);
324
+ });
325
+ // ---- Type (#4802): attach a db3 type, or read the one it has ----
326
+ const type = db3.command("type").description("Attach a db3 type to a db3, or show the one it has");
327
+ type
328
+ .command("attach")
329
+ .description("Install a type's current revision in a db3, whole or not at all (a type is never detached)")
330
+ .argument("<db3-id>", "db3 ID")
331
+ .argument("<name>", "Type name")
332
+ .option("--app <app-id>", "App ID")
333
+ .option("--json", "Output as JSON")
334
+ .action(async (db3Id, name, options) => {
335
+ const resolvedAppId = resolveAppId(undefined, options);
336
+ try {
337
+ const answer = await new ApiClient().attachDb3Type(resolvedAppId, db3Id, name);
338
+ if (options.json) {
339
+ json(answer);
340
+ return;
341
+ }
342
+ success(`${db3Id} is of type ${answer.type}: ${answer.outcome} (revision ${new Date(answer.revision.generation).toISOString()})`);
343
+ }
344
+ catch (err) {
345
+ if (options.json) {
346
+ json({ ok: false, code: err?.code ?? null, message: err?.message ?? String(err), details: err?.details ?? null });
347
+ process.exit(1);
348
+ }
349
+ error(describeRecordsFailure(err));
350
+ for (const reason of err?.details?.reasons ?? [])
351
+ console.error(` ${reason.path}: ${reason.reason}`);
352
+ if (err?.details?.installed)
353
+ console.error(` installed: ${err.details.installed}`);
354
+ process.exit(1);
355
+ }
356
+ });
357
+ type
358
+ .command("get")
359
+ .description("Show the type a db3's row names, its revision, and what the db3's room holds")
360
+ .argument("<db3-id>", "db3 ID")
361
+ .option("--app <app-id>", "App ID")
362
+ .option("--json", "Output as JSON")
363
+ .action(async (db3Id, options) => {
364
+ const resolvedAppId = resolveAppId(undefined, options);
365
+ try {
366
+ const answer = await new ApiClient().getDb3Type(resolvedAppId, db3Id);
367
+ if (options.json) {
368
+ json(answer);
369
+ return;
370
+ }
371
+ const revision = (r) => (r ? `${new Date(r.generation).toISOString()} (${String(r.hash).slice(0, 12)})` : "—");
372
+ console.log(`Type: ${answer.type ?? "none"}`);
373
+ console.log(`Revision: ${revision(answer.revision)}`);
374
+ console.log(`Installed: ${answer.installed ? `${answer.installed.name} ${revision(answer.installed.revision)}` : "none"}`);
375
+ }
376
+ catch (err) {
377
+ error(describeRecordsFailure(err));
378
+ process.exit(1);
379
+ }
380
+ });
381
+ db3
382
+ .command("inspect")
383
+ .description("Show a db3's room: epochs, log number, floors, writers, the bulk load in progress and checkpoint")
384
+ .argument("<db3-id>", "db3 ID")
385
+ .option("--app <app-id>", "App ID")
386
+ .option("--refused <session-id>", "Print every row that bulk load refused, with its code, instead")
387
+ .option("--limit <n>", "With --refused: rows per page read (1–100)", "100")
388
+ .option("--json", "Output as JSON")
389
+ .action(async (db3Id, options) => {
390
+ await inspectAction(DB3_ROUTES, db3Id, options);
391
+ });
392
+ // ---- Bulk loads, snapshots, export and import (#4889) ----
393
+ // The `documents ingest|ingests|snapshots` verbs' twins over `db3/:id/*`:
394
+ // the same action code (`./documents.ts`), arguments and flags.
395
+ db3
396
+ .command("ingest")
397
+ .description("Bulk-load records into a db3 from a directory")
398
+ .argument("<db3-id>", "db3 ID")
399
+ .requiredOption("--input <dir>", "Directory of <model>.ndjson[.gz] files, or a `db3 export` or `documents export` output")
400
+ .option("--app <app-id>", "App ID")
401
+ .option("--reserve-epoch <when>", "Reserve the load's epoch at session open (open, the default) or at commit")
402
+ .option("--mode <mode>", "Merge the rows (merge, the default), or refresh: also delete every record of the input's models that no row names")
403
+ .option("-y, --yes", "Skip the confirmation prompt")
404
+ .option("--no-wait", "Exit once the session is committed")
405
+ .option("--timeout <seconds>", "Give up waiting after this many seconds")
406
+ .option("--json", "Output as JSON")
407
+ .addHelpText("after", `
408
+ Rows a load refuses are listed by \`primitive db3 inspect <db3-id> --refused <session-id>\`.
409
+ `)
410
+ .action(async (db3Id, options) => {
411
+ await ingestAction(DB3_LOAD_ROUTES, db3Id, options);
412
+ });
413
+ const ingests = db3.command("ingests").description("Inspect or abort a db3's bulk-load sessions");
414
+ ingests
415
+ .command("list")
416
+ .description("List a db3's bulk-load sessions, newest first")
417
+ .argument("<db3-id>", "db3 ID")
418
+ .option("--app <app-id>", "App ID")
419
+ .option("--limit <n>", "Page size (1–100)", "20")
420
+ .option("--cursor <cursor>", "Continue from a previous page's nextCursor")
421
+ .option("--json", "Output as JSON")
422
+ .action(async (db3Id, options) => {
423
+ await listIngestsAction(DB3_LOAD_ROUTES, db3Id, options);
424
+ });
425
+ ingests
426
+ .command("get")
427
+ .description("Show one bulk-load session, its progress and why it stopped")
428
+ .argument("<db3-id>", "db3 ID")
429
+ .argument("<session-id>", "Session ID")
430
+ .option("--app <app-id>", "App ID")
431
+ .option("--json", "Output as JSON")
432
+ .action(async (db3Id, sessionId, options) => {
433
+ await getIngestAction(DB3_LOAD_ROUTES, db3Id, sessionId, options);
434
+ });
435
+ ingests
436
+ .command("abort")
437
+ .description("Abort a bulk-load session and discard what it uploaded")
438
+ .argument("<db3-id>", "db3 ID")
439
+ .argument("<session-id>", "Session ID")
440
+ .option("--app <app-id>", "App ID")
441
+ .option("-y, --yes", "Skip the confirmation prompt")
442
+ .option("--json", "Output as JSON")
443
+ .action(async (db3Id, sessionId, options) => {
444
+ await abortIngestAction(DB3_LOAD_ROUTES, db3Id, sessionId, options);
445
+ });
446
+ const snapshots = db3.command("snapshots").description("Inspect or start a db3's segment exports");
447
+ snapshots
448
+ .command("list")
449
+ .description("List a db3's segment exports, newest first")
450
+ .argument("<db3-id>", "db3 ID")
451
+ .option("--app <app-id>", "App ID")
452
+ .option("--limit <n>", "Page size (1–100)", "20")
453
+ .option("--cursor <cursor>", "Continue from a previous page's nextCursor")
454
+ .option("--json", "Output as JSON")
455
+ .action(async (db3Id, options) => {
456
+ await listSnapshotsAction(DB3_LOAD_ROUTES, db3Id, options);
457
+ });
458
+ snapshots
459
+ .command("get")
460
+ .description("Show one segment export: its state, log number, rows and chunks")
461
+ .argument("<db3-id>", "db3 ID")
462
+ .argument("<segment-id>", "Segment ID")
463
+ .option("--app <app-id>", "App ID")
464
+ .option("--json", "Output as JSON")
465
+ .action(async (db3Id, segmentId, options) => {
466
+ await getSnapshotAction(DB3_LOAD_ROUTES, db3Id, segmentId, options);
467
+ });
468
+ snapshots
469
+ .command("build")
470
+ .description("Start a segment export of a db3's records now")
471
+ .argument("<db3-id>", "db3 ID")
472
+ .option("--app <app-id>", "App ID")
473
+ .option("--wait", "Poll until the segment is complete or failed")
474
+ .option("--timeout <seconds>", "Give up waiting after this many seconds")
475
+ .option("--json", "Output as JSON")
476
+ .action(async (db3Id, options) => {
477
+ await buildSnapshotAction(DB3_LOAD_ROUTES, db3Id, options);
478
+ });
479
+ db3
480
+ .command("export")
481
+ .description("Export a db3 to a directory: its rows, type, declaration and blobs")
482
+ .argument("<db3-id>", "db3 ID")
483
+ .option("--app <app-id>", "App ID")
484
+ .option("--output <dir>", "Directory to write (default ./primitive-export/db3/<db3-id>)")
485
+ .option("--no-blobs", "Leave the blobs out")
486
+ .option("--json", "Output as JSON")
487
+ .addHelpText("after", `
488
+ The directory holds db3.json (the db3's id, title, tags, type and revision,
489
+ its declaration and registered indexes, and the log number the rows are at),
490
+ the rows under snapshot/, chain.json and the blobs under blobs/. It holds no
491
+ grant, custody, sync state or alias. \`primitive db3 import\` loads it.
492
+ `)
493
+ .action(async (db3Id, options) => {
494
+ const resolvedAppId = resolveAppId(undefined, options);
495
+ const dir = path.resolve(options.output ?? path.join("primitive-export", "db3", db3Id));
496
+ let code = 0;
497
+ try {
498
+ const exported = await exportDb3(new ApiClient(), resolvedAppId, db3Id, dir, {
499
+ blobs: options.blobs !== false,
500
+ onProgress: (line) => info(line),
501
+ });
502
+ if (options.json) {
503
+ json({ id: db3Id, exportPath: dir, rows: exported.rows, blobs: exported.blobs, type: exported.manifest.type, lsn: exported.manifest.lsn });
504
+ }
505
+ else {
506
+ success(`Exported db3 ${db3Id} (${exported.manifest.title || "untitled"}) to ${dir}`);
507
+ printResult("Rows", exported.rows);
508
+ printResult("Blobs", options.blobs === false ? "left out" : exported.blobs);
509
+ printResult("Type", exported.manifest.type?.name ?? "none");
510
+ printResult("Log number", exported.manifest.lsn);
511
+ }
512
+ }
513
+ catch (err) {
514
+ error(err?.statusCode ? describeRecordsFailure(err) : err?.message ?? String(err));
515
+ code = 1;
516
+ }
517
+ await flushOutput();
518
+ process.exit(code);
519
+ });
520
+ db3
521
+ .command("import")
522
+ .description("Import a `db3 export` directory: a new db3 of its type, or --into an existing one")
523
+ .argument("<path>", "The export's directory")
524
+ .option("--app <app-id>", "App ID")
525
+ .option("--into <db3-id>", "Load into this db3 instead of creating one (of the same type and declaration)")
526
+ .option("--keep-id", "Create the db3 under the export's id (an app owner or admin; the id must be free in this app)")
527
+ .option("--title <title>", "The new db3's title (default: the export's)")
528
+ .option("--type <name>", "The db3 type to create it with (default: the export's)")
529
+ .option("--untyped", "Load into an untyped db3, registering the export's indexes and uniques first")
530
+ .option("--no-blobs", "Leave the blobs out")
531
+ .option("-y, --yes", "Skip the confirmation prompt (--into)")
532
+ .option("--json", "Output as JSON")
533
+ .addHelpText("after", `
534
+ Every check runs before anything is written: the type must be one the app
535
+ has (primitive db3-types push), with the export's declaration; an --into
536
+ target must be of the export's type and declare its models alike; and the
537
+ blobs keep their ids, so the exported db3 must be gone from the app (or
538
+ import into another app, or pass --no-blobs). A load that refuses a row exits
539
+ 1 naming \`primitive db3 inspect <db3-id> --refused <session-id>\`.
540
+
541
+ --keep-id creates the db3 under the export's id, so what stored that id still
542
+ finds it: the id must be free in this app (delete the exported db3 first, or
543
+ import into another app). Without it the import gets a new id.
544
+ `)
545
+ .action(async (dir, options) => {
546
+ const code = await importAction(dir, options);
547
+ await flushOutput();
548
+ process.exit(code);
549
+ });
550
+ // ---- Lifecycle (#4804) ----
551
+ db3
552
+ .command("create")
553
+ .description("Create a db3")
554
+ .argument("<title>", "db3 title")
555
+ .option("--type <name>", "A db3 type of the app: its current revision is installed before the db3 answers")
556
+ .option("--sync <on|off>", "off: no client ever opens the db3 over a socket (app owners and admins only)")
557
+ .option("--custodian <custodian>", '"app" or "user:<user-id>" (a member of the app)')
558
+ .option("--app <app-id>", "App ID")
559
+ .option("--json", "Output as JSON")
560
+ .addHelpText("after", `
561
+ Custody:
562
+ A member's token creates a db3 the member holds. An admin token's create is
563
+ held by the app, which no member owns, unless --custodian names a member.
564
+ `)
565
+ .action(async (title, options) => {
566
+ const sync = options.sync === undefined ? undefined : parseOnOff(options.sync, "--sync");
567
+ const custodian = options.custodian === undefined ? undefined : parseCustodianOrExit(options.custodian, "--custodian");
568
+ const resolvedAppId = resolveAppId(undefined, options);
569
+ try {
570
+ const created = await new ApiClient().createDb3(resolvedAppId, {
571
+ title,
572
+ ...(options.type !== undefined ? { type: options.type } : {}),
573
+ ...(sync !== undefined ? { sync } : {}),
574
+ ...(custodian !== undefined ? { custodian } : {}),
575
+ });
576
+ if (options.json) {
577
+ json(created);
578
+ return;
579
+ }
580
+ success("db3 created.");
581
+ printDb3(created);
582
+ }
583
+ catch (err) {
584
+ fail(err);
585
+ }
586
+ });
587
+ db3
588
+ .command("get")
589
+ .description("Show a db3, and the caller's access to it")
590
+ .argument("<db3-id>", "db3 ID")
591
+ .option("--app <app-id>", "App ID")
592
+ .option("--json", "Output as JSON")
593
+ .action(async (db3Id, options) => {
594
+ const resolvedAppId = resolveAppId(undefined, options);
595
+ try {
596
+ const row = await new ApiClient().getDb3(resolvedAppId, db3Id);
597
+ if (options.json) {
598
+ json(row);
599
+ return;
600
+ }
601
+ printDb3(row);
602
+ printResult("Created By", row.createdBy);
603
+ printResult("Created", formatDate(row.createdAt));
604
+ printResult("Modified", formatDate(row.modifiedAt));
605
+ const tags = displayTags(row.tags);
606
+ if (tags.length > 0)
607
+ printResult("Tags", tags.join(", "));
608
+ if (row.permission)
609
+ printResult("Your Permission", row.permission);
610
+ if (row.accessSource)
611
+ printResult("Access Source", row.accessSource);
612
+ }
613
+ catch (err) {
614
+ fail(err);
615
+ }
616
+ });
617
+ db3
618
+ .command("list")
619
+ .description("List one custodian's db3s, oldest first")
620
+ .requiredOption("--custodian <custodian>", '"app" or "user:<user-id>"')
621
+ .option("--app <app-id>", "App ID")
622
+ .addOption(pageLimitOption())
623
+ .addOption(pageCursorOption())
624
+ .option("--json", "Output as JSON")
625
+ .allowExcessArguments(false)
626
+ .action(async (options) => {
627
+ const limit = parsePageLimit(options.limit);
628
+ const custodian = parseCustodianOrExit(options.custodian, "--custodian");
629
+ const resolvedAppId = resolveAppId(undefined, options);
630
+ try {
631
+ const page = normalizeCliListEnvelope(await new ApiClient().listDb3ByCustodian(resolvedAppId, custodian, {
632
+ ...(limit !== undefined ? { limit } : {}),
633
+ ...(options.cursor ? { cursor: options.cursor } : {}),
634
+ }));
635
+ if (options.json) {
636
+ json(page);
637
+ return;
638
+ }
639
+ if (page.items.length === 0) {
640
+ printEmptyPage(page, "db3s");
641
+ return;
642
+ }
643
+ const rows = page.items.map((row) => ({
644
+ id: row.id,
645
+ title: row.title ?? "",
646
+ custodian: row.custodian ?? "none",
647
+ sync: row.sync === false ? "off" : "on",
648
+ type: row.type ?? "none",
649
+ createdAt: row.createdAt,
650
+ }));
651
+ console.log(formatTable(rows, [
652
+ { header: "ID", key: "id" },
653
+ { header: "TITLE", key: "title", flex: true },
654
+ { header: "CUSTODIAN", key: "custodian" },
655
+ { header: "SYNC", key: "sync" },
656
+ { header: "TYPE", key: "type" },
657
+ { header: "CREATED", key: "createdAt", format: formatDate },
658
+ ]));
659
+ printPageHint(page);
660
+ }
661
+ catch (err) {
662
+ fail(err);
663
+ }
664
+ });
665
+ db3
666
+ .command("delete")
667
+ .description("Delete a db3 and all its data (records, blobs, aliases, permissions)")
668
+ .argument("<db3-id>", "db3 ID")
669
+ .option("--app <app-id>", "App ID")
670
+ .option("-y, --yes", "Skip confirmation prompt")
671
+ .option("--json", "Output as JSON")
672
+ .action(async (db3Id, options) => {
673
+ const resolvedAppId = resolveAppId(undefined, options);
674
+ if (!options.yes) {
675
+ let confirmed;
676
+ try {
677
+ confirmed = await confirmPrompt(`Delete db3 ${db3Id}? This permanently deletes its records, blobs, aliases and permissions.`);
678
+ }
679
+ catch (err) {
680
+ error(err.message);
681
+ process.exit(1);
682
+ }
683
+ if (!confirmed) {
684
+ info("Cancelled.");
685
+ return;
686
+ }
687
+ }
688
+ try {
689
+ const answer = await new ApiClient().deleteDb3(resolvedAppId, db3Id);
690
+ if (options.json) {
691
+ json(answer);
692
+ return;
693
+ }
694
+ success(`db3 ${db3Id} deleted.`);
695
+ }
696
+ catch (err) {
697
+ fail(err);
698
+ }
699
+ });
700
+ db3
701
+ .command("stats")
702
+ .description("Show a db3's record/model/blob counts and size")
703
+ .argument("<db3-id>", "db3 ID")
704
+ .option("--app <app-id>", "App ID")
705
+ .option("--json", "Output as JSON")
706
+ .action(async (db3Id, options) => {
707
+ await statsAction(DB3_ROUTES, db3Id, options);
708
+ });
709
+ // ---- Sync (#4799, #4804) ----
710
+ const sync = db3.command("sync").description("Show or change whether a db3 is synced");
711
+ sync
712
+ .command("get")
713
+ .description("Print on or off: whether clients open the db3 over a socket")
714
+ .argument("<db3-id>", "db3 ID")
715
+ .option("--app <app-id>", "App ID")
716
+ .option("--json", "Output as JSON")
717
+ .action(async (db3Id, options) => {
718
+ const resolvedAppId = resolveAppId(undefined, options);
719
+ try {
720
+ const answer = await new ApiClient().getDb3Sync(resolvedAppId, db3Id);
721
+ if (options.json) {
722
+ json(answer);
723
+ return;
724
+ }
725
+ console.log(answer.sync ? "on" : "off");
726
+ }
727
+ catch (err) {
728
+ fail(err);
729
+ }
730
+ });
731
+ sync
732
+ .command("set")
733
+ .description("Turn a db3's sync on or off (app owners and admins only)")
734
+ .argument("<db3-id>", "db3 ID")
735
+ .argument("<on|off>", "on or off")
736
+ .option("--app <app-id>", "App ID")
737
+ .option("--json", "Output as JSON")
738
+ .action(async (db3Id, state, options) => {
739
+ const on = parseOnOff(state, "The sync state");
740
+ const resolvedAppId = resolveAppId(undefined, options);
741
+ try {
742
+ const answer = await new ApiClient().setDb3Sync(resolvedAppId, db3Id, on);
743
+ if (options.json) {
744
+ json(answer);
745
+ return;
746
+ }
747
+ success(answer.changed ? `Sync is ${on ? "on" : "off"} for ${db3Id}.` : `Sync was already ${on ? "on" : "off"} for ${db3Id}.`);
748
+ }
749
+ catch (err) {
750
+ fail(err);
751
+ }
752
+ });
753
+ // ---- App access (#4801, #4804) ----
754
+ const appAccess = db3.command("app-access").description("Show or change the access every user of the app holds on a db3");
755
+ appAccess
756
+ .command("get")
757
+ .description("Print reader, read-write or none")
758
+ .argument("<db3-id>", "db3 ID")
759
+ .option("--app <app-id>", "App ID")
760
+ .option("--json", "Output as JSON")
761
+ .action(async (db3Id, options) => {
762
+ const resolvedAppId = resolveAppId(undefined, options);
763
+ try {
764
+ const answer = await new ApiClient().getDb3AppAccess(resolvedAppId, db3Id);
765
+ if (options.json) {
766
+ json(answer);
767
+ return;
768
+ }
769
+ console.log(answer.level ?? "none");
770
+ }
771
+ catch (err) {
772
+ fail(err);
773
+ }
774
+ });
775
+ appAccess
776
+ .command("set")
777
+ .description("Grant the db3 to every user of the app, or remove the grant with none (app owners and admins only)")
778
+ .argument("<db3-id>", "db3 ID")
779
+ .argument("<level>", "reader, read-write or none")
780
+ .option("--app <app-id>", "App ID")
781
+ .option("--json", "Output as JSON")
782
+ .action(async (db3Id, level, options) => {
783
+ if (!["reader", "read-write", "none"].includes(level)) {
784
+ error('The level must be "reader", "read-write" or "none".');
785
+ process.exit(1);
786
+ }
787
+ const resolvedAppId = resolveAppId(undefined, options);
788
+ try {
789
+ const answer = await new ApiClient().setDb3AppAccess(resolvedAppId, db3Id, level === "none" ? null : level);
790
+ if (options.json) {
791
+ json(answer);
792
+ return;
793
+ }
794
+ success(`App access on ${db3Id}: ${answer.level ?? "none"}${answer.changed ? "" : " (unchanged)"}.`);
795
+ }
796
+ catch (err) {
797
+ fail(err);
798
+ }
799
+ });
800
+ // ---- Custody (#4800, #4804): through the admin API ----
801
+ db3
802
+ .command("transfer")
803
+ .description("Transfer a db3 to another user or to the app")
804
+ .argument("<db3-id>", "db3 ID")
805
+ .argument("<custodian>", '"user:<user-id>" (a member of the app) or "app"')
806
+ .option("--app <app-id>", "App ID")
807
+ .option("--json", "Output as JSON")
808
+ .allowExcessArguments(false)
809
+ .addHelpText("after", `
810
+ The custodian and the owner row move together: a user custodian holds the
811
+ owner row and the previous owner keeps read-write; moving to the app deletes
812
+ every owner row. No other grant changes.
813
+ `)
814
+ .action(async (db3Id, custodianArg, options) => {
815
+ const to = parseCustodianOrExit(custodianArg, "custodian");
816
+ const resolvedAppId = resolveAppId(undefined, options);
817
+ try {
818
+ const answer = await new ApiClient().transferDb3(resolvedAppId, db3Id, to);
819
+ if (options.json) {
820
+ json(answer);
821
+ return;
822
+ }
823
+ success(`db3 ${db3Id} transferred.`);
824
+ printResult("Custodian", answer.custodian);
825
+ }
826
+ catch (err) {
827
+ fail(err);
828
+ }
829
+ });
830
+ const ownerRow = db3.command("owner-row").description("Remove or restore the owner row of the user who holds a db3");
831
+ ownerRow
832
+ .command("set")
833
+ .description("present restores the custodian user's owner row, absent removes it; the custodian stays")
834
+ .argument("<db3-id>", "db3 ID")
835
+ .argument("<present|absent>", "present or absent")
836
+ .option("--app <app-id>", "App ID")
837
+ .option("--json", "Output as JSON")
838
+ .action(async (db3Id, state, options) => {
839
+ if (state !== "present" && state !== "absent") {
840
+ error('The owner row must be "present" or "absent".');
841
+ process.exit(1);
842
+ }
843
+ const resolvedAppId = resolveAppId(undefined, options);
844
+ try {
845
+ const answer = await new ApiClient().setDb3OwnerRow(resolvedAppId, db3Id, state === "present");
846
+ if (options.json) {
847
+ json(answer);
848
+ return;
849
+ }
850
+ printResult("Custodian", answer.custodian);
851
+ printResult("Owner row", answer.ownerRow ? "present" : "absent");
852
+ printResult("Changed", answer.changed ? "yes" : "no");
853
+ }
854
+ catch (err) {
855
+ fail(err);
856
+ }
857
+ });
858
+ }
859
+ /** What to do about a refused create of the import's db3 (#4921), after the refusal itself. */
860
+ function createRefusalAdvice(code) {
861
+ switch (code) {
862
+ case "DB3_ID_EXISTS":
863
+ return " This app holds the export's id: delete that db3 first, import into another app, or import without --keep-id.";
864
+ case "DB3_CREATE_IN_PROGRESS":
865
+ return " Another create of this id is running: try again shortly.";
866
+ case "DB3_ID_INVALID":
867
+ return " The manifest's id is not a ULID this server accepts: import without --keep-id.";
868
+ case "DB3_ID_NOT_ALLOWED":
869
+ return " Keeping an id needs an app owner or admin: log in as one, or import without --keep-id.";
870
+ default:
871
+ return "";
872
+ }
873
+ }
874
+ /** `db3 import`: the reads, the plan, then the writes; answers the exit code. */
875
+ async function importAction(dir, options) {
876
+ const resolvedAppId = resolveAppId(undefined, options);
877
+ const client = new ApiClient();
878
+ const root = path.resolve(dir);
879
+ try {
880
+ const manifest = readDb3Manifest(root);
881
+ if (!manifest) {
882
+ error(`${root} holds no db3.json, so it is not a \`db3 export\` directory. ` +
883
+ "Load a directory of rows into an existing db3 with `primitive db3 ingest <db3-id> --input <dir>`.");
884
+ return 1;
885
+ }
886
+ const flags = {
887
+ ...(options.into ? { into: String(options.into) } : {}),
888
+ ...(options.title !== undefined ? { title: String(options.title) } : {}),
889
+ ...(options.type !== undefined ? { type: String(options.type) } : {}),
890
+ untyped: Boolean(options.untyped),
891
+ noBlobs: options.blobs === false,
892
+ keepId: Boolean(options.keepId),
893
+ };
894
+ if (flags.keepId && flags.into) {
895
+ const refused = planDb3Import(manifest, flags, { blobCount: 0 });
896
+ if ("refusal" in refused)
897
+ error(refused.refusal);
898
+ return 1;
899
+ }
900
+ // Every read before any write.
901
+ const blobs = flags.noBlobs ? [] : readExportedBlobs(root);
902
+ const facts = { blobCount: blobs.length };
903
+ const named = resolvedTypeName(manifest, flags);
904
+ if (named && !flags.untyped) {
905
+ try {
906
+ facts.type = await client.getDb3TypeConfig(resolvedAppId, named);
907
+ }
908
+ catch (err) {
909
+ if (err?.statusCode !== 404)
910
+ throw err;
911
+ facts.type = null;
912
+ }
913
+ }
914
+ if (flags.into) {
915
+ const row = await client.getDb3(resolvedAppId, flags.into);
916
+ let declaredModels = [];
917
+ if (row?.type) {
918
+ const targetType = facts.type?.name === row.type ? facts.type : await client.getDb3TypeConfig(resolvedAppId, String(row.type));
919
+ declaredModels = declaredModelNames(targetType?.schema);
920
+ }
921
+ const declaration = declarationOfSchemaAnswer(await client.getDb3Schema(resolvedAppId, flags.into), { declaredModels });
922
+ const listed = await client.listDb3Indexes(resolvedAppId, flags.into);
923
+ facts.target = { row, declaration, indexes: listed?.indexes ?? [] };
924
+ }
925
+ // One read of the source's id, for the blobs and for --keep-id alike.
926
+ if (blobs.length > 0 || flags.keepId) {
927
+ try {
928
+ await client.getDb3(resolvedAppId, manifest.id);
929
+ facts.sourceExists = true;
930
+ }
931
+ catch (err) {
932
+ if (err?.statusCode !== 404)
933
+ throw err;
934
+ facts.sourceExists = false;
935
+ }
936
+ }
937
+ const plan = planDb3Import(manifest, flags, facts);
938
+ if ("refusal" in plan) {
939
+ error(plan.refusal);
940
+ for (const line of plan.lines ?? [])
941
+ console.error(` ${line}`);
942
+ return 1;
943
+ }
944
+ for (const note of plan.notes)
945
+ info(note);
946
+ let db3Id;
947
+ let created = false;
948
+ if (plan.into) {
949
+ if (!options.yes) {
950
+ let confirmed;
951
+ try {
952
+ confirmed = await confirmPrompt(`Load the export's rows into db3 ${plan.into}? Rows with an id it already holds are replaced.`);
953
+ }
954
+ catch (err) {
955
+ error(err.message);
956
+ return 1;
957
+ }
958
+ if (!confirmed) {
959
+ info("Nothing was written.");
960
+ return 1;
961
+ }
962
+ }
963
+ db3Id = plan.into;
964
+ }
965
+ else {
966
+ let row;
967
+ try {
968
+ row = await client.createDb3(resolvedAppId, plan.create);
969
+ }
970
+ catch (err) {
971
+ error(`${describeRecordsFailure(err)}${createRefusalAdvice(err?.code)} Nothing was written.`);
972
+ return 1;
973
+ }
974
+ db3Id = row.id;
975
+ created = true;
976
+ if (!options.json)
977
+ success(`Created db3 ${db3Id}${plan.typeName ? ` of type ${plan.typeName}` : ""}.`);
978
+ }
979
+ let register = plan.register;
980
+ if (created && plan.typeName && register.length > 0) {
981
+ // A typed db3 has its type's indexes from the create: register only what they leave out.
982
+ const pending = pendingRegistrations(register, (await client.listDb3Indexes(resolvedAppId, db3Id))?.indexes ?? []);
983
+ if (pending.conflicts.length) {
984
+ error(`The export's indexes clash with type ${plan.typeName}'s by name; db3 ${db3Id} was created and holds no rows.`);
985
+ for (const line of pending.conflicts)
986
+ console.error(` ${line}`);
987
+ return 1;
988
+ }
989
+ register = pending.register;
990
+ }
991
+ for (const registration of register) {
992
+ await client.registerDb3Index(resolvedAppId, db3Id, registration);
993
+ }
994
+ const outcome = await loadDb3Rows(client, resolvedAppId, db3Id, root, (line) => info(line));
995
+ const session = outcome?.session ?? null;
996
+ if (outcome && outcome.exitCode !== 0) {
997
+ if (outcome.message)
998
+ error(outcome.message);
999
+ if (options.json)
1000
+ json({ id: db3Id, created, keptId: flags.keepId, session, exitCode: outcome.exitCode });
1001
+ return 1;
1002
+ }
1003
+ const refusedRows = Number(session?.refusedRows ?? 0);
1004
+ let blobsUploaded = 0;
1005
+ if (plan.blobs) {
1006
+ for (const blob of blobs) {
1007
+ const data = fs.readFileSync(path.join(root, "blobs", `${blob.blobId}.bin`));
1008
+ try {
1009
+ await client.uploadDb3Blob(resolvedAppId, db3Id, blob.blobId, data, {
1010
+ filename: blob.filename,
1011
+ contentType: blob.contentType,
1012
+ sha256: blob.sha256,
1013
+ });
1014
+ }
1015
+ catch (err) {
1016
+ error(`Blob ${blob.blobId} could not be uploaded under its id: ${describeRecordsFailure(err)}. The rows are loaded into db3 ${db3Id}.`);
1017
+ return 1;
1018
+ }
1019
+ blobsUploaded++;
1020
+ }
1021
+ }
1022
+ if (options.json) {
1023
+ json({
1024
+ id: db3Id,
1025
+ created,
1026
+ keptId: flags.keepId,
1027
+ type: plan.typeName,
1028
+ registered: register.length,
1029
+ rows: session?.rows ?? 0,
1030
+ refusedRows,
1031
+ session,
1032
+ blobs: blobsUploaded,
1033
+ });
1034
+ }
1035
+ else {
1036
+ printResult("db3", db3Id);
1037
+ printResult("Rows", session?.rows ?? 0);
1038
+ printResult("Indexes registered", register.length);
1039
+ printResult("Blobs", plan.blobs ? blobsUploaded : "none");
1040
+ }
1041
+ if (refusedRows > 0) {
1042
+ error(`The load refused ${refusedRows} row(s). List them with \`primitive db3 inspect ${db3Id} --refused ${session?.sessionId}\`.`);
1043
+ return 1;
1044
+ }
1045
+ return 0;
1046
+ }
1047
+ catch (err) {
1048
+ error(err?.statusCode ? describeRecordsFailure(err) : err?.message ?? String(err));
1049
+ return 1;
1050
+ }
1051
+ }
1052
+ //# sourceMappingURL=db3.js.map