@niledatabase/server 5.0.0-alpha.14 → 5.0.0-alpha.15

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
@@ -2,6 +2,12 @@ import 'dotenv/config';
2
2
  import pg from 'pg';
3
3
 
4
4
  // src/types.ts
5
+ var ExtensionState = /* @__PURE__ */ ((ExtensionState2) => {
6
+ ExtensionState2["onHandleRequest"] = "onHandleRequest";
7
+ ExtensionState2["onRequest"] = "onRequest";
8
+ ExtensionState2["onResponse"] = "onResposne";
9
+ return ExtensionState2;
10
+ })(ExtensionState || {});
5
11
  var APIErrorErrorCodeEnum = {
6
12
  InternalError: "internal_error",
7
13
  BadRequest: "bad_request",
@@ -183,7 +189,12 @@ async function request(url, _init, config) {
183
189
  params.headers.set("request-id", crypto.randomUUID());
184
190
  params.cache = "no-store";
185
191
  }
186
- await config.extensionCtx?.handleOnRequest(config, _init, params);
192
+ await config.extensionCtx?.runExtensions(
193
+ "onRequest" /* onRequest */,
194
+ config,
195
+ params,
196
+ _init
197
+ );
187
198
  try {
188
199
  const res = await fetch(fullUrl, {
189
200
  ...params
@@ -203,6 +214,14 @@ async function request(url, _init, config) {
203
214
  statusText: res?.statusText,
204
215
  text: await loggingRes?.text()
205
216
  });
217
+ const updatedRes = await config.extensionCtx?.runExtensions(
218
+ "onResposne" /* onResponse */,
219
+ config,
220
+ params
221
+ );
222
+ if (updatedRes) {
223
+ return updatedRes;
224
+ }
206
225
  return res;
207
226
  } catch (e) {
208
227
  if (e instanceof Error) {
@@ -226,16 +245,13 @@ async function auth(req, config) {
226
245
  info(`using session ${sessionUrl}`);
227
246
  req.headers.delete("content-length");
228
247
  const res = await request(sessionUrl, { request: req }, config);
229
- if (!res) {
230
- info("no session found");
231
- return void 0;
232
- }
233
- info("session active");
234
248
  try {
235
249
  const session = await new Response(res.body).json();
236
250
  if (Object.keys(session).length === 0) {
251
+ info("no session found");
237
252
  return void 0;
238
253
  }
254
+ info("session active");
239
255
  return session;
240
256
  } catch (e) {
241
257
  error(e);
@@ -474,7 +490,7 @@ async function PUT3(config, init) {
474
490
  init.method = "PUT";
475
491
  const url = `${apiRoutes(config).INVITE(tenantId)}`;
476
492
  const res = await request(url, init, config);
477
- const location = res?.headers.get("location");
493
+ const location = res?.headers?.get("location");
478
494
  if (location) {
479
495
  return new Response(res?.body, {
480
496
  status: 302,
@@ -847,7 +863,7 @@ async function route11(req, config) {
847
863
  ).catch((e) => {
848
864
  error("an error as occurred", e);
849
865
  });
850
- const location = res?.headers.get("location");
866
+ const location = res?.headers?.get("location");
851
867
  if (location) {
852
868
  return new Response(res?.body, {
853
869
  status: 302,
@@ -948,7 +964,7 @@ async function route15(req, config) {
948
964
  },
949
965
  config
950
966
  );
951
- const location = res?.headers.get("location");
967
+ const location = res?.headers?.get("location");
952
968
  if (location) {
953
969
  return new Response(res?.body, {
954
970
  status: 302,
@@ -992,7 +1008,7 @@ async function route16(req, config) {
992
1008
  },
993
1009
  config
994
1010
  );
995
- const location = res?.headers.get("location");
1011
+ const location = res?.headers?.get("location");
996
1012
  if (location) {
997
1013
  return new Response(res?.body, {
998
1014
  status: 302,
@@ -1022,8 +1038,21 @@ async function fetchVerifyEmail(config, method, body) {
1022
1038
 
1023
1039
  // src/api/handlers/GET.ts
1024
1040
  function GETTER(configRoutes, config) {
1025
- const { info, warn } = config.logger("[GET MATCHER]");
1026
- return async function GET7(req) {
1041
+ const { error, info, warn } = config.logger("[GET MATCHER]");
1042
+ return async function GET7(...params) {
1043
+ const handledRequest = await config.extensionCtx?.runExtensions(
1044
+ "onHandleRequest" /* onHandleRequest */,
1045
+ config,
1046
+ params
1047
+ );
1048
+ if (handledRequest) {
1049
+ return handledRequest;
1050
+ }
1051
+ const req = params[0] instanceof Request ? params[0] : null;
1052
+ if (!req) {
1053
+ error("Proxy requests failed, a Request object was not passed.");
1054
+ return;
1055
+ }
1027
1056
  if (matches(configRoutes, req)) {
1028
1057
  info("matches me");
1029
1058
  return route(req, config);
@@ -1197,7 +1226,20 @@ async function fetchSignUp(config, payload) {
1197
1226
  // src/api/handlers/POST.ts
1198
1227
  function POSTER(configRoutes, config) {
1199
1228
  const { info, warn, error } = config.logger("[POST MATCHER]");
1200
- return async function POST6(req) {
1229
+ return async function POST6(...params) {
1230
+ const handledRequest = await config.extensionCtx?.runExtensions(
1231
+ "onHandleRequest" /* onHandleRequest */,
1232
+ config,
1233
+ params
1234
+ );
1235
+ if (handledRequest) {
1236
+ return handledRequest;
1237
+ }
1238
+ const req = params[0] instanceof Request ? params[0] : null;
1239
+ if (!req) {
1240
+ error("Proxy requests failed, a Request object was not passed.");
1241
+ return;
1242
+ }
1201
1243
  if (matchesLog(configRoutes, req)) {
1202
1244
  try {
1203
1245
  const json = await req.clone().json();
@@ -1372,8 +1414,21 @@ function matches19(configRoutes, request2) {
1372
1414
 
1373
1415
  // src/api/handlers/DELETE.ts
1374
1416
  function DELETER(configRoutes, config) {
1375
- const { info, warn } = config.logger("[DELETE MATCHER]");
1376
- return async function DELETE5(req) {
1417
+ const { error, info, warn } = config.logger("[DELETE MATCHER]");
1418
+ return async function DELETE5(...params) {
1419
+ const handledRequest = await config.extensionCtx?.runExtensions(
1420
+ "onHandleRequest" /* onHandleRequest */,
1421
+ config,
1422
+ params
1423
+ );
1424
+ if (handledRequest) {
1425
+ return handledRequest;
1426
+ }
1427
+ const req = params[0] instanceof Request ? params[0] : null;
1428
+ if (!req) {
1429
+ error("Proxy requests failed, a Request object was not passed.");
1430
+ return;
1431
+ }
1377
1432
  if (matches19(configRoutes, req)) {
1378
1433
  info("matches tenant invite id");
1379
1434
  return route19(req, config);
@@ -1382,10 +1437,6 @@ function DELETER(configRoutes, config) {
1382
1437
  info("matches tenant user");
1383
1438
  return route18(req, config);
1384
1439
  }
1385
- if (matches3(configRoutes, req)) {
1386
- info("matches tenant users");
1387
- return route3(req, config);
1388
- }
1389
1440
  if (matches6(configRoutes, req)) {
1390
1441
  info("matches tenants");
1391
1442
  return route6(req, config);
@@ -1401,8 +1452,21 @@ function DELETER(configRoutes, config) {
1401
1452
 
1402
1453
  // src/api/handlers/PUT.ts
1403
1454
  function PUTER(configRoutes, config) {
1404
- const { info, warn } = config.logger("[PUT MATCHER]");
1405
- return async function PUT6(req) {
1455
+ const { error, info, warn } = config.logger("[PUT MATCHER]");
1456
+ return async function PUT6(...params) {
1457
+ const handledRequest = await config.extensionCtx?.runExtensions(
1458
+ "onHandleRequest" /* onHandleRequest */,
1459
+ config,
1460
+ params
1461
+ );
1462
+ if (handledRequest) {
1463
+ return handledRequest;
1464
+ }
1465
+ const req = params[0] instanceof Request ? params[0] : null;
1466
+ if (!req) {
1467
+ error("Proxy requests failed, a Request object was not passed.");
1468
+ return;
1469
+ }
1406
1470
  if (matches4(configRoutes, req)) {
1407
1471
  info("matches tenant invite");
1408
1472
  return route4(req, config);
@@ -2341,6 +2405,9 @@ var Auth = class {
2341
2405
  }
2342
2406
  info(`Obtaining providers for ${email}`);
2343
2407
  info(`Attempting sign in with email ${email}`);
2408
+ if (!email) {
2409
+ throw new Error("Email missing from payload, unable to sign in");
2410
+ }
2344
2411
  const body = JSON.stringify({
2345
2412
  email,
2346
2413
  password,
@@ -2458,6 +2525,7 @@ function defaultCallbackUrl({ config }) {
2458
2525
  async function obtainCsrf(config, rawResponse = false) {
2459
2526
  const res = await fetchCsrf(config);
2460
2527
  const csrfCook = parseCSRF(res.headers);
2528
+ const h = new Headers();
2461
2529
  if (csrfCook) {
2462
2530
  const [, value] = csrfCook.split("=");
2463
2531
  const [token] = decodeURIComponent(value).split("|");
@@ -2469,7 +2537,8 @@ async function obtainCsrf(config, rawResponse = false) {
2469
2537
  parseToken(res.headers)
2470
2538
  ].filter(Boolean).join("; ");
2471
2539
  config.headers.set("cookie", cookie);
2472
- updateHeaders(new Headers({ cookie }));
2540
+ h.set("cookie", cookie);
2541
+ updateHeaders(h);
2473
2542
  }
2474
2543
  if (!rawResponse) {
2475
2544
  return { csrfToken: token };
@@ -2917,24 +2986,26 @@ function handlersWithContext(config) {
2917
2986
  function updateConfig(response, config) {
2918
2987
  let origin = "http://localhost:3000";
2919
2988
  let headers = null;
2920
- if (response?.status === 302) {
2921
- const location = response.headers.get("location");
2922
- if (location) {
2923
- const urlLocation = new URL(location);
2924
- origin = urlLocation.origin;
2989
+ if (response instanceof Response) {
2990
+ if (response?.status === 302) {
2991
+ const location = response.headers.get("location");
2992
+ if (location) {
2993
+ const urlLocation = new URL(location);
2994
+ origin = urlLocation.origin;
2995
+ }
2925
2996
  }
2926
- }
2927
- const setCookies = [];
2928
- if (response?.headers) {
2929
- for (const [key17, value] of response.headers) {
2930
- if (key17.toLowerCase() === "set-cookie") {
2931
- setCookies.push(value);
2997
+ const setCookies = [];
2998
+ if (response?.headers) {
2999
+ for (const [key17, value] of response.headers) {
3000
+ if (key17.toLowerCase() === "set-cookie") {
3001
+ setCookies.push(value);
3002
+ }
2932
3003
  }
2933
3004
  }
2934
- }
2935
- if (setCookies.length > 0) {
2936
- const cookieHeader = setCookies.map((cookieStr) => cookieStr.split(";")[0]).join("; ");
2937
- headers = new Headers({ cookie: cookieHeader });
3005
+ if (setCookies.length > 0) {
3006
+ const cookieHeader = setCookies.map((cookieStr) => cookieStr.split(";")[0]).join("; ");
3007
+ headers = new Headers({ cookie: cookieHeader });
3008
+ }
2938
3009
  }
2939
3010
  return {
2940
3011
  ...config,
@@ -2945,26 +3016,51 @@ function updateConfig(response, config) {
2945
3016
  }
2946
3017
 
2947
3018
  // src/api/utils/extensions.ts
2948
- function bindHandleOnRequest(instance) {
2949
- return async function handleOnRequest(config, _init, params) {
3019
+ function getRequestConfig(params) {
3020
+ if (typeof params[1] === "object") {
3021
+ return params[1];
3022
+ }
3023
+ return {};
3024
+ }
3025
+ function bindRunExtensions(instance) {
3026
+ return async function runExtensions(toRun, config, params, _init) {
2950
3027
  const { debug } = config.logger("[EXTENSIONS]");
3028
+ const extensionConfig = getRequestConfig(
3029
+ Array.isArray(params) ? params : [null, params]
3030
+ );
2951
3031
  if (config.extensions) {
2952
3032
  for (const create2 of config.extensions) {
2953
3033
  if (typeof create2 !== "function") {
2954
- return void 0;
3034
+ continue;
3035
+ }
3036
+ const ext = create2(instance);
3037
+ if (extensionConfig.disableExtensions?.includes(ext.id)) {
3038
+ continue;
2955
3039
  }
2956
- const ext = await create2(instance);
2957
- if (ext.onRequest) {
3040
+ if (ext.onHandleRequest && toRun === "onHandleRequest" /* onHandleRequest */) {
3041
+ const result = await ext.onHandleRequest(
3042
+ ...Array.isArray(params) ? params : [params]
3043
+ );
3044
+ if (result != null) {
3045
+ return result;
3046
+ }
3047
+ continue;
3048
+ }
3049
+ const [param] = Array.isArray(params) ? params : [params];
3050
+ if (ext.onRequest && toRun === "onRequest" /* onRequest */) {
2958
3051
  const previousContext = instance.getContext();
2959
3052
  if (previousContext.preserveHeaders) {
2960
3053
  instance.setContext({ preserveHeaders: false });
2961
3054
  }
3055
+ if (!_init) {
3056
+ continue;
3057
+ }
2962
3058
  await ext.onRequest(_init.request);
2963
3059
  const updatedContext = instance.getContext();
2964
3060
  if (updatedContext?.headers) {
2965
3061
  const cookie = updatedContext.headers.get("cookie");
2966
- if (cookie) {
2967
- params.headers.set(
3062
+ if (cookie && param.headers) {
3063
+ param.headers.set(
2968
3064
  "cookie",
2969
3065
  mergeCookies(
2970
3066
  previousContext.preserveHeaders ? previousContext.headers?.get("cookie") : null,
@@ -2972,22 +3068,31 @@ function bindHandleOnRequest(instance) {
2972
3068
  )
2973
3069
  );
2974
3070
  }
2975
- if (updatedContext.tenantId) {
2976
- params.headers.set(
3071
+ if (updatedContext.tenantId && param.headers) {
3072
+ param.headers.set(
2977
3073
  TENANT_COOKIE,
2978
3074
  String(updatedContext.headers.get(TENANT_COOKIE))
2979
3075
  );
2980
3076
  }
2981
3077
  }
2982
3078
  debug(`${ext.id ?? create2.name} ran onRequest`);
3079
+ continue;
3080
+ }
3081
+ if (ext.onResponse && toRun === "onResposne" /* onResponse */) {
3082
+ const result = await ext.onResponse(param);
3083
+ if (result != null) {
3084
+ return result;
3085
+ }
3086
+ continue;
2983
3087
  }
2984
3088
  }
2985
3089
  }
3090
+ return void 0;
2986
3091
  };
2987
3092
  }
2988
3093
  function buildExtensionConfig(instance) {
2989
3094
  return {
2990
- handleOnRequest: bindHandleOnRequest(instance)
3095
+ runExtensions: bindRunExtensions(instance)
2991
3096
  };
2992
3097
  }
2993
3098
  function mergeCookies(...cookieStrings) {
@@ -3009,7 +3114,6 @@ var Server = class {
3009
3114
  auth;
3010
3115
  #config;
3011
3116
  #handlers;
3012
- #paths;
3013
3117
  #manager;
3014
3118
  #headers;
3015
3119
  #preserveHeaders;
@@ -3039,13 +3143,23 @@ var Server = class {
3039
3143
  withContext: handlersWithContext(this.#config)
3040
3144
  };
3041
3145
  this.#preserveHeaders = config?.preserveHeaders ?? false;
3042
- this.#paths = this.#config.paths;
3043
3146
  this.#config.tenantId = getTenantId({ config: this.#config });
3044
3147
  this.#manager = new DBManager(this.#config);
3045
3148
  this.#handleHeaders(config);
3046
3149
  this.users = new Users(this.#config);
3047
3150
  this.tenants = new Tenants(this.#config);
3048
3151
  this.auth = new Auth(this.#config);
3152
+ if (config?.extensions) {
3153
+ for (const create2 of config.extensions) {
3154
+ if (typeof create2 !== "function") {
3155
+ continue;
3156
+ }
3157
+ const ext = create2(this);
3158
+ if (ext.onConfigure) {
3159
+ ext.onConfigure();
3160
+ }
3161
+ }
3162
+ }
3049
3163
  }
3050
3164
  get db() {
3051
3165
  const pool = this.#manager.getConnection(this.#config);
@@ -3055,6 +3169,28 @@ var Server = class {
3055
3169
  }
3056
3170
  });
3057
3171
  }
3172
+ get logger() {
3173
+ return this.#config.logger;
3174
+ }
3175
+ get extensions() {
3176
+ return {
3177
+ remove: async (id) => {
3178
+ if (!this.#config.extensions) return;
3179
+ const resolved = this.#config.extensions.map((ext) => ext(this));
3180
+ const index = resolved.findIndex((ext) => ext.id === id);
3181
+ if (index !== -1) {
3182
+ this.#config.extensions.splice(index, 1);
3183
+ }
3184
+ return resolved;
3185
+ },
3186
+ add: (extension) => {
3187
+ if (!this.#config.extensions) {
3188
+ this.#config.extensions = [];
3189
+ }
3190
+ this.#config.extensions.push(extension);
3191
+ }
3192
+ };
3193
+ }
3058
3194
  /**
3059
3195
  * A convenience function that applies a config and ensures whatever was passed is set properly
3060
3196
  */
@@ -3070,12 +3206,15 @@ var Server = class {
3070
3206
  this.#reset();
3071
3207
  return this;
3072
3208
  }
3073
- getPaths() {
3074
- return this.#paths;
3075
- }
3076
3209
  get handlers() {
3077
3210
  return this.#handlers;
3078
3211
  }
3212
+ get paths() {
3213
+ return this.#config.paths;
3214
+ }
3215
+ set paths(paths) {
3216
+ this.#config.paths = paths;
3217
+ }
3079
3218
  /**
3080
3219
  * Allow the setting of headers from a req or header object.
3081
3220
  * Makes it possible to handle REST requests easily
@@ -3083,7 +3222,27 @@ var Server = class {
3083
3222
  * @param req
3084
3223
  * @returns undefined
3085
3224
  */
3086
- setContext(req) {
3225
+ setContext = (req, ...remaining) => {
3226
+ let atLeastOne = false;
3227
+ if (this.#config?.extensions) {
3228
+ for (const create2 of this.#config.extensions) {
3229
+ if (typeof create2 !== "function") {
3230
+ continue;
3231
+ }
3232
+ const ext = create2(this);
3233
+ if (typeof ext.onSetContext === "function") {
3234
+ if (req) {
3235
+ ext.onSetContext(req, ...remaining);
3236
+ atLeastOne = true;
3237
+ } else {
3238
+ this.#config.logger("extension").warn("attempted to call onSetContext without a value");
3239
+ }
3240
+ }
3241
+ }
3242
+ }
3243
+ if (atLeastOne) {
3244
+ return;
3245
+ }
3087
3246
  try {
3088
3247
  if (req instanceof Headers) {
3089
3248
  this.#handleHeaders(req);
@@ -3113,11 +3272,14 @@ var Server = class {
3113
3272
  return;
3114
3273
  }
3115
3274
  if (typeof req === "object") {
3116
- const headers = new Headers(req);
3117
- if (headers) {
3118
- this.#handleHeaders(headers);
3119
- this.#reset();
3120
- return;
3275
+ try {
3276
+ const headers = new Headers(req);
3277
+ if (headers) {
3278
+ this.#handleHeaders(headers);
3279
+ this.#reset();
3280
+ return;
3281
+ }
3282
+ } catch {
3121
3283
  }
3122
3284
  }
3123
3285
  const { warn } = Logger(this.#config)("[API]");
@@ -3126,12 +3288,12 @@ var Server = class {
3126
3288
  "Set context expects a Request, Header instance or an object of Record<string, string>"
3127
3289
  );
3128
3290
  }
3129
- }
3291
+ };
3130
3292
  getContext() {
3131
3293
  return {
3132
3294
  headers: this.#headers,
3133
- userId: this.#config.userId,
3134
- tenantId: this.#config.tenantId,
3295
+ userId: this.#config?.userId,
3296
+ tenantId: this.#config?.tenantId,
3135
3297
  preserveHeaders: this.#preserveHeaders
3136
3298
  };
3137
3299
  }
@@ -3184,6 +3346,7 @@ var Server = class {
3184
3346
  */
3185
3347
  #reset = () => {
3186
3348
  this.#config.headers = this.#headers ?? new Headers();
3349
+ this.#config.extensionCtx = buildExtensionConfig(this);
3187
3350
  this.users = new Users(this.#config);
3188
3351
  this.tenants = new Tenants(this.#config);
3189
3352
  this.auth = new Auth(this.#config);
@@ -3197,6 +3360,6 @@ function create(config) {
3197
3360
  return server;
3198
3361
  }
3199
3362
 
3200
- export { APIErrorErrorCodeEnum, HEADER_ORIGIN, HEADER_SECURE_COOKIES, LoginUserResponseTokenTypeEnum, create as Nile, Server, TENANT_COOKIE, USER_COOKIE, parseCSRF, parseCallback, parseToken };
3363
+ export { APIErrorErrorCodeEnum, ExtensionState, HEADER_ORIGIN, HEADER_SECURE_COOKIES, LoginUserResponseTokenTypeEnum, create as Nile, Server, TENANT_COOKIE, USER_COOKIE, parseCSRF, parseCallback, parseResetToken, parseToken };
3201
3364
  //# sourceMappingURL=index.mjs.map
3202
3365
  //# sourceMappingURL=index.mjs.map