Skip to content

Commit 4be95ca

Browse files
committed
Update README
1 parent d872272 commit 4be95ca

File tree

1 file changed

+67
-262
lines changed

1 file changed

+67
-262
lines changed

README.md

+67-262
Original file line numberDiff line numberDiff line change
@@ -5,296 +5,101 @@ _A semantic dependency injection framework_
55
[![Build Status](https://travis-ci.org/LinkedSoftwareDependencies/Components.js.svg?branch=master)](https://travis-ci.org/LinkedSoftwareDependencies/Components.js)
66
[![npm version](https://badge.fury.io/js/lsd-components.svg)](https://www.npmjs.com/package/lsd-components)
77

8-
## Installation
8+
This repository contains the source code of Components.js.
9+
Full documentation on its usage can be found at http://componentsjs.readthedocs.io/.
910

10-
```bash
11-
$ [sudo] npm install lsd-components
12-
```
13-
14-
## Terminology
15-
A **module** is equivalent to a **Node module** and can contain several **components**.
16-
17-
A **component** is either a **class** or an **instance** that can be respectively instantiated or retrieved.
18-
A **class** can be instantiated by creating a new **instance** of that type with zero or more **parameter** values.
19-
**Parameters** are defined by the class and its superclasses.
11+
## Introduction
2012

21-
A **component configuration** is a declarative instantiation of
22-
**components** into **instances** based on **parameters**.
13+
Components.js is a [dependency injection] framework for JavaScript applications.
2314

24-
## Workflow
15+
Instead of hard-wiring software components together, Components.js allows these components to be _instantiated_ and _wired together_ declaratively using _semantic configuration files_.
16+
The advantage of these semantic configuration files is that software components can be uniquely and globally identified using [URIs].
2517

26-
This framework provides the following workflow for injecting components.
18+
Configurations can be written in any [RDF] serialization, such as [JSON-LD].
2719

28-
- Defining a Module
29-
- Defining a Component
30-
- Configuring a Component
31-
- Invoking a Component configuration
32-
33-
This injection framework is based on RDF config files.
34-
The RDF serializations that are currently supported are JSON-LD, Turtle, TriG, N-Triples and N-Quads.
35-
36-
## Prefixes
37-
38-
We use the following prefixes in the following examples:
39-
```
40-
@prefix oo: <https://linkedsoftwaredependencies.org/vocabularies/object-oriented#>.
41-
@prefix om: <https://linkedsoftwaredependencies.org/vocabularies/object-mapping#>.
42-
@prefix doap: <http://usefulinc.com/ns/doap#>.
43-
```
20+
This software is aimed for developers who want to build _modular_ and _easily configurable_ and _rewireable_ JavaScript applications.
4421

45-
For the JSON-LD format, we provide a context for simplified config files:
46-
[https://linkedsoftwaredependencies.org/contexts/components.jsonld](https://linkedsoftwaredependencies.org/contexts/components.jsonld)
22+
## Quick Start
4723

48-
## Defining a Module
49-
50-
Example:
51-
```
52-
:SomeModule a oo:Module;
53-
doap:name "helloworld";
54-
oo:component :SomeModule#Component1.
24+
Components.js can be installed using npm:
25+
```bash
26+
$ [sudo] npm install lsd-components
5527
```
5628

57-
## Defining a Component
58-
59-
A component is either a **class** or an **instance**.
60-
A **class** can be instantiated into an **instance** based on a set of parameters.
61-
An **instance** can be used directly without instantiation.
62-
63-
### Defining a Component: Unmapped
64-
65-
Parameter values will directly be sent to the constructor.
66-
67-
Example:
68-
```
69-
:SomeModule#Component1 a oo:Class;
70-
oo:componentPath "Hello";
71-
oo:parameter hello:say;
72-
oo:parameter hello:world.
73-
```
29+
#### 1. Define your module and its components
7430

75-
In this case the `Hello` component will always receive a single object as argument like:
76-
```
31+
`my-module.jsonld`:
32+
```json
7733
{
78-
'http://example.org/hello/say': 'Hello',
79-
'http://example.org/hello/world': 'World'
34+
"@context": [
35+
"https://linkedsoftwaredependencies.org/contexts/components.jsonld",
36+
{ "ex": "http://example.org/" }
37+
],
38+
"@id": "ex:MyModule",
39+
"@type": "Module",
40+
"requireName": "my-module",
41+
"components": [
42+
{
43+
"@id": "ex:MyModule/MyComponent",
44+
"@type": "Class",
45+
"requireElement": "MyComponent",
46+
"parameters": [
47+
{ "@id": "ex:MyModule/MyComponent#name", "unique": true }
48+
],
49+
"constructorArguments": [
50+
{ "@id": "ex:MyModule/MyComponent#name" }
51+
]
52+
}
53+
]
8054
}
8155
```
8256

83-
### Defining a Component: Mapped
57+
The npm module `my-module` exports a component with the name `MyComponent`.
8458

85-
Parameter values will first be mapped to a configured parameter structure before being sent to the constructor.
59+
The constructor of `MyComponent` takes a single `name` argument.
8660

87-
Example:
88-
```
89-
:SomeModule#Component1 a oo:Class;
90-
oo:componentPath "Hello";
91-
oo:parameter hello:say;
92-
oo:parameter hello:world;
93-
oo:constructorArguments (
94-
[
95-
rdf:value hello:say.
96-
],
97-
[
98-
rdf:value hello:world.
99-
]
100-
).
101-
```
102-
In this case the `Hello` component will receive two objects as arguments like:
103-
```
104-
[
105-
'Hello',
106-
'World'
107-
]
108-
```
61+
#### 2. Create a configuration file containing a component instantiation
10962

110-
Each argument can be an `om:ObjectMapping` as follows:
111-
```
112-
:SomeModule#Component1 a oo:Class;
113-
oo:componentPath "Hello";
114-
oo:parameter hello:say;
115-
oo:parameter hello:world;
116-
oo:constructorArguments (
117-
[
118-
om:field [
119-
om:fieldName "say",
120-
om:fieldValue hello:say.
121-
];
122-
om:field [
123-
om:fieldName "world",
124-
om:fieldValue hello:world.
125-
];
126-
],
127-
[
128-
om:fieldValue hello:world.
129-
]
130-
).
131-
```
132-
In this case the `Hello` component will receive two object as arguments like:
133-
```
134-
[
63+
`config-my-component.jsonld`:
64+
```json
65+
{
66+
"@context": [
67+
"https://linkedsoftwaredependencies.org/contexts/components.jsonld",
13568
{
136-
'say': 'Hello',
137-
'world': 'World'
138-
},
139-
'World'
140-
]
141-
```
142-
143-
## Configuring a Component
144-
145-
If a component definition exists (the component is _named_), parameter predicates are defined and can be used.
146-
If no such definition exists (the component is _unnamed_), the constructor arguments must be provided in the configuration.
147-
148-
### Configuring a Component: Named
149-
150-
When a component definition exists, parameter predicates can be used to fill in the parameters.
151-
152-
Example:
153-
```
154-
:myComponent a :SomeModule#Component1;
155-
hello:say "Hello";
156-
hello:world "World".
157-
```
158-
159-
### Configuring a Component: Unnamed
160-
161-
When a component definition does not exists, constructor arguments can be filled in manually using the `oo:arguments` predicate.
162-
The NPM module name and the component element path must be provided as well.
163-
164-
Example:
165-
```
166-
:myComponent a :SomeModule#Component1;
167-
doap:name "helloworld",
168-
oo:componentPath "Hello",
169-
oo:arguments (
170-
[
171-
om:fieldValue "SAY".
172-
],
173-
[
174-
om:fieldValue "WORLD".
175-
]
176-
).
177-
```
178-
179-
Each argument can be an `om:ObjectMapping` as follows:
180-
```
181-
:myComponent a :SomeModule#Component1;
182-
doap:name "helloworld",
183-
oo:componentPath "Hello",
184-
oo:arguments (
185-
[
186-
om:field [
187-
om:fieldName "say",
188-
om:fieldValue "SAY".
189-
];
190-
om:field [
191-
om:fieldName "world",
192-
om:fieldValue "WORLD".
193-
];
194-
],
195-
[
196-
om:fieldValue "WORLD".
197-
]
198-
).
199-
```
200-
201-
## Invoking a Component configuration
202-
203-
Components can be constructed in code based on an RDF document, triple stream or by manually passing parameters.
204-
205-
First, a stream containing modules and components must be registered to the Loader.
206-
After that, either a component config URI with a config stream must be passed,
207-
or a component URI with a set of manual parameters.
208-
209-
### from an RDF document
210-
```javascript
211-
const Loader = require('lsd-components').Loader;
212-
213-
let loader = new Loader();
214-
loader.registerModuleResourcesUrl('module-hello-world.jsonld')
215-
.then(() => loader.instantiateFromUrl('http://example.org/myHelloWorld', 'config-hello-world.jsonld'))
216-
.then((helloWorld) => helloWorld.run());
217-
```
218-
219-
### from a triple stream
220-
```javascript
221-
const Loader = require('lsd-components').Loader;
222-
const JsonLdStreamParser = require('lsd-components').JsonLdStreamParser;
223-
224-
let loader = new Loader();
225-
let moduleStream = fs.createReadStream('module-hello-world.jsonld').pipe(new JsonLdStreamParser());
226-
let configStream = fs.createReadStream('config-hello-world.jsonld').pipe(new JsonLdStreamParser());
227-
loader.registerModuleResourcesUrl('module-hello-world.jsonld')
228-
.then(() => loader.runConfigStream('http://example.org/myHelloWorld', configStream))
229-
.then((helloWorld) => helloWorld.run());
69+
"ex": "http://example.org/",
70+
"name": "ex:MyModule/MyComponent#name"
71+
}
72+
],
73+
"@id": "http://example.org/myInstance",
74+
"@type": "ex:MyModule/MyComponent",
75+
"name": "John"
76+
}
23077
```
23178

232-
### manually
233-
```javascript
234-
const Loader = require('lsd-components').Loader;
235-
const JsonLdStreamParser = require('lsd-components').JsonLdStreamParser;
236-
237-
let loader = new Loader();
238-
let moduleStream = fs.createReadStream('module-hello-world.jsonld').pipe(new JsonLdStreamParser());
239-
let params = {};
240-
params['http://example.org/hello/hello'] = 'WORLD';
241-
params['http://example.org/hello/say'] = 'BONJOUR';
242-
params['http://example.org/hello/bla'] = 'BLA';
243-
loader.registerModuleResourcesStream(moduleStream)
244-
.then(() => loader.runManually('http://example.org/HelloWorldModule#SayHelloComponent', params))
245-
.then((helloWorld) => helloWorld.run());
246-
```
79+
This configuration is a semantic representation of the instantiation of `MyComponent` with `name` set to `"John"`.
24780

248-
### Module scanning
249-
Instead of loading module resources manually,
250-
the current node module and its dependencies can be scanned automatically for modules.
81+
#### 3. Instantiate your component programmatically
25182

25283
```javascript
84+
...
25385
const Loader = require('lsd-components').Loader;
25486

255-
let loader = new Loader();
256-
loader.registerAvailableModuleResources()
257-
.then(() => loader.instantiateFromUrl('http://example.org/myHelloWorld', 'config-hello-world.jsonld'))
258-
.then((helloWorld) => helloWorld.run());
87+
const loader = new Loader();
88+
await loader.registerModuleResourcesUrl('path/or/url/to/my-module.jsonld');
89+
const myComponent = await loader.instantiateFromUrl(
90+
'http://example.org/myInstance', 'path/or/url/to/config-my-component.jsonld');
91+
...
25992
```
26093

261-
If global modules should also be scanned, the `scanGlobal` flag
262-
in the `Loader` constructor can be set to `true`, as follows: `new Loader({ scanGlobal: true })`
263-
264-
## Exposing Modules and Components
265-
266-
Once a module and its components have been defined,
267-
they can be exposed through Node's package.json.
268-
The `lsd:module` entry is used to refer to the module URI.
269-
The `lsd:components` entry is used to refer to the components file path relative to the module root.
94+
`myComponent` is an instance of type `MyComponent`, as defined in the config file.
27095

271-
An example package.json could look as follows:
272-
```json
273-
{
274-
"name": "my-module",
275-
"description": "My Module",
276-
"version": "1.0.0",
277-
"lsd:module": "https://linkedsoftwaredependencies.org/bundles/npm/my-module",
278-
"lsd:components": "components/my-components.jsonld"
279-
}
280-
```
281-
282-
Additionally, JSON-LD context files can be defined in the package.json.
283-
When this is done, users that refer to JSON-LD contexts,
284-
will use the predefined contexts instead of fetching them over HTTP.
285-
For example:
286-
```json
287-
{
288-
"name": "my-module",
289-
"description": "My Module",
290-
"version": "1.0.0",
291-
"lsd:module": "https://linkedsoftwaredependencies.org/bundles/npm/my-module",
292-
"lsd:components": "components/my-components.jsonld",
293-
"lsd:contexts": {
294-
"https://example.org/context.jsonld": "contexts/my-context.jsonld"
295-
}
296-
}
297-
```
96+
[Components.js]: https://github.com/LinkedSoftwareDependencies/Components.js
97+
[GitHub]: https://github.com/LinkedSoftwareDependencies/Documentation-Components.js
98+
[dependency injection]: https://martinfowler.com/articles/injection.html
99+
[Node.js]: https://nodejs.org/en/
100+
[URIs]: https://www.w3.org/wiki/URI
101+
[RDF]: https://www.w3.org/RDF/
102+
[JSON-LD]: https://json-ld.org/
298103

299104
## License
300105
Components.js is written by [Ruben Taelman](http://www.rubensworks.net/).

0 commit comments

Comments
 (0)