@timeback/sdk 0.1.9 → 0.1.11
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/README.md +10 -8
- package/dist/chunk-1cqa51je.js +2 -0
- package/dist/chunk-3ew9vn2d.js +2 -0
- package/dist/chunk-6b0ppq9d.js +2 -0
- package/dist/chunk-92nnwa7t.js +2 -0
- package/dist/chunk-bavxzt1k.js +2 -0
- package/dist/chunk-c8pw96sp.js +10 -0
- package/dist/chunk-edk3nfj7.js +2 -0
- package/dist/chunk-g67efaph.js +4 -0
- package/dist/chunk-pd91g539.js +1 -0
- package/dist/chunk-sgcwg4j6.js +1 -0
- package/dist/client/adapters/react/hooks/types.d.ts +2 -29
- package/dist/client/adapters/react/hooks/types.d.ts.map +1 -1
- package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts.map +1 -1
- package/dist/client/adapters/react/index.js +2 -2
- package/dist/client/adapters/solid/types.d.ts +2 -29
- package/dist/client/adapters/solid/types.d.ts.map +1 -1
- package/dist/client/adapters/solid/types.ts +2 -18
- package/dist/client/adapters/svelte/stores/client.d.ts.map +1 -1
- package/dist/client/adapters/svelte/stores/client.ts +2 -9
- package/dist/client/adapters/svelte/stores/profile.d.ts +1 -1
- package/dist/client/adapters/svelte/stores/profile.d.ts.map +1 -1
- package/dist/client/adapters/svelte/stores/profile.ts +4 -11
- package/dist/client/adapters/svelte/stores/verification.d.ts.map +1 -1
- package/dist/client/adapters/svelte/stores/verification.ts +1 -10
- package/dist/client/adapters/svelte/types.d.ts +1 -29
- package/dist/client/adapters/svelte/types.d.ts.map +1 -1
- package/dist/client/adapters/vue/provider.d.ts.map +1 -1
- package/dist/client/adapters/vue/provider.ts +4 -11
- package/dist/client/adapters/vue/types.d.ts +2 -29
- package/dist/client/adapters/vue/types.d.ts.map +1 -1
- package/dist/client/adapters/vue/types.ts +2 -18
- package/dist/client/auth/types.d.ts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/lib/activity/activity.class.d.ts +130 -22
- package/dist/client/lib/activity/activity.class.d.ts.map +1 -1
- package/dist/client/lib/activity/transport.d.ts +15 -0
- package/dist/client/lib/activity/transport.d.ts.map +1 -0
- package/dist/client/lib/activity/types.d.ts +53 -0
- package/dist/client/lib/activity/types.d.ts.map +1 -0
- package/dist/client/lib/utils.d.ts +18 -0
- package/dist/client/lib/utils.d.ts.map +1 -1
- package/dist/client/lib/utils.ts +109 -0
- package/dist/client/namespaces/activity.d.ts +49 -7
- package/dist/client/namespaces/activity.d.ts.map +1 -1
- package/dist/client/timeback-client.class.d.ts +7 -1
- package/dist/client/timeback-client.class.d.ts.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/identity.d.ts +2 -5
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -21
- package/dist/server/adapters/express.d.ts.map +1 -1
- package/dist/server/adapters/express.js +1 -1
- package/dist/server/adapters/native.d.ts.map +1 -1
- package/dist/server/adapters/native.js +2 -2
- package/dist/server/adapters/nextjs.js +1 -1
- package/dist/server/adapters/nuxt.d.ts.map +1 -1
- package/dist/server/adapters/nuxt.js +1 -1
- package/dist/server/adapters/solid-start.d.ts.map +1 -1
- package/dist/server/adapters/solid-start.js +1 -1
- package/dist/server/adapters/svelte-kit.d.ts.map +1 -1
- package/dist/server/adapters/svelte-kit.js +1 -1
- package/dist/server/adapters/tanstack-start.d.ts.map +1 -1
- package/dist/server/adapters/tanstack-start.js +1 -1
- package/dist/server/adapters/types.d.ts +16 -4
- package/dist/server/adapters/types.d.ts.map +1 -1
- package/dist/server/adapters/utils.d.ts +1 -1
- package/dist/server/adapters/utils.d.ts.map +1 -1
- package/dist/server/handlers/activity/attempts.d.ts +1 -1
- package/dist/server/handlers/activity/attempts.d.ts.map +1 -1
- package/dist/server/handlers/activity/caliper.d.ts +54 -16
- package/dist/server/handlers/activity/caliper.d.ts.map +1 -1
- package/dist/server/handlers/activity/heartbeat-handler.d.ts +15 -0
- package/dist/server/handlers/activity/heartbeat-handler.d.ts.map +1 -0
- package/dist/server/handlers/activity/index.d.ts +5 -3
- package/dist/server/handlers/activity/index.d.ts.map +1 -1
- package/dist/server/handlers/activity/progress.d.ts +2 -2
- package/dist/server/handlers/activity/progress.d.ts.map +1 -1
- package/dist/server/handlers/activity/schema.d.ts +40 -6
- package/dist/server/handlers/activity/schema.d.ts.map +1 -1
- package/dist/server/handlers/activity/submit-handler.d.ts +29 -0
- package/dist/server/handlers/activity/submit-handler.d.ts.map +1 -0
- package/dist/server/handlers/activity/submit.d.ts +44 -0
- package/dist/server/handlers/activity/submit.d.ts.map +1 -0
- package/dist/server/handlers/activity/types.d.ts +126 -5
- package/dist/server/handlers/activity/types.d.ts.map +1 -1
- package/dist/server/handlers/identity/handler.d.ts +23 -4
- package/dist/server/handlers/identity/handler.d.ts.map +1 -1
- package/dist/server/handlers/identity/index.d.ts +2 -2
- package/dist/server/handlers/identity/index.d.ts.map +1 -1
- package/dist/server/handlers/identity/oidc.d.ts.map +1 -1
- package/dist/server/handlers/identity/types.d.ts +0 -6
- package/dist/server/handlers/identity/types.d.ts.map +1 -1
- package/dist/server/handlers/index.d.ts +3 -3
- package/dist/server/handlers/index.d.ts.map +1 -1
- package/dist/server/handlers/user/handler.d.ts.map +1 -1
- package/dist/server/handlers/user/profile.d.ts.map +1 -1
- package/dist/server/handlers/user/types.d.ts +3 -0
- package/dist/server/handlers/user/types.d.ts.map +1 -1
- package/dist/server/handlers/user/verify.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/lib/hooks.d.ts +20 -0
- package/dist/server/lib/hooks.d.ts.map +1 -0
- package/dist/server/lib/index.d.ts +4 -2
- package/dist/server/lib/index.d.ts.map +1 -1
- package/dist/server/lib/logger.d.ts +36 -9
- package/dist/server/lib/logger.d.ts.map +1 -1
- package/dist/server/lib/resolve.d.ts +1 -1
- package/dist/server/lib/resolve.d.ts.map +1 -1
- package/dist/server/lib/utils.d.ts +23 -2
- package/dist/server/lib/utils.d.ts.map +1 -1
- package/dist/server/lib/validation.d.ts +55 -0
- package/dist/server/lib/validation.d.ts.map +1 -0
- package/dist/server/namespaces/activity/index.d.ts +8 -0
- package/dist/server/namespaces/activity/index.d.ts.map +1 -0
- package/dist/server/namespaces/activity/record.d.ts +49 -0
- package/dist/server/namespaces/activity/record.d.ts.map +1 -0
- package/dist/server/namespaces/activity/schema.d.ts +50 -0
- package/dist/server/namespaces/activity/schema.d.ts.map +1 -0
- package/dist/server/namespaces/user/get-profile.d.ts +32 -0
- package/dist/server/namespaces/user/get-profile.d.ts.map +1 -0
- package/dist/server/namespaces/user/index.d.ts +8 -0
- package/dist/server/namespaces/user/index.d.ts.map +1 -0
- package/dist/server/namespaces/user/verify.d.ts +28 -0
- package/dist/server/namespaces/user/verify.d.ts.map +1 -0
- package/dist/server/timeback-identity.d.ts +3 -3
- package/dist/server/timeback.d.ts +5 -3
- package/dist/server/timeback.d.ts.map +1 -1
- package/dist/server/types.d.ts +407 -14
- package/dist/server/types.d.ts.map +1 -1
- package/dist/shared/constants.d.ts +7 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.ts +51 -0
- package/dist/shared/index.d.ts +9 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/schemas.d.ts +57 -0
- package/dist/shared/schemas.d.ts.map +1 -0
- package/dist/shared/types.d.ts +287 -18
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.ts +636 -0
- package/package.json +7 -10
- package/dist/chunk-07j8zre9.js +0 -2
- package/dist/chunk-5171mkp2.js +0 -2
- package/dist/chunk-63afdp3y.js +0 -8
- package/dist/chunk-8gg8n8v9.js +0 -2
- package/dist/chunk-9se82640.js +0 -1
- package/dist/chunk-agpf1x3g.js +0 -16
- package/dist/chunk-hnf0tart.js +0 -2
- package/dist/chunk-qr0bbnsr.js +0 -1
- package/dist/chunk-whc53e0y.js +0 -11
- package/dist/chunk-x9gvef7q.js +0 -1
- package/dist/edge.d.ts +0 -13
- package/dist/edge.d.ts.map +0 -1
- package/dist/edge.js +0 -1
- package/dist/server/handlers/activity/handler.d.ts +0 -32
- package/dist/server/handlers/activity/handler.d.ts.map +0 -1
- package/dist/shared/xp-calculator.d.ts +0 -25
- package/dist/shared/xp-calculator.d.ts.map +0 -1
|
@@ -3,33 +3,5 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Types for Svelte-specific stores.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Verification state for the current user.
|
|
9
|
-
*/
|
|
10
|
-
export type TimebackVerificationState = {
|
|
11
|
-
status: 'loading';
|
|
12
|
-
} | {
|
|
13
|
-
status: 'verified';
|
|
14
|
-
timebackId: string;
|
|
15
|
-
} | {
|
|
16
|
-
status: 'unverified';
|
|
17
|
-
} | {
|
|
18
|
-
status: 'error';
|
|
19
|
-
message: string;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Profile state for the current user.
|
|
23
|
-
*/
|
|
24
|
-
export type TimebackProfileState = {
|
|
25
|
-
status: 'idle';
|
|
26
|
-
} | {
|
|
27
|
-
status: 'loading';
|
|
28
|
-
} | {
|
|
29
|
-
status: 'loaded';
|
|
30
|
-
profile: TimebackProfile;
|
|
31
|
-
} | {
|
|
32
|
-
status: 'error';
|
|
33
|
-
message: string;
|
|
34
|
-
};
|
|
6
|
+
export type { TimebackProfileState, TimebackVerificationState } from '../../../shared/types';
|
|
35
7
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/svelte/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/svelte/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/vue/provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/vue/provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAIrD,OAAO,KAAK,EAAgB,QAAQ,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AA2B7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,gBAAgB;IAG3B,wFAAwF;;;;;;;;IAAxF,wFAAwF;;;;;;;0FAoBxF,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,WAAW,IAAI,UAAU,CAAC,cAAc,GAAG,SAAS,CAAC,CAQpE"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { TimebackClient } from '@timeback/sdk/client'
|
|
2
1
|
import { defineComponent, inject, onMounted, provide, shallowRef } from 'vue'
|
|
3
2
|
|
|
3
|
+
import { TimebackClient } from '@timeback/sdk/client'
|
|
4
|
+
|
|
5
|
+
import { isBrowser } from '../../lib/utils'
|
|
6
|
+
|
|
4
7
|
import type { InjectionKey, PropType, ShallowRef } from 'vue'
|
|
5
8
|
|
|
6
9
|
/**
|
|
@@ -14,16 +17,6 @@ import type { InjectionKey, PropType, ShallowRef } from 'vue'
|
|
|
14
17
|
*/
|
|
15
18
|
const TimebackKey: InjectionKey<ShallowRef<TimebackClient | undefined>> = Symbol('timeback')
|
|
16
19
|
|
|
17
|
-
/**
|
|
18
|
-
* Check if we're running in the browser.
|
|
19
|
-
*
|
|
20
|
-
* @returns True if in browser
|
|
21
|
-
*/
|
|
22
|
-
function isBrowser(): boolean {
|
|
23
|
-
return typeof window !== 'undefined'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Singleton client instance for browser
|
|
27
20
|
let clientInstance: TimebackClient | undefined
|
|
28
21
|
|
|
29
22
|
/**
|
|
@@ -3,35 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Types for Vue-specific composables.
|
|
5
5
|
*/
|
|
6
|
-
import type {
|
|
7
|
-
|
|
8
|
-
* Verification state for the current user.
|
|
9
|
-
*/
|
|
10
|
-
export type TimebackVerificationState = {
|
|
11
|
-
status: 'loading';
|
|
12
|
-
} | {
|
|
13
|
-
status: 'verified';
|
|
14
|
-
timebackId: string;
|
|
15
|
-
} | {
|
|
16
|
-
status: 'unverified';
|
|
17
|
-
} | {
|
|
18
|
-
status: 'error';
|
|
19
|
-
message: string;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Profile state for the current user.
|
|
23
|
-
*/
|
|
24
|
-
export type TimebackProfileState = {
|
|
25
|
-
status: 'idle';
|
|
26
|
-
} | {
|
|
27
|
-
status: 'loading';
|
|
28
|
-
} | {
|
|
29
|
-
status: 'loaded';
|
|
30
|
-
profile: TimebackProfile;
|
|
31
|
-
} | {
|
|
32
|
-
status: 'error';
|
|
33
|
-
message: string;
|
|
34
|
-
};
|
|
6
|
+
import type { TimebackProfileState, TimebackVerificationState } from '../../../shared/types';
|
|
7
|
+
export type { TimebackProfileState, TimebackVerificationState } from '../../../shared/types';
|
|
35
8
|
/**
|
|
36
9
|
* Options for the useTimebackVerification composable.
|
|
37
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/vue/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/vue/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AAE5F,YAAY,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AAE5F;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC7C,gDAAgD;IAChD,KAAK,EAAE,yBAAyB,CAAA;IAEhC,qDAAqD;IACrD,OAAO,EAAE,MAAM,IAAI,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,2CAA2C;IAC3C,KAAK,EAAE,oBAAoB,CAAA;IAE3B,gFAAgF;IAChF,QAAQ,EAAE,OAAO,CAAA;IAEjB,oEAAoE;IACpE,YAAY,EAAE,MAAM,IAAI,CAAA;IAExB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,IAAI,CAAA;CACnB"}
|
|
@@ -4,25 +4,9 @@
|
|
|
4
4
|
* Types for Vue-specific composables.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {
|
|
7
|
+
import type { TimebackProfileState, TimebackVerificationState } from '../../../shared/types'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
* Verification state for the current user.
|
|
11
|
-
*/
|
|
12
|
-
export type TimebackVerificationState =
|
|
13
|
-
| { status: 'loading' }
|
|
14
|
-
| { status: 'verified'; timebackId: string }
|
|
15
|
-
| { status: 'unverified' }
|
|
16
|
-
| { status: 'error'; message: string }
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Profile state for the current user.
|
|
20
|
-
*/
|
|
21
|
-
export type TimebackProfileState =
|
|
22
|
-
| { status: 'idle' }
|
|
23
|
-
| { status: 'loading' }
|
|
24
|
-
| { status: 'loaded'; profile: TimebackProfile }
|
|
25
|
-
| { status: 'error'; message: string }
|
|
9
|
+
export type { TimebackProfileState, TimebackVerificationState } from '../../../shared/types'
|
|
26
10
|
|
|
27
11
|
/**
|
|
28
12
|
* Options for the useTimebackVerification composable.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Client Auth Types
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Extension point for customizing how the SDK makes HTTP requests.
|
|
5
5
|
*/
|
|
6
6
|
export type TimebackFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
7
7
|
/**
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,32 +1,56 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Activity Class
|
|
3
3
|
*
|
|
4
|
-
* Client-side activity tracking
|
|
4
|
+
* Client-side activity tracking with continuous time-spent reporting.
|
|
5
5
|
*/
|
|
6
|
-
import type { ActivityEndData,
|
|
6
|
+
import type { ActivityEndData, ActivityParams } from '../../../shared/types';
|
|
7
|
+
import type { ActivityCallbacks } from './types';
|
|
7
8
|
/**
|
|
8
|
-
* Activity tracker
|
|
9
|
+
* Activity tracker with continuous heartbeat reporting.
|
|
9
10
|
*
|
|
10
|
-
* Activities are started immediately on construction.
|
|
11
|
+
* Activities are started immediately on construction. Heartbeats are sent
|
|
12
|
+
* at regular intervals to report time spent. Use `pause()`, `resume()`,
|
|
11
13
|
* and `end()` to control the activity lifecycle.
|
|
12
14
|
*/
|
|
13
15
|
export declare class Activity {
|
|
14
16
|
private readonly params;
|
|
15
|
-
|
|
17
|
+
/** Activity slug passed to `start()`. */
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly runId: string;
|
|
16
20
|
private readonly _startedAt;
|
|
21
|
+
private readonly _timeEnabled;
|
|
22
|
+
private readonly _timeOptions;
|
|
23
|
+
private readonly _callbacks;
|
|
24
|
+
private _windowStartMs;
|
|
25
|
+
private _activeSinceMs;
|
|
26
|
+
private _accumulatedActiveMs;
|
|
27
|
+
private _totalFlushedActiveMs;
|
|
17
28
|
private _isPaused;
|
|
18
|
-
private _pausedAt;
|
|
19
|
-
private _totalPausedMs;
|
|
20
29
|
private _ended;
|
|
30
|
+
private _ending;
|
|
31
|
+
private _heartbeatTimer;
|
|
32
|
+
private _flushInFlight;
|
|
33
|
+
private _boundVisibilityHandler;
|
|
34
|
+
private _boundPageHideHandler;
|
|
35
|
+
private _hiddenTimeoutTimer;
|
|
36
|
+
private _timedOutWhileHidden;
|
|
21
37
|
/**
|
|
22
38
|
* Create and start a new activity tracker.
|
|
23
39
|
*
|
|
24
|
-
* The activity timer begins immediately.
|
|
40
|
+
* The activity timer begins immediately. Heartbeats are sent at regular
|
|
41
|
+
* intervals (default: 15 seconds) to report accumulated time.
|
|
25
42
|
*
|
|
26
43
|
* @param params - Activity parameters
|
|
27
|
-
* @param
|
|
44
|
+
* @param callbacks - Network operation callbacks
|
|
28
45
|
*/
|
|
29
|
-
constructor(params: ActivityParams,
|
|
46
|
+
constructor(params: ActivityParams, callbacks: ActivityCallbacks);
|
|
47
|
+
/**
|
|
48
|
+
* Build an error context object for the `onError` callback.
|
|
49
|
+
*
|
|
50
|
+
* @param type - Which operation failed
|
|
51
|
+
* @returns Error context
|
|
52
|
+
*/
|
|
53
|
+
private _errorContext;
|
|
30
54
|
/**
|
|
31
55
|
* When the activity was started.
|
|
32
56
|
*
|
|
@@ -40,34 +64,118 @@ export declare class Activity {
|
|
|
40
64
|
*/
|
|
41
65
|
get isPaused(): boolean;
|
|
42
66
|
/**
|
|
43
|
-
*
|
|
67
|
+
* Whether the activity has ended.
|
|
44
68
|
*
|
|
45
|
-
* @returns
|
|
69
|
+
* @returns True if `end()` completed successfully
|
|
70
|
+
*/
|
|
71
|
+
get isEnded(): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Active time in the current heartbeat window in milliseconds.
|
|
74
|
+
*
|
|
75
|
+
* Resets to 0 after each flush (heartbeat). For total time across all
|
|
76
|
+
* windows, use {@link totalActiveMs}.
|
|
77
|
+
*
|
|
78
|
+
* @returns Active milliseconds in the current window
|
|
46
79
|
*/
|
|
47
80
|
get elapsedMs(): number;
|
|
48
81
|
/**
|
|
49
|
-
*
|
|
82
|
+
* Total active time in milliseconds since the activity started.
|
|
50
83
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
84
|
+
* Accumulates across all flushed heartbeat windows plus the current
|
|
85
|
+
* in-progress window. Not affected by pause/resume or hidden timeouts
|
|
86
|
+
* (those reset the window but already-flushed time is preserved).
|
|
53
87
|
*
|
|
54
|
-
* @
|
|
55
|
-
|
|
88
|
+
* @returns Total active milliseconds
|
|
89
|
+
*/
|
|
90
|
+
get totalActiveMs(): number;
|
|
91
|
+
/**
|
|
92
|
+
* Get accumulated active time in the current window, including any in-progress period.
|
|
93
|
+
*
|
|
94
|
+
* @returns Active milliseconds in current window
|
|
56
95
|
*/
|
|
57
|
-
|
|
96
|
+
private _getCurrentWindowActiveMs;
|
|
58
97
|
/**
|
|
59
|
-
*
|
|
98
|
+
* Start the heartbeat interval timer.
|
|
99
|
+
*/
|
|
100
|
+
private _startHeartbeatTimer;
|
|
101
|
+
/**
|
|
102
|
+
* Stop the heartbeat interval timer.
|
|
103
|
+
*/
|
|
104
|
+
private _stopHeartbeatTimer;
|
|
105
|
+
/**
|
|
106
|
+
* Restart the heartbeat interval timer.
|
|
107
|
+
*
|
|
108
|
+
* Used after visibility-triggered flushes to ensure the next heartbeat
|
|
109
|
+
* fires at a full interval from when the page became visible again.
|
|
110
|
+
*/
|
|
111
|
+
private _restartHeartbeatTimer;
|
|
112
|
+
/**
|
|
113
|
+
* Set up visibility and pagehide event listeners for time tracking.
|
|
114
|
+
*/
|
|
115
|
+
private _setupVisibilityHandlers;
|
|
116
|
+
/**
|
|
117
|
+
* Clean up event listeners.
|
|
118
|
+
*/
|
|
119
|
+
private _teardownVisibilityHandlers;
|
|
120
|
+
/**
|
|
121
|
+
* Handle visibility change events — pause/resume time accumulation and flush as configured.
|
|
122
|
+
*/
|
|
123
|
+
private _handleVisibilityChange;
|
|
124
|
+
/**
|
|
125
|
+
* Start the hidden timeout timer.
|
|
126
|
+
*
|
|
127
|
+
* After this timeout expires, heartbeats stop and the tracking window
|
|
128
|
+
* resets when the user returns so the extended absence isn't counted.
|
|
129
|
+
*/
|
|
130
|
+
private _startHiddenTimeout;
|
|
131
|
+
/**
|
|
132
|
+
* Clear the hidden timeout timer.
|
|
133
|
+
*/
|
|
134
|
+
private _clearHiddenTimeout;
|
|
135
|
+
/**
|
|
136
|
+
* Handle pagehide events — best-effort flush via sendBeacon or fetch keepalive.
|
|
137
|
+
*/
|
|
138
|
+
private _handlePageHide;
|
|
139
|
+
private _flushSync;
|
|
140
|
+
/**
|
|
141
|
+
* Build heartbeat payload for the current time window.
|
|
142
|
+
*
|
|
143
|
+
* @param endMs - End timestamp in milliseconds
|
|
144
|
+
* @param activeMs - Active time in milliseconds
|
|
145
|
+
* @returns Heartbeat payload
|
|
146
|
+
*/
|
|
147
|
+
private _buildHeartbeatPayload;
|
|
148
|
+
/**
|
|
149
|
+
* Flush accumulated time to server.
|
|
150
|
+
*
|
|
151
|
+
* Serialized — only one flush can be in flight at a time. No-op when
|
|
152
|
+
* time tracking is disabled (`time: false`).
|
|
153
|
+
*
|
|
154
|
+
* @returns Promise that resolves when flush completes
|
|
155
|
+
*/
|
|
156
|
+
flushTimeSpent(): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* Pause the activity.
|
|
159
|
+
*
|
|
160
|
+
* Flushes accumulated time, then stops heartbeats until `resume()` is called.
|
|
60
161
|
*/
|
|
61
162
|
pause(): void;
|
|
62
163
|
/**
|
|
63
|
-
* Resume the activity
|
|
164
|
+
* Resume the activity.
|
|
165
|
+
*
|
|
166
|
+
* Starts a fresh tracking window and restarts heartbeats.
|
|
64
167
|
*/
|
|
65
168
|
resume(): void;
|
|
66
169
|
/**
|
|
67
|
-
* End the activity
|
|
170
|
+
* End the activity.
|
|
171
|
+
*
|
|
172
|
+
* Performs a final heartbeat flush then sends the completion event
|
|
173
|
+
* (if metrics or pctComplete are provided). If the network call fails,
|
|
174
|
+
* the activity remains usable so the consumer can retry.
|
|
68
175
|
*
|
|
69
176
|
* @param data - Activity completion data (metrics + optional time override)
|
|
70
177
|
*/
|
|
71
|
-
end(data
|
|
178
|
+
end(data?: ActivityEndData): Promise<void>;
|
|
179
|
+
private _sendCompletion;
|
|
72
180
|
}
|
|
73
181
|
//# sourceMappingURL=activity.class.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.class.d.ts","sourceRoot":"","sources":["../../../../src/client/lib/activity/activity.class.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"activity.class.d.ts","sourceRoot":"","sources":["../../../../src/client/lib/activity/activity.class.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EACX,eAAe,EAGf,cAAc,EAGd,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAEhD;;;;;;GAMG;AACH,qBAAa,QAAQ;IAsCnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IArCxB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IAEtB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+B;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAE9C,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,cAAc,CAAe;IACrC,OAAO,CAAC,oBAAoB,CAAI;IAChC,OAAO,CAAC,qBAAqB,CAAI;IAEjC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAQ;IAEvB,OAAO,CAAC,eAAe,CAA8C;IAErE,OAAO,CAAC,cAAc,CAA6B;IAEnD,OAAO,CAAC,uBAAuB,CAA4B;IAC3D,OAAO,CAAC,qBAAqB,CAA4B;IACzD,OAAO,CAAC,mBAAmB,CAA6C;IACxE,OAAO,CAAC,oBAAoB,CAAQ;IAEpC;;;;;;;;OAQG;IACH,YACkB,MAAM,EAAE,cAAc,EACvC,SAAS,EAAE,iBAAiB,EA+B5B;IAED;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;OAIG;IACH,IAAI,SAAS,IAAI,IAAI,CAEpB;IAED;;;;OAIG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;;OAIG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;;;;;OAOG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;;;;;;;OAQG;IACH,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED;;;;OAIG;IACH,OAAO,CAAC,yBAAyB;IAUjC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAQ5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAK9B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAchC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAcnC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA0C/B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAoB3B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;OAEG;IACH,OAAO,CAAC,eAAe;YAuBT,UAAU;IAoBxB;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;;;;;;OAOG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA0DpC;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAcZ;IAED;;;;OAIG;IACH,MAAM,IAAI,IAAI,CAkBb;IAED;;;;;;;;OAQG;IACG,GAAG,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqDnD;YAOa,eAAe;CA4C7B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity Transport
|
|
3
|
+
*
|
|
4
|
+
* HTTP transport for activity heartbeats and submissions.
|
|
5
|
+
* Encapsulates page-exit transport policy (sendBeacon vs keepalive fetch).
|
|
6
|
+
*/
|
|
7
|
+
import type { ActivityTransport, ActivityTransportConfig } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Create activity transport.
|
|
10
|
+
*
|
|
11
|
+
* @param config - Transport configuration
|
|
12
|
+
* @returns Activity transport
|
|
13
|
+
*/
|
|
14
|
+
export declare function createActivityTransport(config: ActivityTransportConfig): ActivityTransport;
|
|
15
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../../src/client/lib/activity/transport.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAEzE;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,uBAAuB,GAAG,iBAAiB,CAmH1F"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity Module Types
|
|
3
|
+
*
|
|
4
|
+
* Internal types for activity tracking.
|
|
5
|
+
*/
|
|
6
|
+
import type { ActivityHeartbeatPayload, ActivitySubmitPayload } from '../../../shared/types';
|
|
7
|
+
import type { TimebackFetch } from '../../auth/types';
|
|
8
|
+
/**
|
|
9
|
+
* Callbacks for activity network operations.
|
|
10
|
+
*/
|
|
11
|
+
export interface ActivityCallbacks {
|
|
12
|
+
/** Send heartbeat (normal) */
|
|
13
|
+
sendHeartbeat: (payload: ActivityHeartbeatPayload) => Promise<void>;
|
|
14
|
+
/** Send heartbeat on page exit (beacon/keepalive) */
|
|
15
|
+
sendHeartbeatOnPageHide: (payload: ActivityHeartbeatPayload) => Promise<void>;
|
|
16
|
+
/** Send completion */
|
|
17
|
+
sendSubmit: (payload: ActivitySubmitPayload) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Configuration for activity transport.
|
|
21
|
+
*/
|
|
22
|
+
export interface ActivityTransportConfig {
|
|
23
|
+
/** Base URL for Timeback API routes */
|
|
24
|
+
baseURL: string;
|
|
25
|
+
/** Fetch implementation (possibly plugin-wrapped) */
|
|
26
|
+
fetch: TimebackFetch;
|
|
27
|
+
/**
|
|
28
|
+
* Whether sendBeacon is safe to use on page exit.
|
|
29
|
+
*
|
|
30
|
+
* False when fetch plugins are present (e.g. for bearer token auth),
|
|
31
|
+
* since sendBeacon cannot set Authorization headers.
|
|
32
|
+
*/
|
|
33
|
+
canUseBeacon: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Credentials policy for fetch requests.
|
|
36
|
+
*
|
|
37
|
+
* Defaults to `'include'` (sends cookies cross-origin). Use `'same-origin'`
|
|
38
|
+
* or `'omit'` for token-based or cross-origin setups where cookies are not needed.
|
|
39
|
+
*/
|
|
40
|
+
credentials: RequestCredentials;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Activity transport interface.
|
|
44
|
+
*/
|
|
45
|
+
export interface ActivityTransport {
|
|
46
|
+
/** Send heartbeat (normal fetch) */
|
|
47
|
+
sendHeartbeat: (payload: ActivityHeartbeatPayload) => Promise<void>;
|
|
48
|
+
/** Send heartbeat on page exit (beacon or keepalive fetch) */
|
|
49
|
+
sendHeartbeatOnPageHide: (payload: ActivityHeartbeatPayload) => Promise<void>;
|
|
50
|
+
/** Send completion (normal fetch) */
|
|
51
|
+
sendSubmit: (payload: ActivitySubmitPayload) => Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/client/lib/activity/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC5F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAMrD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,8BAA8B;IAC9B,aAAa,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,qDAAqD;IACrD,uBAAuB,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7E,sBAAsB;IACtB,UAAU,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D;AAMD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACvC,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,KAAK,EAAE,aAAa,CAAA;IACpB;;;;;OAKG;IACH,YAAY,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,WAAW,EAAE,kBAAkB,CAAA;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,oCAAoC;IACpC,aAAa,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnE,8DAA8D;IAC9D,uBAAuB,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7E,qCAAqC;IACrC,UAAU,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D"}
|
|
@@ -32,4 +32,22 @@ export declare function sleep(ms: number): Promise<void>;
|
|
|
32
32
|
* @returns Delay in milliseconds
|
|
33
33
|
*/
|
|
34
34
|
export declare function getRetryDelay(delays: number | readonly number[], attempt: number): number;
|
|
35
|
+
/**
|
|
36
|
+
* Execute an async operation with optional retry and exponential backoff.
|
|
37
|
+
*
|
|
38
|
+
* @param fn - The async operation to attempt
|
|
39
|
+
* @param attempts - Number of retries (0 = no retry, just one attempt)
|
|
40
|
+
* @param delays - Delay schedule between retries
|
|
41
|
+
* @returns The result of `fn`
|
|
42
|
+
*/
|
|
43
|
+
export declare function withRetry<T>(fn: () => Promise<T>, attempts: number, delays: number | readonly number[]): Promise<T>;
|
|
44
|
+
/**
|
|
45
|
+
* Generate a unique run identifier.
|
|
46
|
+
*
|
|
47
|
+
* Uses `crypto.randomUUID()` when available, with a Math.random() fallback
|
|
48
|
+
* for older browsers where crypto is unavailable.
|
|
49
|
+
*
|
|
50
|
+
* @returns Generated UUID string
|
|
51
|
+
*/
|
|
52
|
+
export declare function generateRunId(): string;
|
|
35
53
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/client/lib/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAMtD;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMzF"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/client/lib/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAMtD;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMzF;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAChC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAChC,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAWtC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client Utilities
|
|
3
|
+
*
|
|
4
|
+
* Internal utility functions for the client SDK.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_BASE_PATH } from '../../shared/constants'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check if we're in a browser environment.
|
|
11
|
+
*
|
|
12
|
+
* @returns True if in browser
|
|
13
|
+
*/
|
|
14
|
+
export function isBrowser(): boolean {
|
|
15
|
+
return typeof window !== 'undefined'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get the default base URL.
|
|
20
|
+
*
|
|
21
|
+
* Returns undefined during SSR - baseURL is resolved lazily on first API call.
|
|
22
|
+
*
|
|
23
|
+
* @returns The default base URL or undefined during SSR
|
|
24
|
+
*/
|
|
25
|
+
export function getDefaultBaseURL(): string | undefined {
|
|
26
|
+
if (!isBrowser()) {
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return `${window.location.origin}${DEFAULT_BASE_PATH}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Sleep for a given number of milliseconds.
|
|
35
|
+
*
|
|
36
|
+
* @param ms - Duration to sleep in milliseconds
|
|
37
|
+
* @returns Promise that resolves after the delay
|
|
38
|
+
*/
|
|
39
|
+
export function sleep(ms: number): Promise<void> {
|
|
40
|
+
return new Promise<void>(resolve => {
|
|
41
|
+
setTimeout(resolve, ms)
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get retry delay for a given attempt from a delay configuration.
|
|
47
|
+
*
|
|
48
|
+
* @param delays - Single delay or array of delays per attempt
|
|
49
|
+
* @param attempt - Zero-based attempt index
|
|
50
|
+
* @returns Delay in milliseconds
|
|
51
|
+
*/
|
|
52
|
+
export function getRetryDelay(delays: number | readonly number[], attempt: number): number {
|
|
53
|
+
if (typeof delays === 'number') {
|
|
54
|
+
return delays
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return delays[Math.min(attempt, delays.length - 1)] ?? 1000
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Execute an async operation with optional retry and exponential backoff.
|
|
62
|
+
*
|
|
63
|
+
* @param fn - The async operation to attempt
|
|
64
|
+
* @param attempts - Number of retries (0 = no retry, just one attempt)
|
|
65
|
+
* @param delays - Delay schedule between retries
|
|
66
|
+
* @returns The result of `fn`
|
|
67
|
+
*/
|
|
68
|
+
export async function withRetry<T>(
|
|
69
|
+
fn: () => Promise<T>,
|
|
70
|
+
attempts: number,
|
|
71
|
+
delays: number | readonly number[],
|
|
72
|
+
): Promise<T> {
|
|
73
|
+
let lastError: unknown
|
|
74
|
+
|
|
75
|
+
for (let attempt = 0; attempt <= attempts; attempt++) {
|
|
76
|
+
try {
|
|
77
|
+
return await fn()
|
|
78
|
+
} catch (error: unknown) {
|
|
79
|
+
lastError = error
|
|
80
|
+
|
|
81
|
+
if (attempt < attempts) {
|
|
82
|
+
await sleep(getRetryDelay(delays, attempt))
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Generate a unique run identifier.
|
|
92
|
+
*
|
|
93
|
+
* Uses `crypto.randomUUID()` when available, with a Math.random() fallback
|
|
94
|
+
* for older browsers where crypto is unavailable.
|
|
95
|
+
*
|
|
96
|
+
* @returns Generated UUID string
|
|
97
|
+
*/
|
|
98
|
+
export function generateRunId(): string {
|
|
99
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
100
|
+
return crypto.randomUUID()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Fallback for environments without crypto.randomUUID
|
|
104
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
105
|
+
const r = (Math.random() * 16) | 0
|
|
106
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8
|
|
107
|
+
return v.toString(16)
|
|
108
|
+
})
|
|
109
|
+
}
|