@niledatabase/server 4.0.0-alpha.2 → 4.0.0-alpha.21

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.mjs CHANGED
@@ -73,7 +73,7 @@ var X_NILE_SECURECOOKIES = "nile.secure_cookies";
73
73
 
74
74
  // src/api/utils/request.ts
75
75
  async function request(url, _init, config) {
76
- const { info, error } = Logger(config, "[REQUEST]");
76
+ const { debug, info, error } = Logger(config, "[REQUEST]");
77
77
  const { request: request2, ...init } = _init;
78
78
  const requestUrl = new URL(request2.url);
79
79
  const updatedHeaders = new Headers({});
@@ -91,9 +91,17 @@ async function request(url, _init, config) {
91
91
  }
92
92
  updatedHeaders.set("host", requestUrl.host);
93
93
  if (config.api.callbackUrl) {
94
- updatedHeaders.set(X_NILE_ORIGIN, config.api.callbackUrl);
94
+ const cbUrl = new URL(config.api.callbackUrl);
95
+ debug(
96
+ `Obtained origin from config.api.callbackUrl ${config.api.callbackUrl}`
97
+ );
98
+ updatedHeaders.set(X_NILE_ORIGIN, cbUrl.origin);
99
+ } else if (config.api.origin) {
100
+ debug(`Obtained origin from config.api.origin ${config.api.origin}`);
101
+ updatedHeaders.set(X_NILE_ORIGIN, config.api.origin);
95
102
  } else {
96
103
  updatedHeaders.set(X_NILE_ORIGIN, requestUrl.origin);
104
+ debug(`Obtained origin from request ${requestUrl.origin}`);
97
105
  }
98
106
  const params = { ...init, headers: updatedHeaders };
99
107
  if (params.method === "POST" || params.method === "PUT") {
@@ -420,6 +428,7 @@ var ApiConfig = class {
420
428
  routes;
421
429
  routePrefix;
422
430
  secureCookies;
431
+ origin;
423
432
  /**
424
433
  * 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
425
434
  * If this is set, any `callbackUrl` from the client will be ignored.
@@ -435,6 +444,7 @@ var ApiConfig = class {
435
444
  this.basePath = getBasePath(envVarConfig);
436
445
  this.routes = config?.api?.routes;
437
446
  this.routePrefix = config?.api?.routePrefix;
447
+ this.origin = config?.api?.origin;
438
448
  }
439
449
  get token() {
440
450
  return this._token;
@@ -1067,12 +1077,9 @@ async function _fetch(config, path, opts) {
1067
1077
  if (response?.status === 405) {
1068
1078
  return new ResponseError("Method not allowed", { status: 405 });
1069
1079
  }
1070
- let res;
1071
1080
  const errorHandler = typeof response?.clone === "function" ? response.clone() : null;
1072
1081
  let msg = "";
1073
- try {
1074
- res = await response?.json();
1075
- } catch (e) {
1082
+ const res = await response?.json().catch(async (e) => {
1076
1083
  if (errorHandler) {
1077
1084
  msg = await errorHandler.text();
1078
1085
  if (msg) {
@@ -1085,7 +1092,8 @@ async function _fetch(config, path, opts) {
1085
1092
  if (!msg) {
1086
1093
  error("[fetch][response]", { e });
1087
1094
  }
1088
- }
1095
+ return e;
1096
+ });
1089
1097
  if (msg) {
1090
1098
  return new ResponseError(msg, { status: errorHandler?.status });
1091
1099
  }
@@ -1104,7 +1112,8 @@ async function _fetch(config, path, opts) {
1104
1112
  error(
1105
1113
  `[fetch][response][status: ${errorHandler?.status}] UNHANDLED ERROR`,
1106
1114
  {
1107
- res
1115
+ response,
1116
+ message: await response.text()
1108
1117
  }
1109
1118
  );
1110
1119
  return new ResponseError(null, {
@@ -1528,11 +1537,7 @@ function matches12(configRoutes, request2) {
1528
1537
  // src/api/routes/auth/password-reset.ts
1529
1538
  var key10 = "PASSWORD_RESET";
1530
1539
  async function route13(req, config) {
1531
- let url = proxyRoutes(config)[key10];
1532
- const { searchParams } = new URL(req.url);
1533
- if (searchParams.size > 0) {
1534
- url = `${url}?${searchParams.toString()}`;
1535
- }
1540
+ const url = proxyRoutes(config)[key10];
1536
1541
  const res = await request(
1537
1542
  url,
1538
1543
  {
@@ -1645,8 +1650,16 @@ function POSTER(configRoutes, config) {
1645
1650
  const { info, warn, error } = Logger(config, "[POST MATCHER]");
1646
1651
  return async function POST5(req) {
1647
1652
  if (matchesLog(configRoutes, req)) {
1648
- error(req.body && await req.json());
1649
- return new Response(null, { status: 200 });
1653
+ if (req.body) {
1654
+ try {
1655
+ const text = await req.text();
1656
+ error(text);
1657
+ return new Response(null, {
1658
+ status: 200
1659
+ });
1660
+ } catch (e) {
1661
+ }
1662
+ }
1650
1663
  }
1651
1664
  if (matches3(configRoutes, req)) {
1652
1665
  info("matches tenant users");
@@ -1771,7 +1784,7 @@ var appRoutes = (prefix = "/api") => ({
1771
1784
  TENANT_USER: `${prefix}/tenants/{tenantId}/users/{userId}`,
1772
1785
  TENANT_USERS: `${prefix}/tenants/{tenantId}/users`,
1773
1786
  SIGNUP: `${prefix}/signup`,
1774
- LOG: `${prefix}/auth/_log`
1787
+ LOG: `${prefix}/_log`
1775
1788
  });
1776
1789
 
1777
1790
  // src/utils/Requester/index.ts
@@ -1781,9 +1794,9 @@ var Requester = class extends Config {
1781
1794
  }
1782
1795
  async rawRequest(method, url, init, body) {
1783
1796
  const _init = {
1784
- ...init,
1785
1797
  body,
1786
- method
1798
+ method,
1799
+ ...init
1787
1800
  };
1788
1801
  const res = await _fetch(this, url, _init);
1789
1802
  if (res instanceof ResponseError) {
@@ -1852,8 +1865,11 @@ var Requester = class extends Config {
1852
1865
  }
1853
1866
  return response;
1854
1867
  }
1855
- async get(req, url, init) {
1868
+ async get(req, url, init, raw = false) {
1856
1869
  const response = await this.request("GET", url, req, init);
1870
+ if (raw) {
1871
+ return response;
1872
+ }
1857
1873
  if (response && response.status >= 200 && response.status < 300) {
1858
1874
  const cloned = response.clone();
1859
1875
  try {
@@ -1881,8 +1897,8 @@ var Requester = class extends Config {
1881
1897
  };
1882
1898
 
1883
1899
  // src/auth/index.ts
1884
- var ORIGIN = "https://us-west-2.api.dev.thenile.dev";
1885
1900
  function serverLogin(config, handlers) {
1901
+ const ORIGIN = config.api.origin ?? "http://localhost:3000";
1886
1902
  const { info, error, debug } = Logger(config, "[server side login]");
1887
1903
  const routes = appRoutes(config.api.routePrefix);
1888
1904
  return async function login({
@@ -1973,17 +1989,31 @@ function serverLogin(config, handlers) {
1973
1989
  ...baseHeaders,
1974
1990
  cookie: [token, csrfCookie].join("; ")
1975
1991
  });
1976
- return headers;
1992
+ return [headers, loginRes];
1977
1993
  };
1978
1994
  }
1979
1995
  var Auth = class extends Config {
1980
1996
  headers;
1981
- constructor(config, headers) {
1997
+ resetHeaders;
1998
+ constructor(config, headers, params) {
1982
1999
  super(config);
2000
+ this.logger = Logger(config, "[auth]");
1983
2001
  this.headers = headers;
2002
+ this.logger = Logger(config, "[auth]");
2003
+ this.resetHeaders = params?.resetHeaders;
1984
2004
  }
1985
2005
  handleHeaders(init) {
1986
2006
  if (this.headers) {
2007
+ const cburl = getCallbackUrl2(this.headers);
2008
+ if (cburl) {
2009
+ try {
2010
+ this.headers.set(X_NILE_ORIGIN, new URL(cburl).origin);
2011
+ } catch (e) {
2012
+ if (this.logger?.debug) {
2013
+ this.logger.debug("Invalid URL supplied by cookie header");
2014
+ }
2015
+ }
2016
+ }
1987
2017
  if (init) {
1988
2018
  init.headers = new Headers({ ...this.headers, ...init?.headers });
1989
2019
  return init;
@@ -2008,6 +2038,113 @@ var Auth = class extends Config {
2008
2038
  }
2009
2039
  return session;
2010
2040
  };
2041
+ get getCsrfUrl() {
2042
+ return "/auth/csrf";
2043
+ }
2044
+ async getCsrf(req, init, raw = false) {
2045
+ const _requester = new Requester(this);
2046
+ const _init = this.handleHeaders(init);
2047
+ return await _requester.get(req, this.getCsrfUrl, _init, raw);
2048
+ }
2049
+ get listProvidersUrl() {
2050
+ return "/auth/providers";
2051
+ }
2052
+ listProviders = async (req, init) => {
2053
+ const _requester = new Requester(this);
2054
+ const _init = this.handleHeaders(init);
2055
+ return await _requester.get(req, this.listProvidersUrl, _init);
2056
+ };
2057
+ get signOutUrl() {
2058
+ return "/auth/signout";
2059
+ }
2060
+ signOut = async (req, init) => {
2061
+ const _requester = new Requester(this);
2062
+ const _init = this.handleHeaders(init);
2063
+ const csrf = await this.getCsrf(
2064
+ req,
2065
+ void 0,
2066
+ true
2067
+ );
2068
+ const csrfHeader = getCsrfToken(csrf.headers, this.headers);
2069
+ const callbackUrl = req && "callbackUrl" in req ? String(req.callbackUrl) : "/";
2070
+ if (!csrfHeader) {
2071
+ this.logger?.debug && this.logger.debug("Request blocked from invalid csrf header");
2072
+ return new Response("Request blocked", { status: 400 });
2073
+ }
2074
+ const headers = new Headers(_init?.headers);
2075
+ const { csrfToken } = await csrf.json() ?? {};
2076
+ const cooks = getCookies(headers);
2077
+ if (csrfHeader) {
2078
+ if (cooks["__Secure-nile.csrf-token"]) {
2079
+ cooks["__Secure-nile.csrf-token"] = encodeURIComponent(csrfHeader);
2080
+ }
2081
+ if (cooks["nile.csrf-token"]) {
2082
+ cooks["nile.csrf-token"] = encodeURIComponent(csrfHeader);
2083
+ }
2084
+ }
2085
+ headers.set(
2086
+ "cookie",
2087
+ Object.keys(cooks).map((key12) => `${key12}=${cooks[key12]}`).join("; ")
2088
+ );
2089
+ const res = await _requester.post(req, this.signOutUrl, {
2090
+ method: "post",
2091
+ body: JSON.stringify({
2092
+ csrfToken,
2093
+ callbackUrl,
2094
+ json: String(true)
2095
+ }),
2096
+ ..._init,
2097
+ headers
2098
+ });
2099
+ this.resetHeaders && this.resetHeaders();
2100
+ return res;
2101
+ };
2102
+ };
2103
+ function getCallbackUrl2(headers) {
2104
+ if (headers) {
2105
+ const cookies = getCookies(headers);
2106
+ if (cookies) {
2107
+ return cookies["__Secure-nile.callback-url"] || cookies["nile.callback-url"];
2108
+ }
2109
+ }
2110
+ }
2111
+ function getCsrfToken(headers, initHeaders) {
2112
+ if (headers) {
2113
+ const cookies = getCookies(headers);
2114
+ let validCookie = "";
2115
+ if (cookies) {
2116
+ validCookie = cookies["__Secure-nile.csrf-token"] || cookies["nile.csrf-token"];
2117
+ }
2118
+ if (validCookie) {
2119
+ return validCookie;
2120
+ }
2121
+ }
2122
+ if (initHeaders) {
2123
+ const cookies = getCookies(initHeaders);
2124
+ if (cookies) {
2125
+ return cookies["__Secure-nile.csrf-token"] || cookies["nile.csrf-token"];
2126
+ }
2127
+ }
2128
+ }
2129
+ var getCookies = (headers) => {
2130
+ if (!headers) return {};
2131
+ const cookieHeader = headers.get("cookie") || "";
2132
+ const setCookieHeaders = headers.get("set-cookie") || "";
2133
+ const allCookies = [
2134
+ ...cookieHeader.split("; "),
2135
+ // Regular 'cookie' header (semicolon-separated)
2136
+ ...setCookieHeaders.split(/,\s*(?=[^;, ]+=)/)
2137
+ // Smart split for 'set-cookie'
2138
+ ].filter(Boolean);
2139
+ return Object.fromEntries(
2140
+ allCookies.map((cookie) => {
2141
+ const [key12, ...val] = cookie.split("=");
2142
+ return [
2143
+ decodeURIComponent(key12.trim()),
2144
+ decodeURIComponent(val.join("=").trim())
2145
+ ];
2146
+ })
2147
+ );
2011
2148
  };
2012
2149
 
2013
2150
  // src/tenants/index.ts
@@ -2214,7 +2351,9 @@ var Api = class {
2214
2351
  paths;
2215
2352
  constructor(config) {
2216
2353
  this.config = config;
2217
- this.auth = new Auth(config);
2354
+ this.auth = new Auth(config, void 0, {
2355
+ resetHeaders: this.resetHeaders
2356
+ });
2218
2357
  this.users = new Users(config);
2219
2358
  this.tenants = new Tenants(config);
2220
2359
  this.routes = {
@@ -2244,7 +2383,7 @@ var Api = class {
2244
2383
  this.routes.USERS,
2245
2384
  this.routes.TENANTS,
2246
2385
  this.routes.SESSION,
2247
- this.routes.SIGNIN,
2386
+ `${this.routes.SIGNIN}/{provider}`,
2248
2387
  this.routes.PASSWORD_RESET,
2249
2388
  this.routes.PROVIDERS,
2250
2389
  this.routes.CSRF,
@@ -2260,27 +2399,47 @@ var Api = class {
2260
2399
  delete: [this.routes.TENANT_USER, this.routes.TENANT]
2261
2400
  };
2262
2401
  }
2263
- updateConfig(config) {
2402
+ reset = () => {
2403
+ this.users = new Users(this.config, this._headers);
2404
+ this.tenants = new Tenants(this.config, this._headers);
2405
+ this.auth = new Auth(this.config, this._headers, {
2406
+ resetHeaders: this.resetHeaders
2407
+ });
2408
+ };
2409
+ updateConfig = (config) => {
2264
2410
  this.config = config;
2265
2411
  this.handlers = Handlers(this.routes, config);
2266
- }
2412
+ };
2413
+ resetHeaders = (headers) => {
2414
+ this._headers = new Headers(headers ?? {});
2415
+ this.reset();
2416
+ };
2267
2417
  set headers(headers) {
2268
- this.users = new Users(this.config, headers);
2269
- this.tenants = new Tenants(this.config, headers);
2270
- this.auth = new Auth(this.config, headers);
2271
2418
  this._headers = headers;
2419
+ this.reset();
2272
2420
  }
2273
- async login(payload) {
2274
- this.headers = await serverLogin(this.config, this.handlers)(payload);
2421
+ get headers() {
2422
+ return this._headers;
2275
2423
  }
2276
- async session(req) {
2424
+ login = async (payload, config) => {
2425
+ const [headers, loginRes] = await serverLogin(
2426
+ this.config,
2427
+ this.handlers
2428
+ )(payload);
2429
+ this.headers = headers;
2430
+ if (config?.returnResponse) {
2431
+ return loginRes;
2432
+ }
2433
+ return void 0;
2434
+ };
2435
+ session = async (req) => {
2277
2436
  if (req instanceof Headers) {
2278
2437
  return this.auth.getSession(req);
2279
2438
  } else if (req instanceof Request) {
2280
2439
  return auth(req, this.config);
2281
2440
  }
2282
2441
  return this.auth.getSession(this._headers);
2283
- }
2442
+ };
2284
2443
  };
2285
2444
 
2286
2445
  // src/Server.ts