![Namecheap Takes Down Polyfill.io Service Following Supply Chain Attack](https://cdn.sanity.io/images/cgdhsj6q/production/6af25114feaaac7179b18127c83327568ff592d1-1024x1024.webp?w=800&fit=max&auto=format)
Security News
Namecheap Takes Down Polyfill.io Service Following Supply Chain Attack
Polyfill.io has been serving malware for months via its CDN, after the project's open source maintainer sold the service to a company based in China.
@fleekhq/space-client
Advanced tools
Readme
Space Client it's a grpc-web wrapper that allows you to connect with the space daemon and interact with it.
Before initialize the client you need to have the space-daemon up and running. You can find the daemon installation docs here
Please have in mind that daemon only supports local connections for now, that means that you just can connect through your localhost. You can't connect through a dns or try to connect to a daemon running on a different machine.
import { SpaceClient } from '@fleekhq/space-client';
// default port exposed by the daemon for client connection is 9998
const client = new SpaceClient({
url: `http://0.0.0.0:9998`,
});
...
If you are running the client on the server-side, you need to declare XMLHttpRequest
module as global. (this is because client is based on grpc-web, which is supposed to be used on client-side).
install XMLHttpRequest
yarn add xmlhttprequest
Or using npm
npm install xmlhttprequest
then to initialize the client:
global.XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const { SpaceClient } = require('@fleekhq/space-client');
// default port exposed by the daemon for client connection is 9998
const client = new SpaceClient({
url: `http://0.0.0.0:9998`,
});
...
Use this class to create space client instances able to interact with space-daemon
Options:
opts.url
: (string, required) space dameon url + port (https://0.0.0.0:9998
)opts.defaultBucket?
: (string, optional) change the default bucket. This value is used when you don't pass the bucket param on some of the methods below. if you don't pass this property, personal
bucket is going to be used as default value (personal
bucket is created by default when you run space-daemon for the first time).opts.options?
: (object, optional) grpc-web client options.opts.credentials?
: (object, optional) grpc-web client credentials.import { SpaceClient } from '@fleekhq/space-client';
const opts = {
url: 'http://0.0.0.0:9998',
defaultBucket: 'my-bucket',
};
const client = new SpaceClient(opts);
Returns the folder or files in the path directory.
If you don't specify the bucket
property, client.defaultBucket
value is going to be used instead.
client
.listDirectory({ path: '/', bucket: 'my-bucket' })
.then((res) => {
const entries = res.getEntriesList();
entries.forEach((entry) => {
console.log(entry.getPath());
console.log(entry.getName());
console.log(entry.getIsdir());
console.log(entry.getCreated());
console.log(entry.getUpdated());
console.log(entry.getIpfshash());
console.log(entry.getSizeinbytes());
console.log(entry.getFileextension());
console.log(entry.getIslocallyavailable());
console.log(entry.getBackupcount());
console.log(entry.getMembersList());
});
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.listDirectory({ path: '/', bucket: 'my-bucket' });
const entries = res.getEntriesList();
entries.forEach((entry) => {
...
});
};
Returns a Promise that resolves to an array of Directories representing all the folders and files inside the bucket.
If you don't specify the bucket
property, client.defaultBucket
value is going to be used instead.
client
.listDirectories({ bucket: 'my-bucket' })
.then((res) => {
const entries = res.getEntriesList();
entries.forEach((entry) => {
console.log(entry.getPath());
console.log(entry.getName());
console.log(entry.getIsdir());
console.log(entry.getCreated());
console.log(entry.getUpdated());
console.log(entry.getIpfshash());
console.log(entry.getSizeinbytes());
console.log(entry.getFileextension());
console.log(entry.getIslocallyavailable());
console.log(entry.getBackupcount());
console.log(entry.getMembersList());
});
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.listDirectories({ bucket: 'my-bucket' });
const entries = res.getEntriesList();
entries.forEach((entry) => {
...
});
};
Returns a ReadableStream that notifies when something changed on the bucket (data stream returns the Bucket name).
const txlStream = client.txlSubscribe();
txlStream.on('data', (res) => {
const bucket = res.getBucket();
console.log(bucket);
});
Returns a ReadableStream that notifies when a change related to the a file has occured such as the amount of members the file is shared with or whether the file is backup in Space.
const fileInfoStream = client.fileInfoSubscribe();
fileInfoStream.on('data', (res) => {
const file = res.getFile();
console.log(file);
});
Copies the file referenced by the path arg to a temp folder and returns a Promise that resolves to the file location.
If you don't specify the bucket
property, client.defaultBucket
value is going to be used instead.
const asyncFunc = async () => {
const bucket = 'my-bucket';
const dirRes = await client.listDirectories({
bucket,
});
const entriesList = dirRes.getEntriesList();
const openFileRes = await client.openFile({
bucket,
path: entriesList[0].getPath(),
});
const location = openFileRes.getLocation();
console.log(location); // "/path/to/the/copied/file"
};
Creates a new bucket. Returns a Promise that resolves to the new bucket
client
.createBucket('myNewBucket')
.then((res) => {
const bucket = res.getBucket();
console.log(bucket.getKey());
console.log(bucket.getName());
console.log(bucket.getPath());
console.log(bucket.getCreatedat());
console.log(bucket.getUpdatedat());
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.createBucket('myNewBucket');
const bucket = res.getBucket();
console.log(bucket.getName());
...
};
Add new items. Returns a readable stream to resolves the new items.
If you don't specify the bucket
property, client.defaultBucket
value is going to be used instead.
const stream = client.addItems({
bucket: 'my-bucket',
targetPath: '/',
sourcePaths: ['/path-to-my-folder-or-file-to-upload']
});
stream.on('data', (data) => {
console.log('data: ', data);
});
stream.on('error', (error) => {
console.error('error: ', error);
});
stream.on('end', () => {
console.log('end');
});
Creates a new empty folder. Returns a Promise that resolves to the new folder.
If you don't specify the bucket
property, client.defaultBucket
value is going to be used instead.
client
.createFolder({ path: '/', bucket: 'my-bucket' })
.then(() => {
console.log('folder created in path "/"');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.createFolder({ path: '/', bucket: 'my-bucket' });
};
[WIP]
.toggleBucketBackup({ bucket: string, backup: boolean }) Toggles whether or not to back up the content of a bucket to Space.
client
.toggleBucketBackup({ bucket: 'bucket-name', backup: true })
.then(() => {
console.log('bucket-name is backed up in Space!');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.toggleBucketBackup({ bucket: 'bucket-name', backup: true });
};
Backup keys by a passphrase
client
.backupKeysByPassphrase({
uuid: 'user-uuid',
passphrase: 'my-passphrase',
})
.then(() => {
console.log('keys backup');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.backupKeysByPassphrase({
uuid: 'user-uuid',
passphrase: 'my-passphrase',
});
};
Recovery keys by passphrase
client
.recoverKeysByPassphrase({
uuid: 'user-uuid',
passphrase: 'my-passphrase',
})
.then(() => {
console.log('recovery keys');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.recoverKeysByPassphrase({
uuid: 'user-uuid',
passphrase: 'my-passphrase',
});
};
Test keys with passphrase
client
.testKeysPassphrase({
uuid: 'user-uuid',
passphrase: 'my-passphrase',
})
.then(() => {
console.log('test success');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.testKeysPassphrase({
uuid: 'user-uuid',
passphrase: 'my-passphrase',
});
};
Generate key pair with force
client
.generateKeyPairWithForce()
.then(() => {
console.log('keys generated');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.generateKeyPairWithForce();
};
[WIP]
.toggleFuseDrive({ mountDrive: boolean })this method is still not supported by space-daemon
Toggle Fuse drive
client
.toggleFuseDrive({
mountDrive: true || false,
})
.then((res) => {
console.log(res.getFusedrivemounted());
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.toggleFuseDrive({
mountDrive: true || false,
});
console.log(res.getFusedrivemounted());
};
[WIP]
.getFuseDriveStatus({})this method is still not supported by space-daemon
Get Fuse drive status
client
.getFuseDriveStatus({})
.then((res) => {
console.log(res.getFusedrivemounted());
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.getFuseDriveStatus({});
console.log(res.getFusedrivemounted());
};
Returns a ReadableStream that notifies when something changed on the bucket (data stream returns the event type + the entry affected).
Event type can be one of [ENTRY_ADDED, ENTRY_DELETED, ENTRY_UPDATED]
const subscribeStream = client.subscribe();
subscribeStream.on('data', (res) => {
const eventType = res.getType();
const entry = res.getEntry();
console.log('eventType', eventType.toString());
console.log('path', entry.getPath());
console.log('name', entry.getName());
console.log('isDir', entry.getIsdir());
console.log('created', entry.getCreated());
console.log('updated', entry.getUpdated());
console.log('ipfsHash', entry.getIpfshash());
console.log('sizeInBytes', entry.getSizeinbytes());
console.log('fileExtension', entry.getFileextension());
});
[WIP]
.listBuckets()this method is still not supported by space-daemon
Returns all the buckets available
client
.listBuckets()
.then((res) => {
const buckets = res.getBucketsList();
buckets.forEach((bucket) => {
console.log('key:', bucket.getKey());
console.log('name:', bucket.getName());
console.log('path:', bucket.getPath());
console.log('createdAt:', bucket.getCreatedat());
console.log('updatedAt:', bucket.getUpdatedat());
});
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.listBuckets();
const buckets = res.getBucketsList();
...
};
Shares a bucket. Returns a promis that resolves to the threadInfo (required to join a bucket).
If you don't specify the bucket
property, client.defaultBucket
value is going to be used instead.
client
.shareBucket({ bucket: 'my-bucket' })
.then((res) => {
const threadInfo = res.getThreadinfo();
console.log('key:', threadInfo.getKey());
console.log('addresses:', threadInfo.getAddressesList());
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.shareBucket({ bucket: 'my-bucket' });
const threadInfo = res.getThreadinfo();
...
};
Joins a shared bucket.
If you don't specify the bucket
property, client.defaultBucket
value is going to be used instead.
client
.joinBucket({
bucket: 'my-bucket',
threadInfo: {
key: 'my-key',
addresses: ['address1', 'address2', 'address3'],
},
})
.then((res) => {
console.log('result', res.getResult());
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.joinBucket({
bucket: 'my-bucket',
threadInfo: {
key: 'my-key',
addresses: ['address1', 'address2', 'address3'],
},
});
console.log('result', res.getResult());
...
};
Get the current public key generated by the daemon and the hub auth token.
client
.getPublicKey()
.then((res) => {
const publicKey = res.getPublickey();
const hubAuthToken = res.getHubauthtoken();
console.log('publicKey', publicKey);
console.log('hubAuthToken', hubAuthToken);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.getPublicKey();
console.log('publicKey', res.getPublickey());
console.log('hubAuthToken', res.getHubauthtoken());
...
};
Returns a ReadableStream that notifies about new notifications. Notifications are triggered upon another member's interaction with a shared file or bucket, for example if he attempts to add a new file to a shared bucket.
const notificationStream = client.notificationSubscribe();
notificationStream.on('data', (res) => {
const notification = res.getNotification();
console.log(notification);
});
Mark a notification as read.
client
.readNotifcation({ ID: '1234' })
.then(() => {
console.log('notifcation was marked as read');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.readNotification({ ID: '1234' });
console.log('notifcation was marked as read');
...
};
Returns a list of notifications objects. Notifications objects represent just share file invitations for now.
client
.getNotifications({ seek: 'some-value', limit: 20 })
.then((res) => {
const objectRes = {
nextOffset: res.getNextoffset(),
notifications: res.getNotificationsList().map((notification) => ({
id: notification.getId(),
body: notification.getBody(),
type: notification.getType(),
readAt: notification.getReadat(),
subject: notification.getSubject(),
createdAt: notification.getCreatedat(),
relatedObject: notification.getRelatedobjectCase(),
})),
};
console.log(objectRes);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.getNotifications({ seek: 'some-value', limit: 20 });
console.log(res);
...
};
This method is for accepting or rejecting an invitation to a sharing request of a file.
client
.handleFilesInvitation({ invitationID: '123-123-123', accept: true })
.then((response) => {
console.log(response);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.handleFilesInvitation({ invitationID: '123-123-123', accept: true });
...
};
Updates the timestamp which is returned by the getNotifications()
method through calling getLastseenat()
.
This timestamp can be used to track which notification has not yet been seen by the user.
client
.setNotificationsLastSeenAt({ timestamp: 1598889151456 })
.then(() => {
console.log('Updated the notifications timestamp');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.setNotificationsLastSeenAt({ timestamp: 1598889151456 });
...
};
Delete an account.
client.deleteAccount().then((res) => {
console.log('account delted');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.deleteAccount();
console.log('account delted');
};
Deletes the Key Pair
client
.deleteKeyPair()
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.deleteKeyPair();
console.log(res);
...
};
Fetches account storage usage info such as amount of space used locally and in Space, alongside bandwith quotas and limits.
client
.getUsageInfo()
.then((usageInfoRes) => {
const usageInfo = {
localstorageused: usageInfoRes.getLocalstorageused(),
localbandwidthused: usageInfoRes.getLocalbandwidthused(),
spacestorageused: usageInfoRes.getSpacestorageused(),
spacebandwidthused: usageInfoRes.getSpacebandwidthused(),
usagequota: usageInfoRes.getUsagequota(),
}
console.log(usageInfo);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const usageInfoRes = await client.getUsageInfo();
const usageInfo = {
localstorageused: usageInfoRes.getLocalstorageused(),
localbandwidthused: usageInfoRes.getLocalbandwidthused(),
spacestorageused: usageInfoRes.getSpacestorageused(),
spacebandwidthused: usageInfoRes.getSpacebandwidthused(),
usagequota: usageInfoRes.getUsagequota(),
}
console.log(usageInfo);
...
};
Get the stored mnemonic seed.
client
.getStoredMnemonic()
.then((res) => {
console.log(res.getMnemonic());
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.getMnemonic();
console.log(res.getMnemonic());
...
};
Restore key pair via mnemonic
client
.restoreKeyPairViaMnemonic({
mnemonic: 'my-mnemonic',
})
.then(() => {
console.log('restore keys');
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
await client.restoreKeyPairViaMnemonic({
mnemonic: 'my-mnemonic',
});
};
Returns the list of files shared with me
client
.getSharedWithMeFiles({
seek: "seek_value",
limit: 30,
})
.then((res) => {
const result = {
nextOffset: result.getNextoffset(),
items: result.getItemsList().map((item) => {
const entry = item.getEntry();
return {
dbId: item.getDbid(),
bucket: item.getBucket(),
path: entry.getEntrygetPath(),
isDir: entry.getIsdir(),
name: entry.getName(),
sizeInBytes: entry.getSizeinbytes(),
created: entry.getCreated(),
updated: entry.getUpdated(),
fileExtension: entry.getFileextension(),
ipfsHash: entry.getIpfshash(),
isLocallyAvailable: entry.getIslocallyavailable(),
backupCount: entry.getBackupcount(),
members: entry.getMembersList().map((member) => ({
publicKey: member.getPublickey(),
})),
};
}),
};
console.log(result);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.getSharedWithMeFiles({
seek: "seek_value",
limit: 30,
});
console.log(res.getItemsList());
...
};
Share files with other users via their public keys
client
.shareFilesViaPublicKey({
publicKeys: ['pubKey1', 'pubKey2', 'pubKey3'],
paths: [{
path: 'path1/file.jpeg',
dbId: 'db-id-1',
bucket: 'my-bucket',
}],
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.shareFilesViaPublicKey({
publicKeys: ['pubKey1', 'pubKey2', 'pubKey3'],
paths: [{
path: 'path1/file.jpeg',
dbId: 'db-id-1',
bucket: 'my-bucket',
}],
});
console.log(res);
...
};
Get the current api session tokens.
client
.getAPISessionTokens()
.then((res) => {
const hubToken = res.getHubtoken();
const servicestoken = res.getServicestoken();
console.log('hubToken', hubToken);
console.log('servicestoken', servicestoken);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.getAPISessionTokens();
console.log('hubToken', res.getHubtoken());
console.log('servicestoken', res.getServicestoken());
...
};
Returns a list of the recently members that you shared with
client
.getRecentlySharedWith()
.then((res) => {
const membersList = res.getMembersList();
const members = membersList.map((member) => ({
address: member.getAddress(),
publicKey: member.getPublickey(),
}));
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.getRecentlySharedWith();
const membersList = res.getMembersList();
...
};
Generates a sharing public link for the files specified.
If you don't specify the bucket
property, client.defaultBucket
value is going to be used instead.
client
.generatePublicFileLink({
dbId: 'db-id-string',
bucket: 'my-bucket',
password: '123asd',
itemPaths: ['path/to/file1.txt', 'path/to/file2.txt'],
})
.then((res) => {
const fileInfo = {
link: res.getLink(),
fileCid: res.getFilecid(),
};
console.log(fileInfo);
})
.catch((err) => {
console.error(err);
});
/* Or using Async/Await */
const asyncFunc = async () => {
const res = await client.generatePublicFileLink({
bucket: 'my-bucket',
password: '123asd',
itemPaths: ['path/to/file1.txt', 'path/to/file2.txt'],
});
const fileInfo = {
link: res.getLink(),
fileCid: res.getFilecid(),
};
...
};
You can check the example included in the example
folder.
To run the example you need to download and run the daemon first
Then you can run the example by
npm run example
then on your web browser go to localhost:3001
If you need more information about the available methods, you can check the Proto File Schema.
You can find more information related to the daemon here
FAQs
![Publish Action Status](https://github.com/FleekHQ/space-client/workflows/Publish/badge.svg?branch=master) ![Tests Action Status](https://github.com/FleekHQ/space-client/workflows/Tests/badge.svg)
The npm package @fleekhq/space-client receives a total of 0 weekly downloads. As such, @fleekhq/space-client popularity was classified as not popular.
We found that @fleekhq/space-client demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Polyfill.io has been serving malware for months via its CDN, after the project's open source maintainer sold the service to a company based in China.
Security News
OpenSSF is warning open source maintainers to stay vigilant against reputation farming on GitHub, where users artificially inflate their status by manipulating interactions on closed issues and PRs.
Security News
A JavaScript library maintainer is under fire after merging a controversial PR to support legacy versions of Node.js.