@lotics/app-sdk 0.5.0 → 0.6.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/dist/src/hooks.d.ts +33 -0
- package/dist/src/hooks.js +38 -4
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +1 -1
- package/dist/src/rpc.d.ts +1 -1
- package/package.json +1 -1
package/dist/src/hooks.d.ts
CHANGED
|
@@ -56,4 +56,37 @@ type UseQueryParams<K extends keyof AppQueries & string> = AppQueries[K] extends
|
|
|
56
56
|
*/
|
|
57
57
|
export declare function useQuery<K extends keyof AppQueries & string>(alias: K, ...rest: UseQueryParams<K>): QueryState<Record<string, unknown>>;
|
|
58
58
|
export declare function useQuery(alias: string, params?: Record<string, unknown>): QueryState<Record<string, unknown>>;
|
|
59
|
+
/** A file the host has stored and resolved serving URLs for. */
|
|
60
|
+
export interface UploadedFile {
|
|
61
|
+
id: string;
|
|
62
|
+
filename: string;
|
|
63
|
+
mime_type: string;
|
|
64
|
+
url?: string;
|
|
65
|
+
thumbnail_url?: string;
|
|
66
|
+
}
|
|
67
|
+
interface FileUploadState {
|
|
68
|
+
/**
|
|
69
|
+
* Upload one file. Resolves to the stored file; pass `UploadedFile.id` into
|
|
70
|
+
* a `useWorkflow` call to attach it to a record. Rejects on failure — the
|
|
71
|
+
* file is never partially stored.
|
|
72
|
+
*/
|
|
73
|
+
upload: (file: File) => Promise<UploadedFile>;
|
|
74
|
+
/** True while any upload from this hook is in flight. */
|
|
75
|
+
uploading: boolean;
|
|
76
|
+
/** Message of the most recent failed upload, cleared when a new one starts. */
|
|
77
|
+
error: string | null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Upload files from an app. The bytes are stored via a presigned
|
|
81
|
+
* direct-to-storage upload the host mediates; the API server never proxies
|
|
82
|
+
* them. Works the same in a public (anonymous) app and a member-facing one.
|
|
83
|
+
*
|
|
84
|
+
* ```tsx
|
|
85
|
+
* const { upload, uploading } = useFileUpload();
|
|
86
|
+
* const submit = useWorkflow("submitApplication");
|
|
87
|
+
* const cccd = await upload(file);
|
|
88
|
+
* await submit({ ...fields, cccd_file_id: cccd.id });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare function useFileUpload(): FileUploadState;
|
|
59
92
|
export {};
|
package/dist/src/hooks.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Typed React hooks for Lotics app data access.
|
|
3
3
|
*
|
|
4
|
-
* The SDK surface is
|
|
5
|
-
* mutation
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The SDK surface is three hooks: `useQuery` for reads, `useWorkflow` for
|
|
5
|
+
* every mutation, and `useFileUpload` for attaching files. App code never
|
|
6
|
+
* writes records directly — all writes flow through declared workflows, which
|
|
7
|
+
* gives the app owner a typed, audited chokepoint and means a publicly-shared
|
|
8
|
+
* app exposes no anonymous direct-write path. An uploaded file is inert until
|
|
9
|
+
* a workflow attaches it, so file upload keeps that same property.
|
|
8
10
|
*
|
|
9
11
|
* Every hook is a thin wrapper over the postMessage RPC bridge — the parent
|
|
10
12
|
* does the actual API calls, results stream back through `rpc()`. Hooks manage
|
|
@@ -53,3 +55,35 @@ export function useQuery(alias, params) {
|
|
|
53
55
|
}, []);
|
|
54
56
|
return { ...state, refetch };
|
|
55
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Upload files from an app. The bytes are stored via a presigned
|
|
60
|
+
* direct-to-storage upload the host mediates; the API server never proxies
|
|
61
|
+
* them. Works the same in a public (anonymous) app and a member-facing one.
|
|
62
|
+
*
|
|
63
|
+
* ```tsx
|
|
64
|
+
* const { upload, uploading } = useFileUpload();
|
|
65
|
+
* const submit = useWorkflow("submitApplication");
|
|
66
|
+
* const cccd = await upload(file);
|
|
67
|
+
* await submit({ ...fields, cccd_file_id: cccd.id });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function useFileUpload() {
|
|
71
|
+
const [inFlight, setInFlight] = useState(0);
|
|
72
|
+
const [error, setError] = useState(null);
|
|
73
|
+
const upload = useCallback(async (file) => {
|
|
74
|
+
setInFlight((n) => n + 1);
|
|
75
|
+
setError(null);
|
|
76
|
+
try {
|
|
77
|
+
return await rpc("upload", { file });
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
const message = err instanceof Error ? err.message : "Upload failed";
|
|
81
|
+
setError(message);
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
setInFlight((n) => n - 1);
|
|
86
|
+
}
|
|
87
|
+
}, []);
|
|
88
|
+
return { upload, uploading: inFlight > 0, error };
|
|
89
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* depending on packages/ui's React Native Web setup.
|
|
11
11
|
*/
|
|
12
12
|
export { mount } from "./mount.js";
|
|
13
|
-
export { useWorkflow, useQuery } from "./hooks.js";
|
|
13
|
+
export { useWorkflow, useQuery, useFileUpload } from "./hooks.js";
|
|
14
|
+
export type { UploadedFile } from "./hooks.js";
|
|
14
15
|
export { rpc } from "./rpc.js";
|
|
15
16
|
export type { RpcOp } from "./rpc.js";
|
|
16
17
|
export type { AppWorkflows, AppQueries } from "./types.js";
|
package/dist/src/index.js
CHANGED
package/dist/src/rpc.d.ts
CHANGED
|
@@ -13,5 +13,5 @@
|
|
|
13
13
|
* Bumping protocol version requires a coordinated change in the parent.
|
|
14
14
|
* Add new ops alongside existing ones; never repurpose them.
|
|
15
15
|
*/
|
|
16
|
-
export type RpcOp = "query" | "workflow";
|
|
16
|
+
export type RpcOp = "query" | "workflow" | "upload";
|
|
17
17
|
export declare function rpc<T = unknown>(op: RpcOp, payload: unknown): Promise<T>;
|