naystack 1.8.3 → 1.8.5
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/auth/client.cjs.js +18 -8
- package/dist/auth/client.d.mts +1 -0
- package/dist/auth/client.d.ts +1 -0
- package/dist/auth/client.esm.js +24 -8
- package/dist/auth/email/client.cjs.js +18 -8
- package/dist/auth/email/client.d.mts +2 -1
- package/dist/auth/email/client.d.ts +2 -1
- package/dist/auth/email/client.esm.js +24 -8
- package/dist/auth/email/index.cjs.js +4 -2
- package/dist/auth/email/index.d.mts +1 -0
- package/dist/auth/email/index.d.ts +1 -0
- package/dist/auth/email/index.esm.js +4 -2
- package/dist/auth/email/next.d.mts +1 -0
- package/dist/auth/email/next.d.ts +1 -0
- package/dist/auth/email/routes/delete.cjs.js +4 -2
- package/dist/auth/email/routes/delete.esm.js +4 -2
- package/dist/auth/email/routes/get.cjs.js +4 -2
- package/dist/auth/email/routes/get.esm.js +4 -2
- package/dist/auth/email/routes/post.cjs.js +4 -2
- package/dist/auth/email/routes/post.esm.js +4 -2
- package/dist/auth/email/routes/put.cjs.js +4 -2
- package/dist/auth/email/routes/put.esm.js +4 -2
- package/dist/auth/email/token.cjs.js +4 -2
- package/dist/auth/email/token.d.mts +2 -2
- package/dist/auth/email/token.d.ts +2 -2
- package/dist/auth/email/token.esm.js +4 -2
- package/dist/auth/google/get.cjs.js +3 -1
- package/dist/auth/google/get.esm.js +3 -1
- package/dist/auth/google/index.cjs.js +3 -1
- package/dist/auth/google/index.esm.js +3 -1
- package/dist/auth/index.cjs.js +4 -2
- package/dist/auth/index.d.mts +1 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.esm.js +4 -2
- package/dist/auth/token-store.cjs.js +120 -0
- package/dist/auth/token-store.d.mts +42 -0
- package/dist/auth/token-store.d.ts +42 -0
- package/dist/auth/token-store.esm.js +90 -0
- package/dist/graphql/client.cjs.js +77 -31
- package/dist/graphql/client.esm.js +69 -24
- package/dist/graphql/links.cjs.js +126 -0
- package/dist/graphql/links.d.mts +14 -0
- package/dist/graphql/links.d.ts +14 -0
- package/dist/graphql/links.esm.js +101 -0
- package/dist/graphql/next.cjs.js +67 -21
- package/dist/graphql/next.esm.js +67 -21
- package/package.json +6 -1
package/dist/auth/index.d.mts
CHANGED
package/dist/auth/index.d.ts
CHANGED
package/dist/auth/index.esm.js
CHANGED
|
@@ -104,11 +104,13 @@ function getEnv(key, skipCheck) {
|
|
|
104
104
|
// src/auth/email/token.ts
|
|
105
105
|
function generateAccessToken(id) {
|
|
106
106
|
return sign({ id }, getEnv("SIGNING_KEY" /* SIGNING_KEY */), {
|
|
107
|
-
expiresIn: "
|
|
107
|
+
expiresIn: "24h"
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
110
|
function generateRefreshToken(id) {
|
|
111
|
-
return sign({ id }, getEnv("REFRESH_KEY" /* REFRESH_KEY */)
|
|
111
|
+
return sign({ id }, getEnv("REFRESH_KEY" /* REFRESH_KEY */), {
|
|
112
|
+
expiresIn: "365d"
|
|
113
|
+
});
|
|
112
114
|
}
|
|
113
115
|
function getTokenizedResponse(id) {
|
|
114
116
|
const accessToken = id ? generateAccessToken(id) : void 0;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/auth/token-store.ts
|
|
21
|
+
var token_store_exports = {};
|
|
22
|
+
__export(token_store_exports, {
|
|
23
|
+
getAccessToken: () => getAccessToken,
|
|
24
|
+
refreshAccessToken: () => refreshAccessToken,
|
|
25
|
+
setAccessToken: () => setAccessToken,
|
|
26
|
+
subscribeToAccessToken: () => subscribeToAccessToken
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(token_store_exports);
|
|
29
|
+
|
|
30
|
+
// src/env.ts
|
|
31
|
+
var EXTRA_ENV = globalThis.__NAYSTACK_ENV__ || (globalThis.__NAYSTACK_ENV__ = {});
|
|
32
|
+
var getEnvValue = (key) => {
|
|
33
|
+
switch (key) {
|
|
34
|
+
case "NEXT_PUBLIC_GRAPHQL_ENDPOINT" /* NEXT_PUBLIC_GRAPHQL_ENDPOINT */:
|
|
35
|
+
return process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT || EXTRA_ENV.GRAPHQL_ENDPOINT;
|
|
36
|
+
case "NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT" /* NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT */:
|
|
37
|
+
return process.env.NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT || EXTRA_ENV.EMAIL_AUTH_ENDPOINT;
|
|
38
|
+
case "NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT" /* NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT */:
|
|
39
|
+
return process.env.NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT || EXTRA_ENV.GOOGLE_AUTH_ENDPOINT;
|
|
40
|
+
case "NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */:
|
|
41
|
+
return process.env.NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT || EXTRA_ENV.INSTAGRAM_AUTH_ENDPOINT;
|
|
42
|
+
case "NEXT_PUBLIC_FILE_ENDPOINT" /* NEXT_PUBLIC_FILE_ENDPOINT */:
|
|
43
|
+
return process.env.NEXT_PUBLIC_FILE_ENDPOINT || EXTRA_ENV.FILE_ENDPOINT;
|
|
44
|
+
case "NEXT_PUBLIC_BASE_URL" /* NEXT_PUBLIC_BASE_URL */:
|
|
45
|
+
return process.env.NEXT_PUBLIC_BASE_URL || EXTRA_ENV.BASE_URL;
|
|
46
|
+
case "REFRESH_KEY" /* REFRESH_KEY */:
|
|
47
|
+
return process.env.REFRESH_KEY;
|
|
48
|
+
case "SIGNING_KEY" /* SIGNING_KEY */:
|
|
49
|
+
return process.env.SIGNING_KEY;
|
|
50
|
+
case "INSTAGRAM_CLIENT_SECRET" /* INSTAGRAM_CLIENT_SECRET */:
|
|
51
|
+
return process.env.INSTAGRAM_CLIENT_SECRET;
|
|
52
|
+
case "INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */:
|
|
53
|
+
return process.env.INSTAGRAM_CLIENT_ID;
|
|
54
|
+
case "GOOGLE_CLIENT_SECRET" /* GOOGLE_CLIENT_SECRET */:
|
|
55
|
+
return process.env.GOOGLE_CLIENT_SECRET;
|
|
56
|
+
case "GOOGLE_CLIENT_ID" /* GOOGLE_CLIENT_ID */:
|
|
57
|
+
return process.env.GOOGLE_CLIENT_ID;
|
|
58
|
+
case "TURNSTILE_KEY" /* TURNSTILE_KEY */:
|
|
59
|
+
return process.env.TURNSTILE_KEY;
|
|
60
|
+
case "S3_ACCESS_KEY_ID" /* S3_ACCESS_KEY_ID */:
|
|
61
|
+
return process.env.S3_ACCESS_KEY_ID;
|
|
62
|
+
case "S3_ACCESS_KEY_SECRET" /* S3_ACCESS_KEY_SECRET */:
|
|
63
|
+
return process.env.S3_ACCESS_KEY_SECRET;
|
|
64
|
+
case "S3_REGION" /* S3_REGION */:
|
|
65
|
+
return process.env.S3_REGION;
|
|
66
|
+
case "S3_BUCKET" /* S3_BUCKET */:
|
|
67
|
+
return process.env.S3_BUCKET;
|
|
68
|
+
case "NODE_ENV" /* NODE_ENV */:
|
|
69
|
+
return process.env.NODE_ENV;
|
|
70
|
+
default:
|
|
71
|
+
return process.env[key];
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
function getEnv(key, skipCheck) {
|
|
75
|
+
const value = getEnvValue(key);
|
|
76
|
+
if (!skipCheck && !value) throw new Error(`${key} is not defined`);
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/auth/token-store.ts
|
|
81
|
+
var currentToken;
|
|
82
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
83
|
+
var inFlightRefresh = null;
|
|
84
|
+
function getAccessToken() {
|
|
85
|
+
return currentToken;
|
|
86
|
+
}
|
|
87
|
+
function setAccessToken(token) {
|
|
88
|
+
if (token === currentToken) return;
|
|
89
|
+
currentToken = token;
|
|
90
|
+
listeners.forEach((listener) => listener(token));
|
|
91
|
+
}
|
|
92
|
+
function subscribeToAccessToken(listener) {
|
|
93
|
+
listeners.add(listener);
|
|
94
|
+
return () => {
|
|
95
|
+
listeners.delete(listener);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function refreshAccessToken() {
|
|
99
|
+
if (inFlightRefresh) return inFlightRefresh;
|
|
100
|
+
inFlightRefresh = (async () => {
|
|
101
|
+
const res = await fetch(
|
|
102
|
+
getEnv("NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT" /* NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT */),
|
|
103
|
+
{ credentials: "include" }
|
|
104
|
+
);
|
|
105
|
+
if (!res.ok) throw new Error(`Token refresh failed: ${res.status}`);
|
|
106
|
+
const token = await res.text() || null;
|
|
107
|
+
setAccessToken(token);
|
|
108
|
+
return token;
|
|
109
|
+
})().finally(() => {
|
|
110
|
+
inFlightRefresh = null;
|
|
111
|
+
});
|
|
112
|
+
return inFlightRefresh;
|
|
113
|
+
}
|
|
114
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
115
|
+
0 && (module.exports = {
|
|
116
|
+
getAccessToken,
|
|
117
|
+
refreshAccessToken,
|
|
118
|
+
setAccessToken,
|
|
119
|
+
subscribeToAccessToken
|
|
120
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the current access token synchronously, outside React.
|
|
3
|
+
* Used by the Apollo auth link; components should use `useToken()`.
|
|
4
|
+
*
|
|
5
|
+
* @returns The access token, `null` when logged out, or `undefined` before the first fetch resolves.
|
|
6
|
+
* @category Auth
|
|
7
|
+
*/
|
|
8
|
+
declare function getAccessToken(): string | null | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Writes the access token and notifies subscribers (which updates `TokenContext`).
|
|
11
|
+
*
|
|
12
|
+
* @param token - New token, or `null` to clear the session.
|
|
13
|
+
* @category Auth
|
|
14
|
+
*/
|
|
15
|
+
declare function setAccessToken(token: string | null | undefined): void;
|
|
16
|
+
/**
|
|
17
|
+
* Subscribes to token changes. `AuthWrapper` uses this to mirror the store into React state.
|
|
18
|
+
*
|
|
19
|
+
* @param listener - Called with the new token on every change.
|
|
20
|
+
* @returns Unsubscribe function.
|
|
21
|
+
* @category Auth
|
|
22
|
+
*/
|
|
23
|
+
declare function subscribeToAccessToken(listener: (token: string | null | undefined) => void): () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Exchanges the httpOnly refresh cookie for a fresh access token via the auth endpoint,
|
|
26
|
+
* and stores the result. Concurrent callers share one request.
|
|
27
|
+
*
|
|
28
|
+
* The auth endpoint answers 200 in both directions, so the body is the signal:
|
|
29
|
+
* a token means the session is alive, an empty body means the refresh cookie is
|
|
30
|
+
* gone or expired and the user is logged out (which clears the token, and in turn
|
|
31
|
+
* trips `ClearStoreOnLogout`).
|
|
32
|
+
*
|
|
33
|
+
* A transport failure (offline, 5xx) rejects **without** clearing the token — a
|
|
34
|
+
* flaky network shouldn't end a valid session.
|
|
35
|
+
*
|
|
36
|
+
* @returns The new access token, or `null` if the session has ended.
|
|
37
|
+
* @throws If the request fails at the transport level or the endpoint returns non-2xx.
|
|
38
|
+
* @category Auth
|
|
39
|
+
*/
|
|
40
|
+
declare function refreshAccessToken(): Promise<string | null>;
|
|
41
|
+
|
|
42
|
+
export { getAccessToken, refreshAccessToken, setAccessToken, subscribeToAccessToken };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the current access token synchronously, outside React.
|
|
3
|
+
* Used by the Apollo auth link; components should use `useToken()`.
|
|
4
|
+
*
|
|
5
|
+
* @returns The access token, `null` when logged out, or `undefined` before the first fetch resolves.
|
|
6
|
+
* @category Auth
|
|
7
|
+
*/
|
|
8
|
+
declare function getAccessToken(): string | null | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Writes the access token and notifies subscribers (which updates `TokenContext`).
|
|
11
|
+
*
|
|
12
|
+
* @param token - New token, or `null` to clear the session.
|
|
13
|
+
* @category Auth
|
|
14
|
+
*/
|
|
15
|
+
declare function setAccessToken(token: string | null | undefined): void;
|
|
16
|
+
/**
|
|
17
|
+
* Subscribes to token changes. `AuthWrapper` uses this to mirror the store into React state.
|
|
18
|
+
*
|
|
19
|
+
* @param listener - Called with the new token on every change.
|
|
20
|
+
* @returns Unsubscribe function.
|
|
21
|
+
* @category Auth
|
|
22
|
+
*/
|
|
23
|
+
declare function subscribeToAccessToken(listener: (token: string | null | undefined) => void): () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Exchanges the httpOnly refresh cookie for a fresh access token via the auth endpoint,
|
|
26
|
+
* and stores the result. Concurrent callers share one request.
|
|
27
|
+
*
|
|
28
|
+
* The auth endpoint answers 200 in both directions, so the body is the signal:
|
|
29
|
+
* a token means the session is alive, an empty body means the refresh cookie is
|
|
30
|
+
* gone or expired and the user is logged out (which clears the token, and in turn
|
|
31
|
+
* trips `ClearStoreOnLogout`).
|
|
32
|
+
*
|
|
33
|
+
* A transport failure (offline, 5xx) rejects **without** clearing the token — a
|
|
34
|
+
* flaky network shouldn't end a valid session.
|
|
35
|
+
*
|
|
36
|
+
* @returns The new access token, or `null` if the session has ended.
|
|
37
|
+
* @throws If the request fails at the transport level or the endpoint returns non-2xx.
|
|
38
|
+
* @category Auth
|
|
39
|
+
*/
|
|
40
|
+
declare function refreshAccessToken(): Promise<string | null>;
|
|
41
|
+
|
|
42
|
+
export { getAccessToken, refreshAccessToken, setAccessToken, subscribeToAccessToken };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// src/env.ts
|
|
2
|
+
var EXTRA_ENV = globalThis.__NAYSTACK_ENV__ || (globalThis.__NAYSTACK_ENV__ = {});
|
|
3
|
+
var getEnvValue = (key) => {
|
|
4
|
+
switch (key) {
|
|
5
|
+
case "NEXT_PUBLIC_GRAPHQL_ENDPOINT" /* NEXT_PUBLIC_GRAPHQL_ENDPOINT */:
|
|
6
|
+
return process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT || EXTRA_ENV.GRAPHQL_ENDPOINT;
|
|
7
|
+
case "NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT" /* NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT */:
|
|
8
|
+
return process.env.NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT || EXTRA_ENV.EMAIL_AUTH_ENDPOINT;
|
|
9
|
+
case "NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT" /* NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT */:
|
|
10
|
+
return process.env.NEXT_PUBLIC_GOOGLE_AUTH_ENDPOINT || EXTRA_ENV.GOOGLE_AUTH_ENDPOINT;
|
|
11
|
+
case "NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */:
|
|
12
|
+
return process.env.NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT || EXTRA_ENV.INSTAGRAM_AUTH_ENDPOINT;
|
|
13
|
+
case "NEXT_PUBLIC_FILE_ENDPOINT" /* NEXT_PUBLIC_FILE_ENDPOINT */:
|
|
14
|
+
return process.env.NEXT_PUBLIC_FILE_ENDPOINT || EXTRA_ENV.FILE_ENDPOINT;
|
|
15
|
+
case "NEXT_PUBLIC_BASE_URL" /* NEXT_PUBLIC_BASE_URL */:
|
|
16
|
+
return process.env.NEXT_PUBLIC_BASE_URL || EXTRA_ENV.BASE_URL;
|
|
17
|
+
case "REFRESH_KEY" /* REFRESH_KEY */:
|
|
18
|
+
return process.env.REFRESH_KEY;
|
|
19
|
+
case "SIGNING_KEY" /* SIGNING_KEY */:
|
|
20
|
+
return process.env.SIGNING_KEY;
|
|
21
|
+
case "INSTAGRAM_CLIENT_SECRET" /* INSTAGRAM_CLIENT_SECRET */:
|
|
22
|
+
return process.env.INSTAGRAM_CLIENT_SECRET;
|
|
23
|
+
case "INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */:
|
|
24
|
+
return process.env.INSTAGRAM_CLIENT_ID;
|
|
25
|
+
case "GOOGLE_CLIENT_SECRET" /* GOOGLE_CLIENT_SECRET */:
|
|
26
|
+
return process.env.GOOGLE_CLIENT_SECRET;
|
|
27
|
+
case "GOOGLE_CLIENT_ID" /* GOOGLE_CLIENT_ID */:
|
|
28
|
+
return process.env.GOOGLE_CLIENT_ID;
|
|
29
|
+
case "TURNSTILE_KEY" /* TURNSTILE_KEY */:
|
|
30
|
+
return process.env.TURNSTILE_KEY;
|
|
31
|
+
case "S3_ACCESS_KEY_ID" /* S3_ACCESS_KEY_ID */:
|
|
32
|
+
return process.env.S3_ACCESS_KEY_ID;
|
|
33
|
+
case "S3_ACCESS_KEY_SECRET" /* S3_ACCESS_KEY_SECRET */:
|
|
34
|
+
return process.env.S3_ACCESS_KEY_SECRET;
|
|
35
|
+
case "S3_REGION" /* S3_REGION */:
|
|
36
|
+
return process.env.S3_REGION;
|
|
37
|
+
case "S3_BUCKET" /* S3_BUCKET */:
|
|
38
|
+
return process.env.S3_BUCKET;
|
|
39
|
+
case "NODE_ENV" /* NODE_ENV */:
|
|
40
|
+
return process.env.NODE_ENV;
|
|
41
|
+
default:
|
|
42
|
+
return process.env[key];
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
function getEnv(key, skipCheck) {
|
|
46
|
+
const value = getEnvValue(key);
|
|
47
|
+
if (!skipCheck && !value) throw new Error(`${key} is not defined`);
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/auth/token-store.ts
|
|
52
|
+
var currentToken;
|
|
53
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
54
|
+
var inFlightRefresh = null;
|
|
55
|
+
function getAccessToken() {
|
|
56
|
+
return currentToken;
|
|
57
|
+
}
|
|
58
|
+
function setAccessToken(token) {
|
|
59
|
+
if (token === currentToken) return;
|
|
60
|
+
currentToken = token;
|
|
61
|
+
listeners.forEach((listener) => listener(token));
|
|
62
|
+
}
|
|
63
|
+
function subscribeToAccessToken(listener) {
|
|
64
|
+
listeners.add(listener);
|
|
65
|
+
return () => {
|
|
66
|
+
listeners.delete(listener);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function refreshAccessToken() {
|
|
70
|
+
if (inFlightRefresh) return inFlightRefresh;
|
|
71
|
+
inFlightRefresh = (async () => {
|
|
72
|
+
const res = await fetch(
|
|
73
|
+
getEnv("NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT" /* NEXT_PUBLIC_EMAIL_AUTH_ENDPOINT */),
|
|
74
|
+
{ credentials: "include" }
|
|
75
|
+
);
|
|
76
|
+
if (!res.ok) throw new Error(`Token refresh failed: ${res.status}`);
|
|
77
|
+
const token = await res.text() || null;
|
|
78
|
+
setAccessToken(token);
|
|
79
|
+
return token;
|
|
80
|
+
})().finally(() => {
|
|
81
|
+
inFlightRefresh = null;
|
|
82
|
+
});
|
|
83
|
+
return inFlightRefresh;
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
getAccessToken,
|
|
87
|
+
refreshAccessToken,
|
|
88
|
+
setAccessToken,
|
|
89
|
+
subscribeToAccessToken
|
|
90
|
+
};
|
|
@@ -37,10 +37,35 @@ __export(client_exports, {
|
|
|
37
37
|
useAuthQuery: () => useAuthQuery
|
|
38
38
|
});
|
|
39
39
|
module.exports = __toCommonJS(client_exports);
|
|
40
|
-
var
|
|
41
|
-
var
|
|
40
|
+
var import_client4 = require("@apollo/client");
|
|
41
|
+
var import_client5 = require("naystack/auth/client");
|
|
42
42
|
var import_react2 = __toESM(require("react"));
|
|
43
43
|
|
|
44
|
+
// src/graphql/clear-store.tsx
|
|
45
|
+
var import_client = require("@apollo/client");
|
|
46
|
+
var import_client2 = require("naystack/auth/client");
|
|
47
|
+
var import_react = require("react");
|
|
48
|
+
function ClearStoreOnLogout() {
|
|
49
|
+
const client = (0, import_client.useApolloClient)();
|
|
50
|
+
const token = (0, import_client2.useToken)();
|
|
51
|
+
const hadToken = (0, import_react.useRef)(false);
|
|
52
|
+
(0, import_react.useEffect)(() => {
|
|
53
|
+
if (token) {
|
|
54
|
+
hadToken.current = true;
|
|
55
|
+
} else if (token === null && hadToken.current) {
|
|
56
|
+
hadToken.current = false;
|
|
57
|
+
void client.clearStore();
|
|
58
|
+
}
|
|
59
|
+
}, [client, token]);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/graphql/links.ts
|
|
64
|
+
var import_client3 = require("@apollo/client");
|
|
65
|
+
var import_context = require("@apollo/client/link/context");
|
|
66
|
+
var import_error = require("@apollo/client/link/error");
|
|
67
|
+
var import_token_store = require("naystack/auth/token-store");
|
|
68
|
+
|
|
44
69
|
// src/env.ts
|
|
45
70
|
var EXTRA_ENV = globalThis.__NAYSTACK_ENV__ || (globalThis.__NAYSTACK_ENV__ = {});
|
|
46
71
|
var getEnvValue = (key) => {
|
|
@@ -91,32 +116,54 @@ function getEnv(key, skipCheck) {
|
|
|
91
116
|
return value;
|
|
92
117
|
}
|
|
93
118
|
|
|
94
|
-
// src/graphql/
|
|
95
|
-
var
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const token = (0,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
// src/graphql/links.ts
|
|
120
|
+
var RETRY_CONTEXT_KEY = "__naystackRetried";
|
|
121
|
+
function isExpiredTokenError(error) {
|
|
122
|
+
return error.extensions?.code === "UNAUTHENTICATED";
|
|
123
|
+
}
|
|
124
|
+
var authLink = (0, import_context.setContext)((_, previousContext) => {
|
|
125
|
+
const token = (0, import_token_store.getAccessToken)();
|
|
126
|
+
if (!token || previousContext.credentials === "include")
|
|
127
|
+
return previousContext;
|
|
128
|
+
return {
|
|
129
|
+
...previousContext,
|
|
130
|
+
headers: {
|
|
131
|
+
...previousContext.headers,
|
|
132
|
+
authorization: `Bearer ${token}`
|
|
133
|
+
},
|
|
134
|
+
credentials: "omit"
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
var refreshLink = (0, import_error.onError)(({ graphQLErrors, operation, forward }) => {
|
|
138
|
+
if (!graphQLErrors?.some(isExpiredTokenError)) return;
|
|
139
|
+
if (operation.getContext()[RETRY_CONTEXT_KEY]) return;
|
|
140
|
+
return (0, import_client3.fromPromise)(
|
|
141
|
+
// A failed refresh still replays once: the retry reproduces the original
|
|
142
|
+
// error for the caller instead of surfacing the refresh's error in its place.
|
|
143
|
+
(0, import_token_store.refreshAccessToken)().catch(() => null)
|
|
144
|
+
).flatMap(() => {
|
|
145
|
+
operation.setContext((previousContext) => ({
|
|
146
|
+
...previousContext,
|
|
147
|
+
[RETRY_CONTEXT_KEY]: true
|
|
148
|
+
}));
|
|
149
|
+
return forward(operation);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
function makeAuthLink() {
|
|
153
|
+
return import_client3.ApolloLink.from([
|
|
154
|
+
refreshLink,
|
|
155
|
+
authLink,
|
|
156
|
+
new import_client3.HttpLink({
|
|
157
|
+
uri: getEnv("NEXT_PUBLIC_GRAPHQL_ENDPOINT" /* NEXT_PUBLIC_GRAPHQL_ENDPOINT */)
|
|
158
|
+
})
|
|
159
|
+
]);
|
|
111
160
|
}
|
|
112
161
|
|
|
113
162
|
// src/graphql/client.tsx
|
|
114
163
|
function makeClient(cacheConfig) {
|
|
115
|
-
return new
|
|
116
|
-
cache: new
|
|
117
|
-
link:
|
|
118
|
-
uri: getEnv("NEXT_PUBLIC_GRAPHQL_ENDPOINT" /* NEXT_PUBLIC_GRAPHQL_ENDPOINT */)
|
|
119
|
-
})
|
|
164
|
+
return new import_client4.ApolloClient({
|
|
165
|
+
cache: new import_client4.InMemoryCache(cacheConfig),
|
|
166
|
+
link: makeAuthLink()
|
|
120
167
|
});
|
|
121
168
|
}
|
|
122
169
|
var ApolloWrapper = ({
|
|
@@ -125,7 +172,7 @@ var ApolloWrapper = ({
|
|
|
125
172
|
}) => {
|
|
126
173
|
const clientRef = (0, import_react2.useRef)(null);
|
|
127
174
|
if (!clientRef.current) clientRef.current = makeClient(cacheConfig);
|
|
128
|
-
return /* @__PURE__ */ import_react2.default.createElement(
|
|
175
|
+
return /* @__PURE__ */ import_react2.default.createElement(import_client4.ApolloProvider, { client: clientRef.current }, /* @__PURE__ */ import_react2.default.createElement(ClearStoreOnLogout, null), children);
|
|
129
176
|
};
|
|
130
177
|
var tokenContext = (token) => {
|
|
131
178
|
if (!token) return void 0;
|
|
@@ -137,7 +184,7 @@ var tokenContext = (token) => {
|
|
|
137
184
|
};
|
|
138
185
|
};
|
|
139
186
|
function useAuthQuery(query, variables, options) {
|
|
140
|
-
const [fetch, result] = (0,
|
|
187
|
+
const [fetch, result] = (0, import_client4.useLazyQuery)(query, {
|
|
141
188
|
fetchPolicy: "no-cache",
|
|
142
189
|
...options
|
|
143
190
|
});
|
|
@@ -168,15 +215,14 @@ function useAuthQuery(query, variables, options) {
|
|
|
168
215
|
return [reFetch, result];
|
|
169
216
|
}
|
|
170
217
|
function useAuthMutation(mutation, options) {
|
|
171
|
-
const token = (0,
|
|
172
|
-
const [mutate, result] = (0,
|
|
218
|
+
const token = (0, import_client5.useToken)();
|
|
219
|
+
const [mutate, result] = (0, import_client4.useMutation)(mutation, options);
|
|
173
220
|
const method = (0, import_react2.useCallback)(
|
|
174
221
|
(input) => mutate({
|
|
175
222
|
// @ts-expect-error -- to allow dynamic props
|
|
176
|
-
variables: { input }
|
|
177
|
-
context: tokenContext(token)
|
|
223
|
+
variables: { input }
|
|
178
224
|
}),
|
|
179
|
-
[
|
|
225
|
+
[mutate]
|
|
180
226
|
);
|
|
181
227
|
return [method, { ...result, hasAuth: !!token }];
|
|
182
228
|
}
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import {
|
|
5
5
|
ApolloClient,
|
|
6
6
|
ApolloProvider,
|
|
7
|
-
HttpLink,
|
|
8
7
|
InMemoryCache,
|
|
9
8
|
useLazyQuery,
|
|
10
9
|
useMutation
|
|
@@ -16,6 +15,31 @@ import React, {
|
|
|
16
15
|
useRef as useRef2
|
|
17
16
|
} from "react";
|
|
18
17
|
|
|
18
|
+
// src/graphql/clear-store.tsx
|
|
19
|
+
import { useApolloClient } from "@apollo/client";
|
|
20
|
+
import { useToken } from "naystack/auth/client";
|
|
21
|
+
import { useEffect, useRef } from "react";
|
|
22
|
+
function ClearStoreOnLogout() {
|
|
23
|
+
const client = useApolloClient();
|
|
24
|
+
const token = useToken();
|
|
25
|
+
const hadToken = useRef(false);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (token) {
|
|
28
|
+
hadToken.current = true;
|
|
29
|
+
} else if (token === null && hadToken.current) {
|
|
30
|
+
hadToken.current = false;
|
|
31
|
+
void client.clearStore();
|
|
32
|
+
}
|
|
33
|
+
}, [client, token]);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/graphql/links.ts
|
|
38
|
+
import { ApolloLink, fromPromise, HttpLink } from "@apollo/client";
|
|
39
|
+
import { setContext } from "@apollo/client/link/context";
|
|
40
|
+
import { onError } from "@apollo/client/link/error";
|
|
41
|
+
import { getAccessToken, refreshAccessToken } from "naystack/auth/token-store";
|
|
42
|
+
|
|
19
43
|
// src/env.ts
|
|
20
44
|
var EXTRA_ENV = globalThis.__NAYSTACK_ENV__ || (globalThis.__NAYSTACK_ENV__ = {});
|
|
21
45
|
var getEnvValue = (key) => {
|
|
@@ -66,32 +90,54 @@ function getEnv(key, skipCheck) {
|
|
|
66
90
|
return value;
|
|
67
91
|
}
|
|
68
92
|
|
|
69
|
-
// src/graphql/
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const token =
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
93
|
+
// src/graphql/links.ts
|
|
94
|
+
var RETRY_CONTEXT_KEY = "__naystackRetried";
|
|
95
|
+
function isExpiredTokenError(error) {
|
|
96
|
+
return error.extensions?.code === "UNAUTHENTICATED";
|
|
97
|
+
}
|
|
98
|
+
var authLink = setContext((_, previousContext) => {
|
|
99
|
+
const token = getAccessToken();
|
|
100
|
+
if (!token || previousContext.credentials === "include")
|
|
101
|
+
return previousContext;
|
|
102
|
+
return {
|
|
103
|
+
...previousContext,
|
|
104
|
+
headers: {
|
|
105
|
+
...previousContext.headers,
|
|
106
|
+
authorization: `Bearer ${token}`
|
|
107
|
+
},
|
|
108
|
+
credentials: "omit"
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
var refreshLink = onError(({ graphQLErrors, operation, forward }) => {
|
|
112
|
+
if (!graphQLErrors?.some(isExpiredTokenError)) return;
|
|
113
|
+
if (operation.getContext()[RETRY_CONTEXT_KEY]) return;
|
|
114
|
+
return fromPromise(
|
|
115
|
+
// A failed refresh still replays once: the retry reproduces the original
|
|
116
|
+
// error for the caller instead of surfacing the refresh's error in its place.
|
|
117
|
+
refreshAccessToken().catch(() => null)
|
|
118
|
+
).flatMap(() => {
|
|
119
|
+
operation.setContext((previousContext) => ({
|
|
120
|
+
...previousContext,
|
|
121
|
+
[RETRY_CONTEXT_KEY]: true
|
|
122
|
+
}));
|
|
123
|
+
return forward(operation);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
function makeAuthLink() {
|
|
127
|
+
return ApolloLink.from([
|
|
128
|
+
refreshLink,
|
|
129
|
+
authLink,
|
|
130
|
+
new HttpLink({
|
|
131
|
+
uri: getEnv("NEXT_PUBLIC_GRAPHQL_ENDPOINT" /* NEXT_PUBLIC_GRAPHQL_ENDPOINT */)
|
|
132
|
+
})
|
|
133
|
+
]);
|
|
86
134
|
}
|
|
87
135
|
|
|
88
136
|
// src/graphql/client.tsx
|
|
89
137
|
function makeClient(cacheConfig) {
|
|
90
138
|
return new ApolloClient({
|
|
91
139
|
cache: new InMemoryCache(cacheConfig),
|
|
92
|
-
link:
|
|
93
|
-
uri: getEnv("NEXT_PUBLIC_GRAPHQL_ENDPOINT" /* NEXT_PUBLIC_GRAPHQL_ENDPOINT */)
|
|
94
|
-
})
|
|
140
|
+
link: makeAuthLink()
|
|
95
141
|
});
|
|
96
142
|
}
|
|
97
143
|
var ApolloWrapper = ({
|
|
@@ -148,10 +194,9 @@ function useAuthMutation(mutation, options) {
|
|
|
148
194
|
const method = useCallback(
|
|
149
195
|
(input) => mutate({
|
|
150
196
|
// @ts-expect-error -- to allow dynamic props
|
|
151
|
-
variables: { input }
|
|
152
|
-
context: tokenContext(token)
|
|
197
|
+
variables: { input }
|
|
153
198
|
}),
|
|
154
|
-
[
|
|
199
|
+
[mutate]
|
|
155
200
|
);
|
|
156
201
|
return [method, { ...result, hasAuth: !!token }];
|
|
157
202
|
}
|