Skip to content

Commit 9c85d12

Browse files
committed
first commit
0 parents  commit 9c85d12

File tree

7 files changed

+302
-0
lines changed

7 files changed

+302
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2018 Mathias Buus
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# random-access-chrome-file
2+
3+
A [random-access-storage](https://github.com/random-access-storage/random-access-storage) instance backed by the Chrome file system api
4+
5+
```
6+
npm install random-access-chrome-file
7+
```
8+
9+
## Usage
10+
11+
``` js
12+
// Currently only works in Chrome
13+
14+
const createFile = require('random-access-chrome-file')
15+
16+
const file = createFile('test.txt')
17+
18+
file.write(0, Buffer.from('hello world'), function (err) {
19+
if (err) throw err
20+
file.read(0, 11, function (err, buf) {
21+
if (err) throw err
22+
console.log(buf.toString())
23+
})
24+
})
25+
```
26+
27+
## API
28+
29+
#### `file = createFile(name, [options])`
30+
31+
Returns a [random-access-storage](https://github.com/random-access-storage/random-access-storage) instance that supports
32+
the full API.
33+
34+
Options include:
35+
36+
```js
37+
{
38+
maxSize: Number.MAX_SAFE_INTEGER
39+
}
40+
```
41+
42+
`maxSize` is the storage quota it asks the browser for. If you are making an extension you can set the `unlimitedStorage`
43+
to get all the storage you want. Otherwise tweak the `maxSize` option to fit your needs.
44+
45+
If you want to change the `maxSize` default for all instances change `createFile.DEFAULT_MAX_SIZE`.
46+
47+
#### `createFile.requestQuota(maxSize, cb)`
48+
49+
Manually request the `maxSize` quota without creating af file.
50+
51+
## License
52+
53+
MIT

bench.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const createFile = require('./')
2+
3+
const st = createFile('benchmark.txt')
4+
st.open(benchWrite)
5+
6+
function benchRead () {
7+
var offset = 0
8+
console.time('512mb read')
9+
st.read(0, 65536, function onread (err, buf) {
10+
if (err) throw err
11+
if (offset >= 512 * 1024 * 1024) return console.timeEnd('512mb read')
12+
st.read(offset += buf.length, 65536, onread)
13+
})
14+
}
15+
16+
function benchWrite () {
17+
var offset = 0
18+
const buf = Buffer.alloc(65536).fill('hi')
19+
console.time('512mb write')
20+
st.write(offset, buf, function onwrite (err) {
21+
if (err) throw err
22+
if (offset >= 512 * 1024 * 1024) {
23+
console.timeEnd('512mb write')
24+
benchRead()
25+
return
26+
}
27+
st.write(offset += buf.length, buf, onwrite)
28+
})
29+
}

example.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const createFile = require('./')
2+
3+
const st = createFile('hello-world.txt')
4+
var missing = 2
5+
6+
st.write(0, Buffer.from('hello '), done)
7+
st.write(6, Buffer.from('world'), done)
8+
9+
function done (err) {
10+
if (err) throw err
11+
if (!--missing) st.read(0, 11, (_, buf) => console.log(buf.toString()))
12+
}

index.js

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
const ras = require('random-access-storage')
2+
3+
const TYPE = {type: 'octet/stream'}
4+
const requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem
5+
const persistentStorage = navigator.persistentStorage || navigator.webkitPersistentStorage
6+
const FileReader = window.FileReader
7+
const Blob = window.Blob
8+
9+
createFile.DEFAULT_MAX_SIZE = Number.MAX_SAFE_INTEGER
10+
createFile.requestQuota = requestQuota
11+
12+
module.exports = createFile
13+
14+
function requestQuota (n, force, cb) {
15+
if (typeof force === 'function') return requestQuota(n, true, force)
16+
persistentStorage.queryUsageAndQuota(function (used, quota) {
17+
if (quota && !force) return cb(null, quota)
18+
persistentStorage.requestQuota(n, function (quota) {
19+
cb(null, quota)
20+
}, cb)
21+
}, cb)
22+
}
23+
24+
function createFile (name, opts) {
25+
if (!opts) opts = {}
26+
27+
const maxSize = opts.maxSize || createFile.DEFAULT_MAX_SIZE
28+
const waiting = []
29+
const writers = []
30+
const readers = []
31+
32+
var fs = null
33+
var file = null
34+
var entry = null
35+
var truncate = null
36+
var totalWriters = 0
37+
38+
return ras({read, write, open, stat, close})
39+
40+
function wait (req) {
41+
waiting.push(req)
42+
}
43+
44+
function allocWriter (req) {
45+
const io = {writer: null, req: null}
46+
47+
entry.createWriter(function (writer) {
48+
io.writer = writer
49+
io.writer.onerror = function (err) {
50+
onwrite(err)
51+
}
52+
io.writer.onwriteend = function () {
53+
onwrite(null)
54+
}
55+
56+
writers.push(io)
57+
totalWriters++
58+
write(req)
59+
}, onallocerror)
60+
61+
function onallocerror (err) {
62+
req.callback(err)
63+
}
64+
65+
function onwrite (err) {
66+
const req = io.req
67+
io.req = null
68+
writers.push(io)
69+
70+
if (truncate) {
71+
if (io === truncate) {
72+
truncate = null
73+
while (waiting.length) write(waiting.pop())
74+
write(req)
75+
return
76+
}
77+
78+
if (totalWriters - writers.length === 1) {
79+
truncate.writer.truncate(truncate.req.offset)
80+
}
81+
}
82+
83+
req.callback(err, null)
84+
}
85+
}
86+
87+
function allocReader () {
88+
const io = {reader: null, req: null}
89+
90+
io.reader = new FileReader()
91+
io.reader.onerror = function (err) {
92+
onread(err, null)
93+
}
94+
io.reader.onload = function () {
95+
onread(null, Buffer.from(this.result))
96+
}
97+
98+
return io
99+
100+
function onread (err, buf) {
101+
const req = io.req
102+
io.req = null
103+
readers.push(io)
104+
req.callback(err, buf)
105+
}
106+
}
107+
108+
function read (req) {
109+
const io = readers.pop() || allocReader()
110+
io.req = req
111+
io.reader.readAsArrayBuffer(file.slice(req.offset, req.offset + req.size))
112+
}
113+
114+
function close (req) {
115+
entry = file = fs = null
116+
req.callback(null)
117+
}
118+
119+
function write (req) {
120+
if (truncate) return wait(req)
121+
122+
const io = writers.pop()
123+
if (!io) return allocWriter(req)
124+
125+
io.req = req
126+
127+
if (req.offset > file.size) {
128+
truncate = io
129+
if (totalWriters - writers.length === 1) io.writer.truncate(req.offset)
130+
return
131+
}
132+
133+
io.writer.seek(req.offset)
134+
io.writer.write(new Blob([req.data], TYPE))
135+
}
136+
137+
function stat (req) {
138+
req.callback(null, file)
139+
}
140+
141+
function open (req) {
142+
requestQuota(maxSize, false, function (err, granted) {
143+
if (err) return onerror(err)
144+
requestFileSystem(window.PERSISTENT, granted, function (res) {
145+
fs = res
146+
fs.root.getFile(name, {create: true}, function (e) {
147+
entry = e
148+
entry.file(function (f) {
149+
file = f
150+
req.callback(null)
151+
}, onerror)
152+
}, onerror)
153+
}, onerror)
154+
})
155+
156+
function onerror (err) {
157+
fs = file = entry = null
158+
req.callback(err)
159+
}
160+
}
161+
}

package.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "random-access-chrome-file",
3+
"version": "0.0.0",
4+
"description": "random-access-storage instance backed by the Chrome file system api.",
5+
"main": "index.js",
6+
"dependencies": {
7+
"random-access-storage": "^1.3.0"
8+
},
9+
"devDependencies": {
10+
"standard": "^11.0.1"
11+
},
12+
"scripts": {
13+
"test": "standard"
14+
},
15+
"repository": {
16+
"type": "git",
17+
"url": "https://github.com/mafintosh/random-access-chrome-file.git"
18+
},
19+
"author": "Mathias Buus (@mafintosh)",
20+
"license": "MIT",
21+
"bugs": {
22+
"url": "https://github.com/mafintosh/random-access-chrome-file/issues"
23+
},
24+
"homepage": "https://github.com/mafintosh/random-access-chrome-file"
25+
}

0 commit comments

Comments
 (0)