range-pie 1.0.1 → 2.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.
@@ -0,0 +1,361 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PyRange = void 0;
4
+ /**
5
+ * A class that simulates Python's range function, combined with several useful JavaScript array methods.
6
+ */
7
+ class PyRange {
8
+ /**
9
+ * Creates a new PyRange instance.
10
+ * @param {...number} args - The arguments of the range. The possible forms are
11
+ * - `PyRange(stop)`
12
+ * - `PyRange(start, stop)`
13
+ * - `PyRange(start, stop, step)`
14
+ * @throws {TypeError} If any of the arguments is not a number.
15
+ * @throws {TypeError} If any of the arguments is not an integer.
16
+ * @throws {Error} If the step is zero.
17
+ * @throws {Error} If the arguments count is not between 1 and 3.
18
+ * @property {number} start - The start of the range, inclusive.
19
+ * @property {number} stop - The stop of the range, exclusive.
20
+ * @property {number} step - The step of the range.
21
+ * @property {number} length - The length of the range.
22
+ */
23
+ constructor(...args) {
24
+ if (!args.every((arg) => typeof arg === "number")) {
25
+ throw new TypeError("All arguments must be numbers");
26
+ }
27
+ if (!args.every(Number.isInteger)) {
28
+ throw new TypeError("All arguments must be integers");
29
+ }
30
+ const [start, stop, step] = args.length === 1
31
+ ? [0, args[0], 1]
32
+ : args.length === 2
33
+ ? [args[0], args[1], 1]
34
+ : args.length === 3
35
+ ? [args[0], args[1], args[2]]
36
+ : (() => {
37
+ throw new Error("Invalid arguments count: must between 1 and 3");
38
+ })();
39
+ if (step === 0) {
40
+ throw new Error("Step cannot be zero");
41
+ }
42
+ this._start = start;
43
+ this._stop = stop;
44
+ this._step = stop < start && args.length !== 3 ? -step : step;
45
+ const diff = this._step > 0 ? stop - start : start - stop;
46
+ this._length = Math.max(Math.ceil(diff / Math.abs(this._step)), 0);
47
+ }
48
+ /**
49
+ * Gets the length of this range.
50
+ *
51
+ * @returns {number} the length of this range
52
+ * @readonly
53
+ */
54
+ get length() {
55
+ return this._length;
56
+ }
57
+ /**
58
+ * Gets the starting value of the range.
59
+ *
60
+ * @returns {number} The starting value of the range.
61
+ * @readonly
62
+ */
63
+ get start() {
64
+ return this._start;
65
+ }
66
+ /**
67
+ * Gets the ending value of the range.
68
+ *
69
+ * @returns {number} The ending value of the range.
70
+ * @readonly
71
+ */
72
+ get stop() {
73
+ return this._stop;
74
+ }
75
+ /**
76
+ * Gets the step value of the range.
77
+ *
78
+ * @returns {number} The step value of the range.
79
+ * @readonly
80
+ */
81
+ get step() {
82
+ return this._step;
83
+ }
84
+ /**
85
+ * Gets the value at the specified index in this range.
86
+ * @param {number} index - The index of the value to retrieve
87
+ * @returns {number} The value at the specified index
88
+ * @throws {RangeError} If the index is out of range
89
+ */
90
+ at(index) {
91
+ if (index < 0 || index >= this._length) {
92
+ throw new RangeError("Index out of range");
93
+ }
94
+ return this._start + index * this._step;
95
+ }
96
+ /**
97
+ * Converts the range to a string.
98
+ * @returns {string} A string of the form `Range(start, stop, step)`.
99
+ */
100
+ toString() {
101
+ return `PyRange(${this._start}, ${this._stop}, ${this._step})`;
102
+ }
103
+ /**
104
+ * Converts the range to an array.
105
+ * @returns {number[]} An array of numbers with the same elements as this range.
106
+ */
107
+ toArray() {
108
+ return [...this];
109
+ }
110
+ /**
111
+ * Validates that the callback is a function.
112
+ * @param {Function} cb - The callback to validate.
113
+ * @throws {TypeError} If the callback is not a function.
114
+ */
115
+ static validateCb(cb) {
116
+ if (typeof cb !== "function") {
117
+ throw new TypeError("Callback must be a function");
118
+ }
119
+ }
120
+ /**
121
+ * Creates a new array with the results of applying the given callback
122
+ * function to every element in this range.
123
+ * @param {function(number, number, PyRange): T} callback - The callback
124
+ * function to apply to every element.
125
+ * @returns {T[]} A new array of the same length as this range.
126
+ * @template T
127
+ */
128
+ map(callback) {
129
+ PyRange.validateCb(callback);
130
+ const result = new Array(this._length);
131
+ for (let i = 0; i < this._length; i++) {
132
+ result[i] = callback(this.at(i), i, this);
133
+ }
134
+ return result;
135
+ }
136
+ /**
137
+ * Creates a new array with all elements that pass the test implemented by
138
+ * the provided function.
139
+ * @param {function(number, number, PyRange): boolean} callback - The
140
+ * predicate function to apply to every element
141
+ * @returns {number[]} A new array of elements that pass the test
142
+ */
143
+ filter(callback) {
144
+ PyRange.validateCb(callback);
145
+ const result = [];
146
+ for (let i = 0; i < this._length; i++) {
147
+ const value = this.at(i);
148
+ if (callback(value, i, this)) {
149
+ result.push(value);
150
+ }
151
+ }
152
+ return result;
153
+ }
154
+ /**
155
+ * Reduces the range to a single value.
156
+ * @param {function(T, number, number, PyRange): T} callback - The callback
157
+ * function to apply to every element. The callback should take four
158
+ * arguments: the accumulator, the current value, the index of the current
159
+ * value, and the range object.
160
+ * @param {T} [initialValue] - The initial value of the accumulator.
161
+ * @returns {T} The final value of the accumulator.
162
+ * @template T
163
+ */
164
+ reduce(callback, initialValue) {
165
+ PyRange.validateCb(callback);
166
+ if (this._length === 0 && initialValue === undefined) {
167
+ throw new TypeError("Reduce of empty range with no initial value");
168
+ }
169
+ let accumulator;
170
+ let startIndex;
171
+ if (initialValue !== undefined) {
172
+ accumulator = initialValue;
173
+ startIndex = 0;
174
+ }
175
+ else {
176
+ accumulator = this.at(0);
177
+ startIndex = 1;
178
+ }
179
+ for (let i = startIndex; i < this._length; i++) {
180
+ accumulator = callback(accumulator, this.at(i), i, this);
181
+ }
182
+ return accumulator;
183
+ }
184
+ /**
185
+ * Determines whether at least one element of the range satisfies the
186
+ * provided test.
187
+ * @param {function(number, number, PyRange): boolean} callback - The
188
+ * predicate function to apply to every element
189
+ * @returns {boolean} True if at least one element of the range passes the
190
+ * test, false otherwise.
191
+ */
192
+ some(callback) {
193
+ PyRange.validateCb(callback);
194
+ for (let i = 0; i < this._length; i++) {
195
+ if (callback(this.at(i), i, this)) {
196
+ return true;
197
+ }
198
+ }
199
+ return false;
200
+ }
201
+ /**
202
+ * Determines whether all elements of the range satisfy the provided test.
203
+ * @param {function(number, number, PyRange): boolean} callback - The
204
+ * predicate function to apply to every element
205
+ * @returns {boolean} True if all elements of the range pass the test,
206
+ * false otherwise.
207
+ */
208
+ every(callback) {
209
+ PyRange.validateCb(callback);
210
+ for (let i = 0; i < this._length; i++) {
211
+ if (!callback(this.at(i), i, this)) {
212
+ return false;
213
+ }
214
+ }
215
+ return true;
216
+ }
217
+ /**
218
+ * Finds the first element in this range that satisfies the provided test.
219
+ * @param {function(number, number, PyRange): boolean} callback - The
220
+ * predicate function to apply to every element
221
+ * @returns {number|undefined} The first element that passes the test,
222
+ * or undefined if no element passes the test.
223
+ */
224
+ find(callback) {
225
+ PyRange.validateCb(callback);
226
+ for (let i = 0; i < this._length; i++) {
227
+ if (callback(this.at(i), i, this)) {
228
+ return this.at(i);
229
+ }
230
+ }
231
+ return undefined;
232
+ }
233
+ /**
234
+ * Finds the index of the first element in this range that satisfies the provided test.
235
+ * @param {function(number, number, PyRange): boolean} callback - The predicate function to apply to each element.
236
+ * @returns {number} The index of the first element that passes the test, or -1 if no element passes the test.
237
+ */
238
+ findIndex(callback) {
239
+ PyRange.validateCb(callback);
240
+ for (let i = 0; i < this._length; i++) {
241
+ if (callback(this.at(i), i, this)) {
242
+ return i;
243
+ }
244
+ }
245
+ return -1;
246
+ }
247
+ /**
248
+ * Finds the index of the last element in this range that satisfies the provided test.
249
+ * @param {function(number, number, PyRange): boolean} callback - The predicate function to apply to each element.
250
+ * @returns {number} The index of the last element that passes the test, or -1 if no element passes the test.
251
+ */
252
+ findLastIndex(callback) {
253
+ PyRange.validateCb(callback);
254
+ for (let i = this._length - 1; i >= 0; i--) {
255
+ if (callback(this.at(i), i, this)) {
256
+ return i;
257
+ }
258
+ }
259
+ return -1;
260
+ }
261
+ /**
262
+ * Executes a provided function once for each element in this range.
263
+ * @param {function(number, number, PyRange): void} callback - The
264
+ * function to execute for each element.
265
+ */
266
+ forEach(callback) {
267
+ PyRange.validateCb(callback);
268
+ for (let i = 0; i < this._length; i++) {
269
+ callback(this.at(i), i, this);
270
+ }
271
+ }
272
+ /**
273
+ * Determines whether the given value is present in this range.
274
+ * @param {any} value - The value to search for.
275
+ * @returns {boolean} True if the value is present, false otherwise.
276
+ */
277
+ includes(value) {
278
+ return this.some((item) => item === value);
279
+ }
280
+ /**
281
+ * Returns the index of the first occurrence of the specified value, or -1 if it is not present.
282
+ * @param {any} value - The value to search for.
283
+ * @returns {number} The index of the value, or -1 if it is not present.
284
+ */
285
+ indexOf(value) {
286
+ for (let i = 0; i < this._length; i++) {
287
+ if (this.at(i) === value) {
288
+ return i;
289
+ }
290
+ }
291
+ return -1;
292
+ }
293
+ /**
294
+ * Returns the index of the last occurrence of the specified value, or -1 if it is not present.
295
+ * @param {any} value - The value to search for.
296
+ * @returns {number} The index of the last occurrence of the value, or -1 if it is not present.
297
+ */
298
+ lastIndexOf(value) {
299
+ for (let i = this._length - 1; i >= 0; i--) {
300
+ if (this.at(i) === value) {
301
+ return i;
302
+ }
303
+ }
304
+ return -1;
305
+ }
306
+ /**
307
+ * Reverses the order of the elements in this range, returning a new PyRange object.
308
+ * @returns {PyRange} A new PyRange object with the elements in reverse order.
309
+ */
310
+ reverse() {
311
+ const result = new PyRange(this._stop, this._start, -this._step);
312
+ // Force the length to be the same as the original range
313
+ result._length = this._length;
314
+ return result;
315
+ }
316
+ /**
317
+ * Implements the iterable protocol for this range.
318
+ * @returns {Iterator<number>} An iterator for this range.
319
+ */
320
+ [Symbol.iterator]() {
321
+ let index = 0;
322
+ let current = this._start;
323
+ const { _step: step, _length: length } = this;
324
+ return {
325
+ next: () => {
326
+ if (index >= length) {
327
+ return { done: true, value: undefined };
328
+ }
329
+ else {
330
+ const value = current;
331
+ current += step;
332
+ index++;
333
+ return { value, done: false };
334
+ }
335
+ },
336
+ };
337
+ }
338
+ /**
339
+ * Returns a Proxy for this range, allowing indexed access.
340
+ * This proxy enables accessing range elements via array-like indexing.
341
+ * If the property is a number, it will return the element at that index.
342
+ *
343
+ * @returns {any} A proxy for the PyRange instance.
344
+ */
345
+ asProxy() {
346
+ return new Proxy(this, {
347
+ get(target, prop) {
348
+ if (typeof prop === "symbol") {
349
+ return target[prop];
350
+ }
351
+ if (!isNaN(Number(prop))) {
352
+ return target.at(parseInt(String(prop), 10));
353
+ }
354
+ return target[prop];
355
+ },
356
+ });
357
+ }
358
+ }
359
+ exports.PyRange = PyRange;
360
+ exports.default = PyRange;
361
+ //# sourceMappingURL=py-range.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"py-range.js","sourceRoot":"","sources":["../src/py-range.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Advanced usage examples for range-pie
3
+ *
4
+ * This file demonstrates more advanced features of the PyRange class
5
+ */
6
+
7
+ const { PyRange } = require('range-pie');
8
+
9
+ console.log('\n--- Advanced PyRange Examples ---');
10
+
11
+ // Example 1: Using the reverse method
12
+ const range1 = new PyRange(1, 6);
13
+ console.log('Original range:', [...range1]); // [1, 2, 3, 4, 5]
14
+
15
+ const reversed = range1.reverse();
16
+ console.log('Reversed range:', [...reversed]); // [5, 4, 3, 2, 1]
17
+
18
+ // Example 2: Using the asProxy method for array-like access
19
+ const range2 = new PyRange(10).asProxy();
20
+ console.log('range2[0]:', range2[0]); // 0
21
+ console.log('range2[5]:', range2[5]); // 5
22
+
23
+ // Create an array using proxy access
24
+ const firstThree = [range2[0], range2[1], range2[2]];
25
+ console.log('firstThree:', firstThree); // [0, 1, 2]
26
+
27
+ // Example 3: Method chaining
28
+ const range3 = new PyRange(1, 10);
29
+ const result = range3
30
+ .filter(x => x % 2 === 0) // Get even numbers
31
+ .map(x => x * x) // Square them
32
+ .filter(x => x > 10); // Filter values greater than 10
33
+
34
+ console.log('Chained methods result:', result); // [16, 36, 64]
35
+
36
+ // Example 4: Using PyRange with other array methods
37
+ const range4 = new PyRange(5);
38
+ const array = [...range4]; // Convert to array: [0, 1, 2, 3, 4]
39
+
40
+ // Now we can use native array methods
41
+ const sorted = array.sort((a, b) => b - a); // Sort in descending order
42
+ console.log('Sorted array:', sorted); // [4, 3, 2, 1, 0]
43
+
44
+ // Example 5: Creating a range with custom step
45
+ const range5 = new PyRange(0, 11, 2);
46
+ console.log('Range with step 2:', [...range5]); // [0, 2, 4, 6, 8, 10]
47
+
48
+ // Example 6: Combining multiple ranges
49
+ const range6a = new PyRange(0, 3);
50
+ const range6b = new PyRange(5, 8);
51
+ const combined = [...range6a, ...range6b];
52
+ console.log('Combined ranges:', combined); // [0, 1, 2, 5, 6, 7]
53
+
54
+ // Example 7: Using PyRange for iteration
55
+ console.log('\nIteration example:');
56
+ for (const num of new PyRange(3)) {
57
+ console.log(`Current number: ${num}`);
58
+ }
59
+ // Current number: 0
60
+ // Current number: 1
61
+ // Current number: 2
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Array method examples for range-pie
3
+ *
4
+ * This file demonstrates how to use the array-like methods provided by PyRange
5
+ */
6
+
7
+ const { PyRange } = require('range-pie');
8
+
9
+ console.log('\n--- Array Method Examples ---');
10
+
11
+ // Create a range to work with
12
+ const range = new PyRange(1, 10);
13
+ console.log('Original range:', [...range]); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
14
+
15
+ // Map: Double each value
16
+ const doubled = range.map(x => x * 2);
17
+ console.log('map(x => x * 2):', doubled); // [2, 4, 6, 8, 10, 12, 14, 16, 18]
18
+
19
+ // Filter: Get only even numbers
20
+ const evens = range.filter(x => x % 2 === 0);
21
+ console.log('filter(x => x % 2 === 0):', evens); // [2, 4, 6, 8]
22
+
23
+ // Reduce: Sum all values
24
+ const sum = range.reduce((acc, curr) => acc + curr, 0);
25
+ console.log('reduce((acc, curr) => acc + curr, 0):', sum); // 45
26
+
27
+ // Some: Check if any value meets a condition
28
+ const hasEven = range.some(x => x % 2 === 0);
29
+ console.log('some(x => x % 2 === 0):', hasEven); // true
30
+
31
+ // Every: Check if all values meet a condition
32
+ const allPositive = range.every(x => x > 0);
33
+ console.log('every(x => x > 0):', allPositive); // true
34
+
35
+ // Find: Get the first value that meets a condition
36
+ const firstEven = range.find(x => x % 2 === 0);
37
+ console.log('find(x => x % 2 === 0):', firstEven); // 2
38
+
39
+ // FindIndex: Get the index of the first value that meets a condition
40
+ const firstEvenIndex = range.findIndex(x => x % 2 === 0);
41
+ console.log('findIndex(x => x % 2 === 0):', firstEvenIndex); // 1
42
+
43
+ // FindLastIndex: Get the index of the last value that meets a condition
44
+ const lastEvenIndex = range.findLastIndex(x => x % 2 === 0);
45
+ console.log('findLastIndex(x => x % 2 === 0):', lastEvenIndex); // 7
46
+
47
+ // Includes: Check if a value exists in the range
48
+ const includesFive = range.includes(5);
49
+ console.log('includes(5):', includesFive); // true
50
+
51
+ // IndexOf: Get the index of a value
52
+ const indexOfFive = range.indexOf(5);
53
+ console.log('indexOf(5):', indexOfFive); // 4
54
+
55
+ // LastIndexOf: Get the last index of a value
56
+ const lastIndexOfFive = range.lastIndexOf(5);
57
+ console.log('lastIndexOf(5):', lastIndexOfFive); // 4
58
+
59
+ // ForEach: Execute a function for each value
60
+ console.log('\nforEach example:');
61
+ range.forEach(x => {
62
+ if (x % 3 === 0) {
63
+ console.log(`${x} is divisible by 3`);
64
+ }
65
+ });
66
+ // 3 is divisible by 3
67
+ // 6 is divisible by 3
68
+ // 9 is divisible by 3
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Basic usage examples for range-pie
3
+ *
4
+ * This file demonstrates the fundamental ways to use the PyRange class
5
+ * with JavaScript.
6
+ */
7
+
8
+ // CommonJS import
9
+ const { PyRange } = require('range-pie');
10
+
11
+ console.log('\n--- Basic PyRange Examples ---');
12
+
13
+ // Example 1: Simple range with just stop value
14
+ const range1 = new PyRange(5);
15
+ console.log('PyRange(5):', [...range1]); // [0, 1, 2, 3, 4]
16
+
17
+ // Example 2: Range with start and stop
18
+ const range2 = new PyRange(2, 8);
19
+ console.log('PyRange(2, 8):', [...range2]); // [2, 3, 4, 5, 6, 7]
20
+
21
+ // Example 3: Range with start, stop, and step
22
+ const range3 = new PyRange(1, 10, 2);
23
+ console.log('PyRange(1, 10, 2):', [...range3]); // [1, 3, 5, 7, 9]
24
+
25
+ // Example 4: Negative step
26
+ const range4 = new PyRange(10, 0, -2);
27
+ console.log('PyRange(10, 0, -2):', [...range4]); // [10, 8, 6, 4, 2]
28
+
29
+ console.log('\n--- Accessing Properties ---');
30
+ console.log('range3.start:', range3.start); // 1
31
+ console.log('range3.stop:', range3.stop); // 10
32
+ console.log('range3.step:', range3.step); // 2
33
+ console.log('range3.length:', range3.length); // 5
34
+
35
+ console.log('\n--- Using at() Method ---');
36
+ console.log('range3.at(0):', range3.at(0)); // 1
37
+ console.log('range3.at(2):', range3.at(2)); // 5
38
+ // console.log(range3.at(10)); // Would throw RangeError: Index out of range
39
+
40
+ console.log('\n--- Converting to Array ---');
41
+ const array = range3.toArray();
42
+ console.log('range3.toArray():', array); // [1, 3, 5, 7, 9]
@@ -0,0 +1,61 @@
1
+ /**
2
+ * TypeScript usage examples for range-pie
3
+ *
4
+ * This file demonstrates how to use the PyRange class with TypeScript,
5
+ * taking advantage of type safety and generics.
6
+ */
7
+
8
+ // ES Module import
9
+ import { PyRange } from "range-pie";
10
+
11
+ console.log("\n--- TypeScript PyRange Examples ---");
12
+
13
+ // Basic usage is the same as JavaScript
14
+ const range = new PyRange(1, 10);
15
+ console.log("Basic range:", [...range]); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
16
+
17
+ // TypeScript provides type safety
18
+ // This would cause a compile-time error:
19
+ // const badRange = new PyRange("not a number");
20
+
21
+ // Type inference with generics
22
+ // TypeScript knows this returns number[]
23
+ const numbers = range.map((x) => x * 2);
24
+ console.log("Doubled numbers:", numbers); // [2, 4, 6, 8, 10, 12, 14, 16, 18]
25
+
26
+ // TypeScript knows this returns string[]
27
+ const strings = range.map((x) => `Number: ${x}`);
28
+ console.log("First string:", strings[0]); // "Number: 1"
29
+
30
+ // TypeScript knows this returns boolean[]
31
+ const booleans = range.map((x) => x % 2 === 0);
32
+ console.log("Is even:", booleans); // [false, true, false, true, false, true, false, true, false]
33
+
34
+ // Type safety with callbacks
35
+ range.forEach((value: number, index: number) => {
36
+ console.log(`Value at index ${index}: ${value}`);
37
+ });
38
+
39
+ // Using reduce with proper typing
40
+ const sum: number = range.reduce((acc, curr) => acc + curr, 0);
41
+ console.log("Sum:", sum); // 45
42
+
43
+ // Creating a custom object with map
44
+ interface NumberInfo {
45
+ value: number;
46
+ isEven: boolean;
47
+ square: number;
48
+ }
49
+
50
+ const infoArray: NumberInfo[] = range.map((x) => ({
51
+ value: x,
52
+ isEven: x % 2 === 0,
53
+ square: x * x,
54
+ }));
55
+
56
+ console.log("First object:", infoArray[0]); // { value: 1, isEven: false, square: 1 }
57
+
58
+ // Chaining methods with type safety
59
+ const evenSquares: number[] = range.filter((x) => x % 2 === 0).map((x) => x * x);
60
+
61
+ console.log("Even squares:", evenSquares); // [4, 16, 36, 64]
package/package.json CHANGED
@@ -1,16 +1,31 @@
1
1
  {
2
2
  "name": "range-pie",
3
- "version": "1.0.1",
4
- "description": "A JavaScript class that simulate Python's range function, combined with several useful JavaScript array methods.",
5
- "main": "src/index.js",
3
+ "version": "2.0.1",
4
+ "description": "A TypeScript class that simulates Python's range function, combined with several useful JavaScript array methods.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
6
7
  "exports": {
7
8
  ".": {
8
- "import": "./src/index.js",
9
- "require": "./src/index.js"
9
+ "import": "./dist/index.js",
10
+ "require": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
10
12
  }
11
13
  },
14
+ "files": [
15
+ "dist",
16
+ "examples"
17
+ ],
12
18
  "scripts": {
13
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
19
+ "build": "tsc",
20
+ "prepublishOnly": "npm run build",
21
+ "test": "jest",
22
+ "clean": "rimraf dist",
23
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"examples/**/*.ts\"",
24
+ "check-format": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\" \"examples/**/*.ts\"",
25
+ "example:basic": "node examples/basic-usage.js",
26
+ "example:array": "node examples/array-methods.js",
27
+ "example:advanced": "node examples/advanced-usage.js",
28
+ "example:ts": "ts-node examples/typescript-usage.ts"
14
29
  },
15
30
  "keywords": [
16
31
  "range",
@@ -20,11 +35,22 @@
20
35
  "JavaScript Array",
21
36
  "Array",
22
37
  "py-range",
23
- "PyRange"
38
+ "PyRange",
39
+ "TypeScript"
24
40
  ],
25
41
  "author": "SkorpionG2000",
26
42
  "license": "MIT",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/SkorpionG/range-pie.git"
46
+ },
27
47
  "devDependencies": {
28
- "jest": "^29.7.0"
48
+ "@types/jest": "^29.5.0",
49
+ "jest": "^29.7.0",
50
+ "prettier": "^3.5.3",
51
+ "rimraf": "^5.0.0",
52
+ "ts-jest": "^29.1.0",
53
+ "ts-node": "^10.9.1",
54
+ "typescript": "^5.0.4"
29
55
  }
30
56
  }
package/src/index.js DELETED
@@ -1,5 +0,0 @@
1
- "use strict";
2
- const PyRange = require("./py-range.js");
3
-
4
- module.exports = PyRange;
5
- module.exports.PyRange = PyRange;