Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cli update notice. #159

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ env:
- PROJECT="sw-routing"
- PROJECT="sw-runtime-caching"

install:
- npm install -g gulp-cli
- npm install
- cd "packages/${PROJECT}/"
- npm install
- cd ../../

# Read more here: https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
before_script:
- "export DISPLAY=:99.0"
Expand Down
4 changes: 4 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
only_commits:
files:
- packages/sw-cli/
- appveyor.yml

install:
- ps: Install-Product node Stable
- npm install
- npm install -g gulp
- cd packages/sw-cli/
- npm install
- cd ..

test_script:
- node --version
Expand Down
7 changes: 6 additions & 1 deletion packages/sw-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
"inquirer": "^2.0.0",
"lodash.template": "^4.4.0",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1"
"mkdirp": "^0.5.1",
"sw-lib": "0.0.7",
"update-notifier": "^1.0.3"
},
"devdependencies": {
"fs-extra": "^2.0.0"
}
}
103 changes: 94 additions & 9 deletions packages/sw-cli/src/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const glob = require('glob');
const crypto = require('crypto');
const mkdirp = require('mkdirp');
const template = require('lodash.template');
const updateNotifier = require('update-notifier');

const errors = require('../lib/errors');
const logHelper = require('../lib/log-helper');
Expand All @@ -46,6 +47,9 @@ class SWCli {
* handling the request has finished.
*/
argv(argv) {
// Update user new version is available.
updateNotifier({pkg}).notify();

const cliArgs = minimist(argv);
if (cliArgs._.length > 0) {
// We have a command
Expand Down Expand Up @@ -174,15 +178,31 @@ class SWCli {

const excludeFiles = [
fileManifestName,
relativePath, serviceWorkerName,
serviceWorkerName,
relativePath,
];

return this._buildFileManifestFromGlobs(
path.join(rootDirectory, fileManifestName),
rootDirectory,
globs,
excludeFiles
);
let swlibPath;
return this._copySWLibFile(rootDirectory)
.then((libPath) => {
swlibPath = libPath;
excludeFiles.push(path.basename(swlibPath));
})
.then(() => {
return this._buildFileManifestFromGlobs(
path.join(rootDirectory, fileManifestName),
rootDirectory,
globs,
excludeFiles
);
})
.then(() => {
return this._buildServiceWorker(
path.join(rootDirectory, serviceWorkerName),
path.join(rootDirectory, fileManifestName),
swlibPath,
rootDirectory
);
});
});
}

Expand Down Expand Up @@ -424,7 +444,6 @@ class SWCli {
}, []);

const manifestEntries = this._filterFiles(globbedFiles, excludeFiles);

return this._writeFilemanifest(manifestFilePath, manifestEntries);
}

Expand Down Expand Up @@ -550,6 +569,72 @@ class SWCli {
throw err;
}
}

_buildServiceWorker(swPath, filemanifestPath, swlibPath, rootDirectory) {
try {
mkdirp.sync(path.dirname(swPath));
} catch (err) {
logHelper.error(errors['unable-to-make-sw-directory'], err);
return Promise.reject(err);
}

const templatePath = path.join(
__dirname, '..', 'lib', 'templates', 'sw.js.tmpl');
return new Promise((resolve, reject) => {
fs.readFile(templatePath, 'utf8', (err, data) => {
if (err) {
logHelper.error(errors['read-sw-template-failure'], err);
return reject(err);
}
resolve(data);
});
})
.then((templateString) => {
const relFileManifest = path.relative(rootDirectory, filemanifestPath);
const relSwlibPath = path.relative(rootDirectory, swlibPath);

try {
return template(templateString)({
manifestPath: relFileManifest,
swlibPath: relSwlibPath,
});
} catch (err) {
logHelper.error(errors['populating-sw-tmpl-failed'], err);
throw err;
}
})
.then((populatedTemplate) => {
return new Promise((resolve, reject) => {
fs.writeFile(swPath, populatedTemplate, (err) => {
if (err) {
logHelper.error(errors['sw-write-failure'], err);
return reject(err);
}

resolve();
});
});
});
}

_copySWLibFile(rootDirectory) {
const swlibPath = path.join(rootDirectory, 'sw-lib.min.js');

return new Promise((resolve, reject) => {
const swlibModulePath = path.join(__dirname, '..', '..', 'node_modules',
'sw-lib', 'build', 'sw-lib.min.js');

const stream = fs.createReadStream(swlibModulePath)
.pipe(fs.createWriteStream(swlibPath));
stream.on('error', function(err) {
logHelper.error(errors['unable-to-copy-sw-lib'], err);
reject(err);
});
stream.on('finish', function() {
resolve(swlibPath);
});
});
}
}

module.exports = SWCli;
7 changes: 7 additions & 0 deletions packages/sw-cli/src/lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@ module.exports = {
'populating-manifest-tmpl-failed': 'An error occured when populating the ' +
'file manifest template.',
'manifest-file-write-failure': 'Unable to write the file manifest.',
'unable-to-make-sw-directory': 'Unable to make the directories to output ' +
'the service worker path.',
'read-sw-template-failure': 'Unable to read the service worker template ' +
'file.',
'sw-write-failure': 'Unable to write the service worker file.',
'unable-to-copy-sw-lib': 'SW-Lib is needed by the service worker and could ' +
'not be copied over to your new site.',
};
6 changes: 6 additions & 0 deletions packages/sw-cli/src/lib/templates/sw.js.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
importScripts(
"<%= manifestPath %>",
"<%= swlibPath %>"
);

self.goog.swlib.cacheRevisionedAssets(self.__file_manifest);
3 changes: 2 additions & 1 deletion packages/sw-cli/test/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
},
"rules": {
"no-console": 0,
"max-len": 0
"max-len": 0,
"no-invalid-this": 0,
}
}
152 changes: 152 additions & 0 deletions packages/sw-cli/test/build-service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
const proxyquire = require('proxyquire');
const cliHelper = require('./helpers/cli-test-helper.js');
const errors = require('../src/lib/errors.js');

describe('Build Service Worker', function() {
const INJECTED_ERROR = new Error('Injected Error');
const globalStubs = [];

afterEach(function() {
cliHelper.endLogCapture();
globalStubs.forEach((stub) => {
stub.restore();
});
});

const checkErrors = (caughtError, errorCode, checkInjectedError) => {
if (!caughtError) {
throw new Error('Expected test to throw an error.');
}

const captured = cliHelper.endLogCapture();
captured.consoleLogs.length.should.equal(0);
captured.consoleWarns.length.should.equal(0);
captured.consoleErrors.length.should.not.equal(0);

let foundErrorMsg = false;
let foundInjectedErrorMsg = false;
captured.consoleErrors.forEach((errLog) => {
if (errLog.indexOf(errors[errorCode]) !== -1) {
foundErrorMsg = true;
}
if (errLog.indexOf(INJECTED_ERROR.message) !== -1) {
foundInjectedErrorMsg = true;
}
});
foundErrorMsg.should.equal(true);
if (typeof checkInjectedError === 'undefined' ||
checkInjectedError === true) {
foundInjectedErrorMsg.should.equal(true);
}
};

it('should handle failing mkdirp.sync', function() {
const SWCli = proxyquire('../src/cli/index', {
mkdirp: {
sync: () => {
throw INJECTED_ERROR;
},
},
});

cliHelper.startLogCapture();
const cli = new SWCli();
return cli._buildServiceWorker(
'fake-path/sw.js',
'fake-path/manifest.js',
'fake-path/sw-lib.min.js',
'fake-path/')
.catch((caughtError) => {
checkErrors(caughtError, 'unable-to-make-sw-directory');
});
});

it('should handle fs.readFile error when checking template', function() {
const SWCli = proxyquire('../src/cli/index', {
mkdirp: {
sync: () => {
return;
},
},
fs: {
readFile: (pathname, encoding, cb) => {
cb(INJECTED_ERROR);
},
},
});

cliHelper.startLogCapture();
const cli = new SWCli();
return cli._buildServiceWorker(
'fake-path/sw.js',
'fake-path/manifest.js',
'fake-path/sw-lib.min.js',
'fake-path/')
.catch((caughtError) => {
checkErrors(caughtError, 'read-sw-template-failure');
});
});

it('should handle error when populating template', function() {
const SWCli = proxyquire('../src/cli/index', {
'mkdirp': {
sync: () => {
return;
},
},
'fs': {
readFile: (pathname, encoding, cb) => {
cb(null, 'Injected Template');
},
},
'lodash.template': () => {
throw INJECTED_ERROR;
},
});

cliHelper.startLogCapture();
const cli = new SWCli();
return cli._buildServiceWorker(
'fake-path/sw.js',
'fake-path/manifest.js',
'fake-path/sw-lib.min.js',
'fake-path/')
.catch((caughtError) => {
checkErrors(caughtError, 'populating-sw-tmpl-failed');
});
});

it('should handle error writing file', function() {
const SWCli = proxyquire('../src/cli/index', {
'mkdirp': {
sync: () => {
return;
},
},
'fs': {
readFile: (pathname, encoding, cb) => {
cb(null, 'Injected Template');
},
writeFile: (filepath, stringToWrite, cb) => {
cb(INJECTED_ERROR);
},
},
'lodash.template': () => {
return () => {
return 'Injected populated template.';
};
},
});

cliHelper.startLogCapture();
const cli = new SWCli();
return cli._buildServiceWorker(
'fake-path/sw.js',
'fake-path/manifest.js',
'fake-path/sw-lib.min.js',
'fake-path/')
.catch((caughtError) => {
checkErrors(caughtError, 'sw-write-failure');
});
});
});
Loading