forked from silvanocerza/github-gitless-sync
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathesbuild.config.mjs
More file actions
159 lines (151 loc) · 5.49 KB
/
Copy pathesbuild.config.mjs
File metadata and controls
159 lines (151 loc) · 5.49 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import esbuild from "esbuild";
import process from "process";
import fs from "fs/promises";
import path from "path";
import os from "os";
import builtins from "builtin-modules";
const banner = `/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
`;
const prod = process.argv[2] === "production";
// ── Worker bundle pipeline ───────────────────────────────────────
// Two separate worker entry points are bundled as standalone IIFE
// scripts and their contents inlined into the main bundle as string
// constants. The main-thread `WorkerClient` (src/worker/worker-client.ts)
// then turns each string into a Blob URL at runtime and constructs
// a `new Worker(url)` from it. This sidesteps the Capacitor `app://`
// URL pattern (unproven in worker scope) and the `importScripts(url)`
// approach (network round-trip + caching concerns).
//
// We build each worker once at config-loading time (before the main
// bundle), capture the output as a UTF-8 string, then pass through
// esbuild's `define` mechanism so references to
// `__CPU_WORKER_SOURCE__` / `__NETWORK_WORKER_SOURCE__` in the main
// code become literal string constants in the final main.js.
async function buildWorkerSource(entry, label) {
const result = await esbuild.build({
entryPoints: [entry],
bundle: true,
format: "iife", // worker scope expects a self-executing script
target: "es2018",
minify: prod,
write: false, // produce in-memory output so we can read text directly
treeShaking: true,
external: [
// Workers never touch Obsidian APIs — but the type imports
// from "obsidian" need to be tree-shaken cleanly. The runtime
// doesn't import obsidian; we still mark it external so esbuild
// doesn't try to bundle a missing module if a type-only import
// ever sneaks in.
"obsidian",
// Node-only modules — must never appear in worker bundle (worker
// runs in browser context only).
...builtins.filter((m) => m !== "path"),
],
logLevel: "info",
});
if (result.errors.length > 0) {
throw new Error(`worker bundle (${label}) failed`);
}
// result.outputFiles[0].text is the bundled IIFE source.
return result.outputFiles[0].text;
}
const cpuWorkerSource = await buildWorkerSource(
"./src/worker/cpu-worker.ts",
"cpu-worker",
);
const networkWorkerSource = await buildWorkerSource(
"./src/worker/network-worker.ts",
"network-worker",
);
// Optional: after each successful build, mirror the plugin outputs into a
// vault's plugin folder so Obsidian picks them up immediately. Set
// OBSIDIAN_PLUGIN_DIR to <Vault>/.obsidian/plugins/github-easy-sync.
// data.json is intentionally not mirrored — that file is vault-specific
// state owned by Obsidian, not a build output.
//
// We expand a leading "~/" ourselves so the value works whether the env var
// is set inline in a shell (where the shell would expand it) or via an IDE
// run config (which passes it through literally — fs.mkdir would otherwise
// create a "~" folder under the project root).
function expandHome(p) {
if (!p) return p;
if (p === "~") return os.homedir();
if (p.startsWith("~/")) return path.join(os.homedir(), p.slice(2));
return p;
}
const mirrorTarget = expandHome(process.env.OBSIDIAN_PLUGIN_DIR);
const mirroredFiles = ["main.js", "manifest.json", "styles.css"];
const mirrorPlugin = {
name: "mirror-to-vault",
setup(build) {
build.onEnd(async (result) => {
if (!mirrorTarget) return;
if (result.errors.length > 0) return;
try {
await fs.mkdir(mirrorTarget, { recursive: true });
await Promise.all(
mirroredFiles.map((file) =>
fs.copyFile(file, path.join(mirrorTarget, file)),
),
);
console.log(`[mirror] copied to ${mirrorTarget}`);
} catch (err) {
console.error(`[mirror] failed: ${err.message}`);
}
});
},
};
const context = await esbuild.context({
banner: {
js: banner,
},
entryPoints: ["./src/main.ts"],
bundle: true,
external: [
"obsidian",
"electron",
"@codemirror/autocomplete",
"@codemirror/collab",
"@codemirror/commands",
"@codemirror/language",
"@codemirror/lint",
"@codemirror/search",
"@codemirror/state",
"@codemirror/view",
"@lezer/common",
"@lezer/highlight",
"@lezer/lr",
// `path` is intentionally NOT externalized: src/gi.ts imports
// path-browserify (pure JS, mobile-safe) and esbuild needs to
// bundle it rather than leave a top-level require("path") that
// would crash on Obsidian Mobile.
...builtins.filter((m) => m !== "path"),
],
format: "cjs",
target: "es2018",
logLevel: "info",
sourcemap: prod ? false : "inline",
treeShaking: true,
outfile: "main.js",
minify: prod,
// Inject the pre-built worker sources as string constants. The
// `WorkerClient` references `__CPU_WORKER_SOURCE__` /
// `__NETWORK_WORKER_SOURCE__` directly; `define` substitutes
// them with JSON-encoded strings before bundling. Each gets
// wrapped in surrounding quotes by JSON.stringify so the final
// main.js contains literal `const x = "...iife source..."`.
define: {
__CPU_WORKER_SOURCE__: JSON.stringify(cpuWorkerSource),
__NETWORK_WORKER_SOURCE__: JSON.stringify(networkWorkerSource),
},
plugins: [mirrorPlugin],
});
if (prod) {
await context.rebuild();
process.exit(0);
} else {
await context.watch();
}