appduct 0.10.0 → 0.11.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 (230) hide show
  1. package/README.md +121 -51
  2. package/dist/artifact-inspect.d.ts +0 -1
  3. package/dist/bin.d.ts +0 -1
  4. package/dist/bin.js +1250 -2
  5. package/dist/cli/command-options.d.ts +8 -1
  6. package/dist/cli/create-cli.d.ts +0 -1
  7. package/dist/cli/dispatch.d.ts +10 -1
  8. package/dist/cli/envelope.d.ts +19 -0
  9. package/dist/cli/global-flags.d.ts +30 -0
  10. package/dist/cli/open-target.d.ts +25 -8
  11. package/dist/cli/result-types.d.ts +30 -5
  12. package/dist/cli/router.d.ts +78 -0
  13. package/dist/cli/routes/daemon/index.d.ts +9 -0
  14. package/dist/cli/routes/daemon/index.js +848 -0
  15. package/dist/cli/routes/daemon/run.d.ts +3 -0
  16. package/dist/cli/routes/daemon/run.js +3246 -0
  17. package/dist/cli/routes/daemon/start.d.ts +3 -0
  18. package/dist/cli/routes/daemon/start.js +1668 -0
  19. package/dist/cli/routes/daemon/status.d.ts +4 -0
  20. package/dist/cli/routes/daemon/status.js +1676 -0
  21. package/dist/cli/routes/daemon/stop.d.ts +4 -0
  22. package/dist/cli/routes/daemon/stop.js +1646 -0
  23. package/dist/cli/routes/doctor.d.ts +3 -0
  24. package/dist/cli/routes/doctor.js +1075 -0
  25. package/dist/cli/routes/events.d.ts +3 -0
  26. package/dist/cli/routes/events.js +1906 -0
  27. package/dist/cli/routes/init.d.ts +3 -0
  28. package/dist/cli/routes/init.js +1486 -0
  29. package/dist/cli/routes/invoke.d.ts +3 -0
  30. package/dist/cli/routes/invoke.js +1884 -0
  31. package/dist/cli/routes/keygen.d.ts +3 -0
  32. package/dist/cli/routes/keygen.js +928 -0
  33. package/dist/cli/routes/link.d.ts +3 -0
  34. package/dist/cli/routes/link.js +2705 -0
  35. package/dist/cli/routes/ls.d.ts +3 -0
  36. package/dist/cli/routes/ls.js +1659 -0
  37. package/dist/cli/routes/mcp.d.ts +5 -0
  38. package/dist/cli/routes/mcp.js +3917 -0
  39. package/dist/cli/routes/revoke.d.ts +3 -0
  40. package/dist/cli/routes/revoke.js +1675 -0
  41. package/dist/cli/routes/tools.d.ts +3 -0
  42. package/dist/cli/routes/tools.js +1851 -0
  43. package/dist/cli/runner.d.ts +3 -11
  44. package/dist/cli/types.d.ts +9 -6
  45. package/dist/cli/version-guard.d.ts +20 -0
  46. package/dist/cli.d.ts +0 -1
  47. package/dist/client/app-client.d.ts +0 -1
  48. package/dist/client/bootstrap.d.ts +4 -4
  49. package/dist/client/connect.d.ts +0 -1
  50. package/dist/client/errors.d.ts +0 -1
  51. package/dist/client/index.d.ts +0 -1
  52. package/dist/client/index.js +2379 -16
  53. package/dist/commands/daemon/context.d.ts +14 -0
  54. package/dist/commands/daemon/run.d.ts +11 -0
  55. package/dist/commands/daemon/start.d.ts +5 -0
  56. package/dist/commands/daemon/status.d.ts +5 -0
  57. package/dist/commands/daemon/stop.d.ts +5 -0
  58. package/dist/commands/doctor.d.ts +0 -1
  59. package/dist/commands/events.d.ts +0 -1
  60. package/dist/commands/init.d.ts +17 -4
  61. package/dist/commands/invoke.d.ts +0 -1
  62. package/dist/commands/keygen.d.ts +0 -1
  63. package/dist/commands/link.d.ts +1 -2
  64. package/dist/commands/ls.d.ts +0 -1
  65. package/dist/commands/mcp.d.ts +2 -4
  66. package/dist/commands/revoke.d.ts +0 -1
  67. package/dist/commands/tools.d.ts +19 -3
  68. package/dist/daemon/address.d.ts +0 -1
  69. package/dist/daemon/audit.d.ts +6 -11
  70. package/dist/daemon/calls.d.ts +0 -1
  71. package/dist/daemon/config.d.ts +13 -16
  72. package/dist/daemon/daemon.d.ts +0 -1
  73. package/dist/daemon/event-bus.d.ts +0 -1
  74. package/dist/daemon/links.d.ts +0 -1
  75. package/dist/daemon/listener.d.ts +0 -1
  76. package/dist/daemon/log-rotation.d.ts +0 -1
  77. package/dist/daemon/pidfile.d.ts +14 -8
  78. package/dist/daemon/policy.d.ts +0 -1
  79. package/dist/daemon/registry.d.ts +0 -1
  80. package/dist/daemon/rpc-errors.d.ts +16 -0
  81. package/dist/daemon/rpc-server.d.ts +0 -11
  82. package/dist/daemon/sessions.d.ts +0 -1
  83. package/dist/daemon/socket-probe.d.ts +0 -1
  84. package/dist/daemon/state-dir.d.ts +0 -1
  85. package/dist/daemon/timers.d.ts +0 -1
  86. package/dist/daemon/tls.d.ts +0 -1
  87. package/dist/errors.d.ts +0 -1
  88. package/dist/host-certificate.d.ts +0 -1
  89. package/dist/index.d.ts +0 -1
  90. package/dist/index.js +1307 -3
  91. package/dist/key-material.d.ts +0 -1
  92. package/dist/link.d.ts +8 -7
  93. package/dist/mcp/app-tools.d.ts +153 -0
  94. package/dist/mcp/connect-tool.d.ts +14 -8
  95. package/dist/mcp/daemon-tools.d.ts +2 -11
  96. package/dist/mcp/events-tool.d.ts +0 -1
  97. package/dist/mcp/server.d.ts +33 -14
  98. package/dist/native-scheme.d.ts +0 -1
  99. package/dist/output.d.ts +8 -11
  100. package/dist/package-root.d.ts +11 -0
  101. package/dist/package-version.d.ts +0 -1
  102. package/dist/qr-terminal.d.ts +0 -1
  103. package/dist/rpc/client.d.ts +0 -1
  104. package/dist/scheme.d.ts +60 -2
  105. package/dist/spki-pin.d.ts +0 -1
  106. package/package.json +4 -3
  107. package/dist/artifact-inspect.d.ts.map +0 -1
  108. package/dist/artifact-inspect.js +0 -334
  109. package/dist/bin.d.ts.map +0 -1
  110. package/dist/cli/command-options.d.ts.map +0 -1
  111. package/dist/cli/command-options.js +0 -95
  112. package/dist/cli/create-cli.d.ts.map +0 -1
  113. package/dist/cli/create-cli.js +0 -56
  114. package/dist/cli/dispatch.d.ts.map +0 -1
  115. package/dist/cli/dispatch.js +0 -275
  116. package/dist/cli/open-target.d.ts.map +0 -1
  117. package/dist/cli/open-target.js +0 -438
  118. package/dist/cli/result-types.d.ts.map +0 -1
  119. package/dist/cli/result-types.js +0 -6
  120. package/dist/cli/runner.d.ts.map +0 -1
  121. package/dist/cli/runner.js +0 -111
  122. package/dist/cli/types.d.ts.map +0 -1
  123. package/dist/cli/types.js +0 -10
  124. package/dist/cli.d.ts.map +0 -1
  125. package/dist/cli.js +0 -2
  126. package/dist/client/app-client.d.ts.map +0 -1
  127. package/dist/client/app-client.js +0 -223
  128. package/dist/client/bootstrap.d.ts.map +0 -1
  129. package/dist/client/bootstrap.js +0 -108
  130. package/dist/client/connect.d.ts.map +0 -1
  131. package/dist/client/connect.js +0 -38
  132. package/dist/client/errors.d.ts.map +0 -1
  133. package/dist/client/errors.js +0 -40
  134. package/dist/client/index.d.ts.map +0 -1
  135. package/dist/commands/daemon.d.ts +0 -22
  136. package/dist/commands/daemon.d.ts.map +0 -1
  137. package/dist/commands/daemon.js +0 -128
  138. package/dist/commands/doctor.d.ts.map +0 -1
  139. package/dist/commands/doctor.js +0 -42
  140. package/dist/commands/events.d.ts.map +0 -1
  141. package/dist/commands/events.js +0 -76
  142. package/dist/commands/init.d.ts.map +0 -1
  143. package/dist/commands/init.js +0 -231
  144. package/dist/commands/invoke.d.ts.map +0 -1
  145. package/dist/commands/invoke.js +0 -54
  146. package/dist/commands/keygen.d.ts.map +0 -1
  147. package/dist/commands/keygen.js +0 -46
  148. package/dist/commands/link.d.ts.map +0 -1
  149. package/dist/commands/link.js +0 -43
  150. package/dist/commands/ls.d.ts.map +0 -1
  151. package/dist/commands/ls.js +0 -7
  152. package/dist/commands/mcp.d.ts.map +0 -1
  153. package/dist/commands/mcp.js +0 -98
  154. package/dist/commands/revoke.d.ts.map +0 -1
  155. package/dist/commands/revoke.js +0 -7
  156. package/dist/commands/tools.d.ts.map +0 -1
  157. package/dist/commands/tools.js +0 -52
  158. package/dist/daemon/address.d.ts.map +0 -1
  159. package/dist/daemon/address.js +0 -71
  160. package/dist/daemon/audit.d.ts.map +0 -1
  161. package/dist/daemon/audit.js +0 -237
  162. package/dist/daemon/calls.d.ts.map +0 -1
  163. package/dist/daemon/calls.js +0 -158
  164. package/dist/daemon/config.d.ts.map +0 -1
  165. package/dist/daemon/config.js +0 -170
  166. package/dist/daemon/daemon.d.ts.map +0 -1
  167. package/dist/daemon/daemon.js +0 -560
  168. package/dist/daemon/event-bus.d.ts.map +0 -1
  169. package/dist/daemon/event-bus.js +0 -111
  170. package/dist/daemon/links.d.ts.map +0 -1
  171. package/dist/daemon/links.js +0 -118
  172. package/dist/daemon/listener.d.ts.map +0 -1
  173. package/dist/daemon/listener.js +0 -132
  174. package/dist/daemon/log-rotation.d.ts.map +0 -1
  175. package/dist/daemon/log-rotation.js +0 -136
  176. package/dist/daemon/pidfile.d.ts.map +0 -1
  177. package/dist/daemon/pidfile.js +0 -90
  178. package/dist/daemon/policy.d.ts.map +0 -1
  179. package/dist/daemon/policy.js +0 -24
  180. package/dist/daemon/registry.d.ts.map +0 -1
  181. package/dist/daemon/registry.js +0 -31
  182. package/dist/daemon/rpc-server.d.ts.map +0 -1
  183. package/dist/daemon/rpc-server.js +0 -203
  184. package/dist/daemon/sessions.d.ts.map +0 -1
  185. package/dist/daemon/sessions.js +0 -429
  186. package/dist/daemon/socket-probe.d.ts.map +0 -1
  187. package/dist/daemon/socket-probe.js +0 -28
  188. package/dist/daemon/state-dir.d.ts.map +0 -1
  189. package/dist/daemon/state-dir.js +0 -43
  190. package/dist/daemon/timers.d.ts.map +0 -1
  191. package/dist/daemon/timers.js +0 -12
  192. package/dist/daemon/tls.d.ts.map +0 -1
  193. package/dist/daemon/tls.js +0 -79
  194. package/dist/errors.d.ts.map +0 -1
  195. package/dist/errors.js +0 -162
  196. package/dist/host-certificate.d.ts.map +0 -1
  197. package/dist/host-certificate.js +0 -111
  198. package/dist/index.d.ts.map +0 -1
  199. package/dist/key-material.d.ts.map +0 -1
  200. package/dist/key-material.js +0 -42
  201. package/dist/link.d.ts.map +0 -1
  202. package/dist/link.js +0 -117
  203. package/dist/mcp/connect-tool.d.ts.map +0 -1
  204. package/dist/mcp/connect-tool.js +0 -396
  205. package/dist/mcp/daemon-tools.d.ts.map +0 -1
  206. package/dist/mcp/daemon-tools.js +0 -29
  207. package/dist/mcp/events-tool.d.ts.map +0 -1
  208. package/dist/mcp/events-tool.js +0 -322
  209. package/dist/mcp/server.d.ts.map +0 -1
  210. package/dist/mcp/server.js +0 -538
  211. package/dist/mcp/tool-mapping.d.ts +0 -58
  212. package/dist/mcp/tool-mapping.d.ts.map +0 -1
  213. package/dist/mcp/tool-mapping.js +0 -143
  214. package/dist/mcp/tool-namespace.d.ts +0 -40
  215. package/dist/mcp/tool-namespace.d.ts.map +0 -1
  216. package/dist/mcp/tool-namespace.js +0 -65
  217. package/dist/native-scheme.d.ts.map +0 -1
  218. package/dist/native-scheme.js +0 -465
  219. package/dist/output.d.ts.map +0 -1
  220. package/dist/output.js +0 -342
  221. package/dist/package-version.d.ts.map +0 -1
  222. package/dist/package-version.js +0 -47
  223. package/dist/qr-terminal.d.ts.map +0 -1
  224. package/dist/qr-terminal.js +0 -45
  225. package/dist/rpc/client.d.ts.map +0 -1
  226. package/dist/rpc/client.js +0 -819
  227. package/dist/scheme.d.ts.map +0 -1
  228. package/dist/scheme.js +0 -321
  229. package/dist/spki-pin.d.ts.map +0 -1
  230. package/dist/spki-pin.js +0 -14
@@ -1 +0,0 @@
1
- {"version":3,"file":"scheme.d.ts","sourceRoot":"","sources":["../src/scheme.ts"],"names":[],"mappings":"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"}
package/dist/scheme.js DELETED
@@ -1,321 +0,0 @@
1
- /**
2
- * Deep-link scheme resolution (ARCHITECTURE.md §10, issue #29).
3
- *
4
- * A scheme is needed to compose `<scheme>:///?appduct=<payload>` in `appduct link`,
5
- * `appduct/client`'s `link()` and the MCP `appduct_connect` tool. Before this module the only
6
- * source was `<state-dir>/config.json` — a single global file, which meant two apps with different
7
- * schemes on one machine required hand-editing it on every switch.
8
- *
9
- * The resolution order below is shared by every one of those callers so it cannot drift, first
10
- * match wins:
11
- *
12
- * 1. an explicit flag/option (`--scheme`)
13
- * 2. the `APPDUCT_SCHEME` environment variable
14
- * 3. the nearest `.appduct/config.json` that declares a `scheme`, walking up from the working
15
- * directory (never `~/.appduct` or the state dir in use — see {@link findProjectConfigs};
16
- * a project config without a `scheme` key does not stop the walk)
17
- * 4. `scheme` in the state directory's `config.json` (the pre-#29 behaviour)
18
- * 5. a static-file project probe, tried in this order (no walk-up — an app root is where you
19
- * run these commands), with {@link discoverStaticProjectScheme} owning the whole step:
20
- * a. `<cwd>/app.json`'s `expo.scheme` (the pre-#48 behaviour, unchanged)
21
- * b. Android: `app/build.gradle(.kts)`'s `appductScheme` manifest placeholder, then
22
- * `app/src/main/AndroidManifest.xml`'s first `<data android:scheme>` in a `VIEW`
23
- * intent filter
24
- * c. iOS: any `Info.plist` up to two levels deep (excluding `Pods`/`build`/`node_modules`/
25
- * `DerivedData`) for the first `CFBundleURLSchemes` entry, then xcodegen's `project.yml`
26
- * for the same key — see `native-scheme.ts`, which owns 5b/5c and never guesses when two
27
- * of them disagree (throws instead, naming both)
28
- *
29
- * Nothing here executes project code: `app.config.js`/`app.config.ts` are deliberately *not*
30
- * evaluated (running arbitrary project JS to read one string is a much larger blast radius than
31
- * this feature warrants), and neither is `xcodebuild`/`plutil`/a Gradle evaluation for the native
32
- * probes added in issue #48 — every one of them is a plain, defensively-parsed read of a static
33
- * project file (`native-scheme.ts`'s doc comment has the detail). Dynamic-config projects use
34
- * `--scheme`, `APPDUCT_SCHEME`, or a project `.appduct/config.json` instead.
35
- *
36
- * A project `.appduct/config.json` carries client-side keys only (`scheme` today). It never
37
- * redirects the state directory — `--state-dir` / `APPDUCT_STATE_DIR` remain the only way to do
38
- * that — so a project file can never move the daemon's key, socket or audit log.
39
- */
40
- import { existsSync } from "node:fs";
41
- import { readFile } from "node:fs/promises";
42
- import { homedir } from "node:os";
43
- import { dirname, join, resolve } from "node:path";
44
- import { usageError } from "./errors.js";
45
- import { discoverNativeScheme } from "./native-scheme.js";
46
- /** The directory a project-level config lives in, relative to an app root. */
47
- export const PROJECT_CONFIG_DIR = ".appduct";
48
- /** The project-level config filename, inside {@link PROJECT_CONFIG_DIR}. */
49
- export const PROJECT_CONFIG_FILENAME = "config.json";
50
- /** Relative path used in messages/docs: `.appduct/config.json`. */
51
- export const PROJECT_CONFIG_RELATIVE_PATH = join(PROJECT_CONFIG_DIR, PROJECT_CONFIG_FILENAME);
52
- /** The Expo app manifest discovery reads. Only static JSON — see this module's doc comment. */
53
- export const APP_JSON_FILENAME = "app.json";
54
- export const SCHEME_ENV_VAR = "APPDUCT_SCHEME";
55
- /**
56
- * RFC 3986 §3.1 scheme grammar: `ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )`.
57
- *
58
- * Enforced so a value like `"myapp://"` (a very natural thing to paste into `--scheme`) fails with
59
- * a message naming the offending source instead of silently composing the unopenable
60
- * `myapp://:///?appduct=…`.
61
- */
62
- const SCHEME_PATTERN = /^[a-zA-Z][a-zA-Z0-9+.-]*$/u;
63
- export const isValidScheme = (value) => SCHEME_PATTERN.test(value);
64
- const requireValidScheme = (value, origin) => {
65
- if (!isValidScheme(value)) {
66
- throw usageError(`Invalid deep-link scheme ${JSON.stringify(value)} from ${origin}: a scheme must start with ` +
67
- 'a letter and contain only letters, digits, "+", "-" or "." (for example "myapp") — do not ' +
68
- 'include "://".');
69
- }
70
- return value;
71
- };
72
- const isPlainObject = (value) => {
73
- return typeof value === "object" && value !== null && !Array.isArray(value);
74
- };
75
- /** Reads and JSON-parses a file; `undefined` when it does not exist. Other I/O errors propagate. */
76
- const readJsonFile = async (path) => {
77
- let text;
78
- try {
79
- text = await readFile(path, "utf8");
80
- }
81
- catch (error) {
82
- const code = error.code;
83
- // A `.appduct` that is a file, or an `app.json` that is a directory, is "nothing usable
84
- // here" rather than a hard failure — the caller falls through to the next source.
85
- if (code === "ENOENT" || code === "ENOTDIR" || code === "EISDIR") {
86
- return undefined;
87
- }
88
- throw error;
89
- }
90
- try {
91
- return { raw: JSON.parse(text) };
92
- }
93
- catch (error) {
94
- throw usageError(`Could not parse ${path}: ${error.message}`);
95
- }
96
- };
97
- /**
98
- * Normalizes Expo's `scheme` field, which is either a single string or an array of them. Mirrors
99
- * `packages/react-native/app.plugin.js`'s `configuredSchemes` so the CLI and the config plugin
100
- * agree on what "the app's scheme" means; the first entry wins for an array.
101
- *
102
- * Exported so {@link ../native-scheme.js} can apply the same "string, or first non-empty entry of
103
- * an array" rule to `CFBundleURLSchemes` (`Info.plist`/`project.yml`) — the shape is identical.
104
- */
105
- export const firstConfiguredScheme = (value) => {
106
- if (Array.isArray(value)) {
107
- return value.find((entry) => typeof entry === "string" && entry.length > 0);
108
- }
109
- return typeof value === "string" && value.length > 0 ? value : undefined;
110
- };
111
- /**
112
- * Reads `<dir>/app.json`'s `expo.scheme`. Returns `undefined` when the file is missing, is not a
113
- * JSON object, has no `expo` object, or declares no usable scheme — every one of which just means
114
- * "discovery found nothing here". A *malformed* `app.json` throws, because silently ignoring a
115
- * syntax error in the file the user is pointing us at reads as "Appduct ignored my config".
116
- */
117
- export const discoverExpoScheme = async (dir) => {
118
- const path = join(resolve(dir), APP_JSON_FILENAME);
119
- const file = await readJsonFile(path);
120
- if (!file || !isPlainObject(file.raw)) {
121
- return undefined;
122
- }
123
- const expo = file.raw.expo;
124
- if (!isPlainObject(expo)) {
125
- return undefined;
126
- }
127
- const scheme = firstConfiguredScheme(expo.scheme);
128
- return scheme === undefined ? undefined : requireValidScheme(scheme, `"expo.scheme" in ${path}`);
129
- };
130
- /**
131
- * Step 5 of {@link resolveScheme} in full: `<cwd>/app.json` first (unchanged), then the native
132
- * Android/iOS project probes from `native-scheme.ts`. Exported as its own step — not inlined into
133
- * `resolveScheme` — because `appduct init` (`commands/init.ts`) runs exactly this same
134
- * discovery on its own, deliberately skipping steps 1-4 (see that file's doc comment for why): the
135
- * two must never disagree about what "discovery" means for the tail of the precedence order, or
136
- * `init` could write a scheme `resolveScheme` would never have found on its own.
137
- */
138
- export const discoverStaticProjectScheme = async (cwd) => {
139
- const appJsonPath = join(resolve(cwd), APP_JSON_FILENAME);
140
- const tried = [`${appJsonPath} ("expo.scheme")`];
141
- const appJsonScheme = await discoverExpoScheme(cwd);
142
- if (appJsonScheme !== undefined) {
143
- return { scheme: appJsonScheme, source: "app-json", origin: appJsonPath, tried };
144
- }
145
- const native = await discoverNativeScheme(resolve(cwd));
146
- tried.push(...native.tried);
147
- if (native.result !== undefined) {
148
- return {
149
- scheme: native.result.scheme,
150
- source: native.result.source,
151
- origin: native.result.origin,
152
- tried,
153
- };
154
- }
155
- return { tried };
156
- };
157
- /**
158
- * The `.appduct` directories that are *global* state, never a project's own config.
159
- *
160
- * Shared by the walk-up (which must not read them at the project tier) and `appduct init`
161
- * (which must not *write* into them: it would drop a config next to the daemon's `key.pem` and
162
- * call it safe to commit), so the two can never disagree about which directory is which.
163
- */
164
- export const globalConfigDirs = (options = {}) => {
165
- const excluded = new Set([join(resolve(options.homeDir ?? homedir()), PROJECT_CONFIG_DIR)]);
166
- if (options.stateDirRoot !== undefined) {
167
- excluded.add(resolve(options.stateDirRoot));
168
- }
169
- return excluded;
170
- };
171
- /**
172
- * Every `<dir>/.appduct/config.json` on the path from `startDir` up to the filesystem root,
173
- * nearest first.
174
- *
175
- * The walk terminates at the root (`dirname("/") === "/"`, and likewise for a Windows drive root)
176
- * — it cannot escape above it, and it never follows `..` out of a caller-supplied path because
177
- * every candidate is derived from the resolved absolute `startDir`.
178
- *
179
- * Two directories are never treated as a project root, because a hit there would silently apply a
180
- * *global* file at the project tier — one step above the state dir's own config, inverting the
181
- * documented precedence:
182
- *
183
- * - `<homeDir>/.appduct`, the default state dir. Essentially every project lives somewhere under
184
- * the home directory, so without this a plain `appduct link` in any repo would pick up the
185
- * global `config.json` as if it were the project's — and with `--state-dir` pointing elsewhere it
186
- * would shadow the state dir the operator explicitly chose.
187
- * - `stateDirRoot`, the state dir actually in use, for the same reason when it is not the default.
188
- */
189
- export const findProjectConfigs = (startDir, options = {}) => {
190
- const excluded = globalConfigDirs(options);
191
- const found = [];
192
- let dir = resolve(startDir);
193
- for (;;) {
194
- const projectDir = join(dir, PROJECT_CONFIG_DIR);
195
- if (!excluded.has(projectDir)) {
196
- const candidate = join(projectDir, PROJECT_CONFIG_FILENAME);
197
- if (existsSync(candidate)) {
198
- found.push(candidate);
199
- }
200
- }
201
- const parent = dirname(dir);
202
- if (parent === dir) {
203
- return found;
204
- }
205
- dir = parent;
206
- }
207
- };
208
- /** The nearest project config on the path from `startDir` upwards, if any. */
209
- export const findProjectConfig = (startDir, options = {}) => {
210
- return findProjectConfigs(startDir, options)[0];
211
- };
212
- /**
213
- * Reads the `scheme` key out of a project `.appduct/config.json`. Unlike `app.json` this *is*
214
- * Appduct's own file, so anything wrong with it (not an object, `scheme` not a non-empty
215
- * string) is a hard error rather than a silent fall-through — a typo here must not quietly
216
- * degrade to a different scheme from a lower-precedence source.
217
- *
218
- * Keys other than `scheme` are ignored: a project file is client-side settings only, and
219
- * accepting (say) `keyPath` here would let a checked-in file redirect the daemon's key material.
220
- */
221
- export const readProjectConfigScheme = async (path) => {
222
- const file = await readJsonFile(path);
223
- if (!file) {
224
- return undefined;
225
- }
226
- if (!isPlainObject(file.raw)) {
227
- throw usageError(`Invalid Appduct project config at ${path}: must be a JSON object.`);
228
- }
229
- const scheme = file.raw.scheme;
230
- if (scheme === undefined) {
231
- return undefined;
232
- }
233
- if (typeof scheme !== "string" || scheme.length === 0) {
234
- throw usageError(`Invalid Appduct project config at ${path}: "scheme" must be a non-empty string.`);
235
- }
236
- return requireValidScheme(scheme, `"scheme" in ${path}`);
237
- };
238
- /**
239
- * Resolves the deep-link scheme against the documented order, reporting both the winner and every
240
- * location consulted so callers can render an error that says where to put one.
241
- */
242
- export const resolveScheme = async (options = {}) => {
243
- const env = options.env ?? process.env;
244
- const cwd = resolve(options.cwd ?? process.cwd());
245
- const tried = [];
246
- tried.push("the --scheme flag");
247
- if (options.flagScheme !== undefined && options.flagScheme.length > 0) {
248
- return {
249
- scheme: requireValidScheme(options.flagScheme, "the --scheme flag"),
250
- source: "flag",
251
- tried,
252
- };
253
- }
254
- tried.push(`the ${SCHEME_ENV_VAR} environment variable`);
255
- const envScheme = env[SCHEME_ENV_VAR];
256
- if (typeof envScheme === "string" && envScheme.length > 0) {
257
- return {
258
- scheme: requireValidScheme(envScheme, `the ${SCHEME_ENV_VAR} environment variable`),
259
- source: "env",
260
- tried,
261
- };
262
- }
263
- // Every project config on the way up, not just the nearest: one that exists but declares no
264
- // `scheme` (a future version's file holding some other client-side key, say) is not an answer,
265
- // so the walk continues past it rather than treating its silence as "no project scheme".
266
- const projectConfigPaths = findProjectConfigs(cwd, {
267
- stateDirRoot: options.stateDirRoot,
268
- homeDir: options.homeDir,
269
- });
270
- tried.push(projectConfigPaths.length === 0
271
- ? `${PROJECT_CONFIG_RELATIVE_PATH} (searched upwards from ${cwd})`
272
- : projectConfigPaths.join(", "));
273
- for (const projectConfigPath of projectConfigPaths) {
274
- const projectScheme = await readProjectConfigScheme(projectConfigPath);
275
- if (projectScheme !== undefined) {
276
- return { scheme: projectScheme, source: "project-config", tried };
277
- }
278
- }
279
- tried.push(options.stateConfigPath === undefined
280
- ? 'the state directory\'s config.json ("scheme")'
281
- : `${options.stateConfigPath} ("scheme")`);
282
- if (options.configScheme !== undefined && options.configScheme.length > 0) {
283
- return {
284
- scheme: requireValidScheme(options.configScheme, options.stateConfigPath === undefined
285
- ? 'the state directory\'s config.json "scheme"'
286
- : `"scheme" in ${options.stateConfigPath}`),
287
- source: "state-config",
288
- tried,
289
- };
290
- }
291
- const discovered = await discoverStaticProjectScheme(cwd);
292
- tried.push(...discovered.tried);
293
- if (discovered.scheme !== undefined) {
294
- return { scheme: discovered.scheme, source: discovered.source, tried };
295
- }
296
- return { tried };
297
- };
298
- /**
299
- * The shared "no scheme anywhere" message. Every caller renders the same body so the locations
300
- * listed (and the fixes suggested) can't drift between `appduct link`, `appduct mcp` and
301
- * `appduct_connect`.
302
- */
303
- export const describeMissingScheme = (tried) => {
304
- const locations = tried.length === 0
305
- ? ""
306
- : `Looked in, in order:\n${tried
307
- .map((location, index) => ` ${index + 1}. ${location}`)
308
- .join("\n")}\n`;
309
- return ("A deep-link scheme is required to compose the link, and none was found. " +
310
- locations +
311
- `Set one with --scheme <scheme>, ${SCHEME_ENV_VAR}=<scheme>, "expo.scheme" in ${APP_JSON_FILENAME}, ` +
312
- `or run \`appduct init\` in your app root to write ${PROJECT_CONFIG_RELATIVE_PATH}.`);
313
- };
314
- /** {@link resolveScheme}, throwing {@link usageError} with {@link describeMissingScheme} when nothing matched. */
315
- export const resolveSchemeOrThrow = async (options = {}) => {
316
- const resolved = await resolveScheme(options);
317
- if (resolved.scheme === undefined) {
318
- throw usageError(describeMissingScheme(resolved.tried));
319
- }
320
- return resolved.scheme;
321
- };
@@ -1 +0,0 @@
1
- {"version":3,"file":"spki-pin.d.ts","sourceRoot":"","sources":["../src/spki-pin.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAI/C,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,QAAQ,MAAM,KAAG,MAW5D,CAAC"}
package/dist/spki-pin.js DELETED
@@ -1,14 +0,0 @@
1
- import { createHash, createPrivateKey, createPublicKey } from "node:crypto";
2
- export const createSpkiPin = (spkiDer) => {
3
- const digest = createHash("sha256").update(spkiDer).digest("base64");
4
- return `sha256/${digest}`;
5
- };
6
- export const getSpkiPinFromPrivateKeyPem = (keyPem) => {
7
- const privateKey = createPrivateKey(keyPem);
8
- const publicKey = createPublicKey(privateKey);
9
- const spkiDer = Buffer.from(publicKey.export({
10
- type: "spki",
11
- format: "der",
12
- }));
13
- return createSpkiPin(spkiDer);
14
- };