@baskerhq/localstage 1.0.1-beta.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/README.md +56 -0
- package/dist/basker.d.ts +1 -0
- package/dist/basker.js +2 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +2 -0
- package/dist/commands/theme/check.d.ts +19 -0
- package/dist/commands/theme/check.js +1 -0
- package/dist/commands/theme/dev.d.ts +28 -0
- package/dist/commands/theme/dev.js +1 -0
- package/dist/commands/theme/pull.d.ts +10 -0
- package/dist/commands/theme/pull.js +1 -0
- package/dist/commands/theme/set.d.ts +19 -0
- package/dist/commands/theme/set.js +1 -0
- package/dist/config/defaults.json +3 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.js +1 -0
- package/dist/livereload/client.js +205 -0
- package/package.json +102 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// Configuration
|
|
5
|
+
const config = {
|
|
6
|
+
port: (Number.parseInt(window.location.port) + 1) || "9293",
|
|
7
|
+
reconnectInterval: 2000,
|
|
8
|
+
maxReconnectAttempts: 50,
|
|
9
|
+
pingInterval: 25000,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
let socket = null;
|
|
13
|
+
let reconnectAttempts = 0;
|
|
14
|
+
let pingInterval = null;
|
|
15
|
+
let isReconnecting = false;
|
|
16
|
+
|
|
17
|
+
function log(message, level) {
|
|
18
|
+
level = level || "info";
|
|
19
|
+
if (level === "error") {
|
|
20
|
+
console.error(`[LocalStage Live Reload] ${message}`);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
console.warn(`[LocalStage Live Reload] ${message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function connect() {
|
|
28
|
+
if (socket && socket.readyState === WebSocket.OPEN) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const wsUrl = `ws://${window.location.hostname}:${config.port}/livereload`;
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
socket = new WebSocket(wsUrl);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
log(`Failed to create WebSocket: ${error.message}`, "error");
|
|
39
|
+
scheduleReconnect();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
socket.onopen = function () {
|
|
44
|
+
log("Connected to live reload server");
|
|
45
|
+
reconnectAttempts = 0;
|
|
46
|
+
isReconnecting = false;
|
|
47
|
+
startPingInterval();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
socket.onmessage = function (event) {
|
|
51
|
+
try {
|
|
52
|
+
const message = JSON.parse(event.data);
|
|
53
|
+
handleMessage(message);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
log(`Failed to parse message: ${error.message}`, "error");
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
socket.onclose = function (_event) {
|
|
61
|
+
log("Disconnected from live reload server");
|
|
62
|
+
stopPingInterval();
|
|
63
|
+
|
|
64
|
+
if (!isReconnecting) {
|
|
65
|
+
scheduleReconnect();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
socket.onerror = function (error) {
|
|
70
|
+
log(`WebSocket error occurred: ${error?.message || "unknown"}`, "error");
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function handleMessage(message) {
|
|
75
|
+
switch (message.type) {
|
|
76
|
+
case "reload":
|
|
77
|
+
log(`Reloading page due to file changes: ${(message.data.files || []).join(", ")}`);
|
|
78
|
+
showReloadNotification();
|
|
79
|
+
|
|
80
|
+
// Small delay to ensure any pending requests complete
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
window.location.reload();
|
|
83
|
+
}, 100);
|
|
84
|
+
break;
|
|
85
|
+
|
|
86
|
+
case "ping":
|
|
87
|
+
// Respond to server ping
|
|
88
|
+
if (socket && socket.readyState === WebSocket.OPEN) {
|
|
89
|
+
socket.send(JSON.stringify({
|
|
90
|
+
type: "pong",
|
|
91
|
+
data: { timestamp: Date.now() },
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
|
|
96
|
+
case "pong":
|
|
97
|
+
// Server responded to our ping, connection is healthy
|
|
98
|
+
break;
|
|
99
|
+
|
|
100
|
+
default:
|
|
101
|
+
log(`Unknown message type: ${message.type}`, "warn");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function scheduleReconnect() {
|
|
106
|
+
if (reconnectAttempts >= config.maxReconnectAttempts) {
|
|
107
|
+
log("Max reconnection attempts reached. Please refresh the page manually.", "error");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
isReconnecting = true;
|
|
112
|
+
reconnectAttempts++;
|
|
113
|
+
|
|
114
|
+
log(`Attempting to reconnect in ${config.reconnectInterval / 1000}s... (attempt ${reconnectAttempts}/${config.maxReconnectAttempts})`);
|
|
115
|
+
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
connect();
|
|
118
|
+
}, config.reconnectInterval);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function startPingInterval() {
|
|
122
|
+
stopPingInterval();
|
|
123
|
+
|
|
124
|
+
pingInterval = setInterval(() => {
|
|
125
|
+
if (socket && socket.readyState === WebSocket.OPEN) {
|
|
126
|
+
socket.send(JSON.stringify({
|
|
127
|
+
type: "ping",
|
|
128
|
+
data: { timestamp: Date.now() },
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
}, config.pingInterval);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function stopPingInterval() {
|
|
135
|
+
if (pingInterval) {
|
|
136
|
+
clearInterval(pingInterval);
|
|
137
|
+
pingInterval = null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function showReloadNotification() {
|
|
142
|
+
const notification = document.createElement("div");
|
|
143
|
+
notification.style.cssText = [
|
|
144
|
+
"position: fixed",
|
|
145
|
+
"top: 50%",
|
|
146
|
+
"left: 50%",
|
|
147
|
+
"transform: translate(-50%, -50%)",
|
|
148
|
+
"padding: 16px 24px",
|
|
149
|
+
"background: rgba(0, 0, 0, 0.8)",
|
|
150
|
+
"color: white",
|
|
151
|
+
"border-radius: 8px",
|
|
152
|
+
"font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif",
|
|
153
|
+
"font-size: 14px",
|
|
154
|
+
"font-weight: 500",
|
|
155
|
+
"z-index: 10001",
|
|
156
|
+
"backdrop-filter: blur(4px)",
|
|
157
|
+
].join(";");
|
|
158
|
+
|
|
159
|
+
notification.textContent = "🔄 Reloading...";
|
|
160
|
+
|
|
161
|
+
document.body.appendChild(notification);
|
|
162
|
+
|
|
163
|
+
setTimeout(() => {
|
|
164
|
+
if (notification.parentNode) {
|
|
165
|
+
notification.parentNode.removeChild(notification);
|
|
166
|
+
}
|
|
167
|
+
}, 2000);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Initialize when DOM is ready
|
|
171
|
+
function initialize() {
|
|
172
|
+
log("Initializing live reload client");
|
|
173
|
+
connect();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Handle page visibility changes
|
|
177
|
+
document.addEventListener("visibilitychange", () => {
|
|
178
|
+
if (document.hidden) {
|
|
179
|
+
// Page is hidden, stop pinging
|
|
180
|
+
stopPingInterval();
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// Page is visible again, restart pinging if connected
|
|
184
|
+
if (socket && socket.readyState === WebSocket.OPEN) {
|
|
185
|
+
startPingInterval();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Handle page unload
|
|
191
|
+
window.addEventListener("beforeunload", () => {
|
|
192
|
+
if (socket) {
|
|
193
|
+
socket.close();
|
|
194
|
+
}
|
|
195
|
+
stopPingInterval();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Start when DOM is ready
|
|
199
|
+
if (document.readyState === "loading") {
|
|
200
|
+
document.addEventListener("DOMContentLoaded", initialize);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
initialize();
|
|
204
|
+
}
|
|
205
|
+
})();
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@baskerhq/localstage",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.1-beta.0",
|
|
5
|
+
"description": "Local development server for Basker themes - CLI tool for theme development",
|
|
6
|
+
"author": "Basker Ltd.",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/BaskerHQ/basker-cms/tree/main/packages/localstage",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/BaskerHQ/basker-cms.git",
|
|
12
|
+
"directory": "packages/localstage"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/BaskerHQ/basker-cms/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"basker",
|
|
19
|
+
"cms",
|
|
20
|
+
"theme",
|
|
21
|
+
"development",
|
|
22
|
+
"liquid",
|
|
23
|
+
"hono",
|
|
24
|
+
"local",
|
|
25
|
+
"cli"
|
|
26
|
+
],
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"main": "./dist/index.js",
|
|
36
|
+
"bin": {
|
|
37
|
+
"localstage": "./dist/cli.js",
|
|
38
|
+
"basker": "./dist/basker.js"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"README.md",
|
|
42
|
+
"dist/**/*",
|
|
43
|
+
"package.json"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22.12.0"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"dev": "LOCALSTAGE_THEME_PATH=./example_theme tsx watch src/cli.ts",
|
|
50
|
+
"dev:localstage": "LOCALSTAGE_THEME_PATH=./example_theme tsx watch src/cli.ts",
|
|
51
|
+
"start": "node dist/cli.js",
|
|
52
|
+
"cli": "tsx src/cli.ts",
|
|
53
|
+
"build": "tsup",
|
|
54
|
+
"link:global": "pnpm build && pnpm link --global",
|
|
55
|
+
"install:local": "bash ./scripts/install-local-cli.sh",
|
|
56
|
+
"prepublish:check": "bash ./scripts/prepublish-check.sh",
|
|
57
|
+
"release:cli": "bash ./scripts/release-cli.sh",
|
|
58
|
+
"prepublishOnly": "npm run build",
|
|
59
|
+
"lint": "eslint .",
|
|
60
|
+
"lint:fix": "eslint . --fix",
|
|
61
|
+
"typecheck": "tsc --noEmit",
|
|
62
|
+
"test": "vitest run --passWithNoTests"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@hono/node-server": "1.19.9",
|
|
66
|
+
"@oclif/core": "4.2.5",
|
|
67
|
+
"@payloadcms/sdk": "3.72.0",
|
|
68
|
+
"chokidar": "^3.5.3",
|
|
69
|
+
"date-fns": "4.1.0",
|
|
70
|
+
"hono": "4.11.4",
|
|
71
|
+
"liquidjs": "10.24.0",
|
|
72
|
+
"ws": "^8.18.0"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@antfu/eslint-config": "4.16.1",
|
|
76
|
+
"@baskerhq/frontstage": "workspace:*",
|
|
77
|
+
"@baskerhq/liquidjs": "workspace:*",
|
|
78
|
+
"@baskerhq/ui": "workspace:^",
|
|
79
|
+
"@types/node": "22.13.14",
|
|
80
|
+
"eslint": "^9.34.0",
|
|
81
|
+
"eslint-plugin-import-x": "^4.15.2",
|
|
82
|
+
"eslint-plugin-jsdoc": "^51.2.3",
|
|
83
|
+
"eslint-plugin-tsdoc": "^0.4.0",
|
|
84
|
+
"javascript-obfuscator": "^4.1.0",
|
|
85
|
+
"tsup": "^8.5.1",
|
|
86
|
+
"tsx": "^4.19.4",
|
|
87
|
+
"typescript": "5.8.3"
|
|
88
|
+
},
|
|
89
|
+
"oclif": {
|
|
90
|
+
"bin": "basker",
|
|
91
|
+
"binAliases": [
|
|
92
|
+
"localstage"
|
|
93
|
+
],
|
|
94
|
+
"commands": "./dist/commands",
|
|
95
|
+
"topicSeparator": " ",
|
|
96
|
+
"topics": {
|
|
97
|
+
"theme": {
|
|
98
|
+
"description": "Theme development commands"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|