O le Mobiletto o se vaega e teu ai mea e teu ai le JavaScript, fa'atasi ai ma le fa'amalamalamaga manino a le tagata o tausia.
- Aisea Mobiletto?
- [Amata vave](#Amata vave)
- Mobiletto CLI
- Source
- Fa'apipi'i
- Lagolago ma le Faatupeina
- Fa'aoga masani
- Metadata
- Sui fa'aulufale mai
- Cach
- Fa'ata
- [Fa'amatalaga manino](#Fa'amatalaga manino)
- Tili ki ki
- Ataavale ta'avale
- Logging
O lenei README.md pepa ua faaliliuina, e ala i le hokeylization, i totonu gagana uma e lagolagoina e Google Translate!
Ou te mautinoa e le atoatoa, ae ou te faʻamoemoe e sili atu nai lo le leai!
🇸🇦 Alapi 🇧🇩 Bengali 🇩🇪 Siamani 🇺🇸 Igilisi 🇪🇸 Sipaniolo 🇫🇷 Farani 🇹🇩 Hausa 🇮🇳 Hindi 🇮🇩 Initonesia 🇮🇹 Italia 🇯🇵 Iapani 🇰🇷 Korea 🇮🇳 Marathi 🇵🇱 Polani 🇧🇷 Potukale 🇷🇺 Rusia 🇰🇪 Swahili 🇵🇭 Tagalog 🇹🇷 Turkish 🇵🇰 Urdu 🇻🇳 Vietnamese 🇨🇳 Saina
Lenei fa'aliliuga fa'apitoa o le ulua'i README atonu e sese -- fa'asa'oga e matua talia lava! Fa'amolemole lafo mai se talosaga toso ile GitHub, pe afai e te le fiafia e fai lena mea, tatala se mataupu
A e fatuina se lomiga fou GitHub e uiga i se faaliliuga, faamolemole fai:
- fa'aaofia ai le itulau URL (kopi/pa'i mai le tuatusi tuatusi pa)
- fa'aaofia ai le fa'amatalaga sa'o e sese (kopi/pa'i mai le su'esu'ega)
- fa'amolemole fa'amatala le mea o lo'o fa'aletonu -- e le sa'o le fa'aliliuga? ua malepe le faatulagaga?
- ofo mai ma le agalelei se fautuaga o se faaliliuga e sili atu, po o le auala e tatau ona faatulaga lelei ai le tusitusiga
- Faafetai!
O le tele o mea e teu ai ao e iai API e le fetaui. E oʻo lava ia i latou o loʻo taumafai mo le "S3 compatibility" e iai uiga fa'apitoa.
A e filifilia se fa'atau oloa teu mo lau app, pe a e fa'ailoga sa'o i la latou API, lau app ua faalagolago nei i lea auaunaga. A'o alu le taimi ma fa'aputuina le code, o le a suia tagata fa'atau ua faateleina le le mafaia. Faʻafeiloaʻi i le lalolagi malie o le faʻatau loka-i totonu!
Mobiletto na fuafuaina e foia lenei faafitauli. I le fa'ailogaina o lau app ile mobiletto's API, e faigofie sui kamupani teu oloa ma iloa o le a tutusa le amio a lau app.
O aveta'avale uma e fa'ata'ita'iina mo uiga tutusa ma le 60+ su'ega mo ta'avale ta'itasi. Matou te suʻeina avetaʻavale uma i tuʻufaʻatasiga uma o:
- Fa'ailoga: e mafai uma ma fa'aletonu
- Redis cache: mafai uma ma le le atoatoa
O lenei faiga e maua ai le filemu o le mafaufau o le mobiletto o le a amio tutusa tusa lava po o le a le avetaavale e te faʻaaogaina, ma e tusa lava pe e te faʻaogaina le faʻaogaina ma/poʻo le faʻailoga.
Avetaavale teuina Mobiletto nei:
s3
: Amazon S3b2
: Backblaze B2local
: faiga faila fa'apitonu'u
O sao e lagolago ai le tele o kamupani e teu ai ao e matua talia!
Mobiletto ua fa'amoemoe e fa'aoga e fai ma faletusi e isi code JavaScript.
Ina ia galue ma mobiletto i le laina-faʻatonu, faʻaaoga mobiletto-cli
O lo'o ou taumafai e avea a'u ma se tagata fa'apolofesa fa'apolofesa fa'apolofesa matala. Sa ou galue i totonu le pisinisi faakomepiuta mo le tele o tausaga, ua ou amataina kamupani manuia ma faatau atu i kamupani lautele. Talu ai nei na ou leiloa ai laʻu galuega, ma e leai lava se isi galuega o loʻo faʻatulagaina
O lea o le a ou taumafai e tusi le polokalama fesoasoani ma vaai pe aoga
Afai e te fiafia e faʻaaoga lenei polokalama, ou te matua faʻafetai lava mo le aupito itiiti saomea faalemasina e ala i Patreon
Faafetai!
Fa'apipi'i fa'aaoga npm
po'o yarn
. Atonu e te mana'o i le lite
version e le aofia uma ai
fa'aliliu faila README:
npm install mobiletto-lite
yarn add mobiletto-lite
Afai e te manaʻo moni i faila README i gagana uma, faʻapipiʻi le faʻasologa atoa:
npm install mobiletto
yarn add mobiletto
O se fa'ata'ita'iga pu'upu'u e fa'aaoga ai le aveta'avale mobiletto s3
.
E tutusa le fa'aogaina o lenei code pe afai o le aveta'avale o le b2
po'o local
.
const storage = require('mobiletto')
const bucket = await storage.connect('s3', aws_key, aws_secret, {bucket: 'bk'})
// list objects: returns array of metadata objects
const listing = await bucket.list()
const dirList = await bucket.list('some/dir/')
const everything = await bucket.list('', {recursive: true})
// write an entire file
let bytesWritten = await bucket.writeFile('some/path', someBufferOfData)
// write a file from a stream/generator
bytesWritten = await bucket.write('some/path', streamOrGenerator)
// read an entire file
// returns null if an exception would otherwise be thrown
const bufferOrNull = await bucket.safeReadFile('some/path')
// stream-read a file, passing data to callback
const bytesRead = await bucket.read('some/path', (chunk) => { ...do something with chunk... } )
// remove a file, returns the path removed
let removed = await bucket.remove('some/path') // removed is a string
// remove a directory, returns array of paths removed
removed = await bucket.remove('some/directory', {recursive: true}) // removed is now an array!
O se faʻataʻitaʻiga sili atu ona lautele, faʻaalia le tele o foliga o loʻo ofoina atu:
const { mobiletto } = require('mobiletto')
// General usage
const api = await mobiletto(driverName, key, secret, opts)
// To use 'local' driver:
// * key: base directory
// * secret: ignored, can be null
// * opts object:
// * readOnly: optional, never change anything on the filesystem; default is false
// * fileMode: optional, permissions used when creating new files, default is 0600. can be string or integer
// * dirMode: optional, permissions used when creating new directories, default is 0700. can be string or integer
const local = await mobiletto('local', '/home/ubuntu/tmp', null, {fileMode: 0o0600, dirMode: '0700'})
// To use 's3' driver:
// * key: AWS Access Key ID
// * secret: AWS Secret Key
// * opts object:
// * readOnly: optional, never change anything on the bucket; default is false
// * bucket: required, name of the S3 bucket
// * region: optional, the AWS region to communicate with, default is us-east-1
// * prefix: optional, all read/writes within the S3 bucket will be under this prefix
// * delimiter: optional, directory delimiter, default is '/' (note: always '/' when encryption is enabled)
const s3 = await mobiletto('s3', aws_key, aws_secret, {bucket: 'bk', region: 'us-east-1'})
// To use 'b2' driver:
// * key: Backblaze Key ID
// * secret: Backblaze Application Key
// * opts object:
// * readOnly: optional, never change anything on the bucket; default is false
// * bucket: required, the ID (**not the name**) of the B2 bucket
// * prefix: optional, all read/writes within the B2 bucket will be under this prefix
// * delimiter: optional, directory delimiter, default is '/' (note: always '/' when encryption is enabled)
// * partSize: optional, large files will be split into chunks of this size when uploading
const b3 = await mobiletto('b2', b2_key_id, b2_app_key, {bucket: 'bk', partSize: 10000000})
// List files
api.list() // --> returns an array of metadata objects
// List files recursively
api.list({ recursive: true })
// List files in a directory
const path = 'some/path'
api.list(path)
api.list(path, { recursive: true }) // also supports recursive flag
// Visit files in a directory -- visitor function must be async
api.list(path, { visitor: myAsyncFunc })
api.list(path, { visitor: myAsyncFunc, recursive: true })
// The `list` method throws MobilettoNotFoundError if the path does not exist
// When you call `safeList` on a non-existent path, it returns an empty array
api.safeList('/path/that/does/not/exist') // returns []
// Read metadata for a file
api.metadata(path) // returns metadata object
// The `metadata` method throws MobilettoNotFoundError if the path does not exist
// When you call `safeMetadata` on a non-existent path, it returns null
api.safeMetadata('/tmp/does_not_exist') // returns null
// Read a file
// Provide a callback that writes the data someplace
const callback = (chunk) => { ... write chunk somewhere ... }
api.read(path, callback) // returns count of bytes read
// Read an entire file at once
const data = await api.readFile(path) // returns a byte Buffer of the file contents
// Read an entire file at once
// returns null if an exception would otherwise be thrown
const bufferOrNull = await bucket.safeReadFile('some/path')
// Write a file
// Provide a generator function that yields chunks of data
const generator = function* () {
while ( ... more-data-to-return ... ) {
data = ... load-data ...
yield data
}
}
local.api(path, generator) // returns count of bytes written
// Write an entire file at once (convenience method)
await api.writeFile(path, bufferOrString) // returns count of bytes written
// Delete a file
// Quiet param is optional (default false), when set errors will not be thrown if the path does not exist
// Always returns a value or throws an error.
// Return value may be a single string of the file removed, or an array of all files removed (driver-dependent)
const quiet = true
api.remove(path, {quiet}) // returns single path removed
// Recursively delete a directory and do it quietly (do not report errors)
const recursive = true
const quiet = true
api.remove(path, {recursive, quiet}) // returns array of paths removed
O le metadata
poloaiga e toe fa'afo'i mai metadata e uiga i se faila faila e tasi.
E fa'apea fo'i, o le tau fa'afo'i mai le list
fa'atonuga o se fa'asologa o mea metadata.
O se mea metadata e pei o lenei:
{
"name": "fully/qualified/path/to/file",
"type": "entry-type",
"size": size-in-bytes,
"ctime": creation-time-epoch-millis,
"mtime": modification-time-epoch-millis
}
O le meatotino type
e mafai ona avea ma file
, dir
, link
, po'o special
.
Fa'alagolago ile ituaiga aveta'avale, ole list
fa'atonuga e le mafai ona toe fa'afo'i uma fanua. Le name
ma type
meatotino
e tatau ona i ai i taimi uma. Ole fa'atonuga ole metadata
ole a toe fa'afo'i uma meatotino avanoa.
Fa'aulufale mai le fa'aoga atoa ma fa'aoga le connect
galuega:
const storage = require('mobiletto')
const opts = {bucket: 'bk', region: 'us-east-1'}
const s3 = await storage.connect('s3', aws_key, aws_secret, opts)
const objectData = await s3.readFile('some/path')
E sili ona aoga le Mobiletto i le redis cache.
Mobiletto o le a taumafai e faʻafesoʻotaʻi i se redis faʻataʻitaʻiga ile 127.0.0.1:6379
E mafai ona e suia se tasi o mea nei:
- Seti le
MOBILETTO_REDIS_HOST
env var, mobiletto fesootai iinei nai lo localhost - Seti le
MOBILETTO_REDIS_PORT
env var, o le a fa'aoga lenei uafu
Mobiletto o le a teuina uma ana ki redis ma le prefix _mobiletto__
. E mafai ona e suia lenei mea
e ala i le setiina o le MOBILETTO_REDIS_PREFIX
env var.
E mafai fo'i ona e setiina le fa'aogaina o feso'ota'iga ma le mea opts.redisConfig
:
const redisConfig = {
enabled: true, // optional, default is true. if false other props are ignored
host: '127.0.0.1',
port: 6379,
prefix: '_mobiletto__'
}
const opts = { redisConfig, bucket: 'bk', region: 'us-east-1' }
const s3 = await storage.connect('s3', aws_key, aws_secret, opts)
E fa'agata: pasi enabled: false
i lau opts.redisConfig
mea pe a e fa'atuina lau feso'ota'iga.
E pei ona talanoaina i lalo, o le tapeina o le caching o le a i ai se aafiaga leaga i le faatinoga ma maua ai nisi talosaga i le teuina e te manaʻomia moni lava.
Teuga fa'aigoa: faitau/tusitusi fa'ailoga fa'ailoga e fa'agesegese teisi nai lo le masani, ae o le fa'ata'amilo i fa'atonuga (lea e fai e nisi mea) e fai si taugata. Faʻaaogaina o le redis cache o le a tu'uina atu ia te oe se fa'aopoopoga taua tele.
O le fa'aoga fa'aoga e saogalemu, ae e le lelei pe afai e tele au tusitusi/ave'ese galuega. So'o se tusi pe aveese fa'agaioiga e fa'aleaogaina ai le fa'aoga atoa, fa'amautinoa o le a va'aia e faitauga mulimuli ane le suiga lata mai.
Afai o lo'o e fa'aogaina se meafaigaluega CLI pei o le mobiletto-cli,
e mautinoa lava e te mana'o e fa'aaga le cache redis, aua e tumau i le fa'atonuga o le mo
command.
// Copy a local filesystem mobiletto to S3
s3.mirror(local)
// Mirror a local subdirectory from one mobiletto to an S3 mobiletto, with it's own subdirectory
local.mirror(s3, 'some/local-folder', 'some/s3-folder')
O le mirror
fa'atonuga e faia se kopi tasi taimi o faila uma mai le tasi mobiletto i le isi.
E leai se faiga e fa'atumauina ai le fa'ata ile taimi. Toe fa'atonu le mirror
e fa'amaopoopo so'o se faila e misi.
O le tau fa'afo'i mai mirror
o se mea faigofie ma fa'atau mo le tele o faila na manuia
fa'ata ma pe fia faila na iai mea sese:
{
success: count-of-files-mirrored,
errors: count-of-files-with-errors
}
LAPATA'IGA: O le fa'ataina o seti fa'amaumauga tetele e mafai ona alu tele le taimi ma fa'ato'a tele le bandwidth
Faatasi ai ma le mirror
valaau semantics e mafai i nisi taimi ona fenumiai le malamalama po o ai le
tagata faitau ma o ai le tusitala. Vaʻai faalemafaufau e pei o se faʻamatalaga o tofiga: o le "lima agavale mobiletto"
o le mea o loʻo tuʻuina atu i (faʻata faʻamatalaga tusia), ma le "lima taumatau mobiletto" (le
finauga i le mirror
auala) o le tau o loʻo tuʻuina atu (faʻata faʻamatalaga faitau).
Fa'aagaioi le fa'amalamalamaga manino le itu o tagata o tausia:
// Pass encryption parameters
const encryption = {
// key is required, must be >= 16 chars
key: randomstring.generate(128),
// optional, the default is to derive IV from key
// when set, IV must be >= 16 chars
iv: randomstring.generate(128),
// optional, the default is aes-256-cbc
algo: 'aes-256-cbc'
}
const api = await mobiletto(driverName, key, secret, opts, encryption)
// Subsequent write operations will encrypt data (client side) when writing
// Subsequent read operations will decrypt data (client side) when reading
O le a le mea o tupu? O se isi fa'asinomaga "fa'asinomaga" (dirent) fa'ailoga (fa'ailoga) e su'e ai faila o lo'o i ai directory (a'o le directory directory).
- O le
list
poloaiga e faitau ai faila fa'amaufa'ailoga, fa'ate'aina ala ta'itasi o lo'o lisiina; ona toe faafoi mai lea o metadata mo faila taitasi list
poloaiga e sili atu le le lelei, aemaise lava mo faʻamaumauga e tele faila- O le fa'atonuga
write
tusi' e tusia ai faila eseese i fa'amaumauga a matua ta'itasi, fa'asolosolo; ona tusi lea o le faila - O tulafono
write
o le a maua ai le O(N) tusitusi, ma N = loloto i le fa'atonuga o le lisi. - O le fa'atonuga
remove
e aveese ai le faila tu'usa'o, ma lona matua pe a gaogao, fa'asolosolo; ona aveese lea o le faila - O tulafono
remove
e le toe fa'afo'isia o le a maua ai le O(N) faitau ma e ono tele fo'i le tapeina, fa'atasi ai ma le N = loloto i le fa'asologa o fa'atonuga. remove
i luga o faila faila tetele ma loloto e mafai ona taugata
Manatua e tusa lava pe fa'amanaia le fa'ailoga tagata o tausia, o se fili ma le va'aia atoatoa i lau 'au'aunaga fa'ailoga. teuina, e tusa lava pe leai se ki, e mafai lava ona vaʻaia le aofaʻi o faʻamaumauga ma pe fia faila i totonu taʻitasi, ma faʻatasi nisi taumafaiga, su'e nisi po'o le fa'atulagaina atoa o le fa'asologa o fa'atonuga. Manatua: Fa'aoga se fausaga mafolafola mo le saogalemu lelei. O le a le iloa e le fili igoa o directories/faila sei vagana ua latou iloa foi lau fa'ailoga ki po'o na fa'asolo manuia le fa'ailoga. Ua uma loa peti uma!
E mafai ona faagesegese le fa'agaioiga i luga o le teuina fa'ailoga. E mafai ona telegese le fa'asologa o lisi ma aveese. E fesoasoani tele le fa'asaoina e ala i le redis, ae ia maitauina o lo'o fa'afefe le cache i luga o so'o se tusitusiga pe aveese.
Fausia se mobiletto i lau ki fou, ona faʻataʻitaʻi lea o faʻamaumauga tuai i totonu:
const storage = require('mobiletto')
const oldEncryption = { key: .... }
const oldStorage = await storage.connect('s3', aws_key, aws_secret, {bucket: 'bk', region: 'us-east-1'}, oldEncryption)
const newEncryption = { key: .... }
const newStorage = await storage.connect('s3', aws_key, aws_secret, {bucket: 'zz', region: 'us-east-1'}, newEncryption)
newStorage.mirror(oldStorage) // if oldStorage is very large, this may take a looooooong time...
O le aveta'avale o so'o se faila JS e auina atu i fafo se galuega 'storageClient' ma lenei saini:
function storageClient (key, secret, opts)
key
: o se manoa, lau ki API (mo lelocal
aveta'avale o le lisi autu lea)secret
: o se manoa, lau API mealilo (e mafai ona aveese mo le avetaavalelocal
)opts
: o se mea, o meatotino e ta'i-taavale:- Mo
local
, o lefileMode
madirMode
meatotino e fuafua ai pe fa'afefea ona faia faila fou ma fa'atonuga. - Mo
s3
, e mana'omia le meatotinobucket
. O meatotino e filifili ai o:region
: the S3 region, default is us-east-1prefix
: a prefix to prepend to all S3 paths, default is the empty stringdelimiter
: the directory delimiter, default is '/'
O le mea e toe faʻafoʻi mai e le storageClient galuega e tatau ona faʻamalamalamaina galuega nei:
// Test the driver before using, ensure proper configuration
async testConfig ()
// List files in path (or from base-directory)
// If recursive is true, list recursively
// If visitor is defined, it will be an async function. await the visitor function on each file found
// Otherwise, perform the listing and return an array of objects
async list (path, recursive = false, visitor = null) // path may be omitted
// Read metadata for a path
async metadata (path)
// Read a file
// callback receives a chunk of data. endCallback is called at end-of-stream
async read (path, callback, endCallback = null)
// Write a file
// driver must be able to handle a generator or a stream
async write (path, generatorOrReadableStream)
// Remove a file, or recursively delete a directory
// returns a string of a single path removed, or an array of multiple paths removed
async remove (path, recursive = false, quiet = false)
E fa'aoga e Mobiletto le faletusi talatala winston.
O ogalaau o le a iai ala faila ma feʻau sese, ae o le a leai lava iai ki, mealilo, po'o so'o se isi fa'amatalaga fa'aopoopo feso'ota'iga.
Fa'aoga le suiga ole siosiomaga MOBILETTO_LOG_LEVEL
e seti ai le maualuga o ogalaau, fa'aaoga le tasi
o tulaga npm
o lo'o fa'amatalaina i le https://www.npmjs.com/package/winston#logging-levels
Ole tulaga fa'aletonu ole error
. Ole la'asaga pito sili ona tautala ole silly
, e ui o le taimi nei o le mobiletto
e le fa'amauina i tulaga i lalo ole debug
MOBILETTO_LOG_LEVEL=silly # maximum logs!
Ona o le faaletonu, e tusi le logger i le faamafanafanaga. Ina ia lafo atu ogalaau i se faila, seti le MOBILETTO_LOG_FILE
fesuiaiga o le siosiomaga. A o'o i se faila, o le a le toe tusia ni ogalaau i le fa'amafanafanaga.
MOBILETTO_LOG_FILE=/var/my_mobiletto_log
Ina ia tape le laiga:
MOBILETTO_LOG_FILE=/dev/null