@econneq/gql-auth 1.2.11 → 2.0.1
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 +304 -22
- package/dist/api-factory.d.ts +11 -27
- package/dist/api-factory.d.ts.map +1 -1
- package/dist/api-factory.js +96 -43
- package/dist/api-factory.js.map +1 -0
- package/dist/authServer.d.ts +28 -1
- package/dist/authServer.d.ts.map +1 -1
- package/dist/authServer.js +66 -13
- package/dist/authServer.js.map +1 -0
- package/dist/client.d.ts +28 -11
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +75 -55
- package/dist/client.js.map +1 -0
- package/dist/env.d.ts +35 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +65 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +24 -0
- package/dist/errors.js.map +1 -0
- package/dist/functions.d.ts +21 -3
- package/dist/functions.d.ts.map +1 -1
- package/dist/functions.js +74 -26
- package/dist/functions.js.map +1 -0
- package/dist/index.d.ts +11 -50
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -6
- package/dist/index.js.map +1 -0
- package/dist/query-server.d.ts +31 -9
- package/dist/query-server.d.ts.map +1 -1
- package/dist/query-server.js +63 -11
- package/dist/query-server.js.map +1 -0
- package/dist/tenant.d.ts +21 -0
- package/dist/tenant.d.ts.map +1 -0
- package/dist/tenant.js +50 -0
- package/dist/tenant.js.map +1 -0
- package/dist/types.d.ts +124 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/upload-gql.d.ts +2 -17
- package/dist/upload-gql.d.ts.map +1 -1
- package/dist/upload-gql.js +63 -44
- package/dist/upload-gql.js.map +1 -0
- package/dist/utils.d.ts +24 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +257 -0
- package/dist/utilsGeneral.d.ts +1 -1
- package/dist/utilsGeneral.d.ts.map +1 -1
- package/package.json +49 -22
package/dist/authServer.js
CHANGED
|
@@ -1,40 +1,93 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @econneq/gql-auth — Server-side auth helpers
|
|
3
|
+
// ============================================================
|
|
4
|
+
//
|
|
5
|
+
// These helpers are Next.js-specific (they use next/headers).
|
|
6
|
+
// Import them only in Server Components, Server Actions, or
|
|
7
|
+
// Route Handlers.
|
|
8
|
+
// ─────────────────────────────────────────────────────────────
|
|
9
|
+
"use server";
|
|
10
|
+
// ─── Token ───────────────────────────────────────────────────
|
|
11
|
+
/**
|
|
12
|
+
* Read the JWT from the incoming request cookies.
|
|
13
|
+
* Returns null when no token cookie is present.
|
|
14
|
+
*/
|
|
4
15
|
export const getServerToken = async () => {
|
|
5
|
-
|
|
6
|
-
|
|
16
|
+
try {
|
|
17
|
+
const { cookies } = await import("next/headers");
|
|
18
|
+
const cookieStore = await cookies();
|
|
19
|
+
return cookieStore.get("token")?.value ?? null;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// next/headers not available outside of a Next.js context
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
7
25
|
};
|
|
26
|
+
// ─── User ─────────────────────────────────────────────────────
|
|
27
|
+
/**
|
|
28
|
+
* Decode the server-side JWT and return the payload.
|
|
29
|
+
* Returns null when no token is present or decoding fails.
|
|
30
|
+
*/
|
|
8
31
|
export const getServerUser = async () => {
|
|
9
32
|
const token = await getServerToken();
|
|
10
33
|
if (!token)
|
|
11
34
|
return null;
|
|
12
35
|
try {
|
|
13
|
-
const
|
|
14
|
-
return
|
|
36
|
+
const { jwtDecode } = await import("jwt-decode");
|
|
37
|
+
return jwtDecode(token);
|
|
15
38
|
}
|
|
16
|
-
catch
|
|
39
|
+
catch {
|
|
17
40
|
return null;
|
|
18
41
|
}
|
|
19
42
|
};
|
|
43
|
+
// ─── Permissions ─────────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* Check whether a permission list grants access to a resource.
|
|
46
|
+
*
|
|
47
|
+
* @param list - Array of permission strings (from JwtPayload.permissions)
|
|
48
|
+
* @param access - Numeric resource/module identifier
|
|
49
|
+
* @param action - Optional action suffix (e.g. "C", "R", "U", "D")
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Does the user have ANY access to module 42?
|
|
53
|
+
* getPermissions(user.permissions, 42);
|
|
54
|
+
*
|
|
55
|
+
* // Does the user have CREATE access to module 42?
|
|
56
|
+
* getPermissions(user.permissions, 42, "C");
|
|
57
|
+
*/
|
|
20
58
|
export const getPermissions = (list, access, action) => {
|
|
21
|
-
if (!list
|
|
59
|
+
if (!list?.length)
|
|
22
60
|
return false;
|
|
23
61
|
try {
|
|
24
|
-
return list.some(entry => {
|
|
25
|
-
// If only num is provided, check if entry starts with that number followed by non-digits
|
|
62
|
+
return list.some((entry) => {
|
|
26
63
|
if (access && !action) {
|
|
64
|
+
// Match "42", "42C", "42R", etc. — but NOT "420"
|
|
27
65
|
const regex = new RegExp(`^${access}(?!\\d)`);
|
|
28
66
|
return regex.test(entry);
|
|
29
67
|
}
|
|
30
|
-
// If both are provided, check for the exact combination
|
|
31
68
|
if (access && action) {
|
|
32
69
|
return entry === `${access}${action}`;
|
|
33
70
|
}
|
|
34
71
|
return false;
|
|
35
72
|
});
|
|
36
73
|
}
|
|
37
|
-
catch
|
|
74
|
+
catch {
|
|
38
75
|
return false;
|
|
39
76
|
}
|
|
40
77
|
};
|
|
78
|
+
// ─── Cookie string ────────────────────────────────────────────
|
|
79
|
+
/**
|
|
80
|
+
* Return the full cookie header string for forwarding to the
|
|
81
|
+
* backend (Django session / CSRF pass-through).
|
|
82
|
+
*/
|
|
83
|
+
export const getServerCookieString = async () => {
|
|
84
|
+
try {
|
|
85
|
+
const { cookies } = await import("next/headers");
|
|
86
|
+
const cookieStore = await cookies();
|
|
87
|
+
return cookieStore.toString();
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return "";
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=authServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authServer.js","sourceRoot":"","sources":["../src/authServer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+CAA+C;AAC/C,+DAA+D;AAC/D,EAAE;AACF,8DAA8D;AAC9D,4DAA4D;AAC5D,kBAAkB;AAClB,gEAAgE;AAEhE,YAAY,CAAC;AAIb,gEAAgE;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,IAA4B,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,OAAO,EAAE,CAAC;QACpC,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,iEAAiE;AAEjE;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,IAAgC,EAAE;IAClE,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC;IACrC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QACjD,OAAO,SAAS,CAAa,KAAK,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,gEAAgE;AAEhE;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,IAAc,EACd,MAAc,EACd,MAAe,EACN,EAAE;IACX,IAAI,CAAC,IAAI,EAAE,MAAM;QAAE,OAAO,KAAK,CAAC;IAEhC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACzB,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;gBACtB,iDAAiD;gBACjD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,MAAM,SAAS,CAAC,CAAC;gBAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;YAED,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;gBACrB,OAAO,KAAK,KAAK,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;YACxC,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,iEAAiE;AAEjE;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,IAAqB,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,OAAO,EAAE,CAAC;QACpC,OAAO,WAAW,CAAC,QAAQ,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,CAAC"}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
|
-
import { ApolloClient } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
1
|
+
import { ApolloClient } from "@apollo/client";
|
|
2
|
+
import type { ApolloOptions, ConfigType } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Inject Next.js `cookies` at app startup to keep this module
|
|
5
|
+
* free of a hard `next/headers` import (which breaks non-Next projects).
|
|
6
|
+
*
|
|
7
|
+
* Call once in your app layout or instrumentation file:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { cookies } from "next/headers";
|
|
11
|
+
* import { registerCookiesFn } from "@econneq/gql-auth";
|
|
12
|
+
* registerCookiesFn(cookies);
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function registerCookiesFn(fn: () => Promise<{
|
|
16
|
+
get: (k: string) => {
|
|
17
|
+
value: string;
|
|
18
|
+
} | undefined;
|
|
19
|
+
toString: () => string;
|
|
20
|
+
}>): void;
|
|
21
|
+
type ClientOptions = {
|
|
22
|
+
options?: ApolloOptions;
|
|
23
|
+
/** Tenant subdomain. Omit for single-tenant. */
|
|
24
|
+
domain?: string | null;
|
|
25
|
+
config: ConfigType;
|
|
26
|
+
};
|
|
27
|
+
export declare function getApolloClient({ options, domain, config, }: ClientOptions): Promise<ApolloClient>;
|
|
28
|
+
export {};
|
|
12
29
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,YAAY,EAA2B,MAAM,gBAAgB,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAazD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,OAAO,CAAC;IAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,MAAM,CAAA;CAAE,CAAC,GAC/F,IAAI,CAEN;AAID,KAAK,aAAa,GAAG;IACnB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,MAAM,EACN,MAAM,GACP,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CA4DvC"}
|
package/dist/client.js
CHANGED
|
@@ -1,65 +1,85 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @econneq/gql-auth — Apollo Client factory
|
|
3
|
+
// ============================================================
|
|
4
|
+
//
|
|
5
|
+
// • Server-side → uses internal Docker URL + cookie forwarding
|
|
6
|
+
// • Client-side → uses /api/graphql proxy + CSRF token
|
|
7
|
+
// • Multi-tenant → injects X-Tenant-ID / X-Process-ID headers
|
|
8
|
+
// • Single-tenant → falls back to Subdomains[0]
|
|
9
|
+
// ─────────────────────────────────────────────────────────────
|
|
10
|
+
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client";
|
|
11
|
+
import { Env, assertServerEnv, externalBaseUrl, externalGraphQLUrl, internalGraphQLUrl, isServer, } from "./env";
|
|
12
|
+
import { buildTenantHeaders, resolveTenant } from "./tenant";
|
|
13
|
+
let _cookiesFn = null;
|
|
14
|
+
/**
|
|
15
|
+
* Inject Next.js `cookies` at app startup to keep this module
|
|
16
|
+
* free of a hard `next/headers` import (which breaks non-Next projects).
|
|
17
|
+
*
|
|
18
|
+
* Call once in your app layout or instrumentation file:
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { cookies } from "next/headers";
|
|
22
|
+
* import { registerCookiesFn } from "@econneq/gql-auth";
|
|
23
|
+
* registerCookiesFn(cookies);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function registerCookiesFn(fn) {
|
|
27
|
+
_cookiesFn = fn;
|
|
28
|
+
}
|
|
29
|
+
export async function getApolloClient({ options, domain, config, }) {
|
|
30
|
+
const server = isServer();
|
|
31
|
+
if (server)
|
|
32
|
+
assertServerEnv();
|
|
33
|
+
// ── Tenant resolution ────────────────────────────────────
|
|
34
|
+
const tenant = resolveTenant(config, domain ? { domain } : undefined);
|
|
35
|
+
const tenantHeaders = buildTenantHeaders(tenant, Env.apiKey);
|
|
36
|
+
// ── URI ─────────────────────────────────────────────────
|
|
37
|
+
const uri = server ? internalGraphQLUrl() : externalGraphQLUrl();
|
|
38
|
+
const destUrl = server
|
|
39
|
+
? `http://${Env.backendInt}`
|
|
40
|
+
: externalBaseUrl();
|
|
41
|
+
// ── Source host (Referer / Host) ─────────────────────────
|
|
42
|
+
const sourceSubdomain = tenant?.subdomain ?? "public";
|
|
43
|
+
const sourceHost = `${Env.protocol}${sourceSubdomain}.${Env.domainUrl}`;
|
|
44
|
+
// ── CSRF ─────────────────────────────────────────────────
|
|
45
|
+
let csrfToken = options?.csrfToken ?? "";
|
|
46
|
+
if (!csrfToken && !server) {
|
|
47
|
+
try {
|
|
48
|
+
// Lazy import so SSR never executes this branch
|
|
49
|
+
const Cookies = (await import("js-cookie")).default;
|
|
50
|
+
csrfToken = Cookies.get("csrftoken") ?? "";
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// js-cookie not available in some environments
|
|
54
|
+
}
|
|
31
55
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
56
|
+
// ── Cookie forwarding (server → backend) ─────────────────
|
|
57
|
+
let cookieHeader = options?.cookie ?? "";
|
|
58
|
+
if (!cookieHeader && server && _cookiesFn) {
|
|
59
|
+
try {
|
|
60
|
+
const store = await _cookiesFn();
|
|
61
|
+
cookieHeader = store.toString();
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// cookies() may throw outside a request context
|
|
65
|
+
}
|
|
35
66
|
}
|
|
36
|
-
|
|
37
|
-
console.log("g-auth sourceHost =======", sourceHost);
|
|
38
|
-
console.log("g-auth destinationHost ==========", destUrl);
|
|
39
|
-
const csrfToken = options?.csrfToken || (!isServer ? Cookies.get("csrftoken") : "");
|
|
67
|
+
// ── Assemble headers ─────────────────────────────────────
|
|
40
68
|
const headers = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
...(
|
|
44
|
-
...(csrfToken
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
'X-Process-ID': tenant?.processId || "",
|
|
48
|
-
'X-Widget-ID': tenant?.widgetID || "",
|
|
49
|
-
}),
|
|
50
|
-
'Referer': destUrl,
|
|
51
|
-
'Host': isServer ? sourceHost : window.location.host,
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
...tenantHeaders,
|
|
71
|
+
...(cookieHeader ? { Cookie: cookieHeader } : {}),
|
|
72
|
+
...(csrfToken ? { "X-CSRFToken": csrfToken } : {}),
|
|
73
|
+
Referer: destUrl,
|
|
74
|
+
Host: server ? sourceHost : (typeof window !== "undefined" ? window.location.host : sourceHost),
|
|
52
75
|
};
|
|
53
76
|
return new ApolloClient({
|
|
54
|
-
link: new HttpLink({
|
|
55
|
-
uri,
|
|
56
|
-
fetch,
|
|
57
|
-
headers,
|
|
58
|
-
}),
|
|
77
|
+
link: new HttpLink({ uri, fetch, headers }),
|
|
59
78
|
cache: new InMemoryCache(),
|
|
60
79
|
defaultOptions: {
|
|
61
|
-
mutate: { fetchPolicy:
|
|
62
|
-
query: { fetchPolicy:
|
|
80
|
+
mutate: { fetchPolicy: "no-cache" },
|
|
81
|
+
query: { fetchPolicy: "no-cache" },
|
|
63
82
|
},
|
|
64
83
|
});
|
|
65
84
|
}
|
|
85
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,4CAA4C;AAC5C,+DAA+D;AAC/D,EAAE;AACF,gEAAgE;AAChE,wDAAwD;AACxD,8DAA8D;AAC9D,gDAAgD;AAChD,gEAAgE;AAEhE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEvE,OAAO,EACL,GAAG,EACH,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,IAAI,UAAU,GAA0G,IAAI,CAAC;AAE7H;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAgG;IAEhG,UAAU,GAAG,EAAE,CAAC;AAClB,CAAC;AAWD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EACpC,OAAO,EACP,MAAM,EACN,MAAM,GACQ;IACd,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAE1B,IAAI,MAAM;QAAE,eAAe,EAAE,CAAC;IAE9B,4DAA4D;IAC5D,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAE7D,2DAA2D;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;IACjE,MAAM,OAAO,GAAG,MAAM;QACpB,CAAC,CAAC,UAAU,GAAG,CAAC,UAAU,EAAE;QAC5B,CAAC,CAAC,eAAe,EAAE,CAAC;IAEtB,4DAA4D;IAC5D,MAAM,eAAe,GAAG,MAAM,EAAE,SAAS,IAAI,QAAQ,CAAC;IACtD,MAAM,UAAU,GAAG,GAAG,GAAG,CAAC,QAAQ,GAAG,eAAe,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;IAExE,4DAA4D;IAC5D,IAAI,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;IACzC,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,gDAAgD;YAChD,MAAM,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;YACpD,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,+CAA+C;QACjD,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,IAAI,YAAY,GAAG,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC;IACzC,IAAI,CAAC,YAAY,IAAI,MAAM,IAAI,UAAU,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,UAAU,EAAE,CAAC;YACjC,YAAY,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,gDAAgD;QAClD,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,aAAa;QAChB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;KAChG,CAAC;IAEF,OAAO,IAAI,YAAY,CAAC;QACtB,IAAI,EAAE,IAAI,QAAQ,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAC3C,KAAK,EAAE,IAAI,aAAa,EAAE;QAC1B,cAAc,EAAE;YACd,MAAM,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE;YACnC,KAAK,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE;SACnC;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare const Env: {
|
|
2
|
+
/** e.g. "e-conneq.com" */
|
|
3
|
+
readonly domainUrl: string;
|
|
4
|
+
/** e.g. "https://" */
|
|
5
|
+
readonly protocol: string;
|
|
6
|
+
/**
|
|
7
|
+
* Internal backend used from within the Docker network (server-side).
|
|
8
|
+
* e.g. "api:8000"
|
|
9
|
+
*/
|
|
10
|
+
readonly backendInt: string;
|
|
11
|
+
/**
|
|
12
|
+
* External backend reachable from the browser.
|
|
13
|
+
* e.g. "admin.e-conneq.com"
|
|
14
|
+
*/
|
|
15
|
+
readonly backendExt: string;
|
|
16
|
+
/** Optional service-to-service API key. */
|
|
17
|
+
readonly apiKey: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function assertServerEnv(): void;
|
|
20
|
+
export declare const isServer: () => boolean;
|
|
21
|
+
/**
|
|
22
|
+
* GraphQL endpoint used by server-side code (internal Docker network).
|
|
23
|
+
* e.g. http://api:8000/graphql/
|
|
24
|
+
*/
|
|
25
|
+
export declare const internalGraphQLUrl: () => string;
|
|
26
|
+
/**
|
|
27
|
+
* GraphQL endpoint used by browser code (proxied Next.js API route).
|
|
28
|
+
*/
|
|
29
|
+
export declare const externalGraphQLUrl: () => string;
|
|
30
|
+
/**
|
|
31
|
+
* Full external base URL.
|
|
32
|
+
* e.g. https://admin.e-conneq.com
|
|
33
|
+
*/
|
|
34
|
+
export declare const externalBaseUrl: () => string;
|
|
35
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,GAAG;IACd,0BAA0B;;IAG1B,sBAAsB;;IAGtB;;;OAGG;;IAGH;;;OAGG;;IAGH,2CAA2C;;CAEnC,CAAC;AAIX,wBAAgB,eAAe,IAAI,IAAI,CAWtC;AAID,eAAO,MAAM,QAAQ,QAAO,OAAwC,CAAC;AAErE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAO,MACD,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,kBAAkB,QAAO,MAAwB,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAO,MACC,CAAC"}
|
package/dist/env.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @econneq/gql-auth — Environment resolver
|
|
3
|
+
// ============================================================
|
|
4
|
+
//
|
|
5
|
+
// All env variables are consumed here so the rest of the
|
|
6
|
+
// codebase never touches process.env directly.
|
|
7
|
+
// ─────────────────────────────────────────────────────────────
|
|
8
|
+
const get = (keys) => {
|
|
9
|
+
for (const key of keys) {
|
|
10
|
+
const val = typeof process !== "undefined" ? process.env[key] : undefined;
|
|
11
|
+
if (val)
|
|
12
|
+
return val;
|
|
13
|
+
}
|
|
14
|
+
return "";
|
|
15
|
+
};
|
|
16
|
+
export const Env = {
|
|
17
|
+
/** e.g. "e-conneq.com" */
|
|
18
|
+
domainUrl: get(["NEXT_PUBLIC_DOMAIN_URL", "DOMAIN_URL"]),
|
|
19
|
+
/** e.g. "https://" */
|
|
20
|
+
protocol: get(["NEXT_PUBLIC_PROTOCOL", "PROTOCOL"]),
|
|
21
|
+
/**
|
|
22
|
+
* Internal backend used from within the Docker network (server-side).
|
|
23
|
+
* e.g. "api:8000"
|
|
24
|
+
*/
|
|
25
|
+
backendInt: get(["BACKEND_URL_INT", "NEXT_PUBLIC_BACKEND_URL_INT"]),
|
|
26
|
+
/**
|
|
27
|
+
* External backend reachable from the browser.
|
|
28
|
+
* e.g. "admin.e-conneq.com"
|
|
29
|
+
*/
|
|
30
|
+
backendExt: get(["NEXT_PUBLIC_BACKEND_URL_EXT", "BACKEND_URL_EXT"]),
|
|
31
|
+
/** Optional service-to-service API key. */
|
|
32
|
+
apiKey: get(["API_KEY", "NEXT_PUBLIC_API_KEY"]),
|
|
33
|
+
};
|
|
34
|
+
// ─── Runtime validators ───────────────────────────────────────
|
|
35
|
+
export function assertServerEnv() {
|
|
36
|
+
const missing = [];
|
|
37
|
+
if (!Env.domainUrl)
|
|
38
|
+
missing.push("DOMAIN_URL");
|
|
39
|
+
if (!Env.protocol)
|
|
40
|
+
missing.push("PROTOCOL");
|
|
41
|
+
if (!Env.backendInt)
|
|
42
|
+
missing.push("BACKEND_URL_INT");
|
|
43
|
+
if (!Env.backendExt)
|
|
44
|
+
missing.push("BACKEND_URL_EXT");
|
|
45
|
+
if (missing.length) {
|
|
46
|
+
throw new Error(`[@econneq/gql-auth] Missing required env variables: ${missing.join(", ")}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ─── URL builders ─────────────────────────────────────────────
|
|
50
|
+
export const isServer = () => typeof window === "undefined";
|
|
51
|
+
/**
|
|
52
|
+
* GraphQL endpoint used by server-side code (internal Docker network).
|
|
53
|
+
* e.g. http://api:8000/graphql/
|
|
54
|
+
*/
|
|
55
|
+
export const internalGraphQLUrl = () => `http://${Env.backendInt}/graphql/`;
|
|
56
|
+
/**
|
|
57
|
+
* GraphQL endpoint used by browser code (proxied Next.js API route).
|
|
58
|
+
*/
|
|
59
|
+
export const externalGraphQLUrl = () => `/api/graphql`;
|
|
60
|
+
/**
|
|
61
|
+
* Full external base URL.
|
|
62
|
+
* e.g. https://admin.e-conneq.com
|
|
63
|
+
*/
|
|
64
|
+
export const externalBaseUrl = () => `${Env.protocol}${Env.backendExt}`;
|
|
65
|
+
//# sourceMappingURL=env.js.map
|
package/dist/env.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,2CAA2C;AAC3C,+DAA+D;AAC/D,EAAE;AACF,yDAAyD;AACzD,+CAA+C;AAC/C,gEAAgE;AAEhE,MAAM,GAAG,GAAG,CAAC,IAAc,EAAU,EAAE;IACrC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GACP,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAE,OAAO,CAAC,GAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzE,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,0BAA0B;IAC1B,SAAS,EAAE,GAAG,CAAC,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;IAExD,sBAAsB;IACtB,QAAQ,EAAE,GAAG,CAAC,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAC;IAEnD;;;OAGG;IACH,UAAU,EAAE,GAAG,CAAC,CAAC,iBAAiB,EAAE,6BAA6B,CAAC,CAAC;IAEnE;;;OAGG;IACH,UAAU,EAAE,GAAG,CAAC,CAAC,6BAA6B,EAAE,iBAAiB,CAAC,CAAC;IAEnE,2CAA2C;IAC3C,MAAM,EAAE,GAAG,CAAC,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;CACvC,CAAC;AAEX,iEAAiE;AAEjE,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/C,IAAI,CAAC,GAAG,CAAC,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,CAAC,GAAG,CAAC,UAAU;QAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACrD,IAAI,CAAC,GAAG,CAAC,UAAU;QAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,uDAAuD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5E,CAAC;IACJ,CAAC;AACH,CAAC;AAED,iEAAiE;AAEjE,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAY,EAAE,CAAC,OAAO,MAAM,KAAK,WAAW,CAAC;AAErE;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAW,EAAE,CAC7C,UAAU,GAAG,CAAC,UAAU,WAAW,CAAC;AAEtC;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAW,EAAE,CAAC,cAAc,CAAC;AAE/D;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAW,EAAE,CAC1C,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type ParsedError = {
|
|
2
|
+
message: string;
|
|
3
|
+
code?: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Convert raw GraphQL errors into user-friendly strings.
|
|
7
|
+
* Extend the switch/map here to handle more backend error codes.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseGraphQLErrors(errors: any[]): string[];
|
|
10
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,CAY1D"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @econneq/gql-auth — GraphQL error parser
|
|
3
|
+
// ============================================================
|
|
4
|
+
/**
|
|
5
|
+
* Convert raw GraphQL errors into user-friendly strings.
|
|
6
|
+
* Extend the switch/map here to handle more backend error codes.
|
|
7
|
+
*/
|
|
8
|
+
export function parseGraphQLErrors(errors) {
|
|
9
|
+
return errors.map((err) => {
|
|
10
|
+
const msg = err?.message ?? "Unknown error";
|
|
11
|
+
if (/duplicate/i.test(msg))
|
|
12
|
+
return "Record already exists ❌";
|
|
13
|
+
if (/authentication/i.test(msg))
|
|
14
|
+
return "Login required ❌";
|
|
15
|
+
if (/permission/i.test(msg))
|
|
16
|
+
return "Permission denied ❌";
|
|
17
|
+
if (/not found/i.test(msg))
|
|
18
|
+
return "Record not found ❌";
|
|
19
|
+
if (/unique constraint/i.test(msg))
|
|
20
|
+
return "Duplicate value ❌";
|
|
21
|
+
return msg;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,2CAA2C;AAC3C,+DAA+D;AAO/D;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAa;IAC9C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAU,EAAE;QAChC,MAAM,GAAG,GAAW,GAAG,EAAE,OAAO,IAAI,eAAe,CAAC;QAEpD,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,yBAAyB,CAAC;QAC7D,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,kBAAkB,CAAC;QAC3D,IAAI,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,qBAAqB,CAAC;QAC1D,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,oBAAoB,CAAC;QACxD,IAAI,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,mBAAmB,CAAC;QAE/D,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/functions.d.ts
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
import { JwtPayload } from "./
|
|
2
|
-
|
|
1
|
+
import type { JwtPayload } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Read the JWT from cookies first, then localStorage.
|
|
4
|
+
* Returns null on the server (window is undefined).
|
|
5
|
+
*/
|
|
3
6
|
export declare const getToken: () => string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Decode the JWT and return the payload.
|
|
9
|
+
* Returns null when no token is present or decoding fails.
|
|
10
|
+
*/
|
|
4
11
|
export declare const getUser: () => JwtPayload | null;
|
|
5
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Clear all session state client-side.
|
|
14
|
+
* Does NOT call any server endpoint — combine with a Server Action
|
|
15
|
+
* or API route if you need to invalidate the session server-side.
|
|
16
|
+
*/
|
|
17
|
+
export declare const logout: () => void;
|
|
18
|
+
/**
|
|
19
|
+
* Strip null / undefined / empty-string fields from an object
|
|
20
|
+
* before sending it as GraphQL variables.
|
|
21
|
+
* File objects are always preserved.
|
|
22
|
+
*/
|
|
23
|
+
export declare const removeEmptyFields: <T extends Record<string, any>>(obj: T) => Partial<T>;
|
|
6
24
|
//# sourceMappingURL=functions.d.ts.map
|
package/dist/functions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1C;;;GAGG;AACH,eAAO,MAAM,QAAQ,QAAO,MAAM,GAAG,IAgBpC,CAAC;AAIF;;;GAGG;AACH,eAAO,MAAM,OAAO,QAAO,UAAU,GAAG,IAavC,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,MAAM,QAAO,IAezB,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7D,KAAK,CAAC,KACL,OAAO,CAAC,CAAC,CAuBX,CAAC"}
|
package/dist/functions.js
CHANGED
|
@@ -1,38 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const cookies = document.cookie.split(";");
|
|
10
|
-
for (let i = 0; i < cookies.length; i++) {
|
|
11
|
-
const cookie = cookies[i];
|
|
12
|
-
const eqPos = cookie.indexOf("=");
|
|
13
|
-
const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim();
|
|
14
|
-
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;`;
|
|
15
|
-
}
|
|
16
|
-
};
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @econneq/gql-auth — Client utilities
|
|
3
|
+
// ============================================================
|
|
4
|
+
// ─── Token ───────────────────────────────────────────────────
|
|
5
|
+
/**
|
|
6
|
+
* Read the JWT from cookies first, then localStorage.
|
|
7
|
+
* Returns null on the server (window is undefined).
|
|
8
|
+
*/
|
|
17
9
|
export const getToken = () => {
|
|
18
|
-
if (typeof window === "undefined")
|
|
10
|
+
if (typeof window === "undefined")
|
|
19
11
|
return null;
|
|
12
|
+
try {
|
|
13
|
+
// Prefer cookie (set by server on login)
|
|
14
|
+
const fromCookie = document.cookie
|
|
15
|
+
.split("; ")
|
|
16
|
+
.find((row) => row.startsWith("token="))
|
|
17
|
+
?.split("=")?.[1];
|
|
18
|
+
if (fromCookie)
|
|
19
|
+
return fromCookie;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
catch {
|
|
22
|
+
// Cookies blocked (e.g. incognito with strict settings)
|
|
23
|
+
}
|
|
24
|
+
return localStorage.getItem("token");
|
|
22
25
|
};
|
|
26
|
+
// ─── User ────────────────────────────────────────────────────
|
|
27
|
+
/**
|
|
28
|
+
* Decode the JWT and return the payload.
|
|
29
|
+
* Returns null when no token is present or decoding fails.
|
|
30
|
+
*/
|
|
23
31
|
export const getUser = () => {
|
|
24
32
|
const token = getToken();
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
if (!token)
|
|
34
|
+
return null;
|
|
35
|
+
try {
|
|
36
|
+
// jwtDecode is a peer dependency — lazy-required to keep SSR safe
|
|
37
|
+
const { jwtDecode } = require("jwt-decode");
|
|
38
|
+
return jwtDecode(token);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
// ─── Logout ──────────────────────────────────────────────────
|
|
45
|
+
/**
|
|
46
|
+
* Clear all session state client-side.
|
|
47
|
+
* Does NOT call any server endpoint — combine with a Server Action
|
|
48
|
+
* or API route if you need to invalidate the session server-side.
|
|
49
|
+
*/
|
|
50
|
+
export const logout = () => {
|
|
51
|
+
if (typeof window === "undefined")
|
|
52
|
+
return;
|
|
53
|
+
localStorage.removeItem("token");
|
|
54
|
+
// Expire the token cookie
|
|
55
|
+
document.cookie = "token=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;";
|
|
56
|
+
// Expire every other cookie for this origin
|
|
57
|
+
document.cookie.split(";").forEach((c) => {
|
|
58
|
+
const name = c.trim().split("=")?.[0];
|
|
59
|
+
if (name) {
|
|
60
|
+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;`;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
27
63
|
};
|
|
64
|
+
// ─── Data helpers ─────────────────────────────────────────────
|
|
65
|
+
/**
|
|
66
|
+
* Strip null / undefined / empty-string fields from an object
|
|
67
|
+
* before sending it as GraphQL variables.
|
|
68
|
+
* File objects are always preserved.
|
|
69
|
+
*/
|
|
28
70
|
export const removeEmptyFields = (obj) => {
|
|
29
|
-
const
|
|
71
|
+
const result = {};
|
|
30
72
|
for (const key in obj) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
73
|
+
const value = obj[key];
|
|
74
|
+
const v = value;
|
|
75
|
+
const isFile = typeof File !== "undefined" &&
|
|
76
|
+
typeof v === "object" &&
|
|
77
|
+
v !== null &&
|
|
78
|
+
v instanceof File;
|
|
79
|
+
if (isFile ||
|
|
80
|
+
(value !== null && value !== undefined && value !== "")) {
|
|
81
|
+
result[key] = value;
|
|
35
82
|
}
|
|
36
83
|
}
|
|
37
|
-
return
|
|
84
|
+
return result;
|
|
38
85
|
};
|
|
86
|
+
//# sourceMappingURL=functions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions.js","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,uCAAuC;AACvC,+DAA+D;AAI/D,gEAAgE;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAkB,EAAE;IAC1C,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAE/C,IAAI,CAAC;QACH,yCAAyC;QACzC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM;aAC/B,KAAK,CAAC,IAAI,CAAC;aACX,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YACxC,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;IAC1D,CAAC;IAED,OAAO,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,gEAAgE;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,GAAsB,EAAE;IAC7C,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,IAAI,CAAC;QACH,kEAAkE;QAClE,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,YAAY,CAEzC,CAAC;QACF,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,gEAAgE;AAEhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,GAAS,EAAE;IAC/B,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO;IAE1C,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAEjC,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,GAAG,wDAAwD,CAAC;IAE3E,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,IAAI,EAAE,CAAC;YACT,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,mDAAmD,CAAC;QAC/E,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,iEAAiE;AAEjE;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,GAAM,EACM,EAAE;IACd,MAAM,MAAM,GAAe,EAAE,CAAC;IAE9B,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAExB,MAAM,CAAC,GAAG,KAAgB,CAAC;QAE9B,MAAM,MAAM,GACV,OAAO,IAAI,KAAK,WAAW;YAC3B,OAAO,CAAC,KAAK,QAAQ;YACrB,CAAC,KAAK,IAAI;YACV,CAAC,YAAY,IAAI,CAAC;QAEhB,IACE,MAAM;YACN,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,CAAC,EACvD,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
|