@noya-app/noya-api-client-react 0.1.19
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/.eslintrc.js +11 -0
- package/.turbo/turbo-build.log +17 -0
- package/CHANGELOG.md +9 -0
- package/dist/index.d.mts +301 -0
- package/dist/index.d.ts +301 -0
- package/dist/index.js +321 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +266 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +20 -0
- package/src/index.ts +3 -0
- package/src/react/context.ts +41 -0
- package/src/react/hooks.ts +262 -0
- package/tsconfig.json +3 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { NoyaAPI } from "@noya-app/noya-api";
|
|
2
|
+
import { createContext, useContext, useMemo } from "react";
|
|
3
|
+
|
|
4
|
+
type NoyaAPIContextValue = NoyaAPI.Client;
|
|
5
|
+
|
|
6
|
+
const NoyaAPIContext = createContext<NoyaAPIContextValue | undefined>(
|
|
7
|
+
undefined
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
export const NoyaAPIProvider: React.Provider<NoyaAPIContextValue | undefined> =
|
|
11
|
+
NoyaAPIContext.Provider;
|
|
12
|
+
|
|
13
|
+
export function useNoyaClient(): NoyaAPIContextValue {
|
|
14
|
+
const value = useContext(NoyaAPIContext);
|
|
15
|
+
|
|
16
|
+
if (!value) {
|
|
17
|
+
throw new Error("Missing NoyaAPIContextValue");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function useOptionalNoyaClient(): NoyaAPIContextValue | undefined {
|
|
24
|
+
return useContext(NoyaAPIContext);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* If there's no client, fallback to a memory client.
|
|
29
|
+
* We do this to safely render content when logged out (e.g. when sharing).
|
|
30
|
+
*/
|
|
31
|
+
export function useNoyaClientOrFallback(): NoyaAPIContextValue {
|
|
32
|
+
const value = useContext(NoyaAPIContext);
|
|
33
|
+
|
|
34
|
+
const memoryClient = useMemo(() => {
|
|
35
|
+
return new NoyaAPI.Client({
|
|
36
|
+
networkClient: new NoyaAPI.MemoryClient(),
|
|
37
|
+
});
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
return value ?? memoryClient;
|
|
41
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { useSelector } from "@legendapp/state/react";
|
|
2
|
+
import { GENERATED_PAGE_NAME_COUNT, NoyaAPI } from "@noya-app/noya-api";
|
|
3
|
+
import { range } from "@noya-app/noya-utils";
|
|
4
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
5
|
+
import {
|
|
6
|
+
useNoyaClient,
|
|
7
|
+
useNoyaClientOrFallback,
|
|
8
|
+
useOptionalNoyaClient,
|
|
9
|
+
} from "./context";
|
|
10
|
+
|
|
11
|
+
export function useNoyaFiles(): {
|
|
12
|
+
files: NoyaAPI.File[];
|
|
13
|
+
loading: NoyaAPI.DataLoadingState;
|
|
14
|
+
} {
|
|
15
|
+
const client = useNoyaClientOrFallback();
|
|
16
|
+
const files = useSelector(client.files$);
|
|
17
|
+
const session = useSelector(useNoyaClient().session$);
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (!session) return;
|
|
21
|
+
|
|
22
|
+
if (
|
|
23
|
+
files.loading === "notStarted" ||
|
|
24
|
+
files.loading === "populatedOnServer"
|
|
25
|
+
) {
|
|
26
|
+
client.files.refetch();
|
|
27
|
+
}
|
|
28
|
+
}, [client, files.loading, session]);
|
|
29
|
+
|
|
30
|
+
return files;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function useNoyaIsOwnFile(fileId?: string) {
|
|
34
|
+
const client = useNoyaClientOrFallback();
|
|
35
|
+
const files = useSelector(client.files$);
|
|
36
|
+
const session = useSelector(client.session$);
|
|
37
|
+
const file = files.files.find((file) => file.id === fileId);
|
|
38
|
+
return file?.userId === session?.user.id;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function useNoyaTools(initial?: NoyaAPI.Tool[]) {
|
|
42
|
+
const didInitialize = useRef(false);
|
|
43
|
+
const client = useNoyaClientOrFallback();
|
|
44
|
+
const tools = useSelector(client.tools$);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (didInitialize.current) return;
|
|
47
|
+
didInitialize.current = true;
|
|
48
|
+
|
|
49
|
+
if (initial) {
|
|
50
|
+
client.tools.setInitial(initial);
|
|
51
|
+
} else {
|
|
52
|
+
client.tools.list();
|
|
53
|
+
}
|
|
54
|
+
}, [client, initial]);
|
|
55
|
+
return tools;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function useOptionalNoyaTools(initial?: NoyaAPI.Tool[]) {
|
|
59
|
+
const client = useNoyaClientOrFallback();
|
|
60
|
+
const tools = useSelector(client.tools$);
|
|
61
|
+
return useMemo(
|
|
62
|
+
() =>
|
|
63
|
+
tools.loading && initial ? { loading: true, tools: initial } : tools,
|
|
64
|
+
[initial, tools]
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function useNoyaTags() {
|
|
69
|
+
const client = useNoyaClient();
|
|
70
|
+
const tags = useSelector(client.tags$);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
client.tags.read();
|
|
73
|
+
}, [client]);
|
|
74
|
+
return tags;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function useOptionalNoyaTags() {
|
|
78
|
+
const client = useNoyaClientOrFallback();
|
|
79
|
+
const tags = useSelector(client.tags$);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
client.tags.read();
|
|
82
|
+
}, [client]);
|
|
83
|
+
return tags;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function useNoyaCreators() {
|
|
87
|
+
const client = useNoyaClientOrFallback();
|
|
88
|
+
const creators = useSelector(client.creators$);
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
client.creators.read();
|
|
91
|
+
}, [client]);
|
|
92
|
+
return creators;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function useOptionalNoyaCreators() {
|
|
96
|
+
const client = useNoyaClientOrFallback();
|
|
97
|
+
const creators = useSelector(client.creators$);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
client.creators.read();
|
|
100
|
+
}, [client]);
|
|
101
|
+
return creators;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function useNoyaAssets(fileId?: string) {
|
|
105
|
+
const client = useNoyaClientOrFallback();
|
|
106
|
+
const empty = useMemo(() => ({ assets: [], loading: true }), []);
|
|
107
|
+
const assets = useSelector(
|
|
108
|
+
fileId ? client.assetsByFileId$[fileId] : client.assets$
|
|
109
|
+
);
|
|
110
|
+
return assets ?? empty;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function useNoyaSession() {
|
|
114
|
+
const session = useSelector(useNoyaClient().session$);
|
|
115
|
+
return session;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function useOptionalNoyaSession() {
|
|
119
|
+
const session = useSelector(useOptionalNoyaClient()?.session$);
|
|
120
|
+
return session;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function useNoyaBilling() {
|
|
124
|
+
const billing = useSelector(useNoyaClient().billing$);
|
|
125
|
+
return billing;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function useNoyaEmailLists() {
|
|
129
|
+
const emailLists = useSelector(useNoyaClient().emailLists$);
|
|
130
|
+
return emailLists;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function useNoyaUserData() {
|
|
134
|
+
const userData = useSelector(useNoyaClientOrFallback().userData$);
|
|
135
|
+
return userData;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function useOptionalNoyaUserData() {
|
|
139
|
+
const userData = useSelector(useNoyaClientOrFallback().userData$);
|
|
140
|
+
return userData;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function useIsBeta() {
|
|
144
|
+
const userData = useOptionalNoyaUserData();
|
|
145
|
+
return userData?.userData?.beta ?? false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function useMetadata<T extends NoyaAPI.Json>(key: string) {
|
|
149
|
+
const { userData } = useNoyaUserData();
|
|
150
|
+
const metadata = userData?.metadata || [];
|
|
151
|
+
const metadataItem = metadata.find((item) => item.key === key);
|
|
152
|
+
return metadataItem?.value as T | undefined;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function useGeneratedComponentNames(name: string) {
|
|
156
|
+
const key = name.trim().toLowerCase();
|
|
157
|
+
const { generatedNames$, loadingNames$ } = useNoyaClientOrFallback();
|
|
158
|
+
const result = useSelector(
|
|
159
|
+
() => generatedNames$[key].get() as NoyaAPI.GeneratedName[] | undefined
|
|
160
|
+
);
|
|
161
|
+
const loading = useSelector(() => loadingNames$[key].get());
|
|
162
|
+
return useMemo(() => ({ names: result ?? [], loading }), [loading, result]);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function useGeneratedComponentDescriptions() {
|
|
166
|
+
const { generatedDescriptions$, loadingDescriptions$ } =
|
|
167
|
+
useNoyaClientOrFallback();
|
|
168
|
+
const descriptions = useSelector(generatedDescriptions$);
|
|
169
|
+
const loading = useSelector(loadingDescriptions$);
|
|
170
|
+
return useMemo(() => ({ descriptions, loading }), [loading, descriptions]);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function useGeneratedComponentDescription(name: string) {
|
|
174
|
+
const key = name.trim().toLowerCase();
|
|
175
|
+
const { generatedDescriptions$, loadingDescriptions$ } =
|
|
176
|
+
useNoyaClientOrFallback();
|
|
177
|
+
const description = useSelector(
|
|
178
|
+
() => generatedDescriptions$[key].get() as string | undefined
|
|
179
|
+
);
|
|
180
|
+
const loading = useSelector(() => loadingDescriptions$[key].get());
|
|
181
|
+
return useMemo(() => ({ description, loading }), [loading, description]);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function useRandomImages() {
|
|
185
|
+
const { randomImages$, loadingRandomImages$ } = useNoyaClientOrFallback();
|
|
186
|
+
const images = useSelector(randomImages$);
|
|
187
|
+
const loading = useSelector(loadingRandomImages$);
|
|
188
|
+
return useMemo(() => ({ images, loading }), [loading, images]);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function useRandomIcons() {
|
|
192
|
+
const { randomIcons$, loadingRandomIcons$ } = useNoyaClientOrFallback();
|
|
193
|
+
const icons = useSelector(randomIcons$);
|
|
194
|
+
const loading = useSelector(loadingRandomIcons$);
|
|
195
|
+
return useMemo(() => ({ icons, loading }), [loading, icons]);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function useNetworkRequests() {
|
|
199
|
+
const { requests$ } = useNoyaClientOrFallback();
|
|
200
|
+
const requests = useSelector(requests$) as NoyaAPI.RequestSnapshot[];
|
|
201
|
+
return requests;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export type EnhancedGeneratedPageName = NoyaAPI.GeneratedName & {
|
|
205
|
+
index: number;
|
|
206
|
+
type: "suggestion";
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
export function useGeneratedPageNames(): EnhancedGeneratedPageName[] {
|
|
210
|
+
const { generatedPageNames$ } = useNoyaClientOrFallback();
|
|
211
|
+
const names = useSelector(generatedPageNames$) as NoyaAPI.GeneratedName[];
|
|
212
|
+
|
|
213
|
+
const namesWithDefaultsAndTypes = useMemo(() => {
|
|
214
|
+
const rangeArray = range(0, GENERATED_PAGE_NAME_COUNT);
|
|
215
|
+
|
|
216
|
+
// Fill any empty slots with default names in the 'loading' state
|
|
217
|
+
const withDefaults = rangeArray.map((index): NoyaAPI.GeneratedName => {
|
|
218
|
+
const name = names[index];
|
|
219
|
+
return name ?? { name: `Page ${index + 1}`, loading: true, key: "" };
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return withDefaults.map(
|
|
223
|
+
(name, index): EnhancedGeneratedPageName => ({
|
|
224
|
+
...name,
|
|
225
|
+
index,
|
|
226
|
+
type: "suggestion",
|
|
227
|
+
})
|
|
228
|
+
);
|
|
229
|
+
}, [names]);
|
|
230
|
+
|
|
231
|
+
// Take the first 3
|
|
232
|
+
return namesWithDefaultsAndTypes.slice(0, 3);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function useGeneratedPageComponentNames(): EnhancedGeneratedPageName[] {
|
|
236
|
+
const { generatedPageComponentNames$: generatedComponentNames$ } =
|
|
237
|
+
useNoyaClientOrFallback();
|
|
238
|
+
const names = useSelector(
|
|
239
|
+
generatedComponentNames$
|
|
240
|
+
) as NoyaAPI.GeneratedName[];
|
|
241
|
+
|
|
242
|
+
const namesWithDefaultsAndTypes = useMemo(() => {
|
|
243
|
+
const rangeArray = range(0, GENERATED_PAGE_NAME_COUNT);
|
|
244
|
+
|
|
245
|
+
// Fill any empty slots with default names in the 'loading' state
|
|
246
|
+
const withDefaults = rangeArray.map((index): NoyaAPI.GeneratedName => {
|
|
247
|
+
const name = names[index];
|
|
248
|
+
return name ?? { name: `Component ${index + 1}`, loading: true, key: "" };
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
return withDefaults.map(
|
|
252
|
+
(name, index): EnhancedGeneratedPageName => ({
|
|
253
|
+
...name,
|
|
254
|
+
index,
|
|
255
|
+
type: "suggestion",
|
|
256
|
+
})
|
|
257
|
+
);
|
|
258
|
+
}, [names]);
|
|
259
|
+
|
|
260
|
+
// Take the first 3
|
|
261
|
+
return namesWithDefaultsAndTypes.slice(0, 3);
|
|
262
|
+
}
|
package/tsconfig.json
ADDED