@eighty4/dank 0.0.5-2 → 0.0.5-3
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/lib/build.ts +1 -2
- package/lib/build_tag.ts +119 -15
- package/lib/config.ts +28 -0
- package/lib/dank.ts +10 -2
- package/lib_js/build.js +1 -2
- package/lib_js/build_tag.js +74 -14
- package/lib_js/config.js +20 -0
- package/lib_types/dank.d.ts +5 -0
- package/package.json +1 -1
package/lib/build.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
|
-
import { createBuildTag } from './build_tag.ts'
|
|
4
3
|
import { loadConfig, type ResolvedDankConfig } from './config.ts'
|
|
5
4
|
import { type DefineDankGlobal, createGlobalDefinitions } from './define.ts'
|
|
6
5
|
import type { DankDirectories } from './dirs.ts'
|
|
@@ -14,7 +13,7 @@ export async function buildWebsite(
|
|
|
14
13
|
if (!c) {
|
|
15
14
|
c = await loadConfig('build', process.cwd())
|
|
16
15
|
}
|
|
17
|
-
const buildTag = await
|
|
16
|
+
const buildTag = await c.buildTag()
|
|
18
17
|
console.log(
|
|
19
18
|
c.flags.minify
|
|
20
19
|
? c.flags.production
|
package/lib/build_tag.ts
CHANGED
|
@@ -1,25 +1,129 @@
|
|
|
1
1
|
import { exec } from 'node:child_process'
|
|
2
|
+
import type { DankConfig } from './dank.ts'
|
|
2
3
|
import type { DankFlags } from './flags.ts'
|
|
3
4
|
|
|
4
|
-
export async function createBuildTag(
|
|
5
|
+
export async function createBuildTag(
|
|
6
|
+
projectDir: string,
|
|
7
|
+
flags: DankFlags,
|
|
8
|
+
buildTagSource?: DankConfig['buildTag'],
|
|
9
|
+
): Promise<string> {
|
|
10
|
+
if (typeof buildTagSource === 'function') {
|
|
11
|
+
buildTagSource = await buildTagSource({ production: flags.production })
|
|
12
|
+
}
|
|
13
|
+
if (typeof buildTagSource === 'undefined' || buildTagSource === null) {
|
|
14
|
+
buildTagSource = await resolveExpressionDefault(projectDir)
|
|
15
|
+
}
|
|
16
|
+
if (typeof buildTagSource !== 'string') {
|
|
17
|
+
throw TypeError(
|
|
18
|
+
'DankConfig.buildTag must resolve to a string expession',
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
const params: BuildTagParams = {}
|
|
5
22
|
const now = new Date()
|
|
23
|
+
const paramPattern = new RegExp(/{{\s*(?<name>[a-z][A-Za-z]+)\s*}}/g)
|
|
24
|
+
let paramMatch: RegExpExecArray | null
|
|
25
|
+
let buildTag = buildTagSource
|
|
26
|
+
let offset = 0
|
|
27
|
+
while ((paramMatch = paramPattern.exec(buildTagSource)) != null) {
|
|
28
|
+
const paramName = paramMatch.groups!.name.trim() as keyof BuildTagParams
|
|
29
|
+
let paramValue: string
|
|
30
|
+
if (params[paramName]) {
|
|
31
|
+
paramValue = params[paramName]
|
|
32
|
+
} else {
|
|
33
|
+
paramValue = params[paramName] = await getParamValue(
|
|
34
|
+
projectDir,
|
|
35
|
+
paramName,
|
|
36
|
+
now,
|
|
37
|
+
buildTagSource,
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
buildTag =
|
|
41
|
+
buildTag.substring(0, paramMatch.index + offset) +
|
|
42
|
+
paramValue +
|
|
43
|
+
buildTag.substring(paramMatch.index + paramMatch[0].length + offset)
|
|
44
|
+
offset += paramValue.length - paramMatch[0].length
|
|
45
|
+
}
|
|
46
|
+
const validate = /^[A-Za-z\d][A-Za-z\d-_\.]+$/
|
|
47
|
+
if (!validate.test(buildTag)) {
|
|
48
|
+
throw Error(
|
|
49
|
+
`build tag ${buildTag} does not pass pattern ${validate.source} validation`,
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
return buildTag
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function resolveExpressionDefault(projectDir: string): Promise<string> {
|
|
56
|
+
const base = '{{ date }}-{{ timeMS }}'
|
|
57
|
+
const isGitRepo = await new Promise(res =>
|
|
58
|
+
exec('git rev-parse --is-inside-work-tree', { cwd: projectDir }, err =>
|
|
59
|
+
res(!err),
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
return isGitRepo ? base + '-{{ gitHash }}' : base
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
type BuildTagParams = {
|
|
66
|
+
date?: string
|
|
67
|
+
gitHash?: string
|
|
68
|
+
timeMS?: string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function getParamValue(
|
|
72
|
+
projectDir: string,
|
|
73
|
+
name: keyof BuildTagParams,
|
|
74
|
+
now: Date,
|
|
75
|
+
buildTagSource: string,
|
|
76
|
+
): Promise<string> {
|
|
77
|
+
switch (name) {
|
|
78
|
+
case 'date':
|
|
79
|
+
return getDate(now)
|
|
80
|
+
case 'gitHash':
|
|
81
|
+
try {
|
|
82
|
+
return await getGitHash(projectDir)
|
|
83
|
+
} catch (e) {
|
|
84
|
+
if (e === 'not-repo') {
|
|
85
|
+
throw Error(
|
|
86
|
+
`buildTag cannot use \`gitHash\` in \`${buildTagSource}\` outside of a git repository`,
|
|
87
|
+
)
|
|
88
|
+
} else {
|
|
89
|
+
throw e
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
case 'timeMS':
|
|
93
|
+
return getTimeMS(now)
|
|
94
|
+
default:
|
|
95
|
+
throw Error(name + ' is not a supported build tag param')
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function getDate(now: Date): string {
|
|
100
|
+
return now.toISOString().substring(0, 10)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function getGitHash(projectDir: string): Promise<string> {
|
|
104
|
+
return await new Promise((res, rej) =>
|
|
105
|
+
exec(
|
|
106
|
+
'git rev-parse --short HEAD',
|
|
107
|
+
{ cwd: projectDir },
|
|
108
|
+
(err, stdout, stderr) => {
|
|
109
|
+
if (err) {
|
|
110
|
+
if (stderr.includes('not a git repository')) {
|
|
111
|
+
rej('not-repo')
|
|
112
|
+
} else {
|
|
113
|
+
rej(err)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
res(stdout.trim())
|
|
117
|
+
},
|
|
118
|
+
),
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function getTimeMS(now: Date): string {
|
|
6
123
|
const ms =
|
|
7
124
|
now.getUTCMilliseconds() +
|
|
8
125
|
now.getUTCSeconds() * 1000 +
|
|
9
126
|
now.getUTCMinutes() * 1000 * 60 +
|
|
10
127
|
now.getUTCHours() * 1000 * 60 * 60
|
|
11
|
-
|
|
12
|
-
const time = String(ms).padStart(8, '0')
|
|
13
|
-
const when = `${date}-${time}`
|
|
14
|
-
if (flags.production) {
|
|
15
|
-
const gitHash = await new Promise((res, rej) =>
|
|
16
|
-
exec('git rev-parse --short HEAD', (err, stdout) => {
|
|
17
|
-
if (err) rej(err)
|
|
18
|
-
res(stdout.trim())
|
|
19
|
-
}),
|
|
20
|
-
)
|
|
21
|
-
return `${when}-${gitHash}`
|
|
22
|
-
} else {
|
|
23
|
-
return when
|
|
24
|
-
}
|
|
128
|
+
return String(ms).padStart(8, '0')
|
|
25
129
|
}
|
package/lib/config.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isAbsolute, resolve } from 'node:path'
|
|
2
|
+
import { createBuildTag } from './build_tag.ts'
|
|
2
3
|
import type {
|
|
3
4
|
DankConfig,
|
|
4
5
|
DankDetails,
|
|
@@ -34,6 +35,8 @@ export type ResolvedDankConfig = {
|
|
|
34
35
|
get devPages(): Readonly<DankConfig['devPages']>
|
|
35
36
|
get services(): Readonly<DankConfig['services']>
|
|
36
37
|
|
|
38
|
+
buildTag(): Promise<string>
|
|
39
|
+
|
|
37
40
|
reload(): Promise<void>
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -60,6 +63,7 @@ export async function loadConfig(
|
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
class DankConfigInternal implements ResolvedDankConfig {
|
|
66
|
+
#buildTag: DankConfig['buildTag']
|
|
63
67
|
#dirs: Readonly<DankDirectories>
|
|
64
68
|
#flags: Readonly<DankFlags>
|
|
65
69
|
#mode: 'build' | 'serve'
|
|
@@ -119,11 +123,20 @@ class DankConfigInternal implements ResolvedDankConfig {
|
|
|
119
123
|
return this.#services
|
|
120
124
|
}
|
|
121
125
|
|
|
126
|
+
async buildTag(): Promise<string> {
|
|
127
|
+
return await createBuildTag(
|
|
128
|
+
this.#dirs.projectRootAbs,
|
|
129
|
+
this.#flags,
|
|
130
|
+
this.#buildTag,
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
122
134
|
async reload() {
|
|
123
135
|
const userConfig = await resolveConfig(
|
|
124
136
|
this.#modulePath,
|
|
125
137
|
resolveDankDetails(this.#mode, this.#flags),
|
|
126
138
|
)
|
|
139
|
+
this.#buildTag = userConfig.buildTag
|
|
127
140
|
this.#dankPort = resolveDankPort(this.#flags, userConfig)
|
|
128
141
|
this.#esbuildPort = resolveEsbuildPort(this.#flags, userConfig)
|
|
129
142
|
this.#esbuild = Object.freeze(userConfig.esbuild)
|
|
@@ -173,6 +186,7 @@ function resolveDankDetails(
|
|
|
173
186
|
function validateDankConfig(c: Partial<DankConfig>) {
|
|
174
187
|
try {
|
|
175
188
|
validatePorts(c)
|
|
189
|
+
validateBuildTag(c.buildTag)
|
|
176
190
|
validatePages(c.pages)
|
|
177
191
|
validateDevPages(c.devPages)
|
|
178
192
|
validateDevServices(c.services)
|
|
@@ -202,6 +216,20 @@ function validatePorts(c: Partial<DankConfig>) {
|
|
|
202
216
|
}
|
|
203
217
|
}
|
|
204
218
|
|
|
219
|
+
function validateBuildTag(buildTag: DankConfig['buildTag']) {
|
|
220
|
+
if (buildTag === null) {
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
switch (typeof buildTag) {
|
|
224
|
+
case 'undefined':
|
|
225
|
+
case 'string':
|
|
226
|
+
case 'function':
|
|
227
|
+
return
|
|
228
|
+
default:
|
|
229
|
+
throw Error('DankConfig.buildTag must be a string or function')
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
205
233
|
function validateEsbuildConfig(esbuild?: EsbuildConfig) {
|
|
206
234
|
if (esbuild?.loaders !== null && typeof esbuild?.loaders !== 'undefined') {
|
|
207
235
|
if (typeof esbuild.loaders !== 'object') {
|
package/lib/dank.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Plugin as EsbuildPlugin } from 'esbuild'
|
|
2
2
|
|
|
3
3
|
export type DankConfig = {
|
|
4
|
-
// used for
|
|
5
|
-
|
|
4
|
+
// used for service worker caching
|
|
5
|
+
buildTag?: string | BuildTagBuilder
|
|
6
6
|
|
|
7
7
|
// customize esbuild configs
|
|
8
8
|
esbuild?: EsbuildConfig
|
|
@@ -26,6 +26,14 @@ export type DankConfig = {
|
|
|
26
26
|
services?: Array<DevService>
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export type BuildTagParams = {
|
|
30
|
+
production: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type BuildTagBuilder = (
|
|
34
|
+
build: BuildTagParams,
|
|
35
|
+
) => Promise<string> | string
|
|
36
|
+
|
|
29
37
|
// extend an html entrypoint with url rewriting similar to cdn configurations
|
|
30
38
|
// after trying all webpage, bundle and asset paths, mapping patterns
|
|
31
39
|
// will be tested in the alphabetical order of the webpage paths
|
package/lib_js/build.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { createBuildTag } from "./build_tag.js";
|
|
4
3
|
import { loadConfig } from "./config.js";
|
|
5
4
|
import { createGlobalDefinitions } from "./define.js";
|
|
6
5
|
import { esbuildWebpages, esbuildWorkers } from "./esbuild.js";
|
|
@@ -10,7 +9,7 @@ async function buildWebsite(c) {
|
|
|
10
9
|
if (!c) {
|
|
11
10
|
c = await loadConfig("build", process.cwd());
|
|
12
11
|
}
|
|
13
|
-
const buildTag = await
|
|
12
|
+
const buildTag = await c.buildTag();
|
|
14
13
|
console.log(c.flags.minify ? c.flags.production ? "minified production" : "minified" : "unminified", "build", buildTag, "building in ./build/dist");
|
|
15
14
|
await rm(c.dirs.buildRoot, { recursive: true, force: true });
|
|
16
15
|
await mkdir(c.dirs.buildDist, { recursive: true });
|
package/lib_js/build_tag.js
CHANGED
|
@@ -1,21 +1,81 @@
|
|
|
1
1
|
import { exec } from "node:child_process";
|
|
2
|
-
async function createBuildTag(flags) {
|
|
2
|
+
async function createBuildTag(projectDir, flags, buildTagSource) {
|
|
3
|
+
if (typeof buildTagSource === "function") {
|
|
4
|
+
buildTagSource = await buildTagSource({ production: flags.production });
|
|
5
|
+
}
|
|
6
|
+
if (typeof buildTagSource === "undefined" || buildTagSource === null) {
|
|
7
|
+
buildTagSource = await resolveExpressionDefault(projectDir);
|
|
8
|
+
}
|
|
9
|
+
if (typeof buildTagSource !== "string") {
|
|
10
|
+
throw TypeError("DankConfig.buildTag must resolve to a string expession");
|
|
11
|
+
}
|
|
12
|
+
const params = {};
|
|
3
13
|
const now = /* @__PURE__ */ new Date();
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const paramPattern = new RegExp(/{{\s*(?<name>[a-z][A-Za-z]+)\s*}}/g);
|
|
15
|
+
let paramMatch;
|
|
16
|
+
let buildTag = buildTagSource;
|
|
17
|
+
let offset = 0;
|
|
18
|
+
while ((paramMatch = paramPattern.exec(buildTagSource)) != null) {
|
|
19
|
+
const paramName = paramMatch.groups.name.trim();
|
|
20
|
+
let paramValue;
|
|
21
|
+
if (params[paramName]) {
|
|
22
|
+
paramValue = params[paramName];
|
|
23
|
+
} else {
|
|
24
|
+
paramValue = params[paramName] = await getParamValue(projectDir, paramName, now, buildTagSource);
|
|
25
|
+
}
|
|
26
|
+
buildTag = buildTag.substring(0, paramMatch.index + offset) + paramValue + buildTag.substring(paramMatch.index + paramMatch[0].length + offset);
|
|
27
|
+
offset += paramValue.length - paramMatch[0].length;
|
|
28
|
+
}
|
|
29
|
+
const validate = /^[A-Za-z\d][A-Za-z\d-_\.]+$/;
|
|
30
|
+
if (!validate.test(buildTag)) {
|
|
31
|
+
throw Error(`build tag ${buildTag} does not pass pattern ${validate.source} validation`);
|
|
32
|
+
}
|
|
33
|
+
return buildTag;
|
|
34
|
+
}
|
|
35
|
+
async function resolveExpressionDefault(projectDir) {
|
|
36
|
+
const base = "{{ date }}-{{ timeMS }}";
|
|
37
|
+
const isGitRepo = await new Promise((res) => exec("git rev-parse --is-inside-work-tree", { cwd: projectDir }, (err) => res(!err)));
|
|
38
|
+
return isGitRepo ? base + "-{{ gitHash }}" : base;
|
|
39
|
+
}
|
|
40
|
+
async function getParamValue(projectDir, name, now, buildTagSource) {
|
|
41
|
+
switch (name) {
|
|
42
|
+
case "date":
|
|
43
|
+
return getDate(now);
|
|
44
|
+
case "gitHash":
|
|
45
|
+
try {
|
|
46
|
+
return await getGitHash(projectDir);
|
|
47
|
+
} catch (e) {
|
|
48
|
+
if (e === "not-repo") {
|
|
49
|
+
throw Error(`buildTag cannot use \`gitHash\` in \`${buildTagSource}\` outside of a git repository`);
|
|
50
|
+
} else {
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
case "timeMS":
|
|
55
|
+
return getTimeMS(now);
|
|
56
|
+
default:
|
|
57
|
+
throw Error(name + " is not a supported build tag param");
|
|
17
58
|
}
|
|
18
59
|
}
|
|
60
|
+
function getDate(now) {
|
|
61
|
+
return now.toISOString().substring(0, 10);
|
|
62
|
+
}
|
|
63
|
+
async function getGitHash(projectDir) {
|
|
64
|
+
return await new Promise((res, rej) => exec("git rev-parse --short HEAD", { cwd: projectDir }, (err, stdout, stderr) => {
|
|
65
|
+
if (err) {
|
|
66
|
+
if (stderr.includes("not a git repository")) {
|
|
67
|
+
rej("not-repo");
|
|
68
|
+
} else {
|
|
69
|
+
rej(err);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
res(stdout.trim());
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
function getTimeMS(now) {
|
|
76
|
+
const ms = now.getUTCMilliseconds() + now.getUTCSeconds() * 1e3 + now.getUTCMinutes() * 1e3 * 60 + now.getUTCHours() * 1e3 * 60 * 60;
|
|
77
|
+
return String(ms).padStart(8, "0");
|
|
78
|
+
}
|
|
19
79
|
export {
|
|
20
80
|
createBuildTag
|
|
21
81
|
};
|
package/lib_js/config.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isAbsolute, resolve } from "node:path";
|
|
2
|
+
import { createBuildTag } from "./build_tag.js";
|
|
2
3
|
import { defaultProjectDirs } from "./dirs.js";
|
|
3
4
|
import { resolveFlags as lookupDankFlags } from "./flags.js";
|
|
4
5
|
var __rewriteRelativeImportExtension = function(path, preserveJsx) {
|
|
@@ -24,6 +25,7 @@ async function loadConfig(mode, projectRootAbs) {
|
|
|
24
25
|
return c;
|
|
25
26
|
}
|
|
26
27
|
class DankConfigInternal {
|
|
28
|
+
#buildTag;
|
|
27
29
|
#dirs;
|
|
28
30
|
#flags;
|
|
29
31
|
#mode;
|
|
@@ -67,8 +69,12 @@ class DankConfigInternal {
|
|
|
67
69
|
get services() {
|
|
68
70
|
return this.#services;
|
|
69
71
|
}
|
|
72
|
+
async buildTag() {
|
|
73
|
+
return await createBuildTag(this.#dirs.projectRootAbs, this.#flags, this.#buildTag);
|
|
74
|
+
}
|
|
70
75
|
async reload() {
|
|
71
76
|
const userConfig = await resolveConfig(this.#modulePath, resolveDankDetails(this.#mode, this.#flags));
|
|
77
|
+
this.#buildTag = userConfig.buildTag;
|
|
72
78
|
this.#dankPort = resolveDankPort(this.#flags, userConfig);
|
|
73
79
|
this.#esbuildPort = resolveEsbuildPort(this.#flags, userConfig);
|
|
74
80
|
this.#esbuild = Object.freeze(userConfig.esbuild);
|
|
@@ -99,6 +105,7 @@ function resolveDankDetails(mode, flags) {
|
|
|
99
105
|
function validateDankConfig(c) {
|
|
100
106
|
try {
|
|
101
107
|
validatePorts(c);
|
|
108
|
+
validateBuildTag(c.buildTag);
|
|
102
109
|
validatePages(c.pages);
|
|
103
110
|
validateDevPages(c.devPages);
|
|
104
111
|
validateDevServices(c.services);
|
|
@@ -119,6 +126,19 @@ function validatePorts(c) {
|
|
|
119
126
|
}
|
|
120
127
|
}
|
|
121
128
|
}
|
|
129
|
+
function validateBuildTag(buildTag) {
|
|
130
|
+
if (buildTag === null) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
switch (typeof buildTag) {
|
|
134
|
+
case "undefined":
|
|
135
|
+
case "string":
|
|
136
|
+
case "function":
|
|
137
|
+
return;
|
|
138
|
+
default:
|
|
139
|
+
throw Error("DankConfig.buildTag must be a string or function");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
122
142
|
function validateEsbuildConfig(esbuild) {
|
|
123
143
|
if (esbuild?.loaders !== null && typeof esbuild?.loaders !== "undefined") {
|
|
124
144
|
if (typeof esbuild.loaders !== "object") {
|
package/lib_types/dank.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
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>;
|
|
@@ -7,6 +8,10 @@ export type DankConfig = {
|
|
|
7
8
|
previewPort?: number;
|
|
8
9
|
services?: Array<DevService>;
|
|
9
10
|
};
|
|
11
|
+
export type BuildTagParams = {
|
|
12
|
+
production: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type BuildTagBuilder = (build: BuildTagParams) => Promise<string> | string;
|
|
10
15
|
export type PageMapping = {
|
|
11
16
|
pattern?: RegExp;
|
|
12
17
|
webpage: `${string}.html`;
|