diff --git a/bin/esiur.cjs b/bin/esiur.cjs index 458bd67..bb252d3 100644 --- a/bin/esiur.cjs +++ b/bin/esiur.cjs @@ -1,7 +1,5 @@ #!/usr/bin/env node - - if (process.argv.length == 2) { console.log("Usage: [arguments]"); console.log(""); @@ -50,12 +48,19 @@ else if (cmd == "get-template") let url = args[0]; console.log(`Getting ${url} ${username} ${password} ${dir}`); + + let getTemplate = async () => { + let Esiur = (await import('../src/esiur.js')).default; + await Esiur.Proxy.TemplateGenerator.getTemplate(url, dir, username, password, true); + } + + getTemplate(); } function getOption(args, option, abbreviation) { let index = args.indexOf(abbreviation); if (index == -1) index = args.indexOf(option); if (index > -1 && index + 1 < args.length) - return args.slice(index, index + 1)[1]; + return args.splice(index, 2)[1]; return null; -} \ No newline at end of file +} diff --git a/demo/chat/chat.js b/demo/chat/chat.js index 6635812..99a042d 100644 --- a/demo/chat/chat.js +++ b/demo/chat/chat.js @@ -10,6 +10,8 @@ import DC from "../../src/Data/DC.js"; import IResource from "../../src/Resource/IResource.js"; import TransmissionType, { TransmissionTypeIdentifier } from "../../src/Data/TransmissionType.js"; import TypedMap from "../../src/Data/TypedMap.js"; +import { Arg, Evt, Func, Prop, TemplateDescriber } from "../../src/Resource/Template/TemplateDescriber.js"; +import { Int32 } from "../../src/Data/ExtendedTypes.js"; const require = createRequire(import.meta.url); @@ -36,7 +38,7 @@ var server; class MyChat extends IResource { // void (string, string)->void - static get template() { + static get templateOld() { return { namespace: "Chat", properties: [["title", String], ["messages", Array], ["users", Array]], @@ -45,6 +47,14 @@ class MyChat extends IResource { }; } + static get template() { + return new TemplateDescriber("Chat",[ + new Prop("title", String), new Prop("messages", Array), new Prop("users", Array), + new Func("send", null, [new Arg("msg", String, true)]), + new Evt("message", Map), new Evt("voice", Int32, true), new Evt("login"), new Evt("logout")] + ); + } + constructor() { super(); this.messages = [new TypedMap({usr: "Admin", msg: "Welcome to Esiur", date: new Date()})]; diff --git a/demo/mongo/mongo.js b/demo/mongo/mongo.js index 052c502..07ce67a 100644 --- a/demo/mongo/mongo.js +++ b/demo/mongo/mongo.js @@ -10,13 +10,12 @@ import DC from "../../src/Data/DC.js"; import IResource from "../../src/Resource/IResource.js"; import Structure from "../../src/Data/Structure.js"; import MongoDBStore from "../../src/Stores/MongoDBStore.js"; +import { Prop, TemplateDescriber } from "../../src/Resource/Template/TemplateDescriber.js"; class User extends IResource { static get template() { - return { - properties: [{name: "username"}, {name: "password"}] - }; + return new TemplateDescriber("Esiur", [new Prop("username", String), new Prop("password", String)]); } } diff --git a/esiur-2.1.4.tgz b/esiur-2.1.4.tgz new file mode 100644 index 0000000..41dd747 Binary files /dev/null and b/esiur-2.1.4.tgz differ diff --git a/lib/333/Test.MyChildRecord.g.js b/lib/333/Test.MyChildRecord.g.js new file mode 100644 index 0000000..54f16bc --- /dev/null +++ b/lib/333/Test.MyChildRecord.g.js @@ -0,0 +1,20 @@ +import Test_MyService from './Test.MyService.g.js'; +import Test_MyGenericRecordOfTest_MyResource from './Test.MyGenericRecordOfTest_MyResource.g.js'; +import Test_MyResource from './Test.MyResource.g.js'; +import Test_MyRecord from './Test.MyRecord.g.js'; +import Test_MyChildResource from './Test.MyChildResource.g.js'; +import Test_SizeEnum from './Test.SizeEnum.g.js'; + +class MyChildRecord extends Test_MyRecord { +/* String */ ChildName; + + + +static get template() {return new TemplateDescriber('Test.MyChildRecord', [ +new Prop('Id', Esiur.Data.Int32, 'Int32', null), +new Prop('Name', String, 'String', null), +new Prop('Score', Esiur.Data.Float64, 'Double', null), +new Prop('ChildName', String, 'String', null)], +Test_MyRecord, 0, null); +} +} \ No newline at end of file diff --git a/lib/333/Test.MyChildResource.g.js b/lib/333/Test.MyChildResource.g.js new file mode 100644 index 0000000..addeb7e --- /dev/null +++ b/lib/333/Test.MyChildResource.g.js @@ -0,0 +1,37 @@ +import Test_MyService from './Test.MyService.g.js'; +import Test_MyGenericRecordOfTest_MyResource from './Test.MyGenericRecordOfTest_MyResource.g.js'; +import Test_MyResource from './Test.MyResource.g.js'; +import Test_MyRecord from './Test.MyRecord.g.js'; +import Test_MyChildRecord from './Test.MyChildRecord.g.js'; +import Test_SizeEnum from './Test.SizeEnum.g.js'; + +export default class MyChildResource extends Test_MyResource { +/* Esiur.Data.Int32 */ Hell2o(/* String */ childName) { +var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({new Esiur.Data.UInt8(0) :childName}); +var rt = new Esiur.Core.AsyncReply(); +this._invoke(2, args).then((x) => rt.trigger(x)) +.error((x) => rt.triggerError(x)) +.chunk((x) => rt.triggerChunk(x)); +return rt; } +/* String */ HelloChild() { +var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({}); +var rt = new Esiur.Core.AsyncReply(); +this._invoke(3, args).then((x) => rt.trigger(x)) +.error((x) => rt.triggerError(x)) +.chunk((x) => rt.triggerChunk(x)); +return rt; } +/* String */ get ChildName() { return this._get(2); } +set ChildName(/* String */ value) { this._set(2, value); } + +static get template() {return new Esiur.Resource.Template.TemplateDescriber('Test', [ +new Esiur.Resource.Template.Prop('CategoryId', Esiur.Data.Int32, 'Int32', null), +new Esiur.Resource.Template.Prop('Description', String, 'Comment', null), +new Esiur.Resource.Template.Prop('ChildName', String, 'String', null), +new Esiur.Resource.Template.Func('Hello', String, [], '() -> String'), +new Esiur.Resource.Template.Func('HelloParent', String, [], '() -> String'), +new Esiur.Resource.Template.Func('Hell2o', Esiur.Data.Int32, [new Esiur.Resource.Template.Arg('childName', String, false)], '([String] childName) -> Int32'), +new Esiur.Resource.Template.Func('HelloChild', String, [], '() -> String')], +Test_MyResource, 0, null, Esiur.Data.Guid.parse('a884cf07481805fe97e6713175a99320'), 'MyChildResource'); +} +} +new Esiur.Resource.Template.TypeTemplate(MyChildResource, true); diff --git a/lib/333/Test.MyGenericRecordOfTest_MyResource.g.js b/lib/333/Test.MyGenericRecordOfTest_MyResource.g.js new file mode 100644 index 0000000..c6af216 --- /dev/null +++ b/lib/333/Test.MyGenericRecordOfTest_MyResource.g.js @@ -0,0 +1,26 @@ +import Test_MyService from './Test.MyService.g.js'; +import Test_MyResource from './Test.MyResource.g.js'; +import Test_MyRecord from './Test.MyRecord.g.js'; +import Test_MyChildRecord from './Test.MyChildRecord.g.js'; +import Test_MyChildResource from './Test.MyChildResource.g.js'; +import Test_SizeEnum from './Test.SizeEnum.g.js'; + +class MyGenericRecordOfTest_MyResource extends IRecord { +/* Esiur.Data.Int32 */ Needed; + +/* TypedList.of(Test_MyResource) */ Results; + +/* Esiur.Data.Int32 */ Start; + +/* Esiur.Data.Int32 */ Total; + + + +static get template() {return new TemplateDescriber('Test.MyGenericRecordOfTest_MyResource', [ +new Prop('Needed', Esiur.Data.Int32, 'Int32', null), +new Prop('Results', TypedList.of(Test_MyResource), 'MyResource[]', null), +new Prop('Start', Esiur.Data.Int32, 'Int32', null), +new Prop('Total', Esiur.Data.Int32, 'Int32', null)], +undefined, 0, null); +} +} \ No newline at end of file diff --git a/lib/333/Test.MyRecord.g.js b/lib/333/Test.MyRecord.g.js new file mode 100644 index 0000000..5010dca --- /dev/null +++ b/lib/333/Test.MyRecord.g.js @@ -0,0 +1,23 @@ +import Test_MyService from './Test.MyService.g.js'; +import Test_MyGenericRecordOfTest_MyResource from './Test.MyGenericRecordOfTest_MyResource.g.js'; +import Test_MyResource from './Test.MyResource.g.js'; +import Test_MyChildRecord from './Test.MyChildRecord.g.js'; +import Test_MyChildResource from './Test.MyChildResource.g.js'; +import Test_SizeEnum from './Test.SizeEnum.g.js'; + +class MyRecord extends IRecord { +/* Esiur.Data.Int32 */ Id; + +/* String */ Name; + +/* Esiur.Data.Float64 */ Score; + + + +static get template() {return new TemplateDescriber('Test.MyRecord', [ +new Prop('Id', Esiur.Data.Int32, 'Int32', null), +new Prop('Name', String, 'String', null), +new Prop('Score', Esiur.Data.Float64, 'Double', null)], +undefined, 0, null); +} +} \ No newline at end of file diff --git a/lib/333/Test.MyResource.g.js b/lib/333/Test.MyResource.g.js new file mode 100644 index 0000000..cc543eb --- /dev/null +++ b/lib/333/Test.MyResource.g.js @@ -0,0 +1,36 @@ +import Test_MyService from './Test.MyService.g.js'; +import Test_MyGenericRecordOfTest_MyResource from './Test.MyGenericRecordOfTest_MyResource.g.js'; +import Test_MyRecord from './Test.MyRecord.g.js'; +import Test_MyChildRecord from './Test.MyChildRecord.g.js'; +import Test_MyChildResource from './Test.MyChildResource.g.js'; +import Test_SizeEnum from './Test.SizeEnum.g.js'; + +export default class MyResource extends Esiur.Net.IIP.DistributedResource { +/* String */ Hello() { +var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({}); +var rt = new Esiur.Core.AsyncReply(); +this._invoke(0, args).then((x) => rt.trigger(x)) +.error((x) => rt.triggerError(x)) +.chunk((x) => rt.triggerChunk(x)); +return rt; } +/* String */ HelloParent() { +var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({}); +var rt = new Esiur.Core.AsyncReply(); +this._invoke(1, args).then((x) => rt.trigger(x)) +.error((x) => rt.triggerError(x)) +.chunk((x) => rt.triggerChunk(x)); +return rt; } +/* Esiur.Data.Int32 */ get CategoryId() { return this._get(0); } +set CategoryId(/* Esiur.Data.Int32 */ value) { this._set(0, value); } +/* String */ get Description() { return this._get(1); } +set Description(/* String */ value) { this._set(1, value); } + +static get template() {return new Esiur.Resource.Template.TemplateDescriber('Test', [ +new Esiur.Resource.Template.Prop('CategoryId', Esiur.Data.Int32, 'Int32', null), +new Esiur.Resource.Template.Prop('Description', String, 'Comment', null), +new Esiur.Resource.Template.Func('Hello', String, [], '() -> String'), +new Esiur.Resource.Template.Func('HelloParent', String, [], '() -> String')], +null, 0, "A\nB\nC\nD", Esiur.Data.Guid.parse('99ce4d8acdf8ab959b8328d636b98ba9'), 'MyResource'); +} +} +new Esiur.Resource.Template.TypeTemplate(MyResource, true); diff --git a/lib/333/Test.MyService.g.js b/lib/333/Test.MyService.g.js new file mode 100644 index 0000000..61b2c04 --- /dev/null +++ b/lib/333/Test.MyService.g.js @@ -0,0 +1,268 @@ +import Test_MyGenericRecordOfTest_MyResource from './Test.MyGenericRecordOfTest_MyResource.g.js'; +import Test_MyResource from './Test.MyResource.g.js'; +import Test_MyRecord from './Test.MyRecord.g.js'; +import Test_MyChildRecord from './Test.MyChildRecord.g.js'; +import Test_MyChildResource from './Test.MyChildResource.g.js'; +import Test_SizeEnum from './Test.SizeEnum.g.js'; + +export default class MyService extends Esiur.Net.IIP.DistributedResource { +/* TypedList.of(Esiur.Data.Nullable.of(TypedMap.of(Esiur.Data.Int32,Esiur.Data.Nullable.of(String)))) */ AsyncHello() { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({}); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(0, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Object */ Connection(/* Object */ a1,/* Esiur.Data.Int32 */ a2) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ (new Esiur.Data.UInt8(0)) : a1, new Esiur.Data.UInt8(1) : a2 }); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(1, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Object */ ConnectionOptional(/* Object */ a1,/* Esiur.Data.Int32 */ a2,/* Esiur.Data.Nullable.of(String) */ a3 = null) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ new Esiur.Data.UInt8(0) : a1, new Esiur.Data.UInt8(1) : a2 }); + if (a3 != null) args.set(new Esiur.Data.UInt8(2), a3); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(2, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Test_MyGenericRecordOfTest_MyResource */ GetGenericRecord() { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({}); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(3, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Tuple.of(Object,Object) */ GetTuple2(/* Esiur.Data.Int32 */ a1,/* String */ a2) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ new Esiur.Data.UInt8(0) : a1, new Esiur.Data.UInt8(1) : a2 }); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(4, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Tuple.of(Object,Object,Object) */ GetTuple3(/* Esiur.Data.Int32 */ a1,/* String */ a2,/* Esiur.Data.Float64 */ a3) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ new Esiur.Data.UInt8(0) : a1, new Esiur.Data.UInt8(1) : a2, new Esiur.Data.UInt8(2) : a3 }); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(5, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Tuple.of(Object,Object,Object,Object) */ GetTuple4(/* Esiur.Data.Int32 */ a1,/* String */ a2,/* Esiur.Data.Float64 */ a3,/* Boolean */ a4) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ new Esiur.Data.UInt8(0) : a1, new Esiur.Data.UInt8(1) : a2, new Esiur.Data.UInt8(2) : a3, new Esiur.Data.UInt8(3) : a4 }); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(6, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Object */ InvokeEvents(/* String */ msg) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ new Esiur.Data.UInt8(0) : msg }); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(7, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Esiur.Data.Float64 */ Optional(/* Object */ a1,/* Esiur.Data.Int32 */ a2,/* Esiur.Data.Nullable.of(String) */ a3 = null,/* Esiur.Data.Nullable.of(String) */ a4 = null) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ new Esiur.Data.UInt8(0) : a1, new Esiur.Data.UInt8(1) : a2 }); + if (a3 != null) args.set(new Esiur.Data.UInt8(2), a3); + if (a4 != null) args.set(new Esiur.Data.UInt8(3), a4); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(8, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Test_MyRecord */ SendRecord(/* Test_MyRecord */ record) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ new Esiur.Data.UInt8(0) : record }); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(9, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } + static /* String */ staticFunction(connection, /* String */ name) { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({ new Esiur.Data.UInt8(0) : name }); + var rt = new Esiur.Core.AsyncReply(); + connection.staticCall(Guid.parse('c4250e9a35c707e9280c7ff2f46d3654'), 10, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } +/* Object */ Void() { + var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))({}); + var rt = new Esiur.Core.AsyncReply(); + this._invoke(11, args).then((x) => rt.trigger(x)) + .error((x) => rt.triggerError(x)) + .chunk((x) => rt.triggerChunk(x)); + return rt; + } + + /* TypedList.of(Boolean) */ get BooleanArray() { return this._get(1); } + set BooleanArray(/* TypedList.of(Boolean) */ value) { this._set(1, value); } +/* String */ get Char16() { return this._get(2); } + set Char16(/* String */ value) { this._set(2, value); } +/* TypedList.of(String) */ get Char16Array() { return this._get(3); } + set Char16Array(/* TypedList.of(String) */ value) { this._set(3, value); } +/* Test_MyChildRecord */ get ChildRecord() { return this._get(4); } + set ChildRecord(/* Test_MyChildRecord */ value) { this._set(4, value); } +/* Test_MyChildResource */ get ChildResource() { return this._get(5); } + set ChildResource(/* Test_MyChildResource */ value) { this._set(5, value); } +/* Test_SizeEnum */ get Enum() { return this._get(6); } + set Enum(/* Test_SizeEnum */ value) { this._set(6, value); } +/* Esiur.Data.Float128 */ get Float128() { return this._get(7); } + set Float128(/* Esiur.Data.Float128 */ value) { this._set(7, value); } +/* TypedList.of(Esiur.Data.Float128) */ get Float128Array() { return this._get(8); } + set Float128Array(/* TypedList.of(Esiur.Data.Float128) */ value) { this._set(8, value); } +/* Esiur.Data.Float32 */ get Float32() { return this._get(9); } + set Float32(/* Esiur.Data.Float32 */ value) { this._set(9, value); } +/* TypedList.of(Esiur.Data.Float32) */ get Float32Array() { return this._get(10); } + set Float32Array(/* TypedList.of(Esiur.Data.Float32) */ value) { this._set(10, value); } +/* Esiur.Data.Float64 */ get Float64() { return this._get(11); } + set Float64(/* Esiur.Data.Float64 */ value) { this._set(11, value); } +/* TypedList.of(Esiur.Data.Float64) */ get Float64Array() { return this._get(12); } + set Float64Array(/* TypedList.of(Esiur.Data.Float64) */ value) { this._set(12, value); } +/* Esiur.Data.Int16 */ get Int16() { return this._get(13); } + set Int16(/* Esiur.Data.Int16 */ value) { this._set(13, value); } +/* TypedList.of(Esiur.Data.Int16) */ get Int16Array() { return this._get(14); } + set Int16Array(/* TypedList.of(Esiur.Data.Int16) */ value) { this._set(14, value); } +/* TypedList.of(Esiur.Data.Int32) */ get Int32Array() { return this._get(15); } + set Int32Array(/* TypedList.of(Esiur.Data.Int32) */ value) { this._set(15, value); } +/* Esiur.Data.Int32 */ get Int32Prop() { return this._get(16); } + set Int32Prop(/* Esiur.Data.Int32 */ value) { this._set(16, value); } +/* Esiur.Data.Int64 */ get Int64() { return this._get(17); } + set Int64(/* Esiur.Data.Int64 */ value) { this._set(17, value); } +/* TypedList.of(Esiur.Data.Int64) */ get Int64Array() { return this._get(18); } + set Int64Array(/* TypedList.of(Esiur.Data.Int64) */ value) { this._set(18, value); } +/* Esiur.Data.Int8 */ get Int8() { return this._get(19); } + set Int8(/* Esiur.Data.Int8 */ value) { this._set(19, value); } +/* TypedList.of(Esiur.Data.Int8) */ get Int8Array() { return this._get(20); } + set Int8Array(/* TypedList.of(Esiur.Data.Int8) */ value) { this._set(20, value); } +/* TypedList.of(Esiur.Data.Int32) */ get IntList() { return this._get(21); } + set IntList(/* TypedList.of(Esiur.Data.Int32) */ value) { this._set(21, value); } +/* TypedMap.of(Esiur.Data.Int32,String) */ get IntStringMap() { return this._get(22); } + set IntStringMap(/* TypedMap.of(Esiur.Data.Int32,String) */ value) { this._set(22, value); } +/* undefined */ get Me() { return this._get(23); } + set Me(/* undefined */ value) { this._set(23, value); } +/* TypedList.of(Test_MyResource) */ get MyResources() { return this._get(24); } + set MyResources(/* TypedList.of(Test_MyResource) */ value) { this._set(24, value); } +/* Object */ get Object() { return this._get(25); } + set Object(/* Object */ value) { this._set(25, value); } +/* Esiur.Data.List */ get ObjectArray() { return this._get(26); } + set ObjectArray(/* Esiur.Data.List */ value) { this._set(26, value); } +/* Esiur.Data.Int32 */ get PropertyContext() { return this._get(27); } + set PropertyContext(/* Esiur.Data.Int32 */ value) { this._set(27, value); } +/* Test_MyRecord */ get Record() { return this._get(28); } + set Record(/* Test_MyRecord */ value) { this._set(28, value); } +/* TypedList.of(Esiur.Data.IRecord) */ get RecordsArray() { return this._get(29); } + set RecordsArray(/* TypedList.of(Esiur.Data.IRecord) */ value) { this._set(29, value); } +/* TypedList.of(Test_MyRecord) */ get RecordsList() { return this._get(30); } + set RecordsList(/* TypedList.of(Test_MyRecord) */ value) { this._set(30, value); } +/* Test_MyResource */ get Resource() { return this._get(31); } + set Resource(/* Test_MyResource */ value) { this._set(31, value); } +/* TypedList.of(Esiur.Resource.IResource) */ get Resources() { return this._get(32); } + set Resources(/* TypedList.of(Esiur.Resource.IResource) */ value) { this._set(32, value); } +/* TypedList.of(String) */ get StringArray() { return this._get(33); } + set StringArray(/* TypedList.of(String) */ value) { this._set(33, value); } +/* TypedMap.of(String,Object) */ get StringMap() { return this._get(34); } + set StringMap(/* TypedMap.of(String,Object) */ value) { this._set(34, value); } +/* String */ get Text() { return this._get(35); } + set Text(/* String */ value) { this._set(35, value); } +/* Date */ get Time() { return this._get(36); } + set Time(/* Date */ value) { this._set(36, value); } +/* Esiur.Data.UInt16 */ get UInt16() { return this._get(37); } + set UInt16(/* Esiur.Data.UInt16 */ value) { this._set(37, value); } +/* TypedList.of(Esiur.Data.UInt16) */ get UInt16Array() { return this._get(38); } + set UInt16Array(/* TypedList.of(Esiur.Data.UInt16) */ value) { this._set(38, value); } +/* Esiur.Data.UInt32 */ get UInt32() { return this._get(39); } + set UInt32(/* Esiur.Data.UInt32 */ value) { this._set(39, value); } +/* TypedList.of(Esiur.Data.UInt32) */ get UInt32Array() { return this._get(40); } + set UInt32Array(/* TypedList.of(Esiur.Data.UInt32) */ value) { this._set(40, value); } +/* Esiur.Data.UInt64 */ get UInt64() { return this._get(41); } + set UInt64(/* Esiur.Data.UInt64 */ value) { this._set(41, value); } +/* TypedList.of(Esiur.Data.UInt64) */ get UInt64Array() { return this._get(42); } + set UInt64Array(/* TypedList.of(Esiur.Data.UInt64) */ value) { this._set(42, value); } +/* TypedList.of(Esiur.Data.UInt8) */ get UInt8Array() { return this._get(43); } + set UInt8Array(/* TypedList.of(Esiur.Data.UInt8) */ value) { this._set(43, value); } +/* TypedList.of(Esiur.Data.Nullable.of(Esiur.Data.UInt8)) */ get UInt8ArrayNull() { return this._get(44); } + set UInt8ArrayNull(/* TypedList.of(Esiur.Data.Nullable.of(Esiur.Data.UInt8)) */ value) { this._set(44, value); } +/* Esiur.Data.Nullable.of(Esiur.Data.UInt8) */ get UInt8Null() { return this._get(45); } + set UInt8Null(/* Esiur.Data.Nullable.of(Esiur.Data.UInt8) */ value) { this._set(45, value); } +/* Esiur.Data.UInt8 */ get UInt8Test() { return this._get(46); } + set UInt8Test(/* Esiur.Data.UInt8 */ value) { this._set(46, value); } + + static get template() { + return new Esiur.Resource.Template.TemplateDescriber('Test', [ + new Esiur.Resource.Template.Prop('Boolean', Boolean, 'Boolean', null), + new Esiur.Resource.Template.Prop('BooleanArray', TypedList.of(Boolean), 'Boolean[]', null), + new Esiur.Resource.Template.Prop('Char16', String, 'Char', null), + new Esiur.Resource.Template.Prop('Char16Array', TypedList.of(String), 'Char[]', null), + new Esiur.Resource.Template.Prop('ChildRecord', Test_MyChildRecord, 'MyChildRecord', null), + new Esiur.Resource.Template.Prop('ChildResource', Test_MyChildResource, 'MyChildResource', null), + new Esiur.Resource.Template.Prop('Enum', Test_SizeEnum, 'SizeEnum', null), + new Esiur.Resource.Template.Prop('Float128', Esiur.Data.Float128, 'Decimal', null), + new Esiur.Resource.Template.Prop('Float128Array', TypedList.of(Esiur.Data.Float128), 'Decimal[]', null), + new Esiur.Resource.Template.Prop('Float32', Esiur.Data.Float32, 'Single', null), + new Esiur.Resource.Template.Prop('Float32Array', TypedList.of(Esiur.Data.Float32), 'Single[]', null), + new Esiur.Resource.Template.Prop('Float64', Esiur.Data.Float64, 'Double', null), + new Esiur.Resource.Template.Prop('Float64Array', TypedList.of(Esiur.Data.Float64), 'Double[]', null), + new Esiur.Resource.Template.Prop('Int16', Esiur.Data.Int16, 'Int16', null), + new Esiur.Resource.Template.Prop('Int16Array', TypedList.of(Esiur.Data.Int16), 'Int16[]', null), + new Esiur.Resource.Template.Prop('Int32Array', TypedList.of(Esiur.Data.Int32), 'Int32[]', null), + new Esiur.Resource.Template.Prop('Int32Prop', Esiur.Data.Int32, 'Int32', null), + new Esiur.Resource.Template.Prop('Int64', Esiur.Data.Int64, 'Int64', null), + new Esiur.Resource.Template.Prop('Int64Array', TypedList.of(Esiur.Data.Int64), 'Int64[]', null), + new Esiur.Resource.Template.Prop('Int8', Esiur.Data.Int8, 'SByte', null), + new Esiur.Resource.Template.Prop('Int8Array', TypedList.of(Esiur.Data.Int8), 'SByte[]', null), + new Esiur.Resource.Template.Prop('IntList', TypedList.of(Esiur.Data.Int32), 'List`1', null), + new Esiur.Resource.Template.Prop('IntStringMap', TypedMap.of(Esiur.Data.Int32, String), 'Map`2', null), + new Esiur.Resource.Template.Prop('Me', undefined, 'MyService', null), + new Esiur.Resource.Template.Prop('MyResources', TypedList.of(Test_MyResource), 'MyResource[]', null), + new Esiur.Resource.Template.Prop('Object', Object, 'Object', null), + new Esiur.Resource.Template.Prop('ObjectArray', Esiur.Data.List, 'Object[]', null), + new Esiur.Resource.Template.Prop('PropertyContext', Esiur.Data.Int32, 'DistributedPropertyContext`1', null), + new Esiur.Resource.Template.Prop('Record', Test_MyRecord, 'MyRecord', null), + new Esiur.Resource.Template.Prop('RecordsArray', TypedList.of(Esiur.Data.IRecord), 'IRecord[]', null), + new Esiur.Resource.Template.Prop('RecordsList', TypedList.of(Test_MyRecord), 'List`1', null), + new Esiur.Resource.Template.Prop('Resource', Test_MyResource, 'MyResource', null), + new Esiur.Resource.Template.Prop('Resources', TypedList.of(Esiur.Resource.IResource), 'IResource[]', null), + new Esiur.Resource.Template.Prop('StringArray', TypedList.of(String), 'String[]', null), + new Esiur.Resource.Template.Prop('StringMap', TypedMap.of(String, Object), 'Map`2', null), + new Esiur.Resource.Template.Prop('Text', String, 'String', null), + new Esiur.Resource.Template.Prop('Time', Date, 'DateTime', null), + new Esiur.Resource.Template.Prop('UInt16', Esiur.Data.UInt16, 'UInt16', null), + new Esiur.Resource.Template.Prop('UInt16Array', TypedList.of(Esiur.Data.UInt16), 'UInt16[]', null), + new Esiur.Resource.Template.Prop('UInt32', Esiur.Data.UInt32, 'UInt32', null), + new Esiur.Resource.Template.Prop('UInt32Array', TypedList.of(Esiur.Data.UInt32), 'UInt32[]', null), + new Esiur.Resource.Template.Prop('UInt64', Esiur.Data.UInt64, 'UInt64', null), + new Esiur.Resource.Template.Prop('UInt64Array', TypedList.of(Esiur.Data.UInt64), 'UInt64[]', null), + new Esiur.Resource.Template.Prop('UInt8Array', TypedList.of(Esiur.Data.UInt8), 'Byte[]', null), + new Esiur.Resource.Template.Prop('UInt8ArrayNull', TypedList.of(Esiur.Data.Nullable.of(Esiur.Data.UInt8)), 'Nullable`1[]', null), + new Esiur.Resource.Template.Prop('UInt8Null', Esiur.Data.Nullable.of(Esiur.Data.UInt8), 'Nullable`1?', null), + new Esiur.Resource.Template.Prop('UInt8Test', Esiur.Data.UInt8, 'Byte', null), + new Esiur.Resource.Template.Func('AsyncHello', TypedList.of(Esiur.Data.Nullable.of(TypedMap.of(Esiur.Data.Int32, Esiur.Data.Nullable.of(String)))), [], '() -> AsyncReply`1'), + new Esiur.Resource.Template.Func('Connection', Object, [new Esiur.Resource.Template.Arg('a1', Object, false), new Esiur.Resource.Template.Arg('a2', Esiur.Data.Int32, false)], '([Object] a1,[Int32] a2) -> Void'), + new Esiur.Resource.Template.Func('ConnectionOptional', Object, [new Esiur.Resource.Template.Arg('a1', Object, false), new Esiur.Resource.Template.Arg('a2', Esiur.Data.Int32, false), new Esiur.Resource.Template.Arg('a3', String, true)], '([Object] a1,[Int32] a2,[String] a3) -> Void'), + new Esiur.Resource.Template.Func('GetGenericRecord', Test_MyGenericRecordOfTest_MyResource, [], '() -> MyGenericRecord`1'), + new Esiur.Resource.Template.Func('GetTuple2', Tuple.of(Object, Object), [new Esiur.Resource.Template.Arg('a1', Esiur.Data.Int32, false), new Esiur.Resource.Template.Arg('a2', String, false)], '([Int32] a1,[String] a2) -> ValueTuple`2'), + new Esiur.Resource.Template.Func('GetTuple3', Tuple.of(Object, Object, Object), [new Esiur.Resource.Template.Arg('a1', Esiur.Data.Int32, false), new Esiur.Resource.Template.Arg('a2', String, false), new Esiur.Resource.Template.Arg('a3', Esiur.Data.Float64, false)], '([Int32] a1,[String] a2,[Double] a3) -> ValueTuple`3'), + new Esiur.Resource.Template.Func('GetTuple4', Tuple.of(Object, Object, Object, Object), [new Esiur.Resource.Template.Arg('a1', Esiur.Data.Int32, false), new Esiur.Resource.Template.Arg('a2', String, false), new Esiur.Resource.Template.Arg('a3', Esiur.Data.Float64, false), new Esiur.Resource.Template.Arg('a4', Boolean, false)], '([Int32] a1,[String] a2,[Double] a3,[Boolean] a4) -> ValueTuple`4'), + new Esiur.Resource.Template.Func('InvokeEvents', Object, [new Esiur.Resource.Template.Arg('msg', String, false)], '([String] msg) -> Void'), + new Esiur.Resource.Template.Func('Optional', Esiur.Data.Float64, [new Esiur.Resource.Template.Arg('a1', Object, false), new Esiur.Resource.Template.Arg('a2', Esiur.Data.Int32, false), new Esiur.Resource.Template.Arg('a3', String, true), new Esiur.Resource.Template.Arg('a4', String, true)], '([Object] a1,[Int32] a2,[String] a3,[String] a4) -> Double'), + new Esiur.Resource.Template.Func('SendRecord', Test_MyRecord, [new Esiur.Resource.Template.Arg('record', Test_MyRecord, false)], '([MyRecord] record) -> MyRecord'), + new Esiur.Resource.Template.Func('staticFunction', String, [new Esiur.Resource.Template.Arg('name', String, false)], '([String] name) -> String'), + new Esiur.Resource.Template.Func('Void', Object, [], '() -> Void'), + new Esiur.Resource.Template.Evt('ArrayEvent', Esiur.Data.List, false, null), + new Esiur.Resource.Template.Evt('StringEvent', String, false, null)], + null, 0, null, Esiur.Data.Guid.parse('c4250e9a35c707e9280c7ff2f46d3654'), 'MyService'); + } +} +new Esiur.Resource.Template.TypeTemplate(MyService, true); diff --git a/lib/333/Test.SizeEnum.g.js b/lib/333/Test.SizeEnum.g.js new file mode 100644 index 0000000..69b54de --- /dev/null +++ b/lib/333/Test.SizeEnum.g.js @@ -0,0 +1,16 @@ +import Test_MyService from './Test.MyService.g.js'; +import Test_MyGenericRecordOfTest_MyResource from './Test.MyGenericRecordOfTest_MyResource.g.js'; +import Test_MyResource from './Test.MyResource.g.js'; +import Test_MyRecord from './Test.MyRecord.g.js'; +import Test_MyChildRecord from './Test.MyChildRecord.g.js'; +import Test_MyChildResource from './Test.MyChildResource.g.js'; + +class SizeEnum extends IEnum { +static SizeEnum Large = SizeEnum(0, 1, 'Large'); +static SizeEnum Medium = SizeEnum(1, 0, 'Medium'); +static SizeEnum Small = SizeEnum(2, -10, 'Small'); +static SizeEnum XLarge = SizeEnum(3, 22, 'XLarge'); +static SizeEnum xSmall = SizeEnum(4, -11, 'xSmall'); + +SizeEnum([int index = 0, value, String name = '']) : super(index, value, name);TemplateDescriber get template => TemplateDescriber('Test.SizeEnum', constants: [Const('Large', getTypeOf(), 1, null), Const('Medium', getTypeOf(), 0, null), Const('Small', getTypeOf(), -10, null), Const('XLarge', getTypeOf(), 22, null), Const('xSmall', getTypeOf(), -11, null)], annotation: null); +} \ No newline at end of file diff --git a/lib/333/init.g.dart b/lib/333/init.g.dart new file mode 100644 index 0000000..6c5f4c1 --- /dev/null +++ b/lib/333/init.g.dart @@ -0,0 +1,30 @@ +import 'dart:async'; +import 'package:esiur/esiur.dart'; +import 'Test.MyService.g.js' as myservice;import 'Test.MyGenericRecordOfTest_MyResource.g.js' as mygenericrecordoftest_myresource;import 'Test.MyResource.g.js' as myresource;import 'Test.MyRecord.g.js' as myrecord;import 'Test.MyChildRecord.g.js' as mychildrecord;import 'Test.MyChildResource.g.js' as mychildresource;import 'Test.SizeEnum.g.js' as sizeenum; + + void init_333(){ + + + Warehouse.defineType(() => myservice.MyService(), RepresentationType(RepresentationTypeIdentifier.TypedResource, false, Guid.parse(''))); + +Warehouse.defineType(() => mygenericrecordoftest_myresource.MyGenericRecordOfTest_MyResource(), RepresentationType(RepresentationTypeIdentifier.TypedRecord, false, Guid.parse(''))); + +Warehouse.defineType(() => myresource.MyResource(), RepresentationType(RepresentationTypeIdentifier.TypedResource, false, Guid.parse(''))); + +Warehouse.defineType(() => myrecord.MyRecord(), RepresentationType(RepresentationTypeIdentifier.TypedRecord, false, Guid.parse(''))); + +Warehouse.defineType(() => mychildrecord.MyChildRecord(), RepresentationType(RepresentationTypeIdentifier.TypedRecord, false, Guid.parse(''))); + +Warehouse.defineType(() => mychildresource.MyChildResource(), RepresentationType(RepresentationTypeIdentifier.TypedResource, false, Guid.parse(''))); + +Warehouse.defineType(() => sizeenum.SizeEnum(), RepresentationType(RepresentationTypeIdentifier.Enum, false, Guid.parse(''))); + + Esiur.Resource.Warehouse.putTemplate(Esiur.Resource.Template.TypeTemplate.fromType(myservice.MyService)); + + +Warehouse.putTemplate(TypeTemplate.fromType(mygenericrecordoftest_myresource.MyGenericRecordOfTest_MyResource)); +Warehouse.putTemplate(TypeTemplate.fromType(myresource.MyResource)); +Warehouse.putTemplate(TypeTemplate.fromType(myrecord.MyRecord)); +Warehouse.putTemplate(TypeTemplate.fromType(mychildrecord.MyChildRecord)); +Warehouse.putTemplate(TypeTemplate.fromType(mychildresource.MyChildResource)); +Warehouse.putTemplate(TypeTemplate.fromType(sizeenum.SizeEnum));} \ No newline at end of file diff --git a/src/Data/DC.js b/src/Data/DC.js index 8e9d5eb..f04533f 100644 --- a/src/Data/DC.js +++ b/src/Data/DC.js @@ -72,7 +72,7 @@ export default class DC extends Uint8Array return new DC(list); } - static hexToBytes(value) + static fromHex(value) { // convert hex to Uint8Array var rt = new DC(value.length/2); @@ -467,9 +467,13 @@ export default class DC extends Uint8Array return rt; } - getHex(offset, length) + toHex(offset, length) { var rt = ""; + if (length == null) + length = this.byteLength; + if (offset == null) + offset = 0; for(var i = offset; i < offset + length; i++) { var h = this[i].toString(16); rt += h.length == 1 ? "0" + h : h; diff --git a/src/Data/DataSerializer.js b/src/Data/DataSerializer.js index 8a1f13a..e418fd0 100644 --- a/src/Data/DataSerializer.js +++ b/src/Data/DataSerializer.js @@ -129,7 +129,7 @@ export default class DataSerializer { return new DataSerializerComposeResults( TransmissionTypeIdentifier.Null, new DC(0)); - var template = Warehouse.getTemplateByType(value.runtimeType) ?? value.template; + var template = Warehouse.getTemplateByType(value.constructor); if (template == null) return new DataSerializerComposeResults( @@ -355,7 +355,7 @@ export default class DataSerializer { var rt = BinaryList(); - var template = Warehouse.getTemplateByType(value.runtimeType); + var template = Warehouse.getTemplateByType(value.constructor); if (template == null) return new DataSerializerComposeResults( diff --git a/src/Data/Guid.js b/src/Data/Guid.js index ea7b3c2..0042bbf 100644 --- a/src/Data/Guid.js +++ b/src/Data/Guid.js @@ -35,15 +35,15 @@ export default class Guid valueOf() { - return this.value.getHex(0, 16); + return this.value.toHex(0, 16); } - static fromString(data) { - this.value = DC.fromHex(data, ''); + static parse(data) { + return new Guid(DC.fromHex(data, '')) } toString() { - return this.vlue.toHex(''); + return this.value.toHex(); } // [Symbol.toPrimitive](hint){ diff --git a/src/Data/Nullable.js b/src/Data/Nullable.js new file mode 100644 index 0000000..9166da6 --- /dev/null +++ b/src/Data/Nullable.js @@ -0,0 +1,25 @@ +export default class Nullable { + + static cache = { }; + + static getType(nullableType){ + return nullableType.constructor.type; + } + + static of(type){ + + if (type.constructor.isNullable) + return type; + + if (Nullable.cache[type] != null) + return Nullable.cache[type]; + + let c = class extends type{} + Object.defineProperty(c, "isNullable", {value: true}); + Object.defineProperty(c, "type", {value: type}); + + Nullable.cache[type] = c; + + return c; + } +} \ No newline at end of file diff --git a/src/Data/RepresentationType.js b/src/Data/RepresentationType.js index b96aa95..9573cc9 100644 --- a/src/Data/RepresentationType.js +++ b/src/Data/RepresentationType.js @@ -9,8 +9,17 @@ import DC from './DC.js'; import Warehouse from '../Resource/Warehouse.js'; import {Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UInt128, Char8, Char16, Float32, Float64, Float128} from './ExtendedTypes.js'; +import Nullable from './Nullable.js'; +import IEnum from './IEnum.js'; +import TypedList from './TypedList.js'; +import TypedMap from './TypedMap.js'; +import RecordArray from './RecordArray.js'; +import ResourceArray from './ResourceArray.js'; +import Tuple from './Tuple.js'; +import Void from './Void.js'; + export const RepresentationTypeIdentifier = { - Void: 0x0, + Void: 0x0, Dynamic : 0x1, Bool : 0x2, UInt8 : 0x3, @@ -47,31 +56,70 @@ export const RepresentationTypeIdentifier = { Tuple7 : 0x78 } -let RuntimeTypes = {}; +let IdentifierToTypeMap = {}; -RuntimeTypes[RepresentationTypeIdentifier.Void] = [Object, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Bool] = [Boolean, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Char] = [Char8, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Char16] = [Char16, Object]; -RuntimeTypes[RepresentationTypeIdentifier.UInt8] = [UInt8, UInt8]; -RuntimeTypes[RepresentationTypeIdentifier.Int8] = [Int8, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Int16] = [Int16, Object]; -RuntimeTypes[RepresentationTypeIdentifier.UInt16] = [UInt16, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Int32] = [Int32, Object]; -RuntimeTypes[RepresentationTypeIdentifier.UInt32] = [UInt32, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Int64] = [Int64, Object]; -RuntimeTypes[RepresentationTypeIdentifier.UInt64] = [UInt64, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Int128] = [Int128, Object]; -RuntimeTypes[RepresentationTypeIdentifier.UInt128] = [UInt128, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Float32] = [Float32, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Float64] = [Float64, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Decimal] = [Float128, Object]; -RuntimeTypes[RepresentationTypeIdentifier.String] = [String, Object]; -RuntimeTypes[RepresentationTypeIdentifier.DateTime] = [Date, Object]; -RuntimeTypes[RepresentationTypeIdentifier.Resource] = [IResource, IResource]; -RuntimeTypes[RepresentationTypeIdentifier.Record] = [IRecord, IRecord]; +IdentifierToTypeMap[RepresentationTypeIdentifier.Void] = Void; +IdentifierToTypeMap[RepresentationTypeIdentifier.Bool] = Boolean; +IdentifierToTypeMap[RepresentationTypeIdentifier.Char] = Char8; +IdentifierToTypeMap[RepresentationTypeIdentifier.Char16] = Char16; +IdentifierToTypeMap[RepresentationTypeIdentifier.UInt8] = UInt8; +IdentifierToTypeMap[RepresentationTypeIdentifier.Int8] = Int8; +IdentifierToTypeMap[RepresentationTypeIdentifier.Int16] = Int16; +IdentifierToTypeMap[RepresentationTypeIdentifier.UInt16] = UInt16; +IdentifierToTypeMap[RepresentationTypeIdentifier.Int32] = Int32; +IdentifierToTypeMap[RepresentationTypeIdentifier.UInt32] = UInt32; +IdentifierToTypeMap[RepresentationTypeIdentifier.Int64] = Int64; +IdentifierToTypeMap[RepresentationTypeIdentifier.UInt64] = UInt64; +IdentifierToTypeMap[RepresentationTypeIdentifier.Int128] = Int128; +IdentifierToTypeMap[RepresentationTypeIdentifier.UInt128] = UInt128; +IdentifierToTypeMap[RepresentationTypeIdentifier.Float32] = Float32; +IdentifierToTypeMap[RepresentationTypeIdentifier.Float64] = Float64; +IdentifierToTypeMap[RepresentationTypeIdentifier.Decimal] = Float128; +IdentifierToTypeMap[RepresentationTypeIdentifier.String] = String; +IdentifierToTypeMap[RepresentationTypeIdentifier.DateTime] = Date; +IdentifierToTypeMap[RepresentationTypeIdentifier.Resource] = IResource; +IdentifierToTypeMap[RepresentationTypeIdentifier.Record] = IRecord; +IdentifierToTypeMap[RepresentationTypeIdentifier.List] = Array; +IdentifierToTypeMap[RepresentationTypeIdentifier.Map] = Map; +IdentifierToTypeMap[RepresentationTypeIdentifier.ResourceArray] = ResourceArray; +IdentifierToTypeMap[RepresentationTypeIdentifier.RecordArray] = RecordArray; + +const TypeToIdentifierMap = {}; +TypeToIdentifierMap[Void] = RepresentationTypeIdentifier.Void; +TypeToIdentifierMap[Boolean] = RepresentationTypeIdentifier.Bool; +TypeToIdentifierMap[Char8] = RepresentationTypeIdentifier.Char; +TypeToIdentifierMap[Char16] = RepresentationTypeIdentifier.Char16; +TypeToIdentifierMap[UInt8] = RepresentationTypeIdentifier.UInt8; +TypeToIdentifierMap[Int8] = RepresentationTypeIdentifier.Int8; +TypeToIdentifierMap[Int16] = RepresentationTypeIdentifier.Int16; +TypeToIdentifierMap[UInt16] = RepresentationTypeIdentifier.UInt16; +TypeToIdentifierMap[Int32] = RepresentationTypeIdentifier.Int32; +TypeToIdentifierMap[UInt32] = RepresentationTypeIdentifier.UInt32; +TypeToIdentifierMap[Int64] = RepresentationTypeIdentifier.Int64; +TypeToIdentifierMap[UInt64] = RepresentationTypeIdentifier.UInt64; +TypeToIdentifierMap[Int128] = RepresentationTypeIdentifier.Int128; +TypeToIdentifierMap[UInt128] = RepresentationTypeIdentifier.UInt128; +TypeToIdentifierMap[Float32] = RepresentationTypeIdentifier.Float32; +TypeToIdentifierMap[Float64] = RepresentationTypeIdentifier.Float64; +TypeToIdentifierMap[Float128] = RepresentationTypeIdentifier.Decimal; +TypeToIdentifierMap[String] = RepresentationTypeIdentifier.String; +TypeToIdentifierMap[Date] = RepresentationTypeIdentifier.DateTime; +TypeToIdentifierMap[IResource] = RepresentationTypeIdentifier.Resource; +TypeToIdentifierMap[IRecord] = RepresentationTypeIdentifier.Record; +TypeToIdentifierMap[Array] = RepresentationTypeIdentifier.List; +TypeToIdentifierMap[Map] = RepresentationTypeIdentifier.Map; +TypeToIdentifierMap[RecordArray] = RepresentationTypeIdentifier.RecordArray; +TypeToIdentifierMap[ResourceArray] = RepresentationTypeIdentifier.ResourceArray; + +const TupleIdentifierByLength = { + 2: RepresentationTypeIdentifier.Tuple2, + 3: RepresentationTypeIdentifier.Tuple3, + 4: RepresentationTypeIdentifier.Tuple4, + 5: RepresentationTypeIdentifier.Tuple5, + 6: RepresentationTypeIdentifier.Tuple6, + 7: RepresentationTypeIdentifier.Tuple7, +} - export class RepresentationTypeParseResults { //RepresentationType type; //int size; @@ -82,23 +130,41 @@ export class RepresentationTypeParseResults { } export default class RepresentationType { -// static getTypeFromName(name) { -// const types = { -// "int": int, -// "bool": bool, -// "double": double, -// "String": String, -// "IResource": IResource, -// "IRecord": IRecord, -// "IEnum": IEnum, -// "DC": DC, -// }; -// if (types[name] != null) { -// return types[name]; -// } else -// return Object().runtimeType; -// } + static getRuntimeType() { + let runtimeType = null; + + if (IdentifierToTypeMap[this.identifier] != undefined) + runtimeType = IdentifierToTypeMap[this.identifier] + if (this.identifier == RepresentationTypeIdentifier.TypedResource) { + runtimeType = Warehouse.getTemplateByClassId(this.guid)?.definedType; + } else if (this.identifier == RepresentationTypeIdentifier.TypedRecord) { + runtimeType = Warehouse.getTemplateByClassId(this.guid, TemplateType.Record)?.definedType; + } else if (this.identifier == RepresentationTypeIdentifier.Enum) { + runtimeType = Warehouse.getTemplateByClassId(this.guid, TemplateType.Enum)?.definedType; + } else if (this.identifier == RepresentationTypeIdentifier.TypedList){ + let elementType = this.subTypes[0].getRuntimeType(); + runtimeType = TypedList.of(elementType); + } else if (this.identifier == RepresentationTypeIdentifier.TypedMap){ + let keyType = this.subTypes[0].getRuntimeType(); + let valueType = this.subTypes[1].getRuntimeType(); + runtimeType = TypedMap.of(keyType, valueType); + } else if (this.identifier == RepresentationTypeIdentifier.Tuple2 + || this.identifier == RepresentationTypeIdentifier.Tuple3 + || this.identifier == RepresentationTypeIdentifier.Tuple4 + || this.identifier == RepresentationTypeIdentifier.Tuple5 + || this.identifier == RepresentationTypeIdentifier.Tuple6 + || this.identifier == RepresentationTypeIdentifier.Tuple7) { + + let subs = this.subTypes.map(x=>x.getRuntimeType()); + runtimeType = Tuple.of(...subs); + } + + if (this.nullable) + return Nullable.of(runtimeType); + else + return runtimeType; + } toNullable() { return new RepresentationType(this.identifier, true, this.guid, this.subTypes); @@ -108,29 +174,60 @@ export default class RepresentationType { static get Dynamic() { return new RepresentationType(RepresentationTypeIdentifier.Dynamic, true, null, null);} - static fromType(type) { - return Warehouse.typesFactory[type]?.representationType; - } - - getRuntimeType() { - if (RuntimeTypes[this.identifier]) - return this.nullable - ? RuntimeTypes[this.identifier][1] - : RuntimeTypes[this.identifier][0]; - if (this.identifier == RepresentationTypeIdentifier.TypedRecord) - return Warehouse.getTemplateByClassId(this.guid, TemplateType.Record) - ?.definedType; - else if (this.identifier == RepresentationTypeIdentifier.TypedResource) - return Warehouse.getTemplateByClassId(this.guid, TemplateType.Unspecified) - ?.definedType; - else if (this.identifier == RepresentationTypeIdentifier.Enum) - return Warehouse.getTemplateByClassId(this.guid, TemplateType.Enum) - ?.definedType; + static fromType(type) { + + + if (type == null) + throw new Error("Type can't be null."); + + let nullable = type.constructor.isNullable; + + if (nullable) + type = type.constructor.type; // original type + + let identifier = TypeToIdentifierMap[type]; + + if (identifier != null) + return new RepresentationType(identifier, null); + + if (type.prototype instanceof IResource){ + + let template = Warehouse.getTemplateByType(type); + return new RepresentationType(RepresentationTypeIdentifier.TypedResource, nullable, template.classId); + + } else if (type.prototype instanceof IRecord) { + + let template = Warehouse.getTemplateByType(type); + return new RepresentationType(RepresentationTypeIdentifier.TypedRecord, nullable, template.classId); + + } else if (type.prototype instanceof IEnum) { + + let template = Warehouse.getTemplateByType(type); + return new RepresentationType(RepresentationTypeIdentifier.Enum, nullable, template.classId); + + } else if (type.prototype instanceof TypedList) { + + let elementType = RepresentationType.fromType(TypedList.getType(type)); + return new RepresentationType(RepresentationTypeIdentifier.TypedList, null, null, [elementType]); + + } else if (type.prototype instanceof TypedMap) { + + let subs = TypedMap.getTypes(type); + let keyType = RepresentationType.fromType(subs[0]); + let valueType = RepresentationType.fromType(subs[1]); + return new RepresentationType(RepresentationTypeIdentifier.TypedMap, null, null, [keyType, valueType]); + + } else if (type.prototype instanceof Tuple) { + + let subs = Tuple.gettypes(type).map(x=> RepresentationType.fromType(x)); + return new RepresentationType(TupleIdentifierByLength[subs.length], nullable, null, subs); + } + return null; } - + constructor(identifier, nullable, guid, subTypes) { this.identifier = identifier; diff --git a/src/Data/Void.js b/src/Data/Void.js new file mode 100644 index 0000000..8bfc666 --- /dev/null +++ b/src/Data/Void.js @@ -0,0 +1,4 @@ + +export default class Void { + +} \ No newline at end of file diff --git a/src/Net/IIP/DistributedConnection.js b/src/Net/IIP/DistributedConnection.js index a9025eb..2e15860 100644 --- a/src/Net/IIP/DistributedConnection.js +++ b/src/Net/IIP/DistributedConnection.js @@ -82,6 +82,7 @@ import PropertyValue from '../../Data/PropertyValue.js'; import PropertyValueArray from '../../Data/PropertyValueArray.js'; import { UInt8 } from '../../Data/ExtendedTypes.js'; import ConnectionStatus from './ConnectionStatus.js'; +import { Prop, TemplateDescriber } from '../../Resource/Template/TemplateDescriber.js'; export default class DistributedConnection extends IStore { @@ -3184,9 +3185,6 @@ export default class DistributedConnection extends IStore { static get template() { - return { - namespace: "Esiur", - properties: [["status", UInt8]] - }; + return new TemplateDescriber("Esiur", [new Prop("status", UInt8)]); } } diff --git a/src/Net/IIP/DistributedResource.js b/src/Net/IIP/DistributedResource.js index 92964fd..419e503 100644 --- a/src/Net/IIP/DistributedResource.js +++ b/src/Net/IIP/DistributedResource.js @@ -171,15 +171,6 @@ export default class DistributedResource extends IResource var makeSetter = function(index) { return async function (value) { - if (self._p.destroyed) - throw new Error("Trying to access a destroyed object."); - - if (self._p.suspended) - throw new Error("Trying to access a suspended object."); - - if (self._p.attached) - return; - await self._set(index, value); }; }; @@ -286,11 +277,15 @@ export default class DistributedResource extends IResource _set(index, value) { + if (this._p.destroyed) + throw new Error("Trying to access a destroyed object."); + + if (this._p.suspended) + throw new Error("Trying to access a suspended object."); + if (!this._p.attached) - { - console.log("Resource not attached."); - return; - } + throw new Error("Resource not attached."); + if (this._p.neglect) return; diff --git a/src/Proxy/TemplateGenerator.js b/src/Proxy/TemplateGenerator.js new file mode 100644 index 0000000..d397c6e --- /dev/null +++ b/src/Proxy/TemplateGenerator.js @@ -0,0 +1,488 @@ + +import { RepresentationTypeIdentifier } from '../Data/RepresentationType.js'; +import TemplateType from '../Resource/Template/TemplateType.js'; +import Warehouse from '../Resource/Warehouse.js'; + +export default class TemplateGenerator { + + static toLiteral(input) { + if (input == null) return "null"; + + let literal = ""; + + literal += "\""; + + input.split('').forEach((c) => { + switch (c) { + case '"': + literal += "\\\""; + break; + case '\\': + literal += "\\\\"; + break; + case '\0': + literal += "\\0"; + break; + case '\b': + literal += "\\b"; + break; + case '\f': + literal += "\\f"; + break; + case '\n': + literal += "\\n"; + break; + case '\r': + literal += "\\r"; + break; + case '\t': + literal += "\\t"; + break; + case '\v': + literal += "\\v"; + break; + default: + literal += c; + break; + } + }); + + literal += "\""; + return literal; + } + + static generateRecord(template, templates) { + let className = template.className.split('.').slice(-1)[0]; + let rt = ""; + + let parentName; + + if (template.parentId != null) { + parentName = this._translateClassName(templates + .find((x) => + (x.classId.valueOf() == template.parentId.valueOf()) && + (x.type == TemplateType.Record)) + .className); + rt += `class ${className} extends ${parentName} {\r\n`; + } else { + rt += `class ${className} extends IRecord { \r\n`; + } + + template.properties.forEach((p) => { + if (p.inherited) return; + let ptTypeName = this.getDecoratedTypeName(template, p.valueType, templates); + rt += `${ptTypeName} ${p.name};\r\n\r\n`; + }); + + rt += "\r\n"; + + + // rt += "deserialize(Map value) {"); + + // template.properties.forEach((p) { + // rt.writeln("${p.name} = value['${p.name}'];"); + // }); + + //rt += "}\r\n"; + + // rt.writeln("Map serialize() {"); + // rt.writeln("var rt = Map();"); + + // template.properties.forEach((p) { + // rt.writeln("rt['${p.name}'] = ${p.name};"); + // }); + + // rt.writeln("return rt;"); + // rt.writeln("}"); + + // add template + var descProps = template.properties + .map((p) => { + var ptTypeName = this.getTypeName(template, p.valueType, templates); + return `new Prop('${p.name}', ${ptTypeName}, ${this._escape(p.readAnnotation)}, ${this._escape(p.writeAnnotation)})`; + }); + + rt += `\r\nstatic get template() {return new TemplateDescriber('${template.className}', [\r\n${descProps.join(',\r\n')}], \r\n${parentName}, ${template.version}, ${this.toLiteral(template.annotation)});\r\n}`; + + rt += "\r\n}"; + + return rt; + } + + static _translateClassName(className) { + var cls = className.split('.'); + return cls.join('_'); + } + + static getDecoratedTypeName(forTemplate, representationType, templates){ + return `/* ${this.getTypeName(forTemplate, representationType, templates)} */`; + } + + static getTypeName(forTemplate, representationType, templates) { + let name; + + if (representationType.identifier == RepresentationTypeIdentifier.TypedResource) { + if (representationType.guid.valueOf() == forTemplate.classId.valueOf()) + name = forTemplate.className.split('.').last; + else + name = this._translateClassName(templates + .find((x) => + x.classId.valueOf() == representationType.guid.valueOf() && + (x.type == TemplateType.Resource || + x.type == TemplateType.Wrapper)) + .className); + } else if (representationType.identifier == RepresentationTypeIdentifier.TypedRecord) { + if (representationType.guid.valueOf() == forTemplate.classId.valueOf()) + name = forTemplate.className.split('.').last; + else + name = this._translateClassName(templates + .find((x) => + x.classId.valueOf() == representationType.guid.valueOf() && + x.type == TemplateType.Record) + .className); + } else if (representationType.identifier == RepresentationTypeIdentifier.Enum) { + if (representationType.guid.valueOf() == forTemplate.classId.valueOf()) + name = forTemplate.className.split('.').last; + else + name = this._translateClassName(templates + .find((x) => + x.classId.valueOf() == representationType.guid.valueOf() && + x.type == TemplateType.Enum) + .className); + } else if (representationType.identifier == RepresentationTypeIdentifier.TypedList) + name = "TypedList.of(" + this.getTypeName(forTemplate, representationType.subTypes[0], templates) + ")"; + else if (representationType.identifier == + RepresentationTypeIdentifier.TypedMap) + name = "TypedMap.of(" + + this.getTypeName(forTemplate, representationType.subTypes[0], templates) + + "," + + this.getTypeName(forTemplate, representationType.subTypes[1], templates) + + ")"; + else if (representationType.identifier == + RepresentationTypeIdentifier.Tuple2 || + representationType.identifier == RepresentationTypeIdentifier.Tuple3 || + representationType.identifier == RepresentationTypeIdentifier.Tuple4 || + representationType.identifier == RepresentationTypeIdentifier.Tuple5 || + representationType.identifier == RepresentationTypeIdentifier.Tuple6 || + representationType.identifier == RepresentationTypeIdentifier.Tuple7) + name = "Tuple.of(" + representationType.subTypes.map( x => this.getTypeName(x, templates)).join(',') + ")"; + else { + switch (representationType.identifier) { + case RepresentationTypeIdentifier.Dynamic: + name = "Object"; + break; + case RepresentationTypeIdentifier.Bool: + name = "Boolean"; + break; + case RepresentationTypeIdentifier.Char: + name = "String"; + break; + case RepresentationTypeIdentifier.DateTime: + name = "Date"; + break; + case RepresentationTypeIdentifier.Decimal: + name = "Esiur.Data.Float128"; + break; + case RepresentationTypeIdentifier.Float32: + name = "Esiur.Data.Float32"; + break; + case RepresentationTypeIdentifier.Float64: + name = "Esiur.Data.Float64"; + break; + case RepresentationTypeIdentifier.Int16: + name = "Esiur.Data.Int16"; + break; + case RepresentationTypeIdentifier.Int32: + name = "Esiur.Data.Int32"; + break; + case RepresentationTypeIdentifier.Int64: + name = "Esiur.Data.Int64"; + break; + case RepresentationTypeIdentifier.Int8: + name = "Esiur.Data.Int8"; + break; + case RepresentationTypeIdentifier.String: + name = "String"; + break; + case RepresentationTypeIdentifier.Map: + name = "Map"; + break; + case RepresentationTypeIdentifier.UInt16: + name = "Esiur.Data.UInt16"; + break; + case RepresentationTypeIdentifier.UInt32: + name = "Esiur.Data.UInt32"; + break; + case RepresentationTypeIdentifier.UInt64: + name = "Esiur.Data.UInt64"; + break; + case RepresentationTypeIdentifier.UInt8: + name = "Esiur.Data.UInt8"; + break; + case RepresentationTypeIdentifier.List: + name = "Esiur.Data.List"; + break; + case RepresentationTypeIdentifier.Resource: + name = "Esiur.Resource.IResource"; + break; + case RepresentationTypeIdentifier.Record: + name = "Esiur.Data.IRecord"; + break; + default: + name = "Object"; + } + } + + return (representationType.nullable) ? `Esiur.Data.Nullable.of(${name})` : name; + } + + static isNullOrEmpty(v) { + return v == null || v == ""; + } + + static async getTemplate(url, dir, username, password, asyncSetters = true) { + + + const fs = await import("fs"); + // var fs = require('fs'); + + const _urlRegex = /^(?:([^\s|:]*):\/\/([^/]*)\/?(.*))/; + // /^(?:([^\s|:]*):\/\/([^/]*)\/?)/; + + if (!_urlRegex.test(url)) + throw Error(`Invalid IIP URL '${url}'`); + + let path = url.split(_urlRegex); + + let con = await Warehouse.get(path[1] + "://" + path[2], username != null + ? {"username": username, "password": password ?? ""} + : null); + + if (con == null) + throw Error("Can't connect to server"); + + if (dir == null || dir == "") + dir = path[2].replaceAll(":", "_"); + + let templates = await con.getLinkTemplates(path[3]); + + // no longer needed + Warehouse.remove(con); + + let dstDir = `lib/${dir}`; + + + if (!fs.existsSync(dstDir)){ + fs.mkdirSync(dstDir, { recursive: true }); + } + + var makeImports = (skipTemplate) => { + let imports = ""; + // make import names + templates.forEach((tmp) => { + if (tmp != skipTemplate) { + let cls = tmp.className.split('.'); + imports += `import ${cls.join('_')} from './${tmp.className}.g.js';\r\n`; + } + }); + + imports += "\r\n"; + return imports; + }; + + // make sources + templates.forEach(async (tmp) => { + console.log(`Generating '${tmp.className}'.`); + let filePath = `${dstDir}/${tmp.className}.g.js`; + + var source = ""; + if (tmp.type == TemplateType.Resource) { + source = makeImports(tmp) + this.generateClass(tmp, templates, asyncSetters); + } else if (tmp.type == TemplateType.Record) { + source = makeImports(tmp) + this.generateRecord(tmp, templates); + } else if (tmp.type == TemplateType.Enum) { + source = makeImports(tmp) + this.generateEnum(tmp, templates); + } + + fs.writeFileSync(filePath, source); + + }); + + + return dstDir; + + } + + static _escape(str) { + if (str == null) + return "null"; + else + return `'${str}'`; + } + + static generateEnum(template, templates) { + var className = template.className.split('.').slice(-1)[0]; + var rt = ""; + + rt += `class ${className} extends IEnum {\r\n`; + + template.constants.forEach((c) => { + rt += `static ${className} ${c.name} = ${className}(${c.index}, ${c.value}, '${c.name}');\r\n`; + }); + + rt += "\r\n"; + + rt += `${className}([int index = 0, value, String name = '']) : super(index, value, name);`; + + // add template + var descConsts = template.constants.map((p) => { + var ctTypeName = this.getTypeName(template, p.valueType, templates); + return `Const('${p.name}', getTypeOf<${ctTypeName}>(), ${p.value}, ${this._escape(p.annotation)})`; + }).join(', '); + + rt += `TemplateDescriber get template => TemplateDescriber('${template.className}', constants: [${descConsts}], annotation: ${this.toLiteral(template.annotation)});`; + + rt += "\r\n}"; + + return rt; + } + + static generateClass(template, templates, asyncSetters = true) { + let className = template.className.split('.').slice(-1)[0]; + + let parentName = null; + + let rt = ""; + + if (template.parentId != null) { + parentName = this._translateClassName(templates + .find((x) => + (x.classId.valueOf() == template.parentId.valueOf()) && + (x.type == TemplateType.Resource || + x.type == TemplateType.Wrapper)) + .className); + rt += `export default class ${className} extends ${parentName} {\r\n`; + } else { + rt += `export default class ${className} extends Esiur.Net.IIP.DistributedResource {\r\n`; + } + + // rt += `constructor() {`; + + // template.events.filter((e) => !e.inherited).forEach((e) => { + // rt += `on('${e.name}', (x) => _${e.name}Controller.add(x));`; + // }); + + // rt += "}\r\n"; + + + template.functions.filter((f) => !f.inherited).forEach((f) => { + var rtTypeName = this.getDecoratedTypeName(template, f.returnType, templates); + var positionalArgs = f.args.filter((x) => !x.optional); + var optionalArgs = f.args.filter((x) => x.optional); + + if (f.isStatic) { + //rt += `static AsyncReply<${rtTypeName}> ${f.name}(DistributedConnection connection`; + rt += `static ${rtTypeName} ${f.name}(connection`; + + if (positionalArgs.length > 0) + rt += `, ${positionalArgs.map((a) => this.getDecoratedTypeName(template, a.type, templates) + " " + a.name).join(',')}`; + + if (optionalArgs.length > 0) { + rt += `, [${optionalArgs.map((a) => this.getDecoratedTypeName(template, a.type.toNullable(), templates) + " " + a.name).join(',')}]`; + } + } else { + //rt += `AsyncReply<${rtTypeName}> ${f.name}(`; + rt += `${rtTypeName} ${f.name}(`; + + if (positionalArgs.length > 0) + rt += `${positionalArgs.map((a) => this.getDecoratedTypeName(template, a.type, templates) + " " + a.name).join(',')}`; + + if (optionalArgs.length > 0) { + if (positionalArgs.length > 0) rt += ","; + //rt += `[${optionalArgs.map((a) => this.getTypeName(template, a.type.toNullable(), templates) + " " + a.name).join(',')}]`; + rt += `${optionalArgs.map((a) => this.getDecoratedTypeName(template, a.type.toNullable(), templates) + " " + a.name + " = null").join(',')}`; + } + } + + rt += ") {\r\n"; +// var argsMap = new (TypedMap.of(UInt8, Object)); + + rt += "var args = new (Esiur.Data.TypedMap.of(Esiur.Data.UInt8, Object))("; + rt += `{${positionalArgs.map((e) => "new Esiur.Data.UInt8(" + e.index.toString() + ') :' + e.name).join(',')}});\r\n`; + + optionalArgs.forEach((a) => { + rt += `if (${a.name} != null) args.set(new Esiur.Data.UInt8(${a.index}), ${a.name});\r\n`; + }); + + //rt += `var rt = new AsyncReply<${rtTypeName}>();\r\n`; + rt += `var rt = new Esiur.Core.AsyncReply();\r\n`; + if (f.isStatic) { + rt += `connection.staticCall(Guid.parse('${template.classId.toString()}'), ${f.index}, args)`; + } else { + rt += `this._invoke(${f.index}, args)`; + } + rt += `.then((x) => rt.trigger(x))\r\n`; + rt += `.error((x) => rt.triggerError(x))\r\n`; + rt += `.chunk((x) => rt.triggerChunk(x));\r\n`; + rt += `return rt; }\r\n`; + }); + + template.properties.filter((p) => !p.inherited).forEach((p) => { + let ptTypeName = this.getDecoratedTypeName(template, p.valueType, templates); + rt += `${ptTypeName} get ${p.name}() { return this._get(${p.index}); }\r\n`; + + if (asyncSetters) + rt += `set ${p.name}(${ptTypeName} value) { this._set(${p.index}, value); }\r\n`; + else + rt += `set ${p.name}(${ptTypeName} value) { this._setSync(${p.index}, value); }\r\n`; + }); + + // template.events.filter((e) => !e.inherited).forEach((e) => { + // var etTypeName = this.getTypeName(template, e.argumentType, templates); + + // rt += `final _${e.name}Controller = StreamController<$etTypeName>();\r\n`; + // rt += `Stream<${etTypeName}> get ${e.name} { \r\n`; + // rt += `return _${e.name}Controller.stream;\r\n`; + // rt += "}"; + // }); + + // add template + var descProps = template.properties //.where((p) => !p.inherited) + .map((p) => { + var ptTypeName = this.getTypeName(template, p.valueType, templates); + return `new Esiur.Resource.Template.Prop('${p.name}', ${ptTypeName}, ${this._escape(p.readAnnotation)}, ${this._escape(p.writeAnnotation)})`; + }); + + var descFuncs = template.functions + .map((f) => { + var ftTypeName = this.getTypeName(template, f.returnType, templates); + + var args = f.args.map((a) => { + var atTypeName = this.getTypeName(template, a.type, templates); + return `new Esiur.Resource.Template.Arg('${a.name}', ${atTypeName}, ${a.optional})`; + }).join(', '); + + return `new Esiur.Resource.Template.Func('${f.name}', ${ftTypeName}, [${args}], ${this._escape(f.annotation)})`; + }); + + var descEvents = template.events + //.where((e) => !e.inherited) + .map((e) => { + var etTypeName = this.getTypeName(template, e.argumentType, templates); + return `new Esiur.Resource.Template.Evt('${e.name}', ${etTypeName}, ${e.listenable}, ${this._escape(e.annotation)})`; + }); + + // constructor(namespace, members, parent, version = 0, annotation = null){ + + + let cls = template.className.split('.'); + let namespace = cls.slice(0, cls.length - 1).join('.'); + + rt += `\r\nstatic get template() {return new Esiur.Resource.Template.TemplateDescriber('${namespace}', [\r\n${[...descProps, ...descFuncs, ...descEvents].join(',\r\n')}], \r\n${parentName}, ${template.version}, ${this.toLiteral(template.annotation)}, Esiur.Data.Guid.parse('${template.classId.toString()}'), '${className}');\r\n}`; + + rt += "\r\n}\r\n"; + + rt += `new Esiur.Resource.Template.TypeTemplate(${className}, true);\r\n` + return rt; + } +} diff --git a/src/Resource/IResource.js b/src/Resource/IResource.js index a3de804..6f109f6 100644 --- a/src/Resource/IResource.js +++ b/src/Resource/IResource.js @@ -29,6 +29,7 @@ import AsyncBag from '../Core/AsyncBag.js'; import AsyncReply from '../Core/AsyncReply.js'; import IDestructible from '../Core/IDestructible.js'; +import { TemplateDescriber } from './Template/TemplateDescriber.js'; export const ResourceTrigger = { @@ -59,11 +60,6 @@ export default class IResource extends IDestructible static get template() { - return { - namespace: "Esiur", - properties: [], - functions: [], - events: [] - } + return new TemplateDescriber("Esiur", []); } } diff --git a/src/Resource/Template/TemplateDescriber.js b/src/Resource/Template/TemplateDescriber.js new file mode 100644 index 0000000..61d0c1f --- /dev/null +++ b/src/Resource/Template/TemplateDescriber.js @@ -0,0 +1,129 @@ +import Void from "../../Data/Void.js"; + +export class TemplateDescriber { + properties; + events; + functions; + constants; + + namespace; + version; + parent; + annotation; + + classId; + className; + + constructor(namespace, members, parent, version = 0, annotation = null, classId = null, className = null){ + + if (namespace == null) + throw new Error("Namespace name can't be null."); + + if (members == null) + throw new Error("Members name can't be null."); + + this.namespace = namespace; + this.parent = parent; + this.properties = members.filter(x=>x instanceof Prop);; + this.functions = members.filter(x=>x instanceof Func); + this.events = members.filter(x=>x instanceof Evt);; + this.constants = members.filter(x=>x instanceof Const);; + this.version = version; + this.annotation = annotation; + this.classId = classId; + this.className = className; + } + } + + export class Prop { + name; + type; + + readAnnotation; + writeAnnotation; + recordable; + + constructor(name, type = Object, readAnnotation = null, writeAnnotation = null, recordable = false) + { + if (name == null) + throw new Error("Property name can't be null."); + this.name = name; + this.type = type ?? Object; + this.readAnnotation = readAnnotation; + this.writeAnnotation = writeAnnotation; + this.recordable = recordable; + } + } + + export class Evt { + name; + listenable; + type; + annotation; + + constructor(name, type = Object, listenable = false, annotation = null) + { + if (name == null) + throw new Error("Event name can't be null."); + this.name = name; + this.type = type ?? Object; + this.listenable = listenable; + this.annotation = annotation; + } + } + + export class Const { + name; + type; + annotation; + value; + + constructor(name, type = String, value, annotation) + { + if (name == null) + throw new Error("Constant name can't be null."); + + this.name = name; + this.type = type ?? String; + this.value = value ?? ""; + this.annotation = annotation; + } + } + + export class Func { + name; + returnType; + args; + + annotation; + isStatic; + + constructor(name, returnType = Void, args = [], annotation = null, isStatic = false) + { + if (name == null) + throw new Error("Function name can't be null."); + + this.name = name; + this.returnType = returnType ?? Void; + this.args = args ?? []; + this.annotation = annotation; + this.isStatic = isStatic; + } + } + + export class Arg { + name; + type; + optional; + + constructor(name, type = Object, optional = false) + { + if (name == null) + throw new Error("Argument name can't be null."); + + this.name = name; + this.type = type ?? Object; + this.optional = optional; + } + } + \ No newline at end of file diff --git a/src/Resource/Template/TypeTemplate.js b/src/Resource/Template/TypeTemplate.js index b358de4..57246c4 100644 --- a/src/Resource/Template/TypeTemplate.js +++ b/src/Resource/Template/TypeTemplate.js @@ -255,74 +255,73 @@ export default class TypeTemplate { this.definedType = type; - var template = type.template; + let describer = type.template; // set guid - this.className = template.namespace + "." + type.prototype.constructor.name; - - this.classId = SHA256.compute(DC.stringToBytes(this.className)).getGuid(0); + this.className = describer.namespace + "." + (describer.className ?? type.prototype.constructor.name); + this.classId = describer.classId ?? SHA256.compute(DC.stringToBytes(this.className)).getGuid(0); if (addToWarehouse) - addToWarehouse.putTemplate(this); + Warehouse.putTemplate(this); //byte currentIndex = 0; - if (template.properties != null) - for (let i = 0; i < template.properties.length; i++) { + if (describer.properties != null) + for (let i = 0; i < describer.properties.length; i++) { //[name, type, {read: comment, write: comment, recordable: }] - let pi = template.properties[i]; - let pt = new PropertyTemplate(this, i, pi[0], false, - RepresentationType.fromType(pi[1]) ?? RepresentationType.Void, - pi[2]?.read, pi[2]?.write, pi[2]?.recordable); + let pi = describer.properties[i]; + let pt = new PropertyTemplate(this, i, pi.name, false, + RepresentationType.fromType(pi.type) ?? RepresentationType.Void, + pi.readAnnotation, pi.writeAnnotation, pi.recordable); pt.propertyInfo = pi; this.properties.push(pt); } - if (template.constants != null) - for (let i = 0; i < template.constants.length; i++) { - let ci = template.constants[i]; - let ct = new ConstantTemplate(this, i, ci[0], false, - RepresentationType.fromType(ci[1]) ?? RepresentationType.Void, - ci.value, ci.help); + if (describer.constants != null) + for (let i = 0; i < describer.constants.length; i++) { + let ci = describer.constants[i]; + let ct = new ConstantTemplate(this, i, ci.name, false, + RepresentationType.fromType(ci.type) ?? RepresentationType.Void, + ci.value, ci.annotation); ct.propertyInfo = ci; this.constants.push(ct); } if (this.templateType == TemplateType.Resource) { - if (template.events != null) + if (describer.events != null) { - for (let i = 0; i < template.events.length; i++) { + for (let i = 0; i < describer.events.length; i++) { // [name, type, {listenable: true/false, help: ""}] - var ei = template.events[i]; - var et = new EventTemplate(this, i, ei[0], false, - RepresentationType.fromType(ei[1]) ?? RepresentationType.Void, - ei[2]?.help, ei[2]?.listenable) + var ei = describer.events[i]; + var et = new EventTemplate(this, i, ei.name, false, + RepresentationType.fromType(ei.type) ?? RepresentationType.Void, + ei.annotation, ei.listenable) et.eventInfo = ei; this.events.push(et); } } - if (template.functions != null) + if (describer.functions != null) { - for (let i = 0; i < template.functions.length; i++) { + for (let i = 0; i < describer.functions.length; i++) { - var fi = template.functions[i]; + var fi = describer.functions[i]; let args = []; - for(let ai = 0; ai < fi[1].length; ai++) - args.push(new ArgumentTemplate(fi[1][ai][0], RepresentationType.fromType(fi[1][ai][1]) - ?? RepresentationType.Dynamic, fi[1][ai][2]?.optional, ai)); + for(let ai = 0; ai < fi.args.length; ai++) + args.push(new ArgumentTemplate(fi.args[ai].name, RepresentationType.fromType(fi.args[ai].type) + ?? RepresentationType.Dynamic, fi.args[ai].optional, ai)); // [name, {param1: type, param2: int}, returnType, "Description"] - let isStatic = type[fi[0]] instanceof Function; + let isStatic = type[fi.name] instanceof Function; - var ft = new FunctionTemplate(this, i, fi[0], false, isStatic, args, - RepresentationType.fromType(fi[2]) ?? RepresentationType.Void, - fi[3]); + var ft = new FunctionTemplate(this, i, fi.name, false, isStatic, args, + RepresentationType.fromType(fi.returnType) ?? RepresentationType.Void, + fi.annotation); ft.methodInfo = fi; @@ -347,7 +346,7 @@ export default class TypeTemplate { // bake it binarily let b = BL(); - let hasClassAnnotation = template.annotation != null; + let hasClassAnnotation = describer.annotation != null; var cls = DC.stringToBytes(this.className); b.addUint8( (hasClassAnnotation ? 0x40 : 0 ) | this.templateType) @@ -357,13 +356,13 @@ export default class TypeTemplate { if (hasClassAnnotation) { - var classAnnotationBytes = DC.stringToBytes(template.annotation); + var classAnnotationBytes = DC.stringToBytes(describer.annotation); b.addUint16(classAnnotationBytes.length) .addUint8Array(classAnnotationBytes); - this.annotation = template.annotation; + this.annotation = describer.annotation; } - b.addUint32(template.version) + b.addUint32(describer.version) .addUint16(this.members.length); for (let i = 0; i < this.functions.length; i++) diff --git a/src/Resource/Warehouse.js b/src/Resource/Warehouse.js index 2d72d70..1979092 100644 --- a/src/Resource/Warehouse.js +++ b/src/Resource/Warehouse.js @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017 Ahmed Kh. Zamil +* Copyright (c) 2017 - 2022 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 @@ -42,12 +42,6 @@ import AsyncBag from '../Core/AsyncBag.js'; import IRecord from '../Data/IRecord.js'; import TemplateType from './Template/TemplateType.js'; import DistributedResource from '../Net/IIP/DistributedResource.js'; -import TypedList from '../Data/TypedList.js'; -import { Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, Float32, Float64 } from '../Data/ExtendedTypes.js'; -import Record from '../Data/Record.js'; -import TypedMap from '../Data/TypedMap.js'; -import {RepresentationType, RepresentationTypeIdentifier} from '../Data/RepresentationType.js'; -import FactoryEntry from './FactoryEntry.js'; import IEnum from '../Data/IEnum.js'; export class WH extends IEventHandler @@ -69,8 +63,6 @@ export class WH extends IEventHandler this.protocols = new KeyList(); - this.typesFactory = this._getBuiltInTypes(); - this._register("connected"); this._register("disconnected"); ///this._urlRegex = /^(?:([\S]*):\/\/([^\/]*)\/?)/; @@ -122,7 +114,7 @@ export class WH extends IEventHandler } get(path, attributes = null)//, parent = null, manager = null) - { + { var rt = new AsyncReply(); // var self = this; @@ -348,7 +340,7 @@ export class WH extends IEventHandler if (className.startsWith("E_")) className = className.substr(2); - className = type.template.namespace + "." + className; + className = type.template.namespace + "." + (type.template.className ?? className); var templates = this.templates.get(templateType); @@ -358,7 +350,7 @@ export class WH extends IEventHandler if (templates.at(i).className == className) return templates.at(i); - var template = new TypeTemplate(type, this); + var template = new TypeTemplate(type, true); return template; } @@ -434,8 +426,6 @@ export class WH extends IEventHandler query(path) { - - var p = path.trim().split('/'); var resource; @@ -543,92 +533,14 @@ export class WH extends IEventHandler // } return rt; - } + } - /** - * @param {Function} instanceCreator - creator - * @param {RepresentationType} representationType - type - */ - _getTypeEntries(type, representationType) { - let listType = TypedList.of(type); - - - var entry = new FactoryEntry(type, representationType); - let nullableEntry = new FactoryEntry(entry.nullableType, representationType.toNullable()); - let listEntry = new FactoryEntry(listType, - new RepresentationType(RepresentationTypeIdentifier.TypedList, false, - null, [representationType])); - let nullableList = new FactoryEntry(listEntry.nullableType, - new RepresentationType(RepresentationTypeIdentifier.TypedList, true, null, - [representationType])); - - let nullableItemListType = TypedList.of(entry.nullableType); - let listNullableItemEntry = new FactoryEntry(nullableItemListType, - new RepresentationType(RepresentationTypeIdentifier.TypedList, false, - null, [representationType.toNullable()])); - - let nullableListNullableItemEntry = new FactoryEntry(nullableItemListType, - new RepresentationType(RepresentationTypeIdentifier.TypedList, true, null, - [representationType.toNullable()])); - - return [ - entry, nullableEntry, listEntry, nullableList, listNullableItemEntry, nullableListNullableItemEntry - ]; - } - - - /** - * @param {Function} instanceCreator - creator - * @param {RepresentationType} representationType - type - */ - defineType(type, representationType) { - var entries = this._getTypeEntries(type, representationType); - - for(var e of entries) - this.typesFactory[e.type] = e; //.push(e); - } - - _getBuiltInTypes() { - - let entries = [ - ...this._getTypeEntries(Int8, new RepresentationType(RepresentationTypeIdentifier.Int8, false)), - ...this._getTypeEntries(UInt8, new RepresentationType(RepresentationTypeIdentifier.UInt8, false)), - ...this._getTypeEntries(Int16, new RepresentationType(RepresentationTypeIdentifier.Int16, false)), - ...this._getTypeEntries(UInt16, new RepresentationType(RepresentationTypeIdentifier.UInt16, false)), - ...this._getTypeEntries(Int32, new RepresentationType(RepresentationTypeIdentifier.Int32, false)), - ...this._getTypeEntries(UInt32, new RepresentationType(RepresentationTypeIdentifier.UInt32, false)), - ...this._getTypeEntries(Int64, new RepresentationType(RepresentationTypeIdentifier.Int64, false)), - ...this._getTypeEntries(UInt64, new RepresentationType(RepresentationTypeIdentifier.UInt64, false)), - ...this._getTypeEntries(Float32, new RepresentationType(RepresentationTypeIdentifier.Float32, false)), - ...this._getTypeEntries(Float64, new RepresentationType(RepresentationTypeIdentifier.Float64, false)), - ...this._getTypeEntries(String, new RepresentationType(RepresentationTypeIdentifier.String, String)), - ...this._getTypeEntries(Date, new RepresentationType(RepresentationTypeIdentifier.DateTime, Date)), - ...this._getTypeEntries(Record, new RepresentationType(RepresentationTypeIdentifier.Record, false)), - ...this._getTypeEntries(IResource, new RepresentationType(RepresentationTypeIdentifier.Resource, false)), - ...this._getTypeEntries(Array, new RepresentationType(RepresentationTypeIdentifier.List, false)), - ...this._getTypeEntries(Map, new RepresentationType(RepresentationTypeIdentifier.Map, false)), - //...this._getTypeEntries(IResource, new RepresentationType(RepresentationTypeIdentifier.Resource, false)), - //...this._getTypeEntries(TypedMap, new RepresentationType(RepresentationTypeIdentifier.Resource, false)), - - ...this._getTypeEntries(TypedMap.of(String, Object), new RepresentationType(RepresentationTypeIdentifier.TypedMap, false, null, [ - new RepresentationType(RepresentationTypeIdentifier.String, false), - RepresentationType.Dynamic])), - - ...this._getTypeEntries(TypedMap.of(UInt8, Object), new RepresentationType(RepresentationTypeIdentifier.TypedMap, false, null, [ - new RepresentationType(RepresentationTypeIdentifier.UInt8, false), - RepresentationType.Dynamic])), - - ...this._getTypeEntries(TypedMap.of(Int32, Object), new RepresentationType(RepresentationTypeIdentifier.TypedMap, false, null, [ - new RepresentationType(RepresentationTypeIdentifier.Int32, false), - RepresentationType.Dynamic])), - - ]; - - let rt = {}; - for(let entry of entries) - rt[entry.type] = entry; - return rt; + defineType(type){ + let template = this.getTemplateByType(type); + if (template == null) + throw new Error("Unsupported type."); + this.putTemplate(template); } } diff --git a/src/esiur.js b/src/esiur.js index b0c8ebf..ca1a4fd 100644 --- a/src/esiur.js +++ b/src/esiur.js @@ -6,7 +6,10 @@ import DistributedResource from './Net/IIP/DistributedResource.js' import MemoryStore from './Stores/MemoryStore.js'; import IndexedDBStore from './Stores/IndexedDBStore.js'; import IResource from './Resource/IResource.js'; + import ResourceProxy from './Proxy/ResourceProxy.js'; +import TemplateGenerator from './Proxy/TemplateGenerator.js'; + import DistributedConnection from './Net/IIP/DistributedConnection.js'; import IIPAuthPacket from './Net/Packets/IIPAuthPacket.js'; import IIPPacketCommand from './Net/Packets/IIPPacketCommand.js'; @@ -84,12 +87,16 @@ import IPermissionsManager from './Security/Permissions/IPermissionsManager.js'; import Ruling from './Security/Permissions/Ruling.js'; import { Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, Float32, Float64, Float128, Char16, Char8 } from './Data/ExtendedTypes.js'; +import Tuple from './Data/Tuple.js'; +import Nullable from './Data/Nullable.js'; +import Void from './Data/Void.js'; -let namespace = { +const namespace = { Core: { AsyncReply, AsyncException, AsyncQueue, ErrorType, ExceptionCode, IDestructible, IEventHandler, ProgressType}, - Data: {AutoList, AutoMap, BinaryList, Codec, DC, TypedList, TypedMap, Guid, IRecord, KeyList, NotModified, + Data: {AutoList, AutoMap, BinaryList, Codec, DC, TypedList, TypedMap, Guid, IRecord, KeyList, NotModified, ResourceArrayType, PropertyValue, Record, ResourceArray, RepresentationType, RepresentationTypeIdentifier, TransmissionType, TransmissionTypeIdentifier, - Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, Float32, Float64, Float128, Char16, Char8 + Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, Float32, Float64, Float128, Char16, Char8, Tuple, + Nullable, Void }, Net: {INetworkReceiver, NetworkBuffer, NetworkConnections, NetworkServer, NetworkSession, SendList, IIP: {DistributedConnection, DistributedPropertyContext, DistributedResource, DistributedResourceQueueItem, @@ -98,7 +105,7 @@ let namespace = { Sockets: {ISocket, SocketState, WSocket} }, - Proxy: {ResourceProxy}, + Proxy: {ResourceProxy, TemplateGenerator}, Resource: {CustomResourceEvent, Instance, IResource, IStore, Warehouse, Template: { ArgumentTemplate, EventTemplate, FunctionTemplate, MemberTemplate, @@ -115,8 +122,23 @@ let namespace = { Permissions: {ActionType, IPermissionsManager, Ruling}, }, Stores: {IndexedDBStore, MemoryStore}, + Generated: {}, }; +namespace.define = function(type, className) { + let sc = className.split('.'); + let target = namespace.Generated; + + for(let i = 0; i < sc.length; i++) { + if (target[sc[i]] == undefined) + target[sc[i]] = {}; + target = target[sc[i]]; + } + + target[sc[sc.length - 1]] = type; +} + + if (typeof window !== 'undefined') { window.wh = Warehouse; @@ -144,4 +166,4 @@ else if (typeof global !== 'undefined') global.Esiur = namespace; } -export default Warehouse; \ No newline at end of file +export default namespace; \ No newline at end of file