@cimplify/cli 0.12.0 → 0.12.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.
- package/dist/{chunk-W64GWXPF.mjs → chunk-FOJVWJ57.mjs} +1 -1
- package/dist/{chunk-EL34CORK.mjs → chunk-JPUGWNVY.mjs} +1 -1
- package/dist/{dev-3TPDHU67.mjs → dev-6OWQ2FZ7.mjs} +438 -29
- package/dist/dispatcher.mjs +7 -7
- package/dist/{doctor-JQYXARYQ.mjs → doctor-UMR72TNV.mjs} +2 -2
- package/dist/{explain-2I4MWMPY.mjs → explain-RD6TURI3.mjs} +1 -1
- package/dist/{introspect-TB2QFQMF.mjs → introspect-M2KNI7TW.mjs} +2 -2
- package/dist/{update-T5O6YCIC.mjs → update-MCTGCQIY.mjs} +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { gitDetectRoot, gitCurrentBranch, gitCurrentSha, gitStatusPorcelain } from './chunk-K5464A3L.mjs';
|
|
3
3
|
import { parseEnvFile } from './chunk-DBZ3UOQ2.mjs';
|
|
4
|
-
import { package_default } from './chunk-
|
|
4
|
+
import { package_default } from './chunk-FOJVWJ57.mjs';
|
|
5
5
|
import { parseArgs } from './chunk-C4M3DXKC.mjs';
|
|
6
6
|
import { readAuthOrNull, readProjectLinkOrNull, readProjectState } from './chunk-UBAI443T.mjs';
|
|
7
7
|
import { bold, dim, yellow, green, info, result, red } from './chunk-E2T2SBP5.mjs';
|
|
@@ -6,8 +6,8 @@ import { ApiClient } from './chunk-F4S5KETY.mjs';
|
|
|
6
6
|
import { readAuth, readProjectLink } from './chunk-UBAI443T.mjs';
|
|
7
7
|
import { info, CliError, CLI_ERROR_CODE, dim } from './chunk-E2T2SBP5.mjs';
|
|
8
8
|
import { spawn } from 'child_process';
|
|
9
|
-
import { promises } from 'fs';
|
|
10
|
-
import
|
|
9
|
+
import { promises, watch } from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
11
|
import http from 'http';
|
|
12
12
|
|
|
13
13
|
// src/tunnel/v2/codec.ts
|
|
@@ -367,6 +367,408 @@ function sendableCloseCode(code) {
|
|
|
367
367
|
return legal ? code : void 0;
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
+
// src/tunnel/v2/control-protocol.ts
|
|
371
|
+
var CONTROL_KIND = "control";
|
|
372
|
+
var LENGTH_PREFIX_BYTES = 4;
|
|
373
|
+
var MAX_MESSAGE_BYTES = 32 * 1024 * 1024;
|
|
374
|
+
var CONTROL_OP = {
|
|
375
|
+
READ: "read",
|
|
376
|
+
WRITE: "write",
|
|
377
|
+
DELETE: "delete",
|
|
378
|
+
LIST: "list",
|
|
379
|
+
LIST_TREE: "list_tree",
|
|
380
|
+
STAT: "stat",
|
|
381
|
+
MKDIR: "mkdir",
|
|
382
|
+
RENAME: "rename",
|
|
383
|
+
WATCH_START: "watch_start",
|
|
384
|
+
WATCH_STOP: "watch_stop",
|
|
385
|
+
EXEC: "exec"
|
|
386
|
+
};
|
|
387
|
+
var CONTROL_ERROR = {
|
|
388
|
+
NOT_FOUND: "not_found",
|
|
389
|
+
INVALID_PATH: "invalid_path",
|
|
390
|
+
PERMISSION_DENIED: "permission_denied",
|
|
391
|
+
IO: "io",
|
|
392
|
+
UNSUPPORTED: "unsupported"};
|
|
393
|
+
var WATCH_EVENT = {
|
|
394
|
+
ADD: "add",
|
|
395
|
+
CHANGE: "change",
|
|
396
|
+
REMOVE: "remove",
|
|
397
|
+
RESYNC: "resync"
|
|
398
|
+
};
|
|
399
|
+
var ENCODING = {
|
|
400
|
+
UTF8: "utf8",
|
|
401
|
+
BASE64: "base64"
|
|
402
|
+
};
|
|
403
|
+
var ControlProtocolError = class extends Error {
|
|
404
|
+
};
|
|
405
|
+
var textEncoder3 = new TextEncoder();
|
|
406
|
+
var textDecoder2 = new TextDecoder();
|
|
407
|
+
function encodeMessage(message) {
|
|
408
|
+
const json = textEncoder3.encode(JSON.stringify(message));
|
|
409
|
+
if (json.length > MAX_MESSAGE_BYTES) {
|
|
410
|
+
throw new ControlProtocolError(`control message ${json.length} exceeds ${MAX_MESSAGE_BYTES}`);
|
|
411
|
+
}
|
|
412
|
+
const framed = new Uint8Array(LENGTH_PREFIX_BYTES + json.length);
|
|
413
|
+
new DataView(framed.buffer).setUint32(0, json.length);
|
|
414
|
+
framed.set(json, LENGTH_PREFIX_BYTES);
|
|
415
|
+
return framed;
|
|
416
|
+
}
|
|
417
|
+
function isRequest(message) {
|
|
418
|
+
return typeof message.op === "string";
|
|
419
|
+
}
|
|
420
|
+
var MessageFramer = class {
|
|
421
|
+
buffer = new Uint8Array(0);
|
|
422
|
+
push(bytes) {
|
|
423
|
+
this.buffer = concat(this.buffer, bytes);
|
|
424
|
+
const messages = [];
|
|
425
|
+
for (; ; ) {
|
|
426
|
+
if (this.buffer.length < LENGTH_PREFIX_BYTES) break;
|
|
427
|
+
const length = new DataView(
|
|
428
|
+
this.buffer.buffer,
|
|
429
|
+
this.buffer.byteOffset,
|
|
430
|
+
LENGTH_PREFIX_BYTES
|
|
431
|
+
).getUint32(0);
|
|
432
|
+
if (length > MAX_MESSAGE_BYTES) {
|
|
433
|
+
throw new ControlProtocolError(`framed length ${length} exceeds ${MAX_MESSAGE_BYTES}`);
|
|
434
|
+
}
|
|
435
|
+
if (this.buffer.length < LENGTH_PREFIX_BYTES + length) break;
|
|
436
|
+
const jsonBytes = this.buffer.subarray(LENGTH_PREFIX_BYTES, LENGTH_PREFIX_BYTES + length);
|
|
437
|
+
messages.push(JSON.parse(textDecoder2.decode(jsonBytes)));
|
|
438
|
+
this.buffer = this.buffer.subarray(LENGTH_PREFIX_BYTES + length);
|
|
439
|
+
}
|
|
440
|
+
if (this.buffer.byteOffset > 0) this.buffer = this.buffer.slice();
|
|
441
|
+
return messages;
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
function concat(a, b) {
|
|
445
|
+
if (a.length === 0) return b;
|
|
446
|
+
if (b.length === 0) return a;
|
|
447
|
+
const out = new Uint8Array(a.length + b.length);
|
|
448
|
+
out.set(a, 0);
|
|
449
|
+
out.set(b, a.length);
|
|
450
|
+
return out;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/tunnel/v2/control-agent.ts
|
|
454
|
+
var DEFAULT_IGNORED = /* @__PURE__ */ new Set([
|
|
455
|
+
"node_modules",
|
|
456
|
+
".git",
|
|
457
|
+
".next",
|
|
458
|
+
"dist",
|
|
459
|
+
"build",
|
|
460
|
+
".turbo",
|
|
461
|
+
".cache",
|
|
462
|
+
".cimplify"
|
|
463
|
+
]);
|
|
464
|
+
var ControlFsError = class extends Error {
|
|
465
|
+
constructor(code, message) {
|
|
466
|
+
super(message);
|
|
467
|
+
this.code = code;
|
|
468
|
+
}
|
|
469
|
+
code;
|
|
470
|
+
};
|
|
471
|
+
var ControlKind = class {
|
|
472
|
+
constructor(deps) {
|
|
473
|
+
this.deps = deps;
|
|
474
|
+
}
|
|
475
|
+
deps;
|
|
476
|
+
kind = CONTROL_KIND;
|
|
477
|
+
handle(incoming) {
|
|
478
|
+
void new ControlSession(incoming.stream, this.deps).run();
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
var ControlSession = class {
|
|
482
|
+
constructor(stream, deps) {
|
|
483
|
+
this.stream = stream;
|
|
484
|
+
this.deps = deps;
|
|
485
|
+
}
|
|
486
|
+
stream;
|
|
487
|
+
deps;
|
|
488
|
+
framer = new MessageFramer();
|
|
489
|
+
watch = null;
|
|
490
|
+
epoch = 0;
|
|
491
|
+
seq = 0;
|
|
492
|
+
// Serialize all writes so message bytes never interleave and event order
|
|
493
|
+
// (which carries seq) is preserved.
|
|
494
|
+
sending = Promise.resolve();
|
|
495
|
+
async run() {
|
|
496
|
+
try {
|
|
497
|
+
for (; ; ) {
|
|
498
|
+
const event = await this.stream.recv();
|
|
499
|
+
if (event === null) return;
|
|
500
|
+
if (event.type === "data") {
|
|
501
|
+
for (const message of this.framer.push(event.payload)) {
|
|
502
|
+
if (isRequest(message)) void this.dispatch(message);
|
|
503
|
+
}
|
|
504
|
+
} else if (event.type === "end") {
|
|
505
|
+
continue;
|
|
506
|
+
} else {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
} finally {
|
|
511
|
+
this.watch?.stop();
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
send(message) {
|
|
515
|
+
const bytes = encodeMessage(message);
|
|
516
|
+
this.sending = this.sending.then(() => this.stream.data(bytes).catch(() => {
|
|
517
|
+
}));
|
|
518
|
+
}
|
|
519
|
+
async dispatch(request) {
|
|
520
|
+
try {
|
|
521
|
+
const data = await this.execute(request);
|
|
522
|
+
this.send({ id: request.id, ok: true, data });
|
|
523
|
+
} catch (error) {
|
|
524
|
+
const code = error instanceof ControlFsError ? error.code : CONTROL_ERROR.IO;
|
|
525
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
526
|
+
this.send({ id: request.id, ok: false, error: { code, message } });
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
async execute(request) {
|
|
530
|
+
const { fs: backend } = this.deps;
|
|
531
|
+
switch (request.op) {
|
|
532
|
+
case CONTROL_OP.READ:
|
|
533
|
+
return backend.read(str(request, FIELD.PATH));
|
|
534
|
+
case CONTROL_OP.WRITE:
|
|
535
|
+
await backend.write(str(request, FIELD.PATH), str(request, FIELD.CONTENT), enc(request));
|
|
536
|
+
return {};
|
|
537
|
+
case CONTROL_OP.DELETE:
|
|
538
|
+
await backend.delete(str(request, FIELD.PATH), request.recursive === true);
|
|
539
|
+
return {};
|
|
540
|
+
case CONTROL_OP.LIST:
|
|
541
|
+
return { entries: await backend.list(str(request, FIELD.PATH)) };
|
|
542
|
+
case CONTROL_OP.LIST_TREE:
|
|
543
|
+
return { paths: await backend.listTree() };
|
|
544
|
+
case CONTROL_OP.STAT:
|
|
545
|
+
return await backend.stat(str(request, FIELD.PATH));
|
|
546
|
+
case CONTROL_OP.MKDIR:
|
|
547
|
+
await backend.mkdir(str(request, FIELD.PATH));
|
|
548
|
+
return {};
|
|
549
|
+
case CONTROL_OP.RENAME:
|
|
550
|
+
await backend.rename(str(request, FIELD.FROM), str(request, FIELD.TO));
|
|
551
|
+
return {};
|
|
552
|
+
case CONTROL_OP.WATCH_START:
|
|
553
|
+
return this.startWatch(request);
|
|
554
|
+
case CONTROL_OP.WATCH_STOP:
|
|
555
|
+
this.watch?.stop();
|
|
556
|
+
this.watch = null;
|
|
557
|
+
return {};
|
|
558
|
+
case CONTROL_OP.EXEC:
|
|
559
|
+
return this.deps.exec.run(execCommand(request));
|
|
560
|
+
default:
|
|
561
|
+
throw new ControlFsError(CONTROL_ERROR.UNSUPPORTED, `unknown op ${request.op}`);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
startWatch(request) {
|
|
565
|
+
this.watch?.stop();
|
|
566
|
+
this.epoch += 1;
|
|
567
|
+
this.seq = 0;
|
|
568
|
+
const epoch = this.epoch;
|
|
569
|
+
const paths = Array.isArray(request.paths) ? request.paths : [WORKSPACE_ROOT];
|
|
570
|
+
this.watch = this.deps.watcher.start(
|
|
571
|
+
paths,
|
|
572
|
+
(type, changed) => {
|
|
573
|
+
if (this.epoch !== epoch) return;
|
|
574
|
+
this.seq += 1;
|
|
575
|
+
this.send({ event: type, paths: changed, seq: this.seq, epoch });
|
|
576
|
+
},
|
|
577
|
+
() => {
|
|
578
|
+
if (this.epoch !== epoch) return;
|
|
579
|
+
this.send({ event: WATCH_EVENT.RESYNC, epoch });
|
|
580
|
+
}
|
|
581
|
+
);
|
|
582
|
+
return { epoch };
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
var WORKSPACE_ROOT = ".";
|
|
586
|
+
var FIELD = {
|
|
587
|
+
PATH: "path",
|
|
588
|
+
CONTENT: "content",
|
|
589
|
+
FROM: "from",
|
|
590
|
+
TO: "to"
|
|
591
|
+
};
|
|
592
|
+
function str(request, field) {
|
|
593
|
+
const value = request[field];
|
|
594
|
+
if (typeof value !== "string") {
|
|
595
|
+
throw new ControlFsError(CONTROL_ERROR.INVALID_PATH, `missing string field '${field}'`);
|
|
596
|
+
}
|
|
597
|
+
return value;
|
|
598
|
+
}
|
|
599
|
+
function enc(request) {
|
|
600
|
+
return request.encoding === ENCODING.BASE64 ? ENCODING.BASE64 : ENCODING.UTF8;
|
|
601
|
+
}
|
|
602
|
+
function execCommand(request) {
|
|
603
|
+
const command = request.command;
|
|
604
|
+
if (typeof command === "string") return command;
|
|
605
|
+
if (Array.isArray(command) && command.every((part) => typeof part === "string")) {
|
|
606
|
+
return command;
|
|
607
|
+
}
|
|
608
|
+
throw new ControlFsError(CONTROL_ERROR.INVALID_PATH, "exec requires a command");
|
|
609
|
+
}
|
|
610
|
+
function resolveInRoot(root, rel) {
|
|
611
|
+
const resolved = path.resolve(root, rel);
|
|
612
|
+
const rootWithSep = root.endsWith(path.sep) ? root : root + path.sep;
|
|
613
|
+
if (resolved !== root && !resolved.startsWith(rootWithSep)) {
|
|
614
|
+
throw new ControlFsError(CONTROL_ERROR.INVALID_PATH, `path escapes workspace: ${rel}`);
|
|
615
|
+
}
|
|
616
|
+
return resolved;
|
|
617
|
+
}
|
|
618
|
+
function isIgnored(rel) {
|
|
619
|
+
return rel.split(/[\\/]/).some((segment) => DEFAULT_IGNORED.has(segment));
|
|
620
|
+
}
|
|
621
|
+
var NodeControlFs = class {
|
|
622
|
+
constructor(root) {
|
|
623
|
+
this.root = root;
|
|
624
|
+
}
|
|
625
|
+
root;
|
|
626
|
+
async read(rel) {
|
|
627
|
+
const abs = resolveInRoot(this.root, rel);
|
|
628
|
+
const bytes = await promises.readFile(abs).catch(rethrow(rel));
|
|
629
|
+
const text = tryDecodeUtf8(bytes);
|
|
630
|
+
return text !== null ? { content: text, encoding: ENCODING.UTF8 } : { content: Buffer.from(bytes).toString("base64"), encoding: ENCODING.BASE64 };
|
|
631
|
+
}
|
|
632
|
+
async write(rel, content, encoding) {
|
|
633
|
+
const abs = resolveInRoot(this.root, rel);
|
|
634
|
+
await promises.mkdir(path.dirname(abs), { recursive: true });
|
|
635
|
+
const bytes = encoding === ENCODING.BASE64 ? Buffer.from(content, "base64") : Buffer.from(content, "utf8");
|
|
636
|
+
await promises.writeFile(abs, bytes).catch(rethrow(rel));
|
|
637
|
+
}
|
|
638
|
+
async delete(rel, recursive) {
|
|
639
|
+
const abs = resolveInRoot(this.root, rel);
|
|
640
|
+
await promises.rm(abs, { recursive, force: true });
|
|
641
|
+
}
|
|
642
|
+
async list(rel) {
|
|
643
|
+
const abs = resolveInRoot(this.root, rel);
|
|
644
|
+
const dirents = await promises.readdir(abs, { withFileTypes: true }).catch(rethrow(rel));
|
|
645
|
+
return dirents.filter((d) => !DEFAULT_IGNORED.has(d.name)).map((d) => ({ name: d.name, dir: d.isDirectory() }));
|
|
646
|
+
}
|
|
647
|
+
async listTree() {
|
|
648
|
+
const out = [];
|
|
649
|
+
const walk = async (dir) => {
|
|
650
|
+
const dirents = await promises.readdir(path.join(this.root, dir), { withFileTypes: true });
|
|
651
|
+
for (const dirent of dirents) {
|
|
652
|
+
if (DEFAULT_IGNORED.has(dirent.name)) continue;
|
|
653
|
+
const rel = dir ? `${dir}/${dirent.name}` : dirent.name;
|
|
654
|
+
if (dirent.isDirectory()) await walk(rel);
|
|
655
|
+
else out.push(rel);
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
await walk("");
|
|
659
|
+
return out;
|
|
660
|
+
}
|
|
661
|
+
async stat(rel) {
|
|
662
|
+
const abs = resolveInRoot(this.root, rel);
|
|
663
|
+
const stat = await promises.stat(abs).catch(rethrow(rel));
|
|
664
|
+
return {
|
|
665
|
+
kind: stat.isDirectory() ? "dir" : "file",
|
|
666
|
+
size: stat.size,
|
|
667
|
+
mtimeMs: Math.floor(stat.mtimeMs)
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
async mkdir(rel) {
|
|
671
|
+
await promises.mkdir(resolveInRoot(this.root, rel), { recursive: true });
|
|
672
|
+
}
|
|
673
|
+
async rename(from, to) {
|
|
674
|
+
const absFrom = resolveInRoot(this.root, from);
|
|
675
|
+
const absTo = resolveInRoot(this.root, to);
|
|
676
|
+
await promises.mkdir(path.dirname(absTo), { recursive: true });
|
|
677
|
+
await promises.rename(absFrom, absTo).catch(rethrow(from));
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
var WATCH_DEBOUNCE_MS = 60;
|
|
681
|
+
var NodeControlWatcher = class {
|
|
682
|
+
constructor(root) {
|
|
683
|
+
this.root = root;
|
|
684
|
+
}
|
|
685
|
+
root;
|
|
686
|
+
start(_relPaths, onEvent, onResync) {
|
|
687
|
+
let watcher;
|
|
688
|
+
const pending = /* @__PURE__ */ new Map();
|
|
689
|
+
const flush = (rel) => {
|
|
690
|
+
pending.delete(rel);
|
|
691
|
+
promises.stat(path.join(this.root, rel)).then(
|
|
692
|
+
(stat) => onEvent(stat.isDirectory() ? WATCH_EVENT.ADD : WATCH_EVENT.CHANGE, [rel]),
|
|
693
|
+
() => onEvent(WATCH_EVENT.REMOVE, [rel])
|
|
694
|
+
);
|
|
695
|
+
};
|
|
696
|
+
try {
|
|
697
|
+
watcher = watch(this.root, { recursive: true }, (_type, filename) => {
|
|
698
|
+
if (filename === null) {
|
|
699
|
+
onResync();
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
const rel = filename.toString().split(path.sep).join("/");
|
|
703
|
+
if (isIgnored(rel)) return;
|
|
704
|
+
const existing = pending.get(rel);
|
|
705
|
+
if (existing) clearTimeout(existing);
|
|
706
|
+
pending.set(
|
|
707
|
+
rel,
|
|
708
|
+
setTimeout(() => flush(rel), WATCH_DEBOUNCE_MS)
|
|
709
|
+
);
|
|
710
|
+
});
|
|
711
|
+
} catch (error) {
|
|
712
|
+
onResync();
|
|
713
|
+
return { stop: () => {
|
|
714
|
+
} };
|
|
715
|
+
}
|
|
716
|
+
watcher.on("error", () => onResync());
|
|
717
|
+
return {
|
|
718
|
+
stop: () => {
|
|
719
|
+
for (const timer of pending.values()) clearTimeout(timer);
|
|
720
|
+
pending.clear();
|
|
721
|
+
watcher.close();
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
var EXEC_MAX_BUFFER = 8 * 1024 * 1024;
|
|
727
|
+
var NodeControlExec = class {
|
|
728
|
+
constructor(root) {
|
|
729
|
+
this.root = root;
|
|
730
|
+
}
|
|
731
|
+
root;
|
|
732
|
+
run(command) {
|
|
733
|
+
const [file, args, shell] = Array.isArray(command) ? [command[0], command.slice(1), false] : [command, [], true];
|
|
734
|
+
return new Promise((resolve) => {
|
|
735
|
+
const child = spawn(file, args, { cwd: this.root, shell, env: process.env });
|
|
736
|
+
let stdout = "";
|
|
737
|
+
let stderr = "";
|
|
738
|
+
let truncated = false;
|
|
739
|
+
const cap = (existing, chunk) => {
|
|
740
|
+
if (existing.length >= EXEC_MAX_BUFFER) {
|
|
741
|
+
truncated = true;
|
|
742
|
+
return existing;
|
|
743
|
+
}
|
|
744
|
+
return existing + chunk.toString("utf8");
|
|
745
|
+
};
|
|
746
|
+
child.stdout?.on("data", (chunk) => stdout = cap(stdout, chunk));
|
|
747
|
+
child.stderr?.on("data", (chunk) => stderr = cap(stderr, chunk));
|
|
748
|
+
child.on("error", (error) => resolve({ stdout, stderr: error.message, exitCode: 127 }));
|
|
749
|
+
child.on("close", (code) => {
|
|
750
|
+
if (truncated) stderr += "\n[output truncated]";
|
|
751
|
+
resolve({ stdout, stderr, exitCode: code ?? 0 });
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
function tryDecodeUtf8(bytes) {
|
|
757
|
+
try {
|
|
758
|
+
const text = new TextDecoder("utf8", { fatal: true }).decode(bytes);
|
|
759
|
+
return text;
|
|
760
|
+
} catch {
|
|
761
|
+
return null;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
function rethrow(rel) {
|
|
765
|
+
return (error) => {
|
|
766
|
+
if (error.code === "ENOENT") throw new ControlFsError(CONTROL_ERROR.NOT_FOUND, `not found: ${rel}`);
|
|
767
|
+
if (error.code === "EACCES") throw new ControlFsError(CONTROL_ERROR.PERMISSION_DENIED, rel);
|
|
768
|
+
throw new ControlFsError(CONTROL_ERROR.IO, error.message);
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
|
|
370
772
|
// src/tunnel/protocol.ts
|
|
371
773
|
var MAX_PAYLOAD = 262144;
|
|
372
774
|
var HEADER_LEN2 = 9;
|
|
@@ -419,13 +821,13 @@ function decodeFrame(bytes) {
|
|
|
419
821
|
}
|
|
420
822
|
return { streamId, frameType: rawType, payload: bytes.subarray(HEADER_LEN2) };
|
|
421
823
|
}
|
|
422
|
-
var
|
|
423
|
-
var
|
|
824
|
+
var textEncoder4 = new TextEncoder();
|
|
825
|
+
var textDecoder3 = new TextDecoder();
|
|
424
826
|
function encodeJsonPayload(value) {
|
|
425
|
-
return
|
|
827
|
+
return textEncoder4.encode(JSON.stringify(value));
|
|
426
828
|
}
|
|
427
829
|
function decodeJsonPayload(payload) {
|
|
428
|
-
return JSON.parse(
|
|
830
|
+
return JSON.parse(textDecoder3.decode(payload));
|
|
429
831
|
}
|
|
430
832
|
function* chunkPayload(bytes) {
|
|
431
833
|
if (bytes.length === 0) {
|
|
@@ -454,8 +856,8 @@ var HOP_BY_HOP_HEADERS2 = /* @__PURE__ */ new Set([
|
|
|
454
856
|
"transfer-encoding",
|
|
455
857
|
"upgrade"
|
|
456
858
|
]);
|
|
457
|
-
var
|
|
458
|
-
var
|
|
859
|
+
var textEncoder5 = new TextEncoder();
|
|
860
|
+
var textDecoder4 = new TextDecoder();
|
|
459
861
|
function defaultSocketFactory(url, protocols) {
|
|
460
862
|
const ctor = globalThis.WebSocket;
|
|
461
863
|
if (!ctor) {
|
|
@@ -705,7 +1107,7 @@ var HttpProxyStream = class {
|
|
|
705
1107
|
status: 502,
|
|
706
1108
|
headers: [HEADER_CONTENT_TYPE_TEXT]
|
|
707
1109
|
});
|
|
708
|
-
this.ctx.send(FRAME_TYPE.BODY,
|
|
1110
|
+
this.ctx.send(FRAME_TYPE.BODY, textEncoder5.encode(`dev server unreachable: ${err.message}`));
|
|
709
1111
|
this.ctx.send(FRAME_TYPE.END, EMPTY_PAYLOAD);
|
|
710
1112
|
this.ctx.finish();
|
|
711
1113
|
}
|
|
@@ -736,7 +1138,7 @@ var WsProxyStream = class {
|
|
|
736
1138
|
status: 502,
|
|
737
1139
|
headers: [HEADER_CONTENT_TYPE_TEXT]
|
|
738
1140
|
});
|
|
739
|
-
this.ctx.send(FRAME_TYPE.BODY,
|
|
1141
|
+
this.ctx.send(FRAME_TYPE.BODY, textEncoder5.encode("dev server refused the websocket"));
|
|
740
1142
|
this.ctx.send(FRAME_TYPE.END, EMPTY_PAYLOAD);
|
|
741
1143
|
this.ctx.finish();
|
|
742
1144
|
});
|
|
@@ -748,7 +1150,7 @@ var WsProxyStream = class {
|
|
|
748
1150
|
handleFrame(frame) {
|
|
749
1151
|
switch (frame.frameType) {
|
|
750
1152
|
case FRAME_TYPE.WS_TEXT:
|
|
751
|
-
this.local.send(
|
|
1153
|
+
this.local.send(textDecoder4.decode(frame.payload));
|
|
752
1154
|
break;
|
|
753
1155
|
case FRAME_TYPE.WS_BIN:
|
|
754
1156
|
this.local.send(frame.payload);
|
|
@@ -776,7 +1178,7 @@ var WsProxyStream = class {
|
|
|
776
1178
|
let payload;
|
|
777
1179
|
let frameType;
|
|
778
1180
|
if (typeof data === "string") {
|
|
779
|
-
payload =
|
|
1181
|
+
payload = textEncoder5.encode(data);
|
|
780
1182
|
frameType = FRAME_TYPE.WS_TEXT;
|
|
781
1183
|
} else if (data instanceof ArrayBuffer) {
|
|
782
1184
|
payload = new Uint8Array(data);
|
|
@@ -902,8 +1304,8 @@ var StreamHandleV2 = class {
|
|
|
902
1304
|
}
|
|
903
1305
|
};
|
|
904
1306
|
var CONNECTION_STREAM_ID = 0;
|
|
905
|
-
var
|
|
906
|
-
var
|
|
1307
|
+
var textEncoder6 = new TextEncoder();
|
|
1308
|
+
var textDecoder5 = new TextDecoder();
|
|
907
1309
|
var SessionV2 = class {
|
|
908
1310
|
constructor(transport, options) {
|
|
909
1311
|
this.transport = transport;
|
|
@@ -927,7 +1329,7 @@ var SessionV2 = class {
|
|
|
927
1329
|
sending = Promise.resolve();
|
|
928
1330
|
/** Send our HELLO; the peer's must arrive as its first frame. */
|
|
929
1331
|
async start() {
|
|
930
|
-
const payload =
|
|
1332
|
+
const payload = textEncoder6.encode(JSON.stringify(this.options.local));
|
|
931
1333
|
await this.transport.send(
|
|
932
1334
|
encodeFrameV2({ streamId: CONNECTION_STREAM_ID, frameType: FRAME_TYPE_V2.HELLO, payload })
|
|
933
1335
|
);
|
|
@@ -1153,7 +1555,7 @@ var SessionV2 = class {
|
|
|
1153
1555
|
}
|
|
1154
1556
|
}
|
|
1155
1557
|
sendHead(streamId, frameType, value) {
|
|
1156
|
-
const payload =
|
|
1558
|
+
const payload = textEncoder6.encode(JSON.stringify(value ?? null));
|
|
1157
1559
|
if (payload.length > MAX_HEAD_BYTES) {
|
|
1158
1560
|
return Promise.reject(new SessionV2Error("head exceeds MAX_HEAD_BYTES"));
|
|
1159
1561
|
}
|
|
@@ -1277,7 +1679,7 @@ var SessionV2 = class {
|
|
|
1277
1679
|
function parseJson(payload) {
|
|
1278
1680
|
if (payload.length === 0) return null;
|
|
1279
1681
|
try {
|
|
1280
|
-
return JSON.parse(
|
|
1682
|
+
return JSON.parse(textDecoder5.decode(payload));
|
|
1281
1683
|
} catch {
|
|
1282
1684
|
return null;
|
|
1283
1685
|
}
|
|
@@ -1373,7 +1775,13 @@ var NegotiatingAgentClient = class {
|
|
|
1373
1775
|
const hello = defaultHello();
|
|
1374
1776
|
const transport = new WsTransportV2(socket);
|
|
1375
1777
|
const createLocalSocket = this.options.createLocalSocket ?? defaultSocketFactory;
|
|
1376
|
-
const dispatcher = new AgentDispatcher().register(new HttpProxyKind(makeAgentContext(this.options.localPort, hello, createLocalSocket))).register(new WsSpliceKind(makeAgentContext(this.options.localPort, hello, createLocalSocket)))
|
|
1778
|
+
const dispatcher = new AgentDispatcher().register(new HttpProxyKind(makeAgentContext(this.options.localPort, hello, createLocalSocket))).register(new WsSpliceKind(makeAgentContext(this.options.localPort, hello, createLocalSocket))).register(
|
|
1779
|
+
new ControlKind({
|
|
1780
|
+
fs: new NodeControlFs(this.options.workspaceRoot),
|
|
1781
|
+
watcher: new NodeControlWatcher(this.options.workspaceRoot),
|
|
1782
|
+
exec: new NodeControlExec(this.options.workspaceRoot)
|
|
1783
|
+
})
|
|
1784
|
+
);
|
|
1377
1785
|
const session = new SessionV2(transport, {
|
|
1378
1786
|
role: "agent",
|
|
1379
1787
|
local: hello,
|
|
@@ -1412,7 +1820,7 @@ var TUNNEL_CONFIG_DIR = ".cimplify";
|
|
|
1412
1820
|
var TUNNEL_CONFIG_FILE = "tunnel.json";
|
|
1413
1821
|
var DEFAULT_DEV_SERVER_PORT = 3e3;
|
|
1414
1822
|
function tunnelConfigPath(cwd) {
|
|
1415
|
-
return
|
|
1823
|
+
return path.join(cwd, TUNNEL_CONFIG_DIR, TUNNEL_CONFIG_FILE);
|
|
1416
1824
|
}
|
|
1417
1825
|
async function readTunnelConfig(cwd, env = process.env) {
|
|
1418
1826
|
const url = env[TUNNEL_URL_ENV];
|
|
@@ -1461,17 +1869,18 @@ var CONFIG_POLL_MS = 2e3;
|
|
|
1461
1869
|
var RECONNECT_MIN_MS = 1e3;
|
|
1462
1870
|
var RECONNECT_MAX_MS = 3e4;
|
|
1463
1871
|
var CLOSE_CODE_REPLACED = 4e3;
|
|
1464
|
-
function
|
|
1465
|
-
return new NegotiatingAgentClient({
|
|
1872
|
+
function makeDefaultCreateClient(workspaceRoot) {
|
|
1873
|
+
return (config, events) => new NegotiatingAgentClient({
|
|
1466
1874
|
url: config.url,
|
|
1467
1875
|
token: config.token,
|
|
1468
1876
|
localPort: config.localPort,
|
|
1877
|
+
workspaceRoot,
|
|
1469
1878
|
events
|
|
1470
1879
|
});
|
|
1471
1880
|
}
|
|
1472
1881
|
function startTunnelRuntime(cwd, options = {}) {
|
|
1473
1882
|
const pollIntervalMs = options.pollIntervalMs ?? CONFIG_POLL_MS;
|
|
1474
|
-
const createClient = options.createClient ??
|
|
1883
|
+
const createClient = options.createClient ?? makeDefaultCreateClient(cwd);
|
|
1475
1884
|
const onStatus = options.onStatus ?? ((message) => info(dim(message)));
|
|
1476
1885
|
let stopped = false;
|
|
1477
1886
|
let generation = 0;
|
|
@@ -1609,11 +2018,11 @@ function envEndpoint(businessId, projectId) {
|
|
|
1609
2018
|
return `/v1/businesses/${encodeURIComponent(businessId)}/projects/${encodeURIComponent(projectId)}/env-vars`;
|
|
1610
2019
|
}
|
|
1611
2020
|
async function detectPackageManager(cwd) {
|
|
1612
|
-
if (await pathExists(
|
|
1613
|
-
if (await pathExists(
|
|
1614
|
-
if (await pathExists(
|
|
1615
|
-
if (await pathExists(
|
|
1616
|
-
if (await pathExists(
|
|
2021
|
+
if (await pathExists(path.join(cwd, LOCKFILE_BUN))) return PM_BUN;
|
|
2022
|
+
if (await pathExists(path.join(cwd, LOCKFILE_BUN_BINARY))) return PM_BUN;
|
|
2023
|
+
if (await pathExists(path.join(cwd, BUNFIG))) return PM_BUN;
|
|
2024
|
+
if (await pathExists(path.join(cwd, LOCKFILE_PNPM))) return PM_PNPM;
|
|
2025
|
+
if (await pathExists(path.join(cwd, LOCKFILE_YARN))) return PM_YARN;
|
|
1617
2026
|
return PM_NPM;
|
|
1618
2027
|
}
|
|
1619
2028
|
async function pathExists(target) {
|
|
@@ -1626,7 +2035,7 @@ async function pathExists(target) {
|
|
|
1626
2035
|
}
|
|
1627
2036
|
}
|
|
1628
2037
|
async function readPackageJson(cwd) {
|
|
1629
|
-
const pkgPath =
|
|
2038
|
+
const pkgPath = path.join(cwd, PACKAGE_JSON);
|
|
1630
2039
|
let raw;
|
|
1631
2040
|
try {
|
|
1632
2041
|
raw = await promises.readFile(pkgPath, "utf8");
|
|
@@ -1657,7 +2066,7 @@ async function applyRemoteEnv(client, businessId, projectId, apiBaseUrl, cwd) {
|
|
|
1657
2066
|
});
|
|
1658
2067
|
const incoming = records.filter((r) => r.value !== null && !r.is_secret).map((r) => ({ key: r.key, value: r.value }));
|
|
1659
2068
|
incoming.push({ key: PUBLIC_API_URL_KEY, value: apiBaseUrl });
|
|
1660
|
-
const envPath =
|
|
2069
|
+
const envPath = path.join(cwd, ENV_LOCAL_FILE);
|
|
1661
2070
|
let existing = [];
|
|
1662
2071
|
try {
|
|
1663
2072
|
const raw = await promises.readFile(envPath, "utf8");
|
package/dist/dispatcher.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { package_default } from './chunk-FOJVWJ57.mjs';
|
|
3
3
|
import { TEMPLATES } from './chunk-W3WLADJP.mjs';
|
|
4
4
|
|
|
5
5
|
// src/dispatcher.ts
|
|
@@ -142,18 +142,18 @@ var COMMANDS = {
|
|
|
142
142
|
domains: () => import('./domains-H3K2WW55.mjs'),
|
|
143
143
|
logs: () => import('./logs-2ECJQ3MU.mjs'),
|
|
144
144
|
status: () => import('./status-IA7PJ4TV.mjs'),
|
|
145
|
-
dev: () => import('./dev-
|
|
145
|
+
dev: () => import('./dev-6OWQ2FZ7.mjs'),
|
|
146
146
|
mock: () => import('./mock-TSUKCLWU.mjs'),
|
|
147
|
-
introspect: () => import('./introspect-
|
|
147
|
+
introspect: () => import('./introspect-M2KNI7TW.mjs'),
|
|
148
148
|
inspect: () => import('./inspect-CGYX4DDF.mjs'),
|
|
149
|
-
doctor: () => import('./doctor-
|
|
150
|
-
explain: () => import('./explain-
|
|
149
|
+
doctor: () => import('./doctor-UMR72TNV.mjs'),
|
|
150
|
+
explain: () => import('./explain-RD6TURI3.mjs'),
|
|
151
151
|
assets: () => import('./assets-4D7VXRUE.mjs'),
|
|
152
152
|
repo: () => import('./repo-WSUAHXWO.mjs'),
|
|
153
153
|
list: () => import('./list-27TS2L47.mjs'),
|
|
154
154
|
add: () => import('./add-5ODVFWVR.mjs'),
|
|
155
|
-
update: () => import('./update-
|
|
156
|
-
upgrade: () => import('./update-
|
|
155
|
+
update: () => import('./update-MCTGCQIY.mjs'),
|
|
156
|
+
upgrade: () => import('./update-MCTGCQIY.mjs'),
|
|
157
157
|
"auth-step-up": () => import('./auth-step-up-NOSM4PUR.mjs')
|
|
158
158
|
};
|
|
159
159
|
var COMMAND_PREFIXES = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { gatherIntrospection } from './chunk-
|
|
2
|
+
import { gatherIntrospection } from './chunk-JPUGWNVY.mjs';
|
|
3
3
|
import './chunk-K5464A3L.mjs';
|
|
4
4
|
import './chunk-DBZ3UOQ2.mjs';
|
|
5
|
-
import './chunk-
|
|
5
|
+
import './chunk-FOJVWJ57.mjs';
|
|
6
6
|
import { parseArgs, flagBool } from './chunk-C4M3DXKC.mjs';
|
|
7
7
|
import { SDK_ENV_API_URL, DEFAULT_API_BASE_URL, ApiClient, ENV_API_BASE_URL } from './chunk-F4S5KETY.mjs';
|
|
8
8
|
import { readAuthOrNull } from './chunk-UBAI443T.mjs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { package_default } from './chunk-FOJVWJ57.mjs';
|
|
3
3
|
import { parseArgs } from './chunk-C4M3DXKC.mjs';
|
|
4
4
|
import { bold, dim, info, result, CliError, CLI_ERROR_CODE } from './chunk-E2T2SBP5.mjs';
|
|
5
5
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { run as default, extractMockSeed, gatherIntrospection, renderIntrospection } from './chunk-
|
|
2
|
+
export { run as default, extractMockSeed, gatherIntrospection, renderIntrospection } from './chunk-JPUGWNVY.mjs';
|
|
3
3
|
import './chunk-K5464A3L.mjs';
|
|
4
4
|
import './chunk-DBZ3UOQ2.mjs';
|
|
5
|
-
import './chunk-
|
|
5
|
+
import './chunk-FOJVWJ57.mjs';
|
|
6
6
|
import './chunk-C4M3DXKC.mjs';
|
|
7
7
|
import './chunk-UBAI443T.mjs';
|
|
8
8
|
import './chunk-E2T2SBP5.mjs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { package_default } from './chunk-
|
|
2
|
+
import { package_default } from './chunk-FOJVWJ57.mjs';
|
|
3
3
|
import { promptYesNo } from './chunk-ITAFAORS.mjs';
|
|
4
4
|
import { parseArgs, flagBool, flagString } from './chunk-C4M3DXKC.mjs';
|
|
5
5
|
import { success, bold, info, dim, result, failure, CliError, CLI_ERROR_CODE, step, isJsonMode } from './chunk-E2T2SBP5.mjs';
|