@push-rpc/next 2.0.0-beta.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.
Files changed (97) hide show
  1. package/.prettierrc.json +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +26 -0
  4. package/dist/client/HttpClient.d.ts +10 -0
  5. package/dist/client/HttpClient.js +67 -0
  6. package/dist/client/HttpClient.js.map +1 -0
  7. package/dist/client/RemoteSubscriptions.d.ts +14 -0
  8. package/dist/client/RemoteSubscriptions.js +84 -0
  9. package/dist/client/RemoteSubscriptions.js.map +1 -0
  10. package/dist/client/RpcClientImpl.d.ts +22 -0
  11. package/dist/client/RpcClientImpl.js +96 -0
  12. package/dist/client/RpcClientImpl.js.map +1 -0
  13. package/dist/client/WebSocketConnection.d.ts +33 -0
  14. package/dist/client/WebSocketConnection.js +152 -0
  15. package/dist/client/WebSocketConnection.js.map +1 -0
  16. package/dist/client/index.d.ts +22 -0
  17. package/dist/client/index.js +28 -0
  18. package/dist/client/index.js.map +1 -0
  19. package/dist/client/remote.d.ts +14 -0
  20. package/dist/client/remote.js +66 -0
  21. package/dist/client/remote.js.map +1 -0
  22. package/dist/index.d.ts +12 -0
  23. package/dist/index.js +20 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/logger.d.ts +8 -0
  26. package/dist/logger.js +9 -0
  27. package/dist/logger.js.map +1 -0
  28. package/dist/rpc.d.ts +36 -0
  29. package/dist/rpc.js +32 -0
  30. package/dist/rpc.js.map +1 -0
  31. package/dist/server/ConnectionsServer.d.ts +13 -0
  32. package/dist/server/ConnectionsServer.js +60 -0
  33. package/dist/server/ConnectionsServer.js.map +1 -0
  34. package/dist/server/LocalSubscriptions.d.ts +12 -0
  35. package/dist/server/LocalSubscriptions.js +113 -0
  36. package/dist/server/LocalSubscriptions.js.map +1 -0
  37. package/dist/server/RpcServerImpl.d.ts +23 -0
  38. package/dist/server/RpcServerImpl.js +164 -0
  39. package/dist/server/RpcServerImpl.js.map +1 -0
  40. package/dist/server/http.d.ts +9 -0
  41. package/dist/server/http.js +83 -0
  42. package/dist/server/http.js.map +1 -0
  43. package/dist/server/index.d.ts +29 -0
  44. package/dist/server/index.js +31 -0
  45. package/dist/server/index.js.map +1 -0
  46. package/dist/server/local.d.ts +15 -0
  47. package/dist/server/local.js +46 -0
  48. package/dist/server/local.js.map +1 -0
  49. package/dist/utils/json.d.ts +2 -0
  50. package/dist/utils/json.js +34 -0
  51. package/dist/utils/json.js.map +1 -0
  52. package/dist/utils/middleware.d.ts +2 -0
  53. package/dist/utils/middleware.js +31 -0
  54. package/dist/utils/middleware.js.map +1 -0
  55. package/dist/utils/promises.d.ts +5 -0
  56. package/dist/utils/promises.js +29 -0
  57. package/dist/utils/promises.js.map +1 -0
  58. package/dist/utils/throttle.d.ts +4 -0
  59. package/dist/utils/throttle.js +40 -0
  60. package/dist/utils/throttle.js.map +1 -0
  61. package/dist/utils/types.d.ts +1 -0
  62. package/dist/utils/types.js +3 -0
  63. package/dist/utils/types.js.map +1 -0
  64. package/example/api.ts +15 -0
  65. package/example/client.ts +16 -0
  66. package/example/server.ts +37 -0
  67. package/package.json +34 -0
  68. package/src/client/HttpClient.ts +80 -0
  69. package/src/client/RemoteSubscriptions.ts +121 -0
  70. package/src/client/RpcClientImpl.ts +177 -0
  71. package/src/client/WebSocketConnection.ts +183 -0
  72. package/src/client/index.ts +56 -0
  73. package/src/client/remote.ts +118 -0
  74. package/src/index.ts +18 -0
  75. package/src/logger.ts +12 -0
  76. package/src/rpc.ts +51 -0
  77. package/src/server/ConnectionsServer.ts +78 -0
  78. package/src/server/LocalSubscriptions.ts +155 -0
  79. package/src/server/RpcServerImpl.ts +252 -0
  80. package/src/server/http.ts +109 -0
  81. package/src/server/index.ts +65 -0
  82. package/src/server/local.ts +80 -0
  83. package/src/utils/json.ts +32 -0
  84. package/src/utils/middleware.ts +38 -0
  85. package/src/utils/promises.ts +25 -0
  86. package/src/utils/throttle.ts +48 -0
  87. package/src/utils/types.ts +1 -0
  88. package/tests/calls.ts +215 -0
  89. package/tests/connection.ts +107 -0
  90. package/tests/context.ts +176 -0
  91. package/tests/middleware.ts +112 -0
  92. package/tests/misc.ts +187 -0
  93. package/tests/subscriptions.ts +442 -0
  94. package/tests/testUtils.ts +52 -0
  95. package/tests/triggers.ts +138 -0
  96. package/tsconfig.cjs.json +20 -0
  97. package/tsconfig.json +26 -0
@@ -0,0 +1,176 @@
1
+ import {createTestClient, startTestServer} from "./testUtils.js"
2
+ import {assert} from "chai"
3
+ import {adelay} from "../src/utils/promises.js"
4
+ import {RpcContext} from "../src/index.js"
5
+ import {InvocationType, RpcConnectionContext} from "../src/rpc.js"
6
+
7
+ describe("context", () => {
8
+ it("available in call", async () => {
9
+ let ctx: RpcContext | undefined
10
+
11
+ const services = await startTestServer({
12
+ test: {
13
+ async call(passedCtx?: RpcContext) {
14
+ ctx = passedCtx
15
+ },
16
+ },
17
+ })
18
+
19
+ const client = await createTestClient<typeof services>()
20
+
21
+ await client.test.call()
22
+
23
+ assert.ok(ctx)
24
+ assert.ok(ctx!.clientId)
25
+ assert.equal(ctx!.itemName, "test/call")
26
+ assert.equal(ctx!.invocationType, InvocationType.Call)
27
+ })
28
+
29
+ it("override creation", async () => {
30
+ let ctx = null
31
+
32
+ const services = await startTestServer(
33
+ {
34
+ test: {
35
+ async call(passedCtx?: any) {
36
+ ctx = passedCtx
37
+ },
38
+ },
39
+ },
40
+ {
41
+ async createConnectionContext() {
42
+ return {clientId: "test", newKey: "bla"}
43
+ },
44
+ }
45
+ )
46
+
47
+ const client = await createTestClient<typeof services>()
48
+
49
+ await client.test.call()
50
+
51
+ assert.equal(ctx!.clientId, "test")
52
+ assert.equal(ctx!.newKey, "bla")
53
+ })
54
+
55
+ it("available in subscribe", async () => {
56
+ let ctx = null
57
+
58
+ const services = await startTestServer({
59
+ test: {
60
+ async call(passedCtx?: any) {
61
+ ctx = passedCtx
62
+ },
63
+ },
64
+ })
65
+
66
+ const client = await createTestClient<typeof services>()
67
+
68
+ await client.test.call.subscribe(() => {})
69
+
70
+ assert.ok(ctx)
71
+ assert.ok(ctx!.clientId)
72
+ assert.equal(ctx!.invocationType, InvocationType.Subscribe)
73
+ })
74
+
75
+ it("available in trigger", async () => {
76
+ let ctx = null
77
+
78
+ const services = await startTestServer(
79
+ {
80
+ test: {
81
+ async call(passedCtx?: any) {
82
+ ctx = passedCtx
83
+ },
84
+ },
85
+ },
86
+ {
87
+ async createConnectionContext() {
88
+ return {clientId: "test"}
89
+ },
90
+ }
91
+ )
92
+
93
+ const client = await createTestClient<typeof services>()
94
+
95
+ await client.test.call.subscribe(() => {})
96
+ assert.equal(ctx!.clientId, "test")
97
+
98
+ ctx = null
99
+ services.test.call.trigger()
100
+ await adelay(20)
101
+ assert.equal(ctx!.clientId, "test")
102
+ assert.equal(ctx!.invocationType, InvocationType.Trigger)
103
+ })
104
+
105
+ it("trigger has a copy", async () => {
106
+ let ctx = null
107
+
108
+ let count = 0
109
+
110
+ const services = await startTestServer(
111
+ {
112
+ test: {
113
+ async call(passedCtx?: any) {
114
+ ctx = passedCtx
115
+
116
+ if (!count) {
117
+ ctx.modified = true
118
+ }
119
+
120
+ count++
121
+ },
122
+ },
123
+ },
124
+ {
125
+ async createConnectionContext() {
126
+ return {clientId: "test"}
127
+ },
128
+ }
129
+ )
130
+
131
+ const client = await createTestClient<typeof services>()
132
+
133
+ await client.test.call.subscribe(() => {})
134
+ services.test.call.trigger()
135
+
136
+ await adelay(20)
137
+ assert.isNotOk(ctx!.modified)
138
+ })
139
+
140
+ it("modified in middleware", async () => {
141
+ let ctx = null
142
+
143
+ type Ctx = RpcContext & {count: number}
144
+
145
+ const services = await startTestServer(
146
+ {
147
+ test: {
148
+ async call(passedCtx?: any) {
149
+ ctx = passedCtx
150
+ },
151
+ },
152
+ },
153
+ {
154
+ async createConnectionContext() {
155
+ return {clientId: "test", count: 0}
156
+ },
157
+ middleware: [
158
+ (ctx: Ctx, next) => {
159
+ ctx.count++
160
+ return next(ctx)
161
+ },
162
+ ],
163
+ }
164
+ )
165
+
166
+ const client = await createTestClient<typeof services>()
167
+
168
+ await client.test.call.subscribe(() => {})
169
+ assert.equal(ctx!.count, 1)
170
+
171
+ services.test.call.trigger()
172
+
173
+ await adelay(20)
174
+ assert.equal(ctx!.count, 1)
175
+ })
176
+ })
@@ -0,0 +1,112 @@
1
+ import {assert} from "chai"
2
+ import {Middleware, withMiddlewares} from "../src/index.js"
3
+ import {createTestClient, startTestServer} from "./testUtils.js"
4
+ import {adelay} from "../src/utils/promises.js"
5
+
6
+ describe("middleware", () => {
7
+ it("compose override params", async () => {
8
+ const m1: Middleware<{}> = (ctx, next, param: any) => {
9
+ return next(param + 1)
10
+ }
11
+
12
+ const m2: Middleware<{}> = (ctx, next, param: any) => {
13
+ return next(param + 2)
14
+ }
15
+
16
+ const r = await withMiddlewares({}, [m1, m2], async (p, ctx) => p, 0)
17
+
18
+ assert.equal(r, 3)
19
+ })
20
+
21
+ it("compose use prev params", async () => {
22
+ const m1: Middleware<{}> = (ctx, next) => {
23
+ return next()
24
+ }
25
+
26
+ const r = await withMiddlewares({}, [m1], async (p) => p, 0)
27
+
28
+ assert.equal(r, 0)
29
+ })
30
+
31
+ it("local", async () => {
32
+ let contextValue = null
33
+
34
+ const services = await startTestServer(
35
+ {
36
+ item: async (ctx?: any) => {
37
+ contextValue = ctx.value
38
+ },
39
+ },
40
+ {
41
+ middleware: [
42
+ (ctx: any, next) => {
43
+ ctx.value = 1
44
+ return next()
45
+ },
46
+ ],
47
+ }
48
+ )
49
+
50
+ const remote = await createTestClient<typeof services>()
51
+ await remote.item()
52
+ assert.equal(contextValue, 1)
53
+
54
+ contextValue = null
55
+ await remote.item.subscribe(() => {})
56
+ assert.equal(contextValue, 1)
57
+
58
+ contextValue = null
59
+ services.item.trigger()
60
+ await adelay(20)
61
+ assert.equal(contextValue, 1)
62
+ })
63
+
64
+ it("remote", async () => {
65
+ let mwInvoked = false
66
+
67
+ const services = await startTestServer({
68
+ item: async () => "1",
69
+ })
70
+
71
+ const remote = await createTestClient<typeof services>({
72
+ middleware: [
73
+ (ctx, next) => {
74
+ mwInvoked = true
75
+ return next()
76
+ },
77
+ ],
78
+ })
79
+
80
+ await remote.item()
81
+ assert.isOk(mwInvoked)
82
+
83
+ const sub = () => {}
84
+
85
+ mwInvoked = false
86
+ await remote.item.subscribe(sub)
87
+ assert.isOk(mwInvoked)
88
+
89
+ mwInvoked = false
90
+ await remote.item.unsubscribe(sub)
91
+ assert.isOk(mwInvoked)
92
+ })
93
+
94
+ it("remote with rejection", async () => {
95
+ const services = await startTestServer({
96
+ async getSomething() {
97
+ throw new Error("msg")
98
+ },
99
+ })
100
+
101
+ const client = await createTestClient<typeof services>({
102
+ middleware: [(ctx, next, params) => next(params)],
103
+ })
104
+
105
+ try {
106
+ await client.getSomething()
107
+ assert.fail("Error expected")
108
+ } catch (e: any) {
109
+ assert.equal(e.message, "msg")
110
+ }
111
+ })
112
+ })
package/tests/misc.ts ADDED
@@ -0,0 +1,187 @@
1
+ import {assert} from "chai"
2
+ import {createTestClient, startTestServer, TEST_PORT} from "./testUtils.js"
3
+ import {RpcErrors} from "../src/index.js"
4
+
5
+ describe("Misc", () => {
6
+ it("Send array in parameter", async () => {
7
+ let param
8
+
9
+ const services = await startTestServer({
10
+ async hello(p) {
11
+ param = p
12
+ },
13
+ })
14
+
15
+ const client = await createTestClient<typeof services>()
16
+
17
+ await client.hello(["a"])
18
+ assert.equal(typeof param, "object")
19
+ assert.isArray(param)
20
+ })
21
+
22
+ it("Circular reference in params", async () => {
23
+ let param: any
24
+
25
+ const services = await startTestServer({
26
+ async hello(p) {
27
+ param = p
28
+ },
29
+ })
30
+
31
+ const client = await createTestClient<typeof services>()
32
+
33
+ const msg = {
34
+ some: "string",
35
+ ref: null as any,
36
+ }
37
+ msg.ref = msg
38
+
39
+ await client.hello(msg)
40
+
41
+ assert.equal(param.some, msg.some)
42
+ })
43
+
44
+ it("Circular reference in response", async () => {
45
+ const msg = {
46
+ some: "string",
47
+ ref: null as any,
48
+ }
49
+ msg.ref = msg
50
+
51
+ const services = await startTestServer({
52
+ async hello() {
53
+ return msg
54
+ },
55
+ })
56
+
57
+ const client = await createTestClient<typeof services>()
58
+
59
+ const r = await client.hello()
60
+
61
+ assert.equal(r.some, msg.some)
62
+ })
63
+
64
+ it("date in response", async () => {
65
+ const date = new Date()
66
+
67
+ const msg = {
68
+ date,
69
+ }
70
+
71
+ const services = await startTestServer({
72
+ async hello() {
73
+ return msg
74
+ },
75
+ })
76
+
77
+ const client = await createTestClient<typeof services>()
78
+
79
+ const r = await client.hello()
80
+
81
+ assert.equal(r.date.getTime(), date.getTime())
82
+ })
83
+
84
+ it("date in params", async () => {
85
+ const date = new Date()
86
+
87
+ let receivedDate: Date | undefined
88
+
89
+ const services = await startTestServer({
90
+ async hello(d: Date) {
91
+ receivedDate = d
92
+ },
93
+ })
94
+
95
+ const client = await createTestClient<typeof services>()
96
+
97
+ await client.hello(date)
98
+ assert.equal(receivedDate!.getTime(), date.getTime())
99
+ })
100
+
101
+ it("null member in local", async () => {
102
+ await startTestServer({
103
+ nested: null,
104
+ } as any)
105
+ })
106
+
107
+ it("recursive member in local", async () => {
108
+ const local = {
109
+ nested: null as unknown,
110
+ }
111
+
112
+ local.nested = local
113
+
114
+ await startTestServer(local as any)
115
+ })
116
+
117
+ it("Non flat remote", async () => {
118
+ const services = await startTestServer({
119
+ async hello1() {
120
+ return "yes1"
121
+ },
122
+
123
+ nested: {
124
+ async hello2() {
125
+ return "yes2"
126
+ },
127
+ },
128
+ })
129
+
130
+ const client = await createTestClient<typeof services>()
131
+
132
+ assert.equal("yes1", await client.hello1())
133
+ assert.equal("yes2", await client.nested.hello2())
134
+ })
135
+
136
+ it("Item not found", async () => {
137
+ await startTestServer({
138
+ async hello1() {
139
+ return "yes1"
140
+ },
141
+
142
+ nested: {
143
+ async hello2() {
144
+ return "yes2"
145
+ },
146
+ },
147
+ })
148
+
149
+ const remote: any = await createTestClient<any>()
150
+
151
+ try {
152
+ await remote.hello()
153
+ assert.fail("Error expected")
154
+ } catch (e: any) {
155
+ assert.equal(e.code, RpcErrors.NotFound)
156
+ }
157
+
158
+ try {
159
+ await remote.nested.hello()
160
+ assert.fail("Error expected")
161
+ } catch (e: any) {
162
+ assert.equal(e.code, RpcErrors.NotFound)
163
+ }
164
+
165
+ try {
166
+ await remote.nested.nested2.hello()
167
+ assert.fail("Error expected")
168
+ } catch (e: any) {
169
+ assert.equal(e.code, RpcErrors.NotFound)
170
+ }
171
+ })
172
+
173
+ it("invoke with empty body", async () => {
174
+ await startTestServer({
175
+ async hello1() {
176
+ return "yes1"
177
+ },
178
+ })
179
+
180
+ const r = await fetch(`http://127.0.0.1:${TEST_PORT}/rpc/hello1`, {
181
+ method: "POST",
182
+ })
183
+
184
+ const body = await r.text()
185
+ assert.equal(body, "yes1")
186
+ })
187
+ })