Dynamic access to Operators in both front and backend
This commit is contained in:
3
shared-operations/declarations/ImportMeta.d.ts
vendored
Normal file
3
shared-operations/declarations/ImportMeta.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
declare interface ImportMeta {
|
||||
compileTime: <T>(file: string) => T
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
import { PdfFile } from "../wrappers/PdfFile.js";
|
||||
import { Sorts } from "./common/pageIndexesSorting.js";
|
||||
import { getPages } from "./common/getPagesByIndex.js";
|
||||
import { parsePageIndexSpecification } from "./common/pageIndexesUtils.js";
|
||||
import { PdfFile } from "../wrappers/PdfFile";
|
||||
import { Sorts } from "./common/pageIndexesSorting";
|
||||
import { getPages } from "./common/getPagesByIndex";
|
||||
import { parsePageIndexSpecification } from "./common/pageIndexesUtils";
|
||||
|
||||
export interface ArrangePagesParamsType {
|
||||
file: PdfFile;
|
||||
|
||||
@@ -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"];
|
||||
}
|
||||
38
shared-operations/src/workflow/listOperatorsInDir.ts
Normal file
38
shared-operations/src/workflow/listOperatorsInDir.ts
Normal 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],
|
||||
}
|
||||
}
|
||||
24
shared-operations/src/workflow/operatorAccessor.ts
Normal file
24
shared-operations/src/workflow/operatorAccessor.ts
Normal 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);
|
||||
}
|
||||
@@ -3,10 +3,10 @@ import { Action, WaitAction } from "../../declarations/Action";
|
||||
import { PdfFile } from "../wrappers/PdfFile";
|
||||
import { Progress } from "../functions";
|
||||
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[]> {
|
||||
const validationResult = validateOperations(operations);
|
||||
const validationResult = await validateOperations(operations);
|
||||
if(!validationResult.valid) {
|
||||
return Promise.reject({validationError: validationResult.reason});
|
||||
}
|
||||
@@ -47,7 +47,7 @@ export async function traverseOperations(operations: Action[], input: PdfFile[],
|
||||
}
|
||||
break;
|
||||
default:
|
||||
const operator = getOperatorByName(action.type);
|
||||
const operator = await getOperatorByName(action.type);
|
||||
if(operator) {
|
||||
const operation = new operator(action);
|
||||
input = await operation.run(input, progressCallback);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Operator } from "../functions";
|
||||
import { Action } from "../../declarations/Action";
|
||||
import { getOperatorByName } from "./getOperatorByName";
|
||||
import { getOperatorByName } from "./operatorAccessor";
|
||||
|
||||
/** 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[] = [];
|
||||
|
||||
for (const action of actions) {
|
||||
@@ -15,7 +15,7 @@ export function validateOperations(actions: Action[]): { valid: boolean, reason?
|
||||
continue;
|
||||
}
|
||||
|
||||
const operator = getOperatorByName(action.type);
|
||||
const operator = await getOperatorByName(action.type);
|
||||
if(!operator) {
|
||||
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 || []) {
|
||||
const receivingOperator = getOperatorByName(afterDoneChild.type);
|
||||
const receivingOperator = await getOperatorByName(afterDoneChild.type);
|
||||
if (receivingOperator === undefined) {
|
||||
return { valid: false, reason: `action.type ${afterDoneChild.type} does not exist.` };
|
||||
} 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." };
|
||||
}
|
||||
else {
|
||||
const receivingOperator = getOperatorByName(childAction.type);
|
||||
const receivingOperator = await getOperatorByName(childAction.type);
|
||||
if (receivingOperator === undefined) {
|
||||
return { valid: false, reason: `action.type ${childAction.type} does not exist.` };
|
||||
} 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) {
|
||||
return validationResult;
|
||||
|
||||
Reference in New Issue
Block a user