Skip to content

Commit aacc806

Browse files
authored
Merge pull request #762 from medayo/resolvePackageJSONConflicts
Using filer with webpack
2 parents 3061328 + c378288 commit aacc806

File tree

15 files changed

+314
-3
lines changed

15 files changed

+314
-3
lines changed

AUTHORS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ Barry Tulchinsky <[email protected]> (@btulchinsky)
55
Kieran Sedgwick <[email protected]> (@sedge)
66
Yoav Gurevich <[email protected]>
77
Gideon Thomas <[email protected]>
8-
Abdirahman Guled <[email protected]>
8+
Abdirahman Guled <[email protected]>
9+
Ben Heidemann <[email protected]>

README.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,148 @@ requirejs(['filer'], function(Filer) {...}
5454
var Filer = window.Filer;
5555
```
5656
57+
### Webpack
58+
59+
Filer can be used as a drop-in replacement for the node.js [fs module](http://nodejs.org/api/fs.html) using webpack.
60+
61+
In order to use filer in place of fs, insert the following into your webpack config:
62+
63+
```javascript
64+
// webpack.config.js
65+
module.exports = {
66+
resolve: {
67+
alias: {
68+
'fs': 'filer/shims/fs.js',
69+
}
70+
}
71+
}
72+
```
73+
74+
You can then import the node.js [fs module](http://nodejs.org/api/fs.html) as normal
75+
and the shim will ensure that calls to fs are appropriately handled by filer.
76+
77+
```javascript
78+
import fs from 'fs';
79+
```
80+
81+
If any calls are made to fs or fs.promises methods before the file system has been
82+
initialised, the shim will automatically delay the call until the file system is ready.
83+
84+
If you're using filer in a typescript project, the fs shim has the added
85+
benefit of allowing you to use the types for the node.js [fs module](http://nodejs.org/api/fs.html),
86+
which filer tries to match as closely as possible. Note that some methods from fs are
87+
not available, even though typescript will tell you that they are! See [Getting Started](#getting-started)
88+
for more details on filers limitations.
89+
90+
If you wish to use an alternative file system provider in place of the default (IndexedDB), you must also
91+
include an alias for this in your webpack config. For example, if you wish to use an "in memory"
92+
file system, configure webpack as shown below.
93+
94+
```javascript
95+
// webpack.config.js
96+
module.exports = {
97+
resolve: {
98+
alias: {
99+
'fsProvider': 'filer/shims/providers/memory.js',
100+
'fs': 'filer/shims/fs.js',
101+
}
102+
}
103+
}
104+
```
105+
106+
The current options for file system providers are:
107+
108+
* Default (IndexedDB) - filer/shims/providers/default.js
109+
* IndexedDB - filer/shims/providers/default.js
110+
* Memory - filer/shims/providers/memory.js
111+
112+
Though it's technically optional, it is recommended to include an alias for fsProvider in your
113+
webpack config. This will prevent webpack from logging unnecessary warnings.
114+
115+
If you wish to use your own file system provider with the node.js [fs module](http://nodejs.org/api/fs.html)
116+
shim, it will be necessary to include an alias for fsProvider which points to your providers implementation.
117+
This can be done as follows:
118+
119+
```javascript
120+
// webpack.config.js
121+
const path = require('path');
122+
123+
module.exports = {
124+
resolve: {
125+
alias: {
126+
'fsProvider': path.resolve(__dirname, 'example/dir/provider.js'),
127+
'fs': 'filer/shims/fs.js',
128+
}
129+
}
130+
}
131+
```
132+
133+
The node.js [path module](http://nodejs.org/api/path.html) also has a shim available, which can
134+
be applied in a similar manner to the node.js [fs module](http://nodejs.org/api/fs.html) shim.
135+
136+
```javascript
137+
// webpack.config.js
138+
module.exports = {
139+
resolve: {
140+
alias: {
141+
'path': 'filer/shims/path.js',
142+
}
143+
}
144+
}
145+
```
146+
147+
You can then import the node.js [path module](http://nodejs.org/api/path.html) as normal and the
148+
shim will ensure that calls to path are appropriately handled by filer.
149+
150+
```javascript
151+
import path from 'path';
152+
```
153+
154+
It may be necessary in certain cases to shim the node.js [Buffer object](http://nodejs.org/api/buffer.html). This can be impoerted as follows:
155+
156+
```javascript
157+
import { Buffer } from 'buffer';
158+
```
159+
160+
As such it can be shimmed in much the same way as path and fs:
161+
162+
```javascript
163+
// webpack.config.js
164+
module.exports = {
165+
resolve: {
166+
alias: {
167+
'buffer': 'filer/shims/buffer.js',
168+
}
169+
}
170+
}
171+
```
172+
173+
However, the Buffer object is globally defined in a node environment and many third party libraries will not import (or require) it.
174+
Using the resolve alias alone will be ineffective in such cases. Instead we must expand our webpack config to use webpacks
175+
[provide plugin](https://webpack.js.org/plugins/provide-plugin/), which will automatically load the module without the need for an import
176+
or require. This can be implemented as follows:
177+
178+
```javascript
179+
// webpack.config.js
180+
const webpack = require('webpack');
181+
182+
module.exports = {
183+
resolve: {
184+
alias: {
185+
'buffer': 'filer/shims/buffer.js',
186+
}
187+
},
188+
plugins: [
189+
new webpack.ProvidePlugin({
190+
Buffer: 'buffer',
191+
}),
192+
]
193+
}
194+
```
195+
196+
This will, in effect, make the Buffer object shim globally available in the same way that the node.js
197+
[Buffer object](http://nodejs.org/api/buffer.html) is in a node environment.
198+
57199
### Getting Started
58200
59201
Filer is as close to the node.js [fs module](http://nodejs.org/api/fs.html) as possible,

karma.conf.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@ module.exports = function(config) {
22
config.set({
33
singleRun: true,
44
basePath: '',
5-
files: ['tests/dist/index.js'],
5+
files: [
6+
'node_modules/regenerator-runtime/runtime.js',
7+
'tests/dist/index.js'
8+
],
69
frameworks: ['mocha', 'chai'],
710
reporters: ['mocha', 'summary'],
811
client: {
12+
captureConsole: true,
913
mocha: {
1014
ui: 'bdd',
1115
timeout: 5000,

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"minimatch": "^3.0.4"
5050
},
5151
"devDependencies": {
52+
"regenerator-runtime": "^0.13.7",
5253
"chai": "^4.3.0",
5354
"chai-datetime": "^1.8.0",
5455
"eslint": "^7.20.0",

shims/buffer.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const { Buffer } = require('../src/index');
2+
3+
module.exports = {
4+
__esModule: true,
5+
default: Buffer,
6+
Buffer,
7+
};

shims/fs.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const { FileSystem } = require('../src/index');
2+
3+
let Provider;
4+
try {
5+
Provider = require('fsProvider');
6+
}
7+
catch (err) {
8+
Provider = require('./providers/default');
9+
}
10+
11+
const provider = new Provider();
12+
13+
let onFsReady;
14+
let onFsError;
15+
16+
let fsReady = new Promise((resolve, reject) => {
17+
onFsReady = resolve;
18+
onFsError = reject;
19+
});
20+
21+
var fsInstance = new FileSystem({ provider }, (err) => {
22+
if (err) {
23+
onFsError(err);
24+
} else {
25+
onFsReady(true);
26+
}
27+
});
28+
29+
const fsPromises = new Proxy(fsInstance.promises, {
30+
get(target, prop) {
31+
return async (...args) => {
32+
await fsReady;
33+
return await target[prop](...args);
34+
};
35+
},
36+
});
37+
38+
const fs = new Proxy(fsInstance, {
39+
get(target, prop) {
40+
if (prop === 'promises') {
41+
return fsPromises;
42+
}
43+
44+
return (...args) => {
45+
(async () => {
46+
await fsReady;
47+
target[prop](...args);
48+
})();
49+
};
50+
},
51+
});
52+
53+
module.exports = {
54+
__esModule: true,
55+
default: fs,
56+
};

shims/path.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const { path } = require('../src/index');
2+
3+
module.exports = {
4+
__esModule: true,
5+
default: path,
6+
};

shims/providers/default.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const { Default } = require('../../src/providers/index');
2+
module.exports = Default;

shims/providers/indexeddb.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const IndexedDB = require('../../src/providers/indexeddb');
2+
module.exports = IndexedDB;

shims/providers/memory.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const Memory = require('../../src/providers/memory');
2+
module.exports = Memory;

tests/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
* get them running by default.
44
*/
55

6+
// Shims
7+
require('./spec/shims/fs.spec');
8+
require('./spec/shims/path.spec');
9+
require('./spec/shims/buffer.spec');
10+
611
// Filer
712
require('./spec/filer.spec');
813
require('./spec/filer.buffer.spec.js');

tests/lib/test-utils.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@ function shimIndexedDB(fn) {
5252
global.indexedDB = require('fake-indexeddb');
5353
}
5454

55-
fn();
55+
var result = fn();
5656

5757
if(addShim) {
5858
delete global.indexedDB;
5959
}
60+
61+
return result;
6062
}
6163

6264
function setup(callback) {

tests/spec/shims/buffer.spec.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
const expect = require('chai').expect;
3+
const bufferDefault = require('../../../shims/buffer').default;
4+
const bufferNamed = require('../../../shims/buffer').Buffer;
5+
const bufferActual = require('../../../src/index').Buffer;
6+
7+
describe.only('path shim', () => {
8+
it('default export should be defined', () => {
9+
expect(bufferDefault).to.not.be.undefined;
10+
});
11+
12+
it('named export should be defined', () => {
13+
expect(bufferNamed).to.not.be.undefined;
14+
});
15+
16+
it('default export should be re-exposing Buffer', () => {
17+
expect(bufferDefault).to.equal(bufferActual);
18+
});
19+
20+
it('named export should be re-exposing Buffer', () => {
21+
expect(bufferNamed).to.equal(bufferActual);
22+
});
23+
});

tests/spec/shims/fs.spec.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict';
2+
const expect = require('chai').expect;
3+
const utils = require('../../lib/test-utils');
4+
const fs = utils.shimIndexedDB(() => require('../../../shims/fs').default);
5+
6+
describe.only('fs shim', () => {
7+
it('should be defined', () => {
8+
expect(fs).to.not.be.undefined;
9+
});
10+
11+
it('should be an object', () => {
12+
expect(typeof fs).to.equal('object');
13+
});
14+
15+
it('should return a function when accessing fs.writeFile', () => {
16+
expect(typeof fs.writeFile).to.equal('function');
17+
});
18+
19+
it('should call callback when calling fs.writeFile', (done) => {
20+
fs.writeFile('/test.txt', 'test', function(err) {
21+
if(err) throw err;
22+
23+
done();
24+
});
25+
});
26+
27+
it('should return an object when accessing fs.promises', () => {
28+
expect(typeof fs.promises).to.equal('object');
29+
});
30+
31+
it('should return a function when accessing fs.promises.writeFile', () => {
32+
expect(typeof fs.promises.writeFile).to.equal('function');
33+
});
34+
35+
it('should return a promise which resolves when calling fs.promises.writeFile', (done) => {
36+
const writeFilePromise = fs.promises.writeFile('/test2.txt', '');
37+
expect(writeFilePromise instanceof Promise).to.equal(true);
38+
writeFilePromise.then(() => {
39+
done();
40+
}).catch((err) => {
41+
done(err);
42+
});
43+
});
44+
});

tests/spec/shims/path.spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
const expect = require('chai').expect;
3+
const path = require('../../../shims/path').default;
4+
const pathActual = require('../../../src/index').path;
5+
6+
describe.only('path shim', () => {
7+
it('should be defined', () => {
8+
expect(path).to.not.be.undefined;
9+
});
10+
11+
it('should be re-exposing path', () => {
12+
expect(path).to.equal(pathActual);
13+
});
14+
});

0 commit comments

Comments
 (0)