@immediately-run/sdk 0.2.1 → 0.2.3

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.
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var catalog_exports = {};
20
+ __export(catalog_exports, {
21
+ getCatalog: () => getCatalog,
22
+ invoke: () => invoke,
23
+ invokeStream: () => invokeStream,
24
+ onCatalogChange: () => onCatalogChange,
25
+ useCatalog: () => useCatalog
26
+ });
27
+ module.exports = __toCommonJS(catalog_exports);
28
+ var import_react = require("react");
29
+ var import_sandboxUtils = require("./sandboxUtils");
30
+ var import_protocolStream = require("./protocolStream");
31
+ const split = (name) => {
32
+ const i = name.indexOf(":");
33
+ if (i <= 0) throw new Error(`invalid catalog method name: ${name}`);
34
+ return [name.slice(0, i), name.slice(i + 1)];
35
+ };
36
+ const invoke = (name, params = {}) => {
37
+ const [scheme, method] = split(name);
38
+ return (0, import_sandboxUtils.protocolRequest)(scheme, method, [params]);
39
+ };
40
+ const bundlerTransport = {
41
+ send: (msg) => (
42
+ // @ts-ignore - injected by the sandbox runtime
43
+ module.evaluation.module.bundler.messageBus.sendMessage(msg.type, msg)
44
+ ),
45
+ subscribe: (type, handler) => {
46
+ const d = module.evaluation.module.bundler.messageBus.onMessage((m) => {
47
+ if (m && m.type === type) handler(m);
48
+ });
49
+ return () => d.dispose();
50
+ }
51
+ };
52
+ function invokeStream(name, params = {}) {
53
+ const [scheme, method] = split(name);
54
+ return (0, import_protocolStream.consumeStream)(bundlerTransport, `protocol-${scheme}`, method, [params]);
55
+ }
56
+ const catalogService = () => {
57
+ return module.evaluation.module.bundler.catalog;
58
+ };
59
+ const getCatalog = () => catalogService().getCatalog();
60
+ const onCatalogChange = (listener) => {
61
+ const disposable = catalogService().onChange(listener);
62
+ return () => disposable.dispose();
63
+ };
64
+ const useCatalog = () => {
65
+ const [catalog, setCatalog] = (0, import_react.useState)(getCatalog);
66
+ (0, import_react.useEffect)(() => onCatalogChange(setCatalog), []);
67
+ return catalog;
68
+ };
69
+ // Annotate the CommonJS export names for ESM import in node:
70
+ 0 && (module.exports = {
71
+ getCatalog,
72
+ invoke,
73
+ invokeStream,
74
+ onCatalogChange,
75
+ useCatalog
76
+ });
77
+ //# sourceMappingURL=catalog.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/catalog.ts"],"sourcesContent":["// The method catalog (UI_AS_APPS_SPEC §5.5) — the app's own grant-filtered RPC\n// surface, and a generic way to call it. The host advertises exactly the methods\n// this app may invoke (MCP-tool-shaped); `invoke()` calls one by its catalog name.\n// Handing the catalog to an embedded agent as its tool list confines the agent to\n// the app's authority (agent sandboxing falls out of the capability model, §5.9).\nimport { useEffect, useState } from 'react';\nimport { protocolRequest } from './sandboxUtils';\nimport type { StreamFrame } from './protocolStream';\nimport { consumeStream } from './protocolStream';\n\n/** One advertised method, as the host generated it from its gate table. */\nexport interface ApiMethod {\n /** Catalog name, `protocol-` stripped — e.g. `spaces:share`, `contribute:run`. */\n name: string;\n /** The capability this method requires (already held — it's in your catalog). */\n capability: string;\n /** True when the method STREAMS (use {@link invokeStream}) vs. single-reply. */\n stream?: boolean;\n}\n\n// `scheme:method` → ['scheme', 'method'] (the wire protocol is `protocol-scheme`).\nconst split = (name: string): [string, string] => {\n const i = name.indexOf(':');\n if (i <= 0) throw new Error(`invalid catalog method name: ${name}`);\n return [name.slice(0, i), name.slice(i + 1)];\n};\n\n/**\n * Call a catalog method by name — `invoke('spaces:share', { spaceId, login, role })`.\n * A thin generic over the host protocol: the host validates params and gates the\n * call (an un-granted method → `forbidden`, even if you name it directly). For a\n * STREAMING method (`ApiMethod.stream`), use {@link invokeStream}.\n */\nexport const invoke = <T = unknown>(name: string, params: Record<string, unknown> = {}): Promise<T> => {\n const [scheme, method] = split(name);\n return protocolRequest(scheme, method, [params]) as Promise<T>;\n};\n\nconst bundlerTransport = {\n send: (msg: { type: string; method: string; params: unknown[]; msgId: number; stream: true }) =>\n // @ts-ignore - injected by the sandbox runtime\n module.evaluation.module.bundler.messageBus.sendMessage(msg.type, msg),\n subscribe: (type: string, handler: (msg: { msgId?: number; stream?: StreamFrame }) => void) => {\n // @ts-ignore - injected by the sandbox runtime\n const d = module.evaluation.module.bundler.messageBus.onMessage((m: { type?: string }) => {\n if (m && m.type === type) handler(m as { msgId?: number; stream?: StreamFrame });\n });\n return () => d.dispose();\n },\n};\n\n/** Call a STREAMING catalog method by name, yielding its events. */\nexport function invokeStream<T = unknown, R = unknown>(\n name: string,\n params: Record<string, unknown> = {},\n): AsyncGenerator<T, R, void> {\n const [scheme, method] = split(name);\n return consumeStream<T, R>(bundlerTransport, `protocol-${scheme}`, method, [params]);\n}\n\ninterface CatalogService {\n getCatalog(): ApiMethod[];\n onChange(listener: (catalog: ApiMethod[]) => void): { dispose(): void };\n}\n\n// `module.evaluation.module.bundler.catalog` — injected by the sandbox runtime.\nconst catalogService = (): CatalogService => {\n // @ts-ignore - injected by the sandbox runtime\n return module.evaluation.module.bundler.catalog;\n};\n\n/** The methods this app may call (grant-filtered, §5.5). Poll for a one-off read;\n * use {@link onCatalogChange} / {@link useCatalog} to react. */\nexport const getCatalog = (): ApiMethod[] => catalogService().getCatalog();\n\n/** Subscribe to catalog changes (e.g. a grant added/revoked). Invoked immediately\n * with the current catalog, then on every change. Returns an unsubscribe fn. */\nexport const onCatalogChange = (listener: (catalog: ApiMethod[]) => void): (() => void) => {\n const disposable = catalogService().onChange(listener);\n return () => disposable.dispose();\n};\n\n/** React hook returning this app's method catalog, re-rendering on change. Hand\n * it to an embedded agent as its tool list to confine the agent to the app's\n * authority (§5.9). */\nexport const useCatalog = (): ApiMethod[] => {\n const [catalog, setCatalog] = useState<ApiMethod[]>(getCatalog);\n useEffect(() => onCatalogChange(setCatalog), []);\n return catalog;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,mBAAoC;AACpC,0BAAgC;AAEhC,4BAA8B;AAa9B,MAAM,QAAQ,CAAC,SAAmC;AAChD,QAAM,IAAI,KAAK,QAAQ,GAAG;AAC1B,MAAI,KAAK,EAAG,OAAM,IAAI,MAAM,gCAAgC,IAAI,EAAE;AAClE,SAAO,CAAC,KAAK,MAAM,GAAG,CAAC,GAAG,KAAK,MAAM,IAAI,CAAC,CAAC;AAC7C;AAQO,MAAM,SAAS,CAAc,MAAc,SAAkC,CAAC,MAAkB;AACrG,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,IAAI;AACnC,aAAO,qCAAgB,QAAQ,QAAQ,CAAC,MAAM,CAAC;AACjD;AAEA,MAAM,mBAAmB;AAAA,EACvB,MAAM,CAAC;AAAA;AAAA,IAEL,OAAO,WAAW,OAAO,QAAQ,WAAW,YAAY,IAAI,MAAM,GAAG;AAAA;AAAA,EACvE,WAAW,CAAC,MAAc,YAAqE;AAE7F,UAAM,IAAI,OAAO,WAAW,OAAO,QAAQ,WAAW,UAAU,CAAC,MAAyB;AACxF,UAAI,KAAK,EAAE,SAAS,KAAM,SAAQ,CAA6C;AAAA,IACjF,CAAC;AACD,WAAO,MAAM,EAAE,QAAQ;AAAA,EACzB;AACF;AAGO,SAAS,aACd,MACA,SAAkC,CAAC,GACP;AAC5B,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,IAAI;AACnC,aAAO,qCAAoB,kBAAkB,YAAY,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;AACrF;AAQA,MAAM,iBAAiB,MAAsB;AAE3C,SAAO,OAAO,WAAW,OAAO,QAAQ;AAC1C;AAIO,MAAM,aAAa,MAAmB,eAAe,EAAE,WAAW;AAIlE,MAAM,kBAAkB,CAAC,aAA2D;AACzF,QAAM,aAAa,eAAe,EAAE,SAAS,QAAQ;AACrD,SAAO,MAAM,WAAW,QAAQ;AAClC;AAKO,MAAM,aAAa,MAAmB;AAC3C,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAsB,UAAU;AAC9D,8BAAU,MAAM,gBAAgB,UAAU,GAAG,CAAC,CAAC;AAC/C,SAAO;AACT;","names":[]}
@@ -0,0 +1,30 @@
1
+ /** One advertised method, as the host generated it from its gate table. */
2
+ interface ApiMethod {
3
+ /** Catalog name, `protocol-` stripped — e.g. `spaces:share`, `contribute:run`. */
4
+ name: string;
5
+ /** The capability this method requires (already held — it's in your catalog). */
6
+ capability: string;
7
+ /** True when the method STREAMS (use {@link invokeStream}) vs. single-reply. */
8
+ stream?: boolean;
9
+ }
10
+ /**
11
+ * Call a catalog method by name — `invoke('spaces:share', { spaceId, login, role })`.
12
+ * A thin generic over the host protocol: the host validates params and gates the
13
+ * call (an un-granted method → `forbidden`, even if you name it directly). For a
14
+ * STREAMING method (`ApiMethod.stream`), use {@link invokeStream}.
15
+ */
16
+ declare const invoke: <T = unknown>(name: string, params?: Record<string, unknown>) => Promise<T>;
17
+ /** Call a STREAMING catalog method by name, yielding its events. */
18
+ declare function invokeStream<T = unknown, R = unknown>(name: string, params?: Record<string, unknown>): AsyncGenerator<T, R, void>;
19
+ /** The methods this app may call (grant-filtered, §5.5). Poll for a one-off read;
20
+ * use {@link onCatalogChange} / {@link useCatalog} to react. */
21
+ declare const getCatalog: () => ApiMethod[];
22
+ /** Subscribe to catalog changes (e.g. a grant added/revoked). Invoked immediately
23
+ * with the current catalog, then on every change. Returns an unsubscribe fn. */
24
+ declare const onCatalogChange: (listener: (catalog: ApiMethod[]) => void) => (() => void);
25
+ /** React hook returning this app's method catalog, re-rendering on change. Hand
26
+ * it to an embedded agent as its tool list to confine the agent to the app's
27
+ * authority (§5.9). */
28
+ declare const useCatalog: () => ApiMethod[];
29
+
30
+ export { type ApiMethod, getCatalog, invoke, invokeStream, onCatalogChange, useCatalog };
@@ -0,0 +1,30 @@
1
+ /** One advertised method, as the host generated it from its gate table. */
2
+ interface ApiMethod {
3
+ /** Catalog name, `protocol-` stripped — e.g. `spaces:share`, `contribute:run`. */
4
+ name: string;
5
+ /** The capability this method requires (already held — it's in your catalog). */
6
+ capability: string;
7
+ /** True when the method STREAMS (use {@link invokeStream}) vs. single-reply. */
8
+ stream?: boolean;
9
+ }
10
+ /**
11
+ * Call a catalog method by name — `invoke('spaces:share', { spaceId, login, role })`.
12
+ * A thin generic over the host protocol: the host validates params and gates the
13
+ * call (an un-granted method → `forbidden`, even if you name it directly). For a
14
+ * STREAMING method (`ApiMethod.stream`), use {@link invokeStream}.
15
+ */
16
+ declare const invoke: <T = unknown>(name: string, params?: Record<string, unknown>) => Promise<T>;
17
+ /** Call a STREAMING catalog method by name, yielding its events. */
18
+ declare function invokeStream<T = unknown, R = unknown>(name: string, params?: Record<string, unknown>): AsyncGenerator<T, R, void>;
19
+ /** The methods this app may call (grant-filtered, §5.5). Poll for a one-off read;
20
+ * use {@link onCatalogChange} / {@link useCatalog} to react. */
21
+ declare const getCatalog: () => ApiMethod[];
22
+ /** Subscribe to catalog changes (e.g. a grant added/revoked). Invoked immediately
23
+ * with the current catalog, then on every change. Returns an unsubscribe fn. */
24
+ declare const onCatalogChange: (listener: (catalog: ApiMethod[]) => void) => (() => void);
25
+ /** React hook returning this app's method catalog, re-rendering on change. Hand
26
+ * it to an embedded agent as its tool list to confine the agent to the app's
27
+ * authority (§5.9). */
28
+ declare const useCatalog: () => ApiMethod[];
29
+
30
+ export { type ApiMethod, getCatalog, invoke, invokeStream, onCatalogChange, useCatalog };
@@ -0,0 +1,49 @@
1
+ import { useEffect, useState } from "react";
2
+ import { protocolRequest } from "./sandboxUtils";
3
+ import { consumeStream } from "./protocolStream";
4
+ const split = (name) => {
5
+ const i = name.indexOf(":");
6
+ if (i <= 0) throw new Error(`invalid catalog method name: ${name}`);
7
+ return [name.slice(0, i), name.slice(i + 1)];
8
+ };
9
+ const invoke = (name, params = {}) => {
10
+ const [scheme, method] = split(name);
11
+ return protocolRequest(scheme, method, [params]);
12
+ };
13
+ const bundlerTransport = {
14
+ send: (msg) => (
15
+ // @ts-ignore - injected by the sandbox runtime
16
+ module.evaluation.module.bundler.messageBus.sendMessage(msg.type, msg)
17
+ ),
18
+ subscribe: (type, handler) => {
19
+ const d = module.evaluation.module.bundler.messageBus.onMessage((m) => {
20
+ if (m && m.type === type) handler(m);
21
+ });
22
+ return () => d.dispose();
23
+ }
24
+ };
25
+ function invokeStream(name, params = {}) {
26
+ const [scheme, method] = split(name);
27
+ return consumeStream(bundlerTransport, `protocol-${scheme}`, method, [params]);
28
+ }
29
+ const catalogService = () => {
30
+ return module.evaluation.module.bundler.catalog;
31
+ };
32
+ const getCatalog = () => catalogService().getCatalog();
33
+ const onCatalogChange = (listener) => {
34
+ const disposable = catalogService().onChange(listener);
35
+ return () => disposable.dispose();
36
+ };
37
+ const useCatalog = () => {
38
+ const [catalog, setCatalog] = useState(getCatalog);
39
+ useEffect(() => onCatalogChange(setCatalog), []);
40
+ return catalog;
41
+ };
42
+ export {
43
+ getCatalog,
44
+ invoke,
45
+ invokeStream,
46
+ onCatalogChange,
47
+ useCatalog
48
+ };
49
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/catalog.ts"],"sourcesContent":["// The method catalog (UI_AS_APPS_SPEC §5.5) — the app's own grant-filtered RPC\n// surface, and a generic way to call it. The host advertises exactly the methods\n// this app may invoke (MCP-tool-shaped); `invoke()` calls one by its catalog name.\n// Handing the catalog to an embedded agent as its tool list confines the agent to\n// the app's authority (agent sandboxing falls out of the capability model, §5.9).\nimport { useEffect, useState } from 'react';\nimport { protocolRequest } from './sandboxUtils';\nimport type { StreamFrame } from './protocolStream';\nimport { consumeStream } from './protocolStream';\n\n/** One advertised method, as the host generated it from its gate table. */\nexport interface ApiMethod {\n /** Catalog name, `protocol-` stripped — e.g. `spaces:share`, `contribute:run`. */\n name: string;\n /** The capability this method requires (already held — it's in your catalog). */\n capability: string;\n /** True when the method STREAMS (use {@link invokeStream}) vs. single-reply. */\n stream?: boolean;\n}\n\n// `scheme:method` → ['scheme', 'method'] (the wire protocol is `protocol-scheme`).\nconst split = (name: string): [string, string] => {\n const i = name.indexOf(':');\n if (i <= 0) throw new Error(`invalid catalog method name: ${name}`);\n return [name.slice(0, i), name.slice(i + 1)];\n};\n\n/**\n * Call a catalog method by name — `invoke('spaces:share', { spaceId, login, role })`.\n * A thin generic over the host protocol: the host validates params and gates the\n * call (an un-granted method → `forbidden`, even if you name it directly). For a\n * STREAMING method (`ApiMethod.stream`), use {@link invokeStream}.\n */\nexport const invoke = <T = unknown>(name: string, params: Record<string, unknown> = {}): Promise<T> => {\n const [scheme, method] = split(name);\n return protocolRequest(scheme, method, [params]) as Promise<T>;\n};\n\nconst bundlerTransport = {\n send: (msg: { type: string; method: string; params: unknown[]; msgId: number; stream: true }) =>\n // @ts-ignore - injected by the sandbox runtime\n module.evaluation.module.bundler.messageBus.sendMessage(msg.type, msg),\n subscribe: (type: string, handler: (msg: { msgId?: number; stream?: StreamFrame }) => void) => {\n // @ts-ignore - injected by the sandbox runtime\n const d = module.evaluation.module.bundler.messageBus.onMessage((m: { type?: string }) => {\n if (m && m.type === type) handler(m as { msgId?: number; stream?: StreamFrame });\n });\n return () => d.dispose();\n },\n};\n\n/** Call a STREAMING catalog method by name, yielding its events. */\nexport function invokeStream<T = unknown, R = unknown>(\n name: string,\n params: Record<string, unknown> = {},\n): AsyncGenerator<T, R, void> {\n const [scheme, method] = split(name);\n return consumeStream<T, R>(bundlerTransport, `protocol-${scheme}`, method, [params]);\n}\n\ninterface CatalogService {\n getCatalog(): ApiMethod[];\n onChange(listener: (catalog: ApiMethod[]) => void): { dispose(): void };\n}\n\n// `module.evaluation.module.bundler.catalog` — injected by the sandbox runtime.\nconst catalogService = (): CatalogService => {\n // @ts-ignore - injected by the sandbox runtime\n return module.evaluation.module.bundler.catalog;\n};\n\n/** The methods this app may call (grant-filtered, §5.5). Poll for a one-off read;\n * use {@link onCatalogChange} / {@link useCatalog} to react. */\nexport const getCatalog = (): ApiMethod[] => catalogService().getCatalog();\n\n/** Subscribe to catalog changes (e.g. a grant added/revoked). Invoked immediately\n * with the current catalog, then on every change. Returns an unsubscribe fn. */\nexport const onCatalogChange = (listener: (catalog: ApiMethod[]) => void): (() => void) => {\n const disposable = catalogService().onChange(listener);\n return () => disposable.dispose();\n};\n\n/** React hook returning this app's method catalog, re-rendering on change. Hand\n * it to an embedded agent as its tool list to confine the agent to the app's\n * authority (§5.9). */\nexport const useCatalog = (): ApiMethod[] => {\n const [catalog, setCatalog] = useState<ApiMethod[]>(getCatalog);\n useEffect(() => onCatalogChange(setCatalog), []);\n return catalog;\n};\n"],"mappings":"AAKA,SAAS,WAAW,gBAAgB;AACpC,SAAS,uBAAuB;AAEhC,SAAS,qBAAqB;AAa9B,MAAM,QAAQ,CAAC,SAAmC;AAChD,QAAM,IAAI,KAAK,QAAQ,GAAG;AAC1B,MAAI,KAAK,EAAG,OAAM,IAAI,MAAM,gCAAgC,IAAI,EAAE;AAClE,SAAO,CAAC,KAAK,MAAM,GAAG,CAAC,GAAG,KAAK,MAAM,IAAI,CAAC,CAAC;AAC7C;AAQO,MAAM,SAAS,CAAc,MAAc,SAAkC,CAAC,MAAkB;AACrG,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,IAAI;AACnC,SAAO,gBAAgB,QAAQ,QAAQ,CAAC,MAAM,CAAC;AACjD;AAEA,MAAM,mBAAmB;AAAA,EACvB,MAAM,CAAC;AAAA;AAAA,IAEL,OAAO,WAAW,OAAO,QAAQ,WAAW,YAAY,IAAI,MAAM,GAAG;AAAA;AAAA,EACvE,WAAW,CAAC,MAAc,YAAqE;AAE7F,UAAM,IAAI,OAAO,WAAW,OAAO,QAAQ,WAAW,UAAU,CAAC,MAAyB;AACxF,UAAI,KAAK,EAAE,SAAS,KAAM,SAAQ,CAA6C;AAAA,IACjF,CAAC;AACD,WAAO,MAAM,EAAE,QAAQ;AAAA,EACzB;AACF;AAGO,SAAS,aACd,MACA,SAAkC,CAAC,GACP;AAC5B,QAAM,CAAC,QAAQ,MAAM,IAAI,MAAM,IAAI;AACnC,SAAO,cAAoB,kBAAkB,YAAY,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;AACrF;AAQA,MAAM,iBAAiB,MAAsB;AAE3C,SAAO,OAAO,WAAW,OAAO,QAAQ;AAC1C;AAIO,MAAM,aAAa,MAAmB,eAAe,EAAE,WAAW;AAIlE,MAAM,kBAAkB,CAAC,aAA2D;AACzF,QAAM,aAAa,eAAe,EAAE,SAAS,QAAQ;AACrD,SAAO,MAAM,WAAW,QAAQ;AAClC;AAKO,MAAM,aAAa,MAAmB;AAC3C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAsB,UAAU;AAC9D,YAAU,MAAM,gBAAgB,UAAU,GAAG,CAAC,CAAC;AAC/C,SAAO;AACT;","names":[]}
package/dist/index.cjs CHANGED
@@ -27,6 +27,7 @@ __reExport(index_exports, require("./editorContext"), module.exports);
27
27
  __reExport(index_exports, require("./formFactor"), module.exports);
28
28
  __reExport(index_exports, require("./mounts"), module.exports);
29
29
  __reExport(index_exports, require("./contribute"), module.exports);
30
+ __reExport(index_exports, require("./catalog"), module.exports);
30
31
  __reExport(index_exports, require("./protocolStream"), module.exports);
31
32
  __reExport(index_exports, require("./sandboxTypes"), module.exports);
32
33
  // Annotate the CommonJS export names for ESM import in node:
@@ -43,6 +44,7 @@ __reExport(index_exports, require("./sandboxTypes"), module.exports);
43
44
  ...require("./formFactor"),
44
45
  ...require("./mounts"),
45
46
  ...require("./contribute"),
47
+ ...require("./catalog"),
46
48
  ...require("./protocolStream"),
47
49
  ...require("./sandboxTypes")
48
50
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './hooks'\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './formFactor';\nexport * from './mounts';\nexport * from './contribute';\nexport * from './protocolStream';\nexport * from './sandboxTypes';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAc,0BAAd;AACA,0BAAc,sBADd;AAEA,0BAAc,mBAFd;AAGA,0BAAc,iCAHd;AAIA,0BAAc,uCAJd;AAKA,0BAAc,oBALd;AAMA,0BAAc,mBANd;AAOA,0BAAc,oBAPd;AAQA,0BAAc,4BARd;AASA,0BAAc,yBATd;AAUA,0BAAc,qBAVd;AAWA,0BAAc,yBAXd;AAYA,0BAAc,6BAZd;AAaA,0BAAc,2BAbd;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './hooks'\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './formFactor';\nexport * from './mounts';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './protocolStream';\nexport * from './sandboxTypes';\n"],"mappings":";;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAc,0BAAd;AACA,0BAAc,sBADd;AAEA,0BAAc,mBAFd;AAGA,0BAAc,iCAHd;AAIA,0BAAc,uCAJd;AAKA,0BAAc,oBALd;AAMA,0BAAc,mBANd;AAOA,0BAAc,oBAPd;AAQA,0BAAc,4BARd;AASA,0BAAc,yBATd;AAUA,0BAAc,qBAVd;AAWA,0BAAc,yBAXd;AAYA,0BAAc,sBAZd;AAaA,0BAAc,6BAbd;AAcA,0BAAc,2BAdd;","names":[]}
package/dist/index.d.cts CHANGED
@@ -8,8 +8,9 @@ export { AuthState, AuthStatus, SandboxUser, getAuthState, onAuthChange, useAuth
8
8
  export { HostTheme, getHostTheme, onHostThemeChange, setHostTheme, useHostTheme } from './theme.cjs';
9
9
  export { EditorContext, getEditorContext, onEditorContextChange, useEditorContext } from './editorContext.cjs';
10
10
  export { FormFactor, FormFactorClass, Orientation, getFormFactor, onFormFactorChange, useFormFactor } from './formFactor.cjs';
11
- export { Member, MountQuery, ResolvedUser, Role, SandboxMount, SpaceError, SpaceInfo, createSpace, findMount, getMounts, getSpaceMembers, listAllSpaces, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount } from './mounts.cjs';
11
+ export { GrantRecord, Member, MountQuery, ResolvedUser, Role, SandboxMount, SpaceError, SpaceInfo, createSpace, findMount, getMounts, getSpaceMembers, listAllSpaces, listGrants, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, revokeGrant, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount } from './mounts.cjs';
12
12
  export { ContributeMode, ContributeOptions, ContributionEvent, ContributionResult, contribute } from './contribute.cjs';
13
+ export { ApiMethod, getCatalog, invoke, invokeStream, onCatalogChange, useCatalog } from './catalog.cjs';
13
14
  export { StreamError, StreamFrame, StreamTransport, consumeStream, protocolStream } from './protocolStream.cjs';
14
15
  export { EvaluationContext, FileQueryResult, FilesMetadata, Metadata, MetadataQueryFunction, MetadataQueryResult, ModuleExports } from './sandboxTypes.cjs';
15
16
  import 'react';
package/dist/index.d.ts CHANGED
@@ -8,8 +8,9 @@ export { AuthState, AuthStatus, SandboxUser, getAuthState, onAuthChange, useAuth
8
8
  export { HostTheme, getHostTheme, onHostThemeChange, setHostTheme, useHostTheme } from './theme.js';
9
9
  export { EditorContext, getEditorContext, onEditorContextChange, useEditorContext } from './editorContext.js';
10
10
  export { FormFactor, FormFactorClass, Orientation, getFormFactor, onFormFactorChange, useFormFactor } from './formFactor.js';
11
- export { Member, MountQuery, ResolvedUser, Role, SandboxMount, SpaceError, SpaceInfo, createSpace, findMount, getMounts, getSpaceMembers, listAllSpaces, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount } from './mounts.js';
11
+ export { GrantRecord, Member, MountQuery, ResolvedUser, Role, SandboxMount, SpaceError, SpaceInfo, createSpace, findMount, getMounts, getSpaceMembers, listAllSpaces, listGrants, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, revokeGrant, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount } from './mounts.js';
12
12
  export { ContributeMode, ContributeOptions, ContributionEvent, ContributionResult, contribute } from './contribute.js';
13
+ export { ApiMethod, getCatalog, invoke, invokeStream, onCatalogChange, useCatalog } from './catalog.js';
13
14
  export { StreamError, StreamFrame, StreamTransport, consumeStream, protocolStream } from './protocolStream.js';
14
15
  export { EvaluationContext, FileQueryResult, FilesMetadata, Metadata, MetadataQueryFunction, MetadataQueryResult, ModuleExports } from './sandboxTypes.js';
15
16
  import 'react';
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ export * from "./editorContext";
10
10
  export * from "./formFactor";
11
11
  export * from "./mounts";
12
12
  export * from "./contribute";
13
+ export * from "./catalog";
13
14
  export * from "./protocolStream";
14
15
  export * from "./sandboxTypes";
15
16
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './hooks'\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './formFactor';\nexport * from './mounts';\nexport * from './contribute';\nexport * from './protocolStream';\nexport * from './sandboxTypes';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./MDXProvider\";\nexport * from \"./routing\";\nexport * from \"./boot\";\nexport * from './components/Include';\nexport * from './components/MDXComponents';\nexport * from './hooks'\nexport * from './auth';\nexport * from './theme';\nexport * from './editorContext';\nexport * from './formFactor';\nexport * from './mounts';\nexport * from './contribute';\nexport * from './catalog';\nexport * from './protocolStream';\nexport * from './sandboxTypes';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
package/dist/mounts.cjs CHANGED
@@ -23,6 +23,7 @@ __export(mounts_exports, {
23
23
  getMounts: () => getMounts,
24
24
  getSpaceMembers: () => getSpaceMembers,
25
25
  listAllSpaces: () => listAllSpaces,
26
+ listGrants: () => listGrants,
26
27
  listSpaces: () => listSpaces,
27
28
  lookupUser: () => lookupUser,
28
29
  mount: () => mount,
@@ -31,6 +32,7 @@ __export(mounts_exports, {
31
32
  openAppSpace: () => openAppSpace,
32
33
  requestMount: () => requestMount,
33
34
  requestSpace: () => requestSpace,
35
+ revokeGrant: () => revokeGrant,
34
36
  setSpaceRole: () => setSpaceRole,
35
37
  shareSpace: () => shareSpace,
36
38
  unmountSpace: () => unmountSpace,
@@ -100,6 +102,10 @@ const setSpaceRole = async (spaceId, uid, role) => {
100
102
  await request("setRole", { spaceId, uid, role });
101
103
  };
102
104
  const lookupUser = (login) => request("lookupUser", { login });
105
+ const listGrants = () => request("grants", {});
106
+ const revokeGrant = async (appKey, spaceId) => {
107
+ await request("revokeGrant", { appKey, spaceId });
108
+ };
103
109
  // Annotate the CommonJS export names for ESM import in node:
104
110
  0 && (module.exports = {
105
111
  createSpace,
@@ -107,6 +113,7 @@ const lookupUser = (login) => request("lookupUser", { login });
107
113
  getMounts,
108
114
  getSpaceMembers,
109
115
  listAllSpaces,
116
+ listGrants,
110
117
  listSpaces,
111
118
  lookupUser,
112
119
  mount,
@@ -115,6 +122,7 @@ const lookupUser = (login) => request("lookupUser", { login });
115
122
  openAppSpace,
116
123
  requestMount,
117
124
  requestSpace,
125
+ revokeGrant,
118
126
  setSpaceRole,
119
127
  shareSpace,
120
128
  unmountSpace,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mounts.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { protocolRequest } from './sandboxUtils';\n\n/**\n * A filesystem mount available to the sandbox, mirrored from the host window.\n *\n * Mounts appear on demand — call {@link openAppSpace} / {@link mountSpace} to ask\n * the host to mount a Firestore-backed \"space\"; it appears at `/spaces/{id}`.\n * Read or subscribe to the set, then access the files through the `fs` module at\n * the mount's `path`.\n */\nexport interface SandboxMount {\n /** Absolute path where the mount is reachable (e.g. `/spaces/{id}`). */\n path: string;\n /** Backend kind, e.g. `'firestore'`. */\n type: string;\n /** Optional stable identifier (the spaceId, for spaces). */\n id?: string;\n}\n\ninterface MountService {\n getMounts(): SandboxMount[];\n onChange(listener: (mounts: SandboxMount[]) => void): { dispose(): void };\n}\n\n// `module.evaluation.module.bundler` is the sandbox bundler injected into the\n// evaluation context (same path the other SDK helpers reach for `messageBus`).\nconst mountService = (): MountService => {\n // @ts-ignore - injected by the sandbox runtime\n return module.evaluation.module.bundler.mounts;\n};\n\n/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. */\nexport type MountQuery = { type?: string; id?: string; path?: string };\n\nconst matches = (mount: SandboxMount, query: MountQuery): boolean =>\n (query.type === undefined || mount.type === query.type) &&\n (query.id === undefined || mount.id === query.id) &&\n (query.path === undefined || mount.path === query.path);\n\n/**\n * Returns the mounts currently available. Poll this whenever you need a one-off\n * read; use {@link onMountsChange} or {@link useMounts} to react to changes.\n */\nexport const getMounts = (): SandboxMount[] => mountService().getMounts();\n\n/** Returns the first mount matching `query`, or `undefined`. */\nexport const findMount = (query: MountQuery): SandboxMount | undefined =>\n getMounts().find((m) => matches(m, query));\n\n/**\n * Subscribe to mount changes. The listener is invoked immediately with the\n * current mounts, then again on every change. Returns an unsubscribe fn.\n */\nexport const onMountsChange = (listener: (mounts: SandboxMount[]) => void): (() => void) => {\n const disposable = mountService().onChange(listener);\n return () => disposable.dispose();\n};\n\n/**\n * Resolves once a mount matching `query` is present (immediately if it already\n * is). Handy for \"use it when it appears\" — e.g.\n * `await waitForMount({ type: 'firestore' })` before reading `/firestore`.\n */\nexport const waitForMount = (query: MountQuery): Promise<SandboxMount> =>\n new Promise((resolve) => {\n const unsubscribe = onMountsChange((mounts) => {\n const found = mounts.find((m) => matches(m, query));\n if (found) {\n // Defer unsubscribe so we don't dispose during the initial replay call.\n Promise.resolve().then(unsubscribe);\n resolve(found);\n }\n });\n });\n\n/** React hook returning the mounts currently available, re-rendering on change. */\nexport const useMounts = (): SandboxMount[] => {\n const [mounts, setMounts] = useState<SandboxMount[]>(getMounts);\n useEffect(() => onMountsChange(setMounts), []);\n return mounts;\n};\n\n// ---------------------------------------------------------------------------\n// Spaces — on-demand, shareable Firestore-backed filesystems.\n// The host owns all UX: if you aren't signed in, or the space doesn't exist or\n// isn't accessible, the parent window presents sign-in / create / request-access\n// and only then resolves these calls. See docs/specs/FILE_SHARING_SPEC.md.\n// ---------------------------------------------------------------------------\n\n/** Summary of a space, as returned by {@link listSpaces}. */\nexport interface SpaceInfo {\n spaceId: string;\n role?: 'owner' | 'writer' | 'reader';\n owner?: string;\n name?: string;\n}\n\n/** An error from a space operation, carrying a machine-readable `code`. */\nexport interface SpaceError extends Error {\n code:\n | 'auth-required'\n | 'cancelled'\n | 'forbidden'\n | 'not-found'\n | 'unsupported-scheme'\n | 'unknown';\n}\n\ntype SpaceResult =\n | { ok: true; data: unknown }\n | { ok: false; code: string; message: string };\n\n// Issue a spaces protocol request, unwrapping the host's {ok,data} envelope and\n// throwing a typed SpaceError on failure.\nconst request = async <T = unknown>(\n method: string,\n query: Record<string, unknown> = {},\n): Promise<T> => {\n const res = (await protocolRequest('spaces', method, [query])) as SpaceResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? 'space request failed') as SpaceError;\n err.code = (res?.code as SpaceError['code']) ?? 'unknown';\n throw err;\n }\n return res.data as T;\n};\n\n// Request a space mount, then wait until the host actually registers it. The\n// host announces the mount (`mount-add`) separately from the protocol reply, so\n// an immediate read could otherwise race the mount.\nconst requestMountInternal = async (\n method: string,\n query: Record<string, unknown>,\n): Promise<SandboxMount> => {\n const mount = await request<SandboxMount>(method, query);\n return waitForMount({ id: mount.id ?? mount.path });\n};\n\n/**\n * Open this app's workspace for the signed-in user (the zero-config path). The\n * `slot` names which workspace (default `'default'`); pass distinct slots for\n * multiple filesystems in one app. On a missing slot the host shows a\n * create-or-pick dialog. Rejects with a {@link SpaceError} (`.code`) on cancel.\n */\nexport const openAppSpace = (slot = 'default'): Promise<SandboxMount> =>\n requestMountInternal('open', { slot });\n\n/**\n * Mount a filesystem by its **universal mount id** (UI_AS_APPS_SPEC §3.5) —\n * `scheme:locator`, e.g. `space:{spaceId}` or `github:owner/repo@ref`. Backend-blind:\n * the host resolves the scheme. A scheme with no resolver rejects with\n * {@link SpaceError} `unsupported-scheme`.\n */\nexport const mount = (mountId: string): Promise<SandboxMount> =>\n requestMountInternal('mount', { mount: mountId });\n\n/** Mount a specific space by id (e.g. one shared with you, or from a link). A thin\n * shim over {@link mount} with the `space:` scheme. */\nexport const mountSpace = (query: { spaceId: string }): Promise<SandboxMount> =>\n mount(`space:${query.spaceId}`);\n\n/**\n * Ask the user to grant a filesystem to this app — the §8.6 powerbox. The app\n * asks; the HOST shows the user their mounts and the access choice (which mount,\n * an optional subtree, read-only vs read-write); the USER picks or declines. The\n * app never sees the list — it resolves with the single granted mount, or rejects\n * with a {@link SpaceError} (`cancelled`) if declined. The granted scope is\n * enforced host-side: the mount is chroot'd / `ro`-limited accordingly.\n *\n * Backend-general (§3.5): the picker offers whatever mounts the user has (today,\n * their spaces). Returns the granted mount by its universal id.\n */\nexport const requestMount = (): Promise<SandboxMount> =>\n requestMountInternal('request', {});\n\n/** @deprecated renamed to {@link requestMount} (backend-general, §3.5). */\nexport const requestSpace = requestMount;\n\n/** Create a brand-new space, optionally binding it to this app (a slot). */\nexport const createSpace = (\n opts: { name?: string; slot?: string; bindToApp?: boolean } = {}\n): Promise<SandboxMount> => requestMountInternal('create', opts);\n\n/** List spaces you can access — all of them, or just those bound to this app. */\nexport const listSpaces = (opts: { app?: boolean } = {}): Promise<SpaceInfo[]> =>\n request<SpaceInfo[]>('list', opts);\n\n/** Release a mounted space (stops its listener on the host). */\nexport const unmountSpace = async (query: { spaceId: string }): Promise<void> => {\n await request('unmount', query);\n};\n\n// ---------------------------------------------------------------------------\n// Space management (the space-manager app) — UI_AS_APPS_SPEC §5.2. These are\n// ELEVATED: enumerating all the user's spaces is `spaces:user`; mutating\n// membership (share/unshare/setRole) and resolving handles is `spaces:admin`.\n// The host enforces the owner-lockout invariant (a space always keeps an owner,\n// T41) and rate-limits handle lookups (L1); the OAuth/identity token never\n// crosses to the app.\n// ---------------------------------------------------------------------------\n\nexport type Role = 'owner' | 'writer' | 'reader';\n\n/** A member of a space (for the share/manage UI). */\nexport interface Member {\n /** `user:{uid}` | `group:{gid}`. */\n principal: string;\n role: Role;\n login?: string;\n avatarUrl?: string;\n}\n\n/** A handle resolved to a principal (handle → who). */\nexport interface ResolvedUser {\n uid: string;\n login: string;\n avatarUrl?: string;\n}\n\n/** Enumerate ALL the user's spaces (not just this app's) — `spaces:user`. */\nexport const listAllSpaces = (): Promise<SpaceInfo[]> => request<SpaceInfo[]>('listAll', {});\n\n/** Read a space's members one-shot — `spaces:admin`. */\nexport const getSpaceMembers = (spaceId: string): Promise<Member[]> =>\n request<Member[]>('members', { spaceId });\n\n/** Invite a user (by provider handle) to a space at a role — `spaces:admin`. The\n * host resolves the handle, so the app never sees other users' uids except the\n * one it invited. */\nexport const shareSpace = async (spaceId: string, login: string, role: Role): Promise<void> => {\n await request('share', { spaceId, login, role });\n};\n\n/** Remove a member from a space — `spaces:admin`. Refused if it would orphan the\n * space (owner-lockout, T41). */\nexport const unshareSpace = async (spaceId: string, uid: string): Promise<void> => {\n await request('unshare', { spaceId, uid });\n};\n\n/** Change a member's role — `spaces:admin`. Refused if it would drop the sole\n * owner (owner-lockout, T41). */\nexport const setSpaceRole = async (spaceId: string, uid: string, role: Role): Promise<void> => {\n await request('setRole', { spaceId, uid, role });\n};\n\n/** Resolve a provider handle to a principal (for the invite flow) — `spaces:admin`,\n * rate-limited host-side. */\nexport const lookupUser = (login: string): Promise<ResolvedUser> =>\n request<ResolvedUser>('lookupUser', { login });\n"],"mappings":"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","names":["mount"]}
1
+ {"version":3,"sources":["../src/mounts.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { protocolRequest } from './sandboxUtils';\n\n/**\n * A filesystem mount available to the sandbox, mirrored from the host window.\n *\n * Mounts appear on demand — call {@link openAppSpace} / {@link mountSpace} to ask\n * the host to mount a Firestore-backed \"space\"; it appears at `/spaces/{id}`.\n * Read or subscribe to the set, then access the files through the `fs` module at\n * the mount's `path`.\n */\nexport interface SandboxMount {\n /** Absolute path where the mount is reachable (e.g. `/spaces/{id}`). */\n path: string;\n /** Backend kind, e.g. `'firestore'`. */\n type: string;\n /** Optional stable identifier (the spaceId, for spaces). */\n id?: string;\n}\n\ninterface MountService {\n getMounts(): SandboxMount[];\n onChange(listener: (mounts: SandboxMount[]) => void): { dispose(): void };\n}\n\n// `module.evaluation.module.bundler` is the sandbox bundler injected into the\n// evaluation context (same path the other SDK helpers reach for `messageBus`).\nconst mountService = (): MountService => {\n // @ts-ignore - injected by the sandbox runtime\n return module.evaluation.module.bundler.mounts;\n};\n\n/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. */\nexport type MountQuery = { type?: string; id?: string; path?: string };\n\nconst matches = (mount: SandboxMount, query: MountQuery): boolean =>\n (query.type === undefined || mount.type === query.type) &&\n (query.id === undefined || mount.id === query.id) &&\n (query.path === undefined || mount.path === query.path);\n\n/**\n * Returns the mounts currently available. Poll this whenever you need a one-off\n * read; use {@link onMountsChange} or {@link useMounts} to react to changes.\n */\nexport const getMounts = (): SandboxMount[] => mountService().getMounts();\n\n/** Returns the first mount matching `query`, or `undefined`. */\nexport const findMount = (query: MountQuery): SandboxMount | undefined =>\n getMounts().find((m) => matches(m, query));\n\n/**\n * Subscribe to mount changes. The listener is invoked immediately with the\n * current mounts, then again on every change. Returns an unsubscribe fn.\n */\nexport const onMountsChange = (listener: (mounts: SandboxMount[]) => void): (() => void) => {\n const disposable = mountService().onChange(listener);\n return () => disposable.dispose();\n};\n\n/**\n * Resolves once a mount matching `query` is present (immediately if it already\n * is). Handy for \"use it when it appears\" — e.g.\n * `await waitForMount({ type: 'firestore' })` before reading `/firestore`.\n */\nexport const waitForMount = (query: MountQuery): Promise<SandboxMount> =>\n new Promise((resolve) => {\n const unsubscribe = onMountsChange((mounts) => {\n const found = mounts.find((m) => matches(m, query));\n if (found) {\n // Defer unsubscribe so we don't dispose during the initial replay call.\n Promise.resolve().then(unsubscribe);\n resolve(found);\n }\n });\n });\n\n/** React hook returning the mounts currently available, re-rendering on change. */\nexport const useMounts = (): SandboxMount[] => {\n const [mounts, setMounts] = useState<SandboxMount[]>(getMounts);\n useEffect(() => onMountsChange(setMounts), []);\n return mounts;\n};\n\n// ---------------------------------------------------------------------------\n// Spaces — on-demand, shareable Firestore-backed filesystems.\n// The host owns all UX: if you aren't signed in, or the space doesn't exist or\n// isn't accessible, the parent window presents sign-in / create / request-access\n// and only then resolves these calls. See docs/specs/FILE_SHARING_SPEC.md.\n// ---------------------------------------------------------------------------\n\n/** Summary of a space, as returned by {@link listSpaces}. */\nexport interface SpaceInfo {\n spaceId: string;\n role?: 'owner' | 'writer' | 'reader';\n owner?: string;\n name?: string;\n}\n\n/** An error from a space operation, carrying a machine-readable `code`. */\nexport interface SpaceError extends Error {\n code:\n | 'auth-required'\n | 'cancelled'\n | 'forbidden'\n | 'not-found'\n | 'unsupported-scheme'\n | 'unknown';\n}\n\ntype SpaceResult =\n | { ok: true; data: unknown }\n | { ok: false; code: string; message: string };\n\n// Issue a spaces protocol request, unwrapping the host's {ok,data} envelope and\n// throwing a typed SpaceError on failure.\nconst request = async <T = unknown>(\n method: string,\n query: Record<string, unknown> = {},\n): Promise<T> => {\n const res = (await protocolRequest('spaces', method, [query])) as SpaceResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? 'space request failed') as SpaceError;\n err.code = (res?.code as SpaceError['code']) ?? 'unknown';\n throw err;\n }\n return res.data as T;\n};\n\n// Request a space mount, then wait until the host actually registers it. The\n// host announces the mount (`mount-add`) separately from the protocol reply, so\n// an immediate read could otherwise race the mount.\nconst requestMountInternal = async (\n method: string,\n query: Record<string, unknown>,\n): Promise<SandboxMount> => {\n const mount = await request<SandboxMount>(method, query);\n return waitForMount({ id: mount.id ?? mount.path });\n};\n\n/**\n * Open this app's workspace for the signed-in user (the zero-config path). The\n * `slot` names which workspace (default `'default'`); pass distinct slots for\n * multiple filesystems in one app. On a missing slot the host shows a\n * create-or-pick dialog. Rejects with a {@link SpaceError} (`.code`) on cancel.\n */\nexport const openAppSpace = (slot = 'default'): Promise<SandboxMount> =>\n requestMountInternal('open', { slot });\n\n/**\n * Mount a filesystem by its **universal mount id** (UI_AS_APPS_SPEC §3.5) —\n * `scheme:locator`, e.g. `space:{spaceId}` or `github:owner/repo@ref`. Backend-blind:\n * the host resolves the scheme. A scheme with no resolver rejects with\n * {@link SpaceError} `unsupported-scheme`.\n */\nexport const mount = (mountId: string): Promise<SandboxMount> =>\n requestMountInternal('mount', { mount: mountId });\n\n/** Mount a specific space by id (e.g. one shared with you, or from a link). A thin\n * shim over {@link mount} with the `space:` scheme. */\nexport const mountSpace = (query: { spaceId: string }): Promise<SandboxMount> =>\n mount(`space:${query.spaceId}`);\n\n/**\n * Ask the user to grant a filesystem to this app — the §8.6 powerbox. The app\n * asks; the HOST shows the user their mounts and the access choice (which mount,\n * an optional subtree, read-only vs read-write); the USER picks or declines. The\n * app never sees the list — it resolves with the single granted mount, or rejects\n * with a {@link SpaceError} (`cancelled`) if declined. The granted scope is\n * enforced host-side: the mount is chroot'd / `ro`-limited accordingly.\n *\n * Backend-general (§3.5): the picker offers whatever mounts the user has (today,\n * their spaces). Returns the granted mount by its universal id.\n */\nexport const requestMount = (): Promise<SandboxMount> =>\n requestMountInternal('request', {});\n\n/** @deprecated renamed to {@link requestMount} (backend-general, §3.5). */\nexport const requestSpace = requestMount;\n\n/** Create a brand-new space, optionally binding it to this app (a slot). */\nexport const createSpace = (\n opts: { name?: string; slot?: string; bindToApp?: boolean } = {}\n): Promise<SandboxMount> => requestMountInternal('create', opts);\n\n/** List spaces you can access — all of them, or just those bound to this app. */\nexport const listSpaces = (opts: { app?: boolean } = {}): Promise<SpaceInfo[]> =>\n request<SpaceInfo[]>('list', opts);\n\n/** Release a mounted space (stops its listener on the host). */\nexport const unmountSpace = async (query: { spaceId: string }): Promise<void> => {\n await request('unmount', query);\n};\n\n// ---------------------------------------------------------------------------\n// Space management (the space-manager app) — UI_AS_APPS_SPEC §5.2. These are\n// ELEVATED: enumerating all the user's spaces is `spaces:user`; mutating\n// membership (share/unshare/setRole) and resolving handles is `spaces:admin`.\n// The host enforces the owner-lockout invariant (a space always keeps an owner,\n// T41) and rate-limits handle lookups (L1); the OAuth/identity token never\n// crosses to the app.\n// ---------------------------------------------------------------------------\n\nexport type Role = 'owner' | 'writer' | 'reader';\n\n/** A member of a space (for the share/manage UI). */\nexport interface Member {\n /** `user:{uid}` | `group:{gid}`. */\n principal: string;\n role: Role;\n login?: string;\n avatarUrl?: string;\n}\n\n/** A handle resolved to a principal (handle → who). */\nexport interface ResolvedUser {\n uid: string;\n login: string;\n avatarUrl?: string;\n}\n\n/** Enumerate ALL the user's spaces (not just this app's) — `spaces:user`. */\nexport const listAllSpaces = (): Promise<SpaceInfo[]> => request<SpaceInfo[]>('listAll', {});\n\n/** Read a space's members one-shot — `spaces:admin`. */\nexport const getSpaceMembers = (spaceId: string): Promise<Member[]> =>\n request<Member[]>('members', { spaceId });\n\n/** Invite a user (by provider handle) to a space at a role — `spaces:admin`. The\n * host resolves the handle, so the app never sees other users' uids except the\n * one it invited. */\nexport const shareSpace = async (spaceId: string, login: string, role: Role): Promise<void> => {\n await request('share', { spaceId, login, role });\n};\n\n/** Remove a member from a space — `spaces:admin`. Refused if it would orphan the\n * space (owner-lockout, T41). */\nexport const unshareSpace = async (spaceId: string, uid: string): Promise<void> => {\n await request('unshare', { spaceId, uid });\n};\n\n/** Change a member's role — `spaces:admin`. Refused if it would drop the sole\n * owner (owner-lockout, T41). */\nexport const setSpaceRole = async (spaceId: string, uid: string, role: Role): Promise<void> => {\n await request('setRole', { spaceId, uid, role });\n};\n\n/** Resolve a provider handle to a principal (for the invite flow) — `spaces:admin`,\n * rate-limited host-side. */\nexport const lookupUser = (login: string): Promise<ResolvedUser> =>\n request<ResolvedUser>('lookupUser', { login });\n\n/** One durable grant an app holds, for the §8.11 capability audit view. */\nexport interface GrantRecord {\n /** The app's provider-qualified identity (`provider__namespace__repository`). */\n appKey: string;\n spaceId: string;\n /** Universal mount id (§3.5). */\n mountId: string;\n subtree?: string;\n mode: 'ro' | 'rw';\n name?: string;\n}\n\n/** Enumerate every (app, mount) grant the user holds — the audit view\n * (§8.11). Elevated `spaces:admin`. */\nexport const listGrants = (): Promise<GrantRecord[]> => request<GrantRecord[]>('grants', {});\n\n/** Revoke one app's grant on a space — durable (the app can't re-mount) plus a\n * best-effort live teardown. Elevated `spaces:admin`. */\nexport const revokeGrant = async (appKey: string, spaceId: string): Promise<void> => {\n await request('revokeGrant', { appKey, spaceId });\n};\n"],"mappings":"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","names":["mount"]}
package/dist/mounts.d.cts CHANGED
@@ -130,5 +130,22 @@ declare const setSpaceRole: (spaceId: string, uid: string, role: Role) => Promis
130
130
  /** Resolve a provider handle to a principal (for the invite flow) — `spaces:admin`,
131
131
  * rate-limited host-side. */
132
132
  declare const lookupUser: (login: string) => Promise<ResolvedUser>;
133
+ /** One durable grant an app holds, for the §8.11 capability audit view. */
134
+ interface GrantRecord {
135
+ /** The app's provider-qualified identity (`provider__namespace__repository`). */
136
+ appKey: string;
137
+ spaceId: string;
138
+ /** Universal mount id (§3.5). */
139
+ mountId: string;
140
+ subtree?: string;
141
+ mode: 'ro' | 'rw';
142
+ name?: string;
143
+ }
144
+ /** Enumerate every (app, mount) grant the user holds — the audit view
145
+ * (§8.11). Elevated `spaces:admin`. */
146
+ declare const listGrants: () => Promise<GrantRecord[]>;
147
+ /** Revoke one app's grant on a space — durable (the app can't re-mount) plus a
148
+ * best-effort live teardown. Elevated `spaces:admin`. */
149
+ declare const revokeGrant: (appKey: string, spaceId: string) => Promise<void>;
133
150
 
134
- export { type Member, type MountQuery, type ResolvedUser, type Role, type SandboxMount, type SpaceError, type SpaceInfo, createSpace, findMount, getMounts, getSpaceMembers, listAllSpaces, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount };
151
+ export { type GrantRecord, type Member, type MountQuery, type ResolvedUser, type Role, type SandboxMount, type SpaceError, type SpaceInfo, createSpace, findMount, getMounts, getSpaceMembers, listAllSpaces, listGrants, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, revokeGrant, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount };
package/dist/mounts.d.ts CHANGED
@@ -130,5 +130,22 @@ declare const setSpaceRole: (spaceId: string, uid: string, role: Role) => Promis
130
130
  /** Resolve a provider handle to a principal (for the invite flow) — `spaces:admin`,
131
131
  * rate-limited host-side. */
132
132
  declare const lookupUser: (login: string) => Promise<ResolvedUser>;
133
+ /** One durable grant an app holds, for the §8.11 capability audit view. */
134
+ interface GrantRecord {
135
+ /** The app's provider-qualified identity (`provider__namespace__repository`). */
136
+ appKey: string;
137
+ spaceId: string;
138
+ /** Universal mount id (§3.5). */
139
+ mountId: string;
140
+ subtree?: string;
141
+ mode: 'ro' | 'rw';
142
+ name?: string;
143
+ }
144
+ /** Enumerate every (app, mount) grant the user holds — the audit view
145
+ * (§8.11). Elevated `spaces:admin`. */
146
+ declare const listGrants: () => Promise<GrantRecord[]>;
147
+ /** Revoke one app's grant on a space — durable (the app can't re-mount) plus a
148
+ * best-effort live teardown. Elevated `spaces:admin`. */
149
+ declare const revokeGrant: (appKey: string, spaceId: string) => Promise<void>;
133
150
 
134
- export { type Member, type MountQuery, type ResolvedUser, type Role, type SandboxMount, type SpaceError, type SpaceInfo, createSpace, findMount, getMounts, getSpaceMembers, listAllSpaces, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount };
151
+ export { type GrantRecord, type Member, type MountQuery, type ResolvedUser, type Role, type SandboxMount, type SpaceError, type SpaceInfo, createSpace, findMount, getMounts, getSpaceMembers, listAllSpaces, listGrants, listSpaces, lookupUser, mount, mountSpace, onMountsChange, openAppSpace, requestMount, requestSpace, revokeGrant, setSpaceRole, shareSpace, unmountSpace, unshareSpace, useMounts, waitForMount };
package/dist/mounts.js CHANGED
@@ -59,12 +59,17 @@ const setSpaceRole = async (spaceId, uid, role) => {
59
59
  await request("setRole", { spaceId, uid, role });
60
60
  };
61
61
  const lookupUser = (login) => request("lookupUser", { login });
62
+ const listGrants = () => request("grants", {});
63
+ const revokeGrant = async (appKey, spaceId) => {
64
+ await request("revokeGrant", { appKey, spaceId });
65
+ };
62
66
  export {
63
67
  createSpace,
64
68
  findMount,
65
69
  getMounts,
66
70
  getSpaceMembers,
67
71
  listAllSpaces,
72
+ listGrants,
68
73
  listSpaces,
69
74
  lookupUser,
70
75
  mount,
@@ -73,6 +78,7 @@ export {
73
78
  openAppSpace,
74
79
  requestMount,
75
80
  requestSpace,
81
+ revokeGrant,
76
82
  setSpaceRole,
77
83
  shareSpace,
78
84
  unmountSpace,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mounts.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { protocolRequest } from './sandboxUtils';\n\n/**\n * A filesystem mount available to the sandbox, mirrored from the host window.\n *\n * Mounts appear on demand — call {@link openAppSpace} / {@link mountSpace} to ask\n * the host to mount a Firestore-backed \"space\"; it appears at `/spaces/{id}`.\n * Read or subscribe to the set, then access the files through the `fs` module at\n * the mount's `path`.\n */\nexport interface SandboxMount {\n /** Absolute path where the mount is reachable (e.g. `/spaces/{id}`). */\n path: string;\n /** Backend kind, e.g. `'firestore'`. */\n type: string;\n /** Optional stable identifier (the spaceId, for spaces). */\n id?: string;\n}\n\ninterface MountService {\n getMounts(): SandboxMount[];\n onChange(listener: (mounts: SandboxMount[]) => void): { dispose(): void };\n}\n\n// `module.evaluation.module.bundler` is the sandbox bundler injected into the\n// evaluation context (same path the other SDK helpers reach for `messageBus`).\nconst mountService = (): MountService => {\n // @ts-ignore - injected by the sandbox runtime\n return module.evaluation.module.bundler.mounts;\n};\n\n/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. */\nexport type MountQuery = { type?: string; id?: string; path?: string };\n\nconst matches = (mount: SandboxMount, query: MountQuery): boolean =>\n (query.type === undefined || mount.type === query.type) &&\n (query.id === undefined || mount.id === query.id) &&\n (query.path === undefined || mount.path === query.path);\n\n/**\n * Returns the mounts currently available. Poll this whenever you need a one-off\n * read; use {@link onMountsChange} or {@link useMounts} to react to changes.\n */\nexport const getMounts = (): SandboxMount[] => mountService().getMounts();\n\n/** Returns the first mount matching `query`, or `undefined`. */\nexport const findMount = (query: MountQuery): SandboxMount | undefined =>\n getMounts().find((m) => matches(m, query));\n\n/**\n * Subscribe to mount changes. The listener is invoked immediately with the\n * current mounts, then again on every change. Returns an unsubscribe fn.\n */\nexport const onMountsChange = (listener: (mounts: SandboxMount[]) => void): (() => void) => {\n const disposable = mountService().onChange(listener);\n return () => disposable.dispose();\n};\n\n/**\n * Resolves once a mount matching `query` is present (immediately if it already\n * is). Handy for \"use it when it appears\" — e.g.\n * `await waitForMount({ type: 'firestore' })` before reading `/firestore`.\n */\nexport const waitForMount = (query: MountQuery): Promise<SandboxMount> =>\n new Promise((resolve) => {\n const unsubscribe = onMountsChange((mounts) => {\n const found = mounts.find((m) => matches(m, query));\n if (found) {\n // Defer unsubscribe so we don't dispose during the initial replay call.\n Promise.resolve().then(unsubscribe);\n resolve(found);\n }\n });\n });\n\n/** React hook returning the mounts currently available, re-rendering on change. */\nexport const useMounts = (): SandboxMount[] => {\n const [mounts, setMounts] = useState<SandboxMount[]>(getMounts);\n useEffect(() => onMountsChange(setMounts), []);\n return mounts;\n};\n\n// ---------------------------------------------------------------------------\n// Spaces — on-demand, shareable Firestore-backed filesystems.\n// The host owns all UX: if you aren't signed in, or the space doesn't exist or\n// isn't accessible, the parent window presents sign-in / create / request-access\n// and only then resolves these calls. See docs/specs/FILE_SHARING_SPEC.md.\n// ---------------------------------------------------------------------------\n\n/** Summary of a space, as returned by {@link listSpaces}. */\nexport interface SpaceInfo {\n spaceId: string;\n role?: 'owner' | 'writer' | 'reader';\n owner?: string;\n name?: string;\n}\n\n/** An error from a space operation, carrying a machine-readable `code`. */\nexport interface SpaceError extends Error {\n code:\n | 'auth-required'\n | 'cancelled'\n | 'forbidden'\n | 'not-found'\n | 'unsupported-scheme'\n | 'unknown';\n}\n\ntype SpaceResult =\n | { ok: true; data: unknown }\n | { ok: false; code: string; message: string };\n\n// Issue a spaces protocol request, unwrapping the host's {ok,data} envelope and\n// throwing a typed SpaceError on failure.\nconst request = async <T = unknown>(\n method: string,\n query: Record<string, unknown> = {},\n): Promise<T> => {\n const res = (await protocolRequest('spaces', method, [query])) as SpaceResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? 'space request failed') as SpaceError;\n err.code = (res?.code as SpaceError['code']) ?? 'unknown';\n throw err;\n }\n return res.data as T;\n};\n\n// Request a space mount, then wait until the host actually registers it. The\n// host announces the mount (`mount-add`) separately from the protocol reply, so\n// an immediate read could otherwise race the mount.\nconst requestMountInternal = async (\n method: string,\n query: Record<string, unknown>,\n): Promise<SandboxMount> => {\n const mount = await request<SandboxMount>(method, query);\n return waitForMount({ id: mount.id ?? mount.path });\n};\n\n/**\n * Open this app's workspace for the signed-in user (the zero-config path). The\n * `slot` names which workspace (default `'default'`); pass distinct slots for\n * multiple filesystems in one app. On a missing slot the host shows a\n * create-or-pick dialog. Rejects with a {@link SpaceError} (`.code`) on cancel.\n */\nexport const openAppSpace = (slot = 'default'): Promise<SandboxMount> =>\n requestMountInternal('open', { slot });\n\n/**\n * Mount a filesystem by its **universal mount id** (UI_AS_APPS_SPEC §3.5) —\n * `scheme:locator`, e.g. `space:{spaceId}` or `github:owner/repo@ref`. Backend-blind:\n * the host resolves the scheme. A scheme with no resolver rejects with\n * {@link SpaceError} `unsupported-scheme`.\n */\nexport const mount = (mountId: string): Promise<SandboxMount> =>\n requestMountInternal('mount', { mount: mountId });\n\n/** Mount a specific space by id (e.g. one shared with you, or from a link). A thin\n * shim over {@link mount} with the `space:` scheme. */\nexport const mountSpace = (query: { spaceId: string }): Promise<SandboxMount> =>\n mount(`space:${query.spaceId}`);\n\n/**\n * Ask the user to grant a filesystem to this app — the §8.6 powerbox. The app\n * asks; the HOST shows the user their mounts and the access choice (which mount,\n * an optional subtree, read-only vs read-write); the USER picks or declines. The\n * app never sees the list — it resolves with the single granted mount, or rejects\n * with a {@link SpaceError} (`cancelled`) if declined. The granted scope is\n * enforced host-side: the mount is chroot'd / `ro`-limited accordingly.\n *\n * Backend-general (§3.5): the picker offers whatever mounts the user has (today,\n * their spaces). Returns the granted mount by its universal id.\n */\nexport const requestMount = (): Promise<SandboxMount> =>\n requestMountInternal('request', {});\n\n/** @deprecated renamed to {@link requestMount} (backend-general, §3.5). */\nexport const requestSpace = requestMount;\n\n/** Create a brand-new space, optionally binding it to this app (a slot). */\nexport const createSpace = (\n opts: { name?: string; slot?: string; bindToApp?: boolean } = {}\n): Promise<SandboxMount> => requestMountInternal('create', opts);\n\n/** List spaces you can access — all of them, or just those bound to this app. */\nexport const listSpaces = (opts: { app?: boolean } = {}): Promise<SpaceInfo[]> =>\n request<SpaceInfo[]>('list', opts);\n\n/** Release a mounted space (stops its listener on the host). */\nexport const unmountSpace = async (query: { spaceId: string }): Promise<void> => {\n await request('unmount', query);\n};\n\n// ---------------------------------------------------------------------------\n// Space management (the space-manager app) — UI_AS_APPS_SPEC §5.2. These are\n// ELEVATED: enumerating all the user's spaces is `spaces:user`; mutating\n// membership (share/unshare/setRole) and resolving handles is `spaces:admin`.\n// The host enforces the owner-lockout invariant (a space always keeps an owner,\n// T41) and rate-limits handle lookups (L1); the OAuth/identity token never\n// crosses to the app.\n// ---------------------------------------------------------------------------\n\nexport type Role = 'owner' | 'writer' | 'reader';\n\n/** A member of a space (for the share/manage UI). */\nexport interface Member {\n /** `user:{uid}` | `group:{gid}`. */\n principal: string;\n role: Role;\n login?: string;\n avatarUrl?: string;\n}\n\n/** A handle resolved to a principal (handle → who). */\nexport interface ResolvedUser {\n uid: string;\n login: string;\n avatarUrl?: string;\n}\n\n/** Enumerate ALL the user's spaces (not just this app's) — `spaces:user`. */\nexport const listAllSpaces = (): Promise<SpaceInfo[]> => request<SpaceInfo[]>('listAll', {});\n\n/** Read a space's members one-shot — `spaces:admin`. */\nexport const getSpaceMembers = (spaceId: string): Promise<Member[]> =>\n request<Member[]>('members', { spaceId });\n\n/** Invite a user (by provider handle) to a space at a role — `spaces:admin`. The\n * host resolves the handle, so the app never sees other users' uids except the\n * one it invited. */\nexport const shareSpace = async (spaceId: string, login: string, role: Role): Promise<void> => {\n await request('share', { spaceId, login, role });\n};\n\n/** Remove a member from a space — `spaces:admin`. Refused if it would orphan the\n * space (owner-lockout, T41). */\nexport const unshareSpace = async (spaceId: string, uid: string): Promise<void> => {\n await request('unshare', { spaceId, uid });\n};\n\n/** Change a member's role — `spaces:admin`. Refused if it would drop the sole\n * owner (owner-lockout, T41). */\nexport const setSpaceRole = async (spaceId: string, uid: string, role: Role): Promise<void> => {\n await request('setRole', { spaceId, uid, role });\n};\n\n/** Resolve a provider handle to a principal (for the invite flow) — `spaces:admin`,\n * rate-limited host-side. */\nexport const lookupUser = (login: string): Promise<ResolvedUser> =>\n request<ResolvedUser>('lookupUser', { login });\n"],"mappings":"AAAA,SAAS,WAAW,gBAAgB;AACpC,SAAS,uBAAuB;AA0BhC,MAAM,eAAe,MAAoB;AAEvC,SAAO,OAAO,WAAW,OAAO,QAAQ;AAC1C;AAKA,MAAM,UAAU,CAACA,QAAqB,WACnC,MAAM,SAAS,UAAaA,OAAM,SAAS,MAAM,UACjD,MAAM,OAAO,UAAaA,OAAM,OAAO,MAAM,QAC7C,MAAM,SAAS,UAAaA,OAAM,SAAS,MAAM;AAM7C,MAAM,YAAY,MAAsB,aAAa,EAAE,UAAU;AAGjE,MAAM,YAAY,CAAC,UACxB,UAAU,EAAE,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAMpC,MAAM,iBAAiB,CAAC,aAA6D;AAC1F,QAAM,aAAa,aAAa,EAAE,SAAS,QAAQ;AACnD,SAAO,MAAM,WAAW,QAAQ;AAClC;AAOO,MAAM,eAAe,CAAC,UAC3B,IAAI,QAAQ,CAAC,YAAY;AACvB,QAAM,cAAc,eAAe,CAAC,WAAW;AAC7C,UAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAClD,QAAI,OAAO;AAET,cAAQ,QAAQ,EAAE,KAAK,WAAW;AAClC,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AACH,CAAC;AAGI,MAAM,YAAY,MAAsB;AAC7C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAyB,SAAS;AAC9D,YAAU,MAAM,eAAe,SAAS,GAAG,CAAC,CAAC;AAC7C,SAAO;AACT;AAkCA,MAAM,UAAU,OACd,QACA,QAAiC,CAAC,MACnB;AACf,QAAM,MAAO,MAAM,gBAAgB,UAAU,QAAQ,CAAC,KAAK,CAAC;AAC5D,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,sBAAsB;AAC5D,QAAI,OAAQ,KAAK,QAA+B;AAChD,UAAM;AAAA,EACR;AACA,SAAO,IAAI;AACb;AAKA,MAAM,uBAAuB,OAC3B,QACA,UAC0B;AAC1B,QAAMA,SAAQ,MAAM,QAAsB,QAAQ,KAAK;AACvD,SAAO,aAAa,EAAE,IAAIA,OAAM,MAAMA,OAAM,KAAK,CAAC;AACpD;AAQO,MAAM,eAAe,CAAC,OAAO,cAClC,qBAAqB,QAAQ,EAAE,KAAK,CAAC;AAQhC,MAAM,QAAQ,CAAC,YACpB,qBAAqB,SAAS,EAAE,OAAO,QAAQ,CAAC;AAI3C,MAAM,aAAa,CAAC,UACzB,MAAM,SAAS,MAAM,OAAO,EAAE;AAazB,MAAM,eAAe,MAC1B,qBAAqB,WAAW,CAAC,CAAC;AAG7B,MAAM,eAAe;AAGrB,MAAM,cAAc,CACzB,OAA8D,CAAC,MACrC,qBAAqB,UAAU,IAAI;AAGxD,MAAM,aAAa,CAAC,OAA0B,CAAC,MACpD,QAAqB,QAAQ,IAAI;AAG5B,MAAM,eAAe,OAAO,UAA8C;AAC/E,QAAM,QAAQ,WAAW,KAAK;AAChC;AA8BO,MAAM,gBAAgB,MAA4B,QAAqB,WAAW,CAAC,CAAC;AAGpF,MAAM,kBAAkB,CAAC,YAC9B,QAAkB,WAAW,EAAE,QAAQ,CAAC;AAKnC,MAAM,aAAa,OAAO,SAAiB,OAAe,SAA8B;AAC7F,QAAM,QAAQ,SAAS,EAAE,SAAS,OAAO,KAAK,CAAC;AACjD;AAIO,MAAM,eAAe,OAAO,SAAiB,QAA+B;AACjF,QAAM,QAAQ,WAAW,EAAE,SAAS,IAAI,CAAC;AAC3C;AAIO,MAAM,eAAe,OAAO,SAAiB,KAAa,SAA8B;AAC7F,QAAM,QAAQ,WAAW,EAAE,SAAS,KAAK,KAAK,CAAC;AACjD;AAIO,MAAM,aAAa,CAAC,UACzB,QAAsB,cAAc,EAAE,MAAM,CAAC;","names":["mount"]}
1
+ {"version":3,"sources":["../src/mounts.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { protocolRequest } from './sandboxUtils';\n\n/**\n * A filesystem mount available to the sandbox, mirrored from the host window.\n *\n * Mounts appear on demand — call {@link openAppSpace} / {@link mountSpace} to ask\n * the host to mount a Firestore-backed \"space\"; it appears at `/spaces/{id}`.\n * Read or subscribe to the set, then access the files through the `fs` module at\n * the mount's `path`.\n */\nexport interface SandboxMount {\n /** Absolute path where the mount is reachable (e.g. `/spaces/{id}`). */\n path: string;\n /** Backend kind, e.g. `'firestore'`. */\n type: string;\n /** Optional stable identifier (the spaceId, for spaces). */\n id?: string;\n}\n\ninterface MountService {\n getMounts(): SandboxMount[];\n onChange(listener: (mounts: SandboxMount[]) => void): { dispose(): void };\n}\n\n// `module.evaluation.module.bundler` is the sandbox bundler injected into the\n// evaluation context (same path the other SDK helpers reach for `messageBus`).\nconst mountService = (): MountService => {\n // @ts-ignore - injected by the sandbox runtime\n return module.evaluation.module.bundler.mounts;\n};\n\n/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. */\nexport type MountQuery = { type?: string; id?: string; path?: string };\n\nconst matches = (mount: SandboxMount, query: MountQuery): boolean =>\n (query.type === undefined || mount.type === query.type) &&\n (query.id === undefined || mount.id === query.id) &&\n (query.path === undefined || mount.path === query.path);\n\n/**\n * Returns the mounts currently available. Poll this whenever you need a one-off\n * read; use {@link onMountsChange} or {@link useMounts} to react to changes.\n */\nexport const getMounts = (): SandboxMount[] => mountService().getMounts();\n\n/** Returns the first mount matching `query`, or `undefined`. */\nexport const findMount = (query: MountQuery): SandboxMount | undefined =>\n getMounts().find((m) => matches(m, query));\n\n/**\n * Subscribe to mount changes. The listener is invoked immediately with the\n * current mounts, then again on every change. Returns an unsubscribe fn.\n */\nexport const onMountsChange = (listener: (mounts: SandboxMount[]) => void): (() => void) => {\n const disposable = mountService().onChange(listener);\n return () => disposable.dispose();\n};\n\n/**\n * Resolves once a mount matching `query` is present (immediately if it already\n * is). Handy for \"use it when it appears\" — e.g.\n * `await waitForMount({ type: 'firestore' })` before reading `/firestore`.\n */\nexport const waitForMount = (query: MountQuery): Promise<SandboxMount> =>\n new Promise((resolve) => {\n const unsubscribe = onMountsChange((mounts) => {\n const found = mounts.find((m) => matches(m, query));\n if (found) {\n // Defer unsubscribe so we don't dispose during the initial replay call.\n Promise.resolve().then(unsubscribe);\n resolve(found);\n }\n });\n });\n\n/** React hook returning the mounts currently available, re-rendering on change. */\nexport const useMounts = (): SandboxMount[] => {\n const [mounts, setMounts] = useState<SandboxMount[]>(getMounts);\n useEffect(() => onMountsChange(setMounts), []);\n return mounts;\n};\n\n// ---------------------------------------------------------------------------\n// Spaces — on-demand, shareable Firestore-backed filesystems.\n// The host owns all UX: if you aren't signed in, or the space doesn't exist or\n// isn't accessible, the parent window presents sign-in / create / request-access\n// and only then resolves these calls. See docs/specs/FILE_SHARING_SPEC.md.\n// ---------------------------------------------------------------------------\n\n/** Summary of a space, as returned by {@link listSpaces}. */\nexport interface SpaceInfo {\n spaceId: string;\n role?: 'owner' | 'writer' | 'reader';\n owner?: string;\n name?: string;\n}\n\n/** An error from a space operation, carrying a machine-readable `code`. */\nexport interface SpaceError extends Error {\n code:\n | 'auth-required'\n | 'cancelled'\n | 'forbidden'\n | 'not-found'\n | 'unsupported-scheme'\n | 'unknown';\n}\n\ntype SpaceResult =\n | { ok: true; data: unknown }\n | { ok: false; code: string; message: string };\n\n// Issue a spaces protocol request, unwrapping the host's {ok,data} envelope and\n// throwing a typed SpaceError on failure.\nconst request = async <T = unknown>(\n method: string,\n query: Record<string, unknown> = {},\n): Promise<T> => {\n const res = (await protocolRequest('spaces', method, [query])) as SpaceResult;\n if (!res || res.ok !== true) {\n const err = new Error(res?.message ?? 'space request failed') as SpaceError;\n err.code = (res?.code as SpaceError['code']) ?? 'unknown';\n throw err;\n }\n return res.data as T;\n};\n\n// Request a space mount, then wait until the host actually registers it. The\n// host announces the mount (`mount-add`) separately from the protocol reply, so\n// an immediate read could otherwise race the mount.\nconst requestMountInternal = async (\n method: string,\n query: Record<string, unknown>,\n): Promise<SandboxMount> => {\n const mount = await request<SandboxMount>(method, query);\n return waitForMount({ id: mount.id ?? mount.path });\n};\n\n/**\n * Open this app's workspace for the signed-in user (the zero-config path). The\n * `slot` names which workspace (default `'default'`); pass distinct slots for\n * multiple filesystems in one app. On a missing slot the host shows a\n * create-or-pick dialog. Rejects with a {@link SpaceError} (`.code`) on cancel.\n */\nexport const openAppSpace = (slot = 'default'): Promise<SandboxMount> =>\n requestMountInternal('open', { slot });\n\n/**\n * Mount a filesystem by its **universal mount id** (UI_AS_APPS_SPEC §3.5) —\n * `scheme:locator`, e.g. `space:{spaceId}` or `github:owner/repo@ref`. Backend-blind:\n * the host resolves the scheme. A scheme with no resolver rejects with\n * {@link SpaceError} `unsupported-scheme`.\n */\nexport const mount = (mountId: string): Promise<SandboxMount> =>\n requestMountInternal('mount', { mount: mountId });\n\n/** Mount a specific space by id (e.g. one shared with you, or from a link). A thin\n * shim over {@link mount} with the `space:` scheme. */\nexport const mountSpace = (query: { spaceId: string }): Promise<SandboxMount> =>\n mount(`space:${query.spaceId}`);\n\n/**\n * Ask the user to grant a filesystem to this app — the §8.6 powerbox. The app\n * asks; the HOST shows the user their mounts and the access choice (which mount,\n * an optional subtree, read-only vs read-write); the USER picks or declines. The\n * app never sees the list — it resolves with the single granted mount, or rejects\n * with a {@link SpaceError} (`cancelled`) if declined. The granted scope is\n * enforced host-side: the mount is chroot'd / `ro`-limited accordingly.\n *\n * Backend-general (§3.5): the picker offers whatever mounts the user has (today,\n * their spaces). Returns the granted mount by its universal id.\n */\nexport const requestMount = (): Promise<SandboxMount> =>\n requestMountInternal('request', {});\n\n/** @deprecated renamed to {@link requestMount} (backend-general, §3.5). */\nexport const requestSpace = requestMount;\n\n/** Create a brand-new space, optionally binding it to this app (a slot). */\nexport const createSpace = (\n opts: { name?: string; slot?: string; bindToApp?: boolean } = {}\n): Promise<SandboxMount> => requestMountInternal('create', opts);\n\n/** List spaces you can access — all of them, or just those bound to this app. */\nexport const listSpaces = (opts: { app?: boolean } = {}): Promise<SpaceInfo[]> =>\n request<SpaceInfo[]>('list', opts);\n\n/** Release a mounted space (stops its listener on the host). */\nexport const unmountSpace = async (query: { spaceId: string }): Promise<void> => {\n await request('unmount', query);\n};\n\n// ---------------------------------------------------------------------------\n// Space management (the space-manager app) — UI_AS_APPS_SPEC §5.2. These are\n// ELEVATED: enumerating all the user's spaces is `spaces:user`; mutating\n// membership (share/unshare/setRole) and resolving handles is `spaces:admin`.\n// The host enforces the owner-lockout invariant (a space always keeps an owner,\n// T41) and rate-limits handle lookups (L1); the OAuth/identity token never\n// crosses to the app.\n// ---------------------------------------------------------------------------\n\nexport type Role = 'owner' | 'writer' | 'reader';\n\n/** A member of a space (for the share/manage UI). */\nexport interface Member {\n /** `user:{uid}` | `group:{gid}`. */\n principal: string;\n role: Role;\n login?: string;\n avatarUrl?: string;\n}\n\n/** A handle resolved to a principal (handle → who). */\nexport interface ResolvedUser {\n uid: string;\n login: string;\n avatarUrl?: string;\n}\n\n/** Enumerate ALL the user's spaces (not just this app's) — `spaces:user`. */\nexport const listAllSpaces = (): Promise<SpaceInfo[]> => request<SpaceInfo[]>('listAll', {});\n\n/** Read a space's members one-shot — `spaces:admin`. */\nexport const getSpaceMembers = (spaceId: string): Promise<Member[]> =>\n request<Member[]>('members', { spaceId });\n\n/** Invite a user (by provider handle) to a space at a role — `spaces:admin`. The\n * host resolves the handle, so the app never sees other users' uids except the\n * one it invited. */\nexport const shareSpace = async (spaceId: string, login: string, role: Role): Promise<void> => {\n await request('share', { spaceId, login, role });\n};\n\n/** Remove a member from a space — `spaces:admin`. Refused if it would orphan the\n * space (owner-lockout, T41). */\nexport const unshareSpace = async (spaceId: string, uid: string): Promise<void> => {\n await request('unshare', { spaceId, uid });\n};\n\n/** Change a member's role — `spaces:admin`. Refused if it would drop the sole\n * owner (owner-lockout, T41). */\nexport const setSpaceRole = async (spaceId: string, uid: string, role: Role): Promise<void> => {\n await request('setRole', { spaceId, uid, role });\n};\n\n/** Resolve a provider handle to a principal (for the invite flow) — `spaces:admin`,\n * rate-limited host-side. */\nexport const lookupUser = (login: string): Promise<ResolvedUser> =>\n request<ResolvedUser>('lookupUser', { login });\n\n/** One durable grant an app holds, for the §8.11 capability audit view. */\nexport interface GrantRecord {\n /** The app's provider-qualified identity (`provider__namespace__repository`). */\n appKey: string;\n spaceId: string;\n /** Universal mount id (§3.5). */\n mountId: string;\n subtree?: string;\n mode: 'ro' | 'rw';\n name?: string;\n}\n\n/** Enumerate every (app, mount) grant the user holds — the audit view\n * (§8.11). Elevated `spaces:admin`. */\nexport const listGrants = (): Promise<GrantRecord[]> => request<GrantRecord[]>('grants', {});\n\n/** Revoke one app's grant on a space — durable (the app can't re-mount) plus a\n * best-effort live teardown. Elevated `spaces:admin`. */\nexport const revokeGrant = async (appKey: string, spaceId: string): Promise<void> => {\n await request('revokeGrant', { appKey, spaceId });\n};\n"],"mappings":"AAAA,SAAS,WAAW,gBAAgB;AACpC,SAAS,uBAAuB;AA0BhC,MAAM,eAAe,MAAoB;AAEvC,SAAO,OAAO,WAAW,OAAO,QAAQ;AAC1C;AAKA,MAAM,UAAU,CAACA,QAAqB,WACnC,MAAM,SAAS,UAAaA,OAAM,SAAS,MAAM,UACjD,MAAM,OAAO,UAAaA,OAAM,OAAO,MAAM,QAC7C,MAAM,SAAS,UAAaA,OAAM,SAAS,MAAM;AAM7C,MAAM,YAAY,MAAsB,aAAa,EAAE,UAAU;AAGjE,MAAM,YAAY,CAAC,UACxB,UAAU,EAAE,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAMpC,MAAM,iBAAiB,CAAC,aAA6D;AAC1F,QAAM,aAAa,aAAa,EAAE,SAAS,QAAQ;AACnD,SAAO,MAAM,WAAW,QAAQ;AAClC;AAOO,MAAM,eAAe,CAAC,UAC3B,IAAI,QAAQ,CAAC,YAAY;AACvB,QAAM,cAAc,eAAe,CAAC,WAAW;AAC7C,UAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAClD,QAAI,OAAO;AAET,cAAQ,QAAQ,EAAE,KAAK,WAAW;AAClC,cAAQ,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AACH,CAAC;AAGI,MAAM,YAAY,MAAsB;AAC7C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAyB,SAAS;AAC9D,YAAU,MAAM,eAAe,SAAS,GAAG,CAAC,CAAC;AAC7C,SAAO;AACT;AAkCA,MAAM,UAAU,OACd,QACA,QAAiC,CAAC,MACnB;AACf,QAAM,MAAO,MAAM,gBAAgB,UAAU,QAAQ,CAAC,KAAK,CAAC;AAC5D,MAAI,CAAC,OAAO,IAAI,OAAO,MAAM;AAC3B,UAAM,MAAM,IAAI,MAAM,KAAK,WAAW,sBAAsB;AAC5D,QAAI,OAAQ,KAAK,QAA+B;AAChD,UAAM;AAAA,EACR;AACA,SAAO,IAAI;AACb;AAKA,MAAM,uBAAuB,OAC3B,QACA,UAC0B;AAC1B,QAAMA,SAAQ,MAAM,QAAsB,QAAQ,KAAK;AACvD,SAAO,aAAa,EAAE,IAAIA,OAAM,MAAMA,OAAM,KAAK,CAAC;AACpD;AAQO,MAAM,eAAe,CAAC,OAAO,cAClC,qBAAqB,QAAQ,EAAE,KAAK,CAAC;AAQhC,MAAM,QAAQ,CAAC,YACpB,qBAAqB,SAAS,EAAE,OAAO,QAAQ,CAAC;AAI3C,MAAM,aAAa,CAAC,UACzB,MAAM,SAAS,MAAM,OAAO,EAAE;AAazB,MAAM,eAAe,MAC1B,qBAAqB,WAAW,CAAC,CAAC;AAG7B,MAAM,eAAe;AAGrB,MAAM,cAAc,CACzB,OAA8D,CAAC,MACrC,qBAAqB,UAAU,IAAI;AAGxD,MAAM,aAAa,CAAC,OAA0B,CAAC,MACpD,QAAqB,QAAQ,IAAI;AAG5B,MAAM,eAAe,OAAO,UAA8C;AAC/E,QAAM,QAAQ,WAAW,KAAK;AAChC;AA8BO,MAAM,gBAAgB,MAA4B,QAAqB,WAAW,CAAC,CAAC;AAGpF,MAAM,kBAAkB,CAAC,YAC9B,QAAkB,WAAW,EAAE,QAAQ,CAAC;AAKnC,MAAM,aAAa,OAAO,SAAiB,OAAe,SAA8B;AAC7F,QAAM,QAAQ,SAAS,EAAE,SAAS,OAAO,KAAK,CAAC;AACjD;AAIO,MAAM,eAAe,OAAO,SAAiB,QAA+B;AACjF,QAAM,QAAQ,WAAW,EAAE,SAAS,IAAI,CAAC;AAC3C;AAIO,MAAM,eAAe,OAAO,SAAiB,KAAa,SAA8B;AAC7F,QAAM,QAAQ,WAAW,EAAE,SAAS,KAAK,KAAK,CAAC;AACjD;AAIO,MAAM,aAAa,CAAC,UACzB,QAAsB,cAAc,EAAE,MAAM,CAAC;AAgBxC,MAAM,aAAa,MAA8B,QAAuB,UAAU,CAAC,CAAC;AAIpF,MAAM,cAAc,OAAO,QAAgB,YAAmC;AACnF,QAAM,QAAQ,eAAe,EAAE,QAAQ,QAAQ,CAAC;AAClD;","names":["mount"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immediately-run/sdk",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Runtime SDK for code executing inside an immediately.run sandbox.",
5
5
  "license": "MIT",
6
6
  "repository": "github:immediately-run/immediately-run-sdk",