@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
@@ -1,13 +1,107 @@
1
+ /**
2
+ * File acceptance filter categories used by branch schemas and forms.
3
+ */
1
4
  export type FileAccept = 'image' | 'document' | 'any';
2
- export declare const IMAGE_EXTENSIONS: Set<string>;
3
- export declare const BLOCKED_IMAGE_EXTENSIONS: Set<string>;
4
- export declare const DOCUMENT_EXTENSIONS: Set<string>;
5
- export declare const ARCHIVE_EXTENSIONS: Set<string>;
6
- export declare const IMAGE_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/avif", "image/bmp", "image/x-icon", "image/vnd.microsoft.icon"];
7
- export declare const BLOCKED_IMAGE_MIME_TYPES: readonly ["image/svg+xml", "image/svg"];
8
- export declare const DOCUMENT_MIME_TYPES: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "text/plain", "text/csv", "text/markdown"];
9
- export declare const ARCHIVE_MIME_TYPES: readonly ["application/zip", "application/x-zip-compressed", "application/x-7z-compressed", "application/x-tar", "application/gzip", "application/json"];
5
+ /**
6
+ * High-level categorization of supported file types.
7
+ */
8
+ export type FileCategory = 'image' | 'document' | 'archive';
9
+ /**
10
+ * Definition of a supported file format in BeechCMS, including MIME types,
11
+ * binary classification, and binary signature verification rules.
12
+ */
13
+ export interface FileTypeDefinition {
14
+ /** File extension without leading dot (e.g. 'jpg', 'png', 'pdf'). */
15
+ readonly extension: string;
16
+ /** Canonical primary MIME type (e.g. 'image/jpeg'). */
17
+ readonly primaryMime: string;
18
+ /** All valid MIME types associated with this format. */
19
+ readonly mimeTypes: readonly string[];
20
+ /** High-level file category. */
21
+ readonly category: FileCategory;
22
+ /** Whether the file is a binary format requiring magic byte signature validation. */
23
+ readonly isBinary: boolean;
24
+ /** Expected magic bytes prefix if the format uses a static prefix. */
25
+ readonly magicBytes?: readonly number[];
26
+ /** Custom signature matching function for formats with complex, variable, or offset headers. */
27
+ readonly matchSignature?: (bytes: Uint8Array) => boolean;
28
+ }
29
+ /**
30
+ * Checks whether a byte buffer starts with a specified byte prefix.
31
+ *
32
+ * @param bytes - The byte buffer to inspect.
33
+ * @param prefix - The sequence of bytes to match against.
34
+ * @returns True if the buffer starts with the given prefix, false otherwise.
35
+ */
36
+ export declare function matchBytePrefix(bytes: Uint8Array, prefix: readonly number[]): boolean;
37
+ /**
38
+ * Evaluates whether the given byte buffer matches the binary signature of a file definition.
39
+ *
40
+ * @param def - The file type definition to check against.
41
+ * @param bytes - The raw byte buffer to inspect.
42
+ * @returns True if the bytes match the definition's signature rules, false otherwise.
43
+ */
44
+ export declare function matchesFileSignature(def: FileTypeDefinition, bytes: Uint8Array): boolean;
45
+ /**
46
+ * Single source of truth registry for all supported file types in BeechCMS.
47
+ */
48
+ export declare const SUPPORTED_FILE_TYPES: Record<string, FileTypeDefinition>;
49
+ /**
50
+ * SVG is intentionally blocked from general file upload as it can embed executable scripts
51
+ * creating a stored XSS vulnerability when served directly to browsers.
52
+ */
53
+ export declare const BLOCKED_IMAGE_EXTENSIONS: ReadonlySet<string>;
54
+ /**
55
+ * Blocked MIME types associated with unsafe image formats.
56
+ */
57
+ export declare const BLOCKED_IMAGE_MIME_TYPES: readonly string[];
58
+ /** Set of supported image file extensions. */
59
+ export declare const IMAGE_EXTENSIONS: ReadonlySet<string>;
60
+ /** Set of supported document file extensions. */
61
+ export declare const DOCUMENT_EXTENSIONS: ReadonlySet<string>;
62
+ /** Set of supported archive file extensions. */
63
+ export declare const ARCHIVE_EXTENSIONS: ReadonlySet<string>;
64
+ /** List of supported image MIME types. */
65
+ export declare const IMAGE_MIME_TYPES: readonly string[];
66
+ /** List of supported document MIME types. */
67
+ export declare const DOCUMENT_MIME_TYPES: readonly string[];
68
+ /** List of supported archive MIME types. */
69
+ export declare const ARCHIVE_MIME_TYPES: readonly string[];
70
+ /**
71
+ * Look up a supported file type definition by its extension.
72
+ *
73
+ * @param ext - The extension string with or without leading dot.
74
+ * @returns The matching FileTypeDefinition, or undefined if unsupported.
75
+ */
76
+ export declare function getFileTypeByExtension(ext: string | null | undefined): FileTypeDefinition | undefined;
77
+ /**
78
+ * Look up a supported file type definition by its declared MIME type.
79
+ *
80
+ * @param mime - The MIME string (e.g. 'image/png' or 'image/jpeg; charset=utf-8').
81
+ * @returns The matching FileTypeDefinition, or undefined if unsupported.
82
+ */
83
+ export declare function getFileTypeByMime(mime: string | null | undefined): FileTypeDefinition | undefined;
84
+ /**
85
+ * Extracts a lowercase file extension from a URL string or query parameters.
86
+ *
87
+ * @param url - The URL string to parse.
88
+ * @returns The extracted extension, or null if none was found.
89
+ */
10
90
  export declare function extensionFromUrl(url: string): string | null;
11
- export declare function isExtensionAccepted(ext: string | null, accept: FileAccept): boolean;
91
+ /**
92
+ * Checks whether a given file extension satisfies an acceptance policy ('image' | 'document' | 'any').
93
+ *
94
+ * @param ext - The file extension.
95
+ * @param accept - The acceptance mode.
96
+ * @returns True if accepted, false otherwise.
97
+ */
98
+ export declare function isExtensionAccepted(ext: string | null | undefined, accept: FileAccept): boolean;
99
+ /**
100
+ * Checks whether a given MIME type satisfies an acceptance policy ('image' | 'document' | 'any').
101
+ *
102
+ * @param mime - The declared MIME string.
103
+ * @param accept - The acceptance mode.
104
+ * @returns True if accepted, false otherwise.
105
+ */
12
106
  export declare function isMimeAccepted(mime: string, accept: FileAccept): boolean;
13
107
  //# sourceMappingURL=file-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-types.d.ts","sourceRoot":"","sources":["../../src/media/file-types.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAA;AAKrD,eAAO,MAAM,gBAAgB,aAAuE,CAAA;AACpG,eAAO,MAAM,wBAAwB,aAA2B,CAAA;AAChE,eAAO,MAAM,mBAAmB,aAAoF,CAAA;AACpH,eAAO,MAAM,kBAAkB,aAA8C,CAAA;AAI7E,eAAO,MAAM,gBAAgB,wIASnB,CAAA;AAGV,eAAO,MAAM,wBAAwB,yCAA0C,CAAA;AAC/E,eAAO,MAAM,mBAAmB,yXAWtB,CAAA;AACV,eAAO,MAAM,kBAAkB,0JAOrB,CAAA;AAEV,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB3D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAOnF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAcxE"}
1
+ {"version":3,"file":"file-types.d.ts","sourceRoot":"","sources":["../../src/media/file-types.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAA;AAErD;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAA;AAE3D;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,wDAAwD;IACxD,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC,gGAAgG;IAChG,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAA;CACzD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAMrF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAKxF;AA6CD;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAgMnE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAA4B,CAAA;AAErF;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAAmC,CAAA;AAIzF,8CAA8C;AAC9C,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAEhD,CAAA;AAED,iDAAiD;AACjD,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAEnD,CAAA;AAED,gDAAgD;AAChD,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAElD,CAAA;AAED,0CAA0C;AAC1C,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAE7C,CAAA;AAED,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAEhD,CAAA;AAED,4CAA4C;AAC5C,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAE/C,CAAA;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAIrG;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAMjG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB3D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAO/F;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CASxE"}
@@ -1,47 +1,322 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // Copyright (c) 2024–2026 Flavio De Musso
3
- // SVG is intentionally excluded: SVG can embed <script> tags and is rendered
4
- // inline by browsers when served as image/svg+xml on a same-origin route,
5
- // creating a stored XSS vector (see security audit finding #4).
6
- export const IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'avif', 'bmp', 'ico']);
3
+ /**
4
+ * Checks whether a byte buffer starts with a specified byte prefix.
5
+ *
6
+ * @param bytes - The byte buffer to inspect.
7
+ * @param prefix - The sequence of bytes to match against.
8
+ * @returns True if the buffer starts with the given prefix, false otherwise.
9
+ */
10
+ export function matchBytePrefix(bytes, prefix) {
11
+ if (bytes.length < prefix.length)
12
+ return false;
13
+ for (let i = 0; i < prefix.length; i++) {
14
+ if (bytes[i] !== prefix[i])
15
+ return false;
16
+ }
17
+ return true;
18
+ }
19
+ /**
20
+ * Evaluates whether the given byte buffer matches the binary signature of a file definition.
21
+ *
22
+ * @param def - The file type definition to check against.
23
+ * @param bytes - The raw byte buffer to inspect.
24
+ * @returns True if the bytes match the definition's signature rules, false otherwise.
25
+ */
26
+ export function matchesFileSignature(def, bytes) {
27
+ if (!def.isBinary)
28
+ return true;
29
+ if (def.matchSignature)
30
+ return def.matchSignature(bytes);
31
+ if (def.magicBytes)
32
+ return matchBytePrefix(bytes, def.magicBytes);
33
+ return false;
34
+ }
35
+ /** OLE Compound File Binary Format (CFBF) header used by legacy MS Office files (.doc, .xls, .ppt). */
36
+ const OLE_MAGIC = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1];
37
+ /** Matcher for OLE CFBF binary files. */
38
+ function matchOleSignature(bytes) {
39
+ return matchBytePrefix(bytes, OLE_MAGIC);
40
+ }
41
+ /** Standard ZIP header matcher used by .zip and Office OpenXML (.docx, .xlsx, .pptx). */
42
+ function matchZipSignature(bytes) {
43
+ if (bytes.length < 4)
44
+ return false;
45
+ return ((bytes[0] === 0x50 && bytes[1] === 0x4B && bytes[2] === 0x03 && bytes[3] === 0x04) || // standard zip
46
+ (bytes[0] === 0x50 && bytes[1] === 0x4B && bytes[2] === 0x05 && bytes[3] === 0x06) || // empty zip
47
+ (bytes[0] === 0x50 && bytes[1] === 0x4B && bytes[2] === 0x07 && bytes[3] === 0x08) // spanned zip
48
+ );
49
+ }
50
+ /** Common shared definition for JPEG files. */
51
+ const JPEG_DEFINITION = {
52
+ primaryMime: 'image/jpeg',
53
+ mimeTypes: ['image/jpeg', 'image/jpg'],
54
+ category: 'image',
55
+ isBinary: true,
56
+ magicBytes: [0xFF, 0xD8, 0xFF],
57
+ };
58
+ /** Common shared definition for legacy MS Office files. */
59
+ const OLE_DOCUMENT_DEFINITION = {
60
+ category: 'document',
61
+ isBinary: true,
62
+ magicBytes: [...OLE_MAGIC],
63
+ matchSignature: matchOleSignature,
64
+ };
65
+ /** Common shared definition for OpenXML Office files. */
66
+ const OPENXML_DOCUMENT_DEFINITION = {
67
+ category: 'document',
68
+ isBinary: true,
69
+ magicBytes: [0x50, 0x4B, 0x03, 0x04],
70
+ matchSignature: matchZipSignature,
71
+ };
72
+ /**
73
+ * Single source of truth registry for all supported file types in BeechCMS.
74
+ */
75
+ export const SUPPORTED_FILE_TYPES = {
76
+ // --- IMAGES ---
77
+ jpg: {
78
+ extension: 'jpg',
79
+ ...JPEG_DEFINITION,
80
+ },
81
+ jpeg: {
82
+ extension: 'jpeg',
83
+ ...JPEG_DEFINITION,
84
+ },
85
+ png: {
86
+ extension: 'png',
87
+ primaryMime: 'image/png',
88
+ mimeTypes: ['image/png'],
89
+ category: 'image',
90
+ isBinary: true,
91
+ magicBytes: [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A],
92
+ },
93
+ gif: {
94
+ extension: 'gif',
95
+ primaryMime: 'image/gif',
96
+ mimeTypes: ['image/gif'],
97
+ category: 'image',
98
+ isBinary: true,
99
+ magicBytes: [0x47, 0x49, 0x46, 0x38],
100
+ matchSignature: (bytes) => bytes.length >= 6 &&
101
+ bytes[0] === 0x47 && bytes[1] === 0x49 && bytes[2] === 0x46 && bytes[3] === 0x38 &&
102
+ (bytes[4] === 0x37 || bytes[4] === 0x39) && bytes[5] === 0x61,
103
+ },
104
+ webp: {
105
+ extension: 'webp',
106
+ primaryMime: 'image/webp',
107
+ mimeTypes: ['image/webp'],
108
+ category: 'image',
109
+ isBinary: true,
110
+ magicBytes: [0x52, 0x49, 0x46, 0x46],
111
+ matchSignature: (bytes) => bytes.length >= 12 &&
112
+ bytes[0] === 0x52 && bytes[1] === 0x49 && bytes[2] === 0x46 && bytes[3] === 0x46 &&
113
+ bytes[8] === 0x57 && bytes[9] === 0x45 && bytes[10] === 0x42 && bytes[11] === 0x50,
114
+ },
115
+ avif: {
116
+ extension: 'avif',
117
+ primaryMime: 'image/avif',
118
+ mimeTypes: ['image/avif'],
119
+ category: 'image',
120
+ isBinary: true,
121
+ magicBytes: [0x66, 0x74, 0x79, 0x70],
122
+ matchSignature: (bytes) => {
123
+ if (bytes.length < 12)
124
+ return false;
125
+ // Check for 'ftyp' at offset 4
126
+ const isFtyp = bytes[4] === 0x66 && bytes[5] === 0x74 && bytes[6] === 0x79 && bytes[7] === 0x70;
127
+ if (!isFtyp)
128
+ return false;
129
+ // Brand check: 'avif', 'avis', 'mif1', 'msf1'
130
+ const brand = String.fromCharCode(bytes[8], bytes[9], bytes[10], bytes[11]);
131
+ return brand === 'avif' || brand === 'avis' || brand === 'mif1' || brand === 'msf1';
132
+ },
133
+ },
134
+ bmp: {
135
+ extension: 'bmp',
136
+ primaryMime: 'image/bmp',
137
+ mimeTypes: ['image/bmp'],
138
+ category: 'image',
139
+ isBinary: true,
140
+ magicBytes: [0x42, 0x4D],
141
+ },
142
+ ico: {
143
+ extension: 'ico',
144
+ primaryMime: 'image/x-icon',
145
+ mimeTypes: ['image/x-icon', 'image/vnd.microsoft.icon'],
146
+ category: 'image',
147
+ isBinary: true,
148
+ magicBytes: [0x00, 0x00, 0x01, 0x00],
149
+ },
150
+ // --- DOCUMENTS ---
151
+ pdf: {
152
+ extension: 'pdf',
153
+ primaryMime: 'application/pdf',
154
+ mimeTypes: ['application/pdf'],
155
+ category: 'document',
156
+ isBinary: true,
157
+ magicBytes: [0x25, 0x50, 0x44, 0x46],
158
+ },
159
+ docx: {
160
+ extension: 'docx',
161
+ primaryMime: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
162
+ mimeTypes: ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
163
+ ...OPENXML_DOCUMENT_DEFINITION,
164
+ },
165
+ doc: {
166
+ extension: 'doc',
167
+ primaryMime: 'application/msword',
168
+ mimeTypes: ['application/msword'],
169
+ ...OLE_DOCUMENT_DEFINITION,
170
+ },
171
+ xlsx: {
172
+ extension: 'xlsx',
173
+ primaryMime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
174
+ mimeTypes: ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
175
+ ...OPENXML_DOCUMENT_DEFINITION,
176
+ },
177
+ xls: {
178
+ extension: 'xls',
179
+ primaryMime: 'application/vnd.ms-excel',
180
+ mimeTypes: ['application/vnd.ms-excel'],
181
+ ...OLE_DOCUMENT_DEFINITION,
182
+ },
183
+ pptx: {
184
+ extension: 'pptx',
185
+ primaryMime: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
186
+ mimeTypes: ['application/vnd.openxmlformats-officedocument.presentationml.presentation'],
187
+ ...OPENXML_DOCUMENT_DEFINITION,
188
+ },
189
+ ppt: {
190
+ extension: 'ppt',
191
+ primaryMime: 'application/vnd.ms-powerpoint',
192
+ mimeTypes: ['application/vnd.ms-powerpoint'],
193
+ ...OLE_DOCUMENT_DEFINITION,
194
+ },
195
+ txt: {
196
+ extension: 'txt',
197
+ primaryMime: 'text/plain',
198
+ mimeTypes: ['text/plain'],
199
+ category: 'document',
200
+ isBinary: false,
201
+ },
202
+ csv: {
203
+ extension: 'csv',
204
+ primaryMime: 'text/csv',
205
+ mimeTypes: ['text/csv'],
206
+ category: 'document',
207
+ isBinary: false,
208
+ },
209
+ md: {
210
+ extension: 'md',
211
+ primaryMime: 'text/markdown',
212
+ mimeTypes: ['text/markdown'],
213
+ category: 'document',
214
+ isBinary: false,
215
+ },
216
+ // --- ARCHIVES & DATA ---
217
+ zip: {
218
+ extension: 'zip',
219
+ primaryMime: 'application/zip',
220
+ mimeTypes: ['application/zip', 'application/x-zip-compressed'],
221
+ category: 'archive',
222
+ isBinary: true,
223
+ magicBytes: [0x50, 0x4B, 0x03, 0x04],
224
+ matchSignature: matchZipSignature,
225
+ },
226
+ '7z': {
227
+ extension: '7z',
228
+ primaryMime: 'application/x-7z-compressed',
229
+ mimeTypes: ['application/x-7z-compressed'],
230
+ category: 'archive',
231
+ isBinary: true,
232
+ magicBytes: [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C],
233
+ },
234
+ tar: {
235
+ extension: 'tar',
236
+ primaryMime: 'application/x-tar',
237
+ mimeTypes: ['application/x-tar'],
238
+ category: 'archive',
239
+ isBinary: true,
240
+ magicBytes: [0x75, 0x73, 0x74, 0x61, 0x72], // 'ustar'
241
+ matchSignature: (bytes) => {
242
+ if (bytes.length < 512)
243
+ return false;
244
+ // Check for POSIX 'ustar' at offset 257
245
+ return (bytes[257] === 0x75 && bytes[258] === 0x73 && bytes[259] === 0x74 &&
246
+ bytes[260] === 0x61 && bytes[261] === 0x72);
247
+ },
248
+ },
249
+ gz: {
250
+ extension: 'gz',
251
+ primaryMime: 'application/gzip',
252
+ mimeTypes: ['application/gzip'],
253
+ category: 'archive',
254
+ isBinary: true,
255
+ magicBytes: [0x1F, 0x8B],
256
+ },
257
+ json: {
258
+ extension: 'json',
259
+ primaryMime: 'application/json',
260
+ mimeTypes: ['application/json'],
261
+ category: 'archive',
262
+ isBinary: false,
263
+ },
264
+ };
265
+ /**
266
+ * SVG is intentionally blocked from general file upload as it can embed executable scripts
267
+ * creating a stored XSS vulnerability when served directly to browsers.
268
+ */
7
269
  export const BLOCKED_IMAGE_EXTENSIONS = new Set(['svg', 'svgz']);
8
- export const DOCUMENT_EXTENSIONS = new Set(['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv', 'md']);
9
- export const ARCHIVE_EXTENSIONS = new Set(['zip', '7z', 'tar', 'gz', 'json']);
10
- // Explicitly enumerate safe image MIME types instead of using the wildcard
11
- // `image/*` prefix, which would permit `image/svg+xml` and other XSS vectors.
12
- export const IMAGE_MIME_TYPES = [
13
- 'image/jpeg',
14
- 'image/png',
15
- 'image/gif',
16
- 'image/webp',
17
- 'image/avif',
18
- 'image/bmp',
19
- 'image/x-icon',
20
- 'image/vnd.microsoft.icon',
21
- ];
22
- // Blocked image MIME types — listed explicitly so upload code can reject them
23
- // with a clear error rather than a generic "file type not allowed".
270
+ /**
271
+ * Blocked MIME types associated with unsafe image formats.
272
+ */
24
273
  export const BLOCKED_IMAGE_MIME_TYPES = ['image/svg+xml', 'image/svg'];
25
- export const DOCUMENT_MIME_TYPES = [
26
- 'application/pdf',
27
- 'application/msword',
28
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
29
- 'application/vnd.ms-excel',
30
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
31
- 'application/vnd.ms-powerpoint',
32
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
33
- 'text/plain',
34
- 'text/csv',
35
- 'text/markdown',
36
- ];
37
- export const ARCHIVE_MIME_TYPES = [
38
- 'application/zip',
39
- 'application/x-zip-compressed',
40
- 'application/x-7z-compressed',
41
- 'application/x-tar',
42
- 'application/gzip',
43
- 'application/json',
44
- ];
274
+ const BLOCKED_IMAGE_MIME_SET = new Set(BLOCKED_IMAGE_MIME_TYPES);
275
+ /** Set of supported image file extensions. */
276
+ export const IMAGE_EXTENSIONS = new Set(Object.values(SUPPORTED_FILE_TYPES).filter((def) => def.category === 'image').map((def) => def.extension));
277
+ /** Set of supported document file extensions. */
278
+ export const DOCUMENT_EXTENSIONS = new Set(Object.values(SUPPORTED_FILE_TYPES).filter((def) => def.category === 'document').map((def) => def.extension));
279
+ /** Set of supported archive file extensions. */
280
+ export const ARCHIVE_EXTENSIONS = new Set(Object.values(SUPPORTED_FILE_TYPES).filter((def) => def.category === 'archive').map((def) => def.extension));
281
+ /** List of supported image MIME types. */
282
+ export const IMAGE_MIME_TYPES = Array.from(new Set(Object.values(SUPPORTED_FILE_TYPES).filter((def) => def.category === 'image').flatMap((def) => def.mimeTypes)));
283
+ /** List of supported document MIME types. */
284
+ export const DOCUMENT_MIME_TYPES = Array.from(new Set(Object.values(SUPPORTED_FILE_TYPES).filter((def) => def.category === 'document').flatMap((def) => def.mimeTypes)));
285
+ /** List of supported archive MIME types. */
286
+ export const ARCHIVE_MIME_TYPES = Array.from(new Set(Object.values(SUPPORTED_FILE_TYPES).filter((def) => def.category === 'archive').flatMap((def) => def.mimeTypes)));
287
+ const IMAGE_MIME_SET = new Set(IMAGE_MIME_TYPES);
288
+ const DOCUMENT_MIME_SET = new Set(DOCUMENT_MIME_TYPES);
289
+ const ARCHIVE_MIME_SET = new Set(ARCHIVE_MIME_TYPES);
290
+ /**
291
+ * Look up a supported file type definition by its extension.
292
+ *
293
+ * @param ext - The extension string with or without leading dot.
294
+ * @returns The matching FileTypeDefinition, or undefined if unsupported.
295
+ */
296
+ export function getFileTypeByExtension(ext) {
297
+ if (!ext)
298
+ return undefined;
299
+ const normalised = ext.replace(/^\./, '').toLowerCase().trim();
300
+ return SUPPORTED_FILE_TYPES[normalised];
301
+ }
302
+ /**
303
+ * Look up a supported file type definition by its declared MIME type.
304
+ *
305
+ * @param mime - The MIME string (e.g. 'image/png' or 'image/jpeg; charset=utf-8').
306
+ * @returns The matching FileTypeDefinition, or undefined if unsupported.
307
+ */
308
+ export function getFileTypeByMime(mime) {
309
+ if (!mime)
310
+ return undefined;
311
+ const normalised = mime.split(';')[0].trim().toLowerCase();
312
+ return Object.values(SUPPORTED_FILE_TYPES).find((def) => def.mimeTypes.some((m) => m.toLowerCase() === normalised));
313
+ }
314
+ /**
315
+ * Extracts a lowercase file extension from a URL string or query parameters.
316
+ *
317
+ * @param url - The URL string to parse.
318
+ * @returns The extracted extension, or null if none was found.
319
+ */
45
320
  export function extensionFromUrl(url) {
46
321
  try {
47
322
  const parsed = new URL(url);
@@ -50,9 +325,9 @@ export function extensionFromUrl(url) {
50
325
  if (dot >= 0 && dot < path.length - 1) {
51
326
  return path.slice(dot + 1).toLowerCase();
52
327
  }
53
- const fm = parsed.searchParams.get('fm') || parsed.searchParams.get('format') || parsed.searchParams.get('ext');
54
- if (fm && /^[a-z0-9]+$/i.test(fm)) {
55
- return fm.toLowerCase();
328
+ const param = parsed.searchParams.get('fm') || parsed.searchParams.get('format') || parsed.searchParams.get('ext');
329
+ if (param && /^[a-z0-9]+$/i.test(param)) {
330
+ return param.toLowerCase();
56
331
  }
57
332
  return null;
58
333
  }
@@ -60,6 +335,13 @@ export function extensionFromUrl(url) {
60
335
  return null;
61
336
  }
62
337
  }
338
+ /**
339
+ * Checks whether a given file extension satisfies an acceptance policy ('image' | 'document' | 'any').
340
+ *
341
+ * @param ext - The file extension.
342
+ * @param accept - The acceptance mode.
343
+ * @returns True if accepted, false otherwise.
344
+ */
63
345
  export function isExtensionAccepted(ext, accept) {
64
346
  if (accept === 'any')
65
347
  return true;
@@ -73,21 +355,23 @@ export function isExtensionAccepted(ext, accept) {
73
355
  return DOCUMENT_EXTENSIONS.has(ext);
74
356
  return false;
75
357
  }
358
+ /**
359
+ * Checks whether a given MIME type satisfies an acceptance policy ('image' | 'document' | 'any').
360
+ *
361
+ * @param mime - The declared MIME string.
362
+ * @param accept - The acceptance mode.
363
+ * @returns True if accepted, false otherwise.
364
+ */
76
365
  export function isMimeAccepted(mime, accept) {
77
- // Normalise: strip parameters (e.g. "image/jpeg; charset=utf-8" → "image/jpeg")
78
366
  const normalised = mime.split(';')[0].trim().toLowerCase();
79
- // Unconditionally reject SVG regardless of accept mode — SVG can carry
80
- // embedded scripts and is rendered by browsers when served inline.
81
- if (BLOCKED_IMAGE_MIME_TYPES.includes(normalised))
367
+ if (BLOCKED_IMAGE_MIME_SET.has(normalised))
82
368
  return false;
83
369
  if (accept === 'any') {
84
- return IMAGE_MIME_TYPES.includes(normalised)
85
- || DOCUMENT_MIME_TYPES.includes(normalised)
86
- || ARCHIVE_MIME_TYPES.includes(normalised);
370
+ return IMAGE_MIME_SET.has(normalised) || DOCUMENT_MIME_SET.has(normalised) || ARCHIVE_MIME_SET.has(normalised);
87
371
  }
88
372
  if (accept === 'image')
89
- return IMAGE_MIME_TYPES.includes(normalised);
373
+ return IMAGE_MIME_SET.has(normalised);
90
374
  if (accept === 'document')
91
- return DOCUMENT_MIME_TYPES.includes(normalised);
375
+ return DOCUMENT_MIME_SET.has(normalised);
92
376
  return false;
93
377
  }
@@ -0,0 +1,34 @@
1
+ /** Pixel dimensions of an image. */
2
+ export interface MediaDimensions {
3
+ readonly width: number;
4
+ readonly height: number;
5
+ }
6
+ /** Output MIME types the transform path may emit. AVIF is deliberately absent (v1). */
7
+ export type ImageOutputMime = 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp';
8
+ /**
9
+ * A fully resolved transformation. Every number here comes from a pre-registered preset or from
10
+ * MEDIA_QUALITY_VALUES — never from the request.
11
+ */
12
+ export interface ImageTransformSpec {
13
+ readonly width: number;
14
+ /** Present for crop presets only; scale presets derive height from the source aspect ratio. */
15
+ readonly height?: number;
16
+ readonly fit: 'cover' | 'scale-down';
17
+ readonly outputMime: ImageOutputMime;
18
+ readonly quality: number;
19
+ }
20
+ export interface TransformedImage {
21
+ readonly body: ReadableStream<Uint8Array>;
22
+ readonly contentType: string;
23
+ }
24
+ /**
25
+ * Port for edge image transformation. The API injects a Cloudflare Images adapter when the
26
+ * `IMAGES` binding exists and `null` otherwise; handlers never see the binding itself.
27
+ */
28
+ export interface IImageTransformer {
29
+ /** Reads the source's pixel dimensions. Rejects when the stream is not a raster image. */
30
+ probe(source: ReadableStream<Uint8Array>): Promise<MediaDimensions>;
31
+ /** Applies the spec and returns the encoded variant. */
32
+ transform(source: ReadableStream<Uint8Array>, spec: ImageTransformSpec): Promise<TransformedImage>;
33
+ }
34
+ //# sourceMappingURL=image-transformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-transformer.d.ts","sourceRoot":"","sources":["../../src/media/image-transformer.ts"],"names":[],"mappings":"AAGA,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,uFAAuF;AACvF,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,CAAA;AAErF;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,+FAA+F;IAC/F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,0FAA0F;IAC1F,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IACnE,wDAAwD;IACxD,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;CACnG"}
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2024–2026 Flavio De Musso
3
+ export {};
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Result of a file magic bytes signature validation.
3
+ */
4
+ export interface MagicBytesValidationResult {
5
+ /** Whether the byte buffer matches the declared format signature. */
6
+ valid: boolean;
7
+ /** Detected canonical primary MIME type if valid or identified. */
8
+ detectedMime?: string;
9
+ /** Human-readable error description when validation fails. */
10
+ error?: string;
11
+ }
12
+ /**
13
+ * Validates that an uploaded file's binary content matches its declared MIME type,
14
+ * protecting against MIME-spoofing, disguised executables, and blocked formats (e.g. SVG).
15
+ *
16
+ * @param buffer - The raw binary buffer (ArrayBuffer or Uint8Array).
17
+ * @param declaredMime - The client-declared MIME type string.
18
+ * @returns A MagicBytesValidationResult indicating validity and details.
19
+ */
20
+ export declare function verifyMagicBytes(buffer: ArrayBuffer | Uint8Array, declaredMime: string): MagicBytesValidationResult;
21
+ //# sourceMappingURL=magic-bytes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"magic-bytes.d.ts","sourceRoot":"","sources":["../../src/media/magic-bytes.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAA;IACd,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAiBD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,GAAG,UAAU,EAChC,YAAY,EAAE,MAAM,GACnB,0BAA0B,CAgD5B"}