UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

202 lines (158 loc) 4.85 kB
import type { ModelConfig, Services } from '../typings'; import { ok } from 'node:assert'; import fs from 'fs'; import { Command, Option } from 'commander'; import * as utils from './utils'; import yaml from 'js-yaml'; export function upsertModel(services: Services) { return async (modelPath: string, cmd: any) => { try { const datastore = services.datastores.get(cmd.datastore); if (!datastore) { return; } let modelConfigs: any = null; if (cmd.yaml === true) { modelConfigs = yaml.load(fs.readFileSync(modelPath, 'utf8')); } else { modelConfigs = require(modelPath); if ('default' in modelConfigs) { // @ts-ignore modelConfigs = modelConfigs.default; } } ok(modelConfigs !== null, 'Invalid model configuration'); ok( cmd.multi !== true || cmd.name === undefined, 'Model name can not be used in conjunction of --multi', ); ok( cmd.multi !== true || cmd.description === undefined, 'Model description can not be used in conjunction of --multi', ); const models: ModelConfig[] = []; if (cmd.multi === false) { models.push(modelConfigs); } else if (Array.isArray(modelConfigs)) { models.push(...modelConfigs); } else { models.push(...Object.values(modelConfigs as object)); } for (const modelConfig of models) { if (cmd.name) { modelConfig.name = cmd.name; modelConfig?.indexes?.forEach((index) => { index.collection = cmd.name; }); } if (cmd.description) { modelConfig.description = cmd.description; } let model; try { const { data } = await datastore.createModel(modelConfig); model = data; } catch (err: any) { if (err.response && err.response.status === 409) { const { data } = await datastore.updateModel(modelConfig); model = data; } else { throw err; } } utils.log(model, cmd.format); if (cmd.withIndexes !== true) { continue; } const { data: indexes } = await datastore.createModelIndexes(modelConfig); utils.log(indexes, cmd.format); } } catch (err: any) { if (err.response) { utils.log(err.response.data, cmd.format); return; } utils.log(err, cmd.format); } }; } export function models(services: Services) { return async (cmd: any) => { try { const datastore = services.datastores.get(cmd.datastore); if (!datastore) { return; } const { data } = await datastore.getModels(); utils.log(Object.keys(data), cmd.format); } catch (err: any) { if (err.response) { utils.log(err.response.data, cmd.format); return; } utils.log(err, cmd.format); } }; } export function graph(services: Services) { return async (cmd: any) => { try { const datastore = services.datastores.get(cmd.datastore); if (!datastore) { return; } const { data } = await datastore.getGraph(); utils.log(data, cmd.format); } catch (err: any) { if (err.response) { utils.log(err.response.data, cmd.format); return; } utils.log(err, cmd.format); } }; } export default function register(services: Services, name = 'admin') { const program = new Command(name); program.summary('Administration commands'); // Upsert let c = program.command('upsert <model_path>'); utils.addDatastoreOptions(c, services); c.option('--name <name>', 'Model name') .option('--description <description>', 'Model description') .option('--with-indexes', 'Update indexes', false) .option('--yaml', 'Is model in YAML format', false) .option('--multi', 'Do we import multiple models at once', false) .addOption( new Option('--format <format>', 'Response format').choices([ 'json', 'yaml', ]), ) .description('Admin create or update a model') .action(upsertModel(services)); // Models c = program.command('models'); utils.addDatastoreOptions(c, services); c.addOption( new Option('--format <format>', 'Response format').choices([ 'json', 'yaml', ]), ) .description('Get models available in the Datastore') .action(models(services)); // Graph c = program.command('graph'); utils.addDatastoreOptions(c, services); c.addOption( new Option('--format <format>', 'Response format').choices([ 'json', 'yaml', ]), ) .description('Get the entities dependency graph') .action(graph(services)); return program; }