@velarscript/desktop 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/compiler.js CHANGED
@@ -8,8 +8,6 @@ const boolType = { kind: "bool" };
8
8
  const numberType = { kind: "number" };
9
9
  const nullType = { kind: "null" };
10
10
  const optionalStringType = optionalOf(stringType);
11
- const optionalNumberType = optionalOf(numberType);
12
- const listStringType = { kind: "list", element: stringType };
13
11
  function functionType(parameters, result, requiredParameters = parameters.length) {
14
12
  return { kind: "function", parameters, requiredParameters, result };
15
13
  }
@@ -68,107 +66,11 @@ function __velarDesktopHostCall(capability, operation, args, timeout = 30000) {
68
66
  return __velarDesktopReflectApply(__velarDesktopInvoke, bridge, [capability, operation, args, timeout]);
69
67
  }
70
68
  `.trim();
71
- const languageServerIdentity = "velar/desktop#type:LanguageServer";
72
- const languageServerType = { kind: "named", name: "LanguageServer", identity: languageServerIdentity };
73
69
  const desktopPlatformIdentity = "velar/desktop#enum:DesktopPlatform";
74
70
  const desktopPlatforms = new Set(["macos", "test"]);
75
71
  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
72
  const desktopModuleInterface = moduleInterface(new Map([
163
- ["LanguageServer", { kind: "typeObject", name: "LanguageServer" }],
164
73
  ["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
74
  ["platform", functionType([], desktopPlatformType)],
173
75
  ["packaged", functionType([], boolType)],
174
76
  ["homeDirectory", functionType([], { kind: "promise", value: stringType })],
@@ -176,55 +78,13 @@ const desktopModuleInterface = moduleInterface(new Map([
176
78
  ["projectDirectory", functionType([], { kind: "promise", value: stringType })],
177
79
  ["selectedProjectDirectory", functionType([], { kind: "promise", value: optionalStringType })],
178
80
  ["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([
81
+ ]), new Map(), new Map(), new Map([
217
82
  ["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
83
  ]));
223
84
  const desktopTestModuleInterface = moduleInterface(new Map([
224
85
  ["setPlatform", functionType([desktopPlatformType], { kind: "promise", value: nullType })],
225
86
  ["appDataDirectory", functionType([], { kind: "promise", value: stringType })],
226
87
  ["projectDirectory", functionType([], { kind: "promise", value: stringType })],
227
- ["seedProjectChange", functionType([stringType, stringType, stringType], { kind: "promise", value: nullType })],
228
88
  ["makeDirectory", functionType([stringType], { kind: "promise", value: nullType })],
229
89
  ["readText", functionType([stringType, { kind: "number" }], { kind: "promise", value: stringType })],
230
90
  ["writeText", functionType([stringType, stringType], { kind: "promise", value: nullType })],
@@ -235,17 +95,12 @@ const desktopProcessInterface = nodeProcessInterface;
235
95
  const DESKTOP_MODULE_SOURCE = String.raw `
236
96
  ${DESKTOP_HOST_ABI_RUNTIME}
237
97
  ${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({
98
+ const __velarDesktopFreeze = Object.freeze;
99
+ export const DesktopPlatform = __velarRegisterRuntimeType(__velarDesktopFreeze({
245
100
  macos: "macos", test: "test",
246
101
  is(value) { return value === "macos" || value === "test"; },
247
102
  parse(value) {
248
- if (!DesktopPlatform.is(value)) throw new __velarProcessNativeTypeError("Value does not match DesktopPlatform");
103
+ if (!DesktopPlatform.is(value)) throw new TypeError("Value does not match DesktopPlatform");
249
104
  return value;
250
105
  },
251
106
  values() { return ["macos", "test"]; },
@@ -274,545 +129,6 @@ export async function appDataDirectory() { return path("appDataDirectory"); }
274
129
  export async function projectDirectory() { return path("projectDirectory"); }
275
130
  export async function selectedProjectDirectory() { return optionalPath("selectedProjectDirectory"); }
276
131
  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
132
  `.trimStart();
817
133
  const DESKTOP_TEST_SOURCE = String.raw `
818
134
  const runtimeKey = Symbol.for("velar.browser.test.v1");
@@ -849,20 +165,6 @@ export async function projectDirectory() {
849
165
  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
166
  return value;
851
167
  }
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
168
  export async function makeDirectory(path) {
867
169
  if (typeof path !== "string" || path.length === 0 || path.length > 4096 || path.includes("\0")) throw new TypeError("Desktop test makeDirectory requires a bounded path");
868
170
  const value = await invoke("fs", "makeDirectory", [path], 30000);