Skip to content

Commit

Permalink
refactor!: use bzz endpoint for file and dirs (#280)
Browse files Browse the repository at this point in the history
  • Loading branch information
AuHau committed May 6, 2021
1 parent b9e1b6c commit d08de26
Show file tree
Hide file tree
Showing 11 changed files with 545 additions and 632 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,6 @@
"engines": {
"node": ">=12.0.0",
"npm": ">=6.0.0",
"bee": "0.5.3-acbd0e2"
"bee": "0.6.0-acbd0e2"
}
}
62 changes: 15 additions & 47 deletions src/bee.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Readable } from 'stream'
import * as file from './modules/file'
import * as collection from './modules/collection'
import * as bzz from './modules/bzz'
import * as tag from './modules/tag'
import * as pinning from './modules/pinning'
import * as bytes from './modules/bytes'
Expand Down Expand Up @@ -45,6 +44,7 @@ import { EthAddress, makeEthAddress, makeHexEthAddress } from './utils/eth'
import { wrapBytesWithHelpers } from './utils/bytes'
import { assertReference } from './utils/type'
import { setJsonData, getJsonData } from './feed/json'
import { makeCollectionFromFS, makeCollectionFromFileList } from './utils/collection'

/**
* The Bee class provides a way of interacting with the Bee APIs based on the provided url
Expand Down Expand Up @@ -126,32 +126,34 @@ export class Bee {
const contentType = data.type
const fileOptions = options !== undefined ? { contentType, ...options } : { contentType }

return file.upload(this.url, fileData, fileName, fileOptions)
return bzz.uploadFile(this.url, fileData, fileName, fileOptions)
} else {
return file.upload(this.url, data, name, options)
return bzz.uploadFile(this.url, data, name, options)
}
}

/**
* Download single file as a byte array
*
* @param reference Bee file reference
* @param path If reference points to manifest, then this parameter defines path to the file
*/
downloadFile(reference: Reference | string): Promise<FileData<Data>> {
downloadFile(reference: Reference | string, path = ''): Promise<FileData<Data>> {
assertReference(reference)

return file.download(this.url, reference)
return bzz.downloadFile(this.url, reference, path)
}

/**
* Download single file as a readable stream
*
* @param reference Bee file reference
* @param path If reference points to manifest, then this parameter defines path to the file
*/
downloadReadableFile(reference: Reference | string): Promise<FileData<Readable>> {
downloadReadableFile(reference: Reference | string, path = ''): Promise<FileData<Readable>> {
assertReference(reference)

return file.downloadReadable(this.url, reference)
return bzz.downloadFileReadable(this.url, reference, path)
}

/**
Expand All @@ -165,9 +167,9 @@ export class Bee {
* @returns reference of the collection of files
*/
async uploadFiles(fileList: FileList | File[], options?: CollectionUploadOptions): Promise<Reference> {
const data = await collection.buildFileListCollection(fileList)
const data = await makeCollectionFromFileList(fileList)

return collection.upload(this.url, data, options)
return bzz.uploadCollection(this.url, data, options)
}

/**
Expand All @@ -176,48 +178,14 @@ export class Bee {
* Uses the `fs` module of Node.js
*
* @param dir the path of the files to be uploaded
* @param recursive specifies if the directory should be recursively uploaded
* @param options Additional options like tag, encryption, pinning
*
* @returns reference of the collection of files
*/
async uploadFilesFromDirectory(dir: string, recursive = true, options?: CollectionUploadOptions): Promise<Reference> {
const data = await collection.buildCollection(dir, recursive)
async uploadFilesFromDirectory(dir: string, options?: CollectionUploadOptions): Promise<Reference> {
const data = await makeCollectionFromFS(dir)

return collection.upload(this.url, data, options)
}

/**
* Download single file as a byte array from collection given using the path
*
* @param reference Bee collection reference
* @param path Path of the requested file in the collection
*
* @returns file in byte array with metadata
*/
downloadFileFromCollection(reference: Reference | string, path = ''): Promise<FileData<Data>> {
assertReference(reference)

return collection.download(this.url, reference, path)
}

/**
* Download single file as a readable stream from collection given using the path
*
* @param reference Bee collection reference
* @param path Path of the requested file in the collection
* @param axiosOptions optional - alter default options of axios HTTP client
*
* @returns file in readable stream with metadata
*/
downloadReadableFileFromCollection(
reference: Reference | string,
path = '',
axiosOptions?: AxiosRequestConfig,
): Promise<FileData<Readable>> {
assertReference(reference)

return collection.downloadReadable(this.url, reference, path, axiosOptions)
return bzz.uploadCollection(this.url, data, options)
}

/**
Expand Down
161 changes: 161 additions & 0 deletions src/modules/bzz.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import {
Collection,
CollectionUploadOptions,
Data,
FileData,
FileUploadOptions,
Reference,
UploadHeaders,
} from '../types'
import { extractUploadHeaders, readFileHeaders } from '../utils/headers'
import { safeAxios } from '../utils/safeAxios'
import { prepareData } from '../utils/data'
import { BeeArgumentError } from '../utils/error'
import { makeTar } from '../utils/tar'
import { assertCollection } from '../utils/collection'
import { AxiosRequestConfig } from 'axios'
import { wrapBytesWithHelpers } from '../utils/bytes'
import { Readable } from 'stream'

const bzzEndpoint = '/bzz'

interface FileUploadHeaders extends UploadHeaders {
'content-length'?: string
'content-type'?: string
}

function extractFileUploadHeaders(options?: FileUploadOptions): FileUploadHeaders {
const headers: FileUploadHeaders = extractUploadHeaders(options)

if (options?.size) headers['content-length'] = String(options.size)

if (options?.contentType) headers['content-type'] = options.contentType

return headers
}
export async function uploadFile(
url: string,
data: string | Uint8Array | Readable | ArrayBuffer,
name?: string,
options?: FileUploadOptions,
): Promise<Reference> {
if (!url) {
throw new BeeArgumentError('url parameter is required and cannot be empty', url)
}

const response = await safeAxios<{ reference: Reference }>({
...options?.axiosOptions,
method: 'post',
url: url + bzzEndpoint,
data: prepareData(data),
headers: {
...extractFileUploadHeaders(options),
},
params: { name },
responseType: 'json',
})

return response.data.reference
}

/**
* Download single file as a buffer
*
* @param url Bee URL
* @param hash Bee file or collection hash
* @param path If hash is collection then this defines path to a single file in the collection
* @param axiosOptions optional - alter default options of axios HTTP client
*/
export async function downloadFile(
url: string,
hash: string,
path = '',
axiosOptions?: AxiosRequestConfig,
): Promise<FileData<Data>> {
const response = await safeAxios<ArrayBuffer>({
...axiosOptions,
method: 'GET',
responseType: 'arraybuffer',
url: `${url}${bzzEndpoint}/${hash}/${path}`,
})
const file = {
...readFileHeaders(response.headers),
data: wrapBytesWithHelpers(new Uint8Array(response.data)),
}

return file
}

/**
* Download single file as a readable stream
*
* @param url Bee URL
* @param hash Bee file or collection hash
* @param path If hash is collection then this defines path to a single file in the collection
* @param axiosOptions optional - alter default options of axios HTTP client
*/
export async function downloadFileReadable(
url: string,
hash: string,
path = '',
axiosOptions?: AxiosRequestConfig,
): Promise<FileData<Readable>> {
const response = await safeAxios<Readable>({
...axiosOptions,
method: 'GET',
responseType: 'stream',
url: `${url}${bzzEndpoint}/${hash}/${path}`,
})
const file = {
...readFileHeaders(response.headers),
data: response.data,
}

return file
}

/*******************************************************************************************************************/
// Collections

interface CollectionUploadHeaders extends UploadHeaders {
'swarm-index-document'?: string
'swarm-error-document'?: string
}

function extractCollectionUploadHeaders(options?: CollectionUploadOptions): CollectionUploadHeaders {
const headers: CollectionUploadHeaders = extractUploadHeaders(options)

if (options?.indexDocument) headers['swarm-index-document'] = options.indexDocument

if (options?.errorDocument) headers['swarm-error-document'] = options.errorDocument

return headers
}

export async function uploadCollection(
url: string,
collection: Collection<Uint8Array>,
options?: CollectionUploadOptions,
): Promise<Reference> {
if (!url) {
throw new BeeArgumentError('url parameter is required and cannot be empty', url)
}

assertCollection(collection)
const tarData = makeTar(collection)

const response = await safeAxios<{ reference: Reference }>({
...options?.axiosOptions,
method: 'post',
url: url + bzzEndpoint,
data: tarData,
responseType: 'json',
headers: {
'content-type': 'application/x-tar',
'swarm-collection': 'true',
...extractCollectionUploadHeaders(options),
},
})

return response.data.reference
}
Loading

0 comments on commit d08de26

Please sign in to comment.