@valbuild/server 0.16.3 → 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 +8 -4
- package/dist/declarations/src/ValServer.d.ts +4 -4
- package/dist/declarations/src/hosting.d.ts +34 -0
- package/dist/declarations/src/index.d.ts +1 -1
- package/dist/declarations/src/patchValFile.d.ts +1 -1
- package/dist/valbuild-server.cjs.dev.js +324 -116
- package/dist/valbuild-server.cjs.prod.js +324 -116
- package/dist/valbuild-server.esm.js +308 -118
- package/package.json +3 -3
- package/src/LocalValServer.ts +89 -19
- package/src/ProxyValServer.ts +86 -28
- package/src/Service.ts +4 -3
- package/src/ValQuickJSRuntime.ts +18 -0
- package/src/ValServer.ts +6 -6
- package/src/createRequestHandler.ts +7 -5
- package/src/hosting.ts +122 -1
- package/src/index.ts +1 -1
- package/src/patch/ts/ops.test.ts +0 -1
- package/src/patchValFile.ts +8 -1
- package/src/readValFile.ts +2 -2
|
@@ -17,8 +17,26 @@ var sizeOf = require('image-size');
|
|
|
17
17
|
|
|
18
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
19
19
|
|
|
20
|
+
function _interopNamespace(e) {
|
|
21
|
+
if (e && e.__esModule) return e;
|
|
22
|
+
var n = Object.create(null);
|
|
23
|
+
if (e) {
|
|
24
|
+
Object.keys(e).forEach(function (k) {
|
|
25
|
+
if (k !== 'default') {
|
|
26
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
27
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () { return e[k]; }
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
n["default"] = e;
|
|
35
|
+
return Object.freeze(n);
|
|
36
|
+
}
|
|
37
|
+
|
|
20
38
|
var ts__default = /*#__PURE__*/_interopDefault(ts);
|
|
21
|
-
var
|
|
39
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
22
40
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
23
41
|
var express__default = /*#__PURE__*/_interopDefault(express);
|
|
24
42
|
var z__default = /*#__PURE__*/_interopDefault(z);
|
|
@@ -572,16 +590,16 @@ import { Internal } from "@valbuild/core";
|
|
|
572
590
|
globalThis.valModule = {
|
|
573
591
|
id: valModule?.default && Internal.getValPath(valModule?.default),
|
|
574
592
|
schema: valModule?.default && Internal.getSchema(valModule?.default)?.serialize(),
|
|
575
|
-
source: valModule?.default && Internal.
|
|
593
|
+
source: valModule?.default && Internal.getSource(valModule?.default),
|
|
576
594
|
validation: valModule?.default && Internal.getSchema(valModule?.default)?.validate(
|
|
577
595
|
valModule?.default && Internal.getValPath(valModule?.default) || "/",
|
|
578
|
-
valModule?.default && Internal.
|
|
596
|
+
valModule?.default && Internal.getSource(valModule?.default)
|
|
579
597
|
)
|
|
580
598
|
};
|
|
581
599
|
`;
|
|
582
600
|
const result = context.evalCode(code,
|
|
583
601
|
// Synthetic module name
|
|
584
|
-
|
|
602
|
+
path__namespace["default"].join(path__namespace["default"].dirname(valConfigPath), "<val>"));
|
|
585
603
|
const fatalErrors = [];
|
|
586
604
|
if (result.error) {
|
|
587
605
|
const error = result.error.consume(context.dump);
|
|
@@ -686,12 +704,15 @@ function convertDataUrlToBase64(dataUrl) {
|
|
|
686
704
|
return Buffer.from(base64, "base64");
|
|
687
705
|
}
|
|
688
706
|
const patchSourceFile = (sourceFile, patch$1) => {
|
|
707
|
+
if (typeof sourceFile === "string") {
|
|
708
|
+
return patch.applyPatch(ts__default["default"].createSourceFile("<val>", sourceFile, ts__default["default"].ScriptTarget.ES2015), ops, patch$1);
|
|
709
|
+
}
|
|
689
710
|
return patch.applyPatch(sourceFile, ops, patch$1);
|
|
690
711
|
};
|
|
691
712
|
|
|
692
713
|
const getCompilerOptions = (rootDir, parseConfigHost) => {
|
|
693
|
-
const tsConfigPath =
|
|
694
|
-
const jsConfigPath =
|
|
714
|
+
const tsConfigPath = path__namespace["default"].resolve(rootDir, "tsconfig.json");
|
|
715
|
+
const jsConfigPath = path__namespace["default"].resolve(rootDir, "jsconfig.json");
|
|
695
716
|
let configFilePath;
|
|
696
717
|
if (parseConfigHost.fileExists(jsConfigPath)) {
|
|
697
718
|
configFilePath = jsConfigPath;
|
|
@@ -741,7 +762,7 @@ class ValSourceFileHandler {
|
|
|
741
762
|
this.host.writeFile(filePath, content, encoding);
|
|
742
763
|
}
|
|
743
764
|
resolveSourceModulePath(containingFilePath, requestedModuleName) {
|
|
744
|
-
const resolutionRes = ts__default["default"].resolveModuleName(requestedModuleName,
|
|
765
|
+
const resolutionRes = ts__default["default"].resolveModuleName(requestedModuleName, path__namespace["default"].isAbsolute(containingFilePath) ? containingFilePath : path__namespace["default"].resolve(this.projectRoot, containingFilePath), this.compilerOptions, this.host, undefined, undefined, ts__default["default"].ModuleKind.ESNext);
|
|
745
766
|
const resolvedModule = resolutionRes.resolvedModule;
|
|
746
767
|
if (!resolvedModule) {
|
|
747
768
|
throw Error(`Could not resolve module "${requestedModuleName}", base: "${containingFilePath}": No resolved modules returned: ${JSON.stringify(resolutionRes)}`);
|
|
@@ -861,6 +882,16 @@ async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
|
|
861
882
|
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 */ };"
|
|
862
883
|
};
|
|
863
884
|
}
|
|
885
|
+
if (modulePath.startsWith("next")) {
|
|
886
|
+
return {
|
|
887
|
+
value: "export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'next' in this file`) } } } )"
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
if (modulePath.startsWith("react")) {
|
|
891
|
+
return {
|
|
892
|
+
value: "export default new Proxy({}, { get() { return () => { throw new Error(`Cannot import 'react' in this file`) } } } )"
|
|
893
|
+
};
|
|
894
|
+
}
|
|
864
895
|
return {
|
|
865
896
|
value: moduleLoader.getModule(modulePath)
|
|
866
897
|
};
|
|
@@ -881,6 +912,16 @@ async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
|
|
881
912
|
value: requestedName
|
|
882
913
|
};
|
|
883
914
|
}
|
|
915
|
+
if (requestedName.startsWith("next")) {
|
|
916
|
+
return {
|
|
917
|
+
value: requestedName
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
if (requestedName.startsWith("react")) {
|
|
921
|
+
return {
|
|
922
|
+
value: requestedName
|
|
923
|
+
};
|
|
924
|
+
}
|
|
884
925
|
const modulePath = moduleLoader.resolveModulePath(baseModuleName, requestedName);
|
|
885
926
|
return {
|
|
886
927
|
value: modulePath
|
|
@@ -917,7 +958,7 @@ class Service {
|
|
|
917
958
|
const valModule = await readValFile(moduleId, this.valConfigPath, this.runtime);
|
|
918
959
|
if (valModule.source && valModule.schema) {
|
|
919
960
|
const resolved = core.Internal.resolvePath(modulePath, valModule.source, valModule.schema);
|
|
920
|
-
const sourcePath = [moduleId, resolved.path].join(".");
|
|
961
|
+
const sourcePath = resolved.path ? [moduleId, resolved.path].join(".") : moduleId;
|
|
921
962
|
return {
|
|
922
963
|
path: sourcePath,
|
|
923
964
|
schema: resolved.schema instanceof core.Schema ? resolved.schema.serialize() : resolved.schema,
|
|
@@ -948,15 +989,21 @@ function createRequestHandler(valServer) {
|
|
|
948
989
|
router.get("/authorize", valServer.authorize.bind(valServer));
|
|
949
990
|
router.get("/callback", valServer.callback.bind(valServer));
|
|
950
991
|
router.get("/logout", valServer.logout.bind(valServer));
|
|
951
|
-
router.
|
|
952
|
-
|
|
953
|
-
type: "application/json-patch+json",
|
|
992
|
+
router.post("/patches/*", express__default["default"].json({
|
|
993
|
+
type: "application/json",
|
|
954
994
|
limit: "10mb"
|
|
955
|
-
}), valServer.
|
|
995
|
+
}), valServer.postPatches.bind(valServer));
|
|
956
996
|
router.post("/commit", valServer.commit.bind(valServer));
|
|
997
|
+
router.get("/enable", valServer.enable.bind(valServer));
|
|
998
|
+
router.get("/disable", valServer.disable.bind(valServer));
|
|
999
|
+
router.get("/tree/*", valServer.getTree.bind(valServer));
|
|
957
1000
|
return router;
|
|
958
1001
|
}
|
|
959
1002
|
|
|
1003
|
+
function getPathFromParams(params) {
|
|
1004
|
+
return `/${params[0]}`;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
960
1007
|
const JSONValueT = z__default["default"].lazy(() => z__default["default"].union([z__default["default"].string(), z__default["default"].number(), z__default["default"].boolean(), z__default["default"].null(), z__default["default"].array(JSONValueT), z__default["default"].record(JSONValueT)]));
|
|
961
1008
|
|
|
962
1009
|
/**
|
|
@@ -994,75 +1041,6 @@ const OperationJSONT = z__default["default"].discriminatedUnion("op", [z__defaul
|
|
|
994
1041
|
}).strict()]);
|
|
995
1042
|
const PatchJSON = z__default["default"].array(OperationJSONT);
|
|
996
1043
|
|
|
997
|
-
function getPathFromParams(params) {
|
|
998
|
-
return `/${params[0]}`;
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
class LocalValServer {
|
|
1002
|
-
constructor(options) {
|
|
1003
|
-
this.options = options;
|
|
1004
|
-
}
|
|
1005
|
-
async session(_req, res) {
|
|
1006
|
-
res.json({
|
|
1007
|
-
mode: "local"
|
|
1008
|
-
});
|
|
1009
|
-
}
|
|
1010
|
-
async getIds(req, res) {
|
|
1011
|
-
try {
|
|
1012
|
-
console.log(req.params);
|
|
1013
|
-
const path = getPathFromParams(req.params);
|
|
1014
|
-
const [moduleId, modulePath] = core.Internal.splitModuleIdAndModulePath(path);
|
|
1015
|
-
const valModule = await this.options.service.get(moduleId, modulePath);
|
|
1016
|
-
res.json(valModule);
|
|
1017
|
-
} catch (err) {
|
|
1018
|
-
console.error(err);
|
|
1019
|
-
res.sendStatus(500);
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
async patchIds(req, res) {
|
|
1023
|
-
// First validate that the body has the right structure
|
|
1024
|
-
const patchJSON = PatchJSON.safeParse(req.body);
|
|
1025
|
-
if (!patchJSON.success) {
|
|
1026
|
-
res.status(401).json(patchJSON.error.issues);
|
|
1027
|
-
return;
|
|
1028
|
-
}
|
|
1029
|
-
// Then parse/validate
|
|
1030
|
-
const patch$1 = patch.parsePatch(patchJSON.data);
|
|
1031
|
-
if (fp.result.isErr(patch$1)) {
|
|
1032
|
-
res.status(401).json(patch$1.error);
|
|
1033
|
-
return;
|
|
1034
|
-
}
|
|
1035
|
-
const id = getPathFromParams(req.params);
|
|
1036
|
-
try {
|
|
1037
|
-
const valModule = await this.options.service.patch(id, patch$1.value);
|
|
1038
|
-
res.json(valModule);
|
|
1039
|
-
} catch (err) {
|
|
1040
|
-
if (err instanceof patch.PatchError) {
|
|
1041
|
-
res.status(401).send(err.message);
|
|
1042
|
-
} else {
|
|
1043
|
-
console.error(err);
|
|
1044
|
-
res.status(500).send(err instanceof Error ? err.message : "Unknown error");
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
async badRequest(req, res) {
|
|
1049
|
-
console.debug("Local server does handle this request", req.url);
|
|
1050
|
-
res.sendStatus(400);
|
|
1051
|
-
}
|
|
1052
|
-
commit(req, res) {
|
|
1053
|
-
return this.badRequest(req, res);
|
|
1054
|
-
}
|
|
1055
|
-
authorize(req, res) {
|
|
1056
|
-
return this.badRequest(req, res);
|
|
1057
|
-
}
|
|
1058
|
-
callback(req, res) {
|
|
1059
|
-
return this.badRequest(req, res);
|
|
1060
|
-
}
|
|
1061
|
-
logout(req, res) {
|
|
1062
|
-
return this.badRequest(req, res);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
1044
|
function decodeJwt(token, secretKey) {
|
|
1067
1045
|
const [headerBase64, payloadBase64, signatureBase64, ...rest] = token.split(".");
|
|
1068
1046
|
if (!headerBase64 || !payloadBase64 || !signatureBase64 || rest.length > 0) {
|
|
@@ -1122,8 +1100,9 @@ function encodeJwt(payload, sessionKey) {
|
|
|
1122
1100
|
return `${jwtHeaderBase64}.${payloadBase64}.${crypto__default["default"].createHmac("sha256", sessionKey).update(`${jwtHeaderBase64}.${payloadBase64}`).digest("base64")}`;
|
|
1123
1101
|
}
|
|
1124
1102
|
|
|
1125
|
-
const VAL_SESSION_COOKIE =
|
|
1126
|
-
const VAL_STATE_COOKIE =
|
|
1103
|
+
const VAL_SESSION_COOKIE = core.Internal.VAL_SESSION_COOKIE;
|
|
1104
|
+
const VAL_STATE_COOKIE = core.Internal.VAL_STATE_COOKIE;
|
|
1105
|
+
const VAL_ENABLED_COOKIE = core.Internal.VAL_ENABLE_COOKIE_NAME;
|
|
1127
1106
|
class ProxyValServer {
|
|
1128
1107
|
constructor(options) {
|
|
1129
1108
|
this.options = options;
|
|
@@ -1148,6 +1127,12 @@ class ProxyValServer {
|
|
|
1148
1127
|
expires: new Date(Date.now() + 1000 * 60 * 60) // 1 hour
|
|
1149
1128
|
}).redirect(appAuthorizeUrl);
|
|
1150
1129
|
}
|
|
1130
|
+
async enable(req, res) {
|
|
1131
|
+
return enable(req, res, this.options.valEnableRedirectUrl);
|
|
1132
|
+
}
|
|
1133
|
+
async disable(req, res) {
|
|
1134
|
+
return disable(req, res, this.options.valEnableRedirectUrl);
|
|
1135
|
+
}
|
|
1151
1136
|
async callback(req, res) {
|
|
1152
1137
|
const {
|
|
1153
1138
|
success: callbackReqSuccess,
|
|
@@ -1193,7 +1178,6 @@ class ProxyValServer {
|
|
|
1193
1178
|
}
|
|
1194
1179
|
}
|
|
1195
1180
|
async session(req, res) {
|
|
1196
|
-
console.log("hit session");
|
|
1197
1181
|
return this.withAuth(req, res, async data => {
|
|
1198
1182
|
const url = new URL(`/api/val/${this.options.valName}/auth/session`, this.options.valBuildUrl);
|
|
1199
1183
|
const fetchRes = await fetch(url, {
|
|
@@ -1209,30 +1193,38 @@ class ProxyValServer {
|
|
|
1209
1193
|
}
|
|
1210
1194
|
});
|
|
1211
1195
|
}
|
|
1212
|
-
async
|
|
1213
|
-
return this.withAuth(req, res, async
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
} else {
|
|
1224
|
-
res.sendStatus(fetchRes.status);
|
|
1225
|
-
}
|
|
1226
|
-
}).catch(e => {
|
|
1227
|
-
res.status(500).send({
|
|
1228
|
-
error: {
|
|
1229
|
-
message: e === null || e === void 0 ? void 0 : e.message,
|
|
1230
|
-
status: 500
|
|
1231
|
-
}
|
|
1196
|
+
async getTree(req, res) {
|
|
1197
|
+
return this.withAuth(req, res, async data => {
|
|
1198
|
+
const {
|
|
1199
|
+
patch,
|
|
1200
|
+
schema,
|
|
1201
|
+
source
|
|
1202
|
+
} = req.query;
|
|
1203
|
+
const params = new URLSearchParams({
|
|
1204
|
+
patch: (patch === "true").toString(),
|
|
1205
|
+
schema: (schema === "true").toString(),
|
|
1206
|
+
source: (source === "true").toString()
|
|
1232
1207
|
});
|
|
1208
|
+
const url = new URL(`/v1/tree/${this.options.valName}/heads/${this.options.gitBranch}/${req.params["0"]}/?${params}`, this.options.valContentUrl);
|
|
1209
|
+
const json = await fetch(url, {
|
|
1210
|
+
headers: this.getAuthHeaders(data.token, "application/json")
|
|
1211
|
+
}).then(res => res.json());
|
|
1212
|
+
res.send(json);
|
|
1233
1213
|
});
|
|
1234
1214
|
}
|
|
1235
|
-
async
|
|
1215
|
+
async postPatches(req, res) {
|
|
1216
|
+
const {
|
|
1217
|
+
commit
|
|
1218
|
+
} = req.query;
|
|
1219
|
+
if (typeof commit !== "string" || typeof commit === "undefined") {
|
|
1220
|
+
res.status(401).json({
|
|
1221
|
+
error: "Missing or invalid commit query param"
|
|
1222
|
+
});
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
const params = new URLSearchParams({
|
|
1226
|
+
commit
|
|
1227
|
+
});
|
|
1236
1228
|
this.withAuth(req, res, async ({
|
|
1237
1229
|
token
|
|
1238
1230
|
}) => {
|
|
@@ -1248,12 +1240,11 @@ class ProxyValServer {
|
|
|
1248
1240
|
res.status(401).json(patch$1.error);
|
|
1249
1241
|
return;
|
|
1250
1242
|
}
|
|
1251
|
-
const
|
|
1252
|
-
const url = new URL(`/api/val/modules/${encodeURIComponent(this.options.gitCommit)}${id}`, this.options.valBuildUrl);
|
|
1243
|
+
const url = new URL(`/v1/tree/${this.options.valName}/heads/${this.options.gitBranch}/${req.params["0"]}/?${params}`, this.options.valContentUrl);
|
|
1253
1244
|
// Proxy patch to val.build
|
|
1254
1245
|
const fetchRes = await fetch(url, {
|
|
1255
|
-
method: "
|
|
1256
|
-
headers: this.getAuthHeaders(token, "application/json
|
|
1246
|
+
method: "POST",
|
|
1247
|
+
headers: this.getAuthHeaders(token, "application/json"),
|
|
1257
1248
|
body: JSON.stringify(patch$1)
|
|
1258
1249
|
});
|
|
1259
1250
|
if (fetchRes.ok) {
|
|
@@ -1435,6 +1426,40 @@ function getStateFromCookie(stateCookie) {
|
|
|
1435
1426
|
};
|
|
1436
1427
|
}
|
|
1437
1428
|
}
|
|
1429
|
+
async function enable(req, res, redirectUrl) {
|
|
1430
|
+
const {
|
|
1431
|
+
redirect_to
|
|
1432
|
+
} = req.query;
|
|
1433
|
+
if (typeof redirect_to === "string" || typeof redirect_to === "undefined") {
|
|
1434
|
+
let redirectUrlToUse = redirect_to || "/";
|
|
1435
|
+
if (redirectUrl) {
|
|
1436
|
+
redirectUrlToUse = redirectUrl + "?redirect_to=" + encodeURIComponent(redirectUrlToUse);
|
|
1437
|
+
}
|
|
1438
|
+
res.cookie(VAL_ENABLED_COOKIE, "true", {
|
|
1439
|
+
httpOnly: false,
|
|
1440
|
+
sameSite: "lax"
|
|
1441
|
+
}).redirect(redirectUrlToUse);
|
|
1442
|
+
} else {
|
|
1443
|
+
res.sendStatus(400);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
async function disable(req, res, redirectUrl) {
|
|
1447
|
+
const {
|
|
1448
|
+
redirect_to
|
|
1449
|
+
} = req.query;
|
|
1450
|
+
if (typeof redirect_to === "string" || typeof redirect_to === "undefined") {
|
|
1451
|
+
let redirectUrlToUse = redirect_to || "/";
|
|
1452
|
+
if (redirectUrl) {
|
|
1453
|
+
redirectUrlToUse = redirectUrl + "?redirect_to=" + encodeURIComponent(redirectUrlToUse);
|
|
1454
|
+
}
|
|
1455
|
+
res.cookie(VAL_ENABLED_COOKIE, "false", {
|
|
1456
|
+
httpOnly: false,
|
|
1457
|
+
sameSite: "lax"
|
|
1458
|
+
}).redirect(redirectUrlToUse);
|
|
1459
|
+
} else {
|
|
1460
|
+
res.sendStatus(400);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1438
1463
|
function createStateCookie(state) {
|
|
1439
1464
|
return Buffer.from(JSON.stringify(state), "utf8").toString("base64");
|
|
1440
1465
|
}
|
|
@@ -1452,6 +1477,123 @@ const IntegratedServerJwtPayload = z.z.object({
|
|
|
1452
1477
|
project: z.z.string()
|
|
1453
1478
|
});
|
|
1454
1479
|
|
|
1480
|
+
class LocalValServer {
|
|
1481
|
+
constructor(options) {
|
|
1482
|
+
this.options = options;
|
|
1483
|
+
}
|
|
1484
|
+
async session(_req, res) {
|
|
1485
|
+
res.json({
|
|
1486
|
+
mode: "local"
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
async getTree(req, res) {
|
|
1490
|
+
try {
|
|
1491
|
+
// TODO: use the params: patch, schema, source
|
|
1492
|
+
const treePath = req.params["0"].replace("~", "");
|
|
1493
|
+
const rootDir = process.cwd();
|
|
1494
|
+
const moduleIds = [];
|
|
1495
|
+
// iterate over all .val files in the root directory
|
|
1496
|
+
const walk = async dir => {
|
|
1497
|
+
const files = await fs.promises.readdir(dir);
|
|
1498
|
+
for (const file of files) {
|
|
1499
|
+
if ((await fs.promises.stat(path__namespace["default"].join(dir, file))).isDirectory()) {
|
|
1500
|
+
if (file === "node_modules") continue;
|
|
1501
|
+
await walk(path__namespace["default"].join(dir, file));
|
|
1502
|
+
} else {
|
|
1503
|
+
const isValFile = file.endsWith(".val.js") || file.endsWith(".val.ts");
|
|
1504
|
+
if (!isValFile) {
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1507
|
+
if (treePath && !path__namespace["default"].join(dir, file).replace(rootDir, "").startsWith(treePath)) {
|
|
1508
|
+
continue;
|
|
1509
|
+
}
|
|
1510
|
+
moduleIds.push(path__namespace["default"].join(dir, file).replace(rootDir, "").replace(".val.js", "").replace(".val.ts", ""));
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
};
|
|
1514
|
+
const serializedModuleContent = await walk(rootDir).then(async () => {
|
|
1515
|
+
return Promise.all(moduleIds.map(async moduleId => {
|
|
1516
|
+
return await this.options.service.get(moduleId, "");
|
|
1517
|
+
}));
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
//
|
|
1521
|
+
const modules = Object.fromEntries(serializedModuleContent.map(serializedModuleContent => {
|
|
1522
|
+
const module = {
|
|
1523
|
+
schema: serializedModuleContent.schema,
|
|
1524
|
+
source: serializedModuleContent.source
|
|
1525
|
+
};
|
|
1526
|
+
return [serializedModuleContent.path, module];
|
|
1527
|
+
}));
|
|
1528
|
+
const apiTreeResponse = {
|
|
1529
|
+
modules,
|
|
1530
|
+
git: this.options.git
|
|
1531
|
+
};
|
|
1532
|
+
return walk(rootDir).then(async () => {
|
|
1533
|
+
res.send(JSON.stringify(apiTreeResponse));
|
|
1534
|
+
});
|
|
1535
|
+
} catch (err) {
|
|
1536
|
+
console.error(err);
|
|
1537
|
+
res.sendStatus(500);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
async enable(req, res) {
|
|
1541
|
+
return enable(req, res);
|
|
1542
|
+
}
|
|
1543
|
+
async disable(req, res) {
|
|
1544
|
+
return disable(req, res);
|
|
1545
|
+
}
|
|
1546
|
+
async postPatches(req, res) {
|
|
1547
|
+
var _getPathFromParams;
|
|
1548
|
+
const id = (_getPathFromParams = getPathFromParams(req.params)) === null || _getPathFromParams === void 0 ? void 0 : _getPathFromParams.replace("/~", "");
|
|
1549
|
+
|
|
1550
|
+
// First validate that the body has the right structure
|
|
1551
|
+
const patchJSON = PatchJSON.safeParse(req.body);
|
|
1552
|
+
console.log("patch id", id, patchJSON);
|
|
1553
|
+
if (!patchJSON.success) {
|
|
1554
|
+
res.status(401).json(patchJSON.error.issues);
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
// Then parse/validate
|
|
1558
|
+
const patch$1 = patch.parsePatch(patchJSON.data);
|
|
1559
|
+
if (fp.result.isErr(patch$1)) {
|
|
1560
|
+
res.status(401).json(patch$1.error);
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
try {
|
|
1564
|
+
await this.options.service.patch(id, patch$1.value);
|
|
1565
|
+
res.json({});
|
|
1566
|
+
} catch (err) {
|
|
1567
|
+
if (err instanceof patch.PatchError) {
|
|
1568
|
+
res.status(400).send({
|
|
1569
|
+
message: err.message
|
|
1570
|
+
});
|
|
1571
|
+
} else {
|
|
1572
|
+
console.error(err);
|
|
1573
|
+
res.status(500).send({
|
|
1574
|
+
message: err instanceof Error ? err.message : "Unknown error"
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
async badRequest(req, res) {
|
|
1580
|
+
console.debug("Local server does handle this request", req.url);
|
|
1581
|
+
res.sendStatus(400);
|
|
1582
|
+
}
|
|
1583
|
+
commit(req, res) {
|
|
1584
|
+
return this.badRequest(req, res);
|
|
1585
|
+
}
|
|
1586
|
+
authorize(req, res) {
|
|
1587
|
+
return this.badRequest(req, res);
|
|
1588
|
+
}
|
|
1589
|
+
callback(req, res) {
|
|
1590
|
+
return this.badRequest(req, res);
|
|
1591
|
+
}
|
|
1592
|
+
logout(req, res) {
|
|
1593
|
+
return this.badRequest(req, res);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1455
1597
|
async function _createRequestListener(route, opts) {
|
|
1456
1598
|
const serverOpts = await initHandlerOptions(route, opts);
|
|
1457
1599
|
let valServer;
|
|
@@ -1472,6 +1614,7 @@ async function initHandlerOptions(route, opts) {
|
|
|
1472
1614
|
if (!maybeApiKey || !maybeValSecret) {
|
|
1473
1615
|
throw new Error("VAL_API_KEY and VAL_SECRET env vars must both be set in proxy mode");
|
|
1474
1616
|
}
|
|
1617
|
+
const valContentUrl = opts.valContentUrl || process.env.VAL_CONTENT_URL || "https://content.val.build";
|
|
1475
1618
|
const maybeGitCommit = opts.gitCommit || process.env.VAL_GIT_COMMIT;
|
|
1476
1619
|
if (!maybeGitCommit) {
|
|
1477
1620
|
throw new Error("VAL_GIT_COMMIT env var must be set in proxy mode");
|
|
@@ -1490,18 +1633,82 @@ async function initHandlerOptions(route, opts) {
|
|
|
1490
1633
|
apiKey: maybeApiKey,
|
|
1491
1634
|
valSecret: maybeValSecret,
|
|
1492
1635
|
valBuildUrl,
|
|
1636
|
+
valContentUrl,
|
|
1493
1637
|
gitCommit: maybeGitCommit,
|
|
1494
1638
|
gitBranch: maybeGitBranch,
|
|
1495
|
-
valName: maybeValName
|
|
1639
|
+
valName: maybeValName,
|
|
1640
|
+
valEnableRedirectUrl: opts.valEnableRedirectUrl || process.env.VAL_ENABLE_REDIRECT_URL,
|
|
1641
|
+
valDisableRedirectUrl: opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL
|
|
1496
1642
|
};
|
|
1497
1643
|
} else {
|
|
1498
|
-
const
|
|
1644
|
+
const cwd = process.cwd();
|
|
1645
|
+
const service = await createService(cwd, opts);
|
|
1646
|
+
const git = await safeReadGit(cwd);
|
|
1499
1647
|
return {
|
|
1500
1648
|
mode: "local",
|
|
1501
|
-
service
|
|
1649
|
+
service,
|
|
1650
|
+
git: {
|
|
1651
|
+
commit: process.env.VAL_GIT_COMMIT || git.commit,
|
|
1652
|
+
branch: process.env.VAL_GIT_BRANCH || git.branch
|
|
1653
|
+
}
|
|
1502
1654
|
};
|
|
1503
1655
|
}
|
|
1504
1656
|
}
|
|
1657
|
+
async function safeReadGit(cwd) {
|
|
1658
|
+
async function findGitHead(currentDir, depth) {
|
|
1659
|
+
const gitHeadPath = path__namespace.join(currentDir, ".git", "HEAD");
|
|
1660
|
+
if (depth > 1000) {
|
|
1661
|
+
console.error(`Reached max depth while scanning for .git folder. Current working dir: ${cwd}.`);
|
|
1662
|
+
return {
|
|
1663
|
+
commit: undefined,
|
|
1664
|
+
branch: undefined
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
try {
|
|
1668
|
+
const headContents = await fs.promises.readFile(gitHeadPath, "utf-8");
|
|
1669
|
+
const match = headContents.match(/^ref: refs\/heads\/(.+)/);
|
|
1670
|
+
if (match) {
|
|
1671
|
+
const branchName = match[1];
|
|
1672
|
+
return {
|
|
1673
|
+
branch: branchName,
|
|
1674
|
+
commit: await readCommit(currentDir, branchName)
|
|
1675
|
+
};
|
|
1676
|
+
} else {
|
|
1677
|
+
return {
|
|
1678
|
+
commit: undefined,
|
|
1679
|
+
branch: undefined
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
} catch (error) {
|
|
1683
|
+
const parentDir = path__namespace.dirname(currentDir);
|
|
1684
|
+
|
|
1685
|
+
// We've reached the root directory
|
|
1686
|
+
if (parentDir === currentDir) {
|
|
1687
|
+
return {
|
|
1688
|
+
commit: undefined,
|
|
1689
|
+
branch: undefined
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
return findGitHead(parentDir, depth + 1);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
try {
|
|
1696
|
+
return findGitHead(cwd, 0);
|
|
1697
|
+
} catch (err) {
|
|
1698
|
+
console.error("Error while reading .git", err);
|
|
1699
|
+
return {
|
|
1700
|
+
commit: undefined,
|
|
1701
|
+
branch: undefined
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
async function readCommit(gitDir, branchName) {
|
|
1706
|
+
try {
|
|
1707
|
+
return (await fs.promises.readFile(path__namespace.join(gitDir, ".git", "refs", "heads", branchName), "utf-8")).trim();
|
|
1708
|
+
} catch (err) {
|
|
1709
|
+
return undefined;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1505
1712
|
|
|
1506
1713
|
// TODO: rename to createValApiHandlers?
|
|
1507
1714
|
function createRequestListener(route, opts) {
|
|
@@ -1539,10 +1746,10 @@ class ValFSHost {
|
|
|
1539
1746
|
return this.currentDirectory;
|
|
1540
1747
|
}
|
|
1541
1748
|
getCanonicalFileName(fileName) {
|
|
1542
|
-
if (
|
|
1543
|
-
return
|
|
1749
|
+
if (path__namespace["default"].isAbsolute(fileName)) {
|
|
1750
|
+
return path__namespace["default"].normalize(fileName);
|
|
1544
1751
|
}
|
|
1545
|
-
return
|
|
1752
|
+
return path__namespace["default"].resolve(this.getCurrentDirectory(), fileName);
|
|
1546
1753
|
}
|
|
1547
1754
|
fileExists(fileName) {
|
|
1548
1755
|
return this.valFS.fileExists(fileName);
|
|
@@ -1563,7 +1770,7 @@ async function createFixPatch(config, apply, sourcePath, validationError) {
|
|
|
1563
1770
|
// TODO:
|
|
1564
1771
|
throw Error("Cannot fix image without a file reference");
|
|
1565
1772
|
}
|
|
1566
|
-
const localFile =
|
|
1773
|
+
const localFile = path__namespace["default"].join(config.projectRoot, maybeRef);
|
|
1567
1774
|
const buffer = fs__default["default"].readFileSync(localFile);
|
|
1568
1775
|
const sha256 = await getSHA256Hash(buffer);
|
|
1569
1776
|
const imageSize = sizeOf__default["default"](buffer);
|
|
@@ -1680,3 +1887,4 @@ exports.formatSyntaxErrorTree = formatSyntaxErrorTree;
|
|
|
1680
1887
|
exports.getCompilerOptions = getCompilerOptions;
|
|
1681
1888
|
exports.getExpire = getExpire;
|
|
1682
1889
|
exports.patchSourceFile = patchSourceFile;
|
|
1890
|
+
exports.safeReadGit = safeReadGit;
|