UNPKG

32.2 kBMarkdownView Raw
1<img src="https://digitalbazaar.com/wp-content/uploads/BedrockLogo.png">
2
3[![Build Status](https://ci.digitalbazaar.com/buildStatus/icon?job=bedrock)](https://ci.digitalbazaar.com/job/bedrock)
4[![Dependency Status](https://img.shields.io/david/digitalbazaar/bedrock.svg)](https://david-dm.org/digitalbazaar/bedrock)
5
6A core foundation for rich Web applications.
7
8## Overview
9
10When creating a Web app, you need a foundation on which to build. There are
11a lot of disparate technologies out there that can be brought together into
12a cohesive whole to make this happen. The trouble is in finding, vetting,
13testing, and combining these technologies -- all of which needs to happen
14before you can begin to make serious progress on your own project.
15
16Bedrock helps you launch your ideas faster by bundling all the best-of-breed
17tooling that's necessary to build a modern, scalable Web app. It creates a
18solid foundation on which you can build, letting you focus on your
19project-specific needs.
20
21Bedrock uses a modular design to help keep code well-organized and to allow an
22ecosystem to grow without unnecessary hindrance. Bedrock keeps its core simple:
23it provides a powerful configuration system, an event-based API, Linked
24Data-capabilities, and testing infrastructure that makes writing interactive
25modules easy. Bedrock is an opinionated, but flexible framework; it tells
26developers that there's one recommended way to accomplish a task, but if need
27be, a developer can go in another direction. Many of Bedrock's modules attempt
28to emulate this approach, creating organizing priniciples and clear guidelines
29for developers to follow that help break down problems and reduce cognitive
30load.
31
32Bedrock uses node.js and runs on Linux, Mac OS X, and Windows. It can run on a
33low-powered laptop all the way up to an enterprise server.
34
35## Runnable Examples
36
37A very basic, runnable "Hello World" bedrock example can be found
38at [bedrock-hello-world](https://github.com/digitalbazaar/bedrock-hello-world).
39
40More complex, runnable examples can be found at [bedrock-examples](https://github.com/digitalbazaar/bedrock-examples).
41
42## Quick Examples
43
44```
45npm install bedrock
46```
47
48Create a MEAN stack application:
49
50```js
51var bedrock = require('bedrock');
52
53// modules
54require('bedrock-express');
55require('bedrock-docs');
56require('bedrock-i18n');
57require('bedrock-mongodb');
58require('bedrock-protractor');
59require('bedrock-request-limiter');
60require('bedrock-requirejs');
61require('bedrock-server');
62require('bedrock-session-mongodb');
63require('bedrock-validation');
64require('bedrock-views');
65
66bedrock.start();
67```
68
69To include the [AngularJS][]-based frontend, `bower install` these modules:
70
71```
72bedrock-angular
73bedrock-angular-alert
74bedrock-angular-filters
75bedrock-angular-form
76bedrock-angular-lazy-compile
77bedrock-angular-modal
78bedrock-angular-model
79bedrock-angular-selector
80bedrock-angular-ui
81```
82
83Create a simple express-based bedrock application:
84
85```js
86var bedrock = require('bedrock');
87
88// modules
89require('bedrock-express');
90
91bedrock.events.on('bedrock-express.configure.routes', function(app) {
92 app.get('/', function(req, res) {
93 res.send('Hello World!');
94 });
95});
96
97bedrock.start();
98```
99
100Create a bedrock REST application with an express server, mongodb database,
101and mongodb-backed session storage:
102
103```js
104var bedrock = require('bedrock');
105
106// modules
107require('bedrock-express');
108require('bedrock-session-mongodb');
109var database = require('bedrock-mongodb');
110
111bedrock.events.on('bedrock-mongodb.ready', function(callback) {
112 database.openCollections(['people'], function(err) {
113 if(err) {
114 return callback(err);
115 }
116 callback();
117 });
118});
119
120bedrock.events.on('bedrock-express.configure.routes', function(app) {
121 app.get('/people', function(req, res, next) {
122 database.collections.people.find({}).toArray(function(err, docs) {
123 if(err) {
124 return next(err);
125 }
126 res.send(docs);
127 });
128 });
129
130 app.get('/people/:name', function(req, res, next) {
131 database.collections.people.findOne(
132 {name: req.param('name')}, function(err, result) {
133 if(err) {
134 return next(err);
135 }
136 res.send(result);
137 });
138 });
139
140 app.post('/people/:name', function(req, res){
141 database.collections.people.insert(
142 [{name: req.param('name')}], function(err, result) {
143 if(err) {
144 return next(err);
145 }
146 res.send(result.result);
147 });
148 });
149
150 app.delete('/people/:name', function(req, res){
151 database.collections.people.remove(
152 {name: req.param('name')}, function(err, result) {
153 if(err) {
154 return next(err);
155 }
156 res.send(result.result);
157 });
158 });
159});
160
161bedrock.start();
162```
163
164To create a MEAN stack application with identity management and authentication,
165see the [bedrock-seed][] project.
166
167## Comprehensive Module Example
168
169Below is an example that demonstrates Bedrock's event API. It creates a
170module with an http server that other modules can attach listeners to. It
171also registers a `debug` subcommand that displays the listeners that attached
172to the http server. The example also creates a module that attaches a simple
173"hello world" listener to the http server. The example demonstrates how to use
174Bedrock's event API to:
175
1761. Register a subcommand and handle it if is detected when the command line
177 is parsed.
1782. Create a modular http server, listen to a privileged port (80), and emit a
179 custom event to allow other modules to attach listeners to the server only
180 after process privileges have been dropped.
1813. Execute custom behavior (eg: print the server's registered event listeners)
182 after all other modules have started, if a subcommand was detected.
183
184### Module `bedrock-example-server.js`:
185
186```js
187var bedrock = require('bedrock');
188var http = require('http');
189
190// setup default module config
191bedrock.config['example-server'] = {port: 80};
192
193var server = http.createServer();
194
195// emitted prior to command line parsing
196bedrock.events.on('bedrock-cli.init', function() {
197 // add a new subcommand executed via: node project.js debug
198 var command = bedrock.program
199 .command('debug')
200 .description('display registered http listeners')
201 .option(
202 '--debug-event <event>',
203 'The event to print listeners for. [request]')
204 .action(function() {
205 // save the parsed command information
206 bedrock.config.cli.command = command;
207 });
208});
209
210// emitted after the command line has been parsed
211bedrock.events.on('bedrock-cli.ready', function() {
212 var command = bedrock.config.cli.command;
213 if(command.name() !== 'debug') {
214 // `debug` not specified on the command line, return early
215 return;
216 }
217
218 // emitted after all bedrock.start listeners have run
219 bedrock.events.on('bedrock.ready', function() {
220 // print out all the listeners that registered with the server
221 var event = command.debugEvent || 'request';
222 var listeners = server.listeners(event);
223 console.log('listeners for event: ' + event);
224 listeners.forEach(function(listener, index) {
225 console.log(index, listener.toString());
226 });
227 });
228});
229
230// emitted before initialization, to allow any further configuration
231bedrock.events.on('bedrock.configure', function() {
232 if(bedrock.config.foo) {
233 bedrock.config.foo.bar = true;
234 }
235});
236
237// emitted for early initialization, prior to dropping process privileges
238bedrock.events.on('bedrock.admin.init', function(callback) {
239 // listen on port 80
240 server.listen(bedrock.config['example-server'].port, function() {
241 // ready, call callback to allow bedrock to continue processing events
242 callback();
243 });
244});
245
246// emitted for modules to do or schedule any unprivileged work on start up
247bedrock.events.on('bedrock.start', function(callback) {
248 // emit a custom event giving other modules access to the example server
249 bedrock.events.emit('example.server.ready', server, function() {
250 callback();
251 });
252});
253
254// emitted after all bedrock.ready listeners have run
255bedrock.events.on('bedrock.started', function() {
256 console.log('everything is running now');
257});
258```
259
260### Module `bedrock-example-listener.js`:
261
262```js
263var bedrock = require('bedrock');
264
265// load bedrock-example-server dependency
266require('./bedrock-example-server');
267
268// emitted to allow listeners to be attached to the example server
269bedrock.events.on('example.server.ready', function(server) {
270 server.on('request', function(request, response) {
271 response.writeHead(200, {'Content-Type': 'text/plain'});
272 response.end('Hello World\n');
273 });
274});
275```
276
277### Example Main Project `project.js`:
278
279```js
280var bedrock = require('bedrock');
281
282// bedrock modules to load
283require('./bedrock-example-server');
284require('./bedrock-example-listener');
285
286// change the port to use
287// bedrock.config['example-server'].port = 8123;
288
289bedrock.start();
290```
291
292Run the main project and display the debug information with:
293
294```
295node project.js debug --debug-event request
296```
297
298Example output:
299
300```
3012015-03-05T21:59:23.727Z - info: starting bedrock...
3022015-03-05T21:59:23.729Z - info: running bedrock master process pid=7705
3032015-03-05T21:59:23.904Z - info: running bedrock worker process workerPid=7711
3042015-03-05T21:59:23.906Z - info: startup time: 6ms workerPid=7711
305listeners for event: request
3060 'function (request, response) {\n response.writeHead(200, {\'Content-Type\': \'text/plain\'});\n response.end(\'Hello World\\n\');\n }'
307everything is running now
308```
309
310## Configuration
311
312For documentation on Bedrock's core configuration, see [config.js](./lib/config.js).
313
314## How It Works
315
316Bedrock is a modular system built on node.js. Node.js modules typically
317communicate with each other using the CommonJS API (eg: `require` and
318`module.exports`, etc.), and Bedrock modules are no different. However,
319Bedrock also provides some additional low-level subsystems to help modules
320coordinate. These include: `bedrock.config`, `bedrock.events`,
321`bedrock.jsonld`, `bedrock.loggers`, `bedrock.test`, and `bedrock.util`.
322
323To create a Bedrock project, all you need to do is create a JavaScript file,
324for example `project.js`, that requires `bedrock`, any other Bedrock modules
325you're interested in, and that then calls `bedrock.start()`. To run your
326project, run:
327
328```
329node project.js
330```
331
332If you're developing your project and you have installed all of the development
333packages for the Bedrock modules you're using, you can also easily test your
334project and any of the modules it has included by running:
335
336```
337node project.js test
338```
339
340This will execute Bedrock's built-in test framework, running all of the tests
341that each module has written. This approach ensures you're running tests for
342your entire project and its dependencies.
343
344### bedrock.config
345
346Bedrock has a simple, but highly-customizable configuration system. All
347configuration variables are stored in a shared JavaScript object
348`bedrock.config`. The object is partitioned into separate configuration objects
349that are identified by the object's keys. For example Bedrock introduces the
350`cli`, `core`, `constants`, `jsonld`, and `loggers` object keys. The best
351practice for modules to claim their own area in the configuration object is to
352insert their default configuration object using a key that either matches their
353module name or that matches their module name minus any `bedrock-` prefix. For
354example, the [bedrock-server][] module's specific configuration object can be
355found under `bedrock.config.server`. A `mycompany-feature` module would be
356found under `bedrock.config['mycompany-feature']`. Modules may define whatever
357configuration variables they want to using whatever format is appropriate for
358their own use.
359
360The `bedrock.util` module has helpers to setup configurations, and in
361particular, dynamically computed configurations. Computed values can help to
362simplify dependency issues by allowing values to be computed at runtime from a
363function or string template. (Note there is a small cost with computed config
364values which could be important depending on the use case.)
365
366`bedrock.util.config.Config` creates a wrapper around a config object and
367optional options. This wrapper exposes a new, helpful API that is detailed
368below. A common setup could look like the following.
369
370```js
371// an empty config object
372let config = {};
373// common options
374let options = {
375 // the config
376 config: config
377 // local vars used during string template evaluation
378 locals: config
379};
380// wrap the config
381let c = new bedrock.util.config.Config(config, options);
382```
383
384Bedrock provides a shared wrapper around the common `bedrock.config` as
385`bedrock.util.config.main`.
386
387To do simple sets of config data, use the `set()` API.
388
389```js
390let c = bedrock.util.config.main;
391// set a config variable with a path
392// path components are created as needed
393c.set('server.port', 8443);
394// config is now {"server": {"port": 8443}}
395```
396
397Normal code and the config API can be mixed. A useful helper is `setDefault()`.
398This call lets you simplify ensuring a full object path exists before setting
399data. Objects in the path are created as needed.
400
401```js
402let config = bedrock.config;
403let c = bedrock.util.config.main;
404// create container object if needed
405c.setDefault('accounts.admin', {});
406// the config is just a normal object
407config.accounts.admin.name = 'Ima Admin';
408c.set('accounts.admin.id', 1);
409// the config object is returned from setDefault()
410let account123 = c.setDefault('accounts.account123', {});
411account123.id = 123;
412account123.name = 'Account 123';
413```
414
415Computed config values using the `setComputed()` API add on a much more
416powerful feature where values will be calculated at runtime.
417
418```js
419let config = bedrock.config;
420// get the Config wrapper for the default bedrock.config
421let c = bedrock.util.config.main;
422// set static values
423c.set('server.port', 8443);
424c.set('server.domain', 'bedrock.dev');
425// set a computed value that uses values from the main config
426c.setComputed('server.host', () => {
427 return config.server.domain + ':' + config.server.port;
428});
429console.log(config.server.host); // "bedrock.dev:8443"
430```
431
432The logic for a computed value can be any normal code. If source config values
433are updated the computed values will reflect the change.
434
435```js
436let config = bedrock.config;
437let c = bedrock.util.config.main;
438c.set('server.port', 8443);
439c.set('server.domain', 'bedrock.dev');
440c.setComputed('server.host', () => {
441 // only add the port if it's not the well known default
442 if(config.server.port !== 443) {
443 return config.server.domain + ':' + config.server.port;
444 }
445 return config.server.domain;
446});
447console.log(config.server.host); // "bedrock.dev:8443"
448c.set('server.port', 443);
449console.log(config.server.host); // "bedrock.dev"
450```
451
452`setComputed()` can be verbose. a wrapper can be created using the standard
453`bind()` functionality. A helper called `computer()` will do this for you.
454```js
455let config = bedrock.config;
456let cc = bedrock.util.config.main.computer();
457cc('server.host', () => {
458 // only add the port if it's not the well known default
459 if(config.server.port !== 443) {
460 return config.server.domain + ':' + config.server.port;
461 }
462 return config.server.domain;
463});
464```
465
466Computed values can also be created with [lodash-style string
467templates](https://lodash.com/docs/#template).
468
469```js
470let config = bedrock.config;
471let cc = bedrock.util.config.main.computer();
472cc('server.baseUri', 'https://${server.host}');
473console.log(config.server.baseUri); // "https://bedrock.dev:8443"
474// use locals option to simplify templates
475cc('base.computed', '${base.a}:${base.b}:${base.c}');
476cc('base.computed', '${a}:${b}:${c}', {locals: config.base});
477```
478
479Setting or computing multiple values with one call uses an object notation:
480
481```js
482let c = bedrock.util.config.main;
483let cc = c.computer();
484c.set({
485 'server.port': 8443,
486 'server.domain': 'bedrock.dev',
487 'server.name': 'Bedrock Dev',
488 'users.admin.id': 1
489});
490cc({
491 'server.url': 'https://${server.domain}:${server.port}',
492 'users.admin.url': '${server.url}/users/${users.admin.id}'
493});
494```
495
496Computed values can be added to an array using indexing or the `pushComputed`
497feature. If indexing is used the array must already exist or the
498`{parentDefault: []}` option should be used. `pushComputed` will create the
499parent array if needed.
500
501```js
502let config = bedrock.config;
503let c = bedrock.util.config.main;
504let cc = c.computer();
505cc('server.baseUri', 'https://${server.host}');
506c.setDefault('resources', []);
507cc('resources[0]', '${server.baseUri}/r/0');
508c.pushComputed('resources', '${server.baseUri}/r/1');
509```
510
511### bedrock.events
512
513It's sometimes necessary to allow modules to coordinate with each other in
514an orderly fashion. To achieve this, Bedrock provides an event API. Bedrock's
515event API is very similar to node's built-in EventEmitter, but it provides a
516few additional features.
517
518In particular, when emitting an event, Bedrock can wait for a listener to run
519asynchronous code before executing the next listener. This allows each listener
520to run synchronously or asynchronously, depending on their individual needs,
521without worrying that the next listener or the next event will be emitted
522before they have completed what they need to do.
523
524Bedrock's event system also provides another feature, which is the ability to
525cancel events. Event cancelation allows modules to build-in default
526behavior that can be canceled by other modules. Whenever a synchronous listener
527returns `false` or an asynchronous listener passes `false` to its callback, the
528event will not be emitted to the remaining listeners, and, if a callback was
529given when the event was emitted, it will be given the `false` value allowing
530the emitter to take a different action.
531
532To a emit an event:
533
534```js
535bedrock.events.emit('example-module.foo', data, function(err, result) {
536 if(err) {
537 console.log('an error occurred in a listener and the event was canceled');
538 return;
539 }
540 if(result === false) {
541 console.log('the event was canceled, but not due to an error');
542 return;
543 }
544 console.log('the event was not canceled');
545});
546```
547
548To create a synchronous listener:
549
550```js
551bedrock.events.on('example-module.foo', function(data) {
552 if(anErrorOccured) {
553 throw new Error('foo');
554 }
555 if(shouldCancel) {
556 return false;
557 }
558 // do something synchronous
559});
560```
561
562To create an asynchronous listener:
563
564```js
565bedrock.events.on('example-module.foo', function(data, callback) {
566 // because an additional parameter was added to the listener function,
567 // it is assumed it should be a function and a callback will be passed
568 // that *must* be called
569 if(anErrorOccurred) {
570 return callback(new Error('foo'));
571 }
572 if(shouldCancel) {
573 return callback(null, false);
574 }
575 // do something asynchronous, other listeners won't execute and event
576 // emission won't continue until you call the callback
577 process.nextTick(function() {
578 callback();
579 });
580});
581```
582
583Note that the asynchronous analog for throwing an error is calling the callback
584with an error as its first parameter and the analog for returning a value
585(typically only used for event cancelation) is to pass `null` for the first
586parameter and the return value for the second parameter of the callback. This
587API matches the "error-first" callback continuation-style that is standard
588practice in node.
589
590Bedrock core emits several events that modules may listen for. These events
591fall into three possible namespaces: `bedrock-cli`, `bedrock-loggers` and
592`bedrock`. The `bedrock-cli` events are emitted to allow coordination with
593Bedrock's command line interface. The `bedrock-loggers.init` event is emitted
594after the `bedrock-cli.init` event. The `bedrock` events are emitted after
595all the `bedrock-cli` events, unless a listener cancels the `bedrock-cli.ready`
596event or causes the application to exit early.
597
598- **bedrock-cli.init**
599 - Emitted before command line parsing. Allows registration of new subcommands.
600- **bedrock-cli.parsed**
601 - Emitted after command line parsing. Allows for configuration of loggers
602 based on command line flags. For instance, a logger may provide for the
603 specification of a `logGroupName` that may be computed at runtime based
604 on some command line flag(s).
605- **bedrock-loggers.init**
606 - Emitted after command line parsing. Allows registration of new logging
607 transports prior to initialization of the logging subsystem.
608- **bedrock-cli.ready**
609 - Emitted after command line parsing and logging initialization. Allows
610 execution of subcommands or the prevention of `bedrock` events from being
611 emitted, either by canceling this event or by exiting the application early.
612- **bedrock-cli.test.configure**
613 - Emitted during `bedrock-cli.init` after `test` subcommand has been
614 registered. Listeners receive the `test` command object. Allows modules
615 that define new test frameworks to add new `test` command line options via
616 the `test` command object.
617- **bedrock.test.configure**
618 - Emitted during `bedrock-cli.ready`, before `bedrock.configure`. Allows
619 listeners to make configuration changes for running tests. This event
620 is particularly useful for changing configuration values prior to their
621 later use when `bedrock.configure` is emitted. To make late configuration
622 changes on the basis of whether or not tests are going to run, instead
623 add a listener to the `bedrock.configure` event after any other relevant
624 listeners have been added.
625- **bedrock.configure**
626 - Emitted after `bedrock-cli.ready` and before `bedrock.admin.init`. Allows
627 additional custom configuration before Bedrock initializes but after
628 command line parsing.
629- **bedrock.admin.init**
630 - Emitted after `bedrock.configure` and before elevated process privileges
631 are dropped. Allows listeners to perform early initialization tasks that
632 require special privileges. Note that, if Bedrock is started with elevated
633 privileges (ie: as root), listeners will execute with those privileges. Any
634 early initialization that needs to execute before `bedrock.start` but does
635 not require elevated privileges should be deferred to `bedrock.init`. Most
636 modules should find binding to `bedrock.init` to be sufficient for any
637 initialization work.
638- **bedrock.init**
639 - Emitted after `bedrock.admin.init` and just after elevated process
640 privileges are dropped. Allows listeners to perform early initialization
641 tasks that do not require special privileges. This event should be used
642 to ensure, for example, that a module's API has the required supporting
643 data structures in memory prior to another module's use of it. For example,
644 a validation module may need to load validation schemas from files on disk
645 before they can be accessed via its API, but this loading must occur after
646 the configuration events have passed and after special process privileges
647 have been dropped. **As a best practice, modules should not emit custom
648 events during `bedrock.init` because it may cause scenarios where two
649 unrelated modules can't be easily combined.** For example, if a module emits
650 a custom event during `bedrock.init`, then a listener of that event would
651 be unable to use the API of an unrelated module that hasn't been
652 initialized yet. Deferring custom event emitting to `bedrock.start` solves
653 this problem; it ensures all modules have had a chance to complete
654 initialization before attempting to interact with one another through the
655 event system.
656- **bedrock.start**
657 - Emitted after `bedrock.init`. This is the event modules should use to
658 execute or schedule their main background behavior and to emit any custom
659 events they would like to make available to their dependents.
660- **bedrock.ready**
661 - Emitted after `bedrock.start`. Allows listeners to execute custom behavior
662 after all modules have handled the `bedrock.start` event. This event is
663 useful for turning on external access to web services or other modular
664 systems that should now be fully ready for use. It can also be used to run
665 analysis on modules that have started, for example, to build live
666 documentation.
667- **bedrock.started**
668 - Emitted after `bedrock.ready`. External access to web services or other
669 features provided by modules should now be available. Allows custom
670 subcommands or behavior to run after Bedrock has fully started, eg: tests.
671- **bedrock.tests.run**
672 - Emitted during `bedrock.started`. Once Bedrock has fully started, this
673 event is emitted to inform test frameworks to run their tests. Listeners
674 are passed a test state object with a `pass` property that they can set to
675 `false` to indicate to the test subsystem that at least one test did not
676 pass. Test frameworks may add their own information to the state object
677 using a property matching their framework name.
678
679### bedrock.jsonld
680
681Bedrock is intended to provide a foundation for [Linked Data][] applications,
682and as such, it provides a [JSON-LD][] processor (via [jsonld.js][]) that is
683integrated with its configuration system. Any [JSON-LD context][] that is
684inserted into the `bedrock.config.constants.CONTEXTS` object (where keys
685are the URL for the context and the values are the context itself), will be
686served from disk instead of retrieved from the Web. This is a useful feature
687for both developing [Linked Data][] applications and for ensuring contexts
688are available in offline mode.
689
690### bedrock.loggers
691
692Bedrock has a built-in logging subsystem based on [winston][]. Anything you
693can do with [winston][], you can do with Bedrock. Bedrock provides a set of
694default loggers that are suitable for most applications. The main application
695logger can be retrieved via `bedrock.loggers.get('app')`. A call to
696`bedrock.loggers.addTransport` can be made in event handlers of the
697`bedrock-loggers.init` event to add new [winston][] transports. Logging
698categories (such as `app`) and the transports used by them can be configured
699via `bedrock.config`.
700
701Bedrock supports multi-level child loggers with common metadata. These are
702created with `bedrock.loggers.get('app').child({...})`. Provided metadata will
703be added to child log output. A special `module` meta name can optionally be
704used for pretty output. A shortcut for creating named module loggers is
705`bedrock.loggers.get('app').child('name')`.
706
707Module prefix display can be controlled per-category:
708
709```js
710// get a child logger with custom module name
711let logger = bedrock.loggers.get('app').child('my-module');
712
713// message module prefix controlled with a per-category config value
714bedrock.config.loggers.app.bedrock.modulePrefix = false;
715logger.info('an info message');
716// module displayed as normal meta data:
717// 2017-06-30T12:34:56.789Z - info: an info message workerPid=1234, module=my-module
718
719// with module prefix enabled:
720bedrock.config.loggers.app.bedrock.modulePrefix = true;
721logger.info('an info message');
722// displayed as an nice message prefix:
723// 2017-06-30T12:34:56.789Z - info: [my-module] an info message workerPid=1234
724```
725
726### bedrock.test
727
728Bedrock comes with test support built-in. It provides a test framework based
729on mocha that integrates with `bedrock.config`. To add a mocha test to a
730Bedrock module, you simply push a directory or a file path onto the
731`config.mocha.tests` array. Bedrock also makes it easy to add other test
732frameworks via Bedrock modules. For example, [bedrock-protractor][] integrates
733the [AngularJS][] [protractor][] test framework with Bedrock. Whenever you
734run tests against your project, your project and all of its dependencies will
735be tested, using whatever test frameworks they have registered with. Bedrock
736also provides command line options to limit the tests that run as desired.
737
738### bedrock.util
739
740Bedrock provides a number of helpful general purpose utilities. For example,
741Bedrock defines a `BedrockError` class that extends the default `Error`
742class. A `BedrockError` can keep track of a series of "causes" (other errors)
743that allow developers to better understand why an error occured.
744`BedrockError`s can also be marked as `public`, which allows modules that
745may, for example, serve error information over the Web to display more error
746details. `bedrock.util` also contains tools for formatting dates,
747extending/merging/cloning objects, and generating UUIDs.
748
749## Recommended Modules
750
751<!-- TODO: Change section to "If you want to do X, use these modules" format -->
752
753[bedrock-server][] provides a core, cluster-based HTTPS server.
754
755[bedrock-express][] provides an Express server with reasonable
756defaults and extra features like the ability to layer static
757files and directories to support overrides.
758
759[bedrock-mongodb][] provides an API for connecting to a MongoDB
760database and creating and using collections.
761
762[bedrock-jobs][] provides a background job scheduler.
763
764[bedrock-requirejs][] provides a client-side module loader and
765autoconfiguration capabilities for bower components.
766
767[bedrock-views][] provides server-rendered views with HTML5 + Bootstrap3.
768
769[bedrock-angular][] layers on top of [bedrock-views][] to provide
770client-rendered AngularJS views.
771
772[bedrock-idp][] provides user identity and public key management.
773
774[bedrock-protractor][] integrates [protractor][] with Bedrock, exposing a
775powerful end-to-end [AngularJS][] test framework to Bedrock modules.
776
777Other Bedrock modules provide REST APIs, user account management, strong
778cryptography support, DoS protection, digital signatures, Linked Data, and
779tons of other [FEATURES][]. If you don't need all the fancy features, Bedrock
780is modular, so you can use only the modules you want.
781
782## Quickstart
783
784You can follow the following tutorial to setup and use Bedrock on a Linux or
785Mac OS X development machine.
786
787## Requirements
788
789* Linux, Mac OS X, Windows
790* node.js >= 0.10.x
791* npm >= 1.4.x
792
793Running Bedrock
794---------------
795
796Run the following to start up a development server from the source directory:
797
798 node index.js
799
800To add more verbose debugging, use the `--log-level` option:
801
802 node index.js --log-level debug
803
804Running the Tests
805-----------------
806
807Run all tests:
808
809 npm test
810
811Run only the mocha test framework:
812
813 node index.js test --framework mocha
814
815Run a specific mocha test:
816
817 node index.js test --framework mocha --mocha-test tests/test.js
818
819Running the Code Coverage Tool
820------------------------------
821
822 npm run coverage
823
824Look at 'coverage.html' using a web browser
825
826Features
827--------
828
829For an example list of features provided by Bedrock modules, see the
830[FEATURES][] file.
831
832FAQ
833---
834
835See the [FAQ][] file for answers to frequently asked questions.
836
837Hacking
838-------
839
840See the [CONTRIBUTING][] file for various details for coders about
841hacking on this project.
842
843Authors
844-------
845
846See the [AUTHORS][] file for author contact information.
847
848License
849-------
850
851Bedrock and all Bedrock modules are:
852
853 Copyright (c) 2011-2015 Digital Bazaar, Inc.
854 All Rights Reserved
855
856You can use Bedrock for non-commercial purposes such as self-study, research,
857personal projects, or for evaluation purposes. See the [LICENSE][] file for
858details about the included non-commercial license information.
859
860[AUTHORS]: AUTHORS.md
861[FEATURES]: FEATURES.md
862[CONTRIBUTING]: CONTRIBUTING.md
863[FAQ]: FAQ.md
864[LICENSE]: LICENSE.md
865[AngularJS]: https://github.com/angular/angular.js
866[JSON-LD]: http://json-ld.org
867[JSON-LD context]: http://www.w3.org/TR/json-ld/#the-context
868[Linked Data]: http://en.wikipedia.org/wiki/Linked_data
869[bedrock-angular]: https://github.com/digitalbazaar/bedrock-angular
870[bedrock-express]: https://github.com/digitalbazaar/bedrock-express
871[bedrock-idp]: https://github.com/digitalbazaar/bedrock-idp
872[bedrock-jobs]: https://github.com/digitalbazaar/bedrock-jobs
873[bedrock-mongodb]: https://github.com/digitalbazaar/bedrock-mongodb
874[bedrock-protractor]: https://github.com/digitalbazaar/bedrock-protractor
875[bedrock-requirejs]: https://github.com/digitalbazaar/bedrock-requirejs
876[bedrock-seed]: https://github.com/digitalbazaar/bedrock-seed
877[bedrock-server]: https://github.com/digitalbazaar/bedrock-server
878[bedrock-views]: https://github.com/digitalbazaar/bedrock-views
879[jsonld.js]: https://github.com/digitalbazaar/jsonld.js
880[protractor]: https://github.com/angular/protractor
881[winston]: https://github.com/winstonjs/winston