@ekrooh/bare 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -5
- package/dist/{index-BkwUzwVt.d.mts → index-Do-kTNXw.d.mts} +16 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{messages-BbpF3wNH.mjs → messages-CMNIFMFY.mjs} +40 -23
- package/dist/{plugins-DZu_NWVp.mjs → plugins-BnpdCi3A.mjs} +6 -3
- package/dist/plugins-discovery-events.d.mts +1 -1
- package/dist/plugins-discovery-events.mjs +1 -1
- package/dist/plugins-health-events.d.mts +1 -1
- package/dist/plugins-health-events.mjs +1 -1
- package/dist/plugins-logs-events.d.mts +1 -1
- package/dist/plugins-logs-events.mjs +1 -1
- package/dist/plugins-media-events.d.mts +1 -1
- package/dist/plugins-media-events.mjs +1 -1
- package/dist/plugins-permissions-events.d.mts +1 -1
- package/dist/plugins-permissions-events.mjs +1 -1
- package/dist/plugins.d.mts +2 -2
- package/dist/plugins.mjs +1 -1
- package/dist/runtime.d.mts +45 -34
- package/dist/runtime.mjs +891 -598
- package/dist/{static-file-server-C8pIX1JD.d.mts → static-file-server-COxd-PFR.d.mts} +41 -36
- package/dist/transports.d.mts +4 -6
- package/dist/transports.mjs +2 -3
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
**One soul, many platforms.** One codebase and identity across Android, iOS,
|
|
4
4
|
web, and desktop.
|
|
5
5
|
|
|
6
|
+
**Docs: <https://anderscan.github.io/ekrooh>**
|
|
7
|
+
|
|
6
8
|
[](https://github.com/AndersCan/ekrooh/actions/workflows/test.yml)
|
|
9
|
+
[](https://github.com/AndersCan/ekrooh/releases/latest)
|
|
7
10
|
|
|
8
11
|
The boring bootstrap for cross-platform apps on the Bare runtime (holepunch): a
|
|
9
12
|
binary wire protocol, plugin kernel, RPC messenger, transports, and native host
|
|
10
|
-
bridges, plus a reference app.
|
|
13
|
+
bridges, plus a reference app.
|
|
11
14
|
|
|
12
15
|
- [`vision.md`](vision.md): what this project is and is not.
|
|
13
16
|
- [`AGENTS.md`](AGENTS.md): how to develop it and the canonical commands.
|
|
@@ -99,16 +102,23 @@ ephemeral port. Every request is gated by a per-session token:
|
|
|
99
102
|
|
|
100
103
|
1. The shell injects `window.__ekrooh = { bootstrap }`, a single-use nonce (never the raw token).
|
|
101
104
|
2. The page calls `POST /login` with the nonce and receives a
|
|
102
|
-
`
|
|
105
|
+
`bare_session_<port>` cookie (`HttpOnly; SameSite=Strict; Path=/`). The port
|
|
106
|
+
in the name keeps two loopback servers in one cookie store apart. The raw
|
|
107
|
+
token is never a login credential.
|
|
103
108
|
3. The cookie authorizes `<img>`, `<video>`, `fetch`, and the WS upgrade.
|
|
104
109
|
Non-browser clients send `X-Bare-Token`. There is no `?token=` fallback
|
|
105
110
|
(see `docs/adr/0003-loopback-auth-surface.md`).
|
|
106
111
|
|
|
107
112
|
Only the bootstrap mount at `/` is public pre-auth. The worklet writes
|
|
108
|
-
`{ origin, port,
|
|
109
|
-
the
|
|
113
|
+
`{ origin, port, bootstrap }` to `handoff.json` in the host's sandbox dir (never
|
|
114
|
+
the session token); the host loads `http://127.0.0.1:<port>/index.html` and
|
|
115
|
+
deletes the file.
|
|
116
|
+
|
|
117
|
+
Every request must also target the bound loopback server (`Host`), and a page
|
|
118
|
+
`Origin` must be that server or an explicitly allowed one, in every mode.
|
|
110
119
|
|
|
111
|
-
The dev backend runs the same bundle with auth off on
|
|
120
|
+
The dev backend (`mode=dev`) runs the same bundle with auth off on
|
|
121
|
+
`ws://localhost:8080`, allowing the Vite dev origin (`origin=` tokens).
|
|
112
122
|
|
|
113
123
|
## Testing
|
|
114
124
|
|
|
@@ -154,6 +154,18 @@ declare function coerceErrorCode(code: string | undefined): ErrorCode;
|
|
|
154
154
|
type Ok<T> = [null, T];
|
|
155
155
|
type Err = [CoreError, null];
|
|
156
156
|
type PluginResult<T> = Either<CoreError, T>;
|
|
157
|
+
/**
|
|
158
|
+
* Environment capabilities the message layer needs but must not read from
|
|
159
|
+
* globals: Bare has no Web Crypto global, so reaching for
|
|
160
|
+
* `globalThis.crypto` broke host invokes in consumer worklets (ekrooh#268).
|
|
161
|
+
* Each entry point injects its own implementation; tests override fields.
|
|
162
|
+
*/
|
|
163
|
+
interface Platform {
|
|
164
|
+
/** Fill `bytes` with CSPRNG output and return it. Never Math.random. */
|
|
165
|
+
randomBytes(bytes: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>;
|
|
166
|
+
/** Milliseconds since the epoch. */
|
|
167
|
+
now(): number;
|
|
168
|
+
}
|
|
157
169
|
type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
|
|
158
170
|
type InternalDispatchRequest = (PluginDispatchHeader & {
|
|
159
171
|
requestId: string;
|
|
@@ -167,7 +179,9 @@ interface ProtocolMessenger {
|
|
|
167
179
|
invoke(request: InvokeRequest, payload?: Uint8Array | ArrayBuffer | string | null, timeoutMs?: number): Promise<MessageHeader>;
|
|
168
180
|
handleIncoming(header: MessageHeader): void;
|
|
169
181
|
}
|
|
170
|
-
declare function createProtocolMessenger(send: (request: InternalDispatchRequest, payload?: Uint8Array | ArrayBuffer | string | null) => void
|
|
182
|
+
declare function createProtocolMessenger(send: (request: InternalDispatchRequest, payload?: Uint8Array | ArrayBuffer | string | null) => void, options?: {
|
|
183
|
+
platform?: Partial<Platform>;
|
|
184
|
+
}): ProtocolMessenger;
|
|
171
185
|
interface PluginRegistry {
|
|
172
186
|
register(plugin: PluginManifest): void;
|
|
173
187
|
resolve(pluginId: string, runtime: RuntimeTarget): PluginManifest['runtimes'][RuntimeTarget] | undefined;
|
|
@@ -332,4 +346,4 @@ type WebConsoleCapture = {
|
|
|
332
346
|
* where there is no loopback backend to ingest into.
|
|
333
347
|
*/
|
|
334
348
|
declare function installWebConsoleCapture(options?: WebConsoleCaptureOptions): WebConsoleCapture;
|
|
335
|
-
export {
|
|
349
|
+
export { PluginManifest as $, Err as A, Either as B, createPluginRegistry as C, ProtocolMessenger as D, InvokeRequest as E, ok as F, HostInvokeResponseHeader as G, HostCapabilitiesQueryHeader as H, CapabilityDescriptor as I, PluginContext as J, InvokeEnvelope as K, CoreError as L, PluginResult as M, coerceErrorCode as N, createProtocolMessenger as O, err as P, PluginInvokeResponseHeader as Q, CoreErrorWire as R, createPluginBus as S, DispatchRequest as T, HostCapabilitiesResponseHeader as U, ErrorCodeOrString as V, HostInvokeRequestHeader as W, PluginHeader as X, PluginDispatchHeader as Y, PluginInvokeRequestHeader as Z, ProtocolOptions as _, LogStore as a, MAX_HEADER_BYTES as at, PluginRouter as b, DispatchHandler as c, VERSION as ct, definePlugin as d, PluginRuntimeAdapter as et, dispatchEvent as f, MessageProtocol as g, Encoder as h, LogSource as i, MAX_FRAME_BYTES as it, Ok as j, Platform as k, EventSpec as l, Decoder as m, LogEntry as n, WireMessage as nt, BareRuntimeContext as o, MessageType as ot, invokeEvent as p, MessageHeader as q, LogLevel as r, ErrorCode as rt, createBareRuntimeContext as s, MessageTypeValue as st, installWebConsoleCapture as t, RuntimeTarget as tt, InvokeHandler as u, PluginBus as v, createPluginRouter as w, PluginRouterOptions as x, PluginRegistry as y, DispatchEnvelope as z };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
export { BareRuntimeContext, CapabilityDescriptor, CoreError, CoreErrorWire, Decoder, DispatchEnvelope, DispatchHandler, DispatchRequest, Either, Encoder, Err, ErrorCode, ErrorCodeOrString, EventSpec, HostCapabilitiesQueryHeader, HostCapabilitiesResponseHeader, HostInvokeRequestHeader, HostInvokeResponseHeader, InvokeEnvelope, InvokeHandler, InvokeRequest, MAX_FRAME_BYTES, MAX_HEADER_BYTES, MessageHeader, MessageProtocol, MessageType, MessageTypeValue, Ok, PluginBus, PluginContext, PluginDispatchHeader, PluginHeader, PluginInvokeRequestHeader, PluginInvokeResponseHeader, PluginManifest, PluginRegistry, PluginResult, PluginRouter, PluginRouterOptions, PluginRuntimeAdapter, ProtocolMessenger, ProtocolOptions, RuntimeTarget, VERSION, WireMessage, coerceErrorCode, createBareRuntimeContext, createPluginBus, createPluginRegistry, createPluginRouter, createProtocolMessenger, definePlugin, dispatchEvent, err, installWebConsoleCapture, invokeEvent, ok };
|
|
1
|
+
import { $ as PluginManifest, A as Err, B as Either, C as createPluginRegistry, D as ProtocolMessenger, E as InvokeRequest, F as ok, G as HostInvokeResponseHeader, H as HostCapabilitiesQueryHeader, I as CapabilityDescriptor, J as PluginContext, K as InvokeEnvelope, L as CoreError, M as PluginResult, N as coerceErrorCode, O as createProtocolMessenger, P as err, Q as PluginInvokeResponseHeader, R as CoreErrorWire, S as createPluginBus, T as DispatchRequest, U as HostCapabilitiesResponseHeader, V as ErrorCodeOrString, W as HostInvokeRequestHeader, X as PluginHeader, Y as PluginDispatchHeader, Z as PluginInvokeRequestHeader, _ as ProtocolOptions, at as MAX_HEADER_BYTES, b as PluginRouter, c as DispatchHandler, ct as VERSION, d as definePlugin, et as PluginRuntimeAdapter, f as dispatchEvent, g as MessageProtocol, h as Encoder, it as MAX_FRAME_BYTES, j as Ok, k as Platform, l as EventSpec, m as Decoder, nt as WireMessage, o as BareRuntimeContext, ot as MessageType, p as invokeEvent, q as MessageHeader, rt as ErrorCode, s as createBareRuntimeContext, st as MessageTypeValue, t as installWebConsoleCapture, tt as RuntimeTarget, u as InvokeHandler, v as PluginBus, w as createPluginRouter, x as PluginRouterOptions, y as PluginRegistry, z as DispatchEnvelope } from "./index-Do-kTNXw.mjs";
|
|
2
|
+
export { BareRuntimeContext, CapabilityDescriptor, CoreError, CoreErrorWire, Decoder, DispatchEnvelope, DispatchHandler, DispatchRequest, Either, Encoder, Err, ErrorCode, ErrorCodeOrString, EventSpec, HostCapabilitiesQueryHeader, HostCapabilitiesResponseHeader, HostInvokeRequestHeader, HostInvokeResponseHeader, InvokeEnvelope, InvokeHandler, InvokeRequest, MAX_FRAME_BYTES, MAX_HEADER_BYTES, MessageHeader, MessageProtocol, MessageType, MessageTypeValue, Ok, type Platform, PluginBus, PluginContext, PluginDispatchHeader, PluginHeader, PluginInvokeRequestHeader, PluginInvokeResponseHeader, PluginManifest, PluginRegistry, PluginResult, PluginRouter, PluginRouterOptions, PluginRuntimeAdapter, ProtocolMessenger, ProtocolOptions, RuntimeTarget, VERSION, WireMessage, coerceErrorCode, createBareRuntimeContext, createPluginBus, createPluginRegistry, createPluginRouter, createProtocolMessenger, definePlugin, dispatchEvent, err, installWebConsoleCapture, invokeEvent, ok };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { h as CoreError, g as ErrorCode, _ as MAX_FRAME_BYTES, v as MAX_HEADER_BYTES, o as MessageProtocol, y as MessageType, b as VERSION, f as coerceErrorCode, n as createBareRuntimeContext, l as createPluginBus, u as createPluginRegistry, d as createPluginRouter, s as createProtocolMessenger, r as definePlugin, i as dispatchEvent, p as err, t as installWebConsoleCapture, a as invokeEvent, m as ok } from "./messages-
|
|
1
|
+
export { h as CoreError, g as ErrorCode, _ as MAX_FRAME_BYTES, v as MAX_HEADER_BYTES, o as MessageProtocol, y as MessageType, b as VERSION, f as coerceErrorCode, n as createBareRuntimeContext, l as createPluginBus, u as createPluginRegistry, d as createPluginRouter, s as createProtocolMessenger, r as definePlugin, i as dispatchEvent, p as err, t as installWebConsoleCapture, a as invokeEvent, m as ok } from "./messages-CMNIFMFY.mjs";
|
|
@@ -204,8 +204,8 @@ function createPluginRouter(registry, runtime, options) {
|
|
|
204
204
|
logger.error(`invoke ${header.pluginId}.${header.event} failed: ${error.message}`);
|
|
205
205
|
return invokeErrorResponse(header, error);
|
|
206
206
|
}
|
|
207
|
-
if (header.requestId && options?.delegateToHost) {
|
|
208
|
-
if (await hostAnnounces(header.pluginId, header.event))
|
|
207
|
+
if (header.requestId && options?.delegateToHost) try {
|
|
208
|
+
if (await hostAnnounces(header.pluginId, header.event)) {
|
|
209
209
|
const delegated = await options.delegateToHost(header, payload);
|
|
210
210
|
if (delegated) {
|
|
211
211
|
const code = delegated.error?.code;
|
|
@@ -213,10 +213,10 @@ function createPluginRouter(registry, runtime, options) {
|
|
|
213
213
|
return delegated;
|
|
214
214
|
}
|
|
215
215
|
capsCache = null;
|
|
216
|
-
} catch (e) {
|
|
217
|
-
capsCache = null;
|
|
218
|
-
return invokeErrorResponse(header, new CoreError(ErrorCode.HOST_ERROR, e instanceof Error ? e.message : String(e)));
|
|
219
216
|
}
|
|
217
|
+
} catch (e) {
|
|
218
|
+
capsCache = null;
|
|
219
|
+
return invokeErrorResponse(header, new CoreError(ErrorCode.HOST_ERROR, e instanceof Error ? e.message : String(e)));
|
|
220
220
|
}
|
|
221
221
|
return invokeErrorResponse(header, new CoreError(ErrorCode.UNSUPPORTED_CAPABILITY, `Unsupported capability ${header.pluginId}.${header.event} on ${runtime}`));
|
|
222
222
|
}
|
|
@@ -296,25 +296,46 @@ function isPluginInvokeResponseHeader(header) {
|
|
|
296
296
|
/**
|
|
297
297
|
* CSPRNG-backed correlation id for RPC requests.
|
|
298
298
|
*
|
|
299
|
-
* Shared by the
|
|
300
|
-
*
|
|
301
|
-
*
|
|
299
|
+
* Shared by the RPC messenger (`rpc-messenger.ts`) and the host IPC bridge
|
|
300
|
+
* (`host-ipc.ts`) so the unguessable, collision-resistant guarantee can never
|
|
301
|
+
* regress in a single copy. Request
|
|
302
302
|
* IDs must never be derived from `Math.random()` — a guessable id lets a peer
|
|
303
303
|
* spoof or collide with an in-flight request and corrupt correlation. See
|
|
304
|
-
* ekrooh#141.
|
|
304
|
+
* ekrooh#141. The random source is injected, never read from a global
|
|
305
|
+
* (ekrooh#268).
|
|
305
306
|
*/
|
|
306
|
-
function createRequestId() {
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
function createRequestId(platform) {
|
|
308
|
+
const rand = platform.randomBytes(/* @__PURE__ */ new Uint8Array(16)).reduce((acc, b) => acc + b.toString(36), "").slice(0, 22);
|
|
309
|
+
return `${platform.now().toString(36)}-${rand}`;
|
|
310
|
+
}
|
|
311
|
+
// core/messages/platform.ts
|
|
312
|
+
/**
|
|
313
|
+
* Fill in any field `override` leaves out from the Web platform (browser,
|
|
314
|
+
* Node). Throws when a CSPRNG is needed but the environment has none, rather
|
|
315
|
+
* than falling back to a guessable source (ekrooh#141).
|
|
316
|
+
*/
|
|
317
|
+
function resolvePlatform(override = {}) {
|
|
318
|
+
return {
|
|
319
|
+
randomBytes: override.randomBytes ?? webRandomBytes(),
|
|
320
|
+
now: override.now ?? Date.now
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function webRandomBytes() {
|
|
324
|
+
const c = globalThis.crypto;
|
|
325
|
+
if (typeof c?.getRandomValues !== "function") throw new Error("ekrooh: no CSPRNG in this environment; pass `platform.randomBytes`");
|
|
326
|
+
return (bytes) => c.getRandomValues(bytes);
|
|
311
327
|
}
|
|
312
328
|
// core/messages/rpc-messenger.ts
|
|
313
329
|
/** Hard ceiling on concurrently in-flight invokes. Above this, the oldest call
|
|
314
330
|
* is dropped (its timer cleared and promise rejected) so a flood of requests
|
|
315
331
|
* cannot grow the pending map without bound. */
|
|
316
332
|
const MAX_CONCURRENT_INVOKES = 1024;
|
|
317
|
-
function createProtocolMessenger(send) {
|
|
333
|
+
function createProtocolMessenger(send, options = {}) {
|
|
334
|
+
const platform = resolvePlatform(options.platform);
|
|
335
|
+
const withRequestId = (request) => ({
|
|
336
|
+
...request,
|
|
337
|
+
requestId: createRequestId(platform)
|
|
338
|
+
});
|
|
318
339
|
const pending = /* @__PURE__ */ new Map();
|
|
319
340
|
const sharedLogTail = createSharedLogTail();
|
|
320
341
|
return {
|
|
@@ -383,12 +404,6 @@ function createProtocolMessenger(send) {
|
|
|
383
404
|
}
|
|
384
405
|
};
|
|
385
406
|
}
|
|
386
|
-
function withRequestId(request) {
|
|
387
|
-
return {
|
|
388
|
-
...request,
|
|
389
|
-
requestId: createRequestId()
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
407
|
const INVOKE_TAIL_TIMEOUT_MS = 2e3;
|
|
393
408
|
/** A tail fetched within this window is reused for later timeouts instead of
|
|
394
409
|
* fetching again. Timeouts cluster (a stalled peer times out every pending
|
|
@@ -747,9 +762,11 @@ function dispatchEvent(spec, args, payload) {
|
|
|
747
762
|
// core/messages/create-bare-runtime-context.ts
|
|
748
763
|
function createBareRuntimeContext(plugins = [], routerOptions) {
|
|
749
764
|
const runtime = "bare";
|
|
765
|
+
const textEncoder = new TextEncoder$1();
|
|
766
|
+
const textDecoder = new TextDecoder$1();
|
|
750
767
|
const protocol = new MessageProtocol({
|
|
751
|
-
encode: (str) =>
|
|
752
|
-
decode: (bytes) =>
|
|
768
|
+
encode: (str) => textEncoder.encode(str),
|
|
769
|
+
decode: (bytes) => textDecoder.decode(bytes)
|
|
753
770
|
});
|
|
754
771
|
const pluginRegistry = createPluginRegistry();
|
|
755
772
|
for (const plugin of plugins) pluginRegistry.register(plugin);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as ErrorCode, m as ok, p as err, r as definePlugin } from "./messages-
|
|
1
|
+
import { g as ErrorCode, m as ok, p as err, r as definePlugin } from "./messages-CMNIFMFY.mjs";
|
|
2
2
|
import { discoverySpecs } from "./plugins-discovery-events.mjs";
|
|
3
3
|
import { healthSpecs } from "./plugins-health-events.mjs";
|
|
4
4
|
import { logsSpecs } from "./plugins-logs-events.mjs";
|
|
@@ -84,6 +84,7 @@ function createLogsPlugin(deps) {
|
|
|
84
84
|
* mounted at once and evict the least-recently-used so picked/captured files
|
|
85
85
|
* do not accumulate on the loopback server for the whole session. */
|
|
86
86
|
const MEDIA_MOUNT_CAP = 4;
|
|
87
|
+
const MEDIA_KINDS = ["image", "video"];
|
|
87
88
|
function newRequestId() {
|
|
88
89
|
const rand = crypto.randomBytes(16).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
89
90
|
return `${Date.now().toString(36)}-${rand}`;
|
|
@@ -108,18 +109,20 @@ function createMediaPlugin(deps) {
|
|
|
108
109
|
}
|
|
109
110
|
};
|
|
110
111
|
const serve = async (event, args) => {
|
|
112
|
+
const kind = args?.kind;
|
|
113
|
+
if (kind !== void 0 && !MEDIA_KINDS.includes(kind)) return err(ErrorCode.PLUGIN_ERROR, `Unknown media kind for ${event}`);
|
|
111
114
|
const host = await deps.invokeOnHost({
|
|
112
115
|
type: "INVOKE_REQUEST",
|
|
113
116
|
pluginId: "vendor.media",
|
|
114
117
|
event,
|
|
115
118
|
requestId: newRequestId(),
|
|
116
|
-
args
|
|
119
|
+
args: kind === void 0 ? {} : { kind }
|
|
117
120
|
}, /* @__PURE__ */ new Uint8Array(0));
|
|
118
121
|
if (!host) return err(ErrorCode.HOST_ERROR, `Host did not answer ${event}`);
|
|
119
122
|
if (host.error) return err(host.error.code || ErrorCode.HOST_ERROR, host.error.message ?? `Host failed ${event}`);
|
|
120
123
|
const path = host.result?.path;
|
|
121
124
|
if (!path) return err(ErrorCode.HOST_ERROR, `Host returned no path for ${event}`);
|
|
122
|
-
const id = `${
|
|
125
|
+
const id = `${kind ?? "media"}-${newRequestId()}`;
|
|
123
126
|
mountMedia(id, path);
|
|
124
127
|
const url = await deps.staticServer.url(`/media/${id}`);
|
|
125
128
|
return ok({ url });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I as CapabilityDescriptor, K as InvokeEnvelope } from "./index-Do-kTNXw.mjs";
|
|
2
2
|
export type DiscoveryListResult = {
|
|
3
3
|
schemaVersion: 1;
|
|
4
4
|
capabilities: CapabilityDescriptor[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { K as InvokeEnvelope, i as LogSource, n as LogEntry, r as LogLevel } from "./index-Do-kTNXw.mjs";
|
|
2
2
|
export type LogsViewArgs = {
|
|
3
3
|
/** Most-recent N matching entries. Defaults to a small window. */
|
|
4
4
|
tail?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { K as InvokeEnvelope } from "./index-Do-kTNXw.mjs";
|
|
2
2
|
export type MediaKind = 'image' | 'video';
|
|
3
3
|
export type MediaResult = {
|
|
4
4
|
/** URL served by the worklet's loopback HTTP server (no bytes on the wire). */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { K as InvokeEnvelope } from "./index-Do-kTNXw.mjs";
|
|
2
2
|
/** Canonical permission ids. Hosts map each to their platform equivalent. */
|
|
3
3
|
export type PermissionId = 'storage' | 'camera';
|
|
4
4
|
export type PermissionStatus = 'granted' | 'denied' | 'notDetermined' | 'unsupported';
|
package/dist/plugins.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as LoopbackServer } from "./static-file-server-
|
|
1
|
+
import { $ as PluginManifest, I as CapabilityDescriptor, Q as PluginInvokeResponseHeader, Z as PluginInvokeRequestHeader, a as LogStore, tt as RuntimeTarget } from "./index-Do-kTNXw.mjs";
|
|
2
|
+
import { n as LoopbackServer } from "./static-file-server-COxd-PFR.mjs";
|
|
3
3
|
type DiscoveryPluginDeps = {
|
|
4
4
|
listBareCapabilities: () => Array<{
|
|
5
5
|
pluginId: string;
|
package/dist/plugins.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as createDefaultPlugins } from "./plugins-
|
|
1
|
+
export { t as createDefaultPlugins } from "./plugins-BnpdCi3A.mjs";
|
package/dist/runtime.d.mts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import { C as createPluginRegistry,
|
|
2
|
-
import { i as createLoopbackServer, n as LoopbackServer, r as collectRequestBody, t as LoopbackRouteHandler } from "./static-file-server-
|
|
1
|
+
import { $ as PluginManifest, C as createPluginRegistry, I as CapabilityDescriptor, Q as PluginInvokeResponseHeader, Z as PluginInvokeRequestHeader, g as MessageProtocol, k as Platform, nt as WireMessage, o as BareRuntimeContext, q as MessageHeader, w as createPluginRouter } from "./index-Do-kTNXw.mjs";
|
|
2
|
+
import { i as createLoopbackServer, n as LoopbackServer, r as collectRequestBody, t as LoopbackRouteHandler } from "./static-file-server-COxd-PFR.mjs";
|
|
3
3
|
type BareIpcLike = {
|
|
4
|
-
write(data: Uint8Array |
|
|
4
|
+
write(data: Uint8Array | string): boolean;
|
|
5
5
|
};
|
|
6
6
|
declare function createHostIpcBridge(config: {
|
|
7
7
|
ipc: BareIpcLike;
|
|
8
8
|
protocol: MessageProtocol;
|
|
9
|
+
/** Worklet entry points pass `barePlatform`; Bare has no Web Crypto global. */
|
|
10
|
+
platform: Platform;
|
|
9
11
|
}): {
|
|
10
12
|
tryConsumeDownstream: (parsed: WireMessage) => boolean;
|
|
11
|
-
tryConsumeDownstreamFromHost(raw: Uint8Array | ArrayBuffer
|
|
13
|
+
tryConsumeDownstreamFromHost(raw: Uint8Array | ArrayBuffer): boolean;
|
|
12
14
|
queryCapabilities(timeoutMs?: number): Promise<CapabilityDescriptor[]>;
|
|
13
15
|
invokeOnHost(header: PluginInvokeRequestHeader, payload: Uint8Array, timeoutMs?: number): Promise<PluginInvokeResponseHeader | null>;
|
|
14
16
|
};
|
|
17
|
+
/** Envelope encoder bound to a loopback server's connected protocol socket —
|
|
18
|
+
* the server-initiated (backend → web) push seam. */
|
|
15
19
|
type LoopbackPush = (header: MessageHeader, payload?: Uint8Array | ArrayBuffer | null) => boolean;
|
|
16
20
|
/** Builds the push seam for the server's connected protocol socket: encodes a
|
|
17
21
|
* `DISPATCH`-style envelope and writes it, mirroring how `attachWebSocketProtocol`
|
|
@@ -20,8 +24,9 @@ export declare function createLoopbackPush(server: LoopbackServer, protocol: Mes
|
|
|
20
24
|
/**
|
|
21
25
|
* Attaches the framed-protocol socket to the unified loopback server. The
|
|
22
26
|
* server owns the WebSocket upgrade (origin check, cookie/token auth, single
|
|
23
|
-
* client, idle timeout); this layer
|
|
24
|
-
*
|
|
27
|
+
* client, idle timeout); this layer runs one frame channel per socket. A peer
|
|
28
|
+
* that sends a malformed frame is not recoverable on that socket, so it is
|
|
29
|
+
* torn down and the client reconnects.
|
|
25
30
|
*/
|
|
26
31
|
export declare function attachWebSocketProtocol(server: LoopbackServer, context: BareRuntimeContext): void;
|
|
27
32
|
/**
|
|
@@ -29,36 +34,36 @@ export declare function attachWebSocketProtocol(server: LoopbackServer, context:
|
|
|
29
34
|
*/
|
|
30
35
|
interface BareIPC extends NodeJS.EventEmitter {
|
|
31
36
|
read(n?: number): Buffer | null;
|
|
32
|
-
write(data:
|
|
37
|
+
write(data: Uint8Array | string): boolean;
|
|
33
38
|
resume?(): void;
|
|
34
39
|
pause?(): void;
|
|
35
40
|
}
|
|
36
41
|
/**
|
|
37
|
-
* Returns the active IPC channel.
|
|
38
|
-
* In BareKit (Android), it uses BareKit.IPC.
|
|
42
|
+
* Returns the active IPC channel, or null when there is no host.
|
|
43
|
+
* In BareKit (Android, iOS), it uses BareKit.IPC.
|
|
39
44
|
* In Bare (Sidecar), it uses Bare.IPC.
|
|
40
45
|
*/
|
|
41
|
-
export declare function getIPC(): BareIPC;
|
|
46
|
+
export declare function getIPC(): BareIPC | null;
|
|
42
47
|
/** Resolves the host-provided worklet configuration from `start(...)`
|
|
43
48
|
* arguments. On-device hosts pass `["<webAssets>", "<storage>", "<cache>"]`
|
|
44
|
-
* (three existing directories, in that order), landing at `Bare.argv[0..2]
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* device and dev runs. */
|
|
49
|
+
* (three existing directories, in that order), landing at `Bare.argv[0..2]`.
|
|
50
|
+
* Falls back to the labeled CLI token syntax (see `resolveCliConfig`) when the
|
|
51
|
+
* positional shape doesn't match, so the same entry works for device and dev
|
|
52
|
+
* runs. Nothing here turns auth off: the dev backend is selected only by an
|
|
53
|
+
* explicit `mode=dev` token. */
|
|
50
54
|
export declare function resolveWorkletConfig(): WorkletRuntimeOptions;
|
|
51
55
|
/**
|
|
52
|
-
* Parses
|
|
53
|
-
* `webassets=<dir>`, `storage=<dir>`, `cache=<dir>`,
|
|
54
|
-
* `port=<n>`, `auth=<on|off|true|false|1|0
|
|
55
|
-
*
|
|
56
|
-
*
|
|
56
|
+
* Parses labeled-token configuration from bare CLI arguments, one `key=value`
|
|
57
|
+
* per token: `webassets=<dir>`, `storage=<dir>`, `cache=<dir>`,
|
|
58
|
+
* `host=<addr>`, `port=<n>`, `auth=<on|off|true|false|1|0>`,
|
|
59
|
+
* `mode=<device|dev>` and `origin=<scheme://host[:port]>` (repeatable; an
|
|
60
|
+
* extra allowed page origin, e.g. the Vite dev server). Unknown labels (e.g.
|
|
61
|
+
* `bootstrap=127.0.0.1:49737`) are ignored and stay consumer-owned.
|
|
57
62
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* no labeled tokens are present
|
|
63
|
+
* Without `mode=dev` the result keeps the secure device defaults (auth on, an
|
|
64
|
+
* ephemeral port), and `auth=off` is ignored with a warning. `mode=dev` selects the dev backend: `deviceMode: false`,
|
|
65
|
+
* `auth: false`, `port: 8080`, each overridable by a token. Returns `{}` when
|
|
66
|
+
* no labeled tokens are present.
|
|
62
67
|
*/
|
|
63
68
|
export declare function resolveCliConfig(argv?: readonly string[]): WorkletRuntimeOptions;
|
|
64
69
|
export type WorkletRuntimeOptions = {
|
|
@@ -73,16 +78,21 @@ export type WorkletRuntimeOptions = {
|
|
|
73
78
|
/** Port to bind; `0` picks an ephemeral port (on-device). Defaults to an
|
|
74
79
|
* ephemeral port in device mode, 8080 in dev mode. */
|
|
75
80
|
port?: number;
|
|
76
|
-
/** Require the per-session token/cookie. Defaults to on in device mode
|
|
81
|
+
/** Require the per-session token/cookie. Defaults to on in device mode and
|
|
82
|
+
* off in dev mode. The origin check applies either way. */
|
|
77
83
|
auth?: boolean;
|
|
78
|
-
/**
|
|
79
|
-
* (
|
|
80
|
-
*
|
|
81
|
-
|
|
84
|
+
/** Extra page origins allowed to call the loopback server, e.g. the Vite dev
|
|
85
|
+
* server (`http://localhost:5173`). The bound origin and its loopback
|
|
86
|
+
* aliases are always allowed. */
|
|
87
|
+
allowedOrigins?: readonly string[];
|
|
88
|
+
/** Write `{ origin, port, bootstrap }` to `<storage>/handoff.json` for the
|
|
89
|
+
* host to read (auth on only; the session token is never written). Defaults
|
|
90
|
+
* to true; a host that receives them over its own channel (the desktop host
|
|
91
|
+
* reads them from a pipe) sets false so nothing touches disk. */
|
|
82
92
|
handoffFile?: boolean;
|
|
83
|
-
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
93
|
+
/** Device mode (the default): auth on, an ephemeral port, and the handoff
|
|
94
|
+
* file when `storage` is set. Pass `false` (or the `mode=dev` CLI token) for
|
|
95
|
+
* the dev backend: auth off and port 8080 unless set explicitly. */
|
|
86
96
|
deviceMode?: boolean;
|
|
87
97
|
/** Additional plugin manifests to register after the canonical defaults
|
|
88
98
|
* (consumer product plugins, e.g. `app.photos`). */
|
|
@@ -93,7 +103,8 @@ export type WorkletRuntimeOptions = {
|
|
|
93
103
|
* is destroyed, freeing the slot. Defaults to 10s. */
|
|
94
104
|
wsDeadPeerTimeoutMs?: number;
|
|
95
105
|
/** Minimum gap (ms) before an accepted protocol socket may be replaced by a
|
|
96
|
-
* new authenticated one
|
|
106
|
+
* new authenticated one; an upgrade that arrives sooner is held until then.
|
|
107
|
+
* Defaults to 1s. */
|
|
97
108
|
wsReplaceMinIntervalMs?: number;
|
|
98
109
|
/** Bytes queued behind a protocol socket whose reader stopped reading before
|
|
99
110
|
* server pushes are dropped (newest first). Defaults to 2 MiB. */
|