@aperture-browser/api-client 0.0.0-init.0 → 0.0.0-nightly.101.c63f90ec6164

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/authorization/service.ts","../src/auth/schemas.ts","../src/auth/service.ts","../src/auth/layer.ts","../src/errors.ts","../src/authorization/layer.ts","../src/query.ts","../src/events/service.ts","../src/events/layer.ts","../src/sessions/schemas.ts","../src/sessions/service.ts","../src/sessions/layer.ts","../src/snapshots/service.ts","../src/snapshots/layer.ts","../src/tenants/service.ts","../src/tenants/layer.ts","../src/tokens/service.ts","../src/tokens/layer.ts","../src/users/service.ts","../src/users/layer.ts","../src/layer.ts","../src/pagination.ts","../src/schemas.ts"],"sourcesContent":["import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type * as Schema from \"effect/Schema\";\nimport type * as Stream from \"effect/Stream\";\nimport type * as HttpClientError from \"effect/unstable/http/HttpClientError\";\nimport type { ApiRequestError } from \"../errors.ts\";\n\nexport const TENANT_HEADER = \"X-Aperture-Tenant-Id\";\n\ninterface CredentialContext {\n authorityType: \"system_admin\" | \"tenant\" | null;\n tenantId: string | null;\n selectedTenantId: string | null;\n}\n\nexport type ApiCredentials =\n | (CredentialContext & {\n kind: \"bearer\";\n token: string;\n })\n | (CredentialContext & {\n kind: \"session\";\n });\n\n/** The browser's own login session, sent as a cookie. */\nexport const webSessionCredentials: ApiCredentials = {\n kind: \"session\",\n authorityType: null,\n tenantId: null,\n selectedTenantId: null,\n};\n\nexport type TenantHeaderMode = \"none\" | \"optional\" | \"tenant-scoped\";\n\n/** Which tenant, if any, a request acts for under the given credentials. */\nexport function resolveTenantHeader(\n credentials: ApiCredentials,\n mode: TenantHeaderMode,\n): string | undefined {\n if (mode === \"none\") {\n return undefined;\n }\n\n if (mode === \"optional\") {\n return credentials.selectedTenantId ?? undefined;\n }\n\n if (credentials.authorityType === \"tenant\") {\n if (credentials.kind === \"bearer\") {\n return undefined;\n }\n return credentials.tenantId ?? undefined;\n }\n\n if (credentials.authorityType === \"system_admin\") {\n return credentials.selectedTenantId ?? undefined;\n }\n\n return undefined;\n}\n\n/** How a request authenticates, and which tenant it acts for. */\nexport interface Authorization {\n readonly credentials?: ApiCredentials;\n readonly bearerToken?: string;\n readonly tenantHeader?: TenantHeaderMode;\n}\n\nexport const Authorization = {\n anonymous: {} as Authorization,\n webSession: { credentials: webSessionCredentials } as Authorization,\n of: (credentials: ApiCredentials): Authorization => ({ credentials }),\n tenantScoped: (credentials: ApiCredentials): Authorization => ({\n credentials,\n tenantHeader: \"tenant-scoped\",\n }),\n};\n\n/**\n * Authenticates API calls. Inside `authorize`, every request sent through the HttpClient\n * that `authorizedHttpClientLayer` provides carries that call's credentials and tenant, so\n * callers never touch headers.\n */\nexport class ApiAuthorization extends Context.Service<\n ApiAuthorization,\n {\n /** Runs a call with the given authorization and maps its failures to ApiRequestError. */\n readonly authorize: (\n authorization: Authorization,\n ) => <A, R>(\n self: Effect.Effect<A, HttpClientError.HttpClientError | Schema.SchemaError, R>,\n ) => Effect.Effect<A, ApiRequestError, R>;\n /** Emits whenever the web session is found to be missing, expired or revoked. */\n readonly sessionAuthenticationFailures: Stream.Stream<void>;\n }\n>()(\"@aperture-browser/api-client/ApiAuthorization\") {}\n","import * as Schema from \"effect/Schema\";\n\n// The browser login flows are not part of api/openapi.yaml.\n\nconst passkeyAuthenticatorTransport = Schema.Literals([\n \"ble\",\n \"cable\",\n \"hybrid\",\n \"internal\",\n \"nfc\",\n \"smart-card\",\n \"usb\",\n]);\n\nconst passkeyCredentialDescriptor = Schema.Struct({\n id: Schema.String,\n type: Schema.Literal(\"public-key\"),\n transports: Schema.optionalKey(Schema.mutable(Schema.Array(passkeyAuthenticatorTransport))),\n});\n\nconst passkeyExtensions = Schema.optionalKey(\n Schema.Struct({\n appid: Schema.optionalKey(Schema.String),\n credProps: Schema.optionalKey(Schema.Boolean),\n hmacCreateSecret: Schema.optionalKey(Schema.Boolean),\n minPinLength: Schema.optionalKey(Schema.Boolean),\n }),\n);\n\nconst passkeyHint = Schema.Literals([\"hybrid\", \"security-key\", \"client-device\"]);\nconst passkeyUserVerification = Schema.Literals([\"discouraged\", \"preferred\", \"required\"]);\n\nexport const LoginMethods = Schema.Struct({\n methods: Schema.Array(\n Schema.Union([\n Schema.Struct({ type: Schema.Literal(\"password\") }),\n Schema.Struct({ type: Schema.Literal(\"api_token\") }),\n Schema.Struct({ type: Schema.Literal(\"passkey\") }),\n Schema.Struct({\n type: Schema.Literal(\"oidc\"),\n id: Schema.String,\n name: Schema.String,\n loginUrl: Schema.String,\n }),\n ]),\n ),\n});\n\nexport const PasskeyLoginOptions = Schema.Struct({\n publicKey: Schema.Struct({\n challenge: Schema.String,\n timeout: Schema.optionalKey(Schema.Number),\n rpId: Schema.optionalKey(Schema.String),\n allowCredentials: Schema.optionalKey(Schema.mutable(Schema.Array(passkeyCredentialDescriptor))),\n userVerification: Schema.optionalKey(passkeyUserVerification),\n hints: Schema.optionalKey(Schema.mutable(Schema.Array(passkeyHint))),\n extensions: passkeyExtensions,\n }),\n});\n\nexport const PasskeyRegistrationOptions = Schema.Struct({\n publicKey: Schema.Struct({\n rp: Schema.Struct({\n id: Schema.optionalKey(Schema.String),\n name: Schema.String,\n }),\n user: Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n displayName: Schema.String,\n }),\n challenge: Schema.String,\n pubKeyCredParams: Schema.mutable(\n Schema.Array(\n Schema.Struct({\n alg: Schema.Literals([-7, -8, -35, -36, -37, -38, -39, -257, -258, -259]),\n type: Schema.Literal(\"public-key\"),\n }),\n ),\n ),\n timeout: Schema.optionalKey(Schema.Number),\n excludeCredentials: Schema.optionalKey(\n Schema.mutable(Schema.Array(passkeyCredentialDescriptor)),\n ),\n authenticatorSelection: Schema.optionalKey(\n Schema.Struct({\n authenticatorAttachment: Schema.optionalKey(\n Schema.Literals([\"platform\", \"cross-platform\"]),\n ),\n requireResidentKey: Schema.optionalKey(Schema.Boolean),\n residentKey: Schema.optionalKey(Schema.Literals([\"discouraged\", \"preferred\", \"required\"])),\n userVerification: Schema.optionalKey(passkeyUserVerification),\n }),\n ),\n hints: Schema.optionalKey(Schema.mutable(Schema.Array(passkeyHint))),\n attestation: Schema.optionalKey(Schema.Literals([\"direct\", \"enterprise\", \"indirect\", \"none\"])),\n attestationFormats: Schema.optionalKey(\n Schema.mutable(\n Schema.Array(\n Schema.Literals([\n \"fido-u2f\",\n \"packed\",\n \"android-safetynet\",\n \"android-key\",\n \"tpm\",\n \"apple\",\n \"none\",\n ]),\n ),\n ),\n ),\n extensions: passkeyExtensions,\n }),\n});\n\nexport const Passkey = Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n createdAt: Schema.String,\n lastUsedAt: Schema.NullOr(Schema.String),\n});\n\nexport const Passkeys = Schema.Struct({\n passkeys: Schema.Array(Passkey),\n});\n\nexport const PasskeyMutation = Schema.Struct({\n passkey: Passkey,\n});\n\nexport const PasswordLoginResponse = Schema.Struct({\n mfaRequired: Schema.Boolean,\n});\n\nexport const SecurityStatus = Schema.Struct({\n hasPassword: Schema.Boolean,\n totpEnabled: Schema.Boolean,\n recoveryCodesRemaining: Schema.Number.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0)),\n});\n\nexport const TOTPEnrollment = Schema.Struct({\n secret: Schema.String,\n otpauthUrl: Schema.String,\n qrCodeDataUrl: Schema.String,\n});\n\nexport const RecoveryCodes = Schema.Struct({\n recoveryCodes: Schema.Array(Schema.String),\n});\n\nexport type LoginMethods = typeof LoginMethods.Type;\nexport type PasskeyLoginOptions = typeof PasskeyLoginOptions.Type;\nexport type PasskeyRegistrationOptions = typeof PasskeyRegistrationOptions.Type;\nexport type Passkey = typeof Passkey.Type;\nexport type Passkeys = typeof Passkeys.Type;\nexport type PasskeyMutation = typeof PasskeyMutation.Type;\nexport type PasswordLoginResponse = typeof PasswordLoginResponse.Type;\nexport type RecoveryCodes = typeof RecoveryCodes.Type;\nexport type SecurityStatus = typeof SecurityStatus.Type;\nexport type TOTPEnrollment = typeof TOTPEnrollment.Type;\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { AuthenticationResponseJSON, RegistrationResponseJSON } from \"@simplewebauthn/browser\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { AuthMeResponse } from \"../schemas.ts\";\nimport type * as S from \"./schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\n/** Browser login, account security, and the current principal. */\nexport class AuthApi extends Context.Service<\n AuthApi,\n {\n readonly listLoginMethods: () => Call<S.LoginMethods>;\n readonly loginWithPassword: (email: string, password: string) => Call<S.PasswordLoginResponse>;\n readonly completePasswordMFA: (code: string) => Call<void>;\n readonly loginWithAPIToken: (token: string) => Call<void>;\n readonly beginPasskeyLogin: () => Call<S.PasskeyLoginOptions>;\n readonly finishPasskeyLogin: (credential: AuthenticationResponseJSON) => Call<void>;\n readonly acceptUserInvitation: (token: string, password: string) => Call<void>;\n readonly logoutWebSession: () => Call<void>;\n\n readonly getAuthMe: (\n selectedTenantId?: string | null,\n credentials?: ApiCredentials,\n ) => Call<AuthMeResponse>;\n\n readonly getSecurityStatus: () => Call<S.SecurityStatus>;\n readonly setPassword: (currentPassword: string, newPassword: string) => Call<void>;\n readonly listPasskeys: () => Call<S.Passkeys>;\n readonly beginPasskeyRegistration: (name: string) => Call<S.PasskeyRegistrationOptions>;\n readonly finishPasskeyRegistration: (\n credential: RegistrationResponseJSON,\n ) => Call<S.PasskeyMutation>;\n readonly renamePasskey: (passkeyId: string, name: string) => Call<S.PasskeyMutation>;\n readonly deletePasskey: (passkeyId: string) => Call<void>;\n readonly beginTOTPEnrollment: () => Call<S.TOTPEnrollment>;\n readonly completeTOTPEnrollment: (code: string) => Call<S.RecoveryCodes>;\n readonly regenerateRecoveryCodes: (code: string) => Call<S.RecoveryCodes>;\n readonly disableTOTP: (code: string) => Call<void>;\n }\n>()(\"@aperture-browser/api-client/AuthApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpBody from \"effect/unstable/http/HttpBody\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as HttpClientResponse from \"effect/unstable/http/HttpClientResponse\";\nimport type { AuthenticationResponseJSON, RegistrationResponseJSON } from \"@simplewebauthn/browser\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport {\n ApiAuthorization,\n Authorization,\n webSessionCredentials,\n type ApiCredentials,\n} from \"../authorization/service.ts\";\nimport {\n LoginMethods,\n PasskeyLoginOptions,\n PasskeyMutation,\n PasskeyRegistrationOptions,\n Passkeys,\n PasswordLoginResponse,\n RecoveryCodes,\n SecurityStatus,\n TOTPEnrollment,\n} from \"./schemas.ts\";\nimport { AuthApi } from \"./service.ts\";\n\nconst jsonBody = (body: unknown) => ({ body: HttpBody.jsonUnsafe(body) });\n\nexport const makeAuthApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const http = HttpClient.filterStatusOk(httpClient);\n const api = Api.make(httpClient);\n const anonymous = authorize(Authorization.anonymous);\n const webSession = authorize(Authorization.webSession);\n\n const listLoginMethods = Effect.fn(\"AuthApi.listLoginMethods\")(function* () {\n return yield* http\n .get(\"/auth/login-methods\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(LoginMethods)), anonymous);\n });\n\n const loginWithPassword = Effect.fn(\"AuthApi.loginWithPassword\")(function* (\n email: string,\n password: string,\n ) {\n return yield* http\n .post(\"/auth/password/login\", jsonBody({ email, password }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(PasswordLoginResponse)), anonymous);\n });\n\n const completePasswordMFA = Effect.fn(\"AuthApi.completePasswordMFA\")(function* (code: string) {\n yield* http.post(\"/auth/password/login/mfa\", jsonBody({ code })).pipe(anonymous);\n });\n\n const loginWithAPIToken = Effect.fn(\"AuthApi.loginWithAPIToken\")(function* (token: string) {\n yield* http.post(\"/auth/token/login\", jsonBody({ token })).pipe(anonymous);\n });\n\n const beginPasskeyLogin = Effect.fn(\"AuthApi.beginPasskeyLogin\")(function* () {\n return yield* http\n .post(\"/auth/passkeys/login/options\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(PasskeyLoginOptions)), anonymous);\n });\n\n const finishPasskeyLogin = Effect.fn(\"AuthApi.finishPasskeyLogin\")(function* (\n credential: AuthenticationResponseJSON,\n ) {\n yield* http.post(\"/auth/passkeys/login/finish\", jsonBody(credential)).pipe(anonymous);\n });\n\n const acceptUserInvitation = Effect.fn(\"AuthApi.acceptUserInvitation\")(function* (\n token: string,\n password: string,\n ) {\n yield* http.post(\"/auth/invitations/accept\", jsonBody({ token, password })).pipe(anonymous);\n });\n\n const logoutWebSession = Effect.fn(\"AuthApi.logoutWebSession\")(function* () {\n yield* http.post(\"/auth/logout\").pipe(webSession);\n });\n\n const getAuthMe = Effect.fn(\"AuthApi.getAuthMe\")(function* (\n selectedTenantId: string | null = null,\n credentials: ApiCredentials = webSessionCredentials,\n ) {\n return yield* api.getCurrentPrincipal(undefined).pipe(\n authorize({\n credentials: { ...credentials, selectedTenantId },\n tenantHeader: \"optional\",\n }),\n );\n });\n\n const getSecurityStatus = Effect.fn(\"AuthApi.getSecurityStatus\")(function* () {\n return yield* http\n .get(\"/auth/security\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(SecurityStatus)), webSession);\n });\n\n const setPassword = Effect.fn(\"AuthApi.setPassword\")(function* (\n currentPassword: string,\n newPassword: string,\n ) {\n yield* http.put(\"/auth/password\", jsonBody({ currentPassword, newPassword })).pipe(webSession);\n });\n\n const listPasskeys = Effect.fn(\"AuthApi.listPasskeys\")(function* () {\n return yield* http\n .get(\"/auth/passkeys\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(Passkeys)), webSession);\n });\n\n const beginPasskeyRegistration = Effect.fn(\"AuthApi.beginPasskeyRegistration\")(function* (\n name: string,\n ) {\n return yield* http\n .post(\"/auth/passkeys/registration/options\", jsonBody({ name }))\n .pipe(\n Effect.flatMap(HttpClientResponse.schemaBodyJson(PasskeyRegistrationOptions)),\n webSession,\n );\n });\n\n const finishPasskeyRegistration = Effect.fn(\"AuthApi.finishPasskeyRegistration\")(function* (\n credential: RegistrationResponseJSON,\n ) {\n return yield* http\n .post(\"/auth/passkeys/registration/finish\", jsonBody(credential))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(PasskeyMutation)), webSession);\n });\n\n const renamePasskey = Effect.fn(\"AuthApi.renamePasskey\")(function* (\n passkeyId: string,\n name: string,\n ) {\n return yield* http\n .patch(`/auth/passkeys/${encodeURIComponent(passkeyId)}`, jsonBody({ name }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(PasskeyMutation)), webSession);\n });\n\n const deletePasskey = Effect.fn(\"AuthApi.deletePasskey\")(function* (passkeyId: string) {\n yield* http.del(`/auth/passkeys/${encodeURIComponent(passkeyId)}`).pipe(webSession);\n });\n\n const beginTOTPEnrollment = Effect.fn(\"AuthApi.beginTOTPEnrollment\")(function* () {\n return yield* http\n .post(\"/auth/totp/enrollment/options\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(TOTPEnrollment)), webSession);\n });\n\n const completeTOTPEnrollment = Effect.fn(\"AuthApi.completeTOTPEnrollment\")(function* (\n code: string,\n ) {\n return yield* http\n .post(\"/auth/totp/enrollment/finish\", jsonBody({ code }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(RecoveryCodes)), webSession);\n });\n\n const regenerateRecoveryCodes = Effect.fn(\"AuthApi.regenerateRecoveryCodes\")(function* (\n code: string,\n ) {\n return yield* http\n .post(\"/auth/totp/recovery-codes\", jsonBody({ code }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(RecoveryCodes)), webSession);\n });\n\n const disableTOTP = Effect.fn(\"AuthApi.disableTOTP\")(function* (code: string) {\n yield* http.post(\"/auth/totp/disable\", jsonBody({ code })).pipe(webSession);\n });\n\n return AuthApi.of({\n listLoginMethods,\n loginWithPassword,\n completePasswordMFA,\n loginWithAPIToken,\n beginPasskeyLogin,\n finishPasskeyLogin,\n acceptUserInvitation,\n logoutWebSession,\n getAuthMe,\n getSecurityStatus,\n setPassword,\n listPasskeys,\n beginPasskeyRegistration,\n finishPasskeyRegistration,\n renamePasskey,\n deletePasskey,\n beginTOTPEnrollment,\n completeTOTPEnrollment,\n regenerateRecoveryCodes,\n disableTOTP,\n });\n});\n\nexport const authApiLayer = Layer.effect(AuthApi, makeAuthApi);\n","import * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport * as HttpClientResponse from \"effect/unstable/http/HttpClientResponse\";\nimport type * as HttpClientError from \"effect/unstable/http/HttpClientError\";\n\nexport const ApiErrorBody = Schema.Struct({\n error: Schema.Struct({\n code: Schema.String,\n message: Schema.String,\n }),\n});\n\nexport type ApiErrorBody = typeof ApiErrorBody.Type;\n\n/**\n * A failed API request. `code` and `message` come from the server's error body when it\n * sent one; `status` is 0 when no HTTP status applies.\n */\nexport class ApiRequestError extends Schema.TaggedError<ApiRequestError>()(\"ApiRequestError\", {\n code: Schema.String,\n message: Schema.String,\n status: Schema.Number,\n}) {}\n\nconst invalidResponse = (status: number) =>\n new ApiRequestError({ code: \"internal_error\", message: \"Invalid response\", status });\n\nconst networkError = new ApiRequestError({\n code: \"network_error\",\n message: \"The server could not be reached\",\n status: 0,\n});\n\n/**\n * Maps HTTP and decoding failures to ApiRequestError. Error responses keep the code and\n * message of the server's error body.\n */\nexport const toApiRequestError = <A, R>(\n self: Effect.Effect<A, HttpClientError.HttpClientError | Schema.SchemaError, R>,\n): Effect.Effect<A, ApiRequestError, R> =>\n self.pipe(\n Effect.catchReasons(\"HttpClientError\", {\n StatusCodeError: ({ response }) =>\n HttpClientResponse.schemaBodyJson(ApiErrorBody)(response).pipe(\n Effect.map(({ error }) => new ApiRequestError({ ...error, status: response.status })),\n Effect.orElseSucceed(\n () =>\n new ApiRequestError({\n code: \"internal_error\",\n message: \"Request failed\",\n status: response.status,\n }),\n ),\n Effect.flatMap(Effect.fail),\n ),\n DecodeError: ({ response }) => Effect.fail(invalidResponse(response.status)),\n }),\n Effect.catchTags({\n HttpClientError: () => Effect.fail(networkError),\n SchemaError: () => Effect.fail(invalidResponse(0)),\n }),\n );\n","import * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as PubSub from \"effect/PubSub\";\nimport * as Stream from \"effect/Stream\";\nimport type * as Schema from \"effect/Schema\";\nimport * as Function from \"effect/Function\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\";\nimport type * as HttpClientError from \"effect/unstable/http/HttpClientError\";\nimport { toApiRequestError } from \"../errors.ts\";\nimport {\n ApiAuthorization,\n resolveTenantHeader,\n TENANT_HEADER,\n type Authorization,\n} from \"./service.ts\";\n\n/** The authorization of the call a request belongs to; set by `authorize`. */\nconst CurrentAuthorization = Context.Reference<Authorization>(\n \"@aperture-browser/api-client/CurrentAuthorization\",\n { defaultValue: () => ({}) },\n);\n\nconst authorizeRequest = (request: HttpClientRequest.HttpClientRequest) =>\n CurrentAuthorization.useSync(({ credentials, bearerToken, tenantHeader = \"none\" }) => {\n const token =\n bearerToken ?? (credentials?.kind === \"bearer\" ? credentials.token.trim() : undefined);\n const tenantId = credentials ? resolveTenantHeader(credentials, tenantHeader) : undefined;\n return request.pipe(\n HttpClientRequest.acceptJson,\n token ? HttpClientRequest.bearerToken(token) : Function.identity,\n tenantId\n ? HttpClientRequest.setHeader(TENANT_HEADER, tenantId)\n : HttpClientRequest.removeHeader(TENANT_HEADER),\n );\n });\n\nconst sessionAuthenticationFailureCodes = new Set([\n \"authentication_required\",\n \"invalid_authentication_token\",\n \"authentication_token_expired\",\n \"authentication_token_revoked\",\n \"user_disabled\",\n]);\n\n/**\n * Decorates the HttpClient so each request carries the authorization of the `authorize`\n * call it runs in.\n */\nexport const authorizedHttpClientLayer = Layer.effect(\n HttpClient.HttpClient,\n Effect.map(HttpClient.HttpClient, HttpClient.mapRequestEffect(authorizeRequest)),\n);\n\nexport const makeApiAuthorization = Effect.gen(function* () {\n const failures = yield* PubSub.unbounded<void>();\n\n const authorize =\n (authorization: Authorization) =>\n <A, R>(self: Effect.Effect<A, HttpClientError.HttpClientError | Schema.SchemaError, R>) =>\n self.pipe(\n toApiRequestError,\n Effect.tapError((error) =>\n authorization.credentials?.kind === \"session\" &&\n sessionAuthenticationFailureCodes.has(error.code)\n ? PubSub.publish(failures, undefined)\n : Effect.void,\n ),\n Effect.provideService(CurrentAuthorization, authorization),\n );\n\n return ApiAuthorization.of({\n authorize,\n sessionAuthenticationFailures: Stream.fromPubSub(failures),\n });\n});\n\nexport const apiAuthorizationLayer = Layer.effect(ApiAuthorization, makeApiAuthorization);\n","export type TagFilterValue = Array<{\n key: string;\n operator: \"eq\" | \"neq\" | \"in\" | \"not_in\";\n values: string[];\n}>;\n\n/** Encodes tag filters as the parallel tagKey, tagOperator and tagValue query lists. */\nexport const tagQuery = (tags: TagFilterValue | undefined) => ({\n tagKey: tags?.map((tag) => tag.key),\n tagOperator: tags?.map((tag) => tag.operator),\n tagValue: tags?.map((tag) => tag.values.join(\",\")),\n});\n\n/** Drops empty strings and empty list items, which mean \"no filter\". */\nexport const compactQuery = <T extends object>(query: T): T =>\n Object.fromEntries(\n Object.entries(query).flatMap(([key, value]) => {\n if (value === undefined || value === null || value === \"\") return [];\n if (!Array.isArray(value)) return [[key, value]];\n const items = value.filter((item) => item !== \"\");\n return items.length > 0 ? [[key, items]] : [];\n }),\n ) as T;\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { EventsPage } from \"../schemas.ts\";\n\nexport interface EventsListParams {\n limit?: number;\n cursor?: string;\n resourceType?: string;\n resourceId?: string;\n}\n\n/** The tenant's resource event log. */\nexport class EventsApi extends Context.Service<\n EventsApi,\n {\n readonly listEvents: (\n credentials: ApiCredentials,\n params?: EventsListParams,\n ) => Effect.Effect<EventsPage, ApiRequestError>;\n }\n>()(\"@aperture-browser/api-client/EventsApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { compactQuery } from \"../query.ts\";\nimport { EventsApi, type EventsListParams } from \"./service.ts\";\n\nexport const makeEventsApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const listEvents = Effect.fn(\"EventsApi.listEvents\")(function* (\n credentials: ApiCredentials,\n params: EventsListParams = {},\n ) {\n return yield* api\n .listEvents({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n resourceType: params.resourceType,\n resourceId: params.resourceId,\n }),\n })\n .pipe(authorize(Authorization.tenantScoped(credentials)));\n });\n\n return EventsApi.of({ listEvents });\n});\n\nexport const eventsApiLayer = Layer.effect(EventsApi, makeEventsApi);\n","import * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport * as Api from \"@aperture-browser/api-schema\";\n\n// The live session endpoints are not part of api/openapi.yaml.\n\nconst positiveInt = Schema.Number.check(Schema.isInt(), Schema.isGreaterThan(0));\nconst emptyArray = Effect.succeed([]);\n\nexport const BrowserStatus = Schema.Struct({\n sessionId: Schema.String,\n cdpUrl: Schema.String,\n media: Api.SessionMedia,\n targets: Schema.Array(\n Schema.Struct({\n targetId: Schema.String,\n generation: positiveInt,\n state: Schema.Literals([\"pending\", \"ready\", \"unavailable\", \"closed\"]),\n title: Schema.String,\n url: Schema.String,\n viewport: Schema.Struct({\n width: positiveInt,\n height: positiveInt,\n deviceScaleFactor: Schema.Number.check(Schema.isGreaterThan(0)),\n contentWidth: positiveInt,\n contentHeight: positiveInt,\n canvasWidth: positiveInt,\n canvasHeight: positiveInt,\n }),\n }),\n ).pipe(Schema.withDecodingDefaultKey(emptyArray)),\n});\n\n/** A recording as the live session reports it. */\nexport const Recording = Schema.Struct({\n recordingId: Schema.String,\n mode: Schema.Literals([\"tab\", \"viewer\"]),\n targetId: Schema.String,\n captureGeneration: positiveInt,\n status: Schema.Literals([\"starting\", \"running\", \"stopped\", \"failed\"]),\n stopReason: Schema.optionalKey(Schema.String),\n path: Schema.String,\n startedAt: Schema.String,\n stoppedAt: Schema.optionalKey(Schema.String),\n sizeBytes: Schema.optionalKey(\n Schema.Number.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0)),\n ),\n fps: positiveInt,\n bitrateKbps: positiveInt,\n codec: Schema.String,\n});\n\nexport type BrowserStatus = typeof BrowserStatus.Type;\nexport type Recording = typeof Recording.Type;\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type * as Api from \"@aperture-browser/api-schema\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { TagFilterValue } from \"../query.ts\";\nimport type {\n BrowserChannelsResponse,\n CreateSessionResponse,\n PromoteSessionResponse,\n Session,\n SessionMutationResponse,\n SessionsBulkResponse,\n SessionsPage,\n} from \"../schemas.ts\";\nimport type { BrowserStatus } from \"./schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface SessionsListParams {\n limit?: number;\n cursor?: string;\n includeDeleted?: boolean;\n status?: Api.SessionStatus;\n tags?: TagFilterValue;\n}\n\nexport type InitialBrowserTarget = Api.InitialBrowserTarget;\nexport type InitialBrowserStorageState = Api.InitialBrowserStorageState;\n\nexport interface CreateSessionInput {\n baseSnapshotName?: string | null;\n label?: string | null;\n browser: {\n channel: string;\n args?: string[];\n };\n initialTargets?: readonly InitialBrowserTarget[];\n storageState?: InitialBrowserStorageState;\n tags?: Record<string, string>;\n}\n\nexport interface CreateSessionOptions {\n waitForReady?: boolean;\n}\n\nexport interface PromoteSessionInput {\n name: string;\n description?: string | null;\n force?: boolean;\n tags?: Record<string, string>;\n}\n\nexport interface DownloadedFile {\n blob: Blob;\n filename: string | null;\n}\n\n/** Browser sessions, their live browser, and their recordings. */\nexport class SessionsApi extends Context.Service<\n SessionsApi,\n {\n readonly listSessions: (\n credentials: ApiCredentials,\n params?: SessionsListParams,\n ) => Call<SessionsPage>;\n readonly getSession: (credentials: ApiCredentials, sessionId: string) => Call<Session>;\n readonly getSessionsBulk: (\n credentials: ApiCredentials,\n sessionIds: readonly string[],\n ) => Call<SessionsBulkResponse>;\n readonly createSession: (\n credentials: ApiCredentials,\n input: CreateSessionInput,\n options?: CreateSessionOptions,\n ) => Call<CreateSessionResponse>;\n readonly deleteSession: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<SessionMutationResponse>;\n readonly reopenSession: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<SessionMutationResponse>;\n readonly suspendSession: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<SessionMutationResponse>;\n readonly rotateSessionToken: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<SessionMutationResponse>;\n readonly rotateCollaborationCapability: (\n credentials: ApiCredentials,\n sessionId: string,\n role: \"editor\" | \"viewer\",\n ) => Call<SessionMutationResponse>;\n readonly replaceSessionTags: (\n credentials: ApiCredentials,\n sessionId: string,\n tags: Record<string, string>,\n ) => Call<SessionMutationResponse>;\n readonly promoteSession: (\n credentials: ApiCredentials,\n sessionId: string,\n input: PromoteSessionInput,\n ) => Call<PromoteSessionResponse>;\n readonly getBrowserChannels: (credentials: ApiCredentials) => Call<BrowserChannelsResponse>;\n readonly getBrowserStatus: (\n credentials: ApiCredentials,\n sessionId: string,\n sessionToken?: string,\n ) => Call<BrowserStatus>;\n readonly downloadSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n sessionToken?: string,\n ) => Call<DownloadedFile>;\n }\n>()(\"@aperture-browser/api-client/SessionsApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as HttpClientResponse from \"effect/unstable/http/HttpClientResponse\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { compactQuery, tagQuery } from \"../query.ts\";\nimport { BrowserStatus } from \"./schemas.ts\";\nimport {\n SessionsApi,\n type CreateSessionInput,\n type CreateSessionOptions,\n type DownloadedFile,\n type PromoteSessionInput,\n type SessionsListParams,\n} from \"./service.ts\";\n\nconst contentDispositionFilename = (header: string | undefined): string | null =>\n header?.match(/filename=\"([^\"]+)\"/)?.[1] ?? null;\n\nexport const makeSessionsApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const http = HttpClient.filterStatusOk(httpClient);\n const api = Api.make(httpClient);\n const tenantScoped = (credentials: ApiCredentials) =>\n authorize(Authorization.tenantScoped(credentials));\n\n const listSessions = Effect.fn(\"SessionsApi.listSessions\")(function* (\n credentials: ApiCredentials,\n params: SessionsListParams = {},\n ) {\n return yield* api\n .listSessions({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n includeDeleted: params.includeDeleted || undefined,\n status: params.status,\n ...tagQuery(params.tags),\n }),\n })\n .pipe(tenantScoped(credentials));\n });\n\n const getSession = Effect.fn(\"SessionsApi.getSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.getSession(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const getSessionsBulk = Effect.fn(\"SessionsApi.getSessionsBulk\")(function* (\n credentials: ApiCredentials,\n sessionIds: readonly string[],\n ) {\n return yield* api\n .getSessionsBulk({ payload: { ids: sessionIds } })\n .pipe(tenantScoped(credentials));\n });\n\n const createSession = Effect.fn(\"SessionsApi.createSession\")(function* (\n credentials: ApiCredentials,\n input: CreateSessionInput,\n options: CreateSessionOptions = {},\n ) {\n return yield* api\n .createSession({\n params: compactQuery({ waitForReady: options.waitForReady }),\n payload: {\n baseSnapshotName: input.baseSnapshotName ?? null,\n label: input.label ?? null,\n browser: { channel: input.browser.channel, args: input.browser.args ?? [] },\n initialTargets: input.initialTargets ?? [],\n ...(input.storageState === undefined ? {} : { storageState: input.storageState }),\n tags: input.tags ?? {},\n },\n })\n .pipe(tenantScoped(credentials));\n });\n\n const deleteSession = Effect.fn(\"SessionsApi.deleteSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.deleteSession(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const reopenSession = Effect.fn(\"SessionsApi.reopenSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.reopenSession(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const suspendSession = Effect.fn(\"SessionsApi.suspendSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.suspendSession(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const rotateSessionToken = Effect.fn(\"SessionsApi.rotateSessionToken\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.rotateSessionToken(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const rotateCollaborationCapability = Effect.fn(\"SessionsApi.rotateCollaborationCapability\")(\n function* (credentials: ApiCredentials, sessionId: string, role: \"editor\" | \"viewer\") {\n return yield* api\n .rotateCollaborationCapability(sessionId, role, undefined)\n .pipe(tenantScoped(credentials));\n },\n );\n\n const replaceSessionTags = Effect.fn(\"SessionsApi.replaceSessionTags\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n tags: Record<string, string>,\n ) {\n return yield* api\n .replaceSessionTags(sessionId, { payload: { tags } })\n .pipe(tenantScoped(credentials));\n });\n\n const promoteSession = Effect.fn(\"SessionsApi.promoteSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n input: PromoteSessionInput,\n ) {\n return yield* api\n .promoteSession(sessionId, {\n payload: {\n name: input.name,\n description: input.description ?? null,\n force: input.force ?? false,\n tags: input.tags ?? {},\n },\n })\n .pipe(tenantScoped(credentials));\n });\n\n const getBrowserChannels = Effect.fn(\"SessionsApi.getBrowserChannels\")(function* (\n credentials: ApiCredentials,\n ) {\n return yield* api.listBrowserChannels(undefined).pipe(tenantScoped(credentials));\n });\n\n const getBrowserStatus = Effect.fn(\"SessionsApi.getBrowserStatus\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n sessionToken?: string,\n ) {\n return yield* http\n .get(`/sessions/${encodeURIComponent(sessionId)}/browser/status`)\n .pipe(\n Effect.flatMap(HttpClientResponse.schemaBodyJson(BrowserStatus)),\n authorize({ credentials, bearerToken: sessionToken }),\n );\n });\n\n const downloadSessionRecording = Effect.fn(\"SessionsApi.downloadSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n sessionToken?: string,\n ) {\n return yield* http\n .get(\n `/sessions/${encodeURIComponent(sessionId)}/recordings/${encodeURIComponent(recordingId)}/content`,\n )\n .pipe(\n Effect.flatMap((response) =>\n Effect.map(\n response.arrayBuffer,\n (body): DownloadedFile => ({\n blob: new Blob([body], { type: response.headers[\"content-type\"] ?? \"\" }),\n filename: contentDispositionFilename(response.headers[\"content-disposition\"]),\n }),\n ),\n ),\n authorize({ credentials, bearerToken: sessionToken, tenantHeader: \"tenant-scoped\" }),\n );\n });\n\n return SessionsApi.of({\n listSessions,\n getSession,\n getSessionsBulk,\n createSession,\n deleteSession,\n reopenSession,\n suspendSession,\n rotateSessionToken,\n rotateCollaborationCapability,\n replaceSessionTags,\n promoteSession,\n getBrowserChannels,\n getBrowserStatus,\n downloadSessionRecording,\n });\n});\n\nexport const sessionsApiLayer = Layer.effect(SessionsApi, makeSessionsApi);\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { TagFilterValue } from \"../query.ts\";\nimport type { SnapshotMutationResponse, SnapshotsPage } from \"../schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface SnapshotsListParams {\n limit?: number;\n cursor?: string;\n includeDeleted?: boolean;\n deleted?: \"active\" | \"deleted\" | \"all\";\n name?: string;\n tags?: TagFilterValue;\n}\n\nexport interface UpdateSnapshotInput {\n description: string | null;\n}\n\n/** Retained snapshots that new sessions start from. */\nexport class SnapshotsApi extends Context.Service<\n SnapshotsApi,\n {\n readonly listSnapshots: (\n credentials: ApiCredentials,\n params?: SnapshotsListParams,\n ) => Call<SnapshotsPage>;\n readonly updateSnapshot: (\n credentials: ApiCredentials,\n name: string,\n input: UpdateSnapshotInput,\n ) => Call<SnapshotMutationResponse>;\n readonly replaceSnapshotTags: (\n credentials: ApiCredentials,\n name: string,\n tags: Record<string, string>,\n ) => Call<SnapshotMutationResponse>;\n readonly deleteSnapshot: (\n credentials: ApiCredentials,\n name: string,\n ) => Call<SnapshotMutationResponse>;\n readonly restoreSnapshot: (\n credentials: ApiCredentials,\n name: string,\n ) => Call<SnapshotMutationResponse>;\n }\n>()(\"@aperture-browser/api-client/SnapshotsApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { compactQuery, tagQuery } from \"../query.ts\";\nimport { SnapshotsApi, type SnapshotsListParams, type UpdateSnapshotInput } from \"./service.ts\";\n\nexport const makeSnapshotsApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n const tenantScoped = (credentials: ApiCredentials) =>\n authorize(Authorization.tenantScoped(credentials));\n\n const listSnapshots = Effect.fn(\"SnapshotsApi.listSnapshots\")(function* (\n credentials: ApiCredentials,\n params: SnapshotsListParams = {},\n ) {\n return yield* api\n .listSnapshots({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n includeDeleted: params.includeDeleted || undefined,\n deleted: params.deleted,\n name: params.name,\n ...tagQuery(params.tags),\n }),\n })\n .pipe(tenantScoped(credentials));\n });\n\n const updateSnapshot = Effect.fn(\"SnapshotsApi.updateSnapshot\")(function* (\n credentials: ApiCredentials,\n name: string,\n input: UpdateSnapshotInput,\n ) {\n return yield* api.updateSnapshot(name, { payload: input }).pipe(tenantScoped(credentials));\n });\n\n const replaceSnapshotTags = Effect.fn(\"SnapshotsApi.replaceSnapshotTags\")(function* (\n credentials: ApiCredentials,\n name: string,\n tags: Record<string, string>,\n ) {\n return yield* api\n .replaceSnapshotTags(name, { payload: { tags } })\n .pipe(tenantScoped(credentials));\n });\n\n const deleteSnapshot = Effect.fn(\"SnapshotsApi.deleteSnapshot\")(function* (\n credentials: ApiCredentials,\n name: string,\n ) {\n return yield* api.deleteSnapshot(name, undefined).pipe(tenantScoped(credentials));\n });\n\n const restoreSnapshot = Effect.fn(\"SnapshotsApi.restoreSnapshot\")(function* (\n credentials: ApiCredentials,\n name: string,\n ) {\n return yield* api.restoreSnapshot(name, undefined).pipe(tenantScoped(credentials));\n });\n\n return SnapshotsApi.of({\n listSnapshots,\n updateSnapshot,\n replaceSnapshotTags,\n deleteSnapshot,\n restoreSnapshot,\n });\n});\n\nexport const snapshotsApiLayer = Layer.effect(SnapshotsApi, makeSnapshotsApi);\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type * as Api from \"@aperture-browser/api-schema\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { Tenant, TenantsPage } from \"../schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface TenantsListParams {\n limit?: number;\n cursor?: string;\n includeDeleted?: boolean;\n deleted?: \"active\" | \"deleted\" | \"all\";\n}\n\n/** Tenant administration. */\nexport class TenantsApi extends Context.Service<\n TenantsApi,\n {\n readonly listTenants: (\n credentials: ApiCredentials,\n params?: TenantsListParams,\n ) => Call<TenantsPage>;\n readonly createTenant: (credentials: ApiCredentials, input: Api.TenantInput) => Call<Tenant>;\n readonly updateTenant: (\n credentials: ApiCredentials,\n tenantId: string,\n input: Api.TenantInput,\n ) => Call<Tenant>;\n readonly deleteTenant: (credentials: ApiCredentials, tenantId: string) => Call<Tenant>;\n readonly restoreTenant: (credentials: ApiCredentials, tenantId: string) => Call<Tenant>;\n }\n>()(\"@aperture-browser/api-client/TenantsApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { compactQuery } from \"../query.ts\";\nimport { TenantsApi, type TenantsListParams } from \"./service.ts\";\n\nexport const makeTenantsApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const listTenants = Effect.fn(\"TenantsApi.listTenants\")(function* (\n credentials: ApiCredentials,\n params: TenantsListParams = {},\n ) {\n return yield* api\n .listTenants({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n includeDeleted: params.includeDeleted || undefined,\n deleted: params.deleted,\n }),\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const createTenant = Effect.fn(\"TenantsApi.createTenant\")(function* (\n credentials: ApiCredentials,\n input: Api.TenantInput,\n ) {\n return yield* api\n .createTenant({ payload: input })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const updateTenant = Effect.fn(\"TenantsApi.updateTenant\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n input: Api.TenantInput,\n ) {\n return yield* api\n .updateTenant(tenantId, { payload: input })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const deleteTenant = Effect.fn(\"TenantsApi.deleteTenant\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n ) {\n return yield* api\n .deleteTenant(tenantId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const restoreTenant = Effect.fn(\"TenantsApi.restoreTenant\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n ) {\n return yield* api\n .restoreTenant(tenantId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n return TenantsApi.of({ listTenants, createTenant, updateTenant, deleteTenant, restoreTenant });\n});\n\nexport const tenantsApiLayer = Layer.effect(TenantsApi, makeTenantsApi);\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { CreateTokenResponse, ResourceGrant, ResourceMode, TokensPage } from \"../schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface TokensListParams {\n limit?: number;\n cursor?: string;\n tenantId?: string;\n name?: string;\n authorityType?: \"system_admin\" | \"tenant\";\n revoked?: \"all\" | \"active\" | \"revoked\";\n scope?: string;\n}\n\nexport interface CreateAdminTokenInput {\n name: string;\n authorityType: \"system_admin\" | \"tenant\";\n tenantId?: string | null;\n scopes: string[];\n resourceMode: ResourceMode;\n resourceGrants: ResourceGrant[];\n expiresAt?: string | null;\n}\n\nexport interface CreateTenantTokenInput {\n name: string;\n scopes: string[];\n resourceMode: ResourceMode;\n resourceGrants: ResourceGrant[];\n expiresAt?: string | null;\n}\n\n/** API tokens, issued either deployment-wide or within the current tenant. */\nexport class TokensApi extends Context.Service<\n TokensApi,\n {\n readonly listAdminTokens: (\n credentials: ApiCredentials,\n params?: TokensListParams,\n ) => Call<TokensPage>;\n readonly createAdminToken: (\n credentials: ApiCredentials,\n input: CreateAdminTokenInput,\n ) => Call<CreateTokenResponse>;\n readonly revokeAdminToken: (credentials: ApiCredentials, tokenId: string) => Call<void>;\n readonly listTenantTokens: (\n credentials: ApiCredentials,\n params?: TokensListParams,\n ) => Call<TokensPage>;\n readonly createTenantToken: (\n credentials: ApiCredentials,\n input: CreateTenantTokenInput,\n ) => Call<CreateTokenResponse>;\n readonly revokeTenantToken: (credentials: ApiCredentials, tokenId: string) => Call<void>;\n }\n>()(\"@aperture-browser/api-client/TokensApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { compactQuery } from \"../query.ts\";\nimport {\n TokensApi,\n type CreateAdminTokenInput,\n type CreateTenantTokenInput,\n type TokensListParams,\n} from \"./service.ts\";\n\n// Filters and scopes arrive from free-form UI state; the server validates them, so they\n// are sent as the generated request types without narrowing.\n\nexport const makeTokensApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const listAdminTokens = Effect.fn(\"TokensApi.listAdminTokens\")(function* (\n credentials: ApiCredentials,\n params: TokensListParams = {},\n ) {\n return yield* api\n .listAdminTokens({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n tenantId: params.tenantId,\n name: params.name,\n authorityType: params.authorityType,\n revoked: params.revoked,\n scope: params.scope,\n }) as typeof Api.ListAdminTokensParams.Encoded,\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const createAdminToken = Effect.fn(\"TokensApi.createAdminToken\")(function* (\n credentials: ApiCredentials,\n input: CreateAdminTokenInput,\n ) {\n const systemAdmin = input.authorityType === \"system_admin\";\n return yield* api\n .createAdminToken({\n payload: {\n name: input.name,\n authorityType: input.authorityType,\n tenantId: input.tenantId ?? null,\n scopes: input.scopes,\n resourceMode: systemAdmin ? \"all\" : input.resourceMode,\n resourceGrants: systemAdmin ? [] : input.resourceGrants,\n expiresAt: input.expiresAt ?? null,\n } as typeof Api.CreateAdminTokenRequestJson.Encoded,\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const revokeAdminToken = Effect.fn(\"TokensApi.revokeAdminToken\")(function* (\n credentials: ApiCredentials,\n tokenId: string,\n ) {\n yield* api.revokeAdminToken(tokenId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const listTenantTokens = Effect.fn(\"TokensApi.listTenantTokens\")(function* (\n credentials: ApiCredentials,\n params: TokensListParams = {},\n ) {\n return yield* api\n .listTenantTokens({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n name: params.name,\n revoked: params.revoked,\n scope: params.scope,\n }) as typeof Api.ListTenantTokensParams.Encoded,\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const createTenantToken = Effect.fn(\"TokensApi.createTenantToken\")(function* (\n credentials: ApiCredentials,\n input: CreateTenantTokenInput,\n ) {\n return yield* api\n .createTenantToken({\n payload: {\n name: input.name,\n scopes: input.scopes,\n resourceMode: input.resourceMode,\n resourceGrants: input.resourceGrants,\n expiresAt: input.expiresAt ?? null,\n } as typeof Api.CreateTenantTokenRequestJson.Encoded,\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const revokeTenantToken = Effect.fn(\"TokensApi.revokeTenantToken\")(function* (\n credentials: ApiCredentials,\n tokenId: string,\n ) {\n yield* api.revokeTenantToken(tokenId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n return TokensApi.of({\n listAdminTokens,\n createAdminToken,\n revokeAdminToken,\n listTenantTokens,\n createTenantToken,\n revokeTenantToken,\n });\n});\n\nexport const tokensApiLayer = Layer.effect(TokensApi, makeTokensApi);\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { TenantMembership, User, UserInvitation, UsersPage } from \"../schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface UsersListParams {\n limit?: number;\n cursor?: string;\n query?: string;\n disabled?: \"active\" | \"disabled\" | \"all\";\n}\n\nexport interface UserInput {\n email: string | null;\n displayName: string;\n isSystemAdmin: boolean;\n}\n\n/** User administration and tenant memberships. */\nexport class UsersApi extends Context.Service<\n UsersApi,\n {\n readonly listUsers: (credentials: ApiCredentials, params?: UsersListParams) => Call<UsersPage>;\n readonly createUser: (credentials: ApiCredentials, input: UserInput) => Call<User>;\n readonly getUser: (credentials: ApiCredentials, userId: string) => Call<User>;\n readonly updateUser: (\n credentials: ApiCredentials,\n userId: string,\n input: UserInput,\n ) => Call<User>;\n readonly createUserInvitation: (\n credentials: ApiCredentials,\n userId: string,\n ) => Call<UserInvitation>;\n readonly disableUser: (credentials: ApiCredentials, userId: string) => Call<User>;\n readonly restoreUser: (credentials: ApiCredentials, userId: string) => Call<User>;\n readonly listUserMemberships: (\n credentials: ApiCredentials,\n userId: string,\n ) => Call<ReadonlyArray<TenantMembership>>;\n readonly upsertTenantMembership: (\n credentials: ApiCredentials,\n tenantId: string,\n userId: string,\n scopes: readonly string[],\n ) => Call<TenantMembership>;\n readonly deleteTenantMembership: (\n credentials: ApiCredentials,\n tenantId: string,\n userId: string,\n ) => Call<void>;\n }\n>()(\"@aperture-browser/api-client/UsersApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { compactQuery } from \"../query.ts\";\nimport { UsersApi, type UserInput, type UsersListParams } from \"./service.ts\";\n\nexport const makeUsersApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const listUsers = Effect.fn(\"UsersApi.listUsers\")(function* (\n credentials: ApiCredentials,\n params: UsersListParams = {},\n ) {\n return yield* api\n .listUsers({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n query: params.query,\n disabled: params.disabled,\n }),\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const createUser = Effect.fn(\"UsersApi.createUser\")(function* (\n credentials: ApiCredentials,\n input: UserInput,\n ) {\n return yield* api.createUser({ payload: input }).pipe(authorize(Authorization.of(credentials)));\n });\n\n const getUser = Effect.fn(\"UsersApi.getUser\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api.getUser(userId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const updateUser = Effect.fn(\"UsersApi.updateUser\")(function* (\n credentials: ApiCredentials,\n userId: string,\n input: UserInput,\n ) {\n return yield* api\n .updateUser(userId, { payload: input })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const createUserInvitation = Effect.fn(\"UsersApi.createUserInvitation\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api\n .createUserInvitation(userId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const disableUser = Effect.fn(\"UsersApi.disableUser\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api.disableUser(userId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const restoreUser = Effect.fn(\"UsersApi.restoreUser\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api.restoreUser(userId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const listUserMemberships = Effect.fn(\"UsersApi.listUserMemberships\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api\n .listUserMemberships(userId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const upsertTenantMembership = Effect.fn(\"UsersApi.upsertTenantMembership\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n userId: string,\n scopes: readonly string[],\n ) {\n // Scopes arrive from free-form UI state; the server validates them.\n const payload = { scopes } as typeof Api.UpsertTenantMembershipRequestJson.Encoded;\n return yield* api\n .upsertTenantMembership(tenantId, userId, { payload })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const deleteTenantMembership = Effect.fn(\"UsersApi.deleteTenantMembership\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n userId: string,\n ) {\n yield* api\n .deleteTenantMembership(tenantId, userId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n return UsersApi.of({\n listUsers,\n createUser,\n getUser,\n updateUser,\n createUserInvitation,\n disableUser,\n restoreUser,\n listUserMemberships,\n upsertTenantMembership,\n deleteTenantMembership,\n });\n});\n\nexport const usersApiLayer = Layer.effect(UsersApi, makeUsersApi);\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as HttpClientRequest from \"effect/unstable/http/HttpClientRequest\";\nimport { authApiLayer } from \"./auth/layer.ts\";\nimport { apiAuthorizationLayer, authorizedHttpClientLayer } from \"./authorization/layer.ts\";\nimport { eventsApiLayer } from \"./events/layer.ts\";\nimport { sessionsApiLayer } from \"./sessions/layer.ts\";\nimport { snapshotsApiLayer } from \"./snapshots/layer.ts\";\nimport { tenantsApiLayer } from \"./tenants/layer.ts\";\nimport { tokensApiLayer } from \"./tokens/layer.ts\";\nimport { usersApiLayer } from \"./users/layer.ts\";\n\n/**\n * Every API service, sharing one ApiAuthorization. The services send requests through the\n * HttpClient the app provides, decorated with each call's authorization.\n */\nexport const apiClientLayer = Layer.mergeAll(\n authApiLayer,\n tenantsApiLayer,\n usersApiLayer,\n sessionsApiLayer,\n snapshotsApiLayer,\n tokensApiLayer,\n eventsApiLayer,\n).pipe(Layer.provide(authorizedHttpClientLayer), Layer.provideMerge(apiAuthorizationLayer));\n\nexport type ApiServices = Layer.Success<typeof apiClientLayer>;\n\nexport const baseUrlLayer = (baseUrl: string) =>\n Layer.effect(\n HttpClient.HttpClient,\n Effect.map(HttpClient.HttpClient, HttpClient.mapRequest(HttpClientRequest.prependUrl(baseUrl))),\n );\n","import type { PageMeta } from \"./schemas.ts\";\n\nexport interface PaginatedResponse<T> {\n readonly data: ReadonlyArray<T>;\n readonly meta: PageMeta;\n}\n\nexport interface ListQueryParams {\n limit?: number;\n cursor?: string;\n}\n\nexport function getNextPageParam<T>(page: PaginatedResponse<T>): string | undefined {\n return page.meta.hasMore ? page.meta.nextCursor : undefined;\n}\n\nexport function flattenInfinitePages<T>(pages: PaginatedResponse<T>[] | undefined): T[] {\n return pages?.flatMap((page) => page.data) ?? [];\n}\n\nexport const defaultListLimit = 50;\n\nexport const listQueryDefaults = {\n refetchOnWindowFocus: true,\n} as const;\n","import * as Api from \"@aperture-browser/api-schema\";\n\n// Resources described by api/openapi.yaml, under the names the app uses.\n\nexport type PageMeta = Api.PageMeta;\nexport type Tenant = Api.Tenant;\nexport type User = Api.User;\nexport type UserInvitation = Api.UserInvitation;\nexport type TenantMembership = Api.TenantMembership;\nexport type AuthMeResponse = Api.AuthMe;\nexport type AuthMePrincipal = Api.Principal;\nexport type AuthMeTenant = Api.Tenant;\nexport type ResourceMode = Api.ResourceMode;\nexport type ResourceGrant = Api.ResourceGrant;\nexport type Scope = Api.Scope;\nexport type TenantScope = Api.TenantScope;\nexport type Session = Api.Session;\nexport type SessionMedia = Api.SessionMedia;\nexport type IceServer = Api.IceServer;\nexport const SessionStatus = Api.SessionStatus;\nexport type SessionStatus = Api.SessionStatus;\nexport type Snapshot = Api.Snapshot;\nexport type ApiToken = Api.Token;\nexport type TenantsPage = Api.TenantPage;\nexport type UsersPage = Api.UserPage;\nexport type SessionsPage = Api.SessionPage;\nexport type SessionsBulkResponse = Api.SessionBulkResponse;\nexport type SnapshotsPage = Api.SnapshotPage;\nexport type TokensPage = Api.TokenPage;\nexport type BrowserChannel = Api.BrowserChannel;\nexport type BrowserChannelsResponse = Api.BrowserChannels;\nexport type ResourceEvent = Api.Event;\nexport type EventsPage = Api.EventPage;\nexport type CreateSessionResponse = Api.CreateSessionResult;\nexport type SessionMutationResponse = Api.SessionMutation;\nexport type SnapshotMutationResponse = Api.SnapshotMutation;\nexport type PromoteSessionResponse = Api.SnapshotMutation;\nexport type CreateTokenResponse = Api.CreateTokenResponse;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/authorization/service.ts","../src/auth/schemas.ts","../src/auth/layer.ts","../src/errors.ts","../src/authorization/layer.ts","../src/events/service.ts","../src/health/service.ts","../src/pagination.ts","../src/query.ts","../src/events/layer.ts","../src/health/layer.ts","../src/sessions/schemas.ts","../src/sessions/service.ts","../src/sessions/uploads.ts","../src/sessions/layer.ts","../src/snapshots/service.ts","../src/snapshots/layer.ts","../src/tenants/service.ts","../src/tenants/layer.ts","../src/tokens/service.ts","../src/tokens/layer.ts","../src/users/service.ts","../src/users/layer.ts","../src/layer.ts","../src/client.ts","../src/schemas.ts","../src/sessions/tree.ts"],"sourcesContent":["import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type * as Redacted from \"effect/Redacted\";\nimport type * as Schema from \"effect/Schema\";\nimport type * as Stream from \"effect/Stream\";\nimport type * as HttpClientError from \"effect/http/HttpClientError\";\nimport type { ApiRequestError } from \"../errors.ts\";\n\nexport const TENANT_HEADER = \"X-Aperture-Tenant-Id\";\n\ninterface CredentialContext {\n authorityType: \"system_admin\" | \"tenant\" | null;\n tenantId: string | null;\n selectedTenantId: string | null;\n}\n\nexport type ApiCredentials =\n | (CredentialContext & {\n kind: \"bearer\";\n token: Redacted.Redacted<string>;\n })\n | (CredentialContext & {\n kind: \"session\";\n });\n\n/** The browser's own login session, sent as a cookie. */\nexport const webSessionCredentials: ApiCredentials = {\n kind: \"session\",\n authorityType: null,\n tenantId: null,\n selectedTenantId: null,\n};\n\nexport type TenantHeaderMode = \"none\" | \"optional\" | \"tenant-scoped\";\n\n/** Which tenant, if any, a request acts for under the given credentials. */\nexport function resolveTenantHeader(\n credentials: ApiCredentials,\n mode: TenantHeaderMode,\n): string | undefined {\n if (mode === \"none\") {\n return undefined;\n }\n\n if (mode === \"optional\") {\n return credentials.selectedTenantId ?? undefined;\n }\n\n if (credentials.authorityType === \"tenant\") {\n if (credentials.kind === \"bearer\") {\n return undefined;\n }\n return credentials.tenantId ?? undefined;\n }\n\n if (credentials.authorityType === \"system_admin\") {\n return credentials.selectedTenantId ?? undefined;\n }\n\n return undefined;\n}\n\n/** How a request authenticates, and which tenant it acts for. */\nexport interface Authorization {\n readonly credentials?: ApiCredentials;\n readonly bearerToken?: Redacted.Redacted<string>;\n readonly tenantHeader?: TenantHeaderMode;\n}\n\nexport const Authorization = {\n anonymous: {} as Authorization,\n webSession: { credentials: webSessionCredentials } as Authorization,\n of: (credentials: ApiCredentials): Authorization => ({ credentials }),\n tenantScoped: (credentials: ApiCredentials): Authorization => ({\n credentials,\n tenantHeader: \"tenant-scoped\",\n }),\n};\n\n/**\n * Authenticates API calls. Inside `authorize`, every request sent through the HttpClient\n * that `authorizedHttpClientLayer` provides carries that call's credentials and tenant, so\n * callers never touch headers.\n */\nexport class ApiAuthorization extends Context.Service<\n ApiAuthorization,\n {\n /** Runs a call with the given authorization and maps its failures to ApiRequestError. */\n readonly authorize: (\n authorization: Authorization,\n ) => <A, R>(\n self: Effect.Effect<A, HttpClientError.HttpClientError | Schema.SchemaError, R>,\n ) => Effect.Effect<A, ApiRequestError, R>;\n /** Emits whenever the web session is found to be missing, expired or revoked. */\n readonly sessionAuthenticationFailures: Stream.Stream<void>;\n }\n>()(\"@aperture-browser/api-client/ApiAuthorization\") {}\n","import * as Schema from \"effect/Schema\";\nimport * as Api from \"@aperture-browser/api-schema\";\n\n// The browser login flows are not part of api/openapi.yaml.\n\nconst passkeyAuthenticatorTransport = Schema.Literals([\n \"ble\",\n \"cable\",\n \"hybrid\",\n \"internal\",\n \"nfc\",\n \"smart-card\",\n \"usb\",\n]);\n\nconst passkeyCredentialDescriptor = Schema.Struct({\n id: Schema.String,\n type: Schema.Literal(\"public-key\"),\n transports: Schema.optionalKey(Schema.mutable(Schema.Array(passkeyAuthenticatorTransport))),\n});\n\nconst passkeyExtensions = Schema.optionalKey(\n Schema.Struct({\n appid: Schema.optionalKey(Schema.String),\n credProps: Schema.optionalKey(Schema.Boolean),\n hmacCreateSecret: Schema.optionalKey(Schema.Boolean),\n minPinLength: Schema.optionalKey(Schema.Boolean),\n }),\n);\n\nconst passkeyHint = Schema.Literals([\"hybrid\", \"security-key\", \"client-device\"]);\nconst passkeyUserVerification = Schema.Literals([\"discouraged\", \"preferred\", \"required\"]);\n\nexport const LoginMethods = Schema.Struct({\n methods: Schema.Array(\n Schema.Union([\n Schema.Struct({ type: Schema.Literal(\"password\") }),\n Schema.Struct({ type: Schema.Literal(\"api_token\") }),\n Schema.Struct({ type: Schema.Literal(\"passkey\") }),\n Schema.Struct({\n type: Schema.Literal(\"oidc\"),\n id: Schema.String,\n name: Schema.String,\n loginUrl: Schema.String,\n }),\n ]),\n ),\n});\n\nexport const PasskeyLoginOptions = Schema.Struct({\n publicKey: Schema.Struct({\n challenge: Schema.String,\n timeout: Schema.optionalKey(Schema.Number),\n rpId: Schema.optionalKey(Schema.String),\n allowCredentials: Schema.optionalKey(Schema.mutable(Schema.Array(passkeyCredentialDescriptor))),\n userVerification: Schema.optionalKey(passkeyUserVerification),\n hints: Schema.optionalKey(Schema.mutable(Schema.Array(passkeyHint))),\n extensions: passkeyExtensions,\n }),\n});\n\nexport const PasskeyRegistrationOptions = Schema.Struct({\n publicKey: Schema.Struct({\n rp: Schema.Struct({\n id: Schema.optionalKey(Schema.String),\n name: Schema.String,\n }),\n user: Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n displayName: Schema.String,\n }),\n challenge: Schema.String,\n pubKeyCredParams: Schema.mutable(\n Schema.Array(\n Schema.Struct({\n alg: Schema.Literals([-7, -8, -35, -36, -37, -38, -39, -257, -258, -259]),\n type: Schema.Literal(\"public-key\"),\n }),\n ),\n ),\n timeout: Schema.optionalKey(Schema.Number),\n excludeCredentials: Schema.optionalKey(\n Schema.mutable(Schema.Array(passkeyCredentialDescriptor)),\n ),\n authenticatorSelection: Schema.optionalKey(\n Schema.Struct({\n authenticatorAttachment: Schema.optionalKey(\n Schema.Literals([\"platform\", \"cross-platform\"]),\n ),\n requireResidentKey: Schema.optionalKey(Schema.Boolean),\n residentKey: Schema.optionalKey(Schema.Literals([\"discouraged\", \"preferred\", \"required\"])),\n userVerification: Schema.optionalKey(passkeyUserVerification),\n }),\n ),\n hints: Schema.optionalKey(Schema.mutable(Schema.Array(passkeyHint))),\n attestation: Schema.optionalKey(Schema.Literals([\"direct\", \"enterprise\", \"indirect\", \"none\"])),\n attestationFormats: Schema.optionalKey(\n Schema.mutable(\n Schema.Array(\n Schema.Literals([\n \"fido-u2f\",\n \"packed\",\n \"android-safetynet\",\n \"android-key\",\n \"tpm\",\n \"apple\",\n \"none\",\n ]),\n ),\n ),\n ),\n extensions: passkeyExtensions,\n }),\n});\n\nexport const Passkey = Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n createdAt: Schema.String,\n lastUsedAt: Schema.NullOr(Schema.String),\n});\n\nexport const Passkeys = Schema.Struct({\n passkeys: Schema.Array(Passkey),\n});\n\nexport const PasskeyMutation = Schema.Struct({\n passkey: Passkey,\n});\n\nexport const PasswordLoginResponse = Schema.Struct({\n mfaRequired: Schema.Boolean,\n});\n\nexport const SecurityStatus = Schema.Struct({\n hasPassword: Schema.Boolean,\n totpEnabled: Schema.Boolean,\n recoveryCodesRemaining: Schema.Number.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0)),\n});\n\nexport const TOTPEnrollment = Schema.Struct({\n secret: Schema.String,\n otpauthUrl: Schema.String,\n qrCodeDataUrl: Schema.String,\n});\n\nexport const RecoveryCodes = Schema.Struct({\n recoveryCodes: Schema.Array(Schema.String),\n});\n\nexport const OAuthClient = Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n uri: Schema.NullOr(Schema.String),\n logoUri: Schema.NullOr(Schema.String),\n kind: Schema.Literals([\"registered\", \"metadata_document\"]),\n});\n\n/** A pending OAuth authorization request, as the consent page presents it. */\nexport const OAuthAuthorizationRequest = Schema.Struct({\n client: OAuthClient,\n redirectUri: Schema.String,\n requestedScopes: Schema.Array(Schema.String),\n user: Schema.Struct({\n id: Schema.String,\n displayName: Schema.String,\n isSystemAdmin: Schema.Boolean,\n }),\n tenants: Schema.Array(\n Schema.Struct({\n id: Schema.String,\n displayName: Schema.String,\n scopes: Schema.Array(Api.TenantScope),\n }),\n ),\n availableScopes: Schema.Array(Api.TenantScope),\n canGrantSystemAdmin: Schema.Boolean,\n});\n\n/** Where the browser goes after the user approves or denies an authorization request. */\nexport const OAuthRedirect = Schema.Struct({\n redirectUrl: Schema.String,\n});\n\nexport const OAuthGrant = Schema.Struct({\n id: Schema.String,\n client: OAuthClient,\n authorityType: Api.AuthorityType,\n tenants: Schema.Array(Schema.Struct({ id: Schema.String, displayName: Schema.String })),\n scopes: Schema.Array(Schema.String),\n resourceMode: Api.ResourceMode,\n resourceGrants: Schema.Array(\n Schema.Struct({ resourceType: Api.ResourceType, resourceId: Schema.String }),\n ),\n createdAt: Schema.String,\n lastUsedAt: Schema.NullOr(Schema.String),\n});\n\nexport const OAuthGrants = Schema.Struct({\n grants: Schema.Array(OAuthGrant),\n});\n\n/**\n * The user's answer to an authorization request. `query` is the authorize query string\n * without its leading `?`. With `systemAdmin`, the tenant, scope and resource fields are\n * ignored.\n */\nexport interface OAuthApproval {\n readonly query: string;\n readonly systemAdmin: boolean;\n readonly tenantIds: ReadonlyArray<string>;\n readonly scopes: ReadonlyArray<Api.TenantScope>;\n readonly resourceMode: Api.ResourceMode;\n readonly resourceGrants: ReadonlyArray<Api.ResourceGrant>;\n}\n\nexport type LoginMethods = typeof LoginMethods.Type;\nexport type PasskeyLoginOptions = typeof PasskeyLoginOptions.Type;\nexport type PasskeyRegistrationOptions = typeof PasskeyRegistrationOptions.Type;\nexport type Passkey = typeof Passkey.Type;\nexport type Passkeys = typeof Passkeys.Type;\nexport type PasskeyMutation = typeof PasskeyMutation.Type;\nexport type PasswordLoginResponse = typeof PasswordLoginResponse.Type;\nexport type RecoveryCodes = typeof RecoveryCodes.Type;\nexport type SecurityStatus = typeof SecurityStatus.Type;\nexport type TOTPEnrollment = typeof TOTPEnrollment.Type;\nexport type OAuthClient = typeof OAuthClient.Type;\nexport type OAuthAuthorizationRequest = typeof OAuthAuthorizationRequest.Type;\nexport type OAuthRedirect = typeof OAuthRedirect.Type;\nexport type OAuthGrant = typeof OAuthGrant.Type;\nexport type OAuthGrants = typeof OAuthGrants.Type;\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpBody from \"effect/http/HttpBody\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as HttpClientResponse from \"effect/http/HttpClientResponse\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport {\n ApiAuthorization,\n Authorization,\n webSessionCredentials,\n type ApiCredentials,\n} from \"../authorization/service.ts\";\nimport {\n LoginMethods,\n OAuthAuthorizationRequest,\n type OAuthApproval,\n OAuthGrants,\n OAuthRedirect,\n PasskeyLoginOptions,\n PasskeyMutation,\n PasskeyRegistrationOptions,\n Passkeys,\n PasswordLoginResponse,\n RecoveryCodes,\n SecurityStatus,\n TOTPEnrollment,\n} from \"./schemas.ts\";\nimport { AuthApi, type PasskeyCredentialJSON } from \"./service.ts\";\n\nconst jsonBody = (body: unknown) => ({ body: HttpBody.jsonUnsafe(body) });\n\nexport const makeAuthApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const http = HttpClient.filterStatusOk(httpClient);\n const api = Api.make(httpClient);\n const anonymous = authorize(Authorization.anonymous);\n const webSession = authorize(Authorization.webSession);\n\n const listLoginMethods = Effect.fn(\"AuthApi.listLoginMethods\")(function* () {\n return yield* http\n .get(\"/auth/login-methods\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(LoginMethods)), anonymous);\n });\n\n const loginWithPassword = Effect.fn(\"AuthApi.loginWithPassword\")(function* (\n email: string,\n password: string,\n ) {\n return yield* http\n .post(\"/auth/password/login\", jsonBody({ email, password }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(PasswordLoginResponse)), anonymous);\n });\n\n const completePasswordMFA = Effect.fn(\"AuthApi.completePasswordMFA\")(function* (code: string) {\n yield* http.post(\"/auth/password/login/mfa\", jsonBody({ code })).pipe(anonymous);\n });\n\n const loginWithAPIToken = Effect.fn(\"AuthApi.loginWithAPIToken\")(function* (token: string) {\n yield* http.post(\"/auth/token/login\", jsonBody({ token })).pipe(anonymous);\n });\n\n const beginPasskeyLogin = Effect.fn(\"AuthApi.beginPasskeyLogin\")(function* () {\n return yield* http\n .post(\"/auth/passkeys/login/options\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(PasskeyLoginOptions)), anonymous);\n });\n\n const finishPasskeyLogin = Effect.fn(\"AuthApi.finishPasskeyLogin\")(function* (\n credential: PasskeyCredentialJSON,\n ) {\n yield* http.post(\"/auth/passkeys/login/finish\", jsonBody(credential)).pipe(anonymous);\n });\n\n const acceptUserInvitation = Effect.fn(\"AuthApi.acceptUserInvitation\")(function* (\n token: string,\n password: string,\n ) {\n yield* http.post(\"/auth/invitations/accept\", jsonBody({ token, password })).pipe(anonymous);\n });\n\n const logoutWebSession = Effect.fn(\"AuthApi.logoutWebSession\")(function* () {\n yield* http.post(\"/auth/logout\").pipe(webSession);\n });\n\n const getAuthMe = Effect.fn(\"AuthApi.getAuthMe\")(function* (\n selectedTenantId: string | null = null,\n credentials: ApiCredentials = webSessionCredentials,\n ) {\n return yield* api.getCurrentPrincipal(undefined).pipe(\n authorize({\n credentials: { ...credentials, selectedTenantId },\n tenantHeader: \"optional\",\n }),\n );\n });\n\n const getSecurityStatus = Effect.fn(\"AuthApi.getSecurityStatus\")(function* () {\n return yield* http\n .get(\"/auth/security\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(SecurityStatus)), webSession);\n });\n\n const setPassword = Effect.fn(\"AuthApi.setPassword\")(function* (\n currentPassword: string,\n newPassword: string,\n ) {\n yield* http.put(\"/auth/password\", jsonBody({ currentPassword, newPassword })).pipe(webSession);\n });\n\n const listPasskeys = Effect.fn(\"AuthApi.listPasskeys\")(function* () {\n return yield* http\n .get(\"/auth/passkeys\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(Passkeys)), webSession);\n });\n\n const beginPasskeyRegistration = Effect.fn(\"AuthApi.beginPasskeyRegistration\")(function* (\n name: string,\n ) {\n return yield* http\n .post(\"/auth/passkeys/registration/options\", jsonBody({ name }))\n .pipe(\n Effect.flatMap(HttpClientResponse.schemaBodyJson(PasskeyRegistrationOptions)),\n webSession,\n );\n });\n\n const finishPasskeyRegistration = Effect.fn(\"AuthApi.finishPasskeyRegistration\")(function* (\n credential: PasskeyCredentialJSON,\n ) {\n return yield* http\n .post(\"/auth/passkeys/registration/finish\", jsonBody(credential))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(PasskeyMutation)), webSession);\n });\n\n const renamePasskey = Effect.fn(\"AuthApi.renamePasskey\")(function* (\n passkeyId: string,\n name: string,\n ) {\n return yield* http\n .patch(`/auth/passkeys/${encodeURIComponent(passkeyId)}`, jsonBody({ name }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(PasskeyMutation)), webSession);\n });\n\n const deletePasskey = Effect.fn(\"AuthApi.deletePasskey\")(function* (passkeyId: string) {\n yield* http.del(`/auth/passkeys/${encodeURIComponent(passkeyId)}`).pipe(webSession);\n });\n\n const beginTOTPEnrollment = Effect.fn(\"AuthApi.beginTOTPEnrollment\")(function* () {\n return yield* http\n .post(\"/auth/totp/enrollment/options\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(TOTPEnrollment)), webSession);\n });\n\n const completeTOTPEnrollment = Effect.fn(\"AuthApi.completeTOTPEnrollment\")(function* (\n code: string,\n ) {\n return yield* http\n .post(\"/auth/totp/enrollment/finish\", jsonBody({ code }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(RecoveryCodes)), webSession);\n });\n\n const regenerateRecoveryCodes = Effect.fn(\"AuthApi.regenerateRecoveryCodes\")(function* (\n code: string,\n ) {\n return yield* http\n .post(\"/auth/totp/recovery-codes\", jsonBody({ code }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(RecoveryCodes)), webSession);\n });\n\n const disableTOTP = Effect.fn(\"AuthApi.disableTOTP\")(function* (code: string) {\n yield* http.post(\"/auth/totp/disable\", jsonBody({ code })).pipe(webSession);\n });\n\n const getOAuthAuthorization = Effect.fn(\"AuthApi.getOAuthAuthorization\")(function* (\n query: string,\n ) {\n return yield* http\n .get(`/auth/oauth/authorization?${query}`)\n .pipe(\n Effect.flatMap(HttpClientResponse.schemaBodyJson(OAuthAuthorizationRequest)),\n webSession,\n );\n });\n\n const approveOAuthAuthorization = Effect.fn(\"AuthApi.approveOAuthAuthorization\")(function* (\n approval: OAuthApproval,\n ) {\n return yield* http\n .post(\"/auth/oauth/authorization/approve\", jsonBody(approval))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(OAuthRedirect)), webSession);\n });\n\n const denyOAuthAuthorization = Effect.fn(\"AuthApi.denyOAuthAuthorization\")(function* (\n query: string,\n ) {\n return yield* http\n .post(\"/auth/oauth/authorization/deny\", jsonBody({ query }))\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(OAuthRedirect)), webSession);\n });\n\n const listOAuthGrants = Effect.fn(\"AuthApi.listOAuthGrants\")(function* () {\n return yield* http\n .get(\"/auth/oauth/grants\")\n .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(OAuthGrants)), webSession);\n });\n\n const revokeOAuthGrant = Effect.fn(\"AuthApi.revokeOAuthGrant\")(function* (grantId: string) {\n yield* http.del(`/auth/oauth/grants/${encodeURIComponent(grantId)}`).pipe(webSession);\n });\n\n return AuthApi.of({\n listLoginMethods,\n loginWithPassword,\n completePasswordMFA,\n loginWithAPIToken,\n beginPasskeyLogin,\n finishPasskeyLogin,\n acceptUserInvitation,\n logoutWebSession,\n getAuthMe,\n getSecurityStatus,\n setPassword,\n listPasskeys,\n beginPasskeyRegistration,\n finishPasskeyRegistration,\n renamePasskey,\n deletePasskey,\n beginTOTPEnrollment,\n completeTOTPEnrollment,\n regenerateRecoveryCodes,\n disableTOTP,\n getOAuthAuthorization,\n approveOAuthAuthorization,\n denyOAuthAuthorization,\n listOAuthGrants,\n revokeOAuthGrant,\n });\n});\n\nexport const authApiLayer = Layer.effect(AuthApi, makeAuthApi);\n","import * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport * as HttpClientResponse from \"effect/http/HttpClientResponse\";\nimport * as HttpClientError from \"effect/http/HttpClientError\";\n\nexport const ApiErrorBody = Schema.Struct({\n error: Schema.Struct({\n code: Schema.String,\n message: Schema.String,\n }),\n});\n\nexport type ApiErrorBody = typeof ApiErrorBody.Type;\n\n/**\n * The error body of a live-session route that failed inside the running session. It carries\n * no stable code, so the resulting ApiRequestError uses `live_session_error` and callers\n * branch on its status.\n */\nexport const LiveSessionErrorBody = Schema.Struct({\n error: Schema.String,\n});\n\nexport type LiveSessionErrorBody = typeof LiveSessionErrorBody.Type;\n\nconst ErrorResponseBody = Schema.Union([ApiErrorBody, LiveSessionErrorBody]);\n\n/**\n * A failed API request. `code` and `message` come from the server's error body when it\n * sent one; `status` is 0 when no HTTP status applies. `cause` is the underlying HTTP or\n * decoding failure when the server's error body alone does not explain it.\n */\nexport class ApiRequestError extends Schema.TaggedError<ApiRequestError>()(\"ApiRequestError\", {\n code: Schema.String,\n message: Schema.String,\n status: Schema.Number,\n cause: Schema.optional(\n Schema.Union([\n Schema.instanceOf(HttpClientError.HttpClientError),\n Schema.instanceOf(Schema.SchemaError),\n ]),\n ),\n}) {}\n\nconst invalidResponse = (\n status: number,\n cause: HttpClientError.HttpClientError | Schema.SchemaError,\n) => new ApiRequestError({ code: \"internal_error\", message: \"Invalid response\", status, cause });\n\n/**\n * Maps HTTP and decoding failures to ApiRequestError. Error responses keep the code and\n * message of the server's error body.\n */\nexport const toApiRequestError = <A, R>(\n self: Effect.Effect<A, HttpClientError.HttpClientError | Schema.SchemaError, R>,\n): Effect.Effect<A, ApiRequestError, R> =>\n self.pipe(\n Effect.catchReasons(\"HttpClientError\", {\n StatusCodeError: ({ response }, cause) =>\n HttpClientResponse.schemaBodyJson(ErrorResponseBody)(response).pipe(\n Effect.map(({ error }) =>\n typeof error === \"string\"\n ? new ApiRequestError({\n code: \"live_session_error\",\n message: error,\n status: response.status,\n })\n : new ApiRequestError({ ...error, status: response.status }),\n ),\n Effect.orElseSucceed(\n () =>\n new ApiRequestError({\n code: \"internal_error\",\n message: \"Request failed\",\n status: response.status,\n cause,\n }),\n ),\n Effect.flatMap(Effect.fail),\n ),\n DecodeError: ({ response }, cause) => Effect.fail(invalidResponse(response.status, cause)),\n }),\n Effect.catchTags({\n HttpClientError: (cause) =>\n Effect.fail(\n new ApiRequestError({\n code: \"network_error\",\n message: \"The server could not be reached\",\n status: 0,\n cause,\n }),\n ),\n SchemaError: (cause) => Effect.fail(invalidResponse(0, cause)),\n }),\n );\n","import * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as PubSub from \"effect/PubSub\";\nimport * as Redacted from \"effect/Redacted\";\nimport * as Stream from \"effect/Stream\";\nimport type * as Schema from \"effect/Schema\";\nimport * as Function from \"effect/Function\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as HttpClientRequest from \"effect/http/HttpClientRequest\";\nimport type * as HttpClientError from \"effect/http/HttpClientError\";\nimport { toApiRequestError } from \"../errors.ts\";\nimport {\n ApiAuthorization,\n resolveTenantHeader,\n TENANT_HEADER,\n type Authorization,\n} from \"./service.ts\";\n\n/** The authorization of the call a request belongs to; set by `authorize`. */\nconst CurrentAuthorization = Context.Reference<Authorization>(\n \"@aperture-browser/api-client/CurrentAuthorization\",\n { defaultValue: () => ({}) },\n);\n\nconst authorizeRequest = (request: HttpClientRequest.HttpClientRequest) =>\n CurrentAuthorization.useSync(({ credentials, bearerToken, tenantHeader = \"none\" }) => {\n const secret = bearerToken ?? (credentials?.kind === \"bearer\" ? credentials.token : undefined);\n const token = secret === undefined ? undefined : Redacted.value(secret).trim();\n const tenantId = credentials ? resolveTenantHeader(credentials, tenantHeader) : undefined;\n return request.pipe(\n HttpClientRequest.acceptJson,\n token ? HttpClientRequest.bearerToken(token) : Function.identity,\n tenantId\n ? HttpClientRequest.setHeader(TENANT_HEADER, tenantId)\n : HttpClientRequest.removeHeader(TENANT_HEADER),\n );\n });\n\nconst sessionAuthenticationFailureCodes = new Set([\n \"authentication_required\",\n \"invalid_authentication_token\",\n \"authentication_token_expired\",\n \"authentication_token_revoked\",\n \"user_disabled\",\n]);\n\n/**\n * Decorates the HttpClient so each request carries the authorization of the `authorize`\n * call it runs in.\n */\nexport const authorizedHttpClientLayer = Layer.effect(\n HttpClient.HttpClient,\n Effect.map(HttpClient.HttpClient, HttpClient.mapRequestEffect(authorizeRequest)),\n);\n\nexport const makeApiAuthorization = Effect.gen(function* () {\n const failures = yield* PubSub.unbounded<void>();\n\n const authorize =\n (authorization: Authorization) =>\n <A, R>(self: Effect.Effect<A, HttpClientError.HttpClientError | Schema.SchemaError, R>) =>\n self.pipe(\n toApiRequestError,\n Effect.tapError((error) =>\n authorization.credentials?.kind === \"session\" &&\n sessionAuthenticationFailureCodes.has(error.code)\n ? PubSub.publish(failures, undefined)\n : Effect.void,\n ),\n Effect.provideService(CurrentAuthorization, authorization),\n );\n\n return ApiAuthorization.of({\n authorize,\n sessionAuthenticationFailures: Stream.fromPubSub(failures),\n });\n});\n\nexport const apiAuthorizationLayer = Layer.effect(ApiAuthorization, makeApiAuthorization);\n","import * as Context from \"effect/Context\";\nimport type * as Api from \"@aperture-browser/api-schema\";\nimport type { PageCursor, PaginatedList } from \"../pagination.ts\";\nimport type { AuditEvent, ResourceEvent } from \"../schemas.ts\";\n\nexport interface EventsFilter {\n limit?: number;\n resourceType?: string;\n resourceId?: string;\n}\n\nexport type EventsListParams = EventsFilter & PageCursor;\n\ntype EventsList = PaginatedList<EventsFilter, ResourceEvent>;\n\nexport interface AuditEventsFilter {\n limit?: number;\n tenantId?: string;\n actorType?: Api.PrincipalType;\n actorId?: string;\n action?: string;\n resourceType?: string;\n resourceId?: string;\n}\n\nexport type AuditEventsListParams = AuditEventsFilter & PageCursor;\n\ntype AuditEventsList = PaginatedList<AuditEventsFilter, AuditEvent>;\n\n/** The tenant's resource event log, and the deployment-wide audit log. */\nexport class EventsApi extends Context.Service<\n EventsApi,\n {\n readonly listEvents: EventsList[\"list\"];\n readonly streamEvents: EventsList[\"stream\"];\n readonly listAllEvents: EventsList[\"listAll\"];\n readonly listAuditEvents: AuditEventsList[\"list\"];\n readonly streamAuditEvents: AuditEventsList[\"stream\"];\n readonly listAllAuditEvents: AuditEventsList[\"listAll\"];\n }\n>()(\"@aperture-browser/api-client/EventsApi\") {}\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { Health } from \"../schemas.ts\";\n\n/** The instance's unauthenticated health check. */\nexport class HealthApi extends Context.Service<\n HealthApi,\n {\n readonly getHealth: () => Effect.Effect<Health, ApiRequestError>;\n }\n>()(\"@aperture-browser/api-client/HealthApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Stream from \"effect/Stream\";\nimport type { ApiCredentials } from \"./authorization/service.ts\";\nimport type { ApiRequestError } from \"./errors.ts\";\nimport type { PageMeta } from \"./schemas.ts\";\n\nexport interface PaginatedResponse<T> {\n readonly data: ReadonlyArray<T>;\n readonly meta: PageMeta;\n}\n\n/** The opaque `nextCursor` of the previous page, sent along with the same filter. */\nexport interface PageCursor {\n cursor?: string;\n}\n\n/**\n * The calls every cursor-paginated list exposes. The filter's `limit` is the page size.\n * `list` fetches one page; `stream` fetches pages only as the stream is pulled; `listAll`\n * collects every page.\n */\nexport interface PaginatedList<Filter, T> {\n readonly list: (\n credentials: ApiCredentials,\n params?: Filter & PageCursor,\n ) => Effect.Effect<PaginatedResponse<T>, ApiRequestError>;\n readonly stream: (\n credentials: ApiCredentials,\n filter?: Filter,\n ) => Stream.Stream<T, ApiRequestError>;\n readonly listAll: (\n credentials: ApiCredentials,\n filter?: Filter,\n ) => Effect.Effect<ReadonlyArray<T>, ApiRequestError>;\n}\n\nexport function getNextPageParam<T>(page: PaginatedResponse<T>): string | undefined {\n return page.meta.hasMore ? page.meta.nextCursor : undefined;\n}\n\nexport function flattenInfinitePages<T>(pages: PaginatedResponse<T>[] | undefined): T[] {\n return pages?.flatMap((page) => page.data) ?? [];\n}\n\n/**\n * Derives `stream` and `listAll` from the call that fetches one page. That call must also\n * accept a bare cursor, which every filter allows because all its fields are optional.\n */\nexport function paginated<Filter, T>(\n list: (\n credentials: ApiCredentials,\n params?: (Filter & PageCursor) | PageCursor,\n ) => Effect.Effect<PaginatedResponse<T>, ApiRequestError>,\n): PaginatedList<Filter, T> {\n const stream = (credentials: ApiCredentials, filter?: Filter) =>\n Stream.paginate<string | undefined, T, ApiRequestError>(undefined, (cursor) =>\n list(credentials, filter === undefined ? { cursor } : { ...filter, cursor }).pipe(\n Effect.map((page) => {\n const next = getNextPageParam(page);\n return [page.data, next === undefined ? Option.none() : Option.some(next)] as const;\n }),\n ),\n );\n\n const listAll = (credentials: ApiCredentials, filter?: Filter) =>\n Stream.runCollect(stream(credentials, filter));\n\n return { list, stream, listAll };\n}\n\nexport const defaultListLimit = 50;\n\nexport const listQueryDefaults = {\n refetchOnWindowFocus: true,\n} as const;\n","export type TagFilterValue = Array<{\n key: string;\n operator: \"eq\" | \"neq\" | \"in\" | \"not_in\";\n values: string[];\n}>;\n\n/** Encodes tag filters as the parallel tagKey, tagOperator and tagValue query lists. */\nexport const tagQuery = (tags: TagFilterValue | undefined) => ({\n tagKey: tags?.map((tag) => tag.key),\n tagOperator: tags?.map((tag) => tag.operator),\n tagValue: tags?.map((tag) => tag.values.join(\",\")),\n});\n\n/** Drops empty strings and empty list items, which mean \"no filter\". */\nexport const compactQuery = <T extends object>(query: T): T =>\n Object.fromEntries(\n Object.entries(query).flatMap(([key, value]) => {\n if (value === undefined || value === null || value === \"\") return [];\n if (!Array.isArray(value)) return [[key, value]];\n const items = value.filter((item) => item !== \"\");\n return items.length > 0 ? [[key, items]] : [];\n }),\n ) as T;\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { paginated } from \"../pagination.ts\";\nimport { compactQuery } from \"../query.ts\";\nimport type { AuditEvent, ResourceEvent } from \"../schemas.ts\";\nimport {\n EventsApi,\n type AuditEventsFilter,\n type AuditEventsListParams,\n type EventsFilter,\n type EventsListParams,\n} from \"./service.ts\";\n\nexport const makeEventsApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const listEvents = Effect.fn(\"EventsApi.listEvents\")(function* (\n credentials: ApiCredentials,\n params: EventsListParams = {},\n ) {\n return yield* api\n .listEvents({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n resourceType: params.resourceType,\n resourceId: params.resourceId,\n }),\n })\n .pipe(authorize(Authorization.tenantScoped(credentials)));\n });\n\n const listAuditEvents = Effect.fn(\"EventsApi.listAuditEvents\")(function* (\n credentials: ApiCredentials,\n params: AuditEventsListParams = {},\n ) {\n return yield* api\n .listAuditEvents({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n tenantId: params.tenantId,\n actorType: params.actorType,\n actorId: params.actorId,\n action: params.action,\n resourceType: params.resourceType,\n resourceId: params.resourceId,\n }),\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const events = paginated<EventsFilter, ResourceEvent>(listEvents);\n const auditEvents = paginated<AuditEventsFilter, AuditEvent>(listAuditEvents);\n\n return EventsApi.of({\n listEvents,\n streamEvents: events.stream,\n listAllEvents: events.listAll,\n listAuditEvents,\n streamAuditEvents: auditEvents.stream,\n listAllAuditEvents: auditEvents.listAll,\n });\n});\n\nexport const eventsApiLayer = Layer.effect(EventsApi, makeEventsApi);\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization } from \"../authorization/service.ts\";\nimport { HealthApi } from \"./service.ts\";\n\nexport const makeHealthApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const getHealth = Effect.fn(\"HealthApi.getHealth\")(function* () {\n return yield* api.getHealth(undefined).pipe(authorize(Authorization.anonymous));\n });\n\n return HealthApi.of({ getHealth });\n});\n\nexport const healthApiLayer = Layer.effect(HealthApi, makeHealthApi);\n","import * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport * as SchemaTransformation from \"effect/SchemaTransformation\";\nimport * as Api from \"@aperture-browser/api-schema\";\n\n// The live session endpoints are not part of api/openapi.yaml.\n\nconst positiveInt = Schema.Number.check(Schema.isInt(), Schema.isGreaterThan(0));\nconst emptyArray = Effect.succeed([]);\n\nexport const RecordingSettings = Schema.Struct({\n capture: Api.CreateSessionRecordingInput.fields.capture,\n presentation: Api.CreateSessionRecordingInput.fields.presentation,\n idle: Api.CreateSessionRecordingInput.fields.idle,\n ripple: Api.CreateSessionRecordingInput.fields.ripple,\n burst: Api.CreateSessionRecordingInput.fields.burst,\n});\nexport type RecordingSettings = typeof RecordingSettings.Type;\n\nexport const BrowserPage = Schema.Struct({\n targetId: Schema.String,\n state: Schema.Literals([\"pending\", \"ready\", \"unavailable\", \"closed\"]),\n title: Schema.String,\n url: Schema.String,\n viewport: Schema.optionalKey(\n Schema.Struct({\n width: positiveInt,\n height: positiveInt,\n deviceScaleFactor: Schema.Number.check(Schema.isGreaterThan(0)),\n contentWidth: positiveInt,\n contentHeight: positiveInt,\n canvasWidth: positiveInt,\n canvasHeight: positiveInt,\n }),\n ),\n thumbnailAvailable: Schema.Boolean,\n});\n\nconst browserStatusCommon = {\n sessionId: Schema.String,\n cdpUrl: Schema.String,\n media: Api.SessionMedia,\n thumbnailAvailable: Schema.Boolean,\n pages: Schema.Array(BrowserPage).pipe(Schema.withDecodingDefaultKey(emptyArray)),\n};\n\nconst availableBrowserStatus = {\n ...browserStatusCommon,\n capturedAt: Schema.String,\n representativeTargetId: Schema.optionalKey(Schema.String),\n};\n\n/** Passive page discovery. Reading it never wakes or keeps a browser session alive. */\nexport const BrowserStatus = Schema.Union([\n Schema.Struct({\n ...availableBrowserStatus,\n status: Schema.Literal(\"running\"),\n source: Schema.Literal(\"live\"),\n }),\n Schema.Struct({\n ...availableBrowserStatus,\n status: Schema.Literal(\"suspended\"),\n source: Schema.Literal(\"persisted\"),\n }),\n Schema.Struct({\n ...browserStatusCommon,\n status: Schema.Literal(\"suspended\"),\n source: Schema.Literal(\"unavailable\"),\n }),\n]);\n\nconst recordingFields = {\n recordingId: Schema.String,\n mode: Schema.Literals([\"tab\", \"viewer\"]),\n targetId: Schema.String,\n captureGeneration: positiveInt,\n status: Schema.Literals([\"starting\", \"running\", \"stopped\", \"failed\"]),\n stopReason: Schema.optionalKey(Schema.String),\n sandboxPath: Schema.optionalKey(Schema.String),\n /** @deprecated Read `relativePath`. Sessions started before it existed send only this. */\n path: Schema.optionalKey(Schema.String),\n startedAt: Schema.String,\n stoppedAt: Schema.optionalKey(Schema.String),\n sizeBytes: Schema.optionalKey(\n Schema.Number.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0)),\n ),\n fps: positiveInt,\n bitrateKbps: positiveInt,\n codec: Schema.String,\n /** The stop returned and the edit is still running; `editedRelativePath` or `editError` follows. */\n editing: Schema.Boolean,\n editedRelativePath: Schema.optionalKey(Schema.String),\n timelineRelativePath: Schema.optionalKey(Schema.String),\n editError: Schema.optionalKey(Api.RecordingEditError),\n};\n\n/**\n * A recording as the live session reports it. Sessions that are still running an\n * older wrapper send only `path`, which decoding carries over into `relativePath`.\n */\nexport const Recording = Schema.Struct({\n ...recordingFields,\n relativePath: Schema.optionalKey(Schema.String),\n}).pipe(\n Schema.decodeTo(\n Schema.Struct({ ...recordingFields, relativePath: Schema.String }),\n SchemaTransformation.transform({\n decode: ({ relativePath, ...recording }) => ({\n ...recording,\n relativePath: relativePath ?? recording.path ?? \"\",\n }),\n encode: (recording) => recording,\n }),\n ),\n);\n\nexport type BrowserStatus = typeof BrowserStatus.Type;\nexport type BrowserPage = typeof BrowserPage.Type;\nexport type Recording = typeof Recording.Type;\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type * as Redacted from \"effect/Redacted\";\nimport type * as Stream from \"effect/Stream\";\nimport type * as Api from \"@aperture-browser/api-schema\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { PageCursor, PaginatedList } from \"../pagination.ts\";\nimport type { TagFilterValue } from \"../query.ts\";\nimport type {\n BrowserChannelsResponse,\n CreateSessionResponse,\n CursorVisibility,\n PromoteSessionResponse,\n ProxyConfig,\n Session,\n SessionDirectory,\n SessionFile,\n SessionFileDownloadURL,\n SessionFileEntry,\n SessionMutationResponse,\n SessionRecording,\n SessionsBulkResponse,\n SetViewportInput,\n TargetViewport,\n UpdateProxyConfig,\n} from \"../schemas.ts\";\nimport type { BrowserStatus } from \"./schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface SessionsFilter {\n limit?: number;\n includeDeleted?: boolean;\n status?: Api.SessionStatus;\n query?: string;\n tags?: TagFilterValue;\n}\n\nexport type SessionsListParams = SessionsFilter & PageCursor;\n\ntype SessionsList = PaginatedList<SessionsFilter, Session>;\n\nexport type InitialBrowserTarget = Api.InitialBrowserTarget;\nexport type InitialBrowserStorageState = Api.InitialBrowserStorageState;\n\nexport interface CreateSessionInput {\n baseSnapshotName?: string | null;\n label?: string | null;\n browser: {\n channel: string;\n args?: string[];\n };\n initialTargets?: readonly InitialBrowserTarget[];\n storageState?: InitialBrowserStorageState;\n tags?: Record<string, string>;\n proxy?: ProxyConfig;\n}\n\nexport interface CreateSessionOptions {\n waitForReady?: boolean;\n}\n\nexport interface PromoteSessionInput {\n name: string;\n description?: string | null;\n force?: boolean;\n tags?: Record<string, string>;\n}\n\nexport type CreateSessionRecordingInput = Api.CreateSessionRecordingInput;\nexport type RecordingCaptionInput = Api.RecordingCaptionInput;\nexport type RecordingFocusInput = Api.RecordingFocusInput;\nexport type RecordingAttentionInput = Api.RecordingAttentionInput;\nexport type SessionFileDownloadURLInput = Api.SessionFileDownloadURLInput;\n\nexport interface DownloadedFile {\n blob: Blob;\n filename: string | null;\n}\n\n/**\n * One file to upload. Blob and Uint8Array contents are sent as FormData. Any stream content\n * makes the whole body a streamed request, which browsers other than Chromium cannot send;\n * a stream failure aborts the upload and surfaces as a `network_error`.\n */\nexport interface SessionUploadFile {\n name: string;\n content: Blob | Uint8Array | Stream.Stream<Uint8Array, unknown>;\n}\n\nexport interface UploadSessionFilesOptions {\n /** Directory below the session files root; `uploads` when omitted. */\n directory?: string;\n}\n\nexport type MoveSessionFileInput = Api.MoveSessionFileInput;\n\nexport interface DeleteSessionFileOptions {\n /** Delete a directory together with everything below it. */\n recursive?: boolean;\n}\n\n/** Browser sessions, their live browser, and their recordings. */\nexport class SessionsApi extends Context.Service<\n SessionsApi,\n {\n readonly listSessions: SessionsList[\"list\"];\n readonly streamSessions: SessionsList[\"stream\"];\n readonly listAllSessions: SessionsList[\"listAll\"];\n readonly exportSessionStorageState: (\n credentials: ApiCredentials,\n sessionId: string,\n input: Api.ExportSessionStorageStateInput,\n ) => Call<Api.InitialBrowserStorageState>;\n readonly getSession: (credentials: ApiCredentials, sessionId: string) => Call<Session>;\n /** Any number of IDs; the API takes 100 per request, so larger lists are sent in batches. */\n readonly getSessionsBulk: (\n credentials: ApiCredentials,\n sessionIds: readonly string[],\n ) => Call<SessionsBulkResponse>;\n readonly createSession: (\n credentials: ApiCredentials,\n input: CreateSessionInput,\n options?: CreateSessionOptions,\n ) => Call<CreateSessionResponse>;\n readonly deleteSession: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<SessionMutationResponse>;\n readonly reopenSession: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<SessionMutationResponse>;\n readonly suspendSession: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<SessionMutationResponse>;\n readonly rotateSessionToken: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<SessionMutationResponse>;\n readonly rotateCollaborationCapability: (\n credentials: ApiCredentials,\n sessionId: string,\n role: \"editor\" | \"viewer\",\n ) => Call<SessionMutationResponse>;\n readonly replaceSessionTags: (\n credentials: ApiCredentials,\n sessionId: string,\n tags: Record<string, string>,\n ) => Call<SessionMutationResponse>;\n /** Replaces the session's egress proxy; new connections use it immediately. */\n readonly updateSessionProxy: (\n credentials: ApiCredentials,\n sessionId: string,\n proxy: UpdateProxyConfig,\n ) => Call<SessionMutationResponse>;\n readonly promoteSession: (\n credentials: ApiCredentials,\n sessionId: string,\n input: PromoteSessionInput,\n ) => Call<PromoteSessionResponse>;\n readonly getSessionCursor: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<CursorVisibility>;\n readonly setSessionCursor: (\n credentials: ApiCredentials,\n sessionId: string,\n visible: boolean,\n ) => Call<CursorVisibility>;\n readonly listSessionRecordings: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<ReadonlyArray<SessionRecording>>;\n readonly createSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n input: CreateSessionRecordingInput,\n ) => Call<SessionRecording>;\n readonly getSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n ) => Call<SessionRecording>;\n /** Moves a running tab recording to another ready target. */\n readonly retargetSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n targetId: string,\n ) => Call<SessionRecording>;\n /**\n * Stops a recording and returns it at once with its raw video published. The edit runs\n * afterwards: the recording stays `editing` until `editedRelativePath` or `editError` is set,\n * which `getSessionRecording` reports.\n */\n readonly stopSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n ) => Call<SessionRecording>;\n readonly captionSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n input: RecordingCaptionInput,\n ) => Call<void>;\n readonly focusSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n input: RecordingFocusInput,\n ) => Call<void>;\n readonly attentionSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n input: RecordingAttentionInput,\n ) => Call<void>;\n /**\n * Every file and directory of the session, also while it is not running. See\n * `sessionFileTree`.\n */\n readonly listSessionFiles: (\n credentials: ApiCredentials,\n sessionId: string,\n ) => Call<ReadonlyArray<SessionFileEntry>>;\n /**\n * Stores files in a directory of the session's files, `uploads` by default, in any\n * retained state. Contents are sent as described for `SessionUploadFile`.\n */\n readonly uploadSessionFiles: (\n credentials: ApiCredentials,\n sessionId: string,\n files: ReadonlyArray<SessionUploadFile>,\n options?: UploadSessionFilesOptions,\n ) => Call<ReadonlyArray<SessionFile>>;\n /** Deletes one file, or a directory; a directory with entries needs `recursive`. */\n readonly deleteSessionFile: (\n credentials: ApiCredentials,\n sessionId: string,\n relativePath: string,\n options?: DeleteSessionFileOptions,\n ) => Call<void>;\n /** Moves or renames one file or directory. It never replaces an existing entry. */\n readonly moveSessionFile: (\n credentials: ApiCredentials,\n sessionId: string,\n input: MoveSessionFileInput,\n ) => Call<SessionFileEntry>;\n /** Creates a directory, with any missing parents. */\n readonly createSessionDirectory: (\n credentials: ApiCredentials,\n sessionId: string,\n relativePath: string,\n ) => Call<SessionDirectory>;\n /**\n * A signed URL that serves one session file without credentials until it expires.\n * `disposition: \"inline\"` makes it usable as an `<img>` or `<video>` source.\n */\n readonly createSessionFileDownloadURL: (\n credentials: ApiCredentials,\n sessionId: string,\n input: SessionFileDownloadURLInput,\n ) => Call<SessionFileDownloadURL>;\n readonly getBrowserChannels: (credentials: ApiCredentials) => Call<BrowserChannelsResponse>;\n /** Reads live or persisted page metadata without waking or keeping the session alive. */\n readonly getBrowserStatus: (\n credentials: ApiCredentials,\n sessionId: string,\n sessionToken?: Redacted.Redacted<string>,\n ) => Call<BrowserStatus>;\n readonly downloadSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n sessionToken?: Redacted.Redacted<string>,\n ) => Call<DownloadedFile>;\n /** A JPEG of the session, or of one tab when `targetId` is given. Never wakes a suspended session. */\n readonly getSessionThumbnail: (\n credentials: ApiCredentials,\n sessionId: string,\n targetId?: string,\n ) => Call<Blob>;\n /** The recording's bytes as they arrive, for files too large to hold in memory. */\n readonly streamSessionRecording: (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n sessionToken?: Redacted.Redacted<string>,\n ) => Stream.Stream<Uint8Array, ApiRequestError>;\n /**\n * Stores files in the running session's `uploads` directory through the session itself,\n * which also accepts its `sessionToken`.\n */\n readonly uploadLiveSessionFiles: (\n credentials: ApiCredentials,\n sessionId: string,\n files: ReadonlyArray<SessionUploadFile>,\n sessionToken?: Redacted.Redacted<string>,\n ) => Call<ReadonlyArray<SessionFile>>;\n /** Resizes a top-level target of the running session and returns the applied viewport. */\n readonly setSessionViewport: (\n credentials: ApiCredentials,\n sessionId: string,\n input: SetViewportInput,\n sessionToken?: Redacted.Redacted<string>,\n ) => Call<TargetViewport>;\n }\n>()(\"@aperture-browser/api-client/SessionsApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Random from \"effect/Random\";\nimport * as Stream from \"effect/Stream\";\nimport * as HttpBody from \"effect/http/HttpBody\";\nimport type { SessionUploadFile } from \"./service.ts\";\n\nconst encoder = new TextEncoder();\n\n// Percent-encodes the characters that would end the quoted filename or the header line,\n// as browsers do for FormData.\nconst quotedFilename = (name: string) =>\n name.replaceAll('\"', \"%22\").replaceAll(\"\\r\", \"%0D\").replaceAll(\"\\n\", \"%0A\");\n\nconst contentStream = (\n content: SessionUploadFile[\"content\"],\n): Stream.Stream<Uint8Array, unknown> => {\n if (content instanceof Blob) {\n return Stream.fromReadableStream({\n evaluate: () => content.stream(),\n onError: (cause) => cause,\n });\n }\n if (content instanceof Uint8Array) {\n return Stream.succeed(content);\n }\n return content;\n};\n\nconst streamedMultipart = Effect.fn(\"SessionsApi.streamedMultipart\")(function* (\n files: ReadonlyArray<SessionUploadFile>,\n) {\n const token = yield* Random.nextIntBetween(0, Number.MAX_SAFE_INTEGER);\n const boundary = `aperture-upload-${token.toString(36)}`;\n const parts = files.map((file) => {\n const header =\n `--${boundary}\\r\\n` +\n `Content-Disposition: form-data; name=\"files\"; filename=\"${quotedFilename(file.name)}\"\\r\\n` +\n \"Content-Type: application/octet-stream\\r\\n\\r\\n\";\n return Stream.succeed(encoder.encode(header)).pipe(\n Stream.concat(contentStream(file.content)),\n Stream.concat(Stream.succeed(encoder.encode(\"\\r\\n\"))),\n );\n });\n const body = Stream.fromIterable(parts).pipe(\n Stream.flatten(),\n Stream.concat(Stream.succeed(encoder.encode(`--${boundary}--\\r\\n`))),\n );\n return HttpBody.stream(body, `multipart/form-data; boundary=${boundary}`);\n});\n\n/**\n * The multipart body of an upload. FormData works with every fetch, so it is used unless a\n * content is a stream, which needs the body itself to be streamed.\n */\nexport const uploadBody = Effect.fn(\"SessionsApi.uploadBody\")(function* (\n files: ReadonlyArray<SessionUploadFile>,\n) {\n const form = new FormData();\n for (const file of files) {\n if (file.content instanceof Blob) {\n form.append(\"files\", file.content, file.name);\n } else if (file.content instanceof Uint8Array) {\n // Blob takes only views of an ArrayBuffer, not of a SharedArrayBuffer, so copy.\n form.append(\"files\", new Blob([new Uint8Array(file.content)]), file.name);\n } else {\n return yield* streamedMultipart(files);\n }\n }\n return HttpBody.formData(form);\n});\n","import * as Arr from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport type * as Redacted from \"effect/Redacted\";\nimport * as Schema from \"effect/Schema\";\nimport * as Stream from \"effect/Stream\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as HttpClientResponse from \"effect/http/HttpClientResponse\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { toApiRequestError } from \"../errors.ts\";\nimport { paginated } from \"../pagination.ts\";\nimport { compactQuery, tagQuery } from \"../query.ts\";\nimport type { Session, SetViewportInput, UpdateProxyConfig } from \"../schemas.ts\";\nimport { BrowserStatus } from \"./schemas.ts\";\nimport {\n SessionsApi,\n type CreateSessionInput,\n type CreateSessionOptions,\n type CreateSessionRecordingInput,\n type RecordingCaptionInput,\n type RecordingFocusInput,\n type RecordingAttentionInput,\n type DownloadedFile,\n type PromoteSessionInput,\n type SessionFileDownloadURLInput,\n type SessionsFilter,\n type SessionsListParams,\n type DeleteSessionFileOptions,\n type MoveSessionFileInput,\n type SessionUploadFile,\n type UploadSessionFilesOptions,\n} from \"./service.ts\";\nimport { uploadBody } from \"./uploads.ts\";\n\nexport const contentDispositionFilename = (header: string | undefined): string | null =>\n header?.match(/filename=\"([^\"]+)\"/)?.[1] ?? null;\n\nconst recordingContentPath = (sessionId: string, recordingId: string) =>\n `/sessions/${encodeURIComponent(sessionId)}/recordings/${encodeURIComponent(recordingId)}/content`;\n\nconst BULK_SESSION_IDS_LIMIT = 100;\n\nexport const makeSessionsApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const http = HttpClient.filterStatusOk(httpClient);\n const api = Api.make(httpClient);\n const tenantScoped = (credentials: ApiCredentials) =>\n authorize(Authorization.tenantScoped(credentials));\n\n const listSessions = Effect.fn(\"SessionsApi.listSessions\")(function* (\n credentials: ApiCredentials,\n params: SessionsListParams = {},\n ) {\n return yield* api\n .listSessions({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n includeDeleted: params.includeDeleted || undefined,\n status: params.status,\n query: params.query,\n ...tagQuery(params.tags),\n }),\n })\n .pipe(tenantScoped(credentials));\n });\n\n const sessions = paginated<SessionsFilter, Session>(listSessions);\n\n const exportSessionStorageState = Effect.fn(\"SessionsApi.exportSessionStorageState\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n input: Api.ExportSessionStorageStateInput,\n ) {\n return yield* api\n .exportSessionStorageState(sessionId, { payload: input })\n .pipe(tenantScoped(credentials));\n });\n\n const getSession = Effect.fn(\"SessionsApi.getSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.getSession(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const getSessionsBulk = Effect.fn(\"SessionsApi.getSessionsBulk\")(function* (\n credentials: ApiCredentials,\n sessionIds: readonly string[],\n ) {\n const responses = yield* Effect.forEach(\n Arr.chunksOf(sessionIds, BULK_SESSION_IDS_LIMIT),\n (ids) => api.getSessionsBulk({ payload: { ids } }).pipe(tenantScoped(credentials)),\n );\n return { sessions: responses.flatMap((response) => response.sessions) };\n });\n\n const createSession = Effect.fn(\"SessionsApi.createSession\")(function* (\n credentials: ApiCredentials,\n input: CreateSessionInput,\n options: CreateSessionOptions = {},\n ) {\n return yield* api\n .createSession({\n params: compactQuery({ waitForReady: options.waitForReady }),\n payload: Schema.encodeSync(Api.CreateSessionRequestJson)({\n baseSnapshotName: input.baseSnapshotName ?? null,\n label: input.label ?? null,\n browser: { channel: input.browser.channel, args: input.browser.args ?? [] },\n initialTargets: input.initialTargets ?? [],\n ...(input.storageState === undefined ? {} : { storageState: input.storageState }),\n tags: input.tags ?? {},\n ...(input.proxy === undefined ? {} : { proxy: input.proxy }),\n }),\n })\n .pipe(tenantScoped(credentials));\n });\n\n const deleteSession = Effect.fn(\"SessionsApi.deleteSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.deleteSession(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const reopenSession = Effect.fn(\"SessionsApi.reopenSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.reopenSession(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const suspendSession = Effect.fn(\"SessionsApi.suspendSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.suspendSession(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const rotateSessionToken = Effect.fn(\"SessionsApi.rotateSessionToken\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.rotateSessionToken(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const rotateCollaborationCapability = Effect.fn(\"SessionsApi.rotateCollaborationCapability\")(\n function* (credentials: ApiCredentials, sessionId: string, role: \"editor\" | \"viewer\") {\n return yield* api\n .rotateCollaborationCapability(sessionId, role, undefined)\n .pipe(tenantScoped(credentials));\n },\n );\n\n const replaceSessionTags = Effect.fn(\"SessionsApi.replaceSessionTags\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n tags: Record<string, string>,\n ) {\n return yield* api\n .replaceSessionTags(sessionId, { payload: { tags } })\n .pipe(tenantScoped(credentials));\n });\n\n const updateSessionProxy = Effect.fn(\"SessionsApi.updateSessionProxy\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n proxy: UpdateProxyConfig,\n ) {\n return yield* api\n .updateSessionProxy(sessionId, {\n payload: Schema.encodeSync(Api.UpdateSessionProxyRequestJson)(proxy),\n })\n .pipe(tenantScoped(credentials));\n });\n\n const promoteSession = Effect.fn(\"SessionsApi.promoteSession\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n input: PromoteSessionInput,\n ) {\n return yield* api\n .promoteSession(sessionId, {\n payload: {\n name: input.name,\n description: input.description ?? null,\n force: input.force ?? false,\n tags: input.tags ?? {},\n },\n })\n .pipe(tenantScoped(credentials));\n });\n\n const getSessionCursor = Effect.fn(\"SessionsApi.getSessionCursor\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.getSessionCursor(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const setSessionCursor = Effect.fn(\"SessionsApi.setSessionCursor\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n visible: boolean,\n ) {\n return yield* api\n .setSessionCursor(sessionId, { payload: { visible } })\n .pipe(tenantScoped(credentials));\n });\n\n const listSessionRecordings = Effect.fn(\"SessionsApi.listSessionRecordings\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.listSessionRecordings(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const createSessionRecording = Effect.fn(\"SessionsApi.createSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n input: CreateSessionRecordingInput,\n ) {\n return yield* api\n .createSessionRecording(sessionId, { payload: input })\n .pipe(tenantScoped(credentials));\n });\n\n const getSessionRecording = Effect.fn(\"SessionsApi.getSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n ) {\n return yield* api\n .getSessionRecording(sessionId, recordingId, undefined)\n .pipe(tenantScoped(credentials));\n });\n\n const retargetSessionRecording = Effect.fn(\"SessionsApi.retargetSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n targetId: string,\n ) {\n return yield* api\n .retargetSessionRecording(sessionId, recordingId, { payload: { targetId } })\n .pipe(tenantScoped(credentials));\n });\n\n const stopSessionRecording = Effect.fn(\"SessionsApi.stopSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n ) {\n return yield* api\n .stopSessionRecording(sessionId, recordingId, undefined)\n .pipe(tenantScoped(credentials));\n });\n\n const listSessionFiles = Effect.fn(\"SessionsApi.listSessionFiles\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n ) {\n return yield* api.listSessionFiles(sessionId, undefined).pipe(tenantScoped(credentials));\n });\n\n const captionSessionRecording = Effect.fn(\"SessionsApi.captionSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n input: RecordingCaptionInput,\n ) {\n yield* api\n .captionSessionRecording(sessionId, recordingId, { payload: input })\n .pipe(tenantScoped(credentials));\n });\n\n const focusSessionRecording = Effect.fn(\"SessionsApi.focusSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n input: RecordingFocusInput,\n ) {\n yield* api\n .focusSessionRecording(sessionId, recordingId, { payload: input })\n .pipe(tenantScoped(credentials));\n });\n\n const attentionSessionRecording = Effect.fn(\"SessionsApi.attentionSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n input: RecordingAttentionInput,\n ) {\n yield* api\n .attentionSessionRecording(sessionId, recordingId, { payload: input })\n .pipe(tenantScoped(credentials));\n });\n\n const createSessionFileDownloadURL = Effect.fn(\"SessionsApi.createSessionFileDownloadURL\")(\n function* (credentials: ApiCredentials, sessionId: string, input: SessionFileDownloadURLInput) {\n return yield* api\n .createSessionFileDownloadURL(sessionId, { payload: input })\n .pipe(tenantScoped(credentials));\n },\n );\n\n const getBrowserChannels = Effect.fn(\"SessionsApi.getBrowserChannels\")(function* (\n credentials: ApiCredentials,\n ) {\n return yield* api.listBrowserChannels(undefined).pipe(tenantScoped(credentials));\n });\n\n const getBrowserStatus = Effect.fn(\"SessionsApi.getBrowserStatus\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n sessionToken?: Redacted.Redacted<string>,\n ) {\n return yield* http\n .get(`/sessions/${encodeURIComponent(sessionId)}/browser/status`)\n .pipe(\n Effect.flatMap(HttpClientResponse.schemaBodyJson(BrowserStatus)),\n authorize({ credentials, bearerToken: sessionToken, tenantHeader: \"tenant-scoped\" }),\n );\n });\n\n const downloadSessionRecording = Effect.fn(\"SessionsApi.downloadSessionRecording\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n sessionToken?: Redacted.Redacted<string>,\n ) {\n return yield* http.get(recordingContentPath(sessionId, recordingId)).pipe(\n Effect.flatMap((response) =>\n Effect.map(\n response.arrayBuffer,\n (body): DownloadedFile => ({\n blob: new Blob([body], { type: response.headers[\"content-type\"] ?? \"\" }),\n filename: contentDispositionFilename(response.headers[\"content-disposition\"]),\n }),\n ),\n ),\n authorize({ credentials, bearerToken: sessionToken, tenantHeader: \"tenant-scoped\" }),\n );\n });\n\n const getSessionThumbnail = Effect.fn(\"SessionsApi.getSessionThumbnail\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n targetId?: string,\n ) {\n const session = `/api/sessions/${encodeURIComponent(sessionId)}`;\n const path =\n targetId === undefined\n ? `${session}/thumbnail`\n : `${session}/targets/${encodeURIComponent(targetId)}/thumbnail`;\n return yield* http.get(path).pipe(\n Effect.flatMap((response) =>\n Effect.map(response.arrayBuffer, (body) => new Blob([body], { type: \"image/jpeg\" })),\n ),\n authorize({ credentials, tenantHeader: \"tenant-scoped\" }),\n );\n });\n\n const streamSessionRecording = (\n credentials: ApiCredentials,\n sessionId: string,\n recordingId: string,\n sessionToken?: Redacted.Redacted<string>,\n ) =>\n http.get(recordingContentPath(sessionId, recordingId)).pipe(\n authorize({ credentials, bearerToken: sessionToken, tenantHeader: \"tenant-scoped\" }),\n Effect.map((response) =>\n response.stream.pipe(\n Stream.catchTag(\"HttpClientError\", (error) =>\n Stream.fromEffect(toApiRequestError(Effect.fail(error))),\n ),\n ),\n ),\n Stream.unwrap,\n );\n\n const uploadSessionFiles = Effect.fn(\"SessionsApi.uploadSessionFiles\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n files: ReadonlyArray<SessionUploadFile>,\n options: UploadSessionFilesOptions = {},\n ) {\n const body = yield* uploadBody(files);\n const response = yield* http\n .post(`/api/sessions/${encodeURIComponent(sessionId)}/files`, {\n body,\n urlParams: compactQuery({ directory: options.directory }),\n })\n .pipe(\n Effect.flatMap(HttpClientResponse.schemaBodyJson(Api.UploadSessionFiles201)),\n tenantScoped(credentials),\n );\n return response.files;\n });\n\n const deleteSessionFile = Effect.fn(\"SessionsApi.deleteSessionFile\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n relativePath: string,\n options: DeleteSessionFileOptions = {},\n ) {\n yield* api\n .deleteSessionFile(sessionId, {\n params: compactQuery({ relativePath, recursive: options.recursive }),\n })\n .pipe(tenantScoped(credentials));\n });\n\n const createSessionDirectory = Effect.fn(\"SessionsApi.createSessionDirectory\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n relativePath: string,\n ) {\n return yield* api\n .createSessionDirectory(sessionId, { payload: { relativePath } })\n .pipe(tenantScoped(credentials));\n });\n\n const moveSessionFile = Effect.fn(\"SessionsApi.moveSessionFile\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n input: MoveSessionFileInput,\n ) {\n return yield* api\n .moveSessionFile(sessionId, { payload: input })\n .pipe(tenantScoped(credentials));\n });\n\n const uploadLiveSessionFiles = Effect.fn(\"SessionsApi.uploadLiveSessionFiles\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n files: ReadonlyArray<SessionUploadFile>,\n sessionToken?: Redacted.Redacted<string>,\n ) {\n const body = yield* uploadBody(files);\n const response = yield* http\n .post(`/sessions/${encodeURIComponent(sessionId)}/uploads`, { body })\n .pipe(\n Effect.flatMap(HttpClientResponse.schemaBodyJson(Api.UploadLiveSessionFiles201)),\n authorize({ credentials, bearerToken: sessionToken, tenantHeader: \"tenant-scoped\" }),\n );\n return response.files;\n });\n\n const setSessionViewport = Effect.fn(\"SessionsApi.setSessionViewport\")(function* (\n credentials: ApiCredentials,\n sessionId: string,\n input: SetViewportInput,\n sessionToken?: Redacted.Redacted<string>,\n ) {\n return yield* api\n .setSessionViewport(sessionId, { payload: input })\n .pipe(authorize({ credentials, bearerToken: sessionToken, tenantHeader: \"tenant-scoped\" }));\n });\n\n return SessionsApi.of({\n listSessions,\n streamSessions: sessions.stream,\n listAllSessions: sessions.listAll,\n getSession,\n exportSessionStorageState,\n getSessionsBulk,\n createSession,\n deleteSession,\n reopenSession,\n suspendSession,\n rotateSessionToken,\n rotateCollaborationCapability,\n replaceSessionTags,\n updateSessionProxy,\n promoteSession,\n getSessionCursor,\n setSessionCursor,\n listSessionRecordings,\n createSessionRecording,\n getSessionRecording,\n retargetSessionRecording,\n stopSessionRecording,\n captionSessionRecording,\n focusSessionRecording,\n attentionSessionRecording,\n listSessionFiles,\n createSessionFileDownloadURL,\n getBrowserChannels,\n getBrowserStatus,\n downloadSessionRecording,\n getSessionThumbnail,\n streamSessionRecording,\n uploadSessionFiles,\n uploadLiveSessionFiles,\n deleteSessionFile,\n moveSessionFile,\n createSessionDirectory,\n setSessionViewport,\n });\n});\n\nexport const sessionsApiLayer = Layer.effect(SessionsApi, makeSessionsApi);\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type * as Option from \"effect/Option\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { PageCursor, PaginatedList } from \"../pagination.ts\";\nimport type { TagFilterValue } from \"../query.ts\";\nimport type { Snapshot, SnapshotMutationResponse } from \"../schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface SnapshotsFilter {\n limit?: number;\n includeDeleted?: boolean;\n deleted?: \"active\" | \"deleted\" | \"all\";\n name?: string;\n tags?: TagFilterValue;\n}\n\nexport type SnapshotsListParams = SnapshotsFilter & PageCursor;\n\ntype SnapshotsList = PaginatedList<SnapshotsFilter, Snapshot>;\n\nexport interface UpdateSnapshotInput {\n description: string | null;\n}\n\n/** Retained snapshots that new sessions start from. */\nexport class SnapshotsApi extends Context.Service<\n SnapshotsApi,\n {\n readonly listSnapshots: SnapshotsList[\"list\"];\n readonly streamSnapshots: SnapshotsList[\"stream\"];\n readonly listAllSnapshots: SnapshotsList[\"listAll\"];\n /** The active snapshot with exactly this name, if there is one. */\n readonly getSnapshotByName: (\n credentials: ApiCredentials,\n name: string,\n ) => Call<Option.Option<Snapshot>>;\n readonly updateSnapshot: (\n credentials: ApiCredentials,\n name: string,\n input: UpdateSnapshotInput,\n ) => Call<SnapshotMutationResponse>;\n readonly replaceSnapshotTags: (\n credentials: ApiCredentials,\n name: string,\n tags: Record<string, string>,\n ) => Call<SnapshotMutationResponse>;\n readonly deleteSnapshot: (\n credentials: ApiCredentials,\n name: string,\n ) => Call<SnapshotMutationResponse>;\n readonly restoreSnapshot: (\n credentials: ApiCredentials,\n name: string,\n ) => Call<SnapshotMutationResponse>;\n }\n>()(\"@aperture-browser/api-client/SnapshotsApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Stream from \"effect/Stream\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { paginated } from \"../pagination.ts\";\nimport { compactQuery, tagQuery } from \"../query.ts\";\nimport type { Snapshot } from \"../schemas.ts\";\nimport {\n SnapshotsApi,\n type SnapshotsFilter,\n type SnapshotsListParams,\n type UpdateSnapshotInput,\n} from \"./service.ts\";\n\nexport const makeSnapshotsApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n const tenantScoped = (credentials: ApiCredentials) =>\n authorize(Authorization.tenantScoped(credentials));\n\n const listSnapshots = Effect.fn(\"SnapshotsApi.listSnapshots\")(function* (\n credentials: ApiCredentials,\n params: SnapshotsListParams = {},\n ) {\n return yield* api\n .listSnapshots({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n includeDeleted: params.includeDeleted || undefined,\n deleted: params.deleted,\n name: params.name,\n ...tagQuery(params.tags),\n }),\n })\n .pipe(tenantScoped(credentials));\n });\n\n const snapshots = paginated<SnapshotsFilter, Snapshot>(listSnapshots);\n\n // The API has no lookup by name; its name filter is a case-insensitive substring match,\n // so the exact name is picked from the filtered pages.\n const getSnapshotByName = Effect.fn(\"SnapshotsApi.getSnapshotByName\")(function* (\n credentials: ApiCredentials,\n name: string,\n ) {\n return yield* snapshots.stream(credentials, { name, limit: 100 }).pipe(\n Stream.filter((candidate) => candidate.name === name),\n Stream.runHead,\n );\n });\n\n const updateSnapshot = Effect.fn(\"SnapshotsApi.updateSnapshot\")(function* (\n credentials: ApiCredentials,\n name: string,\n input: UpdateSnapshotInput,\n ) {\n return yield* api.updateSnapshot(name, { payload: input }).pipe(tenantScoped(credentials));\n });\n\n const replaceSnapshotTags = Effect.fn(\"SnapshotsApi.replaceSnapshotTags\")(function* (\n credentials: ApiCredentials,\n name: string,\n tags: Record<string, string>,\n ) {\n return yield* api\n .replaceSnapshotTags(name, { payload: { tags } })\n .pipe(tenantScoped(credentials));\n });\n\n const deleteSnapshot = Effect.fn(\"SnapshotsApi.deleteSnapshot\")(function* (\n credentials: ApiCredentials,\n name: string,\n ) {\n return yield* api.deleteSnapshot(name, undefined).pipe(tenantScoped(credentials));\n });\n\n const restoreSnapshot = Effect.fn(\"SnapshotsApi.restoreSnapshot\")(function* (\n credentials: ApiCredentials,\n name: string,\n ) {\n return yield* api.restoreSnapshot(name, undefined).pipe(tenantScoped(credentials));\n });\n\n return SnapshotsApi.of({\n listSnapshots,\n streamSnapshots: snapshots.stream,\n listAllSnapshots: snapshots.listAll,\n getSnapshotByName,\n updateSnapshot,\n replaceSnapshotTags,\n deleteSnapshot,\n restoreSnapshot,\n });\n});\n\nexport const snapshotsApiLayer = Layer.effect(SnapshotsApi, makeSnapshotsApi);\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type * as Api from \"@aperture-browser/api-schema\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { PageCursor, PaginatedList } from \"../pagination.ts\";\nimport type { Tenant } from \"../schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface TenantsFilter {\n limit?: number;\n includeDeleted?: boolean;\n deleted?: \"active\" | \"deleted\" | \"all\";\n query?: string;\n}\n\nexport type TenantsListParams = TenantsFilter & PageCursor;\n\ntype TenantsList = PaginatedList<TenantsFilter, Tenant>;\n\n/** Tenant administration, and the tenant a tenant token belongs to. */\nexport class TenantsApi extends Context.Service<\n TenantsApi,\n {\n readonly listTenants: TenantsList[\"list\"];\n readonly streamTenants: TenantsList[\"stream\"];\n readonly listAllTenants: TenantsList[\"listAll\"];\n readonly createTenant: (credentials: ApiCredentials, input: Api.TenantInput) => Call<Tenant>;\n readonly updateTenant: (\n credentials: ApiCredentials,\n tenantId: string,\n input: Api.TenantInput,\n ) => Call<Tenant>;\n readonly deleteTenant: (credentials: ApiCredentials, tenantId: string) => Call<Tenant>;\n readonly restoreTenant: (credentials: ApiCredentials, tenantId: string) => Call<Tenant>;\n /** The tenant of a tenant token. */\n readonly getCurrentTenant: (credentials: ApiCredentials) => Call<Tenant>;\n readonly updateCurrentTenant: (\n credentials: ApiCredentials,\n input: Api.TenantInput,\n ) => Call<Tenant>;\n }\n>()(\"@aperture-browser/api-client/TenantsApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { paginated } from \"../pagination.ts\";\nimport { compactQuery } from \"../query.ts\";\nimport type { Tenant } from \"../schemas.ts\";\nimport { TenantsApi, type TenantsFilter, type TenantsListParams } from \"./service.ts\";\n\nexport const makeTenantsApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const listTenants = Effect.fn(\"TenantsApi.listTenants\")(function* (\n credentials: ApiCredentials,\n params: TenantsListParams = {},\n ) {\n return yield* api\n .listTenants({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n includeDeleted: params.includeDeleted || undefined,\n deleted: params.deleted,\n query: params.query,\n }),\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const tenants = paginated<TenantsFilter, Tenant>(listTenants);\n\n const getCurrentTenant = Effect.fn(\"TenantsApi.getCurrentTenant\")(function* (\n credentials: ApiCredentials,\n ) {\n return yield* api.getTenant(undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const updateCurrentTenant = Effect.fn(\"TenantsApi.updateCurrentTenant\")(function* (\n credentials: ApiCredentials,\n input: Api.TenantInput,\n ) {\n return yield* api\n .updateSelectedTenant({ payload: input })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const createTenant = Effect.fn(\"TenantsApi.createTenant\")(function* (\n credentials: ApiCredentials,\n input: Api.TenantInput,\n ) {\n return yield* api\n .createTenant({ payload: input })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const updateTenant = Effect.fn(\"TenantsApi.updateTenant\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n input: Api.TenantInput,\n ) {\n return yield* api\n .updateTenant(tenantId, { payload: input })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const deleteTenant = Effect.fn(\"TenantsApi.deleteTenant\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n ) {\n return yield* api\n .deleteTenant(tenantId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const restoreTenant = Effect.fn(\"TenantsApi.restoreTenant\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n ) {\n return yield* api\n .restoreTenant(tenantId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n return TenantsApi.of({\n listTenants,\n streamTenants: tenants.stream,\n listAllTenants: tenants.listAll,\n createTenant,\n updateTenant,\n deleteTenant,\n restoreTenant,\n getCurrentTenant,\n updateCurrentTenant,\n });\n});\n\nexport const tenantsApiLayer = Layer.effect(TenantsApi, makeTenantsApi);\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { PageCursor, PaginatedList } from \"../pagination.ts\";\nimport type { ApiToken, CreateTokenResponse, ResourceGrant, ResourceMode } from \"../schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface TokensFilter {\n limit?: number;\n tenantId?: string;\n name?: string;\n authorityType?: \"system_admin\" | \"tenant\";\n revoked?: \"all\" | \"active\" | \"revoked\";\n scope?: string;\n}\n\nexport type TokensListParams = TokensFilter & PageCursor;\n\ntype TokensList = PaginatedList<TokensFilter, ApiToken>;\n\nexport interface CreateAdminTokenInput {\n name: string;\n authorityType: \"system_admin\" | \"tenant\";\n tenantId?: string | null;\n scopes: string[];\n resourceMode: ResourceMode;\n resourceGrants: ResourceGrant[];\n expiresAt?: string | null;\n}\n\nexport interface CreateTenantTokenInput {\n name: string;\n scopes: string[];\n resourceMode: ResourceMode;\n resourceGrants: ResourceGrant[];\n expiresAt?: string | null;\n}\n\n/** API tokens, issued either deployment-wide or within the current tenant. */\nexport class TokensApi extends Context.Service<\n TokensApi,\n {\n readonly listAdminTokens: TokensList[\"list\"];\n readonly streamAdminTokens: TokensList[\"stream\"];\n readonly listAllAdminTokens: TokensList[\"listAll\"];\n readonly createAdminToken: (\n credentials: ApiCredentials,\n input: CreateAdminTokenInput,\n ) => Call<CreateTokenResponse>;\n readonly revokeAdminToken: (credentials: ApiCredentials, tokenId: string) => Call<void>;\n readonly listTenantTokens: TokensList[\"list\"];\n readonly streamTenantTokens: TokensList[\"stream\"];\n readonly listAllTenantTokens: TokensList[\"listAll\"];\n readonly createTenantToken: (\n credentials: ApiCredentials,\n input: CreateTenantTokenInput,\n ) => Call<CreateTokenResponse>;\n readonly revokeTenantToken: (credentials: ApiCredentials, tokenId: string) => Call<void>;\n }\n>()(\"@aperture-browser/api-client/TokensApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { paginated } from \"../pagination.ts\";\nimport { compactQuery } from \"../query.ts\";\nimport type { ApiToken } from \"../schemas.ts\";\nimport {\n TokensApi,\n type CreateAdminTokenInput,\n type CreateTenantTokenInput,\n type TokensFilter,\n type TokensListParams,\n} from \"./service.ts\";\n\n// Filters and scopes arrive from free-form UI state; the server validates them, so they\n// are sent as the generated request types without narrowing.\n\nexport const makeTokensApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const listAdminTokens = Effect.fn(\"TokensApi.listAdminTokens\")(function* (\n credentials: ApiCredentials,\n params: TokensListParams = {},\n ) {\n return yield* api\n .listAdminTokens({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n tenantId: params.tenantId,\n name: params.name,\n authorityType: params.authorityType,\n revoked: params.revoked,\n scope: params.scope,\n }) as typeof Api.ListAdminTokensParams.Encoded,\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const adminTokens = paginated<TokensFilter, ApiToken>(listAdminTokens);\n\n const createAdminToken = Effect.fn(\"TokensApi.createAdminToken\")(function* (\n credentials: ApiCredentials,\n input: CreateAdminTokenInput,\n ) {\n const systemAdmin = input.authorityType === \"system_admin\";\n return yield* api\n .createAdminToken({\n payload: {\n name: input.name,\n authorityType: input.authorityType,\n tenantId: input.tenantId ?? null,\n scopes: input.scopes,\n resourceMode: systemAdmin ? \"all\" : input.resourceMode,\n resourceGrants: systemAdmin ? [] : input.resourceGrants,\n expiresAt: input.expiresAt ?? null,\n } as typeof Api.CreateAdminTokenRequestJson.Encoded,\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const revokeAdminToken = Effect.fn(\"TokensApi.revokeAdminToken\")(function* (\n credentials: ApiCredentials,\n tokenId: string,\n ) {\n yield* api.revokeAdminToken(tokenId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const listTenantTokens = Effect.fn(\"TokensApi.listTenantTokens\")(function* (\n credentials: ApiCredentials,\n params: TokensListParams = {},\n ) {\n return yield* api\n .listTenantTokens({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n name: params.name,\n revoked: params.revoked,\n scope: params.scope,\n }) as typeof Api.ListTenantTokensParams.Encoded,\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const tenantTokens = paginated<TokensFilter, ApiToken>(listTenantTokens);\n\n const createTenantToken = Effect.fn(\"TokensApi.createTenantToken\")(function* (\n credentials: ApiCredentials,\n input: CreateTenantTokenInput,\n ) {\n return yield* api\n .createTenantToken({\n payload: {\n name: input.name,\n scopes: input.scopes,\n resourceMode: input.resourceMode,\n resourceGrants: input.resourceGrants,\n expiresAt: input.expiresAt ?? null,\n } as typeof Api.CreateTenantTokenRequestJson.Encoded,\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const revokeTenantToken = Effect.fn(\"TokensApi.revokeTenantToken\")(function* (\n credentials: ApiCredentials,\n tokenId: string,\n ) {\n yield* api.revokeTenantToken(tokenId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n return TokensApi.of({\n listAdminTokens,\n streamAdminTokens: adminTokens.stream,\n listAllAdminTokens: adminTokens.listAll,\n createAdminToken,\n revokeAdminToken,\n listTenantTokens,\n streamTenantTokens: tenantTokens.stream,\n listAllTenantTokens: tenantTokens.listAll,\n createTenantToken,\n revokeTenantToken,\n });\n});\n\nexport const tokensApiLayer = Layer.effect(TokensApi, makeTokensApi);\n","import * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { ApiCredentials } from \"../authorization/service.ts\";\nimport type { ApiRequestError } from \"../errors.ts\";\nimport type { PageCursor, PaginatedList } from \"../pagination.ts\";\nimport type { TenantMembership, User, UserInvitation } from \"../schemas.ts\";\n\ntype Call<A> = Effect.Effect<A, ApiRequestError>;\n\nexport interface UsersFilter {\n limit?: number;\n query?: string;\n disabled?: \"active\" | \"disabled\" | \"all\";\n}\n\nexport type UsersListParams = UsersFilter & PageCursor;\n\ntype UsersList = PaginatedList<UsersFilter, User>;\n\nexport interface UserInput {\n email: string | null;\n displayName: string;\n isSystemAdmin: boolean;\n}\n\n/** User administration and tenant memberships. */\nexport class UsersApi extends Context.Service<\n UsersApi,\n {\n readonly listUsers: UsersList[\"list\"];\n readonly streamUsers: UsersList[\"stream\"];\n readonly listAllUsers: UsersList[\"listAll\"];\n readonly createUser: (credentials: ApiCredentials, input: UserInput) => Call<User>;\n readonly getUser: (credentials: ApiCredentials, userId: string) => Call<User>;\n readonly updateUser: (\n credentials: ApiCredentials,\n userId: string,\n input: UserInput,\n ) => Call<User>;\n readonly createUserInvitation: (\n credentials: ApiCredentials,\n userId: string,\n ) => Call<UserInvitation>;\n readonly disableUser: (credentials: ApiCredentials, userId: string) => Call<User>;\n readonly restoreUser: (credentials: ApiCredentials, userId: string) => Call<User>;\n readonly listUserMemberships: (\n credentials: ApiCredentials,\n userId: string,\n ) => Call<ReadonlyArray<TenantMembership>>;\n readonly listTenantMemberships: (\n credentials: ApiCredentials,\n tenantId: string,\n ) => Call<ReadonlyArray<TenantMembership>>;\n readonly upsertTenantMembership: (\n credentials: ApiCredentials,\n tenantId: string,\n userId: string,\n scopes: readonly string[],\n ) => Call<TenantMembership>;\n readonly deleteTenantMembership: (\n credentials: ApiCredentials,\n tenantId: string,\n userId: string,\n ) => Call<void>;\n }\n>()(\"@aperture-browser/api-client/UsersApi\") {}\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as Api from \"@aperture-browser/api-schema\";\nimport { ApiAuthorization, Authorization, type ApiCredentials } from \"../authorization/service.ts\";\nimport { paginated } from \"../pagination.ts\";\nimport { compactQuery } from \"../query.ts\";\nimport type { User } from \"../schemas.ts\";\nimport { UsersApi, type UserInput, type UsersFilter, type UsersListParams } from \"./service.ts\";\n\nexport const makeUsersApi = Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const { authorize } = yield* ApiAuthorization;\n const api = Api.make(httpClient);\n\n const listUsers = Effect.fn(\"UsersApi.listUsers\")(function* (\n credentials: ApiCredentials,\n params: UsersListParams = {},\n ) {\n return yield* api\n .listUsers({\n params: compactQuery({\n limit: params.limit,\n cursor: params.cursor,\n query: params.query,\n disabled: params.disabled,\n }),\n })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const users = paginated<UsersFilter, User>(listUsers);\n\n const createUser = Effect.fn(\"UsersApi.createUser\")(function* (\n credentials: ApiCredentials,\n input: UserInput,\n ) {\n return yield* api.createUser({ payload: input }).pipe(authorize(Authorization.of(credentials)));\n });\n\n const getUser = Effect.fn(\"UsersApi.getUser\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api.getUser(userId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const updateUser = Effect.fn(\"UsersApi.updateUser\")(function* (\n credentials: ApiCredentials,\n userId: string,\n input: UserInput,\n ) {\n return yield* api\n .updateUser(userId, { payload: input })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const createUserInvitation = Effect.fn(\"UsersApi.createUserInvitation\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api\n .createUserInvitation(userId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const disableUser = Effect.fn(\"UsersApi.disableUser\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api.disableUser(userId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const restoreUser = Effect.fn(\"UsersApi.restoreUser\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api.restoreUser(userId, undefined).pipe(authorize(Authorization.of(credentials)));\n });\n\n const listUserMemberships = Effect.fn(\"UsersApi.listUserMemberships\")(function* (\n credentials: ApiCredentials,\n userId: string,\n ) {\n return yield* api\n .listUserMemberships(userId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const listTenantMemberships = Effect.fn(\"UsersApi.listTenantMemberships\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n ) {\n return yield* api\n .listTenantMemberships(tenantId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const upsertTenantMembership = Effect.fn(\"UsersApi.upsertTenantMembership\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n userId: string,\n scopes: readonly string[],\n ) {\n // Scopes arrive from free-form UI state; the server validates them.\n const payload = { scopes } as typeof Api.UpsertTenantMembershipRequestJson.Encoded;\n return yield* api\n .upsertTenantMembership(tenantId, userId, { payload })\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n const deleteTenantMembership = Effect.fn(\"UsersApi.deleteTenantMembership\")(function* (\n credentials: ApiCredentials,\n tenantId: string,\n userId: string,\n ) {\n yield* api\n .deleteTenantMembership(tenantId, userId, undefined)\n .pipe(authorize(Authorization.of(credentials)));\n });\n\n return UsersApi.of({\n listUsers,\n streamUsers: users.stream,\n listAllUsers: users.listAll,\n createUser,\n getUser,\n updateUser,\n createUserInvitation,\n disableUser,\n restoreUser,\n listUserMemberships,\n listTenantMemberships,\n upsertTenantMembership,\n deleteTenantMembership,\n });\n});\n\nexport const usersApiLayer = Layer.effect(UsersApi, makeUsersApi);\n","import * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as HttpClientRequest from \"effect/http/HttpClientRequest\";\nimport { authApiLayer } from \"./auth/layer.ts\";\nimport { apiAuthorizationLayer, authorizedHttpClientLayer } from \"./authorization/layer.ts\";\nimport { eventsApiLayer } from \"./events/layer.ts\";\nimport { healthApiLayer } from \"./health/layer.ts\";\nimport { sessionsApiLayer } from \"./sessions/layer.ts\";\nimport { snapshotsApiLayer } from \"./snapshots/layer.ts\";\nimport { tenantsApiLayer } from \"./tenants/layer.ts\";\nimport { tokensApiLayer } from \"./tokens/layer.ts\";\nimport { usersApiLayer } from \"./users/layer.ts\";\n\n/**\n * Every API service, sharing one ApiAuthorization. The services send requests through the\n * HttpClient the app provides, decorated with each call's authorization.\n */\nexport const apiClientLayer = Layer.mergeAll(\n authApiLayer,\n tenantsApiLayer,\n usersApiLayer,\n sessionsApiLayer,\n snapshotsApiLayer,\n tokensApiLayer,\n eventsApiLayer,\n healthApiLayer,\n).pipe(Layer.provide(authorizedHttpClientLayer), Layer.provideMerge(apiAuthorizationLayer));\n\nexport type ApiServices = Layer.Success<typeof apiClientLayer>;\n\nexport const baseUrlLayer = (baseUrl: string) =>\n Layer.effect(\n HttpClient.HttpClient,\n Effect.map(HttpClient.HttpClient, HttpClient.mapRequest(HttpClientRequest.prependUrl(baseUrl))),\n );\n","import * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport { AuthApi } from \"./auth/service.ts\";\nimport type { ApiCredentials } from \"./authorization/service.ts\";\nimport type { ApiRequestError } from \"./errors.ts\";\nimport { EventsApi } from \"./events/service.ts\";\nimport { HealthApi } from \"./health/service.ts\";\nimport { apiClientLayer } from \"./layer.ts\";\nimport type { AuthMeResponse } from \"./schemas.ts\";\nimport { SessionsApi } from \"./sessions/service.ts\";\nimport { SnapshotsApi } from \"./snapshots/service.ts\";\nimport { TenantsApi } from \"./tenants/service.ts\";\nimport { TokensApi } from \"./tokens/service.ts\";\nimport { UsersApi } from \"./users/service.ts\";\n\ntype CredentialedMethod = (credentials: ApiCredentials, ...args: never[]) => unknown;\n\n/** A service whose methods have their leading credentials argument already applied. */\nexport type WithCredentials<S> = {\n readonly [K in keyof S]: S[K] extends (\n credentials: ApiCredentials,\n ...args: infer Args\n ) => infer Result\n ? (...args: Args) => Result\n : never;\n};\n\n/** Binds `credentials` as the first argument of every method of `service`. */\nexport function withCredentials<S extends { readonly [K in keyof S]: CredentialedMethod }>(\n service: S,\n credentials: ApiCredentials,\n): WithCredentials<S> {\n const methods: ReadonlyArray<[string, CredentialedMethod]> = Object.entries(service);\n const bound = Object.fromEntries(\n methods.map(([name, method]) => [name, (...args: never[]) => method(credentials, ...args)]),\n );\n // Object.fromEntries forgets the per-method signatures that WithCredentials restores.\n return bound as WithCredentials<S>;\n}\n\n/**\n * The credentialed API services with one set of credentials bound, for callers that always\n * act as the same principal, such as a server holding one API token.\n */\nexport class ApertureClient extends Context.Service<\n ApertureClient,\n {\n readonly sessions: WithCredentials<SessionsApi[\"Service\"]>;\n readonly snapshots: WithCredentials<SnapshotsApi[\"Service\"]>;\n readonly tenants: WithCredentials<TenantsApi[\"Service\"]>;\n readonly users: WithCredentials<UsersApi[\"Service\"]>;\n readonly tokens: WithCredentials<TokensApi[\"Service\"]>;\n readonly events: WithCredentials<EventsApi[\"Service\"]>;\n /** The calls of AuthApi that work with API credentials rather than a browser login. */\n readonly auth: {\n readonly getAuthMe: () => Effect.Effect<AuthMeResponse, ApiRequestError>;\n };\n readonly health: HealthApi[\"Service\"];\n }\n>()(\"@aperture-browser/api-client/ApertureClient\") {}\n\nexport const makeApertureClient = Effect.fn(\"makeApertureClient\")(function* (\n credentials: ApiCredentials,\n) {\n const auth = yield* AuthApi;\n return ApertureClient.of({\n sessions: withCredentials(yield* SessionsApi, credentials),\n snapshots: withCredentials(yield* SnapshotsApi, credentials),\n tenants: withCredentials(yield* TenantsApi, credentials),\n users: withCredentials(yield* UsersApi, credentials),\n tokens: withCredentials(yield* TokensApi, credentials),\n events: withCredentials(yield* EventsApi, credentials),\n auth: {\n getAuthMe: () => auth.getAuthMe(credentials.selectedTenantId, credentials),\n },\n health: yield* HealthApi,\n });\n});\n\n/** ApertureClient acting with `credentials`, over the HttpClient the app provides. */\nexport const apertureClientLayer = (credentials: ApiCredentials) =>\n Layer.effect(ApertureClient, makeApertureClient(credentials)).pipe(Layer.provide(apiClientLayer));\n","import * as Api from \"@aperture-browser/api-schema\";\n\n// Resources described by api/openapi.yaml, under the names the app uses.\n\nexport type PageMeta = Api.PageMeta;\nexport type Tenant = Api.Tenant;\nexport type User = Api.User;\nexport type UserInvitation = Api.UserInvitation;\nexport type TenantMembership = Api.TenantMembership;\nexport type AuthMeResponse = Api.AuthMe;\nexport type AuthMePrincipal = Api.Principal;\nexport type AuthMeTenant = Api.Tenant;\nexport type ResourceMode = Api.ResourceMode;\nexport type ResourceGrant = Api.ResourceGrant;\nexport type Scope = Api.Scope;\nexport type TenantScope = Api.TenantScope;\nexport type Session = Api.Session;\nexport type SessionMedia = Api.SessionMedia;\nexport type SessionProxy = Api.SessionProxy;\nexport type ProxyConfig = Api.ProxyConfig;\nexport type UpdateProxyConfig = Api.UpdateProxyConfig;\nexport type ProxyUpstream = Api.ProxyUpstream;\nexport type ProxyRule = Api.ProxyRule;\nexport type CursorVisibility = Api.CursorVisibility;\nexport type SessionRecording = Api.Recording;\nexport type SessionFile = Api.SessionFile;\nexport type SessionRecordingEditError = Api.RecordingEditError;\nexport type SessionDirectory = Api.SessionDirectory;\nexport type SessionFileEntry = Api.SessionFileEntry;\nexport type SessionFileDownloadURL = Api.SessionFileDownloadURL;\nexport type SetViewportInput = Api.SetViewportInput;\nexport type TargetViewport = Api.TargetViewport;\nexport type Health = Api.Health;\nexport type AuditEvent = Api.AuditEvent;\nexport type AuditEventsPage = Api.AuditEventPage;\nexport type IceServer = Api.IceServer;\nexport const SessionStatus = Api.SessionStatus;\nexport type SessionStatus = Api.SessionStatus;\nexport type Snapshot = Api.Snapshot;\nexport type ApiToken = Api.Token;\nexport type TenantsPage = Api.TenantPage;\nexport type UsersPage = Api.UserPage;\nexport type SessionsPage = Api.SessionPage;\nexport type SessionsBulkResponse = Api.SessionBulkResponse;\nexport type SnapshotsPage = Api.SnapshotPage;\nexport type TokensPage = Api.TokenPage;\nexport type BrowserChannel = Api.BrowserChannel;\nexport type BrowserChannelsResponse = Api.BrowserChannels;\nexport type ResourceEvent = Api.Event;\nexport type EventsPage = Api.EventPage;\nexport type CreateSessionResponse = Api.CreateSessionResult;\nexport type SessionMutationResponse = Api.SessionMutation;\nexport type SnapshotMutationResponse = Api.SnapshotMutation;\nexport type PromoteSessionResponse = Api.SnapshotMutation;\nexport type CreateTokenResponse = Api.CreateTokenResponse;\n","import type { SessionDirectory, SessionFile, SessionFileEntry } from \"../schemas.ts\";\n\n/**\n * The top-level directories the session writes into. They always exist and cannot be\n * deleted, moved or renamed.\n */\nexport const sessionFileRootDirectories = [\n \"downloads\",\n \"recordings\",\n \"uploads\",\n \"outputs\",\n] as const;\n\nexport interface SessionFileDirectoryNode {\n readonly kind: \"directory\";\n readonly name: string;\n readonly relativePath: string;\n /** Absent for a directory known only from the paths of legacy files. */\n readonly directory: SessionDirectory | undefined;\n readonly children: ReadonlyArray<SessionFileTreeNode>;\n}\n\nexport interface SessionFileNode {\n readonly kind: \"file\";\n readonly name: string;\n readonly relativePath: string;\n readonly file: SessionFile;\n}\n\nexport type SessionFileTreeNode = SessionFileDirectoryNode | SessionFileNode;\n\ninterface DirectoryBuilder {\n directory: SessionDirectory | undefined;\n readonly directories: Map<string, DirectoryBuilder>;\n readonly files: Array<SessionFileNode>;\n}\n\nconst emptyDirectory = (): DirectoryBuilder => ({\n directory: undefined,\n directories: new Map(),\n files: [],\n});\n\nfunction directoryAt(root: DirectoryBuilder, segments: ReadonlyArray<string>): DirectoryBuilder {\n let directory = root;\n for (const segment of segments) {\n let child = directory.directories.get(segment);\n if (child === undefined) {\n child = emptyDirectory();\n directory.directories.set(segment, child);\n }\n directory = child;\n }\n return directory;\n}\n\nfunction toNodes(directory: DirectoryBuilder, parentPath: string): Array<SessionFileTreeNode> {\n const directories = [...directory.directories.entries()]\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([name, child]): SessionFileDirectoryNode => {\n const relativePath = parentPath === \"\" ? name : `${parentPath}/${name}`;\n return {\n kind: \"directory\",\n name,\n relativePath,\n directory: child.directory,\n children: toNodes(child, relativePath),\n };\n });\n const files = [...directory.files].sort((left, right) => left.name.localeCompare(right.name));\n return [...directories, ...files];\n}\n\n/**\n * Arranges `listSessionFiles` results into a tree: directories first, then files, each\n * sorted by name. Empty directories appear because the listing includes them.\n */\nexport function sessionFileTree(\n entries: ReadonlyArray<SessionFileEntry>,\n): ReadonlyArray<SessionFileTreeNode> {\n const root = emptyDirectory();\n for (const entry of entries) {\n const segments = entry.relativePath.split(\"/\");\n if (entry.type === \"directory\") {\n directoryAt(root, segments).directory = entry;\n continue;\n }\n const name = segments.pop() ?? entry.relativePath;\n directoryAt(root, segments).files.push({\n kind: \"file\",\n name,\n relativePath: entry.relativePath,\n file: entry,\n });\n }\n return toNodes(root, \"\");\n}\n"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { Ct as ApiRequestError, t as AuthApi } from "./service-DbyEmdKS.js";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Schema from "effect/Schema";
4
+
5
+ //#region src/passkeys.d.ts
6
+ declare const PasskeyCeremonyError_base: Schema.Class<PasskeyCeremonyError, Schema.TaggedStruct<"PasskeyCeremonyError", {
7
+ readonly ceremony: Schema.Literals<readonly ["authentication", "registration"]>;
8
+ readonly reason: Schema.Literals<readonly ["cancelled", "failed"]>;
9
+ readonly message: Schema.String;
10
+ readonly cause: Schema.Defect;
11
+ }>, import("effect/Cause").YieldableError>;
12
+ /**
13
+ * The browser did not complete the WebAuthn ceremony. `cancelled` covers the user
14
+ * dismissing the prompt or letting it time out; anything else is `failed`.
15
+ */
16
+ declare class PasskeyCeremonyError extends PasskeyCeremonyError_base {}
17
+ /** Signs the browser in with a passkey, establishing the web session. */
18
+ declare const loginWithPasskey: () => Effect.Effect<void, PasskeyCeremonyError | ApiRequestError, AuthApi>;
19
+ /** Creates a passkey on this device and registers it for the signed-in user. */
20
+ declare const registerPasskey: (name: string) => Effect.Effect<{
21
+ readonly passkey: {
22
+ readonly id: string;
23
+ readonly name: string;
24
+ readonly createdAt: string;
25
+ readonly lastUsedAt: string | null;
26
+ };
27
+ }, PasskeyCeremonyError | ApiRequestError, AuthApi>;
28
+ //#endregion
29
+ export { PasskeyCeremonyError, loginWithPasskey, registerPasskey };
30
+ //# sourceMappingURL=passkeys.d.ts.map