@noya-app/noya-api-client-react 0.1.35 → 0.1.37
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/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +23 -0
- package/dist/index.d.mts +150 -151
- package/dist/index.d.ts +150 -151
- package/dist/index.js +11071 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11114 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
- package/src/index.ts +1 -0
- package/src/react/context.ts +10 -7
- package/src/react/hooks.ts +24 -52
- package/src/react/tableHooks.ts +217 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noya-app/noya-api-client-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.37",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@legendapp/state": "^2.1.1",
|
|
13
|
-
"@noya-app/noya-api": "0.1.
|
|
14
|
-
"@noya-app/noya-utils": "0.1.
|
|
15
|
-
"@noya-app/observable": "0.1.
|
|
16
|
-
"@noya-app/observable-
|
|
13
|
+
"@noya-app/noya-api": "0.1.37",
|
|
14
|
+
"@noya-app/noya-utils": "0.1.7",
|
|
15
|
+
"@noya-app/observable": "0.1.12",
|
|
16
|
+
"@noya-app/observable-store": "0.1.1",
|
|
17
|
+
"@noya-app/observable-react": "0.1.22"
|
|
17
18
|
},
|
|
18
19
|
"peerDependencies": {
|
|
19
20
|
"react": "*",
|
package/src/index.ts
CHANGED
package/src/react/context.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { NoyaAPI } from "@noya-app/noya-api";
|
|
2
4
|
import { createContext, useContext, useMemo } from "react";
|
|
3
5
|
|
|
@@ -31,11 +33,12 @@ export function useOptionalNoyaClient(): NoyaAPIContextValue | undefined {
|
|
|
31
33
|
export function useNoyaClientOrFallback(): NoyaAPIContextValue {
|
|
32
34
|
const value = useContext(NoyaAPIContext);
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
return useMemo(() => {
|
|
37
|
+
return (
|
|
38
|
+
value ??
|
|
39
|
+
new NoyaAPI.Client({
|
|
40
|
+
networkClient: new NoyaAPI.MemoryClient(),
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
}, [value]);
|
|
41
44
|
}
|
package/src/react/hooks.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { useSelector } from "@legendapp/state/react";
|
|
2
4
|
import { GENERATED_PAGE_NAME_COUNT, NoyaAPI } from "@noya-app/noya-api";
|
|
3
5
|
import { range } from "@noya-app/noya-utils";
|
|
@@ -9,52 +11,6 @@ import {
|
|
|
9
11
|
useOptionalNoyaClient,
|
|
10
12
|
} from "./context";
|
|
11
13
|
|
|
12
|
-
export function useNoyaFiles(): {
|
|
13
|
-
files: NoyaAPI.File[];
|
|
14
|
-
loading: boolean;
|
|
15
|
-
reload: () => Promise<void>;
|
|
16
|
-
} {
|
|
17
|
-
const client = useNoyaClientOrFallback();
|
|
18
|
-
const files = useSelector(client.files$);
|
|
19
|
-
const session = useSelector(useNoyaClient().session$);
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (!session) return;
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
files.loading === "notStarted" ||
|
|
26
|
-
files.loading === "populatedOnServer"
|
|
27
|
-
) {
|
|
28
|
-
client.files.refetch();
|
|
29
|
-
}
|
|
30
|
-
}, [client, files.loading, session]);
|
|
31
|
-
|
|
32
|
-
const reload = useCallback(() => {
|
|
33
|
-
return client.files.refetch();
|
|
34
|
-
}, [client]);
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
files: files.files,
|
|
38
|
-
loading: !(
|
|
39
|
-
files.loading === "loadedInClient" ||
|
|
40
|
-
files.loading === "populatedOnServer"
|
|
41
|
-
),
|
|
42
|
-
reload,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function useNoyaFile(fileId?: string) {
|
|
47
|
-
const client = useNoyaClientOrFallback();
|
|
48
|
-
const files = useSelector(client.files$);
|
|
49
|
-
return files.files.find((file) => file.id === fileId);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function useNoyaIsOwnFile(fileId?: string) {
|
|
53
|
-
const file = useNoyaFile(fileId);
|
|
54
|
-
const session = useNoyaSession();
|
|
55
|
-
return file?.userId === session?.user.id;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
14
|
export function useNoyaTools(initial?: NoyaAPI.Tool[]) {
|
|
59
15
|
const didInitialize = useRef(false);
|
|
60
16
|
const client = useNoyaClientOrFallback();
|
|
@@ -127,6 +83,13 @@ export function useNoyaAssets(fileId?: string) {
|
|
|
127
83
|
return assets ?? empty;
|
|
128
84
|
}
|
|
129
85
|
|
|
86
|
+
export function useNoyaAssetsByFileVersionId(fileVersionId: string) {
|
|
87
|
+
const client = useNoyaClientOrFallback();
|
|
88
|
+
const empty = useMemo(() => ({ assets: [], loading: true }), []);
|
|
89
|
+
const assets = useSelector(client.assetsByFileVersionId$[fileVersionId]);
|
|
90
|
+
return assets ?? empty;
|
|
91
|
+
}
|
|
92
|
+
|
|
130
93
|
export function useNoyaSecrets(fileId?: string) {
|
|
131
94
|
const client = useNoyaClientOrFallback();
|
|
132
95
|
const empty = useMemo(() => ({ secrets: [], loading: true }), []);
|
|
@@ -355,6 +318,15 @@ export function useNoyaWorkspaces() {
|
|
|
355
318
|
return workspaces;
|
|
356
319
|
}
|
|
357
320
|
|
|
321
|
+
export function useNoyaMultiplayerRoomToken(fileId: string) {
|
|
322
|
+
const client = useNoyaClientOrFallback();
|
|
323
|
+
const multiplayerRoomToken = useObservable(
|
|
324
|
+
client.multiplayerRoomTokens$,
|
|
325
|
+
useMemo(() => (tokens) => tokens[fileId]?.payload ?? undefined, [fileId])
|
|
326
|
+
);
|
|
327
|
+
return multiplayerRoomToken as { access: "read" | "write" } | undefined;
|
|
328
|
+
}
|
|
329
|
+
|
|
358
330
|
export function useNoyaWorkspaceInvitations(workspaceId: string) {
|
|
359
331
|
const client = useNoyaClientOrFallback();
|
|
360
332
|
const workspaceInvitations = useSelector(
|
|
@@ -380,15 +352,15 @@ export function useNoyaWorkspaceInvitations(workspaceId: string) {
|
|
|
380
352
|
|
|
381
353
|
const emptyObservedFileVersions: {
|
|
382
354
|
fileVersions: NoyaAPI.FileVersion[];
|
|
383
|
-
loading: NoyaAPI.
|
|
355
|
+
loading: NoyaAPI.FetchStatus;
|
|
384
356
|
} = {
|
|
385
357
|
fileVersions: [],
|
|
386
|
-
loading: "
|
|
358
|
+
loading: "idle",
|
|
387
359
|
};
|
|
388
360
|
|
|
389
361
|
export function useNoyaOwnedFileVersions(fileId: string): {
|
|
390
362
|
fileVersions: NoyaAPI.FileVersion[];
|
|
391
|
-
loading: NoyaAPI.
|
|
363
|
+
loading: NoyaAPI.FetchStatus;
|
|
392
364
|
reload: () => Promise<void>;
|
|
393
365
|
} {
|
|
394
366
|
const client = useNoyaClientOrFallback();
|
|
@@ -396,7 +368,7 @@ export function useNoyaOwnedFileVersions(fileId: string): {
|
|
|
396
368
|
const fileVersions = useObservable(client.ownedFileVersions$, path);
|
|
397
369
|
|
|
398
370
|
useEffect(() => {
|
|
399
|
-
if (!fileVersions || fileVersions.loading === "
|
|
371
|
+
if (!fileVersions || fileVersions.loading === "idle") {
|
|
400
372
|
client.fileVersions.refetch({ fileId, type: "owned" });
|
|
401
373
|
}
|
|
402
374
|
}, [client, fileId, fileVersions, fileVersions?.loading]);
|
|
@@ -420,13 +392,13 @@ export function useNoyaTemplates() {
|
|
|
420
392
|
const { templates, loading } = useSelector(client.templates$);
|
|
421
393
|
|
|
422
394
|
useEffect(() => {
|
|
423
|
-
if (loading === "
|
|
395
|
+
if (loading === "idle") {
|
|
424
396
|
client.templates.read();
|
|
425
397
|
}
|
|
426
398
|
}, [client, loading]);
|
|
427
399
|
|
|
428
400
|
return {
|
|
429
401
|
templates,
|
|
430
|
-
loading:
|
|
402
|
+
loading: loading === "fetching",
|
|
431
403
|
};
|
|
432
404
|
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { NoyaAPI } from "@noya-app/noya-api";
|
|
4
|
+
import { Static, useObservable } from "@noya-app/noya-multiplayer-react";
|
|
5
|
+
import { ActivityEvent, Resource } from "@noya-app/noya-schemas";
|
|
6
|
+
import { SelectConfig, SelectedShape } from "@noya-app/observable";
|
|
7
|
+
import {
|
|
8
|
+
EntitySchema,
|
|
9
|
+
RefetchFunction,
|
|
10
|
+
RefetchableObservable,
|
|
11
|
+
Table,
|
|
12
|
+
TableFetchOptions,
|
|
13
|
+
} from "@noya-app/observable-store";
|
|
14
|
+
import { useEffect, useMemo } from "react";
|
|
15
|
+
import { useNoyaClientOrFallback } from "./context";
|
|
16
|
+
|
|
17
|
+
type GetRowType<TTable extends Table<EntitySchema>> = Static<TTable["schema"]>;
|
|
18
|
+
type GetSelectConfig<TTable extends Table<EntitySchema>> = SelectConfig<
|
|
19
|
+
GetRowType<TTable>[]
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
type UseTableOptions = Omit<TableFetchOptions, "autoStart">;
|
|
23
|
+
|
|
24
|
+
export function useTable<
|
|
25
|
+
TTable extends Table<any>,
|
|
26
|
+
Config extends GetSelectConfig<TTable>,
|
|
27
|
+
>(
|
|
28
|
+
table: TTable | null | undefined,
|
|
29
|
+
{
|
|
30
|
+
where,
|
|
31
|
+
select,
|
|
32
|
+
}: {
|
|
33
|
+
where?: Partial<Record<string, any>> & { id?: string | null };
|
|
34
|
+
select: Config;
|
|
35
|
+
},
|
|
36
|
+
options: UseTableOptions = {}
|
|
37
|
+
): {
|
|
38
|
+
status: NoyaAPI.FetchStatus;
|
|
39
|
+
data: SelectedShape<GetRowType<TTable>, Config>[];
|
|
40
|
+
refetch: () => void;
|
|
41
|
+
} {
|
|
42
|
+
const stableSelect = useMemo(() => {
|
|
43
|
+
return JSON.stringify(select);
|
|
44
|
+
}, [select]);
|
|
45
|
+
|
|
46
|
+
const stableWhere = useMemo(() => {
|
|
47
|
+
let cloneWithNoUndefined: Partial<typeof where> = {};
|
|
48
|
+
for (const [key, value] of Object.entries(where ?? {})) {
|
|
49
|
+
if (value !== undefined) {
|
|
50
|
+
cloneWithNoUndefined[key] = value;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return JSON.stringify(cloneWithNoUndefined);
|
|
54
|
+
}, [where]);
|
|
55
|
+
|
|
56
|
+
const observable = useMemo((): RefetchableObservable<{
|
|
57
|
+
status: NoyaAPI.FetchStatus;
|
|
58
|
+
data: SelectedShape<GetRowType<TTable>, Config>[];
|
|
59
|
+
}> => {
|
|
60
|
+
const parsedSelect = JSON.parse(stableSelect) as typeof select;
|
|
61
|
+
const parsedWhere = JSON.parse(stableWhere) as typeof where;
|
|
62
|
+
|
|
63
|
+
if (!table) {
|
|
64
|
+
return new RefetchableObservable<{
|
|
65
|
+
status: NoyaAPI.FetchStatus;
|
|
66
|
+
data: SelectedShape<GetRowType<TTable>, Config>[];
|
|
67
|
+
}>({
|
|
68
|
+
status: "idle",
|
|
69
|
+
data: [],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (parsedWhere?.id === null) {
|
|
74
|
+
return new RefetchableObservable<{
|
|
75
|
+
status: NoyaAPI.FetchStatus;
|
|
76
|
+
data: SelectedShape<GetRowType<TTable>, Config>[];
|
|
77
|
+
}>({
|
|
78
|
+
status: "success",
|
|
79
|
+
data: [],
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return table.query(
|
|
84
|
+
{
|
|
85
|
+
$where: parsedWhere,
|
|
86
|
+
$select: parsedSelect,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
policy: options.policy,
|
|
90
|
+
debug: options.debug,
|
|
91
|
+
autoStart: false,
|
|
92
|
+
}
|
|
93
|
+
) as RefetchableObservable<{
|
|
94
|
+
status: NoyaAPI.FetchStatus;
|
|
95
|
+
data: any[];
|
|
96
|
+
}>;
|
|
97
|
+
}, [stableSelect, stableWhere, table, options.policy, options.debug]);
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
observable.start?.();
|
|
101
|
+
}, [observable]);
|
|
102
|
+
|
|
103
|
+
const { status, data } = useObservable(observable);
|
|
104
|
+
|
|
105
|
+
return useMemo(() => {
|
|
106
|
+
return {
|
|
107
|
+
status,
|
|
108
|
+
data,
|
|
109
|
+
refetch: observable.refetch,
|
|
110
|
+
};
|
|
111
|
+
}, [status, data, observable]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function useFileList<Config extends SelectConfig<NoyaAPI.FileListItem>>(
|
|
115
|
+
select: Config,
|
|
116
|
+
options: UseTableOptions = {}
|
|
117
|
+
): {
|
|
118
|
+
status: NoyaAPI.FetchStatus;
|
|
119
|
+
data: SelectedShape<NoyaAPI.FileListItem, Config>[];
|
|
120
|
+
refetch: RefetchFunction;
|
|
121
|
+
} {
|
|
122
|
+
const client = useNoyaClientOrFallback();
|
|
123
|
+
|
|
124
|
+
return useTable(client.fileList$, { select }, options);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function useFileListItem<
|
|
128
|
+
Config extends SelectConfig<NoyaAPI.FileListItem>,
|
|
129
|
+
>(
|
|
130
|
+
id: string | undefined,
|
|
131
|
+
select: Config,
|
|
132
|
+
options: UseTableOptions = {}
|
|
133
|
+
): {
|
|
134
|
+
status: NoyaAPI.FetchStatus;
|
|
135
|
+
data: SelectedShape<NoyaAPI.FileListItem, Config> | undefined;
|
|
136
|
+
refetch: RefetchFunction;
|
|
137
|
+
} {
|
|
138
|
+
const client = useNoyaClientOrFallback();
|
|
139
|
+
|
|
140
|
+
const { status, data, refetch } = useTable(
|
|
141
|
+
client.fileList$,
|
|
142
|
+
{ where: { id: id ?? null }, select },
|
|
143
|
+
options
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
return useMemo(() => {
|
|
147
|
+
return {
|
|
148
|
+
data: data.at(0),
|
|
149
|
+
status,
|
|
150
|
+
refetch,
|
|
151
|
+
};
|
|
152
|
+
}, [data, status, refetch]);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function useResourcesList<Config extends SelectConfig<Resource>>(
|
|
156
|
+
fileId: string,
|
|
157
|
+
select: Config,
|
|
158
|
+
options: UseTableOptions = {}
|
|
159
|
+
): {
|
|
160
|
+
status: NoyaAPI.FetchStatus;
|
|
161
|
+
data: SelectedShape<Resource, Config>[];
|
|
162
|
+
refetch: RefetchFunction;
|
|
163
|
+
} {
|
|
164
|
+
const client = useNoyaClientOrFallback();
|
|
165
|
+
|
|
166
|
+
return useTable(
|
|
167
|
+
client.resources$,
|
|
168
|
+
{ select, where: { accessibleByFileId: fileId } },
|
|
169
|
+
options
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function useUser<Config extends SelectConfig<NoyaAPI.PublicUser>>(
|
|
174
|
+
id: string | null | undefined,
|
|
175
|
+
select: Config,
|
|
176
|
+
options: UseTableOptions = {}
|
|
177
|
+
): {
|
|
178
|
+
status: NoyaAPI.FetchStatus;
|
|
179
|
+
data: SelectedShape<NoyaAPI.PublicUser, Config> | undefined;
|
|
180
|
+
refetch: RefetchFunction;
|
|
181
|
+
} {
|
|
182
|
+
const client = useNoyaClientOrFallback();
|
|
183
|
+
|
|
184
|
+
const { status, data, refetch } = useTable(
|
|
185
|
+
client.users$,
|
|
186
|
+
{ select, where: { id: id ?? null } },
|
|
187
|
+
options
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
return useMemo(() => {
|
|
191
|
+
return {
|
|
192
|
+
status,
|
|
193
|
+
data: data.at(0),
|
|
194
|
+
refetch,
|
|
195
|
+
};
|
|
196
|
+
}, [status, data, refetch]);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function useActivityEventsList<
|
|
200
|
+
Config extends SelectConfig<ActivityEvent>,
|
|
201
|
+
>(
|
|
202
|
+
fileId: string,
|
|
203
|
+
select: Config,
|
|
204
|
+
options: UseTableOptions = {}
|
|
205
|
+
): {
|
|
206
|
+
status: NoyaAPI.FetchStatus;
|
|
207
|
+
data: SelectedShape<ActivityEvent, Config>[];
|
|
208
|
+
refetch: RefetchFunction;
|
|
209
|
+
} {
|
|
210
|
+
const client = useNoyaClientOrFallback();
|
|
211
|
+
|
|
212
|
+
return useTable(
|
|
213
|
+
client.activityEvents$,
|
|
214
|
+
{ select, where: { fileId } },
|
|
215
|
+
options
|
|
216
|
+
);
|
|
217
|
+
}
|