@niledatabase/server 5.0.3-alpha.0 → 5.0.3-alpha.1
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 +238 -103
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +238 -103
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -298,8 +298,13 @@ function mergeCookies(...cookieStrings) {
|
|
|
298
298
|
}
|
|
299
299
|
return [...cookieMap.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
|
|
300
300
|
}
|
|
301
|
-
async function runExtensionContext(config) {
|
|
302
|
-
|
|
301
|
+
async function runExtensionContext(config, options) {
|
|
302
|
+
if (!options?.skipWithContext) {
|
|
303
|
+
await config?.extensionCtx?.runExtensions(
|
|
304
|
+
"withContext" /* withContext */,
|
|
305
|
+
config
|
|
306
|
+
);
|
|
307
|
+
}
|
|
303
308
|
await config?.extensionCtx?.runExtensions(
|
|
304
309
|
"withTenantId" /* withTenantId */,
|
|
305
310
|
config
|
|
@@ -369,38 +374,55 @@ var ctx = {
|
|
|
369
374
|
// for convenience only
|
|
370
375
|
getLastUsed: () => lastUsedContext
|
|
371
376
|
};
|
|
372
|
-
function withNileContext(config, fn, name = "unknown") {
|
|
377
|
+
async function withNileContext(config, fn, name = "unknown") {
|
|
373
378
|
const initialContext = config.context;
|
|
374
379
|
const existing = ctx.get();
|
|
375
|
-
const
|
|
380
|
+
const { overrides: extensionOverrides, ran: extensionRan } = await resolveExtensionOverrides(config, existing);
|
|
381
|
+
let mergedHeaders = new Headers(existing.headers);
|
|
382
|
+
let tenantId = existing.tenantId;
|
|
383
|
+
let userId = existing.userId;
|
|
376
384
|
if (initialContext instanceof Request) {
|
|
377
385
|
initialContext.headers.forEach((value, key17) => {
|
|
378
386
|
mergedHeaders.set(key17, value);
|
|
379
387
|
});
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
388
|
+
} else {
|
|
389
|
+
if (initialContext.headers === null) {
|
|
390
|
+
mergedHeaders = new Headers();
|
|
391
|
+
} else if (initialContext.headers) {
|
|
392
|
+
const incoming = initialContext.headers instanceof Headers ? initialContext.headers : new Headers(initialContext.headers);
|
|
393
|
+
incoming.forEach((value, key17) => {
|
|
394
|
+
mergedHeaders.set(key17, value);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
if ("tenantId" in initialContext) {
|
|
398
|
+
tenantId = initialContext.tenantId;
|
|
399
|
+
}
|
|
400
|
+
if ("userId" in initialContext) {
|
|
401
|
+
userId = initialContext.userId;
|
|
402
|
+
}
|
|
387
403
|
}
|
|
388
|
-
if (
|
|
389
|
-
const
|
|
390
|
-
|
|
404
|
+
if (extensionOverrides?.headers) {
|
|
405
|
+
for (const key17 of extensionOverrides.headers.removed) {
|
|
406
|
+
mergedHeaders.delete(key17);
|
|
407
|
+
}
|
|
408
|
+
for (const [key17, value] of extensionOverrides.headers.set) {
|
|
391
409
|
mergedHeaders.set(key17, value);
|
|
392
|
-
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (extensionOverrides?.tenantId) {
|
|
413
|
+
tenantId = extensionOverrides.tenantId.value;
|
|
414
|
+
}
|
|
415
|
+
if (extensionOverrides?.userId) {
|
|
416
|
+
userId = extensionOverrides.userId.value;
|
|
393
417
|
}
|
|
394
|
-
const hasTenantId = "tenantId" in initialContext;
|
|
395
|
-
const hasUserId = "userId" in initialContext;
|
|
396
418
|
const context = {
|
|
397
419
|
headers: mergedHeaders,
|
|
398
|
-
tenantId
|
|
399
|
-
userId
|
|
420
|
+
tenantId,
|
|
421
|
+
userId
|
|
400
422
|
};
|
|
401
|
-
silly(`${name} [INITIAL
|
|
423
|
+
silly(`${name} [INITIAL] ${serializeContext(context)}`);
|
|
402
424
|
return ctx.run(context, async () => {
|
|
403
|
-
await runExtensionContext(config);
|
|
425
|
+
await runExtensionContext(config, { skipWithContext: extensionRan });
|
|
404
426
|
return fn();
|
|
405
427
|
});
|
|
406
428
|
}
|
|
@@ -426,10 +448,81 @@ function parseCookieHeader(header) {
|
|
|
426
448
|
function serializeCookies(cookies) {
|
|
427
449
|
return Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
428
450
|
}
|
|
451
|
+
async function resolveExtensionOverrides(config, existing) {
|
|
452
|
+
if (!config.extensions?.length || !config.extensionCtx) {
|
|
453
|
+
return { ran: false };
|
|
454
|
+
}
|
|
455
|
+
let updated;
|
|
456
|
+
await ctx.run(
|
|
457
|
+
{
|
|
458
|
+
headers: new Headers(existing.headers),
|
|
459
|
+
tenantId: existing.tenantId,
|
|
460
|
+
userId: existing.userId
|
|
461
|
+
},
|
|
462
|
+
async () => {
|
|
463
|
+
await config.extensionCtx?.runExtensions(
|
|
464
|
+
"withContext" /* withContext */,
|
|
465
|
+
config
|
|
466
|
+
);
|
|
467
|
+
updated = ctx.get();
|
|
468
|
+
}
|
|
469
|
+
);
|
|
470
|
+
if (!updated) {
|
|
471
|
+
return { ran: true };
|
|
472
|
+
}
|
|
473
|
+
const diff = diffContext(existing, updated);
|
|
474
|
+
return { overrides: diff, ran: true };
|
|
475
|
+
}
|
|
476
|
+
function diffContext(before, after) {
|
|
477
|
+
const headers = diffHeaders(before.headers, after.headers);
|
|
478
|
+
const tenantChanged = before.tenantId !== after.tenantId;
|
|
479
|
+
const userChanged = before.userId !== after.userId;
|
|
480
|
+
if (!headers && !tenantChanged && !userChanged) {
|
|
481
|
+
return void 0;
|
|
482
|
+
}
|
|
483
|
+
const overrides = {};
|
|
484
|
+
if (headers) {
|
|
485
|
+
overrides.headers = headers;
|
|
486
|
+
}
|
|
487
|
+
if (tenantChanged) {
|
|
488
|
+
overrides.tenantId = { value: after.tenantId };
|
|
489
|
+
}
|
|
490
|
+
if (userChanged) {
|
|
491
|
+
overrides.userId = { value: after.userId };
|
|
492
|
+
}
|
|
493
|
+
return overrides;
|
|
494
|
+
}
|
|
495
|
+
function diffHeaders(before, after) {
|
|
496
|
+
const beforeMap = headersToMap(before);
|
|
497
|
+
const afterMap = headersToMap(after);
|
|
498
|
+
const set = [];
|
|
499
|
+
const removed = [];
|
|
500
|
+
for (const [key17, value] of afterMap.entries()) {
|
|
501
|
+
if (beforeMap.get(key17) !== value) {
|
|
502
|
+
set.push([key17, value]);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
for (const key17 of beforeMap.keys()) {
|
|
506
|
+
if (!afterMap.has(key17)) {
|
|
507
|
+
removed.push(key17);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (set.length === 0 && removed.length === 0) {
|
|
511
|
+
return void 0;
|
|
512
|
+
}
|
|
513
|
+
return { set, removed };
|
|
514
|
+
}
|
|
515
|
+
function headersToMap(headers) {
|
|
516
|
+
const map = /* @__PURE__ */ new Map();
|
|
517
|
+
headers.forEach((value, key17) => {
|
|
518
|
+
map.set(key17.toLowerCase(), value);
|
|
519
|
+
});
|
|
520
|
+
return map;
|
|
521
|
+
}
|
|
429
522
|
|
|
430
523
|
// src/api/utils/request.ts
|
|
431
524
|
async function request(url, _init, config) {
|
|
432
|
-
const { debug, info, error
|
|
525
|
+
const { debug, info, error } = config.logger("[REQUEST]");
|
|
433
526
|
const { request: request2, ...init } = _init;
|
|
434
527
|
const requestUrl = new URL(request2.url);
|
|
435
528
|
const updatedHeaders = new Headers({});
|
|
@@ -2405,79 +2498,89 @@ var Auth = class {
|
|
|
2405
2498
|
* from the internal configuration once the request completes.
|
|
2406
2499
|
*/
|
|
2407
2500
|
async signOut() {
|
|
2408
|
-
return withNileContext(
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2501
|
+
return withNileContext(
|
|
2502
|
+
this.#config,
|
|
2503
|
+
async () => {
|
|
2504
|
+
const csrfRes = await this.getCsrf();
|
|
2505
|
+
if (!("csrfToken" in csrfRes)) {
|
|
2506
|
+
throw new Error("Unable to obtain CSRF token. Sign out failed.");
|
|
2507
|
+
}
|
|
2508
|
+
const body = JSON.stringify({
|
|
2509
|
+
csrfToken: csrfRes.csrfToken,
|
|
2510
|
+
json: true
|
|
2511
|
+
});
|
|
2512
|
+
const res = await fetchSignOut(this.#config, body);
|
|
2513
|
+
updateHeaders(new Headers({}));
|
|
2514
|
+
ctx.set({ headers: null });
|
|
2515
|
+
return res;
|
|
2516
|
+
},
|
|
2517
|
+
"signout"
|
|
2518
|
+
);
|
|
2422
2519
|
}
|
|
2423
2520
|
async signUp(payload, rawResponse) {
|
|
2424
|
-
return withNileContext(
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
this.#
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2521
|
+
return withNileContext(
|
|
2522
|
+
this.#config,
|
|
2523
|
+
async () => {
|
|
2524
|
+
ctx.set({ headers: null });
|
|
2525
|
+
const { email, password, ...params } = payload;
|
|
2526
|
+
if (!email || !password) {
|
|
2527
|
+
throw new Error(
|
|
2528
|
+
"Server side sign up requires a user email and password."
|
|
2529
|
+
);
|
|
2530
|
+
}
|
|
2531
|
+
const providers = await this.listProviders();
|
|
2532
|
+
const { credentials } = providers ?? {};
|
|
2533
|
+
if (!credentials) {
|
|
2534
|
+
throw new Error(
|
|
2535
|
+
"Unable to obtain credential provider. Aborting server side sign up."
|
|
2536
|
+
);
|
|
2537
|
+
}
|
|
2538
|
+
const csrf = await obtainCsrf(this.#config);
|
|
2539
|
+
let csrfToken;
|
|
2540
|
+
if ("csrfToken" in csrf) {
|
|
2541
|
+
csrfToken = csrf.csrfToken;
|
|
2542
|
+
} else {
|
|
2543
|
+
throw new Error("Unable to obtain parse CSRF. Request blocked.");
|
|
2544
|
+
}
|
|
2545
|
+
const body = JSON.stringify({
|
|
2546
|
+
email,
|
|
2547
|
+
password,
|
|
2548
|
+
csrfToken,
|
|
2549
|
+
callbackUrl: credentials.callbackUrl
|
|
2550
|
+
});
|
|
2551
|
+
const res = await fetchSignUp(this.#config, { body, params });
|
|
2552
|
+
if (res.status > 299) {
|
|
2553
|
+
this.#logger.error(await res.clone().text());
|
|
2554
|
+
return void 0;
|
|
2555
|
+
}
|
|
2556
|
+
const token = parseToken(res.headers);
|
|
2557
|
+
if (!token) {
|
|
2558
|
+
throw new Error(
|
|
2559
|
+
"Server side sign up failed. Session token not found"
|
|
2560
|
+
);
|
|
2561
|
+
}
|
|
2562
|
+
const { headers } = ctx.get();
|
|
2563
|
+
headers?.append("cookie", token);
|
|
2564
|
+
ctx.set({ headers });
|
|
2565
|
+
updateHeaders(headers);
|
|
2566
|
+
if (rawResponse) {
|
|
2567
|
+
return res;
|
|
2568
|
+
}
|
|
2569
|
+
try {
|
|
2570
|
+
const json = await res.clone().json();
|
|
2571
|
+
if (json && typeof json === "object" && "tenants" in json) {
|
|
2572
|
+
const tenantId = json.tenants[0];
|
|
2573
|
+
if (tenantId) {
|
|
2574
|
+
updateTenantId(tenantId);
|
|
2575
|
+
}
|
|
2474
2576
|
}
|
|
2577
|
+
return json;
|
|
2578
|
+
} catch {
|
|
2579
|
+
return res;
|
|
2475
2580
|
}
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
}
|
|
2480
|
-
});
|
|
2581
|
+
},
|
|
2582
|
+
"signup"
|
|
2583
|
+
);
|
|
2481
2584
|
}
|
|
2482
2585
|
/**
|
|
2483
2586
|
* Request a password reset email.
|
|
@@ -2960,17 +3063,21 @@ var Users = class {
|
|
|
2960
3063
|
});
|
|
2961
3064
|
}
|
|
2962
3065
|
async getSelf(rawResponse) {
|
|
2963
|
-
return withNileContext(
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
3066
|
+
return withNileContext(
|
|
3067
|
+
this.#config,
|
|
3068
|
+
async () => {
|
|
3069
|
+
const res = await fetchMe(this.#config);
|
|
3070
|
+
if (rawResponse) {
|
|
3071
|
+
return res;
|
|
3072
|
+
}
|
|
3073
|
+
try {
|
|
3074
|
+
return await res?.clone().json();
|
|
3075
|
+
} catch {
|
|
3076
|
+
return res;
|
|
3077
|
+
}
|
|
3078
|
+
},
|
|
3079
|
+
"getSelf"
|
|
3080
|
+
);
|
|
2974
3081
|
}
|
|
2975
3082
|
async verifySelf(options, rawResponse = false) {
|
|
2976
3083
|
return withNileContext(this.#config, async () => {
|
|
@@ -3534,8 +3641,11 @@ var Server = class {
|
|
|
3534
3641
|
const context = isFn ? {} : contextOrFn ?? {};
|
|
3535
3642
|
const fn = isFn ? contextOrFn : maybeFn;
|
|
3536
3643
|
const preserve = "useLastContext" in context ? context.useLastContext : true;
|
|
3644
|
+
let hydrated;
|
|
3537
3645
|
if (preserve) {
|
|
3538
|
-
|
|
3646
|
+
hydrated = await this.#hydrateContextFromExtensions();
|
|
3647
|
+
const base = hydrated ?? this.#config.context;
|
|
3648
|
+
this.#config.context = { ...base, ...context };
|
|
3539
3649
|
} else {
|
|
3540
3650
|
this.#config.context = { ...defaultContext, ...context };
|
|
3541
3651
|
}
|
|
@@ -3607,6 +3717,31 @@ var Server = class {
|
|
|
3607
3717
|
}
|
|
3608
3718
|
this.#config.logger("[handleHeaders]").debug(JSON.stringify(merged));
|
|
3609
3719
|
}
|
|
3720
|
+
async #hydrateContextFromExtensions() {
|
|
3721
|
+
if (!this.#config.extensions || this.#config.extensions.length === 0) {
|
|
3722
|
+
return void 0;
|
|
3723
|
+
}
|
|
3724
|
+
let updated;
|
|
3725
|
+
await ctx.run({}, async () => {
|
|
3726
|
+
await this.#config.extensionCtx?.runExtensions(
|
|
3727
|
+
"withContext" /* withContext */,
|
|
3728
|
+
this.#config
|
|
3729
|
+
);
|
|
3730
|
+
updated = ctx.get();
|
|
3731
|
+
});
|
|
3732
|
+
if (!updated) {
|
|
3733
|
+
return void 0;
|
|
3734
|
+
}
|
|
3735
|
+
const hydrated = {
|
|
3736
|
+
headers: new Headers(updated.headers),
|
|
3737
|
+
tenantId: updated.tenantId,
|
|
3738
|
+
userId: updated.userId
|
|
3739
|
+
};
|
|
3740
|
+
this.#config.context.headers = new Headers(hydrated.headers);
|
|
3741
|
+
this.#config.context.tenantId = hydrated.tenantId;
|
|
3742
|
+
this.#config.context.userId = hydrated.userId;
|
|
3743
|
+
return hydrated;
|
|
3744
|
+
}
|
|
3610
3745
|
/**
|
|
3611
3746
|
* Allow some internal mutations to reset our config + headers
|
|
3612
3747
|
*/
|