@remotex-labs/xmap 2.0.3 → 2.1.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.
@@ -7,227 +7,311 @@ import type { MapType, SegmentInterface } from './interfaces/mapping.interface';
7
7
  */
8
8
  import { Bias } from './interfaces/mapping.interface';
9
9
  /**
10
- * The `MappingProvider` class provides methods to encode and decode mappings
11
- * from a source map or mapping string to an internal structured representation.
10
+ * Provides functionality for encoding and decoding source map mappings.
11
+ *
12
+ * The MappingProvider class handles the conversion between various mapping representations:
13
+ * - String format (VLQ-encoded mappings)
14
+ * - Structured array format (MapType)
15
+ * - Internal structured representation
16
+ *
17
+ * It also provides methods to query and retrieve source map segments based on
18
+ * generated or original source positions.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // Create from VLQ-encoded mapping string
23
+ * const provider = new MappingProvider(mappingString);
24
+ *
25
+ * // Get a segment by generated position
26
+ * const segment = provider.getSegment(10, 15);
27
+ *
28
+ * // Convert back to mapping string
29
+ * const encoded = provider.encode();
30
+ * ```
31
+ *
32
+ * @since 1.0.0
12
33
  */
13
34
  export declare class MappingProvider {
14
- /**
15
- * The internal mapping representation, where each index represents a frame of segments.
16
- */
17
35
  private mapping;
18
36
  /**
19
- * Constructor to initialize the `MappingProvider` with a mapping.
20
- * Can be initialized with either a mapping string or a structured mapping array.
21
- *
22
- * @param mapping - The mapping data, either as a string or structured array.
23
- * @param namesOffset - Optional offset for the names index.
24
- * @param sourceOffset - Optional offset for the sources index.
25
- *
26
- * @example
27
- * ```ts
28
- * const provider = new MappingProvider(";;;AAiBO,SAAS,OAAO;AACnB,UAAQ,IAAI,MAAM;AACtB;;;ACjBA,QAAQ,IAAI,GAAG;AACf,KAAK;", 0, 0);
29
- * const provider2 = new MappingProvider([
30
- * null,
31
- * [
32
- * {
33
- * line: 1,
34
- * column: 1,
35
- * nameIndex: null,
36
- * sourceIndex: 0,
37
- * generatedLine: 2,
38
- * generatedColumn: 1
39
- * }
40
- * ],
41
- * null
42
- * ], 0, 0);
43
- * ```
37
+ * Creates a new MappingProvider instance.
38
+ *
39
+ * @param mapping - Source map mapping data in one of three formats:
40
+ * - VLQ-encoded string
41
+ * - Structured array (MapType)
42
+ * - Another MappingProvider instance (copy constructor)
43
+ * @param namesOffset - Optional offset to apply to name indices (default: 0)
44
+ * @param sourceOffset - Optional offset to apply to source indices (default: 0)
45
+ *
46
+ * @remarks
47
+ * The constructor automatically detects the mapping format and decodes it accordingly.
48
+ * When providing offsets, these values will be added to the corresponding indices
49
+ * in the decoded mapping data, which is useful when concatenating multiple source maps.
50
+ *
51
+ * @since 1.0.0
44
52
  */
45
53
  constructor(mapping: string, namesOffset?: number, sourceOffset?: number);
46
54
  constructor(mapping: MapType, namesOffset?: number, sourceOffset?: number);
47
55
  constructor(mapping: MappingProvider, namesOffset?: number, sourceOffset?: number);
48
56
  /**
49
- * Encodes the internal mapping array back into a mapping string.
50
- *
51
- * @returns {string} - The encoded mapping string.
52
- * @example
53
- * ```ts
54
- * const encoded = provider.encode();
55
- * console.log(encoded); // Outputs encoded mapping string
56
- * ```
57
+ * Encodes the internal mapping representation to a VLQ-encoded mapping string.
58
+ *
59
+ * @returns VLQ-encoded mapping string compatible with the source map format specification
60
+ *
61
+ * @remarks
62
+ * This method converts the internal structured mapping representation into a compact
63
+ * string format using Variable Length Quantity (VLQ) encoding.
64
+ * The resulting string follows the source map v3 format for the 'mappings' field.
65
+ *
66
+ * @see https://sourcemaps.info/spec.html
67
+ *
68
+ * @since 1.0.0
57
69
  */
58
70
  encode(): string;
59
71
  /**
60
- * Decodes a mapping from either a string or structured array into the internal mapping.
61
- *
62
- * @param mapping - The mapping data to decode.
63
- * @param namesOffset - Offset for the names index.
64
- * @param sourcesOffset - Offset for the sources index.
65
- * @example
66
- * ```ts
67
- * provider.decode(";;;AAiBO,SAAS,OAAO;AACnB,UAAQ,IAAI,MAAM;AACtB;;;ACjBA,QAAQ,IAAI,GAAG;AACf,KAAK;", 0, 0);
68
- * provider.decode([
69
- * null,
70
- * [
71
- * {
72
- * line: 1,
73
- * column: 1,
74
- * nameIndex: null,
75
- * sourceIndex: 0,
76
- * generatedLine: 2,
77
- * generatedColumn: 1
78
- * }
79
- * ],
80
- * null
81
- * ], 0, 0);
82
- * ```
72
+ * Decodes mapping data into the internal representation.
73
+ *
74
+ * @param mapping - Mapping data to decode in one of three formats:
75
+ * - VLQ-encoded string
76
+ * - Structured array (MapType)
77
+ * - Another MappingProvider instance
78
+ * @param namesOffset - Optional offset for name indices (default: 0)
79
+ * @param sourcesOffset - Optional offset for source indices (default: 0)
80
+ *
81
+ * @remarks
82
+ * This method replaces the current internal mapping data with the newly decoded mapping.
83
+ * The format of the input mapping is automatically detected and processed accordingly.
84
+ *
85
+ * @see MapType
86
+ * @see MappingProvider
87
+ *
88
+ * @since 1.0.0
83
89
  */
84
90
  decode(mapping: MappingProvider | MapType | string, namesOffset?: number, sourcesOffset?: number): void;
85
91
  /**
86
- * Retrieves a segment based on the provided generated line and column,
87
- * applying the specified bias when the exact match is not found.
88
- *
89
- * This method performs a binary search on the segments of the specified
90
- * generated line to efficiently locate the segment corresponding to
91
- * the provided generated column. If an exact match is not found,
92
- * the method returns the closest segment based on the specified bias:
93
- * - `Bias.BOUND`: No preference for column matching (returns the closest segment).
94
- * - `Bias.LOWER_BOUND`: Prefers the closest mapping with a lower column value.
95
- * - `Bias.UPPER_BOUND`: Prefers the closest mapping with a higher column value.
96
- *
97
- * @param generatedLine - The line number of the generated code (1-based index).
98
- * @param generatedColumn - The column number of the generated code (0-based index).
99
- * @param bias - The bias to use when the line matches, can be one of:
100
- * - `Bias.BOUND` (default): No preference for column matching.
101
- * - `Bias.LOWER_BOUND`: Prefer the closest mapping with a lower column value.
102
- * - `Bias.UPPER_BOUND`: Prefer the closest mapping with a higher column value.
103
- * @returns The matching segment if found;
104
- * returns null if no segments exist for the specified generated line
105
- * or if the generated line is out of bounds.
106
- *
107
- * @throws { Error } - Throws an error if the generated line is invalid
108
- * (out of bounds).
109
- *
110
- * @example
111
- * ```ts
112
- * const segment = sourceMap.getSegment(5, 10, Bias.UPPER_BOUND);
113
- * if (segment) {
114
- * console.log(`Found segment: line ${segment.line}, column ${segment.column}`);
115
- * } else {
116
- * console.log('No matching segment found.');
117
- * }
118
- * ```
92
+ * Retrieves a segment based on a position in the generated code.
93
+ *
94
+ * @param generatedLine - Line number in generated code (1-based)
95
+ * @param generatedColumn - Column number in generated code (0-based)
96
+ * @param bias - Controls matching behavior when exact position not found:
97
+ * - BOUND: No preference (default)
98
+ * - LOWER_BOUND: Prefer segment with lower column
99
+ * - UPPER_BOUND: Prefer segment with higher column
100
+ * @returns Matching segment or null if not found
101
+ *
102
+ * @remarks
103
+ * Uses binary search to efficiently locate matching segments.
104
+ * When no exact match is found, the bias parameter determines which nearby segment to return.
105
+ *
106
+ * @since 1.0.0
119
107
  */
120
108
  getSegment(generatedLine: number, generatedColumn: number, bias?: Bias): SegmentInterface | null;
121
109
  /**
122
- * Retrieves the original segment based on the provided line, column, and source index.
123
- *
124
- * This method searches for the original segment that corresponds to the specified
125
- * line, column, and source index. It uses binary search to find the closest segment
126
- * based on the provided bias.
127
- *
128
- * @param line - The line number of the original code (1-based index).
129
- * @param column - The column number of the original code (0-based index).
130
- * @param sourceIndex - The index of the source file in the source map.
131
- * @param bias - The bias to apply when multiple segments match; defaults to `Bias.BOUND`.
132
- * @returns {SegmentInterface | null} - The matching original segment if found;
133
- * returns null if no segments exist for the specified line and source index.
134
- *
135
- * @example
136
- * ```ts
137
- * const originalSegment = sourceMap.getOriginalSegment(3, 5, 0, Bias.LOWER_BOUND);
138
- * if (originalSegment) {
139
- * console.log(`Found original segment: line ${originalSegment.line}, column ${originalSegment.column}`);
140
- * } else {
141
- * console.log('No matching original segment found.');
142
- * }
143
- * ```
110
+ * Retrieves a segment based on a position in the original source code.
111
+ *
112
+ * @param line - Line number in original source (1-based)
113
+ * @param column - Column number in original source (0-based)
114
+ * @param sourceIndex - Index of source file in the sources array
115
+ * @param bias - Controls matching behavior when exact position not found:
116
+ * - BOUND: No preference (default)
117
+ * - LOWER_BOUND: Prefer segment with lower column
118
+ * - UPPER_BOUND: Prefer segment with higher column
119
+ * @returns Matching segment or null if not found
120
+ *
121
+ * @remarks
122
+ * Searches across all mapping segments to find those matching the specified original source position.
123
+ * When multiple matches are possible, the bias
124
+ * parameter determines which segment to return.
125
+ *
126
+ * This operation is more expensive than getSegment as it must potentially
127
+ * scan the entire mapping structure.
128
+ *
129
+ * @since 1.0.0
144
130
  */
145
131
  getOriginalSegment(line: number, column: number, sourceIndex: number, bias?: Bias): SegmentInterface | null;
146
132
  /**
147
- * Initializes the segment offsets used to track the current decoding position.
133
+ * Initializes a new segment offset object with default values.
134
+ *
135
+ * @param namesOffset - Initial name index offset value (default: 0)
136
+ * @param sourceIndex - Initial source index offset value (default: 0)
137
+ * @returns A new segment offset object with initialized position tracking values
148
138
  *
149
- * @param namesOffset - The offset for the names index.
150
- * @param sourceIndex - The offset for the source index.
151
- * @returns { SegmentOffsetInterface } - The initialized segment offset.
139
+ * @remarks
140
+ * This method creates an object that tracks position data during mapping operations.
141
+ * All position values (line, column, generatedLine, generatedColumn) are initialized to 0,
142
+ * while the nameIndex and sourceIndex can be initialized with custom offsets.
143
+ *
144
+ * @since 1.0.0
152
145
  */
153
146
  private initPositionOffsets;
154
147
  /**
155
148
  * Validates the format of an encoded mapping string.
156
149
  *
157
- * @param encodedSourceMap - The encoded source map string to validate.
158
- * @returns Returns `true` if the format is valid, otherwise `false`.
150
+ * @param encodedSourceMap - The encoded source map string to validate
151
+ * @returns `true` if the string contains only valid VLQ mapping characters, otherwise `false`
152
+ *
153
+ * @remarks
154
+ * Checks if the string contains only characters valid in source map mappings:
155
+ * - Base64 characters (a-z, A-Z, 0-9, +, /)
156
+ * - Separators (commas for segments, semicolons for lines)
157
+ *
158
+ * This is a basic format validation and doesn't verify the semantic correctness
159
+ * of the VLQ encoding itself.
160
+ *
161
+ * @since 1.0.0
159
162
  */
160
163
  private validateMappingString;
161
164
  /**
162
- * Validates the properties of a segment to ensure they conform to expected types.
163
- *
164
- * This method checks that the segment's properties are finite numbers and that
165
- * the nameIndex, if provided, is either a finite number or null.
166
- * An error is thrown if any of the properties do not meet the specified criteria.
167
- *
168
- * @param segment - The segment object to validate, which must conform to the
169
- * SegmentInterface structure, including:
170
- * - line: number (finite)
171
- * - column: number (finite)
172
- * - nameIndex: number | null (if not null, must be finite)
173
- * - sourceIndex: number (finite)
174
- * - generatedLine: number (finite)
175
- * - generatedColumn: number (finite)
176
- *
177
- * @throws {Error} - Throws an error if any property of the segment is invalid.
178
- * The error message will specify which property is invalid
179
- * and the value that was received.
165
+ * Validates that a segment's properties conform to expected types.
166
+ *
167
+ * @param segment - The segment object to validate
168
+ *
169
+ * @remarks
170
+ * Performs the following validations on the segment properties:
171
+ * - line: Must be a finite number
172
+ * - column: Must be a finite number
173
+ * - nameIndex: Must be either null or a finite number
174
+ * - sourceIndex: Must be a finite number
175
+ * - generatedLine: Must be a finite number
176
+ * - generatedColumn: Must be a finite number
177
+ *
178
+ * This validation ensures that segments can be safely used in mapping operations
179
+ * and prevents potential issues with non-numeric or infinite values.
180
+ *
181
+ * @throws Error - When any property of the segment is invalid, with a message
182
+ * indicating which property failed validation and its value
183
+ *
184
+ * @since 1.0.0
180
185
  */
181
186
  private validateSegment;
182
187
  /**
183
- * Encodes a segment into a VLQ-encoded string based on the segment offsets.
188
+ * Encodes a segment into a VLQ-encoded string based on relative offsets.
184
189
  *
185
- * @param segmentOffset - The current segment offset.
186
- * @param segmentObject - The segment to encode.
187
- * @returns The encoded segment string.
190
+ * @param segmentOffset - The current segment offset tracking state
191
+ * @param segmentObject - The segment to encode
192
+ * @returns A VLQ-encoded string representation of the segment
193
+ *
194
+ * @remarks
195
+ * The encoding process:
196
+ * 1. Adjusts line and column values (subtracts 1 to convert from 1-based to 0-based)
197
+ * 2. Calculates relative differences between current values and previous offsets
198
+ * 3. Creates an array with the following components:
199
+ * - generatedColumn difference
200
+ * - sourceIndex difference (0 if unchanged)
201
+ * - line difference
202
+ * - column difference
203
+ * - nameIndex difference (only if nameIndex is present)
204
+ * 4. Updates the segment offset state for the next encoding
205
+ * 5. Returns the array as a VLQ-encoded string
206
+ *
207
+ * This method implements the source map V3 specification's delta encoding scheme
208
+ * where values are stored as differences from previous positions.
209
+ *
210
+ * @since 1.0.0
188
211
  */
189
212
  private encodeSegment;
190
213
  /**
191
- * Encodes the entire mapping array into a VLQ-encoded mapping string.
214
+ * Encodes a mapping array into a VLQ-encoded mapping string following the source map V3 spec.
215
+ *
216
+ * @param map - The mapping array to encode, organized by generated lines and segments
217
+ * @returns A complete VLQ-encoded mapping string with line and segment separators
218
+ *
219
+ * @remarks
220
+ * The encoding process:
221
+ * 1. Initializes position offsets to track state across the entire mapping
222
+ * 2. Processes each frame (line) in the mapping array:
223
+ * - Resets generated column offset to 0 at the start of each line
224
+ * - Encodes each segment within the line using relative VLQ encoding
225
+ * - Joins segments with commas (,)
226
+ * 3. Joins lines with semicolons (;)
227
+ *
228
+ * Empty frames are preserved as empty strings in the output to maintain
229
+ * the correct line numbering in the resulting source map.
192
230
  *
193
- * @param map - The mapping array to encode.
194
- * @returns The encoded mapping string.
231
+ * @since 1.0.0
195
232
  */
196
233
  private encodeMappings;
197
234
  /**
198
- * Decodes a VLQ-encoded segment into a segment object based on the current offset.
235
+ * Converts a VLQ-decoded segment array into a structured segment object.
199
236
  *
200
- * @param segmentOffset - The current segment offset.
201
- * @param decodedSegment - The decoded VLQ segment values.
202
- * @returns The decoded segment object.
237
+ * @param segmentOffset - The current positional state tracking offsets
238
+ * @param decodedSegment - Array of VLQ-decoded values representing relative offsets
239
+ * @returns A complete segment object with absolute positions
240
+ *
241
+ * @remarks
242
+ * The decoding process:
243
+ * 1. Extracts position values from the decoded array:
244
+ * - [0]: generatedColumn delta
245
+ * - [1]: sourceIndex delta
246
+ * - [2]: sourceLine delta
247
+ * - [3]: sourceColumn delta
248
+ * - [4]: nameIndex delta (optional)
249
+ * 2. Updates the segmentOffset state by adding each delta
250
+ * 3. Constructs a segment object with absolute positions (adding 1 to convert
251
+ * from 0-based to 1-based coordinates)
252
+ * 4. Handles nameIndex appropriately (null if not present in the input)
253
+ *
254
+ * This method implements the inverse operation of the delta encoding scheme
255
+ * defined in the source map V3 specification.
256
+ *
257
+ * @since 1.0.0
203
258
  */
204
259
  private decodedSegment;
205
260
  /**
206
- * Decodes a VLQ-encoded mapping string into the internal mapping representation.
261
+ * Decodes a VLQ-encoded mapping string into the internal mapping data structure.
262
+ *
263
+ * @param encodedMap - The VLQ-encoded mapping string from a source map
264
+ * @param namesOffset - Base offset for name indices in the global names array
265
+ * @param sourceOffset - Base offset for source indices in the global sources array
266
+ *
267
+ * @remarks
268
+ * The decoding process:
269
+ * 1. Validates the mapping string format before processing
270
+ * 2. Splits the string into frames using semicolons (;) as line separators
271
+ * 3. Initializes position offsets with the provided name and source offsets
272
+ * 4. For each frame (line):
273
+ * - Adds `null` to the mapping array if the frame is empty
274
+ * - Resets the generated column offset to 0 for each new line
275
+ * - Sets the generated line index using the offset + current index
276
+ * - Splits segments using commas (,) and decodes each segment
277
+ * - Transforms each decoded segment into a segment object
278
+ * 5. Updates the internal mapping array with the decoded data
279
+ *
280
+ * Error handling includes validation checks and descriptive error messages
281
+ * indicating which frame caused a decoding failure.
207
282
  *
208
- * @param encodedMap - The VLQ-encoded mapping string.
209
- * @param namesOffset - Offset for the names index.
210
- * @param sourceOffset - Offset for the sources index.
211
- * @throws { Error } - Throws an error if the mapping string is invalid.
283
+ * @throws Error - When the mapping string format is invalid or decoding fails
284
+ *
285
+ * @since 1.0.0
212
286
  */
213
287
  private decodeMappingString;
214
288
  /**
215
- * Decodes a mapping array into the internal mapping representation, adjusting for offsets.
216
- *
217
- * This method processes each frame in the provided structured mapping array,
218
- * validating each segment within the frame and adjusting the indices based on the
219
- * specified offsets for names and sources. If a frame is invalid or not an array,
220
- * an error will be thrown.
221
- *
222
- * @param encodedMap - The structured mapping array, which should be an array of frames,
223
- * where each frame is an array of segments. Each segment must conform
224
- * to the SegmentInterface.
225
- * @param namesOffset - Offset for the names index, which will be added to each segment's nameIndex.
226
- * @param sourceOffset - Offset for the sources index, which will be added to each segment's sourceIndex.
227
- * @throws { Error } - Throws an error if:
228
- * - The mapping array is invalid (not an array).
229
- * - Any frame is not an array.
230
- * - Any segment does not conform to the SegmentInterface.
289
+ * Decodes a structured mapping array into the internal mapping representation.
290
+ *
291
+ * @param encodedMap - The structured mapping array (array of frames, with each frame being an array of segments)
292
+ * @param namesOffset - Offset to add to each segment's nameIndex (for merging multiple source maps)
293
+ * @param sourceOffset - Offset to add to each segment's sourceIndex (for merging multiple source maps)
294
+ *
295
+ * @remarks
296
+ * The decoding process:
297
+ * 1. Validates that the input is a properly structured array
298
+ * 2. Tracks the current line offset based on the existing mapping length
299
+ * 3. For each frame (line) in the mapping:
300
+ * - Preserves null frames as-is (representing empty lines)
301
+ * - Validates that each frame is an array
302
+ * - For each segment in a frame:
303
+ * - Validates the segment structure
304
+ * - Applies the name and source offsets
305
+ * - Adjusts the generated line index by the line offset
306
+ * - Adds the processed frame to the internal mapping array
307
+ *
308
+ * This method is primarily used when combining multiple source maps or
309
+ * importing mapping data from pre-structured arrays rather than VLQ strings.
310
+ * The offsets enable proper indexing when concatenating multiple mappings.
311
+ *
312
+ * @throws Error - When the input format is invalid or segments don't conform to requirements
313
+ *
314
+ * @since 1.0.0
231
315
  */
232
316
  private decodeMappingArray;
233
317
  }