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 Debug from 'debug';
import { minilinks } from './minilinks.js';
import { serializeError } from 'serialize-error';
const debug = Debug('deeplinks:packager');
const log = debug.extend('log');
const error = debug.extend('error');
const corePackage = '@deep-foundation/core';
export function sort(pckg, data, errors = [], references) {
    let sorted = [];
    if (pckg.strict) {
        sorted = data;
    }
    else {
        for (let i = 0; i < data.length; i++) {
            const item = data[i];
            if (item.value && !item[references.type]) {
                const max = sorted.reduce((p, l, index) => l[references.id] == item[references.id] ? index : p, 0);
                sorted.splice((max) + 1, 0, item);
            }
            else if (item.package) {
                sorted.splice(0, 0, item);
            }
            else {
                const _ = item === null || item === void 0 ? void 0 : item._;
                const firstDependIndex = sorted.findIndex((l, index) => {
                    return l[references.from] == item[references.id] || l[references.to] == item[references.id] || ((l[references.type] == item[references.id]) && !l._);
                });
                const maxDependIndex = sorted.reduce((p, l, index) => {
                    return ((l[references.id] == item[references.type]) && !_) || l[references.id] == item[references.from] || l[references.id] === item[references.to] ? index : p;
                }, 0);
                const _index = (!!~firstDependIndex && firstDependIndex < maxDependIndex ? firstDependIndex : maxDependIndex);
                sorted.splice(_index + 1, 0, item);
            }
        }
    }
    return { sorted };
}
export class Packager {
    constructor(client) {
        this.client = client;
    }
    fetchPackageNamespaceId(name, deep) {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const q = yield this.client.select({
                    value: { _eq: name },
                    link: { type_id: { _eq: deep.idLocal('@deep-foundation/core', 'PackageNamespace') } },
                }, {
                    table: `strings`,
                    returning: 'id: link_id'
                });
                return { error: false, namespaceId: (_b = (_a = q === null || q === void 0 ? void 0 : q.data) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.id };
            }
            catch (e) {
                log('fetchPackageNamespaceId error');
                const serializedError = serializeError(e);
                return { error: serializedError, namespaceId: 0 };
            }
            return { error: true, namespaceId: 0 };
        });
    }
    fetchDependenciedLinkId(pckg, dependedLink) {
        var _a, _b, _c, _d, _e, _f, _g;
        return __awaiter(this, void 0, void 0, function* () {
            try {
                const packageName = (_c = (_a = pckg === null || pckg === void 0 ? void 0 : pckg.dependencies) === null || _a === void 0 ? void 0 : _a[(_b = dependedLink === null || dependedLink === void 0 ? void 0 : dependedLink.package) === null || _b === void 0 ? void 0 : _b.dependencyId]) === null || _c === void 0 ? void 0 : _c.name;
                const packageTableName = `strings`;
                const q = yield this.client.select({
                    value: (_d = dependedLink === null || dependedLink === void 0 ? void 0 : dependedLink.package) === null || _d === void 0 ? void 0 : _d.containValue,
                    link: { from: { [packageTableName]: { value: packageName } } },
                }, {
                    table: `strings`,
                    returning: 'id link { id: to_id }'
                });
                return ((_g = (_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.link) === null || _g === void 0 ? void 0 : _g.id) || 0;
            }
            catch (e) {
                log('fetchDependenciedLinkId error');
                const serializedError = serializeError(e);
                error(JSON.stringify(serializedError, null, 2));
            }
            return 0;
        });
    }
    insertItem(items, item, errors, mutated) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            log('insertItem', item);
            try {
                if (item.type) {
                    const insert = { id: +item.id, type_id: +item.type, from_id: +item.from || 0, to_id: +item.to || 0 };
                    const operations = [{
                            table: 'links',
                            type: 'insert',
                            objects: [insert]
                        }];
                    log('insertItem promise awaited', item.id);
                    if (item.value && !item.package) {
                        log('insertItem value', item);
                        let valueLink;
                        if (!item.type) {
                            valueLink = items.find(i => i.id === item.id && !!i.type);
                            log('insertItem .value', item, valueLink);
                        }
                        else {
                            valueLink = item;
                        }
                        if (!valueLink) {
                            log('insertItem insertValue error');
                            errors.push(`Link ${JSON.stringify(item)} for value is not found.`);
                        }
                        else {
                            log('insertItem tables');
                            const type = typeof ((_a = item === null || item === void 0 ? void 0 : item.value) === null || _a === void 0 ? void 0 : _a.value);
                            operations.push({
                                table: `${type}s`,
                                type: 'insert',
                                objects: [Object.assign({ link_id: valueLink.id }, item.value)]
                            });
                        }
                    }
                    const linkInsert = yield this.client.serial({
                        name: 'IMPORT_PACKAGE_LINK',
                        operations
                    });
                    if (linkInsert === null || linkInsert === void 0 ? void 0 : linkInsert.errors) {
                        log('insertItem linkInsert error', insert);
                        errors.push(linkInsert === null || linkInsert === void 0 ? void 0 : linkInsert.errors);
                    }
                    log('insertItem promise', item.id);
                    yield this.client.await(+item.id);
                }
            }
            catch (e) {
                log('insertItem error');
                const serializedError = serializeError(e);
                error(JSON.stringify(serializedError, null, 2));
                errors.push(serializedError);
            }
            return;
        });
    }
    insertItems(pckg, data, counter, dependedLinks, errors = [], mutated = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                for (let i = 0; i < dependedLinks.length; i++) {
                    const item = dependedLinks[i];
                    yield this.insertItem(data, item, errors, mutated);
                    if (errors.length)
                        return { ids: [] };
                }
                for (let i = 0; i < data.length; i++) {
                    const item = data[i];
                    if (!item.package) {
                        yield this.insertItem(data, item, errors, mutated);
                        if (errors.length)
                            return { ids: [] };
                    }
                }
                return;
            }
            catch (e) {
                log('insertItems error');
                const serializedError = serializeError(e);
                error(JSON.stringify(serializedError, null, 2));
                errors.push(serializedError);
            }
            return;
        });
    }
    globalizeIds(pckg, ids, links) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
        return __awaiter(this, void 0, void 0, function* () {
            const difference = {};
            const global = links.map(l => (Object.assign({}, l)));
            let idsIndex = 0;
            for (let l = 0; l < links.length; l++) {
                const item = links[l];
                const oldId = item.id;
                let newId;
                if (item.package) {
                    newId = yield this.client.id((_c = (_a = pckg === null || pckg === void 0 ? void 0 : pckg.dependencies) === null || _a === void 0 ? void 0 : _a[(_b = item === null || item === void 0 ? void 0 : item.package) === null || _b === void 0 ? void 0 : _b.dependencyId]) === null || _c === void 0 ? void 0 : _c.name, item.package.containValue, true);
                    if (!newId)
                        pckg.errors.push(`${pckg.package.name} package depends on link with path ['${(_f = (_d = pckg === null || pckg === void 0 ? void 0 : pckg.dependencies) === null || _d === void 0 ? void 0 : _d[(_e = item === null || item === void 0 ? void 0 : item.package) === null || _e === void 0 ? void 0 : _e.dependencyId]) === null || _f === void 0 ? void 0 : _f.name}', '${item.package.containValue}'], but ${(_j = (_g = pckg === null || pckg === void 0 ? void 0 : pckg.dependencies) === null || _g === void 0 ? void 0 : _g[(_h = item === null || item === void 0 ? void 0 : item.package) === null || _h === void 0 ? void 0 : _h.dependencyId]) === null || _j === void 0 ? void 0 : _j.name} package does not have a link with that name (no 'Contain' type instance with value ' ${item.package.containValue}'). It might mean that ${(_m = (_k = pckg === null || pckg === void 0 ? void 0 : pckg.dependencies) === null || _k === void 0 ? void 0 : _k[(_l = item === null || item === void 0 ? void 0 : item.package) === null || _l === void 0 ? void 0 : _l.dependencyId]) === null || _m === void 0 ? void 0 : _m.name} package have a breaking change in its new version.`);
                }
                else if (item.type) {
                    newId = ids[idsIndex++];
                }
                if (oldId && newId)
                    difference[oldId] = newId;
                if (item.type || item.package) {
                    for (let l = 0; l < links.length; l++) {
                        const link = links[l];
                        if (link.from === oldId) {
                            global[l].from = newId;
                        }
                        if (link.to === oldId) {
                            global[l].to = newId;
                        }
                        if (link.type === oldId && !link._) {
                            global[l].type = newId;
                        }
                        if (link.id === oldId) {
                            global[l].id = newId;
                        }
                    }
                }
            }
            const resultGlobal = global.filter(l => !l.package);
            return { global: resultGlobal, difference };
        });
    }
    validate(pckg, errors) {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        if (pckg.strict)
            return;
        if (!((_a = pckg === null || pckg === void 0 ? void 0 : pckg.package) === null || _a === void 0 ? void 0 : _a.name))
            errors.push(`!pckg?.package?.name`);
        if (!((_b = pckg === null || pckg === void 0 ? void 0 : pckg.package) === null || _b === void 0 ? void 0 : _b.version))
            errors.push(`!pckg?.package?.version`);
        if (pckg.hasOwnProperty('dependencies')) {
            if (typeof (pckg === null || pckg === void 0 ? void 0 : pckg.dependencies) === 'object') {
                const keys = Object.keys(pckg === null || pckg === void 0 ? void 0 : pckg.dependencies);
                for (let i = 0; i < keys.length; i++) {
                    const dep = pckg === null || pckg === void 0 ? void 0 : pckg.dependencies[keys[i]];
                    if (typeof (dep) === 'object') {
                        if (typeof (dep.name) !== 'string')
                            errors.push(`!dep[${i}].name`);
                    }
                    else
                        errors.push(`!pckg.dependencies[keys[${i}]]`);
                }
            }
            else
                errors.push('!pckg?.dependencies');
        }
        if (Object.prototype.toString.call(pckg === null || pckg === void 0 ? void 0 : pckg.data) === '[object Array]') {
            for (let i = 0; i < (pckg === null || pckg === void 0 ? void 0 : pckg.data.length); i++) {
                const item = pckg === null || pckg === void 0 ? void 0 : pckg.data[i];
                if (typeof (item) === 'object') {
                    if (typeof (item === null || item === void 0 ? void 0 : item.id) !== 'string' && typeof (item === null || item === void 0 ? void 0 : item.id) !== 'number')
                        errors.push(`!item[${i}].id`);
                    if (typeof (item === null || item === void 0 ? void 0 : item.package) === 'object') {
                        if (typeof ((_c = item === null || item === void 0 ? void 0 : item.package) === null || _c === void 0 ? void 0 : _c.dependencyId) !== 'number')
                            errors.push(`!item[${i}].package?.dependencyId`);
                        if (typeof ((_d = item === null || item === void 0 ? void 0 : item.package) === null || _d === void 0 ? void 0 : _d.containValue) !== 'string')
                            errors.push(`!item[${i}].package?.containValue`);
                        if (!((_e = pckg.dependencies) === null || _e === void 0 ? void 0 : _e[item.package.dependencyId]))
                            errors.push(`!pckg.dependencies?.[pckg.data[${i}].package.dependencyId,(${item.package.dependencyId})]`);
                    }
                    else {
                        if (typeof (item === null || item === void 0 ? void 0 : item.type) !== 'string' && typeof (item === null || item === void 0 ? void 0 : item.type) !== 'number')
                            errors.push(`!item[${i}(id:${item === null || item === void 0 ? void 0 : item.id})].type`);
                        if (item.hasOwnProperty('from') && typeof (item === null || item === void 0 ? void 0 : item.from) !== 'undefined')
                            if (typeof (item === null || item === void 0 ? void 0 : item.from) !== 'string' && typeof (item === null || item === void 0 ? void 0 : item.from) !== 'number')
                                errors.push(`!item[${i}(id:${item === null || item === void 0 ? void 0 : item.id})].from`);
                        if (item.hasOwnProperty('to') && typeof (item === null || item === void 0 ? void 0 : item.to) !== 'undefined')
                            if (typeof (item === null || item === void 0 ? void 0 : item.to) !== 'string' && typeof (item === null || item === void 0 ? void 0 : item.to) !== 'number')
                                errors.push(`!item[${i}(id:${item === null || item === void 0 ? void 0 : item.id})].to`);
                        if (item.value) {
                            if (typeof (item === null || item === void 0 ? void 0 : item.value) !== 'object')
                                errors.push(`!item[${i}].value`);
                            else {
                                if (typeof ((_f = item === null || item === void 0 ? void 0 : item.value) === null || _f === void 0 ? void 0 : _f.value) !== 'number' && typeof ((_g = item === null || item === void 0 ? void 0 : item.value) === null || _g === void 0 ? void 0 : _g.value) !== 'string' && typeof ((_h = item === null || item === void 0 ? void 0 : item.value) === null || _h === void 0 ? void 0 : _h.value) !== 'object')
                                    errors.push(`!item[${i}].value.value`);
                            }
                        }
                    }
                }
                else
                    errors.push(`!pckg.dependencies[keys[${i}]]`);
            }
        }
        else
            errors.push('!pckg?.dependencies');
    }
    import(pckg) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const errors = [];
            try {
                this.validate(pckg, errors);
                if (errors.length)
                    return { errors };
                const { data, counter, dependedLinks, packageId, namespaceId } = yield this.deserialize(pckg, errors);
                if (errors.length)
                    return { errors };
                const { sorted } = sort(pckg, data, errors, {
                    id: 'id',
                    from: 'from',
                    to: 'to',
                    type: 'type',
                });
                if (errors.length)
                    return { errors };
                const mutated = {};
                const ids = yield this.client.reserve(counter);
                const { global, difference } = yield this.globalizeIds(pckg, ids, sorted);
                if ((_a = pckg.errors) === null || _a === void 0 ? void 0 : _a.length) {
                    return { errors: pckg.errors };
                }
                yield this.insertItems(pckg, global, counter, dependedLinks, errors, mutated);
                if (errors.length)
                    return { errors };
                return { ids, errors, namespaceId: difference[namespaceId], packageId: difference[packageId] };
            }
            catch (e) {
                log('import error');
                const serializedError = serializeError(e);
                ;
                errors.push(serializedError);
            }
            return { ids: [], errors };
        });
    }
    update(packageId, pckg) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const errors = [];
            try {
                this.validate(pckg, errors);
                if (errors.length)
                    return { errors };
                const { data, counter, dependedLinks, packageId, namespaceId } = yield this.deserialize(pckg, errors);
                if (errors.length)
                    return { errors };
                const { sorted } = sort(pckg, data, errors, {
                    id: 'id',
                    from: 'from',
                    to: 'to',
                    type: 'type',
                });
                if (errors.length)
                    return { errors };
                const mutated = {};
                const ids = yield this.client.reserve(counter);
                const { global, difference } = yield this.globalizeIds(pckg, ids, sorted);
                if ((_a = pckg.errors) === null || _a === void 0 ? void 0 : _a.length) {
                    return { errors: pckg.errors };
                }
                console.log('update', { packageId, pckg, global, difference, ids, sorted, data });
            }
            catch (e) {
                log('import error');
                const serializedError = serializeError(e);
                ;
                errors.push(serializedError);
            }
            return { ids: [], errors };
        });
    }
    selectLinks(options) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const Contain = yield this.client.id('@deep-foundation/core', 'Contain');
            const Package = yield this.client.id('@deep-foundation/core', 'Package');
            const PackageVersion = yield this.client.id('@deep-foundation/core', 'PackageVersion');
            const result = yield this.client.select({
                _or: [
                    { id: { _eq: options.packageLinkId } },
                    { type_id: { _eq: Contain }, from: { id: { _eq: options.packageLinkId } } },
                    { in: { type_id: { _eq: Contain }, from: { id: { _eq: options.packageLinkId } } } },
                    { type_id: { _eq: PackageVersion }, to: { id: { _eq: options.packageLinkId } } },
                ],
                order_by: { id: 'asc' }
            }, {
                name: 'LOAD_PACKAGE_LINKS',
                returning: `
          id type_id from_id to_id value
          contains: in(where: { type_id: { _eq: ${Contain} }, string: { value: { _is_null: false } }, from: { type_id: { _eq: ${Package} } } }) {
            id value
            package: from {
              id value
              versions: in(where: {type_id: {_eq: ${PackageVersion}}, string: { value: { _is_null: false } }}) {
                id
                value
              }
            }
          }
          _type:type {
            id value
            contains: in(where: { type_id: { _eq: ${Contain} }, string: { value: { _is_null: false } }, from: { type_id: { _eq: ${Package} } } }) {
              id value
              package: from {
                id value
                versions: in(where: {type_id: {_eq: ${PackageVersion}}, string: { value: { _is_null: false } }}) {
                  id
                  value
                }
              }
            }
          }
          _from:from {
            id
            contains: in(where: { type_id: { _eq: ${Contain} }, string: { value: { _is_null: false } }, from: { type_id: { _eq: ${Package} } } }) {
              id value
              package: from {
                id value
                versions: in(where: {type_id: {_eq: ${PackageVersion}}, string: { value: { _is_null: false } }}) {
                  id
                  value
                }
              }
            }
          }
          _to:to {
            id
            contains: in(where: { type_id: { _eq: ${Contain} }, string: { value: { _is_null: false } }, from: { type_id: { _eq: ${Package} } } }) {
              id value
              package: from {
                id value
                versions: in(where: {type_id: {_eq: ${PackageVersion}}, string: { value: { _is_null: false } }}) {
                  id
                  value
                }
              }
            }
          }
        `
            });
            return minilinks((_a = (result)) === null || _a === void 0 ? void 0 : _a.data);
        });
    }
    deserialize(pckg, errors = []) {
        return __awaiter(this, void 0, void 0, function* () {
            const Contain = yield this.client.id('@deep-foundation/core', 'Contain');
            const Join = yield this.client.id('@deep-foundation/core', 'Join');
            const Package = yield this.client.id('@deep-foundation/core', 'Package');
            const PackageNamespace = yield this.client.id('@deep-foundation/core', 'PackageNamespace');
            const Active = yield this.client.id('@deep-foundation/core', 'PackageActive');
            const Version = yield this.client.id('@deep-foundation/core', 'PackageVersion');
            const containsHash = {};
            let counter = 0;
            const dependedLinks = [];
            let packageId;
            const data = [];
            packageId = 'package';
            if (pckg.package.name !== corePackage) {
                containsHash[packageId] = ++counter;
                data.push({
                    id: packageId,
                    type: Package,
                    value: { value: pckg.package.name },
                    _: true,
                });
            }
            data.push(...pckg.data.map(l => (Object.assign(Object.assign({}, l), { value: l.value ? Object.assign({}, l.value) : undefined }))));
            for (let l = 0; l < data.length; l++) {
                const item = data[l];
                const local = item.id;
                if (containsHash[local])
                    item.id = containsHash[local];
                else
                    containsHash[local] = (item.id = ++counter);
                if (item.package)
                    dependedLinks.push(item);
            }
            for (let l = 0; l < data.length; l++) {
                const item = data[l];
                if (item.type && !item._) {
                    if (!containsHash[item.type])
                        errors.push(`${item.id} type ${item.type} !contain ${containsHash[item.type]}`);
                    item.type = containsHash[item.type];
                }
                if (item.from) {
                    if (!containsHash[item.from])
                        errors.push(`${item.id} from ${item.from} !contain ${containsHash[item.from]}`);
                    item.from = containsHash[item.from];
                }
                if (item.to) {
                    if (!containsHash[item.to])
                        errors.push(`${item.id} to ${item.to} !contain ${containsHash[item.to]}`);
                    item.to = containsHash[item.to];
                }
            }
            if (pckg.package.name === corePackage) {
                packageId = 'package';
                containsHash[packageId] = ++counter;
                data.push({
                    id: packageId,
                    type: Package,
                    value: { value: pckg.package.name },
                    _: true,
                });
            }
            const containsArray = Object.keys(containsHash);
            for (let c = 0; c < containsArray.length; c++) {
                const containKey = containsArray[c];
                if (containsHash[containKey] != containsHash[packageId] && !!data.find(l => (l === null || l === void 0 ? void 0 : l.id) === containsHash[containKey] && !(l === null || l === void 0 ? void 0 : l.package))) {
                    data.push({
                        id: ++counter,
                        type: Contain,
                        from: containsHash[packageId],
                        to: containsHash[containKey],
                        value: { value: containKey },
                        _: true,
                    });
                }
            }
            const n = yield this.fetchPackageNamespaceId(pckg.package.name, this.client);
            if (n.error)
                errors.push(n.error);
            let namespaceId = n.namespaceId;
            if (!namespaceId) {
                namespaceId = ++counter;
                data.push({
                    id: namespaceId,
                    type: PackageNamespace,
                    value: { value: pckg.package.name },
                    _: true,
                });
                data.push({
                    id: ++counter,
                    type: Active,
                    to: containsHash[packageId],
                    from: namespaceId,
                    _: true,
                });
            }
            data.push({
                id: ++counter,
                type: Version,
                to: containsHash[packageId],
                from: namespaceId,
                value: { value: pckg.package.version },
                _: true,
            });
            data.push({
                id: ++counter,
                type: Contain,
                from: namespaceId,
                to: containsHash[packageId],
                _: true,
            });
            if (pckg.package.name !== corePackage) {
                const packages = yield this.client.id('deep', 'users', 'packages');
                data.push({
                    id: ++counter,
                    type: Join,
                    from: containsHash[packageId],
                    to: packages,
                    _: true,
                });
                data.push({
                    id: ++counter,
                    type: Contain,
                    from: packages,
                    to: containsHash[packageId],
                    _: true,
                });
            }
            return { data, errors, counter, dependedLinks, packageId: containsHash[packageId], namespaceId };
        });
    }
    serialize(globalLinks, options, pckg) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
        return __awaiter(this, void 0, void 0, function* () {
            const Contain = yield this.client.id('@deep-foundation/core', 'Contain');
            const names = {};
            for (let l = 0; l < globalLinks.links.length; l++) {
                const globalLink = globalLinks.links[l];
                if (((_a = globalLink === null || globalLink === void 0 ? void 0 : globalLink.contains) === null || _a === void 0 ? void 0 : _a.length) > 1)
                    pckg.errors.push(`Link ${globalLink.id} have more then 1 Contain from package ${JSON.stringify(globalLink === null || globalLink === void 0 ? void 0 : globalLink.contains)}.`);
                if (!((globalLink === null || globalLink === void 0 ? void 0 : globalLink.type_id) === Contain && ((_b = globalLink === null || globalLink === void 0 ? void 0 : globalLink.from) === null || _b === void 0 ? void 0 : _b.id) === options.packageLinkId)
                    && (globalLink === null || globalLink === void 0 ? void 0 : globalLink.id) !== options.packageLinkId) {
                    const name = (_e = (_d = (_c = globalLink === null || globalLink === void 0 ? void 0 : globalLink.contains) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.value) === null || _e === void 0 ? void 0 : _e.value;
                    if (!name)
                        pckg.errors.push(`Link ${globalLink.id} has empty or invalid name: '${name}'.`);
                    if (name === "this")
                        pckg.errors.push(`Link ${globalLink.id} has invalid name: '${name}'. '${name}' is reserved for package itself, so it cannot be used as a name for link that is contained by package.`);
                    if (names[name])
                        pckg.errors.push(`Link ${globalLink.id} has name '${name}' that is already used by ${names[name]} link.`);
                    names[name] = globalLink.id;
                }
            }
            const localLinks = {};
            const lbyg = {};
            const gbyl = {};
            let localCounter = 1;
            const addLocalLink = (gId, localLink) => {
                if (!localLink.id)
                    localLink.id = localCounter++;
                gbyl[localLink.id] = gId;
                lbyg[gId] = localLink.id;
                localLinks[localLink.id] = localLink;
                return localLink;
            };
            for (let g = 0; g < globalLinks.links.length; g++) {
                const link = globalLinks.links[g];
                if (!((link === null || link === void 0 ? void 0 : link.type_id) === Contain && ((_f = link === null || link === void 0 ? void 0 : link.from) === null || _f === void 0 ? void 0 : _f.id) === options.packageLinkId)
                    && (link === null || link === void 0 ? void 0 : link.id) !== options.packageLinkId) {
                    const name = (_j = (_h = (_g = link === null || link === void 0 ? void 0 : link.contains) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.value) === null || _j === void 0 ? void 0 : _j.value;
                    addLocalLink(link.id, { id: name });
                }
            }
            const dependencies = [];
            const getDependencyIndex = (link) => {
                var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
                const alreadyIndex = dependencies.findIndex(l => { var _a, _b, _c, _d; return l.name === ((_d = (_c = (_b = (_a = link === null || link === void 0 ? void 0 : link.contains) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.package) === null || _c === void 0 ? void 0 : _c.value) === null || _d === void 0 ? void 0 : _d.value); });
                if (!!~alreadyIndex) {
                    return alreadyIndex;
                }
                else {
                    if (!((_d = (_c = (_b = (_a = link === null || link === void 0 ? void 0 : link.contains) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.package) === null || _c === void 0 ? void 0 : _c.value) === null || _d === void 0 ? void 0 : _d.value))
                        pckg.errors.push(`!link?.contains?.[0]?.package?.value?.value for ${link === null || link === void 0 ? void 0 : link.id}`);
                    if (!((_k = (_j = (_h = (_g = (_f = (_e = link === null || link === void 0 ? void 0 : link.contains) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.package) === null || _g === void 0 ? void 0 : _g.versions) === null || _h === void 0 ? void 0 : _h[0]) === null || _j === void 0 ? void 0 : _j.value) === null || _k === void 0 ? void 0 : _k.value))
                        pckg.errors.push(`!link?.contains?.[0]?.package?.versions?.[0]?.value?.value for ${link === null || link === void 0 ? void 0 : link.id}`);
                    dependencies.push({ name: (_p = (_o = (_m = (_l = link === null || link === void 0 ? void 0 : link.contains) === null || _l === void 0 ? void 0 : _l[0]) === null || _m === void 0 ? void 0 : _m.package) === null || _o === void 0 ? void 0 : _o.value) === null || _p === void 0 ? void 0 : _p.value, version: (_v = (_u = (_t = (_s = (_r = (_q = link === null || link === void 0 ? void 0 : link.contains) === null || _q === void 0 ? void 0 : _q[0]) === null || _r === void 0 ? void 0 : _r.package) === null || _s === void 0 ? void 0 : _s.versions) === null || _t === void 0 ? void 0 : _t[0]) === null || _u === void 0 ? void 0 : _u.value) === null || _v === void 0 ? void 0 : _v.value });
                    return dependencies.length - 1;
                }
            };
            const getDependencyId = (link) => {
                var _a, _b, _c;
                if (!(link === null || link === void 0 ? void 0 : link.id)) {
                    return link === null || link === void 0 ? void 0 : link.id;
                }
                const dependencyId = getDependencyIndex(link);
                const containValue = (_c = (_b = (_a = link === null || link === void 0 ? void 0 : link.contains) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value) === null || _c === void 0 ? void 0 : _c.value;
                const exists = Object.values(localLinks).find((l) => { var _a, _b; return ((_a = l === null || l === void 0 ? void 0 : l.package) === null || _a === void 0 ? void 0 : _a.dependencyId) === dependencyId && ((_b = l === null || l === void 0 ? void 0 : l.package) === null || _b === void 0 ? void 0 : _b.containValue) === containValue; });
                const result = exists || addLocalLink(link === null || link === void 0 ? void 0 : link.id, {
                    package: { dependencyId, containValue }
                });
                return result;
            };
            for (let g = 0; g < globalLinks.links.length; g++) {
                const globalLink = globalLinks.links[g];
                if (!((globalLink === null || globalLink === void 0 ? void 0 : globalLink.type_id) === Contain && ((_k = globalLink === null || globalLink === void 0 ? void 0 : globalLink.from) === null || _k === void 0 ? void 0 : _k.id) === options.packageLinkId)
                    && (globalLink === null || globalLink === void 0 ? void 0 : globalLink.id) !== options.packageLinkId) {
                    const localLink = localLinks[lbyg[globalLink.id]];
                    if (localLink) {
                        if (globalLink.type_id) {
                            if (globalLink.type) {
                                localLink.type_id = (_l = localLinks[lbyg[globalLink.type_id]]) === null || _l === void 0 ? void 0 : _l.id;
                                if (typeof localLink.type_id !== 'string') {
                                    pckg.errors.push(`Link '${globalLink.id}' is serialized as '${localLink.id}': its 'type_id' has invalid value '${localLink.type_id}' converted from '${globalLink.type_id}'.`);
                                }
                            }
                            else if (globalLink._type) {
                                localLink.type_id = (_m = getDependencyId(globalLink._type)) === null || _m === void 0 ? void 0 : _m.id;
                                if (!Number.isInteger(localLink.type_id)) {
                                    pckg.errors.push(`Link '${globalLink.id}' is serialized as '${localLink.id}': its 'type_id' has invalid value '${localLink.type_id}' converted from '${globalLink._type}'.`);
                                }
                            }
                            else {
                                pckg.errors.push(`Unable to determine 'type_id' for link '${globalLink.id}' that is serialized as '${localLink.id}'.`);
                            }
                        }
                        if (globalLink.from_id) {
                            if (globalLink.from) {
                                localLink.from_id = (_o = localLinks[lbyg[globalLink.from_id]]) === null || _o === void 0 ? void 0 : _o.id;
                                if (typeof localLink.from_id !== 'string') {
                                    pckg.errors.push(`Link '${globalLink.id}' is serialized as '${localLink.id}': its 'from_id' has invalid value '${localLink.from_id}' converted from '${globalLink.from_id}'.`);
                                }
                            }
                            else if (globalLink._from) {
                                localLink.from_id = (_p = getDependencyId(globalLink._from)) === null || _p === void 0 ? void 0 : _p.id;
                                if (!Number.isInteger(localLink.from_id)) {
                                    pckg.errors.push(`Link '${globalLink.id}' is serialized as '${localLink.id}': its 'from_id' has invalid value '${localLink.from_id}' converted from '${globalLink._from}'.`);
                                }
                            }
                            else {
                                pckg.errors.push(`Unable to determine 'from_id' for link '${globalLink.id}' that is serialized as '${localLink.id}'.`);
                            }
                        }
                        if (globalLink.to_id) {
                            if (globalLink.to) {
                                localLink.to_id = (_q = localLinks[lbyg[globalLink.to_id]]) === null || _q === void 0 ? void 0 : _q.id;
                                if (typeof localLink.to_id !== 'string') {
                                    pckg.errors.push(`Link '${globalLink.id}' is serialized as '${localLink.id}': its 'from_id' has invalid value '${localLink.to_id}' converted from '${globalLink.to_id}'.`);
                                }
                            }
                            else if (globalLink._to) {
                                localLink.to_id = (_r = getDependencyId(globalLink._to)) === null || _r === void 0 ? void 0 : _r.id;
                                if (!Number.isInteger(localLink.to_id)) {
                                    pckg.errors.push(`Link '${globalLink.id}' is serialized as '${localLink.id}': its 'from_id' has invalid value '${localLink.to_id}' converted from '${globalLink._to}'.`);
                                }
                            }
                            else {
                                pckg.errors.push(`Unable to determine 'to_id' for link '${globalLink.id}' that is serialized as '${localLink.id}'.`);
                            }
                        }
                        if (globalLink.value) {
                            localLink.value = { value: (_s = globalLink === null || globalLink === void 0 ? void 0 : globalLink.value) === null || _s === void 0 ? void 0 : _s.value };
                        }
                    }
                }
            }
            pckg.data = Object.values(localLinks).map((l) => (l.type_id ? {
                id: l.id,
                type: l.type_id,
                from: l.from_id,
                to: l.to_id,
                value: l.value,
            } : Object.assign({}, l)));
            pckg.dependencies = dependencies;
            return pckg;
        });
    }
    export(options) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        return __awaiter(this, void 0, void 0, function* () {
            const globalLinks = yield this.selectLinks(options);
            const Package = yield this.client.id('@deep-foundation/core', 'Package');
            const PackageVersion = yield this.client.id('@deep-foundation/core', 'PackageVersion');
            const versionLink = (_a = globalLinks.types[PackageVersion]) === null || _a === void 0 ? void 0 : _a[0];
            const packageLink = (_b = globalLinks.types[Package]) === null || _b === void 0 ? void 0 : _b[0];
            const pckg = {
                package: { name: (_c = packageLink === null || packageLink === void 0 ? void 0 : packageLink.value) === null || _c === void 0 ? void 0 : _c.value, version: (_d = versionLink === null || versionLink === void 0 ? void 0 : versionLink.value) === null || _d === void 0 ? void 0 : _d.value },
                data: [],
                errors: []
            };
            if (pckg.package.name === '@deep-foundation/core') {
                pckg.strict = true;
            }
            if (!packageLink)
                pckg.errors.push(`Failed to fetch Package link for package with id ${options.packageLinkId}.`);
            if (!versionLink)
                pckg.errors.push(`Failed to fetch PackageVersion link for package with id ${options.packageLinkId}.`);
            if (!((_e = pckg === null || pckg === void 0 ? void 0 : pckg.package) === null || _e === void 0 ? void 0 : _e.name))
                pckg.errors.push(`Package name ('${(_f = pckg === null || pckg === void 0 ? void 0 : pckg.package) === null || _f === void 0 ? void 0 : _f.name}') is missing or invalid in Package link with id ${packageLink === null || packageLink === void 0 ? void 0 : packageLink.id}.`);
            if (!((_g = pckg === null || pckg === void 0 ? void 0 : pckg.package) === null || _g === void 0 ? void 0 : _g.version))
                pckg.errors.push(`Package version ('${(_h = pckg === null || pckg === void 0 ? void 0 : pckg.package) === null || _h === void 0 ? void 0 : _h.version}') is missing or invalid in PackageVersion link with id ${versionLink === null || versionLink === void 0 ? void 0 : versionLink.id}.`);
            if ((_j = pckg === null || pckg === void 0 ? void 0 : pckg.errors) === null || _j === void 0 ? void 0 : _j.length)
                return pckg;
            const ml = minilinks(globalLinks.links.filter(l => l.id !== (versionLink === null || versionLink === void 0 ? void 0 : versionLink.id)));
            const { sorted } = sort(pckg, ml.links, pckg.errors, {
                id: 'id',
                from: 'from_id',
                to: 'to_id',
                type: 'type_id',
            });
            ml.links = ml._traveled(sorted);
            yield this.serialize(ml, options, pckg);
            this.validate(pckg, pckg.errors);
            return pckg;
        });
    }
}
//# sourceMappingURL=packager.js.map