Add verification and value stripping

This commit is contained in:
K35
2022-01-02 22:02:47 +00:00
parent db21c1c42e
commit cf49fca928
9 changed files with 272 additions and 125 deletions

View File

@ -7496,6 +7496,7 @@ var CompileTarget = class {
}
};
function compile(ir, target) {
target.start();
ir.forEach((step) => {
const [type, def] = step;
if (type == "type")
@ -7523,13 +7524,15 @@ var TypescriptTarget = class extends CompileTarget {
name = "Typescript";
flavour = "node";
start() {
this.writeFormattedFile("ts_base.ts", this.getTemplate("ts_base.ts"));
}
generateImport(imports, path) {
return `import ${imports} from "${path + (this.flavour === "esm" ? ".ts" : "")}";
`;
}
generateImports(a, def) {
a(0, def.depends.map((dep) => this.generateImport(`${dep}, { verify_${dep} }`, "./" + dep)));
a(0, this.generateImport(`{ VerificationError, verify_number, verify_string, verify_boolean, verify_void, strip_number, strip_string, strip_boolean, strip_void }`, `./ts_base`));
a(0, def.depends.map((dep) => this.generateImport(`${dep}, { verify_${dep}, strip_${dep} }`, "./" + dep)));
}
getFileName(typename) {
return typename + ".ts";
@ -7552,7 +7555,7 @@ var TypescriptTarget = class extends CompileTarget {
if (field.array) {
type = toJSType(field.type) + "[]";
} else if (field.map) {
type = `Map<${toJSType(field.map)}, ${toJSType(field.type)}>`;
type = `{ [key: ${toJSType(field.map)}]: ${toJSType(field.type)} }`;
} else {
type = toJSType(field.type);
}
@ -7569,39 +7572,58 @@ var TypescriptTarget = class extends CompileTarget {
a(1, `}`);
a(0, ``);
a(0, ``);
a(1, `static verify(data: ${def.name}){`);
a(2, `return verify_${def.name}(data);`);
a(1, `static verify(data: ${def.name}) {`);
a(2, `verify_${def.name}(data);`);
a(1, `}`);
a(0, `}`);
a(0, ``);
a(0, `export function verify_${def.name}(data: ${def.name}): boolean {`);
a(0, `export function strip_${def.name}(data: ${def.name}): ${def.name} {`);
{
a(1, `let res = {} as any;`);
def.fields.forEach((field) => {
if (field.array) {
a(1, `res["${field.name}"] = data["${field.name}"].map(elm=>`);
a(2, `strip_${field.type}(elm)`);
a(1, `)`);
} else if (field.map) {
a(1, `res["${field.name}"] = {}`);
a(1, `Object.entries(data["${field.name}"]).forEach(([key, val]) => res["${field.name}"][key] = strip_${field.type}(val))`);
} else {
a(1, `res["${field.name}"] = strip_${field.type}(data["${field.name}"])`);
}
});
a(1, `return res;`);
}
a(0, `}`);
a(0, ``);
a(0, `export function verify_${def.name}(data: ${def.name}) {`);
{
def.fields.forEach((field) => {
a(1, `if(data["${field.name}"] !== null && data["${field.name}"] !== undefined ) {`);
const verifyType = (varName) => {
const verifyType = (varName, off = 0) => {
switch (field.type) {
case "string":
a(2, `if(typeof ${varName} !== "string") return false;`);
a(2 + off, `if(typeof ${varName} !== "string") throw new VerificationError("string", "${field.name}", ${varName});`);
break;
case "number":
a(2, `if(typeof ${varName} !== "number") return false;`);
a(2 + off, `if(typeof ${varName} !== "number") throw new VerificationError("number", "${field.name}", ${varName});`);
break;
case "boolean":
a(2, `if(typeof ${varName} !== "boolean") return false;`);
a(2 + off, `if(typeof ${varName} !== "boolean") throw new VerificationError("boolean", "${field.name}", ${varName});`);
break;
default:
a(2, `if(!verify_${field.type}(${varName})) return false;`);
a(2 + off, `if(!verify_${field.type}(${varName})) throw new VerificationError("${field.type}", "${field.name}", ${varName});`);
}
};
if (field.array) {
a(2, `if(!Array.isArray(data["${field.name}"])) return false`);
a(2, `if(!Array.isArray(data["${field.name}"])) throw new VerificationError("array", "${field.name}", data["${field.name}"]);`);
a(2, `for(const elm of data["${field.name}"]) {`);
verifyType("elm");
verifyType("elm", 1);
a(2, `}`);
} else if (field.map) {
a(2, `if(typeof data["${field.name}"] !== "object") return false`);
a(2, `if(typeof data["${field.name}"] !== "object") throw new VerificationError("object", ${field.name}, data["${field.name}"]);`);
a(2, `for(const key in data["${field.name}"]) {`);
verifyType(`data["${field.name}"][key]`);
verifyType(`data["${field.name}"][key]`, 1);
a(2, `}`);
} else {
verifyType(`data["${field.name}"]`);
@ -7609,7 +7631,7 @@ var TypescriptTarget = class extends CompileTarget {
a(1, "}");
a(0, ``);
});
a(1, `return true`);
a(1, `return data`);
}
a(0, `}`);
this.writeFormattedFile(this.getFileName(def.name), lines.join("\n"));
@ -7627,14 +7649,21 @@ var TypescriptTarget = class extends CompileTarget {
a(1, `${value.name}=${value.value},`);
}
a(0, `}`);
a(0, ``);
a(0, `export default ${def.name}`);
a(0, `export function verify_${def.name} (data: ${def.name}): boolean {`);
a(1, `return ${def.name}[data] != undefined`);
a(0, "}");
a(0, ``);
a(0, `export function strip_${def.name} (data: ${def.name}): ${def.name} {`);
a(1, `return data;`);
a(0, `}`);
a(0, ``);
a(0, `export function verify_${def.name} (data: ${def.name}) {`);
a(1, `if(${def.name}[data] == undefined) throw new VerificationError("${def.name}", undefined, data);`);
a(1, `return data`);
a(0, `}`);
this.writeFormattedFile(this.getFileName(def.name), lines.join("\n"));
}
generateServiceClient(def) {
this.writeFile("service_client.ts", this.generateImport("{ RequestObject, ResponseObject, ErrorCodes, Logging }", "./service_base") + "\n\n" + this.getTemplate("ts_service_client.ts"));
this.writeFormattedFile("service_client.ts", this.generateImport("{ RequestObject, ResponseObject, ErrorCodes, Logging }", "./service_base") + this.generateImport(" { VerificationError }", "./ts_base") + "\n\n" + this.getTemplate("ts_service_client.ts"));
let lines = [];
const a = (i, t) => {
if (!Array.isArray(t)) {
@ -7648,7 +7677,6 @@ var TypescriptTarget = class extends CompileTarget {
a(1, `${dep},`);
});
a(0, `}`);
a(0, this.generateImport("{ verify_number, verify_string, verify_boolean, verify_void }", "./service_base"));
a(0, this.generateImport("{ Service, ServiceProvider, getRandomID }", "./service_client"));
a(0, ``);
a(0, `export class ${def.name} extends Service {`);
@ -7680,10 +7708,10 @@ var TypescriptTarget = class extends CompileTarget {
a(2, `}).then(result => {`);
if (fnc.return.array) {
a(2, `for(const elm of result) {`);
a(3, `if(!verify_${fnc.return.type}(elm)) throw new Error("Invalid result data!");`);
a(3, `verify_${fnc.return.type}(elm);`);
a(2, `}`);
} else {
a(3, `if(!verify_${fnc.return.type}(result)) throw new Error("Invalid result data!");`);
a(3, `verify_${fnc.return.type}(result);`);
}
a(3, `return result;`);
a(2, `});`);
@ -7703,7 +7731,7 @@ var TypescriptTarget = class extends CompileTarget {
}
t.forEach((l) => lines.push(" ".repeat(i) + l.trim()));
};
this.writeFile("service_server.ts", this.generateImport("{ RequestObject, ResponseObject, ErrorCodes, Logging }", "./service_base") + "\n\n" + this.getTemplate("ts_service_server.ts"));
this.writeFormattedFile("service_server.ts", this.generateImport("{ RequestObject, ResponseObject, ErrorCodes, Logging }", "./service_base") + this.generateImport(" { VerificationError }", "./ts_base") + "\n\n" + this.getTemplate("ts_service_server.ts"));
this.generateImports(a, def);
a(0, `export type {`);
def.depends.forEach((dep) => {
@ -7711,7 +7739,6 @@ var TypescriptTarget = class extends CompileTarget {
});
a(0, `}`);
a(0, this.generateImport("{ Service }", "./service_server"));
a(0, this.generateImport("{ verify_number, verify_string, verify_boolean, verify_void }", "./service_base"));
a(0, ``);
a(0, `export abstract class ${def.name}<T> extends Service<T> {`);
a(1, `public name = "${def.name}";`);
@ -7743,16 +7770,16 @@ var TypescriptTarget = class extends CompileTarget {
a(2, `if(p[${i}] !== null && p[${i}] !== undefined) {`);
if (fnc.inputs[i].array) {
a(2, `for(const elm of p[${i}]) {`);
a(3, `if(!verify_${fnc.inputs[i].type}(elm)) throw new Error("Parameter verification failed!")`);
a(3, `verify_${fnc.inputs[i].type}(elm)`);
a(2, `}`);
} else {
a(2, `if(!verify_${fnc.inputs[i].type}(p[${i}])) throw new Error("Parameter verification failed!")`);
a(2, `verify_${fnc.inputs[i].type}(p[${i}])`);
}
a(2, `}`);
}
a(2, ``);
a(2, `p.push(ctx);`);
a(2, `return this.${fnc.name}.call(this, ...p)${((_a = fnc.return) == null ? void 0 : _a.type) == "void" ? ".then(res => undefined)" : ""};`);
a(2, `return this.${fnc.name}.call(this, ...p)` + (fnc.return ? `.then(${((_a = fnc.return) == null ? void 0 : _a.array) ? `res => res.map(e => verify_${fnc.return.type}(strip_${fnc.return.type}(e)))` : `res => verify_${fnc.return.type}(strip_${fnc.return.type}(res))`});` : ""));
a(1, `}`);
a(0, ``);
}
@ -7760,7 +7787,7 @@ var TypescriptTarget = class extends CompileTarget {
this.writeFormattedFile(this.getFileName(def.name + "_server"), lines.join("\n"));
}
generateService(def) {
this.writeFile("service_base.ts", this.getTemplate("ts_service_base.ts"));
this.writeFormattedFile("service_base.ts", this.getTemplate("ts_service_base.ts"));
this.generateServiceClient(def);
this.generateServiceServer(def);
}
@ -7790,14 +7817,14 @@ var TypescriptTarget = class extends CompileTarget {
steps.forEach(([type, def]) => {
switch (type) {
case "type":
a(0, this.generateImport(`${def.name}, { verify_${def.name} }`, "./" + def.name));
a(0, `export { verify_${def.name} }`);
a(0, this.generateImport(`${def.name}, { verify_${def.name}, strip_${def.name} }`, "./" + def.name));
a(0, `export { verify_${def.name}, strip_${def.name} }`);
a(0, `export type { ${def.name} }`);
a(0, ``);
break;
case "enum":
a(0, this.generateImport(`${def.name}, { verify_${def.name} }`, "./" + def.name));
a(0, `export { ${def.name}, verify_${def.name} }`);
a(0, this.generateImport(`${def.name}, { verify_${def.name}, strip_${def.name} }`, "./" + def.name));
a(0, `export { ${def.name}, verify_${def.name}, strip_${def.name} }`);
a(0, ``);
break;
case "service":