UNPKG

@grouparoo/core

Version:
350 lines (349 loc) 14.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SourceDestroy = exports.SourceDefaultPropertyOptions = exports.SourcePreview = exports.SourceConnectionOptions = exports.SourceBootstrapUniqueProperty = exports.SourceGenerateSampleRecords = exports.SourceEdit = exports.SourceView = exports.SourceCreate = exports.SourceConnectionApps = exports.SourcesList = void 0; const actionhero_1 = require("actionhero"); const authenticatedAction_1 = require("../classes/actions/authenticatedAction"); const App_1 = require("../models/App"); const Source_1 = require("../models/Source"); const GrouparooRecord_1 = require("../models/GrouparooRecord"); const optionHelper_1 = require("../modules/optionHelper"); const configWriter_1 = require("../modules/configWriter"); const Property_1 = require("../models/Property"); const tableSpeculation_1 = require("../modules/tableSpeculation"); const apiData_1 = require("../modules/apiData"); const runMode_1 = require("../modules/runMode"); class SourcesList extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "sources:list"; this.description = "list all the sources"; this.outputExample = {}; this.permission = { topic: "source", mode: "read" }; this.inputs = { limit: { required: true, default: 100, formatter: apiData_1.APIData.ensureNumber }, offset: { required: true, default: 0, formatter: apiData_1.APIData.ensureNumber }, state: { required: false }, modelId: { required: false }, order: { required: false, formatter: apiData_1.APIData.ensureArray, default: [ ["appId", "desc"], ["createdAt", "asc"], ], }, }; } async runWithinTransaction({ params }) { const where = {}; if (params.state) where["state"] = params.state; if (params.modelId) where["modelId"] = params.modelId; const sources = await Source_1.Source.scope(null).findAll({ where, limit: params.limit, offset: params.offset, order: params.order, }); const total = await Source_1.Source.scope(null).count({ where }); return { total, sources: await Promise.all(sources.map((source) => source.apiData())), }; } } exports.SourcesList = SourcesList; class SourceConnectionApps extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "sources:connectionApps"; this.description = "enumerate the connection and app pairs for creating a new source"; this.outputExample = {}; this.permission = { topic: "source", mode: "read" }; } async runWithinTransaction() { const apps = await App_1.App.findAll(); const existingAppTypes = apps.map((a) => a.type); const connectionApps = []; let importConnections = []; actionhero_1.api.plugins.plugins.forEach((plugin) => { if (plugin.connections) { plugin.connections .filter((c) => c.direction === "import") .filter((c) => { let match = false; for (const app of c.apps) { if (existingAppTypes.includes(app)) match = true; } return match; }) .map((c) => importConnections.push(c)); } }); for (const app of apps) { for (const connection of importConnections) { if (connection.apps.includes(app.type)) { const methods = Object.keys(connection.methods).filter((key) => typeof connection.methods[key] === "function"); connectionApps.push({ app: await app.apiData(), connection: { ...connection, methods, }, }); } } } const environmentVariableOptions = optionHelper_1.OptionHelper.getEnvironmentVariableOptionsForTopic("source"); return { connectionApps, environmentVariableOptions }; } } exports.SourceConnectionApps = SourceConnectionApps; class SourceCreate extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:create"; this.description = "create a source"; this.outputExample = {}; this.permission = { topic: "source", mode: "write" }; this.inputs = { appId: { required: true }, modelId: { required: true }, name: { required: false }, type: { required: true }, state: { required: false }, options: { required: false, formatter: apiData_1.APIData.ensureObject }, mapping: { required: false, formatter: apiData_1.APIData.ensureObject }, }; } async runWithinTransaction({ params }) { const source = await Source_1.Source.create({ appId: params.appId, modelId: params.modelId, name: params.name, type: params.type, }); if (params.options) await source.setOptions(params.options); if (params.mapping) await source.setMapping(params.mapping); if (params.state) await source.update({ state: params.state }); await configWriter_1.ConfigWriter.run(); return { source: await source.apiData() }; } } exports.SourceCreate = SourceCreate; class SourceView extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:view"; this.description = "view a source"; this.outputExample = {}; this.permission = { topic: "source", mode: "read" }; this.inputs = { id: { required: true }, }; } async runWithinTransaction({ params }) { const source = await Source_1.Source.findById(params.id); return { source: await source.apiData() }; } } exports.SourceView = SourceView; class SourceEdit extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:edit"; this.description = "edit a source"; this.outputExample = {}; this.permission = { topic: "source", mode: "write" }; this.inputs = { id: { required: true }, appId: { required: false }, name: { required: false }, type: { required: false }, state: { required: false }, options: { required: false, formatter: apiData_1.APIData.ensureObject }, mapping: { required: false, formatter: apiData_1.APIData.ensureObject }, }; } async runWithinTransaction({ params }) { const source = await Source_1.Source.findById(params.id); if (params.options) await source.setOptions(params.options); if (params.mapping) await source.setMapping(params.mapping); await source.update(params); await configWriter_1.ConfigWriter.run(); return { source: await source.apiData() }; } } exports.SourceEdit = SourceEdit; class SourceGenerateSampleRecords extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:generateSampleRecords"; this.description = "create 3 sample records for this model"; this.permission = { topic: "source", mode: "write" }; this.inputs = { id: { required: true } }; } async runWithinTransaction({ params, }) { const source = await Source_1.Source.findById(params.id); if ((0, runMode_1.getGrouparooRunMode)() !== "cli:config") throw new Error(`this action is only valid in cli:config mode`); if (source.state !== "ready") throw new Error(`source is not ready`); if (!(await source.previewAvailable())) throw new Error(`source does not provide a preview`); let attempt = 0; let records = []; const mapping = await source.getMapping(); const mappingKey = Object.keys(mapping)[0]; const mappingValue = Object.values(mapping)[0]; const preview = await source.sourcePreview(); while (records.length < 3 && attempt < preview.length) { const value = preview[attempt][mappingKey]; if (value) { const record = new GrouparooRecord_1.GrouparooRecord({ modelId: source.modelId }); await record.save(); try { await record.addOrUpdateProperties({ [mappingValue]: value }); records.push(record); } catch (error) { (0, actionhero_1.log)(error, "error"); await record.destroy(); } } attempt++; } return { records: await Promise.all(records.map((record) => record.apiData())), }; } } exports.SourceGenerateSampleRecords = SourceGenerateSampleRecords; class SourceBootstrapUniqueProperty extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:bootstrapUniqueProperty"; this.description = "bootstrap a new unique record property for this source before the mapping is set"; this.outputExample = {}; this.permission = { topic: "source", mode: "write" }; this.inputs = { id: { required: true }, key: { required: false }, type: { required: false, formatter: (p) => p, }, mappedColumn: { required: true }, sourceOptions: { required: false, formatter: apiData_1.APIData.ensureObject }, }; } async runWithinTransaction({ params, }) { const source = await Source_1.Source.findById(params.id); const property = await source.bootstrapUniqueProperty({ mappedColumn: params.mappedColumn, key: params.key, type: params.type, sourceOptions: params.sourceOptions, }); await configWriter_1.ConfigWriter.run(); return { source: await source.apiData(), property: await property.apiData(), }; } } exports.SourceBootstrapUniqueProperty = SourceBootstrapUniqueProperty; class SourceConnectionOptions extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:connectionOptions"; this.description = "return option choices from this source"; this.outputExample = {}; this.permission = { topic: "source", mode: "read" }; this.inputs = { id: { required: true }, options: { required: false, formatter: apiData_1.APIData.ensureObject }, }; } async runWithinTransaction({ params, }) { const source = await Source_1.Source.findById(params.id); return { options: await source.sourceConnectionOptions(params.options) }; } } exports.SourceConnectionOptions = SourceConnectionOptions; class SourcePreview extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:preview"; this.description = "preview the data from this source"; this.outputExample = {}; this.permission = { topic: "source", mode: "read" }; this.inputs = { id: { required: true }, options: { required: false, formatter: apiData_1.APIData.ensureObject }, }; } async runWithinTransaction({ params, }) { const source = await Source_1.Source.findById(params.id); const model = await source.$get("model"); const preview = await source.sourcePreview(params.options); const existingProperties = await Property_1.Property.findAll(); const columnSpeculation = {}; if (preview.length > 0) { const keys = Object.keys(preview[0]); for (const key of keys) { const suggestedPropertyKey = tableSpeculation_1.TableSpeculation.suggestKey(key, model, existingProperties); columnSpeculation[key] = { suggestedPropertyKey, isUnique: tableSpeculation_1.TableSpeculation.isUniqueColumn(key), type: tableSpeculation_1.TableSpeculation.columnType(key, preview.map((row) => row[key])), }; } } return { preview, columnSpeculation }; } } exports.SourcePreview = SourcePreview; class SourceDefaultPropertyOptions extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:defaultPropertyOptions"; this.description = "view the default plugin options for a source"; this.outputExample = {}; this.permission = { topic: "source", mode: "read" }; this.inputs = { id: { required: true }, }; } async runWithinTransaction({ params, }) { const source = await Source_1.Source.findById(params.id); return { defaultPropertyOptions: await source.defaultPropertyOptions() }; } } exports.SourceDefaultPropertyOptions = SourceDefaultPropertyOptions; class SourceDestroy extends authenticatedAction_1.AuthenticatedAction { constructor() { super(...arguments); this.name = "source:destroy"; this.description = "destroy a source"; this.outputExample = {}; this.permission = { topic: "source", mode: "write" }; this.inputs = { id: { required: true }, }; } async runWithinTransaction({ params, }) { const source = await Source_1.Source.findById(params.id); await source.destroy(); await configWriter_1.ConfigWriter.run(); return { success: true }; } } exports.SourceDestroy = SourceDestroy;