pdfdancer-client-typescript 1.0.21 → 2.0.0

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.
@@ -13,6 +13,7 @@ const exceptions_1 = require("./exceptions");
13
13
  const models_1 = require("./models");
14
14
  const paragraph_builder_1 = require("./paragraph-builder");
15
15
  const page_builder_1 = require("./page-builder");
16
+ const env_loader_1 = require("./env-loader");
16
17
  const types_1 = require("./types");
17
18
  const image_builder_1 = require("./image-builder");
18
19
  const path_builder_1 = require("./path-builder");
@@ -165,35 +166,35 @@ function generateTimestamp() {
165
166
  return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${microseconds}Z`;
166
167
  }
167
168
  class PageClient {
168
- constructor(client, pageIndex, pageRef) {
169
+ constructor(client, pageNumber, pageRef) {
169
170
  this.type = models_1.ObjectType.PAGE;
170
171
  this._client = client;
171
- this._pageIndex = pageIndex;
172
- this.internalId = pageRef?.internalId ?? `PAGE-${this._pageIndex}`;
173
- this.position = pageRef?.position ?? models_1.Position.atPage(this._pageIndex);
172
+ this._pageNumber = pageNumber;
173
+ this.internalId = pageRef?.internalId ?? `PAGE-${this._pageNumber}`;
174
+ this.position = pageRef?.position ?? models_1.Position.atPage(this._pageNumber);
174
175
  this.pageSize = pageRef?.pageSize;
175
176
  this.orientation = pageRef?.orientation;
176
177
  // Cast to the internal interface to get access
177
178
  this._internals = this._client;
178
179
  }
179
180
  async selectPathsAt(x, y, tolerance = 0) {
180
- return this._internals.toPathObjects(await this._internals.findPaths(models_1.Position.atPageCoordinates(this._pageIndex, x, y, tolerance)));
181
+ return this._internals.toPathObjects(await this._internals.findPaths(models_1.Position.atPageCoordinates(this._pageNumber, x, y, tolerance)));
181
182
  }
182
183
  async selectPaths() {
183
- return this._internals.toPathObjects(await this._internals.findPaths(models_1.Position.atPage(this._pageIndex)));
184
+ return this._internals.toPathObjects(await this._internals.findPaths(models_1.Position.atPage(this._pageNumber)));
184
185
  }
185
186
  async selectImages() {
186
- return this._internals.toImageObjects(await this._internals._findImages(models_1.Position.atPage(this._pageIndex)));
187
+ return this._internals.toImageObjects(await this._internals._findImages(models_1.Position.atPage(this._pageNumber)));
187
188
  }
188
189
  async selectImagesAt(x, y, tolerance = 0) {
189
- return this._internals.toImageObjects(await this._internals._findImages(models_1.Position.atPageCoordinates(this._pageIndex, x, y, tolerance)));
190
+ return this._internals.toImageObjects(await this._internals._findImages(models_1.Position.atPageCoordinates(this._pageNumber, x, y, tolerance)));
190
191
  }
191
192
  async delete() {
192
- return this._client.deletePage(this._pageIndex);
193
+ return this._client.deletePage(this._pageNumber);
193
194
  }
194
- async moveTo(targetPageIndex) {
195
- const pageRef = await this._client.movePage(this._pageIndex, targetPageIndex);
196
- this._pageIndex = pageRef.position.pageIndex ?? targetPageIndex;
195
+ async moveTo(targetPageNumber) {
196
+ const pageRef = await this._client.movePage(this._pageNumber, targetPageNumber);
197
+ this._pageNumber = pageRef.position.pageNumber !== undefined ? pageRef.position.pageNumber + 1 : targetPageNumber;
197
198
  this.position = pageRef.position;
198
199
  this.internalId = pageRef.internalId;
199
200
  this.pageSize = pageRef.pageSize;
@@ -202,82 +203,82 @@ class PageClient {
202
203
  }
203
204
  // noinspection JSUnusedGlobalSymbols
204
205
  async selectForms() {
205
- return this._internals.toFormXObjects(await this._internals.findFormXObjects(models_1.Position.atPage(this._pageIndex)));
206
+ return this._internals.toFormXObjects(await this._internals.findFormXObjects(models_1.Position.atPage(this._pageNumber)));
206
207
  }
207
208
  async selectFormsAt(x, y, tolerance = 0) {
208
- return this._internals.toFormXObjects(await this._internals.findFormXObjects(models_1.Position.atPageCoordinates(this._pageIndex, x, y, tolerance)));
209
+ return this._internals.toFormXObjects(await this._internals.findFormXObjects(models_1.Position.atPageCoordinates(this._pageNumber, x, y, tolerance)));
209
210
  }
210
211
  async selectFormFields() {
211
- return this._internals.toFormFields(await this._internals.findFormFields(models_1.Position.atPage(this._pageIndex)));
212
+ return this._internals.toFormFields(await this._internals.findFormFields(models_1.Position.atPage(this._pageNumber)));
212
213
  }
213
214
  async selectFormFieldsAt(x, y, tolerance = 0) {
214
- return this._internals.toFormFields(await this._internals.findFormFields(models_1.Position.atPageCoordinates(this._pageIndex, x, y, tolerance)));
215
+ return this._internals.toFormFields(await this._internals.findFormFields(models_1.Position.atPageCoordinates(this._pageNumber, x, y, tolerance)));
215
216
  }
216
217
  // noinspection JSUnusedGlobalSymbols
217
218
  async selectFormFieldsByName(fieldName) {
218
- let pos = models_1.Position.atPage(this._pageIndex);
219
+ let pos = models_1.Position.atPage(this._pageNumber);
219
220
  pos.name = fieldName;
220
221
  return this._internals.toFormFields(await this._internals.findFormFields(pos));
221
222
  }
222
223
  async selectParagraphs() {
223
- return this._internals.toParagraphObjects(await this._internals.findParagraphs(models_1.Position.atPage(this._pageIndex)));
224
+ return this._internals.toParagraphObjects(await this._internals.findParagraphs(models_1.Position.atPage(this._pageNumber)));
224
225
  }
225
226
  async selectElements(types) {
226
- const snapshot = await this._client.getPageSnapshot(this._pageIndex, types);
227
+ const snapshot = await this._client.getPageSnapshot(this._pageNumber, types);
227
228
  return snapshot.elements;
228
229
  }
229
230
  async selectParagraphsStartingWith(text) {
230
- let pos = models_1.Position.atPage(this._pageIndex);
231
+ let pos = models_1.Position.atPage(this._pageNumber);
231
232
  pos.textStartsWith = text;
232
233
  return this._internals.toParagraphObjects(await this._internals.findParagraphs(pos));
233
234
  }
234
235
  async selectParagraphsMatching(pattern) {
235
- let pos = models_1.Position.atPage(this._pageIndex);
236
+ let pos = models_1.Position.atPage(this._pageNumber);
236
237
  pos.textPattern = pattern;
237
238
  return this._internals.toParagraphObjects(await this._internals.findParagraphs(pos));
238
239
  }
239
240
  async selectParagraphsAt(x, y, tolerance = DEFAULT_TOLERANCE) {
240
- return this._internals.toParagraphObjects(await this._internals.findParagraphs(models_1.Position.atPageCoordinates(this._pageIndex, x, y, tolerance)));
241
+ return this._internals.toParagraphObjects(await this._internals.findParagraphs(models_1.Position.atPageCoordinates(this._pageNumber, x, y, tolerance)));
241
242
  }
242
243
  async selectTextLinesStartingWith(text) {
243
- let pos = models_1.Position.atPage(this._pageIndex);
244
+ let pos = models_1.Position.atPage(this._pageNumber);
244
245
  pos.textStartsWith = text;
245
246
  return this._internals.toTextLineObjects(await this._internals.findTextLines(pos));
246
247
  }
247
248
  /**
248
249
  * Creates a new ParagraphBuilder for fluent paragraph construction.
249
250
  */
250
- newParagraph(pageIndex) {
251
- const targetIndex = pageIndex ?? this.position.pageIndex;
251
+ newParagraph(pageNumber) {
252
+ const targetIndex = pageNumber ?? this.position.pageNumber;
252
253
  return new paragraph_builder_1.ParagraphBuilder(this._client, targetIndex);
253
254
  }
254
- newImage(pageIndex) {
255
- const targetIndex = pageIndex ?? this.position.pageIndex;
255
+ newImage(pageNumber) {
256
+ const targetIndex = pageNumber ?? this.position.pageNumber;
256
257
  return new image_builder_1.ImageBuilder(this._client, targetIndex);
257
258
  }
258
- newPath(pageIndex) {
259
- const targetIndex = pageIndex ?? this.position.pageIndex;
259
+ newPath(pageNumber) {
260
+ const targetIndex = pageNumber ?? this.position.pageNumber;
260
261
  return new path_builder_1.PathBuilder(this._client, targetIndex);
261
262
  }
262
263
  async selectTextLines() {
263
- return this._internals.toTextLineObjects(await this._internals.findTextLines(models_1.Position.atPage(this._pageIndex)));
264
+ return this._internals.toTextLineObjects(await this._internals.findTextLines(models_1.Position.atPage(this._pageNumber)));
264
265
  }
265
266
  // noinspection JSUnusedGlobalSymbols
266
267
  async selectTextLinesMatching(pattern) {
267
- let pos = models_1.Position.atPage(this._pageIndex);
268
+ let pos = models_1.Position.atPage(this._pageNumber);
268
269
  pos.textPattern = pattern;
269
270
  return this._internals.toTextLineObjects(await this._internals.findTextLines(pos));
270
271
  }
271
272
  // noinspection JSUnusedGlobalSymbols
272
273
  async selectTextLinesAt(x, y, tolerance = DEFAULT_TOLERANCE) {
273
- return this._internals.toTextLineObjects(await this._internals.findTextLines(models_1.Position.atPageCoordinates(this._pageIndex, x, y, tolerance)));
274
+ return this._internals.toTextLineObjects(await this._internals.findTextLines(models_1.Position.atPageCoordinates(this._pageNumber, x, y, tolerance)));
274
275
  }
275
276
  /**
276
277
  * Gets a snapshot of this page, including all elements.
277
278
  * Optionally filter by object types.
278
279
  */
279
280
  async getSnapshot(types) {
280
- return this._client.getPageSnapshot(this._pageIndex, types);
281
+ return this._client.getPageSnapshot(this._pageNumber, types);
281
282
  }
282
283
  // Singular convenience methods - return the first element or null
283
284
  async selectPath() {
@@ -405,7 +406,18 @@ class PDFDancer {
405
406
  this._sessionId = await this._createSession();
406
407
  return this;
407
408
  }
409
+ /**
410
+ * Opens a PDF document for manipulation.
411
+ *
412
+ * @param pdfData PDF data as Uint8Array (raw bytes) or string (filepath)
413
+ * @param token Authentication token (optional, can use PDFDANCER_TOKEN env var)
414
+ * @param baseUrl Base URL for the PDFDancer API (optional)
415
+ * @param timeout Request timeout in milliseconds (default: 60000)
416
+ * @param retryConfig Retry configuration (optional, uses defaults if not specified)
417
+ * @returns A PDFDancer client instance
418
+ */
408
419
  static async open(pdfData, token, baseUrl, timeout, retryConfig) {
420
+ (0, env_loader_1.loadEnv)();
409
421
  const resolvedBaseUrl = baseUrl ??
410
422
  process.env.PDFDANCER_BASE_URL ??
411
423
  "https://api.pdfdancer.com";
@@ -430,6 +442,7 @@ class PDFDancer {
430
442
  * @param retryConfig Retry configuration (optional, uses defaults if not specified)
431
443
  */
432
444
  static async new(options, token, baseUrl, timeout, retryConfig) {
445
+ (0, env_loader_1.loadEnv)();
433
446
  const resolvedBaseUrl = baseUrl ??
434
447
  process.env.PDFDANCER_BASE_URL ??
435
448
  "https://api.pdfdancer.com";
@@ -539,7 +552,7 @@ class PDFDancer {
539
552
  throw new exceptions_1.ValidationException("PDF data cannot be null");
540
553
  }
541
554
  try {
542
- if (pdfData && pdfData.constructor === Uint8Array) {
555
+ if (pdfData && (pdfData.constructor === Uint8Array || Buffer.isBuffer(pdfData))) {
543
556
  if (pdfData.length === 0) {
544
557
  throw new exceptions_1.ValidationException("PDF data cannot be empty");
545
558
  }
@@ -557,6 +570,7 @@ class PDFDancer {
557
570
  return new Uint8Array(); // Placeholder, will be replaced in _createSession
558
571
  }
559
572
  else if (typeof pdfData === 'string') {
573
+ // TODO why is this different to `instanceof File`?
560
574
  // Handle string as filepath
561
575
  if (!fs_1.default.existsSync(pdfData)) {
562
576
  throw new exceptions_1.ValidationException(`PDF file not found: ${pdfData}`);
@@ -711,7 +725,8 @@ class PDFDancer {
711
725
  'X-Session-Id': this._sessionId,
712
726
  'Content-Type': 'application/json',
713
727
  'X-Generated-At': generateTimestamp(),
714
- 'X-Fingerprint': fingerprint
728
+ 'X-Fingerprint': fingerprint,
729
+ 'X-API-VERSION': '1'
715
730
  };
716
731
  try {
717
732
  const response = await this._fetchWithRetry(url.toString(), {
@@ -771,9 +786,9 @@ class PDFDancer {
771
786
  }
772
787
  // Use snapshot-based search
773
788
  let elements;
774
- if (position?.pageIndex !== undefined) {
789
+ if (position?.pageNumber !== undefined) {
775
790
  // Page-specific query - use page snapshot
776
- const pageSnapshot = await this._getOrFetchPageSnapshot(position.pageIndex);
791
+ const pageSnapshot = await this._getOrFetchPageSnapshot(position.pageNumber);
777
792
  elements = pageSnapshot.elements;
778
793
  }
779
794
  else {
@@ -842,9 +857,9 @@ class PDFDancer {
842
857
  async findFormFields(position) {
843
858
  // Use snapshot-based search
844
859
  let elements;
845
- if (position?.pageIndex !== undefined) {
860
+ if (position?.pageNumber !== undefined) {
846
861
  // Page-specific query - use page snapshot
847
- const pageSnapshot = await this._getOrFetchPageSnapshot(position.pageIndex);
862
+ const pageSnapshot = await this._getOrFetchPageSnapshot(position.pageNumber);
848
863
  elements = pageSnapshot.elements;
849
864
  }
850
865
  else {
@@ -887,68 +902,76 @@ class PDFDancer {
887
902
  * Retrieves a reference to a specific page by its page index.
888
903
  * Now uses snapshot caching to avoid HTTP requests.
889
904
  */
890
- async _getPage(pageIndex) {
891
- if (pageIndex < 0) {
892
- throw new exceptions_1.ValidationException(`Page index must be >= 0, got ${pageIndex}`);
905
+ async _getPage(pageNumber) {
906
+ if (pageNumber < 0) {
907
+ throw new exceptions_1.ValidationException(`Page index must be >= 0, got ${pageNumber}`);
893
908
  }
894
909
  // Try page snapshot cache first
895
- if (this._pageSnapshotCache.has(pageIndex)) {
896
- return this._pageSnapshotCache.get(pageIndex).pageRef;
910
+ if (this._pageSnapshotCache.has(pageNumber)) {
911
+ return this._pageSnapshotCache.get(pageNumber).pageRef;
897
912
  }
898
913
  // Try document snapshot cache
899
914
  if (this._documentSnapshotCache) {
900
- const pageSnapshot = this._documentSnapshotCache.getPageSnapshot(pageIndex);
915
+ const pageSnapshot = this._documentSnapshotCache.getPageSnapshot(pageNumber);
901
916
  if (pageSnapshot) {
902
917
  return pageSnapshot.pageRef;
903
918
  }
904
919
  }
905
920
  // Fetch document snapshot to get page (this will cache it)
906
921
  const docSnapshot = await this._getOrFetchDocumentSnapshot();
907
- const pageSnapshot = docSnapshot.getPageSnapshot(pageIndex);
922
+ const pageSnapshot = docSnapshot.getPageSnapshot(pageNumber);
908
923
  return pageSnapshot?.pageRef ?? null;
909
924
  }
910
925
  /**
911
- * Moves an existing page to a new index.
926
+ * Moves an existing page to a new position.
927
+ *
928
+ * @param fromPage - The source page number (1-based, page 1 is first page)
929
+ * @param toPage - The target page number (1-based)
930
+ * @returns The page reference at the new position
931
+ * @throws ValidationException if fromPage or toPage is less than 1
912
932
  */
913
- async movePage(pageIndex, targetPageIndex) {
914
- this._validatePageIndex(pageIndex, 'pageIndex');
915
- this._validatePageIndex(targetPageIndex, 'targetPageIndex');
933
+ async movePage(fromPage, toPage) {
934
+ this._validatePageNumber(fromPage, 'fromPage');
935
+ this._validatePageNumber(toPage, 'toPage');
916
936
  // Ensure the source page exists before attempting the move
917
- await this._requirePageRef(pageIndex);
918
- const request = new models_1.MovePageRequest(pageIndex, targetPageIndex).toDict();
937
+ await this._requirePageRef(fromPage);
938
+ const request = new models_1.MovePageRequest(fromPage, toPage).toDict();
919
939
  const response = await this._makeRequest('PUT', '/pdf/page/move', request);
920
940
  const success = await response.json();
921
941
  if (!success) {
922
- throw new exceptions_1.HttpClientException(`Failed to move page from ${pageIndex} to ${targetPageIndex}`, response);
942
+ throw new exceptions_1.HttpClientException(`Failed to move page from ${fromPage} to ${toPage}`, response);
923
943
  }
924
944
  // Invalidate cache after mutation
925
945
  this._invalidateCache();
926
946
  // Fetch the page again at its new position for up-to-date metadata
927
- return await this._requirePageRef(targetPageIndex);
947
+ return await this._requirePageRef(toPage);
928
948
  }
929
949
  /**
930
- * Deletes the page at the specified index.
950
+ * Deletes the page at the specified page number.
951
+ *
952
+ * @param pageNumber - The page number to delete (1-based, page 1 is first page)
953
+ * @throws ValidationException if pageNumber is less than 1
931
954
  */
932
- async deletePage(pageIndex) {
933
- this._validatePageIndex(pageIndex, 'pageIndex');
934
- const pageRef = await this._requirePageRef(pageIndex);
955
+ async deletePage(pageNumber) {
956
+ this._validatePageNumber(pageNumber, 'pageNumber');
957
+ const pageRef = await this._requirePageRef(pageNumber);
935
958
  const result = await this._deletePage(pageRef);
936
959
  // Invalidate cache after mutation
937
960
  this._invalidateCache();
938
961
  return result;
939
962
  }
940
- _validatePageIndex(pageIndex, fieldName) {
941
- if (!Number.isInteger(pageIndex)) {
942
- throw new exceptions_1.ValidationException(`${fieldName} must be an integer, got ${pageIndex}`);
963
+ _validatePageNumber(pageNumber, fieldName) {
964
+ if (!Number.isInteger(pageNumber)) {
965
+ throw new exceptions_1.ValidationException(`${fieldName} must be an integer, got ${pageNumber}`);
943
966
  }
944
- if (pageIndex < 0) {
945
- throw new exceptions_1.ValidationException(`${fieldName} must be >= 0, got ${pageIndex}`);
967
+ if (pageNumber < 1) {
968
+ throw new exceptions_1.ValidationException(`${fieldName} must be >= 1 (1-based indexing), got ${pageNumber}`);
946
969
  }
947
970
  }
948
- async _requirePageRef(pageIndex) {
949
- const pageRef = await this._getPage(pageIndex);
971
+ async _requirePageRef(pageNumber) {
972
+ const pageRef = await this._getPage(pageNumber);
950
973
  if (!pageRef) {
951
- throw new exceptions_1.ValidationException(`Page not found at index ${pageIndex}`);
974
+ throw new exceptions_1.ValidationException(`Page not found at page number ${pageNumber}`);
952
975
  }
953
976
  return pageRef;
954
977
  }
@@ -984,17 +1007,18 @@ class PDFDancer {
984
1007
  * Gets a snapshot of a specific page.
985
1008
  * Returns the page reference and all elements on that page.
986
1009
  *
987
- * @param pageIndex Zero-based page index
988
- * @param types Optional array of ObjectType to filter elements by type
1010
+ * @param pageNumber - The page number to retrieve (1-based, page 1 is first page)
1011
+ * @param types - Optional array of ObjectType to filter elements by type
989
1012
  * @returns PageSnapshot containing page information and elements
1013
+ * @throws ValidationException if pageNumber is less than 1
990
1014
  */
991
- async getPageSnapshot(pageIndex, types) {
992
- this._validatePageIndex(pageIndex, 'pageIndex');
1015
+ async getPageSnapshot(pageNumber, types) {
1016
+ this._validatePageNumber(pageNumber, 'pageNumber');
993
1017
  const params = {};
994
1018
  if (types && types.length > 0) {
995
1019
  params.types = types.join(',');
996
1020
  }
997
- const response = await this._makeRequest('GET', `/pdf/page/${pageIndex}/snapshot`, undefined, params);
1021
+ const response = await this._makeRequest('GET', `/pdf/page/${pageNumber}/snapshot`, undefined, params);
998
1022
  const data = await response.json();
999
1023
  return this._parsePageSnapshot(data);
1000
1024
  }
@@ -1002,24 +1026,27 @@ class PDFDancer {
1002
1026
  /**
1003
1027
  * Gets a page snapshot from cache or fetches it.
1004
1028
  * First checks page cache, then document cache, then fetches from server.
1029
+ *
1030
+ * @param pageNumber - 1-based page number
1005
1031
  */
1006
- async _getOrFetchPageSnapshot(pageIndex) {
1032
+ async _getOrFetchPageSnapshot(pageNumber) {
1007
1033
  // Check page cache first
1008
- if (this._pageSnapshotCache.has(pageIndex)) {
1009
- return this._pageSnapshotCache.get(pageIndex);
1034
+ if (this._pageSnapshotCache.has(pageNumber)) {
1035
+ return this._pageSnapshotCache.get(pageNumber);
1010
1036
  }
1011
1037
  // Check if we have document snapshot and can extract the page
1038
+ // Convert 1-based page number to 0-based index for array access
1012
1039
  if (this._documentSnapshotCache) {
1013
- const pageSnapshot = this._documentSnapshotCache.getPageSnapshot(pageIndex);
1040
+ const pageSnapshot = this._documentSnapshotCache.getPageSnapshot(pageNumber);
1014
1041
  if (pageSnapshot) {
1015
1042
  // Cache it for future use
1016
- this._pageSnapshotCache.set(pageIndex, pageSnapshot);
1043
+ this._pageSnapshotCache.set(pageNumber, pageSnapshot);
1017
1044
  return pageSnapshot;
1018
1045
  }
1019
1046
  }
1020
1047
  // Fetch page snapshot from server
1021
- const pageSnapshot = await this.getPageSnapshot(pageIndex);
1022
- this._pageSnapshotCache.set(pageIndex, pageSnapshot);
1048
+ const pageSnapshot = await this.getPageSnapshot(pageNumber);
1049
+ this._pageSnapshotCache.set(pageNumber, pageSnapshot);
1023
1050
  return pageSnapshot;
1024
1051
  }
1025
1052
  /**
@@ -1050,8 +1077,8 @@ class PDFDancer {
1050
1077
  }
1051
1078
  let filtered = elements;
1052
1079
  // Filter by page index
1053
- if (position.pageIndex !== undefined) {
1054
- filtered = filtered.filter(el => el.position.pageIndex === position.pageIndex);
1080
+ if (position.pageNumber !== undefined) {
1081
+ filtered = filtered.filter(el => el.position.pageNumber === position.pageNumber);
1055
1082
  }
1056
1083
  // Filter by coordinates (point containment with tolerance)
1057
1084
  if (position.boundingRect && position.shape === models_1.ShapeType.POINT) {
@@ -1193,11 +1220,11 @@ class PDFDancer {
1193
1220
  if (!paragraph.getPosition()) {
1194
1221
  throw new exceptions_1.ValidationException("Paragraph position is null, you need to specify a position for the new paragraph, using .at(x,y)");
1195
1222
  }
1196
- if (paragraph.getPosition().pageIndex === undefined) {
1197
- throw new exceptions_1.ValidationException("Paragraph position page index is null");
1223
+ if (paragraph.getPosition().pageNumber === undefined) {
1224
+ throw new exceptions_1.ValidationException("Paragraph position page number is null");
1198
1225
  }
1199
- if (paragraph.getPosition().pageIndex < 0) {
1200
- throw new exceptions_1.ValidationException("Paragraph position page index is less than 0");
1226
+ if (paragraph.getPosition().pageNumber < 1) {
1227
+ throw new exceptions_1.ValidationException("Paragraph position page number is less than 1");
1201
1228
  }
1202
1229
  return this._addObject(paragraph);
1203
1230
  }
@@ -1211,11 +1238,11 @@ class PDFDancer {
1211
1238
  if (!path.getPosition()) {
1212
1239
  throw new exceptions_1.ValidationException("Path position is null, you need to specify a position for the new path, using .at(x,y)");
1213
1240
  }
1214
- if (path.getPosition().pageIndex === undefined) {
1215
- throw new exceptions_1.ValidationException("Path position page index is null");
1241
+ if (path.getPosition().pageNumber === undefined) {
1242
+ throw new exceptions_1.ValidationException("Path position page number is null");
1216
1243
  }
1217
- if (path.getPosition().pageIndex < 0) {
1218
- throw new exceptions_1.ValidationException("Path position page index is less than 0");
1244
+ if (path.getPosition().pageNumber < 1) {
1245
+ throw new exceptions_1.ValidationException("Path position page number is less than 1");
1219
1246
  }
1220
1247
  return await this._addObject(path);
1221
1248
  }
@@ -1530,7 +1557,7 @@ class PDFDancer {
1530
1557
  */
1531
1558
  _parsePosition(posData) {
1532
1559
  const position = new models_1.Position();
1533
- position.pageIndex = posData.pageIndex;
1560
+ position.pageNumber = posData.pageNumber;
1534
1561
  position.textStartsWith = posData.textStartsWith;
1535
1562
  if (posData.shape) {
1536
1563
  position.shape = models_1.ShapeType[posData.shape];
@@ -1584,9 +1611,9 @@ class PDFDancer {
1584
1611
  if (Array.isArray(data.elements)) {
1585
1612
  for (const elementData of data.elements) {
1586
1613
  const element = this._parseObjectRef(elementData);
1587
- // If the element's position doesn't have a pageIndex, inherit it from the page
1588
- if (element.position && element.position.pageIndex === undefined) {
1589
- element.position.pageIndex = pageRef.position.pageIndex;
1614
+ // If the element's position doesn't have a pageNumber, inherit it from the page
1615
+ if (element.position && element.position.pageNumber === undefined) {
1616
+ element.position.pageNumber = pageRef.position.pageNumber;
1590
1617
  }
1591
1618
  elements.push(element);
1592
1619
  }
@@ -1603,27 +1630,35 @@ class PDFDancer {
1603
1630
  toImageObjects(objectRefs) {
1604
1631
  return objectRefs.map(ref => types_1.ImageObject.fromRef(this, ref));
1605
1632
  }
1606
- newImage(pageIndex) {
1607
- return new image_builder_1.ImageBuilder(this, pageIndex);
1633
+ newImage(pageNumber) {
1634
+ return new image_builder_1.ImageBuilder(this, pageNumber);
1608
1635
  }
1609
- newParagraph(pageIndex) {
1610
- return new paragraph_builder_1.ParagraphBuilder(this, pageIndex);
1636
+ newParagraph(pageNumber) {
1637
+ return new paragraph_builder_1.ParagraphBuilder(this, pageNumber);
1611
1638
  }
1612
- newPath(pageIndex) {
1613
- return new path_builder_1.PathBuilder(this, pageIndex);
1639
+ newPath(pageNumber) {
1640
+ return new path_builder_1.PathBuilder(this, pageNumber);
1614
1641
  }
1615
1642
  newPage() {
1616
1643
  return new page_builder_1.PageBuilder(this);
1617
1644
  }
1618
- page(pageIndex) {
1619
- if (pageIndex < 0) {
1620
- throw new exceptions_1.ValidationException(`Page index must be >= 0, got ${pageIndex}`);
1645
+ /**
1646
+ * Creates a client for working with a specific page.
1647
+ *
1648
+ * @param pageNumber - The page number (1-based, page 1 is first page)
1649
+ * @returns A PageClient for the specified page
1650
+ * @throws ValidationException if pageNumber is less than 1
1651
+ */
1652
+ page(pageNumber) {
1653
+ if (pageNumber < 1) {
1654
+ throw new exceptions_1.ValidationException(`Page number must be >= 1 (1-based indexing), got ${pageNumber}`);
1621
1655
  }
1622
- return new PageClient(this, pageIndex);
1656
+ return new PageClient(this, pageNumber);
1623
1657
  }
1624
1658
  async pages() {
1625
1659
  const pageRefs = await this.getPages();
1626
- return pageRefs.map((pageRef, pageIndex) => new PageClient(this, pageIndex, pageRef));
1660
+ // Page numbers are 1-based
1661
+ return pageRefs.map((pageRef, index) => new PageClient(this, index + 1, pageRef));
1627
1662
  }
1628
1663
  toFormFields(objectRefs) {
1629
1664
  return objectRefs.map(ref => types_1.FormFieldObject.fromRef(this, ref));