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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.2.40",
3
+ "version": "4.2.41",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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.109",
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.109",
355
- "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.109.tgz",
356
- "integrity": "sha512-PUziWyoM3Khyv4f/MthguaVdM/zTXFjlRRetD6oaVd1S8wipJ9BWEWAoR/LsOdbZdMZGDwmY8+fcJp+IRdojnQ==",
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
  },
@@ -13,7 +13,7 @@
13
13
  "license": "ISC",
14
14
  "dependencies": {
15
15
  "@types/node": "^20.9.2",
16
- "prostgles-client": "^4.0.109",
16
+ "prostgles-client": "^4.0.115",
17
17
  "prostgles-types": "^4.0.51",
18
18
  "socket.io-client": "^4.7.5"
19
19
  },
@@ -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: (...args: any[]) => any;
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
- const newTableName = "newly_created_table";
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: getSocketOptions(true) }],
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
  }
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "../..": {
23
23
  "name": "prostgles-server",
24
- "version": "4.2.39",
24
+ "version": "4.2.40",
25
25
  "license": "MIT",
26
26
  "dependencies": {
27
27
  "@types/express": "^4.17.13",