UNPKG

@flyyer/flyyer-lite

Version:

Flyyer.io helper classes and methods to generate smart URL to render images.

144 lines (130 loc) 4.75 kB
import type { IStringifyOptions } from "qs"; import type { FlyyerCommonParams } from "./common"; import type { FlyyerExtension } from "./ext"; import { invariant } from "./invariant"; import type { FlyyerMetaVariables } from "./meta"; import { FlyyerPath, normalizePath } from "./paths"; import { toQuery } from "./query"; import { CDN, isUndefined } from "./utils"; import { __V } from "./v"; import type { FlyyerVariables } from "./variables"; /** * This class helps you creating URLs that will render Flyyer images. * * Required is: `project`. * * Set default variables by using the `variables` object. * * Example: https://cdn.flyyer.io/v2/flyyer-com/_/_/marketplace/simple-fade * @example * const flyyer = new Flyyer({ * project: "flyyer-com", * route: "simple-fade", * }); * console.log(flyyer.href()) * // https://cdn.flyyer.io/v2/flyyer-com/_/_/marketplace/templates/simple-fade */ export interface FlyyerParams<T extends FlyyerVariables> extends FlyyerCommonParams<T> { /** * Your project's `slug`. Lowercase and no spaces. * Visit https://flyyer.io/dashboard to get this value for your project */ project: string; /** * Preferred way of declaring the default social image to use along with Flyyer. It will be available as `{{ page.image }}` and `{{ flyyer.default }}`. **Use an absolute URL**, but relative URLs are also supported. * * Alternatively you can set a custom meta-tag but it was worst performance: `<meta property="flyyer:default" content="" />`. * * Values defined here takes precedence over `flyyer:default` meta-tag. */ default?: string | undefined | null; /** * Current page path we will use in conjunction with the base URL defined in the Flyyer's Dashboard of your project. * @example * const flyyer = new Flyyer({ path: "/" }); * @example * const flyyer = new Flyyer({ path: "/about" }); * @example * const flyyer = new Flyyer({ path: "/products/1" }); * @example * const flyyer = new Flyyer({ path: ["products", "1"] }); * @example * const flyyer = new Flyyer({ path: "/page?id=1" }); */ path?: FlyyerPath; } export class Flyyer<T extends FlyyerVariables = FlyyerVariables> implements FlyyerParams<T> { public project: string; public default?: string | undefined | null; public path?: FlyyerPath; public extension?: FlyyerExtension | undefined | null; public variables: T; public meta: FlyyerMetaVariables; public secret?: string | undefined | null; public strategy?: "JWT" | "HMAC" | undefined | null; public constructor(args: FlyyerParams<T>) { invariant(args, "Flyyer constructor must not be empty. Expected object with 'project' property."); this.project = args.project; this.path = args.path; this.default = args.default; this.extension = args.extension; this.variables = args.variables || ({} as T); this.meta = args.meta || {}; this.secret = args.secret; this.strategy = args.strategy; } /** * Override this method to implement signatures. Must be synchronous (no `Promise` allowed). */ public sign( project: FlyyerParams<T>["project"], path: string, // normalized params: string, strategy: FlyyerParams<T>["strategy"], secret: FlyyerParams<T>["secret"], ): string | undefined | void {} public params(extra?: any, options?: IStringifyOptions): string { const meta = this.meta; const defaults = { __v: __V(meta.v), __id: meta.id, _w: meta.width, _h: meta.height, _res: meta.resolution, _ua: meta.agent, _def: this.default, _ext: this.extension, }; return toQuery(Object.assign(defaults, this.variables, extra), options); } /** * Generate final URL you can use in your og:images. * @example * <meta property="og:image" content={flyyer.href()} /> * @example * const flyyer = new Flyyer({ meta: { v: null } }); * <img src={flyyer.href()} /> */ public href(): string { const project = this.project; invariant(!isUndefined(project), "Missing 'project' property"); const path = normalizePath(this.path); const strategy = this.strategy; const secret = this.secret; const signature = this.sign(project, path, this.params({ __v: undefined }), strategy, secret); const params = this.params() || "_"; if (strategy && strategy.toUpperCase() === "JWT") { const __v = __V(this.meta.v); const query = toQuery({ __v }, { addQueryPrefix: true }); return `${CDN}/v2/${project}/jwt-${signature}${query}`; } else { return `${CDN}/v2/${project}/${signature || "_"}/${params}/${path}`; } } /** * Alias of `.href()` */ public toString() { return this.href(); } }