Skip to content

Commit

Permalink
feat(buckets): fix abstract interfaces, adjust bucket to inherit abst…
Browse files Browse the repository at this point in the history
…ract bucket
  • Loading branch information
josephmcg committed May 26, 2022
1 parent 3c3337d commit be5a7c4
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 119 deletions.
2 changes: 1 addition & 1 deletion components/views/files/view/View.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default Vue.extend({
.slice(((this.file.name.lastIndexOf('.') - 1) >>> 0) + 2)
.toLowerCase()
await this.$TextileManager.bucket?.pullFileStream(
await this.$TextileManager.bucket?.pullFile(
this.file.id,
this.file.extension === fileExt
? this.file.name
Expand Down
3 changes: 2 additions & 1 deletion config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export const Config = {
groupChatThreadID:
'bafkv7ordeargenxdutqdltvlo6sbfcfdhuvmocrt4qe6kpohrdbrbdi',
fsTable: 'sat.json',
bucketName: 'personal-files',
privateBucket: 'personal-files',
sharedBucket: 'shared-files',
},
ipfs: {
gateway: 'https://satellite.mypinata.cloud/ipfs/',
Expand Down
6 changes: 3 additions & 3 deletions libraries/Files/TextileFileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Vue from 'vue'
import skaler from 'skaler'
import { FilSystem } from './FilSystem'
import { FILE_TYPE } from './types/file'
import { Bucket } from './remote/textile/Bucket'
import { PrivateBucket } from './remote/textile/PrivateBucket'
import { Config } from '~/config'
import { EnvInfo } from '~/utilities/EnvInfo'
import { mimeType, isHeic, isMimeEmbeddableImage } from '~/utilities/FileType'
Expand All @@ -13,9 +13,9 @@ const convert = require('heic-convert')
export class TextileFileSystem extends FilSystem {
/**
* @getter bucket
* @returns {Bucket} bucket global to upload files to textile
* @returns {PrivateBucket} bucket global to upload files to textile
*/
get bucket(): Bucket {
get bucket(): PrivateBucket {
return Vue.prototype.$TextileManager.bucket
}

Expand Down
1 change: 0 additions & 1 deletion libraries/Files/errors/Errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export enum TextileErrors {

export enum FileSystemErrors {
// internal
METHOD_MISSING = 'Method not implemented.',
RFM_ABSTRACT_ONLY = 'RFM class is Abstract. It can only be extended',
ITEM_ABSTRACT_ONLY = 'Item class is Abstract. It can only be extended',
// user facing - Item
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,30 @@
import { Buckets, Root } from '@textile/buckets'
import { createWriteStream } from 'streamsaver'
import { Config } from '~/config'
import {
FileSystemExport,
FILESYSTEM_TYPE,
} from '~/libraries/Files/types/filesystem'
import { FileSystemExport } from '~/libraries/Files/types/filesystem'
import { TextileInitializationData } from '~/types/textile/manager'
import { RFM } from '~/libraries/Files/remote/abstracts/RFM.abstract'
import { RFMInterface } from '~/libraries/Files/remote/interface/RFM.interface'

export class Bucket extends RFM implements RFMInterface {
private _textile: TextileInitializationData
private _index: FileSystemExport | null = null
private _buckets: Buckets | null
private _key: Root['key'] | null
private _root: Root | Root['path'] = ''
export abstract class BucketAbstract extends RFM {
protected _textile?: TextileInitializationData
protected _buckets?: Buckets
protected _key?: Root['key']
protected _root?: Root | Root['path']

constructor(textile: TextileInitializationData) {
super()
this._textile = textile
this._buckets = null
this._key = null
}

/**
* @getter
* @returns file system export data
*/
get index(): FileSystemExport | null {
return this._index
}
abstract get index(): FileSystemExport | undefined

/**
* @method init
* @method getBucket
* @description Initializes bucket
* @param name bucket name
* @param param0 bucket name and encrypted status
* @returns a promise that resolves when the initialization completes
*/
async init(name: string): Promise<FileSystemExport> {
async getBucket({ name, encrypted }: { name: string; encrypted: boolean }) {
if (!Config.textile.key) {
throw new Error('Textile key not found')
}
Expand All @@ -46,69 +33,17 @@ export class Bucket extends RFM implements RFMInterface {
{ key: Config.textile.key },
{ host: Config.textile.apiUrl },
)
if (!this._textile?.identity) {
throw new Error('textile not initialized')
}
await this._buckets.getToken(this._textile.identity)

const result = await this._buckets.getOrCreate(name, { encrypted: true })
const result = await this._buckets.getOrCreate(name, { encrypted })

if (!result.root) throw new Error(`failed to open bucket ${name}`)

this._key = result.root.key
this._root = result.root

try {
const data = []
for await (const bytes of this._buckets.pullPath(
this._key,
Config.textile.fsTable,
)) {
data.push(bytes)
}
this._index = JSON.parse(
await new Blob(data, {
type: 'application/json',
}).text(),
)

if (!this._index) throw new Error('Index not found')

return this._index
} catch (e) {
return {
type: FILESYSTEM_TYPE.DEFAULT,
version: 1,
content: [],
}
}
}

/**
* @method updateIndex
* @param index FileSystemExport
* @description sets file system import data
*/
async updateIndex(index: FileSystemExport) {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}
this._index = index
const res = await this._buckets.pushPath(
this._key,
Config.textile.fsTable,
Buffer.from(JSON.stringify(index)),
{ root: this._root },
)
this._root = res.root
}

/**
* @method ipnsLink
* @returns {Promise<string>} ipns bucket link
*/
async ipnsLink(): Promise<string> {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}
return (await this._buckets.links(this._key)).ipns
}

/**
Expand Down Expand Up @@ -142,6 +77,7 @@ export class Bucket extends RFM implements RFMInterface {
}

private _getStream(file: File) {
// @ts-ignore
const reader = file.stream().getReader()
const stream = new ReadableStream({
start(controller) {
Expand All @@ -164,13 +100,13 @@ export class Bucket extends RFM implements RFMInterface {
}

/**
* @method pullFileStream
* @method pullFile
* @description fetch encrypted file from bucket
* @param {string} id file path in bucket
* @param {string} name file name
* @param {number} size file size to show progress in browser
*/
async pullFileStream(id: string, name: string, size: number) {
async pullFile(id: string, name: string, size: number) {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}
Expand Down
20 changes: 5 additions & 15 deletions libraries/Files/remote/abstracts/RFM.abstract.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
// Remote file management
import { FileSystemErrors } from '../../errors/Errors'
import { Fil } from '../../Fil'
import { RFMInterface } from '../interface/RFM.interface'
import { FileSystemExport } from '~/libraries/Files/types/filesystem'

export abstract class RFM implements RFMInterface {
export abstract class RFM {
constructor() {
if (this.constructor.name === 'RFM')
throw new Error(FileSystemErrors.RFM_ABSTRACT_ONLY)
}

updateIndex(index: FileSystemExport): void {
throw new Error(FileSystemErrors.METHOD_MISSING)
}
abstract updateIndex(index: FileSystemExport): void

get index(): FileSystemExport | null {
throw new Error(FileSystemErrors.METHOD_MISSING)
}
abstract get index(): FileSystemExport | undefined

delete(file: Fil): boolean {
throw new Error(FileSystemErrors.METHOD_MISSING)
}
abstract pullFile(id: string, name: string, size: number): void

upload(file: File, name: string, meta: any): string {
throw new Error(FileSystemErrors.METHOD_MISSING)
}
abstract removeFile(name: string): void
}
9 changes: 0 additions & 9 deletions libraries/Files/remote/interface/RFM.interface.ts

This file was deleted.

79 changes: 79 additions & 0 deletions libraries/Files/remote/textile/PrivateBucket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { BucketAbstract } from '../abstracts/Bucket.abstract'
import { Config } from '~/config'
import {
FileSystemExport,
FILESYSTEM_TYPE,
} from '~/libraries/Files/types/filesystem'

export class PrivateBucket extends BucketAbstract {
private _index?: FileSystemExport
/**
* @getter
* @returns file system export data
*/
get index(): FileSystemExport | undefined {
return this._index
}

/**
* @method init
* @description Initializes bucket
* @param name bucket name
* @returns {Promise<FileSystemExport>} a promise that resolves when the initialization completes
*/
async init({
name,
encrypted,
}: {
name: string
encrypted: boolean
}): Promise<FileSystemExport> {
await this.getBucket({ name, encrypted })
if (!this._buckets || !this._key) {
throw new Error('woah')
}
try {
const data = []
for await (const bytes of this._buckets.pullPath(
this._key,
Config.textile.fsTable,
)) {
data.push(bytes)
}
this._index = JSON.parse(
await new Blob(data, {
type: 'application/json',
}).text(),
)

if (!this._index) throw new Error('Index not found')

return this._index
} catch (e) {
return {
type: FILESYSTEM_TYPE.DEFAULT,
version: 1,
content: [],
}
}
}

/**
* @method updateIndex
* @param index FileSystemExport
* @description sets file system import data
*/
async updateIndex(index: FileSystemExport) {
if (!this._buckets || !this._key) {
throw new Error('Bucket or bucket key not found')
}
this._index = index
const res = await this._buckets.pushPath(
this._key,
Config.textile.fsTable,
Buffer.from(JSON.stringify(index)),
{ root: this._root },
)
this._root = res.root
}
}
8 changes: 4 additions & 4 deletions libraries/Files/test/Bucket.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Fil } from '../Fil'
import { FilSystem } from '../FilSystem'
import { Bucket } from '../remote/textile/Bucket'
import { PrivateBucket } from '../remote/textile/PrivateBucket'
import { DIRECTORY_TYPE } from '../types/directory'
import { FileSystemExport } from '../types/filesystem'

Expand Down Expand Up @@ -41,9 +41,9 @@ describe('Test FileSystem Directory', () => {
users: 'Users',
wallet: 'SolanaWallet',
}
const bucket = new Bucket(initializationData)
const bucket = new PrivateBucket(initializationData)

expect(bucket.index).toBeNull()
expect(bucket.index).toBeUndefined()
})
it.skip('initialize bucket', async () => {
const initializationData = {
Expand All @@ -54,7 +54,7 @@ describe('Test FileSystem Directory', () => {
users: 'Users',
wallet: 'SolanaWallet',
}
const bucket = new Bucket(initializationData)
const bucket = new PrivateBucket(initializationData)
try {
await bucket.init('init')
} catch (error) {
Expand Down
11 changes: 7 additions & 4 deletions libraries/Textile/TextileManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Bucket } from '../Files/remote/textile/Bucket'
import { PrivateBucket } from '../Files/remote/textile/PrivateBucket'
import { MetadataManager } from './MetadataManager'
import { UserInfoManager } from './UserManager'
import { Config } from '~/config'
Expand All @@ -18,7 +18,7 @@ export default class TextileManager {
identityManager: IdentityManager
mailboxManager?: MailboxManager
bucketManager?: BucketManager
bucket?: Bucket
bucket?: PrivateBucket
groupChatManager?: GroupChatManager
metadataManager?: MetadataManager
userInfoManager?: UserInfoManager
Expand Down Expand Up @@ -80,8 +80,11 @@ export default class TextileManager {
await this.bucketManager.init().catch((e) => console.log(e))

// Initialize bucket
this.bucket = new Bucket(textile)
await this.bucket.init(Config.textile.bucketName)
this.bucket = new PrivateBucket(textile)
await this.bucket.init({
name: Config.textile.privateBucket,
encrypted: true,
})

// GroupChatManager initializes itself during the creation
this.groupChatManager = new GroupChatManager(
Expand Down

0 comments on commit be5a7c4

Please sign in to comment.