@mnemotix/cortex-core
v0.0.14
Published
Cortex Core -----------
Downloads
5
Keywords
Readme
Cortex Core
This is the main bundle that gathering all convenient toolkits to :
- Fastly start a new Cortex-based application.
- Create a new sharable Cortex bundle to share with every Cortex-based application.
Principle
The main idea to remember is that a Cortex-based application is no more than a bunch of bundles, costumized or not, cleverly placed in a React application and linked each other thanks to the excellent concept of dynamic routing from React Router V4.
Cortex-based application concepts
Skeleton
client/
entrypoint.js --> The client entrypoint for webpack
Application.js --> Extends a Cortex Application.
routes.js --> A list of Cortex Routes
schema/
schema.json --> Autogenerated JSON schema (https://json-schema.org/)
components/
... --> All application related components
config/
environment.js --> List of environment variables
resources/
... --> All images/icons/fonts stuff.
locales/
fr/
labels.json --> A i18next label file.
...
server/
entrypoint.js --> The server entrypoint to start with node.
schema/
schemaBuilder.js --> The datamodel schema definition (that generates the two following schema files)
schema.graphql --> Autogenerated GraphQL schema
schema.json --> Autogenerated JSON introspection schema (useful for Idea GraphQL plugin)
datastores/
Session.js --> Extends a SynaptixSession
styling/
semantic.less --> Copy of semantic-ui-less/semantic.less (Needed to the compiler)
theme.config --> SemanticUI theme config definition
theme/
... All less variables and less overrides files.
webpack.config.js
webpack.production.config.js
package.json
Server side initialization steps.
1. Defining and building a schema
Defining a schema consists on expose a server/schema/schemaBuilder.js
defined as following :
import {SchemaBuilder} from '@mnemotix/cortex-core';
export default new SchemaBuilder({
typeDefs: [] /* An array of GraphQL types (See Synaptix.js) */,
resolvers: {} /* An object of GraphQL resolvers (See Synaptix.js) */,
modelDefinitions: [] /* A list of ModelDefinitionAbstract (See Synaptix.js) */
});
For example if you want to use the FOAF ontology, Synaptix.js gives all resources defining the builder like so:
import {SchemaBuilder} from '@mnemotix/cortex-core';
import {Ontologies, mergeResolvers} from '@mnemotix/synaptix.js';
export default new SchemaBuilder({
typeDefs: [].concat(Ontologies.foaf.schema.Types, Ontologies.foaf.schema.Mutations),
resolvers: mergeResolvers(Ontologies.foaf.resolvers.Types, Ontologies.foaf.resolvers.Mutations),
modelDefinitions: Ontologies.foaf.ModelDefinitions
});
Of course, this is highly customizable. You can define your own ontology. Please take a look on the standard ontologies defined in Synaptix.js to implement one.
The resulting schema files will be automatically generated a launch time (see entrypoint section).
server/schema/schema.graphql
is the default GraphQL schema used by GraphQL server ans Relay compiler.server/schema/schema.json
is the introspection schema useful for IntelliJ Idea GraphQL Pluginclient/schema/schema.json
is the JSON Schema (https://json-schema.org) usefull for generating forms (see @mnemotix/cortex-form bundle)
2. Create an entrypoint
The next step consists on defining a server entrypoint in server/entrypoint.js
.
The launchApplication() magic function.
In this entrypoint you just have to call plug-n-play function to start the app.
import {launchApplication} from '@mnemotix/cortex-core';
launchApplication({
Package, // This is the object related to package.json (needs a json-loader on Webpack)
webpackDevConfig, //This is the Webpack config file.
schemaBuilder, // This is the schema builder of the application
bundles, //This list of bundles path (so as import/require path) used in the application.
generateGraphQLEndpoints, //GraphQL endpoints (detailed below)
generateNetworkLayer //This is the network layer used to communicate with Synaptix middleware bus.
}).then(() => {
/* app launched */
});
If you look to this function, you will see that it :
- Print a beautiful banner.
- Initialize and concatenate all environment variables defined in
[bundle]/config/environment.js
. See environment section - Initiate a connection to the Synaptix middleware bus
- Setup an ExpressJS server.
- Setup a Socket.IO websocket server binded to ExpressJS server.
- Setup all ExpressJS server middlewares located in
[bundle]/server/middlewares/index.js
. See middleware section. - Setup a default SSO login/register endpoint. See graphQL endpoints section
- Setup GraphQL endpoints
- Initialize the Synaptix middleware adaptor. See Synaptix adaptor section.
Synaptix Adaptor
To interact with Synaptix middleware, the application needs to define three classes:
The Synaptix Adaptor
Located in server/datastores/Adapter.js
import {SynaptixAdapter} from '@mnemotix/cortex-core';
export default class Adapter extends SynaptixAdapter {
init(){
/* Called a startup. Usefull for example to instantiate application specific context connections */
}
}
Note that if no initialisation is needed you can directly use the Cortex-Core SynaptixAdapter
.
The Synaptix Session
Located in server/datastores/Session.js
this class is instantiated for each GraphQL request (and more generally for all client user request).
This is in that class that you can add application specific middleware resolutions.
import {SynaptixSession} from '@mnemotix/cortex-core';
export default class Session extends SynaptixSession {
createForExampleSpecificObject(){
/* Retrieve here the services to communicate with Synatix middleware. See Synaptix.js.*/
}
}
Instantiation of a network layer
The network layer is the lowest layer to communicate with Synaptix Middleware bus.
For example to connect the bus using AMQP, use a NetworkLayerAMQP
class.
import {NetworkLayerAMQP} from '@mnemotix/synaptix.js';
import {SynaptixAdapter} from '@mnemotix/cortex-core';
import {Session} from './datastores/synaptix/Session'; //See preceding section
const amqpURL = `amqp://${process.env.RABBITMQ_LOGIN}:${process.env.RABBITMQ_PASSWORD}@${process.env.RABBITMQ_HOST}:${process.env.RABBITMQ_PORT}`;
const networkLayer = new NetworkLayerAMQP(amqpURL, process.env.RABBITMQ_EXCHANGE_NAME);
const datastoreAdapter = new SynaptixAdapter(schemaBuilder.generateModelDefinitionsRegister(), networkLayer, Session);
GraphQL Endpoints
An application can expose different GraphQL endpoints (Ex: one for the application, and one for a public API).
let graphQLEndpoints = [
{
endpointURI: '/graphql', // The exposed URL
graphQLSchema: schemaBuilder.generateExecutableSchema({ // This method of SchemaBuilder is a quick way to generate an executable GraphQL schema and the related physical files.
printGraphQLSchemaPath: path.join(__dirname, 'schema/schema.graphql'), // Points to [application]/server/schema/schema.graphql
printJSONSchemaPath: path.join(__dirname, 'schema/schema.json'), // Points to [application]/server/schema/schema.json
printJSONSchemaDotOrgPath: path.join(__dirname, '../client/schema/schema.json') // Points to [application]/client/schema/schema.json
}),
datastoreAdapter // The instance of SynaptixAdaptor (See preceding section)
}
];
All together
For example, your entrypoint could look like this :
import path from 'path';
import Package from '../../package.json';
import webpackDevConfig from '../webpack.config';
import {SynaptixAdapter, launchApplication} from '@mnemotix/cortex-core';
import {NetworkLayerAMQP} from '@mnemotix/synaptix.js';
import Session from "./datastores/Session";
import schemaBuilder from "./schema/schemaBuilder";
const bundles = [
path.resolve(__dirname, '../'),
"@mnemotix/cortex-core",
"@mnemotix/cortex-addressbook",
"@mnemotix/cortex-profile",
"@mnemotix/cortex-uploader",
"@mnemotix/cortex-finder"
];
launchApplication({
Package,
schemaBuilder,
webpackDevConfig,
bundles,
generateNetworkLayer: () => {
const amqpURL = `amqp://${process.env.RABBITMQ_LOGIN}:${process.env.RABBITMQ_PASSWORD}@${process.env.RABBITMQ_HOST}:${process.env.RABBITMQ_PORT}`;
return new NetworkLayerAMQP(amqpURL, process.env.RABBITMQ_EXCHANGE_NAME);
},
generateGraphQLEndpoints: (networkLayer) => {
const datastoreAdapter = new SynaptixAdapter(schemaBuilder.generateModelDefinitionsRegister(), networkLayer, Session);
return [
{
endpointURI: '/graphql',
graphQLSchema: schemaBuilder.generateExecutableSchema({
printGraphQLSchemaPath: path.join(__dirname, 'schema/schema.graphql'), /* Optionnal to print schema.graphql */
printJSONSchemaPath: path.join(__dirname, 'schema/schema.json'), /* Optionnal to print schema.json */
printJSONSchemaDotOrgPath: path.join(__dirname, '../client/schema/schema.json') /* Optionnal to print schema.json */
}),
datastoreAdapter
}
];
}
})
.then()
.catch(error => console.log(error));