@arcanejs/toolkit 0.0.2 → 0.1.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 (59) hide show
  1. package/dist/backend/components/base.d.mts +2 -0
  2. package/dist/backend/components/base.d.ts +2 -0
  3. package/dist/backend/components/base.js +189 -0
  4. package/dist/backend/components/base.mjs +10 -0
  5. package/dist/backend/components/button.d.mts +30 -0
  6. package/dist/backend/components/button.d.ts +30 -0
  7. package/dist/backend/components/button.js +168 -0
  8. package/dist/backend/components/button.mjs +7 -0
  9. package/dist/backend/components/group.d.mts +51 -0
  10. package/dist/backend/components/group.d.ts +51 -0
  11. package/dist/backend/components/group.js +287 -0
  12. package/dist/backend/components/group.mjs +9 -0
  13. package/dist/backend/components/label.d.mts +21 -0
  14. package/dist/backend/components/label.d.ts +21 -0
  15. package/dist/backend/components/label.js +105 -0
  16. package/dist/backend/components/label.mjs +7 -0
  17. package/dist/backend/components/rect.d.mts +20 -0
  18. package/dist/backend/components/rect.d.ts +20 -0
  19. package/dist/backend/components/rect.js +105 -0
  20. package/dist/backend/components/rect.mjs +7 -0
  21. package/dist/backend/components/slider-button.d.mts +31 -0
  22. package/dist/backend/components/slider-button.d.ts +31 -0
  23. package/dist/backend/components/slider-button.js +161 -0
  24. package/dist/backend/components/slider-button.mjs +7 -0
  25. package/dist/backend/components/switch.d.mts +24 -0
  26. package/dist/backend/components/switch.d.ts +24 -0
  27. package/dist/backend/components/switch.js +144 -0
  28. package/dist/backend/components/switch.mjs +7 -0
  29. package/dist/backend/components/tabs.d.mts +28 -0
  30. package/dist/backend/components/tabs.d.ts +28 -0
  31. package/dist/backend/components/tabs.js +209 -0
  32. package/dist/backend/components/tabs.mjs +9 -0
  33. package/dist/backend/components/text-input.d.mts +26 -0
  34. package/dist/backend/components/text-input.d.ts +26 -0
  35. package/dist/backend/components/text-input.js +146 -0
  36. package/dist/backend/components/text-input.mjs +7 -0
  37. package/dist/backend/components/timeline.d.mts +17 -0
  38. package/dist/backend/components/timeline.d.ts +17 -0
  39. package/dist/backend/components/timeline.js +109 -0
  40. package/dist/backend/components/timeline.mjs +7 -0
  41. package/dist/base-BJAPu0O1.d.mts +234 -0
  42. package/dist/base-BJAPu0O1.d.ts +234 -0
  43. package/dist/chunk-37VNFO5S.mjs +42 -0
  44. package/dist/chunk-3ZBM7Q4A.mjs +55 -0
  45. package/dist/chunk-6LL3X7ZZ.mjs +44 -0
  46. package/dist/chunk-DBW4OPGN.mjs +33 -0
  47. package/dist/chunk-DP3QFYSS.mjs +66 -0
  48. package/dist/chunk-GQZA5K4M.mjs +29 -0
  49. package/dist/chunk-HF77PS7J.mjs +171 -0
  50. package/dist/chunk-HVFTRNLQ.mjs +59 -0
  51. package/dist/chunk-P6X5GIDT.mjs +29 -0
  52. package/dist/chunk-S5DQIYC2.mjs +107 -0
  53. package/dist/frontend.js +26321 -0
  54. package/dist/frontend.js.map +7 -0
  55. package/dist/index.d.mts +75 -1
  56. package/dist/index.d.ts +75 -1
  57. package/dist/index.js +852 -1
  58. package/dist/index.mjs +288 -2
  59. package/package.json +86 -6
package/dist/index.mjs CHANGED
@@ -1,2 +1,288 @@
1
- // src/index.ts
2
- console.log("hello world");
1
+ import {
2
+ Tab,
3
+ Tabs
4
+ } from "./chunk-3ZBM7Q4A.mjs";
5
+ import {
6
+ TextInput
7
+ } from "./chunk-6LL3X7ZZ.mjs";
8
+ import {
9
+ Timeline
10
+ } from "./chunk-DBW4OPGN.mjs";
11
+ import {
12
+ Button
13
+ } from "./chunk-DP3QFYSS.mjs";
14
+ import {
15
+ Group,
16
+ GroupHeader
17
+ } from "./chunk-S5DQIYC2.mjs";
18
+ import {
19
+ Label
20
+ } from "./chunk-P6X5GIDT.mjs";
21
+ import {
22
+ Rect
23
+ } from "./chunk-GQZA5K4M.mjs";
24
+ import {
25
+ SliderButton
26
+ } from "./chunk-HVFTRNLQ.mjs";
27
+ import {
28
+ Switch
29
+ } from "./chunk-37VNFO5S.mjs";
30
+ import {
31
+ __require
32
+ } from "./chunk-HF77PS7J.mjs";
33
+
34
+ // src/backend/toolkit.ts
35
+ import _ from "lodash";
36
+ import { diffJson } from "@arcanejs/diff/diff";
37
+
38
+ // src/backend/options.ts
39
+ var DEFAULT_LIGHT_DESK_OPTIONS = {
40
+ path: "/"
41
+ };
42
+
43
+ // src/backend/server.ts
44
+ import * as fs from "fs";
45
+ import * as path from "path";
46
+
47
+ // src/shared/static.ts
48
+ var FONTS = {
49
+ materialSymbolsOutlined: "material-symbols-outlined.woff2"
50
+ };
51
+
52
+ // src/backend/server.ts
53
+ var parentDir = path.basename(__dirname);
54
+ var DIST_DIR = (() => {
55
+ switch (parentDir) {
56
+ case "backend":
57
+ return path.resolve(__dirname, "../../dist");
58
+ case "dist":
59
+ return __dirname;
60
+ default:
61
+ throw new Error(`Server running from unknown location: ${__dirname}`);
62
+ }
63
+ })();
64
+ var STATIC_FILES = {
65
+ "/frontend.js": {
66
+ path: path.join(DIST_DIR, "frontend.js"),
67
+ contentType: "text/javascript"
68
+ },
69
+ "/frontend.js.map": {
70
+ path: path.join(DIST_DIR, "frontend.js.map"),
71
+ contentType: "text/plain"
72
+ },
73
+ [`/${FONTS.materialSymbolsOutlined}`]: {
74
+ path: __require.resolve("material-symbols/material-symbols-outlined.woff2"),
75
+ contentType: "font/woff2"
76
+ }
77
+ };
78
+ console.log("STATIC_FILES", STATIC_FILES);
79
+ var Server = class {
80
+ constructor(options, onNewConnection, onClosedConnection, onMessage) {
81
+ this.options = options;
82
+ this.onNewConnection = onNewConnection;
83
+ this.onClosedConnection = onClosedConnection;
84
+ this.onMessage = onMessage;
85
+ }
86
+ handleHttpRequest = async (req, res) => {
87
+ console.log("handleHttpRequest", req.url);
88
+ if (req.url === this.options.path) {
89
+ const content = `
90
+ <html>
91
+ <head>
92
+ <title>Light Desk</title>
93
+ <meta name="viewport" content="width=device-width, initial-scale=1">
94
+ </head>
95
+ <body>
96
+ <div id="root"></div>
97
+ <script type="text/javascript" src="${this.options.path}frontend.js"></script>
98
+ </body>
99
+ </html>`;
100
+ res.writeHead(200, { "Content-Type": "text/html" });
101
+ res.end(content, "utf-8");
102
+ return;
103
+ }
104
+ if (req.url && req.url.startsWith(this.options.path)) {
105
+ const relativePath = req.url.substr(this.options.path.length - 1);
106
+ const f = STATIC_FILES[relativePath];
107
+ if (f) {
108
+ return fs.promises.stat(f.path).then(
109
+ () => {
110
+ this.sendStaticFile(f.path, res, f.contentType);
111
+ },
112
+ (err) => {
113
+ console.error(err);
114
+ res.writeHead(500, { "Content-Type": "text/plain" });
115
+ res.end("Expected static file not found", "utf-8");
116
+ }
117
+ );
118
+ }
119
+ }
120
+ res.writeHead(404, { "Content-Type": "text/plain" });
121
+ res.end("not found", "utf-8");
122
+ };
123
+ sendStaticFile = (file, response, contentType) => {
124
+ fs.readFile(file, function(error, content) {
125
+ if (error) {
126
+ if (error.code === "ENOENT") {
127
+ response.writeHead(404, { "Content-Type": "text/plain" });
128
+ response.end("file not found", "utf-8");
129
+ } else {
130
+ response.writeHead(500, { "Content-Type": "text/plain" });
131
+ response.end("Error", "utf-8");
132
+ console.error(error);
133
+ }
134
+ } else {
135
+ response.writeHead(200, { "Content-Type": contentType });
136
+ response.end(content, "utf-8");
137
+ }
138
+ });
139
+ };
140
+ handleWsConnection = (ws) => {
141
+ const connection = {
142
+ sendMessage: (msg) => ws.send(JSON.stringify(msg))
143
+ };
144
+ this.onNewConnection(connection);
145
+ console.log("new connection");
146
+ ws.on(
147
+ "message",
148
+ (msg) => this.onMessage(connection, JSON.parse(msg.toString()))
149
+ );
150
+ ws.on("close", () => this.onClosedConnection(connection));
151
+ };
152
+ };
153
+
154
+ // src/backend/util/id-map.ts
155
+ var IDMap = class {
156
+ idMap = /* @__PURE__ */ new WeakMap();
157
+ nextId = 0;
158
+ getId(object) {
159
+ let i = this.idMap.get(object);
160
+ if (i === void 0) {
161
+ i = this.nextId++;
162
+ this.idMap.set(object, i);
163
+ }
164
+ return i;
165
+ }
166
+ };
167
+
168
+ // src/backend/toolkit.ts
169
+ import { WebSocketServer } from "ws";
170
+ import { createServer } from "http";
171
+ console.log(diffJson);
172
+ var Toolkit = class {
173
+ options;
174
+ /**
175
+ * Mapping from components to unique IDs that identify them
176
+ */
177
+ componentIDMap = new IDMap();
178
+ connections = /* @__PURE__ */ new Map();
179
+ rootGroup = null;
180
+ constructor(options = {}) {
181
+ this.options = {
182
+ ...DEFAULT_LIGHT_DESK_OPTIONS,
183
+ ...options
184
+ };
185
+ if (!this.options.path.endsWith("/") || !this.options.path.startsWith("/")) {
186
+ throw new Error(
187
+ `path must start and end with "/", set to: ${this.options.path}`
188
+ );
189
+ }
190
+ }
191
+ start = (opts) => {
192
+ const server = new Server(
193
+ this.options,
194
+ this.onNewConnection,
195
+ this.onClosedConnection,
196
+ this.onMessage
197
+ );
198
+ if (opts.mode === "automatic") {
199
+ const httpServer = createServer(server.handleHttpRequest);
200
+ const wss = new WebSocketServer({
201
+ server: httpServer
202
+ });
203
+ wss.on("connection", server.handleWsConnection);
204
+ httpServer.listen(opts.port, () => {
205
+ console.log(
206
+ `Light Desk Started: http://localhost:${opts.port}${this.options.path}`
207
+ );
208
+ });
209
+ } else if (opts.mode === "express") {
210
+ const wss = new WebSocketServer({
211
+ server: opts.server
212
+ });
213
+ wss.on("connection", server.handleWsConnection);
214
+ opts.express.get(`${this.options.path}*`, server.handleHttpRequest);
215
+ } else if (opts.mode === "manual") {
216
+ opts.setup(server);
217
+ } else {
218
+ throw new Error(`Unsupported mode`);
219
+ }
220
+ };
221
+ setRoot = (group) => {
222
+ if (this.rootGroup) {
223
+ throw new Error("Can only set root group once");
224
+ }
225
+ this.rootGroup = group;
226
+ this.rootGroup.setParent(this);
227
+ };
228
+ updateTree = _.throttle(
229
+ () => {
230
+ setImmediate(() => {
231
+ if (!this.rootGroup) return;
232
+ const root = this.rootGroup.getProtoInfo(this.componentIDMap);
233
+ for (const [connection, meta] of this.connections.entries()) {
234
+ connection.sendMessage({
235
+ type: "tree-diff",
236
+ diff: diffJson(meta.lastTreeSent, root)
237
+ });
238
+ meta.lastTreeSent = root;
239
+ }
240
+ });
241
+ },
242
+ 10,
243
+ { leading: true, trailing: true }
244
+ );
245
+ removeChild = (component) => {
246
+ if (this.rootGroup === component) {
247
+ this.rootGroup = null;
248
+ component.setParent(null);
249
+ }
250
+ };
251
+ onNewConnection = (connection) => {
252
+ const lastTreeSent = this.rootGroup?.getProtoInfo(this.componentIDMap) ?? void 0;
253
+ this.connections.set(connection, { lastTreeSent });
254
+ if (lastTreeSent) {
255
+ connection.sendMessage({
256
+ type: "tree-full",
257
+ root: lastTreeSent
258
+ });
259
+ }
260
+ };
261
+ onClosedConnection = (connection) => {
262
+ console.log("removing connection");
263
+ this.connections.delete(connection);
264
+ };
265
+ onMessage = (_connection, message) => {
266
+ console.log("got message", message);
267
+ switch (message.type) {
268
+ case "component-message":
269
+ if (this.rootGroup)
270
+ this.rootGroup.routeMessage(this.componentIDMap, message);
271
+ break;
272
+ }
273
+ };
274
+ };
275
+ export {
276
+ Button,
277
+ Group,
278
+ GroupHeader,
279
+ Label,
280
+ Rect,
281
+ SliderButton,
282
+ Switch,
283
+ Tab,
284
+ Tabs,
285
+ TextInput,
286
+ Timeline,
287
+ Toolkit
288
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcanejs/toolkit",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "private": false,
5
5
  "description": "Build web-accessible control interfaces for your long-running Node.js processes",
6
6
  "keywords": [
@@ -18,22 +18,96 @@
18
18
  },
19
19
  "exports": {
20
20
  ".": {
21
+ "@arcanejs/source": "./src/index.ts",
21
22
  "import": "./dist/index.mjs",
22
23
  "require": "./dist/index.js",
23
24
  "types": "./dist/index.d.ts"
25
+ },
26
+ "./components/base": {
27
+ "@arcanejs/source": "./src/backend/components/base.ts",
28
+ "import": "./dist/backend/components/base.mjs",
29
+ "require": "./dist/backend/components/base.js",
30
+ "types": "./dist/backend/components/base.d.ts"
31
+ },
32
+ "./components/button": {
33
+ "@arcanejs/source": "./src/backend/components/button.ts",
34
+ "import": "./dist/backend/components/button.mjs",
35
+ "require": "./dist/backend/components/button.js",
36
+ "types": "./dist/backend/components/button.d.ts"
37
+ },
38
+ "./components/group": {
39
+ "@arcanejs/source": "./src/backend/components/group.ts",
40
+ "import": "./dist/backend/components/group.mjs",
41
+ "require": "./dist/backend/components/group.js",
42
+ "types": "./dist/backend/components/group.d.ts"
43
+ },
44
+ "./components/label": {
45
+ "@arcanejs/source": "./src/backend/components/label.ts",
46
+ "import": "./dist/backend/components/label.mjs",
47
+ "require": "./dist/backend/components/label.js",
48
+ "types": "./dist/backend/components/label.d.ts"
49
+ },
50
+ "./components/rect": {
51
+ "@arcanejs/source": "./src/backend/components/rect.ts",
52
+ "import": "./dist/backend/components/rect.mjs",
53
+ "require": "./dist/backend/components/rect.js",
54
+ "types": "./dist/backend/components/rect.d.ts"
55
+ },
56
+ "./components/slider-button": {
57
+ "@arcanejs/source": "./src/backend/components/slider-button.ts",
58
+ "import": "./dist/backend/components/slider-button.mjs",
59
+ "require": "./dist/backend/components/slider-button.js",
60
+ "types": "./dist/backend/components/slider-button.d.ts"
61
+ },
62
+ "./components/switch": {
63
+ "@arcanejs/source": "./src/backend/components/switch.ts",
64
+ "import": "./dist/backend/components/switch.mjs",
65
+ "require": "./dist/backend/components/switch.js",
66
+ "types": "./dist/backend/components/switch.d.ts"
67
+ },
68
+ "./components/tabs": {
69
+ "@arcanejs/source": "./src/backend/components/tabs.ts",
70
+ "import": "./dist/backend/components/tabs.mjs",
71
+ "require": "./dist/backend/components/tabs.js",
72
+ "types": "./dist/backend/components/tabs.d.ts"
73
+ },
74
+ "./components/text-input": {
75
+ "@arcanejs/source": "./src/backend/components/text-input.ts",
76
+ "import": "./dist/backend/components/text-input.mjs",
77
+ "require": "./dist/backend/components/text-input.js",
78
+ "types": "./dist/backend/components/text-input.d.ts"
79
+ },
80
+ "./components/timeline": {
81
+ "@arcanejs/source": "./src/backend/components/timeline.ts",
82
+ "import": "./dist/backend/components/timeline.mjs",
83
+ "require": "./dist/backend/components/timeline.js",
84
+ "types": "./dist/backend/components/timeline.d.ts"
24
85
  }
25
86
  },
26
87
  "devDependencies": {
27
88
  "@types/eslint": "^8.56.5",
89
+ "@types/express": "^5.0.0",
90
+ "@types/lodash": "^4.17.10",
28
91
  "@types/node": "^20.11.24",
92
+ "@types/react": "^18",
93
+ "@types/react-dom": "^18",
94
+ "@types/ws": "^8.5.12",
95
+ "esbuild": "^0.24.0",
29
96
  "eslint": "^8.57.0",
97
+ "react": "^18",
98
+ "react-dom": "18.3.1",
99
+ "styled-components": "^6.1.13",
30
100
  "tsup": "^8.1.0",
31
101
  "typescript": "^5.3.3",
32
- "@arcanejs/typescript-config": "0.0.0",
33
- "@arcanejs/eslint-config": "0.0.0"
102
+ "@arcanejs/eslint-config": "^0.0.0",
103
+ "@arcanejs/typescript-config": "^0.0.0"
34
104
  },
35
105
  "dependencies": {
36
- "@arcanejs/diff": "0.3.0"
106
+ "express": "^4.21.1",
107
+ "lodash": "^4.17.21",
108
+ "material-symbols": "^0.25.0",
109
+ "ws": "^8.18.0",
110
+ "@arcanejs/diff": "^0.3.0"
37
111
  },
38
112
  "files": [
39
113
  "dist"
@@ -43,7 +117,13 @@
43
117
  },
44
118
  "scripts": {
45
119
  "lint": "eslint . --max-warnings 0",
46
- "build": "tsup",
47
- "dev": "tsup --watch"
120
+ "build": "pnpm build:backend && pnpm type-check:frontend && pnpm build:frontend",
121
+ "build:backend": "tsup",
122
+ "build:frontend": "esbuild src/frontend/frontend.ts --bundle --sourcemap --outfile=dist/frontend.js",
123
+ "dev": "pnpm dev:backend & pnpm dev:frontend",
124
+ "dev:backend": "pnpm build:backend --watch",
125
+ "dev:frontend": "pnpm type-check:frontend:watch & pnpm build:frontend --watch",
126
+ "type-check:frontend": "tsc --noEmit -p tsconfig.frontend.json",
127
+ "type-check:frontend:watch": "pnpm type-check:frontend --watch --preserveWatchOutput"
48
128
  }
49
129
  }