@prairielearn/postgres-tools 2.0.18 → 2.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/bin/pg-describe.js +34 -50
- package/dist/bin/pg-describe.js.map +1 -1
- package/dist/bin/pg-diff.js +22 -28
- package/dist/bin/pg-diff.js.map +1 -1
- package/package.json +6 -7
- package/src/bin/pg-describe.ts +38 -56
- package/src/bin/pg-diff.ts +22 -31
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @prairielearn/postgres-tools
|
|
2
2
|
|
|
3
|
+
## 2.0.20
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [b911b61]
|
|
8
|
+
- @prairielearn/postgres@3.0.0
|
|
9
|
+
|
|
10
|
+
## 2.0.19
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 678b48a: Upgrade all JavaScript dependencies
|
|
15
|
+
- Updated dependencies [678b48a]
|
|
16
|
+
- @prairielearn/postgres@2.1.15
|
|
17
|
+
|
|
3
18
|
## 2.0.18
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/bin/pg-describe.js
CHANGED
|
@@ -2,65 +2,33 @@
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import async from 'async';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
|
+
import { Command } from 'commander';
|
|
5
6
|
import fs from 'fs-extra';
|
|
6
|
-
import yargs from 'yargs';
|
|
7
7
|
import { describeDatabase, formatDatabaseDescription, } from '../describe.js';
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
description: 'a list of enums to ignore',
|
|
24
|
-
})
|
|
25
|
-
.option('ignore-columns', {
|
|
26
|
-
array: true,
|
|
27
|
-
description: 'a list of columns to ignore, formatted like [table].[column]',
|
|
28
|
-
})
|
|
29
|
-
.help('h')
|
|
30
|
-
.alias('h', 'help')
|
|
31
|
-
.example('$0 postgres', 'Describe the "postgres" database')
|
|
32
|
-
.example('$0 userdb -o db_description --ignore-tables a b --ignore-columns a.col1 a.col2', 'Describe the "userdb" database; ignore specific tables and columns')
|
|
33
|
-
.strict();
|
|
34
|
-
const argv = args.parseSync();
|
|
35
|
-
if (argv._.length !== 1) {
|
|
36
|
-
args.showHelp();
|
|
37
|
-
process.exit(1);
|
|
8
|
+
const program = new Command();
|
|
9
|
+
program
|
|
10
|
+
.name('pg-describe')
|
|
11
|
+
.usage('<database name> [options]')
|
|
12
|
+
.argument('<database>', 'Database name to describe')
|
|
13
|
+
.option('-o, --output <dir>', 'Specify a directory to output files to')
|
|
14
|
+
.option('--ignore-tables <tables...>', 'A list of tables to ignore')
|
|
15
|
+
.option('--ignore-enums <enums...>', 'A list of enums to ignore')
|
|
16
|
+
.option('--ignore-columns <columns...>', 'A list of columns to ignore, formatted like [table].[column]')
|
|
17
|
+
.showHelpAfterError();
|
|
18
|
+
program.parse(process.argv);
|
|
19
|
+
const opts = program.opts();
|
|
20
|
+
const dbName = program.args[0];
|
|
21
|
+
if (!dbName) {
|
|
22
|
+
program.help({ error: true });
|
|
38
23
|
}
|
|
39
24
|
// Disable color if we're not attached to a tty
|
|
40
|
-
const coloredOutput = !
|
|
41
|
-
const options = {
|
|
42
|
-
ignoreTables: (argv['ignore-tables'] ?? []).map((table) => table.toString()),
|
|
43
|
-
ignoreEnums: (argv['ignore-enums'] ?? []).map((enumName) => enumName.toString()),
|
|
44
|
-
ignoreColumns: (argv['ignore-columns'] ?? []).map((column) => column.toString()),
|
|
45
|
-
};
|
|
25
|
+
const coloredOutput = !opts.output && process.stdout.isTTY;
|
|
46
26
|
function formatText(text, formatter) {
|
|
47
|
-
if (!
|
|
27
|
+
if (!opts.output && coloredOutput) {
|
|
48
28
|
return formatter(text);
|
|
49
29
|
}
|
|
50
30
|
return text;
|
|
51
31
|
}
|
|
52
|
-
describeDatabase(argv._[0].toString(), options).then(async (description) => {
|
|
53
|
-
if (argv.output) {
|
|
54
|
-
await writeDescriptionToDisk(description, argv.output);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
printDescription(description);
|
|
58
|
-
}
|
|
59
|
-
process.exit(0);
|
|
60
|
-
}, (err) => {
|
|
61
|
-
console.error(err);
|
|
62
|
-
process.exit(1);
|
|
63
|
-
});
|
|
64
32
|
function printDescription(description) {
|
|
65
33
|
const formattedDescription = formatDatabaseDescription(description, { coloredOutput });
|
|
66
34
|
for (const tableName of Object.keys(formattedDescription.tables).sort()) {
|
|
@@ -87,4 +55,20 @@ async function writeDescriptionToDisk(description, dir) {
|
|
|
87
55
|
await fs.writeFile(path.join(dir, 'enums', `${key}.pg`), value);
|
|
88
56
|
});
|
|
89
57
|
}
|
|
58
|
+
function parseListOption(option) {
|
|
59
|
+
return option.flatMap((item) => item.split(',').map((part) => part.trim()));
|
|
60
|
+
}
|
|
61
|
+
const options = {
|
|
62
|
+
ignoreTables: parseListOption(opts.ignoreTables ?? []),
|
|
63
|
+
ignoreEnums: parseListOption(opts.ignoreEnums ?? []),
|
|
64
|
+
ignoreColumns: parseListOption(opts.ignoreColumns ?? []),
|
|
65
|
+
};
|
|
66
|
+
const description = await describeDatabase(dbName, options);
|
|
67
|
+
if (opts.output) {
|
|
68
|
+
await writeDescriptionToDisk(description, opts.output);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
printDescription(description);
|
|
72
|
+
}
|
|
73
|
+
process.exit(0);
|
|
90
74
|
//# sourceMappingURL=pg-describe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-describe.js","sourceRoot":"","sources":["../../src/bin/pg-describe.ts"],"names":[],"mappings":";AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"pg-describe.js","sourceRoot":"","sources":["../../src/bin/pg-describe.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport path from 'path';\n\nimport async from 'async';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport fs from 'fs-extra';\n\nimport {\n type DatabaseDescription,\n describeDatabase,\n formatDatabaseDescription,\n} from '../describe.js';\n\nconst program = new Command();\nprogram\n .name('pg-describe')\n .usage('<database name> [options]')\n .argument('<database>', 'Database name to describe')\n .option('-o, --output <dir>', 'Specify a directory to output files to')\n .option('--ignore-tables <tables...>', 'A list of tables to ignore')\n .option('--ignore-enums <enums...>', 'A list of enums to ignore')\n .option(\n '--ignore-columns <columns...>',\n 'A list of columns to ignore, formatted like [table].[column]',\n )\n .showHelpAfterError();\n\nprogram.parse(process.argv);\nconst opts = program.opts();\nconst dbName = program.args[0];\n\nif (!dbName) {\n program.help({ error: true });\n}\n\n// Disable color if we're not attached to a tty\nconst coloredOutput = !opts.output && process.stdout.isTTY;\n\nfunction formatText(text: string, formatter: (text: string) => string) {\n if (!opts.output && coloredOutput) {\n return formatter(text);\n }\n return text;\n}\n\nfunction printDescription(description: DatabaseDescription) {\n const formattedDescription = formatDatabaseDescription(description, { coloredOutput });\n for (const tableName of Object.keys(formattedDescription.tables).sort()) {\n process.stdout.write(formatText(`[table] ${tableName}\\n`, chalk.bold));\n process.stdout.write(formattedDescription.tables[tableName]);\n process.stdout.write('\\n\\n');\n }\n\n for (const enumName of Object.keys(formattedDescription.enums).sort()) {\n process.stdout.write(formatText(`[enum] ${enumName}\\n`, chalk.bold));\n process.stdout.write(formattedDescription.enums[enumName]);\n process.stdout.write('\\n\\n');\n }\n}\n\nasync function writeDescriptionToDisk(description: DatabaseDescription, dir: string) {\n const formattedDescription = formatDatabaseDescription(description, { coloredOutput: false });\n await fs.ensureDir(path.join(dir, 'tables'));\n await fs.ensureDir(path.join(dir, 'enums'));\n await fs.emptyDir(path.join(dir, 'tables'));\n await fs.emptyDir(path.join(dir, 'enums'));\n await async.eachOf(formattedDescription.tables, async (value, key) => {\n await fs.writeFile(path.join(dir, 'tables', `${key}.pg`), value);\n });\n await async.eachOf(formattedDescription.enums, async (value, key) => {\n await fs.writeFile(path.join(dir, 'enums', `${key}.pg`), value);\n });\n}\n\nfunction parseListOption(option: string[]): string[] {\n return option.flatMap((item: string) => item.split(',').map((part) => part.trim()));\n}\n\nconst options = {\n ignoreTables: parseListOption(opts.ignoreTables ?? []),\n ignoreEnums: parseListOption(opts.ignoreEnums ?? []),\n ignoreColumns: parseListOption(opts.ignoreColumns ?? []),\n};\n\nconst description = await describeDatabase(dbName, options);\nif (opts.output) {\n await writeDescriptionToDisk(description, opts.output);\n} else {\n printDescription(description);\n}\nprocess.exit(0);\n"]}
|
package/dist/bin/pg-diff.js
CHANGED
|
@@ -1,42 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import { Command } from 'commander';
|
|
3
3
|
import { diffDatabaseAndDirectory, diffDatabases, diffDirectories, diffDirectoryAndDatabase, } from '../diff.js';
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
.option('dir',
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.alias('h', 'help')
|
|
14
|
-
.example('$0 --db postgres --dir db_dump', 'Diffs the database "postgres" with the description in the directory "db_dump"')
|
|
15
|
-
.example('$0 --db postgres --db old_restore', 'Diffs the database "postgres" with the database "old_restore"')
|
|
16
|
-
.strict();
|
|
17
|
-
const argv = args.parseSync();
|
|
4
|
+
const program = new Command();
|
|
5
|
+
program
|
|
6
|
+
.name('pg-diff')
|
|
7
|
+
.usage('[options]')
|
|
8
|
+
.option('--db <db...>', 'Reads a description from the named database (can be specified twice)')
|
|
9
|
+
.option('--dir <dir...>', "Reads a description from a directory that's been generated by pg-describe (can be specified twice)")
|
|
10
|
+
.showHelpAfterError();
|
|
11
|
+
program.parse(process.argv);
|
|
12
|
+
const opts = program.opts();
|
|
18
13
|
const options = {
|
|
19
14
|
outputFormat: 'string',
|
|
20
15
|
coloredOutput: process.stdout.isTTY,
|
|
21
16
|
};
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
if (opts.db.length === 2 && !opts.dir) {
|
|
18
|
+
diffDatabases(opts.db[0], opts.db[1], options).then(handleResults, handleError);
|
|
19
|
+
}
|
|
20
|
+
else if (opts.dir.length === 2 && !opts.db) {
|
|
21
|
+
diffDirectories(opts.dir[0], opts.dir[1], options).then(handleResults, handleError);
|
|
22
|
+
}
|
|
23
|
+
else if (opts.db.length === 1 && opts.dir.length === 1) {
|
|
24
|
+
const dbIsFirst = process.argv.lastIndexOf('--db') < process.argv.lastIndexOf('--dir');
|
|
25
|
+
if (dbIsFirst) {
|
|
26
|
+
diffDatabaseAndDirectory(opts.db[0], opts.dir[0], options).then(handleResults, handleError);
|
|
26
27
|
}
|
|
27
28
|
else {
|
|
28
|
-
diffDirectoryAndDatabase(
|
|
29
|
+
diffDirectoryAndDatabase(opts.dir[0], opts.db[0], options).then(handleResults, handleError);
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
|
-
else if (argv.db && Array.isArray(argv.db) && argv.db.length === 2 && !argv.dir) {
|
|
32
|
-
diffDatabases(argv.db[0], argv.db[1], options).then(handleResults, handleError);
|
|
33
|
-
}
|
|
34
|
-
else if (argv.dir && Array.isArray(argv.dir) && argv.dir.length === 2 && !argv.db) {
|
|
35
|
-
diffDirectories(argv.dir[0], argv.dir[1], options).then(handleResults, handleError);
|
|
36
|
-
}
|
|
37
32
|
else {
|
|
38
|
-
|
|
39
|
-
process.exit(1);
|
|
33
|
+
program.help({ error: true });
|
|
40
34
|
}
|
|
41
35
|
function handleResults(results) {
|
|
42
36
|
process.stdout.write(results);
|
package/dist/bin/pg-diff.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-diff.js","sourceRoot":"","sources":["../../src/bin/pg-diff.ts"],"names":[],"mappings":";AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"pg-diff.js","sourceRoot":"","sources":["../../src/bin/pg-diff.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,wBAAwB,EACxB,aAAa,EACb,eAAe,EACf,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAEpB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,KAAK,CAAC,WAAW,CAAC;KAClB,MAAM,CAAC,cAAc,EAAE,sEAAsE,CAAC;KAC9F,MAAM,CACL,gBAAgB,EAChB,oGAAoG,CACrG;KACA,kBAAkB,EAAE,CAAC;AAExB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;AAE5B,MAAM,OAAO,GAAG;IACd,YAAY,EAAE,QAAQ;IACtB,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;CACpC,CAAC;AAEF,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACtC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AAClF,CAAC;KAAM,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IAC7C,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACtF,CAAC;KAAM,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACzD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACvF,IAAI,SAAS,EAAE,CAAC;QACd,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAC9F,CAAC;SAAM,CAAC;QACN,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,GAAQ;IAC3B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\n\nimport {\n diffDatabaseAndDirectory,\n diffDatabases,\n diffDirectories,\n diffDirectoryAndDatabase,\n} from '../diff.js';\n\nconst program = new Command();\nprogram\n .name('pg-diff')\n .usage('[options]')\n .option('--db <db...>', 'Reads a description from the named database (can be specified twice)')\n .option(\n '--dir <dir...>',\n \"Reads a description from a directory that's been generated by pg-describe (can be specified twice)\",\n )\n .showHelpAfterError();\n\nprogram.parse(process.argv);\nconst opts = program.opts();\n\nconst options = {\n outputFormat: 'string',\n coloredOutput: process.stdout.isTTY,\n};\n\nif (opts.db.length === 2 && !opts.dir) {\n diffDatabases(opts.db[0], opts.db[1], options).then(handleResults, handleError);\n} else if (opts.dir.length === 2 && !opts.db) {\n diffDirectories(opts.dir[0], opts.dir[1], options).then(handleResults, handleError);\n} else if (opts.db.length === 1 && opts.dir.length === 1) {\n const dbIsFirst = process.argv.lastIndexOf('--db') < process.argv.lastIndexOf('--dir');\n if (dbIsFirst) {\n diffDatabaseAndDirectory(opts.db[0], opts.dir[0], options).then(handleResults, handleError);\n } else {\n diffDirectoryAndDatabase(opts.dir[0], opts.db[0], options).then(handleResults, handleError);\n }\n} else {\n program.help({ error: true });\n}\n\nfunction handleResults(results: string) {\n process.stdout.write(results);\n process.exit(0);\n}\n\nfunction handleError(err: any) {\n console.error(err);\n process.exit(1);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prairielearn/postgres-tools",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,21 +17,20 @@
|
|
|
17
17
|
"dev": "tsc --watch --preserveWatchOutput & tscp --watch"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@prairielearn/postgres": "^
|
|
20
|
+
"@prairielearn/postgres": "^3.0.0",
|
|
21
21
|
"async": "^3.2.6",
|
|
22
22
|
"chalk": "^5.4.1",
|
|
23
|
+
"commander": "^14.0.0",
|
|
23
24
|
"diff": "^8.0.2",
|
|
24
25
|
"fs-extra": "^11.3.0",
|
|
25
26
|
"lodash": "^4.17.21",
|
|
26
|
-
"postgres-array": "^3.0.4"
|
|
27
|
-
"yargs": "^17.7.2"
|
|
27
|
+
"postgres-array": "^3.0.4"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@prairielearn/tsconfig": "^0.0.0",
|
|
31
31
|
"@types/fs-extra": "^11.0.4",
|
|
32
|
-
"@types/lodash": "^4.17.
|
|
33
|
-
"@types/node": "^
|
|
34
|
-
"@types/yargs": "^17.0.33",
|
|
32
|
+
"@types/lodash": "^4.17.20",
|
|
33
|
+
"@types/node": "^22.15.34",
|
|
35
34
|
"typescript": "^5.8.3",
|
|
36
35
|
"typescript-cp": "^0.1.9"
|
|
37
36
|
}
|
package/src/bin/pg-describe.ts
CHANGED
|
@@ -4,8 +4,8 @@ import path from 'path';
|
|
|
4
4
|
|
|
5
5
|
import async from 'async';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
|
+
import { Command } from 'commander';
|
|
7
8
|
import fs from 'fs-extra';
|
|
8
|
-
import yargs from 'yargs';
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
type DatabaseDescription,
|
|
@@ -13,74 +13,38 @@ import {
|
|
|
13
13
|
formatDatabaseDescription,
|
|
14
14
|
} from '../describe.js';
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
.
|
|
19
|
-
.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
description: 'a list of tables to ignore',
|
|
28
|
-
})
|
|
29
|
-
.option('ignore-enums', {
|
|
30
|
-
array: true,
|
|
31
|
-
description: 'a list of enums to ignore',
|
|
32
|
-
})
|
|
33
|
-
.option('ignore-columns', {
|
|
34
|
-
array: true,
|
|
35
|
-
description: 'a list of columns to ignore, formatted like [table].[column]',
|
|
36
|
-
})
|
|
37
|
-
.help('h')
|
|
38
|
-
.alias('h', 'help')
|
|
39
|
-
.example('$0 postgres', 'Describe the "postgres" database')
|
|
40
|
-
.example(
|
|
41
|
-
'$0 userdb -o db_description --ignore-tables a b --ignore-columns a.col1 a.col2',
|
|
42
|
-
'Describe the "userdb" database; ignore specific tables and columns',
|
|
16
|
+
const program = new Command();
|
|
17
|
+
program
|
|
18
|
+
.name('pg-describe')
|
|
19
|
+
.usage('<database name> [options]')
|
|
20
|
+
.argument('<database>', 'Database name to describe')
|
|
21
|
+
.option('-o, --output <dir>', 'Specify a directory to output files to')
|
|
22
|
+
.option('--ignore-tables <tables...>', 'A list of tables to ignore')
|
|
23
|
+
.option('--ignore-enums <enums...>', 'A list of enums to ignore')
|
|
24
|
+
.option(
|
|
25
|
+
'--ignore-columns <columns...>',
|
|
26
|
+
'A list of columns to ignore, formatted like [table].[column]',
|
|
43
27
|
)
|
|
44
|
-
.
|
|
28
|
+
.showHelpAfterError();
|
|
45
29
|
|
|
46
|
-
|
|
30
|
+
program.parse(process.argv);
|
|
31
|
+
const opts = program.opts();
|
|
32
|
+
const dbName = program.args[0];
|
|
47
33
|
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
process.exit(1);
|
|
34
|
+
if (!dbName) {
|
|
35
|
+
program.help({ error: true });
|
|
51
36
|
}
|
|
52
37
|
|
|
53
38
|
// Disable color if we're not attached to a tty
|
|
54
|
-
const coloredOutput = !
|
|
55
|
-
|
|
56
|
-
const options = {
|
|
57
|
-
ignoreTables: (argv['ignore-tables'] ?? []).map((table) => table.toString()),
|
|
58
|
-
ignoreEnums: (argv['ignore-enums'] ?? []).map((enumName) => enumName.toString()),
|
|
59
|
-
ignoreColumns: (argv['ignore-columns'] ?? []).map((column) => column.toString()),
|
|
60
|
-
};
|
|
39
|
+
const coloredOutput = !opts.output && process.stdout.isTTY;
|
|
61
40
|
|
|
62
41
|
function formatText(text: string, formatter: (text: string) => string) {
|
|
63
|
-
if (!
|
|
42
|
+
if (!opts.output && coloredOutput) {
|
|
64
43
|
return formatter(text);
|
|
65
44
|
}
|
|
66
45
|
return text;
|
|
67
46
|
}
|
|
68
47
|
|
|
69
|
-
describeDatabase(argv._[0].toString(), options).then(
|
|
70
|
-
async (description) => {
|
|
71
|
-
if (argv.output) {
|
|
72
|
-
await writeDescriptionToDisk(description, argv.output);
|
|
73
|
-
} else {
|
|
74
|
-
printDescription(description);
|
|
75
|
-
}
|
|
76
|
-
process.exit(0);
|
|
77
|
-
},
|
|
78
|
-
(err) => {
|
|
79
|
-
console.error(err);
|
|
80
|
-
process.exit(1);
|
|
81
|
-
},
|
|
82
|
-
);
|
|
83
|
-
|
|
84
48
|
function printDescription(description: DatabaseDescription) {
|
|
85
49
|
const formattedDescription = formatDatabaseDescription(description, { coloredOutput });
|
|
86
50
|
for (const tableName of Object.keys(formattedDescription.tables).sort()) {
|
|
@@ -109,3 +73,21 @@ async function writeDescriptionToDisk(description: DatabaseDescription, dir: str
|
|
|
109
73
|
await fs.writeFile(path.join(dir, 'enums', `${key}.pg`), value);
|
|
110
74
|
});
|
|
111
75
|
}
|
|
76
|
+
|
|
77
|
+
function parseListOption(option: string[]): string[] {
|
|
78
|
+
return option.flatMap((item: string) => item.split(',').map((part) => part.trim()));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const options = {
|
|
82
|
+
ignoreTables: parseListOption(opts.ignoreTables ?? []),
|
|
83
|
+
ignoreEnums: parseListOption(opts.ignoreEnums ?? []),
|
|
84
|
+
ignoreColumns: parseListOption(opts.ignoreColumns ?? []),
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const description = await describeDatabase(dbName, options);
|
|
88
|
+
if (opts.output) {
|
|
89
|
+
await writeDescriptionToDisk(description, opts.output);
|
|
90
|
+
} else {
|
|
91
|
+
printDescription(description);
|
|
92
|
+
}
|
|
93
|
+
process.exit(0);
|
package/src/bin/pg-diff.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { Command } from 'commander';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
diffDatabaseAndDirectory,
|
|
@@ -9,47 +9,38 @@ import {
|
|
|
9
9
|
diffDirectoryAndDatabase,
|
|
10
10
|
} from '../diff.js';
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.option(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.help('h')
|
|
21
|
-
.alias('h', 'help')
|
|
22
|
-
.example(
|
|
23
|
-
'$0 --db postgres --dir db_dump',
|
|
24
|
-
'Diffs the database "postgres" with the description in the directory "db_dump"',
|
|
12
|
+
const program = new Command();
|
|
13
|
+
program
|
|
14
|
+
.name('pg-diff')
|
|
15
|
+
.usage('[options]')
|
|
16
|
+
.option('--db <db...>', 'Reads a description from the named database (can be specified twice)')
|
|
17
|
+
.option(
|
|
18
|
+
'--dir <dir...>',
|
|
19
|
+
"Reads a description from a directory that's been generated by pg-describe (can be specified twice)",
|
|
25
20
|
)
|
|
26
|
-
.
|
|
27
|
-
'$0 --db postgres --db old_restore',
|
|
28
|
-
'Diffs the database "postgres" with the database "old_restore"',
|
|
29
|
-
)
|
|
30
|
-
.strict();
|
|
21
|
+
.showHelpAfterError();
|
|
31
22
|
|
|
32
|
-
|
|
23
|
+
program.parse(process.argv);
|
|
24
|
+
const opts = program.opts();
|
|
33
25
|
|
|
34
26
|
const options = {
|
|
35
27
|
outputFormat: 'string',
|
|
36
28
|
coloredOutput: process.stdout.isTTY,
|
|
37
29
|
};
|
|
38
30
|
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
if (opts.db.length === 2 && !opts.dir) {
|
|
32
|
+
diffDatabases(opts.db[0], opts.db[1], options).then(handleResults, handleError);
|
|
33
|
+
} else if (opts.dir.length === 2 && !opts.db) {
|
|
34
|
+
diffDirectories(opts.dir[0], opts.dir[1], options).then(handleResults, handleError);
|
|
35
|
+
} else if (opts.db.length === 1 && opts.dir.length === 1) {
|
|
36
|
+
const dbIsFirst = process.argv.lastIndexOf('--db') < process.argv.lastIndexOf('--dir');
|
|
37
|
+
if (dbIsFirst) {
|
|
38
|
+
diffDatabaseAndDirectory(opts.db[0], opts.dir[0], options).then(handleResults, handleError);
|
|
43
39
|
} else {
|
|
44
|
-
diffDirectoryAndDatabase(
|
|
40
|
+
diffDirectoryAndDatabase(opts.dir[0], opts.db[0], options).then(handleResults, handleError);
|
|
45
41
|
}
|
|
46
|
-
} else if (argv.db && Array.isArray(argv.db) && argv.db.length === 2 && !argv.dir) {
|
|
47
|
-
diffDatabases(argv.db[0], argv.db[1], options).then(handleResults, handleError);
|
|
48
|
-
} else if (argv.dir && Array.isArray(argv.dir) && argv.dir.length === 2 && !argv.db) {
|
|
49
|
-
diffDirectories(argv.dir[0], argv.dir[1], options).then(handleResults, handleError);
|
|
50
42
|
} else {
|
|
51
|
-
|
|
52
|
-
process.exit(1);
|
|
43
|
+
program.help({ error: true });
|
|
53
44
|
}
|
|
54
45
|
|
|
55
46
|
function handleResults(results: string) {
|