@prisma-psm/core 1.0.56 → 1.0.57
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/package.json +1 -1
- package/src/launcher/commands/shell.d.ts +5 -0
- package/src/launcher/commands/shell.d.ts.map +1 -0
- package/src/launcher/commands/shell.js +32 -0
- package/src/launcher/commands/shell.js.map +1 -0
- package/src/launcher/commands/shell.ts +34 -0
- package/src/tools/shell.d.ts +8 -0
- package/src/tools/shell.d.ts.map +1 -0
- package/src/tools/shell.js +221 -0
- package/src/tools/shell.js.map +1 -0
- package/src/tools/shell.ts +210 -0
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["shell.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAS,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAExD,QAAA,MAAM,OAAO,EAAE,aAAa,CAAC,YAAY,EAAE,YAAY,CA0BtD,CAAC;AAEF,SAAS,OAAO,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// filename: src/launcher/commands/shell.ts
|
|
3
|
+
const shell_1 = require("../../tools/shell");
|
|
4
|
+
const command = {
|
|
5
|
+
command: "shell",
|
|
6
|
+
describe: "Open interactive SQL shell with transaction (similar to psql)",
|
|
7
|
+
builder: args => {
|
|
8
|
+
return args
|
|
9
|
+
.options("schema", {
|
|
10
|
+
type: "string",
|
|
11
|
+
alias: "s",
|
|
12
|
+
describe: "Caminho para o schema.prisma (opcional)",
|
|
13
|
+
})
|
|
14
|
+
.options("label", {
|
|
15
|
+
type: "string",
|
|
16
|
+
alias: "l",
|
|
17
|
+
describe: "Label para a revisão gerada ao commitar",
|
|
18
|
+
})
|
|
19
|
+
.options("add", {
|
|
20
|
+
type: "boolean",
|
|
21
|
+
describe: "Adicionar o arquivo .tar.gz ao git após gerar revisão",
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
handler: (argv) => {
|
|
25
|
+
(0, shell_1.shell)(argv).catch((reason) => {
|
|
26
|
+
console.error("Erro no shell:", reason);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
module.exports = command;
|
|
32
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["shell.ts"],"names":[],"mappings":";AAAA,2CAA2C;AAG3C,6CAAwD;AAExD,MAAM,OAAO,GAA8C;IACvD,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,+DAA+D;IACzE,OAAO,EAAE,IAAI,CAAC,EAAE;QACZ,OAAO,IAAI;aACN,OAAO,CAAC,QAAQ,EAAE;YACf,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,yCAAyC;SACtD,CAAC;aACD,OAAO,CAAC,OAAO,EAAE;YACd,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,yCAAyC;SACtD,CAAC;aACD,OAAO,CAAC,KAAK,EAAE;YACZ,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,uDAAuD;SACpE,CAAC,CAAC;IACX,CAAC;IACD,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;QACd,IAAA,aAAK,EAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE;YACzB,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAC;AAEF,iBAAS,OAAO,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// filename: src/launcher/commands/shell.ts
|
|
2
|
+
|
|
3
|
+
import { CommandModule } from "yargs";
|
|
4
|
+
import { shell, ShellOptions } from "../../tools/shell";
|
|
5
|
+
|
|
6
|
+
const command: CommandModule<ShellOptions, ShellOptions> = {
|
|
7
|
+
command: "shell",
|
|
8
|
+
describe: "Open interactive SQL shell with transaction (similar to psql)",
|
|
9
|
+
builder: args => {
|
|
10
|
+
return args
|
|
11
|
+
.options("schema", {
|
|
12
|
+
type: "string",
|
|
13
|
+
alias: "s",
|
|
14
|
+
describe: "Caminho para o schema.prisma (opcional)",
|
|
15
|
+
})
|
|
16
|
+
.options("label", {
|
|
17
|
+
type: "string",
|
|
18
|
+
alias: "l",
|
|
19
|
+
describe: "Label para a revisão gerada ao commitar",
|
|
20
|
+
})
|
|
21
|
+
.options("add", {
|
|
22
|
+
type: "boolean",
|
|
23
|
+
describe: "Adicionar o arquivo .tar.gz ao git após gerar revisão",
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
handler: (argv) => {
|
|
27
|
+
shell(argv).catch((reason) => {
|
|
28
|
+
console.error("Erro no shell:", reason);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export = command;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["shell.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,YAAY;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,KAAK,CAAC,IAAI,EAAE,YAAY,iBA0F7C"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// filename: src/tools/shell.ts
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
27
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
28
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
29
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
30
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
31
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
32
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.shell = shell;
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const Path = __importStar(require("node:path"));
|
|
42
|
+
const os = __importStar(require("node:os"));
|
|
43
|
+
const readline = __importStar(require("node:readline"));
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
const common_1 = require("./common");
|
|
46
|
+
const fs_1 = require("../utils/fs");
|
|
47
|
+
const tar = __importStar(require("tar"));
|
|
48
|
+
const yaml = __importStar(require("yaml"));
|
|
49
|
+
function shell(opts) {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
require('dotenv').config();
|
|
52
|
+
const { psm, driver, home } = yield (0, common_1.psmLockup)({ schema: opts.schema, driver: opts.driver });
|
|
53
|
+
const migrator = driver.migrator({
|
|
54
|
+
url: process.env[psm.psm.url],
|
|
55
|
+
migrate: "",
|
|
56
|
+
check: "",
|
|
57
|
+
core: "",
|
|
58
|
+
});
|
|
59
|
+
console.log(chalk_1.default.cyan("🐚 PSM Shell Interativo"));
|
|
60
|
+
console.log(chalk_1.default.gray("Digite comandos SQL (terminados com ';'). Comandos especiais:"));
|
|
61
|
+
console.log(chalk_1.default.gray(" \\commit - commita a transação e gera revisão"));
|
|
62
|
+
console.log(chalk_1.default.gray(" \\rollback - desfaz a transação e sai"));
|
|
63
|
+
console.log(chalk_1.default.gray(" \\exit - sai sem commitar (rollback implícito)"));
|
|
64
|
+
// Inicia transação
|
|
65
|
+
const beginResult = yield migrator.execute([{ raw: "BEGIN", group: "shell", filename: "shell" }]);
|
|
66
|
+
if (!beginResult.success) {
|
|
67
|
+
console.error(chalk_1.default.red("Erro ao iniciar transação:"), beginResult.error);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const successfulCommands = [];
|
|
71
|
+
const rl = readline.createInterface({
|
|
72
|
+
input: process.stdin,
|
|
73
|
+
output: process.stdout,
|
|
74
|
+
prompt: chalk_1.default.green("psm> "),
|
|
75
|
+
});
|
|
76
|
+
let currentCommand = "";
|
|
77
|
+
rl.prompt();
|
|
78
|
+
rl.on('line', (line) => __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
const trimmed = line.trim();
|
|
80
|
+
// Comandos especiais
|
|
81
|
+
if (trimmed === "\\commit") {
|
|
82
|
+
yield commitTransaction(migrator, successfulCommands, psm, home, opts);
|
|
83
|
+
rl.close();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (trimmed === "\\rollback") {
|
|
87
|
+
yield rollbackTransaction(migrator);
|
|
88
|
+
console.log(chalk_1.default.yellow("Transação revertida. Nenhuma revisão gerada."));
|
|
89
|
+
rl.close();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (trimmed === "\\exit") {
|
|
93
|
+
yield rollbackTransaction(migrator);
|
|
94
|
+
console.log(chalk_1.default.yellow("Saindo sem commitar."));
|
|
95
|
+
rl.close();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Acumula linhas até encontrar ';' no final (ignorando espaços)
|
|
99
|
+
currentCommand += line + "\n";
|
|
100
|
+
if (line.trim().endsWith(';')) {
|
|
101
|
+
const sql = currentCommand.trim();
|
|
102
|
+
if (sql) {
|
|
103
|
+
try {
|
|
104
|
+
const result = yield migrator.execute([{ raw: sql, group: "shell", filename: "shell" }]);
|
|
105
|
+
if (result.success) {
|
|
106
|
+
console.log(chalk_1.default.green("✔ Comando executado com sucesso."));
|
|
107
|
+
successfulCommands.push(sql);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
console.error(chalk_1.default.red("✘ Erro ao executar comando:"), result.error);
|
|
111
|
+
// Em caso de erro, podemos dar rollback imediato
|
|
112
|
+
yield rollbackTransaction(migrator);
|
|
113
|
+
console.log(chalk_1.default.red("Transação revertida devido a erro. Encerrando."));
|
|
114
|
+
rl.close();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
console.error(chalk_1.default.red("Exceção:"), err.message);
|
|
120
|
+
yield rollbackTransaction(migrator);
|
|
121
|
+
rl.close();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
currentCommand = "";
|
|
126
|
+
rl.prompt();
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
rl.prompt();
|
|
130
|
+
}
|
|
131
|
+
})).on('close', () => {
|
|
132
|
+
process.exit(0);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function commitTransaction(migrator, commands, psm, home, opts) {
|
|
137
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
138
|
+
const commitResult = yield migrator.execute([{ raw: "COMMIT", group: "shell", filename: "shell" }]);
|
|
139
|
+
if (!commitResult.success) {
|
|
140
|
+
console.error(chalk_1.default.red("Erro ao commitar transação:"), commitResult.error);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
console.log(chalk_1.default.green("✔ Transação commitada."));
|
|
144
|
+
// Gera revisão com os comandos bem-sucedidos
|
|
145
|
+
yield createRevisionFromCommands(commands, psm, home, opts);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function rollbackTransaction(migrator) {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
const rollbackResult = yield migrator.execute([{ raw: "ROLLBACK", group: "shell", filename: "shell" }]);
|
|
151
|
+
if (!rollbackResult.success) {
|
|
152
|
+
console.error(chalk_1.default.red("Erro ao fazer rollback:"), rollbackResult.error);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function createRevisionFromCommands(commands, psm, home, opts) {
|
|
157
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
158
|
+
var _a;
|
|
159
|
+
if (commands.length === 0) {
|
|
160
|
+
console.log(chalk_1.default.yellow("Nenhum comando bem-sucedido para gerar revisão."));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const moment = require('moment');
|
|
164
|
+
const now = moment();
|
|
165
|
+
const instante = now.format('YYYYMMDDHHmmss');
|
|
166
|
+
const safeLabel = opts.label ? ` - ${(0, fs_1.sanitizeLabel)(opts.label)}` : '';
|
|
167
|
+
const revDirName = `${instante}${safeLabel}`;
|
|
168
|
+
const revisionsBase = Path.join(home, "psm/revisions/schema");
|
|
169
|
+
const tempDir = fs.mkdtempSync(Path.join(os.tmpdir(), "psm-shell-"));
|
|
170
|
+
try {
|
|
171
|
+
// Cria migration.sql com todos os comandos
|
|
172
|
+
const migrationContent = commands.join(';\n') + (commands.length ? ';' : '');
|
|
173
|
+
fs.writeFileSync(Path.join(tempDir, "migration.sql"), migrationContent);
|
|
174
|
+
// Gera psm.yml básico
|
|
175
|
+
const revPsm = {
|
|
176
|
+
psm: {
|
|
177
|
+
migration: psm.psm.migration,
|
|
178
|
+
driver: psm.psm.driver,
|
|
179
|
+
url: psm.psm.url,
|
|
180
|
+
sys: psm.psm.sys,
|
|
181
|
+
output: psm.psm.output,
|
|
182
|
+
schema: psm.psm.schema,
|
|
183
|
+
},
|
|
184
|
+
test: {
|
|
185
|
+
check: "skipped",
|
|
186
|
+
success: true,
|
|
187
|
+
messages: [],
|
|
188
|
+
},
|
|
189
|
+
migration: {
|
|
190
|
+
revision: `${instante} - ${psm.psm.migration}`,
|
|
191
|
+
instante: instante,
|
|
192
|
+
preview: (_a = psm.migration) === null || _a === void 0 ? void 0 : _a.revision, // último preview se houver
|
|
193
|
+
label: opts.label || "",
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
fs.writeFileSync(Path.join(tempDir, "psm.yml"), yaml.stringify(revPsm));
|
|
197
|
+
// Cria o diretório de destino com o nome da revisão
|
|
198
|
+
const targetDir = Path.join(revisionsBase, revDirName);
|
|
199
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
200
|
+
fs.cpSync(tempDir, targetDir, { recursive: true });
|
|
201
|
+
// Compacta
|
|
202
|
+
const archiveName = Path.join(revisionsBase, `${revDirName}.tar.gz`);
|
|
203
|
+
yield tar.c({
|
|
204
|
+
gzip: { level: 9 },
|
|
205
|
+
file: archiveName,
|
|
206
|
+
cwd: revisionsBase,
|
|
207
|
+
}, [revDirName]);
|
|
208
|
+
console.log(chalk_1.default.green(`✔ Revisão gerada: ${archiveName}`));
|
|
209
|
+
// Remove diretório descompactado
|
|
210
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
211
|
+
// Adiciona ao git se solicitado
|
|
212
|
+
if (opts.add) {
|
|
213
|
+
(0, fs_1.gitAddPath)(home, archiveName);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["shell.ts"],"names":[],"mappings":";AAAA,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqB/B,sBA0FC;AA7GD,4CAA8B;AAC9B,gDAAkC;AAClC,4CAA8B;AAC9B,wDAA0C;AAC1C,kDAA0B;AAE1B,qCAAqC;AACrC,oCAAwD;AAExD,yCAA2B;AAC3B,2CAA6B;AAS7B,SAAsB,KAAK,CAAC,IAAkB;;QAC1C,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;QAE3B,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAA,kBAAS,EAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAE5F,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;YAC7B,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;YAC7B,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,EAAE;SACX,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC,CAAC;QACzF,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC,CAAC;QAEhF,mBAAmB;QACnB,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAClG,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;YAC1E,OAAO;QACX,CAAC;QAED,MAAM,kBAAkB,GAAa,EAAE,CAAC;QACxC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAChC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,MAAM,EAAE,eAAK,CAAC,KAAK,CAAC,OAAO,CAAC;SAC/B,CAAC,CAAC;QAEH,IAAI,cAAc,GAAG,EAAE,CAAC;QACxB,EAAE,CAAC,MAAM,EAAE,CAAC;QAEZ,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAO,IAAI,EAAE,EAAE;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAE5B,qBAAqB;YACrB,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;gBACzB,MAAM,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;gBACvE,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACX,CAAC;YACD,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;gBAC3B,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;gBACpC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,8CAA8C,CAAC,CAAC,CAAC;gBAC1E,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACX,CAAC;YACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACvB,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;gBACpC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC;gBAClD,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACX,CAAC;YAED,gEAAgE;YAChE,cAAc,IAAI,IAAI,GAAG,IAAI,CAAC;YAC9B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;gBAClC,IAAI,GAAG,EAAE,CAAC;oBACN,IAAI,CAAC;wBACD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;wBACzF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;4BACjB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;4BAC7D,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wBACjC,CAAC;6BAAM,CAAC;4BACJ,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;4BACtE,iDAAiD;4BACjD,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;4BACpC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC,CAAC;4BACzE,EAAE,CAAC,KAAK,EAAE,CAAC;4BACX,OAAO;wBACX,CAAC;oBACL,CAAC;oBAAC,OAAO,GAAQ,EAAE,CAAC;wBAChB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;wBAClD,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;wBACpC,EAAE,CAAC,KAAK,EAAE,CAAC;wBACX,OAAO;oBACX,CAAC;gBACL,CAAC;gBACD,cAAc,GAAG,EAAE,CAAC;gBACpB,EAAE,CAAC,MAAM,EAAE,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACJ,EAAE,CAAC,MAAM,EAAE,CAAC;YAChB,CAAC;QACL,CAAC,CAAA,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACP,CAAC;CAAA;AAED,SAAe,iBAAiB,CAC5B,QAAqB,EACrB,QAAkB,EAClB,GAAQ,EACR,IAAY,EACZ,IAAkB;;QAElB,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QACpG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC5E,OAAO;QACX,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAEnD,6CAA6C;QAC7C,MAAM,0BAA0B,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;CAAA;AAED,SAAe,mBAAmB,CAAC,QAAqB;;QACpD,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QACxG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;QAC9E,CAAC;IACL,CAAC;CAAA;AAED,SAAe,0BAA0B,CAAC,QAAkB,EAAE,GAAQ,EAAE,IAAY,EAAE,IAAkB;;;QACpG,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,iDAAiD,CAAC,CAAC,CAAC;YAC7E,OAAO;QACX,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,IAAA,kBAAa,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,MAAM,UAAU,GAAG,GAAG,QAAQ,GAAG,SAAS,EAAE,CAAC;QAC7C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;QAErE,IAAI,CAAC;YACD,2CAA2C;YAC3C,MAAM,gBAAgB,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7E,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,gBAAgB,CAAC,CAAC;YAExE,sBAAsB;YACtB,MAAM,MAAM,GAAkB;gBAC1B,GAAG,EAAE;oBACD,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS;oBAC5B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM;oBACtB,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG;oBAChB,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG;oBAChB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM;oBACtB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM;iBACzB;gBACD,IAAI,EAAE;oBACF,KAAK,EAAE,SAAS;oBAChB,OAAO,EAAE,IAAI;oBACb,QAAQ,EAAE,EAAE;iBACf;gBACD,SAAS,EAAE;oBACP,QAAQ,EAAE,GAAG,QAAQ,MAAM,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE;oBAC9C,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAE,MAAA,GAAG,CAAC,SAAS,0CAAE,QAAQ,EAAE,2BAA2B;oBAC7D,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;iBAC1B;aACJ,CAAC;YACF,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YAExE,oDAAoD;YACpD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;YACvD,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEnD,WAAW;YACX,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,UAAU,SAAS,CAAC,CAAC;YACrE,MAAM,GAAG,CAAC,CAAC,CACP;gBACI,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;gBAClB,IAAI,EAAE,WAAW;gBACjB,GAAG,EAAE,aAAa;aACrB,EACD,CAAC,UAAU,CAAC,CACf,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,qBAAqB,WAAW,EAAE,CAAC,CAAC,CAAC;YAE7D,iCAAiC;YACjC,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAEvD,gCAAgC;YAChC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;gBACX,IAAA,eAAU,EAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAClC,CAAC;QACL,CAAC;gBAAS,CAAC;YACP,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;IACL,CAAC;CAAA"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// filename: src/tools/shell.ts
|
|
2
|
+
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as Path from "node:path";
|
|
5
|
+
import * as os from "node:os";
|
|
6
|
+
import * as readline from "node:readline";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import { PSMMigrator } from "../driver";
|
|
9
|
+
import { psmLockup } from "./common";
|
|
10
|
+
import { gitAddPath, sanitizeLabel } from "../utils/fs";
|
|
11
|
+
import { PSMConfigFile } from "../configs";
|
|
12
|
+
import * as tar from "tar";
|
|
13
|
+
import * as yaml from "yaml";
|
|
14
|
+
|
|
15
|
+
export interface ShellOptions {
|
|
16
|
+
schema?: string;
|
|
17
|
+
label?: string;
|
|
18
|
+
add?: boolean; // adicionar ao git após gerar revisão
|
|
19
|
+
driver?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function shell(opts: ShellOptions) {
|
|
23
|
+
require('dotenv').config();
|
|
24
|
+
|
|
25
|
+
const { psm, driver, home } = await psmLockup({ schema: opts.schema, driver: opts.driver });
|
|
26
|
+
|
|
27
|
+
const migrator = driver.migrator({
|
|
28
|
+
url: process.env[psm.psm.url],
|
|
29
|
+
migrate: "",
|
|
30
|
+
check: "",
|
|
31
|
+
core: "",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
console.log(chalk.cyan("🐚 PSM Shell Interativo"));
|
|
35
|
+
console.log(chalk.gray("Digite comandos SQL (terminados com ';'). Comandos especiais:"));
|
|
36
|
+
console.log(chalk.gray(" \\commit - commita a transação e gera revisão"));
|
|
37
|
+
console.log(chalk.gray(" \\rollback - desfaz a transação e sai"));
|
|
38
|
+
console.log(chalk.gray(" \\exit - sai sem commitar (rollback implícito)"));
|
|
39
|
+
|
|
40
|
+
// Inicia transação
|
|
41
|
+
const beginResult = await migrator.execute([{ raw: "BEGIN", group: "shell", filename: "shell" }]);
|
|
42
|
+
if (!beginResult.success) {
|
|
43
|
+
console.error(chalk.red("Erro ao iniciar transação:"), beginResult.error);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const successfulCommands: string[] = [];
|
|
48
|
+
const rl = readline.createInterface({
|
|
49
|
+
input: process.stdin,
|
|
50
|
+
output: process.stdout,
|
|
51
|
+
prompt: chalk.green("psm> "),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
let currentCommand = "";
|
|
55
|
+
rl.prompt();
|
|
56
|
+
|
|
57
|
+
rl.on('line', async (line) => {
|
|
58
|
+
const trimmed = line.trim();
|
|
59
|
+
|
|
60
|
+
// Comandos especiais
|
|
61
|
+
if (trimmed === "\\commit") {
|
|
62
|
+
await commitTransaction(migrator, successfulCommands, psm, home, opts);
|
|
63
|
+
rl.close();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (trimmed === "\\rollback") {
|
|
67
|
+
await rollbackTransaction(migrator);
|
|
68
|
+
console.log(chalk.yellow("Transação revertida. Nenhuma revisão gerada."));
|
|
69
|
+
rl.close();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (trimmed === "\\exit") {
|
|
73
|
+
await rollbackTransaction(migrator);
|
|
74
|
+
console.log(chalk.yellow("Saindo sem commitar."));
|
|
75
|
+
rl.close();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Acumula linhas até encontrar ';' no final (ignorando espaços)
|
|
80
|
+
currentCommand += line + "\n";
|
|
81
|
+
if (line.trim().endsWith(';')) {
|
|
82
|
+
const sql = currentCommand.trim();
|
|
83
|
+
if (sql) {
|
|
84
|
+
try {
|
|
85
|
+
const result = await migrator.execute([{ raw: sql, group: "shell", filename: "shell" }]);
|
|
86
|
+
if (result.success) {
|
|
87
|
+
console.log(chalk.green("✔ Comando executado com sucesso."));
|
|
88
|
+
successfulCommands.push(sql);
|
|
89
|
+
} else {
|
|
90
|
+
console.error(chalk.red("✘ Erro ao executar comando:"), result.error);
|
|
91
|
+
// Em caso de erro, podemos dar rollback imediato
|
|
92
|
+
await rollbackTransaction(migrator);
|
|
93
|
+
console.log(chalk.red("Transação revertida devido a erro. Encerrando."));
|
|
94
|
+
rl.close();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
} catch (err: any) {
|
|
98
|
+
console.error(chalk.red("Exceção:"), err.message);
|
|
99
|
+
await rollbackTransaction(migrator);
|
|
100
|
+
rl.close();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
currentCommand = "";
|
|
105
|
+
rl.prompt();
|
|
106
|
+
} else {
|
|
107
|
+
rl.prompt();
|
|
108
|
+
}
|
|
109
|
+
}).on('close', () => {
|
|
110
|
+
process.exit(0);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function commitTransaction(
|
|
115
|
+
migrator: PSMMigrator,
|
|
116
|
+
commands: string[],
|
|
117
|
+
psm: any,
|
|
118
|
+
home: string,
|
|
119
|
+
opts: ShellOptions
|
|
120
|
+
) {
|
|
121
|
+
const commitResult = await migrator.execute([{ raw: "COMMIT", group: "shell", filename: "shell" }]);
|
|
122
|
+
if (!commitResult.success) {
|
|
123
|
+
console.error(chalk.red("Erro ao commitar transação:"), commitResult.error);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
console.log(chalk.green("✔ Transação commitada."));
|
|
127
|
+
|
|
128
|
+
// Gera revisão com os comandos bem-sucedidos
|
|
129
|
+
await createRevisionFromCommands(commands, psm, home, opts);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function rollbackTransaction(migrator: PSMMigrator) {
|
|
133
|
+
const rollbackResult = await migrator.execute([{ raw: "ROLLBACK", group: "shell", filename: "shell" }]);
|
|
134
|
+
if (!rollbackResult.success) {
|
|
135
|
+
console.error(chalk.red("Erro ao fazer rollback:"), rollbackResult.error);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function createRevisionFromCommands(commands: string[], psm: any, home: string, opts: ShellOptions) {
|
|
140
|
+
if (commands.length === 0) {
|
|
141
|
+
console.log(chalk.yellow("Nenhum comando bem-sucedido para gerar revisão."));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const moment = require('moment');
|
|
146
|
+
const now = moment();
|
|
147
|
+
const instante = now.format('YYYYMMDDHHmmss');
|
|
148
|
+
const safeLabel = opts.label ? ` - ${sanitizeLabel(opts.label)}` : '';
|
|
149
|
+
const revDirName = `${instante}${safeLabel}`;
|
|
150
|
+
const revisionsBase = Path.join(home, "psm/revisions/schema");
|
|
151
|
+
const tempDir = fs.mkdtempSync(Path.join(os.tmpdir(), "psm-shell-"));
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
// Cria migration.sql com todos os comandos
|
|
155
|
+
const migrationContent = commands.join(';\n') + (commands.length ? ';' : '');
|
|
156
|
+
fs.writeFileSync(Path.join(tempDir, "migration.sql"), migrationContent);
|
|
157
|
+
|
|
158
|
+
// Gera psm.yml básico
|
|
159
|
+
const revPsm: PSMConfigFile = {
|
|
160
|
+
psm: {
|
|
161
|
+
migration: psm.psm.migration,
|
|
162
|
+
driver: psm.psm.driver,
|
|
163
|
+
url: psm.psm.url,
|
|
164
|
+
sys: psm.psm.sys,
|
|
165
|
+
output: psm.psm.output,
|
|
166
|
+
schema: psm.psm.schema,
|
|
167
|
+
},
|
|
168
|
+
test: {
|
|
169
|
+
check: "skipped",
|
|
170
|
+
success: true,
|
|
171
|
+
messages: [],
|
|
172
|
+
},
|
|
173
|
+
migration: {
|
|
174
|
+
revision: `${instante} - ${psm.psm.migration}`,
|
|
175
|
+
instante: instante,
|
|
176
|
+
preview: psm.migration?.revision, // último preview se houver
|
|
177
|
+
label: opts.label || "",
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
fs.writeFileSync(Path.join(tempDir, "psm.yml"), yaml.stringify(revPsm));
|
|
181
|
+
|
|
182
|
+
// Cria o diretório de destino com o nome da revisão
|
|
183
|
+
const targetDir = Path.join(revisionsBase, revDirName);
|
|
184
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
185
|
+
fs.cpSync(tempDir, targetDir, { recursive: true });
|
|
186
|
+
|
|
187
|
+
// Compacta
|
|
188
|
+
const archiveName = Path.join(revisionsBase, `${revDirName}.tar.gz`);
|
|
189
|
+
await tar.c(
|
|
190
|
+
{
|
|
191
|
+
gzip: { level: 9 },
|
|
192
|
+
file: archiveName,
|
|
193
|
+
cwd: revisionsBase,
|
|
194
|
+
},
|
|
195
|
+
[revDirName]
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
console.log(chalk.green(`✔ Revisão gerada: ${archiveName}`));
|
|
199
|
+
|
|
200
|
+
// Remove diretório descompactado
|
|
201
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
202
|
+
|
|
203
|
+
// Adiciona ao git se solicitado
|
|
204
|
+
if (opts.add) {
|
|
205
|
+
gitAddPath(home, archiveName);
|
|
206
|
+
}
|
|
207
|
+
} finally {
|
|
208
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
209
|
+
}
|
|
210
|
+
}
|