Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules/
dist/
tmp/
tmp/
lib/**/*.d.ts
10 changes: 10 additions & 0 deletions lib/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,20 @@
*/
export default function Base() { }

/**
* Get property value
* @param {string} name
* @return {*}
*/
Base.prototype.get = function(name) {
return this.$model.properties.get(this, name);
};

/**
* Set property value
* @param {string} name
* @param {*} value
*/
Base.prototype.set = function(name, value) {
this.$model.properties.set(this, name, value);
};
13 changes: 13 additions & 0 deletions lib/base.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Base from './base.js';

const baseElement = new Base();

baseElement.set('prop1', true);
baseElement.set('prop2', 123);
baseElement.set('prop3', 'string value');
baseElement.set('prop4', null);
baseElement.set('prop5', undefined);
baseElement.set('prop6', { foo: null });
baseElement.set('prop7', [ true, 123, null, undefined, 'string value', { foo: null } ]);

baseElement.get('prop1');
134 changes: 129 additions & 5 deletions lib/descriptor-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,98 @@ import {
parseName as parseNameNs
} from './ns.js';

/**
* @typedef {import('./ns.js').Namespace} Namespace
* @typedef {import('./registry.js').RegisteredPackage} RegisteredPackage
* @typedef {import('./registry.js').RegisteredTypeDef} RegisteredTypeDef
* @typedef {import('./registry.js').RegisteredPropertyDef} RegisteredPropertyDef
*/

/**
* Effective element descriptor
* aka element type descriptor
* aka element descriptor
* @typedef {{
* readonly ns: Namespace;
* readonly name: Namespace['name'];
* readonly allTypes: Array<RegisteredTypeDef>;
* readonly allTypesByName: Record<string, RegisteredTypeDef>;
* readonly properties: Array<PropertyDescriptor>;
* readonly propertiesByName: Record<string, PropertyDescriptor>;
* readonly bodyProperty?: PropertyDescriptor;
* readonly idProperty?: PropertyDescriptor;
* readonly $pkg?: RegisteredPackage;
* }} EffectiveDescriptor
*/

/**
* Property descriptor
* @typedef {RegisteredPropertyDef & {
* localName: Namespace['localName'];
* inherited?: boolean;
* definedBy?: RegisteredTypeDef;
* }} PropertyDescriptor
*/

/**
* @typedef {{
* name: string;
* isGeneric: true;
* ns: {
* prefix: string;
* localName: string;
* uri: string;
* };
* }} AnyTypeDescriptor
*/

/**
* A utility to build element descriptors.
* @class DescriptorBuilder
* @param {Namespace} nameNs
*/
export default function DescriptorBuilder(nameNs) {

/**
* @private
* @type {Namespace}
*/
this.ns = nameNs;

/**
* @private
* @type {Namespace['name']}
*/
this.name = nameNs.name;

/**
* @private
* @type {Array<RegisteredTypeDef>}
*/
this.allTypes = [];

/**
* @private
* @type {Record<string, RegisteredTypeDef>}
*/
this.allTypesByName = {};

/**
* @private
* @type {Array<PropertyDescriptor>}
*/
this.properties = [];

/**
* @private
* @type {Record<string, PropertyDescriptor>}
*/
this.propertiesByName = {};
}


/**
* @return {EffectiveDescriptor}
*/
DescriptorBuilder.prototype.build = function() {
return pick(this, [
'ns',
Expand All @@ -38,8 +116,8 @@ DescriptorBuilder.prototype.build = function() {

/**
* Add property at given index.
*
* @param {Object} p
* @private
* @param {PropertyDescriptor} p
* @param {Number} [idx]
* @param {Boolean} [validate=true]
*/
Expand All @@ -61,7 +139,12 @@ DescriptorBuilder.prototype.addProperty = function(p, idx, validate) {
}
};


/**
* @private
* @param {PropertyDescriptor} oldProperty
* @param {PropertyDescriptor} newProperty
* @param {string} replace
*/
DescriptorBuilder.prototype.replaceProperty = function(oldProperty, newProperty, replace) {
var oldNameNs = oldProperty.ns;

Expand Down Expand Up @@ -111,7 +194,12 @@ DescriptorBuilder.prototype.replaceProperty = function(oldProperty, newProperty,
propertiesByName[oldNameNs.name] = propertiesByName[oldNameNs.localName] = newProperty;
};


/**
* @private
* @param {PropertyDescriptor} p
* @param {string} targetPropertyName
* @param {string} replace
*/
DescriptorBuilder.prototype.redefineProperty = function(p, targetPropertyName, replace) {

var nsPrefix = p.ns.prefix;
Expand All @@ -130,6 +218,11 @@ DescriptorBuilder.prototype.redefineProperty = function(p, targetPropertyName, r
delete p.redefines;
};

/**
* @private
* @param {PropertyDescriptor} p
* @param {boolean} validate
*/
DescriptorBuilder.prototype.addNamedProperty = function(p, validate) {
var ns = p.ns,
propsByName = this.propertiesByName;
Expand All @@ -142,6 +235,10 @@ DescriptorBuilder.prototype.addNamedProperty = function(p, validate) {
propsByName[ns.name] = propsByName[ns.localName] = p;
};

/**
* @private
* @param {RegisteredPropertyDef} p
*/
DescriptorBuilder.prototype.removeNamedProperty = function(p) {
var ns = p.ns,
propsByName = this.propertiesByName;
Expand All @@ -150,6 +247,11 @@ DescriptorBuilder.prototype.removeNamedProperty = function(p) {
delete propsByName[ns.localName];
};

/**
* @private
* @param {PropertyDescriptor} p
* @param {boolean} [validate]
*/
DescriptorBuilder.prototype.setBodyProperty = function(p, validate) {

if (validate && this.bodyProperty) {
Expand All @@ -161,6 +263,11 @@ DescriptorBuilder.prototype.setBodyProperty = function(p, validate) {
this.bodyProperty = p;
};

/**
* @private
* @param {PropertyDescriptor} p
* @param {boolean} [validate]
*/
DescriptorBuilder.prototype.setIdProperty = function(p, validate) {

if (validate && this.idProperty) {
Expand All @@ -172,6 +279,10 @@ DescriptorBuilder.prototype.setIdProperty = function(p, validate) {
this.idProperty = p;
};

/**
* @private
* @param {RegisteredTypeDef} typeDescriptor
*/
DescriptorBuilder.prototype.assertNotTrait = function(typeDescriptor) {

const _extends = typeDescriptor.extends || [];
Expand All @@ -183,6 +294,10 @@ DescriptorBuilder.prototype.assertNotTrait = function(typeDescriptor) {
}
};

/**
* @private
* @param {PropertyDescriptor} p
*/
DescriptorBuilder.prototype.assertNotDefined = function(p, name) {
var propertyName = p.name,
definedProperty = this.propertiesByName[propertyName];
Expand All @@ -195,10 +310,19 @@ DescriptorBuilder.prototype.assertNotDefined = function(p, name) {
}
};

/**
* @private
* @param {string} name
* @return {PropertyDescriptor}
*/
DescriptorBuilder.prototype.hasProperty = function(name) {
return this.propertiesByName[name];
};

/**
* @param {RegisteredTypeDef} t
* @param {boolean} inherited
*/
DescriptorBuilder.prototype.addTrait = function(t, inherited) {

if (inherited) {
Expand Down
63 changes: 63 additions & 0 deletions lib/descriptor-builder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import DescriptorBuilder, { PropertyDescriptor } from './descriptor-builder.js';
import { Namespace } from './ns.js';
import { RegisteredTypeDef } from './registry.js';
import { expectType } from 'ts-expect';

const ns: Namespace = { name: 'foo:bar', localName: 'bar', prefix: 'foo' };

const builder = new DescriptorBuilder(ns);

const typeStub = {} as RegisteredTypeDef;
builder.addTrait(typeStub , false);

const descriptor = builder.build();

if (ns === descriptor.ns) {
}

descriptor.allTypes.forEach(t => {
// do something
// for example, check the type
expectType<RegisteredTypeDef>(t);
});

for (const name of Object.keys(descriptor.allTypesByName)) {
// do something
// for example, check the type
expectType<string>(name);

//when
const type = descriptor.allTypesByName[name];
//then
expectType<RegisteredTypeDef>(type);
}

descriptor.properties.forEach(p => {
if (p.definedBy?.name === descriptor.name) {
}

if (p.inherited) {
}

if (p.localName === p.ns.localName) {
}

if (p.isMany) {
}

expectType<PropertyDescriptor>(p);
});

for (const name of Object.keys(descriptor.propertiesByName)) {
//when
const propertyDesc = descriptor.propertiesByName[name];
//then
expectType<PropertyDescriptor>(propertyDesc);

if (propertyDesc == descriptor.bodyProperty) {
}

if (propertyDesc == descriptor.idProperty) {
}
}

Loading