Magic Code Generator
Magic Code is a low code development platform.
It is a model-centric system producing imperative code from a declarative model definition. A few lines of a model definition can create several hundred if not a thousand lines of code. It does the tedious task for you by automatically writing repetitive code both on the client and the server sides.
- • On the server-side, a microservice provides a CRUD REST API to several types of databases (Relational DB, document DB, Graph DB, etc.).
- • On the client-side, as a web application.
Both a microservice (server-side) connected to a database and an application (client-side) can be generated by the same model or from 2 separate models.
To be notified of new published versions, get a tutorial and get access to a dashbord container go to the link below to join the Magic Code community.
Otherwise, to be informed of new releases, additional packages, or to download additional code generation scenarios go to: Magic Code Web site
Table of Contents
Introduction
This Visual Studio Code extension package includes a code generation scenario to create both a client application and a microservice interfacing with MongoDB.
More code generators for different environments and improved features are provided on magiccodegenerator.com.
server side
At the moment, Magic Code supports only nodeJS based tools such as express (REST calls dispatching), Mongoose (ORM for MongoDB), and work in progress for Sequelize (for SQL servers) and typeORM (for SQL Servers).
client side
Presently, Magic code supports only Angular as an application framework. Other application frameworks such as
Vue or react are works in progress. Rendition frameworks complement the application frameworks.
Actually Bootstrap and Material are supported. Mobile frameworks such as nativeScript or Ionic are a work in progress
Getting started
Download and install the Visual studio Code extension from the VCSE market place.
Download Magic Code
Prerequisites
1. How to create a new model
Models are defined as javascript objects.
- Create a new file with an ".mdl" extension, this indicates it is a model from which code is generated.
- On the newly created empty file, type CTRL + Space" (windows) or type command + Space (Mac). this will display a "to be filled" model template.
- Fill the properties' content enclosed by "< >" or modify existing one.
See how short video below
Microservice models comprise three parts:
- A server definition
- A service definition¸
- One or several collection definition.
Web application models comprise three parts
- A server definition (the http server hosting the application code).
- An application definition.
- One or several collection definition.
Mixed models comprise 4 parts
A model file may contain a definition for a web service and a definition for a microservice. This can be specified when a microservice is hooked to a user interface. In that case, a model file will include:
- A server definition
- A service definition
- An application definition
- One or several collection definition
2. Generate Code
Actually only two (2) code generator scenarios are provided, other packages and new updates can be obtained from magiccodegenerator.com:
- mongoose-mongoDB: this will create a mongoose+mongoDB microservice.
- Bootstrap-Angular: this will create an angular client web application.
To generate code from a model specification, click on the right mouse button over the model's file name in the
file directory and select Magic Code Generator as illustrated in the animation below.
Model
As illustrated in the model below, the directory path where the code will be generated is specified in the "Start"
function
import {Model, Start} from 'magicCode.js';
@Model([
{
// Server specifications
server: {
name: 'Magic Code Server',
description: 'Project to test the MongoDB back-end',
documentation: 'openAPI 3.0',
contact: 'alberteinstein@magiccodegenerator.com',
version: '1.0',
path: '/', // Main server entry point
type: 'NodeJS', // server type: nodeJS, Apache
host: 'localhost', // host name
port: '3000', // server port
url: 'http://localhost',// main server endpoint
cors: {
origin:'*',
methods: "['GET','POST','DELETE','UPDATE','PUT']"
},
authentication: {
type: 'JWTToken',
key: 'ibLX-mf#R0ujo`Pg/[HG^5(bJ]&fWg',
algorithm: 'HS256',
expiresIn: '2h',
redirect: 'http://localhost:8084'
},
interface: {
rest: true,
graphql: {
graphiql: true
}
}
},
},
{
// service specifications
service: {
path: '/user', // Service endpoint
name: 'myClass', // WARNING this property name should
// be identical to the class name at
// the end of this document and in
// 'Start'.
description:'Service used to test authenticated MongoDB-mongoose',
paginate: true,
storage: {
type: 'noSQL',
database: 'mongoDB',
ORM: 'mongoose',
connector: 'mongodb+srv://albert:Eintein@cluster0.4y0za.mongodb.net/test?retryWrites=true&w=majority',
}
}
},
{
application: {
type: 'angular_bootstrap',
}
},
{
collections: [
{
// Collection specifications
// you can define more than one collection per model
// each collection is defined as an object in the Array of objects
endpoint: 'testclass',
name: 'testClass',
model: {
id: { type: String, label:'id', required: true},
name: {type:String, label: 'Name', index: true, required: true}
},
methods: {
get: true,
put: true,
post: true,
delete: true
},
views: {
form: true,
list: true
}
}
]
}
])
class myClass {}
Start(myClass,'d:/testMagicCode');
Each model file should contain at least these mandatory sections:
- A server section
- Either a service or application section, or both
- A collections section containing one or several collection data definition.
1 - The server section
An online documentation is available to each generated server code. To access the online documentation use the following url:
http(s)://domainName:portNumber/api-docs/
DomainNumber is set with the server.host property, the portNumber is set with the server.port. After the domain name and port number, the url should be set with the server.path followed by /api-docs/.
The produced swagger user interface ca be used to test the generated service.
server internals
All REST calls are received by the index.js file (Dispatcher) defined in the server section. At the moment, only the pair nodejs with express.js are supported as request dispatcher.
Dispatched REST calls are sent to the class.js or class.ts file. generated from the service section. Service developers can add a pre process and post process executed code in the addon.js or addon.ts_ file.
The server section is used to define the type of microservice host. At the moment only nodejs is supported, but in the future more host like nginx or Apache will be supported.
The generated code is based on the following NodeJS modules:
- express.js as request dispatcher-middleware.
- it is using Express for authentication
server: {
name: 'Magic Code Server',
description: 'Project to test the MongoDB back-end',
documentation: 'openAPI 3.0',
contact: 'albert@magiccodegenerator.com',
version: '1.0',
path: '/', // Main server entry point
type: 'NodeJS', // server type: nodeJS, Apache
host: 'localhost', // host name
port: '3000', // server port
url: 'http://localhost',// main server endpoint
cors: {
origin:'*',
methods: "['GET','POST','DELETE','UPDATE','PUT']"
},
authentication: {
type: 'JWTToken',
key: 'ibLX-mf#R0ujo`Pg/[HG^5(bJ]&fWg', // is a Location pointing to a file for
// RSA encryption or a simple key.
algorithm: 'HS256',
expiresIn: '2h',
redirect: 'http://localhost:8084'
},
interface: {
rest: true,
graphql: {
graphiql: true
}
}
},
Property |
Description |
host |
the host name |
description |
A short description of the microserveice |
documentation |
indicates if a swagger (openAPI) file and interface is created. |
contact |
email of the model author |
version |
model version |
path |
the main entry point to the server. Usually it is '/'. |
type |
the host server type. Actually can only be nodejs |
port |
the port nodeJS listen for incoming REST calls |
url |
The reference URL for client applications |
cors |
cors sub-section - see detailed documentation below |
authentication |
authentication sub-section - see detailed documentation below |
interface |
interface sub section - see detailed documentation below |
The "cors" sub section
For more information about cors see: cors tutorial a guide to cross origin resource sharing
Property |
Description |
origin |
An array of domains or any origin specified by the * character |
methods |
An array of allowed access to REST methods |
The "authentication" sub section
For more information about JWT Token authentication protocol see: JWT: The Complete Guide to JSON Web Tokens.
Another excellent source about the differences between HMAC and RSA: RS256 vs HS256 What's The Difference?
Property |
Description |
type |
Identification type. Actually, only JWT is supported |
key |
Key used to sign the JWT token data. |
algorithm |
encryption algorithem. Can be HS256 or RS256 |
exprireIn |
Valid JWT token duration time |
redirect |
URL indicating the redirected URL if the user is authnticated. This url will receive a JWT token in the HTTP "authorization" header |
The "interface" sub section
For more information about the REST interface see: What is REST?
For more information about graphQL see: A query language for your API.
We are currently analysing to support event based interfaces like the ones provided by kafka and firebase.
Property |
Description |
rest |
Implementing a REST interface for CRUD operation for a collection model defined in the collections section |
graphql |
implementation of a grahQL interface. Currently not supported. For the next release |
2 - The service section used to create a microservice
The service section is used to create a microservice running on a nodeJS server. The micrososervice endpoint react to HTTP verbs to create the following functions:
- HTTP GET: to get a particular data set from a collection
- HTTP PUT: to update a particular data set in a collection.
- HTTP POST: to store a particular data set in a collection.
- HTTP DELETE: to delete a particular data set in a collection.
{
// service specifications
service: {
path: '/user', // Service endpoint
name: 'myClass', // WARNING this property name should
// be identical to the class name at
// the end of this document and in
// 'Start'.
description:'Service used to test authenticated MongoDB-mongoose',
paginate: true,
storage: {
type: 'noSQL',
database: 'mongoDB',
ORM: 'mongoose',
connector: 'mongodb+srv://albert:Eintein@cluster0.4y0za.mongodb.net/test?retryWrites=true&w=majority',
}
}
Property |
Description |
path |
service endpoint (Ex: /api) |
name |
service name, should be identical to the class name |
description |
service description |
paginate |
specifies if pagination is to be included for limiting returned records |
storage |
the "storage" sub section - see detailed documentation below |
The "storage" sub section
The storage sub section is dependent onthe type of database used. The properties will be different
MongoDB database "type"
storage: {
type: 'noSQL',
database: 'mongoDB',
ORM: 'mongoose',
connector: 'mongodb+srv://albert:Eintein@cluster0.4y0za.mongodb.net/test?retryWrites=true&w=majority',
}
Property |
Description |
type |
Should be "noSQL". it is case sensitive |
database |
set to "mongoDB" |
ORM |
in fact for noSQL server this is an ODM but to reduced complexity between SQL and noSQL, it set to "orm" for both. It is case sensitive |
connector |
a string used to connect to a mongoDB database |
The SQLite database "type"
storage: {
type: 'SQL',
database: 'sqlite',
ORM: 'sequelize',
connector: 'sqlite::memory:'
}
Property |
Description |
type |
Should be "SQL". it is case sensitive |
database |
set to "sqlite" |
ORM |
specified as 'sequelize' |
connector |
a string used to connect to a sqlite database. It can be a file path or 'sqlite::memory:' |
3 - The application section used to create a web application
Modern web applications stand on frameworks such as React, Angular, Vue, etc., and display frameworks
such as Material or Bootstrap. Display frameworks complement the application frameworks. Thus, in the Magic
Code context, they come in pairs like, for example, angular-bootstrap, which is based on the Angular web
application framework and Bootstrap used as the display framework.
The application section is defined as a javascript object as illustrated in the example below:
{
application: {
type: 'angular_bootstrap'
}
},
property |
Description |
type |
Specify an application-display framework pair, like for example, angular_bootstrap. The convention being that the application frameowrk comes first and the display framework comes second. Both being connected with an underscore. Actually, only the angular_bootstrap application pack is provided. regisred users can get additional packs like, for example: angular_dashboard, teammap, etc. |
4 - The collection section to define data structure
{
// Collection specifications
// you can define more than one collection per model
// each collection is defined as an object in the Array of objects
endpoint: 'testclass',
name: 'testClass',
model: {
id: { type: String, label:'id', required: true},
name: {type:String, label: 'Name', index: true, required: true}
},
methods: {
get: true,
put: true,
post: true,
delete: true
},
views: {
form: true,
list: true
}
}
Property |
Description |
name |
collection name |
model |
model object defining data structure |
methods |
REST methods activation - deactivation |
views |
Generated client views |
Collection content model types
The model section is used to define the structure of each record in a collection. These types are valid
- String
- Number
- Date
- Boolean
String
Property |
Description |
type |
String type, example: {name: {type: String} |
index |
Indicates if this property is used as an index, takes a value a boolean, example: { index: true } |
unique |
indicates if this property has a unique value in an index, takes a boolean as value, example: {unique: true } |
Number
property |
Description |
type |
Number type, example: {type: Number } |
index |
Indicates if this property is used as an index, takes a value a boolean, example: { index: true } |
unique |
indicates if this property has a unique value in an index, takes a boolean as value, example: {unique: true } |
Date
property |
description |
type |
Number type, example: {type: Date } |
index |
Indicates if this property is used as an index, takes a value a boolean, example: { index: true } |
unique |
indicates if this property has a unique value in an index, takes a boolean as value, example: {unique: true } |
Boolean
property |
description |
type |
Boolean type, example: {type: Boolean } |
index |
Indicates if this property is used as an index, takes a value a boolean, example: { index: true } |
unique |
indicates if this property has a unique value in an index, takes a boolean as value, example: {unique: true } |
Pre and post process class
In the server-side service, before data are store through an ODM middleware, pre and post process function are invoked in the class.
- the preProcess function is invoked before data are stored in the collection. This allows to perform any processing on the data before storing it.
- the postProcess function is invoked after data are stored in the collection. This allows to perform some action after data are stored in the collection. For example to send an email to collaborators or send an event to an external process.
Client side Applications
At the moment, the sole framework supported by Magic Code is Angular but we will support React as this framework is currently a work in progress.
These two framworks are stucturing web applications running in browsers. Rendition frameworks like Boostrap or Material provide adaptatio to different device form format, they provide "responsive behavior". Thus, code generated by Magic Code automatically construct web applications based on:
- Web application frameworks like Angular, React or Vue. Actually, only Angular is supported by Magic Code but React is a work in progress.
- Rendition frameworks like Bootstrap or Material offering a responsive behavior and a display style.
A package is a set of a client-side web application framworks and a server-side web service. Thus, with a single model (an mdl file), both a web application and a backend service code is generated. Some package are provided with the Visual studio code extension, others are available only to registered users
Generated web applications are displayed, after the generation process, in a visual studio code IDE. To run the web application, the following operations are required:
- npm init: to download the module dependencies.
- ng serve: to run and render the web application in a browser.
The base application framework such as angular or react should be previously installed.
The following web applications packages are either a work in progress or already available:
- angular_bootstrap: Magic Code generates forms and lists (i.e tables) based on Angular and Bootstrap. Forms and lists are in the form of angular components. (provided with the visual studio extension.).
- angular_bootstrap_dashboard: Is it the same package as just previously mentionned but the generated code is aggregated in a dashboard acting as a component container. (provided to registered users).
- angular_material: The code is identical to the angular_bootstrap package but, in that case, bootstrap is replaced by Material.
- angular_material_dashboard: identical to the bootstrap package but, this time, based on material as rentition framework.
1. Client-side angular_bootstrap Web application
This package allows to generate forms and lists (i.e tables) from a Magic Code model. It is based, as its name indicates, on Angular and Bootstrap. Form's layout is vertical but can be modified to better suits the needs of the application.
{
application: {
name: "<insert your web app nae here>",
type: 'angular_bootstrap',
}
},
2. Client-side angular_bootstrap_dashboard
This package generates Forms and lists (i.e tables) based on angular and Bootstrap but also aggregate the produced components in a dashboard container component. Forms and lists routes are automatically included in a menu facilitating navigation. In the next version of this package, we will add additional parameters to configure the dashboard.
{
application: {
name: "<insert your web app nae here>",
type: 'angular_bootstrap_dashboard',
}
},
3. Client-side angular_material
This package generates Forms and lists (i.e tables) based on angular and Material.
{
application: {
name: "<insert your web app nae here>",
type: 'angular_material',
}
},
4. Client-side angular_material_dashboard
his package generates Forms and lists (i.e tables) based on angular and Material but also aggregate the produced components in a dashboard container component. Forms and lists routes are automatically included in a menu facilitating navigation. In the next version of this package, we will add additional parameters to configure the dashboard.
{
application: {
name: "<insert your web app nae here>",
type: 'angular_material_dashboard',
}
},
Server-side web services
Code generated on the server side are based on the REST protocol. These services support Basic CRUD (create, read, update, delete) operations. They are best packaged as microservice component even if fat applications can be created. However, microservices are more scalable and easier to maintain. A dockerfile is automatically generated and incorporated into the final set of files composing the project. This makes it easier to package the service in a container.
Actually Magic Code generates code for the following ORM:
- Mongoose: A well known ORM used to interact with the mongoDB databases.
- Sequelize: A well known ORM used to interact with several SQL databases (Postgres, mySQL, MariaDB, SQLLite, MsSQL)
1 - noSQL (MongoDB) microservice model definition
This package is included in the current installation.
Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Mongoose supports both promises and callbacks.
The current Mongoose version included in this Visual Studio Code extension is version 5.11.17 (see NPM mongoose ).
{
// service specifications
service: {
path: '/',
name: 'myClass', // should be identical to the class name
type: 'mongoose',
connector: '<Include here your dataBase connector>'
}
/*
The name property in the service definition above
should be identical to the class name below (in this example: myClass):
*/
class myClass {} // class name
Start(myClass,'d:/testMagicCode'); // class name, destination directory
The MongoDB microservice connection requires only these properties.
Property |
Description |
path |
REST service endpoint |
name |
Service name. CAUTION: this property value sould be identical to the class definition and the class parameter in the start function (see previous model example above). |
type |
mongoose. it is an Object Definition Model running in NodeJS to access a MongoDB database. |
connector |
a string used to connect to a mongoDB database |
The model definition is specified as metadata introduced by a @model statement. It is followed by a class statement. Then the start statement takes as parameters the destination directory. More specifically, inside the target directory, in the server directory:
- index.js: the main entry point with a dispatcher based on express.js
- classes.js: a file edited by developers to handle pre and post processes.
- addon.js: a file created only once in the project. Contains a template for a pre and post process.
- model.js: the collection data model used by the Object Model Middleware (Ex: Mongoose for Mongo DB servers, typeORM or Sequilize for SQL servers)).
- package.json: a file containing module dependencies for the project.
- readme.md : a documentation file about the generated code.
2 - SQL microservice model definition
This package is currently in test, it should be available soon.
Sequelize is a promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite and Microsoft SQL Server. It features solid transaction support, relations, eager and lazy loading, read replication and more.
Sequelize follows Semantic Versioning and supports Node v10 and above.
New to Sequelize? Take a look at the Tutorials and Guides. You might also be interested in the API Reference.
The current release in this package is version 6.5.0 (see NPM sequelize )
You can find the detailed changelog here.
{
// service specifications
service: {
path: '/',
name: 'myClass', // should be identical to the class name
type: 'sequelize', // should be sequelize
port: '1234', // port to communicate with SQL server
database: 'mysql', // can be pany of the supported databases
connector: '<Include here your dataBase connector>',
// specific sql database parameters
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
/*
The name property in the service definition above
should be identical to the class name below (in this example: myClass):
*/
class myClass {} // class name
Start(myClass,'d:/testMagicCode'); // class name, destination directory
The Sequelize microservice connection requires only these properties
Property |
Description |
path |
REST service endpoint |
name |
Service name. CAUTION: this property value sould be identical to the class definition and the class parameter in the start function (see previous model example ). |
type |
sequelize It is an Object Definition Model running in NodeJS to access a SQL database. |
port |
databse port connection |
database |
database type, could be: postgres, mariadb, mysql, sqllite, mssql. |
connector |
a string used to connect to a mongoDB database |
pool |
parameters specific to the database |
The model definition is specified as metadata introduced by a @model statement. It is followed by a class statement. Then the start statement takes as parameters:
- the class name
- the output file path where the code is to be stored.
The following files are created by magic Code:
- index.js: the main entry point with a dispatcher based on express.js
- classes.js: a file edited by developers to handle pre and post processes.
- addon.js: a file created only once in the project. Contains a template for a pre and post process.
- model.js: the collection data model used to create the Object Model for Sequilize.
- package.json: a file containing module dependencies for the project.
- readme.md : a documentation file about the generated code.
Copyright
Didier PH Martin 2017-2022