"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
    if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
    var m = o[Symbol.asyncIterator], i;
    return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
    function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
    function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable import/first */
;
global.WebSocket = require('isomorphic-ws');
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const browser_or_node_1 = require("browser-or-node");
const chai_1 = require("chai");
const context_1 = require("@textile/context");
const buckets_1 = require("./buckets");
const spec_util_1 = require("./spec.util");
// Settings for localhost development and testing
const addrApiurl = 'http://127.0.0.1:3007';
const addrGatewayUrl = 'http://127.0.0.1:8006';
const wrongError = new Error('wrong error!');
const sessionSecret = 'hubsession';
describe('Buckets...', () => {
    const ctx = new context_1.Context(addrApiurl, undefined);
    const client = new buckets_1.Buckets(ctx);
    let buck;
    let fileSize;
    before(() => __awaiter(void 0, void 0, void 0, function* () {
        var _a;
        const user = yield spec_util_1.signUp(ctx, addrGatewayUrl, sessionSecret);
        ctx.withSession((_a = user.user) === null || _a === void 0 ? void 0 : _a.session);
    }));
    it('should open a bucket by name without thread info', () => __awaiter(void 0, void 0, void 0, function* () {
        const root = yield client.open('initbuck');
        chai_1.expect(root).to.have.ownProperty('key');
        chai_1.expect(root).to.have.ownProperty('path');
        chai_1.expect(root).to.have.ownProperty('createdat');
        chai_1.expect(root).to.have.ownProperty('updatedat');
    }));
    it('should init a new bucket on open thread', () => __awaiter(void 0, void 0, void 0, function* () {
        // Check that we're empty
        const list = yield client.list();
        chai_1.expect(list).to.have.length(1);
        // Now initialize a bucket
        buck = yield client.init('mybuck');
        chai_1.expect(buck).to.have.ownProperty('root');
        chai_1.expect(buck.root).to.have.ownProperty('key');
        chai_1.expect(buck.root).to.have.ownProperty('path');
        chai_1.expect(buck.root).to.have.ownProperty('createdat');
        chai_1.expect(buck.root).to.have.ownProperty('updatedat');
    }));
    it('should list buckets', () => __awaiter(void 0, void 0, void 0, function* () {
        var _b, _c, _d, _e;
        const roots = yield client.list();
        chai_1.expect(roots).to.have.length(2);
        const root = roots[0];
        chai_1.expect(root).to.have.ownProperty('key', (_b = buck.root) === null || _b === void 0 ? void 0 : _b.key);
        chai_1.expect(root).to.have.ownProperty('path', (_c = buck.root) === null || _c === void 0 ? void 0 : _c.path);
        chai_1.expect(root).to.have.ownProperty('createdat', (_d = buck.root) === null || _d === void 0 ? void 0 : _d.createdat);
        chai_1.expect(root).to.have.ownProperty('updatedat', (_e = buck.root) === null || _e === void 0 ? void 0 : _e.updatedat);
    }));
    it('should list empty bucket content at path', () => __awaiter(void 0, void 0, void 0, function* () {
        var _f, _g, _h;
        // Mostly empty
        const res = yield client.listPath(((_f = buck.root) === null || _f === void 0 ? void 0 : _f.key) || '', '');
        chai_1.expect(res).to.have.ownProperty('root');
        chai_1.expect(res.root).to.not.be.undefined;
        chai_1.expect((_g = res.item) === null || _g === void 0 ? void 0 : _g.isdir).to.be.true;
        // @todo: Should we rename itemsList to just be items?
        chai_1.expect((_h = res.item) === null || _h === void 0 ? void 0 : _h.itemsList).to.have.length(1); // Includes .textileseed
    }));
    it('should push data from filesystem on node', function () {
        var _a, _b, _c;
        return __awaiter(this, void 0, void 0, function* () {
            if (browser_or_node_1.isBrowser)
                return this.skip();
            const pth = path_1.default.join(__dirname, '../../..', 'testdata');
            fileSize = fs_1.default.statSync(path_1.default.join(pth, 'file1.jpg')).size;
            let stream = fs_1.default.createReadStream(path_1.default.join(pth, 'file1.jpg'));
            const rootKey = ((_a = buck.root) === null || _a === void 0 ? void 0 : _a.key) || '';
            let length = 0;
            // Bucket path
            const res = yield client.pushPath(rootKey, 'dir1/file1.jpg', stream, undefined, {
                progress: (num) => (length = num || 0),
            });
            chai_1.expect(length).to.equal(fileSize);
            chai_1.expect(res.path).to.not.be.undefined;
            chai_1.expect(res.root).to.not.be.undefined;
            // Nested bucket path
            stream = fs_1.default.createReadStream(path_1.default.join(pth, 'file2.jpg'));
            const { root } = yield client.pushPath(rootKey, 'path/to/file2.jpg', stream);
            chai_1.expect(root).to.not.be.undefined;
            // Root dir
            const rep = yield client.listPath(rootKey, '');
            chai_1.expect((_b = rep.item) === null || _b === void 0 ? void 0 : _b.isdir).to.be.true;
            chai_1.expect((_c = rep.item) === null || _c === void 0 ? void 0 : _c.itemsList).to.have.length(3); // Includes .textileseed
        });
    });
    it('should push data from file API in browser', function () {
        var _a, _b, _c;
        return __awaiter(this, void 0, void 0, function* () {
            if (browser_or_node_1.isNode)
                return this.skip();
            const parts = [
                new Blob(['you construct a file...'], { type: 'text/plain' }),
                ' Same way as you do with blob',
                new Uint16Array([33]),
            ];
            // Construct a file
            const file = new File(parts, 'file1.txt');
            const rootKey = ((_a = buck.root) === null || _a === void 0 ? void 0 : _a.key) || '';
            let length = 0;
            // Bucket path
            const res = yield client.pushPath(rootKey, 'dir1/file1.jpg', file, undefined, {
                progress: (num) => (length = num || 0),
            });
            chai_1.expect(length).to.equal(54);
            chai_1.expect(res.path).to.not.be.undefined;
            chai_1.expect(res.root).to.not.be.undefined;
            // Nested bucket path
            // @note: We're reusing file here...
            const { root } = yield client.pushPath(rootKey, 'path/to/file2.jpg', file);
            chai_1.expect(root).to.not.be.undefined;
            // Root dir
            const rep = yield client.listPath(rootKey, '');
            chai_1.expect((_b = rep.item) === null || _b === void 0 ? void 0 : _b.isdir).to.be.true;
            chai_1.expect((_c = rep.item) === null || _c === void 0 ? void 0 : _c.itemsList).to.have.length(3);
        });
    });
    it('should list (nested) files within a bucket', () => __awaiter(void 0, void 0, void 0, function* () {
        var _j, _k, _l, _m, _o;
        const rootKey = ((_j = buck.root) === null || _j === void 0 ? void 0 : _j.key) || '';
        // Nested dir
        let rep = yield client.listPath(rootKey, 'dir1');
        chai_1.expect((_k = rep.item) === null || _k === void 0 ? void 0 : _k.isdir).to.be.true;
        chai_1.expect((_l = rep.item) === null || _l === void 0 ? void 0 : _l.itemsList).to.have.length(1);
        // File
        rep = yield client.listPath(rootKey, 'dir1/file1.jpg');
        chai_1.expect((_m = rep.item) === null || _m === void 0 ? void 0 : _m.path.endsWith('file1.jpg')).to.be.true;
        chai_1.expect((_o = rep.item) === null || _o === void 0 ? void 0 : _o.isdir).to.be.false;
    }));
    it('should pull files by path and write to file on node', function () {
        var e_1, _a, e_2, _b;
        var _c;
        return __awaiter(this, void 0, void 0, function* () {
            if (browser_or_node_1.isBrowser)
                return this.skip();
            // Bucket path
            const rootKey = ((_c = buck.root) === null || _c === void 0 ? void 0 : _c.key) || '';
            let length = 0;
            // Bucket path
            const chunks = client.pullPath(rootKey, 'dir1/file1.jpg', undefined, {
                progress: (num) => (length = num || 0),
            });
            const pth = path_1.default.join(__dirname, '../../..', 'testdata');
            const stream = fs_1.default.createWriteStream(path_1.default.join(pth, 'output.jpg'));
            try {
                // Should be an AsyncIterable
                for (var chunks_1 = __asyncValues(chunks), chunks_1_1; chunks_1_1 = yield chunks_1.next(), !chunks_1_1.done;) {
                    const chunk = chunks_1_1.value;
                    stream.write(chunk);
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (chunks_1_1 && !chunks_1_1.done && (_a = chunks_1.return)) yield _a.call(chunks_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
            stream.close();
            chai_1.expect(length).to.equal(fileSize);
            const stored = fs_1.default.statSync(path_1.default.join(pth, 'file1.jpg'));
            const written = fs_1.default.statSync(path_1.default.join(pth, 'output.jpg'));
            // expect(stored.size).to.equal(written.size)
            fs_1.default.unlinkSync(path_1.default.join(pth, 'output.jpg'));
            // Should throw correctly when the file isn't available
            try {
                const more = client.pullPath(rootKey, 'dir1/nope.jpg');
                try {
                    for (var more_1 = __asyncValues(more), more_1_1; more_1_1 = yield more_1.next(), !more_1_1.done;) {
                        const chk = more_1_1.value;
                        chai_1.expect(chk).to.not.be.undefined;
                    }
                }
                catch (e_2_1) { e_2 = { error: e_2_1 }; }
                finally {
                    try {
                        if (more_1_1 && !more_1_1.done && (_b = more_1.return)) yield _b.call(more_1);
                    }
                    finally { if (e_2) throw e_2.error; }
                }
                throw wrongError;
            }
            catch (err) {
                chai_1.expect(err).to.not.equal(wrongError);
                chai_1.expect(err.toString()).to.include('nope.jpg');
            }
            // Should be an AsyncIterator
            const more = client.pullPath(rootKey, 'dir1/file1.jpg');
            const { value } = yield more.next();
            chai_1.expect(value).to.not.be.undefined;
        });
    });
    it('should remove files by path', () => __awaiter(void 0, void 0, void 0, function* () {
        var _p, _q, _r;
        const rootKey = ((_p = buck.root) === null || _p === void 0 ? void 0 : _p.key) || '';
        yield client.removePath(rootKey, 'path/to/file2.jpg');
        try {
            yield client.listPath(rootKey, 'path/to/file2.jpg');
            throw wrongError;
        }
        catch (err) {
            chai_1.expect(err).to.not.equal(wrongError);
        }
        let list = yield client.listPath(rootKey, '');
        chai_1.expect((_q = list.item) === null || _q === void 0 ? void 0 : _q.itemsList).to.have.length(3); // Includes .textileseed
        yield client.removePath(rootKey, 'path');
        try {
            yield client.listPath(rootKey, 'path');
            throw wrongError;
        }
        catch (err) {
            chai_1.expect(err).to.not.equal(wrongError);
        }
        list = yield client.listPath(rootKey, '');
        chai_1.expect((_r = list.item) === null || _r === void 0 ? void 0 : _r.itemsList).to.have.length(2); // Includes .textileseed
    }));
    it('should list bucket links', () => __awaiter(void 0, void 0, void 0, function* () {
        var _s;
        const rootKey = ((_s = buck.root) === null || _s === void 0 ? void 0 : _s.key) || '';
        const rep = yield client.links(rootKey);
        chai_1.expect(rep.url).to.not.equal('');
        chai_1.expect(rep.ipns).to.not.equal('');
    }));
    it('should remove an entire bucket', () => __awaiter(void 0, void 0, void 0, function* () {
        var _t;
        const rootKey = ((_t = buck.root) === null || _t === void 0 ? void 0 : _t.key) || '';
        const rep = yield client.listPath(rootKey, 'dir1/file1.jpg');
        chai_1.expect(rep).to.not.be.undefined;
        yield client.remove(rootKey);
        try {
            yield client.listPath(rootKey, 'dir1/file1.jpg');
            throw wrongError;
        }
        catch (err) {
            chai_1.expect(err).to.not.equal(wrongError);
        }
    }));
});
//# sourceMappingURL=buckets.spec.js.map