GitRoot
Craft your forge, Build your project, Grow your community freely
1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: MIT
4
5import { JSON } from "json-as";
6import { HttpRequest, HttpResponse } from "./server";
7import { FS, FsBaseCache, FsBaseWebcontent, FsBaseWorktree } from "./src/fs";
8import { HttpClient, needServer } from "./src/httpclient";
9import {
10 _call,
11 _canCall,
12 _commitAll,
13 _commits,
14 _diffWithParent,
15 _exec,
16 _forgeConf,
17 _httpClient,
18 _log,
19 _logError,
20 _merge,
21 _report,
22} from "./src/imports";
23import { Call, CallRes } from "./src/model/call";
24import { Commit } from "./src/model/commit";
25import { Exec, ExecStatus } from "./src/model/exec";
26import { ForgeConf } from "./src/model/forgeconf";
27import { PluginRun } from "./src/model/pluginrun";
28import { Report, ReportToGitroot } from "./src/model/report";
29import { exportFuncCallback, Server } from "./src/model/server";
30import { Plugin } from "./src/plugin";
31
32export * from "./src/index";
33
34export let __server: server | null = null;
35
36export function Register(
37 run: Array<PluginRun>,
38 p: (server: Server) => Plugin,
39): void {
40 const s = new server();
41 s.plugin = p(s);
42 s.run = run;
43 __server = s;
44}
45
46type ReporterCallback = (report: Report) => void;
47
48class PluginOption {
49 constructor(public reporter: ReporterCallback) {}
50}
51
52class server implements Server, needServer {
53 private worktreeFS: FS = new FS(FsBaseWorktree);
54 private webcontentFS: FS = new FS(FsBaseWebcontent);
55 private cacheFS: FS = new FS(FsBaseCache);
56 private exportedFuncs: Map<string, exportFuncCallback> = new Map<
57 string,
58 exportFuncCallback
59 >();
60
61 plugin: Plugin | null = null;
62 run: Array<PluginRun> = [];
63 pluginOption: PluginOption | null = null;
64
65 addPluginOption(opt: PluginOption): void {
66 this.pluginOption = opt;
67 }
68
69 getExportedFuncs(name: string): exportFuncCallback {
70 return this.exportedFuncs.get(name);
71 }
72
73 forgeConf(): ForgeConf {
74 const ptrSize = _forgeConf();
75 const ptr = u32((ptrSize >> 32) & 0xffffffff);
76 const size = u32(ptrSize & 0xffffffff);
77 return JSON.parse<ForgeConf>(String.UTF8.decodeUnsafe(ptr, size));
78 }
79
80 worktree(): FS {
81 return this.worktreeFS;
82 }
83
84 webcontent(): FS {
85 return this.webcontentFS;
86 }
87
88 cache(): FS {
89 return this.cacheFS;
90 }
91
92 commitAllIfNeeded(message: string): void {
93 _commitAll(message);
94 }
95
96 diffWithParent(
97 hash: string,
98 oldFilepath: string,
99 newFilepath: string,
100 ): string {
101 const ptrSize = _diffWithParent(hash, oldFilepath, newFilepath);
102 const ptr = u32((ptrSize >> 32) & 0xffffffff);
103 const size = u32(ptrSize & 0xffffffff);
104 return String.UTF8.decodeUnsafe(ptr, size);
105 }
106
107 merge(from: string, to: string): void {
108 _merge(from, to);
109 }
110
111 log(message: string): void {
112 _log(message);
113 }
114
115 logError(message: string, error: string): void {
116 _logError(message, error);
117 }
118
119 commits(from: string, to: string): Array<Commit> {
120 const ptrSize = _commits(from, to);
121 const ptr = u32((ptrSize >> 32) & 0xffffffff);
122 const size = u32(ptrSize & 0xffffffff);
123 return JSON.parse<Array<Commit>>(String.UTF8.decodeUnsafe(ptr, size));
124 }
125
126 exec(exec: Exec): ExecStatus {
127 const execJson = JSON.stringify(exec);
128 const ptrSize = _exec(execJson);
129 const ptr = u32((ptrSize >> 32) & 0xffffffff);
130 const size = u32(ptrSize & 0xffffffff);
131 return JSON.parse<ExecStatus>(String.UTF8.decodeUnsafe(ptr, size));
132 }
133
134 report(level: string, content: Array<string>): void {
135 const reportMarshalled = JSON.stringify(
136 new ReportToGitroot(level, content),
137 );
138 _report(reportMarshalled);
139 }
140
141 reportToPlugin(report: Report): void {
142 if (this.pluginOption != null) {
143 this.pluginOption!.reporter(report);
144 }
145 }
146
147 exportFunc(name: string, callback: exportFuncCallback): void {
148 this.exportedFuncs.set(name, callback);
149 }
150
151 canCallFunc(plugin: string, name: string, args: Map<string, string>): bool {
152 const call = new Call(plugin, name, args);
153 const callJson = JSON.stringify(call);
154 return _canCall(callJson) != 0;
155 }
156
157 callFunc(plugin: string, name: string, args: Map<string, string>): CallRes {
158 const call = new Call(plugin, name, args);
159 const callJson = JSON.stringify(call);
160 const ptrSize = _call(callJson);
161 const ptrRes = u32(ptrSize >> 32);
162 const sizeRes = u32(ptrSize);
163 const res = String.UTF8.decodeUnsafe(ptrRes, sizeRes);
164 return JSON.parse<CallRes>(res);
165 }
166
167 httpClient(header: Map<string, Array<string>>): HttpClient {
168 return new HttpClient(this, header);
169 }
170
171 doRequest(request: HttpRequest): HttpResponse {
172 const requestJson = JSON.stringify(request);
173 const ptrSize = _httpClient(requestJson);
174 if (ptrSize === 0) {
175 return new HttpResponse(0, "unknown error");
176 }
177 const ptrRes = u32(ptrSize >> 32);
178 const sizeRes = u32(ptrSize);
179 const res = String.UTF8.decodeUnsafe(ptrRes, sizeRes);
180 return JSON.parse<HttpResponse>(res);
181 }
182}