pdfdancer-client-typescript 1.0.4 → 1.0.6
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 +5 -5
- package/dist/__tests__/e2e/test-helpers.d.ts +2 -1
- package/dist/__tests__/e2e/test-helpers.d.ts.map +1 -1
- package/dist/__tests__/e2e/test-helpers.js +7 -3
- package/dist/__tests__/e2e/test-helpers.js.map +1 -1
- package/dist/client-v1.js +1 -1
- package/dist/client-v1.js.map +1 -1
- package/dist/client-v2.d.ts +129 -0
- package/dist/client-v2.d.ts.map +1 -0
- package/dist/client-v2.js +696 -0
- package/dist/client-v2.js.map +1 -0
- package/dist/image-builder.d.ts +13 -0
- package/dist/image-builder.d.ts.map +1 -0
- package/dist/image-builder.js +44 -0
- package/dist/image-builder.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +5 -10
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +3 -13
- package/dist/models.js.map +1 -1
- package/dist/paragraph-builder.d.ts +19 -10
- package/dist/paragraph-builder.d.ts.map +1 -1
- package/dist/paragraph-builder.js +65 -26
- package/dist/paragraph-builder.js.map +1 -1
- package/dist/pdfdancer_v1.d.ts +202 -0
- package/dist/pdfdancer_v1.d.ts.map +1 -0
- package/dist/pdfdancer_v1.js +702 -0
- package/dist/pdfdancer_v1.js.map +1 -0
- package/dist/types.d.ts +56 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +92 -0
- package/dist/types.js.map +1 -0
- package/package.json +1 -1
- package/scripts/release.js +1 -1
- package/src/__tests__/client-v1.test.ts +46 -87
- package/src/__tests__/e2e/acroform.test.ts +60 -57
- package/src/__tests__/e2e/form_x_object.test.ts +17 -16
- package/src/__tests__/e2e/image.test.ts +53 -56
- package/src/__tests__/e2e/line.test.ts +47 -48
- package/src/__tests__/e2e/page.test.ts +37 -36
- package/src/__tests__/e2e/paragraph.test.ts +107 -101
- package/src/__tests__/e2e/path.test.ts +67 -64
- package/src/__tests__/e2e/test-helpers.ts +71 -67
- package/src/__tests__/e2e/token_from_env.test.ts +35 -0
- package/src/image-builder.ts +52 -0
- package/src/index.ts +1 -1
- package/src/models.ts +5 -21
- package/src/paragraph-builder.ts +217 -162
- package/src/{client-v1.ts → pdfdancer_v1.ts} +248 -53
- package/src/types.ts +133 -0
- package/example.ts +0 -99
|
@@ -31,7 +31,153 @@ import {
|
|
|
31
31
|
ShapeType
|
|
32
32
|
} from './models';
|
|
33
33
|
import {ParagraphBuilder} from './paragraph-builder';
|
|
34
|
+
import {FormFieldObject, FormXObject, ImageObject, ParagraphObject, PathObject, TextLineObject} from "./types";
|
|
35
|
+
import {ImageBuilder} from "./image-builder";
|
|
36
|
+
import fs from "fs";
|
|
34
37
|
|
|
38
|
+
// 👇 Internal view of PDFDancer methods, not exported
|
|
39
|
+
interface PDFDancerInternals {
|
|
40
|
+
|
|
41
|
+
toImageObjects(objectRefs: ObjectRef[]): ImageObject[];
|
|
42
|
+
|
|
43
|
+
toPathObjects(objectRefs: ObjectRef[]): PathObject[];
|
|
44
|
+
|
|
45
|
+
toFormXObjects(objectRefs: ObjectRef[]): FormXObject[];
|
|
46
|
+
|
|
47
|
+
deletePage(objectRef: ObjectRef): Promise<boolean>;
|
|
48
|
+
|
|
49
|
+
toTextLineObjects(objectRefs: ObjectRef[]): TextLineObject[];
|
|
50
|
+
|
|
51
|
+
toFormFields(formFieldRefs: FormFieldRef[]): FormFieldObject[];
|
|
52
|
+
|
|
53
|
+
toParagraphObjects(objectRefs: ObjectRef[]): ParagraphObject[];
|
|
54
|
+
|
|
55
|
+
findFormFields(position?: Position): Promise<FormFieldRef[]>;
|
|
56
|
+
|
|
57
|
+
findPaths(position?: Position): Promise<ObjectRef[]>;
|
|
58
|
+
|
|
59
|
+
findFormXObjects(position?: Position): Promise<ObjectRef[]>;
|
|
60
|
+
|
|
61
|
+
findParagraphs(position?: Position): Promise<ObjectRef[]>;
|
|
62
|
+
|
|
63
|
+
findTextLines(pos?: Position): Promise<ObjectRef[]>;
|
|
64
|
+
|
|
65
|
+
_findImages(position?: Position): Promise<ObjectRef[]>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
class PageClient {
|
|
69
|
+
|
|
70
|
+
private _pageIndex: number;
|
|
71
|
+
private _client: PDFDancer;
|
|
72
|
+
type: ObjectType = ObjectType.PAGE;
|
|
73
|
+
position: Position;
|
|
74
|
+
internalId: string;
|
|
75
|
+
private _internals: PDFDancerInternals;
|
|
76
|
+
|
|
77
|
+
constructor(client: PDFDancer, pageIndex: number) {
|
|
78
|
+
this._client = client;
|
|
79
|
+
this._pageIndex = pageIndex;
|
|
80
|
+
this.internalId = `PAGE-${this._pageIndex}`;
|
|
81
|
+
this.position = Position.atPage(this._pageIndex);
|
|
82
|
+
// Cast to the internal interface to get access
|
|
83
|
+
this._internals = this._client as unknown as PDFDancerInternals;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async selectPathsAt(x: number, y: number) {
|
|
87
|
+
return this._internals.toPathObjects(await this._internals.findPaths(Position.atPageCoordinates(this._pageIndex, x, y)));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async selectImages() {
|
|
91
|
+
return this._internals.toImageObjects(await this._internals._findImages(Position.atPage(this._pageIndex)));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async selectImagesAt(x: number, y: number) {
|
|
95
|
+
return this._internals.toImageObjects(await this._internals._findImages(Position.atPageCoordinates(this._pageIndex, x, y)));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async delete() {
|
|
99
|
+
return this._internals.deletePage(this.ref());
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private ref() {
|
|
103
|
+
return new ObjectRef(this.internalId, this.position, this.type);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// noinspection JSUnusedGlobalSymbols
|
|
107
|
+
async selectForms() {
|
|
108
|
+
return this._internals.toFormXObjects(await this._internals.findFormXObjects(Position.atPage(this._pageIndex)));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async selectFormsAt(x: number, y: number) {
|
|
112
|
+
return this._internals.toFormXObjects(await this._internals.findFormXObjects(Position.atPageCoordinates(this._pageIndex, x, y)));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async selectFormFields() {
|
|
116
|
+
return this._internals.toFormFields(await this._internals.findFormFields(Position.atPage(this._pageIndex)));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async selectFormFieldsAt(x: number, y: number) {
|
|
120
|
+
return this._internals.toFormFields(await this._internals.findFormFields(Position.atPageCoordinates(this._pageIndex, x, y)));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// noinspection JSUnusedGlobalSymbols
|
|
124
|
+
async selectFormFieldsByName(fieldName: string) {
|
|
125
|
+
let pos = Position.atPage(this._pageIndex);
|
|
126
|
+
pos.name = fieldName;
|
|
127
|
+
return this._internals.toFormFields(await this._internals.findFormFields(pos));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async selectParagraphs() {
|
|
131
|
+
return this._internals.toParagraphObjects(await this._internals.findParagraphs(Position.atPage(this._pageIndex)));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async selectParagraphsStartingWith(text: string) {
|
|
135
|
+
let pos = Position.atPage(this._pageIndex);
|
|
136
|
+
pos.textStartsWith = text;
|
|
137
|
+
return this._internals.toParagraphObjects(await this._internals.findParagraphs(pos));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async selectParagraphsMatching(pattern: string) {
|
|
141
|
+
let pos = Position.atPage(this._pageIndex);
|
|
142
|
+
pos.textPattern = pattern;
|
|
143
|
+
return this._internals.toParagraphObjects(await this._internals.findParagraphs(pos));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async selectParagraphsAt(x: number, y: number) {
|
|
147
|
+
return this._internals.toParagraphObjects(await this._internals.findParagraphs(Position.atPageCoordinates(this._pageIndex, x, y)));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async selectTextLinesStartingWith(text: string) {
|
|
151
|
+
let pos = Position.atPage(this._pageIndex);
|
|
152
|
+
pos.textStartsWith = text;
|
|
153
|
+
return this._internals.toTextLineObjects(await this._internals.findTextLines(pos));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Creates a new ParagraphBuilder for fluent paragraph construction.
|
|
158
|
+
*/
|
|
159
|
+
newParagraph(): ParagraphBuilder {
|
|
160
|
+
return new ParagraphBuilder(this._client, this.position.pageIndex);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async selectTextLines() {
|
|
164
|
+
return this._internals.toTextLineObjects(await this._internals.findTextLines(Position.atPage(this._pageIndex)));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// noinspection JSUnusedGlobalSymbols
|
|
168
|
+
async selectTextLinesMatching(pattern: string) {
|
|
169
|
+
let pos = Position.atPage(this._pageIndex);
|
|
170
|
+
pos.textPattern = pattern;
|
|
171
|
+
return this._internals.toTextLineObjects(await this._internals.findTextLines(pos));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// noinspection JSUnusedGlobalSymbols
|
|
175
|
+
async selectTextLinesAt(x: number, y: number) {
|
|
176
|
+
return this._internals.toTextLineObjects(await this._internals.findTextLines(Position.atPageCoordinates(this._pageIndex, x, y)));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// noinspection ExceptionCaughtLocallyJS,JSUnusedLocalSymbols
|
|
35
181
|
/**
|
|
36
182
|
* REST API client for interacting with the PDFDancer PDF manipulation service.
|
|
37
183
|
* This client provides a convenient TypeScript interface for performing PDF operations
|
|
@@ -39,7 +185,7 @@ import {ParagraphBuilder} from './paragraph-builder';
|
|
|
39
185
|
* Handles authentication, session lifecycle, and HTTP communication transparently.
|
|
40
186
|
*
|
|
41
187
|
*/
|
|
42
|
-
export class
|
|
188
|
+
export class PDFDancer {
|
|
43
189
|
private _token: string;
|
|
44
190
|
private _baseUrl: string;
|
|
45
191
|
private _readTimeout: number;
|
|
@@ -48,10 +194,10 @@ export class ClientV1 {
|
|
|
48
194
|
|
|
49
195
|
/**
|
|
50
196
|
* Creates a new client with PDF data.
|
|
51
|
-
* This constructor initializes the client, uploads the PDF data to
|
|
197
|
+
* This constructor initializes the client, uploads the PDF data to open
|
|
52
198
|
* a new session, and prepares the client for PDF manipulation operations.
|
|
53
199
|
*/
|
|
54
|
-
constructor(
|
|
200
|
+
private constructor(
|
|
55
201
|
token: string,
|
|
56
202
|
pdfData: Uint8Array | File | ArrayBuffer,
|
|
57
203
|
baseUrl: string = "http://localhost:8080",
|
|
@@ -78,8 +224,19 @@ export class ClientV1 {
|
|
|
78
224
|
return this;
|
|
79
225
|
}
|
|
80
226
|
|
|
81
|
-
static async
|
|
82
|
-
const
|
|
227
|
+
static async open(pdfData: Uint8Array, token?: string, baseUrl?: string, timeout?: number): Promise<PDFDancer> {
|
|
228
|
+
const resolvedToken = token ?? process.env.PDFDANCER_TOKEN;
|
|
229
|
+
const resolvedBaseUrl =
|
|
230
|
+
baseUrl ??
|
|
231
|
+
process.env.PDFDANCER_BASE_URL ??
|
|
232
|
+
"https://api.pdfdancer.com";
|
|
233
|
+
const resolvedTimeout = timeout ?? 30000;
|
|
234
|
+
|
|
235
|
+
if (!resolvedToken) {
|
|
236
|
+
throw new Error("Missing PDFDancer token (pass it explicitly or set PDFDANCER_TOKEN in environment).");
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const client = new PDFDancer(resolvedToken, pdfData, resolvedBaseUrl, resolvedTimeout);
|
|
83
240
|
return await client.init();
|
|
84
241
|
}
|
|
85
242
|
|
|
@@ -272,7 +429,7 @@ export class ClientV1 {
|
|
|
272
429
|
* This method provides flexible search capabilities across all PDF content,
|
|
273
430
|
* allowing filtering by object type and position constraints.
|
|
274
431
|
*/
|
|
275
|
-
async find(objectType?: ObjectType, position?: Position): Promise<ObjectRef[]> {
|
|
432
|
+
private async find(objectType?: ObjectType, position?: Position): Promise<ObjectRef[]> {
|
|
276
433
|
const requestData = new FindRequest(objectType, position).toDict();
|
|
277
434
|
const response = await this._makeRequest('POST', '/pdf/find', requestData);
|
|
278
435
|
|
|
@@ -283,35 +440,55 @@ export class ClientV1 {
|
|
|
283
440
|
/**
|
|
284
441
|
* Searches for paragraph objects at the specified position.
|
|
285
442
|
*/
|
|
286
|
-
async findParagraphs(position?: Position): Promise<ObjectRef[]> {
|
|
443
|
+
private async findParagraphs(position?: Position): Promise<ObjectRef[]> {
|
|
287
444
|
return this.find(ObjectType.PARAGRAPH, position);
|
|
288
445
|
}
|
|
289
446
|
|
|
290
447
|
/**
|
|
291
448
|
* Searches for image objects at the specified position.
|
|
292
449
|
*/
|
|
293
|
-
async
|
|
450
|
+
private async _findImages(position?: Position): Promise<ObjectRef[]> {
|
|
294
451
|
return this.find(ObjectType.IMAGE, position);
|
|
295
452
|
}
|
|
296
453
|
|
|
454
|
+
async selectImages(): Promise<ImageObject[]> {
|
|
455
|
+
return this.toImageObjects(await this.find(ObjectType.IMAGE));
|
|
456
|
+
}
|
|
457
|
+
|
|
297
458
|
/**
|
|
298
459
|
* Searches for form X objects at the specified position.
|
|
299
460
|
*/
|
|
300
|
-
async findFormXObjects(position?: Position): Promise<ObjectRef[]> {
|
|
461
|
+
private async findFormXObjects(position?: Position): Promise<ObjectRef[]> {
|
|
301
462
|
return this.find(ObjectType.FORM_X_OBJECT, position);
|
|
302
463
|
}
|
|
303
464
|
|
|
304
465
|
/**
|
|
305
466
|
* Searches for vector path objects at the specified position.
|
|
306
467
|
*/
|
|
307
|
-
async findPaths(position?: Position): Promise<ObjectRef[]> {
|
|
468
|
+
private async findPaths(position?: Position): Promise<ObjectRef[]> {
|
|
308
469
|
return this.find(ObjectType.PATH, position);
|
|
309
470
|
}
|
|
310
471
|
|
|
472
|
+
async selectPaths() {
|
|
473
|
+
return this.toPathObjects(await this.find(ObjectType.PATH));
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
async selectForms() {
|
|
477
|
+
return this.toFormXObjects(await this.find(ObjectType.FORM_X_OBJECT));
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
async selectFormFields() {
|
|
481
|
+
return this.toFormFields(await this.findFormFields());
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async selectFieldsByName(fieldName: string) {
|
|
485
|
+
return this.toFormFields(await this.findFormFields(Position.byName(fieldName)));
|
|
486
|
+
}
|
|
487
|
+
|
|
311
488
|
/**
|
|
312
489
|
* Searches for text line objects at the specified position.
|
|
313
490
|
*/
|
|
314
|
-
async findTextLines(position?: Position): Promise<ObjectRef[]> {
|
|
491
|
+
private async findTextLines(position?: Position): Promise<ObjectRef[]> {
|
|
315
492
|
return this.find(ObjectType.TEXT_LINE, position);
|
|
316
493
|
}
|
|
317
494
|
|
|
@@ -319,7 +496,7 @@ export class ClientV1 {
|
|
|
319
496
|
* Searches for form fields at the specified position.
|
|
320
497
|
* Returns FormFieldRef objects with name and value properties.
|
|
321
498
|
*/
|
|
322
|
-
async findFormFields(position?: Position): Promise<FormFieldRef[]> {
|
|
499
|
+
private async findFormFields(position?: Position): Promise<FormFieldRef[]> {
|
|
323
500
|
const requestData = new FindRequest(ObjectType.FORM_FIELD, position).toDict();
|
|
324
501
|
const response = await this._makeRequest('POST', '/pdf/find', requestData);
|
|
325
502
|
|
|
@@ -332,7 +509,7 @@ export class ClientV1 {
|
|
|
332
509
|
/**
|
|
333
510
|
* Retrieves references to all pages in the PDF document.
|
|
334
511
|
*/
|
|
335
|
-
async getPages(): Promise<ObjectRef[]> {
|
|
512
|
+
private async getPages(): Promise<ObjectRef[]> {
|
|
336
513
|
const response = await this._makeRequest('POST', '/pdf/page/find');
|
|
337
514
|
const pagesData = await response.json() as any[];
|
|
338
515
|
return pagesData.map((pageData: any) => this._parseObjectRef(pageData));
|
|
@@ -341,7 +518,7 @@ export class ClientV1 {
|
|
|
341
518
|
/**
|
|
342
519
|
* Retrieves a reference to a specific page by its page index.
|
|
343
520
|
*/
|
|
344
|
-
async
|
|
521
|
+
private async _getPage(pageIndex: number): Promise<ObjectRef | null> {
|
|
345
522
|
if (pageIndex < 0) {
|
|
346
523
|
throw new ValidationException(`Page index must be >= 0, got ${pageIndex}`);
|
|
347
524
|
}
|
|
@@ -360,7 +537,7 @@ export class ClientV1 {
|
|
|
360
537
|
/**
|
|
361
538
|
* Deletes a page from the PDF document.
|
|
362
539
|
*/
|
|
363
|
-
async deletePage(pageRef: ObjectRef): Promise<boolean> {
|
|
540
|
+
private async deletePage(pageRef: ObjectRef): Promise<boolean> {
|
|
364
541
|
if (!pageRef) {
|
|
365
542
|
throw new ValidationException("Page reference cannot be null");
|
|
366
543
|
}
|
|
@@ -375,7 +552,7 @@ export class ClientV1 {
|
|
|
375
552
|
/**
|
|
376
553
|
* Deletes the specified PDF object from the document.
|
|
377
554
|
*/
|
|
378
|
-
async delete(objectRef: ObjectRef): Promise<boolean> {
|
|
555
|
+
private async delete(objectRef: ObjectRef): Promise<boolean> {
|
|
379
556
|
if (!objectRef) {
|
|
380
557
|
throw new ValidationException("Object reference cannot be null");
|
|
381
558
|
}
|
|
@@ -388,7 +565,7 @@ export class ClientV1 {
|
|
|
388
565
|
/**
|
|
389
566
|
* Moves a PDF object to a new position within the document.
|
|
390
567
|
*/
|
|
391
|
-
async move(objectRef: ObjectRef, position: Position): Promise<boolean> {
|
|
568
|
+
private async move(objectRef: ObjectRef, position: Position): Promise<boolean> {
|
|
392
569
|
if (!objectRef) {
|
|
393
570
|
throw new ValidationException("Object reference cannot be null");
|
|
394
571
|
}
|
|
@@ -404,7 +581,7 @@ export class ClientV1 {
|
|
|
404
581
|
/**
|
|
405
582
|
* Changes the value of a form field.
|
|
406
583
|
*/
|
|
407
|
-
async changeFormField(formFieldRef: FormFieldRef, newValue: string): Promise<boolean> {
|
|
584
|
+
private async changeFormField(formFieldRef: FormFieldRef, newValue: string): Promise<boolean> {
|
|
408
585
|
if (!formFieldRef) {
|
|
409
586
|
throw new ValidationException("Form field reference cannot be null");
|
|
410
587
|
}
|
|
@@ -419,7 +596,7 @@ export class ClientV1 {
|
|
|
419
596
|
/**
|
|
420
597
|
* Adds an image to the PDF document.
|
|
421
598
|
*/
|
|
422
|
-
async addImage(image: Image, position?: Position): Promise<boolean> {
|
|
599
|
+
private async addImage(image: Image, position?: Position): Promise<boolean> {
|
|
423
600
|
if (!image) {
|
|
424
601
|
throw new ValidationException("Image cannot be null");
|
|
425
602
|
}
|
|
@@ -438,7 +615,7 @@ export class ClientV1 {
|
|
|
438
615
|
/**
|
|
439
616
|
* Adds a paragraph to the PDF document.
|
|
440
617
|
*/
|
|
441
|
-
async addParagraph(paragraph: Paragraph): Promise<boolean> {
|
|
618
|
+
private async addParagraph(paragraph: Paragraph): Promise<boolean> {
|
|
442
619
|
if (!paragraph) {
|
|
443
620
|
throw new ValidationException("Paragraph cannot be null");
|
|
444
621
|
}
|
|
@@ -469,7 +646,7 @@ export class ClientV1 {
|
|
|
469
646
|
/**
|
|
470
647
|
* Modifies a paragraph object or its text content.
|
|
471
648
|
*/
|
|
472
|
-
async modifyParagraph(objectRef: ObjectRef, newParagraph: Paragraph | string): Promise<boolean> {
|
|
649
|
+
private async modifyParagraph(objectRef: ObjectRef, newParagraph: Paragraph | string): Promise<boolean> {
|
|
473
650
|
if (!objectRef) {
|
|
474
651
|
throw new ValidationException("Object reference cannot be null");
|
|
475
652
|
}
|
|
@@ -493,7 +670,7 @@ export class ClientV1 {
|
|
|
493
670
|
/**
|
|
494
671
|
* Modifies a text line object.
|
|
495
672
|
*/
|
|
496
|
-
async modifyTextLine(objectRef: ObjectRef, newText: string): Promise<boolean> {
|
|
673
|
+
private async modifyTextLine(objectRef: ObjectRef, newText: string): Promise<boolean> {
|
|
497
674
|
if (!objectRef) {
|
|
498
675
|
throw new ValidationException("Object reference cannot be null");
|
|
499
676
|
}
|
|
@@ -594,42 +771,18 @@ export class ClientV1 {
|
|
|
594
771
|
return new Uint8Array(await response.arrayBuffer());
|
|
595
772
|
}
|
|
596
773
|
|
|
597
|
-
async getXmlFile(): Promise<String> {
|
|
598
|
-
const response = await fetch(`${this._baseUrl}/xml`, {
|
|
599
|
-
method: 'POST',
|
|
600
|
-
headers: {
|
|
601
|
-
'Authorization': `Bearer ${this._token}`,
|
|
602
|
-
'X-Session-Id': this._sessionId
|
|
603
|
-
},
|
|
604
|
-
signal: AbortSignal.timeout(30000)
|
|
605
|
-
});
|
|
606
|
-
return response.text()
|
|
607
|
-
}
|
|
608
|
-
|
|
609
774
|
/**
|
|
610
775
|
* Saves the current PDF to a file (browser environment).
|
|
611
776
|
* Downloads the PDF in the browser.
|
|
612
777
|
*/
|
|
613
|
-
async
|
|
778
|
+
async save(filename: string): Promise<void> {
|
|
614
779
|
if (!filename) {
|
|
615
780
|
throw new ValidationException("Filename cannot be null or empty");
|
|
616
781
|
}
|
|
617
782
|
|
|
618
783
|
try {
|
|
619
784
|
const pdfData = await this.getPdfFile();
|
|
620
|
-
|
|
621
|
-
// Create blob and download link
|
|
622
|
-
const blob = new Blob([pdfData.buffer as ArrayBuffer], {type: 'application/pdf'});
|
|
623
|
-
const url = URL.createObjectURL(blob);
|
|
624
|
-
|
|
625
|
-
const link = document.createElement('a');
|
|
626
|
-
link.href = url;
|
|
627
|
-
link.download = filename;
|
|
628
|
-
document.body.appendChild(link);
|
|
629
|
-
link.click();
|
|
630
|
-
document.body.removeChild(link);
|
|
631
|
-
|
|
632
|
-
URL.revokeObjectURL(url);
|
|
785
|
+
fs.writeFileSync(filename, pdfData);
|
|
633
786
|
} catch (error) {
|
|
634
787
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
635
788
|
throw new PdfDancerException(`Failed to save PDF file: ${errorMessage}`, error as Error);
|
|
@@ -699,10 +852,52 @@ export class ClientV1 {
|
|
|
699
852
|
|
|
700
853
|
// Builder Pattern Support
|
|
701
854
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
855
|
+
|
|
856
|
+
private toPathObjects(objectRefs: ObjectRef[]) {
|
|
857
|
+
return objectRefs.map(ref => PathObject.fromRef(this, ref));
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
private toFormXObjects(objectRefs: ObjectRef[]) {
|
|
861
|
+
return objectRefs.map(ref => FormXObject.fromRef(this, ref));
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
private toImageObjects(objectRefs: ObjectRef[]) {
|
|
865
|
+
return objectRefs.map(ref => ImageObject.fromRef(this, ref));
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
newImage() {
|
|
869
|
+
return new ImageBuilder(this);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
page(pageIndex: number) {
|
|
873
|
+
if (pageIndex < 0) {
|
|
874
|
+
throw new ValidationException(`Page index must be >= 0, got ${pageIndex}`);
|
|
875
|
+
}
|
|
876
|
+
return new PageClient(this, pageIndex);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
async pages() {
|
|
880
|
+
let pageRefs = await this.getPages();
|
|
881
|
+
return pageRefs.map((_, pageIndex) => new PageClient(this, pageIndex));
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
private toFormFields(objectRefs: FormFieldRef[]) {
|
|
885
|
+
return objectRefs.map(ref => FormFieldObject.fromRef(this, ref));
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
async selectParagraphs() {
|
|
889
|
+
return this.toParagraphObjects(await this.findParagraphs());
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
private toParagraphObjects(objectRefs: ObjectRef[]) {
|
|
893
|
+
return objectRefs.map(ref => ParagraphObject.fromRef(this, ref));
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
private toTextLineObjects(objectRefs: ObjectRef[]) {
|
|
897
|
+
return objectRefs.map(ref => TextLineObject.fromRef(this, ref));
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
async selectLines() {
|
|
901
|
+
return this.toTextLineObjects(await this.findTextLines());
|
|
707
902
|
}
|
|
708
903
|
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {FormFieldRef, ObjectRef, ObjectType, Position} from "./models";
|
|
2
|
+
import {PDFDancer} from "./pdfdancer_v1";
|
|
3
|
+
import {ParagraphBuilder} from "./paragraph-builder";
|
|
4
|
+
|
|
5
|
+
// 👇 Internal view of PDFDancer methods, not exported
|
|
6
|
+
interface PDFDancerInternals {
|
|
7
|
+
delete(objectRef: ObjectRef): Promise<boolean>;
|
|
8
|
+
|
|
9
|
+
move(objectRef: ObjectRef, position: Position): Promise<boolean>;
|
|
10
|
+
|
|
11
|
+
changeFormField(formFieldRef: FormFieldRef, value: string): Promise<boolean>;
|
|
12
|
+
|
|
13
|
+
modifyTextLine(objectRef: ObjectRef, newText: string): Promise<boolean>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class BaseObject<TRef extends ObjectRef = ObjectRef> {
|
|
17
|
+
|
|
18
|
+
_client: PDFDancer;
|
|
19
|
+
|
|
20
|
+
internalId: string;
|
|
21
|
+
type: ObjectType;
|
|
22
|
+
position: Position;
|
|
23
|
+
protected _internals: PDFDancerInternals;
|
|
24
|
+
|
|
25
|
+
constructor(client: PDFDancer, internalId: string, type: ObjectType, position: Position) {
|
|
26
|
+
this.internalId = internalId;
|
|
27
|
+
this.type = type;
|
|
28
|
+
this.position = position;
|
|
29
|
+
this._client = client;
|
|
30
|
+
this._internals = this._client as unknown as PDFDancerInternals;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async delete() {
|
|
34
|
+
return this._internals.delete(this.ref());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected ref(): TRef {
|
|
38
|
+
return new ObjectRef(this.internalId, this.position, this.type) as TRef;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async moveTo(x: number, y: number) {
|
|
42
|
+
return this._internals.move(this.ref(), Position.atPageCoordinates(this.position.pageIndex!, x, y));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class PathObject extends BaseObject {
|
|
47
|
+
|
|
48
|
+
static fromRef(_client: PDFDancer, objectRef: ObjectRef) {
|
|
49
|
+
return new PathObject(_client, objectRef.internalId, objectRef.type, objectRef.position);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class ImageObject extends BaseObject {
|
|
54
|
+
|
|
55
|
+
static fromRef(_client: PDFDancer, objectRef: ObjectRef) {
|
|
56
|
+
return new ImageObject(_client, objectRef.internalId, objectRef.type, objectRef.position);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export class FormXObject extends BaseObject {
|
|
61
|
+
|
|
62
|
+
static fromRef(_client: PDFDancer, objectRef: ObjectRef) {
|
|
63
|
+
return new FormXObject(_client, objectRef.internalId, objectRef.type, objectRef.position);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class FormFieldObject extends BaseObject<FormFieldRef> {
|
|
68
|
+
name: string;
|
|
69
|
+
value: string | null;
|
|
70
|
+
|
|
71
|
+
constructor(client: PDFDancer, internalId: string, type: ObjectType, position: Position, name: string, value: string | null) {
|
|
72
|
+
super(client, internalId, type, position);
|
|
73
|
+
this.name = name;
|
|
74
|
+
this.value = value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async fill(value: string) {
|
|
78
|
+
return await this._internals.changeFormField(this.ref(), value);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected ref() {
|
|
82
|
+
return new FormFieldRef(this.internalId, this.position, this.type, this.name, this.value);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static fromRef(_client: PDFDancer, objectRef: FormFieldRef) {
|
|
86
|
+
return new FormFieldObject(_client, objectRef.internalId, objectRef.type, objectRef.position, objectRef.name, objectRef.value);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export class ParagraphObject extends BaseObject {
|
|
91
|
+
|
|
92
|
+
static fromRef(_client: PDFDancer, objectRef: ObjectRef) {
|
|
93
|
+
return new ParagraphObject(_client, objectRef.internalId, objectRef.type, objectRef.position);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
edit() {
|
|
97
|
+
return new ParagraphBuilder(this._client, this.ref());
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export class TextLineObject extends BaseObject {
|
|
102
|
+
static fromRef(_client: PDFDancer, objectRef: ObjectRef) {
|
|
103
|
+
return new TextLineObject(_client, objectRef.internalId, objectRef.type, objectRef.position);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
edit() {
|
|
107
|
+
return new TextLineBuilder(this._client, this.ref());
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class TextLineBuilder {
|
|
113
|
+
|
|
114
|
+
private _text: string | undefined;
|
|
115
|
+
private _objectRef: ObjectRef;
|
|
116
|
+
private _client: PDFDancer
|
|
117
|
+
private _internals: PDFDancerInternals;
|
|
118
|
+
|
|
119
|
+
constructor(client: PDFDancer, objectRef: ObjectRef) {
|
|
120
|
+
this._objectRef = objectRef;
|
|
121
|
+
this._client = client;
|
|
122
|
+
this._internals = this._client as unknown as PDFDancerInternals;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
text(newText: string) {
|
|
126
|
+
this._text = newText;
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async apply() {
|
|
131
|
+
return await this._internals.modifyTextLine(this._objectRef, this._text!);
|
|
132
|
+
}
|
|
133
|
+
}
|
package/example.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Example usage of the PDFDancer TypeScript client
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
ClientV1,
|
|
7
|
-
Position,
|
|
8
|
-
Color,
|
|
9
|
-
Font,
|
|
10
|
-
ValidationException,
|
|
11
|
-
HttpClientException
|
|
12
|
-
} from './src/index';
|
|
13
|
-
|
|
14
|
-
async function exampleUsage() {
|
|
15
|
-
try {
|
|
16
|
-
// Create a sample PDF data (in a real application, this would be loaded from a file)
|
|
17
|
-
const pdfData = new Uint8Array([
|
|
18
|
-
0x25, 0x50, 0x44, 0x46, // %PDF header
|
|
19
|
-
// ... rest of PDF data would go here
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
// Initialize the client with authentication token and PDF data
|
|
23
|
-
const client = await ClientV1.create('your-auth-token', pdfData, 'http://localhost:8080', 30000);
|
|
24
|
-
|
|
25
|
-
// Example 1: Find all paragraphs on page 1
|
|
26
|
-
const page1Position = Position.atPage(1);
|
|
27
|
-
const paragraphs = await client.findParagraphs(page1Position);
|
|
28
|
-
console.log(`Found ${paragraphs.length} paragraphs on page 1`);
|
|
29
|
-
|
|
30
|
-
// Example 2: Add a new paragraph using the builder pattern
|
|
31
|
-
const newParagraph = client.paragraphBuilder()
|
|
32
|
-
.fromString('Hello, PDFDancer!', new Color(255, 0, 0)) // Red text
|
|
33
|
-
.withFont(new Font('Arial', 12))
|
|
34
|
-
.withPosition(Position.atPageCoordinates(1, 100, 200))
|
|
35
|
-
.withLineSpacing(1.5)
|
|
36
|
-
.build();
|
|
37
|
-
|
|
38
|
-
await client.addParagraph(newParagraph);
|
|
39
|
-
console.log('Added new paragraph successfully');
|
|
40
|
-
|
|
41
|
-
// Example 3: Find and modify existing text
|
|
42
|
-
const textLines = await client.findTextLines(page1Position);
|
|
43
|
-
if (textLines.length > 0) {
|
|
44
|
-
await client.modifyTextLine(textLines[0], 'Modified text content');
|
|
45
|
-
console.log('Modified first text line');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Example 4: Get the modified PDF
|
|
49
|
-
const modifiedPdf = await client.getPdfFile();
|
|
50
|
-
console.log(`Generated PDF size: ${modifiedPdf.length} bytes`);
|
|
51
|
-
|
|
52
|
-
// Example 5: Save PDF (in browser environment)
|
|
53
|
-
// await client.savePdf('modified-document.pdf');
|
|
54
|
-
|
|
55
|
-
} catch (error) {
|
|
56
|
-
if (error instanceof ValidationException) {
|
|
57
|
-
console.error('Validation error:', error.message);
|
|
58
|
-
} else if (error instanceof HttpClientException) {
|
|
59
|
-
console.error('HTTP error:', error.message, 'Status:', error.statusCode);
|
|
60
|
-
} else {
|
|
61
|
-
console.error('Unexpected error:', error);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Example of using with custom font
|
|
67
|
-
async function exampleWithCustomFont() {
|
|
68
|
-
try {
|
|
69
|
-
const pdfData = new Uint8Array([0x25, 0x50, 0x44, 0x46]);
|
|
70
|
-
const client = await ClientV1.create('your-auth-token', pdfData, undefined, 30000);
|
|
71
|
-
|
|
72
|
-
// Register a custom font (example with dummy TTF data)
|
|
73
|
-
const customFontData = new Uint8Array([/* TTF font data here */]);
|
|
74
|
-
const fontName = await client.registerFont(customFontData);
|
|
75
|
-
console.log(`Registered font: ${fontName}`);
|
|
76
|
-
|
|
77
|
-
// Use the custom font in a paragraph
|
|
78
|
-
const paragraph = client.paragraphBuilder()
|
|
79
|
-
.fromString('Text with custom font')
|
|
80
|
-
.withFont(new Font(fontName, 14))
|
|
81
|
-
.withPosition(Position.atPageCoordinates(1, 50, 300))
|
|
82
|
-
.build();
|
|
83
|
-
|
|
84
|
-
await client.addParagraph(paragraph);
|
|
85
|
-
console.log('Added paragraph with custom font');
|
|
86
|
-
|
|
87
|
-
} catch (error) {
|
|
88
|
-
console.error('Error with custom font:', error);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Note: These examples show the API usage patterns.
|
|
93
|
-
// In a real application, you would need:
|
|
94
|
-
// 1. A valid authentication token
|
|
95
|
-
// 2. Actual PDF data
|
|
96
|
-
// 3. A running PDFDancer server at the specified URL
|
|
97
|
-
// 4. Proper error handling for your use case
|
|
98
|
-
|
|
99
|
-
export { exampleUsage, exampleWithCustomFont };
|