mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-23 07:55:07 +00:00
created OperatorConstraints and impelemented it in impose
This commit is contained in:
parent
a7545b017f
commit
7df48d43d6
@ -1,8 +1,9 @@
|
|||||||
|
|
||||||
import Operations from '../../utils/pdf-operations';
|
import Operations from '../../utils/pdf-operations';
|
||||||
import { respondWithPdfFile, respondWithPdfFiles, response_mustHaveExactlyOneFile } from '../../utils/endpoint-utils';
|
import { respondWithPdfFile, respondWithPdfFiles, response_mustHaveExactlyOneFile } from '../../utils/endpoint-utils';
|
||||||
import { PdfFile, PdfFileSchema } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile'
|
import { PdfFile, /*PdfFileSchema*/ } from '@stirling-pdf/shared-operations/src/wrappers/PdfFile'
|
||||||
import { ScalePageSchema } from '@stirling-pdf/shared-operations/src/functions/scalePage'
|
//import { ScalePageSchema } from '@stirling-pdf/shared-operations/src/functions/scalePage'
|
||||||
|
import { OperatorType } from '@stirling-pdf/shared-operations/src';
|
||||||
|
|
||||||
import express, { Request, Response, RequestHandler } from 'express';
|
import express, { Request, Response, RequestHandler } from 'express';
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@ -13,8 +14,7 @@ import Joi from 'joi';
|
|||||||
function registerEndpoint(endpoint: string,
|
function registerEndpoint(endpoint: string,
|
||||||
nameToAppend: string,
|
nameToAppend: string,
|
||||||
fileHandler: RequestHandler,
|
fileHandler: RequestHandler,
|
||||||
operationFunction: (params: any) => Promise<PdfFile|PdfFile[]>,
|
operator: OperatorType
|
||||||
joiSchema: Joi.ObjectSchema<any>
|
|
||||||
): void {
|
): void {
|
||||||
router.post(endpoint, fileHandler, async function(req: Request, res: Response) {
|
router.post(endpoint, fileHandler, async function(req: Request, res: Response) {
|
||||||
const body = req.body;
|
const body = req.body;
|
||||||
@ -31,13 +31,13 @@ function registerEndpoint(endpoint: string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(req.body)
|
console.log(req.body)
|
||||||
const { error, value } = joiSchema.validate(req.body);
|
const { error, value } = operator.spec.toJoiSchema().validate(req.body);
|
||||||
if (error) {
|
if (error) {
|
||||||
res.status(400).send(error.details);
|
res.status(400).send(error.details);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const processed = await operationFunction(value)
|
const processed = await operator.exec(value)
|
||||||
|
|
||||||
if (body.files && Array.isArray(processed)) { // MIMO
|
if (body.files && Array.isArray(processed)) { // MIMO
|
||||||
respondWithPdfFiles(res, processed, nameToAppend);
|
respondWithPdfFiles(res, processed, nameToAppend);
|
||||||
@ -55,7 +55,7 @@ function registerEndpoint(endpoint: string,
|
|||||||
/////////////////////
|
/////////////////////
|
||||||
// Page Operations //
|
// Page Operations //
|
||||||
/////////////////////
|
/////////////////////
|
||||||
registerEndpoint("/merge-pdfs", "", upload.any(), Operations.mergePDFs, Joi.object({
|
/*registerEndpoint("/merge-pdfs", "", upload.any(), Operations.mergePDFs, Joi.object({
|
||||||
files: Joi.array().items(PdfFileSchema).required(),
|
files: Joi.array().items(PdfFileSchema).required(),
|
||||||
}).required());
|
}).required());
|
||||||
|
|
||||||
@ -78,13 +78,9 @@ registerEndpoint("/remove-pages", "", upload.single("file"), Operations.removePa
|
|||||||
file: PdfFileSchema.required(),
|
file: PdfFileSchema.required(),
|
||||||
pageSelector: Joi.string().required(),
|
pageSelector: Joi.string().required(),
|
||||||
}).required());
|
}).required());
|
||||||
|
*/
|
||||||
registerEndpoint("/impose", "", upload.single("file"), Operations.impose, Joi.object({
|
registerEndpoint("/impose", "", upload.single("file"), Operations.Impose);
|
||||||
file: PdfFileSchema.required(),
|
/*
|
||||||
nup: Joi.number().valid(2, 3, 4, 8, 9, 12, 16).required(),
|
|
||||||
format: Joi.string().required(),
|
|
||||||
}).required());
|
|
||||||
|
|
||||||
registerEndpoint("/scale-pages", "", upload.single("file"), Operations.scalePage, ScalePageSchema.required());
|
registerEndpoint("/scale-pages", "", upload.single("file"), Operations.scalePage, ScalePageSchema.required());
|
||||||
|
|
||||||
//Auto Split Pages
|
//Auto Split Pages
|
||||||
@ -159,5 +155,5 @@ registerEndpoint("/update-metadata", "", upload.single("file"), Operations.updat
|
|||||||
//Auto Rename
|
//Auto Rename
|
||||||
//Get info
|
//Get info
|
||||||
//Show JS
|
//Show JS
|
||||||
|
*/
|
||||||
export default router;
|
export default router;
|
@ -1,17 +1,16 @@
|
|||||||
|
|
||||||
import SharedOperations, { OperationsType } from "@stirling-pdf/shared-operations/src"
|
import SharedOperations, { OperatorsType, OperatorParametersType } from "@stirling-pdf/shared-operations/src"
|
||||||
import { ImposeParamsType } from '@stirling-pdf/shared-operations/src/functions/impose'
|
|
||||||
import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"
|
import { PdfFile } from "@stirling-pdf/shared-operations/src/wrappers/PdfFile"
|
||||||
|
|
||||||
// Import injected libraries here!
|
// Import injected libraries here!
|
||||||
import * as pdfcpuWrapper from "@stirling-pdf/shared-operations/src/wasm/pdfcpu/pdfcpu-wrapper-node.js";
|
import * as pdfcpuWrapper from "@stirling-pdf/shared-operations/src/wasm/pdfcpu/pdfcpu-wrapper-node.js";
|
||||||
|
|
||||||
async function impose(params: ImposeParamsType): Promise<PdfFile> {
|
async function impose(params: OperatorParametersType["Impose"]): Promise<PdfFile> {
|
||||||
return SharedOperations.impose(params, pdfcpuWrapper);
|
return SharedOperations.Impose.exec(params, pdfcpuWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
const toExport: OperationsType = {
|
const toExport: OperatorsType = {
|
||||||
...SharedOperations,
|
...SharedOperations,
|
||||||
impose,
|
Impose: {exec: impose, spec: SharedOperations.Impose.spec},
|
||||||
}
|
}
|
||||||
export default toExport;
|
export default toExport;
|
||||||
|
85
shared-operations/src/dynamic-ui/OperatorConstraints.ts
Normal file
85
shared-operations/src/dynamic-ui/OperatorConstraints.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
import Joi from 'joi';
|
||||||
|
import { PdfFileSchema } from '../wrappers/PdfFile';
|
||||||
|
|
||||||
|
export class RecordConstraint {
|
||||||
|
|
||||||
|
record: Record<string, FieldConstraint>;
|
||||||
|
|
||||||
|
constructor(record: Record<string, FieldConstraint>) {
|
||||||
|
this.record = record;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJoiSchema() {
|
||||||
|
const newSchemaObj: any = {};
|
||||||
|
Object.keys(this.record).forEach(key => {
|
||||||
|
newSchemaObj[key] = this.record[key].toJoiSchema();
|
||||||
|
});
|
||||||
|
return Joi.object(newSchemaObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export class FieldConstraint {
|
||||||
|
|
||||||
|
displayNameKey: string;
|
||||||
|
type: "file.pdf" | "files.pdf" | "string" | "number" | number[] | string[] | RecordConstraint;
|
||||||
|
required: boolean;
|
||||||
|
hintKey?: string;
|
||||||
|
customSchema?: Joi.Schema;
|
||||||
|
|
||||||
|
constructor(displayNameKey: string,
|
||||||
|
type: "file.pdf" | "files.pdf" | "string" | "number" | number[] | string[] | RecordConstraint,
|
||||||
|
required: boolean,
|
||||||
|
hintKey?: string,
|
||||||
|
customSchema?: Joi.Schema) {
|
||||||
|
this.displayNameKey = displayNameKey;
|
||||||
|
this.type = type;
|
||||||
|
this.required = required;
|
||||||
|
this.hintKey = hintKey;
|
||||||
|
this.customSchema = customSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJoiSchema(): Joi.Schema {
|
||||||
|
if (this.customSchema) return this.customSchema;
|
||||||
|
|
||||||
|
var schema: Joi.Schema;
|
||||||
|
if (Array.isArray(this.type)) {
|
||||||
|
if (this.type.every(e => typeof e == 'string')) {
|
||||||
|
schema = Joi.string().valid(...this.type);
|
||||||
|
} else if (this.type.every(e => typeof e == 'number')) {
|
||||||
|
schema = Joi.number().valid(...this.type);
|
||||||
|
} else {
|
||||||
|
schema = Joi.any().valid(this.type);
|
||||||
|
}
|
||||||
|
} else if (typeof this.type == 'string') {
|
||||||
|
switch (this.type) {
|
||||||
|
case "file.pdf":
|
||||||
|
schema = PdfFileSchema;
|
||||||
|
break;
|
||||||
|
case "files.pdf":
|
||||||
|
schema = Joi.array().items(PdfFileSchema);
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
schema = Joi.string();
|
||||||
|
break;
|
||||||
|
case "number":
|
||||||
|
schema = Joi.number();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`UiConf type '${this.type}' not supported`)
|
||||||
|
}
|
||||||
|
} else if (this.type instanceof FieldConstraint) {
|
||||||
|
schema = this.type.toJoiSchema()
|
||||||
|
} else {
|
||||||
|
throw new Error(`UiConf type '${this.type}' not supported`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.required) {
|
||||||
|
schema = schema.required();
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,13 +1,20 @@
|
|||||||
import { PdfFile, RepresentationType } from "../wrappers/PdfFile";
|
import { PdfFile, RepresentationType } from "../wrappers/PdfFile";
|
||||||
|
import { FieldConstraint, RecordConstraint } from '../dynamic-ui/OperatorConstraints'
|
||||||
|
|
||||||
export type ImposeParamsType = {
|
export type ImposeParamsType = {
|
||||||
file: PdfFile;
|
file: PdfFile;
|
||||||
/** Accepted values are 2, 3, 4, 8, 9, 12, 16 - see: {@link https://pdfcpu.io/generate/nup.html#n-up-value} */
|
/** Accepted values are 2, 3, 4, 8, 9, 12, 16 - see: {@link https://pdfcpu.io/generate/nup.html#n-up-value} */
|
||||||
nup: number;
|
nup: 2 | 3 | 4 | 8 | 9 | 12 | 16;
|
||||||
/** A0-A10, other formats available - see: {@link https://pdfcpu.io/paper.html} */
|
/** A0-A10, other formats available - see: {@link https://pdfcpu.io/paper.html} */
|
||||||
format: string;
|
format: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ImposeParamConstraints = new RecordConstraint({
|
||||||
|
file: new FieldConstraint("display", "file.pdf", true, "hint"),
|
||||||
|
nup: new FieldConstraint("display", [2, 3, 4, 8, 9, 12, 16], true, "hint"),
|
||||||
|
format: new FieldConstraint("display", "string", true, "hint"),
|
||||||
|
})
|
||||||
|
|
||||||
/** PDF-Imposition, PDF-N-Up: Put multiple pages of the input document into a single page of the output document. - see: {@link https://en.wikipedia.org/wiki/N-up} */
|
/** PDF-Imposition, PDF-N-Up: Put multiple pages of the input document into a single page of the output document. - see: {@link https://en.wikipedia.org/wiki/N-up} */
|
||||||
export async function impose(params: ImposeParamsType, pdfcpuWrapper: any): Promise<PdfFile> {
|
export async function impose(params: ImposeParamsType, pdfcpuWrapper: any): Promise<PdfFile> {
|
||||||
// https://pdfcpu.io/generate/nup.html
|
// https://pdfcpu.io/generate/nup.html
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
import { arrangePages, ArrangePagesParamsType } from './functions/arrangePages'
|
import { arrangePages, ArrangePagesParamsType } from './functions/arrangePages'
|
||||||
import { extractPages, ExtractPagesParamsType } from "./functions/extractPages";
|
import { extractPages, ExtractPagesParamsType } from "./functions/extractPages";
|
||||||
import { impose, ImposeParamsType } from "./functions/impose";
|
import { impose, ImposeParamConstraints, ImposeParamsType } from "./functions/impose";
|
||||||
import { mergePDFs, MergeParamsType } from './functions/mergePDFs';
|
import { mergePDFs, MergeParamsType } from './functions/mergePDFs';
|
||||||
import { removeBlankPages, RemoveBlankPagesParamsType } from "./functions/removeBlankPages";
|
import { removeBlankPages, RemoveBlankPagesParamsType } from "./functions/removeBlankPages";
|
||||||
import { removePages, RemovePagesParamsType } from "./functions/removePages";
|
import { removePages, RemovePagesParamsType } from "./functions/removePages";
|
||||||
@ -11,17 +11,18 @@ import { scalePage, ScalePageParamsType } from './functions/scalePage';
|
|||||||
import { splitPagesByPreset, SplitPageByPresetParamsType } from './functions/splitPagesByPreset';
|
import { splitPagesByPreset, SplitPageByPresetParamsType } from './functions/splitPagesByPreset';
|
||||||
import { splitPdfByIndex, SplitPdfByIndexParamsType } from './functions/splitPdfByIndex';
|
import { splitPdfByIndex, SplitPdfByIndexParamsType } from './functions/splitPdfByIndex';
|
||||||
import { updateMetadata, UpdateMetadataParams } from "./functions/updateMetadata";
|
import { updateMetadata, UpdateMetadataParams } from "./functions/updateMetadata";
|
||||||
|
import { FieldConstraint, RecordConstraint } from '@stirling-pdf/shared-operations/src/dynamic-ui/OperatorConstraints'
|
||||||
import { PdfFile } from "./wrappers/PdfFile";
|
import { PdfFile } from "./wrappers/PdfFile";
|
||||||
|
|
||||||
import { Override } from '../declarations/TypeScriptUtils'
|
import { Override, ValuesType } from '../declarations/TypeScriptUtils'
|
||||||
|
|
||||||
// Import injected libraries here!
|
// Import injected libraries here!
|
||||||
|
|
||||||
const toExport = {
|
const toExport = {
|
||||||
arrangePages,
|
/*arrangePages,
|
||||||
extractPages,
|
extractPages,*/
|
||||||
impose,
|
Impose: {exec: impose, spec: ImposeParamConstraints},
|
||||||
mergePDFs,
|
/*mergePDFs,
|
||||||
removeBlankPages,
|
removeBlankPages,
|
||||||
removePages,
|
removePages,
|
||||||
rotatePages,
|
rotatePages,
|
||||||
@ -29,15 +30,25 @@ const toExport = {
|
|||||||
scalePage,
|
scalePage,
|
||||||
splitPagesByPreset,
|
splitPagesByPreset,
|
||||||
splitPdfByIndex,
|
splitPdfByIndex,
|
||||||
updateMetadata,
|
updateMetadata,*/
|
||||||
}
|
}
|
||||||
export default toExport;
|
export default toExport;
|
||||||
|
|
||||||
export type OperationsParametersBaseType = {
|
type OperatorsBaseType = typeof toExport;
|
||||||
arrangePages: ArrangePagesParamsType
|
export type OperatorsType = Override<OperatorsBaseType, {
|
||||||
extractPages: ExtractPagesParamsType;
|
Impose: {
|
||||||
impose: ImposeParamsType;
|
exec: (params: ImposeParamsType) => Promise<PdfFile>;
|
||||||
mergePDFs: MergeParamsType;
|
spec: RecordConstraint;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type OperatorType = ValuesType<OperatorsType>;
|
||||||
|
|
||||||
|
export type OperatorParametersType = {
|
||||||
|
/*arrangePages: ArrangePagesParamsType
|
||||||
|
extractPages: ExtractPagesParamsType;*/
|
||||||
|
Impose: ImposeParamsType;
|
||||||
|
/*mergePDFs: MergeParamsType;
|
||||||
removeBlankPages: RemoveBlankPagesParamsType;
|
removeBlankPages: RemoveBlankPagesParamsType;
|
||||||
removePages: RemovePagesParamsType;
|
removePages: RemovePagesParamsType;
|
||||||
rotatePages: RotateParamsType;
|
rotatePages: RotateParamsType;
|
||||||
@ -45,16 +56,5 @@ export type OperationsParametersBaseType = {
|
|||||||
scalePage: ScalePageParamsType;
|
scalePage: ScalePageParamsType;
|
||||||
splitPagesByPreset: SplitPageByPresetParamsType;
|
splitPagesByPreset: SplitPageByPresetParamsType;
|
||||||
splitPdfByIndex: SplitPdfByIndexParamsType;
|
splitPdfByIndex: SplitPdfByIndexParamsType;
|
||||||
updateMetadata: UpdateMetadataParams;
|
updateMetadata: UpdateMetadataParams;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OperationsBaseType = typeof toExport;
|
|
||||||
|
|
||||||
// Overide fields in the type of toExport, with the given fields and types. This seems to magically work!
|
|
||||||
export type OperationsType = Override<OperationsBaseType, {
|
|
||||||
impose: (params: ImposeParamsType) => Promise<PdfFile>;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
export type OperationsParametersType = Override<OperationsParametersBaseType, {
|
|
||||||
impose: ImposeParamsType;
|
|
||||||
}>;
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { organizeWaitOperations } from "./organizeWaitOperations";
|
import { organizeWaitOperations } from "./organizeWaitOperations";
|
||||||
import { Action, WaitAction } from "../../declarations/Action";
|
import { Action, WaitAction } from "../../declarations/Action";
|
||||||
import { OperationsType } from "../../src/index";
|
import { OperatorsType } from "../../src/index";
|
||||||
import { PdfFile } from "../wrappers/PdfFile";
|
import { PdfFile } from "../wrappers/PdfFile";
|
||||||
|
|
||||||
export async function * traverseOperations(operations: Action[], input: PdfFile[] | PdfFile, Operations: OperationsType): AsyncGenerator<string, PdfFile[], void> {
|
export async function * traverseOperations(operations: Action[], input: PdfFile[] | PdfFile, Operators: OperatorsType): AsyncGenerator<string, PdfFile[], void> {
|
||||||
const waitOperations = organizeWaitOperations(operations);
|
const waitOperations = organizeWaitOperations(operations);
|
||||||
let results: PdfFile[] = [];
|
let results: PdfFile[] = [];
|
||||||
yield* nextOperation(operations, input);
|
yield* nextOperation(operations, input);
|
||||||
@ -52,19 +52,19 @@ export async function * traverseOperations(operations: Action[], input: PdfFile[
|
|||||||
yield* nextOperation(waitOperation.doneOperation.actions, waitOperation.input);
|
yield* nextOperation(waitOperation.doneOperation.actions, waitOperation.input);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "extract":
|
/*case "extract":
|
||||||
yield* nToN(input, action, async (input) => {
|
yield* nToN(input, action, async (input) => {
|
||||||
const newPdf = await Operations.extractPages({file: input, pageIndexes: action.values["pageIndexes"]});
|
const newPdf = await Operations.extractPages({file: input, pageIndexes: action.values["pageIndexes"]});
|
||||||
return newPdf;
|
return newPdf;
|
||||||
});
|
});
|
||||||
break;
|
break;*/
|
||||||
case "impose":
|
case "impose":
|
||||||
yield* nToN(input, action, async (input) => {
|
yield* nToN(input, action, async (input) => {
|
||||||
const newPdf = await Operations.impose({file: input, nup: action.values["nup"], format: action.values["format"]});
|
const newPdf = await Operators.Impose.exec({file: input, nup: action.values["nup"], format: action.values["format"]});
|
||||||
return newPdf;
|
return newPdf;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "merge":
|
/*case "merge":
|
||||||
yield* nToOne(input, action, async (inputs) => {
|
yield* nToOne(input, action, async (inputs) => {
|
||||||
const newPdf = await Operations.mergePDFs({files: inputs});
|
const newPdf = await Operations.mergePDFs({files: inputs});
|
||||||
return newPdf;
|
return newPdf;
|
||||||
@ -112,7 +112,7 @@ export async function * traverseOperations(operations: Action[], input: PdfFile[
|
|||||||
const newPdf = await Operations.updateMetadata({file: input, ...action.values["metadata"]});
|
const newPdf = await Operations.updateMetadata({file: input, ...action.values["metadata"]});
|
||||||
return newPdf;
|
return newPdf;
|
||||||
});
|
});
|
||||||
break;
|
break;*/
|
||||||
default:
|
default:
|
||||||
throw new Error(`${action.type} not implemented yet.`);
|
throw new Error(`${action.type} not implemented yet.`);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import * as PDFJS from 'pdfjs-dist';
|
import * as PDFJS from 'pdfjs-dist';
|
||||||
import type { PDFDocumentProxy as PDFJSDocument } from 'pdfjs-dist/types/src/display/api';
|
import type { PDFDocumentProxy as PDFJSDocument } from 'pdfjs-dist/types/src/display/api';
|
||||||
import { PDFDocument as PDFLibDocument } from 'pdf-lib';
|
import { PDFDocument as PDFLibDocument } from 'pdf-lib';
|
||||||
|
|
||||||
import Joi from 'joi';
|
import Joi from 'joi';
|
||||||
|
|
||||||
export enum RepresentationType {
|
export enum RepresentationType {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user