{"id":13403659,"url":"https://github.com/digitalbazaar/bedrock","last_synced_at":"2025-04-04T13:05:49.596Z","repository":{"id":24169365,"uuid":"27559729","full_name":"digitalbazaar/bedrock","owner":"digitalbazaar","description":"Bedrock: A core foundation for rich Web applications.","archived":false,"fork":false,"pushed_at":"2024-10-17T03:02:58.000Z","size":3183,"stargazers_count":67,"open_issues_count":9,"forks_count":16,"subscribers_count":23,"default_branch":"main","last_synced_at":"2024-10-19T05:30:33.867Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digitalbazaar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.md","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-12-04T20:57:14.000Z","updated_at":"2024-10-15T17:10:12.000Z","dependencies_parsed_at":"2024-01-16T10:36:38.321Z","dependency_job_id":"099f9689-bf46-49fc-aad5-1a3b41048464","html_url":"https://github.com/digitalbazaar/bedrock","commit_stats":{"total_commits":2039,"total_committers":13,"mean_commits":"156.84615384615384","dds":0.3859735164296224,"last_synced_commit":"fa55908e8a0fcf984120153a838b66fb5771836d"},"previous_names":[],"tags_count":104,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fbedrock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fbedrock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fbedrock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalbazaar%2Fbedrock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digitalbazaar","download_url":"https://codeload.github.com/digitalbazaar/bedrock/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247174458,"owners_count":20896078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:01:32.942Z","updated_at":"2025-04-04T13:05:49.574Z","avatar_url":"https://github.com/digitalbazaar.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Bedrock® _(@bedrock/core)_\n\n![Bedrock Logo](./branding/BedrockLogo.png)\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/digitalbazaar/bedrock/main.yml)](https://github.com/digitalbazaar/bedrock/actions/workflows/main.yml)\n[![Coverage Status](https://img.shields.io/codecov/c/github/digitalbazaar/bedrock)](https://codecov.io/gh/digitalbazaar/bedrock)\n\nA core foundation for rich Web applications.\n\n## Overview\n\nBedrock® is a modular Web application framework designed to help keep code\nwell-organized, secure, and to allow an ecosystem to grow without unnecessary\nhindrance. Bedrock provides a powerful configuration system, an event-based API,\nLinked Data-capabilities, securely integrated modules, and testing capabilities\nthat make writing modular Web applications easy.\n\nWhen creating a Web app, you need a foundation on which to build. There are\na lot of disparate technologies out there that can be brought together into\na cohesive whole to make this happen. The trouble is in finding, vetting,\ntesting, and combining these technologies -- all of which needs to happen\nbefore you can begin to make serious progress on your own project.\n\nBedrock is an opinionated, but flexible framework. Bedrock modules emulate\norganizing principles and clear guidelines for developers to follow that help\nbreak down problems and reduce cognitive load.\n\nBedrock uses node.js and runs on Linux, Mac OS X, and Windows. It can run on a\nlow-powered laptop all the way up to an enterprise server.\n\n## Runnable Examples\n\nRunnable examples can be found at [bedrock-examples](https://github.com/digitalbazaar/bedrock-examples).\n\n## Quick Examples\n\n```sh\nnpm install bedrock\n```\n\nCreate a typical application:\n\n```js\nimport * as bedrock from '@bedrock/core';\n\n// modules\nimport 'bedrock-express';\nimport 'bedrock-mongodb';\nimport 'bedrock-server';\nimport 'bedrock-session-mongodb';\nimport 'bedrock-validation';\nimport 'bedrock-views';\nimport 'bedrock-webpack';\n\nbedrock.start();\n```\n\nTo include the [Vue.js][]-based frontend, `npm install` these modules:\n\n```sh\nnpm install bedrock-vue bedrock-quasar\n```\n\nCreate a simple express-based bedrock application:\n\n```js\nimport * as bedrock from '@bedrock/core';\n\n// modules\nimport 'bedrock-express';\n\nbedrock.events.on('bedrock-express.configure.routes', function(app) {\n  app.get('/', function(req, res) {\n    res.send('Hello World!');\n  });\n});\n\nbedrock.start();\n```\n\nCreate a bedrock REST application with an express server, mongodb database,\nand mongodb-backed session storage:\n\n```js\nimport * as bedrock from '@bedrock/core';\n\n// modules\nimport 'bedrock-express';\nimport 'bedrock-session-mongodb';\nimport * as database from 'bedrock-mongodb';\n\nbedrock.events.on('bedrock-mongodb.ready', async () =\u003e {\n  await database.openCollections(['people']);\n});\n\nbedrock.events.on('bedrock-express.configure.routes', function(app) {\n  app.get('/people', function(req, res, next) {\n    database.collections.people.find({}).toArray(function(err, docs) {\n      if(err) {\n        return next(err);\n      }\n      res.send(docs);\n    });\n  });\n\n  app.get('/people/:name', function(req, res, next) {\n    database.collections.people.findOne(\n      {name: req.param('name')}, function(err, result) {\n        if(err) {\n          return next(err);\n        }\n        res.send(result);\n      });\n  });\n\n  app.post('/people/:name', function(req, res){\n    database.collections.people.insert(\n      [{name: req.param('name')}], function(err, result) {\n        if(err) {\n          return next(err);\n        }\n        res.send(result.result);\n      });\n  });\n\n  app.delete('/people/:name', function(req, res){\n    database.collections.people.remove(\n      {name: req.param('name')}, function(err, result) {\n        if(err) {\n          return next(err);\n        }\n        res.send(result.result);\n      });\n  });\n});\n\nbedrock.start();\n```\n\nTo create a MEAN stack application with identity management and authentication,\nsee the [bedrock-seed][] project.\n\n## Comprehensive Module Example\n\nBelow is an example that demonstrates Bedrock's event API. It creates a\nmodule with an http server that other modules can attach listeners to. It\nalso registers a `debug` subcommand that displays the listeners that attached\nto the http server. The example also creates a module that attaches a simple\n\"hello world\" listener to the http server. The example demonstrates how to use\nBedrock's event API to:\n\n1. Register a subcommand and handle it if is detected when the command line\n   is parsed.\n2. Create a modular http server, listen to a privileged port (80), and emit a\n   custom event to allow other modules to attach listeners to the server only\n   after process privileges have been dropped.\n3. Execute custom behavior (eg: print the server's registered event listeners)\n   after all other modules have started, if a subcommand was detected.\n\n### Module `bedrock-example-server.js`:\n\n```js\nimport * as bedrock from '@bedrock/core';\nimport http from 'http';\n\n// setup default module config\nbedrock.config['example-server'] = {port: 80};\n\nconst server = http.createServer();\n\n// emitted prior to command line parsing\nbedrock.events.on('bedrock-cli.init', function() {\n  // add a new subcommand executed via: node project.js debug\n  const command = bedrock.program\n    .command('debug')\n    .description('display registered http listeners')\n    .option(\n      '--debug-event \u003cevent\u003e',\n      'The event to print listeners for. [request]')\n    .action(function() {\n      // save the parsed command information\n      bedrock.config.cli.command = command;\n    });\n});\n\n// emitted after the command line has been parsed\nbedrock.events.on('bedrock-cli.ready', function() {\n  const command = bedrock.config.cli.command;\n  if(command.name() !== 'debug') {\n    // `debug` not specified on the command line, return early\n    return;\n  }\n\n  // emitted after all bedrock.start listeners have run\n  bedrock.events.on('bedrock.ready', function() {\n    // print out all the listeners that registered with the server\n    const event = command.debugEvent || 'request';\n    const listeners = server.listeners(event);\n    console.log('listeners for event: ' + event);\n    listeners.forEach(function(listener, index) {\n      console.log(index, listener.toString());\n    });\n  });\n});\n\n// emitted before initialization, to allow any further configuration\nbedrock.events.on('bedrock.configure', function() {\n  if(bedrock.config.foo) {\n    bedrock.config.foo.bar = true;\n  }\n});\n\n// emitted for early initialization, prior to dropping process privileges\nbedrock.events.on('bedrock.admin.init', async () =\u003e {\n  // listen on port 80\n  return new Promise((resolve, reject) =\u003e {\n    // resolve when listening to allow bedrock to continue processing events\n    server.listen(bedrock.config['example-server'].port, () =\u003e resolve());\n  });\n});\n\n// emitted for modules to do or schedule any unprivileged work on start up\nbedrock.events.on('bedrock.start', async () {\n  // emit a custom event giving other modules access to the example server\n  await bedrock.events.emit('example.server.ready', server);\n});\n\n// emitted after all bedrock.ready listeners have run\nbedrock.events.on('bedrock.started', function() {\n  console.log('everything is running now');\n});\n```\n\n### Module `bedrock-example-listener.js`:\n\n```js\nimport * as bedrock from '@bedrock/core';\n\n// load bedrock-example-server dependency\nimport './bedrock-example-server.js';\n\n// emitted to allow listeners to be attached to the example server\nbedrock.events.on('example.server.ready', function(server) {\n  server.on('request', function(request, response) {\n    response.writeHead(200, {'Content-Type': 'text/plain'});\n    response.end('Hello World\\n');\n  });\n});\n```\n\n### Example Main Project `project.js`:\n\n```js\nimport * as bedrock from '@bedrock/core';\n\n// bedrock modules to load\nimport './bedrock-example-server.js';\nimport './bedrock-example-listener.js';\n\n// change the port to use\n// bedrock.config['example-server'].port = 8123;\n\nbedrock.start();\n```\n\nRun the main project and display the debug information with:\n\n```sh\nnode project.js debug --debug-event request\n```\n\nExample output:\n\n```\n2015-03-05T21:59:23.727Z - info: starting bedrock...\n2015-03-05T21:59:23.729Z - info: running bedrock master process pid=7705\n2015-03-05T21:59:23.904Z - info: running bedrock worker process workerPid=7711\n2015-03-05T21:59:23.906Z - info: startup time: 6ms workerPid=7711\nlisteners for event: request\n0 'function (request, response) {\\n    response.writeHead(200, {\\'Content-Type\\': \\'text/plain\\'});\\n    response.end(\\'Hello World\\\\n\\');\\n  }'\neverything is running now\n```\n\n## Configuration\n\nFor documentation on Bedrock's core configuration, see [config.js](./lib/config.js).\n\n## How It Works\n\nBedrock is a modular system built on node.js. Node.js modules can\ncommunicate with each other using the ESM API (eg: `export` and\n`import`, etc.), and Bedrock modules are no different. However,\nBedrock also provides some additional low-level subsystems to help modules\ncoordinate. These include: `bedrock.config`, `bedrock.events`,\n`bedrock.loggers`, and `bedrock.util`.\n\nTo create a Bedrock project, all you need to do is create a JavaScript file,\nfor example `project.js`, that imports `bedrock`, any other Bedrock modules\nyou're interested in, and that then calls `bedrock.start()`. To run your\nproject, run:\n\n```sh\nnode project.js\n```\n\nIf you're developing your project and you have installed all of the development\npackages for the Bedrock modules you're using, you can also easily test your\nproject and any of the modules it has included by running:\n\n```sh\nnode project.js test\n```\n\nThis will execute Bedrock's built-in test framework, running all of the tests\nthat each module has written. This approach ensures you're running tests for\nyour entire project and its dependencies.\n\n### bedrock.config\n\nBedrock has a simple, but highly-customizable configuration system. All\nconfiguration variables are stored in a shared JavaScript object\n`bedrock.config`. The object is partitioned into separate configuration objects\nthat are identified by the object's keys. For example Bedrock introduces the\n`cli`, `core`, `constants`, and `loggers` object keys. The best\npractice for modules to claim their own area in the configuration object is to\ninsert their default configuration object using a key that either matches their\nmodule name or that matches their module name minus any `bedrock-` prefix. For\nexample, the [bedrock-server][] module's specific configuration object can be\nfound under `bedrock.config.server`. A `mycompany-feature` module would be\nfound under `bedrock.config['mycompany-feature']`. Modules may define whatever\nconfiguration variables they want to using whatever format is appropriate for\ntheir own use.\n\nThe `bedrock.util` module has helpers to setup configurations, and in\nparticular, dynamically computed configurations. Computed values can help to\nsimplify dependency issues by allowing values to be computed at runtime from a\nfunction or string template. (Note there is a small cost with computed config\nvalues which could be important depending on the use case.)\n\n`bedrock.util.config.Config` creates a wrapper around a config object and\noptional options. This wrapper exposes a new, helpful API that is detailed\nbelow. A common setup could look like the following.\n\n```js\n// an empty config object\nlet config = {};\n// common options\nlet options = {\n  // the config\n  config: config\n  // local vars used during string template evaluation\n  locals: config\n};\n// wrap the config\nlet c = new bedrock.util.config.Config(config, options);\n```\n\nBedrock provides a shared wrapper around the common `bedrock.config` as\n`bedrock.util.config.main`.\n\nTo do simple sets of config data, use the `set()` API.\n\n```js\nlet c = bedrock.util.config.main;\n// set a config variable with a path\n// path components are created as needed\nc.set('server.port', 8443);\n// config is now {\"server\": {\"port\": 8443}}\n```\n\nNormal code and the config API can be mixed. A useful helper is `setDefault()`.\nThis call lets you simplify ensuring a full object path exists before setting\ndata. Objects in the path are created as needed.\n\n```js\nlet config = bedrock.config;\nlet c = bedrock.util.config.main;\n// create container object if needed\nc.setDefault('accounts.admin', {});\n// the config is just a normal object\nconfig.accounts.admin.name = 'Ima Admin';\nc.set('accounts.admin.id', 1);\n// the config object is returned from setDefault()\nlet account123 = c.setDefault('accounts.account123', {});\naccount123.id = 123;\naccount123.name = 'Account 123';\n```\n\nComputed config values using the `setComputed()` API add on a much more\npowerful feature where values will be calculated at runtime.\n\n```js\nlet config = bedrock.config;\n// get the Config wrapper for the default bedrock.config\nlet c = bedrock.util.config.main;\n// set static values\nc.set('server.port', 8443);\nc.set('server.domain', 'bedrock.dev');\n// set a computed value that uses values from the main config\nc.setComputed('server.host', () =\u003e {\n  return config.server.domain + ':' + config.server.port;\n});\nconsole.log(config.server.host); // \"bedrock.dev:8443\"\n```\n\nThe logic for a computed value can be any normal code. If source config values\nare updated the computed values will reflect the change.\n\n```js\nlet config = bedrock.config;\nlet c = bedrock.util.config.main;\nc.set('server.port', 8443);\nc.set('server.domain', 'bedrock.dev');\nc.setComputed('server.host', () =\u003e {\n  // only add the port if it's not the well known default\n  if(config.server.port !== 443) {\n    return config.server.domain + ':' + config.server.port;\n  }\n  return config.server.domain;\n});\nconsole.log(config.server.host); // \"bedrock.dev:8443\"\nc.set('server.port', 443);\nconsole.log(config.server.host); // \"bedrock.dev\"\n```\n\n`setComputed()` can be verbose. a wrapper can be created using the standard\n`bind()` functionality. A helper called `computer()` will do this for you.\n```js\nlet config = bedrock.config;\nlet cc = bedrock.util.config.main.computer();\ncc('server.host', () =\u003e {\n  // only add the port if it's not the well known default\n  if(config.server.port !== 443) {\n    return config.server.domain + ':' + config.server.port;\n  }\n  return config.server.domain;\n});\n```\n\nComputed values can also be created with [lodash-style string\ntemplates](https://lodash.com/docs/#template).\n\n```js\nlet config = bedrock.config;\nlet cc = bedrock.util.config.main.computer();\ncc('server.baseUri', 'https://${server.host}');\nconsole.log(config.server.baseUri); // \"https://bedrock.dev:8443\"\n// use locals option to simplify templates\ncc('base.computed', '${base.a}:${base.b}:${base.c}');\ncc('base.computed', '${a}:${b}:${c}', {locals: config.base});\n```\n\nSetting or computing multiple values with one call uses an object notation:\n\n```js\nlet c = bedrock.util.config.main;\nlet cc = c.computer();\nc.set({\n  'server.port': 8443,\n  'server.domain': 'bedrock.dev',\n  'server.name': 'Bedrock Dev',\n  'users.admin.id': 1\n});\ncc({\n  'server.url': 'https://${server.domain}:${server.port}',\n  'users.admin.url': '${server.url}/users/${users.admin.id}'\n});\n```\n\nComputed values can be added to an array using indexing or the `pushComputed`\nfeature. If indexing is used the array must already exist or the\n`{parentDefault: []}` option should be used. `pushComputed` will create the\nparent array if needed.\n\n```js\nlet config = bedrock.config;\nlet c = bedrock.util.config.main;\nlet cc = c.computer();\ncc('server.baseUri', 'https://${server.host}');\nc.setDefault('resources', []);\ncc('resources[0]', '${server.baseUri}/r/0');\nc.pushComputed('resources', '${server.baseUri}/r/1');\n```\n\n### bedrock.events\n\nIt's sometimes necessary to allow modules to coordinate with each other in\nan orderly fashion. To achieve this, Bedrock provides an event API. Bedrock's\nevent API is very similar to node's built-in EventEmitter, but it provides a\nfew additional features.\n\nIn particular, when emitting an event, Bedrock can wait for a listener to run\nasynchronous code before executing the next listener. This allows each listener\nto run synchronously or asynchronously, depending on their individual needs,\nwithout worrying that the next listener or the next event will be emitted\nbefore they have completed what they need to do.\n\nBedrock's event system also provides another feature, which is the ability to\ncancel events. Event cancelation allows modules to build-in default behavior\nthat can be canceled by other modules. Whenever a synchronous listener returns\n`false` or an asynchronous listener resolves to `false`, the event will not be\nemitted to the remaining listeners, and the emit call will resolve to `false`\nallowing the emitter to take a different action.\n\nTo a emit an event:\n\n```js\ntry {\n  const result = await bedrock.events.emit('example-module.foo', data);\n  if(result === false) {\n    console.log('the event was canceled, but not due to an error');\n  }\n} catch(err) {\n  console.log('an error occurred in a listener and the event was canceled');\n}\nconsole.log('the event was not canceled');\n```\n\nTo create a synchronous listener:\n\n```js\nbedrock.events.on('example-module.foo', function(data) {\n  if(anErrorOccurred) {\n    throw new Error('foo');\n  }\n  if(shouldCancel) {\n    return false;\n  }\n  // do something synchronous\n});\n```\n\nTo create an asynchronous listener:\n\n```js\nbedrock.events.on('example-module.promise', data =\u003e {\n  return new Promise((resolve, reject) =\u003e {\n    if(anErrorOccurred) {\n      reject(throw new Error('foo'));\n      return;\n    }\n    if(shouldCancel) {\n      resolve(false);\n      return;\n    }\n    // do something asynchronous, other listeners won't execute and event\n    // emission won't continue until you resolve the promise\n    process.nextTick(() =\u003e {\n      resolve();\n    });\n  });\n});\nbedrock.events.on('example-module.async-await', async data =\u003e {\n  if(anErrorOccurred) {\n    throw new Error('foo');\n  }\n  if(shouldCancel) {\n    return false;\n  }\n  // do something asynchronous, other listeners won't execute and event\n  // emission won't continue until you return\n  await myFunction();\n});\n```\n\nNote that the asynchronous Promise analog for throwing an error is rejecting\nthe Promise with an error and the analog for returning a value (typically only\nused for event cancelation) is to resolve the Promise with the value.\n\nBedrock core emits several events that modules may listen for. These events\nfall into three possible namespaces: `bedrock-cli`, `bedrock-loggers` and\n`bedrock`. The `bedrock-cli` events are emitted to allow coordination with\nBedrock's command line interface. The `bedrock-loggers.init` event is emitted\nafter the `bedrock-cli.init` event. The `bedrock` events are emitted after\nall the `bedrock-cli` events, unless a listener cancels the `bedrock-cli.ready`\nevent or causes the application to exit early.\n\n- **bedrock-cli.init**\n  - Emitted before command line parsing. Allows registration of new\n    subcommands.\n- **bedrock-cli.parsed**\n  - Emitted after command line parsing. Allows for configuration of loggers\n    based on command line flags. For instance, a logger may provide for the\n    specification of a `logGroupName` that may be computed at runtime based on\n    some command line flag(s).\n- **bedrock-loggers.init**\n  - Emitted after command line parsing. Allows registration of new logging\n    transports prior to initialization of the logging subsystem.\n- **bedrock-cli.ready**\n  - Emitted after command line parsing and logging initialization. Allows\n    execution of subcommands or the prevention of `bedrock` events from being\n    emitted, either by canceling this event or by exiting the application\n    early.\n- **bedrock.configure**\n  - Emitted after `bedrock-cli.ready` and before `bedrock.admin.init`. Allows\n    additional custom configuration before Bedrock initializes but after\n    command line parsing.\n- **bedrock.admin.init**\n  - Emitted after `bedrock.configure` and before elevated process privileges\n    are dropped. Allows listeners to perform early initialization tasks that\n    require special privileges. Note that, if Bedrock is started with elevated\n    privileges (ie: as root), listeners will execute with those privileges. Any\n    early initialization that needs to execute before `bedrock.start` but does\n    not require elevated privileges should be deferred to `bedrock.init`. Most\n    modules should find binding to `bedrock.init` to be sufficient for any\n    initialization work.\n- **bedrock.init**\n  - Emitted after `bedrock.admin.init` and just after elevated process\n    privileges are dropped. Allows listeners to perform early initialization\n    tasks that do not require special privileges. This event should be used to\n    ensure, for example, that a module's API has the required supporting data\n    structures in memory prior to another module's use of it. For example, a\n    validation module may need to load validation schemas from files on disk\n    before they can be accessed via its API, but this loading must occur after\n    the configuration events have passed and after special process privileges\n    have been dropped. **As a best practice, modules should not emit custom\n    events during `bedrock.init` because it may cause scenarios where two\n    unrelated modules can't be easily combined.** For example, if a module\n    emits a custom event during `bedrock.init`, then a listener of that event\n    would be unable to use the API of an unrelated module that hasn't been\n    initialized yet. Deferring custom event emitting to `bedrock.start` solves\n    this problem; it ensures all modules have had a chance to complete\n    initialization before attempting to interact with one another through the\n    event system.\n- **bedrock.start**\n  - Emitted after `bedrock.init`. This is the event modules should use to\n    execute or schedule their main background behavior and to emit any custom\n    events they would like to make available to their dependents.\n- **bedrock.ready**\n  - Emitted after `bedrock.start`. Allows listeners to execute custom behavior\n    after all modules have handled the `bedrock.start` event. This event is\n    useful for turning on external access to web services or other modular\n    systems that should now be fully ready for use. It can also be used to run\n    analysis on modules that have started, for example, to build live\n    documentation.\n- **bedrock.started**\n  - Emitted after `bedrock.ready`. External access to web services or other\n    features provided by modules should now be available. Allows custom\n    subcommands or behavior to run after Bedrock has fully started, eg: tests.\n- **bedrock.tests.run**\n  - Emitted during `bedrock.started`. Once Bedrock has fully started, this\n    event is emitted to inform test frameworks to run their tests. Listeners\n    are passed a test state object with a `pass` property that they can set to\n    `false` to indicate to the test subsystem that at least one test did not\n    pass. Test frameworks may add their own information to the state object\n    using a property matching their framework name.\n- **bedrock.stop**\n  - Emitted while exiting if process was previous in a started state. This is\n    the event modules should use to stop services for a clean shutdown and to\n    emit any custom events they would like to make available to their\n    dependents.\n- **bedrock.stopped**\n  - Emitted while exiting, and after `bedrock.stop` if process was previously\n    in a started state. External access to web services or other features\n    provided by modules should now be unavailable.\n- **bedrock.exit**\n  - Emitted immediately before exiting.\n\n### bedrock.loggers\n\nBedrock has a built-in logging subsystem based on [winston][]. Anything you\ncan do with [winston][], you can do with Bedrock. Bedrock provides a set of\ndefault loggers that are suitable for most applications. The main application\nlogger can be retrieved via `bedrock.loggers.get('app')`. A call to\n`bedrock.loggers.addTransport` can be made in event handlers of the\n`bedrock-loggers.init` event to add new [winston][] transports. Logging\ncategories (such as `app`) and the transports used by them can be configured\nvia `bedrock.config`.\n\nBedrock supports multi-level child loggers with common metadata. These are\ncreated with `bedrock.loggers.get('app').child({...})`. Provided metadata will\nbe added to child log output. A special `module` meta name can optionally be\nused for pretty output. A shortcut for creating named module loggers is\n`bedrock.loggers.get('app').child('name')`.\n\nModule prefix display can be controlled per-category:\n\n```js\n// get a child logger with custom module name\nlet logger = bedrock.loggers.get('app').child('my-module');\n\n// message module prefix controlled with a per-category config value\nbedrock.config.loggers.app.bedrock.modulePrefix = false;\nlogger.info('an info message');\n// module displayed as normal meta data:\n// 2017-06-30T12:34:56.789Z - info: an info message workerPid=1234, module=my-module\n\n// with module prefix enabled:\nbedrock.config.loggers.app.bedrock.modulePrefix = true;\nlogger.info('an info message');\n// displayed as an nice message prefix:\n// 2017-06-30T12:34:56.789Z - info: [my-module] an info message workerPid=1234\n```\n\n### bedrock.util\n\nBedrock provides a number of helpful general purpose utilities. For example,\nBedrock defines a `BedrockError` class that extends the default `Error`\nclass. A `BedrockError` can keep track of a series of \"causes\" (other errors)\nthat allow developers to better understand why an error occurred.\n`BedrockError`s can also be marked as `public`, which allows modules that\nmay, for example, serve error information over the Web to display more error\ndetails. `bedrock.util` also contains tools for formatting dates,\nextending/merging/cloning objects, and generating UUIDs.\n\n## Recommended Modules\n\n\u003c!-- TODO: Change section to \"If you want to do X, use these modules\" format --\u003e\n\n[bedrock-server][] provides a core, cluster-based HTTPS server.\n\n[bedrock-express][] provides an Express server with reasonable\ndefaults and extra features like the ability to layer static\nfiles and directories to support overrides.\n\n[bedrock-mongodb][] provides an API for connecting to a MongoDB\ndatabase and creating and using collections.\n\n[bedrock-webpack][] provides webpack configuration and build tools for\nfrontend bundling.\n\n[bedrock-views][] provides infrastructure for serving single page\napplications.\n\n[bedrock-vue][] layers on top of [bedrock-views][] to provide\nclient-rendered Vue.js views.\n\n[bedrock-quasar][] layers on top of [bedrock-vue][] to provide\nclient-rendered Quasar components.\n\n[bedrock-account][] provides user account management.\n\nOther Bedrock modules provide REST APIs, user account management, strong\ncryptography support, DoS protection, digital signatures, Linked Data, and\ntons of other [FEATURES][]. If you don't need all the fancy features, Bedrock\nis modular, so you can use only the modules you want.\n\n## Quickstart\n\nYou can follow the following tutorial to setup and use Bedrock on a Linux or\nMac OS X development machine.\n\n## Requirements\n\n* Linux, Mac OS X, Windows\n* node.js \u003e= 18.x\n* npm \u003e= 9.x\n\nRunning Bedrock\n---------------\n\nRun the following to start up a development server from the source directory:\n\n```sh\nnode index.js\n```\n\nTo add more verbose debugging, use the `--log-level` option:\n\n```sh\nnode index.js --log-level debug\n```\n\nRunning the Tests\n-----------------\n\nRun all tests:\n\n```sh\nnpm test\n```\n\nRun only the mocha test framework:\n\n```sh\nnode index.js test --framework mocha\n```\n\nRun a specific mocha test:\n\n```sh\nnode index.js test --framework mocha --mocha-test tests/test.js\n```\n\nRunning the Code Coverage Tool\n------------------------------\n\n```sh\nnpm run coverage\n```\n\nLook at `coverage.html` using a web browser\n\nFeatures\n--------\n\nFor an example list of features provided by Bedrock modules, see the\n[FEATURES][] file.\n\nFAQ\n---\n\nSee the [FAQ][] file for answers to frequently asked questions.\n\nHacking\n-------\n\nSee the [CONTRIBUTING][] file for various details for coders about\nhacking on this project.\n\nAuthors\n-------\n\nSee the [AUTHORS][] file for author contact information.\n\nLicense\n-------\n\n[Apache License, Version 2.0](LICENSE) Copyright 2011-2024 Digital Bazaar, Inc.\n\nOther Bedrock libraries are available under a non-commercial license for uses\nsuch as self-study, research, personal projects, or for evaluation purposes.\nSee the\n[Bedrock Non-Commercial License v1.0](https://github.com/digitalbazaar/bedrock/blob/main/LICENSES/LicenseRef-Bedrock-NC-1.0.txt)\nfor details.\n\nCommercial licensing and support are available by contacting\n[Digital Bazaar](https://digitalbazaar.com/) \u003csupport@digitalbazaar.com\u003e.\n\n[AUTHORS]: AUTHORS.md\n[FEATURES]: FEATURES.md\n[CONTRIBUTING]: CONTRIBUTING.md\n[FAQ]: FAQ.md\n[Vue.js]: https://vuejs.org/\n[JSON-LD]: http://json-ld.org\n[JSON-LD context]: http://www.w3.org/TR/json-ld/#the-context\n[Linked Data]: http://en.wikipedia.org/wiki/Linked_data\n[bedrock-account]: https://github.com/digitalbazaar/bedrock-account\n[bedrock-account-http]: https://github.com/digitalbazaar/bedrock-account-http\n[bedrock-authn-token]: https://github.com/digitalbazaar/bedrock-authn-token\n[bedrock-app-identity]: https://github.com/digitalbazaar/bedrock-app-identity\n[bedrock-edv-storage]: https://github.com/digitalbazaar/bedrock-edv-storage\n[bedrock-express]: https://github.com/digitalbazaar/bedrock-express\n[bedrock-kms]: https://github.com/digitalbazaar/bedrock-kms\n[bedrock-kms-http]: https://github.com/digitalbazaar/bedrock-kms-http\n[bedrock-meter]: https://github.com/digitalbazaar/bedrock-meter\n[bedrock-mongodb]: https://github.com/digitalbazaar/bedrock-mongodb\n[bedrock-quasar]: https://github.com/digitalbazaar/bedrock-quasar\n[bedrock-server]: https://github.com/digitalbazaar/bedrock-server\n[bedrock-validation]: https://github.com/digitalbazaar/bedrock-validation\n[bedrock-views]: https://github.com/digitalbazaar/bedrock-views\n[bedrock-vue]: https://github.com/digitalbazaar/bedrock-vue\n[bedrock-web]: https://github.com/digitalbazaar/bedrock-web\n[bedrock-webpack]: https://github.com/digitalbazaar/bedrock-webpack\n[winston]: https://github.com/winstonjs/winston\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalbazaar%2Fbedrock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigitalbazaar%2Fbedrock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalbazaar%2Fbedrock/lists"}