@qelos/integrator-nuxt 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.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Rewrite the `Domain=` attribute of a single `Set-Cookie` header value.
3
+ *
4
+ * - If the cookie contains a `Domain=<value>` attribute (case-insensitive), its
5
+ * value is replaced with `newDomain`, with any trailing `:port` suffix
6
+ * stripped first (cookie `Domain` attributes do not include a port).
7
+ * - If `newDomain` is `undefined` (or empty), the entire `; Domain=<value>`
8
+ * segment is removed so the browser scopes the cookie to the current host.
9
+ * - If no `Domain=` attribute is present, the input is returned unchanged.
10
+ *
11
+ * All other attributes, their casing/order and the original cookie name/value
12
+ * bytes are preserved.
13
+ */
14
+ export declare function rewriteSetCookieDomain(setCookie: string, newDomain: string | undefined): string;
15
+ /**
16
+ * Apply {@link rewriteSetCookieDomain} to each entry of a `Set-Cookie` array
17
+ * (e.g. the result of `Headers.getSetCookie()`).
18
+ */
19
+ export declare function rewriteSetCookieDomains(values: string[], newDomain: string | undefined): string[];
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Rewrite the `Domain=` attribute of a single `Set-Cookie` header value.
3
+ *
4
+ * - If the cookie contains a `Domain=<value>` attribute (case-insensitive), its
5
+ * value is replaced with `newDomain`, with any trailing `:port` suffix
6
+ * stripped first (cookie `Domain` attributes do not include a port).
7
+ * - If `newDomain` is `undefined` (or empty), the entire `; Domain=<value>`
8
+ * segment is removed so the browser scopes the cookie to the current host.
9
+ * - If no `Domain=` attribute is present, the input is returned unchanged.
10
+ *
11
+ * All other attributes, their casing/order and the original cookie name/value
12
+ * bytes are preserved.
13
+ */
14
+ export function rewriteSetCookieDomain(setCookie, newDomain) {
15
+ const domainSegment = /;\s*Domain\s*=\s*[^;]+/i;
16
+ if (!domainSegment.test(setCookie))
17
+ return setCookie;
18
+ const stripped = newDomain ? stripPort(newDomain) : '';
19
+ if (!stripped) {
20
+ return setCookie.replace(domainSegment, '');
21
+ }
22
+ return setCookie.replace(/(;\s*Domain\s*=\s*)[^;]+/i, `$1${stripped}`);
23
+ }
24
+ /**
25
+ * Apply {@link rewriteSetCookieDomain} to each entry of a `Set-Cookie` array
26
+ * (e.g. the result of `Headers.getSetCookie()`).
27
+ */
28
+ export function rewriteSetCookieDomains(values, newDomain) {
29
+ return values.map((value) => rewriteSetCookieDomain(value, newDomain));
30
+ }
31
+ function stripPort(host) {
32
+ if (host.startsWith('[')) {
33
+ const end = host.indexOf(']');
34
+ return end === -1 ? host : host.slice(1, end);
35
+ }
36
+ const colon = host.indexOf(':');
37
+ return colon === -1 ? host : host.slice(0, colon);
38
+ }
39
+ //# sourceMappingURL=cookies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies.js","sourceRoot":"","sources":["../src/cookies.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAAiB,EACjB,SAA6B;IAE7B,MAAM,aAAa,GAAG,yBAAyB,CAAC;IAChD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAErD,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,SAAS,CAAC,OAAO,CACtB,2BAA2B,EAC3B,KAAK,QAAQ,EAAE,CAChB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAgB,EAChB,SAA6B;IAE7B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACpD,CAAC"}
@@ -1,17 +1,13 @@
1
1
  import { type H3Event } from 'h3';
2
2
  import type { IUser } from '@qelos/sdk/dist/authentication';
3
3
  import type { IWorkspace } from '@qelos/sdk/workspaces';
4
- import type { QelosNuxtRuntimeConfig, TokenRefreshHook } from './types';
4
+ import type { QelosNuxtRuntimeConfig } from './types';
5
5
  export interface CreateMiddlewareOptions {
6
6
  config: QelosNuxtRuntimeConfig;
7
7
  /**
8
- * Hook invoked after a successful token refresh. The default implementation
9
- * writes the new tokens back to the response cookies.
10
- */
11
- onTokenRefresh?: TokenRefreshHook;
12
- /**
13
- * Resolve the active workspace for a request. Defaults to picking the first
14
- * workspace returned from `sdk.workspaces.getList()`.
8
+ * Resolve the active workspace for a request. Defaults to whatever
9
+ * `/api/me` reports on `user.workspace` (the user's currently activated
10
+ * workspace, or `null` when none is active).
15
11
  */
16
12
  resolveWorkspace?: (params: {
17
13
  event: H3Event;
@@ -1,35 +1,7 @@
1
- import { defineEventHandler, getCookie, getRequestHeader, setCookie, createError, } from 'h3';
1
+ import { appendResponseHeader, createError, defineEventHandler, getRequestHeader, } from 'h3';
2
+ import { rewriteSetCookieDomain } from './cookies';
3
+ import { resolveQelosProxyTarget } from './proxy-target';
2
4
  import { createRequestSdk } from './sdk-factory';
3
- const DEFAULT_ACCESS_COOKIE = 'q_access_token';
4
- const DEFAULT_REFRESH_COOKIE = 'q_refresh_token';
5
- function readTokens(event, config) {
6
- const accessCookie = config.accessTokenCookie || DEFAULT_ACCESS_COOKIE;
7
- const refreshCookie = config.refreshTokenCookie || DEFAULT_REFRESH_COOKIE;
8
- const cookieAccess = getCookie(event, accessCookie);
9
- const cookieRefresh = getCookie(event, refreshCookie);
10
- const authHeader = getRequestHeader(event, 'authorization');
11
- const headerAccess = authHeader && authHeader.toLowerCase().startsWith('bearer ')
12
- ? authHeader.slice(7).trim()
13
- : undefined;
14
- return {
15
- accessToken: headerAccess || cookieAccess || undefined,
16
- refreshToken: cookieRefresh || undefined,
17
- };
18
- }
19
- function writeTokensToCookies(event, config, tokens) {
20
- const accessCookie = config.accessTokenCookie || DEFAULT_ACCESS_COOKIE;
21
- const refreshCookie = config.refreshTokenCookie || DEFAULT_REFRESH_COOKIE;
22
- const cookieOptions = {
23
- httpOnly: true,
24
- secure: true,
25
- sameSite: 'lax',
26
- path: '/',
27
- };
28
- setCookie(event, accessCookie, tokens.accessToken, cookieOptions);
29
- if (tokens.refreshToken) {
30
- setCookie(event, refreshCookie, tokens.refreshToken, cookieOptions);
31
- }
32
- }
33
5
  function shouldSkip(event, config) {
34
6
  if (!config.skipPaths?.length) {
35
7
  return false;
@@ -37,37 +9,67 @@ function shouldSkip(event, config) {
37
9
  const path = event.path || event.node?.req?.url || '';
38
10
  return config.skipPaths.some((prefix) => path.startsWith(prefix));
39
11
  }
12
+ function buildMeUrl(base) {
13
+ return `${base.replace(/\/+$/, '')}/api/me`;
14
+ }
40
15
  export function createQelosMiddleware(options) {
41
16
  const { config, resolveWorkspace } = options;
42
- const onTokenRefresh = options.onTokenRefresh
43
- || (async ({ event, newTokens }) => {
44
- writeTokensToCookies(event, config, newTokens);
45
- });
46
17
  return defineEventHandler(async (event) => {
47
18
  if (shouldSkip(event, config)) {
48
19
  return;
49
20
  }
50
- const tokens = readTokens(event, config);
51
- const sdk = createRequestSdk({ config, tokens, event, onTokenRefresh });
21
+ const sdk = createRequestSdk({ config, event });
52
22
  const ctx = {
53
23
  user: null,
54
24
  workspace: null,
55
25
  workspaces: [],
56
26
  sdk,
57
- tokens,
58
27
  };
59
28
  event.context.qelos = ctx;
60
- const hasAuthMaterial = Boolean(config.apiToken || tokens.accessToken || tokens.refreshToken);
61
- if (!hasAuthMaterial) {
29
+ const base = resolveQelosProxyTarget(config);
30
+ if (!base && !config.apiToken) {
62
31
  if (config.requireAuth) {
63
32
  throw createError({ statusCode: 401, statusMessage: 'Unauthorized' });
64
33
  }
65
34
  return;
66
35
  }
67
- try {
68
- ctx.user = await sdk.authentication.getLoggedInUser();
36
+ if (base) {
37
+ const headers = {};
38
+ const cookieHeader = getRequestHeader(event, 'cookie');
39
+ if (cookieHeader)
40
+ headers.cookie = cookieHeader;
41
+ const authHeader = getRequestHeader(event, 'authorization');
42
+ if (authHeader)
43
+ headers.authorization = authHeader;
44
+ const originalHost = getRequestHeader(event, 'host');
45
+ let response;
46
+ try {
47
+ response = await fetch(buildMeUrl(base), {
48
+ method: 'GET',
49
+ headers,
50
+ redirect: 'manual',
51
+ });
52
+ }
53
+ catch {
54
+ if (config.requireAuth) {
55
+ throw createError({ statusCode: 401, statusMessage: 'Unauthorized' });
56
+ }
57
+ return;
58
+ }
59
+ const setCookieValues = response.headers.getSetCookie?.() ?? [];
60
+ for (const value of setCookieValues) {
61
+ appendResponseHeader(event, 'set-cookie', rewriteSetCookieDomain(value, originalHost));
62
+ }
63
+ if (response.ok) {
64
+ try {
65
+ ctx.user = (await response.json());
66
+ }
67
+ catch {
68
+ ctx.user = null;
69
+ }
70
+ }
69
71
  }
70
- catch (err) {
72
+ if (!ctx.user) {
71
73
  if (config.requireAuth) {
72
74
  throw createError({ statusCode: 401, statusMessage: 'Unauthorized' });
73
75
  }
@@ -79,17 +81,19 @@ export function createQelosMiddleware(options) {
79
81
  catch {
80
82
  ctx.workspaces = [];
81
83
  }
82
- if (ctx.user && ctx.workspaces.length) {
83
- if (resolveWorkspace) {
84
- ctx.workspace = await resolveWorkspace({
85
- event,
86
- user: ctx.user,
87
- workspaces: ctx.workspaces,
88
- }) || null;
89
- }
90
- else {
91
- ctx.workspace = ctx.workspaces[0] || null;
92
- }
84
+ if (resolveWorkspace) {
85
+ ctx.workspace = (await resolveWorkspace({
86
+ event,
87
+ user: ctx.user,
88
+ workspaces: ctx.workspaces,
89
+ })) || null;
90
+ }
91
+ else {
92
+ // `/api/me` carries `user.workspace` (`{ _id, name, roles }`) only when
93
+ // the user has activated a workspace. Null means the frontend must
94
+ // prompt to activate/create one — don't silently pick workspaces[0].
95
+ ctx.workspace =
96
+ ctx.user.workspace || null;
93
97
  }
94
98
  });
95
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
package/dist/module.d.ts CHANGED
@@ -5,6 +5,11 @@ export interface QelosNuxtModuleOptions extends QelosNuxtRuntimeConfig {
5
5
  * want to call `createQelosMiddleware` yourself from your own server route.
6
6
  */
7
7
  disableMiddleware?: boolean;
8
+ /**
9
+ * Disable registration of the catch-all `/api/**` proxy server handler.
10
+ * Defaults to `false`.
11
+ */
12
+ disableProxy?: boolean;
8
13
  }
9
14
  declare const _default: import("nuxt/schema").NuxtModule<QelosNuxtModuleOptions, QelosNuxtModuleOptions, false>;
10
15
  export default _default;
@@ -12,4 +17,4 @@ export { createQelosMiddleware } from './middleware';
12
17
  export { createRequestSdk } from './sdk-factory';
13
18
  export { defineQelosEventHandler } from './event-handler';
14
19
  export type { DefineQelosEventHandlerOptions, QelosEventContext, QelosEventHandler, } from './event-handler';
15
- export type { QelosNuxtRuntimeConfig, QelosRequestContext, QelosTokenPair, ResolvedTokens, TokenRefreshContext, TokenRefreshHook, } from './types';
20
+ export type { QelosNuxtRuntimeConfig, QelosRequestContext, } from './types';
package/dist/module.js CHANGED
@@ -15,7 +15,21 @@ export default defineNuxtModule({
15
15
  throw new Error('[@qelos/integrator-nuxt] `qelos.appUrl` must be set in nuxt.config');
16
16
  }
17
17
  const { resolve } = createResolver(import.meta.url);
18
- const { disableMiddleware, ...runtimeConfig } = options;
18
+ const { disableMiddleware, disableProxy, ...runtimeConfig } = options;
19
+ if (!disableProxy) {
20
+ // When the catch-all `/api/**` proxy is enabled, the user-resolution
21
+ // middleware MUST skip `/api/` requests. The middleware itself calls
22
+ // `${appUrl}/api/me` to identify the user, so without this skip
23
+ // every inbound `/api/me` would be both proxied AND used as the
24
+ // identification probe — a duplicate upstream hit and a potential
25
+ // cookie-rewrite loop. Users can extend `skipPaths` further but
26
+ // `/api/` must remain covered whenever `disableProxy` is false.
27
+ const existingSkipPaths = runtimeConfig.skipPaths ?? [];
28
+ const alreadyCovered = existingSkipPaths.some((prefix) => '/api/'.startsWith(prefix));
29
+ if (!alreadyCovered) {
30
+ runtimeConfig.skipPaths = ['/api/', ...existingSkipPaths];
31
+ }
32
+ }
19
33
  nuxt.options.runtimeConfig.qelos = {
20
34
  ...nuxt.options.runtimeConfig.qelos,
21
35
  ...runtimeConfig,
@@ -26,6 +40,12 @@ export default defineNuxtModule({
26
40
  middleware: true,
27
41
  });
28
42
  }
43
+ if (!disableProxy) {
44
+ addServerHandler({
45
+ route: '/api/**',
46
+ handler: resolve('./runtime/api-proxy'),
47
+ });
48
+ }
29
49
  addImportsDir(resolve('./runtime/composables'));
30
50
  addTypeTemplate({
31
51
  filename: 'types/qelos-nuxt.d.ts',
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,eAAe,GAChB,MAAM,WAAW,CAAC;AAWnB,eAAe,gBAAgB,CAAyB;IACtD,IAAI,EAAE;QACJ,IAAI,EAAE,wBAAwB;QAC9B,SAAS,EAAE,OAAO;QAClB,aAAa,EAAE;YACb,IAAI,EAAE,QAAQ;SACf;KACF;IACD,QAAQ,EAAE;QACR,MAAM,EAAE,EAAE;KACX;IACD,KAAK,CAAC,OAAO,EAAE,IAAI;QACjB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpD,MAAM,EAAE,iBAAiB,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;QAExD,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,GAAG;YACjC,GAAI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAA6C;YAC5E,GAAG,aAAa;SACjB,CAAC;QAEF,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,gBAAgB,CAAC;gBACf,OAAO,EAAE,OAAO,CAAC,0BAA0B,CAAC;gBAC5C,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;QACL,CAAC;QAED,aAAa,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC;QAEhD,eAAe,CAAC;YACd,QAAQ,EAAE,uBAAuB;YACjC,WAAW,EAAE,GAAG,EAAE,CAAC;;;;;;;;;;CAUxB;SACI,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,eAAe,GAChB,MAAM,WAAW,CAAC;AAgBnB,eAAe,gBAAgB,CAAyB;IACtD,IAAI,EAAE;QACJ,IAAI,EAAE,wBAAwB;QAC9B,SAAS,EAAE,OAAO;QAClB,aAAa,EAAE;YACb,IAAI,EAAE,QAAQ;SACf;KACF;IACD,QAAQ,EAAE;QACR,MAAM,EAAE,EAAE;KACX;IACD,KAAK,CAAC,OAAO,EAAE,IAAI;QACjB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpD,MAAM,EAAE,iBAAiB,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;QAEtE,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,qEAAqE;YACrE,qEAAqE;YACrE,gEAAgE;YAChE,gEAAgE;YAChE,kEAAkE;YAClE,gEAAgE;YAChE,gEAAgE;YAChE,MAAM,iBAAiB,GAAG,aAAa,CAAC,SAAS,IAAI,EAAE,CAAC;YACxD,MAAM,cAAc,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;YACtF,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,aAAa,CAAC,SAAS,GAAG,CAAC,OAAO,EAAE,GAAG,iBAAiB,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,GAAG;YACjC,GAAI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAA6C;YAC5E,GAAG,aAAa;SACjB,CAAC;QAEF,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,gBAAgB,CAAC;gBACf,OAAO,EAAE,OAAO,CAAC,0BAA0B,CAAC;gBAC5C,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,gBAAgB,CAAC;gBACf,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,OAAO,CAAC,qBAAqB,CAAC;aACxC,CAAC,CAAC;QACL,CAAC;QAED,aAAa,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC;QAEhD,eAAe,CAAC;YACd,QAAQ,EAAE,uBAAuB;YACjC,WAAW,EAAE,GAAG,EAAE,CAAC;;;;;;;;;;CAUxB;SACI,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { QelosNuxtRuntimeConfig } 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.NUXT_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: QelosNuxtRuntimeConfig): 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.NUXT_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.NUXT_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,MAA8B;IAE9B,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,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,27 @@
1
+ // This file is registered as a Nuxt server handler by `module.ts`. It is
2
+ // bundled by Nitro, so `#imports` resolves at the consuming-app build time
3
+ // (not at this package's `tsc` build).
4
+ // @ts-ignore - resolved by Nitro
5
+ import { useRuntimeConfig } from '#imports';
6
+ import { createError, defineEventHandler, getRequestHeader, proxyRequest, } from 'h3';
7
+ // @ts-ignore - resolved by Nitro (transitive dep of Nuxt)
8
+ import { joinURL } from 'ufo';
9
+ import { resolveQelosProxyTarget } from '../proxy-target';
10
+ export default defineEventHandler((event) => {
11
+ const config = (useRuntimeConfig().qelos || {});
12
+ const base = resolveQelosProxyTarget(config);
13
+ if (!base) {
14
+ throw createError({
15
+ statusCode: 503,
16
+ statusMessage: '[@qelos/integrator-nuxt] Qelos API proxy is not configured. Set qelos.appUrl (or NUXT_QELOS_PROXY_TARGET / QELOS_IP / QELOS_API_IP in development).',
17
+ });
18
+ }
19
+ const originalHost = getRequestHeader(event, 'host');
20
+ const path = event.path.split('?')[0] ?? event.path;
21
+ const target = joinURL(base, path);
22
+ return proxyRequest(event, target, {
23
+ fetch: globalThis.fetch,
24
+ cookieDomainRewrite: { '*': originalHost ?? '' },
25
+ });
26
+ });
27
+ //# sourceMappingURL=api-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-proxy.js","sourceRoot":"","sources":["../../src/runtime/api-proxy.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,2EAA2E;AAC3E,uCAAuC;AACvC,iCAAiC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,GACb,MAAM,IAAI,CAAC;AACZ,0DAA0D;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,eAAe,kBAAkB,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1C,MAAM,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,KAAK,IAAI,EAAE,CAA2B,CAAC;IAC1E,MAAM,IAAI,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,WAAW,CAAC;YAChB,UAAU,EAAE,GAAG;YACf,aAAa,EACX,qJAAqJ;SACxJ,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC;IACpD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAEnC,OAAO,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE;QACjC,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,mBAAmB,EAAE,EAAE,GAAG,EAAE,YAAY,IAAI,EAAE,EAAE;KACjD,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,15 +1,8 @@
1
1
  import QelosSDK from '@qelos/sdk';
2
- import type { QelosNuxtRuntimeConfig, QelosTokenPair, TokenRefreshHook } from './types';
3
- import type { H3Event } from 'h3';
2
+ import { type H3Event } from 'h3';
3
+ import type { QelosNuxtRuntimeConfig } from './types';
4
4
  export interface CreateSdkParams {
5
5
  config: QelosNuxtRuntimeConfig;
6
- /**
7
- * Tokens for the current request. The factory mutates this object in
8
- * place when a token refresh occurs, so callers can read the latest pair
9
- * after the SDK has been used.
10
- */
11
- tokens: QelosTokenPair;
12
6
  event: H3Event;
13
- onTokenRefresh?: TokenRefreshHook;
14
7
  }
15
- export declare function createRequestSdk({ config, tokens, event, onTokenRefresh }: CreateSdkParams): QelosSDK;
8
+ export declare function createRequestSdk({ config, event }: CreateSdkParams): QelosSDK;
@@ -1,84 +1,28 @@
1
1
  import QelosSDK from '@qelos/sdk';
2
- const NO_AUTH_URLS = new Set([
3
- '/api/token/refresh',
4
- '/api/cookie/refresh',
5
- '/api/signin',
6
- '/api/signup',
7
- ]);
8
- export function createRequestSdk({ config, tokens, event, onTokenRefresh }) {
9
- let sdk;
10
- let refreshInFlight = null;
2
+ import { getRequestHeader } from 'h3';
3
+ export function createRequestSdk({ config, event }) {
11
4
  const baseOptions = config.sdkOptions || {};
12
- async function performRefresh() {
13
- if (!tokens.refreshToken && !tokens.accessToken) {
14
- throw new Error('no refresh token available');
15
- }
16
- const previous = {
17
- accessToken: tokens.accessToken,
18
- refreshToken: tokens.refreshToken,
19
- };
20
- let refreshed;
21
- if (tokens.refreshToken) {
22
- const result = await sdk.authentication.refreshToken(tokens.refreshToken);
23
- refreshed = {
24
- accessToken: result.payload.token,
25
- refreshToken: result.payload.refreshToken,
26
- };
27
- }
28
- else {
29
- const result = await sdk.authentication.refreshCookieToken(tokens.accessToken);
30
- refreshed = {
31
- accessToken: result.payload.cookieToken,
32
- };
33
- }
34
- tokens.accessToken = refreshed.accessToken;
35
- tokens.refreshToken = refreshed.refreshToken;
36
- if (onTokenRefresh) {
37
- await onTokenRefresh({ event, oldTokens: previous, newTokens: refreshed, sdk });
38
- }
39
- }
40
- function ensureRefresh() {
41
- if (!refreshInFlight) {
42
- refreshInFlight = performRefresh().finally(() => {
43
- refreshInFlight = null;
44
- });
45
- }
46
- return refreshInFlight;
47
- }
48
5
  const options = {
49
6
  appUrl: config.appUrl,
50
7
  fetch: globalThis.fetch,
51
- forceRefresh: !config.apiToken,
52
8
  ...baseOptions,
53
9
  };
54
10
  if (config.apiToken) {
55
11
  options.apiToken = config.apiToken;
12
+ return new QelosSDK(options);
56
13
  }
57
- else {
58
- if (tokens.accessToken) {
59
- options.accessToken = tokens.accessToken;
14
+ options.extraHeaders = async () => {
15
+ const headers = {};
16
+ const cookieHeader = getRequestHeader(event, 'cookie');
17
+ if (cookieHeader) {
18
+ headers.cookie = cookieHeader;
60
19
  }
61
- if (tokens.refreshToken) {
62
- options.refreshToken = tokens.refreshToken;
20
+ const authHeader = getRequestHeader(event, 'authorization');
21
+ if (authHeader) {
22
+ headers.authorization = authHeader;
63
23
  }
64
- options.extraHeaders = async (relativeUrl, forceRefresh) => {
65
- if (NO_AUTH_URLS.has(relativeUrl)) {
66
- return {};
67
- }
68
- if (forceRefresh && tokens.refreshToken) {
69
- await ensureRefresh();
70
- }
71
- const token = sdk?.authentication?.accessToken || tokens.accessToken;
72
- if (token) {
73
- return { authorization: 'Bearer ' + token };
74
- }
75
- return {};
76
- };
77
- options.onFailedRefreshToken = async () => {
78
- await ensureRefresh();
79
- };
80
- }
81
- sdk = new QelosSDK(options);
82
- return sdk;
24
+ return headers;
25
+ };
26
+ return new QelosSDK(options);
83
27
  }
84
28
  //# sourceMappingURL=sdk-factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk-factory.js","sourceRoot":"","sources":["../src/sdk-factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdk-factory.js","sourceRoot":"","sources":["../src/sdk-factory.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,YAAY,CAAC;AAElC,OAAO,EAAE,gBAAgB,EAAgB,MAAM,IAAI,CAAC;AAQpD,MAAM,UAAU,gBAAgB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAmB;IACjE,MAAM,WAAW,GAA6B,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IAEtE,MAAM,OAAO,GAAoB;QAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAG,UAAU,CAAC,KAA8B;QACjD,GAAG,WAAW;KACf,CAAC;IAEF,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QACnC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,CAAC,YAAY,GAAG,KAAK,IAAI,EAAE;QAChC,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACvD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,GAAG,YAAY,CAAC;QAChC,CAAC;QACD,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QAC5D,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,CAAC,aAAa,GAAG,UAAU,CAAC;QACrC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IAEF,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC"}
package/dist/types.d.ts CHANGED
@@ -2,10 +2,6 @@ import type QelosSDK from '@qelos/sdk';
2
2
  import type { IUser } from '@qelos/sdk/dist/authentication';
3
3
  import type { IWorkspace } from '@qelos/sdk/workspaces';
4
4
  import type { QelosSDKOptions } from '@qelos/sdk/types';
5
- export interface QelosTokenPair {
6
- accessToken?: string;
7
- refreshToken?: string;
8
- }
9
5
  export interface QelosNuxtRuntimeConfig {
10
6
  /**
11
7
  * Base URL of the Qelos backend (e.g. https://yourdomain.com).
@@ -13,17 +9,9 @@ export interface QelosNuxtRuntimeConfig {
13
9
  appUrl: string;
14
10
  /**
15
11
  * Static API token used for service-to-service calls. When provided, no
16
- * cookie/refresh-token handling is performed.
12
+ * cookie-based authentication is performed.
17
13
  */
18
14
  apiToken?: string;
19
- /**
20
- * Cookie name carrying the Qelos access token. Defaults to `q_access_token`.
21
- */
22
- accessTokenCookie?: string;
23
- /**
24
- * Cookie name carrying the Qelos refresh token. Defaults to `q_refresh_token`.
25
- */
26
- refreshTokenCookie?: string;
27
15
  /**
28
16
  * Path to mount the server middleware on. Defaults to `''` (every request).
29
17
  */
@@ -42,18 +30,12 @@ export interface QelosNuxtRuntimeConfig {
42
30
  * Optional extra options merged into the per-request SDK instance.
43
31
  */
44
32
  sdkOptions?: Partial<QelosSDKOptions>;
33
+ /**
34
+ * If true, the catch-all `/api/**` proxy handler is not registered.
35
+ * Defaults to `false`.
36
+ */
37
+ disableProxy?: boolean;
45
38
  }
46
- export interface ResolvedTokens {
47
- accessToken: string;
48
- refreshToken?: string;
49
- }
50
- export interface TokenRefreshContext {
51
- event: import('h3').H3Event;
52
- oldTokens: QelosTokenPair;
53
- newTokens: ResolvedTokens;
54
- sdk: QelosSDK;
55
- }
56
- export type TokenRefreshHook = (ctx: TokenRefreshContext) => void | Promise<void>;
57
39
  export interface QelosRequestContext {
58
40
  /**
59
41
  * The authenticated user, or `null` when anonymous.
@@ -69,13 +51,11 @@ export interface QelosRequestContext {
69
51
  */
70
52
  workspaces: IWorkspace[];
71
53
  /**
72
- * SDK instance bound to the current request's tokens.
54
+ * SDK instance bound to the current request's cookies. `extraHeaders`
55
+ * re-reads cookies live on each call, so cookie rotations applied by the
56
+ * middleware are picked up automatically.
73
57
  */
74
58
  sdk: QelosSDK;
75
- /**
76
- * Tokens read from the request. Mutated when a refresh occurs.
77
- */
78
- tokens: QelosTokenPair;
79
59
  }
80
60
  declare module 'h3' {
81
61
  interface H3EventContext {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qelos/integrator-nuxt",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "type": "module",
5
5
  "description": "Nuxt integrator for Qelos: server middleware/module that identifies the user and workspace from the Qelos SDK before your handlers run.",
6
6
  "main": "./dist/module.js",
@@ -59,7 +59,7 @@
59
59
  }
60
60
  },
61
61
  "dependencies": {
62
- "@qelos/sdk": "4.0.0"
62
+ "@qelos/sdk": "4.1.0"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@nuxt/kit": "^3.13.0",