Dynamic access to Operators in both front and backend

This commit is contained in:
Felix Kaspar 2024-02-23 23:48:03 +01:00
parent 244fb36195
commit 644e0ceae9
18 changed files with 593 additions and 74 deletions

View File

@ -36,6 +36,7 @@
"@vitejs/plugin-react": "^4.0.3", "@vitejs/plugin-react": "^4.0.3",
"typescript": "^5.0.2", "typescript": "^5.0.2",
"vite": "^4.4.4", "vite": "^4.4.4",
"vite-plugin-compile-time": "^0.2.1",
"vite-plugin-dynamic-import": "^1.5.0" "vite-plugin-dynamic-import": "^1.5.0"
} }
} }

View File

@ -0,0 +1,15 @@
import Joi from "@stirling-tools/joi";
interface BuildFieldsProps {
/** The text to display inside the button */
schemaDescription: Joi.Description | undefined;
}
export function BuildFields({ schemaDescription }: BuildFieldsProps) {
console.log("Render Build Fields", schemaDescription);
return (
<div>Description: {(schemaDescription?.flags as any)?.description}</div>
);
}

View File

@ -0,0 +1,12 @@
interface StringFieldProps {
/** The text to display inside the button */
validValues: string[];
exampleValues: string;
}
export function StringField({ validValues, exampleValues }: StringFieldProps) {
return (
<button>{validValues}</button>
);
}

View File

@ -1,15 +1,23 @@
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { BaseSyntheticEvent } from "react"; import { BaseSyntheticEvent, createContext, useState } from "react";
import { Operator } from "@stirling-pdf/shared-operations/src/functions"; import { Operator } from "@stirling-pdf/shared-operations/src/functions";
import i18next from "i18next"; import i18next from "i18next";
import Joi from "@stirling-tools/joi";
import { BuildFields } from "../components/fields/BuildFields";
function Dynamic() { function Dynamic() {
const [schemaDescription, setSchemaDescription] = useState<Joi.Description>();
const operators = ["impose"]; // TODO: Make this dynamic const operators = ["impose"]; // TODO: Make this dynamic
function selectionChanged(s: BaseSyntheticEvent) { function selectionChanged(s: BaseSyntheticEvent) {
const selectedValue = s.target.value; const selectedValue = s.target.value;
if(selectedValue == "none") return; if(selectedValue == "none") {
setSchemaDescription(undefined);
return;
}
i18next.loadNamespaces("impose", (err, t) => { i18next.loadNamespaces("impose", (err, t) => {
if (err) throw err; if (err) throw err;
@ -19,8 +27,8 @@ function Dynamic() {
const Operator = Module[capitalizeFirstLetter(selectedValue)]; const Operator = Module[capitalizeFirstLetter(selectedValue)];
const description = Operator.schema.describe(); const description = Operator.schema.describe();
setSchemaDescription(description); // This will update children
console.log(description); console.log(description);
// TODO: use description to generate fields
}); });
}); });
} }
@ -35,21 +43,19 @@ function Dynamic() {
<input type="file" id="pdfFile" accept=".pdf" multiple /> <input type="file" id="pdfFile" accept=".pdf" multiple />
<br /> <br />
<br />
<textarea name="workflow" id="workflow"></textarea>
<br />
<select id="pdfOptions" onChange={selectionChanged}> <select id="pdfOptions" onChange={selectionChanged}>
<option value="none">none</option> <option value="none">none</option>
{ operators.map((operator, i) => { { operators.map((operator, i) => {
return (<option value={operator}>{operator}</option>) return (<option value={operator}>{operator}</option>)
}) } }) }
</select> </select>
<button id="loadButton">Load</button>
<br /> <div id="values">
<BuildFields schemaDescription={schemaDescription}></BuildFields>
</div>
<br /> <br />
<button id="doneButton">Done</button> <button id="processButton">Process process file with current settings</button>
<p> <p>
<Link to="/">Go back home...</Link> <Link to="/">Go back home...</Link>

View File

@ -2,6 +2,8 @@ import { defineConfig } from "vite";
import react from "@vitejs/plugin-react"; import react from "@vitejs/plugin-react";
import topLevelAwait from "vite-plugin-top-level-await"; import topLevelAwait from "vite-plugin-top-level-await";
import dynamicImport from 'vite-plugin-dynamic-import' import dynamicImport from 'vite-plugin-dynamic-import'
import compileTime from "vite-plugin-compile-time"
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(async () => ({ export default defineConfig(async () => ({
@ -13,6 +15,7 @@ export default defineConfig(async () => ({
// The function to generate import names of top-level await promise in each chunk module // The function to generate import names of top-level await promise in each chunk module
promiseImportName: i => `__tla_${i}` promiseImportName: i => `__tla_${i}`
}), }),
compileTime(),
dynamicImport(), dynamicImport(),
], ],

456
package-lock.json generated
View File

@ -50,6 +50,7 @@
"@vitejs/plugin-react": "^4.0.3", "@vitejs/plugin-react": "^4.0.3",
"typescript": "^5.0.2", "typescript": "^5.0.2",
"vite": "^4.4.4", "vite": "^4.4.4",
"vite-plugin-compile-time": "^0.2.1",
"vite-plugin-dynamic-import": "^1.5.0" "vite-plugin-dynamic-import": "^1.5.0"
} }
}, },
@ -474,6 +475,21 @@
"@jridgewell/sourcemap-codec": "^1.4.10" "@jridgewell/sourcemap-codec": "^1.4.10"
} }
}, },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
"integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==",
"cpu": [
"ppc64"
],
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.18.20", "version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@ -790,9 +806,9 @@
} }
}, },
"node_modules/@esbuild/win32-x64": { "node_modules/@esbuild/win32-x64": {
"version": "0.19.11", "version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz",
"integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -1550,6 +1566,30 @@
} }
} }
}, },
"node_modules/@rollup/plugin-dynamic-import-vars": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-dynamic-import-vars/-/plugin-dynamic-import-vars-2.1.2.tgz",
"integrity": "sha512-4lr2oXxs9hcxtGGaK8s0i9evfjzDrAs7ngw28TqruWKTEm0+U4Eljb+F6HXGYdFv8xRojQlrQwV7M/yxeh3yzQ==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"astring": "^1.8.5",
"estree-walker": "^2.0.2",
"fast-glob": "^3.2.12",
"magic-string": "^0.30.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-inject": { "node_modules/@rollup/plugin-inject": {
"version": "5.0.5", "version": "5.0.5",
"resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz",
@ -2910,7 +2950,6 @@
"version": "8.11.3", "version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -3118,6 +3157,15 @@
"util": "^0.12.5" "util": "^0.12.5"
} }
}, },
"node_modules/astring": {
"version": "1.8.6",
"resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz",
"integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==",
"dev": true,
"bin": {
"astring": "bin/astring"
}
},
"node_modules/async": { "node_modules/async": {
"version": "3.2.5", "version": "3.2.5",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
@ -3438,6 +3486,20 @@
"resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
"integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ=="
}, },
"node_modules/bundle-require": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.2.tgz",
"integrity": "sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag==",
"dependencies": {
"load-tsconfig": "^0.2.3"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"peerDependencies": {
"esbuild": ">=0.17"
}
},
"node_modules/busboy": { "node_modules/busboy": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
@ -4233,6 +4295,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/devalue": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-4.3.2.tgz",
"integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg=="
},
"node_modules/diff": { "node_modules/diff": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
@ -4370,8 +4437,7 @@
"node_modules/es-module-lexer": { "node_modules/es-module-lexer": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz",
"integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w=="
"dev": true
}, },
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.18.20", "version": "0.18.20",
@ -6098,6 +6164,14 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/load-tsconfig": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz",
"integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/locate-path": { "node_modules/locate-path": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -8970,11 +9044,376 @@
} }
} }
}, },
"node_modules/vite-plugin-compile-time": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/vite-plugin-compile-time/-/vite-plugin-compile-time-0.2.1.tgz",
"integrity": "sha512-lRuoSO2wg2r0rWPLo9aeOH3s70FcuQZIhvcR7yGubbezFVsebljWf9Vtk/TlvuvBLLahfnEUyeV2FQM2sj2EYQ==",
"dependencies": {
"bundle-require": "^4.0.1",
"devalue": "^4.3.2",
"esbuild": "^0.19.1",
"magic-string": "^0.30.2"
},
"peerDependencies": {
"vite": ">=2"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/android-arm": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz",
"integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/android-arm64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz",
"integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/android-x64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz",
"integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/darwin-arm64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz",
"integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/darwin-x64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz",
"integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/freebsd-arm64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz",
"integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/freebsd-x64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz",
"integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-arm": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz",
"integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-arm64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz",
"integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-ia32": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz",
"integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-loong64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz",
"integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==",
"cpu": [
"loong64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-mips64el": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz",
"integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==",
"cpu": [
"mips64el"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-ppc64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz",
"integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==",
"cpu": [
"ppc64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-riscv64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz",
"integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==",
"cpu": [
"riscv64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-s390x": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz",
"integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==",
"cpu": [
"s390x"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/linux-x64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz",
"integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/netbsd-x64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz",
"integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/openbsd-x64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz",
"integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/sunos-x64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz",
"integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/win32-arm64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz",
"integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/@esbuild/win32-ia32": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz",
"integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/vite-plugin-compile-time/node_modules/esbuild": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
"integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.19.12",
"@esbuild/android-arm": "0.19.12",
"@esbuild/android-arm64": "0.19.12",
"@esbuild/android-x64": "0.19.12",
"@esbuild/darwin-arm64": "0.19.12",
"@esbuild/darwin-x64": "0.19.12",
"@esbuild/freebsd-arm64": "0.19.12",
"@esbuild/freebsd-x64": "0.19.12",
"@esbuild/linux-arm": "0.19.12",
"@esbuild/linux-arm64": "0.19.12",
"@esbuild/linux-ia32": "0.19.12",
"@esbuild/linux-loong64": "0.19.12",
"@esbuild/linux-mips64el": "0.19.12",
"@esbuild/linux-ppc64": "0.19.12",
"@esbuild/linux-riscv64": "0.19.12",
"@esbuild/linux-s390x": "0.19.12",
"@esbuild/linux-x64": "0.19.12",
"@esbuild/netbsd-x64": "0.19.12",
"@esbuild/openbsd-x64": "0.19.12",
"@esbuild/sunos-x64": "0.19.12",
"@esbuild/win32-arm64": "0.19.12",
"@esbuild/win32-ia32": "0.19.12",
"@esbuild/win32-x64": "0.19.12"
}
},
"node_modules/vite-plugin-dynamic-import": { "node_modules/vite-plugin-dynamic-import": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/vite-plugin-dynamic-import/-/vite-plugin-dynamic-import-1.5.0.tgz", "resolved": "https://registry.npmjs.org/vite-plugin-dynamic-import/-/vite-plugin-dynamic-import-1.5.0.tgz",
"integrity": "sha512-Qp85c+AVJmLa8MLni74U4BDiWpUeFNx7NJqbGZyR2XJOU7mgW0cb7nwlAMucFyM4arEd92Nfxp4j44xPi6Fu7g==", "integrity": "sha512-Qp85c+AVJmLa8MLni74U4BDiWpUeFNx7NJqbGZyR2XJOU7mgW0cb7nwlAMucFyM4arEd92Nfxp4j44xPi6Fu7g==",
"dev": true,
"dependencies": { "dependencies": {
"acorn": "^8.8.2", "acorn": "^8.8.2",
"es-module-lexer": "^1.2.1", "es-module-lexer": "^1.2.1",
@ -9318,10 +9757,13 @@
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",
"rollup-plugin-copy": "^3.5.0", "rollup-plugin-copy": "^3.5.0",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"vite-plugin-compile-time": "^0.2.1",
"vite-plugin-dynamic-import": "^1.5.0",
"vite-plugin-node-polyfills": "^0.19.0", "vite-plugin-node-polyfills": "^0.19.0",
"vite-plugin-top-level-await": "^1.4.1" "vite-plugin-top-level-await": "^1.4.1"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-dynamic-import-vars": "^2.1.2",
"@rollup/plugin-run": "^3.0.2", "@rollup/plugin-run": "^3.0.2",
"@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-typescript": "^11.1.6",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",

View File

@ -36,10 +36,13 @@
"pdf-lib": "^1.17.1", "pdf-lib": "^1.17.1",
"rollup-plugin-copy": "^3.5.0", "rollup-plugin-copy": "^3.5.0",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"vite-plugin-compile-time": "^0.2.1",
"vite-plugin-dynamic-import": "^1.5.0",
"vite-plugin-node-polyfills": "^0.19.0", "vite-plugin-node-polyfills": "^0.19.0",
"vite-plugin-top-level-await": "^1.4.1" "vite-plugin-top-level-await": "^1.4.1"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-dynamic-import-vars": "^2.1.2",
"@rollup/plugin-run": "^3.0.2", "@rollup/plugin-run": "^3.0.2",
"@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-typescript": "^11.1.6",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",

View File

@ -1,15 +1,16 @@
import run from "@rollup/plugin-run"; import run from "@rollup/plugin-run";
import typescript from '@rollup/plugin-typescript'; import typescript from '@rollup/plugin-typescript';
import json from '@rollup/plugin-json'; import json from '@rollup/plugin-json';
import copy from 'rollup-plugin-copy' import copy from 'rollup-plugin-copy';
import compileTime from "vite-plugin-compile-time";
import dynamicImportVars from '@rollup/plugin-dynamic-import-vars';
const isDev = process.env.NODE_ENV !== "production"; const isDev = process.env.NODE_ENV !== "production";
export default { export default {
input: "src/index.ts", input: "src/index.ts",
output: { output: {
file: "dist/bundle.js", dir: "dist/",
format: "es", format: "es",
}, },
watch: { watch: {
@ -18,6 +19,8 @@ export default {
plugins: [ plugins: [
json(), json(),
typescript(), typescript(),
dynamicImportVars(),
compileTime(),
copy({ copy({
targets: [ targets: [
{ src: '../shared-operations/public', dest: 'dist' }, { src: '../shared-operations/public', dest: 'dist' },

View File

@ -6,6 +6,7 @@ const PORT = 8000;
// server-node: backend api // server-node: backend api
import api from "./routes/api/api-controller"; import api from "./routes/api/api-controller";
import { listOperatorNames } from "@stirling-pdf/shared-operations/src/workflow/operatorAccessor";
app.use("/api", api); app.use("/api", api);
// serve // serve
@ -16,3 +17,5 @@ app.listen(PORT, () => {
process.on('unhandledRejection', (reason, promise) => { process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason); console.error('Unhandled Rejection at:', promise, 'reason:', reason);
}); });
console.log("Available Modules: ", listOperatorNames())

View File

@ -2,7 +2,7 @@ import express, { Request, Response } from "express";
const router = express.Router(); const router = express.Router();
import multer from "multer"; import multer from "multer";
const upload = multer(); const upload = multer();
import { getOperatorByName } from "@stirling-pdf/shared-operations/src/workflow/getOperatorByName"; import { getOperatorByName } from "@stirling-pdf/shared-operations/src/workflow/operatorAccessor";
import { Operator } from "@stirling-pdf/shared-operations/src/functions"; import { Operator } from "@stirling-pdf/shared-operations/src/functions";
import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"; import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile";
@ -11,14 +11,14 @@ import { Action } from "@stirling-pdf/shared-operations/declarations/Action";
import { JoiPDFFileSchema } from "@stirling-pdf/shared-operations/src/wrappers/PdfFileJoi"; import { JoiPDFFileSchema } from "@stirling-pdf/shared-operations/src/wrappers/PdfFileJoi";
router.post("/:func", upload.array("file"), async function(req: Request, res: Response) { router.post("/:func", upload.array("file"), async function(req: Request, res: Response) {
handleEndpoint(req, res); await handleEndpoint(req, res);
}); });
router.post("/:dir/:func", upload.array("file"), async function(req: Request, res: Response) { router.post("/:dir/:func", upload.array("file"), async function(req: Request, res: Response) {
handleEndpoint(req, res); await handleEndpoint(req, res);
}); });
function handleEndpoint(req: Request, res: Response) { async function handleEndpoint(req: Request, res: Response) {
if(!req.files || req.files.length == 0) { if(!req.files || req.files.length == 0) {
res.status(400).json({error: "no input file(s) were provided"}); res.status(400).json({error: "no input file(s) were provided"});
return; return;
@ -31,7 +31,8 @@ function handleEndpoint(req: Request, res: Response) {
} }
const pdfFiles: PdfFile[] = validationResults.value; const pdfFiles: PdfFile[] = validationResults.value;
const operator = getOperatorByName(req.params.func); const operator = await getOperatorByName(req.params.func);
if(operator) { if(operator) {
const action: Action = {type: req.params.func, values: req.body}; const action: Action = {type: req.params.func, values: req.body};

View File

@ -30,7 +30,7 @@
"moduleResolution": "Node", /* Specify how TypeScript looks up a file from a given module specifier. */ "moduleResolution": "Node", /* Specify how TypeScript looks up a file from a given module specifier. */
"baseUrl": "./src", /* Specify the base directory to resolve non-relative module names. */ "baseUrl": "./src", /* Specify the base directory to resolve non-relative module names. */
"paths": { "paths": {
"#pdfcpu": ["@stirling-pdf/shared-operations/src/wasm/pdfcpu/pdfcpu-wrapper.server"], "#pdfcpu": ["../shared-operations/src/wasm/pdfcpu/pdfcpu-wrapper.server.js"],
"@stirling-pdf/*": [ "../../*" ] "@stirling-pdf/*": [ "../../*" ]
}, /* Specify a set of entries that re-map imports to additional lookup locations. */ }, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */

View File

@ -0,0 +1,3 @@
declare interface ImportMeta {
compileTime: <T>(file: string) => T
}

View File

@ -1,8 +1,7 @@
import { PdfFile } from "../wrappers/PdfFile";
import { PdfFile } from "../wrappers/PdfFile.js"; import { Sorts } from "./common/pageIndexesSorting";
import { Sorts } from "./common/pageIndexesSorting.js"; import { getPages } from "./common/getPagesByIndex";
import { getPages } from "./common/getPagesByIndex.js"; import { parsePageIndexSpecification } from "./common/pageIndexesUtils";
import { parsePageIndexSpecification } from "./common/pageIndexesUtils.js";
export interface ArrangePagesParamsType { export interface ArrangePagesParamsType {
file: PdfFile; file: PdfFile;

View File

@ -1,34 +0,0 @@
import { Operator } from "../functions";
import i18next from "i18next";
// TODO: Import other Operators (should make this dynamic imports)
i18next.loadNamespaces("impose", (err, t) => { if (err) throw err; });
import { Impose } from "../functions/impose";
export const Operators = {
Impose: Impose
};
// TODO: Convert this to a map or similar
export function getOperatorByName(name: string): typeof Operator | undefined {
let foundClass: typeof Operator | undefined = undefined;
// Loop over each default export
Object.entries(Operators).some(([className, exportedClass]) => {
// Check if the exported item is a class
if (typeof exportedClass === "function" && exportedClass.prototype) {
if (exportedClass.type === name) {
foundClass = exportedClass;
return true; // Stop the iteration
}
}
return false;
});
return foundClass;
}
export function listOperatorNames(): string[] {
// TODO: Implement this
return ["impose"];
}

View File

@ -0,0 +1,38 @@
import fs from "fs";
import path from "path";
import {
CompileTimeFunctionArgs,
CompileTimeFunctionResult,
} from "vite-plugin-compile-time"
function getAllJsFiles(directory) {
const jsFiles = [];
// Synchronously read the contents of the directory
const files = fs.readdirSync(directory);
// Iterate through the files and filter out the JavaScript files
files.forEach((file) => {
const filePath = path.join(directory, file)
const isJsFile = fs.statSync(filePath).isFile() && path.extname(filePath) === '.ts';
if (isJsFile) {
const baseName = path.basename(filePath, '.ts');
if(baseName != "index") {
jsFiles.push(baseName);
}
}
});
return jsFiles;
}
export default async (
args: CompileTimeFunctionArgs,
): Promise<CompileTimeFunctionResult> => {
const jsFiles = getAllJsFiles(__dirname + "/../functions/");
return {
data: jsFiles,
// Trigger rebuild when watched files change
watchFiles: [__filename],
}
}

View File

@ -0,0 +1,24 @@
import { Operator } from "../functions";
import i18next from "i18next";
function getCompileTimeOperatorList(): string[] {
return import.meta.compileTime("./listOperatorsInDir.ts");
}
export async function getOperatorByName(name: string): Promise<typeof Operator | undefined> {
// Check if exists
if(!getCompileTimeOperatorList().includes(name)) return;
i18next.loadNamespaces(name, (err, t) => { if (err) throw err; });
return (await import("../functions/" + name + ".ts"))[capitalizeFirstLetter(name)];
}
export function listOperatorNames(): string[] {
const availableOperators = getCompileTimeOperatorList();
// TODO: Implement this
return availableOperators;
}
function capitalizeFirstLetter(string: String) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

View File

@ -3,10 +3,10 @@ import { Action, WaitAction } from "../../declarations/Action";
import { PdfFile } from "../wrappers/PdfFile"; import { PdfFile } from "../wrappers/PdfFile";
import { Progress } from "../functions"; import { Progress } from "../functions";
import { validateOperations } from "./validateOperations"; import { validateOperations } from "./validateOperations";
import { getOperatorByName } from "./getOperatorByName"; import { getOperatorByName } from "./operatorAccessor";
export async function traverseOperations(operations: Action[], input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> { export async function traverseOperations(operations: Action[], input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
const validationResult = validateOperations(operations); const validationResult = await validateOperations(operations);
if(!validationResult.valid) { if(!validationResult.valid) {
return Promise.reject({validationError: validationResult.reason}); return Promise.reject({validationError: validationResult.reason});
} }
@ -47,7 +47,7 @@ export async function traverseOperations(operations: Action[], input: PdfFile[],
} }
break; break;
default: default:
const operator = getOperatorByName(action.type); const operator = await getOperatorByName(action.type);
if(operator) { if(operator) {
const operation = new operator(action); const operation = new operator(action);
input = await operation.run(input, progressCallback); input = await operation.run(input, progressCallback);

View File

@ -1,9 +1,9 @@
import { Operator } from "../functions"; import { Operator } from "../functions";
import { Action } from "../../declarations/Action"; import { Action } from "../../declarations/Action";
import { getOperatorByName } from "./getOperatorByName"; import { getOperatorByName } from "./operatorAccessor";
/** This function validates the "workflow-json" from the API */ /** This function validates the "workflow-json" from the API */
export function validateOperations(actions: Action[]): { valid: boolean, reason?: string} { export async function validateOperations(actions: Action[]): Promise<{ valid: boolean, reason?: string}> {
const done: Action[] = []; const done: Action[] = [];
for (const action of actions) { for (const action of actions) {
@ -15,7 +15,7 @@ export function validateOperations(actions: Action[]): { valid: boolean, reason?
continue; continue;
} }
const operator = getOperatorByName(action.type); const operator = await getOperatorByName(action.type);
if(!operator) { if(!operator) {
return { valid: false, reason: `action.type ${action.type} does not exist` }; return { valid: false, reason: `action.type ${action.type} does not exist` };
} }
@ -35,7 +35,7 @@ export function validateOperations(actions: Action[]): { valid: boolean, reason?
} }
for (const afterDoneChild of done[childAction.values.id]?.actions || []) { for (const afterDoneChild of done[childAction.values.id]?.actions || []) {
const receivingOperator = getOperatorByName(afterDoneChild.type); const receivingOperator = await getOperatorByName(afterDoneChild.type);
if (receivingOperator === undefined) { if (receivingOperator === undefined) {
return { valid: false, reason: `action.type ${afterDoneChild.type} does not exist.` }; return { valid: false, reason: `action.type ${afterDoneChild.type} does not exist.` };
} else if (!ioCompatible(operator, receivingOperator)) { } else if (!ioCompatible(operator, receivingOperator)) {
@ -47,7 +47,7 @@ export function validateOperations(actions: Action[]): { valid: boolean, reason?
return { valid: false, reason: "There shouldn't be a done action here." }; return { valid: false, reason: "There shouldn't be a done action here." };
} }
else { else {
const receivingOperator = getOperatorByName(childAction.type); const receivingOperator = await getOperatorByName(childAction.type);
if (receivingOperator === undefined) { if (receivingOperator === undefined) {
return { valid: false, reason: `action.type ${childAction.type} does not exist.` }; return { valid: false, reason: `action.type ${childAction.type} does not exist.` };
} else if (!ioCompatible(operator, receivingOperator)) { } else if (!ioCompatible(operator, receivingOperator)) {
@ -56,7 +56,7 @@ export function validateOperations(actions: Action[]): { valid: boolean, reason?
} }
} }
const validationResult = validateOperations(action.actions); const validationResult = await validateOperations(action.actions);
if(!validationResult.valid) { if(!validationResult.valid) {
return validationResult; return validationResult;