Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
System233 committed May 23, 2022
0 parents commit 9c78a77
Show file tree
Hide file tree
Showing 18 changed files with 1,062 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
examples
tests
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!--
Copyright (c) 2022 System233
This software is released under the MIT License.
https://opensource.org/licenses/MIT
-->

# TSON-RPC
Connect objects anywhere in pairs like quantum entanglement.

🧪 Experimental Technology.
❌ DO NOT USE IF YOU DON'T KNOW WHAT YOU'RE DOING.
❗It may expose your system to danger or attack.

## Example

```ts


class Test{
constructor(public name:string){}
call(obj:Test,...args:any){
console.log(this.name,'call()',obj, args);
obj.print(args)
}

print(args:[]){
console.log(this.name,'print', args);
console.log(this.name,'print length', args.length);
console.log(this.name,'print', args.map(x=>`${x}!`));
}
push(array:any[]){
console.log(this.name,'push() before',array)
array.push('pushed data');
console.log(this.name,'push() after',array)
console.log(this.name,'set',array)
console.log(this.name,'set length',array.length)
console.log(this.name,'set iter..',[...array])
console.log(this.name,'set iter',array[Symbol.iterator])
}
};
let client:WrappedHandler;

const test=new Test("[Remote]");

const erase=(data:any)=>JSON.parse(JSON.stringify(data));

const server=new WrappedHandler(req=>client.handle(erase(req)));
const id=server.new(test);



client=new WrappedHandler(req=>server.handle(erase(req)));
const remote=client.remote<Test>({id,type:typeOf(test)});


const localArray:string[]=[];

const local=new Test("[Local]");
remote.call(local,"local string");
remote.push(localArray);
console.log('localArray',localArray)

// [Remote] call() {} [ 'local string' ]
// [Local] print []
// [Local] print length 1
// [Local] print []
// [Remote] push() before []
// [Remote] push() after [] <--You can't see the remote object.
// [Remote] set []
// [Remote] set length 1
// [Remote] set iter.. [ 'pushed data' ]
// [Remote] set iter [Function (anonymous)]
// localArray [ 'pushed data' ]
```
22 changes: 22 additions & 0 deletions dist/cjs/bimap.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export declare class BiMap<K, T> {
map: Map<K, T>;
imap: Map<T, K>;
constructor(pairs?: [K, T][]);
has(key: K): boolean;
hasKey(key: K): boolean;
hasValue(value: T): boolean;
get(key: K): T;
getByKey(key: K): T;
getByValue(value: T): K;
set(key: K, value: T): void;
delete(key: K): boolean;
deleteBoth(key: K, value: T): boolean;
deleteKey(key: K): boolean;
deleteValue(value: T): boolean;
clear(): void;
forEach(callbackfn: (value: T, key: K, map: Map<K, T>) => void, thisArg?: any): void;
entries(): IterableIterator<[K, T]>;
keys(): IterableIterator<K>;
values(): IterableIterator<T>;
get size(): number;
}
74 changes: 74 additions & 0 deletions dist/cjs/bimap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"use strict";
// Copyright (c) 2022 System233
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
Object.defineProperty(exports, "__esModule", { value: true });
exports.BiMap = void 0;
class BiMap {
map = new Map;
imap = new Map;
constructor(pairs) {
if (pairs != null) {
pairs.forEach(([key, value]) => this.set(key, value));
}
}
has(key) {
return this.hasKey(key);
}
hasKey(key) {
return this.map.has(key);
}
hasValue(value) {
return this.imap.has(value);
}
get(key) {
return this.getByKey(key);
}
getByKey(key) {
return this.map.get(key);
}
getByValue(value) {
return this.imap.get(value);
}
set(key, value) {
this.map.set(key, value);
this.imap.set(value, key);
}
delete(key) {
return this.deleteKey(key);
}
deleteBoth(key, value) {
if (this.hasKey(key) && this.hasValue(value)) {
return this.map.delete(key) && this.imap.delete(value);
}
return true;
}
deleteKey(key) {
return this.deleteBoth(key, this.getByKey(key));
}
deleteValue(value) {
return this.deleteBoth(this.getByValue(value), value);
}
clear() {
this.map.clear();
this.imap.clear();
}
forEach(callbackfn, thisArg) {
return this.map.forEach(callbackfn, thisArg);
}
entries() {
return this.map.entries();
}
keys() {
return this.map.keys();
}
values() {
return this.map.values();
}
get size() {
return this.map.size;
}
}
exports.BiMap = BiMap;
;
53 changes: 53 additions & 0 deletions dist/cjs/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { TSON, TSONData } from "tson-serializer";
import { BiMap } from "./bimap";
export declare type TypeOf = "array" | "object" | "function" | null;
export declare class Handler implements ProxyHandler<any> {
apply(target: Function, thisArg: any, argArray: any[]): any;
construct(target: any, argArray: any[], newTarget: Function): object;
defineProperty(target: any, p: string | symbol, attributes: PropertyDescriptor): boolean;
deleteProperty(target: any, p: string | symbol): boolean;
get(target: any, p: string | symbol, receiver: any): any;
getOwnPropertyDescriptor(target: any, p: string | symbol): PropertyDescriptor | undefined;
getPrototypeOf(target: any): object | null;
has(target: any, p: string | symbol): boolean;
isExtensible(target: any): boolean;
ownKeys(target: any): ArrayLike<string | symbol>;
preventExtensions(target: any): boolean;
set(target: any, p: string | symbol, value: any, receiver: any): boolean;
setPrototypeOf(target: any, v: object | null): boolean;
}
export interface WrappedObjectData {
id: string;
type: TypeOf;
}
export declare type ParametersSkipFirst<T extends (first: any, ...args: any) => any> = T extends (first: any, ...args: infer P) => any ? P : never;
export declare class WrappedObject<T extends object> implements ProxyHandler<T> {
handler: WrappedHandler;
data: WrappedObjectData;
constructor(handler: WrappedHandler, data: WrappedObjectData);
call<T extends keyof Handler>(method: T, args: ParametersSkipFirst<Handler[T]>): ReturnType<Handler[T]>;
get(target: any, p: keyof Handler, receiver: any): any;
has(target: any, p: string | symbol): boolean;
}
export interface WrappedRequest {
target: WrappedObjectData;
method: keyof Handler;
data: TSONData[];
}
export declare type RequestHandler = (request: WrappedRequest) => TSONData | TSONData[];
export declare const typeOf: (value: any) => TypeOf;
export declare class WrappedHandler {
request: RequestHandler;
map: BiMap<string, object>;
tson: TSON;
handler: Handler;
constructor(request: RequestHandler);
id(value: object): string;
dump(obj: object): WrappedObjectData;
load<T extends object>(data: WrappedObjectData): T;
new(value: object, id?: string): string;
remote<T extends object>(data: WrappedObjectData): T;
call<T extends keyof Handler>(target: WrappedObjectData, method: T, params: ParametersSkipFirst<Handler[T]>): ReturnType<Handler[T]>;
handle<T extends keyof Handler>(request: WrappedRequest): TSONData<any, any>;
delete(id: string): boolean;
}
142 changes: 142 additions & 0 deletions dist/cjs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
"use strict";
// Copyright (c) 2022 System233
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
Object.defineProperty(exports, "__esModule", { value: true });
exports.WrappedHandler = exports.typeOf = exports.WrappedObject = exports.Handler = void 0;
const tson_serializer_1 = require("tson-serializer");
const uuid_1 = require("uuid");
const bimap_1 = require("./bimap");
class Handler {
apply(target, thisArg, argArray) {
return target.apply(thisArg, argArray);
}
construct(target, argArray, newTarget) {
return new target(...argArray);
}
defineProperty(target, p, attributes) {
Object.defineProperty(target, p, attributes);
return true;
}
deleteProperty(target, p) {
return delete target[p];
}
get(target, p, receiver) {
return target[p];
}
getOwnPropertyDescriptor(target, p) {
return Object.getOwnPropertyDescriptor(target, p);
}
getPrototypeOf(target) {
return Object.getPrototypeOf(target);
}
has(target, p) {
return p in target;
}
isExtensible(target) {
return Object.isExtensible(target);
}
ownKeys(target) {
return Object.keys(target);
}
preventExtensions(target) {
return Object.isFrozen(target);
}
set(target, p, value, receiver) {
target[p] = value;
return true;
}
setPrototypeOf(target, v) {
Object.setPrototypeOf(target, v);
return true;
}
}
exports.Handler = Handler;
;
class WrappedObject {
handler;
data;
constructor(handler, data) {
this.handler = handler;
this.data = data;
const target = data.type == 'function' ? function () { } : data.type == 'array' ? [] : {};
return new Proxy(target, new Proxy({}, this));
}
call(method, args) {
return this.handler.call(this.data, method, args);
}
get(target, p, receiver) {
if (p in target) {
return target[p];
}
const handler = (_, ...args) => this.call(p, args);
target[p] = handler;
return handler;
}
has(target, p) {
return p in target;
}
}
exports.WrappedObject = WrappedObject;
const typeOf = (value) => value != null ? Array.isArray(value) ? 'array' : typeof value == 'object' ? 'object' : typeof value == 'function' ? 'function' : null : null;
exports.typeOf = typeOf;
class WrappedHandler {
request;
map = new bimap_1.BiMap;
tson = new tson_serializer_1.TSON;
handler = new Handler;
constructor(request) {
this.request = request;
this.tson.register('Wrapped', (data) => this.load(data), (obj) => this.dump(obj), (value) => !!(0, exports.typeOf)(value));
}
id(value) {
if (this.map.hasValue(value)) {
return this.map.getByValue(value);
}
return this.new(value);
}
dump(obj) {
const type = (0, exports.typeOf)(obj);
let id = this.map.getByValue(obj);
if (id == null) {
id = (0, uuid_1.v4)();
this.map.set(id, obj);
}
return {
id,
type
};
}
load(data) {
if (this.map.has(data.id)) {
return this.map.get(data.id);
}
return this.remote(data);
}
new(value, id) {
id = id || (0, uuid_1.v4)();
this.map.set(id, value);
return id;
}
remote(data) {
const obj = new WrappedObject(this, data);
this.new(obj, data.id);
return obj;
}
call(target, method, params) {
const data = params.map(x => this.tson.forward(x));
const result = this.request({ target, method, data });
return this.tson.backward(result);
}
handle(request) {
const { target, method, data } = request;
const args = this.tson.backward(data);
const result = this.handler[method].call(this.handler, this.load(target), ...args);
return this.tson.forward(result);
}
delete(id) {
return this.map.delete(id);
}
}
exports.WrappedHandler = WrappedHandler;
Loading

0 comments on commit 9c78a77

Please sign in to comment.