@lotics/app-sdk 0.123.11 → 0.124.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -3
- package/dist/{chunk-COWN73CO.js → chunk-BWMAO5IY.js} +33 -3
- package/dist/comments.d.ts +1 -1
- package/dist/index.d.ts +5 -6
- package/dist/index.js +2488 -1782
- package/dist/outside_link.d.ts +27 -0
- package/dist/router.js +1 -1
- package/dist/row.d.ts +9 -2
- package/dist/rpc.d.ts +17 -3
- package/dist/shared_types.d.ts +5 -4
- package/dist/viewer.d.ts +2 -1
- package/docs/ai.md +3 -29
- package/docs/data_fetching.md +1 -0
- package/docs/files.md +1 -1
- package/docs/members_and_options.md +12 -62
- package/docs/mutations.md +4 -3
- package/docs/recipes.md +4 -4
- package/docs/runtime.md +5 -1
- package/docs/security.md +0 -3
- package/docs/workflows.md +19 -46
- package/package.json +1 -1
- package/dist/activity.d.ts +0 -40
package/AGENTS.md
CHANGED
|
@@ -14,17 +14,17 @@ This file is the index. The **exact type** of anything is its shipped declaratio
|
|
|
14
14
|
|
|
15
15
|
| Doc | Read it for |
|
|
16
16
|
|---|---|
|
|
17
|
-
| [docs/data_fetching.md](./docs/data_fetching.md) | The reads: `useQuery(alias, params, opts)` — its rows (`limit`), numbered pages (`page`), a keyset feed (`more`), its `total` or the total alone, with `total: { by }` a count per value of one column and `total: { where }` a count per named filter, from one scan — `useQueries` for reads known only at render, `queryAll` outside React, `exportQuery` for a file of them the server makes; every hook answers one `QueryState`. The ROW type (`RowOf` — the alias's projected columns and nothing else), runtime `sort`/`filter` keys, cell readers (`row.*`, `readSelect`, `readMembers`, `readLinks`, `readFiles`, `readLocked`, `readCreatedAt`/`readUpdatedAt`), the SDK's own cache — **arrival revalidates** — **realtime push** and `answeredAt` (the server answering again what a screen drew), a write drawn on every read from the press, a count as its own full scan, and the search-as-you-type and record-picker patterns. |
|
|
17
|
+
| [docs/data_fetching.md](./docs/data_fetching.md) | The reads: `useQuery(alias, params, opts)` — its rows (`limit`), numbered pages (`page`), a keyset feed (`more`), its `total` or the total alone, with `total: { by }` a count per value of one column and `total: { where }` a count per named filter, from one scan — `useQueries` for reads known only at render, `queryAll` outside React, `exportQuery` for a file of them the server makes; every hook answers one `QueryState`. The ROW type (`RowOf` — the alias's projected columns and nothing else), runtime `sort`/`filter` keys, cell readers (`row.*`, `readSelect`, `readMembers`, `readLinks`, `readFiles`, `readLocked`/`readLockedBy`, `readCreatedAt`/`readUpdatedAt`), the SDK's own cache — **arrival revalidates** — **realtime push** and `answeredAt` (the server answering again what a screen drew), a write drawn on every read from the press, a count as its own full scan, and the search-as-you-type and record-picker patterns. |
|
|
18
18
|
| [docs/queries.md](./docs/queries.md) | **The query engine reference** — AST node kinds, per-field-type operators, filters/params/pruning, free-text search, combining tables, shaping (aggregates, date buckets, windows), runtime refinement bounds, limits and the efficiency playbook. |
|
|
19
19
|
| [docs/mutations.md](./docs/mutations.md) | `useWorkflow` (the ONLY write path; `useWorkflows` for writes that are data), the `WorkflowResult` resolve-never-throw contract (`field_errors`), typed inputs, every write drawn on every read from the press — predicted from the workflow's own steps, taken back on a refusal, `pending` meanwhile — the re-read a successful write triggers over the tables its body names, diff-before-update, locked records, `useNewRecord`, read-after-write ordering (`writesSettled()`), `useRecording`, `useRecordings` over several aliases. |
|
|
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, select options and comments — `useMembers`, `useFieldOptions`, `useViewer`, `useWorkspaceTimezone`/`useWorkspaceCurrency`, `useAppContext`, the workspace's zone at the root, `useComments`, a
|
|
23
|
+
| [docs/members_and_options.md](./docs/members_and_options.md) | People, select options and comments — `useMembers`, `useFieldOptions`, `useViewer`, `useWorkspaceTimezone`/`useWorkspaceCurrency`, `useAppContext`, the workspace's zone at the root, `useComments`, 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()
|
|
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`/`openApp`/`peekApp`/`downloadFile`, geofencing, the peer dependencies. |
|
|
28
28
|
|
|
29
29
|
## Non-negotiables (each detailed in its doc)
|
|
30
30
|
|
|
@@ -249,6 +249,18 @@ function isFieldKey(value) {
|
|
|
249
249
|
return value.startsWith(FIELD_KEY_PREFIX);
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
// ../shared/src/compare_bounds.ts
|
|
253
|
+
var COMPARE_KEYS = ["gt", "gte", "lt", "lte"];
|
|
254
|
+
function isRecordBound(bound) {
|
|
255
|
+
return typeof bound === "object" && "record" in bound;
|
|
256
|
+
}
|
|
257
|
+
function boundsOf(compared) {
|
|
258
|
+
return COMPARE_KEYS.flatMap((key) => {
|
|
259
|
+
const bound = compared[key];
|
|
260
|
+
return bound === void 0 ? [] : [{ key, bound }];
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
252
264
|
// ../shared/src/schemas/app_spec_rules.ts
|
|
253
265
|
var bandKey = (band) => `${band.min ?? ""}..${band.max ?? ""}`;
|
|
254
266
|
function bandOf(tiers, figure) {
|
|
@@ -256,6 +268,8 @@ function bandOf(tiers, figure) {
|
|
|
256
268
|
const at = above < 0 ? tiers.length : above;
|
|
257
269
|
return { min: tiers[at - 1] ?? null, max: tiers[at] ?? null };
|
|
258
270
|
}
|
|
271
|
+
var AGENT_SCAN_READS = ["text", "iso6346"];
|
|
272
|
+
var SCAN_READS = [...AGENT_SCAN_READS, "code"];
|
|
259
273
|
|
|
260
274
|
// ../../node_modules/big.js/big.mjs
|
|
261
275
|
var DP = 20;
|
|
@@ -1315,7 +1329,15 @@ function getHostOrigin() {
|
|
|
1315
1329
|
function isEmbedded() {
|
|
1316
1330
|
return Boolean(getHostOrigin());
|
|
1317
1331
|
}
|
|
1332
|
+
var installedTransport = null;
|
|
1333
|
+
function installRpcTransport(transport) {
|
|
1334
|
+
installedTransport = transport;
|
|
1335
|
+
}
|
|
1336
|
+
function hostSpec() {
|
|
1337
|
+
return rpc("spec", {});
|
|
1338
|
+
}
|
|
1318
1339
|
function rpc(op, payload) {
|
|
1340
|
+
if (installedTransport !== null) return installedTransport(op, payload);
|
|
1319
1341
|
const hostOrigin = getHostOrigin();
|
|
1320
1342
|
return hostOrigin ? rpcBridged(op, payload, hostOrigin) : rpcStandalone(op, payload);
|
|
1321
1343
|
}
|
|
@@ -1750,6 +1772,8 @@ function rpcStandalone(op, payload) {
|
|
|
1750
1772
|
return standaloneMembers(payload);
|
|
1751
1773
|
case "context":
|
|
1752
1774
|
return standaloneContext();
|
|
1775
|
+
case "spec":
|
|
1776
|
+
return Promise.reject(new Error("A standalone app carries its spec in its document; only the Lotics host hands one over the bridge."));
|
|
1753
1777
|
case "write_model":
|
|
1754
1778
|
return standaloneWriteModel();
|
|
1755
1779
|
case "prediction_miss":
|
|
@@ -1780,14 +1804,15 @@ function rpcStandalone(op, payload) {
|
|
|
1780
1804
|
case "comments.delete":
|
|
1781
1805
|
case "comments.counts":
|
|
1782
1806
|
return rejectCommentsStandalone();
|
|
1783
|
-
case "activity.list":
|
|
1784
|
-
case "activity.undo":
|
|
1785
|
-
return Promise.reject(new Error("A record's activity is available only in embedded apps \u2014 a signed-in member is required."));
|
|
1786
1807
|
case "recording.start":
|
|
1787
1808
|
case "recording.stop":
|
|
1788
1809
|
return Promise.reject(
|
|
1789
1810
|
new Error("Recording needs the Lotics host and a signed-in member. Gate the control on useRecording's `available`.")
|
|
1790
1811
|
);
|
|
1812
|
+
case "outsideLink.list":
|
|
1813
|
+
case "outsideLink.create":
|
|
1814
|
+
case "outsideLink.revoke":
|
|
1815
|
+
return Promise.reject(new Error("A link to a record is made and withdrawn by a signed-in member in the Lotics host. Gate the control on useOutsideLinks' `available`."));
|
|
1791
1816
|
}
|
|
1792
1817
|
}
|
|
1793
1818
|
function folderTable(payload) {
|
|
@@ -2000,6 +2025,9 @@ export {
|
|
|
2000
2025
|
searchWords,
|
|
2001
2026
|
customAlphabet,
|
|
2002
2027
|
isFieldKey,
|
|
2028
|
+
COMPARE_KEYS,
|
|
2029
|
+
isRecordBound,
|
|
2030
|
+
boundsOf,
|
|
2003
2031
|
bandKey,
|
|
2004
2032
|
bandOf,
|
|
2005
2033
|
addDecimal,
|
|
@@ -2030,6 +2058,8 @@ export {
|
|
|
2030
2058
|
applyPatch,
|
|
2031
2059
|
paramsEqual,
|
|
2032
2060
|
isEmbedded,
|
|
2061
|
+
installRpcTransport,
|
|
2062
|
+
hostSpec,
|
|
2033
2063
|
rpc,
|
|
2034
2064
|
getUrlParams,
|
|
2035
2065
|
setUrlParams,
|
package/dist/comments.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export interface CommentsState {
|
|
|
51
51
|
export interface UseCommentsArgs {
|
|
52
52
|
record_id: string;
|
|
53
53
|
}
|
|
54
|
-
/** What every read a comment changes is read under — the counts
|
|
54
|
+
/** What every read a comment changes is read under — the counts — so a comment written or deleted asks each again. */
|
|
55
55
|
export declare const COMMENT_WRITES = "comment-counts";
|
|
56
56
|
/**
|
|
57
57
|
* `record_id` must be a real id — an empty string still fetches. Gate the
|
package/dist/index.d.ts
CHANGED
|
@@ -11,18 +11,17 @@ export type { ExportedFile } from "./shared_types.js";
|
|
|
11
11
|
export type { AttachedFile, AttachmentPiles, AttachmentPilesOptions, AttachmentsOptions, AttachmentsState } from "./attachments.js";
|
|
12
12
|
export { useComments, useCommentCounts } from "./comments.js";
|
|
13
13
|
export type { AppComment, AppCommentAuthor, AppCommentFile, CommentsState, UseCommentsArgs, CommentCountsState, UseCommentCountsArgs, } from "./comments.js";
|
|
14
|
-
export { undoRecordChange, useRecordActivity } from "./activity.js";
|
|
15
|
-
export type { RecordActivityOptions, RecordActivityState } from "./activity.js";
|
|
16
|
-
export type { ActivityActor, ActivityActorKind, ActivityChange, ActivityComment, ActivityEntry, ActivityUndoResult, ActivityValue, RecordActivityPage, UndoKeptReason, } from "./shared_types.js";
|
|
17
14
|
export { useAppContext, useViewer, useWorkspaceCurrency, useWorkspaceTimezone } from "./viewer.js";
|
|
18
15
|
export type { AppAbsence } from "./shared_types.js";
|
|
16
|
+
export { useOutsideLinks } from "./outside_link.js";
|
|
17
|
+
export type { OutsideLinksState } from "./outside_link.js";
|
|
19
18
|
export { useRecording, useRecordings } from "./recording.js";
|
|
20
19
|
export type { UseRecording, UseRecordings } from "./recording.js";
|
|
21
20
|
export type { RecordingState, RecordingInputs } from "./recording_state.js";
|
|
22
21
|
export { requestGeofencedLocation, isWithinZone } from "./geolocation.js";
|
|
23
22
|
export type { GeofenceZone, GeoCoords, GeofenceOutcome, GeofenceOptions } from "./geolocation.js";
|
|
24
|
-
export { rpc, isEmbedded } from "./rpc.js";
|
|
25
|
-
export type { RpcOp, AiContextValue, AiContextRecordRef } from "./rpc.js";
|
|
23
|
+
export { rpc, hostSpec, isEmbedded, installRpcTransport } from "./rpc.js";
|
|
24
|
+
export type { RpcOp, RpcTransport, HostSpec, AiContextValue, AiContextRecordRef } from "./rpc.js";
|
|
26
25
|
export { openExternal } from "./open_external.js";
|
|
27
26
|
export { openApp, peekApp } from "./open_app.js";
|
|
28
27
|
export { askAi, type AskAiArgs } from "./ask_ai.js";
|
|
@@ -35,7 +34,7 @@ export type { ResolvedOption } from "./select.js";
|
|
|
35
34
|
export type { AppFixture, MockExport, MockQuery, MockQueryCall, MockWorkflow } from "./mock.js";
|
|
36
35
|
export type { MockAgent, MockAgentRun } from "./mock_agent_run.js";
|
|
37
36
|
export type { AppWorkflows, AppWorkflowResults, AppQueries, AppQueryColumns, AppAgents, AppAgentResults } from "./types.js";
|
|
38
|
-
export { row, readLinks, readFiles, readLocked, readCreatedAt, readUpdatedAt, PENDING } from "./row.js";
|
|
37
|
+
export { row, readLinks, readFiles, readLocked, readLockedBy, readCreatedAt, readUpdatedAt, PENDING } from "./row.js";
|
|
39
38
|
export type { ResolvedLink, AppFile, PhotoPlace } from "./row.js";
|
|
40
39
|
export { useNewRecord, newRecordId } from "./new_record.js";
|
|
41
40
|
export type { NewRecordApi } from "./new_record.js";
|