@arcanejs/toolkit 6.0.1 → 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 +26048 -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 +82 -300
  65. package/dist/frontend/index.mjs +89 -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
@@ -12,22 +12,58 @@ import { I as IDMap } from './id-map-DxQ3_gyA.js';
12
12
  interface Connection {
13
13
  sendMessage(msg: ServerMessage): void;
14
14
  }
15
- declare class Server {
15
+ declare class Server<TAdditionalFiles extends ToolkitAdditionalFiles = Record<never, never>> {
16
16
  private readonly options;
17
17
  private readonly onNewConnection;
18
18
  private readonly onClosedConnection;
19
19
  private readonly onMessage;
20
20
  private readonly log?;
21
- private readonly staticFiles;
22
- private readonly entrypointFilename;
23
- private title;
24
- constructor(options: ToolkitOptions, onNewConnection: (connection: Connection) => void, onClosedConnection: (connection: Connection) => void, onMessage: (connection: Connection, message: ClientMessage) => void, log?: Logger | undefined);
21
+ private staticFiles;
22
+ private htmlContext;
23
+ private staticFilesInitPromise;
24
+ private readonly title;
25
+ constructor(options: ToolkitOptions<TAdditionalFiles>, onNewConnection: (connection: Connection) => void, onClosedConnection: (connection: Connection) => void, onMessage: (connection: Connection, message: ClientMessage) => void, log?: Logger | undefined);
26
+ private getEntrypointPaths;
27
+ private fileExists;
28
+ private ensureStaticFilesInitialized;
25
29
  handleHttpRequest: (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
26
- private sendStaticFile;
30
+ private parsePathname;
31
+ private toRoutePath;
32
+ private toSiteRelativeUrl;
33
+ private createAssetUrls;
27
34
  handleWsConnection: <S extends WebSocket>(ws: S) => void;
28
35
  }
29
36
 
30
- interface ToolkitOptions {
37
+ declare const FONTS: {
38
+ readonly materialSymbolsOutlined: "material-symbols-outlined.woff2";
39
+ };
40
+
41
+ type ToolkitStaticFile = {
42
+ contentType: string;
43
+ content: Buffer;
44
+ };
45
+ type ToolkitStaticFileResolver = () => Promise<ToolkitStaticFile>;
46
+ type ToolkitAdditionalFiles = Record<string, ToolkitStaticFileResolver>;
47
+ type ToolkitCoreAssetRelativePath = typeof FONTS.materialSymbolsOutlined | `${string}.js` | `${string}.js.map` | `${string}.css` | `${string}.css.map`;
48
+ type ToolkitHtmlPageContext<TAdditionalFiles extends ToolkitAdditionalFiles> = {
49
+ title: string;
50
+ path: string;
51
+ coreAssets: {
52
+ materialSymbolsOutlined: string;
53
+ entrypointJs: string;
54
+ entrypointJsMap: string | null;
55
+ entrypointCss: string | null;
56
+ entrypointCssMap: string | null;
57
+ };
58
+ assetUrls: Record<ToolkitCoreAssetRelativePath | Extract<keyof TAdditionalFiles, string>, string>;
59
+ };
60
+ type ToolkitClockSyncOptions = {
61
+ /**
62
+ * How often the browser should request a ping in milliseconds.
63
+ */
64
+ pingIntervalMs: number;
65
+ };
66
+ interface ToolkitOptions<TAdditionalFiles extends ToolkitAdditionalFiles = Record<never, never>> {
31
67
  /**
32
68
  * What window title should the toolkit be initialized with?
33
69
  */
@@ -53,8 +89,10 @@ interface ToolkitOptions {
53
89
  * This is only needed if you have defined custom extensions,
54
90
  * and need to load custom frontend code that includes your extensions.
55
91
  *
56
- * This will allow access to both the js file and the `.map.js` file,
57
- * that matches this name.
92
+ * ArcaneJS expects an associated `.css` file with the same basename
93
+ * (for example `entrypoint.js` + `entrypoint.css`) so browser styles are
94
+ * served automatically. Source map files (`.js.map`, `.css.map`) are optional,
95
+ * and exposed when present.
58
96
  */
59
97
  entrypointJsFile?: string;
60
98
  /**
@@ -64,8 +102,29 @@ interface ToolkitOptions {
64
102
  * you can provide the path to the material-symbols-outlined.woff2 file here.
65
103
  */
66
104
  materialIconsFontFile?: string;
105
+ /**
106
+ * Additional static assets that should be exposed from the toolkit path.
107
+ *
108
+ * The object key is the relative request path (for example `styles/app.css`),
109
+ * and the loader returns the response payload and content type.
110
+ */
111
+ additionalFiles?: TAdditionalFiles;
112
+ /**
113
+ * Optional custom HTML renderer for the root page.
114
+ *
115
+ * Receives resolved site-relative URLs for all available static assets,
116
+ * including toolkit defaults and files provided by `additionalFiles`.
117
+ */
118
+ htmlPage?: (context: ToolkitHtmlPageContext<TAdditionalFiles>) => string | Promise<string>;
119
+ /**
120
+ * Enable browser/server clock synchronization support.
121
+ *
122
+ * When enabled, frontend clients will periodically ping the toolkit server
123
+ * and expose a calculated server clock offset in stage context.
124
+ */
125
+ clockSync?: false | ToolkitClockSyncOptions;
67
126
  }
68
- type InitializationOptions =
127
+ type InitializationOptions<TAdditionalFiles extends ToolkitAdditionalFiles = Record<never, never>> =
69
128
  /** automatically start a simple */
70
129
  {
71
130
  mode: 'automatic';
@@ -85,7 +144,7 @@ type InitializationOptions =
85
144
  /** Create a websocket server that attaches to an existing express and http server */
86
145
  | {
87
146
  mode: 'manual';
88
- setup: (server: Server) => void;
147
+ setup: (server: Server<TAdditionalFiles>) => void;
89
148
  };
90
149
 
91
150
  declare abstract class Base<Namespace extends string, Proto extends BaseComponentProto<Namespace, string>, Props, CallPairs = any, CallActions extends string & keyof CallPairs = any> {
@@ -114,7 +173,7 @@ declare abstract class Base<Namespace extends string, Proto extends BaseComponen
114
173
  /** @hidden */
115
174
  updateTree(): void;
116
175
  /** @hidden */
117
- abstract getProtoInfo(idMap: IDMap): Proto;
176
+ abstract getProtoInfo(idMap: IDMap, context: ToolkitRenderContext): Proto;
118
177
  /** @hidden */
119
178
  handleMessage(_message: AnyClientComponentMessage, _connection: ToolkitConnection): void;
120
179
  /** @hidden */
@@ -199,7 +258,7 @@ declare class Button extends Base<proto.CoreNamespace, proto.ButtonComponent, In
199
258
  setIcon: (icon: string | undefined | null) => this;
200
259
  setMode: (mode: ButtonMode) => this;
201
260
  /** @hidden */
202
- getProtoInfo: (idMap: IDMap) => proto.ButtonComponent;
261
+ getProtoInfo: (idMap: IDMap, _context: ToolkitRenderContext) => proto.ButtonComponent;
203
262
  /** @hidden */
204
263
  handleCall: (call: AnyClientComponentCall, connection: ToolkitConnection) => Promise<true>;
205
264
  }
@@ -221,7 +280,7 @@ type Props = Partial<InternalProps>;
221
280
  declare class GroupHeader extends BaseParent<proto.CoreNamespace, proto.CoreComponent, Record<never, never>> {
222
281
  validateChildren: () => void;
223
282
  /** @hidden */
224
- getProtoInfo: (idMap: IDMap) => proto.GroupHeaderComponent;
283
+ getProtoInfo: (idMap: IDMap, context: ToolkitRenderContext) => proto.GroupHeaderComponent;
225
284
  }
226
285
  /**
227
286
  * A collection of components, grouped in either a row or column. Can contain
@@ -245,7 +304,7 @@ declare class Group extends BaseParent<proto.CoreNamespace, proto.GroupComponent
245
304
  removeHeaderChild: (child: Button) => void;
246
305
  removeAllHeaderChildren: () => void;
247
306
  /** @hidden */
248
- getProtoInfo: (idMap: IDMap) => proto.GroupComponent;
307
+ getProtoInfo: (idMap: IDMap, context: ToolkitRenderContext) => proto.GroupComponent;
249
308
  /** @hidden */
250
309
  handleMessage: (message: AnyClientComponentMessage, connection: ToolkitConnection) => void;
251
310
  }
@@ -253,6 +312,9 @@ declare class Group extends BaseParent<proto.CoreNamespace, proto.GroupComponent
253
312
  type ToolkitConnection = {
254
313
  uuid: string;
255
314
  };
315
+ type ToolkitRenderContext = {
316
+ connection: ToolkitConnection;
317
+ };
256
318
  type Events = {
257
319
  'new-connection': (connection: ToolkitConnection) => void;
258
320
  'closed-connection': (connection: ToolkitConnection) => void;
@@ -264,8 +326,9 @@ type ToolkitServerListenerOptions = {
264
326
  type ToolkitServerListener = {
265
327
  close: () => void;
266
328
  };
267
- declare class Toolkit implements Parent, Listenable<Events> {
329
+ declare class Toolkit<TAdditionalFiles extends ToolkitAdditionalFiles = Record<never, never>> implements Parent, Listenable<Events> {
268
330
  private readonly options;
331
+ private readonly clockSync;
269
332
  /**
270
333
  * Mapping from components to unique IDs that identify them
271
334
  */
@@ -275,10 +338,10 @@ declare class Toolkit implements Parent, Listenable<Events> {
275
338
  /** @hidden */
276
339
  private readonly events;
277
340
  private readonly server;
278
- constructor(options?: Partial<ToolkitOptions>);
341
+ constructor(options?: Partial<ToolkitOptions<TAdditionalFiles>>);
279
342
  addListener: <T extends keyof Events>(type: T, listener: Events[T]) => void;
280
343
  removeListener: <T extends keyof Events>(type: T, listener: Events[T]) => void;
281
- start: (opts: InitializationOptions) => void;
344
+ start: (opts: InitializationOptions<TAdditionalFiles>) => void;
282
345
  listen: ({ port, host, }: ToolkitServerListenerOptions) => Promise<ToolkitServerListener>;
283
346
  setRoot: (group: Group) => void;
284
347
  log(): _arcanejs_protocol_logging.Logger | null;
@@ -291,4 +354,4 @@ declare class Toolkit implements Parent, Listenable<Events> {
291
354
  private onMessage;
292
355
  }
293
356
 
294
- export { type AnyComponent as A, Button as B, EventEmitter as E, Group as G, type InternalProps$1 as I, type Listenable as L, type Parent as P, Toolkit as T, type ToolkitConnection as a, type ToolkitServerListenerOptions as b, type ToolkitServerListener as c, type ToolkitOptions as d, GroupHeader as e, Base as f, BaseParent as g, type Events$2 as h, type ButtonMode as i, type Props$1 as j, type Events$1 as k, type InternalProps as l, type Props as m };
357
+ export { type AnyComponent as A, Button as B, EventEmitter as E, Group as G, type InternalProps$1 as I, type Listenable as L, type Parent as P, Toolkit as T, type ToolkitConnection as a, type ToolkitRenderContext as b, type ToolkitServerListenerOptions as c, type ToolkitServerListener as d, type ToolkitAdditionalFiles as e, type ToolkitClockSyncOptions as f, type ToolkitCoreAssetRelativePath as g, type ToolkitHtmlPageContext as h, type ToolkitOptions as i, type ToolkitStaticFile as j, type ToolkitStaticFileResolver as k, GroupHeader as l, Base as m, BaseParent as n, type Events$2 as o, type ButtonMode as p, type Props$1 as q, type Events$1 as r, type InternalProps as s, type Props as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcanejs/toolkit",
3
- "version": "6.0.1",
3
+ "version": "7.0.0",
4
4
  "private": false,
5
5
  "description": "Build web-accessible control interfaces for your long-running Node.js processes",
6
6
  "keywords": [
@@ -103,36 +103,34 @@
103
103
  "@types/express": "^5.0.0",
104
104
  "@types/lodash": "^4.17.10",
105
105
  "@types/node": "^20.11.24",
106
- "@types/react": "^18",
107
- "@types/react-dom": "^18",
106
+ "@types/react": "^19.2.2",
107
+ "@types/react-dom": "^19.2.2",
108
108
  "@types/ws": "^8.5.12",
109
109
  "check-export-map": "^1.3.1",
110
- "esbuild": "^0.24.0",
111
110
  "eslint": "^8.57.0",
112
- "react": "^18",
113
- "react-dom": "18.3.1",
114
- "styled-components": "^6.1.13",
111
+ "react": "^19.2.0",
112
+ "react-dom": "^19.2.0",
115
113
  "tsup": "^8.1.0",
116
114
  "typescript": "^5.3.3",
117
115
  "@arcanejs/eslint-config": "^0.0.0",
118
- "@arcanejs/toolkit-frontend": "^0.9.0",
119
- "@arcanejs/typescript-config": "^0.0.0"
116
+ "@arcanejs/toolkit-frontend": "^0.10.0",
117
+ "@arcanejs/typescript-config": "^0.0.0",
118
+ "@arcanejs/build-utils": "^0.1.1"
120
119
  },
121
120
  "dependencies": {
122
121
  "escape-html": "^1.0.3",
123
122
  "express": "^4.21.1",
124
- "lodash": "^4.17.21",
123
+ "lodash": "^4.17.23",
125
124
  "material-symbols": "^0.25.0",
126
125
  "uuid": "^11.0.3",
127
126
  "ws": "^8.18.0",
128
- "@arcanejs/diff": "^0.5.1",
129
- "@arcanejs/protocol": "^0.7.0"
127
+ "@arcanejs/diff": "^0.5.2",
128
+ "@arcanejs/protocol": "^0.8.0"
130
129
  },
131
130
  "peerDependencies": {
132
- "react": "^18",
133
- "react-dom": "18.3.1",
134
- "styled-components": "^6.1.13",
135
- "@arcanejs/toolkit-frontend": "^0.9.0"
131
+ "react": "^19.2.0",
132
+ "react-dom": "^19.2.0",
133
+ "@arcanejs/toolkit-frontend": "^0.10.0"
136
134
  },
137
135
  "peerDependenciesMeta": {
138
136
  "@arcanejs/toolkit-frontend": {
@@ -143,9 +141,6 @@
143
141
  },
144
142
  "react-dom": {
145
143
  "optional": true
146
- },
147
- "styled-components": {
148
- "optional": true
149
144
  }
150
145
  },
151
146
  "files": [
@@ -158,7 +153,7 @@
158
153
  "lint": "eslint . --max-warnings 0",
159
154
  "build": "rm -rf dist && pnpm build:backend && pnpm type-check:frontend && pnpm build:frontend && check-export-map",
160
155
  "build:backend": "tsup",
161
- "build:frontend": "esbuild src/frontend/entrypoint-core.ts --bundle --sourcemap --outfile=dist/frontend/entrypoint.js",
156
+ "build:frontend": "arcane-build-frontend --entry src/frontend/entrypoint-core.ts --outfile dist/frontend/entrypoint.js --sourcemap --condition @arcanejs/source",
162
157
  "dev": "pnpm dev:backend & pnpm dev:frontend",
163
158
  "dev:backend": "pnpm build:backend --watch",
164
159
  "dev:frontend": "pnpm type-check:frontend:watch & pnpm build:frontend --watch",