Skip to content

Getting Started

Installation

Download the daemon

First thing is go the latest release of the daemon and download the binary version for your Operating System:

Binary versions

Run the daemon

Once you downloaded the daemon binary, open a new terminal window and go to the path where you placed the daemon and change its access permissions by doing:

chmod 755 space_binary_file

Change permissions

Then you can run daemon as any other normal binary file:

./your_binary_file

Running daemon

If you get a warning window when you try to execute the daemon, please follow this instructions:

Click on cancel:

Warning window

Then go to your System Preferences/Security and Privacy and click Allow Anyway:

System PReferences

then try to execute the daemon again:

./your_binary_file

Running daemon

this time you will get a new warning window, click Open

New warning window

If everything goes well, you will see the daemon logs indicating that Daemon is ready

Daemon Ready

Download the client

If you are using NodeJS, you can install the Space Js client package so you can interact with the daemon using nice and simple JavaScript methods without worring about gRPC calls.

The Space Js client is built on top of grpc-web

You can install the client on your project as any normal package, using npm or yarn:

npm install @fleekhq/space-client

or

yarn add @fleekhq/space-client

Space Js client on server side

As space-client is built on top of grpc-web, if you want to use the client on server side you'll need to install XMLHttpRequest package:

yarn add xmlhttprequest

or

npm install xmlhttprequest

Setup the client

You can import the client as any normal package.

Please have in mind that space daemon is a service that runs on users desktops, 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).

  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`,
  });

  ...

CRUD Operations

Create client instance

class SpaceClient(opts)

Use this class to create Space Js 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);

Create bucket

.createBucket({ slug: string })

Creates a new bucket. Returns a Promise that resolves to the new bucket instance

  client
    .createBucket({ slug: '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({ slug: 'my-bucket'});
    const bucket = res.getBucket();

    console.log(bucket.getName());
    ...
  };

List buckets

[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();

    ...
  };

Upload files/folders

.addItems({ bucket?: string, targetPath: string, sourcePaths: string[] })

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: '/', // path in the bucket to be saved
    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');
  });

Create folders

.createFolder({ path: string, bucket?: string })

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' });
  };

List a directory

.listDirectory({ path: string, bucket?: string })

Returns a promise that resolves to list of Entry instances representing each folder and files present 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());
      });
    })
    .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) => {
      ...
    });
  };

List all the bucket directories/files

.listDirectories({ bucket?: string })

Returns a Promise that resolves to list of Entry 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());
      });
    })
    .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) => {
      ...
    });
  };

Open a file

.openFile({ path: string, bucket?: string })

Copies the file referenced by the path arg to a temp folder on your machine 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"
};

Subscribe to txl events

.txlSubscribe()

Returns a ReadableStream that notifies when something changed on the bucket (data stream returns the Bucket name). NOTE: currently the payload will always be the bucket and then you would have to use the other functions to find the data that change, however we have an open issue to track this so we can return more granular information in the event payload.

  const txlStream = client.txlSubscribe();

  txlStream.on('data', (res) => {
    const bucket = res.getBucket();
    console.log(bucket);
  });

Subscribe to buckets events

.subscribe()

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());
  });

Identity

Create username and email

.createUsernameAndEmail({ username: string, email?: string })

Create a new username with/out email. Returns a Promise that resolves to the username

  client
    .createUsernameAndEmail({ username: 'myusername' })
    .then(() => {
      console.log('username created');
    })
    .catch((err) => {
      console.error(err);
    });

  /* Or using Async/Await */

  const asyncFunc = async () => {
    await client.createUsernameAndEmail({ username: 'myusername', email: '[email protected]' });
  };

Get identity by username

.getIdentityByUsername({ username: string, email?: string })

Get an indentity based on a username. Returns a Promise that resolves if a username already exists

  client
    .getIdentityByUsername({ username: 'myusername' })
    .then((res) => {
      console.log(res.getIdentity());
    })
    .catch(() => {
      console.log('Username doesnt exists.');
    });

  /* Or using Async/Await */

  const asyncFunc = async () => {
    const res = await client.getIdentityByUsername({ username: 'myusername' });

    console.log(res.getIdentity());
  };

Sharing

Share a bucket

.shareBucket({ bucket?: string })

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();
    ...
  };

Join a shared bucket

joinBucket({ bucket?: string, threadInfo: { key: string, addresses: [string] } })

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());
    ...
  };

Share a bucket via email

[WIP] .shareBucketViaEmail({ bucket?: string, email: string })

this method is still not supported by space-daemon

Shares a bucket via email. If you don't specify the bucket property, client.defaultBucket value is going to be used instead.

  client
    .shareBucketViaEmail({ bucket: 'my-bucket-slug', email: '[email protected]' })
    .then((res) => {
      console.log(res);
    })
    .catch((err) => {
      console.error(err);
    });

  /* Or using Asyn/Await */

  const asyncFunc = async () => {
    const res = await client.shareBucketViaEmail({
      bucket: 'my-bucket-slug',
      email: '[email protected]',
    });

    console.log(res);
  };

Share a bucket via identity

.shareBucketViaIdentity({ identityType: 'USERNAME' | 'EMAIL', identityValue: string, bucket?: string })

Shares a bucket via identity. If you don't specify the bucket property, client.defaultBucket value is going to be used instead.

  client
    .shareBucketViaIdentity({
      bucket: 'my-bucket-slug',
      identityType: 'USERNAME',
      identityValue: 'user123',
    })
    .then((res) => {
      console.log(res);
    })
    .catch((err) => {
      console.error(err);
    });

  /* Or using Async/Await */

  const asyncFunc = async () => {
    const res = await client.shareBucketViaIdentity({
      bucket: 'my-bucket-slug',
      identityType: 'USERNAME',
      identityValue: 'user123',
    });

    console.log(res);
  };

[WIP] .generateFileShareLink({ bucket?: string, filePath: string })

this method is still not supported by space-daemon

Generates a share link. If you don't specify the bucket property, client.defaultBucket value is going to be used instead.

  client
    .generateFileShareLink({
      bucket: 'my-bucket-slug',
      filePath: 'path/to/file.js',
    })
    .then((res) => {
      console.log(res.getLink());
    })
    .catch((err) => {
      console.error(err);
    });

  /* Or using Async/Await */

  const asyncFunc = async () => {
    const res = await client.generateFileShareLink({
      bucket: 'my-bucket-slug',
      filePath: 'path/to/file.js',
    });

    console.log(res.getLink());
  };

Backup

Backup keys by passphrase

[WIP] .backupKeysByPassphrase({ passphrase: string })

this method is still not supported by space-daemon

Backup keys by passphrase

  client
    .backupKeysByPassphrase({
      passphrase: 'my-passphrase',
    })
    .then(() => {
      console.log('keys backup');
    })
    .catch((err) => {
      console.error(err);
    });

  /* Or using Async/Await */

  const asyncFunc = async () => {
    await client.backupKeysByPassphrase({
      passphrase: 'my-passphrase',
    });
  };

Recovery keys by passphrase

[WIP] .recoverKeysByPassphrase({ passphrase: string })

this method is still not supported by space-daemon

Recovery keys by passphrase

  client
    .recoverKeysByPassphrase({
      passphrase: 'my-passphrase',
    })
    .then(() => {
      console.log('recovery keys');
    })
    .catch((err) => {
      console.error(err);
    });

  /* Or using Async/Await */

  const asyncFunc = async () => {
    await client.recoverKeysByPassphrase({
      passphrase: 'my-passphrase',
    });
  };

Mount

Toggle fuse drive

[WIP] .toggleFuseDrive({ mountDrive: boolean })

this method is still not supported by space-daemon

Mounts the fuse drive on your machine

  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());
  };

Get fuse drive status

[WIP] .getFuseDriveStatus({})

this method is still not supported by space-daemon

Get the current 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());
  };