@niledatabase/server 5.0.0-alpha.0 → 5.0.0-alpha.10

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/index.js CHANGED
@@ -2,12 +2,28 @@
2
2
 
3
3
  require('dotenv/config');
4
4
  var pg = require('pg');
5
- var jose = require('jose');
6
5
 
7
6
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
7
 
9
8
  var pg__default = /*#__PURE__*/_interopDefault(pg);
10
9
 
10
+ // src/types.ts
11
+ var APIErrorErrorCodeEnum = {
12
+ InternalError: "internal_error",
13
+ BadRequest: "bad_request",
14
+ EntityNotFound: "entity_not_found",
15
+ DuplicateEntity: "duplicate_entity",
16
+ InvalidCredentials: "invalid_credentials",
17
+ UnknownOidcProvider: "unknown_oidc_provider",
18
+ ProviderAlreadyExists: "provider_already_exists",
19
+ ProviderConfigError: "provider_config_error",
20
+ ProviderMismatch: "provider_mismatch",
21
+ ProviderUpdateError: "provider_update_error",
22
+ SessionStateMissing: "session_state_missing",
23
+ SessionStateMismatch: "session_state_mismatch",
24
+ OidcCodeMissing: "oidc_code_missing"
25
+ };
26
+
11
27
  // src/users/types.ts
12
28
  var LoginUserResponseTokenTypeEnum = {
13
29
  AccessToken: "ACCESS_TOKEN",
@@ -15,212 +31,184 @@ var LoginUserResponseTokenTypeEnum = {
15
31
  IdToken: "ID_TOKEN"
16
32
  };
17
33
 
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
- }
34
+ // src/utils/constants.ts
35
+ var TENANT_COOKIE = "nile.tenant-id";
36
+ var USER_COOKIE = "nile.user-id";
37
+ var HEADER_ORIGIN = "nile-origin";
38
+ var HEADER_SECURE_COOKIES = "nile-secure-cookies";
23
39
 
24
- // src/utils/Logger.ts
25
- var red = "\x1B[31m";
26
- var yellow = "\x1B[38;2;255;255;0m";
27
- var purple = "\x1B[38;2;200;160;255m";
28
- var orange = "\x1B[38;2;255;165;0m";
29
- var reset = "\x1B[0m";
30
- var baseLogger = (config, ...params) => ({
31
- info(message, meta) {
32
- if (config?.debug) {
33
- console.info(
34
- `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
35
- ""
36
- )}${reset} ${message}`,
37
- meta ? `${JSON.stringify(meta)}` : ""
38
- );
39
- }
40
- },
41
- debug(message, meta) {
42
- if (config?.debug) {
43
- console.debug(
44
- `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
45
- ""
46
- )}${reset} ${message}`,
47
- meta ? `${JSON.stringify(meta)}` : ""
48
- );
49
- }
50
- },
51
- warn(message, meta) {
52
- if (config?.debug) {
53
- console.warn(
54
- `${orange}[niledb]${reset}${yellow}[WARN]${reset}${params.join(
55
- ""
56
- )}${reset} ${message}`,
57
- meta ? JSON.stringify(meta) : ""
58
- );
59
- }
60
- },
61
- error(message, meta) {
62
- console.error(
63
- `${orange}[niledb]${reset}${red}[ERROR]${reset}${params.join(
64
- ""
65
- )}${red} ${message}`,
66
- meta ? meta : "",
67
- `${reset}`
68
- );
69
- }
40
+ // src/api/utils/routes/index.ts
41
+ var NILEDB_API_URL = process.env.NILEDB_API_URL;
42
+ var DEFAULT_PREFIX = "/api";
43
+ var appRoutes = (prefix = DEFAULT_PREFIX) => ({
44
+ SIGNIN: `${prefix}${"/auth/signin" /* SIGNIN */}`,
45
+ PROVIDERS: `${prefix}${"/auth/providers" /* PROVIDERS */}`,
46
+ SESSION: `${prefix}${"/auth/session" /* SESSION */}`,
47
+ CSRF: `${prefix}${"/auth/csrf" /* CSRF */}`,
48
+ CALLBACK: `${prefix}${"/auth/callback" /* CALLBACK */}`,
49
+ SIGNOUT: `${prefix}${"/auth/signout" /* SIGNOUT */}`,
50
+ ERROR: `${prefix}/auth/error`,
51
+ VERIFY_REQUEST: `${prefix}/auth/verify-request`,
52
+ VERIFY_EMAIL: `${prefix}${"/auth/verify-email" /* VERIFY_EMAIL */}`,
53
+ PASSWORD_RESET: `${prefix}${"/auth/reset-password" /* PASSWORD_RESET */}`,
54
+ ME: `${prefix}${"/me" /* ME */}`,
55
+ USERS: `${prefix}${"/users" /* USERS */}`,
56
+ USER_TENANTS: `${prefix}${"/users/{userId}/tenants" /* USER_TENANTS */}`,
57
+ TENANTS: `${prefix}${"/tenants" /* TENANTS */}`,
58
+ TENANT: `${prefix}${"/tenants/{tenantId}" /* TENANT */}`,
59
+ TENANT_USER: `${prefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */}`,
60
+ TENANT_USERS: `${prefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */}`,
61
+ SIGNUP: `${prefix}${"/signup" /* SIGNUP */}`,
62
+ INVITES: `${prefix}${"/tenants/{tenantId}/invites" /* INVITES */}`,
63
+ INVITE: `${prefix}${"/tenants/{tenantId}/invite" /* INVITE */}`,
64
+ LOG: `${prefix}/_log`
70
65
  });
71
- function Logger(config, ...params) {
72
- const base = baseLogger(config, params);
73
- const info = config?.logger?.info ?? base.info;
74
- const debug = config?.logger?.debug ?? base.debug;
75
- const warn = config?.logger?.warn ?? base.warn;
76
- const error = config?.logger?.error ?? base.error;
77
- return { info, warn, error, debug };
78
- }
79
- function matchesLog(configRoutes, request2) {
80
- return urlMatches(request2.url, configRoutes.LOG);
81
- }
82
-
83
- // src/utils/constants.ts
84
- var X_NILE_TENANT = "nile.tenant_id";
85
- var X_NILE_USER_ID = "nile.user_id";
86
- var X_NILE_ORIGIN = "nile.origin";
87
- var X_NILE_SECURECOOKIES = "nile.secure_cookies";
88
-
89
- // src/context/asyncStorage.ts
90
- var globalContext = null;
91
- function setContext(headers) {
92
- const origin = headers.get(X_NILE_ORIGIN);
93
- const host = headers.get("host");
94
- const cookie = headers.get("cookie");
95
- const tenantId = headers.get(X_NILE_TENANT);
96
- const userId = headers.get(X_NILE_USER_ID);
97
- const context = {};
98
- if (origin) {
99
- context.origin = origin;
100
- } else if (host) {
101
- context.origin = host;
102
- }
103
- if (cookie) {
104
- context.cookie = cookie;
105
- }
106
- if (tenantId) {
107
- context.tenantId = tenantId;
108
- }
109
- if (userId) {
110
- context.userId = userId;
66
+ var apiRoutes = (config) => ({
67
+ ME: makeRestUrl(config, "/me"),
68
+ USERS: (qp) => makeRestUrl(config, "/users", qp),
69
+ USER: (userId) => makeRestUrl(config, `/users/${userId}`),
70
+ TENANTS: makeRestUrl(config, "/tenants"),
71
+ TENANT: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}`),
72
+ SIGNUP: makeRestUrl(config, "/signup"),
73
+ TENANT_USERS: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/users`),
74
+ INVITES: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/invites`),
75
+ INVITE: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/invite`),
76
+ TENANT_USER: makeRestUrl(
77
+ config,
78
+ `/tenants/${config.tenantId}/users/${config.userId}`
79
+ ),
80
+ USER_TENANTS: (userId) => makeRestUrl(config, `/users/${userId}/tenants`)
81
+ });
82
+ var proxyRoutes = (config) => ({
83
+ SIGNIN: makeRestUrl(config, "/auth/signin" /* SIGNIN */),
84
+ PROVIDERS: makeRestUrl(config, "/auth/providers" /* PROVIDERS */),
85
+ SESSION: makeRestUrl(config, "/auth/session" /* SESSION */),
86
+ CSRF: makeRestUrl(config, "/auth/csrf" /* CSRF */),
87
+ CALLBACK: makeRestUrl(config, "/auth/callback" /* CALLBACK */),
88
+ SIGNOUT: makeRestUrl(config, "/auth/signout" /* SIGNOUT */),
89
+ ERROR: makeRestUrl(config, "/auth/error"),
90
+ VERIFY_REQUEST: makeRestUrl(config, "/auth/verify-request"),
91
+ PASSWORD_RESET: makeRestUrl(config, "/auth/reset-password" /* PASSWORD_RESET */),
92
+ VERIFY_EMAIL: makeRestUrl(config, "/auth/verify-email" /* VERIFY_EMAIL */)
93
+ });
94
+ function filterNullUndefined(obj) {
95
+ if (!obj) {
96
+ return void 0;
111
97
  }
112
- globalContext = context;
113
- }
114
- function getOrigin() {
115
- return globalContext?.origin;
116
- }
117
- function getCookie() {
118
- return globalContext?.cookie;
98
+ return Object.fromEntries(
99
+ Object.entries(obj).filter(
100
+ ([, value]) => value !== null && value !== void 0
101
+ )
102
+ );
119
103
  }
120
- function setCookie(headers) {
121
- const getSet = headers?.getSetCookie?.();
122
- if (getSet?.length) {
123
- const updatedCookie = [];
124
- for (const cook of getSet) {
125
- const [c] = cook.split("; ");
126
- const [, val] = c.split("=");
127
- if (val) {
128
- updatedCookie.push(c);
129
- }
130
- }
131
- const cookie = mergeCookies(updatedCookie);
132
- globalContext = { ...globalContext, cookie };
104
+ function makeRestUrl(config, path, qp) {
105
+ const url = config.apiUrl || NILEDB_API_URL;
106
+ if (!url) {
107
+ throw new Error(
108
+ "An API url is required. Set it via NILEDB_API_URL. Was auto configuration run?"
109
+ );
133
110
  }
111
+ const params = new URLSearchParams(
112
+ filterNullUndefined(qp)
113
+ );
114
+ const strParams = params.toString();
115
+ return `${[url, path.substring(1, path.length)].join("/")}${strParams ? `?${strParams}` : ""}`;
116
+ }
117
+ function urlMatches(requestUrl, route20) {
118
+ const url = new URL(requestUrl);
119
+ return url.pathname.startsWith(route20);
134
120
  }
135
- function mergeCookies(overrideArray) {
136
- const cookieString = getCookie();
137
- const cookieMap = {};
138
- if (!cookieString) {
139
- return overrideArray.join("; ");
121
+ function isUUID(value) {
122
+ if (!value) {
123
+ return false;
140
124
  }
141
- cookieString.split(";").forEach((cookie) => {
142
- const [rawKey, ...rawVal] = cookie.trim().split("=");
143
- const key12 = rawKey.trim();
144
- const value = rawVal.join("=").trim();
145
- if (key12) cookieMap[key12] = value;
146
- });
147
- overrideArray.forEach((cookie) => {
148
- const [rawKey, ...rawVal] = cookie.trim().split("=");
149
- const key12 = rawKey.trim();
150
- const value = rawVal.join("=").trim();
151
- if (key12) cookieMap[key12] = value;
152
- });
153
- return Object.entries(cookieMap).map(([k, v]) => `${k}=${v}`).join("; ");
125
+ 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}$/;
126
+ return regex.test(value);
154
127
  }
155
128
 
156
129
  // src/api/utils/request.ts
157
130
  async function request(url, _init, config) {
158
- const { debug, info, error } = Logger(config, "[REQUEST]");
131
+ const { debug, info, error } = config.logger("[REQUEST]");
159
132
  const { request: request2, ...init } = _init;
160
133
  const requestUrl = new URL(request2.url);
161
134
  const updatedHeaders = new Headers({});
162
135
  if (request2.headers.get("cookie")) {
163
136
  updatedHeaders.set("cookie", String(request2.headers.get("cookie")));
164
137
  }
165
- if (request2.headers.get(X_NILE_TENANT)) {
138
+ if (request2.headers.get(TENANT_COOKIE)) {
166
139
  updatedHeaders.set(
167
- X_NILE_TENANT,
168
- String(request2.headers.get(X_NILE_TENANT))
140
+ TENANT_COOKIE,
141
+ String(request2.headers.get(TENANT_COOKIE))
169
142
  );
170
143
  }
171
- if (config.api.secureCookies != null) {
172
- updatedHeaders.set(X_NILE_SECURECOOKIES, String(config.api.secureCookies));
144
+ if (config.secureCookies != null) {
145
+ updatedHeaders.set(HEADER_SECURE_COOKIES, String(config.secureCookies));
146
+ } else {
147
+ updatedHeaders.set(
148
+ HEADER_SECURE_COOKIES,
149
+ process.env.NODE_ENV === "production" ? "true" : "false"
150
+ );
173
151
  }
174
152
  updatedHeaders.set("host", requestUrl.host);
175
- if (config.api.callbackUrl) {
176
- const cbUrl = new URL(config.api.callbackUrl);
177
- debug(
178
- `Obtained origin from config.api.callbackUrl ${config.api.callbackUrl}`
179
- );
180
- updatedHeaders.set(X_NILE_ORIGIN, cbUrl.origin);
181
- } else if (config.api.origin) {
182
- debug(`Obtained origin from config.api.origin ${config.api.origin}`);
183
- updatedHeaders.set(X_NILE_ORIGIN, config.api.origin);
153
+ if (config.callbackUrl) {
154
+ const cbUrl = new URL(config.callbackUrl);
155
+ debug(`Obtained origin from config.callbackUrl ${config.callbackUrl}`);
156
+ updatedHeaders.set(HEADER_ORIGIN, cbUrl.origin);
157
+ } else if (config.origin) {
158
+ debug(`Obtained origin from config.origin ${config.origin}`);
159
+ updatedHeaders.set(HEADER_ORIGIN, config.origin);
184
160
  } else {
185
- updatedHeaders.set(X_NILE_ORIGIN, requestUrl.origin);
186
- debug(`Obtained origin from request ${requestUrl.origin}`);
161
+ const passedOrigin = request2.headers.get(HEADER_ORIGIN);
162
+ if (passedOrigin) {
163
+ updatedHeaders.set(HEADER_ORIGIN, passedOrigin);
164
+ } else {
165
+ const reqOrigin = config.routePrefix !== DEFAULT_PREFIX ? `${requestUrl.origin}${config.routePrefix}` : requestUrl.origin;
166
+ updatedHeaders.set(HEADER_ORIGIN, reqOrigin);
167
+ debug(`Obtained origin from request ${reqOrigin}`);
168
+ }
187
169
  }
188
- const params = { ...init, headers: updatedHeaders };
170
+ const params = { ...init };
189
171
  if (params.method?.toLowerCase() === "post" || params.method?.toLowerCase() === "put") {
190
172
  try {
191
173
  updatedHeaders.set("content-type", "application/json");
192
- const initBody = await new Response(_init.request.clone().body).json();
193
- const requestBody = await new Response(request2.clone().body).json();
194
- params.body = JSON.stringify(initBody ?? requestBody);
174
+ const bodyStream = _init.body ?? _init.request?.body ?? request2.body;
175
+ const bodyText = await new Response(bodyStream).text();
176
+ try {
177
+ params.body = JSON.stringify(JSON.parse(bodyText));
178
+ } catch {
179
+ updatedHeaders.set("content-type", "application/x-www-form-urlencoded");
180
+ params.body = bodyText;
181
+ }
195
182
  } catch (e) {
196
- updatedHeaders.set("content-type", "application/x-www-form-urlencoded");
197
- const initBody = await new Response(_init.request.clone().body).text();
198
- const requestBody = await new Response(request2.clone().body).text();
199
- params.body = initBody ?? requestBody;
183
+ error("Failed to parse request body");
200
184
  }
201
185
  }
186
+ params.headers = updatedHeaders;
202
187
  const fullUrl = `${url}${requestUrl.search}`;
188
+ if (config.debug) {
189
+ params.headers.set("request-id", crypto.randomUUID());
190
+ params.cache = "no-store";
191
+ }
192
+ await config.extensionCtx?.handleOnRequest(config, _init, params);
203
193
  try {
204
- setContext(updatedHeaders);
205
- const res = await fetch(fullUrl, { ...params }).catch(
206
- (e) => {
207
- error("An error has occurred in the fetch", {
208
- message: e.message,
209
- stack: e.stack
210
- });
211
- return new Response(
212
- "An unexpected (most likely configuration) problem has occurred",
213
- { status: 500 }
214
- );
215
- }
216
- );
194
+ const res = await fetch(fullUrl, {
195
+ ...params
196
+ }).catch((e) => {
197
+ error("An error has occurred in the fetch", {
198
+ message: e.message,
199
+ stack: e.stack
200
+ });
201
+ return new Response(
202
+ "An unexpected (most likely configuration) problem has occurred",
203
+ { status: 500 }
204
+ );
205
+ });
217
206
  const loggingRes = typeof res?.clone === "function" ? res?.clone() : null;
218
207
  info(`[${params.method ?? "GET"}] ${fullUrl}`, {
219
208
  status: res?.status,
220
209
  statusText: res?.statusText,
221
210
  text: await loggingRes?.text()
222
211
  });
223
- setCookie(res?.headers);
224
212
  return res;
225
213
  } catch (e) {
226
214
  if (e instanceof Error) {
@@ -238,10 +226,10 @@ async function request(url, _init, config) {
238
226
 
239
227
  // src/api/utils/auth.ts
240
228
  async function auth(req, config) {
241
- const { info, error } = Logger(config, "[nileauth]");
229
+ const { info, error } = config.logger("[nileauth]");
242
230
  info("checking auth");
243
- const sessionUrl = `${config.api.basePath}/auth/session`;
244
- info(`using session${sessionUrl}`);
231
+ const sessionUrl = `${config.apiUrl}/auth/session`;
232
+ info(`using session ${sessionUrl}`);
245
233
  req.headers.delete("content-length");
246
234
  const res = await request(sessionUrl, { request: req }, config);
247
235
  if (!res) {
@@ -260,1009 +248,368 @@ async function auth(req, config) {
260
248
  return void 0;
261
249
  }
262
250
  }
263
- var getCallbackUrl = (cfg) => {
264
- const { config } = cfg;
265
- if (stringCheck(config?.api?.callbackUrl)) {
266
- return config?.api?.callbackUrl;
267
- }
268
- return process.env.NILEDB_CALLBACK_URL;
269
- };
270
- var getSecureCookies = (cfg) => {
271
- const { config } = cfg;
272
- if (config?.api?.secureCookies != null) {
273
- return config?.api?.secureCookies;
251
+
252
+ // src/api/routes/me/index.ts
253
+ var key = "ME";
254
+ async function route(request2, config) {
255
+ const url = apiRoutes(config)[key];
256
+ if (request2.method === "GET") {
257
+ return await GET(url, { request: request2 }, config);
274
258
  }
275
- if (stringCheck(process.env.NILEDB_SECURECOOKIES)) {
276
- return Boolean(process.env.NILEDB_SECURECOOKIES);
259
+ if (request2.method === "PUT") {
260
+ return await PUT(url, { request: request2 }, config);
277
261
  }
278
- return void 0;
279
- };
280
- var getDatabaseId = (cfg) => {
281
- const { config, logger } = cfg;
282
- const { info } = Logger(config, "[databaseId]");
283
- if (stringCheck(config?.databaseId)) {
284
- logger && info(`${logger}[config] ${config?.databaseId}`);
285
- return String(config?.databaseId);
286
- }
287
- const dbFromEnv = stringCheck(process.env.NILEDB_ID);
288
- if (dbFromEnv) {
289
- logger && info(`${logger}[NILEDB_ID] ${dbFromEnv}`);
290
- return dbFromEnv;
291
- }
292
- const dbId = stringCheck(process.env.NILEDB_API_URL);
293
- if (dbId) {
294
- try {
295
- const pgUrl = new URL(dbId);
296
- return pgUrl.pathname.split("/")[3];
297
- } catch (e) {
262
+ if (request2.method === "DELETE") {
263
+ const session = await auth(request2, config);
264
+ if (!session) {
265
+ return new Response(null, { status: 401 });
298
266
  }
267
+ return await DELETE(url, { request: request2 }, config);
299
268
  }
300
- return null;
301
- };
302
- var getUsername = (cfg) => {
303
- const { config, logger } = cfg;
304
- const { info } = Logger(config, "[username]");
305
- if (config?.user) {
306
- logger && info(`${logger}[config] ${config.user}`);
307
- return String(config?.user);
308
- }
309
- const user = stringCheck(process.env.NILEDB_USER);
310
- if (user) {
311
- logger && info(`${logger}[NILEDB_USER] ${user}`);
312
- return user;
313
- }
314
- const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
315
- if (pg2) {
316
- try {
317
- const url = new URL(pg2);
318
- if (url.username) {
319
- return url.username;
320
- }
321
- } catch (e) {
322
- }
269
+ return new Response("method not allowed", { status: 405 });
270
+ }
271
+ function matches(configRoutes, request2) {
272
+ return urlMatches(request2.url, configRoutes[key]);
273
+ }
274
+ async function fetchMe(config, method, body) {
275
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/me" /* ME */}`;
276
+ const init = {
277
+ headers: config.headers,
278
+ method: method ?? "GET"
279
+ };
280
+ if (method === "PUT") {
281
+ init.body = body;
323
282
  }
324
- return void 0;
325
- };
326
- var getPassword = (cfg) => {
327
- const { config, logger } = cfg;
328
- const log = logProtector(logger);
329
- const { info } = Logger(config, "[password]");
330
- if (stringCheck(config?.password)) {
331
- log && info(`${logger}[config] ***`);
332
- return String(config?.password);
283
+ const req = new Request(clientUrl, init);
284
+ if (method === "DELETE") {
285
+ return await config.handlers.DELETE(req);
333
286
  }
334
- const pass = stringCheck(process.env.NILEDB_PASSWORD);
335
- if (pass) {
336
- logger && info(`${logger}[NILEDB_PASSWORD] ***`);
337
- return pass;
287
+ if (method === "PUT") {
288
+ return await config.handlers.PUT(req);
338
289
  }
339
- const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
340
- if (pg2) {
341
- try {
342
- const url = new URL(pg2);
343
- if (url.password) {
344
- return url.password;
345
- }
346
- } catch (e) {
290
+ return await config.handlers.GET(req);
291
+ }
292
+ async function DELETE(url, init, config) {
293
+ init.method = "DELETE";
294
+ return await request(url, init, config);
295
+ }
296
+ async function PUT(url, init, config) {
297
+ init.method = "PUT";
298
+ return await request(url, init, config);
299
+ }
300
+ async function GET(url, init, config) {
301
+ const res = await request(url, init, config);
302
+ return res;
303
+ }
304
+
305
+ // src/utils/fetch.ts
306
+ function getTokenFromCookie(headers, cookieKey) {
307
+ const cookie = headers.get("cookie")?.split("; ");
308
+ const _cookies = {};
309
+ if (cookie) {
310
+ for (const parts of cookie) {
311
+ const cookieParts = parts.split("=");
312
+ const _cookie = cookieParts.slice(1).join("=");
313
+ const name = cookieParts[0];
314
+ _cookies[name] = _cookie;
347
315
  }
348
316
  }
349
- return void 0;
350
- };
351
- var getToken = (cfg) => {
352
- const { config, logger } = cfg;
353
- const { info } = Logger(config, "[token]");
354
- if (stringCheck(config?.api?.token)) {
355
- logger && info(`${logger}[config] ${config?.api?.token}`);
356
- return String(config?.api?.token);
357
- }
358
- const token = stringCheck(process.env.NILEDB_TOKEN);
359
- if (token) {
360
- logger && info(`${logger}[NILEDB_TOKEN] ${token}`);
361
- return token;
362
- }
363
- return void 0;
364
- };
365
- var getDatabaseName = (cfg) => {
366
- const { config, logger } = cfg;
367
- const { info } = Logger(config, "[databaseName]");
368
- if (stringCheck(config?.databaseName)) {
369
- logger && info(`${logger}[config] ${config?.databaseName}`);
370
- return String(config?.databaseName);
371
- }
372
- const name = stringCheck(process.env.NILEDB_NAME);
373
- if (name) {
374
- logger && info(`${logger}[NILEDB_NAME] ${name}`);
375
- return name;
376
- }
377
- if (process.env.NILEDB_POSTGRES_URL) {
378
- try {
379
- const pgUrl = new URL(process.env.NILEDB_POSTGRES_URL);
380
- return pgUrl.pathname.substring(1);
381
- } catch (e) {
317
+ if (cookie) {
318
+ for (const parts of cookie) {
319
+ const cookieParts = parts.split("=");
320
+ const _cookie = cookieParts.slice(1).join("=");
321
+ const name = cookieParts[0];
322
+ _cookies[name] = _cookie;
382
323
  }
383
324
  }
384
- return null;
385
- };
386
- var getTenantId = (cfg) => {
387
- const { config, logger } = cfg;
388
- const { info } = Logger(config, "[tenantId]");
389
- if (stringCheck(config?.tenantId)) {
390
- logger && info(`${logger}[config] ${config?.tenantId}`);
391
- return String(config?.tenantId);
392
- }
393
- if (stringCheck(process.env.NILEDB_TENANT)) {
394
- logger && info(`${logger}[NILEDB_TENANT] ${process.env.NILEDB_TENANT}`);
395
- return String(process.env.NILEDB_TENANT);
396
- }
397
- return null;
398
- };
399
- var getCookieKey = (cfg) => {
400
- const { config, logger } = cfg;
401
- const { info } = Logger(config, "[cookieKey]");
402
- if (stringCheck(config?.api?.cookieKey)) {
403
- logger && info(`${logger}[config] ${config?.api?.cookieKey}`);
404
- return String(config?.api?.cookieKey);
405
- }
406
- if (stringCheck(process.env.NILEDB_COOKIE_KEY)) {
407
- logger && info(`${logger}[NILEDB_COOKIE_KEY] ${process.env.NILEDB_COOKIE_KEY}`);
408
- return String(process.env.NILEDB_COOKIE_KEY);
409
- }
410
- return "token";
411
- };
412
- var getBasePath = (cfg) => {
413
- const { config, logger } = cfg;
414
- const { warn, info, error } = Logger(config, "[basePath]");
415
- const basePath = config?.api?.basePath;
416
- if (stringCheck(basePath)) {
417
- logger && info(`${logger}[config] ${basePath}`);
418
- return basePath;
419
- }
420
- const envUrl = stringCheck(process.env.NILEDB_API_URL);
421
- if (envUrl) {
422
- logger && info(`${logger}[NILEDB_API_URL] ${process.env.NILEDB_API_URL}`);
423
- try {
424
- const apiUrl = new URL(envUrl);
425
- return apiUrl.href;
426
- } catch (e) {
427
- if (e instanceof Error) {
428
- error(e.stack);
429
- }
430
- }
325
+ {
326
+ return _cookies[cookieKey];
431
327
  }
432
- warn("not set. Must run auto-configuration");
433
- return void 0;
434
- };
435
- function getDbHost(cfg) {
436
- const { config, logger } = cfg;
437
- const { info } = Logger(config, "[db.host]");
438
- if (stringCheck(config?.db && config.db.host)) {
439
- logger && info(`${logger}[config] ${config?.db?.host}`);
440
- return String(config?.db?.host);
441
- }
442
- if (stringCheck(process.env.NILEDB_HOST)) {
443
- logger && info(`${logger}[NILEDB_HOST] ${process.env.NILEDB_HOST}`);
444
- return process.env.NILEDB_HOST;
328
+ }
329
+ function getTenantFromHttp(headers, config) {
330
+ const cookieTenant = getTokenFromCookie(headers, TENANT_COOKIE);
331
+ return cookieTenant ? cookieTenant : config?.tenantId;
332
+ }
333
+
334
+ // src/api/routes/users/POST.ts
335
+ async function POST(config, init) {
336
+ init.body = init.request.body;
337
+ init.method = "POST";
338
+ const yurl = new URL(init.request.url);
339
+ const tenantId = yurl.searchParams.get("tenantId");
340
+ const newTenantName = yurl.searchParams.get("newTenantName");
341
+ const tenant = tenantId ?? getTenantFromHttp(init.request.headers, config);
342
+ const url = apiRoutes(config).USERS({ tenantId: tenant, newTenantName });
343
+ return await request(url, init, config);
344
+ }
345
+
346
+ // src/api/routes/users/GET.ts
347
+ async function GET2(config, init, log) {
348
+ const yurl = new URL(init.request.url);
349
+ const tenantId = yurl.searchParams.get("tenantId");
350
+ const tenant = tenantId ?? getTenantFromHttp(init.request.headers, config);
351
+ if (!tenant) {
352
+ log("[GET] No tenant id provided.");
353
+ return new Response(null, { status: 404 });
445
354
  }
446
- const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
447
- if (pg2) {
448
- try {
449
- const pgUrl = new URL(pg2);
450
- logger && info(`${logger}[NILEDB_POSTGRES_URL] ${pgUrl.hostname}`);
451
- return pgUrl.hostname;
452
- } catch (e) {
453
- }
355
+ init.method = "GET";
356
+ const url = apiRoutes(config).TENANT_USERS(tenant);
357
+ return await request(url, init, config);
358
+ }
359
+
360
+ // src/api/routes/users/[userId]/PUT.ts
361
+ async function PUT2(config, init) {
362
+ init.body = init.request.body;
363
+ init.method = "PUT";
364
+ const [userId] = new URL(init.request.url).pathname.split("/").reverse();
365
+ const url = apiRoutes(config).USER(userId);
366
+ return await request(url, init, config);
367
+ }
368
+
369
+ // src/api/routes/users/index.ts
370
+ var key2 = "USERS";
371
+ async function route2(request2, config) {
372
+ const { info } = config.logger(`[ROUTES][${key2}]`);
373
+ switch (request2.method) {
374
+ case "GET":
375
+ return await GET2(config, { request: request2 }, info);
376
+ case "POST":
377
+ return await POST(config, { request: request2 });
378
+ case "PUT":
379
+ return await PUT2(config, { request: request2 });
380
+ default:
381
+ return new Response("method not allowed", { status: 405 });
454
382
  }
455
- logger && info(`${logger}[default] db.thenile.dev`);
456
- return "db.thenile.dev";
457
383
  }
458
- function getDbPort(cfg) {
459
- const { config, logger } = cfg;
460
- const { info } = Logger(config, "[db.port]");
461
- if (config?.db?.port && config.db.port != null) {
462
- logger && info(`${logger}[config] ${config?.db.port}`);
463
- return Number(config.db?.port);
384
+ function matches2(configRoutes, request2) {
385
+ return urlMatches(request2.url, configRoutes[key2]);
386
+ }
387
+
388
+ // src/api/routes/tenants/[tenantId]/users/GET.ts
389
+ async function GET3(config, init) {
390
+ const yurl = new URL(init.request.url);
391
+ const [, tenantId] = yurl.pathname.split("/").reverse();
392
+ const url = `${apiRoutes(config).TENANT_USERS(tenantId)}`;
393
+ return await request(url, init, config);
394
+ }
395
+
396
+ // src/api/routes/tenants/[tenantId]/users/POST.ts
397
+ async function POST2(config, init) {
398
+ const session = await auth(init.request, config);
399
+ if (!session) {
400
+ return new Response(null, { status: 401 });
464
401
  }
465
- if (stringCheck(process.env.NILEDB_PORT)) {
466
- logger && info(`${logger}[NILEDB_PORT] ${process.env.NILEDB_PORT}`);
467
- return Number(process.env.NILEDB_PORT);
402
+ const yurl = new URL(init.request.url);
403
+ const [, tenantId] = yurl.pathname.split("/").reverse();
404
+ init.body = JSON.stringify({ email: session.email });
405
+ init.method = "POST";
406
+ const url = apiRoutes(config).TENANT_USERS(tenantId);
407
+ return await request(url, init, config);
408
+ }
409
+
410
+ // src/api/routes/tenants/[tenantId]/users/index.ts
411
+ var key3 = "TENANT_USERS";
412
+ async function route3(request2, config) {
413
+ const { info } = config.logger(`[ROUTES][${key3}]`);
414
+ const yurl = new URL(request2.url);
415
+ const [, tenantId] = yurl.pathname.split("/").reverse();
416
+ if (!tenantId) {
417
+ info("No tenant id found in path");
418
+ return new Response(null, { status: 404 });
468
419
  }
469
- const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
470
- if (pg2) {
471
- try {
472
- const pgUrl = new URL(pg2);
473
- if (pgUrl.port) {
474
- return Number(pgUrl.port);
475
- }
476
- } catch (e) {
477
- }
420
+ switch (request2.method) {
421
+ case "GET":
422
+ return await GET3(config, { request: request2 });
423
+ case "POST":
424
+ return await POST2(config, { request: request2 });
425
+ default:
426
+ return new Response("method not allowed", { status: 405 });
478
427
  }
479
- logger && info(`${logger}[default] 5432`);
480
- return 5432;
481
428
  }
482
- var logProtector = (logger) => {
483
- return process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test" ? logger : null;
484
- };
485
- var stringCheck = (str) => {
486
- if (str && str !== "") {
487
- return str;
429
+ function matches3(configRoutes, request2) {
430
+ const url = new URL(request2.url);
431
+ const [userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
432
+ let route20 = configRoutes[key3].replace("{tenantId}", tenantId).replace("{userId}", userId);
433
+ if (userId === "users") {
434
+ route20 = configRoutes[key3].replace("{tenantId}", possibleTenantId);
488
435
  }
489
- return;
490
- };
491
-
492
- // src/utils/Config/index.ts
493
- var ApiConfig = class {
494
- cookieKey;
495
- basePath;
496
- routes;
497
- routePrefix;
498
- secureCookies;
499
- origin;
500
- /**
501
- * The client side callback url. Defaults to nothing (so nile.origin will be it), but in the cases of x-origin, you want to set this explicitly to be sure nile-auth does the right thing
502
- * If this is set, any `callbackUrl` from the client will be ignored.
503
- */
504
- callbackUrl;
505
- #token;
506
- constructor(config, logger) {
507
- const envVarConfig = { config, logger };
508
- this.cookieKey = getCookieKey(envVarConfig);
509
- this.#token = getToken(envVarConfig);
510
- this.callbackUrl = getCallbackUrl(envVarConfig);
511
- this.secureCookies = getSecureCookies(envVarConfig);
512
- this.basePath = getBasePath(envVarConfig);
513
- this.routes = config?.api?.routes;
514
- this.routePrefix = config?.api?.routePrefix;
515
- this.origin = config?.api?.origin;
436
+ return urlMatches(request2.url, route20);
437
+ }
438
+ async function fetchTenantUsers(config, method, payload) {
439
+ const { body, params } = {};
440
+ if (!config.tenantId) {
441
+ throw new Error(
442
+ "Unable to fetch the user's tenants, the tenantId context is missing. Call nile.setContext({ tenantId })"
443
+ );
516
444
  }
517
- get token() {
518
- return this.#token;
445
+ if (!isUUID(config.tenantId)) {
446
+ config.logger("fetchTenantUsers").warn(
447
+ "nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
448
+ );
519
449
  }
520
- set token(value) {
521
- this.#token = value;
450
+ const q = new URLSearchParams();
451
+ if (params?.newTenantName) {
452
+ q.set("newTenantName", params.newTenantName);
522
453
  }
523
- };
524
- var Config = class {
525
- user;
526
- password;
527
- databaseId;
528
- databaseName;
529
- logger;
530
- debug;
531
- db;
532
- api;
533
- #tenantId;
534
- #userId;
535
- get tenantId() {
536
- return this.#tenantId;
537
- }
538
- set tenantId(value) {
539
- this.#tenantId = value;
540
- }
541
- get userId() {
542
- return this.#userId;
543
- }
544
- set userId(value) {
545
- this.#userId = value;
546
- }
547
- constructor(config, logger) {
548
- const envVarConfig = { config, logger };
549
- this.user = getUsername(envVarConfig);
550
- this.logger = config?.logger;
551
- this.password = getPassword(envVarConfig);
552
- if (process.env.NODE_ENV !== "TEST") {
553
- if (!this.user) {
554
- throw new Error(
555
- "User is required. Set NILEDB_USER as an environment variable or set `user` in the config options."
556
- );
557
- }
558
- if (!this.password) {
559
- throw new Error(
560
- "Password is required. Set NILEDB_PASSWORD as an environment variable or set `password` in the config options."
561
- );
562
- }
563
- }
564
- this.databaseId = getDatabaseId(envVarConfig);
565
- this.databaseName = getDatabaseName(envVarConfig);
566
- this.#tenantId = getTenantId(envVarConfig);
567
- this.debug = Boolean(config?.debug);
568
- this.#userId = config?.userId;
569
- const { host, port, ...dbConfig } = config?.db ?? {};
570
- const configuredHost = host ?? getDbHost(envVarConfig);
571
- const configuredPort = port ?? getDbPort(envVarConfig);
572
- this.api = new ApiConfig(config, logger);
573
- this.db = {
574
- user: this.user,
575
- password: this.password,
576
- host: configuredHost,
577
- port: configuredPort,
578
- ...dbConfig
579
- };
580
- if (this.databaseName) {
581
- this.db.database = this.databaseName;
582
- }
454
+ if (params?.tenantId) {
455
+ q.set("tenantId", params.tenantId);
583
456
  }
584
- };
457
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */.replace(
458
+ "{tenantId}",
459
+ config.tenantId
460
+ )}`;
461
+ const m = method;
462
+ const init = {
463
+ method: m,
464
+ headers: config.headers
465
+ };
466
+ const req = new Request(clientUrl, init);
467
+ return await config.handlers[m](req);
468
+ }
585
469
 
586
- // src/utils/Event/index.ts
587
- var Eventer = class {
588
- events = {};
589
- // Publish event and notify all subscribers
590
- publish(eventName, value) {
591
- const callbackList = this.events[eventName];
592
- if (callbackList) {
593
- for (const callback of callbackList) {
594
- callback(value);
595
- }
596
- }
470
+ // src/api/routes/tenants/[tenantId]/invite/PUT.ts
471
+ async function PUT3(config, init) {
472
+ const yurl = new URL(init.request.url);
473
+ const [, tenantId] = yurl.pathname.split("/").reverse();
474
+ if (!tenantId) {
475
+ return new Response(null, { status: 404 });
597
476
  }
598
- // Subscribe to events
599
- subscribe(eventName, callback) {
600
- if (!this.events[eventName]) {
601
- this.events[eventName] = [];
602
- }
603
- this.events[eventName].push(callback);
477
+ if (yurl.searchParams.size > 0) {
478
+ init.body = new URLSearchParams(yurl.searchParams).toString();
604
479
  }
605
- // Unsubscribe from an event
606
- unsubscribe(eventName, callback) {
607
- const callbackList = this.events[eventName];
608
- if (!callbackList) {
609
- return;
610
- }
611
- const index = callbackList.indexOf(callback);
612
- if (index !== -1) {
613
- callbackList.splice(index, 1);
614
- }
615
- if (callbackList.length === 0) {
616
- delete this.events[eventName];
617
- }
480
+ init.method = "PUT";
481
+ const url = `${apiRoutes(config).INVITE(tenantId)}`;
482
+ const res = await request(url, init, config);
483
+ const location = res?.headers.get("location");
484
+ if (location) {
485
+ return new Response(res?.body, {
486
+ status: 302,
487
+ headers: res?.headers
488
+ });
618
489
  }
619
- };
620
- var eventer = new Eventer();
621
- var updateTenantId = (tenantId) => {
622
- eventer.publish("tenantId" /* Tenant */, tenantId);
623
- };
624
- var watchTenantId = (cb) => eventer.subscribe("tenantId" /* Tenant */, cb);
625
- var updateUserId = (userId) => {
626
- eventer.publish("userId" /* User */, userId);
627
- };
628
- var watchUserId = (cb) => eventer.subscribe("userId" /* User */, cb);
629
- var watchToken = (cb) => eventer.subscribe("token" /* Token */, cb);
630
- var watchEvictPool = (cb) => eventer.subscribe("EvictPool" /* EvictPool */, cb);
631
- var evictPool = (val) => {
632
- eventer.publish("EvictPool" /* EvictPool */, val);
633
- };
634
-
635
- // src/db/PoolProxy.ts
636
- function createProxyForPool(pool, config) {
637
- const { info, error } = Logger(config, "[pool]");
638
- return new Proxy(pool, {
639
- get(target, property) {
640
- if (property === "query") {
641
- if (!config.db.connectionString) {
642
- if (!config.user || !config.password) {
643
- error(
644
- "Cannot connect to the database. User and/or password are missing. Generate them at https://console.thenile.dev"
645
- );
646
- } else if (!config.db.database) {
647
- error(
648
- "Database name is missing from the config. Call `nile.init()` or set NILEDB_ID in your .env"
649
- );
650
- }
651
- }
652
- const caller = target[property];
653
- return function query(...args) {
654
- info("query", ...args);
655
- const called = caller.apply(this, args);
656
- return called;
657
- };
658
- }
659
- return target[property];
660
- }
490
+ return new Response(res?.body, {
491
+ status: res?.status,
492
+ headers: res?.headers
661
493
  });
662
494
  }
663
495
 
664
- // src/db/NileInstance.ts
665
- var NileDatabase = class {
666
- pool;
667
- tenantId;
668
- userId;
669
- id;
670
- config;
671
- timer;
672
- constructor(config, id) {
673
- const { warn, info, debug } = Logger(config, "[NileInstance]");
674
- this.id = id;
675
- const poolConfig = {
676
- min: 0,
677
- max: 10,
678
- idleTimeoutMillis: 3e4,
679
- ...config.db
680
- };
681
- const { afterCreate, ...remaining } = poolConfig;
682
- config.db = poolConfig;
683
- this.config = config;
684
- const cloned = { ...this.config.db };
685
- cloned.password = "***";
686
- debug(`Connection pool config ${JSON.stringify(cloned)}`);
687
- this.pool = createProxyForPool(new pg__default.default.Pool(remaining), this.config);
688
- if (typeof afterCreate === "function") {
689
- warn(
690
- "Providing an pool configuration will stop automatic tenant context setting."
691
- );
692
- }
693
- this.startTimeout();
694
- this.pool.on("connect", async (client) => {
695
- debug(`pool connected ${this.id}`);
696
- this.startTimeout();
697
- const afterCreate2 = makeAfterCreate(
698
- config,
699
- `${this.id}-${this.timer}`
700
- );
701
- afterCreate2(client, (err) => {
702
- const { error } = Logger(config, "[after create callback]");
703
- if (err) {
704
- clearTimeout(this.timer);
705
- error("after create failed", {
706
- message: err.message,
707
- stack: err.stack
708
- });
709
- evictPool(this.id);
710
- }
711
- });
712
- });
713
- this.pool.on("error", (err) => {
714
- clearTimeout(this.timer);
715
- info(`pool ${this.id} failed`, {
716
- message: err.message,
717
- stack: err.stack
718
- });
719
- evictPool(this.id);
720
- });
721
- this.pool.on("release", (destroy) => {
722
- if (destroy) {
723
- clearTimeout(this.timer);
724
- evictPool(this.id);
725
- debug(`destroying pool ${this.id}`);
726
- }
727
- });
728
- }
729
- startTimeout() {
730
- const { debug } = Logger(this.config, "[NileInstance]");
731
- if (this.timer) {
732
- clearTimeout(this.timer);
733
- }
734
- this.timer = setTimeout(() => {
735
- debug(
736
- `Pool reached idleTimeoutMillis. ${this.id} evicted after ${Number(this.config.db.idleTimeoutMillis) ?? 3e4}ms`
737
- );
738
- this.pool.end(() => {
739
- clearTimeout(this.timer);
740
- evictPool(this.id);
741
- });
742
- }, Number(this.config.db.idleTimeoutMillis) ?? 3e4);
743
- }
744
- shutdown() {
745
- const { debug } = Logger(this.config, "[NileInstance]");
746
- debug(`attempting to shut down ${this.id}`);
747
- clearTimeout(this.timer);
748
- this.pool.end(() => {
749
- debug(`${this.id} has been shut down`);
750
- });
496
+ // src/api/routes/tenants/[tenantId]/invite/POST.ts
497
+ async function POST3(config, init) {
498
+ const yurl = new URL(init.request.url);
499
+ const [, tenantId] = yurl.pathname.split("/").reverse();
500
+ if (!tenantId) {
501
+ return new Response(null, { status: 404 });
751
502
  }
752
- };
753
- var NileInstance_default = NileDatabase;
754
- function makeAfterCreate(config, id) {
755
- const { error, warn, debug } = Logger(config, "[afterCreate]");
756
- return (conn, done) => {
757
- conn.on("error", function errorHandler(e) {
758
- error(`Connection ${id} was terminated by server`, {
759
- message: e.message,
760
- stack: e.stack
761
- });
762
- done(e, conn);
763
- });
764
- if (config.tenantId) {
765
- const query = [`SET nile.tenant_id = '${config.tenantId}'`];
766
- if (config.userId) {
767
- if (!config.tenantId) {
768
- warn("A user id cannot be set in context without a tenant id");
769
- }
770
- query.push(`SET nile.user_id = '${config.userId}'`);
771
- }
772
- conn.query(query.join(";"), function(err) {
773
- if (err) {
774
- error("query connection failed", {
775
- cause: err.cause,
776
- stack: err.stack,
777
- message: err.message,
778
- name: err.name,
779
- id
780
- });
781
- } else {
782
- if (query.length === 1) {
783
- debug(`connection context set: tenantId=${config.tenantId}`);
784
- }
785
- if (query.length === 2) {
786
- debug(
787
- `connection context set: tenantId=${config.tenantId} userId=${config.userId}`
788
- );
789
- }
790
- }
791
- done(err, conn);
792
- });
793
- }
794
- done(null, conn);
795
- };
503
+ init.method = "POST";
504
+ init.body = init.request.body;
505
+ const url = `${apiRoutes(config).INVITE(tenantId)}`;
506
+ return await request(url, init, config);
796
507
  }
797
508
 
798
- // src/db/DBManager.ts
799
- var DBManager = class {
800
- connections;
801
- cleared;
802
- poolWatcherFn;
803
- makeId(tenantId, userId) {
804
- if (tenantId && userId) {
805
- return `${tenantId}:${userId}`;
806
- }
807
- if (tenantId) {
808
- return `${tenantId}`;
809
- }
810
- return "base";
811
- }
812
- constructor(config) {
813
- this.cleared = false;
814
- this.connections = /* @__PURE__ */ new Map();
815
- this.poolWatcherFn = this.poolWatcher(config);
816
- watchEvictPool(this.poolWatcherFn);
817
- }
818
- poolWatcher = (config) => (id) => {
819
- const { info, warn } = Logger(config, "[DBManager]");
820
- if (id && this.connections.has(id)) {
821
- info(`Removing ${id} from db connection pool.`);
822
- const connection = this.connections.get(id);
823
- connection?.shutdown();
824
- this.connections.delete(id);
825
- } else {
826
- warn(`missed eviction of ${id}`);
827
- }
828
- };
829
- getConnection = (config) => {
830
- const { info } = Logger(config, "[DBManager]");
831
- const id = this.makeId(config.tenantId, config.userId);
832
- const existing = this.connections.get(id);
833
- info(`# of instances: ${this.connections.size}`);
834
- if (existing) {
835
- info(`returning existing ${id}`);
836
- existing.startTimeout();
837
- return existing.pool;
838
- }
839
- const newOne = new NileInstance_default(new Config(config), id);
840
- this.connections.set(id, newOne);
841
- info(`created new ${id}`);
842
- info(`# of instances: ${this.connections.size}`);
843
- if (this.cleared) {
844
- this.cleared = false;
845
- }
846
- return newOne.pool;
847
- };
848
- clear = (config) => {
849
- const { info } = Logger(config, "[DBManager]");
850
- info(`Clearing all connections ${this.connections.size}`);
851
- this.cleared = true;
852
- this.connections.forEach((connection) => {
853
- connection.shutdown();
854
- });
855
- this.connections.clear();
856
- };
857
- };
858
-
859
- // src/api/utils/routes/makeRestUrl.ts
860
- var NILEDB_API_URL = process.env.NILEDB_API_URL;
861
- function filterNullUndefined(obj) {
862
- if (!obj) {
863
- return void 0;
509
+ // src/api/routes/tenants/[tenantId]/invite/index.ts
510
+ var key4 = "INVITE";
511
+ async function route4(request2, config) {
512
+ switch (request2.method) {
513
+ // the browser is a GET, but we need to PUT it into nile-auth
514
+ // server side, this is a put
515
+ case "GET":
516
+ case "PUT":
517
+ return await PUT3(config, { request: request2 });
518
+ case "POST":
519
+ return await POST3(config, { request: request2 });
520
+ default:
521
+ return new Response("method not allowed", { status: 405 });
864
522
  }
865
- return Object.fromEntries(
866
- Object.entries(obj).filter(
867
- ([, value]) => value !== null && value !== void 0
868
- )
869
- );
870
523
  }
871
- function makeRestUrl(config, path, qp) {
872
- const url = config.api.basePath || NILEDB_API_URL;
873
- if (!url) {
524
+ function matches4(configRoutes, request2) {
525
+ const url = new URL(request2.url);
526
+ const [, tenantId] = url.pathname.split("/").reverse();
527
+ const route20 = configRoutes[key4].replace("{tenantId}", tenantId);
528
+ return urlMatches(request2.url, route20);
529
+ }
530
+ async function fetchInvite(config, method, body) {
531
+ if (!config.tenantId) {
874
532
  throw new Error(
875
- "An API url is required. Set it via NILEDB_API_URL. Was auto configuration run?"
533
+ "Unable to fetch the invite for the tenant, the tenantId context is missing. Call nile.setContext({ tenantId })"
876
534
  );
877
535
  }
878
- const params = new URLSearchParams(
879
- filterNullUndefined(qp)
880
- );
881
- const strParams = params.toString();
882
- return `${[url, path.substring(1, path.length)].join("/")}${strParams ? `?${strParams}` : ""}`;
536
+ if (!isUUID(config.tenantId)) {
537
+ config.logger("fetchInvite").warn(
538
+ "nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
539
+ );
540
+ }
541
+ let clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/invite" /* INVITE */.replace("{tenantId}", config.tenantId)}`;
542
+ const m = method ?? "GET";
543
+ const init = {
544
+ method: m,
545
+ headers: config.headers
546
+ };
547
+ if (method === "POST" || method === "PUT") {
548
+ init.body = body;
549
+ }
550
+ if (method === "DELETE") {
551
+ clientUrl = `${clientUrl}/${body}`;
552
+ }
553
+ const req = new Request(clientUrl, init);
554
+ return await config.handlers[m](req);
883
555
  }
884
556
 
885
- // src/api/utils/routes/apiRoutes.ts
886
- var apiRoutes = (config) => ({
887
- ME: makeRestUrl(config, "/me"),
888
- USERS: (qp) => makeRestUrl(config, "/users", qp),
889
- USER: (userId) => makeRestUrl(config, `/users/${userId}`),
890
- TENANTS: makeRestUrl(config, "/tenants"),
891
- TENANT: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}`),
892
- SIGNUP: makeRestUrl(config, "/signup"),
893
- TENANT_USERS: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/users`),
894
- TENANT_USER: (tenantId, userId) => makeRestUrl(config, `/tenants/${tenantId}/users/${userId}`),
895
- USER_TENANTS: (userId) => makeRestUrl(config, `/users/${userId}/tenants`)
896
- });
897
-
898
- // src/api/routes/me/index.ts
899
- var key = "ME";
900
- async function GET(url, init, config) {
901
- const res = await request(url, init, config);
902
- return res;
557
+ // src/api/routes/tenants/[tenantId]/invites/GET.ts
558
+ async function GET4(config, init) {
559
+ const yurl = new URL(init.request.url);
560
+ const [, tenantId] = yurl.pathname.split("/").reverse();
561
+ if (!tenantId) {
562
+ return new Response(null, { status: 404 });
563
+ }
564
+ init.method = "GET";
565
+ const url = `${apiRoutes(config).INVITES(tenantId)}`;
566
+ return await request(url, init, config);
903
567
  }
904
- async function route(request2, config) {
905
- const url = apiRoutes(config)[key];
568
+
569
+ // src/api/routes/tenants/[tenantId]/invites/index.ts
570
+ var key5 = "INVITES";
571
+ async function route5(request2, config) {
906
572
  switch (request2.method) {
907
573
  case "GET":
908
- return await GET(url, { request: request2 }, config);
574
+ return await GET4(config, { request: request2 });
909
575
  default:
910
576
  return new Response("method not allowed", { status: 405 });
911
577
  }
912
578
  }
913
- function matches(configRoutes, request2) {
914
- return urlMatches(request2.url, configRoutes[key]);
579
+ function matches5(configRoutes, request2) {
580
+ const url = new URL(request2.url);
581
+ const [, tenantId] = url.pathname.split("/").reverse();
582
+ const route20 = configRoutes[key5].replace("{tenantId}", tenantId);
583
+ return url.pathname.endsWith(route20);
915
584
  }
916
-
917
- // src/utils/ResponseError.ts
918
- var ResponseError = class {
919
- response;
920
- constructor(body, init) {
921
- this.response = new Response(body, init);
585
+ async function fetchInvites(config) {
586
+ if (!config.tenantId) {
587
+ throw new Error(
588
+ "Unable to fetch invites for the tenant, the tenantId context is missing. Call nile.setContext({ tenantId })"
589
+ );
922
590
  }
923
- };
591
+ if (!isUUID(config.tenantId)) {
592
+ config.logger("fetchInvites").warn(
593
+ "nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
594
+ );
595
+ }
596
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/invites" /* INVITES */.replace("{tenantId}", config.tenantId)}`;
597
+ const req = new Request(clientUrl, { headers: config.headers });
598
+ return await config.handlers.GET(req);
599
+ }
924
600
 
925
- // src/utils/fetch.ts
926
- function getTokenFromCookie(headers, cookieKey) {
927
- const cookie = headers.get("cookie")?.split("; ") ?? getCookie()?.split("; ");
928
- const _cookies = {};
929
- if (cookie) {
930
- for (const parts of cookie) {
931
- const cookieParts = parts.split("=");
932
- const _cookie = cookieParts.slice(1).join("=");
933
- const name = cookieParts[0];
934
- _cookies[name] = _cookie;
935
- }
936
- }
937
- if (cookie) {
938
- for (const parts of cookie) {
939
- const cookieParts = parts.split("=");
940
- const _cookie = cookieParts.slice(1).join("=");
941
- const name = cookieParts[0];
942
- _cookies[name] = _cookie;
943
- }
944
- }
945
- if (cookieKey) {
946
- return _cookies[cookieKey];
947
- }
948
- return null;
949
- }
950
- function getTenantFromHttp(headers, config) {
951
- const cookieTenant = getTokenFromCookie(headers, X_NILE_TENANT);
952
- return cookieTenant ?? headers?.get(X_NILE_TENANT) ?? config?.tenantId;
953
- }
954
- function getUserFromHttp(headers, config) {
955
- const token = getTokenFromCookie(headers, config.api.cookieKey);
956
- if (token) {
957
- const jwt = jose.decodeJwt(token);
958
- return jwt.sub;
959
- }
960
- return headers?.get(X_NILE_USER_ID) ?? config.userId;
961
- }
962
- function makeBasicHeaders(config, url, opts) {
963
- const { warn, error } = Logger(config, "[headers]");
964
- const headers = new Headers(opts?.headers);
965
- headers.set("content-type", "application/json; charset=utf-8");
966
- const cookieKey = config.api?.cookieKey;
967
- const authHeader = headers.get("Authorization");
968
- if (!authHeader) {
969
- const token = getTokenFromCookie(headers, cookieKey);
970
- if (token) {
971
- headers.set("Authorization", `Bearer ${token}`);
972
- } else if (getToken({ config })) {
973
- headers.set("Authorization", `Bearer ${getToken({ config })}`);
974
- }
975
- }
976
- const cookie = headers.get("cookie");
977
- if (!cookie) {
978
- const contextCookie = getCookie();
979
- if (contextCookie) {
980
- headers.set("cookie", contextCookie);
981
- } else {
982
- if (!url.endsWith("/users")) {
983
- error(
984
- "Missing cookie header from request. Call nile.api.setContext(request) before making additional calls."
985
- );
986
- }
987
- }
988
- }
989
- if (config && config.api.secureCookies != null) {
990
- headers.set(X_NILE_SECURECOOKIES, String(config.api.secureCookies));
991
- }
992
- const savedOrigin = getOrigin();
993
- if (config && config.api.origin) {
994
- headers.set(X_NILE_ORIGIN, config.api.origin);
995
- } else if (savedOrigin) {
996
- headers.set(X_NILE_ORIGIN, savedOrigin);
997
- } else {
998
- warn(
999
- "nile.origin missing from header, which defaults to secure cookies only."
1000
- );
1001
- }
1002
- return headers;
1003
- }
1004
- async function _fetch(config, path, opts) {
1005
- const { debug, error } = Logger(config, "[server]");
1006
- const url = `${config.api?.basePath}${path}`;
1007
- const headers = new Headers(opts?.headers);
1008
- const tenantId = getTenantFromHttp(headers, config);
1009
- const basicHeaders = makeBasicHeaders(config, url, opts);
1010
- updateTenantId(tenantId);
1011
- const userId = getUserFromHttp(headers, config);
1012
- updateUserId(userId);
1013
- if (url.includes("{tenantId}") && !tenantId) {
1014
- return new ResponseError("tenantId is not set for request", {
1015
- status: 400
1016
- });
1017
- }
1018
- const useableUrl = url.replace("{tenantId}", encodeURIComponent(String(tenantId))).replace("{userId}", encodeURIComponent(String(userId)));
1019
- debug(`[fetch] ${useableUrl}`);
1020
- try {
1021
- const response = await fetch(useableUrl, {
1022
- ...opts,
1023
- headers: basicHeaders
1024
- }).catch((e) => {
1025
- error("[fetch][response]", {
1026
- message: e.message,
1027
- stack: e.stack,
1028
- debug: "Is nile-auth running?"
1029
- });
1030
- return new Error(e);
1031
- });
1032
- if (response instanceof Error) {
1033
- return new ResponseError("Failed to connect to database", {
1034
- status: 400
1035
- });
1036
- }
1037
- if (response && response.status >= 200 && response.status < 300) {
1038
- if (typeof response.clone === "function") {
1039
- try {
1040
- debug(
1041
- `[fetch][response][${opts?.method ?? "GET"}] ${response.status} ${useableUrl}`,
1042
- {
1043
- body: await response.clone().json()
1044
- }
1045
- );
1046
- } catch (e) {
1047
- debug(
1048
- `[fetch][response][${opts?.method ?? "GET"}] ${response.status} ${useableUrl}`,
1049
- {
1050
- body: await response.clone().text()
1051
- }
1052
- );
1053
- }
1054
- }
1055
- return response;
1056
- }
1057
- if (response?.status === 404) {
1058
- return new ResponseError("Not found", { status: 404 });
1059
- }
1060
- if (response?.status === 401) {
1061
- return new ResponseError("Unauthorized", { status: 401 });
1062
- }
1063
- if (response?.status === 405) {
1064
- return new ResponseError("Method not allowed", { status: 405 });
1065
- }
1066
- const errorHandler = typeof response?.clone === "function" ? response.clone() : null;
1067
- let msg = "";
1068
- const res = await response?.json().catch(async (e) => {
1069
- if (errorHandler) {
1070
- msg = await errorHandler.text();
1071
- if (msg) {
1072
- error(`[fetch][response][status: ${errorHandler.status}]`, {
1073
- message: msg
1074
- });
1075
- }
1076
- return e;
1077
- }
1078
- if (!msg) {
1079
- error("[fetch][response]", { e });
1080
- }
1081
- return e;
1082
- });
1083
- if (msg) {
1084
- return new ResponseError(msg, { status: errorHandler?.status });
1085
- }
1086
- if (res && "message" in res) {
1087
- const { message } = res;
1088
- error(`[fetch][response][status: ${errorHandler?.status}] ${message}`);
1089
- return new ResponseError(message, { status: 400 });
1090
- }
1091
- if (res && "errors" in res) {
1092
- const {
1093
- errors: [message]
1094
- } = res;
1095
- error(`[fetch][response] [status: ${errorHandler?.status}] ${message}`);
1096
- return new ResponseError(message, { status: 400 });
1097
- }
1098
- error(
1099
- `[fetch][response][status: ${errorHandler?.status}] UNHANDLED ERROR`,
1100
- {
1101
- response,
1102
- message: await response.text()
1103
- }
1104
- );
1105
- return new ResponseError(null, {
1106
- status: response?.status ?? 500
1107
- });
1108
- } catch (e) {
1109
- return new ResponseError("an unexpected error has occurred", {
1110
- status: 500
1111
- });
1112
- }
1113
- }
1114
-
1115
- // src/api/routes/users/POST.ts
1116
- async function POST(config, init) {
1117
- init.body = init.request.body;
1118
- init.method = "POST";
1119
- const yurl = new URL(init.request.url);
1120
- const tenantId = yurl.searchParams.get("tenantId");
1121
- const newTenantName = yurl.searchParams.get("newTenantName");
1122
- const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
1123
- const url = apiRoutes(config).USERS({ tenantId: tenant, newTenantName });
1124
- return await request(url, init, config);
1125
- }
1126
-
1127
- // src/api/routes/users/GET.ts
1128
- async function GET2(config, init, log) {
1129
- const yurl = new URL(init.request.url);
1130
- const tenantId = yurl.searchParams.get("tenantId");
1131
- const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
1132
- if (!tenant) {
1133
- log("[GET] No tenant id provided.");
1134
- return new Response(null, { status: 404 });
1135
- }
1136
- const url = apiRoutes(config).TENANT_USERS(tenant);
1137
- init.method = "GET";
1138
- return await request(url, init, config);
1139
- }
1140
-
1141
- // src/api/routes/users/[userId]/PUT.ts
1142
- async function PUT(config, session, init) {
1143
- if (!session) {
1144
- return new Response(null, { status: 401 });
1145
- }
1146
- init.body = init.request.body;
1147
- init.method = "PUT";
1148
- const [userId] = new URL(init.request.url).pathname.split("/").reverse();
1149
- const url = apiRoutes(config).USER(userId);
1150
- return await request(url, init, config);
1151
- }
1152
-
1153
- // src/api/routes/users/index.ts
1154
- var key2 = "USERS";
1155
- async function route2(request2, config) {
1156
- const { info } = Logger(
1157
- { ...config, debug: config.debug },
1158
- `[ROUTES][${key2}]`
1159
- );
1160
- const session = await auth(request2, config);
1161
- switch (request2.method) {
1162
- case "GET":
1163
- return await GET2(config, { request: request2 }, info);
1164
- case "POST":
1165
- return await POST(config, { request: request2 });
1166
- case "PUT":
1167
- return await PUT(config, session, { request: request2 });
1168
- default:
1169
- return new Response("method not allowed", { status: 405 });
1170
- }
1171
- }
1172
- function matches2(configRoutes, request2) {
1173
- return urlMatches(request2.url, configRoutes[key2]);
1174
- }
1175
-
1176
- // src/api/routes/tenants/[tenantId]/users/GET.ts
1177
- async function GET3(config, init) {
1178
- const yurl = new URL(init.request.url);
1179
- const [, tenantId] = yurl.pathname.split("/").reverse();
1180
- const url = `${apiRoutes(config).TENANT_USERS(tenantId)}`;
1181
- return await request(url, init, config);
1182
- }
1183
-
1184
- // src/api/routes/tenants/[tenantId]/users/POST.ts
1185
- async function POST2(config, session, init) {
1186
- const yurl = new URL(init.request.url);
1187
- const [, tenantId] = yurl.pathname.split("/").reverse();
1188
- init.body = JSON.stringify({ email: session.email });
1189
- init.method = "PUT";
1190
- const url = apiRoutes(config).TENANT_USERS(tenantId);
1191
- return await request(url, init, config);
1192
- }
1193
-
1194
- // src/api/routes/tenants/[tenantId]/users/[userId]/DELETE.ts
1195
- async function DELETE(config, init) {
1196
- const yurl = new URL(init.request.url);
1197
- const [userId, _, tenantId] = yurl.pathname.split("/").reverse();
1198
- init.method = "DELETE";
1199
- init.body = JSON.stringify({ email: userId });
1200
- const url = `${apiRoutes(config).TENANT_USER(tenantId, userId)}`;
1201
- return await request(url, init, config);
1202
- }
1203
-
1204
- // src/api/routes/tenants/[tenantId]/users/PUT.ts
1205
- async function PUT2(config, init) {
1206
- const yurl = new URL(init.request.url);
1207
- const [, tenantId] = yurl.pathname.split("/").reverse();
1208
- init.method = "PUT";
1209
- const url = `${apiRoutes(config).TENANT_USERS(tenantId)}`;
1210
- return await request(url, init, config);
1211
- }
1212
-
1213
- // src/api/routes/tenants/[tenantId]/users/index.ts
1214
- var key3 = "TENANT_USERS";
1215
- async function route3(request2, config) {
1216
- const { info } = Logger(
1217
- { ...config, debug: config.debug },
1218
- `[ROUTES][${key3}]`
1219
- );
1220
- const session = await auth(request2, config);
1221
- if (!session) {
1222
- info("401");
1223
- return new Response(null, { status: 401 });
1224
- }
1225
- const yurl = new URL(request2.url);
1226
- const [, tenantId] = yurl.pathname.split("/").reverse();
1227
- if (!tenantId) {
1228
- info("No tenant id found in path");
1229
- return new Response(null, { status: 404 });
1230
- }
1231
- switch (request2.method) {
1232
- case "GET":
1233
- return await GET3(config, { request: request2 });
1234
- case "POST":
1235
- return await POST2(config, session, { request: request2 });
1236
- case "PUT":
1237
- return await PUT2(config, { request: request2 });
1238
- case "DELETE":
1239
- return await DELETE(config, { request: request2 });
1240
- default:
1241
- return new Response("method not allowed", { status: 405 });
1242
- }
1243
- }
1244
- function matches3(configRoutes, request2) {
1245
- const url = new URL(request2.url);
1246
- const [userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
1247
- let route15 = configRoutes[key3].replace("{tenantId}", tenantId).replace("{userId}", userId);
1248
- if (userId === "users") {
1249
- route15 = configRoutes[key3].replace("{tenantId}", possibleTenantId);
1250
- }
1251
- return urlMatches(request2.url, route15);
1252
- }
1253
-
1254
- // src/api/routes/tenants/GET.ts
1255
- async function GET4(config, session, init) {
1256
- let url = `${apiRoutes(config).USER_TENANTS(session.id)}`;
1257
- if (typeof session === "object" && "user" in session && session.user) {
1258
- url = `${apiRoutes(config).USER_TENANTS(session.user.id)}`;
601
+ // src/api/routes/tenants/GET.ts
602
+ async function GET5(config, session, init) {
603
+ let url = `${apiRoutes(config).USER_TENANTS(session.id)}`;
604
+ if (typeof session === "object" && "user" in session && session.user) {
605
+ url = `${apiRoutes(config).USER_TENANTS(session.user.id)}`;
1259
606
  }
1260
607
  const res = await request(url, init, config);
1261
608
  return res;
1262
609
  }
1263
610
 
1264
611
  // src/api/routes/tenants/[tenantId]/GET.ts
1265
- async function GET5(config, init, log) {
612
+ async function GET6(config, init, log) {
1266
613
  const yurl = new URL(init.request.url);
1267
614
  const [tenantId] = yurl.pathname.split("/").reverse();
1268
615
  if (!tenantId) {
@@ -1287,7 +634,7 @@ async function DELETE2(config, init) {
1287
634
  }
1288
635
 
1289
636
  // src/api/routes/tenants/[tenantId]/PUT.ts
1290
- async function PUT3(config, init) {
637
+ async function PUT4(config, init) {
1291
638
  const yurl = new URL(init.request.url);
1292
639
  const [tenantId] = yurl.pathname.split("/").reverse();
1293
640
  if (!tenantId) {
@@ -1300,7 +647,7 @@ async function PUT3(config, init) {
1300
647
  }
1301
648
 
1302
649
  // src/api/routes/tenants/POST.ts
1303
- async function POST3(config, init) {
650
+ async function POST4(config, init) {
1304
651
  init.body = init.request.body;
1305
652
  init.method = "POST";
1306
653
  const url = `${apiRoutes(config).TENANTS}`;
@@ -1308,19 +655,9 @@ async function POST3(config, init) {
1308
655
  }
1309
656
 
1310
657
  // src/api/routes/tenants/index.ts
1311
- function isUUID(value) {
1312
- if (!value) {
1313
- return false;
1314
- }
1315
- 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}$/;
1316
- return regex.test(value);
1317
- }
1318
- var key4 = "TENANTS";
1319
- async function route4(request2, config) {
1320
- const { info } = Logger(
1321
- { ...config, debug: config.debug },
1322
- `[ROUTES][${key4}]`
1323
- );
658
+ var key6 = "TENANTS";
659
+ async function route6(request2, config) {
660
+ const { info } = config.logger(`[ROUTES][${key6}]`);
1324
661
  const session = await auth(request2, config);
1325
662
  if (!session) {
1326
663
  info("401");
@@ -1330,47 +667,84 @@ async function route4(request2, config) {
1330
667
  switch (request2.method) {
1331
668
  case "GET":
1332
669
  if (isUUID(possibleTenantId)) {
1333
- return await GET5(config, { request: request2 }, info);
670
+ return await GET6(config, { request: request2 }, info);
1334
671
  }
1335
- return await GET4(config, session, { request: request2 });
672
+ return await GET5(config, session, { request: request2 });
1336
673
  case "POST":
1337
- return await POST3(config, { request: request2 });
674
+ return await POST4(config, { request: request2 });
1338
675
  case "DELETE":
1339
676
  return await DELETE2(config, { request: request2 });
1340
677
  case "PUT":
1341
- return await PUT3(config, { request: request2 });
678
+ return await PUT4(config, { request: request2 });
1342
679
  default:
1343
680
  return new Response("method not allowed", { status: 405 });
1344
681
  }
1345
682
  }
1346
- function matches4(configRoutes, request2) {
1347
- return urlMatches(request2.url, configRoutes[key4]);
683
+ function matches6(configRoutes, request2) {
684
+ return urlMatches(request2.url, configRoutes[key6]);
685
+ }
686
+ async function fetchTenants(config, method, body) {
687
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants" /* TENANTS */}`;
688
+ const init = {
689
+ method,
690
+ headers: config.headers
691
+ };
692
+ {
693
+ init.body = body;
694
+ }
695
+ const req = new Request(clientUrl, init);
696
+ return await config.handlers.POST(req);
697
+ }
698
+ async function fetchTenant(config, method, body) {
699
+ if (!config.tenantId) {
700
+ throw new Error(
701
+ "Unable to fetch tenants, the tenantId context is missing. Call nile.setContext({ tenantId })"
702
+ );
703
+ }
704
+ if (!isUUID(config.tenantId)) {
705
+ config.logger("fetch tenant").warn(
706
+ "nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
707
+ );
708
+ }
709
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}" /* TENANT */.replace("{tenantId}", config.tenantId)}`;
710
+ const m = method ?? "GET";
711
+ const init = {
712
+ method: m,
713
+ headers: config.headers
714
+ };
715
+ if (m === "PUT") {
716
+ init.body = body;
717
+ }
718
+ const req = new Request(clientUrl, init);
719
+ return await config.handlers[m](req);
720
+ }
721
+ async function fetchTenantsByUser(config) {
722
+ const { warn } = config.logger("fetchTenantsByUser");
723
+ if (!config.userId) {
724
+ warn(
725
+ "nile.userId is not set. The call will still work for the API, but the database context is not set properly and may lead to unexpected behavior in your application."
726
+ );
727
+ } else if (!isUUID(config.userId)) {
728
+ warn(
729
+ "nile.userId is not a valid UUID. This may lead to unexpected behavior in your application."
730
+ );
731
+ }
732
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants" /* TENANTS */}`;
733
+ const req = new Request(clientUrl, { headers: config.headers });
734
+ return await config.handlers.GET(req);
1348
735
  }
1349
-
1350
- // src/api/utils/routes/proxyRoutes.ts
1351
- var proxyRoutes = (config) => ({
1352
- SIGNIN: makeRestUrl(config, "/auth/signin"),
1353
- PROVIDERS: makeRestUrl(config, "/auth/providers"),
1354
- SESSION: makeRestUrl(config, "/auth/session"),
1355
- CSRF: makeRestUrl(config, "/auth/csrf"),
1356
- CALLBACK: makeRestUrl(config, "/auth/callback"),
1357
- SIGNOUT: makeRestUrl(config, "/auth/signout"),
1358
- ERROR: makeRestUrl(config, "/auth/error"),
1359
- VERIFY_REQUEST: makeRestUrl(config, "/auth/verify-request"),
1360
- PASSWORD_RESET: makeRestUrl(config, "/auth/reset-password")
1361
- });
1362
736
 
1363
737
  // src/api/routes/auth/signin.ts
1364
- var key5 = "SIGNIN";
1365
- async function route5(req, config) {
1366
- let url = proxyRoutes(config)[key5];
738
+ var key7 = "SIGNIN";
739
+ async function route7(req, config) {
740
+ let url = proxyRoutes(config)[key7];
1367
741
  const init = {
1368
742
  method: req.method,
1369
743
  headers: req.headers
1370
744
  };
1371
745
  if (req.method === "POST") {
1372
746
  const [provider] = new URL(req.url).pathname.split("/").reverse();
1373
- url = `${proxyRoutes(config)[key5]}/${provider}`;
747
+ url = `${proxyRoutes(config)[key7]}/${provider}`;
1374
748
  }
1375
749
  const passThroughUrl = new URL(req.url);
1376
750
  const params = new URLSearchParams(passThroughUrl.search);
@@ -1378,12 +752,21 @@ async function route5(req, config) {
1378
752
  const res = await request(url, { ...init, request: req }, config);
1379
753
  return res;
1380
754
  }
1381
- function matches5(configRoutes, request2) {
1382
- return urlMatches(request2.url, configRoutes[key5]);
755
+ function matches7(configRoutes, request2) {
756
+ return urlMatches(request2.url, configRoutes[key7]);
757
+ }
758
+ async function fetchSignIn(config, provider, body) {
759
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/signin" /* SIGNIN */}/${provider}`;
760
+ const req = new Request(clientUrl, {
761
+ method: "POST",
762
+ headers: config.headers,
763
+ body
764
+ });
765
+ return await config.handlers.POST(req);
1383
766
  }
1384
767
 
1385
768
  // src/api/routes/auth/session.ts
1386
- async function route6(req, config) {
769
+ async function route8(req, config) {
1387
770
  return request(
1388
771
  proxyRoutes(config).SESSION,
1389
772
  {
@@ -1393,12 +776,20 @@ async function route6(req, config) {
1393
776
  config
1394
777
  );
1395
778
  }
1396
- function matches6(configRoutes, request2) {
779
+ function matches8(configRoutes, request2) {
1397
780
  return urlMatches(request2.url, configRoutes.SESSION);
1398
781
  }
782
+ async function fetchSession(config) {
783
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/session" /* SESSION */}`;
784
+ const req = new Request(clientUrl, {
785
+ method: "GET",
786
+ headers: config.headers
787
+ });
788
+ return await config.handlers.GET(req);
789
+ }
1399
790
 
1400
791
  // src/api/routes/auth/providers.ts
1401
- async function route7(req, config) {
792
+ async function route9(req, config) {
1402
793
  return request(
1403
794
  proxyRoutes(config).PROVIDERS,
1404
795
  {
@@ -1408,12 +799,20 @@ async function route7(req, config) {
1408
799
  config
1409
800
  );
1410
801
  }
1411
- function matches7(configRoutes, request2) {
802
+ function matches9(configRoutes, request2) {
1412
803
  return urlMatches(request2.url, configRoutes.PROVIDERS);
1413
804
  }
805
+ async function fetchProviders(config) {
806
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/providers" /* PROVIDERS */}`;
807
+ const req = new Request(clientUrl, {
808
+ method: "GET",
809
+ headers: config.headers
810
+ });
811
+ return await config.handlers.GET(req);
812
+ }
1414
813
 
1415
814
  // src/api/routes/auth/csrf.ts
1416
- async function route8(req, config) {
815
+ async function route10(req, config) {
1417
816
  return request(
1418
817
  proxyRoutes(config).CSRF,
1419
818
  {
@@ -1423,22 +822,27 @@ async function route8(req, config) {
1423
822
  config
1424
823
  );
1425
824
  }
1426
- function matches8(configRoutes, request2) {
825
+ function matches10(configRoutes, request2) {
1427
826
  return urlMatches(request2.url, configRoutes.CSRF);
1428
827
  }
828
+ async function fetchCsrf(config) {
829
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/csrf" /* CSRF */}`;
830
+ const req = new Request(clientUrl, {
831
+ method: "GET",
832
+ headers: config.headers
833
+ });
834
+ return await config.handlers.GET(req);
835
+ }
1429
836
 
1430
837
  // src/api/routes/auth/callback.ts
1431
- var key6 = "CALLBACK";
1432
- async function route9(req, config) {
1433
- const { error } = Logger(
1434
- { ...config, debug: config.debug },
1435
- `[ROUTES][${key6}]`
1436
- );
838
+ var key8 = "CALLBACK";
839
+ async function route11(req, config) {
840
+ const { error } = config.logger(`[ROUTES][${key8}]`);
1437
841
  const [provider] = new URL(req.url).pathname.split("/").reverse();
1438
842
  try {
1439
843
  const passThroughUrl = new URL(req.url);
1440
844
  const params = new URLSearchParams(passThroughUrl.search);
1441
- const url = `${proxyRoutes(config)[key6]}/${provider}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
845
+ const url = `${proxyRoutes(config)[key8]}/${provider}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
1442
846
  const res = await request(
1443
847
  url,
1444
848
  {
@@ -1465,34 +869,52 @@ async function route9(req, config) {
1465
869
  }
1466
870
  return new Response("An unexpected error has occurred.", { status: 400 });
1467
871
  }
1468
- function matches9(configRoutes, request2) {
872
+ function matches11(configRoutes, request2) {
1469
873
  return urlMatches(request2.url, configRoutes.CALLBACK);
1470
874
  }
875
+ async function fetchCallback(config, provider, body, request2, method = "POST") {
876
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/callback" /* CALLBACK */}/${provider}${request2 ? `?${new URL(request2.url).searchParams}` : ""}`;
877
+ const req = new Request(clientUrl, {
878
+ method,
879
+ headers: config.headers,
880
+ body
881
+ });
882
+ return await config.handlers.POST(req);
883
+ }
1471
884
 
1472
885
  // src/api/routes/auth/signout.ts
1473
- var key7 = "SIGNOUT";
1474
- async function route10(request2, config) {
1475
- let url = proxyRoutes(config)[key7];
886
+ var key9 = "SIGNOUT";
887
+ async function route12(request2, config) {
888
+ let url = proxyRoutes(config)[key9];
1476
889
  const init = {
1477
890
  method: request2.method
1478
891
  };
1479
892
  if (request2.method === "POST") {
1480
893
  init.body = request2.body;
1481
894
  const [provider] = new URL(request2.url).pathname.split("/").reverse();
1482
- url = `${proxyRoutes(config)[key7]}${provider !== "signout" ? `/${provider}` : ""}`;
895
+ url = `${proxyRoutes(config)[key9]}${provider !== "signout" ? `/${provider}` : ""}`;
1483
896
  }
1484
897
  const res = await request(url, { ...init, request: request2 }, config);
1485
898
  return res;
1486
899
  }
1487
- function matches10(configRoutes, request2) {
1488
- return urlMatches(request2.url, configRoutes[key7]);
1489
- }
900
+ function matches12(configRoutes, request2) {
901
+ return urlMatches(request2.url, configRoutes[key9]);
902
+ }
903
+ async function fetchSignOut(config, body) {
904
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/signout" /* SIGNOUT */}`;
905
+ const req = new Request(clientUrl, {
906
+ method: "POST",
907
+ body,
908
+ headers: config.headers
909
+ });
910
+ return await config.handlers.POST(req);
911
+ }
1490
912
 
1491
913
  // src/api/routes/auth/error.ts
1492
- var key8 = "ERROR";
1493
- async function route11(req, config) {
914
+ var key10 = "ERROR";
915
+ async function route13(req, config) {
1494
916
  return request(
1495
- proxyRoutes(config)[key8],
917
+ proxyRoutes(config)[key10],
1496
918
  {
1497
919
  method: req.method,
1498
920
  request: req
@@ -1500,15 +922,15 @@ async function route11(req, config) {
1500
922
  config
1501
923
  );
1502
924
  }
1503
- function matches11(configRoutes, request2) {
1504
- return urlMatches(request2.url, configRoutes[key8]);
925
+ function matches13(configRoutes, request2) {
926
+ return urlMatches(request2.url, configRoutes[key10]);
1505
927
  }
1506
928
 
1507
929
  // src/api/routes/auth/verify-request.ts
1508
- var key9 = "VERIFY_REQUEST";
1509
- async function route12(req, config) {
930
+ var key11 = "VERIFY_REQUEST";
931
+ async function route14(req, config) {
1510
932
  return request(
1511
- proxyRoutes(config)[key9],
933
+ proxyRoutes(config)[key11],
1512
934
  {
1513
935
  method: req.method,
1514
936
  request: req
@@ -1516,14 +938,14 @@ async function route12(req, config) {
1516
938
  config
1517
939
  );
1518
940
  }
1519
- function matches12(configRoutes, request2) {
1520
- return urlMatches(request2.url, configRoutes[key9]);
941
+ function matches14(configRoutes, request2) {
942
+ return urlMatches(request2.url, configRoutes[key11]);
1521
943
  }
1522
944
 
1523
945
  // src/api/routes/auth/password-reset.ts
1524
- var key10 = "PASSWORD_RESET";
1525
- async function route13(req, config) {
1526
- const url = proxyRoutes(config)[key10];
946
+ var key12 = "PASSWORD_RESET";
947
+ async function route15(req, config) {
948
+ const url = proxyRoutes(config)[key12];
1527
949
  const res = await request(
1528
950
  url,
1529
951
  {
@@ -1544,73 +966,203 @@ async function route13(req, config) {
1544
966
  headers: res?.headers
1545
967
  });
1546
968
  }
1547
- function matches13(configRoutes, request2) {
969
+ function matches15(configRoutes, request2) {
1548
970
  return urlMatches(request2.url, configRoutes.PASSWORD_RESET);
1549
971
  }
972
+ async function fetchResetPassword(config, method, body, params, useJson = true) {
973
+ const authParams = new URLSearchParams(params ?? {});
974
+ if (useJson) {
975
+ authParams?.set("json", "true");
976
+ }
977
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/reset-password" /* PASSWORD_RESET */}?${authParams?.toString()}`;
978
+ const init = {
979
+ method,
980
+ headers: config.headers
981
+ };
982
+ if (body && method !== "GET") {
983
+ init.body = body;
984
+ }
985
+ const req = new Request(clientUrl, init);
986
+ return await config.handlers[method](req);
987
+ }
988
+
989
+ // src/api/routes/auth/verify-email.ts
990
+ var key13 = "VERIFY_EMAIL";
991
+ async function route16(req, config) {
992
+ const url = proxyRoutes(config)[key13];
993
+ const res = await request(
994
+ url,
995
+ {
996
+ method: req.method,
997
+ request: req
998
+ },
999
+ config
1000
+ );
1001
+ const location = res?.headers.get("location");
1002
+ if (location) {
1003
+ return new Response(res?.body, {
1004
+ status: 302,
1005
+ headers: res?.headers
1006
+ });
1007
+ }
1008
+ return new Response(res?.body, {
1009
+ status: res?.status,
1010
+ headers: res?.headers
1011
+ });
1012
+ }
1013
+ function matches16(configRoutes, request2) {
1014
+ return urlMatches(request2.url, configRoutes[key13]);
1015
+ }
1016
+ async function fetchVerifyEmail(config, method, body) {
1017
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/verify-email" /* VERIFY_EMAIL */}`;
1018
+ const init = {
1019
+ method,
1020
+ headers: config.headers
1021
+ };
1022
+ if (body) {
1023
+ init.body = body;
1024
+ }
1025
+ const req = new Request(clientUrl, init);
1026
+ return await config.handlers[method](req);
1027
+ }
1550
1028
 
1551
1029
  // src/api/handlers/GET.ts
1552
1030
  function GETTER(configRoutes, config) {
1553
- const { info, warn } = Logger(config, "[GET MATCHER]");
1554
- return async function GET6(req) {
1031
+ const { info, warn } = config.logger("[GET MATCHER]");
1032
+ return async function GET7(req) {
1555
1033
  if (matches(configRoutes, req)) {
1556
1034
  info("matches me");
1557
1035
  return route(req, config);
1558
1036
  }
1037
+ if (matches5(configRoutes, req)) {
1038
+ info("matches tenant invites");
1039
+ return route5(req, config);
1040
+ }
1041
+ if (matches4(configRoutes, req)) {
1042
+ info("matches invite");
1043
+ return route4(req, config);
1044
+ }
1559
1045
  if (matches3(configRoutes, req)) {
1560
1046
  info("matches tenant users");
1561
1047
  return route3(req, config);
1562
1048
  }
1049
+ if (matches6(configRoutes, req)) {
1050
+ info("matches tenants");
1051
+ return route6(req, config);
1052
+ }
1563
1053
  if (matches2(configRoutes, req)) {
1564
1054
  info("matches users");
1565
1055
  return route2(req, config);
1566
1056
  }
1567
- if (matches4(configRoutes, req)) {
1568
- info("matches tenants");
1569
- return route4(req, config);
1570
- }
1571
- if (matches6(configRoutes, req)) {
1057
+ if (matches8(configRoutes, req)) {
1572
1058
  info("matches session");
1573
- return route6(req, config);
1059
+ return route8(req, config);
1574
1060
  }
1575
- if (matches5(configRoutes, req)) {
1061
+ if (matches7(configRoutes, req)) {
1576
1062
  info("matches signin");
1577
- return route5(req, config);
1063
+ return route7(req, config);
1578
1064
  }
1579
- if (matches7(configRoutes, req)) {
1065
+ if (matches9(configRoutes, req)) {
1580
1066
  info("matches providers");
1581
- return route7(req, config);
1067
+ return route9(req, config);
1582
1068
  }
1583
- if (matches8(configRoutes, req)) {
1069
+ if (matches10(configRoutes, req)) {
1584
1070
  info("matches csrf");
1585
- return route8(req, config);
1071
+ return route10(req, config);
1586
1072
  }
1587
- if (matches13(configRoutes, req)) {
1073
+ if (matches15(configRoutes, req)) {
1588
1074
  info("matches password reset");
1589
- return route13(req, config);
1075
+ return route15(req, config);
1590
1076
  }
1591
- if (matches9(configRoutes, req)) {
1077
+ if (matches11(configRoutes, req)) {
1592
1078
  info("matches callback");
1593
- return route9(req, config);
1079
+ return route11(req, config);
1594
1080
  }
1595
- if (matches10(configRoutes, req)) {
1081
+ if (matches12(configRoutes, req)) {
1596
1082
  info("matches signout");
1597
- return route10(req, config);
1083
+ return route12(req, config);
1598
1084
  }
1599
- if (matches12(configRoutes, req)) {
1085
+ if (matches14(configRoutes, req)) {
1600
1086
  info("matches verify-request");
1601
- return route12(req, config);
1087
+ return route14(req, config);
1602
1088
  }
1603
- if (matches11(configRoutes, req)) {
1089
+ if (matches16(configRoutes, req)) {
1090
+ info("matches verify-email");
1091
+ return route16(req, config);
1092
+ }
1093
+ if (matches13(configRoutes, req)) {
1604
1094
  info("matches error");
1605
- return route11(req, config);
1095
+ return route13(req, config);
1606
1096
  }
1607
- warn("No GET routes matched");
1097
+ warn(`No GET routes matched ${req.url}`);
1608
1098
  return new Response(null, { status: 404 });
1609
1099
  };
1610
1100
  }
1611
1101
 
1102
+ // src/utils/Logger.ts
1103
+ var red = "\x1B[31m";
1104
+ var yellow = "\x1B[38;2;255;255;0m";
1105
+ var purple = "\x1B[38;2;200;160;255m";
1106
+ var orange = "\x1B[38;2;255;165;0m";
1107
+ var reset = "\x1B[0m";
1108
+ var baseLogger = (config, ...params) => ({
1109
+ info(message, meta) {
1110
+ if (config?.debug) {
1111
+ console.info(
1112
+ `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
1113
+ ""
1114
+ )}${reset} ${message}`,
1115
+ meta ? `${JSON.stringify(meta)}` : ""
1116
+ );
1117
+ }
1118
+ },
1119
+ debug(message, meta) {
1120
+ if (config?.debug) {
1121
+ console.debug(
1122
+ `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
1123
+ ""
1124
+ )}${reset} ${message}`,
1125
+ meta ? `${JSON.stringify(meta)}` : ""
1126
+ );
1127
+ }
1128
+ },
1129
+ warn(message, meta) {
1130
+ if (config?.debug) {
1131
+ console.warn(
1132
+ `${orange}[niledb]${reset}${yellow}[WARN]${reset}${params.join(
1133
+ ""
1134
+ )}${reset} ${message}`,
1135
+ meta ? JSON.stringify(meta) : ""
1136
+ );
1137
+ }
1138
+ },
1139
+ error(message, meta) {
1140
+ console.error(
1141
+ `${orange}[niledb]${reset}${red}[ERROR]${reset}${params.join(
1142
+ ""
1143
+ )}${red} ${message}`,
1144
+ meta ? meta : "",
1145
+ `${reset}`
1146
+ );
1147
+ }
1148
+ });
1149
+ function Logger(config) {
1150
+ return (prefixes) => {
1151
+ const { info, debug, warn, error } = config && typeof config?.logger === "function" ? config.logger(prefixes) : baseLogger(config, prefixes);
1152
+ return {
1153
+ info,
1154
+ debug,
1155
+ warn,
1156
+ error
1157
+ };
1158
+ };
1159
+ }
1160
+ function matchesLog(configRoutes, request2) {
1161
+ return urlMatches(request2.url, configRoutes.LOG);
1162
+ }
1163
+
1612
1164
  // src/api/routes/signup/POST.ts
1613
- async function POST4(config, init) {
1165
+ async function POST5(config, init) {
1614
1166
  init.body = init.request.body;
1615
1167
  init.method = "POST";
1616
1168
  const url = `${apiRoutes(config).SIGNUP}`;
@@ -1618,365 +1170,1224 @@ async function POST4(config, init) {
1618
1170
  }
1619
1171
 
1620
1172
  // src/api/routes/signup/index.tsx
1621
- var key11 = "SIGNUP";
1622
- async function route14(request2, config) {
1173
+ var key14 = "SIGNUP";
1174
+ async function route17(request2, config) {
1623
1175
  switch (request2.method) {
1624
1176
  case "POST":
1625
- return await POST4(config, { request: request2 });
1177
+ return await POST5(config, { request: request2 });
1626
1178
  default:
1627
1179
  return new Response("method not allowed", { status: 405 });
1628
1180
  }
1629
1181
  }
1630
- function matches14(configRoutes, request2) {
1631
- return urlMatches(request2.url, configRoutes[key11]);
1182
+ function matches17(configRoutes, request2) {
1183
+ return urlMatches(request2.url, configRoutes[key14]);
1184
+ }
1185
+ async function fetchSignUp(config, payload) {
1186
+ const { body, params } = payload ?? {};
1187
+ const q = new URLSearchParams();
1188
+ if (params?.newTenantName) {
1189
+ q.set("newTenantName", params.newTenantName);
1190
+ }
1191
+ if (params?.tenantId) {
1192
+ q.set("tenantId", params.tenantId);
1193
+ }
1194
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/signup" /* SIGNUP */}${q.size > 0 ? `?${q}` : ""}`;
1195
+ const req = new Request(clientUrl, {
1196
+ method: "POST",
1197
+ headers: config.headers,
1198
+ body
1199
+ });
1200
+ return await config.handlers.POST(req);
1632
1201
  }
1633
1202
 
1634
1203
  // src/api/handlers/POST.ts
1635
1204
  function POSTER(configRoutes, config) {
1636
- const { info, warn, error } = Logger(config, "[POST MATCHER]");
1637
- return async function POST5(req) {
1205
+ const { info, warn, error } = config.logger("[POST MATCHER]");
1206
+ return async function POST6(req) {
1638
1207
  if (matchesLog(configRoutes, req)) {
1639
- if (req.body) {
1640
- try {
1641
- const text = await req.text();
1642
- error(text);
1643
- return new Response(null, {
1644
- status: 200
1645
- });
1646
- } catch (e) {
1647
- }
1208
+ try {
1209
+ const json = await req.clone().json();
1210
+ error(req.body && json);
1211
+ } catch {
1212
+ error(await req.text());
1648
1213
  }
1214
+ return new Response(null, { status: 200 });
1649
1215
  }
1650
1216
  if (matches3(configRoutes, req)) {
1651
1217
  info("matches tenant users");
1652
1218
  return route3(req, config);
1653
1219
  }
1654
- if (matches14(configRoutes, req)) {
1220
+ if (matches4(configRoutes, req)) {
1221
+ info("matches tenant invite");
1222
+ return route4(req, config);
1223
+ }
1224
+ if (matches17(configRoutes, req)) {
1655
1225
  info("matches signup");
1656
- return route14(req, config);
1226
+ return route17(req, config);
1657
1227
  }
1658
1228
  if (matches2(configRoutes, req)) {
1659
1229
  info("matches users");
1660
1230
  return route2(req, config);
1661
1231
  }
1662
- if (matches4(configRoutes, req)) {
1663
- info("matches tenants");
1664
- return route4(req, config);
1232
+ if (matches6(configRoutes, req)) {
1233
+ info("matches tenants");
1234
+ return route6(req, config);
1235
+ }
1236
+ if (matches8(configRoutes, req)) {
1237
+ info("matches session");
1238
+ return route8(req, config);
1239
+ }
1240
+ if (matches7(configRoutes, req)) {
1241
+ info("matches signin");
1242
+ return route7(req, config);
1243
+ }
1244
+ if (matches15(configRoutes, req)) {
1245
+ info("matches password reset");
1246
+ return route15(req, config);
1247
+ }
1248
+ if (matches9(configRoutes, req)) {
1249
+ info("matches providers");
1250
+ return route9(req, config);
1251
+ }
1252
+ if (matches10(configRoutes, req)) {
1253
+ info("matches csrf");
1254
+ return route10(req, config);
1255
+ }
1256
+ if (matches11(configRoutes, req)) {
1257
+ info("matches callback");
1258
+ return route11(req, config);
1259
+ }
1260
+ if (matches12(configRoutes, req)) {
1261
+ info("matches signout");
1262
+ return route12(req, config);
1263
+ }
1264
+ if (matches16(configRoutes, req)) {
1265
+ info("matches verify-email");
1266
+ return route16(req, config);
1267
+ }
1268
+ warn(`No POST routes matched ${req.url}`);
1269
+ return new Response(null, { status: 404 });
1270
+ };
1271
+ }
1272
+
1273
+ // src/api/routes/tenants/[tenantId]/users/[userId]/DELETE.ts
1274
+ async function DELETE3(config, init) {
1275
+ const yurl = new URL(init.request.url);
1276
+ const [, userId, , tenantId] = yurl.pathname.split("/").reverse();
1277
+ config.tenantId = tenantId;
1278
+ config.userId = userId;
1279
+ init.method = "DELETE";
1280
+ const url = `${apiRoutes(config).TENANT_USER}/link`;
1281
+ return await request(url, init, config);
1282
+ }
1283
+
1284
+ // src/api/routes/tenants/[tenantId]/users/[userId]/PUT.ts
1285
+ async function PUT5(config, init) {
1286
+ const yurl = new URL(init.request.url);
1287
+ const [, userId, , tenantId] = yurl.pathname.split("/").reverse();
1288
+ config.tenantId = tenantId;
1289
+ config.userId = userId;
1290
+ init.method = "PUT";
1291
+ const url = `${apiRoutes(config).TENANT_USER}/link`;
1292
+ return await request(url, init, config);
1293
+ }
1294
+
1295
+ // src/api/routes/tenants/[tenantId]/users/[userId]/index.ts
1296
+ var key15 = "TENANT_USER";
1297
+ async function route18(request2, config) {
1298
+ const { info } = config.logger(`[ROUTES][${key15}]`);
1299
+ const session = await auth(request2, config);
1300
+ if (!session) {
1301
+ info("401");
1302
+ return new Response(null, { status: 401 });
1303
+ }
1304
+ const yurl = new URL(request2.url);
1305
+ const [, userId] = yurl.pathname.split("/").reverse();
1306
+ if (!userId) {
1307
+ info("No tenant id found in path");
1308
+ return new Response(null, { status: 404 });
1309
+ }
1310
+ switch (request2.method) {
1311
+ case "PUT":
1312
+ return await PUT5(config, { request: request2 });
1313
+ case "DELETE":
1314
+ return await DELETE3(config, { request: request2 });
1315
+ default:
1316
+ return new Response("method not allowed", { status: 405 });
1317
+ }
1318
+ }
1319
+ function matches18(configRoutes, request2) {
1320
+ const url = new URL(request2.url);
1321
+ const [, userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
1322
+ let route20 = configRoutes[key15].replace("{tenantId}", tenantId).replace("{userId}", userId);
1323
+ if (userId === "users") {
1324
+ route20 = configRoutes[key15].replace("{tenantId}", possibleTenantId);
1325
+ }
1326
+ return urlMatches(request2.url, route20);
1327
+ }
1328
+ async function fetchTenantUser(config, method) {
1329
+ if (!config.tenantId) {
1330
+ throw new Error(
1331
+ "The tenantId context is missing. Call nile.setContext({ tenantId })"
1332
+ );
1333
+ }
1334
+ if (!config.userId) {
1335
+ throw new Error(
1336
+ "the userId context is missing. Call nile.setContext({ userId })"
1337
+ );
1338
+ }
1339
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */.replace(
1340
+ "{tenantId}",
1341
+ config.tenantId
1342
+ ).replace("{userId}", config.userId)}/link`;
1343
+ const req = new Request(clientUrl, {
1344
+ headers: config.headers,
1345
+ method
1346
+ });
1347
+ return await config.handlers[method](req);
1348
+ }
1349
+
1350
+ // src/api/routes/tenants/[tenantId]/invite/[inviteId]/DELETE.ts
1351
+ async function DELETE4(config, init) {
1352
+ const yurl = new URL(init.request.url);
1353
+ const [inviteId, , tenantId] = yurl.pathname.split("/").reverse();
1354
+ if (!tenantId) {
1355
+ return new Response(null, { status: 404 });
1356
+ }
1357
+ init.method = "DELETE";
1358
+ const url = `${apiRoutes(config).INVITE(tenantId)}/${inviteId}`;
1359
+ return await request(url, init, config);
1360
+ }
1361
+
1362
+ // src/api/routes/tenants/[tenantId]/invite/[inviteId]/index.ts
1363
+ var key16 = "INVITE";
1364
+ async function route19(request2, config) {
1365
+ switch (request2.method) {
1366
+ case "DELETE":
1367
+ return await DELETE4(config, { request: request2 });
1368
+ default:
1369
+ return new Response("method not allowed", { status: 405 });
1370
+ }
1371
+ }
1372
+ function matches19(configRoutes, request2) {
1373
+ const url = new URL(request2.url);
1374
+ const [inviteId, , tenantId] = url.pathname.split("/").reverse();
1375
+ const route20 = configRoutes[key16].replace("{tenantId}", tenantId).replace("{inviteId}", inviteId);
1376
+ return urlMatches(request2.url, route20);
1377
+ }
1378
+
1379
+ // src/api/handlers/DELETE.ts
1380
+ function DELETER(configRoutes, config) {
1381
+ const { info, warn } = config.logger("[DELETE MATCHER]");
1382
+ return async function DELETE5(req) {
1383
+ if (matches19(configRoutes, req)) {
1384
+ info("matches tenant invite id");
1385
+ return route19(req, config);
1386
+ }
1387
+ if (matches18(configRoutes, req)) {
1388
+ info("matches tenant user");
1389
+ return route18(req, config);
1390
+ }
1391
+ if (matches3(configRoutes, req)) {
1392
+ info("matches tenant users");
1393
+ return route3(req, config);
1394
+ }
1395
+ if (matches6(configRoutes, req)) {
1396
+ info("matches tenants");
1397
+ return route6(req, config);
1398
+ }
1399
+ if (matches(configRoutes, req)) {
1400
+ info("matches me");
1401
+ return route(req, config);
1402
+ }
1403
+ warn("No DELETE routes matched");
1404
+ return new Response(null, { status: 404 });
1405
+ };
1406
+ }
1407
+
1408
+ // src/api/handlers/PUT.ts
1409
+ function PUTER(configRoutes, config) {
1410
+ const { info, warn } = config.logger("[PUT MATCHER]");
1411
+ return async function PUT6(req) {
1412
+ if (matches4(configRoutes, req)) {
1413
+ info("matches tenant invite");
1414
+ return route4(req, config);
1415
+ }
1416
+ if (matches18(configRoutes, req)) {
1417
+ info("matches tenant user");
1418
+ return route18(req, config);
1419
+ }
1420
+ if (matches3(configRoutes, req)) {
1421
+ info("matches tenant users");
1422
+ return route3(req, config);
1423
+ }
1424
+ if (matches2(configRoutes, req)) {
1425
+ info("matches users");
1426
+ return route2(req, config);
1427
+ }
1428
+ if (matches(configRoutes, req)) {
1429
+ info("matches me");
1430
+ return route(req, config);
1431
+ }
1432
+ if (matches6(configRoutes, req)) {
1433
+ info("matches tenants");
1434
+ return route6(req, config);
1435
+ }
1436
+ if (matches15(configRoutes, req)) {
1437
+ info("matches reset password");
1438
+ return route15(req, config);
1439
+ }
1440
+ warn("No PUT routes matched");
1441
+ return new Response(null, { status: 404 });
1442
+ };
1443
+ }
1444
+
1445
+ // src/api/handlers/index.ts
1446
+ function Handlers(configRoutes, config) {
1447
+ const GET7 = GETTER(configRoutes, config);
1448
+ const POST6 = POSTER(configRoutes, config);
1449
+ const DELETE5 = DELETER(configRoutes, config);
1450
+ const PUT6 = PUTER(configRoutes, config);
1451
+ return {
1452
+ GET: GET7,
1453
+ POST: POST6,
1454
+ DELETE: DELETE5,
1455
+ PUT: PUT6
1456
+ };
1457
+ }
1458
+ var getApiUrl = (cfg) => {
1459
+ const { config } = cfg;
1460
+ if (config?.apiUrl != null) {
1461
+ return config?.apiUrl;
1462
+ }
1463
+ if (stringCheck(process.env.NILEDB_API_URL)) {
1464
+ return process.env.NILEDB_API_URL;
1465
+ }
1466
+ throw new Error(
1467
+ "A connection to nile-auth is required. Set NILEDB_API_URL as an environment variable."
1468
+ );
1469
+ };
1470
+ var getCallbackUrl = (cfg) => {
1471
+ const { config } = cfg;
1472
+ if (stringCheck(config?.callbackUrl)) {
1473
+ return config?.callbackUrl;
1474
+ }
1475
+ return process.env.NILEDB_CALLBACK_URL;
1476
+ };
1477
+ var getSecureCookies = (cfg) => {
1478
+ const { config } = cfg;
1479
+ if (config?.secureCookies != null) {
1480
+ return config?.secureCookies;
1481
+ }
1482
+ if (stringCheck(process.env.NILEDB_SECURECOOKIES)) {
1483
+ return Boolean(process.env.NILEDB_SECURECOOKIES);
1484
+ }
1485
+ return void 0;
1486
+ };
1487
+ var getUsername = (cfg) => {
1488
+ const { config } = cfg;
1489
+ const logger = config.logger;
1490
+ const { info } = logger();
1491
+ if (config?.user) {
1492
+ info(`[config] ${config.user}`);
1493
+ return String(config?.user);
1494
+ }
1495
+ const user = stringCheck(process.env.NILEDB_USER);
1496
+ if (user) {
1497
+ info(`[NILEDB_USER] ${user}`);
1498
+ return user;
1499
+ }
1500
+ const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
1501
+ if (pg2) {
1502
+ try {
1503
+ const url = new URL(pg2);
1504
+ if (url.username) {
1505
+ return url.username;
1506
+ }
1507
+ } catch (e) {
1508
+ }
1509
+ }
1510
+ throw new Error(
1511
+ "A database user is required. Set NILEDB_USER as an environment variable."
1512
+ );
1513
+ };
1514
+ var getPassword = (cfg) => {
1515
+ const { config } = cfg;
1516
+ const logger = config.logger;
1517
+ const log = logProtector(logger);
1518
+ if (stringCheck(config?.password)) {
1519
+ log && log("[config]").info("***");
1520
+ return String(config?.password);
1521
+ }
1522
+ const pass = stringCheck(process.env.NILEDB_PASSWORD);
1523
+ if (pass) {
1524
+ logger("[NILEDB_PASSWORD]").info("***");
1525
+ return pass;
1526
+ }
1527
+ const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
1528
+ if (pg2) {
1529
+ try {
1530
+ const url = new URL(pg2);
1531
+ if (url.password) {
1532
+ return url.password;
1533
+ }
1534
+ } catch (e) {
1535
+ }
1536
+ }
1537
+ throw new Error(
1538
+ "A database password is required. Set NILEDB_PASSWORD as an environment variable."
1539
+ );
1540
+ };
1541
+ var getDatabaseName = (cfg) => {
1542
+ const { config } = cfg;
1543
+ const { info } = config.logger("[databaseName]");
1544
+ if (stringCheck(config?.databaseName)) {
1545
+ info(`[config] ${config?.databaseName}`);
1546
+ return String(config?.databaseName);
1547
+ }
1548
+ const name = stringCheck(process.env.NILEDB_NAME);
1549
+ if (name) {
1550
+ info(`[NILEDB_NAME] ${name}`);
1551
+ return name;
1552
+ }
1553
+ if (process.env.NILEDB_POSTGRES_URL) {
1554
+ try {
1555
+ const pgUrl = new URL(process.env.NILEDB_POSTGRES_URL);
1556
+ return pgUrl.pathname.substring(1);
1557
+ } catch (e) {
1558
+ }
1559
+ }
1560
+ throw new Error(
1561
+ "A database name is required. Set NILEDB_PASSWORD as an environment variable."
1562
+ );
1563
+ };
1564
+ var getTenantId = (cfg) => {
1565
+ const { config } = cfg;
1566
+ const { info } = config.logger("[tenantId]");
1567
+ if (stringCheck(config?.tenantId)) {
1568
+ info(`[config] ${config?.tenantId}`);
1569
+ return String(config?.tenantId);
1570
+ }
1571
+ if (stringCheck(process.env.NILEDB_TENANT)) {
1572
+ info(`[NILEDB_TENANT] ${process.env.NILEDB_TENANT}`);
1573
+ return String(process.env.NILEDB_TENANT);
1574
+ }
1575
+ return null;
1576
+ };
1577
+ function getDbHost(cfg) {
1578
+ const { config } = cfg;
1579
+ const logger = config.logger;
1580
+ const { info } = logger("[db.host]");
1581
+ if (stringCheck(config?.db && config.db.host)) {
1582
+ info(`[config] ${config?.db?.host}`);
1583
+ return String(config?.db?.host);
1584
+ }
1585
+ if (stringCheck(process.env.NILEDB_HOST)) {
1586
+ info(`[NILEDB_HOST] ${process.env.NILEDB_HOST}`);
1587
+ return process.env.NILEDB_HOST;
1588
+ }
1589
+ const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
1590
+ if (pg2) {
1591
+ try {
1592
+ const pgUrl = new URL(pg2);
1593
+ info(`[NILEDB_POSTGRES_URL] ${pgUrl.hostname}`);
1594
+ return pgUrl.hostname;
1595
+ } catch (e) {
1596
+ }
1597
+ }
1598
+ info("[default] db.thenile.dev");
1599
+ return "db.thenile.dev";
1600
+ }
1601
+ function getDbPort(cfg) {
1602
+ const { config } = cfg;
1603
+ const logger = config.logger;
1604
+ const { info } = logger("[db.port]");
1605
+ if (config?.db?.port && config.db.port != null) {
1606
+ info(`[config] ${config?.db.port}`);
1607
+ return Number(config.db?.port);
1608
+ }
1609
+ if (stringCheck(process.env.NILEDB_PORT)) {
1610
+ info(`[NILEDB_PORT] ${process.env.NILEDB_PORT}`);
1611
+ return Number(process.env.NILEDB_PORT);
1612
+ }
1613
+ const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
1614
+ if (pg2) {
1615
+ try {
1616
+ const pgUrl = new URL(pg2);
1617
+ if (pgUrl.port) {
1618
+ return Number(pgUrl.port);
1619
+ }
1620
+ } catch (e) {
1621
+ }
1622
+ }
1623
+ info("[default] 5432");
1624
+ return 5432;
1625
+ }
1626
+ var logProtector = (logger) => {
1627
+ return process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test" ? logger : null;
1628
+ };
1629
+ var stringCheck = (str) => {
1630
+ if (str && str !== "") {
1631
+ return str;
1632
+ }
1633
+ return;
1634
+ };
1635
+
1636
+ // src/utils/Config/index.ts
1637
+ var Config = class {
1638
+ routes;
1639
+ handlers;
1640
+ paths;
1641
+ extensionCtx;
1642
+ extensions;
1643
+ logger;
1644
+ /**
1645
+ * Stores the set tenant id from Server for use in sub classes
1646
+ */
1647
+ tenantId;
1648
+ /**
1649
+ * Stores the set user id from Server for use in sub classes
1650
+ */
1651
+ userId;
1652
+ /**
1653
+ * Stores the headers to be used in `fetch` calls
1654
+ */
1655
+ headers;
1656
+ /**
1657
+ * The nile-auth url
1658
+ */
1659
+ apiUrl;
1660
+ origin;
1661
+ /**
1662
+ * important for separating the `origin` config value from a default in order to make requests
1663
+ */
1664
+ serverOrigin;
1665
+ debug;
1666
+ /**
1667
+ * To use secure cookies or not in the fetch
1668
+ */
1669
+ secureCookies;
1670
+ callbackUrl;
1671
+ /**
1672
+ * change the starting route
1673
+ */
1674
+ routePrefix;
1675
+ db;
1676
+ constructor(config) {
1677
+ this.routePrefix = config?.routePrefix ?? "/api";
1678
+ this.debug = config?.debug;
1679
+ this.origin = config?.origin;
1680
+ this.extensions = config?.extensions;
1681
+ this.extensionCtx = config?.extensionCtx;
1682
+ this.serverOrigin = config?.origin ?? "http://localhost:3000";
1683
+ this.logger = Logger(config);
1684
+ const envVarConfig = {
1685
+ config: { ...config, logger: this.logger }
1686
+ };
1687
+ this.secureCookies = getSecureCookies(envVarConfig);
1688
+ this.callbackUrl = getCallbackUrl(envVarConfig);
1689
+ this.apiUrl = getApiUrl(envVarConfig);
1690
+ const user = getUsername(envVarConfig);
1691
+ const password = getPassword(envVarConfig);
1692
+ const databaseName = getDatabaseName(envVarConfig);
1693
+ const { host, port, ...dbConfig } = config?.db ?? {};
1694
+ const configuredHost = host ?? getDbHost(envVarConfig);
1695
+ const configuredPort = port ?? getDbPort(envVarConfig);
1696
+ this.db = {
1697
+ user,
1698
+ password,
1699
+ host: configuredHost,
1700
+ port: configuredPort,
1701
+ ...dbConfig
1702
+ };
1703
+ if (databaseName) {
1704
+ this.db.database = databaseName;
1705
+ }
1706
+ if (config?.headers) {
1707
+ this.headers = config?.headers;
1708
+ } else {
1709
+ this.headers = new Headers();
1710
+ }
1711
+ this.routes = {
1712
+ ...appRoutes(config?.routePrefix),
1713
+ ...config?.routes
1714
+ };
1715
+ this.handlers = Handlers(this.routes, this);
1716
+ this.paths = {
1717
+ get: [
1718
+ this.routes.ME,
1719
+ this.routes.TENANT_USERS,
1720
+ this.routes.TENANTS,
1721
+ this.routes.TENANT,
1722
+ this.routes.SESSION,
1723
+ this.routes.SIGNIN,
1724
+ this.routes.PROVIDERS,
1725
+ this.routes.CSRF,
1726
+ this.routes.PASSWORD_RESET,
1727
+ this.routes.CALLBACK,
1728
+ this.routes.SIGNOUT,
1729
+ this.routes.VERIFY_REQUEST,
1730
+ this.routes.ERROR
1731
+ ],
1732
+ post: [
1733
+ this.routes.TENANT_USERS,
1734
+ this.routes.SIGNUP,
1735
+ this.routes.USERS,
1736
+ this.routes.TENANTS,
1737
+ this.routes.SESSION,
1738
+ `${this.routes.SIGNIN}/{provider}`,
1739
+ this.routes.PASSWORD_RESET,
1740
+ this.routes.PROVIDERS,
1741
+ this.routes.CSRF,
1742
+ `${this.routes.CALLBACK}/{provider}`,
1743
+ this.routes.SIGNOUT
1744
+ ],
1745
+ put: [
1746
+ this.routes.TENANT_USERS,
1747
+ this.routes.USERS,
1748
+ this.routes.TENANT,
1749
+ this.routes.PASSWORD_RESET
1750
+ ],
1751
+ delete: [this.routes.TENANT_USER, this.routes.TENANT]
1752
+ };
1753
+ this.tenantId = config?.tenantId;
1754
+ this.userId = config?.userId;
1755
+ }
1756
+ };
1757
+
1758
+ // src/utils/Event/index.ts
1759
+ var Eventer = class {
1760
+ events = {};
1761
+ publish(eventName, value) {
1762
+ const callbacks = this.events[eventName];
1763
+ if (callbacks) {
1764
+ for (const callback of callbacks) {
1765
+ callback(value);
1766
+ }
1767
+ }
1768
+ }
1769
+ subscribe(eventName, callback) {
1770
+ if (!this.events[eventName]) {
1771
+ this.events[eventName] = [];
1772
+ }
1773
+ this.events[eventName].push(callback);
1774
+ }
1775
+ unsubscribe(eventName, callback) {
1776
+ const callbacks = this.events[eventName];
1777
+ if (!callbacks) return;
1778
+ const index = callbacks.indexOf(callback);
1779
+ if (index !== -1) {
1780
+ callbacks.splice(index, 1);
1781
+ }
1782
+ if (callbacks.length === 0) {
1783
+ delete this.events[eventName];
1784
+ }
1785
+ }
1786
+ };
1787
+ var eventer = new Eventer();
1788
+ var updateTenantId = (tenantId) => {
1789
+ eventer.publish("tenantId" /* Tenant */, tenantId);
1790
+ };
1791
+ var watchTenantId = (cb) => eventer.subscribe("tenantId" /* Tenant */, cb);
1792
+ var watchUserId = (cb) => eventer.subscribe("userId" /* User */, cb);
1793
+ var evictPool = (val) => {
1794
+ eventer.publish("EvictPool" /* EvictPool */, val);
1795
+ };
1796
+ var watchEvictPool = (cb) => eventer.subscribe("EvictPool" /* EvictPool */, cb);
1797
+ var updateHeaders = (val) => {
1798
+ eventer.publish("headers" /* Headers */, val);
1799
+ };
1800
+ var watchHeaders = (cb) => eventer.subscribe("headers" /* Headers */, cb);
1801
+
1802
+ // src/db/PoolProxy.ts
1803
+ function createProxyForPool(pool, config) {
1804
+ const { info, error } = config.logger("[pool]");
1805
+ return new Proxy(pool, {
1806
+ get(target, property) {
1807
+ if (property === "query") {
1808
+ if (!config.db.connectionString) {
1809
+ if (!config.db.user || !config.db.password) {
1810
+ error(
1811
+ "Cannot connect to the database. User and/or password are missing. Generate them at https://console.thenile.dev"
1812
+ );
1813
+ } else if (!config.db.database) {
1814
+ error(
1815
+ "Unable to obtain database name. Is process.env.NILEDB_POSTGRES_URL set?"
1816
+ );
1817
+ }
1818
+ }
1819
+ const caller = target[property];
1820
+ return function query(...args) {
1821
+ info("query", ...args);
1822
+ const called = caller.apply(this, args);
1823
+ return called;
1824
+ };
1825
+ }
1826
+ return target[property];
1827
+ }
1828
+ });
1829
+ }
1830
+
1831
+ // src/db/NileInstance.ts
1832
+ var NileDatabase = class {
1833
+ pool;
1834
+ tenantId;
1835
+ userId;
1836
+ id;
1837
+ config;
1838
+ timer;
1839
+ constructor(config, id) {
1840
+ const { warn, info, debug } = config.logger("[NileInstance]");
1841
+ this.id = id;
1842
+ const poolConfig = {
1843
+ min: 0,
1844
+ max: 10,
1845
+ idleTimeoutMillis: 3e4,
1846
+ ...config.db
1847
+ };
1848
+ const { afterCreate, ...remaining } = poolConfig;
1849
+ config.db = poolConfig;
1850
+ this.config = config;
1851
+ const cloned = { ...this.config.db };
1852
+ cloned.password = "***";
1853
+ debug(`Connection pool config ${JSON.stringify(cloned)}`);
1854
+ this.pool = createProxyForPool(new pg__default.default.Pool(remaining), this.config);
1855
+ if (typeof afterCreate === "function") {
1856
+ warn(
1857
+ "Providing an pool configuration will stop automatic tenant context setting."
1858
+ );
1859
+ }
1860
+ this.startTimeout();
1861
+ this.pool.on("connect", async (client) => {
1862
+ debug(`pool connected ${this.id}`);
1863
+ this.startTimeout();
1864
+ const afterCreate2 = makeAfterCreate(
1865
+ config,
1866
+ `${this.id}-${this.timer}`
1867
+ );
1868
+ afterCreate2(client, (err) => {
1869
+ const { error } = config.logger("[after create callback]");
1870
+ if (err) {
1871
+ clearTimeout(this.timer);
1872
+ error("after create failed", {
1873
+ message: err.message,
1874
+ stack: err.stack
1875
+ });
1876
+ evictPool(this.id);
1877
+ }
1878
+ });
1879
+ });
1880
+ this.pool.on("error", (err) => {
1881
+ clearTimeout(this.timer);
1882
+ info(`pool ${this.id} failed`, {
1883
+ message: err.message,
1884
+ stack: err.stack
1885
+ });
1886
+ evictPool(this.id);
1887
+ });
1888
+ this.pool.on("release", (destroy) => {
1889
+ if (destroy) {
1890
+ clearTimeout(this.timer);
1891
+ evictPool(this.id);
1892
+ debug(`destroying pool ${this.id}`);
1893
+ }
1894
+ });
1895
+ }
1896
+ startTimeout() {
1897
+ const { debug } = this.config.logger("[NileInstance]");
1898
+ if (this.timer) {
1899
+ clearTimeout(this.timer);
1900
+ }
1901
+ this.timer = setTimeout(() => {
1902
+ debug(
1903
+ `Pool reached idleTimeoutMillis. ${this.id} evicted after ${Number(this.config.db.idleTimeoutMillis) ?? 3e4}ms`
1904
+ );
1905
+ this.pool.end(() => {
1906
+ clearTimeout(this.timer);
1907
+ evictPool(this.id);
1908
+ });
1909
+ }, Number(this.config.db.idleTimeoutMillis) ?? 3e4);
1910
+ }
1911
+ shutdown() {
1912
+ const { debug } = this.config.logger("[NileInstance]");
1913
+ debug(`attempting to shut down ${this.id}`);
1914
+ clearTimeout(this.timer);
1915
+ this.pool.end(() => {
1916
+ debug(`${this.id} has been shut down`);
1917
+ });
1918
+ }
1919
+ };
1920
+ var NileInstance_default = NileDatabase;
1921
+ function makeAfterCreate(config, id) {
1922
+ const { error, warn, debug } = config.logger("[afterCreate]");
1923
+ return (conn, done) => {
1924
+ conn.on("error", function errorHandler(e) {
1925
+ error(`Connection ${id} was terminated by server`, {
1926
+ message: e.message,
1927
+ stack: e.stack
1928
+ });
1929
+ done(e, conn);
1930
+ });
1931
+ if (config.tenantId) {
1932
+ const query = [`SET nile.tenant_id = '${config.tenantId}'`];
1933
+ if (config.userId) {
1934
+ if (!config.tenantId) {
1935
+ warn("A user id cannot be set in context without a tenant id");
1936
+ }
1937
+ query.push(`SET nile.user_id = '${config.userId}'`);
1938
+ }
1939
+ conn.query(query.join(";"), function(err) {
1940
+ if (err) {
1941
+ error("query connection failed", {
1942
+ cause: err.cause,
1943
+ stack: err.stack,
1944
+ message: err.message,
1945
+ name: err.name,
1946
+ id
1947
+ });
1948
+ } else {
1949
+ if (query.length === 1) {
1950
+ debug(`connection context set: tenantId=${config.tenantId}`);
1951
+ }
1952
+ if (query.length === 2) {
1953
+ debug(
1954
+ `connection context set: tenantId=${config.tenantId} userId=${config.userId}`
1955
+ );
1956
+ }
1957
+ }
1958
+ done(err, conn);
1959
+ });
1960
+ }
1961
+ done(null, conn);
1962
+ };
1963
+ }
1964
+
1965
+ // src/db/DBManager.ts
1966
+ var DBManager = class {
1967
+ connections;
1968
+ cleared;
1969
+ poolWatcherFn;
1970
+ makeId(tenantId, userId) {
1971
+ if (tenantId && userId) {
1972
+ return `${tenantId}:${userId}`;
1973
+ }
1974
+ if (tenantId) {
1975
+ return `${tenantId}`;
1976
+ }
1977
+ return "base";
1978
+ }
1979
+ constructor(config) {
1980
+ this.cleared = false;
1981
+ this.connections = /* @__PURE__ */ new Map();
1982
+ this.poolWatcherFn = this.poolWatcher(config);
1983
+ watchEvictPool(this.poolWatcherFn);
1984
+ }
1985
+ poolWatcher = (config) => (id) => {
1986
+ const { info, warn } = Logger(config)("[DBManager]");
1987
+ if (id && this.connections.has(id)) {
1988
+ info(`Removing ${id} from db connection pool.`);
1989
+ const connection = this.connections.get(id);
1990
+ connection?.shutdown();
1991
+ this.connections.delete(id);
1992
+ } else {
1993
+ warn(`missed eviction of ${id}`);
1994
+ }
1995
+ };
1996
+ getConnection = (config) => {
1997
+ const { info } = Logger(config)("[DBManager]");
1998
+ const id = this.makeId(config.tenantId, config.userId);
1999
+ const existing = this.connections.get(id);
2000
+ info(`# of instances: ${this.connections.size}`);
2001
+ if (existing) {
2002
+ info(`returning existing ${id}`);
2003
+ existing.startTimeout();
2004
+ return existing.pool;
2005
+ }
2006
+ const newOne = new NileInstance_default(new Config(config), id);
2007
+ this.connections.set(id, newOne);
2008
+ info(`created new ${id}`);
2009
+ info(`# of instances: ${this.connections.size}`);
2010
+ if (this.cleared) {
2011
+ this.cleared = false;
2012
+ }
2013
+ return newOne.pool;
2014
+ };
2015
+ clear = (config) => {
2016
+ const { info } = Logger(config)("[DBManager]");
2017
+ info(`Clearing all connections ${this.connections.size}`);
2018
+ this.cleared = true;
2019
+ this.connections.forEach((connection) => {
2020
+ connection.shutdown();
2021
+ });
2022
+ this.connections.clear();
2023
+ };
2024
+ };
2025
+
2026
+ // src/auth/index.ts
2027
+ var Auth = class {
2028
+ #logger;
2029
+ #config;
2030
+ constructor(config) {
2031
+ this.#config = config;
2032
+ this.#logger = config.logger("[auth]");
2033
+ }
2034
+ async getSession(rawResponse = false) {
2035
+ const res = await fetchSession(this.#config);
2036
+ if (rawResponse) {
2037
+ return res;
2038
+ }
2039
+ try {
2040
+ const session = await res.clone().json();
2041
+ if (Object.keys(session).length === 0) {
2042
+ return void 0;
2043
+ }
2044
+ return session;
2045
+ } catch {
2046
+ return res;
1665
2047
  }
1666
- if (matches6(configRoutes, req)) {
1667
- info("matches session");
1668
- return route6(req, config);
2048
+ }
2049
+ async getCsrf(rawResponse = false) {
2050
+ return await obtainCsrf(this.#config, rawResponse);
2051
+ }
2052
+ async listProviders(rawResponse = false) {
2053
+ const res = await fetchProviders(this.#config);
2054
+ if (rawResponse) {
2055
+ return res;
1669
2056
  }
1670
- if (matches5(configRoutes, req)) {
1671
- info("matches signin");
1672
- return route5(req, config);
2057
+ try {
2058
+ return await res.clone().json();
2059
+ } catch {
2060
+ return res;
1673
2061
  }
1674
- if (matches13(configRoutes, req)) {
1675
- info("matches password reset");
1676
- return route13(req, config);
2062
+ }
2063
+ async signOut() {
2064
+ const csrfRes = await this.getCsrf();
2065
+ if (!("csrfToken" in csrfRes)) {
2066
+ throw new Error("Unable to obtain CSRF token. Sign out failed.");
1677
2067
  }
1678
- if (matches7(configRoutes, req)) {
1679
- info("matches providers");
1680
- return route7(req, config);
2068
+ const body = JSON.stringify({
2069
+ csrfToken: csrfRes.csrfToken,
2070
+ json: true
2071
+ });
2072
+ const res = await fetchSignOut(this.#config, body);
2073
+ updateHeaders(new Headers({}));
2074
+ this.#config.headers = new Headers();
2075
+ return res;
2076
+ }
2077
+ async signUp(payload, rawResponse) {
2078
+ this.#config.headers = new Headers();
2079
+ const { email, password, ...params } = payload;
2080
+ if (!email || !password) {
2081
+ throw new Error(
2082
+ "Server side sign up requires a user email and password."
2083
+ );
1681
2084
  }
1682
- if (matches8(configRoutes, req)) {
1683
- info("matches csrf");
1684
- return route8(req, config);
2085
+ const providers = await this.listProviders();
2086
+ const { credentials } = providers ?? {};
2087
+ if (!credentials) {
2088
+ throw new Error(
2089
+ "Unable to obtain credential provider. Aborting server side sign up."
2090
+ );
1685
2091
  }
1686
- if (matches9(configRoutes, req)) {
1687
- info("matches callback");
1688
- return route9(req, config);
2092
+ const csrf = await this.getCsrf();
2093
+ let csrfToken;
2094
+ if ("csrfToken" in csrf) {
2095
+ csrfToken = csrf.csrfToken;
2096
+ } else {
2097
+ throw new Error("Unable to obtain parse CSRF. Request blocked.");
1689
2098
  }
1690
- if (matches10(configRoutes, req)) {
1691
- info("matches signout");
1692
- return route10(req, config);
2099
+ const body = JSON.stringify({
2100
+ email,
2101
+ password,
2102
+ csrfToken,
2103
+ callbackUrl: credentials.callbackUrl
2104
+ });
2105
+ const res = await fetchSignUp(this.#config, { body, params });
2106
+ if (res.status > 299) {
2107
+ this.#logger.error(await res.clone().text());
2108
+ return void 0;
1693
2109
  }
1694
- warn("No POST routes matched");
1695
- return new Response(null, { status: 404 });
1696
- };
1697
- }
1698
-
1699
- // src/api/handlers/DELETE.ts
1700
- function DELETER(configRoutes, config) {
1701
- const { info, warn } = Logger(config, "[DELETE MATCHER]");
1702
- return async function DELETE3(req) {
1703
- if (matches3(configRoutes, req)) {
1704
- info("matches tenant users");
1705
- return route3(req, config);
2110
+ const token = parseToken(res.headers);
2111
+ if (!token) {
2112
+ throw new Error("Server side sign up failed. Session token not found");
1706
2113
  }
1707
- if (matches4(configRoutes, req)) {
1708
- info("matches tenants");
1709
- return route4(req, config);
2114
+ this.#config.headers?.append("cookie", token);
2115
+ updateHeaders(this.#config.headers);
2116
+ if (rawResponse) {
2117
+ return res;
1710
2118
  }
1711
- warn("No DELETE routes matched");
1712
- return new Response(null, { status: 404 });
1713
- };
1714
- }
1715
-
1716
- // src/api/handlers/PUT.ts
1717
- function PUTER(configRoutes, config) {
1718
- const { info, warn } = Logger(config, "[PUT MATCHER]");
1719
- return async function PUT4(req) {
1720
- if (matches3(configRoutes, req)) {
1721
- info("matches tenant users");
1722
- return route3(req, config);
2119
+ try {
2120
+ const json = await res.clone().json();
2121
+ if (json && typeof json === "object" && "tenants" in json) {
2122
+ const tenantId = json.tenants[0];
2123
+ if (tenantId) {
2124
+ updateTenantId(tenantId);
2125
+ }
2126
+ }
2127
+ return json;
2128
+ } catch {
2129
+ return res;
1723
2130
  }
1724
- if (matches2(configRoutes, req)) {
1725
- info("matches users");
1726
- return route2(req, config);
2131
+ }
2132
+ async forgotPassword(req) {
2133
+ let email = "";
2134
+ const defaults = defaultCallbackUrl({
2135
+ config: this.#config
2136
+ });
2137
+ let callbackUrl = defaults.callbackUrl;
2138
+ let redirectUrl = defaults.redirectUrl;
2139
+ if ("email" in req) {
2140
+ email = req.email;
1727
2141
  }
1728
- if (matches4(configRoutes, req)) {
1729
- info("matches tenants");
1730
- return route4(req, config);
2142
+ if ("callbackUrl" in req) {
2143
+ callbackUrl = req.callbackUrl ? req.callbackUrl : null;
1731
2144
  }
1732
- if (matches13(configRoutes, req)) {
1733
- info("matches reset password");
1734
- return route13(req, config);
2145
+ if ("redirectUrl" in req) {
2146
+ redirectUrl = req.redirectUrl ? req.redirectUrl : null;
1735
2147
  }
1736
- warn("No PUT routes matched");
1737
- return new Response(null, { status: 404 });
1738
- };
1739
- }
1740
-
1741
- // src/api/handlers/index.ts
1742
- function Handlers(configRoutes, config) {
1743
- const GET6 = GETTER(configRoutes, config);
1744
- const POST5 = POSTER(configRoutes, config);
1745
- const DELETE3 = DELETER(configRoutes, config);
1746
- const PUT4 = PUTER(configRoutes, config);
1747
- return {
1748
- GET: GET6,
1749
- POST: POST5,
1750
- DELETE: DELETE3,
1751
- PUT: PUT4
1752
- };
1753
- }
1754
-
1755
- // src/api/utils/routes/defaultRoutes.ts
1756
- var appRoutes = (prefix = "/api") => ({
1757
- SIGNIN: `${prefix}/auth/signin`,
1758
- PROVIDERS: `${prefix}/auth/providers`,
1759
- SESSION: `${prefix}/auth/session`,
1760
- CSRF: `${prefix}/auth/csrf`,
1761
- CALLBACK: `${prefix}/auth/callback`,
1762
- SIGNOUT: `${prefix}/auth/signout`,
1763
- ERROR: `${prefix}/auth/error`,
1764
- VERIFY_REQUEST: `${prefix}/auth/verify-request`,
1765
- PASSWORD_RESET: `${prefix}/auth/reset-password`,
1766
- ME: `${prefix}/me`,
1767
- USERS: `${prefix}/users`,
1768
- TENANTS: `${prefix}/tenants`,
1769
- TENANT: `${prefix}/tenants/{tenantId}`,
1770
- TENANT_USER: `${prefix}/tenants/{tenantId}/users/{userId}`,
1771
- TENANT_USERS: `${prefix}/tenants/{tenantId}/users`,
1772
- SIGNUP: `${prefix}/signup`,
1773
- LOG: `${prefix}/_log`
1774
- });
1775
-
1776
- // src/utils/Requester/index.ts
1777
- var Requester = class extends Config {
1778
- constructor(config) {
1779
- super(config);
1780
- }
1781
- async rawRequest(method, url, init, body) {
1782
- const _init = {
2148
+ const body = JSON.stringify({
2149
+ email,
2150
+ redirectUrl,
2151
+ callbackUrl
2152
+ });
2153
+ const data = await fetchResetPassword(
2154
+ this.#config,
2155
+ "POST",
1783
2156
  body,
1784
- method,
1785
- ...init
1786
- };
1787
- const res = await _fetch(this, url, _init);
1788
- if (res instanceof ResponseError) {
1789
- return res.response;
1790
- }
1791
- return res;
1792
- }
1793
- /**
1794
- * three options here
1795
- * 1) pass in headers for a server side request
1796
- * 2) pass in the payload that matches the api
1797
- * 3) pass in the request object sent by a browser
1798
- * @param method
1799
- * @param url
1800
- * @param req
1801
- * @param init
1802
- * @returns
1803
- */
1804
- async request(method, url, req, init) {
1805
- const headers = new Headers(init ? init?.headers : {});
1806
- if (req instanceof Headers) {
1807
- const tenantId = req.get(X_NILE_TENANT);
1808
- const cookie = req.get("cookie");
1809
- if (tenantId) {
1810
- headers.set(X_NILE_TENANT, tenantId);
2157
+ new URLSearchParams(),
2158
+ false
2159
+ );
2160
+ return data;
2161
+ }
2162
+ async resetPassword(req) {
2163
+ let email = "";
2164
+ let password = "";
2165
+ const defaults = defaultCallbackUrl({ config: this.#config });
2166
+ let callbackUrl = defaults.callbackUrl;
2167
+ let redirectUrl = defaults.redirectUrl;
2168
+ if (req instanceof Request) {
2169
+ const body2 = await req.json();
2170
+ email = body2.email;
2171
+ password = body2.password;
2172
+ const cbFromHeaders = parseCallback(req.headers);
2173
+ if (cbFromHeaders) {
2174
+ callbackUrl = cbFromHeaders;
1811
2175
  }
1812
- if (cookie) {
1813
- headers.set("cookie", cookie);
2176
+ if (body2.callbackUrl) {
2177
+ callbackUrl = body2.callbackUrl;
1814
2178
  }
1815
- } else if (req instanceof Request) {
1816
- const _headers = new Headers(req?.headers);
1817
- const tenantId = _headers.get(X_NILE_TENANT);
1818
- const cookie = _headers.get("cookie");
1819
- if (tenantId) {
1820
- headers.set(X_NILE_TENANT, tenantId);
2179
+ if (body2.redirectUrl) {
2180
+ redirectUrl = body2.redirectUrl;
1821
2181
  }
1822
- if (cookie) {
1823
- headers.set("cookie", cookie);
2182
+ } else {
2183
+ if ("email" in req) {
2184
+ email = req.email;
1824
2185
  }
1825
- }
1826
- let body = JSON.stringify(req);
1827
- if (method === "GET") {
1828
- body = void 0;
1829
- } else if (req instanceof Request) {
1830
- body = await new Response(req.body).text();
1831
- } else if (
1832
- // is just headers for a GET request
1833
- req instanceof Headers || JSON.stringify(req) === "{}" || req && typeof req === "object" && Object.values(req).length === 0
1834
- ) {
1835
- body = void 0;
1836
- }
1837
- const _init = {
1838
- ...init,
1839
- headers
1840
- };
1841
- return await this.rawRequest(method, url, _init, body);
1842
- }
1843
- async post(req, url, init) {
1844
- const response = await this.request("POST", url, req, init);
1845
- if (response && response.status >= 200 && response.status < 300) {
1846
- const cloned = response.clone();
1847
- try {
1848
- return await cloned.json();
1849
- } catch (e) {
2186
+ if ("password" in req) {
2187
+ password = req.password;
1850
2188
  }
1851
- }
1852
- return response;
1853
- }
1854
- async get(req, url, init, raw = false) {
1855
- const response = await this.request("GET", url, req, init);
1856
- if (raw) {
1857
- return response;
1858
- }
1859
- if (response && response.status >= 200 && response.status < 300) {
1860
- const cloned = response.clone();
1861
- try {
1862
- return await cloned.json();
1863
- } catch (e) {
2189
+ if ("callbackUrl" in req) {
2190
+ callbackUrl = req.callbackUrl ? req.callbackUrl : null;
2191
+ }
2192
+ if ("redirectUrl" in req) {
2193
+ redirectUrl = req.redirectUrl ? req.redirectUrl : null;
1864
2194
  }
1865
2195
  }
1866
- return response;
1867
- }
1868
- async put(req, url, init) {
1869
- const response = await this.request("PUT", url, req, init);
1870
- if (response && response.status >= 200 && response.status < 300) {
1871
- const cloned = response.clone();
1872
- try {
1873
- return await cloned.json();
1874
- } catch (e) {
2196
+ await this.getCsrf();
2197
+ const body = JSON.stringify({
2198
+ email,
2199
+ password,
2200
+ redirectUrl,
2201
+ callbackUrl
2202
+ });
2203
+ let urlWithParams;
2204
+ try {
2205
+ const data = await fetchResetPassword(this.#config, "POST", body);
2206
+ const cloned = data.clone();
2207
+ if (data.status === 400) {
2208
+ const text = await cloned.text();
2209
+ this.#logger.error(text);
2210
+ return data;
1875
2211
  }
2212
+ const { url } = await data.json();
2213
+ urlWithParams = url;
2214
+ } catch {
1876
2215
  }
1877
- return response;
1878
- }
1879
- async delete(req, url, init) {
1880
- const response = await this.request("DELETE", url, req, init);
1881
- return response;
1882
- }
1883
- };
1884
-
1885
- // src/auth/index.ts
1886
- function serverLogin(config, handlers) {
1887
- const ORIGIN = config.api.origin ?? "http://localhost:3000";
1888
- const { info, error, debug } = Logger(config, "[server side login]");
1889
- const routes = appRoutes(config.api.routePrefix);
1890
- return async function login({
1891
- email,
1892
- password
1893
- }) {
1894
- if (!email || !password) {
1895
- throw new Error("Server side login requires a user email and password.");
2216
+ let token;
2217
+ try {
2218
+ const worthyParams = new URL(urlWithParams).searchParams;
2219
+ const answer = await fetchResetPassword(
2220
+ this.#config,
2221
+ "GET",
2222
+ null,
2223
+ worthyParams
2224
+ );
2225
+ token = parseResetToken(answer.headers);
2226
+ } catch {
2227
+ this.#logger.warn(
2228
+ "Unable to parse reset password url. Password not reset."
2229
+ );
1896
2230
  }
1897
- const sessionUrl = new URL(`${ORIGIN}${routes.PROVIDERS}`);
1898
- const baseHeaders = {
1899
- host: sessionUrl.host,
1900
- [X_NILE_ORIGIN]: ORIGIN
1901
- };
1902
- info(`Obtaining providers for ${email}`);
1903
- const sessionReq = new Request(sessionUrl, {
1904
- method: "GET",
1905
- ...baseHeaders
2231
+ const cookie = this.#config.headers.get("cookie")?.split("; ");
2232
+ if (token) {
2233
+ cookie?.push(token);
2234
+ } else {
2235
+ throw new Error(
2236
+ "Unable to reset password, reset token is missing from response"
2237
+ );
2238
+ }
2239
+ this.#config.headers = new Headers({
2240
+ ...this.#config.headers,
2241
+ cookie: cookie?.join("; ")
1906
2242
  });
1907
- const sessionRes = await handlers.POST(sessionReq);
1908
- if (sessionRes?.status === 404) {
1909
- throw new Error("Unable to login, cannot find region api.");
2243
+ const res = await fetchResetPassword(this.#config, "PUT", body);
2244
+ cookie?.pop();
2245
+ const cleaned = cookie?.filter((c) => !c.includes("nile.session")) ?? [];
2246
+ cleaned.push(String(parseToken(res.headers)));
2247
+ const updatedHeaders = new Headers({ cookie: cleaned.join("; ") });
2248
+ updateHeaders(updatedHeaders);
2249
+ return res;
2250
+ }
2251
+ async callback(provider, body) {
2252
+ if (body instanceof Request) {
2253
+ this.#config.headers = body.headers;
2254
+ return await fetchCallback(
2255
+ this.#config,
2256
+ provider,
2257
+ void 0,
2258
+ body,
2259
+ "GET"
2260
+ );
1910
2261
  }
1911
- let providers;
1912
- try {
1913
- providers = await sessionRes?.json();
1914
- } catch (e) {
1915
- info(sessionUrl, { sessionRes });
1916
- error(e);
2262
+ return await fetchCallback(this.#config, provider, body);
2263
+ }
2264
+ async signIn(provider, payload, rawResponse) {
2265
+ if (payload instanceof Request) {
2266
+ const body2 = new URLSearchParams(await payload.text());
2267
+ const origin = new URL(payload.url).origin;
2268
+ const payloadUrl = body2?.get("callbackUrl");
2269
+ const csrfToken2 = body2?.get("csrfToken");
2270
+ const callbackUrl = `${!payloadUrl?.startsWith("http") ? origin : ""}${payloadUrl}`;
2271
+ if (!csrfToken2) {
2272
+ throw new Error(
2273
+ "CSRF token in missing from request. Request it by the client before calling sign in"
2274
+ );
2275
+ }
2276
+ this.#config.headers = new Headers(payload.headers);
2277
+ this.#config.headers.set(
2278
+ "Content-Type",
2279
+ "application/x-www-form-urlencoded"
2280
+ );
2281
+ const params = new URLSearchParams({
2282
+ csrfToken: csrfToken2,
2283
+ json: String(true)
2284
+ });
2285
+ if (payloadUrl) {
2286
+ params.set("callbackUrl", callbackUrl);
2287
+ }
2288
+ return await fetchSignIn(this.#config, provider, params);
1917
2289
  }
2290
+ this.#config.headers = new Headers();
2291
+ const { info, error } = this.#logger;
2292
+ const providers = await this.listProviders();
1918
2293
  info("Obtaining csrf");
1919
- const csrf = new URL(`${ORIGIN}${routes.CSRF}`);
1920
- const csrfReq = new Request(csrf, {
1921
- method: "GET",
1922
- headers: new Headers({
1923
- ...baseHeaders
1924
- })
1925
- });
1926
- const csrfRes = await handlers.POST(csrfReq);
2294
+ const csrf = await this.getCsrf();
1927
2295
  let csrfToken;
1928
- try {
1929
- const json = await csrfRes?.json() ?? {};
1930
- csrfToken = json?.csrfToken;
1931
- } catch (e) {
1932
- info(sessionUrl, { csrfRes });
1933
- error(e, { csrfRes });
2296
+ if ("csrfToken" in csrf) {
2297
+ csrfToken = csrf.csrfToken;
2298
+ } else {
2299
+ throw new Error("Unable to obtain parse CSRF. Request blocked.");
1934
2300
  }
1935
2301
  const { credentials } = providers ?? {};
1936
- const csrfCookie = csrfRes?.headers.get("set-cookie");
1937
2302
  if (!credentials) {
1938
2303
  throw new Error(
1939
- "Unable to obtain credential provider. Aborting server side login."
2304
+ "Unable to obtain credential provider. Aborting server side sign in."
1940
2305
  );
1941
2306
  }
1942
- const signInUrl = new URL(credentials.callbackUrl);
1943
- if (!csrfCookie) {
1944
- debug("CSRF failed", { headers: csrfRes?.headers });
1945
- throw new Error("Unable to authenticate REST, CSRF missing.");
2307
+ const { email, password } = payload ?? {};
2308
+ if (provider === "email" && (!email || !password)) {
2309
+ throw new Error(
2310
+ "Server side sign in requires a user email and password."
2311
+ );
1946
2312
  }
1947
- info(`Attempting sign in with email ${email} ${signInUrl.href}`);
2313
+ info(`Obtaining providers for ${email}`);
2314
+ info(`Attempting sign in with email ${email}`);
1948
2315
  const body = JSON.stringify({
1949
2316
  email,
1950
2317
  password,
1951
2318
  csrfToken,
1952
2319
  callbackUrl: credentials.callbackUrl
1953
2320
  });
1954
- const postReq = new Request(signInUrl, {
1955
- method: "POST",
1956
- headers: new Headers({
1957
- ...baseHeaders,
1958
- "content-type": "application/json",
1959
- cookie: csrfCookie.split(",").join("; ")
1960
- }),
1961
- body
1962
- });
1963
- const loginRes = await handlers.POST(postReq);
1964
- const authCookie = loginRes?.headers.get("set-cookie");
2321
+ const signInRes = await this.callback(provider, body);
2322
+ const authCookie = signInRes?.headers.get("set-cookie");
1965
2323
  if (!authCookie) {
1966
2324
  throw new Error("authentication failed");
1967
2325
  }
1968
- const token = parseToken(loginRes?.headers);
2326
+ const token = parseToken(signInRes?.headers);
2327
+ const possibleError = signInRes?.headers.get("location");
2328
+ if (possibleError) {
2329
+ let urlError;
2330
+ try {
2331
+ urlError = new URL(possibleError).searchParams.get("error");
2332
+ } catch {
2333
+ }
2334
+ if (urlError) {
2335
+ error("Unable to log user in", { error: urlError });
2336
+ return new Response(urlError, { status: signInRes.status });
2337
+ }
2338
+ }
1969
2339
  if (!token) {
1970
- error("Unable to obtain auth token", { authCookie });
2340
+ error("Unable to obtain auth token", {
2341
+ authCookie,
2342
+ signInRes
2343
+ });
1971
2344
  throw new Error("Server login failed");
1972
2345
  }
1973
- info("Server login successful", { authCookie, csrfCookie });
1974
- const headers = new Headers({
1975
- ...baseHeaders,
1976
- cookie: [token, csrfCookie].join("; ")
1977
- });
1978
- return [headers, loginRes];
1979
- };
2346
+ info("Server sign in successful", { authCookie });
2347
+ const setCookie = signInRes.headers.get("set-cookie");
2348
+ if (setCookie) {
2349
+ const cookie = [
2350
+ parseCSRF(this.#config.headers),
2351
+ parseCallback(signInRes.headers),
2352
+ parseToken(signInRes.headers)
2353
+ ].filter(Boolean).join("; ");
2354
+ updateHeaders(new Headers({ cookie }));
2355
+ } else {
2356
+ error("Unable to set context after sign in", {
2357
+ headers: signInRes.headers
2358
+ });
2359
+ }
2360
+ if (rawResponse) {
2361
+ return signInRes;
2362
+ }
2363
+ try {
2364
+ return await signInRes.clone().json();
2365
+ } catch {
2366
+ return signInRes;
2367
+ }
2368
+ }
2369
+ };
2370
+ function parseCSRF(headers) {
2371
+ let cookie = headers?.get("set-cookie");
2372
+ if (!cookie) {
2373
+ cookie = headers?.get("cookie");
2374
+ }
2375
+ if (!cookie) {
2376
+ return void 0;
2377
+ }
2378
+ const [, token] = /((__Secure-)?nile\.csrf-token=[^;]+)/.exec(cookie) ?? [];
2379
+ return token;
2380
+ }
2381
+ function parseCallback(headers) {
2382
+ let cookie = headers?.get("set-cookie");
2383
+ if (!cookie) {
2384
+ cookie = headers?.get("cookie");
2385
+ }
2386
+ if (!cookie) {
2387
+ return void 0;
2388
+ }
2389
+ const [, token] = /((__Secure-)?nile\.callback-url=[^;]+)/.exec(cookie) ?? [];
2390
+ return token;
1980
2391
  }
1981
2392
  function parseToken(headers) {
1982
2393
  let authCookie = headers?.get("set-cookie");
@@ -1989,604 +2400,700 @@ function parseToken(headers) {
1989
2400
  const [, token] = /((__Secure-)?nile\.session-token=[^;]+)/.exec(authCookie) ?? [];
1990
2401
  return token;
1991
2402
  }
1992
- var Auth = class extends Config {
1993
- headers;
1994
- resetHeaders;
1995
- constructor(config, headers, params) {
1996
- super(config);
1997
- this.logger = Logger(config, "[auth]");
1998
- this.headers = headers;
1999
- this.logger = Logger(config, "[auth]");
2000
- this.resetHeaders = params?.resetHeaders;
2001
- }
2002
- handleHeaders(init) {
2003
- if (this.headers) {
2004
- const cburl = getCallbackUrl2(this.headers);
2005
- if (cburl) {
2006
- try {
2007
- this.headers.set(X_NILE_ORIGIN, new URL(cburl).origin);
2008
- } catch (e) {
2009
- if (this.logger?.debug) {
2010
- this.logger.debug("Invalid URL supplied by cookie header");
2011
- }
2012
- }
2013
- }
2014
- if (init) {
2015
- init.headers = new Headers({ ...this.headers, ...init?.headers });
2016
- return init;
2017
- } else {
2018
- init = {
2019
- headers: this.headers
2020
- };
2021
- return init;
2022
- }
2023
- }
2403
+ function parseResetToken(headers) {
2404
+ let authCookie = headers?.get("set-cookie");
2405
+ if (!authCookie) {
2406
+ authCookie = headers?.get("cookie");
2407
+ }
2408
+ if (!authCookie) {
2024
2409
  return void 0;
2025
2410
  }
2026
- get sessionUrl() {
2027
- return "/auth/session";
2411
+ const [, token] = /((__Secure-)?nile\.reset=[^;]+)/.exec(authCookie) ?? [];
2412
+ return token;
2413
+ }
2414
+ function defaultCallbackUrl({ config }) {
2415
+ let cb = null;
2416
+ let redirect = null;
2417
+ const fallbackCb = parseCallback(config.headers);
2418
+ if (fallbackCb) {
2419
+ const [, value] = fallbackCb.split("=");
2420
+ cb = decodeURIComponent(value);
2421
+ if (value) {
2422
+ redirect = `${new URL(cb).origin}${"/auth/reset-password" /* PASSWORD_RESET */}`;
2423
+ }
2028
2424
  }
2029
- getSession = async (req, init) => {
2030
- const _requester = new Requester(this);
2031
- const _init = this.handleHeaders(init);
2032
- const session = await _requester.get(req, this.sessionUrl, _init);
2033
- if (Object.keys(session).length === 0) {
2034
- return void 0;
2425
+ return { callbackUrl: cb, redirectUrl: redirect };
2426
+ }
2427
+
2428
+ // src/auth/obtainCsrf.ts
2429
+ async function obtainCsrf(config, rawResponse = false) {
2430
+ const res = await fetchCsrf(config);
2431
+ const csrfCook = parseCSRF(res.headers);
2432
+ if (csrfCook) {
2433
+ const [, value] = csrfCook.split("=");
2434
+ const [token] = decodeURIComponent(value).split("|");
2435
+ const setCookie = res.headers.get("set-cookie");
2436
+ if (setCookie) {
2437
+ const cookie = [
2438
+ csrfCook,
2439
+ parseCallback(res.headers),
2440
+ parseToken(res.headers)
2441
+ ].filter(Boolean).join("; ");
2442
+ config.headers.set("cookie", cookie);
2443
+ updateHeaders(new Headers({ cookie }));
2444
+ }
2445
+ if (!rawResponse) {
2446
+ return { csrfToken: token };
2035
2447
  }
2036
- return session;
2037
- };
2038
- get getCsrfUrl() {
2039
- return "/auth/csrf";
2448
+ } else {
2449
+ const existingCookie = config.headers.get("cookie");
2450
+ const cookieParts = [];
2451
+ if (existingCookie) {
2452
+ cookieParts.push(
2453
+ parseToken(config.headers),
2454
+ parseCallback(config.headers)
2455
+ );
2456
+ }
2457
+ if (csrfCook) {
2458
+ cookieParts.push(csrfCook);
2459
+ } else {
2460
+ cookieParts.push(parseCSRF(config.headers));
2461
+ }
2462
+ const cookie = cookieParts.filter(Boolean).join("; ");
2463
+ config.headers.set("cookie", cookie);
2464
+ updateHeaders(new Headers({ cookie }));
2040
2465
  }
2041
- async getCsrf(req, init, raw = false) {
2042
- const _requester = new Requester(this);
2043
- const _init = this.handleHeaders(init);
2044
- return await _requester.get(req, this.getCsrfUrl, _init, raw);
2466
+ if (rawResponse) {
2467
+ return res;
2045
2468
  }
2046
- get listProvidersUrl() {
2047
- return "/auth/providers";
2469
+ try {
2470
+ return await res.clone().json();
2471
+ } catch {
2472
+ return res;
2048
2473
  }
2049
- listProviders = async (req, init) => {
2050
- const _requester = new Requester(this);
2051
- const _init = this.handleHeaders(init);
2052
- return await _requester.get(req, this.listProvidersUrl, _init);
2053
- };
2054
- get signOutUrl() {
2055
- return "/auth/signout";
2056
- }
2057
- signOut = async (req, init) => {
2058
- const _requester = new Requester(this);
2059
- const _init = this.handleHeaders(init);
2060
- const csrf = await this.getCsrf(
2061
- req,
2062
- void 0,
2063
- true
2064
- );
2065
- const csrfHeader = getCsrfToken(csrf.headers, this.headers);
2066
- const callbackUrl = req && "callbackUrl" in req ? String(req.callbackUrl) : "/";
2067
- if (!csrfHeader) {
2068
- this.logger?.debug && this.logger.debug("Request blocked from invalid csrf header");
2069
- return new Response("Request blocked", { status: 400 });
2070
- }
2071
- const headers = new Headers(_init?.headers);
2072
- const { csrfToken } = await csrf.json() ?? {};
2073
- const cooks = getCookies(headers);
2074
- if (csrfHeader) {
2075
- if (cooks["__Secure-nile.csrf-token"]) {
2076
- cooks["__Secure-nile.csrf-token"] = encodeURIComponent(csrfHeader);
2077
- }
2078
- if (cooks["nile.csrf-token"]) {
2079
- cooks["nile.csrf-token"] = encodeURIComponent(csrfHeader);
2474
+ }
2475
+
2476
+ // src/users/index.ts
2477
+ var Users = class {
2478
+ #config;
2479
+ #logger;
2480
+ constructor(config) {
2481
+ this.#config = config;
2482
+ this.#logger = config.logger("[me]");
2483
+ }
2484
+ async updateSelf(req, rawResponse) {
2485
+ const res = await fetchMe(this.#config, "PUT", JSON.stringify(req));
2486
+ if (rawResponse) {
2487
+ return res;
2488
+ }
2489
+ try {
2490
+ return await res?.clone().json();
2491
+ } catch {
2492
+ return res;
2493
+ }
2494
+ }
2495
+ async removeSelf() {
2496
+ const me = await this.getSelf();
2497
+ if ("id" in me) {
2498
+ this.#config.userId = me.id;
2499
+ }
2500
+ const res = await fetchMe(this.#config, "DELETE");
2501
+ updateHeaders(new Headers());
2502
+ return res;
2503
+ }
2504
+ async getSelf(rawResponse) {
2505
+ const res = await fetchMe(this.#config);
2506
+ if (rawResponse) {
2507
+ return res;
2508
+ }
2509
+ try {
2510
+ return await res?.clone().json();
2511
+ } catch {
2512
+ return res;
2513
+ }
2514
+ }
2515
+ async verifySelf(options, rawResponse = false) {
2516
+ const bypassEmail = typeof options === "object" ? options.bypassEmail ?? process.env.NODE_ENV !== "production" : process.env.NODE_ENV !== "production";
2517
+ const callbackUrl = typeof options === "object" ? options.callbackUrl : defaultCallbackUrl2(this.#config).callbackUrl;
2518
+ let res;
2519
+ try {
2520
+ const me = await this.getSelf();
2521
+ if (me instanceof Response) {
2522
+ return me;
2080
2523
  }
2081
- }
2082
- headers.set(
2083
- "cookie",
2084
- Object.keys(cooks).map((key12) => `${key12}=${cooks[key12]}`).join("; ")
2524
+ res = await verifyEmailAddress(this.#config, me, String(callbackUrl));
2525
+ return res;
2526
+ } catch {
2527
+ const message = "Unable to verify email.";
2528
+ this.#logger?.warn(message);
2529
+ res = new Response(message, { status: 400 });
2530
+ }
2531
+ if (bypassEmail) {
2532
+ res = this.updateSelf({ emailVerified: true }, rawResponse);
2533
+ }
2534
+ this.#logger.error(
2535
+ "Unable to verify email address. Configure your SMTP server in the console."
2085
2536
  );
2086
- const res = await _requester.post(req, this.signOutUrl, {
2087
- method: "post",
2088
- body: JSON.stringify({
2089
- csrfToken,
2090
- callbackUrl,
2091
- json: String(true)
2092
- }),
2093
- ..._init,
2094
- headers
2095
- });
2096
- this.resetHeaders && this.resetHeaders();
2097
2537
  return res;
2098
- };
2538
+ }
2099
2539
  };
2100
- function getCallbackUrl2(headers) {
2101
- if (headers) {
2102
- const cookies = getCookies(headers);
2103
- if (cookies) {
2104
- return cookies["__Secure-nile.callback-url"] || cookies["nile.callback-url"];
2105
- }
2540
+ async function verifyEmailAddress(config, user, callback) {
2541
+ config.headers.set("content-type", "application/x-www-form-urlencoded");
2542
+ const { csrfToken } = await obtainCsrf(config);
2543
+ const defaults = defaultCallbackUrl2(config);
2544
+ const callbackUrl = callback ?? String(defaults.callbackUrl);
2545
+ const res = await fetchVerifyEmail(
2546
+ config,
2547
+ "POST",
2548
+ new URLSearchParams({
2549
+ csrfToken,
2550
+ email: user.email,
2551
+ callbackUrl
2552
+ }).toString()
2553
+ );
2554
+ if (res.status > 299) {
2555
+ throw new Error(await res.text());
2106
2556
  }
2557
+ return res;
2107
2558
  }
2108
- function getCsrfToken(headers, initHeaders) {
2109
- if (headers) {
2110
- const cookies = getCookies(headers);
2111
- let validCookie = "";
2112
- if (cookies) {
2113
- validCookie = cookies["__Secure-nile.csrf-token"] || cookies["nile.csrf-token"];
2114
- }
2115
- if (validCookie) {
2116
- return validCookie;
2117
- }
2118
- }
2119
- if (initHeaders) {
2120
- const cookies = getCookies(initHeaders);
2121
- if (cookies) {
2122
- return cookies["__Secure-nile.csrf-token"] || cookies["nile.csrf-token"];
2123
- }
2559
+ function defaultCallbackUrl2(config) {
2560
+ let cb = null;
2561
+ const fallbackCb = parseCallback(config.headers);
2562
+ if (fallbackCb) {
2563
+ const [, value] = fallbackCb.split("=");
2564
+ cb = decodeURIComponent(value);
2124
2565
  }
2566
+ return { callbackUrl: cb };
2125
2567
  }
2126
- var getCookies = (headers) => {
2127
- if (!headers) return {};
2128
- const cookieHeader = headers.get("cookie") || "";
2129
- const setCookieHeaders = headers.get("set-cookie") || "";
2130
- const allCookies = [
2131
- ...cookieHeader.split("; "),
2132
- // Regular 'cookie' header (semicolon-separated)
2133
- ...setCookieHeaders.split(/,\s*(?=[^;, ]+=)/)
2134
- // Smart split for 'set-cookie'
2135
- ].filter(Boolean);
2136
- return Object.fromEntries(
2137
- allCookies.map((cookie) => {
2138
- const [key12, ...val] = cookie.split("=");
2139
- return [
2140
- decodeURIComponent(key12.trim()),
2141
- decodeURIComponent(val.join("=").trim())
2142
- ];
2143
- })
2144
- );
2145
- };
2146
2568
 
2147
2569
  // src/tenants/index.ts
2148
- var Tenants = class extends Config {
2149
- headers;
2150
- constructor(config, headers) {
2151
- super(config);
2152
- this.headers = headers;
2153
- }
2154
- handleHeaders(init) {
2155
- if (this.headers) {
2156
- if (init) {
2157
- init.headers = new Headers({ ...this.headers, ...init?.headers });
2158
- return init;
2159
- } else {
2160
- init = {
2161
- headers: this.headers
2162
- };
2163
- return init;
2164
- }
2165
- }
2166
- return void 0;
2167
- }
2168
- get tenantsUrl() {
2169
- return "/tenants";
2170
- }
2171
- get tenantUrl() {
2172
- return `/tenants/${this.tenantId ?? "{tenantId}"}`;
2570
+ var Tenants = class {
2571
+ #config;
2572
+ constructor(config) {
2573
+ this.#config = config;
2173
2574
  }
2174
- createTenant = async (req, init) => {
2175
- let _req;
2575
+ async create(req, rawResponse) {
2576
+ let res;
2176
2577
  if (typeof req === "string") {
2177
- _req = new Request(`${this.api.basePath}${this.tenantsUrl}`, {
2178
- body: JSON.stringify({ name: req }),
2179
- method: "POST",
2180
- headers: {
2181
- "content-type": "application/json"
2182
- }
2183
- });
2184
- } else if ("name" in req || "id" in req) {
2185
- _req = new Request(`${this.api.basePath}${this.tenantsUrl}`, {
2186
- body: JSON.stringify(req),
2187
- method: "POST",
2188
- headers: {
2189
- "content-type": "application/json"
2190
- }
2191
- });
2192
- } else {
2193
- _req = req;
2578
+ res = await fetchTenants(
2579
+ this.#config,
2580
+ "POST",
2581
+ JSON.stringify({ name: req })
2582
+ );
2583
+ } else if (typeof req === "object" && ("name" in req || "id" in req)) {
2584
+ res = await fetchTenants(this.#config, "POST", JSON.stringify(req));
2194
2585
  }
2195
- const _requester = new Requester(this);
2196
- const _init = this.handleHeaders(init);
2197
- return _requester.post(_req, this.tenantsUrl, _init);
2198
- };
2199
- getTenant = async (req, init) => {
2200
- if (typeof req === "string") {
2201
- this.tenantId = req;
2586
+ if (rawResponse) {
2587
+ return res;
2588
+ }
2589
+ try {
2590
+ return await res?.clone().json();
2591
+ } catch {
2592
+ return res;
2202
2593
  }
2203
- const _requester = new Requester(this);
2204
- const _init = this.handleHeaders(init);
2205
- return _requester.get(req, this.tenantUrl, _init);
2206
- };
2207
- get tenantListUrl() {
2208
- return `/users/${this.userId ?? "{userId}"}/tenants`;
2209
2594
  }
2210
- listTenants = async (req, init) => {
2211
- const _requester = new Requester(this);
2212
- const _init = this.handleHeaders(init);
2213
- return _requester.get(req, this.tenantListUrl, _init);
2214
- };
2215
- deleteTenant = async (req, init) => {
2595
+ async delete(req) {
2216
2596
  if (typeof req === "string") {
2217
- this.tenantId = req;
2597
+ this.#config.tenantId = req;
2218
2598
  }
2219
- const _requester = new Requester(this);
2220
- const _init = this.handleHeaders(init);
2221
- return _requester.delete(req, this.tenantUrl, _init);
2222
- };
2223
- updateTenant = async (req, init) => {
2224
- let _req;
2225
- if (req && "name" in req) {
2226
- _req = new Request(`${this.api.basePath}${this.tenantUrl}`, {
2227
- body: JSON.stringify(req),
2228
- method: "PUT"
2229
- });
2230
- } else {
2231
- _req = req;
2599
+ if (typeof req === "object" && "id" in req) {
2600
+ this.#config.tenantId = req.id;
2232
2601
  }
2233
- const _requester = new Requester(this);
2234
- const _init = this.handleHeaders(init);
2235
- return _requester.put(_req, this.tenantUrl, _init);
2236
- };
2237
- };
2238
-
2239
- // src/users/index.ts
2240
- var Users = class extends Config {
2241
- headers;
2242
- constructor(config, headers) {
2243
- super(config);
2244
- this.headers = headers;
2602
+ const res = await fetchTenant(this.#config, "DELETE");
2603
+ return res;
2245
2604
  }
2246
- usersUrl(user) {
2247
- const params = new URLSearchParams();
2248
- if (user.newTenantName) {
2249
- params.set("newTenantName", user.newTenantName);
2605
+ async get(req, rawResponse) {
2606
+ if (typeof req === "string") {
2607
+ this.#config.tenantId = req;
2608
+ } else if (typeof req === "object" && "id" in req) {
2609
+ this.#config.tenantId = req.id;
2250
2610
  }
2251
- if (user.tenantId) {
2252
- params.set("tenantId", user.tenantId);
2611
+ const res = await fetchTenant(this.#config, "GET");
2612
+ if (rawResponse === true || req === true) {
2613
+ return res;
2614
+ }
2615
+ try {
2616
+ return await res?.clone().json();
2617
+ } catch {
2618
+ return res;
2253
2619
  }
2254
- return `/users?${params.size > 0 ? params : ""}`;
2255
- }
2256
- get tenantUsersUrl() {
2257
- return `/tenants/${this.tenantId ?? "{tenantId}"}/users`;
2258
- }
2259
- get linkUsersUrl() {
2260
- return `/tenants/${this.tenantId ?? "{tenantId}"}/users/${this.userId ?? "{userId}"}/link`;
2261
- }
2262
- get tenantUserUrl() {
2263
- return `/tenants/${this.tenantId ?? "{tenantId}"}/users/${this.userId ?? "{userId}"}`;
2264
2620
  }
2265
- handleHeaders(init) {
2266
- if (this.headers) {
2267
- if (init) {
2268
- init.headers = new Headers({ ...this.headers, ...init?.headers });
2269
- return init;
2270
- } else {
2271
- init = {
2272
- headers: this.headers
2273
- };
2274
- return init;
2621
+ async update(req, rawResponse) {
2622
+ let res;
2623
+ if (typeof req === "object" && ("name" in req || "id" in req)) {
2624
+ const { id, ...remaining } = req;
2625
+ if (id) {
2626
+ this.#config.tenantId = id;
2275
2627
  }
2628
+ res = await fetchTenant(this.#config, "PUT", JSON.stringify(remaining));
2629
+ }
2630
+ if (rawResponse) {
2631
+ return res;
2632
+ }
2633
+ try {
2634
+ return await res?.clone().json();
2635
+ } catch {
2636
+ return res;
2276
2637
  }
2277
- return void 0;
2278
2638
  }
2279
- createUser = async (user, init) => {
2280
- const _requester = new Requester(this);
2281
- const _init = this.handleHeaders(init);
2282
- return await _requester.post(user, this.usersUrl(user), _init);
2283
- };
2284
- createTenantUser = async (req, init) => {
2285
- const _requester = new Requester(this);
2286
- const _init = this.handleHeaders(init);
2287
- return await _requester.post(req, this.tenantUsersUrl, _init);
2288
- };
2289
- updateUser = async (req, init) => {
2290
- let _req;
2291
- if (req && "id" in req) {
2292
- _req = new Request(`${this.api.basePath}${this.tenantUserUrl}`, {
2293
- body: JSON.stringify(req),
2294
- method: "PUT"
2295
- });
2296
- this.userId = String(req.id);
2297
- } else {
2298
- _req = req;
2639
+ async list(req) {
2640
+ const res = await fetchTenantsByUser(this.#config);
2641
+ if (req === true) {
2642
+ return res;
2643
+ }
2644
+ try {
2645
+ return await res?.clone().json();
2646
+ } catch {
2647
+ return res;
2648
+ }
2649
+ }
2650
+ async leaveTenant(req) {
2651
+ const me = await fetchMe(this.#config);
2652
+ try {
2653
+ const json = await me.json();
2654
+ if ("id" in json) {
2655
+ this.#config.userId = json.id;
2656
+ }
2657
+ } catch {
2299
2658
  }
2300
- const _requester = new Requester(this);
2301
- const _init = this.handleHeaders(init);
2302
- return await _requester.put(_req, this.tenantUserUrl, _init);
2303
- };
2304
- listUsers = async (req, init) => {
2305
- const _requester = new Requester(this);
2306
- const _init = this.handleHeaders(init);
2307
- return await _requester.get(req, this.tenantUsersUrl, _init);
2308
- };
2309
- linkUser = async (req, init) => {
2310
- const _requester = new Requester(this);
2311
2659
  if (typeof req === "string") {
2312
- this.userId = req;
2660
+ this.#config.tenantId = req;
2313
2661
  } else {
2314
- if ("id" in req) {
2315
- this.userId = req.id;
2316
- }
2317
- if ("tenantId" in req) {
2318
- this.tenantId = req.tenantId;
2319
- }
2662
+ this.#handleContext(req);
2320
2663
  }
2321
- const _init = this.handleHeaders(init);
2322
- return await _requester.put(req, this.linkUsersUrl, _init);
2323
- };
2324
- unlinkUser = async (req, init) => {
2664
+ return await fetchTenantUser(this.#config, "DELETE");
2665
+ }
2666
+ async addMember(req, rawResponse) {
2325
2667
  if (typeof req === "string") {
2326
- this.userId = req;
2668
+ this.#config.userId = req;
2327
2669
  } else {
2328
- if ("id" in req) {
2329
- this.userId = req.id;
2670
+ this.#handleContext(req);
2671
+ }
2672
+ const res = await fetchTenantUser(this.#config, "PUT");
2673
+ return responseHandler(res, rawResponse);
2674
+ }
2675
+ async removeMember(req, rawResponse) {
2676
+ this.#handleContext(req);
2677
+ const res = await fetchTenantUser(this.#config, "DELETE");
2678
+ return responseHandler(res, rawResponse);
2679
+ }
2680
+ async users(req, rawResponse) {
2681
+ this.#handleContext(req);
2682
+ const res = await fetchTenantUsers(this.#config, "GET");
2683
+ return responseHandler(
2684
+ res,
2685
+ rawResponse || typeof req === "boolean" && req
2686
+ );
2687
+ }
2688
+ async invites() {
2689
+ const res = await fetchInvites(this.#config);
2690
+ return responseHandler(res);
2691
+ }
2692
+ async invite(req, rawResponse) {
2693
+ const { csrfToken } = await obtainCsrf(this.#config);
2694
+ const defaults = defaultCallbackUrl3(this.#config);
2695
+ let identifier = req;
2696
+ let callbackUrl = defaults.callbackUrl;
2697
+ let redirectUrl = defaults.redirectUrl;
2698
+ if (typeof req === "object") {
2699
+ if ("email" in req) {
2700
+ identifier = req.email;
2330
2701
  }
2331
- if ("tenantId" in req) {
2332
- this.tenantId = req.tenantId;
2702
+ if ("callbackUrl" in req) {
2703
+ callbackUrl = req.callbackUrl ? req.callbackUrl : "";
2704
+ }
2705
+ if ("redirectUrl" in req) {
2706
+ redirectUrl = req.redirectUrl ? req.redirectUrl : "";
2333
2707
  }
2334
2708
  }
2335
- const _requester = new Requester(this);
2336
- const _init = this.handleHeaders(init);
2337
- return await _requester.delete(req, this.linkUsersUrl, _init);
2338
- };
2339
- get meUrl() {
2340
- return "/me";
2341
- }
2342
- me = async (req, init) => {
2343
- const _requester = new Requester(this);
2344
- const _init = this.handleHeaders(init);
2345
- return await _requester.get(req, this.meUrl, _init);
2346
- };
2347
- updateMe = async (req, init) => {
2348
- const _requester = new Requester(this);
2349
- const _init = this.handleHeaders(init);
2350
- return await _requester.put(req, this.meUrl, _init);
2351
- };
2352
- };
2353
-
2354
- // src/Api.ts
2355
- var Api = class {
2356
- config;
2357
- users;
2358
- auth;
2359
- tenants;
2360
- routes;
2361
- #headers;
2362
- handlers;
2363
- paths;
2364
- constructor(config) {
2365
- this.config = config;
2366
- this.auth = new Auth(config, void 0, {
2367
- resetHeaders: this.resetHeaders
2368
- });
2369
- this.users = new Users(config);
2370
- this.tenants = new Tenants(config);
2371
- this.routes = {
2372
- ...appRoutes(config?.api.routePrefix),
2373
- ...config?.api.routes
2374
- };
2375
- this.handlers = Handlers(this.routes, config);
2376
- this.paths = {
2377
- get: [
2378
- this.routes.ME,
2379
- this.routes.TENANT_USERS,
2380
- this.routes.TENANTS,
2381
- this.routes.TENANT,
2382
- this.routes.SESSION,
2383
- this.routes.SIGNIN,
2384
- this.routes.PROVIDERS,
2385
- this.routes.CSRF,
2386
- this.routes.PASSWORD_RESET,
2387
- this.routes.CALLBACK,
2388
- this.routes.SIGNOUT,
2389
- this.routes.VERIFY_REQUEST,
2390
- this.routes.ERROR
2391
- ],
2392
- post: [
2393
- this.routes.TENANT_USERS,
2394
- this.routes.SIGNUP,
2395
- this.routes.USERS,
2396
- this.routes.TENANTS,
2397
- this.routes.SESSION,
2398
- `${this.routes.SIGNIN}/{provider}`,
2399
- this.routes.PASSWORD_RESET,
2400
- this.routes.PROVIDERS,
2401
- this.routes.CSRF,
2402
- `${this.routes.CALLBACK}/{provider}`,
2403
- this.routes.SIGNOUT
2404
- ],
2405
- put: [
2406
- this.routes.TENANT_USERS,
2407
- this.routes.USERS,
2408
- this.routes.TENANT,
2409
- this.routes.PASSWORD_RESET
2410
- ],
2411
- delete: [this.routes.TENANT_USER, this.routes.TENANT]
2412
- };
2709
+ this.#config.headers.set(
2710
+ "Content-Type",
2711
+ "application/x-www-form-urlencoded"
2712
+ );
2713
+ const res = await fetchInvite(
2714
+ this.#config,
2715
+ "POST",
2716
+ new URLSearchParams({
2717
+ identifier,
2718
+ csrfToken,
2719
+ callbackUrl,
2720
+ redirectUrl
2721
+ }).toString()
2722
+ );
2723
+ return responseHandler(res, rawResponse);
2724
+ }
2725
+ async acceptInvite(req, rawResponse) {
2726
+ if (!req) {
2727
+ throw new Error("The identifier and token are required.");
2728
+ }
2729
+ const { identifier, token } = req;
2730
+ const defaults = defaultCallbackUrl3(this.#config);
2731
+ const callbackUrl = String(defaults.callbackUrl);
2732
+ const res = await fetchInvite(
2733
+ this.#config,
2734
+ "PUT",
2735
+ new URLSearchParams({
2736
+ identifier,
2737
+ token,
2738
+ callbackUrl
2739
+ }).toString()
2740
+ );
2741
+ return responseHandler(res, rawResponse);
2413
2742
  }
2414
- reset = () => {
2415
- this.users = new Users(this.config, this.#headers);
2416
- this.tenants = new Tenants(this.config, this.#headers);
2417
- this.auth = new Auth(this.config, this.#headers, {
2418
- resetHeaders: this.resetHeaders
2419
- });
2420
- };
2421
- updateConfig = (config) => {
2422
- this.config = config;
2423
- this.handlers = Handlers(this.routes, config);
2424
- };
2425
- resetHeaders = (headers) => {
2426
- this.#headers = new Headers(headers ?? {});
2427
- setContext(new Headers());
2428
- this.reset();
2429
- };
2430
- set headers(headers) {
2431
- const updates = [];
2432
- if (headers instanceof Headers) {
2433
- headers.forEach((value, key12) => {
2434
- updates.push([key12.toLowerCase(), value]);
2435
- });
2743
+ async deleteInvite(req) {
2744
+ let id = "";
2745
+ if (typeof req === "object") {
2746
+ id = req.id;
2436
2747
  } else {
2437
- for (const [key12, value] of Object.entries(headers)) {
2438
- updates.push([key12.toLowerCase(), value]);
2439
- }
2748
+ id = req;
2440
2749
  }
2441
- const merged = {};
2442
- this.#headers?.forEach((value, key12) => {
2443
- merged[key12.toLowerCase()] = value;
2444
- });
2445
- for (const [key12, value] of updates) {
2446
- merged[key12] = value;
2750
+ if (!id) {
2751
+ throw new Error("An invite id is required.");
2447
2752
  }
2448
- this.#headers = new Headers();
2449
- for (const [key12, value] of Object.entries(merged)) {
2450
- this.#headers.set(key12, value);
2753
+ const res = await fetchInvite(this.#config, "DELETE", id);
2754
+ return responseHandler(res, true);
2755
+ }
2756
+ #handleContext(req) {
2757
+ if (typeof req === "object") {
2758
+ if ("tenantId" in req) {
2759
+ this.#config.tenantId = req.tenantId;
2760
+ }
2761
+ if ("userId" in req) {
2762
+ this.#config.tenantId = req.tenantId;
2763
+ }
2451
2764
  }
2452
- this.reset();
2453
2765
  }
2454
- get headers() {
2455
- return this.#headers;
2766
+ };
2767
+ async function responseHandler(res, rawResponse) {
2768
+ if (rawResponse) {
2769
+ return res;
2770
+ }
2771
+ try {
2772
+ return await res?.clone().json();
2773
+ } catch {
2774
+ return res;
2456
2775
  }
2457
- getCookie(req) {
2458
- if (req instanceof Headers) {
2459
- return parseToken(req);
2460
- } else if (req instanceof Request) {
2461
- return parseToken(req.headers);
2776
+ }
2777
+ function defaultCallbackUrl3(config) {
2778
+ let cb = null;
2779
+ let redirect = null;
2780
+ const fallbackCb = parseCallback(config.headers);
2781
+ if (fallbackCb) {
2782
+ const [, value] = fallbackCb.split("=");
2783
+ cb = decodeURIComponent(value);
2784
+ if (value) {
2785
+ redirect = `${new URL(cb).origin}${config.routePrefix}${"/tenants/{tenantId}/invite" /* INVITE */.replace(
2786
+ "{tenantId}",
2787
+ String(config.tenantId)
2788
+ )}`;
2462
2789
  }
2463
- return null;
2464
2790
  }
2465
- login = async (payload, config) => {
2466
- const [headers, loginRes] = await serverLogin(
2467
- this.config,
2468
- this.handlers
2469
- )(payload);
2470
- this.headers = headers;
2471
- this.setContext(headers);
2472
- if (config?.returnResponse) {
2473
- return loginRes;
2791
+ return { callbackUrl: cb, redirectUrl: redirect };
2792
+ }
2793
+
2794
+ // src/api/handlers/withContext/index.ts
2795
+ function handlersWithContext(config) {
2796
+ const GET7 = GETTER(config.routes, config);
2797
+ const POST6 = POSTER(config.routes, config);
2798
+ const DELETE5 = DELETER(config.routes, config);
2799
+ const PUT6 = PUTER(config.routes, config);
2800
+ return {
2801
+ GET: async (req) => {
2802
+ const response = await GET7(req);
2803
+ const updatedConfig = updateConfig(response, config);
2804
+ return { response, nile: new Server(updatedConfig) };
2805
+ },
2806
+ POST: async (req) => {
2807
+ const response = await POST6(req);
2808
+ const updatedConfig = updateConfig(response, config);
2809
+ return { response, nile: new Server(updatedConfig) };
2810
+ },
2811
+ DELETE: async (req) => {
2812
+ const response = await DELETE5(req);
2813
+ const updatedConfig = updateConfig(response, config);
2814
+ return { response, nile: new Server(updatedConfig) };
2815
+ },
2816
+ PUT: async (req) => {
2817
+ const response = await PUT6(req);
2818
+ const updatedConfig = updateConfig(response, config);
2819
+ return { response, nile: new Server(updatedConfig) };
2474
2820
  }
2475
- return void 0;
2476
2821
  };
2477
- session = async (req) => {
2478
- if (req instanceof Headers) {
2479
- return this.auth.getSession(req);
2480
- } else if (req instanceof Request) {
2481
- return auth(req, this.config);
2822
+ }
2823
+ function updateConfig(response, config) {
2824
+ let origin = "http://localhost:3000";
2825
+ let headers = null;
2826
+ if (response?.status === 302) {
2827
+ const location = response.headers.get("location");
2828
+ if (location) {
2829
+ const urlLocation = new URL(location);
2830
+ origin = urlLocation.origin;
2482
2831
  }
2483
- return this.auth.getSession(this.#headers);
2484
- };
2485
- setContext = (req) => {
2486
- if (req instanceof Headers) {
2487
- setContext(req);
2488
- return;
2489
- } else if (req instanceof Request) {
2490
- setContext(req.headers);
2491
- return;
2832
+ }
2833
+ const setCookies = [];
2834
+ if (response?.headers) {
2835
+ for (const [key17, value] of response.headers) {
2836
+ if (key17.toLowerCase() === "set-cookie") {
2837
+ setCookies.push(value);
2838
+ }
2492
2839
  }
2493
- const headers = new Headers(req);
2494
- if (headers) {
2495
- setContext(headers);
2496
- } else {
2497
- const { warn } = Logger(this.config, "[API]");
2498
- if (warn) {
2499
- warn("Set context expects a Request or Header object");
2840
+ }
2841
+ if (setCookies.length > 0) {
2842
+ const cookieHeader = setCookies.map((cookieStr) => cookieStr.split(";")[0]).join("; ");
2843
+ headers = new Headers({ cookie: cookieHeader });
2844
+ }
2845
+ return {
2846
+ ...config,
2847
+ origin,
2848
+ headers: headers ?? void 0,
2849
+ preserveHeaders: true
2850
+ };
2851
+ }
2852
+
2853
+ // src/api/utils/extensions.ts
2854
+ function bindHandleOnRequest(instance) {
2855
+ return async function handleOnRequest(config, _init, params) {
2856
+ const { debug } = config.logger("[EXTENSIONS]");
2857
+ if (config.extensions) {
2858
+ for (const create2 of config.extensions) {
2859
+ if (typeof create2 !== "function") {
2860
+ return void 0;
2861
+ }
2862
+ const ext = await create2(instance);
2863
+ if (ext.onRequest) {
2864
+ const previousContext = instance.getContext();
2865
+ if (previousContext.preserveHeaders) {
2866
+ instance.setContext({ preserveHeaders: false });
2867
+ }
2868
+ await ext.onRequest(_init.request);
2869
+ const updatedContext = instance.getContext();
2870
+ if (updatedContext?.headers) {
2871
+ const cookie = updatedContext.headers.get("cookie");
2872
+ if (cookie) {
2873
+ params.headers.set(
2874
+ "cookie",
2875
+ mergeCookies(
2876
+ previousContext.preserveHeaders ? previousContext.headers?.get("cookie") : null,
2877
+ updatedContext.headers.get("cookie")
2878
+ )
2879
+ );
2880
+ }
2881
+ if (updatedContext.tenantId) {
2882
+ params.headers.set(
2883
+ TENANT_COOKIE,
2884
+ String(updatedContext.headers.get(TENANT_COOKIE))
2885
+ );
2886
+ }
2887
+ }
2888
+ debug(`${ext.id ?? create2.name} ran onRequest`);
2889
+ }
2500
2890
  }
2501
2891
  }
2502
2892
  };
2503
- };
2893
+ }
2894
+ function buildExtensionConfig(instance) {
2895
+ return {
2896
+ handleOnRequest: bindHandleOnRequest(instance)
2897
+ };
2898
+ }
2899
+ function mergeCookies(...cookieStrings) {
2900
+ const cookieMap = /* @__PURE__ */ new Map();
2901
+ for (const str of cookieStrings) {
2902
+ if (!str) continue;
2903
+ for (const part of str.split(";")) {
2904
+ const [key17, value] = part.split("=").map((s) => s.trim());
2905
+ if (key17 && value) cookieMap.set(key17, value);
2906
+ }
2907
+ }
2908
+ return [...cookieMap.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
2909
+ }
2504
2910
 
2505
2911
  // src/Server.ts
2506
2912
  var Server = class {
2507
- config;
2508
- api;
2509
- manager;
2913
+ users;
2914
+ tenants;
2915
+ auth;
2916
+ #config;
2917
+ #handlers;
2918
+ #paths;
2919
+ #manager;
2920
+ #headers;
2921
+ #preserveHeaders;
2510
2922
  constructor(config) {
2511
- this.config = new Config(config, "[initial config]");
2512
- this.api = new Api(this.config);
2513
- this.manager = new DBManager(this.config);
2923
+ this.#config = new Config({
2924
+ ...config,
2925
+ extensionCtx: buildExtensionConfig(this)
2926
+ });
2514
2927
  watchTenantId((tenantId) => {
2515
- this.tenantId = tenantId;
2928
+ if (tenantId !== this.#config.tenantId) {
2929
+ this.#config.tenantId = tenantId;
2930
+ this.#reset();
2931
+ }
2516
2932
  });
2517
2933
  watchUserId((userId) => {
2518
- this.userId = userId;
2934
+ if (userId !== this.#config.userId) {
2935
+ this.#config.userId = userId;
2936
+ this.#reset();
2937
+ }
2519
2938
  });
2520
- watchToken((token) => {
2521
- this.token = token;
2939
+ watchHeaders((headers) => {
2940
+ this.setContext(headers);
2941
+ this.#reset();
2522
2942
  });
2943
+ this.#handlers = {
2944
+ ...this.#config.handlers,
2945
+ withContext: handlersWithContext(this.#config)
2946
+ };
2947
+ this.#preserveHeaders = config?.preserveHeaders ?? false;
2948
+ this.#paths = this.#config.paths;
2949
+ this.#config.tenantId = getTenantId({ config: this.#config });
2950
+ this.#manager = new DBManager(this.#config);
2951
+ this.#handleHeaders(config);
2952
+ this.users = new Users(this.#config);
2953
+ this.tenants = new Tenants(this.#config);
2954
+ this.auth = new Auth(this.#config);
2523
2955
  }
2524
- setConfig(cfg) {
2525
- this.config = new Config(cfg);
2526
- this.api.updateConfig(this.config);
2956
+ get db() {
2957
+ const pool = this.#manager.getConnection(this.#config);
2958
+ return Object.assign(pool, {
2959
+ clearConnections: () => {
2960
+ this.#manager.clear(this.#config);
2961
+ }
2962
+ });
2527
2963
  }
2528
- set databaseId(val) {
2529
- if (val) {
2530
- this.config.databaseId = val;
2531
- this.api.users.databaseId = val;
2532
- this.api.tenants.databaseId = val;
2964
+ /**
2965
+ * A convenience function that applies a config and ensures whatever was passed is set properly
2966
+ */
2967
+ getInstance(config, req) {
2968
+ const _config = { ...this.#config, ...config };
2969
+ const updatedConfig = new Config(_config);
2970
+ this.#config = new Config(updatedConfig);
2971
+ this.#config.tenantId = config.tenantId;
2972
+ this.#config.userId = config.userId;
2973
+ if (req) {
2974
+ this.setContext(req);
2533
2975
  }
2976
+ this.#reset();
2977
+ return this;
2534
2978
  }
2535
- get userId() {
2536
- return this.config.userId;
2537
- }
2538
- set userId(userId) {
2539
- this.databaseId = this.config.databaseId;
2540
- this.config.userId = userId;
2541
- if (this.api) {
2542
- this.api.users.userId = this.config.userId;
2543
- this.api.tenants.userId = this.config.userId;
2544
- }
2979
+ getPaths() {
2980
+ return this.#paths;
2545
2981
  }
2546
- get tenantId() {
2547
- return this.config.tenantId;
2982
+ get handlers() {
2983
+ return this.#handlers;
2548
2984
  }
2549
- set tenantId(tenantId) {
2550
- this.databaseId = this.config.databaseId;
2551
- this.config.tenantId = tenantId;
2552
- if (this.api) {
2553
- this.api.users.tenantId = tenantId;
2554
- this.api.tenants.tenantId = tenantId;
2985
+ /**
2986
+ * Allow the setting of headers from a req or header object.
2987
+ * Makes it possible to handle REST requests easily
2988
+ * Also makes it easy to set user + tenant in some way
2989
+ * @param req
2990
+ * @returns undefined
2991
+ */
2992
+ setContext(req) {
2993
+ try {
2994
+ if (req instanceof Headers) {
2995
+ this.#handleHeaders(req);
2996
+ this.#reset();
2997
+ return;
2998
+ } else if (req instanceof Request) {
2999
+ this.#handleHeaders(new Headers(req.headers));
3000
+ this.#reset();
3001
+ return;
3002
+ }
3003
+ } catch {
2555
3004
  }
2556
- }
2557
- get token() {
2558
- return this.config?.api?.token;
2559
- }
2560
- set token(token) {
2561
- if (token) {
2562
- this.config.api.token = token;
2563
- if (this.api) {
2564
- this.api.users.api.token = token;
2565
- this.api.tenants.api.token = token;
3005
+ let ok = false;
3006
+ if (req && typeof req === "object" && "tenantId" in req) {
3007
+ ok = true;
3008
+ this.#config.tenantId = req.tenantId;
3009
+ }
3010
+ if (req && typeof req === "object" && "userId" in req) {
3011
+ ok = true;
3012
+ this.#config.userId = req.userId;
3013
+ }
3014
+ if (req && typeof req === "object" && "preserveHeaders" in req) {
3015
+ ok = true;
3016
+ this.#preserveHeaders = Boolean(req.preserveHeaders);
3017
+ }
3018
+ if (ok) {
3019
+ return;
3020
+ }
3021
+ if (typeof req === "object") {
3022
+ const headers = new Headers(req);
3023
+ if (headers) {
3024
+ this.#handleHeaders(headers);
3025
+ this.#reset();
3026
+ return;
2566
3027
  }
2567
3028
  }
3029
+ const { warn } = Logger(this.#config)("[API]");
3030
+ if (warn) {
3031
+ warn(
3032
+ "Set context expects a Request, Header instance or an object of Record<string, string>"
3033
+ );
3034
+ }
2568
3035
  }
2569
- get db() {
2570
- return this.manager.getConnection(this.config);
2571
- }
2572
- clearConnections() {
2573
- this.manager.clear(this.config);
3036
+ getContext() {
3037
+ return {
3038
+ headers: this.#headers,
3039
+ userId: this.#config.userId,
3040
+ tenantId: this.#config.tenantId,
3041
+ preserveHeaders: this.#preserveHeaders
3042
+ };
2574
3043
  }
2575
3044
  /**
2576
- * A convenience function that applies a config and ensures whatever was passed is set properly
3045
+ * Merge headers together
3046
+ * Internally, passed a NileConfig, externally, should be using Headers
2577
3047
  */
2578
- getInstance(config) {
2579
- const _config = { ...this.config, ...config };
2580
- const updatedConfig = new Config(_config);
2581
- this.setConfig(updatedConfig);
2582
- this.tenantId = updatedConfig.tenantId;
2583
- this.userId = updatedConfig.userId;
2584
- if (updatedConfig.api.token) {
2585
- this.token = updatedConfig.api.token;
3048
+ #handleHeaders(config) {
3049
+ const updates = [];
3050
+ let headers;
3051
+ this.#headers = new Headers();
3052
+ if (config instanceof Headers) {
3053
+ headers = config;
3054
+ } else if (config?.headers) {
3055
+ headers = config?.headers;
3056
+ if (config && config.origin) {
3057
+ this.#headers.set(HEADER_ORIGIN, config.origin);
3058
+ }
3059
+ if (config && config.secureCookies != null) {
3060
+ this.#headers.set(HEADER_SECURE_COOKIES, String(config.secureCookies));
3061
+ }
2586
3062
  }
2587
- this.databaseId = updatedConfig.databaseId;
2588
- return this;
3063
+ if (headers instanceof Headers) {
3064
+ headers.forEach((value, key17) => {
3065
+ updates.push([key17.toLowerCase(), value]);
3066
+ });
3067
+ } else {
3068
+ for (const [key17, value] of Object.entries(headers ?? {})) {
3069
+ updates.push([key17.toLowerCase(), value]);
3070
+ }
3071
+ }
3072
+ const merged = {};
3073
+ this.#config.tenantId = getTenantFromHttp(this.#headers, this.#config);
3074
+ this.#headers?.forEach((value, key17) => {
3075
+ if (key17.toLowerCase() !== "cookie") {
3076
+ merged[key17.toLowerCase()] = value;
3077
+ }
3078
+ });
3079
+ for (const [key17, value] of updates) {
3080
+ merged[key17] = value;
3081
+ }
3082
+ for (const [key17, value] of Object.entries(merged)) {
3083
+ this.#headers.set(key17, value);
3084
+ }
3085
+ this.#config.logger("[handleHeaders]").debug(JSON.stringify(merged));
3086
+ this.#config.headers = this.#headers;
2589
3087
  }
3088
+ /**
3089
+ * Allow some internal mutations to reset our config + headers
3090
+ */
3091
+ #reset = () => {
3092
+ this.#config.headers = this.#headers ?? new Headers();
3093
+ this.users = new Users(this.#config);
3094
+ this.tenants = new Tenants(this.#config);
3095
+ this.auth = new Auth(this.#config);
3096
+ };
2590
3097
  };
2591
3098
  var server;
2592
3099
  function create(config) {
@@ -2596,8 +3103,16 @@ function create(config) {
2596
3103
  return server;
2597
3104
  }
2598
3105
 
3106
+ exports.APIErrorErrorCodeEnum = APIErrorErrorCodeEnum;
3107
+ exports.HEADER_ORIGIN = HEADER_ORIGIN;
3108
+ exports.HEADER_SECURE_COOKIES = HEADER_SECURE_COOKIES;
2599
3109
  exports.LoginUserResponseTokenTypeEnum = LoginUserResponseTokenTypeEnum;
2600
3110
  exports.Nile = create;
2601
3111
  exports.Server = Server;
3112
+ exports.TENANT_COOKIE = TENANT_COOKIE;
3113
+ exports.USER_COOKIE = USER_COOKIE;
3114
+ exports.parseCSRF = parseCSRF;
3115
+ exports.parseCallback = parseCallback;
3116
+ exports.parseToken = parseToken;
2602
3117
  //# sourceMappingURL=index.js.map
2603
3118
  //# sourceMappingURL=index.js.map