@grouparoo/core
Version:
The Grouparoo Core
350 lines (349 loc) • 14.5 kB
JavaScript
;
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;