Skip to content

Commit

Permalink
Merge pull request #182 from qgustavor/next
Browse files Browse the repository at this point in the history
Release - v1.2.0
  • Loading branch information
qgustavor authored Apr 18, 2024
2 parents 261eaac + aa6e1b7 commit 1d74498
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 4 deletions.
14 changes: 11 additions & 3 deletions lib/api.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { EventEmitter } from 'events'
import { Agent as HttpAgent } from 'http'
import { Agent as HttpsAgent } from 'https'
import fetch from 'node-fetch'
import AbortController from './abort-controller-polyfill.mjs'
import { createPromise } from './util.mjs'

Expand Down Expand Up @@ -63,7 +62,7 @@ class API extends EventEmitter {
this.closed = false
}

defaultFetch (url, opts) {
async defaultFetch (url, opts) {
if (!opts) opts = {}
if (!opts.agent) {
opts.agent = url => url.protocol === 'http:' ? this.httpAgent : this.httpsAgent
Expand All @@ -74,7 +73,16 @@ class API extends EventEmitter {
if (!opts.headers['user-agent']) opts.headers['user-agent'] = this.userAgent
}

return fetch(url, opts)
if (!API.fetchModule) {
if (typeof globalThis.fetch === 'function') {
API.fetchModule = globalThis.fetch
} else {
const nodeFetch = await import('node-fetch')
API.fetchModule = nodeFetch.fetch
}
}

return API.fetchModule(url, opts)
}

request (json, originalCb, retryno = 0) {
Expand Down
60 changes: 60 additions & 0 deletions lib/file.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,66 @@ class File extends EventEmitter {
return promise
}

find (query, deep) {
if (!this.children) throw Error('You can only call .find on directories')

if (typeof query === 'string') {
const queryString = query
query = file => file.name === queryString
} else if (Array.isArray(query)) {
const queryArray = query
query = file => queryArray.includes(file.name)
}
if (typeof query !== 'function') {
throw Error('Query must be a file matching function, an array of valid file names or a string with a file name')
}

return this.children.reduce((result, entry) => {
if (result) return result
if (entry.children) {
return deep ? entry.find(query, deep) : null
}
return query(entry) ? entry : null
}, null)
}

filter (query, deep) {
if (!this.children) throw Error('You can only call .filter on directories')

if (typeof query === 'string') {
const queryString = query
query = file => file.name === queryString
} else if (Array.isArray(query)) {
const queryArray = query
query = file => queryArray.includes(file.name)
}
if (typeof query !== 'function') {
throw Error('Query must be a file matching function, an array of valid file names or a string with a file name')
}

return this.children.reduce((results, entry) => {
if (entry.children) {
if (deep) return results.concat(entry.find(query, deep))
return results
}
return query(entry) ? results.concat(entry) : results
}, [])
}

navigate (query, deep) {
if (!this.children) throw Error('You can only call .navigate on directories')

if (typeof query === 'string') {
query = query.split('/')
} else if (!Array.isArray(query)) {
throw Error('Query must be an array or a string')
}

return query.reduce((node, name) => {
return node && node.children && node.children.find(e => e.name === name)
}, this)
}

static fromURL (opt, extraOpt = {}) {
if (typeof opt === 'object') {
// todo: warn to use File directly
Expand Down
24 changes: 24 additions & 0 deletions lib/storage.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,30 @@ class Storage extends EventEmitter {
return this.root.upload(opt, buffer, cb)
}

// alternative to this.root.find
find (query, deep) {
if (this.status !== 'ready') {
throw Error('storage is not ready')
}
return this.root.find(query, deep)
}

// alternative to this.root.filter
filter (query, deep) {
if (this.status !== 'ready') {
throw Error('storage is not ready')
}
return this.root.filter(query, deep)
}

// alternative to this.root.navigate
navigate (query, deep) {
if (this.status !== 'ready') {
throw Error('storage is not ready')
}
return this.root.navigate(query, deep)
}

close (cb) {
// Does not handle still connecting or incomplete streams
this.status = 'closed'
Expand Down
2 changes: 1 addition & 1 deletion test/helpers/test-runner.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ if (testedPlatform === 'node') {
if (!wasFailed) {
const serverStateSerialized = JSON.stringify(server.state)
const serverStateHash = crypto.createHash('blake2b512').update(serverStateSerialized).digest('hex').slice(0, 64)
const expectedStateHash = 'f7f498beb8fd4b1175e65474c38b0cd54c2b4f57442ab964645e9459bf62d89b'
const expectedStateHash = '49bd600b894f168a356f9cd2c5b3bf638bafd63c941005097cd893cd35229b99'

if (serverStateHash !== expectedStateHash) {
console.error('Got server state hash', serverStateHash)
Expand Down
64 changes: 64 additions & 0 deletions test/storage.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import test from 'ava'
import { testBuffer, sha1 } from './helpers/test-utils.mjs'
import { Storage, File } from '../dist/main.node-es.mjs'
import { Readable } from 'stream'

// Set up Storage to use test server and credentials
const gatewayUrl = typeof Deno !== 'undefined'
Expand Down Expand Up @@ -502,6 +503,69 @@ test.serial('Should allowUploadBuffering ', async t => {
t.is(file.size, dataSize)
})

test.serial('Should stream as upload arguments', async t => {
const dataSize = 2 * 1024 * 1024
const uploadedData = testBuffer(dataSize)
let readBytes = 0
const inputStream = new Readable({
read (size) {
const newPointer = readBytes + size
this.push(readBytes < dataSize ? uploadedData.slice(readBytes, newPointer) : null)
readBytes = newPointer
}
})
const uploadStream = storage.upload({
name: 'test file streams 2',
key: Buffer.alloc(24),
size: dataSize
}, inputStream)

const file = await uploadStream.complete
t.is(file.name, 'test file streams 2')
t.is(file.key.toString('hex'), '0000000000000000831f1ab870f945580000000000000000831f1ab870f94558')
t.is(file.size, dataSize)
})

test.serial('Should find files using functions', t => {
const matchingFile = storage.find(e => e.name.includes('test file streams'))
t.is(matchingFile.size, 2097152)
})

test.serial('Should find files using string', t => {
const matchingFile = storage.find('file in folder 2', true)
t.is(matchingFile.size, 16)
})

test.serial('Should find files using arrays', t => {
const matchingFile = storage.find(['file in folder 2'], true)
t.is(matchingFile.size, 16)
})

test.serial('Should filter files using functions', t => {
const matchingFiles = storage.filter(e => e.name.includes('test file streams'))
t.is(matchingFiles.length, 4)
})

test.serial('Should filter files using string', t => {
const matchingFiles = storage.filter('file in folder 2', true)
t.is(matchingFiles.length, 1)
})

test.serial('Should filter files using arrays', t => {
const matchingFiles = storage.filter(['test file streams', 'test file streams 2', 'file in folder 2'], true)
t.is(matchingFiles.length, 5)
})

test.serial('Should navigate to files using arrays', t => {
const matchingFile = storage.navigate(['test folder', 'test folder 2', 'file in folder 2'])
t.is(matchingFile.size, 16)
})

test.serial('Should navigate to files using strings', t => {
const matchingFile = storage.navigate('test folder/test folder 2/file in folder 2')
t.is(matchingFile.size, 16)
})

test.serial('Should logout from MEGA', t => {
return new Promise((resolve, reject) => {
storage.close((error) => {
Expand Down

0 comments on commit 1d74498

Please sign in to comment.