apexify.js 5.0.0 → 5.0.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,137 @@
1
+ # Changelog
2
+
3
+ All notable changes to Apexify.js will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [5.0.0] - 2024-12-20
9
+
10
+ ### 🎉 Major Feature Release - Advanced Image & Canvas Features
11
+
12
+ #### ✨ Added
13
+
14
+ ##### Background Enhancements
15
+ - **Background Image Filters**: Apply filters directly to background images via `customBg.filters`
16
+ - **Background Image Opacity**: Control background image transparency with `customBg.opacity`
17
+ - **Video Backgrounds**: Support for video backgrounds with frame extraction via `videoBg` option
18
+ - Extract specific frames from videos
19
+ - Loop and autoplay support
20
+ - Opacity control for video backgrounds
21
+
22
+ ##### Image Processing Enhancements
23
+ - **Image Masking**: Apply masks to images with multiple modes (`alpha`, `luminance`, `inverse`)
24
+ - **Custom Clip Paths**: Define custom polygon clipping paths for images
25
+ - **Image Distortion**:
26
+ - Perspective distortion with 4-point control
27
+ - Bulge/pinch effects with intensity control
28
+ - Mesh warping with customizable grid control points
29
+ - **Effects Stack**: Professional image effects
30
+ - Vignette effect with intensity and size control
31
+ - Lens flare with position and intensity
32
+ - Chromatic aberration effect
33
+ - Film grain effect
34
+ - **Enhanced Filters**:
35
+ - `filterIntensity` - Global intensity multiplier for all filters
36
+ - `filterOrder` - Control when filters are applied (`pre` or `post` transformation)
37
+
38
+ ##### Text Enhancements
39
+ - **Text on Paths**: Render text along curves and paths
40
+ - Support for line, arc, bezier, and quadratic curve paths
41
+ - Offset control for text distance from path
42
+ - Automatic text distribution along path
43
+
44
+ ##### Custom Lines Enhancements
45
+ - **Advanced Path Options**:
46
+ - Smooth path interpolation with tension control
47
+ - Bezier curve paths
48
+ - Catmull-Rom spline paths
49
+ - Closed path support
50
+ - **Arrow Markers**:
51
+ - Start and end arrows on lines
52
+ - Customizable arrow size and style (filled/outline)
53
+ - Color control for arrows
54
+ - **Path Markers**:
55
+ - Add markers at any position along a path (0-1)
56
+ - Multiple marker shapes: circle, square, diamond, arrow
57
+ - Customizable marker size and color
58
+ - **Line Patterns**:
59
+ - Built-in patterns: dots, dashes, custom segments
60
+ - Pattern offset control
61
+ - **Line Textures**: Apply texture images to lines
62
+
63
+ ##### New Utility Methods
64
+ - **Batch Operations**: `batch()` - Process multiple operations in parallel
65
+ - **Chain Operations**: `chain()` - Chain operations sequentially
66
+ - **Image Stitching**: `stitchImages()` - Stitch multiple images together
67
+ - Horizontal, vertical, and grid layouts
68
+ - Overlap and blend support
69
+ - Spacing control
70
+ - **Collage Maker**: `createCollage()` - Create image collages
71
+ - Grid, masonry, carousel, and custom layouts
72
+ - Automatic spacing and alignment
73
+ - Background and border radius support
74
+ - **Image Compression**: `compress()` - Compress images with quality control
75
+ - Support for JPEG, WebP, and AVIF formats
76
+ - Progressive JPEG support
77
+ - Max width/height constraints
78
+ - **Color Palette Extraction**: `extractPalette()` - Extract color palettes from images
79
+ - Multiple algorithms: k-means, median-cut, octree
80
+ - Customizable color count
81
+ - Multiple output formats: hex, rgb, hsl
82
+ - **Advanced Save Method**: `save()` - Save buffers to local files with extensive customization
83
+ - Multiple file formats: PNG, JPEG, WebP, AVIF, GIF
84
+ - Smart naming patterns: timestamp, counter, or custom
85
+ - Auto-create directories
86
+ - Quality control for JPEG/WebP
87
+ - Prefix/suffix support
88
+ - Overwrite protection with auto-renaming
89
+ - Batch saving with `saveMultiple()`
90
+ - Counter management with `resetSaveCounter()`
91
+
92
+ #### 🔧 Technical Improvements
93
+ - Added comprehensive TypeScript type definitions for all new features
94
+ - Created utility modules for better code organization:
95
+ - `imageMasking.ts` - Image masking and distortion utilities
96
+ - `imageEffects.ts` - Image effects utilities
97
+ - `textPathRenderer.ts` - Text path rendering utilities
98
+ - `advancedLines.ts` - Advanced line drawing utilities
99
+ - `batchOperations.ts` - Batch and chain operation utilities
100
+ - `imageStitching.ts` - Image stitching and collage utilities
101
+ - `imageCompression.ts` - Image compression and palette extraction utilities
102
+ - Enhanced error handling and validation
103
+ - Improved type safety across all new features
104
+
105
+ #### 📚 Documentation
106
+ - Updated README with new features
107
+ - Added comprehensive examples for all new features
108
+ - Enhanced API documentation
109
+
110
+ ---
111
+
112
+ ## [4.9.28] - Previous Release
113
+
114
+ ### Features
115
+ - Enhanced text renderer with decorations
116
+ - Professional pattern system
117
+ - Advanced gradient support
118
+ - Comprehensive shape drawing
119
+ - Chart generation capabilities
120
+ - GIF creation support
121
+
122
+ ---
123
+
124
+ ## [4.9.0] - Initial Major Release
125
+
126
+ ### Features
127
+ - Core canvas creation
128
+ - Image and shape drawing
129
+ - Text rendering
130
+ - Basic filters and effects
131
+ - Format conversion
132
+ - Background removal
133
+
134
+ ---
135
+
136
+ For a complete list of changes, please refer to the [GitHub repository](https://github.com/zenith-79/apexify.js).
137
+
package/README.md CHANGED
@@ -6,7 +6,8 @@
6
6
 
7
7
  **The Ultimate TypeScript Canvas Library for Node.js**
8
8
 
9
- [![npm version](https://badge.fury.io/js/apexify.svg)](https://badge.fury.io/js/apexify)
9
+ [![npm version](https://badge.fury.io/js/apexify.js.svg)](https://badge.fury.io/js/apexify.js)
10
+ [![npm downloads](https://img.shields.io/npm/dt/apexify.js.svg)](https://www.npmjs.com/package/apexify.js)
10
11
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
11
12
  [![Node.js](https://img.shields.io/badge/Node.js-16%2B-green.svg)](https://nodejs.org/)
12
13
  [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
@@ -64,6 +65,7 @@
64
65
  - **Color Detection**: Extract and analyze colors from images
65
66
  - **Batch Operations**: Process multiple operations in parallel
66
67
  - **Chain Operations**: Chain operations sequentially for complex workflows
68
+ - **Advanced File Saving**: Save buffers to local files with smart naming, format conversion, and batch support
67
69
 
68
70
  ---
69
71
 
@@ -168,10 +170,64 @@ const textImage = await painter.createText({
168
170
  }
169
171
  }, heartImage);
170
172
 
171
- // Save the result
172
- fs.writeFileSync('beautiful-artwork.png', textImage);
173
+ // Save the result using the advanced save method
174
+ const saveResult = await painter.save(textImage, {
175
+ directory: './output',
176
+ filename: 'beautiful-artwork',
177
+ format: 'png'
178
+ });
179
+ console.log(`Saved to: ${saveResult.path} (${saveResult.size} bytes)`);
180
+
181
+ // Or use the simple approach (auto-generated filename)
182
+ const autoSave = await painter.save(textImage);
183
+ // Saves to: ./ApexPainter_output/20241220_143025_123.png
173
184
  ```
174
185
 
186
+ ### 💾 **Advanced Save Method**
187
+
188
+ The `save()` method provides powerful file saving capabilities with extensive customization:
189
+
190
+ ```typescript
191
+ // Simple save with auto-generated timestamp name
192
+ const canvas = await painter.createCanvas({ width: 800, height: 600 });
193
+ const result = await painter.save(canvas.buffer);
194
+ // Saves to: ./ApexPainter_output/20241220_143025_123.png
195
+
196
+ // Custom filename and directory
197
+ await painter.save(canvas.buffer, {
198
+ directory: './my-images',
199
+ filename: 'my-canvas',
200
+ format: 'jpg',
201
+ quality: 95
202
+ });
203
+
204
+ // Save with counter naming
205
+ await painter.save(canvas.buffer, {
206
+ naming: 'counter',
207
+ prefix: 'image-',
208
+ counterStart: 1
209
+ });
210
+ // Saves to: ./ApexPainter_output/image-1.png, image-2.png, etc.
211
+
212
+ // Save multiple buffers in batch
213
+ const buffers = [canvas1.buffer, canvas2.buffer, canvas3.buffer];
214
+ const results = await painter.saveMultiple(buffers, {
215
+ prefix: 'batch-',
216
+ naming: 'counter'
217
+ });
218
+ // Saves: batch-1.png, batch-2.png, batch-3.png
219
+ ```
220
+
221
+ **Save Options:**
222
+ - `directory` - Output directory (default: `./ApexPainter_output`)
223
+ - `filename` - Custom filename (auto-generated if not provided)
224
+ - `format` - File format: `png`, `jpg`, `jpeg`, `webp`, `avif`, `gif` (default: `png`)
225
+ - `quality` - Quality for JPEG/WebP (0-100, default: 90)
226
+ - `naming` - Naming pattern: `timestamp`, `counter`, or `custom` (default: `timestamp`)
227
+ - `prefix` / `suffix` - Add prefix/suffix to filenames
228
+ - `overwrite` - Overwrite existing files (default: `false`, auto-renames if exists)
229
+ - `createDirectory` - Auto-create directory if missing (default: `true`)
230
+
175
231
  ### 📝 **Flexible Array Support**
176
232
 
177
233
  Both `createImage()` and `createText()` methods accept **single objects** OR **arrays of objects**:
@@ -583,6 +639,9 @@ const buttonText = await painter.createText({
583
639
  | `createText()` | Add text to canvas | `TextProperties \| TextProperties[]` |
584
640
  | `createChart()` | Generate charts | `ChartConfig` |
585
641
  | `createGIF()` | Create animated GIFs | `GIFConfig` |
642
+ | `save()` | Save buffer to local file with advanced options | `Buffer, SaveOptions?` |
643
+ | `saveMultiple()` | Save multiple buffers in batch | `Buffer[], SaveOptions?` |
644
+ | `resetSaveCounter()` | Reset the save counter for naming | `void` |
586
645
 
587
646
  ### 🔄 **Flexible Parameters**
588
647
 
@@ -652,6 +711,7 @@ This allows you to add multiple elements in one call for better performance and
652
711
  - 🎨 **Collage Maker**: Create beautiful image collages
653
712
  - 📦 **Image Compression**: Optimize images with quality control
654
713
  - 🎨 **Color Palette Extraction**: Extract color palettes from images
714
+ - 💾 **Advanced Save Method**: Save buffers to files with smart naming, format conversion, and batch support
655
715
 
656
716
  See [CHANGELOG.md](CHANGELOG.md) for complete details.
657
717
 
Binary file
@@ -1,5 +1,5 @@
1
1
  import { PathLike } from "fs";
2
- import { OutputFormat, CanvasConfig, TextProperties, ImageProperties, GIFOptions, GIFResults, CustomOptions, cropOptions, GradientConfig, Frame, ExtractFramesOptions, ResizeOptions, MaskOptions, BlendOptions, ImageFilter, BatchOperation, ChainOperation, StitchOptions, CollageLayout, CompressionOptions, PaletteOptions } from "./utils/utils";
2
+ import { OutputFormat, CanvasConfig, TextProperties, ImageProperties, GIFOptions, GIFResults, CustomOptions, cropOptions, GradientConfig, Frame, ExtractFramesOptions, ResizeOptions, MaskOptions, BlendOptions, ImageFilter, BatchOperation, ChainOperation, StitchOptions, CollageLayout, CompressionOptions, PaletteOptions, SaveOptions, SaveResult } from "./utils/utils";
3
3
  interface CanvasResults {
4
4
  buffer: Buffer;
5
5
  canvas: CanvasConfig;
@@ -7,6 +7,7 @@ interface CanvasResults {
7
7
  export declare class ApexPainter {
8
8
  #private;
9
9
  private format?;
10
+ private saveCounter;
10
11
  constructor({ type }?: OutputFormat);
11
12
  createCanvas(canvas: CanvasConfig): Promise<CanvasResults>;
12
13
  createImage(images: ImageProperties | ImageProperties[], canvasBuffer: CanvasResults | Buffer): Promise<Buffer>;
@@ -135,6 +136,67 @@ export declare class ApexPainter {
135
136
  * ```
136
137
  */
137
138
  outPut(results: Buffer): Promise<Buffer | string | Blob | ArrayBuffer>;
139
+ /**
140
+ * Advanced save method to save buffers to local files with extensive customization options.
141
+ *
142
+ * @param buffer - Buffer to save (from createCanvas, createImage, createText, etc.)
143
+ * @param options - Save options for file path, format, naming, etc.
144
+ * @returns SaveResult with file path, name, size, and format
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * // Simple save with auto-generated name
149
+ * const canvas = await painter.createCanvas({ width: 800, height: 600 });
150
+ * const result = await painter.save(canvas.buffer);
151
+ * // Saves to: ./ApexPainter_output/20241220_143025_123.png
152
+ *
153
+ * // Custom filename and directory
154
+ * await painter.save(canvas.buffer, {
155
+ * directory: './my-images',
156
+ * filename: 'my-canvas',
157
+ * format: 'jpg',
158
+ * quality: 95
159
+ * });
160
+ *
161
+ * // Save with counter naming
162
+ * await painter.save(canvas.buffer, {
163
+ * naming: 'counter',
164
+ * prefix: 'image-',
165
+ * counterStart: 1
166
+ * });
167
+ * // Saves to: ./ApexPainter_output/image-1.png, image-2.png, etc.
168
+ *
169
+ * // Save multiple buffers
170
+ * const buffers = [canvas1.buffer, canvas2.buffer, canvas3.buffer];
171
+ * const results = await painter.saveMultiple(buffers, {
172
+ * prefix: 'batch-',
173
+ * naming: 'counter'
174
+ * });
175
+ * ```
176
+ */
177
+ save(buffer: Buffer, options?: SaveOptions): Promise<SaveResult>;
178
+ /**
179
+ * Save multiple buffers at once with batch options.
180
+ *
181
+ * @param buffers - Array of buffers to save
182
+ * @param options - Save options (applied to all files)
183
+ * @returns Array of SaveResult objects
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * const canvas1 = await painter.createCanvas({ width: 800, height: 600 });
188
+ * const canvas2 = await painter.createCanvas({ width: 800, height: 600 });
189
+ * const results = await painter.saveMultiple([canvas1.buffer, canvas2.buffer], {
190
+ * prefix: 'batch-',
191
+ * naming: 'counter'
192
+ * });
193
+ * ```
194
+ */
195
+ saveMultiple(buffers: Buffer[], options?: SaveOptions): Promise<SaveResult[]>;
196
+ /**
197
+ * Reset the save counter (useful when using 'counter' naming).
198
+ */
199
+ resetSaveCounter(): void;
138
200
  }
139
201
  export {};
140
202
  //# sourceMappingURL=ApexPainter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApexPainter.d.ts","sourceRoot":"","sources":["../../../lib/Canvas/ApexPainter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ApexPainter.d.ts","sourceRoot":"","sources":["../../../lib/Canvas/ApexPainter.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,7 @@ const enhancedTextRenderer_1 = require("./utils/Texts/enhancedTextRenderer");
16
16
  const enhancedPatternRenderer_1 = require("./utils/Patterns/enhancedPatternRenderer");
17
17
  class ApexPainter {
18
18
  format;
19
+ saveCounter = 1;
19
20
  constructor({ type } = { type: 'buffer' }) {
20
21
  this.format = { type: type || 'buffer' };
21
22
  }
@@ -1849,6 +1850,201 @@ class ApexPainter {
1849
1850
  throw new Error(`outPut failed: ${errorMessage}`);
1850
1851
  }
1851
1852
  }
1853
+ /**
1854
+ * Advanced save method to save buffers to local files with extensive customization options.
1855
+ *
1856
+ * @param buffer - Buffer to save (from createCanvas, createImage, createText, etc.)
1857
+ * @param options - Save options for file path, format, naming, etc.
1858
+ * @returns SaveResult with file path, name, size, and format
1859
+ *
1860
+ * @example
1861
+ * ```typescript
1862
+ * // Simple save with auto-generated name
1863
+ * const canvas = await painter.createCanvas({ width: 800, height: 600 });
1864
+ * const result = await painter.save(canvas.buffer);
1865
+ * // Saves to: ./ApexPainter_output/20241220_143025_123.png
1866
+ *
1867
+ * // Custom filename and directory
1868
+ * await painter.save(canvas.buffer, {
1869
+ * directory: './my-images',
1870
+ * filename: 'my-canvas',
1871
+ * format: 'jpg',
1872
+ * quality: 95
1873
+ * });
1874
+ *
1875
+ * // Save with counter naming
1876
+ * await painter.save(canvas.buffer, {
1877
+ * naming: 'counter',
1878
+ * prefix: 'image-',
1879
+ * counterStart: 1
1880
+ * });
1881
+ * // Saves to: ./ApexPainter_output/image-1.png, image-2.png, etc.
1882
+ *
1883
+ * // Save multiple buffers
1884
+ * const buffers = [canvas1.buffer, canvas2.buffer, canvas3.buffer];
1885
+ * const results = await painter.saveMultiple(buffers, {
1886
+ * prefix: 'batch-',
1887
+ * naming: 'counter'
1888
+ * });
1889
+ * ```
1890
+ */
1891
+ async save(buffer, options) {
1892
+ try {
1893
+ if (!Buffer.isBuffer(buffer)) {
1894
+ throw new Error("save: buffer must be a Buffer.");
1895
+ }
1896
+ const opts = {
1897
+ directory: options?.directory ?? './ApexPainter_output',
1898
+ filename: options?.filename,
1899
+ format: options?.format ?? 'png',
1900
+ quality: options?.quality ?? 90,
1901
+ createDirectory: options?.createDirectory ?? true,
1902
+ naming: options?.naming ?? 'timestamp',
1903
+ counterStart: options?.counterStart ?? 1,
1904
+ prefix: options?.prefix ?? '',
1905
+ suffix: options?.suffix ?? '',
1906
+ overwrite: options?.overwrite ?? false
1907
+ };
1908
+ // Create directory if needed
1909
+ if (opts.createDirectory && !fs_1.default.existsSync(opts.directory)) {
1910
+ fs_1.default.mkdirSync(opts.directory, { recursive: true });
1911
+ }
1912
+ // Generate filename
1913
+ let filename;
1914
+ if (opts.filename) {
1915
+ filename = opts.filename;
1916
+ // Add extension if not present
1917
+ if (!filename.includes('.')) {
1918
+ filename += `.${opts.format}`;
1919
+ }
1920
+ }
1921
+ else {
1922
+ // Auto-generate filename based on naming pattern
1923
+ switch (opts.naming) {
1924
+ case 'timestamp':
1925
+ const now = new Date();
1926
+ const timestamp = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}_${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}_${String(now.getMilliseconds()).padStart(3, '0')}`;
1927
+ filename = `${opts.prefix}${timestamp}${opts.suffix}.${opts.format}`;
1928
+ break;
1929
+ case 'counter':
1930
+ filename = `${opts.prefix}${this.saveCounter}${opts.suffix}.${opts.format}`;
1931
+ this.saveCounter++;
1932
+ break;
1933
+ case 'custom':
1934
+ filename = `${opts.prefix}${opts.suffix}.${opts.format}`;
1935
+ break;
1936
+ default:
1937
+ filename = `${opts.prefix}${Date.now()}${opts.suffix}.${opts.format}`;
1938
+ }
1939
+ }
1940
+ // Handle file overwrite
1941
+ const filePath = path_1.default.join(opts.directory, filename);
1942
+ if (!opts.overwrite && fs_1.default.existsSync(filePath)) {
1943
+ // Add number suffix if file exists
1944
+ let counter = 1;
1945
+ let newPath = filePath;
1946
+ const ext = path_1.default.extname(filePath);
1947
+ const baseName = path_1.default.basename(filePath, ext);
1948
+ const dir = path_1.default.dirname(filePath);
1949
+ while (fs_1.default.existsSync(newPath)) {
1950
+ newPath = path_1.default.join(dir, `${baseName}_${counter}${ext}`);
1951
+ counter++;
1952
+ }
1953
+ filename = path_1.default.basename(newPath);
1954
+ }
1955
+ // Convert buffer format if needed
1956
+ let finalBuffer = buffer;
1957
+ if (opts.format !== 'png') {
1958
+ // Use Sharp for format conversion
1959
+ const sharp = require('sharp');
1960
+ let sharpImage = sharp(buffer);
1961
+ switch (opts.format) {
1962
+ case 'jpg':
1963
+ case 'jpeg':
1964
+ finalBuffer = await sharpImage
1965
+ .jpeg({ quality: opts.quality, progressive: false })
1966
+ .toBuffer();
1967
+ break;
1968
+ case 'webp':
1969
+ finalBuffer = await sharpImage
1970
+ .webp({ quality: opts.quality })
1971
+ .toBuffer();
1972
+ break;
1973
+ case 'avif':
1974
+ finalBuffer = await sharpImage
1975
+ .avif({ quality: opts.quality })
1976
+ .toBuffer();
1977
+ break;
1978
+ case 'gif':
1979
+ // GIF requires special handling - keep as PNG if not already GIF
1980
+ if (!buffer.toString('ascii', 0, 3).includes('GIF')) {
1981
+ console.warn('save: Converting to GIF may not preserve quality. Consider using PNG.');
1982
+ finalBuffer = buffer; // Keep original for now
1983
+ }
1984
+ break;
1985
+ }
1986
+ }
1987
+ // Write file
1988
+ const finalPath = path_1.default.join(opts.directory, filename);
1989
+ fs_1.default.writeFileSync(finalPath, finalBuffer);
1990
+ return {
1991
+ path: finalPath,
1992
+ filename: filename,
1993
+ size: finalBuffer.length,
1994
+ format: opts.format
1995
+ };
1996
+ }
1997
+ catch (error) {
1998
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
1999
+ throw new Error(`save failed: ${errorMessage}`);
2000
+ }
2001
+ }
2002
+ /**
2003
+ * Save multiple buffers at once with batch options.
2004
+ *
2005
+ * @param buffers - Array of buffers to save
2006
+ * @param options - Save options (applied to all files)
2007
+ * @returns Array of SaveResult objects
2008
+ *
2009
+ * @example
2010
+ * ```typescript
2011
+ * const canvas1 = await painter.createCanvas({ width: 800, height: 600 });
2012
+ * const canvas2 = await painter.createCanvas({ width: 800, height: 600 });
2013
+ * const results = await painter.saveMultiple([canvas1.buffer, canvas2.buffer], {
2014
+ * prefix: 'batch-',
2015
+ * naming: 'counter'
2016
+ * });
2017
+ * ```
2018
+ */
2019
+ async saveMultiple(buffers, options) {
2020
+ try {
2021
+ if (!Array.isArray(buffers) || buffers.length === 0) {
2022
+ throw new Error("saveMultiple: buffers must be a non-empty array.");
2023
+ }
2024
+ const results = [];
2025
+ const baseCounter = options?.counterStart ?? this.saveCounter;
2026
+ for (let i = 0; i < buffers.length; i++) {
2027
+ const bufferOptions = {
2028
+ ...options,
2029
+ counterStart: baseCounter + i,
2030
+ naming: options?.naming === 'counter' ? 'counter' : options?.naming
2031
+ };
2032
+ const result = await this.save(buffers[i], bufferOptions);
2033
+ results.push(result);
2034
+ }
2035
+ return results;
2036
+ }
2037
+ catch (error) {
2038
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
2039
+ throw new Error(`saveMultiple failed: ${errorMessage}`);
2040
+ }
2041
+ }
2042
+ /**
2043
+ * Reset the save counter (useful when using 'counter' naming).
2044
+ */
2045
+ resetSaveCounter() {
2046
+ this.saveCounter = 1;
2047
+ }
1852
2048
  /**
1853
2049
  * Applies stroke style to shape context
1854
2050
  * @private