@rpcbase/server 0.513.0 → 0.515.0
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/applyRouteLoaders.d.ts.map +1 -1
- package/dist/{email-DEw8keax.js → email-DK8uUU4X.js} +5 -2
- package/dist/{email-DEw8keax.js.map → email-DK8uUU4X.js.map} +1 -1
- package/dist/{handler-r-HYO3Oy.js → handler-3gksYOQv.js} +299 -99
- package/dist/{handler-r-HYO3Oy.js.map → handler-3gksYOQv.js.map} +1 -1
- package/dist/{handler-BNrqh1Kb.js → handler-BsauvgjA.js} +58 -19
- package/dist/{handler-BNrqh1Kb.js.map → handler-BsauvgjA.js.map} +1 -1
- package/dist/{handler-Cohj3cz3.js → handler-DY5UEwlw.js} +45 -18
- package/dist/{handler-Cohj3cz3.js.map → handler-DY5UEwlw.js.map} +1 -1
- package/dist/{handler-Bh3a6Br1.js → handler-GZgk5k3c.js} +326 -130
- package/dist/{handler-Bh3a6Br1.js.map → handler-GZgk5k3c.js.map} +1 -1
- package/dist/index.js +315 -155
- package/dist/index.js.map +1 -1
- package/dist/notifications.js +103 -32
- package/dist/notifications.js.map +1 -1
- package/dist/{queryExecutor-DSCpsVI8.js → queryExecutor-Dn62mIDL.js} +47 -33
- package/dist/{queryExecutor-DSCpsVI8.js.map → queryExecutor-Dn62mIDL.js.map} +1 -1
- package/dist/renderSSR.d.ts.map +1 -1
- package/dist/rts/index.js +99 -21
- package/dist/rts/index.js.map +1 -1
- package/dist/{shared-BJomDDWK.js → shared-Dy9x-P7F.js} +10 -7
- package/dist/{shared-BJomDDWK.js.map → shared-Dy9x-P7F.js.map} +1 -1
- package/dist/ssrMiddleware.d.ts.map +1 -1
- package/dist/uploads.js +1 -1
- package/dist/uploads.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { dirname, posix, sep } from "path";
|
|
|
9
9
|
import fs, { createReadStream, readFileSync } from "node:fs";
|
|
10
10
|
import { createInterface } from "node:readline";
|
|
11
11
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
12
|
-
import { g as getDerivedKey, r as resolveRtsRequestTenantId, i as isRtsRequestAuthorized, b as buildRtsAbilityFromRequest, n as normalizeRtsQueryOptions, a as runRtsQuery } from "./queryExecutor-
|
|
12
|
+
import { g as getDerivedKey, r as resolveRtsRequestTenantId, i as isRtsRequestAuthorized, b as buildRtsAbilityFromRequest, n as normalizeRtsQueryOptions, a as runRtsQuery } from "./queryExecutor-Dn62mIDL.js";
|
|
13
13
|
import httpProxy from "http-proxy-3";
|
|
14
14
|
import fsPromises from "node:fs/promises";
|
|
15
15
|
import inspector from "node:inspector";
|
|
@@ -21,7 +21,7 @@ import { StrictMode, createElement } from "react";
|
|
|
21
21
|
import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
|
|
22
22
|
import { jsx } from "react/jsx-runtime";
|
|
23
23
|
import { createPath, matchRoutes, parsePath, createStaticRouter, StaticRouterProvider } from "@rpcbase/router";
|
|
24
|
-
import { s } from "./email-
|
|
24
|
+
import { s } from "./email-DK8uUU4X.js";
|
|
25
25
|
function getDefaultExportFromCjs(x) {
|
|
26
26
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
27
27
|
}
|
|
@@ -3491,7 +3491,9 @@ const metricsIngestProxyMiddleware = (app) => {
|
|
|
3491
3491
|
if (!req.url) {
|
|
3492
3492
|
req.url = "/";
|
|
3493
3493
|
}
|
|
3494
|
-
proxy.web(req, res, {
|
|
3494
|
+
proxy.web(req, res, {
|
|
3495
|
+
target: POSTHOG_INGEST_TARGET
|
|
3496
|
+
});
|
|
3495
3497
|
});
|
|
3496
3498
|
};
|
|
3497
3499
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -3509,7 +3511,9 @@ const checkInitReplicaSet = async (serverEnv) => {
|
|
|
3509
3511
|
const maxWaitAttempts = 10;
|
|
3510
3512
|
for (let attempt = 1; attempt <= maxWaitAttempts; attempt++) {
|
|
3511
3513
|
try {
|
|
3512
|
-
const status = await admin.command({
|
|
3514
|
+
const status = await admin.command({
|
|
3515
|
+
replSetGetStatus: 1
|
|
3516
|
+
});
|
|
3513
3517
|
const state = Number(status?.myState ?? 0);
|
|
3514
3518
|
if (status?.ok && (state === 1 || state === 2)) return;
|
|
3515
3519
|
} catch {
|
|
@@ -3527,9 +3531,13 @@ const checkInitReplicaSet = async (serverEnv) => {
|
|
|
3527
3531
|
});
|
|
3528
3532
|
await client2.connect();
|
|
3529
3533
|
const admin = client2.db("admin").admin();
|
|
3530
|
-
await admin.command({
|
|
3534
|
+
await admin.command({
|
|
3535
|
+
ping: 1
|
|
3536
|
+
});
|
|
3531
3537
|
try {
|
|
3532
|
-
await admin.command({
|
|
3538
|
+
await admin.command({
|
|
3539
|
+
replSetGetStatus: 1
|
|
3540
|
+
});
|
|
3533
3541
|
return;
|
|
3534
3542
|
} catch (error) {
|
|
3535
3543
|
const codeName = error?.codeName;
|
|
@@ -3538,7 +3546,10 @@ const checkInitReplicaSet = async (serverEnv) => {
|
|
|
3538
3546
|
const res = await admin.command({
|
|
3539
3547
|
replSetInitiate: {
|
|
3540
3548
|
_id: replSetName,
|
|
3541
|
-
members: [{
|
|
3549
|
+
members: [{
|
|
3550
|
+
_id: 0,
|
|
3551
|
+
host: memberHost
|
|
3552
|
+
}]
|
|
3542
3553
|
}
|
|
3543
3554
|
});
|
|
3544
3555
|
if (res?.ok) {
|
|
@@ -3552,9 +3563,7 @@ const checkInitReplicaSet = async (serverEnv) => {
|
|
|
3552
3563
|
const message2 = initError instanceof Error ? initError.message : String(initError);
|
|
3553
3564
|
console.warn(`[rb/server] MongoDB replica set initiation failed: ${message2}`);
|
|
3554
3565
|
if (initCodeName === "InvalidReplicaSetConfig") {
|
|
3555
|
-
console.warn(
|
|
3556
|
-
`[rb/server] Hint: the replica set member host must match the mongod address/port. If MongoDB runs in Docker with port mapping, ensure the container listens on ${port} (e.g. mongod --port ${port}) instead of the default 27017.`
|
|
3557
|
-
);
|
|
3566
|
+
console.warn(`[rb/server] Hint: the replica set member host must match the mongod address/port. If MongoDB runs in Docker with port mapping, ensure the container listens on ${port} (e.g. mongod --port ${port}) instead of the default 27017.`);
|
|
3558
3567
|
}
|
|
3559
3568
|
}
|
|
3560
3569
|
}
|
|
@@ -3564,9 +3573,7 @@ const checkInitReplicaSet = async (serverEnv) => {
|
|
|
3564
3573
|
if (codeName === "NoReplicationEnabled") {
|
|
3565
3574
|
if (!hasWarnedNoReplicationEnabled) {
|
|
3566
3575
|
hasWarnedNoReplicationEnabled = true;
|
|
3567
|
-
console.warn(
|
|
3568
|
-
`[rb/server] MongoDB is not started with --replSet ${replSetName} (replication disabled). Change streams require a replica set; start mongod with --replSet.`
|
|
3569
|
-
);
|
|
3576
|
+
console.warn(`[rb/server] MongoDB is not started with --replSet ${replSetName} (replication disabled). Change streams require a replica set; start mongod with --replSet.`);
|
|
3570
3577
|
}
|
|
3571
3578
|
return;
|
|
3572
3579
|
}
|
|
@@ -3628,10 +3635,7 @@ const findWorkspaceRoot = (projectRoot) => {
|
|
|
3628
3635
|
const stripQuery = (url) => {
|
|
3629
3636
|
const queryIndex = url.indexOf("?");
|
|
3630
3637
|
const hashIndex = url.indexOf("#");
|
|
3631
|
-
const endIndex = Math.min(
|
|
3632
|
-
queryIndex === -1 ? Number.POSITIVE_INFINITY : queryIndex,
|
|
3633
|
-
hashIndex === -1 ? Number.POSITIVE_INFINITY : hashIndex
|
|
3634
|
-
);
|
|
3638
|
+
const endIndex = Math.min(queryIndex === -1 ? Number.POSITIVE_INFINITY : queryIndex, hashIndex === -1 ? Number.POSITIVE_INFINITY : hashIndex);
|
|
3635
3639
|
if (!Number.isFinite(endIndex)) {
|
|
3636
3640
|
return url;
|
|
3637
3641
|
}
|
|
@@ -3703,7 +3707,9 @@ const normalizeScriptUrl = async (rawUrl, roots) => {
|
|
|
3703
3707
|
};
|
|
3704
3708
|
const fetchScriptSource = async (session2, scriptId) => {
|
|
3705
3709
|
try {
|
|
3706
|
-
const response = await post(session2, "Debugger.getScriptSource", {
|
|
3710
|
+
const response = await post(session2, "Debugger.getScriptSource", {
|
|
3711
|
+
scriptId
|
|
3712
|
+
});
|
|
3707
3713
|
return typeof response?.scriptSource === "string" ? response.scriptSource : "";
|
|
3708
3714
|
} catch {
|
|
3709
3715
|
return "";
|
|
@@ -3719,11 +3725,7 @@ const resolveScriptSource = async (session2, cache, scriptId) => {
|
|
|
3719
3725
|
return await promise;
|
|
3720
3726
|
};
|
|
3721
3727
|
const shutdownSession = async (session2) => {
|
|
3722
|
-
await Promise.allSettled([
|
|
3723
|
-
post(session2, "Profiler.stopPreciseCoverage").catch(() => void 0),
|
|
3724
|
-
post(session2, "Profiler.disable").catch(() => void 0),
|
|
3725
|
-
post(session2, "Debugger.disable").catch(() => void 0)
|
|
3726
|
-
]);
|
|
3728
|
+
await Promise.allSettled([post(session2, "Profiler.stopPreciseCoverage").catch(() => void 0), post(session2, "Profiler.disable").catch(() => void 0), post(session2, "Debugger.disable").catch(() => void 0)]);
|
|
3727
3729
|
try {
|
|
3728
3730
|
session2.disconnect();
|
|
3729
3731
|
} catch {
|
|
@@ -3762,11 +3764,17 @@ const classifyServerTarget = (absolutePath, projectRoot) => {
|
|
|
3762
3764
|
function registerDevCoverageEndpoints(app) {
|
|
3763
3765
|
app.post("/api/dev/coverage/start", async (_req, res) => {
|
|
3764
3766
|
if (process.env.NODE_ENV === "production") {
|
|
3765
|
-
res.status(404).json({
|
|
3767
|
+
res.status(404).json({
|
|
3768
|
+
error: "Not Found"
|
|
3769
|
+
});
|
|
3766
3770
|
return;
|
|
3767
3771
|
}
|
|
3768
3772
|
if (activeRun) {
|
|
3769
|
-
res.json({
|
|
3773
|
+
res.json({
|
|
3774
|
+
ok: true,
|
|
3775
|
+
status: "already_started",
|
|
3776
|
+
startedAt: activeRun.startedAt
|
|
3777
|
+
});
|
|
3770
3778
|
return;
|
|
3771
3779
|
}
|
|
3772
3780
|
const roots = {
|
|
@@ -3778,28 +3786,43 @@ function registerDevCoverageEndpoints(app) {
|
|
|
3778
3786
|
try {
|
|
3779
3787
|
await post(session2, "Debugger.enable");
|
|
3780
3788
|
await post(session2, "Profiler.enable");
|
|
3781
|
-
await post(session2, "Profiler.startPreciseCoverage", {
|
|
3789
|
+
await post(session2, "Profiler.startPreciseCoverage", {
|
|
3790
|
+
callCount: false,
|
|
3791
|
+
detailed: true
|
|
3792
|
+
});
|
|
3782
3793
|
activeRun = {
|
|
3783
3794
|
roots,
|
|
3784
3795
|
session: session2,
|
|
3785
3796
|
sourceCache: /* @__PURE__ */ new Map(),
|
|
3786
3797
|
startedAt: Date.now()
|
|
3787
3798
|
};
|
|
3788
|
-
res.json({
|
|
3799
|
+
res.json({
|
|
3800
|
+
ok: true,
|
|
3801
|
+
status: "started",
|
|
3802
|
+
startedAt: activeRun.startedAt
|
|
3803
|
+
});
|
|
3789
3804
|
} catch (error) {
|
|
3790
3805
|
await shutdownSession(session2);
|
|
3791
3806
|
activeRun = null;
|
|
3792
|
-
res.status(500).json({
|
|
3807
|
+
res.status(500).json({
|
|
3808
|
+
ok: false,
|
|
3809
|
+
error: describeError(error)
|
|
3810
|
+
});
|
|
3793
3811
|
}
|
|
3794
3812
|
});
|
|
3795
3813
|
app.post("/api/dev/coverage/stop", async (req, res) => {
|
|
3796
3814
|
if (process.env.NODE_ENV === "production") {
|
|
3797
|
-
res.status(404).json({
|
|
3815
|
+
res.status(404).json({
|
|
3816
|
+
error: "Not Found"
|
|
3817
|
+
});
|
|
3798
3818
|
return;
|
|
3799
3819
|
}
|
|
3800
3820
|
const run = activeRun;
|
|
3801
3821
|
if (!run) {
|
|
3802
|
-
res.status(409).json({
|
|
3822
|
+
res.status(409).json({
|
|
3823
|
+
ok: false,
|
|
3824
|
+
error: "coverage_not_started"
|
|
3825
|
+
});
|
|
3803
3826
|
return;
|
|
3804
3827
|
}
|
|
3805
3828
|
activeRun = null;
|
|
@@ -3838,17 +3861,17 @@ function registerDevCoverageEndpoints(app) {
|
|
|
3838
3861
|
const target = classifyServerTarget(script.absolutePath, run.roots.projectRoot);
|
|
3839
3862
|
scriptsByTarget[target].push(script);
|
|
3840
3863
|
}
|
|
3841
|
-
await Promise.all(
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
);
|
|
3864
|
+
await Promise.all(Object.keys(outputFiles).map(async (target) => {
|
|
3865
|
+
const outputFile = outputFiles[target];
|
|
3866
|
+
const payload = {
|
|
3867
|
+
testId: `node-${target}`,
|
|
3868
|
+
scripts: scriptsByTarget[target]
|
|
3869
|
+
};
|
|
3870
|
+
await fsPromises.mkdir(path.dirname(outputFile), {
|
|
3871
|
+
recursive: true
|
|
3872
|
+
});
|
|
3873
|
+
await fsPromises.writeFile(outputFile, JSON.stringify(payload, null, 2), "utf8");
|
|
3874
|
+
}));
|
|
3852
3875
|
res.json({
|
|
3853
3876
|
ok: true,
|
|
3854
3877
|
status: "stopped",
|
|
@@ -3860,7 +3883,10 @@ function registerDevCoverageEndpoints(app) {
|
|
|
3860
3883
|
}
|
|
3861
3884
|
});
|
|
3862
3885
|
} catch (error) {
|
|
3863
|
-
res.status(500).json({
|
|
3886
|
+
res.status(500).json({
|
|
3887
|
+
ok: false,
|
|
3888
|
+
error: describeError(error)
|
|
3889
|
+
});
|
|
3864
3890
|
} finally {
|
|
3865
3891
|
await shutdownSession(run.session);
|
|
3866
3892
|
}
|
|
@@ -3939,7 +3965,9 @@ const createRedisSessionStore = async (redisUrl) => {
|
|
|
3939
3965
|
});
|
|
3940
3966
|
};
|
|
3941
3967
|
const initServer = async (app, serverEnv) => {
|
|
3942
|
-
await initApiClient({
|
|
3968
|
+
await initApiClient({
|
|
3969
|
+
app
|
|
3970
|
+
});
|
|
3943
3971
|
const replicaSetInitPromise = checkInitReplicaSet(serverEnv).catch((error) => {
|
|
3944
3972
|
const message = error instanceof Error ? error.message : String(error);
|
|
3945
3973
|
console.warn(`[rb/server] MongoDB replica set auto-init error: ${message}`);
|
|
@@ -4038,34 +4066,72 @@ const parseEnvInt = (value) => {
|
|
|
4038
4066
|
return parsed;
|
|
4039
4067
|
};
|
|
4040
4068
|
const isPowerOfTwo = (value) => (value & value - 1) === 0;
|
|
4041
|
-
const estimateScryptMemoryBytes = ({
|
|
4069
|
+
const estimateScryptMemoryBytes = ({
|
|
4070
|
+
N,
|
|
4071
|
+
r,
|
|
4072
|
+
p
|
|
4073
|
+
}) => {
|
|
4042
4074
|
return 128 * r * (N + p);
|
|
4043
4075
|
};
|
|
4044
4076
|
const validateScryptParams = (params) => {
|
|
4045
|
-
const {
|
|
4077
|
+
const {
|
|
4078
|
+
N,
|
|
4079
|
+
r,
|
|
4080
|
+
p,
|
|
4081
|
+
keylen,
|
|
4082
|
+
saltBytes,
|
|
4083
|
+
maxmemBytes
|
|
4084
|
+
} = params;
|
|
4046
4085
|
if (!Number.isSafeInteger(N) || N < 2 || N > MAX_SCRYPT_N || !isPowerOfTwo(N)) {
|
|
4047
|
-
return {
|
|
4086
|
+
return {
|
|
4087
|
+
ok: false,
|
|
4088
|
+
error: "invalid_scrypt_N"
|
|
4089
|
+
};
|
|
4048
4090
|
}
|
|
4049
4091
|
if (!Number.isSafeInteger(r) || r < 1 || r > MAX_SCRYPT_R) {
|
|
4050
|
-
return {
|
|
4092
|
+
return {
|
|
4093
|
+
ok: false,
|
|
4094
|
+
error: "invalid_scrypt_r"
|
|
4095
|
+
};
|
|
4051
4096
|
}
|
|
4052
4097
|
if (!Number.isSafeInteger(p) || p < 1 || p > MAX_SCRYPT_P) {
|
|
4053
|
-
return {
|
|
4098
|
+
return {
|
|
4099
|
+
ok: false,
|
|
4100
|
+
error: "invalid_scrypt_p"
|
|
4101
|
+
};
|
|
4054
4102
|
}
|
|
4055
4103
|
if (!Number.isSafeInteger(keylen) || keylen < 16 || keylen > MAX_SCRYPT_KEYLEN) {
|
|
4056
|
-
return {
|
|
4104
|
+
return {
|
|
4105
|
+
ok: false,
|
|
4106
|
+
error: "invalid_scrypt_keylen"
|
|
4107
|
+
};
|
|
4057
4108
|
}
|
|
4058
4109
|
if (!Number.isSafeInteger(saltBytes) || saltBytes < 8 || saltBytes > MAX_SCRYPT_SALT_BYTES) {
|
|
4059
|
-
return {
|
|
4110
|
+
return {
|
|
4111
|
+
ok: false,
|
|
4112
|
+
error: "invalid_scrypt_salt_bytes"
|
|
4113
|
+
};
|
|
4060
4114
|
}
|
|
4061
4115
|
if (!Number.isSafeInteger(maxmemBytes) || maxmemBytes < 16 * 1024 * 1024 || maxmemBytes > MAX_SCRYPT_MAXMEM_BYTES) {
|
|
4062
|
-
return {
|
|
4116
|
+
return {
|
|
4117
|
+
ok: false,
|
|
4118
|
+
error: "invalid_scrypt_maxmem"
|
|
4119
|
+
};
|
|
4063
4120
|
}
|
|
4064
|
-
const estimatedMem = estimateScryptMemoryBytes({
|
|
4121
|
+
const estimatedMem = estimateScryptMemoryBytes({
|
|
4122
|
+
N,
|
|
4123
|
+
r,
|
|
4124
|
+
p
|
|
4125
|
+
});
|
|
4065
4126
|
if (estimatedMem > maxmemBytes) {
|
|
4066
|
-
return {
|
|
4127
|
+
return {
|
|
4128
|
+
ok: false,
|
|
4129
|
+
error: "scrypt_params_exceed_maxmem"
|
|
4130
|
+
};
|
|
4067
4131
|
}
|
|
4068
|
-
return {
|
|
4132
|
+
return {
|
|
4133
|
+
ok: true
|
|
4134
|
+
};
|
|
4069
4135
|
};
|
|
4070
4136
|
const getCurrentMaxmemBytes = (opts) => {
|
|
4071
4137
|
const envMaxmemBytes = parseEnvInt(process.env.RB_PASSWORD_SCRYPT_MAXMEM_BYTES);
|
|
@@ -4096,9 +4162,20 @@ const getCurrentScryptParams = (opts) => {
|
|
|
4096
4162
|
return params;
|
|
4097
4163
|
};
|
|
4098
4164
|
const scryptAsync = async (password, salt, params) => {
|
|
4099
|
-
const {
|
|
4165
|
+
const {
|
|
4166
|
+
N,
|
|
4167
|
+
r,
|
|
4168
|
+
p,
|
|
4169
|
+
keylen,
|
|
4170
|
+
maxmemBytes
|
|
4171
|
+
} = params;
|
|
4100
4172
|
return await new Promise((resolve, reject) => {
|
|
4101
|
-
crypto.scrypt(password, salt, keylen, {
|
|
4173
|
+
crypto.scrypt(password, salt, keylen, {
|
|
4174
|
+
N,
|
|
4175
|
+
r,
|
|
4176
|
+
p,
|
|
4177
|
+
maxmem: maxmemBytes
|
|
4178
|
+
}, (err, derivedKey) => {
|
|
4102
4179
|
if (err) {
|
|
4103
4180
|
reject(err);
|
|
4104
4181
|
return;
|
|
@@ -4166,12 +4243,32 @@ const parseStoredScryptHash = (stored) => {
|
|
|
4166
4243
|
maxmemBytes: currentMaxmemBytes
|
|
4167
4244
|
});
|
|
4168
4245
|
if (!validated.ok) return null;
|
|
4169
|
-
return {
|
|
4246
|
+
return {
|
|
4247
|
+
N,
|
|
4248
|
+
r,
|
|
4249
|
+
p,
|
|
4250
|
+
keylen,
|
|
4251
|
+
salt,
|
|
4252
|
+
dk
|
|
4253
|
+
};
|
|
4170
4254
|
};
|
|
4171
4255
|
async function hashPasswordForStorage(password, opts) {
|
|
4172
|
-
const {
|
|
4256
|
+
const {
|
|
4257
|
+
N,
|
|
4258
|
+
r,
|
|
4259
|
+
p,
|
|
4260
|
+
keylen,
|
|
4261
|
+
saltBytes,
|
|
4262
|
+
maxmemBytes
|
|
4263
|
+
} = getCurrentScryptParams(opts);
|
|
4173
4264
|
const salt = crypto.randomBytes(saltBytes);
|
|
4174
|
-
const dk = await scryptAsync(password, salt, {
|
|
4265
|
+
const dk = await scryptAsync(password, salt, {
|
|
4266
|
+
N,
|
|
4267
|
+
r,
|
|
4268
|
+
p,
|
|
4269
|
+
keylen,
|
|
4270
|
+
maxmemBytes
|
|
4271
|
+
});
|
|
4175
4272
|
const saltB64 = salt.toString("base64");
|
|
4176
4273
|
const dkB64 = dk.toString("base64");
|
|
4177
4274
|
return `$scrypt$N=${N},r=${r},p=${p},keylen=${keylen}$${saltB64}$${dkB64}`;
|
|
@@ -4179,11 +4276,24 @@ async function hashPasswordForStorage(password, opts) {
|
|
|
4179
4276
|
async function verifyPasswordFromStorage(password, stored) {
|
|
4180
4277
|
const parsed = parseStoredScryptHash(stored);
|
|
4181
4278
|
if (!parsed) return false;
|
|
4182
|
-
const {
|
|
4279
|
+
const {
|
|
4280
|
+
N,
|
|
4281
|
+
r,
|
|
4282
|
+
p,
|
|
4283
|
+
keylen,
|
|
4284
|
+
salt,
|
|
4285
|
+
dk
|
|
4286
|
+
} = parsed;
|
|
4183
4287
|
const maxmemBytes = getCurrentMaxmemBytes();
|
|
4184
4288
|
let derivedKey;
|
|
4185
4289
|
try {
|
|
4186
|
-
derivedKey = await scryptAsync(password, salt, {
|
|
4290
|
+
derivedKey = await scryptAsync(password, salt, {
|
|
4291
|
+
N,
|
|
4292
|
+
r,
|
|
4293
|
+
p,
|
|
4294
|
+
keylen,
|
|
4295
|
+
maxmemBytes
|
|
4296
|
+
});
|
|
4187
4297
|
} catch {
|
|
4188
4298
|
return false;
|
|
4189
4299
|
}
|
|
@@ -4210,19 +4320,18 @@ function getShortCircuitMatches(routes) {
|
|
|
4210
4320
|
id: "__shim-error-route__"
|
|
4211
4321
|
};
|
|
4212
4322
|
return {
|
|
4213
|
-
matches: [
|
|
4214
|
-
{
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
}
|
|
4220
|
-
],
|
|
4323
|
+
matches: [{
|
|
4324
|
+
params: {},
|
|
4325
|
+
pathname: "",
|
|
4326
|
+
pathnameBase: "",
|
|
4327
|
+
route
|
|
4328
|
+
}],
|
|
4221
4329
|
route
|
|
4222
4330
|
};
|
|
4223
4331
|
}
|
|
4224
4332
|
const NOT_FOUND_STATUS = 404;
|
|
4225
4333
|
const LOADER_TIMEOUT_MS = 4e3;
|
|
4334
|
+
const IMMUTABLE_LAZY_ROUTE_KEYS = /* @__PURE__ */ new Set(["lazy", "caseSensitive", "path", "id", "index", "children"]);
|
|
4226
4335
|
const getErrorStatus = (error) => {
|
|
4227
4336
|
if (!error) return void 0;
|
|
4228
4337
|
const candidate = error?.reason ?? error;
|
|
@@ -4232,9 +4341,7 @@ const getErrorStatus = (error) => {
|
|
|
4232
4341
|
return void 0;
|
|
4233
4342
|
};
|
|
4234
4343
|
const isResponseLike = (value) => {
|
|
4235
|
-
return Boolean(
|
|
4236
|
-
value && typeof value === "object" && typeof value.status === "number" && value.headers && typeof value.headers.get === "function"
|
|
4237
|
-
);
|
|
4344
|
+
return Boolean(value && typeof value === "object" && typeof value.status === "number" && value.headers && typeof value.headers.get === "function");
|
|
4238
4345
|
};
|
|
4239
4346
|
const isRedirectResponse = (value) => {
|
|
4240
4347
|
if (!isResponseLike(value)) return false;
|
|
@@ -4267,19 +4374,40 @@ async function applyRouteLoaders(req, dataRoutes) {
|
|
|
4267
4374
|
loaderHeaders: {},
|
|
4268
4375
|
actionHeaders: {}
|
|
4269
4376
|
};
|
|
4377
|
+
const resolveLazyRoute = async (route) => {
|
|
4378
|
+
if (!route || typeof route !== "object") return;
|
|
4379
|
+
const lazy = route.lazy;
|
|
4380
|
+
if (typeof lazy !== "function") return;
|
|
4381
|
+
const lazyModule = await lazy();
|
|
4382
|
+
if (!lazyModule || typeof lazyModule !== "object") {
|
|
4383
|
+
route.lazy = void 0;
|
|
4384
|
+
return;
|
|
4385
|
+
}
|
|
4386
|
+
for (const [key, value] of Object.entries(lazyModule)) {
|
|
4387
|
+
if (IMMUTABLE_LAZY_ROUTE_KEYS.has(key)) continue;
|
|
4388
|
+
if (route[key] !== void 0) continue;
|
|
4389
|
+
route[key] = value;
|
|
4390
|
+
}
|
|
4391
|
+
route.lazy = void 0;
|
|
4392
|
+
};
|
|
4270
4393
|
const matches = matchRoutes(dataRoutes, location);
|
|
4271
4394
|
if (!matches || matches.length === 0) {
|
|
4272
4395
|
const error = {
|
|
4273
4396
|
status: 404,
|
|
4274
4397
|
message: `No route matches URL: ${req.originalUrl}`
|
|
4275
4398
|
};
|
|
4276
|
-
const {
|
|
4399
|
+
const {
|
|
4400
|
+
matches: notFoundMatches,
|
|
4401
|
+
route
|
|
4402
|
+
} = getShortCircuitMatches(dataRoutes);
|
|
4277
4403
|
return {
|
|
4278
4404
|
...baseContext,
|
|
4279
4405
|
matches: notFoundMatches,
|
|
4280
4406
|
loaderData: {},
|
|
4281
4407
|
actionData: null,
|
|
4282
|
-
errors: {
|
|
4408
|
+
errors: {
|
|
4409
|
+
[route.id]: error
|
|
4410
|
+
},
|
|
4283
4411
|
statusCode: 404
|
|
4284
4412
|
};
|
|
4285
4413
|
}
|
|
@@ -4294,6 +4422,7 @@ async function applyRouteLoaders(req, dataRoutes) {
|
|
|
4294
4422
|
};
|
|
4295
4423
|
}
|
|
4296
4424
|
const runLoaderWithTimeout = async (route, params) => {
|
|
4425
|
+
await resolveLazyRoute(route);
|
|
4297
4426
|
if (!route.loader) return null;
|
|
4298
4427
|
let timeoutId;
|
|
4299
4428
|
const timeoutPromise = new Promise((_, reject) => {
|
|
@@ -4305,18 +4434,32 @@ async function applyRouteLoaders(req, dataRoutes) {
|
|
|
4305
4434
|
ms: LOADER_TIMEOUT_MS,
|
|
4306
4435
|
url: req.originalUrl
|
|
4307
4436
|
});
|
|
4308
|
-
reject({
|
|
4437
|
+
reject({
|
|
4438
|
+
id: route.id,
|
|
4439
|
+
path: route.path,
|
|
4440
|
+
reason: err
|
|
4441
|
+
});
|
|
4309
4442
|
}, LOADER_TIMEOUT_MS);
|
|
4310
4443
|
});
|
|
4311
4444
|
const loaderPromise = (async () => {
|
|
4312
4445
|
try {
|
|
4313
4446
|
const data = await route.loader({
|
|
4314
4447
|
params,
|
|
4315
|
-
ctx: {
|
|
4448
|
+
ctx: {
|
|
4449
|
+
req
|
|
4450
|
+
}
|
|
4316
4451
|
});
|
|
4317
|
-
return {
|
|
4452
|
+
return {
|
|
4453
|
+
id: route.id,
|
|
4454
|
+
path: route.path,
|
|
4455
|
+
data
|
|
4456
|
+
};
|
|
4318
4457
|
} catch (error) {
|
|
4319
|
-
throw {
|
|
4458
|
+
throw {
|
|
4459
|
+
id: route.id,
|
|
4460
|
+
path: route.path,
|
|
4461
|
+
reason: error
|
|
4462
|
+
};
|
|
4320
4463
|
} finally {
|
|
4321
4464
|
if (timeoutId) {
|
|
4322
4465
|
clearTimeout(timeoutId);
|
|
@@ -4325,9 +4468,7 @@ async function applyRouteLoaders(req, dataRoutes) {
|
|
|
4325
4468
|
})();
|
|
4326
4469
|
return Promise.race([loaderPromise, timeoutPromise]);
|
|
4327
4470
|
};
|
|
4328
|
-
const loaderPromisesResults = await Promise.allSettled(
|
|
4329
|
-
matches.map((match) => runLoaderWithTimeout(match.route, match.params))
|
|
4330
|
-
);
|
|
4471
|
+
const loaderPromisesResults = await Promise.allSettled(matches.map((match) => runLoaderWithTimeout(match.route, match.params)));
|
|
4331
4472
|
const loaderData = {};
|
|
4332
4473
|
let errors = null;
|
|
4333
4474
|
let hasNotFoundError = false;
|
|
@@ -4349,9 +4490,7 @@ async function applyRouteLoaders(req, dataRoutes) {
|
|
|
4349
4490
|
} else if (result.status === "rejected") {
|
|
4350
4491
|
const id = result.reason?.id;
|
|
4351
4492
|
if (!id) {
|
|
4352
|
-
throw new Error(
|
|
4353
|
-
`missing route ID in error: ${result.reason}`
|
|
4354
|
-
);
|
|
4493
|
+
throw new Error(`missing route ID in error: ${result.reason}`);
|
|
4355
4494
|
}
|
|
4356
4495
|
const reasonCandidate = result.reason?.reason ?? result.reason;
|
|
4357
4496
|
if (isRedirectResponse(reasonCandidate)) {
|
|
@@ -4460,7 +4599,10 @@ const createRtsSsrCollector = (req, opts) => {
|
|
|
4460
4599
|
if (hasSessionUser(req) && !isRtsRequestAuthorized(req, tenantId)) {
|
|
4461
4600
|
return null;
|
|
4462
4601
|
}
|
|
4463
|
-
const {
|
|
4602
|
+
const {
|
|
4603
|
+
ability,
|
|
4604
|
+
userId
|
|
4605
|
+
} = await buildRtsAbilityFromRequest(req, tenantId);
|
|
4464
4606
|
const queryEntries = [];
|
|
4465
4607
|
for (const registration of registrations.values()) {
|
|
4466
4608
|
const options = normalizeRtsQueryOptions(registration.options);
|
|
@@ -4477,7 +4619,9 @@ const createRtsSsrCollector = (req, opts) => {
|
|
|
4477
4619
|
modelName: registration.modelName,
|
|
4478
4620
|
queryKey: registration.queryKey,
|
|
4479
4621
|
data: boundedData,
|
|
4480
|
-
...result.pageInfo ? {
|
|
4622
|
+
...result.pageInfo ? {
|
|
4623
|
+
pageInfo: result.pageInfo
|
|
4624
|
+
} : {}
|
|
4481
4625
|
});
|
|
4482
4626
|
} catch {
|
|
4483
4627
|
continue;
|
|
@@ -4507,7 +4651,11 @@ const createRtsSsrCollector = (req, opts) => {
|
|
|
4507
4651
|
return payload.queries.length ? payload : null;
|
|
4508
4652
|
};
|
|
4509
4653
|
const hasRegistrations = () => registrations.size > 0;
|
|
4510
|
-
return {
|
|
4654
|
+
return {
|
|
4655
|
+
runtime,
|
|
4656
|
+
hasRegistrations,
|
|
4657
|
+
resolve
|
|
4658
|
+
};
|
|
4511
4659
|
};
|
|
4512
4660
|
const renderRtsHydrationScript = (data) => {
|
|
4513
4661
|
if (!data) return "";
|
|
@@ -4515,6 +4663,7 @@ const renderRtsHydrationScript = (data) => {
|
|
|
4515
4663
|
return `<script>window.${STATIC_RPCBASE_RTS_HYDRATION_DATA_KEY}=${serialized};<\/script>`;
|
|
4516
4664
|
};
|
|
4517
4665
|
const RTS_SSR_PREPASS_TIMEOUT_MS = 4e3;
|
|
4666
|
+
const SSR_IDENTIFIER_PREFIX$1 = "rb-";
|
|
4518
4667
|
const runRtsPrepass = async (element) => {
|
|
4519
4668
|
return await new Promise((resolve) => {
|
|
4520
4669
|
let isDone = false;
|
|
@@ -4538,7 +4687,11 @@ const runRtsPrepass = async (element) => {
|
|
|
4538
4687
|
sink.on("error", () => {
|
|
4539
4688
|
finish(false);
|
|
4540
4689
|
});
|
|
4541
|
-
const {
|
|
4690
|
+
const {
|
|
4691
|
+
pipe,
|
|
4692
|
+
abort
|
|
4693
|
+
} = renderToPipeableStream(element, {
|
|
4694
|
+
identifierPrefix: SSR_IDENTIFIER_PREFIX$1,
|
|
4542
4695
|
onAllReady() {
|
|
4543
4696
|
if (isDone) return;
|
|
4544
4697
|
pipe(sink);
|
|
@@ -4582,13 +4735,10 @@ async function renderSSR(req, dataRoutes) {
|
|
|
4582
4735
|
pathname: m.pathname,
|
|
4583
4736
|
pathnameBase: m.pathnameBase
|
|
4584
4737
|
}));
|
|
4585
|
-
console.error(
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
matches: matchesSummary
|
|
4590
|
-
}
|
|
4591
|
-
);
|
|
4738
|
+
console.error(`SSR ${routerContext.statusCode || 500} ${req.method} ${req.originalUrl}`, {
|
|
4739
|
+
errors: routerContext.errors,
|
|
4740
|
+
matches: matchesSummary
|
|
4741
|
+
});
|
|
4592
4742
|
const errorEntries = Object.entries(routerContext.errors || {});
|
|
4593
4743
|
const firstErrorEntry = errorEntries[0]?.[1];
|
|
4594
4744
|
const firstReason = firstErrorEntry?.reason ?? firstErrorEntry;
|
|
@@ -4633,6 +4783,7 @@ async function renderSSR(req, dataRoutes) {
|
|
|
4633
4783
|
};
|
|
4634
4784
|
}
|
|
4635
4785
|
const ABORT_DELAY_MS = 1e4;
|
|
4786
|
+
const SSR_IDENTIFIER_PREFIX = "rb-";
|
|
4636
4787
|
const APP_HTML_PLACEHOLDER = "<!--app-html-->";
|
|
4637
4788
|
const DEFAULT_SERVER_ERROR_MESSAGE = "We couldn't render this page on the server. Please refresh and try again.";
|
|
4638
4789
|
const FALLBACK_ERROR_TEMPLATE_START = `<!doctype html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>Server error</title><style>body{margin:0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#0b1021;color:#eef1f7;display:flex;align-items:center;justify-content:center;min-height:100vh;}main{max-width:420px;padding:32px;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:14px;box-shadow:0 25px 50px rgba(0,0,0,0.35);}h1{font-size:24px;margin:0 0 8px;}p{margin:0 0 12px;line-height:1.5;}code{background:rgba(255,255,255,0.08);padding:2px 6px;border-radius:6px;font-size:12px;}</style></head><body><main>`;
|
|
@@ -4695,7 +4846,9 @@ const sendErrorResponse = ({
|
|
|
4695
4846
|
const start = htmlStart ?? FALLBACK_ERROR_TEMPLATE_START;
|
|
4696
4847
|
const end = htmlEnd ?? FALLBACK_ERROR_TEMPLATE_END;
|
|
4697
4848
|
res.status(status);
|
|
4698
|
-
res.set({
|
|
4849
|
+
res.set({
|
|
4850
|
+
"Content-Type": "text/html"
|
|
4851
|
+
});
|
|
4699
4852
|
const details = formatErrorDetails(error);
|
|
4700
4853
|
const state = {
|
|
4701
4854
|
statusCode: status,
|
|
@@ -4703,16 +4856,12 @@ const sendErrorResponse = ({
|
|
|
4703
4856
|
message,
|
|
4704
4857
|
details
|
|
4705
4858
|
};
|
|
4706
|
-
const markup = renderToStaticMarkup(
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
renderErrorExtra: errorExtraComponent ? (payload) => createElement(errorExtraComponent, { state: payload }) : void 0
|
|
4713
|
-
})
|
|
4714
|
-
)
|
|
4715
|
-
);
|
|
4859
|
+
const markup = renderToStaticMarkup(createElement(StrictMode, null, createElement(SsrErrorFallback, {
|
|
4860
|
+
state,
|
|
4861
|
+
renderErrorExtra: errorExtraComponent ? (payload) => createElement(errorExtraComponent, {
|
|
4862
|
+
state: payload
|
|
4863
|
+
}) : void 0
|
|
4864
|
+
})));
|
|
4716
4865
|
const serializedState = `<script>window.${SSR_ERROR_STATE_GLOBAL_KEY}=${serializeSsrErrorState({
|
|
4717
4866
|
...state,
|
|
4718
4867
|
details: isProduction ? void 0 : details
|
|
@@ -4753,7 +4902,9 @@ const ssrMiddleware = ({
|
|
|
4753
4902
|
});
|
|
4754
4903
|
responseCommitted = true;
|
|
4755
4904
|
if (error) {
|
|
4756
|
-
captureException(error, {
|
|
4905
|
+
captureException(error, {
|
|
4906
|
+
phase: "finalizeWithErrorPage"
|
|
4907
|
+
});
|
|
4757
4908
|
}
|
|
4758
4909
|
};
|
|
4759
4910
|
try {
|
|
@@ -4808,55 +4959,62 @@ const ssrMiddleware = ({
|
|
|
4808
4959
|
return;
|
|
4809
4960
|
}
|
|
4810
4961
|
let didError = false;
|
|
4811
|
-
const {
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
captureException(error, { phase: "shell" });
|
|
4820
|
-
finalizeWithErrorPage(error);
|
|
4821
|
-
abort();
|
|
4822
|
-
},
|
|
4823
|
-
onError(error) {
|
|
4824
|
-
didError = true;
|
|
4825
|
-
if (error instanceof Error) {
|
|
4826
|
-
viteInstance?.ssrFixStacktrace(error);
|
|
4827
|
-
}
|
|
4828
|
-
console.error("SSR rendering error", error);
|
|
4829
|
-
captureException(error, { phase: "render" });
|
|
4830
|
-
},
|
|
4831
|
-
onShellReady() {
|
|
4832
|
-
if (responseCommitted) {
|
|
4833
|
-
return;
|
|
4834
|
-
}
|
|
4835
|
-
if (!htmlStart || !htmlEnd) {
|
|
4836
|
-
finalizeWithErrorPage();
|
|
4837
|
-
return;
|
|
4838
|
-
}
|
|
4839
|
-
responseCommitted = true;
|
|
4840
|
-
const responseStatus = didError ? 500 : statusCode || 200;
|
|
4841
|
-
res.status(responseStatus);
|
|
4842
|
-
res.set({ "Content-Type": "text/html" });
|
|
4843
|
-
const transformStream = new Transform({
|
|
4844
|
-
transform(chunk, encoding, callback) {
|
|
4845
|
-
res.write(chunk, encoding);
|
|
4846
|
-
callback();
|
|
4847
|
-
}
|
|
4848
|
-
});
|
|
4849
|
-
const start = htmlStart;
|
|
4850
|
-
const end = htmlEnd;
|
|
4851
|
-
const rtsHydrationScript = renderRtsHydrationScript(rtsHydrationData);
|
|
4852
|
-
res.write(start);
|
|
4853
|
-
transformStream.on("finish", () => {
|
|
4854
|
-
res.end(`${rtsHydrationScript}${end}`);
|
|
4855
|
-
});
|
|
4856
|
-
pipe(transformStream);
|
|
4962
|
+
const {
|
|
4963
|
+
pipe,
|
|
4964
|
+
abort
|
|
4965
|
+
} = renderToPipeableStream(element, {
|
|
4966
|
+
identifierPrefix: SSR_IDENTIFIER_PREFIX,
|
|
4967
|
+
onShellError(error) {
|
|
4968
|
+
if (error instanceof Error) {
|
|
4969
|
+
viteInstance?.ssrFixStacktrace(error);
|
|
4857
4970
|
}
|
|
4971
|
+
console.error("SSR shell error", error);
|
|
4972
|
+
captureException(error, {
|
|
4973
|
+
phase: "shell"
|
|
4974
|
+
});
|
|
4975
|
+
finalizeWithErrorPage(error);
|
|
4976
|
+
abort();
|
|
4977
|
+
},
|
|
4978
|
+
onError(error) {
|
|
4979
|
+
didError = true;
|
|
4980
|
+
if (error instanceof Error) {
|
|
4981
|
+
viteInstance?.ssrFixStacktrace(error);
|
|
4982
|
+
}
|
|
4983
|
+
console.error("SSR rendering error", error);
|
|
4984
|
+
captureException(error, {
|
|
4985
|
+
phase: "render"
|
|
4986
|
+
});
|
|
4987
|
+
},
|
|
4988
|
+
onShellReady() {
|
|
4989
|
+
if (responseCommitted) {
|
|
4990
|
+
return;
|
|
4991
|
+
}
|
|
4992
|
+
if (!htmlStart || !htmlEnd) {
|
|
4993
|
+
finalizeWithErrorPage();
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4996
|
+
responseCommitted = true;
|
|
4997
|
+
const responseStatus = didError ? 500 : statusCode || 200;
|
|
4998
|
+
res.status(responseStatus);
|
|
4999
|
+
res.set({
|
|
5000
|
+
"Content-Type": "text/html"
|
|
5001
|
+
});
|
|
5002
|
+
const transformStream = new Transform({
|
|
5003
|
+
transform(chunk, encoding, callback) {
|
|
5004
|
+
res.write(chunk, encoding);
|
|
5005
|
+
callback();
|
|
5006
|
+
}
|
|
5007
|
+
});
|
|
5008
|
+
const start = htmlStart;
|
|
5009
|
+
const end = htmlEnd;
|
|
5010
|
+
const rtsHydrationScript = renderRtsHydrationScript(rtsHydrationData);
|
|
5011
|
+
res.write(start);
|
|
5012
|
+
transformStream.on("finish", () => {
|
|
5013
|
+
res.end(`${rtsHydrationScript}${end}`);
|
|
5014
|
+
});
|
|
5015
|
+
pipe(transformStream);
|
|
4858
5016
|
}
|
|
4859
|
-
);
|
|
5017
|
+
});
|
|
4860
5018
|
setTimeout(() => {
|
|
4861
5019
|
abort();
|
|
4862
5020
|
}, ABORT_DELAY_MS);
|
|
@@ -4868,7 +5026,9 @@ const ssrMiddleware = ({
|
|
|
4868
5026
|
} else {
|
|
4869
5027
|
console.error("Unknown SSR middleware error", err);
|
|
4870
5028
|
}
|
|
4871
|
-
captureException(err, {
|
|
5029
|
+
captureException(err, {
|
|
5030
|
+
phase: "catch"
|
|
5031
|
+
});
|
|
4872
5032
|
finalizeWithErrorPage(err);
|
|
4873
5033
|
}
|
|
4874
5034
|
};
|