Comparing version 0.0.8 to 0.1.0
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.download = download; | ||
var _client = require("./client.js"); | ||
var _utils = require("./utils.js"); | ||
function download(portalUrl, skylink) { | ||
const url = (0, _utils.getUrl)(portalUrl, (0, _utils.parseSkylink)(skylink), { | ||
/* eslint-disable no-unused-vars */ | ||
const defaultDownloadOptions = { ...(0, _utils.defaultOptions)("/") | ||
}; | ||
_client.SkynetClient.prototype.download = function (skylink, customOptions = {}) { | ||
const opts = { ...defaultDownloadOptions, | ||
...customOptions, | ||
download: true | ||
}); | ||
}; | ||
const url = this.getDownloadUrl(skylink, opts); | ||
window.open(url, "_blank"); | ||
} | ||
}; | ||
_client.SkynetClient.prototype.getDownloadUrl = function (skylink, customOptions = {}) { | ||
const opts = { ...defaultDownloadOptions, | ||
...customOptions | ||
}; | ||
const query = opts.download ? { | ||
attachment: true | ||
} : {}; | ||
return (0, _utils.makeUrlWithSkylink)(this.portalUrl, opts.endpointPath, skylink, query); | ||
}; | ||
_client.SkynetClient.prototype.metadata = function (skylink, customOptions = {}) { | ||
const opts = { ...defaultDownloadOptions, | ||
...customOptions | ||
}; | ||
throw new Error("Unimplemented"); | ||
}; | ||
_client.SkynetClient.prototype.open = function (skylink, customOptions = {}) { | ||
const opts = { ...defaultDownloadOptions, | ||
...customOptions | ||
}; | ||
const url = (0, _utils.makeUrlWithSkylink)(this.portalUrl, opts.endpointPath, skylink); | ||
window.open(url, "_blank"); | ||
}; |
@@ -6,31 +6,30 @@ "use strict"; | ||
}); | ||
exports.default = SkynetClient; | ||
Object.defineProperty(exports, "upload", { | ||
Object.defineProperty(exports, "SkynetClient", { | ||
enumerable: true, | ||
get: function () { | ||
return _upload.upload; | ||
return _client.SkynetClient; | ||
} | ||
}); | ||
Object.defineProperty(exports, "uploadDirectory", { | ||
Object.defineProperty(exports, "defaultPortalUrl", { | ||
enumerable: true, | ||
get: function () { | ||
return _upload.uploadDirectory; | ||
return _utils.defaultPortalUrl; | ||
} | ||
}); | ||
Object.defineProperty(exports, "download", { | ||
Object.defineProperty(exports, "defaultSkynetPortalUrl", { | ||
enumerable: true, | ||
get: function () { | ||
return _download.download; | ||
return _utils.defaultSkynetPortalUrl; | ||
} | ||
}); | ||
Object.defineProperty(exports, "open", { | ||
Object.defineProperty(exports, "getRelativeFilePath", { | ||
enumerable: true, | ||
get: function () { | ||
return _utils.open; | ||
return _utils.getRelativeFilePath; | ||
} | ||
}); | ||
Object.defineProperty(exports, "getUrl", { | ||
Object.defineProperty(exports, "getRootDirectory", { | ||
enumerable: true, | ||
get: function () { | ||
return _utils.getUrl; | ||
return _utils.getRootDirectory; | ||
} | ||
@@ -45,15 +44,8 @@ }); | ||
var _upload = require("./upload.js"); | ||
var _client = require("./client.js"); | ||
var _download = require("./download.js"); | ||
require("./download.js"); | ||
var _utils = require("./utils.js"); | ||
require("./upload.js"); | ||
function SkynetClient(portalUrl) { | ||
this.upload = _upload.upload.bind(null, portalUrl); | ||
this.uploadDirectory = _upload.uploadDirectory.bind(null, portalUrl); | ||
this.download = _download.download.bind(null, portalUrl); | ||
this.open = _utils.open.bind(null, portalUrl); | ||
this.getUrl = _utils.getUrl.bind(null, portalUrl); | ||
this.parseSkylink = _utils.parseSkylink; | ||
} | ||
var _utils = require("./utils.js"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.upload = upload; | ||
exports.uploadDirectory = uploadDirectory; | ||
var _axios = _interopRequireDefault(require("axios")); | ||
var _urlParse = _interopRequireDefault(require("url-parse")); | ||
var _client = require("./client.js"); | ||
var _utils = require("./utils.js"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
async function upload(portalUrl, file, options = {}) { | ||
const defaultUploadOptions = { ...(0, _utils.defaultOptions)("/skynet/skyfile"), | ||
portalFileFieldname: "file", | ||
portalDirectoryFileFieldname: "files[]" // TODO: | ||
// customFilename: "", | ||
}; | ||
_client.SkynetClient.prototype.upload = async function (file, customOptions = {}) { | ||
const opts = { ...defaultUploadOptions, | ||
...customOptions | ||
}; | ||
const formData = new FormData(); | ||
formData.append("file", ensureFileObjectConsistency(file)); | ||
const parsed = (0, _urlParse.default)(portalUrl); | ||
parsed.set("pathname", "/skynet/skyfile"); | ||
formData.append(opts.portalFileFieldname, ensureFileObjectConsistency(file)); | ||
const url = (0, _utils.makeUrl)(this.portalUrl, opts.endpointPath); | ||
const { | ||
data | ||
} = await _axios.default.post(parsed.toString(), formData, options.onUploadProgress && { | ||
} = await _axios.default.post(url, formData, opts.onUploadProgress && { | ||
onUploadProgress: ({ | ||
@@ -28,3 +33,3 @@ loaded, | ||
const progress = loaded / total; | ||
options.onUploadProgress(progress, { | ||
opts.onUploadProgress(progress, { | ||
loaded, | ||
@@ -36,12 +41,22 @@ total | ||
return data; | ||
} | ||
}; | ||
/** | ||
* Uploads a local directory to Skynet. | ||
* @param {Object} directory - File objects to upload, indexed by their path strings. | ||
* @param {string} filename - The name of the directory. | ||
* @param {Object} [customOptions={}] - Additional settings that can optionally be set. | ||
* @param {string} [customOptions.endpointPath="/skynet/skyfile"] - The relative URL path of the portal endpoint to contact. | ||
* @param {string} [customOptions.portalDirectoryfilefieldname="files[]"] - The fieldName for directory files on the portal. | ||
*/ | ||
async function uploadDirectory(portalUrl, directory, filename, options = {}) { | ||
_client.SkynetClient.prototype.uploadDirectory = async function (directory, filename, customOptions = {}) { | ||
const opts = { ...defaultUploadOptions, | ||
...customOptions | ||
}; | ||
const formData = new FormData(); | ||
Object.entries(directory).forEach(([path, file]) => { | ||
formData.append("files[]", ensureFileObjectConsistency(file), path); | ||
formData.append(opts.portalDirectoryFileFieldname, ensureFileObjectConsistency(file), path); | ||
}); | ||
const parsed = (0, _urlParse.default)(portalUrl); | ||
parsed.set("pathname", "/skynet/skyfile"); | ||
parsed.set("query", { | ||
const url = (0, _utils.makeUrl)(this.portalUrl, opts.endpointPath, { | ||
filename | ||
@@ -51,3 +66,3 @@ }); | ||
data | ||
} = await _axios.default.post(parsed.toString(), formData, options.onUploadProgress && { | ||
} = await _axios.default.post(url, formData, opts.onUploadProgress && { | ||
onUploadProgress: ({ | ||
@@ -58,3 +73,3 @@ loaded, | ||
const progress = loaded / total; | ||
options.onUploadProgress(progress, { | ||
opts.onUploadProgress(progress, { | ||
loaded, | ||
@@ -66,8 +81,9 @@ total | ||
return data; | ||
} | ||
}; | ||
/** | ||
* Sometimes file object might have had the type property defined manually with Object.defineProperty | ||
* and some browsers (namely firefox) can have problems reading it after the file has been appended | ||
* to form data. To overcome this, we recreate the file object using native File constructor with | ||
* a type defined as a constructor argument. | ||
* Sometimes file object might have had the type property defined manually with | ||
* Object.defineProperty and some browsers (namely firefox) can have problems | ||
* reading it after the file has been appended to form data. To overcome this, | ||
* we recreate the file object using native File constructor with a type defined | ||
* as a constructor argument. | ||
* Related issue: https://github.com/NebulousLabs/skynet-webportal/issues/290 | ||
@@ -74,0 +90,0 @@ */ |
@@ -6,6 +6,13 @@ "use strict"; | ||
}); | ||
exports.open = open; | ||
exports.getUrl = getUrl; | ||
exports.defaultPortalUrl = defaultPortalUrl; | ||
exports.defaultOptions = defaultOptions; | ||
exports.getRelativeFilePath = getRelativeFilePath; | ||
exports.getRootDirectory = getRootDirectory; | ||
exports.makeUrl = makeUrl; | ||
exports.makeUrlWithSkylink = makeUrlWithSkylink; | ||
exports.parseSkylink = parseSkylink; | ||
exports.defaultSkynetPortalUrl = void 0; | ||
var _pathBrowserify = _interopRequireDefault(require("path-browserify")); | ||
var _urlParse = _interopRequireDefault(require("url-parse")); | ||
@@ -15,20 +22,77 @@ | ||
function open(portalUrl, skylink) { | ||
const url = getUrl(portalUrl, parseSkylink(skylink)); | ||
window.open(url, "_blank"); | ||
// import axios from "axios"; | ||
const defaultSkynetPortalUrl = "https://siasky.net"; | ||
exports.defaultSkynetPortalUrl = defaultSkynetPortalUrl; | ||
function defaultPortalUrl() { | ||
var url = new URL(window.location.href); | ||
return url.href.substring(0, url.href.indexOf(url.pathname)); | ||
} | ||
function getUrl(portalUrl, skylink, options = {}) { | ||
const parsed = (0, _urlParse.default)(portalUrl); | ||
parsed.set("pathname", parseSkylink(skylink)); | ||
function defaultOptions(endpointPath) { | ||
return { | ||
endpointPath: endpointPath // TODO: | ||
// APIKey: "", | ||
// customUserAgent: "", | ||
if (options.download) { | ||
parsed.set("query", { | ||
attachment: true | ||
}); | ||
} | ||
}; | ||
} // TODO: Use this to simplify creating requests. Needs to be tested. | ||
// export function executeRequest(portalUrl, method, opts, query, data = {}) { | ||
// const url = makeUrl(portalUrl, opts.endpointPath, query); | ||
// return axios({ | ||
// method: method, | ||
// url: url, | ||
// data: data, | ||
// auth: opts.APIKey && {username: "", password: opts.APIKey }, | ||
// onUploadProgress: opts.onUploadProgress && { | ||
// onUploadProgress: ({ loaded, total }) => { | ||
// const progress = loaded / total; | ||
// opts.onUploadProgress(progress, { loaded, total }); | ||
// }, | ||
// } | ||
// }); | ||
// } | ||
function getFilePath(file) { | ||
return file.webkitRelativePath || file.path || file.name; | ||
} | ||
function getRelativeFilePath(file) { | ||
const filePath = getFilePath(file); | ||
const { | ||
root, | ||
dir, | ||
base | ||
} = _pathBrowserify.default.parse(filePath); | ||
const relative = _pathBrowserify.default.normalize(dir).slice(root.length).split(_pathBrowserify.default.sep).slice(1); | ||
return _pathBrowserify.default.join(...relative, base); | ||
} | ||
function getRootDirectory(file) { | ||
const filePath = getFilePath(file); | ||
const { | ||
root, | ||
dir | ||
} = _pathBrowserify.default.parse(filePath); | ||
return _pathBrowserify.default.normalize(dir).slice(root.length).split(_pathBrowserify.default.sep)[0]; | ||
} | ||
function makeUrl(portalUrl, pathname, query = {}) { | ||
const parsed = (0, _urlParse.default)(portalUrl); | ||
parsed.set("pathname", pathname); | ||
parsed.set("query", query); | ||
return parsed.toString(); | ||
} | ||
function makeUrlWithSkylink(portalUrl, endpointPath, skylink, query = {}) { | ||
const parsedSkylink = parseSkylink(skylink); | ||
return makeUrl(portalUrl, _pathBrowserify.default.posix.join(endpointPath, parsedSkylink), query); | ||
} | ||
const SKYLINK_MATCHER = "([a-zA-Z0-9_-]{46})"; | ||
@@ -35,0 +99,0 @@ const SKYLINK_DIRECT_REGEX = new RegExp(`^${SKYLINK_MATCHER}$`); |
{ | ||
"name": "skynet-js", | ||
"version": "0.0.8", | ||
"version": "0.1.0", | ||
"description": "Sia Skynet Javascript Client", | ||
@@ -44,2 +44,3 @@ "main": "dist/index.js", | ||
"axios": "^0.19.2", | ||
"path-browserify": "^1.0.1", | ||
"url-parse": "^1.4.7" | ||
@@ -46,0 +47,0 @@ }, |
147
README.md
@@ -25,16 +25,26 @@ # skynet-js - Javascript Sia Skynet Client | ||
## Docs: using standalone function | ||
## Docs | ||
### async upload(portalUrl, file, [options]) | ||
### Using SkynetClient | ||
Client implements all the standalone functions as methods with bound `portalUrl` so you don't need to repeat it every time. | ||
`portalUrl` (string) - Optional portal url. If not specified, will try to use the current portal that the sky app is running inside of. | ||
```javascript | ||
import { upload } from "skynet-js"; | ||
import { SkynetClient } from "skynet-js"; | ||
const client = new SkynetClient("https://siasky.net"); | ||
``` | ||
Use the `portalUrl` to upload `file` contents. | ||
Calling `SkynetClient` without parameters will use the URL of the current portal that is running the skapp (sky app). | ||
`portalUrl` (string) - The string portal url. | ||
### async upload(file, [options]) | ||
Use the client to upload `file` contents. | ||
`file` (File) - The file to upload. | ||
`options.APIKey` (string) - Optional API key password for authentication. | ||
`options.onUploadProgress` (function) - Optional callback to track progress. | ||
@@ -45,2 +55,4 @@ | ||
```javascript | ||
import { SkynetClient } from "skynet-js"; | ||
const onUploadProgress = (progress, { loaded, total }) => { | ||
@@ -50,18 +62,30 @@ console.info(`Progress ${Math.round(progress * 100)}%`); | ||
try { | ||
const { skylink } = await upload(portalUrl, file, { onUploadProgress }); | ||
} catch (error) { | ||
// handle error | ||
async function uploadExample() { | ||
try { | ||
const client = new SkynetClient(); | ||
const { skylink } = await client.upload(file, { onUploadProgress }); | ||
} catch (error) { | ||
console.log(error); | ||
} | ||
} | ||
``` | ||
### async uploadDirectory(portalUrl, directory, filename, [options]) | ||
With authentication: | ||
```javascript | ||
import { uploadDirectory } from "skynet-js"; | ||
import { SkynetClient } from "skynet-js"; | ||
async function authenticationExample() { | ||
try { | ||
const client = new SkynetClient("https://my-portal.net"); | ||
const { skylink } = await client.upload(file, { APIKey: "foobar" }); | ||
} catch (error) { | ||
console.log(error); | ||
} | ||
} | ||
``` | ||
Use the `portalUrl` to upload `directory` contents as a `filename`. | ||
### async uploadDirectory(directory, filename, [options]) | ||
`portalUrl` (string) - The string portal url. | ||
Use the client to upload `directory` contents as a `filename`. | ||
@@ -79,49 +103,46 @@ `directory` (Object) - Directory map `{ "file1.jpeg": <File>, "subdirectory/file2.jpeg": <File> }` | ||
```javascript | ||
import path from "path-browserify"; | ||
import { getRelativeFilePath, getRootDirectory, SkynetClient } from "skynet-js"; | ||
const getFilePath = (file) => file.webkitRelativePath || file.path || file.name; | ||
// Assume we have a list of files from an input form. | ||
const getRelativeFilePath = (file) => { | ||
const filePath = getFilePath(file); | ||
const { root, dir, base } = path.parse(filePath); | ||
const relative = path.normalize(dir).slice(root.length).split(path.sep).slice(1); | ||
async function uploadDirectoryExample() { | ||
try { | ||
// Get the directory name from the list of files. | ||
// Can also be named manually, i.e. if you build the files yourself | ||
// instead of getting them from an input form. | ||
const filename = getRootDirectory(files[0]); | ||
return path.join(...relative, base); | ||
}; | ||
// Use reduce to build the map of files indexed by filepaths | ||
// (relative from the directory). | ||
const directory = files.reduce((accumulator, file) => { | ||
const path = getRelativeFilePath(file); | ||
const getRootDirectory = (file) => { | ||
const filePath = getFilePath(file); | ||
const { root, dir } = path.parse(filePath); | ||
return { ...accumulator, [path]: file }; | ||
}, {}); | ||
return path.normalize(dir).slice(root.length).split(path.sep)[0]; | ||
}; | ||
const client = new SkynetClient(); | ||
const { skylink } = await client.uploadDirectory(directory, filename); | ||
} catch (error) { | ||
console.log(error); | ||
} | ||
} | ||
``` | ||
const onUploadProgress = (progress, { loaded, total }) => { | ||
console.info(`Progress ${Math.round(progress * 100)}%`); | ||
}; | ||
### download(skylink) | ||
try { | ||
const filename = getRootDirectory(files[0]); | ||
const directory = files.reduce((acc, file) => { | ||
const path = getRelativeFilePath(file); | ||
```javascript | ||
import { SkynetClient } from "skynet-js"; | ||
return { ...acc, [path]: file }; | ||
}, {}); | ||
// Assume we have a skylink e.g. from a previous upload. | ||
const { skylink } = await uploadDirectory(portalUrl, directory, filename, { onUploadProgress }); | ||
try { | ||
const client = new SkynetClient(); | ||
client.download(skylink); | ||
} catch (error) { | ||
// handle error | ||
console.log(error); | ||
} | ||
``` | ||
### download(portalUrl, skylink) | ||
Use the client to download `skylink` contents. | ||
```javascript | ||
import { download } from "skynet-js"; | ||
``` | ||
Use the `portalUrl` to download `skylink` contents. | ||
`portalUrl` (string) - The string portal url. | ||
`skylink` (string) - 46 character skylink. | ||
@@ -131,12 +152,10 @@ | ||
### open(portalUrl, skylink) | ||
### open(skylink) | ||
```javascript | ||
import { open } from "skynet-js"; | ||
import { SkynetClient } from "skynet-js"; | ||
``` | ||
Use the `portalUrl` to open `skylink` in a new browser tab. Browsers support opening natively only limited file extensions like .html or .jpg and will fallback to downloading the file. | ||
Use the client to open `skylink` in a new browser tab. Browsers support opening natively only limited file extensions like .html or .jpg and will fallback to downloading the file. | ||
`portalUrl` (string) - The string portal url. | ||
`skylink` (string) - 46 character skylink. | ||
@@ -146,12 +165,10 @@ | ||
### getUrl(portalUrl, skylink, [options]) | ||
### getDownloadUrl(skylink, [options]) | ||
```javascript | ||
import { getUrl } from "skynet-js"; | ||
import { SkynetClient } from "skynet-js"; | ||
``` | ||
Use the `portalUrl` to generate direct `skylink` url. | ||
Use the client to generate direct `skylink` url. | ||
`portalUrl` (string) - The string portal url. | ||
`skylink` (string) - 46 character skylink. | ||
@@ -171,6 +188,6 @@ | ||
- direct skylink string, example "XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg" | ||
- sia: prefixed string, example "sia:XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg" | ||
- sia:// prefixed string, example "sia://XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg" | ||
- skylink from url, example "https://siasky.net/XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg" | ||
- direct skylink string, for example `"XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg"` | ||
- `sia:` prefixed string, for example `"sia:XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg"` | ||
- `sia://` prefixed string, for example `"sia://XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg"` | ||
- skylink from url, for example `"https://siasky.net/XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg"` | ||
@@ -180,11 +197,1 @@ `skylink` (string) - String containing 46 character skylink. | ||
Returns extracted skylink string or throws error. | ||
## Docs: using SkynetClient | ||
```javascript | ||
import SkynetClient from "skynet-js"; | ||
const client = new SkynetClient("https://siasky.net"); | ||
``` | ||
Client implements all the standalone functions as methods with bound `portalUrl` so you don't need to repeat it every time. |
@@ -1,7 +0,35 @@ | ||
import { getUrl, parseSkylink } from "./utils.js"; | ||
/* eslint-disable no-unused-vars */ | ||
export function download(portalUrl, skylink) { | ||
const url = getUrl(portalUrl, parseSkylink(skylink), { download: true }); | ||
import { SkynetClient } from "./client.js"; | ||
import { makeUrlWithSkylink, defaultOptions } from "./utils.js"; | ||
const defaultDownloadOptions = { | ||
...defaultOptions("/"), | ||
}; | ||
SkynetClient.prototype.download = function (skylink, customOptions = {}) { | ||
const opts = { ...defaultDownloadOptions, ...customOptions, download: true }; | ||
const url = this.getDownloadUrl(skylink, opts); | ||
window.open(url, "_blank"); | ||
} | ||
}; | ||
SkynetClient.prototype.getDownloadUrl = function (skylink, customOptions = {}) { | ||
const opts = { ...defaultDownloadOptions, ...customOptions }; | ||
const query = opts.download ? { attachment: true } : {}; | ||
return makeUrlWithSkylink(this.portalUrl, opts.endpointPath, skylink, query); | ||
}; | ||
SkynetClient.prototype.metadata = function (skylink, customOptions = {}) { | ||
const opts = { ...defaultDownloadOptions, ...customOptions }; | ||
throw new Error("Unimplemented"); | ||
}; | ||
SkynetClient.prototype.open = function (skylink, customOptions = {}) { | ||
const opts = { ...defaultDownloadOptions, ...customOptions }; | ||
const url = makeUrlWithSkylink(this.portalUrl, opts.endpointPath, skylink); | ||
window.open(url, "_blank"); | ||
}; |
@@ -1,16 +0,13 @@ | ||
export { upload, uploadDirectory } from "./upload.js"; | ||
export { download } from "./download.js"; | ||
export { open, getUrl, parseSkylink } from "./utils.js"; | ||
export { SkynetClient } from "./client.js"; | ||
import { upload, uploadDirectory } from "./upload.js"; | ||
import { download } from "./download.js"; | ||
import { open, getUrl, parseSkylink } from "./utils.js"; | ||
// Get the following files to run or the client's methods won't be defined. | ||
export {} from "./download.js"; | ||
export {} from "./upload.js"; | ||
export default function SkynetClient(portalUrl) { | ||
this.upload = upload.bind(null, portalUrl); | ||
this.uploadDirectory = uploadDirectory.bind(null, portalUrl); | ||
this.download = download.bind(null, portalUrl); | ||
this.open = open.bind(null, portalUrl); | ||
this.getUrl = getUrl.bind(null, portalUrl); | ||
this.parseSkylink = parseSkylink; | ||
} | ||
export { | ||
defaultPortalUrl, | ||
defaultSkynetPortalUrl, | ||
getRelativeFilePath, | ||
getRootDirectory, | ||
parseSkylink, | ||
} from "./utils.js"; |
import axios from "axios"; | ||
import parse from "url-parse"; | ||
export async function upload(portalUrl, file, options = {}) { | ||
const formData = new FormData(); | ||
import { SkynetClient } from "./client.js"; | ||
import { defaultOptions, makeUrl } from "./utils.js"; | ||
formData.append("file", ensureFileObjectConsistency(file)); | ||
const defaultUploadOptions = { | ||
...defaultOptions("/skynet/skyfile"), | ||
portalFileFieldname: "file", | ||
portalDirectoryFileFieldname: "files[]", | ||
// TODO: | ||
// customFilename: "", | ||
}; | ||
const parsed = parse(portalUrl); | ||
SkynetClient.prototype.upload = async function (file, customOptions = {}) { | ||
const opts = { ...defaultUploadOptions, ...customOptions }; | ||
parsed.set("pathname", "/skynet/skyfile"); | ||
const formData = new FormData(); | ||
formData.append(opts.portalFileFieldname, ensureFileObjectConsistency(file)); | ||
const url = makeUrl(this.portalUrl, opts.endpointPath); | ||
const { data } = await axios.post( | ||
parsed.toString(), | ||
url, | ||
formData, | ||
options.onUploadProgress && { | ||
opts.onUploadProgress && { | ||
onUploadProgress: ({ loaded, total }) => { | ||
const progress = loaded / total; | ||
options.onUploadProgress(progress, { loaded, total }); | ||
opts.onUploadProgress(progress, { loaded, total }); | ||
}, | ||
@@ -26,24 +35,30 @@ } | ||
return data; | ||
} | ||
}; | ||
export async function uploadDirectory(portalUrl, directory, filename, options = {}) { | ||
/** | ||
* Uploads a local directory to Skynet. | ||
* @param {Object} directory - File objects to upload, indexed by their path strings. | ||
* @param {string} filename - The name of the directory. | ||
* @param {Object} [customOptions={}] - Additional settings that can optionally be set. | ||
* @param {string} [customOptions.endpointPath="/skynet/skyfile"] - The relative URL path of the portal endpoint to contact. | ||
* @param {string} [customOptions.portalDirectoryfilefieldname="files[]"] - The fieldName for directory files on the portal. | ||
*/ | ||
SkynetClient.prototype.uploadDirectory = async function (directory, filename, customOptions = {}) { | ||
const opts = { ...defaultUploadOptions, ...customOptions }; | ||
const formData = new FormData(); | ||
Object.entries(directory).forEach(([path, file]) => { | ||
formData.append("files[]", ensureFileObjectConsistency(file), path); | ||
formData.append(opts.portalDirectoryFileFieldname, ensureFileObjectConsistency(file), path); | ||
}); | ||
const parsed = parse(portalUrl); | ||
const url = makeUrl(this.portalUrl, opts.endpointPath, { filename }); | ||
parsed.set("pathname", "/skynet/skyfile"); | ||
parsed.set("query", { filename }); | ||
const { data } = await axios.post( | ||
parsed.toString(), | ||
url, | ||
formData, | ||
options.onUploadProgress && { | ||
opts.onUploadProgress && { | ||
onUploadProgress: ({ loaded, total }) => { | ||
const progress = loaded / total; | ||
options.onUploadProgress(progress, { loaded, total }); | ||
opts.onUploadProgress(progress, { loaded, total }); | ||
}, | ||
@@ -54,9 +69,10 @@ } | ||
return data; | ||
} | ||
}; | ||
/** | ||
* Sometimes file object might have had the type property defined manually with Object.defineProperty | ||
* and some browsers (namely firefox) can have problems reading it after the file has been appended | ||
* to form data. To overcome this, we recreate the file object using native File constructor with | ||
* a type defined as a constructor argument. | ||
* Sometimes file object might have had the type property defined manually with | ||
* Object.defineProperty and some browsers (namely firefox) can have problems | ||
* reading it after the file has been appended to form data. To overcome this, | ||
* we recreate the file object using native File constructor with a type defined | ||
* as a constructor argument. | ||
* Related issue: https://github.com/NebulousLabs/skynet-webportal/issues/290 | ||
@@ -63,0 +79,0 @@ */ |
@@ -0,21 +1,73 @@ | ||
// import axios from "axios"; | ||
import path from "path-browserify"; | ||
import parse from "url-parse"; | ||
export function open(portalUrl, skylink) { | ||
const url = getUrl(portalUrl, parseSkylink(skylink)); | ||
export const defaultSkynetPortalUrl = "https://siasky.net"; | ||
window.open(url, "_blank"); | ||
export function defaultPortalUrl() { | ||
var url = new URL(window.location.href); | ||
return url.href.substring(0, url.href.indexOf(url.pathname)); | ||
} | ||
export function getUrl(portalUrl, skylink, options = {}) { | ||
const parsed = parse(portalUrl); | ||
export function defaultOptions(endpointPath) { | ||
return { | ||
endpointPath: endpointPath, | ||
// TODO: | ||
// APIKey: "", | ||
// customUserAgent: "", | ||
}; | ||
} | ||
parsed.set("pathname", parseSkylink(skylink)); | ||
// TODO: Use this to simplify creating requests. Needs to be tested. | ||
// export function executeRequest(portalUrl, method, opts, query, data = {}) { | ||
// const url = makeUrl(portalUrl, opts.endpointPath, query); | ||
if (options.download) { | ||
parsed.set("query", { attachment: true }); | ||
} | ||
// return axios({ | ||
// method: method, | ||
// url: url, | ||
// data: data, | ||
// auth: opts.APIKey && {username: "", password: opts.APIKey }, | ||
// onUploadProgress: opts.onUploadProgress && { | ||
// onUploadProgress: ({ loaded, total }) => { | ||
// const progress = loaded / total; | ||
// opts.onUploadProgress(progress, { loaded, total }); | ||
// }, | ||
// } | ||
// }); | ||
// } | ||
function getFilePath(file) { | ||
return file.webkitRelativePath || file.path || file.name; | ||
} | ||
export function getRelativeFilePath(file) { | ||
const filePath = getFilePath(file); | ||
const { root, dir, base } = path.parse(filePath); | ||
const relative = path.normalize(dir).slice(root.length).split(path.sep).slice(1); | ||
return path.join(...relative, base); | ||
} | ||
export function getRootDirectory(file) { | ||
const filePath = getFilePath(file); | ||
const { root, dir } = path.parse(filePath); | ||
return path.normalize(dir).slice(root.length).split(path.sep)[0]; | ||
} | ||
export function makeUrl(portalUrl, pathname, query = {}) { | ||
const parsed = parse(portalUrl); | ||
parsed.set("pathname", pathname); | ||
parsed.set("query", query); | ||
return parsed.toString(); | ||
} | ||
export function makeUrlWithSkylink(portalUrl, endpointPath, skylink, query = {}) { | ||
const parsedSkylink = parseSkylink(skylink); | ||
return makeUrl(portalUrl, path.posix.join(endpointPath, parsedSkylink), query); | ||
} | ||
const SKYLINK_MATCHER = "([a-zA-Z0-9_-]{46})"; | ||
@@ -22,0 +74,0 @@ const SKYLINK_DIRECT_REGEX = new RegExp(`^${SKYLINK_MATCHER}$`); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
46582
35
1014
190
3
+ Addedpath-browserify@^1.0.1
+ Addedpath-browserify@1.0.1(transitive)