azul-sync 1.3.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/.gitattributes +1 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/README.md +142 -0
- package/dist/build.d.ts +19 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +92 -0
- package/dist/build.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +397 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +105 -0
- package/dist/config.js.map +1 -0
- package/dist/fs/fileWriter.d.ts +100 -0
- package/dist/fs/fileWriter.d.ts.map +1 -0
- package/dist/fs/fileWriter.js +342 -0
- package/dist/fs/fileWriter.js.map +1 -0
- package/dist/fs/treeManager.d.ts +84 -0
- package/dist/fs/treeManager.d.ts.map +1 -0
- package/dist/fs/treeManager.js +365 -0
- package/dist/fs/treeManager.js.map +1 -0
- package/dist/fs/watcher.d.ts +39 -0
- package/dist/fs/watcher.d.ts.map +1 -0
- package/dist/fs/watcher.js +120 -0
- package/dist/fs/watcher.js.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +349 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/httpPolling.d.ts +56 -0
- package/dist/ipc/httpPolling.d.ts.map +1 -0
- package/dist/ipc/httpPolling.js +171 -0
- package/dist/ipc/httpPolling.js.map +1 -0
- package/dist/ipc/messages.d.ts +112 -0
- package/dist/ipc/messages.d.ts.map +1 -0
- package/dist/ipc/messages.js +5 -0
- package/dist/ipc/messages.js.map +1 -0
- package/dist/ipc/server.d.ts +50 -0
- package/dist/ipc/server.d.ts.map +1 -0
- package/dist/ipc/server.js +168 -0
- package/dist/ipc/server.js.map +1 -0
- package/dist/pack.d.ts +19 -0
- package/dist/pack.d.ts.map +1 -0
- package/dist/pack.js +225 -0
- package/dist/pack.js.map +1 -0
- package/dist/push.d.ts +43 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/push.js +532 -0
- package/dist/push.js.map +1 -0
- package/dist/rojo.d.ts +9 -0
- package/dist/rojo.d.ts.map +1 -0
- package/dist/rojo.js +114 -0
- package/dist/rojo.js.map +1 -0
- package/dist/snapshot/rojo.d.ts +39 -0
- package/dist/snapshot/rojo.d.ts.map +1 -0
- package/dist/snapshot/rojo.js +364 -0
- package/dist/snapshot/rojo.js.map +1 -0
- package/dist/snapshot.d.ts +23 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +132 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/sourcemap/generator.d.ts +78 -0
- package/dist/sourcemap/generator.d.ts.map +1 -0
- package/dist/sourcemap/generator.js +351 -0
- package/dist/sourcemap/generator.js.map +1 -0
- package/dist/sourcemap/propertyLoader.d.ts +19 -0
- package/dist/sourcemap/propertyLoader.d.ts.map +1 -0
- package/dist/sourcemap/propertyLoader.js +131 -0
- package/dist/sourcemap/propertyLoader.js.map +1 -0
- package/dist/util/id.d.ts +9 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +14 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/log.d.ts +13 -0
- package/dist/util/log.d.ts.map +1 -0
- package/dist/util/log.js +51 -0
- package/dist/util/log.js.map +1 -0
- package/docs/assets/azul-logo.pdn +0 -0
- package/docs/assets/logo-200px.png +0 -0
- package/docs/assets/logo.png +0 -0
- package/docs/assets/plugin/toolbox.png +0 -0
- package/docs/assets/synced.png +0 -0
- package/package.json +41 -0
- package/plugin/README.md +54 -0
- package/plugin/sourcemap.json +264 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Actor/AzulSync.server.luau +905 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/AzulService.luau +1010 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Config.luau +29 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Enums.luau +11 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/CollapsibleTitledSection.luau +214 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/ColorPicker.luau +360 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/CustomTextButton.luau +170 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/DropdownMenu.luau +363 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/HorizontalLine.luau +43 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/ImageButtonWithText.luau +181 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledCheckbox.luau +295 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledColorInputPicker.luau +294 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledMultiChoice.luau +163 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledNumberInput.luau +312 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledRadioButton.luau +55 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledSlider.luau +151 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledTextInput.luau +222 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledToggleButton.luau +73 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/StatefulImageButton.luau +125 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticalScrollingFrame.luau +100 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticalSpacer.luau +35 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticallyScalingListFrame.luau +107 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/GuiUtilities.luau +429 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/RbxGui.luau +4363 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/UI.luau +425 -0
- package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/WebSocketClient.luau +161 -0
- package/src/build.ts +120 -0
- package/src/cli.ts +496 -0
- package/src/config.ts +170 -0
- package/src/fs/fileWriter.ts +414 -0
- package/src/fs/treeManager.ts +458 -0
- package/src/fs/watcher.ts +142 -0
- package/src/index.ts +450 -0
- package/src/ipc/httpPolling.ts +214 -0
- package/src/ipc/messages.ts +159 -0
- package/src/ipc/server.ts +196 -0
- package/src/pack.ts +309 -0
- package/src/push.ts +726 -0
- package/src/snapshot/rojo.ts +467 -0
- package/src/snapshot.ts +161 -0
- package/src/sourcemap/generator.ts +504 -0
- package/src/sourcemap/propertyLoader.ts +195 -0
- package/src/util/id.ts +15 -0
- package/src/util/log.ts +94 -0
- package/tsconfig.json +24 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import * as http from "http";
|
|
5
|
+
import { IPCServer } from "./ipc/server.js";
|
|
6
|
+
import { HttpPollingServer } from "./ipc/httpPolling.js";
|
|
7
|
+
import { TreeManager } from "./fs/treeManager.js";
|
|
8
|
+
import { FileWriter } from "./fs/fileWriter.js";
|
|
9
|
+
import { FileWatcher } from "./fs/watcher.js";
|
|
10
|
+
import { SourcemapGenerator } from "./sourcemap/generator.js";
|
|
11
|
+
import { log } from "./util/log.js";
|
|
12
|
+
import { config, initializeConfig } from "./config.js";
|
|
13
|
+
/**
|
|
14
|
+
* Main orchestrator for the Azul daemon
|
|
15
|
+
*/
|
|
16
|
+
export class SyncDaemon {
|
|
17
|
+
ipc;
|
|
18
|
+
httpPolling;
|
|
19
|
+
httpServer;
|
|
20
|
+
tree;
|
|
21
|
+
fileWriter;
|
|
22
|
+
fileWatcher;
|
|
23
|
+
sourcemapGenerator;
|
|
24
|
+
batchDepth = 0; // Tracks nested batch processing
|
|
25
|
+
batchNeedsSourcemapRegen = false; // Defer regen until batch ends
|
|
26
|
+
constructor() {
|
|
27
|
+
this.tree = new TreeManager();
|
|
28
|
+
this.fileWriter = new FileWriter(config.syncDir);
|
|
29
|
+
this.fileWatcher = new FileWatcher();
|
|
30
|
+
this.sourcemapGenerator = new SourcemapGenerator();
|
|
31
|
+
this.httpPolling = new HttpPollingServer();
|
|
32
|
+
// Create HTTP server that handles both WebSocket upgrades and HTTP polling
|
|
33
|
+
this.httpServer = http.createServer((req, res) => {
|
|
34
|
+
const handled = this.httpPolling.handleRequest(req, res);
|
|
35
|
+
if (!handled) {
|
|
36
|
+
res.writeHead(404);
|
|
37
|
+
res.end("Not found");
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
this.ipc = new IPCServer(config.port, this.httpServer);
|
|
41
|
+
this.setupHandlers();
|
|
42
|
+
this.httpServer.listen(config.port);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Set up all event handlers
|
|
46
|
+
*/
|
|
47
|
+
setupHandlers() {
|
|
48
|
+
// Handle messages from Studio (WebSocket)
|
|
49
|
+
this.ipc.onMessage((message) => this.handleStudioMessage(message));
|
|
50
|
+
// Handle messages from Studio (HTTP polling)
|
|
51
|
+
this.httpPolling.onMessage((message) => this.handleStudioMessage(message));
|
|
52
|
+
// Handle file changes from filesystem
|
|
53
|
+
this.fileWatcher.onChange((filePath, source) => {
|
|
54
|
+
this.handleFileChange(filePath, source);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Handle incoming messages from Studio
|
|
59
|
+
*/
|
|
60
|
+
handleStudioMessage(message) {
|
|
61
|
+
if (message.type === "batch") {
|
|
62
|
+
this.batchDepth += 1;
|
|
63
|
+
try {
|
|
64
|
+
for (const payload of message.messages) {
|
|
65
|
+
this.handleStudioMessage(payload);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
this.batchDepth -= 1;
|
|
70
|
+
// If any delete in this batch missed its prune, only regenerate once at the end
|
|
71
|
+
if (this.batchDepth === 0 && this.batchNeedsSourcemapRegen) {
|
|
72
|
+
this.regenerateSourcemap();
|
|
73
|
+
this.batchNeedsSourcemapRegen = false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
switch (message.type) {
|
|
79
|
+
case "fullSnapshot":
|
|
80
|
+
this.handleFullSnapshot(message.data);
|
|
81
|
+
break;
|
|
82
|
+
case "scriptChanged":
|
|
83
|
+
this.handleScriptChanged(message.data);
|
|
84
|
+
break;
|
|
85
|
+
case "instanceUpdated":
|
|
86
|
+
this.handleInstanceUpdated(message.data);
|
|
87
|
+
break;
|
|
88
|
+
case "deleted":
|
|
89
|
+
this.handleDeleted(message.data);
|
|
90
|
+
break;
|
|
91
|
+
case "ping":
|
|
92
|
+
this.ipc.send({ type: "pong" });
|
|
93
|
+
break;
|
|
94
|
+
case "clientDisconnect":
|
|
95
|
+
log.info("Studio requested to close the connection");
|
|
96
|
+
this.ipc.close();
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
log.warn("Unknown message type:", message.type);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Handle full snapshot from Studio
|
|
104
|
+
*/
|
|
105
|
+
handleFullSnapshot(data) {
|
|
106
|
+
log.info("Received full snapshot from Studio");
|
|
107
|
+
// Update tree
|
|
108
|
+
this.tree.applyFullSnapshot(data);
|
|
109
|
+
// Write all scripts to filesystem
|
|
110
|
+
this.fileWriter.writeTree(this.tree.getAllNodes());
|
|
111
|
+
// Remove any pre-existing files that are no longer mapped (optional)
|
|
112
|
+
this.cleanupOrphanFiles();
|
|
113
|
+
// Start file watching
|
|
114
|
+
this.fileWatcher.watch(this.fileWriter.getBaseDir());
|
|
115
|
+
// Generate sourcemap
|
|
116
|
+
this.regenerateSourcemap();
|
|
117
|
+
// Log statistics
|
|
118
|
+
const stats = this.tree.getStats();
|
|
119
|
+
log.success(`Sync complete: ${stats.scriptNodes} scripts, ${stats.totalNodes} total nodes`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Handle script source change
|
|
123
|
+
*/
|
|
124
|
+
handleScriptChanged(message) {
|
|
125
|
+
const { guid, source, path: instancePath, className } = message;
|
|
126
|
+
// Update tree
|
|
127
|
+
this.tree.updateScriptSource(guid, source);
|
|
128
|
+
// Get or create node
|
|
129
|
+
let node = this.tree.getNode(guid);
|
|
130
|
+
if (!node) {
|
|
131
|
+
// Create new node if it doesn't exist
|
|
132
|
+
this.tree.updateInstance({
|
|
133
|
+
guid,
|
|
134
|
+
className,
|
|
135
|
+
name: instancePath[instancePath.length - 1],
|
|
136
|
+
path: instancePath,
|
|
137
|
+
source,
|
|
138
|
+
});
|
|
139
|
+
node = this.tree.getNode(guid);
|
|
140
|
+
}
|
|
141
|
+
if (node) {
|
|
142
|
+
// Precompute path and suppress watcher before writing to avoid race conditions
|
|
143
|
+
const filePath = this.fileWriter.getFilePath(node);
|
|
144
|
+
this.fileWatcher.suppressNextChange(filePath);
|
|
145
|
+
// Write to filesystem
|
|
146
|
+
this.fileWriter.writeScript(node);
|
|
147
|
+
// Incrementally update sourcemap entry for this script
|
|
148
|
+
this.sourcemapGenerator.upsertSubtree(node, this.tree.getAllNodes(), this.fileWriter.getAllMappings(), config.sourcemapPath, undefined, false);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Handle instance update (rename, move, etc.)
|
|
153
|
+
*/
|
|
154
|
+
handleInstanceUpdated(data) {
|
|
155
|
+
const update = this.tree.updateInstance(data);
|
|
156
|
+
const node = update?.node;
|
|
157
|
+
if (!node) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const scriptsToUpdate = new Map();
|
|
161
|
+
if (this.isScriptClass(node.className)) {
|
|
162
|
+
scriptsToUpdate.set(node.guid, node);
|
|
163
|
+
}
|
|
164
|
+
if (update.pathChanged || update.nameChanged || update.parentChanged) {
|
|
165
|
+
for (const child of this.tree.getDescendantScripts(node.guid)) {
|
|
166
|
+
scriptsToUpdate.set(child.guid, child);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (const scriptNode of scriptsToUpdate.values()) {
|
|
170
|
+
const filePath = this.fileWriter.getFilePath(scriptNode);
|
|
171
|
+
this.fileWatcher.suppressNextChange(filePath);
|
|
172
|
+
this.fileWriter.writeScript(scriptNode);
|
|
173
|
+
}
|
|
174
|
+
const shouldUpdateSourcemap = update.isNew ||
|
|
175
|
+
update.pathChanged ||
|
|
176
|
+
update.nameChanged ||
|
|
177
|
+
update.parentChanged ||
|
|
178
|
+
this.isScriptClass(node.className);
|
|
179
|
+
if (shouldUpdateSourcemap) {
|
|
180
|
+
this.sourcemapGenerator.upsertSubtree(node, this.tree.getAllNodes(), this.fileWriter.getAllMappings(), config.sourcemapPath, update.prevPath, update.isNew);
|
|
181
|
+
}
|
|
182
|
+
this.fileWriter.cleanupEmptyDirectories();
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Handle instance deletion
|
|
186
|
+
*/
|
|
187
|
+
handleDeleted(message) {
|
|
188
|
+
const { guid } = message;
|
|
189
|
+
const node = this.tree.getNode(guid);
|
|
190
|
+
// If the node is already gone (e.g., child deletes after parent delete), fall back to full cleanup
|
|
191
|
+
if (!node) {
|
|
192
|
+
log.debug(`Delete ignored for unknown guid: ${guid}`);
|
|
193
|
+
this.fileWriter.deleteScript(guid);
|
|
194
|
+
// this.regenerateSourcemap();
|
|
195
|
+
this.fileWriter.cleanupEmptyDirectories();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
// Capture all script descendants (and the node itself if script) before we delete the tree nodes
|
|
199
|
+
const scriptsToDelete = [];
|
|
200
|
+
const collectScript = (scriptNode) => {
|
|
201
|
+
const filePath = this.fileWriter.getFilePath(scriptNode);
|
|
202
|
+
scriptsToDelete.push({ guid: scriptNode.guid, filePath });
|
|
203
|
+
};
|
|
204
|
+
if (this.isScriptClass(node.className)) {
|
|
205
|
+
collectScript(node);
|
|
206
|
+
}
|
|
207
|
+
for (const child of this.tree.getDescendantScripts(node.guid)) {
|
|
208
|
+
collectScript(child);
|
|
209
|
+
}
|
|
210
|
+
const pathSegments = node.path;
|
|
211
|
+
// Delete from tree (removes node and descendants)
|
|
212
|
+
this.tree.deleteInstance(guid);
|
|
213
|
+
// Delete files for all affected scripts
|
|
214
|
+
for (const entry of scriptsToDelete) {
|
|
215
|
+
const removed = this.fileWriter.deleteScript(entry.guid);
|
|
216
|
+
if (!removed && entry.filePath) {
|
|
217
|
+
this.fileWriter.deleteFilePath(entry.filePath);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Remove subtree from sourcemap
|
|
221
|
+
const outputPath = config.sourcemapPath;
|
|
222
|
+
const pruned = this.sourcemapGenerator.prunePath(pathSegments, outputPath, this.tree.getAllNodes(), this.fileWriter.getAllMappings(), node.className, node.guid);
|
|
223
|
+
// If prune failed to find the path (e.g., sourcemap drift), rebuild once to stay consistent
|
|
224
|
+
if (!pruned) {
|
|
225
|
+
if (this.batchDepth > 0) {
|
|
226
|
+
// Defer regeneration until the batch completes to avoid repeated full rebuilds
|
|
227
|
+
this.batchNeedsSourcemapRegen = true;
|
|
228
|
+
log.debug("Regenerating sourcemap after batched prune miss");
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
log.debug("Regenerating sourcemap due to prune miss");
|
|
232
|
+
this.regenerateSourcemap();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
this.fileWriter.cleanupEmptyDirectories();
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Handle file change from filesystem
|
|
239
|
+
*/
|
|
240
|
+
handleFileChange(filePath, source) {
|
|
241
|
+
// Find the GUID for this file
|
|
242
|
+
const guid = this.fileWriter.getGuidByPath(filePath);
|
|
243
|
+
if (guid) {
|
|
244
|
+
log.info(`File changed externally: ${path.relative(this.fileWriter.getBaseDir(), filePath)}.`);
|
|
245
|
+
// Update tree
|
|
246
|
+
this.tree.updateScriptSource(guid, source);
|
|
247
|
+
// Send patch to Studio (both WebSocket and HTTP polling clients)
|
|
248
|
+
this.ipc.patchScript(guid, source);
|
|
249
|
+
this.httpPolling.broadcast({ type: "patchScript", guid, source });
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
log.warn(`No mapping found for file: ${filePath}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Regenerate the sourcemap
|
|
257
|
+
*/
|
|
258
|
+
regenerateSourcemap() {
|
|
259
|
+
// Write sourcemap into the sync directory so Luau-LSP can find it
|
|
260
|
+
const outputPath = config.sourcemapPath;
|
|
261
|
+
this.sourcemapGenerator.generateAndWrite(this.tree.getAllNodes(), this.fileWriter.getAllMappings(), outputPath);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Start the daemon
|
|
265
|
+
*/
|
|
266
|
+
start() {
|
|
267
|
+
log.info("🚀 Azul daemon starting...");
|
|
268
|
+
log.info(`Sync directory: ${config.syncDir}`);
|
|
269
|
+
log.info(`HTTP/WebSocket port: ${config.port}`);
|
|
270
|
+
log.info("");
|
|
271
|
+
log.success(`Server listening on http://localhost:${config.port}`);
|
|
272
|
+
log.info("Waiting for Studio connection...");
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Stop the daemon
|
|
276
|
+
*/
|
|
277
|
+
async stop() {
|
|
278
|
+
log.info("Stopping daemon...");
|
|
279
|
+
await this.fileWatcher.stop();
|
|
280
|
+
this.ipc.close();
|
|
281
|
+
this.httpServer.close();
|
|
282
|
+
log.info("Daemon stopped");
|
|
283
|
+
}
|
|
284
|
+
isScriptClass(className) {
|
|
285
|
+
return (className === "Script" ||
|
|
286
|
+
className === "LocalScript" ||
|
|
287
|
+
className === "ModuleScript");
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Delete files under syncDir that are not mapped to any instance (opt-in).
|
|
291
|
+
*/
|
|
292
|
+
cleanupOrphanFiles() {
|
|
293
|
+
if (!config.deleteOrphansOnConnect) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const baseDir = this.fileWriter.getBaseDir();
|
|
297
|
+
const mapped = new Set();
|
|
298
|
+
for (const mapping of this.fileWriter.getAllMappings().values()) {
|
|
299
|
+
mapped.add(path.resolve(mapping.filePath));
|
|
300
|
+
}
|
|
301
|
+
let removedFiles = [];
|
|
302
|
+
const walk = (dir) => {
|
|
303
|
+
if (!fs.existsSync(dir))
|
|
304
|
+
return;
|
|
305
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
306
|
+
for (const entry of entries) {
|
|
307
|
+
const fullPath = path.join(dir, entry.name);
|
|
308
|
+
if (entry.isDirectory()) {
|
|
309
|
+
walk(fullPath);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
if (!mapped.has(path.resolve(fullPath))) {
|
|
313
|
+
try {
|
|
314
|
+
fs.unlinkSync(fullPath);
|
|
315
|
+
removedFiles.push(entry.name);
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
log.warn("Failed to delete orphan file:", fullPath, error);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
walk(baseDir);
|
|
325
|
+
if (removedFiles.length > 0) {
|
|
326
|
+
this.fileWriter.cleanupEmptyDirectories();
|
|
327
|
+
log.success(`Removed ${removedFiles.length} orphan file(s) from sync directory (${removedFiles.join(", ")})`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// Allow direct execution (`node dist/index.js`) while preventing side effects when imported by the CLI
|
|
332
|
+
const isDirectRun = process.argv[1] &&
|
|
333
|
+
fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
334
|
+
if (isDirectRun) {
|
|
335
|
+
initializeConfig();
|
|
336
|
+
const daemon = new SyncDaemon();
|
|
337
|
+
daemon.start();
|
|
338
|
+
// Handle graceful shutdown
|
|
339
|
+
process.on("SIGINT", async () => {
|
|
340
|
+
console.log("\n");
|
|
341
|
+
await daemon.stop();
|
|
342
|
+
process.exit(0);
|
|
343
|
+
});
|
|
344
|
+
process.on("SIGTERM", async () => {
|
|
345
|
+
await daemon.stop();
|
|
346
|
+
process.exit(0);
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP endpoints for plugin polling compatibility
|
|
3
|
+
*/
|
|
4
|
+
import { IncomingMessage, ServerResponse } from "http";
|
|
5
|
+
/**
|
|
6
|
+
* Manages HTTP polling for Roblox Studio plugin compatibility
|
|
7
|
+
*/
|
|
8
|
+
export declare class HttpPollingServer {
|
|
9
|
+
private clients;
|
|
10
|
+
private messageHandler;
|
|
11
|
+
/**
|
|
12
|
+
* Handle HTTP request
|
|
13
|
+
*/
|
|
14
|
+
handleRequest(req: IncomingMessage, res: ServerResponse): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Handle connect request
|
|
17
|
+
*/
|
|
18
|
+
private handleConnect;
|
|
19
|
+
/**
|
|
20
|
+
* Handle send request
|
|
21
|
+
*/
|
|
22
|
+
private handleSend;
|
|
23
|
+
/**
|
|
24
|
+
* Handle poll request
|
|
25
|
+
*/
|
|
26
|
+
private handlePoll;
|
|
27
|
+
/**
|
|
28
|
+
* Handle disconnect request
|
|
29
|
+
*/
|
|
30
|
+
private handleDisconnect;
|
|
31
|
+
/**
|
|
32
|
+
* Send message to a specific client
|
|
33
|
+
*/
|
|
34
|
+
sendToClient(clientId: string, message: any): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Broadcast message to all clients
|
|
37
|
+
*/
|
|
38
|
+
broadcast(message: any): void;
|
|
39
|
+
/**
|
|
40
|
+
* Set message handler
|
|
41
|
+
*/
|
|
42
|
+
onMessage(handler: (message: any, clientId: string) => void): void;
|
|
43
|
+
/**
|
|
44
|
+
* Clean up stale clients
|
|
45
|
+
*/
|
|
46
|
+
cleanupStaleClients(timeoutMs?: number): void;
|
|
47
|
+
/**
|
|
48
|
+
* Generate unique client ID
|
|
49
|
+
*/
|
|
50
|
+
private generateClientId;
|
|
51
|
+
/**
|
|
52
|
+
* Get active client count
|
|
53
|
+
*/
|
|
54
|
+
getClientCount(): number;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=httpPolling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpPolling.d.ts","sourceRoot":"","sources":["../../src/ipc/httpPolling.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AASvD;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,cAAc,CACf;IAEP;;OAEG;IACI,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO;IA4BxE;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;IACH,OAAO,CAAC,UAAU;IA2BlB;;OAEG;IACH,OAAO,CAAC,UAAU;IAuBlB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA4BxB;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO;IAU5D;;OAEG;IACI,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAMpC;;OAEG;IACI,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIzE;;OAEG;IACI,mBAAmB,CAAC,SAAS,GAAE,MAAc,GAAG,IAAI;IAU3D;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACI,cAAc,IAAI,MAAM;CAGhC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP endpoints for plugin polling compatibility
|
|
3
|
+
*/
|
|
4
|
+
import { log } from "../util/log.js";
|
|
5
|
+
/**
|
|
6
|
+
* Manages HTTP polling for Roblox Studio plugin compatibility
|
|
7
|
+
*/
|
|
8
|
+
export class HttpPollingServer {
|
|
9
|
+
clients = new Map();
|
|
10
|
+
messageHandler = null;
|
|
11
|
+
/**
|
|
12
|
+
* Handle HTTP request
|
|
13
|
+
*/
|
|
14
|
+
handleRequest(req, res) {
|
|
15
|
+
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
|
16
|
+
// Enable CORS
|
|
17
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
18
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
19
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
20
|
+
if (req.method === "OPTIONS") {
|
|
21
|
+
res.writeHead(200);
|
|
22
|
+
res.end();
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
switch (url.pathname) {
|
|
26
|
+
case "/connect":
|
|
27
|
+
return this.handleConnect(req, res);
|
|
28
|
+
case "/send":
|
|
29
|
+
return this.handleSend(req, res);
|
|
30
|
+
case "/poll":
|
|
31
|
+
return this.handlePoll(req, res, url);
|
|
32
|
+
case "/disconnect":
|
|
33
|
+
return this.handleDisconnect(req, res);
|
|
34
|
+
default:
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Handle connect request
|
|
40
|
+
*/
|
|
41
|
+
handleConnect(_req, res) {
|
|
42
|
+
const clientId = this.generateClientId();
|
|
43
|
+
this.clients.set(clientId, {
|
|
44
|
+
id: clientId,
|
|
45
|
+
messageQueue: [],
|
|
46
|
+
lastPoll: Date.now(),
|
|
47
|
+
});
|
|
48
|
+
log.info(`HTTP client connected: ${clientId}`);
|
|
49
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
50
|
+
res.end(JSON.stringify({ clientId }));
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Handle send request
|
|
55
|
+
*/
|
|
56
|
+
handleSend(req, res) {
|
|
57
|
+
let body = "";
|
|
58
|
+
req.on("data", (chunk) => {
|
|
59
|
+
body += chunk.toString();
|
|
60
|
+
});
|
|
61
|
+
req.on("end", () => {
|
|
62
|
+
try {
|
|
63
|
+
const data = JSON.parse(body);
|
|
64
|
+
const { clientId, message } = data;
|
|
65
|
+
if (this.messageHandler) {
|
|
66
|
+
this.messageHandler(message, clientId);
|
|
67
|
+
}
|
|
68
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
69
|
+
res.end(JSON.stringify({ success: true }));
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
73
|
+
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Handle poll request
|
|
80
|
+
*/
|
|
81
|
+
handlePoll(_req, res, url) {
|
|
82
|
+
const clientId = url.searchParams.get("clientId");
|
|
83
|
+
if (!clientId || !this.clients.has(clientId)) {
|
|
84
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
85
|
+
res.end(JSON.stringify({ error: "Client not found" }));
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
const client = this.clients.get(clientId);
|
|
89
|
+
client.lastPoll = Date.now();
|
|
90
|
+
const messages = client.messageQueue.splice(0); // Take all messages
|
|
91
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
92
|
+
res.end(JSON.stringify(messages));
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Handle disconnect request
|
|
97
|
+
*/
|
|
98
|
+
handleDisconnect(req, res) {
|
|
99
|
+
let body = "";
|
|
100
|
+
req.on("data", (chunk) => {
|
|
101
|
+
body += chunk.toString();
|
|
102
|
+
});
|
|
103
|
+
req.on("end", () => {
|
|
104
|
+
try {
|
|
105
|
+
const data = JSON.parse(body);
|
|
106
|
+
const { clientId } = data;
|
|
107
|
+
if (clientId && this.clients.has(clientId)) {
|
|
108
|
+
this.clients.delete(clientId);
|
|
109
|
+
log.info(`HTTP client disconnected: ${clientId}`);
|
|
110
|
+
}
|
|
111
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
112
|
+
res.end(JSON.stringify({ success: true }));
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
116
|
+
res.end(JSON.stringify({ error: "Invalid JSON" }));
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Send message to a specific client
|
|
123
|
+
*/
|
|
124
|
+
sendToClient(clientId, message) {
|
|
125
|
+
const client = this.clients.get(clientId);
|
|
126
|
+
if (!client) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
client.messageQueue.push(message);
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Broadcast message to all clients
|
|
134
|
+
*/
|
|
135
|
+
broadcast(message) {
|
|
136
|
+
for (const client of this.clients.values()) {
|
|
137
|
+
client.messageQueue.push(message);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Set message handler
|
|
142
|
+
*/
|
|
143
|
+
onMessage(handler) {
|
|
144
|
+
this.messageHandler = handler;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Clean up stale clients
|
|
148
|
+
*/
|
|
149
|
+
cleanupStaleClients(timeoutMs = 60000) {
|
|
150
|
+
const now = Date.now();
|
|
151
|
+
for (const [id, client] of this.clients.entries()) {
|
|
152
|
+
if (now - client.lastPoll > timeoutMs) {
|
|
153
|
+
this.clients.delete(id);
|
|
154
|
+
log.info(`Removed stale HTTP client: ${id}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Generate unique client ID
|
|
160
|
+
*/
|
|
161
|
+
generateClientId() {
|
|
162
|
+
return `client_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get active client count
|
|
166
|
+
*/
|
|
167
|
+
getClientCount() {
|
|
168
|
+
return this.clients.size;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=httpPolling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpPolling.js","sourceRoot":"","sources":["../../src/ipc/httpPolling.ts"],"names":[],"mappings":"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"}
|