@eighty4/dank 0.0.5-2 → 0.0.5-4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/ServiceWorker.ts +89 -0
- package/lib/bin.ts +6 -5
- package/lib/build.ts +57 -5
- package/lib/build_tag.ts +119 -15
- package/lib/config.ts +56 -1
- package/lib/dank.ts +44 -2
- package/lib/esbuild.ts +1 -0
- package/lib/http.ts +3 -3
- package/lib/public.ts +4 -4
- package/lib/registry.ts +59 -31
- package/lib/service_worker.ts +63 -0
- package/lib_js/bin.js +6 -5
- package/lib_js/build.js +40 -4
- package/lib_js/build_tag.js +74 -14
- package/lib_js/config.js +43 -0
- package/lib_js/dank.js +2 -0
- package/lib_js/esbuild.js +1 -0
- package/lib_js/http.js +2 -2
- package/lib_js/public.js +1 -1
- package/lib_js/registry.js +39 -13
- package/lib_js/service_worker.js +47 -0
- package/lib_types/dank.d.ts +22 -0
- package/lib_types/service_worker.d.ts +10 -0
- package/package.json +3 -2
package/lib_js/registry.js
CHANGED
|
@@ -11,6 +11,7 @@ class WebsiteRegistry extends EventEmitter {
|
|
|
11
11
|
#copiedAssets = null;
|
|
12
12
|
// map of entrypoints to their output path
|
|
13
13
|
#entrypointHrefs = {};
|
|
14
|
+
#otherOutputs = null;
|
|
14
15
|
#pages = {};
|
|
15
16
|
#resolver;
|
|
16
17
|
#workers = null;
|
|
@@ -28,6 +29,13 @@ class WebsiteRegistry extends EventEmitter {
|
|
|
28
29
|
get htmlEntrypoints() {
|
|
29
30
|
return Object.values(this.#pages).map((p) => p.html);
|
|
30
31
|
}
|
|
32
|
+
async manifest() {
|
|
33
|
+
return {
|
|
34
|
+
buildTag: await this.#c.buildTag(),
|
|
35
|
+
files: this.files(),
|
|
36
|
+
pageUrls: Object.keys(this.#pages)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
31
39
|
get pageUrls() {
|
|
32
40
|
return Object.keys(this.#pages);
|
|
33
41
|
}
|
|
@@ -71,6 +79,18 @@ class WebsiteRegistry extends EventEmitter {
|
|
|
71
79
|
get workers() {
|
|
72
80
|
return this.#workers;
|
|
73
81
|
}
|
|
82
|
+
// add a build output that does is manually injected into build output,
|
|
83
|
+
// not from HTML processing, public directory, or esbuild entrypoints
|
|
84
|
+
async addBuildOutput(url, content) {
|
|
85
|
+
if (this.#pages[url] || this.#bundles.has(url) || this.#otherOutputs?.has(url) || this.#copiedAssets?.has(url)) {
|
|
86
|
+
throw Error("build already has a " + url);
|
|
87
|
+
}
|
|
88
|
+
if (this.#otherOutputs === null)
|
|
89
|
+
this.#otherOutputs = /* @__PURE__ */ new Set();
|
|
90
|
+
this.#otherOutputs.add(url);
|
|
91
|
+
const outputPath = join(this.#c.dirs.projectRootAbs, this.#c.dirs.buildDist, url);
|
|
92
|
+
await writeFile(outputPath, content);
|
|
93
|
+
}
|
|
74
94
|
buildRegistry() {
|
|
75
95
|
return new BuildRegistry(this.#c.dirs, this.#resolver, this.#onBuildManifest);
|
|
76
96
|
}
|
|
@@ -86,7 +106,10 @@ class WebsiteRegistry extends EventEmitter {
|
|
|
86
106
|
if (this.#copiedAssets)
|
|
87
107
|
for (const f of this.#copiedAssets)
|
|
88
108
|
files.add(f);
|
|
89
|
-
|
|
109
|
+
if (this.#otherOutputs)
|
|
110
|
+
for (const f of this.#otherOutputs)
|
|
111
|
+
files.add(f);
|
|
112
|
+
return Array.from(files);
|
|
90
113
|
}
|
|
91
114
|
mappedHref(lookup) {
|
|
92
115
|
const found = this.#entrypointHrefs[lookup];
|
|
@@ -96,13 +119,9 @@ class WebsiteRegistry extends EventEmitter {
|
|
|
96
119
|
throw Error(`mapped href for ${lookup} not found`);
|
|
97
120
|
}
|
|
98
121
|
}
|
|
99
|
-
async writeManifest(
|
|
100
|
-
const manifest = this.#manifest(
|
|
101
|
-
await writeFile(join(this.#c.dirs.projectRootAbs, this.#c.dirs.buildRoot, "website.json"), JSON.stringify(
|
|
102
|
-
buildTag,
|
|
103
|
-
files: Array.from(manifest.files),
|
|
104
|
-
pageUrls: Array.from(manifest.pageUrls)
|
|
105
|
-
}, null, 4));
|
|
122
|
+
async writeManifest() {
|
|
123
|
+
const manifest = await this.#manifest();
|
|
124
|
+
await writeFile(join(this.#c.dirs.projectRootAbs, this.#c.dirs.buildRoot, "website.json"), JSON.stringify(manifest, null, 4));
|
|
106
125
|
return manifest;
|
|
107
126
|
}
|
|
108
127
|
#configDiff() {
|
|
@@ -155,16 +174,16 @@ class WebsiteRegistry extends EventEmitter {
|
|
|
155
174
|
registration.html.removeAllListeners();
|
|
156
175
|
delete this.#pages[urlPath];
|
|
157
176
|
}
|
|
158
|
-
#manifest(
|
|
177
|
+
async #manifest() {
|
|
159
178
|
return {
|
|
160
|
-
buildTag,
|
|
179
|
+
buildTag: await this.#c.buildTag(),
|
|
161
180
|
files: this.files(),
|
|
162
|
-
pageUrls:
|
|
181
|
+
pageUrls: Object.keys(this.#pages)
|
|
163
182
|
};
|
|
164
183
|
}
|
|
165
184
|
#onBuildManifest = (build) => {
|
|
166
185
|
for (const [outPath, entrypoint] of Object.entries(build.bundles)) {
|
|
167
|
-
this.#bundles.add(outPath);
|
|
186
|
+
this.#bundles.add(ensurePath(outPath));
|
|
168
187
|
if (entrypoint) {
|
|
169
188
|
this.#entrypointHrefs[entrypoint] = outPath;
|
|
170
189
|
}
|
|
@@ -229,7 +248,7 @@ class BuildRegistry {
|
|
|
229
248
|
completeBuild(result) {
|
|
230
249
|
const bundles = {};
|
|
231
250
|
for (const [outPath, output] of Object.entries(result.metafile.outputs)) {
|
|
232
|
-
bundles[outPath.replace(/^build[/\\]dist/, "")] = output.entryPoint || null;
|
|
251
|
+
bundles[outPath.replace(/^build[/\\](dist|watch)/, "")] = output.entryPoint || null;
|
|
233
252
|
}
|
|
234
253
|
let workers = null;
|
|
235
254
|
if (this.#workers) {
|
|
@@ -254,6 +273,13 @@ class BuildRegistry {
|
|
|
254
273
|
});
|
|
255
274
|
}
|
|
256
275
|
}
|
|
276
|
+
function ensurePath(path) {
|
|
277
|
+
if (path.startsWith("/")) {
|
|
278
|
+
return path;
|
|
279
|
+
} else {
|
|
280
|
+
throw Error(`expect build dist path ${path} to start with /`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
257
283
|
export {
|
|
258
284
|
BuildRegistry,
|
|
259
285
|
WebsiteRegistry
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import esbuild from "esbuild";
|
|
3
|
+
async function createServiceWorker(caching) {
|
|
4
|
+
return {
|
|
5
|
+
outputs: [
|
|
6
|
+
{
|
|
7
|
+
content: await buildServiceWorkerBackend(caching),
|
|
8
|
+
url: "/sw.js"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
async function buildServiceWorkerBackend(caching) {
|
|
14
|
+
const result = await esbuild.build({
|
|
15
|
+
logLevel: "silent",
|
|
16
|
+
absWorkingDir: join(import.meta.dirname, "../client"),
|
|
17
|
+
entryPoints: ["ServiceWorker.ts"],
|
|
18
|
+
treeShaking: true,
|
|
19
|
+
target: "ES2022",
|
|
20
|
+
bundle: true,
|
|
21
|
+
minify: true,
|
|
22
|
+
format: "iife",
|
|
23
|
+
platform: "browser",
|
|
24
|
+
write: false,
|
|
25
|
+
metafile: true,
|
|
26
|
+
plugins: [
|
|
27
|
+
{
|
|
28
|
+
name: "DANK:sw",
|
|
29
|
+
setup(build) {
|
|
30
|
+
build.onResolve({ filter: /DANK:sw/ }, () => {
|
|
31
|
+
return {
|
|
32
|
+
path: join(import.meta.dirname, "DANK.sw.json")
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
build.onLoad({ filter: /DANK\.sw\.json$/, namespace: "file" }, async () => ({
|
|
36
|
+
contents: JSON.stringify(caching),
|
|
37
|
+
loader: "json"
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
});
|
|
43
|
+
return new TextDecoder().decode(result.outputFiles[0].contents);
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
createServiceWorker
|
|
47
|
+
};
|
package/lib_types/dank.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { Plugin as EsbuildPlugin } from 'esbuild';
|
|
2
2
|
export type DankConfig = {
|
|
3
|
+
buildTag?: string | BuildTagBuilder;
|
|
3
4
|
esbuild?: EsbuildConfig;
|
|
4
5
|
pages: Record<`/${string}`, `${string}.html` | PageMapping>;
|
|
5
6
|
devPages?: Record<`/__${string}`, `${string}.html` | DevPageMapping>;
|
|
6
7
|
port?: number;
|
|
7
8
|
previewPort?: number;
|
|
8
9
|
services?: Array<DevService>;
|
|
10
|
+
serviceWorker?: ServiceWorkerBuilder;
|
|
9
11
|
};
|
|
12
|
+
export type BuildTagParams = {
|
|
13
|
+
production: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type BuildTagBuilder = (build: BuildTagParams) => Promise<string> | string;
|
|
10
16
|
export type PageMapping = {
|
|
11
17
|
pattern?: RegExp;
|
|
12
18
|
webpage: `${string}.html`;
|
|
@@ -37,3 +43,19 @@ export type DankDetails = {
|
|
|
37
43
|
export type DankConfigFunction = (dank: DankDetails) => Partial<DankConfig> | Promise<Partial<DankConfig>>;
|
|
38
44
|
export declare function defineConfig(config: Partial<DankConfig>): Partial<DankConfig>;
|
|
39
45
|
export declare function defineConfig(config: DankConfigFunction): DankConfigFunction;
|
|
46
|
+
export type WebsiteManifest = {
|
|
47
|
+
buildTag: string;
|
|
48
|
+
files: Array<`/${string}`>;
|
|
49
|
+
pageUrls: Array<`/${string}`>;
|
|
50
|
+
};
|
|
51
|
+
export type ServiceWorkerParams = {
|
|
52
|
+
website: WebsiteManifest;
|
|
53
|
+
};
|
|
54
|
+
export type ServiceWorkerBuild = {
|
|
55
|
+
outputs: Array<{
|
|
56
|
+
url: `/${string}.js`;
|
|
57
|
+
content: string;
|
|
58
|
+
}>;
|
|
59
|
+
};
|
|
60
|
+
export type ServiceWorkerBuilder = (params: ServiceWorkerParams) => ServiceWorkerBuild | Promise<ServiceWorkerBuild>;
|
|
61
|
+
export { createServiceWorker, type ServiceWorkerCaching, } from './service_worker.ts';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ServiceWorkerBuild } from './dank.ts';
|
|
2
|
+
export type ServiceWorkerCaching = {
|
|
3
|
+
cacheKey: string;
|
|
4
|
+
bypassCache?: {
|
|
5
|
+
hosts?: Array<string>;
|
|
6
|
+
paths?: Array<`/${string}`>;
|
|
7
|
+
};
|
|
8
|
+
files: Array<`/${string}`>;
|
|
9
|
+
};
|
|
10
|
+
export declare function createServiceWorker(caching: ServiceWorkerCaching): Promise<ServiceWorkerBuild>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eighty4/dank",
|
|
3
|
-
"version": "0.0.5-
|
|
3
|
+
"version": "0.0.5-4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Adam McKee Bennett <adam.be.g84d@gmail.com>",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"files": [
|
|
40
40
|
"client/client.js",
|
|
41
|
+
"client/ServiceWorker.ts",
|
|
41
42
|
"lib/*.ts",
|
|
42
43
|
"lib_js/*.js",
|
|
43
44
|
"lib_types/*.d.ts"
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
"scripts": {
|
|
46
47
|
"build": "pnpm build:client && pnpm build:lib",
|
|
47
48
|
"build:client": "node scripts/build_client.ts",
|
|
48
|
-
"build:lib": "tsc && tsc -p tsconfig.exports.json",
|
|
49
|
+
"build:lib": "tsc && tsc -p tsconfig.exports.json && tsc -p tsconfig.sw.json",
|
|
49
50
|
"build:release": "pnpm build && node scripts/prepare_release.ts",
|
|
50
51
|
"fmt": "prettier --write .",
|
|
51
52
|
"fmtcheck": "prettier --check .",
|