import 'dotenv/config'; import sql from 'mssql'; import chalk from 'chalk'; import * as p from '@clack/prompts'; import LibDashStore from '../src/index.js'; const config = { server: process.env.MSSQL_SERVER, database: process.env.MSSQL_DATABASE, user: process.env.MSSQL_USER, password: process.env.MSSQL_PASSWORD, options: { encrypt: false, trustServerCertificate: true, }, }; function printResult(label, value) { p.log.step(chalk.cyan(label)); const text = value === undefined ? chalk.dim('undefined') : typeof value === 'string' ? value : JSON.stringify(value, null, 2); console.log(chalk.white(text)); console.log(); } async function askText(message, { placeholder, validate } = {}) { const value = await p.text({ message, placeholder, validate }); if (p.isCancel(value)) return null; return value.trim(); } async function askInt(message, placeholder = '1') { return askText(message, { placeholder, validate: (v) => (!/^\d+$/.test(v?.trim() ?? '') ? 'Integer required' : undefined), }); } async function shutdown(pool, code = 0) { try { await pool.close(); } catch { // ignore } process.exit(code); } const METHODS = [ { value: 'company.create', label: 'company.create', hint: '{name} → id' }, { value: 'company.list', label: 'company.list', hint: '→ rows' }, { value: 'company.setDefaultLang', label: 'company.setDefaultLang', hint: 'companyId, langId' }, { value: 'company.setRootCategory', label: 'company.setRootCategory', hint: 'companyId, categoryId' }, { value: 'company.delete', label: 'company.delete', hint: 'companyId' }, { value: 'company.getByCompanyUserId', label: 'company.getByCompanyUserId', hint: 'id → tuple' }, { value: 'lang.create', label: 'lang.create', hint: 'iso639 → id' }, { value: 'lang.list', label: 'lang.list', hint: '→ rows' }, { value: 'lang.delete', label: 'lang.delete', hint: 'id' }, { value: 'category.create', label: 'category.create', hint: '{parent_id, sort} → id' }, { value: 'category.getTree', label: 'category.getTree', hint: 'rootId → rows' }, { value: 'companyuser.add', label: 'companyuser.add', hint: 'companyId, authId → id' }, { value: 'companyuser.getByEmail', label: 'companyuser.getByEmail', hint: 'email → ids' }, { value: 'google_auth.add', label: 'google_auth.add', hint: 'email → authId' }, { value: 'google_auth.list', label: 'google_auth.list', hint: '→ rows' }, { value: 'google_auth.del', label: 'google_auth.del', hint: 'id' }, { value: 'initialize', label: 'initialize', hint: 'ensure schema (no purge)' }, { value: 'purge', label: chalk.red('purge'), hint: 'drop all · exit' }, { value: 'exit', label: 'exit', hint: 'quit without purge' }, ]; async function runMethod(client, action) { switch (action) { case 'company.create': { const name = await askText('Name', { placeholder: 'Acme', validate: (v) => (!v?.trim() ? 'Required' : undefined), }); if (name == null) return; return ['id', await client.company.create({ name })]; } case 'company.list': { return ['rows', await client.company.list()]; } case 'company.setDefaultLang': { const companyId = await askInt('Company id'); if (companyId == null) return; const languageId = await askInt('Language id'); if (languageId == null) return; await client.company.setDefaultLang(Number(companyId), Number(languageId)); return ['ok', true]; } case 'company.setRootCategory': { const companyId = await askInt('Company id'); if (companyId == null) return; const categoryId = await askInt('Category id'); if (categoryId == null) return; await client.company.setRootCategory(Number(companyId), Number(categoryId)); return ['ok', true]; } case 'company.delete': { const companyId = await askInt('Company id'); if (companyId == null) return; await client.company.delete(Number(companyId)); return ['ok', true]; } case 'company.getByCompanyUserId': { const id = await askInt('Company user id'); if (id == null) return; return [ '[id, defaultLangId, rootCategoryId, name]', await client.company.getByCompanyUserId(Number(id)), ]; } case 'lang.create': { const iso639 = await askText('ISO 639', { placeholder: 'de', validate: (v) => (!v?.trim() ? 'Required' : undefined), }); if (iso639 == null) return; return ['id', await client.lang.create(iso639)]; } case 'lang.list': { return ['rows', await client.lang.list()]; } case 'lang.delete': { const id = await askInt('Language id'); if (id == null) return; await client.lang.delete(Number(id)); return ['ok', true]; } case 'category.create': { const parentRaw = await askText('parent_id (null as empty)', { placeholder: '', validate: (v) => v?.trim() && !/^\d+$/.test(v.trim()) ? 'Integer or empty' : undefined, }); if (parentRaw == null) return; const sortRaw = await askInt('sort', '0'); if (sortRaw == null) return; const parent_id = parentRaw === '' ? null : Number(parentRaw); return ['id', await client.category.create({ parent_id, sort: Number(sortRaw) })]; } case 'category.getTree': { const rootId = await askInt('Root category id'); if (rootId == null) return; return ['rows', await client.category.getTree(Number(rootId))]; } case 'companyuser.add': { const companyId = await askInt('Company id'); if (companyId == null) return; const authId = await askInt('Auth id'); if (authId == null) return; return ['id', await client.companyuser.add(Number(companyId), Number(authId))]; } case 'companyuser.getByEmail': { const email = await askText('Email', { placeholder: 'user@example.com', validate: (v) => (!v?.trim() ? 'Required' : undefined), }); if (email == null) return; return ['ids', await client.companyuser.getByEmail(email)]; } case 'google_auth.add': { const email = await askText('Email', { placeholder: 'user@example.com', validate: (v) => (!v?.trim() ? 'Required' : undefined), }); if (email == null) return; return ['authId', await client.google_auth.add(email)]; } case 'google_auth.list': { return ['rows', await client.google_auth.list()]; } case 'google_auth.del': { const id = await askInt('Auth id'); if (id == null) return; await client.google_auth.del(Number(id)); return ['ok', true]; } case 'initialize': { await client.initialize(); return ['ok', true]; } default: return null; } } async function main() { console.clear(); p.intro(chalk.bgMagenta.black(' libdashstore ') + chalk.dim(' api tester')); const spin = p.spinner(); spin.start('Connecting to MSSQL…'); let pool; try { pool = await sql.connect(config); } catch (err) { spin.stop(chalk.red('Connection failed')); p.log.error(err.message); p.outro(chalk.red('Aborted')); process.exit(1); } spin.message('Initializing schema…'); let client; try { client = await new LibDashStore(pool); spin.stop(chalk.green('Ready')); } catch (err) { spin.stop(chalk.red('Initialize failed')); p.log.error(err.message); await shutdown(pool, 1); } p.note( [ chalk.dim(`${config.server} / ${config.database}`), chalk.dim('initialize = ensure schema · purge ends session'), ].join('\n'), 'Connected', ); while (true) { const action = await p.select({ message: 'API method', options: METHODS, }); if (p.isCancel(action) || action === 'exit') { p.outro(chalk.dim('Bye')); await shutdown(pool, 0); } if (action === 'purge') { const run = p.spinner(); run.start('Purging…'); await client.purge(); run.stop(chalk.green('purge')); p.outro(chalk.red('Database purged — exiting')); await shutdown(pool, 0); } try { const result = await runMethod(client, action); if (result) { p.log.success(action); printResult(result[0], result[1]); } } catch (err) { p.log.error(err.message); console.log(chalk.dim(err.stack?.split('\n').slice(1, 4).join('\n') ?? '')); console.log(); } } } main().catch(async (err) => { console.error(chalk.red(err.stack ?? err.message)); process.exit(1); });