@arcanejs/toolkit 6.0.0 → 7.0.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.
Files changed (72) hide show
  1. package/README.md +156 -12
  2. package/dist/backend/components/base.d.mts +1 -1
  3. package/dist/backend/components/base.d.ts +1 -1
  4. package/dist/backend/components/button.d.mts +1 -1
  5. package/dist/backend/components/button.d.ts +1 -1
  6. package/dist/backend/components/button.js +2 -2
  7. package/dist/backend/components/button.mjs +1 -1
  8. package/dist/backend/components/group.d.mts +1 -1
  9. package/dist/backend/components/group.d.ts +1 -1
  10. package/dist/backend/components/group.js +2 -2
  11. package/dist/backend/components/group.mjs +1 -1
  12. package/dist/backend/components/label.d.mts +2 -2
  13. package/dist/backend/components/label.d.ts +2 -2
  14. package/dist/backend/components/label.js +2 -2
  15. package/dist/backend/components/label.mjs +1 -1
  16. package/dist/backend/components/rect.d.mts +2 -2
  17. package/dist/backend/components/rect.d.ts +2 -2
  18. package/dist/backend/components/rect.js +2 -2
  19. package/dist/backend/components/rect.mjs +1 -1
  20. package/dist/backend/components/slider-button.d.mts +2 -2
  21. package/dist/backend/components/slider-button.d.ts +2 -2
  22. package/dist/backend/components/slider-button.js +2 -2
  23. package/dist/backend/components/slider-button.mjs +1 -1
  24. package/dist/backend/components/switch.d.mts +2 -2
  25. package/dist/backend/components/switch.d.ts +2 -2
  26. package/dist/backend/components/switch.js +2 -2
  27. package/dist/backend/components/switch.mjs +1 -1
  28. package/dist/backend/components/tabs.d.mts +3 -3
  29. package/dist/backend/components/tabs.d.ts +3 -3
  30. package/dist/backend/components/tabs.js +2 -2
  31. package/dist/backend/components/tabs.mjs +1 -1
  32. package/dist/backend/components/text-input.d.mts +2 -2
  33. package/dist/backend/components/text-input.d.ts +2 -2
  34. package/dist/backend/components/text-input.js +2 -2
  35. package/dist/backend/components/text-input.mjs +1 -1
  36. package/dist/backend/components/timeline.d.mts +2 -2
  37. package/dist/backend/components/timeline.d.ts +2 -2
  38. package/dist/backend/components/timeline.js +2 -2
  39. package/dist/backend/components/timeline.mjs +1 -1
  40. package/dist/{chunk-53EOA4UE.js → chunk-2K4UT5QB.js} +1 -1
  41. package/dist/{chunk-4OCRZD4F.js → chunk-4AGKM5NT.js} +1 -1
  42. package/dist/{chunk-QAH2OSHR.js → chunk-5B65Q7RL.js} +1 -1
  43. package/dist/{chunk-3TXBS2UN.mjs → chunk-6PS3Q66F.mjs} +1 -1
  44. package/dist/{chunk-LK6MGXYC.mjs → chunk-7MQHRTBE.mjs} +1 -1
  45. package/dist/{chunk-U6FSQBQ3.js → chunk-A3RWE7HZ.js} +6 -4
  46. package/dist/{chunk-NL3W4M7J.js → chunk-CVY55KAR.js} +1 -1
  47. package/dist/{chunk-WDB3IMOP.mjs → chunk-GXJ3JRRK.mjs} +1 -1
  48. package/dist/{chunk-HTCWMJUA.js → chunk-IV3AE3CW.js} +1 -1
  49. package/dist/{chunk-UQWCTVMC.mjs → chunk-JHWFQLLE.mjs} +1 -1
  50. package/dist/{chunk-QB2WPBWV.mjs → chunk-K6V55JTG.mjs} +1 -1
  51. package/dist/{chunk-PG5EAV5X.mjs → chunk-MHSAHTVN.mjs} +1 -1
  52. package/dist/{chunk-KMEDXCBI.mjs → chunk-R5OA7LLZ.mjs} +6 -4
  53. package/dist/{chunk-6ELB27LK.mjs → chunk-RJLYYTZ6.mjs} +1 -1
  54. package/dist/{chunk-3GTEUTFT.js → chunk-TF7N4O5G.js} +1 -1
  55. package/dist/{chunk-E6FGU7DA.mjs → chunk-TULW7CRV.mjs} +4 -4
  56. package/dist/{chunk-6QWYIJLM.js → chunk-UHEZQR2Q.js} +1 -1
  57. package/dist/{chunk-7JIC2XBC.js → chunk-XSKWLJOQ.js} +4 -4
  58. package/dist/frontend/entrypoint.css +836 -0
  59. package/dist/frontend/entrypoint.css.map +7 -0
  60. package/dist/frontend/entrypoint.js +26049 -26682
  61. package/dist/frontend/entrypoint.js.map +4 -4
  62. package/dist/frontend/index.d.mts +4 -6
  63. package/dist/frontend/index.d.ts +4 -6
  64. package/dist/frontend/index.js +83 -300
  65. package/dist/frontend/index.mjs +90 -307
  66. package/dist/index.d.mts +1 -1
  67. package/dist/index.d.ts +1 -1
  68. package/dist/index.js +280 -98
  69. package/dist/index.mjs +250 -68
  70. package/dist/{toolkit-CohVRj6u.d.mts → toolkit-BPqxbDbk.d.mts} +82 -19
  71. package/dist/{toolkit-C_2Y8N9R.d.ts → toolkit-Bglbv3ix.d.ts} +82 -19
  72. package/package.json +15 -20
package/dist/index.js CHANGED
@@ -1,35 +1,35 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
2
2
 
3
3
 
4
- var _chunkU6FSQBQ3js = require('./chunk-U6FSQBQ3.js');
4
+ var _chunkA3RWE7HZjs = require('./chunk-A3RWE7HZ.js');
5
5
 
6
6
 
7
- var _chunkHTCWMJUAjs = require('./chunk-HTCWMJUA.js');
7
+ var _chunkIV3AE3CWjs = require('./chunk-IV3AE3CW.js');
8
8
 
9
9
 
10
- var _chunk6QWYIJLMjs = require('./chunk-6QWYIJLM.js');
10
+ var _chunkUHEZQR2Qjs = require('./chunk-UHEZQR2Q.js');
11
11
 
12
12
 
13
13
  var _chunkEABM5X65js = require('./chunk-EABM5X65.js');
14
14
 
15
15
 
16
- var _chunk4OCRZD4Fjs = require('./chunk-4OCRZD4F.js');
16
+ var _chunk4AGKM5NTjs = require('./chunk-4AGKM5NT.js');
17
17
 
18
18
 
19
19
 
20
- var _chunk7JIC2XBCjs = require('./chunk-7JIC2XBC.js');
20
+ var _chunkXSKWLJOQjs = require('./chunk-XSKWLJOQ.js');
21
21
 
22
22
 
23
- var _chunk3GTEUTFTjs = require('./chunk-3GTEUTFT.js');
23
+ var _chunkTF7N4O5Gjs = require('./chunk-TF7N4O5G.js');
24
24
 
25
25
 
26
- var _chunkQAH2OSHRjs = require('./chunk-QAH2OSHR.js');
26
+ var _chunk5B65Q7RLjs = require('./chunk-5B65Q7RL.js');
27
27
 
28
28
 
29
- var _chunkNL3W4M7Jjs = require('./chunk-NL3W4M7J.js');
29
+ var _chunkCVY55KARjs = require('./chunk-CVY55KAR.js');
30
30
 
31
31
 
32
- var _chunk53EOA4UEjs = require('./chunk-53EOA4UE.js');
32
+ var _chunk2K4UT5QBjs = require('./chunk-2K4UT5QB.js');
33
33
 
34
34
 
35
35
  var _chunkWN3GXVUEjs = require('./chunk-WN3GXVUE.js');
@@ -43,7 +43,8 @@ var _diff = require('@arcanejs/diff/diff');
43
43
 
44
44
  // src/backend/options.ts
45
45
  var DEFAULT_LIGHT_DESK_OPTIONS = {
46
- path: "/"
46
+ path: "/",
47
+ clockSync: false
47
48
  };
48
49
 
49
50
  // src/backend/server.ts
@@ -69,106 +70,251 @@ var distDir = () => {
69
70
  }
70
71
  };
71
72
  var Server = (_class = class {
72
- constructor(options, onNewConnection, onClosedConnection, onMessage, log) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
73
+ constructor(options, onNewConnection, onClosedConnection, onMessage, log) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);
73
74
  this.options = options;
74
75
  this.onNewConnection = onNewConnection;
75
76
  this.onClosedConnection = onClosedConnection;
76
77
  this.onMessage = onMessage;
77
78
  this.log = log;
79
+ this.title = _nullishCoalesce(options.title, () => ( "@arcanejs"));
80
+ }
81
+ __init() {this.staticFiles = null}
82
+ __init2() {this.htmlContext = null}
83
+ __init3() {this.staticFilesInitPromise = null}
84
+
85
+ __init4() {this.getEntrypointPaths = () => {
78
86
  const entrypoint = _nullishCoalesce(this.options.entrypointJsFile, () => ( path.join(distDir(), "frontend", "entrypoint.js")));
79
87
  if (!entrypoint.endsWith(".js")) {
80
88
  throw new Error("Entrypoint file must be a .js file");
81
89
  }
82
90
  const entrypointMap = entrypoint + ".map";
83
- this.entrypointFilename = path.basename(entrypoint);
84
- this.title = _escapehtml2.default.call(void 0, _nullishCoalesce(options.title, () => ( "@arcanejs")));
85
- this.staticFiles = {
86
- [`/${FONTS.materialSymbolsOutlined}`]: {
87
- path: _nullishCoalesce(this.options.materialIconsFontFile, () => ( _chunk3RG5ZIWIjs.__require.resolve("material-symbols/material-symbols-outlined.woff2"))),
88
- contentType: "font/woff2"
89
- },
90
- [`/${this.entrypointFilename}`]: {
91
- path: entrypoint,
92
- contentType: "text/javascript"
93
- },
94
- [`/${path.basename(entrypointMap)}`]: {
95
- path: entrypointMap,
96
- contentType: "text/plain"
97
- }
91
+ const entrypointCss = entrypoint.replace(/\.js$/, ".css");
92
+ const entrypointCssMap = entrypointCss + ".map";
93
+ return {
94
+ entrypoint,
95
+ entrypointMap,
96
+ entrypointCss,
97
+ entrypointCssMap,
98
+ entrypointFilename: path.basename(entrypoint),
99
+ entrypointMapFilename: path.basename(entrypointMap),
100
+ entrypointCssFilename: path.basename(entrypointCss),
101
+ entrypointCssMapFilename: path.basename(entrypointCssMap)
98
102
  };
99
- _optionalChain([log, 'optionalAccess', _14 => _14.debug, 'call', _15 => _15("Static Assets: %o", this.staticFiles)]);
100
- }
101
-
102
-
103
-
104
- __init() {this.handleHttpRequest = async (req, res) => {
105
- _optionalChain([this, 'access', _16 => _16.log, 'optionalAccess', _17 => _17.debug, 'call', _18 => _18("handleHttpRequest %s", req.url)]);
106
- if (req.url === this.options.path) {
107
- const content = `
103
+ }}
104
+ __init5() {this.fileExists = async (filePath) => {
105
+ try {
106
+ await fs.promises.access(filePath, fs.constants.F_OK);
107
+ return true;
108
+ } catch (e3) {
109
+ return false;
110
+ }
111
+ }}
112
+ __init6() {this.ensureStaticFilesInitialized = async () => {
113
+ if (this.staticFiles && this.htmlContext) return;
114
+ if (this.staticFilesInitPromise) return this.staticFilesInitPromise;
115
+ this.staticFilesInitPromise = (async () => {
116
+ const {
117
+ entrypoint,
118
+ entrypointMap,
119
+ entrypointCss,
120
+ entrypointCssMap,
121
+ entrypointFilename,
122
+ entrypointMapFilename,
123
+ entrypointCssFilename,
124
+ entrypointCssMapFilename
125
+ } = this.getEntrypointPaths();
126
+ const [hasEntrypointMap, hasEntrypointCss, hasEntrypointCssMap] = await Promise.all([
127
+ this.fileExists(entrypointMap),
128
+ this.fileExists(entrypointCss),
129
+ this.fileExists(entrypointCssMap)
130
+ ]);
131
+ const staticFilePaths = {
132
+ materialSymbolsOutlined: FONTS.materialSymbolsOutlined,
133
+ entrypointJs: entrypointFilename,
134
+ ...hasEntrypointMap ? { entrypointJsMap: entrypointMapFilename } : {},
135
+ ...hasEntrypointCss ? { entrypointCss: entrypointCssFilename } : {},
136
+ ...hasEntrypointCssMap ? { entrypointCssMap: entrypointCssMapFilename } : {}
137
+ };
138
+ const additionalFiles = _nullishCoalesce(this.options.additionalFiles, () => ( {}));
139
+ const additionalFileEntries = Object.entries(additionalFiles).map(
140
+ ([relativePath, loader]) => [
141
+ this.toRoutePath(relativePath),
142
+ async () => {
143
+ const asset = await loader();
144
+ if (!Buffer.isBuffer(asset.content)) {
145
+ throw new Error(
146
+ `Additional file "${relativePath}" did not return a Buffer in content`
147
+ );
148
+ }
149
+ return asset;
150
+ }
151
+ ]
152
+ );
153
+ this.staticFiles = {
154
+ [this.toRoutePath(staticFilePaths.materialSymbolsOutlined)]: async () => ({
155
+ content: await fs.promises.readFile(
156
+ _nullishCoalesce(this.options.materialIconsFontFile, () => ( _chunk3RG5ZIWIjs.__require.resolve(
157
+ "material-symbols/material-symbols-outlined.woff2"
158
+ )))
159
+ ),
160
+ contentType: "font/woff2"
161
+ }),
162
+ [this.toRoutePath(staticFilePaths.entrypointJs)]: async () => ({
163
+ content: await fs.promises.readFile(entrypoint),
164
+ contentType: "text/javascript"
165
+ }),
166
+ ...hasEntrypointMap ? {
167
+ [this.toRoutePath(entrypointMapFilename)]: async () => ({
168
+ content: await fs.promises.readFile(entrypointMap),
169
+ contentType: "text/plain"
170
+ })
171
+ } : {},
172
+ ...hasEntrypointCss ? {
173
+ [this.toRoutePath(entrypointCssFilename)]: async () => ({
174
+ content: await fs.promises.readFile(entrypointCss),
175
+ contentType: "text/css"
176
+ })
177
+ } : {},
178
+ ...hasEntrypointCssMap ? {
179
+ [this.toRoutePath(entrypointCssMapFilename)]: async () => ({
180
+ content: await fs.promises.readFile(entrypointCssMap),
181
+ contentType: "text/plain"
182
+ })
183
+ } : {},
184
+ ...Object.fromEntries(additionalFileEntries)
185
+ };
186
+ this.htmlContext = {
187
+ title: this.title,
188
+ path: this.options.path,
189
+ coreAssets: {
190
+ materialSymbolsOutlined: this.toSiteRelativeUrl(
191
+ staticFilePaths.materialSymbolsOutlined
192
+ ),
193
+ entrypointJs: this.toSiteRelativeUrl(staticFilePaths.entrypointJs),
194
+ entrypointJsMap: hasEntrypointMap ? this.toSiteRelativeUrl(entrypointMapFilename) : null,
195
+ entrypointCss: hasEntrypointCss ? this.toSiteRelativeUrl(entrypointCssFilename) : null,
196
+ entrypointCssMap: hasEntrypointCssMap ? this.toSiteRelativeUrl(entrypointCssMapFilename) : null
197
+ },
198
+ assetUrls: this.createAssetUrls(this.staticFiles)
199
+ };
200
+ _optionalChain([this, 'access', _26 => _26.log, 'optionalAccess', _27 => _27.debug, 'call', _28 => _28("Static Assets: %o", this.staticFiles)]);
201
+ })();
202
+ this.staticFilesInitPromise.catch(() => {
203
+ this.staticFilesInitPromise = null;
204
+ this.staticFiles = null;
205
+ this.htmlContext = null;
206
+ });
207
+ return this.staticFilesInitPromise;
208
+ }}
209
+ __init7() {this.handleHttpRequest = async (req, res) => {
210
+ try {
211
+ await this.ensureStaticFilesInitialized();
212
+ } catch (err) {
213
+ if (err instanceof Error) {
214
+ _optionalChain([this, 'access', _29 => _29.log, 'optionalAccess', _30 => _30.error, 'call', _31 => _31(err)]);
215
+ } else {
216
+ _optionalChain([this, 'access', _32 => _32.log, 'optionalAccess', _33 => _33.error, 'call', _34 => _34("Error preparing static files: %o", err)]);
217
+ }
218
+ res.writeHead(500, { "Content-Type": "text/plain" });
219
+ res.end("Unable to prepare static files", "utf-8");
220
+ return;
221
+ }
222
+ const htmlContext = this.htmlContext;
223
+ const staticFiles = this.staticFiles;
224
+ if (!htmlContext || !staticFiles) {
225
+ throw new Error("Static assets were not initialized");
226
+ }
227
+ const requestUrl = _nullishCoalesce(req.originalUrl, () => ( req.url));
228
+ _optionalChain([this, 'access', _35 => _35.log, 'optionalAccess', _36 => _36.debug, 'call', _37 => _37("handleHttpRequest %s", requestUrl)]);
229
+ const pathname = this.parsePathname(requestUrl);
230
+ if (pathname === this.options.path) {
231
+ const content = await _asyncNullishCoalesce(await _optionalChain([this, 'access', _38 => _38.options, 'access', _39 => _39.htmlPage, 'optionalCall', _40 => _40(htmlContext)]), async () => ( `
108
232
  <html>
109
233
  <head>
110
- <title>${this.title}</title>
234
+ <title>${_escapehtml2.default.call(void 0, htmlContext.title)}</title>
111
235
  <meta charset="utf-8">
112
236
  <meta name="viewport" content="width=device-width, initial-scale=1">
113
237
  <style type="text/css">
114
238
  @font-face {
115
239
  font-family: 'Material Symbols Outlined';
116
240
  font-style: normal;
117
- src: url(${FONTS.materialSymbolsOutlined}) format('woff');
241
+ src: url(${htmlContext.coreAssets.materialSymbolsOutlined}) format('woff');
118
242
  }
119
243
  </style>
244
+ ${htmlContext.coreAssets.entrypointCss ? `<link rel="stylesheet" href="${htmlContext.coreAssets.entrypointCss}" />` : ""}
120
245
  </head>
121
246
  <body>
122
247
  <div id="root"></div>
123
- <script type="text/javascript" src="${this.options.path}${this.entrypointFilename}"></script>
248
+ <script type="text/javascript" src="${htmlContext.coreAssets.entrypointJs}"></script>
124
249
  </body>
125
- </html>`;
250
+ </html>`));
126
251
  res.writeHead(200, { "Content-Type": "text/html" });
127
252
  res.end(content, "utf-8");
128
253
  return;
129
254
  }
130
- if (req.url && req.url.startsWith(this.options.path)) {
131
- const relativePath = req.url.substr(this.options.path.length - 1);
132
- const f = this.staticFiles[relativePath];
255
+ if (pathname && pathname.startsWith(this.options.path)) {
256
+ const relativePath = pathname.substr(this.options.path.length - 1);
257
+ const f = staticFiles[relativePath];
133
258
  if (f) {
134
- return fs.promises.stat(f.path).then(
135
- () => {
136
- this.sendStaticFile(f.path, res, f.contentType);
137
- },
138
- (err) => {
139
- _optionalChain([this, 'access', _19 => _19.log, 'optionalAccess', _20 => _20.error, 'call', _21 => _21(err)]);
140
- res.writeHead(500, { "Content-Type": "text/plain" });
141
- res.end("Expected static file not found", "utf-8");
259
+ try {
260
+ const response = await f();
261
+ res.writeHead(200, { "Content-Type": response.contentType });
262
+ res.end(response.content);
263
+ return;
264
+ } catch (err) {
265
+ if (err instanceof Error) {
266
+ _optionalChain([this, 'access', _41 => _41.log, 'optionalAccess', _42 => _42.error, 'call', _43 => _43(err)]);
267
+ } else {
268
+ _optionalChain([this, 'access', _44 => _44.log, 'optionalAccess', _45 => _45.error, 'call', _46 => _46("Error loading static file: %o", err)]);
142
269
  }
143
- );
270
+ res.writeHead(500, { "Content-Type": "text/plain" });
271
+ res.end("Expected static file not found", "utf-8");
272
+ return;
273
+ }
144
274
  }
145
275
  }
146
276
  res.writeHead(404, { "Content-Type": "text/plain" });
147
277
  res.end("not found", "utf-8");
148
278
  }}
149
- __init2() {this.sendStaticFile = (file, response, contentType) => {
150
- fs.readFile(file, (error, content) => {
151
- if (error) {
152
- if (error.code === "ENOENT") {
153
- response.writeHead(404, { "Content-Type": "text/plain" });
154
- response.end("file not found", "utf-8");
155
- } else {
156
- response.writeHead(500, { "Content-Type": "text/plain" });
157
- response.end("Error", "utf-8");
158
- _optionalChain([this, 'access', _22 => _22.log, 'optionalAccess', _23 => _23.error, 'call', _24 => _24(`Error reading static file: %s`, error)]);
159
- }
160
- } else {
161
- response.writeHead(200, { "Content-Type": contentType });
162
- response.end(content, "utf-8");
163
- }
164
- });
279
+ __init8() {this.parsePathname = (url) => {
280
+ if (!url) return "";
281
+ try {
282
+ return new URL(url, "http://127.0.0.1").pathname;
283
+ } catch (e4) {
284
+ return url;
285
+ }
286
+ }}
287
+ __init9() {this.toRoutePath = (relativePath) => {
288
+ if (!relativePath) {
289
+ throw new Error("Static file path must be non-empty");
290
+ }
291
+ if (relativePath.startsWith("/")) {
292
+ throw new Error(
293
+ `Static file path "${relativePath}" must be relative and not start with "/"`
294
+ );
295
+ }
296
+ return `/${relativePath}`;
297
+ }}
298
+ __init10() {this.toSiteRelativeUrl = (relativePath) => {
299
+ const normalizedPath = relativePath.replace(/^\/+/, "");
300
+ return `${this.options.path}${normalizedPath}`;
301
+ }}
302
+ __init11() {this.createAssetUrls = (staticFiles) => {
303
+ const urls = {};
304
+ for (const routePath of Object.keys(staticFiles)) {
305
+ const relativePath = routePath.replace(/^\/+/, "");
306
+ urls[relativePath] = this.toSiteRelativeUrl(
307
+ relativePath
308
+ );
309
+ }
310
+ return urls;
165
311
  }}
166
- __init3() {this.handleWsConnection = (ws) => {
312
+ __init12() {this.handleWsConnection = (ws) => {
167
313
  const connection = {
168
314
  sendMessage: (msg) => ws.send(JSON.stringify(msg))
169
315
  };
170
316
  this.onNewConnection(connection);
171
- _optionalChain([this, 'access', _25 => _25.log, 'optionalAccess', _26 => _26.debug, 'call', _27 => _27("new connection")]);
317
+ _optionalChain([this, 'access', _47 => _47.log, 'optionalAccess', _48 => _48.debug, 'call', _49 => _49("new connection")]);
172
318
  ws.on(
173
319
  "message",
174
320
  (msg) => this.onMessage(connection, JSON.parse(msg.toString()))
@@ -181,22 +327,38 @@ var Server = (_class = class {
181
327
  var _ws = require('ws');
182
328
  var _http = require('http');
183
329
  var _uuid = require('uuid');
330
+ var normalizeClockSyncOptions = (clockSync) => {
331
+ if (!clockSync) {
332
+ return null;
333
+ }
334
+ const { pingIntervalMs } = clockSync;
335
+ if (!Number.isFinite(pingIntervalMs) || pingIntervalMs <= 0) {
336
+ throw new Error(
337
+ `clockSync.pingIntervalMs must be a positive number, got: ${pingIntervalMs}`
338
+ );
339
+ }
340
+ return {
341
+ pingIntervalMs
342
+ };
343
+ };
184
344
  var Toolkit = (_class2 = class {
185
345
 
346
+
186
347
  /**
187
348
  * Mapping from components to unique IDs that identify them
188
349
  */
189
- __init4() {this.componentIDMap = new (0, _chunkEABM5X65js.IDMap)()}
190
- __init5() {this.connections = /* @__PURE__ */ new Map()}
191
- __init6() {this.rootGroup = null}
350
+ __init13() {this.componentIDMap = new (0, _chunkEABM5X65js.IDMap)()}
351
+ __init14() {this.connections = /* @__PURE__ */ new Map()}
352
+ __init15() {this.rootGroup = null}
192
353
  /** @hidden */
193
- __init7() {this.events = new (0, _chunkWN3GXVUEjs.EventEmitter)()}
354
+ __init16() {this.events = new (0, _chunkWN3GXVUEjs.EventEmitter)()}
194
355
 
195
- constructor(options = {}) {;_class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);_class2.prototype.__init12.call(this);_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);
356
+ constructor(options = {}) {;_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);_class2.prototype.__init20.call(this);_class2.prototype.__init21.call(this);_class2.prototype.__init22.call(this);_class2.prototype.__init23.call(this);_class2.prototype.__init24.call(this);_class2.prototype.__init25.call(this);_class2.prototype.__init26.call(this);_class2.prototype.__init27.call(this);_class2.prototype.__init28.call(this);
196
357
  this.options = {
197
358
  ...DEFAULT_LIGHT_DESK_OPTIONS,
198
359
  ...options
199
360
  };
361
+ this.clockSync = normalizeClockSyncOptions(this.options.clockSync);
200
362
  if (!this.options.path.endsWith("/") || !this.options.path.startsWith("/")) {
201
363
  throw new Error(
202
364
  `path must start and end with "/", set to: ${this.options.path}`
@@ -210,14 +372,14 @@ var Toolkit = (_class2 = class {
210
372
  this.options.log
211
373
  );
212
374
  }
213
- __init8() {this.addListener = this.events.addListener}
214
- __init9() {this.removeListener = this.events.removeListener}
215
- __init10() {this.start = (opts) => {
375
+ __init17() {this.addListener = this.events.addListener}
376
+ __init18() {this.removeListener = this.events.removeListener}
377
+ __init19() {this.start = (opts) => {
216
378
  if (opts.mode === "automatic") {
217
379
  this.listen({ port: opts.port }).then(() => {
218
380
  const url = `http://localhost:${opts.port}${this.options.path}`;
219
- _optionalChain([opts, 'access', _49 => _49.onReady, 'optionalCall', _50 => _50(url)]);
220
- _optionalChain([this, 'access', _51 => _51.options, 'access', _52 => _52.log, 'optionalAccess', _53 => _53.info, 'call', _54 => _54(`Light Desk Started: ${url}`)]);
381
+ _optionalChain([opts, 'access', _71 => _71.onReady, 'optionalCall', _72 => _72(url)]);
382
+ _optionalChain([this, 'access', _73 => _73.options, 'access', _74 => _74.log, 'optionalAccess', _75 => _75.info, 'call', _76 => _76(`Light Desk Started: ${url}`)]);
221
383
  });
222
384
  } else if (opts.mode === "express") {
223
385
  const wss = new (0, _ws.WebSocketServer)({
@@ -231,7 +393,7 @@ var Toolkit = (_class2 = class {
231
393
  throw new Error(`Unsupported mode`);
232
394
  }
233
395
  }}
234
- __init11() {this.listen = ({
396
+ __init20() {this.listen = ({
235
397
  port,
236
398
  host
237
399
  }) => {
@@ -266,7 +428,7 @@ var Toolkit = (_class2 = class {
266
428
  }
267
429
  });
268
430
  }}
269
- __init12() {this.setRoot = (group) => {
431
+ __init21() {this.setRoot = (group) => {
270
432
  if (this.rootGroup) {
271
433
  throw new Error("Can only set root group once");
272
434
  }
@@ -276,18 +438,22 @@ var Toolkit = (_class2 = class {
276
438
  log() {
277
439
  return _nullishCoalesce(this.options.log, () => ( null));
278
440
  }
279
- __init13() {this.getConnections = () => {
441
+ __init22() {this.getConnections = () => {
280
442
  return [...this.connections.values()].map((c) => c.publicConnection);
281
443
  }}
282
- __init14() {this.updateTree = _lodash2.default.throttle(
444
+ __init23() {this.updateTree = _lodash2.default.throttle(
283
445
  () => {
284
446
  setImmediate(() => {
285
447
  if (!this.rootGroup) return;
286
- const root = this.rootGroup.getProtoInfo(this.componentIDMap);
287
448
  for (const [connection, meta] of this.connections.entries()) {
449
+ const root = this.rootGroup.getProtoInfo(this.componentIDMap, {
450
+ connection: meta.publicConnection
451
+ });
452
+ const diff = _diff.diffJson.call(void 0, meta.lastTreeSent, root);
453
+ if (diff.type === "match") continue;
288
454
  connection.sendMessage({
289
455
  type: "tree-diff",
290
- diff: _diff.diffJson.call(void 0, meta.lastTreeSent, root)
456
+ diff
291
457
  });
292
458
  meta.lastTreeSent = root;
293
459
  }
@@ -296,25 +462,33 @@ var Toolkit = (_class2 = class {
296
462
  10,
297
463
  { leading: true, trailing: true }
298
464
  )}
299
- __init15() {this.removeChild = (component) => {
465
+ __init24() {this.removeChild = (component) => {
300
466
  if (this.rootGroup === component) {
301
467
  this.rootGroup = null;
302
468
  component.setParent(null);
303
469
  }
304
470
  }}
305
- __init16() {this.onNewConnection = (connection) => {
306
- const lastTreeSent = _nullishCoalesce(_optionalChain([this, 'access', _55 => _55.rootGroup, 'optionalAccess', _56 => _56.getProtoInfo, 'call', _57 => _57(this.componentIDMap)]), () => ( void 0));
471
+ __init25() {this.onNewConnection = (connection) => {
307
472
  const uuid = _uuid.v4.call(void 0, );
308
473
  const publicConnection = {
309
474
  get uuid() {
310
475
  return uuid;
311
476
  }
312
477
  };
313
- this.connections.set(connection, { publicConnection, lastTreeSent });
478
+ const lastTreeSent = _nullishCoalesce(_optionalChain([this, 'access', _77 => _77.rootGroup, 'optionalAccess', _78 => _78.getProtoInfo, 'call', _79 => _79(this.componentIDMap, {
479
+ connection: publicConnection
480
+ })]), () => ( void 0));
481
+ this.connections.set(connection, {
482
+ publicConnection,
483
+ lastTreeSent
484
+ });
314
485
  this.events.emit("new-connection", publicConnection);
315
486
  connection.sendMessage({
316
487
  type: "metadata",
317
- connectionUuid: uuid
488
+ connectionUuid: uuid,
489
+ clockSync: this.clockSync ? {
490
+ pingIntervalMs: this.clockSync.pingIntervalMs
491
+ } : null
318
492
  });
319
493
  if (lastTreeSent) {
320
494
  connection.sendMessage({
@@ -323,15 +497,15 @@ var Toolkit = (_class2 = class {
323
497
  });
324
498
  }
325
499
  }}
326
- __init17() {this.onClosedConnection = (connection) => {
327
- _optionalChain([this, 'access', _58 => _58.log, 'call', _59 => _59(), 'optionalAccess', _60 => _60.debug, 'call', _61 => _61("removing connection")]);
500
+ __init26() {this.onClosedConnection = (connection) => {
501
+ _optionalChain([this, 'access', _80 => _80.log, 'call', _81 => _81(), 'optionalAccess', _82 => _82.debug, 'call', _83 => _83("removing connection")]);
328
502
  const con = this.connections.get(connection);
329
503
  this.connections.delete(connection);
330
504
  if (con) {
331
505
  this.events.emit("closed-connection", con.publicConnection);
332
506
  }
333
507
  }}
334
- __init18() {this.handleCall = async (connection, publicConnection, call) => {
508
+ __init27() {this.handleCall = async (connection, publicConnection, call) => {
335
509
  try {
336
510
  const rg = this.rootGroup;
337
511
  if (rg) {
@@ -361,14 +535,14 @@ var Toolkit = (_class2 = class {
361
535
  });
362
536
  }
363
537
  }}
364
- __init19() {this.onMessage = (connection, message) => {
538
+ __init28() {this.onMessage = (connection, message) => {
365
539
  const con = this.connections.get(connection);
366
540
  if (!con) {
367
- _optionalChain([this, 'access', _62 => _62.log, 'call', _63 => _63(), 'optionalAccess', _64 => _64.warn, 'call', _65 => _65(`got message from unknown connection`)]);
541
+ _optionalChain([this, 'access', _84 => _84.log, 'call', _85 => _85(), 'optionalAccess', _86 => _86.warn, 'call', _87 => _87(`got message from unknown connection`)]);
368
542
  return;
369
543
  }
370
544
  const { publicConnection } = con;
371
- _optionalChain([this, 'access', _66 => _66.log, 'call', _67 => _67(), 'optionalAccess', _68 => _68.debug, 'call', _69 => _69(
545
+ _optionalChain([this, 'access', _88 => _88.log, 'call', _89 => _89(), 'optionalAccess', _90 => _90.debug, 'call', _91 => _91(
372
546
  "got message: %o from %s",
373
547
  message,
374
548
  publicConnection.uuid
@@ -385,6 +559,14 @@ var Toolkit = (_class2 = class {
385
559
  case "component-call":
386
560
  this.handleCall(connection, publicConnection, message);
387
561
  break;
562
+ case "ping": {
563
+ connection.sendMessage({
564
+ type: "pong",
565
+ pingId: message.pingId,
566
+ serverTimeMillis: Date.now()
567
+ });
568
+ break;
569
+ }
388
570
  }
389
571
  }}
390
572
  }, _class2);
@@ -401,4 +583,4 @@ var Toolkit = (_class2 = class {
401
583
 
402
584
 
403
585
 
404
- exports.Button = _chunk4OCRZD4Fjs.Button; exports.Group = _chunk7JIC2XBCjs.Group; exports.GroupHeader = _chunk7JIC2XBCjs.GroupHeader; exports.Label = _chunk3GTEUTFTjs.Label; exports.Rect = _chunkQAH2OSHRjs.Rect; exports.SliderButton = _chunkNL3W4M7Jjs.SliderButton; exports.Switch = _chunk53EOA4UEjs.Switch; exports.Tab = _chunkU6FSQBQ3js.Tab; exports.Tabs = _chunkU6FSQBQ3js.Tabs; exports.TextInput = _chunkHTCWMJUAjs.TextInput; exports.Timeline = _chunk6QWYIJLMjs.Timeline; exports.Toolkit = Toolkit;
586
+ exports.Button = _chunk4AGKM5NTjs.Button; exports.Group = _chunkXSKWLJOQjs.Group; exports.GroupHeader = _chunkXSKWLJOQjs.GroupHeader; exports.Label = _chunkTF7N4O5Gjs.Label; exports.Rect = _chunk5B65Q7RLjs.Rect; exports.SliderButton = _chunkCVY55KARjs.SliderButton; exports.Switch = _chunk2K4UT5QBjs.Switch; exports.Tab = _chunkA3RWE7HZjs.Tab; exports.Tabs = _chunkA3RWE7HZjs.Tabs; exports.TextInput = _chunkIV3AE3CWjs.TextInput; exports.Timeline = _chunkUHEZQR2Qjs.Timeline; exports.Toolkit = Toolkit;