@oxyhq/core 3.8.1 → 3.9.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 (55) hide show
  1. package/README.md +10 -0
  2. package/dist/cjs/.tsbuildinfo +1 -1
  3. package/dist/cjs/HttpService.js +18 -4
  4. package/dist/cjs/OxyServices.base.js +15 -1
  5. package/dist/cjs/mixins/OxyServices.applications.js +69 -6
  6. package/dist/cjs/mixins/OxyServices.assets.js +16 -3
  7. package/dist/cjs/mixins/OxyServices.features.js +47 -10
  8. package/dist/cjs/mixins/OxyServices.managedAccounts.js +29 -3
  9. package/dist/cjs/mixins/OxyServices.privacy.js +34 -8
  10. package/dist/cjs/mixins/OxyServices.topics.js +5 -1
  11. package/dist/cjs/mixins/OxyServices.user.js +11 -2
  12. package/dist/cjs/mixins/OxyServices.workspaces.js +38 -3
  13. package/dist/cjs/utils/cache.js +9 -2
  14. package/dist/esm/.tsbuildinfo +1 -1
  15. package/dist/esm/HttpService.js +18 -4
  16. package/dist/esm/OxyServices.base.js +15 -1
  17. package/dist/esm/mixins/OxyServices.applications.js +69 -6
  18. package/dist/esm/mixins/OxyServices.assets.js +16 -3
  19. package/dist/esm/mixins/OxyServices.features.js +47 -10
  20. package/dist/esm/mixins/OxyServices.managedAccounts.js +29 -3
  21. package/dist/esm/mixins/OxyServices.privacy.js +34 -8
  22. package/dist/esm/mixins/OxyServices.topics.js +5 -1
  23. package/dist/esm/mixins/OxyServices.user.js +11 -2
  24. package/dist/esm/mixins/OxyServices.workspaces.js +38 -3
  25. package/dist/esm/utils/cache.js +9 -2
  26. package/dist/types/.tsbuildinfo +1 -1
  27. package/dist/types/HttpService.d.ts +9 -0
  28. package/dist/types/OxyServices.base.d.ts +12 -0
  29. package/dist/types/mixins/OxyServices.applications.d.ts +26 -0
  30. package/dist/types/mixins/OxyServices.features.d.ts +27 -6
  31. package/dist/types/mixins/OxyServices.managedAccounts.d.ts +16 -1
  32. package/dist/types/mixins/OxyServices.privacy.d.ts +22 -4
  33. package/dist/types/mixins/OxyServices.user.d.ts +8 -1
  34. package/dist/types/mixins/OxyServices.workspaces.d.ts +12 -0
  35. package/dist/types/models/interfaces.d.ts +12 -0
  36. package/dist/types/utils/cache.d.ts +4 -1
  37. package/package.json +1 -4
  38. package/src/HttpService.ts +28 -4
  39. package/src/OxyServices.base.ts +15 -1
  40. package/src/__tests__/httpServiceCache.test.ts +68 -0
  41. package/src/__tests__/linkedClient.test.ts +61 -0
  42. package/src/mixins/OxyServices.applications.ts +71 -6
  43. package/src/mixins/OxyServices.assets.ts +16 -3
  44. package/src/mixins/OxyServices.features.ts +47 -10
  45. package/src/mixins/OxyServices.managedAccounts.ts +29 -3
  46. package/src/mixins/OxyServices.privacy.ts +34 -8
  47. package/src/mixins/OxyServices.topics.ts +5 -1
  48. package/src/mixins/OxyServices.user.ts +11 -2
  49. package/src/mixins/OxyServices.workspaces.ts +39 -3
  50. package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +147 -0
  51. package/src/models/interfaces.ts +13 -1
  52. package/src/utils/cache.ts +9 -2
  53. package/dist/cjs/mixins/OxyServices.popup.js +0 -263
  54. package/dist/esm/mixins/OxyServices.popup.js +0 -261
  55. package/dist/types/mixins/OxyServices.popup.d.ts +0 -170
@@ -26,6 +26,9 @@ function OxyServicesWorkspacesMixin(Base) {
26
26
  async createWorkspace(data) {
27
27
  try {
28
28
  const res = await this.makeRequest('POST', '/workspaces', data, { cache: false });
29
+ // Bust the cached workspace list so the new workspace appears on the
30
+ // next `getWorkspaces()` read within the TTL window.
31
+ this.clearCacheEntry('GET:/workspaces');
29
32
  return res.workspace;
30
33
  }
31
34
  catch (error) {
@@ -53,6 +56,9 @@ function OxyServicesWorkspacesMixin(Base) {
53
56
  async updateWorkspace(workspaceId, data) {
54
57
  try {
55
58
  const res = await this.makeRequest('PATCH', `/workspaces/${encodeURIComponent(workspaceId)}`, data, { cache: false });
59
+ // Bust the cached detail and list — both surface workspace fields.
60
+ this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}`);
61
+ this.clearCacheEntry('GET:/workspaces');
56
62
  return res.workspace;
57
63
  }
58
64
  catch (error) {
@@ -65,7 +71,12 @@ function OxyServicesWorkspacesMixin(Base) {
65
71
  */
66
72
  async deleteWorkspace(workspaceId) {
67
73
  try {
68
- return await this.makeRequest('DELETE', `/workspaces/${encodeURIComponent(workspaceId)}`, undefined, { cache: false });
74
+ const result = await this.makeRequest('DELETE', `/workspaces/${encodeURIComponent(workspaceId)}`, undefined, { cache: false });
75
+ // Bust every cached representation of the deleted workspace.
76
+ this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}`);
77
+ this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}/members`);
78
+ this.clearCacheEntry('GET:/workspaces');
79
+ return result;
69
80
  }
70
81
  catch (error) {
71
82
  throw this.handleError(error);
@@ -94,6 +105,7 @@ function OxyServicesWorkspacesMixin(Base) {
94
105
  async inviteWorkspaceMember(workspaceId, data) {
95
106
  try {
96
107
  const res = await this.makeRequest('POST', `/workspaces/${encodeURIComponent(workspaceId)}/members`, data, { cache: false });
108
+ this._invalidateWorkspaceMembership(workspaceId);
97
109
  return res.member;
98
110
  }
99
111
  catch (error) {
@@ -109,6 +121,7 @@ function OxyServicesWorkspacesMixin(Base) {
109
121
  async updateWorkspaceMember(workspaceId, memberId, data) {
110
122
  try {
111
123
  const res = await this.makeRequest('PATCH', `/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(memberId)}`, data, { cache: false });
124
+ this._invalidateWorkspaceMembership(workspaceId);
112
125
  return res.member;
113
126
  }
114
127
  catch (error) {
@@ -122,7 +135,9 @@ function OxyServicesWorkspacesMixin(Base) {
122
135
  */
123
136
  async removeWorkspaceMember(workspaceId, memberId) {
124
137
  try {
125
- return await this.makeRequest('DELETE', `/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(memberId)}`, undefined, { cache: false });
138
+ const result = await this.makeRequest('DELETE', `/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(memberId)}`, undefined, { cache: false });
139
+ this._invalidateWorkspaceMembership(workspaceId);
140
+ return result;
126
141
  }
127
142
  catch (error) {
128
143
  throw this.handleError(error);
@@ -136,11 +151,31 @@ function OxyServicesWorkspacesMixin(Base) {
136
151
  */
137
152
  async transferWorkspaceOwnership(workspaceId, data) {
138
153
  try {
139
- return await this.makeRequest('POST', `/workspaces/${encodeURIComponent(workspaceId)}/transfer-ownership`, data, { cache: false });
154
+ const result = await this.makeRequest('POST', `/workspaces/${encodeURIComponent(workspaceId)}/transfer-ownership`, data, { cache: false });
155
+ // Ownership change alters roles in the member list AND the detail, and
156
+ // can change which workspaces the caller "owns" in the list view.
157
+ this._invalidateWorkspaceMembership(workspaceId);
158
+ this.clearCacheEntry('GET:/workspaces');
159
+ return result;
140
160
  }
141
161
  catch (error) {
142
162
  throw this.handleError(error);
143
163
  }
144
164
  }
165
+ /**
166
+ * Bust the cached member list and detail for a workspace after a membership
167
+ * mutation. The member list (`getWorkspaceMembers`) and the detail
168
+ * (`getWorkspace`, which can embed member counts) both go stale when the
169
+ * member set or a member's role changes.
170
+ *
171
+ * Internal helper (leading underscore); not part of the supported public
172
+ * surface. Public rather than `private` because mixins compose into an
173
+ * exported anonymous class, where TypeScript cannot represent a private
174
+ * member in the emitted declaration file (TS4094).
175
+ */
176
+ _invalidateWorkspaceMembership(workspaceId) {
177
+ this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}/members`);
178
+ this.clearCacheEntry(`GET:/workspaces/${encodeURIComponent(workspaceId)}`);
179
+ }
145
180
  };
146
181
  }
@@ -72,11 +72,18 @@ class TTLCache {
72
72
  * Set a value in cache
73
73
  * @param key Cache key
74
74
  * @param data Data to cache
75
- * @param ttl Optional TTL override (uses default if not provided)
75
+ * @param ttl Optional TTL override (uses default if not provided). An
76
+ * explicit `0` or negative value is honored as "already expired" — the
77
+ * entry is stored with `expiresAt <= now`, so the next `get`/`has` treats
78
+ * it as a miss — rather than silently falling back to the default TTL.
76
79
  */
77
80
  set(key, data, ttl) {
78
81
  const now = Date.now();
79
- const expiresAt = now + (ttl || this.defaultTTL);
82
+ // Distinguish "no override provided" (undefined use default) from an
83
+ // explicit `0`/negative (do not cache). `ttl || this.defaultTTL` collapsed
84
+ // both into the default, making `cacheTTL:0` impossible to honor.
85
+ const effectiveTTL = ttl === undefined ? this.defaultTTL : ttl;
86
+ const expiresAt = now + effectiveTTL;
80
87
  this.cache.set(key, { data, timestamp: now, expiresAt });
81
88
  }
82
89
  /**