@ankhorage/permissions 0.2.63 → 0.3.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 +16 -0
- package/README.md +22 -79
- package/dist/ankh.provider.d.ts +46 -6
- package/dist/ankh.provider.d.ts.map +1 -1
- package/dist/ankh.provider.js +4 -9
- package/dist/ankh.provider.js.map +1 -1
- package/dist/capabilities/index.d.ts +43 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +36 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/expo/adapters/camera.d.ts +1 -1
- package/dist/expo/adapters/camera.d.ts.map +1 -1
- package/dist/expo/adapters/camera.js +1 -1
- package/dist/expo/adapters/camera.js.map +1 -1
- package/dist/expo/adapters/location.d.ts +1 -1
- package/dist/expo/adapters/location.d.ts.map +1 -1
- package/dist/expo/adapters/location.js +1 -1
- package/dist/expo/adapters/location.js.map +1 -1
- package/dist/expo/adapters/mediaLibrary.d.ts +1 -1
- package/dist/expo/adapters/mediaLibrary.d.ts.map +1 -1
- package/dist/expo/adapters/mediaLibrary.js +1 -1
- package/dist/expo/adapters/mediaLibrary.js.map +1 -1
- package/dist/expo/adapters/microphone.d.ts +1 -1
- package/dist/expo/adapters/microphone.d.ts.map +1 -1
- package/dist/expo/adapters/microphone.js +1 -1
- package/dist/expo/adapters/microphone.js.map +1 -1
- package/dist/expo/adapters/notifications.d.ts +1 -1
- package/dist/expo/adapters/notifications.d.ts.map +1 -1
- package/dist/expo/adapters/notifications.js +1 -1
- package/dist/expo/adapters/notifications.js.map +1 -1
- package/dist/expo/{permissionResponse.d.ts → adapters/permissionResponse.d.ts} +2 -2
- package/dist/expo/adapters/permissionResponse.d.ts.map +1 -0
- package/dist/expo/{permissionResponse.js → adapters/permissionResponse.js} +1 -1
- package/dist/expo/adapters/permissionResponse.js.map +1 -0
- package/dist/expo/client.d.ts +0 -6
- package/dist/expo/client.d.ts.map +1 -1
- package/dist/expo/client.js.map +1 -1
- package/dist/types/expo.d.ts +7 -0
- package/dist/types/expo.d.ts.map +1 -0
- package/dist/types/expo.js +2 -0
- package/dist/types/expo.js.map +1 -0
- package/package.json +72 -8
- package/src/ankh.provider.ts +16 -16
- package/src/capabilities/index.test.ts +15 -0
- package/src/capabilities/index.ts +37 -0
- package/src/expo/adapters/camera.ts +2 -2
- package/src/expo/adapters/location.ts +2 -2
- package/src/expo/adapters/mediaLibrary.ts +2 -2
- package/src/expo/adapters/microphone.ts +2 -2
- package/src/expo/adapters/notifications.ts +2 -2
- package/src/expo/{permissionResponse.ts → adapters/permissionResponse.ts} +2 -2
- package/src/expo/client.ts +1 -5
- package/src/provider.test.ts +30 -0
- package/src/types/expo.ts +7 -0
- package/dist/expo/permissionResponse.d.ts.map +0 -1
- package/dist/expo/permissionResponse.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @ankhorage/permissions
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 253d7f3: Publish canonical Capability descriptors for the Permissions Ankh provider.
|
|
8
|
+
|
|
9
|
+
## 0.2.64
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 1699471: Update dependencies: `@ankhorage/devtools`.
|
|
14
|
+
- 4f72e8d: Update Renovate-managed workflows.
|
|
15
|
+
- 39117c9: Update dependencies: `@ankhorage/devtools`.
|
|
16
|
+
- aed1e43: Update Renovate-managed workflows.
|
|
17
|
+
- 5dac26d: Update dependencies: `@ankhorage/paradox`.
|
|
18
|
+
|
|
3
19
|
## 0.2.63
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -3,101 +3,44 @@
|
|
|
3
3
|
|
|
4
4
|
# PERMISSIONS
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Cross-platform permission registry and runtime helpers for Expo, React Native, and React Native Web apps, with unified request/check APIs for camera, media, location, notifications, microphone, and other web/native capabilities.
|
|
9
9
|
|
|
10
10
|
## Usage
|
|
11
11
|
|
|
12
|
-
###
|
|
12
|
+
### CLI
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
`usePermission` to read, refresh, and request a normalized permission state.
|
|
16
|
-
|
|
17
|
-
Source: `examples/basic/App.tsx`
|
|
18
|
-
|
|
19
|
-
```tsx
|
|
20
|
-
import {
|
|
21
|
-
createFakePermissionClient,
|
|
22
|
-
Permission,
|
|
23
|
-
PermissionsProvider,
|
|
24
|
-
usePermission,
|
|
25
|
-
} from '@ankhorage/permissions';
|
|
26
|
-
|
|
27
|
-
const permissionClient = createFakePermissionClient({
|
|
28
|
-
initialStates: [{ permission: Permission.Camera, status: 'denied' }],
|
|
29
|
-
requestStates: [{ permission: Permission.Camera, status: 'granted' }],
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
export default function BasicPermissionsExample() {
|
|
33
|
-
return (
|
|
34
|
-
<PermissionsProvider client={permissionClient}>
|
|
35
|
-
<CameraPermissionExample />
|
|
36
|
-
</PermissionsProvider>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
14
|
+
Ankhorage packages expose their command-line interface through `ankh`. Use `ankh --help` to discover available package commands, or run a package command with `--help` for package-specific usage.
|
|
39
15
|
|
|
40
|
-
|
|
41
|
-
|
|
16
|
+
```zsh
|
|
17
|
+
# Install the Ankhorage CLI
|
|
18
|
+
bun add --global @ankhorage/ankh
|
|
42
19
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<p>Camera permission: {camera.status}</p>
|
|
46
|
-
<button
|
|
47
|
-
type="button"
|
|
48
|
-
disabled={camera.granted}
|
|
49
|
-
onClick={() => {
|
|
50
|
-
void camera.request();
|
|
51
|
-
}}
|
|
52
|
-
>
|
|
53
|
-
Request camera permission
|
|
54
|
-
</button>
|
|
55
|
-
</>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
20
|
+
# Show usage information for permissions
|
|
21
|
+
ankh permissions --help
|
|
58
22
|
```
|
|
59
23
|
|
|
60
|
-
###
|
|
24
|
+
### Basic permissions
|
|
61
25
|
|
|
62
|
-
|
|
63
|
-
it at the app root, and call `request()` only from an explicit user action.
|
|
26
|
+
Basic permissions runtime example.
|
|
64
27
|
|
|
65
|
-
Source: `examples/expo/App.tsx`
|
|
66
|
-
|
|
67
|
-
```tsx
|
|
68
|
-
import { Permission, PermissionsProvider, usePermission } from '@ankhorage/permissions';
|
|
69
|
-
import { createPermissionClient } from '@ankhorage/permissions/expo';
|
|
70
28
|
|
|
71
|
-
|
|
29
|
+
Create a permission client, provide it at the app root, and use
|
|
30
|
+
`usePermission` to read, refresh, and request a normalized permission state.
|
|
72
31
|
|
|
73
|
-
|
|
32
|
+
```tsx
|
|
33
|
+
export default function BasicPermissionsExample() {
|
|
74
34
|
return (
|
|
75
35
|
<PermissionsProvider client={permissionClient}>
|
|
76
36
|
<CameraPermissionExample />
|
|
77
37
|
</PermissionsProvider>
|
|
78
38
|
);
|
|
79
39
|
}
|
|
80
|
-
|
|
81
|
-
function CameraPermissionExample() {
|
|
82
|
-
const camera = usePermission(Permission.Camera, { refreshOnMount: true });
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<>
|
|
86
|
-
<p>Camera permission: {camera.status}</p>
|
|
87
|
-
<button
|
|
88
|
-
type="button"
|
|
89
|
-
disabled={camera.granted}
|
|
90
|
-
onClick={() => {
|
|
91
|
-
void camera.request();
|
|
92
|
-
}}
|
|
93
|
-
>
|
|
94
|
-
Request camera permission
|
|
95
|
-
</button>
|
|
96
|
-
</>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
40
|
```
|
|
100
41
|
|
|
42
|
+
This package contains 1 additional example. See the generated documentation for the complete set.
|
|
43
|
+
|
|
101
44
|
## Generated documentation
|
|
102
45
|
|
|
103
46
|
- [Interactive documentation app](././paradox/index.html)
|
|
@@ -156,7 +99,7 @@ Expo modules are loaded only when a client operation uses them. The package
|
|
|
156
99
|
root and Expo manifest metadata remain free of native module imports.
|
|
157
100
|
|
|
158
101
|
Module: `src/expo/client.ts`
|
|
159
|
-
Source: `src/expo/client.ts:
|
|
102
|
+
Source: `src/expo/client.ts:38:1`
|
|
160
103
|
Related symbols: `PermissionClient`
|
|
161
104
|
|
|
162
105
|
</details>
|
|
@@ -232,11 +175,11 @@ Related types: `PermissionsProviderProps`
|
|
|
232
175
|
<details>
|
|
233
176
|
<summary>Props</summary>
|
|
234
177
|
|
|
235
|
-
| Prop
|
|
236
|
-
|
|
|
237
|
-
| children | `ReactNode \| undefined`
|
|
238
|
-
| client
|
|
239
|
-
| manager
|
|
178
|
+
| Prop | Type | Required | Default | Description |
|
|
179
|
+
| --- | --- | --- | --- | --- |
|
|
180
|
+
| children | `ReactNode \| undefined` | no | — | |
|
|
181
|
+
| client | `PermissionClient \| undefined` | no | — | |
|
|
182
|
+
| manager | `PermissionManager \| undefined` | no | — | |
|
|
240
183
|
|
|
241
184
|
</details>
|
|
242
185
|
|
package/dist/ankh.provider.d.ts
CHANGED
|
@@ -1,9 +1,49 @@
|
|
|
1
1
|
declare const provider: {
|
|
2
|
-
id:
|
|
3
|
-
category:
|
|
4
|
-
version: string;
|
|
5
|
-
capabilities: readonly [
|
|
6
|
-
|
|
2
|
+
readonly id: "@ankhorage/permissions";
|
|
3
|
+
readonly category: "permissions";
|
|
4
|
+
readonly version: string;
|
|
5
|
+
readonly capabilities: readonly [{
|
|
6
|
+
readonly id: "permissions.inspect";
|
|
7
|
+
readonly owner: "@ankhorage/permissions";
|
|
8
|
+
readonly access: readonly ["invoke"];
|
|
9
|
+
readonly binding: {
|
|
10
|
+
readonly kind: "action";
|
|
11
|
+
readonly bindableAs: readonly ["target"];
|
|
12
|
+
};
|
|
13
|
+
readonly label: "Inspect permissions";
|
|
14
|
+
readonly description: "List known permission identifiers and registry metadata.";
|
|
15
|
+
}, {
|
|
16
|
+
readonly id: "permissions.check";
|
|
17
|
+
readonly owner: "@ankhorage/permissions";
|
|
18
|
+
readonly access: readonly ["invoke"];
|
|
19
|
+
readonly binding: {
|
|
20
|
+
readonly kind: "action";
|
|
21
|
+
readonly bindableAs: readonly ["target"];
|
|
22
|
+
};
|
|
23
|
+
readonly label: "Check permission";
|
|
24
|
+
readonly description: "Check a permission state through a host-provided permission client.";
|
|
25
|
+
}, {
|
|
26
|
+
readonly id: "permissions.request";
|
|
27
|
+
readonly owner: "@ankhorage/permissions";
|
|
28
|
+
readonly access: readonly ["invoke"];
|
|
29
|
+
readonly binding: {
|
|
30
|
+
readonly kind: "action";
|
|
31
|
+
readonly bindableAs: readonly ["target"];
|
|
32
|
+
};
|
|
33
|
+
readonly label: "Request permission";
|
|
34
|
+
readonly description: "Request a permission through a host-provided permission client.";
|
|
35
|
+
}, {
|
|
36
|
+
readonly id: "permissions.manifest";
|
|
37
|
+
readonly owner: "@ankhorage/permissions";
|
|
38
|
+
readonly access: readonly ["invoke"];
|
|
39
|
+
readonly binding: {
|
|
40
|
+
readonly kind: "action";
|
|
41
|
+
readonly bindableAs: readonly ["target"];
|
|
42
|
+
};
|
|
43
|
+
readonly label: "Inspect permission manifest";
|
|
44
|
+
readonly description: "Show native and web manifest metadata required by registered permissions.";
|
|
45
|
+
}];
|
|
46
|
+
readonly commands: readonly [{
|
|
7
47
|
readonly path: readonly ["list"];
|
|
8
48
|
readonly summary: "List known permission identifiers and registry metadata.";
|
|
9
49
|
readonly capability: "permissions.inspect";
|
|
@@ -25,7 +65,7 @@ declare const provider: {
|
|
|
25
65
|
readonly capability: "permissions.manifest";
|
|
26
66
|
readonly examples: readonly ["ankh permissions manifest camera"];
|
|
27
67
|
}];
|
|
28
|
-
handlers: {
|
|
68
|
+
readonly handlers: {
|
|
29
69
|
path: readonly ["list"] | readonly ["check"] | readonly ["request"] | readonly ["manifest"];
|
|
30
70
|
handler(request: {
|
|
31
71
|
readonly context: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ankh.provider.d.ts","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAwDA,QAAA,MAAM,QAAQ
|
|
1
|
+
{"version":3,"file":"ankh.provider.d.ts","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAwDA,QAAA,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAbK;YACf,QAAQ,CAAC,OAAO,EAAE;gBAChB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;aACjC,CAAC;SACH;;;;CAgB4C,CAAC;AAEhD,eAAe,QAAQ,CAAC"}
|
package/dist/ankh.provider.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
+
import packageJson from '../package.json';
|
|
2
|
+
import { CAPABILITIES } from './capabilities/index';
|
|
1
3
|
import { PERMISSIONS } from './registry/permissions';
|
|
2
4
|
const PERMISSIONS_PACKAGE_NAME = '@ankhorage/permissions';
|
|
3
|
-
const PERMISSIONS_PACKAGE_VERSION = '0.2.0';
|
|
4
5
|
const PERMISSIONS_COMMAND_CATEGORY = 'permissions';
|
|
5
|
-
const PERMISSIONS_CAPABILITIES = [
|
|
6
|
-
'permissions.inspect',
|
|
7
|
-
'permissions.check',
|
|
8
|
-
'permissions.request',
|
|
9
|
-
'permissions.manifest',
|
|
10
|
-
];
|
|
11
6
|
const commands = [
|
|
12
7
|
{
|
|
13
8
|
path: ['list'],
|
|
@@ -46,8 +41,8 @@ const handlers = commands.map((command) => ({
|
|
|
46
41
|
const provider = {
|
|
47
42
|
id: PERMISSIONS_PACKAGE_NAME,
|
|
48
43
|
category: PERMISSIONS_COMMAND_CATEGORY,
|
|
49
|
-
version:
|
|
50
|
-
capabilities:
|
|
44
|
+
version: packageJson.version,
|
|
45
|
+
capabilities: CAPABILITIES,
|
|
51
46
|
commands,
|
|
52
47
|
handlers,
|
|
53
48
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ankh.provider.js","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ankh.provider.js","sourceRoot":"","sources":["../src/ankh.provider.ts"],"names":[],"mappings":"AAIA,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AAC1D,MAAM,4BAA4B,GAAG,aAAa,CAAC;AAEnD,MAAM,QAAQ,GAAG;IACf;QACE,IAAI,EAAE,CAAC,MAAM,CAAC;QACd,OAAO,EAAE,0DAA0D;QACnE,UAAU,EAAE,qBAAgD;QAC5D,OAAO,EAAE,CAAC,UAAU,CAAC;QACrB,QAAQ,EAAE,CAAC,uBAAuB,CAAC;KACpC;IACD;QACE,IAAI,EAAE,CAAC,OAAO,CAAC;QACf,OAAO,EAAE,qEAAqE;QAC9E,UAAU,EAAE,mBAA8C;QAC1D,QAAQ,EAAE,CAAC,+BAA+B,CAAC;KAC5C;IACD;QACE,IAAI,EAAE,CAAC,SAAS,CAAC;QACjB,OAAO,EAAE,iEAAiE;QAC1E,UAAU,EAAE,qBAAgD;QAC5D,QAAQ,EAAE,CAAC,iCAAiC,CAAC;KAC9C;IACD;QACE,IAAI,EAAE,CAAC,UAAU,CAAC;QAClB,OAAO,EAAE,uEAAuE;QAChF,UAAU,EAAE,sBAAiD;QAC7D,QAAQ,EAAE,CAAC,kCAAkC,CAAC;KAC/C;CAGC,CAAC;AAEL,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,OAAO,CAAC,OAIP;QACC,OAAO,CAAC,OAAO,CAAC,WAAW,CACzB,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,wBAAwB,IAAI;YACtE,sBAAsB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CACpD,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;CACF,CAAC,CAAC,CAAC;AAEJ,MAAM,QAAQ,GAAG;IACf,EAAE,EAAE,wBAAwB;IAC5B,QAAQ,EAAE,4BAA4B;IACtC,OAAO,EAAE,WAAW,CAAC,OAAO;IAC5B,YAAY,EAAE,YAAY;IAC1B,QAAQ;IACR,QAAQ;CACqC,CAAC;AAEhD,eAAe,QAAQ,CAAC","sourcesContent":["import type { AnkhRuntimeCommandProvider } from '@ankhorage/ankh';\nimport type { Capability } from '@ankhorage/contracts/capabilities';\nimport type { AnkhCommandDescriptor } from '@ankhorage/contracts/cli';\n\nimport packageJson from '../package.json';\nimport { CAPABILITIES } from './capabilities/index';\nimport { PERMISSIONS } from './registry/permissions';\n\nconst PERMISSIONS_PACKAGE_NAME = '@ankhorage/permissions';\nconst PERMISSIONS_COMMAND_CATEGORY = 'permissions';\n\nconst commands = [\n {\n path: ['list'],\n summary: 'List known permission identifiers and registry metadata.',\n capability: 'permissions.inspect' satisfies Capability['id'],\n aliases: ['registry'],\n examples: ['ankh permissions list'],\n },\n {\n path: ['check'],\n summary: 'Check a permission state through a host-provided permission client.',\n capability: 'permissions.check' satisfies Capability['id'],\n examples: ['ankh permissions check camera'],\n },\n {\n path: ['request'],\n summary: 'Request a permission through a host-provided permission client.',\n capability: 'permissions.request' satisfies Capability['id'],\n examples: ['ankh permissions request camera'],\n },\n {\n path: ['manifest'],\n summary: 'Show native/web manifest metadata required by registered permissions.',\n capability: 'permissions.manifest' satisfies Capability['id'],\n examples: ['ankh permissions manifest camera'],\n },\n] as const satisfies readonly (AnkhCommandDescriptor & {\n readonly capability: Capability['id'];\n})[];\n\nconst handlers = commands.map((command) => ({\n path: command.path,\n handler(request: {\n readonly context: {\n writeStdout(text: string): void;\n };\n }) {\n request.context.writeStdout(\n `${command.path.join(' ')} is provided by ${PERMISSIONS_PACKAGE_NAME}. ` +\n `Known permissions: ${PERMISSIONS.join(', ')}.\\n`,\n );\n return { exitCode: 0 };\n },\n}));\n\nconst provider = {\n id: PERMISSIONS_PACKAGE_NAME,\n category: PERMISSIONS_COMMAND_CATEGORY,\n version: packageJson.version,\n capabilities: CAPABILITIES,\n commands,\n handlers,\n} as const satisfies AnkhRuntimeCommandProvider;\n\nexport default provider;\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*** Define the executable permission operations published by this package. */
|
|
2
|
+
export declare const CAPABILITIES: readonly [{
|
|
3
|
+
readonly id: "permissions.inspect";
|
|
4
|
+
readonly owner: "@ankhorage/permissions";
|
|
5
|
+
readonly access: readonly ["invoke"];
|
|
6
|
+
readonly binding: {
|
|
7
|
+
readonly kind: "action";
|
|
8
|
+
readonly bindableAs: readonly ["target"];
|
|
9
|
+
};
|
|
10
|
+
readonly label: "Inspect permissions";
|
|
11
|
+
readonly description: "List known permission identifiers and registry metadata.";
|
|
12
|
+
}, {
|
|
13
|
+
readonly id: "permissions.check";
|
|
14
|
+
readonly owner: "@ankhorage/permissions";
|
|
15
|
+
readonly access: readonly ["invoke"];
|
|
16
|
+
readonly binding: {
|
|
17
|
+
readonly kind: "action";
|
|
18
|
+
readonly bindableAs: readonly ["target"];
|
|
19
|
+
};
|
|
20
|
+
readonly label: "Check permission";
|
|
21
|
+
readonly description: "Check a permission state through a host-provided permission client.";
|
|
22
|
+
}, {
|
|
23
|
+
readonly id: "permissions.request";
|
|
24
|
+
readonly owner: "@ankhorage/permissions";
|
|
25
|
+
readonly access: readonly ["invoke"];
|
|
26
|
+
readonly binding: {
|
|
27
|
+
readonly kind: "action";
|
|
28
|
+
readonly bindableAs: readonly ["target"];
|
|
29
|
+
};
|
|
30
|
+
readonly label: "Request permission";
|
|
31
|
+
readonly description: "Request a permission through a host-provided permission client.";
|
|
32
|
+
}, {
|
|
33
|
+
readonly id: "permissions.manifest";
|
|
34
|
+
readonly owner: "@ankhorage/permissions";
|
|
35
|
+
readonly access: readonly ["invoke"];
|
|
36
|
+
readonly binding: {
|
|
37
|
+
readonly kind: "action";
|
|
38
|
+
readonly bindableAs: readonly ["target"];
|
|
39
|
+
};
|
|
40
|
+
readonly label: "Inspect permission manifest";
|
|
41
|
+
readonly description: "Show native and web manifest metadata required by registered permissions.";
|
|
42
|
+
}];
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capabilities/index.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCiB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*** Define the executable permission operations published by this package. */
|
|
2
|
+
export const CAPABILITIES = [
|
|
3
|
+
{
|
|
4
|
+
id: 'permissions.inspect',
|
|
5
|
+
owner: '@ankhorage/permissions',
|
|
6
|
+
access: ['invoke'],
|
|
7
|
+
binding: { kind: 'action', bindableAs: ['target'] },
|
|
8
|
+
label: 'Inspect permissions',
|
|
9
|
+
description: 'List known permission identifiers and registry metadata.',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: 'permissions.check',
|
|
13
|
+
owner: '@ankhorage/permissions',
|
|
14
|
+
access: ['invoke'],
|
|
15
|
+
binding: { kind: 'action', bindableAs: ['target'] },
|
|
16
|
+
label: 'Check permission',
|
|
17
|
+
description: 'Check a permission state through a host-provided permission client.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 'permissions.request',
|
|
21
|
+
owner: '@ankhorage/permissions',
|
|
22
|
+
access: ['invoke'],
|
|
23
|
+
binding: { kind: 'action', bindableAs: ['target'] },
|
|
24
|
+
label: 'Request permission',
|
|
25
|
+
description: 'Request a permission through a host-provided permission client.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: 'permissions.manifest',
|
|
29
|
+
owner: '@ankhorage/permissions',
|
|
30
|
+
access: ['invoke'],
|
|
31
|
+
binding: { kind: 'action', bindableAs: ['target'] },
|
|
32
|
+
label: 'Inspect permission manifest',
|
|
33
|
+
description: 'Show native and web manifest metadata required by registered permissions.',
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/capabilities/index.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;QACE,EAAE,EAAE,qBAAqB;QACzB,KAAK,EAAE,wBAAwB;QAC/B,MAAM,EAAE,CAAC,QAAQ,CAAC;QAClB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;QACnD,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,0DAA0D;KACxE;IACD;QACE,EAAE,EAAE,mBAAmB;QACvB,KAAK,EAAE,wBAAwB;QAC/B,MAAM,EAAE,CAAC,QAAQ,CAAC;QAClB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;QACnD,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,qEAAqE;KACnF;IACD;QACE,EAAE,EAAE,qBAAqB;QACzB,KAAK,EAAE,wBAAwB;QAC/B,MAAM,EAAE,CAAC,QAAQ,CAAC;QAClB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;QACnD,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,iEAAiE;KAC/E;IACD;QACE,EAAE,EAAE,sBAAsB;QAC1B,KAAK,EAAE,wBAAwB;QAC/B,MAAM,EAAE,CAAC,QAAQ,CAAC;QAClB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;QACnD,KAAK,EAAE,6BAA6B;QACpC,WAAW,EAAE,2EAA2E;KACzF;CACuC,CAAC","sourcesContent":["import type { Capability } from '@ankhorage/contracts/capabilities';\n\n/*** Define the executable permission operations published by this package. */\nexport const CAPABILITIES = [\n {\n id: 'permissions.inspect',\n owner: '@ankhorage/permissions',\n access: ['invoke'],\n binding: { kind: 'action', bindableAs: ['target'] },\n label: 'Inspect permissions',\n description: 'List known permission identifiers and registry metadata.',\n },\n {\n id: 'permissions.check',\n owner: '@ankhorage/permissions',\n access: ['invoke'],\n binding: { kind: 'action', bindableAs: ['target'] },\n label: 'Check permission',\n description: 'Check a permission state through a host-provided permission client.',\n },\n {\n id: 'permissions.request',\n owner: '@ankhorage/permissions',\n access: ['invoke'],\n binding: { kind: 'action', bindableAs: ['target'] },\n label: 'Request permission',\n description: 'Request a permission through a host-provided permission client.',\n },\n {\n id: 'permissions.manifest',\n owner: '@ankhorage/permissions',\n access: ['invoke'],\n binding: { kind: 'action', bindableAs: ['target'] },\n label: 'Inspect permission manifest',\n description: 'Show native and web manifest metadata required by registered permissions.',\n },\n] as const satisfies readonly Capability[];\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/camera.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/camera.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAU9D,eAAO,MAAM,aAAa,EAAE,qBA0B3B,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createExpoPermissionState, createExpoUnavailableState, findExpoPermissionMethod, } from '
|
|
1
|
+
import { createExpoPermissionState, createExpoUnavailableState, findExpoPermissionMethod, } from './permissionResponse';
|
|
2
2
|
const CAMERA_PERMISSION_CONTAINER_NAMES = ['CameraNativeModule', 'Camera'];
|
|
3
3
|
export const cameraAdapter = {
|
|
4
4
|
async getStatus(permission) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"camera.js","sourceRoot":"","sources":["../../../src/expo/adapters/camera.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAE1B,wBAAwB,GACzB,MAAM,
|
|
1
|
+
{"version":3,"file":"camera.js","sourceRoot":"","sources":["../../../src/expo/adapters/camera.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAE1B,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,iCAAiC,GAAG,CAAC,oBAAoB,EAAE,QAAQ,CAAU,CAAC;AAEpF,MAAM,CAAC,MAAM,aAAa,GAA0B;IAClD,KAAK,CAAC,SAAS,CAAC,UAAsB;QACpC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,6BAA6B,CAChD,MAAM,MAAM,CAAC,aAAa,CAAC,EAC3B,2BAA2B,CAC5B,EAAE,CAAC;YAEJ,OAAO,yBAAyB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAsB;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,6BAA6B,CAChD,MAAM,MAAM,CAAC,aAAa,CAAC,EAC3B,+BAA+B,CAChC,EAAE,CAAC;YAEJ,OAAO,yBAAyB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,SAAS,6BAA6B,CACpC,MAAe,EACf,UAAyE;IAEzE,MAAM,MAAM,GAAG,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,iCAAiC,CAAC,CAAC;IAE/F,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,+BAA+B,UAAU,GAAG,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type { Permission } from '../../registry/permissions';\nimport type { PermissionState } from '../../state/permissionState';\nimport type { ExpoPermissionAdapter } from '../../types/expo';\nimport {\n createExpoPermissionState,\n createExpoUnavailableState,\n type ExpoPermissionMethod,\n findExpoPermissionMethod,\n} from './permissionResponse';\n\nconst CAMERA_PERMISSION_CONTAINER_NAMES = ['CameraNativeModule', 'Camera'] as const;\n\nexport const cameraAdapter: ExpoPermissionAdapter = {\n async getStatus(permission: Permission): Promise<PermissionState> {\n try {\n const result = await resolveCameraPermissionMethod(\n await import('expo-camera'),\n 'getCameraPermissionsAsync',\n )();\n\n return createExpoPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n\n async request(permission: Permission): Promise<PermissionState> {\n try {\n const result = await resolveCameraPermissionMethod(\n await import('expo-camera'),\n 'requestCameraPermissionsAsync',\n )();\n\n return createExpoPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n};\n\nfunction resolveCameraPermissionMethod(\n source: unknown,\n methodName: 'getCameraPermissionsAsync' | 'requestCameraPermissionsAsync',\n): ExpoPermissionMethod {\n const method = findExpoPermissionMethod(source, methodName, CAMERA_PERMISSION_CONTAINER_NAMES);\n\n if (method === undefined) {\n throw new Error(`expo-camera does not export ${methodName}.`);\n }\n\n return method;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/location.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/location.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAG9D,eAAO,MAAM,eAAe,EAAE,qBA4B7B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Permission } from '../../registry/permissions';
|
|
2
|
-
import { createExpoPermissionState, createExpoUnavailableState } from '
|
|
2
|
+
import { createExpoPermissionState, createExpoUnavailableState } from './permissionResponse';
|
|
3
3
|
export const locationAdapter = {
|
|
4
4
|
async getStatus(permission) {
|
|
5
5
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"location.js","sourceRoot":"","sources":["../../../src/expo/adapters/location.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAGxD,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"location.js","sourceRoot":"","sources":["../../../src/expo/adapters/location.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAGxD,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAE7F,MAAM,CAAC,MAAM,eAAe,GAA0B;IACpD,KAAK,CAAC,SAAS,CAAC,UAAsB;QACpC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;YAC1C,MAAM,YAAY,GAAG,UAAU,KAAK,UAAU,CAAC,kBAAkB,CAAC;YAClE,MAAM,MAAM,GAAG,YAAY;gBACzB,CAAC,CAAC,MAAM,GAAG,CAAC,6BAA6B,EAAE;gBAC3C,CAAC,CAAC,MAAM,GAAG,CAAC,6BAA6B,EAAE,CAAC;YAE9C,OAAO,yBAAyB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAsB;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;YAC1C,MAAM,YAAY,GAAG,UAAU,KAAK,UAAU,CAAC,kBAAkB,CAAC;YAClE,MAAM,MAAM,GAAG,YAAY;gBACzB,CAAC,CAAC,MAAM,GAAG,CAAC,iCAAiC,EAAE;gBAC/C,CAAC,CAAC,MAAM,GAAG,CAAC,iCAAiC,EAAE,CAAC;YAElD,OAAO,yBAAyB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF,CAAC","sourcesContent":["import { Permission } from '../../registry/permissions';\nimport type { PermissionState } from '../../state/permissionState';\nimport type { ExpoPermissionAdapter } from '../../types/expo';\nimport { createExpoPermissionState, createExpoUnavailableState } from './permissionResponse';\n\nexport const locationAdapter: ExpoPermissionAdapter = {\n async getStatus(permission: Permission): Promise<PermissionState> {\n try {\n const mod = await import('expo-location');\n const isBackground = permission === Permission.LocationBackground;\n const result = isBackground\n ? await mod.getBackgroundPermissionsAsync()\n : await mod.getForegroundPermissionsAsync();\n\n return createExpoPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n\n async request(permission: Permission): Promise<PermissionState> {\n try {\n const mod = await import('expo-location');\n const isBackground = permission === Permission.LocationBackground;\n const result = isBackground\n ? await mod.requestBackgroundPermissionsAsync()\n : await mod.requestForegroundPermissionsAsync();\n\n return createExpoPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mediaLibrary.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/mediaLibrary.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"mediaLibrary.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/mediaLibrary.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAW9D,eAAO,MAAM,mBAAmB,EAAE,qBAsBjC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Permission as KnownPermission } from '../../registry/permissions';
|
|
2
2
|
import { createPermissionState } from '../../state/permissionState';
|
|
3
|
-
import { createExpoPermissionState, createExpoUnavailableState, } from '
|
|
3
|
+
import { createExpoPermissionState, createExpoUnavailableState, } from './permissionResponse';
|
|
4
4
|
export const mediaLibraryAdapter = {
|
|
5
5
|
async getStatus(permission) {
|
|
6
6
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mediaLibrary.js","sourceRoot":"","sources":["../../../src/expo/adapters/mediaLibrary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,IAAI,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAwB,MAAM,6BAA6B,CAAC;AAE1F,OAAO,EACL,yBAAyB,EACzB,0BAA0B,GAE3B,MAAM,
|
|
1
|
+
{"version":3,"file":"mediaLibrary.js","sourceRoot":"","sources":["../../../src/expo/adapters/mediaLibrary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,IAAI,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAwB,MAAM,6BAA6B,CAAC;AAE1F,OAAO,EACL,yBAAyB,EACzB,0BAA0B,GAE3B,MAAM,sBAAsB,CAAC;AAM9B,MAAM,CAAC,MAAM,mBAAmB,GAA0B;IACxD,KAAK,CAAC,SAAS,CAAC,UAAsB;QACpC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,mBAAmB,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC;YAEhF,OAAO,iCAAiC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAsB;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,uBAAuB,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC;YAEpF,OAAO,iCAAiC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,SAAS,iCAAiC,CACxC,UAAsB,EACtB,QAA4C;IAE5C,IAAI,QAAQ,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO,yBAAyB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,qBAAqB,CAAC;QAC3B,UAAU;QACV,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,MAAM,EAAE,0DAA0D;KACnE,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAAC,UAAsB;IACnD,OAAO,UAAU,KAAK,eAAe,CAAC,iBAAiB,CAAC;AAC1D,CAAC","sourcesContent":["import type { Permission } from '../../registry/permissions';\nimport { Permission as KnownPermission } from '../../registry/permissions';\nimport { createPermissionState, type PermissionState } from '../../state/permissionState';\nimport type { ExpoPermissionAdapter } from '../../types/expo';\nimport {\n createExpoPermissionState,\n createExpoUnavailableState,\n type ExpoPermissionResponse,\n} from './permissionResponse';\n\ninterface ExpoMediaLibraryPermissionResponse extends ExpoPermissionResponse {\n readonly accessPrivileges?: 'all' | 'limited' | 'none';\n}\n\nexport const mediaLibraryAdapter: ExpoPermissionAdapter = {\n async getStatus(permission: Permission): Promise<PermissionState> {\n try {\n const mod = await import('expo-media-library');\n const result = await mod.getPermissionsAsync(isWriteOnlyPermission(permission));\n\n return createMediaLibraryPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n\n async request(permission: Permission): Promise<PermissionState> {\n try {\n const mod = await import('expo-media-library');\n const result = await mod.requestPermissionsAsync(isWriteOnlyPermission(permission));\n\n return createMediaLibraryPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n};\n\nfunction createMediaLibraryPermissionState(\n permission: Permission,\n response: ExpoMediaLibraryPermissionResponse,\n): PermissionState {\n if (response.accessPrivileges !== 'limited') {\n return createExpoPermissionState(permission, response);\n }\n\n return createPermissionState({\n permission,\n status: 'limited',\n canAskAgain: response.canAskAgain,\n reason: 'Media library access is limited to user-selected assets.',\n });\n}\n\nfunction isWriteOnlyPermission(permission: Permission): boolean {\n return permission === KnownPermission.MediaLibraryWrite;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microphone.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/microphone.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"microphone.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/microphone.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAU9D,eAAO,MAAM,iBAAiB,EAAE,qBA0B/B,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createExpoPermissionState, createExpoUnavailableState, findExpoPermissionMethod, } from '
|
|
1
|
+
import { createExpoPermissionState, createExpoUnavailableState, findExpoPermissionMethod, } from './permissionResponse';
|
|
2
2
|
const AUDIO_PERMISSION_CONTAINER_NAMES = ['AudioModule', 'Audio'];
|
|
3
3
|
export const microphoneAdapter = {
|
|
4
4
|
async getStatus(permission) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microphone.js","sourceRoot":"","sources":["../../../src/expo/adapters/microphone.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAE1B,wBAAwB,GACzB,MAAM,
|
|
1
|
+
{"version":3,"file":"microphone.js","sourceRoot":"","sources":["../../../src/expo/adapters/microphone.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAE1B,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,gCAAgC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAU,CAAC;AAE3E,MAAM,CAAC,MAAM,iBAAiB,GAA0B;IACtD,KAAK,CAAC,SAAS,CAAC,UAAsB;QACpC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAC/C,MAAM,MAAM,CAAC,YAAY,CAAC,EAC1B,8BAA8B,CAC/B,EAAE,CAAC;YAEJ,OAAO,yBAAyB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAsB;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAC/C,MAAM,MAAM,CAAC,YAAY,CAAC,EAC1B,kCAAkC,CACnC,EAAE,CAAC;YAEJ,OAAO,yBAAyB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,SAAS,4BAA4B,CACnC,MAAe,EACf,UAA+E;IAE/E,MAAM,MAAM,GAAG,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,gCAAgC,CAAC,CAAC;IAE9F,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,8BAA8B,UAAU,GAAG,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type { Permission } from '../../registry/permissions';\nimport type { PermissionState } from '../../state/permissionState';\nimport type { ExpoPermissionAdapter } from '../../types/expo';\nimport {\n createExpoPermissionState,\n createExpoUnavailableState,\n type ExpoPermissionMethod,\n findExpoPermissionMethod,\n} from './permissionResponse';\n\nconst AUDIO_PERMISSION_CONTAINER_NAMES = ['AudioModule', 'Audio'] as const;\n\nexport const microphoneAdapter: ExpoPermissionAdapter = {\n async getStatus(permission: Permission): Promise<PermissionState> {\n try {\n const result = await resolveAudioPermissionMethod(\n await import('expo-audio'),\n 'getRecordingPermissionsAsync',\n )();\n\n return createExpoPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n\n async request(permission: Permission): Promise<PermissionState> {\n try {\n const result = await resolveAudioPermissionMethod(\n await import('expo-audio'),\n 'requestRecordingPermissionsAsync',\n )();\n\n return createExpoPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n};\n\nfunction resolveAudioPermissionMethod(\n source: unknown,\n methodName: 'getRecordingPermissionsAsync' | 'requestRecordingPermissionsAsync',\n): ExpoPermissionMethod {\n const method = findExpoPermissionMethod(source, methodName, AUDIO_PERMISSION_CONTAINER_NAMES);\n\n if (method === undefined) {\n throw new Error(`expo-audio does not export ${methodName}.`);\n }\n\n return method;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/notifications.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/notifications.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAa9D,eAAO,MAAM,oBAAoB,EAAE,qBAsBlC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createPermissionState } from '../../state/permissionState';
|
|
2
|
-
import { createExpoPermissionState, createExpoUnavailableState, } from '
|
|
2
|
+
import { createExpoPermissionState, createExpoUnavailableState, } from './permissionResponse';
|
|
3
3
|
export const notificationsAdapter = {
|
|
4
4
|
async getStatus(permission) {
|
|
5
5
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/expo/adapters/notifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAwB,MAAM,6BAA6B,CAAC;AAE1F,OAAO,EACL,yBAAyB,EACzB,0BAA0B,GAE3B,MAAM,
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/expo/adapters/notifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAwB,MAAM,6BAA6B,CAAC;AAE1F,OAAO,EACL,yBAAyB,EACzB,0BAA0B,GAE3B,MAAM,sBAAsB,CAAC;AAQ9B,MAAM,CAAC,MAAM,oBAAoB,GAA0B;IACzD,KAAK,CAAC,SAAS,CAAC,UAAsB;QACpC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,mBAAmB,EAAE,CAAC;YAE/C,OAAO,iCAAiC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAsB;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,uBAAuB,EAAE,CAAC;YAEnD,OAAO,iCAAiC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,SAAS,iCAAiC,CACxC,UAAsB,EACtB,QAA4C;IAE5C,QAAQ,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;QAC7B,KAAK,CAAC;YACJ,OAAO,uBAAuB,CAC5B,UAAU,EACV,QAAQ,EACR,SAAS,EACT,yDAAyD,CAC1D,CAAC;QACJ,KAAK,CAAC;YACJ,OAAO,uBAAuB,CAC5B,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,2CAA2C,CAC5C,CAAC;QACJ,KAAK,CAAC;YACJ,OAAO,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAClE,KAAK,CAAC;YACJ,OAAO,uBAAuB,CAC5B,UAAU,EACV,QAAQ,EACR,SAAS,EACT,gDAAgD,CACjD,CAAC;QACJ,KAAK,CAAC;YACJ,OAAO,uBAAuB,CAC5B,UAAU,EACV,QAAQ,EACR,SAAS,EACT,8CAA8C,CAC/C,CAAC;QACJ;YACE,OAAO,yBAAyB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAC9B,UAAsB,EACtB,QAA4C,EAC5C,MAAiC,EACjC,MAAe;IAEf,MAAM,KAAK,GAAG,yBAAyB,CAAC,UAAU,EAAE;QAClD,MAAM;QACN,WAAW,EAAE,QAAQ,CAAC,WAAW;KAClC,CAAC,CAAC;IAEH,OAAO,qBAAqB,CAAC;QAC3B,UAAU;QACV,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM;KAC/B,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { Permission } from '../../registry/permissions';\nimport { createPermissionState, type PermissionState } from '../../state/permissionState';\nimport type { ExpoPermissionAdapter } from '../../types/expo';\nimport {\n createExpoPermissionState,\n createExpoUnavailableState,\n type ExpoPermissionResponse,\n} from './permissionResponse';\n\ninterface ExpoNotificationPermissionResponse extends ExpoPermissionResponse {\n readonly ios?: {\n readonly status?: number;\n };\n}\n\nexport const notificationsAdapter: ExpoPermissionAdapter = {\n async getStatus(permission: Permission): Promise<PermissionState> {\n try {\n const mod = await import('expo-notifications');\n const result = await mod.getPermissionsAsync();\n\n return createNotificationPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n\n async request(permission: Permission): Promise<PermissionState> {\n try {\n const mod = await import('expo-notifications');\n const result = await mod.requestPermissionsAsync();\n\n return createNotificationPermissionState(permission, result);\n } catch (error) {\n return createExpoUnavailableState(permission, error);\n }\n },\n};\n\nfunction createNotificationPermissionState(\n permission: Permission,\n response: ExpoNotificationPermissionResponse,\n): PermissionState {\n switch (response.ios?.status) {\n case 0:\n return createNotificationState(\n permission,\n response,\n 'unknown',\n 'iOS notification authorization has not been determined.',\n );\n case 1:\n return createNotificationState(\n permission,\n response,\n 'denied',\n 'iOS notification authorization is denied.',\n );\n case 2:\n return createNotificationState(permission, response, 'granted');\n case 3:\n return createNotificationState(\n permission,\n response,\n 'limited',\n 'iOS notification authorization is provisional.',\n );\n case 4:\n return createNotificationState(\n permission,\n response,\n 'limited',\n 'iOS notification authorization is ephemeral.',\n );\n default:\n return createExpoPermissionState(permission, response);\n }\n}\n\nfunction createNotificationState(\n permission: Permission,\n response: ExpoNotificationPermissionResponse,\n status: PermissionState['status'],\n reason?: string,\n): PermissionState {\n const state = createExpoPermissionState(permission, {\n status,\n canAskAgain: response.canAskAgain,\n });\n\n return createPermissionState({\n permission,\n status: state.status,\n canAskAgain: state.canAskAgain,\n reason: state.reason ?? reason,\n });\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Permission } from '
|
|
2
|
-
import { type PermissionState } from '
|
|
1
|
+
import type { Permission } from '../../registry/permissions';
|
|
2
|
+
import { type PermissionState } from '../../state/permissionState';
|
|
3
3
|
export interface ExpoPermissionResponse {
|
|
4
4
|
readonly status: string;
|
|
5
5
|
readonly canAskAgain?: boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionResponse.d.ts","sourceRoot":"","sources":["../../../src/expo/adapters/permissionResponse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAEzE,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,sBAAsB,GAC/B,eAAe,CAIjB;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,OAAO,GACb,eAAe,CAMjB;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,MAAM,EAClB,cAAc,GAAE,SAAS,MAAM,EAAO,GACrC,oBAAoB,GAAG,SAAS,CAkBlC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createPermissionState, isPermissionStatus, } from '
|
|
1
|
+
import { createPermissionState, isPermissionStatus, } from '../../state/permissionState';
|
|
2
2
|
export function createExpoPermissionState(permission, response) {
|
|
3
3
|
const status = isPermissionStatus(response.status) ? response.status : 'unknown';
|
|
4
4
|
return createNormalizedExpoPermissionState(permission, response, status);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionResponse.js","sourceRoot":"","sources":["../../../src/expo/adapters/permissionResponse.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,GAGnB,MAAM,6BAA6B,CAAC;AASrC,MAAM,UAAU,yBAAyB,CACvC,UAAsB,EACtB,QAAgC;IAEhC,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAEjF,OAAO,mCAAmC,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,UAAsB,EACtB,KAAc;IAEd,OAAO,qBAAqB,CAAC;QAC3B,UAAU;QACV,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,6BAA6B,CAAC,KAAK,CAAC;KAC7C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,MAAe,EACf,UAAkB,EAClB,iBAAoC,EAAE;IAEtC,IAAI,uBAAuB,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QAChD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAErD,IAAI,uBAAuB,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC;YACnD,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,6BAA6B,CAAC,KAAc;IACnD,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvD,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,mCAAmC,CAAC;AAC7C,CAAC;AAED,SAAS,mCAAmC,CAC1C,UAAsB,EACtB,QAAgC,EAChC,MAAwB,EACxB,MAAe;IAEf,MAAM,gBAAgB,GACpB,MAAM,KAAK,QAAQ,IAAI,QAAQ,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IAE7E,OAAO,qBAAqB,CAAC;QAC3B,UAAU;QACV,MAAM,EAAE,gBAAgB;QACxB,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,MAAM,EACJ,gBAAgB,KAAK,SAAS;YAC5B,CAAC,CAAC,2DAA2D;YAC7D,CAAC,CAAC,MAAM;KACb,CAAC,CAAC;AACL,CAAC;AAED,SAAS,uBAAuB,CAC9B,KAAc,EACd,UAAkB;IAElB,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK,UAAU,CAAC;AACjF,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC","sourcesContent":["import type { Permission } from '../../registry/permissions';\nimport {\n createPermissionState,\n isPermissionStatus,\n type PermissionState,\n type PermissionStatus,\n} from '../../state/permissionState';\n\nexport interface ExpoPermissionResponse {\n readonly status: string;\n readonly canAskAgain?: boolean;\n}\n\nexport type ExpoPermissionMethod = () => Promise<ExpoPermissionResponse>;\n\nexport function createExpoPermissionState(\n permission: Permission,\n response: ExpoPermissionResponse,\n): PermissionState {\n const status = isPermissionStatus(response.status) ? response.status : 'unknown';\n\n return createNormalizedExpoPermissionState(permission, response, status);\n}\n\nexport function createExpoUnavailableState(\n permission: Permission,\n error: unknown,\n): PermissionState {\n return createPermissionState({\n permission,\n status: 'unavailable',\n reason: getExpoPermissionErrorMessage(error),\n });\n}\n\nexport function findExpoPermissionMethod(\n source: unknown,\n methodName: string,\n containerNames: readonly string[] = [],\n): ExpoPermissionMethod | undefined {\n if (hasExpoPermissionMethod(source, methodName)) {\n return Reflect.get(source, methodName);\n }\n\n if (!isRecord(source)) {\n return undefined;\n }\n\n for (const containerName of containerNames) {\n const container = Reflect.get(source, containerName);\n\n if (hasExpoPermissionMethod(container, methodName)) {\n return Reflect.get(container, methodName);\n }\n }\n\n return undefined;\n}\n\nfunction getExpoPermissionErrorMessage(error: unknown): string {\n if (error instanceof Error && error.message.length > 0) {\n return error.message;\n }\n\n if (typeof error === 'string' && error.length > 0) {\n return error;\n }\n\n return 'Expo permission operation failed.';\n}\n\nfunction createNormalizedExpoPermissionState(\n permission: Permission,\n response: ExpoPermissionResponse,\n status: PermissionStatus,\n reason?: string,\n): PermissionState {\n const normalizedStatus =\n status === 'denied' && response.canAskAgain === false ? 'blocked' : status;\n\n return createPermissionState({\n permission,\n status: normalizedStatus,\n canAskAgain: response.canAskAgain,\n reason:\n normalizedStatus === 'blocked'\n ? 'Permission is blocked. Open system settings to change it.'\n : reason,\n });\n}\n\nfunction hasExpoPermissionMethod(\n value: unknown,\n methodName: string,\n): value is Record<string, ExpoPermissionMethod> {\n return isRecord(value) && typeof Reflect.get(value, methodName) === 'function';\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n"]}
|
package/dist/expo/client.d.ts
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import type { PermissionClient } from '../client/types';
|
|
2
|
-
import { Permission } from '../registry/permissions';
|
|
3
|
-
import { type PermissionState } from '../state/permissionState';
|
|
4
|
-
export interface ExpoPermissionAdapter {
|
|
5
|
-
getStatus(permission: Permission): Promise<PermissionState>;
|
|
6
|
-
request(permission: Permission): Promise<PermissionState>;
|
|
7
|
-
}
|
|
8
2
|
/***
|
|
9
3
|
* Creates a permission client backed by Expo SDK modules.
|
|
10
4
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/expo/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/expo/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAuBxD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAkDzD"}
|
package/dist/expo/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/expo/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAwB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/expo/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAwB,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,2BAA2B,GAAG,sCAAsC,CAAC;AAE3E,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAoC;IAC1D,CAAC,UAAU,CAAC,MAAM,EAAE,aAAa,CAAC;IAClC,CAAC,UAAU,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC9C,CAAC,UAAU,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;IACnD,CAAC,UAAU,CAAC,UAAU,EAAE,iBAAiB,CAAC;IAC1C,CAAC,UAAU,CAAC,kBAAkB,EAAE,eAAe,CAAC;IAChD,CAAC,UAAU,CAAC,kBAAkB,EAAE,eAAe,CAAC;IAChD,CAAC,UAAU,CAAC,aAAa,EAAE,oBAAoB,CAAC;CACjD,CAAC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,UAAsB;YACpC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,QAAQ,CAAC,OAAO,KAAK,aAAa,IAAI,QAAQ,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;gBAChF,OAAO,6BAA6B,CAAC,UAAU,CAAC,CAAC;YACnD,CAAC;YAED,IAAI,QAAQ,CAAC,OAAO,KAAK,aAAa,EAAE,CAAC;gBACvC,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAC;YAC5C,CAAC;YAED,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,yCAAyC,UAAU,EAAE,CAAC,CAAC;YACzE,CAAC;YAED,OAAO,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,UAAsB;YAClC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,QAAQ,CAAC,OAAO,KAAK,aAAa,IAAI,QAAQ,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;gBAChF,OAAO,6BAA6B,CAAC,UAAU,CAAC,CAAC;YACnD,CAAC;YAED,IAAI,QAAQ,CAAC,OAAO,KAAK,aAAa,EAAE,CAAC;gBACvC,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAC;YAC5C,CAAC;YAED,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,yCAAyC,UAAU,EAAE,CAAC,CAAC;YACzE,CAAC;YAED,OAAO,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACrC,CAAC;QAED,KAAK,CAAC,YAAY;YAChB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;gBAE7C,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;YAC/B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE;oBAC3C,KAAK,EAAE,KAAK;iBACb,CAAC,CAAC;YACL,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,UAAsB;IAClD,OAAO,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,6BAA6B,CAAC,UAAsB;IAC3D,OAAO,qBAAqB,CAAC;QAC3B,UAAU;QACV,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,cAAc,UAAU,2CAA2C;KAC5E,CAAC,CAAC;AACL,CAAC;AAED,SAAS,sBAAsB,CAAC,UAAsB;IACpD,OAAO,qBAAqB,CAAC;QAC3B,UAAU;QACV,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { PermissionClient } from '../client/types';\nimport { Permission } from '../registry/permissions';\nimport { createPermissionState, type PermissionState } from '../state/permissionState';\nimport type { ExpoPermissionAdapter } from '../types/expo';\nimport { cameraAdapter } from './adapters/camera';\nimport { locationAdapter } from './adapters/location';\nimport { mediaLibraryAdapter } from './adapters/mediaLibrary';\nimport { microphoneAdapter } from './adapters/microphone';\nimport { notificationsAdapter } from './adapters/notifications';\nimport { EXPO_PERMISSION_SUPPORT } from './manifest';\n\nconst OPEN_SETTINGS_ERROR_MESSAGE = 'Unable to open application settings.';\n\nconst adapters = new Map<Permission, ExpoPermissionAdapter>([\n [Permission.Camera, cameraAdapter],\n [Permission.MediaLibrary, mediaLibraryAdapter],\n [Permission.MediaLibraryWrite, mediaLibraryAdapter],\n [Permission.Microphone, microphoneAdapter],\n [Permission.LocationForeground, locationAdapter],\n [Permission.LocationBackground, locationAdapter],\n [Permission.Notifications, notificationsAdapter],\n]);\n\n/***\n * Creates a permission client backed by Expo SDK modules.\n *\n * Denials that Expo cannot request again are normalized to `blocked`. Limited\n * media-library access and provisional or ephemeral iOS notification access\n * are normalized to usable `limited` states, where `granted` remains true.\n * The client requires `expo-linking` for settings recovery and rejects with a\n * stable error when the operating-system settings page cannot be opened.\n *\n * Expo modules are loaded only when a client operation uses them. The package\n * root and Expo manifest metadata remain free of native module imports.\n *\n * @readme\n */\nexport function createPermissionClient(): PermissionClient {\n return {\n async getStatus(permission: Permission): Promise<PermissionState> {\n const metadata = getPermissionSupport(permission);\n if (metadata.support === 'unsupported' || metadata.support === 'notImplemented') {\n return createUnavailableSupportState(permission);\n }\n\n if (metadata.support === 'notRequired') {\n return createNotRequiredState(permission);\n }\n\n const adapter = adapters.get(permission);\n if (!adapter) {\n throw new Error(`No adapter registered for permission: ${permission}`);\n }\n\n return adapter.getStatus(permission);\n },\n\n async request(permission: Permission): Promise<PermissionState> {\n const metadata = getPermissionSupport(permission);\n if (metadata.support === 'unsupported' || metadata.support === 'notImplemented') {\n return createUnavailableSupportState(permission);\n }\n\n if (metadata.support === 'notRequired') {\n return createNotRequiredState(permission);\n }\n\n const adapter = adapters.get(permission);\n if (!adapter) {\n throw new Error(`No adapter registered for permission: ${permission}`);\n }\n\n return adapter.request(permission);\n },\n\n async openSettings(): Promise<void> {\n try {\n const linking = await import('expo-linking');\n\n await linking.openSettings();\n } catch (error) {\n throw new Error(OPEN_SETTINGS_ERROR_MESSAGE, {\n cause: error,\n });\n }\n },\n };\n}\n\nfunction getPermissionSupport(permission: Permission) {\n return Reflect.get(EXPO_PERMISSION_SUPPORT, permission);\n}\n\nfunction createUnavailableSupportState(permission: Permission): PermissionState {\n return createPermissionState({\n permission,\n status: 'unavailable',\n reason: `Permission ${permission} is not implemented or supported on Expo.`,\n });\n}\n\nfunction createNotRequiredState(permission: Permission): PermissionState {\n return createPermissionState({\n permission,\n status: 'granted',\n });\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Permission } from '../registry/permissions';
|
|
2
|
+
import type { PermissionState } from '../state/permissionState';
|
|
3
|
+
export interface ExpoPermissionAdapter {
|
|
4
|
+
getStatus(permission: Permission): Promise<PermissionState>;
|
|
5
|
+
request(permission: Permission): Promise<PermissionState>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=expo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expo.d.ts","sourceRoot":"","sources":["../../src/types/expo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5D,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC3D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expo.js","sourceRoot":"","sources":["../../src/types/expo.ts"],"names":[],"mappings":"","sourcesContent":["import type { Permission } from '../registry/permissions';\nimport type { PermissionState } from '../state/permissionState';\n\nexport interface ExpoPermissionAdapter {\n getStatus(permission: Permission): Promise<PermissionState>;\n request(permission: Permission): Promise<PermissionState>;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/permissions",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "Cross-platform permission registry and runtime helpers for Expo, React Native, and React Native Web apps, with unified request/check APIs for camera, media, location, notifications, microphone, and other web/native capabilities.",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/permissions#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -34,7 +34,10 @@
|
|
|
34
34
|
"typescript",
|
|
35
35
|
"web"
|
|
36
36
|
],
|
|
37
|
-
"dependencies": {
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@ankhorage/ankh": "^0.12.0",
|
|
39
|
+
"@ankhorage/contracts": "^24.1.0"
|
|
40
|
+
},
|
|
38
41
|
"peerDependencies": {
|
|
39
42
|
"react": ">=18.2.0 || >=19.0.0"
|
|
40
43
|
},
|
|
@@ -42,10 +45,66 @@
|
|
|
42
45
|
"category": "permissions",
|
|
43
46
|
"provider": "./dist/cli/index.js",
|
|
44
47
|
"capabilities": [
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
{
|
|
49
|
+
"id": "permissions.inspect",
|
|
50
|
+
"owner": "@ankhorage/permissions",
|
|
51
|
+
"access": [
|
|
52
|
+
"invoke"
|
|
53
|
+
],
|
|
54
|
+
"binding": {
|
|
55
|
+
"kind": "action",
|
|
56
|
+
"bindableAs": [
|
|
57
|
+
"target"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"label": "Inspect permissions",
|
|
61
|
+
"description": "List known permission identifiers and registry metadata."
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "permissions.check",
|
|
65
|
+
"owner": "@ankhorage/permissions",
|
|
66
|
+
"access": [
|
|
67
|
+
"invoke"
|
|
68
|
+
],
|
|
69
|
+
"binding": {
|
|
70
|
+
"kind": "action",
|
|
71
|
+
"bindableAs": [
|
|
72
|
+
"target"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"label": "Check permission",
|
|
76
|
+
"description": "Check a permission state through a host-provided permission client."
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "permissions.request",
|
|
80
|
+
"owner": "@ankhorage/permissions",
|
|
81
|
+
"access": [
|
|
82
|
+
"invoke"
|
|
83
|
+
],
|
|
84
|
+
"binding": {
|
|
85
|
+
"kind": "action",
|
|
86
|
+
"bindableAs": [
|
|
87
|
+
"target"
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
"label": "Request permission",
|
|
91
|
+
"description": "Request a permission through a host-provided permission client."
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "permissions.manifest",
|
|
95
|
+
"owner": "@ankhorage/permissions",
|
|
96
|
+
"access": [
|
|
97
|
+
"invoke"
|
|
98
|
+
],
|
|
99
|
+
"binding": {
|
|
100
|
+
"kind": "action",
|
|
101
|
+
"bindableAs": [
|
|
102
|
+
"target"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"label": "Inspect permission manifest",
|
|
106
|
+
"description": "Show native and web manifest metadata required by registered permissions."
|
|
107
|
+
}
|
|
49
108
|
]
|
|
50
109
|
},
|
|
51
110
|
"files": [
|
|
@@ -69,6 +128,11 @@
|
|
|
69
128
|
"import": "./dist/cli/index.js",
|
|
70
129
|
"default": "./dist/cli/index.js"
|
|
71
130
|
},
|
|
131
|
+
"./capabilities": {
|
|
132
|
+
"types": "./dist/capabilities/index.d.ts",
|
|
133
|
+
"import": "./dist/capabilities/index.js",
|
|
134
|
+
"default": "./dist/capabilities/index.js"
|
|
135
|
+
},
|
|
72
136
|
"./react": {
|
|
73
137
|
"react-native": "./dist/react/index.js",
|
|
74
138
|
"browser": "./dist/react/index.js",
|
|
@@ -136,8 +200,8 @@
|
|
|
136
200
|
"knip:check": "ankhorage-knip"
|
|
137
201
|
},
|
|
138
202
|
"devDependencies": {
|
|
139
|
-
"@ankhorage/devtools": "^1.
|
|
140
|
-
"@ankhorage/paradox": "^0.2.
|
|
203
|
+
"@ankhorage/devtools": "^2.1.19",
|
|
204
|
+
"@ankhorage/paradox": "^0.2.28",
|
|
141
205
|
"@types/bun": "^1.4.2",
|
|
142
206
|
"@types/node": "^26.6.4",
|
|
143
207
|
"@types/react": "^19.3.0",
|
package/src/ankh.provider.ts
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
+
import type { AnkhRuntimeCommandProvider } from '@ankhorage/ankh';
|
|
2
|
+
import type { Capability } from '@ankhorage/contracts/capabilities';
|
|
3
|
+
import type { AnkhCommandDescriptor } from '@ankhorage/contracts/cli';
|
|
4
|
+
|
|
5
|
+
import packageJson from '../package.json';
|
|
6
|
+
import { CAPABILITIES } from './capabilities/index';
|
|
1
7
|
import { PERMISSIONS } from './registry/permissions';
|
|
2
8
|
|
|
3
9
|
const PERMISSIONS_PACKAGE_NAME = '@ankhorage/permissions';
|
|
4
|
-
const PERMISSIONS_PACKAGE_VERSION = '0.2.0';
|
|
5
10
|
const PERMISSIONS_COMMAND_CATEGORY = 'permissions';
|
|
6
11
|
|
|
7
|
-
const PERMISSIONS_CAPABILITIES = [
|
|
8
|
-
'permissions.inspect',
|
|
9
|
-
'permissions.check',
|
|
10
|
-
'permissions.request',
|
|
11
|
-
'permissions.manifest',
|
|
12
|
-
] as const;
|
|
13
|
-
|
|
14
12
|
const commands = [
|
|
15
13
|
{
|
|
16
14
|
path: ['list'],
|
|
17
15
|
summary: 'List known permission identifiers and registry metadata.',
|
|
18
|
-
capability: 'permissions.inspect',
|
|
16
|
+
capability: 'permissions.inspect' satisfies Capability['id'],
|
|
19
17
|
aliases: ['registry'],
|
|
20
18
|
examples: ['ankh permissions list'],
|
|
21
19
|
},
|
|
22
20
|
{
|
|
23
21
|
path: ['check'],
|
|
24
22
|
summary: 'Check a permission state through a host-provided permission client.',
|
|
25
|
-
capability: 'permissions.check',
|
|
23
|
+
capability: 'permissions.check' satisfies Capability['id'],
|
|
26
24
|
examples: ['ankh permissions check camera'],
|
|
27
25
|
},
|
|
28
26
|
{
|
|
29
27
|
path: ['request'],
|
|
30
28
|
summary: 'Request a permission through a host-provided permission client.',
|
|
31
|
-
capability: 'permissions.request',
|
|
29
|
+
capability: 'permissions.request' satisfies Capability['id'],
|
|
32
30
|
examples: ['ankh permissions request camera'],
|
|
33
31
|
},
|
|
34
32
|
{
|
|
35
33
|
path: ['manifest'],
|
|
36
34
|
summary: 'Show native/web manifest metadata required by registered permissions.',
|
|
37
|
-
capability: 'permissions.manifest',
|
|
35
|
+
capability: 'permissions.manifest' satisfies Capability['id'],
|
|
38
36
|
examples: ['ankh permissions manifest camera'],
|
|
39
37
|
},
|
|
40
|
-
] as const
|
|
38
|
+
] as const satisfies readonly (AnkhCommandDescriptor & {
|
|
39
|
+
readonly capability: Capability['id'];
|
|
40
|
+
})[];
|
|
41
41
|
|
|
42
42
|
const handlers = commands.map((command) => ({
|
|
43
43
|
path: command.path,
|
|
@@ -57,10 +57,10 @@ const handlers = commands.map((command) => ({
|
|
|
57
57
|
const provider = {
|
|
58
58
|
id: PERMISSIONS_PACKAGE_NAME,
|
|
59
59
|
category: PERMISSIONS_COMMAND_CATEGORY,
|
|
60
|
-
version:
|
|
61
|
-
capabilities:
|
|
60
|
+
version: packageJson.version,
|
|
61
|
+
capabilities: CAPABILITIES,
|
|
62
62
|
commands,
|
|
63
63
|
handlers,
|
|
64
|
-
};
|
|
64
|
+
} as const satisfies AnkhRuntimeCommandProvider;
|
|
65
65
|
|
|
66
66
|
export default provider;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isCapability } from '@ankhorage/contracts/capabilities';
|
|
2
|
+
import { describe, expect, test } from 'bun:test';
|
|
3
|
+
|
|
4
|
+
import { CAPABILITIES } from './index';
|
|
5
|
+
|
|
6
|
+
describe('CAPABILITIES', () => {
|
|
7
|
+
test('publishes canonical executable action targets', () => {
|
|
8
|
+
expect(CAPABILITIES).toHaveLength(4);
|
|
9
|
+
for (const capability of CAPABILITIES) {
|
|
10
|
+
expect(isCapability(capability)).toBeTrue();
|
|
11
|
+
expect(capability.access).toEqual(['invoke']);
|
|
12
|
+
expect(capability.binding).toEqual({ kind: 'action', bindableAs: ['target'] });
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Capability } from '@ankhorage/contracts/capabilities';
|
|
2
|
+
|
|
3
|
+
/*** Define the executable permission operations published by this package. */
|
|
4
|
+
export const CAPABILITIES = [
|
|
5
|
+
{
|
|
6
|
+
id: 'permissions.inspect',
|
|
7
|
+
owner: '@ankhorage/permissions',
|
|
8
|
+
access: ['invoke'],
|
|
9
|
+
binding: { kind: 'action', bindableAs: ['target'] },
|
|
10
|
+
label: 'Inspect permissions',
|
|
11
|
+
description: 'List known permission identifiers and registry metadata.',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'permissions.check',
|
|
15
|
+
owner: '@ankhorage/permissions',
|
|
16
|
+
access: ['invoke'],
|
|
17
|
+
binding: { kind: 'action', bindableAs: ['target'] },
|
|
18
|
+
label: 'Check permission',
|
|
19
|
+
description: 'Check a permission state through a host-provided permission client.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'permissions.request',
|
|
23
|
+
owner: '@ankhorage/permissions',
|
|
24
|
+
access: ['invoke'],
|
|
25
|
+
binding: { kind: 'action', bindableAs: ['target'] },
|
|
26
|
+
label: 'Request permission',
|
|
27
|
+
description: 'Request a permission through a host-provided permission client.',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'permissions.manifest',
|
|
31
|
+
owner: '@ankhorage/permissions',
|
|
32
|
+
access: ['invoke'],
|
|
33
|
+
binding: { kind: 'action', bindableAs: ['target'] },
|
|
34
|
+
label: 'Inspect permission manifest',
|
|
35
|
+
description: 'Show native and web manifest metadata required by registered permissions.',
|
|
36
|
+
},
|
|
37
|
+
] as const satisfies readonly Capability[];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Permission } from '../../registry/permissions';
|
|
2
2
|
import type { PermissionState } from '../../state/permissionState';
|
|
3
|
-
import type { ExpoPermissionAdapter } from '
|
|
3
|
+
import type { ExpoPermissionAdapter } from '../../types/expo';
|
|
4
4
|
import {
|
|
5
5
|
createExpoPermissionState,
|
|
6
6
|
createExpoUnavailableState,
|
|
7
7
|
type ExpoPermissionMethod,
|
|
8
8
|
findExpoPermissionMethod,
|
|
9
|
-
} from '
|
|
9
|
+
} from './permissionResponse';
|
|
10
10
|
|
|
11
11
|
const CAMERA_PERMISSION_CONTAINER_NAMES = ['CameraNativeModule', 'Camera'] as const;
|
|
12
12
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Permission } from '../../registry/permissions';
|
|
2
2
|
import type { PermissionState } from '../../state/permissionState';
|
|
3
|
-
import type { ExpoPermissionAdapter } from '
|
|
4
|
-
import { createExpoPermissionState, createExpoUnavailableState } from '
|
|
3
|
+
import type { ExpoPermissionAdapter } from '../../types/expo';
|
|
4
|
+
import { createExpoPermissionState, createExpoUnavailableState } from './permissionResponse';
|
|
5
5
|
|
|
6
6
|
export const locationAdapter: ExpoPermissionAdapter = {
|
|
7
7
|
async getStatus(permission: Permission): Promise<PermissionState> {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Permission } from '../../registry/permissions';
|
|
2
2
|
import { Permission as KnownPermission } from '../../registry/permissions';
|
|
3
3
|
import { createPermissionState, type PermissionState } from '../../state/permissionState';
|
|
4
|
-
import type { ExpoPermissionAdapter } from '
|
|
4
|
+
import type { ExpoPermissionAdapter } from '../../types/expo';
|
|
5
5
|
import {
|
|
6
6
|
createExpoPermissionState,
|
|
7
7
|
createExpoUnavailableState,
|
|
8
8
|
type ExpoPermissionResponse,
|
|
9
|
-
} from '
|
|
9
|
+
} from './permissionResponse';
|
|
10
10
|
|
|
11
11
|
interface ExpoMediaLibraryPermissionResponse extends ExpoPermissionResponse {
|
|
12
12
|
readonly accessPrivileges?: 'all' | 'limited' | 'none';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Permission } from '../../registry/permissions';
|
|
2
2
|
import type { PermissionState } from '../../state/permissionState';
|
|
3
|
-
import type { ExpoPermissionAdapter } from '
|
|
3
|
+
import type { ExpoPermissionAdapter } from '../../types/expo';
|
|
4
4
|
import {
|
|
5
5
|
createExpoPermissionState,
|
|
6
6
|
createExpoUnavailableState,
|
|
7
7
|
type ExpoPermissionMethod,
|
|
8
8
|
findExpoPermissionMethod,
|
|
9
|
-
} from '
|
|
9
|
+
} from './permissionResponse';
|
|
10
10
|
|
|
11
11
|
const AUDIO_PERMISSION_CONTAINER_NAMES = ['AudioModule', 'Audio'] as const;
|
|
12
12
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Permission } from '../../registry/permissions';
|
|
2
2
|
import { createPermissionState, type PermissionState } from '../../state/permissionState';
|
|
3
|
-
import type { ExpoPermissionAdapter } from '
|
|
3
|
+
import type { ExpoPermissionAdapter } from '../../types/expo';
|
|
4
4
|
import {
|
|
5
5
|
createExpoPermissionState,
|
|
6
6
|
createExpoUnavailableState,
|
|
7
7
|
type ExpoPermissionResponse,
|
|
8
|
-
} from '
|
|
8
|
+
} from './permissionResponse';
|
|
9
9
|
|
|
10
10
|
interface ExpoNotificationPermissionResponse extends ExpoPermissionResponse {
|
|
11
11
|
readonly ios?: {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Permission } from '
|
|
1
|
+
import type { Permission } from '../../registry/permissions';
|
|
2
2
|
import {
|
|
3
3
|
createPermissionState,
|
|
4
4
|
isPermissionStatus,
|
|
5
5
|
type PermissionState,
|
|
6
6
|
type PermissionStatus,
|
|
7
|
-
} from '
|
|
7
|
+
} from '../../state/permissionState';
|
|
8
8
|
|
|
9
9
|
export interface ExpoPermissionResponse {
|
|
10
10
|
readonly status: string;
|
package/src/expo/client.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PermissionClient } from '../client/types';
|
|
2
2
|
import { Permission } from '../registry/permissions';
|
|
3
3
|
import { createPermissionState, type PermissionState } from '../state/permissionState';
|
|
4
|
+
import type { ExpoPermissionAdapter } from '../types/expo';
|
|
4
5
|
import { cameraAdapter } from './adapters/camera';
|
|
5
6
|
import { locationAdapter } from './adapters/location';
|
|
6
7
|
import { mediaLibraryAdapter } from './adapters/mediaLibrary';
|
|
@@ -10,11 +11,6 @@ import { EXPO_PERMISSION_SUPPORT } from './manifest';
|
|
|
10
11
|
|
|
11
12
|
const OPEN_SETTINGS_ERROR_MESSAGE = 'Unable to open application settings.';
|
|
12
13
|
|
|
13
|
-
export interface ExpoPermissionAdapter {
|
|
14
|
-
getStatus(permission: Permission): Promise<PermissionState>;
|
|
15
|
-
request(permission: Permission): Promise<PermissionState>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
14
|
const adapters = new Map<Permission, ExpoPermissionAdapter>([
|
|
19
15
|
[Permission.Camera, cameraAdapter],
|
|
20
16
|
[Permission.MediaLibrary, mediaLibraryAdapter],
|
package/src/provider.test.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test';
|
|
2
2
|
|
|
3
|
+
import packageJson from '../package.json';
|
|
3
4
|
import provider from './ankh.provider';
|
|
5
|
+
import { CAPABILITIES } from './capabilities/index';
|
|
4
6
|
|
|
5
7
|
describe('provider', () => {
|
|
6
8
|
test('declares permission command metadata', () => {
|
|
@@ -10,4 +12,32 @@ describe('provider', () => {
|
|
|
10
12
|
provider.commands.map((entry) => entry.path.join(' ')),
|
|
11
13
|
);
|
|
12
14
|
});
|
|
15
|
+
|
|
16
|
+
test('keeps package metadata, provider metadata, and catalog aligned', () => {
|
|
17
|
+
expect(packageJson.ankh.capabilities).toEqual(
|
|
18
|
+
CAPABILITIES.map((capability) => ({
|
|
19
|
+
...capability,
|
|
20
|
+
access: [...capability.access],
|
|
21
|
+
binding: {
|
|
22
|
+
...capability.binding,
|
|
23
|
+
bindableAs: [...capability.binding.bindableAs],
|
|
24
|
+
},
|
|
25
|
+
})),
|
|
26
|
+
);
|
|
27
|
+
expect(provider.capabilities).toEqual(CAPABILITIES);
|
|
28
|
+
expect(provider.version).toBe(packageJson.version);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('maps every command to its canonical capability by ID', () => {
|
|
32
|
+
expect(provider.commands.map(({ path, capability }) => ({ path, capability }))).toEqual([
|
|
33
|
+
{ path: ['list'], capability: 'permissions.inspect' },
|
|
34
|
+
{ path: ['check'], capability: 'permissions.check' },
|
|
35
|
+
{ path: ['request'], capability: 'permissions.request' },
|
|
36
|
+
{ path: ['manifest'], capability: 'permissions.manifest' },
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
expect([...provider.commands.map(({ capability }) => capability)].sort()).toEqual(
|
|
40
|
+
[...CAPABILITIES.map(({ id }) => id)].sort(),
|
|
41
|
+
);
|
|
42
|
+
});
|
|
13
43
|
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Permission } from '../registry/permissions';
|
|
2
|
+
import type { PermissionState } from '../state/permissionState';
|
|
3
|
+
|
|
4
|
+
export interface ExpoPermissionAdapter {
|
|
5
|
+
getStatus(permission: Permission): Promise<PermissionState>;
|
|
6
|
+
request(permission: Permission): Promise<PermissionState>;
|
|
7
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"permissionResponse.d.ts","sourceRoot":"","sources":["../../src/expo/permissionResponse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAEzE,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,sBAAsB,GAC/B,eAAe,CAIjB;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,OAAO,GACb,eAAe,CAMjB;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,MAAM,EAClB,cAAc,GAAE,SAAS,MAAM,EAAO,GACrC,oBAAoB,GAAG,SAAS,CAkBlC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"permissionResponse.js","sourceRoot":"","sources":["../../src/expo/permissionResponse.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,GAGnB,MAAM,0BAA0B,CAAC;AASlC,MAAM,UAAU,yBAAyB,CACvC,UAAsB,EACtB,QAAgC;IAEhC,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAEjF,OAAO,mCAAmC,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,UAAsB,EACtB,KAAc;IAEd,OAAO,qBAAqB,CAAC;QAC3B,UAAU;QACV,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,6BAA6B,CAAC,KAAK,CAAC;KAC7C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,MAAe,EACf,UAAkB,EAClB,iBAAoC,EAAE;IAEtC,IAAI,uBAAuB,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QAChD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAErD,IAAI,uBAAuB,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC;YACnD,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,6BAA6B,CAAC,KAAc;IACnD,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvD,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,mCAAmC,CAAC;AAC7C,CAAC;AAED,SAAS,mCAAmC,CAC1C,UAAsB,EACtB,QAAgC,EAChC,MAAwB,EACxB,MAAe;IAEf,MAAM,gBAAgB,GACpB,MAAM,KAAK,QAAQ,IAAI,QAAQ,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IAE7E,OAAO,qBAAqB,CAAC;QAC3B,UAAU;QACV,MAAM,EAAE,gBAAgB;QACxB,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,MAAM,EACJ,gBAAgB,KAAK,SAAS;YAC5B,CAAC,CAAC,2DAA2D;YAC7D,CAAC,CAAC,MAAM;KACb,CAAC,CAAC;AACL,CAAC;AAED,SAAS,uBAAuB,CAC9B,KAAc,EACd,UAAkB;IAElB,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK,UAAU,CAAC;AACjF,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC","sourcesContent":["import type { Permission } from '../registry/permissions';\nimport {\n createPermissionState,\n isPermissionStatus,\n type PermissionState,\n type PermissionStatus,\n} from '../state/permissionState';\n\nexport interface ExpoPermissionResponse {\n readonly status: string;\n readonly canAskAgain?: boolean;\n}\n\nexport type ExpoPermissionMethod = () => Promise<ExpoPermissionResponse>;\n\nexport function createExpoPermissionState(\n permission: Permission,\n response: ExpoPermissionResponse,\n): PermissionState {\n const status = isPermissionStatus(response.status) ? response.status : 'unknown';\n\n return createNormalizedExpoPermissionState(permission, response, status);\n}\n\nexport function createExpoUnavailableState(\n permission: Permission,\n error: unknown,\n): PermissionState {\n return createPermissionState({\n permission,\n status: 'unavailable',\n reason: getExpoPermissionErrorMessage(error),\n });\n}\n\nexport function findExpoPermissionMethod(\n source: unknown,\n methodName: string,\n containerNames: readonly string[] = [],\n): ExpoPermissionMethod | undefined {\n if (hasExpoPermissionMethod(source, methodName)) {\n return Reflect.get(source, methodName);\n }\n\n if (!isRecord(source)) {\n return undefined;\n }\n\n for (const containerName of containerNames) {\n const container = Reflect.get(source, containerName);\n\n if (hasExpoPermissionMethod(container, methodName)) {\n return Reflect.get(container, methodName);\n }\n }\n\n return undefined;\n}\n\nfunction getExpoPermissionErrorMessage(error: unknown): string {\n if (error instanceof Error && error.message.length > 0) {\n return error.message;\n }\n\n if (typeof error === 'string' && error.length > 0) {\n return error;\n }\n\n return 'Expo permission operation failed.';\n}\n\nfunction createNormalizedExpoPermissionState(\n permission: Permission,\n response: ExpoPermissionResponse,\n status: PermissionStatus,\n reason?: string,\n): PermissionState {\n const normalizedStatus =\n status === 'denied' && response.canAskAgain === false ? 'blocked' : status;\n\n return createPermissionState({\n permission,\n status: normalizedStatus,\n canAskAgain: response.canAskAgain,\n reason:\n normalizedStatus === 'blocked'\n ? 'Permission is blocked. Open system settings to change it.'\n : reason,\n });\n}\n\nfunction hasExpoPermissionMethod(\n value: unknown,\n methodName: string,\n): value is Record<string, ExpoPermissionMethod> {\n return isRecord(value) && typeof Reflect.get(value, methodName) === 'function';\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n"]}
|