2
0
mirror of https://github.com/esiur/esiur-js.git synced 2025-05-06 12:32:58 +00:00

Template 2.0

This commit is contained in:
Ahmed Zamil 2021-05-26 08:54:29 +03:00
parent f5365adec3
commit 2bf5605ef1
21 changed files with 1963 additions and 2752 deletions

View File

@ -1,11 +1,10 @@
{
"presets": [
[
"@babel/preset-env", { "useBuiltIns": "entry" }
"@babel/preset-env"
]
],
"plugins": [
["@babel/transform-runtime"],
["@babel/plugin-proposal-class-properties", { "loose": true }]
]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
import DistributedConnection from "../../src/Net/IIP/DistributedConnection.js";
import Warehouse from "../../src/Resource/Warehouse.js";
import { createRequire } from 'module'
@ -10,6 +9,7 @@ import MemoryStore from "../../src/Stores/MemoryStore.js";
import DC from "../../src/Data/DataConverter.js";
import IResource from "../../src/Resource/IResource.js";
import Structure from "../../src/Data/Structure.js";
import DataType from "../../src/Data/DataType.js";
const require = createRequire(import.meta.url);
@ -32,12 +32,13 @@ var server;
class MyChat extends IResource {
// void (string, string)->void
static get template() {
return {
namespace: "Chat",
properties: [{name: "title"}, { name: "messages" }, {name: "users"}],
events: [{ name: "message" }, { name: "voice", listenable: true }, {name: "login"}, {name: "logout"}],
functions: [{ name: "send" }]
properties: [["title", DataType.String], ["messages", DataType.StructureArray], ["users", DataType.StringArray]],
events: [["message", DataType.Structure], ["voice", 0, {listenable: true }], ["login"], ["logout"]],
functions: [[ "send", {msg: DataType.String} ]]
};
}

View File

@ -1,4 +1,3 @@
import DistributedConnection from "../../src/Net/IIP/DistributedConnection.js";
import Warehouse from "../../src/Resource/Warehouse.js";
import { createRequire } from 'module'

1918
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "esiur",
"version": "1.6.1",
"version": "1.6.8",
"description": "Distributed Object Framework",
"main": "esiur.js",
"type": "module",
@ -13,25 +13,22 @@
"type": "git",
"url": "git+https://github.com/esiur/esiur-js.git"
},
"author": "Ahmed Zamil",
"author": "Ahmed Kh. Zamil",
"license": "MIT",
"bugs": {
"url": "https://github.com/esiur/esiur-js/issues"
},
"homepage": "https://github.com/esiur/esiur-js#readme",
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.13.10",
"mongodb": "^3.6.6",
"ws": "^6.2.1"
},
"devDependencies": {
"@babel/cli": "^7.13.14",
"@babel/core": "^7.13.15",
"@babel/plugin-transform-runtime": "^7.13.15",
"@babel/cli": "^7.13.16",
"@babel/core": "^7.13.16",
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/preset-env": "^7.13.15",
"babel-cli": "^6.0.0",
"babelify": "^10.0.0",
"browserify": "^16.5.2"
"browserify": "^17.0.0"
},
"dependencies": {
"mongodb": "^3.6.6",
"ws": "^7.4.5"
}
}

View File

@ -148,6 +148,8 @@ export default class DistributedConnection extends IStore {
var packet = new IIPPacket();
var rt = packet.parse(msg, offset, ends);
if (rt <= 0) {
data.holdFor(msg, offset, ends - offset, -rt);
return ends;
@ -238,6 +240,10 @@ export default class DistributedConnection extends IStore {
this.IIPRequestInquireResourceHistory(packet.callbackId, packet.resourceId, packet.fromDate, packet.toDate);
break;
case IIPPacketAction.LinkTemplates:
this.IIPRequestLinkTemplates(packet.callbackId, packet.resourceLink);
break;
// Invoke
case IIPPacketAction.InvokeFunctionArrayArguments:
this.IIPRequestInvokeFunctionArrayArguments(packet.callbackId, packet.resourceId, packet.methodIndex, packet.content);
@ -262,12 +268,7 @@ export default class DistributedConnection extends IStore {
case IIPPacketAction.SetProperty:
this.IIPRequestSetProperty(packet.callbackId, packet.resourceId, packet.methodIndex, packet.content);
break;
case IIPPacketAction.ResourceHistory:
this.IIPRequestInquireResourceHistory(packet.callbackId, packet.resourceId, packet.fromDate, packet.toDate);
break;
case IIPPacketAction.QueryLink:
this.IIPRequestQueryResources(packet.callbackId, packet.resourceLink);
break;
// Attribute
case IIPPacketAction.GetAllAttributes:
@ -321,6 +322,7 @@ export default class DistributedConnection extends IStore {
case IIPPacketAction.ResourceChildren:
case IIPPacketAction.ResourceParents:
case IIPPacketAction.ResourceHistory:
case IIPPacketAction.LinkTemplates:
this.IIPReply(packet.callbackId, packet.content);
break;
@ -463,7 +465,8 @@ export default class DistributedConnection extends IStore {
else
{
//Console.WriteLine("User not found");
this.sendParams().addUint8(0xc0)
this.sendParams()
.addUint8(0xc0)
.addUint8(ExceptionCode.UserOrTokenNotFound)
.addUint16(15)
.addString("Token not found")
@ -477,13 +480,53 @@ export default class DistributedConnection extends IStore {
var errMsg = DC.stringToBytes(ex.message);
this.sendParams().addUint8(0xc0)
this.sendParams()
.addUint8(0xc0)
.addUint8(ExceptionCode.GeneralFailure)
.addUint16(errMsg.length)
.addUint8Array(errMsg)
.done();
}
}
else if (authPacket.remoteMethod == AuthenticationMethod.None
&& authPacket.localMethod == AuthenticationMethod.None)
{
try
{
// Check if guests are allowed
if (this.server?.membership.guestsAllowed)
{
this.session.remoteAuthentication.username = "g-" + Math.random().toString(36).substring(10);
this.session.remoteAuthentication.domain = authPacket.domain;
this.readyToEstablish = true;
this.sendParams()
.addUint8(0x80)
.done();
}
else
{
this.sendParams()
.addUInt8(0xc0)
.addUint8(ExceptionCode.AccessDenied)
.addUint16(18)
.addString("Guests not allowed")
.done();
}
}
catch (ex)
{
var errMsg = DC.stringToBytes(ex.message);
this.sendParams()
.addUInt8(0xc0)
.addUint8(ExceptionCode.GeneralFailure)
.addUint16(errMsg.length)
.addUint8Array(errMsg)
.done();
}
}
}
else if (authPacket.command == IIPAuthPacketCommand.Action)
{
@ -553,7 +596,8 @@ export default class DistributedConnection extends IStore {
var errMsg = DC.stringToBytes(ex.message);
this.sendParams().addUint8(0xc0)
this.sendParams()
.addUint8(0xc0)
.addUint8(ExceptionCode.GeneralFailure)
.addUint16(errMsg.Length)
.addUint8Array(errMsg)
@ -573,7 +617,7 @@ export default class DistributedConnection extends IStore {
if (this.instance == null)
{
Warehouse.put(this, this.localUsername, null, this.server).then(x =>
Warehouse.put(this.localUsername, this, null, this.server).then(x =>
{
this.ready = true;
@ -594,6 +638,17 @@ export default class DistributedConnection extends IStore {
this.server?.membership.login(this.session);
}
}
else
{
this.sendParams()
.addUint8(0xc0)
.addUint8(ExceptionCode.GeneralFailure)
.addUint16(9)
.addString("Not ready")
.done();
// this.close();
}
}
}
}
@ -601,6 +656,18 @@ export default class DistributedConnection extends IStore {
{
if (authPacket.command == IIPAuthPacketCommand.Acknowledge)
{
if (authPacket.remoteMethod == AuthenticationMethod.None)
{
// send establish
this.sendParams()
.addUint8(0x20)
.addUint16(0)
.done();
}
else if (authPacket.remoteMethod == AuthenticationMethod.Credentials
|| authPacket.remoteMethod == AuthenticationMethod.Token)
{
this.remoteNonce = authPacket.remoteNonce;
// send our hash
@ -614,6 +681,7 @@ export default class DistributedConnection extends IStore {
.addUint8(0)
.addUint8Array(localHash)
.done();
}
}
else if (authPacket.command == IIPAuthPacketCommand.Action)
@ -657,7 +725,7 @@ export default class DistributedConnection extends IStore {
// put it in the warehouse
if (this.instance == null)
{
Warehouse.put(this, this.localUsername, null, this.server).then(x =>
Warehouse.put(this.localUsername, this, null, this.server).then(x =>
{
this.openReply?.trigger(true);
this._emit("ready", this);
@ -900,11 +968,17 @@ export default class DistributedConnection extends IStore {
}
trigger(trigger) {
console.log(this, trigger);
if (trigger == ResourceTrigger.Open) {
if (this.server != null)
return new AsyncReply(true);
var { domain = null,
secure = false,
username = "guest",
password = "",
username = null,
password = null,
checkInterval = 30,
connectionTimeout = 600,
revivingTime = 120,
@ -924,15 +998,20 @@ export default class DistributedConnection extends IStore {
var address = host[0];
var port = parseInt(host[1]);
if (token != null)
if (username != null
&& password != null)
{
var tk = DC.stringToBytes(token);
return this.connect(secure, AuthenticationMethod.token, address, port, null, tokenIndex, tk, domain);
var pw = DC.stringToBytes(password);
return this.connect(AuthenticationMethod.Credentials, null, address, port, username, null, pw, domain, secure);
}
else if (token != null)
{
var tk = token instanceof Uint8Array ? token : DC.stringToBytes(token);
return this.connect(AuthenticationMethod.Token, null, address, port, null, tokenIndex, tk, domain, secure);
}
else
{
var pw = DC.stringToBytes(password);
return this.connect(secure, AuthenticationMethod.credentials, address, port, username, null, pw, domain);
return this.connect(AuthenticationMethod.None, null, address, port, null, 0, null, domain);
}
}
@ -1016,6 +1095,41 @@ export default class DistributedConnection extends IStore {
}
_declare() {
// declare (Credentials -> No Auth, No Enctypt)
var dmn = DC.stringToBytes(this.session.localAuthentication.domain);
if (this.session.localAuthentication.method == AuthenticationMethod.Credentials) {
var un = DC.stringToBytes(this.session.localAuthentication.username);
this.sendParams()
.addUint8(0x60)
.addUint8(dmn.length)
.addUint8Array(dmn)
.addUint8Array(this.localNonce)
.addUint8(un.length)
.addUint8Array(un)
.done();
}
else if (this.session.localAuthentication.method == AuthenticationMethod.Token) {
this.sendParams()
.addUint8(0x70)
.addUint8(dmn.length)
.addUint8Array(dmn)
.addUint8Array(this.localNonce)
.addUint64(this.session.localAuthentication.tokenIndex)
.done();
}
else if (this.session.localAuthentication.method == AuthenticationMethod.None) {
this.sendParams()
.addUint8(0x40)
.addUint8(dmn.length)
.addUint8Array(dmn)
.done();
}
}
assign(socket)
{
this.socket = socket;
@ -1028,77 +1142,10 @@ export default class DistributedConnection extends IStore {
if (socket.state == SocketState.Established &&
this.session.localAuthentication.type == AuthenticationType.Client)
{
// declare (Credentials -> No Auth, No Enctypt)
var un = DC.stringToBytes(this.session.localAuthentication.username);
var dmn = DC.stringToBytes(this.session.localAuthentication.domain);// domain);
this.sendParams()
.addUint8(0x60)
.addUint8(dmn.length)
.addUint8Array(dmn)
.addUint8Array(this.localNonce)
.addUint8(un.length)
.addUint8Array(un)
.done();
}
this._declare();
}
assign_old(socket)
{
socket.networkBuffer = new NetworkBuffer();
this.socket = socket;
//this.debug = debug;
this.totalReceived = 0;
this.totalSent = 0;
this.lastAction = Date.now();
this.sendBuffer = new NetworkBuffer();
var self = this;
socket.onopen = function () {
if (self.session.localAuthentication.type == AuthenticationType.Client)
{
var un = DC.stringToBytes(self.session.localAuthentication.username);
var dmn = DC.stringToBytes(self.session.localAuthentication.domain);
var bl = BL();
bl.addUint8(0x60).addUint8(dmn.length).addUint8Array(dmn).addUint8Array(self.localNonce).addUint8(un.length).addUint8Array(un);
self.sendAll(bl.toArray());
}
};
socket.onmessage = function (msg) {
//console.log("Rec", msg.data.byteLength);
this.networkBuffer.writeAll(msg.data);
self.lastAction = new Date();
self.hold();
while (this.networkBuffer.available > 0 && !this.networkBuffer.protected) {
self.receive(this.networkBuffer);
}
self.unhold();
};
socket.onclose = function (event) {
if (this.connection.openReply) {
this.connection.openReply.triggerError(0, 0, "Host not reachable");
this.connection.openReply = null;
}
self.close(event);
};
}
_unsubscribeAll()
{
@ -1153,21 +1200,7 @@ export default class DistributedConnection extends IStore {
networkConnect(socket)
{
if (this.session.localAuthentication.Type == AuthenticationType.Client)
{
// declare (Credentials -> No Auth, No Enctypt)
var un = DC.stringToBytes(this.session.localAuthentication.username);
var dmn = DC.stringToBytes(this.session.localAuthentication.domain);// domain);
this.sendParams()
.addUint8(0x60)
.addUint8(dmn.Length)
.addUint8Array(dmn)
.addUint8Array(this.localNonce)
.addUint8(un.Length)
.addUint8Array(un)
.done();
}
this._declare();
this._emit("connect", this);
}
@ -1194,6 +1227,7 @@ export default class DistributedConnection extends IStore {
{
while (buffer.available > 0 && !buffer.protected)
{
//console.log("RX", buffer.length );
this._dataReceived(buffer);
}
}
@ -1673,7 +1707,7 @@ export default class DistributedConnection extends IStore {
var resource = new (Function.prototype.bind.apply(type, values));
Warehouse.put(resource, name, store, parent).then(function(ok){
Warehouse.put(name, resource, store, parent).then(function(ok){
self.sendReply(IIPPacketAction.CreateResource, callback)
.addUint32(resource.Instance.Id)
.done();
@ -1708,6 +1742,50 @@ export default class DistributedConnection extends IStore {
});
}
IIPRequestLinkTemplates(callback, resourceLink)
{
var queryCallback = (r) =>
{
if (r == null)
this.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
else
{
var list = r.filter(x => x.instance.applicable(this.session, ActionType.ViewTemplate, null) != Ruling.Denied);
if (list.length == 0)
this.sendError(ErrorType.Management, callback, ExceptionCode.ResourceNotFound);
else
{
// get all templates related to this resource
var msg = new BinaryList();
var templates = [];
for (var i = 0; i < list.length; i++)
templates = templates
.concat(ResourceTemplate.getDependencies(list[i].instance.template)
.filter(x => !templates.includes(x)));
for(var i = 0; i < templates.length; i++) {
msg.addInt32(templates[i].content.length)
.addUint8Array(templates[i].content);
}
// send
this.sendReply(IIPPacketAction.LinkTemplates, callback)
.addInt32(msg.length)
.addUint8Array(msg.toArray())
.done();
}
}
};
if (this.server?.entryPoint != null)
this.server.entryPoint.query(resourceLink, this).then(queryCallback);
else
Warehouse.query(resourceLink).then(queryCallback);
}
IIPRequestTemplateFromClassName(callback, className) {
var self = this;
@ -1727,7 +1805,8 @@ export default class DistributedConnection extends IStore {
IIPRequestTemplateFromClassId(callback, classId) {
var self = this;
Warehouse.getTemplateByClassId(classId).then(function (t) {
var t = Warehouse.getTemplateByClassId(classId);
if (t != null)
self.sendReply(IIPPacketAction.TemplateFromClassId, callback)
.addUint32(t.content.length)
@ -1737,7 +1816,6 @@ export default class DistributedConnection extends IStore {
// reply failed
self.sendError(ErrorType.Management, callback, ExceptionCode.TemplateNotFound);
}
});
}
IIPRequestTemplateFromResourceId(callback, resourceId) {
@ -2367,6 +2445,42 @@ export default class DistributedConnection extends IStore {
//return new AsyncReply(null);
}
getLinkTemplates(link)
{
var reply = new AsyncReply();
var l = DC.stringToBytes(link);
this.sendRequest(IIPPacketAction.LinkTemplates)
.addUint16(l.length)
.addUint8Array(l)
.done()
.then((rt) =>
{
var templates = [];
// parse templates
var data = rt[0];
//var offset = 0;
for (var offset = 0; offset < data.length;)
{
var cs = data.getUint32(offset);
offset += 4;
templates.push(ResourceTemplate.parse(data, offset, cs));
offset += cs;
}
reply.trigger(templates);
}).error((ex) =>
{
reply.triggerError(ex);
});
return reply;
}
// Get a resource from the other end
fetch(id) {
@ -2396,14 +2510,27 @@ export default class DistributedConnection extends IStore {
.done()
.then(function (rt) {
let dr = resource || new DistributedResource(self, id, rt[1], rt[2]);
var dr;
if (resource == null)
{
var template = Warehouse.getTemplateByClassId(rt[0]);
if (template?.resourceType != null)
dr = new template.getDependencies(self, id, rt[1], rt[2]);
else
dr = new DistributedResource(self, id, rt[1], rt[2]);
}
else
dr = resource;
//let dr = resource || new DistributedResource(self, id, rt[1], rt[2]);
self.getTemplate(rt[0]).then(function (tmp) {
// ClassId, ResourceAge, ResourceLink, Content
if (resource == null)
{
let wp = Warehouse.put(dr, id.toString(), self, null, tmp).then(function(ok){
let wp = Warehouse.put(id.toString(), dr, self, null, tmp).then(function(ok){
Codec.parsePropertyValueArray(rt[3], 0, rt[3].length, self).then(function (ar) {
dr._attach(ar);
self.resourceRequests.remove(id);

View File

@ -199,11 +199,15 @@ export default class IIPAuthPacket
this.localMethod = (data.getUint8(offset) >> 2) & 0x3;
var encrypt = ((data.getUint8(offset++) & 0x2) == 0x2);
if (this.notEnough(offset, ends, 1))
return -this.dataLengthNeeded;
if (this.remoteMethod == AuthenticationMethod.Credentials
if (this.remoteMethod == AuthenticationMethod.None)
{
if (this.localMethod == AuthenticationMethod.None)
{
// do nothing
}
}
else if (this.remoteMethod == AuthenticationMethod.Credentials
|| this.remoteMethod == AuthenticationMethod.Token)
{
if (this.localMethod == AuthenticationMethod.None)

View File

@ -331,7 +331,8 @@ export default class IIPPacket
this.resourceId = data.getUint32(offset);
offset += 4;
}
else if (this.action == IIPPacketAction.QueryLink)
else if (this.action == IIPPacketAction.QueryLink
|| this.action == IIPPacketAction.LinkTemplates)
{
if (this.notEnough(offset, ends, 2))
return -this.dataLengthNeeded;
@ -537,6 +538,8 @@ export default class IIPPacket
|| this.action == IIPPacketAction.ResourceChildren
|| this.action == IIPPacketAction.ResourceParents
|| this.action == IIPPacketAction.ResourceHistory
|| this.action == IIPPacketAction.LinkTemplates
// Attribute
|| this.action == IIPPacketAction.GetAllAttributes
|| this.action == IIPPacketAction.GetAttributes)

View File

@ -18,6 +18,7 @@ export default // const IIPPacketAction =
ResourceHistory: 12,
ResourceChildren: 13,
ResourceParents: 14,
LinkTemplates: 15,
// Request Invoke
InvokeFunctionArrayArguments: 16,

View File

@ -0,0 +1,32 @@
import DC from "../../Data/DataConverter.js";
import BinaryList from "../../Data/BinaryList.js";
import TemplateDataType from "./TemplateDataType.js";
export default class ArgumentTemplate
{
static parse(data, offset)
{
var cs = data[offset++];
var name = data.getString(offset, cs);
offset += cs;
var {size, value} = TemplateDataType.parse(data, offset);
return {size: cs + 1 + size, value: new ArgumentTemplate(name, value)};
}
constructor(name, type){
this.name = name;
this.type = type;
}
compose()
{
var name = DC.stringToBytes(this.name);
return new BinaryList()
.addUint8(name.length)
.addUint8Array(name)
.addUint8Array(this.type.compose())
.toArray();
}
}

View File

@ -49,6 +49,7 @@ export default class EventTemplate extends MemberTemplate
return rt.addUint8(this.listenable ? 0x58 : 0x50)
.addUint8(name.length)
.addUint8Array(name)
.addUint8Array(this.argumentType.compose())
.addUint32(exp.length)
.addUint8Array(exp)
.toArray();
@ -57,7 +58,7 @@ export default class EventTemplate extends MemberTemplate
return rt.addUint8(this.listenable ? 0x48 : 0x40)
.addUint8(name.length)
.addUint8Array(name)
.addUint8Array(this.argumentType.compose())
.toArray();
}
}

View File

@ -33,23 +33,27 @@ import MemberType from './MemberType.js';
export default class FunctionTemplate extends MemberTemplate {
compose() {
var name = super.compose();
var rt = BL();
if (this.expansion != null) {
var exp = DC.stringToBytes(this.expansion);
return rt.addUint8(0x10 | (this.isVoid ? 0x8 : 0x0))
var bl = BL()
.addUint8(name.length)
.addUint8Array(name)
.addUint32(exp.length)
.addUint8Array(exp)
.toArray();
.addUint8Array(this.returnType.compose())
.addUint8(this.arguments.length);
for (var i = 0; i < this.arguments.length; i++)
bl.addUint8Array(this.arguments[i].compose());
if (this.expansion != null)
{
var exp = DC.stringToBytes(this.expansion);
bl.addInt32(exp.length)
.addUint8Array(exp);
bl.insertUint8(0, 0x10);
}
else
return rt.addUint8(this.isVoid ? 0x8 : 0x0)
.addUint8(name.length)
.addUint8Array(name)
.toArray();
bl.addUint8(0x0, 0);
return bl.toArray();
}
constructor() {

View File

@ -58,6 +58,7 @@ export default class PropertyTemplate extends MemberTemplate
return rt.addUint8(0x38 | pv)
.addUint8(name.length)
.addUint8Array(name)
.addUint8Array(this.valueType.compose())
.addUint32(wexp.length)
.addUint8Array(wexp)
.addUint32(rexp.length)
@ -70,6 +71,7 @@ export default class PropertyTemplate extends MemberTemplate
return rt.addUint8(0x30 | pv)
.addUint8(name.length)
.addUint8Array(name)
.addUint8Array(this.valueType.compose())
.addUint32(wexp.length)
.addUint8Array(wexp)
.toArray();
@ -80,6 +82,7 @@ export default class PropertyTemplate extends MemberTemplate
return rt.addUint8(0x28 | pv)
.addUint8(name.length)
.addUint8Array(name)
.addUint8Array(this.valueType.compose())
.addUint32(rexp.length)
.addUint8Array(rexp)
.toArray();
@ -88,6 +91,7 @@ export default class PropertyTemplate extends MemberTemplate
return rt.addUint8(0x20 | pv)
.addUint8(name.length)
.addUint8Array(name)
.addUint8Array(this.valueType.compose())
.toArray();
}
}

View File

@ -27,6 +27,8 @@ import PropertyTemplate from './PropertyTemplate.js';
import EventTemplate from './EventTemplate.js';
import SHA256 from '../../Security/Integrity/SHA256.js';
import {DC, BL} from '../../Data/DataConverter.js';
import ArgumentTemplate from './ArgumentTemplate.js';
import TemplateDataType from "./TemplateDataType.js";
export default class ResourceTemplate {
@ -88,8 +90,120 @@ export default class ResourceTemplate {
}
*/
static getTypeGuid(type) {
return getTypeGuidByName(type.template.namespace + "." + type.prototype.constructor.name);
}
static getTypeGuidByName(typeName)
{
return SHA256.compute(DC.stringToBytes(this.className)).getGuid(0);
}
static getDependencies(template)
{
var list = [];
list.add(template);
var getDependenciesFunc = null;
getDependenciesFunc = (tmp, bag) =>
{
if (template.resourceType == null)
return;
// functions
for(var i = 0; i < tmp.functions.length; i++)
{
f = tmp.functions[i];
var frtt = Warehouse.getTemplateByType(f.methodInfo.returnType);
if (frtt != null)
{
if (!bag.includes(frtt))
{
list.push(frtt);
getDependenciesFunc(frtt, bag);
}
}
var args = f.methodInfo.parameters;
for(var i = 0; i < args.length - 1; i++)
{
var fpt = Warehouse.getTemplateByType(args[i].parameterType);
if (fpt != null)
{
if (!bag.includes(fpt))
{
bag.push(fpt);
getDependenciesFunc(fpt, bag);
}
}
}
// skip DistributedConnection argument
if (args.length > 0)
{
var last = args[args.length - 1];
if (last.parameterType == DistributedConnection)
{
var fpt = Warehouse.getTemplateByType(last.parameterType);
if (fpt != null)
{
if (!bag.includes(fpt))
{
bag.push(fpt);
getDependenciesFunc(fpt, bag);
}
}
}
}
}
// properties
for (var i = 0; i < tmp.properties.length; i++)
{
var p = tmp.properties[i];
var pt = Warehouse.getTemplateByType(p.propertyInfo.propertyType);
if (pt != null)
{
if (!bag.includes(pt))
{
bag.push(pt);
getDependenciesFunc(pt, bag);
}
}
}
// events
for(var i = 0; i < tmp.events.length; i++)
{
var e = tmp.events[i];
var et = Warehouse.getTemplateByType(e.eventInfo.eventHandlerType);
if (et != null)
{
if (!bag.includes(et))
{
bag.Add(et);
getDependenciesFunc(et, bag);
}
}
}
};
getDependenciesFunc(template, list);
return list;
}
constructor(type) {
//@TODO: check if the type is IResource
this.properties = [];
this.events = [];
@ -99,6 +213,8 @@ export default class ResourceTemplate {
if (type === undefined)
return;
this.resourceType = type;
var template = type.template;
// set guid
@ -108,31 +224,54 @@ export default class ResourceTemplate {
//byte currentIndex = 0;
for (var i = 0; i < template.properties?.length; i++) {
if (template.properties != null)
for (var i = 0; i < template.properties.length; i++) {
//[name, type, {read: comment, write: comment, recordable: }]
var pi = template.properties[i];
var pt = new PropertyTemplate();
pt.name = template.properties[i].name;
pt.name = pi[0];
pt.index = i;
pt.readExpansion = template.properties[i].read;
pt.writeExpansion = template.properties[i].write;
pt.recordable = template.properties[i].recordable;
pt.valueType = TemplateDataType.fromType(pi[1]),
pt.readExpansion = pi[2]?.read;
pt.writeExpansion = pi[2]?.write;
pt.recordable = pi[2]?.recordable;
pt.propertyInfo = pi;
this.properties.push(pt);
}
for (var i = 0; i < template.events?.length; i++) {
if (template.events != null)
for (var i = 0; i < template.events.length; i++) {
// [name, type, {listenable: true/false, help: ""}]
var ei = template.events[i];
var et = new EventTemplate();
et.name = template.events[i].name;
et.name = ei[0];
et.index = i;
et.expansion = template.events[i].help;
et.listenable = template.events[i].listenable;
et.argumentType = TemplateDataType.fromType(ei[1]),
et.expansion = ei[2]?.help;
et.listenable = ei[2]?.listenable;
et.eventInfo = ei;
this.events.push(et);
}
for (var i = 0; i < template.functions?.length; i++) {
if (template.functions != null)
for (var i = 0; i < template.functions.length; i++) {
var fi = template.functions[i];
// [name, {param1: type, param2: int}, returnType, "Description"]
var ft = new FunctionTemplate();
ft.name = template.functions[i].name;
ft.name = fi[0];
ft.index = i;
ft.isVoid = template.functions[i].void;
ft.expansion = template.functions[i].help;
ft.returnType = TemplateDataType.fromType(fi[2]);
ft.expansion = fi[3];
ft.arguments = [];
for(var arg in fi[1])
ft.arguments.push(new ArgumentTemplate(arg, TemplateDataType.fromType(fi[1][arg])))
ft.methodInfo = fi;
this.functions.push(ft);
}
@ -180,6 +319,14 @@ export default class ResourceTemplate {
return result;
}
static _getParamNames(func) {
var fnStr = func.toString().replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '');
var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(/([^\s,]+)/g);
if(result === null)
result = [];
return result;
}
static parse(data, offset = 0, contentLength = -1) {
if (contentLength == -1)
@ -216,13 +363,32 @@ export default class ResourceTemplate {
{
var ft = new FunctionTemplate();
ft.index = functionIndex++;
var expansion = ((data.getUint8(offset) & 0x10) == 0x10);
ft.isVoid = ((data.getUint8(offset++) & 0x08) == 0x08);
var hasExpansion = ((data.getUint8(offset++) & 0x10) == 0x10);
var len = data.getUint8(offset++);
ft.name = data.getString(offset, len);
offset += len;
if (expansion) // expansion ?
// return type
var {size, value: returnType} = TemplateDataType.parse(data, offset);
offset += size;
ft.returnType = returnType;
// arguments count
var argsCount = data.getUint8(offset++);
var args = [];
for (var a = 0; a < argsCount; a++)
{
var {size, value: argType} = ArgumentTemplate.parse(data, offset);
args.push(argType);
offset += size;
}
ft.arguments = args;
if (hasExpansion) // expansion ?
{
var cs = data.getUint32(offset);
offset += 4;
@ -237,15 +403,21 @@ export default class ResourceTemplate {
var pt = new PropertyTemplate();
pt.index = propertyIndex++;
var readExpansion = ((data.getUint8(offset) & 0x8) == 0x8);
var writeExpansion = ((data.getUint8(offset) & 0x10) == 0x10);
var hasReadExpansion = ((data.getUint8(offset) & 0x8) == 0x8);
var hasWriteExpansion = ((data.getUint8(offset) & 0x10) == 0x10);
pt.recordable = ((data.getUint8(offset) & 1) == 1);
pt.permission = ((data.getUint8(offset++) >> 1) & 0x3);
var len = data.getUint8(offset++);
pt.name = data.getString(offset, len);
offset += len;
if (readExpansion) // expansion ?
var {size, value: valueType} = TemplateDataType.parse(data, offset);
offset += size;
pt.valueType = valueType;
if (hasReadExpansion) // expansion ?
{
var cs = data.getUint32(offset);
offset += 4;
@ -253,7 +425,7 @@ export default class ResourceTemplate {
offset += cs;
}
if (writeExpansion) // expansion ?
if (hasWriteExpansion) // expansion ?
{
var cs = data.getUint32(offset);
offset += 4;
@ -267,14 +439,19 @@ export default class ResourceTemplate {
{
var et = new EventTemplate();
et.index = eventIndex++;
var expansion = ((data.getUint8(offset) & 0x10) == 0x10);
var hasExpansion = ((data.getUint8(offset) & 0x10) == 0x10);
et.listenable = ((data.getUint8(offset++) & 0x8) == 0x8);
var len = data.getUint8(offset++);
et.name = data.getString(offset, len);
offset += len;
if (expansion) // expansion ?
var {size, value: argType} = TemplateDataType.parse(data, offset);
offset += size;
et.argumentType = argType;
if (hasExpansion) // expansion ?
{
var cs = data.getUint32(offset);
offset += 4;

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2017 Ahmed Kh. Zamil
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
"use strict";
import {DC, BL} from '../../Data/DataConverter.js';
import DataType from "../../Data/DataType.js";
import Structure from '../../Data/Structure.js';
import IResource from '../IResource.js';
import ResourceTemplate from './ResourceTemplate.js';
export default class TemplateDataType
{
static typesDefinitions = [
"var",
"bool",
"sbyte",
"byte",
"char",
"short",
"ushort",
"int",
"uint",
"long",
"ulong",
"float",
"double",
"decimal",
"date",
"resource",
"DistributedResource",
"ResourceLink",
"string",
"structure"
];
get typeTemplate() {
return this.typeGuid == null ? null : Warehouse.getTemplateByType(this.typeGuid);
}
//@TODO: implement this
static fromType(type)
{
var isArray = type instanceof Array;
if (isArray)
type = type[0]
var dataType = 0;
var typeGuid = null;
if (!isNaN(type))
dataType = type;
else if (type == Structure)
dataType = DataType.Structure;
else if (typeof type == "string")
{
var tIndex = this.typesDefinitions.indexOf(type);
dataType = tIndex > -1 ? tIndex : 0;
}
else if (type?.prototype instanceof IResource)
{
dataType = DataType.Resource;
typeGuid = ResourceTemplate.getTypeGuid(type);
}
if (isArray)
dataType |= DataType.VarArray;
return new TemplateDataType(DataType.StructureArray);
}
compose()
{
if (this.type == DataType.Resource ||
this.type == DataType.ResourceArray)
{
return BL()
.addUint8(this.type)
.addUint8Array(this.typeGuid)
.toDC();
}
else
return DC.from([this.type]);
}
constructor(type, guid){
this.type = type;
this.typeGuid = guid;
}
static parse(data, offset)
{
var type = data.getUint8(offset++);
if (type == DataType.Resource ||
type == DataType.ResourceArray)
{
var guid = data.getGuid(offset);
return {size: 17, value: new TemplateDataType(type, guid)};
}
else
return {size: 1, value: new TemplateDataType(type)};
}
}

View File

@ -35,7 +35,7 @@ import DistributedConnection from '../Net/IIP/DistributedConnection.js';
import MemoryStore from '../Stores/MemoryStore.js';
import Instance from '../Resource/Instance.js';
import IStore from './IStore.js';
import { ResourceTrigger } from './IResource.js';
import IResource, { ResourceTrigger } from './IResource.js';
import IndexedDBStore from '../Stores/IndexedDBStore.js';
import ResourceProxy from '../Proxy/ResourceProxy.js';
import AsyncBag from '../Core/AsyncBag.js';
@ -80,7 +80,7 @@ export class WH extends IEventHandler
{
var rt = new AsyncReply();
this.put(res, name, store, parent, null, 0, manager, attributes)
this.put(name, res, store, parent, null, 0, manager, attributes)
.then((ok)=>rt.trigger(res))
.error((ex)=>rt.triggerError(ex));
@ -117,7 +117,7 @@ export class WH extends IEventHandler
if (url[3].length > 0 && url[3] != "")
store.get(url[3]).then(r=>rt.trigger(r)).error(ex=>rt.triggerError(ex));
else
rt.triggerError(store);
rt.trigger(store);
}).error(ex=>{
rt.triggerError(ex);
});
@ -192,7 +192,7 @@ export class WH extends IEventHandler
return true;
}
put(resource, name, store, parent, customTemplate = null, age = 0, manager = null, attributes = null){
put(name, resource, store, parent, customTemplate = null, age = 0, manager = null, attributes = null){
var rt = new AsyncReply();
@ -297,6 +297,12 @@ export class WH extends IEventHandler
getTemplateByType(type)
{
if (type == IResource)
return null;
if (!(type.prototype instanceof IResource))
return false;
let className = type.prototype.constructor.name;
if (className.startsWith("E_"))
@ -318,7 +324,7 @@ export class WH extends IEventHandler
getTemplateByClassId(classId)
{
var template = this.templates.item(classId);
return new AsyncReply(template);
return template;
}
getTemplateByClassName(className)

View File

@ -12,10 +12,15 @@ export default class IMembership extends IResource
return new AsyncReply(null);
}
get guestsAllowed() {
return false;
}
getToken(tokenIndex, domain)
{
return new AsyncReply(null);
}
login(session)
{

View File

@ -41,5 +41,7 @@ export default // ActionType =
AddChild: 10,
RemoveChild: 11,
Rename: 12,
ReceiveEvent: 13
ReceiveEvent: 13,
ViewTemplate: 14
};

View File

@ -177,7 +177,7 @@ export default class IndexedDBStore extends IStore
resource._id = doc.id;
Warehouse.put(resource, doc.name, self, null, null, null, null).then(ok=>{
Warehouse.put(doc.name, resource, self, null, null, null, null).then(ok=>{
self.parse(doc.attributes).then(attributes=>{
resource.instance.setAttributes(attributes);

View File

@ -178,7 +178,7 @@
resource._id = doc.id;
Warehouse.put(resource, doc.name, self, null, null, null, null).then(ok=>{
Warehouse.put(doc.name, resource, self, null, null, null, null).then(ok=>{
self.parse(doc.attributes).then(attributes=>{
resource.instance.setAttributes(attributes);