Gulp build faild - build

I am getting problem with running Anguler 1.2 app with gulp, throws following error. Build was developer by some other developer and i am not good at it.
I tried to run npm install, bower update.
Nothing worked.
Any suggestions will be helpful.
Please take a look at following error output and code.
Thanks.
events.js:141
throw er; // Unhandled 'error' event
^
Error: watch /home/web/src/ ENOSPC
at exports._errnoException (util.js:907:11)
at FSWatcher.start (fs.js:1234:19)
at Object.fs.watch (fs.js:1262:11)
at Gaze._watchDir (/home/web/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-watcher/node_modules/gaze/lib/gaze.js:289:30)
at /home/web/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-watcher/node_modules/gaze/lib/gaze.js:358:10
at iterate (/home/web/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-watcher/node_modules/gaze/lib/helper.js:52:5)
at Object.forEachSeries (/home/web/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-watcher/node_modules/gaze/lib/helper.js:66:3)
at Gaze._initWatched (/home/web/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-watcher/node_modules/gaze/lib/gaze.js:354:10)
at Gaze.add (/home/web/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-watcher/node_modules/gaze/lib/gaze.js:177:8)
at new Gaze (/home/web/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-watcher/node_modules/gaze/lib/gaze.js:74:10)
--Gulp File--------------------------
var Gulp = require('gulp');
var Less = require('gulp-less');
var Path = require('path');
var JShint = require('gulp-jshint');
var Browserify = require('browserify');
var Sourcemaps = require('gulp-sourcemaps');
var Source = require('vinyl-source-stream');
var MinifyHTML = require('gulp-minify-html');
var RunSequence = require('run-sequence');
/**
* HTML template task + watch
*/
Gulp.task('templates', function () {
// Get our index.html
// find options here: https://www.npmjs.com/package/gulp-minify-html
var opts = {};
Gulp.src('src/index.html')
// And put it in the public folder
// .pipe(MinifyHTML(opts))
.pipe(Gulp.dest('public/'));
Gulp.src('src/index.php')
// And put it in the public folder
// .pipe(MinifyHTML(opts))
.pipe(Gulp.dest('public/'));
// Any other view files from src/templates
return Gulp.src('src/templates/**/*.html')
// Will be put in the public/templates folder
// .pipe(MinifyHTML(opts))
.pipe(Gulp.dest('public/templates/'));
});
Gulp.watch(['src/index.php', 'src/index.html', 'src/templates/**/*.html'], {interval: 500}, [
'templates'
]);
/**
* LESS / CSS task + watch
*/
Gulp.task('css', function () {
return Gulp.src('src/css/*.css*')
.pipe(Gulp.dest('./public/css'));
});
Gulp.watch(['src/css/*.css*'], {interval: 500}, [
'css'
]);
Gulp.task('less', function () {
return Gulp.src('src/css/less/*.less')
.pipe(Sourcemaps.init())
.pipe(Less({
paths: [Path.join(__dirname, 'less', 'includes')]
}))
.pipe(Sourcemaps.write())
.pipe(Gulp.dest('./public/css'));
});
Gulp.watch(['src/css/**/*.less'], {interval: 500}, [
'less'
]);
/**
* Images task + watch
*/
// Image "copy" / "optimize" task
Gulp.task('images', function () {
// Get our images
return Gulp.src('src/img/**/*')
// Do some optional image processing here, such as optimizing
// And put it in the dist folder
.pipe(Gulp.dest('public/img/'))
});
Gulp.watch(['src/img/**/*'], {interval: 1000}, ['images']);
/**
* Font task + watch
*/
Gulp.task('fonts', function () {
// Get our fonts
return Gulp.src('src/fonts/**/*')
// Do some optional image processing here, such as optimizing
// And put it in the dist folder
.pipe(Gulp.dest('public/fonts/'))
});
Gulp.watch(['src/fonts/**/*'], {interval: 1000}, ['fonts']);
/**
* JS tasks + watches
*/
// linting
Gulp.task('lint', function () {
return;
Gulp.src('src/js/**/*.js')
.pipe(JShint())
// You can look into pretty reporters as well, but that's another story
.pipe(JShint.reporter('default'));
});
// Browserify task
Gulp.task('l10n', function () {
return Gulp.src('src/js/l10n/*.js')
.pipe(Gulp.dest('public/js/l10n/'));
});
// Browserify task
Gulp.task('browserify', function () {
var b = Browserify({
basedir: './',
entries: './src/js/main.js',
debug: true,
insertGlobals: true
});
b.transform('deamdify');
/* b.transform({
global: true
}, ngAnnotate);*/
/* b.transform({
global: true
}, uglifyify);*/
return b.bundle()
.on('error', function (err) {
// print the error (can replace with gulp-util)
console.log(err.message);
// end this stream
this.end();
})
.pipe(Source('bundle.js'))
// .pipe(streamify(rename({suffix: '.min'})))
.pipe(Gulp.dest('public/js'));
});
Gulp.task('javascript', ['lint'], function () {
// Watch our scripts
Gulp.watch(['src/js/*.js', 'src/js/**/*.js'], {interval: 500}, [
'lint',
'browserify',
'l10n'
]);
});
/**
* Copy vendor JS
*/
Gulp.task('vendor', function () {
// Get our images
return Gulp.src('src/vendor/**/*')
// Do some optional image processing here, such as optimizing
// And put it in the dist folder
.pipe(Gulp.dest('public/vendor/'));
});
Gulp.watch(['src/vendor/**/*'], {interval: 2000}, ['vendor']);
/**
* default task, start with "gulp"
*/
Gulp.task('default', ['css', 'less', 'images', 'javascript', 'templates', 'fonts', 'vendor'], function () {
// we depend on 'watch' tasks, so nothing to do really
});
Gulp.task('build', function () {
RunSequence(
'css',
//'less',
'images',
'browserify',
'l10n',
'templates',
'fonts',
'vendor',
function(){
console.log('Build completed, closing');
process.exit(0);
});
});

Related

how to filter out files during when ember-cli is building my app (filtering monaco's many files, specifically)

I am trying to reduce monaco-editor dependency size.
I found this answer which shows how to do it on angular - by editing the glob configuration in angular.json file.
What is the corresponding file for this configuration on ember?
EDIT
I found this read me for configuring on ember-cli-build, any idea how to configure?
module.exports = function (defaults) {
const app = new EmberApp(defaults, {
autoImport: {
alias: {
'monaco-editor': '** what here? **',
},
},
I don't know how to read the angular comment there, but what I did was build my own copy of Monaco, with esbuild.
I am trying to reduce monaco-editor dependency size.
generally, if you're using embroider, if you don't import it, it won't be a part of your build.
This is probably more try-hard than you're looking for, but gives you more control over your assets.
here is my package where I do that: https://github.com/NullVoxPopuli/limber/tree/main/packages/monaco
I use this build script:
'use strict';
const path = require('path');
const os = require('os');
const fs = require('fs').promises;
const copy = require('recursive-copy');
const esbuild = require('esbuild');
const { esBuildBrowserTargets } = require('#nullvoxpopuli/limber-consts');
const OUTPUT_DIR = path.join(__dirname, 'dist').toString();
const ME = path.dirname(require.resolve('monaco-editor/package.json'));
const cssLocation = path.join(`${ME}/min/vs/editor`);
const workers = {
base: path.join(ME, 'esm/vs/editor/editor.main.js'),
editor: path.join(ME, 'esm/vs/editor/editor.worker.js'),
json: path.join(ME, 'esm/vs/language/json/json.worker.js'),
css: path.join(ME, 'esm/vs/language/css/css.worker.js'),
html: path.join(ME, 'esm/vs/language/html/html.worker.js'),
ts: path.join(ME, 'esm/vs/language/typescript/ts.worker.js'),
};
/**
* - Builds Web Workers
* - Builds a preconfigured bundle with monaco-editor
* - Copies tall relevant CSS to the same output folder
*/
module.exports = async function build() {
let buildDir = await fs.mkdtemp(path.join(os.tmpdir(), 'monaco--workers-'));
await esbuild.build({
loader: { '.ts': 'ts', '.js': 'js', '.ttf': 'file' },
entryPoints: [
workers.editor,
workers.json,
workers.css,
workers.html,
workers.ts,
workers.base,
],
bundle: true,
outdir: buildDir,
format: 'esm',
target: esBuildBrowserTargets,
minify: false,
sourcemap: false,
});
await esbuild.build({
loader: { '.ts': 'ts', '.js': 'js', '.ttf': 'file' },
entryPoints: [path.join('preconfigured', 'index.ts')],
bundle: true,
outfile: path.join(buildDir, 'preconfigured.js'),
format: 'esm',
target: esBuildBrowserTargets,
// something silly is going on with Monaco and esbuild
// TODO: report this to ESBuild's GitHub
minify: false,
sourcemap: false,
});
await copy(`${buildDir}`, OUTPUT_DIR, {
overwrite: true,
filter: ['**/*', '!*.nls.*'],
rename(filePath) {
if (filePath.includes('ttf')) {
return 'codicon.ttf';
}
return filePath;
},
});
await copy(`${cssLocation}`, OUTPUT_DIR, {
overwrite: 'inline',
filter: ['**/*.css'],
});
// TODO: how to change the monaco config to allow this to be in a `monaco/` folder
// const ICON_PATH = 'base/browser/ui/codicons/codicon/codicon.ttf';
// await copy(path.join(ME, 'esm/vs', ICON_PATH), ICON_PATH)
};
if (require.main === module) {
module.exports();
}
and then in my ember-cli-build.js here: https://github.com/NullVoxPopuli/limber/blob/main/frontend/ember-cli-build.js#L50
(merging the extraPublic Trees)
I invoke:
// Desktop Editor
require('#nullvoxpopuli/limber-monaco/broccoli-funnel')(),
the broccoli-funnel
'use strict';
const path = require('path');
const Funnel = require('broccoli-funnel');
const SRC_FILES = path.join(__dirname, 'dist');
/**
* This broccoli funnel is for copying the built assets to a target
* app's public folder. No building occurs
*
*/
module.exports = function monacoFunnel() {
return new Funnel(SRC_FILES, {
destDir: 'monaco/',
});
};
I then load monaco via a modifier like this:
import { assert } from '#ember/debug';
import type { Args } from './-types';
/**
* I wish there was a way to specify types-only packages
* while Limber uses Monaco, it's provided by the limber-monaco
* broccoli funnel (copied into the public folder).
*
* So the devDep on monaco-editor in limber/frontend is *solely*
* for the type defs
*/
import type * as monaco from 'monaco-editor';
export default function installMonaco(element: HTMLElement, ...[value, updateText, named]: Args) {
assert(`Expected MONACO to exist`, MONACO);
element.innerHTML = '';
let { editor, setText } = MONACO(element, value, updateText, named);
named.setValue((text) => {
// changing the text this ways calls updateText for us
// updateText(text); // update the service / URL
setText(text); // update the editor
});
return () => editor?.dispose();
}
let MONACO:
| undefined
| ((
element: HTMLElement,
...args: Args
) => { editor: monaco.editor.IStandaloneCodeEditor; setText: (text: string) => void });
export async function setupMonaco() {
if (MONACO) return;
// TypeScript doesn't have a way to type files in the public folder
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
// #ts-ignore
MONACO = (await import(/* webpackIgnore: true */ '/monaco/preconfigured.js')).default;
}
and usage:
import monacoModifier from './my-monaco-modifier';
export default class Demo extends Component {
monaco = monacoModifier
}
<div {{this.monaco}}></div>
You can view this in action here: https://limber.glimdown.com/
I solved the issue by skipping languages import (which I don't need since I use custom language.
adding the following under webpackConfig:
new MonacoWebpackPlugin({
languages: [],
}),
Here is the full config in ember-cli-build.js:
return require('#embroider/compat').compatBuild(app, Webpack, {
staticAddonTestSupportTrees: true,
staticAddonTrees: true,
staticHelpers: true,
// staticComponents: true,
onOutputPath(outputPath) {
writeFileSync(join(__dirname, '.embroider-app-path'), outputPath, 'utf8');
},
packagerOptions: {
webpackConfig: {
module: {
rules: [
{
test: /\.(png|jpg|gif|svg|woff|woff2|eot|ttf|otf|flac)$/i,
loader: 'file-loader',
options: {
name: '[path][name]-[contenthash].[ext]',
},
},
],
},
plugins: [
new MonacoWebpackPlugin({
languages: [],
}),
],
},
},
});

Mock file upload in unit test controller NestJs

I have a method in nest js controller which takes two arguments looks like below :
#UseGuards(JwtAuthGuard, RolesGuard)
#Roles(MemberType.OWNER)
#Post('')
#UseInterceptors(
FilesInterceptor('images', 4, {
storage: fileStorageProductImage,
fileFilter: fileFilter,
limits: fileSizeLimit,
}),
)
#UseInterceptors(new MulterInterceptor('images'))
public async addProduct(
#Req()
req: Request,
#UploadedFiles() files: Express.Multer.File[],
) {
//code
//
}
And here is my unit test
describe('Unit testing path 1', () => {
const MemberServiceProvider = {
provide: MemberService,
useClass: MemberServiceStub,
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ProductsController],
providers: [MemberServiceProvider],
}).compile();
controller = module.get<ProductsController>(ProductsController);
});
//
const result = controller.addProduct(..., ...);
});
I currently dont know what to pass into that addProduct method since i dont know how to mock request object and Express.Multer.File[]. Thanks in advance
For anyone who are still loking for the answer. I just figured it how to solved this. First thing first we need to define a method that can be used to read file from our local machine via stream.
const fileToBuffer = (filename) => {
const readStream = fs.createReadStream(filename);
const chunks = [];
return new Promise((resolve, reject) => {
// Handle any errors while reading
readStream.on('error', (err) => {
// handle error
// File could not be read
reject(err);
});
// Listen for data
readStream.on('data', (chunk) => {
chunks.push(chunk);
});
// File is done being read
readStream.on('close', () => {
// Create a buffer of the image from the stream
resolve(Buffer.concat(chunks));
});
});
};
Then, we call that method inside our unit test
const imageBuffer = (await fileToBuffer(
__dirname + 'path-to-file',
)) as Buffer;
In our controller, the uploaded files has Express.Multer.File[] types so we have to make variables that has the same type as above.
const imageFiles: Express.Multer.File[] = [];
const myReadableStreamBuffer = new streamBuffers.ReadableStreamBuffer({
frequency: 10, // in milliseconds.
chunkSize: 2048, // in bytes.
});
myReadableStreamBuffer.put(imageBuffer as Buffer);
imageFiles.push({
buffer: imageBuffer,
fieldname: 'fieldname-defined-in-#UseInterceptors-decorator',
originalname: 'original-filename',
encoding: '7bit',
mimetype: 'file-mimetyp',
destination: 'destination-path',
filename: 'file-name',
path: 'file-path',
size: 955578,
stream: myReadableStreamBuffer,
});
Finally we can call our addProduct method with newly created imagesFiles variable as arguments.

React native - executing store method via action while retaining `this` context of component

Hopefully this code sample does a good job of explaining the problem that I am trying to solve.
/**
* We happen to be working in React Native here, so fluxible's
* connectToStores as well as the implementation of flux-react
* are non-starters here due to both's peer dependency on
* react.
*/
// Store.js
var Store = {
getState: function () {
var endpoint = '/endpoint';
var promise = fetch(endpoint)
.then(response => response.json());
return Promise.resolve(promise)
.then((data) => {
this.setState({
hasData: true,
data: data
});
})
.done();
}
};
module.exports = Store;
// Component.js
var Component = React.createClass({
getInitialState: function () {
return {
hasData: false,
data: {}
};
},
componentDidUpdate: function () {
console.log('this.state', this.state);
},
componentDidMount: function () {
/**
* Rather than directly apply here, possible to wrap the Store somehow
* so that the Component scope of `this` is applied automatically when
* calling _any_ of Store's methods?
*
* Even better, how to execute an action here that triggers a method in
* the Store and passes along `this` from the Component as the context.
*/
Store.getState.apply(this);
},
render: function () {
return (
<View></View>
);
}
});
module.exports = Component;
What you did with passing the 'this' should work. However, I would suggest doing something like:
this.setState(Store.getState())
If you are repeating this multiple times, you can use a mixin. In a mixin, your 'this' is the context.

Unit testing AngularJS and Flot Charts

I am trying to unit test (Jasmine) AngularJS and Flot Charts but receive the following errors. I do not receive these errors in the console of my application and the charts render as expected.
PhantomJS 1.9.2 (Mac OS X) Charts Directive should populate the container element FAILED
TypeError: 'undefined' is not an object (evaluating 'placeholder.css("font-size").replace')
at parseOptions (/Library/WebServer/Documents/zui/app/js/libs/flot/jquery.flot.js:740)
at Plot (/Library/WebServer/Documents/zui/app/js/libs/flot/jquery.flot.js:673)
at /Library/WebServer/Documents/zui/app/js/libs/flot/jquery.flot.js:3059
at /Library/WebServer/Documents/zui/app/js/directives/charts.js:6
at /Library/WebServer/Documents/zui/app/js/libs/angular.js:7942
at /Library/WebServer/Documents/zui/test/unit/directives/charts.spec.js:10
at /Library/WebServer/Documents/zui/test/unit/directives/charts.spec.js:23
at invoke (/Library/WebServer/Documents/zui/app/js/libs/angular.js:2902)
at workFn (/Library/WebServer/Documents/zui/app/js/libs/angular-mocks.js:1795)
at /Library/WebServer/Documents/zui/app/js/libs/angular-mocks.js:1782
at /Library/WebServer/Documents/zui/test/unit/directives/charts.spec.js:24
PhantomJS 1.9.2 (Mac OS X): Executed 30 of 40 (1 FAILED) (0 secs / 0.126 secs)
Charts Directive:
FAILED - should populate the container element TypeError: 'undefined' is not an object (evaluating 'placeholder.css("font-size").replace')
at parseOptions (/Library/WebServer/Documents/zui/app/js/libs/flot/jquery.flot.js:740)
at Plot (/Library/WebServer/Documents/zui/app/js/libs/flot/jquery.flot.js:673)
at /Library/WebServer/Documents/zui/app/js/libs/flot/jquery.flot.js:3059
at /Library/WebServer/Documents/zui/app/js/directives/charts.js:6
at /Library/WebServer/Documents/zui/app/js/libs/angular.js:7942
at /Library/WebServer/Documents/zui/test/unit/directives/charts.spec.js:10
at /Library/WebServer/Documents/zui/test/unit/directives/charts.spec.js:23
at invoke (/Library/WebServer/Documents/zui/app/js/libs/angular.js:2902)
at workFn (/Library/WebServer/Documents/zui/app/js/libs/angular-mocks.js:1795)
at /Library/WebServer/Documents/zui/app/js/libs/angular-mocks.js:1782
at /Library/WebServer/Documents/zui/test/unit/directives/charts.spec.js:24
PhantomJS 1.9.2 (Mac OS X): Executed 31 of 40 (1 FAILED) (0 secs / 0.134 secs)
Directive:
angular.module('directives.FlotCharts', [])
.directive('flotChart', function () {
return {
restrict: 'EA',
controller: ['$scope', '$attrs', function ($scope, $attrs) {
var plotid = '#' + $attrs.id,
model = $scope[$attrs.ngModel];
$scope.$watch('model', function (x) {
$.plot(plotid, x.data, x.options);
});
}]
};
});
Controller:
angular.module('Charts', ['directives.FlotCharts'])
.controller('diskChartCtrl', ['$scope', function ($scope) {
$scope.model = {};
$scope.model.data = [
{
label: "Available",
data: 20,
color:"#00a34a"
},
{
label: "Used",
data: 100,
color:"#c00"
}
];
$scope.model.options = {
series: {
pie: {
innerRadius: 0.5, // for donut
show: true,
label: {
formatter: function (label, series) {
return '<div class="pie">' + label + ': ' +
series.data[0][1] + 'GB <br>(' + Math.round(series.percent) + '%)</div>';
}
}
}
},
legend: {
show: false
}
};
}])
}]);
Test Spec:
describe('Charts Directive', function () {
var scope, html, tmpl, ctrl, $compile;
var compileTmpl = function (markup, scope) {
var el = $compile(markup)(scope);
scope.$digest();
return el;
};
beforeEach(function () {
module('directives.FlotCharts');
module('Charts');
inject(function ($rootScope, _$compile_, $controller) {
$compile = _$compile_;
scope = $rootScope.$new();
ctrl = $controller('diskChartCtrl', {$scope: scope});
html = angular.element('<div data-flot-chart id="disk" data-chart="pie" data-status="danger" data-ng-model="model" data-ng-controller="diskChartCtrl"></div>');
tmpl = compileTmpl(html, scope);
});
});
it('should populate the container element', function () {
expect(true).toBe(true);
//expect(tmpl.html()).toContain('canvas');
});
});
Any insight is greatly appreciated.
This may not be the answer to your question, but hopefully it will help steer you in the right direction. Here's the source of the exception from jquery.flot.js:
fontDefaults = {
style: placeholder.css("font-style"),
size: Math.round(0.8 * (+placeholder.css("font-size").replace("px", "") || 13)),
variant: placeholder.css("font-variant"),
weight: placeholder.css("font-weight"),
family: placeholder.css("font-family")
};
It appears that placeholder.css('font-size') is returning undefined. I seem to remember hearing of some problems with jQuery.css('margin') not working in PhantomJS, but jQuery.css('margin-left') behaving correctly.
If you explicitly set style: "font-size: 10px;" on the element do you get different results? I noticed you were setting the directive's class to pie, have you included any stylesheets?
I was able to solve this issue as commented by compiling the markup against rootScope and setting inline width and height styles. It may have been an issue of missing width and height properties.
inject(['$rootScope', '$compile', '$controller', function ($rootScope, $compile, $controller) {
scope = $rootScope.$new();
ctrl = $controller('itemChartCtrl', { $scope: scope });
tmpl = '<div data-flot-chart id="items" data-chart="pie" data-status="danger" data-ng-model="model" data-ng-controller="itemChartCtrl" style="width:300px;height:300px"></div>';
$compile(tmpl)($rootScope);
}]);

BeforeEach with expectGets cannot be executed more then once

I have a problem with my unit test for a directive where I need to setup the directive before being able to test it.
This is the way I initialize it:
var elm, $templateCache
var count = 0;
beforeEach(module('app/js/directives/templates/mytemplate.html'));
beforeEach(inject(function($injector) {
$templateCache = $injector.get('$templateCache');
}));
beforeEach(inject(
['$httpBackend','$compile','$rootScope', function(_$compile) {
var template = $templateCache.get('app/js/directives/templates/mytemplate.html');
if(count == 0 ){
$httpBackend.expectGET('js/directives/templates/mytemplate.html').respond(template);
}
elm = angular.element('<div my-directive</div>');
$compile(elm)($rootScope);
if(count == 0){
$httpBackend.expectGET('/app/js/content/some.json').respond('{ "left" : "<div>Contact information</div>"}');
$httpBackend.flush();
}
$rootScope.$digest();
count++;
}]
));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it("should work like I want it to", function() {
$rootScope.my-directive.somefunction();
expect($rootScope.somevalue).toBe(2);
});
it("should load the previous page if the function scope.layover.qa_pager.prev is called", function() {
$rootScope.my-directive.someotherfunction();
expect($rootScope.somevalue).toBe(1);
});
This works, but the hack with the count should not be needed in my opinion. If I leave it out I get problems with the $httpbackend which doesn't seem to be reinitialised every time so it gives me 'Error: Unsatisfied requests: GET /app/js/content/some.json' and 'Error: No pending request to flush !'
To me it looks like you are trying to load a template for a unit test. I'm assuming you are using karma to run the tests, so you should look at html2js. It loads your templates into the template cache for you.
https://github.com/karma-runner/karma-ng-html2js-preprocessor
// karma.conf.js
module.exports = function(config) {
config.set({
preprocessors: {
'**/*.html': ['ng-html2js']
},
files: [
'*.js',
'*.html'
],
ngHtml2JsPreprocessor: {
// strip this from the file path
stripPrefix: 'public/',
// prepend this to the
prependPrefix: 'served/',
// or define a custom transform function
cacheIdFromPath: function(filepath) {
return cacheId;
}
}
});
};