-
Notifications
You must be signed in to change notification settings - Fork 204
/
plugin.ts
83 lines (72 loc) · 2.42 KB
/
plugin.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import path from "path";
import {
Compatibility,
Log,
Option,
OptionType,
Plugin,
SetupResult,
globsToMatcher,
} from "@miniflare/shared";
import { FilteredKVNamespace } from "./filtered";
export interface SitesOptions {
sitePath?: string;
siteInclude?: string[];
siteExclude?: string[];
}
export class SitesPlugin extends Plugin<SitesOptions> implements SitesOptions {
@Option({
type: OptionType.STRING,
name: "site",
alias: "s",
description: "Path to serve Workers Site files from",
logName: "Workers Site Path",
fromWrangler: ({ site }) => site?.bucket,
})
sitePath?: string;
@Option({
type: OptionType.ARRAY,
description: "Glob pattern of site files to serve",
logName: "Workers Site Include",
fromWrangler: ({ site }) => site?.include,
})
siteInclude?: string[];
@Option({
type: OptionType.ARRAY,
description: "Glob pattern of site files not to serve",
logName: "Workers Site Exclude",
fromWrangler: ({ site }) => site?.exclude,
})
siteExclude?: string[];
readonly #setupResult: Promise<SetupResult>;
constructor(log: Log, compat: Compatibility, options?: SitesOptions) {
super(log, compat);
this.assignOptions(options);
// setup() will be called each time a site file changes, but there's no need
// to recreate the namespace each time, so create it once and then return it
this.#setupResult = this.#setup();
}
async #setup(): Promise<SetupResult> {
if (!this.sitePath) return {};
// Create file KV storage with sanitisation DISABLED so paths containing
// /'s resolve correctly
const { FileStorage } = await import("@miniflare/storage-file");
const storage = new FileStorage(path.resolve(this.sitePath), false);
const bindings = {
__STATIC_CONTENT: new FilteredKVNamespace(storage, {
readOnly: true,
include: this.siteInclude && globsToMatcher(this.siteInclude),
exclude: this.siteExclude && globsToMatcher(this.siteExclude),
}),
// Empty manifest means @cloudflare/kv-asset-handler will use the request
// path as the file path and won't edge cache files
__STATIC_CONTENT_MANIFEST: {},
};
// Whilst FileStorage will always serve the latest files, we want to
// force a reload when these files change for live reload.
return { bindings, watch: [this.sitePath] };
}
async setup(): Promise<SetupResult> {
return this.#setupResult;
}
}