@pylo/react 0.7.0 → 0.9.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/README.md +5 -107
- package/dist/{chunk-IKQ52QLH.js → chunk-BPRHGSZF.js} +175 -22
- package/dist/{chunk-DOPZ5GRU.js → chunk-O456XBDT.js} +1 -1
- package/dist/hooks.js +2 -2
- package/dist/index.d.ts +22 -9
- package/dist/index.js +4 -3
- package/dist/provider-4DBl_6p0.d.ts +74 -0
- package/dist/provider.d.ts +1 -1
- package/dist/provider.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-SBMMJYJT.js +0 -346
- package/dist/chunk-VUY6OTMP.js +0 -540
package/dist/chunk-SBMMJYJT.js
DELETED
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
// src/provider.tsx
|
|
2
|
-
import {
|
|
3
|
-
createContext,
|
|
4
|
-
useContext,
|
|
5
|
-
useEffect,
|
|
6
|
-
useMemo,
|
|
7
|
-
useRef,
|
|
8
|
-
useSyncExternalStore
|
|
9
|
-
} from "react";
|
|
10
|
-
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
11
|
-
import { createPyloClient, resolveEndpoint } from "@pylo/core";
|
|
12
|
-
import { ME_QUERY } from "@pylo/auth";
|
|
13
|
-
|
|
14
|
-
// src/session/store.ts
|
|
15
|
-
import {
|
|
16
|
-
graphqlRequest,
|
|
17
|
-
hasErrors,
|
|
18
|
-
extractErrorMessage,
|
|
19
|
-
isUnauthorizedError,
|
|
20
|
-
shouldRefreshToken,
|
|
21
|
-
LOGIN_MUTATION,
|
|
22
|
-
REFRESH_TOKEN_MUTATION
|
|
23
|
-
} from "@pylo/auth";
|
|
24
|
-
function createSessionStore(options) {
|
|
25
|
-
var _a;
|
|
26
|
-
const prefix = (_a = options.keyPrefix) != null ? _a : "pylo";
|
|
27
|
-
const AUTH_KEY = `${prefix}.auth_token`;
|
|
28
|
-
const REFRESH_KEY = `${prefix}.refresh_token`;
|
|
29
|
-
let state = { status: "loading", token: null };
|
|
30
|
-
let refreshToken = null;
|
|
31
|
-
let inFlight = null;
|
|
32
|
-
let ready = null;
|
|
33
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
34
|
-
function setState(next) {
|
|
35
|
-
state = next;
|
|
36
|
-
for (const listener of listeners) listener();
|
|
37
|
-
}
|
|
38
|
-
async function persist(auth, refresh2) {
|
|
39
|
-
refreshToken = refresh2;
|
|
40
|
-
await options.storage.setItem(AUTH_KEY, auth);
|
|
41
|
-
await options.storage.setItem(REFRESH_KEY, refresh2);
|
|
42
|
-
setState({ status: "signedIn", token: auth });
|
|
43
|
-
}
|
|
44
|
-
async function clear() {
|
|
45
|
-
var _a2;
|
|
46
|
-
refreshToken = null;
|
|
47
|
-
await options.storage.removeItem(AUTH_KEY);
|
|
48
|
-
await options.storage.removeItem(REFRESH_KEY);
|
|
49
|
-
setState({ status: "signedOut", token: null });
|
|
50
|
-
(_a2 = options.onSignOut) == null ? void 0 : _a2.call(options);
|
|
51
|
-
}
|
|
52
|
-
async function runRefresh() {
|
|
53
|
-
await init();
|
|
54
|
-
if (!refreshToken) {
|
|
55
|
-
await clear();
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
const response = await graphqlRequest(
|
|
59
|
-
options.endpoint,
|
|
60
|
-
REFRESH_TOKEN_MUTATION,
|
|
61
|
-
{ input: { refresh_token: refreshToken } }
|
|
62
|
-
);
|
|
63
|
-
if (hasErrors(response) || !response.data) {
|
|
64
|
-
if (isUnauthorizedError(response)) {
|
|
65
|
-
await clear();
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
return state.token;
|
|
69
|
-
}
|
|
70
|
-
const { auth_token, refresh_token } = response.data.refreshToken.data;
|
|
71
|
-
await persist(auth_token, refresh_token);
|
|
72
|
-
return auth_token;
|
|
73
|
-
}
|
|
74
|
-
function init() {
|
|
75
|
-
ready != null ? ready : ready = (async () => {
|
|
76
|
-
try {
|
|
77
|
-
const [auth, stored] = await Promise.all([
|
|
78
|
-
options.storage.getItem(AUTH_KEY),
|
|
79
|
-
options.storage.getItem(REFRESH_KEY)
|
|
80
|
-
]);
|
|
81
|
-
refreshToken = stored;
|
|
82
|
-
setState(
|
|
83
|
-
auth ? { status: "signedIn", token: auth } : { status: "signedOut", token: null }
|
|
84
|
-
);
|
|
85
|
-
} catch {
|
|
86
|
-
refreshToken = null;
|
|
87
|
-
setState({ status: "signedOut", token: null });
|
|
88
|
-
}
|
|
89
|
-
})();
|
|
90
|
-
return ready;
|
|
91
|
-
}
|
|
92
|
-
function refresh() {
|
|
93
|
-
inFlight != null ? inFlight : inFlight = runRefresh().finally(() => {
|
|
94
|
-
inFlight = null;
|
|
95
|
-
});
|
|
96
|
-
return inFlight;
|
|
97
|
-
}
|
|
98
|
-
return {
|
|
99
|
-
getState: () => state,
|
|
100
|
-
subscribe(listener) {
|
|
101
|
-
listeners.add(listener);
|
|
102
|
-
return () => void listeners.delete(listener);
|
|
103
|
-
},
|
|
104
|
-
init,
|
|
105
|
-
async getToken() {
|
|
106
|
-
await init();
|
|
107
|
-
if (!state.token) return null;
|
|
108
|
-
if (shouldRefreshToken(state.token)) return refresh();
|
|
109
|
-
return state.token;
|
|
110
|
-
},
|
|
111
|
-
refresh,
|
|
112
|
-
async login(email, password) {
|
|
113
|
-
var _a2, _b;
|
|
114
|
-
const response = await graphqlRequest(
|
|
115
|
-
options.endpoint,
|
|
116
|
-
LOGIN_MUTATION,
|
|
117
|
-
{
|
|
118
|
-
input: {
|
|
119
|
-
email,
|
|
120
|
-
password,
|
|
121
|
-
...options.appId !== void 0 ? { pylo_app_id: options.appId } : {}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
);
|
|
125
|
-
if (hasErrors(response)) {
|
|
126
|
-
return {
|
|
127
|
-
success: false,
|
|
128
|
-
error: {
|
|
129
|
-
code: "INVALID_CREDENTIALS",
|
|
130
|
-
message: (_a2 = extractErrorMessage(response.errors)) != null ? _a2 : "Login failed"
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
if (!response.data) {
|
|
135
|
-
return {
|
|
136
|
-
success: false,
|
|
137
|
-
error: { code: "SERVER_ERROR", message: "No data returned" }
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
const { auth_token, refresh_token } = response.data.login.data;
|
|
141
|
-
await persist(auth_token, refresh_token);
|
|
142
|
-
(_b = options.onSignIn) == null ? void 0 : _b.call(options);
|
|
143
|
-
return { success: true, authToken: auth_token, refreshToken: refresh_token };
|
|
144
|
-
},
|
|
145
|
-
logout: clear
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// src/session/storage.ts
|
|
150
|
-
function createMemoryStorage() {
|
|
151
|
-
const store = /* @__PURE__ */ new Map();
|
|
152
|
-
return {
|
|
153
|
-
getItem: async (key) => {
|
|
154
|
-
var _a;
|
|
155
|
-
return (_a = store.get(key)) != null ? _a : null;
|
|
156
|
-
},
|
|
157
|
-
setItem: async (key, value) => void store.set(key, value),
|
|
158
|
-
removeItem: async (key) => void store.delete(key)
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
function createLocalStorageAdapter() {
|
|
162
|
-
let web;
|
|
163
|
-
try {
|
|
164
|
-
web = globalThis.localStorage;
|
|
165
|
-
} catch {
|
|
166
|
-
web = void 0;
|
|
167
|
-
}
|
|
168
|
-
if (!web) return createMemoryStorage();
|
|
169
|
-
const fallback = createMemoryStorage();
|
|
170
|
-
return {
|
|
171
|
-
getItem: async (key) => {
|
|
172
|
-
try {
|
|
173
|
-
const value = web.getItem(key);
|
|
174
|
-
if (value !== null) return value;
|
|
175
|
-
} catch {
|
|
176
|
-
}
|
|
177
|
-
return fallback.getItem(key);
|
|
178
|
-
},
|
|
179
|
-
setItem: async (key, value) => {
|
|
180
|
-
try {
|
|
181
|
-
web.setItem(key, value);
|
|
182
|
-
} catch {
|
|
183
|
-
await fallback.setItem(key, value);
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
removeItem: async (key) => {
|
|
187
|
-
try {
|
|
188
|
-
web.removeItem(key);
|
|
189
|
-
} catch {
|
|
190
|
-
}
|
|
191
|
-
await fallback.removeItem(key);
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// src/transport.ts
|
|
197
|
-
import {
|
|
198
|
-
graphqlRequest as graphqlRequest2,
|
|
199
|
-
hasErrors as hasErrors2,
|
|
200
|
-
extractErrorMessage as extractErrorMessage2,
|
|
201
|
-
isUnauthorizedError as isUnauthorizedError2
|
|
202
|
-
} from "@pylo/auth";
|
|
203
|
-
import { PyloError } from "@pylo/core";
|
|
204
|
-
function createDirectTransport(options) {
|
|
205
|
-
function send(query, variables, headers, token) {
|
|
206
|
-
return graphqlRequest2(
|
|
207
|
-
options.endpoint,
|
|
208
|
-
query,
|
|
209
|
-
variables,
|
|
210
|
-
{
|
|
211
|
-
...token !== null ? { token } : {},
|
|
212
|
-
...headers !== void 0 ? { headers } : {}
|
|
213
|
-
}
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
return async (query, variables, headers) => {
|
|
217
|
-
var _a;
|
|
218
|
-
let response = await send(query, variables, headers, await options.getToken());
|
|
219
|
-
if (isUnauthorizedError2(response) && options.onUnauthorized) {
|
|
220
|
-
const token = await options.onUnauthorized();
|
|
221
|
-
if (token !== null) {
|
|
222
|
-
response = await send(query, variables, headers, token);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (hasErrors2(response)) {
|
|
226
|
-
throw new PyloError(
|
|
227
|
-
(_a = extractErrorMessage2(response.errors)) != null ? _a : "GraphQL request failed",
|
|
228
|
-
response.errors
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
if (!response.data) {
|
|
232
|
-
throw new PyloError("No data returned from GraphQL request");
|
|
233
|
-
}
|
|
234
|
-
return response.data;
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// src/provider.tsx
|
|
239
|
-
import { jsx } from "react/jsx-runtime";
|
|
240
|
-
var PyloContext = createContext(null);
|
|
241
|
-
function usePyloContext() {
|
|
242
|
-
const value = useContext(PyloContext);
|
|
243
|
-
if (!value) {
|
|
244
|
-
throw new Error("usePylo* must be used inside <PyloProvider>");
|
|
245
|
-
}
|
|
246
|
-
return value;
|
|
247
|
-
}
|
|
248
|
-
var SIGNED_OUT = { status: "signedOut", token: null };
|
|
249
|
-
var NO_OP = () => () => {
|
|
250
|
-
};
|
|
251
|
-
function PyloProvider(props) {
|
|
252
|
-
var _a;
|
|
253
|
-
const queryClient = useQueryClient();
|
|
254
|
-
const endpoint = resolveEndpoint(props.endpoint);
|
|
255
|
-
const storeRef = useRef(null);
|
|
256
|
-
if (storeRef.current === null && !props.getToken) {
|
|
257
|
-
storeRef.current = createSessionStore({
|
|
258
|
-
endpoint,
|
|
259
|
-
storage: (_a = props.storage) != null ? _a : createLocalStorageAdapter(),
|
|
260
|
-
...props.appId !== void 0 ? { appId: props.appId } : {},
|
|
261
|
-
...props.keyPrefix !== void 0 ? { keyPrefix: props.keyPrefix } : {},
|
|
262
|
-
onSignOut: () => queryClient.clear(),
|
|
263
|
-
onSignIn: () => void queryClient.invalidateQueries({ queryKey: ["pylo"] })
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
const store = storeRef.current;
|
|
267
|
-
const state = useSyncExternalStore(
|
|
268
|
-
store ? store.subscribe : NO_OP,
|
|
269
|
-
store ? store.getState : () => SIGNED_OUT,
|
|
270
|
-
store ? store.getState : () => SIGNED_OUT
|
|
271
|
-
);
|
|
272
|
-
useEffect(() => {
|
|
273
|
-
void (store == null ? void 0 : store.init());
|
|
274
|
-
}, [store]);
|
|
275
|
-
const getTokenProp = props.getToken;
|
|
276
|
-
const getTokenRef = useRef(getTokenProp);
|
|
277
|
-
getTokenRef.current = getTokenProp;
|
|
278
|
-
const isEscapeHatch = getTokenProp !== void 0;
|
|
279
|
-
const value = useMemo(() => {
|
|
280
|
-
const getToken = isEscapeHatch ? () => getTokenRef.current() : () => store.getToken();
|
|
281
|
-
const transport = createDirectTransport({
|
|
282
|
-
endpoint,
|
|
283
|
-
getToken,
|
|
284
|
-
...store ? { onUnauthorized: () => store.refresh() } : {}
|
|
285
|
-
});
|
|
286
|
-
return { transport, endpoint, state, store, getToken };
|
|
287
|
-
}, [endpoint, state, store, isEscapeHatch]);
|
|
288
|
-
return /* @__PURE__ */ jsx(PyloContext.Provider, { value, children: props.children });
|
|
289
|
-
}
|
|
290
|
-
function usePyloTransport() {
|
|
291
|
-
return usePyloContext().transport;
|
|
292
|
-
}
|
|
293
|
-
function usePyloClient() {
|
|
294
|
-
const { endpoint, getToken } = usePyloContext();
|
|
295
|
-
return useMemo(
|
|
296
|
-
() => createPyloClient({
|
|
297
|
-
endpoint,
|
|
298
|
-
auth: async () => {
|
|
299
|
-
const token = await getToken();
|
|
300
|
-
return token !== null ? { token } : {};
|
|
301
|
-
}
|
|
302
|
-
}),
|
|
303
|
-
[endpoint, getToken]
|
|
304
|
-
);
|
|
305
|
-
}
|
|
306
|
-
function usePyloAuth() {
|
|
307
|
-
const { state, store, transport, getToken } = usePyloContext();
|
|
308
|
-
const isSignedIn = state.status === "signedIn";
|
|
309
|
-
const me = useQuery({
|
|
310
|
-
queryKey: ["pylo", "me"],
|
|
311
|
-
queryFn: async () => {
|
|
312
|
-
const data = await transport(ME_QUERY, {});
|
|
313
|
-
return data.me.current_user.data;
|
|
314
|
-
},
|
|
315
|
-
enabled: isSignedIn
|
|
316
|
-
});
|
|
317
|
-
return {
|
|
318
|
-
isLoading: state.status === "loading" || isSignedIn && me.isLoading,
|
|
319
|
-
isSignedIn,
|
|
320
|
-
user: me.data,
|
|
321
|
-
login: async (email, password) => {
|
|
322
|
-
if (!store) {
|
|
323
|
-
throw new Error("login is unavailable when PyloProvider is given getToken");
|
|
324
|
-
}
|
|
325
|
-
return store.login(email, password);
|
|
326
|
-
},
|
|
327
|
-
logout: async () => {
|
|
328
|
-
if (!store) {
|
|
329
|
-
throw new Error("logout is unavailable when PyloProvider is given getToken");
|
|
330
|
-
}
|
|
331
|
-
await store.logout();
|
|
332
|
-
},
|
|
333
|
-
getToken
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
export {
|
|
338
|
-
createSessionStore,
|
|
339
|
-
createMemoryStorage,
|
|
340
|
-
createLocalStorageAdapter,
|
|
341
|
-
createDirectTransport,
|
|
342
|
-
PyloProvider,
|
|
343
|
-
usePyloTransport,
|
|
344
|
-
usePyloClient,
|
|
345
|
-
usePyloAuth
|
|
346
|
-
};
|