Skip to content
This repository has been archived by the owner on Apr 16, 2021. It is now read-only.

Add CI and unit tests #29

Merged
merged 20 commits into from
Jul 8, 2020
12 changes: 12 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"env": {
"es6": true,
"jest": true,
"node": true
},
"extends": "eslint:recommended"
}
12 changes: 6 additions & 6 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
time: '10:00'
open-pull-requests-limit: 10
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
time: "10:00"
open-pull-requests-limit: 10
20 changes: 0 additions & 20 deletions .github/workflows/build.yml

This file was deleted.

25 changes: 25 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Pull Request

# Run on PRs.
on: [pull_request]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [10.x, 12.x, 14.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: yarn
- name: Prettier
run: yarn prettier --check .
- name: Lint
run: yarn eslint .
- run: yarn test
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
package-lock.json
package-lock.json
.DS_Store
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# Skynet SDK
# Skynet NodeJS SDK
mrcnski marked this conversation as resolved.
Show resolved Hide resolved

An SDK for integrating Skynet into Node.js applications
An SDK for integrating Skynet into Node.js applications.

## Installing

Using `npm`:

```sh
npm install @nebulous/skynet
mrcnski marked this conversation as resolved.
Show resolved Hide resolved
```

Using `yarn`:

```sh
yarn add @nebulous/skynet
```

## Documentation

For documentation complete with examples, please see [the Skynet SDK docs](https://nebulouslabs.github.io/skynet-docs/?javascript#introduction).
16 changes: 0 additions & 16 deletions config.js

This file was deleted.

17 changes: 9 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"use strict";

const { DefaultUploadOptions, DefaultDownloadOptions } = require("./config");
const { UploadFile, UploadDirectory } = require("./src/upload");
const { DownloadFile } = require("./src/download");
const { defaultUploadOptions, uploadFile, uploadDirectory } = require("./src/upload");
const { defaultDownloadOptions, downloadFile } = require("./src/download");
const { uriSkynetPrefix } = require("./src/utils");

module.exports = {
DefaultUploadOptions: DefaultUploadOptions,
DefaultDownloadOptions: DefaultDownloadOptions,
UploadFile: UploadFile,
UploadDirectory: UploadDirectory,
DownloadFile: DownloadFile,
defaultDownloadOptions,
defaultUploadOptions,
downloadFile,
uploadDirectory,
uploadFile,
uriSkynetPrefix,
};
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
"name": "@nebulous/skynet",
"version": "1.0.1",
"description": "Skynet SDK",
"repository": "https://github.com/NebulousLabs/nodejs-skynet",
"main": "index.js",
"scripts": {
"test": "jest",
"format": "prettier --write ."
},
"husky": {
Expand Down Expand Up @@ -31,13 +33,15 @@
],
"license": "MIT",
"dependencies": {
"axios": "^0.19.2",
"form-data": "^3.0.0",
"fs": "0.0.1-security"
"axios": "0.19.2",
"form-data": "3.0.0"
},
"devDependencies": {
"eslint": "^7.2.0",
"jest": "^26.0.1",
"husky": "^4.2.3",
"lint-staged": "^10.0.8",
"prettier": "^2.0.2"
"prettier": "^2.0.5",
"tmp": "0.2.1"
}
}
10 changes: 8 additions & 2 deletions src/download.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ const fs = require("fs");

const { trimTrailingSlash, trimSiaPrefix } = require("./utils");

function DownloadFile(path, skylink, opts) {
const defaultDownloadOptions = {
portalUrl: "https://siasky.net",
};

function downloadFile(path, skylink, customOptions = {}) {
const opts = { ...defaultDownloadOptions, ...customOptions };

const url = `${trimTrailingSlash(opts.portalUrl)}/${trimSiaPrefix(skylink)}`;

const writer = fs.createWriteStream(path);
Expand All @@ -24,4 +30,4 @@ function DownloadFile(path, skylink, opts) {
});
}

module.exports = { DownloadFile };
module.exports = { defaultDownloadOptions, downloadFile };
33 changes: 33 additions & 0 deletions src/download.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const axios = require("axios");
const tmp = require("tmp");

const { downloadFile } = require("./download");

jest.mock("axios");

const portalUrl = "https://siasky.net";
const skylink = "XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg";

describe("download", () => {
const body = "asdf";

axios.get.mockResolvedValue({ data: { body, pipe: function () {} } });
mrcnski marked this conversation as resolved.
Show resolved Hide resolved

it("should send get request to default portal", () => {
const tmpFile = tmp.fileSync();
downloadFile(tmpFile.name, skylink);

expect(axios.get).toHaveBeenCalledWith(`${portalUrl}/${skylink}`, { responseType: "stream" });
tmpFile.removeCallback();
});

it("should use custom options if defined", () => {
const tmpFile = tmp.fileSync();
downloadFile(tmpFile.name, skylink, {
portalUrl: "localhost",
});

expect(axios.get).toHaveBeenCalledWith(`localhost/${skylink}`, { responseType: "stream" });
tmpFile.removeCallback();
});
});
32 changes: 23 additions & 9 deletions src/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,42 @@ const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");

const { walkDirectory, trimTrailingSlash } = require("./utils");
const { walkDirectory, uriSkynetPrefix, trimTrailingSlash } = require("./utils");

function UploadFile(path, opts) {
const options = opts.customFilename ? { filename: opts.customFilename } : {};
const defaultUploadOptions = {
portalUrl: "https://siasky.net",
portalUploadPath: "/skynet/skyfile",
portalFileFieldname: "file",
portalDirectoryFileFieldname: "files[]",
customFilename: "",
};

function uploadFile(path, customOptions = {}) {
const opts = { ...defaultUploadOptions, ...customOptions };

const formData = new FormData();
const options = opts.customFilename ? { filename: opts.customFilename } : {};
formData.append(opts.portalFileFieldname, fs.createReadStream(path), options);

// Form the URL.
const url = `${trimTrailingSlash(opts.portalUrl)}${trimTrailingSlash(opts.portalUploadPath)}`;

return new Promise((resolve, reject) => {
axios
.post(url, formData, { headers: formData.getHeaders() })
.then((resp) => {
resolve(`sia://${resp.data.skylink}`);
.then((response) => {
resolve(`${uriSkynetPrefix}${response.data.skylink}`);
kwypchlo marked this conversation as resolved.
Show resolved Hide resolved
})
.catch((error) => {
reject(error);
});
});
}

function UploadDirectory(path, opts) {
function uploadDirectory(path, customOptions = {}) {
const opts = { ...defaultUploadOptions, ...customOptions };

// Check if there is a directory at given path.
const stat = fs.statSync(path);
if (!stat.isDirectory()) {
throw new Error(`Given path is not a directory: ${path}`);
Expand All @@ -37,20 +50,21 @@ function UploadDirectory(path, opts) {
formData.append(opts.portalDirectoryFileFieldname, fs.createReadStream(file), { filepath: file });
}

// Form the URL.
const url = `${trimTrailingSlash(opts.portalUrl)}${trimTrailingSlash(opts.portalUploadPath)}?filename=${
opts.customFilename || path
}`;

return new Promise((resolve, reject) => {
axios
.post(url, formData, { headers: formData.getHeaders() })
.then((resp) => {
resolve(`sia://${resp.data.skylink}`);
.then((response) => {
resolve(`${uriSkynetPrefix}${response.data.skylink}`);
})
.catch((error) => {
reject(error);
});
});
}

module.exports = { UploadFile, UploadDirectory };
module.exports = { defaultUploadOptions, uploadFile, uploadDirectory };
Loading