Skip to content

Commit 93564bd

Browse files
pixeldesuphated
andauthored
Docs: Add advanced section for creation of custom registries (#2479)
Co-authored-by: Blaine Bublitz <blaine.bublitz@gmail.com>
1 parent 22ce5f5 commit 93564bd

File tree

2 files changed

+200
-1
lines changed

2 files changed

+200
-1
lines changed
+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
<!-- front-matter
2+
id: creating-custom-registries
3+
title: Creating Custom Registries
4+
hide_title: true
5+
sidebar_label: Creating Custom Registries
6+
-->
7+
8+
# Creating Custom Registries
9+
10+
Allows custom registries to be plugged into the task system, which can provide shared tasks or augmented functionality. Registries are registered using [`registry()`](registry).
11+
12+
## Structure
13+
14+
In order to be accepted by gulp, custom registries must follow a specific format.
15+
16+
```js
17+
// as a function
18+
function TestRegistry() {}
19+
20+
TestRegistry.prototype.init = function (gulpInst) {}
21+
TestRegistry.prototype.get = function (name) {}
22+
TestRegistry.prototype.set = function (name, fn) {}
23+
TestRegistry.prototype.tasks = function () {}
24+
25+
// as a class
26+
class TestRegistry {
27+
init(gulpInst) {}
28+
29+
get(name) {}
30+
31+
set(name, fn) {}
32+
33+
tasks() {}
34+
}
35+
```
36+
37+
If a registry instance passed to `registry()` doesn't have all four methods, an error will be thrown.
38+
39+
## Registration
40+
41+
If we want to register our example registry from above, we will need to pass an instance of it to `registry()`.
42+
43+
```js
44+
const { registry } = require('gulp');
45+
46+
// ... TestRegistry setup code
47+
48+
// good!
49+
registry(new TestRegistry())
50+
51+
// bad!
52+
registry(TestRegistry())
53+
// This will trigger an error: 'Custom registries must be instantiated, but it looks like you passed a constructor'
54+
```
55+
56+
## Methods
57+
58+
### `init(gulpInst)`
59+
60+
The `init()` method of a registry is called at the very end of the `registry()` function. The gulp instance passed as the only argument (`gulpInst`) can be used to pre-define tasks using
61+
`gulpInst.task(taskName, fn)`.
62+
63+
#### Parameters
64+
65+
| parameter | type | note |
66+
|:---------:|:----:|------|
67+
| gulpInst | object | Instance of gulp. |
68+
69+
### `get(name)`
70+
71+
The `get()` method receives a task `name` for the custom registry to resolve and return, or `undefined` if no task with that name exists.
72+
73+
#### Parameters
74+
75+
| parameter | type | note |
76+
|:---------:|:----:|------|
77+
| name | string | Name of the task to be retrieved. |
78+
79+
### `set(name, fn)`
80+
81+
The `set()` method receives a task `name` and `fn`. This is called internally by `task()` to provide user-registered tasks to custom registries.
82+
83+
#### Parameters
84+
85+
| parameter | type | note |
86+
|:---------:|:----:|------|
87+
| name | string | Name of the task to be set. |
88+
| fn | function | Task function to be set. |
89+
90+
### `tasks()`
91+
92+
Must return an object listing all tasks in the registry.
93+
94+
## Use Cases
95+
96+
### Sharing Tasks
97+
98+
To share common tasks with all your projects, you can expose an `init` method on the registry and it will receive the an instance of gulp as the only argument. You can then use `gulpInst.task(name, fn)` to register pre-defined tasks.
99+
100+
For example, you might want to share a `clean` task:
101+
102+
```js
103+
const fs = require('fs');
104+
const util = require('util');
105+
106+
const DefaultRegistry = require('undertaker-registry');
107+
const del = require('del');
108+
109+
function CommonRegistry(opts){
110+
DefaultRegistry.call(this);
111+
112+
opts = opts || {};
113+
114+
this.buildDir = opts.buildDir || './build';
115+
}
116+
117+
util.inherits(CommonRegistry, DefaultRegistry);
118+
119+
CommonRegistry.prototype.init = function(gulpInst) {
120+
const buildDir = this.buildDir;
121+
const exists = fs.existsSync(buildDir);
122+
123+
if(exists){
124+
throw new Error('Cannot initialize common tasks. ' + buildDir + ' directory exists.');
125+
}
126+
127+
gulpInst.task('clean', function(){
128+
return del([buildDir]);
129+
});
130+
}
131+
132+
module.exports = CommonRegistry;
133+
```
134+
135+
Then to use it in a project:
136+
137+
```js
138+
const { registry, series, task } = require('gulp');
139+
const CommonRegistry = require('myorg-common-tasks');
140+
141+
registry(new CommonRegistry({ buildDir: '/dist' }));
142+
143+
task('build', series('clean', function build(cb) {
144+
// do things
145+
cb();
146+
}));
147+
```
148+
149+
### Sharing Functionality
150+
151+
By controlling how tasks are added to the registry, you can decorate them.
152+
153+
For example, if you wanted all tasks to share some data, you can use a custom registry to bind them to that data. Be sure to return the altered task, as per the description of registry methods above:
154+
155+
```js
156+
const { registry, series, task } = require('gulp');
157+
const util = require('util');
158+
const DefaultRegistry = require('undertaker-registry');
159+
160+
// Some task defined somewhere else
161+
const BuildRegistry = require('./build.js');
162+
const ServeRegistry = require('./serve.js');
163+
164+
function ConfigRegistry(config){
165+
DefaultRegistry.call(this);
166+
this.config = config;
167+
}
168+
169+
util.inherits(ConfigRegistry, DefaultRegistry);
170+
171+
ConfigRegistry.prototype.set = function set(name, fn) {
172+
// The `DefaultRegistry` uses `this._tasks` for storage.
173+
var task = this._tasks[name] = fn.bind(this.config);
174+
return task;
175+
};
176+
177+
registry(new BuildRegistry());
178+
registry(new ServeRegistry());
179+
180+
// `registry` will reset each task in the registry with
181+
// `ConfigRegistry.prototype.set` which will bind them to the config object.
182+
registry(new ConfigRegistry({
183+
src: './src',
184+
build: './build',
185+
bindTo: '0.0.0.0:8888'
186+
}));
187+
188+
task('default', series('clean', 'build', 'serve', function(cb) {
189+
console.log('Server bind to ' + this.bindTo);
190+
console.log('Serving' + this.build);
191+
cb();
192+
}));
193+
```
194+
195+
## Examples
196+
197+
* [`undertaker-registry`](https://github.com/gulpjs/undertaker-registry): The Gulp 4 default registry.
198+
* [`undertaker-common-tasks`](https://github.com/gulpjs/undertaker-common-tasks): Proof-of-concept custom registry that pre-defines tasks.
199+
* [` undertaker-task-metadata`](https://github.com/gulpjs/undertaker-task-metadata): Proof-of-concept custom registry that attaches metadata to each task.

docs/api/registry.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,4 @@ When a registry without an `init` method is passed as `registryInstance`, throws
6060

6161
When a registry without a `tasks` method is passed as `registryInstance`, throws an error with the message, "Custom registry must have `tasks` function".
6262

63-
[creating-custom-registries]: ../documentation-missing.md
63+
[creating-custom-registries]: ../advanced/creating-custom-registries.md

0 commit comments

Comments
 (0)