@qelos/integrator-next 4.0.1 → 4.1.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/dist/context.d.ts +5 -11
- package/dist/context.js +63 -43
- package/dist/context.js.map +1 -1
- package/dist/cookies.d.ts +19 -0
- package/dist/cookies.js +39 -0
- package/dist/cookies.js.map +1 -0
- package/dist/env-config.d.ts +3 -3
- package/dist/env-config.js +6 -7
- package/dist/env-config.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/me-client.d.ts +15 -0
- package/dist/me-client.js +35 -0
- package/dist/me-client.js.map +1 -0
- package/dist/middleware.d.ts +10 -34
- package/dist/middleware.js +75 -80
- package/dist/middleware.js.map +1 -1
- package/dist/pages.d.ts +5 -9
- package/dist/pages.js +61 -98
- package/dist/pages.js.map +1 -1
- package/dist/proxy-target.d.ts +17 -0
- package/dist/proxy-target.js +26 -0
- package/dist/proxy-target.js.map +1 -0
- package/dist/runtime/api-proxy.d.ts +16 -0
- package/dist/runtime/api-proxy.js +90 -0
- package/dist/runtime/api-proxy.js.map +1 -0
- package/dist/sdk-factory.d.ts +13 -16
- package/dist/sdk-factory.js +29 -79
- package/dist/sdk-factory.js.map +1 -1
- package/dist/types.d.ts +28 -16
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
package/dist/middleware.js
CHANGED
|
@@ -1,43 +1,25 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
|
+
import { rewriteSetCookieDomain } from './cookies';
|
|
2
3
|
import { applyQelosForwardHeaders } from './forward-headers';
|
|
3
4
|
import { getDefaultQelosConfig } from './env-config';
|
|
5
|
+
import { fetchMeIdentity } from './me-client';
|
|
6
|
+
import { resolveQelosProxyTarget } from './proxy-target';
|
|
4
7
|
import { createRequestSdk } from './sdk-factory';
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const authHeader = req.headers.get('authorization');
|
|
13
|
-
const headerAccess = authHeader && authHeader.toLowerCase().startsWith('bearer ')
|
|
14
|
-
? authHeader.slice(7).trim()
|
|
15
|
-
: undefined;
|
|
16
|
-
return {
|
|
17
|
-
accessToken: headerAccess || cookieAccess || undefined,
|
|
18
|
-
refreshToken: cookieRefresh || undefined,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
function stagePendingCookies(pending, config, tokens) {
|
|
22
|
-
const accessCookie = config.accessTokenCookie || DEFAULT_ACCESS_COOKIE;
|
|
23
|
-
const refreshCookie = config.refreshTokenCookie || DEFAULT_REFRESH_COOKIE;
|
|
24
|
-
const secure = !/^http:\/\//i.test(config.appUrl);
|
|
25
|
-
const options = {
|
|
26
|
-
httpOnly: true,
|
|
27
|
-
secure,
|
|
28
|
-
sameSite: 'lax',
|
|
29
|
-
path: '/',
|
|
30
|
-
};
|
|
31
|
-
pending.push({ name: accessCookie, value: tokens.accessToken, options });
|
|
32
|
-
if (tokens.refreshToken) {
|
|
33
|
-
pending.push({ name: refreshCookie, value: tokens.refreshToken, options });
|
|
8
|
+
function mergeProxySkipPaths(config) {
|
|
9
|
+
const merged = [...(config.skipPaths ?? [])];
|
|
10
|
+
if (config.disableProxy !== true) {
|
|
11
|
+
const hasApiPrefix = merged.some((p) => p === '/api' || p === '/api/' || p.startsWith('/api/'));
|
|
12
|
+
if (!hasApiPrefix) {
|
|
13
|
+
merged.unshift('/api/');
|
|
14
|
+
}
|
|
34
15
|
}
|
|
16
|
+
return merged.length ? merged : undefined;
|
|
35
17
|
}
|
|
36
|
-
function shouldSkip(req,
|
|
37
|
-
if (!
|
|
18
|
+
function shouldSkip(req, skipPaths) {
|
|
19
|
+
if (!skipPaths?.length)
|
|
38
20
|
return false;
|
|
39
21
|
const path = req.nextUrl.pathname;
|
|
40
|
-
return
|
|
22
|
+
return skipPaths.some((prefix) => path.startsWith(prefix));
|
|
41
23
|
}
|
|
42
24
|
function unauthorized() {
|
|
43
25
|
return new NextResponse(JSON.stringify({ code: 'UNAUTHORIZED' }), {
|
|
@@ -47,72 +29,85 @@ function unauthorized() {
|
|
|
47
29
|
}
|
|
48
30
|
/**
|
|
49
31
|
* Create a Next.js (App Router) edge middleware that identifies the user and
|
|
50
|
-
* the active workspace via
|
|
51
|
-
* application's own handler. Resolved identity
|
|
52
|
-
* handlers via request headers (`x-qelos-user-id`,
|
|
53
|
-
* use `getQelosContext()` from
|
|
54
|
-
* full user / workspace objects
|
|
32
|
+
* the active workspace via a same-origin BFF round-trip to Qelos `GET /api/me`
|
|
33
|
+
* before the request reaches the application's own handler. Resolved identity
|
|
34
|
+
* is forwarded to downstream handlers via request headers (`x-qelos-user-id`,
|
|
35
|
+
* `x-qelos-workspace-id`); use `getQelosContext()` from
|
|
36
|
+
* `@qelos/integrator-next/context` to obtain the full user / workspace objects
|
|
37
|
+
* inside server components or route handlers.
|
|
55
38
|
*/
|
|
56
39
|
export function createQelosMiddleware(options) {
|
|
57
40
|
const { config, resolveWorkspace } = options;
|
|
58
|
-
const
|
|
59
|
-
(async ({ target, newTokens }) => {
|
|
60
|
-
stagePendingCookies(target.pendingCookies, config, newTokens);
|
|
61
|
-
});
|
|
41
|
+
const skipPathsEffective = mergeProxySkipPaths(config);
|
|
62
42
|
return async function qelosMiddleware(req) {
|
|
63
|
-
if (shouldSkip(req,
|
|
43
|
+
if (shouldSkip(req, skipPathsEffective)) {
|
|
64
44
|
return NextResponse.next();
|
|
65
45
|
}
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const sdk = createRequestSdk({
|
|
70
|
-
config,
|
|
71
|
-
tokens,
|
|
72
|
-
refreshTarget: { req, pendingCookies },
|
|
73
|
-
onTokenRefresh,
|
|
46
|
+
const getHeaders = () => ({
|
|
47
|
+
cookie: req.headers.get('cookie') ?? undefined,
|
|
48
|
+
authorization: req.headers.get('authorization') ?? undefined,
|
|
74
49
|
});
|
|
75
|
-
const
|
|
50
|
+
const sdk = createRequestSdk({ config, getHeaders });
|
|
51
|
+
const base = resolveQelosProxyTarget(config);
|
|
52
|
+
if (!base && !config.apiToken) {
|
|
53
|
+
if (config.requireAuth) {
|
|
54
|
+
return unauthorized();
|
|
55
|
+
}
|
|
56
|
+
const forwardedHeaders = new Headers(req.headers);
|
|
57
|
+
applyQelosForwardHeaders(forwardedHeaders, null, null);
|
|
58
|
+
return NextResponse.next({ request: { headers: forwardedHeaders } });
|
|
59
|
+
}
|
|
76
60
|
let user = null;
|
|
77
|
-
let
|
|
61
|
+
let setCookieValues = [];
|
|
62
|
+
const originalHost = req.headers.get('host');
|
|
63
|
+
if (base) {
|
|
64
|
+
const h = getHeaders();
|
|
65
|
+
const { response, user: meUser } = await fetchMeIdentity({
|
|
66
|
+
base,
|
|
67
|
+
cookie: h.cookie,
|
|
68
|
+
authorization: h.authorization,
|
|
69
|
+
});
|
|
70
|
+
user = meUser;
|
|
71
|
+
setCookieValues = response.headers.getSetCookie?.() ?? [];
|
|
72
|
+
}
|
|
78
73
|
let workspace = null;
|
|
79
|
-
let
|
|
80
|
-
if (
|
|
74
|
+
let workspaces = [];
|
|
75
|
+
if (user) {
|
|
81
76
|
try {
|
|
82
|
-
|
|
77
|
+
workspaces = await sdk.workspaces.getList();
|
|
83
78
|
}
|
|
84
79
|
catch {
|
|
85
|
-
|
|
80
|
+
workspaces = [];
|
|
81
|
+
}
|
|
82
|
+
if (resolveWorkspace) {
|
|
83
|
+
workspace =
|
|
84
|
+
(await resolveWorkspace({ req, user, workspaces })) || null;
|
|
86
85
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
catch {
|
|
92
|
-
workspaces = [];
|
|
93
|
-
}
|
|
94
|
-
if (workspaces.length) {
|
|
95
|
-
if (resolveWorkspace) {
|
|
96
|
-
workspace =
|
|
97
|
-
(await resolveWorkspace({ req, user, workspaces })) || null;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
workspace = workspaces[0] || null;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
86
|
+
else {
|
|
87
|
+
workspace =
|
|
88
|
+
user.workspace ||
|
|
89
|
+
null;
|
|
103
90
|
}
|
|
104
91
|
}
|
|
105
|
-
if (
|
|
106
|
-
|
|
92
|
+
if (!user) {
|
|
93
|
+
if (config.requireAuth) {
|
|
94
|
+
return unauthorized();
|
|
95
|
+
}
|
|
96
|
+
const forwardedHeaders = new Headers(req.headers);
|
|
97
|
+
applyQelosForwardHeaders(forwardedHeaders, null, null);
|
|
98
|
+
const res = NextResponse.next({ request: { headers: forwardedHeaders } });
|
|
99
|
+
for (const value of setCookieValues) {
|
|
100
|
+
res.headers.append('set-cookie', rewriteSetCookieDomain(value, originalHost ?? undefined));
|
|
101
|
+
}
|
|
102
|
+
return res;
|
|
107
103
|
}
|
|
104
|
+
const forwardedHeaders = new Headers(req.headers);
|
|
108
105
|
applyQelosForwardHeaders(forwardedHeaders, user, workspace);
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
for (const cookie of pendingCookies) {
|
|
113
|
-
response.cookies.set(cookie.name, cookie.value, cookie.options);
|
|
106
|
+
const res = NextResponse.next({ request: { headers: forwardedHeaders } });
|
|
107
|
+
for (const value of setCookieValues) {
|
|
108
|
+
res.headers.append('set-cookie', rewriteSetCookieDomain(value, originalHost ?? undefined));
|
|
114
109
|
}
|
|
115
|
-
return
|
|
110
|
+
return res;
|
|
116
111
|
};
|
|
117
112
|
}
|
|
118
113
|
let defaultMiddleware = null;
|
package/dist/middleware.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAoB,MAAM,aAAa,CAAC;AAG7D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/pages.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { IncomingMessage
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
2
2
|
import type { GetServerSideProps, GetServerSidePropsContext, GetServerSidePropsResult, NextApiHandler } from 'next';
|
|
3
3
|
import type { IUser } from '@qelos/sdk/dist/authentication';
|
|
4
4
|
import type { IWorkspace } from '@qelos/sdk/workspaces';
|
|
5
|
-
import type { QelosNextConfig, QelosRequestContext
|
|
5
|
+
import type { QelosNextConfig, QelosRequestContext } from './types';
|
|
6
6
|
type CookieMap = Partial<Record<string, string>>;
|
|
7
7
|
interface RequestWithCookies extends IncomingMessage {
|
|
8
8
|
cookies?: CookieMap;
|
|
@@ -15,13 +15,9 @@ declare module 'http' {
|
|
|
15
15
|
export interface PagesIntegratorOptions {
|
|
16
16
|
config: QelosNextConfig;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
onTokenRefresh?: TokenRefreshHook<ServerResponse>;
|
|
22
|
-
/**
|
|
23
|
-
* Resolve the active workspace for a request. Defaults to picking the first
|
|
24
|
-
* workspace returned from `sdk.workspaces.getList()`.
|
|
18
|
+
* Resolve the active workspace for a request. Defaults to whatever
|
|
19
|
+
* `/api/me` reports on `user.workspace` (the user's currently activated
|
|
20
|
+
* workspace, or `null` when none is active).
|
|
25
21
|
*/
|
|
26
22
|
resolveWorkspace?: (params: {
|
|
27
23
|
req: RequestWithCookies;
|
package/dist/pages.js
CHANGED
|
@@ -1,54 +1,20 @@
|
|
|
1
|
+
import { rewriteSetCookieDomain } from './cookies';
|
|
2
|
+
import { fetchMeIdentity } from './me-client';
|
|
3
|
+
import { resolveQelosProxyTarget } from './proxy-target';
|
|
1
4
|
import { createRequestSdk } from './sdk-factory';
|
|
2
5
|
import { runWithQelosContext } from './context';
|
|
3
|
-
|
|
4
|
-
const DEFAULT_REFRESH_COOKIE = 'q_refresh_token';
|
|
5
|
-
function readCookieFromHeader(header, name) {
|
|
6
|
-
if (!header)
|
|
7
|
-
return undefined;
|
|
8
|
-
const prefix = name + '=';
|
|
9
|
-
for (const part of header.split(';')) {
|
|
10
|
-
const trimmed = part.trim();
|
|
11
|
-
if (trimmed.startsWith(prefix)) {
|
|
12
|
-
try {
|
|
13
|
-
return decodeURIComponent(trimmed.slice(prefix.length));
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return trimmed.slice(prefix.length);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
function readTokens(req, config) {
|
|
23
|
-
const accessCookie = config.accessTokenCookie || DEFAULT_ACCESS_COOKIE;
|
|
24
|
-
const refreshCookie = config.refreshTokenCookie || DEFAULT_REFRESH_COOKIE;
|
|
25
|
-
const parsed = req.cookies;
|
|
26
|
-
const cookieAccess = (parsed && typeof parsed[accessCookie] === 'string'
|
|
27
|
-
? parsed[accessCookie]
|
|
28
|
-
: undefined) || readCookieFromHeader(req.headers.cookie, accessCookie);
|
|
29
|
-
const cookieRefresh = (parsed && typeof parsed[refreshCookie] === 'string'
|
|
30
|
-
? parsed[refreshCookie]
|
|
31
|
-
: undefined) || readCookieFromHeader(req.headers.cookie, refreshCookie);
|
|
6
|
+
function getAuthorization(req) {
|
|
32
7
|
const authHeaderRaw = req.headers.authorization;
|
|
33
8
|
const authHeader = Array.isArray(authHeaderRaw) ? authHeaderRaw[0] : authHeaderRaw;
|
|
34
|
-
|
|
35
|
-
? authHeader.slice(7).trim()
|
|
36
|
-
: undefined;
|
|
37
|
-
return {
|
|
38
|
-
accessToken: headerAccess || cookieAccess || undefined,
|
|
39
|
-
refreshToken: cookieRefresh || undefined,
|
|
40
|
-
};
|
|
9
|
+
return authHeader ?? undefined;
|
|
41
10
|
}
|
|
42
|
-
function
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
'
|
|
48
|
-
|
|
49
|
-
if (secure)
|
|
50
|
-
parts.push('Secure');
|
|
51
|
-
return parts.join('; ');
|
|
11
|
+
function getCookieHeader(req) {
|
|
12
|
+
const raw = req.headers.cookie;
|
|
13
|
+
if (typeof raw === 'string')
|
|
14
|
+
return raw;
|
|
15
|
+
if (Array.isArray(raw))
|
|
16
|
+
return raw.join('; ');
|
|
17
|
+
return undefined;
|
|
52
18
|
}
|
|
53
19
|
function appendSetCookie(res, value) {
|
|
54
20
|
const existing = res.getHeader('set-cookie');
|
|
@@ -62,75 +28,71 @@ function appendSetCookie(res, value) {
|
|
|
62
28
|
res.setHeader('set-cookie', [value]);
|
|
63
29
|
}
|
|
64
30
|
}
|
|
65
|
-
function writeTokensToResponse(res, config, tokens) {
|
|
66
|
-
const accessCookie = config.accessTokenCookie || DEFAULT_ACCESS_COOKIE;
|
|
67
|
-
const refreshCookie = config.refreshTokenCookie || DEFAULT_REFRESH_COOKIE;
|
|
68
|
-
const secure = !/^http:\/\//i.test(config.appUrl);
|
|
69
|
-
appendSetCookie(res, serializeCookie(accessCookie, tokens.accessToken, secure));
|
|
70
|
-
if (tokens.refreshToken) {
|
|
71
|
-
appendSetCookie(res, serializeCookie(refreshCookie, tokens.refreshToken, secure));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
31
|
function shouldSkip(req, config) {
|
|
75
32
|
if (!config.skipPaths?.length)
|
|
76
33
|
return false;
|
|
77
34
|
const path = req.url || '';
|
|
78
35
|
return config.skipPaths.some((prefix) => path.startsWith(prefix));
|
|
79
36
|
}
|
|
37
|
+
function requestHost(req) {
|
|
38
|
+
const h = req.headers.host;
|
|
39
|
+
return Array.isArray(h) ? h[0] ?? null : h ?? null;
|
|
40
|
+
}
|
|
80
41
|
async function buildContext(req, res, options) {
|
|
81
42
|
const { config, resolveWorkspace } = options;
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
});
|
|
86
|
-
const tokens = readTokens(req, config);
|
|
87
|
-
const sdk = createRequestSdk({
|
|
88
|
-
config,
|
|
89
|
-
tokens,
|
|
90
|
-
refreshTarget: res,
|
|
91
|
-
onTokenRefresh,
|
|
43
|
+
const getHeaders = () => ({
|
|
44
|
+
cookie: getCookieHeader(req),
|
|
45
|
+
authorization: getAuthorization(req),
|
|
92
46
|
});
|
|
47
|
+
const sdk = createRequestSdk({ config, getHeaders });
|
|
93
48
|
const ctx = {
|
|
94
49
|
user: null,
|
|
95
50
|
workspace: null,
|
|
96
51
|
workspaces: [],
|
|
97
52
|
sdk,
|
|
98
|
-
tokens,
|
|
99
53
|
};
|
|
100
|
-
const
|
|
101
|
-
if (!
|
|
102
|
-
return { ctx
|
|
54
|
+
const base = resolveQelosProxyTarget(config);
|
|
55
|
+
if (!base && !config.apiToken) {
|
|
56
|
+
return { ctx };
|
|
103
57
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
ctx.user = await sdk.authentication.getLoggedInUser();
|
|
58
|
+
if (!base) {
|
|
59
|
+
return { ctx };
|
|
107
60
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
61
|
+
const h = getHeaders();
|
|
62
|
+
const { response, user } = await fetchMeIdentity({
|
|
63
|
+
base,
|
|
64
|
+
cookie: h.cookie,
|
|
65
|
+
authorization: h.authorization,
|
|
66
|
+
});
|
|
67
|
+
const host = requestHost(req);
|
|
68
|
+
const setCookieValues = response.headers.getSetCookie?.() ?? [];
|
|
69
|
+
for (const value of setCookieValues) {
|
|
70
|
+
appendSetCookie(res, rewriteSetCookieDomain(value, host ?? undefined));
|
|
71
|
+
}
|
|
72
|
+
ctx.user = user;
|
|
73
|
+
if (!ctx.user) {
|
|
74
|
+
return { ctx };
|
|
111
75
|
}
|
|
112
|
-
if (!ctx.user)
|
|
113
|
-
return { ctx, identifyFailed };
|
|
114
76
|
try {
|
|
115
77
|
ctx.workspaces = await sdk.workspaces.getList();
|
|
116
78
|
}
|
|
117
79
|
catch {
|
|
118
80
|
ctx.workspaces = [];
|
|
119
81
|
}
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
ctx.workspace
|
|
131
|
-
|
|
82
|
+
if (resolveWorkspace) {
|
|
83
|
+
ctx.workspace =
|
|
84
|
+
(await resolveWorkspace({
|
|
85
|
+
req,
|
|
86
|
+
user: ctx.user,
|
|
87
|
+
workspaces: ctx.workspaces,
|
|
88
|
+
})) || null;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
ctx.workspace =
|
|
92
|
+
ctx.user.workspace ||
|
|
93
|
+
null;
|
|
132
94
|
}
|
|
133
|
-
return { ctx
|
|
95
|
+
return { ctx };
|
|
134
96
|
}
|
|
135
97
|
/**
|
|
136
98
|
* Wrap a Pages Router API route handler so that `req.qelos` is populated
|
|
@@ -143,9 +105,9 @@ export function withQelosApi(handler, options) {
|
|
|
143
105
|
if (shouldSkip(req, config)) {
|
|
144
106
|
return handler(req, res);
|
|
145
107
|
}
|
|
146
|
-
const { ctx
|
|
108
|
+
const { ctx } = await buildContext(req, res, options);
|
|
147
109
|
req.qelos = ctx;
|
|
148
|
-
if (config.requireAuth &&
|
|
110
|
+
if (config.requireAuth && !ctx.user) {
|
|
149
111
|
res.status(401).json({ code: 'UNAUTHORIZED' });
|
|
150
112
|
return;
|
|
151
113
|
}
|
|
@@ -171,17 +133,18 @@ export function withQelosSSR(handler, options) {
|
|
|
171
133
|
const req = context.req;
|
|
172
134
|
const res = context.res;
|
|
173
135
|
if (shouldSkip(req, config)) {
|
|
174
|
-
|
|
136
|
+
const emptySdk = null;
|
|
137
|
+
const emptyCtx = {
|
|
175
138
|
user: null,
|
|
176
139
|
workspace: null,
|
|
177
140
|
workspaces: [],
|
|
178
|
-
sdk:
|
|
179
|
-
|
|
180
|
-
|
|
141
|
+
sdk: emptySdk,
|
|
142
|
+
};
|
|
143
|
+
return runWithQelosContext(emptyCtx, () => handler(context, emptyCtx));
|
|
181
144
|
}
|
|
182
|
-
const { ctx
|
|
145
|
+
const { ctx } = await buildContext(req, res, options);
|
|
183
146
|
req.qelos = ctx;
|
|
184
|
-
if (config.requireAuth &&
|
|
147
|
+
if (config.requireAuth && !ctx.user) {
|
|
185
148
|
return { redirect: { destination: '/login', permanent: false } };
|
|
186
149
|
}
|
|
187
150
|
return (await runWithQelosContext(ctx, () => handler(context, ctx)));
|
package/dist/pages.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { QelosNextConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the origin to which `/api/**` requests are proxied. The managed
|
|
4
|
+
* Qelos app URL (`config.appUrl`) is the proxy target — env vars are only
|
|
5
|
+
* dev-time overrides when the configured `appUrl` is not reachable from
|
|
6
|
+
* the local host.
|
|
7
|
+
*
|
|
8
|
+
* Priority (highest first):
|
|
9
|
+
* 1. `process.env.NEXT_QELOS_PROXY_TARGET`
|
|
10
|
+
* 2. `process.env.QELOS_IP`
|
|
11
|
+
* 3. `process.env.QELOS_API_IP`
|
|
12
|
+
* 4. `config.appUrl`
|
|
13
|
+
*
|
|
14
|
+
* Empty / whitespace-only values are skipped, and `undefined` is returned when
|
|
15
|
+
* nothing is configured so the caller can surface a clear error.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveQelosProxyTarget(config: QelosNextConfig): string | undefined;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the origin to which `/api/**` requests are proxied. The managed
|
|
3
|
+
* Qelos app URL (`config.appUrl`) is the proxy target — env vars are only
|
|
4
|
+
* dev-time overrides when the configured `appUrl` is not reachable from
|
|
5
|
+
* the local host.
|
|
6
|
+
*
|
|
7
|
+
* Priority (highest first):
|
|
8
|
+
* 1. `process.env.NEXT_QELOS_PROXY_TARGET`
|
|
9
|
+
* 2. `process.env.QELOS_IP`
|
|
10
|
+
* 3. `process.env.QELOS_API_IP`
|
|
11
|
+
* 4. `config.appUrl`
|
|
12
|
+
*
|
|
13
|
+
* Empty / whitespace-only values are skipped, and `undefined` is returned when
|
|
14
|
+
* nothing is configured so the caller can surface a clear error.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveQelosProxyTarget(config) {
|
|
17
|
+
const env = process.env;
|
|
18
|
+
const fromEnv = env.NEXT_QELOS_PROXY_TARGET?.trim() ||
|
|
19
|
+
env.QELOS_IP?.trim() ||
|
|
20
|
+
env.QELOS_API_IP?.trim();
|
|
21
|
+
if (fromEnv)
|
|
22
|
+
return fromEnv;
|
|
23
|
+
const fromAppUrl = config.appUrl?.trim();
|
|
24
|
+
return fromAppUrl || undefined;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=proxy-target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-target.js","sourceRoot":"","sources":["../src/proxy-target.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAuB;IAEvB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IACxB,MAAM,OAAO,GACX,GAAG,CAAC,uBAAuB,EAAE,IAAI,EAAE;QACnC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE;QACpB,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;IACzC,OAAO,UAAU,IAAI,SAAS,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type NextRequest } from 'next/server';
|
|
2
|
+
import type { QelosNextConfig } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Handlers for a catch-all App Router route (e.g. `app/api/[...qelos]/route.ts`)
|
|
5
|
+
* that reverse-proxies every `/api/**` call to Qelos with `Set-Cookie` domain
|
|
6
|
+
* rewriting. Use `export const runtime = 'nodejs'`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createQelosApiProxyHandlers(config: QelosNextConfig): {
|
|
9
|
+
runtime: "nodejs";
|
|
10
|
+
GET: (req: NextRequest) => Promise<Response>;
|
|
11
|
+
POST: (req: NextRequest) => Promise<Response>;
|
|
12
|
+
PUT: (req: NextRequest) => Promise<Response>;
|
|
13
|
+
PATCH: (req: NextRequest) => Promise<Response>;
|
|
14
|
+
DELETE: (req: NextRequest) => Promise<Response>;
|
|
15
|
+
OPTIONS: (req: NextRequest) => Promise<Response>;
|
|
16
|
+
};
|