@geekapps/auth-nextjs 0.21.0 → 0.24.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 +56 -2
- package/dist/actions.js +1 -10
- package/dist/actions.js.map +1 -1
- package/dist/client.d.ts +33 -2
- package/dist/client.js +17 -2
- package/dist/client.js.map +1 -1
- package/dist/connections.d.ts +101 -9
- package/dist/connections.js +313 -19
- package/dist/connections.js.map +1 -1
- package/dist/middleware.js +47 -26
- package/dist/middleware.js.map +1 -1
- package/dist/server.d.ts +20 -2
- package/dist/server.js +65 -18
- package/dist/server.js.map +1 -1
- package/dist/typegen.d.ts +42 -10
- package/dist/typegen.js +116 -15
- package/dist/typegen.js.map +1 -1
- package/package.json +8 -3
package/dist/connections.js
CHANGED
|
@@ -14,7 +14,9 @@ __export(typegen_exports, {
|
|
|
14
14
|
DEFAULT_ISSUER: () => DEFAULT_ISSUER,
|
|
15
15
|
DEFAULT_OUT_DIR: () => DEFAULT_OUT_DIR,
|
|
16
16
|
fetchCatalog: () => fetchCatalog,
|
|
17
|
-
|
|
17
|
+
fetchManifest: () => fetchManifest,
|
|
18
|
+
generateConnectionTypes: () => generateConnectionTypes,
|
|
19
|
+
generateManifestTypes: () => generateManifestTypes
|
|
18
20
|
});
|
|
19
21
|
import { mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync, existsSync } from "fs";
|
|
20
22
|
import { join, resolve } from "path";
|
|
@@ -28,13 +30,95 @@ async function fetchCatalog({ issuer, clientId, clientSecret }) {
|
|
|
28
30
|
}
|
|
29
31
|
return await response.json();
|
|
30
32
|
}
|
|
33
|
+
async function fetchManifest(manifestUrl) {
|
|
34
|
+
const response = await fetch(manifestUrl, { headers: { accept: "application/json" }, cache: "no-store" });
|
|
35
|
+
if (!response.ok) throw new Error(`manifesto indispon\xEDvel (${response.status})`);
|
|
36
|
+
const manifest = await response.json();
|
|
37
|
+
if (manifest?.version !== 1 || !manifest.scopes || !Array.isArray(manifest.routes)) {
|
|
38
|
+
throw new Error("manifesto em formato inv\xE1lido");
|
|
39
|
+
}
|
|
40
|
+
return manifest;
|
|
41
|
+
}
|
|
42
|
+
function pascal(name) {
|
|
43
|
+
return name.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join("");
|
|
44
|
+
}
|
|
45
|
+
function properties(schema) {
|
|
46
|
+
return schema?.properties ?? {};
|
|
47
|
+
}
|
|
48
|
+
function required(schema) {
|
|
49
|
+
return Array.isArray(schema?.required) ? schema.required : [];
|
|
50
|
+
}
|
|
51
|
+
function mergeInputSchema(route) {
|
|
52
|
+
const parts = [route.params, route.query, route.body];
|
|
53
|
+
const pathParams = [...route.path.matchAll(/:([A-Za-z0-9_]+)/g)].map((m) => m[1]);
|
|
54
|
+
return {
|
|
55
|
+
type: "object",
|
|
56
|
+
properties: Object.assign({}, ...parts.map(properties)),
|
|
57
|
+
required: [.../* @__PURE__ */ new Set([...pathParams, ...parts.flatMap(required)])],
|
|
58
|
+
additionalProperties: false
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async function generateManifestTypes(app, manifest) {
|
|
62
|
+
const { compile } = await import("json-schema-to-typescript");
|
|
63
|
+
const options = { bannerComment: "", additionalProperties: false, format: false, declareExternallyReferenced: true };
|
|
64
|
+
const blocks = [];
|
|
65
|
+
const routeEntries = [];
|
|
66
|
+
for (const route of manifest.routes) {
|
|
67
|
+
const base = pascal(route.route);
|
|
68
|
+
const input = `${base}Input`;
|
|
69
|
+
const output = `${base}Output`;
|
|
70
|
+
blocks.push(await compile(mergeInputSchema(route), input, options));
|
|
71
|
+
blocks.push(
|
|
72
|
+
route.response ? await compile({ ...route.response, title: void 0 }, output, options) : `export type ${output} = unknown;
|
|
73
|
+
`
|
|
74
|
+
);
|
|
75
|
+
routeEntries.push(
|
|
76
|
+
` ${JSON.stringify(route.route)}: {
|
|
77
|
+
scope: ${JSON.stringify(route.scope)};
|
|
78
|
+
method: ${JSON.stringify(route.method)};
|
|
79
|
+
path: ${JSON.stringify(route.path)};
|
|
80
|
+
input: ${input};
|
|
81
|
+
output: ${output};
|
|
82
|
+
};`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
const scopeIds = Object.keys(manifest.scopes);
|
|
86
|
+
const scopeDocs = scopeIds.map((id) => ` ${JSON.stringify(id)}: ${JSON.stringify(manifest.scopes[id].description)};`).join("\n");
|
|
87
|
+
return `${HEADER}/** Escopos que esta app aceita em conex\xF5es. */
|
|
88
|
+
export type Scope = ${scopeIds.length ? scopeIds.map((id) => JSON.stringify(id)).join(" | ") : "never"};
|
|
89
|
+
|
|
90
|
+
/** Descri\xE7\xE3o de cada escopo, como aparece no consent. */
|
|
91
|
+
export interface ScopeDescriptions {
|
|
92
|
+
${scopeDocs}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Rotas liberadas por escopo, pelo nome usado no cliente (\`post.messages.send(...)\`). */
|
|
96
|
+
export interface Routes {
|
|
97
|
+
${routeEntries.join("\n")}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface App {
|
|
101
|
+
slug: ${JSON.stringify(app.slug)};
|
|
102
|
+
targetAppId: ${JSON.stringify(app.targetAppId)};
|
|
103
|
+
scopes: Scope;
|
|
104
|
+
routes: Routes;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
${blocks.join("\n")}`;
|
|
108
|
+
}
|
|
31
109
|
async function generateOpenApiTypes(openApiUrl) {
|
|
32
110
|
const { default: openapiTS, astToString } = await import("openapi-typescript");
|
|
33
111
|
return HEADER + astToString(await openapiTS(new URL(openApiUrl)));
|
|
34
112
|
}
|
|
35
113
|
function renderIndex(apps, augment) {
|
|
36
|
-
const imports = apps.
|
|
37
|
-
|
|
114
|
+
const imports = apps.flatMap(({ app, manifest, openApi }, i) => [
|
|
115
|
+
manifest ? `import type { App as App${i} } from "./${app.slug}";` : null,
|
|
116
|
+
openApi ? `import type { paths as paths${i} } from "./${app.slug}.openapi";` : null
|
|
117
|
+
]).filter(Boolean).join("\n");
|
|
118
|
+
const members = apps.map(({ app, manifest, openApi }, i) => {
|
|
119
|
+
const fields = [manifest ? `app: App${i};` : null, openApi ? `paths: paths${i};` : null].filter(Boolean).join(" ");
|
|
120
|
+
return ` ${JSON.stringify(app.slug)}: { ${fields} };`;
|
|
121
|
+
}).join("\n");
|
|
38
122
|
return `${HEADER}${imports}
|
|
39
123
|
|
|
40
124
|
declare module ${JSON.stringify(augment)} {
|
|
@@ -52,22 +136,38 @@ async function generateConnectionTypes(params) {
|
|
|
52
136
|
const files = /* @__PURE__ */ new Map();
|
|
53
137
|
const result = { apps: [], failed: [], stale: [] };
|
|
54
138
|
const generated = [];
|
|
139
|
+
const keepExisting = (file) => {
|
|
140
|
+
const existing = join(outDir, file);
|
|
141
|
+
if (!existsSync(existing)) return false;
|
|
142
|
+
files.set(file, readFileSync(existing, "utf-8"));
|
|
143
|
+
return true;
|
|
144
|
+
};
|
|
55
145
|
for (const app of catalog) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
146
|
+
const entry = { app, manifest: false, openApi: false };
|
|
147
|
+
if (app.manifestUrl) {
|
|
148
|
+
const file = `${app.slug}.d.ts`;
|
|
149
|
+
try {
|
|
150
|
+
files.set(file, await generateManifestTypes(app, await fetchManifest(app.manifestUrl)));
|
|
151
|
+
entry.manifest = true;
|
|
152
|
+
} catch (error) {
|
|
153
|
+
result.failed.push({ name: app.name, reason: `manifesto: ${error.message}` });
|
|
154
|
+
entry.manifest = keepExisting(file);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (app.openApiUrl) {
|
|
158
|
+
const file = `${app.slug}.openapi.d.ts`;
|
|
159
|
+
try {
|
|
160
|
+
files.set(file, await generateOpenApiTypes(app.openApiUrl));
|
|
161
|
+
entry.openApi = true;
|
|
162
|
+
} catch (error) {
|
|
163
|
+
result.failed.push({ name: app.name, reason: `openapi: ${error.message}` });
|
|
164
|
+
entry.openApi = keepExisting(file);
|
|
66
165
|
}
|
|
67
166
|
}
|
|
167
|
+
if (entry.manifest || entry.openApi) generated.push(entry);
|
|
68
168
|
}
|
|
69
|
-
result.apps = generated.map((app) => app.name);
|
|
70
|
-
files.set("index.d.ts", renderIndex(generated, params.augment ??
|
|
169
|
+
result.apps = generated.map(({ app }) => app.name);
|
|
170
|
+
files.set("index.d.ts", renderIndex(generated, params.augment ?? DEFAULT_AUGMENT));
|
|
71
171
|
const current = existsSync(outDir) ? new Set(readdirSync(outDir).filter((f) => f.endsWith(".d.ts"))) : /* @__PURE__ */ new Set();
|
|
72
172
|
if (params.check) {
|
|
73
173
|
for (const [file, content] of files) {
|
|
@@ -85,12 +185,13 @@ async function generateConnectionTypes(params) {
|
|
|
85
185
|
for (const file of current) if (!files.has(file)) rmSync(join(outDir, file));
|
|
86
186
|
return result;
|
|
87
187
|
}
|
|
88
|
-
var DEFAULT_ISSUER, DEFAULT_OUT_DIR, HEADER;
|
|
188
|
+
var DEFAULT_ISSUER, DEFAULT_OUT_DIR, DEFAULT_AUGMENT, HEADER;
|
|
89
189
|
var init_typegen = __esm({
|
|
90
190
|
"src/typegen.ts"() {
|
|
91
191
|
"use strict";
|
|
92
192
|
DEFAULT_ISSUER = "https://accounts-api.geekapps.com.br";
|
|
93
193
|
DEFAULT_OUT_DIR = "geekapps-connections";
|
|
194
|
+
DEFAULT_AUGMENT = "@geekapps/auth-nextjs/connections";
|
|
94
195
|
HEADER = "// Gerado pelo SDK do Geekapps Auth. N\xE3o edite \xE0 m\xE3o.\n\n";
|
|
95
196
|
}
|
|
96
197
|
});
|
|
@@ -112,15 +213,39 @@ var GEEKAPPS_AUTH_SERVER_URL = "https://accounts-api.geekapps.com.br";
|
|
|
112
213
|
var AppConnectionError = class extends Error {
|
|
113
214
|
status;
|
|
114
215
|
code;
|
|
216
|
+
/** Código de erro como o servidor mandou (ex: "connection_inactive", "invalid_state"). */
|
|
217
|
+
reason;
|
|
218
|
+
/** Escopo que faltou, quando `code` é "missing_scope". */
|
|
219
|
+
scope;
|
|
115
220
|
body;
|
|
116
|
-
constructor(message, status,
|
|
221
|
+
constructor(message, status, reason, body) {
|
|
117
222
|
super(message);
|
|
118
223
|
this.name = "AppConnectionError";
|
|
119
224
|
this.status = status;
|
|
120
|
-
this.
|
|
225
|
+
this.reason = reason;
|
|
226
|
+
this.code = toErrorCode(status, reason);
|
|
121
227
|
this.body = body;
|
|
228
|
+
this.scope = body && typeof body === "object" && typeof body.scope === "string" ? body.scope : void 0;
|
|
122
229
|
}
|
|
123
230
|
};
|
|
231
|
+
function toErrorCode(status, reason) {
|
|
232
|
+
switch (reason) {
|
|
233
|
+
case "missing_scope":
|
|
234
|
+
case "app_connection_not_allowed":
|
|
235
|
+
return "missing_scope";
|
|
236
|
+
case "connection_expired":
|
|
237
|
+
return "connection_expired";
|
|
238
|
+
case "connection_inactive":
|
|
239
|
+
case "connection_revoked":
|
|
240
|
+
case "invalid_token":
|
|
241
|
+
case "membership_required":
|
|
242
|
+
return "connection_revoked";
|
|
243
|
+
case "network_error":
|
|
244
|
+
return "network_error";
|
|
245
|
+
}
|
|
246
|
+
if (status === 400 || status === 422) return "validation_error";
|
|
247
|
+
return "unknown";
|
|
248
|
+
}
|
|
124
249
|
function env(name) {
|
|
125
250
|
const value = process.env[name];
|
|
126
251
|
return value && value.trim().length > 0 ? value : void 0;
|
|
@@ -154,6 +279,7 @@ async function connectApp(params) {
|
|
|
154
279
|
if (!clientId) {
|
|
155
280
|
throw new Error("App Connections: defina GEEKAPPS_AUTH_CLIENT_ID \u2014 \xE9 o client_id desta app, a que pede a conex\xE3o.");
|
|
156
281
|
}
|
|
282
|
+
const targetAppId = params.targetAppId ?? await resolveAppSlug(params.app, params.config ?? {});
|
|
157
283
|
const codeVerifier = randomBytes2(64).toString("base64url");
|
|
158
284
|
const state = randomBytes2(24).toString("base64url");
|
|
159
285
|
const store = await cookies2();
|
|
@@ -170,7 +296,10 @@ async function connectApp(params) {
|
|
|
170
296
|
url.searchParams.set("state", state);
|
|
171
297
|
url.searchParams.set("code_challenge", createHash2("sha256").update(codeVerifier).digest("base64url"));
|
|
172
298
|
url.searchParams.set("code_challenge_method", "S256");
|
|
173
|
-
url.searchParams.set("target_app_id",
|
|
299
|
+
url.searchParams.set("target_app_id", targetAppId);
|
|
300
|
+
if (params.scopes && params.scopes.length > 0) {
|
|
301
|
+
url.searchParams.set("connection_scopes", [...new Set(params.scopes)].join(" "));
|
|
302
|
+
}
|
|
174
303
|
url.searchParams.set("prompt", "select_account consent");
|
|
175
304
|
if (params.displayName) url.searchParams.set("connection_display_name", params.displayName);
|
|
176
305
|
redirect2(url.toString());
|
|
@@ -222,6 +351,21 @@ async function completeAppConnection(params) {
|
|
|
222
351
|
}
|
|
223
352
|
};
|
|
224
353
|
}
|
|
354
|
+
var _catalogCache = {
|
|
355
|
+
value: null,
|
|
356
|
+
fetchedAt: 0
|
|
357
|
+
};
|
|
358
|
+
async function resolveAppSlug(slug, config) {
|
|
359
|
+
if (!_catalogCache.value || Date.now() - _catalogCache.fetchedAt > 5 * 6e4) {
|
|
360
|
+
const { issuer, clientId, clientSecret } = requireCredentials(config);
|
|
361
|
+
const { fetchCatalog: fetchCatalog2 } = await Promise.resolve().then(() => (init_typegen(), typegen_exports));
|
|
362
|
+
_catalogCache.value = await fetchCatalog2({ issuer, clientId, clientSecret });
|
|
363
|
+
_catalogCache.fetchedAt = Date.now();
|
|
364
|
+
}
|
|
365
|
+
const app = _catalogCache.value.find((item) => item.slug === slug);
|
|
366
|
+
if (!app) throw new Error(`App Connections: a app "${slug}" n\xE3o est\xE1 no cat\xE1logo do Geekapps Auth.`);
|
|
367
|
+
return app.targetAppId;
|
|
368
|
+
}
|
|
225
369
|
var _jwtCache = /* @__PURE__ */ new Map();
|
|
226
370
|
async function postToAuthServer(path, connectionToken, config) {
|
|
227
371
|
const { issuer, clientId, clientSecret } = requireCredentials(config);
|
|
@@ -309,6 +453,154 @@ async function rotateConnectionToken(params) {
|
|
|
309
453
|
_jwtCache.delete(params.connectionToken);
|
|
310
454
|
return { token: data.connection_token, expiresAt: data.expires_at };
|
|
311
455
|
}
|
|
456
|
+
var MANIFEST_PATH = "/.well-known/geekapps-app.json";
|
|
457
|
+
var MANIFEST_TTL_MS = 5 * 6e4;
|
|
458
|
+
var _manifestCache = /* @__PURE__ */ new Map();
|
|
459
|
+
async function getRuntimeManifest(baseUrl, force = false) {
|
|
460
|
+
const url = `${baseUrl.replace(/\/+$/, "")}${MANIFEST_PATH}`;
|
|
461
|
+
const cached = _manifestCache.get(url);
|
|
462
|
+
if (cached && !force && Date.now() - cached.fetchedAt < MANIFEST_TTL_MS) return cached.value;
|
|
463
|
+
try {
|
|
464
|
+
const response = await fetch(url, { headers: { accept: "application/json" }, cache: "no-store" });
|
|
465
|
+
if (!response.ok) throw new Error(`status ${response.status}`);
|
|
466
|
+
const value = await response.json();
|
|
467
|
+
if (value?.version !== 1 || !Array.isArray(value.routes)) throw new Error("formato inv\xE1lido");
|
|
468
|
+
_manifestCache.set(url, { value, fetchedAt: Date.now() });
|
|
469
|
+
return value;
|
|
470
|
+
} catch (error) {
|
|
471
|
+
if (cached) return cached.value;
|
|
472
|
+
throw new AppConnectionError(
|
|
473
|
+
`App Connections: manifesto da app alvo indispon\xEDvel em ${url} (${error.message})`,
|
|
474
|
+
0,
|
|
475
|
+
"network_error",
|
|
476
|
+
null
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
function propertyNames(schema) {
|
|
481
|
+
const properties2 = schema?.properties;
|
|
482
|
+
return properties2 && typeof properties2 === "object" ? Object.keys(properties2) : [];
|
|
483
|
+
}
|
|
484
|
+
function appendQuery(url, key, value) {
|
|
485
|
+
if (value === void 0) return;
|
|
486
|
+
if (Array.isArray(value)) {
|
|
487
|
+
for (const item of value) appendQuery(url, key, item);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
url.searchParams.append(key, value !== null && typeof value === "object" ? JSON.stringify(value) : String(value));
|
|
491
|
+
}
|
|
492
|
+
function buildRequest(baseUrl, route, input) {
|
|
493
|
+
const rest = { ...input };
|
|
494
|
+
const path = route.path.replace(/:([A-Za-z0-9_]+)/g, (_, name) => {
|
|
495
|
+
const value = rest[name];
|
|
496
|
+
delete rest[name];
|
|
497
|
+
if (value === void 0 || value === null || value === "") {
|
|
498
|
+
throw new AppConnectionError(`App Connections: falta o par\xE2metro "${name}" em ${route.route}.`, 0, "validation_error", null);
|
|
499
|
+
}
|
|
500
|
+
return encodeURIComponent(String(value));
|
|
501
|
+
});
|
|
502
|
+
const url = new URL(path.replace(/^\//, ""), `${baseUrl.replace(/\/+$/, "")}/`);
|
|
503
|
+
const method = route.method.toUpperCase();
|
|
504
|
+
const bodyless = method === "GET" || method === "DELETE" || method === "HEAD";
|
|
505
|
+
const queryFields = new Set(propertyNames(route.query));
|
|
506
|
+
const body = {};
|
|
507
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
508
|
+
if (bodyless || queryFields.has(key)) appendQuery(url, key, value);
|
|
509
|
+
else if (value !== void 0) body[key] = value;
|
|
510
|
+
}
|
|
511
|
+
const hasBody = !bodyless && (route.body !== null || Object.keys(body).length > 0);
|
|
512
|
+
return { url, method, body: hasBody ? JSON.stringify(body) : void 0 };
|
|
513
|
+
}
|
|
514
|
+
async function accessTokenFor(connectionToken, config) {
|
|
515
|
+
try {
|
|
516
|
+
return await getConnectionAccessToken({ connectionToken, config });
|
|
517
|
+
} catch (error) {
|
|
518
|
+
if (error instanceof AppConnectionError) throw error;
|
|
519
|
+
throw new AppConnectionError(`App Connections: auth-server inacess\xEDvel (${error.message})`, 0, "network_error", null);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
async function callRoute(connectionToken, options, routeName, input = {}) {
|
|
523
|
+
const config = options.config ?? {};
|
|
524
|
+
let token = await accessTokenFor(connectionToken, config);
|
|
525
|
+
const baseUrl = options.baseUrl ?? token.targetApiBaseUrl;
|
|
526
|
+
if (!baseUrl) {
|
|
527
|
+
throw new AppConnectionError("App Connections: a app alvo n\xE3o declarou apiBaseUrl \u2014 passe `baseUrl`.", 0, "unknown", null);
|
|
528
|
+
}
|
|
529
|
+
let manifest = await getRuntimeManifest(baseUrl);
|
|
530
|
+
let route = manifest.routes.find((item) => item.route === routeName);
|
|
531
|
+
if (!route) {
|
|
532
|
+
manifest = await getRuntimeManifest(baseUrl, true);
|
|
533
|
+
route = manifest.routes.find((item) => item.route === routeName);
|
|
534
|
+
}
|
|
535
|
+
if (!route) {
|
|
536
|
+
throw new AppConnectionError(`App Connections: a app alvo n\xE3o tem a rota "${routeName}".`, 404, "route_not_found", null);
|
|
537
|
+
}
|
|
538
|
+
const request = buildRequest(baseUrl, route, input);
|
|
539
|
+
for (let attempt = 0; ; attempt++) {
|
|
540
|
+
let response;
|
|
541
|
+
try {
|
|
542
|
+
response = await fetch(request.url, {
|
|
543
|
+
method: request.method,
|
|
544
|
+
headers: {
|
|
545
|
+
authorization: `Bearer ${token.accessToken}`,
|
|
546
|
+
accept: "application/json",
|
|
547
|
+
...request.body !== void 0 && { "content-type": "application/json" }
|
|
548
|
+
},
|
|
549
|
+
body: request.body,
|
|
550
|
+
cache: "no-store"
|
|
551
|
+
});
|
|
552
|
+
} catch (error) {
|
|
553
|
+
throw new AppConnectionError(`App Connections: app alvo inacess\xEDvel (${error.message})`, 0, "network_error", null);
|
|
554
|
+
}
|
|
555
|
+
if (response.status === 401 && attempt === 0) {
|
|
556
|
+
_jwtCache.delete(connectionToken);
|
|
557
|
+
token = await accessTokenFor(connectionToken, config);
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
const text = await response.text();
|
|
561
|
+
let body = null;
|
|
562
|
+
try {
|
|
563
|
+
body = text ? JSON.parse(text) : null;
|
|
564
|
+
} catch {
|
|
565
|
+
body = text;
|
|
566
|
+
}
|
|
567
|
+
if (!response.ok) {
|
|
568
|
+
const reason = errorCode(body) ?? (response.status === 401 ? "connection_revoked" : void 0);
|
|
569
|
+
throw new AppConnectionError(
|
|
570
|
+
`App Connections: ${route.route} falhou (${response.status}${reason ? ` ${reason}` : ""})`,
|
|
571
|
+
response.status,
|
|
572
|
+
reason,
|
|
573
|
+
body
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
return body ?? void 0;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
function routeProxy(call, path) {
|
|
580
|
+
return new Proxy(function() {
|
|
581
|
+
}, {
|
|
582
|
+
get(_target, property) {
|
|
583
|
+
if (typeof property !== "string" || property === "then") return void 0;
|
|
584
|
+
return routeProxy(call, [...path, property]);
|
|
585
|
+
},
|
|
586
|
+
apply(_target, _this, args) {
|
|
587
|
+
if (path.length === 0) throw new Error("App Connections: chame uma rota, ex: post.messages.send({ ... }).");
|
|
588
|
+
return call(path.join("."), args[0]);
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
function createConnections(config = {}) {
|
|
593
|
+
return new Proxy({}, {
|
|
594
|
+
get(_target, slug) {
|
|
595
|
+
if (typeof slug !== "string" || slug === "then") return void 0;
|
|
596
|
+
return (connectionToken, options = {}) => routeProxy(
|
|
597
|
+
(route, input) => callRoute(connectionToken, { config, ...options }, route, input),
|
|
598
|
+
[]
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
var connections = createConnections();
|
|
312
604
|
var TYPES_AUGMENT_MODULE = "@geekapps/auth-nextjs/connections";
|
|
313
605
|
async function syncTypes() {
|
|
314
606
|
const { issuer, clientId, clientSecret } = resolveConfig({});
|
|
@@ -331,7 +623,9 @@ export {
|
|
|
331
623
|
completeAppConnection,
|
|
332
624
|
connectApp,
|
|
333
625
|
connectionFetch,
|
|
626
|
+
connections,
|
|
334
627
|
createConnectionClient,
|
|
628
|
+
createConnections,
|
|
335
629
|
getConnectionAccessToken,
|
|
336
630
|
rotateConnectionToken
|
|
337
631
|
};
|