@workos-inc/node 7.75.0 → 7.76.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.
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.AuditLogs = void 0;
13
- const crypto_1 = require("crypto");
14
13
  const serializers_1 = require("./serializers");
15
14
  class AuditLogs {
16
15
  constructor(workos) {
@@ -19,7 +18,8 @@ class AuditLogs {
19
18
  createEvent(organization, event, options = {}) {
20
19
  return __awaiter(this, void 0, void 0, function* () {
21
20
  // Auto-generate idempotency key if not provided
22
- const optionsWithIdempotency = Object.assign(Object.assign({}, options), { idempotencyKey: options.idempotencyKey || `workos-node-${(0, crypto_1.randomUUID)()}` });
21
+ const optionsWithIdempotency = Object.assign(Object.assign({}, options), { idempotencyKey: options.idempotencyKey ||
22
+ `workos-node-${this.workos.getCryptoProvider().randomUUID()}` });
23
23
  yield this.workos.post('/audit_logs/events', {
24
24
  event: (0, serializers_1.serializeCreateAuditLogEventOptions)(event),
25
25
  organization_id: organization,
@@ -62,4 +62,10 @@ export declare abstract class CryptoProvider {
62
62
  * @returns A Uint8Array containing the random bytes
63
63
  */
64
64
  abstract randomBytes(length: number): Uint8Array;
65
+ /**
66
+ * Generates a random UUID v4 string.
67
+ *
68
+ * @returns A UUID v4 string in the format xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
69
+ */
70
+ abstract randomUUID(): string;
65
71
  }
@@ -54,4 +54,41 @@ describe('CryptoProvider', () => {
54
54
  expect(nodeCryptoProvider.secureCompare(signature, 'foo')).toEqual(subtleCryptoProvider.secureCompare(signature, 'foo'));
55
55
  }));
56
56
  });
57
+ describe('when generating UUIDs', () => {
58
+ const UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
59
+ it('generates valid UUID v4 format for NodeCryptoProvider', () => {
60
+ const nodeCryptoProvider = new node_crypto_provider_1.NodeCryptoProvider();
61
+ const uuid = nodeCryptoProvider.randomUUID();
62
+ expect(uuid).toMatch(UUID_V4_REGEX);
63
+ });
64
+ it('generates valid UUID v4 format for SubtleCryptoProvider', () => {
65
+ const subtleCryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
66
+ const uuid = subtleCryptoProvider.randomUUID();
67
+ expect(uuid).toMatch(UUID_V4_REGEX);
68
+ });
69
+ it('generates unique UUIDs', () => {
70
+ const nodeCryptoProvider = new node_crypto_provider_1.NodeCryptoProvider();
71
+ const subtleCryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
72
+ const uuids = new Set([
73
+ nodeCryptoProvider.randomUUID(),
74
+ nodeCryptoProvider.randomUUID(),
75
+ subtleCryptoProvider.randomUUID(),
76
+ subtleCryptoProvider.randomUUID(),
77
+ ]);
78
+ expect(uuids.size).toBe(4);
79
+ });
80
+ it('SubtleCryptoProvider falls back when crypto.randomUUID is unavailable', () => {
81
+ const originalRandomUUID = globalThis.crypto.randomUUID;
82
+ // @ts-ignore - intentionally removing for test
83
+ delete globalThis.crypto.randomUUID;
84
+ try {
85
+ const subtleCryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
86
+ const uuid = subtleCryptoProvider.randomUUID();
87
+ expect(uuid).toMatch(UUID_V4_REGEX);
88
+ }
89
+ finally {
90
+ globalThis.crypto.randomUUID = originalRandomUUID;
91
+ }
92
+ });
93
+ });
57
94
  });
@@ -16,4 +16,5 @@ export declare class NodeCryptoProvider extends CryptoProvider {
16
16
  }>;
17
17
  decrypt(ciphertext: Uint8Array, key: Uint8Array, iv: Uint8Array, tag: Uint8Array, aad?: Uint8Array): Promise<Uint8Array>;
18
18
  randomBytes(length: number): Uint8Array;
19
+ randomUUID(): string;
19
20
  }
@@ -105,5 +105,8 @@ class NodeCryptoProvider extends crypto_provider_1.CryptoProvider {
105
105
  randomBytes(length) {
106
106
  return new Uint8Array(crypto.randomBytes(length));
107
107
  }
108
+ randomUUID() {
109
+ return crypto.randomUUID();
110
+ }
108
111
  }
109
112
  exports.NodeCryptoProvider = NodeCryptoProvider;
@@ -19,4 +19,5 @@ export declare class SubtleCryptoProvider extends CryptoProvider {
19
19
  }>;
20
20
  decrypt(ciphertext: Uint8Array, key: Uint8Array, iv: Uint8Array, tag: Uint8Array, aad?: Uint8Array): Promise<Uint8Array>;
21
21
  randomBytes(length: number): Uint8Array;
22
+ randomUUID(): string;
22
23
  }
@@ -113,6 +113,20 @@ class SubtleCryptoProvider extends crypto_provider_1.CryptoProvider {
113
113
  crypto.getRandomValues(bytes);
114
114
  return bytes;
115
115
  }
116
+ randomUUID() {
117
+ if (typeof crypto !== 'undefined' &&
118
+ typeof crypto.randomUUID === 'function') {
119
+ return crypto.randomUUID();
120
+ }
121
+ // Fallback for environments without crypto.randomUUID
122
+ const bytes = this.randomBytes(16);
123
+ // tslint:disable-next-line:no-bitwise
124
+ bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
125
+ // tslint:disable-next-line:no-bitwise
126
+ bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant
127
+ const hex = Array.from(bytes, (b) => byteHexMapping[b]).join('');
128
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
129
+ }
116
130
  }
117
131
  exports.SubtleCryptoProvider = SubtleCryptoProvider;
118
132
  // Cached mapping of byte to hex representation. We do this once to avoid re-
@@ -120,7 +120,7 @@ describe('DirectorySync', () => {
120
120
  created_at: '2021-10-27 15:21:50.640959',
121
121
  updated_at: '2021-12-13 12:15:45.531847',
122
122
  };
123
- const userWithRole = {
123
+ const userWithRoles = {
124
124
  object: 'directory_user',
125
125
  id: 'directory_user_456',
126
126
  customAttributes: {
@@ -145,6 +145,7 @@ describe('DirectorySync', () => {
145
145
  state: 'active',
146
146
  username: 'jonsnow',
147
147
  role: { slug: 'super_admin' },
148
+ roles: [{ slug: 'super_admin' }],
148
149
  createdAt: '2021-10-27 15:21:50.640959',
149
150
  updatedAt: '2021-12-13 12:15:45.531847',
150
151
  };
@@ -173,6 +174,7 @@ describe('DirectorySync', () => {
173
174
  state: 'active',
174
175
  username: 'jonsnow',
175
176
  role: { slug: 'super_admin' },
177
+ roles: [{ slug: 'super_admin' }],
176
178
  created_at: '2021-10-27 15:21:50.640959',
177
179
  updated_at: '2021-12-13 12:15:45.531847',
178
180
  };
@@ -409,11 +411,11 @@ describe('DirectorySync', () => {
409
411
  const subject = yield workos.directorySync.getUser('dir_usr_123');
410
412
  expect(subject).toEqual(userWithGroup);
411
413
  }));
412
- describe('with a Role', () => {
414
+ describe('with roles', () => {
413
415
  it(`requests a Directory User`, () => __awaiter(void 0, void 0, void 0, function* () {
414
416
  (0, test_utils_1.fetchOnce)(userWithRoleResponse);
415
417
  const subject = yield workos.directorySync.getUser('directory_user_456');
416
- expect(subject).toEqual(userWithRole);
418
+ expect(subject).toEqual(userWithRoles);
417
419
  }));
418
420
  });
419
421
  });
@@ -33,6 +33,7 @@ export interface DirectoryUser<TCustomAttributes extends object = DefaultCustomA
33
33
  jobTitle: string | null;
34
34
  state: 'active' | 'inactive';
35
35
  role?: RoleResponse;
36
+ roles?: RoleResponse[];
36
37
  createdAt: string;
37
38
  updatedAt: string;
38
39
  }
@@ -68,6 +69,7 @@ export interface DirectoryUserResponse<TCustomAttributes extends object = Defaul
68
69
  job_title: string | null;
69
70
  state: 'active' | 'inactive';
70
71
  role?: RoleResponse;
72
+ roles?: RoleResponse[];
71
73
  created_at: string;
72
74
  updated_at: string;
73
75
  }
@@ -18,6 +18,7 @@ const deserializeDirectoryUser = (directoryUser) => ({
18
18
  jobTitle: directoryUser.job_title,
19
19
  state: directoryUser.state,
20
20
  role: directoryUser.role,
21
+ roles: directoryUser.roles,
21
22
  createdAt: directoryUser.created_at,
22
23
  updatedAt: directoryUser.updated_at,
23
24
  });
@@ -40,6 +41,7 @@ const deserializeUpdatedEventDirectoryUser = (directoryUser) => ({
40
41
  jobTitle: directoryUser.job_title,
41
42
  state: directoryUser.state,
42
43
  role: directoryUser.role,
44
+ roles: directoryUser.roles,
43
45
  createdAt: directoryUser.created_at,
44
46
  updatedAt: directoryUser.updated_at,
45
47
  previousAttributes: directoryUser.previous_attributes,
@@ -11,6 +11,7 @@ export interface Profile<CustomAttributesType extends UnknownRecord> {
11
11
  firstName?: string;
12
12
  lastName?: string;
13
13
  role?: RoleResponse;
14
+ roles?: RoleResponse[];
14
15
  groups?: string[];
15
16
  customAttributes?: CustomAttributesType;
16
17
  rawAttributes?: {
@@ -27,6 +28,7 @@ export interface ProfileResponse<CustomAttributesType extends UnknownRecord> {
27
28
  first_name?: string;
28
29
  last_name?: string;
29
30
  role?: RoleResponse;
31
+ roles?: RoleResponse[];
30
32
  groups?: string[];
31
33
  custom_attributes?: CustomAttributesType;
32
34
  raw_attributes?: {
@@ -11,6 +11,7 @@ const deserializeProfile = (profile) => ({
11
11
  firstName: profile.first_name,
12
12
  lastName: profile.last_name,
13
13
  role: profile.role,
14
+ roles: profile.roles,
14
15
  groups: profile.groups,
15
16
  customAttributes: profile.custom_attributes,
16
17
  rawAttributes: profile.raw_attributes,
@@ -227,6 +227,7 @@ describe('SSO', () => {
227
227
  role: {
228
228
  slug: 'admin',
229
229
  },
230
+ roles: [{ slug: 'admin' }],
230
231
  groups: ['Admins', 'Developers'],
231
232
  raw_attributes: {
232
233
  email: 'foo@test.com',
@@ -268,6 +269,7 @@ describe('SSO', () => {
268
269
  role: {
269
270
  slug: 'admin',
270
271
  },
272
+ roles: [{ slug: 'admin' }],
271
273
  raw_attributes: {
272
274
  email: 'foo@test.com',
273
275
  first_name: 'foo',
@@ -304,6 +306,7 @@ describe('SSO', () => {
304
306
  role: {
305
307
  slug: 'admin',
306
308
  },
309
+ roles: [{ slug: 'admin' }],
307
310
  groups: ['Admins', 'Developers'],
308
311
  raw_attributes: {
309
312
  email: 'foo@test.com',
@@ -352,6 +355,7 @@ describe('SSO', () => {
352
355
  role: {
353
356
  slug: 'admin',
354
357
  },
358
+ roles: [{ slug: 'admin' }],
355
359
  raw_attributes: {
356
360
  email: 'foo@test.com',
357
361
  first_name: 'foo',
@@ -386,6 +390,7 @@ describe('SSO', () => {
386
390
  role: {
387
391
  slug: 'admin',
388
392
  },
393
+ roles: [{ slug: 'admin' }],
389
394
  groups: ['Admins', 'Developers'],
390
395
  raw_attributes: {
391
396
  email: 'foo@test.com',
package/lib/workos.js CHANGED
@@ -33,7 +33,7 @@ const actions_1 = require("./actions/actions");
33
33
  const vault_1 = require("./vault/vault");
34
34
  const conflict_exception_1 = require("./common/exceptions/conflict.exception");
35
35
  const parse_error_1 = require("./common/exceptions/parse-error");
36
- const VERSION = '7.75.0';
36
+ const VERSION = '7.76.0';
37
37
  const DEFAULT_HOSTNAME = 'api.workos.com';
38
38
  const HEADER_AUTHORIZATION = 'Authorization';
39
39
  const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "7.75.0",
2
+ "version": "7.76.0",
3
3
  "name": "@workos-inc/node",
4
4
  "author": "WorkOS",
5
5
  "description": "A Node wrapper for the WorkOS API",