@stratum-hq/sdk 1.0.1 → 1.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/README.md +6 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +60 -20
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/middleware/express.d.ts.map +1 -1
- package/dist/middleware/express.js +8 -18
- package/dist/middleware/express.js.map +1 -1
- package/dist/middleware/fastify.d.ts.map +1 -1
- package/dist/middleware/fastify.js +13 -19
- package/dist/middleware/fastify.js.map +1 -1
- package/dist/resolvers/header.d.ts +5 -1
- package/dist/resolvers/header.d.ts.map +1 -1
- package/dist/resolvers/header.js +8 -2
- package/dist/resolvers/header.js.map +1 -1
- package/dist/resolvers/jwt.d.ts +28 -0
- package/dist/resolvers/jwt.d.ts.map +1 -1
- package/dist/resolvers/jwt.js +46 -9
- package/dist/resolvers/jwt.js.map +1 -1
- package/dist/resolvers/resolve.d.ts +25 -0
- package/dist/resolvers/resolve.d.ts.map +1 -0
- package/dist/resolvers/resolve.js +39 -0
- package/dist/resolvers/resolve.js.map +1 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -52,12 +52,16 @@ app.get("/data", (req, res) => {
|
|
|
52
52
|
|
|
53
53
|
## Features
|
|
54
54
|
|
|
55
|
-
- **`StratumClient`** — HTTP client for the control plane API (`resolveTenant`, `getTenantTree`, `createTenant`, `createWebhook`, `listRegions`, …) with a built-in LRU cache
|
|
55
|
+
- **`StratumClient`** — HTTP client for the control plane API (`resolveTenant`, `getTenantTree`, `createTenant`, `createWebhook`, `listRegions`, …) with a built-in LRU cache. Mutations made through the client invalidate affected entries (a move clears the whole cache); changes made elsewhere, such as a suspension or a config or permission change, are picked up when the entry expires, so the cache TTL (`cache.ttlMs`, default 60s) bounds how stale a context can be.
|
|
56
56
|
- **`expressMiddleware` / `fastifyPlugin`** — resolve the tenant from a JWT claim, `X-Tenant-ID` header, or custom resolvers (tried in that order), then populate `req.tenant`.
|
|
57
57
|
- **AsyncLocalStorage context** — `getTenantContext()` and `runWithTenantContext()` make the resolved context available to services that never see the request object.
|
|
58
58
|
- **Custom resolvers** — supply async functions (e.g. subdomain- or query-based) via the `resolvers` option.
|
|
59
59
|
|
|
60
|
-
JWT resolution activates only when `jwtSecret` or `jwtVerify` is provided; otherwise Bearer tokens are ignored. If no tenant is found, the middleware returns `400 MISSING_TENANT`.
|
|
60
|
+
JWT resolution activates only when `jwtSecret` or `jwtVerify` is provided; otherwise Bearer tokens are ignored. When it is active, the verified JWT is the tenant binding: a Bearer token that fails verification is rejected with `401 INVALID_TOKEN`, and the tenant header is not read unless you set `trustTenantHeader: true`. If no tenant is found, the middleware returns `400 MISSING_TENANT`.
|
|
61
|
+
|
|
62
|
+
`jwtSecret` verifies HS256 tokens with [`jsonwebtoken`](https://www.npmjs.com/package/jsonwebtoken), an optional peer dependency: install it alongside the SDK (`npm install jsonwebtoken`) or pass `jwtVerify` instead. The middleware throws at construction if `jwtSecret` is set and `jsonwebtoken` cannot be loaded.
|
|
63
|
+
|
|
64
|
+
`headerName` replaces the default `X-Tenant-ID` header: when it is set, only that header is read.
|
|
61
65
|
|
|
62
66
|
## Error Handling
|
|
63
67
|
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGhO,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGhO,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE;AAyCD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0C;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;gBAE3B,OAAO,EAAE,oBAAoB;YAW3B,KAAK;IA2Bb,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAkB/D,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAQrD,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAO3D,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAIhD,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAS7E,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IAUzE,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIvC,UAAU,IAAI,IAAI;IAIZ,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAO1D,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAOnD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxC,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAOtE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAOzI,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAOzL,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAQ1I,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIhC,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAOvD,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAOnE,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAK9C"}
|
package/dist/client.js
CHANGED
|
@@ -3,6 +3,40 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.StratumClient = void 0;
|
|
4
4
|
const core_1 = require("@stratum-hq/core");
|
|
5
5
|
const cache_js_1 = require("./cache.js");
|
|
6
|
+
/**
|
|
7
|
+
* Encode an ID for use as a single URL path segment. Dot segments are refused
|
|
8
|
+
* because URL parsing would resolve them against the surrounding path.
|
|
9
|
+
*/
|
|
10
|
+
function pathSegment(id) {
|
|
11
|
+
if (id === "" || id === "." || id === "..") {
|
|
12
|
+
throw new Error("Invalid identifier");
|
|
13
|
+
}
|
|
14
|
+
return encodeURIComponent(id);
|
|
15
|
+
}
|
|
16
|
+
function cacheKey(tenantId) {
|
|
17
|
+
return tenantId.toLowerCase();
|
|
18
|
+
}
|
|
19
|
+
function isObject(value) {
|
|
20
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check that a /context response is a ResolvedTenantContext for the requested
|
|
24
|
+
* tenant. Anything else fails closed rather than being bound as the request's
|
|
25
|
+
* tenant.
|
|
26
|
+
*/
|
|
27
|
+
function assertResolvedTenantContext(value, tenantId) {
|
|
28
|
+
const ok = isObject(value) &&
|
|
29
|
+
typeof value["tenant_id"] === "string" &&
|
|
30
|
+
value["tenant_id"].toLowerCase() === tenantId.toLowerCase() &&
|
|
31
|
+
typeof value["ancestry_path"] === "string" &&
|
|
32
|
+
typeof value["depth"] === "number" &&
|
|
33
|
+
isObject(value["resolved_config"]) &&
|
|
34
|
+
isObject(value["resolved_permissions"]) &&
|
|
35
|
+
typeof value["isolation_strategy"] === "string";
|
|
36
|
+
if (!ok) {
|
|
37
|
+
throw new Error("Control plane returned an invalid tenant context");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
6
40
|
class StratumClient {
|
|
7
41
|
baseUrl;
|
|
8
42
|
apiKey;
|
|
@@ -45,20 +79,25 @@ class StratumClient {
|
|
|
45
79
|
return response.json();
|
|
46
80
|
}
|
|
47
81
|
async resolveTenant(tenantId) {
|
|
82
|
+
if (tenantId === "" || tenantId === "." || tenantId === "..") {
|
|
83
|
+
throw new core_1.TenantNotFoundError(tenantId);
|
|
84
|
+
}
|
|
85
|
+
const path = `/api/v1/tenants/${pathSegment(tenantId)}/context`;
|
|
48
86
|
if (this.cacheEnabled) {
|
|
49
|
-
const cached = this.cache.get(tenantId);
|
|
87
|
+
const cached = this.cache.get(cacheKey(tenantId));
|
|
50
88
|
if (cached)
|
|
51
89
|
return cached;
|
|
52
90
|
}
|
|
53
|
-
const context = await this.fetch(
|
|
91
|
+
const context = await this.fetch(path);
|
|
92
|
+
assertResolvedTenantContext(context, tenantId);
|
|
54
93
|
if (this.cacheEnabled) {
|
|
55
|
-
this.cache.set(tenantId, context);
|
|
94
|
+
this.cache.set(cacheKey(tenantId), context);
|
|
56
95
|
}
|
|
57
96
|
return context;
|
|
58
97
|
}
|
|
59
98
|
async getTenantTree(rootId) {
|
|
60
99
|
if (rootId) {
|
|
61
|
-
return this.fetch(`/api/v1/tenants/${rootId}/descendants`);
|
|
100
|
+
return this.fetch(`/api/v1/tenants/${pathSegment(rootId)}/descendants`);
|
|
62
101
|
}
|
|
63
102
|
const result = await this.fetch(`/api/v1/tenants`);
|
|
64
103
|
return result.data;
|
|
@@ -70,38 +109,39 @@ class StratumClient {
|
|
|
70
109
|
});
|
|
71
110
|
}
|
|
72
111
|
async getTenant(tenantId) {
|
|
73
|
-
return this.fetch(`/api/v1/tenants/${tenantId}`);
|
|
112
|
+
return this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}`);
|
|
74
113
|
}
|
|
75
114
|
async updateTenant(tenantId, input) {
|
|
76
|
-
const node = await this.fetch(`/api/v1/tenants/${tenantId}`, {
|
|
115
|
+
const node = await this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}`, {
|
|
77
116
|
method: "PATCH",
|
|
78
117
|
body: JSON.stringify(input),
|
|
79
118
|
});
|
|
80
|
-
this.cache.invalidate(tenantId);
|
|
119
|
+
this.cache.invalidate(cacheKey(tenantId));
|
|
81
120
|
return node;
|
|
82
121
|
}
|
|
83
122
|
async moveTenant(tenantId, input) {
|
|
84
|
-
const node = await this.fetch(`/api/v1/tenants/${tenantId}/move`, {
|
|
123
|
+
const node = await this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}/move`, {
|
|
85
124
|
method: "POST",
|
|
86
125
|
body: JSON.stringify(input),
|
|
87
126
|
});
|
|
88
|
-
|
|
127
|
+
// Descendants' cached ancestry, config and permissions change with the move.
|
|
128
|
+
this.cache.clear();
|
|
89
129
|
return node;
|
|
90
130
|
}
|
|
91
131
|
async archiveTenant(tenantId) {
|
|
92
|
-
await this.fetch(`/api/v1/tenants/${tenantId}`, {
|
|
132
|
+
await this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}`, {
|
|
93
133
|
method: "DELETE",
|
|
94
134
|
});
|
|
95
|
-
this.cache.invalidate(tenantId);
|
|
135
|
+
this.cache.invalidate(cacheKey(tenantId));
|
|
96
136
|
}
|
|
97
137
|
async deleteTenant(tenantId) {
|
|
98
|
-
await this.fetch(`/api/v1/tenants/${tenantId}`, {
|
|
138
|
+
await this.fetch(`/api/v1/tenants/${pathSegment(tenantId)}`, {
|
|
99
139
|
method: "DELETE",
|
|
100
140
|
});
|
|
101
|
-
this.cache.invalidate(tenantId);
|
|
141
|
+
this.cache.invalidate(cacheKey(tenantId));
|
|
102
142
|
}
|
|
103
143
|
invalidateCache(tenantId) {
|
|
104
|
-
this.cache.invalidate(tenantId);
|
|
144
|
+
this.cache.invalidate(cacheKey(tenantId));
|
|
105
145
|
}
|
|
106
146
|
clearCache() {
|
|
107
147
|
this.cache.clear();
|
|
@@ -119,21 +159,21 @@ class StratumClient {
|
|
|
119
159
|
return this.fetch(path);
|
|
120
160
|
}
|
|
121
161
|
async getWebhook(id) {
|
|
122
|
-
return this.fetch(`/api/v1/webhooks/${id}`);
|
|
162
|
+
return this.fetch(`/api/v1/webhooks/${pathSegment(id)}`);
|
|
123
163
|
}
|
|
124
164
|
async updateWebhook(id, input) {
|
|
125
|
-
return this.fetch(`/api/v1/webhooks/${id}`, {
|
|
165
|
+
return this.fetch(`/api/v1/webhooks/${pathSegment(id)}`, {
|
|
126
166
|
method: "PATCH",
|
|
127
167
|
body: JSON.stringify(input),
|
|
128
168
|
});
|
|
129
169
|
}
|
|
130
170
|
async deleteWebhook(id) {
|
|
131
|
-
await this.fetch(`/api/v1/webhooks/${id}`, {
|
|
171
|
+
await this.fetch(`/api/v1/webhooks/${pathSegment(id)}`, {
|
|
132
172
|
method: "DELETE",
|
|
133
173
|
});
|
|
134
174
|
}
|
|
135
175
|
async rotateApiKey(keyId, name) {
|
|
136
|
-
return this.fetch(`/api/v1/api-keys/${keyId}/rotate`, {
|
|
176
|
+
return this.fetch(`/api/v1/api-keys/${pathSegment(keyId)}/rotate`, {
|
|
137
177
|
method: "POST",
|
|
138
178
|
body: JSON.stringify(name ? { name } : {}),
|
|
139
179
|
});
|
|
@@ -161,13 +201,13 @@ class StratumClient {
|
|
|
161
201
|
});
|
|
162
202
|
}
|
|
163
203
|
async updateRegion(id, input) {
|
|
164
|
-
return this.fetch(`/api/v1/regions/${id}`, {
|
|
204
|
+
return this.fetch(`/api/v1/regions/${pathSegment(id)}`, {
|
|
165
205
|
method: "PATCH",
|
|
166
206
|
body: JSON.stringify(input),
|
|
167
207
|
});
|
|
168
208
|
}
|
|
169
209
|
async deleteRegion(id) {
|
|
170
|
-
await this.fetch(`/api/v1/regions/${id}`, {
|
|
210
|
+
await this.fetch(`/api/v1/regions/${pathSegment(id)}`, {
|
|
171
211
|
method: "DELETE",
|
|
172
212
|
});
|
|
173
213
|
}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAAA,2CAA0E;AAE1E,yCAAsC;AAStC,MAAa,aAAa;IACP,OAAO,CAAS;IAChB,MAAM,CAAS;IACf,SAAS,CAAqB;IAC9B,KAAK,CAA0C;IAC/C,YAAY,CAAU;IAEvC,YAAY,OAA6B;QACvC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,CAAC;QACrD,IAAI,CAAC,KAAK,GAAG,IAAI,mBAAQ,CAAgC;YACvD,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK;YAC3B,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,KAAK,CAAI,IAAY,EAAE,IAAkB;QACrD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE;YAC3C,GAAG,IAAI;YACP,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;gBACxB,GAAI,IAAI,EAAE,OAA8C;aACzD;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,IAAI,wBAAiB,CAAC,4BAA4B,CAAC,CAAC;YAC5D,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAqC,CAAC;gBACzF,MAAM,IAAI,0BAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,SAAS,CAAC,CAAC;YACnE,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAqC,CAAC;YACzF,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,SAAc,CAAC;QACnD,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB;QAClC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -25,7 +25,9 @@ export { getTenantContext, runWithTenantContext, setTenantContext } from "./cont
|
|
|
25
25
|
export { expressMiddleware } from "./middleware/express.js";
|
|
26
26
|
export { fastifyPlugin } from "./middleware/fastify.js";
|
|
27
27
|
export { resolveFromHeader } from "./resolvers/header.js";
|
|
28
|
-
export { resolveFromJwt } from "./resolvers/jwt.js";
|
|
28
|
+
export { resolveFromJwt, assertJwtSupport } from "./resolvers/jwt.js";
|
|
29
|
+
export { resolveTenantId } from "./resolvers/resolve.js";
|
|
30
|
+
export type { TenantIdResolution } from "./resolvers/resolve.js";
|
|
29
31
|
export type { TenantResolver } from "./resolvers/custom.js";
|
|
30
32
|
export type { MiddlewareOptions } from "./types.js";
|
|
31
33
|
export type { ResolvedTenantContext, TenantNode, CreateTenantInput, UpdateTenantInput, MoveTenantInput, ResolvedPermission, } from "@stratum-hq/core";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,OAAO,CAAC,OAAO,EAAE,oBAAoB;;wBAI7B,iBAAiB;;;;;;;;;;oBACrB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,OAAO,CAAC,OAAO,EAAE,oBAAoB;;wBAI7B,iBAAiB;;;;;;;;;;oBACrB,iBAAiB,eAEpB,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,SACrC,OAAO,QACR,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC;;;EAShD;AAGD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,YAAY,EACV,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveFromJwt = exports.resolveFromHeader = exports.fastifyPlugin = exports.expressMiddleware = exports.setTenantContext = exports.runWithTenantContext = exports.getTenantContext = exports.StratumClient = void 0;
|
|
3
|
+
exports.resolveTenantId = exports.assertJwtSupport = exports.resolveFromJwt = exports.resolveFromHeader = exports.fastifyPlugin = exports.expressMiddleware = exports.setTenantContext = exports.runWithTenantContext = exports.getTenantContext = exports.StratumClient = void 0;
|
|
4
4
|
exports.stratum = stratum;
|
|
5
5
|
const client_js_1 = require("./client.js");
|
|
6
6
|
const express_js_1 = require("./middleware/express.js");
|
|
@@ -11,7 +11,12 @@ function stratum(options) {
|
|
|
11
11
|
return {
|
|
12
12
|
client,
|
|
13
13
|
middleware: (opts) => (0, express_js_1.expressMiddleware)(client, opts),
|
|
14
|
-
plugin: (opts) =>
|
|
14
|
+
plugin: (opts) => {
|
|
15
|
+
const plugin = (fastify, _opts, done) => (0, fastify_js_1.fastifyPlugin)(fastify, { client, ...opts }, done);
|
|
16
|
+
// Same non-encapsulated registration as fastifyPlugin itself.
|
|
17
|
+
plugin[Symbol.for("skip-override")] = true;
|
|
18
|
+
return plugin;
|
|
19
|
+
},
|
|
15
20
|
getTenantContext: context_js_1.getTenantContext,
|
|
16
21
|
runWithTenantContext: context_js_1.runWithTenantContext,
|
|
17
22
|
};
|
|
@@ -31,4 +36,7 @@ var header_js_1 = require("./resolvers/header.js");
|
|
|
31
36
|
Object.defineProperty(exports, "resolveFromHeader", { enumerable: true, get: function () { return header_js_1.resolveFromHeader; } });
|
|
32
37
|
var jwt_js_1 = require("./resolvers/jwt.js");
|
|
33
38
|
Object.defineProperty(exports, "resolveFromJwt", { enumerable: true, get: function () { return jwt_js_1.resolveFromJwt; } });
|
|
39
|
+
Object.defineProperty(exports, "assertJwtSupport", { enumerable: true, get: function () { return jwt_js_1.assertJwtSupport; } });
|
|
40
|
+
var resolve_js_1 = require("./resolvers/resolve.js");
|
|
41
|
+
Object.defineProperty(exports, "resolveTenantId", { enumerable: true, get: function () { return resolve_js_1.resolveTenantId; } });
|
|
34
42
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAOA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAOA,0BAkBC;AAzBD,2CAA4C;AAE5C,wDAA4D;AAC5D,wDAAwD;AACxD,6CAAsE;AAGtE,SAAgB,OAAO,CAAC,OAA6B;IACnD,MAAM,MAAM,GAAG,IAAI,yBAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO;QACL,MAAM;QACN,UAAU,EAAE,CAAC,IAAwB,EAAE,EAAE,CAAC,IAAA,8BAAiB,EAAC,MAAM,EAAE,IAAI,CAAC;QACzE,MAAM,EAAE,CAAC,IAAwB,EAAE,EAAE;YACnC,MAAM,MAAM,GAAG,CACb,OAA4C,EAC5C,KAAc,EACd,IAAyC,EACzC,EAAE,CAAC,IAAA,0BAAa,EAAC,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;YACvD,8DAA8D;YAC7D,MAA6C,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI,CAAC;YACnF,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,gBAAgB,EAAhB,6BAAgB;QAChB,oBAAoB,EAApB,iCAAoB;KACrB,CAAC;AACJ,CAAC;AAED,iCAAiC;AACjC,yCAA4C;AAAnC,0GAAA,aAAa,OAAA;AAEtB,2CAAwF;AAA/E,8GAAA,gBAAgB,OAAA;AAAE,kHAAA,oBAAoB,OAAA;AAAE,8GAAA,gBAAgB,OAAA;AACjE,sDAA4D;AAAnD,+GAAA,iBAAiB,OAAA;AAC1B,sDAAwD;AAA/C,2GAAA,aAAa,OAAA;AACtB,mDAA0D;AAAjD,8GAAA,iBAAiB,OAAA;AAC1B,6CAAsE;AAA7D,wGAAA,cAAc,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AACzC,qDAAyD;AAAhD,6GAAA,eAAe,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAOrD,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAEtC,KAAK,kBAAkB,GAAG;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;CACrD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAOrD,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAEtC,KAAK,kBAAkB,GAAG;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;CACrD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,iBAAiB,IAEpE,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CAyE9F"}
|
|
@@ -4,32 +4,22 @@ exports.expressMiddleware = expressMiddleware;
|
|
|
4
4
|
const core_1 = require("@stratum-hq/core");
|
|
5
5
|
const context_js_1 = require("../context.js");
|
|
6
6
|
const jwt_js_1 = require("../resolvers/jwt.js");
|
|
7
|
-
const
|
|
7
|
+
const resolve_js_1 = require("../resolvers/resolve.js");
|
|
8
8
|
function expressMiddleware(client, options) {
|
|
9
|
+
(0, jwt_js_1.assertJwtSupport)(options);
|
|
9
10
|
return async (req, res, next) => {
|
|
10
11
|
try {
|
|
11
12
|
// Resolve tenant ID: JWT → header → custom resolvers
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
});
|
|
17
|
-
if (!tenantId) {
|
|
18
|
-
tenantId = (0, header_js_1.resolveFromHeader)(req);
|
|
19
|
-
}
|
|
20
|
-
if (!tenantId && options?.resolvers) {
|
|
21
|
-
for (const resolver of options.resolvers) {
|
|
22
|
-
const result = await resolver.resolve(req);
|
|
23
|
-
if (result) {
|
|
24
|
-
tenantId = result;
|
|
25
|
-
break;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
13
|
+
const resolution = await (0, resolve_js_1.resolveTenantId)(req, options);
|
|
14
|
+
if (resolution.status === "invalid_token") {
|
|
15
|
+
res.status(401).json({ error: { code: "INVALID_TOKEN", message: "Bearer token could not be verified" } });
|
|
16
|
+
return;
|
|
28
17
|
}
|
|
29
|
-
if (
|
|
18
|
+
if (resolution.status === "missing") {
|
|
30
19
|
res.status(400).json({ error: { code: "MISSING_TENANT", message: "Tenant ID could not be resolved from request" } });
|
|
31
20
|
return;
|
|
32
21
|
}
|
|
22
|
+
const tenantId = resolution.tenantId;
|
|
33
23
|
let context;
|
|
34
24
|
try {
|
|
35
25
|
context = await client.resolveTenant(tenantId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":";;AAsBA,
|
|
1
|
+
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAOrD,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAEtC,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,UAAU,gBAAgB;IACxB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;CACrD;AAED,UAAU,WAAW;IACnB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACpD,OAAO,CACL,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GACpF,IAAI,CAAC;CACT;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG,iBAAiB,EACtD,IAAI,EAAE,MAAM,GACX,IAAI,
|
|
1
|
+
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAOrD,KAAK,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAEtC,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,UAAU,gBAAgB;IACxB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;CACrD;AAED,UAAU,WAAW;IACnB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACpD,OAAO,CACL,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GACpF,IAAI,CAAC;CACT;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG,iBAAiB,EACtD,IAAI,EAAE,MAAM,GACX,IAAI,CA+EN"}
|
|
@@ -4,36 +4,26 @@ exports.fastifyPlugin = fastifyPlugin;
|
|
|
4
4
|
const core_1 = require("@stratum-hq/core");
|
|
5
5
|
const context_js_1 = require("../context.js");
|
|
6
6
|
const jwt_js_1 = require("../resolvers/jwt.js");
|
|
7
|
-
const
|
|
7
|
+
const resolve_js_1 = require("../resolvers/resolve.js");
|
|
8
8
|
function fastifyPlugin(fastify, options, done) {
|
|
9
9
|
const { client, ...middlewareOptions } = options;
|
|
10
|
+
(0, jwt_js_1.assertJwtSupport)(middlewareOptions);
|
|
10
11
|
fastify.decorateRequest("tenant", null);
|
|
11
12
|
fastify.decorateRequest("impersonating", false);
|
|
12
13
|
fastify.decorateRequest("originalTenantId", null);
|
|
13
14
|
fastify.addHook("onRequest", (request, reply, done) => {
|
|
14
|
-
// Resolve tenant ID: JWT → header → custom resolvers
|
|
15
|
-
let tenantId = null;
|
|
16
|
-
tenantId = (0, jwt_js_1.resolveFromJwt)(request, middlewareOptions.jwtClaimPath, {
|
|
17
|
-
secret: middlewareOptions.jwtSecret,
|
|
18
|
-
verify: middlewareOptions.jwtVerify,
|
|
19
|
-
});
|
|
20
|
-
if (!tenantId) {
|
|
21
|
-
tenantId = (0, header_js_1.resolveFromHeader)(request);
|
|
22
|
-
}
|
|
23
15
|
const resolveAndRun = async () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
break;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
16
|
+
// Resolve tenant ID: JWT → header → custom resolvers
|
|
17
|
+
const resolution = await (0, resolve_js_1.resolveTenantId)(request, middlewareOptions);
|
|
18
|
+
if (resolution.status === "invalid_token") {
|
|
19
|
+
reply.status(401).send({ error: { code: "INVALID_TOKEN", message: "Bearer token could not be verified" } });
|
|
20
|
+
return;
|
|
32
21
|
}
|
|
33
|
-
if (
|
|
22
|
+
if (resolution.status === "missing") {
|
|
34
23
|
reply.status(400).send({ error: { code: "MISSING_TENANT", message: "Tenant ID could not be resolved from request" } });
|
|
35
24
|
return;
|
|
36
25
|
}
|
|
26
|
+
const tenantId = resolution.tenantId;
|
|
37
27
|
let context;
|
|
38
28
|
try {
|
|
39
29
|
context = await client.resolveTenant(tenantId);
|
|
@@ -81,4 +71,8 @@ function fastifyPlugin(fastify, options, done) {
|
|
|
81
71
|
});
|
|
82
72
|
done();
|
|
83
73
|
}
|
|
74
|
+
// Register the hook and decorators on the instance that calls
|
|
75
|
+
// `register(fastifyPlugin)`, not in an encapsulated child context, so routes
|
|
76
|
+
// declared on that instance run the tenant hook (the fastify-plugin convention).
|
|
77
|
+
fastifyPlugin[Symbol.for("skip-override")] = true;
|
|
84
78
|
//# sourceMappingURL=fastify.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":";;AA+BA,
|
|
1
|
+
{"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Read the tenant ID from a request header. When `headerName` is given, only
|
|
3
|
+
* that header is read; otherwise the default X-Tenant-ID header is used.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resolveFromHeader(req: unknown, headerName?: string): string | null;
|
|
2
6
|
//# sourceMappingURL=header.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/resolvers/header.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/resolvers/header.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASlF"}
|
package/dist/resolvers/header.js
CHANGED
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveFromHeader = resolveFromHeader;
|
|
4
4
|
const core_1 = require("@stratum-hq/core");
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Read the tenant ID from a request header. When `headerName` is given, only
|
|
7
|
+
* that header is read; otherwise the default X-Tenant-ID header is used.
|
|
8
|
+
*/
|
|
9
|
+
function resolveFromHeader(req, headerName) {
|
|
6
10
|
const r = req;
|
|
7
11
|
const headers = r["headers"];
|
|
8
12
|
if (!headers)
|
|
9
13
|
return null;
|
|
10
|
-
const value =
|
|
14
|
+
const value = headerName
|
|
15
|
+
? headers[headerName.toLowerCase()]
|
|
16
|
+
: headers[core_1.TENANT_HEADER.toLowerCase()] ?? headers[core_1.TENANT_HEADER];
|
|
11
17
|
if (!value)
|
|
12
18
|
return null;
|
|
13
19
|
return Array.isArray(value) ? value[0] ?? null : value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/resolvers/header.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/resolvers/header.ts"],"names":[],"mappings":";;AAMA,8CASC;AAfD,2CAAiD;AAEjD;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,GAAY,EAAE,UAAmB;IACjE,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAA8D,CAAC;IAC1F,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,KAAK,GAAG,UAAU;QACtB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;QACnC,CAAC,CAAC,OAAO,CAAC,oBAAa,CAAC,WAAW,EAAE,CAAC,IAAI,OAAO,CAAC,oBAAa,CAAC,CAAC;IACnE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC"}
|
package/dist/resolvers/jwt.d.ts
CHANGED
|
@@ -2,5 +2,33 @@ export interface JwtResolverOptions {
|
|
|
2
2
|
secret?: string;
|
|
3
3
|
verify?: (token: string) => Record<string, unknown> | null;
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Throw if `jwtSecret` is configured without a `jwtVerify` function and the
|
|
7
|
+
* optional `jsonwebtoken` peer dependency cannot be loaded. Called when a
|
|
8
|
+
* middleware is constructed, so a missing module fails loudly at startup
|
|
9
|
+
* instead of making every token look unverifiable.
|
|
10
|
+
*/
|
|
11
|
+
export declare function assertJwtSupport(options?: {
|
|
12
|
+
jwtSecret?: string;
|
|
13
|
+
jwtVerify?: unknown;
|
|
14
|
+
}): void;
|
|
15
|
+
/**
|
|
16
|
+
* Outcome of JWT tenant resolution:
|
|
17
|
+
* - `absent`: no bearer token, or no secret / verify function configured
|
|
18
|
+
* - `invalid`: a bearer token was sent but did not verify
|
|
19
|
+
* - `no_claim`: the token verified but carries no string tenant claim
|
|
20
|
+
* - `resolved`: the token verified and carries the tenant claim
|
|
21
|
+
*/
|
|
22
|
+
export type JwtTenantResolution = {
|
|
23
|
+
status: "absent";
|
|
24
|
+
} | {
|
|
25
|
+
status: "invalid";
|
|
26
|
+
} | {
|
|
27
|
+
status: "no_claim";
|
|
28
|
+
} | {
|
|
29
|
+
status: "resolved";
|
|
30
|
+
tenantId: string;
|
|
31
|
+
};
|
|
32
|
+
export declare function resolveJwtTenant(req: unknown, claimPath?: string, options?: JwtResolverOptions): JwtTenantResolution;
|
|
5
33
|
export declare function resolveFromJwt(req: unknown, claimPath?: string, options?: JwtResolverOptions): string | null;
|
|
6
34
|
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/resolvers/jwt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5D;
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/resolvers/jwt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5D;AAkBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAQ5F;AAgBD;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,MAAoB,EAC/B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,mBAAmB,CAuCrB;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,MAAoB,EAC/B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,GAAG,IAAI,CAGf"}
|
package/dist/resolvers/jwt.js
CHANGED
|
@@ -1,10 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertJwtSupport = assertJwtSupport;
|
|
4
|
+
exports.resolveJwtTenant = resolveJwtTenant;
|
|
3
5
|
exports.resolveFromJwt = resolveFromJwt;
|
|
4
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Load the optional `jsonwebtoken` peer dependency. Returns null only when the
|
|
8
|
+
* module is not installed; any other load failure is rethrown.
|
|
9
|
+
*/
|
|
10
|
+
function loadJsonwebtoken() {
|
|
5
11
|
try {
|
|
6
12
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
7
|
-
|
|
13
|
+
return require("jsonwebtoken");
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err.code === "MODULE_NOT_FOUND")
|
|
17
|
+
return null;
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Throw if `jwtSecret` is configured without a `jwtVerify` function and the
|
|
23
|
+
* optional `jsonwebtoken` peer dependency cannot be loaded. Called when a
|
|
24
|
+
* middleware is constructed, so a missing module fails loudly at startup
|
|
25
|
+
* instead of making every token look unverifiable.
|
|
26
|
+
*/
|
|
27
|
+
function assertJwtSupport(options) {
|
|
28
|
+
if (!options?.jwtSecret || options.jwtVerify)
|
|
29
|
+
return;
|
|
30
|
+
if (!loadJsonwebtoken()) {
|
|
31
|
+
throw new Error("[stratum] jwtSecret is set but the optional peer dependency 'jsonwebtoken' could not be loaded. " +
|
|
32
|
+
"Install jsonwebtoken, or provide jwtVerify.");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function verifyWithJsonwebtoken(token, secret) {
|
|
36
|
+
const jwt = loadJsonwebtoken();
|
|
37
|
+
if (!jwt) {
|
|
38
|
+
throw new Error("[stratum] jwtSecret is set but the optional peer dependency 'jsonwebtoken' is not installed.");
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
8
41
|
const decoded = jwt.verify(token, secret, { algorithms: ["HS256"] });
|
|
9
42
|
if (typeof decoded === "string")
|
|
10
43
|
return null;
|
|
@@ -14,15 +47,15 @@ function verifyWithJsonwebtoken(token, secret) {
|
|
|
14
47
|
return null;
|
|
15
48
|
}
|
|
16
49
|
}
|
|
17
|
-
function
|
|
50
|
+
function resolveJwtTenant(req, claimPath = "tenant_id", options) {
|
|
18
51
|
const r = req;
|
|
19
52
|
const headers = r["headers"];
|
|
20
53
|
if (!headers)
|
|
21
|
-
return
|
|
54
|
+
return { status: "absent" };
|
|
22
55
|
const authHeader = headers["authorization"];
|
|
23
56
|
const auth = Array.isArray(authHeader) ? authHeader[0] : authHeader;
|
|
24
57
|
if (!auth || !auth.startsWith("Bearer "))
|
|
25
|
-
return
|
|
58
|
+
return { status: "absent" };
|
|
26
59
|
const token = auth.slice(7);
|
|
27
60
|
let claims = null;
|
|
28
61
|
if (options?.verify) {
|
|
@@ -37,18 +70,22 @@ function resolveFromJwt(req, claimPath = "tenant_id", options) {
|
|
|
37
70
|
// No secret or verify function provided — refuse to trust unsigned tokens
|
|
38
71
|
console.warn("[stratum] JWT ignored: no jwtSecret or jwtVerify provided. " +
|
|
39
72
|
"Configure middleware options to enable JWT tenant resolution.");
|
|
40
|
-
return
|
|
73
|
+
return { status: "absent" };
|
|
41
74
|
}
|
|
42
75
|
if (!claims)
|
|
43
|
-
return
|
|
76
|
+
return { status: "invalid" };
|
|
44
77
|
// Support dotted claim paths like "stratum.tenant_id"
|
|
45
78
|
const segments = claimPath.split(".");
|
|
46
79
|
let current = claims;
|
|
47
80
|
for (const seg of segments) {
|
|
48
81
|
if (current == null || typeof current !== "object")
|
|
49
|
-
return
|
|
82
|
+
return { status: "no_claim" };
|
|
50
83
|
current = current[seg];
|
|
51
84
|
}
|
|
52
|
-
return typeof current === "string" ? current :
|
|
85
|
+
return typeof current === "string" ? { status: "resolved", tenantId: current } : { status: "no_claim" };
|
|
86
|
+
}
|
|
87
|
+
function resolveFromJwt(req, claimPath = "tenant_id", options) {
|
|
88
|
+
const result = resolveJwtTenant(req, claimPath, options);
|
|
89
|
+
return result.status === "resolved" ? result.tenantId : null;
|
|
53
90
|
}
|
|
54
91
|
//# sourceMappingURL=jwt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/resolvers/jwt.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/resolvers/jwt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MiddlewareOptions } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Outcome of request tenant resolution. `invalid_token` means a bearer token
|
|
4
|
+
* was sent while JWT verification is configured and it did not verify; the
|
|
5
|
+
* caller must reject the request rather than try other sources.
|
|
6
|
+
*/
|
|
7
|
+
export type TenantIdResolution = {
|
|
8
|
+
status: "resolved";
|
|
9
|
+
tenantId: string;
|
|
10
|
+
} | {
|
|
11
|
+
status: "missing";
|
|
12
|
+
} | {
|
|
13
|
+
status: "invalid_token";
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the tenant ID for a request: verified JWT, then the tenant header,
|
|
17
|
+
* then custom resolvers.
|
|
18
|
+
*
|
|
19
|
+
* When `jwtSecret` or `jwtVerify` is configured, the JWT is the tenant binding:
|
|
20
|
+
* a token that fails verification is reported as `invalid_token`, and the
|
|
21
|
+
* client-supplied tenant header is not consulted unless `trustTenantHeader`
|
|
22
|
+
* is true.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveTenantId(req: unknown, options?: MiddlewareOptions): Promise<TenantIdResolution>;
|
|
25
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/resolvers/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,eAAe,CAAA;CAAE,CAAC;AAEhC;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuB5G"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveTenantId = resolveTenantId;
|
|
4
|
+
const jwt_js_1 = require("./jwt.js");
|
|
5
|
+
const header_js_1 = require("./header.js");
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the tenant ID for a request: verified JWT, then the tenant header,
|
|
8
|
+
* then custom resolvers.
|
|
9
|
+
*
|
|
10
|
+
* When `jwtSecret` or `jwtVerify` is configured, the JWT is the tenant binding:
|
|
11
|
+
* a token that fails verification is reported as `invalid_token`, and the
|
|
12
|
+
* client-supplied tenant header is not consulted unless `trustTenantHeader`
|
|
13
|
+
* is true.
|
|
14
|
+
*/
|
|
15
|
+
async function resolveTenantId(req, options) {
|
|
16
|
+
const jwtConfigured = Boolean(options?.jwtSecret || options?.jwtVerify);
|
|
17
|
+
const jwt = (0, jwt_js_1.resolveJwtTenant)(req, options?.jwtClaimPath, {
|
|
18
|
+
secret: options?.jwtSecret,
|
|
19
|
+
verify: options?.jwtVerify,
|
|
20
|
+
});
|
|
21
|
+
if (jwt.status === "resolved")
|
|
22
|
+
return { status: "resolved", tenantId: jwt.tenantId };
|
|
23
|
+
if (jwt.status === "invalid")
|
|
24
|
+
return { status: "invalid_token" };
|
|
25
|
+
if (!jwtConfigured || options?.trustTenantHeader) {
|
|
26
|
+
const fromHeader = (0, header_js_1.resolveFromHeader)(req, options?.headerName);
|
|
27
|
+
if (fromHeader)
|
|
28
|
+
return { status: "resolved", tenantId: fromHeader };
|
|
29
|
+
}
|
|
30
|
+
if (options?.resolvers) {
|
|
31
|
+
for (const resolver of options.resolvers) {
|
|
32
|
+
const result = await resolver.resolve(req);
|
|
33
|
+
if (result)
|
|
34
|
+
return { status: "resolved", tenantId: result };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { status: "missing" };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/resolvers/resolve.ts"],"names":[],"mappings":";;AAuBA,0CAuBC;AA7CD,qCAA4C;AAC5C,2CAAgD;AAYhD;;;;;;;;GAQG;AACI,KAAK,UAAU,eAAe,CAAC,GAAY,EAAE,OAA2B;IAC7E,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,SAAS,IAAI,OAAO,EAAE,SAAS,CAAC,CAAC;IAExE,MAAM,GAAG,GAAG,IAAA,yBAAgB,EAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE;QACvD,MAAM,EAAE,OAAO,EAAE,SAAS;QAC1B,MAAM,EAAE,OAAO,EAAE,SAAS;KAC3B,CAAC,CAAC;IACH,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;IACrF,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAEjE,IAAI,CAAC,aAAa,IAAI,OAAO,EAAE,iBAAiB,EAAE,CAAC;QACjD,MAAM,UAAU,GAAG,IAAA,6BAAiB,EAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAC/D,IAAI,UAAU;YAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IACtE,CAAC;IAED,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;QACvB,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAI,MAAM;gBAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC/B,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,10 +3,19 @@ export type { ResolvedTenantContext, TenantNode, CreateTenantInput, UpdateTenant
|
|
|
3
3
|
export type { TenantResolver } from "./resolvers/custom.js";
|
|
4
4
|
export interface MiddlewareOptions {
|
|
5
5
|
resolvers?: import("./resolvers/custom.js").TenantResolver[];
|
|
6
|
+
/** Header to read the tenant ID from. When set, only this header is read (default: X-Tenant-ID). */
|
|
6
7
|
headerName?: string;
|
|
7
8
|
jwtClaimPath?: string;
|
|
9
|
+
/** HS256 secret for JWT verification. Requires the optional `jsonwebtoken` peer dependency unless `jwtVerify` is given. */
|
|
8
10
|
jwtSecret?: string;
|
|
9
11
|
jwtVerify?: (token: string) => Record<string, unknown> | null;
|
|
12
|
+
/**
|
|
13
|
+
* When `jwtSecret` or `jwtVerify` is configured, the tenant header is ignored
|
|
14
|
+
* unless this is true, so the verified JWT is the only tenant binding. A
|
|
15
|
+
* bearer token that fails verification is always rejected with 401. Has no
|
|
16
|
+
* effect when JWT verification is not configured. Default: false.
|
|
17
|
+
*/
|
|
18
|
+
trustTenantHeader?: boolean;
|
|
10
19
|
onError?: (err: Error, req: unknown) => void;
|
|
11
20
|
/**
|
|
12
21
|
* Enable tenant impersonation via X-Impersonate-Tenant header.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAErJ,YAAY,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,CAAC;AAE7H,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,uBAAuB,EAAE,cAAc,EAAE,CAAC;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;KACxF,CAAC;CACH"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAErJ,YAAY,EAAE,qBAAqB,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,CAAC;AAE7H,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,uBAAuB,EAAE,cAAc,EAAE,CAAC;IAC7D,oGAAoG;IACpG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2HAA2H;IAC3H,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxG,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;KACxF,CAAC;CACH"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratum-hq/sdk",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Stratum Node.js SDK for multi-tenant context propagation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"multi-tenancy",
|
|
@@ -45,8 +45,10 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/express": "^4.17.0",
|
|
48
|
+
"@types/jsonwebtoken": "^9.0.0",
|
|
48
49
|
"express": "^4.18.0",
|
|
49
|
-
"fastify": "^5.
|
|
50
|
+
"fastify": "^5.12.5",
|
|
51
|
+
"jsonwebtoken": "^9.0.0",
|
|
50
52
|
"typescript": "^5.4.0",
|
|
51
53
|
"vitest": "^4.1.11"
|
|
52
54
|
},
|
|
@@ -61,5 +63,13 @@
|
|
|
61
63
|
"type": "git",
|
|
62
64
|
"url": "https://github.com/stratum-hq/Stratum.git",
|
|
63
65
|
"directory": "packages/sdk"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"jsonwebtoken": "^9.0.0"
|
|
69
|
+
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"jsonwebtoken": {
|
|
72
|
+
"optional": true
|
|
73
|
+
}
|
|
64
74
|
}
|
|
65
75
|
}
|