@actuallab/core 13.0.4 → 13.0.12

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.cjs CHANGED
@@ -29,21 +29,34 @@ __export(index_exports, {
29
29
  LogLevel: () => LogLevel,
30
30
  LogLevelController: () => LogLevelController,
31
31
  PromiseSource: () => PromiseSource,
32
+ PromiseSourceWithTimeout: () => PromiseSourceWithTimeout,
33
+ ResolvedPromise: () => ResolvedPromise,
32
34
  Result: () => Result,
33
35
  RetryDelayLimitExceeded: () => RetryDelayLimitExceeded,
34
36
  RetryDelayNone: () => RetryDelayNone,
35
37
  RetryDelaySeq: () => RetryDelaySeq,
36
38
  RetryDelayer: () => RetryDelayer,
37
39
  RingBuffer: () => RingBuffer,
40
+ TimedOut: () => TimedOut,
41
+ TimeoutError: () => TimeoutError,
42
+ abortPromise: () => abortPromise,
38
43
  abortSignalKey: () => abortSignalKey,
44
+ catchErrors: () => catchErrors,
39
45
  createLogProvider: () => createLogProvider,
46
+ debounce: () => debounce,
47
+ delayAsync: () => delayAsync,
48
+ delayAsyncWith: () => delayAsyncWith,
40
49
  errorResult: () => errorResult,
41
50
  initLogging: () => initLogging,
42
51
  initWorkerLogging: () => initWorkerLogging,
43
52
  resolvedVoidPromise: () => resolvedVoidPromise,
44
53
  result: () => result,
45
54
  resultFrom: () => resultFrom,
46
- resultFromAsync: () => resultFromAsync
55
+ resultFromAsync: () => resultFromAsync,
56
+ retry: () => retry,
57
+ serialize: () => serialize,
58
+ throttle: () => throttle,
59
+ withTimeout: () => withTimeout
47
60
  });
48
61
  module.exports = __toCommonJS(index_exports);
49
62
 
@@ -698,6 +711,231 @@ var EventHandlerSet = class {
698
711
  }
699
712
  };
700
713
 
714
+ // src/withTimeout.ts
715
+ var TimeoutError = class extends Error {
716
+ name = "TimeoutError";
717
+ constructor(message = "Operation timed out") {
718
+ super(message);
719
+ }
720
+ };
721
+ async function withTimeout(promise, ms, message) {
722
+ let timer;
723
+ const timeoutPromise = new Promise((_, reject) => {
724
+ timer = setTimeout(
725
+ () => reject(new TimeoutError(message ?? `Operation timed out after ${ms}ms`)),
726
+ ms
727
+ );
728
+ });
729
+ timeoutPromise.catch(() => {
730
+ });
731
+ try {
732
+ return await Promise.race([promise, timeoutPromise]);
733
+ } finally {
734
+ if (timer !== void 0) clearTimeout(timer);
735
+ }
736
+ }
737
+
738
+ // src/promise-source-with-timeout.ts
739
+ var PromiseSourceWithTimeout = class extends PromiseSource {
740
+ _timer;
741
+ hasTimeout() {
742
+ return this._timer !== void 0;
743
+ }
744
+ /**
745
+ * Install (or replace) a timeout. Pass `null` to remove without setting a
746
+ * new one. `callback` is invoked when the timer fires — if omitted, the
747
+ * promise is rejected with a generic "timed out" error.
748
+ */
749
+ setTimeout(ms, callback) {
750
+ this.clearTimeout();
751
+ if (ms === null || this.isCompleted) return;
752
+ this._timer = setTimeout(() => {
753
+ this._timer = void 0;
754
+ if (callback) callback();
755
+ else this.reject(new TimeoutError(`The promise has timed out after ${ms}ms.`));
756
+ }, ms);
757
+ }
758
+ clearTimeout() {
759
+ if (this._timer === void 0) return;
760
+ clearTimeout(this._timer);
761
+ this._timer = void 0;
762
+ }
763
+ resolve(value) {
764
+ const didSettle = super.resolve(value);
765
+ if (didSettle) this.clearTimeout();
766
+ return didSettle;
767
+ }
768
+ reject(reason) {
769
+ const didSettle = super.reject(reason);
770
+ if (didSettle) this.clearTimeout();
771
+ return didSettle;
772
+ }
773
+ };
774
+
775
+ // src/resolved-promise.ts
776
+ var ResolvedPromise = {
777
+ Void: Promise.resolve(),
778
+ True: Promise.resolve(true),
779
+ False: Promise.resolve(false)
780
+ };
781
+
782
+ // src/timed-out.ts
783
+ var TimedOut = class _TimedOut {
784
+ static instance = new _TimedOut();
785
+ };
786
+
787
+ // src/delay.ts
788
+ function delayAsync(ms) {
789
+ return new Promise((resolve) => {
790
+ setTimeout(resolve, ms);
791
+ });
792
+ }
793
+ function delayAsyncWith(ms, value) {
794
+ return new Promise((resolve) => {
795
+ setTimeout(() => resolve(value), ms);
796
+ });
797
+ }
798
+
799
+ // src/abort-promise.ts
800
+ var abortPromiseCache = /* @__PURE__ */ new WeakMap();
801
+ function abortPromise(signal) {
802
+ if (signal.aborted) return Promise.reject(signal.reason);
803
+ let cached = abortPromiseCache.get(signal);
804
+ if (!cached) {
805
+ cached = new Promise((_, reject) => {
806
+ signal.addEventListener("abort", () => reject(signal.reason), { once: true });
807
+ });
808
+ cached.catch(() => {
809
+ });
810
+ abortPromiseCache.set(signal, cached);
811
+ }
812
+ return cached;
813
+ }
814
+
815
+ // src/internal-logging.ts
816
+ var scopeDefaults = {
817
+ retry: 3 /* Warn */,
818
+ throttle: 3 /* Warn */
819
+ };
820
+ var getLogs = createLogProvider("core.", scopeDefaults);
821
+
822
+ // src/throttle.ts
823
+ var { errorLog } = getLogs("throttle");
824
+ var Call = class {
825
+ constructor(func, self, parameters) {
826
+ this.func = func;
827
+ this.self = self;
828
+ this.parameters = parameters;
829
+ }
830
+ invoke() {
831
+ return this.func.apply(this.self, this.parameters);
832
+ }
833
+ invokeSilently() {
834
+ try {
835
+ return this.invoke();
836
+ } catch (error) {
837
+ errorLog?.log("Call.invokeSilently: unhandled error:", error);
838
+ }
839
+ }
840
+ };
841
+ function throttle(func, intervalMs, mode = "default") {
842
+ let lastCall = null;
843
+ let nextFireTime = 0;
844
+ let timeoutHandle = null;
845
+ const reset2 = () => {
846
+ if (timeoutHandle !== null) clearTimeout(timeoutHandle);
847
+ timeoutHandle = null;
848
+ lastCall = null;
849
+ nextFireTime = 0;
850
+ };
851
+ const fire = () => {
852
+ if (timeoutHandle !== null) clearTimeout(timeoutHandle);
853
+ if (lastCall !== null) {
854
+ const call = lastCall;
855
+ lastCall = null;
856
+ nextFireTime = Date.now() + intervalMs;
857
+ timeoutHandle = setTimeout(fire, intervalMs);
858
+ call.invokeSilently();
859
+ } else {
860
+ timeoutHandle = null;
861
+ nextFireTime = 0;
862
+ }
863
+ };
864
+ const wrapped = function(...args) {
865
+ const call = new Call(func, this, args);
866
+ const fireDelay = nextFireTime - Date.now();
867
+ if (timeoutHandle !== null && fireDelay <= 0) {
868
+ fire();
869
+ }
870
+ if (timeoutHandle === null) {
871
+ nextFireTime = Date.now() + intervalMs;
872
+ timeoutHandle = setTimeout(fire, intervalMs);
873
+ if (mode === "delayHead") {
874
+ lastCall = call;
875
+ } else {
876
+ call.invokeSilently();
877
+ }
878
+ } else if (mode !== "skip") {
879
+ lastCall = call;
880
+ }
881
+ };
882
+ wrapped.reset = reset2;
883
+ return wrapped;
884
+ }
885
+ function debounce(func, intervalMs) {
886
+ let lastCall = null;
887
+ let nextFireTime = 0;
888
+ let timeoutHandle = null;
889
+ const reset2 = () => {
890
+ timeoutHandle = null;
891
+ lastCall = null;
892
+ nextFireTime = 0;
893
+ };
894
+ const fire = () => {
895
+ if (timeoutHandle !== null) clearTimeout(timeoutHandle);
896
+ timeoutHandle = null;
897
+ const fireDelay = nextFireTime - Date.now();
898
+ if (fireDelay <= 0) {
899
+ nextFireTime = 0;
900
+ if (lastCall !== null) {
901
+ const call = lastCall;
902
+ lastCall = null;
903
+ call.invokeSilently();
904
+ }
905
+ } else {
906
+ timeoutHandle = setTimeout(fire, fireDelay);
907
+ }
908
+ };
909
+ const wrapped = function(...args) {
910
+ lastCall = new Call(func, this, args);
911
+ nextFireTime = Date.now() + intervalMs;
912
+ timeoutHandle ??= setTimeout(fire, intervalMs);
913
+ };
914
+ wrapped.reset = reset2;
915
+ return wrapped;
916
+ }
917
+
918
+ // src/serialize.ts
919
+ function serialize(func, limit = null) {
920
+ let lastCall = Promise.resolve(null);
921
+ let queueSize = 0;
922
+ return function(...args) {
923
+ if (limit !== null && queueSize >= limit) return lastCall;
924
+ queueSize++;
925
+ const prevCall = lastCall;
926
+ const invoke = () => func.apply(this, args);
927
+ return lastCall = (async () => {
928
+ try {
929
+ await prevCall.catch(() => {
930
+ });
931
+ return await invoke();
932
+ } finally {
933
+ queueSize--;
934
+ }
935
+ })();
936
+ };
937
+ }
938
+
701
939
  // src/ring-buffer.ts
702
940
  var RingBuffer = class {
703
941
  _buffer;
@@ -888,6 +1126,34 @@ var RetryDelayer = class {
888
1126
  this.cancelDelaysChanged.trigger();
889
1127
  }
890
1128
  };
1129
+
1130
+ // src/retry.ts
1131
+ var { warnLog } = getLogs("retry");
1132
+ var defaultRetryDelays = () => 50;
1133
+ async function retry(tryCount, fn, retryDelays = defaultRetryDelays) {
1134
+ if (tryCount <= 0)
1135
+ throw new Error("retry: tryCount must be positive.");
1136
+ let lastError;
1137
+ for (let tryIndex = 0; ; ) {
1138
+ if (tryIndex >= tryCount) throw lastError;
1139
+ try {
1140
+ return await fn(tryIndex, lastError);
1141
+ } catch (e) {
1142
+ lastError = e;
1143
+ }
1144
+ ++tryIndex;
1145
+ if (tryIndex >= tryCount) throw lastError;
1146
+ warnLog?.log(`retry(${tryIndex}/${tryCount}): error:`, lastError);
1147
+ await delayAsync(retryDelays(tryIndex));
1148
+ }
1149
+ }
1150
+ async function catchErrors(fn, onError) {
1151
+ try {
1152
+ return await fn();
1153
+ } catch (e) {
1154
+ return onError ? onError(e) : void 0;
1155
+ }
1156
+ }
891
1157
  // Annotate the CommonJS export names for ESM import in node:
892
1158
  0 && (module.exports = {
893
1159
  AsyncContext,
@@ -899,20 +1165,33 @@ var RetryDelayer = class {
899
1165
  LogLevel,
900
1166
  LogLevelController,
901
1167
  PromiseSource,
1168
+ PromiseSourceWithTimeout,
1169
+ ResolvedPromise,
902
1170
  Result,
903
1171
  RetryDelayLimitExceeded,
904
1172
  RetryDelayNone,
905
1173
  RetryDelaySeq,
906
1174
  RetryDelayer,
907
1175
  RingBuffer,
1176
+ TimedOut,
1177
+ TimeoutError,
1178
+ abortPromise,
908
1179
  abortSignalKey,
1180
+ catchErrors,
909
1181
  createLogProvider,
1182
+ debounce,
1183
+ delayAsync,
1184
+ delayAsyncWith,
910
1185
  errorResult,
911
1186
  initLogging,
912
1187
  initWorkerLogging,
913
1188
  resolvedVoidPromise,
914
1189
  result,
915
1190
  resultFrom,
916
- resultFromAsync
1191
+ resultFromAsync,
1192
+ retry,
1193
+ serialize,
1194
+ throttle,
1195
+ withTimeout
917
1196
  });
918
1197
  //# sourceMappingURL=index.cjs.map