From c4023b15829754e937d29e7e84beeb5ac6a0faaa Mon Sep 17 00:00:00 2001 From: David Blass Date: Fri, 25 Oct 2024 16:54:15 -0400 Subject: [PATCH] refactor: remove applyWhen in favor of explicit props overlap check with alwaysApply exception --- .../components/SchemaTable/SchemaTable.tsx | 2 +- packages/types/CHANGELOG.md | 6 +- packages/url-loader/CHANGELOG.md | 22 +---- packages/url-loader/package.json | 2 +- packages/url-loader/src/lib/cloudinary.ts | 31 +++---- packages/url-loader/src/lib/plugin.ts | 82 +++++++++++++------ packages/url-loader/src/lib/upload.ts | 4 +- packages/url-loader/src/lib/utils.ts | 2 +- packages/url-loader/src/lib/video-player.ts | 6 +- packages/url-loader/src/plugins/abr.ts | 5 +- packages/url-loader/src/plugins/cropping.ts | 26 +++--- .../url-loader/src/plugins/default-image.ts | 14 ++-- packages/url-loader/src/plugins/effects.ts | 10 +-- packages/url-loader/src/plugins/enhance.ts | 4 +- packages/url-loader/src/plugins/extract.ts | 1 - .../url-loader/src/plugins/fill-background.ts | 14 ++-- packages/url-loader/src/plugins/flags.ts | 1 - .../src/plugins/named-transformations.ts | 6 +- packages/url-loader/src/plugins/overlays.ts | 12 +-- .../src/plugins/preserve-transformations.ts | 12 +-- .../src/plugins/raw-transformations.ts | 4 +- packages/url-loader/src/plugins/recolor.ts | 4 +- .../src/plugins/remove-background.ts | 4 +- packages/url-loader/src/plugins/remove.ts | 8 +- .../src/plugins/replace-background.ts | 9 +- packages/url-loader/src/plugins/replace.ts | 50 ++++++----- packages/url-loader/src/plugins/restore.ts | 4 +- packages/url-loader/src/plugins/sanitize.ts | 7 +- packages/url-loader/src/plugins/seo.ts | 16 ++-- packages/url-loader/src/plugins/underlays.ts | 6 +- packages/url-loader/src/plugins/version.ts | 12 ++- packages/url-loader/src/plugins/zoompan.ts | 4 +- packages/url-loader/src/types/asset.ts | 2 +- .../url-loader/tests/plugins/default.spec.ts | 6 +- .../tests/plugins/remove-background.spec.ts | 12 --- .../url-loader/tests/plugins/replace.spec.ts | 12 --- .../url-loader/tests/plugins/restore.spec.ts | 12 --- .../url-loader/tests/plugins/zoompan.spec.ts | 12 --- packages/util/CHANGELOG.md | 15 ++-- packages/util/src/lib/cloudinary.ts | 4 +- packages/util/src/lib/util.ts | 2 +- 41 files changed, 207 insertions(+), 260 deletions(-) diff --git a/docs/src/components/SchemaTable/SchemaTable.tsx b/docs/src/components/SchemaTable/SchemaTable.tsx index db51dae8..aa30564e 100644 --- a/docs/src/components/SchemaTable/SchemaTable.tsx +++ b/docs/src/components/SchemaTable/SchemaTable.tsx @@ -59,7 +59,7 @@ export const SchemaTable = ({ schema, schemaKey }) => { }; return property; - } + }, ); const sortedProperties = sortByKey(formattedProperties, "name"); diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index a4976f31..7d044d01 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -1,16 +1,14 @@ # [@cloudinary-util/types-v2.0.0-beta.2](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/types-v2.0.0-beta.1...@cloudinary-util/types-v2.0.0-beta.2) (2024-10-22) - ### Bug Fixes -* Add TypeScript Types for Cloudinary Product Gallery Widget ([#218](https://github.com/cloudinary-community/cloudinary-util/issues/218)) ([05cd33e](https://github.com/cloudinary-community/cloudinary-util/commit/05cd33e3948d486ac87600b798e0006789e2d914)), closes [#199](https://github.com/cloudinary-community/cloudinary-util/issues/199) +- Add TypeScript Types for Cloudinary Product Gallery Widget ([#218](https://github.com/cloudinary-community/cloudinary-util/issues/218)) ([05cd33e](https://github.com/cloudinary-community/cloudinary-util/commit/05cd33e3948d486ac87600b798e0006789e2d914)), closes [#199](https://github.com/cloudinary-community/cloudinary-util/issues/199) # [@cloudinary-util/types-v2.0.0-beta.1](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/types-v1.5.11...@cloudinary-util/types-v2.0.0-beta.1) (2024-10-18) - ### Features -* migrate Zod to pure TS w/ JSDoc, improve type safety and simplify parsing ([#217](https://github.com/cloudinary-community/cloudinary-util/issues/217)) ([f605f26](https://github.com/cloudinary-community/cloudinary-util/commit/f605f26f9de1d111c26d65dd3b8955491b357481)) +- migrate Zod to pure TS w/ JSDoc, improve type safety and simplify parsing ([#217](https://github.com/cloudinary-community/cloudinary-util/issues/217)) ([f605f26](https://github.com/cloudinary-community/cloudinary-util/commit/f605f26f9de1d111c26d65dd3b8955491b357481)) # [@cloudinary-util/types-v1.5.11](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/types-v1.5.10...@cloudinary-util/types-v1.5.11) (2024-10-07) diff --git a/packages/url-loader/CHANGELOG.md b/packages/url-loader/CHANGELOG.md index 7435dcdc..e4630687 100644 --- a/packages/url-loader/CHANGELOG.md +++ b/packages/url-loader/CHANGELOG.md @@ -1,36 +1,20 @@ -# [@cloudinary-util/url-loader-v6.0.0-beta.4](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v6.0.0-beta.3...@cloudinary-util/url-loader-v6.0.0-beta.4) (2024-10-25) - - -### Bug Fixes - -* adding applyWhen to streaming profile to prevent abr plugin from running ([ef7e57a](https://github.com/cloudinary-community/cloudinary-util/commit/ef7e57adc03afb0e08ebf2bb0053d34c12054523)) -* adding string and number back to replaceBackground ([672009a](https://github.com/cloudinary-community/cloudinary-util/commit/672009afb7797c540c0a6fdc31115f0c245ed8b2)) - -# [@cloudinary-util/url-loader-v6.0.0-beta.3](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v6.0.0-beta.2...@cloudinary-util/url-loader-v6.0.0-beta.3) (2024-10-24) - - -### Features - -* enumerate plugin props ([#224](https://github.com/cloudinary-community/cloudinary-util/issues/224)) ([731d545](https://github.com/cloudinary-community/cloudinary-util/commit/731d54511741f9bb56fc6b1d6e978a8f21d88082)) - # [@cloudinary-util/url-loader-v6.0.0-beta.2](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v6.0.0-beta.1...@cloudinary-util/url-loader-v6.0.0-beta.2) (2024-10-22) - ### Bug Fixes -* Add enum for format parameter ([#220](https://github.com/cloudinary-community/cloudinary-util/issues/220)) ([0ecd331](https://github.com/cloudinary-community/cloudinary-util/commit/0ecd331e1bfe9244bedc82fc8d61e228bdc00d4c)), closes [#142](https://github.com/cloudinary-community/cloudinary-util/issues/142) +- Add enum for format parameter ([#220](https://github.com/cloudinary-community/cloudinary-util/issues/220)) ([0ecd331](https://github.com/cloudinary-community/cloudinary-util/commit/0ecd331e1bfe9244bedc82fc8d61e228bdc00d4c)), closes [#142](https://github.com/cloudinary-community/cloudinary-util/issues/142) # [@cloudinary-util/url-loader-v6.0.0-beta.1](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v5.10.5...@cloudinary-util/url-loader-v6.0.0-beta.1) (2024-10-18) ### Features -* migrate Zod to pure TS w/ JSDoc, improve type safety and simplify parsing ([#217](https://github.com/cloudinary-community/cloudinary-util/issues/217)) ([f605f26](https://github.com/cloudinary-community/cloudinary-util/commit/f605f26f9de1d111c26d65dd3b8955491b357481)) +- migrate Zod to pure TS w/ JSDoc, improve type safety and simplify parsing ([#217](https://github.com/cloudinary-community/cloudinary-util/issues/217)) ([f605f26](https://github.com/cloudinary-community/cloudinary-util/commit/f605f26f9de1d111c26d65dd3b8955491b357481)) # [@cloudinary-util/url-loader-v5.10.6](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v5.10.5...@cloudinary-util/url-loader-v5.10.6) (2024-10-22) ### Bug Fixes -* Add enum for format parameter ([#220](https://github.com/cloudinary-community/cloudinary-util/issues/220)) ([0ecd331](https://github.com/cloudinary-community/cloudinary-util/commit/0ecd331e1bfe9244bedc82fc8d61e228bdc00d4c)), closes [#142](https://github.com/cloudinary-community/cloudinary-util/issues/142) +- Add enum for format parameter ([#220](https://github.com/cloudinary-community/cloudinary-util/issues/220)) ([0ecd331](https://github.com/cloudinary-community/cloudinary-util/commit/0ecd331e1bfe9244bedc82fc8d61e228bdc00d4c)), closes [#142](https://github.com/cloudinary-community/cloudinary-util/issues/142) # [@cloudinary-util/url-loader-v5.10.5](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/url-loader-v5.10.4...@cloudinary-util/url-loader-v5.10.5) (2024-10-07) diff --git a/packages/url-loader/package.json b/packages/url-loader/package.json index f20e5d1b..39f917e0 100644 --- a/packages/url-loader/package.json +++ b/packages/url-loader/package.json @@ -1,6 +1,6 @@ { "name": "@cloudinary-util/url-loader", - "version": "6.0.0-beta.4", + "version": "6.0.0-beta.2", "type": "module", "main": "./dist/index.cjs", "types": "./dist/index.d.cts", diff --git a/packages/url-loader/src/lib/cloudinary.ts b/packages/url-loader/src/lib/cloudinary.ts index bcc01085..a330d975 100644 --- a/packages/url-loader/src/lib/cloudinary.ts +++ b/packages/url-loader/src/lib/cloudinary.ts @@ -40,7 +40,7 @@ import type { PluginOptions, PluginResults } from "../types/plugins.js"; import type { VideoOptions } from "../types/video.js"; import type { CloudinaryKey, - OptionsFor, + CtxParam, TransformationPlugin, } from "./plugin.js"; import { entriesOf, throwError } from "./utils.js"; @@ -95,12 +95,12 @@ export const transformationPlugins = validatePlugins( SeoPlugin, UnderlaysPlugin, VersionPlugin, - ZoompanPlugin + ZoompanPlugin, ); // important this comes after `validatePlugins` is called so we've collected the props export const cloudinaryPluginKeys: readonly CloudinaryKey[] = Object.keys( - cloudinaryPluginProps + cloudinaryPluginProps, ) as never; export interface AnalyticsOptions extends IAnalyticsOptions {} @@ -133,7 +133,7 @@ export interface ConstructUrlProps< */ config?: ConfigOptions; // prioritize inferring assetType so available options can be derived from it - options: { assetType?: assetType } & OptionsFor; + options: { assetType?: assetType } & CtxParam; } export type CldAsset = CloudinaryImage | CloudinaryVideo; @@ -157,7 +157,7 @@ export function constructCloudinaryUrl< if (typeof options?.src !== "string") { throw Error( - `Failed to construct Cloudinary URL: Missing source (src) in options.` + `Failed to construct Cloudinary URL: Missing source (src) in options.`, ); } @@ -212,18 +212,16 @@ export function constructCloudinaryUrl< const pluginEffects: PluginOptions = {}; transformationPlugins.forEach( - ({ name, apply, strict, applyWhen, supports }: TransformationPlugin) => { - const shouldApply = - applyWhen === undefined || - (typeof applyWhen === "string" - ? options[applyWhen as never] !== undefined - : applyWhen(options)); + ({ name, apply, strict, supports, props }: TransformationPlugin) => { + const shouldApply = Object.keys(props).some( + (key) => options[key as never] !== undefined, + ); if (!shouldApply) return; if (normalizedAssetType !== supports && supports !== "all") { console.warn( - `${name} does not support assetType ${normalizedAssetType}` + `${name} does not support assetType ${normalizedAssetType}`, ); return; } @@ -233,12 +231,15 @@ export function constructCloudinaryUrl< return; } + // we're actually passing options for both opts and ctx, but + // the second param is typed to only include the options + // declared by the plugin's `inferOwnOptions` const results: PluginResults = apply(cldAsset, options); const pluginOptions = results?.options ?? {}; Object.assign(pluginEffects, pluginOptions); - } + }, ); // We want to perform any resizing at the end of the end of the transformation @@ -315,7 +316,7 @@ interface SearchAssetRawTransformationsOptions { export function searchAssetRawTransformations( query: string, asset: CloudinaryImage | CloudinaryVideo, - options?: SearchAssetRawTransformationsOptions + options?: SearchAssetRawTransformationsOptions, ) { if (typeof asset.transformation === "undefined") return; @@ -329,7 +330,7 @@ export function searchAssetRawTransformations( .toString() .split("/") .flatMap((seg) => seg.split(",")); - } + }, ); const matches = transformations.filter((transformation) => { diff --git a/packages/url-loader/src/lib/plugin.ts b/packages/url-loader/src/lib/plugin.ts index 4b3ddfc0..e38f4439 100644 --- a/packages/url-loader/src/lib/plugin.ts +++ b/packages/url-loader/src/lib/plugin.ts @@ -18,59 +18,89 @@ export type AlwaysApply = () => true; export interface PluginDefinition< assetType extends SupportedAssetType, - when extends ApplyWhen, name extends string, options extends object, + alwaysApply extends boolean, > { name: name; supports: assetType; - apply: PluginApplication; + apply: PluginApplicationDefinition; inferOwnOptions: options; props: Record; - applyWhen?: when | undefined; + alwaysApply?: alwaysApply; strict?: boolean; } export interface TransformationPlugin< assetType extends SupportedAssetType = SupportedAssetType, - when extends ApplyWhen = ApplyWhen, name extends string = string, - options extends object = object, + opts extends object = object, + alwaysApply extends boolean = boolean, > { name: name; supports: assetType; - apply: PluginApplication; - inferOwnOptions: options; - props: Record; - applyWhen?: when | undefined; + apply: PluginApplication; + inferOwnOptions: opts; + props: Record; + alwaysApply: alwaysApply; strict?: boolean; } -export type OptionsFor< - assetType extends SupportedAssetTypeInput, - when extends ApplyWhen = AlwaysApply, - options = assetType extends "all" +export type OwnOptionsParam< + opts extends object, + alwaysApply extends boolean, +> = opts & + // if there's only one owned key, we know it must be present if + // apply is being invoked, so require it so we don't have to recheck + // in the implementation unless alwaysApply is true + ([alwaysApply] extends [true] + ? {} + : { [k in singleKeyOf]: Exclude }); + +export type CtxParam = + assetType extends "all" ? AllOptions : assetType extends "video" | "videos" ? VideoOptions - : ImageOptions, -> = [when] extends [keyof options] - ? // if the plugin applies based on a single key being defined, we know it will be - // present in the options passed to apply - options & { [k in when]: {} } - : options; + : ImageOptions; + +// extract the key if there is exactly one, otherwise never +type singleKeyOf = { + [k in keyof opts]: keyof opts extends k ? k : never; +}[keyof opts]; + +export type PluginApplicationDefinition< + assetType extends SupportedAssetType, + opts extends object, + alwaysApply extends boolean, +> = ( + cldAsset: CldAsset, + /** Options owned by this plugin */ + opts: OwnOptionsParam, + ctx: CtxParam, +) => PluginResults; export type PluginApplication< assetType extends SupportedAssetType, - when extends ApplyWhen = AlwaysApply, -> = (cldAsset: CldAsset, options: OptionsFor) => PluginResults; + opts extends object, + alwaysApply extends boolean, +> = ( + cldAsset: CldAsset, + // externally, we want the wider assetType options as well + opts: OwnOptionsParam & CtxParam, +) => PluginResults; export const plugin = < asset extends SupportedAssetType, - when extends ApplyWhen, name extends string, - options extends object, + opts extends object, + alwaysApply extends boolean, >( - def: PluginDefinition -): TransformationPlugin => - ({ strict: false, ...def }) as never; + def: PluginDefinition, +): TransformationPlugin => + ({ + strict: false, + alwaysApply: false, + ...def, + apply: (cldAsset, ctx) => def.apply(cldAsset, ctx as never, ctx as never), + }) satisfies TransformationPlugin as never; diff --git a/packages/url-loader/src/lib/upload.ts b/packages/url-loader/src/lib/upload.ts index 7c05fc8c..7e22db4b 100644 --- a/packages/url-loader/src/lib/upload.ts +++ b/packages/url-loader/src/lib/upload.ts @@ -14,11 +14,11 @@ export function generateSignatureCallback({ }: GenerateSignatureCallback) { return function generateSignature( callback: (signature: string | null, error?: unknown) => void, - paramsToSign: object + paramsToSign: object, ) { if (typeof signatureEndpoint === "undefined") { throw Error( - "Failed to generate signature: signatureEndpoint property undefined." + "Failed to generate signature: signatureEndpoint property undefined.", ); } diff --git a/packages/url-loader/src/lib/utils.ts b/packages/url-loader/src/lib/utils.ts index 106f75ca..df102233 100644 --- a/packages/url-loader/src/lib/utils.ts +++ b/packages/url-loader/src/lib/utils.ts @@ -33,7 +33,7 @@ export const entriesOf: (o: o) => entryOf[] = */ export const throwError: ( message: string, - ctor?: new (message: string) => Error + ctor?: new (message: string) => Error, ) => never = (message, ctor = Error) => { throw new ctor(message); }; diff --git a/packages/url-loader/src/lib/video-player.ts b/packages/url-loader/src/lib/video-player.ts index a95c8d30..bcea13ef 100644 --- a/packages/url-loader/src/lib/video-player.ts +++ b/packages/url-loader/src/lib/video-player.ts @@ -38,7 +38,7 @@ export interface GetVideoPlayerOptionsLogo { export function getVideoPlayerOptions( options: GetVideoPlayerOptions, - config: CloudinaryAssetConfiguration + config: CloudinaryAssetConfiguration, ) { const { autoplay, @@ -63,7 +63,7 @@ export function getVideoPlayerOptions( if (!cloudName) { throw new Error( - "A Cloudinary Cloud name is required, please make sure your environment variable is set and configured in your environment." + "A Cloudinary Cloud name is required, please make sure your environment variable is set and configured in your environment.", ); } @@ -85,7 +85,7 @@ export function getVideoPlayerOptions( if (!publicId) { throw new Error( - "Video Player requires a src, please make sure to configure your src as a public ID or Cloudinary URL." + "Video Player requires a src, please make sure to configure your src as a public ID or Cloudinary URL.", ); } diff --git a/packages/url-loader/src/plugins/abr.ts b/packages/url-loader/src/plugins/abr.ts index eb1d903f..f5c72b01 100644 --- a/packages/url-loader/src/plugins/abr.ts +++ b/packages/url-loader/src/plugins/abr.ts @@ -14,14 +14,11 @@ export const AbrPlugin = plugin({ name: "Abr", supports: "video", inferOwnOptions: {} as AbrPlugin.Options, - applyWhen: 'streamingProfile', props: { streamingProfile: true, }, apply: (asset, opts) => { - if (typeof opts.streamingProfile === "string") { - asset.addTransformation(`sp_${opts.streamingProfile}`); - } + asset.addTransformation(`sp_${opts.streamingProfile}`); return {}; }, diff --git a/packages/url-loader/src/plugins/cropping.ts b/packages/url-loader/src/plugins/cropping.ts index d9d92bf9..f790db6e 100644 --- a/packages/url-loader/src/plugins/cropping.ts +++ b/packages/url-loader/src/plugins/cropping.ts @@ -25,6 +25,8 @@ export declare namespace CroppingPlugin { crop?: CropMode | NestedOptions | ReadonlyArray; gravity?: Gravity; zoom?: Zoom; + height?: Height; + width?: Width; } export interface NestedOptions { @@ -49,9 +51,11 @@ export const CroppingPlugin = plugin({ crop: true, gravity: true, zoom: true, + height: true, + width: true, }, // crop is applied even if the crop key is undefined - apply: (asset, opts) => { + apply: (asset, opts, ctx) => { let crops: Array = []; // Normalize the data that we're working with for simpler processing @@ -64,10 +68,10 @@ export const CroppingPlugin = plugin({ crops.push({ aspectRatio: opts.aspectRatio, - height: opts.height, + height: ctx.height, gravity: opts.gravity, type: opts.crop || DEFAULT_CROP, - width: opts.width, + width: ctx.width, zoom: opts.zoom, }); } else if (typeof opts.crop === "object" && !isArray(opts.crop)) { @@ -83,8 +87,8 @@ export const CroppingPlugin = plugin({ if (crops.length === 1 && crops[0].source === true) { crops.push({ aspectRatio: opts.aspectRatio, - width: opts.width, - height: opts.height, + width: ctx.width, + height: ctx.height, gravity: opts.gravity, type: DEFAULT_CROP, zoom: opts.zoom, @@ -107,13 +111,13 @@ export const CroppingPlugin = plugin({ typeof cropDimensions.width === "undefined" && typeof crop.aspectRatio === "undefined" ) { - cropDimensions.width = opts.width; + cropDimensions.width = ctx.width; // We likely don't want to infer one dimension and not the other // so only infer the height if we're already inferring the width if (typeof cropDimensions.height === "undefined") { - cropDimensions.height = opts.height; + cropDimensions.height = ctx.height; } } @@ -242,8 +246,8 @@ function collectTransformations(collectOptions: CroppingPlugin.NestedOptions) { if (gravity === "auto" && !cropsGravityAuto.includes(crop)) { console.warn( `Auto gravity can only be used with crop modes: ${cropsGravityAuto.join( - ", " - )}. Not applying gravity.` + ", ", + )}. Not applying gravity.`, ); } else { transformations.push(`g_${gravity}`); @@ -256,8 +260,8 @@ function collectTransformations(collectOptions: CroppingPlugin.NestedOptions) { if (zoom === "auto" && !cropsWithZoom.includes(crop)) { console.warn( `Zoom can only be used with crop modes: ${cropsWithZoom.join( - ", " - )}. Not applying zoom.` + ", ", + )}. Not applying zoom.`, ); } else { transformations.push(`z_${zoom}`); diff --git a/packages/url-loader/src/plugins/default-image.ts b/packages/url-loader/src/plugins/default-image.ts index 76070c6d..e49365bc 100644 --- a/packages/url-loader/src/plugins/default-image.ts +++ b/packages/url-loader/src/plugins/default-image.ts @@ -19,15 +19,13 @@ export const DefaultImagePlugin = plugin({ apply: (asset, opts) => { const { defaultImage } = opts; - if (typeof defaultImage === "string") { - if (!getFormat(defaultImage)) { - console.warn( - `The defaultImage prop may be missing a format and must include it along with the public ID. (Ex: myimage.jpg)` - ); - } - const defaultImageId = defaultImage.replace(/\//g, ":"); - asset.addTransformation(`d_${defaultImageId}`); + if (!getFormat(defaultImage)) { + console.warn( + `The defaultImage prop may be missing a format and must include it along with the public ID. (Ex: myimage.jpg)`, + ); } + const defaultImageId = defaultImage.replace(/\//g, ":"); + asset.addTransformation(`d_${defaultImageId}`); return {}; }, diff --git a/packages/url-loader/src/plugins/effects.ts b/packages/url-loader/src/plugins/effects.ts index d01cc938..5826dce8 100644 --- a/packages/url-loader/src/plugins/effects.ts +++ b/packages/url-loader/src/plugins/effects.ts @@ -76,12 +76,12 @@ export const EffectsPlugin = plugin({ vignette: true, effects: true, }, - apply: (cldAsset, options) => { + apply: (cldAsset, opts) => { // Handle any top-level effect props const transformationStrings = constructTransformationString({ effects: qualifiersEffects, - options, + options: opts, }); transformationStrings.forEach((transformation) => { @@ -93,8 +93,8 @@ export const EffectsPlugin = plugin({ // If we're passing in an effects prop explicitly, treat it as an array of // effects that we need to process - if (isArray(options?.effects)) { - options?.effects.forEach((effectsSet) => { + if (isArray(opts?.effects)) { + opts?.effects.forEach((effectsSet) => { const transformationString = constructTransformationString({ effects: qualifiersEffects, options: effectsSet, @@ -123,7 +123,7 @@ export const EffectsPlugin = plugin({ value: options?.[key], converters, }); - } + }, ); } diff --git a/packages/url-loader/src/plugins/enhance.ts b/packages/url-loader/src/plugins/enhance.ts index 0347a130..ca17c85a 100644 --- a/packages/url-loader/src/plugins/enhance.ts +++ b/packages/url-loader/src/plugins/enhance.ts @@ -17,8 +17,8 @@ export const EnhancePlugin = plugin({ props: { enhance: true, }, - apply: (cldAsset, options) => { - if (options.enhance) { + apply: (cldAsset, opts) => { + if (opts.enhance) { cldAsset.addTransformation("e_enhance"); } diff --git a/packages/url-loader/src/plugins/extract.ts b/packages/url-loader/src/plugins/extract.ts index 53a66ec2..8408204f 100644 --- a/packages/url-loader/src/plugins/extract.ts +++ b/packages/url-loader/src/plugins/extract.ts @@ -26,7 +26,6 @@ export declare namespace ExtractPlugin { export const ExtractPlugin = plugin({ name: "Extract", supports: "image", - applyWhen: "extract", inferOwnOptions: {} as ExtractPlugin.Options, props: { extract: true, diff --git a/packages/url-loader/src/plugins/fill-background.ts b/packages/url-loader/src/plugins/fill-background.ts index 610863b5..786b7fcb 100644 --- a/packages/url-loader/src/plugins/fill-background.ts +++ b/packages/url-loader/src/plugins/fill-background.ts @@ -31,16 +31,14 @@ export const FillBackgroundPlugin = plugin({ props: { fillBackground: true, }, - apply: (cldAsset, options) => { - const { fillBackground } = options; + apply: (cldAsset, opts, ctx) => { + const { fillBackground } = opts; - if (typeof fillBackground === "undefined") return {}; - - const width = normalizeNumberParameter(options.width); - const height = normalizeNumberParameter(options.height); + const width = normalizeNumberParameter(ctx.width); + const height = normalizeNumberParameter(ctx.height); const hasDefinedDimensions = typeof height === "number" && typeof width === "number"; - let aspectRatio = options.aspectRatio; + let aspectRatio = ctx.aspectRatio; if (!aspectRatio && hasDefinedDimensions) { aspectRatio = `${width}:${height}`; @@ -49,7 +47,7 @@ export const FillBackgroundPlugin = plugin({ if (!aspectRatio) { if (process.env.NODE_ENV === "development") { console.warn( - `Could not determine aspect ratio based on available options to use fillBackground. Please specify width and height or an aspect ratio.` + `Could not determine aspect ratio based on available options to use fillBackground. Please specify width and height or an aspect ratio.`, ); } return {}; diff --git a/packages/url-loader/src/plugins/flags.ts b/packages/url-loader/src/plugins/flags.ts index d2c09a9a..79120195 100644 --- a/packages/url-loader/src/plugins/flags.ts +++ b/packages/url-loader/src/plugins/flags.ts @@ -11,7 +11,6 @@ export declare namespace FlagsPlugin { export const FlagsPlugin = plugin({ name: "Flags", supports: "all", - applyWhen: "flags", inferOwnOptions: {} as FlagsPlugin.Options, props: { flags: true, diff --git a/packages/url-loader/src/plugins/named-transformations.ts b/packages/url-loader/src/plugins/named-transformations.ts index 924628e3..5a0f5294 100644 --- a/packages/url-loader/src/plugins/named-transformations.ts +++ b/packages/url-loader/src/plugins/named-transformations.ts @@ -26,12 +26,12 @@ export const NamedTransformationsPlugin = plugin({ namedTransformations: true, transformations: true, }, - apply: (cldAsset, options) => { - const { transformations, namedTransformations } = options; + apply: (cldAsset, opts) => { + const { transformations, namedTransformations } = opts; if (transformations && process.env.NODE_ENVIRONMENT === "development") { console.warn( - "The transformations prop is deprecated. Please use namedTransformations instead." + "The transformations prop is deprecated. Please use namedTransformations instead.", ); } diff --git a/packages/url-loader/src/plugins/overlays.ts b/packages/url-loader/src/plugins/overlays.ts index 9d1ebde3..76d403e8 100644 --- a/packages/url-loader/src/plugins/overlays.ts +++ b/packages/url-loader/src/plugins/overlays.ts @@ -77,8 +77,8 @@ export const OverlaysPlugin = plugin({ overlays: true, text: true, }, - apply: (cldAsset, options) => { - const { text, overlays = [] } = options; + apply: (cldAsset, opts) => { + const { text, overlays = [] } = opts; const type = "overlay"; const typeQualifier = "l"; @@ -130,7 +130,7 @@ export const OverlaysPlugin = plugin({ } else if (hasPublicId) { layerTransformation = `${typeQualifier}_${publicId.replace( /\//g, - ":" + ":", )}`; } else if (hasUrl) { layerTransformation = `${typeQualifier}_fetch:${encodeBase64(url)}`; @@ -271,7 +271,7 @@ export const OverlaysPlugin = plugin({ value, order: qualifiersText[key].order || 99, }; - } + }, ); const sortedTextOptions = sortByKey(textOptions, "order"); @@ -314,13 +314,13 @@ export const OverlaysPlugin = plugin({ )?.forEach((character: string) => { layerText = layerText?.replace( character, - specialCharacters[character] + specialCharacters[character], ); }); } layerTransformation = `${layerTransformation}:${textTransformations.join( - "_" + "_", )}:${layerText}`; } diff --git a/packages/url-loader/src/plugins/preserve-transformations.ts b/packages/url-loader/src/plugins/preserve-transformations.ts index 19c8995c..6bfd0f8e 100644 --- a/packages/url-loader/src/plugins/preserve-transformations.ts +++ b/packages/url-loader/src/plugins/preserve-transformations.ts @@ -17,8 +17,8 @@ export const PreserveTransformationsPlugin = plugin({ props: { preserveTransformations: true, }, - apply: (cldAsset, options) => { - const { preserveTransformations = false } = options; + apply: (cldAsset, opts, ctx) => { + const { preserveTransformations = false } = opts; // Try to preserve the original transformations from the Cloudinary URL passed in // to the function. This only works if the URL has a version number on it and otherwise @@ -26,18 +26,18 @@ export const PreserveTransformationsPlugin = plugin({ if (preserveTransformations) { try { - if (options.src === undefined) { + if (ctx.src === undefined) { throw new Error("options.src was undefined"); } - const transformations = getTransformations(options.src).map((t) => - t.join(",") + const transformations = getTransformations(ctx.src).map((t) => + t.join(","), ); transformations.flat().forEach((transformation) => { cldAsset.addTransformation(transformation); }); } catch (e) { console.warn( - `Failed to preserve transformations: ${(e as Error).message}` + `Failed to preserve transformations: ${(e as Error).message}`, ); } } diff --git a/packages/url-loader/src/plugins/raw-transformations.ts b/packages/url-loader/src/plugins/raw-transformations.ts index 6ca1ab2c..4f08a277 100644 --- a/packages/url-loader/src/plugins/raw-transformations.ts +++ b/packages/url-loader/src/plugins/raw-transformations.ts @@ -18,8 +18,8 @@ export const RawTransformationsPlugin = plugin({ props: { rawTransformations: true, }, - apply: (cldAsset, options) => { - let { rawTransformations = [] } = options; + apply: (cldAsset, opts) => { + let { rawTransformations = [] } = opts; if (!isArray(rawTransformations)) { rawTransformations = [rawTransformations]; diff --git a/packages/url-loader/src/plugins/recolor.ts b/packages/url-loader/src/plugins/recolor.ts index da394613..890e5c0f 100644 --- a/packages/url-loader/src/plugins/recolor.ts +++ b/packages/url-loader/src/plugins/recolor.ts @@ -30,8 +30,8 @@ export const RecolorPlugin = plugin({ props: { recolor: true, }, - apply: (cldAsset, options) => { - const { recolor } = options; + apply: (cldAsset, opts) => { + const { recolor } = opts; const recolorOptions: Record = { prompt: undefined, diff --git a/packages/url-loader/src/plugins/remove-background.ts b/packages/url-loader/src/plugins/remove-background.ts index 193f3fd0..e2177a95 100644 --- a/packages/url-loader/src/plugins/remove-background.ts +++ b/packages/url-loader/src/plugins/remove-background.ts @@ -17,8 +17,8 @@ export const RemoveBackgroundPlugin = plugin({ props: { removeBackground: true, }, - apply: (cldAsset, options) => { - if (options.removeBackground) { + apply: (cldAsset, opts) => { + if (opts.removeBackground) { cldAsset.addTransformation("e_background_removal"); } return {}; diff --git a/packages/url-loader/src/plugins/remove.ts b/packages/url-loader/src/plugins/remove.ts index ab48e95d..e611f124 100644 --- a/packages/url-loader/src/plugins/remove.ts +++ b/packages/url-loader/src/plugins/remove.ts @@ -27,8 +27,8 @@ export const RemovePlugin = plugin({ props: { remove: true, }, - apply: (cldAsset, options) => { - const { remove } = options; + apply: (cldAsset, opts) => { + const { remove } = opts; const removeOptions: Record = { prompt: undefined, @@ -48,7 +48,7 @@ export const RemovePlugin = plugin({ if (hasPrompt && hasRegion) { throw new Error( - "Invalid remove options: you can not have both a prompt and a region. More info: https://cloudinary.com/documentation/transformation_reference#e_gen_remove" + "Invalid remove options: you can not have both a prompt and a region. More info: https://cloudinary.com/documentation/transformation_reference#e_gen_remove", ); } @@ -93,7 +93,7 @@ export const RemovePlugin = plugin({ */ function regionArrayToString( - regionArray: Array> + regionArray: Array>, ): string { const indexes: Record = { 0: "x", diff --git a/packages/url-loader/src/plugins/replace-background.ts b/packages/url-loader/src/plugins/replace-background.ts index 6a42e8ef..b69945f8 100644 --- a/packages/url-loader/src/plugins/replace-background.ts +++ b/packages/url-loader/src/plugins/replace-background.ts @@ -6,7 +6,7 @@ export declare namespace ReplaceBackgroundPlugin { * @description Replaces the background of an image with an AI-generated background. * @url https://cloudinary.com/documentation/transformation_reference#e_gen_background_replace */ - replaceBackground?: NestedOptions | string | number; + replaceBackground?: NestedOptions | string | boolean; } export interface NestedOptions { @@ -22,11 +22,10 @@ export const ReplaceBackgroundPlugin = plugin({ props: { replaceBackground: true, }, - apply: (cldAsset, options) => { - const { replaceBackground } = options; + apply: (cldAsset, opts) => { + const { replaceBackground } = opts; - if (!replaceBackground || typeof replaceBackground === "undefined") - return {}; + if (!replaceBackground) return {}; const properties = []; diff --git a/packages/url-loader/src/plugins/replace.ts b/packages/url-loader/src/plugins/replace.ts index 3463473d..9cb7ff93 100644 --- a/packages/url-loader/src/plugins/replace.ts +++ b/packages/url-loader/src/plugins/replace.ts @@ -24,34 +24,32 @@ export const ReplacePlugin = plugin({ props: { replace: true, }, - apply: (cldAsset, options) => { - const { replace = null } = options; - - if (replace) { - let from: string, - to: string, - preserveGeometry: boolean = false; - - if (isArray(replace)) { - from = replace[0] as string; - to = replace[1] as string; - preserveGeometry = (replace[2] as boolean) || false; - } else { - from = replace.from; - to = replace.to; - preserveGeometry = replace.preserveGeometry || false; - } - - const properties = [`e_gen_replace:from_${from}`, `to_${to}`]; - - // This property defaults to false, so we only need to pass it if it's true - if (preserveGeometry) { - properties.push(`preserve-geometry_${preserveGeometry}`); - } - - cldAsset.addTransformation(properties.join(";")); + apply: (cldAsset, opts) => { + const { replace } = opts; + + let from: string, + to: string, + preserveGeometry: boolean = false; + + if (isArray(replace)) { + from = replace[0] as string; + to = replace[1] as string; + preserveGeometry = (replace[2] as boolean) || false; + } else { + from = replace.from; + to = replace.to; + preserveGeometry = replace.preserveGeometry || false; } + const properties = [`e_gen_replace:from_${from}`, `to_${to}`]; + + // This property defaults to false, so we only need to pass it if it's true + if (preserveGeometry) { + properties.push(`preserve-geometry_${preserveGeometry}`); + } + + cldAsset.addTransformation(properties.join(";")); + return {}; }, }); diff --git a/packages/url-loader/src/plugins/restore.ts b/packages/url-loader/src/plugins/restore.ts index 21966b91..4ed987a6 100644 --- a/packages/url-loader/src/plugins/restore.ts +++ b/packages/url-loader/src/plugins/restore.ts @@ -17,8 +17,8 @@ export const RestorePlugin = plugin({ props: { restore: true, }, - apply: (cldAsset, options) => { - const { restore = false } = options; + apply: (cldAsset, opts) => { + const { restore } = opts; if (restore) { cldAsset.addTransformation("e_gen_restore"); diff --git a/packages/url-loader/src/plugins/sanitize.ts b/packages/url-loader/src/plugins/sanitize.ts index 3c24c39c..3c5836c8 100644 --- a/packages/url-loader/src/plugins/sanitize.ts +++ b/packages/url-loader/src/plugins/sanitize.ts @@ -17,12 +17,13 @@ export const SanitizePlugin = plugin({ props: { sanitize: true, }, - apply: (cldAsset, options) => { - const { sanitize = true } = options; + alwaysApply: true, + apply: (cldAsset, opts, ctx) => { + const { sanitize = true } = opts; const shouldApplySanitizer: boolean = sanitize && - (options.format === "svg" || + (ctx.format === "svg" || (cldAsset as {} as { publicID: string }).publicID.endsWith(".svg")); if (shouldApplySanitizer) { diff --git a/packages/url-loader/src/plugins/seo.ts b/packages/url-loader/src/plugins/seo.ts index 42c7292d..d2391a4d 100644 --- a/packages/url-loader/src/plugins/seo.ts +++ b/packages/url-loader/src/plugins/seo.ts @@ -17,17 +17,13 @@ export const SeoPlugin = plugin({ props: { seoSuffix: true, }, - apply: (cldAsset, options) => { - const { seoSuffix } = options; + apply: (cldAsset, opts, ctx) => { + const { seoSuffix } = opts; - if (typeof seoSuffix === "string") { - if (options.deliveryType === "fetch") { - console.warn( - "SEO suffix is not supported with a delivery type of fetch" - ); - } else { - cldAsset.setSuffix(seoSuffix); - } + if (ctx.deliveryType === "fetch") { + console.warn("SEO suffix is not supported with a delivery type of fetch"); + } else { + cldAsset.setSuffix(seoSuffix); } return {}; diff --git a/packages/url-loader/src/plugins/underlays.ts b/packages/url-loader/src/plugins/underlays.ts index 9378e456..3a172bef 100644 --- a/packages/url-loader/src/plugins/underlays.ts +++ b/packages/url-loader/src/plugins/underlays.ts @@ -50,8 +50,8 @@ export const UnderlaysPlugin = plugin({ underlay: true, underlays: true, }, - apply: (cldAsset, options) => { - const { underlay, underlays = [] } = options; + apply: (cldAsset, opts) => { + const { underlay, underlays = [] } = opts; const typeQualifier = "u"; @@ -96,7 +96,7 @@ export const UnderlaysPlugin = plugin({ let layerTransformation = `${typeQualifier}_${publicId.replace( /\//g, - ":" + ":", )}`; // Begin organizing transformations based on what it is and the location diff --git a/packages/url-loader/src/plugins/version.ts b/packages/url-loader/src/plugins/version.ts index f762b76d..b8fd376c 100644 --- a/packages/url-loader/src/plugins/version.ts +++ b/packages/url-loader/src/plugins/version.ts @@ -17,14 +17,12 @@ export const VersionPlugin = plugin({ props: { version: true, }, - apply: (cldAsset, options) => { - const { version } = options; + apply: (cldAsset, opts) => { + const { version } = opts; - if (typeof version === "string" || typeof version === "number") { - // Replace a `v` in the string just in case the caller - // passes it in - cldAsset.setVersion(`${version}`.replace("v", "")); - } + // Replace a `v` in the string just in case the caller + // passes it in + cldAsset.setVersion(`${version}`.replace("v", "")); return {}; }, diff --git a/packages/url-loader/src/plugins/zoompan.ts b/packages/url-loader/src/plugins/zoompan.ts index 5866df06..a3e75d73 100644 --- a/packages/url-loader/src/plugins/zoompan.ts +++ b/packages/url-loader/src/plugins/zoompan.ts @@ -24,8 +24,8 @@ export const ZoompanPlugin = plugin({ props: { zoompan: true, }, - apply: (cldAsset, options) => { - const { zoompan = false } = options; + apply: (cldAsset, opts) => { + const { zoompan = false } = opts; const overrides: PluginOptions = { format: undefined, diff --git a/packages/url-loader/src/types/asset.ts b/packages/url-loader/src/types/asset.ts index ae93cecc..f93fbf39 100644 --- a/packages/url-loader/src/types/asset.ts +++ b/packages/url-loader/src/types/asset.ts @@ -13,7 +13,7 @@ import type { UnderlaysPlugin } from "../plugins/underlays.js"; import type { VersionPlugin } from "../plugins/version.js"; import type { ZoompanPlugin } from "../plugins/zoompan.js"; -import type { Format } from '../constants/parameters.js'; +import type { Format } from "../constants/parameters.js"; export type SupportedAssetTypeInput = SupportedAssetType | "videos" | "images"; diff --git a/packages/url-loader/tests/plugins/default.spec.ts b/packages/url-loader/tests/plugins/default.spec.ts index ceee5ebe..ef01c82b 100644 --- a/packages/url-loader/tests/plugins/default.spec.ts +++ b/packages/url-loader/tests/plugins/default.spec.ts @@ -32,7 +32,7 @@ describe("Default Image plugin", () => { }; DefaultImagePlugin.apply(cldImage, options); expect(cldImage.toURL()).toContain( - `d_${options.defaultImage}/${TEST_PUBLIC_ID}` + `d_${options.defaultImage}/${TEST_PUBLIC_ID}`, ); }); it("should warn if no format", () => { @@ -45,10 +45,10 @@ describe("Default Image plugin", () => { }; DefaultImagePlugin.apply(cldImage, options); expect((console.warn as any).mock.calls[0][0]).toContain( - "The defaultImage prop may be missing" + "The defaultImage prop may be missing", ); expect(cldImage.toURL()).toContain( - `d_${options.defaultImage}/${TEST_PUBLIC_ID}` + `d_${options.defaultImage}/${TEST_PUBLIC_ID}`, ); }); }); diff --git a/packages/url-loader/tests/plugins/remove-background.spec.ts b/packages/url-loader/tests/plugins/remove-background.spec.ts index d5ccf7ad..701b3d5f 100644 --- a/packages/url-loader/tests/plugins/remove-background.spec.ts +++ b/packages/url-loader/tests/plugins/remove-background.spec.ts @@ -25,17 +25,5 @@ describe("Plugins", () => { expect(cldImage.toURL()).toContain(`e_background_removal`); }); - - it("should not remove the background", () => { - const cldImage = cld.image(TEST_PUBLIC_ID); - - const options = { - src: TEST_PUBLIC_ID, - }; - - RemoveBackgroundPlugin.apply(cldImage, options); - - expect(cldImage.toURL()).not.toContain(`e_background_removal`); - }); }); }); diff --git a/packages/url-loader/tests/plugins/replace.spec.ts b/packages/url-loader/tests/plugins/replace.spec.ts index 6ee0b3f2..e31a9beb 100644 --- a/packages/url-loader/tests/plugins/replace.spec.ts +++ b/packages/url-loader/tests/plugins/replace.spec.ts @@ -75,17 +75,5 @@ describe("Plugins", () => { `e_gen_replace:from_apple;to_candy%20bar;preserve-geometry_true`, ); }); - - it("should not attempt generative replace", () => { - const cldImage = cld.image(TEST_PUBLIC_ID); - - const options = { - src: TEST_PUBLIC_ID, - }; - - ReplacePlugin.apply(cldImage, options); - - expect(cldImage.toURL()).not.toContain(`e_gen_replace`); - }); }); }); diff --git a/packages/url-loader/tests/plugins/restore.spec.ts b/packages/url-loader/tests/plugins/restore.spec.ts index a70a4a74..f98f752e 100644 --- a/packages/url-loader/tests/plugins/restore.spec.ts +++ b/packages/url-loader/tests/plugins/restore.spec.ts @@ -25,17 +25,5 @@ describe("Plugins", () => { expect(cldImage.toURL()).toContain(`e_gen_restore`); }); - - it("should not restore", () => { - const cldImage = cld.image(TEST_PUBLIC_ID); - - const options = { - src: TEST_PUBLIC_ID, - }; - - RestorePlugin.apply(cldImage, options); - - expect(cldImage.toURL()).not.toContain(`e_gen_restore`); - }); }); }); diff --git a/packages/url-loader/tests/plugins/zoompan.spec.ts b/packages/url-loader/tests/plugins/zoompan.spec.ts index 5cfbd914..795dd2f7 100644 --- a/packages/url-loader/tests/plugins/zoompan.spec.ts +++ b/packages/url-loader/tests/plugins/zoompan.spec.ts @@ -26,18 +26,6 @@ describe("Plugins", () => { expect(cldImage.toURL()).toContain(`e_zoompan`); }); - it("should not zoom pan", () => { - const cldImage = cld.image(TEST_PUBLIC_ID); - - const options = { - src: TEST_PUBLIC_ID, - }; - - ZoompanPlugin.apply(cldImage, options); - - expect(cldImage.toURL()).not.toContain(`e_zoompan`); - }); - it("should add loop effect ", () => { const cldImage = cld.image(TEST_PUBLIC_ID); diff --git a/packages/util/CHANGELOG.md b/packages/util/CHANGELOG.md index d0422ae0..ef19c468 100644 --- a/packages/util/CHANGELOG.md +++ b/packages/util/CHANGELOG.md @@ -1,35 +1,30 @@ # [@cloudinary-util/util-v5.0.0-beta.1](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/util-v4.0.0...@cloudinary-util/util-v5.0.0-beta.1) (2024-10-18) - ### Features -* migrate Zod to pure TS w/ JSDoc, improve type safety and simplify parsing ([#217](https://github.com/cloudinary-community/cloudinary-util/issues/217)) ([f605f26](https://github.com/cloudinary-community/cloudinary-util/commit/f605f26f9de1d111c26d65dd3b8955491b357481)) +- migrate Zod to pure TS w/ JSDoc, improve type safety and simplify parsing ([#217](https://github.com/cloudinary-community/cloudinary-util/issues/217)) ([f605f26](https://github.com/cloudinary-community/cloudinary-util/commit/f605f26f9de1d111c26d65dd3b8955491b357481)) # [@cloudinary-util/util-v4.0.0](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/util-v3.4.0...@cloudinary-util/util-v4.0.0) (2024-10-15) - ### Features -* Change to Force Deploy ([#216](https://github.com/cloudinary-community/cloudinary-util/issues/216)) ([78e44a0](https://github.com/cloudinary-community/cloudinary-util/commit/78e44a043da447394280bdc9065910d0194517b8)) +- Change to Force Deploy ([#216](https://github.com/cloudinary-community/cloudinary-util/issues/216)) ([78e44a0](https://github.com/cloudinary-community/cloudinary-util/commit/78e44a043da447394280bdc9065910d0194517b8)) # [@cloudinary-util/util-v3.4.0](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/util-v3.3.2...@cloudinary-util/util-v3.4.0) (2024-10-15) - ### Features -* Util v4 ([#213](https://github.com/cloudinary-community/cloudinary-util/issues/213)) ([75fef30](https://github.com/cloudinary-community/cloudinary-util/commit/75fef30393a678f435acf8bbc4814e8da4a0bd40)) +- Util v4 ([#213](https://github.com/cloudinary-community/cloudinary-util/issues/213)) ([75fef30](https://github.com/cloudinary-community/cloudinary-util/commit/75fef30393a678f435acf8bbc4814e8da4a0bd40)) # [@cloudinary-util/util-v4.0.0-beta.1](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/util-v3.3.2...@cloudinary-util/util-v4.0.0-beta.1) (2024-10-08) - ### Features -* Log X-Cld-Error header in dev mode ([#211](https://github.com/cloudinary-community/cloudinary-util/issues/211)) ([2a5251b](https://github.com/cloudinary-community/cloudinary-util/commit/2a5251b83a44e22d11d4abf9def3bbd975a25f8c)) - +- Log X-Cld-Error header in dev mode ([#211](https://github.com/cloudinary-community/cloudinary-util/issues/211)) ([2a5251b](https://github.com/cloudinary-community/cloudinary-util/commit/2a5251b83a44e22d11d4abf9def3bbd975a25f8c)) ### BREAKING CHANGES -* pollForProcessingImage now returns an object instead of a boolean +- pollForProcessingImage now returns an object instead of a boolean # [@cloudinary-util/util-v3.3.2](https://github.com/cloudinary-community/cloudinary-util/compare/@cloudinary-util/util-v3.3.1...@cloudinary-util/util-v3.3.2) (2024-08-28) diff --git a/packages/util/src/lib/cloudinary.ts b/packages/util/src/lib/cloudinary.ts index bfc2e458..de9d05c1 100644 --- a/packages/util/src/lib/cloudinary.ts +++ b/packages/util/src/lib/cloudinary.ts @@ -181,7 +181,7 @@ export async function pollForProcessingImage( return { success: false, status: response.status, - error: response.headers.get('x-cld-error') || 'Unknown error', + error: response.headers.get("x-cld-error") || "Unknown error", }; } @@ -193,7 +193,7 @@ export async function pollForProcessingImage( return { success: false, status: 500, - error: (error as Error).message || 'Network error', + error: (error as Error).message || "Network error", }; } } diff --git a/packages/util/src/lib/util.ts b/packages/util/src/lib/util.ts index 70eaf50d..b783f009 100644 --- a/packages/util/src/lib/util.ts +++ b/packages/util/src/lib/util.ts @@ -32,7 +32,7 @@ export function objectHasKey(obj: T, key: PropertyKey): key is keyof T { export function sortByKey( array: Array = [], key: string, - type: string = "asc" + type: string = "asc", ) { function compare(a: any, b: any) { let keyA = a[key];