@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.
- package/dist/backend/components/base.d.mts +2 -0
- package/dist/backend/components/base.d.ts +2 -0
- package/dist/backend/components/base.js +189 -0
- package/dist/backend/components/base.mjs +10 -0
- package/dist/backend/components/button.d.mts +30 -0
- package/dist/backend/components/button.d.ts +30 -0
- package/dist/backend/components/button.js +168 -0
- package/dist/backend/components/button.mjs +7 -0
- package/dist/backend/components/group.d.mts +51 -0
- package/dist/backend/components/group.d.ts +51 -0
- package/dist/backend/components/group.js +287 -0
- package/dist/backend/components/group.mjs +9 -0
- package/dist/backend/components/label.d.mts +21 -0
- package/dist/backend/components/label.d.ts +21 -0
- package/dist/backend/components/label.js +105 -0
- package/dist/backend/components/label.mjs +7 -0
- package/dist/backend/components/rect.d.mts +20 -0
- package/dist/backend/components/rect.d.ts +20 -0
- package/dist/backend/components/rect.js +105 -0
- package/dist/backend/components/rect.mjs +7 -0
- package/dist/backend/components/slider-button.d.mts +31 -0
- package/dist/backend/components/slider-button.d.ts +31 -0
- package/dist/backend/components/slider-button.js +161 -0
- package/dist/backend/components/slider-button.mjs +7 -0
- package/dist/backend/components/switch.d.mts +24 -0
- package/dist/backend/components/switch.d.ts +24 -0
- package/dist/backend/components/switch.js +144 -0
- package/dist/backend/components/switch.mjs +7 -0
- package/dist/backend/components/tabs.d.mts +28 -0
- package/dist/backend/components/tabs.d.ts +28 -0
- package/dist/backend/components/tabs.js +209 -0
- package/dist/backend/components/tabs.mjs +9 -0
- package/dist/backend/components/text-input.d.mts +26 -0
- package/dist/backend/components/text-input.d.ts +26 -0
- package/dist/backend/components/text-input.js +146 -0
- package/dist/backend/components/text-input.mjs +7 -0
- package/dist/backend/components/timeline.d.mts +17 -0
- package/dist/backend/components/timeline.d.ts +17 -0
- package/dist/backend/components/timeline.js +109 -0
- package/dist/backend/components/timeline.mjs +7 -0
- package/dist/base-BJAPu0O1.d.mts +234 -0
- package/dist/base-BJAPu0O1.d.ts +234 -0
- package/dist/chunk-37VNFO5S.mjs +42 -0
- package/dist/chunk-3ZBM7Q4A.mjs +55 -0
- package/dist/chunk-6LL3X7ZZ.mjs +44 -0
- package/dist/chunk-DBW4OPGN.mjs +33 -0
- package/dist/chunk-DP3QFYSS.mjs +66 -0
- package/dist/chunk-GQZA5K4M.mjs +29 -0
- package/dist/chunk-HF77PS7J.mjs +171 -0
- package/dist/chunk-HVFTRNLQ.mjs +59 -0
- package/dist/chunk-P6X5GIDT.mjs +29 -0
- package/dist/chunk-S5DQIYC2.mjs +107 -0
- package/dist/frontend.js +26321 -0
- package/dist/frontend.js.map +7 -0
- package/dist/index.d.mts +75 -1
- package/dist/index.d.ts +75 -1
- package/dist/index.js +852 -1
- package/dist/index.mjs +288 -2
- package/package.json +86 -6
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,288 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
|
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/
|
|
33
|
-
"@arcanejs/
|
|
102
|
+
"@arcanejs/eslint-config": "^0.0.0",
|
|
103
|
+
"@arcanejs/typescript-config": "^0.0.0"
|
|
34
104
|
},
|
|
35
105
|
"dependencies": {
|
|
36
|
-
"
|
|
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": "
|
|
47
|
-
"
|
|
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
|
}
|