primitive-admin 1.2.0-alpha.1 → 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 (410) hide show
  1. package/README.md +105 -134
  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 +11 -12
  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 +221 -457
  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/sync-app-settings.d.ts +36 -8
  67. package/dist/src/commands/sync-app-settings.js +109 -23
  68. package/dist/src/commands/sync-app-settings.js.map +1 -1
  69. package/dist/src/commands/sync.d.ts +360 -610
  70. package/dist/src/commands/sync.js +3151 -6697
  71. package/dist/src/commands/sync.js.map +1 -1
  72. package/dist/src/commands/tokens.js +3 -3
  73. package/dist/src/commands/tokens.js.map +1 -1
  74. package/dist/src/commands/users.js +77 -2
  75. package/dist/src/commands/users.js.map +1 -1
  76. package/dist/src/commands/workflows.d.ts +5 -83
  77. package/dist/src/commands/workflows.js +57 -2282
  78. package/dist/src/commands/workflows.js.map +1 -1
  79. package/dist/src/lib/aggregate-output.d.ts +25 -0
  80. package/dist/src/lib/aggregate-output.js +53 -0
  81. package/dist/src/lib/aggregate-output.js.map +1 -0
  82. package/dist/src/lib/api-client.d.ts +681 -551
  83. package/dist/src/lib/api-client.js +880 -814
  84. package/dist/src/lib/api-client.js.map +1 -1
  85. package/dist/src/lib/app-settings-descriptor.d.ts +47 -1
  86. package/dist/src/lib/app-settings-descriptor.js +114 -10
  87. package/dist/src/lib/app-settings-descriptor.js.map +1 -1
  88. package/dist/src/lib/auth-fixtures.d.ts +44 -0
  89. package/dist/src/lib/auth-fixtures.js +61 -0
  90. package/dist/src/lib/auth-fixtures.js.map +1 -0
  91. package/dist/src/lib/auth-flow.d.ts +41 -1
  92. package/dist/src/lib/auth-flow.js +70 -16
  93. package/dist/src/lib/auth-flow.js.map +1 -1
  94. package/dist/src/lib/block-layout.d.ts +12 -23
  95. package/dist/src/lib/block-layout.js +26 -92
  96. package/dist/src/lib/block-layout.js.map +1 -1
  97. package/dist/src/lib/block-selector.d.ts +2 -2
  98. package/dist/src/lib/block-selector.js +2 -2
  99. package/dist/src/lib/child-apps-local.d.ts +164 -0
  100. package/dist/src/lib/child-apps-local.js +258 -0
  101. package/dist/src/lib/child-apps-local.js.map +1 -0
  102. package/dist/src/lib/ci-session-request.d.ts +22 -0
  103. package/dist/src/lib/ci-session-request.js +51 -0
  104. package/dist/src/lib/ci-session-request.js.map +1 -0
  105. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +10 -8
  106. package/dist/src/lib/codegen-shared/generatedFiles.js +21 -15
  107. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
  108. package/dist/src/lib/codegen-shared/prettierStable.d.ts +1 -1
  109. package/dist/src/lib/codegen-shared/prettierStable.js +1 -1
  110. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +2 -2
  111. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +2 -2
  112. package/dist/src/lib/collection-export.d.ts +76 -15
  113. package/dist/src/lib/collection-export.js +116 -23
  114. package/dist/src/lib/collection-export.js.map +1 -1
  115. package/dist/src/lib/collection-principal.d.ts +22 -0
  116. package/dist/src/lib/collection-principal.js +35 -0
  117. package/dist/src/lib/collection-principal.js.map +1 -0
  118. package/dist/src/lib/config-object-descriptor.d.ts +3 -22
  119. package/dist/src/lib/config-object-descriptor.js +56 -290
  120. package/dist/src/lib/config-object-descriptor.js.map +1 -1
  121. package/dist/src/lib/config-payload.js +2 -3
  122. package/dist/src/lib/config-payload.js.map +1 -1
  123. package/dist/src/lib/config-surface.d.ts +5 -7
  124. package/dist/src/lib/config-surface.js +18 -40
  125. package/dist/src/lib/config-surface.js.map +1 -1
  126. package/dist/src/lib/connections-list.d.ts +10 -0
  127. package/dist/src/lib/connections-list.js +18 -0
  128. package/dist/src/lib/connections-list.js.map +1 -0
  129. package/dist/src/lib/credentials-home.d.ts +58 -0
  130. package/dist/src/lib/credentials-home.js +204 -0
  131. package/dist/src/lib/credentials-home.js.map +1 -0
  132. package/dist/src/lib/credentials-lock.d.ts +88 -0
  133. package/dist/src/lib/credentials-lock.js +302 -0
  134. package/dist/src/lib/credentials-lock.js.map +1 -0
  135. package/dist/src/lib/credentials-store.d.ts +179 -24
  136. package/dist/src/lib/credentials-store.js +712 -77
  137. package/dist/src/lib/credentials-store.js.map +1 -1
  138. package/dist/src/lib/csv.d.ts +8 -9
  139. package/dist/src/lib/csv.js +3 -4
  140. package/dist/src/lib/csv.js.map +1 -1
  141. package/dist/src/lib/custodian.d.ts +8 -0
  142. package/dist/src/lib/custodian.js +18 -0
  143. package/dist/src/lib/custodian.js.map +1 -0
  144. package/dist/src/lib/db-codegen/dbGenerator.js +5 -16
  145. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
  146. package/dist/src/lib/db-codegen/dbNaming.d.ts +5 -13
  147. package/dist/src/lib/db-codegen/dbNaming.js +5 -17
  148. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
  149. package/dist/src/lib/db-codegen/dbTemplates.d.ts +7 -56
  150. package/dist/src/lib/db-codegen/dbTemplates.js +25 -125
  151. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
  152. package/dist/src/lib/db-codegen/dbTsTypes.d.ts +2 -2
  153. package/dist/src/lib/db-codegen/dbTsTypes.js +2 -2
  154. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +67 -2
  155. package/dist/src/lib/db-codegen/dbTypeIR.js +13 -2
  156. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -1
  157. package/dist/src/lib/db3-export.d.ts +231 -0
  158. package/dist/src/lib/db3-export.js +510 -0
  159. package/dist/src/lib/db3-export.js.map +1 -0
  160. package/dist/src/lib/db3-index-output.d.ts +27 -0
  161. package/dist/src/lib/db3-index-output.js +49 -0
  162. package/dist/src/lib/db3-index-output.js.map +1 -0
  163. package/dist/src/lib/document-export-lookups.d.ts +31 -0
  164. package/dist/src/lib/document-export-lookups.js +53 -0
  165. package/dist/src/lib/document-export-lookups.js.map +1 -0
  166. package/dist/src/lib/document-export-permissions.d.ts +7 -5
  167. package/dist/src/lib/document-export-permissions.js +7 -5
  168. package/dist/src/lib/document-export-permissions.js.map +1 -1
  169. package/dist/src/lib/document-export-record-log.d.ts +57 -0
  170. package/dist/src/lib/document-export-record-log.js +215 -0
  171. package/dist/src/lib/document-export-record-log.js.map +1 -0
  172. package/dist/src/lib/document-ingest-artifact.d.ts +26 -2
  173. package/dist/src/lib/document-ingest-artifact.js +42 -8
  174. package/dist/src/lib/document-ingest-artifact.js.map +1 -1
  175. package/dist/src/lib/document-ingest-format2.d.ts +36 -0
  176. package/dist/src/lib/document-ingest-format2.js +78 -0
  177. package/dist/src/lib/document-ingest-format2.js.map +1 -0
  178. package/dist/src/lib/document-ingest-input.d.ts +9 -0
  179. package/dist/src/lib/document-ingest-input.js +28 -1
  180. package/dist/src/lib/document-ingest-input.js.map +1 -1
  181. package/dist/src/lib/document-ingest-rows.d.ts +16 -0
  182. package/dist/src/lib/document-ingest-rows.js +17 -0
  183. package/dist/src/lib/document-ingest-rows.js.map +1 -1
  184. package/dist/src/lib/document-ingest.d.ts +33 -1
  185. package/dist/src/lib/document-ingest.js +49 -0
  186. package/dist/src/lib/document-ingest.js.map +1 -1
  187. package/dist/src/lib/document-schema-rows.d.ts +42 -0
  188. package/dist/src/lib/document-schema-rows.js +53 -0
  189. package/dist/src/lib/document-schema-rows.js.map +1 -0
  190. package/dist/src/lib/env-resolver-core.d.ts +70 -2
  191. package/dist/src/lib/env-resolver-core.js +137 -20
  192. package/dist/src/lib/env-resolver-core.js.map +1 -1
  193. package/dist/src/lib/env-resolver.d.ts +14 -2
  194. package/dist/src/lib/env-resolver.js +32 -10
  195. package/dist/src/lib/env-resolver.js.map +1 -1
  196. package/dist/src/lib/function-authorize-check.d.ts +142 -0
  197. package/dist/src/lib/function-authorize-check.js +310 -0
  198. package/dist/src/lib/function-authorize-check.js.map +1 -0
  199. package/dist/src/lib/function-authorize-view.d.ts +15 -0
  200. package/dist/src/lib/function-authorize-view.js +50 -0
  201. package/dist/src/lib/function-authorize-view.js.map +1 -0
  202. package/dist/src/lib/function-bundle.d.ts +38 -18
  203. package/dist/src/lib/function-bundle.js +96 -35
  204. package/dist/src/lib/function-bundle.js.map +1 -1
  205. package/dist/src/lib/function-collect.d.ts +75 -12
  206. package/dist/src/lib/function-collect.js +427 -12
  207. package/dist/src/lib/function-collect.js.map +1 -1
  208. package/dist/src/lib/function-db-types.d.ts +29 -0
  209. package/dist/src/lib/function-db-types.js +117 -7
  210. package/dist/src/lib/function-db-types.js.map +1 -1
  211. package/dist/src/lib/function-document-types.d.ts +5 -3
  212. package/dist/src/lib/function-document-types.js +10 -14
  213. package/dist/src/lib/function-document-types.js.map +1 -1
  214. package/dist/src/lib/function-lint.d.ts +34 -0
  215. package/dist/src/lib/function-lint.js +112 -0
  216. package/dist/src/lib/function-lint.js.map +1 -0
  217. package/dist/src/lib/function-log-row.js +21 -2
  218. package/dist/src/lib/function-log-row.js.map +1 -1
  219. package/dist/src/lib/function-run.d.ts +16 -21
  220. package/dist/src/lib/function-run.js +37 -30
  221. package/dist/src/lib/function-run.js.map +1 -1
  222. package/dist/src/lib/function-schema-codegen.d.ts +1 -1
  223. package/dist/src/lib/function-schema-codegen.js +5 -5
  224. package/dist/src/lib/function-schema-codegen.js.map +1 -1
  225. package/dist/src/lib/function-source-roots.d.ts +67 -0
  226. package/dist/src/lib/function-source-roots.js +148 -0
  227. package/dist/src/lib/function-source-roots.js.map +1 -0
  228. package/dist/src/lib/function-sync.d.ts +108 -22
  229. package/dist/src/lib/function-sync.js +127 -39
  230. package/dist/src/lib/function-sync.js.map +1 -1
  231. package/dist/src/lib/function-trigger-listing.d.ts +11 -6
  232. package/dist/src/lib/function-trigger-listing.js +32 -11
  233. package/dist/src/lib/function-trigger-listing.js.map +1 -1
  234. package/dist/src/lib/function-typecheck.d.ts +37 -2
  235. package/dist/src/lib/function-typecheck.js +210 -28
  236. package/dist/src/lib/function-typecheck.js.map +1 -1
  237. package/dist/src/lib/function-versions.d.ts +2 -0
  238. package/dist/src/lib/function-versions.js +1 -0
  239. package/dist/src/lib/function-versions.js.map +1 -1
  240. package/dist/src/lib/generated-allowlist.js +0 -20
  241. package/dist/src/lib/generated-allowlist.js.map +1 -1
  242. package/dist/src/lib/generated-config-surfaces.d.ts +703 -203
  243. package/dist/src/lib/generated-config-surfaces.js +2270 -2014
  244. package/dist/src/lib/generated-config-surfaces.js.map +1 -1
  245. package/dist/src/lib/generated-sdk-types.d.ts +1 -1
  246. package/dist/src/lib/generated-sdk-types.js +1 -1
  247. package/dist/src/lib/generated-sdk-types.js.map +1 -1
  248. package/dist/src/lib/init-adopt.js +12 -3
  249. package/dist/src/lib/init-adopt.js.map +1 -1
  250. package/dist/src/lib/init-login-note.d.ts +13 -0
  251. package/dist/src/lib/init-login-note.js +22 -0
  252. package/dist/src/lib/init-login-note.js.map +1 -0
  253. package/dist/src/lib/json-value.d.ts +6 -0
  254. package/dist/src/lib/json-value.js +13 -0
  255. package/dist/src/lib/json-value.js.map +1 -0
  256. package/dist/src/lib/load-routes.d.ts +33 -0
  257. package/dist/src/lib/load-routes.js +35 -0
  258. package/dist/src/lib/load-routes.js.map +1 -0
  259. package/dist/src/lib/local-state.d.ts +38 -7
  260. package/dist/src/lib/local-state.js +172 -49
  261. package/dist/src/lib/local-state.js.map +1 -1
  262. package/dist/src/lib/local-test-cases.d.ts +5 -2
  263. package/dist/src/lib/local-test-cases.js +7 -4
  264. package/dist/src/lib/local-test-cases.js.map +1 -1
  265. package/dist/src/lib/log-inspection.d.ts +42 -4
  266. package/dist/src/lib/log-inspection.js +37 -5
  267. package/dist/src/lib/log-inspection.js.map +1 -1
  268. package/dist/src/lib/login-exchange-check.d.ts +18 -0
  269. package/dist/src/lib/login-exchange-check.js +27 -0
  270. package/dist/src/lib/login-exchange-check.js.map +1 -0
  271. package/dist/src/lib/login-scope-lines.d.ts +25 -0
  272. package/dist/src/lib/login-scope-lines.js +45 -0
  273. package/dist/src/lib/login-scope-lines.js.map +1 -0
  274. package/dist/src/lib/logout-admin-session.d.ts +2 -1
  275. package/dist/src/lib/logout-admin-session.js +7 -1
  276. package/dist/src/lib/logout-admin-session.js.map +1 -1
  277. package/dist/src/lib/object-status-filter.d.ts +9 -1
  278. package/dist/src/lib/object-status-filter.js +9 -1
  279. package/dist/src/lib/object-status-filter.js.map +1 -1
  280. package/dist/src/lib/output.js +2 -0
  281. package/dist/src/lib/output.js.map +1 -1
  282. package/dist/src/lib/paginate.d.ts +0 -5
  283. package/dist/src/lib/paginate.js +0 -5
  284. package/dist/src/lib/paginate.js.map +1 -1
  285. package/dist/src/lib/pin-refusal-hint.d.ts +12 -0
  286. package/dist/src/lib/pin-refusal-hint.js +35 -0
  287. package/dist/src/lib/pin-refusal-hint.js.map +1 -0
  288. package/dist/src/lib/primitive-env-plugin.d.ts +99 -0
  289. package/dist/src/lib/primitive-env-plugin.js +408 -0
  290. package/dist/src/lib/primitive-env-plugin.js.map +1 -0
  291. package/dist/src/lib/project-config.d.ts +7 -0
  292. package/dist/src/lib/project-config.js +22 -1
  293. package/dist/src/lib/project-config.js.map +1 -1
  294. package/dist/src/lib/project-login-apps.d.ts +8 -0
  295. package/dist/src/lib/project-login-apps.js +27 -0
  296. package/dist/src/lib/project-login-apps.js.map +1 -0
  297. package/dist/src/lib/prompt-schema-codegen.d.ts +10 -3
  298. package/dist/src/lib/prompt-schema-codegen.js +52 -11
  299. package/dist/src/lib/prompt-schema-codegen.js.map +1 -1
  300. package/dist/src/lib/pull-write.d.ts +31 -0
  301. package/dist/src/lib/pull-write.js +49 -0
  302. package/dist/src/lib/pull-write.js.map +1 -0
  303. package/dist/src/lib/push-failure-report.d.ts +45 -0
  304. package/dist/src/lib/push-failure-report.js +57 -0
  305. package/dist/src/lib/push-failure-report.js.map +1 -0
  306. package/dist/src/lib/records-verbs.d.ts +69 -0
  307. package/dist/src/lib/records-verbs.js +40 -0
  308. package/dist/src/lib/records-verbs.js.map +1 -0
  309. package/dist/src/lib/refresh-admin-credentials.d.ts +7 -0
  310. package/dist/src/lib/refresh-admin-credentials.js +16 -4
  311. package/dist/src/lib/refresh-admin-credentials.js.map +1 -1
  312. package/dist/src/lib/root-import-decision.d.ts +65 -0
  313. package/dist/src/lib/root-import-decision.js +109 -0
  314. package/dist/src/lib/root-import-decision.js.map +1 -0
  315. package/dist/src/lib/run-status.d.ts +1 -1
  316. package/dist/src/lib/run-status.generated.d.ts +2 -2
  317. package/dist/src/lib/run-status.generated.js +3 -1
  318. package/dist/src/lib/run-status.generated.js.map +1 -1
  319. package/dist/src/lib/run-status.js +1 -1
  320. package/dist/src/lib/schema-codegen/generated-schema-descriptor.d.ts +129 -0
  321. package/dist/src/lib/schema-codegen/generated-schema-descriptor.js +269 -0
  322. package/dist/src/lib/schema-codegen/generated-schema-descriptor.js.map +1 -0
  323. package/dist/src/lib/schema-codegen/naming.d.ts +35 -0
  324. package/dist/src/lib/schema-codegen/naming.js +83 -0
  325. package/dist/src/lib/schema-codegen/naming.js.map +1 -0
  326. package/dist/src/lib/schema-codegen/schemaToTs.d.ts +82 -0
  327. package/dist/src/lib/schema-codegen/schemaToTs.js +305 -0
  328. package/dist/src/lib/schema-codegen/schemaToTs.js.map +1 -0
  329. package/dist/src/lib/scope-request.d.ts +84 -0
  330. package/dist/src/lib/scope-request.js +235 -0
  331. package/dist/src/lib/scope-request.js.map +1 -0
  332. package/dist/src/lib/session-id.d.ts +9 -0
  333. package/dist/src/lib/session-id.js +28 -0
  334. package/dist/src/lib/session-id.js.map +1 -0
  335. package/dist/src/lib/snapshot-build-rows.d.ts +21 -0
  336. package/dist/src/lib/snapshot-build-rows.js +22 -0
  337. package/dist/src/lib/snapshot-build-rows.js.map +1 -1
  338. package/dist/src/lib/snapshot-build.js +8 -3
  339. package/dist/src/lib/snapshot-build.js.map +1 -1
  340. package/dist/src/lib/snapshots.d.ts +17 -1
  341. package/dist/src/lib/snapshots.js +50 -2
  342. package/dist/src/lib/snapshots.js.map +1 -1
  343. package/dist/src/lib/swift-codegen/agentGenerator.d.ts +6 -2
  344. package/dist/src/lib/swift-codegen/agentGenerator.js +57 -5
  345. package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -1
  346. package/dist/src/lib/swift-codegen/banners.d.ts +34 -7
  347. package/dist/src/lib/swift-codegen/banners.js +37 -7
  348. package/dist/src/lib/swift-codegen/banners.js.map +1 -1
  349. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +4 -3
  350. package/dist/src/lib/swift-codegen/dbGenerator.js +14 -117
  351. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
  352. package/dist/src/lib/swift-codegen/functionGenerator.d.ts +3 -3
  353. package/dist/src/lib/swift-codegen/functionGenerator.js +23 -18
  354. package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -1
  355. package/dist/src/lib/swift-codegen/generator.d.ts +5 -5
  356. package/dist/src/lib/swift-codegen/generator.js +35 -40
  357. package/dist/src/lib/swift-codegen/generator.js.map +1 -1
  358. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +3 -3
  359. package/dist/src/lib/swift-codegen/schemaToSwift.js +4 -4
  360. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -1
  361. package/dist/src/lib/swift-codegen/swiftKeys.d.ts +19 -0
  362. package/dist/src/lib/swift-codegen/swiftKeys.js +31 -0
  363. package/dist/src/lib/swift-codegen/swiftKeys.js.map +1 -0
  364. package/dist/src/lib/sync-paths.d.ts +35 -0
  365. package/dist/src/lib/sync-paths.js +57 -5
  366. package/dist/src/lib/sync-paths.js.map +1 -1
  367. package/dist/src/lib/sync-resource-types.d.ts +26 -26
  368. package/dist/src/lib/sync-resource-types.js +61 -189
  369. package/dist/src/lib/sync-resource-types.js.map +1 -1
  370. package/dist/src/lib/sync-selectors.d.ts +5 -1
  371. package/dist/src/lib/sync-selectors.js +23 -13
  372. package/dist/src/lib/sync-selectors.js.map +1 -1
  373. package/dist/src/lib/test-case-file-names.d.ts +3 -5
  374. package/dist/src/lib/test-case-file-names.js +3 -5
  375. package/dist/src/lib/test-case-file-names.js.map +1 -1
  376. package/dist/src/lib/toml-database-config.d.ts +15 -75
  377. package/dist/src/lib/toml-database-config.js +17 -306
  378. package/dist/src/lib/toml-database-config.js.map +1 -1
  379. package/dist/src/lib/transient-retry.d.ts +43 -0
  380. package/dist/src/lib/transient-retry.js +94 -0
  381. package/dist/src/lib/transient-retry.js.map +1 -0
  382. package/dist/src/lib/vars-override.d.ts +105 -0
  383. package/dist/src/lib/vars-override.js +143 -0
  384. package/dist/src/lib/vars-override.js.map +1 -0
  385. package/dist/src/lib/webhook-capture.d.ts +43 -0
  386. package/dist/src/lib/webhook-capture.js +91 -0
  387. package/dist/src/lib/webhook-capture.js.map +1 -0
  388. package/dist/src/lib/webhook-deliver.d.ts +18 -20
  389. package/dist/src/lib/webhook-deliver.js +34 -89
  390. package/dist/src/lib/webhook-deliver.js.map +1 -1
  391. package/dist/src/lib/webhook-test-run.d.ts +32 -0
  392. package/dist/src/lib/webhook-test-run.js +108 -0
  393. package/dist/src/lib/webhook-test-run.js.map +1 -0
  394. package/dist/src/lib/workflow-codegen/generator.d.ts +7 -7
  395. package/dist/src/lib/workflow-codegen/generator.js +16 -23
  396. package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
  397. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +6 -12
  398. package/dist/src/lib/workflow-codegen/invokerIR.js +4 -5
  399. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -1
  400. package/dist/src/lib/workflow-toml-validator.d.ts +2 -0
  401. package/dist/src/lib/workflow-toml-validator.js +28 -1
  402. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  403. package/dist/src/types/index.d.ts +30 -37
  404. package/dist/src/validators.d.ts +7 -55
  405. package/dist/src/validators.js +7 -53
  406. package/dist/src/validators.js.map +1 -1
  407. package/dist/src/vite.d.ts +17 -0
  408. package/dist/src/vite.js +18 -0
  409. package/dist/src/vite.js.map +1 -0
  410. package/package.json +20 -12
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The side reads `primitive documents export` makes for each document (#4149):
3
+ * its permissions, its pending invitations, its aliases and its blob list.
4
+ *
5
+ * Each one used to sit in a bare `catch {}`, so a 403, a 429 or a 5xx wrote an
6
+ * empty list and the export reported success. Aliases and blobs are what an
7
+ * import restores, so the loss carried straight into the migrated app. Only a
8
+ * documented "none" answer reads as empty here — a 404, or whatever extra
9
+ * statuses the caller names — exactly as the import's own existence check
10
+ * reads only a 404 as absence. A transient failure is retried through the
11
+ * CLI's shared retry; anything else fails the document.
12
+ */
13
+ /** Options for {@link readExportLookup}. */
14
+ export interface ExportLookupOptions {
15
+ /** Statuses that mean "the document has none". Defaults to `[404]`. */
16
+ absentStatuses?: readonly number[];
17
+ /** The wait between tries; injectable so a test need not spend it. */
18
+ sleep?: (ms: number) => Promise<void>;
19
+ }
20
+ /**
21
+ * Read one of a document's export lookups, or `null` when it has none.
22
+ *
23
+ * Throws when the read fails with anything other than an absent status, after
24
+ * retrying a transient failure. The error names the document and the lookup,
25
+ * so a caller exporting many documents can report which one is incomplete.
26
+ *
27
+ * @param documentId - The document being exported, named in a failure.
28
+ * @param lookup - What is being read, as an operator reads it ("aliases").
29
+ * @param read - The read itself.
30
+ */
31
+ export declare function readExportLookup<T>(documentId: string, lookup: string, read: () => Promise<T>, options?: ExportLookupOptions): Promise<T | null>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The side reads `primitive documents export` makes for each document (#4149):
3
+ * its permissions, its pending invitations, its aliases and its blob list.
4
+ *
5
+ * Each one used to sit in a bare `catch {}`, so a 403, a 429 or a 5xx wrote an
6
+ * empty list and the export reported success. Aliases and blobs are what an
7
+ * import restores, so the loss carried straight into the migrated app. Only a
8
+ * documented "none" answer reads as empty here — a 404, or whatever extra
9
+ * statuses the caller names — exactly as the import's own existence check
10
+ * reads only a 404 as absence. A transient failure is retried through the
11
+ * CLI's shared retry; anything else fails the document.
12
+ */
13
+ import { failureStatus, withTransientRetry } from "./transient-retry.js";
14
+ /** An absent status, carried out of the retry so it is not retried. */
15
+ const ABSENT = Symbol("absent");
16
+ /**
17
+ * Read one of a document's export lookups, or `null` when it has none.
18
+ *
19
+ * Throws when the read fails with anything other than an absent status, after
20
+ * retrying a transient failure. The error names the document and the lookup,
21
+ * so a caller exporting many documents can report which one is incomplete.
22
+ *
23
+ * @param documentId - The document being exported, named in a failure.
24
+ * @param lookup - What is being read, as an operator reads it ("aliases").
25
+ * @param read - The read itself.
26
+ */
27
+ export async function readExportLookup(documentId, lookup, read, options = {}) {
28
+ const absent = options.absentStatuses ?? [404];
29
+ let attempts = 0;
30
+ try {
31
+ const result = await withTransientRetry(async () => {
32
+ attempts++;
33
+ try {
34
+ return await read();
35
+ }
36
+ catch (error) {
37
+ const status = failureStatus(error);
38
+ if (status !== undefined && absent.includes(status))
39
+ return ABSENT;
40
+ throw error;
41
+ }
42
+ }, undefined, undefined, options.sleep);
43
+ return result === ABSENT ? null : result;
44
+ }
45
+ catch (error) {
46
+ const status = failureStatus(error);
47
+ const reason = `${error?.message || "no reason given"}${status !== undefined ? ` (${status})` : ""}`;
48
+ const tries = attempts > 1 ? ` after ${attempts} attempts` : "";
49
+ throw new Error(`Document ${documentId}: reading its ${lookup} failed${tries} — ` +
50
+ `${reason}. Its export would be incomplete, so it was not exported.`);
51
+ }
52
+ }
53
+ //# sourceMappingURL=document-export-lookups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-export-lookups.js","sourceRoot":"","sources":["../../../src/lib/document-export-lookups.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAUzE,uEAAuE;AACvE,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEhC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAAkB,EAClB,MAAc,EACd,IAAsB,EACtB,UAA+B,EAAE;IAEjC,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACrC,KAAK,IAAI,EAAE;YACT,QAAQ,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,EAAE,CAAC;YACtB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;gBACpC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAAE,OAAO,MAAM,CAAC;gBACnE,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC,EACD,SAAS,EACT,SAAS,EACT,OAAO,CAAC,KAAK,CACd,CAAC;QACF,OAAO,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,GAAG,KAAK,EAAE,OAAO,IAAI,iBAAiB,GACnD,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,EAC1C,EAAE,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,QAAQ,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,YAAY,UAAU,iBAAiB,MAAM,UAAU,KAAK,KAAK;YAC/D,GAAG,MAAM,2DAA2D,CACvE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -9,10 +9,12 @@
9
9
  * which returns a `{ items }` envelope of deferred grants the server has
10
10
  * already filtered down to unresolved, unexpired, still-invited ones.
11
11
  *
12
- * The export tolerates the pending read failing (an older server answers 403
13
- * or 404): the caller swallows the error and passes `null`, and the export
14
- * still writes the permission rows.
12
+ * An older server answers the pending read with 403 or 404; the caller reads
13
+ * either as "no pending invitations" and passes `null`, and the export still
14
+ * writes the permission rows. Any other failure fails the export (#4149).
15
15
  */
16
+ /** The pending-invitations statuses that mean "none": an older server's 403 or 404. */
17
+ export declare const PENDING_INVITATIONS_ABSENT_STATUSES: readonly number[];
16
18
  export interface ExportedPermissionRow {
17
19
  email: string;
18
20
  permission: string;
@@ -24,7 +26,7 @@ export interface ExportedPermissionRow {
24
26
  * Merge a document's permission rows and its pending deferred grants into the
25
27
  * single email-keyed list `permissions.json` carries.
26
28
  *
27
- * @param permissionsResponse - `GET /documents/:id/permissions`, or `null` when the read failed.
28
- * @param pendingResponse - `GET /documents/:id/pending-invitations`, or `null` when the read failed.
29
+ * @param permissionsResponse - `GET /documents/:id/permissions`, or `null` when the document has none.
30
+ * @param pendingResponse - `GET /documents/:id/pending-invitations`, or `null` when the server has none to report.
29
31
  */
30
32
  export declare function buildPermissionsExport(permissionsResponse: unknown, pendingResponse: unknown): ExportedPermissionRow[];
@@ -9,10 +9,12 @@
9
9
  * which returns a `{ items }` envelope of deferred grants the server has
10
10
  * already filtered down to unresolved, unexpired, still-invited ones.
11
11
  *
12
- * The export tolerates the pending read failing (an older server answers 403
13
- * or 404): the caller swallows the error and passes `null`, and the export
14
- * still writes the permission rows.
12
+ * An older server answers the pending read with 403 or 404; the caller reads
13
+ * either as "no pending invitations" and passes `null`, and the export still
14
+ * writes the permission rows. Any other failure fails the export (#4149).
15
15
  */
16
+ /** The pending-invitations statuses that mean "none": an older server's 403 or 404. */
17
+ export const PENDING_INVITATIONS_ABSENT_STATUSES = [403, 404];
16
18
  /** Unwrap a list that may arrive bare, or under `items`, or under a named key. */
17
19
  function rows(value, key) {
18
20
  if (Array.isArray(value))
@@ -30,8 +32,8 @@ function rows(value, key) {
30
32
  * Merge a document's permission rows and its pending deferred grants into the
31
33
  * single email-keyed list `permissions.json` carries.
32
34
  *
33
- * @param permissionsResponse - `GET /documents/:id/permissions`, or `null` when the read failed.
34
- * @param pendingResponse - `GET /documents/:id/pending-invitations`, or `null` when the read failed.
35
+ * @param permissionsResponse - `GET /documents/:id/permissions`, or `null` when the document has none.
36
+ * @param pendingResponse - `GET /documents/:id/pending-invitations`, or `null` when the server has none to report.
35
37
  */
36
38
  export function buildPermissionsExport(permissionsResponse, pendingResponse) {
37
39
  const granted = rows(permissionsResponse, "permissions")
@@ -1 +1 @@
1
- {"version":3,"file":"document-export-permissions.js","sourceRoot":"","sources":["../../../src/lib/document-export-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,kFAAkF;AAClF,SAAS,IAAI,CAAC,KAAc,EAAE,GAAW;IACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,KAAgC,CAAC;QAClD,KAAK,MAAM,SAAS,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAAE,OAAO,QAAQ,CAAC,SAAS,CAAU,CAAC;QAC9E,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,mBAA4B,EAC5B,eAAwB;IAExB,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC;SACrD,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC;SAC5B,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;QAChB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,SAAS,EAAE,CAAC,CAAC,SAAS;KACvB,CAAC,CAAC,CAAC;IAEN,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC;SACjD,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC;SAC5B,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;QAChB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,MAAM,EAAE,YAAqB;QAC7B,MAAM,EAAE,SAAkB;KAC3B,CAAC,CAAC,CAAC;IAEN,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"document-export-permissions.js","sourceRoot":"","sources":["../../../src/lib/document-export-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,uFAAuF;AACvF,MAAM,CAAC,MAAM,mCAAmC,GAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAUjF,kFAAkF;AAClF,SAAS,IAAI,CAAC,KAAc,EAAE,GAAW;IACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,KAAgC,CAAC;QAClD,KAAK,MAAM,SAAS,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAAE,OAAO,QAAQ,CAAC,SAAS,CAAU,CAAC;QAC9E,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,mBAA4B,EAC5B,eAAwB;IAExB,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC;SACrD,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC;SAC5B,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;QAChB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,SAAS,EAAE,CAAC,CAAC,SAAS;KACvB,CAAC,CAAC,CAAC;IAEN,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC;SACjD,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC;SAC5B,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;QAChB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,MAAM,EAAE,YAAqB;QAC7B,MAAM,EAAE,SAAkB;KAC3B,CAAC,CAAC,CAAC;IAEN,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * `documents export` of a record-log (format 3) document (#4310, behavior 24).
3
+ *
4
+ * The document's base is a segment: its row chunks were written across
5
+ * alarms while writes continued, so they are no image of the document at any
6
+ * one log number; its corrections chunk holds every row and tombstone written
7
+ * between the export's start `B` and the read `C`. This module requests a
8
+ * segment, waits for it, downloads the chunks and the corrections through the
9
+ * chain export's grant, verifies each, merges the corrections into the rows
10
+ * (a changed row replaces its line, a tombstone removes it, a new row joins
11
+ * in id order) and re-cuts the merged rows into snapshot-layout chunks — so
12
+ * the directory is the document at `C`, which `documents ingest` loads into
13
+ * another format-3 document.
14
+ *
15
+ * Nothing is written under `snapshot/` until every download has verified.
16
+ */
17
+ /** The calls an export makes; `ApiClient` supplies them in the verb. */
18
+ export interface RecordLogExportClient {
19
+ requestSegment(): Promise<any>;
20
+ getSegment(segmentId: string): Promise<any>;
21
+ listSegments(): Promise<any>;
22
+ exportChain(): Promise<any>;
23
+ /** Read one object through a `/doc-artifact/…` path. */
24
+ download(artifactPath: string): Promise<Buffer>;
25
+ }
26
+ /** What the export wrote. */
27
+ export interface RecordLogExportResult {
28
+ /** Bytes of the segment's chunks and corrections, as downloaded. */
29
+ bytes: number;
30
+ /** `C`: the log number the directory is an image of. */
31
+ lsn: number;
32
+ segment: {
33
+ segmentId: string;
34
+ lsn: number;
35
+ completedLsn: number;
36
+ rows: number;
37
+ chunks: number;
38
+ corrections: number;
39
+ };
40
+ }
41
+ /** Rows per re-cut chunk. */
42
+ export declare const RECORD_LOG_EXPORT_CHUNK_ROWS = 10000;
43
+ /**
44
+ * Export a format-3 document into `docDir`: `snapshot/manifest.json`, its
45
+ * re-cut chunks `snapshot/{model}/{n}.ndjson.gz`, and `chain.json`
46
+ * (`{version: 3, documentFormat: 3, documentId, lsn: C, segment}`, with no
47
+ * grant in it). The caller writes `permissions.json`, `metadata.json` and the
48
+ * blobs, as for every format.
49
+ */
50
+ export declare function exportRecordLogDocument(options: {
51
+ client: RecordLogExportClient;
52
+ documentId: string;
53
+ docDir: string;
54
+ chunkRows?: number;
55
+ sleep?: (ms: number) => Promise<void>;
56
+ onProgress?: (line: string) => void;
57
+ }): Promise<RecordLogExportResult>;
@@ -0,0 +1,215 @@
1
+ /**
2
+ * `documents export` of a record-log (format 3) document (#4310, behavior 24).
3
+ *
4
+ * The document's base is a segment: its row chunks were written across
5
+ * alarms while writes continued, so they are no image of the document at any
6
+ * one log number; its corrections chunk holds every row and tombstone written
7
+ * between the export's start `B` and the read `C`. This module requests a
8
+ * segment, waits for it, downloads the chunks and the corrections through the
9
+ * chain export's grant, verifies each, merges the corrections into the rows
10
+ * (a changed row replaces its line, a tombstone removes it, a new row joins
11
+ * in id order) and re-cuts the merged rows into snapshot-layout chunks — so
12
+ * the directory is the document at `C`, which `documents ingest` loads into
13
+ * another format-3 document.
14
+ *
15
+ * Nothing is written under `snapshot/` until every download has verified.
16
+ */
17
+ import fs from "fs";
18
+ import path from "path";
19
+ import zlib from "zlib";
20
+ import { createHash } from "crypto";
21
+ import { compareRecordIds, readSnapshotChunk } from "js-bao";
22
+ /** Rows per re-cut chunk. */
23
+ export const RECORD_LOG_EXPORT_CHUNK_ROWS = 10_000;
24
+ const POLL_MS = 500;
25
+ /**
26
+ * Request a segment and wait for it: one already exporting is waited for
27
+ * rather than refused. Answers the complete segment's view; a failed one
28
+ * throws with its reason.
29
+ */
30
+ async function awaitSegment(client, options) {
31
+ let segmentId;
32
+ try {
33
+ segmentId = (await client.requestSegment()).segmentId;
34
+ }
35
+ catch (error) {
36
+ if (error?.code !== "SEGMENT_EXPORT_ACTIVE")
37
+ throw error;
38
+ const listed = await client.listSegments();
39
+ const active = (listed?.items ?? []).find((s) => s.state === "exporting");
40
+ if (!active)
41
+ throw error;
42
+ segmentId = active.segmentId;
43
+ }
44
+ options.onProgress?.(`Exporting segment ${segmentId}...`);
45
+ for (;;) {
46
+ const view = await client.getSegment(segmentId);
47
+ if (view.state === "complete")
48
+ return view;
49
+ if (view.state === "failed" || view.state === "superseded") {
50
+ const failure = view.failure ? `${view.failure.code}: ${view.failure.reason}` : view.state;
51
+ throw new Error(`The segment export ${segmentId} failed (${failure}); nothing was written.`);
52
+ }
53
+ await options.sleep(POLL_MS);
54
+ }
55
+ }
56
+ /** The lines of a downloaded corrections chunk, verified against the manifest's entry. */
57
+ function readCorrections(body, entry) {
58
+ if (!entry || body.byteLength !== entry.bytes || createHash("sha256").update(body).digest("hex") !== entry.sha256) {
59
+ throw new Error(`The segment's corrections chunk does not match its manifest (expected ${entry?.bytes} bytes and sha256 ${entry?.sha256}); nothing was written.`);
60
+ }
61
+ const text = zlib.gunzipSync(body).toString("utf8");
62
+ const out = [];
63
+ for (const raw of text.split("\n")) {
64
+ if (!raw)
65
+ continue;
66
+ const tab = raw.indexOf("\t");
67
+ if (tab < 0)
68
+ throw new Error("The segment's corrections chunk holds a line with no id; nothing was written.");
69
+ const line = JSON.parse(raw.slice(tab + 1));
70
+ if (!line || typeof line !== "object" || Array.isArray(line)) {
71
+ throw new Error("The segment's corrections chunk holds a line that is not an object; nothing was written.");
72
+ }
73
+ out.push({ id: raw.slice(0, tab), line });
74
+ }
75
+ if (out.length !== entry.rows) {
76
+ throw new Error(`The segment's corrections chunk holds ${out.length} lines, not ${entry.rows}; nothing was written.`);
77
+ }
78
+ return out;
79
+ }
80
+ /**
81
+ * Whether a corrections line is a tombstone: exactly `{_type, _deleted: true}`,
82
+ * as the room writes one. A live row's line carries its fields beside `_type`,
83
+ * so a field of the record named `_deleted` does not remove it.
84
+ */
85
+ function isTombstoneLine(line) {
86
+ const keys = Object.keys(line);
87
+ return line._deleted === true && keys.length === 2 && keys.includes("_type");
88
+ }
89
+ /**
90
+ * Refuse a model whose directory would not be a plain child of `snapshotDir`:
91
+ * an empty name, `.` or `..`, a path separator, or a NUL. Model names are any
92
+ * string a writer sent, so they are checked before they become paths.
93
+ */
94
+ function assertModelDirectory(snapshotDir, model) {
95
+ const plain = model !== "" && model !== "." && model !== ".." && !/[\\/\0]/.test(model);
96
+ const resolved = path.resolve(snapshotDir, model);
97
+ if (!plain || path.dirname(resolved) !== path.resolve(snapshotDir)) {
98
+ throw new Error(`The document holds a model named ${JSON.stringify(model)}, which cannot be written as a directory of the export; nothing was written.`);
99
+ }
100
+ }
101
+ /** Gzip one chunk's rows in the snapshot layout, `⟨id⟩\t⟨data⟩` per line, and describe it. */
102
+ function encodeChunk(model, index, rows) {
103
+ const raw = Buffer.from(rows.map(([id, data]) => `${id}\t${data}\n`).join(""), "utf8");
104
+ const body = zlib.gzipSync(raw, { level: 9 });
105
+ return {
106
+ body,
107
+ entry: {
108
+ key: `snapshot/${model}/${index}.ndjson.gz`,
109
+ path: `${model}/${index}`,
110
+ model,
111
+ bytes: body.byteLength,
112
+ rawBytes: raw.byteLength,
113
+ rows: rows.length,
114
+ firstId: rows[0][0],
115
+ lastId: rows[rows.length - 1][0],
116
+ sha256: createHash("sha256").update(body).digest("hex"),
117
+ },
118
+ };
119
+ }
120
+ /**
121
+ * Export a format-3 document into `docDir`: `snapshot/manifest.json`, its
122
+ * re-cut chunks `snapshot/{model}/{n}.ndjson.gz`, and `chain.json`
123
+ * (`{version: 3, documentFormat: 3, documentId, lsn: C, segment}`, with no
124
+ * grant in it). The caller writes `permissions.json`, `metadata.json` and the
125
+ * blobs, as for every format.
126
+ */
127
+ export async function exportRecordLogDocument(options) {
128
+ const { client, documentId, docDir } = options;
129
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
130
+ await awaitSegment(client, { sleep, onProgress: options.onProgress });
131
+ const chain = await client.exportChain();
132
+ const grant = chain.segment.download.path;
133
+ const manifest = JSON.parse((await client.download(grant)).toString("utf8"));
134
+ let bytes = 0;
135
+ // Every row of every chunk, verified, by model and id.
136
+ const tables = new Map();
137
+ const table = (model) => {
138
+ let rows = tables.get(model);
139
+ if (!rows)
140
+ tables.set(model, (rows = new Map()));
141
+ return rows;
142
+ };
143
+ for (const entry of manifest.chunks ?? []) {
144
+ const body = await client.download(`${grant}/${entry.path}`);
145
+ bytes += body.byteLength;
146
+ let rows;
147
+ try {
148
+ rows = await readSnapshotChunk(new Uint8Array(body), { ...entry, key: entry.path });
149
+ }
150
+ catch (error) {
151
+ throw new Error(`The segment's chunk ${entry.path} failed verification (${error?.message ?? error}); nothing was written.`);
152
+ }
153
+ for (const row of rows)
154
+ table(row._type).set(row._id, row._data);
155
+ }
156
+ const correctionsBody = await client.download(`${grant}/${manifest.corrections?.path ?? "corrections"}`);
157
+ bytes += correctionsBody.byteLength;
158
+ for (const { id, line } of readCorrections(correctionsBody, manifest.corrections)) {
159
+ const { _type, ...fields } = line;
160
+ if (typeof _type !== "string") {
161
+ throw new Error(`The segment's corrections chunk holds a line for ${id} with no model; nothing was written.`);
162
+ }
163
+ if (isTombstoneLine(line))
164
+ table(_type).delete(id);
165
+ else
166
+ table(_type).set(id, JSON.stringify(fields));
167
+ }
168
+ // Re-cut, model by model in id order. A model is a directory of the export,
169
+ // so one that is not a plain name refuses the export before anything is written.
170
+ const chunkRows = options.chunkRows ?? RECORD_LOG_EXPORT_CHUNK_ROWS;
171
+ const snapshotDir = path.join(docDir, "snapshot");
172
+ for (const model of tables.keys())
173
+ assertModelDirectory(snapshotDir, model);
174
+ fs.rmSync(snapshotDir, { recursive: true, force: true });
175
+ const entries = [];
176
+ let rows = 0;
177
+ let written = 0;
178
+ for (const model of [...tables.keys()].sort(compareRecordIds)) {
179
+ const sorted = [...tables.get(model)].sort(([a], [b]) => compareRecordIds(a, b));
180
+ for (let at = 0, index = 0; at < sorted.length; at += chunkRows, index++) {
181
+ const { body, entry } = encodeChunk(model, index, sorted.slice(at, at + chunkRows));
182
+ const file = path.join(snapshotDir, model, `${index}.ndjson.gz`);
183
+ fs.mkdirSync(path.dirname(file), { recursive: true });
184
+ fs.writeFileSync(file, body);
185
+ entries.push({ ...entry, ordinal: entries.length });
186
+ rows += entry.rows;
187
+ written += entry.bytes;
188
+ }
189
+ }
190
+ const completedLsn = Number(chain.completedLsn);
191
+ fs.mkdirSync(snapshotDir, { recursive: true });
192
+ fs.writeFileSync(path.join(snapshotDir, "manifest.json"), JSON.stringify({
193
+ kind: "segment-export",
194
+ version: 1,
195
+ documentFormat: 3,
196
+ documentId,
197
+ lsn: completedLsn,
198
+ schema: manifest.schema ?? {},
199
+ chunks: entries,
200
+ totals: { rows, chunks: entries.length, bytes: written },
201
+ }, null, 2));
202
+ const segment = {
203
+ segmentId: String(chain.segment.segmentId),
204
+ lsn: Number(chain.lsn),
205
+ completedLsn,
206
+ rows: Number(chain.segment.rows),
207
+ chunks: Number(chain.segment.chunks),
208
+ corrections: Number(chain.segment.corrections),
209
+ };
210
+ // Last, and without the grant: a signature is this run's read of the
211
+ // document, and an artifact that outlives it must not carry one.
212
+ fs.writeFileSync(path.join(docDir, "chain.json"), JSON.stringify({ version: 3, documentFormat: 3, documentId, lsn: completedLsn, segment }, null, 2));
213
+ return { bytes, lsn: completedLsn, segment };
214
+ }
215
+ //# sourceMappingURL=document-export-record-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-export-record-log.js","sourceRoot":"","sources":["../../../src/lib/document-export-record-log.ts"],"names":[],"mappings":"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"}
@@ -14,8 +14,8 @@
14
14
  * falls back to a bounded external sort.
15
15
  *
16
16
  * The local check is the server's, said on this side: the rules it mirrors are
17
- * `planLine`'s in `src/large-documents/ingest-pipeline.ts`, and the artifact's
18
- * own rules are in `docs/large-document-ingest.md`.
17
+ * `planLine`'s in `src/rooms/record-room/load.ts`, and the artifact's own
18
+ * rules are in `docs/large-document-ingest.md`.
19
19
  */
20
20
  import type { DiscoveredIngestInput } from "./document-ingest-input.js";
21
21
  /** A line, a file or a plan this document's schema does not accept. */
@@ -26,6 +26,12 @@ export declare class IngestArtifactError extends Error {
26
26
  export interface IngestModelSchema {
27
27
  fields: Set<string>;
28
28
  stringSets: Set<string>;
29
+ /**
30
+ * A record-log (format 3) document takes fields and models it does not
31
+ * declare, as its writes do; the room refuses a row that breaks a declared
32
+ * type, row by row.
33
+ */
34
+ open?: boolean;
29
35
  }
30
36
  /** Every model the document has a declaration for. */
31
37
  export interface IngestSchema {
@@ -62,10 +68,23 @@ export interface IngestModelSummary {
62
68
  rawBytes: number;
63
69
  deletes: number;
64
70
  }
71
+ /** A row of a format-2 export left out of the artifact, and why. */
72
+ export interface IngestRefusedRow {
73
+ model: string;
74
+ id: string;
75
+ /** `file:line`. */
76
+ where: string;
77
+ reason: string;
78
+ }
65
79
  /** The artifact, ready to upload. */
66
80
  export interface IngestArtifactPlan {
67
81
  models: IngestModelSummary[];
68
82
  chunks: IngestChunkDescriptor[];
83
+ /**
84
+ * Rows of a format-2 export that cannot be sent as one record, left out
85
+ * before upload. Every other input either builds whole or is refused.
86
+ */
87
+ refused: IngestRefusedRow[];
69
88
  rows: number;
70
89
  bytes: number;
71
90
  rawBytes: number;
@@ -79,6 +98,11 @@ export interface IngestArtifactPlan {
79
98
  export interface BuildIngestArtifactOptions {
80
99
  input: DiscoveredIngestInput;
81
100
  schema: IngestSchema;
101
+ /**
102
+ * The document is a record-log (format 3) document: a model or a field it
103
+ * does not declare is taken as it is, as its writes take them.
104
+ */
105
+ open?: boolean;
82
106
  /** Where chunk bodies and sort runs are written. */
83
107
  tmpDir?: string;
84
108
  /** Cut a chunk at this many decompressed bytes. */
@@ -14,8 +14,8 @@
14
14
  * falls back to a bounded external sort.
15
15
  *
16
16
  * The local check is the server's, said on this side: the rules it mirrors are
17
- * `planLine`'s in `src/large-documents/ingest-pipeline.ts`, and the artifact's
18
- * own rules are in `docs/large-document-ingest.md`.
17
+ * `planLine`'s in `src/rooms/record-room/load.ts`, and the artifact's own
18
+ * rules are in `docs/large-document-ingest.md`.
19
19
  */
20
20
  import fs from "fs";
21
21
  import path from "path";
@@ -25,6 +25,7 @@ import zlib from "zlib";
25
25
  import { createHash } from "crypto";
26
26
  import { StringDecoder } from "string_decoder";
27
27
  import { compareRecordIds, INGEST_CHUNK_LIMITS } from "js-bao";
28
+ import { flattenFormat2Row } from "./document-ingest-format2.js";
28
29
  /** A line, a file or a plan this document's schema does not accept. */
29
30
  export class IngestArtifactError extends Error {
30
31
  constructor(message) {
@@ -64,6 +65,8 @@ export async function buildIngestArtifact(options) {
64
65
  const { input, schema, cutRawBytes = INGEST_CUT_RAW_BYTES, cutRows = INGEST_CUT_ROWS, runBytes = INGEST_SORT_RUN_BYTES, maxChunkBytes = INGEST_CHUNK_LIMITS.maxChunkBytes, maxChunkRawBytes = INGEST_CHUNK_LIMITS.maxChunkRawBytes, maxChunkRows = INGEST_CHUNK_LIMITS.maxChunkRows, maxChunks = INGEST_CHUNK_LIMITS.maxChunks, maxTotalBytes = INGEST_CHUNK_LIMITS.maxTotalBytes, } = options;
65
66
  const scratch = fs.mkdtempSync(path.join(options.tmpDir ?? os.tmpdir(), "primitive-ingest-"));
66
67
  const written = [];
68
+ const refused = [];
69
+ const read = (source, onRefused) => readRows(source, Boolean(input.format2), onRefused);
67
70
  const cleanup = async () => {
68
71
  fs.rmSync(scratch, { recursive: true, force: true });
69
72
  };
@@ -79,7 +82,15 @@ export async function buildIngestArtifact(options) {
79
82
  entry.sources.push(source);
80
83
  }
81
84
  for (const [model, entry] of models) {
82
- const declared = schema.models.get(model);
85
+ // A format-2 export's converted row into a record-log document is held
86
+ // to the line's structure only: a value its declaration refuses (an
87
+ // array that is not all strings) is the room's to refuse, row by row
88
+ // and naming the field, not a reason to stop the whole load.
89
+ const declared = options.open
90
+ ? input.format2
91
+ ? { fields: new Set(), stringSets: new Set(), open: true }
92
+ : { ...(schema.models.get(model) ?? { fields: new Set(), stringSets: new Set() }), open: true }
93
+ : schema.models.get(model);
83
94
  if (!declared) {
84
95
  throw new IngestArtifactError(`This document declares no model ${model}. An ingest applies the ` +
85
96
  "document's existing schema; declare the model through your app's " +
@@ -87,7 +98,7 @@ export async function buildIngestArtifact(options) {
87
98
  }
88
99
  let previous = null;
89
100
  for (const source of entry.sources) {
90
- for await (const line of readSource(source)) {
101
+ for await (const line of read(source, (row) => refused.push(row))) {
91
102
  const parsed = checkIngestLine(line.where, model, line.text, declared);
92
103
  entry.rows += 1;
93
104
  if (parsed.deleted)
@@ -124,7 +135,7 @@ export async function buildIngestArtifact(options) {
124
135
  if (entry.sorted) {
125
136
  let previousId = null;
126
137
  for (const source of entry.sources) {
127
- for await (const line of readSource(source)) {
138
+ for await (const line of read(source)) {
128
139
  const parsed = parseIngestLine(line.where, line.text);
129
140
  assertNoDuplicate(previousId, parsed, line.where);
130
141
  previousId = parsed.id;
@@ -133,7 +144,7 @@ export async function buildIngestArtifact(options) {
133
144
  }
134
145
  }
135
146
  else {
136
- const sorted = await externalSort(entry.sources, scratch, runBytes);
147
+ const sorted = await externalSort(entry.sources, read, scratch, runBytes);
137
148
  sortRuns += sorted.runs;
138
149
  let previous = null;
139
150
  for (const line of sorted.lines()) {
@@ -172,6 +183,7 @@ export async function buildIngestArtifact(options) {
172
183
  return {
173
184
  models: summaries,
174
185
  chunks,
186
+ refused,
175
187
  rows: summaries.reduce((sum, model) => sum + model.rows, 0),
176
188
  bytes: totalBytes,
177
189
  rawBytes: summaries.reduce((sum, model) => sum + model.rawBytes, 0),
@@ -211,6 +223,26 @@ async function* readSource(source) {
211
223
  stream.destroy?.();
212
224
  }
213
225
  }
226
+ /**
227
+ * Every row of one source, as {@link readSource} reads it, or as a record-log
228
+ * row when the source is a format-2 export's. A row that cannot be converted
229
+ * is left out and handed to `onRefused`.
230
+ */
231
+ async function* readRows(source, format2, onRefused) {
232
+ for await (const line of readSource(source)) {
233
+ if (!format2) {
234
+ yield line;
235
+ continue;
236
+ }
237
+ const parsed = parseIngestLine(line.where, line.text);
238
+ const converted = flattenFormat2Row(source.model, parsed.id, JSON.parse(parsed.patch));
239
+ if ("refused" in converted) {
240
+ onRefused?.({ model: source.model, id: parsed.id, where: line.where, reason: converted.refused });
241
+ continue;
242
+ }
243
+ yield { where: line.where, text: `${parsed.id}\t${JSON.stringify(converted.fields)}` };
244
+ }
245
+ }
214
246
  /** One line's id and patch, whichever of the two forms it is written in. */
215
247
  export function parseIngestLine(where, text) {
216
248
  let id;
@@ -299,6 +331,8 @@ export function checkIngestLine(where, model, text, declared) {
299
331
  continue;
300
332
  }
301
333
  if (!declared.fields.has(key)) {
334
+ if (declared.open)
335
+ continue;
302
336
  throw new IngestArtifactError(`${where}: the model ${model} does not declare the field ${key}`);
303
337
  }
304
338
  if (Array.isArray(value)) {
@@ -314,7 +348,7 @@ export function checkIngestLine(where, model, text, declared) {
314
348
  * writes each sorted run out and merges them back k-way, so the peak cost is
315
349
  * the run size plus one line per run whatever the input's size.
316
350
  */
317
- async function externalSort(sources, scratch, runBytes) {
351
+ async function externalSort(sources, read, scratch, runBytes) {
318
352
  const runFiles = [];
319
353
  let buffer = [];
320
354
  let buffered = 0;
@@ -327,7 +361,7 @@ async function externalSort(sources, scratch, runBytes) {
327
361
  buffered = 0;
328
362
  };
329
363
  for (const source of sources) {
330
- for await (const raw of readSource(source)) {
364
+ for await (const raw of read(source)) {
331
365
  const parsed = parseIngestLine(raw.where, raw.text);
332
366
  buffer.push({ ...parsed, where: raw.where });
333
367
  buffered += parsed.id.length + parsed.patch.length + raw.where.length + 2;