@ankhorage/permissions 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +97 -21
- package/dist/client/types.d.ts +2 -8
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/types.js.map +1 -1
- package/dist/expo/adapters/camera.d.ts +3 -0
- package/dist/expo/adapters/camera.d.ts.map +1 -0
- package/dist/expo/adapters/camera.js +30 -0
- package/dist/expo/adapters/camera.js.map +1 -0
- package/dist/expo/adapters/location.d.ts +3 -0
- package/dist/expo/adapters/location.d.ts.map +1 -0
- package/dist/expo/adapters/location.js +31 -0
- package/dist/expo/adapters/location.js.map +1 -0
- package/dist/expo/adapters/mediaLibrary.d.ts +3 -0
- package/dist/expo/adapters/mediaLibrary.d.ts.map +1 -0
- package/dist/expo/adapters/mediaLibrary.js +28 -0
- package/dist/expo/adapters/mediaLibrary.js.map +1 -0
- package/dist/expo/adapters/microphone.d.ts +3 -0
- package/dist/expo/adapters/microphone.d.ts.map +1 -0
- package/dist/expo/adapters/microphone.js +30 -0
- package/dist/expo/adapters/microphone.js.map +1 -0
- package/dist/expo/adapters/notifications.d.ts +3 -0
- package/dist/expo/adapters/notifications.d.ts.map +1 -0
- package/dist/expo/adapters/notifications.js +24 -0
- package/dist/expo/adapters/notifications.js.map +1 -0
- package/dist/expo/client.d.ts +9 -0
- package/dist/expo/client.d.ts.map +1 -0
- package/dist/expo/client.js +63 -0
- package/dist/expo/client.js.map +1 -0
- package/dist/expo/index.d.ts +3 -0
- package/dist/expo/index.d.ts.map +1 -0
- package/dist/expo/index.js +3 -0
- package/dist/expo/index.js.map +1 -0
- package/dist/expo/manifest.d.ts +9 -0
- package/dist/expo/manifest.d.ts.map +1 -0
- package/dist/expo/manifest.js +44 -0
- package/dist/expo/manifest.js.map +1 -0
- package/dist/expo/permissionResponse.d.ts +11 -0
- package/dist/expo/permissionResponse.d.ts.map +1 -0
- package/dist/expo/permissionResponse.js +47 -0
- package/dist/expo/permissionResponse.js.map +1 -0
- package/dist/manager/createPermissionManager.d.ts +4 -15
- package/dist/manager/createPermissionManager.d.ts.map +1 -1
- package/dist/manager/createPermissionManager.js +3 -14
- package/dist/manager/createPermissionManager.js.map +1 -1
- package/dist/react/index.d.ts +0 -14
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +0 -14
- package/dist/react/index.js.map +1 -1
- package/dist/testing/index.d.ts +0 -8
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +0 -8
- package/dist/testing/index.js.map +1 -1
- package/package.json +13 -1
- package/src/client/types.ts +2 -8
- package/src/expo/adapters/camera.ts +52 -0
- package/src/expo/adapters/location.ts +34 -0
- package/src/expo/adapters/mediaLibrary.ts +33 -0
- package/src/expo/adapters/microphone.ts +52 -0
- package/src/expo/adapters/notifications.ts +28 -0
- package/src/expo/client.test.ts +372 -0
- package/src/expo/client.ts +79 -0
- package/src/expo/index.ts +3 -0
- package/src/expo/manifest.test.ts +65 -0
- package/src/expo/manifest.ts +57 -0
- package/src/expo/modules.d.ts +53 -0
- package/src/expo/permissionResponse.ts +84 -0
- package/src/manager/createPermissionManager.ts +4 -15
- package/src/react/index.tsx +0 -14
- package/src/testing/index.ts +0 -8
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Permission } from '../registry/permissions';
|
|
2
|
+
import {
|
|
3
|
+
createPermissionState,
|
|
4
|
+
isPermissionStatus,
|
|
5
|
+
type PermissionState,
|
|
6
|
+
} from '../state/permissionState';
|
|
7
|
+
|
|
8
|
+
export interface ExpoPermissionResponse {
|
|
9
|
+
readonly status: string;
|
|
10
|
+
readonly canAskAgain?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type ExpoPermissionMethod = () => Promise<ExpoPermissionResponse>;
|
|
14
|
+
|
|
15
|
+
export function createExpoPermissionState(
|
|
16
|
+
permission: Permission,
|
|
17
|
+
response: ExpoPermissionResponse,
|
|
18
|
+
): PermissionState {
|
|
19
|
+
const status = isPermissionStatus(response.status) ? response.status : 'unknown';
|
|
20
|
+
|
|
21
|
+
return createPermissionState({
|
|
22
|
+
permission,
|
|
23
|
+
status,
|
|
24
|
+
canAskAgain: response.canAskAgain,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function createExpoUnavailableState(
|
|
29
|
+
permission: Permission,
|
|
30
|
+
error: unknown,
|
|
31
|
+
): PermissionState {
|
|
32
|
+
return createPermissionState({
|
|
33
|
+
permission,
|
|
34
|
+
status: 'unavailable',
|
|
35
|
+
reason: getExpoPermissionErrorMessage(error),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function findExpoPermissionMethod(
|
|
40
|
+
source: unknown,
|
|
41
|
+
methodName: string,
|
|
42
|
+
containerNames: readonly string[] = [],
|
|
43
|
+
): ExpoPermissionMethod | undefined {
|
|
44
|
+
if (hasExpoPermissionMethod(source, methodName)) {
|
|
45
|
+
return source[methodName];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!isRecord(source)) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const containerName of containerNames) {
|
|
53
|
+
const container = source[containerName];
|
|
54
|
+
|
|
55
|
+
if (hasExpoPermissionMethod(container, methodName)) {
|
|
56
|
+
return container[methodName];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getExpoPermissionErrorMessage(error: unknown): string {
|
|
64
|
+
if (error instanceof Error && error.message.length > 0) {
|
|
65
|
+
return error.message;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (typeof error === 'string' && error.length > 0) {
|
|
69
|
+
return error;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return 'Expo permission operation failed.';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function hasExpoPermissionMethod(
|
|
76
|
+
value: unknown,
|
|
77
|
+
methodName: string,
|
|
78
|
+
): value is Record<string, ExpoPermissionMethod> {
|
|
79
|
+
return isRecord(value) && typeof value[methodName] === 'function';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
83
|
+
return typeof value === 'object' && value !== null;
|
|
84
|
+
}
|
|
@@ -3,7 +3,7 @@ import { assertKnownPermission, type Permission } from '../registry/permissions'
|
|
|
3
3
|
import { normalizePermissionState, type PermissionState } from '../state/permissionState';
|
|
4
4
|
|
|
5
5
|
/***
|
|
6
|
-
* Public
|
|
6
|
+
* Public facade for checking and requesting normalized permission state.
|
|
7
7
|
*/
|
|
8
8
|
export interface PermissionManager {
|
|
9
9
|
getStatus(permission: Permission): Promise<PermissionState>;
|
|
@@ -12,22 +12,11 @@ export interface PermissionManager {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/***
|
|
15
|
-
*
|
|
15
|
+
* Creates a permission manager from a runtime-specific client.
|
|
16
16
|
*
|
|
17
17
|
* @readme
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* generate iOS usage descriptions, Android manifest entries, or Expo config
|
|
21
|
-
* plugins.
|
|
22
|
-
*
|
|
23
|
-
* @usage
|
|
24
|
-
* ```ts
|
|
25
|
-
* const permissions = createPermissionManager(client);
|
|
26
|
-
* const camera = await permissions.getStatus(Permission.Camera);
|
|
27
|
-
* const requested = camera.granted
|
|
28
|
-
* ? camera
|
|
29
|
-
* : await permissions.request(Permission.Camera);
|
|
30
|
-
* ```
|
|
18
|
+
* The manager validates permission names and normalizes client results.
|
|
19
|
+
* Native app configuration remains a separate build-time concern.
|
|
31
20
|
*/
|
|
32
21
|
export function createPermissionManager(client: PermissionClient): PermissionManager {
|
|
33
22
|
const manager: PermissionManager = {
|
package/src/react/index.tsx
CHANGED
|
@@ -99,20 +99,6 @@ export function usePermissions(): PermissionManager {
|
|
|
99
99
|
|
|
100
100
|
/***
|
|
101
101
|
* Tracks a single permission and exposes explicit refresh/request actions.
|
|
102
|
-
*
|
|
103
|
-
* @usage
|
|
104
|
-
* ```tsx
|
|
105
|
-
* const camera = usePermission(Permission.Camera, { refreshOnMount: true });
|
|
106
|
-
*
|
|
107
|
-
* return (
|
|
108
|
-
* <Button
|
|
109
|
-
* disabled={camera.granted}
|
|
110
|
-
* onPress={() => {
|
|
111
|
-
* void camera.request();
|
|
112
|
-
* }}
|
|
113
|
-
* />
|
|
114
|
-
* );
|
|
115
|
-
* ```
|
|
116
102
|
*/
|
|
117
103
|
export function usePermission(
|
|
118
104
|
permission: Permission,
|
package/src/testing/index.ts
CHANGED
|
@@ -51,14 +51,6 @@ export interface FakePermissionClient extends PermissionClient {
|
|
|
51
51
|
* @readme
|
|
52
52
|
* Fake clients make permission flows testable without native devices, browser
|
|
53
53
|
* prompts, simulators, or network access.
|
|
54
|
-
*
|
|
55
|
-
* @usage
|
|
56
|
-
* ```ts
|
|
57
|
-
* const client = createFakePermissionClient({
|
|
58
|
-
* initialStates: [{ permission: Permission.Camera, status: 'denied' }],
|
|
59
|
-
* });
|
|
60
|
-
* await client.request(Permission.Camera);
|
|
61
|
-
* ```
|
|
62
54
|
*/
|
|
63
55
|
export function createFakePermissionClient(
|
|
64
56
|
options: FakePermissionClientOptions = {},
|