heady-gateway 3.2.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 +40 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# @heady/gateway
|
|
2
|
+
|
|
3
|
+
> API gateway with cross-domain auth, rate limiting, and service routing for the Heady™ AI Platform.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @heady/gateway
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createGateway } from '@heady/gateway';
|
|
15
|
+
|
|
16
|
+
const gw = createGateway({ rateLimitRpm: 600 });
|
|
17
|
+
|
|
18
|
+
// Route a domain to a service
|
|
19
|
+
const service = gw.route('headyme.com'); // → 'command-center'
|
|
20
|
+
|
|
21
|
+
// Check rate limit
|
|
22
|
+
const { allowed, remaining } = gw.checkRateLimit('client-123');
|
|
23
|
+
|
|
24
|
+
// CORS headers
|
|
25
|
+
const headers = gw.getCorsHeaders('https://headyme.com');
|
|
26
|
+
|
|
27
|
+
// Status
|
|
28
|
+
const status = gw.getStatus();
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- **9-domain routing** — headyme.com, headyio.com, headymcp.com, and more
|
|
34
|
+
- **Token-bucket rate limiting** per client
|
|
35
|
+
- **CORS management** with configurable origins
|
|
36
|
+
- **Request metrics** tracking
|
|
37
|
+
|
|
38
|
+
## License
|
|
39
|
+
|
|
40
|
+
Proprietary — © 2026 HeadySystems Inc.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @heady/gateway — API Gateway with Auth + Rate Limiting
|
|
3
|
+
*
|
|
4
|
+
* Routes requests across Heady services with:
|
|
5
|
+
* - Cross-domain authentication (sign in once, roam all sites)
|
|
6
|
+
* - Token-bucket rate limiting per tenant
|
|
7
|
+
* - Request routing based on domain → service mapping
|
|
8
|
+
*/
|
|
9
|
+
export interface GatewayConfig {
|
|
10
|
+
domains: Record<string, string>;
|
|
11
|
+
rateLimitRpm: number;
|
|
12
|
+
corsOrigins: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface RateLimitState {
|
|
15
|
+
tokens: number;
|
|
16
|
+
lastRefill: number;
|
|
17
|
+
maxTokens: number;
|
|
18
|
+
refillRate: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class HeadyGateway {
|
|
21
|
+
private config;
|
|
22
|
+
private rateLimits;
|
|
23
|
+
private routedCount;
|
|
24
|
+
constructor(config?: Partial<GatewayConfig>);
|
|
25
|
+
route(hostname: string): string | null;
|
|
26
|
+
checkRateLimit(clientId: string): {
|
|
27
|
+
allowed: boolean;
|
|
28
|
+
remaining: number;
|
|
29
|
+
};
|
|
30
|
+
getCorsHeaders(origin: string): Record<string, string>;
|
|
31
|
+
getStatus(): {
|
|
32
|
+
ok: boolean;
|
|
33
|
+
domains: number;
|
|
34
|
+
routedCount: number;
|
|
35
|
+
rateLimitClients: number;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export declare function createGateway(config?: Partial<GatewayConfig>): HeadyGateway;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB;AAcD,qBAAa,YAAY;IACrB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,WAAW,CAAK;gBAEZ,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAQ3C,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKtC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAwBzE,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAUtD,SAAS;;;;;;CAQZ;AAED,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,YAAY,CAE3E"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @heady/gateway — API Gateway with Auth + Rate Limiting
|
|
4
|
+
*
|
|
5
|
+
* Routes requests across Heady services with:
|
|
6
|
+
* - Cross-domain authentication (sign in once, roam all sites)
|
|
7
|
+
* - Token-bucket rate limiting per tenant
|
|
8
|
+
* - Request routing based on domain → service mapping
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.HeadyGateway = void 0;
|
|
12
|
+
exports.createGateway = createGateway;
|
|
13
|
+
const DEFAULT_DOMAINS = {
|
|
14
|
+
'headyme.com': 'command-center',
|
|
15
|
+
'headyio.com': 'heady-io-docs',
|
|
16
|
+
'headymcp.com': 'heady-mcp-portal',
|
|
17
|
+
'headysystems.com': 'heady-systems',
|
|
18
|
+
'headyconnection.org': 'heady-connection',
|
|
19
|
+
'headybuddy.org': 'heady-buddy',
|
|
20
|
+
'headybot.com': 'heady-bot',
|
|
21
|
+
'headyapi.com': 'heady-api',
|
|
22
|
+
'headyai.com': 'heady-ai',
|
|
23
|
+
};
|
|
24
|
+
class HeadyGateway {
|
|
25
|
+
config;
|
|
26
|
+
rateLimits = new Map();
|
|
27
|
+
routedCount = 0;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.config = {
|
|
30
|
+
domains: config?.domains || DEFAULT_DOMAINS,
|
|
31
|
+
rateLimitRpm: config?.rateLimitRpm || 600,
|
|
32
|
+
corsOrigins: config?.corsOrigins || Object.keys(DEFAULT_DOMAINS).map(d => `https://${d}`),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
route(hostname) {
|
|
36
|
+
this.routedCount++;
|
|
37
|
+
return this.config.domains[hostname] || null;
|
|
38
|
+
}
|
|
39
|
+
checkRateLimit(clientId) {
|
|
40
|
+
let state = this.rateLimits.get(clientId);
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
const maxTokens = this.config.rateLimitRpm;
|
|
43
|
+
const refillRate = maxTokens / 60000; // tokens per ms
|
|
44
|
+
if (!state) {
|
|
45
|
+
state = { tokens: maxTokens, lastRefill: now, maxTokens, refillRate };
|
|
46
|
+
this.rateLimits.set(clientId, state);
|
|
47
|
+
}
|
|
48
|
+
// Refill tokens
|
|
49
|
+
const elapsed = now - state.lastRefill;
|
|
50
|
+
state.tokens = Math.min(maxTokens, state.tokens + elapsed * refillRate);
|
|
51
|
+
state.lastRefill = now;
|
|
52
|
+
if (state.tokens >= 1) {
|
|
53
|
+
state.tokens -= 1;
|
|
54
|
+
return { allowed: true, remaining: Math.floor(state.tokens) };
|
|
55
|
+
}
|
|
56
|
+
return { allowed: false, remaining: 0 };
|
|
57
|
+
}
|
|
58
|
+
getCorsHeaders(origin) {
|
|
59
|
+
const allowed = this.config.corsOrigins.includes(origin);
|
|
60
|
+
return {
|
|
61
|
+
'Access-Control-Allow-Origin': allowed ? origin : '',
|
|
62
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
63
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
64
|
+
'Access-Control-Max-Age': '86400',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
getStatus() {
|
|
68
|
+
return {
|
|
69
|
+
ok: true,
|
|
70
|
+
domains: Object.keys(this.config.domains).length,
|
|
71
|
+
routedCount: this.routedCount,
|
|
72
|
+
rateLimitClients: this.rateLimits.size,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.HeadyGateway = HeadyGateway;
|
|
77
|
+
function createGateway(config) {
|
|
78
|
+
return new HeadyGateway(config);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "heady-gateway",
|
|
3
|
+
"version": "3.2.0",
|
|
4
|
+
"description": "API gateway with cross-domain auth, token-bucket rate limiting, and domain-to-service routing for the Heady AI Platform.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"test": "jest",
|
|
21
|
+
"clean": "rm -rf dist",
|
|
22
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"heady-core": "^3.2.0"
|
|
26
|
+
},
|
|
27
|
+
"license": "UNLICENSED",
|
|
28
|
+
"author": {
|
|
29
|
+
"name": "HeadySystems Inc.",
|
|
30
|
+
"email": "eric@headyconnection.org",
|
|
31
|
+
"url": "https://headyme.com"
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/HeadyMe/heady-production.git",
|
|
36
|
+
"directory": "packages/gateway"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://headysystems.com",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/HeadyMe/heady-production/issues"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"heady",
|
|
44
|
+
"ai",
|
|
45
|
+
"gateway",
|
|
46
|
+
"api-gateway",
|
|
47
|
+
"rate-limiting",
|
|
48
|
+
"auth",
|
|
49
|
+
"cors"
|
|
50
|
+
],
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|