mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-05-13 11:01:16 +00:00
IgnoreRules (src/apps/cli/serviceModules/IgnoreRules.ts): - Reads .livesync/ignore for user-defined glob patterns - Applies gitignore matchBase semantics: patterns without / get **/ prefix, patterns ending with / get ** appended for directory contents - Supports `import: .gitignore` directive to merge gitignore patterns - Rejects negation patterns with a warning (not fully supportable) - Integrated into both daemon and mirror commands via isTargetFile handler Wiring: - IgnoreRules loaded before LiveSyncBaseCore construction so beginWatch() receives rules when it fires during onLoad/onFirstInitialise - Passed through initialiseServiceModulesCLI -> StorageEventManagerCLI -> CLIStorageEventManagerAdapter -> CLIWatchAdapter Deployment: - src/apps/cli/deploy/livesync-cli.service - systemd unit template - src/apps/cli/deploy/install.sh - user/system install script Testing: - src/apps/cli/test/test-daemon-linux.sh - e2e tests for ignore rules - src/apps/cli/serviceModules/IgnoreRules.unit.spec.ts - 15 unit tests - src/apps/cli/commands/daemonCommand.unit.spec.ts - 7 unit tests
117 lines
5.1 KiB
TypeScript
117 lines
5.1 KiB
TypeScript
import { defineConfig } from "vite";
|
|
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
|
import path from "node:path";
|
|
import { readFileSync } from "node:fs";
|
|
const packageJson = JSON.parse(readFileSync("../../../package.json", "utf-8"));
|
|
const manifestJson = JSON.parse(readFileSync("../../../manifest.json", "utf-8"));
|
|
// https://vite.dev/config/
|
|
const defaultExternal = [
|
|
"obsidian",
|
|
"electron",
|
|
"crypto",
|
|
"pouchdb-adapter-leveldb",
|
|
"commander",
|
|
"chokidar",
|
|
"punycode",
|
|
"werift",
|
|
];
|
|
// Polyfill FileReader at the very top of the CJS bundle. octagonal-wheels uses
|
|
// FileReader for base64 conversion when Uint8Array.toBase64 (TC39 proposal) is
|
|
// unavailable. Node.js has neither, so we inject a minimal FileReader shim before
|
|
// any module-scope code evaluates.
|
|
const fileReaderPolyfillBanner = `
|
|
if (typeof globalThis.FileReader === "undefined") {
|
|
globalThis.FileReader = class FileReader {
|
|
constructor() { this.result = null; this.onload = null; this.onerror = null; }
|
|
readAsDataURL(blob) {
|
|
blob.arrayBuffer().then((buf) => {
|
|
var b64 = require("buffer").Buffer.from(buf).toString("base64");
|
|
this.result = "data:" + (blob.type || "application/octet-stream") + ";base64," + b64;
|
|
if (this.onload) this.onload({ target: this });
|
|
}).catch((err) => { if (this.onerror) this.onerror({ target: this, error: err }); });
|
|
}
|
|
readAsArrayBuffer() { throw new Error("FileReader.readAsArrayBuffer is not implemented in this polyfill"); }
|
|
readAsBinaryString() { throw new Error("FileReader.readAsBinaryString is not implemented in this polyfill"); }
|
|
readAsText() { throw new Error("FileReader.readAsText is not implemented in this polyfill"); }
|
|
abort() { throw new Error("FileReader.abort is not implemented in this polyfill"); }
|
|
};
|
|
}
|
|
`;
|
|
|
|
function injectBanner(): import("vite").Plugin {
|
|
return {
|
|
name: "inject-banner",
|
|
generateBundle(_options, bundle) {
|
|
for (const chunk of Object.values(bundle)) {
|
|
if (chunk.type === "chunk" && chunk.fileName.startsWith("entrypoint")) {
|
|
// Insert after the shebang line if present, otherwise at the top.
|
|
if (chunk.code.startsWith("#!")) {
|
|
const newline = chunk.code.indexOf("\n");
|
|
chunk.code = chunk.code.slice(0, newline + 1) + fileReaderPolyfillBanner + chunk.code.slice(newline + 1);
|
|
} else {
|
|
chunk.code = fileReaderPolyfillBanner + chunk.code;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
export default defineConfig({
|
|
plugins: [svelte(), injectBanner()],
|
|
resolve: {
|
|
alias: {
|
|
"@lib/worker/bgWorker.ts": "../../lib/src/worker/bgWorker.mock.ts",
|
|
"@lib/pouchdb/pouchdb-browser.ts": path.resolve(__dirname, "lib/pouchdb-node.ts"),
|
|
// The CLI runs on Node.js; force AWS XML builder to its CJS Node entry
|
|
// so Vite does not resolve the browser DOMParser-based XML parser.
|
|
"@aws-sdk/xml-builder": path.resolve(
|
|
__dirname,
|
|
"../../../node_modules/@aws-sdk/xml-builder/dist-cjs/index.js"
|
|
),
|
|
// Force fflate to the Node CJS entry; browser entry expects Web Worker globals.
|
|
fflate: path.resolve(__dirname, "../../../node_modules/fflate/lib/node.cjs"),
|
|
"@": path.resolve(__dirname, "../../"),
|
|
"@lib": path.resolve(__dirname, "../../lib/src"),
|
|
"../../src/worker/bgWorker.ts": "../../src/worker/bgWorker.mock.ts",
|
|
},
|
|
},
|
|
|
|
base: "./",
|
|
build: {
|
|
outDir: "dist",
|
|
emptyOutDir: true,
|
|
minify: false,
|
|
rollupOptions: {
|
|
input: {
|
|
index: path.resolve(__dirname, "entrypoint.ts"),
|
|
},
|
|
external: (id) => {
|
|
if (defaultExternal.includes(id)) return true;
|
|
if (id.startsWith(".") || id.startsWith("/")) return false;
|
|
if (id.startsWith("@/") || id.startsWith("@lib/")) return false;
|
|
if (id.endsWith(".ts") || id.endsWith(".js")) return false;
|
|
if (id === "fs" || id === "fs/promises" || id === "path" || id === "crypto" || id === "worker_threads")
|
|
return true;
|
|
if (id.startsWith("pouchdb-")) return true;
|
|
if (id.startsWith("werift")) return true;
|
|
if (id.startsWith("node:")) return true;
|
|
return false;
|
|
},
|
|
},
|
|
lib: {
|
|
entry: path.resolve(__dirname, "entrypoint.ts"),
|
|
formats: ["cjs"],
|
|
fileName: "index",
|
|
},
|
|
},
|
|
define: {
|
|
self: "globalThis",
|
|
global: "globalThis",
|
|
nonInteractive: "true",
|
|
// localStorage: "undefined", // Prevent usage of localStorage in the CLI environment
|
|
MANIFEST_VERSION: JSON.stringify(process.env.MANIFEST_VERSION || manifestJson.version || "0.0.0"),
|
|
PACKAGE_VERSION: JSON.stringify(process.env.PACKAGE_VERSION || packageJson.version || "0.0.0"),
|
|
},
|
|
});
|