@aneuhold/core-ts-api-lib 3.0.40 → 3.0.42
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/CHANGELOG.md +19 -0
- package/lib/services/APIService/API.service.d.ts +11 -1
- package/lib/services/APIService/API.service.d.ts.map +1 -1
- package/lib/services/APIService/API.service.js +11 -0
- package/lib/services/APIService/API.service.js.map +1 -1
- package/lib/services/APIService/API.service.ts +17 -3
- package/lib/services/GCloudAPIService/GCloudAPI.service.d.ts +10 -6
- package/lib/services/GCloudAPIService/GCloudAPI.service.d.ts.map +1 -1
- package/lib/services/GCloudAPIService/GCloudAPI.service.js +51 -11
- package/lib/services/GCloudAPIService/GCloudAPI.service.js.map +1 -1
- package/lib/services/GCloudAPIService/GCloudAPI.service.ts +58 -18
- package/lib/types/AuthRefreshToken.d.ts +9 -0
- package/lib/types/AuthRefreshToken.d.ts.map +1 -1
- package/lib/types/AuthRefreshToken.ts +11 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 🔖 [3.0.42] (2026-08-13)
|
|
9
|
+
|
|
10
|
+
### 🏗️ Changed
|
|
11
|
+
|
|
12
|
+
- Updated `@aneuhold/core-ts-db-lib` to `^5.0.11` and `@aneuhold/core-ts-lib` to `^2.4.7`.
|
|
13
|
+
|
|
14
|
+
## 🔖 [3.0.41] (2026-07-23)
|
|
15
|
+
|
|
16
|
+
### ✅ Added
|
|
17
|
+
|
|
18
|
+
- Added `APIService.setOnAuthExpired()` and `GCloudAPIService.setOnAuthExpired()` to register a callback that fires when a session cannot be recovered from a 401, so consumers can clear stored tokens and prompt re-login.
|
|
19
|
+
- Added the `OnAuthExpiredCallback` and `OnTokensRefreshedCallback` types to `AuthRefreshToken.ts`.
|
|
20
|
+
|
|
21
|
+
### 🩹 Fixed
|
|
22
|
+
|
|
23
|
+
- Fixed 401 handling in `GCloudAPIService` so a request with no refresh token, a failed token refresh, or a post-refresh retry that is still a 401 all report expired auth instead of silently returning the unauthorized response.
|
|
24
|
+
|
|
8
25
|
## 🔖 [3.0.40] (2026-06-19)
|
|
9
26
|
|
|
10
27
|
### 🏗️ Changed
|
|
@@ -439,6 +456,8 @@ No direct code changes; version bump for compatibility.
|
|
|
439
456
|
- Updated workflow permissions to allow repository write access
|
|
440
457
|
|
|
441
458
|
<!-- Link References -->
|
|
459
|
+
[3.0.42]: https://github.com/aneuhold/ts-libs/compare/core-ts-api-lib-v3.0.41...core-ts-api-lib-v3.0.42
|
|
460
|
+
[3.0.41]: https://github.com/aneuhold/ts-libs/compare/core-ts-api-lib-v3.0.40...core-ts-api-lib-v3.0.41
|
|
442
461
|
[3.0.40]: https://github.com/aneuhold/ts-libs/compare/core-ts-api-lib-v3.0.39...core-ts-api-lib-v3.0.40
|
|
443
462
|
[3.0.39]: https://github.com/aneuhold/ts-libs/compare/core-ts-api-lib-v3.0.38...core-ts-api-lib-v3.0.39
|
|
444
463
|
[3.0.38]: https://github.com/aneuhold/ts-libs/compare/core-ts-api-lib-v3.0.37...core-ts-api-lib-v3.0.38
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AdminInput, AdminOutput } from '../../types/Admin.js';
|
|
2
2
|
import type { APIResponse } from '../../types/APIResponse.js';
|
|
3
3
|
import type { AuthDeleteAccountOutput } from '../../types/AuthDeleteAccount.js';
|
|
4
|
+
import type { OnAuthExpiredCallback, OnTokensRefreshedCallback } from '../../types/AuthRefreshToken.js';
|
|
4
5
|
import type { AuthValidateUserInput, AuthValidateUserOutput } from '../../types/AuthValidateUser.js';
|
|
5
6
|
import type { ProjectDashboardInput, ProjectDashboardOutput } from '../../types/project/dashboard/ProjectDashboard.js';
|
|
6
7
|
import type { ProjectWorkoutPrimaryInput, ProjectWorkoutPrimaryOutput } from '../../types/project/workout/ProjectWorkout.js';
|
|
@@ -45,7 +46,16 @@ export default class APIService {
|
|
|
45
46
|
*
|
|
46
47
|
* @param callback - The callback receiving the new accessToken and refreshTokenString.
|
|
47
48
|
*/
|
|
48
|
-
static setOnTokensRefreshed(callback:
|
|
49
|
+
static setOnTokensRefreshed(callback: OnTokensRefreshedCallback | null): void;
|
|
50
|
+
/**
|
|
51
|
+
* Registers a callback that is invoked when the session cannot be recovered
|
|
52
|
+
* on a 401 (no refresh token, refresh failed, or the retry is still 401). The
|
|
53
|
+
* stored tokens are cleared before the callback fires, so use this to clear
|
|
54
|
+
* the consumer's own copy of them and prompt the user to log in again.
|
|
55
|
+
*
|
|
56
|
+
* @param callback - The callback invoked when auth has expired.
|
|
57
|
+
*/
|
|
58
|
+
static setOnAuthExpired(callback: OnAuthExpiredCallback | null): void;
|
|
49
59
|
/**
|
|
50
60
|
* Calls the dashboard API and returns the result.
|
|
51
61
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"API.service.d.ts","sourceRoot":"","sources":["../../../src/services/APIService/API.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,mDAAmD,CAAC;AAC3D,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,+CAA+C,CAAC;AAGvD;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B;;;;;;OAMG;WACU,YAAY,CACvB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAI/C;;;OAGG;WACU,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAItD;;;OAGG;WACU,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAI3E;;;;OAIG;IACH,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1C;;;;OAIG;IACH,MAAM,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIjD;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,
|
|
1
|
+
{"version":3,"file":"API.service.d.ts","sourceRoot":"","sources":["../../../src/services/APIService/API.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,KAAK,EACV,qBAAqB,EACrB,yBAAyB,EAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,mDAAmD,CAAC;AAC3D,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,+CAA+C,CAAC;AAGvD;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B;;;;;;OAMG;WACU,YAAY,CACvB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAI/C;;;OAGG;WACU,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAItD;;;OAGG;WACU,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAI3E;;;;OAIG;IACH,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1C;;;;OAIG;IACH,MAAM,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIjD;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI,GAAG,IAAI;IAI7E;;;;;;;OAOG;IACH,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI;IAIrE;;;;OAIG;WACU,gBAAgB,CAC3B,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAI/C;;;;OAIG;WACU,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAI/E;;;;OAIG;WACU,cAAc,CACzB,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAIpD;;OAEG;IACH,MAAM,CAAC,gBAAgB,IAAI,MAAM;IAIjC;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,MAAM,CAAC,gBAAgB,IAAI,MAAM;CAGlC"}
|
|
@@ -53,6 +53,17 @@ export default class APIService {
|
|
|
53
53
|
static setOnTokensRefreshed(callback) {
|
|
54
54
|
GCloudAPIService.setOnTokensRefreshed(callback);
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Registers a callback that is invoked when the session cannot be recovered
|
|
58
|
+
* on a 401 (no refresh token, refresh failed, or the retry is still 401). The
|
|
59
|
+
* stored tokens are cleared before the callback fires, so use this to clear
|
|
60
|
+
* the consumer's own copy of them and prompt the user to log in again.
|
|
61
|
+
*
|
|
62
|
+
* @param callback - The callback invoked when auth has expired.
|
|
63
|
+
*/
|
|
64
|
+
static setOnAuthExpired(callback) {
|
|
65
|
+
GCloudAPIService.setOnAuthExpired(callback);
|
|
66
|
+
}
|
|
56
67
|
/**
|
|
57
68
|
* Calls the dashboard API and returns the result.
|
|
58
69
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"API.service.js","sourceRoot":"","sources":["../../../src/services/APIService/API.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"API.service.js","sourceRoot":"","sources":["../../../src/services/APIService/API.service.ts"],"names":[],"mappings":"AAmBA,OAAO,gBAAgB,MAAM,0CAA0C,CAAC;AAExE;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,YAAY,CACvB,KAA4B;QAE5B,OAAO,gBAAgB,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM;QACjB,OAAO,gBAAgB,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,aAAa;QACxB,OAAO,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,cAAc,CAAC,KAAa;QACjC,gBAAgB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,qBAAqB,CAAC,KAAa;QACxC,gBAAgB,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CAAC,QAA0C;QACpE,gBAAgB,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,gBAAgB,CAAC,QAAsC;QAC5D,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAC3B,KAA4B;QAE5B,OAAO,gBAAgB,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,KAAiB;QACzC,OAAO,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,cAAc,CACzB,KAAiC;QAEjC,OAAO,gBAAgB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB;QACrB,OAAO,gBAAgB,CAAC,MAAM,EAAE,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,GAAW;QAC1B,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB;QACrB,OAAO,gBAAgB,CAAC,UAAU,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { AdminInput, AdminOutput } from '../../types/Admin.js';
|
|
2
2
|
import type { APIResponse } from '../../types/APIResponse.js';
|
|
3
3
|
import type { AuthDeleteAccountOutput } from '../../types/AuthDeleteAccount.js';
|
|
4
|
+
import type {
|
|
5
|
+
OnAuthExpiredCallback,
|
|
6
|
+
OnTokensRefreshedCallback
|
|
7
|
+
} from '../../types/AuthRefreshToken.js';
|
|
4
8
|
import type {
|
|
5
9
|
AuthValidateUserInput,
|
|
6
10
|
AuthValidateUserOutput
|
|
@@ -73,12 +77,22 @@ export default class APIService {
|
|
|
73
77
|
*
|
|
74
78
|
* @param callback - The callback receiving the new accessToken and refreshTokenString.
|
|
75
79
|
*/
|
|
76
|
-
static setOnTokensRefreshed(
|
|
77
|
-
callback: ((accessToken: string, refreshTokenString: string) => void) | null
|
|
78
|
-
): void {
|
|
80
|
+
static setOnTokensRefreshed(callback: OnTokensRefreshedCallback | null): void {
|
|
79
81
|
GCloudAPIService.setOnTokensRefreshed(callback);
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Registers a callback that is invoked when the session cannot be recovered
|
|
86
|
+
* on a 401 (no refresh token, refresh failed, or the retry is still 401). The
|
|
87
|
+
* stored tokens are cleared before the callback fires, so use this to clear
|
|
88
|
+
* the consumer's own copy of them and prompt the user to log in again.
|
|
89
|
+
*
|
|
90
|
+
* @param callback - The callback invoked when auth has expired.
|
|
91
|
+
*/
|
|
92
|
+
static setOnAuthExpired(callback: OnAuthExpiredCallback | null): void {
|
|
93
|
+
GCloudAPIService.setOnAuthExpired(callback);
|
|
94
|
+
}
|
|
95
|
+
|
|
82
96
|
/**
|
|
83
97
|
* Calls the dashboard API and returns the result.
|
|
84
98
|
*
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import type { AdminInput, AdminOutput } from '../../types/Admin.js';
|
|
2
2
|
import type { APIResponse } from '../../types/APIResponse.js';
|
|
3
3
|
import type { AuthDeleteAccountOutput } from '../../types/AuthDeleteAccount.js';
|
|
4
|
+
import type { OnAuthExpiredCallback, OnTokensRefreshedCallback } from '../../types/AuthRefreshToken.js';
|
|
4
5
|
import type { AuthValidateUserInput, AuthValidateUserOutput } from '../../types/AuthValidateUser.js';
|
|
5
6
|
import type { ProjectDashboardInput, ProjectDashboardOutput } from '../../types/project/dashboard/ProjectDashboard.js';
|
|
6
7
|
import type { ProjectWorkoutPrimaryInput, ProjectWorkoutPrimaryOutput } from '../../types/project/workout/ProjectWorkout.js';
|
|
7
|
-
/**
|
|
8
|
-
* Callback invoked after tokens are successfully refreshed. The frontend
|
|
9
|
-
* should use this to persist the new tokens (e.g. to localStorage).
|
|
10
|
-
*/
|
|
11
|
-
type OnTokensRefreshedCallback = (accessToken: string, refreshTokenString: string) => void;
|
|
12
8
|
/**
|
|
13
9
|
* A service for interacting with the Google Cloud API service for personal projects.
|
|
14
10
|
*/
|
|
@@ -48,6 +44,15 @@ export default class GCloudAPIService {
|
|
|
48
44
|
* @param callback - The callback receiving the new accessToken and refreshTokenString.
|
|
49
45
|
*/
|
|
50
46
|
static setOnTokensRefreshed(callback: OnTokensRefreshedCallback | null): void;
|
|
47
|
+
/**
|
|
48
|
+
* Registers a callback that is invoked when the session cannot be recovered
|
|
49
|
+
* on a 401 (no refresh token, refresh failed, or the post-refresh retry is
|
|
50
|
+
* still 401). The stored tokens are cleared before the callback fires, so use
|
|
51
|
+
* this to clear the consumer's own copy of them and prompt re-login.
|
|
52
|
+
*
|
|
53
|
+
* @param callback - The callback invoked when auth has expired.
|
|
54
|
+
*/
|
|
55
|
+
static setOnAuthExpired(callback: OnAuthExpiredCallback | null): void;
|
|
51
56
|
/**
|
|
52
57
|
* Calls the auth validateUser endpoint.
|
|
53
58
|
*
|
|
@@ -83,5 +88,4 @@ export default class GCloudAPIService {
|
|
|
83
88
|
*/
|
|
84
89
|
static projectWorkout(input: ProjectWorkoutPrimaryInput): Promise<APIResponse<ProjectWorkoutPrimaryOutput>>;
|
|
85
90
|
}
|
|
86
|
-
export {};
|
|
87
91
|
//# sourceMappingURL=GCloudAPI.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GCloudAPI.service.d.ts","sourceRoot":"","sources":["../../../src/services/GCloudAPIService/GCloudAPI.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAEV,uBAAuB,EACxB,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"GCloudAPI.service.d.ts","sourceRoot":"","sources":["../../../src/services/GCloudAPIService/GCloudAPI.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAEV,uBAAuB,EACxB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAGV,qBAAqB,EACrB,yBAAyB,EAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,mDAAmD,CAAC;AAC3D,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,+CAA+C,CAAC;AAEvD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;;IACnC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAmC;IAkBrE;;;;OAIG;IACH,MAAM,CAAC,MAAM,IAAI,MAAM;IAIvB;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIhC;;;;OAIG;IACH,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1C;;;;;OAKG;IACH,MAAM,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIjD;;;;;;OAMG;IACH,MAAM,CAAC,oBAAoB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI,GAAG,IAAI;IAI7E;;;;;;;OAOG;IACH,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI;IAIrE;;;;OAIG;WACU,gBAAgB,CAC3B,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAI/C;;;OAGG;WACU,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAa1D;;;OAGG;WACU,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAO/E;;;;OAIG;WACU,gBAAgB,CAC3B,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAI/C;;;;OAIG;WACU,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAIxE;;;;OAIG;WACU,cAAc,CACzB,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;CAyKrD"}
|
|
@@ -12,6 +12,8 @@ export default class GCloudAPIService {
|
|
|
12
12
|
static #accessToken;
|
|
13
13
|
static #refreshTokenString;
|
|
14
14
|
static #onTokensRefreshed = null;
|
|
15
|
+
static #onAuthExpired = null;
|
|
16
|
+
static #refreshPromise = null;
|
|
15
17
|
/**
|
|
16
18
|
* Gets the current URL of the Google Cloud API.
|
|
17
19
|
*
|
|
@@ -55,6 +57,17 @@ export default class GCloudAPIService {
|
|
|
55
57
|
static setOnTokensRefreshed(callback) {
|
|
56
58
|
this.#onTokensRefreshed = callback;
|
|
57
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Registers a callback that is invoked when the session cannot be recovered
|
|
62
|
+
* on a 401 (no refresh token, refresh failed, or the post-refresh retry is
|
|
63
|
+
* still 401). The stored tokens are cleared before the callback fires, so use
|
|
64
|
+
* this to clear the consumer's own copy of them and prompt re-login.
|
|
65
|
+
*
|
|
66
|
+
* @param callback - The callback invoked when auth has expired.
|
|
67
|
+
*/
|
|
68
|
+
static setOnAuthExpired(callback) {
|
|
69
|
+
this.#onAuthExpired = callback;
|
|
70
|
+
}
|
|
58
71
|
/**
|
|
59
72
|
* Calls the auth validateUser endpoint.
|
|
60
73
|
*
|
|
@@ -110,28 +123,55 @@ export default class GCloudAPIService {
|
|
|
110
123
|
/**
|
|
111
124
|
* Makes a call to the API. On a 401 response, automatically attempts to
|
|
112
125
|
* refresh the access token using the stored refresh token. If refresh
|
|
113
|
-
* succeeds, the original request is retried once.
|
|
126
|
+
* succeeds, the original request is retried once. When the session cannot be
|
|
127
|
+
* recovered, the stored tokens are cleared and the {@link #onAuthExpired}
|
|
128
|
+
* callback fires.
|
|
114
129
|
*
|
|
115
130
|
* @param urlPath - The path to the endpoint.
|
|
116
131
|
* @param input - The input to the endpoint.
|
|
117
132
|
*/
|
|
118
133
|
static async #call(urlPath, input) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
134
|
+
let { response, decoded } = await this.#fetchAndDecode(urlPath, input);
|
|
135
|
+
// On a 401, try once to recover by refreshing the tokens and retrying.
|
|
136
|
+
// #tryRefreshTokens returns false when there is no refresh token to use.
|
|
137
|
+
if (response.status === 401 && (await this.#tryRefreshTokens())) {
|
|
138
|
+
// Fancy destructure into pre-existing variables
|
|
139
|
+
({ response, decoded } = await this.#fetchAndDecode(urlPath, input));
|
|
140
|
+
}
|
|
141
|
+
// Still a 401 after any recovery attempt means the session cannot be
|
|
142
|
+
// recovered, so drop the dead tokens and notify the frontend to prompt
|
|
143
|
+
// re-login.
|
|
144
|
+
if (response.status === 401) {
|
|
145
|
+
this.#accessToken = undefined;
|
|
146
|
+
this.#refreshTokenString = undefined;
|
|
147
|
+
this.#onAuthExpired?.();
|
|
126
148
|
}
|
|
127
149
|
return decoded;
|
|
128
150
|
}
|
|
129
151
|
/**
|
|
130
|
-
* Attempts to refresh the access token
|
|
131
|
-
*
|
|
132
|
-
*
|
|
152
|
+
* Attempts to refresh the access token, sharing one in-flight refresh across
|
|
153
|
+
* concurrent callers. Refresh tokens rotate server-side, so parallel
|
|
154
|
+
* refreshes sent with the same token would invalidate each other and drop the
|
|
155
|
+
* session.
|
|
133
156
|
*/
|
|
134
157
|
static async #tryRefreshTokens() {
|
|
158
|
+
// Set the refreshPromise only if it is currently null, otherwise we continue.
|
|
159
|
+
this.#refreshPromise ??= this.#performTokenRefresh();
|
|
160
|
+
try {
|
|
161
|
+
return await this.#refreshPromise;
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
// Cleared once settled so the next 401 starts a fresh attempt rather than
|
|
165
|
+
// reusing a stale result.
|
|
166
|
+
this.#refreshPromise = null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Exchanges the stored refresh token for a new token pair. On success,
|
|
171
|
+
* updates the stored tokens and notifies via the {@link #onTokensRefreshed}
|
|
172
|
+
* callback.
|
|
173
|
+
*/
|
|
174
|
+
static async #performTokenRefresh() {
|
|
135
175
|
if (!this.#refreshTokenString) {
|
|
136
176
|
return false;
|
|
137
177
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GCloudAPI.service.js","sourceRoot":"","sources":["../../../src/services/GCloudAPIService/GCloudAPI.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"GCloudAPI.service.js","sourceRoot":"","sources":["../../../src/services/GCloudAPIService/GCloudAPI.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,9 @@ import type {
|
|
|
7
7
|
} from '../../types/AuthDeleteAccount.js';
|
|
8
8
|
import type {
|
|
9
9
|
AuthRefreshTokenInput,
|
|
10
|
-
AuthRefreshTokenOutput
|
|
10
|
+
AuthRefreshTokenOutput,
|
|
11
|
+
OnAuthExpiredCallback,
|
|
12
|
+
OnTokensRefreshedCallback
|
|
11
13
|
} from '../../types/AuthRefreshToken.js';
|
|
12
14
|
import type {
|
|
13
15
|
AuthValidateUserInput,
|
|
@@ -22,12 +24,6 @@ import type {
|
|
|
22
24
|
ProjectWorkoutPrimaryOutput
|
|
23
25
|
} from '../../types/project/workout/ProjectWorkout.js';
|
|
24
26
|
|
|
25
|
-
/**
|
|
26
|
-
* Callback invoked after tokens are successfully refreshed. The frontend
|
|
27
|
-
* should use this to persist the new tokens (e.g. to localStorage).
|
|
28
|
-
*/
|
|
29
|
-
type OnTokensRefreshedCallback = (accessToken: string, refreshTokenString: string) => void;
|
|
30
|
-
|
|
31
27
|
/**
|
|
32
28
|
* A service for interacting with the Google Cloud API service for personal projects.
|
|
33
29
|
*/
|
|
@@ -46,6 +42,10 @@ export default class GCloudAPIService {
|
|
|
46
42
|
|
|
47
43
|
static #onTokensRefreshed: OnTokensRefreshedCallback | null = null;
|
|
48
44
|
|
|
45
|
+
static #onAuthExpired: OnAuthExpiredCallback | null = null;
|
|
46
|
+
|
|
47
|
+
static #refreshPromise: Promise<boolean> | null = null;
|
|
48
|
+
|
|
49
49
|
/**
|
|
50
50
|
* Gets the current URL of the Google Cloud API.
|
|
51
51
|
*
|
|
@@ -94,6 +94,18 @@ export default class GCloudAPIService {
|
|
|
94
94
|
this.#onTokensRefreshed = callback;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Registers a callback that is invoked when the session cannot be recovered
|
|
99
|
+
* on a 401 (no refresh token, refresh failed, or the post-refresh retry is
|
|
100
|
+
* still 401). The stored tokens are cleared before the callback fires, so use
|
|
101
|
+
* this to clear the consumer's own copy of them and prompt re-login.
|
|
102
|
+
*
|
|
103
|
+
* @param callback - The callback invoked when auth has expired.
|
|
104
|
+
*/
|
|
105
|
+
static setOnAuthExpired(callback: OnAuthExpiredCallback | null): void {
|
|
106
|
+
this.#onAuthExpired = callback;
|
|
107
|
+
}
|
|
108
|
+
|
|
97
109
|
/**
|
|
98
110
|
* Calls the auth validateUser endpoint.
|
|
99
111
|
*
|
|
@@ -170,7 +182,9 @@ export default class GCloudAPIService {
|
|
|
170
182
|
/**
|
|
171
183
|
* Makes a call to the API. On a 401 response, automatically attempts to
|
|
172
184
|
* refresh the access token using the stored refresh token. If refresh
|
|
173
|
-
* succeeds, the original request is retried once.
|
|
185
|
+
* succeeds, the original request is retried once. When the session cannot be
|
|
186
|
+
* recovered, the stored tokens are cleared and the {@link #onAuthExpired}
|
|
187
|
+
* callback fires.
|
|
174
188
|
*
|
|
175
189
|
* @param urlPath - The path to the endpoint.
|
|
176
190
|
* @param input - The input to the endpoint.
|
|
@@ -179,25 +193,51 @@ export default class GCloudAPIService {
|
|
|
179
193
|
urlPath: string,
|
|
180
194
|
input: TInput
|
|
181
195
|
): Promise<APIResponse<TOutput>> {
|
|
182
|
-
|
|
196
|
+
let { response, decoded } = await this.#fetchAndDecode<TInput, TOutput>(urlPath, input);
|
|
183
197
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
198
|
+
// On a 401, try once to recover by refreshing the tokens and retrying.
|
|
199
|
+
// #tryRefreshTokens returns false when there is no refresh token to use.
|
|
200
|
+
if (response.status === 401 && (await this.#tryRefreshTokens())) {
|
|
201
|
+
// Fancy destructure into pre-existing variables
|
|
202
|
+
({ response, decoded } = await this.#fetchAndDecode<TInput, TOutput>(urlPath, input));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Still a 401 after any recovery attempt means the session cannot be
|
|
206
|
+
// recovered, so drop the dead tokens and notify the frontend to prompt
|
|
207
|
+
// re-login.
|
|
208
|
+
if (response.status === 401) {
|
|
209
|
+
this.#accessToken = undefined;
|
|
210
|
+
this.#refreshTokenString = undefined;
|
|
211
|
+
this.#onAuthExpired?.();
|
|
190
212
|
}
|
|
191
213
|
|
|
192
214
|
return decoded;
|
|
193
215
|
}
|
|
194
216
|
|
|
195
217
|
/**
|
|
196
|
-
* Attempts to refresh the access token
|
|
197
|
-
*
|
|
198
|
-
*
|
|
218
|
+
* Attempts to refresh the access token, sharing one in-flight refresh across
|
|
219
|
+
* concurrent callers. Refresh tokens rotate server-side, so parallel
|
|
220
|
+
* refreshes sent with the same token would invalidate each other and drop the
|
|
221
|
+
* session.
|
|
199
222
|
*/
|
|
200
223
|
static async #tryRefreshTokens(): Promise<boolean> {
|
|
224
|
+
// Set the refreshPromise only if it is currently null, otherwise we continue.
|
|
225
|
+
this.#refreshPromise ??= this.#performTokenRefresh();
|
|
226
|
+
try {
|
|
227
|
+
return await this.#refreshPromise;
|
|
228
|
+
} finally {
|
|
229
|
+
// Cleared once settled so the next 401 starts a fresh attempt rather than
|
|
230
|
+
// reusing a stale result.
|
|
231
|
+
this.#refreshPromise = null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Exchanges the stored refresh token for a new token pair. On success,
|
|
237
|
+
* updates the stored tokens and notifies via the {@link #onTokensRefreshed}
|
|
238
|
+
* callback.
|
|
239
|
+
*/
|
|
240
|
+
static async #performTokenRefresh(): Promise<boolean> {
|
|
201
241
|
if (!this.#refreshTokenString) {
|
|
202
242
|
return false;
|
|
203
243
|
}
|
|
@@ -14,4 +14,13 @@ export interface AuthRefreshTokenOutput {
|
|
|
14
14
|
/** New raw refresh token string (rotation — old one is deleted). */
|
|
15
15
|
refreshTokenString: string;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Callback invoked after tokens are successfully refreshed.
|
|
19
|
+
*/
|
|
20
|
+
export type OnTokensRefreshedCallback = (accessToken: string, refreshTokenString: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Callback invoked when a session can no longer be recovered because the access
|
|
23
|
+
* token is expired and the refresh token is missing or invalid.
|
|
24
|
+
*/
|
|
25
|
+
export type OnAuthExpiredCallback = () => void;
|
|
17
26
|
//# sourceMappingURL=AuthRefreshToken.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthRefreshToken.d.ts","sourceRoot":"","sources":["../../src/types/AuthRefreshToken.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAC;CAC5B"}
|
|
1
|
+
{"version":3,"file":"AuthRefreshToken.d.ts","sourceRoot":"","sources":["../../src/types/AuthRefreshToken.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,KAAK,IAAI,CAAC;AAElG;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC"}
|
|
@@ -15,3 +15,14 @@ export interface AuthRefreshTokenOutput {
|
|
|
15
15
|
/** New raw refresh token string (rotation — old one is deleted). */
|
|
16
16
|
refreshTokenString: string;
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Callback invoked after tokens are successfully refreshed.
|
|
21
|
+
*/
|
|
22
|
+
export type OnTokensRefreshedCallback = (accessToken: string, refreshTokenString: string) => void;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Callback invoked when a session can no longer be recovered because the access
|
|
26
|
+
* token is expired and the refresh token is missing or invalid.
|
|
27
|
+
*/
|
|
28
|
+
export type OnAuthExpiredCallback = () => void;
|
package/package.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"name": "@aneuhold/core-ts-api-lib",
|
|
3
3
|
"author": "Anton G. Neuhold Jr.",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "3.0.
|
|
5
|
+
"version": "3.0.42",
|
|
6
6
|
"description": "A library for interacting with the backend and defining the backend API for personal projects.",
|
|
7
7
|
"packageManager": "pnpm@10.25.0",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "rimraf lib && pnpm build:withoutClean",
|
|
11
|
-
"build:withoutClean": "tsc --project tsconfig.build.json && tsx ./scripts/copyTsFiles.ts
|
|
11
|
+
"build:withoutClean": "tsc --project tsconfig.build.json && tsx ./scripts/copyTsFiles.ts",
|
|
12
12
|
"propagateVersion": "tsx ../../scripts/propagateVersion.ts",
|
|
13
13
|
"watch": "nodemon --ignore lib/ -e ts --exec \"pnpm build:withoutClean && local-npm publish\"",
|
|
14
14
|
"unpub:local": "local-npm unpublish || true",
|
|
@@ -72,12 +72,12 @@
|
|
|
72
72
|
"TypeScript"
|
|
73
73
|
],
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@aneuhold/core-ts-db-lib": "^5.0.
|
|
76
|
-
"@aneuhold/core-ts-lib": "^2.4.
|
|
75
|
+
"@aneuhold/core-ts-db-lib": "^5.0.11",
|
|
76
|
+
"@aneuhold/core-ts-lib": "^2.4.7",
|
|
77
77
|
"bson": "^7.0.0"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@aneuhold/local-npm-registry": "^0.
|
|
80
|
+
"@aneuhold/local-npm-registry": "^1.0.0",
|
|
81
81
|
"@aneuhold/main-scripts": "^2.9.5",
|
|
82
82
|
"@types/node": "^25.0.2",
|
|
83
83
|
"eslint": "^9.39.2",
|