@oxyhq/core 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/AuthManager.js +11 -2
- package/dist/cjs/OxyServices.js +1 -0
- package/dist/cjs/mixins/OxyServices.applications.js +30 -2
- package/dist/cjs/mixins/OxyServices.workspaces.js +144 -0
- package/dist/cjs/mixins/index.js +2 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/AuthManager.js +11 -2
- package/dist/esm/OxyServices.js +1 -0
- package/dist/esm/mixins/OxyServices.applications.js +30 -2
- package/dist/esm/mixins/OxyServices.workspaces.js +141 -0
- package/dist/esm/mixins/index.js +2 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/OxyServices.d.ts +1 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/mixins/OxyServices.applications.d.ts +78 -8
- package/dist/types/mixins/OxyServices.workspaces.d.ts +199 -0
- package/dist/types/mixins/index.d.ts +2 -1
- package/dist/types/models/interfaces.d.ts +9 -0
- package/package.json +1 -1
- package/src/AuthManager.ts +11 -2
- package/src/OxyServices.ts +1 -0
- package/src/__tests__/authManager.cookiePath.test.ts +49 -0
- package/src/index.ts +19 -0
- package/src/mixins/OxyServices.applications.ts +95 -3
- package/src/mixins/OxyServices.workspaces.ts +309 -0
- package/src/mixins/index.ts +3 -0
- package/src/models/interfaces.ts +9 -0
package/dist/esm/AuthManager.js
CHANGED
|
@@ -682,7 +682,14 @@ export class AuthManager {
|
|
|
682
682
|
* Get a valid access token, refreshing automatically if expired or expiring soon.
|
|
683
683
|
*/
|
|
684
684
|
async getAccessToken() {
|
|
685
|
-
|
|
685
|
+
// In cookieOnly / cookie-restore flows the active access token lives only in
|
|
686
|
+
// memory (`_lastKnownAccessToken` + httpService) and is intentionally never
|
|
687
|
+
// written to JS storage — the cookieOnly contract forbids persisting tokens
|
|
688
|
+
// in JS-accessible storage. Fall back to the in-memory token when storage has
|
|
689
|
+
// none, otherwise getAccessToken returns null after every cold-boot/reload and
|
|
690
|
+
// standalone API clients (e.g. the Console axios client) send no Authorization
|
|
691
|
+
// header → 401 on every authed endpoint while `isAuthenticated` is still true.
|
|
692
|
+
const token = (await this.storage.getItem(STORAGE_KEYS.ACCESS_TOKEN)) ?? this._lastKnownAccessToken;
|
|
686
693
|
if (!token)
|
|
687
694
|
return null;
|
|
688
695
|
try {
|
|
@@ -693,7 +700,9 @@ export class AuthManager {
|
|
|
693
700
|
if (decoded.exp - now < buffer) {
|
|
694
701
|
const refreshed = await this.refreshToken();
|
|
695
702
|
if (refreshed) {
|
|
696
|
-
|
|
703
|
+
// refreshToken() updates both storage and `_lastKnownAccessToken`;
|
|
704
|
+
// prefer storage but fall back to memory for the cookieOnly path.
|
|
705
|
+
return (await this.storage.getItem(STORAGE_KEYS.ACCESS_TOKEN)) ?? this._lastKnownAccessToken;
|
|
697
706
|
}
|
|
698
707
|
}
|
|
699
708
|
}
|
package/dist/esm/OxyServices.js
CHANGED
|
@@ -21,6 +21,7 @@ import { composeOxyServices } from './mixins/index.js';
|
|
|
21
21
|
* - **Karma**: Karma system
|
|
22
22
|
* - **Assets**: File upload and asset management
|
|
23
23
|
* - **Applications**: Application, membership, and credential management
|
|
24
|
+
* - **Workspaces**: Workspace and membership management
|
|
24
25
|
* - **Location**: Location-based features
|
|
25
26
|
* - **Analytics**: Analytics tracking
|
|
26
27
|
* - **Devices**: Device management
|
|
@@ -4,12 +4,40 @@ export function OxyServicesApplicationsMixin(Base) {
|
|
|
4
4
|
constructor(...args) {
|
|
5
5
|
super(...args);
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolve an OAuth client identifier to the owning application's PUBLIC
|
|
9
|
+
* identity. No authentication required — the API returns only sanitized,
|
|
10
|
+
* display-safe metadata ({@link PublicApplication}). Use this to render the
|
|
11
|
+
* requesting application's name/icon in consent, authorize, and device-flow
|
|
12
|
+
* approval UIs before any session exists.
|
|
13
|
+
*
|
|
14
|
+
* @param clientId - The OAuth `client_id` (an active credential's public
|
|
15
|
+
* key). URL-encoded before being placed in the path.
|
|
16
|
+
*/
|
|
17
|
+
async getPublicApplication(clientId) {
|
|
18
|
+
try {
|
|
19
|
+
const res = await this.makeRequest('GET', `/auth/oauth/client/${encodeURIComponent(clientId)}`, undefined, { cache: true, cacheTTL: CACHE_TIMES.MEDIUM });
|
|
20
|
+
return res.application;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw this.handleError(error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
7
26
|
/**
|
|
8
27
|
* List applications the current user is an active member of.
|
|
28
|
+
*
|
|
29
|
+
* @param workspaceId - Optional workspace `_id` to scope the listing to
|
|
30
|
+
* applications belonging to that workspace. When provided it is appended
|
|
31
|
+
* as a `workspaceId` query parameter (URL-encoded). The query string is
|
|
32
|
+
* part of the request path, so the response cache keys on it
|
|
33
|
+
* automatically — scoped and unscoped lists never collide.
|
|
9
34
|
*/
|
|
10
|
-
async getApplications() {
|
|
35
|
+
async getApplications(workspaceId) {
|
|
11
36
|
try {
|
|
12
|
-
const
|
|
37
|
+
const path = workspaceId
|
|
38
|
+
? `/applications?workspaceId=${encodeURIComponent(workspaceId)}`
|
|
39
|
+
: '/applications';
|
|
40
|
+
const res = await this.makeRequest('GET', path, undefined, { cache: true, cacheTTL: CACHE_TIMES.MEDIUM });
|
|
13
41
|
return res.applications ?? [];
|
|
14
42
|
}
|
|
15
43
|
catch (error) {
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { CACHE_TIMES } from './mixinHelpers.js';
|
|
2
|
+
export function OxyServicesWorkspacesMixin(Base) {
|
|
3
|
+
return class extends Base {
|
|
4
|
+
constructor(...args) {
|
|
5
|
+
super(...args);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* List workspaces the current user is an active member of.
|
|
9
|
+
*/
|
|
10
|
+
async getWorkspaces() {
|
|
11
|
+
try {
|
|
12
|
+
const res = await this.makeRequest('GET', '/workspaces', undefined, { cache: true, cacheTTL: CACHE_TIMES.MEDIUM });
|
|
13
|
+
return res.workspaces ?? [];
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
throw this.handleError(error);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create a new team workspace. The caller becomes its `owner`.
|
|
21
|
+
* @param data - Workspace configuration.
|
|
22
|
+
*/
|
|
23
|
+
async createWorkspace(data) {
|
|
24
|
+
try {
|
|
25
|
+
const res = await this.makeRequest('POST', '/workspaces', data, { cache: false });
|
|
26
|
+
return res.workspace;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw this.handleError(error);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Fetch a single workspace by id.
|
|
34
|
+
* @param workspaceId - The workspace's Mongo `_id`.
|
|
35
|
+
*/
|
|
36
|
+
async getWorkspace(workspaceId) {
|
|
37
|
+
try {
|
|
38
|
+
const res = await this.makeRequest('GET', `/workspaces/${encodeURIComponent(workspaceId)}`, undefined, { cache: true, cacheTTL: CACHE_TIMES.LONG });
|
|
39
|
+
return res.workspace;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw this.handleError(error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Update a workspace's mutable fields.
|
|
47
|
+
* @param workspaceId - The workspace's Mongo `_id`.
|
|
48
|
+
* @param data - Subset of updatable fields.
|
|
49
|
+
*/
|
|
50
|
+
async updateWorkspace(workspaceId, data) {
|
|
51
|
+
try {
|
|
52
|
+
const res = await this.makeRequest('PATCH', `/workspaces/${encodeURIComponent(workspaceId)}`, data, { cache: false });
|
|
53
|
+
return res.workspace;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
throw this.handleError(error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Soft-delete a workspace (owner only).
|
|
61
|
+
* @param workspaceId - The workspace's Mongo `_id`.
|
|
62
|
+
*/
|
|
63
|
+
async deleteWorkspace(workspaceId) {
|
|
64
|
+
try {
|
|
65
|
+
return await this.makeRequest('DELETE', `/workspaces/${encodeURIComponent(workspaceId)}`, undefined, { cache: false });
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw this.handleError(error);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* List members of a workspace.
|
|
73
|
+
* @param workspaceId - The workspace's Mongo `_id`.
|
|
74
|
+
*/
|
|
75
|
+
async getWorkspaceMembers(workspaceId) {
|
|
76
|
+
try {
|
|
77
|
+
const res = await this.makeRequest('GET', `/workspaces/${encodeURIComponent(workspaceId)}/members`, undefined, { cache: true, cacheTTL: CACHE_TIMES.MEDIUM });
|
|
78
|
+
return res.members ?? [];
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
throw this.handleError(error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Add a member to a workspace.
|
|
86
|
+
* @param workspaceId - The workspace's Mongo `_id`.
|
|
87
|
+
* @param data - Target user id and role (never `owner`).
|
|
88
|
+
*/
|
|
89
|
+
async inviteWorkspaceMember(workspaceId, data) {
|
|
90
|
+
try {
|
|
91
|
+
const res = await this.makeRequest('POST', `/workspaces/${encodeURIComponent(workspaceId)}/members`, data, { cache: false });
|
|
92
|
+
return res.member;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
throw this.handleError(error);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Change a member's role.
|
|
100
|
+
* @param workspaceId - The workspace's Mongo `_id`.
|
|
101
|
+
* @param memberId - The member's Mongo `_id`.
|
|
102
|
+
* @param data - New role (never `owner`).
|
|
103
|
+
*/
|
|
104
|
+
async updateWorkspaceMember(workspaceId, memberId, data) {
|
|
105
|
+
try {
|
|
106
|
+
const res = await this.makeRequest('PATCH', `/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(memberId)}`, data, { cache: false });
|
|
107
|
+
return res.member;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
throw this.handleError(error);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Remove a member from a workspace.
|
|
115
|
+
* @param workspaceId - The workspace's Mongo `_id`.
|
|
116
|
+
* @param memberId - The member's Mongo `_id`.
|
|
117
|
+
*/
|
|
118
|
+
async removeWorkspaceMember(workspaceId, memberId) {
|
|
119
|
+
try {
|
|
120
|
+
return await this.makeRequest('DELETE', `/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(memberId)}`, undefined, { cache: false });
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
throw this.handleError(error);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Transfer ownership of a workspace to another member (owner only).
|
|
128
|
+
* Demotes the current owner and promotes the target to `owner`.
|
|
129
|
+
* @param workspaceId - The workspace's Mongo `_id`.
|
|
130
|
+
* @param data - Target user id.
|
|
131
|
+
*/
|
|
132
|
+
async transferWorkspaceOwnership(workspaceId, data) {
|
|
133
|
+
try {
|
|
134
|
+
return await this.makeRequest('POST', `/workspaces/${encodeURIComponent(workspaceId)}/transfer-ownership`, data, { cache: false });
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
throw this.handleError(error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
package/dist/esm/mixins/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import { OxyServicesPaymentMixin } from './OxyServices.payment.js';
|
|
|
17
17
|
import { OxyServicesKarmaMixin } from './OxyServices.karma.js';
|
|
18
18
|
import { OxyServicesAssetsMixin } from './OxyServices.assets.js';
|
|
19
19
|
import { OxyServicesApplicationsMixin } from './OxyServices.applications.js';
|
|
20
|
+
import { OxyServicesWorkspacesMixin } from './OxyServices.workspaces.js';
|
|
20
21
|
import { OxyServicesLocationMixin } from './OxyServices.location.js';
|
|
21
22
|
import { OxyServicesAnalyticsMixin } from './OxyServices.analytics.js';
|
|
22
23
|
import { OxyServicesDevicesMixin } from './OxyServices.devices.js';
|
|
@@ -61,6 +62,7 @@ const MIXIN_PIPELINE = [
|
|
|
61
62
|
OxyServicesKarmaMixin,
|
|
62
63
|
OxyServicesAssetsMixin,
|
|
63
64
|
OxyServicesApplicationsMixin,
|
|
65
|
+
OxyServicesWorkspacesMixin,
|
|
64
66
|
OxyServicesLocationMixin,
|
|
65
67
|
OxyServicesAnalyticsMixin,
|
|
66
68
|
OxyServicesDevicesMixin,
|