@filsilva/helios-cli 0.10.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/README.md +171 -0
- package/bin/helios.js +34 -0
- package/dist/client/assets/HeliosSessionWorker.browser-BYYjDIKH.js +3 -0
- package/dist/client/assets/HeliosSessionWorker.browser-BYYjDIKH.js.map +1 -0
- package/dist/client/assets/d3force3dWorker-BKANL9of.js +2 -0
- package/dist/client/assets/d3force3dWorker-BKANL9of.js.map +1 -0
- package/dist/client/assets/index-CP7mSmLx.js +9530 -0
- package/dist/client/assets/index-CP7mSmLx.js.map +1 -0
- package/dist/client/assets/layoutWorker-Lc8iIdmf.js +2 -0
- package/dist/client/assets/layoutWorker-Lc8iIdmf.js.map +1 -0
- package/dist/client/index.html +27 -0
- package/package.json +40 -0
- package/skills/helios-cli/SKILL.md +118 -0
- package/skills/helios-cli/references/behaviors.md +47 -0
- package/skills/helios-cli/references/layouts.md +77 -0
- package/skills/helios-cli/references/mappers.md +119 -0
- package/skills/helios-cli/references/metrics.md +83 -0
- package/skills/helios-cli/references/networks.md +53 -0
- package/skills/helios-cli/references/persistence.md +136 -0
- package/skills/helios-cli/references/positions.md +63 -0
- package/skills/helios-cli/references/rendering-export.md +56 -0
- package/skills/helios-cli/references/rpc-methods.md +83 -0
- package/src/cli.js +488 -0
- package/src/client/index.html +27 -0
- package/src/client/main.js +2210 -0
- package/src/daemon/SessionDaemon.js +1065 -0
- package/src/daemon/entry.js +36 -0
- package/src/protocol/jsonl.js +88 -0
- package/src/shared/cliConfig.js +52 -0
- package/src/shared/fileSessionStore.js +202 -0
- package/src/shared/fs.js +59 -0
- package/src/shared/networkFormats.js +55 -0
- package/src/shared/networkInspect.js +81 -0
- package/src/shared/paths.js +43 -0
- package/src/shared/sessionClient.js +88 -0
- package/src/shared/sessionId.js +5 -0
- package/src/shared/sessionRegistry.js +53 -0
- package/src/shared/sessionSurfaces.js +199 -0
- package/vite.config.js +47 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { createJsonLineParser, JsonRpcResponseReader, callJsonRpc } from '../protocol/jsonl.js';
|
|
5
|
+
import { ensureClientBundle, ensureStateDirs } from './fs.js';
|
|
6
|
+
import { packageRoot } from './paths.js';
|
|
7
|
+
import { createSessionId } from './sessionId.js';
|
|
8
|
+
import { listSessionMetas, loadSessionMeta, loadSessionState } from './sessionRegistry.js';
|
|
9
|
+
|
|
10
|
+
const daemonEntryPath = path.join(packageRoot, 'src', 'daemon', 'entry.js');
|
|
11
|
+
|
|
12
|
+
export function normalizeSessionStartConfig(options = {}) {
|
|
13
|
+
return {
|
|
14
|
+
sessionId: options.sessionId ?? createSessionId(),
|
|
15
|
+
mode: options.mode ?? 'server',
|
|
16
|
+
open: options.open === true,
|
|
17
|
+
renderer: options.renderer ?? 'webgpu',
|
|
18
|
+
layout: options.layout ?? 'gpu-force',
|
|
19
|
+
runtime: options.runtime ?? 'cli',
|
|
20
|
+
surface: options.surface ?? null,
|
|
21
|
+
client: options.client ?? null,
|
|
22
|
+
browserChannel: options.browserChannel ?? null,
|
|
23
|
+
storageDir: options.storageDir ? path.resolve(options.storageDir) : (process.env.HELIOS_CLI_STORAGE_DIR ?? null),
|
|
24
|
+
networkPath: options.networkPath ? path.resolve(options.networkPath) : null,
|
|
25
|
+
noGpu: options.noGpu === true,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function waitForSessionMeta(sessionId, { timeoutMs = 30_000, requireBridge = false } = {}) {
|
|
30
|
+
const startedAt = Date.now();
|
|
31
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
32
|
+
const meta = await loadSessionMeta(sessionId);
|
|
33
|
+
if (meta?.status === 'ready' && (!requireBridge || meta.bridgeConnected === true)) return meta;
|
|
34
|
+
if (meta?.status === 'error') {
|
|
35
|
+
throw new Error(meta.lastError ?? `Session ${sessionId} failed to start`);
|
|
36
|
+
}
|
|
37
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
38
|
+
}
|
|
39
|
+
throw new Error(`Timed out waiting for session ${sessionId} to start`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function startSession(options = {}) {
|
|
43
|
+
await ensureStateDirs();
|
|
44
|
+
await ensureClientBundle();
|
|
45
|
+
const config = normalizeSessionStartConfig(options);
|
|
46
|
+
const encoded = Buffer.from(JSON.stringify(config), 'utf8').toString('base64url');
|
|
47
|
+
const child = spawn(process.execPath, [daemonEntryPath, encoded], {
|
|
48
|
+
cwd: packageRoot,
|
|
49
|
+
detached: true,
|
|
50
|
+
stdio: 'ignore',
|
|
51
|
+
});
|
|
52
|
+
child.unref();
|
|
53
|
+
return waitForSessionMeta(config.sessionId, {
|
|
54
|
+
timeoutMs: options.timeoutMs ?? 30_000,
|
|
55
|
+
requireBridge: options.requireBridge ?? (config.mode !== 'server' || config.open === true),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function openRpcSocket(sessionId) {
|
|
60
|
+
const meta = await loadSessionMeta(sessionId);
|
|
61
|
+
if (!meta) throw new Error(`Unknown session ${sessionId}`);
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const socket = net.createConnection(meta.controlSocket, () => resolve({ socket, meta }));
|
|
64
|
+
socket.on('error', reject);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function rpcCall(sessionId, method, params = {}) {
|
|
69
|
+
const { socket } = await openRpcSocket(sessionId);
|
|
70
|
+
const reader = new JsonRpcResponseReader();
|
|
71
|
+
const parser = createJsonLineParser((message) => reader.handleMessage(message));
|
|
72
|
+
socket.setEncoding('utf8');
|
|
73
|
+
socket.on('data', parser);
|
|
74
|
+
try {
|
|
75
|
+
const result = await callJsonRpc(socket, reader, {
|
|
76
|
+
jsonrpc: '2.0',
|
|
77
|
+
id: `${Date.now()}-${Math.random().toString(16).slice(2)}`,
|
|
78
|
+
method,
|
|
79
|
+
params,
|
|
80
|
+
});
|
|
81
|
+
socket.end();
|
|
82
|
+
return result;
|
|
83
|
+
} finally {
|
|
84
|
+
socket.end();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { listSessionMetas, loadSessionMeta, loadSessionState };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { ensureStateDirs, readJsonFile, writeJsonFile } from './fs.js';
|
|
4
|
+
import { sessionMetaPath, sessionStatePath, sessionsDir } from './paths.js';
|
|
5
|
+
|
|
6
|
+
export async function loadSessionMeta(sessionId) {
|
|
7
|
+
return readJsonFile(sessionMetaPath(sessionId), null);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function saveSessionMeta(sessionId, value) {
|
|
11
|
+
await ensureStateDirs();
|
|
12
|
+
await writeJsonFile(sessionMetaPath(sessionId), value);
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function deleteSessionMeta(sessionId) {
|
|
17
|
+
try {
|
|
18
|
+
await fs.unlink(sessionMetaPath(sessionId));
|
|
19
|
+
} catch (error) {
|
|
20
|
+
if (error?.code !== 'ENOENT') throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function loadSessionState(sessionId) {
|
|
25
|
+
return readJsonFile(sessionStatePath(sessionId), null);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function saveSessionState(sessionId, value) {
|
|
29
|
+
await ensureStateDirs();
|
|
30
|
+
await writeJsonFile(sessionStatePath(sessionId), value);
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function deleteSessionState(sessionId) {
|
|
35
|
+
try {
|
|
36
|
+
await fs.unlink(sessionStatePath(sessionId));
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error?.code !== 'ENOENT') throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function listSessionMetas() {
|
|
43
|
+
await ensureStateDirs();
|
|
44
|
+
const entries = await fs.readdir(sessionsDir, { withFileTypes: true });
|
|
45
|
+
const metas = [];
|
|
46
|
+
for (const entry of entries) {
|
|
47
|
+
if (!entry.isFile() || path.extname(entry.name) !== '.json') continue;
|
|
48
|
+
const meta = await readJsonFile(path.join(sessionsDir, entry.name), null);
|
|
49
|
+
if (meta) metas.push(meta);
|
|
50
|
+
}
|
|
51
|
+
metas.sort((a, b) => String(a.sessionId ?? '').localeCompare(String(b.sessionId ?? '')));
|
|
52
|
+
return metas;
|
|
53
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { packageRoot } from './paths.js';
|
|
6
|
+
|
|
7
|
+
export const SESSION_SURFACES = new Set(['server', 'browser', 'managed', 'desktop', 'mac', 'auto']);
|
|
8
|
+
export const HELIOS_MAC_BUNDLE_IDS = ['org.heliosnetwork.HeliosMac', 'io.heliosweb.HeliosMac'];
|
|
9
|
+
export const HELIOS_DESKTOP_BUNDLE_IDS = ['org.heliosnetwork.Helios'];
|
|
10
|
+
|
|
11
|
+
export function normalizeSessionSurface(value) {
|
|
12
|
+
if (value == null) return null;
|
|
13
|
+
const surface = String(value).trim().toLowerCase();
|
|
14
|
+
if (!SESSION_SURFACES.has(surface)) {
|
|
15
|
+
throw new Error(`Unsupported session surface "${value}". Expected one of: ${Array.from(SESSION_SURFACES).join(', ')}`);
|
|
16
|
+
}
|
|
17
|
+
return surface;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function isLocalSessionUrl(value) {
|
|
21
|
+
try {
|
|
22
|
+
const url = new URL(value);
|
|
23
|
+
return (
|
|
24
|
+
(url.protocol === 'http:' || url.protocol === 'https:')
|
|
25
|
+
&& ['127.0.0.1', 'localhost', '::1', '[::1]'].includes(url.hostname)
|
|
26
|
+
);
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function buildMacSessionOpenURL(meta) {
|
|
33
|
+
if (!meta?.sessionId) throw new Error('Cannot open Helios Mac session without a session id.');
|
|
34
|
+
if (!isLocalSessionUrl(meta.url)) throw new Error('Cannot open Helios Mac session without a local session URL.');
|
|
35
|
+
const url = new URL('helios-mac://session/open');
|
|
36
|
+
url.searchParams.set('sessionId', meta.sessionId);
|
|
37
|
+
url.searchParams.set('url', meta.url);
|
|
38
|
+
return url.toString();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function buildDesktopSessionOpenURL(meta) {
|
|
42
|
+
if (!meta?.sessionId) throw new Error('Cannot open Helios Desktop session without a session id.');
|
|
43
|
+
if (!isLocalSessionUrl(meta.url)) throw new Error('Cannot open Helios Desktop session without a local session URL.');
|
|
44
|
+
const url = new URL('helios-desktop://session/open');
|
|
45
|
+
url.searchParams.set('sessionId', meta.sessionId);
|
|
46
|
+
url.searchParams.set('url', meta.url);
|
|
47
|
+
return url.toString();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function appPathExists(appPath) {
|
|
51
|
+
if (!appPath) return false;
|
|
52
|
+
try {
|
|
53
|
+
const stat = await fs.stat(appPath);
|
|
54
|
+
return stat.isDirectory() || stat.isFile();
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function macAppPathExists(appPath) {
|
|
61
|
+
if (!appPath) return false;
|
|
62
|
+
try {
|
|
63
|
+
const stat = await fs.stat(appPath);
|
|
64
|
+
return stat.isDirectory();
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function runProbe(command, args) {
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
const child = spawn(command, args, { stdio: 'ignore' });
|
|
73
|
+
child.on('error', () => resolve(false));
|
|
74
|
+
child.on('close', (code) => resolve(code === 0));
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function runDetached(command, args) {
|
|
79
|
+
return new Promise((resolve) => {
|
|
80
|
+
const child = spawn(command, args, {
|
|
81
|
+
detached: true,
|
|
82
|
+
stdio: 'ignore',
|
|
83
|
+
windowsHide: false,
|
|
84
|
+
});
|
|
85
|
+
child.on('error', () => resolve(false));
|
|
86
|
+
child.on('spawn', () => {
|
|
87
|
+
child.unref();
|
|
88
|
+
resolve(true);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function findRegisteredMacBundleId(bundleIds = HELIOS_MAC_BUNDLE_IDS) {
|
|
94
|
+
if (process.platform !== 'darwin') return null;
|
|
95
|
+
for (const bundleId of bundleIds) {
|
|
96
|
+
const query = `kMDItemCFBundleIdentifier == '${bundleId}'`;
|
|
97
|
+
const found = await new Promise((resolve) => {
|
|
98
|
+
const child = spawn('mdfind', [query], { stdio: ['ignore', 'pipe', 'ignore'] });
|
|
99
|
+
let output = '';
|
|
100
|
+
child.stdout.setEncoding('utf8');
|
|
101
|
+
child.stdout.on('data', (chunk) => { output += chunk; });
|
|
102
|
+
child.on('error', () => resolve(false));
|
|
103
|
+
child.on('close', (code) => resolve(code === 0 && output.trim().length > 0));
|
|
104
|
+
});
|
|
105
|
+
if (found) return bundleId;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function firstExistingPath(candidates) {
|
|
111
|
+
for (const candidate of candidates.filter(Boolean)) {
|
|
112
|
+
if (await appPathExists(candidate)) return candidate;
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function findDesktopAppPath() {
|
|
118
|
+
const envPath = process.env.HELIOS_DESKTOP_APP_PATH;
|
|
119
|
+
if (envPath && await appPathExists(envPath)) return envPath;
|
|
120
|
+
|
|
121
|
+
const home = os.homedir();
|
|
122
|
+
const repoRoot = path.resolve(packageRoot, '..');
|
|
123
|
+
const arch = os.arch() === 'arm64' ? 'arm64' : 'x64';
|
|
124
|
+
|
|
125
|
+
if (process.platform === 'darwin') {
|
|
126
|
+
const otherArch = arch === 'arm64' ? 'x64' : 'arm64';
|
|
127
|
+
return firstExistingPath([
|
|
128
|
+
path.join(home, 'Applications', 'Helios.app'),
|
|
129
|
+
'/Applications/Helios.app',
|
|
130
|
+
path.join(repoRoot, 'helios-desktop', 'dist', `osx-${arch}`, 'Helios.app'),
|
|
131
|
+
path.join(repoRoot, 'helios-desktop', 'dist', `osx-${otherArch}`, 'Helios.app'),
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
if (process.platform === 'win32') {
|
|
135
|
+
return firstExistingPath([
|
|
136
|
+
path.join(repoRoot, 'helios-desktop', 'dist', 'win-x64', 'Helios.exe'),
|
|
137
|
+
process.env.LOCALAPPDATA ? path.join(process.env.LOCALAPPDATA, 'Programs', 'Helios', 'Helios.exe') : null,
|
|
138
|
+
process.env.ProgramFiles ? path.join(process.env.ProgramFiles, 'Helios', 'Helios.exe') : null,
|
|
139
|
+
process.env['ProgramFiles(x86)'] ? path.join(process.env['ProgramFiles(x86)'], 'Helios', 'Helios.exe') : null,
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
return firstExistingPath([
|
|
143
|
+
path.join(repoRoot, 'helios-desktop', 'dist', 'linux-x64', 'Helios'),
|
|
144
|
+
'/usr/local/bin/Helios',
|
|
145
|
+
'/usr/bin/Helios',
|
|
146
|
+
]);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function desktopLaunchCommand(appPath, sessionURL) {
|
|
150
|
+
if (!appPath) throw new Error('Cannot launch Helios Desktop without an app path.');
|
|
151
|
+
if (process.platform === 'darwin' && /\.app$/iu.test(appPath)) {
|
|
152
|
+
return {
|
|
153
|
+
command: 'open',
|
|
154
|
+
args: ['-n', '-a', appPath, '--args', '--helios-cli-session', sessionURL],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
command: appPath,
|
|
159
|
+
args: ['--helios-cli-session', sessionURL],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export async function launchDesktopSession(meta, { appPath = null } = {}) {
|
|
164
|
+
if (!(await appPathExists(appPath))) {
|
|
165
|
+
throw new Error(`Helios Desktop app was not found at ${appPath}`);
|
|
166
|
+
}
|
|
167
|
+
const sessionURL = buildDesktopSessionOpenURL(meta);
|
|
168
|
+
const { command, args } = desktopLaunchCommand(appPath, sessionURL);
|
|
169
|
+
const launched = command === 'open'
|
|
170
|
+
? await runProbe(command, args)
|
|
171
|
+
: await runDetached(command, args);
|
|
172
|
+
if (!launched) {
|
|
173
|
+
throw new Error(`Unable to open Helios Desktop at ${appPath}. Check the path or run "helios config set desktop.appPath <path>".`);
|
|
174
|
+
}
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export async function launchMacSession(meta, { appPath = null, bundleId = null } = {}) {
|
|
179
|
+
if (process.platform !== 'darwin') {
|
|
180
|
+
throw new Error('Helios Mac sessions are only supported on macOS.');
|
|
181
|
+
}
|
|
182
|
+
const sessionURL = buildMacSessionOpenURL(meta);
|
|
183
|
+
if (appPath) {
|
|
184
|
+
if (!(await macAppPathExists(appPath))) {
|
|
185
|
+
throw new Error(`Helios Mac app was not found at ${appPath}`);
|
|
186
|
+
}
|
|
187
|
+
return runProbe('open', ['-n', '-a', appPath, sessionURL]);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const resolvedBundleId = bundleId ?? await findRegisteredMacBundleId();
|
|
191
|
+
if (!resolvedBundleId) {
|
|
192
|
+
throw new Error('HeliosWeb is not registered. Build or install HeliosWeb.app, or pass --app-path /path/to/HeliosWeb.app.');
|
|
193
|
+
}
|
|
194
|
+
const opened = await runProbe('open', ['-b', resolvedBundleId, sessionURL]);
|
|
195
|
+
if (!opened) {
|
|
196
|
+
throw new Error(`Unable to open HeliosWeb using bundle id ${resolvedBundleId}. Pass --app-path /path/to/HeliosWeb.app for a development build.`);
|
|
197
|
+
}
|
|
198
|
+
return true;
|
|
199
|
+
}
|
package/vite.config.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
|
|
11
|
+
function resolveHeliosWebSource() {
|
|
12
|
+
const localSource = resolve(__dirname, '../helios-web-next/src/index.js');
|
|
13
|
+
if (fs.existsSync(localSource)) return localSource;
|
|
14
|
+
try {
|
|
15
|
+
const packageJsonPath = require.resolve('helios-web/package.json');
|
|
16
|
+
const packageRoot = dirname(packageJsonPath);
|
|
17
|
+
const packageSource = resolve(packageRoot, 'src/index.js');
|
|
18
|
+
if (fs.existsSync(packageSource)) return packageSource;
|
|
19
|
+
} catch (_) {
|
|
20
|
+
// Fall through to package export resolution.
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const heliosWebSource = resolveHeliosWebSource();
|
|
26
|
+
|
|
27
|
+
export default defineConfig({
|
|
28
|
+
root: resolve(__dirname, 'src/client'),
|
|
29
|
+
base: '/',
|
|
30
|
+
assetsInclude: ['**/*.wasm'],
|
|
31
|
+
build: {
|
|
32
|
+
outDir: resolve(__dirname, 'dist/client'),
|
|
33
|
+
emptyOutDir: true,
|
|
34
|
+
sourcemap: true,
|
|
35
|
+
},
|
|
36
|
+
worker: {
|
|
37
|
+
format: 'es',
|
|
38
|
+
},
|
|
39
|
+
resolve: {
|
|
40
|
+
alias: heliosWebSource ? { 'helios-web': heliosWebSource } : {},
|
|
41
|
+
preserveSymlinks: true,
|
|
42
|
+
dedupe: ['helios-network'],
|
|
43
|
+
},
|
|
44
|
+
optimizeDeps: {
|
|
45
|
+
exclude: ['helios-network'],
|
|
46
|
+
},
|
|
47
|
+
});
|