@api-client/core 0.18.34 → 0.18.36

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.
@@ -0,0 +1,850 @@
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';
8
+ /**
9
+ * SDK mocking utility for testing. Provides simple API to mock SDK calls
10
+ * with random or custom responses.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { SdkMock } from '@api-client/core/sdk/SdkMock.js';
15
+ * import { StoreSdk } from '@api-client/core/sdk/StoreSdkWeb.js';
16
+ *
17
+ * const sdk = new StoreSdk('http://localhost:8080');
18
+ * const mocker = new SdkMock(sdk);
19
+ *
20
+ * // Simple usage - returns random valid organization
21
+ * const stub1 = mocker.organizations.list();
22
+ *
23
+ * // Custom response
24
+ * const stub2 = mocker.organizations.create({
25
+ * data: { key: 'org-1', name: 'Test Org', ... }
26
+ * });
27
+ *
28
+ * // Custom status and headers
29
+ * const stub3 = mocker.users.me({
30
+ * status: 404,
31
+ * headers: { 'X-Custom': 'value' }
32
+ * });
33
+ *
34
+ * // Restore all stubs
35
+ * mocker.restore();
36
+ * ```
37
+ */
38
+ export class SdkMock {
39
+ sdk;
40
+ stubs = [];
41
+ constructor(sdk) {
42
+ this.sdk = sdk;
43
+ }
44
+ /**
45
+ * Organization API mocks.
46
+ */
47
+ organizations = {
48
+ /**
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.
52
+ */
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
+ });
64
+ },
65
+ /**
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.
69
+ */
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
+ });
78
+ },
79
+ invitations: {
80
+ list: (options) => {
81
+ return this.createStub('organizations.invitations', 'list', () => {
82
+ const defaultData = {
83
+ items: [this.generateInvitation(), this.generateInvitation()],
84
+ };
85
+ if (options?.status !== undefined && options.status !== 200) {
86
+ throw new Exception('Mocked error', { status: options.status });
87
+ }
88
+ return (options?.data ?? defaultData);
89
+ });
90
+ },
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
+ });
99
+ },
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
+ });
108
+ },
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
+ });
117
+ },
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
+ });
126
+ },
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
+ });
135
+ },
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
+ });
144
+ },
145
+ },
146
+ users: {
147
+ list: (options) => {
148
+ return this.createStub('organizations.users', 'list', () => {
149
+ const defaultData = {
150
+ items: [this.generateUser(), this.generateUser()],
151
+ };
152
+ if (options?.status !== undefined && options.status !== 200) {
153
+ throw new Exception('Mocked error', { status: options.status });
154
+ }
155
+ return (options?.data ?? defaultData);
156
+ });
157
+ },
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
+ });
166
+ },
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
+ });
177
+ },
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
+ });
186
+ },
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
+ });
195
+ },
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
+ });
204
+ },
205
+ },
206
+ };
207
+ /**
208
+ * Group API mocks.
209
+ */
210
+ groups = {
211
+ /**
212
+ * Mocks the `groups.list()` method.
213
+ * @param options Optional response customization.
214
+ * @returns A stub reference that can be used to restore the original behavior.
215
+ */
216
+ list: (options) => {
217
+ return this.createStub('groups', 'list', () => {
218
+ const defaultData = {
219
+ items: [this.generateGroup(), this.generateGroup()],
220
+ nextPageToken: undefined,
221
+ };
222
+ if (options?.status !== undefined && options.status !== 200) {
223
+ throw new Exception('Mocked error', { status: options.status });
224
+ }
225
+ return (options?.data ?? defaultData);
226
+ });
227
+ },
228
+ /**
229
+ * Mocks the `groups.create()` method.
230
+ * @param options Optional response customization.
231
+ * @returns A stub reference that can be used to restore the original behavior.
232
+ */
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
+ });
256
+ },
257
+ /**
258
+ * Mocks the `groups.update()` method.
259
+ * @param options Optional response customization.
260
+ * @returns A stub reference that can be used to restore the original behavior.
261
+ */
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
+ });
270
+ },
271
+ /**
272
+ * Mocks the `groups.delete()` method.
273
+ * @param options Optional response customization.
274
+ * @returns A stub reference that can be used to restore the original behavior.
275
+ */
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
+ });
284
+ },
285
+ /**
286
+ * Mocks the `groups.addUsers()` method.
287
+ */
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
+ });
296
+ },
297
+ /**
298
+ * Mocks the `groups.removeUsers()` method.
299
+ */
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
+ });
308
+ },
309
+ };
310
+ /**
311
+ * User API mocks.
312
+ */
313
+ users = {
314
+ /**
315
+ * Mocks the `user.me()` method.
316
+ * @param options Optional response customization.
317
+ * @returns A stub reference that can be used to restore the original behavior.
318
+ */
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 });
324
+ }
325
+ return (options?.data ?? defaultData);
326
+ });
327
+ },
328
+ };
329
+ /**
330
+ * Auth API mocks.
331
+ */
332
+ auth = {
333
+ /**
334
+ * Mocks the `auth.oauthRedirect()` method.
335
+ * This method returns `null` by default as it performs window navigation.
336
+ * @param options Optional response customization.
337
+ * @returns A stub reference that can be used to restore the original behavior.
338
+ */
339
+ oauthRedirect: (options) => {
340
+ return this.createStub('auth', 'oauthRedirect', () => {
341
+ const defaultData = options?.data ?? null;
342
+ return defaultData;
343
+ }, true);
344
+ },
345
+ };
346
+ /**
347
+ * Files API mocks.
348
+ */
349
+ file = {
350
+ /**
351
+ * Mocks the `file.list()` method.
352
+ */
353
+ list: (options) => {
354
+ return this.createStub('file', 'list', () => {
355
+ const defaultData = {
356
+ items: [this.generateFile(), this.generateFile()],
357
+ };
358
+ if (options?.status !== undefined && options.status !== 200) {
359
+ throw new Exception('Mocked error', { status: options.status });
360
+ }
361
+ return (options?.data ?? defaultData);
362
+ });
363
+ },
364
+ /**
365
+ * Mocks the `file.createMeta()` method.
366
+ */
367
+ createMeta: (options) => {
368
+ return this.createStub('file', 'createMeta', () => {
369
+ const defaultData = this.generateFile();
370
+ const status = options?.status ?? 201;
371
+ if (status !== 201) {
372
+ throw new Exception('Mocked error', { status });
373
+ }
374
+ return (options?.data ?? defaultData);
375
+ });
376
+ },
377
+ /**
378
+ * Mocks the `file.createMedia()` method.
379
+ */
380
+ createMedia: (options) => {
381
+ return this.createStub('file', 'createMedia', () => {
382
+ const status = options?.status ?? 200;
383
+ if (status !== 200) {
384
+ throw new Exception('Mocked error', { status });
385
+ }
386
+ return undefined;
387
+ });
388
+ },
389
+ /**
390
+ * Mocks the `file.create()` method.
391
+ */
392
+ create: (options) => {
393
+ return this.createStub('file', 'create', () => {
394
+ const status = options?.status ?? 201;
395
+ if (status !== 201) {
396
+ throw new Exception('Mocked error', { status });
397
+ }
398
+ const defaultData = this.generateFile();
399
+ return (options?.data ?? defaultData);
400
+ });
401
+ },
402
+ /**
403
+ * Mocks the `file.createFolder()` method.
404
+ */
405
+ createFolder: (options) => {
406
+ return this.createStub('file', 'createFolder', () => {
407
+ const status = options?.status ?? 201;
408
+ if (status !== 201) {
409
+ throw new Exception('Mocked error', { status });
410
+ }
411
+ const defaultData = this.generateFolder();
412
+ return (options?.data ?? defaultData);
413
+ });
414
+ },
415
+ /**
416
+ * Mocks the `file.read()` method.
417
+ */
418
+ read: (options) => {
419
+ return this.createStub('file', 'read', () => {
420
+ const defaultData = this.generateFile();
421
+ if (options?.status !== undefined && options.status !== 200) {
422
+ throw new Exception('Mocked error', { status: options.status });
423
+ }
424
+ return (options?.data ?? defaultData);
425
+ });
426
+ },
427
+ /**
428
+ * Mocks the `file.readMedia()` method.
429
+ */
430
+ readMedia: (options) => {
431
+ return this.createStub('file', 'readMedia', () => {
432
+ if (options?.status !== undefined && options.status !== 200) {
433
+ throw new Exception('Mocked error', { status: options.status });
434
+ }
435
+ const defaultData = { media: { ok: true }, version: 1 };
436
+ return (options?.data ?? defaultData);
437
+ });
438
+ },
439
+ /**
440
+ * Mocks the `file.readBulk()` method.
441
+ */
442
+ readBulk: (options) => {
443
+ return this.createStub('file', 'readBulk', () => {
444
+ const defaultData = {
445
+ items: [this.generateFile(), undefined],
446
+ };
447
+ if (options?.status !== undefined && options.status !== 200) {
448
+ throw new Exception('Mocked error', { status: options.status });
449
+ }
450
+ return (options?.data ?? defaultData);
451
+ });
452
+ },
453
+ /**
454
+ * Mocks the `file.patch()` method.
455
+ */
456
+ patch: (options) => {
457
+ return this.createStub('file', 'patch', () => {
458
+ const defaultData = this.generateFile();
459
+ if (options?.status !== undefined && options.status !== 200) {
460
+ throw new Exception('Mocked error', { status: options.status });
461
+ }
462
+ return (options?.data ?? defaultData);
463
+ });
464
+ },
465
+ /**
466
+ * Mocks the `file.patchMedia()` method.
467
+ */
468
+ patchMedia: (options) => {
469
+ return this.createStub('file', 'patchMedia', () => {
470
+ const defaultData = this.generateMediaPatchRevision();
471
+ if (options?.status !== undefined && options.status !== 200) {
472
+ throw new Exception('Mocked error', { status: options.status });
473
+ }
474
+ return (options?.data ?? defaultData);
475
+ });
476
+ },
477
+ /**
478
+ * Mocks the `file.delete()` method.
479
+ */
480
+ delete: (options) => {
481
+ return this.createStub('file', 'delete', () => {
482
+ const status = options?.status ?? 204;
483
+ if (status !== 204) {
484
+ throw new Exception('Mocked error', { status });
485
+ }
486
+ return undefined;
487
+ });
488
+ },
489
+ /**
490
+ * Mocks the `file.deleteBulk()` method.
491
+ */
492
+ deleteBulk: (options) => {
493
+ return this.createStub('file', 'deleteBulk', () => {
494
+ const status = options?.status ?? 204;
495
+ if (status !== 204) {
496
+ throw new Exception('Mocked error', { status });
497
+ }
498
+ return undefined;
499
+ });
500
+ },
501
+ /**
502
+ * Mocks the `file.patchUsers()` method.
503
+ */
504
+ patchUsers: (options) => {
505
+ return this.createStub('file', 'patchUsers', () => {
506
+ const defaultData = this.generateFile();
507
+ if (options?.status !== undefined && options.status !== 200) {
508
+ throw new Exception('Mocked error', { status: options.status });
509
+ }
510
+ return (options?.data ?? defaultData);
511
+ });
512
+ },
513
+ /**
514
+ * Mocks the `file.addUser()` method.
515
+ */
516
+ addUser: (options) => {
517
+ return this.createStub('file', 'addUser', () => {
518
+ const defaultData = this.generateFile();
519
+ if (options?.status !== undefined && options.status !== 200) {
520
+ throw new Exception('Mocked error', { status: options.status });
521
+ }
522
+ return (options?.data ?? defaultData);
523
+ });
524
+ },
525
+ /**
526
+ * Mocks the `file.removeUser()` method.
527
+ */
528
+ removeUser: (options) => {
529
+ return this.createStub('file', 'removeUser', () => {
530
+ const defaultData = this.generateFile();
531
+ if (options?.status !== undefined && options.status !== 200) {
532
+ throw new Exception('Mocked error', { status: options.status });
533
+ }
534
+ return (options?.data ?? defaultData);
535
+ });
536
+ },
537
+ /**
538
+ * Mocks the `file.listUsers()` method.
539
+ */
540
+ listUsers: (options) => {
541
+ return this.createStub('file', 'listUsers', () => {
542
+ const defaultData = {
543
+ items: [this.generateUser(), this.generateUser()],
544
+ };
545
+ if (options?.status !== undefined && options.status !== 200) {
546
+ throw new Exception('Mocked error', { status: options.status });
547
+ }
548
+ return (options?.data ?? defaultData);
549
+ });
550
+ },
551
+ /**
552
+ * Mocks the `file.breadcrumbs()` method.
553
+ */
554
+ breadcrumbs: (options) => {
555
+ return this.createStub('file', 'breadcrumbs', () => {
556
+ const defaultData = {
557
+ items: this.generateBreadcrumbs(),
558
+ };
559
+ if (options?.status !== undefined && options.status !== 200) {
560
+ throw new Exception('Mocked error', { status: options.status });
561
+ }
562
+ return (options?.data ?? defaultData);
563
+ });
564
+ },
565
+ };
566
+ /**
567
+ * Shared API mocks.
568
+ */
569
+ shared = {
570
+ list: (options) => {
571
+ return this.createStub('shared', 'list', () => {
572
+ const defaultData = {
573
+ items: [this.generateFile(), this.generateFile()],
574
+ };
575
+ if (options?.status !== undefined && options.status !== 200) {
576
+ throw new Exception('Mocked error', { status: options.status });
577
+ }
578
+ return (options?.data ?? defaultData);
579
+ });
580
+ },
581
+ };
582
+ /**
583
+ * Trash API mocks.
584
+ */
585
+ trash = {
586
+ list: (options) => {
587
+ return this.createStub('trash', 'list', () => {
588
+ const defaultData = {
589
+ items: [this.generateTrashEntry(), this.generateTrashEntry()],
590
+ };
591
+ if (options?.status !== undefined && options.status !== 200) {
592
+ throw new Exception('Mocked error', { status: options.status });
593
+ }
594
+ return (options?.data ?? defaultData);
595
+ });
596
+ },
597
+ delete: (options) => {
598
+ return this.createStub('trash', 'delete', () => {
599
+ const status = options?.status ?? 204;
600
+ if (status !== 204) {
601
+ throw new Exception('Mocked error', { status });
602
+ }
603
+ return undefined;
604
+ });
605
+ },
606
+ restore: (options) => {
607
+ return this.createStub('trash', 'restore', () => {
608
+ const status = options?.status ?? 204;
609
+ if (status !== 204) {
610
+ throw new Exception('Mocked error', { status });
611
+ }
612
+ return undefined;
613
+ });
614
+ },
615
+ empty: (options) => {
616
+ return this.createStub('trash', 'empty', () => {
617
+ const status = options?.status ?? 204;
618
+ if (status !== 204) {
619
+ throw new Exception('Mocked error', { status });
620
+ }
621
+ return undefined;
622
+ });
623
+ },
624
+ };
625
+ /**
626
+ * Restores all stubs created by this mocker.
627
+ */
628
+ restore() {
629
+ this.stubs.forEach((stub) => stub.restore());
630
+ this.stubs = [];
631
+ }
632
+ /**
633
+ * Creates a stub for a specific SDK method.
634
+ * @param api The API name (e.g., 'organizations', 'groups', 'user', 'auth').
635
+ * @param method The method name to stub.
636
+ * @param implementation The stub implementation that returns the mocked data.
637
+ * @returns A stub reference.
638
+ */
639
+ createStub(api, method, implementation, sync) {
640
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
641
+ let target = this.sdk;
642
+ const parts = api.split('.');
643
+ for (const part of parts) {
644
+ target = target[part];
645
+ if (!target) {
646
+ throw new Error(`API '${api}' not found in SDK`);
647
+ }
648
+ }
649
+ const original = target[method];
650
+ if (typeof original !== 'function') {
651
+ throw new Error(`Method '${method}' not found in ${api} API`);
652
+ }
653
+ // Store original and create stub using sinon
654
+ const stub = sync
655
+ ? sinon.stub(target, method).callsFake(() => implementation())
656
+ : sinon.stub(target, method).callsFake(async () => implementation());
657
+ const stubRef = {
658
+ restore: () => {
659
+ if (stub) {
660
+ stub.restore();
661
+ }
662
+ const index = this.stubs.indexOf(stubRef);
663
+ if (index > -1) {
664
+ this.stubs.splice(index, 1);
665
+ }
666
+ },
667
+ };
668
+ this.stubs.push(stubRef);
669
+ return stubRef;
670
+ }
671
+ /**
672
+ * Creates a response object from data and options.
673
+ * @param defaultData Default data to return if not overridden.
674
+ * @param options Response options.
675
+ * @returns The final data to return (for non-HTTP responses) or IStoreResponse (for HTTP responses).
676
+ */
677
+ createResponse(defaultData, options) {
678
+ // For SDK-level stubs we return plain data. Status and headers are
679
+ // accepted but not propagated, since high-level SDK methods return data.
680
+ const data = options?.data !== undefined ? options.data : defaultData;
681
+ return data;
682
+ }
683
+ /**
684
+ * Generates a random organization object.
685
+ */
686
+ generateOrganization() {
687
+ return {
688
+ kind: OrganizationKind,
689
+ key: nanoid(),
690
+ name: `Organization ${this.randomString()}`,
691
+ createdBy: nanoid(),
692
+ createdDate: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 30,
693
+ grantType: this.randomChoice(['owner', 'manager', 'editor', 'viewer']),
694
+ };
695
+ }
696
+ /**
697
+ * Generates a random group object.
698
+ */
699
+ generateGroup() {
700
+ return {
701
+ kind: GroupKind,
702
+ key: nanoid(),
703
+ name: `Group ${this.randomString()}`,
704
+ description: `Description for ${this.randomString()}`,
705
+ owner: nanoid(),
706
+ oid: nanoid(),
707
+ users: [],
708
+ createdAt: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 30,
709
+ updatedAt: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 7,
710
+ icon: `https://example.com/icon-${nanoid()}.png`,
711
+ color: this.randomColor(),
712
+ };
713
+ }
714
+ /**
715
+ * Generates a random user object.
716
+ */
717
+ generateUser() {
718
+ const firstName = this.randomString();
719
+ const lastName = this.randomString();
720
+ return {
721
+ kind: UserKind,
722
+ key: nanoid(),
723
+ name: `${firstName} ${lastName}`,
724
+ email: [
725
+ {
726
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
727
+ verified: true,
728
+ },
729
+ ],
730
+ status: 'active',
731
+ created: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 365,
732
+ updated: Date.now() - Math.random() * 1000 * 60 * 60 * 24 * 7,
733
+ };
734
+ }
735
+ /**
736
+ * Generates a random file meta object.
737
+ */
738
+ generateFile() {
739
+ const kind = this.randomChoice([ProjectKind, DomainFileKind, CertificateFileKind, FolderKind]);
740
+ const name = `File ${this.randomString()}`;
741
+ return File.createSchema({ kind, info: { name } });
742
+ }
743
+ /**
744
+ * Generates a random folder meta object.
745
+ */
746
+ generateFolder() {
747
+ const file = File.createSchema({ kind: FolderKind, info: { name: `Folder ${this.randomString()}` } });
748
+ return file;
749
+ }
750
+ /**
751
+ * Generates a random media patch revision object.
752
+ */
753
+ generateMediaPatchRevision() {
754
+ const version = Math.floor(Math.random() * 10) + 1;
755
+ return {
756
+ id: nanoid(),
757
+ timestamp: Date.now(),
758
+ patch: [],
759
+ version,
760
+ revert: [],
761
+ newVersion: version + 1,
762
+ };
763
+ }
764
+ /**
765
+ * Generates a random breadcrumbs list.
766
+ */
767
+ generateBreadcrumbs() {
768
+ const depth = 2 + Math.floor(Math.random() * 2); // 2-3
769
+ const items = [];
770
+ for (let i = 0; i < depth; i += 1) {
771
+ items.push({ key: nanoid(), kind: i === depth - 1 ? ProjectKind : FolderKind, name: this.randomString() });
772
+ }
773
+ return items;
774
+ }
775
+ /**
776
+ * Generates a random invitation object.
777
+ */
778
+ generateInvitation() {
779
+ const firstName = this.randomString();
780
+ const lastName = this.randomString();
781
+ const now = Date.now();
782
+ return {
783
+ kind: InvitationKind,
784
+ key: nanoid(),
785
+ uid: nanoid(),
786
+ oid: nanoid(),
787
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
788
+ name: `${firstName} ${lastName}`,
789
+ token: nanoid(),
790
+ expiresAt: now + 7 * 24 * 60 * 60 * 1000,
791
+ status: 'pending',
792
+ grantType: this.randomChoice(['owner', 'manager', 'editor', 'viewer']),
793
+ createdAt: now - Math.random() * 1000 * 60 * 60 * 24,
794
+ updatedAt: now - Math.random() * 1000 * 60 * 60,
795
+ resent: 0,
796
+ lastSentAt: now - Math.random() * 1000 * 60 * 60,
797
+ };
798
+ }
799
+ /**
800
+ * Generates a random trash entry.
801
+ */
802
+ generateTrashEntry() {
803
+ return {
804
+ key: nanoid(),
805
+ refKey: nanoid(),
806
+ kind: this.randomChoice([ProjectKind, DomainFileKind, CertificateFileKind, FolderKind]),
807
+ name: `Deleted ${this.randomString()}`,
808
+ info: { byMe: false, time: Date.now() - Math.floor(Math.random() * 1000000), user: nanoid(), name: 'User' },
809
+ capabilities: { canDelete: true, canRestore: true },
810
+ };
811
+ }
812
+ /**
813
+ * Generates a random string.
814
+ */
815
+ randomString() {
816
+ const words = [
817
+ 'Alpha',
818
+ 'Beta',
819
+ 'Gamma',
820
+ 'Delta',
821
+ 'Epsilon',
822
+ 'Zeta',
823
+ 'Theta',
824
+ 'Lambda',
825
+ 'Sigma',
826
+ 'Omega',
827
+ 'Phoenix',
828
+ 'Dragon',
829
+ 'Tiger',
830
+ 'Eagle',
831
+ 'Falcon',
832
+ ];
833
+ return words[Math.floor(Math.random() * words.length)];
834
+ }
835
+ /**
836
+ * Returns a random choice from an array.
837
+ */
838
+ randomChoice(choices) {
839
+ return choices[Math.floor(Math.random() * choices.length)];
840
+ }
841
+ /**
842
+ * Generates a random hex color.
843
+ */
844
+ randomColor() {
845
+ return `#${Math.floor(Math.random() * 16777215)
846
+ .toString(16)
847
+ .padStart(6, '0')}`;
848
+ }
849
+ }
850
+ //# sourceMappingURL=SdkMock.js.map