UNPKG

@sugarcube/plugin-sql

Version:

Import and export Sugarcube data and queries from and to SQL databases.

272 lines (249 loc) 6.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _fp = require("lodash/fp"); var _core = require("@sugarcube/core"); // The queries export handles the concatenation of two relations list as well. class Units { constructor(db, pgp, queries, { queriesStore }) { this.db = db; this.pgp = pgp; this.queries = queries; this.queriesStore = queriesStore; } async create(unit) { return this.db.tx(async t => { const { id, existing } = await this.selectOrInsertUnit(unit, t); const downloads = _core.queries.concat(await this.listDownloads(id, t), unit._sc_downloads); const media = _core.queries.concat(await this.listMedia(id, t), unit._sc_media); await this.createDownloads(downloads, id, t); await this.createMedia(media, id, t); await this.createQueries(unit._sc_queries, id, t); await this.createTags(unit._sc_tags, id, t); await this.appendToRun(unit._sc_markers, id, t); return existing; }); } async listAll() { const { listAllUnits } = this.queries; const units = await this.db.manyOrNone(listAllUnits); if (units == null) return []; return Promise.all(units.map(async ({ id, id_hash: idHash, id_fields: idFields, content_fields: contentFields, data, ...unit }) => { const downloads = await this.listDownloads(id, this.db); const media = await this.listMedia(id, this.db); // FIXME: Those three method require implementation const queries = await this.listQueries(id, this.db); const tags = await this.listTags(id, this.db); const markers = await this.listMarkers(id, this.db); return { _sc_id_hash: idHash, _sc_id_fields: idFields, _sc_content_fields: contentFields, _sc_data: data, _sc_media: media, _sc_downloads: downloads, _sc_queries: queries, _sc_tags: tags, _sc_markers: markers, // filter null values map names to _sc naming scheme ...Object.keys(unit).reduce((memo, key) => { const value = unit[key]; if (value == null) return memo; return { [`_sc_${key}`]: value, ...memo }; }, {}) }; })); } async selectOrInsertUnit({ _sc_id_hash: idHash, _sc_id_fields: idFields, _sc_content_hash: contentHash, _sc_content_fields: contentFields, _sc_source: source, _sc_unit_id: unitId, _sc_body: body, _sc_href: href, _sc_author: author, _sc_title: title, _sc_description: description, _sc_language: language, _sc_pubdates: dates, _sc_data: data }, t) { const { showQuery, createQuery } = this.queries; const unit = await t.oneOrNone(showQuery, { idHash }, q => q && q.id); if (unit != null) return { id: unit, existing: true }; const createdAt = (0, _fp.get)("source", dates) ? (0, _fp.get)("source", dates).toISOString() : undefined; const fetchedAt = (0, _fp.get)("fetch", dates) ? (0, _fp.get)("fetch", dates).toISOString() : undefined; const { id } = await t.one(createQuery, { idHash, idFields, contentHash, contentFields, source, unitId, body, href, author, title, description, language, createdAt, fetchedAt, data }); return { id, existing: false }; } async selectOrInsertMarker(marker, t) { const { showMarkerQuery, createMarkerQuery } = this.queries; const markerId = await t.oneOrNone(showMarkerQuery, { marker }, q => q && q.id); return markerId || t.one(createMarkerQuery, { marker }, q => q && q.id); } listDownloads(unitId, t) { const { listDownloadsQuery } = this.queries; return this.listRelations(listDownloadsQuery, unitId, t); } listMedia(unitId, t) { const { listMediaQuery } = this.queries; return this.listRelations(listMediaQuery, unitId, t); } async createDownloads(downloads, unitId, t) { const { createDownloadsQuery } = this.queries; await Promise.all(downloads.map(({ _sc_id_hash: idHash, type, term, md5, sha256, location, ...data }) => t.none(createDownloadsQuery, { idHash, type, term, md5, sha256, location, data, unit: unitId }))); } async createMedia(media, unitId, t) { const { createMediaQuery } = this.queries; await Promise.all(media.map(({ _sc_id_hash: idHash, type, term, ...data }) => t.none(createMediaQuery, { idHash, type, term, data, unit: unitId }))); } async createTags(tags, unitId, t) { const { createTaggedUnitQuery } = this.queries; await Promise.all(tags.map(async ({ label }) => { const queryTag = await this.queriesStore.showQueryTag(label, t); if (queryTag) t.none(createTaggedUnitQuery, { queryTag: queryTag.id, unit: unitId }); })); } async createQueries(queries, unitId, t) { const { createQueryResultQuery } = this.queries; await Promise.all(queries.map(async ({ type, term }) => { const query = await this.queriesStore.selectOrInsert(type, term, t); t.none(createQueryResultQuery, { query, unit: unitId }); })); } async appendToRun(markers, unitId, t) { const { createRunQuery } = this.queries; await Promise.all(markers.map(async marker => { const markerId = await this.selectOrInsertMarker(marker, t); await t.none(createRunQuery, { marker: markerId, unit: unitId }); })); } // eslint-disable-next-line class-methods-use-this async listRelations(query, unitId, t) { const relations = await t.manyOrNone(query, { unitId }); return relations.map(({ id_hash: idHash, data, ...relation }) => ({ _sc_id_hash: idHash, ...data, ...relation })); } } var _default = Units; exports.default = _default;