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