@econneq/gql-auth 1.2.11 → 2.0.2

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.
Files changed (46) hide show
  1. package/README.md +293 -11
  2. package/dist/api-factory.d.ts +11 -27
  3. package/dist/api-factory.d.ts.map +1 -1
  4. package/dist/api-factory.js +96 -43
  5. package/dist/api-factory.js.map +1 -0
  6. package/dist/authServer.d.ts +29 -2
  7. package/dist/authServer.d.ts.map +1 -1
  8. package/dist/authServer.js +67 -14
  9. package/dist/authServer.js.map +1 -0
  10. package/dist/client.d.ts +28 -11
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +75 -55
  13. package/dist/client.js.map +1 -0
  14. package/dist/env.d.ts +35 -0
  15. package/dist/env.d.ts.map +1 -0
  16. package/dist/env.js +65 -0
  17. package/dist/env.js.map +1 -0
  18. package/dist/errors.d.ts +10 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +24 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/functions.d.ts +21 -3
  23. package/dist/functions.d.ts.map +1 -1
  24. package/dist/functions.js +74 -26
  25. package/dist/functions.js.map +1 -0
  26. package/dist/index.d.ts +11 -50
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +22 -6
  29. package/dist/index.js.map +1 -0
  30. package/dist/query-server.d.ts +31 -9
  31. package/dist/query-server.d.ts.map +1 -1
  32. package/dist/query-server.js +63 -11
  33. package/dist/query-server.js.map +1 -0
  34. package/dist/tenant.d.ts +21 -0
  35. package/dist/tenant.d.ts.map +1 -0
  36. package/dist/tenant.js +50 -0
  37. package/dist/tenant.js.map +1 -0
  38. package/dist/types.d.ts +124 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +5 -0
  41. package/dist/types.js.map +1 -0
  42. package/dist/upload-gql.d.ts +2 -17
  43. package/dist/upload-gql.d.ts.map +1 -1
  44. package/dist/upload-gql.js +63 -44
  45. package/dist/upload-gql.js.map +1 -0
  46. package/package.json +44 -18
package/README.md CHANGED
@@ -1,22 +1,304 @@
1
1
  # @econneq/gql-auth
2
- ![NPM Version](https://img.shields.io/npm/v/@econneq/gql-auth)
3
2
 
4
- A high-performance, multi-tenant GraphQL abstraction layer designed for **Next.js (App Router)** and **Apollo Client**.
3
+ GraphQL + Auth utilities for **multi-tenant** and **single-tenant** Next.js apps.
5
4
 
6
- This package standardizes how frontend projects interact with a Django GraphQL backend, handling tenant detection, SSR cookie forwarding, and multipart file uploads.
5
+ Handles:
6
+ - Server-side (internal Docker network) and client-side (browser proxy) GraphQL
7
+ - Multi-tenant header injection (`X-Tenant-ID`, `X-Process-ID`, `X-Widget-ID`)
8
+ - JWT auth on both server and client
9
+ - File uploads (GraphQL multipart spec)
10
+ - Batch mutations with per-item error reporting
7
11
 
8
12
  ---
9
13
 
10
- ## ✨ Features
14
+ ## Installation
11
15
 
12
- * 🌍 **Automatic Tenant Injection**: Detects subdomains and injects `X-Tenant-ID`, `X-Process-ID`, and `X-Widget-ID` headers.
13
- * 🔐 **SSR Ready**: Built-in support for `next/headers` to forward authentication cookies during Server-Side Rendering.
14
- * 📁 **Smart File Uploads**: Simplifies `multipart/form-data` logic for GraphQL mutations.
15
- * 🚀 **Lightweight**: Optimized to use peer dependencies, keeping your bundle size minimal.
16
+ ```bash
17
+ npm install @econneq/gql-auth
18
+ ```
19
+
20
+ ### Peer dependencies
21
+
22
+ ```bash
23
+ npm install @apollo/client graphql next react
24
+ ```
16
25
 
17
26
  ---
18
27
 
19
- ## 📦 Installation
28
+ ## Environment Variables
20
29
 
21
- ```bash
22
- npm install @econneq/gql-auth
30
+ | Variable | Side | Description |
31
+ |---|---|---|
32
+ | `DOMAIN_URL` | server | Base domain, e.g. `e-conneq.com` |
33
+ | `PROTOCOL` | server | e.g. `https://` |
34
+ | `BACKEND_URL_INT` | server | Internal Docker URL, e.g. `api:8000` |
35
+ | `BACKEND_URL_EXT` | server | External backend host, e.g. `admin.e-conneq.com` |
36
+ | `NEXT_PUBLIC_DOMAIN_URL` | both | Same as DOMAIN_URL (client-accessible) |
37
+ | `NEXT_PUBLIC_PROTOCOL` | both | Same as PROTOCOL (client-accessible) |
38
+ | `NEXT_PUBLIC_BACKEND_URL_EXT` | both | Same as BACKEND_URL_EXT (client-accessible) |
39
+ | `API_KEY` | server | Optional service-to-service key |
40
+
41
+ > The internal URL (`BACKEND_URL_INT`) is **never** exposed to the browser.
42
+ > Client-side mutations route through Next.js `/api/graphql` proxy.
43
+
44
+ ---
45
+
46
+ ## Config Object
47
+
48
+ Every function accepts a `config` object describing your tenants.
49
+
50
+ ```ts
51
+ // config.ts (shared across your project)
52
+ import type { ConfigType } from "@econneq/gql-auth";
53
+
54
+ export const config: ConfigType = {
55
+ Subdomains: [
56
+ { id: 1, subdomain: "acme", processId: "proc-1", widgetID: "wgt-1" },
57
+ { id: 2, subdomain: "globex", processId: "proc-2" },
58
+ ],
59
+ };
60
+ ```
61
+
62
+ **Single-tenant**: put one entry in `Subdomains`. The library will always use it
63
+ without requiring a `domain` parameter.
64
+
65
+ ---
66
+
67
+ ## Quick start
68
+
69
+ ### 1. Register the cookie helper (Next.js app)
70
+
71
+ In your root layout (`app/layout.tsx`) or instrumentation file:
72
+
73
+ ```ts
74
+ import { cookies } from "next/headers";
75
+ import { registerCookiesFn } from "@econneq/gql-auth";
76
+
77
+ registerCookiesFn(cookies);
78
+ ```
79
+
80
+ This lets the Apollo client forward cookies server-side without a hard
81
+ `next/headers` import inside the package.
82
+
83
+ ---
84
+
85
+ ### 2. Server-side query (Server Component / Route Handler)
86
+
87
+ ```ts
88
+ import { queryServerGraphQL } from "@econneq/gql-auth";
89
+ import { config } from "@/config";
90
+ import { GET_USERS } from "@/graphql/queries";
91
+
92
+ // Multi-tenant
93
+ const data = await queryServerGraphQL({
94
+ query: GET_USERS,
95
+ variables: { active: true },
96
+ domain: "acme", // ← matches Subdomains[].subdomain
97
+ config,
98
+ });
99
+
100
+ // Single-tenant (omit domain)
101
+ const data = await queryServerGraphQL({
102
+ query: GET_USERS,
103
+ config,
104
+ });
105
+ ```
106
+
107
+ ### 3. Server-side mutation (Server Action)
108
+
109
+ ```ts
110
+ "use server";
111
+ import { mutateServerGraphQL } from "@econneq/gql-auth";
112
+
113
+ const result = await mutateServerGraphQL({
114
+ query: CREATE_USER_MUTATION,
115
+ variables: { input: formData },
116
+ domain: params.domain,
117
+ config,
118
+ });
119
+ ```
120
+
121
+ ---
122
+
123
+ ### 4. Client-side mutation with ApiFactory
124
+
125
+ ```tsx
126
+ "use client";
127
+ import { ApiFactory, getToken } from "@econneq/gql-auth";
128
+ import { useRouter } from "next/navigation";
129
+ import { config } from "@/config";
130
+
131
+ export function MyForm({ params }: { params: { domain: string } }) {
132
+ const router = useRouter();
133
+
134
+ const handleSubmit = async (formData: any) => {
135
+ await ApiFactory({
136
+ newData: formData,
137
+ mutationName: "createUser",
138
+ modelName: "user",
139
+ successField: "username",
140
+ query: CREATE_USER_MUTATION,
141
+ params: { domain: params.domain }, // omit for single-tenant
142
+ config,
143
+ router,
144
+ token: getToken() ?? undefined,
145
+ onAlert: ({ title, status }) => {
146
+ // Connect to your toast/alert system
147
+ console.log(title, status);
148
+ },
149
+ redirect: true,
150
+ redirectPath: "/dashboard",
151
+ });
152
+ };
153
+
154
+ return <form onSubmit={...}>...</form>;
155
+ }
156
+ ```
157
+
158
+ #### Batch mutations
159
+
160
+ Pass an array to `newData`:
161
+
162
+ ```ts
163
+ await ApiFactory({
164
+ newData: [item1, item2, item3],
165
+ mutationName: "createProduct",
166
+ modelName: "product",
167
+ // ...
168
+ });
169
+ ```
170
+
171
+ #### File uploads
172
+
173
+ ```ts
174
+ await ApiFactory({
175
+ newData: formData,
176
+ getFileMap: (item) => ({ avatar: item.avatarFile }),
177
+ // ...
178
+ });
179
+ ```
180
+
181
+ #### Return data instead of alert
182
+
183
+ ```ts
184
+ const user = await ApiFactory<{ id: string; username: string }>({
185
+ returnResponseObject: true,
186
+ // ...
187
+ });
188
+ ```
189
+
190
+ ---
191
+
192
+ ### 5. Direct upload mutation
193
+
194
+ For full control over multipart uploads:
195
+
196
+ ```ts
197
+ import { uploadGraphQLMutation } from "@econneq/gql-auth";
198
+
199
+ const response = await uploadGraphQLMutation({
200
+ query: UPLOAD_DOCUMENT_MUTATION.loc!.source.body,
201
+ variables: { title: "Report", file: null },
202
+ fileMap: { file: selectedFile },
203
+ params: { domain: "acme" },
204
+ config,
205
+ token: userToken,
206
+ });
207
+ ```
208
+
209
+ ---
210
+
211
+ ### 6. Auth utilities
212
+
213
+ #### Client-side
214
+
215
+ ```ts
216
+ import { getToken, getUser, logout } from "@econneq/gql-auth";
217
+
218
+ const token = getToken(); // cookie → localStorage
219
+ const user = getUser(); // decoded JwtPayload
220
+ logout(); // clears cookies + localStorage
221
+ ```
222
+
223
+ #### Server-side
224
+
225
+ ```ts
226
+ import {
227
+ getServerToken,
228
+ getServerUser,
229
+ getPermissions,
230
+ } from "@econneq/gql-auth";
231
+
232
+ const token = await getServerToken();
233
+ const user = await getServerUser();
234
+
235
+ // Does the user have any access to module 42?
236
+ const canRead = getPermissions(user?.permissions ?? [], 42);
237
+
238
+ // Does the user have CREATE access to module 42?
239
+ const canCreate = getPermissions(user?.permissions ?? [], 42, "C");
240
+ ```
241
+
242
+ ---
243
+
244
+ ### 7. Apollo client (advanced)
245
+
246
+ Direct access when you need a custom query/mutation outside ApiFactory:
247
+
248
+ ```ts
249
+ import { getApolloClient } from "@econneq/gql-auth";
250
+
251
+ const client = await getApolloClient({
252
+ domain: "acme", // omit for single-tenant
253
+ config,
254
+ });
255
+
256
+ const { data } = await client.query({ query: MY_QUERY });
257
+ ```
258
+
259
+ ---
260
+
261
+ ## Architecture
262
+
263
+ ```
264
+ Browser Next.js Server Backend (Docker)
265
+ ───────── ────────────── ────────────────
266
+ uploadGraphQLMutation ──► /api/graphql (proxy) ──► api:8000/graphql/
267
+ ApiFactory ──► /api/graphql (proxy) ──► api:8000/graphql/
268
+
269
+ queryServerGraphQL ────────────────────────────► http://api:8000/graphql/
270
+ mutateServerGraphQL ────────────────────────────► http://api:8000/graphql/
271
+ getApolloClient ────────────────────────────► http://api:8000/graphql/
272
+ ```
273
+
274
+ Server-side calls skip the proxy entirely and hit the backend directly
275
+ through Docker's internal network — faster and no public exposure.
276
+
277
+ ---
278
+
279
+ ## Permissions format
280
+
281
+ Permission strings encode resource + action:
282
+
283
+ ```
284
+ "42" → access resource 42 (any action)
285
+ "42C" → create on resource 42
286
+ "42R" → read on resource 42
287
+ "42U" → update on resource 42
288
+ "42D" → delete on resource 42
289
+ ```
290
+
291
+ ---
292
+
293
+ ## Changelog
294
+
295
+ ### 2.0.0
296
+ - Centralised env resolution (`env.ts`)
297
+ - Tenant resolution separated into `tenant.ts` — single-tenant fallback
298
+ - `mutateServerGraphQL` added (server-side mutations)
299
+ - `ApiFactory` typed generics, batch partial-error reporting
300
+ - `registerCookiesFn` removes hard `next/headers` dependency
301
+ - `getServerCookieString` helper exported
302
+ - `parseGraphQLErrors` exported for custom use
303
+ - Subdomains[0] fallback for single-tenant setups
304
+ - `uploadGraphQLMutation` no longer throws on missing tenant in single-tenant mode
@@ -1,28 +1,12 @@
1
- type SubmitOptions = {
2
- newData: any;
3
- editData?: any;
4
- mutationName: string;
5
- modelName: string;
6
- successField?: string;
7
- query: any;
8
- params: any;
9
- router: any;
10
- token?: string;
11
- config: {
12
- Subdomains: any[];
13
- };
14
- onAlert: (options: {
15
- title: string;
16
- status: boolean;
17
- duration: number;
18
- }) => void;
19
- redirect?: boolean;
20
- redirectPath?: string;
21
- returnResponseField?: boolean;
22
- returnResponseObject?: boolean;
23
- reload?: boolean;
24
- getFileMap?: (item: any) => Record<string, File>;
25
- };
26
- export declare const ApiFactory: (options: SubmitOptions) => Promise<any>;
27
- export {};
1
+ import type { ApiFactoryOptions } from "./types";
2
+ /**
3
+ * Run one or more GraphQL mutations and handle the full
4
+ * response → alert / redirect / reload lifecycle.
5
+ *
6
+ * @returns
7
+ * - `returnResponseObject = true` → the raw mutation response object
8
+ * - `returnResponseField = true` → the value of `successField` from result
9
+ * - Otherwise → `void` (triggers alert + reload/redirect)
10
+ */
11
+ export declare function ApiFactory<T = any>(options: ApiFactoryOptions): Promise<T | void>;
28
12
  //# sourceMappingURL=api-factory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-factory.d.ts","sourceRoot":"","sources":["../src/api-factory.ts"],"names":[],"mappings":"AAIA,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,GAAG,CAAC;IACX,MAAM,EAAE,GAAG,CAAC;IACZ,MAAM,EAAE,GAAG,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE;QACN,UAAU,EAAE,GAAG,EAAE,CAAC;KACnB,CAAC;IACF,OAAO,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAClD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,SAAS,aAAa,iBAyDtD,CAAC"}
1
+ {"version":3,"file":"api-factory.d.ts","sourceRoot":"","sources":["../src/api-factory.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAiBjD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,CAAC,GAAG,GAAG,EACtC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CA8GnB"}
@@ -1,66 +1,119 @@
1
- import { removeEmptyFields } from "./functions.js";
2
- import { uploadGraphQLMutation } from "./upload-gql.js";
3
- export const ApiFactory = async (options) => {
4
- const { newData, editData, mutationName, modelName, successField = "title", query, router, params, reload = true, redirect, redirectPath, returnResponseField = false, returnResponseObject = false, getFileMap, token, config, onAlert } = options;
5
- const items = Array.isArray(newData || editData) ? (newData || editData) : [(newData || editData)];
1
+ // ============================================================
2
+ // @econneq/gql-auth ApiFactory
3
+ // ============================================================
4
+ //
5
+ // Client-side orchestrator for GraphQL mutations.
6
+ //
7
+ // Features
8
+ // ─────────
9
+ // • Single item or batch (array) mutations in one call
10
+ // • File uploads via multipart (getFileMap)
11
+ // • Multi-tenant and single-tenant support
12
+ // • Typed overloads for returnResponseField / returnResponseObject
13
+ // • Granular alert feedback for partial batch failures
14
+ // • Automatic token resolution (prop → cookie → localStorage)
15
+ // ─────────────────────────────────────────────────────────────
16
+ import { uploadGraphQLMutation } from "./upload-gql";
17
+ import { parseGraphQLErrors } from "./errors";
18
+ import { removeEmptyFields, getToken } from "./functions";
19
+ // ─── Internal helpers ────────────────────────────────────────
20
+ function resolveToken(token) {
21
+ if (token)
22
+ return token;
23
+ if (typeof window !== "undefined") {
24
+ return getToken() ?? undefined;
25
+ }
26
+ return undefined;
27
+ }
28
+ // ─── Main ────────────────────────────────────────────────────
29
+ /**
30
+ * Run one or more GraphQL mutations and handle the full
31
+ * response → alert / redirect / reload lifecycle.
32
+ *
33
+ * @returns
34
+ * - `returnResponseObject = true` → the raw mutation response object
35
+ * - `returnResponseField = true` → the value of `successField` from result
36
+ * - Otherwise → `void` (triggers alert + reload/redirect)
37
+ */
38
+ export async function ApiFactory(options) {
39
+ const { newData, editData, mutationName, modelName, successField = "title", query, router, params, reload = true, redirect, redirectPath, returnResponseField = false, returnResponseObject = false, getFileMap, config, onAlert, } = options;
40
+ const token = resolveToken(options.token);
41
+ // Support single item or batch array
42
+ const source = newData ?? editData;
43
+ const items = Array.isArray(source) ? source : [source];
6
44
  const successMessages = [];
7
45
  const errorMessages = [];
8
46
  let responseFieldData = null;
9
- for (const res of items) {
47
+ // ── Batch loop ─────────────────────────────────────────
48
+ for (const item of items) {
10
49
  try {
50
+ const cleanVariables = removeEmptyFields(item);
11
51
  const response = await uploadGraphQLMutation({
12
- query: query.loc?.source.body || "",
13
- variables: removeEmptyFields(res),
14
- fileMap: getFileMap ? getFileMap(res) : {},
52
+ query: query?.loc?.source?.body ?? query,
53
+ variables: cleanVariables,
54
+ fileMap: getFileMap ? getFileMap(item) : {},
15
55
  params,
16
56
  token,
17
57
  config,
18
58
  });
19
- const result = response?.data?.[mutationName]?.[modelName];
20
- if (response?.data?.[mutationName]) {
21
- successMessages.push(result?.[successField] || "operation successful ✅");
22
- if (returnResponseObject)
23
- responseFieldData = response.data[mutationName];
24
- if (result?.id && returnResponseField)
59
+ // ── Parse success ──────────────────────────────────
60
+ const mutationPayload = response?.data?.[mutationName];
61
+ if (mutationPayload !== undefined) {
62
+ const result = mutationPayload?.[modelName];
63
+ const label = result?.[successField] ?? "Operation successful ✅";
64
+ successMessages.push(label);
65
+ if (returnResponseObject) {
66
+ responseFieldData = mutationPayload;
67
+ }
68
+ else if (returnResponseField && result?.id) {
25
69
  responseFieldData = result[successField];
26
- if (result?.id || result?.token || result === null) {
27
70
  }
28
71
  }
29
- // Error Handling
30
- if (response?.errors) {
31
- handleGraphQLErrors(response.errors, errorMessages);
72
+ // ── Parse GraphQL errors ───────────────────────────
73
+ if (response?.errors?.length) {
74
+ errorMessages.push(...parseGraphQLErrors(response.errors));
32
75
  }
33
76
  }
34
77
  catch (err) {
35
- errorMessages.push(`Error: ${err.message}`);
78
+ errorMessages.push(`Network error: ${err?.message ?? "Unknown"}`);
36
79
  }
37
80
  }
38
- // Handle Response/UI Logic
39
- if (successMessages.length > 0 && errorMessages.length === 0) {
40
- if (returnResponseObject || returnResponseField)
41
- return responseFieldData;
42
- onAlert({ title: "successfully submitted ✅", status: true, duration: 3000 });
43
- if (redirect && redirectPath)
44
- router.push(redirectPath);
45
- else if (reload)
46
- window.location.reload();
81
+ // ── Response / UI logic ────────────────────────────────
82
+ const hasSuccess = successMessages.length > 0;
83
+ const hasErrors = errorMessages.length > 0;
84
+ // Partial batch: some succeeded, some failed
85
+ if (hasSuccess && hasErrors) {
86
+ onAlert({
87
+ title: `⚠️ Partial success:\n${successMessages.join(", ")}\n\nErrors:\n${errorMessages.join("\n")}`,
88
+ status: false,
89
+ duration: 6000,
90
+ });
91
+ return;
47
92
  }
48
- else if (errorMessages.length > 0) {
93
+ if (hasErrors) {
49
94
  onAlert({
50
95
  title: `❌ Errors:\n${errorMessages.join("\n")}`,
51
96
  status: false,
52
- duration: 5000
97
+ duration: 5000,
53
98
  });
99
+ return;
100
+ }
101
+ if (hasSuccess) {
102
+ // Return data when caller wants it
103
+ if (returnResponseObject || returnResponseField) {
104
+ return responseFieldData;
105
+ }
106
+ onAlert({
107
+ title: `Successfully submitted ✅`,
108
+ status: true,
109
+ duration: 3000,
110
+ });
111
+ if (redirect && redirectPath && router) {
112
+ router.push(redirectPath);
113
+ }
114
+ else if (reload && typeof window !== "undefined") {
115
+ window.location.reload();
116
+ }
54
117
  }
55
- };
56
- // Internal Helper for Error Parsing
57
- const handleGraphQLErrors = (errors, errorList) => {
58
- errors.forEach(error => {
59
- if (error.message.includes("duplicate"))
60
- errorList.push("Record Already Exists ❌");
61
- else if (error.message.includes("Authentication"))
62
- errorList.push("Login Required ❌");
63
- else
64
- errorList.push(error.message);
65
- });
66
- };
118
+ }
119
+ //# sourceMappingURL=api-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-factory.js","sourceRoot":"","sources":["../src/api-factory.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,32 @@
1
- import { JwtPayload } from "./index.js";
1
+ import type { JwtPayload } from "./types";
2
+ /**
3
+ * Read the JWT from the incoming request cookies.
4
+ * Returns null when no token cookie is present.
5
+ */
2
6
  export declare const getServerToken: () => Promise<string | null>;
7
+ /**
8
+ * Decode the server-side JWT and return the payload.
9
+ * Returns null when no token is present or decoding fails.
10
+ */
3
11
  export declare const getServerUser: () => Promise<JwtPayload | null>;
4
- export declare const getPermissions: (list: string[], access: number, action?: string) => boolean;
12
+ /**
13
+ * Check whether a permission list grants access to a resource.
14
+ *
15
+ * @param list - Array of permission strings (from JwtPayload.permissions)
16
+ * @param access - Numeric resource/module identifier
17
+ * @param action - Optional action suffix (e.g. "C", "R", "U", "D")
18
+ *
19
+ * @example
20
+ * // Does the user have ANY access to module 42?
21
+ * getPermissions(user.permissions, 42);
22
+ *
23
+ * // Does the user have CREATE access to module 42?
24
+ * getPermissions(user.permissions, 42, "C");
25
+ */
26
+ export declare const getPermissions: (list: string[], access: number, action?: string) => Promise<boolean>;
27
+ /**
28
+ * Return the full cookie header string for forwarding to the
29
+ * backend (Django session / CSRF pass-through).
30
+ */
31
+ export declare const getServerCookieString: () => Promise<string>;
5
32
  //# sourceMappingURL=authServer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"authServer.d.ts","sourceRoot":"","sources":["../src/authServer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,eAAO,MAAM,cAAc,8BAG1B,CAAC;AAEF,eAAO,MAAM,aAAa,kCAUzB,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,EAAE,QAAQ,MAAM,EAAE,SAAS,MAAM,YAqB7E,CAAC"}
1
+ {"version":3,"file":"authServer.d.ts","sourceRoot":"","sources":["../src/authServer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1C;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAa,OAAO,CAAC,MAAM,GAAG,IAAI,CAS5D,CAAC;AAIF;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,UAAU,GAAG,IAAI,CAU/D,CAAC;AAIF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EAAE,EACd,QAAQ,MAAM,EACd,SAAS,MAAM,KACd,OAAO,CAAC,OAAO,CAoBjB,CAAC;AAIF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAa,OAAO,CAAC,MAAM,CAQ5D,CAAC"}