@devframes/plugin-code-server 0.9.7 → 0.9.9
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/README.md +10 -10
- package/dist/cli.d.mts +2 -2
- package/dist/cli.mjs +3 -3
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +1 -1
- package/dist/{constants-DtQz38ex.d.mts → constants-BbInB7V-.d.mts} +1 -1
- package/dist/constants.d.mts +1 -1
- package/dist/constants.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/node/index.d.mts +28 -8
- package/dist/node/index.mjs +199 -159
- package/dist/{src-CtmE1558.mjs → src-5dhTkOqj.mjs} +11 -2
- package/dist/types.d.mts +9 -9
- package/dist/vite.mjs +1 -1
- package/package.json +17 -17
package/README.md
CHANGED
|
@@ -11,13 +11,13 @@ auto-authenticated `<iframe>`. The launcher is a **Vue** SPA built on the shared
|
|
|
11
11
|
|
|
12
12
|
## How it works
|
|
13
13
|
|
|
14
|
-
- **Detection
|
|
14
|
+
- **Detection**: on startup it probes the resolved binary with `--version`.
|
|
15
15
|
When none is found, the launcher renders install instructions instead of a
|
|
16
16
|
launch button.
|
|
17
|
-
- **Launch
|
|
17
|
+
- **Launch**: the launcher's button starts the editor as a managed child
|
|
18
18
|
process bound to a free port, scoped to the workspace. Readiness is probed
|
|
19
19
|
before the iframe loads.
|
|
20
|
-
- **Auto-auth
|
|
20
|
+
- **Auto-auth**: the devframe generates fresh auth material per launch and hands
|
|
21
21
|
it to the already-authorized devframe client, so the editor opens already
|
|
22
22
|
signed in. `code-server` uses a session cookie (`HASHED_PASSWORD`);
|
|
23
23
|
`code serve-web` uses a connection token on the URL (`?tkn=`).
|
|
@@ -50,12 +50,12 @@ pnpx @devframes/plugin-code-server # dev server + launcher
|
|
|
50
50
|
import { createCodeServerDevframe } from '@devframes/plugin-code-server'
|
|
51
51
|
|
|
52
52
|
export default createCodeServerDevframe({
|
|
53
|
-
// backend: 'code-server'
|
|
54
|
-
// mode: 'local'
|
|
55
|
-
// serverPort: 8080
|
|
56
|
-
// startOnBoot: true
|
|
57
|
-
// reuseExistingServer: true
|
|
58
|
-
// tunnel: { name: 'my-box' }
|
|
53
|
+
// backend: 'code-server' | 'ms-code-serve-web' (default: auto)
|
|
54
|
+
// mode: 'local' | 'tunnel'
|
|
55
|
+
// serverPort: 8080 (default: free port near 8080)
|
|
56
|
+
// startOnBoot: true (default: on demand)
|
|
57
|
+
// reuseExistingServer: true (adopt a server on the port)
|
|
58
|
+
// tunnel: { name: 'my-box' }
|
|
59
59
|
})
|
|
60
60
|
```
|
|
61
61
|
|
|
@@ -84,7 +84,7 @@ Status (minus the connect descriptor) is mirrored into the
|
|
|
84
84
|
## UI
|
|
85
85
|
|
|
86
86
|
The launcher is a Vue SPA (`src/spa`). `LauncherView.vue` is a pure,
|
|
87
|
-
state-driven view decoupled from RPC
|
|
87
|
+
state-driven view decoupled from RPC, so every phase renders in isolation and has
|
|
88
88
|
a Storybook story; `App.vue` wires the live connection to it and mounts the
|
|
89
89
|
editor in a full-bleed, auto-authenticated iframe (`EditorFrame.vue`).
|
|
90
90
|
|
package/dist/cli.d.mts
CHANGED
|
@@ -2,8 +2,8 @@ import { CodeServerOptions } from "./types.mjs";
|
|
|
2
2
|
import { CacHandle, CreateCacOptions } from "devframe/adapters/cac";
|
|
3
3
|
//#region src/cli.d.ts
|
|
4
4
|
/**
|
|
5
|
-
* Build a standalone CLI for the code-server panel
|
|
6
|
-
* subcommands, backed by {@link createCodeServerDevframe}. Used by the package
|
|
5
|
+
* Build a standalone CLI for the code-server panel, exposing `dev` / `build` /
|
|
6
|
+
* `mcp` subcommands, backed by {@link createCodeServerDevframe}. Used by the package
|
|
7
7
|
* `bin` (`devframe-code-server`).
|
|
8
8
|
*/
|
|
9
9
|
declare function createCodeServerCli(options?: CodeServerOptions, cliOptions?: CreateCacOptions): CacHandle;
|
package/dist/cli.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { t as createCodeServerDevframe } from "./src-
|
|
1
|
+
import { t as createCodeServerDevframe } from "./src-5dhTkOqj.mjs";
|
|
2
2
|
import { createCac } from "devframe/adapters/cac";
|
|
3
3
|
//#region src/cli.ts
|
|
4
4
|
/**
|
|
5
|
-
* Build a standalone CLI for the code-server panel
|
|
6
|
-
* subcommands, backed by {@link createCodeServerDevframe}. Used by the package
|
|
5
|
+
* Build a standalone CLI for the code-server panel, exposing `dev` / `build` /
|
|
6
|
+
* `mcp` subcommands, backed by {@link createCodeServerDevframe}. Used by the package
|
|
7
7
|
* `bin` (`devframe-code-server`).
|
|
8
8
|
*/
|
|
9
9
|
function createCodeServerCli(options = {}, cliOptions = {}) {
|
package/dist/client/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CodeServerBackend, CodeServerConnect, CodeServerDetection, CodeServerLogin, CodeServerMode, CodeServerServerInfo, CodeServerSharedState, CodeServerStartResult, CodeServerStatus, CodeServerStatusResult } from "../types.mjs";
|
|
2
|
-
import { o as STATE_KEY } from "../constants-
|
|
2
|
+
import { o as STATE_KEY } from "../constants-BbInB7V-.mjs";
|
|
3
3
|
import { DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientOptions } from "devframe/client";
|
|
4
4
|
import { ConnectionMeta } from "devframe/types";
|
|
5
5
|
//#region src/client/index.d.ts
|
package/dist/client/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { connectDevframe } from "devframe/client";
|
|
|
2
2
|
//#region src/constants.ts
|
|
3
3
|
/**
|
|
4
4
|
* Shared-state key holding the serializable, secret-free server status and
|
|
5
|
-
* detection result. Authentication material is never published here
|
|
5
|
+
* detection result. Authentication material is never published here; it is
|
|
6
6
|
* returned only from the `start` / `status` RPCs to the already-authorized
|
|
7
7
|
* client (see {@link import('./types').CodeServerConnect}).
|
|
8
8
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
declare const PLUGIN_ID = "devframes_plugin_code-server";
|
|
4
4
|
/**
|
|
5
5
|
* Shared-state key holding the serializable, secret-free server status and
|
|
6
|
-
* detection result. Authentication material is never published here
|
|
6
|
+
* detection result. Authentication material is never published here; it is
|
|
7
7
|
* returned only from the `start` / `status` RPCs to the already-authorized
|
|
8
8
|
* client (see {@link import('./types').CodeServerConnect}).
|
|
9
9
|
*/
|
package/dist/constants.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SESSION_COOKIE_BASE, c as TERMINAL_SESSION_TITLE, i as PLUGIN_ID, l as getCookieSessionName, n as DEFAULT_PORT, o as STATE_KEY, r as DEFAULT_START_TIMEOUT, s as TERMINAL_SESSION_ICON, t as DEFAULT_CODE_SERVER_PORT } from "./constants-
|
|
1
|
+
import { a as SESSION_COOKIE_BASE, c as TERMINAL_SESSION_TITLE, i as PLUGIN_ID, l as getCookieSessionName, n as DEFAULT_PORT, o as STATE_KEY, r as DEFAULT_START_TIMEOUT, s as TERMINAL_SESSION_ICON, t as DEFAULT_CODE_SERVER_PORT } from "./constants-BbInB7V-.mjs";
|
|
2
2
|
export { DEFAULT_CODE_SERVER_PORT, DEFAULT_PORT, DEFAULT_START_TIMEOUT, PLUGIN_ID, SESSION_COOKIE_BASE, STATE_KEY, TERMINAL_SESSION_ICON, TERMINAL_SESSION_TITLE, getCookieSessionName };
|
package/dist/constants.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const PLUGIN_ID = "devframes_plugin_code-server";
|
|
4
4
|
/**
|
|
5
5
|
* Shared-state key holding the serializable, secret-free server status and
|
|
6
|
-
* detection result. Authentication material is never published here
|
|
6
|
+
* detection result. Authentication material is never published here; it is
|
|
7
7
|
* returned only from the `start` / `status` RPCs to the already-authorized
|
|
8
8
|
* client (see {@link import('./types').CodeServerConnect}).
|
|
9
9
|
*/
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { CodeServerBackend, CodeServerConnect, CodeServerDetection, CodeServerLogin, CodeServerMode, CodeServerOptions, CodeServerServerInfo, CodeServerSharedState, CodeServerStartRequest, CodeServerStartResult, CodeServerStatus, CodeServerStatusResult, CodeServerTunnelOptions } from "./types.mjs";
|
|
2
|
-
import { i as PLUGIN_ID, l as getCookieSessionName, n as DEFAULT_PORT, o as STATE_KEY, t as DEFAULT_CODE_SERVER_PORT } from "./constants-
|
|
2
|
+
import { i as PLUGIN_ID, l as getCookieSessionName, n as DEFAULT_PORT, o as STATE_KEY, t as DEFAULT_CODE_SERVER_PORT } from "./constants-BbInB7V-.mjs";
|
|
3
3
|
import { DevframeDefinition } from "devframe";
|
|
4
4
|
//#region src/index.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* Build a {@link DevframeDefinition} for the code-server panel. The same
|
|
7
7
|
* definition runs standalone (`createCac`), mounts into a Vite host
|
|
8
|
-
* (`/vite`), or docks inside a hub
|
|
8
|
+
* (`/vite`), or docks inside a hub, since its `setup` only relies on the core
|
|
9
9
|
* devframe RPC + shared-state surface.
|
|
10
10
|
*
|
|
11
11
|
* @experimental This plugin is experimental and may change without a major
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as createCodeServerDevframe } from "./src-
|
|
1
|
+
import { t as createCodeServerDevframe } from "./src-5dhTkOqj.mjs";
|
|
2
2
|
import { DEFAULT_CODE_SERVER_PORT, DEFAULT_PORT, PLUGIN_ID, STATE_KEY, getCookieSessionName } from "./constants.mjs";
|
|
3
3
|
export { DEFAULT_CODE_SERVER_PORT, DEFAULT_PORT, PLUGIN_ID, STATE_KEY, createCodeServerDevframe, createCodeServerDevframe as default, getCookieSessionName };
|
package/dist/node/index.d.mts
CHANGED
|
@@ -62,12 +62,28 @@ declare class CodeServerSupervisor {
|
|
|
62
62
|
status(): CodeServerStatusResult;
|
|
63
63
|
/**
|
|
64
64
|
* Launch the editor (if not already up) and resolve once it is reachable.
|
|
65
|
-
* Idempotent while starting/running
|
|
65
|
+
* Idempotent while starting/running; returns the live status instead of
|
|
66
66
|
* spawning a second process. In tunnel mode it resolves as soon as either
|
|
67
67
|
* the `vscode.dev` URL or a device-login prompt is seen, so the action never
|
|
68
68
|
* blocks on interactive authentication.
|
|
69
69
|
*/
|
|
70
70
|
start(req?: CodeServerStartRequest): Promise<CodeServerStartResult>;
|
|
71
|
+
/** Adopt an already-running local server on the target port, if one answers. */
|
|
72
|
+
private tryAdopt;
|
|
73
|
+
/** Resolve the port to launch on: 0 for tunnels/dynamic, a forced port, or a free one. */
|
|
74
|
+
private resolveInitialPort;
|
|
75
|
+
/** The child's environment: inherited env, caller overrides, then profile shaping. */
|
|
76
|
+
private buildLaunchEnv;
|
|
77
|
+
/** Buffer output and latch the port / login / ready-URL signals from each line. */
|
|
78
|
+
private consumeOutput;
|
|
79
|
+
private latchPort;
|
|
80
|
+
private latchLogin;
|
|
81
|
+
private latchReadyUrl;
|
|
82
|
+
private handleChildError;
|
|
83
|
+
private handleChildExit;
|
|
84
|
+
/** Wait for the dynamic port then readiness, and flip to `running`. */
|
|
85
|
+
private finalizeLocalStart;
|
|
86
|
+
private handleStartFailure;
|
|
71
87
|
/** Stop the editor process and reset to `stopped`. */
|
|
72
88
|
stop(): CodeServerStatusResult;
|
|
73
89
|
/** Kill the process on host shutdown / test teardown. */
|
|
@@ -89,7 +105,7 @@ declare class CodeServerSupervisor {
|
|
|
89
105
|
/**
|
|
90
106
|
* Resolve the hub's terminals subsystem when this devframe is mounted in a
|
|
91
107
|
* hub. `ctx.terminals` only exists on a `DevframeHubContext`, so it is
|
|
92
|
-
* duck-typed
|
|
108
|
+
* duck-typed: standalone runtimes (CLI / Vite / build) have no such property
|
|
93
109
|
* and fall back to a direct child process.
|
|
94
110
|
*/
|
|
95
111
|
private resolveHubTerminals;
|
|
@@ -103,6 +119,10 @@ declare class CodeServerSupervisor {
|
|
|
103
119
|
* readiness / port / log wiring in `start()` is identical.
|
|
104
120
|
*/
|
|
105
121
|
private launchProcess;
|
|
122
|
+
/** Spawn through the hub's terminals subsystem so it shows as a terminal session. */
|
|
123
|
+
private launchViaHub;
|
|
124
|
+
/** Spawn the editor binary directly (standalone runtimes with no hub). */
|
|
125
|
+
private launchDirect;
|
|
106
126
|
private appendLog;
|
|
107
127
|
private lastLog;
|
|
108
128
|
private publish;
|
|
@@ -119,8 +139,8 @@ declare class CodeServerSupervisor {
|
|
|
119
139
|
* The internal launch profile the supervisor drives. One of three "kinds":
|
|
120
140
|
* the two local {@link CodeServerBackend}s plus the `code tunnel` profile
|
|
121
141
|
* selected by `mode: 'tunnel'`. Each profile owns the backend-specific pieces
|
|
122
|
-
*
|
|
123
|
-
* ultimately reaches the editor
|
|
142
|
+
* (binary, arguments, auth env, readiness detection, and how the client
|
|
143
|
+
* ultimately reaches the editor), while the supervisor owns the shared
|
|
124
144
|
* spawn / log / publish lifecycle.
|
|
125
145
|
*/
|
|
126
146
|
type CodeServerProfileKind = 'code-server' | 'serve-web' | 'tunnel';
|
|
@@ -181,14 +201,14 @@ interface DetectCodeServerResult {
|
|
|
181
201
|
/**
|
|
182
202
|
* Probe the host for a usable code-server binary by running
|
|
183
203
|
* `<bin> --version`. Resolves to `installed: false` when the binary is
|
|
184
|
-
* missing (ENOENT), errors, or exits non-zero
|
|
204
|
+
* missing (ENOENT), errors, or exits non-zero (never throws), so the
|
|
185
205
|
* launcher can fall back to install instructions.
|
|
186
206
|
*
|
|
187
207
|
* `code-server --version` prints e.g. `4.96.4 abc123 with Code 1.96.4`; the
|
|
188
208
|
* first semver-looking token is taken as the version. Matching a semver
|
|
189
209
|
* pattern (rather than the leading whitespace token) keeps cold-start i18n
|
|
190
|
-
* noise
|
|
191
|
-
*
|
|
210
|
+
* noise (e.g. an `i18next: …` initialization line printed before the version)
|
|
211
|
+
* from leaking into the reported version.
|
|
192
212
|
*/
|
|
193
213
|
declare function detectCodeServer(bin?: string, timeoutMs?: number): Promise<DetectCodeServerResult>;
|
|
194
214
|
//#endregion
|
|
@@ -473,7 +493,7 @@ declare const diagnostics: Diagnostics<{
|
|
|
473
493
|
* status into shared state, and register the control RPC functions. Returns
|
|
474
494
|
* the supervisor so callers can launch/stop or dispose it on shutdown.
|
|
475
495
|
*
|
|
476
|
-
* Works in any devframe runtime (CLI, Vite, embedded, build)
|
|
496
|
+
* Works in any devframe runtime (CLI, Vite, embedded, build), since it only relies
|
|
477
497
|
* on the core `ctx.rpc` shared-state surface, not on the hub.
|
|
478
498
|
*/
|
|
479
499
|
declare function setupCodeServer(ctx: DevframeNodeContext, options?: CodeServerOptions): Promise<CodeServerSupervisor>;
|
package/dist/node/index.mjs
CHANGED
|
@@ -60,6 +60,7 @@ const serveWebProfile = {
|
|
|
60
60
|
...c.extraArgs
|
|
61
61
|
],
|
|
62
62
|
buildEnv: (_c, base) => ({ ...base }),
|
|
63
|
+
/** serve-web has no health endpoint; the root responds (200/redirect) once up. */
|
|
63
64
|
healthPath: "/",
|
|
64
65
|
matchPort: (line) => {
|
|
65
66
|
const m = line.match(/available at https?:\/\/[^:]+:(\d+)/i);
|
|
@@ -113,14 +114,14 @@ function resolveProfile(mode, backend) {
|
|
|
113
114
|
/**
|
|
114
115
|
* Probe the host for a usable code-server binary by running
|
|
115
116
|
* `<bin> --version`. Resolves to `installed: false` when the binary is
|
|
116
|
-
* missing (ENOENT), errors, or exits non-zero
|
|
117
|
+
* missing (ENOENT), errors, or exits non-zero (never throws), so the
|
|
117
118
|
* launcher can fall back to install instructions.
|
|
118
119
|
*
|
|
119
120
|
* `code-server --version` prints e.g. `4.96.4 abc123 with Code 1.96.4`; the
|
|
120
121
|
* first semver-looking token is taken as the version. Matching a semver
|
|
121
122
|
* pattern (rather than the leading whitespace token) keeps cold-start i18n
|
|
122
|
-
* noise
|
|
123
|
-
*
|
|
123
|
+
* noise (e.g. an `i18next: …` initialization line printed before the version)
|
|
124
|
+
* from leaking into the reported version.
|
|
124
125
|
*/
|
|
125
126
|
function detectCodeServer(bin = "code-server", timeoutMs = 5e3) {
|
|
126
127
|
return new Promise((resolve) => {
|
|
@@ -326,7 +327,7 @@ var CodeServerSupervisor = class {
|
|
|
326
327
|
}
|
|
327
328
|
/**
|
|
328
329
|
* Launch the editor (if not already up) and resolve once it is reachable.
|
|
329
|
-
* Idempotent while starting/running
|
|
330
|
+
* Idempotent while starting/running; returns the live status instead of
|
|
330
331
|
* spawning a second process. In tunnel mode it resolves as soon as either
|
|
331
332
|
* the `vscode.dev` URL or a device-login prompt is seen, so the action never
|
|
332
333
|
* blocks on interactive authentication.
|
|
@@ -338,151 +339,177 @@ var CodeServerSupervisor = class {
|
|
|
338
339
|
const folder = req.folder ?? this.workspace;
|
|
339
340
|
const isLocal = this.profile.kind !== "tunnel";
|
|
340
341
|
if (isLocal && this.reuseExistingServer) {
|
|
341
|
-
const
|
|
342
|
-
if (
|
|
343
|
-
this.adopted = true;
|
|
344
|
-
this.launchCtx = this.baseCtx(folder, target, "");
|
|
345
|
-
this.server = {
|
|
346
|
-
status: "running",
|
|
347
|
-
port: target,
|
|
348
|
-
startedAt: Date.now()
|
|
349
|
-
};
|
|
350
|
-
this.publish();
|
|
351
|
-
return this.status();
|
|
352
|
-
}
|
|
342
|
+
const adopted = await this.tryAdopt(folder);
|
|
343
|
+
if (adopted) return adopted;
|
|
353
344
|
}
|
|
354
345
|
const secret = randomBytes(32).toString("hex");
|
|
355
|
-
const initialPort =
|
|
356
|
-
host: "127.0.0.1",
|
|
357
|
-
port: DEFAULT_CODE_SERVER_PORT
|
|
358
|
-
});
|
|
346
|
+
const initialPort = await this.resolveInitialPort(isLocal);
|
|
359
347
|
const ctx = this.baseCtx(folder, initialPort, secret);
|
|
360
348
|
this.launchCtx = ctx;
|
|
361
349
|
this.adopted = false;
|
|
362
350
|
this.readyUrl = void 0;
|
|
363
351
|
const args = this.profile.buildArgs(ctx);
|
|
364
|
-
const
|
|
365
|
-
for (const [k, v] of Object.entries(process.env)) if (v !== void 0) baseEnv[k] = v;
|
|
366
|
-
Object.assign(baseEnv, this.extraEnv);
|
|
367
|
-
const env = this.profile.buildEnv(ctx, baseEnv);
|
|
352
|
+
const env = this.buildLaunchEnv(ctx);
|
|
368
353
|
this.logBuffer = [];
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
354
|
+
const signals = {
|
|
355
|
+
isLocal,
|
|
356
|
+
actualPort: initialPort
|
|
357
|
+
};
|
|
372
358
|
const portPromise = isLocal && initialPort === 0 ? new Promise((resolve, reject) => {
|
|
373
|
-
|
|
374
|
-
|
|
359
|
+
signals.resolvePort = resolve;
|
|
360
|
+
signals.rejectPort = reject;
|
|
375
361
|
}) : Promise.resolve(initialPort);
|
|
376
|
-
let readyUrlResolver;
|
|
377
|
-
let loginResolver;
|
|
378
362
|
const readyUrlPromise = new Promise((resolve) => {
|
|
379
|
-
|
|
363
|
+
signals.resolveReadyUrl = resolve;
|
|
380
364
|
});
|
|
381
365
|
const loginPromise = new Promise((resolve) => {
|
|
382
|
-
|
|
366
|
+
signals.resolveLogin = resolve;
|
|
383
367
|
});
|
|
384
368
|
const child = await this.launchProcess(args, env, folder);
|
|
385
369
|
this.registerCleanup();
|
|
386
370
|
this.proc = child;
|
|
387
371
|
this.server = {
|
|
388
372
|
status: "starting",
|
|
389
|
-
port: isLocal ? actualPort || void 0 : void 0,
|
|
373
|
+
port: isLocal ? signals.actualPort || void 0 : void 0,
|
|
390
374
|
pid: child.pid,
|
|
391
375
|
startedAt: Date.now()
|
|
392
376
|
};
|
|
393
377
|
this.publish();
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
loginResolver?.(login);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
if (this.profile.matchReadyUrl) {
|
|
420
|
-
const url = this.profile.matchReadyUrl(line);
|
|
421
|
-
if (url && this.proc === child) {
|
|
422
|
-
this.readyUrl = url;
|
|
423
|
-
readyUrlResolver?.(url);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
378
|
+
child.stdout?.on("data", (chunk) => this.consumeOutput(chunk, child, signals));
|
|
379
|
+
child.stderr?.on("data", (chunk) => this.consumeOutput(chunk, child, signals));
|
|
380
|
+
child.on("error", (error) => this.handleChildError(child, error, signals));
|
|
381
|
+
child.on("exit", (code) => this.handleChildExit(child, code, signals));
|
|
382
|
+
try {
|
|
383
|
+
if (!isLocal) return await this.awaitTunnel(child, readyUrlPromise, loginPromise);
|
|
384
|
+
return await this.finalizeLocalStart(child, portPromise);
|
|
385
|
+
} catch (error) {
|
|
386
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
387
|
+
return this.handleStartFailure(child, reason, isLocal, signals.actualPort);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/** Adopt an already-running local server on the target port, if one answers. */
|
|
391
|
+
async tryAdopt(folder) {
|
|
392
|
+
const target = this.forcedPort && this.forcedPort !== 0 ? this.forcedPort : DEFAULT_CODE_SERVER_PORT;
|
|
393
|
+
if (!this.profile.healthPath || !await probeHealth(target, this.profile.healthPath)) return void 0;
|
|
394
|
+
this.adopted = true;
|
|
395
|
+
this.launchCtx = this.baseCtx(folder, target, "");
|
|
396
|
+
this.server = {
|
|
397
|
+
status: "running",
|
|
398
|
+
port: target,
|
|
399
|
+
startedAt: Date.now()
|
|
427
400
|
};
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
401
|
+
this.publish();
|
|
402
|
+
return this.status();
|
|
403
|
+
}
|
|
404
|
+
/** Resolve the port to launch on: 0 for tunnels/dynamic, a forced port, or a free one. */
|
|
405
|
+
async resolveInitialPort(isLocal) {
|
|
406
|
+
if (!isLocal) return 0;
|
|
407
|
+
if (this.forcedPort !== void 0 && this.forcedPort !== 0) return this.forcedPort;
|
|
408
|
+
if (this.forcedPort === 0) return 0;
|
|
409
|
+
return getPort({
|
|
410
|
+
host: "127.0.0.1",
|
|
411
|
+
port: DEFAULT_CODE_SERVER_PORT
|
|
439
412
|
});
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
413
|
+
}
|
|
414
|
+
/** The child's environment: inherited env, caller overrides, then profile shaping. */
|
|
415
|
+
buildLaunchEnv(ctx) {
|
|
416
|
+
const baseEnv = {};
|
|
417
|
+
for (const [k, v] of Object.entries(process.env)) if (v !== void 0) baseEnv[k] = v;
|
|
418
|
+
Object.assign(baseEnv, this.extraEnv);
|
|
419
|
+
return this.profile.buildEnv(ctx, baseEnv);
|
|
420
|
+
}
|
|
421
|
+
/** Buffer output and latch the port / login / ready-URL signals from each line. */
|
|
422
|
+
consumeOutput(chunk, child, s) {
|
|
423
|
+
const text = chunk.toString("utf8");
|
|
424
|
+
this.appendLog(text);
|
|
425
|
+
for (const line of text.split("\n")) {
|
|
426
|
+
this.latchPort(line, s);
|
|
427
|
+
this.latchLogin(line, child, s);
|
|
428
|
+
this.latchReadyUrl(line, child, s);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
latchPort(line, s) {
|
|
432
|
+
if (!s.isLocal || s.actualPort !== 0 || !this.profile.matchPort) return;
|
|
433
|
+
const port = this.profile.matchPort(line);
|
|
434
|
+
if (!port) return;
|
|
435
|
+
s.actualPort = port;
|
|
436
|
+
this.server.port = port;
|
|
437
|
+
this.publish();
|
|
438
|
+
s.resolvePort?.(port);
|
|
439
|
+
s.resolvePort = void 0;
|
|
440
|
+
}
|
|
441
|
+
latchLogin(line, child, s) {
|
|
442
|
+
const login = this.profile.matchLogin?.(line);
|
|
443
|
+
if (!login || this.proc !== child) return;
|
|
444
|
+
this.server = {
|
|
445
|
+
...this.server,
|
|
446
|
+
login
|
|
447
|
+
};
|
|
448
|
+
this.publish();
|
|
449
|
+
s.resolveLogin?.(login);
|
|
450
|
+
}
|
|
451
|
+
latchReadyUrl(line, child, s) {
|
|
452
|
+
const url = this.profile.matchReadyUrl?.(line);
|
|
453
|
+
if (!url || this.proc !== child) return;
|
|
454
|
+
this.readyUrl = url;
|
|
455
|
+
s.resolveReadyUrl?.(url);
|
|
456
|
+
}
|
|
457
|
+
handleChildError(child, error, s) {
|
|
458
|
+
if (this.proc !== child) return;
|
|
459
|
+
this.server = {
|
|
460
|
+
status: "error",
|
|
461
|
+
error: error.message
|
|
462
|
+
};
|
|
463
|
+
this.reset();
|
|
464
|
+
s.rejectPort?.(error);
|
|
465
|
+
this.publish();
|
|
466
|
+
}
|
|
467
|
+
handleChildExit(child, code, s) {
|
|
468
|
+
if (this.proc !== child) return;
|
|
469
|
+
const exitCode = code ?? 0;
|
|
470
|
+
const crashed = this.server.status !== "stopped" && exitCode !== 0;
|
|
471
|
+
this.reset();
|
|
472
|
+
this.server = crashed ? {
|
|
473
|
+
status: "error",
|
|
474
|
+
error: this.lastLog() || `${this.bin} exited with code ${exitCode}`
|
|
475
|
+
} : { status: "stopped" };
|
|
476
|
+
if (crashed) diagnostics.DP_CODE_SERVER_0005({ code: exitCode }, { method: "warn" });
|
|
477
|
+
this.reflectHub(crashed ? "error" : "stopped");
|
|
478
|
+
this.session = void 0;
|
|
479
|
+
s.rejectPort?.(/* @__PURE__ */ new Error(`${this.bin} exited before binding (code ${exitCode})`));
|
|
480
|
+
this.publish();
|
|
481
|
+
}
|
|
482
|
+
/** Wait for the dynamic port then readiness, and flip to `running`. */
|
|
483
|
+
async finalizeLocalStart(child, portPromise) {
|
|
484
|
+
const port = await Promise.race([portPromise, new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("timeout waiting for dynamic port allocation")), this.startTimeout))]);
|
|
485
|
+
if (!await this.waitForReady(port, this.profile.healthPath)) throw new Error(this.lastLog() || "startup timed out");
|
|
486
|
+
if (this.proc !== child) return this.status();
|
|
487
|
+
this.server = {
|
|
488
|
+
status: "running",
|
|
489
|
+
port,
|
|
490
|
+
pid: child.pid,
|
|
491
|
+
startedAt: this.server.startedAt
|
|
492
|
+
};
|
|
493
|
+
this.publish();
|
|
494
|
+
return this.status();
|
|
495
|
+
}
|
|
496
|
+
handleStartFailure(child, reason, isLocal, actualPort) {
|
|
497
|
+
if (this.proc === child) {
|
|
498
|
+
this.terminate(child);
|
|
499
|
+
this.reflectHub("error");
|
|
451
500
|
this.session = void 0;
|
|
452
|
-
portRejecter?.(/* @__PURE__ */ new Error(`${this.bin} exited before binding (code ${exitCode})`));
|
|
453
|
-
this.publish();
|
|
454
|
-
});
|
|
455
|
-
try {
|
|
456
|
-
if (!isLocal) return await this.awaitTunnel(child, readyUrlPromise, loginPromise);
|
|
457
|
-
const port = await Promise.race([portPromise, new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("timeout waiting for dynamic port allocation")), this.startTimeout))]);
|
|
458
|
-
if (!await this.waitForReady(port, this.profile.healthPath)) throw new Error(this.lastLog() || "startup timed out");
|
|
459
|
-
if (this.proc !== child) return this.status();
|
|
460
501
|
this.server = {
|
|
461
|
-
status: "
|
|
462
|
-
|
|
463
|
-
pid: child.pid,
|
|
464
|
-
startedAt: this.server.startedAt
|
|
502
|
+
status: "error",
|
|
503
|
+
error: reason
|
|
465
504
|
};
|
|
505
|
+
this.reset();
|
|
466
506
|
this.publish();
|
|
467
|
-
return this.status();
|
|
468
|
-
} catch (error) {
|
|
469
|
-
if (this.proc === child) {
|
|
470
|
-
this.terminate(child);
|
|
471
|
-
this.reflectHub("error");
|
|
472
|
-
this.session = void 0;
|
|
473
|
-
this.server = {
|
|
474
|
-
status: "error",
|
|
475
|
-
error: error instanceof Error ? error.message : String(error)
|
|
476
|
-
};
|
|
477
|
-
this.reset();
|
|
478
|
-
this.publish();
|
|
479
|
-
}
|
|
480
|
-
if (!isLocal) throw diagnostics.DP_CODE_SERVER_0006({ timeout: this.startTimeout });
|
|
481
|
-
throw diagnostics.DP_CODE_SERVER_0002({
|
|
482
|
-
port: actualPort,
|
|
483
|
-
timeout: this.startTimeout
|
|
484
|
-
});
|
|
485
507
|
}
|
|
508
|
+
if (!isLocal) throw diagnostics.DP_CODE_SERVER_0006({ timeout: this.startTimeout });
|
|
509
|
+
throw diagnostics.DP_CODE_SERVER_0002({
|
|
510
|
+
port: actualPort,
|
|
511
|
+
timeout: this.startTimeout
|
|
512
|
+
});
|
|
486
513
|
}
|
|
487
514
|
/** Stop the editor process and reset to `stopped`. */
|
|
488
515
|
stop() {
|
|
@@ -590,7 +617,7 @@ var CodeServerSupervisor = class {
|
|
|
590
617
|
/**
|
|
591
618
|
* Resolve the hub's terminals subsystem when this devframe is mounted in a
|
|
592
619
|
* hub. `ctx.terminals` only exists on a `DevframeHubContext`, so it is
|
|
593
|
-
* duck-typed
|
|
620
|
+
* duck-typed: standalone runtimes (CLI / Vite / build) have no such property
|
|
594
621
|
* and fall back to a direct child process.
|
|
595
622
|
*/
|
|
596
623
|
resolveHubTerminals() {
|
|
@@ -614,45 +641,58 @@ var CodeServerSupervisor = class {
|
|
|
614
641
|
*/
|
|
615
642
|
async launchProcess(args, env, folder) {
|
|
616
643
|
const hub = this.resolveHubTerminals();
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
644
|
+
return hub ? this.launchViaHub(hub, args, env, folder) : this.launchDirect(args, env, folder);
|
|
645
|
+
}
|
|
646
|
+
/** Spawn through the hub's terminals subsystem so it shows as a terminal session. */
|
|
647
|
+
async launchViaHub(hub, args, env, folder) {
|
|
648
|
+
const stale = hub.sessions.get(this.sessionId);
|
|
649
|
+
if (stale) hub.remove?.(stale);
|
|
650
|
+
try {
|
|
651
|
+
const session = await hub.startChildProcess({
|
|
652
|
+
command: this.bin,
|
|
653
|
+
args,
|
|
654
|
+
cwd: folder,
|
|
655
|
+
/**
|
|
656
|
+
* The hub merges `process.env`, so neutralize PASSWORD explicitly
|
|
657
|
+
* (code-server authenticates via HASHED_PASSWORD).
|
|
658
|
+
*/
|
|
659
|
+
env: {
|
|
660
|
+
...env,
|
|
661
|
+
PASSWORD: ""
|
|
662
|
+
}
|
|
663
|
+
}, {
|
|
664
|
+
id: this.sessionId,
|
|
665
|
+
title: TERMINAL_SESSION_TITLE,
|
|
666
|
+
description: folder,
|
|
667
|
+
icon: TERMINAL_SESSION_ICON,
|
|
668
|
+
/**
|
|
669
|
+
* Restart re-runs the supervisor's start flow (fresh port + secret),
|
|
670
|
+
* not this raw process, so hide the panel's generic restart.
|
|
671
|
+
*/
|
|
672
|
+
restartable: false
|
|
673
|
+
});
|
|
674
|
+
const child = session.getChildProcess();
|
|
675
|
+
if (!child) throw new Error("editor process handle was unavailable");
|
|
676
|
+
this.session = session;
|
|
677
|
+
return child;
|
|
678
|
+
} catch (error) {
|
|
679
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
680
|
+
const orphan = hub.sessions.get(this.sessionId);
|
|
681
|
+
if (orphan) hub.remove?.(orphan);
|
|
682
|
+
this.session = void 0;
|
|
683
|
+
this.server = {
|
|
684
|
+
status: "error",
|
|
685
|
+
error: reason
|
|
686
|
+
};
|
|
687
|
+
this.publish();
|
|
688
|
+
throw diagnostics.DP_CODE_SERVER_0003({
|
|
689
|
+
bin: this.bin,
|
|
690
|
+
reason
|
|
691
|
+
});
|
|
655
692
|
}
|
|
693
|
+
}
|
|
694
|
+
/** Spawn the editor binary directly (standalone runtimes with no hub). */
|
|
695
|
+
launchDirect(args, env, folder) {
|
|
656
696
|
try {
|
|
657
697
|
return spawn(this.bin, args, {
|
|
658
698
|
cwd: folder,
|
|
@@ -746,7 +786,7 @@ function probeHealth(port, path) {
|
|
|
746
786
|
* status into shared state, and register the control RPC functions. Returns
|
|
747
787
|
* the supervisor so callers can launch/stop or dispose it on shutdown.
|
|
748
788
|
*
|
|
749
|
-
* Works in any devframe runtime (CLI, Vite, embedded, build)
|
|
789
|
+
* Works in any devframe runtime (CLI, Vite, embedded, build), since it only relies
|
|
750
790
|
* on the core `ctx.rpc` shared-state surface, not on the hub.
|
|
751
791
|
*/
|
|
752
792
|
async function setupCodeServer(ctx, options = {}) {
|
|
@@ -2,7 +2,7 @@ import { PLUGIN_ID } from "./constants.mjs";
|
|
|
2
2
|
import { defineDevframe } from "devframe";
|
|
3
3
|
//#region package.json
|
|
4
4
|
var name = "@devframes/plugin-code-server";
|
|
5
|
-
var version = "0.9.
|
|
5
|
+
var version = "0.9.9";
|
|
6
6
|
var description = "Devframe plugin that runs VS Code in the browser as an embedded editor panel.";
|
|
7
7
|
var homepage = "https://github.com/devframes/devframe#readme";
|
|
8
8
|
//#endregion
|
|
@@ -14,7 +14,7 @@ const remoteAssets = {
|
|
|
14
14
|
/**
|
|
15
15
|
* Build a {@link DevframeDefinition} for the code-server panel. The same
|
|
16
16
|
* definition runs standalone (`createCac`), mounts into a Vite host
|
|
17
|
-
* (`/vite`), or docks inside a hub
|
|
17
|
+
* (`/vite`), or docks inside a hub, since its `setup` only relies on the core
|
|
18
18
|
* devframe RPC + shared-state surface.
|
|
19
19
|
*
|
|
20
20
|
* @experimental This plugin is experimental and may change without a major
|
|
@@ -38,6 +38,10 @@ function createCodeServerDevframe(options = {}) {
|
|
|
38
38
|
homepage,
|
|
39
39
|
description,
|
|
40
40
|
icon: "ph:code-duotone",
|
|
41
|
+
/**
|
|
42
|
+
* Leave undefined so `resolveBasePath` picks `/` standalone and
|
|
43
|
+
* `/__<id>/` when hosted. Authors override via `options.basePath`.
|
|
44
|
+
*/
|
|
41
45
|
basePath: options.basePath,
|
|
42
46
|
cli: {
|
|
43
47
|
command: options.command ?? "devframe-code-server",
|
|
@@ -45,6 +49,11 @@ function createCodeServerDevframe(options = {}) {
|
|
|
45
49
|
portRange: options.portRange,
|
|
46
50
|
random: options.random,
|
|
47
51
|
distDir: resolvedDist,
|
|
52
|
+
/**
|
|
53
|
+
* Gate the standalone launcher by default; `maybeOpenBrowser` folds the
|
|
54
|
+
* current OTP into the `--open` URL so the tab lands already trusted.
|
|
55
|
+
* Hosted adapters supply their own auth layer and ignore this.
|
|
56
|
+
*/
|
|
48
57
|
auth: options.auth ?? true
|
|
49
58
|
},
|
|
50
59
|
async setup(ctx) {
|
package/dist/types.d.mts
CHANGED
|
@@ -4,11 +4,11 @@ type CodeServerStatus = 'stopped' | 'starting' | 'running' | 'error';
|
|
|
4
4
|
/**
|
|
5
5
|
* Which editor server binary the plugin launches in `mode: 'local'`:
|
|
6
6
|
*
|
|
7
|
-
* - `'code-server'
|
|
7
|
+
* - `'code-server'`: Coder's open-source
|
|
8
8
|
* [code-server](https://github.com/coder/code-server) (`code-server …`). The
|
|
9
9
|
* plugin runs it with password auth and hands the client a session cookie, so
|
|
10
10
|
* the embedded editor opens already signed in.
|
|
11
|
-
* - `'ms-code-serve-web'
|
|
11
|
+
* - `'ms-code-serve-web'`: Microsoft's official
|
|
12
12
|
* [`code serve-web`](https://code.visualstudio.com/docs/remote/vscode-server)
|
|
13
13
|
* (ships with the `code` CLI). The plugin generates a connection token and
|
|
14
14
|
* hands it to the client as a `?tkn=` query parameter.
|
|
@@ -17,9 +17,9 @@ type CodeServerBackend = 'code-server' | 'ms-code-serve-web';
|
|
|
17
17
|
/**
|
|
18
18
|
* How the editor is served:
|
|
19
19
|
*
|
|
20
|
-
* - `'local'
|
|
20
|
+
* - `'local'`: a local server ({@link CodeServerBackend}) embedded from this
|
|
21
21
|
* machine's origin.
|
|
22
|
-
* - `'tunnel'
|
|
22
|
+
* - `'tunnel'`: Microsoft's `code tunnel`, which registers a remote tunnel and
|
|
23
23
|
* embeds the hosted `vscode.dev` editor. First launch prints a device-login
|
|
24
24
|
* prompt (surfaced as {@link CodeServerLogin}); authentication is handled by
|
|
25
25
|
* `vscode.dev` itself, not this plugin.
|
|
@@ -70,7 +70,7 @@ interface CodeServerServerInfo {
|
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
72
|
* The full shared-state payload broadcast to subscribed clients. Deliberately
|
|
73
|
-
* carries no authentication material
|
|
73
|
+
* carries no authentication material; see {@link CodeServerConnect}.
|
|
74
74
|
*/
|
|
75
75
|
interface CodeServerSharedState {
|
|
76
76
|
detection: CodeServerDetection;
|
|
@@ -79,7 +79,7 @@ interface CodeServerSharedState {
|
|
|
79
79
|
/**
|
|
80
80
|
* How the client reaches the running editor. May carry a secret (session
|
|
81
81
|
* cookie or connection token), so it is returned only from the `start` /
|
|
82
|
-
* `status` RPCs to the already-authorized client
|
|
82
|
+
* `status` RPCs to the already-authorized client, never published to shared
|
|
83
83
|
* state.
|
|
84
84
|
*
|
|
85
85
|
* - `url` set → embed it verbatim (tunnel mode's `vscode.dev` URL).
|
|
@@ -98,11 +98,11 @@ interface CodeServerConnect {
|
|
|
98
98
|
value: string;
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
|
-
/** Result of the `status` query
|
|
101
|
+
/** Result of the `status` query: shared state plus connect info when running. */
|
|
102
102
|
interface CodeServerStatusResult extends CodeServerSharedState {
|
|
103
103
|
connect?: CodeServerConnect;
|
|
104
104
|
}
|
|
105
|
-
/** Result of the `start` action
|
|
105
|
+
/** Result of the `start` action, identical shape to {@link CodeServerStatusResult}. */
|
|
106
106
|
type CodeServerStartResult = CodeServerStatusResult;
|
|
107
107
|
/** Wire payload for the `start` RPC. */
|
|
108
108
|
interface CodeServerStartRequest {
|
|
@@ -169,7 +169,7 @@ interface CodeServerOptions {
|
|
|
169
169
|
random?: boolean;
|
|
170
170
|
/**
|
|
171
171
|
* Require the trust handshake on the standalone launcher server. Enabled
|
|
172
|
-
* by default
|
|
172
|
+
* by default; `--open` embeds the current OTP in the opened URL, so the
|
|
173
173
|
* tab authenticates automatically without extra prompts. Hosted adapters
|
|
174
174
|
* manage their own auth and ignore this.
|
|
175
175
|
*/
|
package/dist/vite.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devframes/plugin-code-server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.9",
|
|
5
5
|
"description": "Devframe plugin that runs VS Code in the browser as an embedded editor panel.",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"dist"
|
|
41
41
|
],
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
43
|
+
"@devframes/plugin-code-server--assets": "0.9.9",
|
|
44
|
+
"devframe": "0.9.9",
|
|
45
|
+
"vite": "^8.0.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
48
48
|
"@devframes/plugin-code-server--assets": {
|
|
@@ -53,25 +53,25 @@
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"
|
|
57
|
-
"
|
|
56
|
+
"@devframes/vite": "0.9.9",
|
|
57
|
+
"cac": "^7.0.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"@antfu/design": "^0.
|
|
60
|
+
"@antfu/design": "^0.4.0",
|
|
61
|
+
"@devframes/plugin-code-server--assets": "0.9.9",
|
|
61
62
|
"@iconify-json/ph": "^1.2.2",
|
|
62
|
-
"@storybook/addon-docs": "^10.5.
|
|
63
|
-
"@storybook/vue3-vite": "^10.5.
|
|
64
|
-
"@types/node": "^26.
|
|
63
|
+
"@storybook/addon-docs": "^10.5.10",
|
|
64
|
+
"@storybook/vue3-vite": "^10.5.10",
|
|
65
|
+
"@types/node": "^26.4.0",
|
|
65
66
|
"@vitejs/plugin-vue": "^6.0.8",
|
|
66
67
|
"colorjs.io": "^0.7.1",
|
|
67
|
-
"
|
|
68
|
+
"devframe": "0.9.9",
|
|
69
|
+
"storybook": "^10.5.10",
|
|
68
70
|
"tsdown": "^0.22.14",
|
|
69
|
-
"unocss": "^66.
|
|
70
|
-
"vite": "^8.2.
|
|
71
|
-
"vitest": "^4.1.
|
|
72
|
-
"vue": "^3.5.
|
|
73
|
-
"@devframes/plugin-code-server--assets": "0.9.7",
|
|
74
|
-
"devframe": "0.9.7"
|
|
71
|
+
"unocss": "^66.8.1",
|
|
72
|
+
"vite": "^8.2.2",
|
|
73
|
+
"vitest": "^4.1.11",
|
|
74
|
+
"vue": "^3.5.42"
|
|
75
75
|
},
|
|
76
76
|
"scripts": {
|
|
77
77
|
"build": "tsdown && vite build --config src/spa/vite.config.ts",
|