@niledatabase/server 4.0.1-alpha.1 → 4.0.2-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/express.d.mts +9 -1
- package/dist/express.d.ts +9 -1
- package/dist/express.js +22 -12
- package/dist/express.js.map +1 -1
- package/dist/express.mjs +22 -13
- package/dist/express.mjs.map +1 -1
- package/dist/index.d.mts +21 -7
- package/dist/index.d.ts +21 -7
- package/dist/index.js +174 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -17,39 +17,48 @@ function urlMatches(requestUrl, route15) {
|
|
|
17
17
|
|
|
18
18
|
// src/utils/Logger.ts
|
|
19
19
|
var red = "\x1B[31m";
|
|
20
|
-
var yellow = "\x1B[
|
|
20
|
+
var yellow = "\x1B[38;2;255;255;0m";
|
|
21
|
+
var purple = "\x1B[38;2;200;160;255m";
|
|
22
|
+
var orange = "\x1B[38;2;255;165;0m";
|
|
21
23
|
var reset = "\x1B[0m";
|
|
22
24
|
var baseLogger = (config, ...params) => ({
|
|
23
25
|
info(message, meta) {
|
|
24
26
|
if (config?.debug) {
|
|
25
27
|
console.info(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
${
|
|
28
|
+
`${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
|
|
29
|
+
""
|
|
30
|
+
)}${reset} ${message}`,
|
|
31
|
+
meta ? `${JSON.stringify(meta)}` : ""
|
|
29
32
|
);
|
|
30
33
|
}
|
|
31
34
|
},
|
|
32
35
|
debug(message, meta) {
|
|
33
36
|
if (config?.debug) {
|
|
34
37
|
console.debug(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
${
|
|
38
|
+
`${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
|
|
39
|
+
""
|
|
40
|
+
)}${reset} ${message}`,
|
|
41
|
+
meta ? `${JSON.stringify(meta)}` : ""
|
|
38
42
|
);
|
|
39
43
|
}
|
|
40
44
|
},
|
|
41
45
|
warn(message, meta) {
|
|
42
46
|
if (config?.debug) {
|
|
43
47
|
console.warn(
|
|
44
|
-
`${
|
|
45
|
-
|
|
48
|
+
`${orange}[niledb]${reset}${yellow}[WARN]${reset}${params.join(
|
|
49
|
+
""
|
|
50
|
+
)}${reset} ${message}`,
|
|
51
|
+
meta ? JSON.stringify(meta) : ""
|
|
46
52
|
);
|
|
47
53
|
}
|
|
48
54
|
},
|
|
49
55
|
error(message, meta) {
|
|
50
56
|
console.error(
|
|
51
|
-
`${
|
|
52
|
-
|
|
57
|
+
`${orange}[niledb]${reset}${red}[ERROR]${reset}${params.join(
|
|
58
|
+
""
|
|
59
|
+
)}${red} ${message}`,
|
|
60
|
+
meta ? meta : "",
|
|
61
|
+
`${reset}`
|
|
53
62
|
);
|
|
54
63
|
}
|
|
55
64
|
});
|
|
@@ -71,6 +80,73 @@ var X_NILE_USER_ID = "nile.user_id";
|
|
|
71
80
|
var X_NILE_ORIGIN = "nile.origin";
|
|
72
81
|
var X_NILE_SECURECOOKIES = "nile.secure_cookies";
|
|
73
82
|
|
|
83
|
+
// src/context/asyncStorage.ts
|
|
84
|
+
var globalContext = null;
|
|
85
|
+
function setContext(headers) {
|
|
86
|
+
const origin = headers.get(X_NILE_ORIGIN);
|
|
87
|
+
const host = headers.get("host");
|
|
88
|
+
const cookie = headers.get("cookie");
|
|
89
|
+
const tenantId = headers.get(X_NILE_TENANT);
|
|
90
|
+
const userId = headers.get(X_NILE_USER_ID);
|
|
91
|
+
const context = {};
|
|
92
|
+
if (origin) {
|
|
93
|
+
context.origin = origin;
|
|
94
|
+
} else if (host) {
|
|
95
|
+
context.origin = host;
|
|
96
|
+
}
|
|
97
|
+
if (cookie) {
|
|
98
|
+
context.cookie = cookie;
|
|
99
|
+
}
|
|
100
|
+
if (tenantId) {
|
|
101
|
+
context.tenantId = tenantId;
|
|
102
|
+
}
|
|
103
|
+
if (userId) {
|
|
104
|
+
context.userId = userId;
|
|
105
|
+
}
|
|
106
|
+
globalContext = context;
|
|
107
|
+
}
|
|
108
|
+
function getOrigin() {
|
|
109
|
+
return globalContext?.origin;
|
|
110
|
+
}
|
|
111
|
+
function getCookie() {
|
|
112
|
+
return globalContext?.cookie;
|
|
113
|
+
}
|
|
114
|
+
function setCookie(headers) {
|
|
115
|
+
const getSet = headers?.getSetCookie?.();
|
|
116
|
+
if (getSet?.length) {
|
|
117
|
+
const updatedCookie = [];
|
|
118
|
+
for (const cook of getSet) {
|
|
119
|
+
const [c] = cook.split("; ");
|
|
120
|
+
const [, val] = c.split("=");
|
|
121
|
+
if (val) {
|
|
122
|
+
updatedCookie.push(c);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const cookie = mergeCookies(updatedCookie);
|
|
126
|
+
globalContext = { ...globalContext, cookie };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function mergeCookies(overrideArray) {
|
|
130
|
+
const cookieString = getCookie();
|
|
131
|
+
const cookieMap = {};
|
|
132
|
+
if (!cookieString) {
|
|
133
|
+
return overrideArray.join("; ");
|
|
134
|
+
}
|
|
135
|
+
cookieString.split(";").forEach((cookie) => {
|
|
136
|
+
const [rawKey, ...rawVal] = cookie.trim().split("=");
|
|
137
|
+
const key12 = rawKey.trim();
|
|
138
|
+
const value = rawVal.join("=").trim();
|
|
139
|
+
if (key12) cookieMap[key12] = value;
|
|
140
|
+
});
|
|
141
|
+
overrideArray.forEach((cookie) => {
|
|
142
|
+
const [rawKey, ...rawVal] = cookie.trim().split("=");
|
|
143
|
+
const key12 = rawKey.trim();
|
|
144
|
+
const value = rawVal.join("=").trim();
|
|
145
|
+
if (key12) cookieMap[key12] = value;
|
|
146
|
+
});
|
|
147
|
+
return Object.entries(cookieMap).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
148
|
+
}
|
|
149
|
+
|
|
74
150
|
// src/api/utils/request.ts
|
|
75
151
|
async function request(url, _init, config) {
|
|
76
152
|
const { debug, info, error } = Logger(config, "[REQUEST]");
|
|
@@ -104,7 +180,7 @@ async function request(url, _init, config) {
|
|
|
104
180
|
debug(`Obtained origin from request ${requestUrl.origin}`);
|
|
105
181
|
}
|
|
106
182
|
const params = { ...init, headers: updatedHeaders };
|
|
107
|
-
if (params.method === "
|
|
183
|
+
if (params.method?.toLowerCase() === "post" || params.method?.toLowerCase() === "put") {
|
|
108
184
|
try {
|
|
109
185
|
updatedHeaders.set("content-type", "application/json");
|
|
110
186
|
const initBody = await new Response(_init.request.clone().body).json();
|
|
@@ -119,22 +195,26 @@ async function request(url, _init, config) {
|
|
|
119
195
|
}
|
|
120
196
|
const fullUrl = `${url}${requestUrl.search}`;
|
|
121
197
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
198
|
+
setContext(updatedHeaders);
|
|
199
|
+
const res = await fetch(fullUrl, { ...params }).catch(
|
|
200
|
+
(e) => {
|
|
201
|
+
error("An error has occurred in the fetch", {
|
|
202
|
+
message: e.message,
|
|
203
|
+
stack: e.stack
|
|
204
|
+
});
|
|
205
|
+
return new Response(
|
|
206
|
+
"An unexpected (most likely configuration) problem has occurred",
|
|
207
|
+
{ status: 500 }
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
);
|
|
132
211
|
const loggingRes = typeof res?.clone === "function" ? res?.clone() : null;
|
|
133
212
|
info(`[${params.method ?? "GET"}] ${fullUrl}`, {
|
|
134
213
|
status: res?.status,
|
|
135
214
|
statusText: res?.statusText,
|
|
136
215
|
text: await loggingRes?.text()
|
|
137
216
|
});
|
|
217
|
+
setCookie(res?.headers);
|
|
138
218
|
return res;
|
|
139
219
|
} catch (e) {
|
|
140
220
|
if (e instanceof Error) {
|
|
@@ -434,11 +514,11 @@ var ApiConfig = class {
|
|
|
434
514
|
* If this is set, any `callbackUrl` from the client will be ignored.
|
|
435
515
|
*/
|
|
436
516
|
callbackUrl;
|
|
437
|
-
|
|
517
|
+
#token;
|
|
438
518
|
constructor(config, logger) {
|
|
439
519
|
const envVarConfig = { config, logger };
|
|
440
520
|
this.cookieKey = getCookieKey(envVarConfig);
|
|
441
|
-
this
|
|
521
|
+
this.#token = getToken(envVarConfig);
|
|
442
522
|
this.callbackUrl = getCallbackUrl(envVarConfig);
|
|
443
523
|
this.secureCookies = getSecureCookies(envVarConfig);
|
|
444
524
|
this.basePath = getBasePath(envVarConfig);
|
|
@@ -447,10 +527,10 @@ var ApiConfig = class {
|
|
|
447
527
|
this.origin = config?.api?.origin;
|
|
448
528
|
}
|
|
449
529
|
get token() {
|
|
450
|
-
return this
|
|
530
|
+
return this.#token;
|
|
451
531
|
}
|
|
452
532
|
set token(value) {
|
|
453
|
-
this
|
|
533
|
+
this.#token = value;
|
|
454
534
|
}
|
|
455
535
|
};
|
|
456
536
|
var Config = class {
|
|
@@ -962,7 +1042,7 @@ var ResponseError = class {
|
|
|
962
1042
|
|
|
963
1043
|
// src/utils/fetch.ts
|
|
964
1044
|
function getTokenFromCookie(headers, cookieKey) {
|
|
965
|
-
const cookie = headers.get("cookie")?.split("; ");
|
|
1045
|
+
const cookie = headers.get("cookie")?.split("; ") ?? getCookie()?.split("; ");
|
|
966
1046
|
const _cookies = {};
|
|
967
1047
|
if (cookie) {
|
|
968
1048
|
for (const parts of cookie) {
|
|
@@ -997,7 +1077,8 @@ function getUserFromHttp(headers, config) {
|
|
|
997
1077
|
}
|
|
998
1078
|
return headers?.get(X_NILE_USER_ID) ?? config.userId;
|
|
999
1079
|
}
|
|
1000
|
-
function makeBasicHeaders(config, opts) {
|
|
1080
|
+
function makeBasicHeaders(config, url, opts) {
|
|
1081
|
+
const { warn, error } = Logger(config, "[headers]");
|
|
1001
1082
|
const headers = new Headers(opts?.headers);
|
|
1002
1083
|
headers.set("content-type", "application/json; charset=utf-8");
|
|
1003
1084
|
const cookieKey = config.api?.cookieKey;
|
|
@@ -1010,11 +1091,31 @@ function makeBasicHeaders(config, opts) {
|
|
|
1010
1091
|
headers.set("Authorization", `Bearer ${getToken({ config })}`);
|
|
1011
1092
|
}
|
|
1012
1093
|
}
|
|
1094
|
+
const cookie = headers.get("cookie");
|
|
1095
|
+
if (!cookie) {
|
|
1096
|
+
const contextCookie = getCookie();
|
|
1097
|
+
if (contextCookie) {
|
|
1098
|
+
headers.set("cookie", contextCookie);
|
|
1099
|
+
} else {
|
|
1100
|
+
if (!url.endsWith("/users")) {
|
|
1101
|
+
error(
|
|
1102
|
+
"Missing cookie header from request. Call nile.api.setContext(request) before making additional calls."
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1013
1107
|
if (config && config.api.secureCookies != null) {
|
|
1014
1108
|
headers.set(X_NILE_SECURECOOKIES, String(config.api.secureCookies));
|
|
1015
1109
|
}
|
|
1110
|
+
const savedOrigin = getOrigin();
|
|
1016
1111
|
if (config && config.api.origin) {
|
|
1017
1112
|
headers.set(X_NILE_ORIGIN, config.api.origin);
|
|
1113
|
+
} else if (savedOrigin) {
|
|
1114
|
+
headers.set(X_NILE_ORIGIN, savedOrigin);
|
|
1115
|
+
} else {
|
|
1116
|
+
warn(
|
|
1117
|
+
"nile.origin missing from header, which defaults to secure cookies only."
|
|
1118
|
+
);
|
|
1018
1119
|
}
|
|
1019
1120
|
return headers;
|
|
1020
1121
|
}
|
|
@@ -1023,7 +1124,7 @@ async function _fetch(config, path, opts) {
|
|
|
1023
1124
|
const url = `${config.api?.basePath}${path}`;
|
|
1024
1125
|
const headers = new Headers(opts?.headers);
|
|
1025
1126
|
const tenantId = getTenantFromHttp(headers, config);
|
|
1026
|
-
const basicHeaders = makeBasicHeaders(config, opts);
|
|
1127
|
+
const basicHeaders = makeBasicHeaders(config, url, opts);
|
|
1027
1128
|
updateTenantId(tenantId);
|
|
1028
1129
|
const userId = getUserFromHttp(headers, config);
|
|
1029
1130
|
updateUserId(userId);
|
|
@@ -1982,7 +2083,7 @@ function serverLogin(config, handlers) {
|
|
|
1982
2083
|
if (!authCookie) {
|
|
1983
2084
|
throw new Error("authentication failed");
|
|
1984
2085
|
}
|
|
1985
|
-
const
|
|
2086
|
+
const token = parseToken(loginRes?.headers);
|
|
1986
2087
|
if (!token) {
|
|
1987
2088
|
error("Unable to obtain auth token", { authCookie });
|
|
1988
2089
|
throw new Error("Server login failed");
|
|
@@ -1995,6 +2096,17 @@ function serverLogin(config, handlers) {
|
|
|
1995
2096
|
return [headers, loginRes];
|
|
1996
2097
|
};
|
|
1997
2098
|
}
|
|
2099
|
+
function parseToken(headers) {
|
|
2100
|
+
let authCookie = headers?.get("set-cookie");
|
|
2101
|
+
if (!authCookie) {
|
|
2102
|
+
authCookie = headers?.get("cookie");
|
|
2103
|
+
}
|
|
2104
|
+
if (!authCookie) {
|
|
2105
|
+
return void 0;
|
|
2106
|
+
}
|
|
2107
|
+
const [, token] = /((__Secure-)?nile\.session-token=[^;]+)/.exec(authCookie) ?? [];
|
|
2108
|
+
return token;
|
|
2109
|
+
}
|
|
1998
2110
|
var Auth = class extends Config {
|
|
1999
2111
|
headers;
|
|
2000
2112
|
resetHeaders;
|
|
@@ -2241,8 +2353,15 @@ var Users = class extends Config {
|
|
|
2241
2353
|
super(config);
|
|
2242
2354
|
this.headers = headers;
|
|
2243
2355
|
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2356
|
+
usersUrl(user) {
|
|
2357
|
+
const params = new URLSearchParams();
|
|
2358
|
+
if (user.newTenantName) {
|
|
2359
|
+
params.set("newTenantName", user.newTenantName);
|
|
2360
|
+
}
|
|
2361
|
+
if (user.tenantId) {
|
|
2362
|
+
params.set("tenantId", user.tenantId);
|
|
2363
|
+
}
|
|
2364
|
+
return `/users?${params.size > 0 ? params : ""}`;
|
|
2246
2365
|
}
|
|
2247
2366
|
get tenantUsersUrl() {
|
|
2248
2367
|
return `/tenants/${this.tenantId ?? "{tenantId}"}/users`;
|
|
@@ -2267,10 +2386,10 @@ var Users = class extends Config {
|
|
|
2267
2386
|
}
|
|
2268
2387
|
return void 0;
|
|
2269
2388
|
}
|
|
2270
|
-
createUser = async (
|
|
2389
|
+
createUser = async (user, init) => {
|
|
2271
2390
|
const _requester = new Requester(this);
|
|
2272
2391
|
const _init = this.handleHeaders(init);
|
|
2273
|
-
return await _requester.post(
|
|
2392
|
+
return await _requester.post(user, this.usersUrl(user), _init);
|
|
2274
2393
|
};
|
|
2275
2394
|
createTenantUser = async (req, init) => {
|
|
2276
2395
|
const _requester = new Requester(this);
|
|
@@ -2415,6 +2534,7 @@ var Api = class {
|
|
|
2415
2534
|
};
|
|
2416
2535
|
resetHeaders = (headers) => {
|
|
2417
2536
|
this.#headers = new Headers(headers ?? {});
|
|
2537
|
+
setContext(new Headers());
|
|
2418
2538
|
this.reset();
|
|
2419
2539
|
};
|
|
2420
2540
|
set headers(headers) {
|
|
@@ -2444,12 +2564,21 @@ var Api = class {
|
|
|
2444
2564
|
get headers() {
|
|
2445
2565
|
return this.#headers;
|
|
2446
2566
|
}
|
|
2567
|
+
getCookie(req) {
|
|
2568
|
+
if (req instanceof Headers) {
|
|
2569
|
+
return parseToken(req);
|
|
2570
|
+
} else if (req instanceof Request) {
|
|
2571
|
+
return parseToken(req.headers);
|
|
2572
|
+
}
|
|
2573
|
+
return null;
|
|
2574
|
+
}
|
|
2447
2575
|
login = async (payload, config) => {
|
|
2448
2576
|
const [headers, loginRes] = await serverLogin(
|
|
2449
2577
|
this.config,
|
|
2450
2578
|
this.handlers
|
|
2451
2579
|
)(payload);
|
|
2452
2580
|
this.headers = headers;
|
|
2581
|
+
this.setContext(headers);
|
|
2453
2582
|
if (config?.returnResponse) {
|
|
2454
2583
|
return loginRes;
|
|
2455
2584
|
}
|
|
@@ -2463,6 +2592,17 @@ var Api = class {
|
|
|
2463
2592
|
}
|
|
2464
2593
|
return this.auth.getSession(this.#headers);
|
|
2465
2594
|
};
|
|
2595
|
+
setContext = (req) => {
|
|
2596
|
+
if (req instanceof Headers) {
|
|
2597
|
+
setContext(req);
|
|
2598
|
+
} else if (req instanceof Request) {
|
|
2599
|
+
setContext(req.headers);
|
|
2600
|
+
}
|
|
2601
|
+
const { warn } = Logger(this.config, "[API]");
|
|
2602
|
+
if (warn) {
|
|
2603
|
+
warn("Set context expects a Request or Header object");
|
|
2604
|
+
}
|
|
2605
|
+
};
|
|
2466
2606
|
};
|
|
2467
2607
|
|
|
2468
2608
|
// src/Server.ts
|