|  | 
|  | 1 | +#!/usr/bin/env node | 
|  | 2 | + | 
|  | 3 | +import { readFile, writeFile } from 'node:fs/promises' | 
|  | 4 | +import yargs from 'yargs/yargs' | 
|  | 5 | +import { hideBin } from 'yargs/helpers' | 
|  | 6 | +import { cosmiconfig } from 'cosmiconfig' | 
|  | 7 | +import Confirm from 'prompt-confirm' | 
|  | 8 | +import sqldef from './index.js' | 
|  | 9 | + | 
|  | 10 | +// get a reasonable port | 
|  | 11 | +const getPort = (args) => { | 
|  | 12 | +  if (args.port) { | 
|  | 13 | +    return args.port | 
|  | 14 | +  } | 
|  | 15 | +  switch (args.type) { | 
|  | 16 | +    case 'mysql': | 
|  | 17 | +      return 3306 | 
|  | 18 | +    case 'postgres': | 
|  | 19 | +      return 5432 | 
|  | 20 | +    case 'mssql': | 
|  | 21 | +      return 1433 | 
|  | 22 | +  } | 
|  | 23 | +} | 
|  | 24 | + | 
|  | 25 | +// get the current structure of database, as text | 
|  | 26 | +async function getStructure({ type, host, database, user, password, socket, port }) { | 
|  | 27 | +  console.log({ type, host, database, user, password, socket, port }) | 
|  | 28 | +} | 
|  | 29 | + | 
|  | 30 | +// export the current database as a file | 
|  | 31 | +async function handleExport({ file, type, host, database, user, password, socket, port }) { | 
|  | 32 | +  const current = await getStructure({ type, host, database, user, password, socket, port }) | 
|  | 33 | +  await writeFile(file, current) | 
|  | 34 | +} | 
|  | 35 | + | 
|  | 36 | +// import database from file (using diff) | 
|  | 37 | +async function handleImport({ newStruct, type, host, database, user, password, socket, port, dry = false }) { | 
|  | 38 | +  const current = await getStructure({ type, host, database, user, password, socket, port }) | 
|  | 39 | +  if (dry) { | 
|  | 40 | +    console.log('dry') | 
|  | 41 | +  } | 
|  | 42 | +} | 
|  | 43 | + | 
|  | 44 | +const explorer = cosmiconfig('sqldef') | 
|  | 45 | +const r = (await explorer.search()) || { config: {} } | 
|  | 46 | +const { config = {} } = r | 
|  | 47 | +yargs(hideBin(process.argv)) | 
|  | 48 | +  .demandCommand() | 
|  | 49 | +  .usage('Usage: $0 <command> [options]') | 
|  | 50 | +  .help('?') | 
|  | 51 | +  .alias('?', 'help') | 
|  | 52 | + | 
|  | 53 | +  .alias('v', 'version') | 
|  | 54 | +  .example('$0 export --user=cool --password=mysecret --database=mydatabase', 'Save your current schema, from your mysql database, in schema.sql') | 
|  | 55 | +  .example('$0 import --user=cool --password=mysecret --database=mydatabase', 'Update your database to match schema.sql') | 
|  | 56 | + | 
|  | 57 | +  .command( | 
|  | 58 | +    'export', | 
|  | 59 | +    'Export your database to a file', | 
|  | 60 | +    (a) => {}, | 
|  | 61 | +    async (args) => { | 
|  | 62 | +      args.port = args.port || getPort(args) | 
|  | 63 | + | 
|  | 64 | +      const { file, type, host, database, user, password, socket, port = getPort(args) } = args | 
|  | 65 | +      await handleExport({ file, type, host, database, user, password, socket, port, ...config }) | 
|  | 66 | +    } | 
|  | 67 | +  ) | 
|  | 68 | + | 
|  | 69 | +  .command( | 
|  | 70 | +    'import', | 
|  | 71 | +    'Import your database from a file', | 
|  | 72 | +    (a) => {}, | 
|  | 73 | +    async (args) => { | 
|  | 74 | +      const { file, type, host, database, user, password, socket, noConfirm, port = getPort(args) } = args | 
|  | 75 | +      const newStruct = await readFile(file) | 
|  | 76 | +      if (!noConfirm) { | 
|  | 77 | +        await handleImport({ file, type, host, database, user, password, socket, port, ...config, dry: true }) | 
|  | 78 | +        const prompt = new Confirm('Do you want to run this?') | 
|  | 79 | +        if (!(await prompt.run())) { | 
|  | 80 | +          console.error('Export canceled.') | 
|  | 81 | +          process.exit(1) | 
|  | 82 | +        } | 
|  | 83 | +      } | 
|  | 84 | +      await handleImport({ newStruct, type, host, database, user, password, socket, port, ...config, dry: false }) | 
|  | 85 | +    } | 
|  | 86 | +  ) | 
|  | 87 | + | 
|  | 88 | +  .option('f', { | 
|  | 89 | +    alias: 'file', | 
|  | 90 | +    describe: 'The schema file to import/export', | 
|  | 91 | +    nargs: 1, | 
|  | 92 | +    default: config.file || 'schema.sql' | 
|  | 93 | +  }) | 
|  | 94 | + | 
|  | 95 | +  .option('t', { | 
|  | 96 | +    alias: 'type', | 
|  | 97 | +    describe: 'The type of the database', | 
|  | 98 | +    nargs: 1, | 
|  | 99 | +    default: config.type || 'mysql' | 
|  | 100 | +  }) | 
|  | 101 | + | 
|  | 102 | +  .option('h', { | 
|  | 103 | +    alias: 'host', | 
|  | 104 | +    describe: 'The host of the database', | 
|  | 105 | +    nargs: 1, | 
|  | 106 | +    default: config.host || 'localhost' | 
|  | 107 | +  }) | 
|  | 108 | + | 
|  | 109 | +  .option('d', { | 
|  | 110 | +    alias: 'database', | 
|  | 111 | +    describe: 'The name of the database', | 
|  | 112 | +    nargs: 1, | 
|  | 113 | +    default: config.database || 'test' | 
|  | 114 | +  }) | 
|  | 115 | + | 
|  | 116 | +  .option('u', { | 
|  | 117 | +    alias: 'user', | 
|  | 118 | +    describe: 'The user of the database', | 
|  | 119 | +    nargs: 1, | 
|  | 120 | +    default: config.user || 'root' | 
|  | 121 | +  }) | 
|  | 122 | + | 
|  | 123 | +  .option('P', { | 
|  | 124 | +    alias: 'password', | 
|  | 125 | +    describe: 'The password for the database', | 
|  | 126 | +    nargs: 1, | 
|  | 127 | +    default: config.password || '' | 
|  | 128 | +  }) | 
|  | 129 | + | 
|  | 130 | +  .option('p', { | 
|  | 131 | +    alias: 'port', | 
|  | 132 | +    describe: 'The port of the database', | 
|  | 133 | +    nargs: 1, | 
|  | 134 | +    default: config.port | 
|  | 135 | +  }) | 
|  | 136 | + | 
|  | 137 | +  .option('s', { | 
|  | 138 | +    alias: 'socket', | 
|  | 139 | +    describe: 'The socket of the database (only for mysql)', | 
|  | 140 | +    nargs: 1, | 
|  | 141 | +    default: config.socket | 
|  | 142 | +  }) | 
|  | 143 | + | 
|  | 144 | +  .option('x', { | 
|  | 145 | +    alias: 'no-confirm', | 
|  | 146 | +    describe: "Don't confirm before running the import/export", | 
|  | 147 | +    type: 'boolean', | 
|  | 148 | +    default: config['no-confirm'] | 
|  | 149 | +  }).argv | 
0 commit comments