prostgles-server 4.2.40 → 4.2.41
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/package.json +1 -1
- package/tests/client/hooks.spec.ts +1 -42
- package/tests/client/package-lock.json +4 -4
- package/tests/client/package.json +1 -1
- package/tests/client/renderReactHook.ts +68 -6
- package/tests/client/useProstgles.spec.ts +71 -6
- package/tests/server/DBoGenerated.d.ts +2 -0
- package/tests/server/package-lock.json +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { strict as assert } from "assert";
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
3
|
import type { DBHandlerClient } from "./index";
|
|
4
|
-
import { renderReactHook } from "./renderReactHook";
|
|
4
|
+
import { renderReactHook, renderReactHookManual } from "./renderReactHook";
|
|
5
5
|
import { AnyObject, pickKeys } from "prostgles-types";
|
|
6
6
|
import { useProstglesClient } from "prostgles-client/dist/prostgles";
|
|
7
7
|
|
|
@@ -9,47 +9,6 @@ export const clientHooks = async (db: DBHandlerClient, getSocketOptions: (watchS
|
|
|
9
9
|
|
|
10
10
|
const resultLoading = { data: undefined, isLoading: true, error: undefined };
|
|
11
11
|
await describe("React hooks", async (t) => {
|
|
12
|
-
const socketOptions = getSocketOptions();
|
|
13
|
-
await test("useProstglesClient", async (t) => {
|
|
14
|
-
const { results: [res1, res2] } = await renderReactHook({
|
|
15
|
-
hook: useProstglesClient,
|
|
16
|
-
props: [{ socketOptions }],
|
|
17
|
-
expectedRerenders: 2
|
|
18
|
-
});
|
|
19
|
-
assert.deepStrictEqual(
|
|
20
|
-
res1,
|
|
21
|
-
{ isLoading: true }
|
|
22
|
-
);
|
|
23
|
-
assert.equal(
|
|
24
|
-
typeof (res2 as any)?.dbo.items4.useFind,
|
|
25
|
-
"function"
|
|
26
|
-
);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
await test("useProstglesClient with initial skip", async (t) => {
|
|
30
|
-
const { results: [res1], rerender } = await renderReactHook({
|
|
31
|
-
hook: useProstglesClient,
|
|
32
|
-
props: [{ socketOptions, skip: true }],
|
|
33
|
-
expectedRerenders: 1
|
|
34
|
-
});
|
|
35
|
-
assert.deepStrictEqual(
|
|
36
|
-
res1,
|
|
37
|
-
{ isLoading: true }
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
const { results: [res2, res3] } = await rerender({
|
|
41
|
-
props: [{ socketOptions }],
|
|
42
|
-
expectedRerenders: 2,
|
|
43
|
-
});
|
|
44
|
-
assert.deepStrictEqual(
|
|
45
|
-
res2,
|
|
46
|
-
{ isLoading: true }
|
|
47
|
-
);
|
|
48
|
-
assert.equal(
|
|
49
|
-
typeof (res3 as any)?.dbo.items4.useFind,
|
|
50
|
-
"function"
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
12
|
|
|
54
13
|
const defaultFilter = { name: "abc" };
|
|
55
14
|
await Promise.all([
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@types/node": "^20.9.2",
|
|
13
|
-
"prostgles-client": "^4.0.
|
|
13
|
+
"prostgles-client": "^4.0.115",
|
|
14
14
|
"prostgles-types": "^4.0.51",
|
|
15
15
|
"socket.io-client": "^4.7.5"
|
|
16
16
|
},
|
|
@@ -351,9 +351,9 @@
|
|
|
351
351
|
}
|
|
352
352
|
},
|
|
353
353
|
"node_modules/prostgles-client": {
|
|
354
|
-
"version": "4.0.
|
|
355
|
-
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.
|
|
356
|
-
"integrity": "sha512-
|
|
354
|
+
"version": "4.0.115",
|
|
355
|
+
"resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.115.tgz",
|
|
356
|
+
"integrity": "sha512-YMnWOY352K8v++eR8Nb2Ikmi+3U0bxaFbPlsHAa1XmFhGq3UqRponUMcgYLiXjbWrvMRULSVWdYezdMTZU/a/g==",
|
|
357
357
|
"dependencies": {
|
|
358
358
|
"prostgles-types": "^4.0.74"
|
|
359
359
|
},
|
|
@@ -19,15 +19,14 @@ global.document = window.document;
|
|
|
19
19
|
import React from "react";
|
|
20
20
|
import { createRoot } from "react-dom/client";
|
|
21
21
|
|
|
22
|
+
type Hook = (...args: any[]) => any;
|
|
23
|
+
|
|
22
24
|
// TODO: add hook result types
|
|
23
25
|
type RenderHookArgs = {
|
|
24
|
-
hook:
|
|
26
|
+
hook: Hook;
|
|
25
27
|
props: any[];
|
|
26
28
|
onResult?: (result: any) => void;
|
|
27
29
|
expectedRerenders: number;
|
|
28
|
-
/**
|
|
29
|
-
* Time to wait for the expected rerenders
|
|
30
|
-
*/
|
|
31
30
|
timeout?: number;
|
|
32
31
|
/**
|
|
33
32
|
* Time to wait after the last render to resolve the promise
|
|
@@ -38,7 +37,7 @@ type RenderHookArgs = {
|
|
|
38
37
|
|
|
39
38
|
let testedHook: Function;
|
|
40
39
|
const root = createRoot(window.document.getElementById('root'));
|
|
41
|
-
const reactRender = ({ hook, props, onResult, onUnmount }: Pick<Required<RenderHookArgs>, "hook" | "props" | "onResult"> & { onUnmount: ()=>void; }) => {
|
|
40
|
+
const reactRender = ({ hook, props, onResult, onUnmount }: Pick<Required<RenderHookArgs>, "hook" | "props" | "onResult"> & { onUnmount: () => void; }) => {
|
|
42
41
|
const BasicComponent = ({ props }) => {
|
|
43
42
|
const result = hook(...props);
|
|
44
43
|
React.useEffect(() => {
|
|
@@ -65,6 +64,67 @@ const resetBasicComponent = () => {
|
|
|
65
64
|
React.createElement(OtherBasicComponent, { props: {} }, null)
|
|
66
65
|
);
|
|
67
66
|
}
|
|
67
|
+
type OnEnd<H extends Hook> = (results: ReturnType<H>[]) => Promise<void> | void;
|
|
68
|
+
export const renderReactHookManual = async <H extends Hook>(rootArgs: {
|
|
69
|
+
hook: H;
|
|
70
|
+
initialProps: Parameters<H>;
|
|
71
|
+
onUnmount?: () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Time to wait after the last render to resolve the promise
|
|
74
|
+
* default: 250
|
|
75
|
+
*/
|
|
76
|
+
renderDuration?: number;
|
|
77
|
+
onEnd?: OnEnd<H>;
|
|
78
|
+
}): Promise<{
|
|
79
|
+
setProps: (props: Parameters<H>, opts: { waitFor?: number; onEnd?: OnEnd<H>; }) => void;
|
|
80
|
+
getResults: () => ReturnType<H>[];
|
|
81
|
+
}> => {
|
|
82
|
+
const { hook, onUnmount, renderDuration = 250, onEnd } = rootArgs;
|
|
83
|
+
let lastRenderWaitTimeout: NodeJS.Timeout | null = null;
|
|
84
|
+
let didResolve = false;
|
|
85
|
+
let setProps: (props: any[]) => void;
|
|
86
|
+
resetBasicComponent();
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
const results = [];
|
|
89
|
+
const onRender = (result) => {
|
|
90
|
+
results.push(result);
|
|
91
|
+
if(didResolve) return;
|
|
92
|
+
clearTimeout(lastRenderWaitTimeout);
|
|
93
|
+
lastRenderWaitTimeout = setTimeout(async () => {
|
|
94
|
+
|
|
95
|
+
if(!setProps) {
|
|
96
|
+
reject("setProps not set");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
await onEnd?.(results);
|
|
100
|
+
didResolve = true;
|
|
101
|
+
return resolve({
|
|
102
|
+
setProps: async (props, { waitFor = 250, onEnd } = {}) => {
|
|
103
|
+
setProps(props);
|
|
104
|
+
await tout(waitFor);
|
|
105
|
+
await onEnd?.(results);
|
|
106
|
+
},
|
|
107
|
+
getResults: () => results
|
|
108
|
+
});
|
|
109
|
+
}, renderDuration);
|
|
110
|
+
}
|
|
111
|
+
const BasicComponent = ({ props: initialProps }) => {
|
|
112
|
+
const [props, _setProps] = React.useState(initialProps);
|
|
113
|
+
setProps = _setProps;
|
|
114
|
+
const result = hook(...props);
|
|
115
|
+
React.useEffect(() => {
|
|
116
|
+
return () => {
|
|
117
|
+
onUnmount?.();
|
|
118
|
+
};
|
|
119
|
+
}, []);
|
|
120
|
+
onRender(result);
|
|
121
|
+
return React.createElement('h1', null, `Hello`);
|
|
122
|
+
}
|
|
123
|
+
root.render(
|
|
124
|
+
React.createElement(BasicComponent, { props: rootArgs.initialProps }, null)
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
68
128
|
|
|
69
129
|
export const renderReactHook = (rootArgs: RenderHookArgs): Promise<RenderResult> => {
|
|
70
130
|
const { hook, props, onResult, expectedRerenders, timeout = 5000, lastRenderWait = 250 } = rootArgs;
|
|
@@ -110,4 +170,6 @@ export const renderReactHook = (rootArgs: RenderHookArgs): Promise<RenderResult>
|
|
|
110
170
|
}
|
|
111
171
|
}, timeout);
|
|
112
172
|
});
|
|
113
|
-
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const tout = (ms: number) => new Promise(res => setTimeout(res, ms));
|
|
@@ -3,25 +3,41 @@ import { describe, test } from "node:test";
|
|
|
3
3
|
import { useProstglesClient } from "prostgles-client/dist/prostgles";
|
|
4
4
|
import { AnyObject } from "prostgles-types";
|
|
5
5
|
import type { DBHandlerClient } from "./index";
|
|
6
|
-
import { renderReactHook } from "./renderReactHook";
|
|
6
|
+
import { renderReactHook, renderReactHookManual } from "./renderReactHook";
|
|
7
7
|
|
|
8
8
|
export const useProstglesTest = async (db: DBHandlerClient, getSocketOptions: (watchSchema?: boolean) => AnyObject) => {
|
|
9
9
|
await describe("useProstgles hook", async (t) => {
|
|
10
|
+
const socketOptions = getSocketOptions();
|
|
11
|
+
await test("useProstglesClient", async (t) => {
|
|
12
|
+
const { results: [res1, res2] } = await renderReactHook({
|
|
13
|
+
hook: useProstglesClient,
|
|
14
|
+
props: [{ socketOptions }],
|
|
15
|
+
expectedRerenders: 2
|
|
16
|
+
});
|
|
17
|
+
assert.deepStrictEqual(
|
|
18
|
+
res1,
|
|
19
|
+
{ isLoading: true }
|
|
20
|
+
);
|
|
21
|
+
assert.equal(
|
|
22
|
+
typeof (res2 as any)?.dbo.items4.useFind,
|
|
23
|
+
"function"
|
|
24
|
+
);
|
|
25
|
+
});
|
|
10
26
|
|
|
27
|
+
const newTableName = "newly_created_table";
|
|
11
28
|
await test("useProstglesClient with schema reload", async (t) => {
|
|
12
|
-
|
|
13
|
-
await db.sql(`DROP TABLE IF EXISTS ${newTableName};`);
|
|
29
|
+
await db.sql(`DROP TABLE IF EXISTS ${newTableName}; DROP TABLE IF EXISTS will_delete;`);
|
|
14
30
|
await db.sql(`select pg_sleep(1)`);
|
|
15
31
|
let rerenders = 0
|
|
16
|
-
const { results: [res1, res2, res3] } = await renderReactHook({
|
|
32
|
+
const { results: [res1, res2, res3], rerender } = await renderReactHook({
|
|
17
33
|
hook: useProstglesClient,
|
|
18
|
-
props: [{ socketOptions:
|
|
34
|
+
props: [{ socketOptions: getSocketOptions(true) }],
|
|
19
35
|
expectedRerenders: 3,
|
|
20
36
|
onResult: () => {
|
|
21
37
|
rerenders++;
|
|
22
38
|
if(rerenders < 2) return;
|
|
23
39
|
rerenders = -2;
|
|
24
|
-
db.sql(`CREATE TABLE ${newTableName}();`);
|
|
40
|
+
db.sql(`CREATE TABLE ${newTableName}(id integer);`);
|
|
25
41
|
}
|
|
26
42
|
});
|
|
27
43
|
assert.deepStrictEqual(
|
|
@@ -40,6 +56,55 @@ export const useProstglesTest = async (db: DBHandlerClient, getSocketOptions: (w
|
|
|
40
56
|
typeof (res3 as any)?.dbo[newTableName].useFind,
|
|
41
57
|
"function"
|
|
42
58
|
);
|
|
59
|
+
|
|
60
|
+
const count = await (res3 as any)?.dbo[newTableName].count();
|
|
61
|
+
assert.equal(count, 0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await test("useProstglesClient with initial skip", async (t) => {
|
|
65
|
+
const { setProps } = await renderReactHookManual({
|
|
66
|
+
hook: useProstglesClient,
|
|
67
|
+
initialProps: [{ socketOptions, skip: true }],
|
|
68
|
+
onEnd: async (results) => {
|
|
69
|
+
assert.deepStrictEqual(results, [{ isLoading: true }]);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
await setProps([{ socketOptions }], {
|
|
73
|
+
onEnd: async (results) => {
|
|
74
|
+
assert.equal(results.length, 3);
|
|
75
|
+
const [res1, res2, res3] = results;
|
|
76
|
+
assert.deepStrictEqual([res1, res2], [{ isLoading: true }, { isLoading: true }]);
|
|
77
|
+
const count = await (res3 as any)?.dbo.items4.count();
|
|
78
|
+
assert.equal(count, 0);
|
|
79
|
+
|
|
80
|
+
assert.equal(res3.isLoading, false);
|
|
81
|
+
if("error" in res3) throw res3.error;
|
|
82
|
+
assert.equal(
|
|
83
|
+
typeof res3.dbo[newTableName]?.useFind,
|
|
84
|
+
"undefined"
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
await setProps([{ socketOptions: getSocketOptions(true) }], {
|
|
90
|
+
onEnd: async (results) => {
|
|
91
|
+
assert.equal(results.length, 5);
|
|
92
|
+
const [res1, res2, res3, res4, res5] = results;
|
|
93
|
+
assert.equal(results.length, 5);
|
|
94
|
+
assert.equal(res5.isLoading, false);
|
|
95
|
+
if("error" in res5) throw res5.error;
|
|
96
|
+
|
|
97
|
+
const count = await res5.dbo.items4.count();
|
|
98
|
+
assert.equal(count, 0);
|
|
99
|
+
|
|
100
|
+
assert.equal(
|
|
101
|
+
typeof res5.dbo[newTableName].useFind,
|
|
102
|
+
"function"
|
|
103
|
+
);
|
|
104
|
+
const count0 = await res5.dbo[newTableName].count();
|
|
105
|
+
assert.equal(count0, 0);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
43
108
|
});
|
|
44
109
|
|
|
45
110
|
});
|
|
@@ -264,6 +264,7 @@ export type DBSchemaGenerated = {
|
|
|
264
264
|
update: true;
|
|
265
265
|
delete: true;
|
|
266
266
|
columns: {
|
|
267
|
+
id?: null | number;
|
|
267
268
|
};
|
|
268
269
|
};
|
|
269
270
|
obj_table: {
|
|
@@ -532,4 +533,5 @@ export type DBSchemaGenerated = {
|
|
|
532
533
|
tsv?: null | string;
|
|
533
534
|
};
|
|
534
535
|
};
|
|
536
|
+
|
|
535
537
|
}
|