@bgord/bun 1.1.7 → 1.2.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.
- package/dist/checksum.service.d.ts +9 -0
- package/dist/checksum.service.d.ts.map +1 -0
- package/dist/checksum.service.js +20 -0
- package/dist/checksum.service.js.map +1 -0
- package/dist/correlation-storage.service.d.ts +1 -1
- package/dist/correlation-storage.service.d.ts.map +1 -1
- package/dist/correlation-storage.service.js +2 -2
- package/dist/correlation-storage.service.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/prerequisites/clock-drift.d.ts +3 -3
- package/dist/prerequisites/clock-drift.d.ts.map +1 -1
- package/dist/prerequisites/clock-drift.js +16 -10
- package/dist/prerequisites/clock-drift.js.map +1 -1
- package/dist/prerequisites/mailer.d.ts +3 -0
- package/dist/prerequisites/mailer.d.ts.map +1 -1
- package/dist/prerequisites/mailer.js +4 -1
- package/dist/prerequisites/mailer.js.map +1 -1
- package/dist/prerequisites/outside-connectivity.d.ts +5 -1
- package/dist/prerequisites/outside-connectivity.d.ts.map +1 -1
- package/dist/prerequisites/outside-connectivity.js +4 -1
- package/dist/prerequisites/outside-connectivity.js.map +1 -1
- package/dist/prerequisites/space.d.ts +1 -1
- package/dist/prerequisites/space.d.ts.map +1 -1
- package/dist/prerequisites/space.js +2 -1
- package/dist/prerequisites/space.js.map +1 -1
- package/dist/prerequisites/translations.d.ts +4 -4
- package/dist/prerequisites/translations.d.ts.map +1 -1
- package/dist/prerequisites/translations.js +6 -5
- package/dist/prerequisites/translations.js.map +1 -1
- package/dist/timekeeper-google.adapter.d.ts +2 -1
- package/dist/timekeeper-google.adapter.d.ts.map +1 -1
- package/dist/timekeeper-google.adapter.js +3 -2
- package/dist/timekeeper-google.adapter.js.map +1 -1
- package/dist/timekeeper.port.d.ts +1 -1
- package/dist/timekeeper.port.d.ts.map +1 -1
- package/dist/timeout.service.d.ts +11 -0
- package/dist/timeout.service.d.ts.map +1 -0
- package/dist/timeout.service.js +46 -0
- package/dist/timeout.service.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/readme.md +2 -0
- package/src/checksum.service.ts +23 -0
- package/src/correlation-storage.service.ts +2 -2
- package/src/index.ts +2 -0
- package/src/prerequisites/clock-drift.ts +19 -12
- package/src/prerequisites/mailer.ts +5 -2
- package/src/prerequisites/outside-connectivity.ts +9 -2
- package/src/prerequisites/space.ts +3 -2
- package/src/prerequisites/translations.ts +8 -7
- package/src/timekeeper-google.adapter.ts +4 -2
- package/src/timekeeper.port.ts +1 -1
- package/src/timeout.service.ts +71 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bgord/bun",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Bartosz Gordon",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@axiomhq/winston": "1.3.1",
|
|
41
|
-
"@bgord/tools": "1.1.
|
|
41
|
+
"@bgord/tools": "1.1.6",
|
|
42
42
|
"@hono/ua-blocker": "0.1.15",
|
|
43
43
|
"better-auth": "1.3.34",
|
|
44
44
|
"croner": "9.1.0",
|
package/readme.md
CHANGED
|
@@ -41,6 +41,7 @@ src/
|
|
|
41
41
|
├── certificate-inspector-noop.adapter.ts
|
|
42
42
|
├── certificate-inspector-tls.adapter.ts
|
|
43
43
|
├── certificate-inspector.port.ts
|
|
44
|
+
├── checksum.service.ts
|
|
44
45
|
├── client-from-hono.adapter.ts
|
|
45
46
|
├── client.vo.ts
|
|
46
47
|
├── clock-fixed.adapter.ts
|
|
@@ -232,6 +233,7 @@ src/
|
|
|
232
233
|
├── timekeeper-google.adapter.ts
|
|
233
234
|
├── timekeeper-noop.adapter.ts
|
|
234
235
|
├── timekeeper.port.ts
|
|
236
|
+
├── timeout.service.ts
|
|
235
237
|
├── to-event-map.types.ts
|
|
236
238
|
├── translations.service.ts
|
|
237
239
|
├── uptime.service.ts
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { FileHashResult } from "./file-hash.port";
|
|
2
|
+
|
|
3
|
+
export enum ChecksumStrategy {
|
|
4
|
+
etag = "etag",
|
|
5
|
+
complex = "complex",
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class Checksum {
|
|
9
|
+
static compare(first: FileHashResult, second: FileHashResult, strategy: ChecksumStrategy): boolean {
|
|
10
|
+
switch (strategy) {
|
|
11
|
+
case ChecksumStrategy.etag:
|
|
12
|
+
return first.etag === second.etag;
|
|
13
|
+
case ChecksumStrategy.complex:
|
|
14
|
+
return (
|
|
15
|
+
first.etag === second.etag &&
|
|
16
|
+
first.size === second.size &&
|
|
17
|
+
first.lastModified &&
|
|
18
|
+
second.lastModified &&
|
|
19
|
+
first.mime.isSatisfiedBy(second.mime)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -15,8 +15,8 @@ export class CorrelationStorage {
|
|
|
15
15
|
] ??=
|
|
16
16
|
new AsyncLocalStorage<CorrelationContext>());
|
|
17
17
|
|
|
18
|
-
static run<T>(correlationId: CorrelationIdType,
|
|
19
|
-
return CorrelationStorage.als.run({ correlationId },
|
|
18
|
+
static run<T>(correlationId: CorrelationIdType, action: () => T | Promise<T>): T | Promise<T> {
|
|
19
|
+
return CorrelationStorage.als.run({ correlationId }, action);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
static get(): CorrelationIdType {
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from "./cache-response.middleware";
|
|
|
14
14
|
export * from "./certificate-inspector.port";
|
|
15
15
|
export * from "./certificate-inspector-noop.adapter";
|
|
16
16
|
export * from "./certificate-inspector-tls.adapter";
|
|
17
|
+
export * from "./checksum.service";
|
|
17
18
|
export * from "./client.vo";
|
|
18
19
|
export * from "./client-from-hono.adapter";
|
|
19
20
|
export * from "./clock.port";
|
|
@@ -155,6 +156,7 @@ export * from "./time-zone-offset.middleware";
|
|
|
155
156
|
export * from "./timekeeper.port";
|
|
156
157
|
export * from "./timekeeper-google.adapter";
|
|
157
158
|
export * from "./timekeeper-noop.adapter";
|
|
159
|
+
export * from "./timeout.service";
|
|
158
160
|
export * from "./to-event-map.types";
|
|
159
161
|
export * from "./translations.service";
|
|
160
162
|
export * from "./uptime.service";
|
|
@@ -2,6 +2,8 @@ import * as tools from "@bgord/tools";
|
|
|
2
2
|
import type { ClockPort } from "../clock.port";
|
|
3
3
|
import * as prereqs from "../prerequisites.service";
|
|
4
4
|
import type { TimekeeperPort } from "../timekeeper.port";
|
|
5
|
+
import { TimekeeperGoogleAdapter } from "../timekeeper-google.adapter";
|
|
6
|
+
import { Timeout } from "../timeout.service";
|
|
5
7
|
|
|
6
8
|
export class PrerequisiteClockDrift implements prereqs.Prerequisite {
|
|
7
9
|
readonly kind = "clock-drift";
|
|
@@ -10,21 +12,21 @@ export class PrerequisiteClockDrift implements prereqs.Prerequisite {
|
|
|
10
12
|
|
|
11
13
|
readonly skew: tools.Duration;
|
|
12
14
|
readonly timekeeper: TimekeeperPort;
|
|
13
|
-
readonly
|
|
15
|
+
readonly timeout: tools.Duration;
|
|
14
16
|
|
|
15
17
|
constructor(
|
|
16
18
|
config: prereqs.PrerequisiteConfigType & {
|
|
17
19
|
skew: tools.Duration;
|
|
18
|
-
timekeeper
|
|
19
|
-
|
|
20
|
+
timekeeper?: TimekeeperPort;
|
|
21
|
+
timeout?: tools.Duration;
|
|
20
22
|
},
|
|
21
23
|
) {
|
|
22
24
|
this.label = config.label;
|
|
23
25
|
this.enabled = config.enabled === undefined ? true : config.enabled;
|
|
24
26
|
|
|
25
27
|
this.skew = config.skew;
|
|
26
|
-
this.timekeeper = config.timekeeper;
|
|
27
|
-
this.
|
|
28
|
+
this.timekeeper = config.timekeeper ?? new TimekeeperGoogleAdapter();
|
|
29
|
+
this.timeout = config.timeout ?? tools.Duration.Seconds(2);
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
async verify(clock: ClockPort): Promise<prereqs.VerifyOutcome> {
|
|
@@ -32,14 +34,19 @@ export class PrerequisiteClockDrift implements prereqs.Prerequisite {
|
|
|
32
34
|
|
|
33
35
|
if (!this.enabled) return prereqs.Verification.undetermined(stopwatch.stop());
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
try {
|
|
38
|
+
const timestamp = await Timeout.cancellable(
|
|
39
|
+
(signal: AbortSignal) => this.timekeeper.get(signal),
|
|
40
|
+
this.timeout,
|
|
41
|
+
);
|
|
42
|
+
if (!timestamp) return prereqs.Verification.undetermined(stopwatch.stop());
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
if (!timestamp) return prereqs.Verification.undetermined(stopwatch.stop());
|
|
44
|
+
const duration = clock.now().difference(timestamp).toAbsolute();
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
if (duration.isShorterThan(this.skew)) return prereqs.Verification.success(stopwatch.stop());
|
|
47
|
+
return prereqs.Verification.failure(stopwatch.stop(), { message: `Difference: ${duration.seconds}s` });
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return prereqs.Verification.undetermined(stopwatch.stop());
|
|
50
|
+
}
|
|
44
51
|
}
|
|
45
52
|
}
|
|
@@ -2,6 +2,7 @@ import * as tools from "@bgord/tools";
|
|
|
2
2
|
import type { ClockPort } from "../clock.port";
|
|
3
3
|
import type { MailerPort } from "../mailer.port";
|
|
4
4
|
import * as prereqs from "../prerequisites.service";
|
|
5
|
+
import { Timeout } from "../timeout.service";
|
|
5
6
|
|
|
6
7
|
export class PrerequisiteMailer implements prereqs.Prerequisite {
|
|
7
8
|
readonly kind = "mailer";
|
|
@@ -9,12 +10,14 @@ export class PrerequisiteMailer implements prereqs.Prerequisite {
|
|
|
9
10
|
readonly enabled?: boolean = true;
|
|
10
11
|
|
|
11
12
|
private readonly mailer: MailerPort;
|
|
13
|
+
readonly timeout: tools.Duration;
|
|
12
14
|
|
|
13
|
-
constructor(config: prereqs.PrerequisiteConfigType & { mailer: MailerPort }) {
|
|
15
|
+
constructor(config: prereqs.PrerequisiteConfigType & { mailer: MailerPort; timeout?: tools.Duration }) {
|
|
14
16
|
this.label = config.label;
|
|
15
17
|
this.enabled = config.enabled === undefined ? true : config.enabled;
|
|
16
18
|
|
|
17
19
|
this.mailer = config.mailer;
|
|
20
|
+
this.timeout = config.timeout ?? tools.Duration.Seconds(2);
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
async verify(clock: ClockPort): Promise<prereqs.VerifyOutcome> {
|
|
@@ -23,7 +26,7 @@ export class PrerequisiteMailer implements prereqs.Prerequisite {
|
|
|
23
26
|
if (!this.enabled) return prereqs.Verification.undetermined(stopwatch.stop());
|
|
24
27
|
|
|
25
28
|
try {
|
|
26
|
-
await this.mailer.verify();
|
|
29
|
+
await Timeout.run(this.mailer.verify(), this.timeout);
|
|
27
30
|
return prereqs.Verification.success(stopwatch.stop());
|
|
28
31
|
} catch (error) {
|
|
29
32
|
return prereqs.Verification.failure(stopwatch.stop(), error as Error);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as tools from "@bgord/tools";
|
|
2
2
|
import type { ClockPort } from "../clock.port";
|
|
3
3
|
import * as prereqs from "../prerequisites.service";
|
|
4
|
+
import { Timeout } from "../timeout.service";
|
|
4
5
|
|
|
5
6
|
export class PrerequisiteOutsideConnectivity implements prereqs.Prerequisite {
|
|
6
7
|
readonly kind = "outside-connectivity";
|
|
@@ -8,10 +9,13 @@ export class PrerequisiteOutsideConnectivity implements prereqs.Prerequisite {
|
|
|
8
9
|
readonly enabled?: boolean = true;
|
|
9
10
|
|
|
10
11
|
private readonly url = "https://google.com";
|
|
12
|
+
readonly timeout: tools.Duration;
|
|
11
13
|
|
|
12
|
-
constructor(config: prereqs.PrerequisiteConfigType) {
|
|
14
|
+
constructor(config: prereqs.PrerequisiteConfigType & { timeout?: tools.Duration }) {
|
|
13
15
|
this.label = config.label;
|
|
14
16
|
this.enabled = config.enabled === undefined ? true : config.enabled;
|
|
17
|
+
|
|
18
|
+
this.timeout = config.timeout ?? tools.Duration.Seconds(2);
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
async verify(clock: ClockPort): Promise<prereqs.VerifyOutcome> {
|
|
@@ -20,7 +24,10 @@ export class PrerequisiteOutsideConnectivity implements prereqs.Prerequisite {
|
|
|
20
24
|
try {
|
|
21
25
|
if (!this.enabled) return prereqs.Verification.undetermined(stopwatch.stop());
|
|
22
26
|
|
|
23
|
-
const response = await
|
|
27
|
+
const response = await Timeout.cancellable(
|
|
28
|
+
(signal: AbortSignal) => fetch(this.url, { method: "HEAD", signal }),
|
|
29
|
+
this.timeout,
|
|
30
|
+
);
|
|
24
31
|
|
|
25
32
|
if (response.ok) return prereqs.Verification.success(stopwatch.stop());
|
|
26
33
|
return prereqs.Verification.failure(stopwatch.stop(), { message: `HTTP ${response.status}` });
|
|
@@ -2,6 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import * as tools from "@bgord/tools";
|
|
3
3
|
import type { ClockPort } from "../clock.port";
|
|
4
4
|
import type { DiskSpaceCheckerPort } from "../disk-space-checker.port";
|
|
5
|
+
import { DiskSpaceCheckerBunAdapter } from "../disk-space-checker-bun.adapter";
|
|
5
6
|
import * as prereqs from "../prerequisites.service";
|
|
6
7
|
|
|
7
8
|
export class PrerequisiteSpace implements prereqs.Prerequisite {
|
|
@@ -13,13 +14,13 @@ export class PrerequisiteSpace implements prereqs.Prerequisite {
|
|
|
13
14
|
private readonly checker: DiskSpaceCheckerPort;
|
|
14
15
|
|
|
15
16
|
constructor(
|
|
16
|
-
config: prereqs.PrerequisiteConfigType & { minimum: tools.Size; checker
|
|
17
|
+
config: prereqs.PrerequisiteConfigType & { minimum: tools.Size; checker?: DiskSpaceCheckerPort },
|
|
17
18
|
) {
|
|
18
19
|
this.label = config.label;
|
|
19
20
|
this.enabled = config.enabled === undefined ? true : config.enabled;
|
|
20
21
|
|
|
21
22
|
this.minimum = config.minimum;
|
|
22
|
-
this.checker = config.checker;
|
|
23
|
+
this.checker = config.checker ?? new DiskSpaceCheckerBunAdapter();
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
async verify(clock: ClockPort): Promise<prereqs.VerifyOutcome> {
|
|
@@ -5,6 +5,7 @@ import type { ClockPort } from "../clock.port";
|
|
|
5
5
|
import type * as types from "../i18n.service";
|
|
6
6
|
import { I18n } from "../i18n.service";
|
|
7
7
|
import type { JsonFileReaderPort } from "../json-file-reader.port";
|
|
8
|
+
import { JsonFileReaderBunForgivingAdapter } from "../json-file-reader-bun-forgiving.adapter";
|
|
8
9
|
import type { LoggerPort } from "../logger.port";
|
|
9
10
|
import * as prereqs from "../prerequisites.service";
|
|
10
11
|
|
|
@@ -22,15 +23,15 @@ export class PrerequisiteTranslations implements prereqs.Prerequisite {
|
|
|
22
23
|
private readonly translationsPath?: typeof I18n.DEFAULT_TRANSLATIONS_PATH;
|
|
23
24
|
private readonly supportedLanguages: types.I18nConfigType["supportedLanguages"];
|
|
24
25
|
|
|
25
|
-
private readonly
|
|
26
|
-
private readonly
|
|
26
|
+
private readonly logger: LoggerPort;
|
|
27
|
+
private readonly jsonFileReader: JsonFileReaderPort;
|
|
27
28
|
|
|
28
29
|
constructor(
|
|
29
30
|
config: prereqs.PrerequisiteConfigType & {
|
|
30
31
|
translationsPath?: typeof I18n.DEFAULT_TRANSLATIONS_PATH;
|
|
31
32
|
supportedLanguages: types.I18nConfigType["supportedLanguages"];
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
logger: LoggerPort;
|
|
34
|
+
jsonFileReader?: JsonFileReaderPort;
|
|
34
35
|
},
|
|
35
36
|
) {
|
|
36
37
|
this.label = config.label;
|
|
@@ -39,8 +40,8 @@ export class PrerequisiteTranslations implements prereqs.Prerequisite {
|
|
|
39
40
|
this.translationsPath = config.translationsPath;
|
|
40
41
|
this.supportedLanguages = config.supportedLanguages;
|
|
41
42
|
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
43
|
+
this.logger = config.logger;
|
|
44
|
+
this.jsonFileReader = config.jsonFileReader ?? new JsonFileReaderBunForgivingAdapter();
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
async verify(clock: ClockPort): Promise<prereqs.VerifyOutcome> {
|
|
@@ -51,7 +52,7 @@ export class PrerequisiteTranslations implements prereqs.Prerequisite {
|
|
|
51
52
|
const translationsPath = this.translationsPath ?? I18n.DEFAULT_TRANSLATIONS_PATH;
|
|
52
53
|
|
|
53
54
|
const supportedLanguages = Object.keys(this.supportedLanguages);
|
|
54
|
-
const i18n = new I18n({ Logger: this.
|
|
55
|
+
const i18n = new I18n({ Logger: this.logger, JsonFileReader: this.jsonFileReader });
|
|
55
56
|
|
|
56
57
|
try {
|
|
57
58
|
await fsp.access(translationsPath, constants.R_OK);
|
|
@@ -2,9 +2,11 @@ import * as tools from "@bgord/tools";
|
|
|
2
2
|
import type { TimekeeperPort } from "./timekeeper.port";
|
|
3
3
|
|
|
4
4
|
export class TimekeeperGoogleAdapter implements TimekeeperPort {
|
|
5
|
-
|
|
5
|
+
static URL = "https://www.google.com/generate_204";
|
|
6
|
+
|
|
7
|
+
async get(signal?: AbortSignal) {
|
|
6
8
|
try {
|
|
7
|
-
const response = await fetch(
|
|
9
|
+
const response = await fetch(TimekeeperGoogleAdapter.URL, { signal });
|
|
8
10
|
if (!response.ok) return null;
|
|
9
11
|
|
|
10
12
|
const date = response.headers.get("Date");
|
package/src/timekeeper.port.ts
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type * as tools from "@bgord/tools";
|
|
2
|
+
import type { LoggerPort } from "../src/logger.port";
|
|
3
|
+
|
|
4
|
+
export const TimeoutError = { Exceeded: "timeout.exceeded" };
|
|
5
|
+
|
|
6
|
+
export class Timeout {
|
|
7
|
+
static async run<T>(action: Promise<T>, timeout: tools.Duration): Promise<T> {
|
|
8
|
+
return new Promise<T>((resolve, reject) => {
|
|
9
|
+
const reason = new Error(TimeoutError.Exceeded);
|
|
10
|
+
|
|
11
|
+
const canceller = setTimeout(() => reject(reason), timeout.ms);
|
|
12
|
+
|
|
13
|
+
action.then(
|
|
14
|
+
(value) => {
|
|
15
|
+
clearTimeout(canceller);
|
|
16
|
+
resolve(value);
|
|
17
|
+
},
|
|
18
|
+
(error) => {
|
|
19
|
+
clearTimeout(canceller);
|
|
20
|
+
reject(error);
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static async monitor<T>(action: Promise<T>, timeout: tools.Duration, logger: LoggerPort): Promise<T> {
|
|
27
|
+
const monitor = setTimeout(
|
|
28
|
+
() =>
|
|
29
|
+
logger.warn({
|
|
30
|
+
message: "Timeout",
|
|
31
|
+
component: "infra",
|
|
32
|
+
operation: "timeout_monitor",
|
|
33
|
+
metadata: { timeoutMs: timeout.ms },
|
|
34
|
+
}),
|
|
35
|
+
timeout.ms,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return action.finally(() => clearTimeout(monitor));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static async cancellable<T>(
|
|
42
|
+
action: (signal: AbortSignal) => Promise<T>,
|
|
43
|
+
timeout: tools.Duration,
|
|
44
|
+
): Promise<T> {
|
|
45
|
+
return new Promise<T>((resolve, reject) => {
|
|
46
|
+
const controller = new AbortController();
|
|
47
|
+
|
|
48
|
+
const reason = new Error(TimeoutError.Exceeded);
|
|
49
|
+
|
|
50
|
+
const canceller = setTimeout(() => {
|
|
51
|
+
controller.abort(reason);
|
|
52
|
+
reject(reason);
|
|
53
|
+
}, timeout.ms);
|
|
54
|
+
|
|
55
|
+
// Promise.resolve.then used to prevent the initial action(controller.signal) call
|
|
56
|
+
// from throwing before the resulting work-promise is run by promise.then.
|
|
57
|
+
const promise: Promise<T> = Promise.resolve().then(() => action(controller.signal));
|
|
58
|
+
|
|
59
|
+
promise.then(
|
|
60
|
+
(value) => {
|
|
61
|
+
clearTimeout(canceller);
|
|
62
|
+
resolve(value);
|
|
63
|
+
},
|
|
64
|
+
(error) => {
|
|
65
|
+
clearTimeout(canceller);
|
|
66
|
+
reject(error);
|
|
67
|
+
},
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|