@lotics/app-sdk 0.125.9 → 0.126.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/AGENTS.md +2 -2
- package/dist/{chunk-2KJSE73G.js → chunk-GACWCLEV.js} +14 -13
- package/dist/index.d.ts +0 -1
- package/dist/index.js +51 -16
- package/dist/open_external.d.ts +1 -1
- package/dist/router.d.ts +4 -0
- package/dist/router.js +11 -2
- package/dist/rpc.d.ts +4 -11
- package/dist/shared_types.d.ts +3 -26
- package/dist/viewer.d.ts +0 -5
- package/docs/data_fetching.md +4 -4
- package/docs/members_and_options.md +2 -96
- package/docs/mutations.md +1 -2
- package/docs/navigation_and_state.md +7 -0
- package/docs/queries.md +2 -2
- package/docs/runtime.md +9 -64
- package/docs/security.md +0 -4
- package/package.json +1 -1
- package/dist/open_app.d.ts +0 -24
package/AGENTS.md
CHANGED
|
@@ -20,11 +20,11 @@ This file is the index. The **exact type** of anything is its shipped declaratio
|
|
|
20
20
|
| [docs/workflows.md](./docs/workflows.md) | **The workflow-BODY reference** — the JS subset a body may use, opaque `fld_*`/`opt_*` keys, every step form, the accepted sugar, helpers, record-write surfaces, the traps and the verify loop. |
|
|
21
21
|
| [docs/recipes.md](./docs/recipes.md) | Task-shaped how-tos — returning a generated file, returning structured data, parameterized lookups, composable optional filters, cell decoding, testing an AI action without spending credits. |
|
|
22
22
|
| [docs/files.md](./docs/files.md) | Files end to end — `useFileUpload` and its `fidelity` and a photo's `place`, `renameFile` (a new file over the same bytes), `useAttachments`/`useAttachmentPiles`, `readFiles` and presigned URLs (a bearer credential — never logged or persisted), workflow-generated files, naming a zip's entries, the delivery bounds. |
|
|
23
|
-
| [docs/members_and_options.md](./docs/members_and_options.md) | People
|
|
23
|
+
| [docs/members_and_options.md](./docs/members_and_options.md) | People and select options — `useMembers`, `useFieldOptions`, `useViewer`, `useWorkspaceTimezone`/`useWorkspaceCurrency`, `useAppContext`, the workspace's zone at the root, a member's links to one record for a person with no seat (`useOutsideLinks`). |
|
|
24
24
|
| [docs/navigation_and_state.md](./docs/navigation_and_state.md) | `AppRouter` (embedded/standalone URL model, the screens and `drawers` it reports to the host), `useUrlState` + `urlParam` codecs, `useRecents`, `useFolderPick`. |
|
|
25
25
|
| [docs/ai.md](./docs/ai.md) | `useAgentRun` (structured vs free-text, streaming parts, the agent's ask-back), `askAi`, `useAiContext`, and what the member's own chat agent can do with the app while it is open. |
|
|
26
26
|
| [docs/security.md](./docs/security.md) | **Read before shipping** — the owner-principal model, `is_current_member` scoping, write attribution, group gates, public-app bounds, why a per-input bound is a tenancy floor rather than an authorization check. |
|
|
27
|
-
| [docs/runtime.md](./docs/runtime.md) | `mount()` and the errors it reports to the host (`reportAppError`), the two transports, the API address a standalone bundle reads out of its own page (`<meta name="lotics-api-base">`), `rpc()` and `installRpcTransport` (a page that is never an app's answers every op itself), the mock harness (`fixture` + `?__mock=1` — queries, workflows and agents, a mocked agent's run played line by line), `openExternal`/`
|
|
27
|
+
| [docs/runtime.md](./docs/runtime.md) | `mount()` and the errors it reports to the host (`reportAppError`), the two transports, the API address a standalone bundle reads out of its own page (`<meta name="lotics-api-base">`), `rpc()` and `installRpcTransport` (a page that is never an app's answers every op itself), the mock harness (`fixture` + `?__mock=1` — queries, workflows and agents, a mocked agent's run played line by line), `openExternal`/`downloadFile`, geofencing, the peer dependencies. |
|
|
28
28
|
|
|
29
29
|
## Non-negotiables (each detailed in its doc)
|
|
30
30
|
|
|
@@ -154,6 +154,17 @@ function paramsEqual(a, b) {
|
|
|
154
154
|
return true;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
// ../shared/src/openable_url.ts
|
|
158
|
+
var OPENABLE_PROTOCOLS = /* @__PURE__ */ new Set(["https:", "http:", "tel:", "mailto:"]);
|
|
159
|
+
function openableUrl(url) {
|
|
160
|
+
if (!URL.canParse(url)) return void 0;
|
|
161
|
+
const parsed = new URL(url);
|
|
162
|
+
return OPENABLE_PROTOCOLS.has(parsed.protocol) ? parsed : void 0;
|
|
163
|
+
}
|
|
164
|
+
function openTarget(address) {
|
|
165
|
+
return address.protocol === "http:" || address.protocol === "https:" ? "_blank" : "_self";
|
|
166
|
+
}
|
|
167
|
+
|
|
157
168
|
// ../shared/src/app_host/api_base_meta.ts
|
|
158
169
|
var API_BASE_META_NAME = "lotics-api-base";
|
|
159
170
|
|
|
@@ -1794,14 +1805,6 @@ function rpcStandalone(op, payload) {
|
|
|
1794
1805
|
return standalonePredictionMiss(payload);
|
|
1795
1806
|
case "openExternal":
|
|
1796
1807
|
return standaloneOpenExternal(payload);
|
|
1797
|
-
case "peekApp":
|
|
1798
|
-
return Promise.reject(
|
|
1799
|
-
new Error("peekApp needs the Lotics host: a standalone app has no sibling apps to open. Gate the control on isEmbedded().")
|
|
1800
|
-
);
|
|
1801
|
-
case "openApp":
|
|
1802
|
-
return Promise.reject(
|
|
1803
|
-
new Error("openApp needs the Lotics host: a standalone app has no sibling apps to open. Gate the control on isEmbedded().")
|
|
1804
|
-
);
|
|
1805
1808
|
case "askAi":
|
|
1806
1809
|
return Promise.reject(new Error("askAi is only available when the app runs inside Lotics"));
|
|
1807
1810
|
case "urlState.get":
|
|
@@ -1870,11 +1873,9 @@ async function standaloneMembers(p) {
|
|
|
1870
1873
|
}
|
|
1871
1874
|
function openValidatedUrl(url) {
|
|
1872
1875
|
if (typeof url !== "string") throw new Error("openExternal requires a url string");
|
|
1873
|
-
const
|
|
1874
|
-
if (
|
|
1875
|
-
|
|
1876
|
-
}
|
|
1877
|
-
window.open(parsed.href, "_blank", "noopener,noreferrer");
|
|
1876
|
+
const address = openableUrl(url);
|
|
1877
|
+
if (address === void 0) throw new Error(`openExternal: unsupported URL scheme "${url.split(":", 1)[0]}"`);
|
|
1878
|
+
window.open(address.href, openTarget(address), "noopener,noreferrer");
|
|
1878
1879
|
}
|
|
1879
1880
|
async function standaloneOpenExternal(p) {
|
|
1880
1881
|
openValidatedUrl(p.url);
|
package/dist/index.d.ts
CHANGED
|
@@ -25,7 +25,6 @@ export type { GeofenceZone, GeoCoords, GeofenceOutcome, GeofenceOptions } from "
|
|
|
25
25
|
export { rpc, hostSpec, isEmbedded, installRpcTransport } from "./rpc.js";
|
|
26
26
|
export type { RpcOp, RpcTransport, HostSpec, AiContextValue, AiContextRecordRef } from "./rpc.js";
|
|
27
27
|
export { openExternal } from "./open_external.js";
|
|
28
|
-
export { openApp, peekApp } from "./open_app.js";
|
|
29
28
|
export { askAi, type AskAiArgs } from "./ask_ai.js";
|
|
30
29
|
export { downloadFile } from "./download.js";
|
|
31
30
|
export { renameFile } from "./rename_file.js";
|
package/dist/index.js
CHANGED
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
subtractDecimal,
|
|
52
52
|
sumDecimal,
|
|
53
53
|
urlParam
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-GACWCLEV.js";
|
|
55
55
|
|
|
56
56
|
// src/mount.tsx
|
|
57
57
|
import { createRoot } from "react-dom/client";
|
|
@@ -8298,6 +8298,7 @@ var MEMBER_OF = "member_of";
|
|
|
8298
8298
|
var CURRENT_MEMBER_STANDS_IN_FOR = "current_member_stands_in_for";
|
|
8299
8299
|
var CURRENT_MEMBER_STANDS_IN_FOR_ANY_GROUP = "current_member_stands_in_for_any_group";
|
|
8300
8300
|
var CHANGED_OUTSIDE = "changed_outside";
|
|
8301
|
+
var OPTION = "option";
|
|
8301
8302
|
var INLINE_HELPERS = [
|
|
8302
8303
|
"formatCurrency",
|
|
8303
8304
|
"randomNumber",
|
|
@@ -8315,6 +8316,7 @@ var INLINE_HELPERS = [
|
|
|
8315
8316
|
"row_rule_bypassed"
|
|
8316
8317
|
];
|
|
8317
8318
|
var PARSED_ONLY_HELPERS = [CHANGED_OUTSIDE];
|
|
8319
|
+
var SAVE_RESOLVED_HELPERS = [OPTION];
|
|
8318
8320
|
var HELPERS = /* @__PURE__ */ new Set([
|
|
8319
8321
|
...Object.keys(expression_array_exports),
|
|
8320
8322
|
...Object.keys(expression_string_exports),
|
|
@@ -8324,7 +8326,8 @@ var HELPERS = /* @__PURE__ */ new Set([
|
|
|
8324
8326
|
...Object.keys(jsFunctions),
|
|
8325
8327
|
...Object.keys(getDateExpressionFunctions()),
|
|
8326
8328
|
...INLINE_HELPERS,
|
|
8327
|
-
...PARSED_ONLY_HELPERS
|
|
8329
|
+
...PARSED_ONLY_HELPERS,
|
|
8330
|
+
...SAVE_RESOLVED_HELPERS
|
|
8328
8331
|
]);
|
|
8329
8332
|
function isHelper(name) {
|
|
8330
8333
|
return HELPERS.has(name);
|
|
@@ -10203,10 +10206,8 @@ function useAppContext() {
|
|
|
10203
10206
|
insider: data !== void 0 && data.member_id !== null && data.group_ids !== void 0,
|
|
10204
10207
|
groupIds: data?.group_ids ?? null,
|
|
10205
10208
|
absences: data?.absences ?? null,
|
|
10206
|
-
openableApps: data?.openable_apps ?? null,
|
|
10207
10209
|
commentsEnabled: data?.comments_enabled ?? false,
|
|
10208
10210
|
recordingEnabled: data?.recording_enabled === true,
|
|
10209
|
-
peekAppEnabled: data?.peek_app_enabled === true,
|
|
10210
10211
|
hostNamesApp: data?.host_names_app === true,
|
|
10211
10212
|
timezone: data?.timezone,
|
|
10212
10213
|
currency: data?.default_currency,
|
|
@@ -12781,6 +12782,41 @@ function pickedFirst(a, b) {
|
|
|
12781
12782
|
return a.id < b.id ? 1 : a.id > b.id ? -1 : 0;
|
|
12782
12783
|
}
|
|
12783
12784
|
|
|
12785
|
+
// ../shared/src/query_column_types.ts
|
|
12786
|
+
var QUERY_COLUMN_TYPES = [
|
|
12787
|
+
"text",
|
|
12788
|
+
"number",
|
|
12789
|
+
"boolean",
|
|
12790
|
+
"date",
|
|
12791
|
+
"datetime",
|
|
12792
|
+
"select",
|
|
12793
|
+
"select_record_link",
|
|
12794
|
+
"select_member",
|
|
12795
|
+
"files",
|
|
12796
|
+
"text_list",
|
|
12797
|
+
"number_list",
|
|
12798
|
+
"boolean_list",
|
|
12799
|
+
"date_list",
|
|
12800
|
+
"datetime_list",
|
|
12801
|
+
"json"
|
|
12802
|
+
];
|
|
12803
|
+
var LIST_ELEMENT_COLUMN_TYPE = {
|
|
12804
|
+
text_list: "text",
|
|
12805
|
+
number_list: "number",
|
|
12806
|
+
boolean_list: "boolean",
|
|
12807
|
+
date_list: "date",
|
|
12808
|
+
datetime_list: "datetime"
|
|
12809
|
+
};
|
|
12810
|
+
var SCALAR_LIST_COLUMN_TYPES = QUERY_COLUMN_TYPES.filter(
|
|
12811
|
+
(type) => type in LIST_ELEMENT_COLUMN_TYPE
|
|
12812
|
+
);
|
|
12813
|
+
function listColumnTypeOf(element) {
|
|
12814
|
+
return SCALAR_LIST_COLUMN_TYPES.find((type) => LIST_ELEMENT_COLUMN_TYPE[type] === element);
|
|
12815
|
+
}
|
|
12816
|
+
function isScalarListColumnType(type) {
|
|
12817
|
+
return SCALAR_LIST_COLUMN_TYPES.some((one) => one === type);
|
|
12818
|
+
}
|
|
12819
|
+
|
|
12784
12820
|
// ../shared/src/field_column_type.ts
|
|
12785
12821
|
function fieldTypeToColumnType(field) {
|
|
12786
12822
|
switch (field.type) {
|
|
@@ -12817,6 +12853,10 @@ function fieldTypeToColumnType(field) {
|
|
|
12817
12853
|
}
|
|
12818
12854
|
}
|
|
12819
12855
|
}
|
|
12856
|
+
function fieldValueColumnType(field) {
|
|
12857
|
+
const type = fieldTypeToColumnType(field);
|
|
12858
|
+
return isScalarListColumnType(type) ? LIST_ELEMENT_COLUMN_TYPE[type] : type;
|
|
12859
|
+
}
|
|
12820
12860
|
function formulaOutputType(field) {
|
|
12821
12861
|
switch (field.formula.output_type) {
|
|
12822
12862
|
case "number":
|
|
@@ -12840,6 +12880,10 @@ function rollupColumnType(field) {
|
|
|
12840
12880
|
return field.aggregate_field_format === "datetime" || field.aggregate_field_format === "datetime_range" ? "datetime" : "date";
|
|
12841
12881
|
}
|
|
12842
12882
|
function lookupOutputType(field) {
|
|
12883
|
+
const element = lookupElementType(field);
|
|
12884
|
+
return field.lookup_field_several === true ? listColumnTypeOf(element) ?? element : element;
|
|
12885
|
+
}
|
|
12886
|
+
function lookupElementType(field) {
|
|
12843
12887
|
const t = field.lookup_field_type;
|
|
12844
12888
|
if (!t) return "json";
|
|
12845
12889
|
switch (t) {
|
|
@@ -12897,7 +12941,8 @@ function fieldValueInfo(field) {
|
|
|
12897
12941
|
type: field.lookup_field_type ?? "text",
|
|
12898
12942
|
...field.lookup_field_type === "number" ? { notation: fieldNotation(field) } : { format: field.lookup_field_format },
|
|
12899
12943
|
options: field.lookup_field_options,
|
|
12900
|
-
autonumber: field.lookup_field_autonumber
|
|
12944
|
+
autonumber: field.lookup_field_autonumber,
|
|
12945
|
+
several: field.lookup_field_several
|
|
12901
12946
|
};
|
|
12902
12947
|
// The cell stores the composed DISPLAY string ("KH-001"), never the counter.
|
|
12903
12948
|
case "autonumber":
|
|
@@ -12975,7 +13020,7 @@ function termsOf(cell, field) {
|
|
|
12975
13020
|
const value = field.type === "lookup" && Array.isArray(cell) ? cell[0] : cell;
|
|
12976
13021
|
if (fieldValueInfo(field).autonumber === true) return autonumberTerms(value);
|
|
12977
13022
|
const options = effectiveSelectOptions(field);
|
|
12978
|
-
return [options === null ? valueRank(value,
|
|
13023
|
+
return [options === null ? valueRank(value, fieldValueColumnType(field)) : optionRank(value, options)];
|
|
12979
13024
|
}
|
|
12980
13025
|
function rankText(rank) {
|
|
12981
13026
|
if (rank.by === "name") return folded(rank.value.name);
|
|
@@ -14643,14 +14688,6 @@ function openExternal(url) {
|
|
|
14643
14688
|
return rpc("openExternal", { url });
|
|
14644
14689
|
}
|
|
14645
14690
|
|
|
14646
|
-
// src/open_app.ts
|
|
14647
|
-
function openApp(appId, route = "/") {
|
|
14648
|
-
return rpc("openApp", { app_id: appId, route });
|
|
14649
|
-
}
|
|
14650
|
-
function peekApp(appId, route = "/") {
|
|
14651
|
-
return rpc("peekApp", { app_id: appId, route });
|
|
14652
|
-
}
|
|
14653
|
-
|
|
14654
14691
|
// src/ask_ai.ts
|
|
14655
14692
|
function askAi(args) {
|
|
14656
14693
|
const hasPayload = (args.prompt ?? "") !== "" || (args.file_ids?.length ?? 0) > 0 || (args.record_ids?.length ?? 0) > 0 || (args.context ?? "") !== "";
|
|
@@ -14821,9 +14858,7 @@ export {
|
|
|
14821
14858
|
isWithinZone,
|
|
14822
14859
|
mount,
|
|
14823
14860
|
newRecordId,
|
|
14824
|
-
openApp,
|
|
14825
14861
|
openExternal,
|
|
14826
|
-
peekApp,
|
|
14827
14862
|
queryAll,
|
|
14828
14863
|
readCreatedAt,
|
|
14829
14864
|
readFiles,
|
package/dist/open_external.d.ts
CHANGED
package/dist/router.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ export interface NotFoundWords {
|
|
|
4
4
|
message: (path: string) => string;
|
|
5
5
|
firstScreen: string;
|
|
6
6
|
}
|
|
7
|
+
export declare function NotFoundScreen({ home, words }: {
|
|
8
|
+
home: string;
|
|
9
|
+
words: NotFoundWords;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
7
11
|
export declare function AppRouter({ routes, notFound, drawers, }: {
|
|
8
12
|
routes: RouteObject[];
|
|
9
13
|
notFound?: NotFoundWords;
|
package/dist/router.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
isEmbedded,
|
|
3
3
|
postHostNotification,
|
|
4
4
|
setUrlParams
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GACWCLEV.js";
|
|
6
6
|
|
|
7
7
|
// src/router.tsx
|
|
8
8
|
import { useEffect } from "react";
|
|
@@ -22,10 +22,18 @@ function screenHref(loc) {
|
|
|
22
22
|
const qs = search.toString();
|
|
23
23
|
return loc.pathname + (qs ? `?${qs}` : "") + loc.hash;
|
|
24
24
|
}
|
|
25
|
+
function shapeStatedBy(route, pathname) {
|
|
26
|
+
const { handle } = route;
|
|
27
|
+
if (typeof handle !== "object" || handle === null || !("shape" in handle) || typeof handle.shape !== "function") return void 0;
|
|
28
|
+
const shape = Reflect.apply(handle.shape, handle, [pathname]);
|
|
29
|
+
return typeof shape === "string" ? shape : void 0;
|
|
30
|
+
}
|
|
25
31
|
function routePattern(matches, pathname) {
|
|
26
32
|
const concrete = pathname.split("/").filter((segment) => segment !== "");
|
|
27
33
|
let shape = [];
|
|
28
34
|
for (const { route, params } of matches) {
|
|
35
|
+
const stated = shapeStatedBy(route, pathname);
|
|
36
|
+
if (stated !== void 0) return stated;
|
|
29
37
|
const path = route.path ?? "";
|
|
30
38
|
if (path.startsWith("/")) shape = [];
|
|
31
39
|
for (const segment of path.split("/")) {
|
|
@@ -120,5 +128,6 @@ function AppRouter({
|
|
|
120
128
|
] });
|
|
121
129
|
}
|
|
122
130
|
export {
|
|
123
|
-
AppRouter
|
|
131
|
+
AppRouter,
|
|
132
|
+
NotFoundScreen
|
|
124
133
|
};
|
package/dist/rpc.d.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import type { AppAbsence } from "./shared_types.js";
|
|
2
|
-
import type {
|
|
3
|
-
import type { OpenableApp } from "./shared_types.js";
|
|
2
|
+
import type { AppSpec } from "./shared_types.js";
|
|
4
3
|
import type { AskUserChoiceOutput } from "./agent_stream.js";
|
|
5
4
|
import { type UrlParams, type UrlParamsPatch } from "./url_params.js";
|
|
6
5
|
/**
|
|
7
6
|
* The app's RPC bridge. Bridged (`?lotics_host=` present): ops go over
|
|
8
7
|
* postMessage and the host, holding the member's session, calls the API.
|
|
9
8
|
* Standalone: the public `/v1/apps/{id}/*` endpoints are called directly, with
|
|
10
|
-
* no credentials. The bridged wire must match `
|
|
9
|
+
* no credentials. The bridged wire must match `app_frame.tsx`:
|
|
11
10
|
* app → host: { id, op, payload }, the first also carrying `reportsDrawn: true` and `load` (`AppLoadTiming`) when
|
|
12
11
|
* the browser states any
|
|
13
12
|
* app → host: { type: "drawn" }, once, after the first answer when no request has been in flight for two frames:
|
|
14
13
|
* the app's first screen has its data
|
|
15
14
|
* host → app: { id, type: "result", data } | { id, type: "error", message }
|
|
16
15
|
*/
|
|
17
|
-
export type RpcOp = "query" | "export" | "field_options" | "workflow" | "agentRuns" | "agentRun.get" | "agentRun.cancel" | "upload" | "file.rename" | "members" | "context" | "spec" | "write_model" | "prediction_miss" | "openExternal" | "
|
|
16
|
+
export type RpcOp = "query" | "export" | "field_options" | "workflow" | "agentRuns" | "agentRun.get" | "agentRun.cancel" | "upload" | "file.rename" | "members" | "context" | "spec" | "write_model" | "prediction_miss" | "openExternal" | "askAi" | "urlState.get" | "urlState.set" | "folder.get" | "folder.set" | "comments.list" | "comments.create" | "comments.update" | "comments.delete" | "comments.counts" | "recording.start" | "recording.stop" | "outsideLink.list" | "outsideLink.create" | "outsideLink.revoke";
|
|
18
17
|
export interface AgentRunPayload {
|
|
19
18
|
alias: string;
|
|
20
19
|
session_id: string;
|
|
@@ -77,8 +76,6 @@ export interface AppContext {
|
|
|
77
76
|
/** True only from a host with `recording.*`, for a signed-in member, on an
|
|
78
77
|
* instance that transcribes; absent reads as false. */
|
|
79
78
|
recording_enabled?: boolean;
|
|
80
|
-
/** True only from a host that serves `peekApp`; absent reads as false. */
|
|
81
|
-
peek_app_enabled?: boolean;
|
|
82
79
|
/** True only from a host whose own chrome names the app on screen; absent reads as false. */
|
|
83
80
|
host_names_app?: boolean;
|
|
84
81
|
/** This app's recordings the host still tracks, by alias. */
|
|
@@ -86,10 +83,6 @@ export interface AppContext {
|
|
|
86
83
|
/** Who in the organization is away, or will be, and who stands in — absent from an older host and for a visitor from
|
|
87
84
|
* outside the organization. */
|
|
88
85
|
absences?: AppAbsence[];
|
|
89
|
-
/** The apps of the workspace the viewer can open, each by its id and its name, the table its register lists
|
|
90
|
-
* (`table_id`) and each of its logs (`logs`) where the host says — absent from an older host, for a visitor and until
|
|
91
|
-
* the host has listed them. */
|
|
92
|
-
openable_apps?: OpenableApp[];
|
|
93
86
|
}
|
|
94
87
|
/** Whether a Lotics host embeds the app, rather than it standing alone on its own origin. */
|
|
95
88
|
export declare function isEmbedded(): boolean;
|
|
@@ -102,7 +95,7 @@ export type RpcTransport = (op: RpcOp, payload: unknown) => Promise<unknown>;
|
|
|
102
95
|
* last install wins, and a page installs its own before it mounts. */
|
|
103
96
|
export declare function installRpcTransport(transport: RpcTransport): void;
|
|
104
97
|
/** What the host answers `spec`: the app's compiled spec itself, never the route's wrapper around it. */
|
|
105
|
-
export type HostSpec =
|
|
98
|
+
export type HostSpec = AppSpec;
|
|
106
99
|
/** The app's spec, as the host hands it over the bridge. */
|
|
107
100
|
export declare function hostSpec(): Promise<HostSpec>;
|
|
108
101
|
export declare function rpc<T = unknown>(op: RpcOp, payload: unknown): Promise<T>;
|