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());
    });
};
import chaiAsPromised from 'chai-as-promised';
import chai, { expect } from 'chai';
import { ArrayUtility } from '../../src/utils/array.js';
import { IndexLevel } from '../../src/store/index-level.js';
import { Temporal } from '@js-temporal/polyfill';
import { v4 as uuid } from 'uuid';
chai.use(chaiAsPromised);
let index;
describe('Index Level', () => {
    if (process.env.TESTSOFF === 'true') {
        return;
    }
    describe('put', () => {
        before(() => __awaiter(void 0, void 0, void 0, function* () {
            index = new IndexLevel({ location: 'tests/data/TEST-INDEX' });
            yield index.open();
        }));
        beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
            yield index.clear();
        }));
        after(() => __awaiter(void 0, void 0, void 0, function* () {
            yield index.close();
        }));
        it('adds 1 key per property aside from id', () => __awaiter(void 0, void 0, void 0, function* () {
            yield index.put(uuid(), {
                dateCreated: new Date().toISOString(),
                'a': 'b',
                'c': 'd'
            });
            const keys = yield ArrayUtility.fromAsyncGenerator(index.db.keys());
            expect(keys.length).to.equal(4);
        }));
        it('flattens nested records', () => __awaiter(void 0, void 0, void 0, function* () {
            const id = uuid();
            const doc = {
                some: {
                    nested: {
                        object: true
                    }
                }
            };
            yield index.put(id, doc);
            const key = yield index.db.get(index['join']('some.nested.object', true, id));
            expect(key).to.equal(id);
        }));
        it('removes empty objects', () => __awaiter(void 0, void 0, void 0, function* () {
            const id = uuid();
            const doc = {
                empty: { nested: {} }
            };
            yield index.put(id, doc);
            yield expect(index.db.get(index['join']('empty', '[object Object]', id))).to.eventually.be.undefined;
            yield expect(index.db.get(index['join']('empty.nested', '[object Object]', id))).to.eventually.be.undefined;
        }));
        it('removes empty arrays', () => __awaiter(void 0, void 0, void 0, function* () {
            const id = uuid();
            const doc = {
                empty: [[]]
            };
            yield index.put(id, doc);
            yield expect(index.db.get(index['join']('empty', '', id))).to.eventually.be.undefined;
            yield expect(index.db.get(index['join']('empty.0', '', id))).to.eventually.be.undefined;
        }));
        it('should not put anything if aborted beforehand', () => __awaiter(void 0, void 0, void 0, function* () {
            const controller = new AbortController();
            controller.abort('reason');
            const id = uuid();
            const doc = {
                foo: 'bar'
            };
            try {
                yield index.put(id, doc, { signal: controller.signal });
            }
            catch (e) {
                expect(e).to.equal('reason');
            }
            const result = yield index.query({ foo: 'bar' });
            expect(result.length).to.equal(0);
        }));
    });
    describe('query', () => {
        before(() => __awaiter(void 0, void 0, void 0, function* () {
            index = new IndexLevel({ location: 'tests/data/TEST-INDEX' });
            yield index.open();
        }));
        beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
            yield index.clear();
        }));
        after(() => __awaiter(void 0, void 0, void 0, function* () {
            yield index.close();
        }));
        it('works', () => __awaiter(void 0, void 0, void 0, function* () {
            const id1 = uuid();
            const doc1 = {
                'a': 'b',
                'c': 'd'
            };
            const id2 = uuid();
            const doc2 = {
                'a': 'c',
                'c': 'd'
            };
            const id3 = uuid();
            const doc3 = {
                'a': 'b',
                'c': 'e'
            };
            yield index.put(id1, doc1);
            yield index.put(id2, doc2);
            yield index.put(id3, doc3);
            const result = yield index.query({
                'a': 'b',
                'c': 'e'
            });
            expect(result.length).to.equal(1);
            expect(result[0]).to.equal(id3);
        }));
        it('should not match values prefixed with the query', () => __awaiter(void 0, void 0, void 0, function* () {
            const id = uuid();
            const doc = {
                value: 'foobar'
            };
            yield index.put(id, doc);
            const resp = yield index.query({
                value: 'foo'
            });
            expect(resp.length).to.equal(0);
        }));
        it('supports OR queries', () => __awaiter(void 0, void 0, void 0, function* () {
            const id1 = uuid();
            const doc1 = {
                'a': 'a'
            };
            const id2 = uuid();
            const doc2 = {
                'a': 'b'
            };
            const id3 = uuid();
            const doc3 = {
                'a': 'c'
            };
            yield index.put(id1, doc1);
            yield index.put(id2, doc2);
            yield index.put(id3, doc3);
            const resp = yield index.query({
                a: ['a', 'b']
            });
            expect(resp.length).to.equal(2);
            expect(resp).to.include(id1);
            expect(resp).to.include(id2);
        }));
        it('supports range queries', () => __awaiter(void 0, void 0, void 0, function* () {
            for (let i = -5; i < 5; ++i) {
                const id = uuid();
                const doc = {
                    dateCreated: Temporal.PlainDateTime.from({ year: 2023, month: 1, day: 15 + i }).toString({ smallestUnit: 'microseconds' })
                };
                yield index.put(id, doc);
            }
            const resp = yield index.query({
                dateCreated: {
                    gte: Temporal.PlainDateTime.from({ year: 2023, month: 1, day: 15 }).toString({ smallestUnit: 'microseconds' })
                }
            });
            expect(resp.length).to.equal(5);
        }));
        it('supports prefixed range queries', () => __awaiter(void 0, void 0, void 0, function* () {
            const id = uuid();
            const doc = {
                value: 'foobar'
            };
            yield index.put(id, doc);
            const resp = yield index.query({
                value: {
                    gte: 'foo'
                }
            });
            expect(resp.length).to.equal(1);
            expect(resp).to.include(id);
        }));
        it('supports suffixed range queries', () => __awaiter(void 0, void 0, void 0, function* () {
            const id1 = uuid();
            const doc1 = {
                foo: 'bar'
            };
            const id2 = uuid();
            const doc2 = {
                foo: 'barbaz'
            };
            yield index.put(id1, doc1);
            yield index.put(id2, doc2);
            const resp = yield index.query({
                foo: {
                    lte: 'bar'
                }
            });
            expect(resp.length).to.equal(1);
            expect(resp).to.include(id1);
        }));
        it('treats strings differently', () => __awaiter(void 0, void 0, void 0, function* () {
            const id1 = uuid();
            const doc1 = {
                foo: true
            };
            const id2 = uuid();
            const doc2 = {
                foo: 'true'
            };
            yield index.put(id1, doc1);
            yield index.put(id2, doc2);
            const resp = yield index.query({
                foo: true
            });
            expect(resp.length).to.equal(1);
            expect(resp).to.include(id1);
        }));
    });
    describe('delete', () => {
        before(() => __awaiter(void 0, void 0, void 0, function* () {
            index = new IndexLevel({ location: 'tests/data/TEST-INDEX' });
            yield index.open();
        }));
        beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
            yield index.clear();
        }));
        after(() => __awaiter(void 0, void 0, void 0, function* () {
            yield index.close();
        }));
        it('works', () => __awaiter(void 0, void 0, void 0, function* () {
            const id1 = uuid();
            const doc1 = {
                'a': 'b',
                'c': 'd'
            };
            const id2 = uuid();
            const doc2 = {
                'a': 'b',
                'c': 'd'
            };
            yield index.put(id1, doc1);
            yield index.put(id2, doc2);
            let result = yield index.query({ 'a': 'b', 'c': 'd' });
            expect(result.length).to.equal(2);
            expect(result).to.contain(id1);
            yield index.delete(id1);
            result = yield index.query({ 'a': 'b', 'c': 'd' });
            expect(result.length).to.equal(1);
        }));
        it('should not delete anything if aborted beforehand', () => __awaiter(void 0, void 0, void 0, function* () {
            const controller = new AbortController();
            controller.abort('reason');
            const id = uuid();
            const doc = {
                foo: 'bar'
            };
            yield index.put(id, doc);
            try {
                yield index.delete(id, { signal: controller.signal });
            }
            catch (e) {
                expect(e).to.equal('reason');
            }
            const result = yield index.query({ foo: 'bar' });
            expect(result.length).to.equal(1);
            expect(result).to.contain(id);
        }));
    });
});
//# sourceMappingURL=index-level.spec.js.map