Skip to content
This repository has been archived by the owner on Jun 24, 2024. It is now read-only.

Commit

Permalink
feat: add bundlingComplete helper method
Browse files Browse the repository at this point in the history
This method simplifies the process of checking whether bundling is
complete.
  • Loading branch information
digitalsadhu committed Mar 13, 2018
1 parent 89ac62a commit 98c43e2
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 15 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ endpoint.
GET http://<asset-server-url>/bundle/<hash>.js
```

To make some of this a little easier, 2 helper methods exist on the client:

* `bundleURL` - calculates the url location for a bundle based on a given array of asset hashes.
* `bundlingComplete` - determines if bundling is complete for a given array of asset hashes.

See API documentation below for more information.

## Installation

```bash
Expand Down Expand Up @@ -377,6 +384,34 @@ const { uri, id2 } = await client.publishAssets('podlet2', ['/path/to/file.js'])
const url = await client.bundleURL([id1, id2]);
```

### bundlingComplete(feedhashes, options)

Calculates whether a bundling for the given `feedHashes` has been completed. The rules for this method are as follows:

* If `feedHashes` is an empty array, this method resolves to `true` as no bundle needs to be built.
* Otherwise, if `feedHashes` is not an empty array then a bundle url will be computed and a request made to check if the file exists on the server.

* `hashes` - `string[]` - array of asset feed content hashes as returned by `client.publishAssets`
* `options` - `object`
* `options.prefix` - `string` url prefix to use when building bundle url. Defaults to `${client.buildServerUri}/bundle/` which is the location on the asset server that a bundle can be located. Overwrite this if you use a CDN and need to point to that.
* `options.type` - `string` (`js`|`css`) - file type. Defaults to `js`

`return` - `Promise<boolean>` - resolves to a boolean representing whether the bundling process for the given `feedHashes` is considered to be complete.

**Example**

```js
// publish instructions
await client.publishInstructions('layout', 'js', ['podlet1', 'podlet2']);

// publish necessary assets
const { uri, id1 } = await client.publishAssets('podlet1', ['/path/to/file.js']);
const { uri, id2 } = await client.publishAssets('podlet2', ['/path/to/file.js']);

// calculate the url of the finished bundle
const isComplete = await client.bundlingComplete([id1, id2]);
```

## Transpilers

Since [asset-pipe][asset-pipe] is built on [browserify][browserify] under the
Expand Down
17 changes: 17 additions & 0 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ function post(options) {
});
}

function get(uri) {
return new Promise((resolve, reject) => {
request(uri, (error, response, body) => {
if (error) return reject(error);
resolve({ response, body });
});
});
}

module.exports = class Client {
constructor({ serverId, buildServerUri, minify, sourceMaps } = {}) {
assert(
Expand Down Expand Up @@ -370,6 +379,7 @@ module.exports = class Client {
}

async bundleURL(feedHashes, options = {}) {
if (feedHashes.length === 0) return null;
const { type, prefix } = {
prefix: url.resolve(this.buildServerUri, '/bundle/'),
type: 'js',
Expand All @@ -379,4 +389,11 @@ module.exports = class Client {
const filename = this.bundleFilename(hash, type);
return url.resolve(prefix, filename);
}

async bundlingComplete(feedHashes, options = {}) {
const uri = await this.bundleURL(feedHashes, options);
if (!uri) return true;
const { response } = await get(uri);
return response.statusCode >= 200 && response.statusCode < 300;
}
};
78 changes: 63 additions & 15 deletions test/unit/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,26 @@ const buildServerUri = 'http://server.com:3000';

function createRequestMock(error, response, body) {
const { PassThrough } = require('stream');
return {
post(options, callback) {
const resolve = () => {
if (error) {
return callback(error);
}
callback(null, response, body);
};
if (options.body) {
return resolve();
const mockRequest = (url, callback) => {
if (error) return callback(error);
callback(null, response, body);
};
mockRequest.post = (options, callback) => {
const resolve = () => {
if (error) {
return callback(error);
}
const destination = new PassThrough();
destination.on('data', () => {});
destination.on('end', resolve);
return destination;
},
callback(null, response, body);
};
if (options.body) {
return resolve();
}
const destination = new PassThrough();
destination.on('data', () => {});
destination.on('end', resolve);
return destination;
};
return mockRequest;
}

function createJsWriterMock() {
Expand Down Expand Up @@ -365,3 +368,48 @@ test('bundleURL(hashes, options) - js with prefix', async () => {
'http://server/fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603.js'
);
});

test('bundleURL(hashes, options) - empty array returns null', async () => {
expect.assertions(1);
const client = new Client({ buildServerUri });
const url = await client.bundleURL([]);
expect(url).toBe(null);
});

test('bundlingComplete(hashes, options) - empty hashes array returns true', async () => {
expect.assertions(1);
const client = new Client({ buildServerUri });
const isComplete = await client.bundlingComplete([]);
expect(isComplete).toBe(true);
});

test('bundlingComplete(hashes, options) - empty hashes array returns true', async () => {
expect.assertions(1);
jest.resetModules();
jest.doMock('request', () => createRequestMock(null, { statusCode: 200 }));
Client = require('../../');
const client = new Client({ buildServerUri });
const isComplete = await client.bundlingComplete([]);
expect(isComplete).toBe(true);
});

test('bundlingComplete(hashes, options) - bundle does not exist returns false', async () => {
expect.assertions(1);
jest.resetModules();
jest.doMock('request', () => createRequestMock(null, { statusCode: 404 }));
Client = require('../../');
const client = new Client({ buildServerUri });
const isComplete = await client.bundlingComplete(['a12sd2s1a1a1323a']);
expect(isComplete).toBe(false);
});

test('bundlingComplete(hashes, options) - request throws', async () => {
expect.assertions(1);
jest.resetModules();
jest.doMock('request', () => createRequestMock(new Error('fake error')));
Client = require('../../');
const client = new Client({ buildServerUri });
await expect(client.bundlingComplete(['a12sd2s1a1a1323a'])).rejects.toEqual(
new Error('fake error')
);
});

0 comments on commit 98c43e2

Please sign in to comment.