UNPKG

@embeddable.com/sdk-core

Version:

Core Embeddable SDK module responsible for web-components bundling and publishing.

313 lines (292 loc) 9.04 kB
import * as path from "node:path"; import { existsSync } from "node:fs"; import { RollupOptions } from "rollup"; import { z } from "zod"; import { errorFormatter, ComponentLibraryConfig, } from "@embeddable.com/sdk-utils"; export type Region = "EU" | "US" | "legacy-US"; export type EmbeddableConfig = { plugins: (() => { pluginName: string; build: (config: ResolvedEmbeddableConfig) => Promise<unknown>; cleanup: (config: ResolvedEmbeddableConfig) => Promise<unknown>; validate: (config: ResolvedEmbeddableConfig) => Promise<unknown>; buildPackage: (config: ResolvedEmbeddableConfig) => Promise<unknown>; })[]; pushModels?: boolean; pushComponents?: boolean; pushBaseUrl?: string; audienceUrl?: string; authDomain?: string; authClientId?: string; errorFallbackComponent?: string; applicationEnvironment?: string; rollbarAccessToken?: string; previewBaseUrl?: string; componentsSrc?: string; modelsSrc?: string; presetsSrc?: string; customCanvasCss?: string; viteConfig?: { resolve?: { alias?: Record<string, string>; }; }; rollupOptions?: RollupOptions; region?: Region; componentLibraries?: string[] | ComponentLibraryConfig[]; customizationFile?: string; lifecycleHooksFile?: string; }; const PLUGIN_NAME = "sdk-react" as const; export type PluginName = typeof PLUGIN_NAME; export type ResolvedEmbeddableConfig = { core: { rootDir: string; templatesDir: string; configsDir: string; }; client: { rootDir: string; srcDir: string; modelsSrc: string; presetsSrc: string; buildDir: string; tmpDir: string; customCanvasCss: string; webComponentRoot: string; componentDir: string; stencilBuild: string; archiveFile: string; errorFallbackComponent?: string; bundleHash?: string; customizationFile: string; lifecycleHooksFile: string; componentLibraries: string[] | ComponentLibraryConfig[]; viteConfig: { resolve?: { alias?: Record<string, string>; }; }; rollupOptions: RollupOptions; }; outputOptions: { typesEntryPointFilename: string; }; pushModels: boolean; pushComponents: boolean; pushBaseUrl: string; audienceUrl: string; previewBaseUrl: string; authDomain: string; authClientId: string; applicationEnvironment: string; rollbarAccessToken: string; plugins: EmbeddableConfig["plugins"]; buildTime: [number, number]; dev?: { watch: boolean; logger: any; sys: any; }; region: Region; [PLUGIN_NAME]: { rootDir: string; templatesDir: string; outputOptions: { fileName: string; buildName: string; componentsEntryPointFilename: string; }; }; }; const REGION_CONFIGS = { EU: { pushBaseUrl: "https://api.eu.embeddable.com", audienceUrl: "https://auth.eu.embeddable.com", previewBaseUrl: "https://app.eu.embeddable.com", authDomain: "auth.eu.embeddable.com", authClientId: "6OGPwIQsVmtrBKhNrwAaXhz4ePb0kBGV", }, US: { pushBaseUrl: "https://api.us.embeddable.com", audienceUrl: "https://auth.embeddable.com", previewBaseUrl: "https://app.us.embeddable.com", authDomain: "auth.embeddable.com", authClientId: "dygrSUmI6HmgY5ymVbEAoLDEBxIOyr1V", }, "legacy-US": { pushBaseUrl: "https://api.embeddable.com", audienceUrl: "https://auth.embeddable.com", previewBaseUrl: "https://app.embeddable.com", authDomain: "auth.embeddable.com", authClientId: "dygrSUmI6HmgY5ymVbEAoLDEBxIOyr1V", }, }; const ComponentLibraryConfigSchema = z.object({ name: z.string(), include: z.array(z.string()).optional(), exclude: z.array(z.string()).optional(), }); export const embeddableConfigSchema = z .object({ plugins: z.array(z.function()), region: z .union([z.literal("EU"), z.literal("US"), z.literal("legacy-US")]) .optional(), pushModels: z.boolean().optional(), pushComponents: z.boolean().optional(), pushBaseUrl: z.string().optional(), audienceUrl: z.string().optional(), authDomain: z.string().optional(), authClientId: z.string().optional(), errorFallbackComponent: z.string().optional(), applicationEnvironment: z.string().optional(), rollbarAccessToken: z.string().optional(), previewBaseUrl: z.string().optional(), modelsSrc: z.string().optional(), presetsSrc: z.string().optional(), componentsSrc: z.string().optional(), customCanvasCss: z.string().optional(), customizationFile: z.string().optional(), lifecycleHooksFile: z.string().optional(), componentLibraries: z .union([z.array(z.string()), z.array(ComponentLibraryConfigSchema)]) .optional(), viteConfig: z .object({ resolve: z .object({ alias: z.record(z.string()), }) .optional(), }) .optional(), rollupOptions: z.object({}).optional(), }) .strict(); export default (config: EmbeddableConfig) => { const safeParse = embeddableConfigSchema.safeParse(config); const errors: string[] = []; if (!safeParse.success) { errorFormatter(safeParse.error.issues).forEach((error) => { errors.push(`${error}`); }); } if (errors.length > 0) { throw new Error(`Invalid Embeddable Configuration: ${errors.join("\n")}}`); } let { plugins, region = "legacy-US", pushModels = true, pushComponents = true, pushBaseUrl, audienceUrl, authDomain, authClientId, errorFallbackComponent, applicationEnvironment, rollbarAccessToken, previewBaseUrl, modelsSrc = "src", presetsSrc = "src", componentsSrc = "src", customCanvasCss = "src/custom-canvas.css", viteConfig = {}, rollupOptions = {}, componentLibraries = [], customizationFile = "embeddable.theme.ts", lifecycleHooksFile = "lifecycle.config.ts", } = config; const regionConfig = REGION_CONFIGS[region]; const __dirname = import.meta.dirname; const coreRoot = path.resolve(__dirname, ".."); const clientRoot = process.cwd(); if (!path.isAbsolute(componentsSrc)) { componentsSrc = path.resolve(clientRoot, componentsSrc); if (!existsSync(componentsSrc)) { throw new Error( `componentsSrc directory ${componentsSrc} does not exist` ); } } if (modelsSrc && !path.isAbsolute(modelsSrc)) { modelsSrc = path.resolve(clientRoot, modelsSrc); if (!existsSync(modelsSrc)) { throw new Error(`modelsSrc directory ${modelsSrc} does not exist`); } } if (presetsSrc && !path.isAbsolute(presetsSrc)) { presetsSrc = path.resolve(clientRoot, presetsSrc); if (!existsSync(presetsSrc)) { throw new Error(`presetsSrc directory ${presetsSrc} does not exist`); } } return { core: { rootDir: coreRoot, templatesDir: path.resolve(coreRoot, "templates"), configsDir: path.resolve(coreRoot, "configs"), }, client: { rootDir: clientRoot, srcDir: path.resolve(clientRoot, componentsSrc), modelsSrc: modelsSrc ? path.resolve(clientRoot, modelsSrc) : undefined, presetsSrc: presetsSrc ? path.resolve(clientRoot, presetsSrc) : undefined, buildDir: path.resolve(clientRoot, ".embeddable-build"), tmpDir: path.resolve(clientRoot, ".embeddable-tmp"), customCanvasCss: path.resolve(clientRoot, customCanvasCss), webComponentRoot: path.resolve( clientRoot, ".embeddable-build", "web-component" ), componentDir: path.resolve( clientRoot, ".embeddable-build", "web-component", "component" ), stencilBuild: path.resolve( clientRoot, ".embeddable-build", "dist", "embeddable-wrapper" ), archiveFile: path.resolve(clientRoot, "embeddable-build.zip"), errorFallbackComponent: errorFallbackComponent ? path.resolve(clientRoot, errorFallbackComponent) : undefined, bundleHash: undefined, // This will be set by the build process viteConfig, rollupOptions, componentLibraries, customizationFile: path.resolve(clientRoot, customizationFile), lifecycleHooksFile: path.resolve(clientRoot, lifecycleHooksFile), }, outputOptions: { typesEntryPointFilename: "embeddable-types-entry-point.js", }, buildTime: undefined, // This will be set by the build process dev: { watch: false, logger: undefined, sys: undefined, }, region, pushModels, pushComponents, pushBaseUrl: pushBaseUrl ?? regionConfig.pushBaseUrl, audienceUrl: audienceUrl ?? regionConfig.audienceUrl, previewBaseUrl: previewBaseUrl ?? regionConfig.previewBaseUrl, authDomain: authDomain ?? regionConfig.authDomain, authClientId: authClientId ?? regionConfig.authClientId, applicationEnvironment: applicationEnvironment ?? "production", rollbarAccessToken: rollbarAccessToken ?? "5c6028038d844bf1835a0f4db5f55d9e", plugins, }; };