@velarscript/desktop 0.10.1

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.
@@ -0,0 +1,1967 @@
1
+ import { optionalOf } from "@velarscript/compiler";
2
+ import { VELAR_STRICT_JSON_RUNTIME, VELAR_TYPE_REGISTRY_RUNTIME, VELAR_UTF8_RUNTIME } from "@velarscript/compiler/extension";
3
+ import { velarCompilerExtension as webCompilerExtension, webModuleSource } from "@velarscript/web/compiler";
4
+ import { nodeModuleInterfaces, VELAR_NODE_API_VERSION, VELAR_PROCESS_HOST_RUNTIME } from "@velarscript/node/compiler";
5
+ import { VELAR_DESKTOP_API_VERSION, velarProjectExtension } from "./config.js";
6
+ const stringType = { kind: "string" };
7
+ const boolType = { kind: "bool" };
8
+ const numberType = { kind: "number" };
9
+ const nullType = { kind: "null" };
10
+ const optionalStringType = optionalOf(stringType);
11
+ const optionalNumberType = optionalOf(numberType);
12
+ const listStringType = { kind: "list", element: stringType };
13
+ function functionType(parameters, result, requiredParameters = parameters.length) {
14
+ return { kind: "function", parameters, requiredParameters, result };
15
+ }
16
+ function moduleInterface(exports, namedTypes = new Map(), namedTypeIdentities = new Map(), enums = new Map()) {
17
+ return {
18
+ exports,
19
+ mutableExports: new Set(),
20
+ reactiveExports: new Map(),
21
+ reExports: new Map(),
22
+ namedTypes,
23
+ namedTypeIdentities,
24
+ typeAliases: new Map(),
25
+ enums,
26
+ classes: new Map(),
27
+ tests: [],
28
+ extensionExports: new Map(),
29
+ extensionData: new Map(),
30
+ };
31
+ }
32
+ // D60 rule 153: a capability fails where it is *used*, never where it is
33
+ // imported. The bridge is still captured while the module initializes, so a
34
+ // later write to globalThis cannot substitute one -- only the report of its
35
+ // absence moves to the call. Module initialization that threw punished code
36
+ // that never called the capability: a pure function written beside a
37
+ // `velar/desktop` import could not be loaded by a non-browser `velar test`,
38
+ // which made the language demand a file split for testability. This mirrors
39
+ // what velar/storage already does on the Web side.
40
+ const DESKTOP_HOST_ABI_RUNTIME = String.raw `
41
+ const __velarDesktopBridgeKey = Symbol.for("velar.desktop.bridge.v1");
42
+ const __velarDesktopGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
43
+ const __velarDesktopReflectApply = Reflect.apply;
44
+ const __velarDesktopBridgeDescriptor = __velarDesktopGetOwnPropertyDescriptor(globalThis, __velarDesktopBridgeKey);
45
+ const __velarDesktopBridge = __velarDesktopBridgeDescriptor && "value" in __velarDesktopBridgeDescriptor
46
+ && __velarDesktopBridgeDescriptor.value && typeof __velarDesktopBridgeDescriptor.value === "object"
47
+ ? __velarDesktopBridgeDescriptor.value
48
+ : null;
49
+ const __velarDesktopInvokeDescriptor = __velarDesktopBridge === null
50
+ ? null
51
+ : __velarDesktopGetOwnPropertyDescriptor(__velarDesktopBridge, "invoke");
52
+ const __velarDesktopInvoke = __velarDesktopInvokeDescriptor && "value" in __velarDesktopInvokeDescriptor
53
+ && typeof __velarDesktopInvokeDescriptor.value === "function"
54
+ ? __velarDesktopInvokeDescriptor.value
55
+ : null;
56
+ function __velarDesktopRequireBridge() {
57
+ if (__velarDesktopBridge === null) throw new Error("VelarScript Desktop bridge is unavailable");
58
+ if (__velarDesktopInvoke === null) throw new TypeError("Desktop bridge invoke must be a function data value");
59
+ return __velarDesktopBridge;
60
+ }
61
+ function __velarDesktopHostField(name) {
62
+ const descriptor = __velarDesktopGetOwnPropertyDescriptor(__velarDesktopRequireBridge(), name);
63
+ if (!descriptor || !("value" in descriptor)) throw new TypeError("Desktop bridge field '" + name + "' must be a data value");
64
+ return descriptor.value;
65
+ }
66
+ function __velarDesktopHostCall(capability, operation, args, timeout = 30000) {
67
+ const bridge = __velarDesktopRequireBridge();
68
+ return __velarDesktopReflectApply(__velarDesktopInvoke, bridge, [capability, operation, args, timeout]);
69
+ }
70
+ `.trim();
71
+ const languageServerIdentity = "velar/desktop#type:LanguageServer";
72
+ const languageServerType = { kind: "named", name: "LanguageServer", identity: languageServerIdentity };
73
+ const desktopPlatformIdentity = "velar/desktop#enum:DesktopPlatform";
74
+ const desktopPlatforms = new Set(["macos", "test"]);
75
+ const desktopPlatformType = { kind: "enum", name: "DesktopPlatform", identity: desktopPlatformIdentity };
76
+ const projectTaskIdentity = "velar/desktop#type:ProjectTask";
77
+ const projectTaskType = { kind: "named", name: "ProjectTask", identity: projectTaskIdentity };
78
+ const projectTaskCommandIdentity = "velar/desktop#enum:ProjectTaskCommand";
79
+ const projectTaskCommands = new Set(["check", "test", "browserTest", "build", "fix", "package", "run"]);
80
+ const projectTaskCommandType = { kind: "enum", name: "ProjectTaskCommand", identity: projectTaskCommandIdentity };
81
+ const projectTaskOutputChannelIdentity = "velar/desktop#enum:ProjectTaskOutputChannel";
82
+ const projectTaskOutputChannels = new Set(["stdout", "stderr"]);
83
+ const projectTaskOutputChannelType = { kind: "enum", name: "ProjectTaskOutputChannel", identity: projectTaskOutputChannelIdentity };
84
+ const projectTaskResultType = { kind: "object", fields: new Map([
85
+ ["code", optionalNumberType],
86
+ ["signal", optionalStringType],
87
+ ["stdout", stringType],
88
+ ["stderr", stringType],
89
+ ]) };
90
+ const projectTaskOutputType = { kind: "object", fields: new Map([
91
+ ["channel", projectTaskOutputChannelType],
92
+ ["text", stringType],
93
+ ]) };
94
+ const projectTaskOptionsType = {
95
+ kind: "object",
96
+ fields: new Map([["timeout", numberType], ["maxOutputBytes", numberType]]),
97
+ optionalFields: new Set(["timeout", "maxOutputBytes"]),
98
+ };
99
+ const projectChangesIdentity = "velar/desktop#type:ProjectChanges";
100
+ const projectChangesType = { kind: "named", name: "ProjectChanges", identity: projectChangesIdentity };
101
+ const projectChangeLifecycleIdentity = "velar/desktop#enum:ProjectChangeLifecycle";
102
+ const projectChangeLifecycles = new Set(["prepared", "amended", "validated", "validationFailed", "applied", "rolledBack", "discarded"]);
103
+ const projectChangeLifecycleType = { kind: "enum", name: "ProjectChangeLifecycle", identity: projectChangeLifecycleIdentity };
104
+ const projectChangeRiskIdentity = "velar/desktop#enum:ProjectChangeRisk";
105
+ const projectChangeRisks = new Set(["low", "medium", "high"]);
106
+ const projectChangeRiskType = { kind: "enum", name: "ProjectChangeRisk", identity: projectChangeRiskIdentity };
107
+ const projectChangeIntentType = { kind: "object", fields: new Map([
108
+ ["type", stringType],
109
+ ["path", optionalStringType],
110
+ ["from", optionalStringType],
111
+ ["to", optionalStringType],
112
+ ["targetId", optionalStringType],
113
+ ["reason", optionalStringType],
114
+ ]) };
115
+ const projectChangePatchType = { kind: "object", fields: new Map([
116
+ ["patchId", stringType],
117
+ ["strategyId", stringType],
118
+ ["path", stringType],
119
+ ["baseRevision", optionalStringType],
120
+ ["diff", stringType],
121
+ ["changedLines", numberType],
122
+ ["risk", projectChangeRiskType],
123
+ ["operation", optionalStringType],
124
+ ]) };
125
+ const projectChangeRevisionType = { kind: "object", fields: new Map([
126
+ ["path", stringType],
127
+ ["before", optionalStringType],
128
+ ["after", optionalStringType],
129
+ ]) };
130
+ const projectChangeType = { kind: "object", fields: new Map([
131
+ ["transactionId", stringType],
132
+ ["sequence", numberType],
133
+ ["lifecycle", projectChangeLifecycleType],
134
+ ["reason", optionalStringType],
135
+ ["intents", { kind: "list", element: projectChangeIntentType }],
136
+ ["patches", { kind: "list", element: projectChangePatchType }],
137
+ ["changedFiles", listStringType],
138
+ ["diff", stringType],
139
+ ["changedLines", numberType],
140
+ ["risk", projectChangeRiskType],
141
+ ["revisions", { kind: "list", element: projectChangeRevisionType }],
142
+ ["createdAt", numberType],
143
+ ["updatedAt", numberType],
144
+ ["appliedAt", optionalNumberType],
145
+ ]) };
146
+ const projectChangePageType = { kind: "object", fields: new Map([
147
+ ["changes", { kind: "list", element: projectChangeType }],
148
+ ["truncated", boolType],
149
+ ]) };
150
+ const projectChangeUpdateType = { kind: "object", fields: new Map([
151
+ ["changes", { kind: "list", element: projectChangeType }],
152
+ ["rescan", boolType],
153
+ ]) };
154
+ const terminalSessionIdentity = "velar/desktop#type:TerminalSession";
155
+ const terminalSessionType = { kind: "named", name: "TerminalSession", identity: terminalSessionIdentity };
156
+ const terminalResultType = { kind: "object", fields: new Map([["code", numberType]]) };
157
+ const terminalOptionsType = {
158
+ kind: "object",
159
+ fields: new Map([["columns", numberType], ["rows", numberType]]),
160
+ optionalFields: new Set(["columns", "rows"]),
161
+ };
162
+ const desktopModuleInterface = moduleInterface(new Map([
163
+ ["LanguageServer", { kind: "typeObject", name: "LanguageServer" }],
164
+ ["DesktopPlatform", { kind: "enumObject", name: "DesktopPlatform", identity: desktopPlatformIdentity, members: desktopPlatforms }],
165
+ ["ProjectTask", { kind: "typeObject", name: "ProjectTask" }],
166
+ ["ProjectTaskCommand", { kind: "enumObject", name: "ProjectTaskCommand", identity: projectTaskCommandIdentity, members: projectTaskCommands }],
167
+ ["ProjectTaskOutputChannel", { kind: "enumObject", name: "ProjectTaskOutputChannel", identity: projectTaskOutputChannelIdentity, members: projectTaskOutputChannels }],
168
+ ["ProjectChanges", { kind: "typeObject", name: "ProjectChanges" }],
169
+ ["ProjectChangeLifecycle", { kind: "enumObject", name: "ProjectChangeLifecycle", identity: projectChangeLifecycleIdentity, members: projectChangeLifecycles }],
170
+ ["ProjectChangeRisk", { kind: "enumObject", name: "ProjectChangeRisk", identity: projectChangeRiskIdentity, members: projectChangeRisks }],
171
+ ["TerminalSession", { kind: "typeObject", name: "TerminalSession" }],
172
+ ["platform", functionType([], desktopPlatformType)],
173
+ ["packaged", functionType([], boolType)],
174
+ ["homeDirectory", functionType([], { kind: "promise", value: stringType })],
175
+ ["appDataDirectory", functionType([], { kind: "promise", value: stringType })],
176
+ ["projectDirectory", functionType([], { kind: "promise", value: stringType })],
177
+ ["selectedProjectDirectory", functionType([], { kind: "promise", value: optionalStringType })],
178
+ ["selectProjectDirectory", functionType([], { kind: "promise", value: optionalStringType })],
179
+ ["languageServer", functionType([], { kind: "promise", value: languageServerType })],
180
+ ["projectChanges", functionType([], { kind: "promise", value: projectChangesType })],
181
+ ["startProjectTask", functionType([projectTaskCommandType, listStringType, projectTaskOptionsType], { kind: "promise", value: projectTaskType }, 1)],
182
+ ["openTerminal", functionType([terminalOptionsType], { kind: "promise", value: terminalSessionType }, 0)],
183
+ ]), new Map([
184
+ ["LanguageServer", new Map([
185
+ ["send", functionType([stringType], { kind: "promise", value: nullType })],
186
+ ["next", functionType([], { kind: "promise", value: optionalStringType })],
187
+ ["close", functionType([], { kind: "promise", value: nullType })],
188
+ ])],
189
+ ["ProjectTask", new Map([
190
+ ["pid", numberType],
191
+ ["next", functionType([], { kind: "promise", value: optionalOf(projectTaskOutputType) })],
192
+ ["wait", functionType([], { kind: "promise", value: projectTaskResultType })],
193
+ ["stop", functionType([], { kind: "promise", value: nullType })],
194
+ ])],
195
+ ["ProjectChanges", new Map([
196
+ ["list", functionType([numberType], { kind: "promise", value: projectChangePageType }, 0)],
197
+ ["get", functionType([stringType], { kind: "promise", value: optionalOf(projectChangeType) })],
198
+ ["subscribe", functionType([], { kind: "promise", value: optionalOf(projectChangeUpdateType) })],
199
+ ["apply", functionType([stringType], { kind: "promise", value: projectChangeType })],
200
+ ["rollback", functionType([stringType], { kind: "promise", value: projectChangeType })],
201
+ ["close", functionType([], { kind: "promise", value: nullType })],
202
+ ])],
203
+ ["TerminalSession", new Map([
204
+ ["pid", numberType],
205
+ ["write", functionType([stringType], { kind: "promise", value: nullType })],
206
+ ["resize", functionType([numberType, numberType], { kind: "promise", value: nullType })],
207
+ ["next", functionType([], { kind: "promise", value: optionalStringType })],
208
+ ["wait", functionType([], { kind: "promise", value: terminalResultType })],
209
+ ["close", functionType([], { kind: "promise", value: nullType })],
210
+ ])],
211
+ ]), new Map([
212
+ ["LanguageServer", languageServerIdentity],
213
+ ["ProjectTask", projectTaskIdentity],
214
+ ["ProjectChanges", projectChangesIdentity],
215
+ ["TerminalSession", terminalSessionIdentity],
216
+ ]), new Map([
217
+ ["DesktopPlatform", { identity: desktopPlatformIdentity, members: desktopPlatforms }],
218
+ ["ProjectTaskCommand", { identity: projectTaskCommandIdentity, members: projectTaskCommands }],
219
+ ["ProjectTaskOutputChannel", { identity: projectTaskOutputChannelIdentity, members: projectTaskOutputChannels }],
220
+ ["ProjectChangeLifecycle", { identity: projectChangeLifecycleIdentity, members: projectChangeLifecycles }],
221
+ ["ProjectChangeRisk", { identity: projectChangeRiskIdentity, members: projectChangeRisks }],
222
+ ]));
223
+ const desktopTestModuleInterface = moduleInterface(new Map([
224
+ ["setPlatform", functionType([desktopPlatformType], { kind: "promise", value: nullType })],
225
+ ["appDataDirectory", functionType([], { kind: "promise", value: stringType })],
226
+ ["projectDirectory", functionType([], { kind: "promise", value: stringType })],
227
+ ["seedProjectChange", functionType([stringType, stringType, stringType], { kind: "promise", value: nullType })],
228
+ ["makeDirectory", functionType([stringType], { kind: "promise", value: nullType })],
229
+ ["readText", functionType([stringType, { kind: "number" }], { kind: "promise", value: stringType })],
230
+ ["writeText", functionType([stringType, stringType], { kind: "promise", value: nullType })],
231
+ ["removeFile", functionType([stringType], { kind: "promise", value: nullType })],
232
+ ]));
233
+ const nodeProcessInterface = nodeModuleInterfaces.get("velar/process");
234
+ const desktopProcessInterface = nodeProcessInterface;
235
+ const DESKTOP_MODULE_SOURCE = String.raw `
236
+ ${DESKTOP_HOST_ABI_RUNTIME}
237
+ ${VELAR_TYPE_REGISTRY_RUNTIME}
238
+ ${VELAR_UTF8_RUNTIME}
239
+ ${VELAR_PROCESS_HOST_RUNTIME}
240
+ const languageServerToken = Symbol("velar.desktop.language-server");
241
+ const projectTaskToken = Symbol("velar.desktop.project-task");
242
+ const projectChangesToken = Symbol("velar.desktop.project-changes");
243
+ const terminalSessionToken = Symbol("velar.desktop.terminal-session");
244
+ export const DesktopPlatform = __velarRegisterRuntimeType(__velarProcessFreeze({
245
+ macos: "macos", test: "test",
246
+ is(value) { return value === "macos" || value === "test"; },
247
+ parse(value) {
248
+ if (!DesktopPlatform.is(value)) throw new __velarProcessNativeTypeError("Value does not match DesktopPlatform");
249
+ return value;
250
+ },
251
+ values() { return ["macos", "test"]; },
252
+ }));
253
+ export function platform() {
254
+ return DesktopPlatform.parse(__velarDesktopHostField("platform"));
255
+ }
256
+ export function packaged() {
257
+ const value = __velarDesktopHostField("packaged");
258
+ if (typeof value !== "boolean") throw new TypeError("Desktop host returned an invalid packaged marker");
259
+ return value;
260
+ }
261
+ async function path(operation) {
262
+ const value = await __velarDesktopHostCall("desktop", operation, []);
263
+ if (typeof value !== "string" || !value.startsWith("/") || value.length > 4096 || value.includes("\0")) throw new TypeError("Desktop host returned an invalid absolute path");
264
+ return value;
265
+ }
266
+ async function optionalPath(operation, timeout = 30000) {
267
+ const value = await __velarDesktopHostCall("desktop", operation, [], timeout);
268
+ if (value === null) return null;
269
+ if (typeof value !== "string" || !value.startsWith("/") || value.length > 4096 || value.includes("\0")) throw new TypeError("Desktop host returned an invalid optional project path");
270
+ return value;
271
+ }
272
+ export async function homeDirectory() { return path("homeDirectory"); }
273
+ export async function appDataDirectory() { return path("appDataDirectory"); }
274
+ export async function projectDirectory() { return path("projectDirectory"); }
275
+ export async function selectedProjectDirectory() { return optionalPath("selectedProjectDirectory"); }
276
+ export async function selectProjectDirectory() { return optionalPath("selectProjectDirectory", 0); }
277
+ class LanguageServerHandle {
278
+ constructor(token, handle) {
279
+ if (token !== languageServerToken || !Number.isSafeInteger(handle) || handle < 1) throw new TypeError("LanguageServer values are created only by velar/desktop.languageServer");
280
+ this.handle = handle;
281
+ this.closed = false;
282
+ this.reading = false;
283
+ }
284
+ async send(message) {
285
+ if (this.closed) throw new Error("LanguageServer is closed");
286
+ if (typeof message !== "string" || message.length === 0 || message.length > 16 * 1024 * 1024) throw new RangeError("LanguageServer.send requires bounded JSON text");
287
+ const value = await __velarDesktopHostCall("language-server", "send", [this.handle, message]);
288
+ if (value !== null) throw new TypeError("Desktop host returned an invalid language-server send result");
289
+ return null;
290
+ }
291
+ async next() {
292
+ if (this.closed) return null;
293
+ if (this.reading) throw new Error("LanguageServer.next already has an active pull");
294
+ this.reading = true;
295
+ try {
296
+ const value = await __velarDesktopHostCall("language-server", "next", [this.handle], 0);
297
+ if (value === null) { this.closed = true; return null; }
298
+ if (typeof value !== "string" || value.length === 0 || value.length > 16 * 1024 * 1024) throw new TypeError("Desktop host returned invalid language-server JSON text");
299
+ return value;
300
+ } finally {
301
+ this.reading = false;
302
+ }
303
+ }
304
+ async close() {
305
+ if (this.closed) return null;
306
+ const value = await __velarDesktopHostCall("language-server", "close", [this.handle], 10000);
307
+ if (value !== null) throw new TypeError("Desktop host returned an invalid language-server close result");
308
+ this.closed = true;
309
+ return null;
310
+ }
311
+ }
312
+ export const LanguageServer = Object.freeze({
313
+ is(value) { return value instanceof LanguageServerHandle; },
314
+ parse(value) { if (!(value instanceof LanguageServerHandle)) throw new TypeError("Value does not match LanguageServer"); return value; },
315
+ });
316
+ export async function languageServer() {
317
+ const handle = await __velarDesktopHostCall("language-server", "start", []);
318
+ return new LanguageServerHandle(languageServerToken, handle);
319
+ }
320
+ const projectChangeIntentFields = new __velarProcessNativeSet(["type", "path", "from", "to", "targetId", "reason"]);
321
+ const projectChangePatchFields = new __velarProcessNativeSet(["patchId", "strategyId", "path", "baseRevision", "diff", "changedLines", "risk", "operation"]);
322
+ const projectChangeRevisionFields = new __velarProcessNativeSet(["path", "before", "after"]);
323
+ const projectChangeFields = new __velarProcessNativeSet([
324
+ "transactionId", "sequence", "lifecycle", "reason", "intents", "patches", "changedFiles", "diff", "changedLines", "risk",
325
+ "revisions", "createdAt", "updatedAt", "appliedAt",
326
+ ]);
327
+ const projectChangePageFields = new __velarProcessNativeSet(["changes", "truncated"]);
328
+ const projectChangeUpdateFields = new __velarProcessNativeSet(["changes", "rescan"]);
329
+ export const ProjectChangeLifecycle = __velarRegisterRuntimeType(__velarProcessFreeze({
330
+ prepared: "prepared", amended: "amended", validated: "validated", validationFailed: "validationFailed", applied: "applied", rolledBack: "rolledBack", discarded: "discarded",
331
+ is(value) {
332
+ return value === "prepared" || value === "amended" || value === "validated" || value === "validationFailed"
333
+ || value === "applied" || value === "rolledBack" || value === "discarded";
334
+ },
335
+ parse(value) {
336
+ if (!ProjectChangeLifecycle.is(value)) throw new __velarProcessNativeTypeError("Value does not match ProjectChangeLifecycle");
337
+ return value;
338
+ },
339
+ values() { return ["prepared", "amended", "validated", "validationFailed", "applied", "rolledBack", "discarded"]; },
340
+ }));
341
+ export const ProjectChangeRisk = __velarRegisterRuntimeType(__velarProcessFreeze({
342
+ low: "low", medium: "medium", high: "high",
343
+ is(value) { return value === "low" || value === "medium" || value === "high"; },
344
+ parse(value) {
345
+ if (!ProjectChangeRisk.is(value)) throw new __velarProcessNativeTypeError("Value does not match ProjectChangeRisk");
346
+ return value;
347
+ },
348
+ values() { return ["low", "medium", "high"]; },
349
+ }));
350
+ function projectChangeText(value, name, maximumBytes, allowEmpty = false) {
351
+ if (typeof value !== "string" || !allowEmpty && value.length === 0 || __velarProcessIncludes(value, "\0")) {
352
+ throw new __velarProcessNativeTypeError(name + " must be bounded text");
353
+ }
354
+ const bytes = __velarUtf8ByteLength(value);
355
+ if (bytes > maximumBytes) throw new __velarProcessNativeRangeError(name + " exceeds its supported bound");
356
+ return {value, bytes};
357
+ }
358
+ function projectChangeOptionalText(value, name, maximumBytes) {
359
+ return value == null ? {value: null, bytes: 0} : projectChangeText(value, name, maximumBytes);
360
+ }
361
+ function projectChangeInteger(value, name, minimum = 0) {
362
+ if (!__velarProcessIsSafeInteger(value) || value < minimum) throw new __velarProcessNativeTypeError(name + " must be a non-negative safe integer");
363
+ return value;
364
+ }
365
+ function projectChangeList(value, name, maximumItems, read) {
366
+ if (!__velarProcessIsArray(value) || value.length > maximumItems) throw new __velarProcessNativeTypeError(name + " must be a bounded List");
367
+ const output = new __velarProcessNativeArray(value.length);
368
+ let bytes = 0;
369
+ for (let index = 0; index < value.length; index += 1) {
370
+ const descriptor = __velarProcessOwnDescriptor(value, __velarProcessNativeString(index));
371
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new __velarProcessNativeTypeError(name + " must contain enumerable data values");
372
+ const item = read(descriptor.value, index);
373
+ output[index] = item.value;
374
+ bytes += item.bytes;
375
+ }
376
+ // The hostile host value has already been descriptor-checked and copied.
377
+ // Keep the caller-owned copy as a normal VelarScript List: freezing this
378
+ // fresh array makes the language runtime correctly reject iteration even
379
+ // though no host alias remains to protect.
380
+ return {value: output, bytes};
381
+ }
382
+ function projectChangeIntent(value) {
383
+ value = __velarProcessRecord(value, "Project change intent", projectChangeIntentFields);
384
+ const type = projectChangeText(value.type, "Project change intent type", 128);
385
+ const path = projectChangeOptionalText(value.path, "Project change intent path", 4096);
386
+ const from = projectChangeOptionalText(value.from, "Project change intent source path", 4096);
387
+ const to = projectChangeOptionalText(value.to, "Project change intent target path", 4096);
388
+ const targetId = projectChangeOptionalText(value.targetId, "Project change target id", 512);
389
+ const reason = projectChangeOptionalText(value.reason, "Project change intent reason", 64 * 1024);
390
+ return {
391
+ value: __velarProcessFreeze({type: type.value, path: path.value, from: from.value, to: to.value, targetId: targetId.value, reason: reason.value}),
392
+ bytes: type.bytes + path.bytes + from.bytes + to.bytes + targetId.bytes + reason.bytes,
393
+ };
394
+ }
395
+ function projectChangePatch(value) {
396
+ value = __velarProcessRecord(value, "Project change patch", projectChangePatchFields);
397
+ const patchId = projectChangeText(value.patchId, "Project change patch id", 512);
398
+ const strategyId = projectChangeText(value.strategyId, "Project change strategy id", 512);
399
+ const path = projectChangeText(value.path, "Project change patch path", 4096);
400
+ const baseRevision = projectChangeOptionalText(value.baseRevision, "Project change patch base revision", 512);
401
+ const diff = projectChangeText(value.diff, "Project change patch diff", 16 * 1024 * 1024, true);
402
+ const operation = projectChangeOptionalText(value.operation, "Project change patch operation", 128);
403
+ const risk = ProjectChangeRisk.parse(value.risk);
404
+ const changedLines = projectChangeInteger(value.changedLines, "Project change patch changed lines");
405
+ return {
406
+ value: __velarProcessFreeze({patchId: patchId.value, strategyId: strategyId.value, path: path.value, baseRevision: baseRevision.value, diff: diff.value, changedLines, risk, operation: operation.value}),
407
+ bytes: patchId.bytes + strategyId.bytes + path.bytes + baseRevision.bytes + diff.bytes + operation.bytes,
408
+ };
409
+ }
410
+ function projectChangeRevision(value) {
411
+ value = __velarProcessRecord(value, "Project change revision", projectChangeRevisionFields);
412
+ const path = projectChangeText(value.path, "Project change revision path", 4096);
413
+ const before = projectChangeOptionalText(value.before, "Project change prior revision", 512);
414
+ const after = projectChangeOptionalText(value.after, "Project change next revision", 512);
415
+ return {
416
+ value: __velarProcessFreeze({path: path.value, before: before.value, after: after.value}),
417
+ bytes: path.bytes + before.bytes + after.bytes,
418
+ };
419
+ }
420
+ function projectChangeLifecycle(value) {
421
+ if (value === "prepared" || value === "amended" || value === "validated" || value === "applied" || value === "discarded") return value;
422
+ if (value === "validation_failed") return "validationFailed";
423
+ if (value === "rolled_back") return "rolledBack";
424
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid project change lifecycle");
425
+ }
426
+ function projectChangeValue(value) {
427
+ value = __velarProcessRecord(value, "Project change", projectChangeFields);
428
+ const transactionId = projectChangeText(value.transactionId, "Project change transaction id", 512);
429
+ const reason = projectChangeOptionalText(value.reason, "Project change reason", 64 * 1024);
430
+ const intents = projectChangeList(value.intents, "Project change intents", 1000, projectChangeIntent);
431
+ const patches = projectChangeList(value.patches, "Project change patches", 1000, projectChangePatch);
432
+ const changedFiles = projectChangeList(value.changedFiles, "Project change files", 1000, item => projectChangeText(item, "Project change file path", 4096));
433
+ const diff = projectChangeText(value.diff, "Project change diff", 16 * 1024 * 1024, true);
434
+ const revisions = projectChangeList(value.revisions, "Project change revisions", 1000, projectChangeRevision);
435
+ const bytes = transactionId.bytes + reason.bytes + intents.bytes + patches.bytes + changedFiles.bytes + diff.bytes + revisions.bytes;
436
+ if (bytes > 16 * 1024 * 1024) throw new __velarProcessNativeRangeError("Project change record exceeds 16 MiB");
437
+ const appliedAt = value.appliedAt == null ? null : projectChangeInteger(value.appliedAt, "Project change apply time");
438
+ return {
439
+ value: __velarProcessFreeze({
440
+ transactionId: transactionId.value,
441
+ sequence: projectChangeInteger(value.sequence, "Project change sequence", 1),
442
+ lifecycle: projectChangeLifecycle(value.lifecycle),
443
+ reason: reason.value,
444
+ intents: intents.value,
445
+ patches: patches.value,
446
+ changedFiles: changedFiles.value,
447
+ diff: diff.value,
448
+ changedLines: projectChangeInteger(value.changedLines, "Project change changed lines"),
449
+ risk: ProjectChangeRisk.parse(value.risk),
450
+ revisions: revisions.value,
451
+ createdAt: projectChangeInteger(value.createdAt, "Project change creation time"),
452
+ updatedAt: projectChangeInteger(value.updatedAt, "Project change update time"),
453
+ appliedAt,
454
+ }),
455
+ bytes,
456
+ };
457
+ }
458
+ function projectChangeValues(value, name, maximumItems) {
459
+ return projectChangeList(value, name, maximumItems, projectChangeValue);
460
+ }
461
+ function projectChangePage(value) {
462
+ value = __velarProcessRecord(value, "Project change page", projectChangePageFields);
463
+ const changes = projectChangeValues(value.changes, "Project change page", 100);
464
+ if (changes.bytes > 32 * 1024 * 1024 || typeof value.truncated !== "boolean") {
465
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid project change page");
466
+ }
467
+ return __velarProcessFreeze({changes: changes.value, truncated: value.truncated});
468
+ }
469
+ function projectChangeUpdate(value) {
470
+ value = __velarProcessRecord(value, "Project change update", projectChangeUpdateFields);
471
+ const changes = projectChangeValues(value.changes, "Project change update", 100);
472
+ if (changes.bytes > 16 * 1024 * 1024 || typeof value.rescan !== "boolean") {
473
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid project change update");
474
+ }
475
+ return __velarProcessFreeze({changes: changes.value, rescan: value.rescan});
476
+ }
477
+ function projectChangeId(value) {
478
+ return projectChangeText(value, "Project change transaction id", 512).value;
479
+ }
480
+ class ProjectChangesHandle {
481
+ constructor(token, handle) {
482
+ if (token !== projectChangesToken || !__velarProcessIsSafeInteger(handle) || handle < 1) {
483
+ throw new __velarProcessNativeTypeError("ProjectChanges values are created only by velar/desktop.projectChanges");
484
+ }
485
+ this.handle = handle;
486
+ this.closed = false;
487
+ this.reading = false;
488
+ __velarProcessSeal(this);
489
+ }
490
+ async list(limit = 50) {
491
+ if (this.closed) throw new __velarProcessNativeError("ProjectChanges is closed");
492
+ if (!__velarProcessIsSafeInteger(limit) || limit < 1 || limit > 100) throw new __velarProcessNativeRangeError("ProjectChanges.list limit must be an integer from 1 through 100");
493
+ return projectChangePage(await __velarDesktopHostCall("project-changes", "list", [this.handle, limit]));
494
+ }
495
+ async get(transactionId) {
496
+ if (this.closed) throw new __velarProcessNativeError("ProjectChanges is closed");
497
+ const value = await __velarDesktopHostCall("project-changes", "get", [this.handle, projectChangeId(transactionId)]);
498
+ return value === null ? null : projectChangeValue(value).value;
499
+ }
500
+ async subscribe() {
501
+ if (this.closed) return null;
502
+ if (this.reading) throw new __velarProcessNativeError("ProjectChanges.subscribe() allows only one active pull");
503
+ this.reading = true;
504
+ try {
505
+ const value = await __velarDesktopHostCall("project-changes", "subscribe", [this.handle], 0);
506
+ if (value === null) { this.closed = true; return null; }
507
+ return projectChangeUpdate(value);
508
+ } finally { this.reading = false; }
509
+ }
510
+ async apply(transactionId) {
511
+ if (this.closed) throw new __velarProcessNativeError("ProjectChanges is closed");
512
+ return projectChangeValue(await __velarDesktopHostCall("project-changes", "apply", [this.handle, projectChangeId(transactionId)], 0)).value;
513
+ }
514
+ async rollback(transactionId) {
515
+ if (this.closed) throw new __velarProcessNativeError("ProjectChanges is closed");
516
+ return projectChangeValue(await __velarDesktopHostCall("project-changes", "rollback", [this.handle, projectChangeId(transactionId)], 0)).value;
517
+ }
518
+ async close() {
519
+ if (this.closed) return null;
520
+ const value = await __velarDesktopHostCall("project-changes", "close", [this.handle], 10000);
521
+ if (value !== null) throw new __velarProcessNativeTypeError("Desktop host returned an invalid ProjectChanges close result");
522
+ this.closed = true;
523
+ return null;
524
+ }
525
+ }
526
+ export const ProjectChanges = __velarProcessFreeze({
527
+ is(value) { return value instanceof ProjectChangesHandle; },
528
+ parse(value) {
529
+ if (!(value instanceof ProjectChangesHandle)) throw new __velarProcessNativeTypeError("Value does not match ProjectChanges");
530
+ return value;
531
+ },
532
+ });
533
+ export async function projectChanges() {
534
+ const handle = await __velarDesktopHostCall("project-changes", "start", []);
535
+ return new ProjectChangesHandle(projectChangesToken, handle);
536
+ }
537
+ const projectTaskOptionFields = new __velarProcessNativeSet(["timeout", "maxOutputBytes"]);
538
+ const projectTaskStartFields = new __velarProcessNativeSet(["handle", "pid"]);
539
+ const projectTaskOutputFields = new __velarProcessNativeSet(["channel", "text"]);
540
+ const projectTaskResultFields = new __velarProcessNativeSet(["code", "signal", "stdout", "stderr"]);
541
+ const projectTaskErrorFields = new __velarProcessNativeSet(["name", "message"]);
542
+ const projectTaskWaitFields = new __velarProcessNativeSet(["result", "error", "retained"]);
543
+ const projectTaskStopFields = new __velarProcessNativeSet(["result", "error"]);
544
+ export const ProjectTaskCommand = __velarRegisterRuntimeType(__velarProcessFreeze({
545
+ check: "check", test: "test", browserTest: "browserTest", build: "build", fix: "fix", package: "package", run: "run",
546
+ is(value) { return value === "check" || value === "test" || value === "browserTest" || value === "build" || value === "fix" || value === "package" || value === "run"; },
547
+ parse(value) {
548
+ if (!ProjectTaskCommand.is(value)) throw new __velarProcessNativeTypeError("Value does not match ProjectTaskCommand");
549
+ return value;
550
+ },
551
+ // D60 rule 149: values() is the third name charter section 6 reserves on
552
+ // every enum, and it returns a fresh mutable List in declaration order.
553
+ values() { return ["check", "test", "browserTest", "build", "fix", "package", "run"]; },
554
+ }));
555
+ export const ProjectTaskOutputChannel = __velarRegisterRuntimeType(__velarProcessFreeze({
556
+ stdout: "stdout", stderr: "stderr",
557
+ is(value) { return value === "stdout" || value === "stderr"; },
558
+ parse(value) {
559
+ if (!ProjectTaskOutputChannel.is(value)) throw new __velarProcessNativeTypeError("Value does not match ProjectTaskOutputChannel");
560
+ return value;
561
+ },
562
+ values() { return ["stdout", "stderr"]; },
563
+ }));
564
+ function projectTaskArguments(value, command) {
565
+ if (value == null) return [];
566
+ if (!__velarProcessIsArray(value) || value.length > 1000) throw new __velarProcessNativeTypeError("Project task arguments must be a bounded List<string>");
567
+ if (command !== "run" && value.length > 0) throw new __velarProcessNativeTypeError("Only a run project task accepts program arguments");
568
+ let units = 0;
569
+ const output = [];
570
+ for (let index = 0; index < value.length; index += 1) {
571
+ const descriptor = __velarProcessOwnDescriptor(value, __velarProcessNativeString(index));
572
+ const item = descriptor?.enumerable && "value" in descriptor ? descriptor.value : null;
573
+ if (typeof item !== "string" || item.length > 1024 * 1024 || __velarProcessIncludes(item, "\0")) {
574
+ throw new __velarProcessNativeTypeError("Project task arguments must contain bounded string data values");
575
+ }
576
+ units += item.length;
577
+ if (units > 1024 * 1024) throw new __velarProcessNativeRangeError("Project task arguments cannot exceed 1 MiB");
578
+ output[output.length] = item;
579
+ }
580
+ return output;
581
+ }
582
+ function projectTaskOptions(value) {
583
+ value = __velarProcessRecord(value == null ? {} : value, "Project task options", projectTaskOptionFields);
584
+ const timeout = value.timeout ?? 120000;
585
+ const maxOutputBytes = value.maxOutputBytes ?? 4 * 1024 * 1024;
586
+ if (!__velarProcessIsSafeInteger(timeout) || timeout < 0 || timeout > 600000) {
587
+ throw new __velarProcessNativeRangeError("Project task timeout must be an integer from 0 through 600000 milliseconds");
588
+ }
589
+ if (!__velarProcessIsSafeInteger(maxOutputBytes) || maxOutputBytes < 1 || maxOutputBytes > 16 * 1024 * 1024) {
590
+ throw new __velarProcessNativeRangeError("Project task maxOutputBytes must be an integer from 1 through 16777216");
591
+ }
592
+ return {timeout, maxOutputBytes};
593
+ }
594
+ function projectTaskError(value) {
595
+ value = __velarProcessRecord(value, "Project task host error", projectTaskErrorFields);
596
+ if (typeof value.message !== "string" || value.message.length === 0 || value.message.length > 65536
597
+ || value.name !== "Error" && value.name !== "RangeError" && value.name !== "TypeError") {
598
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid project task error");
599
+ }
600
+ if (value.name === "RangeError") return new __velarProcessNativeRangeError(value.message);
601
+ if (value.name === "TypeError") return new __velarProcessNativeTypeError(value.message);
602
+ return new __velarProcessNativeError(value.message);
603
+ }
604
+ function projectTaskResult(value, maxOutputBytes) {
605
+ value = __velarProcessRecord(value, "Project task result", projectTaskResultFields);
606
+ if (value.code !== null && !__velarProcessIsSafeInteger(value.code)
607
+ || value.signal !== null && (typeof value.signal !== "string" || value.signal.length === 0 || value.signal.length > 128)
608
+ || typeof value.stdout !== "string" || typeof value.stderr !== "string"
609
+ || __velarUtf8ByteLength(value.stdout) + __velarUtf8ByteLength(value.stderr) > maxOutputBytes) {
610
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid project task result");
611
+ }
612
+ return __velarProcessFreeze({code: value.code, signal: value.signal, stdout: value.stdout, stderr: value.stderr});
613
+ }
614
+ function projectTaskOutput(value, maxOutputBytes) {
615
+ if (value === null) return null;
616
+ value = __velarProcessRecord(value, "Project task output", projectTaskOutputFields);
617
+ if (!ProjectTaskOutputChannel.is(value.channel) || typeof value.text !== "string" || value.text.length === 0
618
+ || __velarUtf8ByteLength(value.text) > maxOutputBytes) {
619
+ throw new __velarProcessNativeTypeError("Desktop host returned invalid project task output");
620
+ }
621
+ return __velarProcessFreeze({channel: value.channel, text: value.text});
622
+ }
623
+ function projectTaskWait(value, maxOutputBytes) {
624
+ value = __velarProcessRecord(value, "Project task wait result", projectTaskWaitFields);
625
+ if (typeof value.retained !== "boolean" || value.result !== null && value.error !== null
626
+ || value.retained && (value.result !== null || value.error === null)
627
+ || !value.retained && value.result === null && value.error === null) {
628
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid project task wait result");
629
+ }
630
+ return {
631
+ result: value.result === null ? null : projectTaskResult(value.result, maxOutputBytes),
632
+ error: value.error === null ? null : projectTaskError(value.error),
633
+ retained: value.retained,
634
+ };
635
+ }
636
+ function projectTaskStop(value, maxOutputBytes) {
637
+ value = __velarProcessRecord(value, "Project task stop result", projectTaskStopFields);
638
+ if (value.result !== null && value.error !== null) throw new __velarProcessNativeTypeError("Desktop host returned a contradictory project task stop result");
639
+ return {
640
+ result: value.result === null ? null : projectTaskResult(value.result, maxOutputBytes),
641
+ error: value.error === null ? null : projectTaskError(value.error),
642
+ };
643
+ }
644
+ class ProjectTaskHandle {
645
+ constructor(token, handle, pid, maxOutputBytes) {
646
+ if (token !== projectTaskToken || !__velarProcessIsSafeInteger(handle) || handle < 1
647
+ || !__velarProcessIsSafeInteger(pid) || pid < 1) throw new __velarProcessNativeTypeError("ProjectTask values are created only by velar/desktop.startProjectTask");
648
+ this.handle = handle;
649
+ this.pid = pid;
650
+ this.maxOutputBytes = maxOutputBytes;
651
+ this.outputBytes = 0;
652
+ this.reading = false;
653
+ this.waitStarted = false;
654
+ this.stopRequested = false;
655
+ this.result = null;
656
+ __velarProcessSeal(this);
657
+ }
658
+ async next() {
659
+ if (this.waitStarted) throw new __velarProcessNativeError("Project task output must be consumed before wait()");
660
+ if (this.stopRequested) throw new __velarProcessNativeError("Project task output is unavailable after stop()");
661
+ if (this.reading) throw new __velarProcessNativeError("ProjectTask.next() allows only one active pull");
662
+ this.reading = true;
663
+ try {
664
+ const output = projectTaskOutput(await __velarDesktopHostCall("project-task", "read", [this.handle], 0), this.maxOutputBytes);
665
+ if (output !== null) {
666
+ this.outputBytes += __velarUtf8ByteLength(output.text);
667
+ if (this.outputBytes > this.maxOutputBytes) throw new __velarProcessNativeRangeError("Project task output exceeded maxOutputBytes");
668
+ }
669
+ return output;
670
+ } finally { this.reading = false; }
671
+ }
672
+ wait() {
673
+ if (this.reading) return __velarProcessReject(new __velarProcessNativeError("Project task wait() cannot run while next() is pending"));
674
+ this.waitStarted = true;
675
+ if (this.result === null) {
676
+ let pending;
677
+ pending = __velarProcessThen(__velarDesktopHostCall("project-task", "wait", [this.handle], 0), value => {
678
+ const outcome = projectTaskWait(value, this.maxOutputBytes);
679
+ if (outcome.retained) { if (this.result === pending) this.result = null; throw outcome.error; }
680
+ if (outcome.error) throw outcome.error;
681
+ return outcome.result;
682
+ }, error => { if (this.result === pending) this.result = null; throw error; });
683
+ this.result = pending;
684
+ }
685
+ return this.result;
686
+ }
687
+ async stop() {
688
+ if (this.result !== null && this.waitStarted) { await this.result; return null; }
689
+ this.stopRequested = true;
690
+ const outcome = projectTaskStop(await __velarDesktopHostCall("project-task", "stop", [this.handle], 10000), this.maxOutputBytes);
691
+ if (outcome.error) { this.result = __velarProcessObservedReject(outcome.error); throw outcome.error; }
692
+ if (outcome.result) this.result = __velarProcessResolve(outcome.result);
693
+ return null;
694
+ }
695
+ }
696
+ export const ProjectTask = __velarProcessFreeze({
697
+ is(value) { return value instanceof ProjectTaskHandle; },
698
+ parse(value) {
699
+ if (!(value instanceof ProjectTaskHandle)) throw new __velarProcessNativeTypeError("Value does not match ProjectTask");
700
+ return value;
701
+ },
702
+ });
703
+ export async function startProjectTask(command, arguments_ = [], options = {}) {
704
+ command = ProjectTaskCommand.parse(command);
705
+ const args = projectTaskArguments(arguments_, command);
706
+ const wire = projectTaskOptions(options);
707
+ const value = __velarProcessRecord(
708
+ await __velarDesktopHostCall("project-task", "start", [command, args, wire]),
709
+ "Project task start result",
710
+ projectTaskStartFields,
711
+ );
712
+ if (!__velarProcessIsSafeInteger(value.handle) || value.handle < 1 || !__velarProcessIsSafeInteger(value.pid) || value.pid < 1) {
713
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid project task start result");
714
+ }
715
+ return new ProjectTaskHandle(projectTaskToken, value.handle, value.pid, wire.maxOutputBytes);
716
+ }
717
+ const terminalOptionFields = new __velarProcessNativeSet(["columns", "rows"]);
718
+ const terminalStartFields = new __velarProcessNativeSet(["handle", "pid"]);
719
+ const terminalResultFields = new __velarProcessNativeSet(["code"]);
720
+ function terminalDimension(value, fallback, name, minimum) {
721
+ value = value ?? fallback;
722
+ if (!__velarProcessIsSafeInteger(value) || value < minimum || value > 1000) {
723
+ throw new __velarProcessNativeRangeError("Terminal " + name + " must be an integer from " + minimum + " through 1000");
724
+ }
725
+ return value;
726
+ }
727
+ function terminalOptions(value) {
728
+ value = __velarProcessRecord(value == null ? {} : value, "Terminal options", terminalOptionFields);
729
+ return {columns: terminalDimension(value.columns, 80, "columns", 20), rows: terminalDimension(value.rows, 24, "rows", 5)};
730
+ }
731
+ function terminalResult(value) {
732
+ value = __velarProcessRecord(value, "Terminal result", terminalResultFields);
733
+ if (!__velarProcessIsSafeInteger(value.code) || value.code < 0 || value.code > 255) {
734
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid terminal result");
735
+ }
736
+ return __velarProcessFreeze({code: value.code});
737
+ }
738
+ class TerminalSessionHandle {
739
+ constructor(token, handle, pid) {
740
+ if (token !== terminalSessionToken || !__velarProcessIsSafeInteger(handle) || handle < 1
741
+ || !__velarProcessIsSafeInteger(pid) || pid < 1) throw new __velarProcessNativeTypeError("TerminalSession values are created only by velar/desktop.openTerminal");
742
+ this.handle = handle;
743
+ this.pid = pid;
744
+ this.reading = false;
745
+ this.closed = false;
746
+ this.outputEnded = false;
747
+ this.result = null;
748
+ __velarProcessSeal(this);
749
+ }
750
+ async write(text) {
751
+ if (this.closed) throw new __velarProcessNativeError("TerminalSession is closed");
752
+ if (typeof text !== "string" || text.length === 0 || __velarUtf8ByteLength(text) > 1024 * 1024) {
753
+ throw new __velarProcessNativeRangeError("TerminalSession.write requires 1 byte through 1 MiB of text");
754
+ }
755
+ const value = await __velarDesktopHostCall("terminal", "write", [this.handle, text], 0);
756
+ if (value !== null) throw new __velarProcessNativeTypeError("Desktop host returned an invalid terminal write result");
757
+ return null;
758
+ }
759
+ async resize(columns, rows) {
760
+ if (this.closed) throw new __velarProcessNativeError("TerminalSession is closed");
761
+ columns = terminalDimension(columns, 80, "columns", 20);
762
+ rows = terminalDimension(rows, 24, "rows", 5);
763
+ const value = await __velarDesktopHostCall("terminal", "resize", [this.handle, columns, rows]);
764
+ if (value !== null) throw new __velarProcessNativeTypeError("Desktop host returned an invalid terminal resize result");
765
+ return null;
766
+ }
767
+ async next() {
768
+ if (this.reading) throw new __velarProcessNativeError("TerminalSession.next() allows only one active pull");
769
+ if (this.closed || this.outputEnded) return null;
770
+ this.reading = true;
771
+ try {
772
+ const value = await __velarDesktopHostCall("terminal", "next", [this.handle], 0);
773
+ if (value === null) { this.outputEnded = true; return null; }
774
+ if (typeof value !== "string" || value.length === 0 || __velarUtf8ByteLength(value) > 1024 * 1024) {
775
+ throw new __velarProcessNativeTypeError("Desktop host returned invalid terminal output");
776
+ }
777
+ return value;
778
+ } finally { this.reading = false; }
779
+ }
780
+ wait() {
781
+ if (this.result === null) {
782
+ if (this.reading) return __velarProcessReject(new __velarProcessNativeError("Terminal output cannot be waited while next() is pending"));
783
+ if (!this.outputEnded) return __velarProcessReject(new __velarProcessNativeError("Terminal output must be consumed before wait()"));
784
+ let pending;
785
+ pending = __velarProcessThen(__velarDesktopHostCall("terminal", "wait", [this.handle], 0), value => {
786
+ this.closed = true;
787
+ return terminalResult(value);
788
+ }, error => { if (this.result === pending) this.result = null; throw error; });
789
+ this.result = pending;
790
+ }
791
+ return this.result;
792
+ }
793
+ async close() {
794
+ if (this.closed) return null;
795
+ const outcome = terminalResult(await __velarDesktopHostCall("terminal", "close", [this.handle], 10000));
796
+ this.closed = true;
797
+ if (this.result === null) this.result = __velarProcessResolve(outcome);
798
+ return null;
799
+ }
800
+ }
801
+ export const TerminalSession = __velarProcessFreeze({
802
+ is(value) { return value instanceof TerminalSessionHandle; },
803
+ parse(value) {
804
+ if (!(value instanceof TerminalSessionHandle)) throw new __velarProcessNativeTypeError("Value does not match TerminalSession");
805
+ return value;
806
+ },
807
+ });
808
+ export async function openTerminal(options = {}) {
809
+ const wire = terminalOptions(options);
810
+ const value = __velarProcessRecord(await __velarDesktopHostCall("terminal", "open", [wire]), "Terminal start result", terminalStartFields);
811
+ if (!__velarProcessIsSafeInteger(value.handle) || value.handle < 1 || !__velarProcessIsSafeInteger(value.pid) || value.pid < 1) {
812
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid terminal start result");
813
+ }
814
+ return new TerminalSessionHandle(terminalSessionToken, value.handle, value.pid);
815
+ }
816
+ `.trimStart();
817
+ const DESKTOP_TEST_SOURCE = String.raw `
818
+ const runtimeKey = Symbol.for("velar.browser.test.v1");
819
+ const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
820
+ const reflectApply = Reflect.apply;
821
+ function invoke(capability, operation, args, timeout) {
822
+ // The controller replaces this runtime for every isolated browser test, so
823
+ // this test-only module deliberately resolves one data-only snapshot per
824
+ // call instead of retaining a previous test's Page authority.
825
+ const runtimeDescriptor = getOwnPropertyDescriptor(globalThis, runtimeKey);
826
+ if (!runtimeDescriptor || !("value" in runtimeDescriptor) || !runtimeDescriptor.value || typeof runtimeDescriptor.value !== "object") {
827
+ throw new Error("velar/desktop-test requires 'velar test --browser'");
828
+ }
829
+ const runtime = runtimeDescriptor.value;
830
+ const invokeDescriptor = getOwnPropertyDescriptor(runtime, "frameworkInvoke");
831
+ if (!invokeDescriptor || !("value" in invokeDescriptor) || typeof invokeDescriptor.value !== "function") {
832
+ throw new Error("velar/desktop-test requires 'velar test --browser'");
833
+ }
834
+ return reflectApply(invokeDescriptor.value, runtime, [capability, operation, args, timeout]);
835
+ }
836
+ export async function setPlatform(value) {
837
+ if (value !== "macos" && value !== "test") throw new TypeError("Desktop test setPlatform requires a DesktopPlatform value");
838
+ const result = await invoke("desktop-test", "setPlatform", [value], 30000);
839
+ if (result !== null) throw new TypeError("Desktop test host returned an invalid platform setup result");
840
+ return null;
841
+ }
842
+ export async function appDataDirectory() {
843
+ const value = await invoke("desktop", "appDataDirectory", [], 30000);
844
+ if (typeof value !== "string" || !value.startsWith("/") || value.length > 4096 || value.includes("\0")) throw new TypeError("Desktop test host returned an invalid absolute app-data path");
845
+ return value;
846
+ }
847
+ export async function projectDirectory() {
848
+ const value = await invoke("desktop", "projectDirectory", [], 30000);
849
+ if (typeof value !== "string" || !value.startsWith("/") || value.length > 4096 || value.includes("\0")) throw new TypeError("Desktop test host returned an invalid absolute project path");
850
+ return value;
851
+ }
852
+ export async function seedProjectChange(transactionId, lifecycle, diff) {
853
+ if (typeof transactionId !== "string" || transactionId.length === 0 || transactionId.length > 512 || transactionId.includes("\0")) {
854
+ throw new TypeError("Desktop test seedProjectChange requires a bounded transaction id");
855
+ }
856
+ if (typeof lifecycle !== "string" || lifecycle.length === 0 || lifecycle.length > 64) {
857
+ throw new TypeError("Desktop test seedProjectChange requires a lifecycle name");
858
+ }
859
+ if (typeof diff !== "string" || new TextEncoder().encode(diff).byteLength > 16 * 1024 * 1024) {
860
+ throw new RangeError("Desktop test seedProjectChange diff cannot exceed 16 MiB");
861
+ }
862
+ const value = await invoke("project-change-test", "seed", [transactionId, lifecycle, diff], 30000);
863
+ if (value !== null) throw new TypeError("Desktop test host returned an invalid project change seed result");
864
+ return null;
865
+ }
866
+ export async function makeDirectory(path) {
867
+ if (typeof path !== "string" || path.length === 0 || path.length > 4096 || path.includes("\0")) throw new TypeError("Desktop test makeDirectory requires a bounded path");
868
+ const value = await invoke("fs", "makeDirectory", [path], 30000);
869
+ if (value !== null) throw new TypeError("Desktop test host returned an invalid directory result");
870
+ return null;
871
+ }
872
+ export async function readText(path, maxBytes) {
873
+ if (typeof path !== "string" || path.length === 0 || path.length > 4096 || path.includes("\0")) throw new TypeError("Desktop test readText requires a bounded path");
874
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 16 * 1024 * 1024) throw new RangeError("Desktop test readText maxBytes is outside its supported bounds");
875
+ const value = await invoke("fs", "readText", [path, maxBytes], 30000);
876
+ if (typeof value !== "string") throw new TypeError("Desktop test host returned invalid file text");
877
+ return value;
878
+ }
879
+ export async function writeText(path, text) {
880
+ if (typeof path !== "string" || path.length === 0 || path.length > 4096 || path.includes("\0")) throw new TypeError("Desktop test writeText requires a bounded path");
881
+ if (typeof text !== "string") throw new TypeError("Desktop test writeText requires text");
882
+ const value = await invoke("fs", "writeText", [path, text], 30000);
883
+ if (value !== null) throw new TypeError("Desktop test host returned an invalid write result");
884
+ return null;
885
+ }
886
+ export async function removeFile(path) {
887
+ if (typeof path !== "string" || path.length === 0 || path.length > 4096 || path.includes("\0")) throw new TypeError("Desktop test removeFile requires a bounded path");
888
+ const value = await invoke("fs", "removeFile", [path], 30000);
889
+ if (value !== null) throw new TypeError("Desktop test host returned an invalid remove result");
890
+ return null;
891
+ }
892
+ `.trimStart();
893
+ const DESKTOP_PATH_SOURCE = String.raw `
894
+ ${DESKTOP_HOST_ABI_RUNTIME}
895
+ const maxPathCodeUnits = 4096;
896
+ const pathApply = Reflect.apply;
897
+ const pathArrayIsArray = Array.isArray;
898
+ const pathArrayJoin = Array.prototype.join;
899
+ const pathGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
900
+ const pathStringIndexOf = String.prototype.indexOf;
901
+ const pathStringSlice = String.prototype.slice;
902
+ const pathStringToLowerCase = String.prototype.toLowerCase;
903
+ const pathEncodeURIComponent = encodeURIComponent;
904
+ const pathDecodeURIComponent = decodeURIComponent;
905
+ const pathNativeURL = URL;
906
+ const pathURLProtocol = pathGetOwnPropertyDescriptor(pathNativeURL.prototype, "protocol")?.get;
907
+ const pathURLUsername = pathGetOwnPropertyDescriptor(pathNativeURL.prototype, "username")?.get;
908
+ const pathURLPassword = pathGetOwnPropertyDescriptor(pathNativeURL.prototype, "password")?.get;
909
+ const pathURLPort = pathGetOwnPropertyDescriptor(pathNativeURL.prototype, "port")?.get;
910
+ const pathURLSearch = pathGetOwnPropertyDescriptor(pathNativeURL.prototype, "search")?.get;
911
+ const pathURLHash = pathGetOwnPropertyDescriptor(pathNativeURL.prototype, "hash")?.get;
912
+ const pathURLHostname = pathGetOwnPropertyDescriptor(pathNativeURL.prototype, "hostname")?.get;
913
+ const pathURLPathname = pathGetOwnPropertyDescriptor(pathNativeURL.prototype, "pathname")?.get;
914
+ if (typeof pathURLProtocol !== "function" || typeof pathURLUsername !== "function" || typeof pathURLPassword !== "function"
915
+ || typeof pathURLPort !== "function" || typeof pathURLSearch !== "function" || typeof pathURLHash !== "function"
916
+ || typeof pathURLHostname !== "function" || typeof pathURLPathname !== "function") {
917
+ throw new TypeError("Desktop path URL runtime is unavailable");
918
+ }
919
+ function stringIndexOf(value, search) { return pathApply(pathStringIndexOf, value, [search]); }
920
+ function stringSlice(value, start, end) { return pathApply(pathStringSlice, value, end === undefined ? [start] : [start, end]); }
921
+ function stringToLowerCase(value) { return pathApply(pathStringToLowerCase, value, []); }
922
+ function arrayJoin(value, separator) { return pathApply(pathArrayJoin, value, [separator]); }
923
+ function urlValue(value, getter) { return pathApply(getter, value, []); }
924
+ function checked(value, operation) {
925
+ if (typeof value !== "string" || value.length === 0) throw new TypeError(operation + " requires a non-empty path string");
926
+ if (value.length > maxPathCodeUnits || stringIndexOf(value, "\0") !== -1) throw new RangeError(operation + " path is outside the supported bounds");
927
+ return value;
928
+ }
929
+ function bounded(value, operation) {
930
+ if (value.length > maxPathCodeUnits) throw new RangeError(operation + " result is outside the supported bounds");
931
+ return value;
932
+ }
933
+ function normalizePath(value) {
934
+ const absolute = value[0] === "/";
935
+ const trailing = value[value.length - 1] === "/";
936
+ const output = [];
937
+ let start = 0;
938
+ for (let index = 0; index <= value.length; index += 1) {
939
+ if (index < value.length && value[index] !== "/") continue;
940
+ const part = stringSlice(value, start, index);
941
+ start = index + 1;
942
+ if (part === "" || part === ".") continue;
943
+ if (part !== "..") {
944
+ output[output.length] = part;
945
+ continue;
946
+ }
947
+ if (output.length > 0 && output[output.length - 1] !== "..") output.length -= 1;
948
+ else if (!absolute) output[output.length] = "..";
949
+ }
950
+ const body = arrayJoin(output, "/");
951
+ let result = absolute ? "/" + body : body;
952
+ if (result === "") result = absolute ? "/" : ".";
953
+ if (trailing && result !== "/") result += "/";
954
+ return result;
955
+ }
956
+ function dirnamePath(value) {
957
+ const absolute = value[0] === "/";
958
+ let end = -1;
959
+ let matchedSlash = true;
960
+ for (let index = value.length - 1; index >= 1; index -= 1) {
961
+ if (value[index] === "/") {
962
+ if (!matchedSlash) {
963
+ end = index;
964
+ break;
965
+ }
966
+ } else matchedSlash = false;
967
+ }
968
+ if (end === -1) return absolute ? "/" : ".";
969
+ if (absolute && end === 1) return "//";
970
+ return stringSlice(value, 0, end);
971
+ }
972
+ function basenamePath(value) {
973
+ let start = 0;
974
+ let end = -1;
975
+ let matchedSlash = true;
976
+ for (let index = value.length - 1; index >= 0; index -= 1) {
977
+ if (value[index] === "/") {
978
+ if (!matchedSlash) {
979
+ start = index + 1;
980
+ break;
981
+ }
982
+ } else if (end === -1) {
983
+ matchedSlash = false;
984
+ end = index + 1;
985
+ }
986
+ }
987
+ return end === -1 ? "" : stringSlice(value, start, end);
988
+ }
989
+ function extensionPath(value) {
990
+ let startDot = -1;
991
+ let startPart = 0;
992
+ let end = -1;
993
+ let matchedSlash = true;
994
+ let preDotState = 0;
995
+ for (let index = value.length - 1; index >= 0; index -= 1) {
996
+ const character = value[index];
997
+ if (character === "/") {
998
+ if (!matchedSlash) {
999
+ startPart = index + 1;
1000
+ break;
1001
+ }
1002
+ continue;
1003
+ }
1004
+ if (end === -1) {
1005
+ matchedSlash = false;
1006
+ end = index + 1;
1007
+ }
1008
+ if (character === ".") {
1009
+ if (startDot === -1) startDot = index;
1010
+ else if (preDotState !== 1) preDotState = 1;
1011
+ } else if (startDot !== -1) preDotState = -1;
1012
+ }
1013
+ if (startDot === -1 || end === -1 || preDotState === 0
1014
+ || (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) return "";
1015
+ return stringSlice(value, startDot, end);
1016
+ }
1017
+ function parts(value, operation) {
1018
+ if (!pathArrayIsArray(value) || value.length > 256) throw new TypeError(operation + " requires a bounded List<string>");
1019
+ const output = [];
1020
+ for (let index = 0; index < value.length; index += 1) {
1021
+ const descriptor = pathGetOwnPropertyDescriptor(value, index);
1022
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError(operation + " path parts must contain enumerable data values");
1023
+ output[output.length] = checked(descriptor.value, operation);
1024
+ }
1025
+ return output;
1026
+ }
1027
+ function projectDirectory() {
1028
+ const provider = __velarDesktopHostField("projectDirectoryValue");
1029
+ if (typeof provider !== "function") throw new TypeError("Desktop project directory provider must be a function data value");
1030
+ const value = checked(pathApply(provider, undefined, []), "resolve");
1031
+ if (!value.startsWith("/")) throw new TypeError("Desktop project directory must be absolute");
1032
+ return value;
1033
+ }
1034
+ function resolved(values, operation) {
1035
+ let value = projectDirectory();
1036
+ const normalizedParts = parts(values, operation);
1037
+ for (let index = 0; index < normalizedParts.length; index += 1) {
1038
+ const item = normalizedParts[index];
1039
+ value = item[0] === "/" ? item : value + "/" + item;
1040
+ }
1041
+ return normalizePath(value);
1042
+ }
1043
+ function pathSegments(value) {
1044
+ const output = [];
1045
+ let start = value[0] === "/" ? 1 : 0;
1046
+ for (let index = start; index <= value.length; index += 1) {
1047
+ if (index < value.length && value[index] !== "/") continue;
1048
+ if (index > start) output[output.length] = stringSlice(value, start, index);
1049
+ start = index + 1;
1050
+ }
1051
+ return output;
1052
+ }
1053
+ function relativeValue(from, to) {
1054
+ const left = pathSegments(resolved([checked(from, "relative")], "relative"));
1055
+ const right = pathSegments(resolved([checked(to, "relative")], "relative"));
1056
+ let shared = 0;
1057
+ while (shared < left.length && shared < right.length && left[shared] === right[shared]) shared += 1;
1058
+ const output = [];
1059
+ for (let index = shared; index < left.length; index += 1) output[output.length] = "..";
1060
+ for (let index = shared; index < right.length; index += 1) output[output.length] = right[index];
1061
+ return arrayJoin(output, "/");
1062
+ }
1063
+ export function normalize(path) { return bounded(normalizePath(checked(path, "normalize")), "normalize"); }
1064
+ export function join(values = []) { return bounded(normalizePath(arrayJoin(parts(values, "join"), "/")), "join"); }
1065
+ export function resolve(values = []) { return bounded(resolved(values, "resolve"), "resolve"); }
1066
+ export function relative(from, to) { return bounded(relativeValue(from, to), "relative"); }
1067
+ export function dirname(path) { return bounded(dirnamePath(checked(path, "dirname")), "dirname"); }
1068
+ export function basename(path) { return basenamePath(checked(path, "basename")); }
1069
+ export function extension(path) { return extensionPath(checked(path, "extension")); }
1070
+ export function isAbsolute(path) { return checked(path, "isAbsolute")[0] === "/"; }
1071
+ export function contains(root, target) { const value = relativeValue(root, target); return value === "" || (value !== ".." && stringIndexOf(value, "../") !== 0 && value[0] !== "/"); }
1072
+ export function toFileUrl(path) {
1073
+ const segments = pathSegments(resolved([checked(path, "toFileUrl")], "toFileUrl"));
1074
+ const encoded = [];
1075
+ for (let index = 0; index < segments.length; index += 1) encoded[index] = pathEncodeURIComponent(segments[index]);
1076
+ return "file:///" + arrayJoin(encoded, "/");
1077
+ }
1078
+ export function fromFileUrl(value) {
1079
+ value = checked(value, "fromFileUrl");
1080
+ let url;
1081
+ try { url = new pathNativeURL(value); } catch { throw new TypeError("fromFileUrl requires a valid file URL"); }
1082
+ const pathname = urlValue(url, pathURLPathname);
1083
+ const lowercasePathname = stringToLowerCase(pathname);
1084
+ const encodedSeparator = stringIndexOf(lowercasePathname, "%2f") !== -1 || stringIndexOf(lowercasePathname, "%5c") !== -1;
1085
+ const hostname = urlValue(url, pathURLHostname);
1086
+ if (urlValue(url, pathURLProtocol) !== "file:" || urlValue(url, pathURLUsername) !== "" || urlValue(url, pathURLPassword) !== ""
1087
+ || urlValue(url, pathURLPort) !== "" || urlValue(url, pathURLSearch) !== "" || urlValue(url, pathURLHash) !== ""
1088
+ || hostname !== "" && hostname !== "localhost" || encodedSeparator) throw new TypeError("fromFileUrl requires a local file URL");
1089
+ let path;
1090
+ try { path = pathDecodeURIComponent(pathname); } catch { throw new TypeError("fromFileUrl requires a valid encoded file URL"); }
1091
+ return bounded(normalizePath(path), "fromFileUrl");
1092
+ }
1093
+ `.trimStart();
1094
+ const DESKTOP_FS_SOURCE = String.raw `
1095
+ ${DESKTOP_HOST_ABI_RUNTIME}
1096
+ const watcherToken = Symbol("velar.desktop.fs.watcher");
1097
+ const maxPathCodeUnits = 4096;
1098
+ const maxFileBytes = 16 * 1024 * 1024;
1099
+ const maxListItems = 100000;
1100
+ const maxListTextUnits = 2 * 1024 * 1024;
1101
+ const maxWatchPaths = 4096;
1102
+ function pathOf(value, operation) {
1103
+ if (typeof value !== "string" || value.length === 0) throw new TypeError(operation + " requires a non-empty path string");
1104
+ if (value.length > maxPathCodeUnits || value.includes("\0")) throw new RangeError(operation + " path is outside the supported bounds");
1105
+ return value;
1106
+ }
1107
+ function byteLimit(value, operation) {
1108
+ if (!Number.isSafeInteger(value) || value < 1 || value > maxFileBytes) throw new RangeError(operation + " maxBytes must be an integer from 1 through 16777216");
1109
+ return value;
1110
+ }
1111
+ function textOf(value, operation) {
1112
+ if (typeof value !== "string") throw new TypeError(operation + " requires text");
1113
+ if (new TextEncoder().encode(value).byteLength > maxFileBytes) throw new RangeError(operation + " cannot write more than 16 MiB");
1114
+ return value;
1115
+ }
1116
+ function replaceOf(value, operation) {
1117
+ if (typeof value !== "boolean") throw new TypeError(operation + " replace must be bool");
1118
+ return value;
1119
+ }
1120
+ function recordOf(value, name, allowed) {
1121
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError(name + " must be a record");
1122
+ const prototype = Object.getPrototypeOf(value);
1123
+ if (prototype !== Object.prototype && prototype !== null) throw new TypeError(name + " must be a plain record");
1124
+ const output = Object.create(null);
1125
+ for (const key of Reflect.ownKeys(value)) {
1126
+ if (typeof key !== "string") throw new TypeError(name + " fields must use string names");
1127
+ if (!allowed.has(key)) throw new TypeError(name + " has unknown field '" + key + "'");
1128
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1129
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError(name + " fields must be enumerable data values");
1130
+ output[key] = descriptor.value;
1131
+ }
1132
+ return output;
1133
+ }
1134
+ function listOf(value, maximum) {
1135
+ if (!Array.isArray(value) || value.length > maximum) throw new TypeError("Desktop host returned an invalid directory list");
1136
+ const output = [];
1137
+ let units = 0;
1138
+ for (let index = 0; index < value.length; index += 1) {
1139
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
1140
+ if (!descriptor?.enumerable || !("value" in descriptor) || typeof descriptor.value !== "string" || descriptor.value.length === 0 || descriptor.value.includes("/") || descriptor.value.includes("\0")) {
1141
+ throw new TypeError("Desktop host returned an invalid directory list");
1142
+ }
1143
+ units += descriptor.value.length;
1144
+ if (units > maxListTextUnits) throw new RangeError("Desktop directory list cannot exceed 2 MiB of text");
1145
+ output.push(descriptor.value);
1146
+ }
1147
+ return output.sort();
1148
+ }
1149
+ function infoOf(value) {
1150
+ if (value == null) return null;
1151
+ value = recordOf(value, "Desktop file info", new Set(["name", "kind", "size", "modifiedAt"]));
1152
+ if (typeof value.name !== "string" || value.name.length > maxPathCodeUnits || value.name.includes("/") || value.name.includes("\0")
1153
+ || !["file", "directory", "symlink", "other"].includes(value.kind)
1154
+ || !Number.isFinite(value.size) || value.size < 0
1155
+ || !Number.isFinite(value.modifiedAt)) throw new TypeError("Desktop host returned invalid file info");
1156
+ return Object.freeze({name: value.name, kind: value.kind, size: value.size, modifiedAt: value.modifiedAt});
1157
+ }
1158
+ function watchBatchOf(value) {
1159
+ value = recordOf(value, "Desktop file watch batch", new Set(["paths", "rescan"]));
1160
+ if (Reflect.ownKeys(value).length !== 2 || typeof value.rescan !== "boolean" || !Array.isArray(value.paths)
1161
+ || value.paths.length > maxWatchPaths || value.rescan && value.paths.length !== 0) {
1162
+ throw new TypeError("Desktop host returned an invalid file watch batch");
1163
+ }
1164
+ const paths = [];
1165
+ let units = 0;
1166
+ let previous = null;
1167
+ for (let index = 0; index < value.paths.length; index += 1) {
1168
+ const descriptor = Object.getOwnPropertyDescriptor(value.paths, String(index));
1169
+ if (!descriptor?.enumerable || !("value" in descriptor) || typeof descriptor.value !== "string"
1170
+ || descriptor.value.length === 0 || descriptor.value.length > maxPathCodeUnits || descriptor.value.includes("\0")
1171
+ || previous !== null && descriptor.value <= previous) throw new TypeError("Desktop host returned invalid file watch paths");
1172
+ units += descriptor.value.length;
1173
+ if (units > maxListTextUnits) throw new RangeError("Desktop file watch paths cannot exceed 2 MiB of text");
1174
+ paths.push(descriptor.value);
1175
+ previous = descriptor.value;
1176
+ }
1177
+ return Object.freeze({paths, rescan: value.rescan});
1178
+ }
1179
+ function invoke(operation, args, timeout = 30000) {
1180
+ return __velarDesktopHostCall("fs", operation, args, timeout);
1181
+ }
1182
+ async function mutate(operation, args) {
1183
+ const value = await invoke(operation, args);
1184
+ if (value !== null) throw new TypeError("Desktop host returned an invalid " + operation + " result");
1185
+ }
1186
+ class FileWatcherHandle {
1187
+ constructor(token, handle) {
1188
+ if (token !== watcherToken || !Number.isSafeInteger(handle) || handle < 1) throw new TypeError("FileWatcher values are created only by velar/fs.watchFiles");
1189
+ this.handle = handle;
1190
+ this.closed = false;
1191
+ this.pending = false;
1192
+ this.next = async () => {
1193
+ if (this.closed) return null;
1194
+ if (this.pending) throw new Error("FileWatcher.next already has an active pull");
1195
+ this.pending = true;
1196
+ try {
1197
+ const value = await invoke("watchNext", [this.handle], 0);
1198
+ if (value === null) { this.closed = true; return null; }
1199
+ return watchBatchOf(value);
1200
+ } catch (error) {
1201
+ this.closed = true;
1202
+ try { await invoke("watchClose", [this.handle]); } catch {}
1203
+ throw error;
1204
+ } finally {
1205
+ this.pending = false;
1206
+ }
1207
+ };
1208
+ }
1209
+ async close() {
1210
+ if (this.closed) return null;
1211
+ this.closed = true;
1212
+ const value = await invoke("watchClose", [this.handle]);
1213
+ if (typeof value !== "boolean") throw new TypeError("Desktop host returned an invalid file watcher release result");
1214
+ return null;
1215
+ }
1216
+ }
1217
+ export const FileWatcher = Object.freeze({
1218
+ is(value) { return value instanceof FileWatcherHandle; },
1219
+ parse(value) { if (!(value instanceof FileWatcherHandle)) throw new TypeError("Value does not match FileWatcher"); return value; },
1220
+ });
1221
+ export const FileWatchBatch = Object.freeze({
1222
+ is(value) { try { watchBatchOf(value); return true; } catch { return false; } },
1223
+ parse(value) { return watchBatchOf(value); },
1224
+ });
1225
+ export async function readText(path, maxBytes = maxFileBytes) {
1226
+ maxBytes = byteLimit(maxBytes, "readText");
1227
+ const value = await invoke("readText", [pathOf(path, "readText"), maxBytes]);
1228
+ if (typeof value !== "string") throw new TypeError("Desktop host returned invalid file text");
1229
+ if (new TextEncoder().encode(value).byteLength > maxBytes) throw new RangeError("Desktop file text exceeds maxBytes");
1230
+ return value;
1231
+ }
1232
+ export async function createText(path, text) { await mutate("createText", [pathOf(path, "createText"), textOf(text, "createText")]); return null; }
1233
+ export async function replaceTextIfMatches(path, expected, replacement) {
1234
+ const value = await invoke("replaceTextIfMatches", [pathOf(path, "replaceTextIfMatches"), textOf(expected, "replaceTextIfMatches expected"), textOf(replacement, "replaceTextIfMatches replacement")]);
1235
+ if (typeof value !== "boolean") throw new TypeError("Desktop host returned an invalid replaceTextIfMatches result");
1236
+ return value;
1237
+ }
1238
+ export async function writeText(path, text) { await mutate("writeText", [pathOf(path, "writeText"), textOf(text, "writeText")]); return null; }
1239
+ export async function appendText(path, text) { await mutate("appendText", [pathOf(path, "appendText"), textOf(text, "appendText")]); return null; }
1240
+ export async function exists(path) {
1241
+ const value = await invoke("exists", [pathOf(path, "exists")]);
1242
+ if (typeof value !== "boolean") throw new TypeError("Desktop host returned invalid file existence");
1243
+ return value;
1244
+ }
1245
+ export async function list(path, maxItems = maxListItems) {
1246
+ if (!Number.isSafeInteger(maxItems) || maxItems < 1 || maxItems > maxListItems) throw new RangeError("list maxItems must be an integer from 1 through 100000");
1247
+ return listOf(await invoke("list", [pathOf(path, "list"), maxItems]), maxItems);
1248
+ }
1249
+ export async function info(path) { return infoOf(await invoke("info", [pathOf(path, "info")])); }
1250
+ export async function canonical(path) {
1251
+ const value = await invoke("canonical", [pathOf(path, "canonical")]);
1252
+ if (typeof value !== "string" || value.length === 0 || value.length > maxPathCodeUnits || value.includes("\0")) throw new TypeError("Desktop host returned an invalid canonical path");
1253
+ return value;
1254
+ }
1255
+ export async function makeDirectory(path) { await mutate("makeDirectory", [pathOf(path, "makeDirectory")]); return null; }
1256
+ export async function copyFile(source, target, replace = false) { await mutate("copyFile", [pathOf(source, "copyFile"), pathOf(target, "copyFile"), replaceOf(replace, "copyFile")]); return null; }
1257
+ export async function move(source, target, replace = false) { await mutate("move", [pathOf(source, "move"), pathOf(target, "move"), replaceOf(replace, "move")]); return null; }
1258
+ export async function removeFile(path) { await mutate("removeFile", [pathOf(path, "removeFile")]); return null; }
1259
+ export async function watchFiles(path, recursive = false) {
1260
+ path = pathOf(path, "watchFiles");
1261
+ if (typeof recursive !== "boolean") throw new TypeError("watchFiles recursive must be bool");
1262
+ return new FileWatcherHandle(watcherToken, await invoke("watchStart", [path, recursive]));
1263
+ }
1264
+ `.trimStart();
1265
+ const DESKTOP_PROCESS_SOURCE = String.raw `
1266
+ ${DESKTOP_HOST_ABI_RUNTIME}
1267
+ ${VELAR_TYPE_REGISTRY_RUNTIME}
1268
+ ${VELAR_UTF8_RUNTIME}
1269
+ ${VELAR_PROCESS_HOST_RUNTIME}
1270
+ const processToken = Symbol("velar.desktop.process");
1271
+ const maxTextBytes = 16 * 1024 * 1024;
1272
+ const processOptionFields = new __velarProcessNativeSet(["cwd", "env", "stdin", "timeout", "maxOutputBytes"]);
1273
+ const processStartFields = new __velarProcessNativeSet(["handle", "pid"]);
1274
+ const processResultFields = new __velarProcessNativeSet(["code", "signal", "stdout", "stderr"]);
1275
+ const processOutputFields = new __velarProcessNativeSet(["channel", "text"]);
1276
+ const processErrorFields = new __velarProcessNativeSet(["name", "message"]);
1277
+ const processStopFields = new __velarProcessNativeSet(["result", "error"]);
1278
+ const processWaitFields = new __velarProcessNativeSet(["result", "error", "retained"]);
1279
+ export const ProcessOutputChannel = __velarRegisterRuntimeType(__velarProcessFreeze({
1280
+ stdout: "stdout",
1281
+ stderr: "stderr",
1282
+ is(value) { return value === "stdout" || value === "stderr"; },
1283
+ parse(value) {
1284
+ if (!ProcessOutputChannel.is(value)) throw new __velarProcessNativeTypeError("Value does not match ProcessOutputChannel");
1285
+ return value;
1286
+ },
1287
+ // D60 rule 149: values() is the third name charter section 6 reserves on
1288
+ // every enum, and it returns a fresh mutable List in declaration order.
1289
+ values() { return ["stdout", "stderr"]; },
1290
+ }));
1291
+ function boundedText(value, name, maxCodeUnits = 4096) {
1292
+ if (typeof value !== "string" || value.length === 0) throw new __velarProcessNativeTypeError(name + " must be non-empty text");
1293
+ if (value.length > maxCodeUnits || __velarProcessIncludes(value, "\0")) throw new __velarProcessNativeRangeError(name + " is outside the supported bounds");
1294
+ return value;
1295
+ }
1296
+ function argumentsOf(value) {
1297
+ if (value == null) return [];
1298
+ if (!__velarProcessIsArray(value) || value.length > 1000) throw new __velarProcessNativeTypeError("Process args must be a bounded List<string>");
1299
+ let units = 0;
1300
+ const output = [];
1301
+ for (let index = 0; index < value.length; index += 1) {
1302
+ const descriptor = __velarProcessOwnDescriptor(value, __velarProcessNativeString(index));
1303
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new __velarProcessNativeTypeError("Process args must contain enumerable data values");
1304
+ const item = descriptor.value;
1305
+ units += boundedText(item, "Process argument", 1024 * 1024).length;
1306
+ if (units > 1024 * 1024) throw new __velarProcessNativeRangeError("Process arguments cannot exceed 1 MiB");
1307
+ output[output.length] = item;
1308
+ }
1309
+ return output;
1310
+ }
1311
+ function recordOf(value, name, allowed) {
1312
+ return __velarProcessRecord(value, name, allowed);
1313
+ }
1314
+ function mapEntries(value) {
1315
+ if (value == null) return null;
1316
+ const snapshot = __velarProcessMapSnapshot(value);
1317
+ if (snapshot.size > 1000) throw new __velarProcessNativeRangeError("Process env cannot exceed 1000 entries");
1318
+ const output = [];
1319
+ let units = 0;
1320
+ for (let index = 0; index < snapshot.entries.length; index += 1) {
1321
+ const name = snapshot.entries[index][0];
1322
+ const item = snapshot.entries[index][1];
1323
+ if (!__velarProcessEnvironmentName(name) || name === "PATH" || typeof item !== "string" || __velarProcessIncludes(item, "\0")) {
1324
+ throw new __velarProcessNativeTypeError("Desktop process env must contain valid string variables and cannot replace PATH");
1325
+ }
1326
+ units += name.length + item.length;
1327
+ if (units > 1024 * 1024) throw new __velarProcessNativeRangeError("Process env cannot exceed 1 MiB");
1328
+ output[output.length] = [name, item];
1329
+ }
1330
+ return output;
1331
+ }
1332
+ function optionsOf(value) {
1333
+ if (value == null) value = {};
1334
+ value = recordOf(value, "Process options", processOptionFields);
1335
+ const cwd = value.cwd == null ? null : boundedText(value.cwd, "Process cwd");
1336
+ const stdin = value.stdin ?? "";
1337
+ if (typeof stdin !== "string" || __velarUtf8ByteLength(stdin) > maxTextBytes) throw new __velarProcessNativeRangeError("Process stdin cannot exceed 16 MiB");
1338
+ const timeout = value.timeout ?? 120000;
1339
+ if (!__velarProcessIsSafeInteger(timeout) || timeout < 0 || timeout > 600000) throw new __velarProcessNativeRangeError("Process timeout must be an integer from 0 through 600000 milliseconds");
1340
+ const maxOutputBytes = value.maxOutputBytes ?? 4 * 1024 * 1024;
1341
+ if (!__velarProcessIsSafeInteger(maxOutputBytes) || maxOutputBytes < 1 || maxOutputBytes > maxTextBytes) throw new __velarProcessNativeRangeError("Process maxOutputBytes must be an integer from 1 through 16777216");
1342
+ return {cwd, env: mapEntries(value.env), stdin, timeout, maxOutputBytes};
1343
+ }
1344
+ function startValueOf(value) {
1345
+ value = recordOf(value, "Desktop process start result", processStartFields);
1346
+ if (!__velarProcessIsSafeInteger(value.handle) || value.handle < 1 || !__velarProcessIsSafeInteger(value.pid) || value.pid < 0) {
1347
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid process start result");
1348
+ }
1349
+ return value;
1350
+ }
1351
+ function resultOf(value, maxOutputBytes) {
1352
+ value = recordOf(value, "Desktop process result", processResultFields);
1353
+ if ((value.code !== null && !__velarProcessIsSafeInteger(value.code))
1354
+ || (value.signal !== null && (typeof value.signal !== "string" || value.signal.length === 0 || value.signal.length > 128))
1355
+ || typeof value.stdout !== "string" || typeof value.stderr !== "string") {
1356
+ throw new __velarProcessNativeTypeError("Desktop host returned an invalid process result");
1357
+ }
1358
+ if (__velarUtf8ByteLength(value.stdout) + __velarUtf8ByteLength(value.stderr) > maxOutputBytes) {
1359
+ throw new __velarProcessNativeRangeError("Desktop process result exceeded maxOutputBytes");
1360
+ }
1361
+ return __velarProcessFreeze({code: value.code, signal: value.signal, stdout: value.stdout, stderr: value.stderr});
1362
+ }
1363
+ function processErrorOf(value) {
1364
+ value = recordOf(value, "Desktop process host error", processErrorFields);
1365
+ if (typeof value.name !== "string" || value.name !== "Error" && value.name !== "RangeError" && value.name !== "TypeError"
1366
+ || typeof value.message !== "string" || value.message.length === 0 || value.message.length > 65536) {
1367
+ throw new __velarProcessNativeTypeError("Desktop process host returned an invalid error");
1368
+ }
1369
+ if (value.name === "RangeError") return new __velarProcessNativeRangeError(value.message);
1370
+ if (value.name === "TypeError") return new __velarProcessNativeTypeError(value.message);
1371
+ return new __velarProcessNativeError(value.message);
1372
+ }
1373
+ function outputOf(value, maxOutputBytes) {
1374
+ if (value === null) return null;
1375
+ value = recordOf(value, "Desktop process output", processOutputFields);
1376
+ if (!ProcessOutputChannel.is(value.channel) || typeof value.text !== "string" || value.text.length === 0) {
1377
+ throw new __velarProcessNativeTypeError("Desktop host returned invalid process output");
1378
+ }
1379
+ const bytes = __velarUtf8ByteLength(value.text);
1380
+ if (bytes > maxOutputBytes) throw new __velarProcessNativeRangeError("Desktop process output exceeded maxOutputBytes");
1381
+ return __velarProcessFreeze({channel: value.channel, text: value.text, bytes});
1382
+ }
1383
+ function stopValueOf(value, maxOutputBytes) {
1384
+ value = recordOf(value, "Desktop process stop result", processStopFields);
1385
+ const resultDescriptor = __velarProcessOwnDescriptor(value, "result");
1386
+ const errorDescriptor = __velarProcessOwnDescriptor(value, "error");
1387
+ if (!resultDescriptor || !("value" in resultDescriptor) || !errorDescriptor || !("value" in errorDescriptor)
1388
+ || value.result !== null && value.error !== null) {
1389
+ throw new __velarProcessNativeTypeError("Desktop process stop result is invalid or contradictory");
1390
+ }
1391
+ return {
1392
+ result: value.result === null ? null : resultOf(value.result, maxOutputBytes),
1393
+ error: value.error === null ? null : processErrorOf(value.error),
1394
+ };
1395
+ }
1396
+ function waitValueOf(value, maxOutputBytes) {
1397
+ value = recordOf(value, "Desktop process wait result", processWaitFields);
1398
+ const resultDescriptor = __velarProcessOwnDescriptor(value, "result");
1399
+ const errorDescriptor = __velarProcessOwnDescriptor(value, "error");
1400
+ const retainedDescriptor = __velarProcessOwnDescriptor(value, "retained");
1401
+ if (!resultDescriptor || !("value" in resultDescriptor) || !errorDescriptor || !("value" in errorDescriptor)
1402
+ || !retainedDescriptor || !("value" in retainedDescriptor) || typeof value.retained !== "boolean"
1403
+ || value.result !== null && value.error !== null
1404
+ || value.retained && (value.result !== null || value.error === null)
1405
+ || !value.retained && value.result === null && value.error === null) {
1406
+ throw new __velarProcessNativeTypeError("Desktop process wait result is invalid or contradictory");
1407
+ }
1408
+ return {
1409
+ result: value.result === null ? null : resultOf(value.result, maxOutputBytes),
1410
+ error: value.error === null ? null : processErrorOf(value.error),
1411
+ retained: value.retained,
1412
+ };
1413
+ }
1414
+ function invoke(operation, args, timeout = 30000) {
1415
+ return __velarDesktopHostCall("process", operation, args, timeout);
1416
+ }
1417
+ class ProcessHandle {
1418
+ constructor(token, handle, pid, maxOutputBytes) {
1419
+ if (token !== processToken || !__velarProcessIsSafeInteger(handle) || handle < 1 || !__velarProcessIsSafeInteger(pid) || pid < 0) {
1420
+ throw new __velarProcessNativeTypeError("Process values are created only by velar/process.start");
1421
+ }
1422
+ this.handle = handle;
1423
+ this.pid = pid;
1424
+ this.maxOutputBytes = maxOutputBytes;
1425
+ this.result = null;
1426
+ this.stopping = null;
1427
+ this.stopRequested = false;
1428
+ this.cleanup = null;
1429
+ this.reading = false;
1430
+ this.waitStarted = false;
1431
+ this.outputBytes = 0;
1432
+ this.next = async () => {
1433
+ if (this.waitStarted) throw new __velarProcessNativeError("Process output must be consumed before wait()");
1434
+ if (this.stopRequested) throw new __velarProcessNativeError("Process output is unavailable after stop()");
1435
+ if (this.reading) throw new __velarProcessNativeError("Process.next() allows only one active pull");
1436
+ this.reading = true;
1437
+ try {
1438
+ const output = outputOf(await invoke("read", [this.handle], 0), this.maxOutputBytes);
1439
+ if (output === null) return null;
1440
+ this.outputBytes += output.bytes;
1441
+ if (this.outputBytes > this.maxOutputBytes) throw new __velarProcessNativeRangeError("Desktop process output exceeded maxOutputBytes");
1442
+ return __velarProcessFreeze({channel: output.channel, text: output.text});
1443
+ } finally {
1444
+ this.reading = false;
1445
+ }
1446
+ };
1447
+ __velarProcessSeal(this);
1448
+ }
1449
+ wait() {
1450
+ if (this.reading) return __velarProcessReject(new __velarProcessNativeError("Process wait() cannot run while next() is pending"));
1451
+ this.waitStarted = true;
1452
+ if (!this.result) {
1453
+ let result;
1454
+ result = __velarProcessThen(invoke("wait", [this.handle], 0), value => {
1455
+ let outcome;
1456
+ try { outcome = waitValueOf(value, this.maxOutputBytes); }
1457
+ catch (error) {
1458
+ if (this.result === result) this.result = null;
1459
+ throw error;
1460
+ }
1461
+ if (outcome.retained) {
1462
+ if (this.result === result) this.result = null;
1463
+ throw outcome.error;
1464
+ }
1465
+ if (outcome.error) throw outcome.error;
1466
+ return outcome.result;
1467
+ }, error => {
1468
+ if (this.result === result) this.result = null;
1469
+ throw error;
1470
+ });
1471
+ this.result = result;
1472
+ }
1473
+ return this.result;
1474
+ }
1475
+ async stop() {
1476
+ return await __velarProcessRetryableStop(this, () => __velarProcessThen(invoke("stop", [this.handle], 10000), value => {
1477
+ const outcome = stopValueOf(value, this.maxOutputBytes);
1478
+ if (outcome.error) this.result = __velarProcessObservedReject(outcome.error);
1479
+ else if (outcome.result) this.result = __velarProcessResolve(outcome.result);
1480
+ return null;
1481
+ }));
1482
+ }
1483
+ }
1484
+ export const Process = __velarProcessFreeze({
1485
+ is(value) { return value instanceof ProcessHandle; },
1486
+ parse(value) { if (!(value instanceof ProcessHandle)) throw new __velarProcessNativeTypeError("Process values are created only by velar/process.start"); return value; },
1487
+ });
1488
+ export async function start(command, args = [], options = {}) {
1489
+ const wire = optionsOf(options);
1490
+ const value = startValueOf(await invoke("start", [boundedText(command, "Process command"), argumentsOf(args), wire]));
1491
+ return new ProcessHandle(processToken, value.handle, value.pid, wire.maxOutputBytes);
1492
+ }
1493
+ export async function run(command, args = [], options = {}) {
1494
+ const owner = await start(command, args, options);
1495
+ try { return await owner.wait(); }
1496
+ catch (error) {
1497
+ if (!owner.result) __velarProcessRetainRun(owner);
1498
+ throw error;
1499
+ }
1500
+ }
1501
+ `.trimStart();
1502
+ const DESKTOP_ENV_SOURCE = String.raw `
1503
+ ${DESKTOP_HOST_ABI_RUNTIME}
1504
+ let cachedSnapshot = null;
1505
+ function variableName(value) {
1506
+ if (typeof value !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/u.test(value) || value.length > 256) {
1507
+ throw new TypeError("Environment variable names use ASCII letters, digits, and underscores, starting with a letter or underscore");
1508
+ }
1509
+ return value;
1510
+ }
1511
+ function snapshot() {
1512
+ if (cachedSnapshot) return cachedSnapshot;
1513
+ const desktopEnvironment = __velarDesktopHostField("environment");
1514
+ if (!desktopEnvironment || typeof desktopEnvironment !== "object" || Array.isArray(desktopEnvironment)) {
1515
+ throw new Error("VelarScript Desktop environment snapshot is unavailable");
1516
+ }
1517
+ const value = desktopEnvironment;
1518
+ const prototype = Object.getPrototypeOf(value);
1519
+ if (prototype !== Object.prototype && prototype !== null) throw new TypeError("Desktop environment snapshot must be a plain record");
1520
+ const keys = Reflect.ownKeys(value);
1521
+ if (keys.length > 64) throw new RangeError("Desktop environment snapshot cannot exceed 64 variables");
1522
+ const output = Object.create(null);
1523
+ let bytes = 0;
1524
+ for (const key of keys) {
1525
+ if (typeof key !== "string" || !/^[A-Z_][A-Z0-9_]{0,127}$/u.test(key)) throw new TypeError("Desktop environment snapshot has an invalid variable name");
1526
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1527
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError("Desktop environment snapshot fields must be enumerable data values");
1528
+ if (typeof descriptor.value !== "string") throw new TypeError("Desktop environment snapshot values must be text");
1529
+ const itemBytes = new TextEncoder().encode(descriptor.value).byteLength;
1530
+ bytes += new TextEncoder().encode(key).byteLength + itemBytes;
1531
+ if (itemBytes > 64 * 1024 || bytes > 1024 * 1024) throw new RangeError("Desktop environment snapshot exceeds its size boundary");
1532
+ output[key] = descriptor.value;
1533
+ }
1534
+ cachedSnapshot = Object.freeze(output);
1535
+ return cachedSnapshot;
1536
+ }
1537
+ export function get(name) {
1538
+ name = variableName(name);
1539
+ const values = snapshot();
1540
+ return Object.prototype.hasOwnProperty.call(values, name) ? Object.getOwnPropertyDescriptor(values, name).value : null;
1541
+ }
1542
+ export function require(name) {
1543
+ name = variableName(name);
1544
+ const value = get(name);
1545
+ if (value === null) throw new Error("VelarScript environment variable '" + name + "' is required");
1546
+ return value;
1547
+ }
1548
+ `.trimStart();
1549
+ const DESKTOP_HTTP_SOURCE = String.raw `
1550
+ ${VELAR_STRICT_JSON_RUNTIME}
1551
+ ${VELAR_TYPE_REGISTRY_RUNTIME}
1552
+ ${VELAR_UTF8_RUNTIME}
1553
+ ${DESKTOP_HOST_ABI_RUNTIME}
1554
+ const maxResponseChunks = 1000000;
1555
+ let nextHandle = 1;
1556
+ const secretHeaderValues = new WeakSet();
1557
+ function parseJsonText(text) {
1558
+ return __velarJsonParse(text, "HTTP JSON text");
1559
+ }
1560
+ function runtimeHttpType(Type) { return __velarRequireRuntimeType(Type, "HTTP parsing"); }
1561
+ function methodOf(value) {
1562
+ if (typeof value !== "string") throw new TypeError("HTTP method must be text");
1563
+ const method = value.toUpperCase();
1564
+ if (method.length === 0 || method.length > 32 || !/^[!#$%&'*+.^_\x60|~0-9A-Z-]+$/u.test(method) || ["CONNECT", "TRACE", "TRACK"].includes(method)) {
1565
+ throw new TypeError("HTTP method is invalid or forbidden");
1566
+ }
1567
+ return method;
1568
+ }
1569
+ function urlOf(value) {
1570
+ if (typeof value !== "string" || value.length === 0 || value.length > 2 * 1024 * 1024) throw new TypeError("HTTP URL must be bounded text");
1571
+ const url = new URL(value);
1572
+ if (url.protocol !== "http:" && url.protocol !== "https:") throw new TypeError("HTTP URL must use http or https");
1573
+ if (url.username || url.password) throw new TypeError("HTTP URL credentials are not allowed; use an Authorization header");
1574
+ return url.href;
1575
+ }
1576
+ export class HttpAbortError extends Error {
1577
+ constructor(reason) {
1578
+ if (reason !== "cancelled" && reason !== "timeout") throw new TypeError("HTTP abort reason must be cancelled or timeout");
1579
+ super(reason === "timeout" ? "HTTP request timed out" : "HTTP request cancelled");
1580
+ this.name = "HttpAbortError"; this.reason = reason;
1581
+ }
1582
+ }
1583
+ // D60 rule 149: a module-provided enum carries the same runtime face a declared
1584
+ // enum does -- charter section 6 reserves is, parse, and values on every enum.
1585
+ export const HttpTransportPhase = __velarRegisterRuntimeType(Object.freeze({
1586
+ request: "request",
1587
+ response: "response",
1588
+ is(value) { return value === "request" || value === "response"; },
1589
+ parse(value) {
1590
+ if (!HttpTransportPhase.is(value)) throw new TypeError("Value does not match HttpTransportPhase");
1591
+ return value;
1592
+ },
1593
+ values() { return ["request", "response"]; },
1594
+ }));
1595
+ export class HttpTransportError extends Error {
1596
+ constructor(message, phase) {
1597
+ if (typeof message !== "string") throw new TypeError("HTTP transport error message must be text");
1598
+ if (message.length === 0 || message.length > 65536) throw new RangeError("HTTP transport error messages must contain at most 64 KiB");
1599
+ if (phase !== HttpTransportPhase.request && phase !== HttpTransportPhase.response) {
1600
+ throw new TypeError("HTTP transport phase must be request or response");
1601
+ }
1602
+ super(message); this.name = "HttpTransportError"; this.phase = phase;
1603
+ }
1604
+ }
1605
+ export class HttpError extends Error {
1606
+ constructor(message, status, url, body = null) {
1607
+ if (typeof message !== "string") throw new TypeError("HTTP error message must be text");
1608
+ if (message.length > 65536) throw new RangeError("HTTP error messages cannot exceed 64 KiB");
1609
+ if (!Number.isInteger(status) || status < 100 || status > 599) throw new RangeError("HTTP error status must be an integer from 100 through 599");
1610
+ if (typeof url !== "string") throw new TypeError("HTTP error URL must be text");
1611
+ if (url.length > 2 * 1024 * 1024) throw new RangeError("HTTP error URLs cannot exceed 2 MiB");
1612
+ super(message); this.name = "HttpError"; this.status = status; this.url = url; this.body = body;
1613
+ }
1614
+ }
1615
+ function headersOf(value) {
1616
+ if (value == null) return [];
1617
+ let size;
1618
+ try { size = Reflect.getOwnPropertyDescriptor(Map.prototype, "size").get.call(value); }
1619
+ catch { throw new TypeError("HTTP headers must be Map<string, string>"); }
1620
+ if (size > 100) throw new RangeError("HTTP headers cannot exceed 100 fields");
1621
+ const output = [];
1622
+ let units = 0;
1623
+ for (const pair of Map.prototype.entries.call(value)) {
1624
+ const name = pair[0]; const item = pair[1];
1625
+ if (typeof name !== "string" || typeof item !== "string" || !/^[!#$%&'*+.^_|~0-9A-Za-z-]+$/u.test(name) || /[\r\n]/u.test(item)) {
1626
+ throw new TypeError("HTTP headers must use valid string names and single-line values");
1627
+ }
1628
+ units += name.length + item.length;
1629
+ if (units > 65536) throw new RangeError("HTTP headers cannot exceed 64 KiB");
1630
+ output.push([name, item]);
1631
+ }
1632
+ return output;
1633
+ }
1634
+ function checkedHeaders(value) {
1635
+ if (value.length > 100) throw new RangeError("HTTP headers cannot exceed 100 fields");
1636
+ let units = 0;
1637
+ for (const pair of value) {
1638
+ units += pair[0].length + pair[1].length;
1639
+ if (units > 65536) throw new RangeError("HTTP headers cannot exceed 64 KiB");
1640
+ }
1641
+ return value;
1642
+ }
1643
+ const forbiddenSecretHeaders = new Set(["connection", "content-length", "cookie", "cookie2", "host", "proxy-authorization", "te", "trailer", "transfer-encoding", "upgrade"]);
1644
+ export function secretHeader(name, environment, prefix = "") {
1645
+ if (typeof name !== "string" || !/^[!#$%&'*+.^_|~0-9A-Za-z-]+$/u.test(name) || forbiddenSecretHeaders.has(name.toLowerCase())) {
1646
+ throw new TypeError("HTTP secret header name is invalid or transport-controlled");
1647
+ }
1648
+ if (typeof environment !== "string" || !/^[A-Z_][A-Z0-9_]{0,127}$/u.test(environment)) {
1649
+ throw new TypeError("HTTP secret environment name must be uppercase ASCII text");
1650
+ }
1651
+ if (typeof prefix !== "string" || prefix.length > 256 || /[\r\n]/u.test(prefix)) {
1652
+ throw new TypeError("HTTP secret header prefix must be single-line text of at most 256 characters");
1653
+ }
1654
+ const value = Object.freeze({name, environment, prefix});
1655
+ secretHeaderValues.add(value);
1656
+ return value;
1657
+ }
1658
+ function secretHeadersOf(value) {
1659
+ if (value == null) return [];
1660
+ if (!Array.isArray(value) || value.length > 16) throw new TypeError("HTTP secretHeaders must be a List with at most 16 entries");
1661
+ const output = [];
1662
+ for (let index = 0; index < value.length; index += 1) {
1663
+ const descriptor = Object.getOwnPropertyDescriptor(value, index);
1664
+ if (!descriptor?.enumerable || !("value" in descriptor) || !secretHeaderValues.has(descriptor.value)) {
1665
+ throw new TypeError("HTTP secretHeaders entries must be created by secretHeader");
1666
+ }
1667
+ output.push(descriptor.value);
1668
+ }
1669
+ return output;
1670
+ }
1671
+ function plainOptions(value) {
1672
+ if (value == null) return Object.create(null);
1673
+ if (typeof value !== "object" || Array.isArray(value)) throw new TypeError("HTTP options must be a record");
1674
+ const prototype = Object.getPrototypeOf(value);
1675
+ if (prototype !== Object.prototype && prototype !== null) throw new TypeError("HTTP options must be a plain record");
1676
+ const allowed = new Set(["headers", "secretHeaders", "body", "timeout", "maxBytes"]);
1677
+ const output = Object.create(null);
1678
+ for (const key of Reflect.ownKeys(value)) {
1679
+ if (typeof key !== "string" || !allowed.has(key)) throw new TypeError("HTTP options has an unknown field '" + String(key) + "'");
1680
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1681
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError("HTTP options fields must be enumerable data values");
1682
+ output[key] = descriptor.value;
1683
+ }
1684
+ return output;
1685
+ }
1686
+ function optionsOf(value, method) {
1687
+ const options = plainOptions(value);
1688
+ const timeout = options.timeout ?? 120000;
1689
+ if (!Number.isSafeInteger(timeout) || timeout < 0 || timeout > 600000) throw new RangeError("HTTP timeout must be an integer from 0 through 600000 milliseconds");
1690
+ const maxBytes = options.maxBytes ?? 16 * 1024 * 1024;
1691
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 64 * 1024 * 1024) throw new RangeError("HTTP maxBytes must be an integer from 1 through 67108864");
1692
+ const headers = headersOf(options.headers);
1693
+ const secretHeaders = secretHeadersOf(options.secretHeaders);
1694
+ let body = options.body ?? null;
1695
+ if ((method === "GET" || method === "HEAD") && body !== null) throw new TypeError(method + " requests cannot have a body");
1696
+ if (body !== null && typeof body !== "string") {
1697
+ body = __velarJsonStringify(body);
1698
+ if (!headers.some(pair => pair[0].toLowerCase() === "content-type")) headers.push(["content-type", "application/json"]);
1699
+ checkedHeaders(headers);
1700
+ }
1701
+ if (typeof body === "string" && __velarUtf8ByteLength(body) > 16 * 1024 * 1024) throw new RangeError("HTTP body cannot exceed 16 MiB");
1702
+ return Object.freeze({headers, secretHeaders, body, timeout, maxBytes});
1703
+ }
1704
+ function invoke(operation, args, timeout = 30000) {
1705
+ return __velarDesktopHostCall("http", operation, args, timeout);
1706
+ }
1707
+ function bridgeTransportError(error, phase) {
1708
+ if (!error || typeof error !== "object") return null;
1709
+ const name = Object.getOwnPropertyDescriptor(error, "name");
1710
+ const message = Object.getOwnPropertyDescriptor(error, "message");
1711
+ const actualPhase = Object.getOwnPropertyDescriptor(error, "phase");
1712
+ if (!name || !("value" in name) || name.value !== "VelarDesktopHttpTransportError"
1713
+ || !message || !("value" in message) || typeof message.value !== "string" || message.value.length === 0 || message.value.length > 65536
1714
+ || !actualPhase?.enumerable || !("value" in actualPhase) || actualPhase.value !== phase) return null;
1715
+ return new HttpTransportError(message.value, phase);
1716
+ }
1717
+ function responseOf(value) {
1718
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Desktop bridge returned an invalid HTTP response");
1719
+ const prototype = Object.getPrototypeOf(value);
1720
+ if (prototype !== Object.prototype && prototype !== null) throw new TypeError("Desktop bridge returned an invalid HTTP response");
1721
+ const allowed = new Set(["ok", "status", "statusText", "url", "headers", "body"]);
1722
+ const fields = Object.create(null);
1723
+ for (const key of Reflect.ownKeys(value)) {
1724
+ if (typeof key !== "string" || !allowed.has(key)) throw new TypeError("Desktop bridge returned an unknown HTTP response field");
1725
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1726
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError("Desktop bridge HTTP response fields must be enumerable data values");
1727
+ fields[key] = descriptor.value;
1728
+ }
1729
+ for (const key of allowed) if (!Object.prototype.hasOwnProperty.call(fields, key)) throw new TypeError("Desktop bridge HTTP response is missing field '" + key + "'");
1730
+ if (typeof fields.ok !== "boolean" || !Number.isInteger(fields.status) || fields.status < 100 || fields.status > 599
1731
+ || fields.ok !== (fields.status >= 200 && fields.status <= 299)) {
1732
+ throw new TypeError("Desktop bridge returned invalid HTTP response metadata");
1733
+ }
1734
+ if (typeof fields.statusText !== "string") throw new TypeError("HTTP response status text must be text");
1735
+ if (fields.statusText.length > 65536) throw new RangeError("HTTP response status text cannot exceed 64 KiB");
1736
+ if (typeof fields.url !== "string") throw new TypeError("HTTP response URL must be text");
1737
+ if (fields.url.length > 2 * 1024 * 1024) throw new RangeError("HTTP response URLs cannot exceed 2 MiB");
1738
+ if (typeof fields.body !== "boolean") throw new TypeError("Desktop bridge HTTP response body marker must be boolean");
1739
+ if (!Array.isArray(fields.headers) || fields.headers.length > 100) throw new TypeError("Desktop bridge HTTP response headers must be a bounded List");
1740
+ const headers = new Map();
1741
+ let units = 0;
1742
+ for (let index = 0; index < fields.headers.length; index += 1) {
1743
+ const descriptor = Object.getOwnPropertyDescriptor(fields.headers, String(index));
1744
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError("Desktop bridge HTTP response headers must be dense data values");
1745
+ const pair = descriptor.value;
1746
+ if (!Array.isArray(pair) || pair.length !== 2) throw new TypeError("Desktop bridge HTTP response headers must contain pairs");
1747
+ const nameDescriptor = Object.getOwnPropertyDescriptor(pair, "0");
1748
+ const valueDescriptor = Object.getOwnPropertyDescriptor(pair, "1");
1749
+ const name = nameDescriptor?.value;
1750
+ const item = valueDescriptor?.value;
1751
+ if (!nameDescriptor?.enumerable || !("value" in nameDescriptor) || !valueDescriptor?.enumerable || !("value" in valueDescriptor)
1752
+ || typeof name !== "string" || typeof item !== "string" || !/^[!#$%&'*+.^_|~0-9A-Za-z-]+$/u.test(name) || /[\r\n]/u.test(item)) {
1753
+ throw new TypeError("Desktop bridge HTTP response headers are invalid");
1754
+ }
1755
+ units += name.length + item.length;
1756
+ if (units > 65536) throw new RangeError("HTTP response headers cannot exceed 64 KiB");
1757
+ headers.set(name, item);
1758
+ }
1759
+ return Object.freeze({ok: fields.ok, status: fields.status, statusText: fields.statusText, url: fields.url, headers, body: fields.body});
1760
+ }
1761
+ function chunkOf(value) {
1762
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Desktop bridge returned an invalid HTTP chunk");
1763
+ const prototype = Object.getPrototypeOf(value);
1764
+ if (prototype !== Object.prototype && prototype !== null) throw new TypeError("Desktop bridge returned an invalid HTTP chunk");
1765
+ const keys = Reflect.ownKeys(value);
1766
+ if (keys.length !== 2 || !keys.includes("done") || !keys.includes("text")) throw new TypeError("Desktop bridge returned an invalid HTTP chunk");
1767
+ const done = Object.getOwnPropertyDescriptor(value, "done");
1768
+ const text = Object.getOwnPropertyDescriptor(value, "text");
1769
+ if (!done?.enumerable || !("value" in done) || !text?.enumerable || !("value" in text)
1770
+ || typeof done.value !== "boolean" || typeof text.value !== "string") {
1771
+ throw new TypeError("Desktop bridge HTTP chunks must contain boolean done and text data values");
1772
+ }
1773
+ return {done: done.value, text: text.value};
1774
+ }
1775
+ class DesktopResponse {
1776
+ constructor(value, request) {
1777
+ const response = responseOf(value);
1778
+ this.ok = response.ok; this.status = response.status; this.statusText = response.statusText; this.url = response.url;
1779
+ this.headers = response.headers; this.body = response.body; this.request = request; this.cachedText = null; this.textPending = null; this.consuming = false;
1780
+ if (!this.body) request.finish();
1781
+ Object.seal(this);
1782
+ }
1783
+ async consume(consumer) {
1784
+ if (this.cachedText !== null) {
1785
+ const result = await consumer(this.cachedText);
1786
+ if (result !== null) throw new TypeError("HTTP stream consumer must resolve to null");
1787
+ return null;
1788
+ }
1789
+ if (this.consuming) throw new Error("HTTP response body is already being consumed");
1790
+ this.consuming = true;
1791
+ let chunks = 0;
1792
+ try {
1793
+ if (!this.body) return null;
1794
+ while (true) {
1795
+ let wire;
1796
+ try { wire = await invoke("read", [this.request.handle], 0); }
1797
+ catch (error) {
1798
+ if (this.request.abortError) throw this.request.abortError;
1799
+ throw bridgeTransportError(error, HttpTransportPhase.response) ?? error;
1800
+ }
1801
+ const chunk = chunkOf(wire);
1802
+ if (!chunk.done) {
1803
+ chunks += 1;
1804
+ if (chunks > maxResponseChunks) throw new RangeError("HTTP responses cannot exceed 1000000 chunks");
1805
+ }
1806
+ if (chunk.text) {
1807
+ const result = await consumer(chunk.text);
1808
+ if (result !== null) throw new TypeError("HTTP stream consumer must resolve to null");
1809
+ }
1810
+ if (chunk.done) break;
1811
+ if (this.request.abortError) throw this.request.abortError;
1812
+ }
1813
+ if (this.request.abortError) throw this.request.abortError;
1814
+ return null;
1815
+ } catch (error) {
1816
+ if (this.request.abortError) throw this.request.abortError;
1817
+ void invoke("cancel", [this.request.handle], 10000).catch(() => {});
1818
+ throw error;
1819
+ } finally {
1820
+ this.request.finish();
1821
+ }
1822
+ }
1823
+ async streamText(consumer) { if (typeof consumer !== "function") throw new TypeError("HTTP streamText requires an async consumer"); return this.consume(consumer); }
1824
+ async text() {
1825
+ if (this.cachedText !== null) return this.cachedText;
1826
+ if (this.textPending !== null) return this.textPending;
1827
+ const pending = (async () => {
1828
+ const chunks = [];
1829
+ await this.consume(async chunk => { chunks.push(chunk); return null; });
1830
+ return chunks.join("");
1831
+ })();
1832
+ this.textPending = pending;
1833
+ try {
1834
+ this.cachedText = await pending;
1835
+ return this.cachedText;
1836
+ } finally {
1837
+ if (this.textPending === pending) this.textPending = null;
1838
+ }
1839
+ }
1840
+ async json() { return parseJsonText(await this.text()); }
1841
+ async parse(Type) { Type = runtimeHttpType(Type); return Type.parse(await this.json()); }
1842
+ }
1843
+ class DesktopRequest {
1844
+ constructor(method, url, options) {
1845
+ this.method = methodOf(method); this.url = urlOf(url); this.options = optionsOf(options, this.method); this.handle = nextHandle++; this.pending = null; this.timer = null; this.abortError = null; this.finished = false;
1846
+ }
1847
+ finish() { if (this.finished) return; this.finished = true; if (this.timer) { clearTimeout(this.timer); this.timer = null; } }
1848
+ abort(reason) {
1849
+ if (this.finished || this.abortError) return;
1850
+ this.abortError = new HttpAbortError(reason);
1851
+ if (this.timer) { clearTimeout(this.timer); this.timer = null; }
1852
+ void invoke("cancel", [this.handle], 10000).catch(() => {});
1853
+ }
1854
+ async response() {
1855
+ if (this.pending) return this.pending;
1856
+ if (this.abortError) throw this.abortError;
1857
+ const timeout = this.options.timeout ?? 120000;
1858
+ if (!Number.isSafeInteger(timeout) || timeout < 0 || timeout > 600000) throw new RangeError("HTTP timeout must be an integer from 0 through 600000 milliseconds");
1859
+ if (timeout) this.timer = setTimeout(() => this.abort("timeout"), timeout);
1860
+ this.pending = (async () => {
1861
+ try {
1862
+ let value;
1863
+ try { value = await invoke("request", [this.handle, this.method, this.url, this.options], timeout === 0 ? 0 : Math.min(600000, timeout + 1000)); }
1864
+ catch (error) {
1865
+ if (this.abortError) throw this.abortError;
1866
+ throw bridgeTransportError(error, HttpTransportPhase.request) ?? error;
1867
+ }
1868
+ if (this.abortError) throw this.abortError;
1869
+ const response = new DesktopResponse(value, this);
1870
+ if (!response.ok) {
1871
+ const text = await response.text();
1872
+ let body = text;
1873
+ try { body = text ? parseJsonText(text) : null; } catch {}
1874
+ const errorUrl = response.url || this.url;
1875
+ throw new HttpError("HTTP " + response.status + " for " + errorUrl, response.status, errorUrl, body);
1876
+ }
1877
+ return response;
1878
+ } catch (error) {
1879
+ if (!this.abortError && !this.finished) void invoke("cancel", [this.handle], 10000).catch(() => {});
1880
+ this.finish();
1881
+ if (this.abortError) throw this.abortError;
1882
+ throw error;
1883
+ }
1884
+ })();
1885
+ return this.pending;
1886
+ }
1887
+ async text() { return (await this.response()).text(); }
1888
+ async json() { return (await this.response()).json(); }
1889
+ async streamText(consumer) { return (await this.response()).streamText(consumer); }
1890
+ async parse(Type) { Type = runtimeHttpType(Type); return Type.parse(await this.json()); }
1891
+ cancel() { this.abort("cancelled"); return null; }
1892
+ }
1893
+ const create = method => (url, options = {}) => new DesktopRequest(method, url, options);
1894
+ export const http = Object.freeze({
1895
+ request(method, url, options = {}) { return new DesktopRequest(method, url, options); },
1896
+ get: create("GET"), post: create("POST"), put: create("PUT"), patch: create("PATCH"), delete: create("DELETE"), head: create("HEAD"),
1897
+ });
1898
+ `.trimStart();
1899
+ const desktopModuleInterfaces = new Map(webCompilerExtension.modules.interfaces);
1900
+ desktopModuleInterfaces.set("velar/desktop", desktopModuleInterface);
1901
+ desktopModuleInterfaces.set("velar/desktop-test", desktopTestModuleInterface);
1902
+ desktopModuleInterfaces.set("velar/fs", nodeModuleInterfaces.get("velar/fs"));
1903
+ desktopModuleInterfaces.set("velar/path", nodeModuleInterfaces.get("velar/path"));
1904
+ desktopModuleInterfaces.set("velar/process", desktopProcessInterface);
1905
+ desktopModuleInterfaces.set("velar/http", nodeModuleInterfaces.get("velar/http"));
1906
+ desktopModuleInterfaces.set("velar/env", nodeModuleInterfaces.get("velar/env"));
1907
+ const desktopModuleSources = new Map(webCompilerExtension.modules.sources);
1908
+ const desktopModuleDependencies = new Map(webCompilerExtension.modules.dependencies);
1909
+ desktopModuleSources.set("velar/desktop", DESKTOP_MODULE_SOURCE);
1910
+ desktopModuleSources.set("velar/desktop-test", DESKTOP_TEST_SOURCE);
1911
+ desktopModuleSources.set("velar/fs", DESKTOP_FS_SOURCE);
1912
+ desktopModuleSources.set("velar/path", DESKTOP_PATH_SOURCE);
1913
+ desktopModuleSources.set("velar/process", DESKTOP_PROCESS_SOURCE);
1914
+ desktopModuleSources.set("velar/http", DESKTOP_HTTP_SOURCE);
1915
+ desktopModuleSources.set("velar/env", DESKTOP_ENV_SOURCE);
1916
+ export const velarCompilerExtension = Object.freeze({
1917
+ id: "@velarscript/desktop",
1918
+ contract: Object.freeze({
1919
+ protocolVersion: 1,
1920
+ apiVersion: VELAR_DESKTOP_API_VERSION,
1921
+ kind: "application",
1922
+ extends: Object.freeze({}),
1923
+ composes: Object.freeze({
1924
+ "@velarscript/web": webCompilerExtension.contract.apiVersion,
1925
+ "@velarscript/node": VELAR_NODE_API_VERSION,
1926
+ }),
1927
+ }),
1928
+ capabilities: Object.freeze(["web", "desktop"]),
1929
+ // Desktop is an application composition: Web owns surface syntax,
1930
+ // reactivity, DOM lowering, and browser runtime; Desktop owns only its
1931
+ // capability modules and host bridge. Keep each layer explicit so adding a
1932
+ // future application target cannot inherit hidden Web behavior via spread.
1933
+ lexical: webCompilerExtension.lexical,
1934
+ parser: webCompilerExtension.parser,
1935
+ syntax: webCompilerExtension.syntax,
1936
+ analyzer: webCompilerExtension.analyzer,
1937
+ semantic: webCompilerExtension.semantic,
1938
+ inspection: webCompilerExtension.inspection,
1939
+ analysis: webCompilerExtension.analysis,
1940
+ editor: webCompilerExtension.editor,
1941
+ formatting: webCompilerExtension.formatting,
1942
+ createEmitter: webCompilerExtension.createEmitter,
1943
+ modules: Object.freeze({
1944
+ apiVersion: VELAR_DESKTOP_API_VERSION,
1945
+ interfaces: desktopModuleInterfaces,
1946
+ sources: desktopModuleSources,
1947
+ dependencies: desktopModuleDependencies,
1948
+ source(specifier, projectConfig) {
1949
+ if (specifier === "velar/desktop")
1950
+ return DESKTOP_MODULE_SOURCE;
1951
+ if (specifier === "velar/desktop-test")
1952
+ return DESKTOP_TEST_SOURCE;
1953
+ if (specifier === "velar/fs")
1954
+ return DESKTOP_FS_SOURCE;
1955
+ if (specifier === "velar/path")
1956
+ return DESKTOP_PATH_SOURCE;
1957
+ if (specifier === "velar/process")
1958
+ return DESKTOP_PROCESS_SOURCE;
1959
+ if (specifier === "velar/http")
1960
+ return DESKTOP_HTTP_SOURCE;
1961
+ const config = projectConfig;
1962
+ return webModuleSource(specifier, { base: "/", publicConfig: { desktop: { identifier: config.identifier } } });
1963
+ },
1964
+ }),
1965
+ });
1966
+ export { velarProjectExtension } from "./config.js";
1967
+ //# sourceMappingURL=compiler.js.map