import type { WorkOS } from "@workos-inc/node/worker";import { GenericServerException, NotFoundException, WorkOS as WorkOSClient,} from "@workos-inc/node/worker";import { Data, Effect, Option, Result, Schema } from "effect"; export interface WorkOSVaultObjectMetadata { readonly context: Record<string, unknown>; readonly id: string; readonly updatedAt: Date; readonly versionId: string;} export interface WorkOSVaultObject { readonly id: string; readonly metadata: WorkOSVaultObjectMetadata; readonly name: string; readonly value?: string;} const WORKOS_KEK_NOT_READY_MESSAGE = "KEK was created but is not yet ready. This request can be retried."; const CauseWithStatusSchema = Schema.Struct({ status: Schema.Number,});const decodeCauseWithStatusOption = Schema.decodeUnknownOption(CauseWithStatusSchema); const statusFromWorkOSCause = (cause: unknown): number | undefined => { if (cause instanceof GenericServerException || cause instanceof NotFoundException) { return cause.status; } return Option.match(decodeCauseWithStatusOption(cause), { onNone: () => undefined, onSome: (decoded) => decoded.status, });}; const isKekNotReadyWorkOSCause = (cause: unknown): boolean => cause instanceof GenericServerException && // oxlint-disable-next-line executor/no-unknown-error-message -- boundary: WorkOS only exposes this retryable Vault condition through its SDK exception message cause.message.endsWith(WORKOS_KEK_NOT_READY_MESSAGE); export class WorkOSVaultClientError extends Data.TaggedError("WorkOSVaultClientError")<{ readonly cause: unknown; readonly message: string; readonly operation: string; readonly retryKind?: "kek_not_ready"; readonly status?: number;}> { constructor(options: { readonly cause: unknown; readonly message?: string; readonly operation: string; readonly retryKind?: "kek_not_ready"; readonly status?: number; }) { super({ cause: options.cause, message: options.message ?? `WorkOS Vault ${options.operation} failed`, operation: options.operation, retryKind: options.retryKind ?? (isKekNotReadyWorkOSCause(options.cause) ? "kek_not_ready" : undefined), status: options.status ?? statusFromWorkOSCause(options.cause), }); }} export class WorkOSVaultClientInstantiationError extends Data.TaggedError( "WorkOSVaultClientInstantiationError",)<{ readonly cause: unknown;}> {} // Promise-shaped facade onto the underlying WorkOS SDK. Module-private — the// public surface in `WorkOSVaultClient` is Effect-only. Test doubles import// this type to stand up an in-memory equivalent.export interface WorkOSVaultPromiseApi { readonly createObject: (options: { readonly name: string; readonly value: string; readonly context: Record<string, string>; }) => Promise<WorkOSVaultObjectMetadata>; readonly readObjectByName: (name: string) => Promise<WorkOSVaultObject>; readonly updateObject: (options: { readonly id: string; readonly value: string; readonly versionCheck?: string; }) => Promise<WorkOSVaultObject>; readonly deleteObject: (options: { readonly id: string }) => Promise<void>;} export interface WorkOSVaultCredentials { readonly apiKey: string; readonly clientId: string; /** Optional WorkOS API base-URL override (e.g. a WorkOS emulator in tests). */ readonly apiUrl?: string;} const apiUrlOptions = ( url: string | undefined,): { apiHostname?: string; port?: number; https?: boolean } => { if (!url) return {}; const parsed = new URL(url); return { apiHostname: parsed.hostname, ...(parsed.port ? { port: Number(parsed.port) } : {}), https: parsed.protocol === "https:", };}; interface WorkOSVaultUseOptions { readonly expectedErrorStatuses?: readonly number[]; readonly expectedErrorOutcome?: string;} export interface WorkOSVaultClient { readonly use: <A>( operation: string, fn: (client: WorkOSVaultPromiseApi) => Promise<A>, options?: WorkOSVaultUseOptions, ) => Effect.Effect<A, WorkOSVaultClientError, never>; readonly createObject: (options: { readonly name: string; readonly value: string; readonly context: Record<string, string>; }) => Effect.Effect<WorkOSVaultObjectMetadata, WorkOSVaultClientError, never>; readonly readObjectByName: ( name: string, ) => Effect.Effect<WorkOSVaultObject, WorkOSVaultClientError, never>; readonly updateObject: (options: { readonly id: string; readonly value: string; readonly versionCheck?: string; }) => Effect.Effect<WorkOSVaultObject, WorkOSVaultClientError, never>; readonly deleteObject: (options: { readonly id: string; }) => Effect.Effect<void, WorkOSVaultClientError, never>;} const isExpectedVaultError = ( error: WorkOSVaultClientError, options: WorkOSVaultUseOptions | undefined,): boolean => { if (error.status === undefined) return false; return options?.expectedErrorStatuses?.includes(error.status) ?? false;}; export const makeWorkOSVaultClient = (workos: Pick<WorkOS, "vault">): WorkOSVaultClient => { const client: WorkOSVaultPromiseApi = workos.vault; const use = <A>( operation: string, fn: (vault: WorkOSVaultPromiseApi) => Promise<A>, options?: WorkOSVaultUseOptions, ): Effect.Effect<A, WorkOSVaultClientError, never> => { const attempt = Effect.tryPromise({ try: () => fn(client), catch: (cause) => new WorkOSVaultClientError({ cause, operation }), }); const observed = attempt.pipe( Effect.result, Effect.flatMap((outcome) => Effect.gen(function* () { if (Result.isSuccess(outcome)) { yield* Effect.annotateCurrentSpan({ "workos_vault.outcome": "ok" }); return outcome; } const status = outcome.failure.status; if (isExpectedVaultError(outcome.failure, options)) { yield* Effect.annotateCurrentSpan({ "workos_vault.outcome": options?.expectedErrorOutcome ?? "expected_error", "workos_vault.status": status ?? "unknown", }); return outcome; } yield* Effect.annotateCurrentSpan({ "workos_vault.outcome": "error", "workos_vault.status": status ?? "unknown", }); return yield* Effect.fail(outcome.failure); }), ), Effect.withSpan(`workos_vault.${operation}`), ); return observed.pipe( Effect.flatMap((outcome) => Result.isSuccess(outcome) ? Effect.succeed(outcome.success) : Effect.fail(outcome.failure), ), ); }; return { use, createObject: (options) => use("create_object", (vault) => vault.createObject(options)), readObjectByName: (name) => use("read_object_by_name", (vault) => vault.readObjectByName(name), { expectedErrorOutcome: "expected_missing_object", expectedErrorStatuses: [400, 404], }), updateObject: (options) => use("update_object", (vault) => vault.updateObject(options)), deleteObject: (options) => use("delete_object", (vault) => vault.deleteObject(options)), };}; export const makeConfiguredWorkOSVaultClient = ( credentials: WorkOSVaultCredentials,): Effect.Effect<WorkOSVaultClient, WorkOSVaultClientInstantiationError, never> => Effect.try({ try: () => makeWorkOSVaultClient( new WorkOSClient({ apiKey: credentials.apiKey, clientId: credentials.clientId, ...apiUrlOptions(credentials.apiUrl), }), ), catch: (cause) => new WorkOSVaultClientInstantiationError({ cause }), }).pipe(Effect.withSpan("workos_vault.make_client"));
import type { WorkOS } from "@workos-inc/node/worker";
import {
GenericServerException,
NotFoundException,
WorkOS as WorkOSClient,
} from "@workos-inc/node/worker";
import { Data, Effect, Option, Result, Schema } from "effect";
export interface WorkOSVaultObjectMetadata {
readonly context: Record<string, unknown>;
readonly id: string;
readonly updatedAt: Date;
readonly versionId: string;
}
export interface WorkOSVaultObject {
readonly id: string;
readonly metadata: WorkOSVaultObjectMetadata;
readonly name: string;
readonly value?: string;
}
const WORKOS_KEK_NOT_READY_MESSAGE =
"KEK was created but is not yet ready. This request can be retried.";
const CauseWithStatusSchema = Schema.Struct({
status: Schema.Number,
});
const decodeCauseWithStatusOption = Schema.decodeUnknownOption(CauseWithStatusSchema);
const statusFromWorkOSCause = (cause: unknown): number | undefined => {
if (cause instanceof GenericServerException || cause instanceof NotFoundException) {
return cause.status;
}
return Option.match(decodeCauseWithStatusOption(cause), {
onNone: () => undefined,
onSome: (decoded) => decoded.status,
});
};
const isKekNotReadyWorkOSCause = (cause: unknown): boolean =>
cause instanceof GenericServerException &&
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: WorkOS only exposes this retryable Vault condition through its SDK exception message
cause.message.endsWith(WORKOS_KEK_NOT_READY_MESSAGE);
export class WorkOSVaultClientError extends Data.TaggedError("WorkOSVaultClientError")<{
readonly cause: unknown;
readonly message: string;
readonly operation: string;
readonly retryKind?: "kek_not_ready";
readonly status?: number;
}> {
constructor(options: {
readonly cause: unknown;
readonly message?: string;
readonly operation: string;
readonly retryKind?: "kek_not_ready";
readonly status?: number;
}) {
super({
cause: options.cause,
message: options.message ?? `WorkOS Vault ${options.operation} failed`,
operation: options.operation,
retryKind:
options.retryKind ??
(isKekNotReadyWorkOSCause(options.cause) ? "kek_not_ready" : undefined),
status: options.status ?? statusFromWorkOSCause(options.cause),
});
}
}
export class WorkOSVaultClientInstantiationError extends Data.TaggedError(
"WorkOSVaultClientInstantiationError",
)<{
readonly cause: unknown;
}> {}
// Promise-shaped facade onto the underlying WorkOS SDK. Module-private — the
// public surface in `WorkOSVaultClient` is Effect-only. Test doubles import
// this type to stand up an in-memory equivalent.
export interface WorkOSVaultPromiseApi {
readonly createObject: (options: {
readonly name: string;
readonly value: string;
readonly context: Record<string, string>;
}) => Promise<WorkOSVaultObjectMetadata>;
readonly readObjectByName: (name: string) => Promise<WorkOSVaultObject>;
readonly updateObject: (options: {
readonly id: string;
readonly value: string;
readonly versionCheck?: string;
}) => Promise<WorkOSVaultObject>;
readonly deleteObject: (options: { readonly id: string }) => Promise<void>;
}
export interface WorkOSVaultCredentials {
readonly apiKey: string;
readonly clientId: string;
/** Optional WorkOS API base-URL override (e.g. a WorkOS emulator in tests). */
readonly apiUrl?: string;
}
const apiUrlOptions = (
url: string | undefined,
): { apiHostname?: string; port?: number; https?: boolean } => {
if (!url) return {};
const parsed = new URL(url);
return {
apiHostname: parsed.hostname,
...(parsed.port ? { port: Number(parsed.port) } : {}),
https: parsed.protocol === "https:",
};
};
interface WorkOSVaultUseOptions {
readonly expectedErrorStatuses?: readonly number[];
readonly expectedErrorOutcome?: string;
}
export interface WorkOSVaultClient {
readonly use: <A>(
operation: string,
fn: (client: WorkOSVaultPromiseApi) => Promise<A>,
options?: WorkOSVaultUseOptions,
) => Effect.Effect<A, WorkOSVaultClientError, never>;
readonly createObject: (options: {
readonly name: string;
readonly value: string;
readonly context: Record<string, string>;
}) => Effect.Effect<WorkOSVaultObjectMetadata, WorkOSVaultClientError, never>;
readonly readObjectByName: (
name: string,
) => Effect.Effect<WorkOSVaultObject, WorkOSVaultClientError, never>;
readonly updateObject: (options: {
readonly id: string;
readonly value: string;
readonly versionCheck?: string;
}) => Effect.Effect<WorkOSVaultObject, WorkOSVaultClientError, never>;
readonly deleteObject: (options: {
readonly id: string;
}) => Effect.Effect<void, WorkOSVaultClientError, never>;
}
const isExpectedVaultError = (
error: WorkOSVaultClientError,
options: WorkOSVaultUseOptions | undefined,
): boolean => {
if (error.status === undefined) return false;
return options?.expectedErrorStatuses?.includes(error.status) ?? false;
};
export const makeWorkOSVaultClient = (workos: Pick<WorkOS, "vault">): WorkOSVaultClient => {
const client: WorkOSVaultPromiseApi = workos.vault;
const use = <A>(
operation: string,
fn: (vault: WorkOSVaultPromiseApi) => Promise<A>,
options?: WorkOSVaultUseOptions,
): Effect.Effect<A, WorkOSVaultClientError, never> => {
const attempt = Effect.tryPromise({
try: () => fn(client),
catch: (cause) => new WorkOSVaultClientError({ cause, operation }),
});
const observed = attempt.pipe(
Effect.result,
Effect.flatMap((outcome) =>
Effect.gen(function* () {
if (Result.isSuccess(outcome)) {
yield* Effect.annotateCurrentSpan({ "workos_vault.outcome": "ok" });
return outcome;
}
const status = outcome.failure.status;
if (isExpectedVaultError(outcome.failure, options)) {
yield* Effect.annotateCurrentSpan({
"workos_vault.outcome": options?.expectedErrorOutcome ?? "expected_error",
"workos_vault.status": status ?? "unknown",
});
return outcome;
}
yield* Effect.annotateCurrentSpan({
"workos_vault.outcome": "error",
"workos_vault.status": status ?? "unknown",
});
return yield* Effect.fail(outcome.failure);
}),
),
Effect.withSpan(`workos_vault.${operation}`),
);
return observed.pipe(
Effect.flatMap((outcome) =>
Result.isSuccess(outcome) ? Effect.succeed(outcome.success) : Effect.fail(outcome.failure),
),
);
};
return {
use,
createObject: (options) => use("create_object", (vault) => vault.createObject(options)),
readObjectByName: (name) =>
use("read_object_by_name", (vault) => vault.readObjectByName(name), {
expectedErrorOutcome: "expected_missing_object",
expectedErrorStatuses: [400, 404],
}),
updateObject: (options) => use("update_object", (vault) => vault.updateObject(options)),
deleteObject: (options) => use("delete_object", (vault) => vault.deleteObject(options)),
};
};
export const makeConfiguredWorkOSVaultClient = (
credentials: WorkOSVaultCredentials,
): Effect.Effect<WorkOSVaultClient, WorkOSVaultClientInstantiationError, never> =>
Effect.try({
try: () =>
makeWorkOSVaultClient(
new WorkOSClient({
apiKey: credentials.apiKey,
clientId: credentials.clientId,
...apiUrlOptions(credentials.apiUrl),
}),
),
catch: (cause) => new WorkOSVaultClientInstantiationError({ cause }),
}).pipe(Effect.withSpan("workos_vault.make_client"));