sliftutils 1.2.15 → 1.2.17
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/builders/extensionBuild.ts +0 -19
- package/builders/hotReload.ts +17 -39
- package/builders/watch.ts +2 -18
- package/package.json +2 -2
- package/yarn.lock +4 -4
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
-
import crypto from "crypto";
|
|
3
2
|
import { delay } from "socket-function/src/batching";
|
|
4
3
|
import { bundleEntryCaller } from "../bundler/bundleEntryCaller";
|
|
5
4
|
import yargs from "yargs";
|
|
@@ -7,8 +6,6 @@ import { formatTime } from "socket-function/src/formatting/format";
|
|
|
7
6
|
import path from "path";
|
|
8
7
|
import { getAllFiles } from "../misc/fs";
|
|
9
8
|
|
|
10
|
-
const BUILD_HASH_PREFIX = "::SLIFT_HOT_RELOAD_BUILD_HASH::";
|
|
11
|
-
|
|
12
9
|
async function main() {
|
|
13
10
|
let time = Date.now();
|
|
14
11
|
//todonext
|
|
@@ -141,22 +138,6 @@ async function main() {
|
|
|
141
138
|
console.log(`Copied ${filesCopied} changed assets`);
|
|
142
139
|
}
|
|
143
140
|
|
|
144
|
-
// Hash the bundled JS outputs so the watch server can broadcast a version
|
|
145
|
-
// identifier the extension can compare against on a poll.
|
|
146
|
-
let jsOutputs = (await fs.promises.readdir(yargObj.outputFolder))
|
|
147
|
-
.filter(f => f.endsWith(".js"))
|
|
148
|
-
.sort();
|
|
149
|
-
let hasher = crypto.createHash("sha256");
|
|
150
|
-
for (let file of jsOutputs) {
|
|
151
|
-
let buf = await fs.promises.readFile(path.join(yargObj.outputFolder, file));
|
|
152
|
-
hasher.update(file);
|
|
153
|
-
hasher.update("\0");
|
|
154
|
-
hasher.update(buf);
|
|
155
|
-
hasher.update("\0");
|
|
156
|
-
}
|
|
157
|
-
let buildHash = hasher.digest("hex").slice(0, 16);
|
|
158
|
-
console.log(`${BUILD_HASH_PREFIX} ${buildHash}`);
|
|
159
|
-
|
|
160
141
|
let duration = Date.now() - time;
|
|
161
142
|
console.log(`Extension build completed in ${formatTime(duration)}`);
|
|
162
143
|
}
|
package/builders/hotReload.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { isInBrowser, isInChromeExtension, isInChromeExtensionBackground, isInCh
|
|
|
3
3
|
|
|
4
4
|
const DEFAULT_WATCH_PORT = 9876;
|
|
5
5
|
const CONTENT_SCRIPT_POLL_INTERVAL_MS = 1000;
|
|
6
|
-
const HOT_RELOAD_HASH_STORAGE_KEY = "sliftHotReloadBuildHash";
|
|
7
6
|
|
|
8
7
|
export async function enableHotReloading(config?: {
|
|
9
8
|
port?: number;
|
|
@@ -22,7 +21,7 @@ export async function enableHotReloading(config?: {
|
|
|
22
21
|
}
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
function watchPortHotReload(port = DEFAULT_WATCH_PORT, onReload: () => void
|
|
24
|
+
function watchPortHotReload(port = DEFAULT_WATCH_PORT, onReload: () => void) {
|
|
26
25
|
let reconnectTimer: number | undefined;
|
|
27
26
|
let ws: WebSocket | undefined;
|
|
28
27
|
|
|
@@ -41,12 +40,8 @@ function watchPortHotReload(port = DEFAULT_WATCH_PORT, onReload: () => void, onH
|
|
|
41
40
|
try {
|
|
42
41
|
let data = JSON.parse(event.data);
|
|
43
42
|
if (data.type === "build-complete" && data.success) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} else {
|
|
47
|
-
console.log("[Hot Reload] Build complete, reloading page...");
|
|
48
|
-
onReload();
|
|
49
|
-
}
|
|
43
|
+
console.log("[Hot Reload] Build complete, reloading...");
|
|
44
|
+
onReload();
|
|
50
45
|
}
|
|
51
46
|
} catch (error) {
|
|
52
47
|
console.error("[Hot Reload] Failed to parse message:", error);
|
|
@@ -77,48 +72,31 @@ function watchPortHotReload(port = DEFAULT_WATCH_PORT, onReload: () => void, onH
|
|
|
77
72
|
}
|
|
78
73
|
|
|
79
74
|
function chromeExtensionBackgroundHotReload(port = DEFAULT_WATCH_PORT) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
watchPortHotReload(port, () => { /* unused — hash callback drives reloads */ }, (hash) => {
|
|
83
|
-
if (!hash) return;
|
|
84
|
-
void chrome.storage.local.set({ [HOT_RELOAD_HASH_STORAGE_KEY]: hash });
|
|
85
|
-
if (currentHash === undefined) {
|
|
86
|
-
currentHash = hash;
|
|
87
|
-
console.log(`[Hot Reload] Initial build hash: ${hash}`);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
if (hash !== currentHash) {
|
|
91
|
-
console.log(`[Hot Reload] Build hash changed (${currentHash} -> ${hash}), reloading extension...`);
|
|
92
|
-
currentHash = hash;
|
|
93
|
-
chrome.runtime.reload();
|
|
94
|
-
}
|
|
75
|
+
watchPortHotReload(port, () => {
|
|
76
|
+
chrome.runtime.reload();
|
|
95
77
|
});
|
|
96
78
|
}
|
|
97
79
|
|
|
98
80
|
function chromeExtensionContentScriptHotReload() {
|
|
99
|
-
|
|
100
|
-
|
|
81
|
+
// The background reloads the extension on build, which invalidates this
|
|
82
|
+
// content script's extension context. We detect that by touching
|
|
83
|
+
// chrome.storage.local on a poll — once the context is gone, the call
|
|
84
|
+
// throws "Extension context invalidated" and we refresh the page.
|
|
101
85
|
setInterval(() => {
|
|
102
86
|
try {
|
|
103
|
-
chrome.storage.local.get(
|
|
87
|
+
chrome.storage.local.get(null, () => {
|
|
104
88
|
if (chrome.runtime.lastError) {
|
|
105
89
|
console.error("[Hot Reload] storage.get error:", chrome.runtime.lastError.message);
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
let hash: string | undefined = result?.[HOT_RELOAD_HASH_STORAGE_KEY];
|
|
109
|
-
if (!hash) return;
|
|
110
|
-
if (lastHash === undefined) {
|
|
111
|
-
lastHash = hash;
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
if (hash !== lastHash) {
|
|
115
|
-
console.log(`[Hot Reload] Build hash changed (${lastHash} -> ${hash}), refreshing page...`);
|
|
116
|
-
lastHash = hash;
|
|
117
|
-
window.location.reload();
|
|
118
90
|
}
|
|
119
91
|
});
|
|
120
92
|
} catch (error) {
|
|
93
|
+
let message = (error as Error).message ?? "";
|
|
94
|
+
if (message.includes("Extension context invalidated")) {
|
|
95
|
+
console.log("[Hot Reload] Extension context invalidated, refreshing page...");
|
|
96
|
+
window.location.reload();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
121
99
|
console.error("[Hot Reload] poll error:", (error as Error).stack ?? error);
|
|
122
100
|
}
|
|
123
101
|
}, CONTENT_SCRIPT_POLL_INTERVAL_MS);
|
|
124
|
-
}
|
|
102
|
+
}
|
package/builders/watch.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { WebSocketServer } from "ws";
|
|
|
5
5
|
|
|
6
6
|
const DEBOUNCE_DELAY_MS = 250;
|
|
7
7
|
const DEFAULT_WATCH_PORT = 9876;
|
|
8
|
-
const BUILD_HASH_REGEX = /::SLIFT_HOT_RELOAD_BUILD_HASH::\s+(\S+)/g;
|
|
9
8
|
|
|
10
9
|
async function main() {
|
|
11
10
|
let args = process.argv.slice(2);
|
|
@@ -49,9 +48,6 @@ async function main() {
|
|
|
49
48
|
|
|
50
49
|
wss.on("connection", (ws) => {
|
|
51
50
|
console.log(`[${new Date().toLocaleTimeString()}] WebSocket client connected`);
|
|
52
|
-
if (latestBuildHash) {
|
|
53
|
-
ws.send(JSON.stringify({ type: "build-complete", success: true, hash: latestBuildHash }));
|
|
54
|
-
}
|
|
55
51
|
ws.on("close", () => {
|
|
56
52
|
console.log(`[${new Date().toLocaleTimeString()}] WebSocket client disconnected`);
|
|
57
53
|
});
|
|
@@ -67,7 +63,6 @@ async function main() {
|
|
|
67
63
|
let debounceTimer: NodeJS.Timeout | undefined;
|
|
68
64
|
let isRunning = false;
|
|
69
65
|
let needsRerun = false;
|
|
70
|
-
let latestBuildHash: string | undefined;
|
|
71
66
|
|
|
72
67
|
async function executeCommand() {
|
|
73
68
|
if (isRunning) {
|
|
@@ -80,25 +75,14 @@ async function main() {
|
|
|
80
75
|
|
|
81
76
|
try {
|
|
82
77
|
console.log(`\n[${new Date().toLocaleTimeString()}] Running: ${command}`);
|
|
83
|
-
|
|
78
|
+
await runPromise(command);
|
|
84
79
|
console.log(`[${new Date().toLocaleTimeString()}] Completed successfully`);
|
|
85
80
|
|
|
86
|
-
// Extract the most recent [BUILD_HASH] line emitted by the build.
|
|
87
|
-
let match: RegExpExecArray | null;
|
|
88
|
-
let lastHash: string | undefined;
|
|
89
|
-
BUILD_HASH_REGEX.lastIndex = 0;
|
|
90
|
-
while ((match = BUILD_HASH_REGEX.exec(output)) !== null) {
|
|
91
|
-
lastHash = match[1];
|
|
92
|
-
}
|
|
93
|
-
if (lastHash) {
|
|
94
|
-
latestBuildHash = lastHash;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
81
|
// Notify all connected WebSocket clients
|
|
98
82
|
if (wss) {
|
|
99
83
|
wss.clients.forEach((client) => {
|
|
100
84
|
if (client.readyState === 1) { // 1 = OPEN
|
|
101
|
-
client.send(JSON.stringify({ type: "build-complete", success: true
|
|
85
|
+
client.send(JSON.stringify({ type: "build-complete", success: true }));
|
|
102
86
|
}
|
|
103
87
|
});
|
|
104
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sliftutils",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.17",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"mobx": "^6.13.3",
|
|
51
51
|
"preact-old-types": "^10.28.1",
|
|
52
52
|
"shell-quote": "^1.8.3",
|
|
53
|
-
"socket-function": "^1.1.
|
|
53
|
+
"socket-function": "^1.1.30",
|
|
54
54
|
"typenode": "*",
|
|
55
55
|
"typesafecss": "*",
|
|
56
56
|
"ws": "^8.18.3",
|
package/yarn.lock
CHANGED
|
@@ -1940,10 +1940,10 @@ slash@^3.0.0:
|
|
|
1940
1940
|
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
|
1941
1941
|
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
|
1942
1942
|
|
|
1943
|
-
socket-function@^1.1.
|
|
1944
|
-
version "1.1.
|
|
1945
|
-
resolved "https://registry.yarnpkg.com/socket-function/-/socket-function-1.1.
|
|
1946
|
-
integrity sha512-
|
|
1943
|
+
socket-function@^1.1.30:
|
|
1944
|
+
version "1.1.30"
|
|
1945
|
+
resolved "https://registry.yarnpkg.com/socket-function/-/socket-function-1.1.30.tgz#adeb9614996e727518e2abdc7a1aa90544d669cd"
|
|
1946
|
+
integrity sha512-EcqNpM8i0icBr2iU80aovXI05aUBrB4P4e9U7EQyju68TGAMagdA4OQXi+V1MHUipH/3nIdw3UAVYv+kFwZwnQ==
|
|
1947
1947
|
dependencies:
|
|
1948
1948
|
"@types/pako" "^2.0.3"
|
|
1949
1949
|
"@types/ws" "^8.5.3"
|