1 | <p align="center">
|
2 |
|
3 | <a href="https://github.com/node-base/base">
|
4 | <img height="250" width="250" src="https://raw.githubusercontent.com/node-base/base/master/docs/logo.png">
|
5 | </a>
|
6 | </p>
|
7 |
|
8 | # base
|
9 |
|
10 | [![NPM version](https://img.shields.io/npm/v/base.svg?style=flat)](https://www.npmjs.com/package/base) [![NPM monthly downloads](https://img.shields.io/npm/dm/base.svg?style=flat)](https://npmjs.org/package/base) [![Build Status](https://img.shields.io/travis/node-base/base.svg?style=flat)](https://travis-ci.org/node-base/base) [![Gitter](https://badges.gitter.im/join_chat.svg)](https://gitter.im/node-base/base)
|
11 |
|
12 | <details>
|
13 | <summary><strong>Table of contents</strong></summary>
|
14 |
|
15 | - [Why use Base?](#why-use-base)
|
16 | * [Guiding principles](#guiding-principles)
|
17 | * [Minimal API surface](#minimal-api-surface)
|
18 | * [Composability](#composability)
|
19 | - [Install](#install)
|
20 | - [Install](#install-1)
|
21 | - [Usage](#usage)
|
22 | - [API](#api)
|
23 | - [cache object](#cache-object)
|
24 | - [Toolkit suite](#toolkit-suite)
|
25 | * [What is Toolkit?](#what-is-toolkit)
|
26 | - [About](#about)
|
27 | * [Related projects](#related-projects)
|
28 | * [Tests](#tests)
|
29 | * [Contributing](#contributing)
|
30 | * [Release History](#release-history)
|
31 | * [Authors](#authors)
|
32 | * [License](#license)
|
33 |
|
34 | </details>
|
35 |
|
36 | <details>
|
37 | <summary><strong>About</strong></summary>
|
38 |
|
39 | ## Why use Base?
|
40 |
|
41 | Base is a foundation for creating modular, unit testable and highly pluggable server-side node.js APIs.
|
42 |
|
43 | * Go from zero to working application within minutes
|
44 | * Use [community plugins](https://www.npmjs.com/browse/keyword/baseplugin) to add feature-functionality to your application
|
45 | * Create your own custom plugins to add features
|
46 | * Like building blocks, plugins are stackable. Allowing you to build [sophisticated applications](#toolkit-suite) from simple plugins. Moreover, those applications can also be used as plugins themselves.
|
47 |
|
48 | Most importantly, once you learn Base, you will be familiar with the core API of all applications built on Base. This means you will not only benefit as a developer, but as a user as well.
|
49 |
|
50 | ### Guiding principles
|
51 |
|
52 | The core team follows these principles to help guide API decisions:
|
53 |
|
54 | * **Compact API surface**: The smaller the API surface, the easier the library will be to learn and use.
|
55 | * **Easy to extend**: Implementors can use any npm package, and write plugins in pure JavaScript. If you're building complex apps, Base dramatically simplifies inheritance.
|
56 | * **Easy to test**: No special setup should be required to unit test `Base` or base plugins
|
57 | * **100% Node.js core style**
|
58 |
|
59 | - No API sugar (left for higher level projects)
|
60 | - Written in readable vanilla JavaScript
|
61 |
|
62 | ### Minimal API surface
|
63 |
|
64 | [The API](#api) was designed to provide only the minimum necessary functionality for creating a useful application, with or without [plugins](#plugins).
|
65 |
|
66 | **Base core**
|
67 |
|
68 | Base itself ships with only a handful of [useful methods](#api), such as:
|
69 |
|
70 | * `.set`: for setting values on the instance
|
71 | * `.get`: for getting values from the instance
|
72 | * `.has`: to check if a property exists on the instance
|
73 | * `.define`: for setting non-enumerable values on the instance
|
74 | * `.use`: for adding plugins
|
75 |
|
76 | **Be generic**
|
77 |
|
78 | When deciding on method to add or remove, we try to answer these questions:
|
79 |
|
80 | 1. Will all or most Base applications need this method?
|
81 | 2. Will this method encourage practices or enforce conventions that are beneficial to implementors?
|
82 | 3. Can or should this be done in a plugin instead?
|
83 |
|
84 | ### Composability
|
85 |
|
86 | **Plugin system**
|
87 |
|
88 | It couldn't be easier to extend Base with any features or custom functionality you can think of.
|
89 |
|
90 | Base plugins are just functions that take an instance of `Base`:
|
91 |
|
92 | ```js
|
93 | var base = new Base();
|
94 |
|
95 | function plugin(base) {
|
96 | // do plugin stuff, in pure JavaScript
|
97 | }
|
98 | // use the plugin
|
99 | base.use(plugin);
|
100 | ```
|
101 |
|
102 | Add "smart plugin" functionality with the [base-plugins](https://github.com/node-base/base-plugins) plugin.
|
103 |
|
104 | **Inheritance**
|
105 |
|
106 | Easily inherit Base using `.extend`:
|
107 |
|
108 | ```js
|
109 | var Base = require('base');
|
110 |
|
111 | function MyApp() {
|
112 | Base.call(this);
|
113 | }
|
114 | Base.extend(MyApp);
|
115 |
|
116 | var app = new MyApp();
|
117 | app.set('a', 'b');
|
118 | app.get('a');
|
119 | //=> 'b';
|
120 | ```
|
121 |
|
122 | **Inherit or instantiate with a namespace**
|
123 |
|
124 | By default, the `.get`, `.set` and `.has` methods set and get values from the root of the `base` instance. You can customize this using the `.namespace` method exposed on the exported function. For example:
|
125 |
|
126 | ```js
|
127 | var Base = require('base');
|
128 | // get and set values on the `base.cache` object
|
129 | var base = Base.namespace('cache');
|
130 |
|
131 | var app = base();
|
132 | app.set('foo', 'bar');
|
133 | console.log(app.cache.foo);
|
134 | //=> 'bar'
|
135 | ```
|
136 | </details>
|
137 |
|
138 | ## Install
|
139 |
|
140 | **NPM**
|
141 |
|
142 | ## Install
|
143 |
|
144 | Install with [npm](https://www.npmjs.com/):
|
145 |
|
146 | ```sh
|
147 | $ npm install --save base
|
148 | ```
|
149 |
|
150 | **yarn**
|
151 |
|
152 | Install with [yarn](yarnpkg.com):
|
153 |
|
154 | ```sh
|
155 | $ yarn add base && yarn upgrade
|
156 | ```
|
157 |
|
158 | ## Usage
|
159 |
|
160 | ```js
|
161 | var Base = require('base');
|
162 | var app = new Base();
|
163 |
|
164 | // set a value
|
165 | app.set('foo', 'bar');
|
166 | console.log(app.foo);
|
167 | //=> 'bar'
|
168 |
|
169 | // register a plugin
|
170 | app.use(function() {
|
171 | // do stuff (see API docs for ".use")
|
172 | });
|
173 | ```
|
174 |
|
175 | ## API
|
176 |
|
177 | ### [Base](index.js#L43)
|
178 |
|
179 | Create an instance of `Base` with the given `cache` and `options`. Learn about the [cache object](#cache-object).
|
180 |
|
181 | **Params**
|
182 |
|
183 | * `cache` **{Object}**: If supplied, this object is passed to [cache-base](https://github.com/jonschlinkert/cache-base) to merge onto the the instance.
|
184 | * `options` **{Object}**: If supplied, this object is used to initialize the `base.options` object.
|
185 |
|
186 | **Example**
|
187 |
|
188 | ```js
|
189 | // initialize with `cache` and `options`
|
190 | const app = new Base({isApp: true}, {abc: true});
|
191 | app.set('foo', 'bar');
|
192 |
|
193 | // values defined with the given `cache` object will be on the root of the instance
|
194 | console.log(app.baz); //=> undefined
|
195 | console.log(app.foo); //=> 'bar'
|
196 | // or use `.get`
|
197 | console.log(app.get('isApp')); //=> true
|
198 | console.log(app.get('foo')); //=> 'bar'
|
199 |
|
200 | // values defined with the given `options` object will be on `app.options
|
201 | console.log(app.options.abc); //=> true
|
202 | ```
|
203 |
|
204 | ### [.is](index.js#L74)
|
205 |
|
206 | Set the given `name` on `app._name` and `app.is*` properties. Used for doing lookups in plugins.
|
207 |
|
208 | **Params**
|
209 |
|
210 | * `name` **{String}**
|
211 | * `returns` **{Boolean}**
|
212 |
|
213 | **Example**
|
214 |
|
215 | ```js
|
216 | app.is('collection');
|
217 | console.log(app.type);
|
218 | //=> 'collection'
|
219 | console.log(app.isCollection);
|
220 | //=> true
|
221 | ```
|
222 |
|
223 | ### [.isRegistered](index.js#L110)
|
224 |
|
225 | Returns true if a plugin has already been registered on an instance.
|
226 |
|
227 | Plugin implementors are encouraged to use this first thing in a plugin
|
228 | to prevent the plugin from being called more than once on the same
|
229 | instance.
|
230 |
|
231 | **Params**
|
232 |
|
233 | * `name` **{String}**: The plugin name.
|
234 | * `register` **{Boolean}**: If the plugin if not already registered, to record it as being registered pass `true` as the second argument.
|
235 | * `returns` **{Boolean}**: Returns true if a plugin is already registered.
|
236 |
|
237 | **Events**
|
238 |
|
239 | * `emits`: `plugin` Emits the name of the plugin being registered. Useful for unit tests, to ensure plugins are only registered once.
|
240 |
|
241 | **Example**
|
242 |
|
243 | ```js
|
244 | const base = new Base();
|
245 | base.use(function(app) {
|
246 | if (app.isRegistered('myPlugin')) return;
|
247 | // do stuff to `app`
|
248 | });
|
249 |
|
250 | // to also record the plugin as being registered
|
251 | base.use(function(app) {
|
252 | if (app.isRegistered('myPlugin', true)) return;
|
253 | // do stuff to `app`
|
254 | });
|
255 | ```
|
256 |
|
257 | ### [.use](index.js#L139)
|
258 |
|
259 | Call a plugin function or array of plugin functions on the instance. Plugins are called with an instance of base, and options (if defined).
|
260 |
|
261 | **Params**
|
262 |
|
263 | * `name` **{String|Function|Array}**: (optional) plugin name
|
264 | * `plugin` **{Function|Array}**: plugin function, or array of functions, to call.
|
265 | * **{...rest}**: Any additional arguments to pass to plugins(s).
|
266 | * `returns` **{Object}**: Returns the item instance for chaining.
|
267 |
|
268 | **Example**
|
269 |
|
270 | ```js
|
271 | const app = new Base()
|
272 | .use([foo, bar])
|
273 | .use(baz)
|
274 | ```
|
275 |
|
276 | ### [.define](index.js#L178)
|
277 |
|
278 | The `.define` method is used for adding non-enumerable property on the instance. Dot-notation is **not supported** with `define`.
|
279 |
|
280 | **Params**
|
281 |
|
282 | * `key` **{String}**: The name of the property to define.
|
283 | * `value` **{any}**
|
284 | * `returns` **{Object}**: Returns the instance for chaining.
|
285 |
|
286 | **Example**
|
287 |
|
288 | ```js
|
289 | // example of a custom arbitrary `render` function created with lodash's `template` method
|
290 | app.define('render', (str, locals) => _.template(str)(locals));
|
291 | ```
|
292 |
|
293 | ### [.base](index.js#L220)
|
294 |
|
295 | Getter/setter used when creating nested instances of `Base`, for storing a reference to the first ancestor instance. This works by setting an instance of `Base` on the `parent` property of a "child" instance. The `base` property defaults to the current instance if no `parent` property is defined.
|
296 |
|
297 | **Example**
|
298 |
|
299 | ```js
|
300 | // create an instance of `Base`, this is our first ("base") instance
|
301 | const first = new Base();
|
302 | first.foo = 'bar'; // arbitrary property, to make it easier to see what's happening later
|
303 |
|
304 | // create another instance
|
305 | const second = new Base();
|
306 | // create a reference to the first instance (`first`)
|
307 | second.parent = first;
|
308 |
|
309 | // create another instance
|
310 | const third = new Base();
|
311 | // create a reference to the previous instance (`second`)
|
312 | // repeat this pattern every time a "child" instance is created
|
313 | third.parent = second;
|
314 |
|
315 | // we can always access the first instance using the `base` property
|
316 | console.log(first.base.foo);
|
317 | //=> 'bar'
|
318 | console.log(second.base.foo);
|
319 | //=> 'bar'
|
320 | console.log(third.base.foo);
|
321 | //=> 'bar'
|
322 | ```
|
323 |
|
324 | ### [Base.use](index.js#L242)
|
325 |
|
326 | Static method for adding global plugin functions that will be added to an instance when created.
|
327 |
|
328 | **Params**
|
329 |
|
330 | * `fn` **{Function}**: Plugin function to use on each instance.
|
331 | * `returns` **{Object}**: Returns the `Base` constructor for chaining
|
332 |
|
333 | **Example**
|
334 |
|
335 | ```js
|
336 | Base.use(function(app) {
|
337 | app.foo = 'bar';
|
338 | });
|
339 | const app = new Base();
|
340 | console.log(app.foo);
|
341 | //=> 'bar'
|
342 | ```
|
343 |
|
344 | ## cache object
|
345 |
|
346 | **Cache**
|
347 |
|
348 | User-defined properties go on the `cache` object. This keeps the root of the instance clean, so that only reserved methods and properties on the root.
|
349 |
|
350 | ```js
|
351 | Base { cache: {} }
|
352 | ```
|
353 |
|
354 | You can pass a custom object to use as the `cache` as the first argument to the `Base` class when instantiating.
|
355 |
|
356 | ```js
|
357 | const myObject = {};
|
358 | const Base = require('base');
|
359 | const base = new Base(myObject);
|
360 | ```
|
361 |
|
362 | ## Toolkit suite
|
363 |
|
364 | Base is part of the [Toolkit suite](https://github.com/node-toolkit/getting-started) of applications.
|
365 |
|
366 | ### What is Toolkit?
|
367 |
|
368 | Toolkit is a collection of node.js libraries, applications and frameworks for helping developers quickly create high quality node.js applications, web projects, and command-line experiences. There are many other libraries on NPM for handling specific tasks, Toolkit provides the _systems_ and _building blocks_ for creating higher level workflows and processes around those libraries.
|
369 |
|
370 | Toolkit can be used to create a static site generator, blog framework, documentaton system, command line, task or plugin runner, and more!
|
371 |
|
372 | **Building Blocks**
|
373 |
|
374 | The following libraries can be used as "building blocks" for creating modular applications.
|
375 |
|
376 | * [base](https://github.com/node-base/base): (you are here!) framework for rapidly creating high quality node.js applications, using plugins like building blocks. Base serves as the foundation for several other applications in the [Toolkit suite](https://github.com/node-toolkit/getting-started).
|
377 | * [templates](https://github.com/jonschlinkert/templates): Render templates with any node.js template engine, create and manage template collections. Use helpers, layouts, partials, includes...
|
378 | * [enquirer](http://enquirer.io): Plugin-based prompt system for creating highly customizable command line experiences.
|
379 | * [composer](https://github.com/doowb/composer): Plugin-based, async task runner.
|
380 |
|
381 | **Lifecycle Applications**
|
382 |
|
383 | The following applications provide workflows and automation for common phases of the software development lifecycle. Each of these tools can be used entirely standalone or bundled together.
|
384 |
|
385 | * [generate](https://github.com/generate/generate): create projects
|
386 | * [assemble](https://github.com/assemble/assemble): build projects
|
387 | * [verb](https://github.com/verbose/verb): document projects
|
388 | * [update](https://github.com/update/update): maintain projects
|
389 |
|
390 | ## About
|
391 |
|
392 | ### Related projects
|
393 |
|
394 | * [base-cwd](https://www.npmjs.com/package/base-cwd): Base plugin that adds a getter/setter for the current working directory. | [homepage](https://github.com/node-base/base-cwd "Base plugin that adds a getter/setter for the current working directory.")
|
395 | * [base-data](https://www.npmjs.com/package/base-data): adds a `data` method to base-methods. | [homepage](https://github.com/node-base/base-data "adds a `data` method to base-methods.")
|
396 | * [base-fs](https://www.npmjs.com/package/base-fs): base-methods plugin that adds vinyl-fs methods to your 'base' application for working with the file… [more](https://github.com/node-base/base-fs) | [homepage](https://github.com/node-base/base-fs "base-methods plugin that adds vinyl-fs methods to your 'base' application for working with the file system, like src, dest, copy and symlink.")
|
397 | * [base-generators](https://www.npmjs.com/package/base-generators): Adds project-generator support to your `base` application. | [homepage](https://github.com/node-base/base-generators "Adds project-generator support to your `base` application.")
|
398 | * [base-option](https://www.npmjs.com/package/base-option): Adds a few options methods to base, like `option`, `enable` and `disable`. See the readme… [more](https://github.com/node-base/base-option) | [homepage](https://github.com/node-base/base-option "Adds a few options methods to base, like `option`, `enable` and `disable`. See the readme for the full API.")
|
399 | * [base-pipeline](https://www.npmjs.com/package/base-pipeline): base-methods plugin that adds pipeline and plugin methods for dynamically composing streaming plugin pipelines. | [homepage](https://github.com/node-base/base-pipeline "base-methods plugin that adds pipeline and plugin methods for dynamically composing streaming plugin pipelines.")
|
400 | * [base-pkg](https://www.npmjs.com/package/base-pkg): Plugin for adding a `pkg` method that exposes pkg-store to your base application. | [homepage](https://github.com/node-base/base-pkg "Plugin for adding a `pkg` method that exposes pkg-store to your base application.")
|
401 | * [base-plugins](https://www.npmjs.com/package/base-plugins): Adds 'smart plugin' support to your base application. | [homepage](https://github.com/node-base/base-plugins "Adds 'smart plugin' support to your base application.")
|
402 | * [base-questions](https://www.npmjs.com/package/base-questions): Plugin for base-methods that adds methods for prompting the user and storing the answers on… [more](https://github.com/node-base/base-questions) | [homepage](https://github.com/node-base/base-questions "Plugin for base-methods that adds methods for prompting the user and storing the answers on a project-by-project basis.")
|
403 | * [base-store](https://www.npmjs.com/package/base-store): Plugin for getting and persisting config values with your base-methods application. Adds a 'store' object… [more](https://github.com/node-base/base-store) | [homepage](https://github.com/node-base/base-store "Plugin for getting and persisting config values with your base-methods application. Adds a 'store' object that exposes all of the methods from the data-store library. Also now supports sub-stores!")
|
404 | * [base-task](https://www.npmjs.com/package/base-task): Base plugin that provides a very thin wrapper around [https://github.com/doowb/composer](https://github.com/doowb/composer) for adding task methods to… [more](https://github.com/base/base-task) | [homepage](https://github.com/base/base-task "Base plugin that provides a very thin wrapper around <https://github.com/doowb/composer> for adding task methods to your Base application.")
|
405 |
|
406 | ### Tests
|
407 |
|
408 | Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
|
409 |
|
410 | ```sh
|
411 | $ npm install && npm test
|
412 | ```
|
413 |
|
414 | ### Contributing
|
415 |
|
416 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
|
417 |
|
418 | If Base doesn't do what you need, [please let us know](../../issues).
|
419 |
|
420 | ### Release History
|
421 |
|
422 | See the [changelog](CHANGELOG.md);
|
423 |
|
424 | ### Authors
|
425 |
|
426 | **Jon Schlinkert**
|
427 |
|
428 | * [github/jonschlinkert](https://github.com/jonschlinkert)
|
429 | * [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
|
430 |
|
431 | **Brian Woodward**
|
432 |
|
433 | * [github/doowb](https://github.com/doowb)
|
434 | * [twitter/doowb](http://twitter.com/doowb)
|
435 |
|
436 | ### License
|
437 |
|
438 | Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
|
439 | MIT
|
440 |
|
441 | ***
|
442 |
|
443 | _This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on March 29, 2018._ |
\ | No newline at end of file |