@lizard-build/sdk 0.1.72 → 0.1.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.mts +805 -1
- package/dist/index.d.ts +805 -1
- package/dist/index.js +571 -7
- package/dist/index.mjs +555 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27,10 +27,26 @@ __export(index_exports, {
|
|
|
27
27
|
CodeSandbox: () => CodeSandbox,
|
|
28
28
|
ConfigApplyError: () => ConfigApplyError,
|
|
29
29
|
ConflictError: () => ConflictError,
|
|
30
|
+
DEFAULT_GIT_URL: () => DEFAULT_GIT_URL,
|
|
30
31
|
DeployHandle: () => DeployHandle,
|
|
31
32
|
Desktop: () => Desktop,
|
|
32
33
|
DomainsAPI: () => DomainsAPI,
|
|
34
|
+
GitAPI: () => GitAPI,
|
|
35
|
+
GitActionsAPI: () => GitActionsAPI,
|
|
36
|
+
GitBranchRulesAPI: () => GitBranchRulesAPI,
|
|
37
|
+
GitClient: () => GitClient,
|
|
38
|
+
GitCollaboratorsAPI: () => GitCollaboratorsAPI,
|
|
33
39
|
GitHubAPI: () => GitHubAPI,
|
|
40
|
+
GitIssuesOnlyAPI: () => GitIssuesOnlyAPI,
|
|
41
|
+
GitLabelsAPI: () => GitLabelsAPI,
|
|
42
|
+
GitNotificationsAPI: () => GitNotificationsAPI,
|
|
43
|
+
GitPullsAPI: () => GitPullsAPI,
|
|
44
|
+
GitReleasesAPI: () => GitReleasesAPI,
|
|
45
|
+
GitReposAPI: () => GitReposAPI,
|
|
46
|
+
GitSecretsAPI: () => GitSecretsAPI,
|
|
47
|
+
GitStatusesAPI: () => GitStatusesAPI,
|
|
48
|
+
GitTokensAPI: () => GitTokensAPI,
|
|
49
|
+
GitWebhooksAPI: () => GitWebhooksAPI,
|
|
34
50
|
LimitExceededError: () => LimitExceededError,
|
|
35
51
|
Lizard: () => Lizard,
|
|
36
52
|
LizardCLI: () => LizardCLI,
|
|
@@ -179,9 +195,9 @@ async function handleApiError(res) {
|
|
|
179
195
|
// src/platform/client.ts
|
|
180
196
|
var segment = (value) => encodeURIComponent(value);
|
|
181
197
|
function query(path, values) {
|
|
182
|
-
const
|
|
183
|
-
for (const [key, value] of Object.entries(values)) if (value !== void 0)
|
|
184
|
-
return
|
|
198
|
+
const qs2 = new URLSearchParams();
|
|
199
|
+
for (const [key, value] of Object.entries(values)) if (value !== void 0) qs2.set(key, String(value));
|
|
200
|
+
return qs2.size ? `${path}?${qs2}` : path;
|
|
185
201
|
}
|
|
186
202
|
var PlatformClient = class {
|
|
187
203
|
constructor(opts) {
|
|
@@ -535,6 +551,537 @@ var GitHubAPI = class {
|
|
|
535
551
|
}
|
|
536
552
|
};
|
|
537
553
|
|
|
554
|
+
// src/platform/git.ts
|
|
555
|
+
var DEFAULT_GIT_URL = "https://git.lizard.build";
|
|
556
|
+
var seg = encodeURIComponent;
|
|
557
|
+
function qs(path, values) {
|
|
558
|
+
const q = new URLSearchParams();
|
|
559
|
+
for (const [k, v] of Object.entries(values)) if (v !== void 0 && v !== "") q.set(k, String(v));
|
|
560
|
+
return q.size ? `${path}?${q}` : path;
|
|
561
|
+
}
|
|
562
|
+
function segs(p) {
|
|
563
|
+
const parts = p.split("/");
|
|
564
|
+
if (parts.some((x) => x === "" || x === "." || x === "..")) throw new Error(`bad path: "${p}"`);
|
|
565
|
+
return parts.map(seg).join("/");
|
|
566
|
+
}
|
|
567
|
+
function repoPath(repo) {
|
|
568
|
+
const m = /^([^/\s]+)\/([^/\s]+?)(\.git)?$/.exec(repo);
|
|
569
|
+
if (!m || [m[1], m[2]].some((x) => x === "." || x === "..")) throw new Error(`repository must be "owner/name", got "${repo}"`);
|
|
570
|
+
return `/api/repos/${seg(m[1])}/${seg(m[2])}`;
|
|
571
|
+
}
|
|
572
|
+
var GitClient = class {
|
|
573
|
+
constructor(config, url) {
|
|
574
|
+
this.config = config;
|
|
575
|
+
this.url = (url ?? process.env.LIZARD_GIT_URL ?? DEFAULT_GIT_URL).replace(/\/+$/, "");
|
|
576
|
+
}
|
|
577
|
+
async raw(method, path, body, headers = {}) {
|
|
578
|
+
const res = await fetch(this.url + path, {
|
|
579
|
+
method,
|
|
580
|
+
body,
|
|
581
|
+
headers: { "X-API-Key": this.config.apiKey, ...headers },
|
|
582
|
+
redirect: "error",
|
|
583
|
+
// a redirect would carry the key to wherever it points
|
|
584
|
+
signal: AbortSignal.timeout(this.config.requestTimeoutMs)
|
|
585
|
+
});
|
|
586
|
+
if (!res.ok) await handleApiError(res);
|
|
587
|
+
return res;
|
|
588
|
+
}
|
|
589
|
+
async request(method, path, body, headers = {}) {
|
|
590
|
+
const res = await this.raw(
|
|
591
|
+
method,
|
|
592
|
+
path,
|
|
593
|
+
body === void 0 ? void 0 : JSON.stringify(body),
|
|
594
|
+
body === void 0 ? headers : { "Content-Type": "application/json", ...headers }
|
|
595
|
+
);
|
|
596
|
+
const text = res.status === 204 ? "" : await res.text();
|
|
597
|
+
return text ? JSON.parse(text) : void 0;
|
|
598
|
+
}
|
|
599
|
+
get(path) {
|
|
600
|
+
return this.request("GET", path);
|
|
601
|
+
}
|
|
602
|
+
post(path, body) {
|
|
603
|
+
return this.request("POST", path, body ?? {});
|
|
604
|
+
}
|
|
605
|
+
put(path, body) {
|
|
606
|
+
return this.request("PUT", path, body ?? {});
|
|
607
|
+
}
|
|
608
|
+
patch(path, body) {
|
|
609
|
+
return this.request("PATCH", path, body);
|
|
610
|
+
}
|
|
611
|
+
delete(path) {
|
|
612
|
+
return this.request("DELETE", path);
|
|
613
|
+
}
|
|
614
|
+
async bytes(path) {
|
|
615
|
+
return new Uint8Array(await (await this.raw("GET", path)).arrayBuffer());
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
var GitReposAPI = class {
|
|
619
|
+
constructor(c) {
|
|
620
|
+
this.c = c;
|
|
621
|
+
}
|
|
622
|
+
/** Yours and the ones you collaborate on by default; `owner`, `q`, `starred` narrow it. */
|
|
623
|
+
list(opts = {}) {
|
|
624
|
+
return this.c.get(qs("/api/repos", opts));
|
|
625
|
+
}
|
|
626
|
+
/** Answers the new repository's `owner` and `name`. */
|
|
627
|
+
create(opts) {
|
|
628
|
+
return this.c.post("/api/repos", opts);
|
|
629
|
+
}
|
|
630
|
+
get(repo) {
|
|
631
|
+
return this.c.get(repoPath(repo));
|
|
632
|
+
}
|
|
633
|
+
update(repo, opts) {
|
|
634
|
+
return this.c.patch(repoPath(repo), opts);
|
|
635
|
+
}
|
|
636
|
+
delete(repo) {
|
|
637
|
+
return this.c.delete(repoPath(repo));
|
|
638
|
+
}
|
|
639
|
+
star(repo) {
|
|
640
|
+
return this.c.put(`${repoPath(repo)}/star`);
|
|
641
|
+
}
|
|
642
|
+
unstar(repo) {
|
|
643
|
+
return this.c.delete(`${repoPath(repo)}/star`);
|
|
644
|
+
}
|
|
645
|
+
/** Fork into your account (`name` defaults to the same name). */
|
|
646
|
+
fork(repo, opts = {}) {
|
|
647
|
+
return this.c.post(`${repoPath(repo)}/forks`, opts);
|
|
648
|
+
}
|
|
649
|
+
forks(repo) {
|
|
650
|
+
return this.c.get(`${repoPath(repo)}/forks`);
|
|
651
|
+
}
|
|
652
|
+
/** Branches and tags. */
|
|
653
|
+
refs(repo) {
|
|
654
|
+
return this.c.get(`${repoPath(repo)}/refs`);
|
|
655
|
+
}
|
|
656
|
+
createBranch(repo, name, from) {
|
|
657
|
+
return this.c.post(`${repoPath(repo)}/branches`, { name, from });
|
|
658
|
+
}
|
|
659
|
+
deleteBranch(repo, name) {
|
|
660
|
+
return this.c.delete(`${repoPath(repo)}/branches/${segs(name)}`);
|
|
661
|
+
}
|
|
662
|
+
tree(repo, opts = {}) {
|
|
663
|
+
return this.c.get(qs(`${repoPath(repo)}/tree`, opts));
|
|
664
|
+
}
|
|
665
|
+
/** A file as JSON (text in `content`). */
|
|
666
|
+
file(repo, path, ref) {
|
|
667
|
+
return this.c.get(qs(`${repoPath(repo)}/blob`, { path, ref }));
|
|
668
|
+
}
|
|
669
|
+
/** A file's bytes, whatever its size or type. */
|
|
670
|
+
raw(repo, path, ref) {
|
|
671
|
+
repoPath(repo);
|
|
672
|
+
const [owner, name] = repo.split("/");
|
|
673
|
+
return this.c.bytes(`/raw/${seg(owner)}/${seg(name)}/${segs(ref)}/${segs(path)}`);
|
|
674
|
+
}
|
|
675
|
+
/** Every file path at a ref. */
|
|
676
|
+
files(repo, ref) {
|
|
677
|
+
return this.c.get(qs(`${repoPath(repo)}/files`, { ref }));
|
|
678
|
+
}
|
|
679
|
+
search(repo, q, ref) {
|
|
680
|
+
return this.c.get(qs(`${repoPath(repo)}/search`, { q, ref }));
|
|
681
|
+
}
|
|
682
|
+
commits(repo, opts = {}) {
|
|
683
|
+
return this.c.get(qs(`${repoPath(repo)}/commits`, opts));
|
|
684
|
+
}
|
|
685
|
+
commit(repo, sha) {
|
|
686
|
+
return this.c.get(`${repoPath(repo)}/commits/${seg(sha)}`);
|
|
687
|
+
}
|
|
688
|
+
compare(repo, base, head) {
|
|
689
|
+
return this.c.get(qs(`${repoPath(repo)}/compare`, { base, head }));
|
|
690
|
+
}
|
|
691
|
+
/** Commit files on the server: no clone, no push. Answers 409 when `expect` no longer matches. */
|
|
692
|
+
commitFiles(repo, opts) {
|
|
693
|
+
const { idempotencyKey, ...body } = opts;
|
|
694
|
+
return this.c.request("POST", `${repoPath(repo)}/commits`, body, idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {});
|
|
695
|
+
}
|
|
696
|
+
/** Rebase `head` (branch or commit) onto `onto` on the server and move `onto` there; retried on races. */
|
|
697
|
+
land(repo, opts) {
|
|
698
|
+
return this.c.post(`${repoPath(repo)}/land`, opts);
|
|
699
|
+
}
|
|
700
|
+
/** Who moved which branch, when. */
|
|
701
|
+
reflog(repo, ref) {
|
|
702
|
+
return this.c.get(qs(`${repoPath(repo)}/reflog`, { ref }));
|
|
703
|
+
}
|
|
704
|
+
archive(repo, ref, format = "tar.gz") {
|
|
705
|
+
return this.c.bytes(`${repoPath(repo)}/archive/${seg(ref)}.${format}`);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* The HTTPS clone URL. With `withKey`, it carries the API key, so plain `git clone` works
|
|
709
|
+
* without a helper; git then keeps it in .git/config. For anything shared or logged, use a
|
|
710
|
+
* limited Lizard Git token (`tokens.create`) as `apiKey` instead of the account's key.
|
|
711
|
+
*/
|
|
712
|
+
cloneUrl(repo, opts = {}) {
|
|
713
|
+
repoPath(repo);
|
|
714
|
+
const u = new URL(`${this.c.url}/${repo.replace(/\.git$/, "")}.git`);
|
|
715
|
+
if (opts.withKey) {
|
|
716
|
+
u.username = "lizard";
|
|
717
|
+
u.password = this.c.config.apiKey;
|
|
718
|
+
}
|
|
719
|
+
return u.toString();
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
var GitIssuesAPI = class {
|
|
723
|
+
constructor(c, pulls = false) {
|
|
724
|
+
this.c = c;
|
|
725
|
+
this.pulls = pulls;
|
|
726
|
+
}
|
|
727
|
+
base(repo) {
|
|
728
|
+
return `${repoPath(repo)}/issues`;
|
|
729
|
+
}
|
|
730
|
+
list(repo, opts = {}) {
|
|
731
|
+
return this.c.get(qs(this.base(repo), { ...opts, pulls: this.pulls ? 1 : void 0 }));
|
|
732
|
+
}
|
|
733
|
+
get(repo, number) {
|
|
734
|
+
return this.c.get(`${this.base(repo)}/${number}`);
|
|
735
|
+
}
|
|
736
|
+
update(repo, number, opts) {
|
|
737
|
+
return this.c.patch(`${this.base(repo)}/${number}`, opts);
|
|
738
|
+
}
|
|
739
|
+
comment(repo, number, body) {
|
|
740
|
+
return this.c.post(`${this.base(repo)}/${number}/comments`, { body });
|
|
741
|
+
}
|
|
742
|
+
close(repo, number) {
|
|
743
|
+
return this.update(repo, number, { state: "closed" });
|
|
744
|
+
}
|
|
745
|
+
reopen(repo, number) {
|
|
746
|
+
return this.update(repo, number, { state: "open" });
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
var GitIssuesOnlyAPI = class extends GitIssuesAPI {
|
|
750
|
+
constructor(c) {
|
|
751
|
+
super(c, false);
|
|
752
|
+
}
|
|
753
|
+
create(repo, opts) {
|
|
754
|
+
return this.c.post(this.base(repo), opts);
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
var GitPullsAPI = class extends GitIssuesAPI {
|
|
758
|
+
constructor(c) {
|
|
759
|
+
super(c, true);
|
|
760
|
+
}
|
|
761
|
+
create(repo, opts) {
|
|
762
|
+
return this.c.post(this.base(repo), opts);
|
|
763
|
+
}
|
|
764
|
+
/** Mark a draft ready for review. */
|
|
765
|
+
ready(repo, number) {
|
|
766
|
+
return this.update(repo, number, { draft: false });
|
|
767
|
+
}
|
|
768
|
+
merge(repo, number, opts = {}) {
|
|
769
|
+
return this.c.post(`${repoPath(repo)}/pulls/${number}/merge`, opts);
|
|
770
|
+
}
|
|
771
|
+
diff(repo, number) {
|
|
772
|
+
return this.c.get(`${repoPath(repo)}/pulls/${number}/diff`);
|
|
773
|
+
}
|
|
774
|
+
commits(repo, number) {
|
|
775
|
+
return this.c.get(`${repoPath(repo)}/pulls/${number}/commits`);
|
|
776
|
+
}
|
|
777
|
+
reviews(repo, number) {
|
|
778
|
+
return this.c.get(`${repoPath(repo)}/pulls/${number}/reviews`);
|
|
779
|
+
}
|
|
780
|
+
review(repo, number, opts) {
|
|
781
|
+
return this.c.post(`${repoPath(repo)}/pulls/${number}/reviews`, opts);
|
|
782
|
+
}
|
|
783
|
+
approve(repo, number, body = "") {
|
|
784
|
+
return this.review(repo, number, { event: "APPROVE", body });
|
|
785
|
+
}
|
|
786
|
+
requestChanges(repo, number, body) {
|
|
787
|
+
return this.review(repo, number, { event: "REQUEST_CHANGES", body });
|
|
788
|
+
}
|
|
789
|
+
lineComment(repo, number, c) {
|
|
790
|
+
return this.c.post(`${repoPath(repo)}/pulls/${number}/comments`, c);
|
|
791
|
+
}
|
|
792
|
+
deleteLineComment(repo, number, id) {
|
|
793
|
+
return this.c.delete(`${repoPath(repo)}/pulls/${number}/comments/${id}`);
|
|
794
|
+
}
|
|
795
|
+
/** The combined commit status of the pull request's head (CI and external checks). */
|
|
796
|
+
async checks(repo, number) {
|
|
797
|
+
const { pull } = await this.get(repo, number);
|
|
798
|
+
if (!pull?.headSha) throw new Error(`pull request #${number} has no head commit`);
|
|
799
|
+
return this.c.get(`${repoPath(repo)}/commits/${pull.headSha}/status`);
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
var GitSecretsAPI = class {
|
|
803
|
+
constructor(c) {
|
|
804
|
+
this.c = c;
|
|
805
|
+
}
|
|
806
|
+
list(repo) {
|
|
807
|
+
return this.c.get(`${repoPath(repo)}/actions/secrets`);
|
|
808
|
+
}
|
|
809
|
+
set(repo, name, value) {
|
|
810
|
+
return this.c.put(`${repoPath(repo)}/actions/secrets/${seg(name)}`, { value });
|
|
811
|
+
}
|
|
812
|
+
delete(repo, name) {
|
|
813
|
+
return this.c.delete(`${repoPath(repo)}/actions/secrets/${seg(name)}`);
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
var GitActionsAPI = class {
|
|
817
|
+
constructor(c) {
|
|
818
|
+
this.c = c;
|
|
819
|
+
this.secrets = new GitSecretsAPI(c);
|
|
820
|
+
}
|
|
821
|
+
runs(repo, opts = {}) {
|
|
822
|
+
return this.c.get(qs(`${repoPath(repo)}/actions/runs`, { ...opts }));
|
|
823
|
+
}
|
|
824
|
+
run(repo, number) {
|
|
825
|
+
return this.c.get(`${repoPath(repo)}/actions/runs/${number}`);
|
|
826
|
+
}
|
|
827
|
+
cancel(repo, number) {
|
|
828
|
+
return this.c.post(`${repoPath(repo)}/actions/runs/${number}/cancel`);
|
|
829
|
+
}
|
|
830
|
+
/** Run the same workflow at the same commit again (a new run). */
|
|
831
|
+
rerun(repo, number) {
|
|
832
|
+
return this.c.post(`${repoPath(repo)}/actions/runs/${number}/rerun`);
|
|
833
|
+
}
|
|
834
|
+
/** Let a run from a fork's pull request start (it waits for someone with write access). */
|
|
835
|
+
approve(repo, number) {
|
|
836
|
+
return this.c.post(`${repoPath(repo)}/actions/runs/${number}/approve`);
|
|
837
|
+
}
|
|
838
|
+
/** Part of a job's log from `offset`; follow `next` until `done`. */
|
|
839
|
+
log(repo, jobId, offset = 0) {
|
|
840
|
+
return this.c.get(qs(`${repoPath(repo)}/actions/jobs/${jobId}/log`, { offset }));
|
|
841
|
+
}
|
|
842
|
+
async fullLog(repo, jobId) {
|
|
843
|
+
return new TextDecoder().decode(await this.c.bytes(`${repoPath(repo)}/actions/jobs/${jobId}/log.txt`));
|
|
844
|
+
}
|
|
845
|
+
/** Each new piece of the log as it's written, until the job ends. */
|
|
846
|
+
async *followLog(repo, jobId, opts = {}) {
|
|
847
|
+
let offset = 0;
|
|
848
|
+
while (!opts.signal?.aborted) {
|
|
849
|
+
const chunk = await this.log(repo, jobId, offset);
|
|
850
|
+
if (chunk.text) yield chunk.text;
|
|
851
|
+
offset = chunk.next;
|
|
852
|
+
if (chunk.done && offset >= chunk.size) return;
|
|
853
|
+
if (!chunk.text) await new Promise((r) => setTimeout(r, opts.intervalMs ?? 1500));
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
/** Wait until the run ends (success, failure, cancelled, ...). */
|
|
857
|
+
async wait(repo, number, opts = {}) {
|
|
858
|
+
const until = Date.now() + (opts.timeoutMs ?? 30 * 6e4);
|
|
859
|
+
for (; ; ) {
|
|
860
|
+
const run = await this.run(repo, number);
|
|
861
|
+
if (!["queued", "running", "waiting", "pending"].includes(run.status)) return run;
|
|
862
|
+
if (Date.now() > until) throw new Error(`run ${number} is still ${run.status}`);
|
|
863
|
+
await new Promise((r) => setTimeout(r, opts.intervalMs ?? 3e3));
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
artifacts(repo, number) {
|
|
867
|
+
return this.c.get(`${repoPath(repo)}/actions/runs/${number}/artifacts`);
|
|
868
|
+
}
|
|
869
|
+
/** An artifact as a .tar.gz. */
|
|
870
|
+
downloadArtifact(repo, number, name) {
|
|
871
|
+
return this.c.bytes(`${repoPath(repo)}/actions/runs/${number}/artifacts/${seg(name)}`);
|
|
872
|
+
}
|
|
873
|
+
workflows(repo) {
|
|
874
|
+
return this.c.get(`${repoPath(repo)}/actions/workflows`);
|
|
875
|
+
}
|
|
876
|
+
/** Start a workflow that has `on: workflow_dispatch`. */
|
|
877
|
+
dispatch(repo, opts) {
|
|
878
|
+
return this.c.post(`${repoPath(repo)}/actions/workflows/dispatch`, opts);
|
|
879
|
+
}
|
|
880
|
+
/** Latest run status per commit, for the given commits. */
|
|
881
|
+
status(repo, shas) {
|
|
882
|
+
return this.c.get(qs(`${repoPath(repo)}/actions/status`, { shas: shas.join(",") }));
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
var GitCollaboratorsAPI = class {
|
|
886
|
+
constructor(c) {
|
|
887
|
+
this.c = c;
|
|
888
|
+
}
|
|
889
|
+
list(repo) {
|
|
890
|
+
return this.c.get(`${repoPath(repo)}/collaborators`);
|
|
891
|
+
}
|
|
892
|
+
/** Invite someone with a Lizard Git account (they sign in once first); they're in once they accept. */
|
|
893
|
+
invite(repo, login, role = "write") {
|
|
894
|
+
return this.c.post(`${repoPath(repo)}/collaborators`, { login, role });
|
|
895
|
+
}
|
|
896
|
+
setRole(repo, login, role) {
|
|
897
|
+
return this.c.patch(`${repoPath(repo)}/collaborators/${seg(login)}`, { role });
|
|
898
|
+
}
|
|
899
|
+
/** Remove someone (or yourself: leave). */
|
|
900
|
+
remove(repo, login) {
|
|
901
|
+
return this.c.delete(`${repoPath(repo)}/collaborators/${seg(login)}`);
|
|
902
|
+
}
|
|
903
|
+
cancelInvitation(repo, id) {
|
|
904
|
+
return this.c.delete(`${repoPath(repo)}/invitations/${id}`);
|
|
905
|
+
}
|
|
906
|
+
/** Invitations waiting for you. */
|
|
907
|
+
invitations() {
|
|
908
|
+
return this.c.get("/api/user/invitations");
|
|
909
|
+
}
|
|
910
|
+
accept(id) {
|
|
911
|
+
return this.c.post(`/api/user/invitations/${id}/accept`);
|
|
912
|
+
}
|
|
913
|
+
decline(id) {
|
|
914
|
+
return this.c.post(`/api/user/invitations/${id}/decline`);
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
var GitWebhooksAPI = class {
|
|
918
|
+
constructor(c) {
|
|
919
|
+
this.c = c;
|
|
920
|
+
}
|
|
921
|
+
list(repo) {
|
|
922
|
+
return this.c.get(`${repoPath(repo)}/hooks`);
|
|
923
|
+
}
|
|
924
|
+
/** GitHub-style payloads, signed with `X-Hub-Signature-256` when there's a secret. */
|
|
925
|
+
create(repo, opts) {
|
|
926
|
+
return this.c.post(`${repoPath(repo)}/hooks`, opts);
|
|
927
|
+
}
|
|
928
|
+
get(repo, id) {
|
|
929
|
+
return this.c.get(`${repoPath(repo)}/hooks/${id}`);
|
|
930
|
+
}
|
|
931
|
+
update(repo, id, opts) {
|
|
932
|
+
return this.c.patch(`${repoPath(repo)}/hooks/${id}`, opts);
|
|
933
|
+
}
|
|
934
|
+
delete(repo, id) {
|
|
935
|
+
return this.c.delete(`${repoPath(repo)}/hooks/${id}`);
|
|
936
|
+
}
|
|
937
|
+
ping(repo, id) {
|
|
938
|
+
return this.c.post(`${repoPath(repo)}/hooks/${id}/pings`);
|
|
939
|
+
}
|
|
940
|
+
deliveries(repo, id) {
|
|
941
|
+
return this.c.get(`${repoPath(repo)}/hooks/${id}/deliveries`);
|
|
942
|
+
}
|
|
943
|
+
delivery(repo, id, deliveryId) {
|
|
944
|
+
return this.c.get(`${repoPath(repo)}/hooks/${id}/deliveries/${deliveryId}`);
|
|
945
|
+
}
|
|
946
|
+
redeliver(repo, id, deliveryId) {
|
|
947
|
+
return this.c.post(`${repoPath(repo)}/hooks/${id}/deliveries/${deliveryId}/redeliver`);
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
var GitBranchRulesAPI = class {
|
|
951
|
+
constructor(c) {
|
|
952
|
+
this.c = c;
|
|
953
|
+
}
|
|
954
|
+
list(repo) {
|
|
955
|
+
return this.c.get(`${repoPath(repo)}/branch-rules`);
|
|
956
|
+
}
|
|
957
|
+
create(repo, opts) {
|
|
958
|
+
return this.c.post(`${repoPath(repo)}/branch-rules`, opts);
|
|
959
|
+
}
|
|
960
|
+
update(repo, id, opts) {
|
|
961
|
+
return this.c.patch(`${repoPath(repo)}/branch-rules/${id}`, opts);
|
|
962
|
+
}
|
|
963
|
+
delete(repo, id) {
|
|
964
|
+
return this.c.delete(`${repoPath(repo)}/branch-rules/${id}`);
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
var GitLabelsAPI = class {
|
|
968
|
+
constructor(c) {
|
|
969
|
+
this.c = c;
|
|
970
|
+
}
|
|
971
|
+
list(repo) {
|
|
972
|
+
return this.c.get(`${repoPath(repo)}/labels`);
|
|
973
|
+
}
|
|
974
|
+
create(repo, opts) {
|
|
975
|
+
return this.c.post(`${repoPath(repo)}/labels`, opts);
|
|
976
|
+
}
|
|
977
|
+
update(repo, name, opts) {
|
|
978
|
+
return this.c.patch(`${repoPath(repo)}/labels/${seg(name)}`, opts);
|
|
979
|
+
}
|
|
980
|
+
delete(repo, name) {
|
|
981
|
+
return this.c.delete(`${repoPath(repo)}/labels/${seg(name)}`);
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
var GitReleasesAPI = class {
|
|
985
|
+
constructor(c) {
|
|
986
|
+
this.c = c;
|
|
987
|
+
}
|
|
988
|
+
list(repo) {
|
|
989
|
+
return this.c.get(`${repoPath(repo)}/releases`);
|
|
990
|
+
}
|
|
991
|
+
/** Creates the tag too when it doesn't exist (at `target`, default branch by default). */
|
|
992
|
+
create(repo, opts) {
|
|
993
|
+
return this.c.post(`${repoPath(repo)}/releases`, opts);
|
|
994
|
+
}
|
|
995
|
+
get(repo, id) {
|
|
996
|
+
return this.c.get(`${repoPath(repo)}/releases/${id}`);
|
|
997
|
+
}
|
|
998
|
+
getByTag(repo, tag) {
|
|
999
|
+
return this.c.get(`${repoPath(repo)}/releases/tags/${seg(tag)}`);
|
|
1000
|
+
}
|
|
1001
|
+
update(repo, id, opts) {
|
|
1002
|
+
return this.c.patch(`${repoPath(repo)}/releases/${id}`, opts);
|
|
1003
|
+
}
|
|
1004
|
+
delete(repo, id) {
|
|
1005
|
+
return this.c.delete(`${repoPath(repo)}/releases/${id}`);
|
|
1006
|
+
}
|
|
1007
|
+
async uploadAsset(repo, id, name, data, contentType = "application/octet-stream") {
|
|
1008
|
+
const body = typeof data === "string" || data instanceof Blob ? data : new Blob([new Uint8Array(data)]);
|
|
1009
|
+
const res = await this.c.raw("POST", qs(`${repoPath(repo)}/releases/${id}/assets`, { name }), body, { "Content-Type": contentType });
|
|
1010
|
+
return res.json();
|
|
1011
|
+
}
|
|
1012
|
+
downloadAsset(repo, id, assetId) {
|
|
1013
|
+
return this.c.bytes(`${repoPath(repo)}/releases/${id}/assets/${assetId}`);
|
|
1014
|
+
}
|
|
1015
|
+
deleteAsset(repo, id, assetId) {
|
|
1016
|
+
return this.c.delete(`${repoPath(repo)}/releases/${id}/assets/${assetId}`);
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
var GitStatusesAPI = class {
|
|
1020
|
+
constructor(c) {
|
|
1021
|
+
this.c = c;
|
|
1022
|
+
}
|
|
1023
|
+
/** Report a check on a commit (what required checks in branch rules wait for). */
|
|
1024
|
+
create(repo, sha, status) {
|
|
1025
|
+
return this.c.post(`${repoPath(repo)}/statuses/${seg(sha)}`, status);
|
|
1026
|
+
}
|
|
1027
|
+
list(repo, ref) {
|
|
1028
|
+
return this.c.get(`${repoPath(repo)}/commits/${seg(ref)}/statuses`);
|
|
1029
|
+
}
|
|
1030
|
+
combined(repo, ref) {
|
|
1031
|
+
return this.c.get(`${repoPath(repo)}/commits/${seg(ref)}/status`);
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1034
|
+
var GitNotificationsAPI = class {
|
|
1035
|
+
constructor(c) {
|
|
1036
|
+
this.c = c;
|
|
1037
|
+
}
|
|
1038
|
+
list(opts = {}) {
|
|
1039
|
+
return this.c.get(qs("/api/notifications", { all: opts.all ? 1 : void 0 }));
|
|
1040
|
+
}
|
|
1041
|
+
markRead(ids) {
|
|
1042
|
+
return this.c.post("/api/notifications/read", ids?.length ? { ids } : { all: true });
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
var GitTokensAPI = class {
|
|
1046
|
+
constructor(c) {
|
|
1047
|
+
this.c = c;
|
|
1048
|
+
}
|
|
1049
|
+
list() {
|
|
1050
|
+
return this.c.get("/api/user/tokens");
|
|
1051
|
+
}
|
|
1052
|
+
/** A Lizard Git token (lzg_...), optionally limited to repos, refs, paths, or read-only. The secret is in `token`, once. */
|
|
1053
|
+
create(opts) {
|
|
1054
|
+
return this.c.post("/api/user/tokens", opts);
|
|
1055
|
+
}
|
|
1056
|
+
delete(id) {
|
|
1057
|
+
return this.c.delete(`/api/user/tokens/${id}`);
|
|
1058
|
+
}
|
|
1059
|
+
};
|
|
1060
|
+
var GitAPI = class {
|
|
1061
|
+
constructor(config, url) {
|
|
1062
|
+
const c = this.client = new GitClient(config, url);
|
|
1063
|
+
this.repos = new GitReposAPI(c);
|
|
1064
|
+
this.issues = new GitIssuesOnlyAPI(c);
|
|
1065
|
+
this.pulls = new GitPullsAPI(c);
|
|
1066
|
+
this.actions = new GitActionsAPI(c);
|
|
1067
|
+
this.collaborators = new GitCollaboratorsAPI(c);
|
|
1068
|
+
this.webhooks = new GitWebhooksAPI(c);
|
|
1069
|
+
this.branchRules = new GitBranchRulesAPI(c);
|
|
1070
|
+
this.labels = new GitLabelsAPI(c);
|
|
1071
|
+
this.releases = new GitReleasesAPI(c);
|
|
1072
|
+
this.statuses = new GitStatusesAPI(c);
|
|
1073
|
+
this.notifications = new GitNotificationsAPI(c);
|
|
1074
|
+
this.tokens = new GitTokensAPI(c);
|
|
1075
|
+
}
|
|
1076
|
+
/** Who the key signs in as on Lizard Git. */
|
|
1077
|
+
me() {
|
|
1078
|
+
return this.client.get("/api/session");
|
|
1079
|
+
}
|
|
1080
|
+
user(login) {
|
|
1081
|
+
return this.client.get(`/api/users/${seg(login)}`);
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1084
|
+
|
|
538
1085
|
// src/project.ts
|
|
539
1086
|
var import_node_crypto = require("crypto");
|
|
540
1087
|
var projectIdCache = /* @__PURE__ */ new Map();
|
|
@@ -1414,8 +1961,8 @@ var ProjectsAPI = class {
|
|
|
1414
1961
|
}
|
|
1415
1962
|
/** List all projects the API key can access. */
|
|
1416
1963
|
list(opts) {
|
|
1417
|
-
const
|
|
1418
|
-
return this.client.get(`/api/projects${
|
|
1964
|
+
const qs2 = opts?.workspaceId ? `?workspaceId=${opts.workspaceId}` : "";
|
|
1965
|
+
return this.client.get(`/api/projects${qs2}`);
|
|
1419
1966
|
}
|
|
1420
1967
|
/** Get a project by ID. */
|
|
1421
1968
|
get(id) {
|
|
@@ -1808,8 +2355,8 @@ var WorkspacesAPI = class {
|
|
|
1808
2355
|
* volumes and snapshots first.
|
|
1809
2356
|
*/
|
|
1810
2357
|
delete(id, opts) {
|
|
1811
|
-
const
|
|
1812
|
-
return this.client.delete(`/api/workspaces/${id}${
|
|
2358
|
+
const qs2 = opts?.force ? "" : "?requireEmpty=true";
|
|
2359
|
+
return this.client.delete(`/api/workspaces/${id}${qs2}`);
|
|
1813
2360
|
}
|
|
1814
2361
|
/**
|
|
1815
2362
|
* Find a workspace by name, slug, or id, or `null` if there is no such workspace.
|
|
@@ -2091,6 +2638,7 @@ var Lizard = class {
|
|
|
2091
2638
|
this.metrics = new MetricsAPI(platform);
|
|
2092
2639
|
this.storage = new StorageAPI(platform);
|
|
2093
2640
|
this.github = new GitHubAPI(platform);
|
|
2641
|
+
this.git = new GitAPI(this.config, opts.gitUrl);
|
|
2094
2642
|
}
|
|
2095
2643
|
// ── Sandbox convenience methods (backward-compatible) ──────────────────
|
|
2096
2644
|
/** Resolve the client's project reference to a stable project ID (cached). */
|
|
@@ -2703,10 +3251,26 @@ var LizardCLI = class {
|
|
|
2703
3251
|
CodeSandbox,
|
|
2704
3252
|
ConfigApplyError,
|
|
2705
3253
|
ConflictError,
|
|
3254
|
+
DEFAULT_GIT_URL,
|
|
2706
3255
|
DeployHandle,
|
|
2707
3256
|
Desktop,
|
|
2708
3257
|
DomainsAPI,
|
|
3258
|
+
GitAPI,
|
|
3259
|
+
GitActionsAPI,
|
|
3260
|
+
GitBranchRulesAPI,
|
|
3261
|
+
GitClient,
|
|
3262
|
+
GitCollaboratorsAPI,
|
|
2709
3263
|
GitHubAPI,
|
|
3264
|
+
GitIssuesOnlyAPI,
|
|
3265
|
+
GitLabelsAPI,
|
|
3266
|
+
GitNotificationsAPI,
|
|
3267
|
+
GitPullsAPI,
|
|
3268
|
+
GitReleasesAPI,
|
|
3269
|
+
GitReposAPI,
|
|
3270
|
+
GitSecretsAPI,
|
|
3271
|
+
GitStatusesAPI,
|
|
3272
|
+
GitTokensAPI,
|
|
3273
|
+
GitWebhooksAPI,
|
|
2710
3274
|
LimitExceededError,
|
|
2711
3275
|
Lizard,
|
|
2712
3276
|
LizardCLI,
|