@niledatabase/server 3.0.0-alpha.9 → 3.0.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/dist/express.d.mts +24 -0
- package/dist/express.d.ts +24 -0
- package/dist/express.js +147 -0
- package/dist/express.js.map +1 -0
- package/dist/express.mjs +144 -0
- package/dist/express.mjs.map +1 -0
- package/dist/index.d.mts +323 -0
- package/dist/index.d.ts +323 -5
- package/dist/index.js +2382 -5
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2377 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +17 -4
- package/dist/Api.d.ts +0 -22
- package/dist/Server.d.ts +0 -29
- package/dist/api/handlers/DELETE.d.ts +0 -3
- package/dist/api/handlers/GET.d.ts +0 -3
- package/dist/api/handlers/POST.d.ts +0 -3
- package/dist/api/handlers/PUT.d.ts +0 -3
- package/dist/api/handlers/index.d.ts +0 -8
- package/dist/api/routes/auth/callback.d.ts +0 -3
- package/dist/api/routes/auth/csrf.d.ts +0 -3
- package/dist/api/routes/auth/error.d.ts +0 -3
- package/dist/api/routes/auth/index.d.ts +0 -7
- package/dist/api/routes/auth/providers.d.ts +0 -3
- package/dist/api/routes/auth/session.d.ts +0 -4
- package/dist/api/routes/auth/signin.d.ts +0 -33
- package/dist/api/routes/auth/signout.d.ts +0 -3
- package/dist/api/routes/me/index.d.ts +0 -4
- package/dist/api/routes/tenants/GET.d.ts +0 -32
- package/dist/api/routes/tenants/POST.d.ts +0 -45
- package/dist/api/routes/tenants/[tenantId]/DELETE.d.ts +0 -34
- package/dist/api/routes/tenants/[tenantId]/users/GET.d.ts +0 -35
- package/dist/api/routes/tenants/[tenantId]/users/POST.d.ts +0 -44
- package/dist/api/routes/tenants/[tenantId]/users/PUT.d.ts +0 -29
- package/dist/api/routes/tenants/[tenantId]/users/[userId]/DELETE.d.ts +0 -30
- package/dist/api/routes/tenants/[tenantId]/users/index.d.ts +0 -4
- package/dist/api/routes/tenants/index.d.ts +0 -4
- package/dist/api/routes/users/GET.d.ts +0 -34
- package/dist/api/routes/users/POST.d.ts +0 -66
- package/dist/api/routes/users/[userId]/PUT.d.ts +0 -40
- package/dist/api/routes/users/index.d.ts +0 -4
- package/dist/api/swagger.d.ts +0 -152
- package/dist/api/types.d.ts +0 -18
- package/dist/api/utils/auth.d.ts +0 -14
- package/dist/api/utils/request.d.ts +0 -4
- package/dist/api/utils/routes/apiRoutes.d.ts +0 -14
- package/dist/api/utils/routes/defaultRoutes.d.ts +0 -2
- package/dist/api/utils/routes/makeRestUrl.d.ts +0 -1
- package/dist/api/utils/routes/proxyRoutes.d.ts +0 -12
- package/dist/api/utils/routes/urlMatches.d.ts +0 -1
- package/dist/auth/index.d.ts +0 -13
- package/dist/db/DBManager.d.ts +0 -12
- package/dist/db/NileInstance.d.ts +0 -14
- package/dist/db/PoolProxy.d.ts +0 -3
- package/dist/db/index.d.ts +0 -1
- package/dist/db/isUUID.d.ts +0 -1
- package/dist/server.cjs.development.js +0 -3976
- package/dist/server.cjs.development.js.map +0 -1
- package/dist/server.cjs.production.min.js +0 -2
- package/dist/server.cjs.production.min.js.map +0 -1
- package/dist/server.esm.js +0 -3974
- package/dist/server.esm.js.map +0 -1
- package/dist/tenants/index.d.ts +0 -21
- package/dist/types.d.ts +0 -37
- package/dist/users/index.d.ts +0 -52
- package/dist/utils/Config/envVars.d.ts +0 -22
- package/dist/utils/Config/index.d.ts +0 -47
- package/dist/utils/Event/index.d.ts +0 -12
- package/dist/utils/Logger.d.ts +0 -7
- package/dist/utils/Requester/index.d.ts +0 -23
- package/dist/utils/Requester/types.d.ts +0 -88
- package/dist/utils/ResponseError.d.ts +0 -4
- package/dist/utils/Server/index.d.ts +0 -4
- package/dist/utils/fetch.d.ts +0 -9
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2377 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import pg from 'pg';
|
|
3
|
+
import { decodeJwt } from 'jose';
|
|
4
|
+
|
|
5
|
+
// src/users/types.ts
|
|
6
|
+
var LoginUserResponseTokenTypeEnum = {
|
|
7
|
+
AccessToken: "ACCESS_TOKEN",
|
|
8
|
+
RefreshToken: "REFRESH_TOKEN",
|
|
9
|
+
IdToken: "ID_TOKEN"
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/api/utils/routes/urlMatches.ts
|
|
13
|
+
function urlMatches(requestUrl, route15) {
|
|
14
|
+
const url = new URL(requestUrl);
|
|
15
|
+
return url.pathname.startsWith(route15);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/utils/Logger.ts
|
|
19
|
+
var red = "\x1B[31m";
|
|
20
|
+
var yellow = "\x1B[33m";
|
|
21
|
+
var reset = "\x1B[0m";
|
|
22
|
+
var baseLogger = (config, ...params) => ({
|
|
23
|
+
info(message, meta) {
|
|
24
|
+
if (config?.debug) {
|
|
25
|
+
console.info(
|
|
26
|
+
`[niledb][DEBUG]${params.join("")} ${message}`,
|
|
27
|
+
meta ? `
|
|
28
|
+
${JSON.stringify(meta, null, 2)}` : ""
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
debug(message, meta) {
|
|
33
|
+
if (config?.debug) {
|
|
34
|
+
console.debug(
|
|
35
|
+
`[niledb][DEBUG]${params.join("")} ${message}`,
|
|
36
|
+
meta ? `
|
|
37
|
+
${JSON.stringify(meta, null, 2)}` : ""
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
warn(message, meta) {
|
|
42
|
+
if (config?.debug) {
|
|
43
|
+
console.warn(
|
|
44
|
+
`${yellow}[niledb][WARN]${reset}${params.join("")} ${message}`,
|
|
45
|
+
JSON.stringify(meta, null, 2)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
error(message, meta) {
|
|
50
|
+
console.error(
|
|
51
|
+
`${red}[niledb][ERROR]${reset}${params.join("")} ${message}`,
|
|
52
|
+
meta
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
function Logger(config, ...params) {
|
|
57
|
+
const base = baseLogger(config, params);
|
|
58
|
+
const info = config?.logger?.info ?? base.info;
|
|
59
|
+
const debug = config?.logger?.debug ?? base.debug;
|
|
60
|
+
const warn = config?.logger?.warn ?? base.warn;
|
|
61
|
+
const error = config?.logger?.error ?? base.error;
|
|
62
|
+
return { info, warn, error, debug };
|
|
63
|
+
}
|
|
64
|
+
function matchesLog(configRoutes, request2) {
|
|
65
|
+
return urlMatches(request2.url, configRoutes.LOG);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/utils/constants.ts
|
|
69
|
+
var X_NILE_TENANT = "nile.tenant_id";
|
|
70
|
+
var X_NILE_USER_ID = "nile.user_id";
|
|
71
|
+
var X_NILE_ORIGIN = "nile.origin";
|
|
72
|
+
var X_NILE_SECURECOOKIES = "nile.secure_cookies";
|
|
73
|
+
|
|
74
|
+
// src/api/utils/request.ts
|
|
75
|
+
async function request(url, _init, config) {
|
|
76
|
+
const { info, error } = Logger(config, "[REQUEST]");
|
|
77
|
+
const { request: request2, ...init } = _init;
|
|
78
|
+
const requestUrl = new URL(request2.url);
|
|
79
|
+
const updatedHeaders = new Headers({});
|
|
80
|
+
if (request2.headers.get("cookie")) {
|
|
81
|
+
updatedHeaders.set("cookie", String(request2.headers.get("cookie")));
|
|
82
|
+
}
|
|
83
|
+
if (request2.headers.get(X_NILE_TENANT)) {
|
|
84
|
+
updatedHeaders.set(
|
|
85
|
+
X_NILE_TENANT,
|
|
86
|
+
String(request2.headers.get(X_NILE_TENANT))
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
if ("secureCookies" in config && config.secureCookies != null) {
|
|
90
|
+
updatedHeaders.set(X_NILE_SECURECOOKIES, String(config.secureCookies));
|
|
91
|
+
}
|
|
92
|
+
updatedHeaders.set("host", requestUrl.host);
|
|
93
|
+
updatedHeaders.set(X_NILE_ORIGIN, requestUrl.origin);
|
|
94
|
+
const params = { ...init, headers: updatedHeaders };
|
|
95
|
+
if (params.method === "POST" || params.method === "PUT") {
|
|
96
|
+
try {
|
|
97
|
+
updatedHeaders.set("content-type", "application/json");
|
|
98
|
+
const initBody = await new Response(_init.request.clone().body).json();
|
|
99
|
+
const requestBody = await new Response(request2.clone().body).json();
|
|
100
|
+
params.body = JSON.stringify(initBody ?? requestBody);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
updatedHeaders.set("content-type", "application/x-www-form-urlencoded");
|
|
103
|
+
const initBody = await new Response(_init.request.clone().body).text();
|
|
104
|
+
const requestBody = await new Response(request2.clone().body).text();
|
|
105
|
+
params.body = initBody ?? requestBody;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const fullUrl = `${url}${requestUrl.search}`;
|
|
109
|
+
try {
|
|
110
|
+
const res = await fetch(fullUrl, { ...params }).catch((e) => {
|
|
111
|
+
error("An error has occurred in the fetch", {
|
|
112
|
+
message: e.message,
|
|
113
|
+
stack: e.stack
|
|
114
|
+
});
|
|
115
|
+
return new Response(
|
|
116
|
+
"An unexpected (most likely configuration) problem has occurred",
|
|
117
|
+
{ status: 500 }
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
const loggingRes = typeof res?.clone === "function" ? res?.clone() : null;
|
|
121
|
+
info(`[${params.method ?? "GET"}] ${fullUrl}`, {
|
|
122
|
+
status: res?.status,
|
|
123
|
+
statusText: res?.statusText,
|
|
124
|
+
text: await loggingRes?.text()
|
|
125
|
+
});
|
|
126
|
+
return res;
|
|
127
|
+
} catch (e) {
|
|
128
|
+
if (e instanceof Error) {
|
|
129
|
+
error("An error has occurred in the fetch", {
|
|
130
|
+
message: e.message,
|
|
131
|
+
stack: e.stack
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return new Response(
|
|
135
|
+
"An unexpected (most likely configuration) problem has occurred",
|
|
136
|
+
{ status: 500 }
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/api/utils/auth.ts
|
|
142
|
+
async function auth(req, config) {
|
|
143
|
+
const { info, error } = Logger(config, "[nileauth]");
|
|
144
|
+
info("checking auth");
|
|
145
|
+
const sessionUrl = `${config.api.basePath}/auth/session`;
|
|
146
|
+
info(`using session${sessionUrl}`);
|
|
147
|
+
req.headers.delete("content-length");
|
|
148
|
+
const res = await request(sessionUrl, { request: req }, config);
|
|
149
|
+
if (!res) {
|
|
150
|
+
info("no session found");
|
|
151
|
+
return void 0;
|
|
152
|
+
}
|
|
153
|
+
info("session active");
|
|
154
|
+
try {
|
|
155
|
+
const session = await new Response(res.body).json();
|
|
156
|
+
if (Object.keys(session).length === 0) {
|
|
157
|
+
return void 0;
|
|
158
|
+
}
|
|
159
|
+
return session;
|
|
160
|
+
} catch (e) {
|
|
161
|
+
error(e);
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
var getSecureCookies = (cfg) => {
|
|
166
|
+
const { config } = cfg;
|
|
167
|
+
if (stringCheck(process.env.NILEDB_SECURECOOKIES)) {
|
|
168
|
+
return Boolean(process.env.NILEDB_SECURECOOKIES);
|
|
169
|
+
}
|
|
170
|
+
return config?.secureCookies;
|
|
171
|
+
};
|
|
172
|
+
var getDatabaseId = (cfg) => {
|
|
173
|
+
const { config, logger } = cfg;
|
|
174
|
+
const { info } = Logger(config, "[databaseId]");
|
|
175
|
+
if (stringCheck(config?.databaseId)) {
|
|
176
|
+
logger && info(`${logger}[config] ${config?.databaseId}`);
|
|
177
|
+
return String(config?.databaseId);
|
|
178
|
+
}
|
|
179
|
+
const dbFromEnv = stringCheck(process.env.NILEDB_ID);
|
|
180
|
+
if (dbFromEnv) {
|
|
181
|
+
logger && info(`${logger}[NILEDB_ID] ${dbFromEnv}`);
|
|
182
|
+
return dbFromEnv;
|
|
183
|
+
}
|
|
184
|
+
const dbId = stringCheck(process.env.NILEDB_API_URL);
|
|
185
|
+
if (dbId) {
|
|
186
|
+
try {
|
|
187
|
+
const pgUrl = new URL(dbId);
|
|
188
|
+
return pgUrl.pathname.split("/")[3];
|
|
189
|
+
} catch (e) {
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
};
|
|
194
|
+
var getUsername = (cfg) => {
|
|
195
|
+
const { config, logger } = cfg;
|
|
196
|
+
const { info } = Logger(config, "[username]");
|
|
197
|
+
if (config?.user) {
|
|
198
|
+
logger && info(`${logger}[config] ${config.user}`);
|
|
199
|
+
return String(config?.user);
|
|
200
|
+
}
|
|
201
|
+
const user = stringCheck(process.env.NILEDB_USER);
|
|
202
|
+
if (user) {
|
|
203
|
+
logger && info(`${logger}[NILEDB_USER] ${user}`);
|
|
204
|
+
return user;
|
|
205
|
+
}
|
|
206
|
+
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
207
|
+
if (pg2) {
|
|
208
|
+
try {
|
|
209
|
+
const url = new URL(pg2);
|
|
210
|
+
if (url.username) {
|
|
211
|
+
return url.username;
|
|
212
|
+
}
|
|
213
|
+
} catch (e) {
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return void 0;
|
|
217
|
+
};
|
|
218
|
+
var getPassword = (cfg) => {
|
|
219
|
+
const { config, logger } = cfg;
|
|
220
|
+
const log = logProtector(logger);
|
|
221
|
+
const { info } = Logger(config, "[password]");
|
|
222
|
+
if (stringCheck(config?.password)) {
|
|
223
|
+
log && info(`${logger}[config] ${config?.password}`);
|
|
224
|
+
return String(config?.password);
|
|
225
|
+
}
|
|
226
|
+
const pass = stringCheck(process.env.NILEDB_PASSWORD);
|
|
227
|
+
if (pass) {
|
|
228
|
+
logger && info(`${logger}[NILEDB_PASSWORD] ${pass}`);
|
|
229
|
+
return pass;
|
|
230
|
+
}
|
|
231
|
+
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
232
|
+
if (pg2) {
|
|
233
|
+
try {
|
|
234
|
+
const url = new URL(pg2);
|
|
235
|
+
if (url.password) {
|
|
236
|
+
return url.password;
|
|
237
|
+
}
|
|
238
|
+
} catch (e) {
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return void 0;
|
|
242
|
+
};
|
|
243
|
+
var getInfoBearer = (cfg) => {
|
|
244
|
+
return `${getUsername(cfg)}:${getPassword(cfg)}`;
|
|
245
|
+
};
|
|
246
|
+
var getToken = (cfg) => {
|
|
247
|
+
const { config, logger } = cfg;
|
|
248
|
+
const { info } = Logger(config, "[token]");
|
|
249
|
+
if (stringCheck(config?.api?.token)) {
|
|
250
|
+
logger && info(`${logger}[config] ${config?.api?.token}`);
|
|
251
|
+
return String(config?.api?.token);
|
|
252
|
+
}
|
|
253
|
+
const token = stringCheck(process.env.NILEDB_TOKEN);
|
|
254
|
+
if (token) {
|
|
255
|
+
logger && info(`${logger}[NILEDB_TOKEN] ${token}`);
|
|
256
|
+
return token;
|
|
257
|
+
}
|
|
258
|
+
return void 0;
|
|
259
|
+
};
|
|
260
|
+
var getDatabaseName = (cfg) => {
|
|
261
|
+
const { config, logger } = cfg;
|
|
262
|
+
const { info } = Logger(config, "[databaseName]");
|
|
263
|
+
if (stringCheck(config?.databaseName)) {
|
|
264
|
+
logger && info(`${logger}[config] ${config?.databaseName}`);
|
|
265
|
+
return String(config?.databaseName);
|
|
266
|
+
}
|
|
267
|
+
const name = stringCheck(process.env.NILEDB_NAME);
|
|
268
|
+
if (name) {
|
|
269
|
+
logger && info(`${logger}[NILEDB_NAME] ${name}`);
|
|
270
|
+
return name;
|
|
271
|
+
}
|
|
272
|
+
if (process.env.NILEDB_POSTGRES_URL) {
|
|
273
|
+
try {
|
|
274
|
+
const pgUrl = new URL(process.env.NILEDB_POSTGRES_URL);
|
|
275
|
+
return pgUrl.pathname.substring(1);
|
|
276
|
+
} catch (e) {
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return null;
|
|
280
|
+
};
|
|
281
|
+
var getTenantId = (cfg) => {
|
|
282
|
+
const { config, logger } = cfg;
|
|
283
|
+
const { info } = Logger(config, "[tenantId]");
|
|
284
|
+
if (stringCheck(config?.tenantId)) {
|
|
285
|
+
logger && info(`${logger}[config] ${config?.tenantId}`);
|
|
286
|
+
return String(config?.tenantId);
|
|
287
|
+
}
|
|
288
|
+
if (stringCheck(process.env.NILEDB_TENANT)) {
|
|
289
|
+
logger && info(`${logger}[NILEDB_TENANT] ${process.env.NILEDB_TENANT}`);
|
|
290
|
+
return String(process.env.NILEDB_TENANT);
|
|
291
|
+
}
|
|
292
|
+
return null;
|
|
293
|
+
};
|
|
294
|
+
var getBasePath = (cfg) => {
|
|
295
|
+
const { config, logger } = cfg;
|
|
296
|
+
const { warn, info, error } = Logger(config, "[basePath]");
|
|
297
|
+
const basePath = config?.api?.basePath;
|
|
298
|
+
if (stringCheck(basePath)) {
|
|
299
|
+
logger && info(`${logger}[config] ${basePath}`);
|
|
300
|
+
return basePath;
|
|
301
|
+
}
|
|
302
|
+
const envUrl = stringCheck(process.env.NILEDB_API_URL);
|
|
303
|
+
if (envUrl) {
|
|
304
|
+
logger && info(`${logger}[NILEDB_API_URL] ${process.env.NILEDB_API_URL}`);
|
|
305
|
+
try {
|
|
306
|
+
const apiUrl = new URL(envUrl);
|
|
307
|
+
return apiUrl.href;
|
|
308
|
+
} catch (e) {
|
|
309
|
+
if (e instanceof Error) {
|
|
310
|
+
error(e.stack);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
warn("not set. Must run auto-configuration");
|
|
315
|
+
return void 0;
|
|
316
|
+
};
|
|
317
|
+
var getControlPlane = (cfg) => {
|
|
318
|
+
const { config, logger } = cfg;
|
|
319
|
+
const { info } = Logger(config, "[basePath]");
|
|
320
|
+
if (stringCheck(config?.configureUrl)) {
|
|
321
|
+
logger && info(`${logger}[config] ${config?.configureUrl}`);
|
|
322
|
+
return String(config?.configureUrl);
|
|
323
|
+
}
|
|
324
|
+
const autoConfigUrl = stringCheck(process.env.NILEDB_CONFIGURE);
|
|
325
|
+
if (autoConfigUrl) {
|
|
326
|
+
logger && info(`${logger}[NILEDB_CONFIGURE] ${process.env.NILEDB_CONFIGURE}`);
|
|
327
|
+
if (!autoConfigUrl.startsWith("http")) {
|
|
328
|
+
return `https://${process.env.NILEDB_CONFIGURE}`;
|
|
329
|
+
}
|
|
330
|
+
return process.env.NILEDB_CONFIGURE;
|
|
331
|
+
}
|
|
332
|
+
logger && info(`${logger}[default] https://global.thenile.dev`);
|
|
333
|
+
return "https://global.thenile.dev";
|
|
334
|
+
};
|
|
335
|
+
function getDbHost(cfg) {
|
|
336
|
+
const { config, logger } = cfg;
|
|
337
|
+
const { info } = Logger(config, "[db.host]");
|
|
338
|
+
if (stringCheck(config?.db && config.db.host)) {
|
|
339
|
+
logger && info(`${logger}[config] ${config?.db?.host}`);
|
|
340
|
+
return String(config?.db?.host);
|
|
341
|
+
}
|
|
342
|
+
if (stringCheck(process.env.NILEDB_HOST)) {
|
|
343
|
+
logger && info(`${logger}[NILEDB_HOST] ${process.env.NILEDB_HOST}`);
|
|
344
|
+
return process.env.NILEDB_HOST;
|
|
345
|
+
}
|
|
346
|
+
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
347
|
+
if (pg2) {
|
|
348
|
+
try {
|
|
349
|
+
const pgUrl = new URL(pg2);
|
|
350
|
+
logger && info(`${logger}[NILEDB_POSTGRES_URL] ${pgUrl.hostname}`);
|
|
351
|
+
return pgUrl.hostname;
|
|
352
|
+
} catch (e) {
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
logger && info(`${logger}[default] db.thenile.dev`);
|
|
356
|
+
return "db.thenile.dev";
|
|
357
|
+
}
|
|
358
|
+
function getDbPort(cfg) {
|
|
359
|
+
const { config, logger } = cfg;
|
|
360
|
+
const { info } = Logger(config, "[db.port]");
|
|
361
|
+
if (config?.db?.port && config.db.port != null) {
|
|
362
|
+
logger && info(`${logger}[config] ${config?.db.port}`);
|
|
363
|
+
return Number(config.db?.port);
|
|
364
|
+
}
|
|
365
|
+
if (stringCheck(process.env.NILEDB_PORT)) {
|
|
366
|
+
logger && info(`${logger}[NILEDB_PORT] ${process.env.NILEDB_PORT}`);
|
|
367
|
+
return Number(process.env.NILEDB_PORT);
|
|
368
|
+
}
|
|
369
|
+
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
370
|
+
if (pg2) {
|
|
371
|
+
try {
|
|
372
|
+
const pgUrl = new URL(pg2);
|
|
373
|
+
if (pgUrl.port) {
|
|
374
|
+
return Number(pgUrl.port);
|
|
375
|
+
}
|
|
376
|
+
} catch (e) {
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
logger && info(`${logger}[default] 5432`);
|
|
380
|
+
return 5432;
|
|
381
|
+
}
|
|
382
|
+
var logProtector = (logger) => {
|
|
383
|
+
return process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test" ? logger : null;
|
|
384
|
+
};
|
|
385
|
+
var stringCheck = (str) => {
|
|
386
|
+
if (str && str !== "") {
|
|
387
|
+
return str;
|
|
388
|
+
}
|
|
389
|
+
return;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
// src/utils/Config/index.ts
|
|
393
|
+
var ApiConfig = class {
|
|
394
|
+
cookieKey;
|
|
395
|
+
basePath;
|
|
396
|
+
_token;
|
|
397
|
+
constructor({
|
|
398
|
+
basePath,
|
|
399
|
+
cookieKey,
|
|
400
|
+
token
|
|
401
|
+
}) {
|
|
402
|
+
this.basePath = basePath;
|
|
403
|
+
this.cookieKey = cookieKey;
|
|
404
|
+
this._token = token;
|
|
405
|
+
}
|
|
406
|
+
get token() {
|
|
407
|
+
return this._token;
|
|
408
|
+
}
|
|
409
|
+
set token(value) {
|
|
410
|
+
this._token = value;
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
var Config = class {
|
|
414
|
+
user;
|
|
415
|
+
password;
|
|
416
|
+
databaseId;
|
|
417
|
+
databaseName;
|
|
418
|
+
routePrefix;
|
|
419
|
+
routes;
|
|
420
|
+
logger;
|
|
421
|
+
secureCookies;
|
|
422
|
+
debug;
|
|
423
|
+
db;
|
|
424
|
+
api;
|
|
425
|
+
_tenantId;
|
|
426
|
+
_userId;
|
|
427
|
+
get tenantId() {
|
|
428
|
+
return this._tenantId;
|
|
429
|
+
}
|
|
430
|
+
set tenantId(value) {
|
|
431
|
+
this._tenantId = value;
|
|
432
|
+
}
|
|
433
|
+
get userId() {
|
|
434
|
+
return this._userId;
|
|
435
|
+
}
|
|
436
|
+
set userId(value) {
|
|
437
|
+
this._userId = value;
|
|
438
|
+
}
|
|
439
|
+
constructor(config, logger) {
|
|
440
|
+
const envVarConfig = { config, logger };
|
|
441
|
+
this.user = getUsername(envVarConfig);
|
|
442
|
+
this.logger = config?.logger;
|
|
443
|
+
this.password = getPassword(envVarConfig);
|
|
444
|
+
if (process.env.NODE_ENV !== "TEST") {
|
|
445
|
+
if (!this.user) {
|
|
446
|
+
throw new Error(
|
|
447
|
+
"User is required. Set NILEDB_USER as an environment variable or set `user` in the config options."
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
if (!this.password) {
|
|
451
|
+
throw new Error(
|
|
452
|
+
"Password is required. Set NILEDB_PASSWORD as an environment variable or set `password` in the config options."
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
this.secureCookies = getSecureCookies(envVarConfig);
|
|
457
|
+
this.databaseId = getDatabaseId(envVarConfig);
|
|
458
|
+
this.databaseName = getDatabaseName(envVarConfig);
|
|
459
|
+
this._tenantId = getTenantId(envVarConfig);
|
|
460
|
+
this.debug = Boolean(config?.debug);
|
|
461
|
+
this._userId = config?.userId;
|
|
462
|
+
const basePath = getBasePath(envVarConfig);
|
|
463
|
+
const { host, port, ...dbConfig } = config?.db ?? {};
|
|
464
|
+
const configuredHost = host ?? getDbHost(envVarConfig);
|
|
465
|
+
const configuredPort = port ?? getDbPort(envVarConfig);
|
|
466
|
+
this.api = new ApiConfig({
|
|
467
|
+
basePath,
|
|
468
|
+
cookieKey: config?.api?.cookieKey ?? "token",
|
|
469
|
+
token: getToken({ config })
|
|
470
|
+
});
|
|
471
|
+
this.db = {
|
|
472
|
+
user: this.user,
|
|
473
|
+
password: this.password,
|
|
474
|
+
host: configuredHost,
|
|
475
|
+
port: configuredPort,
|
|
476
|
+
...dbConfig
|
|
477
|
+
};
|
|
478
|
+
if (this.databaseName) {
|
|
479
|
+
this.db.database = this.databaseName;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
configure = async (config) => {
|
|
483
|
+
const { info, error, debug } = Logger(config, "[init]");
|
|
484
|
+
const envVarConfig = {
|
|
485
|
+
config
|
|
486
|
+
};
|
|
487
|
+
const { host, port, ...dbConfig } = config.db ?? {};
|
|
488
|
+
let configuredHost = host ?? getDbHost(envVarConfig);
|
|
489
|
+
const configuredPort = port ?? getDbPort(envVarConfig);
|
|
490
|
+
let basePath = getBasePath(envVarConfig);
|
|
491
|
+
if (configuredHost && this.databaseName && this.databaseId && basePath) {
|
|
492
|
+
info("Already configured, aborting fetch");
|
|
493
|
+
this.api = new ApiConfig({
|
|
494
|
+
basePath,
|
|
495
|
+
cookieKey: config?.api?.cookieKey ?? "token",
|
|
496
|
+
token: getToken({ config })
|
|
497
|
+
});
|
|
498
|
+
this.db = {
|
|
499
|
+
user: this.user,
|
|
500
|
+
password: this.password,
|
|
501
|
+
host: configuredHost,
|
|
502
|
+
port: configuredPort,
|
|
503
|
+
database: this.databaseName,
|
|
504
|
+
...dbConfig
|
|
505
|
+
};
|
|
506
|
+
info("[config set]", { db: this.db, api: this.api });
|
|
507
|
+
return this;
|
|
508
|
+
} else {
|
|
509
|
+
const msg = [];
|
|
510
|
+
if (!configuredHost) {
|
|
511
|
+
msg.push("Database host");
|
|
512
|
+
}
|
|
513
|
+
if (!this.databaseName) {
|
|
514
|
+
msg.push("Database name");
|
|
515
|
+
}
|
|
516
|
+
if (!this.databaseId) {
|
|
517
|
+
msg.push("Database id");
|
|
518
|
+
}
|
|
519
|
+
if (!basePath) {
|
|
520
|
+
msg.push("API URL");
|
|
521
|
+
}
|
|
522
|
+
info(
|
|
523
|
+
`[autoconfigure] ${msg.join(", ")} ${msg.length > 1 ? "are" : "is"} missing from the config. Autoconfiguration will run.`
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
const cp = getControlPlane(envVarConfig);
|
|
527
|
+
const databaseName = getDatabaseName({ config, logger: "getInfo" });
|
|
528
|
+
const url = new URL(`${cp}/databases/configure`);
|
|
529
|
+
if (databaseName) {
|
|
530
|
+
url.searchParams.set("databaseName", databaseName);
|
|
531
|
+
}
|
|
532
|
+
info(`configuring from ${url.href}`);
|
|
533
|
+
const res = await fetch(url, {
|
|
534
|
+
headers: {
|
|
535
|
+
Authorization: `Bearer ${getInfoBearer({ config })}`
|
|
536
|
+
}
|
|
537
|
+
}).catch(() => {
|
|
538
|
+
error(`Unable to auto-configure. is ${url} available?`);
|
|
539
|
+
});
|
|
540
|
+
if (!res) {
|
|
541
|
+
return this;
|
|
542
|
+
}
|
|
543
|
+
let database;
|
|
544
|
+
const possibleError = res.clone();
|
|
545
|
+
try {
|
|
546
|
+
const json = await res.json();
|
|
547
|
+
if (res.status === 404) {
|
|
548
|
+
info("is the configured databaseName correct?");
|
|
549
|
+
}
|
|
550
|
+
if (json.status && json.status !== "READY") {
|
|
551
|
+
database = { message: "Database is not ready yet" };
|
|
552
|
+
} else {
|
|
553
|
+
database = json;
|
|
554
|
+
}
|
|
555
|
+
} catch (e) {
|
|
556
|
+
const message = await possibleError.text();
|
|
557
|
+
debug("Unable to auto-configure");
|
|
558
|
+
error(message);
|
|
559
|
+
database = { message };
|
|
560
|
+
}
|
|
561
|
+
info("[fetched database]", database);
|
|
562
|
+
if (process.env.NODE_ENV !== "TEST") {
|
|
563
|
+
if ("message" in database) {
|
|
564
|
+
if ("statusCode" in database) {
|
|
565
|
+
error(database);
|
|
566
|
+
throw new Error("HTTP error has occurred");
|
|
567
|
+
} else {
|
|
568
|
+
throw new Error(
|
|
569
|
+
"Unable to auto-configure. Please remove NILEDB_NAME, NILEDB_API_URL, NILEDB_POSTGRES_URL, and/or NILEDB_HOST from your environment variables."
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if (typeof database === "object") {
|
|
574
|
+
const { apiHost, dbHost, name, id } = database;
|
|
575
|
+
basePath = basePath || apiHost;
|
|
576
|
+
this.databaseId = id;
|
|
577
|
+
this.databaseName = name;
|
|
578
|
+
const dburl = new URL(dbHost);
|
|
579
|
+
configuredHost = dburl.hostname;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
this.api = new ApiConfig({
|
|
583
|
+
basePath,
|
|
584
|
+
cookieKey: config?.api?.cookieKey ?? "token",
|
|
585
|
+
token: getToken({ config })
|
|
586
|
+
});
|
|
587
|
+
this.db = {
|
|
588
|
+
user: this.user,
|
|
589
|
+
password: this.password,
|
|
590
|
+
host: configuredHost,
|
|
591
|
+
port: configuredPort,
|
|
592
|
+
database: this.databaseName,
|
|
593
|
+
...dbConfig
|
|
594
|
+
};
|
|
595
|
+
info("[config set]", { db: this.db, api: this.api });
|
|
596
|
+
return this;
|
|
597
|
+
};
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
// src/utils/Event/index.ts
|
|
601
|
+
var Eventer = class {
|
|
602
|
+
events = {};
|
|
603
|
+
// Publish event and notify all subscribers
|
|
604
|
+
publish(eventName, value) {
|
|
605
|
+
const callbackList = this.events[eventName];
|
|
606
|
+
if (callbackList) {
|
|
607
|
+
for (const callback of callbackList) {
|
|
608
|
+
callback(value);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
// Subscribe to events
|
|
613
|
+
subscribe(eventName, callback) {
|
|
614
|
+
if (!this.events[eventName]) {
|
|
615
|
+
this.events[eventName] = [];
|
|
616
|
+
}
|
|
617
|
+
this.events[eventName].push(callback);
|
|
618
|
+
}
|
|
619
|
+
// Unsubscribe from an event
|
|
620
|
+
unsubscribe(eventName, callback) {
|
|
621
|
+
const callbackList = this.events[eventName];
|
|
622
|
+
if (!callbackList) {
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
const index = callbackList.indexOf(callback);
|
|
626
|
+
if (index !== -1) {
|
|
627
|
+
callbackList.splice(index, 1);
|
|
628
|
+
}
|
|
629
|
+
if (callbackList.length === 0) {
|
|
630
|
+
delete this.events[eventName];
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
var eventer = new Eventer();
|
|
635
|
+
var updateTenantId = (tenantId) => {
|
|
636
|
+
eventer.publish("tenantId" /* Tenant */, tenantId);
|
|
637
|
+
};
|
|
638
|
+
var watchTenantId = (cb) => eventer.subscribe("tenantId" /* Tenant */, cb);
|
|
639
|
+
var updateUserId = (userId) => {
|
|
640
|
+
eventer.publish("userId" /* User */, userId);
|
|
641
|
+
};
|
|
642
|
+
var watchUserId = (cb) => eventer.subscribe("userId" /* User */, cb);
|
|
643
|
+
var watchToken = (cb) => eventer.subscribe("token" /* Token */, cb);
|
|
644
|
+
var watchEvictPool = (cb) => eventer.subscribe("EvictPool" /* EvictPool */, cb);
|
|
645
|
+
var evictPool = (val) => {
|
|
646
|
+
eventer.publish("EvictPool" /* EvictPool */, val);
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
// src/db/PoolProxy.ts
|
|
650
|
+
function createProxyForPool(pool, config) {
|
|
651
|
+
const { info, error } = Logger(config, "[pool]");
|
|
652
|
+
return new Proxy(pool, {
|
|
653
|
+
get(target, property) {
|
|
654
|
+
if (property === "query") {
|
|
655
|
+
if (!config.db.connectionString) {
|
|
656
|
+
if (!config.user || !config.password) {
|
|
657
|
+
error(
|
|
658
|
+
"Cannot connect to the database. User and/or password are missing. Generate them at https://console.thenile.dev"
|
|
659
|
+
);
|
|
660
|
+
} else if (!config.db.database) {
|
|
661
|
+
error(
|
|
662
|
+
"Database name is missing from the config. Call `nile.init()` or set NILEDB_ID in your .env"
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
const caller = target[property];
|
|
667
|
+
return function query(...args) {
|
|
668
|
+
info("query", ...args);
|
|
669
|
+
const called = caller.apply(this, args);
|
|
670
|
+
return called;
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
return target[property];
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// src/db/NileInstance.ts
|
|
679
|
+
var NileDatabase = class {
|
|
680
|
+
pool;
|
|
681
|
+
tenantId;
|
|
682
|
+
userId;
|
|
683
|
+
id;
|
|
684
|
+
config;
|
|
685
|
+
timer;
|
|
686
|
+
constructor(config, id) {
|
|
687
|
+
const { warn, info, debug } = Logger(config, "[NileInstance]");
|
|
688
|
+
this.id = id;
|
|
689
|
+
const poolConfig = {
|
|
690
|
+
min: 0,
|
|
691
|
+
max: 10,
|
|
692
|
+
idleTimeoutMillis: 3e4,
|
|
693
|
+
...config.db
|
|
694
|
+
};
|
|
695
|
+
const { afterCreate, ...remaining } = poolConfig;
|
|
696
|
+
config.db = poolConfig;
|
|
697
|
+
this.config = config;
|
|
698
|
+
debug(`Connection pool config ${JSON.stringify(this.config.db)}`);
|
|
699
|
+
this.pool = createProxyForPool(new pg.Pool(remaining), this.config);
|
|
700
|
+
if (typeof afterCreate === "function") {
|
|
701
|
+
warn(
|
|
702
|
+
"Providing an pool configuration will stop automatic tenant context setting."
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
this.startTimeout();
|
|
706
|
+
this.pool.on("connect", async (client) => {
|
|
707
|
+
debug(`pool connected ${this.id}`);
|
|
708
|
+
this.startTimeout();
|
|
709
|
+
const afterCreate2 = makeAfterCreate(
|
|
710
|
+
config,
|
|
711
|
+
`${this.id}-${this.timer}`
|
|
712
|
+
);
|
|
713
|
+
afterCreate2(client, (err) => {
|
|
714
|
+
const { error } = Logger(config, "[after create callback]");
|
|
715
|
+
if (err) {
|
|
716
|
+
clearTimeout(this.timer);
|
|
717
|
+
error("after create failed", {
|
|
718
|
+
message: err.message,
|
|
719
|
+
stack: err.stack
|
|
720
|
+
});
|
|
721
|
+
evictPool(this.id);
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
this.pool.on("error", (err) => {
|
|
726
|
+
clearTimeout(this.timer);
|
|
727
|
+
info(`pool ${this.id} failed`, {
|
|
728
|
+
message: err.message,
|
|
729
|
+
stack: err.stack
|
|
730
|
+
});
|
|
731
|
+
evictPool(this.id);
|
|
732
|
+
});
|
|
733
|
+
this.pool.on("release", (destroy) => {
|
|
734
|
+
if (destroy) {
|
|
735
|
+
clearTimeout(this.timer);
|
|
736
|
+
evictPool(this.id);
|
|
737
|
+
debug(`destroying pool ${this.id}`);
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
startTimeout() {
|
|
742
|
+
const { debug } = Logger(this.config, "[NileInstance]");
|
|
743
|
+
if (this.timer) {
|
|
744
|
+
clearTimeout(this.timer);
|
|
745
|
+
}
|
|
746
|
+
this.timer = setTimeout(() => {
|
|
747
|
+
debug(
|
|
748
|
+
`Pool reached idleTimeoutMillis. ${this.id} evicted after ${Number(this.config.db.idleTimeoutMillis) ?? 3e4}ms`
|
|
749
|
+
);
|
|
750
|
+
this.pool.end(() => {
|
|
751
|
+
clearTimeout(this.timer);
|
|
752
|
+
evictPool(this.id);
|
|
753
|
+
});
|
|
754
|
+
}, Number(this.config.db.idleTimeoutMillis) ?? 3e4);
|
|
755
|
+
}
|
|
756
|
+
shutdown() {
|
|
757
|
+
const { debug } = Logger(this.config, "[NileInstance]");
|
|
758
|
+
debug(`attempting to shut down ${this.id}`);
|
|
759
|
+
clearTimeout(this.timer);
|
|
760
|
+
this.pool.end(() => {
|
|
761
|
+
debug(`${this.id} has been shut down`);
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
var NileInstance_default = NileDatabase;
|
|
766
|
+
function makeAfterCreate(config, id) {
|
|
767
|
+
const { error, warn, debug } = Logger(config, "[afterCreate]");
|
|
768
|
+
return (conn, done) => {
|
|
769
|
+
conn.on("error", function errorHandler(e) {
|
|
770
|
+
error(`Connection ${id} was terminated by server`, {
|
|
771
|
+
message: e.message,
|
|
772
|
+
stack: e.stack
|
|
773
|
+
});
|
|
774
|
+
done(e, conn);
|
|
775
|
+
});
|
|
776
|
+
if (config.tenantId) {
|
|
777
|
+
const query = [`SET nile.tenant_id = '${config.tenantId}'`];
|
|
778
|
+
if (config.userId) {
|
|
779
|
+
if (!config.tenantId) {
|
|
780
|
+
warn("A user id cannot be set in context without a tenant id");
|
|
781
|
+
}
|
|
782
|
+
query.push(`SET nile.user_id = '${config.userId}'`);
|
|
783
|
+
}
|
|
784
|
+
conn.query(query.join(";"), function(err) {
|
|
785
|
+
if (err) {
|
|
786
|
+
error("query connection failed", {
|
|
787
|
+
cause: err.cause,
|
|
788
|
+
stack: err.stack,
|
|
789
|
+
message: err.message,
|
|
790
|
+
name: err.name,
|
|
791
|
+
id
|
|
792
|
+
});
|
|
793
|
+
} else {
|
|
794
|
+
if (query.length === 1) {
|
|
795
|
+
debug(`connection context set: tenantId=${config.tenantId}`);
|
|
796
|
+
}
|
|
797
|
+
if (query.length === 2) {
|
|
798
|
+
debug(
|
|
799
|
+
`connection context set: tenantId=${config.tenantId} userId=${config.userId}`
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
done(err, conn);
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
done(null, conn);
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// src/db/DBManager.ts
|
|
811
|
+
var DBManager = class {
|
|
812
|
+
connections;
|
|
813
|
+
cleared;
|
|
814
|
+
poolWatcherFn;
|
|
815
|
+
makeId(tenantId, userId) {
|
|
816
|
+
if (tenantId && userId) {
|
|
817
|
+
return `${tenantId}:${userId}`;
|
|
818
|
+
}
|
|
819
|
+
if (tenantId) {
|
|
820
|
+
return `${tenantId}`;
|
|
821
|
+
}
|
|
822
|
+
return "base";
|
|
823
|
+
}
|
|
824
|
+
constructor(config) {
|
|
825
|
+
this.cleared = false;
|
|
826
|
+
this.connections = /* @__PURE__ */ new Map();
|
|
827
|
+
this.poolWatcherFn = this.poolWatcher(config);
|
|
828
|
+
watchEvictPool(this.poolWatcherFn);
|
|
829
|
+
}
|
|
830
|
+
poolWatcher = (config) => (id) => {
|
|
831
|
+
const { info, warn } = Logger(config, "[DBManager]");
|
|
832
|
+
if (id && this.connections.has(id)) {
|
|
833
|
+
info(`Removing ${id} from db connection pool.`);
|
|
834
|
+
const connection = this.connections.get(id);
|
|
835
|
+
connection?.shutdown();
|
|
836
|
+
this.connections.delete(id);
|
|
837
|
+
} else {
|
|
838
|
+
warn(`missed eviction of ${id}`);
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
getConnection = (config) => {
|
|
842
|
+
const { info } = Logger(config, "[DBManager]");
|
|
843
|
+
const id = this.makeId(config.tenantId, config.userId);
|
|
844
|
+
const existing = this.connections.get(id);
|
|
845
|
+
info(`# of instances: ${this.connections.size}`);
|
|
846
|
+
if (existing) {
|
|
847
|
+
info(`returning existing ${id}`);
|
|
848
|
+
existing.startTimeout();
|
|
849
|
+
return existing.pool;
|
|
850
|
+
}
|
|
851
|
+
const newOne = new NileInstance_default(new Config(config), id);
|
|
852
|
+
this.connections.set(id, newOne);
|
|
853
|
+
info(`created new ${id}`);
|
|
854
|
+
info(`# of instances: ${this.connections.size}`);
|
|
855
|
+
if (this.cleared) {
|
|
856
|
+
this.cleared = false;
|
|
857
|
+
}
|
|
858
|
+
return newOne.pool;
|
|
859
|
+
};
|
|
860
|
+
clear = (config) => {
|
|
861
|
+
const { info } = Logger(config, "[DBManager]");
|
|
862
|
+
info(`Clearing all connections ${this.connections.size}`);
|
|
863
|
+
this.cleared = true;
|
|
864
|
+
this.connections.forEach((connection) => {
|
|
865
|
+
connection.shutdown();
|
|
866
|
+
});
|
|
867
|
+
this.connections.clear();
|
|
868
|
+
};
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
// src/api/utils/routes/makeRestUrl.ts
|
|
872
|
+
var NILEDB_API_URL = process.env.NILEDB_API_URL;
|
|
873
|
+
function filterNullUndefined(obj) {
|
|
874
|
+
if (!obj) {
|
|
875
|
+
return void 0;
|
|
876
|
+
}
|
|
877
|
+
return Object.fromEntries(
|
|
878
|
+
Object.entries(obj).filter(
|
|
879
|
+
([, value]) => value !== null && value !== void 0
|
|
880
|
+
)
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
function makeRestUrl(config, path, qp) {
|
|
884
|
+
const url = config.api.basePath || NILEDB_API_URL;
|
|
885
|
+
if (!url) {
|
|
886
|
+
throw new Error(
|
|
887
|
+
"An API url is required. Set it via NILEDB_API_URL. Was auto configuration run?"
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
const params = new URLSearchParams(
|
|
891
|
+
filterNullUndefined(qp)
|
|
892
|
+
);
|
|
893
|
+
const strParams = params.toString();
|
|
894
|
+
return `${[url, path.substring(1, path.length)].join("/")}${strParams ? `?${strParams}` : ""}`;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// src/api/utils/routes/apiRoutes.ts
|
|
898
|
+
var apiRoutes = (config) => ({
|
|
899
|
+
ME: makeRestUrl(config, "/me"),
|
|
900
|
+
USERS: (qp) => makeRestUrl(config, "/users", qp),
|
|
901
|
+
USER: (userId) => makeRestUrl(config, `/users/${userId}`),
|
|
902
|
+
TENANTS: makeRestUrl(config, "/tenants"),
|
|
903
|
+
TENANT: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}`),
|
|
904
|
+
SIGNUP: makeRestUrl(config, "/signup"),
|
|
905
|
+
TENANT_USERS: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/users`),
|
|
906
|
+
TENANT_USER: (tenantId, userId) => makeRestUrl(config, `/tenants/${tenantId}/users/${userId}`),
|
|
907
|
+
USER_TENANTS: (userId) => makeRestUrl(config, `/users/${userId}/tenants`)
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
// src/api/routes/me/index.ts
|
|
911
|
+
var key = "ME";
|
|
912
|
+
async function GET(url, init, config) {
|
|
913
|
+
const res = await request(url, init, config);
|
|
914
|
+
return res;
|
|
915
|
+
}
|
|
916
|
+
async function route(request2, config) {
|
|
917
|
+
const url = apiRoutes(config)[key];
|
|
918
|
+
switch (request2.method) {
|
|
919
|
+
case "GET":
|
|
920
|
+
return await GET(url, { request: request2 }, config);
|
|
921
|
+
default:
|
|
922
|
+
return new Response("method not allowed", { status: 405 });
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function matches(configRoutes, request2) {
|
|
926
|
+
return urlMatches(request2.url, configRoutes[key]);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// src/utils/ResponseError.ts
|
|
930
|
+
var ResponseError = class {
|
|
931
|
+
response;
|
|
932
|
+
constructor(body, init) {
|
|
933
|
+
this.response = new Response(body, init);
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
// src/utils/fetch.ts
|
|
938
|
+
function getTokenFromCookie(headers, cookieKey) {
|
|
939
|
+
const cookie = headers.get("cookie")?.split("; ");
|
|
940
|
+
const _cookies = {};
|
|
941
|
+
if (cookie) {
|
|
942
|
+
for (const parts of cookie) {
|
|
943
|
+
const cookieParts = parts.split("=");
|
|
944
|
+
const _cookie = cookieParts.slice(1).join("=");
|
|
945
|
+
const name = cookieParts[0];
|
|
946
|
+
_cookies[name] = _cookie;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
if (cookie) {
|
|
950
|
+
for (const parts of cookie) {
|
|
951
|
+
const cookieParts = parts.split("=");
|
|
952
|
+
const _cookie = cookieParts.slice(1).join("=");
|
|
953
|
+
const name = cookieParts[0];
|
|
954
|
+
_cookies[name] = _cookie;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
if (cookieKey) {
|
|
958
|
+
return _cookies[cookieKey];
|
|
959
|
+
}
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
function getTenantFromHttp(headers, config) {
|
|
963
|
+
const cookieTenant = getTokenFromCookie(headers, X_NILE_TENANT);
|
|
964
|
+
return cookieTenant ?? headers?.get(X_NILE_TENANT) ?? config?.tenantId;
|
|
965
|
+
}
|
|
966
|
+
function getUserFromHttp(headers, config) {
|
|
967
|
+
const token = getTokenFromCookie(headers, config.api.cookieKey);
|
|
968
|
+
if (token) {
|
|
969
|
+
const jwt = decodeJwt(token);
|
|
970
|
+
return jwt.sub;
|
|
971
|
+
}
|
|
972
|
+
return headers?.get(X_NILE_USER_ID) ?? config.userId;
|
|
973
|
+
}
|
|
974
|
+
function makeBasicHeaders(config, opts) {
|
|
975
|
+
const headers = new Headers(opts?.headers);
|
|
976
|
+
headers.set("content-type", "application/json; charset=utf-8");
|
|
977
|
+
const cookieKey = config.api?.cookieKey;
|
|
978
|
+
const authHeader = headers.get("Authorization");
|
|
979
|
+
if (!authHeader) {
|
|
980
|
+
const token = getTokenFromCookie(headers, cookieKey);
|
|
981
|
+
if (token) {
|
|
982
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
983
|
+
} else if (getToken({ config })) {
|
|
984
|
+
headers.set("Authorization", `Bearer ${getToken({ config })}`);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
if ("secureCookies" in config && config.secureCookies != null) {
|
|
988
|
+
headers.set(X_NILE_SECURECOOKIES, String(config.secureCookies));
|
|
989
|
+
}
|
|
990
|
+
return headers;
|
|
991
|
+
}
|
|
992
|
+
async function _fetch(config, path, opts) {
|
|
993
|
+
const { debug, error } = Logger(config, "[server]");
|
|
994
|
+
const url = `${config.api?.basePath}${path}`;
|
|
995
|
+
const headers = new Headers(opts?.headers);
|
|
996
|
+
const tenantId = getTenantFromHttp(headers, config);
|
|
997
|
+
const basicHeaders = makeBasicHeaders(config, opts);
|
|
998
|
+
updateTenantId(tenantId);
|
|
999
|
+
const userId = getUserFromHttp(headers, config);
|
|
1000
|
+
updateUserId(userId);
|
|
1001
|
+
if (url.includes("{tenantId}") && !tenantId) {
|
|
1002
|
+
return new ResponseError("tenantId is not set for request", {
|
|
1003
|
+
status: 400
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
const useableUrl = url.replace("{tenantId}", encodeURIComponent(String(tenantId))).replace("{userId}", encodeURIComponent(String(userId)));
|
|
1007
|
+
debug(`[fetch] ${useableUrl}`);
|
|
1008
|
+
try {
|
|
1009
|
+
const response = await fetch(useableUrl, {
|
|
1010
|
+
...opts,
|
|
1011
|
+
headers: basicHeaders
|
|
1012
|
+
}).catch((e) => {
|
|
1013
|
+
error("[fetch][response]", {
|
|
1014
|
+
message: e.message,
|
|
1015
|
+
stack: e.stack,
|
|
1016
|
+
debug: "Is nile-auth running?"
|
|
1017
|
+
});
|
|
1018
|
+
return new Error(e);
|
|
1019
|
+
});
|
|
1020
|
+
if (response instanceof Error) {
|
|
1021
|
+
return new ResponseError("Failed to connect to database", {
|
|
1022
|
+
status: 400
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
1026
|
+
if (typeof response.clone === "function") {
|
|
1027
|
+
try {
|
|
1028
|
+
debug(
|
|
1029
|
+
`[fetch][response][${opts?.method ?? "GET"}] ${response.status} ${useableUrl}`,
|
|
1030
|
+
{
|
|
1031
|
+
body: await response.clone().json()
|
|
1032
|
+
}
|
|
1033
|
+
);
|
|
1034
|
+
} catch (e) {
|
|
1035
|
+
debug(
|
|
1036
|
+
`[fetch][response][${opts?.method ?? "GET"}] ${response.status} ${useableUrl}`,
|
|
1037
|
+
{
|
|
1038
|
+
body: await response.clone().text()
|
|
1039
|
+
}
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
return response;
|
|
1044
|
+
}
|
|
1045
|
+
if (response?.status === 404) {
|
|
1046
|
+
return new ResponseError("Not found", { status: 404 });
|
|
1047
|
+
}
|
|
1048
|
+
if (response?.status === 401) {
|
|
1049
|
+
return new ResponseError("Unauthorized", { status: 401 });
|
|
1050
|
+
}
|
|
1051
|
+
if (response?.status === 405) {
|
|
1052
|
+
return new ResponseError("Method not allowed", { status: 405 });
|
|
1053
|
+
}
|
|
1054
|
+
let res;
|
|
1055
|
+
const errorHandler = typeof response?.clone === "function" ? response.clone() : null;
|
|
1056
|
+
let msg = "";
|
|
1057
|
+
try {
|
|
1058
|
+
res = await response?.json();
|
|
1059
|
+
} catch (e) {
|
|
1060
|
+
if (errorHandler) {
|
|
1061
|
+
msg = await errorHandler.text();
|
|
1062
|
+
if (msg) {
|
|
1063
|
+
error(`[fetch][response][status: ${errorHandler.status}]`, {
|
|
1064
|
+
message: msg
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
return e;
|
|
1068
|
+
}
|
|
1069
|
+
if (!msg) {
|
|
1070
|
+
error("[fetch][response]", { e });
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
if (msg) {
|
|
1074
|
+
return new ResponseError(msg, { status: errorHandler?.status });
|
|
1075
|
+
}
|
|
1076
|
+
if (res && "message" in res) {
|
|
1077
|
+
const { message } = res;
|
|
1078
|
+
error(`[fetch][response][status: ${errorHandler?.status}] ${message}`);
|
|
1079
|
+
return new ResponseError(message, { status: 400 });
|
|
1080
|
+
}
|
|
1081
|
+
if (res && "errors" in res) {
|
|
1082
|
+
const {
|
|
1083
|
+
errors: [message]
|
|
1084
|
+
} = res;
|
|
1085
|
+
error(`[fetch][response] [status: ${errorHandler?.status}] ${message}`);
|
|
1086
|
+
return new ResponseError(message, { status: 400 });
|
|
1087
|
+
}
|
|
1088
|
+
error(
|
|
1089
|
+
`[fetch][response][status: ${errorHandler?.status}] UNHANDLED ERROR`,
|
|
1090
|
+
{
|
|
1091
|
+
res
|
|
1092
|
+
}
|
|
1093
|
+
);
|
|
1094
|
+
return new ResponseError(null, {
|
|
1095
|
+
status: response?.status ?? 500
|
|
1096
|
+
});
|
|
1097
|
+
} catch (e) {
|
|
1098
|
+
return new ResponseError("an unexpected error has occurred", {
|
|
1099
|
+
status: 500
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// src/api/routes/users/POST.ts
|
|
1105
|
+
async function POST(config, init) {
|
|
1106
|
+
init.body = init.request.body;
|
|
1107
|
+
init.method = "POST";
|
|
1108
|
+
const yurl = new URL(init.request.url);
|
|
1109
|
+
const tenantId = yurl.searchParams.get("tenantId");
|
|
1110
|
+
const newTenantName = yurl.searchParams.get("newTenantName");
|
|
1111
|
+
const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
|
|
1112
|
+
const url = apiRoutes(config).USERS({ tenantId: tenant, newTenantName });
|
|
1113
|
+
return await request(url, init, config);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// src/api/routes/users/GET.ts
|
|
1117
|
+
async function GET2(config, init, log) {
|
|
1118
|
+
const yurl = new URL(init.request.url);
|
|
1119
|
+
const tenantId = yurl.searchParams.get("tenantId");
|
|
1120
|
+
const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
|
|
1121
|
+
if (!tenant) {
|
|
1122
|
+
log("[GET] No tenant id provided.");
|
|
1123
|
+
return new Response(null, { status: 404 });
|
|
1124
|
+
}
|
|
1125
|
+
const url = apiRoutes(config).TENANT_USERS(tenant);
|
|
1126
|
+
init.method = "GET";
|
|
1127
|
+
return await request(url, init, config);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// src/api/routes/users/[userId]/PUT.ts
|
|
1131
|
+
async function PUT(config, session, init) {
|
|
1132
|
+
if (!session) {
|
|
1133
|
+
return new Response(null, { status: 401 });
|
|
1134
|
+
}
|
|
1135
|
+
init.body = init.request.body;
|
|
1136
|
+
init.method = "PUT";
|
|
1137
|
+
const [userId] = new URL(init.request.url).pathname.split("/").reverse();
|
|
1138
|
+
const url = apiRoutes(config).USER(userId);
|
|
1139
|
+
return await request(url, init, config);
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// src/api/routes/users/index.ts
|
|
1143
|
+
var key2 = "USERS";
|
|
1144
|
+
async function route2(request2, config) {
|
|
1145
|
+
const { info } = Logger(
|
|
1146
|
+
{ ...config, debug: config.debug },
|
|
1147
|
+
`[ROUTES][${key2}]`
|
|
1148
|
+
);
|
|
1149
|
+
const session = await auth(request2, config);
|
|
1150
|
+
switch (request2.method) {
|
|
1151
|
+
case "GET":
|
|
1152
|
+
return await GET2(config, { request: request2 }, info);
|
|
1153
|
+
case "POST":
|
|
1154
|
+
return await POST(config, { request: request2 });
|
|
1155
|
+
case "PUT":
|
|
1156
|
+
return await PUT(config, session, { request: request2 });
|
|
1157
|
+
default:
|
|
1158
|
+
return new Response("method not allowed", { status: 405 });
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
function matches2(configRoutes, request2) {
|
|
1162
|
+
return urlMatches(request2.url, configRoutes[key2]);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
// src/api/routes/tenants/[tenantId]/users/GET.ts
|
|
1166
|
+
async function GET3(config, init) {
|
|
1167
|
+
const yurl = new URL(init.request.url);
|
|
1168
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
1169
|
+
const url = `${apiRoutes(config).TENANT_USERS(tenantId)}`;
|
|
1170
|
+
return await request(url, init, config);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
// src/api/routes/tenants/[tenantId]/users/POST.ts
|
|
1174
|
+
async function POST2(config, session, init) {
|
|
1175
|
+
const yurl = new URL(init.request.url);
|
|
1176
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
1177
|
+
init.body = JSON.stringify({ email: session.email });
|
|
1178
|
+
init.method = "PUT";
|
|
1179
|
+
const url = apiRoutes(config).TENANT_USERS(tenantId);
|
|
1180
|
+
return await request(url, init, config);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// src/api/routes/tenants/[tenantId]/users/[userId]/DELETE.ts
|
|
1184
|
+
async function DELETE(config, init) {
|
|
1185
|
+
const yurl = new URL(init.request.url);
|
|
1186
|
+
const [userId, _, tenantId] = yurl.pathname.split("/").reverse();
|
|
1187
|
+
init.method = "DELETE";
|
|
1188
|
+
init.body = JSON.stringify({ email: userId });
|
|
1189
|
+
const url = `${apiRoutes(config).TENANT_USER(tenantId, userId)}`;
|
|
1190
|
+
return await request(url, init, config);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// src/api/routes/tenants/[tenantId]/users/PUT.ts
|
|
1194
|
+
async function PUT2(config, init) {
|
|
1195
|
+
const yurl = new URL(init.request.url);
|
|
1196
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
1197
|
+
init.method = "PUT";
|
|
1198
|
+
const url = `${apiRoutes(config).TENANT_USERS(tenantId)}`;
|
|
1199
|
+
return await request(url, init, config);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
// src/api/routes/tenants/[tenantId]/users/index.ts
|
|
1203
|
+
var key3 = "TENANT_USERS";
|
|
1204
|
+
async function route3(request2, config) {
|
|
1205
|
+
const { info } = Logger(
|
|
1206
|
+
{ ...config, debug: config.debug },
|
|
1207
|
+
`[ROUTES][${key3}]`
|
|
1208
|
+
);
|
|
1209
|
+
const session = await auth(request2, config);
|
|
1210
|
+
if (!session) {
|
|
1211
|
+
info("401");
|
|
1212
|
+
return new Response(null, { status: 401 });
|
|
1213
|
+
}
|
|
1214
|
+
const yurl = new URL(request2.url);
|
|
1215
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
1216
|
+
if (!tenantId) {
|
|
1217
|
+
info("No tenant id found in path");
|
|
1218
|
+
return new Response(null, { status: 404 });
|
|
1219
|
+
}
|
|
1220
|
+
switch (request2.method) {
|
|
1221
|
+
case "GET":
|
|
1222
|
+
return await GET3(config, { request: request2 });
|
|
1223
|
+
case "POST":
|
|
1224
|
+
return await POST2(config, session, { request: request2 });
|
|
1225
|
+
case "PUT":
|
|
1226
|
+
return await PUT2(config, { request: request2 });
|
|
1227
|
+
case "DELETE":
|
|
1228
|
+
return await DELETE(config, { request: request2 });
|
|
1229
|
+
default:
|
|
1230
|
+
return new Response("method not allowed", { status: 405 });
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
function matches3(configRoutes, request2) {
|
|
1234
|
+
const url = new URL(request2.url);
|
|
1235
|
+
const [userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
|
|
1236
|
+
let route15 = configRoutes[key3].replace("{tenantId}", tenantId).replace("{userId}", userId);
|
|
1237
|
+
if (userId === "users") {
|
|
1238
|
+
route15 = configRoutes[key3].replace("{tenantId}", possibleTenantId);
|
|
1239
|
+
}
|
|
1240
|
+
return urlMatches(request2.url, route15);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
// src/api/routes/tenants/GET.ts
|
|
1244
|
+
async function GET4(config, session, init) {
|
|
1245
|
+
let url = `${apiRoutes(config).USER_TENANTS(session.id)}`;
|
|
1246
|
+
if (typeof session === "object" && "user" in session && session.user) {
|
|
1247
|
+
url = `${apiRoutes(config).USER_TENANTS(session.user.id)}`;
|
|
1248
|
+
}
|
|
1249
|
+
const res = await request(url, init, config);
|
|
1250
|
+
return res;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
// src/api/routes/tenants/[tenantId]/GET.ts
|
|
1254
|
+
async function GET5(config, init, log) {
|
|
1255
|
+
const yurl = new URL(init.request.url);
|
|
1256
|
+
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
1257
|
+
if (!tenantId) {
|
|
1258
|
+
log("[GET] No tenant id provided.");
|
|
1259
|
+
return new Response(null, { status: 404 });
|
|
1260
|
+
}
|
|
1261
|
+
init.method = "GET";
|
|
1262
|
+
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
1263
|
+
return await request(url, init, config);
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// src/api/routes/tenants/[tenantId]/DELETE.ts
|
|
1267
|
+
async function DELETE2(config, init) {
|
|
1268
|
+
const yurl = new URL(init.request.url);
|
|
1269
|
+
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
1270
|
+
if (!tenantId) {
|
|
1271
|
+
return new Response(null, { status: 404 });
|
|
1272
|
+
}
|
|
1273
|
+
init.method = "DELETE";
|
|
1274
|
+
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
1275
|
+
return await request(url, init, config);
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
// src/api/routes/tenants/[tenantId]/PUT.ts
|
|
1279
|
+
async function PUT3(config, init) {
|
|
1280
|
+
const yurl = new URL(init.request.url);
|
|
1281
|
+
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
1282
|
+
if (!tenantId) {
|
|
1283
|
+
return new Response(null, { status: 404 });
|
|
1284
|
+
}
|
|
1285
|
+
init.body = init.request.body;
|
|
1286
|
+
init.method = "PUT";
|
|
1287
|
+
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
1288
|
+
return await request(url, init, config);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
// src/api/routes/tenants/POST.ts
|
|
1292
|
+
async function POST3(config, init) {
|
|
1293
|
+
init.body = init.request.body;
|
|
1294
|
+
init.method = "POST";
|
|
1295
|
+
const url = `${apiRoutes(config).TENANTS}`;
|
|
1296
|
+
return await request(url, init, config);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
// src/api/routes/tenants/index.ts
|
|
1300
|
+
function isUUID(value) {
|
|
1301
|
+
if (!value) {
|
|
1302
|
+
return false;
|
|
1303
|
+
}
|
|
1304
|
+
const regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5|7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
1305
|
+
return regex.test(value);
|
|
1306
|
+
}
|
|
1307
|
+
var key4 = "TENANTS";
|
|
1308
|
+
async function route4(request2, config) {
|
|
1309
|
+
const { info } = Logger(
|
|
1310
|
+
{ ...config, debug: config.debug },
|
|
1311
|
+
`[ROUTES][${key4}]`
|
|
1312
|
+
);
|
|
1313
|
+
const session = await auth(request2, config);
|
|
1314
|
+
if (!session) {
|
|
1315
|
+
info("401");
|
|
1316
|
+
return new Response(null, { status: 401 });
|
|
1317
|
+
}
|
|
1318
|
+
const [possibleTenantId] = request2.url.split("/").reverse();
|
|
1319
|
+
switch (request2.method) {
|
|
1320
|
+
case "GET":
|
|
1321
|
+
if (isUUID(possibleTenantId)) {
|
|
1322
|
+
return await GET5(config, { request: request2 }, info);
|
|
1323
|
+
}
|
|
1324
|
+
return await GET4(config, session, { request: request2 });
|
|
1325
|
+
case "POST":
|
|
1326
|
+
return await POST3(config, { request: request2 });
|
|
1327
|
+
case "DELETE":
|
|
1328
|
+
return await DELETE2(config, { request: request2 });
|
|
1329
|
+
case "PUT":
|
|
1330
|
+
return await PUT3(config, { request: request2 });
|
|
1331
|
+
default:
|
|
1332
|
+
return new Response("method not allowed", { status: 405 });
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
function matches4(configRoutes, request2) {
|
|
1336
|
+
return urlMatches(request2.url, configRoutes[key4]);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// src/api/utils/routes/proxyRoutes.ts
|
|
1340
|
+
var proxyRoutes = (config) => ({
|
|
1341
|
+
SIGNIN: makeRestUrl(config, "/auth/signin"),
|
|
1342
|
+
PROVIDERS: makeRestUrl(config, "/auth/providers"),
|
|
1343
|
+
SESSION: makeRestUrl(config, "/auth/session"),
|
|
1344
|
+
CSRF: makeRestUrl(config, "/auth/csrf"),
|
|
1345
|
+
CALLBACK: makeRestUrl(config, "/auth/callback"),
|
|
1346
|
+
SIGNOUT: makeRestUrl(config, "/auth/signout"),
|
|
1347
|
+
ERROR: makeRestUrl(config, "/auth/error"),
|
|
1348
|
+
VERIFY_REQUEST: makeRestUrl(config, "/auth/verify-request"),
|
|
1349
|
+
PASSWORD_RESET: makeRestUrl(config, "/auth/reset-password")
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1352
|
+
// src/api/routes/auth/signin.ts
|
|
1353
|
+
var key5 = "SIGNIN";
|
|
1354
|
+
async function route5(req, config) {
|
|
1355
|
+
let url = proxyRoutes(config)[key5];
|
|
1356
|
+
const init = {
|
|
1357
|
+
method: req.method,
|
|
1358
|
+
headers: req.headers
|
|
1359
|
+
};
|
|
1360
|
+
if (req.method === "POST") {
|
|
1361
|
+
const [provider] = new URL(req.url).pathname.split("/").reverse();
|
|
1362
|
+
url = `${proxyRoutes(config)[key5]}/${provider}`;
|
|
1363
|
+
}
|
|
1364
|
+
const passThroughUrl = new URL(req.url);
|
|
1365
|
+
const params = new URLSearchParams(passThroughUrl.search);
|
|
1366
|
+
url = `${url}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
|
|
1367
|
+
const res = await request(url, { ...init, request: req }, config);
|
|
1368
|
+
return res;
|
|
1369
|
+
}
|
|
1370
|
+
function matches5(configRoutes, request2) {
|
|
1371
|
+
return urlMatches(request2.url, configRoutes[key5]);
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// src/api/routes/auth/session.ts
|
|
1375
|
+
async function route6(req, config) {
|
|
1376
|
+
return request(
|
|
1377
|
+
proxyRoutes(config).SESSION,
|
|
1378
|
+
{
|
|
1379
|
+
method: req.method,
|
|
1380
|
+
request: req
|
|
1381
|
+
},
|
|
1382
|
+
config
|
|
1383
|
+
);
|
|
1384
|
+
}
|
|
1385
|
+
function matches6(configRoutes, request2) {
|
|
1386
|
+
return urlMatches(request2.url, configRoutes.SESSION);
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
// src/api/routes/auth/providers.ts
|
|
1390
|
+
async function route7(req, config) {
|
|
1391
|
+
return request(
|
|
1392
|
+
proxyRoutes(config).PROVIDERS,
|
|
1393
|
+
{
|
|
1394
|
+
method: req.method,
|
|
1395
|
+
request: req
|
|
1396
|
+
},
|
|
1397
|
+
config
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
function matches7(configRoutes, request2) {
|
|
1401
|
+
return urlMatches(request2.url, configRoutes.PROVIDERS);
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
// src/api/routes/auth/csrf.ts
|
|
1405
|
+
async function route8(req, config) {
|
|
1406
|
+
return request(
|
|
1407
|
+
proxyRoutes(config).CSRF,
|
|
1408
|
+
{
|
|
1409
|
+
method: req.method,
|
|
1410
|
+
request: req
|
|
1411
|
+
},
|
|
1412
|
+
config
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1415
|
+
function matches8(configRoutes, request2) {
|
|
1416
|
+
return urlMatches(request2.url, configRoutes.CSRF);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
// src/api/routes/auth/callback.ts
|
|
1420
|
+
var key6 = "CALLBACK";
|
|
1421
|
+
async function route9(req, config) {
|
|
1422
|
+
const { error } = Logger(
|
|
1423
|
+
{ ...config, debug: config.debug },
|
|
1424
|
+
`[ROUTES][${key6}]`
|
|
1425
|
+
);
|
|
1426
|
+
const [provider] = new URL(req.url).pathname.split("/").reverse();
|
|
1427
|
+
try {
|
|
1428
|
+
const passThroughUrl = new URL(req.url);
|
|
1429
|
+
const params = new URLSearchParams(passThroughUrl.search);
|
|
1430
|
+
const url = `${proxyRoutes(config)[key6]}/${provider}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
|
|
1431
|
+
const res = await request(
|
|
1432
|
+
url,
|
|
1433
|
+
{
|
|
1434
|
+
request: req,
|
|
1435
|
+
method: req.method
|
|
1436
|
+
},
|
|
1437
|
+
config
|
|
1438
|
+
).catch((e) => {
|
|
1439
|
+
error("an error as occurred", e);
|
|
1440
|
+
});
|
|
1441
|
+
const location = res?.headers.get("location");
|
|
1442
|
+
if (location) {
|
|
1443
|
+
return new Response(res?.body, {
|
|
1444
|
+
status: 302,
|
|
1445
|
+
headers: res?.headers
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
return new Response(res?.body, {
|
|
1449
|
+
status: res?.status,
|
|
1450
|
+
headers: res?.headers
|
|
1451
|
+
});
|
|
1452
|
+
} catch (e) {
|
|
1453
|
+
error(e);
|
|
1454
|
+
}
|
|
1455
|
+
return new Response("An unexpected error has occurred.", { status: 400 });
|
|
1456
|
+
}
|
|
1457
|
+
function matches9(configRoutes, request2) {
|
|
1458
|
+
return urlMatches(request2.url, configRoutes.CALLBACK);
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
// src/api/routes/auth/signout.ts
|
|
1462
|
+
var key7 = "SIGNOUT";
|
|
1463
|
+
async function route10(request2, config) {
|
|
1464
|
+
let url = proxyRoutes(config)[key7];
|
|
1465
|
+
const init = {
|
|
1466
|
+
method: request2.method
|
|
1467
|
+
};
|
|
1468
|
+
if (request2.method === "POST") {
|
|
1469
|
+
init.body = request2.body;
|
|
1470
|
+
const [provider] = new URL(request2.url).pathname.split("/").reverse();
|
|
1471
|
+
url = `${proxyRoutes(config)[key7]}/${provider}`;
|
|
1472
|
+
}
|
|
1473
|
+
const res = await request(url, { ...init, request: request2 }, config);
|
|
1474
|
+
return res;
|
|
1475
|
+
}
|
|
1476
|
+
function matches10(configRoutes, request2) {
|
|
1477
|
+
return urlMatches(request2.url, configRoutes[key7]);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
// src/api/routes/auth/error.ts
|
|
1481
|
+
var key8 = "ERROR";
|
|
1482
|
+
async function route11(req, config) {
|
|
1483
|
+
return request(
|
|
1484
|
+
proxyRoutes(config)[key8],
|
|
1485
|
+
{
|
|
1486
|
+
method: req.method,
|
|
1487
|
+
request: req
|
|
1488
|
+
},
|
|
1489
|
+
config
|
|
1490
|
+
);
|
|
1491
|
+
}
|
|
1492
|
+
function matches11(configRoutes, request2) {
|
|
1493
|
+
return urlMatches(request2.url, configRoutes[key8]);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
// src/api/routes/auth/verify-request.ts
|
|
1497
|
+
var key9 = "VERIFY_REQUEST";
|
|
1498
|
+
async function route12(req, config) {
|
|
1499
|
+
return request(
|
|
1500
|
+
proxyRoutes(config)[key9],
|
|
1501
|
+
{
|
|
1502
|
+
method: req.method,
|
|
1503
|
+
request: req
|
|
1504
|
+
},
|
|
1505
|
+
config
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
function matches12(configRoutes, request2) {
|
|
1509
|
+
return urlMatches(request2.url, configRoutes[key9]);
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
// src/api/routes/auth/password-reset.ts
|
|
1513
|
+
var key10 = "PASSWORD_RESET";
|
|
1514
|
+
async function route13(req, config) {
|
|
1515
|
+
let url = proxyRoutes(config)[key10];
|
|
1516
|
+
const { searchParams } = new URL(req.url);
|
|
1517
|
+
if (searchParams.size > 0) {
|
|
1518
|
+
url = `${url}?${searchParams.toString()}`;
|
|
1519
|
+
}
|
|
1520
|
+
const res = await request(
|
|
1521
|
+
url,
|
|
1522
|
+
{
|
|
1523
|
+
method: req.method,
|
|
1524
|
+
request: req
|
|
1525
|
+
},
|
|
1526
|
+
config
|
|
1527
|
+
);
|
|
1528
|
+
const location = res?.headers.get("location");
|
|
1529
|
+
if (location) {
|
|
1530
|
+
return new Response(res?.body, {
|
|
1531
|
+
status: 302,
|
|
1532
|
+
headers: res?.headers
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1535
|
+
return new Response(res?.body, {
|
|
1536
|
+
status: res?.status,
|
|
1537
|
+
headers: res?.headers
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1540
|
+
function matches13(configRoutes, request2) {
|
|
1541
|
+
return urlMatches(request2.url, configRoutes.PASSWORD_RESET);
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
// src/api/handlers/GET.ts
|
|
1545
|
+
function GETTER(configRoutes, config) {
|
|
1546
|
+
const { info, warn } = Logger(config, "[GET MATCHER]");
|
|
1547
|
+
return async function GET6(req) {
|
|
1548
|
+
if (matches(configRoutes, req)) {
|
|
1549
|
+
info("matches me");
|
|
1550
|
+
return route(req, config);
|
|
1551
|
+
}
|
|
1552
|
+
if (matches3(configRoutes, req)) {
|
|
1553
|
+
info("matches tenant users");
|
|
1554
|
+
return route3(req, config);
|
|
1555
|
+
}
|
|
1556
|
+
if (matches2(configRoutes, req)) {
|
|
1557
|
+
info("matches users");
|
|
1558
|
+
return route2(req, config);
|
|
1559
|
+
}
|
|
1560
|
+
if (matches4(configRoutes, req)) {
|
|
1561
|
+
info("matches tenants");
|
|
1562
|
+
return route4(req, config);
|
|
1563
|
+
}
|
|
1564
|
+
if (matches6(configRoutes, req)) {
|
|
1565
|
+
info("matches session");
|
|
1566
|
+
return route6(req, config);
|
|
1567
|
+
}
|
|
1568
|
+
if (matches5(configRoutes, req)) {
|
|
1569
|
+
info("matches signin");
|
|
1570
|
+
return route5(req, config);
|
|
1571
|
+
}
|
|
1572
|
+
if (matches7(configRoutes, req)) {
|
|
1573
|
+
info("matches providers");
|
|
1574
|
+
return route7(req, config);
|
|
1575
|
+
}
|
|
1576
|
+
if (matches8(configRoutes, req)) {
|
|
1577
|
+
info("matches csrf");
|
|
1578
|
+
return route8(req, config);
|
|
1579
|
+
}
|
|
1580
|
+
if (matches13(configRoutes, req)) {
|
|
1581
|
+
info("matches password reset");
|
|
1582
|
+
return route13(req, config);
|
|
1583
|
+
}
|
|
1584
|
+
if (matches9(configRoutes, req)) {
|
|
1585
|
+
info("matches callback");
|
|
1586
|
+
return route9(req, config);
|
|
1587
|
+
}
|
|
1588
|
+
if (matches10(configRoutes, req)) {
|
|
1589
|
+
info("matches signout");
|
|
1590
|
+
return route10(req, config);
|
|
1591
|
+
}
|
|
1592
|
+
if (matches12(configRoutes, req)) {
|
|
1593
|
+
info("matches verify-request");
|
|
1594
|
+
return route12(req, config);
|
|
1595
|
+
}
|
|
1596
|
+
if (matches11(configRoutes, req)) {
|
|
1597
|
+
info("matches error");
|
|
1598
|
+
return route11(req, config);
|
|
1599
|
+
}
|
|
1600
|
+
warn("No GET routes matched");
|
|
1601
|
+
return new Response(null, { status: 404 });
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
// src/api/routes/signup/POST.ts
|
|
1606
|
+
async function POST4(config, init) {
|
|
1607
|
+
init.body = init.request.body;
|
|
1608
|
+
init.method = "POST";
|
|
1609
|
+
const url = `${apiRoutes(config).SIGNUP}`;
|
|
1610
|
+
return await request(url, init, config);
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
// src/api/routes/signup/index.tsx
|
|
1614
|
+
var key11 = "SIGNUP";
|
|
1615
|
+
async function route14(request2, config) {
|
|
1616
|
+
switch (request2.method) {
|
|
1617
|
+
case "POST":
|
|
1618
|
+
return await POST4(config, { request: request2 });
|
|
1619
|
+
default:
|
|
1620
|
+
return new Response("method not allowed", { status: 405 });
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
function matches14(configRoutes, request2) {
|
|
1624
|
+
return urlMatches(request2.url, configRoutes[key11]);
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
// src/api/handlers/POST.ts
|
|
1628
|
+
function POSTER(configRoutes, config) {
|
|
1629
|
+
const { info, warn, error } = Logger(config, "[POST MATCHER]");
|
|
1630
|
+
return async function POST5(req) {
|
|
1631
|
+
if (matchesLog(configRoutes, req)) {
|
|
1632
|
+
error(req.body && await req.json());
|
|
1633
|
+
return new Response(null, { status: 200 });
|
|
1634
|
+
}
|
|
1635
|
+
if (matches3(configRoutes, req)) {
|
|
1636
|
+
info("matches tenant users");
|
|
1637
|
+
return route3(req, config);
|
|
1638
|
+
}
|
|
1639
|
+
if (matches14(configRoutes, req)) {
|
|
1640
|
+
info("matches signup");
|
|
1641
|
+
return route14(req, config);
|
|
1642
|
+
}
|
|
1643
|
+
if (matches2(configRoutes, req)) {
|
|
1644
|
+
info("matches users");
|
|
1645
|
+
return route2(req, config);
|
|
1646
|
+
}
|
|
1647
|
+
if (matches4(configRoutes, req)) {
|
|
1648
|
+
info("matches tenants");
|
|
1649
|
+
return route4(req, config);
|
|
1650
|
+
}
|
|
1651
|
+
if (matches6(configRoutes, req)) {
|
|
1652
|
+
info("matches session");
|
|
1653
|
+
return route6(req, config);
|
|
1654
|
+
}
|
|
1655
|
+
if (matches5(configRoutes, req)) {
|
|
1656
|
+
info("matches signin");
|
|
1657
|
+
return route5(req, config);
|
|
1658
|
+
}
|
|
1659
|
+
if (matches13(configRoutes, req)) {
|
|
1660
|
+
info("matches password reset");
|
|
1661
|
+
return route13(req, config);
|
|
1662
|
+
}
|
|
1663
|
+
if (matches7(configRoutes, req)) {
|
|
1664
|
+
info("matches providers");
|
|
1665
|
+
return route7(req, config);
|
|
1666
|
+
}
|
|
1667
|
+
if (matches8(configRoutes, req)) {
|
|
1668
|
+
info("matches csrf");
|
|
1669
|
+
return route8(req, config);
|
|
1670
|
+
}
|
|
1671
|
+
if (matches9(configRoutes, req)) {
|
|
1672
|
+
info("matches callback");
|
|
1673
|
+
return route9(req, config);
|
|
1674
|
+
}
|
|
1675
|
+
if (matches10(configRoutes, req)) {
|
|
1676
|
+
info("matches signout");
|
|
1677
|
+
return route10(req, config);
|
|
1678
|
+
}
|
|
1679
|
+
warn("No POST routes matched");
|
|
1680
|
+
return new Response(null, { status: 404 });
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
// src/api/handlers/DELETE.ts
|
|
1685
|
+
function DELETER(configRoutes, config) {
|
|
1686
|
+
const { info, warn } = Logger(config, "[DELETE MATCHER]");
|
|
1687
|
+
return async function DELETE3(req) {
|
|
1688
|
+
if (matches3(configRoutes, req)) {
|
|
1689
|
+
info("matches tenant users");
|
|
1690
|
+
return route3(req, config);
|
|
1691
|
+
}
|
|
1692
|
+
if (matches4(configRoutes, req)) {
|
|
1693
|
+
info("matches tenants");
|
|
1694
|
+
return route4(req, config);
|
|
1695
|
+
}
|
|
1696
|
+
warn("No DELETE routes matched");
|
|
1697
|
+
return new Response(null, { status: 404 });
|
|
1698
|
+
};
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
// src/api/handlers/PUT.ts
|
|
1702
|
+
function PUTER(configRoutes, config) {
|
|
1703
|
+
const { info, warn } = Logger(config, "[PUT MATCHER]");
|
|
1704
|
+
return async function PUT4(req) {
|
|
1705
|
+
if (matches3(configRoutes, req)) {
|
|
1706
|
+
info("matches tenant users");
|
|
1707
|
+
return route3(req, config);
|
|
1708
|
+
}
|
|
1709
|
+
if (matches2(configRoutes, req)) {
|
|
1710
|
+
info("matches users");
|
|
1711
|
+
return route2(req, config);
|
|
1712
|
+
}
|
|
1713
|
+
if (matches4(configRoutes, req)) {
|
|
1714
|
+
info("matches tenants");
|
|
1715
|
+
return route4(req, config);
|
|
1716
|
+
}
|
|
1717
|
+
if (matches13(configRoutes, req)) {
|
|
1718
|
+
info("matches reset password");
|
|
1719
|
+
return route13(req, config);
|
|
1720
|
+
}
|
|
1721
|
+
warn("No PUT routes matched");
|
|
1722
|
+
return new Response(null, { status: 404 });
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
// src/api/handlers/index.ts
|
|
1727
|
+
function Handlers(configRoutes, config) {
|
|
1728
|
+
const GET6 = GETTER(configRoutes, config);
|
|
1729
|
+
const POST5 = POSTER(configRoutes, config);
|
|
1730
|
+
const DELETE3 = DELETER(configRoutes, config);
|
|
1731
|
+
const PUT4 = PUTER(configRoutes, config);
|
|
1732
|
+
return {
|
|
1733
|
+
GET: GET6,
|
|
1734
|
+
POST: POST5,
|
|
1735
|
+
DELETE: DELETE3,
|
|
1736
|
+
PUT: PUT4
|
|
1737
|
+
};
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
// src/api/utils/routes/defaultRoutes.ts
|
|
1741
|
+
var appRoutes = (prefix = "/api") => ({
|
|
1742
|
+
SIGNIN: `${prefix}/auth/signin`,
|
|
1743
|
+
PROVIDERS: `${prefix}/auth/providers`,
|
|
1744
|
+
SESSION: `${prefix}/auth/session`,
|
|
1745
|
+
CSRF: `${prefix}/auth/csrf`,
|
|
1746
|
+
CALLBACK: `${prefix}/auth/callback`,
|
|
1747
|
+
SIGNOUT: `${prefix}/auth/signout`,
|
|
1748
|
+
ERROR: `${prefix}/auth/error`,
|
|
1749
|
+
VERIFY_REQUEST: `${prefix}/auth/verify-request`,
|
|
1750
|
+
PASSWORD_RESET: `${prefix}/auth/reset-password`,
|
|
1751
|
+
ME: `${prefix}/me`,
|
|
1752
|
+
USERS: `${prefix}/users`,
|
|
1753
|
+
TENANTS: `${prefix}/tenants`,
|
|
1754
|
+
TENANT: `${prefix}/tenants/{tenantId}`,
|
|
1755
|
+
TENANT_USER: `${prefix}/tenants/{tenantId}/users/{userId}`,
|
|
1756
|
+
TENANT_USERS: `${prefix}/tenants/{tenantId}/users`,
|
|
1757
|
+
SIGNUP: `${prefix}/signup`,
|
|
1758
|
+
LOG: `${prefix}/auth/_log`
|
|
1759
|
+
});
|
|
1760
|
+
|
|
1761
|
+
// src/utils/Requester/index.ts
|
|
1762
|
+
var Requester = class extends Config {
|
|
1763
|
+
constructor(config) {
|
|
1764
|
+
super(config);
|
|
1765
|
+
}
|
|
1766
|
+
async rawRequest(method, url, init, body) {
|
|
1767
|
+
const _init = {
|
|
1768
|
+
...init,
|
|
1769
|
+
body,
|
|
1770
|
+
method
|
|
1771
|
+
};
|
|
1772
|
+
const res = await _fetch(this, url, _init);
|
|
1773
|
+
if (res instanceof ResponseError) {
|
|
1774
|
+
return res.response;
|
|
1775
|
+
}
|
|
1776
|
+
return res;
|
|
1777
|
+
}
|
|
1778
|
+
/**
|
|
1779
|
+
* three options here
|
|
1780
|
+
* 1) pass in headers for a server side request
|
|
1781
|
+
* 2) pass in the payload that matches the api
|
|
1782
|
+
* 3) pass in the request object sent by a browser
|
|
1783
|
+
* @param method
|
|
1784
|
+
* @param url
|
|
1785
|
+
* @param req
|
|
1786
|
+
* @param init
|
|
1787
|
+
* @returns
|
|
1788
|
+
*/
|
|
1789
|
+
async request(method, url, req, init) {
|
|
1790
|
+
const headers = new Headers(init ? init?.headers : {});
|
|
1791
|
+
if (req instanceof Headers) {
|
|
1792
|
+
const tenantId = req.get(X_NILE_TENANT);
|
|
1793
|
+
const cookie = req.get("cookie");
|
|
1794
|
+
if (tenantId) {
|
|
1795
|
+
headers.set(X_NILE_TENANT, tenantId);
|
|
1796
|
+
}
|
|
1797
|
+
if (cookie) {
|
|
1798
|
+
headers.set("cookie", cookie);
|
|
1799
|
+
}
|
|
1800
|
+
} else if (req instanceof Request) {
|
|
1801
|
+
const _headers = new Headers(req?.headers);
|
|
1802
|
+
const tenantId = _headers.get(X_NILE_TENANT);
|
|
1803
|
+
const cookie = _headers.get("cookie");
|
|
1804
|
+
if (tenantId) {
|
|
1805
|
+
headers.set(X_NILE_TENANT, tenantId);
|
|
1806
|
+
}
|
|
1807
|
+
if (cookie) {
|
|
1808
|
+
headers.set("cookie", cookie);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
let body = JSON.stringify(req);
|
|
1812
|
+
if (method === "GET") {
|
|
1813
|
+
body = void 0;
|
|
1814
|
+
} else if (req instanceof Request) {
|
|
1815
|
+
body = await new Response(req.body).text();
|
|
1816
|
+
} else if (
|
|
1817
|
+
// is just headers for a GET request
|
|
1818
|
+
req instanceof Headers || JSON.stringify(req) === "{}" || req && typeof req === "object" && Object.values(req).length === 0
|
|
1819
|
+
) {
|
|
1820
|
+
body = void 0;
|
|
1821
|
+
}
|
|
1822
|
+
const _init = {
|
|
1823
|
+
...init,
|
|
1824
|
+
headers
|
|
1825
|
+
};
|
|
1826
|
+
return await this.rawRequest(method, url, _init, body);
|
|
1827
|
+
}
|
|
1828
|
+
async post(req, url, init) {
|
|
1829
|
+
const response = await this.request("POST", url, req, init);
|
|
1830
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
1831
|
+
const cloned = response.clone();
|
|
1832
|
+
try {
|
|
1833
|
+
return await cloned.json();
|
|
1834
|
+
} catch (e) {
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
return response;
|
|
1838
|
+
}
|
|
1839
|
+
async get(req, url, init) {
|
|
1840
|
+
const response = await this.request("GET", url, req, init);
|
|
1841
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
1842
|
+
const cloned = response.clone();
|
|
1843
|
+
try {
|
|
1844
|
+
return await cloned.json();
|
|
1845
|
+
} catch (e) {
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
return response;
|
|
1849
|
+
}
|
|
1850
|
+
async put(req, url, init) {
|
|
1851
|
+
const response = await this.request("PUT", url, req, init);
|
|
1852
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
1853
|
+
const cloned = response.clone();
|
|
1854
|
+
try {
|
|
1855
|
+
return await cloned.json();
|
|
1856
|
+
} catch (e) {
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
return response;
|
|
1860
|
+
}
|
|
1861
|
+
async delete(req, url, init) {
|
|
1862
|
+
const response = await this.request("DELETE", url, req, init);
|
|
1863
|
+
return response;
|
|
1864
|
+
}
|
|
1865
|
+
};
|
|
1866
|
+
|
|
1867
|
+
// src/auth/index.ts
|
|
1868
|
+
var ORIGIN = "https://us-west-2.api.dev.thenile.dev";
|
|
1869
|
+
function serverLogin(config, handlers) {
|
|
1870
|
+
const { info, error, debug } = Logger(config, "[server side login]");
|
|
1871
|
+
const routes = appRoutes(config.routePrefix);
|
|
1872
|
+
return async function login({
|
|
1873
|
+
email,
|
|
1874
|
+
password
|
|
1875
|
+
}) {
|
|
1876
|
+
if (!email || !password) {
|
|
1877
|
+
throw new Error("Server side login requires a user email and password.");
|
|
1878
|
+
}
|
|
1879
|
+
const sessionUrl = new URL(`${ORIGIN}${routes.PROVIDERS}`);
|
|
1880
|
+
const baseHeaders = {
|
|
1881
|
+
host: sessionUrl.host,
|
|
1882
|
+
[X_NILE_ORIGIN]: ORIGIN
|
|
1883
|
+
};
|
|
1884
|
+
info(`Obtaining providers for ${email}`);
|
|
1885
|
+
const sessionReq = new Request(sessionUrl, {
|
|
1886
|
+
method: "GET",
|
|
1887
|
+
...baseHeaders
|
|
1888
|
+
});
|
|
1889
|
+
const sessionRes = await handlers.POST(sessionReq);
|
|
1890
|
+
if (sessionRes?.status === 404) {
|
|
1891
|
+
throw new Error("Unable to login, cannot find region api.");
|
|
1892
|
+
}
|
|
1893
|
+
let providers;
|
|
1894
|
+
try {
|
|
1895
|
+
providers = await sessionRes?.json();
|
|
1896
|
+
} catch (e) {
|
|
1897
|
+
info(sessionUrl, { sessionRes });
|
|
1898
|
+
error(e);
|
|
1899
|
+
}
|
|
1900
|
+
info("Obtaining csrf");
|
|
1901
|
+
const csrf = new URL(`${ORIGIN}${routes.CSRF}`);
|
|
1902
|
+
const csrfReq = new Request(csrf, {
|
|
1903
|
+
method: "GET",
|
|
1904
|
+
headers: new Headers({
|
|
1905
|
+
...baseHeaders
|
|
1906
|
+
})
|
|
1907
|
+
});
|
|
1908
|
+
const csrfRes = await handlers.POST(csrfReq);
|
|
1909
|
+
let csrfToken;
|
|
1910
|
+
try {
|
|
1911
|
+
const json = await csrfRes?.json() ?? {};
|
|
1912
|
+
csrfToken = json?.csrfToken;
|
|
1913
|
+
} catch (e) {
|
|
1914
|
+
info(sessionUrl, { csrfRes });
|
|
1915
|
+
error(e, { csrfRes });
|
|
1916
|
+
}
|
|
1917
|
+
const { credentials } = providers ?? {};
|
|
1918
|
+
const csrfCookie = csrfRes?.headers.get("set-cookie");
|
|
1919
|
+
if (!credentials) {
|
|
1920
|
+
throw new Error(
|
|
1921
|
+
"Unable to obtain credential provider. Aborting server side login."
|
|
1922
|
+
);
|
|
1923
|
+
}
|
|
1924
|
+
const signInUrl = new URL(credentials.callbackUrl);
|
|
1925
|
+
if (!csrfCookie) {
|
|
1926
|
+
debug("CSRF failed", { headers: csrfRes?.headers });
|
|
1927
|
+
throw new Error("Unable to authenticate REST, CSRF missing.");
|
|
1928
|
+
}
|
|
1929
|
+
info(`Attempting sign in with email ${email} ${signInUrl.href}`);
|
|
1930
|
+
const body = JSON.stringify({
|
|
1931
|
+
email,
|
|
1932
|
+
password,
|
|
1933
|
+
csrfToken,
|
|
1934
|
+
callbackUrl: credentials.callbackUrl
|
|
1935
|
+
});
|
|
1936
|
+
const postReq = new Request(signInUrl, {
|
|
1937
|
+
method: "POST",
|
|
1938
|
+
headers: new Headers({
|
|
1939
|
+
...baseHeaders,
|
|
1940
|
+
"content-type": "application/json",
|
|
1941
|
+
cookie: csrfCookie.split(",").join("; ")
|
|
1942
|
+
}),
|
|
1943
|
+
body
|
|
1944
|
+
});
|
|
1945
|
+
const loginRes = await handlers.POST(postReq);
|
|
1946
|
+
const authCookie = loginRes?.headers.get("set-cookie");
|
|
1947
|
+
if (!authCookie) {
|
|
1948
|
+
throw new Error("authentication failed");
|
|
1949
|
+
}
|
|
1950
|
+
const [, token] = /((__Secure-)?nile\.session-token=.+?);/.exec(authCookie) ?? [];
|
|
1951
|
+
if (!token) {
|
|
1952
|
+
error("Unable to obtain auth token", { authCookie });
|
|
1953
|
+
throw new Error("Server login failed");
|
|
1954
|
+
}
|
|
1955
|
+
info("Server login successful", { authCookie, csrfCookie });
|
|
1956
|
+
const headers = new Headers({
|
|
1957
|
+
...baseHeaders,
|
|
1958
|
+
cookie: [token, csrfCookie].join("; ")
|
|
1959
|
+
});
|
|
1960
|
+
return headers;
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
var Auth = class extends Config {
|
|
1964
|
+
headers;
|
|
1965
|
+
constructor(config, headers) {
|
|
1966
|
+
super(config);
|
|
1967
|
+
this.headers = headers;
|
|
1968
|
+
}
|
|
1969
|
+
handleHeaders(init) {
|
|
1970
|
+
if (this.headers) {
|
|
1971
|
+
if (init) {
|
|
1972
|
+
init.headers = new Headers({ ...this.headers, ...init?.headers });
|
|
1973
|
+
return init;
|
|
1974
|
+
} else {
|
|
1975
|
+
init = {
|
|
1976
|
+
headers: this.headers
|
|
1977
|
+
};
|
|
1978
|
+
return init;
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
return void 0;
|
|
1982
|
+
}
|
|
1983
|
+
get sessionUrl() {
|
|
1984
|
+
return "/auth/session";
|
|
1985
|
+
}
|
|
1986
|
+
getSession = async (req, init) => {
|
|
1987
|
+
const _requester = new Requester(this);
|
|
1988
|
+
const _init = this.handleHeaders(init);
|
|
1989
|
+
const session = await _requester.get(req, this.sessionUrl, _init);
|
|
1990
|
+
if (Object.keys(session).length === 0) {
|
|
1991
|
+
return void 0;
|
|
1992
|
+
}
|
|
1993
|
+
return session;
|
|
1994
|
+
};
|
|
1995
|
+
};
|
|
1996
|
+
|
|
1997
|
+
// src/tenants/index.ts
|
|
1998
|
+
var Tenants = class extends Config {
|
|
1999
|
+
headers;
|
|
2000
|
+
constructor(config, headers) {
|
|
2001
|
+
super(config);
|
|
2002
|
+
this.headers = headers;
|
|
2003
|
+
}
|
|
2004
|
+
handleHeaders(init) {
|
|
2005
|
+
if (this.headers) {
|
|
2006
|
+
if (init) {
|
|
2007
|
+
init.headers = new Headers({ ...this.headers, ...init?.headers });
|
|
2008
|
+
return init;
|
|
2009
|
+
} else {
|
|
2010
|
+
init = {
|
|
2011
|
+
headers: this.headers
|
|
2012
|
+
};
|
|
2013
|
+
return init;
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
return void 0;
|
|
2017
|
+
}
|
|
2018
|
+
get tenantsUrl() {
|
|
2019
|
+
return "/tenants";
|
|
2020
|
+
}
|
|
2021
|
+
get tenantUrl() {
|
|
2022
|
+
return `/tenants/${this.tenantId ?? "{tenantId}"}`;
|
|
2023
|
+
}
|
|
2024
|
+
createTenant = async (req, init) => {
|
|
2025
|
+
let _req;
|
|
2026
|
+
if (typeof req === "string") {
|
|
2027
|
+
_req = new Request(`${this.api.basePath}${this.tenantsUrl}`, {
|
|
2028
|
+
body: JSON.stringify({ name: req }),
|
|
2029
|
+
method: "POST",
|
|
2030
|
+
headers: {
|
|
2031
|
+
"content-type": "application/json"
|
|
2032
|
+
}
|
|
2033
|
+
});
|
|
2034
|
+
} else {
|
|
2035
|
+
_req = req;
|
|
2036
|
+
}
|
|
2037
|
+
const _requester = new Requester(this);
|
|
2038
|
+
const _init = this.handleHeaders(init);
|
|
2039
|
+
return _requester.post(_req, this.tenantsUrl, _init);
|
|
2040
|
+
};
|
|
2041
|
+
getTenant = async (req, init) => {
|
|
2042
|
+
if (typeof req === "string") {
|
|
2043
|
+
this.tenantId = req;
|
|
2044
|
+
}
|
|
2045
|
+
const _requester = new Requester(this);
|
|
2046
|
+
const _init = this.handleHeaders(init);
|
|
2047
|
+
return _requester.get(req, this.tenantUrl, _init);
|
|
2048
|
+
};
|
|
2049
|
+
get tenantListUrl() {
|
|
2050
|
+
return `/users/${this.userId ?? "{userId}"}/tenants`;
|
|
2051
|
+
}
|
|
2052
|
+
listTenants = async (req, init) => {
|
|
2053
|
+
const _requester = new Requester(this);
|
|
2054
|
+
const _init = this.handleHeaders(init);
|
|
2055
|
+
return _requester.get(req, this.tenantListUrl, _init);
|
|
2056
|
+
};
|
|
2057
|
+
deleteTenant = async (req, init) => {
|
|
2058
|
+
if (typeof req === "string") {
|
|
2059
|
+
this.tenantId = req;
|
|
2060
|
+
}
|
|
2061
|
+
const _requester = new Requester(this);
|
|
2062
|
+
const _init = this.handleHeaders(init);
|
|
2063
|
+
return _requester.delete(req, this.tenantUrl, _init);
|
|
2064
|
+
};
|
|
2065
|
+
updateTenant = async (req, init) => {
|
|
2066
|
+
let _req;
|
|
2067
|
+
if (req && "name" in req) {
|
|
2068
|
+
_req = new Request(`${this.api.basePath}${this.tenantUrl}`, {
|
|
2069
|
+
body: JSON.stringify(req),
|
|
2070
|
+
method: "PUT"
|
|
2071
|
+
});
|
|
2072
|
+
} else {
|
|
2073
|
+
_req = req;
|
|
2074
|
+
}
|
|
2075
|
+
const _requester = new Requester(this);
|
|
2076
|
+
const _init = this.handleHeaders(init);
|
|
2077
|
+
return _requester.put(_req, this.tenantUrl, _init);
|
|
2078
|
+
};
|
|
2079
|
+
};
|
|
2080
|
+
|
|
2081
|
+
// src/users/index.ts
|
|
2082
|
+
var Users = class extends Config {
|
|
2083
|
+
headers;
|
|
2084
|
+
constructor(config, headers) {
|
|
2085
|
+
super(config);
|
|
2086
|
+
this.headers = headers;
|
|
2087
|
+
}
|
|
2088
|
+
get usersUrl() {
|
|
2089
|
+
return "/users";
|
|
2090
|
+
}
|
|
2091
|
+
get tenantUsersUrl() {
|
|
2092
|
+
return `/tenants/${this.tenantId ?? "{tenantId}"}/users`;
|
|
2093
|
+
}
|
|
2094
|
+
get linkUsersUrl() {
|
|
2095
|
+
return `/tenants/${this.tenantId ?? "{tenantId}"}/users/${this.userId ?? "{userId}"}/link`;
|
|
2096
|
+
}
|
|
2097
|
+
get tenantUserUrl() {
|
|
2098
|
+
return `/tenants/${this.tenantId ?? "{tenantId}"}/users/${this.userId ?? "{userId}"}`;
|
|
2099
|
+
}
|
|
2100
|
+
handleHeaders(init) {
|
|
2101
|
+
if (this.headers) {
|
|
2102
|
+
if (init) {
|
|
2103
|
+
init.headers = new Headers({ ...this.headers, ...init?.headers });
|
|
2104
|
+
return init;
|
|
2105
|
+
} else {
|
|
2106
|
+
init = {
|
|
2107
|
+
headers: this.headers
|
|
2108
|
+
};
|
|
2109
|
+
return init;
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
return void 0;
|
|
2113
|
+
}
|
|
2114
|
+
createUser = async (req, init) => {
|
|
2115
|
+
const _requester = new Requester(this);
|
|
2116
|
+
const _init = this.handleHeaders(init);
|
|
2117
|
+
return await _requester.post(req, this.usersUrl, _init);
|
|
2118
|
+
};
|
|
2119
|
+
createTenantUser = async (req, init) => {
|
|
2120
|
+
const _requester = new Requester(this);
|
|
2121
|
+
const _init = this.handleHeaders(init);
|
|
2122
|
+
return await _requester.post(req, this.tenantUsersUrl, _init);
|
|
2123
|
+
};
|
|
2124
|
+
updateUser = async (req, init) => {
|
|
2125
|
+
let _req;
|
|
2126
|
+
if (req && "id" in req) {
|
|
2127
|
+
_req = new Request(`${this.api.basePath}${this.tenantUserUrl}`, {
|
|
2128
|
+
body: JSON.stringify(req),
|
|
2129
|
+
method: "PUT"
|
|
2130
|
+
});
|
|
2131
|
+
this.userId = String(req.id);
|
|
2132
|
+
} else {
|
|
2133
|
+
_req = req;
|
|
2134
|
+
}
|
|
2135
|
+
const _requester = new Requester(this);
|
|
2136
|
+
const _init = this.handleHeaders(init);
|
|
2137
|
+
return await _requester.put(_req, this.tenantUserUrl, _init);
|
|
2138
|
+
};
|
|
2139
|
+
listUsers = async (req, init) => {
|
|
2140
|
+
const _requester = new Requester(this);
|
|
2141
|
+
const _init = this.handleHeaders(init);
|
|
2142
|
+
return await _requester.get(req, this.tenantUsersUrl, _init);
|
|
2143
|
+
};
|
|
2144
|
+
linkUser = async (req, init) => {
|
|
2145
|
+
const _requester = new Requester(this);
|
|
2146
|
+
if (typeof req === "string") {
|
|
2147
|
+
this.userId = req;
|
|
2148
|
+
} else {
|
|
2149
|
+
if ("id" in req) {
|
|
2150
|
+
this.userId = req.id;
|
|
2151
|
+
}
|
|
2152
|
+
if ("tenantId" in req) {
|
|
2153
|
+
this.tenantId = req.tenantId;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
const _init = this.handleHeaders(init);
|
|
2157
|
+
return await _requester.put(req, this.linkUsersUrl, _init);
|
|
2158
|
+
};
|
|
2159
|
+
unlinkUser = async (req, init) => {
|
|
2160
|
+
if (typeof req === "string") {
|
|
2161
|
+
this.userId = req;
|
|
2162
|
+
} else {
|
|
2163
|
+
if ("id" in req) {
|
|
2164
|
+
this.userId = req.id;
|
|
2165
|
+
}
|
|
2166
|
+
if ("tenantId" in req) {
|
|
2167
|
+
this.tenantId = req.tenantId;
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
const _requester = new Requester(this);
|
|
2171
|
+
const _init = this.handleHeaders(init);
|
|
2172
|
+
return await _requester.delete(req, this.linkUsersUrl, _init);
|
|
2173
|
+
};
|
|
2174
|
+
get meUrl() {
|
|
2175
|
+
return "/me";
|
|
2176
|
+
}
|
|
2177
|
+
me = async (req, init) => {
|
|
2178
|
+
const _requester = new Requester(this);
|
|
2179
|
+
const _init = this.handleHeaders(init);
|
|
2180
|
+
return await _requester.get(req, this.meUrl, _init);
|
|
2181
|
+
};
|
|
2182
|
+
updateMe = async (req, init) => {
|
|
2183
|
+
const _requester = new Requester(this);
|
|
2184
|
+
const _init = this.handleHeaders(init);
|
|
2185
|
+
return await _requester.put(req, this.meUrl, _init);
|
|
2186
|
+
};
|
|
2187
|
+
};
|
|
2188
|
+
|
|
2189
|
+
// src/Api.ts
|
|
2190
|
+
var Api = class {
|
|
2191
|
+
config;
|
|
2192
|
+
users;
|
|
2193
|
+
auth;
|
|
2194
|
+
tenants;
|
|
2195
|
+
routes;
|
|
2196
|
+
_headers;
|
|
2197
|
+
handlers;
|
|
2198
|
+
paths;
|
|
2199
|
+
constructor(config) {
|
|
2200
|
+
this.config = config;
|
|
2201
|
+
this.auth = new Auth(config);
|
|
2202
|
+
this.users = new Users(config);
|
|
2203
|
+
this.tenants = new Tenants(config);
|
|
2204
|
+
this.routes = {
|
|
2205
|
+
...appRoutes(config?.routePrefix),
|
|
2206
|
+
...config?.routes
|
|
2207
|
+
};
|
|
2208
|
+
this.handlers = Handlers(this.routes, config);
|
|
2209
|
+
this.paths = {
|
|
2210
|
+
get: [
|
|
2211
|
+
this.routes.ME,
|
|
2212
|
+
this.routes.TENANT_USERS,
|
|
2213
|
+
this.routes.TENANTS,
|
|
2214
|
+
this.routes.TENANT,
|
|
2215
|
+
this.routes.SESSION,
|
|
2216
|
+
this.routes.SIGNIN,
|
|
2217
|
+
this.routes.PROVIDERS,
|
|
2218
|
+
this.routes.CSRF,
|
|
2219
|
+
this.routes.PASSWORD_RESET,
|
|
2220
|
+
this.routes.CALLBACK,
|
|
2221
|
+
this.routes.SIGNOUT,
|
|
2222
|
+
this.routes.VERIFY_REQUEST,
|
|
2223
|
+
this.routes.ERROR
|
|
2224
|
+
],
|
|
2225
|
+
post: [
|
|
2226
|
+
this.routes.TENANT_USERS,
|
|
2227
|
+
this.routes.SIGNUP,
|
|
2228
|
+
this.routes.USERS,
|
|
2229
|
+
this.routes.TENANTS,
|
|
2230
|
+
this.routes.SESSION,
|
|
2231
|
+
this.routes.SIGNIN,
|
|
2232
|
+
this.routes.PASSWORD_RESET,
|
|
2233
|
+
this.routes.PROVIDERS,
|
|
2234
|
+
this.routes.CSRF,
|
|
2235
|
+
`${this.routes.CALLBACK}/{provider}`,
|
|
2236
|
+
this.routes.SIGNOUT
|
|
2237
|
+
],
|
|
2238
|
+
put: [
|
|
2239
|
+
this.routes.TENANT_USERS,
|
|
2240
|
+
this.routes.USERS,
|
|
2241
|
+
this.routes.TENANT,
|
|
2242
|
+
this.routes.PASSWORD_RESET
|
|
2243
|
+
],
|
|
2244
|
+
delete: [this.routes.TENANT_USER, this.routes.TENANT]
|
|
2245
|
+
};
|
|
2246
|
+
}
|
|
2247
|
+
updateConfig(config) {
|
|
2248
|
+
this.config = config;
|
|
2249
|
+
this.handlers = Handlers(this.routes, config);
|
|
2250
|
+
}
|
|
2251
|
+
set headers(headers) {
|
|
2252
|
+
this.users = new Users(this.config, headers);
|
|
2253
|
+
this.tenants = new Tenants(this.config, headers);
|
|
2254
|
+
this.auth = new Auth(this.config, headers);
|
|
2255
|
+
this._headers = headers;
|
|
2256
|
+
}
|
|
2257
|
+
async login(payload) {
|
|
2258
|
+
this.headers = await serverLogin(this.config, this.handlers)(payload);
|
|
2259
|
+
}
|
|
2260
|
+
async session(req) {
|
|
2261
|
+
if (req instanceof Headers) {
|
|
2262
|
+
return this.auth.getSession(req);
|
|
2263
|
+
} else if (req instanceof Request) {
|
|
2264
|
+
return auth(req, this.config);
|
|
2265
|
+
}
|
|
2266
|
+
return this.auth.getSession(this._headers);
|
|
2267
|
+
}
|
|
2268
|
+
};
|
|
2269
|
+
|
|
2270
|
+
// src/Server.ts
|
|
2271
|
+
var Server = class {
|
|
2272
|
+
config;
|
|
2273
|
+
api;
|
|
2274
|
+
manager;
|
|
2275
|
+
constructor(config) {
|
|
2276
|
+
this.config = new Config(config, "[initial config]");
|
|
2277
|
+
this.api = new Api(this.config);
|
|
2278
|
+
this.manager = new DBManager(this.config);
|
|
2279
|
+
watchTenantId((tenantId) => {
|
|
2280
|
+
this.tenantId = tenantId;
|
|
2281
|
+
});
|
|
2282
|
+
watchUserId((userId) => {
|
|
2283
|
+
this.userId = userId;
|
|
2284
|
+
});
|
|
2285
|
+
watchToken((token) => {
|
|
2286
|
+
this.token = token;
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
setConfig(cfg) {
|
|
2290
|
+
this.config = new Config(cfg);
|
|
2291
|
+
this.api.updateConfig(this.config);
|
|
2292
|
+
}
|
|
2293
|
+
async init(cfg) {
|
|
2294
|
+
const updatedConfig = await this.config.configure({
|
|
2295
|
+
...this.config,
|
|
2296
|
+
...cfg
|
|
2297
|
+
});
|
|
2298
|
+
this.setConfig(updatedConfig);
|
|
2299
|
+
return this;
|
|
2300
|
+
}
|
|
2301
|
+
set databaseId(val) {
|
|
2302
|
+
if (val) {
|
|
2303
|
+
this.config.databaseId = val;
|
|
2304
|
+
this.api.users.databaseId = val;
|
|
2305
|
+
this.api.tenants.databaseId = val;
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
get userId() {
|
|
2309
|
+
return this.config.userId;
|
|
2310
|
+
}
|
|
2311
|
+
set userId(userId) {
|
|
2312
|
+
this.databaseId = this.config.databaseId;
|
|
2313
|
+
this.config.userId = userId;
|
|
2314
|
+
if (this.api) {
|
|
2315
|
+
this.api.users.userId = this.config.userId;
|
|
2316
|
+
this.api.tenants.userId = this.config.userId;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
get tenantId() {
|
|
2320
|
+
return this.config.tenantId;
|
|
2321
|
+
}
|
|
2322
|
+
set tenantId(tenantId) {
|
|
2323
|
+
this.databaseId = this.config.databaseId;
|
|
2324
|
+
this.config.tenantId = tenantId;
|
|
2325
|
+
if (this.api) {
|
|
2326
|
+
this.api.users.tenantId = tenantId;
|
|
2327
|
+
this.api.tenants.tenantId = tenantId;
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
get token() {
|
|
2331
|
+
return this.config?.api?.token;
|
|
2332
|
+
}
|
|
2333
|
+
set token(token) {
|
|
2334
|
+
if (token) {
|
|
2335
|
+
this.config.api.token = token;
|
|
2336
|
+
if (this.api) {
|
|
2337
|
+
this.api.users.api.token = token;
|
|
2338
|
+
this.api.tenants.api.token = token;
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
get db() {
|
|
2343
|
+
return this.manager.getConnection(this.config);
|
|
2344
|
+
}
|
|
2345
|
+
clearConnections() {
|
|
2346
|
+
this.manager.clear(this.config);
|
|
2347
|
+
}
|
|
2348
|
+
/**
|
|
2349
|
+
* A convenience function that applies a config and ensures whatever was passed is set properly
|
|
2350
|
+
*/
|
|
2351
|
+
getInstance(config) {
|
|
2352
|
+
const _config = { ...this.config, ...config };
|
|
2353
|
+
const updatedConfig = new Config(_config);
|
|
2354
|
+
this.setConfig(updatedConfig);
|
|
2355
|
+
this.tenantId = updatedConfig.tenantId;
|
|
2356
|
+
this.userId = updatedConfig.userId;
|
|
2357
|
+
if (updatedConfig.api.token) {
|
|
2358
|
+
this.token = updatedConfig.api.token;
|
|
2359
|
+
}
|
|
2360
|
+
this.databaseId = updatedConfig.databaseId;
|
|
2361
|
+
return this;
|
|
2362
|
+
}
|
|
2363
|
+
};
|
|
2364
|
+
var server;
|
|
2365
|
+
async function create(config) {
|
|
2366
|
+
if (!server) {
|
|
2367
|
+
server = new Server(config);
|
|
2368
|
+
}
|
|
2369
|
+
if (config) {
|
|
2370
|
+
return await server.init(new Config(config));
|
|
2371
|
+
}
|
|
2372
|
+
return await server.init();
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
export { LoginUserResponseTokenTypeEnum, create as Nile, Server };
|
|
2376
|
+
//# sourceMappingURL=index.mjs.map
|
|
2377
|
+
//# sourceMappingURL=index.mjs.map
|