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, Iterator } 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, PluginReporter } 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
 46class server implements Server, needServer {
 47  private worktreeFS: FS = new FS(FsBaseWorktree);
 48  private webcontentFS: FS = new FS(FsBaseWebcontent);
 49  private cacheFS: FS = new FS(FsBaseCache);
 50  private exportedFuncs: Map<string, exportFuncCallback> = new Map<
 51    string,
 52    exportFuncCallback
 53  >();
 54
 55  plugin: Plugin | null = null;
 56  run: Array<PluginRun> = [];
 57  pluginOption: PluginReporter | null = null;
 58
 59  addPluginOption(opt: PluginReporter): void {
 60    this.pluginOption = opt;
 61  }
 62
 63  getExportedFuncs(name: string): exportFuncCallback {
 64    return this.exportedFuncs.get(name);
 65  }
 66
 67  forgeConf(): ForgeConf {
 68    const ptrSize = _forgeConf();
 69    const ptr = u32((ptrSize >> 32) & 0xffffffff);
 70    const size = u32(ptrSize & 0xffffffff);
 71    return JSON.parse<ForgeConf>(String.UTF8.decodeUnsafe(ptr, size));
 72  }
 73
 74  worktree(): FS {
 75    return this.worktreeFS;
 76  }
 77
 78  webcontent(): FS {
 79    return this.webcontentFS;
 80  }
 81
 82  cache(): FS {
 83    return this.cacheFS;
 84  }
 85
 86  commitAllIfNeeded(message: string): void {
 87    _commitAll(message);
 88  }
 89
 90  diffWithParent(
 91    hash: string,
 92    oldFilepath: string,
 93    newFilepath: string,
 94  ): string {
 95    const ptrSize = _diffWithParent(hash, oldFilepath, newFilepath);
 96    const ptr = u32((ptrSize >> 32) & 0xffffffff);
 97    const size = u32(ptrSize & 0xffffffff);
 98    return String.UTF8.decodeUnsafe(ptr, size);
 99  }
100
101  merge(from: string, to: string): void {
102    _merge(from, to);
103  }
104
105  log(message: string): void {
106    _log(message);
107  }
108
109  logError(message: string, error: string): void {
110    _logError(message, error);
111  }
112
113  commits(from: string, to: string): Array<Commit> {
114    const ptrSize = _commits(from, to);
115    const ptr = u32((ptrSize >> 32) & 0xffffffff);
116    const size = u32(ptrSize & 0xffffffff);
117    return JSON.parse<Array<Commit>>(String.UTF8.decodeUnsafe(ptr, size));
118  }
119
120  exec(exec: Exec): ExecStatus {
121    const execJson = JSON.stringify(exec);
122    const ptrSize = _exec(execJson);
123    const ptr = u32((ptrSize >> 32) & 0xffffffff);
124    const size = u32(ptrSize & 0xffffffff);
125    return JSON.parse<ExecStatus>(String.UTF8.decodeUnsafe(ptr, size));
126  }
127
128  report(level: string, content: Array<string>): void {
129    const reportMarshalled = JSON.stringify(
130      new ReportToGitroot(level, content),
131    );
132    _report(reportMarshalled);
133  }
134
135  reportToPlugin(iteratorName: string): void {
136    if (this.pluginOption != null) {
137      this.pluginOption!.report(new Iterator<Report>(iteratorName));
138    }
139  }
140
141  exportFunc(name: string, callback: exportFuncCallback): void {
142    this.exportedFuncs.set(name, callback);
143  }
144
145  canCallFunc(plugin: string, name: string, args: Map<string, string>): bool {
146    const call = new Call(plugin, name, args);
147    const callJson = JSON.stringify(call);
148    return _canCall(callJson) != 0;
149  }
150
151  callFunc(plugin: string, name: string, args: Map<string, string>): CallRes {
152    const call = new Call(plugin, name, args);
153    const callJson = JSON.stringify(call);
154    const ptrSize = _call(callJson);
155    const ptrRes = u32(ptrSize >> 32);
156    const sizeRes = u32(ptrSize);
157    const res = String.UTF8.decodeUnsafe(ptrRes, sizeRes);
158    return JSON.parse<CallRes>(res);
159  }
160
161  httpClient(header: Map<string, Array<string>>): HttpClient {
162    return new HttpClient(this, header);
163  }
164
165  doRequest(request: HttpRequest): HttpResponse {
166    const requestJson = JSON.stringify(request);
167    const ptrSize = _httpClient(requestJson);
168    if (ptrSize === 0) {
169      return new HttpResponse(0, "unknown error");
170    }
171    const ptrRes = u32(ptrSize >> 32);
172    const sizeRes = u32(ptrSize);
173    const res = String.UTF8.decodeUnsafe(ptrRes, sizeRes);
174    return JSON.parse<HttpResponse>(res);
175  }
176}