@api-client/core 0.18.38 → 0.18.40

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 (56) hide show
  1. package/RELEASE_SETUP.md +4 -2
  2. package/build/src/browser.d.ts +1 -1
  3. package/build/src/browser.d.ts.map +1 -1
  4. package/build/src/browser.js.map +1 -1
  5. package/build/src/mocking/ModelingMock.d.ts +19 -0
  6. package/build/src/mocking/ModelingMock.d.ts.map +1 -0
  7. package/build/src/mocking/ModelingMock.js +19 -0
  8. package/build/src/mocking/ModelingMock.js.map +1 -0
  9. package/build/src/mocking/ProjectMock.js +1 -1
  10. package/build/src/mocking/ProjectMock.js.map +1 -1
  11. package/build/src/mocking/lib/File.d.ts +34 -0
  12. package/build/src/mocking/lib/File.d.ts.map +1 -0
  13. package/build/src/mocking/lib/File.js +64 -0
  14. package/build/src/mocking/lib/File.js.map +1 -0
  15. package/build/src/mocking/lib/Group.d.ts +16 -0
  16. package/build/src/mocking/lib/Group.d.ts.map +1 -0
  17. package/build/src/mocking/lib/Group.js +39 -0
  18. package/build/src/mocking/lib/Group.js.map +1 -0
  19. package/build/src/mocking/lib/Invitation.d.ts +16 -0
  20. package/build/src/mocking/lib/Invitation.d.ts.map +1 -0
  21. package/build/src/mocking/lib/Invitation.js +42 -0
  22. package/build/src/mocking/lib/Invitation.js.map +1 -0
  23. package/build/src/mocking/lib/Organization.d.ts +16 -0
  24. package/build/src/mocking/lib/Organization.d.ts.map +1 -0
  25. package/build/src/mocking/lib/Organization.js +34 -0
  26. package/build/src/mocking/lib/Organization.js.map +1 -0
  27. package/build/src/mocking/lib/Patch.d.ts +29 -0
  28. package/build/src/mocking/lib/Patch.d.ts.map +1 -0
  29. package/build/src/mocking/lib/Patch.js +102 -0
  30. package/build/src/mocking/lib/Patch.js.map +1 -0
  31. package/build/src/mocking/lib/Trash.d.ts +16 -0
  32. package/build/src/mocking/lib/Trash.d.ts.map +1 -0
  33. package/build/src/mocking/lib/Trash.js +39 -0
  34. package/build/src/mocking/lib/Trash.js.map +1 -0
  35. package/build/src/mocking/lib/User.d.ts +12 -12
  36. package/build/src/mocking/lib/User.d.ts.map +1 -1
  37. package/build/src/mocking/lib/User.js +29 -26
  38. package/build/src/mocking/lib/User.js.map +1 -1
  39. package/build/src/sdk/SdkMock.d.ts +129 -156
  40. package/build/src/sdk/SdkMock.d.ts.map +1 -1
  41. package/build/src/sdk/SdkMock.js +816 -634
  42. package/build/src/sdk/SdkMock.js.map +1 -1
  43. package/build/tsconfig.tsbuildinfo +1 -1
  44. package/data/models/example-generator-api.json +6 -6
  45. package/package.json +7 -4
  46. package/src/mocking/ModelingMock.ts +19 -0
  47. package/src/mocking/ProjectMock.ts +1 -1
  48. package/src/mocking/lib/File.ts +72 -0
  49. package/src/mocking/lib/Group.ts +52 -0
  50. package/src/mocking/lib/Invitation.ts +58 -0
  51. package/src/mocking/lib/Organization.ts +42 -0
  52. package/src/mocking/lib/Patch.ts +128 -0
  53. package/src/mocking/lib/Trash.ts +47 -0
  54. package/src/mocking/lib/User.ts +30 -29
  55. package/src/sdk/SdkMock.ts +1141 -692
  56. package/TESTING_READY.md +0 -114
@@ -1,13 +1,13 @@
1
- import { nanoid } from '../nanoid.js';
2
- import { OrganizationKind, GroupKind, InvitationKind } from '../models/kinds.js';
3
- import { Kind as UserKind } from '../models/store/User.js';
4
- import { File } from '../models/store/File.js';
5
- import { CertificateFileKind, DomainFileKind, FolderKind, ProjectKind } from '../models/kinds.js';
6
- import * as sinon from 'sinon';
7
- import { Exception } from '../exceptions/exception.js';
1
+ import { setupWorker, } from '@jarrodek/amw';
2
+ import { RouteBuilder } from './RouteBuilder.js';
3
+ import { ModelingMock } from '../mocking/ModelingMock.js';
8
4
  /**
9
- * SDK mocking utility for testing. Provides simple API to mock SDK calls
10
- * with random or custom responses.
5
+ * SDK mocking utility for testing. Uses Service Workers to intercept HTTP requests
6
+ * and provide mock responses for API calls.
7
+ *
8
+ * This class uses the `@jarrodek/amw` library to set up a Service Worker that intercepts
9
+ * fetch requests matching the configured routes. Each method adds an intercept for a specific
10
+ * API endpoint, returning either random generated data or custom responses.
11
11
  *
12
12
  * @example
13
13
  * ```typescript
@@ -15,192 +15,401 @@ import { Exception } from '../exceptions/exception.js';
15
15
  * import { StoreSdk } from '@api-client/core/sdk/StoreSdkWeb.js';
16
16
  *
17
17
  * const sdk = new StoreSdk('http://localhost:8080');
18
- * const mocker = new SdkMock(sdk);
18
+ * const mocker = new SdkMock({
19
+ * swPath: '/mockServiceWorker.js', // Path to the Service Worker script
20
+ * base: 'http://localhost:8080' // Base URL matching the SDK
21
+ * });
19
22
  *
20
- * // Simple usage - returns random valid organization
21
- * const stub1 = mocker.organizations.list();
23
+ * // Initialize the Service Worker
24
+ * await mocker.setup();
22
25
  *
23
- * // Custom response
24
- * const stub2 = mocker.organizations.create({
25
- * data: { key: 'org-1', name: 'Test Org', ... }
26
+ * // Add intercept - returns random organizations
27
+ * await mocker.organizations.list();
28
+ *
29
+ * // Custom response with specific data
30
+ * await mocker.organizations.create({
31
+ * response: {
32
+ * status: 201,
33
+ * headers: { 'Content-Type': 'application/json', 'X-Custom-Header': 'value' },
34
+ * body: JSON.stringify({ key: 'custom-id', name: 'Custom Org' })
35
+ * }
26
36
  * });
27
37
  *
28
- * // Custom status and headers
29
- * const stub3 = mocker.users.me({
30
- * status: 404,
31
- * headers: { 'X-Custom': 'value' }
38
+ * // Control pagination in list responses
39
+ * await mocker.groups.list({
40
+ * size: 10, // Number of items to generate
41
+ * cursor: true // Include pagination cursor
32
42
  * });
33
43
  *
34
- * // Restore all stubs
35
- * mocker.restore();
44
+ * // Error simulation
45
+ * await mocker.users.me({
46
+ * response: {
47
+ * status: 404,
48
+ * headers: { 'Content-Type': 'application/json' },
49
+ * body: JSON.stringify({ error: 'Not found' })
50
+ * }
51
+ * });
52
+ *
53
+ * // Remove all intercepts (keep Service Worker active)
54
+ * await mocker.reset();
55
+ *
56
+ * // Stop and remove the Service Worker
57
+ * await mocker.teardown();
36
58
  * ```
59
+ *
60
+ * @TODO: Add a in-memory state store so that mocks can maintain state across requests.
61
+ * This way, operations like create, update, delete can affect subsequent list/read calls
62
+ * and we can mimic the API behavior more closely.
37
63
  */
38
64
  export class SdkMock {
39
- sdk;
40
- stubs = [];
41
- constructor(sdk) {
42
- this.sdk = sdk;
65
+ options;
66
+ handler;
67
+ gen = new ModelingMock();
68
+ constructor(options) {
69
+ this.options = options;
70
+ }
71
+ /**
72
+ * Initializes the mock handler. It uses options provided in the constructor.
73
+ * It has to be called before using any of the mock methods.
74
+ */
75
+ async setup() {
76
+ this.handler = await setupWorker(this.options);
77
+ }
78
+ /**
79
+ * Removes the mock worker and all intercepts.
80
+ */
81
+ async teardown() {
82
+ await this.mock.stop();
83
+ }
84
+ /**
85
+ * Removes all added intercepts.
86
+ */
87
+ async reset() {
88
+ await this.mock.reset();
89
+ }
90
+ get mock() {
91
+ if (!this.handler) {
92
+ throw new Error('Mock handler not initialized. Call setup() first.');
93
+ }
94
+ return this.handler;
95
+ }
96
+ createCursorOption(init = {}) {
97
+ if (init.cursor === false) {
98
+ return undefined;
99
+ }
100
+ const hasCursor = init.cursor === true ? true : this.gen.faker.datatype.boolean();
101
+ if (!hasCursor) {
102
+ return undefined;
103
+ }
104
+ return this.gen.faker.internet.jwt();
105
+ }
106
+ createDefaultResponse(status, headers, body, userConfig) {
107
+ let respond;
108
+ if (userConfig?.response) {
109
+ // user config takes precedence
110
+ respond = userConfig.response;
111
+ }
112
+ else {
113
+ respond = {};
114
+ }
115
+ // Set defaults if not provided in user config
116
+ if (!respond.status) {
117
+ respond.status = status;
118
+ }
119
+ // only set headers if the user didn't configure the response only.
120
+ // The user may want to remove default headers.
121
+ if (!userConfig || !userConfig.response) {
122
+ respond.headers = headers;
123
+ }
124
+ if (!respond.body && userConfig?.forceBody && body) {
125
+ // when body is missing and forceBody is set, generate the body
126
+ respond.body = body();
127
+ }
128
+ else if (body && (!userConfig || !userConfig.response)) {
129
+ // we set the body by default when the user config is missing
130
+ respond.body = body();
131
+ }
132
+ return respond;
43
133
  }
44
134
  /**
45
135
  * Organization API mocks.
46
136
  */
47
137
  organizations = {
48
138
  /**
49
- * Mocks the `organizations.list()` method.
50
- * @param options Optional response customization.
51
- * @returns A stub reference that can be used to restore the original behavior.
139
+ * Adds an intercept to mock the `organizations.list()` method.
140
+ * @param options Optional response configuration
52
141
  */
53
- list: (options) => {
54
- return this.createStub('organizations', 'list', () => {
55
- const defaultData = {
56
- items: [this.generateOrganization(), this.generateOrganization()],
57
- nextPageToken: undefined,
58
- };
59
- if (options?.status !== undefined && options.status !== 200) {
60
- throw new Exception('Mocked error', { status: options.status });
61
- }
62
- return (options?.data ?? defaultData);
63
- });
142
+ list: async (init, options) => {
143
+ const { mock } = this;
144
+ // const respond = init?.response ?? {
145
+ // status: 200,
146
+ // headers: { 'content-type': 'application/json' },
147
+ // body: JSON.stringify({
148
+ // items: this.gen.organization.organizations(init?.size ?? 5),
149
+ // cursor: this.createCursorOption(init),
150
+ // } as ContextListResult<IOrganization>),
151
+ // }
152
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify({
153
+ items: this.gen.organization.organizations(init?.size ?? 5),
154
+ cursor: this.createCursorOption(init),
155
+ }), init);
156
+ await mock.add({
157
+ match: {
158
+ uri: RouteBuilder.organizations(),
159
+ methods: ['GET'],
160
+ },
161
+ respond,
162
+ }, options);
64
163
  },
65
164
  /**
66
- * Mocks the `organizations.create()` method.
67
- * @param options Optional response customization.
68
- * @returns A stub reference that can be used to restore the original behavior.
165
+ * Adds an intercept to mock the `organizations.create()` method.
166
+ * @param options Optional response configuration
69
167
  */
70
- create: (options) => {
71
- return this.createStub('organizations', 'create', () => {
72
- const defaultData = this.generateOrganization();
73
- if (options?.status !== undefined && options.status !== 200) {
74
- throw new Exception('Mocked error', { status: options.status });
75
- }
76
- return (options?.data ?? defaultData);
77
- });
168
+ create: async (init, options) => {
169
+ const { mock } = this;
170
+ // const respond = init?.response ?? {
171
+ // status: 200,
172
+ // headers: { 'content-type': 'application/json' },
173
+ // body: JSON.stringify(this.gen.organization.organization()),
174
+ // }
175
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.organization.organization()), init);
176
+ await mock.add({
177
+ match: {
178
+ uri: RouteBuilder.organizations(),
179
+ methods: ['POST'],
180
+ },
181
+ respond,
182
+ }, options);
78
183
  },
79
184
  invitations: {
80
- list: (options) => {
81
- return this.createStub('organizations.invitations', 'list', () => {
82
- const defaultData = {
83
- items: [this.generateInvitation(), this.generateInvitation()],
185
+ list: async (init, options) => {
186
+ const { mock } = this;
187
+ // const respond = init?.response ?? {
188
+ // status: 200,
189
+ // headers: { 'content-type': 'application/json' },
190
+ // body: JSON.stringify({
191
+ // items: this.gen.invitation.invitations(init?.size ?? 5),
192
+ // cursor: this.createCursorOption(init),
193
+ // } as ContextListResult<InvitationSchema>),
194
+ // }
195
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
196
+ const obj = {
197
+ items: this.gen.invitation.invitations(init?.size ?? 5),
198
+ cursor: this.createCursorOption(init),
84
199
  };
85
- if (options?.status !== undefined && options.status !== 200) {
86
- throw new Exception('Mocked error', { status: options.status });
87
- }
88
- return (options?.data ?? defaultData);
89
- });
200
+ return JSON.stringify(obj);
201
+ }, init);
202
+ await mock.add({
203
+ match: {
204
+ uri: RouteBuilder.invitations(':oid'),
205
+ methods: ['GET'],
206
+ },
207
+ respond,
208
+ }, options);
90
209
  },
91
- create: (options) => {
92
- return this.createStub('organizations.invitations', 'create', () => {
93
- const defaultData = this.generateInvitation();
94
- if (options?.status !== undefined && options.status !== 200) {
95
- throw new Exception('Mocked error', { status: options.status });
96
- }
97
- return (options?.data ?? defaultData);
98
- });
210
+ create: async (init, options) => {
211
+ const { mock } = this;
212
+ // const respond = init?.response ?? {
213
+ // status: 200,
214
+ // headers: { 'content-type': 'application/json' },
215
+ // body: JSON.stringify(this.gen.invitation.invitation()),
216
+ // }
217
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
218
+ await mock.add({
219
+ match: {
220
+ uri: RouteBuilder.invitations(':oid'),
221
+ methods: ['POST'],
222
+ },
223
+ respond,
224
+ }, options);
99
225
  },
100
- findByToken: (options) => {
101
- return this.createStub('organizations.invitations', 'findByToken', () => {
102
- const defaultData = this.generateInvitation();
103
- if (options?.status !== undefined && options.status !== 200) {
104
- throw new Exception('Mocked error', { status: options.status });
105
- }
106
- return (options?.data ?? defaultData);
107
- });
226
+ findByToken: async (init, options) => {
227
+ const { mock } = this;
228
+ // const respond = init?.response ?? {
229
+ // status: 200,
230
+ // headers: { 'content-type': 'application/json' },
231
+ // body: JSON.stringify(this.gen.invitation.invitation()),
232
+ // }
233
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
234
+ await mock.add({
235
+ match: {
236
+ uri: RouteBuilder.findInvitation(),
237
+ methods: ['GET'],
238
+ },
239
+ respond,
240
+ }, options);
108
241
  },
109
- decline: (options) => {
110
- return this.createStub('organizations.invitations', 'decline', () => {
111
- const defaultData = this.generateInvitation();
112
- if (options?.status !== undefined && options.status !== 200) {
113
- throw new Exception('Mocked error', { status: options.status });
114
- }
115
- return (options?.data ?? defaultData);
116
- });
242
+ decline: async (init, options) => {
243
+ const { mock } = this;
244
+ // const respond = init?.response ?? {
245
+ // status: 200,
246
+ // headers: { 'content-type': 'application/json' },
247
+ // body: JSON.stringify(this.gen.invitation.invitation()),
248
+ // }
249
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
250
+ await mock.add({
251
+ match: {
252
+ uri: RouteBuilder.declineInvitation(':oid', ':id'),
253
+ methods: ['POST'],
254
+ },
255
+ respond,
256
+ }, options);
117
257
  },
118
- delete: (options) => {
119
- return this.createStub('organizations.invitations', 'delete', () => {
120
- const defaultData = this.generateInvitation();
121
- if (options?.status !== undefined && options.status !== 200) {
122
- throw new Exception('Mocked error', { status: options.status });
123
- }
124
- return (options?.data ?? defaultData);
125
- });
258
+ delete: async (init, options) => {
259
+ const { mock } = this;
260
+ // const respond = init?.response ?? {
261
+ // status: 200,
262
+ // headers: { 'content-type': 'application/json' },
263
+ // body: JSON.stringify(this.gen.invitation.invitation()),
264
+ // }
265
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
266
+ await mock.add({
267
+ match: {
268
+ uri: RouteBuilder.invitation(':oid', ':id'),
269
+ methods: ['DELETE'],
270
+ },
271
+ respond,
272
+ }, options);
126
273
  },
127
- patch: (options) => {
128
- return this.createStub('organizations.invitations', 'patch', () => {
129
- const defaultData = this.generateInvitation();
130
- if (options?.status !== undefined && options.status !== 200) {
131
- throw new Exception('Mocked error', { status: options.status });
132
- }
133
- return (options?.data ?? defaultData);
134
- });
274
+ patch: async (init, options) => {
275
+ const { mock } = this;
276
+ // const respond = init?.response ?? {
277
+ // status: 200,
278
+ // headers: { 'content-type': 'application/json' },
279
+ // body: JSON.stringify(this.gen.invitation.invitation()),
280
+ // }
281
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
282
+ await mock.add({
283
+ match: {
284
+ uri: RouteBuilder.invitation(':oid', ':id'),
285
+ methods: ['PATCH'],
286
+ },
287
+ respond,
288
+ }, options);
135
289
  },
136
- resend: (options) => {
137
- return this.createStub('organizations.invitations', 'resend', () => {
138
- const defaultData = this.generateInvitation();
139
- if (options?.status !== undefined && options.status !== 200) {
140
- throw new Exception('Mocked error', { status: options.status });
141
- }
142
- return (options?.data ?? defaultData);
143
- });
290
+ resend: async (init, options) => {
291
+ const { mock } = this;
292
+ // const respond = init?.response ?? {
293
+ // status: 200,
294
+ // headers: { 'content-type': 'application/json' },
295
+ // body: JSON.stringify(this.gen.invitation.invitation()),
296
+ // }
297
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.invitation.invitation()), init);
298
+ await mock.add({
299
+ match: {
300
+ uri: RouteBuilder.resendInvitation(':oid', ':id'),
301
+ methods: ['PUT'],
302
+ },
303
+ respond,
304
+ }, options);
144
305
  },
145
306
  },
146
307
  users: {
147
- list: (options) => {
148
- return this.createStub('organizations.users', 'list', () => {
149
- const defaultData = {
150
- items: [this.generateUser(), this.generateUser()],
308
+ list: async (init, options) => {
309
+ const { mock } = this;
310
+ // const respond = init?.response ?? {
311
+ // status: 200,
312
+ // headers: { 'content-type': 'application/json' },
313
+ // body: JSON.stringify({
314
+ // items: this.gen.user.users(init?.size ?? 5),
315
+ // cursor: this.createCursorOption(init),
316
+ // } as ContextListResult<IUser>),
317
+ // }
318
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
319
+ const obj = {
320
+ items: this.gen.user.users(init?.size ?? 5),
321
+ cursor: this.createCursorOption(init),
151
322
  };
152
- if (options?.status !== undefined && options.status !== 200) {
153
- throw new Exception('Mocked error', { status: options.status });
154
- }
155
- return (options?.data ?? defaultData);
156
- });
323
+ return JSON.stringify(obj);
324
+ }, init);
325
+ await mock.add({
326
+ match: {
327
+ uri: RouteBuilder.organizationUsers(':oid'),
328
+ methods: ['GET'],
329
+ },
330
+ respond,
331
+ }, options);
157
332
  },
158
- read: (options) => {
159
- return this.createStub('organizations.users', 'read', () => {
160
- const defaultData = this.generateUser();
161
- if (options?.status !== undefined && options.status !== 200) {
162
- throw new Exception('Mocked error', { status: options.status });
163
- }
164
- return (options?.data ?? defaultData);
165
- });
333
+ read: async (init, options) => {
334
+ const { mock } = this;
335
+ // const respond = init?.response ?? {
336
+ // status: 200,
337
+ // headers: { 'content-type': 'application/json' },
338
+ // body: JSON.stringify(this.gen.user.user()),
339
+ // }
340
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.user.user()), init);
341
+ await mock.add({
342
+ match: {
343
+ uri: RouteBuilder.organizationUser(':oid', ':id'),
344
+ methods: ['GET'],
345
+ },
346
+ respond,
347
+ }, options);
166
348
  },
167
- readBatch: (options) => {
168
- return this.createStub('organizations.users', 'readBatch', () => {
169
- const defaultData = {
170
- items: [this.generateUser(), this.generateUser()],
171
- };
172
- if (options?.status !== undefined && options.status !== 200) {
173
- throw new Exception('Mocked error', { status: options.status });
174
- }
175
- return (options?.data ?? defaultData);
176
- });
349
+ readBatch: async (init, options) => {
350
+ const { mock } = this;
351
+ const path = RouteBuilder.organizationUserBatch(':oid');
352
+ const respond = init?.response ?? {
353
+ status: 200,
354
+ headers: { 'content-type': 'application/json' },
355
+ body: JSON.stringify({
356
+ items: this.gen.user.users(init?.size ?? 5),
357
+ cursor: this.createCursorOption(init),
358
+ }),
359
+ };
360
+ await mock.add({
361
+ match: {
362
+ uri: path,
363
+ methods: ['POST'],
364
+ },
365
+ respond,
366
+ }, options);
177
367
  },
178
- activate: (options) => {
179
- return this.createStub('organizations.users', 'activate', () => {
180
- const defaultData = this.generateUser();
181
- if (options?.status !== undefined && options.status !== 200) {
182
- throw new Exception('Mocked error', { status: options.status });
183
- }
184
- return (options?.data ?? defaultData);
185
- });
368
+ activate: async (init, options) => {
369
+ const { mock } = this;
370
+ // const respond = init?.response ?? {
371
+ // status: 200,
372
+ // headers: { 'content-type': 'application/json' },
373
+ // body: JSON.stringify(this.gen.user.user()),
374
+ // }
375
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.user.user()), init);
376
+ await mock.add({
377
+ match: {
378
+ uri: RouteBuilder.organizationUserActivate(':oid', ':id'),
379
+ methods: ['POST'],
380
+ },
381
+ respond,
382
+ }, options);
186
383
  },
187
- deactivate: (options) => {
188
- return this.createStub('organizations.users', 'deactivate', () => {
189
- const defaultData = this.generateUser();
190
- if (options?.status !== undefined && options.status !== 200) {
191
- throw new Exception('Mocked error', { status: options.status });
192
- }
193
- return (options?.data ?? defaultData);
194
- });
384
+ deactivate: async (init, options) => {
385
+ const { mock } = this;
386
+ // const respond = init?.response ?? {
387
+ // status: 200,
388
+ // headers: { 'content-type': 'application/json' },
389
+ // body: JSON.stringify(this.gen.user.user()),
390
+ // }
391
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.user.user()), init);
392
+ await mock.add({
393
+ match: {
394
+ uri: RouteBuilder.organizationUserDeactivate(':oid', ':id'),
395
+ methods: ['POST'],
396
+ },
397
+ respond,
398
+ }, options);
195
399
  },
196
- delete: (options) => {
197
- return this.createStub('organizations.users', 'delete', () => {
198
- const status = options?.status ?? 204;
199
- if (status !== 204) {
200
- throw new Exception('Mocked error', { status });
201
- }
202
- return undefined;
203
- });
400
+ delete: async (init, options) => {
401
+ const { mock } = this;
402
+ // const respond = init?.response ?? {
403
+ // status: 204,
404
+ // }
405
+ const respond = this.createDefaultResponse(204, undefined, undefined, init);
406
+ await mock.add({
407
+ match: {
408
+ uri: RouteBuilder.organizationUser(':oid', ':id'),
409
+ methods: ['DELETE'],
410
+ },
411
+ respond,
412
+ }, options);
204
413
  },
205
414
  },
206
415
  };
@@ -211,100 +420,127 @@ export class SdkMock {
211
420
  /**
212
421
  * Mocks the `groups.list()` method.
213
422
  * @param options Optional response customization.
214
- * @returns A stub reference that can be used to restore the original behavior.
215
423
  */
216
- list: (options) => {
217
- return this.createStub('groups', 'list', () => {
218
- const defaultData = {
219
- items: [this.generateGroup(), this.generateGroup()],
220
- nextPageToken: undefined,
424
+ list: async (init, options) => {
425
+ const { mock } = this;
426
+ // const respond = init?.response ?? {
427
+ // status: 200,
428
+ // headers: { 'content-type': 'application/json' },
429
+ // body: JSON.stringify({
430
+ // items: this.gen.group.groups(init?.size ?? 5),
431
+ // cursor: this.createCursorOption(init),
432
+ // } as ContextListResult<GroupSchema>),
433
+ // }
434
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
435
+ const obj = {
436
+ items: this.gen.group.groups(init?.size ?? 5),
437
+ cursor: this.createCursorOption(init),
221
438
  };
222
- if (options?.status !== undefined && options.status !== 200) {
223
- throw new Exception('Mocked error', { status: options.status });
224
- }
225
- return (options?.data ?? defaultData);
226
- });
439
+ return JSON.stringify(obj);
440
+ }, init);
441
+ await mock.add({
442
+ match: {
443
+ uri: RouteBuilder.groups(':oid'),
444
+ methods: ['GET'],
445
+ },
446
+ respond,
447
+ }, options);
227
448
  },
228
449
  /**
229
450
  * Mocks the `groups.create()` method.
230
451
  * @param options Optional response customization.
231
- * @returns A stub reference that can be used to restore the original behavior.
232
452
  */
233
- create: (options) => {
234
- return this.createStub('groups', 'create', () => {
235
- const defaultData = this.generateGroup();
236
- const status = options?.status ?? 201;
237
- if (status !== 201) {
238
- throw new Exception('Mocked error', { status });
239
- }
240
- return (options?.data ?? defaultData);
241
- });
242
- },
243
- /**
244
- * Mocks the `groups.read()` method.
245
- * @param options Optional response customization.
246
- * @returns A stub reference that can be used to restore the original behavior.
247
- */
248
- read: (options) => {
249
- return this.createStub('groups', 'read', () => {
250
- const defaultData = this.generateGroup();
251
- if (options?.status !== undefined && options.status !== 200) {
252
- throw new Exception('Mocked error', { status: options.status });
253
- }
254
- return (options?.data ?? defaultData);
255
- });
453
+ create: async (init, options) => {
454
+ const { mock } = this;
455
+ // const respond = init?.response ?? {
456
+ // status: 201,
457
+ // headers: { 'content-type': 'application/json' },
458
+ // body: JSON.stringify(this.gen.group.group()),
459
+ // }
460
+ const respond = this.createDefaultResponse(201, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.group.group()), init);
461
+ await mock.add({
462
+ match: {
463
+ uri: RouteBuilder.groups(':oid'),
464
+ methods: ['POST'],
465
+ },
466
+ respond,
467
+ }, options);
256
468
  },
257
469
  /**
258
470
  * Mocks the `groups.update()` method.
259
471
  * @param options Optional response customization.
260
- * @returns A stub reference that can be used to restore the original behavior.
261
472
  */
262
- update: (options) => {
263
- return this.createStub('groups', 'update', () => {
264
- const defaultData = this.generateGroup();
265
- if (options?.status !== undefined && options.status !== 200) {
266
- throw new Exception('Mocked error', { status: options.status });
267
- }
268
- return (options?.data ?? defaultData);
269
- });
473
+ update: async (init, options) => {
474
+ const { mock } = this;
475
+ // const respond = init?.response ?? {
476
+ // status: 200,
477
+ // headers: { 'content-type': 'application/json' },
478
+ // body: JSON.stringify(this.gen.group.group()),
479
+ // }
480
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.group.group()), init);
481
+ await mock.add({
482
+ match: {
483
+ uri: RouteBuilder.group(':oid', ':key'),
484
+ methods: ['PATCH'],
485
+ },
486
+ respond,
487
+ }, options);
270
488
  },
271
489
  /**
272
490
  * Mocks the `groups.delete()` method.
273
491
  * @param options Optional response customization.
274
- * @returns A stub reference that can be used to restore the original behavior.
275
492
  */
276
- delete: (options) => {
277
- return this.createStub('groups', 'delete', () => {
278
- const status = options?.status ?? 204;
279
- if (status !== 204) {
280
- throw new Exception('Mocked error', { status });
281
- }
282
- return undefined;
283
- });
493
+ delete: async (init, options) => {
494
+ const { mock } = this;
495
+ // const respond = init?.response ?? {
496
+ // status: 204,
497
+ // }
498
+ const respond = this.createDefaultResponse(204, undefined, undefined, init);
499
+ await mock.add({
500
+ match: {
501
+ uri: RouteBuilder.group(':oid', ':key'),
502
+ methods: ['DELETE'],
503
+ },
504
+ respond,
505
+ }, options);
284
506
  },
285
507
  /**
286
508
  * Mocks the `groups.addUsers()` method.
287
509
  */
288
- addUsers: (options) => {
289
- return this.createStub('groups', 'addUsers', () => {
290
- const defaultData = this.generateGroup();
291
- if (options?.status !== undefined && options.status !== 200) {
292
- throw new Exception('Mocked error', { status: options.status });
293
- }
294
- return (options?.data ?? defaultData);
295
- });
510
+ addUsers: async (init, options) => {
511
+ const { mock } = this;
512
+ // const respond = init?.response ?? {
513
+ // status: 200,
514
+ // headers: { 'content-type': 'application/json' },
515
+ // body: JSON.stringify(this.gen.group.group()),
516
+ // }
517
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.group.group()), init);
518
+ await mock.add({
519
+ match: {
520
+ uri: RouteBuilder.groupUsers(':oid', ':key'),
521
+ methods: ['POST'],
522
+ },
523
+ respond,
524
+ }, options);
296
525
  },
297
526
  /**
298
527
  * Mocks the `groups.removeUsers()` method.
299
528
  */
300
- removeUsers: (options) => {
301
- return this.createStub('groups', 'removeUsers', () => {
302
- const defaultData = this.generateGroup();
303
- if (options?.status !== undefined && options.status !== 200) {
304
- throw new Exception('Mocked error', { status: options.status });
305
- }
306
- return (options?.data ?? defaultData);
307
- });
529
+ removeUsers: async (init, options) => {
530
+ const { mock } = this;
531
+ // const respond = init?.response ?? {
532
+ // status: 200,
533
+ // headers: { 'content-type': 'application/json' },
534
+ // body: JSON.stringify(this.gen.group.group()),
535
+ // }
536
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.group.group()), init);
537
+ await mock.add({
538
+ match: {
539
+ uri: RouteBuilder.groupUsers(':oid', ':key'),
540
+ methods: ['DELETE'],
541
+ },
542
+ respond,
543
+ }, options);
308
544
  },
309
545
  };
310
546
  /**
@@ -314,16 +550,22 @@ export class SdkMock {
314
550
  /**
315
551
  * Mocks the `user.me()` method.
316
552
  * @param options Optional response customization.
317
- * @returns A stub reference that can be used to restore the original behavior.
318
553
  */
319
- me: (options) => {
320
- return this.createStub('user', 'me', () => {
321
- const defaultData = this.generateUser();
322
- if (options?.status !== undefined && options.status !== 200) {
323
- throw new Exception(`Mocked error. Status: ${options.status}`, { status: options.status });
324
- }
325
- return (options?.data ?? defaultData);
326
- });
554
+ me: async (init, options) => {
555
+ const { mock } = this;
556
+ // const respond = init?.response ?? {
557
+ // status: 200,
558
+ // headers: { 'content-type': 'application/json' },
559
+ // body: JSON.stringify(this.gen.user.user()),
560
+ // }
561
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.user.user()), init);
562
+ await mock.add({
563
+ match: {
564
+ uri: RouteBuilder.usersMe(),
565
+ methods: ['GET'],
566
+ },
567
+ respond,
568
+ }, options);
327
569
  },
328
570
  };
329
571
  /**
@@ -333,487 +575,427 @@ export class SdkMock {
333
575
  /**
334
576
  * Mocks the `file.list()` method.
335
577
  */
336
- list: (options) => {
337
- return this.createStub('file', 'list', () => {
338
- const defaultData = {
339
- items: [this.generateFile(), this.generateFile()],
578
+ list: async (init, options) => {
579
+ const { mock } = this;
580
+ // const respond = init?.response ?? {
581
+ // status: 200,
582
+ // headers: { 'content-type': 'application/json' },
583
+ // body: JSON.stringify({
584
+ // items: this.gen.file.files(init?.size ?? 5),
585
+ // cursor: this.createCursorOption(init),
586
+ // } as ContextListResult<IFile>),
587
+ // }
588
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
589
+ const obj = {
590
+ items: this.gen.file.files(init?.size ?? 5),
591
+ cursor: this.createCursorOption(init),
340
592
  };
341
- if (options?.status !== undefined && options.status !== 200) {
342
- throw new Exception('Mocked error', { status: options.status });
343
- }
344
- return (options?.data ?? defaultData);
345
- });
593
+ return JSON.stringify(obj);
594
+ }, init);
595
+ await mock.add({
596
+ match: {
597
+ uri: RouteBuilder.files(':oid'),
598
+ methods: ['GET'],
599
+ },
600
+ respond,
601
+ }, options);
346
602
  },
347
603
  /**
348
604
  * Mocks the `file.createMeta()` method.
349
605
  */
350
- createMeta: (options) => {
351
- return this.createStub('file', 'createMeta', () => {
352
- const defaultData = this.generateFile();
353
- const status = options?.status ?? 201;
354
- if (status !== 201) {
355
- throw new Exception('Mocked error', { status });
356
- }
357
- return (options?.data ?? defaultData);
358
- });
606
+ createMeta: async (init, options) => {
607
+ const { mock } = this;
608
+ // const respond = init?.response ?? {
609
+ // status: 201,
610
+ // headers: { 'content-type': 'application/json' },
611
+ // body: JSON.stringify(this.gen.file.file()),
612
+ // }
613
+ const respond = this.createDefaultResponse(201, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.file.file()), init);
614
+ await mock.add({
615
+ match: {
616
+ uri: RouteBuilder.files(':oid'),
617
+ methods: ['POST'],
618
+ },
619
+ respond,
620
+ }, options);
359
621
  },
360
622
  /**
361
623
  * Mocks the `file.createMedia()` method.
362
624
  */
363
- createMedia: (options) => {
364
- return this.createStub('file', 'createMedia', () => {
365
- const status = options?.status ?? 200;
366
- if (status !== 200) {
367
- throw new Exception('Mocked error', { status });
368
- }
369
- return undefined;
370
- });
625
+ createMedia: async (init, options) => {
626
+ const { mock } = this;
627
+ // const respond = init?.response ?? {
628
+ // status: 200,
629
+ // }
630
+ const respond = this.createDefaultResponse(200, undefined, undefined, init);
631
+ await mock.add({
632
+ match: {
633
+ uri: RouteBuilder.fileMedia(':oid', ':id'),
634
+ methods: ['PUT'],
635
+ },
636
+ respond,
637
+ }, options);
371
638
  },
372
639
  /**
373
640
  * Mocks the `file.create()` method.
374
641
  */
375
- create: (options) => {
376
- return this.createStub('file', 'create', () => {
377
- const status = options?.status ?? 201;
378
- if (status !== 201) {
379
- throw new Exception('Mocked error', { status });
380
- }
381
- const defaultData = this.generateFile();
382
- return (options?.data ?? defaultData);
383
- });
642
+ create: async (init, options) => {
643
+ await this.file.createMeta(init, options);
644
+ // When SDK's file.create() is called, it responds with
645
+ // what the result of file.createMeta() would be.
646
+ // Because of that, we don't need to configure the media request.
647
+ await this.file.createMedia(undefined, options);
384
648
  },
385
649
  /**
386
650
  * Mocks the `file.createFolder()` method.
387
651
  */
388
- createFolder: (options) => {
389
- return this.createStub('file', 'createFolder', () => {
390
- const status = options?.status ?? 201;
391
- if (status !== 201) {
392
- throw new Exception('Mocked error', { status });
393
- }
394
- const defaultData = this.generateFolder();
395
- return (options?.data ?? defaultData);
396
- });
652
+ createFolder: async (init, options) => {
653
+ const { mock } = this;
654
+ // const respond = init?.response ?? {
655
+ // status: 201,
656
+ // headers: { 'content-type': 'application/json' },
657
+ // body: JSON.stringify(this.gen.file.folder()),
658
+ // }
659
+ const respond = this.createDefaultResponse(201, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.file.folder()), init);
660
+ await mock.add({
661
+ match: {
662
+ uri: RouteBuilder.files(':oid'),
663
+ methods: ['POST'],
664
+ },
665
+ respond,
666
+ }, options);
397
667
  },
398
668
  /**
399
669
  * Mocks the `file.read()` method.
400
670
  */
401
- read: (options) => {
402
- return this.createStub('file', 'read', () => {
403
- const defaultData = this.generateFile();
404
- if (options?.status !== undefined && options.status !== 200) {
405
- throw new Exception('Mocked error', { status: options.status });
406
- }
407
- return (options?.data ?? defaultData);
408
- });
671
+ read: async (init, options) => {
672
+ const { mock } = this;
673
+ // const respond = init?.response ?? {
674
+ // status: 200,
675
+ // headers: { 'content-type': 'application/json' },
676
+ // body: JSON.stringify(this.gen.file.file()),
677
+ // }
678
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.file.file()), init);
679
+ await mock.add({
680
+ match: {
681
+ uri: RouteBuilder.file(':oid', ':id'),
682
+ methods: ['GET'],
683
+ },
684
+ respond,
685
+ }, options);
409
686
  },
410
687
  /**
411
688
  * Mocks the `file.readMedia()` method.
412
689
  */
413
- readMedia: (options) => {
414
- return this.createStub('file', 'readMedia', () => {
415
- if (options?.status !== undefined && options.status !== 200) {
416
- throw new Exception('Mocked error', { status: options.status });
417
- }
418
- const defaultData = { media: { ok: true }, version: 1 };
419
- return (options?.data ?? defaultData);
420
- });
690
+ readMedia: async (init, options) => {
691
+ const { mock } = this;
692
+ // const respond = init?.response ?? {
693
+ // status: 200,
694
+ // headers: {
695
+ // 'content-type': 'application/json',
696
+ // 'x-version': `${this.gen.faker.number.int({ min: 1, max: 100 })}`,
697
+ // },
698
+ // body: JSON.stringify({ data: this.gen.faker.lorem.sentences() }),
699
+ // }
700
+ const respond = this.createDefaultResponse(200, {
701
+ 'content-type': 'application/json',
702
+ 'x-version': `${this.gen.faker.number.int({ min: 1, max: 100 })}`,
703
+ }, () => JSON.stringify({ data: this.gen.faker.lorem.sentences() }), init);
704
+ await mock.add({
705
+ match: {
706
+ uri: RouteBuilder.fileMedia(':oid', ':id'),
707
+ methods: ['GET'],
708
+ },
709
+ respond,
710
+ }, options);
421
711
  },
422
712
  /**
423
713
  * Mocks the `file.readBulk()` method.
424
714
  */
425
- readBulk: (options) => {
426
- return this.createStub('file', 'readBulk', () => {
427
- const defaultData = {
428
- items: [this.generateFile(), undefined],
715
+ readBulk: async (init, options) => {
716
+ const { mock } = this;
717
+ // const respond = init?.response ?? {
718
+ // status: 200,
719
+ // headers: { 'content-type': 'application/json' },
720
+ // body: JSON.stringify({
721
+ // items: this.gen.file.files(init?.size ?? 5),
722
+ // } as IBulkOperationResult<IFile>),
723
+ // }
724
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
725
+ const obj = {
726
+ items: this.gen.file.files(init?.size ?? 5),
429
727
  };
430
- if (options?.status !== undefined && options.status !== 200) {
431
- throw new Exception('Mocked error', { status: options.status });
432
- }
433
- return (options?.data ?? defaultData);
434
- });
728
+ return JSON.stringify(obj);
729
+ }, init);
730
+ await mock.add({
731
+ match: {
732
+ uri: RouteBuilder.filesBatch(':oid'),
733
+ methods: ['POST'],
734
+ },
735
+ respond,
736
+ }, options);
435
737
  },
436
738
  /**
437
739
  * Mocks the `file.patch()` method.
438
740
  */
439
- patch: (options) => {
440
- return this.createStub('file', 'patch', () => {
441
- const defaultData = this.generateFile();
442
- if (options?.status !== undefined && options.status !== 200) {
443
- throw new Exception('Mocked error', { status: options.status });
444
- }
445
- return (options?.data ?? defaultData);
446
- });
741
+ patch: async (init, options) => {
742
+ const { mock } = this;
743
+ // const respond = init?.response ?? {
744
+ // status: 200,
745
+ // headers: { 'content-type': 'application/json' },
746
+ // body: JSON.stringify(this.gen.file.file()),
747
+ // }
748
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.file.file()), init);
749
+ await mock.add({
750
+ match: {
751
+ uri: RouteBuilder.file(':oid', ':id'),
752
+ methods: ['PATCH'],
753
+ },
754
+ respond,
755
+ }, options);
447
756
  },
448
757
  /**
449
758
  * Mocks the `file.patchMedia()` method.
450
759
  */
451
- patchMedia: (options) => {
452
- return this.createStub('file', 'patchMedia', () => {
453
- const defaultData = this.generateMediaPatchRevision();
454
- if (options?.status !== undefined && options.status !== 200) {
455
- throw new Exception('Mocked error', { status: options.status });
456
- }
457
- return (options?.data ?? defaultData);
458
- });
760
+ patchMedia: async (init, options) => {
761
+ const { mock } = this;
762
+ // const respond = init?.response ?? {
763
+ // status: 200,
764
+ // headers: { 'content-type': 'application/json' },
765
+ // body: JSON.stringify(this.gen.patch.mediaPatchRevision()),
766
+ // }
767
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.patch.mediaPatchRevision()), init);
768
+ await mock.add({
769
+ match: {
770
+ uri: RouteBuilder.fileMedia(':oid', ':id'),
771
+ methods: ['PATCH'],
772
+ },
773
+ respond,
774
+ }, options);
459
775
  },
460
776
  /**
461
777
  * Mocks the `file.delete()` method.
462
778
  */
463
- delete: (options) => {
464
- return this.createStub('file', 'delete', () => {
465
- const status = options?.status ?? 204;
466
- if (status !== 204) {
467
- throw new Exception('Mocked error', { status });
468
- }
469
- return undefined;
470
- });
779
+ delete: async (init, options) => {
780
+ const { mock } = this;
781
+ // const respond = init?.response ?? {
782
+ // status: 204,
783
+ // }
784
+ const respond = this.createDefaultResponse(204, undefined, undefined, init);
785
+ await mock.add({
786
+ match: {
787
+ uri: RouteBuilder.file(':oid', ':id'),
788
+ methods: ['DELETE'],
789
+ },
790
+ respond,
791
+ }, options);
471
792
  },
472
793
  /**
473
794
  * Mocks the `file.deleteBulk()` method.
474
795
  */
475
- deleteBulk: (options) => {
476
- return this.createStub('file', 'deleteBulk', () => {
477
- const status = options?.status ?? 204;
478
- if (status !== 204) {
479
- throw new Exception('Mocked error', { status });
480
- }
481
- return undefined;
482
- });
796
+ deleteBulk: async (init, options) => {
797
+ const { mock } = this;
798
+ // const respond = init?.response ?? {
799
+ // status: 204,
800
+ // }
801
+ const respond = this.createDefaultResponse(204, undefined, undefined, init);
802
+ await mock.add({
803
+ match: {
804
+ uri: RouteBuilder.files(':oid'),
805
+ methods: ['DELETE'],
806
+ },
807
+ respond,
808
+ }, options);
483
809
  },
484
810
  /**
485
811
  * Mocks the `file.patchUsers()` method.
486
812
  */
487
- patchUsers: (options) => {
488
- return this.createStub('file', 'patchUsers', () => {
489
- const defaultData = this.generateFile();
490
- if (options?.status !== undefined && options.status !== 200) {
491
- throw new Exception('Mocked error', { status: options.status });
492
- }
493
- return (options?.data ?? defaultData);
494
- });
813
+ patchUsers: async (init, options) => {
814
+ const { mock } = this;
815
+ // const respond = init?.response ?? {
816
+ // status: 200,
817
+ // headers: { 'content-type': 'application/json' },
818
+ // body: JSON.stringify(this.gen.file.file()),
819
+ // }
820
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => JSON.stringify(this.gen.file.file()), init);
821
+ await mock.add({
822
+ match: {
823
+ uri: RouteBuilder.filesAccess(':oid', ':id'),
824
+ methods: ['PATCH'],
825
+ },
826
+ respond,
827
+ }, options);
495
828
  },
496
829
  /**
497
830
  * Mocks the `file.addUser()` method.
498
831
  */
499
- addUser: (options) => {
500
- return this.createStub('file', 'addUser', () => {
501
- const defaultData = this.generateFile();
502
- if (options?.status !== undefined && options.status !== 200) {
503
- throw new Exception('Mocked error', { status: options.status });
504
- }
505
- return (options?.data ?? defaultData);
506
- });
832
+ addUser: async (init, options) => {
833
+ await this.file.patchUsers(init, options);
507
834
  },
508
835
  /**
509
836
  * Mocks the `file.removeUser()` method.
510
837
  */
511
- removeUser: (options) => {
512
- return this.createStub('file', 'removeUser', () => {
513
- const defaultData = this.generateFile();
514
- if (options?.status !== undefined && options.status !== 200) {
515
- throw new Exception('Mocked error', { status: options.status });
516
- }
517
- return (options?.data ?? defaultData);
518
- });
838
+ removeUser: async (init, options) => {
839
+ await this.file.patchUsers(init, options);
519
840
  },
520
841
  /**
521
842
  * Mocks the `file.listUsers()` method.
522
843
  */
523
- listUsers: (options) => {
524
- return this.createStub('file', 'listUsers', () => {
525
- const defaultData = {
526
- items: [this.generateUser(), this.generateUser()],
844
+ listUsers: async (init, options) => {
845
+ const { mock } = this;
846
+ // const respond = init?.response ?? {
847
+ // status: 200,
848
+ // headers: { 'content-type': 'application/json' },
849
+ // body: JSON.stringify({
850
+ // items: this.gen.user.users(init?.size ?? 5),
851
+ // cursor: this.createCursorOption(init),
852
+ // } as ContextListResult<IUser>),
853
+ // }
854
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
855
+ const obj = {
856
+ items: this.gen.user.users(init?.size ?? 5),
857
+ cursor: this.createCursorOption(init),
527
858
  };
528
- if (options?.status !== undefined && options.status !== 200) {
529
- throw new Exception('Mocked error', { status: options.status });
530
- }
531
- return (options?.data ?? defaultData);
532
- });
859
+ return JSON.stringify(obj);
860
+ }, init);
861
+ await mock.add({
862
+ match: {
863
+ uri: RouteBuilder.fileUsers(':oid', ':id'),
864
+ methods: ['GET'],
865
+ },
866
+ respond,
867
+ }, options);
533
868
  },
534
869
  /**
535
870
  * Mocks the `file.breadcrumbs()` method.
536
871
  */
537
- breadcrumbs: (options) => {
538
- return this.createStub('file', 'breadcrumbs', () => {
539
- const defaultData = {
540
- items: this.generateBreadcrumbs(),
872
+ breadcrumbs: async (init, options) => {
873
+ const { mock } = this;
874
+ // const respond = init?.response ?? {
875
+ // status: 200,
876
+ // headers: { 'content-type': 'application/json' },
877
+ // body: JSON.stringify({
878
+ // items: this.gen.file.fileBreadcrumbs(init?.size ?? 5),
879
+ // cursor: this.createCursorOption(init),
880
+ // } as ContextListResult<FileBreadcrumb>),
881
+ // }
882
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
883
+ const obj = {
884
+ items: this.gen.file.fileBreadcrumbs(init?.size ?? 5),
885
+ cursor: this.createCursorOption(init),
541
886
  };
542
- if (options?.status !== undefined && options.status !== 200) {
543
- throw new Exception('Mocked error', { status: options.status });
544
- }
545
- return (options?.data ?? defaultData);
546
- });
887
+ return JSON.stringify(obj);
888
+ }, init);
889
+ await mock.add({
890
+ match: {
891
+ uri: RouteBuilder.fileBreadcrumbs(':oid', ':id'),
892
+ methods: ['GET'],
893
+ },
894
+ respond,
895
+ }, options);
547
896
  },
548
897
  };
549
898
  /**
550
899
  * Shared API mocks.
551
900
  */
552
901
  shared = {
553
- list: (options) => {
554
- return this.createStub('shared', 'list', () => {
555
- const defaultData = {
556
- items: [this.generateFile(), this.generateFile()],
902
+ list: async (init, options) => {
903
+ const { mock } = this;
904
+ // const respond = init?.response ?? {
905
+ // status: 200,
906
+ // headers: { 'content-type': 'application/json' },
907
+ // body: JSON.stringify({
908
+ // items: this.gen.file.files(init?.size ?? 5),
909
+ // cursor: this.createCursorOption(init),
910
+ // } as ContextListResult<IFile>),
911
+ // }
912
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
913
+ const obj = {
914
+ items: this.gen.file.files(init?.size ?? 5),
915
+ cursor: this.createCursorOption(init),
557
916
  };
558
- if (options?.status !== undefined && options.status !== 200) {
559
- throw new Exception('Mocked error', { status: options.status });
560
- }
561
- return (options?.data ?? defaultData);
562
- });
917
+ return JSON.stringify(obj);
918
+ }, init);
919
+ await mock.add({
920
+ match: {
921
+ uri: RouteBuilder.shared(':oid'),
922
+ methods: ['GET'],
923
+ },
924
+ respond,
925
+ }, options);
563
926
  },
564
927
  };
565
928
  /**
566
929
  * Trash API mocks.
567
930
  */
568
931
  trash = {
569
- list: (options) => {
570
- return this.createStub('trash', 'list', () => {
571
- const defaultData = {
572
- items: [this.generateTrashEntry(), this.generateTrashEntry()],
932
+ list: async (init, options) => {
933
+ const { mock } = this;
934
+ // const respond = init?.response ?? {
935
+ // status: 200,
936
+ // headers: { 'content-type': 'application/json' },
937
+ // body: JSON.stringify({
938
+ // items: this.gen.trash.trashEntries(init?.size ?? 5),
939
+ // cursor: this.createCursorOption(init),
940
+ // } as ContextListResult<TrashEntry>),
941
+ // }
942
+ const respond = this.createDefaultResponse(200, { 'content-type': 'application/json' }, () => {
943
+ const obj = {
944
+ items: this.gen.trash.trashEntries(init?.size ?? 5),
945
+ cursor: this.createCursorOption(init),
573
946
  };
574
- if (options?.status !== undefined && options.status !== 200) {
575
- throw new Exception('Mocked error', { status: options.status });
576
- }
577
- return (options?.data ?? defaultData);
578
- });
579
- },
580
- delete: (options) => {
581
- return this.createStub('trash', 'delete', () => {
582
- const status = options?.status ?? 204;
583
- if (status !== 204) {
584
- throw new Exception('Mocked error', { status });
585
- }
586
- return undefined;
587
- });
588
- },
589
- restore: (options) => {
590
- return this.createStub('trash', 'restore', () => {
591
- const status = options?.status ?? 204;
592
- if (status !== 204) {
593
- throw new Exception('Mocked error', { status });
594
- }
595
- return undefined;
596
- });
597
- },
598
- empty: (options) => {
599
- return this.createStub('trash', 'empty', () => {
600
- const status = options?.status ?? 204;
601
- if (status !== 204) {
602
- throw new Exception('Mocked error', { status });
603
- }
604
- return undefined;
605
- });
947
+ return JSON.stringify(obj);
948
+ }, init);
949
+ await mock.add({
950
+ match: {
951
+ uri: RouteBuilder.trash(':oid'),
952
+ methods: ['GET'],
953
+ },
954
+ respond,
955
+ }, options);
956
+ },
957
+ delete: async (init, options) => {
958
+ const { mock } = this;
959
+ // const respond = init?.response ?? {
960
+ // status: 204,
961
+ // }
962
+ const respond = this.createDefaultResponse(204, undefined, undefined, init);
963
+ await mock.add({
964
+ match: {
965
+ uri: RouteBuilder.trashBatchDelete(':oid'),
966
+ methods: ['DELETE'],
967
+ },
968
+ respond,
969
+ }, options);
970
+ },
971
+ restore: async (init, options) => {
972
+ const { mock } = this;
973
+ // const respond = init?.response ?? {
974
+ // status: 204,
975
+ // }
976
+ const respond = this.createDefaultResponse(204, undefined, undefined, init);
977
+ await mock.add({
978
+ match: {
979
+ uri: RouteBuilder.trashBatchRestore(':oid'),
980
+ methods: ['POST'],
981
+ },
982
+ respond,
983
+ }, options);
984
+ },
985
+ empty: async (init, options) => {
986
+ const { mock } = this;
987
+ // const respond = init?.response ?? {
988
+ // status: 204,
989
+ // }
990
+ const respond = this.createDefaultResponse(204, undefined, undefined, init);
991
+ await mock.add({
992
+ match: {
993
+ uri: RouteBuilder.trashEmpty(':oid'),
994
+ methods: ['DELETE'],
995
+ },
996
+ respond,
997
+ }, options);
606
998
  },
607
999
  };
608
- /**
609
- * Restores all stubs created by this mocker.
610
- */
611
- restore() {
612
- this.stubs.forEach((stub) => stub.restore());
613
- this.stubs = [];
614
- }
615
- /**
616
- * Creates a stub for a specific SDK method.
617
- * @param api The API name (e.g., 'organizations', 'groups', 'user', 'auth').
618
- * @param method The method name to stub.
619
- * @param implementation The stub implementation that returns the mocked data.
620
- * @returns A stub reference.
621
- */
622
- createStub(api, method, implementation) {
623
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
624
- let target = this.sdk;
625
- const parts = api.split('.');
626
- for (const part of parts) {
627
- target = target[part];
628
- if (!target) {
629
- throw new Error(`API '${api}' not found in SDK`);
630
- }
631
- }
632
- const original = target[method];
633
- if (typeof original !== 'function') {
634
- throw new Error(`Method '${method}' not found in ${api} API`);
635
- }
636
- // Create stub using sinon
637
- const stub = sinon.stub(target, method).callsFake(async () => implementation());
638
- const stubRef = {
639
- restore: () => {
640
- if (stub) {
641
- stub.restore();
642
- }
643
- const index = this.stubs.indexOf(stubRef);
644
- if (index > -1) {
645
- this.stubs.splice(index, 1);
646
- }
647
- },
648
- };
649
- this.stubs.push(stubRef);
650
- return stubRef;
651
- }
652
- /**
653
- * Generates a random organization object.
654
- */
655
- generateOrganization() {
656
- return {
657
- kind: OrganizationKind,
658
- key: nanoid(),
659
- name: `Organization ${this.randomString()}`,
660
- createdBy: nanoid(),
661
- createdDate: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 30,
662
- grantType: this.randomChoice(['owner', 'manager', 'editor', 'viewer']),
663
- };
664
- }
665
- /**
666
- * Generates a random group object.
667
- */
668
- generateGroup() {
669
- return {
670
- kind: GroupKind,
671
- key: nanoid(),
672
- name: `Group ${this.randomString()}`,
673
- description: `Description for ${this.randomString()}`,
674
- owner: nanoid(),
675
- oid: nanoid(),
676
- users: [],
677
- createdAt: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 30,
678
- updatedAt: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 7,
679
- icon: `https://example.com/icon-${nanoid()}.png`,
680
- color: this.randomColor(),
681
- };
682
- }
683
- /**
684
- * Generates a random user object.
685
- */
686
- generateUser() {
687
- const firstName = this.randomString();
688
- const lastName = this.randomString();
689
- return {
690
- kind: UserKind,
691
- key: nanoid(),
692
- name: `${firstName} ${lastName}`,
693
- email: [
694
- {
695
- email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
696
- verified: true,
697
- },
698
- ],
699
- status: 'active',
700
- created: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 365,
701
- updated: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 7,
702
- };
703
- }
704
- /**
705
- * Generates a random file meta object.
706
- */
707
- generateFile() {
708
- const kind = this.randomChoice([ProjectKind, DomainFileKind, CertificateFileKind, FolderKind]);
709
- const name = `File ${this.randomString()}`;
710
- return File.createSchema({ kind, info: { name } });
711
- }
712
- /**
713
- * Generates a random folder meta object.
714
- */
715
- generateFolder() {
716
- const file = File.createSchema({ kind: FolderKind, info: { name: `Folder ${this.randomString()}` } });
717
- return file;
718
- }
719
- /**
720
- * Generates a random media patch revision object.
721
- */
722
- generateMediaPatchRevision() {
723
- const version = Math.floor(Math.random() * 10) + 1;
724
- return {
725
- id: nanoid(),
726
- timestamp: Date.now(),
727
- patch: [],
728
- version,
729
- revert: [],
730
- newVersion: version + 1,
731
- };
732
- }
733
- /**
734
- * Generates a random breadcrumbs list.
735
- */
736
- generateBreadcrumbs() {
737
- const depth = 2 + Math.floor(Math.random() * 2); // 2-3
738
- const items = [];
739
- for (let i = 0; i < depth; i += 1) {
740
- items.push({ key: nanoid(), kind: i === depth - 1 ? ProjectKind : FolderKind, name: this.randomString() });
741
- }
742
- return items;
743
- }
744
- /**
745
- * Generates a random invitation object.
746
- */
747
- generateInvitation() {
748
- const firstName = this.randomString();
749
- const lastName = this.randomString();
750
- const now = Date.now();
751
- return {
752
- kind: InvitationKind,
753
- key: nanoid(),
754
- uid: nanoid(),
755
- oid: nanoid(),
756
- email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
757
- name: `${firstName} ${lastName}`,
758
- token: nanoid(),
759
- expiresAt: now + 7 * 24 * 60 * 60 * 1000,
760
- status: 'pending',
761
- grantType: this.randomChoice(['owner', 'manager', 'editor', 'viewer']),
762
- createdAt: now - Math.random() * 1000 * 60 * 60 * 24,
763
- updatedAt: now - Math.random() * 1000 * 60 * 60,
764
- resent: 0,
765
- lastSentAt: now - Math.random() * 1000 * 60 * 60,
766
- };
767
- }
768
- /**
769
- * Generates a random trash entry.
770
- */
771
- generateTrashEntry() {
772
- return {
773
- key: nanoid(),
774
- refKey: nanoid(),
775
- kind: this.randomChoice([ProjectKind, DomainFileKind, CertificateFileKind, FolderKind]),
776
- name: `Deleted ${this.randomString()}`,
777
- info: { byMe: false, time: Date.now() - Math.floor(Math.random() * 1000000), user: nanoid(), name: 'User' },
778
- capabilities: { canDelete: true, canRestore: true },
779
- };
780
- }
781
- /**
782
- * Generates a random string.
783
- */
784
- randomString() {
785
- const words = [
786
- 'Alpha',
787
- 'Beta',
788
- 'Gamma',
789
- 'Delta',
790
- 'Epsilon',
791
- 'Zeta',
792
- 'Theta',
793
- 'Lambda',
794
- 'Sigma',
795
- 'Omega',
796
- 'Phoenix',
797
- 'Dragon',
798
- 'Tiger',
799
- 'Eagle',
800
- 'Falcon',
801
- ];
802
- return words[Math.floor(Math.random() * words.length)];
803
- }
804
- /**
805
- * Returns a random choice from an array.
806
- */
807
- randomChoice(choices) {
808
- return choices[Math.floor(Math.random() * choices.length)];
809
- }
810
- /**
811
- * Generates a random hex color.
812
- */
813
- randomColor() {
814
- return `#${Math.floor(Math.random() * 16777215)
815
- .toString(16)
816
- .padStart(6, '0')}`;
817
- }
818
1000
  }
819
1001
  //# sourceMappingURL=SdkMock.js.map