1import * as Effect from "effect/Effect";
2import type { Plugin, PluginOption } from "vite";
3import { loadProjectModule } from "../../core/Loader.ts";
4import { loadVinextModule } from "../Modules.ts";
5
6export type VinextCacheKind = "redis" | "s3" | "kv";
7
8export interface VinextCacheOptions {
9 data?: { adapter: string; options?: Record<string, unknown> };
10 cdn?: { adapter: string; options?: Record<string, unknown> };
11}
12
13interface CacheModule {
14 VIRTUAL_CACHE_ADAPTERS: string;
15 VIRTUAL_CDN_CACHE_ADAPTER: string;
16 findVinextCacheConfigInPlugins(
17 plugins: PluginOption[] | undefined,
18 ): Promise<VinextCacheOptions | null>;
19 generateCacheAdaptersModule(cache: VinextCacheOptions): string;
20 generateCdnCacheAdapterModule(cache: VinextCacheOptions): string;
21}
22
23/** The deploy target owns data caching; native CDN configuration is preserved. */
24export const makeVinextCachePlugin = Effect.fn(function* (
25 root: string,
26 kind: VinextCacheKind,
27) {
28 const native = yield* loadVinextModule<CacheModule>(
29 root,
30 "cache/cache-adapters-virtual.js",
31 );
32 const { kvAdapter, redisAdapter, s3Adapter } = yield* loadProjectModule<
33 typeof import("./index.ts")
34 >(root, "@alchemy.run/frontend-frameworks/vinext/cache");
35 const data =
36 kind === "kv" ? kvAdapter() : kind === "s3" ? s3Adapter() : redisAdapter();
37 let cache: VinextCacheOptions = { data };
38 const adaptersId = "\0alchemy:vinext-cache-adapters";
39 const cdnId = "\0alchemy:vinext-cdn-cache-adapter";
40 return {
41 name: "alchemy:vinext-cache",
42 enforce: "pre",
43 async configResolved(config) {
44 const configured = await native.findVinextCacheConfigInPlugins([
45 ...config.plugins,
46 ]);
47 if (configured?.data && configured.data.adapter !== data.adapter) {
48 config.logger.warn(
49 "[alchemy] Website.Vinext owns the data-cache adapter; the adapter in vite.config is overridden.",
50 );
51 }
52 cache = { ...configured, data };
53 },
54 resolveId: {
55 order: "pre",
56 handler(id) {
57 if (id === native.VIRTUAL_CACHE_ADAPTERS) return adaptersId;
58 if (id === native.VIRTUAL_CDN_CACHE_ADAPTER) return cdnId;
59 },
60 },
61 load(id) {
62 if (id === adaptersId) return native.generateCacheAdaptersModule(cache);
63 if (id === cdnId) return native.generateCdnCacheAdapterModule(cache);
64 },
65 } satisfies Plugin;
66});