@thebes/cadmus-cloudflare-images 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BowenLabs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @thebes/cadmus-cloudflare-images
2
+
3
+ A [Cadmus](https://github.com/bowenlabs/project-thebes) **adapter** — an
4
+ alternate `ImageService` (from `@thebes/cadmus/storage`) backed by
5
+ [Cloudflare Image Resizing](https://developers.cloudflare.com/images/transform-images/).
6
+
7
+ This is the *adapter* extension axis: a swappable implementation of an
8
+ interface Cadmus already defines. Uploads still land in R2 and the database
9
+ still stores the **original** R2 URL — only `render()` changes, returning
10
+ responsive `/cdn-cgi/image/...` transform URLs instead of a pass-through `src`.
11
+
12
+ ```bash
13
+ pnpm add @thebes/cadmus-cloudflare-images
14
+ ```
15
+
16
+ ## Swap it in
17
+
18
+ Because every call site resolves its image service through one selection point
19
+ (e.g. `app/core/lib/image-service.ts`), switching is a one-line change — no
20
+ component, renderer, or stored data changes:
21
+
22
+ ```ts
23
+ import { createCloudflareImageService } from "@thebes/cadmus-cloudflare-images";
24
+
25
+ export function createImageService(bucket: R2Bucket, mediaUrl: string) {
26
+ return createCloudflareImageService({ bucket, mediaUrl });
27
+ }
28
+ ```
29
+
30
+ ## API
31
+
32
+ ```ts
33
+ createCloudflareImageService({
34
+ bucket, // R2Bucket — where originals are uploaded
35
+ mediaUrl, // public base URL for originals (R2 custom domain)
36
+ deliveryUrl, // origin that serves /cdn-cgi/image (default: mediaUrl)
37
+ widths, // srcset widths (default: 320…1920)
38
+ sizes, // sizes attribute (default: "100vw")
39
+ quality, // 1–100 (default: 80)
40
+ })
41
+ ```
42
+
43
+ `render({ url, width?, height?, alt })` returns `{ src, srcset?, sizes? }`. With
44
+ no explicit `width`/`height` it emits a full responsive `srcset`; a fixed
45
+ `width`/`height` pins a single rendition (no `srcset`). `upload(file)` validates
46
+ via `validateImageFile`, stores the original in R2, and returns its original
47
+ URL.
48
+
49
+ > Requires a Cloudflare zone with Image Resizing enabled on the delivery
50
+ > origin. Available on paid plans — see Cloudflare's docs.
51
+
52
+ ## License
53
+
54
+ MIT © BowenLabs
package/dist/index.cjs ADDED
@@ -0,0 +1,59 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _thebes_cadmus_storage = require("@thebes/cadmus/storage");
3
+ //#region src/index.ts
4
+ const DEFAULT_WIDTHS = [
5
+ 320,
6
+ 640,
7
+ 960,
8
+ 1280,
9
+ 1920
10
+ ];
11
+ function safeExtension(filename) {
12
+ const match = /\.([a-zA-Z0-9]{1,5})$/.exec(filename);
13
+ return match ? `.${match[1].toLowerCase()}` : "";
14
+ }
15
+ /** Builds a Cloudflare Image Resizing URL:
16
+ * `${deliveryUrl}/cdn-cgi/image/<options>/<source>`. */
17
+ function transformUrl(deliveryUrl, source, opts) {
18
+ const params = [`format=auto`, `quality=${opts.quality}`];
19
+ if (opts.width) params.push(`width=${opts.width}`);
20
+ if (opts.height) params.push(`height=${opts.height}`);
21
+ return `${deliveryUrl}/cdn-cgi/image/${params.join(",")}/${source}`;
22
+ }
23
+ /**
24
+ * Creates an `ImageService` that uploads to R2 and renders responsive
25
+ * Cloudflare Image Resizing URLs. Drop-in replacement for the default R2
26
+ * pass-through service — the database still stores the original R2 URL.
27
+ */
28
+ function createCloudflareImageService(options) {
29
+ const { bucket, mediaUrl, deliveryUrl = mediaUrl, widths = DEFAULT_WIDTHS, sizes = "100vw", quality = 80 } = options;
30
+ return {
31
+ async upload(file) {
32
+ (0, _thebes_cadmus_storage.validateImageFile)(file);
33
+ const key = `${crypto.randomUUID()}${safeExtension(file.name)}`;
34
+ await bucket.put(key, file);
35
+ return { url: `${mediaUrl}/${key}` };
36
+ },
37
+ render({ url, width, height }) {
38
+ const largest = widths[widths.length - 1];
39
+ const src = transformUrl(deliveryUrl, url, {
40
+ width: width ?? largest,
41
+ height,
42
+ quality
43
+ });
44
+ if (width || height) return { src };
45
+ return {
46
+ src,
47
+ srcset: widths.map((w) => `${transformUrl(deliveryUrl, url, {
48
+ width: w,
49
+ quality
50
+ })} ${w}w`).join(", "),
51
+ sizes
52
+ };
53
+ }
54
+ };
55
+ }
56
+ //#endregion
57
+ exports.createCloudflareImageService = createCloudflareImageService;
58
+
59
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2026 BowenLabs. All rights reserved.\n// MIT licensed. See LICENSE in the repo root.\n//\n// @thebes/cadmus-cloudflare-images\n//\n// A Cadmus *adapter* (the swappable-implementation axis): an alternate\n// `ImageService` (from @thebes/cadmus/storage) backed by Cloudflare\n// Image Resizing. Uploads still land in R2 and the database still stores\n// the original R2 URL — only `render()` differs, returning responsive\n// `/cdn-cgi/image/...` transform URLs instead of a pass-through `src`.\n//\n// Swap it in without touching any component or block data:\n//\n// import { createCloudflareImageService } from \"@thebes/cadmus-cloudflare-images\";\n// const images = createCloudflareImageService({ bucket: env.R2, mediaUrl: env.MEDIA_URL });\n\nimport type { ImageService, RenderedImage } from \"@thebes/cadmus/storage\";\nimport { validateImageFile } from \"@thebes/cadmus/storage\";\n\nexport interface CloudflareImagesOptions {\n /** R2 bucket originals are uploaded to. */\n bucket: R2Bucket;\n /** Public base URL for original objects (an R2 custom domain), no\n * trailing slash. Stored in the DB and used as the transform source. */\n mediaUrl: string;\n /**\n * Origin that serves `/cdn-cgi/image/...` (a zone with Image Resizing\n * enabled). Defaults to `mediaUrl`. No trailing slash.\n */\n deliveryUrl?: string;\n /** Widths emitted in `srcset`. Defaults to a sensible responsive set. */\n widths?: number[];\n /** `sizes` attribute value. Defaults to `100vw`. */\n sizes?: string;\n /** Output quality (1–100). Defaults to 80. */\n quality?: number;\n}\n\nconst DEFAULT_WIDTHS = [320, 640, 960, 1280, 1920];\n\nfunction safeExtension(filename: string): string {\n const match = /\\.([a-zA-Z0-9]{1,5})$/.exec(filename);\n return match ? `.${match[1].toLowerCase()}` : \"\";\n}\n\n/** Builds a Cloudflare Image Resizing URL:\n * `${deliveryUrl}/cdn-cgi/image/<options>/<source>`. */\nfunction transformUrl(\n deliveryUrl: string,\n source: string,\n opts: { width?: number; height?: number; quality: number },\n): string {\n const params = [`format=auto`, `quality=${opts.quality}`];\n if (opts.width) params.push(`width=${opts.width}`);\n if (opts.height) params.push(`height=${opts.height}`);\n return `${deliveryUrl}/cdn-cgi/image/${params.join(\",\")}/${source}`;\n}\n\n/**\n * Creates an `ImageService` that uploads to R2 and renders responsive\n * Cloudflare Image Resizing URLs. Drop-in replacement for the default R2\n * pass-through service — the database still stores the original R2 URL.\n */\nexport function createCloudflareImageService(\n options: CloudflareImagesOptions,\n): ImageService {\n const {\n bucket,\n mediaUrl,\n deliveryUrl = mediaUrl,\n widths = DEFAULT_WIDTHS,\n sizes = \"100vw\",\n quality = 80,\n } = options;\n\n return {\n async upload(file) {\n // Defense-in-depth — callers should validate first, but upload() is\n // reachable directly too.\n validateImageFile(file);\n const key = `${crypto.randomUUID()}${safeExtension(file.name)}`;\n await bucket.put(key, file);\n // Store the ORIGINAL URL, never a transform URL (see CLAUDE.md\n // \"Image service interface\").\n return { url: `${mediaUrl}/${key}` };\n },\n\n render({ url, width, height }): RenderedImage {\n const largest = widths[widths.length - 1];\n const src = transformUrl(deliveryUrl, url, {\n width: width ?? largest,\n height,\n quality,\n });\n // A fixed width/height pins the rendition, so a srcset would be\n // misleading — emit just the single transformed src.\n if (width || height) {\n return { src };\n }\n const srcset = widths\n .map(\n (w) =>\n `${transformUrl(deliveryUrl, url, { width: w, quality })} ${w}w`,\n )\n .join(\", \");\n return { src, srcset, sizes };\n },\n };\n}\n"],"mappings":";;;AAsCA,MAAM,iBAAiB;CAAC;CAAK;CAAK;CAAK;CAAM;AAAI;AAEjD,SAAS,cAAc,UAA0B;CAC/C,MAAM,QAAQ,wBAAwB,KAAK,QAAQ;CACnD,OAAO,QAAQ,IAAI,MAAM,EAAE,CAAC,YAAY,MAAM;AAChD;;;AAIA,SAAS,aACP,aACA,QACA,MACQ;CACR,MAAM,SAAS,CAAC,eAAe,WAAW,KAAK,SAAS;CACxD,IAAI,KAAK,OAAO,OAAO,KAAK,SAAS,KAAK,OAAO;CACjD,IAAI,KAAK,QAAQ,OAAO,KAAK,UAAU,KAAK,QAAQ;CACpD,OAAO,GAAG,YAAY,iBAAiB,OAAO,KAAK,GAAG,EAAE,GAAG;AAC7D;;;;;;AAOA,SAAgB,6BACd,SACc;CACd,MAAM,EACJ,QACA,UACA,cAAc,UACd,SAAS,gBACT,QAAQ,SACR,UAAU,OACR;CAEJ,OAAO;EACL,MAAM,OAAO,MAAM;GAGjB,CAAA,GAAA,uBAAA,kBAAA,CAAkB,IAAI;GACtB,MAAM,MAAM,GAAG,OAAO,WAAW,IAAI,cAAc,KAAK,IAAI;GAC5D,MAAM,OAAO,IAAI,KAAK,IAAI;GAG1B,OAAO,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM;EACrC;EAEA,OAAO,EAAE,KAAK,OAAO,UAAyB;GAC5C,MAAM,UAAU,OAAO,OAAO,SAAS;GACvC,MAAM,MAAM,aAAa,aAAa,KAAK;IACzC,OAAO,SAAS;IAChB;IACA;GACF,CAAC;GAGD,IAAI,SAAS,QACX,OAAO,EAAE,IAAI;GAQf,OAAO;IAAE;IAAK,QANC,OACZ,KACE,MACC,GAAG,aAAa,aAAa,KAAK;KAAE,OAAO;KAAG;IAAQ,CAAC,EAAE,GAAG,EAAE,EAClE,CAAC,CACA,KAAK,IACW;IAAG;GAAM;EAC9B;CACF;AACF"}
@@ -0,0 +1,30 @@
1
+ import { ImageService } from "@thebes/cadmus/storage";
2
+
3
+ //#region src/index.d.ts
4
+ interface CloudflareImagesOptions {
5
+ /** R2 bucket originals are uploaded to. */
6
+ bucket: R2Bucket;
7
+ /** Public base URL for original objects (an R2 custom domain), no
8
+ * trailing slash. Stored in the DB and used as the transform source. */
9
+ mediaUrl: string;
10
+ /**
11
+ * Origin that serves `/cdn-cgi/image/...` (a zone with Image Resizing
12
+ * enabled). Defaults to `mediaUrl`. No trailing slash.
13
+ */
14
+ deliveryUrl?: string;
15
+ /** Widths emitted in `srcset`. Defaults to a sensible responsive set. */
16
+ widths?: number[];
17
+ /** `sizes` attribute value. Defaults to `100vw`. */
18
+ sizes?: string;
19
+ /** Output quality (1–100). Defaults to 80. */
20
+ quality?: number;
21
+ }
22
+ /**
23
+ * Creates an `ImageService` that uploads to R2 and renders responsive
24
+ * Cloudflare Image Resizing URLs. Drop-in replacement for the default R2
25
+ * pass-through service — the database still stores the original R2 URL.
26
+ */
27
+ declare function createCloudflareImageService(options: CloudflareImagesOptions): ImageService;
28
+ //#endregion
29
+ export { CloudflareImagesOptions, createCloudflareImageService };
30
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;UAmBiB,uBAAA;;EAEf,MAAA,EAAQ,QAAQ;EAFsB;;EAKtC,QAAA;EAHA;;;;EAQA,WAAA;EAIA;EAFA,MAAA;EAIO;EAFP,KAAA;EA8Bc;EA5Bd,OAAA;AAAA;;;;;;iBA4Bc,4BAAA,CACd,OAAA,EAAS,uBAAA,GACR,YAAY"}
@@ -0,0 +1,30 @@
1
+ import { ImageService } from "@thebes/cadmus/storage";
2
+
3
+ //#region src/index.d.ts
4
+ interface CloudflareImagesOptions {
5
+ /** R2 bucket originals are uploaded to. */
6
+ bucket: R2Bucket;
7
+ /** Public base URL for original objects (an R2 custom domain), no
8
+ * trailing slash. Stored in the DB and used as the transform source. */
9
+ mediaUrl: string;
10
+ /**
11
+ * Origin that serves `/cdn-cgi/image/...` (a zone with Image Resizing
12
+ * enabled). Defaults to `mediaUrl`. No trailing slash.
13
+ */
14
+ deliveryUrl?: string;
15
+ /** Widths emitted in `srcset`. Defaults to a sensible responsive set. */
16
+ widths?: number[];
17
+ /** `sizes` attribute value. Defaults to `100vw`. */
18
+ sizes?: string;
19
+ /** Output quality (1–100). Defaults to 80. */
20
+ quality?: number;
21
+ }
22
+ /**
23
+ * Creates an `ImageService` that uploads to R2 and renders responsive
24
+ * Cloudflare Image Resizing URLs. Drop-in replacement for the default R2
25
+ * pass-through service — the database still stores the original R2 URL.
26
+ */
27
+ declare function createCloudflareImageService(options: CloudflareImagesOptions): ImageService;
28
+ //#endregion
29
+ export { CloudflareImagesOptions, createCloudflareImageService };
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;UAmBiB,uBAAA;;EAEf,MAAA,EAAQ,QAAQ;EAFsB;;EAKtC,QAAA;EAHA;;;;EAQA,WAAA;EAIA;EAFA,MAAA;EAIO;EAFP,KAAA;EA8Bc;EA5Bd,OAAA;AAAA;;;;;;iBA4Bc,4BAAA,CACd,OAAA,EAAS,uBAAA,GACR,YAAY"}
package/dist/index.js ADDED
@@ -0,0 +1,58 @@
1
+ import { validateImageFile } from "@thebes/cadmus/storage";
2
+ //#region src/index.ts
3
+ const DEFAULT_WIDTHS = [
4
+ 320,
5
+ 640,
6
+ 960,
7
+ 1280,
8
+ 1920
9
+ ];
10
+ function safeExtension(filename) {
11
+ const match = /\.([a-zA-Z0-9]{1,5})$/.exec(filename);
12
+ return match ? `.${match[1].toLowerCase()}` : "";
13
+ }
14
+ /** Builds a Cloudflare Image Resizing URL:
15
+ * `${deliveryUrl}/cdn-cgi/image/<options>/<source>`. */
16
+ function transformUrl(deliveryUrl, source, opts) {
17
+ const params = [`format=auto`, `quality=${opts.quality}`];
18
+ if (opts.width) params.push(`width=${opts.width}`);
19
+ if (opts.height) params.push(`height=${opts.height}`);
20
+ return `${deliveryUrl}/cdn-cgi/image/${params.join(",")}/${source}`;
21
+ }
22
+ /**
23
+ * Creates an `ImageService` that uploads to R2 and renders responsive
24
+ * Cloudflare Image Resizing URLs. Drop-in replacement for the default R2
25
+ * pass-through service — the database still stores the original R2 URL.
26
+ */
27
+ function createCloudflareImageService(options) {
28
+ const { bucket, mediaUrl, deliveryUrl = mediaUrl, widths = DEFAULT_WIDTHS, sizes = "100vw", quality = 80 } = options;
29
+ return {
30
+ async upload(file) {
31
+ validateImageFile(file);
32
+ const key = `${crypto.randomUUID()}${safeExtension(file.name)}`;
33
+ await bucket.put(key, file);
34
+ return { url: `${mediaUrl}/${key}` };
35
+ },
36
+ render({ url, width, height }) {
37
+ const largest = widths[widths.length - 1];
38
+ const src = transformUrl(deliveryUrl, url, {
39
+ width: width ?? largest,
40
+ height,
41
+ quality
42
+ });
43
+ if (width || height) return { src };
44
+ return {
45
+ src,
46
+ srcset: widths.map((w) => `${transformUrl(deliveryUrl, url, {
47
+ width: w,
48
+ quality
49
+ })} ${w}w`).join(", "),
50
+ sizes
51
+ };
52
+ }
53
+ };
54
+ }
55
+ //#endregion
56
+ export { createCloudflareImageService };
57
+
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2026 BowenLabs. All rights reserved.\n// MIT licensed. See LICENSE in the repo root.\n//\n// @thebes/cadmus-cloudflare-images\n//\n// A Cadmus *adapter* (the swappable-implementation axis): an alternate\n// `ImageService` (from @thebes/cadmus/storage) backed by Cloudflare\n// Image Resizing. Uploads still land in R2 and the database still stores\n// the original R2 URL — only `render()` differs, returning responsive\n// `/cdn-cgi/image/...` transform URLs instead of a pass-through `src`.\n//\n// Swap it in without touching any component or block data:\n//\n// import { createCloudflareImageService } from \"@thebes/cadmus-cloudflare-images\";\n// const images = createCloudflareImageService({ bucket: env.R2, mediaUrl: env.MEDIA_URL });\n\nimport type { ImageService, RenderedImage } from \"@thebes/cadmus/storage\";\nimport { validateImageFile } from \"@thebes/cadmus/storage\";\n\nexport interface CloudflareImagesOptions {\n /** R2 bucket originals are uploaded to. */\n bucket: R2Bucket;\n /** Public base URL for original objects (an R2 custom domain), no\n * trailing slash. Stored in the DB and used as the transform source. */\n mediaUrl: string;\n /**\n * Origin that serves `/cdn-cgi/image/...` (a zone with Image Resizing\n * enabled). Defaults to `mediaUrl`. No trailing slash.\n */\n deliveryUrl?: string;\n /** Widths emitted in `srcset`. Defaults to a sensible responsive set. */\n widths?: number[];\n /** `sizes` attribute value. Defaults to `100vw`. */\n sizes?: string;\n /** Output quality (1–100). Defaults to 80. */\n quality?: number;\n}\n\nconst DEFAULT_WIDTHS = [320, 640, 960, 1280, 1920];\n\nfunction safeExtension(filename: string): string {\n const match = /\\.([a-zA-Z0-9]{1,5})$/.exec(filename);\n return match ? `.${match[1].toLowerCase()}` : \"\";\n}\n\n/** Builds a Cloudflare Image Resizing URL:\n * `${deliveryUrl}/cdn-cgi/image/<options>/<source>`. */\nfunction transformUrl(\n deliveryUrl: string,\n source: string,\n opts: { width?: number; height?: number; quality: number },\n): string {\n const params = [`format=auto`, `quality=${opts.quality}`];\n if (opts.width) params.push(`width=${opts.width}`);\n if (opts.height) params.push(`height=${opts.height}`);\n return `${deliveryUrl}/cdn-cgi/image/${params.join(\",\")}/${source}`;\n}\n\n/**\n * Creates an `ImageService` that uploads to R2 and renders responsive\n * Cloudflare Image Resizing URLs. Drop-in replacement for the default R2\n * pass-through service — the database still stores the original R2 URL.\n */\nexport function createCloudflareImageService(\n options: CloudflareImagesOptions,\n): ImageService {\n const {\n bucket,\n mediaUrl,\n deliveryUrl = mediaUrl,\n widths = DEFAULT_WIDTHS,\n sizes = \"100vw\",\n quality = 80,\n } = options;\n\n return {\n async upload(file) {\n // Defense-in-depth — callers should validate first, but upload() is\n // reachable directly too.\n validateImageFile(file);\n const key = `${crypto.randomUUID()}${safeExtension(file.name)}`;\n await bucket.put(key, file);\n // Store the ORIGINAL URL, never a transform URL (see CLAUDE.md\n // \"Image service interface\").\n return { url: `${mediaUrl}/${key}` };\n },\n\n render({ url, width, height }): RenderedImage {\n const largest = widths[widths.length - 1];\n const src = transformUrl(deliveryUrl, url, {\n width: width ?? largest,\n height,\n quality,\n });\n // A fixed width/height pins the rendition, so a srcset would be\n // misleading — emit just the single transformed src.\n if (width || height) {\n return { src };\n }\n const srcset = widths\n .map(\n (w) =>\n `${transformUrl(deliveryUrl, url, { width: w, quality })} ${w}w`,\n )\n .join(\", \");\n return { src, srcset, sizes };\n },\n };\n}\n"],"mappings":";;AAsCA,MAAM,iBAAiB;CAAC;CAAK;CAAK;CAAK;CAAM;AAAI;AAEjD,SAAS,cAAc,UAA0B;CAC/C,MAAM,QAAQ,wBAAwB,KAAK,QAAQ;CACnD,OAAO,QAAQ,IAAI,MAAM,EAAE,CAAC,YAAY,MAAM;AAChD;;;AAIA,SAAS,aACP,aACA,QACA,MACQ;CACR,MAAM,SAAS,CAAC,eAAe,WAAW,KAAK,SAAS;CACxD,IAAI,KAAK,OAAO,OAAO,KAAK,SAAS,KAAK,OAAO;CACjD,IAAI,KAAK,QAAQ,OAAO,KAAK,UAAU,KAAK,QAAQ;CACpD,OAAO,GAAG,YAAY,iBAAiB,OAAO,KAAK,GAAG,EAAE,GAAG;AAC7D;;;;;;AAOA,SAAgB,6BACd,SACc;CACd,MAAM,EACJ,QACA,UACA,cAAc,UACd,SAAS,gBACT,QAAQ,SACR,UAAU,OACR;CAEJ,OAAO;EACL,MAAM,OAAO,MAAM;GAGjB,kBAAkB,IAAI;GACtB,MAAM,MAAM,GAAG,OAAO,WAAW,IAAI,cAAc,KAAK,IAAI;GAC5D,MAAM,OAAO,IAAI,KAAK,IAAI;GAG1B,OAAO,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM;EACrC;EAEA,OAAO,EAAE,KAAK,OAAO,UAAyB;GAC5C,MAAM,UAAU,OAAO,OAAO,SAAS;GACvC,MAAM,MAAM,aAAa,aAAa,KAAK;IACzC,OAAO,SAAS;IAChB;IACA;GACF,CAAC;GAGD,IAAI,SAAS,QACX,OAAO,EAAE,IAAI;GAQf,OAAO;IAAE;IAAK,QANC,OACZ,KACE,MACC,GAAG,aAAa,aAAa,KAAK;KAAE,OAAO;KAAG;IAAQ,CAAC,EAAE,GAAG,EAAE,EAClE,CAAC,CACA,KAAK,IACW;IAAG;GAAM;EAC9B;CACF;AACF"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@thebes/cadmus-cloudflare-images",
3
+ "version": "1.0.0",
4
+ "description": "Cloudflare Image Resizing adapter for @thebes/cadmus/storage's ImageService",
5
+ "author": "BowenLabs <hello@bowenlabs.io>",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/bowenlabs/project-thebes",
10
+ "directory": "packages/cadmus-cloudflare-images"
11
+ },
12
+ "homepage": "https://github.com/bowenlabs/project-thebes/tree/main/packages/cadmus-cloudflare-images#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/bowenlabs/project-thebes/issues"
15
+ },
16
+ "keywords": [
17
+ "cadmus",
18
+ "cloudflare",
19
+ "cloudflare-images",
20
+ "image-resizing",
21
+ "r2",
22
+ "adapter"
23
+ ],
24
+ "type": "module",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ }
30
+ },
31
+ "peerDependencies": {
32
+ "@thebes/cadmus": "^0.2.1"
33
+ },
34
+ "devDependencies": {
35
+ "@cloudflare/workers-types": "latest",
36
+ "typescript": "latest",
37
+ "vite-plus": "latest",
38
+ "vitest": "latest",
39
+ "@thebes/cadmus": "^0.2.1"
40
+ },
41
+ "files": [
42
+ "dist",
43
+ "README.md",
44
+ "LICENSE"
45
+ ],
46
+ "scripts": {
47
+ "build": "vp pack",
48
+ "dev": "vp pack --watch",
49
+ "test": "vitest run",
50
+ "test:watch": "vitest"
51
+ }
52
+ }