@moonlight-mod/esbuild-config 1.0.0 → 1.1.0

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright © 2025 moonlight contributors
3
+ Copyright © 2026 moonlight contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
package/dist/factory.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import fs from "node:fs";
2
1
  import type { Plugin, BuildResult, BuildOptions } from "esbuild";
3
2
  import betterLogging from "./plugins/betterLogging.js";
4
3
  import webpackImports from "./plugins/webpackImports.js";
5
- declare const sides: readonly ["index", "webpackModules", "node", "host"];
4
+ export declare const sides: readonly ["index", "webpackModules", "node", "host"];
6
5
  export interface ESBuildFactoryOptions {
7
6
  /**
8
7
  * The name of your extension.
@@ -35,7 +34,7 @@ export interface ESBuildFactoryOptions {
35
34
  * A string determining what target to compile your extension to.
36
35
  * @remarks In utility functions other than {@link defineConfig}, this is automatically generated.
37
36
  */
38
- side: typeof sides[number];
37
+ side: (typeof sides)[number];
39
38
  /**
40
39
  * A list of extra "external" dependencies, (i.e., dependencies that the
41
40
  * {@link side}'s runtime already provides and thus doesn't need to be bundled)
@@ -59,5 +58,5 @@ export interface ESBuildFactoryOptions {
59
58
  export declare function defineConfig(options: ESBuildFactoryOptions): BuildOptions | null;
60
59
  export declare function defineConfigs(options: Omit<ESBuildFactoryOptions, "side">): BuildOptions[];
61
60
  export declare function buildExtension(options: Omit<ESBuildFactoryOptions, "side">): Promise<BuildResult[]>;
62
- export declare function watchExtension(options: Omit<ESBuildFactoryOptions, "side">): Promise<fs.FSWatcher[]>;
63
- export { defineConfig as makeExtConfig, defineConfigs as makeExtConfigs, buildExtension as buildExt, watchExtension as watchExt, betterLogging as deduplicatedLogging, webpackImports as wpImport, };
61
+ export declare function watchExtension(options: Omit<ESBuildFactoryOptions, "side">): Promise<import("esbuild").BuildContext<BuildOptions>[]>;
62
+ export { defineConfig as makeExtConfig, defineConfigs as makeExtConfigs, buildExtension as buildExt, watchExtension as watchExt, betterLogging as deduplicatedLogging, webpackImports as wpImport };
package/dist/factory.js CHANGED
@@ -1,21 +1,10 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { build, context } from "esbuild";
4
3
  import betterLogging from "./plugins/betterLogging.js";
5
4
  import webpackImports from "./plugins/webpackImports.js";
6
5
  import copyFile from "./plugins/copyFile.js";
7
- const prod = process.env.NODE_ENV === "production";
8
- const external = [
9
- "electron",
10
- "fs",
11
- "path",
12
- "module",
13
- "events",
14
- "original-fs",
15
- "discord" // mappings
16
- ];
17
- const sides = ["index", "webpackModules", "node", "host"];
18
- const fileExts = ["js", "jsx", "ts", "tsx"];
6
+ import { prod, external, fileExts, buildConfigs, watchConfigs, applyDropLabels } from "./shared.js";
7
+ export const sides = ["index", "webpackModules", "node", "host"];
19
8
  export function defineConfig(options) {
20
9
  const entry = options.entry ?? options.src;
21
10
  const output = options.output ?? options.dst;
@@ -52,15 +41,17 @@ export function defineConfig(options) {
52
41
  return {
53
42
  entryPoints: entryPoints,
54
43
  outdir: side === "webpackModules" ? path.join(output, "webpackModules") : output,
55
- format: esm && side === "index" ? "esm" : "iife",
44
+ format: esm && side === "index" ? "esm" : "cjs",
56
45
  globalName: "module.exports",
57
46
  platform: ["index", "webpackModules"].includes(side) ? "browser" : "node",
58
47
  treeShaking: true,
59
48
  bundle: true,
60
49
  minify: prod,
61
50
  sourcemap: "inline",
51
+ dropLabels: applyDropLabels(side),
62
52
  external: [...external, ...extraExternal],
63
53
  plugins: [
54
+ // TODO: maybe don't apply this for each side as this does 4x copies lol
64
55
  copyFile(path.join(entry, "manifest.json"), path.join(output, "manifest.json")),
65
56
  copyFile(path.join(entry, "style.css"), path.join(output, "style.css")),
66
57
  webpackImports,
@@ -71,35 +62,14 @@ export function defineConfig(options) {
71
62
  };
72
63
  }
73
64
  export function defineConfigs(options) {
74
- return sides
75
- .map((side) => defineConfig({ ...options, side }))
76
- .filter((config) => config != null);
65
+ return sides.map((side) => defineConfig({ ...options, side })).filter((config) => config != null);
77
66
  }
78
67
  export async function buildExtension(options) {
79
- const configs = defineConfigs(options);
80
- const builds = [];
81
- configs.forEach(async (config) => builds.push(await build(config)));
82
- return builds;
68
+ return buildConfigs(defineConfigs(options));
83
69
  }
84
70
  export async function watchExtension(options) {
85
- const buildConfigs = defineConfigs(options);
86
- const watchers = [];
87
- for (const config of buildConfigs) {
88
- const ctx = await context(config);
89
- async function rebuild() {
90
- try {
91
- await ctx.rebuild();
92
- }
93
- catch {
94
- // esbuild will log errors, we just need to not do anything
95
- }
96
- }
97
- await rebuild();
98
- const watcher = fs.watch(options.entry, { recursive: true }, async () => await rebuild());
99
- watchers.push(watcher);
100
- }
101
- return watchers;
71
+ return watchConfigs(defineConfigs(options));
102
72
  }
103
73
  // In GitHub PR #3, these original names were modified to be more descriptive.
104
74
  // We re-export these as to not break backwards compatibility with older plugins.
105
- export { defineConfig as makeExtConfig, defineConfigs as makeExtConfigs, buildExtension as buildExt, watchExtension as watchExt, betterLogging as deduplicatedLogging, webpackImports as wpImport, };
75
+ export { defineConfig as makeExtConfig, defineConfigs as makeExtConfigs, buildExtension as buildExt, watchExtension as watchExt, betterLogging as deduplicatedLogging, webpackImports as wpImport };
@@ -0,0 +1,21 @@
1
+ import type { BuildOptions, Plugin } from "esbuild";
2
+ export declare const define: {
3
+ MOONLIGHT_BRANCH: string;
4
+ MOONLIGHT_VERSION: string;
5
+ };
6
+ export declare const sides: readonly ["injector", "web-preload", "node-preload", "browser"];
7
+ export interface CoreFactoryOptions {
8
+ name: string;
9
+ side: (typeof sides)[number];
10
+ entry: string;
11
+ output: string;
12
+ extraExternal?: string[];
13
+ extraPlugins?: Plugin[];
14
+ extraConfig?: BuildOptions;
15
+ }
16
+ export declare function defineCoreConfig(options: CoreFactoryOptions): BuildOptions;
17
+ export interface CoreFactoryPathsOptions {
18
+ cleanPaths?: string[];
19
+ }
20
+ export declare function buildOrWatchConfigs(paths: CoreFactoryPathsOptions, ...configs: BuildOptions[]): Promise<void>;
21
+ export declare function buildOrWatchCore(paths: CoreFactoryPathsOptions, ...configs: CoreFactoryOptions[]): Promise<void>;
@@ -0,0 +1,50 @@
1
+ // everything here is specifically for moonlight's core; no stability guarantees
2
+ import fs from "node:fs/promises";
3
+ import { prod, external, applyDropLabels, watchConfigs, buildConfigs } from "./shared.js";
4
+ import webpackImports from "./plugins/webpackImports.js";
5
+ import betterLogging from "./plugins/betterLogging.js";
6
+ export const define = {
7
+ MOONLIGHT_BRANCH: JSON.stringify(process.env.MOONLIGHT_BRANCH ?? "dev"),
8
+ MOONLIGHT_VERSION: JSON.stringify(process.env.MOONLIGHT_VERSION ?? "dev")
9
+ };
10
+ export const sides = ["injector", "web-preload", "node-preload", "browser"];
11
+ export function defineCoreConfig(options) {
12
+ return {
13
+ entryPoints: [options.entry],
14
+ outfile: options.output,
15
+ format: ["web-preload", "browser"].includes(options.side) ? "iife" : "cjs",
16
+ platform: ["web-preload", "browser"].includes(options.side) ? "browser" : "node",
17
+ treeShaking: true,
18
+ bundle: true,
19
+ minify: prod,
20
+ sourcemap: "inline",
21
+ define,
22
+ dropLabels: applyDropLabels(options.side),
23
+ external: [...external, ...(options.extraExternal ?? [])],
24
+ plugins: [webpackImports, betterLogging(options.name), ...(options.extraPlugins ?? [])],
25
+ ...options.extraConfig
26
+ };
27
+ }
28
+ export async function buildOrWatchConfigs(paths, ...configs) {
29
+ const watch = process.argv.includes("--watch");
30
+ const clean = process.argv.includes("--clean");
31
+ if (clean) {
32
+ // since esbuild-config *is* the clean script, the package.json shorthand script filters it out
33
+ if (paths.cleanPaths) {
34
+ for (const path of paths.cleanPaths) {
35
+ await fs.rm(path, { recursive: true, force: true });
36
+ }
37
+ }
38
+ }
39
+ else {
40
+ if (watch) {
41
+ await watchConfigs(configs);
42
+ }
43
+ else {
44
+ await buildConfigs(configs);
45
+ }
46
+ }
47
+ }
48
+ export function buildOrWatchCore(paths, ...configs) {
49
+ return buildOrWatchConfigs(paths, ...configs.map((config) => defineCoreConfig(config)));
50
+ }
@@ -16,7 +16,7 @@ export const betterLogging = (tag) => ({
16
16
  kind: "warning",
17
17
  color: true
18
18
  }),
19
- formatMessages(result.errors, { kind: "error", color: true }),
19
+ formatMessages(result.errors, { kind: "error", color: true })
20
20
  ]).then((a) => a.flat());
21
21
  for (const message of formatted) {
22
22
  if (lastMessages.has(message))
@@ -2,13 +2,13 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  export const copyFile = (src, dest) => ({
4
4
  name: "copy-files",
5
- setup: build => build.onEnd(() => {
5
+ setup: (build) => build.onEnd(() => {
6
6
  if (!fs.existsSync(src))
7
7
  return;
8
8
  const dir = path.dirname(dest);
9
9
  if (!fs.existsSync(dir))
10
10
  fs.mkdirSync(dir, { recursive: true });
11
11
  fs.copyFileSync(src, dest);
12
- }),
12
+ })
13
13
  });
14
14
  export default copyFile;
@@ -1,8 +1,8 @@
1
1
  const webpackImports = {
2
2
  name: "webpack-imports",
3
- setup: build => build.onResolve({ filter: /^@moonlight-mod\/wp\// }, args => ({
3
+ setup: (build) => build.onResolve({ filter: /^@moonlight-mod\/wp\// }, (args) => ({
4
4
  path: args.path.replace(/^@moonlight-mod\/wp\//, ""),
5
5
  external: true
6
- })),
6
+ }))
7
7
  };
8
8
  export default webpackImports;
@@ -0,0 +1,15 @@
1
+ import { type BuildOptions } from "esbuild";
2
+ export declare const prod: boolean;
3
+ export declare const external: string[];
4
+ export declare const fileExts: string[];
5
+ export declare const dropLabels: {
6
+ injector: string[];
7
+ nodePreload: string[];
8
+ webPreload: string[];
9
+ browser: string[];
10
+ webTarget: string[];
11
+ nodeTarget: string[];
12
+ };
13
+ export declare function applyDropLabels(side: string): string[];
14
+ export declare function buildConfigs(buildConfigs: BuildOptions[]): Promise<import("esbuild").BuildResult<BuildOptions>[]>;
15
+ export declare function watchConfigs(buildConfigs: BuildOptions[]): Promise<import("esbuild").BuildContext<BuildOptions>[]>;
package/dist/shared.js ADDED
@@ -0,0 +1,38 @@
1
+ import { build, context } from "esbuild";
2
+ export const prod = process.env.NODE_ENV === "production";
3
+ export const external = [
4
+ "electron",
5
+ "fs",
6
+ "path",
7
+ "module",
8
+ "original-fs",
9
+ "discord" // mappings
10
+ ];
11
+ export const fileExts = ["js", "jsx", "ts", "tsx"];
12
+ export const dropLabels = {
13
+ injector: ["injector", "host"],
14
+ nodePreload: ["node-preload", "node"],
15
+ webPreload: ["web-preload", "index", "webpackModules"],
16
+ browser: ["browser", "index", "webpackModules"],
17
+ webTarget: ["web-preload", "browser", "index", "webpackModules"],
18
+ nodeTarget: ["node-preload", "injector", "node", "host"]
19
+ };
20
+ export function applyDropLabels(side) {
21
+ const result = [];
22
+ for (const [label, sides] of Object.entries(dropLabels)) {
23
+ if (!sides.includes(side)) {
24
+ result.push(label);
25
+ }
26
+ }
27
+ return result;
28
+ }
29
+ export function buildConfigs(buildConfigs) {
30
+ return Promise.all(buildConfigs.map((config) => build(config)));
31
+ }
32
+ export function watchConfigs(buildConfigs) {
33
+ return Promise.all(buildConfigs.map(async (config) => {
34
+ const ctx = await context(config);
35
+ await ctx.watch();
36
+ return ctx;
37
+ }));
38
+ }
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@moonlight-mod/esbuild-config",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "private": false,
6
- "description": "Yet another Discord mod's shared esbuild config",
7
6
  "license": "MIT",
8
7
  "homepage": "https://moonlight-mod.github.io/",
9
8
  "repository": {
10
9
  "type": "git",
11
- "url": "git+https://github.com/moonlight-mod/esbuild-config.git"
10
+ "url": "git+https://github.com/moonlight-mod/moonlight.git"
12
11
  },
13
12
  "bugs": {
14
- "url": "https://github.com/moonlight-mod/esbuild-config/issues"
13
+ "url": "https://github.com/moonlight-mod/moonlight/issues"
15
14
  },
15
+ "engineStrict": false,
16
16
  "engines": {
17
17
  "node": ">=22",
18
18
  "pnpm": ">=10",
@@ -21,20 +21,26 @@
21
21
  },
22
22
  "main": "./dist/index.js",
23
23
  "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": "./dist/index.js",
26
+ "./internal": "./dist/internal.js"
27
+ },
24
28
  "files": [
25
- "dist"
29
+ "dist",
30
+ "!dist/*.tsbuildinfo"
26
31
  ],
27
32
  "devDependencies": {
28
- "@types/node": "^22.14.0",
29
- "prettier": "^3.4.2",
30
- "esbuild": "^0.25.2",
31
- "typescript": "^5.8.3"
33
+ "@types/node": "22.14.0",
34
+ "esbuild": "^0.19.3",
35
+ "typescript": "^5.3.3"
32
36
  },
33
37
  "peerDependencies": {
34
38
  "esbuild": ">= 0.19"
35
39
  },
36
40
  "scripts": {
37
41
  "build": "tsc --build",
38
- "clean": "pnpm build --clean"
42
+ "dev": "pnpm run build --watch --preserveWatchOutput",
43
+ "clean": "pnpm run build --clean",
44
+ "typecheck": "pnpm run build --noEmit"
39
45
  }
40
46
  }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # `@moonlight-mod/esbuild-config`
2
-
3
- A simple and effective `esbuild` configuration for moonlight extensions and builds.
@@ -1 +0,0 @@
1
- {"root":["../src/factory.ts","../src/index.ts","../src/plugins/betterLogging.ts","../src/plugins/copyFile.ts","../src/plugins/index.ts","../src/plugins/webpackImports.ts"],"version":"5.8.3"}