@workos-inc/node 10.10.0 → 10.12.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.
@@ -321,7 +321,7 @@ var FetchHttpClient = class FetchHttpClient extends HttpClient {
321
321
  message: `Request timeout after ${timeout}ms`,
322
322
  response: {
323
323
  status: 408,
324
- headers: {},
324
+ headers: new Headers(),
325
325
  data: { error: "Request timeout" }
326
326
  }
327
327
  });
@@ -610,10 +610,11 @@ var UnprocessableEntityException = class extends Error {
610
610
  message = "Unprocessable entity";
611
611
  code;
612
612
  requestID;
613
- constructor({ code, errors, message, requestID }) {
613
+ constructor({ code, error, errors, message, requestID }) {
614
614
  super();
615
615
  this.requestID = requestID;
616
616
  if (message) this.message = message;
617
+ else if (error) this.message = `Error: ${error}`;
617
618
  if (code) this.code = code;
618
619
  if (errors) {
619
620
  const requirement = errors.length === 1 ? "requirement" : "requirements";
@@ -1242,7 +1243,8 @@ var Actions = class {
1242
1243
  tolerance
1243
1244
  };
1244
1245
  await this.verifyHeader(options);
1245
- return deserializeAction(typeof payload === "string" || isBinaryPayload(payload) ? JSON.parse(decodePayloadToString(payload)) : payload);
1246
+ const parsed = typeof payload === "string" || isBinaryPayload(payload) ? JSON.parse(decodePayloadToString(payload)) : payload;
1247
+ return deserializeAction(parsed);
1246
1248
  }
1247
1249
  };
1248
1250
  //#endregion
@@ -1410,6 +1412,19 @@ const serializeCreateOrganizationOptions = (options) => ({
1410
1412
  metadata: options.metadata
1411
1413
  });
1412
1414
  //#endregion
1415
+ //#region src/organizations/serializers/it-contact-options.serializer.ts
1416
+ const serializeCreateItContactOptions = (options) => ({ email: options.email });
1417
+ const serializeInviteItContactOptions = (options) => ({ intents: options.intents });
1418
+ //#endregion
1419
+ //#region src/organizations/serializers/it-contact.serializer.ts
1420
+ const deserializeItContact = (itContact) => ({
1421
+ object: itContact.object,
1422
+ id: itContact.id,
1423
+ email: itContact.email,
1424
+ createdAt: itContact.created_at,
1425
+ updatedAt: itContact.updated_at
1426
+ });
1427
+ //#endregion
1413
1428
  //#region src/organizations/serializers/update-organization-options.serializer.ts
1414
1429
  const serializeUpdateOrganizationOptions = (options) => ({
1415
1430
  name: options.name,
@@ -1658,6 +1673,30 @@ const deserializeOrganizationDomainVerificationFailed = (organizationDomainVerif
1658
1673
  });
1659
1674
  //#endregion
1660
1675
  //#region src/common/serializers/event.serializer.ts
1676
+ const deserializePipesConnectedAccount = (connectedAccount) => ({
1677
+ object: connectedAccount.object,
1678
+ id: connectedAccount.id,
1679
+ dataIntegrationId: connectedAccount.data_integration_id,
1680
+ providerSlug: connectedAccount.provider_slug,
1681
+ userId: connectedAccount.user_id,
1682
+ organizationId: connectedAccount.organization_id,
1683
+ scopes: connectedAccount.scopes,
1684
+ state: connectedAccount.state,
1685
+ createdAt: connectedAccount.created_at,
1686
+ updatedAt: connectedAccount.updated_at
1687
+ });
1688
+ const deserializePipesConnectionFailed = (connectionFailed) => ({
1689
+ object: connectionFailed.object,
1690
+ dataIntegrationId: connectionFailed.data_integration_id,
1691
+ providerSlug: connectionFailed.provider_slug,
1692
+ userId: connectionFailed.user_id,
1693
+ organizationId: connectionFailed.organization_id,
1694
+ errorCode: connectionFailed.error_code,
1695
+ errorReason: connectionFailed.error_reason,
1696
+ providerError: connectionFailed.provider_error,
1697
+ providerErrorDescription: connectionFailed.provider_error_description,
1698
+ createdAt: connectionFailed.created_at
1699
+ });
1661
1700
  const deserializeEvent = (event) => {
1662
1701
  const eventBase = {
1663
1702
  id: event.id,
@@ -1850,6 +1889,18 @@ const deserializeEvent = (event) => {
1850
1889
  organizationMembershipId: event.data.organization_membership_id
1851
1890
  }
1852
1891
  };
1892
+ case "pipes.connected_account.connected":
1893
+ case "pipes.connected_account.disconnected":
1894
+ case "pipes.connected_account.reauthorization_needed": return {
1895
+ ...eventBase,
1896
+ event: event.event,
1897
+ data: deserializePipesConnectedAccount(event.data)
1898
+ };
1899
+ case "pipes.connected_account.connection_failed": return {
1900
+ ...eventBase,
1901
+ event: event.event,
1902
+ data: deserializePipesConnectionFailed(event.data)
1903
+ };
1853
1904
  case "vault.data.created": return {
1854
1905
  ...eventBase,
1855
1906
  event: event.event,
@@ -2057,7 +2108,8 @@ var Webhooks = class {
2057
2108
  tolerance
2058
2109
  };
2059
2110
  await this.verifyHeader(options);
2060
- return deserializeEvent(this.parseVerifiedPayload(payload));
2111
+ const webhookPayload = this.parseVerifiedPayload(payload);
2112
+ return deserializeEvent(webhookPayload);
2061
2113
  }
2062
2114
  parseVerifiedPayload(payload) {
2063
2115
  if (typeof payload === "object" && !isBinaryPayload(payload)) return payload;
@@ -2130,7 +2182,7 @@ let _josePromise;
2130
2182
  * @returns Promise that resolves to the jose module
2131
2183
  */
2132
2184
  function getJose() {
2133
- return _josePromise ??= import("./webapi-BgpV54gi.mjs");
2185
+ return _josePromise ??= import("./webapi-BlhUk1KL.mjs");
2134
2186
  }
2135
2187
  //#endregion
2136
2188
  //#region src/agents/serializers/agent-registration.serializer.ts
@@ -2348,7 +2400,7 @@ var Agents = class {
2348
2400
  const { clientId } = this.workos;
2349
2401
  if (!clientId) throw new Error("Missing client ID. Did you provide it when initializing WorkOS?");
2350
2402
  const { createRemoteJWKSet } = await getJose();
2351
- this._jwks ??= createRemoteJWKSet(new URL(`${this.workos.baseURL}/sso/jwks/${clientId}`), { cooldownDuration: 1e3 * 60 * 5 });
2403
+ this._jwks ??= createRemoteJWKSet(new URL(`${this.workos.baseURL}/sso/jwks/${clientId}`), { cooldownDuration: 3e5 });
2352
2404
  return this._jwks;
2353
2405
  }
2354
2406
  };
@@ -3047,6 +3099,88 @@ var Organizations = class {
3047
3099
  const { data } = await this.workos.put(`/organizations/${organizationId}`, serializeUpdateOrganizationOptions(payload));
3048
3100
  return deserializeOrganization(data);
3049
3101
  }
3102
+ /**
3103
+ * List IT Contacts
3104
+ *
3105
+ * Get the IT Contacts for an Organization.
3106
+ * @param options - Object containing the Organization ID.
3107
+ * @returns {Promise<List<ItContact>>}
3108
+ * @throws {AuthorizationException} 403
3109
+ * @throws {NotFoundException} 404
3110
+ */
3111
+ async listItContacts(options) {
3112
+ const { organizationId } = options;
3113
+ const { data } = await this.workos.get(`/organizations/${organizationId}/it_contacts`);
3114
+ return {
3115
+ object: data.object,
3116
+ data: data.data.map(deserializeItContact),
3117
+ listMetadata: {
3118
+ before: data.list_metadata.before,
3119
+ after: data.list_metadata.after
3120
+ }
3121
+ };
3122
+ }
3123
+ /**
3124
+ * Create an IT Contact
3125
+ *
3126
+ * Add an IT Contact to an Organization. No Admin Portal invitation is sent,
3127
+ * though the contact is notified if the Organization has a connection
3128
+ * certificate nearing expiry.
3129
+ * @param options - Object containing the Organization ID and the email address.
3130
+ * @returns {Promise<ItContact>}
3131
+ * @throws {AuthorizationException} 403
3132
+ * @throws {NotFoundException} 404
3133
+ * @throws {ConflictException} 409
3134
+ * @throws {UnprocessableEntityException} 422
3135
+ */
3136
+ async createItContact(options) {
3137
+ const { organizationId, ...payload } = options;
3138
+ const { data } = await this.workos.post(`/organizations/${organizationId}/it_contacts`, serializeCreateItContactOptions(payload));
3139
+ return deserializeItContact(data);
3140
+ }
3141
+ /**
3142
+ * Delete an IT Contact
3143
+ *
3144
+ * Remove an IT Contact from an Organization and revoke the contact's active
3145
+ * setup links.
3146
+ * @param options - Object containing the Organization ID and the IT Contact ID.
3147
+ * @returns {Promise<void>}
3148
+ * @throws {AuthorizationException} 403
3149
+ * @throws {NotFoundException} 404
3150
+ */
3151
+ async deleteItContact(options) {
3152
+ const { organizationId, contactId } = options;
3153
+ await this.workos.delete(`/organizations/${organizationId}/it_contacts/${contactId}`);
3154
+ }
3155
+ /**
3156
+ * Invite an IT Contact
3157
+ *
3158
+ * Create an Admin Portal setup link and email it to the IT Contact. An
3159
+ * Organization can have at most one active invitation.
3160
+ * @param options - Object containing the Organization ID, the IT Contact ID and the intents.
3161
+ * @returns {Promise<void>}
3162
+ * @throws {AuthorizationException} 403
3163
+ * @throws {NotFoundException} 404
3164
+ * @throws {ConflictException} 409
3165
+ * @throws {UnprocessableEntityException} 422
3166
+ */
3167
+ async inviteItContact(options) {
3168
+ const { organizationId, contactId, ...payload } = options;
3169
+ await this.workos.post(`/organizations/${organizationId}/it_contacts/${contactId}/invite`, serializeInviteItContactOptions(payload));
3170
+ }
3171
+ /**
3172
+ * Revoke an IT Contact's invitation
3173
+ *
3174
+ * Revoke the Organization's active Admin Portal invitation.
3175
+ * @param options - Object containing the Organization ID and the IT Contact ID.
3176
+ * @returns {Promise<void>}
3177
+ * @throws {AuthorizationException} 403
3178
+ * @throws {NotFoundException} 404
3179
+ */
3180
+ async revokeItContact(options) {
3181
+ const { organizationId, contactId } = options;
3182
+ await this.workos.post(`/organizations/${organizationId}/it_contacts/${contactId}/revoke`, {});
3183
+ }
3050
3184
  };
3051
3185
  //#endregion
3052
3186
  //#region src/organization-domains/serializers/create-organization-domain-options.serializer.ts
@@ -5037,7 +5171,7 @@ var UserManagement = class {
5037
5171
  async getJWKS() {
5038
5172
  const { createRemoteJWKSet } = await getJose();
5039
5173
  if (!this.clientId) return;
5040
- this._jwks ??= createRemoteJWKSet(new URL(this.getJwksUrl(this.clientId)), { cooldownDuration: 1e3 * 60 * 5 });
5174
+ this._jwks ??= createRemoteJWKSet(new URL(this.getJwksUrl(this.clientId)), { cooldownDuration: 3e5 });
5041
5175
  return this._jwks;
5042
5176
  }
5043
5177
  /**
@@ -5947,31 +6081,91 @@ var InMemoryStore = class {
5947
6081
  };
5948
6082
  //#endregion
5949
6083
  //#region src/feature-flags/evaluator.ts
6084
+ const TARGET_TYPE_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;
6085
+ const TARGET_ID_PATTERN = /^[A-Za-z0-9._:-]{1,255}$/;
6086
+ const LEGACY_KEY_TO_TARGET_TYPE = /* @__PURE__ */ new Map([["userId", "user"], ["organizationId", "organization"]]);
6087
+ const isEvaluationResource = (value) => typeof value === "object" && value !== null && "id" in value && typeof value.id === "string";
5950
6088
  var Evaluator = class {
5951
6089
  store;
5952
- constructor(store) {
6090
+ logger;
6091
+ constructor(store, logger) {
5953
6092
  this.store = store;
6093
+ this.logger = logger;
5954
6094
  }
5955
6095
  isEnabled(flagKey, context = {}, defaultValue = false) {
5956
- const entry = this.store.get(flagKey);
5957
- if (!entry) return defaultValue;
5958
- if (!entry.enabled) return false;
5959
- if (context.userId) {
5960
- const userTarget = entry.targets.users.find((t) => t.id === context.userId);
5961
- if (userTarget) return userTarget.enabled;
5962
- }
5963
- if (context.organizationId) {
5964
- const orgTarget = entry.targets.organizations.find((t) => t.id === context.organizationId);
5965
- if (orgTarget) return orgTarget.enabled;
5966
- }
5967
- return entry.default_value;
6096
+ return this.evaluate(this.store.get(flagKey), this.normalizeContext(context), defaultValue);
5968
6097
  }
5969
6098
  getAllFlags(context = {}) {
6099
+ const normalizedContext = this.normalizeContext(context);
5970
6100
  const flags = this.store.getAll();
5971
6101
  const result = {};
5972
- for (const slug of Object.keys(flags)) result[slug] = this.isEnabled(slug, context);
6102
+ for (const slug of Object.keys(flags)) result[slug] = this.evaluate(flags[slug], normalizedContext, false);
5973
6103
  return result;
5974
6104
  }
6105
+ evaluate(entry, normalizedContext, defaultValue) {
6106
+ if (!entry) return defaultValue;
6107
+ if (!entry.enabled) return false;
6108
+ for (const [targetType, targetId] of normalizedContext) if (this.hasEnabledTarget(entry, targetType, targetId)) return true;
6109
+ return entry.default_value;
6110
+ }
6111
+ /**
6112
+ * Reduces either context form to target type → ID pairs. Evaluation must
6113
+ * never throw in application code, so every invalid piece of context
6114
+ * degrades to "matches no targets" with a logged warning instead of an
6115
+ * error.
6116
+ */
6117
+ normalizeContext(context) {
6118
+ const normalized = /* @__PURE__ */ new Map();
6119
+ const record = context;
6120
+ const legacyEntries = [];
6121
+ const typedKeys = [];
6122
+ for (const [key, value] of Object.entries(record)) {
6123
+ if (value === void 0 || value === null) continue;
6124
+ const legacyTargetType = LEGACY_KEY_TO_TARGET_TYPE.get(key);
6125
+ if (legacyTargetType) {
6126
+ if (typeof value === "string" && value !== "") legacyEntries.push([legacyTargetType, value]);
6127
+ continue;
6128
+ }
6129
+ typedKeys.push(key);
6130
+ }
6131
+ const resourceShapedKeys = typedKeys.filter((key) => typeof record[key] === "object");
6132
+ if (legacyEntries.length > 0 && resourceShapedKeys.length > 0) {
6133
+ this.logger?.warn("Evaluation context mixes legacy keys (userId/organizationId) with typed target keys; no targets will match", { keys: Object.keys(record) });
6134
+ return normalized;
6135
+ }
6136
+ if (legacyEntries.length > 0) {
6137
+ for (const [targetType, targetId] of legacyEntries) normalized.set(targetType, targetId);
6138
+ return normalized;
6139
+ }
6140
+ for (const key of typedKeys) {
6141
+ if (!TARGET_TYPE_PATTERN.test(key)) {
6142
+ this.logger?.warn(`Ignoring invalid target type in evaluation context: ${key}`);
6143
+ continue;
6144
+ }
6145
+ const value = record[key];
6146
+ if (!isEvaluationResource(value)) {
6147
+ this.logger?.warn(`Ignoring target type with a missing or invalid resource id in evaluation context: ${key}`);
6148
+ continue;
6149
+ }
6150
+ const { id } = value;
6151
+ if (!TARGET_ID_PATTERN.test(id) || id === "." || id === "..") {
6152
+ this.logger?.warn(`Ignoring invalid target id in evaluation context for type: ${key}`);
6153
+ continue;
6154
+ }
6155
+ normalized.set(key, id);
6156
+ }
6157
+ return normalized;
6158
+ }
6159
+ /**
6160
+ * A target participates in evaluation only while its `enabled` is true. A
6161
+ * `false` value is reserved for future disabled overrides and is treated
6162
+ * as if the target were absent.
6163
+ */
6164
+ hasEnabledTarget(entry, targetType, targetId) {
6165
+ if (targetType === "user") return entry.targets.users.some((t) => t.id === targetId && t.enabled);
6166
+ if (targetType === "organization") return entry.targets.organizations.some((t) => t.id === targetId && t.enabled);
6167
+ return (entry.targets.custom_targets ?? []).some((t) => t.type === targetType && t.id === targetId && t.enabled);
6168
+ }
5975
6169
  };
5976
6170
  //#endregion
5977
6171
  //#region src/feature-flags/runtime-client.ts
@@ -6013,7 +6207,7 @@ var FeatureFlagsRuntimeClient = class extends EventEmitter {
6013
6207
  this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
6014
6208
  this.logger = options.logger;
6015
6209
  this.store = new InMemoryStore();
6016
- this.evaluator = new Evaluator(this.store);
6210
+ this.evaluator = new Evaluator(this.store, this.logger);
6017
6211
  this.readyPromise = new Promise((resolve, reject) => {
6018
6212
  this.readyResolve = resolve;
6019
6213
  this.readyReject = reject;
@@ -6158,7 +6352,12 @@ var FeatureFlagsRuntimeClient = class extends EventEmitter {
6158
6352
  const map = new Map(ys.map((t) => [t.id, t.enabled]));
6159
6353
  return xs.some((t) => map.get(t.id) !== t.enabled);
6160
6354
  };
6161
- return targetsChanged(a.targets.users, b.targets.users) || targetsChanged(a.targets.organizations, b.targets.organizations);
6355
+ const customTargetsChanged = (xs, ys) => {
6356
+ if (xs.length !== ys.length) return true;
6357
+ const map = new Map(ys.map((t) => [`${t.type}:${t.id}`, t.enabled]));
6358
+ return xs.some((t) => map.get(`${t.type}:${t.id}`) !== t.enabled);
6359
+ };
6360
+ return targetsChanged(a.targets.users, b.targets.users) || targetsChanged(a.targets.organizations, b.targets.organizations) || customTargetsChanged(a.targets.custom_targets ?? [], b.targets.custom_targets ?? []);
6162
6361
  }
6163
6362
  };
6164
6363
  //#endregion
@@ -8071,7 +8270,7 @@ var Vault = class {
8071
8270
  };
8072
8271
  //#endregion
8073
8272
  //#region package.json
8074
- var version = "10.10.0";
8273
+ var version = "10.12.0";
8075
8274
  //#endregion
8076
8275
  //#region src/workos.ts
8077
8276
  const DEFAULT_HOSTNAME = "api.workos.com";
@@ -8302,7 +8501,7 @@ var WorkOS = class {
8302
8501
  const { response } = error;
8303
8502
  if (response) {
8304
8503
  const { status, data, headers } = response;
8305
- const requestID = headers["X-Request-ID"] ?? "";
8504
+ const requestID = headers.get("X-Request-ID") ?? "";
8306
8505
  const { code, error_description: errorDescription, error, errors, message } = data;
8307
8506
  switch (status) {
8308
8507
  case 401: throw new UnauthorizedException(requestID);
@@ -8314,6 +8513,7 @@ var WorkOS = class {
8314
8513
  });
8315
8514
  case 422: throw new UnprocessableEntityException({
8316
8515
  code,
8516
+ error,
8317
8517
  errors,
8318
8518
  message,
8319
8519
  requestID
@@ -8360,6 +8560,15 @@ let DomainDataState = /* @__PURE__ */ function(DomainDataState) {
8360
8560
  return DomainDataState;
8361
8561
  }({});
8362
8562
  //#endregion
8563
+ //#region src/organizations/interfaces/it-contact-options.interface.ts
8564
+ const ItContactIntent = {
8565
+ SSO: "sso",
8566
+ DirectorySync: "directory_sync",
8567
+ LogStreams: "log_streams",
8568
+ DomainVerification: "domain_verification",
8569
+ BringYourOwnKey: "bring_your_own_key"
8570
+ };
8571
+ //#endregion
8363
8572
  //#region src/organization-domains/interfaces/organization-domain.interface.ts
8364
8573
  let OrganizationDomainState = /* @__PURE__ */ function(OrganizationDomainState) {
8365
8574
  OrganizationDomainState["Verified"] = "verified";
@@ -8421,6 +8630,6 @@ function createWorkOS(options) {
8421
8630
  return new WorkOS(options);
8422
8631
  }
8423
8632
  //#endregion
8424
- export { FetchHttpClient as A, NoApiKeyProvidedException as C, isAuthenticationErrorData as D, AuthenticationException as E, GenericServerException as O, NotFoundException as S, BadRequestException as T, UnprocessableEntityException as _, DomainDataState as a, RateLimitExceededException as b, FeatureFlagsRuntimeClient as c, serializeRevokeSessionOptions as d, AuthenticateWithSessionCookieFailureReason as f, Actions as g, AutoPaginatable as h, OrganizationDomainVerificationStrategy as i, SubtleCryptoProvider as j, ApiKeyRequiredException as k, CookieSession as l, Webhooks as m, ConnectionType as n, GenerateLinkIntent as o, PKCE as p, OrganizationDomainState as r, WorkOS as s, createWorkOS as t, RefreshSessionFailureReason as u, UnauthorizedException as v, ConflictException as w, OauthException as x, SignatureVerificationException as y };
8633
+ export { ApiKeyRequiredException as A, NotFoundException as C, AuthenticationException as D, BadRequestException as E, SubtleCryptoProvider as M, isAuthenticationErrorData as O, OauthException as S, ConflictException as T, Actions as _, ItContactIntent as a, SignatureVerificationException as b, WorkOS as c, RefreshSessionFailureReason as d, serializeRevokeSessionOptions as f, AutoPaginatable as g, Webhooks as h, OrganizationDomainVerificationStrategy as i, FetchHttpClient as j, GenericServerException as k, FeatureFlagsRuntimeClient as l, PKCE as m, ConnectionType as n, DomainDataState as o, AuthenticateWithSessionCookieFailureReason as p, OrganizationDomainState as r, GenerateLinkIntent as s, createWorkOS as t, CookieSession as u, UnprocessableEntityException as v, NoApiKeyProvidedException as w, RateLimitExceededException as x, UnauthorizedException as y };
8425
8634
 
8426
- //# sourceMappingURL=factory-2nVUxmEk.mjs.map
8635
+ //# sourceMappingURL=factory-AQv-AfDk.mjs.map