Skip to content

Commit

Permalink
feat: generate typescript definitions (#354)
Browse files Browse the repository at this point in the history
Signed-off-by: Dan Selman <[email protected]>

* feat: generate typescript definitions
* fix: add support for union and optional JSDoc method args
  • Loading branch information
dselman authored Nov 23, 2021
1 parent cbe94eb commit d31da68
Show file tree
Hide file tree
Showing 66 changed files with 3,393 additions and 93 deletions.
88 changes: 44 additions & 44 deletions packages/concerto-core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,36 @@ class BaseException extends Error {
+ void constructor(string,string)
}
class BaseFileException extends BaseException {
+ void constructor(string,string,string,string,string)
+ void constructor(string,string,string,string?,string?)
+ string getFileLocation()
+ string getShortMessage()
+ string getFileName()
}
class Concerto {
+ void constructor()
+ void validate(undefined) throws Error
+ void constructor(modelManager)
+ void validate(obj,options?) throws Error
+ void getModelManager()
+ boolean isObject()
+ void getTypeDeclaration()
+ string getIdentifier()
+ boolean isIdentifiable()
+ boolean isRelationship()
+ void setIdentifier(string)
+ string getFullyQualifiedIdentifier()
+ string toURI()
+ boolean isObject(obj)
+ void getTypeDeclaration(obj)
+ string getIdentifier(obj)
+ boolean isIdentifiable(obj)
+ boolean isRelationship(obj)
+ void setIdentifier(obj,string)
+ string getFullyQualifiedIdentifier(obj)
+ string toURI(obj)
+ void fromURI(string) throws Error
+ string getType()
+ string getNamespace()
+ string getType(obj)
+ string getNamespace(obj)
}
+ object setCurrentTime()
class Factory {
+ string newId()
+ void constructor(ModelManager)
+ Resource newResource(String,String,String,Object,boolean,String,boolean) throws TypeNotFoundException
+ Resource newConcept(String,String,String,Object,boolean,String,boolean) throws TypeNotFoundException
+ Resource newResource(String,String,String?,Object?,boolean?,String?,boolean?) throws TypeNotFoundException
+ Resource newConcept(String,String,String?,Object?,boolean?,String?,boolean?) throws TypeNotFoundException
+ Relationship newRelationship(String,String,String) throws TypeNotFoundException
+ Resource newTransaction(String,String,String,Object,String,boolean)
+ Resource newEvent(String,String,String,Object,String,boolean)
+ Resource newTransaction(String,String,String?,Object?,String?,boolean?)
+ Resource newEvent(String,String,String?,Object?,String?,boolean?)
}
class AssetDeclaration extends IdentifiedDeclaration {
+ void constructor(ModelFile,Object) throws IllegalModelException
Expand Down Expand Up @@ -69,13 +69,13 @@ class ConceptDeclaration extends ClassDeclaration {
+ void constructor(ModelFile,Object) throws IllegalModelException
}
class Decorator {
+ void constructor(Object) throws IllegalModelException
+ void constructor(ClassDeclaration|Property,Object) throws IllegalModelException
+ void getParent()
+ string getName()
+ object[] getArguments()
}
class DecoratorFactory {
+ Decorator newDecorator(Object)
+ Decorator newDecorator(ClassDeclaration|Property,Object)
}
class EnumDeclaration extends ClassDeclaration {
+ void constructor(ModelFile,Object) throws IllegalModelException
Expand All @@ -92,7 +92,7 @@ class IdentifiedDeclaration extends ClassDeclaration {
+ void constructor(ModelFile,Object) throws IllegalModelException
}
class IllegalModelException extends BaseFileException {
+ void constructor(string,ModelFile,Object,number,number,number,number,string)
+ void constructor(string,ModelFile?,Object?,number,number,number,number,string?)
}
class Introspector {
+ void constructor(ModelManager)
Expand All @@ -101,30 +101,30 @@ class Introspector {
}
class ModelFileDownloader {
+ void constructor(ModelFileLoader,Number)
+ Promise downloadExternalDependencies(ModelFile[],Object)
+ Promise downloadExternalDependencies(ModelFile[],Object?)
+ Promise runJob(Object,Object)
}
class MetaModel {
+ void createMetaModelManager()
+ object validateMetaModel(object)
+ object createNameTable(object)
+ object createNameTable(modelManager,object)
+ string resolveName(string,object)
+ object resolveTypeNames(object,object)
+ object resolveMetaModel(object,object)
+ object modelFileToMetaModel(object,boolean)
+ object modelManagerToMetaModel(object,boolean,boolean)
+ object modelFileToMetaModel(object,boolean?)
+ object modelManagerToMetaModel(object,boolean?,boolean?)
+ string decoratorArgFromMetaModel(object)
+ string decoratorFromMetaModel(object)
+ string decoratorsFromMetaModel(object,string)
+ string propertyFromMetaModel(object)
+ string declFromMetaModel(object)
+ string ctoFromMetaModel(object,boolean)
+ object modelManagerFromMetaModel(object,boolean)
+ object ctoToMetaModel(string,boolean)
+ object ctoToMetaModelAndResolve(string,boolean)
+ string ctoFromMetaModel(object,boolean?)
+ object modelManagerFromMetaModel(object,boolean?)
+ object ctoToMetaModel(string,boolean?)
+ object ctoToMetaModelAndResolve(modelManager,string,boolean?)
}
class ModelFile {
+ void constructor(ModelManager,string,string) throws IllegalModelException
+ void constructor(ModelManager,string,string?) throws IllegalModelException
+ boolean isModelFile()
+ Boolean isSystemModelFile()
+ boolean isExternal()
Expand Down Expand Up @@ -187,7 +187,7 @@ class Identifiable extends Typed {
class Relationship extends Identifiable {
+ String toString()
+ boolean isRelationship()
+ Relationship fromURI(ModelManager,String,String,String)
+ Relationship fromURI(ModelManager,String,String?,String?)
}
class Resource extends Identifiable {
+ String toString()
Expand All @@ -210,22 +210,22 @@ class ValidatedResource extends Resource {
+ void validate() throws Error
}
class ModelLoader {
+ object loadModelManager(string[],object,boolean,number)
+ object loadModelManagerFromModelFiles(object[],undefined,object,boolean,number)
+ object loadModelManager(string[],object,boolean?,number?)
+ object loadModelManagerFromModelFiles(object[],string[],object,boolean?,number?)
}
class ModelManager {
+ void constructor(object)
+ void constructor(object?)
+ boolean isModelManager()
+ Object accept(Object,Object)
+ void validateModelFile(string,string) throws IllegalModelException
+ Object addModelFile(string,string,boolean) throws IllegalModelException
+ Object updateModelFile(string,string,boolean) throws IllegalModelException
+ void validateModelFile(string,string?) throws IllegalModelException
+ Object addModelFile(string|ModelFile,string,boolean?) throws IllegalModelException
+ Object updateModelFile(string|ModelFile,string?,boolean?) throws IllegalModelException
+ void deleteModelFile(string)
+ Object[] addModelFiles(object[],undefined,boolean)
+ Object[] addModelFiles(|,string[],boolean?)
+ void validateModelFiles()
+ Promise updateExternalModels(Object,ModelFileDownloader) throws IllegalModelException
+ void writeModelsToFileSystem(string,Object,boolean)
+ Object[] getModels(Object,boolean)
+ Promise updateExternalModels(Object?,ModelFileDownloader?) throws IllegalModelException
+ void writeModelsToFileSystem(string,Object?,boolean)
+ Object[] getModels(Object?,boolean)
+ void clearModelFiles()
+ ModelFile getModelFile(string)
+ string[] getNamespaces()
Expand All @@ -245,10 +245,10 @@ class SecurityException extends BaseException {
+ void constructor(string)
}
class Serializer {
+ void constructor(Factory,ModelManager,object)
+ void constructor(Factory,ModelManager,object?)
+ void setDefaultOptions(Object)
+ Object toJSON(Resource,Object,boolean,boolean,boolean,boolean,boolean,number) throws Error
+ Resource fromJSON(Object,Object,boolean,boolean,number)
+ Object toJSON(Resource,Object?,boolean?,boolean?,boolean?,boolean?,boolean?,number?) throws Error
+ Resource fromJSON(Object,Object,boolean,boolean,number?)
}
class TypedStack {
+ void constructor(Object)
Expand All @@ -258,6 +258,6 @@ class TypedStack {
+ void clear()
}
class TypeNotFoundException extends BaseException {
+ void constructor(string,string,string)
+ void constructor(string,string?,string)
+ string getTypeName()
}
3 changes: 2 additions & 1 deletion packages/concerto-core/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
# Note that the latest public API is documented using JSDocs and is available in api.txt.
#

Version 1.2.2 {cf9d5dad911076e149b7013afe24e3dc} 2021-11-22
Version 1.2.2 {0ed9b2150eb03a620e66b1fd6a2833b5} 2021-11-22
- Remove custom instanceof and add methods to check runtime type
- Remove support for Node 12
- Generate Typescript definitions from JSDoc
- Parser directly constructs metamodel instance
- Convert MetaModel to a class for Typescript + Webpack compatability
- Update Acorn to latest and refactor the JavaScript parser so we can use static class members
Expand Down
6 changes: 3 additions & 3 deletions packages/concerto-core/lib/modelmanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ abstract concept Event {}
* Note that if there are dependencies between multiple files the files
* must be added in dependency order, or the addModelFiles method can be
* used to add a set of files irrespective of dependencies.
* @param {string} modelFile - The Concerto file as a string
* @param {string|ModelFile} modelFile - Model as a string or object
* @param {string} fileName - an optional file name to associate with the model file
* @param {boolean} [disableValidation] - If true then the model files are not validated
* @throws {IllegalModelException}
Expand Down Expand Up @@ -167,7 +167,7 @@ abstract concept Event {}
* Concerto files have a single namespace. If a Concerto file with the
* same namespace has already been added to the ModelManager then it
* will be replaced.
* @param {string} modelFile - The Concerto file as a string
* @param {string|ModelFile} modelFile - Model as a string or object
* @param {string} [fileName] - a file name to associate with the model file
* @param {boolean} [disableValidation] - If true then the model files are not validated
* @throws {IllegalModelException}
Expand Down Expand Up @@ -206,7 +206,7 @@ abstract concept Event {}

/**
* Add a set of Concerto files to the model manager.
* @param {object[]} modelFiles - An array of Concerto files as strings or ModelFile objects.
* @param {string[]|ModelFile[]} modelFiles - An array of models as strings or ModelFile objects.
* @param {string[]} [fileNames] - A array of file names to associate with the model files
* @param {boolean} [disableValidation] - If true then the model files are not validated
* @returns {Object[]} The newly added model files (internal).
Expand Down
2 changes: 1 addition & 1 deletion packages/concerto-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"test:watch": "nyc mocha --watch --recursive -t 10000",
"mocha": "mocha --recursive -t 10000",
"nyc": "nyc mocha --recursive -t 10000",
"build:types" : "npx -p typescript tsc lib/**/*.js index.js --declaration --allowJs --emitDeclarationOnly --outDir types"
"build:types" : "npx -p typescript tsc ./lib/**/*.js index.js --declaration --allowJs --emitDeclarationOnly --outDir types"
},
"repository": {
"type": "git",
Expand Down
56 changes: 49 additions & 7 deletions packages/concerto-core/scripts/javascriptparser.js
Original file line number Diff line number Diff line change
Expand Up @@ -461,13 +461,55 @@ class JavaScriptParser {
}
}

if (tag.type.name) {
paramTypes.push(tag.type.name);
} else if (tag.type.applications) {
paramTypes.push(tag.type.applications[0].name + '[]');
} else if (tag.type.expression) {
paramTypes.push(tag.type.expression.name);

switch(tag.type.type) {
case 'UnionType':
if(tag?.type?.elements) {
paramTypes.push(tag.type.elements.map( e => e.name).join('|'));
}
else {
throw new Error('Malformed JSDoc comment: ' + JSON.stringify(tag));
}
break;
case 'OptionalType':
if(tag?.type?.expression?.type === 'TypeApplication') {
paramTypes.push(`${tag.type.expression.applications[0].name}[]`);
}
else if(tag?.type.expression?.name) {
paramTypes.push(`${tag?.type.expression?.name}?`);
}
else if(tag?.name) {
paramTypes.push(`${tag?.name}?`);
}
else {
throw new Error('Malformed JSDoc comment: ' + JSON.stringify(tag));
}
break;
case 'AllLiteral':
if(tag?.name) {
paramTypes.push(tag.name);
}
else {
throw new Error('Malformed JSDoc comment: ' + JSON.stringify(tag));
}
break;
case 'NameExpression':
if(tag?.type?.name) {
paramTypes.push(tag.type.name);
}
else {
throw new Error('Malformed JSDoc comment: ' + JSON.stringify(tag));
}
break;
case 'TypeApplication':
if(tag?.type?.applications) {
paramTypes.push(tag.type.applications.map(e => e.name).join(',') + '[]');
}
else {
throw new Error('Malformed JSDoc comment: ' + JSON.stringify(tag));
}
break;
default:
throw new Error('Unrecognized JSDoc comment: ' + JSON.stringify(tag));
}
});
return paramTypes;
Expand Down
2 changes: 1 addition & 1 deletion packages/concerto-core/scripts/versionchecker.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class VersionChecker {
if (digest !== md5) {
throw new Error('Computed public API digest did not match the digest in the changelog for the most recent version. ' +
'Increment the version number and add a new entry to the changelog (explaining your public API change) using the digest ' + digest +
'. Run \'git diff api.txt\' to understand the pubic API changes. Please ensure that TypeScript definitions are up to date by updating packages/concerto-core/types/index.ds');
'. Run \'git diff api.txt\' to understand the pubic API changes. Please ensure that TypeScript definitions are up to date by executing `npm run build:types`');
}

// we're done here...
Expand Down
36 changes: 0 additions & 36 deletions packages/concerto-core/test/scripts/javascriptparser.js
Original file line number Diff line number Diff line change
Expand Up @@ -792,42 +792,6 @@ describe('JavascriptParser', () => {
(()=>{JavascriptParser.getMethodArguments(comment);})
.should.throws(/Malformed JSDoc comment/);
});

it('Cope with different types of tag type', () => {
const comment = `
/**
* @returns {Animal[]} Something valid
*/
`;
sandbox.stub(doctrine,'parse').returns(
{
tags:[
{
type:
{
applications:['somename']
}

},
{
type:
{
expression: {name:'somename'}
}

},
{
type:
{
wibble: {name:'somename'}
}

}
]
});
JavascriptParser.getMethodArguments(comment);

});
});

describe('#getExample', () => {
Expand Down
16 changes: 16 additions & 0 deletions packages/concerto-core/types/lib/baseexception.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export = BaseException;
/**
* A base class for all Concerto exceptions
* @extends Error
* @class
* @memberof module:concerto-core
*/
declare class BaseException extends Error {
/**
* Create the BaseException.
* @param {string} message - The exception message.
* @param {string} component - The optional component which throws this error.
*/
constructor(message: string, component: string);
component: any;
}
Loading

0 comments on commit d31da68

Please sign in to comment.