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