@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.
Files changed (56) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +22 -79
  3. package/dist/ankh.provider.d.ts +46 -6
  4. package/dist/ankh.provider.d.ts.map +1 -1
  5. package/dist/ankh.provider.js +4 -9
  6. package/dist/ankh.provider.js.map +1 -1
  7. package/dist/capabilities/index.d.ts +43 -0
  8. package/dist/capabilities/index.d.ts.map +1 -0
  9. package/dist/capabilities/index.js +36 -0
  10. package/dist/capabilities/index.js.map +1 -0
  11. package/dist/expo/adapters/camera.d.ts +1 -1
  12. package/dist/expo/adapters/camera.d.ts.map +1 -1
  13. package/dist/expo/adapters/camera.js +1 -1
  14. package/dist/expo/adapters/camera.js.map +1 -1
  15. package/dist/expo/adapters/location.d.ts +1 -1
  16. package/dist/expo/adapters/location.d.ts.map +1 -1
  17. package/dist/expo/adapters/location.js +1 -1
  18. package/dist/expo/adapters/location.js.map +1 -1
  19. package/dist/expo/adapters/mediaLibrary.d.ts +1 -1
  20. package/dist/expo/adapters/mediaLibrary.d.ts.map +1 -1
  21. package/dist/expo/adapters/mediaLibrary.js +1 -1
  22. package/dist/expo/adapters/mediaLibrary.js.map +1 -1
  23. package/dist/expo/adapters/microphone.d.ts +1 -1
  24. package/dist/expo/adapters/microphone.d.ts.map +1 -1
  25. package/dist/expo/adapters/microphone.js +1 -1
  26. package/dist/expo/adapters/microphone.js.map +1 -1
  27. package/dist/expo/adapters/notifications.d.ts +1 -1
  28. package/dist/expo/adapters/notifications.d.ts.map +1 -1
  29. package/dist/expo/adapters/notifications.js +1 -1
  30. package/dist/expo/adapters/notifications.js.map +1 -1
  31. package/dist/expo/{permissionResponse.d.ts → adapters/permissionResponse.d.ts} +2 -2
  32. package/dist/expo/adapters/permissionResponse.d.ts.map +1 -0
  33. package/dist/expo/{permissionResponse.js → adapters/permissionResponse.js} +1 -1
  34. package/dist/expo/adapters/permissionResponse.js.map +1 -0
  35. package/dist/expo/client.d.ts +0 -6
  36. package/dist/expo/client.d.ts.map +1 -1
  37. package/dist/expo/client.js.map +1 -1
  38. package/dist/types/expo.d.ts +7 -0
  39. package/dist/types/expo.d.ts.map +1 -0
  40. package/dist/types/expo.js +2 -0
  41. package/dist/types/expo.js.map +1 -0
  42. package/package.json +72 -8
  43. package/src/ankh.provider.ts +16 -16
  44. package/src/capabilities/index.test.ts +15 -0
  45. package/src/capabilities/index.ts +37 -0
  46. package/src/expo/adapters/camera.ts +2 -2
  47. package/src/expo/adapters/location.ts +2 -2
  48. package/src/expo/adapters/mediaLibrary.ts +2 -2
  49. package/src/expo/adapters/microphone.ts +2 -2
  50. package/src/expo/adapters/notifications.ts +2 -2
  51. package/src/expo/{permissionResponse.ts → adapters/permissionResponse.ts} +2 -2
  52. package/src/expo/client.ts +1 -5
  53. package/src/provider.test.ts +30 -0
  54. package/src/types/expo.ts +7 -0
  55. package/dist/expo/permissionResponse.d.ts.map +0 -1
  56. 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
- ![license: MIT](././paradox/badges/license.svg) ![npm: v0.2.3](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v0.3.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![paradox: canonical](././paradox/badges/docs.svg)
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
- ### Basic permissions runtime example.
12
+ ### CLI
13
13
 
14
- Create a permission client, provide it at the app root, and use
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
- function CameraPermissionExample() {
41
- const camera = usePermission(Permission.Camera, { refreshOnMount: true });
16
+ ```zsh
17
+ # Install the Ankhorage CLI
18
+ bun add --global @ankhorage/ankh
42
19
 
43
- return (
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
- ### Expo permissions runtime example.
24
+ ### Basic permissions
61
25
 
62
- Create the Expo permission client from the optional Expo entrypoint, provide
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
- const permissionClient = createPermissionClient();
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
- export default function ExpoPermissionsExample() {
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:42:1`
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 | Type | Required | Default | Description |
236
- | -------- | -------------------------------- | -------- | ------- | ----------- |
237
- | children | `ReactNode \| undefined` | no | — | |
238
- | client | `PermissionClient \| undefined` | no | — | |
239
- | manager | `PermissionManager \| undefined` | no | — | |
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
 
@@ -1,9 +1,49 @@
1
1
  declare const provider: {
2
- id: string;
3
- category: string;
4
- version: string;
5
- capabilities: readonly ["permissions.inspect", "permissions.check", "permissions.request", "permissions.manifest"];
6
- commands: readonly [{
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAbK;YACf,QAAQ,CAAC,OAAO,EAAE;gBAChB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;aACjC,CAAC;SACH;;;;CAgBF,CAAC;AAEF,eAAe,QAAQ,CAAC"}
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"}
@@ -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: PERMISSIONS_PACKAGE_VERSION,
50
- capabilities: PERMISSIONS_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":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AAC1D,MAAM,2BAA2B,GAAG,OAAO,CAAC;AAC5C,MAAM,4BAA4B,GAAG,aAAa,CAAC;AAEnD,MAAM,wBAAwB,GAAG;IAC/B,qBAAqB;IACrB,mBAAmB;IACnB,qBAAqB;IACrB,sBAAsB;CACd,CAAC;AAEX,MAAM,QAAQ,GAAG;IACf;QACE,IAAI,EAAE,CAAC,MAAM,CAAC;QACd,OAAO,EAAE,0DAA0D;QACnE,UAAU,EAAE,qBAAqB;QACjC,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,mBAAmB;QAC/B,QAAQ,EAAE,CAAC,+BAA+B,CAAC;KAC5C;IACD;QACE,IAAI,EAAE,CAAC,SAAS,CAAC;QACjB,OAAO,EAAE,iEAAiE;QAC1E,UAAU,EAAE,qBAAqB;QACjC,QAAQ,EAAE,CAAC,iCAAiC,CAAC;KAC9C;IACD;QACE,IAAI,EAAE,CAAC,UAAU,CAAC;QAClB,OAAO,EAAE,uEAAuE;QAChF,UAAU,EAAE,sBAAsB;QAClC,QAAQ,EAAE,CAAC,kCAAkC,CAAC;KAC/C;CACO,CAAC;AAEX,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,2BAA2B;IACpC,YAAY,EAAE,wBAAwB;IACtC,QAAQ;IACR,QAAQ;CACT,CAAC;AAEF,eAAe,QAAQ,CAAC","sourcesContent":["import { PERMISSIONS } from './registry/permissions';\n\nconst PERMISSIONS_PACKAGE_NAME = '@ankhorage/permissions';\nconst PERMISSIONS_PACKAGE_VERSION = '0.2.0';\nconst PERMISSIONS_COMMAND_CATEGORY = 'permissions';\n\nconst PERMISSIONS_CAPABILITIES = [\n 'permissions.inspect',\n 'permissions.check',\n 'permissions.request',\n 'permissions.manifest',\n] as const;\n\nconst commands = [\n {\n path: ['list'],\n summary: 'List known permission identifiers and registry metadata.',\n capability: 'permissions.inspect',\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',\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',\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',\n examples: ['ankh permissions manifest camera'],\n },\n] as const;\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: PERMISSIONS_PACKAGE_VERSION,\n capabilities: PERMISSIONS_CAPABILITIES,\n commands,\n handlers,\n};\n\nexport default provider;\n"]}
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,3 +1,3 @@
1
- import type { ExpoPermissionAdapter } from '../client';
1
+ import type { ExpoPermissionAdapter } from '../../types/expo';
2
2
  export declare const cameraAdapter: ExpoPermissionAdapter;
3
3
  //# sourceMappingURL=camera.d.ts.map
@@ -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,WAAW,CAAC;AAUvD,eAAO,MAAM,aAAa,EAAE,qBA0B3B,CAAC"}
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 '../permissionResponse';
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,uBAAuB,CAAC;AAE/B,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 '../client';\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
+ {"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,3 +1,3 @@
1
- import type { ExpoPermissionAdapter } from '../client';
1
+ import type { ExpoPermissionAdapter } from '../../types/expo';
2
2
  export declare const locationAdapter: ExpoPermissionAdapter;
3
3
  //# sourceMappingURL=location.d.ts.map
@@ -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,WAAW,CAAC;AAGvD,eAAO,MAAM,eAAe,EAAE,qBA4B7B,CAAC"}
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 '../permissionResponse';
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,uBAAuB,CAAC;AAE9F,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 '../client';\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
+ {"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,3 +1,3 @@
1
- import type { ExpoPermissionAdapter } from '../client';
1
+ import type { ExpoPermissionAdapter } from '../../types/expo';
2
2
  export declare const mediaLibraryAdapter: ExpoPermissionAdapter;
3
3
  //# sourceMappingURL=mediaLibrary.d.ts.map
@@ -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,WAAW,CAAC;AAWvD,eAAO,MAAM,mBAAmB,EAAE,qBAsBjC,CAAC"}
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 '../permissionResponse';
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,uBAAuB,CAAC;AAM/B,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 '../client';\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
+ {"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,3 +1,3 @@
1
- import type { ExpoPermissionAdapter } from '../client';
1
+ import type { ExpoPermissionAdapter } from '../../types/expo';
2
2
  export declare const microphoneAdapter: ExpoPermissionAdapter;
3
3
  //# sourceMappingURL=microphone.d.ts.map
@@ -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,WAAW,CAAC;AAUvD,eAAO,MAAM,iBAAiB,EAAE,qBA0B/B,CAAC"}
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 '../permissionResponse';
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,uBAAuB,CAAC;AAE/B,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 '../client';\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
+ {"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,3 +1,3 @@
1
- import type { ExpoPermissionAdapter } from '../client';
1
+ import type { ExpoPermissionAdapter } from '../../types/expo';
2
2
  export declare const notificationsAdapter: ExpoPermissionAdapter;
3
3
  //# sourceMappingURL=notifications.d.ts.map
@@ -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,WAAW,CAAC;AAavD,eAAO,MAAM,oBAAoB,EAAE,qBAsBlC,CAAC"}
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 '../permissionResponse';
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,uBAAuB,CAAC;AAQ/B,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 '../client';\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
+ {"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 '../registry/permissions';
2
- import { type PermissionState } from '../state/permissionState';
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 '../state/permissionState';
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"]}
@@ -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;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAUvF,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;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAkDzD"}
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"}
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/expo/client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PermissionClient } from '../client/types';\nimport { Permission } from '../registry/permissions';\nimport { createPermissionState, type PermissionState } from '../state/permissionState';\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\nexport interface ExpoPermissionAdapter {\n getStatus(permission: Permission): Promise<PermissionState>;\n request(permission: Permission): Promise<PermissionState>;\n}\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"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/expo/client.ts"],"names":[],"mappings":"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","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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=expo.js.map
@@ -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.2.63",
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
- "permissions.inspect",
46
- "permissions.check",
47
- "permissions.request",
48
- "permissions.manifest"
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.11.11",
140
- "@ankhorage/paradox": "^0.2.25",
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",
@@ -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: PERMISSIONS_PACKAGE_VERSION,
61
- capabilities: PERMISSIONS_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 '../client';
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 '../permissionResponse';
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 '../client';
4
- import { createExpoPermissionState, createExpoUnavailableState } from '../permissionResponse';
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 '../client';
4
+ import type { ExpoPermissionAdapter } from '../../types/expo';
5
5
  import {
6
6
  createExpoPermissionState,
7
7
  createExpoUnavailableState,
8
8
  type ExpoPermissionResponse,
9
- } from '../permissionResponse';
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 '../client';
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 '../permissionResponse';
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 '../client';
3
+ import type { ExpoPermissionAdapter } from '../../types/expo';
4
4
  import {
5
5
  createExpoPermissionState,
6
6
  createExpoUnavailableState,
7
7
  type ExpoPermissionResponse,
8
- } from '../permissionResponse';
8
+ } from './permissionResponse';
9
9
 
10
10
  interface ExpoNotificationPermissionResponse extends ExpoPermissionResponse {
11
11
  readonly ios?: {
@@ -1,10 +1,10 @@
1
- import type { Permission } from '../registry/permissions';
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 '../state/permissionState';
7
+ } from '../../state/permissionState';
8
8
 
9
9
  export interface ExpoPermissionResponse {
10
10
  readonly status: string;
@@ -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],
@@ -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"]}