@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.
- package/.prettierrc.json +7 -0
- package/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/client/HttpClient.d.ts +10 -0
- package/dist/client/HttpClient.js +67 -0
- package/dist/client/HttpClient.js.map +1 -0
- package/dist/client/RemoteSubscriptions.d.ts +14 -0
- package/dist/client/RemoteSubscriptions.js +84 -0
- package/dist/client/RemoteSubscriptions.js.map +1 -0
- package/dist/client/RpcClientImpl.d.ts +22 -0
- package/dist/client/RpcClientImpl.js +96 -0
- package/dist/client/RpcClientImpl.js.map +1 -0
- package/dist/client/WebSocketConnection.d.ts +33 -0
- package/dist/client/WebSocketConnection.js +152 -0
- package/dist/client/WebSocketConnection.js.map +1 -0
- package/dist/client/index.d.ts +22 -0
- package/dist/client/index.js +28 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/remote.d.ts +14 -0
- package/dist/client/remote.js +66 -0
- package/dist/client/remote.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.js +9 -0
- package/dist/logger.js.map +1 -0
- package/dist/rpc.d.ts +36 -0
- package/dist/rpc.js +32 -0
- package/dist/rpc.js.map +1 -0
- package/dist/server/ConnectionsServer.d.ts +13 -0
- package/dist/server/ConnectionsServer.js +60 -0
- package/dist/server/ConnectionsServer.js.map +1 -0
- package/dist/server/LocalSubscriptions.d.ts +12 -0
- package/dist/server/LocalSubscriptions.js +113 -0
- package/dist/server/LocalSubscriptions.js.map +1 -0
- package/dist/server/RpcServerImpl.d.ts +23 -0
- package/dist/server/RpcServerImpl.js +164 -0
- package/dist/server/RpcServerImpl.js.map +1 -0
- package/dist/server/http.d.ts +9 -0
- package/dist/server/http.js +83 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/index.d.ts +29 -0
- package/dist/server/index.js +31 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/local.d.ts +15 -0
- package/dist/server/local.js +46 -0
- package/dist/server/local.js.map +1 -0
- package/dist/utils/json.d.ts +2 -0
- package/dist/utils/json.js +34 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/middleware.d.ts +2 -0
- package/dist/utils/middleware.js +31 -0
- package/dist/utils/middleware.js.map +1 -0
- package/dist/utils/promises.d.ts +5 -0
- package/dist/utils/promises.js +29 -0
- package/dist/utils/promises.js.map +1 -0
- package/dist/utils/throttle.d.ts +4 -0
- package/dist/utils/throttle.js +40 -0
- package/dist/utils/throttle.js.map +1 -0
- package/dist/utils/types.d.ts +1 -0
- package/dist/utils/types.js +3 -0
- package/dist/utils/types.js.map +1 -0
- package/example/api.ts +15 -0
- package/example/client.ts +16 -0
- package/example/server.ts +37 -0
- package/package.json +34 -0
- package/src/client/HttpClient.ts +80 -0
- package/src/client/RemoteSubscriptions.ts +121 -0
- package/src/client/RpcClientImpl.ts +177 -0
- package/src/client/WebSocketConnection.ts +183 -0
- package/src/client/index.ts +56 -0
- package/src/client/remote.ts +118 -0
- package/src/index.ts +18 -0
- package/src/logger.ts +12 -0
- package/src/rpc.ts +51 -0
- package/src/server/ConnectionsServer.ts +78 -0
- package/src/server/LocalSubscriptions.ts +155 -0
- package/src/server/RpcServerImpl.ts +252 -0
- package/src/server/http.ts +109 -0
- package/src/server/index.ts +65 -0
- package/src/server/local.ts +80 -0
- package/src/utils/json.ts +32 -0
- package/src/utils/middleware.ts +38 -0
- package/src/utils/promises.ts +25 -0
- package/src/utils/throttle.ts +48 -0
- package/src/utils/types.ts +1 -0
- package/tests/calls.ts +215 -0
- package/tests/connection.ts +107 -0
- package/tests/context.ts +176 -0
- package/tests/middleware.ts +112 -0
- package/tests/misc.ts +187 -0
- package/tests/subscriptions.ts +442 -0
- package/tests/testUtils.ts +52 -0
- package/tests/triggers.ts +138 -0
- package/tsconfig.cjs.json +20 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serveHttpRequest = void 0;
|
|
4
|
+
const json_js_1 = require("../utils/json.js");
|
|
5
|
+
const logger_js_1 = require("../logger.js");
|
|
6
|
+
async function serveHttpRequest(req, res, path, hooks, createConnectionContext) {
|
|
7
|
+
// if port is in options - response 404 on other URLs
|
|
8
|
+
// oherwise just handle request
|
|
9
|
+
if (req.url?.startsWith(path)) {
|
|
10
|
+
try {
|
|
11
|
+
const ctx = await createConnectionContext(req);
|
|
12
|
+
const itemName = req.url.slice(path.length + 1);
|
|
13
|
+
const isJson = req.headersDistinct["content-type"]?.includes("application/json") ?? false;
|
|
14
|
+
const body = isJson ? (0, json_js_1.safeParseJson)(await readBody(req)) : [];
|
|
15
|
+
let result;
|
|
16
|
+
switch (req.method) {
|
|
17
|
+
case "POST":
|
|
18
|
+
result = await hooks.call(ctx, itemName, body);
|
|
19
|
+
break;
|
|
20
|
+
case "PUT":
|
|
21
|
+
result = await hooks.subscribe(ctx, itemName, body);
|
|
22
|
+
break;
|
|
23
|
+
case "PATCH":
|
|
24
|
+
result = await hooks.unsubscribe(ctx, itemName, body);
|
|
25
|
+
break;
|
|
26
|
+
default:
|
|
27
|
+
res.statusCode = 404;
|
|
28
|
+
res.end();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (typeof result == "undefined") {
|
|
32
|
+
res.statusCode = 204;
|
|
33
|
+
res.end();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (typeof result == "string") {
|
|
37
|
+
res.setHeader("Content-Type", "text/plain");
|
|
38
|
+
res.write(result);
|
|
39
|
+
res.end();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
res.setHeader("Content-Type", "application/json");
|
|
43
|
+
res.write((0, json_js_1.safeStringify)(result));
|
|
44
|
+
res.end();
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
if (e.code) {
|
|
48
|
+
res.statusCode = e.code;
|
|
49
|
+
res.statusMessage = e.message;
|
|
50
|
+
const { code, message, stack, ...rest } = e;
|
|
51
|
+
if (Object.keys(rest).length > 0) {
|
|
52
|
+
res.setHeader("Content-Type", "application/json");
|
|
53
|
+
res.write((0, json_js_1.safeStringify)(rest));
|
|
54
|
+
}
|
|
55
|
+
res.end();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
logger_js_1.log.warn(`Error in ${req.url}.`, e);
|
|
60
|
+
res.statusCode = 500;
|
|
61
|
+
res.statusMessage = e["message"] || "Internal Server Error";
|
|
62
|
+
res.end();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.serveHttpRequest = serveHttpRequest;
|
|
69
|
+
function readBody(req) {
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
let body = "";
|
|
72
|
+
req.on("data", (chunk) => {
|
|
73
|
+
body += chunk.toString();
|
|
74
|
+
});
|
|
75
|
+
req.on("end", () => {
|
|
76
|
+
resolve(body);
|
|
77
|
+
});
|
|
78
|
+
req.on("error", (error) => {
|
|
79
|
+
reject(error);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { RpcConnectionContext, RpcContext, Services } from "../rpc.js";
|
|
3
|
+
import { ServicesWithTriggers } from "./local.js";
|
|
4
|
+
import { Middleware } from "../utils/middleware.js";
|
|
5
|
+
import http, { IncomingMessage } from "http";
|
|
6
|
+
export declare function publishServices<S extends Services<S>, C extends RpcContext>(services: S, overrideOptions: Partial<PublishServicesOptions<C>> & ({
|
|
7
|
+
port: number;
|
|
8
|
+
} | {
|
|
9
|
+
server: http.Server;
|
|
10
|
+
})): Promise<{
|
|
11
|
+
server: RpcServer;
|
|
12
|
+
services: ServicesWithTriggers<S>;
|
|
13
|
+
httpServer: http.Server;
|
|
14
|
+
}>;
|
|
15
|
+
export type RpcServer = {
|
|
16
|
+
close(): Promise<void>;
|
|
17
|
+
_allSubscriptions(): Array<any[]>;
|
|
18
|
+
};
|
|
19
|
+
export type PublishServicesOptions<C extends RpcContext> = {
|
|
20
|
+
host: string;
|
|
21
|
+
path: string;
|
|
22
|
+
middleware: Middleware<C>[];
|
|
23
|
+
pingInterval: number;
|
|
24
|
+
createConnectionContext(req: IncomingMessage): Promise<RpcConnectionContext>;
|
|
25
|
+
} & ({
|
|
26
|
+
server: http.Server;
|
|
27
|
+
} | {
|
|
28
|
+
port: number;
|
|
29
|
+
} | {});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.publishServices = void 0;
|
|
4
|
+
const rpc_js_1 = require("../rpc.js");
|
|
5
|
+
const RpcServerImpl_js_1 = require("./RpcServerImpl.js");
|
|
6
|
+
async function publishServices(services, overrideOptions) {
|
|
7
|
+
const options = {
|
|
8
|
+
...defaultOptions,
|
|
9
|
+
...overrideOptions,
|
|
10
|
+
};
|
|
11
|
+
const rpcServer = new RpcServerImpl_js_1.RpcServerImpl(services, options);
|
|
12
|
+
await rpcServer.start();
|
|
13
|
+
return {
|
|
14
|
+
services: rpcServer.createServicesWithTriggers(),
|
|
15
|
+
server: rpcServer,
|
|
16
|
+
httpServer: rpcServer.httpServer,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
exports.publishServices = publishServices;
|
|
20
|
+
const defaultOptions = {
|
|
21
|
+
path: "",
|
|
22
|
+
host: "0.0.0.0",
|
|
23
|
+
middleware: [],
|
|
24
|
+
pingInterval: 30 * 1000, // should be in-sync with client
|
|
25
|
+
async createConnectionContext(req) {
|
|
26
|
+
return {
|
|
27
|
+
clientId: req.headersDistinct[rpc_js_1.CLIENT_ID_HEADER]?.[0] || "anon",
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";;;AAAA,sCAAsF;AAGtF,yDAAgD;AAGzC,KAAK,UAAU,eAAe,CACnC,QAAW,EACX,eAA8F;IAM9F,MAAM,OAAO,GAAG;QACd,GAAG,cAAc;QACjB,GAAG,eAAe;KACnB,CAAA;IAED,MAAM,SAAS,GAAG,IAAI,gCAAa,CAAO,QAAQ,EAAE,OAAO,CAAC,CAAA;IAE5D,MAAM,SAAS,CAAC,KAAK,EAAE,CAAA;IAEvB,OAAO;QACL,QAAQ,EAAE,SAAS,CAAC,0BAA0B,EAAE;QAChD,MAAM,EAAE,SAAS;QACjB,UAAU,EAAE,SAAS,CAAC,UAAU;KACjC,CAAA;AACH,CAAC;AAtBD,0CAsBC;AAyBD,MAAM,cAAc,GAAqD;IACvE,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,SAAS;IACf,UAAU,EAAE,EAAE;IACd,YAAY,EAAE,EAAE,GAAG,IAAI,EAAE,gCAAgC;IAEzD,KAAK,CAAC,uBAAuB,CAAC,GAAoB;QAChD,OAAO;YACL,QAAQ,EAAE,GAAG,CAAC,eAAe,CAAC,yBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM;SAC/D,CAAA;IACH,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RemoteFunction, Services } from "../rpc.js";
|
|
2
|
+
import { LocalSubscriptions } from "./LocalSubscriptions.js";
|
|
3
|
+
import { ExtractPromiseResult } from "../utils/types.js";
|
|
4
|
+
import { ThrottleArgsReducer } from "../utils/throttle.js";
|
|
5
|
+
export type ThrottleSettings<D> = {
|
|
6
|
+
timeout: number;
|
|
7
|
+
reducer?: ThrottleArgsReducer<D>;
|
|
8
|
+
};
|
|
9
|
+
export declare function withTriggers<T extends Services<T>>(localSubscriptions: LocalSubscriptions, services: T, name?: string): ServicesWithTriggers<T>;
|
|
10
|
+
export type ServicesWithTriggers<T extends Services<T>> = {
|
|
11
|
+
[K in keyof T]: T[K] extends RemoteFunction ? T[K] & {
|
|
12
|
+
trigger(filter?: Partial<Parameters<T[K]>[0]>, suppliedData?: ExtractPromiseResult<ReturnType<T[K]>>): void;
|
|
13
|
+
throttle(settings: ThrottleSettings<ExtractPromiseResult<ReturnType<T[K]>>>): void;
|
|
14
|
+
} : T[K] extends object ? ServicesWithTriggers<T[K]> : never;
|
|
15
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withTriggers = void 0;
|
|
4
|
+
function withTriggers(localSubscriptions, services, name = "") {
|
|
5
|
+
const cachedItems = {};
|
|
6
|
+
const skippedProps = ["length", "name", "prototype", "arguments", "caller"];
|
|
7
|
+
return new Proxy(services, {
|
|
8
|
+
get(target, propName) {
|
|
9
|
+
// skip internal props
|
|
10
|
+
if (typeof propName != "string")
|
|
11
|
+
return target[propName];
|
|
12
|
+
// skip other system props
|
|
13
|
+
if (["then", "catch", "toJSON", ...skippedProps].includes(propName))
|
|
14
|
+
return target[propName];
|
|
15
|
+
const itemName = name ? name + "/" + propName : propName;
|
|
16
|
+
if (typeof target[propName] == "function") {
|
|
17
|
+
const delegate = (...params) => {
|
|
18
|
+
return target[propName](...params);
|
|
19
|
+
};
|
|
20
|
+
delegate.trigger = (filter = {}, suppliedData) => {
|
|
21
|
+
// triggers are delayed for consumers to receive updates after the current call ends.
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
localSubscriptions.trigger(itemName, filter, suppliedData);
|
|
24
|
+
}, 0);
|
|
25
|
+
};
|
|
26
|
+
delegate.throttle = (settings) => {
|
|
27
|
+
localSubscriptions.throttleItem(itemName, settings);
|
|
28
|
+
};
|
|
29
|
+
return delegate;
|
|
30
|
+
}
|
|
31
|
+
else if (!cachedItems[propName]) {
|
|
32
|
+
cachedItems[propName] = withTriggers(localSubscriptions, services[propName], itemName);
|
|
33
|
+
}
|
|
34
|
+
return cachedItems[propName];
|
|
35
|
+
},
|
|
36
|
+
set(target, propName, value) {
|
|
37
|
+
cachedItems[propName] = value;
|
|
38
|
+
return true;
|
|
39
|
+
},
|
|
40
|
+
ownKeys() {
|
|
41
|
+
return [...skippedProps, ...Object.keys(cachedItems)];
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
exports.withTriggers = withTriggers;
|
|
46
|
+
//# sourceMappingURL=local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/server/local.ts"],"names":[],"mappings":";;;AAUA,SAAgB,YAAY,CAC1B,kBAAsC,EACtC,QAAW,EACX,IAAI,GAAG,EAAE;IAET,MAAM,WAAW,GAAQ,EAAE,CAAA;IAC3B,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAA;IAE3E,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE;QACzB,GAAG,CAAC,MAAW,EAAE,QAAgB;YAC/B,sBAAsB;YACtB,IAAI,OAAO,QAAQ,IAAI,QAAQ;gBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAA;YAExD,0BAA0B;YAC1B,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAA;YAE5F,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAA;YAExD,IAAI,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,UAAU,EAAE,CAAC;gBAC1C,MAAM,QAAQ,GAAG,CAAC,GAAG,MAAiB,EAAE,EAAE;oBACxC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAA;gBACpC,CAAC,CAAA;gBAED,QAAQ,CAAC,OAAO,GAAG,CAAC,SAAkC,EAAE,EAAE,YAAsB,EAAE,EAAE;oBAClF,qFAAqF;oBACrF,UAAU,CAAC,GAAG,EAAE;wBACd,kBAAkB,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,CAAA;oBAC5D,CAAC,EAAE,CAAC,CAAC,CAAA;gBACP,CAAC,CAAA;gBAED,QAAQ,CAAC,QAAQ,GAAG,CAAC,QAAmC,EAAE,EAAE;oBAC1D,kBAAkB,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;gBACrD,CAAC,CAAA;gBAED,OAAO,QAAQ,CAAA;YACjB,CAAC;iBAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClC,WAAW,CAAC,QAAQ,CAAC,GAAG,YAAY,CAClC,kBAAkB,EAClB,QAAQ,CAAC,QAAmB,CAAQ,EACpC,QAAQ,CACT,CAAA;YACH,CAAC;YAED,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAA;QAC9B,CAAC;QAED,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK;YACzB,WAAW,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAA;YAC7B,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO;YACL,OAAO,CAAC,GAAG,YAAY,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;QACvD,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAvDD,oCAuDC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.safeParseJson = exports.safeStringify = void 0;
|
|
7
|
+
const fast_stringify_1 = __importDefault(require("fast-stringify"));
|
|
8
|
+
function safeStringify(value) {
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
return (0, fast_stringify_1.default)(value);
|
|
11
|
+
}
|
|
12
|
+
exports.safeStringify = safeStringify;
|
|
13
|
+
function safeParseJson(json) {
|
|
14
|
+
return JSON.parse(json, dateReviver);
|
|
15
|
+
}
|
|
16
|
+
exports.safeParseJson = safeParseJson;
|
|
17
|
+
function dateReviver(key, val) {
|
|
18
|
+
if (typeof val == "string") {
|
|
19
|
+
if (ISO8601_secs.test(val)) {
|
|
20
|
+
return new Date(val);
|
|
21
|
+
}
|
|
22
|
+
if (ISO8601.test(val)) {
|
|
23
|
+
return new Date(val);
|
|
24
|
+
}
|
|
25
|
+
if (ISO8601_date.test(val)) {
|
|
26
|
+
return new Date(val);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return val;
|
|
30
|
+
}
|
|
31
|
+
const ISO8601 = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/;
|
|
32
|
+
const ISO8601_secs = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ$/;
|
|
33
|
+
const ISO8601_date = /^\d\d\d\d-\d\d-\d\d$/;
|
|
34
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/utils/json.ts"],"names":[],"mappings":";;;;;;AAAA,oEAAsC;AAEtC,SAAgB,aAAa,CAAC,KAAU;IACtC,aAAa;IACb,OAAO,IAAA,wBAAS,EAAC,KAAK,CAAC,CAAA;AACzB,CAAC;AAHD,sCAGC;AAED,SAAgB,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;AACtC,CAAC;AAFD,sCAEC;AAED,SAAS,WAAW,CAAC,GAAW,EAAE,GAAQ;IACxC,IAAI,OAAO,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAA;QACtB,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAA;QACtB,CAAC;QAED,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,OAAO,GAAG,6CAA6C,CAAA;AAC7D,MAAM,YAAY,GAAG,sCAAsC,CAAA;AAC3D,MAAM,YAAY,GAAG,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type Middleware<Context> = (ctx: Context, next: (...params: unknown[]) => Promise<unknown>, ...params: unknown[]) => Promise<unknown>;
|
|
2
|
+
export declare function withMiddlewares<Context>(ctx: Context, middlewares: Middleware<Context>[], final: (...params: unknown[]) => Promise<unknown>, ...params: any): Promise<unknown>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withMiddlewares = void 0;
|
|
4
|
+
function withMiddlewares(ctx, middlewares, final, ...params) {
|
|
5
|
+
return (function (next, ...params) {
|
|
6
|
+
let index = -1;
|
|
7
|
+
return dispatch(0, ...params);
|
|
8
|
+
function dispatch(i, ...p) {
|
|
9
|
+
if (i <= index)
|
|
10
|
+
return Promise.reject(new Error("next() called multiple times"));
|
|
11
|
+
// use previous invocation params
|
|
12
|
+
if (!p.length) {
|
|
13
|
+
p = params;
|
|
14
|
+
}
|
|
15
|
+
index = i;
|
|
16
|
+
try {
|
|
17
|
+
if (i === middlewares.length) {
|
|
18
|
+
return Promise.resolve(next(...p));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
return Promise.resolve(middlewares[i](ctx, dispatch.bind(null, i + 1), ...p));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
return Promise.reject(err);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})(final, ...params);
|
|
29
|
+
}
|
|
30
|
+
exports.withMiddlewares = withMiddlewares;
|
|
31
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/utils/middleware.ts"],"names":[],"mappings":";;;AAMA,SAAgB,eAAe,CAC7B,GAAY,EACZ,WAAkC,EAClC,KAAiD,EACjD,GAAG,MAAW;IAEd,OAAO,CAAC,UAAU,IAAI,EAAE,GAAG,MAAM;QAC/B,IAAI,KAAK,GAAG,CAAC,CAAC,CAAA;QACd,OAAO,QAAQ,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,CAAA;QAE7B,SAAS,QAAQ,CAAC,CAAS,EAAE,GAAG,CAAY;YAC1C,IAAI,CAAC,IAAI,KAAK;gBAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAA;YAEhF,iCAAiC;YACjC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;gBACd,CAAC,GAAG,MAAM,CAAA;YACZ,CAAC;YAED,KAAK,GAAG,CAAC,CAAA;YAET,IAAI,CAAC;gBACH,IAAI,CAAC,KAAK,WAAW,CAAC,MAAM,EAAE,CAAC;oBAC7B,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;gBACpC,CAAC;qBAAM,CAAC;oBACN,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;gBAC/E,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,CAAA;AACtB,CAAC;AA/BD,0CA+BC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.adelay = exports.PromiseCache = void 0;
|
|
4
|
+
class PromiseCache {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.cache = {};
|
|
7
|
+
}
|
|
8
|
+
invoke(cacheKey, supplier) {
|
|
9
|
+
const key = JSON.stringify(cacheKey);
|
|
10
|
+
if (!this.cache[key]) {
|
|
11
|
+
this.cache[key] = supplier()
|
|
12
|
+
.then((r) => {
|
|
13
|
+
delete this.cache[key];
|
|
14
|
+
return r;
|
|
15
|
+
})
|
|
16
|
+
.catch((e) => {
|
|
17
|
+
delete this.cache[key];
|
|
18
|
+
throw e;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return this.cache[key];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.PromiseCache = PromiseCache;
|
|
25
|
+
async function adelay(ms) {
|
|
26
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
27
|
+
}
|
|
28
|
+
exports.adelay = adelay;
|
|
29
|
+
//# sourceMappingURL=promises.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promises.js","sourceRoot":"","sources":["../../src/utils/promises.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAY;IAAzB;QAmBU,UAAK,GAAkC,EAAE,CAAA;IACnD,CAAC;IAnBC,MAAM,CAAI,QAAiB,EAAE,QAA0B;QACrD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QAEpC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,QAAQ,EAAE;iBACzB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;gBACV,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBACtB,OAAO,CAAC,CAAA;YACV,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;gBACX,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBACtB,MAAM,CAAC,CAAA;YACT,CAAC,CAAC,CAAA;QACN,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACxB,CAAC;CAGF;AApBD,oCAoBC;AAEM,KAAK,UAAU,MAAM,CAAC,EAAU;IACrC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AAC9C,CAAC;AAFD,wBAEC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type ThrottleArgsReducer<D> = (prevValue: D, newValue: D) => D;
|
|
2
|
+
export declare function lastValueReducer<D>(prevValue: D, newValue: D): D;
|
|
3
|
+
export declare function groupReducer<D>(prevValue: D[], newValue: D[]): D[];
|
|
4
|
+
export declare function throttle<D>(callback: (d: D) => void, delay: number, reducer: ThrottleArgsReducer<D>): (d: D) => void;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.throttle = exports.groupReducer = exports.lastValueReducer = void 0;
|
|
4
|
+
function lastValueReducer(prevValue, newValue) {
|
|
5
|
+
return newValue;
|
|
6
|
+
}
|
|
7
|
+
exports.lastValueReducer = lastValueReducer;
|
|
8
|
+
function groupReducer(prevValue, newValue) {
|
|
9
|
+
if (!Array.isArray(newValue))
|
|
10
|
+
throw new Error("groupReducer should only be used with topics that return arrays");
|
|
11
|
+
return prevValue ? [...prevValue, ...newValue] : newValue;
|
|
12
|
+
}
|
|
13
|
+
exports.groupReducer = groupReducer;
|
|
14
|
+
function throttle(callback, delay, reducer) {
|
|
15
|
+
let timer;
|
|
16
|
+
let lastExec = 0;
|
|
17
|
+
let reducedArg;
|
|
18
|
+
function wrapper(d) {
|
|
19
|
+
let self = this;
|
|
20
|
+
let elapsed = Date.now() - lastExec;
|
|
21
|
+
function exec() {
|
|
22
|
+
lastExec = Date.now();
|
|
23
|
+
callback.call(self, reducedArg);
|
|
24
|
+
reducedArg = undefined;
|
|
25
|
+
}
|
|
26
|
+
if (timer) {
|
|
27
|
+
clearTimeout(timer);
|
|
28
|
+
}
|
|
29
|
+
reducedArg = reducer(reducedArg, d);
|
|
30
|
+
if (elapsed > delay) {
|
|
31
|
+
exec();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
timer = setTimeout(exec, delay - elapsed);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return wrapper;
|
|
38
|
+
}
|
|
39
|
+
exports.throttle = throttle;
|
|
40
|
+
//# sourceMappingURL=throttle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.js","sourceRoot":"","sources":["../../src/utils/throttle.ts"],"names":[],"mappings":";;;AAEA,SAAgB,gBAAgB,CAAI,SAAY,EAAE,QAAW;IAC3D,OAAO,QAAQ,CAAA;AACjB,CAAC;AAFD,4CAEC;AAED,SAAgB,YAAY,CAAI,SAAc,EAAE,QAAa;IAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;IAEpF,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC3D,CAAC;AALD,oCAKC;AAED,SAAgB,QAAQ,CACtB,QAAwB,EACxB,KAAa,EACb,OAA+B;IAE/B,IAAI,KAAqB,CAAA;IACzB,IAAI,QAAQ,GAAG,CAAC,CAAA;IAEhB,IAAI,UAAe,CAAA;IAEnB,SAAS,OAAO,CAAY,CAAI;QAC9B,IAAI,IAAI,GAAG,IAAI,CAAA;QACf,IAAI,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAA;QAEnC,SAAS,IAAI;YACX,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACrB,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;YAC/B,UAAU,GAAG,SAAS,CAAA;QACxB,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;QAED,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAA;QAEnC,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;YACpB,IAAI,EAAE,CAAA;QACR,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC,CAAA;QAC3C,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAlCD,4BAkCC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ExtractPromiseResult<Type> = Type extends Promise<infer X> ? X : never;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":""}
|
package/example/api.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Services = {
|
|
2
|
+
todo: TodoService
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export type TodoService = {
|
|
6
|
+
addTodo(req: {text: string}, ctx?: any): Promise<void>
|
|
7
|
+
getTodos(ctx?: any): Promise<Todo[]>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type Todo = {
|
|
11
|
+
id: string
|
|
12
|
+
text: string
|
|
13
|
+
status: "open" | "closed"
|
|
14
|
+
}
|
|
15
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {Services} from "./api"
|
|
2
|
+
import {consumeServices} from "../src/client/index"
|
|
3
|
+
|
|
4
|
+
async function startClient() {
|
|
5
|
+
const {remote} = await consumeServices<Services>("http://127.0.0.1:8080/rpc")
|
|
6
|
+
|
|
7
|
+
console.log("Client created")
|
|
8
|
+
|
|
9
|
+
await remote.todo.getTodos.subscribe((todos) => {
|
|
10
|
+
console.log("Got todo items", todos)
|
|
11
|
+
}, null)
|
|
12
|
+
|
|
13
|
+
await remote.todo.addTodo({text: "Buy groceries"})
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
startClient()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {Todo, TodoService} from "./api"
|
|
2
|
+
import {publishServices} from "../src/server/index"
|
|
3
|
+
|
|
4
|
+
const storage: Todo[] = []
|
|
5
|
+
|
|
6
|
+
async function startServer() {
|
|
7
|
+
class TodoServiceImpl implements TodoService {
|
|
8
|
+
async addTodo({text}: {text: string}) {
|
|
9
|
+
storage.push({
|
|
10
|
+
id: "" + Math.random(),
|
|
11
|
+
text,
|
|
12
|
+
status: "open",
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
console.log("New todo item added")
|
|
16
|
+
services.todo.getTodos.trigger()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async getTodos() {
|
|
20
|
+
return storage
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const {services} = await publishServices(
|
|
25
|
+
{
|
|
26
|
+
todo: new TodoServiceImpl(),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
port: 8080,
|
|
30
|
+
path: "/rpc",
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
console.log("RPC Server started at http://localhost:8080/rpc")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
startServer()
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@push-rpc/next",
|
|
3
|
+
"version": "2.0.0-beta.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"prepublishOnly": "npm run build",
|
|
8
|
+
"build": "rm -fr dist && tsc -p tsconfig.cjs.json",
|
|
9
|
+
"test": "NODE_OPTIONS='--loader ts-node/esm' mocha tests/**/*.ts"
|
|
10
|
+
},
|
|
11
|
+
"repository": "https://github.com/vasyas/push-rpc.git",
|
|
12
|
+
"author": "vasyas <vasyl@stashuk.com>",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"fast-stringify": "^2.0.0",
|
|
19
|
+
"nanoid": "^3.3.7"
|
|
20
|
+
},
|
|
21
|
+
"optionalDependencies": {
|
|
22
|
+
"ws": "^8.16.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/chai": "^4.3.11",
|
|
26
|
+
"@types/mocha": "^10.0.6",
|
|
27
|
+
"@types/ws": "^8.5.10",
|
|
28
|
+
"chai": "^4.4.1",
|
|
29
|
+
"mocha": "^10.2.0",
|
|
30
|
+
"prettier": "^3.2.4",
|
|
31
|
+
"ts-node": "^10.9.2",
|
|
32
|
+
"typescript": "^5.3.3"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {CLIENT_ID_HEADER, RpcErrors} from "../rpc.js"
|
|
2
|
+
import {safeParseJson, safeStringify} from "../utils/json.js"
|
|
3
|
+
|
|
4
|
+
export class HttpClient {
|
|
5
|
+
constructor(
|
|
6
|
+
private url: string,
|
|
7
|
+
private clientId: string
|
|
8
|
+
) {}
|
|
9
|
+
|
|
10
|
+
call(itemName: string, params: unknown[], callTimeout: number): Promise<unknown> {
|
|
11
|
+
return this.httpRequest("POST", itemName, params, callTimeout)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async subscribe(itemName: string, params: unknown[], callTimeout: number) {
|
|
15
|
+
return this.httpRequest("PUT", itemName, params, callTimeout)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async unsubscribe(itemName: string, params: unknown[], callTimeout: number) {
|
|
19
|
+
await this.httpRequest("PATCH", itemName, params, callTimeout)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private getItemUrl(itemName: string): string {
|
|
23
|
+
return `${this.url}/${itemName}`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private async httpRequest(
|
|
27
|
+
method: "POST" | "PUT" | "PATCH",
|
|
28
|
+
itemName: string,
|
|
29
|
+
params: unknown[],
|
|
30
|
+
callTimeout: number
|
|
31
|
+
): Promise<unknown> {
|
|
32
|
+
try {
|
|
33
|
+
const response = await fetch(this.getItemUrl(itemName), {
|
|
34
|
+
method,
|
|
35
|
+
headers: {
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
[CLIENT_ID_HEADER]: this.clientId,
|
|
38
|
+
},
|
|
39
|
+
body: safeStringify(params),
|
|
40
|
+
signal: AbortSignal.timeout(callTimeout),
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
if (response.status == 204) {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const contentType = response.headers.get("content-type")
|
|
48
|
+
|
|
49
|
+
const text = await response.text()
|
|
50
|
+
|
|
51
|
+
const res =
|
|
52
|
+
contentType && contentType.includes("application/json") ? safeParseJson(text) : text
|
|
53
|
+
|
|
54
|
+
if (response.status < 200 || response.status >= 300) {
|
|
55
|
+
const error = new Error(response.statusText)
|
|
56
|
+
|
|
57
|
+
Object.assign(error, {code: response.status})
|
|
58
|
+
|
|
59
|
+
if (typeof res == "object") {
|
|
60
|
+
Object.assign(error, res)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throw error
|
|
64
|
+
} else {
|
|
65
|
+
return res
|
|
66
|
+
}
|
|
67
|
+
} catch (e: any) {
|
|
68
|
+
if (e.message == "fetch failed" && e.cause) {
|
|
69
|
+
e = e.cause
|
|
70
|
+
}
|
|
71
|
+
if (e.message?.toLowerCase()?.includes("timeout")) {
|
|
72
|
+
// NodeJS undici http client timeout
|
|
73
|
+
const error = new Error("Timeout")
|
|
74
|
+
Object.assign(error, {code: RpcErrors.Timeout})
|
|
75
|
+
throw error
|
|
76
|
+
}
|
|
77
|
+
throw e
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|