ts-time-utils 4.1.0 → 4.4.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.
Files changed (61) hide show
  1. package/README.md +81 -31
  2. package/dist/{age.js → age.cjs} +14 -6
  3. package/dist/{calculate.js → calculate.cjs} +30 -18
  4. package/dist/{calendar.js → calendar.cjs} +80 -39
  5. package/dist/{calendars.js → calendars.cjs} +48 -23
  6. package/dist/{chain.js → chain.cjs} +41 -40
  7. package/dist/{compare.js → compare.cjs} +58 -28
  8. package/dist/constants.cjs +19 -0
  9. package/dist/{countdown.js → countdown.cjs} +16 -7
  10. package/dist/{cron.js → cron.cjs} +20 -9
  11. package/dist/{dateRange.js → dateRange.cjs} +42 -26
  12. package/dist/{duration.js → duration.cjs} +56 -44
  13. package/dist/esm/chain.js +0 -5
  14. package/dist/esm/naturalLanguage.d.ts +1 -3
  15. package/dist/esm/naturalLanguage.d.ts.map +1 -1
  16. package/dist/esm/naturalLanguage.js +9 -2
  17. package/dist/esm/plugins.d.ts +0 -6
  18. package/dist/esm/plugins.d.ts.map +1 -1
  19. package/dist/esm/plugins.js +36 -42
  20. package/dist/esm/recurrence.d.ts.map +1 -1
  21. package/dist/esm/recurrence.js +3 -5
  22. package/dist/esm/timezone.d.ts +6 -1
  23. package/dist/esm/timezone.d.ts.map +1 -1
  24. package/dist/esm/timezone.js +106 -66
  25. package/dist/esm/types.d.ts +0 -4
  26. package/dist/esm/types.d.ts.map +1 -1
  27. package/dist/{finance.js → finance.cjs} +39 -22
  28. package/dist/{fiscal.js → fiscal.cjs} +36 -17
  29. package/dist/{format.js → format.cjs} +83 -70
  30. package/dist/{healthcare.js → healthcare.cjs} +37 -22
  31. package/dist/{holidays.js → holidays.cjs} +52 -25
  32. package/dist/index.cjs +595 -0
  33. package/dist/{interval.js → interval.cjs} +24 -11
  34. package/dist/{iterate.js → iterate.cjs} +84 -41
  35. package/dist/{locale.js → locale.cjs} +54 -26
  36. package/dist/{naturalLanguage.js → naturalLanguage.cjs} +36 -23
  37. package/dist/naturalLanguage.d.ts +1 -3
  38. package/dist/naturalLanguage.d.ts.map +1 -1
  39. package/dist/{parse.js → parse.cjs} +24 -11
  40. package/dist/{performance.js → performance.cjs} +23 -10
  41. package/dist/{plugins.js → plugins.cjs} +48 -47
  42. package/dist/plugins.d.ts +0 -6
  43. package/dist/plugins.d.ts.map +1 -1
  44. package/dist/{precision.js → precision.cjs} +74 -37
  45. package/dist/{rangePresets.js → rangePresets.cjs} +40 -19
  46. package/dist/{recurrence.js → recurrence.cjs} +27 -21
  47. package/dist/recurrence.d.ts.map +1 -1
  48. package/dist/{scheduling.js → scheduling.cjs} +46 -31
  49. package/dist/{serialize.js → serialize.cjs} +36 -17
  50. package/dist/{temporal.js → temporal.cjs} +28 -13
  51. package/dist/{timezone.js → timezone.cjs} +140 -82
  52. package/dist/timezone.d.ts +6 -1
  53. package/dist/timezone.d.ts.map +1 -1
  54. package/dist/{types.js → types.cjs} +9 -3
  55. package/dist/types.d.ts +0 -4
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/{validate.js → validate.cjs} +54 -26
  58. package/dist/{workingHours.js → workingHours.cjs} +36 -17
  59. package/package.json +40 -37
  60. package/dist/constants.js +0 -16
  61. package/dist/index.js +0 -72
@@ -1,9 +1,15 @@
1
+ "use strict";
1
2
  /**
2
3
  * @fileoverview Natural language date parsing utilities
3
4
  * Provides intelligent parsing of human-readable date strings
4
5
  */
5
- import { addTime } from './calculate.js';
6
- import { parseRelativeDate } from './parse.js';
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseNaturalDate = parseNaturalDate;
8
+ exports.parseRelativePhrase = parseRelativePhrase;
9
+ exports.extractDatesFromText = extractDatesFromText;
10
+ exports.suggestDateFromContext = suggestDateFromContext;
11
+ const calculate_js_1 = require("./calculate.cjs");
12
+ const parse_js_1 = require("./parse.cjs");
7
13
  /**
8
14
  * Parses natural language date strings into Date objects
9
15
  * @param input - Natural language date string
@@ -25,15 +31,15 @@ import { parseRelativeDate } from './parse.js';
25
31
  * // Date for Dec 25 this year (or next if passed)
26
32
  * ```
27
33
  */
28
- export function parseNaturalDate(input, options = {}) {
29
- const { referenceDate = new Date(), defaultTime } = options;
34
+ function parseNaturalDate(input, options = {}) {
35
+ const { referenceDate = new Date(), defaultTime, strict = false } = options;
30
36
  const normalized = input.toLowerCase().trim();
31
37
  // Try relative phrase parser first (handles "next week", "last month", etc.)
32
38
  const relativePhraseResult = parseRelativePhrase(input, referenceDate);
33
39
  if (relativePhraseResult)
34
40
  return relativePhraseResult;
35
41
  // Try existing relative date parser
36
- const relativeResult = parseRelativeDate(input);
42
+ const relativeResult = (0, parse_js_1.parseRelativeDate)(input);
37
43
  if (relativeResult)
38
44
  return relativeResult;
39
45
  // Common absolute patterns
@@ -61,6 +67,9 @@ export function parseNaturalDate(input, options = {}) {
61
67
  return parseMatchedPattern(match, referenceDate, defaultTime);
62
68
  }
63
69
  }
70
+ if (strict) {
71
+ return null;
72
+ }
64
73
  // Try standard Date parsing as fallback
65
74
  const standardDate = new Date(input);
66
75
  if (!isNaN(standardDate.getTime())) {
@@ -81,7 +90,7 @@ export function parseNaturalDate(input, options = {}) {
81
90
  * parseRelativePhrase('next week'); // 7 days from now
82
91
  * ```
83
92
  */
84
- export function parseRelativePhrase(input, referenceDate = new Date()) {
93
+ function parseRelativePhrase(input, referenceDate = new Date()) {
85
94
  const normalized = input.toLowerCase().trim();
86
95
  // "in X units"
87
96
  const inPattern = /^in\s+(\d+)\s+(millisecond|milliseconds|second|seconds|minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)$/;
@@ -89,7 +98,7 @@ export function parseRelativePhrase(input, referenceDate = new Date()) {
89
98
  if (match) {
90
99
  const amount = parseInt(match[1], 10);
91
100
  const unit = normalizeUnit(match[2]);
92
- return addTime(referenceDate, amount, unit);
101
+ return (0, calculate_js_1.addTime)(referenceDate, amount, unit);
93
102
  }
94
103
  // "X units ago"
95
104
  const agoPattern = /^(\d+)\s+(millisecond|milliseconds|second|seconds|minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)\s+ago$/;
@@ -97,7 +106,7 @@ export function parseRelativePhrase(input, referenceDate = new Date()) {
97
106
  if (match) {
98
107
  const amount = parseInt(match[1], 10);
99
108
  const unit = normalizeUnit(match[2]);
100
- return addTime(referenceDate, -amount, unit);
109
+ return (0, calculate_js_1.addTime)(referenceDate, -amount, unit);
101
110
  }
102
111
  // "X units from now"
103
112
  const fromNowPattern = /^(\d+)\s+(millisecond|milliseconds|second|seconds|minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)\s+from\s+now$/;
@@ -105,7 +114,7 @@ export function parseRelativePhrase(input, referenceDate = new Date()) {
105
114
  if (match) {
106
115
  const amount = parseInt(match[1], 10);
107
116
  const unit = normalizeUnit(match[2]);
108
- return addTime(referenceDate, amount, unit);
117
+ return (0, calculate_js_1.addTime)(referenceDate, amount, unit);
109
118
  }
110
119
  // Common shortcuts - use switch/case to properly use the referenceDate parameter
111
120
  switch (normalized) {
@@ -117,21 +126,21 @@ export function parseRelativePhrase(input, referenceDate = new Date()) {
117
126
  return d;
118
127
  }
119
128
  case 'tomorrow':
120
- return addTime(referenceDate, 1, 'day');
129
+ return (0, calculate_js_1.addTime)(referenceDate, 1, 'day');
121
130
  case 'yesterday':
122
- return addTime(referenceDate, -1, 'day');
131
+ return (0, calculate_js_1.addTime)(referenceDate, -1, 'day');
123
132
  case 'next week':
124
- return addTime(referenceDate, 1, 'week');
133
+ return (0, calculate_js_1.addTime)(referenceDate, 1, 'week');
125
134
  case 'last week':
126
- return addTime(referenceDate, -1, 'week');
135
+ return (0, calculate_js_1.addTime)(referenceDate, -1, 'week');
127
136
  case 'next month':
128
- return addTime(referenceDate, 1, 'month');
137
+ return (0, calculate_js_1.addTime)(referenceDate, 1, 'month');
129
138
  case 'last month':
130
- return addTime(referenceDate, -1, 'month');
139
+ return (0, calculate_js_1.addTime)(referenceDate, -1, 'month');
131
140
  case 'next year':
132
- return addTime(referenceDate, 1, 'year');
141
+ return (0, calculate_js_1.addTime)(referenceDate, 1, 'year');
133
142
  case 'last year':
134
- return addTime(referenceDate, -1, 'year');
143
+ return (0, calculate_js_1.addTime)(referenceDate, -1, 'year');
135
144
  default:
136
145
  return null;
137
146
  }
@@ -152,7 +161,7 @@ export function parseRelativePhrase(input, referenceDate = new Date()) {
152
161
  * // ]
153
162
  * ```
154
163
  */
155
- export function extractDatesFromText(text, options = {}) {
164
+ function extractDatesFromText(text, options = {}) {
156
165
  const { referenceDate = new Date() } = options;
157
166
  const results = [];
158
167
  // Patterns to match
@@ -182,7 +191,11 @@ export function extractDatesFromText(text, options = {}) {
182
191
  continue;
183
192
  processed.add(`${index}-${matchedText}`);
184
193
  // Try to parse the matched text
185
- const parsed = parseNaturalDate(matchedText, { referenceDate });
194
+ const parsed = parseNaturalDate(matchedText, {
195
+ referenceDate,
196
+ defaultTime: options.defaultTime,
197
+ strict: options.strict
198
+ });
186
199
  if (parsed) {
187
200
  results.push({
188
201
  date: parsed,
@@ -209,7 +222,7 @@ export function extractDatesFromText(text, options = {}) {
209
222
  * // [{ date: Date(last day of current month), confidence: 0.8, ... }]
210
223
  * ```
211
224
  */
212
- export function suggestDateFromContext(context, options = {}) {
225
+ function suggestDateFromContext(context, options = {}) {
213
226
  const { referenceDate = new Date() } = options;
214
227
  const suggestions = [];
215
228
  const normalized = context.toLowerCase();
@@ -284,16 +297,16 @@ function parseMatchedPattern(match, referenceDate, defaultTime) {
284
297
  if (daysToAdd <= 0)
285
298
  daysToAdd += 7;
286
299
  }
287
- return addTime(referenceDate, daysToAdd, 'day');
300
+ return (0, calculate_js_1.addTime)(referenceDate, daysToAdd, 'day');
288
301
  }
289
302
  // "in X units" pattern
290
303
  if (match[1] && match[2]) {
291
304
  const amount = parseInt(match[1], 10);
292
305
  const unit = normalizeUnit(match[2]);
293
306
  if (match[3] === 'ago') {
294
- return addTime(referenceDate, -amount, unit);
307
+ return (0, calculate_js_1.addTime)(referenceDate, -amount, unit);
295
308
  }
296
- return addTime(referenceDate, amount, unit);
309
+ return (0, calculate_js_1.addTime)(referenceDate, amount, unit);
297
310
  }
298
311
  return null;
299
312
  }
@@ -14,9 +14,7 @@ export interface NaturalParseOptions {
14
14
  minute: number;
15
15
  second?: number;
16
16
  };
17
- /** Locale for language-specific parsing */
18
- locale?: string;
19
- /** Whether to use strict parsing */
17
+ /** Whether to skip permissive fallback parsing */
20
18
  strict?: boolean;
21
19
  }
22
20
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"naturalLanguage.d.ts","sourceRoot":"","sources":["../src/naturalLanguage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB,sDAAsD;IACtD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IACjD,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,IAAI,GAAG,IAAI,CA8C9F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,GAAE,IAAiB,GAAG,IAAI,GAAG,IAAI,CA6DhG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,mBAAwB,GAChC,aAAa,EAAE,CAkDjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,KAAK,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAkDzD"}
1
+ {"version":3,"file":"naturalLanguage.d.ts","sourceRoot":"","sources":["../src/naturalLanguage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB,sDAAsD;IACtD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,kDAAkD;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IACjD,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,IAAI,GAAG,IAAI,CAkD9F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,GAAE,IAAiB,GAAG,IAAI,GAAG,IAAI,CA6DhG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,mBAAwB,GAChC,aAAa,EAAE,CAsDjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,KAAK,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAkDzD"}
@@ -1,11 +1,24 @@
1
+ "use strict";
1
2
  /**
2
3
  * Advanced date parsing utilities
3
4
  */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseDate = parseDate;
7
+ exports.parseRelativeDate = parseRelativeDate;
8
+ exports.parseTimeAgo = parseTimeAgo;
9
+ exports.parseCustomFormat = parseCustomFormat;
10
+ exports.parseManyFormats = parseManyFormats;
11
+ exports.parseISO8601Duration = parseISO8601Duration;
12
+ exports.parseISO8601DurationToMs = parseISO8601DurationToMs;
13
+ exports.parseTime = parseTime;
14
+ exports.guessDateFormat = guessDateFormat;
15
+ exports.parseAutoFormat = parseAutoFormat;
16
+ exports.parseRangeEndpoint = parseRangeEndpoint;
4
17
  /**
5
18
  * Parse various date formats intelligently
6
19
  * @param input - date string, number, or Date object
7
20
  */
8
- export function parseDate(input) {
21
+ function parseDate(input) {
9
22
  if (input instanceof Date) {
10
23
  return isNaN(input.getTime()) ? null : input;
11
24
  }
@@ -61,7 +74,7 @@ export function parseDate(input) {
61
74
  * Parse relative date strings like "tomorrow", "next monday", "2 weeks ago"
62
75
  * @param input - relative date string
63
76
  */
64
- export function parseRelativeDate(input) {
77
+ function parseRelativeDate(input) {
65
78
  const now = new Date();
66
79
  const lowercaseInput = input.toLowerCase().trim();
67
80
  // Handle simple cases
@@ -105,7 +118,7 @@ export function parseRelativeDate(input) {
105
118
  * Parse "time ago" strings like "5 minutes ago", "2 hours ago"
106
119
  * @param input - time ago string
107
120
  */
108
- export function parseTimeAgo(input) {
121
+ function parseTimeAgo(input) {
109
122
  const now = new Date();
110
123
  const lowercaseInput = input.toLowerCase().trim();
111
124
  // Handle simple cases
@@ -125,7 +138,7 @@ export function parseTimeAgo(input) {
125
138
  * @param dateString - date string to parse
126
139
  * @param format - format pattern (e.g., "YYYY-MM-DD", "DD/MM/YYYY")
127
140
  */
128
- export function parseCustomFormat(dateString, format) {
141
+ function parseCustomFormat(dateString, format) {
129
142
  // Simple implementation for common patterns
130
143
  const formatMap = {
131
144
  'YYYY-MM-DD': /^(\d{4})-(\d{2})-(\d{2})$/,
@@ -176,7 +189,7 @@ export function parseCustomFormat(dateString, format) {
176
189
  * @param dateString - date string to parse
177
190
  * @param formats - array of format patterns to try
178
191
  */
179
- export function parseManyFormats(dateString, formats) {
192
+ function parseManyFormats(dateString, formats) {
180
193
  for (const format of formats) {
181
194
  const result = parseCustomFormat(dateString, format);
182
195
  if (result)
@@ -220,7 +233,7 @@ function subtractTimeUnits(date, amount, unit) {
220
233
  * @param duration - ISO 8601 duration string
221
234
  * @returns object with parsed components
222
235
  */
223
- export function parseISO8601Duration(duration) {
236
+ function parseISO8601Duration(duration) {
224
237
  // ISO 8601 duration format: P[n]Y[n]M[n]DT[n]H[n]M[n]S or P[n]W
225
238
  const result = {
226
239
  years: 0,
@@ -265,7 +278,7 @@ export function parseISO8601Duration(duration) {
265
278
  * Convert ISO 8601 duration to milliseconds (approximate for months/years)
266
279
  * @param duration - ISO 8601 duration string
267
280
  */
268
- export function parseISO8601DurationToMs(duration) {
281
+ function parseISO8601DurationToMs(duration) {
269
282
  const parsed = parseISO8601Duration(duration);
270
283
  if (!parsed)
271
284
  return null;
@@ -289,7 +302,7 @@ export function parseISO8601DurationToMs(duration) {
289
302
  * @param timeString - time string to parse
290
303
  * @returns object with hours, minutes, seconds, or null if invalid
291
304
  */
292
- export function parseTime(timeString) {
305
+ function parseTime(timeString) {
293
306
  const normalized = timeString.trim();
294
307
  // 24-hour format: HH:MM or HH:MM:SS
295
308
  const match24 = normalized.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
@@ -328,7 +341,7 @@ export function parseTime(timeString) {
328
341
  * @param dateString - date string to analyze
329
342
  * @returns detected format pattern or null
330
343
  */
331
- export function guessDateFormat(dateString) {
344
+ function guessDateFormat(dateString) {
332
345
  const normalized = dateString.trim();
333
346
  // YYYY-MM-DD
334
347
  if (/^\d{4}-\d{2}-\d{2}$/.test(normalized)) {
@@ -367,7 +380,7 @@ export function guessDateFormat(dateString) {
367
380
  * Parse a date string using auto-detected format
368
381
  * @param dateString - date string to parse
369
382
  */
370
- export function parseAutoFormat(dateString) {
383
+ function parseAutoFormat(dateString) {
371
384
  const format = guessDateFormat(dateString);
372
385
  if (!format) {
373
386
  return parseDate(dateString);
@@ -387,7 +400,7 @@ export function parseAutoFormat(dateString) {
387
400
  * Parse a date from a natural language date range endpoint
388
401
  * @param input - string like "end of month", "start of year", "beginning of week"
389
402
  */
390
- export function parseRangeEndpoint(input) {
403
+ function parseRangeEndpoint(input) {
391
404
  const now = new Date();
392
405
  const lowercaseInput = input.toLowerCase().trim();
393
406
  // Start/beginning of period
@@ -1,11 +1,23 @@
1
+ "use strict";
1
2
  /**
2
3
  * Async time utilities for delays, timeouts, and performance
3
4
  */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Stopwatch = void 0;
7
+ exports.sleep = sleep;
8
+ exports.timeout = timeout;
9
+ exports.debounce = debounce;
10
+ exports.throttle = throttle;
11
+ exports.retry = retry;
12
+ exports.createStopwatch = createStopwatch;
13
+ exports.measureTime = measureTime;
14
+ exports.measureAsync = measureAsync;
15
+ exports.benchmark = benchmark;
4
16
  /**
5
17
  * Sleep for a specified number of milliseconds
6
18
  * @param ms - milliseconds to sleep
7
19
  */
8
- export function sleep(ms) {
20
+ function sleep(ms) {
9
21
  return new Promise(resolve => setTimeout(resolve, ms));
10
22
  }
11
23
  /**
@@ -14,7 +26,7 @@ export function sleep(ms) {
14
26
  * @param ms - timeout in milliseconds
15
27
  * @param timeoutMessage - optional timeout error message
16
28
  */
17
- export function timeout(promise, ms, timeoutMessage = 'Operation timed out') {
29
+ function timeout(promise, ms, timeoutMessage = 'Operation timed out') {
18
30
  return Promise.race([
19
31
  promise,
20
32
  new Promise((_, reject) => setTimeout(() => reject(new Error(timeoutMessage)), ms))
@@ -25,7 +37,7 @@ export function timeout(promise, ms, timeoutMessage = 'Operation timed out') {
25
37
  * @param fn - function to debounce
26
38
  * @param delay - delay in milliseconds
27
39
  */
28
- export function debounce(fn, delay) {
40
+ function debounce(fn, delay) {
29
41
  let timeoutId;
30
42
  return (...args) => {
31
43
  clearTimeout(timeoutId);
@@ -37,7 +49,7 @@ export function debounce(fn, delay) {
37
49
  * @param fn - function to throttle
38
50
  * @param delay - delay in milliseconds
39
51
  */
40
- export function throttle(fn, delay) {
52
+ function throttle(fn, delay) {
41
53
  let lastCall = 0;
42
54
  return (...args) => {
43
55
  const now = Date.now();
@@ -54,7 +66,7 @@ export function throttle(fn, delay) {
54
66
  * @param baseDelay - base delay in milliseconds
55
67
  * @param maxDelay - maximum delay in milliseconds
56
68
  */
57
- export async function retry(fn, maxAttempts = 3, baseDelay = 1000, maxDelay = 10000) {
69
+ async function retry(fn, maxAttempts = 3, baseDelay = 1000, maxDelay = 10000) {
58
70
  let lastError;
59
71
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
60
72
  try {
@@ -75,7 +87,7 @@ export async function retry(fn, maxAttempts = 3, baseDelay = 1000, maxDelay = 10
75
87
  /**
76
88
  * Stopwatch for measuring elapsed time
77
89
  */
78
- export class Stopwatch {
90
+ class Stopwatch {
79
91
  constructor() {
80
92
  this.startTime = null;
81
93
  this.endTime = null;
@@ -167,10 +179,11 @@ export class Stopwatch {
167
179
  return this.pauseStart !== null;
168
180
  }
169
181
  }
182
+ exports.Stopwatch = Stopwatch;
170
183
  /**
171
184
  * Create a new stopwatch instance
172
185
  */
173
- export function createStopwatch() {
186
+ function createStopwatch() {
174
187
  return new Stopwatch();
175
188
  }
176
189
  /**
@@ -178,7 +191,7 @@ export function createStopwatch() {
178
191
  * @param fn - function to measure
179
192
  * @returns tuple of [result, elapsed time in ms]
180
193
  */
181
- export function measureTime(fn) {
194
+ function measureTime(fn) {
182
195
  const start = performance.now();
183
196
  const result = fn();
184
197
  const elapsed = performance.now() - start;
@@ -189,7 +202,7 @@ export function measureTime(fn) {
189
202
  * @param fn - async function to measure
190
203
  * @returns promise that resolves to tuple of [result, elapsed time in ms]
191
204
  */
192
- export async function measureAsync(fn) {
205
+ async function measureAsync(fn) {
193
206
  const start = performance.now();
194
207
  const result = await fn();
195
208
  const elapsed = performance.now() - start;
@@ -200,7 +213,7 @@ export async function measureAsync(fn) {
200
213
  * @param fn - function to benchmark
201
214
  * @param iterations - number of iterations to run
202
215
  */
203
- export function benchmark(fn, iterations = 1000) {
216
+ function benchmark(fn, iterations = 1000) {
204
217
  const times = [];
205
218
  for (let i = 0; i < iterations; i++) {
206
219
  const [, elapsed] = measureTime(fn);
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /**
2
3
  * Plugin system for extending ChainedDate with custom methods
3
4
  *
@@ -19,38 +20,26 @@
19
20
  * chain(new Date()).nextMonday().format('YYYY-MM-DD');
20
21
  * ```
21
22
  */
22
- // Import ChainedDate class directly - safe because chain.js doesn't import plugins.js
23
- // We need the actual class (not just the type) to modify its prototype
24
- let ChainedDateConstructor = null;
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.extend = extend;
25
+ exports.uninstall = uninstall;
26
+ exports.getRegisteredPlugins = getRegisteredPlugins;
27
+ exports.getPluginMethods = getPluginMethods;
28
+ exports.isPluginRegistered = isPluginRegistered;
29
+ const chain_js_1 = require("./chain.cjs");
25
30
  /**
26
- * Get ChainedDate class lazily to ensure it's fully initialized
31
+ * Get ChainedDate class for prototype mutation.
32
+ * Importing `plugins` now brings in `chain` directly, so the class is available
33
+ * without a hidden global handshake.
27
34
  */
28
35
  function getChainedDate() {
29
- if (!ChainedDateConstructor) {
30
- // Use dynamic import that works in both CJS and ESM
31
- try {
32
- // Try ESM import path first
33
- ChainedDateConstructor = globalThis.__chainedDateClass;
34
- if (!ChainedDateConstructor) {
35
- // Fallback: The class will be set by chain.js when it loads
36
- throw new Error('ChainedDate not yet loaded. Import chain.js before using plugins.');
37
- }
38
- }
39
- catch (e) {
40
- throw new Error('ChainedDate class not available. Ensure chain.js is imported before registering plugins.');
41
- }
36
+ if (!chain_js_1.ChainedDate) {
37
+ throw new Error('ChainedDate export is not available yet. Import chain.js before registering plugins.');
42
38
  }
43
- return ChainedDateConstructor;
44
- }
45
- /**
46
- * Initialize the plugin system with ChainedDate class
47
- * This is called automatically when chain.js is imported
48
- * @internal
49
- */
50
- export function __initPluginSystem(ChainedDateClass) {
51
- ChainedDateConstructor = ChainedDateClass;
39
+ return chain_js_1.ChainedDate;
52
40
  }
53
41
  const registry = {};
42
+ const methodStates = {};
54
43
  /**
55
44
  * Extend ChainedDate with custom methods
56
45
  *
@@ -76,27 +65,27 @@ const registry = {};
76
65
  * chain(new Date()).addBusinessDays(5);
77
66
  * ```
78
67
  */
79
- export function extend(pluginName, methods) {
68
+ function extend(pluginName, methods) {
80
69
  if (registry[pluginName]) {
81
70
  throw new Error(`Plugin "${pluginName}" is already registered. Use a different name or uninstall first.`);
82
71
  }
83
- // Get ChainedDate class and save original methods before overwriting
84
72
  const ChainedDateClass = getChainedDate();
85
- const originalMethods = new Map();
86
73
  Object.entries(methods).forEach(([methodName, fn]) => {
87
- // Save original method if it exists
74
+ const current = ChainedDateClass.prototype[methodName];
75
+ if (!methodStates[methodName]) {
76
+ methodStates[methodName] = {
77
+ original: typeof current === 'function' ? current : undefined,
78
+ owners: []
79
+ };
80
+ }
88
81
  if (methodName in ChainedDateClass.prototype) {
89
- const original = ChainedDateClass.prototype[methodName];
90
- if (typeof original === 'function') {
91
- originalMethods.set(methodName, original);
92
- }
93
82
  console.warn(`Method "${methodName}" already exists on ChainedDate and will be overwritten`);
94
83
  }
84
+ methodStates[methodName].owners.push(pluginName);
95
85
  // Add the plugin method
96
86
  ChainedDateClass.prototype[methodName] = fn;
97
87
  });
98
- // Register the plugin with its original methods
99
- registry[pluginName] = { plugin: methods, originalMethods };
88
+ registry[pluginName] = { plugin: methods };
100
89
  }
101
90
  /**
102
91
  * Remove a plugin and its methods from ChainedDate
@@ -108,25 +97,37 @@ export function extend(pluginName, methods) {
108
97
  * uninstall('businessDays');
109
98
  * ```
110
99
  */
111
- export function uninstall(pluginName) {
100
+ function uninstall(pluginName) {
112
101
  const entry = registry[pluginName];
113
102
  if (!entry) {
114
103
  throw new Error(`Plugin "${pluginName}" is not registered`);
115
104
  }
116
- // Get ChainedDate class and restore/remove methods
117
105
  const ChainedDateClass = getChainedDate();
118
106
  Object.keys(entry.plugin).forEach((methodName) => {
119
- // If there was an original method, restore it
120
- const original = entry.originalMethods.get(methodName);
121
- if (original) {
122
- ChainedDateClass.prototype[methodName] = original;
107
+ const state = methodStates[methodName];
108
+ if (!state) {
109
+ delete ChainedDateClass.prototype[methodName];
110
+ return;
111
+ }
112
+ state.owners = state.owners.filter((owner) => owner !== pluginName);
113
+ const nextOwner = state.owners[state.owners.length - 1];
114
+ if (nextOwner) {
115
+ const nextPlugin = registry[nextOwner];
116
+ if (nextPlugin && methodName in nextPlugin.plugin) {
117
+ ChainedDateClass.prototype[methodName] = nextPlugin.plugin[methodName];
118
+ return;
119
+ }
120
+ delete ChainedDateClass.prototype[methodName];
121
+ return;
122
+ }
123
+ if (state.original) {
124
+ ChainedDateClass.prototype[methodName] = state.original;
123
125
  }
124
126
  else {
125
- // Otherwise, delete the method entirely
126
127
  delete ChainedDateClass.prototype[methodName];
127
128
  }
129
+ delete methodStates[methodName];
128
130
  });
129
- // Remove from registry
130
131
  delete registry[pluginName];
131
132
  }
132
133
  /**
@@ -139,7 +140,7 @@ export function uninstall(pluginName) {
139
140
  * getRegisteredPlugins(); // ['businessDays', 'myPlugin']
140
141
  * ```
141
142
  */
142
- export function getRegisteredPlugins() {
143
+ function getRegisteredPlugins() {
143
144
  return Object.keys(registry);
144
145
  }
145
146
  /**
@@ -153,7 +154,7 @@ export function getRegisteredPlugins() {
153
154
  * getPluginMethods('businessDays'); // ['addBusinessDays', 'subtractBusinessDays']
154
155
  * ```
155
156
  */
156
- export function getPluginMethods(pluginName) {
157
+ function getPluginMethods(pluginName) {
157
158
  const entry = registry[pluginName];
158
159
  return entry ? Object.keys(entry.plugin) : [];
159
160
  }
@@ -168,6 +169,6 @@ export function getPluginMethods(pluginName) {
168
169
  * isPluginRegistered('businessDays'); // true
169
170
  * ```
170
171
  */
171
- export function isPluginRegistered(pluginName) {
172
+ function isPluginRegistered(pluginName) {
172
173
  return pluginName in registry;
173
174
  }
package/dist/plugins.d.ts CHANGED
@@ -19,12 +19,6 @@
19
19
  * chain(new Date()).nextMonday().format('YYYY-MM-DD');
20
20
  * ```
21
21
  */
22
- /**
23
- * Initialize the plugin system with ChainedDate class
24
- * This is called automatically when chain.js is imported
25
- * @internal
26
- */
27
- export declare function __initPluginSystem(ChainedDateClass: any): void;
28
22
  /**
29
23
  * Plugin function type - methods receive ChainedDate instance as `this`
30
24
  */
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0BH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,GAAG,QAEvD;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAAC;CACtC;AAcD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAwBhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAqBlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAG7D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,iBAAiB;CAAG"}
1
+ {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgBH;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAAC;CACtC;AAoBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAwBhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAqClD;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAG7D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,iBAAiB;CAAG"}