first commit
This commit is contained in:
commit
e11a7730d9
|
@ -0,0 +1,4 @@
|
|||
node_modules
|
||||
package.json
|
||||
package-lock.json
|
||||
README.md
|
|
@ -0,0 +1,4 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
db.*.ini
|
||||
.procs-priv.sql
|
|
@ -0,0 +1,60 @@
|
|||
FROM mariadb:10.4.13
|
||||
|
||||
ENV MYSQL_ROOT_PASSWORD root
|
||||
ENV TZ Europe/Madrid
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends curl ca-certificates \
|
||||
&& curl -sL https://apt.verdnatura.es/conf/verdnatura.gpg | apt-key add - \
|
||||
&& echo "deb http://apt.verdnatura.es/ jessie main" > /etc/apt/sources.list.d/vn.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y vn-mariadb \
|
||||
&& apt-get purge -y --auto-remove curl ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY docker/docker.cnf /etc/mysql/conf.d/
|
||||
COPY \
|
||||
docker/docker-init.sh \
|
||||
docker/docker-temp-start.sh \
|
||||
docker/docker-temp-stop.sh \
|
||||
docker/docker-dump.sh \
|
||||
docker/docker-start.sh \
|
||||
/usr/local/bin/
|
||||
|
||||
RUN mkdir /mysql-data \
|
||||
&& chown -R mysql:mysql /mysql-data
|
||||
|
||||
WORKDIR /docker-boot
|
||||
|
||||
COPY \
|
||||
import-changes.sh \
|
||||
db.ini \
|
||||
dump/structure.local.sql \
|
||||
dump/structure.sql \
|
||||
dump/fixtures.sql \
|
||||
./
|
||||
RUN gosu mysql docker-init.sh \
|
||||
&& docker-dump.sh structure.local \
|
||||
&& docker-dump.sh structure \
|
||||
&& docker-dump.sh fixtures \
|
||||
&& gosu mysql docker-temp-stop.sh
|
||||
|
||||
COPY changes ./changes
|
||||
COPY dump/fixtures.local.sql ./
|
||||
ARG STAMP=unknown
|
||||
RUN gosu mysql docker-temp-start.sh \
|
||||
&& ./import-changes.sh \
|
||||
&& docker-dump.sh fixtures.local \
|
||||
&& gosu mysql docker-temp-stop.sh
|
||||
|
||||
RUN echo "[INFO] -> Import finished" \
|
||||
&& rm -rf /docker-boot
|
||||
|
||||
USER mysql
|
||||
ENTRYPOINT ["docker-start.sh"]
|
||||
|
||||
CMD ["mysqld"]
|
||||
|
||||
HEALTHCHECK --interval=2s --timeout=10s --retries=200 \
|
||||
CMD mysqladmin ping -h 127.0.0.1 -u root --password=root || exit 1
|
|
@ -0,0 +1,23 @@
|
|||
FROM debian:bullseye-slim
|
||||
|
||||
ENV TZ Europe/Madrid
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
mariadb-client \
|
||||
libmariadb3 \
|
||||
git \
|
||||
jq \
|
||||
iputils-ping \
|
||||
dnsutils \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY \
|
||||
export-fixtures.sh \
|
||||
export-structure.sh \
|
||||
apply-changes.sh \
|
||||
db.ini \
|
||||
/usr/local/bin/
|
||||
|
||||
WORKDIR /workdir
|
|
@ -0,0 +1,85 @@
|
|||
# MyVC (MySQL Version Control)
|
||||
|
||||
Utilities to ease the maintenance of MySQL database versioning using a Git
|
||||
repository.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Required applications.
|
||||
|
||||
* Git
|
||||
* Node.js = 12.17.0 LTS
|
||||
* Docker
|
||||
|
||||
## How to use
|
||||
|
||||
Export structure (uses production configuration).
|
||||
```
|
||||
$ myvc structure
|
||||
```
|
||||
|
||||
Export fixtures (uses production configuration).
|
||||
```
|
||||
$ myvc fixtures
|
||||
```
|
||||
|
||||
Export routines.
|
||||
```
|
||||
$ myvc routines [environment]
|
||||
```
|
||||
|
||||
Apply changes into database.
|
||||
```
|
||||
$ myvc apply [-f] [-u] [environment]
|
||||
```
|
||||
|
||||
## Basic information
|
||||
|
||||
Create database connection configuration files for each environment at main
|
||||
project folder using the standard MySQL parameters. The predefined environment
|
||||
names are *production* and *testing*.
|
||||
```
|
||||
db.[environment].ini
|
||||
```
|
||||
|
||||
Structure and fixture dumps are located inside *dump* folder.
|
||||
|
||||
* *structure.sql*
|
||||
* *fixtures.sql*
|
||||
* *fixtures.local.sql*
|
||||
|
||||
Routines are located inside *routines* folder. It includes procedures,
|
||||
functions, triggers, views and events with the following structure.
|
||||
```
|
||||
routines
|
||||
`- schema
|
||||
|- events
|
||||
| `- eventName.sql
|
||||
|- functions
|
||||
| `- functionName.sql
|
||||
|- procedures
|
||||
| `- procedureName.sql
|
||||
|- triggers
|
||||
| `- triggerName.sql
|
||||
`- views
|
||||
`- viewName.sql
|
||||
```
|
||||
|
||||
## Versions
|
||||
|
||||
Place your versions inside *changes* folder with the following structure.
|
||||
```
|
||||
changes
|
||||
|- 00001-firstVersionCodeName
|
||||
| |- 00-firstExecutedScript.sql
|
||||
| |- 01-secondScript.sql
|
||||
| `- 99-lastScript.sql
|
||||
`- 00002-secondVersion
|
||||
|- 00-firstExecutedScript.sql
|
||||
`- 00-sameNumbers.sql
|
||||
```
|
||||
## Built With
|
||||
|
||||
* [Git](https://git-scm.com/)
|
||||
* [nodejs](https://nodejs.org/)
|
||||
* [docker](https://www.docker.com/)
|
|
@ -0,0 +1,316 @@
|
|||
#!/bin/bash
|
||||
|
||||
FORCE=FALSE
|
||||
IS_USER=FALSE
|
||||
|
||||
usage() {
|
||||
echo "[ERROR] Usage: $0 [-f] [-u] [environment]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while getopts ":fu" option
|
||||
do
|
||||
case $option in
|
||||
f)
|
||||
FORCE=TRUE
|
||||
;;
|
||||
u)
|
||||
IS_USER=TRUE
|
||||
;;
|
||||
\?|:)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(($OPTIND - 1))
|
||||
ENV=$1
|
||||
|
||||
CONFIG_FILE="myvc.config.json"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "[ERROR] Config file not found in working directory."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||
CODE=$(jq -r ".code" "$CONFIG_FILE")
|
||||
|
||||
# Production protection
|
||||
|
||||
if [ "$ENV" == "production" ]; then
|
||||
echo ""
|
||||
echo " ( ( ) ( ( ) ) "
|
||||
echo " )\ ))\ ) ( /( )\ ) ( ))\ ) ( /( ( /( "
|
||||
echo "(()/(()/( )\()|()/( ( )\ ) /(()/( )\()) )\())"
|
||||
echo " /(_))(_)|(_)\ /(_)) )\ (((_) ( )(_))(_)|(_)\ ((_)\ "
|
||||
echo "(_))(_)) ((_|_))_ _ ((_))\___(_(_()|__)) ((_) _((_)"
|
||||
echo "| _ \ _ \ / _ \| \| | | ((/ __|_ _|_ _| / _ \| \| |"
|
||||
echo "| _/ /| (_) | |) | |_| || (__ | | | | | (_) | . |"
|
||||
echo "|_| |_|_\ \___/|___/ \___/ \___| |_| |___| \___/|_|\_|"
|
||||
echo ""
|
||||
|
||||
if [ "$FORCE" != "TRUE" ]; then
|
||||
read -p "[INTERACTIVE] Are you sure? (Default: no) [yes|no]: " ANSWER
|
||||
|
||||
if [ "$ANSWER" != "yes" ]; then
|
||||
echo "[INFO] Aborting changes."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Configuration file
|
||||
|
||||
if [ -z "$ENV" ]; then
|
||||
INI_FILE="$DIR/db.ini"
|
||||
else
|
||||
INI_FILE="$PWD/db.$ENV.ini"
|
||||
fi
|
||||
|
||||
if [ ! -f "$INI_FILE" ]; then
|
||||
echo "[ERROR] DB config file doesn't exists: $INI_FILE"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "[INFO] Using config file: $INI_FILE"
|
||||
|
||||
# Query functions
|
||||
|
||||
dbQuery() {
|
||||
SQL=$1
|
||||
RETVAL=`echo "$SQL" | mysql --defaults-file="$INI_FILE" --silent --raw`
|
||||
}
|
||||
dbExec() {
|
||||
SQL=$1
|
||||
echo "$SQL" | mysql --defaults-file="$INI_FILE"
|
||||
}
|
||||
dbExecFromFile() {
|
||||
FILE_PATH=$1
|
||||
SCHEMA=$2
|
||||
mysql --defaults-file="$INI_FILE" --default-character-set=utf8 --comments "$SCHEMA" < $FILE_PATH
|
||||
}
|
||||
|
||||
# Fetches database version
|
||||
|
||||
COMMIT_SHA=$(git rev-parse HEAD)
|
||||
echo "[INFO] Commit: $COMMIT_SHA"
|
||||
|
||||
dbQuery "SELECT number, gitCommit FROM util.version WHERE code = '$CODE'"
|
||||
RETVAL=($RETVAL)
|
||||
DB_VERSION=${RETVAL[0]}
|
||||
DB_COMMIT=${RETVAL[1]}
|
||||
|
||||
echo "[INFO] Database information:"
|
||||
echo "[INFO] -> Version: $DB_VERSION"
|
||||
echo "[INFO] -> Commit: $DB_COMMIT"
|
||||
|
||||
if [[ ! "$DB_VERSION" =~ ^[0-9]*$ ]]; then
|
||||
echo "[ERROR] Wrong database version."
|
||||
exit 3
|
||||
fi
|
||||
if [[ -z "$DB_VERSION" ]]; then
|
||||
DB_VERSION=10000
|
||||
fi
|
||||
|
||||
if [ "$IS_USER" == "TRUE" ]; then
|
||||
echo "[INFO] User information:"
|
||||
|
||||
dbQuery "SELECT LEFT(USER(), INSTR(USER(), '@') - 1)"
|
||||
DB_USER=$RETVAL
|
||||
echo "[INFO] -> Name: $DB_USER"
|
||||
|
||||
dbQuery "SELECT number, gitCommit FROM util.versionUser WHERE code = '$CODE' AND user = '$DB_USER'"
|
||||
RETVAL=($RETVAL)
|
||||
USER_VERSION=${RETVAL[0]}
|
||||
USER_COMMIT=${RETVAL[1]}
|
||||
|
||||
echo "[INFO] -> Version: $USER_VERSION"
|
||||
echo "[INFO] -> Commit: $USER_COMMIT"
|
||||
|
||||
if [ ! -z "$USER_VERSION" ]; then
|
||||
if [ "$USER_VERSION" -gt "$DB_VERSION" ]; then
|
||||
DB_VERSION=$USER_VERSION
|
||||
DB_COMMIT=$USER_COMMIT
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Applies changes
|
||||
|
||||
N_CHANGES=0
|
||||
LAST_APPLIED_VERSION=$DB_VERSION
|
||||
|
||||
for DIR_PATH in "$PWD/changes/"*; do
|
||||
DIR_NAME=$(basename $DIR_PATH)
|
||||
DIR_VERSION=${DIR_NAME:0:5}
|
||||
|
||||
if [ "$DIR_NAME" == "README.md" ]; then
|
||||
continue
|
||||
fi
|
||||
if [[ ! "$DIR_NAME" =~ ^[0-9]{5}(-[a-zA-Z0-9]+)?$ ]]; then
|
||||
echo "[WARN] Ignoring wrong directory name: $DIR_NAME"
|
||||
continue
|
||||
fi
|
||||
if [ "$DB_VERSION" -ge "$DIR_VERSION" ]; then
|
||||
echo "[INFO] Ignoring already applied version: $DIR_NAME"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "[INFO] Applying version: $DIR_NAME"
|
||||
|
||||
for FILE in "$DIR_PATH/"*; do
|
||||
FILE_NAME=$(basename "$FILE")
|
||||
|
||||
if [ "$FILE_NAME" == "*" ]; then
|
||||
continue
|
||||
fi
|
||||
if [[ ! "$FILE_NAME" =~ ^[0-9]{2}-[a-zA-Z0-9_]+\.sql$ ]]; then
|
||||
echo "[WARN] Ignoring wrong file name: $FILE_NAME"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "[INFO] -> $FILE_NAME"
|
||||
dbExecFromFile "$FILE"
|
||||
N_CHANGES=$((N_CHANGES + 1))
|
||||
done
|
||||
|
||||
LAST_APPLIED_VERSION=$DIR_VERSION
|
||||
done
|
||||
|
||||
# Applies routines
|
||||
|
||||
applyRoutines() {
|
||||
FILES_CMD=$1
|
||||
|
||||
for FILE_PATH in `$FILES_CMD`; do
|
||||
FILE_NAME=$(basename $FILE_PATH)
|
||||
|
||||
if [[ ! "$FILE_PATH" =~ ^routines/ ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ ! "$FILE_NAME" =~ ^[a-zA-Z0-9_]+\.sql$ ]]; then
|
||||
echo "[WARN] Ignoring wrong file name: $FILE_NAME"
|
||||
continue
|
||||
fi
|
||||
|
||||
FILE_REL_PATH=${FILE_PATH//routines\/}
|
||||
|
||||
IFS='/' read -ra SPLIT <<< "$FILE_REL_PATH"
|
||||
SCHEMA=${SPLIT[0]}
|
||||
NAME=${SPLIT[2]}
|
||||
NAME=${NAME//\.sql/}
|
||||
|
||||
ROUTINE_TYPE=${SPLIT[1]}
|
||||
case "$ROUTINE_TYPE" in
|
||||
events)
|
||||
ROUTINE_TYPE=EVENTS
|
||||
;;
|
||||
functions)
|
||||
ROUTINE_TYPE=FUNCTION
|
||||
;;
|
||||
procedures)
|
||||
ROUTINE_TYPE=PROCEDURE
|
||||
;;
|
||||
triggers)
|
||||
ROUTINE_TYPE=TRIGGER
|
||||
;;
|
||||
views)
|
||||
ROUTINE_TYPE=VIEW
|
||||
;;
|
||||
*)
|
||||
echo "[WARN] Ignoring unknown routine type: $ROUTINE_TYPE"
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
ROUTINE_NAME="\`$SCHEMA\`.\`$NAME\`"
|
||||
|
||||
if [[ -f "$FILE_PATH" ]]; then
|
||||
ACTION="REPLACE"
|
||||
else
|
||||
ACTION="DROP"
|
||||
fi
|
||||
|
||||
echo "[INFO] -> $ROUTINE_TYPE $ROUTINE_NAME: $ACTION"
|
||||
|
||||
if [ "$ACTION" == "REPLACE" ]; then
|
||||
dbExecFromFile "$FILE_PATH" "$SCHEMA"
|
||||
else
|
||||
dbExec "DROP $ROUTINE_TYPE IF EXISTS $ROUTINE_NAME"
|
||||
fi
|
||||
|
||||
ROUTINES_CHANGED=$((ROUTINES_CHANGED + 1))
|
||||
done
|
||||
}
|
||||
|
||||
echo "[INFO] Applying changed routines."
|
||||
|
||||
ROUTINES_CHANGED=0
|
||||
|
||||
PROCS_FILE=.procs-priv.sql
|
||||
mysqldump \
|
||||
--defaults-file="$INI_FILE" \
|
||||
--no-create-info \
|
||||
--skip-triggers \
|
||||
--insert-ignore \
|
||||
mysql procs_priv > "$PROCS_FILE"
|
||||
|
||||
if [[ -z "$DB_COMMIT" ]]; then
|
||||
ROUTINES_CMD="find routines -type f"
|
||||
else
|
||||
ROUTINES_CMD="git diff --name-only $DB_COMMIT -- routines"
|
||||
fi
|
||||
|
||||
applyRoutines "$ROUTINES_CMD"
|
||||
applyRoutines "git ls-files --others --exclude-standard"
|
||||
|
||||
if [ "$ROUTINES_CHANGED" -gt "0" ]; then
|
||||
dbExecFromFile "$PROCS_FILE" "mysql"
|
||||
|
||||
if [ "$?" -eq "0" ]; then
|
||||
dbExec "FLUSH PRIVILEGES"
|
||||
rm "$PROCS_FILE"
|
||||
else
|
||||
echo "[WARN] An error ocurred when restoring routine privileges, backup saved at $PROCS_FILE"
|
||||
fi
|
||||
|
||||
echo "[INFO] -> $ROUTINES_CHANGED routines have changed."
|
||||
else
|
||||
echo "[INFO] -> No routines changed."
|
||||
rm "$PROCS_FILE"
|
||||
fi
|
||||
|
||||
N_CHANGES=$((N_CHANGES + ROUTINES_CHANGED))
|
||||
|
||||
# Displaying summary
|
||||
|
||||
if [ "$N_CHANGES" -gt "0" ]; then
|
||||
if [ "$IS_USER" == "TRUE" ]; then
|
||||
SQL=(
|
||||
"INSERT INTO util.versionUser SET "
|
||||
"code = '$CODE', "
|
||||
"user = '$DB_USER', "
|
||||
"number = '$LAST_APPLIED_VERSION', "
|
||||
"gitCommit = '$COMMIT_SHA' "
|
||||
"ON DUPLICATE KEY UPDATE "
|
||||
"number = VALUES(number), "
|
||||
"gitCommit = VALUES(gitCommit)"
|
||||
)
|
||||
else
|
||||
SQL=(
|
||||
"INSERT INTO util.version SET "
|
||||
"code = '$CODE', "
|
||||
"number = '$LAST_APPLIED_VERSION', "
|
||||
"gitCommit = '$COMMIT_SHA' "
|
||||
"ON DUPLICATE KEY UPDATE "
|
||||
"number = VALUES(number), "
|
||||
"gitCommit = VALUES(gitCommit)"
|
||||
)
|
||||
fi
|
||||
|
||||
dbExec "${SQL[*]}"
|
||||
echo "[INFO] Changes applied succesfully."
|
||||
else
|
||||
echo "[INFO] No changes applied."
|
||||
fi
|
|
@ -0,0 +1,5 @@
|
|||
[client]
|
||||
host = 172.17.0.1
|
||||
port = 3306
|
||||
user = root
|
||||
password = root
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/node
|
||||
const execFileSync = require('child_process').execFileSync;
|
||||
const spawn = require('child_process').spawn;
|
||||
|
||||
module.exports = function(command) {
|
||||
const buildArgs = [
|
||||
'build',
|
||||
'-t', 'vn-db-client',
|
||||
'-f', `${__dirname}/Dockerfile.client`,
|
||||
`${__dirname}/`
|
||||
];
|
||||
execFileSync('docker', buildArgs);
|
||||
|
||||
let args = [
|
||||
'run',
|
||||
'-v', `${process.cwd()}:/workdir`,
|
||||
'vn-db-client',
|
||||
command
|
||||
];
|
||||
args = args.concat(process.argv.slice(2));
|
||||
|
||||
const child = spawn('docker', args, {
|
||||
stdio: [
|
||||
process.stdin,
|
||||
process.stdout,
|
||||
process.stderr
|
||||
]
|
||||
});
|
||||
child.on('exit', code => process.exit(code));
|
||||
};
|
|
@ -0,0 +1,204 @@
|
|||
const exec = require('child_process').exec;
|
||||
const log = require('fancy-log');
|
||||
const dataSources = require('../loopback/server/datasources.json');
|
||||
const serverImage = require(`${process.cwd()}/myvc.config.json`).serverImage;
|
||||
|
||||
module.exports = class Docker {
|
||||
constructor(name) {
|
||||
Object.assign(this, {
|
||||
id: name,
|
||||
name,
|
||||
isRandom: name == null,
|
||||
dbConf: Object.assign({}, dataSources.vn)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the database image and runs a container. It only rebuilds the
|
||||
* image when fixtures have been modified or when the day on which the
|
||||
* image was built is different to today. Some workarounds have been used
|
||||
* to avoid a bug with OverlayFS driver on MacOS.
|
||||
*
|
||||
* @param {Boolean} ci continuous integration environment argument
|
||||
*/
|
||||
async run(ci) {
|
||||
let d = new Date();
|
||||
let pad = v => v < 10 ? '0' + v : v;
|
||||
let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
||||
await this.execP(`docker build --build-arg STAMP=${stamp} -t ${serverImage} ./db`);
|
||||
|
||||
let dockerArgs;
|
||||
|
||||
if (this.isRandom)
|
||||
dockerArgs = '-p 3306';
|
||||
else {
|
||||
try {
|
||||
await this.rm();
|
||||
} catch (e) {}
|
||||
dockerArgs = `--name ${this.name} -p 3306:${this.dbConf.port}`;
|
||||
}
|
||||
|
||||
let runChown = process.platform != 'linux';
|
||||
|
||||
const container = await this.execP(`docker run --env RUN_CHOWN=${runChown} -d ${dockerArgs} ${serverImage}`);
|
||||
this.id = container.stdout.trim();
|
||||
|
||||
try {
|
||||
if (this.isRandom) {
|
||||
let inspect = await this.execP(`docker inspect -f "{{json .NetworkSettings}}" ${this.id}`);
|
||||
let netSettings = JSON.parse(inspect.stdout);
|
||||
|
||||
if (ci)
|
||||
this.dbConf.host = netSettings.Gateway;
|
||||
|
||||
this.dbConf.port = netSettings.Ports['3306/tcp'][0]['HostPort'];
|
||||
}
|
||||
|
||||
await this.wait();
|
||||
} catch (err) {
|
||||
if (this.isRandom)
|
||||
await this.rm();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the minium effort to start the database container, if it doesn't
|
||||
* exists calls the 'docker' task, if it is started does nothing. Keep in
|
||||
* mind that when you do not rebuild the docker you may be using an outdated
|
||||
* version of it. See the 'docker' task for more info.
|
||||
*/
|
||||
async start() {
|
||||
let state;
|
||||
try {
|
||||
let result = await this.execP(`docker inspect -f "{{json .State}}" ${this.id}`);
|
||||
state = JSON.parse(result.stdout);
|
||||
} catch (err) {
|
||||
return await this.run();
|
||||
}
|
||||
|
||||
switch (state.Status) {
|
||||
case 'running':
|
||||
return;
|
||||
case 'exited':
|
||||
await this.execP(`docker start ${this.id}`);
|
||||
await this.wait();
|
||||
return;
|
||||
default:
|
||||
throw new Error(`Unknown docker status: ${state.Status}`);
|
||||
}
|
||||
}
|
||||
|
||||
waitForHealthy() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let interval = 100;
|
||||
let elapsedTime = 0;
|
||||
let maxInterval = 4 * 60 * 1000;
|
||||
|
||||
log('Waiting for MySQL init process...');
|
||||
|
||||
async function checker() {
|
||||
elapsedTime += interval;
|
||||
let status;
|
||||
|
||||
try {
|
||||
let result = await this.execP(`docker inspect -f "{{.State.Health.Status}}" ${this.id}`);
|
||||
status = result.stdout.trimEnd();
|
||||
} catch (err) {
|
||||
return reject(new Error(err.message));
|
||||
}
|
||||
|
||||
if (status == 'unhealthy')
|
||||
return reject(new Error('Docker exited, please see the docker logs for more info'));
|
||||
|
||||
if (status == 'healthy') {
|
||||
log('MySQL process ready.');
|
||||
return resolve();
|
||||
}
|
||||
|
||||
if (elapsedTime >= maxInterval)
|
||||
reject(new Error(`MySQL not initialized whithin ${elapsedTime / 1000} secs`));
|
||||
else
|
||||
setTimeout(bindedChecker, interval);
|
||||
}
|
||||
let bindedChecker = checker.bind(this);
|
||||
bindedChecker();
|
||||
});
|
||||
}
|
||||
|
||||
wait() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const mysql = require('mysql2');
|
||||
|
||||
let interval = 100;
|
||||
let elapsedTime = 0;
|
||||
let maxInterval = 4 * 60 * 1000;
|
||||
|
||||
let myConf = {
|
||||
user: this.dbConf.username,
|
||||
password: this.dbConf.password,
|
||||
host: this.dbConf.host,
|
||||
port: this.dbConf.port
|
||||
};
|
||||
|
||||
log('Waiting for MySQL init process...');
|
||||
|
||||
async function checker() {
|
||||
elapsedTime += interval;
|
||||
let state;
|
||||
|
||||
try {
|
||||
let result = await this.execP(`docker inspect -f "{{json .State}}" ${this.id}`);
|
||||
state = JSON.parse(result.stdout);
|
||||
} catch (err) {
|
||||
return reject(new Error(err.message));
|
||||
}
|
||||
|
||||
if (state.Status === 'exited')
|
||||
return reject(new Error('Docker exited, please see the docker logs for more info'));
|
||||
|
||||
let conn = mysql.createConnection(myConf);
|
||||
conn.on('error', () => {});
|
||||
conn.connect(err => {
|
||||
conn.destroy();
|
||||
if (!err) {
|
||||
log('MySQL process ready.');
|
||||
return resolve();
|
||||
}
|
||||
|
||||
if (elapsedTime >= maxInterval)
|
||||
reject(new Error(`MySQL not initialized whithin ${elapsedTime / 1000} secs`));
|
||||
else
|
||||
setTimeout(bindedChecker, interval);
|
||||
});
|
||||
}
|
||||
let bindedChecker = checker.bind(this);
|
||||
bindedChecker();
|
||||
});
|
||||
}
|
||||
|
||||
rm() {
|
||||
return this.execP(`docker stop ${this.id} && docker rm -v ${this.id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Promisified version of exec().
|
||||
*
|
||||
* @param {String} command The exec command
|
||||
* @return {Promise} The promise
|
||||
*/
|
||||
execP(command) {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(command, (err, stdout, stderr) => {
|
||||
if (err)
|
||||
reject(err);
|
||||
else {
|
||||
resolve({
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
export MYSQL_PWD=root
|
||||
FILE="/docker-boot/$1.sql"
|
||||
echo "[INFO] -> Importing $FILE"
|
||||
mysql -u root --default-character-set=utf8 --comments -f < "$FILE"
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
|
||||
. /usr/local/bin/docker-entrypoint.sh
|
||||
CMD=mysqld
|
||||
|
||||
mysql_check_config "$CMD"
|
||||
docker_setup_env "$CMD"
|
||||
docker_create_db_directories
|
||||
|
||||
docker_verify_minimum_env
|
||||
docker_init_database_dir "$CMD"
|
||||
docker_temp_server_start "$CMD"
|
||||
docker_setup_db
|
||||
docker_process_init_files /docker-entrypoint-initdb.d/*
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
# XXX: Workaround to avoid OverlayFS bug on MacOs
|
||||
# https://docs.docker.com/storage/storagedriver/overlayfs-driver/#limitations-on-overlayfs-compatibility
|
||||
|
||||
if [ "$RUN_CHOWN" = "true" ]; then
|
||||
chown -R mysql:mysql /mysql-data
|
||||
fi
|
||||
|
||||
exec "$@"
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
. /usr/local/bin/docker-entrypoint.sh
|
||||
CMD=mysqld
|
||||
|
||||
docker_setup_env "$CMD"
|
||||
docker_temp_server_start "$CMD"
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
. /usr/local/bin/docker-entrypoint.sh
|
||||
CMD=mysqld
|
||||
|
||||
docker_setup_env "$CMD"
|
||||
docker_temp_server_stop
|
|
@ -0,0 +1,8 @@
|
|||
[mysqld]
|
||||
innodb_log_file_size = 4M
|
||||
innodb_autoextend_increment = 4
|
||||
innodb_page_size = 8K
|
||||
log_bin_trust_function_creators = ON
|
||||
datadir = /mysql-data
|
||||
sql_mode = NO_ENGINE_SUBSTITUTION
|
||||
skip-log-bin
|
|
@ -0,0 +1,28 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
CONFIG_FILE="myvc.config.json"
|
||||
DUMP_FILE="dump/fixtures.sql"
|
||||
INI_FILE="db.production.ini"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Config file not found in working directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SELECT 1;" | mysql --defaults-file="$INI_FILE" >> /dev/null
|
||||
|
||||
echo "Exporting fixtures"
|
||||
echo "" > "$DUMP_FILE"
|
||||
|
||||
for SCHEMA in $(jq -r ".fixtures | keys[]" "$CONFIG_FILE"); do
|
||||
TABLES=( $(jq -r ".fixtures.$SCHEMA[]" "$CONFIG_FILE") )
|
||||
|
||||
echo " -> $SCHEMA"
|
||||
echo "USE \`$SCHEMA\`;" >> "$DUMP_FILE"
|
||||
mysqldump \
|
||||
--defaults-file="$INI_FILE" \
|
||||
--no-create-info \
|
||||
--skip-triggers \
|
||||
$SCHEMA ${TABLES[@]} >> "$DUMP_FILE"
|
||||
done
|
|
@ -0,0 +1,108 @@
|
|||
#!/usr/bin/node
|
||||
const fs = require('fs-extra');
|
||||
const ini = require('ini');
|
||||
const mysql = require('mysql2/promise');
|
||||
const ejs = require('ejs');
|
||||
|
||||
let cwd = process.cwd();
|
||||
let env = process.argv[2];
|
||||
let iniFile = env ? `db.${env}.ini` : `${__dirname}/db.ini`;
|
||||
let dbConf = ini.parse(fs.readFileSync(iniFile, 'utf8')).client;
|
||||
let exportDir = `${cwd}/routines`;
|
||||
let config = require(`${cwd}/myvc.config.json`);
|
||||
|
||||
class Exporter {
|
||||
constructor(objectName, callback) {
|
||||
this.objectName = objectName;
|
||||
this.callback = callback;
|
||||
this.dstDir = `${objectName}s`;
|
||||
|
||||
let templateDir = `${__dirname}/templates/${objectName}`;
|
||||
this.query = fs.readFileSync(`${templateDir}.sql`, 'utf8');
|
||||
|
||||
let templateFile = fs.readFileSync(`${templateDir}.ejs`, 'utf8');
|
||||
this.template = ejs.compile(templateFile);
|
||||
|
||||
if (fs.existsSync(`${templateDir}.js`))
|
||||
this.formatter = require(`${templateDir}.js`);
|
||||
}
|
||||
|
||||
async export(conn, exportDir, schema) {
|
||||
let res = await conn.execute(this.query, [schema]);
|
||||
if (!res[0].length) return;
|
||||
|
||||
let routineDir = `${exportDir}/${schema}/${this.dstDir}`;
|
||||
if (!fs.existsSync(routineDir))
|
||||
fs.mkdirSync(routineDir);
|
||||
|
||||
for (let params of res[0]) {
|
||||
if (this.formatter)
|
||||
this.formatter(params, schema)
|
||||
|
||||
params.schema = schema;
|
||||
let sql = this.template(params);
|
||||
fs.writeFileSync(`${routineDir}/${params.name}.sql`, sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let exporters = [
|
||||
new Exporter('function'),
|
||||
new Exporter('procedure'),
|
||||
new Exporter('view'),
|
||||
new Exporter('trigger'),
|
||||
new Exporter('event')
|
||||
];
|
||||
|
||||
// Exports objects for all schemas
|
||||
|
||||
async function main() {
|
||||
let ssl;
|
||||
if (dbConf.ssl_ca) {
|
||||
ssl = {
|
||||
ca: fs.readFileSync(`${cwd}/${dbConf.ssl_ca}`),
|
||||
rejectUnauthorized: dbConf.ssl_verify_server_cert != undefined
|
||||
}
|
||||
}
|
||||
|
||||
let conn = await mysql.createConnection({
|
||||
host: !env ? 'localhost' : dbConf.host,
|
||||
port: dbConf.port,
|
||||
user: dbConf.user,
|
||||
password: dbConf.password,
|
||||
authPlugins: {
|
||||
mysql_clear_password() {
|
||||
return () => dbConf.password + '\0';
|
||||
}
|
||||
},
|
||||
ssl
|
||||
});
|
||||
conn.queryFromFile = function(file, params) {
|
||||
return this.execute(
|
||||
fs.readFileSync(`${file}.sql`, 'utf8'),
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
if (fs.existsSync(exportDir))
|
||||
fs.removeSync(exportDir, {recursive: true});
|
||||
|
||||
fs.mkdirSync(exportDir);
|
||||
|
||||
for (let schema of config.structure) {
|
||||
let schemaDir = `${exportDir}/${schema}`;
|
||||
|
||||
if (!fs.existsSync(schemaDir))
|
||||
fs.mkdirSync(schemaDir);
|
||||
|
||||
for (let exporter of exporters)
|
||||
await exporter.export(conn, exportDir, schema);
|
||||
}
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
await conn.end();
|
||||
}
|
||||
}
|
||||
main();
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
CONFIG_FILE="myvc.config.json"
|
||||
DUMP_FILE="dump/structure.sql"
|
||||
INI_FILE="db.production.ini"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "Config file found in working directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCHEMAS=( $(jq -r ".structure[]" "$CONFIG_FILE") )
|
||||
|
||||
mysqldump \
|
||||
--defaults-file="$INI_FILE" \
|
||||
--default-character-set=utf8 \
|
||||
--no-data \
|
||||
--comments \
|
||||
--triggers --routines --events \
|
||||
--databases \
|
||||
${SCHEMAS[@]} \
|
||||
| sed 's/ AUTO_INCREMENT=[0-9]* //g' \
|
||||
> "$DUMP_FILE"
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
const getopts = require('getopts');
|
||||
const colors = require('colors');
|
||||
const package = require('./package.json');
|
||||
const dockerRun = require('./docker-run');
|
||||
|
||||
const options = getopts(process.argv.slice(2), {
|
||||
alias: {
|
||||
dir: 'd',
|
||||
env: 'e',
|
||||
help: 'h'
|
||||
},
|
||||
default: {}
|
||||
})
|
||||
|
||||
if (options.help) {
|
||||
console.log('usage: myvc [-d|--dir] [-e|--env] [-h|--help] action');
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
let action = options._[0];
|
||||
console.log('MyVC (MySQL Version Control)'.green, `v${package.version}`.blue);
|
||||
console.log('Action:'.gray, action.magenta);
|
||||
|
||||
switch (action) {
|
||||
case 'structure':
|
||||
dockerRun('export-structure.sh');
|
||||
break;
|
||||
case 'fixtures':
|
||||
dockerRun('export-fixtures.sh');
|
||||
break;
|
||||
case 'routines':
|
||||
require('./export-routines');
|
||||
break;
|
||||
case 'apply':
|
||||
dockerRun('apply-changes.sh');
|
||||
break;
|
||||
}
|
|
@ -0,0 +1,590 @@
|
|||
{
|
||||
"name": "myvc",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@sqltools/formatter": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.2.tgz",
|
||||
"integrity": "sha512-/5O7Fq6Vnv8L6ucmPjaWbVG1XkP4FO+w5glqfkIsq3Xw4oyNAdJddbnYodNDAfjVUvo/rrSCTom4kAND7T1o5Q=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"async": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
|
||||
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
|
||||
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"denque": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
|
||||
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
|
||||
},
|
||||
"ejs": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz",
|
||||
"integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==",
|
||||
"requires": {
|
||||
"jake": "^10.6.1"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"filelist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz",
|
||||
"integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==",
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"requires": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"getopts": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/getopts/-/getopts-2.2.5.tgz",
|
||||
"integrity": "sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA=="
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
|
||||
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
|
||||
},
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
|
||||
},
|
||||
"jake": {
|
||||
"version": "10.8.2",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
|
||||
"integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
|
||||
"requires": {
|
||||
"async": "0.9.x",
|
||||
"chalk": "^2.4.2",
|
||||
"filelist": "^1.0.1",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.2.5.tgz",
|
||||
"integrity": "sha512-XRqPNxcZTpmFdXbJqb+/CtYVLCx14x1RTeNMD4954L331APu75IC74GDqnZMEt1kwaXy6TySo55rF2F3YJS78g==",
|
||||
"requires": {
|
||||
"denque": "^1.4.1",
|
||||
"generate-function": "^2.3.1",
|
||||
"long": "^4.0.0",
|
||||
"lru-cache": "^6.0.0",
|
||||
"named-placeholders": "^1.1.2",
|
||||
"seq-queue": "^0.0.5",
|
||||
"sqlstring": "^2.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"sqlstring": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz",
|
||||
"integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"myvc": {
|
||||
"version": "file:",
|
||||
"requires": {
|
||||
"@sqltools/formatter": "^1.2.2",
|
||||
"ejs": "^3.1.5",
|
||||
"fs-extra": "^8.1.0",
|
||||
"getopts": "^2.2.5",
|
||||
"ini": "^1.3.5",
|
||||
"mysql2": "^2.2.5",
|
||||
"myvc": "file:",
|
||||
"require-yaml": "0.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sqltools/formatter": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.2.tgz",
|
||||
"integrity": "sha512-/5O7Fq6Vnv8L6ucmPjaWbVG1XkP4FO+w5glqfkIsq3Xw4oyNAdJddbnYodNDAfjVUvo/rrSCTom4kAND7T1o5Q=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"ansicolors": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
|
||||
"integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk="
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"async": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
|
||||
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"cardinal": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
|
||||
"integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=",
|
||||
"requires": {
|
||||
"ansicolors": "~0.3.2",
|
||||
"redeyed": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"denque": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
|
||||
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
|
||||
},
|
||||
"ejs": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz",
|
||||
"integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==",
|
||||
"requires": {
|
||||
"jake": "^10.6.1"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"filelist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz",
|
||||
"integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==",
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"requires": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
|
||||
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz",
|
||||
"integrity": "sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q=="
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
|
||||
},
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
|
||||
},
|
||||
"jake": {
|
||||
"version": "10.8.2",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
|
||||
"integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
|
||||
"requires": {
|
||||
"async": "0.9.x",
|
||||
"chalk": "^2.4.2",
|
||||
"filelist": "^1.0.1",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.2.5.tgz",
|
||||
"integrity": "sha512-XRqPNxcZTpmFdXbJqb+/CtYVLCx14x1RTeNMD4954L331APu75IC74GDqnZMEt1kwaXy6TySo55rF2F3YJS78g==",
|
||||
"requires": {
|
||||
"denque": "^1.4.1",
|
||||
"generate-function": "^2.3.1",
|
||||
"long": "^4.0.0",
|
||||
"lru-cache": "^6.0.0",
|
||||
"named-placeholders": "^1.1.2",
|
||||
"seq-queue": "^0.0.5",
|
||||
"sqlstring": "^2.3.2"
|
||||
},
|
||||
"dependencies": {}
|
||||
},
|
||||
"named-placeholders": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz",
|
||||
"integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==",
|
||||
"requires": {
|
||||
"lru-cache": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
}
|
||||
}
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"redeyed": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
|
||||
"integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=",
|
||||
"requires": {
|
||||
"esprima": "~4.0.0"
|
||||
}
|
||||
},
|
||||
"require-yaml": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
|
||||
"integrity": "sha1-LhsY2RPDuqcqWk03O28Tjd0sMr0=",
|
||||
"requires": {
|
||||
"js-yaml": "^3.13.1"
|
||||
}
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"sqlstring": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
||||
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"named-placeholders": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz",
|
||||
"integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==",
|
||||
"requires": {
|
||||
"lru-cache": "^4.1.3"
|
||||
},
|
||||
"dependencies": {}
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"require-yaml": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
|
||||
"integrity": "sha1-LhsY2RPDuqcqWk03O28Tjd0sMr0=",
|
||||
"requires": {
|
||||
"js-yaml": "^3.13.1"
|
||||
}
|
||||
},
|
||||
"seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "myvc",
|
||||
"version": "1.0.0",
|
||||
"author": "Verdnatura Levante SL",
|
||||
"description": "MySQL version control",
|
||||
"license": "GPL-3.0",
|
||||
"bin": "./myvc.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://gitea.verdnatura.es/verdnatura/myvc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sqltools/formatter": "^1.2.2",
|
||||
"colors": "^1.4.0",
|
||||
"ejs": "^3.1.5",
|
||||
"fs-extra": "^8.1.0",
|
||||
"getopts": "^2.2.5",
|
||||
"ini": "^1.3.5",
|
||||
"mysql2": "^2.2.5",
|
||||
"myvc": "file:../myvc",
|
||||
"require-yaml": "0.0.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
DROP EVENT IF EXISTS `<%- schema %>`.`<%- name %>`;
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` EVENT `<%- schema %>`.`<%- name %>`
|
||||
ON SCHEDULE EVERY <%- intervalValue %> <%- intervalField %>
|
||||
ON COMPLETION <%- onCompletion %>
|
||||
<% if (status == 'ENABLED') { %>ENABLE<% } else { %>DISABLE<% } %>
|
||||
DO <%- body %>$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
SELECT
|
||||
EVENT_NAME `name`,
|
||||
DEFINER `definer`,
|
||||
EVENT_DEFINITION `body`,
|
||||
EVENT_TYPE `type`,
|
||||
EXECUTE_AT `execute_at`,
|
||||
INTERVAL_VALUE `intervalValue`,
|
||||
INTERVAL_FIELD `intervalField`,
|
||||
STARTS `starts`,
|
||||
ENDS `ends`,
|
||||
STATUS `status`,
|
||||
ON_COMPLETION `onCompletion`,
|
||||
EVENT_COMMENT `comment`,
|
||||
LAST_ALTERED `modified`
|
||||
FROM information_schema.EVENTS
|
||||
WHERE EVENT_SCHEMA = ?
|
|
@ -0,0 +1,7 @@
|
|||
DROP FUNCTION IF EXISTS `<%- schema %>`.`<%- name %>`;
|
||||
DELIMITER $$
|
||||
CREATE DEFINER='root'@'%' FUNCTION `<%- schema %>`.`<%- name %>`(<%- paramList %>)
|
||||
RETURNS <%- returns %>
|
||||
<% if (isDeterministic != 'NO') { %>DETERMINISTIC<% } else { %>NOT DETERMINISTIC<% } %>
|
||||
<%- body %>$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
SELECT
|
||||
`name`,
|
||||
`definer`,
|
||||
`param_list` paramList,
|
||||
`returns`,
|
||||
`is_deterministic` isDeterministic,
|
||||
`body`,
|
||||
`modified`
|
||||
FROM mysql.proc
|
||||
WHERE `db` = ? AND `type` = 'FUNCTION'
|
|
@ -0,0 +1,5 @@
|
|||
DROP PROCEDURE IF EXISTS `<%- schema %>`.`<%- name %>`;
|
||||
DELIMITER $$
|
||||
CREATE DEFINER='root'@'%' PROCEDURE `<%- schema %>`.`<%- name %>`(<%- paramList %>)
|
||||
<%- body %>$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
SELECT
|
||||
`name`,
|
||||
`definer`,
|
||||
`param_list` paramList,
|
||||
`body`,
|
||||
`modified`
|
||||
FROM mysql.proc
|
||||
WHERE db = ? AND type = 'PROCEDURE'
|
|
@ -0,0 +1,7 @@
|
|||
DROP TRIGGER IF EXISTS `<%- schema %>`.`<%- name %>`;
|
||||
DELIMITER $$
|
||||
CREATE DEFINER=`root`@`%` TRIGGER `<%- schema %>`.`<%- name %>`
|
||||
<%- actionTiming %> <%- actionType %> ON `<%- table %>`
|
||||
FOR EACH ROW
|
||||
<%- body %>$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
SELECT
|
||||
TRIGGER_NAME `name`,
|
||||
DEFINER `definer`,
|
||||
ACTION_TIMING `actionTiming`,
|
||||
EVENT_MANIPULATION `actionType`,
|
||||
EVENT_OBJECT_TABLE `table`,
|
||||
ACTION_STATEMENT `body`,
|
||||
CREATED `modified`
|
||||
FROM information_schema.TRIGGERS
|
||||
WHERE TRIGGER_SCHEMA = ?
|
|
@ -0,0 +1,5 @@
|
|||
CREATE OR REPLACE DEFINER = `root`@`%`
|
||||
SQL SECURITY <%- securityType %>
|
||||
VIEW `<%- schema %>`.`<%- name %>`
|
||||
AS <%- definition %><% if (checkOption != 'NONE') { %>
|
||||
WITH CASCADED CHECK OPTION<% } %>
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
const sqlFormatter = require('@sqltools/formatter');
|
||||
|
||||
module.exports = function(params) {
|
||||
params.definition = sqlFormatter.format(params.definition, {
|
||||
indent: '\t',
|
||||
reservedWordCase: 'upper'
|
||||
});
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
SELECT
|
||||
TABLE_NAME `name`,
|
||||
VIEW_DEFINITION `definition`,
|
||||
CHECK_OPTION `checkOption`,
|
||||
IS_UPDATABLE `isUpdatable`,
|
||||
DEFINER `definer`,
|
||||
SECURITY_TYPE `securityType`
|
||||
FROM information_schema.VIEWS
|
||||
WHERE TABLE_SCHEMA = ?
|
Loading…
Reference in New Issue