Skip to content

Commit 18bdbac

Browse files
Added Permissions module to @effect/platform-browser (#3902)
Co-authored-by: Tim <[email protected]>
1 parent 0184a99 commit 18bdbac

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

.changeset/spicy-foxes-study.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@effect/platform-browser": patch
3+
"@effect/platform": patch
4+
---
5+
6+
Added `Permissions` module to `@effect/platform-browser`
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/**
2+
* @since 1.0.0
3+
*/
4+
import { TypeIdError } from "@effect/platform/Error"
5+
import * as Context from "effect/Context"
6+
import * as Effect from "effect/Effect"
7+
import * as Layer from "effect/Layer"
8+
9+
/**
10+
* @since 1.0.0
11+
* @category type ids
12+
*/
13+
export const TypeId: unique symbol = Symbol.for("@effect/platform-browser/Permissions")
14+
15+
/**
16+
* @since 1.0.0
17+
* @category type ids
18+
*/
19+
export type TypeId = typeof TypeId
20+
21+
/**
22+
* Wrapper on the Permission API (`navigator.permissions`)
23+
* with methods for querying status of permissions.
24+
*
25+
* @since 1.0.0
26+
* @category interface
27+
*/
28+
export interface Permissions {
29+
readonly [TypeId]: TypeId
30+
31+
/**
32+
* Returns the state of a user permission on the global scope.
33+
*/
34+
readonly query: <Name extends PermissionName>(
35+
name: Name
36+
) => Effect.Effect<
37+
// `name` is identical to the name passed to Permissions.query
38+
// https://developer.mozilla.org/en-US/docs/Web/API/PermissionStatus
39+
Omit<PermissionStatus, "name"> & { name: Name },
40+
PermissionsError
41+
>
42+
}
43+
44+
/**
45+
* @since 1.0.0
46+
* @category type ids
47+
*/
48+
export const ErrorTypeId: unique symbol = Symbol.for("@effect/platform-browser/Permissions/PermissionsError")
49+
50+
/**
51+
* @since 1.0.0
52+
* @category type ids
53+
*/
54+
export type ErrorTypeId = typeof ErrorTypeId
55+
56+
/**
57+
* @since 1.0.0
58+
* @category errors
59+
*/
60+
export class PermissionsError extends TypeIdError(ErrorTypeId, "PermissionsError")<{
61+
/** https://developer.mozilla.org/en-US/docs/Web/API/Permissions/query#exceptions */
62+
readonly reason: "InvalidStateError" | "TypeError"
63+
readonly cause: unknown
64+
}> {
65+
get message() {
66+
return this.reason
67+
}
68+
}
69+
70+
/**
71+
* @since 1.0.0
72+
* @category tags
73+
*/
74+
export const Permissions: Context.Tag<Permissions, Permissions> = Context.GenericTag<Permissions>(
75+
"@effect/platform-browser/Permissions"
76+
)
77+
78+
/**
79+
* A layer that directly interfaces with the `navigator.permissions` api
80+
*
81+
* @since 1.0.0
82+
* @category layers
83+
*/
84+
export const layer: Layer.Layer<Permissions> = Layer.succeed(
85+
Permissions,
86+
Permissions.of({
87+
[TypeId]: TypeId,
88+
query: (name) =>
89+
Effect.tryPromise({
90+
try: () => navigator.permissions.query({ name }),
91+
catch: (cause) =>
92+
new PermissionsError({
93+
reason: cause instanceof DOMException ? "InvalidStateError" : "TypeError",
94+
cause
95+
})
96+
}).pipe(
97+
Effect.map((status) => ({ ...status, name }))
98+
)
99+
})
100+
)

0 commit comments

Comments
 (0)