socket-function 0.115.0 → 0.117.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.
@@ -1,202 +1,202 @@
1
- /// <reference path="../../typenode/index.d.ts" />
2
- /// <reference path="../require/RequireController.ts" />
3
- module.allowclient = true;
4
-
5
- import { SocketFunction } from "../SocketFunction";
6
- import { cache, lazy } from "../src/caching";
7
- import * as fs from "fs";
8
- import debugbreak from "debugbreak";
9
- import { isNode } from "../src/misc";
10
- import { magenta, red } from "../src/formatting/logColors";
11
- import { formatTime } from "../src/formatting/format";
12
-
13
- /** Enables some hot reload functionality.
14
- * - Triggers a refresh clientside
15
- * - Triggers a reload server, for modules marked with `module.hotreload`
16
- */
17
- export function watchFilesAndTriggerHotReloading(noAutomaticBrowserWatch = false) {
18
- SocketFunction.expose(HotReloadController);
19
- if (!isNode()) {
20
- if (!noAutomaticBrowserWatch) {
21
- HotReloadController.nodes[SocketFunction.browserNodeId()]
22
- .watchFiles()
23
- .catch(e => console.error("watchFiles error", e))
24
- ;
25
- }
26
- }
27
- setInterval(() => {
28
- for (let module of Object.values(require.cache)) {
29
- if (!module) continue;
30
- hotReloadModule(module);
31
- }
32
- }, 5000);
33
- }
34
-
35
- declare global {
36
- namespace NodeJS {
37
- interface Module {
38
- /** Causes us to hotreload the file. Applies both serverside and clientside.
39
- * - If not set for any files clientside, we will refresh.
40
- * - If not set for any files serverside, we will do nothing (and just leave old code running).
41
- */
42
- hotreload?: boolean;
43
- /** Overrides hotreload to disable hot reloading. Useful if you add "hotreload.flag" to a directory
44
- * (which sets hotreload on all files in and under that directory), but want a specific file
45
- * to not hotreload.
46
- * - Also useful if you want files to hotreload clientside, but not serverside.
47
- */
48
- noserverhotreload?: boolean;
49
- }
50
- }
51
- var isHotReloading: (() => boolean) | undefined;
52
- }
53
-
54
- let isHotReloadingValue = false;
55
- export function isHotReloading() {
56
- return isHotReloadingValue;
57
- }
58
- globalThis.isHotReloading = isHotReloading;
59
- export function hotReloadingGuard(): true {
60
- return !isHotReloading() as any;
61
- }
62
- export function setExternalHotReloading(value: boolean) {
63
- isHotReloadingValue = value;
64
- }
65
- let hotReloadCallbacks: ((modules: NodeJS.Module[]) => void)[] = [];
66
- export function onHotReload(callback: (modules: NodeJS.Module[]) => void) {
67
- hotReloadCallbacks.push(callback);
68
- }
69
-
70
- const hotReloadModule = cache((module: NodeJS.Module) => {
71
- if (!module.updateContents) return;
72
- let interval = 1000;
73
- let fast = false;
74
- if (module.hotreload) {
75
- interval = 10;
76
- fast = true;
77
- }
78
- fs.watchFile(module.filename, { persistent: false, interval }, (curr, prev) => {
79
- if (curr.mtime.getTime() === prev.mtime.getTime()) return;
80
- console.log(`Hot reloading due to change: ${module.filename}`);
81
- module.updateContents?.();
82
- if (isNode() && !module.noserverhotreload) {
83
- if (
84
- module.hotreload
85
- // A fairly big hack (as this could just be in a string, or something similar), but... it also VERY useful
86
- || module.moduleContents?.includes("\nmodule.hotreload = true;" + "\n")
87
- || module.moduleContents?.includes("\r\nmodule.hotreload = true;" + "\r\n")
88
- ) {
89
- console.log(`Serverside reloading ${module.id}`);
90
- isHotReloadingValue = true;
91
- try {
92
- module.loaded = false;
93
- module.load(module.id);
94
- } catch (e) {
95
- console.error(red(`Error hot reloading ${module.id}`));
96
- console.error(e);
97
- } finally {
98
- setTimeout(() => {
99
- isHotReloadingValue = false;
100
- }, 1000);
101
- }
102
- }
103
- for (let callback of hotReloadCallbacks) {
104
- callback([module]);
105
- }
106
- }
107
- if (module.allowclient) {
108
- triggerClientSideReload({
109
- files: [module.filename],
110
- changeTime: curr.mtimeMs,
111
- fast,
112
- });
113
- }
114
- });
115
- });
116
- let reloadTriggering = false;
117
- let clientWatcherNodes = new Set<string>();
118
- function triggerClientSideReload(config: {
119
- files: string[];
120
- changeTime: number;
121
- fast?: boolean;
122
- }) {
123
- if (reloadTriggering) return;
124
- reloadTriggering = true;
125
- setTimeout(async () => {
126
- reloadTriggering = false;
127
- for (let clientNodeId of clientWatcherNodes) {
128
- console.log(`Notifying client of hot reload: ${clientNodeId}`);
129
- HotReloadController.nodes[clientNodeId].fileUpdated(config.files, config.changeTime).catch(() => {
130
- console.log(`Removing erroring client: ${clientNodeId}`);
131
- clientWatcherNodes.delete(clientNodeId);
132
- });
133
- }
134
- }, config.fast ? 10 : 300);
135
- }
136
-
137
- class HotReloadControllerBase {
138
- // TODO: Also hot reload when we reconnect to the server, as it is likely setup will need to
139
- // be rerun in that case as well (for example, we need to call watchFiles again!)
140
- async watchFiles() {
141
- let callerId = SocketFunction.getCaller().nodeId;
142
- clientWatcherNodes.add(callerId);
143
- }
144
- async fileUpdated(files: string[], changeTime: number) {
145
- try {
146
- console.groupCollapsed(magenta(`Trigger hotreload for files ${formatTime(Date.now() - changeTime)} after file change`));
147
- for (let file of files) {
148
- console.log(file);
149
- }
150
- console.groupEnd();
151
- let modules: NodeJS.Module[] = [];
152
- for (let file of files) {
153
- file = location.origin + "/" + file;
154
- let module = require.cache[file];
155
- if (!module) {
156
- console.log(`Module not found: ${file}, reloading page to ensure new version is loaded`);
157
- document.location.reload();
158
- return;
159
- }
160
- if (!module.hotreload) {
161
- console.log(`Module not hotreloadable: ${file}, reloading page to ensure new version is loaded`);
162
- document.location.reload();
163
- return;
164
- }
165
- modules.push(module);
166
- }
167
- for (let module of modules) {
168
- module.loaded = false;
169
- }
170
- isHotReloadingValue = true;
171
- try {
172
- await Promise.all(modules.map(module => module.load(module.filename)));
173
- } finally {
174
- setTimeout(() => {
175
- isHotReloadingValue = false;
176
- }, 1000);
177
- }
178
-
179
- for (let callback of hotReloadCallbacks) {
180
- callback(modules);
181
- }
182
- console.log(magenta(`Hot reload complete ${formatTime(Date.now() - changeTime)} after file change`));
183
- } catch (e: any) {
184
- console.error(`Hot reload failed ${e.stack}`);
185
- }
186
- }
187
- }
188
-
189
- export const HotReloadController = SocketFunction.register(
190
- "HotReloadController-032b2250-3aac-4187-8c95-75412742b8f5",
191
- new HotReloadControllerBase(),
192
- () => ({
193
- watchFiles: {},
194
- fileUpdated: {}
195
- }),
196
- () => ({
197
-
198
- }),
199
- {
200
- noAutoExpose: true,
201
- }
1
+ /// <reference path="../../typenode/index.d.ts" />
2
+ /// <reference path="../require/RequireController.ts" />
3
+ module.allowclient = true;
4
+
5
+ import { SocketFunction } from "../SocketFunction";
6
+ import { cache, lazy } from "../src/caching";
7
+ import * as fs from "fs";
8
+ import debugbreak from "debugbreak";
9
+ import { isNode } from "../src/misc";
10
+ import { magenta, red } from "../src/formatting/logColors";
11
+ import { formatTime } from "../src/formatting/format";
12
+
13
+ /** Enables some hot reload functionality.
14
+ * - Triggers a refresh clientside
15
+ * - Triggers a reload server, for modules marked with `module.hotreload`
16
+ */
17
+ export function watchFilesAndTriggerHotReloading(noAutomaticBrowserWatch = false) {
18
+ SocketFunction.expose(HotReloadController);
19
+ if (!isNode()) {
20
+ if (!noAutomaticBrowserWatch) {
21
+ HotReloadController.nodes[SocketFunction.browserNodeId()]
22
+ .watchFiles()
23
+ .catch(e => console.error("watchFiles error", e))
24
+ ;
25
+ }
26
+ }
27
+ setInterval(() => {
28
+ for (let module of Object.values(require.cache)) {
29
+ if (!module) continue;
30
+ hotReloadModule(module);
31
+ }
32
+ }, 5000);
33
+ }
34
+
35
+ declare global {
36
+ namespace NodeJS {
37
+ interface Module {
38
+ /** Causes us to hotreload the file. Applies both serverside and clientside.
39
+ * - If not set for any files clientside, we will refresh.
40
+ * - If not set for any files serverside, we will do nothing (and just leave old code running).
41
+ */
42
+ hotreload?: boolean;
43
+ /** Overrides hotreload to disable hot reloading. Useful if you add "hotreload.flag" to a directory
44
+ * (which sets hotreload on all files in and under that directory), but want a specific file
45
+ * to not hotreload.
46
+ * - Also useful if you want files to hotreload clientside, but not serverside.
47
+ */
48
+ noserverhotreload?: boolean;
49
+ }
50
+ }
51
+ var isHotReloading: (() => boolean) | undefined;
52
+ }
53
+
54
+ let isHotReloadingValue = false;
55
+ export function isHotReloading() {
56
+ return isHotReloadingValue;
57
+ }
58
+ globalThis.isHotReloading = isHotReloading;
59
+ export function hotReloadingGuard(): true {
60
+ return !isHotReloading() as any;
61
+ }
62
+ export function setExternalHotReloading(value: boolean) {
63
+ isHotReloadingValue = value;
64
+ }
65
+ let hotReloadCallbacks: ((modules: NodeJS.Module[]) => void)[] = [];
66
+ export function onHotReload(callback: (modules: NodeJS.Module[]) => void) {
67
+ hotReloadCallbacks.push(callback);
68
+ }
69
+
70
+ const hotReloadModule = cache((module: NodeJS.Module) => {
71
+ if (!module.updateContents) return;
72
+ let interval = 1000;
73
+ let fast = false;
74
+ if (module.hotreload) {
75
+ interval = 10;
76
+ fast = true;
77
+ }
78
+ fs.watchFile(module.filename, { persistent: false, interval }, (curr, prev) => {
79
+ if (curr.mtime.getTime() === prev.mtime.getTime()) return;
80
+ console.log(`Hot reloading due to change: ${module.filename}`);
81
+ module.updateContents?.();
82
+ if (isNode() && !module.noserverhotreload) {
83
+ if (
84
+ module.hotreload
85
+ // A fairly big hack (as this could just be in a string, or something similar), but... it also VERY useful
86
+ || module.moduleContents?.includes("\nmodule.hotreload = true;" + "\n")
87
+ || module.moduleContents?.includes("\r\nmodule.hotreload = true;" + "\r\n")
88
+ ) {
89
+ console.log(`Serverside reloading ${module.id}`);
90
+ isHotReloadingValue = true;
91
+ try {
92
+ module.loaded = false;
93
+ module.load(module.id);
94
+ } catch (e) {
95
+ console.error(red(`Error hot reloading ${module.id}`));
96
+ console.error(e);
97
+ } finally {
98
+ setTimeout(() => {
99
+ isHotReloadingValue = false;
100
+ }, 1000);
101
+ }
102
+ }
103
+ for (let callback of hotReloadCallbacks) {
104
+ callback([module]);
105
+ }
106
+ }
107
+ if (module.allowclient) {
108
+ triggerClientSideReload({
109
+ files: [module.filename],
110
+ changeTime: curr.mtimeMs,
111
+ fast,
112
+ });
113
+ }
114
+ });
115
+ });
116
+ let reloadTriggering = false;
117
+ let clientWatcherNodes = new Set<string>();
118
+ function triggerClientSideReload(config: {
119
+ files: string[];
120
+ changeTime: number;
121
+ fast?: boolean;
122
+ }) {
123
+ if (reloadTriggering) return;
124
+ reloadTriggering = true;
125
+ setTimeout(async () => {
126
+ reloadTriggering = false;
127
+ for (let clientNodeId of clientWatcherNodes) {
128
+ console.log(`Notifying client of hot reload: ${clientNodeId}`);
129
+ HotReloadController.nodes[clientNodeId].fileUpdated(config.files, config.changeTime).catch(() => {
130
+ console.log(`Removing erroring client: ${clientNodeId}`);
131
+ clientWatcherNodes.delete(clientNodeId);
132
+ });
133
+ }
134
+ }, config.fast ? 10 : 300);
135
+ }
136
+
137
+ class HotReloadControllerBase {
138
+ // TODO: Also hot reload when we reconnect to the server, as it is likely setup will need to
139
+ // be rerun in that case as well (for example, we need to call watchFiles again!)
140
+ async watchFiles() {
141
+ let callerId = SocketFunction.getCaller().nodeId;
142
+ clientWatcherNodes.add(callerId);
143
+ }
144
+ async fileUpdated(files: string[], changeTime: number) {
145
+ try {
146
+ console.groupCollapsed(magenta(`Trigger hotreload for files ${formatTime(Date.now() - changeTime)} after file change`));
147
+ for (let file of files) {
148
+ console.log(file);
149
+ }
150
+ console.groupEnd();
151
+ let modules: NodeJS.Module[] = [];
152
+ for (let file of files) {
153
+ file = "https://" + (BOOTED_EDGE_NODE?.host || location.host) + "/" + file;
154
+ let module = require.cache[file];
155
+ if (!module) {
156
+ console.log(`Module not found: ${file}, reloading page to ensure new version is loaded`);
157
+ document.location.reload();
158
+ return;
159
+ }
160
+ if (!module.hotreload) {
161
+ console.log(`Module not hotreloadable: ${file}, reloading page to ensure new version is loaded`);
162
+ document.location.reload();
163
+ return;
164
+ }
165
+ modules.push(module);
166
+ }
167
+ for (let module of modules) {
168
+ module.loaded = false;
169
+ }
170
+ isHotReloadingValue = true;
171
+ try {
172
+ await Promise.all(modules.map(module => module.load(module.filename)));
173
+ } finally {
174
+ setTimeout(() => {
175
+ isHotReloadingValue = false;
176
+ }, 1000);
177
+ }
178
+
179
+ for (let callback of hotReloadCallbacks) {
180
+ callback(modules);
181
+ }
182
+ console.log(magenta(`Hot reload complete ${formatTime(Date.now() - changeTime)} after file change`));
183
+ } catch (e: any) {
184
+ console.error(`Hot reload failed ${e.stack}`);
185
+ }
186
+ }
187
+ }
188
+
189
+ export const HotReloadController = SocketFunction.register(
190
+ "HotReloadController-032b2250-3aac-4187-8c95-75412742b8f5",
191
+ new HotReloadControllerBase(),
192
+ () => ({
193
+ watchFiles: {},
194
+ fileUpdated: {}
195
+ }),
196
+ () => ({
197
+
198
+ }),
199
+ {
200
+ noAutoExpose: true,
201
+ }
202
202
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "socket-function",
3
- "version": "0.115.0",
3
+ "version": "0.117.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "dependencies": {
@@ -575,8 +575,8 @@ export async function createCallFactory(
575
575
  if (SocketFunction.logMessages) {
576
576
  console.log(`SIZE\t${(formatNumberSuffixed(resultSize) + "B").padEnd(4, " ")}\tEVALUATE\t${call.classGuid}.${call.functionName} at ${Date.now()}, (${nodeId} / ${localNodeId})`);
577
577
  }
578
- if (time > SocketFunction.WIRE_WARN_TIME) {
579
- console.log(red(`Slow parse, took ${time}ms to parse ${resultSize} bytes, for call to ${call.classGuid}.${call.functionName}`));
578
+ if (parseTime > SocketFunction.WIRE_WARN_TIME) {
579
+ console.log(red(`Slow parse, took ${parseTime}ms to parse ${resultSize} bytes, for call to ${call.classGuid}.${call.functionName}`));
580
580
  }
581
581
 
582
582
  let response: InternalReturnType;