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