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 __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import { Observable, gql, useApolloClient, useQuery, useSubscription } from '@apollo/client/index.js';
import { generateApolloClient } from '@deep-foundation/hasura/client.js';
import { useLocalStore } from '@deep-foundation/store/local.js';
import atob from 'atob';
import get from 'get-value';
import React, { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
import { corePckg } from './core.js';
import { debug } from './debug.js';
import { deleteMutation, generateQuery, generateQueryData, generateSerial, insertMutation, updateMutation } from './gql/index.js';
import { MinilinkCollection, useMinilinks, useMinilinksApply, useMinilinksQuery, useMinilinksSubscription } from './minilinks.js';
import { awaitPromise } from './promise.js';
import { useTokenController } from './react-token.js';
import { reserve } from './reserve.js';
import { Traveler as NativeTraveler } from './traveler.js';
const moduleLog = debug.extend('client');
const log = debug.extend('log');
const error = debug.extend('error');
const corePckgIds = {};
corePckg.data.filter(l => !!l.type).forEach((l, i) => {
    corePckgIds[l.id] = i + 1;
});
const random = () => Math.random().toString(36).slice(2, 7);
export const _ids = {
    '@deep-foundation/core': corePckgIds,
};
export const _serialize = {
    links: {
        virtualize: {
            id: ['id', '_id'],
            type_id: ['type_id', '_type_id'],
            from_id: ['from_id', '_from_id'],
            to_id: ['to_id', '_to_id'],
        },
        fields: {
            id: 'number',
            from_id: 'number',
            to_id: 'number',
            type_id: 'number',
            _id: 'number',
            _from_id: 'number',
            _to_id: 'number',
            _type_id: 'number',
        },
        relations: {
            from: 'links',
            to: 'links',
            type: 'links',
            in: 'links',
            out: 'links',
            typed: 'links',
            selected: 'selector',
            selectors: 'selector',
            value: 'value',
            string: 'value',
            number: 'value',
            object: 'value',
            can_rule: 'can',
            can_action: 'can',
            can_object: 'can',
            can_subject: 'can',
            down: 'tree',
            up: 'tree',
            tree: 'tree',
            root: 'tree',
        },
    },
    selector: {
        fields: {
            item_id: 'number',
            selector_id: 'number',
            query_id: 'number',
            selector_include_id: 'number',
        },
        relations: {
            item: 'links',
            selector: 'links',
            query: 'links',
        }
    },
    can: {
        fields: {
            rule_id: 'number',
            action_id: 'number',
            object_id: 'number',
            subject_id: 'number',
        },
        relations: {
            rule: 'links',
            action: 'links',
            object: 'links',
            subject: 'links',
        }
    },
    tree: {
        fields: {
            id: 'number',
            link_id: 'number',
            tree_id: 'number',
            root_id: 'number',
            parent_id: 'number',
            depth: 'number',
            position_id: 'string',
        },
        relations: {
            link: 'links',
            tree: 'links',
            root: 'links',
            parent: 'links',
            by_link: 'tree',
            by_tree: 'tree',
            by_root: 'tree',
            by_parent: 'tree',
            by_position: 'tree',
        }
    },
    value: {
        fields: {
            id: 'number',
            link_id: 'number',
            value: 'value',
        },
        relations: {
            link: 'links',
        },
    },
};
export const _boolExpFields = {
    _and: true,
    _not: true,
    _or: true,
};
export const pathToWhere = (start, ...path) => {
    var _a, _b;
    const pckg = typeof (start) === 'string' ? { type_id: (_a = _ids === null || _ids === void 0 ? void 0 : _ids['@deep-foundation/core']) === null || _a === void 0 ? void 0 : _a.Package, value: start } : { id: start };
    let where = pckg;
    for (let p = 0; p < path.length; p++) {
        const item = path[p];
        if (typeof (item) !== 'boolean') {
            const nextWhere = { in: { type_id: (_b = _ids === null || _ids === void 0 ? void 0 : _ids['@deep-foundation/core']) === null || _b === void 0 ? void 0 : _b.Contain, value: item, from: where } };
            where = nextWhere;
        }
    }
    return where;
};
export const serializeWhere = (exp, env = 'links', unvertualizeId = defaultUnvertualizeId) => {
    var _a, _b, _c, _d, _e, _f;
    if (Object.prototype.toString.call(exp) === '[object Array]')
        return exp.map((e) => serializeWhere(e, env, unvertualizeId));
    else if (typeof (exp) === 'object') {
        const keys = Object.keys(exp);
        const result = {};
        for (let k = 0; k < keys.length; k++) {
            const key = keys[k];
            const type = typeof (exp[key]);
            if (typeof (exp[key]) === 'undefined')
                throw new Error(`${key} === undefined`);
            let setted = false;
            const is_id_field = !!~['type_id', 'from_id', 'to_id'].indexOf(key);
            if (env === 'links') {
                if (key === 'relation') {
                    setted = result[key] = exp[key];
                }
                else if (type === 'string' || type === 'number') {
                    if (key === 'value' || key === type) {
                        setted = result[type] = { value: { _eq: exp[key] } };
                    }
                    else {
                        setted = result[key] = key === 'table' ? exp[key] : { _eq: unvertualizeId(exp[key]) };
                    }
                }
                else if (!_boolExpFields[key] && Object.prototype.toString.call(exp[key]) === '[object Array]') {
                    setted = result[key] = serializeWhere(pathToWhere(...exp[key]), 'links', unvertualizeId);
                }
                else if (key === 'return') {
                    setted = result[key] = {};
                    for (let r in exp[key]) {
                        result[key][r] = serializeWhere(exp[key][r], env, unvertualizeId);
                    }
                }
            }
            else if (env === 'tree') {
                if (type === 'string' || type === 'number') {
                    const isId = key === 'link_id' || key === 'tree_id' || key === 'root_id' || key === 'parent_id';
                    setted = result[key] = { _eq: isId ? unvertualizeId(exp[key]) : exp[key] };
                }
                else if (!_boolExpFields[key] && Object.prototype.toString.call(exp[key]) === '[object Array]') {
                    setted = result[key] = serializeWhere(pathToWhere(...exp[key]), 'links', unvertualizeId);
                }
            }
            else if (env === 'value') {
                if (type === 'string' || type === 'number') {
                    setted = result[key] = { _eq: key === 'link_id' ? unvertualizeId(exp[key]) : exp[key] };
                }
            }
            if (type === 'object' && ((_a = exp[key]) === null || _a === void 0 ? void 0 : _a.hasOwnProperty('_type_of')) && ((env === 'links' && (is_id_field || key === 'id')) ||
                (env === 'selector' && key === 'item_id') ||
                (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
                (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
                (env === 'value' && key === 'link_id'))) {
                const _temp = setted = { _by_item: { path_item_id: { _eq: unvertualizeId(exp[key]._type_of) }, group_id: { _eq: _ids['@deep-foundation/core'].typesTree } } };
                if (key === 'id') {
                    result._and = result._and ? [...result._and, _temp] : [_temp];
                }
                else {
                    result[key.slice(0, -3)] = _temp;
                }
            }
            else if (type === 'object' && ((_b = exp[key]) === null || _b === void 0 ? void 0 : _b.hasOwnProperty('_id')) && ((env === 'links' && (is_id_field || key === 'id')) ||
                (env === 'selector' && key === 'item_id') ||
                (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
                (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
                (env === 'value' && key === 'link_id')) && Object.prototype.toString.call(exp[key]._id) === '[object Array]' && exp[key]._id.length >= 1) {
                const root = exp[key]._id[0];
                const _temp = setted = serializeWhere(pathToWhere(typeof (root) === 'number' ? unvertualizeId(root) : root, ...exp[key]._id.slice(1)), 'links', unvertualizeId);
                if (key === 'id') {
                    result._and = result._and ? [...result._and, _temp] : [_temp];
                }
                else {
                    result[key.slice(0, -3)] = _temp;
                }
            }
            if (!setted) {
                const _temp = (_boolExpFields[key]) ? (serializeWhere(exp[key], env, unvertualizeId)) : ((_d = (_c = _serialize === null || _serialize === void 0 ? void 0 : _serialize[env]) === null || _c === void 0 ? void 0 : _c.relations) === null || _d === void 0 ? void 0 : _d[key]) ? (serializeWhere(exp[key], (_f = (_e = _serialize === null || _serialize === void 0 ? void 0 : _serialize[env]) === null || _e === void 0 ? void 0 : _e.relations) === null || _f === void 0 ? void 0 : _f[key], unvertualizeId)) : (exp[key]);
                if (key === '_and')
                    result._and ? result._and.push(..._temp) : result._and = _temp;
                else
                    result[key] = _temp;
            }
        }
        return result;
    }
    else {
        if (typeof (exp) === 'undefined')
            throw new Error('undefined in query');
        return exp;
    }
};
const defaultUnvertualizeId = (id) => id;
export const serializeQuery = (exp, env = 'links', unvertualizeId = defaultUnvertualizeId) => {
    const { limit, order_by, offset, distinct_on } = exp, where = __rest(exp, ["limit", "order_by", "offset", "distinct_on"]);
    const result = { where: typeof (exp) === 'object' ? Object.prototype.toString.call(exp) === '[object Array]' ? { id: { _in: exp.map(id => unvertualizeId(id)) } } : serializeWhere(where, env, unvertualizeId) : { id: { _eq: unvertualizeId(exp) } } };
    if (limit)
        result.limit = limit;
    if (order_by)
        result.order_by = order_by;
    if (offset)
        result.offset = offset;
    if (distinct_on)
        result.distinct_on = distinct_on;
    return result;
};
export function parseJwt(token) {
    var base64Url = token.split('.')[1];
    var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
    const parsed = JSON.parse(jsonPayload);
    const _a = parsed['https://hasura.io/jwt/claims'] || {}, { 'x-hasura-allowed-roles': roles, 'x-hasura-default-role': role, 'x-hasura-user-id': userId } = _a, other = __rest(_a, ['x-hasura-allowed-roles', 'x-hasura-default-role', 'x-hasura-user-id']);
    return Object.assign({ userId: +userId, role, roles }, other);
}
;
;
export function checkAndFillShorts(obj) {
    var _a, _b, _c;
    for (var i in obj) {
        if (!obj.hasOwnProperty(i))
            continue;
        if ((typeof obj[i]) == 'object' && obj[i] !== null) {
            if (typeof obj[i] === 'object' && i === 'object' && ((_b = (_a = obj[i]) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.value) === undefined) {
                obj[i] = { data: { value: obj[i] } };
                continue;
            }
            if (typeof obj[i] === 'object' && (i === 'to' || i === 'from' || i === 'in' || i === 'out') && ((_c = obj[i]) === null || _c === void 0 ? void 0 : _c.data) === undefined)
                obj[i] = { data: obj[i] };
            checkAndFillShorts(obj[i]);
        }
        else if (i === 'string' && typeof obj[i] === 'string' || i === 'number' && typeof obj[i] === 'number')
            obj[i] = { data: { value: obj[i] } };
    }
}
export function convertDeepInsertToMinilinksApplyAndPatchVirtualIds(deep, objects, table, result = [], errors, patch = {}) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
    const levelIds = [];
    if (table === 'links') {
        for (let i = 0; i < objects.length; i++) {
            const o = objects[i];
            let id = o.id;
            if (!id) {
                id = deep.minilinks.virtualCounter--;
                (_b = (_a = deep.minilinks) === null || _a === void 0 ? void 0 : _a.byId[id]) === null || _b === void 0 ? void 0 : _b._id = apply;
            }
            levelIds.push(id);
            const patchRelationIds = {};
            if (o === null || o === void 0 ? void 0 : o.from) {
                const { objects: objs, levelIds } = convertDeepInsertToMinilinksApplyAndPatchVirtualIds(deep, [(_c = o === null || o === void 0 ? void 0 : o.from) === null || _c === void 0 ? void 0 : _c.data], table, result, errors);
                o.from.data = objs;
                patchRelationIds.from_id = levelIds[0];
            }
            if (o === null || o === void 0 ? void 0 : o.to) {
                const { objects: objs, levelIds } = convertDeepInsertToMinilinksApplyAndPatchVirtualIds(deep, [(_d = o === null || o === void 0 ? void 0 : o.to) === null || _d === void 0 ? void 0 : _d.data], table, result, errors);
                o.to.data = objs;
                patchRelationIds.to_id = levelIds[0];
            }
            if (o === null || o === void 0 ? void 0 : o.type) {
                const { objects: objs, levelIds } = convertDeepInsertToMinilinksApplyAndPatchVirtualIds(deep, [(_e = o === null || o === void 0 ? void 0 : o.type) === null || _e === void 0 ? void 0 : _e.data], table, result, errors);
                o.type.data = objs;
                patchRelationIds.type_id = levelIds[0];
            }
            if (o === null || o === void 0 ? void 0 : o.out) {
                const { objects: objs, levelIds } = convertDeepInsertToMinilinksApplyAndPatchVirtualIds(deep, (((_g = (_f = o === null || o === void 0 ? void 0 : o.out) === null || _f === void 0 ? void 0 : _f.data) === null || _g === void 0 ? void 0 : _g.length) ? (_h = o === null || o === void 0 ? void 0 : o.out) === null || _h === void 0 ? void 0 : _h.data : [(_j = o === null || o === void 0 ? void 0 : o.out) === null || _j === void 0 ? void 0 : _j.data]), table, result, errors, { from_id: id });
                o.out.data = objs;
            }
            if (o === null || o === void 0 ? void 0 : o.in) {
                const { objects: objs, levelIds } = convertDeepInsertToMinilinksApplyAndPatchVirtualIds(deep, (((_l = (_k = o === null || o === void 0 ? void 0 : o.in) === null || _k === void 0 ? void 0 : _k.data) === null || _l === void 0 ? void 0 : _l.length) ? (_m = o === null || o === void 0 ? void 0 : o.in) === null || _m === void 0 ? void 0 : _m.data : [(_o = o === null || o === void 0 ? void 0 : o.in) === null || _o === void 0 ? void 0 : _o.data]), table, result, errors, { to_id: id });
                o.in.data = objs;
            }
            if (o === null || o === void 0 ? void 0 : o.types) {
                const { objects: objs, levelIds } = convertDeepInsertToMinilinksApplyAndPatchVirtualIds(deep, (((_q = (_p = o === null || o === void 0 ? void 0 : o.types) === null || _p === void 0 ? void 0 : _p.data) === null || _q === void 0 ? void 0 : _q.length) ? (_r = o === null || o === void 0 ? void 0 : o.types) === null || _r === void 0 ? void 0 : _r.data : [(_s = o === null || o === void 0 ? void 0 : o.types) === null || _s === void 0 ? void 0 : _s.data]), table, result, errors, { type_id: id });
                o.types.data = objs;
            }
            if (typeof (o.from_id) === 'number' || typeof (o.from_id) === 'string') {
                if (o.from_id < 0) {
                    if (deep.minilinks.virtual[o.from_id])
                        o.from_id = deep.minilinks.virtual[o.from_id];
                    else
                        errors.push(`.from_id=${o.from_id} can't be devertualized, not exists in minilinks.virtual[${o.from_id}]`);
                }
            }
            if (typeof (o.to_id) === 'number' || typeof (o.to_id) === 'string') {
                if (o.to_id < 0) {
                    if (deep.minilinks.virtual[o.to_id])
                        o.to_id = deep.minilinks.virtual[o.to_id];
                    else
                        errors.push(`.to_id=${o.to_id} can't be devertualized, not exists in minilinks.virtual[${o.to_id}]`);
                }
            }
            if (typeof (o.type_id) === 'number' || typeof (o.type_id) === 'string') {
                if (o.type_id < 0) {
                    if (deep.minilinks.virtual[o.type_id])
                        o.type_id = deep.minilinks.virtual[o.type_id];
                    else
                        errors.push(`.type_id=${o.type_id} can't be devertualized, not exists in minilinks.virtual[${o.type_id}]`);
                }
            }
            result.push(Object.assign(Object.assign({ id: id, from_id: o.from_id, to_id: o.to_id, type_id: o.type_id, value: ((_t = o.string) === null || _t === void 0 ? void 0 : _t.data) || ((_u = o.number) === null || _u === void 0 ? void 0 : _u.data) || ((_v = o.object) === null || _v === void 0 ? void 0 : _v.data) }, patch), patchRelationIds));
        }
    }
    return { objects: objects.length == 1 ? objects[0] : objects, levelIds };
}
export function convertDeepUpdateToMinilinksApply(ml, _exp, _set, table, toUpdate = []) {
    if (table === 'links') {
        try {
            const founded = ml.query(_exp);
            for (let f of founded) {
                toUpdate.push(Object.assign({ id: f.id, from_id: f.from_id, to_id: f.to_id, type_id: f.type_id, value: f.value }, _set));
            }
        }
        catch (e) { }
    }
    else if (table === 'strings' || table === 'numbers' || table === 'objects') {
        const key = table.slice(0, -1);
        const founded = ml.query({ [key]: _exp });
        for (let f of founded) {
            toUpdate.push({
                id: f.id, from_id: f.from_id, to_id: f.to_id, type_id: f.type_id,
                value: Object.assign(Object.assign({}, f === null || f === void 0 ? void 0 : f.value), { value: _set.value }),
            });
        }
    }
}
export function convertDeepDeleteToMinilinksApply(ml, _exp, table, toDelete = [], toUpdate = []) {
    if (table === 'links') {
        try {
            const founded = ml.query(_exp);
            toDelete.push(...founded.map(l => l.id));
        }
        catch (e) { }
    }
    else if (table === 'strings' || table === 'numbers' || table === 'objects') {
        const key = table.slice(0, -1);
        const founded = ml.query({ [key]: _exp });
        toUpdate.push(...founded.map(o => ({
            id: o.id, from_id: o.from_id, to_id: o.to_id, type_id: o.type_id,
        })));
    }
}
export class DeepClient {
    _silent(options = {}) {
        return typeof (options.silent) === 'boolean' ? options.silent : this.silent;
    }
    constructor(options) {
        var _a, _b, _c, _d;
        this.useDeep = useDeep;
        this.DeepProvider = DeepProvider;
        this.DeepContext = DeepContext;
        this.DeepClient = DeepClient;
        this.namespace = (options === null || options === void 0 ? void 0 : options.namespace) || randomName();
        this.local = typeof (options === null || options === void 0 ? void 0 : options.local) === 'boolean' ? options === null || options === void 0 ? void 0 : options.local : true;
        this.remote = typeof (options === null || options === void 0 ? void 0 : options.remote) === 'boolean' ? options === null || options === void 0 ? void 0 : options.remote : true;
        if ((options === null || options === void 0 ? void 0 : options.needConnection) != false) {
            this.deep = options === null || options === void 0 ? void 0 : options.deep;
            this.apolloClient = options === null || options === void 0 ? void 0 : options.apolloClient;
            this.token = options === null || options === void 0 ? void 0 : options.token;
            this.client = this.apolloClient;
            this.table = options.table || 'links';
            if (this.deep && !this.apolloClient) {
                const token = (_a = this.token) !== null && _a !== void 0 ? _a : this.deep.token;
                if (!token) {
                    throw new Error('token for apolloClient is invalid or not provided');
                }
                this.apolloClient = generateApolloClient({
                    path: (_b = this.deep.apolloClient) === null || _b === void 0 ? void 0 : _b.path,
                    ssl: (_c = this.deep.apolloClient) === null || _c === void 0 ? void 0 : _c.ssl,
                    token: token,
                });
            }
            if (!this.apolloClient)
                throw new Error('apolloClient is invalid or not provided');
            if (this.token) {
                const decoded = parseJwt(this.token);
                const linkId = decoded === null || decoded === void 0 ? void 0 : decoded.userId;
                if (!linkId) {
                    throw new Error(`Unable to parse linkId from jwt token.`);
                }
                if (options.linkId && options.linkId !== linkId) {
                    throw new Error(`linkId (${linkId}) parsed from jwt token is not the same as linkId passed via options (${options.linkId}).`);
                }
                this.linkId = linkId;
            }
            else {
                this.linkId = options.linkId;
            }
        }
        this.minilinks = options.minilinks || new MinilinkCollection();
        this.unvertualizeId = (id) => {
            return this.minilinks.virtual.hasOwnProperty(id) ? this.minilinks.virtual[id] : id;
        };
        this.linksSelectReturning = options.linksSelectReturning || options.selectReturning || 'id type_id from_id to_id value';
        this.selectReturning = options.selectReturning || this.linksSelectReturning;
        this.valuesSelectReturning = options.valuesSelectReturning || 'id link_id value';
        this.selectorsSelectReturning = options.selectorsSelectReturning || 'item_id selector_id';
        this.filesSelectReturning = options.filesSelectReturning || 'id link_id name mimeType';
        this.insertReturning = options.insertReturning || 'id';
        this.updateReturning = options.updateReturning || 'id';
        this.deleteReturning = options.deleteReturning || 'id';
        this.defaultSelectName = options.defaultSelectName || 'SELECT';
        this.defaultInsertName = options.defaultInsertName || 'INSERT';
        this.defaultUpdateName = options.defaultUpdateName || 'UPDATE';
        this.defaultDeleteName = options.defaultDeleteName || 'DELETE';
        this.silent = options.silent || false;
        this.unsafe = options.unsafe || {};
        this.handleAuth = (options === null || options === void 0 ? void 0 : options.handleAuth) || ((_d = options === null || options === void 0 ? void 0 : options.deep) === null || _d === void 0 ? void 0 : _d.handleAuth);
        this.minilinks = options.minilinks || new MinilinkCollection();
        this._generateHooks(this);
    }
    _generateHooks(deep) {
        this.useDeepId = (start, ...path) => _useDeepId(deep, start, ...path);
        this.useDeepSubscription = (query, options) => useDeepSubscription(query, Object.assign(Object.assign({}, (options || {})), { deep: deep }));
        this.useDeepQuery = (query, options) => useDeepQuery(query, Object.assign(Object.assign({}, (options || {})), { deep: deep }));
        this.useMinilinksQuery = (query) => useMinilinksQuery(deep.minilinks, query);
        this.useMinilinksSubscription = (query) => useMinilinksSubscription(deep.minilinks, query);
    }
    stringify(any) {
        if (typeof (any) === 'string') {
            let json;
            try {
                json = JSON.parse(any);
            }
            catch (e) { }
            return json ? JSON.stringify(json, null, 2) : any.toString();
        }
        else if (typeof (any) === 'object') {
            return JSON.stringify(any, null, 2);
        }
        return any;
    }
    serializeQuery(exp, env) { return serializeQuery(exp, env, this.unvertualizeId); }
    serializeWhere(exp, env) { return serializeWhere(exp, env, this.unvertualizeId); }
    _generateQuery(exp, options) {
        var _a;
        const query = serializeQuery(exp, (options === null || options === void 0 ? void 0 : options.table) || 'links', this.unvertualizeId);
        const table = (options === null || options === void 0 ? void 0 : options.table) || this.table;
        const returning = (_a = options === null || options === void 0 ? void 0 : options.returning) !== null && _a !== void 0 ? _a : (table === 'links' ? this.linksSelectReturning :
            ['strings', 'numbers', 'objects'].includes(table) ? this.valuesSelectReturning :
                table === 'selectors' ? this.selectorsSelectReturning :
                    table === 'files' ? this.filesSelectReturning : `id`);
        const tableNamePostfix = options === null || options === void 0 ? void 0 : options.tableNamePostfix;
        const aggregate = options === null || options === void 0 ? void 0 : options.aggregate;
        const variables = options === null || options === void 0 ? void 0 : options.variables;
        const name = (options === null || options === void 0 ? void 0 : options.name) || this.defaultSelectName;
        const queryData = generateQueryData({
            tableName: table,
            tableNamePostfix: tableNamePostfix || aggregate ? '_aggregate' : '',
            returning: aggregate ? `aggregate { ${aggregate} }` : returning,
            variables: Object.assign(Object.assign({}, variables), query),
        });
        return {
            query: generateQuery({
                operation: (options === null || options === void 0 ? void 0 : options.subscription) ? 'subscription' : 'query',
                queries: [
                    queryData,
                ],
                name: name,
            }),
            queryData,
        };
    }
    _generateResult(exp, options, data) {
        return data;
    }
    select(exp, options) {
        var _a, _b, _c, _d, _e, _f;
        return __awaiter(this, void 0, void 0, function* () {
            if (!exp)
                return { error: { message: '!exp' }, data: undefined, loading: false, networkStatus: undefined };
            const aggregate = options === null || options === void 0 ? void 0 : options.aggregate;
            const queryData = this._generateQuery(exp, options);
            try {
                const q = yield this.apolloClient.query({ query: queryData.query.query, variables: (_a = queryData === null || queryData === void 0 ? void 0 : queryData.query) === null || _a === void 0 ? void 0 : _a.variables });
                return Object.assign(Object.assign({}, q), { data: aggregate ? (_e = (_d = (_c = (_b = (q)) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.q0) === null || _d === void 0 ? void 0 : _d.aggregate) === null || _e === void 0 ? void 0 : _e[aggregate] : yield this._generateResult(exp, options, (_f = q === null || q === void 0 ? void 0 : q.data) === null || _f === void 0 ? void 0 : _f.q0) });
            }
            catch (e) {
                console.dir({ queryData }, { depth: null });
                throw new Error(`DeepClient Select Error: ${e.message}`, { cause: e });
            }
        });
    }
    ;
    subscribe(exp, options) {
        var _a;
        if (!exp)
            return new Observable((observer) => observer.error('!exp'));
        const aggregate = options === null || options === void 0 ? void 0 : options.aggregate;
        const queryData = this._generateQuery(exp, Object.assign(Object.assign({}, options), { subscription: true }));
        try {
            const apolloObservable = this.apolloClient.subscribe({ query: queryData.query.query, variables: (_a = queryData === null || queryData === void 0 ? void 0 : queryData.query) === null || _a === void 0 ? void 0 : _a.variables });
            const observable = new Observable((observer) => {
                const subscription = apolloObservable.subscribe({
                    next: (data) => __awaiter(this, void 0, void 0, function* () {
                        var _a, _b, _c, _d;
                        observer.next(aggregate ? (_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.q0) === null || _b === void 0 ? void 0 : _b.aggregate) === null || _c === void 0 ? void 0 : _c[aggregate] :
                            yield this._generateResult(exp, options, (_d = data === null || data === void 0 ? void 0 : data.data) === null || _d === void 0 ? void 0 : _d.q0));
                    }),
                    error: (error) => observer.error(error),
                });
                return () => subscription.unsubscribe();
            });
            return observable;
        }
        catch (e) {
            throw new Error(`DeepClient Subscription Error: ${e.message}`, { cause: e });
        }
    }
    ;
    insert(objects, options) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
        return __awaiter(this, void 0, void 0, function* () {
            let _objects = Object.prototype.toString.call(objects) === '[object Array]' ? objects : [objects];
            checkAndFillShorts(_objects);
            const { local, remote } = Object.assign({ local: this.local, remote: this.remote }, options);
            const table = (options === null || options === void 0 ? void 0 : options.table) || this.table;
            const returning = (options === null || options === void 0 ? void 0 : options.returning) || this.insertReturning;
            const variables = options === null || options === void 0 ? void 0 : options.variables;
            const name = (options === null || options === void 0 ? void 0 : options.name) || this.defaultInsertName;
            let q = {};
            const toApply = [];
            if (this.minilinks && local !== false) {
                const errors = [];
                const { objects: __objects } = convertDeepInsertToMinilinksApplyAndPatchVirtualIds(this, _objects, table, toApply, errors);
                _objects = __objects;
                if (errors.length)
                    console.log('convertDeepInsertToMinilinksApplyAndPatchVirtualIds', 'errors', errors);
                this.minilinks.add(toApply);
            }
            if (remote !== false) {
                try {
                    q = yield this.apolloClient.mutate(generateSerial({
                        actions: [insertMutation(table, Object.assign(Object.assign({}, variables), { objects: _objects }), { tableName: table, operation: 'insert', returning })],
                        name: name,
                    }));
                }
                catch (e) {
                    const sqlError = (_d = (_c = (_b = (_a = e === null || e === void 0 ? void 0 : e.graphQLErrors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c.internal) === null || _d === void 0 ? void 0 : _d.error;
                    if (sqlError === null || sqlError === void 0 ? void 0 : sqlError.message)
                        e.message = sqlError.message;
                    if (!this._silent(options))
                        throw new Error(`DeepClient Insert Error: ${e.message}`, { cause: e });
                    return Object.assign(Object.assign({}, q), { data: (_g = (_f = (_e = (q)) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.m0) === null || _g === void 0 ? void 0 : _g.returning, error: e });
                }
            }
            else {
                return Object.assign(Object.assign({}, q), { data: toApply.map(l => l.id), loading: false });
            }
            return Object.assign(Object.assign({}, q), { data: (_k = (_j = (_h = (q)) === null || _h === void 0 ? void 0 : _h.data) === null || _j === void 0 ? void 0 : _j.m0) === null || _k === void 0 ? void 0 : _k.returning });
        });
    }
    ;
    update(exp, value, options) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
        return __awaiter(this, void 0, void 0, function* () {
            if (exp === null)
                return this.insert([value], options);
            if (value === null)
                return this.delete(exp, options);
            const { local, remote } = Object.assign({ local: this.local, remote: this.remote }, options);
            const query = serializeQuery(exp, (options === null || options === void 0 ? void 0 : options.table) === this.table || !(options === null || options === void 0 ? void 0 : options.table) ? 'links' : 'value', this.unvertualizeId);
            const table = (options === null || options === void 0 ? void 0 : options.table) || this.table;
            const toUpdate = [];
            if (this.minilinks && local !== false) {
                convertDeepUpdateToMinilinksApply(this.minilinks, exp, value, table, toUpdate);
                this.minilinks.update(toUpdate);
            }
            const returning = (options === null || options === void 0 ? void 0 : options.returning) || this.updateReturning;
            const variables = options === null || options === void 0 ? void 0 : options.variables;
            const name = (options === null || options === void 0 ? void 0 : options.name) || this.defaultUpdateName;
            let q;
            if (remote !== false) {
                try {
                    q = yield this.apolloClient.mutate(generateSerial({
                        actions: [updateMutation(table, Object.assign(Object.assign(Object.assign({}, variables), query), { _set: value }), { tableName: table, operation: 'update', returning })],
                        name: name,
                    }));
                }
                catch (e) {
                    const sqlError = (_d = (_c = (_b = (_a = e === null || e === void 0 ? void 0 : e.graphQLErrors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c.internal) === null || _d === void 0 ? void 0 : _d.error;
                    if (sqlError === null || sqlError === void 0 ? void 0 : sqlError.message)
                        e.message = sqlError.message;
                    if (!this._silent(options))
                        throw new Error(`DeepClient Update Error: ${e.message}`, { cause: e });
                    return Object.assign(Object.assign({}, q), { data: (_g = (_f = (_e = (q)) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.m0) === null || _g === void 0 ? void 0 : _g.returning, error: e });
                }
            }
            else {
                return Object.assign(Object.assign({}, q), { data: toUpdate.map(l => l.id), loading: false });
            }
            return Object.assign(Object.assign({}, q), { data: (_k = (_j = (_h = (q)) === null || _h === void 0 ? void 0 : _h.data) === null || _j === void 0 ? void 0 : _j.m0) === null || _k === void 0 ? void 0 : _k.returning });
        });
    }
    ;
    delete(exp, options) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
        return __awaiter(this, void 0, void 0, function* () {
            if (!exp)
                throw new Error('!exp');
            const { local, remote } = Object.assign({ local: this.local, remote: this.remote }, options);
            const query = serializeQuery(exp, (options === null || options === void 0 ? void 0 : options.table) === this.table || !(options === null || options === void 0 ? void 0 : options.table) ? 'links' : 'value', this.unvertualizeId);
            const table = (options === null || options === void 0 ? void 0 : options.table) || this.table;
            const returning = (options === null || options === void 0 ? void 0 : options.returning) || this.deleteReturning;
            const variables = options === null || options === void 0 ? void 0 : options.variables;
            const name = (options === null || options === void 0 ? void 0 : options.name) || this.defaultDeleteName;
            let q;
            const toDelete = [];
            const toUpdate = [];
            if (this.minilinks && local !== false) {
                convertDeepDeleteToMinilinksApply(this.minilinks, exp, table, toDelete, toUpdate);
                this.minilinks.update(toUpdate);
                this.minilinks.remove(toDelete);
            }
            if (remote !== false) {
                try {
                    q = yield this.apolloClient.mutate(generateSerial({
                        actions: [deleteMutation(table, Object.assign(Object.assign(Object.assign({}, variables), query), { returning }), { tableName: table, operation: 'delete', returning })],
                        name: name,
                    }));
                }
                catch (e) {
                    const sqlError = (_d = (_c = (_b = (_a = e === null || e === void 0 ? void 0 : e.graphQLErrors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c.internal) === null || _d === void 0 ? void 0 : _d.error;
                    if (sqlError === null || sqlError === void 0 ? void 0 : sqlError.message)
                        e.message = sqlError.message;
                    if (!this._silent(options))
                        throw new Error(`DeepClient Delete Error: ${e.message}`, { cause: e });
                    return Object.assign(Object.assign({}, q), { data: (_g = (_f = (_e = (q)) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.m0) === null || _g === void 0 ? void 0 : _g.returning, error: e });
                }
            }
            else {
                return Object.assign(Object.assign({}, q), { data: toDelete.map(l => l.id), loading: false });
            }
            return Object.assign(Object.assign({}, q), { data: (_k = (_j = (_h = (q)) === null || _h === void 0 ? void 0 : _h.data) === null || _j === void 0 ? void 0 : _j.m0) === null || _k === void 0 ? void 0 : _k.returning });
        });
    }
    ;
    serial(options) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        return __awaiter(this, void 0, void 0, function* () {
            const { name, operations, returning, silent } = options;
            let operationsGroupedByTypeAndTable = {};
            operationsGroupedByTypeAndTable = operations.reduce((acc, operation) => {
                if (!acc[operation.type]) {
                    acc[operation.type] = {};
                }
                if (!acc[operation.type][operation.table]) {
                    acc[operation.type][operation.table] = [];
                }
                acc[operation.type][operation.table].push(operation);
                return acc;
            }, operationsGroupedByTypeAndTable);
            let serialActions = [];
            Object.keys(operationsGroupedByTypeAndTable).map((operationType) => {
                const operationsGroupedByTable = operationsGroupedByTypeAndTable[operationType];
                Object.keys(operationsGroupedByTable).map((table) => {
                    const operations = operationsGroupedByTable[table];
                    if (operationType === 'insert') {
                        const insertOperations = operations;
                        const serialAction = insertMutation(table, { objects: insertOperations.map(operation => Array.isArray(operation.objects) ? operation.objects : [operation.objects]).flat() }, { tableName: table, operation: operationType, returning });
                        serialActions.push(serialAction);
                    }
                    else if (operationType === 'update') {
                        const updateOperations = operations;
                        const newSerialActions = updateOperations.map(operation => {
                            const exp = operation.exp;
                            const value = operation.value;
                            const query = serializeQuery(exp, table === this.table || !table ? 'links' : 'value', this.unvertualizeId);
                            return updateMutation(table, Object.assign(Object.assign({}, query), { _set: value }), { tableName: table, operation: operationType, returning });
                        });
                        serialActions = [...serialActions, ...newSerialActions];
                    }
                    else if (operationType === 'delete') {
                        const deleteOperations = operations;
                        ;
                        const newSerialActions = deleteOperations.map(operation => {
                            const exp = operation.exp;
                            const query = serializeQuery(exp, table === this.table || !table ? 'links' : 'value', this.unvertualizeId);
                            return deleteMutation(table, Object.assign({}, query), { tableName: table, operation: operationType, returning });
                        });
                        serialActions = [...serialActions, ...newSerialActions];
                    }
                });
            });
            let result;
            try {
                result = yield this.apolloClient.mutate(generateSerial({
                    actions: serialActions,
                    name: name !== null && name !== void 0 ? name : 'Name',
                }));
            }
            catch (e) {
                const sqlError = (_d = (_c = (_b = (_a = e === null || e === void 0 ? void 0 : e.graphQLErrors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c.internal) === null || _d === void 0 ? void 0 : _d.error;
                if (sqlError === null || sqlError === void 0 ? void 0 : sqlError.message)
                    e.message = sqlError.message;
                if (!silent)
                    throw new Error(`DeepClient Serial Error: ${e.message}`, { cause: e });
                return Object.assign(Object.assign({}, result), { data: (_g = (_f = (_e = (result)) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.m0) === null || _g === void 0 ? void 0 : _g.returning, error: e });
            }
            return Object.assign(Object.assign({}, result), { data: ((_h = (result)) === null || _h === void 0 ? void 0 : _h.data) && Object.values((_j = (result)) === null || _j === void 0 ? void 0 : _j.data).flatMap(m => m.returning) });
        });
    }
    ;
    reserve(count) {
        return reserve({ count, client: this.apolloClient });
    }
    ;
    await(id, options = { results: false }) {
        return __awaiter(this, void 0, void 0, function* () {
            return awaitPromise({
                id, client: this.apolloClient,
                Then: yield this.id('@deep-foundation/core', 'Then'),
                Promise: yield this.id('@deep-foundation/core', 'Promise'),
                Resolved: yield this.id('@deep-foundation/core', 'Resolved'),
                Rejected: yield this.id('@deep-foundation/core', 'Rejected'),
                Results: options.results
            });
        });
    }
    ;
    id(start, ...path) {
        var _a, _b, _c, _d, _e, _f, _g;
        return __awaiter(this, void 0, void 0, function* () {
            if (typeof (start) === 'object') {
                return (_c = (_b = (_a = ((yield this.select(start)))) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.id;
            }
            if ((_d = _ids === null || _ids === void 0 ? void 0 : _ids[start]) === null || _d === void 0 ? void 0 : _d[path[0]]) {
                return _ids[start][path[0]];
            }
            const q = yield this.select(pathToWhere(start, ...path));
            if (q.error) {
                throw q.error;
            }
            const result = (((_f = (_e = q === null || q === void 0 ? void 0 : q.data) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.id) | ((_g = _ids === null || _ids === void 0 ? void 0 : _ids[start]) === null || _g === void 0 ? void 0 : _g[path === null || path === void 0 ? void 0 : path[0]]) | 0);
            if (!result && path[path.length - 1] !== true) {
                throw new Error(`Id not found by [${JSON.stringify([start, ...path])}]`);
            }
            return result;
        });
    }
    ;
    ids(...paths) {
        return __awaiter(this, void 0, void 0, function* () {
            const appendPath = (accumulator, keys, value) => {
                const lastKey = keys.pop();
                const lastObject = keys.reduce((obj, key) => obj[key] = obj[key] || {}, accumulator);
                lastObject[lastKey] = value;
            };
            const result = {};
            yield Promise.all(paths.map(([start, ...path]) => __awaiter(this, void 0, void 0, function* () {
                const id = yield this.id(start, ...path);
                appendPath(result, [start, ...path], id);
            })));
            return result;
        });
    }
    idLocal(start, ...path) {
        const paths = [start, ...path];
        if (get(_ids, paths.join('.'))) {
            return get(_ids, paths.join('.'));
        }
        const [link] = this.minilinks.query({
            id: {
                _id: paths
            }
        });
        const result = link === null || link === void 0 ? void 0 : link.id;
        if (!result) {
            throw new Error(`Id not found by ${JSON.stringify([start, ...path])}`);
        }
        else {
            return result;
        }
    }
    ;
    guest(options = {}) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const relogin = typeof (options.relogin) === 'boolean' ? options.relogin : true;
            const result = yield this.apolloClient.query({ query: GUEST });
            const { linkId, token, error } = ((_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.guest) || {};
            if (!error && !!token && relogin) {
                if (this === null || this === void 0 ? void 0 : this.handleAuth)
                    setTimeout(() => this === null || this === void 0 ? void 0 : this.handleAuth(+linkId, token), 0);
            }
            return { linkId, token, error: !error && (!linkId || !token) ? 'unexepted' : error };
        });
    }
    ;
    jwt(options) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const relogin = typeof (options.relogin) === 'boolean' ? options.relogin : false;
            if (options === null || options === void 0 ? void 0 : options.token) {
                try {
                    const token = options === null || options === void 0 ? void 0 : options.token;
                    const decoded = parseJwt(token);
                    const linkId = decoded === null || decoded === void 0 ? void 0 : decoded.userId;
                    if (!!token && relogin) {
                        if (this === null || this === void 0 ? void 0 : this.handleAuth)
                            setTimeout(() => this === null || this === void 0 ? void 0 : this.handleAuth(+linkId, token), 0);
                    }
                    return { linkId, token, error: (!linkId || !token) ? 'unexepted' : undefined };
                }
                catch (e) {
                    return { error: e };
                }
            }
            else if (options === null || options === void 0 ? void 0 : options.linkId) {
                const result = yield this.apolloClient.query({ query: JWT, variables: { linkId: +options.linkId } });
                const { linkId, token, error } = ((_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.jwt) || {};
                if (!error && !!token && relogin) {
                    if (this === null || this === void 0 ? void 0 : this.handleAuth)
                        setTimeout(() => this === null || this === void 0 ? void 0 : this.handleAuth(+linkId, token), 0);
                }
                return { linkId, token, error: error ? error : (!linkId) ? 'unexepted' : undefined };
            }
            else
                return { error: `linkId or token must be provided` };
        });
    }
    ;
    whoami() {
        var _a, _b, _c, _d;
        return __awaiter(this, void 0, void 0, function* () {
            const result = yield this.apolloClient.query({ query: WHOISME });
            this.linkId = (_b = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.jwt) === null || _b === void 0 ? void 0 : _b.linkId;
            return (_d = (_c = result === null || result === void 0 ? void 0 : result.data) === null || _c === void 0 ? void 0 : _c.jwt) === null || _d === void 0 ? void 0 : _d.linkId;
        });
    }
    login(options) {
        return __awaiter(this, void 0, void 0, function* () {
            return yield this.jwt(Object.assign(Object.assign({}, options), { relogin: true }));
        });
    }
    ;
    logout() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this === null || this === void 0 ? void 0 : this.handleAuth)
                setTimeout(() => this === null || this === void 0 ? void 0 : this.handleAuth(0, ''), 0);
            return { linkId: 0, token: '' };
        });
    }
    ;
    can(objectIds, subjectIds, actionIds, userIds = this.linkId) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const where = {};
            if (objectIds)
                where.object_id = typeof (objectIds) === 'number' ? { _eq: +objectIds } : { _in: objectIds };
            if (subjectIds)
                where.subject_id = typeof (subjectIds) === 'number' ? { _eq: +subjectIds } : { _in: subjectIds };
            if (actionIds)
                where.action_id = typeof (actionIds) === 'number' ? { _eq: +actionIds } : { _in: actionIds };
            const result = yield this.select(where, { table: 'can', returning: 'rule_id' });
            return !!((_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.length);
        });
    }
    name(input) {
        var _a, _b, _c;
        return __awaiter(this, void 0, void 0, function* () {
            const id = typeof (input) === 'number' || typeof (input) === 'string' ? input : input.id;
            const { data: [containLink] } = yield this.select({
                type_id: { _id: ['@deep-foundation/core', 'Contain'] },
                to_id: id,
            });
            if (!((_a = containLink === null || containLink === void 0 ? void 0 : containLink.value) === null || _a === void 0 ? void 0 : _a.value)) {
                const { data: [packageLink] } = yield this.select(id);
                if ((packageLink === null || packageLink === void 0 ? void 0 : packageLink.type_id) === this.idLocal('@deep-foundation/core', 'Package'))
                    return (_b = packageLink === null || packageLink === void 0 ? void 0 : packageLink.value) === null || _b === void 0 ? void 0 : _b.value;
            }
            return (_c = containLink === null || containLink === void 0 ? void 0 : containLink.value) === null || _c === void 0 ? void 0 : _c.value;
        });
    }
    ;
    nameLocal(input) {
        var _a, _b, _c, _d, _e, _f;
        const id = typeof (input) === 'number' || typeof (input) === 'string' ? input : input === null || input === void 0 ? void 0 : input.id;
        if (!id)
            return;
        if (((_a = this.minilinks.byId[id]) === null || _a === void 0 ? void 0 : _a.type_id) === this.idLocal('@deep-foundation/core', 'Package'))
            return (_c = (_b = this.minilinks.byId[id]) === null || _b === void 0 ? void 0 : _b.value) === null || _c === void 0 ? void 0 : _c.value;
        return (_f = (_e = (_d = this.minilinks.byType[this.idLocal('@deep-foundation/core', 'Contain')]) === null || _d === void 0 ? void 0 : _d.find((c) => (c === null || c === void 0 ? void 0 : c.to_id) === id)) === null || _e === void 0 ? void 0 : _e.value) === null || _f === void 0 ? void 0 : _f.value;
    }
    import(path) {
        return __awaiter(this, void 0, void 0, function* () {
            if (typeof DeepClient.resolveDependency !== 'undefined') {
                try {
                    return yield DeepClient.resolveDependency(path);
                }
                catch (e) {
                    console.log(`IGNORED ERROR (ignore if you don't see other errors): Call to DeepClient.resolveDependency is failed with`, e);
                }
            }
            if (typeof require !== 'undefined') {
                try {
                    return yield require(path);
                }
                catch (e) {
                    console.log(`IGNORED ERROR (ignore if you don't see other errors): Call to require is failed with`, e);
                }
            }
            return yield import(path);
        });
    }
    Traveler(links) {
        return new NativeTraveler(this, links);
    }
    ;
}
export const JWT = gql `query JWT($linkId: Int) {
  jwt(input: {linkId: $linkId}) {
    linkId
    token
  }
}`;
export const WHOISME = gql `query WHOISME {
  jwt(input: {}) {
    linkId
  }
}`;
export const GUEST = gql `query GUEST {
  guest {
    linkId
    token
  }
}`;
export function useAuthNode() {
    return useLocalStore('use_auth_link_id', 0);
}
export const DeepNamespaceContext = createContext({
    all: () => ({}),
    select: (namespace) => { },
    insert: (namespace, deep) => { },
    delete: (namespace) => { },
});
export const DeepNamespacesContext = createContext({});
export function useDeepNamespaces() {
    return useContext(DeepNamespacesContext);
}
;
export function useDeepNamespace(namespace, deep) {
    const namespaces = useContext(DeepNamespaceContext);
    const nameRef = useRef();
    useMemo(() => {
        if ((!!nameRef.current && nameRef.current != namespace)) {
            namespaces.delete(nameRef.current);
        }
        if (namespace) {
            if (namespaces.select(namespace) !== deep) {
                namespaces.delete(namespace);
            }
            namespaces.insert(namespace, deep);
        }
    }, [namespace, deep]);
    useEffect(() => {
        return () => nameRef.current && namespaces.delete(namespace);
    }, []);
}
export function DeepNamespaceProvider({ children }) {
    const [namespaces, setNamespaces] = useState({});
    const ref = useRef(namespaces);
    ref.current = namespaces;
    const api = useMemo(() => {
        return {
            all: () => ref.current,
            select: (namespace) => ref.current[namespace],
            insert: (namespace, deep) => {
                console.log('DeepNamespaceProvider', 'insert', namespace, deep);
                setNamespaces(namespaces => (Object.assign(Object.assign({}, namespaces), { [namespace]: deep })));
            },
            delete: (namespace) => {
                console.log('DeepNamespaceProvider', 'delete', namespace);
                setNamespaces(namespaces => (Object.assign(Object.assign({}, namespaces), { [namespace]: undefined })));
            },
        };
    }, []);
    useEffect(() => {
        console.log('DeepNamespaceProvider', 'mounted', api);
        if (typeof (window) == 'object')
            window.dn = api;
    }, []);
    return React.createElement(DeepNamespaceContext.Provider, { value: api },
        React.createElement(DeepNamespacesContext.Provider, { value: namespaces }, children));
}
export const DeepContext = createContext(undefined);
export function useDeepGenerator(generatorOptions) {
    const { apolloClient: apolloClientProps, minilinks } = generatorOptions, otherGeneratorOptions = __rest(generatorOptions, ["apolloClient", "minilinks"]);
    const log = debug.extend(useDeepGenerator.name);
    const apolloClientHook = useApolloClient();
    log({ apolloClientHook });
    const apolloClient = apolloClientProps || apolloClientHook;
    log({ apolloClient });
    const [linkId, setLinkId] = useAuthNode();
    log({ linkId, setLinkId });
    const [token, setToken] = useTokenController();
    log({ token, setToken });
    const deep = useMemo(() => {
        if (!(apolloClient === null || apolloClient === void 0 ? void 0 : apolloClient.jwt_token)) {
            log({ token, apolloClient });
        }
        return new DeepClient(Object.assign(Object.assign({}, otherGeneratorOptions), { apolloClient, linkId, token,
            minilinks, handleAuth: (linkId, token) => {
                setToken(token);
                setLinkId(linkId);
            } }));
    }, [apolloClient]);
    log({ deep });
    return deep;
}
export function DeepProvider({ apolloClient: apolloClientProps, minilinks: inputMinilinks, namespace, children, }) {
    const providedMinilinks = useMinilinks();
    const deep = useDeepGenerator({
        apolloClient: apolloClientProps,
        minilinks: inputMinilinks || providedMinilinks,
        namespace,
    });
    useDeepNamespace(namespace, deep);
    return React.createElement(DeepContext.Provider, { value: deep }, children);
}
export function useDeep() {
    return useContext(DeepContext);
}
export const randomName = () => Math.random().toString(36).slice(2, 7);
export function useDeepQuery(query, options) {
    var _a, _b, _c;
    const [miniName] = useState((options === null || options === void 0 ? void 0 : options.mini) || randomName());
    debug('useDeepQuery', miniName, query, options);
    const _deep = useDeep();
    const deep = (options === null || options === void 0 ? void 0 : options.deep) || _deep;
    const wq = useMemo(() => {
        return deep._generateQuery(query, Object.assign({}, options));
    }, [query, options]);
    const result = useQuery((_a = wq === null || wq === void 0 ? void 0 : wq.query) === null || _a === void 0 ? void 0 : _a.query, { variables: (_b = wq === null || wq === void 0 ? void 0 : wq.query) === null || _b === void 0 ? void 0 : _b.variables, client: deep.apolloClient });
    const [generatedResult, setGeneratedResult] = useState([]);
    useEffect(() => {
        var _a, _b, _c, _d;
        if (options === null || options === void 0 ? void 0 : options.aggregate)
            setGeneratedResult((_d = (_c = (_b = (_a = (result)) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.q0) === null || _c === void 0 ? void 0 : _c.aggregate) === null || _d === void 0 ? void 0 : _d[options.aggregate]);
        else {
            (() => __awaiter(this, void 0, void 0, function* () {
                var _e;
                setGeneratedResult(yield deep._generateResult(query, options, (_e = result === null || result === void 0 ? void 0 : result.data) === null || _e === void 0 ? void 0 : _e.q0));
            }))();
        }
    }, [result]);
    const toReturn = Object.assign(Object.assign({}, result), { data: generatedResult, deep, return: query === null || query === void 0 ? void 0 : query.return });
    useMinilinksApply(deep.minilinks, miniName, toReturn);
    toReturn.data = deep.useMinilinksSubscription({ id: { _in: (_c = toReturn === null || toReturn === void 0 ? void 0 : toReturn.data) === null || _c === void 0 ? void 0 : _c.map(l => l.id) } });
    return toReturn;
}
export function useDeepSubscription(query, options) {
    var _a, _b, _c;
    const [miniName] = useState((options === null || options === void 0 ? void 0 : options.mini) || Math.random().toString(36).slice(2, 7));
    debug('useDeepSubscription', miniName, query, options);
    const _deep = useDeep();
    const deep = (options === null || options === void 0 ? void 0 : options.deep) || _deep;
    useState({ query, options, deep });
    const wq = useMemo(() => {
        return deep._generateQuery(query, Object.assign(Object.assign({}, options), { subscription: true }));
    }, [query, options]);
    const result = useSubscription((_a = wq === null || wq === void 0 ? void 0 : wq.query) === null || _a === void 0 ? void 0 : _a.query, { variables: (_b = wq === null || wq === void 0 ? void 0 : wq.query) === null || _b === void 0 ? void 0 : _b.variables, client: deep.apolloClient });
    const [generatedResult, setGeneratedResult] = useState([]);
    useEffect(() => {
        var _a, _b, _c, _d;
        if (options === null || options === void 0 ? void 0 : options.aggregate)
            setGeneratedResult((_d = (_c = (_b = (_a = (result)) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.q0) === null || _c === void 0 ? void 0 : _c.aggregate) === null || _d === void 0 ? void 0 : _d[options.aggregate]);
        else {
            if (!result.loading) {
                (() => __awaiter(this, void 0, void 0, function* () {
                    var _e;
                    setGeneratedResult(yield deep._generateResult(query, options, (_e = result === null || result === void 0 ? void 0 : result.data) === null || _e === void 0 ? void 0 : _e.q0));
                }))();
            }
        }
    }, [result]);
    const toReturn = Object.assign(Object.assign({}, result), { data: generatedResult, deep, return: query === null || query === void 0 ? void 0 : query.return });
    useMinilinksApply(deep.minilinks, miniName, toReturn);
    toReturn.data = useMinilinksSubscription(deep.minilinks, { id: { _in: (_c = toReturn === null || toReturn === void 0 ? void 0 : toReturn.data) === null || _c === void 0 ? void 0 : _c.map(l => l.id) } });
    return toReturn;
}
export function useDeepId(start, ...path) {
    return useDeep().useDeepId(start, ...path);
}
export function _useDeepId(deep, start, ...path) {
    var _a, _b;
    const result = deep.useDeepQuery({ id: { _id: [start, ...path] } });
    return { data: (_b = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.id, loading: result === null || result === void 0 ? void 0 : result.loading, error: result === null || result === void 0 ? void 0 : result.error };
}
//# sourceMappingURL=client.js.map