| 
									
										
										
										
											2019-10-31 00:12:01 -06:00
										 |  |  | # [greenlock-manager-test.js](https://git.rootprojects.org/root/greenlock-manager-test.js)
 | 
					
						
							| 
									
										
										
										
											2019-10-31 04:56:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | A simple test suite for Greenlock v3 manager plugins. | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Greenlock Manager
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | A Greenlock Manager is responsible for tracking which domains | 
					
						
							|  |  |  | belong on a certificate, when they are scheduled for renewal, | 
					
						
							|  |  |  | and if they have been deleted. | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | It consists of two required functions: | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | ```js | 
					
						
							|  |  |  | set({ subject, altnames, renewAt, deletedAt }); | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | ```js | 
					
						
							|  |  |  | get({ servername }); | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | However, if you implement `find({ subject, servernames, renewBefore })` (optional), | 
					
						
							|  |  |  | you don't have to implement `get()`. | 
					
						
							| 
									
										
										
										
											2019-10-31 00:09:09 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | <details> | 
					
						
							|  |  |  | <summary>Usage Details</summary> | 
					
						
							|  |  |  | # How to use your plugin
 | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | The **Right Way**: | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | ```bash | 
					
						
							|  |  |  | npm install --save greenlack | 
					
						
							|  |  |  | npx greenlock init --manager ./path-or-npm-name.js --manager-xxxx 'sets xxxx' --manager-yyyy 'set yyyy' | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | That creates a `.greenlockrc`, which is essentially the same as doing this: | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | ```js | 
					
						
							|  |  |  | var Greenlock = require("greenlock"); | 
					
						
							|  |  |  | var greenlock = Greenlock.create({ | 
					
						
							|  |  |  |     // ... | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |     manager: "./path-or-npm-name.js", | 
					
						
							|  |  |  |     xxxx: "sets xxxx", | 
					
						
							|  |  |  |     yyyy: "sets yyyy", | 
					
						
							|  |  |  |     packageRoot: __dirname | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | ## Why no require?
 | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | Okay, so you **expect** it to look like this: | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | var Greenlock = require("greenlock"); | 
					
						
							|  |  |  | var greenlock = Greenlock.create({ | 
					
						
							|  |  |  |     // WRONG!! | 
					
						
							|  |  |  |     manager: require("./path-or-npm-name.js").create({ | 
					
						
							|  |  |  |         someOptionYouWant: true | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | **NOPE**! | 
					
						
							| 
									
										
										
										
											2019-10-31 00:09:09 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | Greenlock is designed to so that the CLI tools, Web API, and JavaScript API | 
					
						
							|  |  |  | can all work interdepedently, indpendently. | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | Therefore the configuration has to go into serializable JSON rather than | 
					
						
							|  |  |  | executable JavaScript. | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | </details> | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | # Quick Start
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If you want to write a manager, | 
					
						
							|  |  |  | the best way to start is by using one of the provided templates. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | npm install --save-dev greenlock-manager-test | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | npx greenlock-manager-init | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | It will generate a bare bones manager that passes the tests, | 
					
						
							|  |  |  | (skipping all optional features), and a test file: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <details> | 
					
						
							|  |  |  | <summary>manager.js</summary> | 
					
						
							| 
									
										
										
										
											2019-11-04 21:04:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | ```js | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Manager = module.exports; | 
					
						
							|  |  |  | var db = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Manager.create = function(opts) { | 
					
						
							| 
									
										
										
										
											2019-11-04 21:04:39 -07:00
										 |  |  |     var manager = {}; | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     // REQUIRED (basic issuance) | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Get | 
					
						
							|  |  |  |     manager.get = async function({ servername, wildname }) { | 
					
						
							|  |  |  |         // Required: find the certificate with the subject of `servername` | 
					
						
							|  |  |  |         // Optional (multi-domain certs support): find a certificate with `servername` as an altname | 
					
						
							|  |  |  |         // Optional (wildcard support): find a certificate with `wildname` as an altname | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // { subject, altnames, renewAt, deletedAt, challenges, ... } | 
					
						
							|  |  |  |         return db[servername] || db[wildname]; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Set | 
					
						
							|  |  |  |     manager.set = async function(opts) { | 
					
						
							|  |  |  |         // { subject, altnames, renewAt, deletedAt } | 
					
						
							|  |  |  |         // Required: updated `renewAt` and `deletedAt` for certificate matching `subject` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         var site = db[opts.subject] || {}; | 
					
						
							|  |  |  |         db[opts.subject] = Object.assign(site, opts); | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     // Optional (Fully Automatic Renewal) | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     /* | 
					
						
							|  |  |  |     manager.find = async function(opts) { | 
					
						
							|  |  |  |         // { subject, servernames, altnames, renewBefore } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return [{ subject, altnames, renewAt, deletedAt }]; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     //*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     // Optional (Special Remove Functionality) | 
					
						
							|  |  |  |     // The default behavior is to set `deletedAt` | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     /* | 
					
						
							|  |  |  |     manager.remove = async function(opts) { | 
					
						
							|  |  |  |     	return mfs.remove(opts); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     //*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     // Optional (special settings save) | 
					
						
							|  |  |  |     // Implemented here because this module IS the fallback | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     /* | 
					
						
							|  |  |  |     manager.defaults = async function(opts) { | 
					
						
							|  |  |  |         if (opts) { | 
					
						
							|  |  |  |             return setDefaults(opts); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return getDefaults(); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     //*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     // Optional (for common deps and/or async initialization) | 
					
						
							|  |  |  |     // | 
					
						
							|  |  |  |     /* | 
					
						
							|  |  |  |     manager.init = async function(deps) { | 
					
						
							|  |  |  |         manager.request = deps.request; | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     //*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return manager; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2019-11-04 21:04:39 -07:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | </details> | 
					
						
							| 
									
										
										
										
											2019-11-04 21:04:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | <details> | 
					
						
							|  |  |  | <summary>manager.test.js</summary> | 
					
						
							| 
									
										
										
										
											2019-11-04 21:04:39 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | ```js | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | "use strict"; | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | var Tester = require("greenlock-manager-test"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var Manager = require("./manager.js"); | 
					
						
							|  |  |  | var config = { | 
					
						
							|  |  |  |     configFile: "greenlock-manager-test.delete-me.json" | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | Tester.test(Manager, config) | 
					
						
							|  |  |  |     .then(function(features) { | 
					
						
							|  |  |  |         console.info("PASS"); | 
					
						
							|  |  |  |         console.info(); | 
					
						
							|  |  |  |         console.info("Optional Feature Support:"); | 
					
						
							|  |  |  |         features.forEach(function(feature) { | 
					
						
							| 
									
										
										
										
											2019-11-04 21:04:39 -07:00
										 |  |  |             console.info( | 
					
						
							|  |  |  |                 feature.supported ? "✓ (YES)" : "✘ (NO) ", | 
					
						
							|  |  |  |                 feature.description | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |         console.info(); | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  |     }) | 
					
						
							|  |  |  |     .catch(function(err) { | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |         console.error("Oops, you broke it. Here are the details:"); | 
					
						
							|  |  |  |         console.error(err.stack); | 
					
						
							|  |  |  |         console.error(); | 
					
						
							|  |  |  |         console.error("That's all I know."); | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-11-04 21:04:39 -07:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | node manager.test.js | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | ```txt | 
					
						
							|  |  |  | PASS:  get({ servername, wildname }) | 
					
						
							|  |  |  | PASS:  set({ subject }) | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | Optional Feature Support: | 
					
						
							|  |  |  | ✘ (NO)  Multiple Domains per Certificate | 
					
						
							|  |  |  | ✘ (NO)  Wildcard Certificates | 
					
						
							|  |  |  | ✘ (NO)  Fully Automatic Renewal | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | # Optional Features
 | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | If you're publishing a module to the community, | 
					
						
							|  |  |  | you should implement the full test suite (and it's not that hard). | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | If you're only halfway through, you should note | 
					
						
							|  |  |  | which features are supported and which aren't. | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | ```js | 
					
						
							|  |  |  | find({ subject, servernames, renewBefore }); | 
					
						
							|  |  |  | defaults({ subscriberEmail, agreeToTerms, challenges, store, ... }); | 
					
						
							|  |  |  | defaults(); // as getter | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | -   `find()` is used to get the full list of sites, for continuous fully automatic renewal. | 
					
						
							|  |  |  | -   `defaults()` exists so that the global config can be saved in the same place as the per-site config. | 
					
						
							|  |  |  | -   a proper `get()` should be able to search not just primary domains, but altnames as well. | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | Additionally, you're manager may need an init or a _real_ delete - rather than just using `set({ deletedAt })`: | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | init({ request }); | 
					
						
							|  |  |  | remove({ subject }); | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | <details> | 
					
						
							|  |  |  | <summary>Full Implementation</summary> | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | # The Right Way™
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If you want to publish a module to the community you should do a slightly better job: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | module.exports.create = function(options) { | 
					
						
							|  |  |  |     var manager = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // add some things to... wherever you save things | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     manager.set = async function(siteConfig) { | 
					
						
							|  |  |  |         // You can see in the tests a sample of common values, | 
					
						
							|  |  |  |         // but you don't really need to worry about it. | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |         var subject = siteConfig.subject; | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Cherry pick what you like for indexing / search, and JSONify the rest | 
					
						
							|  |  |  |         return mergeOrCreateSite(subject, siteConfig); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // find the things you've saved before | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |     manager.get = async function({ servername }) { | 
					
						
							|  |  |  |         return getSiteByAltname(servername); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     manager.find = async function({ subject, servernames, renewBefore }) { | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  |         var results = []; | 
					
						
							|  |  |  |         var gotten = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (subject) { | 
					
						
							|  |  |  |             var site = await getSiteBySubject(subject); | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |             if (site && site.subject === subject) { | 
					
						
							|  |  |  |                 return [site]; | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |         if (severnames) { | 
					
						
							|  |  |  |             return await Promise.all(servernames.map(function (altname) { | 
					
						
							|  |  |  |                 var site = getSiteByAltname(subject); | 
					
						
							|  |  |  |                 if (site && !gotten[site.subject]) { | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  |                     gotten[site.subject] = true; | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |                     return site; | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  |         return getSitesThatShouldBeRenewedBefore(renewBefore || Infinity); | 
					
						
							| 
									
										
										
										
											2019-10-31 00:07:33 -06:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // delete a site config | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     manager.remove = async function({ subject }) { | 
					
						
							|  |  |  |         // set deletedAt to a value, or actually delete it - however you like | 
					
						
							|  |  |  |         return mergeOrCreateSite(subject, { deletedAt: Date.now() }); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // get / set global things | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     manager.defaults = async function(options) { | 
					
						
							|  |  |  |         if (!options) { | 
					
						
							|  |  |  |             return getDefaultConfigValues(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return mergeDefaultConfigValues(options); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // optional, if you need it | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     manager.init = async function(deps) { | 
					
						
							|  |  |  |         // a place to do some init, if you need it | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return doMyInit(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Also, `deps` will have some common dependencies | 
					
						
							|  |  |  |         // than many modules need, such as `request`. | 
					
						
							|  |  |  |         // This cuts down on stray dependencies, and helps | 
					
						
							|  |  |  |         // with browser compatibility. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         request = deps.request; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 21:03:21 -07:00
										 |  |  | </details> |