prostgles-server 4.2.643 → 4.2.645
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/debug/fixes-review-build.log +4 -0
- package/debug/fixes-review-client-schema.backup +745 -0
- package/debug/fixes-review-generated-schema.backup +489 -0
- package/debug/fixes-review-probes-build.log +0 -0
- package/debug/fixes-review-probes.patch +43 -0
- package/debug/fixes-review-restore-build.log +0 -0
- package/debug/fixes-review-tests-build.log +0 -0
- package/debug/fixes-review-typecheck.log +8 -0
- package/debug/review-current-fixes-build.log +4 -0
- package/debug/review-current-fixes-client.backup +745 -0
- package/debug/review-current-fixes-probes-build.log +0 -0
- package/debug/review-current-fixes-probes.patch +55 -0
- package/debug/review-current-fixes-restore-build.log +0 -0
- package/debug/review-current-fixes-rls.backup +478 -0
- package/debug/review-current-fixes-schema.backup +489 -0
- package/debug/review-current-fixes-test-build.log +0 -0
- package/debug/review-current-fixes-typecheck.log +8 -0
- package/debug/review-user-identity-build.log +4 -0
- package/debug/review-user-identity-probes-build.log +0 -0
- package/debug/review-user-identity-probes.log +558 -0
- package/debug/review-user-identity-probes.patch +45 -0
- package/debug/review-user-identity-restore-build.log +0 -0
- package/debug/review-user-identity-rls.backup +463 -0
- package/debug/review-user-identity-schema.backup +720 -0
- package/debug/review-user-identity-server.log +3248 -0
- package/debug/review-user-identity-test-build.log +0 -0
- package/debug/review-user-identity-typecheck.log +8 -0
- package/debug/server-user-lint.log +4 -0
- package/debug/server-user-test-server.log +538 -0
- package/debug/server-user-typecheck.log +8 -0
- package/debug/user-identity-direct-call-build.log +0 -0
- package/debug/user-identity-direct-call-schema.backup +489 -0
- package/debug/user-identity-regressions-build.log +4 -0
- package/debug/user-identity-regressions-generated-schema.backup +489 -0
- package/debug/user-identity-regressions-test-build.log +0 -0
- package/dist/Auth/AuthHandler.js +1 -1
- package/dist/Auth/AuthHandler.js.map +1 -1
- package/dist/Auth/AuthTypes.d.ts +8 -6
- package/dist/Auth/AuthTypes.d.ts.map +1 -1
- package/dist/Auth/AuthTypes.js.map +1 -1
- package/dist/Auth/utils/getClientRequestIPsInfo.d.ts +2 -1
- package/dist/Auth/utils/getClientRequestIPsInfo.d.ts.map +1 -1
- package/dist/Auth/utils/getClientRequestIPsInfo.js +8 -1
- package/dist/Auth/utils/getClientRequestIPsInfo.js.map +1 -1
- package/dist/Auth/utils/getSessionUser.d.ts +4 -3
- package/dist/Auth/utils/getSessionUser.d.ts.map +1 -1
- package/dist/Auth/utils/getSessionUser.js +4 -2
- package/dist/Auth/utils/getSessionUser.js.map +1 -1
- package/dist/Auth/utils/getSessionUser.spec.js +2 -4
- package/dist/Auth/utils/getSessionUser.spec.js.map +1 -1
- package/dist/Auth/utils/handleGetUser.d.ts.map +1 -1
- package/dist/Auth/utils/handleGetUser.js +16 -0
- package/dist/Auth/utils/handleGetUser.js.map +1 -1
- package/dist/Auth/utils/serverSideRequest.d.ts +17 -0
- package/dist/Auth/utils/serverSideRequest.d.ts.map +1 -0
- package/dist/Auth/utils/serverSideRequest.js +20 -0
- package/dist/Auth/utils/serverSideRequest.js.map +1 -0
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +0 -4
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.js +5 -8
- package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/count.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/count.js +2 -1
- package/dist/DboBuilder/ViewHandler/count.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.js +2 -1
- package/dist/DboBuilder/ViewHandler/find.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.d.ts +9 -2
- package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.js +57 -23
- package/dist/DboBuilder/ViewHandler/getDbHandlerWithAbort.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/size.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/size.js +2 -1
- package/dist/DboBuilder/ViewHandler/size.js.map +1 -1
- package/dist/StorageClient/getLocalStorageClient.d.ts +9 -2
- package/dist/StorageClient/getLocalStorageClient.d.ts.map +1 -1
- package/dist/StorageClient/getLocalStorageClient.js.map +1 -1
- package/dist/initProstgles.d.ts +12 -2
- package/dist/initProstgles.d.ts.map +1 -1
- package/dist/initProstgles.js +10 -1
- package/dist/initProstgles.js.map +1 -1
- package/dist/runClientRequest.d.ts.map +1 -1
- package/dist/runClientRequest.js +4 -3
- package/dist/runClientRequest.js.map +1 -1
- package/lib/Auth/AuthHandler.ts +1 -1
- package/lib/Auth/AuthTypes.ts +9 -6
- package/lib/Auth/utils/getClientRequestIPsInfo.ts +11 -2
- package/lib/Auth/utils/getSessionUser.spec.ts +4 -6
- package/lib/Auth/utils/getSessionUser.ts +8 -5
- package/lib/Auth/utils/handleGetUser.ts +13 -0
- package/lib/Auth/utils/serverSideRequest.ts +27 -0
- package/lib/DboBuilder/ViewHandler/ViewHandler.ts +11 -11
- package/lib/DboBuilder/ViewHandler/count.ts +2 -1
- package/lib/DboBuilder/ViewHandler/find.ts +2 -1
- package/lib/DboBuilder/ViewHandler/getDbHandlerWithAbort.ts +72 -29
- package/lib/DboBuilder/ViewHandler/size.ts +2 -1
- package/lib/StorageClient/getLocalStorageClient.ts +2 -2
- package/lib/initProstgles.ts +31 -5
- package/lib/runClientRequest.ts +8 -5
- package/package.json +1 -1
|
@@ -2,12 +2,16 @@ import type { DB } from "../../initProstgles";
|
|
|
2
2
|
import { QUERY_ID_PREFIX, type LocalParams } from "../DboBuilder";
|
|
3
3
|
import type { ViewHandler } from "./ViewHandler";
|
|
4
4
|
import type pgPromise from "pg-promise";
|
|
5
|
+
import { getServerSideUserId } from "../../Auth/utils/serverSideRequest";
|
|
6
|
+
import type { Prostgles } from "../../Prostgles";
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
type Params = { abortSignal: AbortSignal | undefined; abortSignalId: string | undefined };
|
|
9
|
+
|
|
10
|
+
export const getDbHandlerWithAbort = (
|
|
11
|
+
viewHandler: ViewHandler,
|
|
8
12
|
localParams: LocalParams | undefined,
|
|
9
|
-
params:
|
|
10
|
-
): Pick<DB | pgPromise.ITask<{}>, "any" | "one" | "many" | "manyOrNone" | "none" | "oneOrNone"> {
|
|
13
|
+
params: Params,
|
|
14
|
+
): Pick<DB | pgPromise.ITask<{}>, "any" | "one" | "many" | "manyOrNone" | "none" | "oneOrNone"> => {
|
|
11
15
|
if (params.abortSignal && params.abortSignalId) {
|
|
12
16
|
throw new Error("Cannot provide both abortSignal and abortSignalId");
|
|
13
17
|
}
|
|
@@ -16,28 +20,29 @@ export function getDbHandlerWithAbort(
|
|
|
16
20
|
throw new Error("Query aborted before execution");
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const abortSignalId = params.abortSignalId ?? crypto.randomUUID();
|
|
22
|
-
|
|
23
|
-
if (this.activeQueries.has(abortSignalId)) {
|
|
24
|
-
throw new Error(
|
|
25
|
-
`A query with abortSignalId ${params.abortSignalId} is already active. Ensure that each query has a unique abortSignalId.`,
|
|
26
|
-
);
|
|
23
|
+
if (params.abortSignal !== undefined && !(params.abortSignal instanceof AbortSignal)) {
|
|
24
|
+
throw new Error("abortSignal must be an instance of AbortSignal");
|
|
27
25
|
}
|
|
28
|
-
|
|
29
|
-
const {
|
|
26
|
+
|
|
27
|
+
const { clientReq } = localParams ?? {};
|
|
28
|
+
const abortSignal = params.abortSignal ?? AbortSignal.timeout(clientReq ? 7_000 : 120_000);
|
|
29
|
+
const { prostgles } = viewHandler.dboBuilder;
|
|
30
|
+
const handler = viewHandler.getTransaction(localParams)?.t ?? viewHandler.db;
|
|
31
|
+
const { adminClient } = prostgles;
|
|
30
32
|
if (!adminClient) {
|
|
31
33
|
throw new Error(
|
|
32
34
|
"adminClient not available. Ensure prostgles.adminClient is initialized before using abortable queries.",
|
|
33
35
|
);
|
|
34
36
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
|
|
38
|
+
const signalKeys = getAbortSignalKeys(prostgles, params, localParams);
|
|
39
|
+
const { abortSignalKey } = signalKeys;
|
|
40
|
+
if (viewHandler.activeQueries.has(abortSignalKey)) {
|
|
37
41
|
throw new Error(
|
|
38
|
-
|
|
42
|
+
`A query with abortSignalId ${params.abortSignalId} is already active. Ensure that each query has a unique abortSignalId.`,
|
|
39
43
|
);
|
|
40
44
|
}
|
|
45
|
+
|
|
41
46
|
const withAbortQuery = <Args extends unknown[], R extends Promise<any>>(
|
|
42
47
|
func: (query: string, ...args: Args) => R,
|
|
43
48
|
) => {
|
|
@@ -52,16 +57,17 @@ export function getDbHandlerWithAbort(
|
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
const abort = () => {
|
|
55
|
-
void
|
|
56
|
-
data: { query, abortSignalId },
|
|
60
|
+
void viewHandler._log({
|
|
61
|
+
data: { query, abortSignalId: signalKeys.abortSignalId },
|
|
57
62
|
command: "abort",
|
|
58
63
|
localParams,
|
|
59
|
-
duration:
|
|
64
|
+
duration:
|
|
65
|
+
Date.now() - (viewHandler.activeQueries.get(abortSignalKey)?.start ?? Date.now()),
|
|
60
66
|
error: new Error("Query aborted"),
|
|
61
67
|
});
|
|
62
68
|
/** Only terminate if there is exactly one matching query with a query id prefix */
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
viewHandler.abortRequests.delete(abortSignalKey);
|
|
65
71
|
void adminClient
|
|
66
72
|
.query(
|
|
67
73
|
`
|
|
@@ -71,17 +77,18 @@ export function getDbHandlerWithAbort(
|
|
|
71
77
|
`,
|
|
72
78
|
[`${queryIdPrefix}%`],
|
|
73
79
|
)
|
|
74
|
-
.catch((
|
|
80
|
+
.catch((_err) => {
|
|
75
81
|
// ignore error
|
|
76
82
|
});
|
|
77
83
|
};
|
|
78
84
|
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
throw new Error(
|
|
85
|
+
if (viewHandler.abortRequests.has(abortSignalKey)) {
|
|
86
|
+
viewHandler.abortRequests.delete(abortSignalKey);
|
|
87
|
+
throw new Error("Abort already requested");
|
|
82
88
|
}
|
|
83
89
|
|
|
84
|
-
|
|
90
|
+
const sid = prostgles.authHandler.getSIDNoError(clientReq);
|
|
91
|
+
viewHandler.activeQueries.set(abortSignalKey, {
|
|
85
92
|
query,
|
|
86
93
|
start: Date.now(),
|
|
87
94
|
sid,
|
|
@@ -91,8 +98,8 @@ export function getDbHandlerWithAbort(
|
|
|
91
98
|
abortSignal.addEventListener("abort", abort);
|
|
92
99
|
return func(query, ...args).finally(() => {
|
|
93
100
|
abortSignal.removeEventListener("abort", abort);
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
viewHandler.activeQueries.delete(abortSignalKey);
|
|
102
|
+
viewHandler.abortRequests.delete(abortSignalKey);
|
|
96
103
|
});
|
|
97
104
|
};
|
|
98
105
|
};
|
|
@@ -105,4 +112,40 @@ export function getDbHandlerWithAbort(
|
|
|
105
112
|
none: withAbortQuery(handler.none.bind(handler)),
|
|
106
113
|
many: withAbortQuery(handler.many.bind(handler)),
|
|
107
114
|
};
|
|
108
|
-
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const getAbortSignalKeys = (
|
|
118
|
+
prostgles: Prostgles,
|
|
119
|
+
params: Pick<Params, "abortSignalId">,
|
|
120
|
+
localParams: LocalParams | undefined,
|
|
121
|
+
) => {
|
|
122
|
+
const clientIdentifier = (() => {
|
|
123
|
+
const { clientReq } = localParams ?? {};
|
|
124
|
+
if (!clientReq) {
|
|
125
|
+
if (params.abortSignalId !== undefined) {
|
|
126
|
+
throw new Error(
|
|
127
|
+
"abortSignalId must not be provided for local requests. Use abortSignal instead.",
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return ["<local-request>", "local"];
|
|
131
|
+
}
|
|
132
|
+
const sid = prostgles.authHandler.getSIDNoError(clientReq);
|
|
133
|
+
if (sid) return [sid, "sid"];
|
|
134
|
+
const userId = getServerSideUserId(prostgles, clientReq);
|
|
135
|
+
if (userId) return [userId, "userId"];
|
|
136
|
+
throw new Error(
|
|
137
|
+
"Cannot get SID or userId from client request. Ensure that the client is authenticated before using abortable queries.",
|
|
138
|
+
);
|
|
139
|
+
})();
|
|
140
|
+
const abortSignalId = params.abortSignalId ?? crypto.randomUUID();
|
|
141
|
+
|
|
142
|
+
const MAX_LENGTH = 36;
|
|
143
|
+
if (abortSignalId.length > MAX_LENGTH) {
|
|
144
|
+
throw new Error(`abortSignalId length must not exceed ${MAX_LENGTH} characters`);
|
|
145
|
+
}
|
|
146
|
+
const abortSignalKey = JSON.stringify([...clientIdentifier, abortSignalId]);
|
|
147
|
+
return {
|
|
148
|
+
abortSignalId,
|
|
149
|
+
abortSignalKey,
|
|
150
|
+
};
|
|
151
|
+
};
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import type { ViewHandler } from "./ViewHandler";
|
|
10
10
|
import { getReturnTypeQuery } from "./getReturnTypeQuery";
|
|
11
11
|
import type { Param3 } from "./find";
|
|
12
|
+
import { getDbHandlerWithAbort } from "./getDbHandlerWithAbort";
|
|
12
13
|
export async function size(
|
|
13
14
|
this: ViewHandler,
|
|
14
15
|
_filter?: Filter,
|
|
@@ -62,7 +63,7 @@ export async function size(
|
|
|
62
63
|
return queryToReturn as unknown[];
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
const handler =
|
|
66
|
+
const handler = getDbHandlerWithAbort(this, localParams, {
|
|
66
67
|
abortSignal: selectParams?.abortSignal,
|
|
67
68
|
abortSignalId: param3?.abortSignalId,
|
|
68
69
|
});
|
|
@@ -23,7 +23,7 @@ export type LocalConfig = {
|
|
|
23
23
|
minFreeBytes?: number;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
export const getLocalStorageClient = (localConfig: LocalConfig)
|
|
26
|
+
export const getLocalStorageClient = (localConfig: LocalConfig) => {
|
|
27
27
|
const { localFolderPath, minFreeBytes = 100 * 1024 * 1024 } = localConfig; // Default 100MB
|
|
28
28
|
|
|
29
29
|
// Helper to ensure we have enough free disk space (Requires Node >= 18.17.0)
|
|
@@ -103,5 +103,5 @@ export const getLocalStorageClient = (localConfig: LocalConfig): LocalStorageCli
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
},
|
|
106
|
-
};
|
|
106
|
+
} satisfies LocalStorageClient;
|
|
107
107
|
};
|
package/lib/initProstgles.ts
CHANGED
|
@@ -19,6 +19,17 @@ import { updateConfiguration, type clientOnlyUpdateKeys } from "./updateConfigur
|
|
|
19
19
|
import { sleep } from "./utils/utils";
|
|
20
20
|
import { getClientHandlers } from "./WebsocketAPI/getClientHandlers";
|
|
21
21
|
import { getAdminClient } from "./DboBuilder/runSql/getAdminClient";
|
|
22
|
+
import { createServerSideRequest } from "./Auth/utils/serverSideRequest";
|
|
23
|
+
|
|
24
|
+
type ClientDBHandlerRequest =
|
|
25
|
+
| AuthClientRequest
|
|
26
|
+
| {
|
|
27
|
+
/** Trusted server-only identity, resolved through auth.findUser on every operation. */
|
|
28
|
+
userId: string;
|
|
29
|
+
socket?: never;
|
|
30
|
+
httpReq?: never;
|
|
31
|
+
res?: never;
|
|
32
|
+
};
|
|
22
33
|
|
|
23
34
|
/**
|
|
24
35
|
* Database connection details
|
|
@@ -125,9 +136,12 @@ export type InitResult<
|
|
|
125
136
|
update: (newOpts: UpdatableOptions<S, SUser, Context>, force?: true) => Promise<void>;
|
|
126
137
|
restart: () => Promise<InitResult<S, SUser, Context, ClientSchema>>;
|
|
127
138
|
options: ProstglesInitOptions<S, SUser, Context>;
|
|
128
|
-
/**
|
|
139
|
+
/**
|
|
140
|
+
* Uses the configured client schema by default and accepts a publish-profile schema override.
|
|
141
|
+
* Only pass userId from trusted server code; never forward client-supplied input here.
|
|
142
|
+
*/
|
|
129
143
|
getClientDBHandlers: <NarrowedClientSchema = ClientSchema>(
|
|
130
|
-
clientReq:
|
|
144
|
+
clientReq: ClientDBHandlerRequest,
|
|
131
145
|
scope: PermissionScope | undefined,
|
|
132
146
|
) => ReturnType<typeof getClientHandlers<NarrowedClientSchema>>;
|
|
133
147
|
|
|
@@ -333,10 +347,22 @@ export const initProstgles = async function (
|
|
|
333
347
|
await sleep(1000);
|
|
334
348
|
return true;
|
|
335
349
|
},
|
|
336
|
-
getClientDBHandlers: <ClientSchema = void>(
|
|
337
|
-
clientReq:
|
|
350
|
+
getClientDBHandlers: async <ClientSchema = void>(
|
|
351
|
+
clientReq: ClientDBHandlerRequest,
|
|
338
352
|
scope: PermissionScope | undefined,
|
|
339
|
-
) =>
|
|
353
|
+
) => {
|
|
354
|
+
if ("userId" in clientReq) {
|
|
355
|
+
if ("socket" in clientReq || "httpReq" in clientReq || "res" in clientReq) {
|
|
356
|
+
throw new Error("userId cannot be combined with a client request");
|
|
357
|
+
}
|
|
358
|
+
return getClientHandlers<ClientSchema>(
|
|
359
|
+
this,
|
|
360
|
+
createServerSideRequest(this, clientReq.userId),
|
|
361
|
+
scope,
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
return getClientHandlers<ClientSchema>(this, clientReq, scope);
|
|
365
|
+
},
|
|
340
366
|
};
|
|
341
367
|
|
|
342
368
|
return initResult;
|
package/lib/runClientRequest.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { canRunSQL } from "./DboBuilder/runSql/runSQL";
|
|
|
15
15
|
import type { Prostgles } from "./Prostgles";
|
|
16
16
|
import type { ParsedTableRule } from "./PublishParser/publishTypesAndUtils";
|
|
17
17
|
import { type PermissionScope } from "./PublishParser/publishTypesAndUtils";
|
|
18
|
+
import { getAbortSignalKeys } from "./DboBuilder/ViewHandler/getDbHandlerWithAbort";
|
|
18
19
|
|
|
19
20
|
const TABLE_METHODS = {
|
|
20
21
|
find: 1,
|
|
@@ -104,9 +105,12 @@ export const runClientRequest = async function (
|
|
|
104
105
|
);
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
const tableHandler =
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
const tableHandler =
|
|
109
|
+
transactionHandlers ?
|
|
110
|
+
Object.hasOwn(transactionHandlers, tableName) ?
|
|
111
|
+
transactionHandlers[tableName]
|
|
112
|
+
: undefined
|
|
113
|
+
: this.dboBuilder.dboMap.get(tableName);
|
|
110
114
|
if (!tableHandler) {
|
|
111
115
|
throw `tableName ${tableName} is invalid or not allowed`;
|
|
112
116
|
}
|
|
@@ -123,7 +127,7 @@ export const runClientRequest = async function (
|
|
|
123
127
|
scope,
|
|
124
128
|
});
|
|
125
129
|
|
|
126
|
-
const sessionUser = getSessionUser(clientInfo);
|
|
130
|
+
const sessionUser = getSessionUser(clientInfo, this.opts.auth?.sessionFields);
|
|
127
131
|
const localParams: LocalParams = {
|
|
128
132
|
clientReq,
|
|
129
133
|
isRemoteRequest: { user: sessionUser, clientInfo },
|
|
@@ -155,7 +159,6 @@ export const runClientRequest = async function (
|
|
|
155
159
|
scope,
|
|
156
160
|
);
|
|
157
161
|
|
|
158
|
-
tableHandler.abortRequests.add(validation.data.param1.abortSignalId);
|
|
159
162
|
return tableHandler.abortRemoteQuery(validation.data.param1.abortSignalId, localParams);
|
|
160
163
|
} else {
|
|
161
164
|
this.publishParser.validateRequestRule(
|