gazetta 0.6.0 → 0.7.0

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 (340) hide show
  1. package/admin-dist/assets/index-BO9-CXmW.css +1 -0
  2. package/admin-dist/assets/index-Ufu8zZH_.js +668 -0
  3. package/admin-dist/index.html +2 -2
  4. package/dist/admin-api/error-response.d.ts +21 -0
  5. package/dist/admin-api/error-response.d.ts.map +1 -0
  6. package/dist/admin-api/error-response.js +12 -0
  7. package/dist/admin-api/error-response.js.map +1 -0
  8. package/dist/admin-api/index.d.ts +0 -2
  9. package/dist/admin-api/index.d.ts.map +1 -1
  10. package/dist/admin-api/index.js +4 -24
  11. package/dist/admin-api/index.js.map +1 -1
  12. package/dist/admin-api/routes/assets.d.ts +16 -0
  13. package/dist/admin-api/routes/assets.d.ts.map +1 -0
  14. package/dist/admin-api/routes/assets.js +433 -0
  15. package/dist/admin-api/routes/assets.js.map +1 -0
  16. package/dist/admin-api/routes/fragments.d.ts.map +1 -1
  17. package/dist/admin-api/routes/fragments.js +30 -4
  18. package/dist/admin-api/routes/fragments.js.map +1 -1
  19. package/dist/admin-api/routes/pages.d.ts.map +1 -1
  20. package/dist/admin-api/routes/pages.js +37 -4
  21. package/dist/admin-api/routes/pages.js.map +1 -1
  22. package/dist/admin-api/routes/publish.d.ts.map +1 -1
  23. package/dist/admin-api/routes/publish.js +68 -35
  24. package/dist/admin-api/routes/publish.js.map +1 -1
  25. package/dist/admin-api/schemas/assets.d.ts +48 -0
  26. package/dist/admin-api/schemas/assets.d.ts.map +1 -0
  27. package/dist/admin-api/schemas/assets.js +44 -0
  28. package/dist/admin-api/schemas/assets.js.map +1 -0
  29. package/dist/admin-api/schemas/index.d.ts +2 -0
  30. package/dist/admin-api/schemas/index.d.ts.map +1 -1
  31. package/dist/admin-api/schemas/index.js +2 -0
  32. package/dist/admin-api/schemas/index.js.map +1 -1
  33. package/dist/admin-api/source-context.d.ts +0 -7
  34. package/dist/admin-api/source-context.d.ts.map +1 -1
  35. package/dist/admin-api/source-context.js +0 -3
  36. package/dist/admin-api/source-context.js.map +1 -1
  37. package/dist/assets/analyze-audio.d.ts +3 -0
  38. package/dist/assets/analyze-audio.d.ts.map +1 -0
  39. package/dist/assets/analyze-audio.js +80 -0
  40. package/dist/assets/analyze-audio.js.map +1 -0
  41. package/dist/assets/analyze-image.d.ts +19 -0
  42. package/dist/assets/analyze-image.d.ts.map +1 -0
  43. package/dist/assets/analyze-image.js +123 -0
  44. package/dist/assets/analyze-image.js.map +1 -0
  45. package/dist/assets/analyze.d.ts +94 -0
  46. package/dist/assets/analyze.d.ts.map +1 -0
  47. package/dist/assets/analyze.js +45 -0
  48. package/dist/assets/analyze.js.map +1 -0
  49. package/dist/assets/asset-deps.d.ts +30 -0
  50. package/dist/assets/asset-deps.d.ts.map +1 -0
  51. package/dist/assets/asset-deps.js +42 -0
  52. package/dist/assets/asset-deps.js.map +1 -0
  53. package/dist/assets/asset-paths.d.ts +155 -0
  54. package/dist/assets/asset-paths.d.ts.map +1 -0
  55. package/dist/assets/asset-paths.js +197 -0
  56. package/dist/assets/asset-paths.js.map +1 -0
  57. package/dist/assets/delete.d.ts +75 -0
  58. package/dist/assets/delete.d.ts.map +1 -0
  59. package/dist/assets/delete.js +82 -0
  60. package/dist/assets/delete.js.map +1 -0
  61. package/dist/assets/errors.d.ts +241 -0
  62. package/dist/assets/errors.d.ts.map +1 -0
  63. package/dist/assets/errors.js +300 -0
  64. package/dist/assets/errors.js.map +1 -0
  65. package/dist/assets/find-refs.d.ts +37 -0
  66. package/dist/assets/find-refs.d.ts.map +1 -0
  67. package/dist/assets/find-refs.js +35 -0
  68. package/dist/assets/find-refs.js.map +1 -0
  69. package/dist/assets/hash.d.ts +13 -0
  70. package/dist/assets/hash.d.ts.map +1 -0
  71. package/dist/assets/hash.js +43 -0
  72. package/dist/assets/hash.js.map +1 -0
  73. package/dist/assets/image-metadata.d.ts +11 -0
  74. package/dist/assets/image-metadata.d.ts.map +1 -0
  75. package/dist/assets/image-metadata.js +31 -0
  76. package/dist/assets/image-metadata.js.map +1 -0
  77. package/dist/assets/ingest-locale.d.ts +86 -0
  78. package/dist/assets/ingest-locale.d.ts.map +1 -0
  79. package/dist/assets/ingest-locale.js +209 -0
  80. package/dist/assets/ingest-locale.js.map +1 -0
  81. package/dist/assets/ingest.d.ts +96 -0
  82. package/dist/assets/ingest.d.ts.map +1 -0
  83. package/dist/assets/ingest.js +308 -0
  84. package/dist/assets/ingest.js.map +1 -0
  85. package/dist/assets/kind-compat.d.ts +34 -0
  86. package/dist/assets/kind-compat.d.ts.map +1 -0
  87. package/dist/assets/kind-compat.js +33 -0
  88. package/dist/assets/kind-compat.js.map +1 -0
  89. package/dist/assets/list.d.ts +46 -0
  90. package/dist/assets/list.d.ts.map +1 -0
  91. package/dist/assets/list.js +102 -0
  92. package/dist/assets/list.js.map +1 -0
  93. package/dist/assets/manifest-default.d.ts +56 -0
  94. package/dist/assets/manifest-default.d.ts.map +1 -0
  95. package/dist/assets/manifest-default.js +120 -0
  96. package/dist/assets/manifest-default.js.map +1 -0
  97. package/dist/assets/manifest-filename.d.ts +52 -0
  98. package/dist/assets/manifest-filename.d.ts.map +1 -0
  99. package/dist/assets/manifest-filename.js +104 -0
  100. package/dist/assets/manifest-filename.js.map +1 -0
  101. package/dist/assets/manifest-locale.d.ts +60 -0
  102. package/dist/assets/manifest-locale.d.ts.map +1 -0
  103. package/dist/assets/manifest-locale.js +206 -0
  104. package/dist/assets/manifest-locale.js.map +1 -0
  105. package/dist/assets/manifest-merge.d.ts +66 -0
  106. package/dist/assets/manifest-merge.d.ts.map +1 -0
  107. package/dist/assets/manifest-merge.js +82 -0
  108. package/dist/assets/manifest-merge.js.map +1 -0
  109. package/dist/assets/manifest.d.ts +83 -0
  110. package/dist/assets/manifest.d.ts.map +1 -0
  111. package/dist/assets/manifest.js +93 -0
  112. package/dist/assets/manifest.js.map +1 -0
  113. package/dist/assets/mime-sniff.d.ts +18 -0
  114. package/dist/assets/mime-sniff.d.ts.map +1 -0
  115. package/dist/assets/mime-sniff.js +84 -0
  116. package/dist/assets/mime-sniff.js.map +1 -0
  117. package/dist/assets/preprocess-svg.d.ts +3 -0
  118. package/dist/assets/preprocess-svg.d.ts.map +1 -0
  119. package/dist/assets/preprocess-svg.js +49 -0
  120. package/dist/assets/preprocess-svg.js.map +1 -0
  121. package/dist/assets/preprocess.d.ts +62 -0
  122. package/dist/assets/preprocess.d.ts.map +1 -0
  123. package/dist/assets/preprocess.js +86 -0
  124. package/dist/assets/preprocess.js.map +1 -0
  125. package/dist/assets/publish-plan.d.ts +41 -0
  126. package/dist/assets/publish-plan.d.ts.map +1 -0
  127. package/dist/assets/publish-plan.js +49 -0
  128. package/dist/assets/publish-plan.js.map +1 -0
  129. package/dist/assets/publish.d.ts +33 -0
  130. package/dist/assets/publish.d.ts.map +1 -0
  131. package/dist/assets/publish.js +81 -0
  132. package/dist/assets/publish.js.map +1 -0
  133. package/dist/assets/refs.d.ts +37 -0
  134. package/dist/assets/refs.d.ts.map +1 -0
  135. package/dist/assets/refs.js +33 -0
  136. package/dist/assets/refs.js.map +1 -0
  137. package/dist/assets/remove-override.d.ts +42 -0
  138. package/dist/assets/remove-override.d.ts.map +1 -0
  139. package/dist/assets/remove-override.js +53 -0
  140. package/dist/assets/remove-override.js.map +1 -0
  141. package/dist/assets/rename.d.ts +43 -0
  142. package/dist/assets/rename.d.ts.map +1 -0
  143. package/dist/assets/rename.js +271 -0
  144. package/dist/assets/rename.js.map +1 -0
  145. package/dist/assets/replace.d.ts +37 -0
  146. package/dist/assets/replace.d.ts.map +1 -0
  147. package/dist/assets/replace.js +195 -0
  148. package/dist/assets/replace.js.map +1 -0
  149. package/dist/assets/resolve.d.ts +141 -0
  150. package/dist/assets/resolve.d.ts.map +1 -0
  151. package/dist/assets/resolve.js +381 -0
  152. package/dist/assets/resolve.js.map +1 -0
  153. package/dist/assets/rewrite-manifest-asset-ref.d.ts +44 -0
  154. package/dist/assets/rewrite-manifest-asset-ref.d.ts.map +1 -0
  155. package/dist/assets/rewrite-manifest-asset-ref.js +51 -0
  156. package/dist/assets/rewrite-manifest-asset-ref.js.map +1 -0
  157. package/dist/assets/scan-manifest-for-asset.d.ts +63 -0
  158. package/dist/assets/scan-manifest-for-asset.d.ts.map +1 -0
  159. package/dist/assets/scan-manifest-for-asset.js +105 -0
  160. package/dist/assets/scan-manifest-for-asset.js.map +1 -0
  161. package/dist/assets/serve-route.d.ts +45 -0
  162. package/dist/assets/serve-route.d.ts.map +1 -0
  163. package/dist/assets/serve-route.js +123 -0
  164. package/dist/assets/serve-route.js.map +1 -0
  165. package/dist/assets/svg-sanitize.d.ts +38 -0
  166. package/dist/assets/svg-sanitize.d.ts.map +1 -0
  167. package/dist/assets/svg-sanitize.js +209 -0
  168. package/dist/assets/svg-sanitize.js.map +1 -0
  169. package/dist/assets/update-metadata.d.ts +61 -0
  170. package/dist/assets/update-metadata.d.ts.map +1 -0
  171. package/dist/assets/update-metadata.js +82 -0
  172. package/dist/assets/update-metadata.js.map +1 -0
  173. package/dist/assets/url.d.ts +82 -0
  174. package/dist/assets/url.d.ts.map +1 -0
  175. package/dist/assets/url.js +103 -0
  176. package/dist/assets/url.js.map +1 -0
  177. package/dist/assets/validate.d.ts +74 -0
  178. package/dist/assets/validate.d.ts.map +1 -0
  179. package/dist/assets/validate.js +136 -0
  180. package/dist/assets/validate.js.map +1 -0
  181. package/dist/assets/variants.d.ts +23 -0
  182. package/dist/assets/variants.d.ts.map +1 -0
  183. package/dist/assets/variants.js +74 -0
  184. package/dist/assets/variants.js.map +1 -0
  185. package/dist/cli/assets-cli.d.ts +58 -0
  186. package/dist/cli/assets-cli.d.ts.map +1 -0
  187. package/dist/cli/assets-cli.js +233 -0
  188. package/dist/cli/assets-cli.js.map +1 -0
  189. package/dist/cli/assets-display.d.ts +112 -0
  190. package/dist/cli/assets-display.d.ts.map +1 -0
  191. package/dist/cli/assets-display.js +106 -0
  192. package/dist/cli/assets-display.js.map +1 -0
  193. package/dist/cli/bootstrap.d.ts +0 -2
  194. package/dist/cli/bootstrap.d.ts.map +1 -1
  195. package/dist/cli/bootstrap.js +0 -1
  196. package/dist/cli/bootstrap.js.map +1 -1
  197. package/dist/cli/index.js +64 -18
  198. package/dist/cli/index.js.map +1 -1
  199. package/dist/compare.d.ts.map +1 -1
  200. package/dist/compare.js +15 -12
  201. package/dist/compare.js.map +1 -1
  202. package/dist/dep-sidecars.d.ts +127 -0
  203. package/dist/dep-sidecars.d.ts.map +1 -0
  204. package/dist/dep-sidecars.js +122 -0
  205. package/dist/dep-sidecars.js.map +1 -0
  206. package/dist/editor/AssetEmbeddedWidget.d.ts +3 -0
  207. package/dist/editor/AssetEmbeddedWidget.d.ts.map +1 -0
  208. package/dist/editor/AssetEmbeddedWidget.js +146 -0
  209. package/dist/editor/AssetEmbeddedWidget.js.map +1 -0
  210. package/dist/editor/mount.d.ts +12 -1
  211. package/dist/editor/mount.d.ts.map +1 -1
  212. package/dist/editor/mount.js +36 -5
  213. package/dist/editor/mount.js.map +1 -1
  214. package/dist/format.d.ts +44 -0
  215. package/dist/format.d.ts.map +1 -0
  216. package/dist/format.js +65 -0
  217. package/dist/format.js.map +1 -0
  218. package/dist/fragment-deps.d.ts +24 -0
  219. package/dist/fragment-deps.d.ts.map +1 -0
  220. package/dist/fragment-deps.js +20 -0
  221. package/dist/fragment-deps.js.map +1 -0
  222. package/dist/hash.d.ts +0 -6
  223. package/dist/hash.d.ts.map +1 -1
  224. package/dist/hash.js +0 -18
  225. package/dist/hash.js.map +1 -1
  226. package/dist/history-provider.d.ts.map +1 -1
  227. package/dist/history-provider.js +30 -8
  228. package/dist/history-provider.js.map +1 -1
  229. package/dist/history-recorder.d.ts +7 -3
  230. package/dist/history-recorder.d.ts.map +1 -1
  231. package/dist/history-recorder.js +9 -1
  232. package/dist/history-recorder.js.map +1 -1
  233. package/dist/history-restorer.d.ts.map +1 -1
  234. package/dist/history-restorer.js +34 -2
  235. package/dist/history-restorer.js.map +1 -1
  236. package/dist/history.d.ts +26 -8
  237. package/dist/history.d.ts.map +1 -1
  238. package/dist/index.d.ts +2 -4
  239. package/dist/index.d.ts.map +1 -1
  240. package/dist/index.js +1 -2
  241. package/dist/index.js.map +1 -1
  242. package/dist/locale.d.ts +20 -0
  243. package/dist/locale.d.ts.map +1 -1
  244. package/dist/locale.js +38 -0
  245. package/dist/locale.js.map +1 -1
  246. package/dist/providers/_atomic-write.d.ts +9 -0
  247. package/dist/providers/_atomic-write.d.ts.map +1 -0
  248. package/dist/providers/_atomic-write.js +72 -0
  249. package/dist/providers/_atomic-write.js.map +1 -0
  250. package/dist/providers/_rm-ignore-missing.d.ts +31 -0
  251. package/dist/providers/_rm-ignore-missing.d.ts.map +1 -0
  252. package/dist/providers/_rm-ignore-missing.js +12 -0
  253. package/dist/providers/_rm-ignore-missing.js.map +1 -0
  254. package/dist/providers/_stream-interop.d.ts +23 -0
  255. package/dist/providers/_stream-interop.d.ts.map +1 -0
  256. package/dist/providers/_stream-interop.js +21 -0
  257. package/dist/providers/_stream-interop.js.map +1 -0
  258. package/dist/providers/azure-blob.d.ts.map +1 -1
  259. package/dist/providers/azure-blob.js +60 -0
  260. package/dist/providers/azure-blob.js.map +1 -1
  261. package/dist/providers/filesystem.d.ts +4 -0
  262. package/dist/providers/filesystem.d.ts.map +1 -1
  263. package/dist/providers/filesystem.js +63 -2
  264. package/dist/providers/filesystem.js.map +1 -1
  265. package/dist/providers/s3.d.ts.map +1 -1
  266. package/dist/providers/s3.js +84 -1
  267. package/dist/providers/s3.js.map +1 -1
  268. package/dist/publish-rendered.d.ts +37 -17
  269. package/dist/publish-rendered.d.ts.map +1 -1
  270. package/dist/publish-rendered.js +71 -67
  271. package/dist/publish-rendered.js.map +1 -1
  272. package/dist/publish.d.ts +13 -12
  273. package/dist/publish.d.ts.map +1 -1
  274. package/dist/publish.js +23 -47
  275. package/dist/publish.js.map +1 -1
  276. package/dist/resolver.d.ts +12 -2
  277. package/dist/resolver.d.ts.map +1 -1
  278. package/dist/resolver.js +54 -9
  279. package/dist/resolver.js.map +1 -1
  280. package/dist/schema/dimensions.d.ts +78 -0
  281. package/dist/schema/dimensions.d.ts.map +1 -0
  282. package/dist/schema/dimensions.js +97 -0
  283. package/dist/schema/dimensions.js.map +1 -0
  284. package/dist/schema/helpers.d.ts +108 -0
  285. package/dist/schema/helpers.d.ts.map +1 -0
  286. package/dist/schema/helpers.js +133 -0
  287. package/dist/schema/helpers.js.map +1 -0
  288. package/dist/schema/index.d.ts +27 -0
  289. package/dist/schema/index.d.ts.map +1 -0
  290. package/dist/schema/index.js +25 -0
  291. package/dist/schema/index.js.map +1 -0
  292. package/dist/schema/types.d.ts +390 -0
  293. package/dist/schema/types.d.ts.map +1 -0
  294. package/dist/schema/types.js +25 -0
  295. package/dist/schema/types.js.map +1 -0
  296. package/dist/selector-chain.d.ts +63 -0
  297. package/dist/selector-chain.d.ts.map +1 -0
  298. package/dist/selector-chain.js +58 -0
  299. package/dist/selector-chain.js.map +1 -0
  300. package/dist/sidecars.d.ts +19 -18
  301. package/dist/sidecars.d.ts.map +1 -1
  302. package/dist/sidecars.js +70 -62
  303. package/dist/sidecars.js.map +1 -1
  304. package/dist/targets.d.ts.map +1 -1
  305. package/dist/targets.js +15 -37
  306. package/dist/targets.js.map +1 -1
  307. package/dist/themes.d.ts +69 -0
  308. package/dist/themes.d.ts.map +1 -0
  309. package/dist/themes.js +85 -0
  310. package/dist/themes.js.map +1 -0
  311. package/dist/transforms/adapter.d.ts +115 -0
  312. package/dist/transforms/adapter.d.ts.map +1 -0
  313. package/dist/transforms/adapter.js +2 -0
  314. package/dist/transforms/adapter.js.map +1 -0
  315. package/dist/transforms/cloudflare.d.ts +17 -0
  316. package/dist/transforms/cloudflare.d.ts.map +1 -0
  317. package/dist/transforms/cloudflare.js +110 -0
  318. package/dist/transforms/cloudflare.js.map +1 -0
  319. package/dist/transforms/index.d.ts +24 -0
  320. package/dist/transforms/index.d.ts.map +1 -0
  321. package/dist/transforms/index.js +30 -0
  322. package/dist/transforms/index.js.map +1 -0
  323. package/dist/transforms/sharp.d.ts +3 -0
  324. package/dist/transforms/sharp.d.ts.map +1 -0
  325. package/dist/transforms/sharp.js +43 -0
  326. package/dist/transforms/sharp.js.map +1 -0
  327. package/dist/types.d.ts +125 -1
  328. package/dist/types.d.ts.map +1 -1
  329. package/dist/types.js.map +1 -1
  330. package/package.json +20 -1
  331. package/admin-dist/assets/index-B6pVot0Y.css +0 -1
  332. package/admin-dist/assets/index-DniLwxJA.js +0 -609
  333. package/dist/providers/r2.d.ts +0 -8
  334. package/dist/providers/r2.d.ts.map +0 -1
  335. package/dist/providers/r2.js +0 -86
  336. package/dist/providers/r2.js.map +0 -1
  337. package/dist/source-sidecars.d.ts +0 -32
  338. package/dist/source-sidecars.d.ts.map +0 -1
  339. package/dist/source-sidecars.js +0 -98
  340. package/dist/source-sidecars.js.map +0 -1
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Content-addressing hash for asset bytes.
3
+ *
4
+ * Uses **SHA-256**, 8-character hex prefix — the canonical asset-URL hash for
5
+ * this codebase. Distinct from:
6
+ * - `src/hash.ts` (MD5-based) used by publish-rendered sidecars
7
+ * - Full SHA-256 used by history blob storage
8
+ *
9
+ * See design-media-reference.md "Codebase alignment verified → Two hash
10
+ * algorithms coexist" for why asset work standardises on SHA-256 and doesn't
11
+ * extend the legacy MD5 sidecar pattern.
12
+ *
13
+ * The streaming helper (`hashStream`) consumes the passed stream. Callers
14
+ * that need both the hash AND the original bytes must tee the stream first.
15
+ */
16
+ import { createHash } from 'node:crypto';
17
+ /** Length of the hex prefix embedded in asset URLs. Matches the doc's `{hash8}`. */
18
+ export const ASSET_HASH_LENGTH = 8;
19
+ /** Hash a complete byte buffer — convenience wrapper for tests and small payloads. */
20
+ export function hashBytes(bytes) {
21
+ const full = createHash('sha256').update(bytes).digest('hex');
22
+ return full.slice(0, ASSET_HASH_LENGTH);
23
+ }
24
+ /**
25
+ * Hash a byte stream as it flows through. Consumes the stream. Returns the
26
+ * 8-char hex prefix once the stream ends.
27
+ *
28
+ * For upload pipelines that need to both hash and persist bytes, tee the
29
+ * source stream and pass one branch here, the other to storage.
30
+ */
31
+ export async function hashStream(stream) {
32
+ const digest = createHash('sha256');
33
+ const reader = stream.getReader();
34
+ while (true) {
35
+ const { value, done } = await reader.read();
36
+ if (done)
37
+ break;
38
+ if (value)
39
+ digest.update(value);
40
+ }
41
+ return digest.digest('hex').slice(0, ASSET_HASH_LENGTH);
42
+ }
43
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/assets/hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,oFAAoF;AACpF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAA;AAElC,sFAAsF;AACtF,MAAM,UAAU,SAAS,CAAC,KAAiB;IACzC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAkC;IACjE,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;IACnC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAA;IACjC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;QAC3C,IAAI,IAAI;YAAE,MAAK;QACf,IAAI,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACzD,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface ImageDimensions {
2
+ width: number;
3
+ height: number;
4
+ }
5
+ /**
6
+ * Extract dimensions from an image buffer. Returns `null` when sharp
7
+ * can't parse the bytes (unsupported format, corrupt, or non-image MIME
8
+ * that slipped past sniffing).
9
+ */
10
+ export declare function extractImageDimensions(bytes: Uint8Array): Promise<ImageDimensions | null>;
11
+ //# sourceMappingURL=image-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-metadata.d.ts","sourceRoot":"","sources":["../../src/assets/image-metadata.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAQ/F"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Image metadata extraction — wraps sharp's `.metadata()` to get width +
3
+ * height from bytes without decoding the full image. Read-only, no transform,
4
+ * no resize.
5
+ *
6
+ * Step 4 will add a sibling transform module (variants via sharp's
7
+ * `.resize()` + `.toFormat()`) that shares the sharp dependency. This file
8
+ * stays focused on "describe the image" — a reason to change independent of
9
+ * variant generation.
10
+ *
11
+ * sharp is an Apache-2.0 Node binding over libvips. See
12
+ * design-media-reference.md → Library and tooling specifics.
13
+ */
14
+ import sharp from 'sharp';
15
+ /**
16
+ * Extract dimensions from an image buffer. Returns `null` when sharp
17
+ * can't parse the bytes (unsupported format, corrupt, or non-image MIME
18
+ * that slipped past sniffing).
19
+ */
20
+ export async function extractImageDimensions(bytes) {
21
+ try {
22
+ const meta = await sharp(bytes).metadata();
23
+ if (typeof meta.width !== 'number' || typeof meta.height !== 'number')
24
+ return null;
25
+ return { width: meta.width, height: meta.height };
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ //# sourceMappingURL=image-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-metadata.js","sourceRoot":"","sources":["../../src/assets/image-metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAAiB;IAC5D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC1C,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QAClF,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Locale-bytes override ingest — write per-locale (or per-theme) bytes
3
+ * for an existing asset.
4
+ *
5
+ * Author-facing semantics (design-media.md → locale-specific bytes):
6
+ * "When the active locale is not the default and the author is
7
+ * uploading a file that matches an existing asset's name, the dialog
8
+ * asks: Replace default bytes / Add {locale} bytes override / Cancel."
9
+ *
10
+ * The "Add override" branch lands here. Result on disk:
11
+ * - `{name}.asset.{selector}.json` — locale-bytes manifest with own hash
12
+ * - `{name}-{hash}.{selector}.{ext}` — primary bytes for this locale
13
+ * - `{name}-{hash}.{selector}-{w}w.{ext}` — variant ladder for this locale
14
+ *
15
+ * The default manifest at `{name}.asset.json` is unchanged.
16
+ *
17
+ * Single responsibility: validate the override candidate, hash + extract
18
+ * dimensions + generate variants, write the locale manifest + bytes.
19
+ * Does NOT own:
20
+ * - the route adapter (HTTP layer)
21
+ * - the "default vs override" decision UX (the route knows whether the
22
+ * active locale is non-default)
23
+ * - per-reference content rewrites (locale-bytes don't affect refs)
24
+ *
25
+ * Compatibility rules per design-media.md:
26
+ * - Same kind as default (image override of image, etc.)
27
+ * - `animated` flag must match (out of v1 scope: animated detection
28
+ * deferred — today both default and override are static images)
29
+ * - MIME may differ within the kind category (jpeg default + webp
30
+ * override is allowed; image → video is not)
31
+ * - Dimensions may differ (warning at upload time is a UX concern)
32
+ *
33
+ * History recording mirrors `ingest.ts`: one revision per upload,
34
+ * recorded BEFORE any writes so the recorder's first-time baseline
35
+ * captures pre-op state.
36
+ */
37
+ import type { ContentRoot } from '../content-root.js';
38
+ import type { HistoryProvider } from '../history.js';
39
+ import type { LocaleBytesOverrideManifest } from '../schema/types.js';
40
+ import type { Selector } from '../schema/dimensions.js';
41
+ import type { StorageProvider } from '../types.js';
42
+ import { type UploadPreprocessor } from './preprocess.js';
43
+ import { type UploadPolicy } from './validate.js';
44
+ export interface IngestLocaleBytesInput {
45
+ /** Storage provider. */
46
+ storage: StorageProvider;
47
+ /** Path prefix for assets (typically `"assets"`). */
48
+ assetsRoot: string;
49
+ /** Existing asset's name. The default manifest must already exist. */
50
+ assetName: string;
51
+ /**
52
+ * Selector for the override (locale + optional theme). Must be
53
+ * non-null — caller decides which dimension(s) to write. The default
54
+ * asset's bytes correspond to selector === null and are untouched.
55
+ */
56
+ selector: Selector;
57
+ /** The incoming byte stream for the override bytes. */
58
+ bytes: ReadableStream<Uint8Array>;
59
+ /** Per-target upload policy (size cap). */
60
+ policy?: UploadPolicy;
61
+ /** Optional history. When set, one revision is recorded for this upload. */
62
+ history?: HistoryProvider;
63
+ /** Required when `history` is set. */
64
+ contentRoot?: ContentRoot;
65
+ /** Author identifier. */
66
+ author?: string;
67
+ /** Format-specific preprocessors. Defaults to `defaultPreprocessors`. */
68
+ preprocessors?: readonly UploadPreprocessor[];
69
+ }
70
+ export interface IngestLocaleBytesResult {
71
+ /** The new locale-bytes manifest as written. */
72
+ manifest: LocaleBytesOverrideManifest;
73
+ /** Path to the override's primary bytes (for caller logging). */
74
+ bytesPath: string;
75
+ }
76
+ /**
77
+ * Ingest a locale-bytes override for an existing asset. Throws:
78
+ * - `AssetManifestNotFoundError` — default manifest doesn't exist
79
+ * - `AssetValidationError` (subclass) — name/size/MIME failed policy
80
+ * - `AssetKindMismatchError` — MIME category differs from default
81
+ * (image override of pdf is rejected, jpeg override of png is fine)
82
+ * - `AssetVariantGenerationError` — sharp couldn't process the bytes
83
+ * - `AssetStorageError` — underlying storage failed
84
+ */
85
+ export declare function ingestLocaleBytes(input: IngestLocaleBytesInput): Promise<IngestLocaleBytesResult>;
86
+ //# sourceMappingURL=ingest-locale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest-locale.d.ts","sourceRoot":"","sources":["../../src/assets/ingest-locale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,OAAO,KAAK,EAA+B,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAClG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAalD,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAE3E,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,eAAe,CAAA;AASjE,MAAM,WAAW,sBAAsB;IACrC,wBAAwB;IACxB,OAAO,EAAE,eAAe,CAAA;IACxB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,EAAE,QAAQ,CAAA;IAClB,uDAAuD;IACvD,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACjC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,sCAAsC;IACtC,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,yBAAyB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAC9C;AAED,MAAM,WAAW,uBAAuB;IACtC,gDAAgD;IAChD,QAAQ,EAAE,2BAA2B,CAAA;IACrC,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAuJvG"}
@@ -0,0 +1,209 @@
1
+ import { recordWrite } from '../history-recorder.js';
2
+ import { selectorSuffix } from '../schema/dimensions.js';
3
+ import { rmIgnoreMissing } from '../providers/_rm-ignore-missing.js';
4
+ import { AssetKindMismatchError, AssetMimeMismatchError, AssetStorageError, AssetVariantGenerationError, } from './errors.js';
5
+ import { ASSET_HASH_LENGTH, hashBytes } from './hash.js';
6
+ import { extractImageDimensions } from './image-metadata.js';
7
+ import { mimeCategory } from './kind-compat.js';
8
+ import { assetBytesPath, assetVariantBytesPath, readManifest, writeLocaleManifest } from './manifest.js';
9
+ import { runAnalyzers } from './analyze.js';
10
+ import { runPreprocessors } from './preprocess.js';
11
+ import { sniffMimeFromStream } from './mime-sniff.js';
12
+ import { validateUpload } from './validate.js';
13
+ import { generateVariants } from './variants.js';
14
+ /** Ext-from-MIME for the v1 allowlist (JPEG, PNG). */
15
+ const EXT_BY_MIME = {
16
+ 'image/jpeg': 'jpg',
17
+ 'image/png': 'png',
18
+ };
19
+ /**
20
+ * Ingest a locale-bytes override for an existing asset. Throws:
21
+ * - `AssetManifestNotFoundError` — default manifest doesn't exist
22
+ * - `AssetValidationError` (subclass) — name/size/MIME failed policy
23
+ * - `AssetKindMismatchError` — MIME category differs from default
24
+ * (image override of pdf is rejected, jpeg override of png is fine)
25
+ * - `AssetVariantGenerationError` — sharp couldn't process the bytes
26
+ * - `AssetStorageError` — underlying storage failed
27
+ */
28
+ export async function ingestLocaleBytes(input) {
29
+ // Step 1 — read the default manifest. Throws AssetManifestNotFoundError
30
+ // when the asset doesn't exist; you can't override bytes for an asset
31
+ // that isn't there.
32
+ const defaultManifest = await readManifest(input.storage, input.assetsRoot, input.assetName);
33
+ // Step 2 — collect bytes once.
34
+ const initialBuffer = await collectBytes(input.bytes);
35
+ // Step 3 — sniff MIME and validate.
36
+ const { mime, ext } = await sniffMimeFromStream(byteStreamFrom(initialBuffer));
37
+ validateUpload({ name: input.assetName, claimedSize: initialBuffer.byteLength, sniffedMime: mime }, input.policy);
38
+ const bytesExt = ext ?? EXT_BY_MIME[mime ?? ''] ?? '';
39
+ if (!bytesExt) {
40
+ throw new AssetMimeMismatchError(mime, []);
41
+ }
42
+ // Step 4 — kind/MIME-category compatibility with default. Per design,
43
+ // jpeg → webp is allowed (same `image` category); image → pdf is not.
44
+ // We don't compare `kind` directly because the override doesn't carry
45
+ // its own kind — it inherits from the default.
46
+ const overrideMime = mime ?? 'application/octet-stream';
47
+ const defaultCategory = mimeCategory(defaultManifest.mime);
48
+ const overrideCategory = mimeCategory(overrideMime);
49
+ if (defaultCategory !== overrideCategory) {
50
+ throw new AssetKindMismatchError(defaultManifest.kind, defaultCategory, defaultManifest.kind, overrideCategory);
51
+ }
52
+ // Step 5 — format-specific preprocessing (SVG sanitization, future
53
+ // EXIF/HEIC/etc.). Same interface as default-asset ingest; failures
54
+ // throw AssetPreprocessError (HTTP 400).
55
+ const { bytes: buffer } = await runPreprocessors(initialBuffer, mime, input.preprocessors);
56
+ const size = buffer.byteLength;
57
+ const hash = hashBytes(buffer);
58
+ if (hash.length !== ASSET_HASH_LENGTH) {
59
+ throw new AssetStorageError('write', input.assetName, new Error('unexpected hash length'));
60
+ }
61
+ // Step 6 — image dimensions (per-locale: override may differ from default).
62
+ const dims = overrideMime.startsWith('image/') ? await extractImageDimensions(buffer) : null;
63
+ // Step 7 — generate variants in memory. Skip for vector formats
64
+ // (SVG) and animated images (multi-frame can't ladder-resize
65
+ // correctly). Animated detection uses the analyzer for parity
66
+ // with the default-ingest path; locale manifests don't carry
67
+ // animated fields today, but the variant skip still matters.
68
+ const generatedVariants = [];
69
+ if (overrideMime.startsWith('image/') && overrideMime !== 'image/svg+xml') {
70
+ let isAnimated = false;
71
+ try {
72
+ const analysis = await runAnalyzers({
73
+ bytes: buffer,
74
+ assetName: input.assetName,
75
+ hash,
76
+ ext: bytesExt,
77
+ mime: overrideMime,
78
+ });
79
+ isAnimated = analysis.manifestPatch?.animated === true;
80
+ }
81
+ catch {
82
+ // Analyzer failure is non-fatal at this layer — fall back to
83
+ // assuming static + variants. Static analyzer would be the one
84
+ // failing; variant generation will surface its own error if
85
+ // sharp can't process the image.
86
+ }
87
+ if (!isAnimated) {
88
+ try {
89
+ const generated = await generateVariants(buffer);
90
+ generatedVariants.push(...generated);
91
+ }
92
+ catch (err) {
93
+ throw new AssetVariantGenerationError(input.assetName, err);
94
+ }
95
+ }
96
+ }
97
+ // Step 8 — compose paths + manifest in memory.
98
+ const variantManifestEntries = generatedVariants.map(v => ({
99
+ width: v.width,
100
+ path: assetVariantBytesPath(input.assetName, hash, bytesExt, v.width, input.selector),
101
+ size: v.bytes.byteLength,
102
+ }));
103
+ const bytesRel = assetBytesPath(input.assetName, hash, bytesExt, input.selector);
104
+ const bytesAbs = `${input.assetsRoot}/${bytesRel}`;
105
+ const localeManifest = {
106
+ version: 1,
107
+ name: input.assetName,
108
+ hash,
109
+ size,
110
+ mime: overrideMime,
111
+ width: dims?.width ?? null,
112
+ height: dims?.height ?? null,
113
+ variants: variantManifestEntries,
114
+ };
115
+ const localeManifestPath = `${input.assetsRoot}/${input.assetName}.asset${selectorSuffix(input.selector)}.json`;
116
+ // Step 8 — record history BEFORE any writes. Mirrors ingest.ts /
117
+ // replace.ts pattern.
118
+ if (input.history) {
119
+ if (!input.contentRoot) {
120
+ throw new Error('ingestLocaleBytes: history requires contentRoot');
121
+ }
122
+ const items = [
123
+ { path: localeManifestPath, content: `${JSON.stringify(localeManifest, null, 2)}\n` },
124
+ { path: bytesAbs, content: buffer },
125
+ ...generatedVariants.map(v => ({
126
+ path: `${input.assetsRoot}/${assetVariantBytesPath(input.assetName, hash, bytesExt, v.width, input.selector)}`,
127
+ content: v.bytes,
128
+ })),
129
+ ];
130
+ await recordWrite({
131
+ history: input.history,
132
+ contentRoot: input.contentRoot,
133
+ operation: 'save',
134
+ author: input.author,
135
+ items,
136
+ message: `Upload ${input.assetName} override (${selectorSuffix(input.selector).slice(1)})`,
137
+ });
138
+ }
139
+ // Step 9 — write primary bytes.
140
+ try {
141
+ await input.storage.writeStream(bytesAbs, byteStreamFrom(buffer));
142
+ }
143
+ catch (err) {
144
+ throw new AssetStorageError('write', bytesAbs, err);
145
+ }
146
+ // Step 10 — write variants with rollback on failure.
147
+ const writtenVariantPaths = [];
148
+ for (const v of generatedVariants) {
149
+ const variantAbs = `${input.assetsRoot}/${assetVariantBytesPath(input.assetName, hash, bytesExt, v.width, input.selector)}`;
150
+ try {
151
+ await input.storage.writeStream(variantAbs, byteStreamFrom(v.bytes));
152
+ }
153
+ catch (err) {
154
+ await rollback(input.storage, [bytesAbs, ...writtenVariantPaths]);
155
+ throw new AssetStorageError('write', variantAbs, err);
156
+ }
157
+ writtenVariantPaths.push(variantAbs);
158
+ }
159
+ // Step 11 — write the locale manifest last (the visible "this
160
+ // override exists" record).
161
+ try {
162
+ await writeLocaleManifest(input.storage, input.assetsRoot, input.assetName, input.selector, localeManifest);
163
+ }
164
+ catch (err) {
165
+ await rollback(input.storage, [bytesAbs, ...writtenVariantPaths]);
166
+ throw err;
167
+ }
168
+ return { manifest: localeManifest, bytesPath: bytesAbs };
169
+ }
170
+ async function rollback(storage, paths) {
171
+ for (const path of paths) {
172
+ try {
173
+ await rmIgnoreMissing(storage, path);
174
+ }
175
+ catch {
176
+ /* best-effort */
177
+ }
178
+ }
179
+ }
180
+ async function collectBytes(stream) {
181
+ const reader = stream.getReader();
182
+ const parts = [];
183
+ let total = 0;
184
+ while (true) {
185
+ const { value, done } = await reader.read();
186
+ if (done)
187
+ break;
188
+ if (value) {
189
+ parts.push(value);
190
+ total += value.byteLength;
191
+ }
192
+ }
193
+ const out = new Uint8Array(total);
194
+ let offset = 0;
195
+ for (const p of parts) {
196
+ out.set(p, offset);
197
+ offset += p.byteLength;
198
+ }
199
+ return out;
200
+ }
201
+ function byteStreamFrom(bytes) {
202
+ return new ReadableStream({
203
+ start(controller) {
204
+ controller.enqueue(bytes);
205
+ controller.close();
206
+ },
207
+ });
208
+ }
209
+ //# sourceMappingURL=ingest-locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest-locale.js","sourceRoot":"","sources":["../../src/assets/ingest-locale.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Asset ingest pipeline — the single entry point for "bytes in → persisted
3
+ * asset out." Composes validation, hashing, MIME sniffing, dimension
4
+ * extraction, byte persistence, and manifest writing.
5
+ *
6
+ * Callers (HTTP upload route, future CLI import, future paste-URL handler):
7
+ * const result = await ingestAsset({ storage, assetsRoot, bytes, requestedName, ... })
8
+ *
9
+ * Inside, the stream is collected into a buffer first — for the v1 slice's
10
+ * 50 MB limit this is the pragmatic choice (validation wants to see all the
11
+ * bytes; hashing + sniffing + dimensions all need to touch them). A future
12
+ * large-video path would need true streaming; calling sites that need that
13
+ * can compose the lower-level primitives (sniffMimeFromStream, hashStream,
14
+ * atomicWriteStream) directly.
15
+ *
16
+ * History atomicity:
17
+ * When `history` is provided, ingest records ONE revision covering the
18
+ * manifest + primary bytes + every variant. Recording happens BEFORE any
19
+ * writes so the recorder's first-time baseline scan captures pre-op
20
+ * state — same pattern as `replace.ts`. If recording succeeds but a
21
+ * subsequent write fails, the revision references blobs we never
22
+ * persisted; that's recoverable (history-restorer degrades gracefully
23
+ * on missing blobs) and rare (writes after a successful record fail
24
+ * only on transient storage errors), and far better than the inverse
25
+ * (writes succeed, recorder captures post-op state, undo is a no-op).
26
+ */
27
+ import type { ContentRoot } from '../content-root.js';
28
+ import type { HistoryProvider } from '../history.js';
29
+ import type { AssetManifest } from '../schema/types.js';
30
+ import type { StorageProvider } from '../types.js';
31
+ import { type UploadAnalyzer } from './analyze.js';
32
+ import { type UploadPolicy } from './validate.js';
33
+ import { type UploadPreprocessor } from './preprocess.js';
34
+ export interface IngestInput {
35
+ /** The target's storage provider. */
36
+ storage: StorageProvider;
37
+ /** The assets directory prefix (e.g., `"assets"`) relative to storage root. */
38
+ assetsRoot: string;
39
+ /** The incoming byte stream (multipart file body). */
40
+ bytes: ReadableStream<Uint8Array>;
41
+ /** Author-chosen asset name (pre-validation; policy may reject). */
42
+ requestedName: string;
43
+ /** Optional author-supplied alt text. Null means "not set" (warns in the library). */
44
+ alt: string | null;
45
+ /** Author identifier, if available. Empty string when RBAC isn't configured. */
46
+ uploadedBy: string;
47
+ /**
48
+ * Per-target upload policy. When omitted, the default size cap
49
+ * (`DEFAULT_ASSET_MAX_BYTES` from validate.ts) applies. The HTTP
50
+ * route should pass `target.assets` through here so per-target
51
+ * limits are honored.
52
+ */
53
+ policy?: UploadPolicy;
54
+ /**
55
+ * Optional history provider. When set, ingest records ONE revision
56
+ * covering manifest + primary bytes + variants. Caller must also pass
57
+ * `contentRoot` so the recorder can scan the pre-op baseline on its
58
+ * first call.
59
+ */
60
+ history?: HistoryProvider;
61
+ /** Required when `history` is set — content root for the baseline scan. */
62
+ contentRoot?: ContentRoot;
63
+ /** Author identifier passed through to the history revision. */
64
+ author?: string;
65
+ /**
66
+ * Format-specific preprocessors to run on the byte buffer before
67
+ * hashing. Defaults to `defaultPreprocessors` (today: SVG
68
+ * sanitization). Tests pass an empty array to bypass; future
69
+ * deployments can register custom preprocessors (HEIC transcode,
70
+ * etc.) without editing this module.
71
+ */
72
+ preprocessors?: readonly UploadPreprocessor[];
73
+ /**
74
+ * Format-specific analyzers to run on the post-preprocess bytes.
75
+ * Defaults to `defaultAnalyzers` (today: width/height + animated
76
+ * detection + poster extraction for images). Empty array bypasses
77
+ * analysis; custom registries plug in audio metadata, EXIF,
78
+ * PDF page count, etc. without editing this module.
79
+ */
80
+ analyzers?: readonly UploadAnalyzer[];
81
+ }
82
+ export interface IngestResult {
83
+ manifest: AssetManifest;
84
+ bytesPath: string;
85
+ }
86
+ /**
87
+ * Ingest an asset. On success, bytes are persisted at
88
+ * `{assetsRoot}/{name}-{hash}.{ext}` and the manifest at
89
+ * `{assetsRoot}/{name}.asset.json`.
90
+ *
91
+ * Throws:
92
+ * - `AssetValidationError` — name, size, or MIME failed policy
93
+ * - `AssetStorageError` — storage write failed
94
+ */
95
+ export declare function ingestAsset(input: IngestInput): Promise<IngestResult>;
96
+ //# sourceMappingURL=ingest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/assets/ingest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,oBAAoB,CAAA;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAMhE,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,eAAe,CAAA;AACjE,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AA2B3E,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,OAAO,EAAE,eAAe,CAAA;IACxB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAA;IAClB,sDAAsD;IACtD,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACjC,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAA;IACrB,sFAAsF;IACtF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;IAC7C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAmM3E"}