@qelos/integrator-express 4.2.0 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-auth.d.ts +12 -0
- package/dist/mcp-auth.js +34 -0
- package/dist/mcp-auth.js.map +1 -0
- package/dist/types.d.ts +6 -8
- package/package.json +15 -13
- package/LICENSE +0 -20
package/README.md
CHANGED
|
@@ -160,6 +160,14 @@ import { requireUser } from '@qelos/integrator-express';
|
|
|
160
160
|
app.get('/private', requireUser((req, res) => res.json(req.qelos.user)));
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
## MCP OAuth
|
|
164
|
+
|
|
165
|
+
When your custom domain serves MCP clients as an OAuth issuer, add `/login` and
|
|
166
|
+
`/mcp/authorize` routes and use the re-exported MCP helpers
|
|
167
|
+
(`resolveMcpLoginRedirect`, `decodeMcpOAuthStatePayload`,
|
|
168
|
+
`completeMcpAuthorizationCallback`, …). See the Qelos docs:
|
|
169
|
+
[MCP OAuth for integrator apps](https://docs.qelos.io/auth/mcp-oauth-integrators).
|
|
170
|
+
|
|
163
171
|
## Workspace resolution
|
|
164
172
|
|
|
165
173
|
`req.qelos.workspace` defaults to whatever the managed Qelos app reports on
|
|
@@ -204,7 +212,18 @@ createQelosIntegrator({
|
|
|
204
212
|
});
|
|
205
213
|
```
|
|
206
214
|
|
|
207
|
-
##
|
|
215
|
+
## Version support
|
|
216
|
+
|
|
217
|
+
| Runtime | Supported versions |
|
|
218
|
+
|---------|-------------------|
|
|
219
|
+
| Node.js | >= 18 (uses global `fetch` and `Headers.getSetCookie`) |
|
|
220
|
+
| Express | 4.17+ and 5.x |
|
|
221
|
+
|
|
222
|
+
The integrator is tested against Express 4 and Express 5 in CI (`pnpm --filter
|
|
223
|
+
@qelos/integrator-express test`). Express is a peer dependency — install the
|
|
224
|
+
major version your app already uses; no integrator-specific adapter is required.
|
|
208
225
|
|
|
209
|
-
|
|
210
|
-
-
|
|
226
|
+
When upgrading from Express 4 to 5, see the [Express 5 migration
|
|
227
|
+
guide](https://expressjs.com/en/guide/migrating-5.html). This package uses only
|
|
228
|
+
APIs that are stable across both majors (middleware, `req.headers`, response
|
|
229
|
+
headers, and request streaming for the proxy).
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { rewriteSetCookieDomain, rewriteSetCookieDomains } from './cookies';
|
|
|
10
10
|
export { resolveQelosProxyTarget } from './proxy-target';
|
|
11
11
|
export type { QelosExpressConfig, QelosRequestContext, } from './types';
|
|
12
12
|
export { completeSocialAuthCallback, getSocialAuthSetCookieParts, parseSocialCallbackRefreshToken, type SocialAuthCallbackPayload, type SocialCallbackInput, } from './social-auth';
|
|
13
|
+
export { completeMcpAuthorizationCallback, appendMcpAccessDeniedRedirect, buildMcpAuthorizePath, buildMcpAuthorizePathFromQuery, buildMcpConsentPageUrl, buildMcpLoginRedirectUrl, buildMcpTokenExchangeBody, decodeMcpOAuthStatePayload, parseMcpCallbackParams, resolveMcpLoginRedirect, type CompleteMcpAuthorizationCallbackOptions, type DecodedMcpOAuthStatePayload, type McpAuthorizeOptions, type McpCallbackInput, type McpCallbackParams, type McpPagePathOptions, type McpTokenExchangeOptions, type McpTokenExchangeResult, } from './mcp-auth';
|
|
13
14
|
export interface QelosIntegrator {
|
|
14
15
|
/**
|
|
15
16
|
* User-resolution middleware. Forwards inbound cookies to `/api/me` and
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseSocialCallbackRefreshToken = exports.getSocialAuthSetCookieParts = exports.completeSocialAuthCallback = exports.resolveQelosProxyTarget = exports.rewriteSetCookieDomains = exports.rewriteSetCookieDomain = exports.createRequestSdk = exports.createQelosProxy = exports.requireUser = exports.createQelosMiddleware = void 0;
|
|
3
|
+
exports.resolveMcpLoginRedirect = exports.parseMcpCallbackParams = exports.decodeMcpOAuthStatePayload = exports.buildMcpTokenExchangeBody = exports.buildMcpLoginRedirectUrl = exports.buildMcpConsentPageUrl = exports.buildMcpAuthorizePathFromQuery = exports.buildMcpAuthorizePath = exports.appendMcpAccessDeniedRedirect = exports.completeMcpAuthorizationCallback = exports.parseSocialCallbackRefreshToken = exports.getSocialAuthSetCookieParts = exports.completeSocialAuthCallback = exports.resolveQelosProxyTarget = exports.rewriteSetCookieDomains = exports.rewriteSetCookieDomain = exports.createRequestSdk = exports.createQelosProxy = exports.requireUser = exports.createQelosMiddleware = void 0;
|
|
4
4
|
exports.createQelosIntegrator = createQelosIntegrator;
|
|
5
5
|
const middleware_1 = require("./middleware");
|
|
6
6
|
const proxy_1 = require("./proxy");
|
|
@@ -20,6 +20,17 @@ var social_auth_1 = require("./social-auth");
|
|
|
20
20
|
Object.defineProperty(exports, "completeSocialAuthCallback", { enumerable: true, get: function () { return social_auth_1.completeSocialAuthCallback; } });
|
|
21
21
|
Object.defineProperty(exports, "getSocialAuthSetCookieParts", { enumerable: true, get: function () { return social_auth_1.getSocialAuthSetCookieParts; } });
|
|
22
22
|
Object.defineProperty(exports, "parseSocialCallbackRefreshToken", { enumerable: true, get: function () { return social_auth_1.parseSocialCallbackRefreshToken; } });
|
|
23
|
+
var mcp_auth_1 = require("./mcp-auth");
|
|
24
|
+
Object.defineProperty(exports, "completeMcpAuthorizationCallback", { enumerable: true, get: function () { return mcp_auth_1.completeMcpAuthorizationCallback; } });
|
|
25
|
+
Object.defineProperty(exports, "appendMcpAccessDeniedRedirect", { enumerable: true, get: function () { return mcp_auth_1.appendMcpAccessDeniedRedirect; } });
|
|
26
|
+
Object.defineProperty(exports, "buildMcpAuthorizePath", { enumerable: true, get: function () { return mcp_auth_1.buildMcpAuthorizePath; } });
|
|
27
|
+
Object.defineProperty(exports, "buildMcpAuthorizePathFromQuery", { enumerable: true, get: function () { return mcp_auth_1.buildMcpAuthorizePathFromQuery; } });
|
|
28
|
+
Object.defineProperty(exports, "buildMcpConsentPageUrl", { enumerable: true, get: function () { return mcp_auth_1.buildMcpConsentPageUrl; } });
|
|
29
|
+
Object.defineProperty(exports, "buildMcpLoginRedirectUrl", { enumerable: true, get: function () { return mcp_auth_1.buildMcpLoginRedirectUrl; } });
|
|
30
|
+
Object.defineProperty(exports, "buildMcpTokenExchangeBody", { enumerable: true, get: function () { return mcp_auth_1.buildMcpTokenExchangeBody; } });
|
|
31
|
+
Object.defineProperty(exports, "decodeMcpOAuthStatePayload", { enumerable: true, get: function () { return mcp_auth_1.decodeMcpOAuthStatePayload; } });
|
|
32
|
+
Object.defineProperty(exports, "parseMcpCallbackParams", { enumerable: true, get: function () { return mcp_auth_1.parseMcpCallbackParams; } });
|
|
33
|
+
Object.defineProperty(exports, "resolveMcpLoginRedirect", { enumerable: true, get: function () { return mcp_auth_1.resolveMcpLoginRedirect; } });
|
|
23
34
|
/**
|
|
24
35
|
* Build both the user-resolution middleware and the `/api/**` reverse proxy
|
|
25
36
|
* from a single config. When the proxy is enabled (the default), `/api/` is
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AA8EA,sDAkBC;AA/FD,6CAAmF;AACnF,mCAA2C;AAG3C,2CAGsB;AAFpB,mHAAA,qBAAqB,OAAA;AACrB,yGAAA,WAAW,OAAA;AAOb,iCAA2C;AAAlC,yGAAA,gBAAgB,OAAA;AAGzB,6CAAiD;AAAxC,+GAAA,gBAAgB,OAAA;AAGzB,qCAA4E;AAAnE,iHAAA,sBAAsB,OAAA;AAAE,kHAAA,uBAAuB,OAAA;AACxD,+CAAyD;AAAhD,uHAAA,uBAAuB,OAAA;AAOhC,6CAMuB;AALrB,yHAAA,0BAA0B,OAAA;AAC1B,0HAAA,2BAA2B,OAAA;AAC3B,8HAAA,+BAA+B,OAAA;AAKjC,uCAmBoB;AAlBlB,4HAAA,gCAAgC,OAAA;AAChC,yHAAA,6BAA6B,OAAA;AAC7B,iHAAA,qBAAqB,OAAA;AACrB,0HAAA,8BAA8B,OAAA;AAC9B,kHAAA,sBAAsB,OAAA;AACtB,oHAAA,wBAAwB,OAAA;AACxB,qHAAA,yBAAyB,OAAA;AACzB,sHAAA,0BAA0B,OAAA;AAC1B,kHAAA,sBAAsB,OAAA;AACtB,mHAAA,uBAAuB,OAAA;AA0BzB;;;;;GAKG;AACH,SAAgB,qBAAqB,CACnC,OAAgC;IAEhC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,KAAK,IAAI,CAAC;IAE1D,IAAI,MAAM,GAAuB,OAAO,CAAC,MAAM,CAAC;IAChD,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;QACzD,MAAM,cAAc,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QACtF,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAA,kCAAqB,EAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,IAAA,wBAAgB,EAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEjE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type QelosSDK from '@qelos/sdk';
|
|
2
|
+
import type { McpCallbackInput, McpTokenExchangeResult } from '@qelos/sdk';
|
|
3
|
+
export interface CompleteMcpAuthorizationCallbackOptions {
|
|
4
|
+
redirectUri: string;
|
|
5
|
+
codeVerifier: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Parse an MCP OAuth callback and exchange the authorization code for tokens.
|
|
9
|
+
* Use when your app owns the MCP client callback URL (e.g. a local loopback server).
|
|
10
|
+
*/
|
|
11
|
+
export declare function completeMcpAuthorizationCallback(sdk: QelosSDK, input: McpCallbackInput, options: CompleteMcpAuthorizationCallbackOptions): Promise<McpTokenExchangeResult>;
|
|
12
|
+
export { appendMcpAccessDeniedRedirect, buildMcpAuthorizePath, buildMcpAuthorizePathFromQuery, buildMcpConsentPageUrl, buildMcpLoginRedirectUrl, buildMcpTokenExchangeBody, decodeMcpOAuthStatePayload, parseMcpCallbackParams, resolveMcpLoginRedirect, type DecodedMcpOAuthStatePayload, type McpAuthorizeOptions, type McpCallbackInput, type McpCallbackParams, type McpPagePathOptions, type McpTokenExchangeOptions, type McpTokenExchangeResult, } from '@qelos/sdk';
|
package/dist/mcp-auth.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveMcpLoginRedirect = exports.parseMcpCallbackParams = exports.decodeMcpOAuthStatePayload = exports.buildMcpTokenExchangeBody = exports.buildMcpLoginRedirectUrl = exports.buildMcpConsentPageUrl = exports.buildMcpAuthorizePathFromQuery = exports.buildMcpAuthorizePath = exports.appendMcpAccessDeniedRedirect = void 0;
|
|
4
|
+
exports.completeMcpAuthorizationCallback = completeMcpAuthorizationCallback;
|
|
5
|
+
const sdk_1 = require("@qelos/sdk");
|
|
6
|
+
/**
|
|
7
|
+
* Parse an MCP OAuth callback and exchange the authorization code for tokens.
|
|
8
|
+
* Use when your app owns the MCP client callback URL (e.g. a local loopback server).
|
|
9
|
+
*/
|
|
10
|
+
async function completeMcpAuthorizationCallback(sdk, input, options) {
|
|
11
|
+
const params = (0, sdk_1.parseMcpCallbackParams)(input);
|
|
12
|
+
if (params.error) {
|
|
13
|
+
throw new Error(params.errorDescription || params.error);
|
|
14
|
+
}
|
|
15
|
+
if (!params.code) {
|
|
16
|
+
throw new Error('missing authorization code');
|
|
17
|
+
}
|
|
18
|
+
return sdk.authentication.exchangeMcpAuthorizationCode({
|
|
19
|
+
code: params.code,
|
|
20
|
+
redirectUri: options.redirectUri,
|
|
21
|
+
codeVerifier: options.codeVerifier,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
var sdk_2 = require("@qelos/sdk");
|
|
25
|
+
Object.defineProperty(exports, "appendMcpAccessDeniedRedirect", { enumerable: true, get: function () { return sdk_2.appendMcpAccessDeniedRedirect; } });
|
|
26
|
+
Object.defineProperty(exports, "buildMcpAuthorizePath", { enumerable: true, get: function () { return sdk_2.buildMcpAuthorizePath; } });
|
|
27
|
+
Object.defineProperty(exports, "buildMcpAuthorizePathFromQuery", { enumerable: true, get: function () { return sdk_2.buildMcpAuthorizePathFromQuery; } });
|
|
28
|
+
Object.defineProperty(exports, "buildMcpConsentPageUrl", { enumerable: true, get: function () { return sdk_2.buildMcpConsentPageUrl; } });
|
|
29
|
+
Object.defineProperty(exports, "buildMcpLoginRedirectUrl", { enumerable: true, get: function () { return sdk_2.buildMcpLoginRedirectUrl; } });
|
|
30
|
+
Object.defineProperty(exports, "buildMcpTokenExchangeBody", { enumerable: true, get: function () { return sdk_2.buildMcpTokenExchangeBody; } });
|
|
31
|
+
Object.defineProperty(exports, "decodeMcpOAuthStatePayload", { enumerable: true, get: function () { return sdk_2.decodeMcpOAuthStatePayload; } });
|
|
32
|
+
Object.defineProperty(exports, "parseMcpCallbackParams", { enumerable: true, get: function () { return sdk_2.parseMcpCallbackParams; } });
|
|
33
|
+
Object.defineProperty(exports, "resolveMcpLoginRedirect", { enumerable: true, get: function () { return sdk_2.resolveMcpLoginRedirect; } });
|
|
34
|
+
//# sourceMappingURL=mcp-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-auth.js","sourceRoot":"","sources":["../src/mcp-auth.ts"],"names":[],"mappings":";;;AAaA,4EAkBC;AA7BD,oCAAoD;AAOpD;;;GAGG;AACI,KAAK,UAAU,gCAAgC,CACpD,GAAa,EACb,KAAuB,EACvB,OAAgD;IAEhD,MAAM,MAAM,GAAG,IAAA,4BAAsB,EAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,gBAAgB,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,GAAG,CAAC,cAAc,CAAC,4BAA4B,CAAC;QACrD,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CAAC;AACL,CAAC;AAED,kCAiBoB;AAhBlB,oHAAA,6BAA6B,OAAA;AAC7B,4GAAA,qBAAqB,OAAA;AACrB,qHAAA,8BAA8B,OAAA;AAC9B,6GAAA,sBAAsB,OAAA;AACtB,+GAAA,wBAAwB,OAAA;AACxB,gHAAA,yBAAyB,OAAA;AACzB,iHAAA,0BAA0B,OAAA;AAC1B,6GAAA,sBAAsB,OAAA;AACtB,8GAAA,uBAAuB,OAAA"}
|
package/dist/types.d.ts
CHANGED
|
@@ -54,13 +54,11 @@ export interface QelosRequestContext {
|
|
|
54
54
|
*/
|
|
55
55
|
sdk: QelosSDK;
|
|
56
56
|
}
|
|
57
|
-
declare
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
declare module 'express-serve-static-core' {
|
|
63
|
-
interface Request {
|
|
64
|
-
qelos: QelosRequestContext;
|
|
57
|
+
declare global {
|
|
58
|
+
namespace Express {
|
|
59
|
+
interface Request {
|
|
60
|
+
qelos: QelosRequestContext;
|
|
61
|
+
}
|
|
65
62
|
}
|
|
66
63
|
}
|
|
64
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qelos/integrator-express",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.1",
|
|
4
4
|
"description": "Express middleware that identifies the Qelos user and active workspace before your route handlers run",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -23,6 +23,14 @@
|
|
|
23
23
|
"dist",
|
|
24
24
|
"README.md"
|
|
25
25
|
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"type-check": "tsc --noEmit",
|
|
28
|
+
"build": "tsc",
|
|
29
|
+
"pre-build": "tsc",
|
|
30
|
+
"test": "pnpm run test:express5 && pnpm run test:express4",
|
|
31
|
+
"test:express5": "node --import tsx --test src/**/*.test.ts test/middleware.test.ts",
|
|
32
|
+
"test:express4": "node --import tsx --test test/middleware.express4.test.ts"
|
|
33
|
+
},
|
|
26
34
|
"keywords": [
|
|
27
35
|
"qelos",
|
|
28
36
|
"express",
|
|
@@ -47,20 +55,14 @@
|
|
|
47
55
|
}
|
|
48
56
|
},
|
|
49
57
|
"dependencies": {
|
|
50
|
-
"@qelos/global-types": "
|
|
51
|
-
"@qelos/sdk": "
|
|
58
|
+
"@qelos/global-types": "workspace:*",
|
|
59
|
+
"@qelos/sdk": "workspace:*"
|
|
52
60
|
},
|
|
53
61
|
"devDependencies": {
|
|
54
|
-
"@types/express": "^
|
|
55
|
-
"
|
|
56
|
-
"
|
|
62
|
+
"@types/express": "^5.0.0",
|
|
63
|
+
"express": "^5.0.0",
|
|
64
|
+
"express4": "npm:express@^4.21.2",
|
|
57
65
|
"tsx": "^4.21.0",
|
|
58
66
|
"typescript": "^5.6.3"
|
|
59
|
-
},
|
|
60
|
-
"scripts": {
|
|
61
|
-
"type-check": "tsc --noEmit",
|
|
62
|
-
"build": "tsc",
|
|
63
|
-
"pre-build": "tsc",
|
|
64
|
-
"test": "node --import tsx --test src/**/*.test.ts test/**/*.test.ts"
|
|
65
67
|
}
|
|
66
|
-
}
|
|
68
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
Polyform Shield License 1.0.0
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Velocitech LTD
|
|
4
|
-
|
|
5
|
-
Your use of this software is governed by the Polyform Shield License 1.0.0.
|
|
6
|
-
|
|
7
|
-
You may obtain a copy of the License at:
|
|
8
|
-
https://polyformproject.org/licenses/shield/1.0.0
|
|
9
|
-
|
|
10
|
-
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
|
|
12
|
-
Additional Terms – Exception Notice:
|
|
13
|
-
|
|
14
|
-
The author of this software grants additional permissions beyond the Polyform Shield License 1.0.0:
|
|
15
|
-
|
|
16
|
-
✅ All uses of the software are permitted — including modification, distribution, commercial use, and sublicensing — as long as the software is not used to create, offer, or operate any product or service that competes directly with Qelos (https://qelos.io), a no-code platform for building AI-assisted SaaS applications.
|
|
17
|
-
|
|
18
|
-
❌ "Direct competition" includes platforms, tools, or services that enable users to visually or programmatically create SaaS applications with the assistance of artificial intelligence.
|
|
19
|
-
|
|
20
|
-
This exception does not modify the terms of the original Polyform Shield License for other users and applies only by explicit permission of the licensor.
|