ts-fsrs 5.3.3 → 5.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.
package/dist/index.umd.js CHANGED
@@ -4,6 +4,23 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.FSRS = {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
+ class FSRSError extends Error {
8
+ constructor(message = "FSRS Error") {
9
+ var _a;
10
+ super(message);
11
+ this.name = "FSRSError";
12
+ (_a = Error.captureStackTrace) == null ? void 0 : _a.call(Error, this, FSRSError);
13
+ }
14
+ }
15
+ class FSRSValidationError extends FSRSError {
16
+ constructor(message) {
17
+ var _a;
18
+ super(message);
19
+ this.name = "FSRSValidationError";
20
+ (_a = Error.captureStackTrace) == null ? void 0 : _a.call(Error, this, FSRSValidationError);
21
+ }
22
+ }
23
+
7
24
  var State = /* @__PURE__ */ ((State2) => {
8
25
  State2[State2["New"] = 0] = "New";
9
26
  State2[State2["Learning"] = 1] = "Learning";
@@ -53,13 +70,13 @@
53
70
  const restOfString = value.slice(1).toLowerCase();
54
71
  const ret = Rating[`${firstLetter}${restOfString}`];
55
72
  if (ret === void 0) {
56
- throw new Error(`Invalid rating:[${value}]`);
73
+ throw new FSRSValidationError(`Invalid rating:[${value}]`);
57
74
  }
58
75
  return ret;
59
76
  } else if (typeof value === "number") {
60
77
  return value;
61
78
  }
62
- throw new Error(`Invalid rating:[${value}]`);
79
+ throw new FSRSValidationError(`Invalid rating:[${value}]`);
63
80
  }
64
81
  static state(value) {
65
82
  if (typeof value === "string") {
@@ -67,13 +84,13 @@
67
84
  const restOfString = value.slice(1).toLowerCase();
68
85
  const ret = State[`${firstLetter}${restOfString}`];
69
86
  if (ret === void 0) {
70
- throw new Error(`Invalid state:[${value}]`);
87
+ throw new FSRSValidationError(`Invalid state:[${value}]`);
71
88
  }
72
89
  return ret;
73
90
  } else if (typeof value === "number") {
74
91
  return value;
75
92
  }
76
- throw new Error(`Invalid state:[${value}]`);
93
+ throw new FSRSValidationError(`Invalid state:[${value}]`);
77
94
  }
78
95
  static time(value) {
79
96
  if (value instanceof Date) {
@@ -87,12 +104,12 @@
87
104
  if (!Number.isNaN(timestamp)) {
88
105
  return new Date(timestamp);
89
106
  } else {
90
- throw new Error(`Invalid date:[${value}]`);
107
+ throw new FSRSValidationError(`Invalid date:[${value}]`);
91
108
  }
92
109
  } else if (typeof value === "number") {
93
110
  return new Date(value);
94
111
  }
95
- throw new Error(`Invalid date:[${value}]`);
112
+ throw new FSRSValidationError(`Invalid date:[${value}]`);
96
113
  }
97
114
  static review_log(log) {
98
115
  return __spreadProps$2(__spreadValues$2({}, log), {
@@ -127,7 +144,7 @@
127
144
  }
128
145
  function date_diff(now, pre, unit) {
129
146
  if (!now || !pre) {
130
- throw new Error("Invalid date");
147
+ throw new FSRSValidationError("Invalid date");
131
148
  }
132
149
  const diff = TypeConvert.time(now).getTime() - TypeConvert.time(pre).getTime();
133
150
  let r = 0;
@@ -253,7 +270,7 @@
253
270
  const unit = step.slice(-1);
254
271
  const value = parseInt(step.slice(0, -1), 10);
255
272
  if (Number.isNaN(value) || !Number.isFinite(value) || value < 0) {
256
- throw new Error(`Invalid step value: ${step}`);
273
+ throw new FSRSValidationError(`Invalid step value: ${step}`);
257
274
  }
258
275
  switch (unit) {
259
276
  case "m":
@@ -263,7 +280,9 @@
263
280
  case "d":
264
281
  return value * 1440;
265
282
  default:
266
- throw new Error(`Invalid step unit: ${step}, expected m/h/d`);
283
+ throw new FSRSValidationError(
284
+ `Invalid step unit: ${step}, expected m/h/d`
285
+ );
267
286
  }
268
287
  };
269
288
  const BasicLearningStepsStrategy = (params, state, cur_step) => {
@@ -364,8 +383,8 @@
364
383
  this.init();
365
384
  }
366
385
  checkGrade(grade) {
367
- if (!Number.isFinite(grade) || grade < 0 || grade > 4) {
368
- throw new Error(`Invalid grade "${grade}",expected 1-4`);
386
+ if (!Number.isFinite(grade) || grade < 1 || grade > 4) {
387
+ throw new FSRSValidationError(`Invalid grade "${grade}",expected 1-4`);
369
388
  }
370
389
  }
371
390
  init() {
@@ -511,7 +530,7 @@
511
530
  return prng;
512
531
  }
513
532
 
514
- const version="5.3.3";
533
+ const version="5.4.0";
515
534
 
516
535
  const default_request_retention = 0.9;
517
536
  const default_maximum_interval = 36500;
@@ -600,13 +619,13 @@
600
619
  );
601
620
  };
602
621
  const checkParameters = (parameters) => {
603
- const invalid = parameters.find(
604
- (param) => !Number.isFinite(param) && !Number.isNaN(param)
605
- );
622
+ const invalid = parameters.find((param) => !Number.isFinite(param));
606
623
  if (invalid !== void 0) {
607
- throw Error(`Non-finite or NaN value in parameters ${parameters}`);
624
+ throw new FSRSValidationError(
625
+ `Non-finite or NaN value in parameters ${parameters}`
626
+ );
608
627
  } else if (![17, 19, 21].includes(parameters.length)) {
609
- throw Error(
628
+ throw new FSRSValidationError(
610
629
  `Invalid parameter length: ${parameters.length}. Must be 17, 19 or 21 for FSRSv4, 5 and 6 respectively.`
611
630
  );
612
631
  }
@@ -736,7 +755,9 @@
736
755
  */
737
756
  calculate_interval_modifier(request_retention) {
738
757
  if (request_retention <= 0 || request_retention > 1) {
739
- throw new Error("Requested retention rate should be in the range (0,1]");
758
+ throw new FSRSValidationError(
759
+ "Requested retention rate should be in the range (0,1]"
760
+ );
740
761
  }
741
762
  const { decay, factor } = computeDecayFactor(this.param.w);
742
763
  return roundTo((Math.pow(request_retention, 1 / decay) - 1) / factor, 8);
@@ -944,10 +965,10 @@
944
965
  stability: 0
945
966
  };
946
967
  if (t < 0) {
947
- throw new Error(`Invalid delta_t "${t}"`);
968
+ throw new FSRSValidationError(`Invalid delta_t "${t}"`);
948
969
  }
949
970
  if (g < 0 || g > 4) {
950
- throw new Error(`Invalid grade "${g}"`);
971
+ throw new FSRSValidationError(`Invalid grade "${g}"`);
951
972
  }
952
973
  if (d === 0 && s === 0) {
953
974
  return {
@@ -962,7 +983,7 @@
962
983
  };
963
984
  }
964
985
  if (d < 1 || s < S_MIN) {
965
- throw new Error(
986
+ throw new FSRSValidationError(
966
987
  `Invalid memory state { difficulty: ${d}, stability: ${s} }`
967
988
  );
968
989
  }
@@ -1367,7 +1388,9 @@
1367
1388
  */
1368
1389
  handleManualRating(card, state, reviewed, elapsed_days, stability, difficulty, due) {
1369
1390
  if (typeof state === "undefined") {
1370
- throw new Error("reschedule: state is required for manual rating");
1391
+ throw new FSRSValidationError(
1392
+ "reschedule: state is required for manual rating"
1393
+ );
1371
1394
  }
1372
1395
  let log;
1373
1396
  let next_card;
@@ -1388,7 +1411,9 @@
1388
1411
  next_card.last_review = reviewed;
1389
1412
  } else {
1390
1413
  if (typeof due === "undefined") {
1391
- throw new Error("reschedule: due is required for manual rating");
1414
+ throw new FSRSValidationError(
1415
+ "reschedule: due is required for manual rating"
1416
+ );
1392
1417
  }
1393
1418
  const scheduled_days = date_diff(due, reviewed, "days");
1394
1419
  log = {
@@ -1497,6 +1522,9 @@
1497
1522
  };
1498
1523
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
1499
1524
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1525
+ function applyAfterHandler(value, afterHandler) {
1526
+ return typeof afterHandler === "function" ? afterHandler(value) : value;
1527
+ }
1500
1528
  class FSRS extends FSRSAlgorithm {
1501
1529
  constructor(param) {
1502
1530
  super(param);
@@ -1612,11 +1640,7 @@
1612
1640
  repeat(card, now, afterHandler) {
1613
1641
  const instance = this.getScheduler(card, now);
1614
1642
  const recordLog = instance.preview();
1615
- if (afterHandler && typeof afterHandler === "function") {
1616
- return afterHandler(recordLog);
1617
- } else {
1618
- return recordLog;
1619
- }
1643
+ return applyAfterHandler(recordLog, afterHandler);
1620
1644
  }
1621
1645
  /**
1622
1646
  * Display the collection of cards and logs for the card scheduled at the current time, after applying a specific grade rating.
@@ -1676,14 +1700,10 @@
1676
1700
  const instance = this.getScheduler(card, now);
1677
1701
  const g = TypeConvert.rating(grade);
1678
1702
  if (g === Rating.Manual) {
1679
- throw new Error("Cannot review a manual rating");
1703
+ throw new FSRSValidationError("Cannot review a manual rating");
1680
1704
  }
1681
1705
  const recordLogItem = instance.review(g);
1682
- if (afterHandler && typeof afterHandler === "function") {
1683
- return afterHandler(recordLogItem);
1684
- } else {
1685
- return recordLogItem;
1686
- }
1706
+ return applyAfterHandler(recordLogItem, afterHandler);
1687
1707
  }
1688
1708
  /**
1689
1709
  * Get the retrievability of the card
@@ -1728,7 +1748,7 @@
1728
1748
  const processedCard = TypeConvert.card(card);
1729
1749
  const processedLog = TypeConvert.review_log(log);
1730
1750
  if (processedLog.rating === Rating.Manual) {
1731
- throw new Error("Cannot rollback a manual rating");
1751
+ throw new FSRSValidationError("Cannot rollback a manual rating");
1732
1752
  }
1733
1753
  let last_due;
1734
1754
  let last_review;
@@ -1759,11 +1779,7 @@
1759
1779
  state: processedLog.state,
1760
1780
  last_review
1761
1781
  });
1762
- if (afterHandler && typeof afterHandler === "function") {
1763
- return afterHandler(prevCard);
1764
- } else {
1765
- return prevCard;
1766
- }
1782
+ return applyAfterHandler(prevCard, afterHandler);
1767
1783
  }
1768
1784
  /**
1769
1785
  *
@@ -1845,11 +1861,7 @@
1845
1861
  last_review: processedCard.last_review
1846
1862
  });
1847
1863
  const recordLogItem = { card: forget_card, log: forget_log };
1848
- if (afterHandler && typeof afterHandler === "function") {
1849
- return afterHandler(recordLogItem);
1850
- } else {
1851
- return recordLogItem;
1852
- }
1864
+ return applyAfterHandler(recordLogItem, afterHandler);
1853
1865
  }
1854
1866
  /**
1855
1867
  * Reschedules the current card and returns the rescheduled collections and reschedule item.
@@ -1916,15 +1928,9 @@
1916
1928
  len ? collections[len - 1] : void 0,
1917
1929
  updateMemoryState
1918
1930
  );
1919
- if (recordLogHandler && typeof recordLogHandler === "function") {
1920
- return {
1921
- collections: collections.map(recordLogHandler),
1922
- reschedule_item: manual_item ? recordLogHandler(manual_item) : null
1923
- };
1924
- }
1925
1931
  return {
1926
- collections,
1927
- reschedule_item: manual_item
1932
+ collections: typeof recordLogHandler === "function" ? collections.map(recordLogHandler) : collections,
1933
+ reschedule_item: manual_item ? applyAfterHandler(manual_item, recordLogHandler) : null
1928
1934
  };
1929
1935
  }
1930
1936
  }