@noya-app/noya-api-client-react 0.1.36 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noya-app/noya-api-client-react",
3
- "version": "0.1.36",
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.36",
14
- "@noya-app/noya-utils": "0.1.6",
15
- "@noya-app/observable": "0.1.11",
16
- "@noya-app/observable-react": "0.1.21"
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": "*",
@@ -83,6 +83,13 @@ export function useNoyaAssets(fileId?: string) {
83
83
  return assets ?? empty;
84
84
  }
85
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
+
86
93
  export function useNoyaSecrets(fileId?: string) {
87
94
  const client = useNoyaClientOrFallback();
88
95
  const empty = useMemo(() => ({ secrets: [], loading: true }), []);
@@ -1,58 +1,104 @@
1
- import { NoyaAPI, RefetchableObservable } from "@noya-app/noya-api";
2
- import { useObservable } from "@noya-app/noya-multiplayer-react";
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";
3
6
  import { SelectConfig, SelectedShape } from "@noya-app/observable";
4
- import { useMemo } from "react";
7
+ import {
8
+ EntitySchema,
9
+ RefetchFunction,
10
+ RefetchableObservable,
11
+ Table,
12
+ TableFetchOptions,
13
+ } from "@noya-app/observable-store";
14
+ import { useEffect, useMemo } from "react";
5
15
  import { useNoyaClientOrFallback } from "./context";
6
16
 
7
- type FileListTableOptions = {
8
- policy?: NoyaAPI.FetchPolicy;
9
- debug?: boolean;
10
- };
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">;
11
23
 
12
- function useFileListTable<Config extends SelectConfig<NoyaAPI.FileListItem>>(
13
- { where, select }: { where?: { id?: string | null }; select: Config },
14
- options: FileListTableOptions
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 = {}
15
37
  ): {
16
38
  status: NoyaAPI.FetchStatus;
17
- data: SelectedShape<NoyaAPI.FileListItem, Config>[];
39
+ data: SelectedShape<GetRowType<TTable>, Config>[];
18
40
  refetch: () => void;
19
41
  } {
20
- const client = useNoyaClientOrFallback();
21
-
22
42
  const stableSelect = useMemo(() => {
23
43
  return JSON.stringify(select);
24
44
  }, [select]);
25
45
 
26
- const observable = useMemo(() => {
27
- if (where?.id === null) {
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) {
28
64
  return new RefetchableObservable<{
29
65
  status: NoyaAPI.FetchStatus;
30
- data: SelectedShape<NoyaAPI.FileListItem, Config>[];
66
+ data: SelectedShape<GetRowType<TTable>, Config>[];
31
67
  }>({
32
- status: "success",
68
+ status: "idle",
33
69
  data: [],
34
70
  });
35
71
  }
36
72
 
37
- const parsedSelect = JSON.parse(stableSelect) as typeof select;
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
+ }
38
82
 
39
- return client.fileList$.query(
83
+ return table.query(
40
84
  {
41
- $where: { id: where?.id },
85
+ $where: parsedWhere,
42
86
  $select: parsedSelect,
43
87
  },
44
88
  {
45
89
  policy: options.policy,
46
90
  debug: options.debug,
91
+ autoStart: false,
47
92
  }
48
- );
49
- }, [
50
- client.fileList$,
51
- options.policy,
52
- stableSelect,
53
- where?.id,
54
- options.debug,
55
- ]);
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]);
56
102
 
57
103
  const { status, data } = useObservable(observable);
58
104
 
@@ -67,13 +113,15 @@ function useFileListTable<Config extends SelectConfig<NoyaAPI.FileListItem>>(
67
113
 
68
114
  export function useFileList<Config extends SelectConfig<NoyaAPI.FileListItem>>(
69
115
  select: Config,
70
- options: FileListTableOptions = {}
116
+ options: UseTableOptions = {}
71
117
  ): {
72
118
  status: NoyaAPI.FetchStatus;
73
119
  data: SelectedShape<NoyaAPI.FileListItem, Config>[];
74
- refetch: () => void;
120
+ refetch: RefetchFunction;
75
121
  } {
76
- return useFileListTable({ select }, options);
122
+ const client = useNoyaClientOrFallback();
123
+
124
+ return useTable(client.fileList$, { select }, options);
77
125
  }
78
126
 
79
127
  export function useFileListItem<
@@ -81,13 +129,16 @@ export function useFileListItem<
81
129
  >(
82
130
  id: string | undefined,
83
131
  select: Config,
84
- options: FileListTableOptions = {}
132
+ options: UseTableOptions = {}
85
133
  ): {
86
134
  status: NoyaAPI.FetchStatus;
87
135
  data: SelectedShape<NoyaAPI.FileListItem, Config> | undefined;
88
- refetch: () => void;
136
+ refetch: RefetchFunction;
89
137
  } {
90
- const { status, data, refetch } = useFileListTable(
138
+ const client = useNoyaClientOrFallback();
139
+
140
+ const { status, data, refetch } = useTable(
141
+ client.fileList$,
91
142
  { where: { id: id ?? null }, select },
92
143
  options
93
144
  );
@@ -100,3 +151,67 @@ export function useFileListItem<
100
151
  };
101
152
  }, [data, status, refetch]);
102
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
+ }