{"_id":"@bloklabs/presets","_rev":"7-383d6cbb552704dda983e872b1af5257","name":"@bloklabs/presets","dist-tags":{"latest":"1.15.2"},"versions":{"1.11.0":{"name":"@bloklabs/presets","version":"1.11.0","keywords":["blok","block-editor","storage","file-upload","uploader","supabase","s3","cloudinary","indexeddb","typescript"],"author":{"name":"JackUait"},"license":"Apache-2.0","_id":"@bloklabs/presets@1.11.0","maintainers":[{"name":"jackuait","email":"jackuait@bk.ru"}],"homepage":"https://blokeditor.com","bugs":{"url":"https://github.com/JackUait/blok/issues"},"dist":{"shasum":"899abbe61ec909cf8e2f95e03d3f6d7750a0bf38","tarball":"https://registry.npmjs.org/@bloklabs/presets/-/presets-1.11.0.tgz","fileCount":5,"integrity":"sha512-nAGN9zKjgfN1DxRkhlBvEsvaxw/WJYZBQhC54/6aSqnt486sZ4AbZS/b3WUw+Uy/bDXTiXYG19TMcaJiQrkBpQ==","signatures":[{"sig":"MEUCIQDctAVydYkXr8vdN5CRwGKZaY4LHpD2/8qvQ8PkPTevpgIgFZpIZDuTkffrDLyFE7HdEvjCDhATbormSGtG6jeuJSg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27963},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/bloklabs-presets-1.11.0.tgz","types":"./types/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./types/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"yarn run -T vitest run","build":"yarn run -T vite build --mode production"},"_npmUser":{"name":"jackuait","email":"jackuait@bk.ru"},"_resolved":"/tmp/bloklabs-presets-1.11.0.tgz","_integrity":"sha512-nAGN9zKjgfN1DxRkhlBvEsvaxw/WJYZBQhC54/6aSqnt486sZ4AbZS/b3WUw+Uy/bDXTiXYG19TMcaJiQrkBpQ==","repository":{"url":"git+https://github.com/JackUait/blok.git","type":"git","directory":"packages/presets"},"_npmVersion":"11.6.2","description":"Storage presets for Blok — ready-made uploaders for Supabase, S3-compatible storage, Cloudinary, and IndexedDB.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"fake-indexeddb":"^6.2.5"},"_npmOperationalInternal":{"tmp":"tmp/presets_1.11.0_1787607324566_0.1375490620316926","host":"s3://npm-registry-packages-npm-production"}},"1.12.0":{"name":"@bloklabs/presets","version":"1.12.0","keywords":["blok","block-editor","storage","file-upload","uploader","supabase","s3","cloudinary","indexeddb","typescript"],"author":{"name":"JackUait"},"license":"Apache-2.0","_id":"@bloklabs/presets@1.12.0","maintainers":[{"name":"jackuait","email":"jackuait@bk.ru"}],"homepage":"https://blokeditor.com","bugs":{"url":"https://github.com/JackUait/blok/issues"},"dist":{"shasum":"2459417bbdc08ac1f2dd0fb451e277fb0b19d0d2","tarball":"https://registry.npmjs.org/@bloklabs/presets/-/presets-1.12.0.tgz","fileCount":5,"integrity":"sha512-21BjI7tDvyHrTDdwr6mRnk2U1/zZ57bc87BB/pOQKPd5MzEWEAyZ4wx023WMv0i2pTg1u6liNE1RGmNfGkEyzA==","signatures":[{"sig":"MEYCIQC6m5awKI/JZcFi2+slFcoxmz9XqGs8RdTwF97iVhyI+AIhAMgHdGOu+Q92oTJAJ2Ddgi6WQp4L30fxLXOkpuXH95fw","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27963},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/bloklabs-presets-1.12.0.tgz","types":"./types/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./types/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"yarn run -T vitest run","build":"yarn run -T vite build --mode production"},"_npmUser":{"name":"jackuait","email":"jackuait@bk.ru"},"_resolved":"/tmp/bloklabs-presets-1.12.0.tgz","_integrity":"sha512-21BjI7tDvyHrTDdwr6mRnk2U1/zZ57bc87BB/pOQKPd5MzEWEAyZ4wx023WMv0i2pTg1u6liNE1RGmNfGkEyzA==","repository":{"url":"git+https://github.com/JackUait/blok.git","type":"git","directory":"packages/presets"},"_npmVersion":"11.6.2","description":"Storage presets for Blok — ready-made uploaders for Supabase, S3-compatible storage, Cloudinary, and IndexedDB.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"fake-indexeddb":"^6.2.5"},"_npmOperationalInternal":{"tmp":"tmp/presets_1.12.0_1787734245368_0.07647070547616508","host":"s3://npm-registry-packages-npm-production"}},"1.13.0":{"name":"@bloklabs/presets","version":"1.13.0","keywords":["blok","block-editor","storage","file-upload","uploader","supabase","s3","cloudinary","indexeddb","typescript"],"author":{"name":"JackUait"},"license":"Apache-2.0","_id":"@bloklabs/presets@1.13.0","maintainers":[{"name":"jackuait","email":"jackuait@bk.ru"}],"homepage":"https://blokeditor.com","bugs":{"url":"https://github.com/JackUait/blok/issues"},"dist":{"shasum":"4977c05bd4c2339a61e6abe0338fd0c319c7cc25","tarball":"https://registry.npmjs.org/@bloklabs/presets/-/presets-1.13.0.tgz","fileCount":5,"integrity":"sha512-kLsepPgCwdutcZkOqB0d7NvA+vjNAvOv+lCsLUs0Jnig7EH/S/yA8ZcYEMotJF1Jv7U7gIasnePiYgMRtrl3bw==","signatures":[{"sig":"MEUCIQDYrd1OmJAcX3SdPEgRMq9n1vJf1KFj3aEbD3budQeMzAIgNt1e6wpH/Ne2Yr1x9C0vc9x45i6zg5IhKyUJA5+Dpnk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDN6Xtt6PZdUfCReZq603iypKYU6QuurMOX1mS/vMp7yAIhAIf4R4LlOnv4RNRpaP3il6lGQHMtDRkjTxFJVNjsXeX6","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29310},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/bloklabs-presets-1.13.0.tgz","types":"./types/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./types/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"yarn run -T vitest run","build":"yarn run -T vite build --mode production"},"_npmUser":{"name":"jackuait","email":"jackuait@bk.ru"},"_resolved":"/tmp/bloklabs-presets-1.13.0.tgz","_integrity":"sha512-kLsepPgCwdutcZkOqB0d7NvA+vjNAvOv+lCsLUs0Jnig7EH/S/yA8ZcYEMotJF1Jv7U7gIasnePiYgMRtrl3bw==","repository":{"url":"git+https://github.com/JackUait/blok.git","type":"git","directory":"packages/presets"},"_npmVersion":"11.6.2","description":"Storage presets for Blok — ready-made uploaders for Supabase, S3-compatible storage, Cloudinary, and IndexedDB.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"fake-indexeddb":"^6.2.5"},"_npmOperationalInternal":{"tmp":"tmp/presets_1.13.0_1788467918699_0.2602440922345308","host":"s3://npm-registry-packages-npm-production"}},"1.14.0":{"name":"@bloklabs/presets","version":"1.14.0","keywords":["blok","block-editor","storage","file-upload","uploader","supabase","s3","cloudinary","indexeddb","typescript"],"author":{"name":"JackUait"},"license":"Apache-2.0","_id":"@bloklabs/presets@1.14.0","maintainers":[{"name":"jackuait","email":"jackuait@bk.ru"}],"homepage":"https://blokeditor.com","bugs":{"url":"https://github.com/JackUait/blok/issues"},"dist":{"shasum":"1079b63173c8e6fd95df3e8d757b103d6c1d7dbd","tarball":"https://registry.npmjs.org/@bloklabs/presets/-/presets-1.14.0.tgz","fileCount":5,"integrity":"sha512-8Tmhxe1lR31iFb9BMWRycSLq8rkhyNJaUMr5BZ3U9v8e0j5QWx9CeQ80cvYA3R6OL4puSeR9XyhTzi0m/0lCqQ==","signatures":[{"sig":"MEUCIQDUybuUEJQ6heA0VwLvBMV7Zz+5F/7ScyWsRfIoxspdEgIgGxBzKTTjAubdT/RK1bFrMb2/VIQeIO+vubqI+1235+Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIG/hhq/drYJ+NwrDv526/HdFcVn2nQpI562UWtBnaFOAAiAs7r+DVvgW81EkB0U9l4j5SukQmjuDmuqWDBQGOTKqnQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29290},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/bloklabs-presets-1.14.0.tgz","types":"./types/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./types/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"yarn run -T vitest run","build":"yarn run -T vite build --mode production"},"_npmUser":{"name":"jackuait","email":"jackuait@bk.ru"},"_resolved":"/tmp/bloklabs-presets-1.14.0.tgz","_integrity":"sha512-8Tmhxe1lR31iFb9BMWRycSLq8rkhyNJaUMr5BZ3U9v8e0j5QWx9CeQ80cvYA3R6OL4puSeR9XyhTzi0m/0lCqQ==","repository":{"url":"git+https://github.com/JackUait/blok.git","type":"git","directory":"packages/presets"},"_npmVersion":"11.6.2","description":"Storage presets for Blok — ready-made uploaders for Supabase, S3-compatible storage, Cloudinary, and IndexedDB.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"fake-indexeddb":"^6.2.5"},"_npmOperationalInternal":{"tmp":"tmp/presets_1.14.0_1789514087448_0.27484001257286605","host":"s3://npm-registry-packages-npm-production"}},"1.15.0":{"name":"@bloklabs/presets","version":"1.15.0","keywords":["blok","block-editor","storage","file-upload","uploader","supabase","s3","cloudinary","indexeddb","typescript"],"author":{"name":"JackUait"},"license":"Apache-2.0","_id":"@bloklabs/presets@1.15.0","maintainers":[{"name":"jackuait","email":"jackuait@bk.ru"}],"homepage":"https://blokeditor.com","bugs":{"url":"https://github.com/JackUait/blok/issues"},"dist":{"shasum":"093c85ec0c2af59ac42de4ab5f89487848a2858c","tarball":"https://registry.npmjs.org/@bloklabs/presets/-/presets-1.15.0.tgz","fileCount":5,"integrity":"sha512-iz3GCKtAmVJPEyI9bOD23omIGCWRv581B0/RROk3+L0m1fJbIJPH0du7G3BDGmQPzTAiu4GTd6uELaLAnWUgZg==","signatures":[{"sig":"MEYCIQC47L9Eizw43Pc4nEDpXerBCNPkRKdixF+BJHMkVr1K+wIhAKCSEKak7MJdaAazG34h4xpdNYtC9Ke/mvkafMLCQUYg","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHDIiJaqsZ2MtbwXWMQgjQ8if032XBcOxZmszRNR4EhrAiEAk4FADV4ijIR3rHSJMbHrmqFhdkj5qmuSq4MRm4hs0rI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29290},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/bloklabs-presets-1.15.0.tgz","types":"./types/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./types/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"yarn run -T vitest run","build":"yarn run -T vite build --mode production"},"_npmUser":{"name":"jackuait","email":"jackuait@bk.ru"},"_resolved":"/tmp/bloklabs-presets-1.15.0.tgz","_integrity":"sha512-iz3GCKtAmVJPEyI9bOD23omIGCWRv581B0/RROk3+L0m1fJbIJPH0du7G3BDGmQPzTAiu4GTd6uELaLAnWUgZg==","repository":{"url":"git+https://github.com/JackUait/blok.git","type":"git","directory":"packages/presets"},"_npmVersion":"11.6.2","description":"Storage presets for Blok — ready-made uploaders for Supabase, S3-compatible storage, Cloudinary, and IndexedDB.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"fake-indexeddb":"^6.2.5"},"_npmOperationalInternal":{"tmp":"tmp/presets_1.15.0_1789566596330_0.489647817950551","host":"s3://npm-registry-packages-npm-production"}},"1.15.1":{"name":"@bloklabs/presets","version":"1.15.1","keywords":["blok","block-editor","storage","file-upload","uploader","supabase","s3","cloudinary","indexeddb","typescript"],"author":{"name":"JackUait"},"license":"Apache-2.0","_id":"@bloklabs/presets@1.15.1","maintainers":[{"name":"jackuait","email":"jackuait@bk.ru"}],"homepage":"https://blokeditor.com","bugs":{"url":"https://github.com/JackUait/blok/issues"},"dist":{"shasum":"d4587d6afb934da9a866fc8ff8e0a3e2824265d6","tarball":"https://registry.npmjs.org/@bloklabs/presets/-/presets-1.15.1.tgz","fileCount":5,"integrity":"sha512-4mMJRnB2Euva5Pwnuu7TpmjBZJ3NJCEQnRE/j/xr8T1qKZMpwM5t+HlgsTJf2Bueiz8pKcqpqtdFy38PoEY+bw==","signatures":[{"sig":"MEQCIDhko0PmJfjC+EZu/K15knEbA8Dlh+TQJhUuFSxGMudaAiBl3hx8bdHRyid3m6pozpHNv0QMYCwp98BG62jXdZQ/kw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDe1KoH2mPGjiMOX7MKb47bzDJ8o+dH95fNysEiwMzYFwIhALR2sb4I1gRU5IQasb5ynkLCeJoscYqxE3O8ZOQzFDLB","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29290},"main":"./dist/index.cjs","type":"module","_from":"file:/tmp/bloklabs-presets-1.15.1.tgz","types":"./types/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./types/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"test":"yarn run -T vitest run","build":"yarn run -T vite build --mode production"},"_npmUser":{"name":"jackuait","email":"jackuait@bk.ru"},"_resolved":"/tmp/bloklabs-presets-1.15.1.tgz","_integrity":"sha512-4mMJRnB2Euva5Pwnuu7TpmjBZJ3NJCEQnRE/j/xr8T1qKZMpwM5t+HlgsTJf2Bueiz8pKcqpqtdFy38PoEY+bw==","repository":{"url":"git+https://github.com/JackUait/blok.git","type":"git","directory":"packages/presets"},"_npmVersion":"11.6.2","description":"Storage presets for Blok — ready-made uploaders for Supabase, S3-compatible storage, Cloudinary, and IndexedDB.","directories":{},"sideEffects":false,"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"fake-indexeddb":"^6.2.5"},"_npmOperationalInternal":{"tmp":"tmp/presets_1.15.1_1789582935831_0.25034261139694913","host":"s3://npm-registry-packages-npm-production"}},"1.15.2":{"_id":"@bloklabs/presets@1.15.2","bugs":{"url":"https://github.com/JackUait/blok/issues"},"dist":{"shasum":"1a09d8da157e37200d8045647eff0b926ca40146","tarball":"https://registry.npmjs.org/@bloklabs/presets/-/presets-1.15.2.tgz","fileCount":5,"integrity":"sha512-U0oOt8MbqDk0gsLIIemBjGDkVy70hps2tMiQE09enLak0WiV7HM5sMg8iLbXcyw5ug9qnBRb9zBi/e92pqgg9w==","signatures":[{"sig":"MEQCIAzYSQfyfMfHRHActHj0VzdY/jo/W1+Hhjf5hmxJQaUkAiAFJ/KduksHQ+G8XkxUqviyOoze61XmzR1nbZEuqDTG8Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDwbwWoZ6+4YL6V4fM6oAySslJscUTuZzjnOspfKJStKQIgPqSeZHotVgq26ZXbY5WLsg1sp1ptCWYHoSPlBEPZNdc="}],"unpackedSize":29290},"main":"./dist/index.cjs","name":"@bloklabs/presets","type":"module","_from":"file:/tmp/bloklabs-presets-1.15.2.tgz","types":"./types/index.d.ts","author":{"name":"JackUait"},"module":"./dist/index.mjs","exports":{".":{"types":"./types/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"license":"Apache-2.0","scripts":{"test":"yarn run -T vitest run","build":"yarn run -T vite build --mode production"},"version":"1.15.2","_npmUser":{"name":"jackuait","email":"jackuait@bk.ru"},"homepage":"https://blokeditor.com","keywords":["blok","block-editor","storage","file-upload","uploader","supabase","s3","cloudinary","indexeddb","typescript"],"_resolved":"/tmp/bloklabs-presets-1.15.2.tgz","_integrity":"sha512-U0oOt8MbqDk0gsLIIemBjGDkVy70hps2tMiQE09enLak0WiV7HM5sMg8iLbXcyw5ug9qnBRb9zBi/e92pqgg9w==","repository":{"url":"git+https://github.com/JackUait/blok.git","type":"git","directory":"packages/presets"},"_npmVersion":"11.6.2","description":"Storage presets for Blok — ready-made uploaders for Supabase, S3-compatible storage, Cloudinary, and IndexedDB.","directories":{},"maintainers":[{"name":"jackuait","email":"jackuait@bk.ru"}],"sideEffects":false,"_nodeVersion":"24.13.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"fake-indexeddb":"^6.2.5"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/presets_1.15.2_1789608009568_0.31304379436032903"}}},"time":{"created":"2026-08-24T21:35:24.346Z","modified":"2026-09-17T01:20:09.840Z","1.11.0":"2026-08-24T21:35:24.758Z","1.12.0":"2026-08-26T08:50:45.525Z","1.13.0":"2026-09-03T20:38:38.788Z","1.14.0":"2026-09-15T23:14:47.534Z","1.15.0":"2026-09-16T13:49:56.416Z","1.15.1":"2026-09-16T18:22:15.920Z","1.15.2":"2026-09-17T01:20:09.649Z"},"bugs":{"url":"https://github.com/JackUait/blok/issues"},"author":{"name":"JackUait"},"license":"Apache-2.0","homepage":"https://blokeditor.com","keywords":["blok","block-editor","storage","file-upload","uploader","supabase","s3","cloudinary","indexeddb","typescript"],"repository":{"url":"git+https://github.com/JackUait/blok.git","type":"git","directory":"packages/presets"},"description":"Storage presets for Blok — ready-made uploaders for Supabase, S3-compatible storage, Cloudinary, and IndexedDB.","maintainers":[{"name":"jackuait","email":"jackuait@bk.ru"}],"readme":"# @bloklabs/presets\n\nReady-made [`uploader`](https://blokeditor.com/docs/uploader-api) implementations for [Blok](https://blokeditor.com). Plug in storage you already have instead of writing an upload handler yourself. Five presets ship today: Supabase, S3-compatible storage (presigned URLs), Cloudinary, a generic fetch endpoint, and IndexedDB.\n\n## Install\n\n```bash\nnpm install @bloklabs/presets @bloklabs/core\n```\n\n## What a preset is\n\nBlok's `uploader` config option takes an object shaped like this. Store the file, return where it landed:\n\n```ts\nimport { Blok } from '@bloklabs/core';\n\nnew Blok({\n  holder: 'editor',\n  uploader: {\n    async uploadByFile(file, { kind }) {\n      const res = await fetch(`/upload/${kind}`, { method: 'POST', body: file });\n      return { url: (await res.json()).url };\n    },\n  },\n});\n```\n\nWithout an `uploadByFile`, an uploaded asset becomes a `blob:` URL. That URL does not survive a reload, so most projects need to configure one. Each preset in this package implements that shape for one storage backend. Import a preset instead of writing `uploadByFile` yourself.\n\n## Which preset, and what it needs\n\n| Preset | Re-hosts a pasted URL? | Needs on the storage side |\n| --- | --- | --- |\n| `fetchStorage` | **Yes** — your endpoint fetches it server-side | A backend answering `POST /upload` and `POST /upload-by-url` |\n| `supabaseStorage` | No | A Storage bucket, made public (or an anon SELECT policy), plus an INSERT policy |\n| `presignedStorage` | No | A backend that mints presigned PUT URLs, and a CORS rule on the bucket allowing PUT |\n| `cloudinaryStorage` | **Yes** — Cloudinary fetches it itself | An **unsigned** upload preset in the Cloudinary dashboard |\n| `indexedDBStorage` | No | Nothing — see the warning below |\n\nOnly `fetchStorage` and `cloudinaryStorage` can turn a pasted remote URL into a re-hosted copy. Both have something that fetches the URL on the server side, either your endpoint or Cloudinary's. The other three cannot. A browser is not allowed to fetch a third-party URL and re-upload it itself. Their `uploadByUrl` is deliberately left undefined rather than faked. Blok then falls back to its documented behavior and stores the pasted URL verbatim.\n\n### fetchStorage\n\n```ts\nimport { fetchStorage } from '@bloklabs/presets';\n\nnew Blok({ holder: 'editor', uploader: fetchStorage({ baseUrl: 'https://api.myapp.com' }) });\n```\n\nYour own backend does the actual storing. This preset only calls it. The backend must answer `POST {baseUrl}/upload` (multipart) and `POST {baseUrl}/upload-by-url` (`{ url }` JSON). Both return `{ url, fileName? }`. The URL you receive on `/upload-by-url` is user-supplied. Validate it server-side and block requests to internal or private addresses before fetching. Otherwise the endpoint becomes an SSRF vector.\n\n### supabaseStorage\n\n```ts\nimport { createClient } from '@supabase/supabase-js';\nimport { supabaseStorage } from '@bloklabs/presets';\n\nconst supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);\nnew Blok({ holder: 'editor', uploader: supabaseStorage(supabase, { bucket: 'blok' }) });\n```\n\nCreate the bucket first (default name `\"blok\"`). Make it public or add an anon `SELECT` policy. This preset returns `getPublicUrl()` directly, so an unreadable object is a broken image. Then add an `INSERT` policy for whichever role the client authenticates as.\n\n### presignedStorage\n\n```ts\nimport { presignedStorage } from '@bloklabs/presets';\n\nnew Blok({ holder: 'editor', uploader: presignedStorage({ sign: (request) => api.sign(request) }) });\n```\n\nFor S3, R2, MinIO, or any S3-compatible store. `sign` is your function. It gets `{ fileName, mimeType, size, kind }` and returns a presigned `{ uploadUrl, publicUrl, headers? }` from your backend. The browser then `PUT`s the file straight to `uploadUrl`. So the bucket needs a CORS rule allowing `PUT` (and `Content-Type`) from your app's origin. That CORS rule is the part that actually blocks people.\n\n### cloudinaryStorage\n\n```ts\nimport { cloudinaryStorage } from '@bloklabs/presets';\n\nnew Blok({\n  holder: 'editor',\n  uploader: cloudinaryStorage({ cloudName: 'my-cloud', uploadPreset: 'blok-unsigned' }),\n});\n```\n\n`uploadPreset` must be **unsigned** (Cloudinary dashboard → Settings → Upload → Upload presets). A signed preset needs a server to sign the request. That defeats the point of a preset with no backend.\n\n### indexedDBStorage\n\n```ts\nimport { indexedDBStorage, resolveBlokObjectUrl } from '@bloklabs/presets';\n\nnew Blok({ holder: 'editor', uploader: indexedDBStorage() });\n\n// Wherever you render a stored asset's url, e.g. an <img src>:\nconst displayUrl = await resolveBlokObjectUrl(asset.url);\n```\n\n**Not for production.** This preset stores uploaded bytes in the visitor's own browser via IndexedDB. They are gone on another device, in another browser, or the moment the user clears site data. Nothing is actually shared or backed up.\n\nIt exists because Blok's built-in fallback (a `blob:` URL) does not even survive a page reload. Before you wire up real storage, that makes local demos and prototypes look broken.\n\n`uploadByFile` returns a `blok:asset/…` reference, not a directly usable URL. Resolve it with `resolveBlokObjectUrl` wherever you render an uploaded asset.\n\nIf you pass a custom `dbName` to `indexedDBStorage()`, pass the same `dbName` to `resolveBlokObjectUrl(url, { dbName })`. A mismatch resolves to `null` with no error, not a thrown exception.\n\nEach call to `resolveBlokObjectUrl` mints a fresh `blob:` URL. Nothing is cached, and nothing is revoked. Call `URL.revokeObjectURL()` yourself once a displayed asset is no longer needed. Otherwise a view that re-renders it repeatedly will leak memory.\n\n## Docs\n\n- [Uploader API reference](https://blokeditor.com/docs/uploader-api)\n- [Storage presets guide](https://blokeditor.com/presets)\n\nLicensed under Apache-2.0.\n","readmeFilename":"README.md"}