diff --git a/README.md b/README.md index 52c150c..1e49970 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ An example is "auth". All code related to authentication and users, could go int ## Systemic Architecture -After an extensive development career looking for the best methods, and trying to keep up with the rate of change, eventually one will stumble upon the reality that nearly systems follows predictable structures. One of these structures follows the natural course of how a parts within a system works together, as well as where the complicated and easy parts are. The trouble in most systems is that complexity and known troublesome code concepts are embedded throughout the application rather than putting them in well-defined areas that can be understood and maintained. +After an extensive development career looking for the best methods, and trying to keep up with the rate of change, eventually one will stumble upon the reality that nearly systems follow predictable structures. One of these structures follows the natural course of how a parts within a system works together, as well as where the complicated and easy parts are. The trouble in most systems is that complexity and known troublesome code concepts are embedded throughout the application rather than putting them in well-defined areas that can be understood and maintained. A well organized system tends to be defined in "layers", where parts of the system are designed to speak to certain other parts of the system. @@ -50,24 +50,18 @@ When a system is designed from the start using distinct layers, it makes it real There are four primary layers in any system, and these are the layers that Node In Layers comes out of the box with. They are the following: -- Dependencies +- Globals - Services - Features - Entries -## Dependencies - The Special Layer +## Globals - The Everywhere Layer -Node In Layers is a dependency injection framework as well as an opinionated framework that heavily suggests how code should be organized and initiated. There are dependencies that exist throughout a system that every single layer uses. Configurations, environment variables, etc. +Node In Layers is a dependency injection framework as well as an opinionated framework that heavily suggests how code should be organized and initiated. There are items that exist throughout a system that every single layer uses. Configurations, environment variables, etc. -Every application has dependencies that are used throughout the application. Here are some common ones: +Unlike every other layer in Node In Layers, this "globals" layer is a special "layer." This layer is made widely available throughout the system, and has no namespaces. (Therefore be careful of collisions). -- Configurations -- Logger -- Environmental Constants - -Unlike every other layer in Node In Layers, this "dependencies" layer is a special "layer." This layer is made widely available throughout the system, and has no namespaces. (Therefore be careful of collisions). - -Simply create a constructor function in an apps `dependencies.ts` file, and it will create the dependencies at the beginning of runtime, and then distributed up the app stack. +Simply create a constructor function in an apps `globals.ts` file, and it will create the dependencies at the beginning of runtime, and then distributed up the app stack. ### Services - The Outside World Communicators diff --git a/package.json b/package.json index bbfa06d..ced596d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@node-in-layers/core", "type": "module", - "version": "1.1.2", + "version": "1.1.3", "description": "The core library for the Node In Layers rapid web development framework.", "main": "index.js", "scripts": { diff --git a/src/entries.ts b/src/entries.ts index 9294c6d..4920dd0 100644 --- a/src/entries.ts +++ b/src/entries.ts @@ -1,5 +1,5 @@ import omit from 'lodash/omit.js' -import * as dependenciesApp from './dependencies.js' +import * as globalsApp from './globals.js' import * as layersApp from './layers.js' import { Config, CoreNamespace, NodeDependencies } from './types.js' @@ -8,23 +8,23 @@ const loadSystem = async (args: { config?: TConfig nodeOverrides?: NodeDependencies }) => { - const depServices = dependenciesApp.services.create({ + const globalServices = globalsApp.services.create({ environment: args.environment, workingDirectory: process.cwd(), nodeOverrides: args.nodeOverrides, }) - const depFeatures = dependenciesApp.features.create({ + const globalFeatures = globalsApp.features.create({ services: { - [dependenciesApp.name]: depServices, + [globalsApp.name]: globalServices, }, }) - const dependencies = await depFeatures.loadDependencies( + const globals = await globalFeatures.loadGlobals( args.config || args.environment ) const layersServices = layersApp.services.create() const layersFeatures = layersApp.features.create({ - ...dependencies, + ...globals, services: { [layersApp.name]: layersServices, }, diff --git a/src/dependencies.ts b/src/globals.ts similarity index 81% rename from src/dependencies.ts rename to src/globals.ts index 75838bd..9087182 100644 --- a/src/dependencies.ts +++ b/src/globals.ts @@ -15,15 +15,15 @@ import { } from './types.js' import { memoizeValue } from './utils.js' -const name = CoreNamespace.dependencies +const name = CoreNamespace.globals -type DependenciesServicesProps = Readonly<{ +type GlobalsServicesProps = Readonly<{ environment: string workingDirectory: string nodeOverrides?: Partial }> -type DependenciesServices = Readonly<{ +type GlobalsServices = Readonly<{ loadConfig: () => Promise configureLogging: (config: TConfig) => RootLogger getConstants: () => { @@ -31,16 +31,16 @@ type DependenciesServices = Readonly<{ environment: string } getNodeServices: () => NodeDependencies - getDependencies: ( - commonDependencies: CommonContext, + getGlobals: ( + commonGlobals: CommonContext, app: App ) => Promise> }> -type DependenciesFeatures = Readonly<{ - loadDependencies: = object>( +type GlobalsFeatures = Readonly<{ + loadGlobals: = object>( environmentOrConfig: string | TConfig - ) => Promise & TDependencies> + ) => Promise & TGlobals> }> const services = { @@ -48,7 +48,7 @@ const services = { environment, workingDirectory, nodeOverrides, - }: DependenciesServicesProps): DependenciesServices => { + }: GlobalsServicesProps): GlobalsServices => { const useFullLogFormat = () => { const originalFactory = log.methodFactory // eslint-disable-next-line functional/immutable-data @@ -170,12 +170,9 @@ const services = { ) } - const getDependencies = ( - commonDependencies: CommonContext, - app: App - ) => { - if (app.dependencies) { - return app.dependencies.create(commonDependencies) + const getGlobals = (commonGlobals: CommonContext, app: App) => { + if (app.globals) { + return app.globals.create(commonGlobals) } return Promise.resolve({}) } @@ -185,7 +182,7 @@ const services = { getConstants, configureLogging, getNodeServices, - getDependencies, + getGlobals, } }, } @@ -195,12 +192,12 @@ const features = { services, }: { services: { - [CoreNamespace.dependencies]: DependenciesServices + [CoreNamespace.globals]: GlobalsServices } - }): DependenciesFeatures => { + }): GlobalsFeatures => { const ourServices = get(services, name) - const loadDependencies = async ( + const loadGlobals = async ( environmentOrConfig: string | TConfig ) => { const config: TConfig = await (isConfig(environmentOrConfig) @@ -208,26 +205,24 @@ const features = { : ourServices.loadConfig()) validateConfig(config) - const commonDependencies = { + const commonGlobals = { config, log: ourServices.configureLogging(config), node: ourServices.getNodeServices(), constants: ourServices.getConstants(), } - const dependencies: TDependencies = await config[ - CoreNamespace.root - ].apps.reduce( + const globals: TGlobals = await config[CoreNamespace.root].apps.reduce( async (accP, app) => { const acc = await accP - const dep = await ourServices.getDependencies(commonDependencies, app) + const dep = await ourServices.getGlobals(commonGlobals, app) return merge(acc, dep) }, - Promise.resolve({} as TDependencies) + Promise.resolve({} as TGlobals) ) - return merge(commonDependencies, dependencies) + return merge(commonGlobals, globals) } return { - loadDependencies, + loadGlobals, } }, } diff --git a/src/layers.ts b/src/layers.ts index 61c3666..6f3e357 100644 --- a/src/layers.ts +++ b/src/layers.ts @@ -53,10 +53,10 @@ const features = { const loadLayers = () => { const layersInOrder = context.config[CoreNamespace.root].layerOrder const antiLayers = getLayersUnavailable(layersInOrder) - const ignoreLayers = [CoreNamespace.layers, CoreNamespace.dependencies] + const ignoreLayers = [CoreNamespace.layers, CoreNamespace.globals] .map(l => `services.${l}`) .concat( - [CoreNamespace.layers, CoreNamespace.dependencies].map( + [CoreNamespace.layers, CoreNamespace.globals].map( l => `features.${l}` ) ) diff --git a/src/types.ts b/src/types.ts index 6e49a67..1eb56f5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -55,11 +55,12 @@ type RootLogger = Readonly<{ enum CoreNamespace { root = '@node-in-layers/core', - dependencies = '@node-in-layers/core/dependencies', + globals = '@node-in-layers/core/globals', layers = '@node-in-layers/core/layers', } type Config = Readonly<{ + systemName: string environment: string [CoreNamespace.root]: { logLevel: LogLevelNames @@ -71,10 +72,10 @@ type Config = Readonly<{ type AppLayer< TConfig extends Config = Config, - TDependencies extends object = object, + TContext extends object = object, TLayer extends object = object, > = Readonly<{ - create: (dependencies: LayerContext) => TLayer + create: (dependencies: LayerContext) => TLayer }> type NodeDependencies = Readonly<{ @@ -93,67 +94,65 @@ type CommonContext = Readonly<{ type LayerContext< TConfig extends Config = Config, - TDependencies extends object = object, -> = CommonContext & TDependencies + TContext extends object = object, +> = CommonContext & TContext type ServicesContext< TConfig extends Config = Config, TServices extends object = object, - TDependencies extends object = object, + TContext extends object = object, > = LayerContext< TConfig, { services: TServices - } & TDependencies + } & TContext > type ServicesLayerFactory< TConfig extends Config = Config, TServices extends object = object, - TDependencies extends object = object, + TContext extends object = object, TLayer extends object = object, > = Readonly<{ - create: ( - context: ServicesContext - ) => TLayer + create: (context: ServicesContext) => TLayer }> -type DependenciesLayer< +type GlobalsLayer< TConfig extends Config = Config, - TDependencies extends object = object, + TGlobals extends object = object, > = Readonly<{ - create: (context: CommonContext) => Promise + create: (context: CommonContext) => Promise }> type FeaturesContext< TConfig extends Config = Config, TServices extends object = object, TFeatures extends object = object, - TDependencies extends object = object, + TGlobals extends object = object, > = LayerContext< TConfig, { services: TServices features: TFeatures - } & TDependencies + } & TGlobals > type FeaturesLayerFactory< TConfig extends Config = Config, - TDependencies extends object = object, + TContext extends object = object, TServices extends object = object, TFeatures extends object = object, TLayer extends object = object, > = Readonly<{ create: ( - context: FeaturesContext + context: FeaturesContext ) => TLayer }> type System< TConfig extends Config = Config, - TFeatures extends object = object, TServices extends object = object, + TFeatures extends object = object, > = CommonContext & { services: TServices features: TFeatures @@ -163,7 +162,7 @@ type App = Readonly<{ name: string services?: AppLayer features?: AppLayer - dependencies?: DependenciesLayer + globals?: GlobalsLayer }> export { diff --git a/test/mocks.ts b/test/mocks.ts index 3ba36fb..850bf2b 100644 --- a/test/mocks.ts +++ b/test/mocks.ts @@ -57,6 +57,7 @@ const deleteUnitTestConfig = () => { const validConfig1 = () => ({ environment: 'unit-test', + systemName: 'nil-core', [CoreNamespace.root]: { apps: [ { @@ -71,6 +72,7 @@ const validConfig1 = () => ({ const validConfig2 = () => ({ environment: 'unit-test', + systemName: 'nil-core', [CoreNamespace.root]: { apps: [ { @@ -97,6 +99,7 @@ const validConfig2 = () => ({ const validConfig3 = () => ({ environment: 'unit-test', + systemName: 'nil-core', [CoreNamespace.root]: { apps: [ { diff --git a/test/src/dependencies.test.ts b/test/src/globals.test.ts similarity index 89% rename from test/src/dependencies.test.ts rename to test/src/globals.test.ts index 4602af7..f95cf45 100644 --- a/test/src/dependencies.test.ts +++ b/test/src/globals.test.ts @@ -4,13 +4,11 @@ import * as chai from 'chai' import asPromised from 'chai-as-promised' import { createMockFs, - validConfig3, - validConfig2, validConfig1, deleteUnitTestConfig, writeUnitTestConfig, } from '../mocks' -import { services, features } from '../../src/dependencies' +import { services, features } from '../../src/globals' chai.use(asPromised) @@ -31,7 +29,7 @@ const _setup = () => { } } -describe('/src/dependencies.ts', () => { +describe('/src/globals.ts', () => { describe('#services.create()', () => {}) describe('#features.create()', () => { describe('#loadLayers()', () => {})