Skip to content

Commit

Permalink
refactor: remove applyWhen in favor of explicit props overlap check w…
Browse files Browse the repository at this point in the history
…ith alwaysApply exception
  • Loading branch information
ssalbdivad committed Oct 25, 2024
1 parent 5e9849e commit c4023b1
Show file tree
Hide file tree
Showing 41 changed files with 207 additions and 260 deletions.
2 changes: 1 addition & 1 deletion docs/src/components/SchemaTable/SchemaTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const SchemaTable = ({ schema, schemaKey }) => {
};

return property;
}
},
);

const sortedProperties = sortByKey(formattedProperties, "name");
Expand Down
6 changes: 2 additions & 4 deletions packages/types/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
22 changes: 3 additions & 19 deletions packages/url-loader/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
2 changes: 1 addition & 1 deletion packages/url-loader/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
31 changes: 16 additions & 15 deletions packages/url-loader/src/lib/cloudinary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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 {}
Expand Down Expand Up @@ -133,7 +133,7 @@ export interface ConstructUrlProps<
*/
config?: ConfigOptions;
// prioritize inferring assetType so available options can be derived from it
options: { assetType?: assetType } & OptionsFor<assetType>;
options: { assetType?: assetType } & CtxParam<assetType>;
}

export type CldAsset = CloudinaryImage | CloudinaryVideo;
Expand All @@ -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.`,
);
}

Expand Down Expand Up @@ -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;
}
Expand All @@ -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
Expand Down Expand Up @@ -315,7 +316,7 @@ interface SearchAssetRawTransformationsOptions {
export function searchAssetRawTransformations(
query: string,
asset: CloudinaryImage | CloudinaryVideo,
options?: SearchAssetRawTransformationsOptions
options?: SearchAssetRawTransformationsOptions,
) {
if (typeof asset.transformation === "undefined") return;

Expand All @@ -329,7 +330,7 @@ export function searchAssetRawTransformations(
.toString()
.split("/")
.flatMap((seg) => seg.split(","));
}
},
);

const matches = transformations.filter((transformation) => {
Expand Down
82 changes: 56 additions & 26 deletions packages/url-loader/src/lib/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<assetType, when>;
apply: PluginApplicationDefinition<assetType, options, alwaysApply>;
inferOwnOptions: options;
props: Record<keyof options, true>;
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<assetType, when>;
inferOwnOptions: options;
props: Record<keyof options, true>;
applyWhen?: when | undefined;
apply: PluginApplication<assetType, opts, alwaysApply>;
inferOwnOptions: opts;
props: Record<keyof opts, true>;
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<opts>]: Exclude<opts[k], undefined> });

export type CtxParam<assetType extends SupportedAssetTypeInput> =
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<opts> = {
[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<opts, alwaysApply>,
ctx: CtxParam<assetType>,
) => PluginResults;

export type PluginApplication<
assetType extends SupportedAssetType,
when extends ApplyWhen = AlwaysApply,
> = (cldAsset: CldAsset, options: OptionsFor<assetType, when>) => PluginResults;
opts extends object,
alwaysApply extends boolean,
> = (
cldAsset: CldAsset,
// externally, we want the wider assetType options as well
opts: OwnOptionsParam<opts, alwaysApply> & CtxParam<assetType>,
) => PluginResults;

export const plugin = <
asset extends SupportedAssetType,
when extends ApplyWhen,
name extends string,
options extends object,
opts extends object,
alwaysApply extends boolean,
>(
def: PluginDefinition<asset, when, name, options>
): TransformationPlugin<asset, when, name, options> =>
({ strict: false, ...def }) as never;
def: PluginDefinition<asset, name, opts, alwaysApply>,
): TransformationPlugin<asset, name, opts, alwaysApply> =>
({
strict: false,
alwaysApply: false,
...def,
apply: (cldAsset, ctx) => def.apply(cldAsset, ctx as never, ctx as never),
}) satisfies TransformationPlugin as never;
4 changes: 2 additions & 2 deletions packages/url-loader/src/lib/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/url-loader/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const entriesOf: <o extends object>(o: o) => entryOf<o>[] =
*/
export const throwError: (
message: string,
ctor?: new (message: string) => Error
ctor?: new (message: string) => Error,
) => never = (message, ctor = Error) => {
throw new ctor(message);
};
Expand Down
6 changes: 3 additions & 3 deletions packages/url-loader/src/lib/video-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface GetVideoPlayerOptionsLogo {

export function getVideoPlayerOptions(
options: GetVideoPlayerOptions,
config: CloudinaryAssetConfiguration
config: CloudinaryAssetConfiguration,
) {
const {
autoplay,
Expand All @@ -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.",
);
}

Expand All @@ -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.",
);
}

Expand Down
5 changes: 1 addition & 4 deletions packages/url-loader/src/plugins/abr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
},
Expand Down
Loading

0 comments on commit c4023b1

Please sign in to comment.