@workos-inc/node
Advanced tools
Comparing version 7.4.0 to 7.5.0-beta.node-compatibility
@@ -6,3 +6,3 @@ import { DirectoryUser, DirectoryUserResponse, DirectoryGroup, DirectoryGroupResponse, EventDirectory, EventDirectoryResponse } from '../../directory-sync/interfaces'; | ||
import { OrganizationMembership, OrganizationMembershipResponse } from '../../user-management/interfaces/organization-membership.interface'; | ||
import { RoleEvent, RoleEventResponse } from '../../user-management/interfaces/role.interface'; | ||
import { RoleEvent, RoleEventResponse } from '../../roles/interfaces/role.interface'; | ||
export interface EventBase { | ||
@@ -9,0 +9,0 @@ id: string; |
@@ -10,1 +10,2 @@ export * from './event.interface'; | ||
export * from './pagination-options.interface'; | ||
export * from './http-client.interface'; |
@@ -26,1 +26,2 @@ "use strict"; | ||
__exportStar(require("./pagination-options.interface"), exports); | ||
__exportStar(require("./http-client.interface"), exports); |
@@ -8,2 +8,3 @@ import { AppInfo } from './app-info.interface'; | ||
appInfo?: AppInfo; | ||
fetchFn?: typeof fetch; | ||
} |
@@ -121,2 +121,56 @@ "use strict"; | ||
}; | ||
const userWithRole = { | ||
object: 'directory_user', | ||
id: 'directory_user_456', | ||
customAttributes: { | ||
custom: true, | ||
}, | ||
directoryId: 'dir_123', | ||
organizationId: 'org_123', | ||
emails: [ | ||
{ | ||
primary: true, | ||
type: 'type', | ||
value: 'jonsnow@workos.com', | ||
}, | ||
], | ||
firstName: 'Jon', | ||
groups: [group], | ||
idpId: 'idp_foo', | ||
lastName: 'Snow', | ||
jobTitle: 'Knight of the Watch', | ||
rawAttributes: {}, | ||
state: 'active', | ||
username: 'jonsnow', | ||
role: { slug: 'super_admin' }, | ||
createdAt: '2021-10-27 15:21:50.640959', | ||
updatedAt: '2021-12-13 12:15:45.531847', | ||
}; | ||
const userWithRoleResponse = { | ||
object: 'directory_user', | ||
id: 'directory_user_456', | ||
custom_attributes: { | ||
custom: true, | ||
}, | ||
directory_id: 'dir_123', | ||
organization_id: 'org_123', | ||
emails: [ | ||
{ | ||
primary: true, | ||
type: 'type', | ||
value: 'jonsnow@workos.com', | ||
}, | ||
], | ||
first_name: 'Jon', | ||
groups: [groupResponse], | ||
idp_id: 'idp_foo', | ||
last_name: 'Snow', | ||
job_title: 'Knight of the Watch', | ||
raw_attributes: {}, | ||
state: 'active', | ||
username: 'jonsnow', | ||
role: { slug: 'super_admin' }, | ||
created_at: '2021-10-27 15:21:50.640959', | ||
updated_at: '2021-12-13 12:15:45.531847', | ||
}; | ||
describe('listDirectories', () => { | ||
@@ -355,3 +409,10 @@ describe('with options', () => { | ||
})); | ||
describe('with a Role', () => { | ||
it(`requests a Directory User`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
(0, test_utils_1.fetchOnce)(userWithRoleResponse); | ||
const subject = yield workos.directorySync.getUser('directory_user_456'); | ||
expect(subject).toEqual(userWithRole); | ||
})); | ||
}); | ||
}); | ||
}); |
@@ -0,1 +1,2 @@ | ||
import { RoleResponse } from '../../roles/interfaces/'; | ||
import { DirectoryGroup, DirectoryGroupResponse } from './directory-group.interface'; | ||
@@ -21,2 +22,3 @@ export type DefaultCustomAttributes = Record<string, unknown>; | ||
state: 'active' | 'inactive'; | ||
role?: RoleResponse; | ||
createdAt: string; | ||
@@ -43,2 +45,3 @@ updatedAt: string; | ||
state: 'active' | 'inactive'; | ||
role?: RoleResponse; | ||
created_at: string; | ||
@@ -45,0 +48,0 @@ updated_at: string; |
@@ -19,2 +19,3 @@ "use strict"; | ||
state: directoryUser.state, | ||
role: directoryUser.role, | ||
createdAt: directoryUser.created_at, | ||
@@ -40,2 +41,3 @@ updatedAt: directoryUser.updated_at, | ||
state: directoryUser.state, | ||
role: directoryUser.role, | ||
createdAt: directoryUser.created_at, | ||
@@ -42,0 +44,0 @@ updatedAt: directoryUser.updated_at, |
@@ -109,3 +109,91 @@ "use strict"; | ||
})); | ||
describe('directory user updated events', () => { | ||
describe('with a role', () => { | ||
const directoryUserUpdated = { | ||
id: 'event_01234ABCD', | ||
createdAt: '2020-05-06 04:21:48.649164', | ||
event: 'dsync.user.updated', | ||
data: { | ||
object: 'directory_user', | ||
id: 'directory_user_456', | ||
customAttributes: { | ||
custom: true, | ||
}, | ||
directoryId: 'dir_123', | ||
organizationId: 'org_123', | ||
emails: [ | ||
{ | ||
primary: true, | ||
type: 'type', | ||
value: 'jonsnow@workos.com', | ||
}, | ||
], | ||
firstName: 'Jon', | ||
idpId: 'idp_foo', | ||
lastName: 'Snow', | ||
jobTitle: 'Knight of the Watch', | ||
rawAttributes: {}, | ||
state: 'active', | ||
username: 'jonsnow', | ||
role: { slug: 'super_admin' }, | ||
previousAttributes: { | ||
role: { slug: 'member' }, | ||
}, | ||
createdAt: '2021-10-27 15:21:50.640959', | ||
updatedAt: '2021-12-13 12:15:45.531847', | ||
}, | ||
}; | ||
const directoryUserUpdatedResponse = { | ||
id: 'event_01234ABCD', | ||
created_at: '2020-05-06 04:21:48.649164', | ||
event: 'dsync.user.updated', | ||
data: { | ||
object: 'directory_user', | ||
id: 'directory_user_456', | ||
custom_attributes: { | ||
custom: true, | ||
}, | ||
directory_id: 'dir_123', | ||
organization_id: 'org_123', | ||
emails: [ | ||
{ | ||
primary: true, | ||
type: 'type', | ||
value: 'jonsnow@workos.com', | ||
}, | ||
], | ||
first_name: 'Jon', | ||
idp_id: 'idp_foo', | ||
last_name: 'Snow', | ||
job_title: 'Knight of the Watch', | ||
raw_attributes: {}, | ||
state: 'active', | ||
username: 'jonsnow', | ||
role: { slug: 'super_admin' }, | ||
previous_attributes: { | ||
role: { slug: 'member' }, | ||
}, | ||
created_at: '2021-10-27 15:21:50.640959', | ||
updated_at: '2021-12-13 12:15:45.531847', | ||
}, | ||
}; | ||
const directoryUserEventsListResponse = { | ||
object: 'list', | ||
data: [directoryUserUpdatedResponse], | ||
list_metadata: {}, | ||
}; | ||
it(`returns the role`, () => __awaiter(void 0, void 0, void 0, function* () { | ||
(0, test_utils_1.fetchOnce)(directoryUserEventsListResponse); | ||
const list = yield workos.events.listEvents({ | ||
events: ['dsync.user.updated'], | ||
}); | ||
expect(list).toEqual({ | ||
object: 'list', | ||
data: [directoryUserUpdated], | ||
listMetadata: {}, | ||
}); | ||
})); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -27,3 +27,2 @@ export * from './authenticate-with-magic-auth-options.interface'; | ||
export * from './revoke-session-options.interface'; | ||
export * from './role.interface'; | ||
export * from './send-invitation-options.interface'; | ||
@@ -39,2 +38,1 @@ export * from './send-magic-auth-code-options.interface'; | ||
export * from './verify-email-options.interface'; | ||
export * from './role.interface'; |
@@ -43,3 +43,2 @@ "use strict"; | ||
__exportStar(require("./revoke-session-options.interface"), exports); | ||
__exportStar(require("./role.interface"), exports); | ||
__exportStar(require("./send-invitation-options.interface"), exports); | ||
@@ -55,2 +54,1 @@ __exportStar(require("./send-magic-auth-code-options.interface"), exports); | ||
__exportStar(require("./verify-email-options.interface"), exports); | ||
__exportStar(require("./role.interface"), exports); |
import { PaginationOptions } from '../../common/interfaces'; | ||
import { OrganizationMembershipStatus } from './organization-membership.interface'; | ||
export interface ListOrganizationMembershipsOptions extends PaginationOptions { | ||
organizationId?: string; | ||
userId?: string; | ||
statuses?: OrganizationMembershipStatus[]; | ||
} | ||
@@ -9,2 +11,3 @@ export interface SerializedListOrganizationMembershipsOptions extends PaginationOptions { | ||
user_id?: string; | ||
statuses?: string; | ||
} |
@@ -1,2 +0,3 @@ | ||
import { RoleResponse } from './role.interface'; | ||
import { RoleResponse } from '../../roles/interfaces/'; | ||
export type OrganizationMembershipStatus = 'active' | 'inactive' | 'pending'; | ||
export interface OrganizationMembership { | ||
@@ -6,3 +7,3 @@ object: 'organization_membership'; | ||
organizationId: string; | ||
status: 'active' | 'pending'; | ||
status: OrganizationMembershipStatus; | ||
userId: string; | ||
@@ -17,3 +18,3 @@ createdAt: string; | ||
organization_id: string; | ||
status: 'active' | 'pending'; | ||
status: OrganizationMembershipStatus; | ||
user_id: string; | ||
@@ -20,0 +21,0 @@ created_at: string; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.serializeListOrganizationMembershipsOptions = void 0; | ||
const serializeListOrganizationMembershipsOptions = (options) => ({ | ||
user_id: options.userId, | ||
organization_id: options.organizationId, | ||
limit: options.limit, | ||
before: options.before, | ||
after: options.after, | ||
order: options.order, | ||
}); | ||
const serializeListOrganizationMembershipsOptions = (options) => { | ||
var _a; | ||
return ({ | ||
user_id: options.userId, | ||
organization_id: options.organizationId, | ||
statuses: (_a = options.statuses) === null || _a === void 0 ? void 0 : _a.join(','), | ||
limit: options.limit, | ||
before: options.before, | ||
after: options.after, | ||
order: options.order, | ||
}); | ||
}; | ||
exports.serializeListOrganizationMembershipsOptions = serializeListOrganizationMembershipsOptions; |
@@ -1,2 +0,2 @@ | ||
import { RoleEvent, RoleEventResponse } from '../interfaces'; | ||
import { RoleEvent, RoleEventResponse } from '../../roles/interfaces'; | ||
export declare const deserializeRole: (role: RoleEventResponse) => RoleEvent; |
@@ -58,2 +58,4 @@ import { WorkOS } from '../workos'; | ||
deleteOrganizationMembership(organizationMembershipId: string): Promise<void>; | ||
deactivateOrganizationMembership(organizationMembershipId: string): Promise<OrganizationMembership>; | ||
reactivateOrganizationMembership(organizationMembershipId: string): Promise<OrganizationMembership>; | ||
getInvitation(invitationId: string): Promise<Invitation>; | ||
@@ -60,0 +62,0 @@ listInvitations(options: ListInvitationsOptions): Promise<AutoPaginatable<Invitation>>; |
@@ -205,2 +205,14 @@ "use strict"; | ||
} | ||
deactivateOrganizationMembership(organizationMembershipId) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { data } = yield this.workos.put(`/user_management/organization_memberships/${organizationMembershipId}/deactivate`, {}); | ||
return (0, organization_membership_serializer_1.deserializeOrganizationMembership)(data); | ||
}); | ||
} | ||
reactivateOrganizationMembership(organizationMembershipId) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { data } = yield this.workos.put(`/user_management/organization_memberships/${organizationMembershipId}/reactivate`, {}); | ||
return (0, organization_membership_serializer_1.deserializeOrganizationMembership)(data); | ||
}); | ||
} | ||
getInvitation(invitationId) { | ||
@@ -207,0 +219,0 @@ return __awaiter(this, void 0, void 0, function* () { |
@@ -18,10 +18,11 @@ "use strict"; | ||
const workos_1 = require("../workos"); | ||
const user_json_1 = __importDefault(require("./fixtures/user.json")); | ||
const list_users_json_1 = __importDefault(require("./fixtures/list-users.json")); | ||
const deactivate_organization_membership_json_1 = __importDefault(require("./fixtures/deactivate-organization-membership.json")); | ||
const invitation_json_1 = __importDefault(require("./fixtures/invitation.json")); | ||
const list_factors_json_1 = __importDefault(require("./fixtures/list-factors.json")); | ||
const organization_membership_json_1 = __importDefault(require("./fixtures/organization-membership.json")); | ||
const list_invitations_json_1 = __importDefault(require("./fixtures/list-invitations.json")); | ||
const list_organization_memberships_json_1 = __importDefault(require("./fixtures/list-organization-memberships.json")); | ||
const invitation_json_1 = __importDefault(require("./fixtures/invitation.json")); | ||
const list_invitations_json_1 = __importDefault(require("./fixtures/list-invitations.json")); | ||
const list_users_json_1 = __importDefault(require("./fixtures/list-users.json")); | ||
const magic_auth_json_1 = __importDefault(require("./fixtures/magic_auth.json")); | ||
const organization_membership_json_1 = __importDefault(require("./fixtures/organization-membership.json")); | ||
const user_json_1 = __importDefault(require("./fixtures/user.json")); | ||
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); | ||
@@ -587,2 +588,3 @@ const userId = 'user_01H5JQDV7R7ATEYZDEG0W5PRYS'; | ||
organizationId: 'org_someorg', | ||
statuses: ['active', 'inactive'], | ||
after: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', | ||
@@ -594,2 +596,3 @@ limit: 10, | ||
organization_id: 'org_someorg', | ||
statuses: 'active,inactive', | ||
after: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', | ||
@@ -650,2 +653,34 @@ limit: '10', | ||
}); | ||
describe('deactivateOrganizationMembership', () => { | ||
it('sends a deactivateOrganizationMembership request', () => __awaiter(void 0, void 0, void 0, function* () { | ||
(0, test_utils_1.fetchOnce)(deactivate_organization_membership_json_1.default); | ||
const organizationMembership = yield workos.userManagement.deactivateOrganizationMembership(organizationMembershipId); | ||
expect((0, test_utils_1.fetchURL)()).toContain(`/user_management/organization_memberships/${organizationMembershipId}/deactivate`); | ||
expect(organizationMembership).toMatchObject({ | ||
object: 'organization_membership', | ||
organizationId: 'organization_01H5JQDV7R7ATEYZDEG0W5PRYS', | ||
userId: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', | ||
status: 'inactive', | ||
role: { | ||
slug: 'member', | ||
}, | ||
}); | ||
})); | ||
}); | ||
describe('reactivateOrganizationMembership', () => { | ||
it('sends a reactivateOrganizationMembership request', () => __awaiter(void 0, void 0, void 0, function* () { | ||
(0, test_utils_1.fetchOnce)(organization_membership_json_1.default); | ||
const organizationMembership = yield workos.userManagement.reactivateOrganizationMembership(organizationMembershipId); | ||
expect((0, test_utils_1.fetchURL)()).toContain(`/user_management/organization_memberships/${organizationMembershipId}/reactivate`); | ||
expect(organizationMembership).toMatchObject({ | ||
object: 'organization_membership', | ||
organizationId: 'organization_01H5JQDV7R7ATEYZDEG0W5PRYS', | ||
userId: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS', | ||
status: 'active', | ||
role: { | ||
slug: 'member', | ||
}, | ||
}); | ||
})); | ||
}); | ||
describe('getInvitation', () => { | ||
@@ -652,0 +687,0 @@ it('sends a Get Invitation request', () => __awaiter(void 0, void 0, void 0, function* () { |
import { Event } from '../common/interfaces'; | ||
export declare class Webhooks { | ||
private encoder; | ||
private cryptoProvider; | ||
constructor(subtleCrypto?: typeof crypto.subtle); | ||
constructEvent({ payload, sigHeader, secret, tolerance, }: { | ||
@@ -18,3 +19,2 @@ payload: unknown; | ||
computeSignature(timestamp: any, payload: any, secret: string): Promise<string>; | ||
secureCompare(stringA: string, stringB: string): Promise<boolean>; | ||
} |
@@ -15,5 +15,11 @@ "use strict"; | ||
const serializers_1 = require("../common/serializers"); | ||
const crypto_1 = require("../common/crypto"); | ||
class Webhooks { | ||
constructor() { | ||
this.encoder = new TextEncoder(); | ||
constructor(subtleCrypto) { | ||
if (typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined') { | ||
this.cryptoProvider = new crypto_1.SubtleCryptoProvider(subtleCrypto); | ||
} | ||
else { | ||
this.cryptoProvider = new crypto_1.NodeCryptoProvider(); | ||
} | ||
} | ||
@@ -38,3 +44,4 @@ constructEvent({ payload, sigHeader, secret, tolerance = 180000, }) { | ||
const expectedSig = yield this.computeSignature(timestamp, payload, secret); | ||
if ((yield this.secureCompare(expectedSig, signatureHash)) === false) { | ||
if ((yield this.cryptoProvider.secureCompare(expectedSig, signatureHash)) === | ||
false) { | ||
throw new exceptions_1.SignatureVerificationException('Signature hash does not match the expected signature hash for payload'); | ||
@@ -59,39 +66,6 @@ } | ||
const signedPayload = `${timestamp}.${payload}`; | ||
const key = yield crypto.subtle.importKey('raw', this.encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']); | ||
const signatureBuffer = yield crypto.subtle.sign('HMAC', key, this.encoder.encode(signedPayload)); | ||
// crypto.subtle returns the signature in base64 format. This must be | ||
// encoded in hex to match the CryptoProvider contract. We map each byte in | ||
// the buffer to its corresponding hex octet and then combine into a string. | ||
const signatureBytes = new Uint8Array(signatureBuffer); | ||
const signatureHexCodes = new Array(signatureBytes.length); | ||
for (let i = 0; i < signatureBytes.length; i++) { | ||
signatureHexCodes[i] = byteHexMapping[signatureBytes[i]]; | ||
} | ||
return signatureHexCodes.join(''); | ||
return yield this.cryptoProvider.computeHMACSignatureAsync(signedPayload, secret); | ||
}); | ||
} | ||
secureCompare(stringA, stringB) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const bufferA = this.encoder.encode(stringA); | ||
const bufferB = this.encoder.encode(stringB); | ||
if (bufferA.length !== bufferB.length) { | ||
return false; | ||
} | ||
const algorithm = { name: 'HMAC', hash: 'SHA-256' }; | ||
const key = (yield crypto.subtle.generateKey(algorithm, false, [ | ||
'sign', | ||
'verify', | ||
])); | ||
const hmac = yield crypto.subtle.sign(algorithm, key, bufferA); | ||
const equal = yield crypto.subtle.verify(algorithm, key, hmac, bufferB); | ||
return equal; | ||
}); | ||
} | ||
} | ||
exports.Webhooks = Webhooks; | ||
// Cached mapping of byte to hex representation. We do this once to avoid re- | ||
// computing every time we need to convert the result of a signature to hex. | ||
const byteHexMapping = new Array(256); | ||
for (let i = 0; i < byteHexMapping.length; i++) { | ||
byteHexMapping[i] = i.toString(16).padStart(2, '0'); | ||
} |
@@ -20,2 +20,3 @@ "use strict"; | ||
const exceptions_1 = require("../common/exceptions"); | ||
const crypto_2 = require("../common/crypto"); | ||
describe('Webhooks', () => { | ||
@@ -191,2 +192,30 @@ let payload; | ||
}); | ||
describe('when in an environment that supports SubtleCrypto', () => { | ||
it('automatically uses the subtle crypto library', () => { | ||
// tslint:disable-next-line | ||
expect(workos.webhooks['cryptoProvider']).toBeInstanceOf(crypto_2.SubtleCryptoProvider); | ||
}); | ||
}); | ||
describe('CryptoProvider', () => { | ||
describe('when computing HMAC signature', () => { | ||
it('returns the same for the Node crypto and Web Crypto versions', () => __awaiter(void 0, void 0, void 0, function* () { | ||
const nodeCryptoProvider = new crypto_2.NodeCryptoProvider(); | ||
const subtleCryptoProvider = new crypto_2.SubtleCryptoProvider(); | ||
const stringifiedPayload = JSON.stringify(payload); | ||
const payloadHMAC = `${timestamp}.${stringifiedPayload}`; | ||
const nodeCompare = yield nodeCryptoProvider.computeHMACSignatureAsync(payloadHMAC, secret); | ||
const subtleCompare = yield subtleCryptoProvider.computeHMACSignatureAsync(payloadHMAC, secret); | ||
expect(nodeCompare).toEqual(subtleCompare); | ||
})); | ||
}); | ||
describe('when securely comparing', () => { | ||
it('returns the same for the Node crypto and Web Crypto versions', () => __awaiter(void 0, void 0, void 0, function* () { | ||
const nodeCryptoProvider = new crypto_2.NodeCryptoProvider(); | ||
const subtleCryptoProvider = new crypto_2.SubtleCryptoProvider(); | ||
const signature = yield workos.webhooks.computeSignature(timestamp, payload, secret); | ||
expect(nodeCryptoProvider.secureCompare(signature, signatureHash)).toEqual(subtleCryptoProvider.secureCompare(signature, signatureHash)); | ||
expect(nodeCryptoProvider.secureCompare(signature, 'foo')).toEqual(subtleCryptoProvider.secureCompare(signature, 'foo')); | ||
})); | ||
}); | ||
}); | ||
}); |
@@ -42,3 +42,3 @@ import { GetOptions, PostOptions, PutOptions, WorkOSOptions } from './common/interfaces'; | ||
emitWarning(warning: string): void; | ||
private handleFetchError; | ||
private handleHttpError; | ||
} |
@@ -26,4 +26,4 @@ "use strict"; | ||
const bad_request_exception_1 = require("./common/exceptions/bad-request.exception"); | ||
const fetch_client_1 = require("./common/utils/fetch-client"); | ||
const VERSION = '7.4.0'; | ||
const net_1 = require("./common/net"); | ||
const VERSION = '7.5.0'; | ||
const DEFAULT_HOSTNAME = 'api.workos.com'; | ||
@@ -68,3 +68,3 @@ class WorkOS { | ||
} | ||
this.client = new fetch_client_1.FetchClient(this.baseURL, Object.assign(Object.assign({}, options.config), { headers: Object.assign(Object.assign({}, (_a = options.config) === null || _a === void 0 ? void 0 : _a.headers), { Authorization: `Bearer ${this.key}`, 'User-Agent': userAgent }) })); | ||
this.client = (0, net_1.createHttpClient)(this.baseURL, Object.assign(Object.assign({}, options.config), { headers: Object.assign(Object.assign({}, (_a = options.config) === null || _a === void 0 ? void 0 : _a.headers), { Authorization: `Bearer ${this.key}`, 'User-Agent': userAgent }) }), options.fetchFn); | ||
} | ||
@@ -81,9 +81,10 @@ get version() { | ||
try { | ||
return yield this.client.post(path, entity, { | ||
const res = yield this.client.post(path, entity, { | ||
params: options.query, | ||
headers: requestHeaders, | ||
}); | ||
return { data: yield res.toJSON() }; | ||
} | ||
catch (error) { | ||
this.handleFetchError({ path, error }); | ||
this.handleHttpError({ path, error }); | ||
throw error; | ||
@@ -97,3 +98,3 @@ } | ||
const { accessToken } = options; | ||
return yield this.client.get(path, { | ||
const res = yield this.client.get(path, { | ||
params: options.query, | ||
@@ -104,5 +105,6 @@ headers: accessToken | ||
}); | ||
return { data: yield res.toJSON() }; | ||
} | ||
catch (error) { | ||
this.handleFetchError({ path, error }); | ||
this.handleHttpError({ path, error }); | ||
throw error; | ||
@@ -119,9 +121,10 @@ } | ||
try { | ||
return yield this.client.put(path, entity, { | ||
const res = yield this.client.put(path, entity, { | ||
params: options.query, | ||
headers: requestHeaders, | ||
}); | ||
return { data: yield res.toJSON() }; | ||
} | ||
catch (error) { | ||
this.handleFetchError({ path, error }); | ||
this.handleHttpError({ path, error }); | ||
throw error; | ||
@@ -139,3 +142,3 @@ } | ||
catch (error) { | ||
this.handleFetchError({ path, error }); | ||
this.handleHttpError({ path, error }); | ||
throw error; | ||
@@ -153,8 +156,11 @@ } | ||
} | ||
handleFetchError({ path, error }) { | ||
handleHttpError({ path, error }) { | ||
var _a; | ||
if (!(error instanceof net_1.HttpClientError)) { | ||
throw new Error(`Unexpected error: ${error}`); | ||
} | ||
const { response } = error; | ||
if (response) { | ||
const { status, data, headers } = response; | ||
const requestID = (_a = headers.get('X-Request-ID')) !== null && _a !== void 0 ? _a : ''; | ||
const requestID = (_a = headers['X-Request-ID']) !== null && _a !== void 0 ? _a : ''; | ||
const { code, error_description: errorDescription, error, errors, message, } = data; | ||
@@ -161,0 +167,0 @@ switch (status) { |
@@ -21,2 +21,3 @@ "use strict"; | ||
const rate_limit_exceeded_exception_1 = require("./common/exceptions/rate-limit-exceeded.exception"); | ||
const net_1 = require("./common/net"); | ||
describe('WorkOS', () => { | ||
@@ -99,6 +100,36 @@ beforeEach(() => jest_fetch_mock_1.default.resetMocks()); | ||
expect((0, test_utils_1.fetchHeaders)()).toMatchObject({ | ||
'User-Agent': `workos-node/${packageJson.version} fooApp: 1.0.0`, | ||
'User-Agent': `workos-node/${packageJson.version}/fetch fooApp: 1.0.0`, | ||
}); | ||
})); | ||
}); | ||
describe('when no `appInfo` option is provided', () => { | ||
it('adds the HTTP client name to the user-agent', () => __awaiter(void 0, void 0, void 0, function* () { | ||
(0, test_utils_1.fetchOnce)('{}'); | ||
const packageJson = JSON.parse(yield promises_1.default.readFile('package.json', 'utf8')); | ||
const workos = new workos_1.WorkOS('sk_test'); | ||
yield workos.post('/somewhere', {}); | ||
expect((0, test_utils_1.fetchHeaders)()).toMatchObject({ | ||
'User-Agent': `workos-node/${packageJson.version}/fetch`, | ||
}); | ||
})); | ||
}); | ||
describe('when no `appInfo` option is provided', () => { | ||
it('adds the HTTP client name to the user-agent', () => __awaiter(void 0, void 0, void 0, function* () { | ||
(0, test_utils_1.fetchOnce)('{}'); | ||
const packageJson = JSON.parse(yield promises_1.default.readFile('package.json', 'utf8')); | ||
const workos = new workos_1.WorkOS('sk_test'); | ||
yield workos.post('/somewhere', {}); | ||
expect((0, test_utils_1.fetchHeaders)()).toMatchObject({ | ||
'User-Agent': `workos-node/${packageJson.version}/fetch`, | ||
}); | ||
})); | ||
}); | ||
describe('when using an environment that supports fetch', () => { | ||
it('automatically uses the fetch HTTP client', () => { | ||
const workos = new workos_1.WorkOS('sk_test'); | ||
// Bracket notation gets past private visibility | ||
// tslint:disable-next-line | ||
expect(workos['client']).toBeInstanceOf(net_1.FetchHttpClient); | ||
}); | ||
}); | ||
}); | ||
@@ -182,10 +213,32 @@ describe('version', () => { | ||
describe('when the entity is null', () => { | ||
it('sends a null body', () => __awaiter(void 0, void 0, void 0, function* () { | ||
it('sends an empty string body', () => __awaiter(void 0, void 0, void 0, function* () { | ||
(0, test_utils_1.fetchOnce)(); | ||
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU'); | ||
yield workos.post('/somewhere', null); | ||
expect((0, test_utils_1.fetchBody)({ raw: true })).toBeNull(); | ||
expect((0, test_utils_1.fetchBody)({ raw: true })).toBe(''); | ||
})); | ||
}); | ||
}); | ||
describe('when in an environment that does not support fetch', () => { | ||
const fetchFn = globalThis.fetch; | ||
beforeEach(() => { | ||
// @ts-ignore | ||
delete globalThis.fetch; | ||
}); | ||
afterEach(() => { | ||
globalThis.fetch = fetchFn; | ||
}); | ||
it('automatically uses the node HTTP client', () => { | ||
const workos = new workos_1.WorkOS('sk_test_key'); | ||
// tslint:disable-next-line | ||
expect(workos['client']).toBeInstanceOf(net_1.NodeHttpClient); | ||
}); | ||
it('uses a fetch function if provided', () => { | ||
const workos = new workos_1.WorkOS('sk_test_key', { | ||
fetchFn, | ||
}); | ||
// tslint:disable-next-line | ||
expect(workos['client']).toBeInstanceOf(net_1.FetchHttpClient); | ||
}); | ||
}); | ||
}); |
{ | ||
"version": "7.4.0", | ||
"version": "7.5.0-beta.node-compatibility", | ||
"name": "@workos-inc/node", | ||
@@ -16,5 +16,4 @@ "author": "WorkOS", | ||
"engines": { | ||
"node": ">=19" | ||
"node": ">=16" | ||
}, | ||
"engineStrict": true, | ||
"main": "lib/index.js", | ||
@@ -21,0 +20,0 @@ "typings": "lib/index.d.ts", |
@@ -12,2 +12,6 @@ # WorkOS Node.js Library | ||
## Requirements | ||
Node 16 or higher. | ||
## Installation | ||
@@ -14,0 +18,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
450079
447
9661
64
1
3