@valbuild/server 0.40.0 → 0.42.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/README.md
ADDED
@@ -10,7 +10,8 @@ export declare class ValModuleLoader {
|
|
10
10
|
private readonly disableCache;
|
11
11
|
private cache;
|
12
12
|
private cacheSize;
|
13
|
-
constructor(projectRoot: string, compilerOptions: ts.CompilerOptions,
|
13
|
+
constructor(projectRoot: string, compilerOptions: ts.CompilerOptions, // TODO: remove this?
|
14
|
+
sourceFileHandler: ValSourceFileHandler, host?: IValFSHost, disableCache?: boolean);
|
14
15
|
getModule(modulePath: string): string;
|
15
16
|
resolveModulePath(containingFilePath: string, requestedModuleName: string): string;
|
16
17
|
private findMatchingJsFile;
|
@@ -676,6 +676,24 @@ const patchSourceFile = (sourceFile, patch$1) => {
|
|
676
676
|
|
677
677
|
const readValFile = async (id, valConfigPath, runtime) => {
|
678
678
|
const context = runtime.newContext();
|
679
|
+
|
680
|
+
// avoid failures when console.log is called
|
681
|
+
const logHandle = context.newFunction("log", () => {
|
682
|
+
// do nothing
|
683
|
+
});
|
684
|
+
const consoleHandle = context.newObject();
|
685
|
+
context.setProp(consoleHandle, "log", logHandle);
|
686
|
+
context.setProp(context.global, "console", consoleHandle);
|
687
|
+
consoleHandle.dispose();
|
688
|
+
logHandle.dispose();
|
689
|
+
|
690
|
+
// avoid failures when process.env is called
|
691
|
+
const envHandle = context.newObject();
|
692
|
+
const processHandle = context.newObject();
|
693
|
+
context.setProp(processHandle, "env", envHandle);
|
694
|
+
context.setProp(context.global, "process", processHandle);
|
695
|
+
envHandle.dispose();
|
696
|
+
processHandle.dispose();
|
679
697
|
try {
|
680
698
|
const modulePath = `.${id}.val`;
|
681
699
|
const code = `import * as valModule from ${JSON.stringify(modulePath)};
|
@@ -716,6 +734,9 @@ globalThis.valModule = {
|
|
716
734
|
if (valModule.id !== id) {
|
717
735
|
fatalErrors.push(`Wrong val.content id! In the file of with: '${id}', found: '${valModule.id}'`);
|
718
736
|
}
|
737
|
+
if (encodeURIComponent(valModule.id).replace(/%2F/g, "/") !== valModule.id) {
|
738
|
+
fatalErrors.push(`Invalid val.content id! Must be a web-safe path without escape characters, found: '${valModule.id}', which was encoded as: '${encodeURIComponent(valModule.id).replace("%2F", "/")}'`);
|
739
|
+
}
|
719
740
|
if (!(valModule !== null && valModule !== void 0 && valModule.schema)) {
|
720
741
|
fatalErrors.push(`Expected val id: '${id}' to have a schema`);
|
721
742
|
}
|
@@ -823,7 +844,9 @@ const MAX_OBJECT_KEY_SIZE = 2 ** 27; // https://stackoverflow.com/questions/1336
|
|
823
844
|
class ValModuleLoader {
|
824
845
|
constructor(projectRoot,
|
825
846
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
826
|
-
compilerOptions,
|
847
|
+
compilerOptions,
|
848
|
+
// TODO: remove this?
|
849
|
+
sourceFileHandler, host = {
|
827
850
|
...ts__default["default"].sys,
|
828
851
|
writeFile: fs__default["default"].writeFileSync
|
829
852
|
}, disableCache = false) {
|
@@ -925,9 +948,9 @@ class ValModuleLoader {
|
|
925
948
|
}
|
926
949
|
|
927
950
|
async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
928
|
-
maxStackSize = 1024 *
|
929
|
-
//
|
930
|
-
memoryLimit = 1024 * 640
|
951
|
+
maxStackSize = 1024 * 20,
|
952
|
+
// maximum stack size that works: 1024 * 640 * 8
|
953
|
+
memoryLimit = 1024 * 640 // 640 mbs
|
931
954
|
} = {}) {
|
932
955
|
const runtime = quickJSModule.newRuntime();
|
933
956
|
runtime.setMaxStackSize(maxStackSize);
|
@@ -948,7 +971,7 @@ async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
|
948
971
|
}
|
949
972
|
if (modulePath === "@valbuild/react/stega") {
|
950
973
|
return {
|
951
|
-
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 */ };"
|
974
|
+
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 */ }; export const stegaClean = () => { throw Error(`Cannot use 'stegaClean' in this type of file`) }; "
|
952
975
|
};
|
953
976
|
}
|
954
977
|
if (modulePath.startsWith("next/navigation")) {
|
@@ -1047,7 +1070,7 @@ async function createService(projectRoot, opts, host = {
|
|
1047
1070
|
const compilerOptions = getCompilerOptions(projectRoot, host);
|
1048
1071
|
const sourceFileHandler = new ValSourceFileHandler(projectRoot, compilerOptions, host);
|
1049
1072
|
const module = await quickjsEmscripten.newQuickJSWASMModule();
|
1050
|
-
const runtime = await newValQuickJSRuntime(module, loader || new ValModuleLoader(projectRoot, compilerOptions, sourceFileHandler, host));
|
1073
|
+
const runtime = await newValQuickJSRuntime(module, loader || new ValModuleLoader(projectRoot, compilerOptions, sourceFileHandler, host, opts.disableCache === undefined ? process.env.NODE_ENV === "development" ? false : true : opts.disableCache));
|
1051
1074
|
return new Service(opts, sourceFileHandler, runtime);
|
1052
1075
|
}
|
1053
1076
|
class Service {
|
@@ -1056,7 +1079,7 @@ class Service {
|
|
1056
1079
|
}, sourceFileHandler, runtime) {
|
1057
1080
|
this.sourceFileHandler = sourceFileHandler;
|
1058
1081
|
this.runtime = runtime;
|
1059
|
-
this.valConfigPath = valConfigPath;
|
1082
|
+
this.valConfigPath = valConfigPath || "./val.config";
|
1060
1083
|
}
|
1061
1084
|
async get(moduleId, modulePath) {
|
1062
1085
|
const valModule = await readValFile(moduleId, this.valConfigPath, this.runtime);
|
@@ -676,6 +676,24 @@ const patchSourceFile = (sourceFile, patch$1) => {
|
|
676
676
|
|
677
677
|
const readValFile = async (id, valConfigPath, runtime) => {
|
678
678
|
const context = runtime.newContext();
|
679
|
+
|
680
|
+
// avoid failures when console.log is called
|
681
|
+
const logHandle = context.newFunction("log", () => {
|
682
|
+
// do nothing
|
683
|
+
});
|
684
|
+
const consoleHandle = context.newObject();
|
685
|
+
context.setProp(consoleHandle, "log", logHandle);
|
686
|
+
context.setProp(context.global, "console", consoleHandle);
|
687
|
+
consoleHandle.dispose();
|
688
|
+
logHandle.dispose();
|
689
|
+
|
690
|
+
// avoid failures when process.env is called
|
691
|
+
const envHandle = context.newObject();
|
692
|
+
const processHandle = context.newObject();
|
693
|
+
context.setProp(processHandle, "env", envHandle);
|
694
|
+
context.setProp(context.global, "process", processHandle);
|
695
|
+
envHandle.dispose();
|
696
|
+
processHandle.dispose();
|
679
697
|
try {
|
680
698
|
const modulePath = `.${id}.val`;
|
681
699
|
const code = `import * as valModule from ${JSON.stringify(modulePath)};
|
@@ -716,6 +734,9 @@ globalThis.valModule = {
|
|
716
734
|
if (valModule.id !== id) {
|
717
735
|
fatalErrors.push(`Wrong val.content id! In the file of with: '${id}', found: '${valModule.id}'`);
|
718
736
|
}
|
737
|
+
if (encodeURIComponent(valModule.id).replace(/%2F/g, "/") !== valModule.id) {
|
738
|
+
fatalErrors.push(`Invalid val.content id! Must be a web-safe path without escape characters, found: '${valModule.id}', which was encoded as: '${encodeURIComponent(valModule.id).replace("%2F", "/")}'`);
|
739
|
+
}
|
719
740
|
if (!(valModule !== null && valModule !== void 0 && valModule.schema)) {
|
720
741
|
fatalErrors.push(`Expected val id: '${id}' to have a schema`);
|
721
742
|
}
|
@@ -823,7 +844,9 @@ const MAX_OBJECT_KEY_SIZE = 2 ** 27; // https://stackoverflow.com/questions/1336
|
|
823
844
|
class ValModuleLoader {
|
824
845
|
constructor(projectRoot,
|
825
846
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
826
|
-
compilerOptions,
|
847
|
+
compilerOptions,
|
848
|
+
// TODO: remove this?
|
849
|
+
sourceFileHandler, host = {
|
827
850
|
...ts__default["default"].sys,
|
828
851
|
writeFile: fs__default["default"].writeFileSync
|
829
852
|
}, disableCache = false) {
|
@@ -925,9 +948,9 @@ class ValModuleLoader {
|
|
925
948
|
}
|
926
949
|
|
927
950
|
async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
928
|
-
maxStackSize = 1024 *
|
929
|
-
//
|
930
|
-
memoryLimit = 1024 * 640
|
951
|
+
maxStackSize = 1024 * 20,
|
952
|
+
// maximum stack size that works: 1024 * 640 * 8
|
953
|
+
memoryLimit = 1024 * 640 // 640 mbs
|
931
954
|
} = {}) {
|
932
955
|
const runtime = quickJSModule.newRuntime();
|
933
956
|
runtime.setMaxStackSize(maxStackSize);
|
@@ -948,7 +971,7 @@ async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
|
948
971
|
}
|
949
972
|
if (modulePath === "@valbuild/react/stega") {
|
950
973
|
return {
|
951
|
-
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 */ };"
|
974
|
+
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 */ }; export const stegaClean = () => { throw Error(`Cannot use 'stegaClean' in this type of file`) }; "
|
952
975
|
};
|
953
976
|
}
|
954
977
|
if (modulePath.startsWith("next/navigation")) {
|
@@ -1047,7 +1070,7 @@ async function createService(projectRoot, opts, host = {
|
|
1047
1070
|
const compilerOptions = getCompilerOptions(projectRoot, host);
|
1048
1071
|
const sourceFileHandler = new ValSourceFileHandler(projectRoot, compilerOptions, host);
|
1049
1072
|
const module = await quickjsEmscripten.newQuickJSWASMModule();
|
1050
|
-
const runtime = await newValQuickJSRuntime(module, loader || new ValModuleLoader(projectRoot, compilerOptions, sourceFileHandler, host));
|
1073
|
+
const runtime = await newValQuickJSRuntime(module, loader || new ValModuleLoader(projectRoot, compilerOptions, sourceFileHandler, host, opts.disableCache === undefined ? true : opts.disableCache));
|
1051
1074
|
return new Service(opts, sourceFileHandler, runtime);
|
1052
1075
|
}
|
1053
1076
|
class Service {
|
@@ -1056,7 +1079,7 @@ class Service {
|
|
1056
1079
|
}, sourceFileHandler, runtime) {
|
1057
1080
|
this.sourceFileHandler = sourceFileHandler;
|
1058
1081
|
this.runtime = runtime;
|
1059
|
-
this.valConfigPath = valConfigPath;
|
1082
|
+
this.valConfigPath = valConfigPath || "./val.config";
|
1060
1083
|
}
|
1061
1084
|
async get(moduleId, modulePath) {
|
1062
1085
|
const valModule = await readValFile(moduleId, this.valConfigPath, this.runtime);
|
@@ -646,6 +646,24 @@ const patchSourceFile = (sourceFile, patch) => {
|
|
646
646
|
|
647
647
|
const readValFile = async (id, valConfigPath, runtime) => {
|
648
648
|
const context = runtime.newContext();
|
649
|
+
|
650
|
+
// avoid failures when console.log is called
|
651
|
+
const logHandle = context.newFunction("log", () => {
|
652
|
+
// do nothing
|
653
|
+
});
|
654
|
+
const consoleHandle = context.newObject();
|
655
|
+
context.setProp(consoleHandle, "log", logHandle);
|
656
|
+
context.setProp(context.global, "console", consoleHandle);
|
657
|
+
consoleHandle.dispose();
|
658
|
+
logHandle.dispose();
|
659
|
+
|
660
|
+
// avoid failures when process.env is called
|
661
|
+
const envHandle = context.newObject();
|
662
|
+
const processHandle = context.newObject();
|
663
|
+
context.setProp(processHandle, "env", envHandle);
|
664
|
+
context.setProp(context.global, "process", processHandle);
|
665
|
+
envHandle.dispose();
|
666
|
+
processHandle.dispose();
|
649
667
|
try {
|
650
668
|
const modulePath = `.${id}.val`;
|
651
669
|
const code = `import * as valModule from ${JSON.stringify(modulePath)};
|
@@ -686,6 +704,9 @@ globalThis.valModule = {
|
|
686
704
|
if (valModule.id !== id) {
|
687
705
|
fatalErrors.push(`Wrong val.content id! In the file of with: '${id}', found: '${valModule.id}'`);
|
688
706
|
}
|
707
|
+
if (encodeURIComponent(valModule.id).replace(/%2F/g, "/") !== valModule.id) {
|
708
|
+
fatalErrors.push(`Invalid val.content id! Must be a web-safe path without escape characters, found: '${valModule.id}', which was encoded as: '${encodeURIComponent(valModule.id).replace("%2F", "/")}'`);
|
709
|
+
}
|
689
710
|
if (!(valModule !== null && valModule !== void 0 && valModule.schema)) {
|
690
711
|
fatalErrors.push(`Expected val id: '${id}' to have a schema`);
|
691
712
|
}
|
@@ -793,7 +814,9 @@ const MAX_OBJECT_KEY_SIZE = 2 ** 27; // https://stackoverflow.com/questions/1336
|
|
793
814
|
class ValModuleLoader {
|
794
815
|
constructor(projectRoot,
|
795
816
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
796
|
-
compilerOptions,
|
817
|
+
compilerOptions,
|
818
|
+
// TODO: remove this?
|
819
|
+
sourceFileHandler, host = {
|
797
820
|
...ts.sys,
|
798
821
|
writeFile: fs.writeFileSync
|
799
822
|
}, disableCache = false) {
|
@@ -895,9 +918,9 @@ class ValModuleLoader {
|
|
895
918
|
}
|
896
919
|
|
897
920
|
async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
898
|
-
maxStackSize = 1024 *
|
899
|
-
//
|
900
|
-
memoryLimit = 1024 * 640
|
921
|
+
maxStackSize = 1024 * 20,
|
922
|
+
// maximum stack size that works: 1024 * 640 * 8
|
923
|
+
memoryLimit = 1024 * 640 // 640 mbs
|
901
924
|
} = {}) {
|
902
925
|
const runtime = quickJSModule.newRuntime();
|
903
926
|
runtime.setMaxStackSize(maxStackSize);
|
@@ -918,7 +941,7 @@ async function newValQuickJSRuntime(quickJSModule, moduleLoader, {
|
|
918
941
|
}
|
919
942
|
if (modulePath === "@valbuild/react/stega") {
|
920
943
|
return {
|
921
|
-
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 */ };"
|
944
|
+
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 */ }; export const stegaClean = () => { throw Error(`Cannot use 'stegaClean' in this type of file`) }; "
|
922
945
|
};
|
923
946
|
}
|
924
947
|
if (modulePath.startsWith("next/navigation")) {
|
@@ -1017,7 +1040,7 @@ async function createService(projectRoot, opts, host = {
|
|
1017
1040
|
const compilerOptions = getCompilerOptions(projectRoot, host);
|
1018
1041
|
const sourceFileHandler = new ValSourceFileHandler(projectRoot, compilerOptions, host);
|
1019
1042
|
const module = await newQuickJSWASMModule();
|
1020
|
-
const runtime = await newValQuickJSRuntime(module, loader || new ValModuleLoader(projectRoot, compilerOptions, sourceFileHandler, host));
|
1043
|
+
const runtime = await newValQuickJSRuntime(module, loader || new ValModuleLoader(projectRoot, compilerOptions, sourceFileHandler, host, opts.disableCache === undefined ? process.env.NODE_ENV === "development" ? false : true : opts.disableCache));
|
1021
1044
|
return new Service(opts, sourceFileHandler, runtime);
|
1022
1045
|
}
|
1023
1046
|
class Service {
|
@@ -1026,7 +1049,7 @@ class Service {
|
|
1026
1049
|
}, sourceFileHandler, runtime) {
|
1027
1050
|
this.sourceFileHandler = sourceFileHandler;
|
1028
1051
|
this.runtime = runtime;
|
1029
|
-
this.valConfigPath = valConfigPath;
|
1052
|
+
this.valConfigPath = valConfigPath || "./val.config";
|
1030
1053
|
}
|
1031
1054
|
async get(moduleId, modulePath) {
|
1032
1055
|
const valModule = await readValFile(moduleId, this.valConfigPath, this.runtime);
|
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.42.0",
|
16
16
|
"scripts": {
|
17
17
|
"typecheck": "tsc --noEmit",
|
18
18
|
"test": "jest",
|
@@ -24,9 +24,9 @@
|
|
24
24
|
"concurrently": "^7.6.0"
|
25
25
|
},
|
26
26
|
"dependencies": {
|
27
|
-
"@valbuild/core": "~0.
|
28
|
-
"@valbuild/shared": "~0.
|
29
|
-
"@valbuild/ui": "~0.
|
27
|
+
"@valbuild/core": "~0.42.0",
|
28
|
+
"@valbuild/shared": "~0.42.0",
|
29
|
+
"@valbuild/ui": "~0.42.0",
|
30
30
|
"express": "^4.18.2",
|
31
31
|
"image-size": "^1.0.2",
|
32
32
|
"queue": "^6.0.2",
|
@@ -37,7 +37,7 @@
|
|
37
37
|
"zod": "^3.20.6"
|
38
38
|
},
|
39
39
|
"engines": {
|
40
|
-
"node": ">=18.17.
|
40
|
+
"node": ">=18.17.0"
|
41
41
|
},
|
42
42
|
"files": [
|
43
43
|
"dist"
|