@valbuild/server 0.16.4 → 0.17.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/declarations/src/LocalValServer.d.ts +7 -5
- package/dist/declarations/src/ValServer.d.ts +3 -7
- package/dist/declarations/src/hosting.d.ts +34 -0
- package/dist/declarations/src/index.d.ts +1 -1
- package/dist/valbuild-server.cjs.dev.js +249 -95
- package/dist/valbuild-server.cjs.prod.js +249 -95
- package/dist/valbuild-server.esm.js +232 -96
- package/package.json +3 -3
- package/src/LocalValServer.ts +82 -60
- package/src/ProxyValServer.ts +66 -36
- package/src/Service.ts +4 -3
- package/src/ValQuickJSRuntime.ts +18 -0
- package/src/ValServer.ts +4 -11
- package/src/createRequestHandler.ts +6 -6
- package/src/hosting.ts +122 -1
- package/src/index.ts +1 -1
- package/src/patch/ts/ops.test.ts +0 -1
- package/src/readValFile.ts +2 -2
@@ -3,7 +3,8 @@ import ts from 'typescript';
|
|
3
3
|
import { result, pipe } from '@valbuild/core/fp';
|
4
4
|
import { FILE_REF_PROP, derefPatch, Internal, Schema } from '@valbuild/core';
|
5
5
|
import { deepEqual, isNotRoot, PatchError, parseAndValidateArrayIndex, applyPatch, parsePatch, sourceToPatchPath } from '@valbuild/core/patch';
|
6
|
-
import path from 'path';
|
6
|
+
import * as path from 'path';
|
7
|
+
import path__default from 'path';
|
7
8
|
import fs, { promises } from 'fs';
|
8
9
|
import express, { Router } from 'express';
|
9
10
|
import { createRequestHandler as createRequestHandler$1 } from '@valbuild/ui/server';
|
@@ -558,16 +559,16 @@ import { Internal } from "@valbuild/core";
|
|
558
559
|
globalThis.valModule = {
|
559
560
|
id: valModule?.default && Internal.getValPath(valModule?.default),
|
560
561
|
schema: valModule?.default && Internal.getSchema(valModule?.default)?.serialize(),
|
561
|
-
source: valModule?.default && Internal.
|
562
|
+
source: valModule?.default && Internal.getSource(valModule?.default),
|
562
563
|
validation: valModule?.default && Internal.getSchema(valModule?.default)?.validate(
|
563
564
|
valModule?.default && Internal.getValPath(valModule?.default) || "/",
|
564
|
-
valModule?.default && Internal.
|
565
|
+
valModule?.default && Internal.getSource(valModule?.default)
|
565
566
|
)
|
566
567
|
};
|
567
568
|
`;
|
568
569
|
const result = context.evalCode(code,
|
569
570
|
// Synthetic module name
|
570
|
-
|
571
|
+
path__default.join(path__default.dirname(valConfigPath), "<val>"));
|
571
572
|
const fatalErrors = [];
|
572
573
|
if (result.error) {
|
573
574
|
const error = result.error.consume(context.dump);
|
@@ -679,8 +680,8 @@ const patchSourceFile = (sourceFile, patch) => {
|
|
679
680
|
};
|
680
681
|
|
681
682
|
const getCompilerOptions = (rootDir, parseConfigHost) => {
|
682
|
-
const tsConfigPath =
|
683
|
-
const jsConfigPath =
|
683
|
+
const tsConfigPath = path__default.resolve(rootDir, "tsconfig.json");
|
684
|
+
const jsConfigPath = path__default.resolve(rootDir, "jsconfig.json");
|
684
685
|
let configFilePath;
|
685
686
|
if (parseConfigHost.fileExists(jsConfigPath)) {
|
686
687
|
configFilePath = jsConfigPath;
|
@@ -730,7 +731,7 @@ class ValSourceFileHandler {
|
|
730
731
|
this.host.writeFile(filePath, content, encoding);
|
731
732
|
}
|
732
733
|
resolveSourceModulePath(containingFilePath, requestedModuleName) {
|
733
|
-
const resolutionRes = ts.resolveModuleName(requestedModuleName,
|
734
|
+
const resolutionRes = ts.resolveModuleName(requestedModuleName, path__default.isAbsolute(containingFilePath) ? containingFilePath : path__default.resolve(this.projectRoot, containingFilePath), this.compilerOptions, this.host, undefined, undefined, ts.ModuleKind.ESNext);
|
734
735
|
const resolvedModule = resolutionRes.resolvedModule;
|
735
736
|
if (!resolvedModule) {
|
736
737
|
throw Error(`Could not resolve module "${requestedModuleName}", base: "${containingFilePath}": No resolved modules returned: ${JSON.stringify(resolutionRes)}`);
|
@@ -850,6 +851,16 @@ async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
|
850
851
|
value: "export const useVal = () => { throw Error(`Cannot use 'useVal' in this type of file`) }; export const fetchVal = () => { throw Error(`Cannot use 'fetchVal' in this type of file`) }; export const autoTagJSX = () => { /* ignore */ };"
|
851
852
|
};
|
852
853
|
}
|
854
|
+
if (modulePath.startsWith("next")) {
|
855
|
+
return {
|
856
|
+
value: "export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'next' in this file`) } } } )"
|
857
|
+
};
|
858
|
+
}
|
859
|
+
if (modulePath.startsWith("react")) {
|
860
|
+
return {
|
861
|
+
value: "export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'react' in this file`) } } } )"
|
862
|
+
};
|
863
|
+
}
|
853
864
|
return {
|
854
865
|
value: moduleLoader.getModule(modulePath)
|
855
866
|
};
|
@@ -870,6 +881,16 @@ async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
|
870
881
|
value: requestedName
|
871
882
|
};
|
872
883
|
}
|
884
|
+
if (requestedName.startsWith("next")) {
|
885
|
+
return {
|
886
|
+
value: requestedName
|
887
|
+
};
|
888
|
+
}
|
889
|
+
if (requestedName.startsWith("react")) {
|
890
|
+
return {
|
891
|
+
value: requestedName
|
892
|
+
};
|
893
|
+
}
|
873
894
|
const modulePath = moduleLoader.resolveModulePath(baseModuleName, requestedName);
|
874
895
|
return {
|
875
896
|
value: modulePath
|
@@ -906,7 +927,7 @@ class Service {
|
|
906
927
|
const valModule = await readValFile(moduleId, this.valConfigPath, this.runtime);
|
907
928
|
if (valModule.source && valModule.schema) {
|
908
929
|
const resolved = Internal.resolvePath(modulePath, valModule.source, valModule.schema);
|
909
|
-
const sourcePath = [moduleId, resolved.path].join(".");
|
930
|
+
const sourcePath = resolved.path ? [moduleId, resolved.path].join(".") : moduleId;
|
910
931
|
return {
|
911
932
|
path: sourcePath,
|
912
933
|
schema: resolved.schema instanceof Schema ? resolved.schema.serialize() : resolved.schema,
|
@@ -937,14 +958,14 @@ function createRequestHandler(valServer) {
|
|
937
958
|
router.get("/authorize", valServer.authorize.bind(valServer));
|
938
959
|
router.get("/callback", valServer.callback.bind(valServer));
|
939
960
|
router.get("/logout", valServer.logout.bind(valServer));
|
940
|
-
router.
|
941
|
-
|
942
|
-
router.patch("/ids/*", express.json({
|
943
|
-
type: "application/json-patch+json",
|
961
|
+
router.post("/patches/*", express.json({
|
962
|
+
type: "application/json",
|
944
963
|
limit: "10mb"
|
945
|
-
}), valServer.
|
964
|
+
}), valServer.postPatches.bind(valServer));
|
946
965
|
router.post("/commit", valServer.commit.bind(valServer));
|
947
966
|
router.get("/enable", valServer.enable.bind(valServer));
|
967
|
+
router.get("/disable", valServer.disable.bind(valServer));
|
968
|
+
router.get("/tree/*", valServer.getTree.bind(valServer));
|
948
969
|
return router;
|
949
970
|
}
|
950
971
|
|
@@ -1048,19 +1069,13 @@ function encodeJwt(payload, sessionKey) {
|
|
1048
1069
|
return `${jwtHeaderBase64}.${payloadBase64}.${crypto.createHmac("sha256", sessionKey).update(`${jwtHeaderBase64}.${payloadBase64}`).digest("base64")}`;
|
1049
1070
|
}
|
1050
1071
|
|
1051
|
-
const VAL_SESSION_COOKIE =
|
1052
|
-
const VAL_STATE_COOKIE =
|
1072
|
+
const VAL_SESSION_COOKIE = Internal.VAL_SESSION_COOKIE;
|
1073
|
+
const VAL_STATE_COOKIE = Internal.VAL_STATE_COOKIE;
|
1053
1074
|
const VAL_ENABLED_COOKIE = Internal.VAL_ENABLE_COOKIE_NAME;
|
1054
1075
|
class ProxyValServer {
|
1055
1076
|
constructor(options) {
|
1056
1077
|
this.options = options;
|
1057
1078
|
}
|
1058
|
-
|
1059
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
1060
|
-
getAllModules(_req, _res) {
|
1061
|
-
// TODO:
|
1062
|
-
throw new Error("Method not implemented.");
|
1063
|
-
}
|
1064
1079
|
async authorize(req, res) {
|
1065
1080
|
const {
|
1066
1081
|
redirect_to
|
@@ -1082,7 +1097,10 @@ class ProxyValServer {
|
|
1082
1097
|
}).redirect(appAuthorizeUrl);
|
1083
1098
|
}
|
1084
1099
|
async enable(req, res) {
|
1085
|
-
return enable(req, res);
|
1100
|
+
return enable(req, res, this.options.valEnableRedirectUrl);
|
1101
|
+
}
|
1102
|
+
async disable(req, res) {
|
1103
|
+
return disable(req, res, this.options.valEnableRedirectUrl);
|
1086
1104
|
}
|
1087
1105
|
async callback(req, res) {
|
1088
1106
|
const {
|
@@ -1144,30 +1162,38 @@ class ProxyValServer {
|
|
1144
1162
|
}
|
1145
1163
|
});
|
1146
1164
|
}
|
1147
|
-
async
|
1148
|
-
return this.withAuth(req, res, async
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
} else {
|
1159
|
-
res.sendStatus(fetchRes.status);
|
1160
|
-
}
|
1161
|
-
}).catch(e => {
|
1162
|
-
res.status(500).send({
|
1163
|
-
error: {
|
1164
|
-
message: e === null || e === void 0 ? void 0 : e.message,
|
1165
|
-
status: 500
|
1166
|
-
}
|
1165
|
+
async getTree(req, res) {
|
1166
|
+
return this.withAuth(req, res, async data => {
|
1167
|
+
const {
|
1168
|
+
patch,
|
1169
|
+
schema,
|
1170
|
+
source
|
1171
|
+
} = req.query;
|
1172
|
+
const params = new URLSearchParams({
|
1173
|
+
patch: (patch === "true").toString(),
|
1174
|
+
schema: (schema === "true").toString(),
|
1175
|
+
source: (source === "true").toString()
|
1167
1176
|
});
|
1177
|
+
const url = new URL(`/v1/tree/${this.options.valName}/heads/${this.options.gitBranch}/${req.params["0"]}/?${params}`, this.options.valContentUrl);
|
1178
|
+
const json = await fetch(url, {
|
1179
|
+
headers: this.getAuthHeaders(data.token, "application/json")
|
1180
|
+
}).then(res => res.json());
|
1181
|
+
res.send(json);
|
1168
1182
|
});
|
1169
1183
|
}
|
1170
|
-
async
|
1184
|
+
async postPatches(req, res) {
|
1185
|
+
const {
|
1186
|
+
commit
|
1187
|
+
} = req.query;
|
1188
|
+
if (typeof commit !== "string" || typeof commit === "undefined") {
|
1189
|
+
res.status(401).json({
|
1190
|
+
error: "Missing or invalid commit query param"
|
1191
|
+
});
|
1192
|
+
return;
|
1193
|
+
}
|
1194
|
+
const params = new URLSearchParams({
|
1195
|
+
commit
|
1196
|
+
});
|
1171
1197
|
this.withAuth(req, res, async ({
|
1172
1198
|
token
|
1173
1199
|
}) => {
|
@@ -1183,12 +1209,11 @@ class ProxyValServer {
|
|
1183
1209
|
res.status(401).json(patch.error);
|
1184
1210
|
return;
|
1185
1211
|
}
|
1186
|
-
const
|
1187
|
-
const url = new URL(`/api/val/modules/${encodeURIComponent(this.options.gitCommit)}${id}`, this.options.valBuildUrl);
|
1212
|
+
const url = new URL(`/v1/tree/${this.options.valName}/heads/${this.options.gitBranch}/${req.params["0"]}/?${params}`, this.options.valContentUrl);
|
1188
1213
|
// Proxy patch to val.build
|
1189
1214
|
const fetchRes = await fetch(url, {
|
1190
|
-
method: "
|
1191
|
-
headers: this.getAuthHeaders(token, "application/json
|
1215
|
+
method: "POST",
|
1216
|
+
headers: this.getAuthHeaders(token, "application/json"),
|
1192
1217
|
body: JSON.stringify(patch)
|
1193
1218
|
});
|
1194
1219
|
if (fetchRes.ok) {
|
@@ -1370,15 +1395,36 @@ function getStateFromCookie(stateCookie) {
|
|
1370
1395
|
};
|
1371
1396
|
}
|
1372
1397
|
}
|
1373
|
-
async function enable(req, res) {
|
1398
|
+
async function enable(req, res, redirectUrl) {
|
1374
1399
|
const {
|
1375
1400
|
redirect_to
|
1376
1401
|
} = req.query;
|
1377
1402
|
if (typeof redirect_to === "string" || typeof redirect_to === "undefined") {
|
1403
|
+
let redirectUrlToUse = redirect_to || "/";
|
1404
|
+
if (redirectUrl) {
|
1405
|
+
redirectUrlToUse = redirectUrl + "?redirect_to=" + encodeURIComponent(redirectUrlToUse);
|
1406
|
+
}
|
1378
1407
|
res.cookie(VAL_ENABLED_COOKIE, "true", {
|
1379
1408
|
httpOnly: false,
|
1380
1409
|
sameSite: "lax"
|
1381
|
-
}).redirect(
|
1410
|
+
}).redirect(redirectUrlToUse);
|
1411
|
+
} else {
|
1412
|
+
res.sendStatus(400);
|
1413
|
+
}
|
1414
|
+
}
|
1415
|
+
async function disable(req, res, redirectUrl) {
|
1416
|
+
const {
|
1417
|
+
redirect_to
|
1418
|
+
} = req.query;
|
1419
|
+
if (typeof redirect_to === "string" || typeof redirect_to === "undefined") {
|
1420
|
+
let redirectUrlToUse = redirect_to || "/";
|
1421
|
+
if (redirectUrl) {
|
1422
|
+
redirectUrlToUse = redirectUrl + "?redirect_to=" + encodeURIComponent(redirectUrlToUse);
|
1423
|
+
}
|
1424
|
+
res.cookie(VAL_ENABLED_COOKIE, "false", {
|
1425
|
+
httpOnly: false,
|
1426
|
+
sameSite: "lax"
|
1427
|
+
}).redirect(redirectUrlToUse);
|
1382
1428
|
} else {
|
1383
1429
|
res.sendStatus(400);
|
1384
1430
|
}
|
@@ -1404,53 +1450,75 @@ class LocalValServer {
|
|
1404
1450
|
constructor(options) {
|
1405
1451
|
this.options = options;
|
1406
1452
|
}
|
1407
|
-
getAllModules(req, res) {
|
1408
|
-
// TODO: this barely works,
|
1409
|
-
const rootDir = process.cwd();
|
1410
|
-
const moduleIds = [];
|
1411
|
-
// iterate over all .val files in the root directory
|
1412
|
-
const walk = async dir => {
|
1413
|
-
const files = await promises.readdir(dir);
|
1414
|
-
for (const file of files) {
|
1415
|
-
if ((await promises.stat(path.join(dir, file))).isDirectory()) {
|
1416
|
-
if (file === "node_modules") continue;
|
1417
|
-
await walk(path.join(dir, file));
|
1418
|
-
} else {
|
1419
|
-
if (file.endsWith(".val.js") || file.endsWith(".val.ts")) {
|
1420
|
-
moduleIds.push(path.join(dir, file).replace(rootDir, "").replace(".val.js", "").replace(".val.ts", ""));
|
1421
|
-
}
|
1422
|
-
}
|
1423
|
-
}
|
1424
|
-
};
|
1425
|
-
return walk(rootDir).then(async () => {
|
1426
|
-
res.send(JSON.stringify(await Promise.all(moduleIds.map(async moduleId => {
|
1427
|
-
return await this.options.service.get(moduleId, "");
|
1428
|
-
}))));
|
1429
|
-
});
|
1430
|
-
}
|
1431
1453
|
async session(_req, res) {
|
1432
1454
|
res.json({
|
1433
1455
|
mode: "local"
|
1434
1456
|
});
|
1435
1457
|
}
|
1436
|
-
async
|
1437
|
-
return enable(req, res);
|
1438
|
-
}
|
1439
|
-
async getIds(req, res) {
|
1458
|
+
async getTree(req, res) {
|
1440
1459
|
try {
|
1441
|
-
|
1442
|
-
const
|
1443
|
-
const
|
1444
|
-
const
|
1445
|
-
|
1460
|
+
// TODO: use the params: patch, schema, source
|
1461
|
+
const treePath = req.params["0"].replace("~", "");
|
1462
|
+
const rootDir = process.cwd();
|
1463
|
+
const moduleIds = [];
|
1464
|
+
// iterate over all .val files in the root directory
|
1465
|
+
const walk = async dir => {
|
1466
|
+
const files = await promises.readdir(dir);
|
1467
|
+
for (const file of files) {
|
1468
|
+
if ((await promises.stat(path__default.join(dir, file))).isDirectory()) {
|
1469
|
+
if (file === "node_modules") continue;
|
1470
|
+
await walk(path__default.join(dir, file));
|
1471
|
+
} else {
|
1472
|
+
const isValFile = file.endsWith(".val.js") || file.endsWith(".val.ts");
|
1473
|
+
if (!isValFile) {
|
1474
|
+
continue;
|
1475
|
+
}
|
1476
|
+
if (treePath && !path__default.join(dir, file).replace(rootDir, "").startsWith(treePath)) {
|
1477
|
+
continue;
|
1478
|
+
}
|
1479
|
+
moduleIds.push(path__default.join(dir, file).replace(rootDir, "").replace(".val.js", "").replace(".val.ts", ""));
|
1480
|
+
}
|
1481
|
+
}
|
1482
|
+
};
|
1483
|
+
const serializedModuleContent = await walk(rootDir).then(async () => {
|
1484
|
+
return Promise.all(moduleIds.map(async moduleId => {
|
1485
|
+
return await this.options.service.get(moduleId, "");
|
1486
|
+
}));
|
1487
|
+
});
|
1488
|
+
|
1489
|
+
//
|
1490
|
+
const modules = Object.fromEntries(serializedModuleContent.map(serializedModuleContent => {
|
1491
|
+
const module = {
|
1492
|
+
schema: serializedModuleContent.schema,
|
1493
|
+
source: serializedModuleContent.source
|
1494
|
+
};
|
1495
|
+
return [serializedModuleContent.path, module];
|
1496
|
+
}));
|
1497
|
+
const apiTreeResponse = {
|
1498
|
+
modules,
|
1499
|
+
git: this.options.git
|
1500
|
+
};
|
1501
|
+
return walk(rootDir).then(async () => {
|
1502
|
+
res.send(JSON.stringify(apiTreeResponse));
|
1503
|
+
});
|
1446
1504
|
} catch (err) {
|
1447
1505
|
console.error(err);
|
1448
1506
|
res.sendStatus(500);
|
1449
1507
|
}
|
1450
1508
|
}
|
1451
|
-
async
|
1509
|
+
async enable(req, res) {
|
1510
|
+
return enable(req, res);
|
1511
|
+
}
|
1512
|
+
async disable(req, res) {
|
1513
|
+
return disable(req, res);
|
1514
|
+
}
|
1515
|
+
async postPatches(req, res) {
|
1516
|
+
var _getPathFromParams;
|
1517
|
+
const id = (_getPathFromParams = getPathFromParams(req.params)) === null || _getPathFromParams === void 0 ? void 0 : _getPathFromParams.replace("/~", "");
|
1518
|
+
|
1452
1519
|
// First validate that the body has the right structure
|
1453
1520
|
const patchJSON = PatchJSON.safeParse(req.body);
|
1521
|
+
console.log("patch id", id, patchJSON);
|
1454
1522
|
if (!patchJSON.success) {
|
1455
1523
|
res.status(401).json(patchJSON.error.issues);
|
1456
1524
|
return;
|
@@ -1461,16 +1529,19 @@ class LocalValServer {
|
|
1461
1529
|
res.status(401).json(patch.error);
|
1462
1530
|
return;
|
1463
1531
|
}
|
1464
|
-
const id = getPathFromParams(req.params);
|
1465
1532
|
try {
|
1466
|
-
|
1467
|
-
res.json(
|
1533
|
+
await this.options.service.patch(id, patch.value);
|
1534
|
+
res.json({});
|
1468
1535
|
} catch (err) {
|
1469
1536
|
if (err instanceof PatchError) {
|
1470
|
-
res.status(
|
1537
|
+
res.status(400).send({
|
1538
|
+
message: err.message
|
1539
|
+
});
|
1471
1540
|
} else {
|
1472
1541
|
console.error(err);
|
1473
|
-
res.status(500).send(
|
1542
|
+
res.status(500).send({
|
1543
|
+
message: err instanceof Error ? err.message : "Unknown error"
|
1544
|
+
});
|
1474
1545
|
}
|
1475
1546
|
}
|
1476
1547
|
}
|
@@ -1512,6 +1583,7 @@ async function initHandlerOptions(route, opts) {
|
|
1512
1583
|
if (!maybeApiKey || !maybeValSecret) {
|
1513
1584
|
throw new Error("VAL_API_KEY and VAL_SECRET env vars must both be set in proxy mode");
|
1514
1585
|
}
|
1586
|
+
const valContentUrl = opts.valContentUrl || process.env.VAL_CONTENT_URL || "https://content.val.build";
|
1515
1587
|
const maybeGitCommit = opts.gitCommit || process.env.VAL_GIT_COMMIT;
|
1516
1588
|
if (!maybeGitCommit) {
|
1517
1589
|
throw new Error("VAL_GIT_COMMIT env var must be set in proxy mode");
|
@@ -1530,18 +1602,82 @@ async function initHandlerOptions(route, opts) {
|
|
1530
1602
|
apiKey: maybeApiKey,
|
1531
1603
|
valSecret: maybeValSecret,
|
1532
1604
|
valBuildUrl,
|
1605
|
+
valContentUrl,
|
1533
1606
|
gitCommit: maybeGitCommit,
|
1534
1607
|
gitBranch: maybeGitBranch,
|
1535
|
-
valName: maybeValName
|
1608
|
+
valName: maybeValName,
|
1609
|
+
valEnableRedirectUrl: opts.valEnableRedirectUrl || process.env.VAL_ENABLE_REDIRECT_URL,
|
1610
|
+
valDisableRedirectUrl: opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL
|
1536
1611
|
};
|
1537
1612
|
} else {
|
1538
|
-
const
|
1613
|
+
const cwd = process.cwd();
|
1614
|
+
const service = await createService(cwd, opts);
|
1615
|
+
const git = await safeReadGit(cwd);
|
1539
1616
|
return {
|
1540
1617
|
mode: "local",
|
1541
|
-
service
|
1618
|
+
service,
|
1619
|
+
git: {
|
1620
|
+
commit: process.env.VAL_GIT_COMMIT || git.commit,
|
1621
|
+
branch: process.env.VAL_GIT_BRANCH || git.branch
|
1622
|
+
}
|
1542
1623
|
};
|
1543
1624
|
}
|
1544
1625
|
}
|
1626
|
+
async function safeReadGit(cwd) {
|
1627
|
+
async function findGitHead(currentDir, depth) {
|
1628
|
+
const gitHeadPath = path.join(currentDir, ".git", "HEAD");
|
1629
|
+
if (depth > 1000) {
|
1630
|
+
console.error(`Reached max depth while scanning for .git folder. Current working dir: ${cwd}.`);
|
1631
|
+
return {
|
1632
|
+
commit: undefined,
|
1633
|
+
branch: undefined
|
1634
|
+
};
|
1635
|
+
}
|
1636
|
+
try {
|
1637
|
+
const headContents = await promises.readFile(gitHeadPath, "utf-8");
|
1638
|
+
const match = headContents.match(/^ref: refs\/heads\/(.+)/);
|
1639
|
+
if (match) {
|
1640
|
+
const branchName = match[1];
|
1641
|
+
return {
|
1642
|
+
branch: branchName,
|
1643
|
+
commit: await readCommit(currentDir, branchName)
|
1644
|
+
};
|
1645
|
+
} else {
|
1646
|
+
return {
|
1647
|
+
commit: undefined,
|
1648
|
+
branch: undefined
|
1649
|
+
};
|
1650
|
+
}
|
1651
|
+
} catch (error) {
|
1652
|
+
const parentDir = path.dirname(currentDir);
|
1653
|
+
|
1654
|
+
// We've reached the root directory
|
1655
|
+
if (parentDir === currentDir) {
|
1656
|
+
return {
|
1657
|
+
commit: undefined,
|
1658
|
+
branch: undefined
|
1659
|
+
};
|
1660
|
+
}
|
1661
|
+
return findGitHead(parentDir, depth + 1);
|
1662
|
+
}
|
1663
|
+
}
|
1664
|
+
try {
|
1665
|
+
return findGitHead(cwd, 0);
|
1666
|
+
} catch (err) {
|
1667
|
+
console.error("Error while reading .git", err);
|
1668
|
+
return {
|
1669
|
+
commit: undefined,
|
1670
|
+
branch: undefined
|
1671
|
+
};
|
1672
|
+
}
|
1673
|
+
}
|
1674
|
+
async function readCommit(gitDir, branchName) {
|
1675
|
+
try {
|
1676
|
+
return (await promises.readFile(path.join(gitDir, ".git", "refs", "heads", branchName), "utf-8")).trim();
|
1677
|
+
} catch (err) {
|
1678
|
+
return undefined;
|
1679
|
+
}
|
1680
|
+
}
|
1545
1681
|
|
1546
1682
|
// TODO: rename to createValApiHandlers?
|
1547
1683
|
function createRequestListener(route, opts) {
|
@@ -1579,10 +1715,10 @@ class ValFSHost {
|
|
1579
1715
|
return this.currentDirectory;
|
1580
1716
|
}
|
1581
1717
|
getCanonicalFileName(fileName) {
|
1582
|
-
if (
|
1583
|
-
return
|
1718
|
+
if (path__default.isAbsolute(fileName)) {
|
1719
|
+
return path__default.normalize(fileName);
|
1584
1720
|
}
|
1585
|
-
return
|
1721
|
+
return path__default.resolve(this.getCurrentDirectory(), fileName);
|
1586
1722
|
}
|
1587
1723
|
fileExists(fileName) {
|
1588
1724
|
return this.valFS.fileExists(fileName);
|
@@ -1603,7 +1739,7 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
1603
1739
|
// TODO:
|
1604
1740
|
throw Error("Cannot fix image without a file reference");
|
1605
1741
|
}
|
1606
|
-
const localFile =
|
1742
|
+
const localFile = path__default.join(config.projectRoot, maybeRef);
|
1607
1743
|
const buffer = fs.readFileSync(localFile);
|
1608
1744
|
const sha256 = await getSHA256Hash(buffer);
|
1609
1745
|
const imageSize = sizeOf(buffer);
|
@@ -1704,4 +1840,4 @@ const getSHA256Hash = async bits => {
|
|
1704
1840
|
return hash;
|
1705
1841
|
};
|
1706
1842
|
|
1707
|
-
export { LocalValServer, PatchJSON, Service, ValFSHost, ValModuleLoader, ValSourceFileHandler, createFixPatch, createRequestHandler, createRequestListener, createService, decodeJwt, encodeJwt, formatSyntaxErrorTree, getCompilerOptions, getExpire, patchSourceFile };
|
1843
|
+
export { LocalValServer, PatchJSON, Service, ValFSHost, ValModuleLoader, ValSourceFileHandler, createFixPatch, createRequestHandler, createRequestListener, createService, decodeJwt, encodeJwt, formatSyntaxErrorTree, getCompilerOptions, getExpire, patchSourceFile, safeReadGit };
|
package/package.json
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
"./package.json": "./package.json"
|
13
13
|
},
|
14
14
|
"types": "dist/valbuild-server.cjs.d.ts",
|
15
|
-
"version": "0.
|
15
|
+
"version": "0.17.0",
|
16
16
|
"scripts": {
|
17
17
|
"typecheck": "tsc --noEmit",
|
18
18
|
"test": "jest",
|
@@ -25,8 +25,8 @@
|
|
25
25
|
"concurrently": "^7.6.0"
|
26
26
|
},
|
27
27
|
"dependencies": {
|
28
|
-
"@valbuild/core": "~0.
|
29
|
-
"@valbuild/ui": "~0.
|
28
|
+
"@valbuild/core": "~0.17.0",
|
29
|
+
"@valbuild/ui": "~0.17.0",
|
30
30
|
"express": "^4.18.2",
|
31
31
|
"image-size": "^1.0.2",
|
32
32
|
"quickjs-emscripten": "^0.21.1",
|