pdfdancer-client-typescript 2.0.5 → 2.0.7
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 +10 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +9 -2
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +23 -1
- package/dist/models.js.map +1 -1
- package/dist/pdfdancer_v1.d.ts +14 -0
- package/dist/pdfdancer_v1.d.ts.map +1 -1
- package/dist/pdfdancer_v1.js +65 -1
- package/dist/pdfdancer_v1.js.map +1 -1
- package/dist/replacement-builder.d.ts +78 -0
- package/dist/replacement-builder.d.ts.map +1 -0
- package/dist/replacement-builder.js +117 -0
- package/dist/replacement-builder.js.map +1 -0
- package/dist/types.d.ts +38 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +158 -2
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/__tests__/assertions.d.ts +0 -2
- package/dist/__tests__/assertions.d.ts.map +0 -1
- package/dist/__tests__/assertions.js +0 -11
- package/dist/__tests__/assertions.js.map +0 -1
- package/dist/__tests__/e2e/pdf-assertions.d.ts +0 -36
- package/dist/__tests__/e2e/pdf-assertions.d.ts.map +0 -1
- package/dist/__tests__/e2e/pdf-assertions.js +0 -218
- package/dist/__tests__/e2e/pdf-assertions.js.map +0 -1
- package/dist/__tests__/e2e/test-drawing-helpers.d.ts +0 -148
- package/dist/__tests__/e2e/test-drawing-helpers.d.ts.map +0 -1
- package/dist/__tests__/e2e/test-drawing-helpers.js +0 -343
- package/dist/__tests__/e2e/test-drawing-helpers.js.map +0 -1
- package/dist/__tests__/e2e/test-helpers.d.ts +0 -44
- package/dist/__tests__/e2e/test-helpers.d.ts.map +0 -1
- package/dist/__tests__/e2e/test-helpers.js +0 -233
- package/dist/__tests__/e2e/test-helpers.js.map +0 -1
- package/dist/client-v1.d.ts +0 -157
- package/dist/client-v1.d.ts.map +0 -1
- package/dist/client-v1.js +0 -576
- package/dist/client-v1.js.map +0 -1
- package/dist/client-v2.d.ts +0 -129
- package/dist/client-v2.d.ts.map +0 -1
- package/dist/client-v2.js +0 -696
- package/dist/client-v2.js.map +0 -1
package/dist/client-v2.js
DELETED
|
@@ -1,696 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* PDFDancer TypeScript Client V2
|
|
4
|
-
*
|
|
5
|
-
* New typed API with the pattern: open → select{Type}(criteria) → edit(properties) → save
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.PDFDancer = exports.ParagraphBuilderV2 = exports.PDFDocument = exports.PDFPage = exports.PathObject = exports.ImageObject = exports.TextObject = void 0;
|
|
9
|
-
const exceptions_1 = require("./exceptions");
|
|
10
|
-
const models_1 = require("./models");
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// Internal HTTP Client
|
|
13
|
-
// ============================================================================
|
|
14
|
-
class HttpClient {
|
|
15
|
-
constructor(token, sessionId, baseUrl, timeout) {
|
|
16
|
-
this.token = token;
|
|
17
|
-
this.sessionId = sessionId;
|
|
18
|
-
this.baseUrl = baseUrl;
|
|
19
|
-
this.timeout = timeout;
|
|
20
|
-
}
|
|
21
|
-
async request(method, path, data, params) {
|
|
22
|
-
const url = new URL(`${this.baseUrl}${path}`);
|
|
23
|
-
if (params) {
|
|
24
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
25
|
-
url.searchParams.append(key, value);
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
const headers = {
|
|
29
|
-
'Authorization': `Bearer ${this.token}`,
|
|
30
|
-
'X-Session-Id': this.sessionId,
|
|
31
|
-
'Content-Type': 'application/json'
|
|
32
|
-
};
|
|
33
|
-
try {
|
|
34
|
-
const response = await fetch(url.toString(), {
|
|
35
|
-
method,
|
|
36
|
-
headers,
|
|
37
|
-
body: data ? JSON.stringify(data) : undefined,
|
|
38
|
-
signal: this.timeout > 0 ? AbortSignal.timeout(this.timeout) : undefined
|
|
39
|
-
});
|
|
40
|
-
if (response.status === 404) {
|
|
41
|
-
try {
|
|
42
|
-
const errorData = await response.json();
|
|
43
|
-
if (errorData.error === 'FontNotFoundException') {
|
|
44
|
-
throw new exceptions_1.FontNotFoundException(errorData.message || 'Font not found');
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
catch (e) {
|
|
48
|
-
if (e instanceof exceptions_1.FontNotFoundException)
|
|
49
|
-
throw e;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (!response.ok) {
|
|
53
|
-
const errorMessage = await this.extractErrorMessage(response);
|
|
54
|
-
throw new exceptions_1.HttpClientException(`API request failed: ${errorMessage}`, response);
|
|
55
|
-
}
|
|
56
|
-
return response;
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
if (error instanceof exceptions_1.FontNotFoundException || error instanceof exceptions_1.HttpClientException) {
|
|
60
|
-
throw error;
|
|
61
|
-
}
|
|
62
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
63
|
-
throw new exceptions_1.HttpClientException(`API request failed: ${errorMessage}`, undefined, error);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
async extractErrorMessage(response) {
|
|
67
|
-
if (!response)
|
|
68
|
-
return "Unknown error";
|
|
69
|
-
try {
|
|
70
|
-
const errorData = await response.json();
|
|
71
|
-
if (errorData._embedded?.errors) {
|
|
72
|
-
const errors = errorData._embedded.errors;
|
|
73
|
-
if (Array.isArray(errors)) {
|
|
74
|
-
const messages = errors
|
|
75
|
-
.filter(error => error.message)
|
|
76
|
-
.map(error => error.message);
|
|
77
|
-
if (messages.length > 0)
|
|
78
|
-
return messages.join("; ");
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (errorData.message)
|
|
82
|
-
return errorData.message;
|
|
83
|
-
return await response.text() || `HTTP ${response.status}`;
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
try {
|
|
87
|
-
return await response.text() || `HTTP ${response.status}`;
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
return `HTTP ${response.status}`;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
// ============================================================================
|
|
96
|
-
// TextObject
|
|
97
|
-
// ============================================================================
|
|
98
|
-
class TextObject {
|
|
99
|
-
constructor(objectRef, client, objectType) {
|
|
100
|
-
this.objectRef = objectRef;
|
|
101
|
-
this.client = client;
|
|
102
|
-
this.objectType = objectType;
|
|
103
|
-
}
|
|
104
|
-
async edit(options) {
|
|
105
|
-
if (options.replace !== undefined) {
|
|
106
|
-
// Text replacement using ModifyTextRequest
|
|
107
|
-
const requestData = new models_1.ModifyTextRequest(this.objectRef, options.replace).toDict();
|
|
108
|
-
const endpoint = this.objectType === models_1.ObjectType.TEXT_LINE
|
|
109
|
-
? '/pdf/text/line'
|
|
110
|
-
: '/pdf/text/paragraph';
|
|
111
|
-
await this.client.request('PUT', endpoint, requestData);
|
|
112
|
-
}
|
|
113
|
-
// Handle formatting changes (font, size, lineSpacing, color)
|
|
114
|
-
if (options.font || options.size !== undefined || options.lineSpacing !== undefined || options.color) {
|
|
115
|
-
const paragraph = new models_1.Paragraph();
|
|
116
|
-
// Set textLines to empty array - required by API
|
|
117
|
-
paragraph.textLines = [];
|
|
118
|
-
if (options.font) {
|
|
119
|
-
paragraph.font = new models_1.Font(options.font, options.size || 12);
|
|
120
|
-
}
|
|
121
|
-
if (options.lineSpacing !== undefined) {
|
|
122
|
-
paragraph.lineSpacing = options.lineSpacing;
|
|
123
|
-
}
|
|
124
|
-
if (options.color) {
|
|
125
|
-
// Parse hex color string to RGB
|
|
126
|
-
const hex = options.color.replace('#', '');
|
|
127
|
-
const r = parseInt(hex.substring(0, 2), 16);
|
|
128
|
-
const g = parseInt(hex.substring(2, 4), 16);
|
|
129
|
-
const b = parseInt(hex.substring(4, 6), 16);
|
|
130
|
-
paragraph.color = new models_1.Color(r, g, b);
|
|
131
|
-
}
|
|
132
|
-
// Use ModifyRequest for object modifications
|
|
133
|
-
const requestData = new models_1.ModifyRequest(this.objectRef, paragraph).toDict();
|
|
134
|
-
await this.client.request('PUT', '/pdf/modify', requestData);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
exports.TextObject = TextObject;
|
|
139
|
-
// ============================================================================
|
|
140
|
-
// ImageObject
|
|
141
|
-
// ============================================================================
|
|
142
|
-
class ImageObject {
|
|
143
|
-
constructor(objectRef, client) {
|
|
144
|
-
this.objectRef = objectRef;
|
|
145
|
-
this.client = client;
|
|
146
|
-
}
|
|
147
|
-
async edit(options) {
|
|
148
|
-
// For now, we'll need to map this to the existing modify API
|
|
149
|
-
// The current API doesn't have direct image transform support,
|
|
150
|
-
// so we'll use the move operation for translate
|
|
151
|
-
if (options.translate) {
|
|
152
|
-
const currentPos = this.objectRef.getPosition();
|
|
153
|
-
const newPos = new models_1.Position();
|
|
154
|
-
newPos.pageIndex = currentPos.pageIndex;
|
|
155
|
-
if (currentPos.boundingRect) {
|
|
156
|
-
newPos.boundingRect = new models_1.BoundingRect(currentPos.boundingRect.x + options.translate[0], currentPos.boundingRect.y + options.translate[1], currentPos.boundingRect.width, currentPos.boundingRect.height);
|
|
157
|
-
}
|
|
158
|
-
// Use MoveRequest for proper format
|
|
159
|
-
const requestData = new models_1.MoveRequest(this.objectRef, newPos).toDict();
|
|
160
|
-
await this.client.request('PUT', '/pdf/move', requestData);
|
|
161
|
-
}
|
|
162
|
-
// Note: scale and rotate are not directly supported by current API
|
|
163
|
-
// These would need backend implementation
|
|
164
|
-
if (options.scale !== undefined || options.rotate !== undefined) {
|
|
165
|
-
throw new exceptions_1.PdfDancerException('Image scale and rotate operations are not yet supported by the backend API');
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
exports.ImageObject = ImageObject;
|
|
170
|
-
// ============================================================================
|
|
171
|
-
// PathObject
|
|
172
|
-
// ============================================================================
|
|
173
|
-
class PathObject {
|
|
174
|
-
constructor(objectRef, client) {
|
|
175
|
-
this.objectRef = objectRef;
|
|
176
|
-
this.client = client;
|
|
177
|
-
}
|
|
178
|
-
async edit(options) {
|
|
179
|
-
// Path editing would require backend support for vector manipulation
|
|
180
|
-
// Current API doesn't have path modification endpoints
|
|
181
|
-
throw new exceptions_1.PdfDancerException('Path editing is not yet supported by the backend API');
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
exports.PathObject = PathObject;
|
|
185
|
-
// ============================================================================
|
|
186
|
-
// PDFPage
|
|
187
|
-
// ============================================================================
|
|
188
|
-
class PDFPage {
|
|
189
|
-
constructor(pageIndex, client) {
|
|
190
|
-
this.pageIndex = pageIndex;
|
|
191
|
-
this.client = client;
|
|
192
|
-
}
|
|
193
|
-
async selectText(criteria) {
|
|
194
|
-
const position = this.buildPositionFromCriteria(criteria);
|
|
195
|
-
// Try paragraph first, then text line
|
|
196
|
-
let objectRefs = await this.findObjects(models_1.ObjectType.PARAGRAPH, position);
|
|
197
|
-
let objectType = models_1.ObjectType.PARAGRAPH;
|
|
198
|
-
if (objectRefs.length === 0) {
|
|
199
|
-
objectRefs = await this.findObjects(models_1.ObjectType.TEXT_LINE, position);
|
|
200
|
-
objectType = models_1.ObjectType.TEXT_LINE;
|
|
201
|
-
}
|
|
202
|
-
if (objectRefs.length === 0) {
|
|
203
|
-
throw new exceptions_1.PdfDancerException('No text object found matching criteria');
|
|
204
|
-
}
|
|
205
|
-
return new TextObject(objectRefs[0], this.client, objectType);
|
|
206
|
-
}
|
|
207
|
-
async selectImage(criteria) {
|
|
208
|
-
const position = this.buildPositionFromImageCriteria(criteria);
|
|
209
|
-
const objectRefs = await this.findObjects(models_1.ObjectType.IMAGE, position);
|
|
210
|
-
if (objectRefs.length === 0) {
|
|
211
|
-
throw new exceptions_1.PdfDancerException('No image found matching criteria');
|
|
212
|
-
}
|
|
213
|
-
// If index specified, return that index, otherwise return first
|
|
214
|
-
const index = criteria.index !== undefined ? criteria.index : 0;
|
|
215
|
-
if (index >= objectRefs.length) {
|
|
216
|
-
throw new exceptions_1.PdfDancerException(`Image index ${index} out of range (found ${objectRefs.length} images)`);
|
|
217
|
-
}
|
|
218
|
-
return new ImageObject(objectRefs[index], this.client);
|
|
219
|
-
}
|
|
220
|
-
async selectPath(criteria) {
|
|
221
|
-
const position = this.buildPositionFromPathCriteria(criteria);
|
|
222
|
-
const objectRefs = await this.findObjects(models_1.ObjectType.PATH, position);
|
|
223
|
-
if (objectRefs.length === 0) {
|
|
224
|
-
throw new exceptions_1.PdfDancerException('No path found matching criteria');
|
|
225
|
-
}
|
|
226
|
-
return new PathObject(objectRefs[0], this.client);
|
|
227
|
-
}
|
|
228
|
-
buildPositionFromCriteria(criteria) {
|
|
229
|
-
const position = new models_1.Position();
|
|
230
|
-
position.pageIndex = this.pageIndex;
|
|
231
|
-
if (criteria.containing) {
|
|
232
|
-
position.textStartsWith = criteria.containing;
|
|
233
|
-
}
|
|
234
|
-
if (criteria.at) {
|
|
235
|
-
position.boundingRect = new models_1.BoundingRect(criteria.at[0], criteria.at[1], 0, 0);
|
|
236
|
-
position.mode = models_1.PositionMode.CONTAINS;
|
|
237
|
-
}
|
|
238
|
-
if (criteria.withinBbox) {
|
|
239
|
-
position.boundingRect = new models_1.BoundingRect(criteria.withinBbox[0], criteria.withinBbox[1], criteria.withinBbox[2], criteria.withinBbox[3]);
|
|
240
|
-
position.mode = models_1.PositionMode.CONTAINS;
|
|
241
|
-
}
|
|
242
|
-
return position;
|
|
243
|
-
}
|
|
244
|
-
buildPositionFromImageCriteria(criteria) {
|
|
245
|
-
const position = new models_1.Position();
|
|
246
|
-
position.pageIndex = this.pageIndex;
|
|
247
|
-
if (criteria.at) {
|
|
248
|
-
position.boundingRect = new models_1.BoundingRect(criteria.at[0], criteria.at[1], 0, 0);
|
|
249
|
-
position.mode = models_1.PositionMode.CONTAINS;
|
|
250
|
-
}
|
|
251
|
-
return position;
|
|
252
|
-
}
|
|
253
|
-
buildPositionFromPathCriteria(criteria) {
|
|
254
|
-
const position = new models_1.Position();
|
|
255
|
-
position.pageIndex = this.pageIndex;
|
|
256
|
-
if (criteria.at) {
|
|
257
|
-
position.boundingRect = new models_1.BoundingRect(criteria.at[0], criteria.at[1], 0, 0);
|
|
258
|
-
position.mode = models_1.PositionMode.CONTAINS;
|
|
259
|
-
}
|
|
260
|
-
return position;
|
|
261
|
-
}
|
|
262
|
-
async findObjects(objectType, position) {
|
|
263
|
-
const requestData = {
|
|
264
|
-
kind: objectType,
|
|
265
|
-
position: (0, models_1.positionToDict)(position)
|
|
266
|
-
};
|
|
267
|
-
const response = await this.client.request('POST', '/pdf/find', requestData);
|
|
268
|
-
const objectsData = await response.json();
|
|
269
|
-
return objectsData.map((objData) => this.parseObjectRef(objData));
|
|
270
|
-
}
|
|
271
|
-
parseObjectRef(objData) {
|
|
272
|
-
if (!objData) {
|
|
273
|
-
throw new exceptions_1.PdfDancerException('Invalid object data: received null or undefined');
|
|
274
|
-
}
|
|
275
|
-
const positionData = objData.position || {};
|
|
276
|
-
const position = this.parsePosition(positionData);
|
|
277
|
-
const objectType = objData.type;
|
|
278
|
-
return new models_1.ObjectRef(objData.internalId, position, objectType);
|
|
279
|
-
}
|
|
280
|
-
parsePosition(posData) {
|
|
281
|
-
const position = new models_1.Position();
|
|
282
|
-
position.pageIndex = posData.pageIndex;
|
|
283
|
-
position.textStartsWith = posData.textStartsWith;
|
|
284
|
-
if (posData.shape) {
|
|
285
|
-
position.shape = models_1.ShapeType[posData.shape];
|
|
286
|
-
}
|
|
287
|
-
if (posData.mode) {
|
|
288
|
-
position.mode = models_1.PositionMode[posData.mode];
|
|
289
|
-
}
|
|
290
|
-
if (posData.boundingRect) {
|
|
291
|
-
const rectData = posData.boundingRect;
|
|
292
|
-
position.boundingRect = new models_1.BoundingRect(rectData.x, rectData.y, rectData.width, rectData.height);
|
|
293
|
-
}
|
|
294
|
-
return position;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
exports.PDFPage = PDFPage;
|
|
298
|
-
// ============================================================================
|
|
299
|
-
// PDFDocument
|
|
300
|
-
// ============================================================================
|
|
301
|
-
class PDFDocument {
|
|
302
|
-
constructor(client, sessionId) {
|
|
303
|
-
this.client = client;
|
|
304
|
-
this.sessionId = sessionId;
|
|
305
|
-
}
|
|
306
|
-
page(index) {
|
|
307
|
-
if (index < 0) {
|
|
308
|
-
throw new exceptions_1.ValidationException(`Page index must be >= 0, got ${index}`);
|
|
309
|
-
}
|
|
310
|
-
return new PDFPage(index, this.client);
|
|
311
|
-
}
|
|
312
|
-
// Document-level find operations
|
|
313
|
-
async findParagraphs(position) {
|
|
314
|
-
return this.findObjects(models_1.ObjectType.PARAGRAPH, position);
|
|
315
|
-
}
|
|
316
|
-
async findImages(position) {
|
|
317
|
-
return this.findObjects(models_1.ObjectType.IMAGE, position);
|
|
318
|
-
}
|
|
319
|
-
async findTextLines(position) {
|
|
320
|
-
return this.findObjects(models_1.ObjectType.TEXT_LINE, position);
|
|
321
|
-
}
|
|
322
|
-
async findPaths(position) {
|
|
323
|
-
return this.findObjects(models_1.ObjectType.PATH, position);
|
|
324
|
-
}
|
|
325
|
-
async findFormXObjects(position) {
|
|
326
|
-
return this.findObjects(models_1.ObjectType.FORM_X_OBJECT, position);
|
|
327
|
-
}
|
|
328
|
-
async findObjects(objectType, position) {
|
|
329
|
-
const requestData = {
|
|
330
|
-
kind: objectType,
|
|
331
|
-
position: position ? (0, models_1.positionToDict)(position) : null
|
|
332
|
-
};
|
|
333
|
-
const response = await this.client.request('POST', '/pdf/find', requestData);
|
|
334
|
-
const objectsData = await response.json();
|
|
335
|
-
// Filter out null entries and filter by objectType
|
|
336
|
-
return objectsData
|
|
337
|
-
.filter((objData) => objData !== null && objData.type === objectType)
|
|
338
|
-
.map((objData) => this.parseObjectRef(objData));
|
|
339
|
-
}
|
|
340
|
-
parseObjectRef(objData) {
|
|
341
|
-
if (!objData) {
|
|
342
|
-
throw new exceptions_1.PdfDancerException('Invalid object data: received null or undefined');
|
|
343
|
-
}
|
|
344
|
-
const positionData = objData.position || {};
|
|
345
|
-
const position = this.parsePosition(positionData);
|
|
346
|
-
const objectType = objData.type;
|
|
347
|
-
return new models_1.ObjectRef(objData.internalId, position, objectType);
|
|
348
|
-
}
|
|
349
|
-
parsePosition(posData) {
|
|
350
|
-
const position = new models_1.Position();
|
|
351
|
-
position.pageIndex = posData.pageIndex;
|
|
352
|
-
position.textStartsWith = posData.textStartsWith;
|
|
353
|
-
if (posData.shape) {
|
|
354
|
-
position.shape = models_1.ShapeType[posData.shape];
|
|
355
|
-
}
|
|
356
|
-
if (posData.mode) {
|
|
357
|
-
position.mode = models_1.PositionMode[posData.mode];
|
|
358
|
-
}
|
|
359
|
-
if (posData.boundingRect) {
|
|
360
|
-
const rectData = posData.boundingRect;
|
|
361
|
-
position.boundingRect = new models_1.BoundingRect(rectData.x, rectData.y, rectData.width, rectData.height);
|
|
362
|
-
}
|
|
363
|
-
return position;
|
|
364
|
-
}
|
|
365
|
-
// Delete operation
|
|
366
|
-
async delete(objectRef) {
|
|
367
|
-
if (!objectRef) {
|
|
368
|
-
throw new exceptions_1.ValidationException("Object reference cannot be null");
|
|
369
|
-
}
|
|
370
|
-
const requestData = {
|
|
371
|
-
objectRef: {
|
|
372
|
-
internalId: objectRef.internalId,
|
|
373
|
-
position: (0, models_1.positionToDict)(objectRef.position),
|
|
374
|
-
type: objectRef.type
|
|
375
|
-
}
|
|
376
|
-
};
|
|
377
|
-
const response = await this.client.request('DELETE', '/pdf/delete', requestData);
|
|
378
|
-
return await response.json();
|
|
379
|
-
}
|
|
380
|
-
// Move operation
|
|
381
|
-
async move(objectRef, position) {
|
|
382
|
-
if (!objectRef) {
|
|
383
|
-
throw new exceptions_1.ValidationException("Object reference cannot be null");
|
|
384
|
-
}
|
|
385
|
-
if (!position) {
|
|
386
|
-
throw new exceptions_1.ValidationException("Position cannot be null");
|
|
387
|
-
}
|
|
388
|
-
const requestData = new models_1.MoveRequest(objectRef, position).toDict();
|
|
389
|
-
const response = await this.client.request('PUT', '/pdf/move', requestData);
|
|
390
|
-
return await response.json();
|
|
391
|
-
}
|
|
392
|
-
// Add paragraph operation
|
|
393
|
-
async addParagraph(paragraph) {
|
|
394
|
-
if (!paragraph) {
|
|
395
|
-
throw new exceptions_1.ValidationException("Paragraph cannot be null");
|
|
396
|
-
}
|
|
397
|
-
if (!paragraph.getPosition()) {
|
|
398
|
-
throw new exceptions_1.ValidationException("Paragraph position is null");
|
|
399
|
-
}
|
|
400
|
-
if (paragraph.getPosition().pageIndex === undefined) {
|
|
401
|
-
throw new exceptions_1.ValidationException("Paragraph position page index is null");
|
|
402
|
-
}
|
|
403
|
-
if (paragraph.getPosition().pageIndex < 0) {
|
|
404
|
-
throw new exceptions_1.ValidationException("Paragraph position page index is less than 0");
|
|
405
|
-
}
|
|
406
|
-
const requestData = new models_1.AddRequest(paragraph).toDict();
|
|
407
|
-
const response = await this.client.request('POST', '/pdf/add', requestData);
|
|
408
|
-
return await response.json();
|
|
409
|
-
}
|
|
410
|
-
// Modify paragraph operation
|
|
411
|
-
async modifyParagraph(objectRef, newParagraph) {
|
|
412
|
-
if (!objectRef) {
|
|
413
|
-
throw new exceptions_1.ValidationException("Object reference cannot be null");
|
|
414
|
-
}
|
|
415
|
-
if (newParagraph === null || newParagraph === undefined) {
|
|
416
|
-
throw new exceptions_1.ValidationException("New paragraph cannot be null");
|
|
417
|
-
}
|
|
418
|
-
if (typeof newParagraph === 'string') {
|
|
419
|
-
// Text modification
|
|
420
|
-
const requestData = new models_1.ModifyTextRequest(objectRef, newParagraph).toDict();
|
|
421
|
-
const response = await this.client.request('PUT', '/pdf/text/paragraph', requestData);
|
|
422
|
-
return await response.json();
|
|
423
|
-
}
|
|
424
|
-
else {
|
|
425
|
-
// Object modification
|
|
426
|
-
const requestData = new models_1.ModifyRequest(objectRef, newParagraph).toDict();
|
|
427
|
-
const response = await this.client.request('PUT', '/pdf/modify', requestData);
|
|
428
|
-
return await response.json();
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
// Font operations
|
|
432
|
-
async findFonts(fontName, fontSize) {
|
|
433
|
-
if (!fontName || !fontName.trim()) {
|
|
434
|
-
throw new exceptions_1.ValidationException("Font name cannot be null or empty");
|
|
435
|
-
}
|
|
436
|
-
if (fontSize <= 0) {
|
|
437
|
-
throw new exceptions_1.ValidationException(`Font size must be positive, got ${fontSize}`);
|
|
438
|
-
}
|
|
439
|
-
const params = { fontName: fontName.trim() };
|
|
440
|
-
const response = await this.client.request('GET', '/font/find', undefined, params);
|
|
441
|
-
const fontNames = await response.json();
|
|
442
|
-
return fontNames.map((name) => new models_1.Font(name, fontSize));
|
|
443
|
-
}
|
|
444
|
-
async registerFont(ttfFile) {
|
|
445
|
-
if (!ttfFile) {
|
|
446
|
-
throw new exceptions_1.ValidationException("TTF file cannot be null");
|
|
447
|
-
}
|
|
448
|
-
try {
|
|
449
|
-
let fontData;
|
|
450
|
-
let filename;
|
|
451
|
-
if (ttfFile instanceof Uint8Array) {
|
|
452
|
-
if (ttfFile.length === 0) {
|
|
453
|
-
throw new exceptions_1.ValidationException("Font data cannot be empty");
|
|
454
|
-
}
|
|
455
|
-
fontData = ttfFile;
|
|
456
|
-
filename = 'font.ttf';
|
|
457
|
-
}
|
|
458
|
-
else if (ttfFile instanceof File) {
|
|
459
|
-
if (ttfFile.size === 0) {
|
|
460
|
-
throw new exceptions_1.ValidationException("Font file is empty");
|
|
461
|
-
}
|
|
462
|
-
fontData = new Uint8Array(await ttfFile.arrayBuffer());
|
|
463
|
-
filename = ttfFile.name;
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
throw new exceptions_1.ValidationException(`Unsupported font file type: ${typeof ttfFile}`);
|
|
467
|
-
}
|
|
468
|
-
const formData = new FormData();
|
|
469
|
-
const blob = new Blob([fontData.buffer], { type: 'font/ttf' });
|
|
470
|
-
formData.append('ttfFile', blob, filename);
|
|
471
|
-
const response = await fetch(`${this.client['baseUrl']}/font/register`, {
|
|
472
|
-
method: 'POST',
|
|
473
|
-
headers: {
|
|
474
|
-
'Authorization': `Bearer ${this.client['token']}`,
|
|
475
|
-
'X-Session-Id': this.sessionId
|
|
476
|
-
},
|
|
477
|
-
body: formData,
|
|
478
|
-
signal: AbortSignal.timeout(30000)
|
|
479
|
-
});
|
|
480
|
-
if (!response.ok) {
|
|
481
|
-
const errorMessage = await this.extractErrorMessage(response);
|
|
482
|
-
throw new exceptions_1.HttpClientException(`Font registration failed: ${errorMessage}`, response);
|
|
483
|
-
}
|
|
484
|
-
return (await response.text()).trim();
|
|
485
|
-
}
|
|
486
|
-
catch (error) {
|
|
487
|
-
if (error instanceof exceptions_1.ValidationException || error instanceof exceptions_1.HttpClientException) {
|
|
488
|
-
throw error;
|
|
489
|
-
}
|
|
490
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
491
|
-
throw new exceptions_1.PdfDancerException(`Failed to read font file: ${errorMessage}`, error);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
async extractErrorMessage(response) {
|
|
495
|
-
if (!response)
|
|
496
|
-
return "Unknown error";
|
|
497
|
-
try {
|
|
498
|
-
const errorData = await response.json();
|
|
499
|
-
if (errorData._embedded?.errors) {
|
|
500
|
-
const errors = errorData._embedded.errors;
|
|
501
|
-
if (Array.isArray(errors)) {
|
|
502
|
-
const messages = errors
|
|
503
|
-
.filter((error) => error.message)
|
|
504
|
-
.map((error) => error.message);
|
|
505
|
-
if (messages.length > 0)
|
|
506
|
-
return messages.join("; ");
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
if (errorData.message)
|
|
510
|
-
return errorData.message;
|
|
511
|
-
return await response.text() || `HTTP ${response.status}`;
|
|
512
|
-
}
|
|
513
|
-
catch {
|
|
514
|
-
try {
|
|
515
|
-
return await response.text() || `HTTP ${response.status}`;
|
|
516
|
-
}
|
|
517
|
-
catch {
|
|
518
|
-
return `HTTP ${response.status}`;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
// Paragraph builder
|
|
523
|
-
paragraphBuilder() {
|
|
524
|
-
return new ParagraphBuilderV2(this);
|
|
525
|
-
}
|
|
526
|
-
async save(filename = 'document.pdf') {
|
|
527
|
-
if (!filename) {
|
|
528
|
-
throw new exceptions_1.ValidationException("Filename cannot be null or empty");
|
|
529
|
-
}
|
|
530
|
-
try {
|
|
531
|
-
const response = await this.client.request('GET', `/session/${this.sessionId}/pdf`);
|
|
532
|
-
const pdfData = new Uint8Array(await response.arrayBuffer());
|
|
533
|
-
// Browser download
|
|
534
|
-
const blob = new Blob([pdfData.buffer], { type: 'application/pdf' });
|
|
535
|
-
const url = URL.createObjectURL(blob);
|
|
536
|
-
const link = document.createElement('a');
|
|
537
|
-
link.href = url;
|
|
538
|
-
link.download = filename;
|
|
539
|
-
document.body.appendChild(link);
|
|
540
|
-
link.click();
|
|
541
|
-
document.body.removeChild(link);
|
|
542
|
-
URL.revokeObjectURL(url);
|
|
543
|
-
}
|
|
544
|
-
catch (error) {
|
|
545
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
546
|
-
throw new exceptions_1.PdfDancerException(`Failed to save PDF file: ${errorMessage}`, error);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
exports.PDFDocument = PDFDocument;
|
|
551
|
-
// ============================================================================
|
|
552
|
-
// ParagraphBuilderV2
|
|
553
|
-
// ============================================================================
|
|
554
|
-
class ParagraphBuilderV2 {
|
|
555
|
-
constructor(document) {
|
|
556
|
-
this.document = document;
|
|
557
|
-
this.paragraph = new models_1.Paragraph();
|
|
558
|
-
}
|
|
559
|
-
fromString(text) {
|
|
560
|
-
this.paragraph.textLines = text.split('\\n');
|
|
561
|
-
return this;
|
|
562
|
-
}
|
|
563
|
-
withFont(font) {
|
|
564
|
-
this.paragraph.font = font;
|
|
565
|
-
return this;
|
|
566
|
-
}
|
|
567
|
-
withLineSpacing(lineSpacing) {
|
|
568
|
-
this.paragraph.lineSpacing = lineSpacing;
|
|
569
|
-
return this;
|
|
570
|
-
}
|
|
571
|
-
withColor(color) {
|
|
572
|
-
this.paragraph.color = color;
|
|
573
|
-
return this;
|
|
574
|
-
}
|
|
575
|
-
withPosition(position) {
|
|
576
|
-
this.paragraph.position = position;
|
|
577
|
-
return this;
|
|
578
|
-
}
|
|
579
|
-
async withFontFile(ttfData, fontSize) {
|
|
580
|
-
const fontName = await this.document.registerFont(ttfData);
|
|
581
|
-
this.paragraph.font = new models_1.Font(fontName, fontSize);
|
|
582
|
-
return this;
|
|
583
|
-
}
|
|
584
|
-
build() {
|
|
585
|
-
return this.paragraph;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
exports.ParagraphBuilderV2 = ParagraphBuilderV2;
|
|
589
|
-
// ============================================================================
|
|
590
|
-
// PDFDancer
|
|
591
|
-
// ============================================================================
|
|
592
|
-
class PDFDancer {
|
|
593
|
-
static async open(pdfData, options) {
|
|
594
|
-
const { token, baseUrl = "http://localhost:8080", timeout = 30000 } = options;
|
|
595
|
-
if (!token || !token.trim()) {
|
|
596
|
-
throw new exceptions_1.ValidationException("Authentication token cannot be null or empty");
|
|
597
|
-
}
|
|
598
|
-
if (!pdfData) {
|
|
599
|
-
throw new exceptions_1.ValidationException("PDF data cannot be null");
|
|
600
|
-
}
|
|
601
|
-
// Process PDF data
|
|
602
|
-
const pdfBytes = PDFDancer.processPdfData(pdfData);
|
|
603
|
-
// Create session
|
|
604
|
-
const sessionId = await PDFDancer.createSession(pdfBytes, token.trim(), baseUrl.replace(/\/$/, ''), timeout);
|
|
605
|
-
// Create HTTP client
|
|
606
|
-
const client = new HttpClient(token.trim(), sessionId, baseUrl.replace(/\/$/, ''), timeout);
|
|
607
|
-
return new PDFDocument(client, sessionId);
|
|
608
|
-
}
|
|
609
|
-
static processPdfData(pdfData) {
|
|
610
|
-
if (pdfData instanceof Uint8Array) {
|
|
611
|
-
if (pdfData.length === 0) {
|
|
612
|
-
throw new exceptions_1.ValidationException("PDF data cannot be empty");
|
|
613
|
-
}
|
|
614
|
-
return pdfData;
|
|
615
|
-
}
|
|
616
|
-
else if (pdfData instanceof ArrayBuffer) {
|
|
617
|
-
const uint8Array = new Uint8Array(pdfData);
|
|
618
|
-
if (uint8Array.length === 0) {
|
|
619
|
-
throw new exceptions_1.ValidationException("PDF data cannot be empty");
|
|
620
|
-
}
|
|
621
|
-
return uint8Array;
|
|
622
|
-
}
|
|
623
|
-
else if (pdfData instanceof File) {
|
|
624
|
-
return pdfData;
|
|
625
|
-
}
|
|
626
|
-
else {
|
|
627
|
-
throw new exceptions_1.ValidationException(`Unsupported PDF data type: ${typeof pdfData}`);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
static async createSession(pdfBytes, token, baseUrl, timeout) {
|
|
631
|
-
try {
|
|
632
|
-
const formData = new FormData();
|
|
633
|
-
if (pdfBytes instanceof File) {
|
|
634
|
-
formData.append('pdf', pdfBytes, 'document.pdf');
|
|
635
|
-
}
|
|
636
|
-
else {
|
|
637
|
-
const blob = new Blob([pdfBytes.buffer], { type: 'application/pdf' });
|
|
638
|
-
formData.append('pdf', blob, 'document.pdf');
|
|
639
|
-
}
|
|
640
|
-
const response = await fetch(`${baseUrl}/session/create`, {
|
|
641
|
-
method: 'POST',
|
|
642
|
-
headers: {
|
|
643
|
-
'Authorization': `Bearer ${token}`
|
|
644
|
-
},
|
|
645
|
-
body: formData,
|
|
646
|
-
signal: timeout > 0 ? AbortSignal.timeout(timeout) : undefined
|
|
647
|
-
});
|
|
648
|
-
if (!response.ok) {
|
|
649
|
-
const errorMessage = await PDFDancer.extractErrorMessage(response);
|
|
650
|
-
throw new exceptions_1.HttpClientException(`Failed to create session: ${errorMessage}`, response);
|
|
651
|
-
}
|
|
652
|
-
const sessionId = (await response.text()).trim();
|
|
653
|
-
if (!sessionId) {
|
|
654
|
-
throw new exceptions_1.SessionException("Server returned empty session ID");
|
|
655
|
-
}
|
|
656
|
-
return sessionId;
|
|
657
|
-
}
|
|
658
|
-
catch (error) {
|
|
659
|
-
if (error instanceof exceptions_1.HttpClientException || error instanceof exceptions_1.SessionException) {
|
|
660
|
-
throw error;
|
|
661
|
-
}
|
|
662
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
663
|
-
throw new exceptions_1.HttpClientException(`Failed to create session: ${errorMessage}`, undefined, error);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
static async extractErrorMessage(response) {
|
|
667
|
-
if (!response)
|
|
668
|
-
return "Unknown error";
|
|
669
|
-
try {
|
|
670
|
-
const errorData = await response.json();
|
|
671
|
-
if (errorData._embedded?.errors) {
|
|
672
|
-
const errors = errorData._embedded.errors;
|
|
673
|
-
if (Array.isArray(errors)) {
|
|
674
|
-
const messages = errors
|
|
675
|
-
.filter((error) => error.message)
|
|
676
|
-
.map((error) => error.message);
|
|
677
|
-
if (messages.length > 0)
|
|
678
|
-
return messages.join("; ");
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
if (errorData.message)
|
|
682
|
-
return errorData.message;
|
|
683
|
-
return await response.text() || `HTTP ${response.status}`;
|
|
684
|
-
}
|
|
685
|
-
catch {
|
|
686
|
-
try {
|
|
687
|
-
return await response.text() || `HTTP ${response.status}`;
|
|
688
|
-
}
|
|
689
|
-
catch {
|
|
690
|
-
return `HTTP ${response.status}`;
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
exports.PDFDancer = PDFDancer;
|
|
696
|
-
//# sourceMappingURL=client-v2.js.map
|