@aperture-browser/api-client 0.0.0-nightly.100.78b4e7ef6edc → 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.d.ts CHANGED
@@ -291,6 +291,19 @@ declare const tagQuery: (tags: TagFilterValue | undefined) => {
291
291
  declare const compactQuery: <T extends object>(query: T) => T;
292
292
  //#endregion
293
293
  //#region src/sessions/schemas.d.ts
294
+ declare const RecordingSettings: Schema.Struct<{
295
+ readonly capture: Schema.optionalKey<Schema.Literals<readonly ["continuous", "bursts"]>>;
296
+ readonly presentation: Schema.optionalKey<Schema.Boolean>;
297
+ readonly idle: Schema.optionalKey<Schema.Literals<readonly ["cut", "speed"]>>;
298
+ readonly ripple: Schema.optionalKey<Schema.Boolean>;
299
+ readonly burst: Schema.optionalKey<Schema.Struct<{
300
+ readonly leadMs: Schema.optionalKey<Schema.Number>;
301
+ readonly tailMs: Schema.optionalKey<Schema.Number>;
302
+ readonly settleMs: Schema.optionalKey<Schema.Number>;
303
+ readonly maxTailMs: Schema.optionalKey<Schema.Number>;
304
+ }>>;
305
+ }>;
306
+ type RecordingSettings = typeof RecordingSettings.Type;
294
307
  declare const BrowserPage: Schema.Struct<{
295
308
  readonly targetId: Schema.String;
296
309
  readonly state: Schema.Literals<readonly ["pending", "ready", "unavailable", "closed"]>;
@@ -496,6 +509,9 @@ interface PromoteSessionInput {
496
509
  tags?: Record<string, string>;
497
510
  }
498
511
  type CreateSessionRecordingInput = Api.CreateSessionRecordingInput;
512
+ type RecordingCaptionInput = Api.RecordingCaptionInput;
513
+ type RecordingFocusInput = Api.RecordingFocusInput;
514
+ type RecordingAttentionInput = Api.RecordingAttentionInput;
499
515
  type SessionFileDownloadURLInput = Api.SessionFileDownloadURLInput;
500
516
  interface DownloadedFile {
501
517
  blob: Blob;
@@ -547,6 +563,9 @@ declare const SessionsApi_base: Context.ServiceClass<SessionsApi, "@aperture-bro
547
563
  * which `getSessionRecording` reports.
548
564
  */
549
565
  readonly stopSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string) => Call$4<SessionRecording>;
566
+ readonly captionSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string, input: RecordingCaptionInput) => Call$4<void>;
567
+ readonly focusSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string, input: RecordingFocusInput) => Call$4<void>;
568
+ readonly attentionSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string, input: RecordingAttentionInput) => Call$4<void>;
550
569
  /**
551
570
  * Every file and directory of the session, also while it is not running. See
552
571
  * `sessionFileTree`.
@@ -740,7 +759,7 @@ declare const makeApertureClient: (credentials: ApiCredentials) => Effect.Effect
740
759
  readonly getAuthMe: () => Effect.Effect<AuthMeResponse, ApiRequestError>;
741
760
  };
742
761
  readonly health: HealthApi["Service"];
743
- }, never, AuthApi | EventsApi | UsersApi | HealthApi | SessionsApi | SnapshotsApi | TenantsApi | TokensApi>;
762
+ }, never, AuthApi | HealthApi | SessionsApi | SnapshotsApi | TenantsApi | UsersApi | TokensApi | EventsApi>;
744
763
  /** ApertureClient acting with `credentials`, over the HttpClient the app provides. */
745
764
  declare const apertureClientLayer: (credentials: ApiCredentials) => Layer.Layer<ApertureClient, never, import("effect/http/HttpClient").HttpClient>;
746
765
  //#endregion
@@ -766,7 +785,7 @@ declare const healthApiLayer: Layer.Layer<HealthApi, never, ApiAuthorization | H
766
785
  * Every API service, sharing one ApiAuthorization. The services send requests through the
767
786
  * HttpClient the app provides, decorated with each call's authorization.
768
787
  */
769
- declare const apiClientLayer: Layer.Layer<AuthApi | ApiAuthorization | EventsApi | UsersApi | HealthApi | SessionsApi | SnapshotsApi | TenantsApi | TokensApi, never, HttpClient.HttpClient>;
788
+ declare const apiClientLayer: Layer.Layer<AuthApi | ApiAuthorization | HealthApi | SessionsApi | SnapshotsApi | TenantsApi | UsersApi | TokensApi | EventsApi, never, HttpClient.HttpClient>;
770
789
  type ApiServices = Layer.Success<typeof apiClientLayer>;
771
790
  declare const baseUrlLayer: (baseUrl: string) => Layer.Layer<HttpClient.HttpClient, never, HttpClient.HttpClient>;
772
791
  //#endregion
@@ -795,6 +814,9 @@ declare const makeSessionsApi: Effect.Effect<{
795
814
  readonly getSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string) => Effect.Effect<Api.Recording, ApiRequestError, never>;
796
815
  readonly retargetSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string, targetId: string) => Effect.Effect<Api.Recording, ApiRequestError, never>;
797
816
  readonly stopSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string) => Effect.Effect<Api.Recording, ApiRequestError, never>;
817
+ readonly captionSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string, input: RecordingCaptionInput) => Effect.Effect<void, ApiRequestError, never>;
818
+ readonly focusSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string, input: RecordingFocusInput) => Effect.Effect<void, ApiRequestError, never>;
819
+ readonly attentionSessionRecording: (credentials: ApiCredentials, sessionId: string, recordingId: string, input: RecordingAttentionInput) => Effect.Effect<void, ApiRequestError, never>;
798
820
  readonly listSessionFiles: (credentials: ApiCredentials, sessionId: string) => Effect.Effect<readonly Api.SessionFileEntry[], ApiRequestError, never>;
799
821
  readonly uploadSessionFiles: (credentials: ApiCredentials, sessionId: string, files: ReadonlyArray<SessionUploadFile>, options?: UploadSessionFilesOptions) => Effect.Effect<readonly Api.SessionFile[], ApiRequestError, never>;
800
822
  readonly deleteSessionFile: (credentials: ApiCredentials, sessionId: string, relativePath: string, options?: DeleteSessionFileOptions) => Effect.Effect<void, ApiRequestError, never>;
@@ -995,5 +1017,5 @@ declare const makeUsersApi: Effect.Effect<{
995
1017
  }, never, ApiAuthorization | HttpClient.HttpClient>;
996
1018
  declare const usersApiLayer: Layer.Layer<UsersApi, never, ApiAuthorization | HttpClient.HttpClient>;
997
1019
  //#endregion
998
- export { ApertureClient, ApiAuthorization, ApiCredentials, ApiErrorBody, ApiRequestError, ApiServices, ApiToken, AuditEvent, AuditEventsFilter, AuditEventsListParams, AuditEventsPage, AuthApi, AuthMePrincipal, AuthMeResponse, AuthMeTenant, Authorization, BrowserChannel, BrowserChannelsResponse, BrowserPage, BrowserStatus, CreateAdminTokenInput, CreateSessionInput, CreateSessionOptions, CreateSessionRecordingInput, CreateSessionResponse, CreateTenantTokenInput, CreateTokenResponse, CursorVisibility, DeleteSessionFileOptions, DownloadedFile, EventsApi, EventsFilter, EventsListParams, EventsPage, Health, HealthApi, IceServer, InitialBrowserStorageState, InitialBrowserTarget, LiveSessionErrorBody, LoginMethods, MoveSessionFileInput, OAuthApproval, OAuthAuthorizationRequest, OAuthClient, OAuthGrant, OAuthGrants, OAuthRedirect, PageCursor, PageMeta, PaginatedList, PaginatedResponse, Passkey, PasskeyCredentialJSON, PasskeyLoginOptions, PasskeyMutation, PasskeyRegistrationOptions, Passkeys, PasswordLoginResponse, PromoteSessionInput, PromoteSessionResponse, ProxyConfig, ProxyRule, ProxyUpstream, Recording, RecoveryCodes, ResourceEvent, ResourceGrant, ResourceMode, Scope, SecurityStatus, Session, SessionDirectory, SessionFile, SessionFileDirectoryNode, SessionFileDownloadURL, SessionFileDownloadURLInput, SessionFileEntry, SessionFileNode, SessionFileTreeNode, SessionMedia, SessionMutationResponse, SessionProxy, SessionRecording, SessionRecordingEditError, SessionStatus, SessionUploadFile, SessionsApi, SessionsBulkResponse, SessionsFilter, SessionsListParams, SessionsPage, SetViewportInput, Snapshot, SnapshotMutationResponse, SnapshotsApi, SnapshotsFilter, SnapshotsListParams, SnapshotsPage, TENANT_HEADER, TOTPEnrollment, TagFilterValue, TargetViewport, Tenant, TenantHeaderMode, TenantMembership, TenantScope, TenantsApi, TenantsFilter, TenantsListParams, TenantsPage, TokensApi, TokensFilter, TokensListParams, TokensPage, UpdateProxyConfig, UpdateSnapshotInput, UploadSessionFilesOptions, User, UserInput, UserInvitation, UsersApi, UsersFilter, UsersListParams, UsersPage, WithCredentials, apertureClientLayer, apiAuthorizationLayer, apiClientLayer, authApiLayer, authorizedHttpClientLayer, baseUrlLayer, compactQuery, contentDispositionFilename, defaultListLimit, eventsApiLayer, flattenInfinitePages, getNextPageParam, healthApiLayer, listQueryDefaults, makeApertureClient, makeApiAuthorization, makeAuthApi, makeEventsApi, makeHealthApi, makeSessionsApi, makeSnapshotsApi, makeTenantsApi, makeTokensApi, makeUsersApi, paginated, resolveTenantHeader, sessionFileRootDirectories, sessionFileTree, sessionsApiLayer, snapshotsApiLayer, tagQuery, tenantsApiLayer, toApiRequestError, tokensApiLayer, usersApiLayer, webSessionCredentials, withCredentials };
1020
+ export { ApertureClient, ApiAuthorization, ApiCredentials, ApiErrorBody, ApiRequestError, ApiServices, ApiToken, AuditEvent, AuditEventsFilter, AuditEventsListParams, AuditEventsPage, AuthApi, AuthMePrincipal, AuthMeResponse, AuthMeTenant, Authorization, BrowserChannel, BrowserChannelsResponse, BrowserPage, BrowserStatus, CreateAdminTokenInput, CreateSessionInput, CreateSessionOptions, CreateSessionRecordingInput, CreateSessionResponse, CreateTenantTokenInput, CreateTokenResponse, CursorVisibility, DeleteSessionFileOptions, DownloadedFile, EventsApi, EventsFilter, EventsListParams, EventsPage, Health, HealthApi, IceServer, InitialBrowserStorageState, InitialBrowserTarget, LiveSessionErrorBody, LoginMethods, MoveSessionFileInput, OAuthApproval, OAuthAuthorizationRequest, OAuthClient, OAuthGrant, OAuthGrants, OAuthRedirect, PageCursor, PageMeta, PaginatedList, PaginatedResponse, Passkey, PasskeyCredentialJSON, PasskeyLoginOptions, PasskeyMutation, PasskeyRegistrationOptions, Passkeys, PasswordLoginResponse, PromoteSessionInput, PromoteSessionResponse, ProxyConfig, ProxyRule, ProxyUpstream, Recording, RecordingAttentionInput, RecordingCaptionInput, RecordingFocusInput, RecordingSettings, RecoveryCodes, ResourceEvent, ResourceGrant, ResourceMode, Scope, SecurityStatus, Session, SessionDirectory, SessionFile, SessionFileDirectoryNode, SessionFileDownloadURL, SessionFileDownloadURLInput, SessionFileEntry, SessionFileNode, SessionFileTreeNode, SessionMedia, SessionMutationResponse, SessionProxy, SessionRecording, SessionRecordingEditError, SessionStatus, SessionUploadFile, SessionsApi, SessionsBulkResponse, SessionsFilter, SessionsListParams, SessionsPage, SetViewportInput, Snapshot, SnapshotMutationResponse, SnapshotsApi, SnapshotsFilter, SnapshotsListParams, SnapshotsPage, TENANT_HEADER, TOTPEnrollment, TagFilterValue, TargetViewport, Tenant, TenantHeaderMode, TenantMembership, TenantScope, TenantsApi, TenantsFilter, TenantsListParams, TenantsPage, TokensApi, TokensFilter, TokensListParams, TokensPage, UpdateProxyConfig, UpdateSnapshotInput, UploadSessionFilesOptions, User, UserInput, UserInvitation, UsersApi, UsersFilter, UsersListParams, UsersPage, WithCredentials, apertureClientLayer, apiAuthorizationLayer, apiClientLayer, authApiLayer, authorizedHttpClientLayer, baseUrlLayer, compactQuery, contentDispositionFilename, defaultListLimit, eventsApiLayer, flattenInfinitePages, getNextPageParam, healthApiLayer, listQueryDefaults, makeApertureClient, makeApiAuthorization, makeAuthApi, makeEventsApi, makeHealthApi, makeSessionsApi, makeSnapshotsApi, makeTenantsApi, makeTokensApi, makeUsersApi, paginated, resolveTenantHeader, sessionFileRootDirectories, sessionFileTree, sessionsApiLayer, snapshotsApiLayer, tagQuery, tenantsApiLayer, toApiRequestError, tokensApiLayer, usersApiLayer, webSessionCredentials, withCredentials };
999
1021
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -548,6 +548,13 @@ const healthApiLayer = Layer.effect(HealthApi, makeHealthApi);
548
548
  //#region src/sessions/schemas.ts
549
549
  const positiveInt = Schema.Number.check(Schema.isInt(), Schema.isGreaterThan(0));
550
550
  const emptyArray = Effect.succeed([]);
551
+ const RecordingSettings = Schema.Struct({
552
+ capture: Api.CreateSessionRecordingInput.fields.capture,
553
+ presentation: Api.CreateSessionRecordingInput.fields.presentation,
554
+ idle: Api.CreateSessionRecordingInput.fields.idle,
555
+ ripple: Api.CreateSessionRecordingInput.fields.ripple,
556
+ burst: Api.CreateSessionRecordingInput.fields.burst
557
+ });
551
558
  const BrowserPage = Schema.Struct({
552
559
  targetId: Schema.String,
553
560
  state: Schema.Literals([
@@ -782,6 +789,15 @@ const makeSessionsApi = Effect.gen(function* () {
782
789
  const listSessionFiles = Effect.fn("SessionsApi.listSessionFiles")(function* (credentials, sessionId) {
783
790
  return yield* api.listSessionFiles(sessionId, void 0).pipe(tenantScoped(credentials));
784
791
  });
792
+ const captionSessionRecording = Effect.fn("SessionsApi.captionSessionRecording")(function* (credentials, sessionId, recordingId, input) {
793
+ yield* api.captionSessionRecording(sessionId, recordingId, { payload: input }).pipe(tenantScoped(credentials));
794
+ });
795
+ const focusSessionRecording = Effect.fn("SessionsApi.focusSessionRecording")(function* (credentials, sessionId, recordingId, input) {
796
+ yield* api.focusSessionRecording(sessionId, recordingId, { payload: input }).pipe(tenantScoped(credentials));
797
+ });
798
+ const attentionSessionRecording = Effect.fn("SessionsApi.attentionSessionRecording")(function* (credentials, sessionId, recordingId, input) {
799
+ yield* api.attentionSessionRecording(sessionId, recordingId, { payload: input }).pipe(tenantScoped(credentials));
800
+ });
785
801
  const createSessionFileDownloadURL = Effect.fn("SessionsApi.createSessionFileDownloadURL")(function* (credentials, sessionId, input) {
786
802
  return yield* api.createSessionFileDownloadURL(sessionId, { payload: input }).pipe(tenantScoped(credentials));
787
803
  });
@@ -875,6 +891,9 @@ const makeSessionsApi = Effect.gen(function* () {
875
891
  getSessionRecording,
876
892
  retargetSessionRecording,
877
893
  stopSessionRecording,
894
+ captionSessionRecording,
895
+ focusSessionRecording,
896
+ attentionSessionRecording,
878
897
  listSessionFiles,
879
898
  createSessionFileDownloadURL,
880
899
  getBrowserChannels,
@@ -1238,6 +1257,6 @@ function sessionFileTree(entries) {
1238
1257
  return toNodes(root, "");
1239
1258
  }
1240
1259
  //#endregion
1241
- export { ApertureClient, ApiAuthorization, ApiErrorBody, ApiRequestError, AuthApi, Authorization, BrowserPage, BrowserStatus, EventsApi, HealthApi, LiveSessionErrorBody, LoginMethods, OAuthAuthorizationRequest, OAuthClient, OAuthGrant, OAuthGrants, OAuthRedirect, Passkey, PasskeyLoginOptions, PasskeyMutation, PasskeyRegistrationOptions, Passkeys, PasswordLoginResponse, Recording, RecoveryCodes, SecurityStatus, SessionStatus, SessionsApi, SnapshotsApi, TENANT_HEADER, TOTPEnrollment, TenantsApi, TokensApi, UsersApi, apertureClientLayer, apiAuthorizationLayer, apiClientLayer, authApiLayer, authorizedHttpClientLayer, baseUrlLayer, compactQuery, contentDispositionFilename, defaultListLimit, eventsApiLayer, flattenInfinitePages, getNextPageParam, healthApiLayer, listQueryDefaults, makeApertureClient, makeApiAuthorization, makeAuthApi, makeEventsApi, makeHealthApi, makeSessionsApi, makeSnapshotsApi, makeTenantsApi, makeTokensApi, makeUsersApi, paginated, resolveTenantHeader, sessionFileRootDirectories, sessionFileTree, sessionsApiLayer, snapshotsApiLayer, tagQuery, tenantsApiLayer, toApiRequestError, tokensApiLayer, usersApiLayer, webSessionCredentials, withCredentials };
1260
+ export { ApertureClient, ApiAuthorization, ApiErrorBody, ApiRequestError, AuthApi, Authorization, BrowserPage, BrowserStatus, EventsApi, HealthApi, LiveSessionErrorBody, LoginMethods, OAuthAuthorizationRequest, OAuthClient, OAuthGrant, OAuthGrants, OAuthRedirect, Passkey, PasskeyLoginOptions, PasskeyMutation, PasskeyRegistrationOptions, Passkeys, PasswordLoginResponse, Recording, RecordingSettings, RecoveryCodes, SecurityStatus, SessionStatus, SessionsApi, SnapshotsApi, TENANT_HEADER, TOTPEnrollment, TenantsApi, TokensApi, UsersApi, apertureClientLayer, apiAuthorizationLayer, apiClientLayer, authApiLayer, authorizedHttpClientLayer, baseUrlLayer, compactQuery, contentDispositionFilename, defaultListLimit, eventsApiLayer, flattenInfinitePages, getNextPageParam, healthApiLayer, listQueryDefaults, makeApertureClient, makeApiAuthorization, makeAuthApi, makeEventsApi, makeHealthApi, makeSessionsApi, makeSnapshotsApi, makeTenantsApi, makeTokensApi, makeUsersApi, paginated, resolveTenantHeader, sessionFileRootDirectories, sessionFileTree, sessionsApiLayer, snapshotsApiLayer, tagQuery, tenantsApiLayer, toApiRequestError, tokensApiLayer, usersApiLayer, webSessionCredentials, withCredentials };
1242
1261
 
1243
1262
  //# sourceMappingURL=index.js.map
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/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 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 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 /**\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 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 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 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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"}
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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aperture-browser/api-client",
3
- "version": "0.0.0-nightly.100.78b4e7ef6edc",
3
+ "version": "0.0.0-nightly.101.c63f90ec6164",
4
4
  "description": "Effect services for the Aperture API: sessions, snapshots, tenants, users, tokens, events and authentication.",
5
5
  "homepage": "https://github.com/tarik02/aperture#readme",
6
6
  "bugs": "https://github.com/tarik02/aperture/issues",
@@ -29,7 +29,7 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@aperture-browser/api-schema": "0.0.0-nightly.100.78b4e7ef6edc"
32
+ "@aperture-browser/api-schema": "0.0.0-nightly.101.c63f90ec6164"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@simplewebauthn/browser": "13.3.0",