-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathtsup.config.ts
100 lines (90 loc) · 3.53 KB
/
tsup.config.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import * as dotenv from "dotenv";
import { execaCommand } from "execa";
import { extract, parse } from "jest-docblock";
import { readFileSync, readdirSync } from "node:fs";
import slugify from "@sindresorhus/slugify";
import { resolve } from "node:path";
import prependFile from "prepend-file";
import { defineConfig } from "tsup";
dotenv.config();
const copyCommand = process.env.COPY_COMMAND;
const devicesConfiguration = process.env.DEVICES ?? '["main"]';
// Read src/config.ts and prepare the configuration section to be prepended to script files
const configFileContents = readFileSync("src/config.ts", { encoding: "utf-8" });
const scriptConfig = /BEGIN JS(?:\r?\n|\r)([\s\S]+)/
.exec(configFileContents)![1]
.replace('devices: ["main"]', `devices: ${devicesConfiguration}`);
// Create a list of all available device configurations and their target directory names by
// enumerating the `src/devices` directory and parsing all `vendor` and `device` pragmas of the
// files therein.
const deviceConfigsDir = "./src/device-configs/";
const devices = readdirSync(deviceConfigsDir)
.map((filename) => ({
...(parse(extract(readFileSync(deviceConfigsDir + filename, { encoding: "utf-8" }))) as {
vendor: string;
device: string;
}),
deviceConfigFilename: filename,
}))
.filter(({ vendor, device }) => vendor && device)
.map(({ deviceConfigFilename, vendor, device }) => {
const vendorFolder = slugify(vendor, { decamelize: false });
const deviceFolder = slugify(
device.replace(/^X-Touch$/, "xtouch"), // for setup instructions backwards compatibility
{ decamelize: false },
);
return {
deviceConfigFilename,
vendor,
device,
targetFilename: `${vendorFolder}_${deviceFolder}`,
targetPath: `dist/${vendorFolder}/${deviceFolder}`,
};
});
export default defineConfig(
devices.map((device) => ({
entry: { [device.targetFilename]: "src/index.ts" },
outDir: device.targetPath,
clean: true,
external: ["midiremote_api_v1"],
onSuccess: async () => {
// Remove all config options with a non-matching `@devices` pragma
const deviceSpecificScriptConfig = scriptConfig.replace(
/(?:\r?\n|\r)\s*\/\*\*\s*(?:\r?\n|\r)(?:[^\*]|(?:\*(?!\/)))*@devices ([\S ]+)(?:\r?\n|\r)\s+\*\/(?:\r?\n|\r)[\S ]+/gm,
(match, devicesPragma: string) => {
// Remove devices pragma from match
match = match.replace(/\*(\r?\n|\r)([\S ]+)(\r?\n|\r)*@devices [\S ]+(\r?\n|\r)\s+/, "");
const supportedDevices = devicesPragma.split(", ");
if (devicesPragma.includes("!")) {
// Negative mode – include everything *but* the specified device(s)
return supportedDevices.includes("!" + device.device) ? "" : match;
}
return supportedDevices.includes(device.device) ? match : "";
},
);
await prependFile(
`${device.targetPath}/${device.targetFilename}.js`,
deviceSpecificScriptConfig,
);
if (copyCommand) {
await execaCommand(copyCommand, { shell: true, stdout: process.stdout });
}
},
define: {
SCRIPT_VERSION: `"${process.env.npm_package_version}"`,
DEVICE_NAME: `"${device.device}"`,
VENDOR_NAME: `"${device.vendor}"`,
},
target: "es5",
esbuildPlugins: [
{
name: "device-config-loader",
setup(build) {
build.onResolve({ filter: /^current-device$/ }, () => ({
path: resolve(deviceConfigsDir + device.deviceConfigFilename),
}));
},
},
],
})),
);