@beechcms/core 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/antivirus/antivirus.interface.d.ts +12 -0
  3. package/dist/antivirus/antivirus.interface.d.ts.map +1 -0
  4. package/dist/antivirus/antivirus.interface.js +3 -0
  5. package/dist/antivirus/noop-antivirus.provider.d.ts +6 -0
  6. package/dist/antivirus/noop-antivirus.provider.d.ts.map +1 -0
  7. package/dist/antivirus/noop-antivirus.provider.js +8 -0
  8. package/dist/antivirus/virustotal-antivirus.provider.d.ts +8 -0
  9. package/dist/antivirus/virustotal-antivirus.provider.d.ts.map +1 -0
  10. package/dist/antivirus/virustotal-antivirus.provider.js +48 -0
  11. package/dist/automations-grammar-words.d.ts +2 -0
  12. package/dist/automations-grammar-words.d.ts.map +1 -0
  13. package/dist/automations-grammar-words.js +8 -0
  14. package/dist/automations.repository.interface.d.ts +19 -0
  15. package/dist/automations.repository.interface.d.ts.map +1 -0
  16. package/dist/automations.repository.interface.js +3 -0
  17. package/dist/automations.runner.interface.d.ts +10 -0
  18. package/dist/automations.runner.interface.d.ts.map +1 -0
  19. package/dist/automations.runner.interface.js +3 -0
  20. package/dist/automations.runner.stub.d.ts +5 -0
  21. package/dist/automations.runner.stub.d.ts.map +1 -0
  22. package/dist/automations.runner.stub.js +7 -0
  23. package/dist/automations.types.d.ts +75 -0
  24. package/dist/automations.types.d.ts.map +1 -0
  25. package/dist/automations.types.js +3 -0
  26. package/dist/clock.d.ts +25 -0
  27. package/dist/clock.d.ts.map +1 -0
  28. package/dist/clock.js +11 -0
  29. package/dist/common/canonical-json.d.ts +30 -0
  30. package/dist/common/canonical-json.d.ts.map +1 -0
  31. package/dist/common/canonical-json.js +89 -0
  32. package/dist/common/hooks.d.ts +3 -0
  33. package/dist/common/hooks.d.ts.map +1 -1
  34. package/dist/content/content.repository.d.ts +2 -2
  35. package/dist/content/content.repository.d.ts.map +1 -1
  36. package/dist/content/deletion-ledger.d.ts +39 -0
  37. package/dist/content/deletion-ledger.d.ts.map +1 -0
  38. package/dist/content/deletion-ledger.js +3 -0
  39. package/dist/content/richtext/richtext-render.d.ts.map +1 -1
  40. package/dist/content/richtext/richtext-render.js +14 -1
  41. package/dist/content/seed.repository.d.ts +22 -0
  42. package/dist/content/seed.repository.d.ts.map +1 -1
  43. package/dist/content-scan.repository.d.ts +9 -0
  44. package/dist/content-scan.repository.d.ts.map +1 -0
  45. package/dist/content-scan.repository.js +3 -0
  46. package/dist/content.repository.d.ts +247 -0
  47. package/dist/content.repository.d.ts.map +1 -0
  48. package/dist/content.repository.js +59 -0
  49. package/dist/dashboard-layout/seed-layout.d.ts.map +1 -1
  50. package/dist/dashboard-layout/seed-layout.js +13 -6
  51. package/dist/dashboard-layout.d.ts +154 -0
  52. package/dist/dashboard-layout.d.ts.map +1 -0
  53. package/dist/dashboard-layout.js +186 -0
  54. package/dist/dashboard-layout.repository.d.ts +18 -0
  55. package/dist/dashboard-layout.repository.d.ts.map +1 -0
  56. package/dist/dashboard-layout.repository.js +3 -0
  57. package/dist/dashboard-permissions.d.ts +3 -0
  58. package/dist/dashboard-permissions.d.ts.map +1 -0
  59. package/dist/dashboard-permissions.js +11 -0
  60. package/dist/dashboard-scopes.d.ts +12 -0
  61. package/dist/dashboard-scopes.d.ts.map +1 -0
  62. package/dist/dashboard-scopes.js +30 -0
  63. package/dist/define-seed.d.ts +3 -0
  64. package/dist/define-seed.d.ts.map +1 -0
  65. package/dist/define-seed.js +5 -0
  66. package/dist/demo-data.repository.d.ts +5 -0
  67. package/dist/demo-data.repository.d.ts.map +1 -0
  68. package/dist/demo-data.repository.js +3 -0
  69. package/dist/email.provider.d.ts +32 -0
  70. package/dist/email.provider.d.ts.map +1 -0
  71. package/dist/email.provider.js +4 -0
  72. package/dist/engine/ddl/ddl.d.ts +216 -0
  73. package/dist/engine/ddl/ddl.d.ts.map +1 -0
  74. package/dist/engine/ddl/ddl.js +574 -0
  75. package/dist/engine/ddl/schema-mutator.d.ts +26 -0
  76. package/dist/engine/ddl/schema-mutator.d.ts.map +1 -0
  77. package/dist/engine/ddl/schema-mutator.js +3 -0
  78. package/dist/engine/ddl/seed-ddl-destructive.d.ts +40 -0
  79. package/dist/engine/ddl/seed-ddl-destructive.d.ts.map +1 -0
  80. package/dist/engine/ddl/seed-ddl-destructive.js +149 -0
  81. package/dist/engine/ddl/seed-ddl.d.ts +43 -0
  82. package/dist/engine/ddl/seed-ddl.d.ts.map +1 -0
  83. package/dist/engine/ddl/seed-ddl.js +115 -0
  84. package/dist/engine/ddl.d.ts +15 -0
  85. package/dist/engine/ddl.d.ts.map +1 -1
  86. package/dist/engine/ddl.js +30 -1
  87. package/dist/engine/introspection/introspection.d.ts +101 -0
  88. package/dist/engine/introspection/introspection.d.ts.map +1 -0
  89. package/dist/engine/introspection/introspection.js +127 -0
  90. package/dist/engine/introspection/schema-fingerprint.d.ts +73 -0
  91. package/dist/engine/introspection/schema-fingerprint.d.ts.map +1 -0
  92. package/dist/engine/introspection/schema-fingerprint.js +97 -0
  93. package/dist/engine/introspection.d.ts +101 -0
  94. package/dist/engine/introspection.d.ts.map +1 -0
  95. package/dist/engine/introspection.js +127 -0
  96. package/dist/engine/localization/localization.d.ts +127 -0
  97. package/dist/engine/localization/localization.d.ts.map +1 -0
  98. package/dist/engine/localization/localization.js +212 -0
  99. package/dist/engine/localization.d.ts +127 -0
  100. package/dist/engine/localization.d.ts.map +1 -0
  101. package/dist/engine/localization.js +212 -0
  102. package/dist/engine/policies.d.ts.map +1 -1
  103. package/dist/engine/policies.js +5 -0
  104. package/dist/engine/privacy/policies.d.ts +58 -0
  105. package/dist/engine/privacy/policies.d.ts.map +1 -0
  106. package/dist/engine/privacy/policies.js +185 -0
  107. package/dist/engine/privacy/privacy.service.d.ts +65 -0
  108. package/dist/engine/privacy/privacy.service.d.ts.map +1 -0
  109. package/dist/engine/privacy/privacy.service.js +114 -0
  110. package/dist/engine/privacy.service.d.ts.map +1 -1
  111. package/dist/engine/query/query.d.ts +23 -0
  112. package/dist/engine/query/query.d.ts.map +1 -0
  113. package/dist/engine/query/query.js +301 -0
  114. package/dist/engine/query/relations.d.ts +28 -0
  115. package/dist/engine/query/relations.d.ts.map +1 -0
  116. package/dist/engine/query/relations.js +25 -0
  117. package/dist/engine/query/serialize.d.ts +22 -0
  118. package/dist/engine/query/serialize.d.ts.map +1 -0
  119. package/dist/engine/query/serialize.js +175 -0
  120. package/dist/engine/schema-fingerprint.d.ts +73 -0
  121. package/dist/engine/schema-fingerprint.d.ts.map +1 -0
  122. package/dist/engine/schema-fingerprint.js +97 -0
  123. package/dist/engine/seed-registry.d.ts.map +1 -1
  124. package/dist/engine/seed-registry.js +23 -4
  125. package/dist/engine/seed-types-generator.d.ts.map +1 -1
  126. package/dist/engine/seed-types-generator.js +8 -5
  127. package/dist/engine/seed-validation.d.ts +7 -0
  128. package/dist/engine/seed-validation.d.ts.map +1 -1
  129. package/dist/engine/seed-validation.js +59 -1
  130. package/dist/engine/seeds/define-seed.d.ts +3 -0
  131. package/dist/engine/seeds/define-seed.d.ts.map +1 -0
  132. package/dist/engine/seeds/define-seed.js +5 -0
  133. package/dist/engine/seeds/seed-registry.d.ts +71 -0
  134. package/dist/engine/seeds/seed-registry.d.ts.map +1 -0
  135. package/dist/engine/seeds/seed-registry.js +167 -0
  136. package/dist/engine/seeds/seed-types-generator.d.ts +25 -0
  137. package/dist/engine/seeds/seed-types-generator.d.ts.map +1 -0
  138. package/dist/engine/seeds/seed-types-generator.js +117 -0
  139. package/dist/engine/seeds/seed-validation.d.ts +30 -0
  140. package/dist/engine/seeds/seed-validation.d.ts.map +1 -0
  141. package/dist/engine/seeds/seed-validation.js +364 -0
  142. package/dist/engine/seeds/seeds.d.ts +20 -0
  143. package/dist/engine/seeds/seeds.d.ts.map +1 -0
  144. package/dist/engine/seeds/seeds.js +21 -0
  145. package/dist/engine/types.d.ts +7 -0
  146. package/dist/engine/types.d.ts.map +1 -1
  147. package/dist/engine/validation/emptiness.d.ts +12 -0
  148. package/dist/engine/validation/emptiness.d.ts.map +1 -0
  149. package/dist/engine/validation/emptiness.js +33 -0
  150. package/dist/engine/validation/index.d.ts +1 -1
  151. package/dist/engine/validation/index.d.ts.map +1 -1
  152. package/dist/engine/validation/richtext-sanitizer.d.ts.map +1 -1
  153. package/dist/engine/validation/richtext-sanitizer.js +2 -1
  154. package/dist/engine.d.ts +144 -0
  155. package/dist/engine.d.ts.map +1 -0
  156. package/dist/engine.js +741 -0
  157. package/dist/file-types.d.ts +13 -0
  158. package/dist/file-types.d.ts.map +1 -0
  159. package/dist/file-types.js +85 -0
  160. package/dist/hooks.d.ts +29 -0
  161. package/dist/hooks.d.ts.map +1 -0
  162. package/dist/hooks.js +3 -0
  163. package/dist/id-generator.d.ts +26 -0
  164. package/dist/id-generator.d.ts.map +1 -0
  165. package/dist/id-generator.js +12 -0
  166. package/dist/idempotency.repository.d.ts +13 -0
  167. package/dist/idempotency.repository.d.ts.map +1 -0
  168. package/dist/idempotency.repository.js +3 -0
  169. package/dist/index.d.ts +16 -1
  170. package/dist/index.d.ts.map +1 -1
  171. package/dist/index.js +16 -1
  172. package/dist/kanban-position.repository.d.ts +19 -0
  173. package/dist/kanban-position.repository.d.ts.map +1 -0
  174. package/dist/kanban-position.repository.js +3 -0
  175. package/dist/kanban.d.ts +75 -0
  176. package/dist/kanban.d.ts.map +1 -0
  177. package/dist/kanban.js +82 -0
  178. package/dist/layout-permissions.d.ts +3 -0
  179. package/dist/layout-permissions.d.ts.map +1 -0
  180. package/dist/layout-permissions.js +11 -0
  181. package/dist/media/file-types.d.ts +103 -9
  182. package/dist/media/file-types.d.ts.map +1 -1
  183. package/dist/media/file-types.js +336 -52
  184. package/dist/media/image-transformer.d.ts +34 -0
  185. package/dist/media/image-transformer.d.ts.map +1 -0
  186. package/dist/media/image-transformer.js +3 -0
  187. package/dist/media/magic-bytes.d.ts +21 -0
  188. package/dist/media/magic-bytes.d.ts.map +1 -0
  189. package/dist/media/magic-bytes.js +66 -0
  190. package/dist/media/media-transform.d.ts +88 -0
  191. package/dist/media/media-transform.d.ts.map +1 -0
  192. package/dist/media/media-transform.js +193 -0
  193. package/dist/media.repository.d.ts +61 -0
  194. package/dist/media.repository.d.ts.map +1 -0
  195. package/dist/media.repository.js +3 -0
  196. package/dist/notifications/notification-service.d.ts +1 -1
  197. package/dist/oauth/authorization-code.repository.d.ts +33 -0
  198. package/dist/oauth/authorization-code.repository.d.ts.map +1 -0
  199. package/dist/oauth/authorization-code.repository.js +3 -0
  200. package/dist/oauth/client.repository.d.ts +17 -0
  201. package/dist/oauth/client.repository.d.ts.map +1 -0
  202. package/dist/oauth/client.repository.js +3 -0
  203. package/dist/oauth/consent.repository.d.ts +25 -0
  204. package/dist/oauth/consent.repository.d.ts.map +1 -0
  205. package/dist/oauth/consent.repository.js +3 -0
  206. package/dist/oauth/pkce.d.ts +21 -0
  207. package/dist/oauth/pkce.d.ts.map +1 -0
  208. package/dist/oauth/pkce.js +47 -0
  209. package/dist/oauth/role-guard.d.ts +32 -0
  210. package/dist/oauth/role-guard.d.ts.map +1 -0
  211. package/dist/oauth/role-guard.js +14 -0
  212. package/dist/oauth/scopes.d.ts +27 -0
  213. package/dist/oauth/scopes.d.ts.map +1 -0
  214. package/dist/oauth/scopes.js +41 -0
  215. package/dist/oauth/token.repository.d.ts +46 -0
  216. package/dist/oauth/token.repository.d.ts.map +1 -0
  217. package/dist/oauth/token.repository.js +3 -0
  218. package/dist/observability/activity-logger.d.ts +1 -1
  219. package/dist/observability/activity-logger.d.ts.map +1 -1
  220. package/dist/policies.d.ts +10 -0
  221. package/dist/policies.d.ts.map +1 -0
  222. package/dist/policies.js +33 -0
  223. package/dist/queue/queue.stub.d.ts.map +1 -1
  224. package/dist/queue/scheduler.stub.d.ts.map +1 -1
  225. package/dist/queue.interface.d.ts +39 -0
  226. package/dist/queue.interface.d.ts.map +1 -0
  227. package/dist/queue.interface.js +3 -0
  228. package/dist/queue.stub.d.ts +6 -0
  229. package/dist/queue.stub.d.ts.map +1 -0
  230. package/dist/queue.stub.js +8 -0
  231. package/dist/rate-limit/rate-limiter.d.ts +13 -5
  232. package/dist/rate-limit/rate-limiter.d.ts.map +1 -1
  233. package/dist/rate-limit/token-bucket-rate-limiter.d.ts +20 -0
  234. package/dist/rate-limit/token-bucket-rate-limiter.d.ts.map +1 -0
  235. package/dist/rate-limit/token-bucket-rate-limiter.js +63 -0
  236. package/dist/rbac/evaluate.d.ts +57 -0
  237. package/dist/rbac/evaluate.d.ts.map +1 -0
  238. package/dist/rbac/evaluate.js +113 -0
  239. package/dist/rbac/invitation.repository.d.ts +66 -0
  240. package/dist/rbac/invitation.repository.d.ts.map +1 -0
  241. package/dist/rbac/invitation.repository.js +3 -0
  242. package/dist/rbac/permissions.d.ts +39 -0
  243. package/dist/rbac/permissions.d.ts.map +1 -0
  244. package/dist/rbac/permissions.js +43 -0
  245. package/dist/rbac/types.d.ts +118 -0
  246. package/dist/rbac/types.d.ts.map +1 -0
  247. package/dist/rbac/types.js +3 -0
  248. package/dist/relations.d.ts +28 -0
  249. package/dist/relations.d.ts.map +1 -0
  250. package/dist/relations.js +25 -0
  251. package/dist/richtext-render.d.ts +11 -0
  252. package/dist/richtext-render.d.ts.map +1 -0
  253. package/dist/richtext-render.js +87 -0
  254. package/dist/richtext.d.ts +11 -0
  255. package/dist/richtext.d.ts.map +1 -0
  256. package/dist/richtext.js +13 -0
  257. package/dist/scheduler.interface.d.ts +4 -0
  258. package/dist/scheduler.interface.d.ts.map +1 -0
  259. package/dist/scheduler.interface.js +3 -0
  260. package/dist/scheduler.stub.d.ts +5 -0
  261. package/dist/scheduler.stub.d.ts.map +1 -0
  262. package/dist/scheduler.stub.js +7 -0
  263. package/dist/schema/canonical.d.ts +15 -0
  264. package/dist/schema/canonical.d.ts.map +1 -0
  265. package/dist/schema/canonical.js +37 -0
  266. package/dist/schema/define.d.ts +42 -0
  267. package/dist/schema/define.d.ts.map +1 -0
  268. package/dist/schema/define.js +56 -0
  269. package/dist/schema/emit.d.ts +14 -0
  270. package/dist/schema/emit.d.ts.map +1 -0
  271. package/dist/schema/emit.js +43 -0
  272. package/dist/schema/index.d.ts +12 -0
  273. package/dist/schema/index.d.ts.map +1 -0
  274. package/dist/schema/index.js +13 -0
  275. package/dist/schema/manifest-seeds.d.ts +12 -0
  276. package/dist/schema/manifest-seeds.d.ts.map +1 -0
  277. package/dist/schema/manifest-seeds.js +48 -0
  278. package/dist/schema/manifest-validation.d.ts +13 -0
  279. package/dist/schema/manifest-validation.d.ts.map +1 -0
  280. package/dist/schema/manifest-validation.js +41 -0
  281. package/dist/schema/manifest.types.d.ts +54 -0
  282. package/dist/schema/manifest.types.d.ts.map +1 -0
  283. package/dist/schema/manifest.types.js +7 -0
  284. package/dist/schema-mutator.d.ts +26 -0
  285. package/dist/schema-mutator.d.ts.map +1 -0
  286. package/dist/schema-mutator.js +3 -0
  287. package/dist/search/vector-extractor.d.ts +11 -0
  288. package/dist/search/vector-extractor.d.ts.map +1 -0
  289. package/dist/search/vector-extractor.js +25 -0
  290. package/dist/search/vector.repository.d.ts +13 -0
  291. package/dist/search/vector.repository.d.ts.map +1 -0
  292. package/dist/search/vector.repository.js +3 -0
  293. package/dist/security/time-trap-token.repository.d.ts +9 -0
  294. package/dist/security/time-trap-token.repository.d.ts.map +1 -0
  295. package/dist/security/time-trap-token.repository.js +3 -0
  296. package/dist/security/time-trap.d.ts +7 -0
  297. package/dist/security/time-trap.d.ts.map +1 -0
  298. package/dist/security/time-trap.js +49 -0
  299. package/dist/seed-ddl-destructive.d.ts +40 -0
  300. package/dist/seed-ddl-destructive.d.ts.map +1 -0
  301. package/dist/seed-ddl-destructive.js +149 -0
  302. package/dist/seed-ddl.d.ts +40 -0
  303. package/dist/seed-ddl.d.ts.map +1 -0
  304. package/dist/seed-ddl.js +100 -0
  305. package/dist/seed-layout.d.ts +145 -0
  306. package/dist/seed-layout.d.ts.map +1 -0
  307. package/dist/seed-layout.js +192 -0
  308. package/dist/seed-layout.repository.d.ts +22 -0
  309. package/dist/seed-layout.repository.d.ts.map +1 -0
  310. package/dist/seed-layout.repository.js +3 -0
  311. package/dist/seed-registry.d.ts +71 -0
  312. package/dist/seed-registry.d.ts.map +1 -0
  313. package/dist/seed-registry.js +143 -0
  314. package/dist/seed-types-generator.d.ts +1 -1
  315. package/dist/seed-types-generator.d.ts.map +1 -1
  316. package/dist/seed-validation.d.ts +23 -0
  317. package/dist/seed-validation.d.ts.map +1 -0
  318. package/dist/seed-validation.js +224 -0
  319. package/dist/seed.repository.d.ts +37 -0
  320. package/dist/seed.repository.d.ts.map +1 -0
  321. package/dist/seed.repository.js +3 -0
  322. package/dist/seeds.d.ts +20 -0
  323. package/dist/seeds.d.ts.map +1 -0
  324. package/dist/seeds.js +21 -0
  325. package/dist/site-settings.repository.d.ts +16 -0
  326. package/dist/site-settings.repository.d.ts.map +1 -0
  327. package/dist/site-settings.repository.js +3 -0
  328. package/dist/slug-utils.d.ts +18 -0
  329. package/dist/slug-utils.d.ts.map +1 -0
  330. package/dist/slug-utils.js +32 -0
  331. package/dist/storage.d.ts +46 -0
  332. package/dist/storage.d.ts.map +1 -0
  333. package/dist/storage.js +3 -0
  334. package/dist/transfer/csv.d.ts +34 -0
  335. package/dist/transfer/csv.d.ts.map +1 -0
  336. package/dist/transfer/csv.js +135 -0
  337. package/dist/transfer/flat-seed.d.ts +13 -0
  338. package/dist/transfer/flat-seed.d.ts.map +1 -0
  339. package/dist/transfer/flat-seed.js +45 -0
  340. package/dist/transfer/index.d.ts +7 -0
  341. package/dist/transfer/index.d.ts.map +1 -0
  342. package/dist/transfer/index.js +8 -0
  343. package/dist/transfer/ndjson.d.ts +25 -0
  344. package/dist/transfer/ndjson.d.ts.map +1 -0
  345. package/dist/transfer/ndjson.js +62 -0
  346. package/dist/transfer/row-mapping.d.ts +36 -0
  347. package/dist/transfer/row-mapping.d.ts.map +1 -0
  348. package/dist/transfer/row-mapping.js +90 -0
  349. package/dist/transfer/transfer.constants.d.ts +20 -0
  350. package/dist/transfer/transfer.constants.d.ts.map +1 -0
  351. package/dist/transfer/transfer.constants.js +21 -0
  352. package/dist/transfer/transfer.types.d.ts +46 -0
  353. package/dist/transfer/transfer.types.d.ts.map +1 -0
  354. package/dist/transfer/transfer.types.js +6 -0
  355. package/dist/types.d.ts +243 -0
  356. package/dist/types.d.ts.map +1 -0
  357. package/dist/types.js +3 -0
  358. package/dist/validation.d.ts +50 -0
  359. package/dist/validation.d.ts.map +1 -0
  360. package/dist/validation.js +660 -0
  361. package/dist/webhook-crypto.d.ts +2 -0
  362. package/dist/webhook-crypto.d.ts.map +1 -1
  363. package/dist/webhook-crypto.js +2 -2
  364. package/dist/webhook-validation.d.ts +3 -0
  365. package/dist/webhook-validation.d.ts.map +1 -0
  366. package/dist/webhook-validation.js +6 -0
  367. package/dist/webhooks/webhook-crypto.d.ts +2 -0
  368. package/dist/webhooks/webhook-crypto.d.ts.map +1 -1
  369. package/dist/webhooks/webhook-crypto.js +2 -2
  370. package/package.json +23 -15
@@ -0,0 +1,46 @@
1
+ export interface PutBucketOptions {
2
+ contentType?: string;
3
+ metadata?: Record<string, string>;
4
+ }
5
+ export interface GetBucketResult {
6
+ body: ReadableStream | ArrayBuffer;
7
+ contentType?: string;
8
+ size: number;
9
+ metadata?: Record<string, string>;
10
+ }
11
+ export interface PresignOptions {
12
+ /** Duration of the signed URL in seconds. */
13
+ expiresIn: number;
14
+ /** Content-Type bound in the signature (PUT). */
15
+ contentType?: string;
16
+ /** Expected Content-Length in bytes (PUT). */
17
+ contentLength?: number;
18
+ }
19
+ export interface BeechBucket {
20
+ put(key: string, body: ArrayBuffer | Uint8Array | ReadableStream, options?: PutBucketOptions): Promise<void>;
21
+ get(key: string): Promise<GetBucketResult | null>;
22
+ delete(key: string): Promise<void>;
23
+ head(key: string): Promise<{
24
+ size: number;
25
+ contentType?: string;
26
+ metadata?: Record<string, string>;
27
+ } | null>;
28
+ getUrl(key: string): string;
29
+ getTotalSize(): Promise<number>;
30
+ list(options?: {
31
+ prefix?: string;
32
+ limit?: number;
33
+ cursor?: string;
34
+ }): Promise<{
35
+ objects: Array<{
36
+ key: string;
37
+ size: number;
38
+ }>;
39
+ cursor?: string;
40
+ }>;
41
+ /** Generates a signed URL for direct upload (PUT). */
42
+ presignPut(key: string, options: PresignOptions): Promise<string>;
43
+ /** Generates a signed URL for direct read (GET). */
44
+ presignGet(key: string, options: PresignOptions): Promise<string>;
45
+ }
46
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,cAAc,GAAG,WAAW,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,cAAc,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7G,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC7G,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAElJ,sDAAsD;IACtD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAElE,oDAAoD;IACpD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnE"}
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ export {};
@@ -0,0 +1,34 @@
1
+ /** Encodes one cell. `null`/`undefined` become an empty, unquoted field. */
2
+ export declare function encodeCsvValue(value: string | null | undefined): string;
3
+ /** Encodes one row, CRLF terminator included (RFC 4180 §2.1). */
4
+ export declare function encodeCsvRow(cells: Array<string | null | undefined>): string;
5
+ /**
6
+ * Splits an arbitrarily-chunked CSV text stream into rows of cells.
7
+ *
8
+ * Stateful and quote-aware: a newline inside a quoted field is DATA, not a row break, so
9
+ * a naive `split('\n')` corrupts any export containing a multi-line text branch — which
10
+ * the export side of this same module is perfectly capable of producing. The parser
11
+ * therefore carries its in-quotes state across chunk boundaries as well as across lines.
12
+ */
13
+ export declare class CsvRowReader {
14
+ private cells;
15
+ private field;
16
+ private inQuotes;
17
+ private quoteJustClosed;
18
+ private pendingCarriageReturn;
19
+ private rowHasContent;
20
+ private sawFirstChunk;
21
+ /** Feeds a chunk and returns every row completed by it. */
22
+ push(chunk: string): string[][];
23
+ /**
24
+ * Flushes the final row of a file with no trailing newline.
25
+ * @throws never — an unterminated quote is reported by `hasUnterminatedQuote()` so the
26
+ * caller can record it as a failed row rather than losing the whole chunk.
27
+ */
28
+ end(): string[][];
29
+ /** True when `end()` was reached inside an open quoted field — the file is truncated. */
30
+ hasUnterminatedQuote(): boolean;
31
+ private pushField;
32
+ private completeRow;
33
+ }
34
+ //# sourceMappingURL=csv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv.d.ts","sourceRoot":"","sources":["../../src/transfer/csv.ts"],"names":[],"mappings":"AAcA,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAIvE;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAE5E;AAID;;;;;;;GAOG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,qBAAqB,CAAQ;IACrC,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,aAAa,CAAQ;IAE7B,2DAA2D;IAC3D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE;IA6D/B;;;;OAIG;IACH,GAAG,IAAI,MAAM,EAAE,EAAE;IAMjB,yFAAyF;IACzF,oBAAoB,IAAI,OAAO;IAI/B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,WAAW;CAWpB"}
@@ -0,0 +1,135 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ /**
4
+ * RFC 4180 CSV codec. Hand-written rather than pulled from npm: `packages/core` ships to a
5
+ * Worker bundle and the two rules that matter here (quote-wrap on delimiter/quote/newline,
6
+ * double the inner quote) are four lines. A dependency would cost more than it saves.
7
+ */
8
+ const DELIMITER = ',';
9
+ const ROW_TERMINATOR = '\r\n';
10
+ const QUOTE = '"';
11
+ const MUST_QUOTE = /[",\r\n]/;
12
+ /** Encodes one cell. `null`/`undefined` become an empty, unquoted field. */
13
+ export function encodeCsvValue(value) {
14
+ if (value === null || value === undefined)
15
+ return '';
16
+ if (!MUST_QUOTE.test(value))
17
+ return value;
18
+ return `${QUOTE}${value.replaceAll(QUOTE, `${QUOTE}${QUOTE}`)}${QUOTE}`;
19
+ }
20
+ /** Encodes one row, CRLF terminator included (RFC 4180 §2.1). */
21
+ export function encodeCsvRow(cells) {
22
+ return cells.map(encodeCsvValue).join(DELIMITER) + ROW_TERMINATOR;
23
+ }
24
+ const BYTE_ORDER_MARK = '\uFEFF';
25
+ /**
26
+ * Splits an arbitrarily-chunked CSV text stream into rows of cells.
27
+ *
28
+ * Stateful and quote-aware: a newline inside a quoted field is DATA, not a row break, so
29
+ * a naive `split('\n')` corrupts any export containing a multi-line text branch — which
30
+ * the export side of this same module is perfectly capable of producing. The parser
31
+ * therefore carries its in-quotes state across chunk boundaries as well as across lines.
32
+ */
33
+ export class CsvRowReader {
34
+ cells = [];
35
+ field = '';
36
+ inQuotes = false;
37
+ quoteJustClosed = false;
38
+ pendingCarriageReturn = false;
39
+ rowHasContent = false;
40
+ sawFirstChunk = false;
41
+ /** Feeds a chunk and returns every row completed by it. */
42
+ push(chunk) {
43
+ let text = chunk;
44
+ if (!this.sawFirstChunk) {
45
+ this.sawFirstChunk = true;
46
+ if (text.startsWith(BYTE_ORDER_MARK))
47
+ text = text.slice(BYTE_ORDER_MARK.length);
48
+ }
49
+ const rows = [];
50
+ for (const char of text) {
51
+ if (this.pendingCarriageReturn) {
52
+ this.pendingCarriageReturn = false;
53
+ // A lone CR terminates the row too; a CRLF consumes the LF here.
54
+ const row = this.completeRow();
55
+ if (row)
56
+ rows.push(row);
57
+ if (char === '\n')
58
+ continue;
59
+ }
60
+ if (this.inQuotes) {
61
+ if (this.quoteJustClosed) {
62
+ this.quoteJustClosed = false;
63
+ if (char === QUOTE) {
64
+ this.field += QUOTE; // an escaped quote inside a quoted field
65
+ continue;
66
+ }
67
+ this.inQuotes = false;
68
+ // fall through: this char is a normal unquoted char
69
+ }
70
+ else if (char === QUOTE) {
71
+ this.quoteJustClosed = true;
72
+ continue;
73
+ }
74
+ else {
75
+ this.field += char;
76
+ continue;
77
+ }
78
+ }
79
+ if (char === QUOTE) {
80
+ this.inQuotes = true;
81
+ this.rowHasContent = true;
82
+ continue;
83
+ }
84
+ if (char === DELIMITER) {
85
+ this.pushField();
86
+ continue;
87
+ }
88
+ if (char === '\r') {
89
+ this.pendingCarriageReturn = true;
90
+ continue;
91
+ }
92
+ if (char === '\n') {
93
+ const row = this.completeRow();
94
+ if (row)
95
+ rows.push(row);
96
+ continue;
97
+ }
98
+ this.field += char;
99
+ this.rowHasContent = true;
100
+ }
101
+ return rows;
102
+ }
103
+ /**
104
+ * Flushes the final row of a file with no trailing newline.
105
+ * @throws never — an unterminated quote is reported by `hasUnterminatedQuote()` so the
106
+ * caller can record it as a failed row rather than losing the whole chunk.
107
+ */
108
+ end() {
109
+ if (this.pendingCarriageReturn)
110
+ this.pendingCarriageReturn = false;
111
+ const row = this.completeRow();
112
+ return row ? [row] : [];
113
+ }
114
+ /** True when `end()` was reached inside an open quoted field — the file is truncated. */
115
+ hasUnterminatedQuote() {
116
+ return this.inQuotes && !this.quoteJustClosed;
117
+ }
118
+ pushField() {
119
+ this.cells.push(this.field);
120
+ this.field = '';
121
+ this.rowHasContent = true;
122
+ }
123
+ completeRow() {
124
+ if (!this.rowHasContent && this.cells.length === 0 && this.field === '')
125
+ return null;
126
+ this.cells.push(this.field);
127
+ const row = this.cells;
128
+ this.cells = [];
129
+ this.field = '';
130
+ this.inQuotes = false;
131
+ this.quoteJustClosed = false;
132
+ this.rowHasContent = false;
133
+ return row;
134
+ }
135
+ }
@@ -0,0 +1,13 @@
1
+ import type { Branch, Seed } from '../engine/types.js';
2
+ import type { FormatCompatibility, TransferFormat } from './transfer.types.js';
3
+ /** Every branch of `seed` that makes it non-flat, in declaration order. Empty when flat. */
4
+ export declare function nonFlatBranches(seed: Seed): Branch[];
5
+ /** A seed is flat when every branch maps to exactly one scalar column. */
6
+ export declare function isFlatSeed(seed: Seed): boolean;
7
+ /**
8
+ * The single authority on "may this seed be transferred in this format?", shared by the
9
+ * export endpoint and the import endpoint so the two can never disagree.
10
+ * NDJSON is universal; CSV requires a flat seed.
11
+ */
12
+ export declare function checkFormatCompatibility(seed: Seed, format: TransferFormat): FormatCompatibility;
13
+ //# sourceMappingURL=flat-seed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flat-seed.d.ts","sourceRoot":"","sources":["../../src/transfer/flat-seed.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAc,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAqB9E,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAEpD;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE9C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,cAAc,GACrB,mBAAmB,CAWrB"}
@@ -0,0 +1,45 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ /**
4
+ * Branch types whose value is a collection or a nested document, never a scalar cell.
5
+ * A CSV cell cannot carry them without inventing a flattening convention that the
6
+ * importer would then have to guess at — which the brief rules out (§5).
7
+ */
8
+ const NON_FLAT_BRANCH_TYPES = new Set([
9
+ 'relation',
10
+ 'repeater',
11
+ 'tags',
12
+ 'json',
13
+ ]);
14
+ /** True for a branch that cannot be represented as a single scalar CSV cell. */
15
+ function isNonFlat(branch) {
16
+ // A `file` branch is a single URL string — flat — unless it is an asset list.
17
+ if (branch.type === 'file')
18
+ return branch.multiple === true;
19
+ return NON_FLAT_BRANCH_TYPES.has(branch.type);
20
+ }
21
+ /** Every branch of `seed` that makes it non-flat, in declaration order. Empty when flat. */
22
+ export function nonFlatBranches(seed) {
23
+ return seed.branches.filter(isNonFlat);
24
+ }
25
+ /** A seed is flat when every branch maps to exactly one scalar column. */
26
+ export function isFlatSeed(seed) {
27
+ return nonFlatBranches(seed).length === 0;
28
+ }
29
+ /**
30
+ * The single authority on "may this seed be transferred in this format?", shared by the
31
+ * export endpoint and the import endpoint so the two can never disagree.
32
+ * NDJSON is universal; CSV requires a flat seed.
33
+ */
34
+ export function checkFormatCompatibility(seed, format) {
35
+ if (format === 'ndjson')
36
+ return { compatible: true };
37
+ const offenders = nonFlatBranches(seed);
38
+ if (offenders.length === 0)
39
+ return { compatible: true };
40
+ return {
41
+ compatible: false,
42
+ code: 'csv_requires_flat_seed',
43
+ offendingBranches: offenders.map((branch) => ({ alias: branch.alias, type: branch.type })),
44
+ };
45
+ }
@@ -0,0 +1,7 @@
1
+ export * from './transfer.types.js';
2
+ export * from './transfer.constants.js';
3
+ export * from './flat-seed.js';
4
+ export * from './ndjson.js';
5
+ export * from './csv.js';
6
+ export * from './row-mapping.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transfer/index.ts"],"names":[],"mappings":"AAGA,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,kBAAkB,CAAA"}
@@ -0,0 +1,8 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ export * from './transfer.types.js';
4
+ export * from './transfer.constants.js';
5
+ export * from './flat-seed.js';
6
+ export * from './ndjson.js';
7
+ export * from './csv.js';
8
+ export * from './row-mapping.js';
@@ -0,0 +1,25 @@
1
+ import type { LineParseResult, TransferRecord } from './transfer.types.js';
2
+ /** Serialises one record as an NDJSON line, terminator included. */
3
+ export declare function encodeNdjsonLine(record: TransferRecord): string;
4
+ /**
5
+ * Decodes one NDJSON line. Never throws: a malformed line is a failed row in the job
6
+ * report, not an aborted import (brief §2 — best-effort, not atomic).
7
+ */
8
+ export declare function parseNdjsonLine(line: string): LineParseResult;
9
+ /**
10
+ * Splits an arbitrarily-chunked text stream into complete lines, holding the trailing
11
+ * partial line until the next chunk completes it. Stateful by necessity: a single
12
+ * R2 read boundary may fall in the middle of a record, and an import that lost that
13
+ * record would report a phantom failed row.
14
+ *
15
+ * Blank lines are dropped — a trailing newline at end of file is not a record.
16
+ */
17
+ export declare class LineReader {
18
+ private buffer;
19
+ private sawFirstChunk;
20
+ /** Feeds a chunk and returns every line completed by it. */
21
+ push(chunk: string): string[];
22
+ /** Flushes the trailing line of a file that does not end in a newline. */
23
+ end(): string[];
24
+ }
25
+ //# sourceMappingURL=ndjson.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ndjson.d.ts","sourceRoot":"","sources":["../../src/transfer/ndjson.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAE1E,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAE/D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAiB7D;AAID;;;;;;;GAOG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,aAAa,CAAQ;IAE7B,4DAA4D;IAC5D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAa7B,0EAA0E;IAC1E,GAAG,IAAI,MAAM,EAAE;CAKhB"}
@@ -0,0 +1,62 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ /** Serialises one record as an NDJSON line, terminator included. */
4
+ export function encodeNdjsonLine(record) {
5
+ return `${JSON.stringify(record)}\n`;
6
+ }
7
+ /**
8
+ * Decodes one NDJSON line. Never throws: a malformed line is a failed row in the job
9
+ * report, not an aborted import (brief §2 — best-effort, not atomic).
10
+ */
11
+ export function parseNdjsonLine(line) {
12
+ let parsed;
13
+ try {
14
+ parsed = JSON.parse(line);
15
+ }
16
+ catch (error) {
17
+ return {
18
+ ok: false,
19
+ code: 'invalid_json',
20
+ message: error instanceof Error ? error.message : 'Malformed JSON',
21
+ };
22
+ }
23
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
24
+ return { ok: false, code: 'not_an_object', message: 'Line is not a JSON object' };
25
+ }
26
+ return { ok: true, record: parsed };
27
+ }
28
+ const BYTE_ORDER_MARK = '\uFEFF';
29
+ /**
30
+ * Splits an arbitrarily-chunked text stream into complete lines, holding the trailing
31
+ * partial line until the next chunk completes it. Stateful by necessity: a single
32
+ * R2 read boundary may fall in the middle of a record, and an import that lost that
33
+ * record would report a phantom failed row.
34
+ *
35
+ * Blank lines are dropped — a trailing newline at end of file is not a record.
36
+ */
37
+ export class LineReader {
38
+ buffer = '';
39
+ sawFirstChunk = false;
40
+ /** Feeds a chunk and returns every line completed by it. */
41
+ push(chunk) {
42
+ let text = chunk;
43
+ if (!this.sawFirstChunk) {
44
+ this.sawFirstChunk = true;
45
+ if (text.startsWith(BYTE_ORDER_MARK))
46
+ text = text.slice(BYTE_ORDER_MARK.length);
47
+ }
48
+ this.buffer += text;
49
+ const parts = this.buffer.split('\n');
50
+ this.buffer = parts.pop() ?? '';
51
+ return parts.map(stripCarriageReturn).filter((line) => line.length > 0);
52
+ }
53
+ /** Flushes the trailing line of a file that does not end in a newline. */
54
+ end() {
55
+ const remainder = stripCarriageReturn(this.buffer);
56
+ this.buffer = '';
57
+ return remainder.length > 0 ? [remainder] : [];
58
+ }
59
+ }
60
+ function stripCarriageReturn(line) {
61
+ return line.endsWith('\r') ? line.slice(0, -1) : line;
62
+ }
@@ -0,0 +1,36 @@
1
+ import type { Seed } from '../engine/types.js';
2
+ import type { ImportPayload, LineParseResult, TransferRecord } from './transfer.types.js';
3
+ /**
4
+ * System columns exported for every seed, in this order, ahead of the branch columns.
5
+ * `deleted_at` is deliberately absent: a trashed row is not exportable content, and the
6
+ * repository's default `trashed: 'active'` mode never hands one to the producer anyway.
7
+ */
8
+ export declare const EXPORT_SYSTEM_COLUMNS: readonly ["id", "slug", "status", "created_at", "updated_at"];
9
+ /**
10
+ * The ordered column projection for exporting `seed`: system columns, then one column per
11
+ * scalar branch in declaration order. Non-flat branches are omitted — this projection is
12
+ * only ever used for CSV, and `checkFormatCompatibility` has already refused a seed that
13
+ * has any. NDJSON export emits the record whole and does not call this.
14
+ */
15
+ export declare function exportColumns(seed: Seed): string[];
16
+ /**
17
+ * Projects an API-shaped record onto `columns` as CSV cells.
18
+ * `null`/`undefined` become an empty field; booleans become `true`/`false`; everything else
19
+ * is stringified. The record is expected to have already passed through `dbToApi`, so a
20
+ * `date` branch arrives as a number and is written as its unix-seconds integer.
21
+ */
22
+ export declare function toCsvCells(record: TransferRecord, columns: string[]): Array<string | null>;
23
+ /**
24
+ * Rebuilds a record from a CSV row. An empty cell is treated as ABSENT, not as null:
25
+ * CSV cannot distinguish the two, and omitting the key lets the engine's own
26
+ * required-field validation produce the error instead of this module guessing.
27
+ */
28
+ export declare function fromCsvCells(columns: string[], cells: string[]): LineParseResult;
29
+ /**
30
+ * Splits a decoded record into the shape `ContentRepository.create` consumes, dropping the
31
+ * engine-owned columns. Returns `data` WITHOUT `slug`/`status`, mirroring
32
+ * `apps/api/src/features/content/handlers/create.ts:68-70`, so the import consumer can feed
33
+ * `data` straight to `validateAndSanitizeSeedPayload` without re-filtering.
34
+ */
35
+ export declare function toImportPayload(record: TransferRecord): ImportPayload;
36
+ //# sourceMappingURL=row-mapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-mapping.d.ts","sourceRoot":"","sources":["../../src/transfer/row-mapping.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAE9C,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,+DAAgE,CAAA;AAclG;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAMlD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAO1F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,CAgBhF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,aAAa,CAYrE"}
@@ -0,0 +1,90 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ import { nonFlatBranches } from './flat-seed.js';
4
+ /**
5
+ * System columns exported for every seed, in this order, ahead of the branch columns.
6
+ * `deleted_at` is deliberately absent: a trashed row is not exportable content, and the
7
+ * repository's default `trashed: 'active'` mode never hands one to the producer anyway.
8
+ */
9
+ export const EXPORT_SYSTEM_COLUMNS = ['id', 'slug', 'status', 'created_at', 'updated_at'];
10
+ /**
11
+ * Columns the importer must never accept from a file: the engine owns them.
12
+ * `id` is minted by `idGenerator.uuid()`, the timestamps by SQLite defaults. Accepting an
13
+ * `id` from a file would also turn insert-only import (brief §2) into a covert upsert.
14
+ */
15
+ const IMPORT_REJECTED_COLUMNS = new Set([
16
+ 'id',
17
+ 'created_at',
18
+ 'updated_at',
19
+ 'deleted_at',
20
+ ]);
21
+ /**
22
+ * The ordered column projection for exporting `seed`: system columns, then one column per
23
+ * scalar branch in declaration order. Non-flat branches are omitted — this projection is
24
+ * only ever used for CSV, and `checkFormatCompatibility` has already refused a seed that
25
+ * has any. NDJSON export emits the record whole and does not call this.
26
+ */
27
+ export function exportColumns(seed) {
28
+ const excluded = new Set(nonFlatBranches(seed).map((branch) => branch.alias));
29
+ return [
30
+ ...EXPORT_SYSTEM_COLUMNS,
31
+ ...seed.branches.map((branch) => branch.alias).filter((alias) => !excluded.has(alias)),
32
+ ];
33
+ }
34
+ /**
35
+ * Projects an API-shaped record onto `columns` as CSV cells.
36
+ * `null`/`undefined` become an empty field; booleans become `true`/`false`; everything else
37
+ * is stringified. The record is expected to have already passed through `dbToApi`, so a
38
+ * `date` branch arrives as a number and is written as its unix-seconds integer.
39
+ */
40
+ export function toCsvCells(record, columns) {
41
+ return columns.map((column) => {
42
+ const value = record[column];
43
+ if (value === null || value === undefined)
44
+ return null;
45
+ if (typeof value === 'boolean')
46
+ return value ? 'true' : 'false';
47
+ return String(value);
48
+ });
49
+ }
50
+ /**
51
+ * Rebuilds a record from a CSV row. An empty cell is treated as ABSENT, not as null:
52
+ * CSV cannot distinguish the two, and omitting the key lets the engine's own
53
+ * required-field validation produce the error instead of this module guessing.
54
+ */
55
+ export function fromCsvCells(columns, cells) {
56
+ if (cells.length !== columns.length) {
57
+ return {
58
+ ok: false,
59
+ code: 'column_count_mismatch',
60
+ message: `Expected ${columns.length} columns, received ${cells.length}`,
61
+ };
62
+ }
63
+ const record = {};
64
+ for (const [index, column] of columns.entries()) {
65
+ const cell = cells[index] ?? '';
66
+ if (cell === '')
67
+ continue;
68
+ record[column] = cell;
69
+ }
70
+ return { ok: true, record };
71
+ }
72
+ /**
73
+ * Splits a decoded record into the shape `ContentRepository.create` consumes, dropping the
74
+ * engine-owned columns. Returns `data` WITHOUT `slug`/`status`, mirroring
75
+ * `apps/api/src/features/content/handlers/create.ts:68-70`, so the import consumer can feed
76
+ * `data` straight to `validateAndSanitizeSeedPayload` without re-filtering.
77
+ */
78
+ export function toImportPayload(record) {
79
+ const data = {};
80
+ for (const [key, value] of Object.entries(record)) {
81
+ if (IMPORT_REJECTED_COLUMNS.has(key))
82
+ continue;
83
+ if (key === 'slug' || key === 'status')
84
+ continue;
85
+ data[key] = value;
86
+ }
87
+ const slug = typeof record['slug'] === 'string' && record['slug'] !== '' ? record['slug'] : undefined;
88
+ const status = typeof record['status'] === 'string' && record['status'] !== '' ? record['status'] : undefined;
89
+ return { ...(slug ? { slug } : {}), ...(status ? { status } : {}), data };
90
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Hard cap on rows a single synchronous export may stream (brief §2). Past this the
3
+ * endpoint answers 413 rather than opening a stream that the edge may truncate mid-file.
4
+ * Overridable per deployment by the API layer (S2) — this is the default, not the law.
5
+ */
6
+ export declare const DEFAULT_EXPORT_MAX_ROWS = 50000;
7
+ /** Page size for the export producer's findMany loop. Never materialise the full set. */
8
+ export declare const DEFAULT_EXPORT_PAGE_SIZE = 500;
9
+ /**
10
+ * Rows an import consumer processes per queue invocation before persisting its offset
11
+ * and re-enqueuing (brief §2). Sized well under the Workers CPU budget so a chunk that
12
+ * retries repeats at most this many already-inserted rows.
13
+ */
14
+ export declare const DEFAULT_IMPORT_CHUNK_ROWS = 500;
15
+ /**
16
+ * Upper bound on per-row errors retained in a job report (brief §4). Beyond this only
17
+ * the aggregate failure count grows, so one pathological file cannot unbound the row.
18
+ */
19
+ export declare const MAX_JOB_ERROR_SAMPLES = 100;
20
+ //# sourceMappingURL=transfer.constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer.constants.d.ts","sourceRoot":"","sources":["../../src/transfer/transfer.constants.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,QAAS,CAAA;AAE7C,yFAAyF;AACzF,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAE3C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAA"}
@@ -0,0 +1,21 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ /**
4
+ * Hard cap on rows a single synchronous export may stream (brief §2). Past this the
5
+ * endpoint answers 413 rather than opening a stream that the edge may truncate mid-file.
6
+ * Overridable per deployment by the API layer (S2) — this is the default, not the law.
7
+ */
8
+ export const DEFAULT_EXPORT_MAX_ROWS = 50_000;
9
+ /** Page size for the export producer's findMany loop. Never materialise the full set. */
10
+ export const DEFAULT_EXPORT_PAGE_SIZE = 500;
11
+ /**
12
+ * Rows an import consumer processes per queue invocation before persisting its offset
13
+ * and re-enqueuing (brief §2). Sized well under the Workers CPU budget so a chunk that
14
+ * retries repeats at most this many already-inserted rows.
15
+ */
16
+ export const DEFAULT_IMPORT_CHUNK_ROWS = 500;
17
+ /**
18
+ * Upper bound on per-row errors retained in a job report (brief §4). Beyond this only
19
+ * the aggregate failure count grows, so one pathological file cannot unbound the row.
20
+ */
21
+ export const MAX_JOB_ERROR_SAMPLES = 100;
@@ -0,0 +1,46 @@
1
+ import type { Branch } from '../engine/types.js';
2
+ /** Wire formats supported for bulk transfer. NDJSON is universal; CSV is flat-only. */
3
+ export type TransferFormat = 'csv' | 'ndjson';
4
+ export declare const TRANSFER_FORMATS: readonly ["csv", "ndjson"];
5
+ export declare function isTransferFormat(value: unknown): value is TransferFormat;
6
+ /**
7
+ * Outcome of checking a requested format against a seed's shape.
8
+ * `offendingBranches` is non-empty only on the incompatible branch, and exists so the
9
+ * caller can name the exact fields in its 400 response instead of a generic message.
10
+ */
11
+ export type FormatCompatibility = {
12
+ compatible: true;
13
+ } | {
14
+ compatible: false;
15
+ code: 'csv_requires_flat_seed';
16
+ offendingBranches: Array<{
17
+ alias: string;
18
+ type: Branch['type'];
19
+ }>;
20
+ };
21
+ /** A decoded wire row, keyed by branch alias / system column name. */
22
+ export type TransferRecord = Record<string, unknown>;
23
+ /**
24
+ * Per-line decode outcome. Import is best-effort (brief §2), so a bad line is a VALUE,
25
+ * never a thrown error — the consumer must record it in the job report and keep going.
26
+ */
27
+ export type LineParseResult = {
28
+ ok: true;
29
+ record: TransferRecord;
30
+ } | {
31
+ ok: false;
32
+ code: LineParseErrorCode;
33
+ message: string;
34
+ };
35
+ export type LineParseErrorCode = 'invalid_json' | 'not_an_object' | 'column_count_mismatch' | 'unterminated_quote';
36
+ /**
37
+ * A decoded row split into the three arguments `ContentRepository.create` takes.
38
+ * `slug` and `status` are optional: the caller supplies its own defaults
39
+ * (`create.ts` slugifies the display-name branch and defaults status to 'draft').
40
+ */
41
+ export interface ImportPayload {
42
+ slug?: string;
43
+ status?: string;
44
+ data: TransferRecord;
45
+ }
46
+ //# sourceMappingURL=transfer.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer.types.d.ts","sourceRoot":"","sources":["../../src/transfer/transfer.types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAEhD,uFAAuF;AACvF,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,CAAA;AAE7C,eAAO,MAAM,gBAAgB,4BAAiE,CAAA;AAE9F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAExE;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,UAAU,EAAE,IAAI,CAAA;CAAE,GACpB;IACE,UAAU,EAAE,KAAK,CAAA;IACjB,IAAI,EAAE,wBAAwB,CAAA;IAC9B,iBAAiB,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;KAAE,CAAC,CAAA;CAClE,CAAA;AAEL,sEAAsE;AACtE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEpD;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5D,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,eAAe,GACf,uBAAuB,GACvB,oBAAoB,CAAA;AAExB;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,cAAc,CAAA;CACrB"}
@@ -0,0 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ export const TRANSFER_FORMATS = ['csv', 'ndjson'];
4
+ export function isTransferFormat(value) {
5
+ return typeof value === 'string' && TRANSFER_FORMATS.includes(value);
6
+ }