@oxyhq/core 3.18.1 → 4.0.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.
Files changed (42) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/OxyServices.js +3 -2
  3. package/dist/cjs/mixins/OxyServices.accounts.js +480 -0
  4. package/dist/cjs/mixins/OxyServices.connectedApps.js +73 -0
  5. package/dist/cjs/mixins/OxyServices.utility.js +3 -2
  6. package/dist/cjs/mixins/index.js +9 -6
  7. package/dist/esm/.tsbuildinfo +1 -1
  8. package/dist/esm/OxyServices.js +3 -2
  9. package/dist/esm/mixins/OxyServices.accounts.js +477 -0
  10. package/dist/esm/mixins/OxyServices.connectedApps.js +70 -0
  11. package/dist/esm/mixins/OxyServices.utility.js +3 -2
  12. package/dist/esm/mixins/index.js +9 -6
  13. package/dist/types/.tsbuildinfo +1 -1
  14. package/dist/types/OxyServices.d.ts +3 -2
  15. package/dist/types/index.d.ts +2 -3
  16. package/dist/types/mixins/OxyServices.accounts.d.ts +642 -0
  17. package/dist/types/mixins/OxyServices.auth.d.ts +1 -1
  18. package/dist/types/mixins/OxyServices.connectedApps.d.ts +168 -0
  19. package/dist/types/mixins/OxyServices.utility.d.ts +6 -3
  20. package/dist/types/mixins/index.d.ts +3 -4
  21. package/package.json +1 -1
  22. package/src/OxyServices.ts +3 -2
  23. package/src/index.ts +33 -34
  24. package/src/mixins/OxyServices.accounts.ts +1079 -0
  25. package/src/mixins/OxyServices.auth.ts +1 -1
  26. package/src/mixins/OxyServices.connectedApps.ts +165 -0
  27. package/src/mixins/OxyServices.utility.ts +7 -4
  28. package/src/mixins/__tests__/accounts.test.ts +667 -0
  29. package/src/mixins/__tests__/connectedApps.test.ts +1 -1
  30. package/src/mixins/index.ts +11 -9
  31. package/dist/cjs/mixins/OxyServices.applications.js +0 -350
  32. package/dist/cjs/mixins/OxyServices.managedAccounts.js +0 -143
  33. package/dist/cjs/mixins/OxyServices.workspaces.js +0 -181
  34. package/dist/esm/mixins/OxyServices.applications.js +0 -347
  35. package/dist/esm/mixins/OxyServices.managedAccounts.js +0 -140
  36. package/dist/esm/mixins/OxyServices.workspaces.js +0 -178
  37. package/dist/types/mixins/OxyServices.applications.d.ts +0 -496
  38. package/dist/types/mixins/OxyServices.managedAccounts.d.ts +0 -145
  39. package/dist/types/mixins/OxyServices.workspaces.d.ts +0 -219
  40. package/src/mixins/OxyServices.applications.ts +0 -773
  41. package/src/mixins/OxyServices.managedAccounts.ts +0 -173
  42. package/src/mixins/OxyServices.workspaces.ts +0 -351
@@ -1,173 +0,0 @@
1
- /**
2
- * Managed Accounts Methods Mixin
3
- *
4
- * Provides SDK methods for creating and managing sub-accounts (managed identities).
5
- * Managed accounts are full User documents without passwords, accessible only
6
- * by their owners/managers via the X-Acting-As header mechanism.
7
- */
8
- import type { User } from '../models/interfaces';
9
- import type { OxyServicesBase } from '../OxyServices.base';
10
-
11
- export interface CreateManagedAccountInput {
12
- username: string;
13
- name?: { first?: string; last?: string };
14
- bio?: string;
15
- avatar?: string;
16
- }
17
-
18
- export interface ManagedAccountManager {
19
- userId: string;
20
- role: 'owner' | 'admin' | 'editor';
21
- addedAt: string;
22
- addedBy?: string;
23
- }
24
-
25
- export interface ManagedAccount {
26
- accountId: string;
27
- ownerId: string;
28
- managers: ManagedAccountManager[];
29
- account?: User;
30
- createdAt?: string;
31
- updatedAt?: string;
32
- }
33
-
34
- export function OxyServicesManagedAccountsMixin<T extends typeof OxyServicesBase>(Base: T) {
35
- return class extends Base {
36
- constructor(...args: any[]) {
37
- super(...(args as [any]));
38
- }
39
-
40
- /**
41
- * Create a new managed account (sub-account).
42
- *
43
- * The server creates a User document with `isManagedAccount: true` and links
44
- * it to the authenticated user as owner. Invalidates the cached
45
- * `GET /managed-accounts` list (~2-minute TTL, identity-scoped) so the next
46
- * read includes the newly created account.
47
- */
48
- async createManagedAccount(data: CreateManagedAccountInput): Promise<ManagedAccount> {
49
- try {
50
- const result = await this.makeRequest<ManagedAccount>('POST', '/managed-accounts', data, {
51
- cache: false,
52
- });
53
- this.clearCacheEntry('GET:/managed-accounts');
54
- return result;
55
- } catch (error) {
56
- throw this.handleError(error);
57
- }
58
- }
59
-
60
- /**
61
- * List all accounts the authenticated user manages.
62
- */
63
- async getManagedAccounts(): Promise<ManagedAccount[]> {
64
- try {
65
- return await this.makeRequest<ManagedAccount[]>('GET', '/managed-accounts', undefined, {
66
- cache: true,
67
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
68
- });
69
- } catch (error) {
70
- throw this.handleError(error);
71
- }
72
- }
73
-
74
- /**
75
- * Get details for a specific managed account.
76
- */
77
- async getManagedAccountDetails(accountId: string): Promise<ManagedAccount> {
78
- try {
79
- return await this.makeRequest<ManagedAccount>('GET', `/managed-accounts/${accountId}`, undefined, {
80
- cache: true,
81
- cacheTTL: 2 * 60 * 1000,
82
- });
83
- } catch (error) {
84
- throw this.handleError(error);
85
- }
86
- }
87
-
88
- /**
89
- * Update a managed account's profile data.
90
- * Requires owner or admin role.
91
- *
92
- * Invalidates both the cached detail (`GET /managed-accounts/<id>`) and the
93
- * cached list (`GET /managed-accounts`, which embeds account profile data)
94
- * so neither serves the pre-update snapshot within their ~2-minute TTL.
95
- */
96
- async updateManagedAccount(accountId: string, data: Partial<CreateManagedAccountInput>): Promise<ManagedAccount> {
97
- try {
98
- const result = await this.makeRequest<ManagedAccount>('PUT', `/managed-accounts/${accountId}`, data, {
99
- cache: false,
100
- });
101
- this.clearCacheEntry(`GET:/managed-accounts/${accountId}`);
102
- this.clearCacheEntry('GET:/managed-accounts');
103
- return result;
104
- } catch (error) {
105
- throw this.handleError(error);
106
- }
107
- }
108
-
109
- /**
110
- * Delete a managed account permanently.
111
- * Requires owner role.
112
- *
113
- * Invalidates the cached detail and list responses so the deleted account
114
- * is not served from cache.
115
- */
116
- async deleteManagedAccount(accountId: string): Promise<void> {
117
- try {
118
- await this.makeRequest<void>('DELETE', `/managed-accounts/${accountId}`, undefined, {
119
- cache: false,
120
- });
121
- this.clearCacheEntry(`GET:/managed-accounts/${accountId}`);
122
- this.clearCacheEntry('GET:/managed-accounts');
123
- } catch (error) {
124
- throw this.handleError(error);
125
- }
126
- }
127
-
128
- /**
129
- * Add a manager to a managed account.
130
- * Requires owner or admin role on the account.
131
- *
132
- * Mutates the account's `managers[]`, which is returned by the detail and
133
- * list reads — invalidate both so they re-fetch the updated manager set.
134
- *
135
- * @param accountId - The managed account to add the manager to
136
- * @param userId - The user to grant management access
137
- * @param role - The role to assign: 'admin' or 'editor'
138
- */
139
- async addManager(accountId: string, userId: string, role: 'admin' | 'editor'): Promise<void> {
140
- try {
141
- await this.makeRequest<void>('POST', `/managed-accounts/${accountId}/managers`, { userId, role }, {
142
- cache: false,
143
- });
144
- this.clearCacheEntry(`GET:/managed-accounts/${accountId}`);
145
- this.clearCacheEntry('GET:/managed-accounts');
146
- } catch (error) {
147
- throw this.handleError(error);
148
- }
149
- }
150
-
151
- /**
152
- * Remove a manager from a managed account.
153
- * Requires owner role.
154
- *
155
- * Invalidates the detail and list responses so the updated `managers[]`
156
- * is observed on the next read (see `addManager`).
157
- *
158
- * @param accountId - The managed account
159
- * @param userId - The manager to remove
160
- */
161
- async removeManager(accountId: string, userId: string): Promise<void> {
162
- try {
163
- await this.makeRequest<void>('DELETE', `/managed-accounts/${accountId}/managers/${userId}`, undefined, {
164
- cache: false,
165
- });
166
- this.clearCacheEntry(`GET:/managed-accounts/${accountId}`);
167
- this.clearCacheEntry('GET:/managed-accounts');
168
- } catch (error) {
169
- throw this.handleError(error);
170
- }
171
- }
172
- };
173
- }
@@ -1,351 +0,0 @@
1
- /**
2
- * Workspaces Methods Mixin
3
- *
4
- * Provides methods for managing Oxy workspaces and their members via the
5
- * `/workspaces` API. A workspace is a multi-user container that owns
6
- * applications and other resources: membership (with a role) grants
7
- * permissions. A `personal` workspace is created implicitly for every user;
8
- * `team` workspaces are created explicitly and can invite additional members.
9
- *
10
- * Reference workspaces by their Mongo `_id` and members by their member `_id`.
11
- * Never by name or slug.
12
- */
13
- import type { OxyServicesBase } from '../OxyServices.base';
14
- import { CACHE_TIMES } from './mixinHelpers';
15
-
16
- /** Role a member holds within a workspace. */
17
- export type WorkspaceRole = 'owner' | 'admin' | 'member' | 'viewer';
18
-
19
- /** Workspace classification. A `personal` workspace is implicit per user. */
20
- export type WorkspaceType = 'personal' | 'team';
21
-
22
- /** Lifecycle status of a workspace. */
23
- export type WorkspaceStatus = 'active' | 'deleted';
24
-
25
- /** Membership lifecycle status. */
26
- export type WorkspaceMemberStatus = 'active' | 'invited' | 'removed';
27
-
28
- /**
29
- * Client-facing WorkspaceMember shape. `permissions` is derived from `role`
30
- * on the server at write time.
31
- */
32
- export interface WorkspaceMember {
33
- _id: string;
34
- workspaceId: string;
35
- userId: string;
36
- role: WorkspaceRole;
37
- permissions: string[];
38
- invitedByUserId?: string | null;
39
- joinedAt?: string | null;
40
- status: WorkspaceMemberStatus;
41
- createdAt: string;
42
- updatedAt: string;
43
- }
44
-
45
- /**
46
- * Client-facing Workspace shape returned by the `/workspaces` API. Mirrors the
47
- * server `Workspace` model with `_id` as a string and dates serialized to ISO
48
- * strings.
49
- */
50
- export interface Workspace {
51
- _id: string;
52
- name: string;
53
- slug: string;
54
- type: WorkspaceType;
55
- description?: string | null;
56
- icon?: string | null;
57
- ownerId: string;
58
- status: WorkspaceStatus;
59
- createdAt: string;
60
- updatedAt: string;
61
- /**
62
- * The calling user's own membership in this workspace, embedded by the API
63
- * on list (`GET /workspaces`) and detail (`GET /workspaces/:id`) responses.
64
- * Use `callerMembership.permissions` to gate UI affordances.
65
- */
66
- callerMembership?: WorkspaceMember | null;
67
- }
68
-
69
- /** Input accepted by `createWorkspace`. */
70
- export interface CreateWorkspaceInput {
71
- name: string;
72
- description?: string;
73
- icon?: string;
74
- }
75
-
76
- /** Input accepted by `updateWorkspace`. */
77
- export interface UpdateWorkspaceInput {
78
- name?: string;
79
- description?: string | null;
80
- icon?: string | null;
81
- }
82
-
83
- /** Input accepted by `inviteWorkspaceMember`. The owner role cannot be invited. */
84
- export interface InviteWorkspaceMemberInput {
85
- /**
86
- * The username or email of the user to invite. Resolved to a user server-side;
87
- * an unknown value yields a 404 "User not found".
88
- */
89
- usernameOrEmail: string;
90
- role: Exclude<WorkspaceRole, 'owner'>;
91
- }
92
-
93
- /** Input accepted by `updateWorkspaceMember`. The owner role cannot be assigned. */
94
- export interface UpdateWorkspaceMemberInput {
95
- role: Exclude<WorkspaceRole, 'owner'>;
96
- }
97
-
98
- /** Input accepted by `transferWorkspaceOwnership`. */
99
- export interface TransferWorkspaceOwnershipInput {
100
- userId: string;
101
- }
102
-
103
- /** Result of a delete/remove/transfer operation. */
104
- export interface WorkspaceSuccessResult {
105
- success: boolean;
106
- }
107
-
108
- export function OxyServicesWorkspacesMixin<T extends typeof OxyServicesBase>(Base: T) {
109
- return class extends Base {
110
- constructor(...args: any[]) {
111
- super(...(args as [any]));
112
- }
113
-
114
- /**
115
- * List workspaces the current user is an active member of.
116
- */
117
- async getWorkspaces(): Promise<Workspace[]> {
118
- try {
119
- const res = await this.makeRequest<{ workspaces?: Workspace[] }>(
120
- 'GET',
121
- '/workspaces',
122
- undefined,
123
- { cache: true, cacheTTL: CACHE_TIMES.MEDIUM },
124
- );
125
- return res.workspaces ?? [];
126
- } catch (error) {
127
- throw this.handleError(error);
128
- }
129
- }
130
-
131
- /**
132
- * Create a new team workspace. The caller becomes its `owner`.
133
- * @param data - Workspace configuration.
134
- */
135
- async createWorkspace(data: CreateWorkspaceInput): Promise<Workspace> {
136
- try {
137
- const res = await this.makeRequest<{ workspace: Workspace }>(
138
- 'POST',
139
- '/workspaces',
140
- data,
141
- { cache: false },
142
- );
143
- // Bust the cached workspace list so the new workspace appears on the
144
- // next `getWorkspaces()` read within the TTL window.
145
- this.clearCacheEntry('GET:/workspaces');
146
- return res.workspace;
147
- } catch (error) {
148
- throw this.handleError(error);
149
- }
150
- }
151
-
152
- /**
153
- * Fetch a single workspace by id.
154
- * @param workspaceId - The workspace's Mongo `_id`.
155
- */
156
- async getWorkspace(workspaceId: string): Promise<Workspace> {
157
- try {
158
- const res = await this.makeRequest<{ workspace: Workspace }>(
159
- 'GET',
160
- `/workspaces/${encodeURIComponent(workspaceId)}`,
161
- undefined,
162
- { cache: true, cacheTTL: CACHE_TIMES.LONG },
163
- );
164
- return res.workspace;
165
- } catch (error) {
166
- throw this.handleError(error);
167
- }
168
- }
169
-
170
- /**
171
- * Update a workspace's mutable fields.
172
- * @param workspaceId - The workspace's Mongo `_id`.
173
- * @param data - Subset of updatable fields.
174
- */
175
- async updateWorkspace(
176
- workspaceId: string,
177
- data: UpdateWorkspaceInput,
178
- ): Promise<Workspace> {
179
- try {
180
- const res = await this.makeRequest<{ workspace: Workspace }>(
181
- 'PATCH',
182
- `/workspaces/${encodeURIComponent(workspaceId)}`,
183
- data,
184
- { cache: false },
185
- );
186
- // Bust the cached detail and list — both surface workspace fields.
187
- this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}`);
188
- this.clearCacheEntry('GET:/workspaces');
189
- return res.workspace;
190
- } catch (error) {
191
- throw this.handleError(error);
192
- }
193
- }
194
-
195
- /**
196
- * Soft-delete a workspace (owner only).
197
- * @param workspaceId - The workspace's Mongo `_id`.
198
- */
199
- async deleteWorkspace(workspaceId: string): Promise<WorkspaceSuccessResult> {
200
- try {
201
- const result = await this.makeRequest<WorkspaceSuccessResult>(
202
- 'DELETE',
203
- `/workspaces/${encodeURIComponent(workspaceId)}`,
204
- undefined,
205
- { cache: false },
206
- );
207
- // Bust every cached representation of the deleted workspace.
208
- this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}`);
209
- this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}/members`);
210
- this.clearCacheEntry('GET:/workspaces');
211
- return result;
212
- } catch (error) {
213
- throw this.handleError(error);
214
- }
215
- }
216
-
217
- /**
218
- * List members of a workspace.
219
- * @param workspaceId - The workspace's Mongo `_id`.
220
- */
221
- async getWorkspaceMembers(workspaceId: string): Promise<WorkspaceMember[]> {
222
- try {
223
- const res = await this.makeRequest<{ members?: WorkspaceMember[] }>(
224
- 'GET',
225
- `/workspaces/${encodeURIComponent(workspaceId)}/members`,
226
- undefined,
227
- { cache: true, cacheTTL: CACHE_TIMES.MEDIUM },
228
- );
229
- return res.members ?? [];
230
- } catch (error) {
231
- throw this.handleError(error);
232
- }
233
- }
234
-
235
- /**
236
- * Add a member to a workspace.
237
- * @param workspaceId - The workspace's Mongo `_id`.
238
- * @param data - Target user's username or email and role (never `owner`).
239
- * The server resolves `usernameOrEmail` to a user; an unknown value yields
240
- * a 404 "User not found".
241
- */
242
- async inviteWorkspaceMember(
243
- workspaceId: string,
244
- data: InviteWorkspaceMemberInput,
245
- ): Promise<WorkspaceMember> {
246
- try {
247
- const res = await this.makeRequest<{ member: WorkspaceMember }>(
248
- 'POST',
249
- `/workspaces/${encodeURIComponent(workspaceId)}/members`,
250
- data,
251
- { cache: false },
252
- );
253
- this._invalidateWorkspaceMembership(workspaceId);
254
- return res.member;
255
- } catch (error) {
256
- throw this.handleError(error);
257
- }
258
- }
259
-
260
- /**
261
- * Change a member's role.
262
- * @param workspaceId - The workspace's Mongo `_id`.
263
- * @param memberId - The member's Mongo `_id`.
264
- * @param data - New role (never `owner`).
265
- */
266
- async updateWorkspaceMember(
267
- workspaceId: string,
268
- memberId: string,
269
- data: UpdateWorkspaceMemberInput,
270
- ): Promise<WorkspaceMember> {
271
- try {
272
- const res = await this.makeRequest<{ member: WorkspaceMember }>(
273
- 'PATCH',
274
- `/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(memberId)}`,
275
- data,
276
- { cache: false },
277
- );
278
- this._invalidateWorkspaceMembership(workspaceId);
279
- return res.member;
280
- } catch (error) {
281
- throw this.handleError(error);
282
- }
283
- }
284
-
285
- /**
286
- * Remove a member from a workspace.
287
- * @param workspaceId - The workspace's Mongo `_id`.
288
- * @param memberId - The member's Mongo `_id`.
289
- */
290
- async removeWorkspaceMember(
291
- workspaceId: string,
292
- memberId: string,
293
- ): Promise<WorkspaceSuccessResult> {
294
- try {
295
- const result = await this.makeRequest<WorkspaceSuccessResult>(
296
- 'DELETE',
297
- `/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(memberId)}`,
298
- undefined,
299
- { cache: false },
300
- );
301
- this._invalidateWorkspaceMembership(workspaceId);
302
- return result;
303
- } catch (error) {
304
- throw this.handleError(error);
305
- }
306
- }
307
-
308
- /**
309
- * Transfer ownership of a workspace to another member (owner only).
310
- * Demotes the current owner and promotes the target to `owner`.
311
- * @param workspaceId - The workspace's Mongo `_id`.
312
- * @param data - Target user id.
313
- */
314
- async transferWorkspaceOwnership(
315
- workspaceId: string,
316
- data: TransferWorkspaceOwnershipInput,
317
- ): Promise<WorkspaceSuccessResult> {
318
- try {
319
- const result = await this.makeRequest<WorkspaceSuccessResult>(
320
- 'POST',
321
- `/workspaces/${encodeURIComponent(workspaceId)}/transfer-ownership`,
322
- data,
323
- { cache: false },
324
- );
325
- // Ownership change alters roles in the member list AND the detail, and
326
- // can change which workspaces the caller "owns" in the list view.
327
- this._invalidateWorkspaceMembership(workspaceId);
328
- this.clearCacheEntry('GET:/workspaces');
329
- return result;
330
- } catch (error) {
331
- throw this.handleError(error);
332
- }
333
- }
334
-
335
- /**
336
- * Bust the cached member list and detail for a workspace after a membership
337
- * mutation. The member list (`getWorkspaceMembers`) and the detail
338
- * (`getWorkspace`, which can embed member counts) both go stale when the
339
- * member set or a member's role changes.
340
- *
341
- * Internal helper (leading underscore); not part of the supported public
342
- * surface. Public rather than `private` because mixins compose into an
343
- * exported anonymous class, where TypeScript cannot represent a private
344
- * member in the emitted declaration file (TS4094).
345
- */
346
- _invalidateWorkspaceMembership(workspaceId: string): void {
347
- this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}/members`);
348
- this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}`);
349
- }
350
- };
351
- }