|
10 | 10 | import type { D1Database } from "@cloudflare/workers-types"; |
11 | 11 | import { WorkerEntrypoint } from "cloudflare:workers"; |
12 | 12 | import type { SandboxEmailSendCallback } from "emdash"; |
13 | | -import { ulid, PluginStorageRepository } from "emdash"; |
| 13 | +import { |
| 14 | + handleObjectCachePurge, |
| 15 | + handleObjectCacheStatus, |
| 16 | + handleWorkersCachePurge, |
| 17 | + handleWorkersCacheStatus, |
| 18 | + ulid, |
| 19 | + PluginStorageRepository, |
| 20 | +} from "emdash"; |
14 | 21 | import { Kysely } from "kysely"; |
15 | 22 | import { D1Dialect } from "kysely-d1"; |
16 | 23 |
|
@@ -1173,6 +1180,70 @@ export class PluginBridge extends WorkerEntrypoint<PluginBridgeEnv, PluginBridge |
1173 | 1180 | await emailSendCallback(message, pluginId); |
1174 | 1181 | } |
1175 | 1182 |
|
| 1183 | + // ========================================================================= |
| 1184 | + // Object cache — capability-gated (cache:purge) |
| 1185 | + // ========================================================================= |
| 1186 | + |
| 1187 | + async getObjectCacheStatus(): Promise<{ configured: boolean }> { |
| 1188 | + const { capabilities } = this.ctx.props; |
| 1189 | + if (!capabilities.includes("cache:purge")) { |
| 1190 | + throw new Error("Missing capability: cache:purge"); |
| 1191 | + } |
| 1192 | + const result = await handleObjectCacheStatus(); |
| 1193 | + if (!result.success) { |
| 1194 | + throw new Error(result.error.message); |
| 1195 | + } |
| 1196 | + return result.data; |
| 1197 | + } |
| 1198 | + |
| 1199 | + async purgeObjectCache(options?: { |
| 1200 | + namespaces?: string[]; |
| 1201 | + }): Promise<{ configured: boolean; active: boolean; purged: string[] }> { |
| 1202 | + const { capabilities } = this.ctx.props; |
| 1203 | + if (!capabilities.includes("cache:purge")) { |
| 1204 | + throw new Error("Missing capability: cache:purge"); |
| 1205 | + } |
| 1206 | + const db = new Kysely<unknown>({ |
| 1207 | + dialect: new D1Dialect({ database: this.env.DB }), |
| 1208 | + }); |
| 1209 | + // eslint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- D1 dialect matches core handler db shape |
| 1210 | + const result = await handleObjectCachePurge(db as never, { |
| 1211 | + namespaces: options?.namespaces, |
| 1212 | + }); |
| 1213 | + if (!result.success) { |
| 1214 | + throw new Error(result.error.message); |
| 1215 | + } |
| 1216 | + return result.data; |
| 1217 | + } |
| 1218 | + |
| 1219 | + async getWorkersCacheStatus(): Promise<{ configured: boolean }> { |
| 1220 | + const { capabilities } = this.ctx.props; |
| 1221 | + if (!capabilities.includes("cache:purge")) { |
| 1222 | + throw new Error("Missing capability: cache:purge"); |
| 1223 | + } |
| 1224 | + const result = await handleWorkersCacheStatus(); |
| 1225 | + if (!result.success) { |
| 1226 | + throw new Error(result.error.message); |
| 1227 | + } |
| 1228 | + return result.data; |
| 1229 | + } |
| 1230 | + |
| 1231 | + async purgeWorkersCache(options?: { |
| 1232 | + pathPrefixes?: string[]; |
| 1233 | + }): Promise<{ configured: boolean; purged: boolean; pathPrefixes?: string[] }> { |
| 1234 | + const { capabilities } = this.ctx.props; |
| 1235 | + if (!capabilities.includes("cache:purge")) { |
| 1236 | + throw new Error("Missing capability: cache:purge"); |
| 1237 | + } |
| 1238 | + const result = await handleWorkersCachePurge({ |
| 1239 | + pathPrefixes: options?.pathPrefixes, |
| 1240 | + }); |
| 1241 | + if (!result.success) { |
| 1242 | + throw new Error(result.error.message); |
| 1243 | + } |
| 1244 | + return result.data; |
| 1245 | + } |
| 1246 | + |
1176 | 1247 | // ========================================================================= |
1177 | 1248 | // Logging |
1178 | 1249 | // ========================================================================= |
|
0 commit comments