@prisma-psm/core 1.0.3 → 1.0.4

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.
Files changed (60) hide show
  1. package/README.md +190 -2
  2. package/package.json +12 -4
  3. package/src/configs.d.ts +20 -0
  4. package/src/configs.d.ts.map +1 -0
  5. package/src/configs.js +3 -0
  6. package/src/configs.js.map +1 -0
  7. package/src/configs.ts +19 -0
  8. package/src/driver.d.ts +1 -0
  9. package/src/driver.d.ts.map +1 -1
  10. package/src/driver.ts +2 -1
  11. package/src/index.d.ts +0 -1
  12. package/src/index.d.ts.map +1 -1
  13. package/src/index.js +0 -159
  14. package/src/index.js.map +1 -1
  15. package/src/index.ts +1 -173
  16. package/src/launcher/commands/check.d.ts +4 -0
  17. package/src/launcher/commands/check.d.ts.map +1 -0
  18. package/src/launcher/commands/check.js +13 -0
  19. package/src/launcher/commands/check.js.map +1 -0
  20. package/src/launcher/commands/check.ts +17 -0
  21. package/src/launcher/commands/deploy.d.ts +5 -0
  22. package/src/launcher/commands/deploy.d.ts.map +1 -0
  23. package/src/launcher/commands/deploy.js +13 -0
  24. package/src/launcher/commands/deploy.js.map +1 -0
  25. package/src/launcher/commands/deploy.ts +17 -0
  26. package/src/launcher/commands/generate.d.ts +4 -0
  27. package/src/launcher/commands/generate.d.ts.map +1 -0
  28. package/src/launcher/commands/generate.js +14 -0
  29. package/src/launcher/commands/generate.js.map +1 -0
  30. package/src/launcher/commands/generate.ts +18 -0
  31. package/src/launcher/commands/migrate.d.ts +5 -0
  32. package/src/launcher/commands/migrate.d.ts.map +1 -0
  33. package/src/launcher/commands/migrate.js +29 -0
  34. package/src/launcher/commands/migrate.js.map +1 -0
  35. package/src/launcher/commands/migrate.ts +35 -0
  36. package/src/launcher/index.d.ts +3 -0
  37. package/src/launcher/index.d.ts.map +1 -0
  38. package/src/launcher/index.js +17 -0
  39. package/src/launcher/index.js.map +1 -0
  40. package/src/launcher/index.ts +14 -0
  41. package/src/tools/check.d.ts +2 -0
  42. package/src/tools/check.d.ts.map +1 -0
  43. package/src/tools/check.js +6 -0
  44. package/src/tools/check.js.map +1 -0
  45. package/src/tools/check.ts +3 -0
  46. package/src/tools/deploy.d.ts +7 -0
  47. package/src/tools/deploy.d.ts.map +1 -0
  48. package/src/tools/deploy.js +3 -0
  49. package/src/tools/deploy.js.map +1 -0
  50. package/src/tools/deploy.ts +6 -0
  51. package/src/tools/generate.d.ts +2 -0
  52. package/src/tools/generate.d.ts.map +1 -0
  53. package/src/tools/generate.js +158 -0
  54. package/src/tools/generate.js.map +1 -0
  55. package/src/tools/generate.ts +151 -0
  56. package/src/tools/migrate.d.ts +8 -0
  57. package/src/tools/migrate.d.ts.map +1 -0
  58. package/src/tools/migrate.js +137 -0
  59. package/src/tools/migrate.js.map +1 -0
  60. package/src/tools/migrate.ts +121 -0
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.generate = generate;
36
+ const fs = __importStar(require("fs"));
37
+ const Path = __importStar(require("node:path"));
38
+ const yaml = __importStar(require("yaml"));
39
+ const generator_helper_1 = require("@prisma/generator-helper");
40
+ const index_1 = require("../extractor/index");
41
+ const nanoid_1 = require("nanoid");
42
+ const docs_1 = require("../docs");
43
+ function write(sql, dirname, file) {
44
+ fs.writeFileSync(Path.join(dirname, file), sql);
45
+ }
46
+ function generate() {
47
+ (0, generator_helper_1.generatorHandler)({
48
+ onManifest() {
49
+ return {
50
+ version: '1.0.0',
51
+ defaultOutput: './psm',
52
+ prettyName: 'PSM - Prisma Safe Migration',
53
+ };
54
+ },
55
+ onGenerate(options) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ var _a, _b;
58
+ try {
59
+ const output = ((_a = options.generator.output) === null || _a === void 0 ? void 0 : _a.value) || "./psm";
60
+ const home = Path.dirname(options.schemaPath);
61
+ const definition = Path.join(output, "definitions");
62
+ const revisions = Path.join(output, "revisions");
63
+ const next = Path.join(output, "next");
64
+ fs.mkdirSync(definition, { recursive: true });
65
+ fs.mkdirSync(revisions, { recursive: true });
66
+ fs.mkdirSync(next, { recursive: true });
67
+ const { datamodels, models } = (0, index_1.extractModels)(options, definition);
68
+ let rand = (0, nanoid_1.customRandom)("abcdefghijklmnopqrstuvwxyz0123456789", 8, nanoid_1.random);
69
+ const migration = rand();
70
+ const configs = options.generator.config;
71
+ const url = process.env[configs.url];
72
+ const driver = yield Promise.resolve(`${configs.driver}`).then(s => __importStar(require(s)));
73
+ let usePrepare = (model) => {
74
+ return Promise.resolve(driver.prepare(model));
75
+ };
76
+ for (let i = 0; i < models.length; i++) {
77
+ const model = models[i];
78
+ model.model = model.name;
79
+ model.name = model.dbName || model.model;
80
+ model.temp = `temp_${i}_${model.name}`;
81
+ if (!!model.documentation) {
82
+ model.psm = (0, docs_1.parsePsmDoc)(model.documentation);
83
+ }
84
+ model.fields.forEach(field => {
85
+ if (!!field.documentation)
86
+ field.psm = (0, docs_1.parsePsmDoc)(field.documentation);
87
+ });
88
+ yield usePrepare(model);
89
+ }
90
+ const opts = {
91
+ models: models,
92
+ indexes: datamodels.indexes,
93
+ migration: migration,
94
+ shadow: `psm_shadow_${rand()}`,
95
+ backup: "backup",
96
+ sys: "sys",
97
+ };
98
+ const generator = driver.generator(opts);
99
+ const check = generator.check();
100
+ const migrate = generator.migrate();
101
+ write(check, next, "migration.next.check.sql");
102
+ let test;
103
+ if (!!url) {
104
+ test = yield driver.migrator({
105
+ migrate: migrate,
106
+ check: check,
107
+ url: url
108
+ }).test();
109
+ }
110
+ console.log(test);
111
+ if (!configs.url) {
112
+ write(migrate, next, "migration.next.sql");
113
+ }
114
+ else if (!!test && test.success) {
115
+ write(migrate, next, "migration.next.sql");
116
+ }
117
+ else {
118
+ console.error(`TEST OF MIGRATION FAILED! Check file migration.next.check.sql`);
119
+ if (fs.existsSync(Path.join(next, "migration.next.sql")))
120
+ fs.unlinkSync(Path.join(next, "migration.next.sql"));
121
+ if (!!((_b = test === null || test === void 0 ? void 0 : test.messages) === null || _b === void 0 ? void 0 : _b.length)) {
122
+ console.log("TESTE MESSAGES>>>>>>>>>>");
123
+ test.messages.forEach(value => {
124
+ console.log(value);
125
+ });
126
+ }
127
+ if (!!(test === null || test === void 0 ? void 0 : test.error)) {
128
+ console.log("TESTE ERROR>>>>>>>>>>");
129
+ console.error(test === null || test === void 0 ? void 0 : test.error);
130
+ }
131
+ }
132
+ const psm = {
133
+ psm: {
134
+ migration: migration,
135
+ driver: options.generator.config.driver,
136
+ url: configs.url,
137
+ output: output,
138
+ schema: options.schemaPath,
139
+ },
140
+ test: {
141
+ check: !!test ? "checked" : "skipped",
142
+ success: test === null || test === void 0 ? void 0 : test.success,
143
+ messages: test === null || test === void 0 ? void 0 : test.messages
144
+ }
145
+ };
146
+ fs.writeFileSync(Path.join(home, "psm.yml"), yaml.stringify(psm, null, {
147
+ version: "next",
148
+ }));
149
+ }
150
+ catch (e) {
151
+ console.error("console.error", e);
152
+ throw e;
153
+ }
154
+ });
155
+ },
156
+ });
157
+ }
158
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["generate.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,4BA+HC;AAtJD,uCAAwB;AACxB,gDAAkC;AAClC,2CAA6B;AAC7B,+DAA+F;AAC/F,8CAAiD;AACjD,mCAA4C;AAU5C,kCAAoC;AAGpC,SAAS,KAAK,CAAE,GAAU,EAAE,OAAc,EAAE,IAAW;IACnD,EAAE,CAAC,aAAa,CAAE,IAAI,CAAC,IAAI,CAAE,OAAO,EAAE,IAAI,CAAE,EAAE,GAAG,CAAE,CAAC;AACxD,CAAC;AAGD,SAAgB,QAAQ;IACpB,IAAA,mCAAgB,EAAC;QACb,UAAU;YACN,OAAO;gBACH,OAAO,EAAE,OAAO;gBAChB,aAAa,EAAE,OAAO;gBACtB,UAAU,EAAE,6BAA6B;aAC5C,CAAA;QACL,CAAC;QACK,UAAU,CAAC,OAAyB;;;gBACtC,IAAG,CAAC;oBAEA,MAAM,MAAM,GAAG,CAAA,MAAA,OAAO,CAAC,SAAS,CAAC,MAAM,0CAAE,KAAK,KAAI,OAAO,CAAC;oBAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAE,OAAO,CAAC,UAAU,CAAE,CAAC;oBAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAE,MAAM,EAAE,aAAa,CAAC,CAAC;oBACrD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAE,MAAM,EAAE,WAAW,CAAC,CAAC;oBAClD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAE,MAAM,EAAE,MAAM,CAAC,CAAC;oBAExC,EAAE,CAAC,SAAS,CAAE,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC/C,EAAE,CAAC,SAAS,CAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC9C,EAAE,CAAC,SAAS,CAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;oBACzC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAC,GAAG,IAAA,qBAAa,EAAE,OAAO,EAAE,UAAU,CAAE,CAAC;oBAGnE,IAAI,IAAI,GAAG,IAAA,qBAAY,EAAE,sCAAsC,EAAC,CAAC,EAAE,eAAM,CAAC,CAAC;oBAC3E,MAAM,SAAS,GAAG,IAAI,EAAE,CAAC;oBACzB,MAAM,OAAO,GAAiB,OAAO,CAAC,SAAS,CAAC,MAAa,CAAC;oBAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAW,CAAC;oBAG/C,MAAM,MAAM,GAAG,yBAAc,OAAO,CAAC,MAAM,uCAAe,CAAC;oBAG3D,IAAI,UAAU,GAAE,CAAE,KAAkB,EAAE,EAAE;wBACpC,OAAO,OAAO,CAAC,OAAO,CAAE,MAAM,CAAC,OAAO,CAAE,KAAK,CAAE,CAAE,CAAA;oBACrD,CAAC,CAAA;oBAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;wBACrC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAwB,CAAC;wBAC/C,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;wBACzB,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,IAAE,KAAK,CAAC,KAAK,CAAC;wBACvC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;wBAGvC,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;4BACxB,KAAK,CAAC,GAAG,GAAG,IAAA,kBAAW,EAAY,KAAK,CAAC,aAAa,CAAE,CAAC;wBAC7D,CAAC;wBACD,KAAK,CAAC,MAAM,CAAC,OAAO,CAAE,KAAK,CAAC,EAAE;4BAC1B,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa;gCAAG,KAAK,CAAC,GAAG,GAAG,IAAA,kBAAW,EAAY,KAAK,CAAC,aAAa,CAAE,CAAC;wBACzF,CAAC,CAAC,CAAC;wBACH,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;oBAC5B,CAAC;oBAED,MAAM,IAAI,GAAqB;wBAC3B,MAAM,EAAE,MAAa;wBACrB,OAAO,EAAE,UAAU,CAAC,OAAO;wBAC3B,SAAS,EAAE,SAAS;wBACpB,MAAM,EAAE,cAAc,IAAI,EAAE,EAAE;wBAC9B,MAAM,EAAE,QAAQ;wBAChB,GAAG,EAAE,KAAK;qBACb,CAAC;oBAEF,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;oBAEzC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC;oBAChC,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;oBAEpC,KAAK,CAAE,KAAK,EAAE,IAAI,EAAE,0BAA0B,CAAE,CAAC;oBAGjD,IAAI,IAAiC,CAAC;oBAEtC,IAAI,CAAC,CAAC,GAAG,EAAG,CAAC;wBACT,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;4BACzB,OAAO,EAAE,OAAO;4BAChB,KAAK,EAAE,KAAK;4BACZ,GAAG,EAAE,GAAa;yBACrB,CAAC,CAAC,IAAI,EAAE,CAAC;oBACd,CAAC;oBAGD,OAAO,CAAC,GAAG,CAAE,IAAI,CAAE,CAAC;oBAEpB,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;wBACf,KAAK,CAAE,OAAO,EAAE,IAAI,EAAE,oBAAoB,CAAE,CAAC;oBACjD,CAAC;yBAAM,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAG,CAAC;wBACjC,KAAK,CAAE,OAAO,EAAE,IAAI,EAAE,oBAAoB,CAAE,CAAC;oBACjD,CAAC;yBAAM,CAAC;wBACJ,OAAO,CAAC,KAAK,CAAE,+DAA+D,CAAE,CAAC;wBACjF,IAAI,EAAE,CAAC,UAAU,CAAE,IAAI,CAAC,IAAI,CAAE,IAAI,EAAE,oBAAoB,CAAE,CAAE;4BAAG,EAAE,CAAC,UAAU,CAAE,IAAI,CAAC,IAAI,CAAE,IAAI,EAAE,oBAAoB,CAAE,CAAE,CAAC;wBAExH,IAAI,CAAC,CAAC,CAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ,0CAAE,MAAM,CAAA,EAAE,CAAC;4BAC3B,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;4BACxC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gCAC1B,OAAO,CAAC,GAAG,CAAE,KAAK,CAAC,CAAA;4BACvB,CAAC,CAAC,CAAC;wBACP,CAAC;wBAED,IAAI,CAAC,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,CAAA,EAAE,CAAC;4BAChB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;4BACrC,OAAO,CAAC,KAAK,CAAE,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,CAAE,CAAC;wBACjC,CAAC;oBACL,CAAC;oBAED,MAAM,GAAG,GAAiB;wBACtB,GAAG,EAAE;4BACD,SAAS,EAAE,SAAS;4BACpB,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAgB;4BACjD,GAAG,EAAE,OAAO,CAAC,GAAG;4BAChB,MAAM,EAAE,MAAM;4BACd,MAAM,EAAE,OAAO,CAAC,UAAU;yBAC7B;wBACD,IAAI,EAAE;4BACF,KAAK,EAAE,CAAC,CAAC,IAAI,CAAA,CAAC,CAAC,SAAS,CAAA,CAAC,CAAC,SAAS;4BACnC,OAAO,EAAE,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO;4BACtB,QAAQ,EAAE,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ;yBAC3B;qBACJ,CAAA;oBACD,EAAE,CAAC,aAAa,CAAE,IAAI,CAAC,IAAI,CAAE,IAAI,EAAE,SAAS,CAAE,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE;wBACtE,OAAO,EAAE,MAAM;qBAClB,CAAC,CAAE,CAAA;gBACR,CAAC;gBAAC,OAAO,CAAC,EAAC,CAAC;oBACR,OAAO,CAAC,KAAK,CAAE,eAAe,EAAE,CAAC,CAAE,CAAC;oBACpC,MAAM,CAAC,CAAA;gBACX,CAAC;YACL,CAAC;SAAA;KACJ,CAAC,CAAA;AACN,CAAC"}
@@ -0,0 +1,151 @@
1
+ import * as fs from 'fs'
2
+ import * as Path from "node:path";
3
+ import * as yaml from "yaml";
4
+ import {generatorHandler, GeneratorManifest, GeneratorOptions} from "@prisma/generator-helper";
5
+ import {extractModels} from "../extractor/index";
6
+ import {customRandom, random} from "nanoid";
7
+ import {
8
+ DriverConfigs,
9
+ ModelOptions,
10
+ PSMDriver,
11
+ PSMField,
12
+ PSMMigrationResult,
13
+ PSMModel,
14
+ PSMParserOptions
15
+ } from "../driver";
16
+ import {parsePsmDoc} from "../docs";
17
+ import {PSMConfigFile} from "../configs";
18
+
19
+ function write( sql:string, dirname:string, file:string){
20
+ fs.writeFileSync( Path.join( dirname, file ), sql );
21
+ }
22
+
23
+
24
+ export function generate(){
25
+ generatorHandler({
26
+ onManifest(): GeneratorManifest {
27
+ return {
28
+ version: '1.0.0',
29
+ defaultOutput: './psm',
30
+ prettyName: 'PSM - Prisma Safe Migration',
31
+ }
32
+ },
33
+ async onGenerate(options: GeneratorOptions) {
34
+ try{
35
+
36
+ const output = options.generator.output?.value || "./psm";
37
+ const home = Path.dirname( options.schemaPath );
38
+ const definition = Path.join( output, "definitions");
39
+ const revisions = Path.join( output, "revisions");
40
+ const next = Path.join( output, "next");
41
+
42
+ fs.mkdirSync( definition, { recursive: true });
43
+ fs.mkdirSync( revisions, { recursive: true });
44
+ fs.mkdirSync( next, { recursive: true });
45
+ const { datamodels, models} = extractModels( options, definition );
46
+
47
+
48
+ let rand = customRandom( "abcdefghijklmnopqrstuvwxyz0123456789",8, random);
49
+ const migration = rand();
50
+ const configs:DriverConfigs = options.generator.config as any;
51
+ const url = process.env[configs.url] as string;
52
+
53
+
54
+ const driver = await import( configs.driver ) as PSMDriver;
55
+
56
+
57
+ let usePrepare= ( model:ModelOptions )=>{
58
+ return Promise.resolve( driver.prepare( model ) )
59
+ }
60
+
61
+ for (let i = 0; i < models.length; i++) {
62
+ const model = models[i] as any as ModelOptions;
63
+ model.model = model.name;
64
+ model.name = model.dbName||model.model;
65
+ model.temp = `temp_${i}_${model.name}`;
66
+
67
+
68
+ if( !!model.documentation ){
69
+ model.psm = parsePsmDoc<PSMModel>( model.documentation );
70
+ }
71
+ model.fields.forEach( field => {
72
+ if( !!field.documentation ) field.psm = parsePsmDoc<PSMField>( field.documentation );
73
+ });
74
+ await usePrepare(model);
75
+ }
76
+
77
+ const opts: PSMParserOptions = {
78
+ models: models as any,
79
+ indexes: datamodels.indexes,
80
+ migration: migration,
81
+ shadow: `psm_shadow_${rand()}`,
82
+ backup: "backup",
83
+ sys: "sys",
84
+ };
85
+
86
+ const generator = driver.generator(opts);
87
+
88
+ const check = generator.check();
89
+ const migrate = generator.migrate();
90
+
91
+ write( check, next, "migration.next.check.sql" );
92
+
93
+
94
+ let test:PSMMigrationResult|undefined;
95
+
96
+ if( !!url ) {
97
+ test = await driver.migrator({
98
+ migrate: migrate,
99
+ check: check,
100
+ url: url as string
101
+ }).test();
102
+ }
103
+
104
+
105
+ console.log( test );
106
+
107
+ if( !configs.url ){
108
+ write( migrate, next, "migration.next.sql" );
109
+ } else if( !!test && test.success ) {
110
+ write( migrate, next, "migration.next.sql" );
111
+ } else {
112
+ console.error( `TEST OF MIGRATION FAILED! Check file migration.next.check.sql` );
113
+ if( fs.existsSync( Path.join( next, "migration.next.sql" ) ) ) fs.unlinkSync( Path.join( next, "migration.next.sql" ) );
114
+
115
+ if( !!test?.messages?.length ){
116
+ console.log("TESTE MESSAGES>>>>>>>>>>");
117
+ test.messages.forEach(value => {
118
+ console.log( value)
119
+ });
120
+ }
121
+
122
+ if( !!test?.error ){
123
+ console.log("TESTE ERROR>>>>>>>>>>");
124
+ console.error( test?.error );
125
+ }
126
+ }
127
+
128
+ const psm:PSMConfigFile = {
129
+ psm: {
130
+ migration: migration,
131
+ driver: options.generator.config.driver as string,
132
+ url: configs.url,
133
+ output: output,
134
+ schema: options.schemaPath,
135
+ },
136
+ test: {
137
+ check: !!test? "checked": "skipped",
138
+ success: test?.success,
139
+ messages: test?.messages
140
+ }
141
+ }
142
+ fs.writeFileSync( Path.join( home, "psm.yml" ), yaml.stringify(psm, null, {
143
+ version: "next",
144
+ }) )
145
+ } catch (e){
146
+ console.error( "console.error", e );
147
+ throw e
148
+ }
149
+ },
150
+ })
151
+ }
@@ -0,0 +1,8 @@
1
+ export interface MigrateOptions {
2
+ schema?: string;
3
+ generate?: string;
4
+ label?: string;
5
+ "generate-command": string;
6
+ }
7
+ export declare function migrate(opts: MigrateOptions): Promise<void>;
8
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["migrate.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC3B,MAAM,CAAC,EAAC,MAAM,CAAA;IACd,QAAQ,CAAC,EAAC,MAAM,CAAA;IAChB,KAAK,CAAC,EAAC,MAAM,CAAA;IACb,kBAAkB,EAAC,MAAM,CAAA;CAC5B;AACD,wBAAsB,OAAO,CAAE,IAAI,EAAC,cAAc,iBAiFjD"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.migrate = migrate;
36
+ const fs = __importStar(require("node:fs"));
37
+ const yaml = __importStar(require("yaml"));
38
+ const Path = __importStar(require("node:path"));
39
+ const node_child_process_1 = require("node:child_process");
40
+ const prisma = [
41
+ `${process.cwd()}/schema.prisma`,
42
+ `${process.cwd()}/prisma/schema.prisma`,
43
+ ];
44
+ function migrate(opts) {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ require('dotenv').config();
47
+ console.log(opts);
48
+ if (opts.generate) {
49
+ let command = opts["generate-command"];
50
+ if (!command)
51
+ command = "prisma generate";
52
+ (0, node_child_process_1.spawnSync)("npx", [...command.split(" ")], {
53
+ cwd: process.cwd()
54
+ });
55
+ }
56
+ let schema = opts.schema;
57
+ if (!schema) {
58
+ schema = prisma.find(value => {
59
+ return fs.existsSync(value);
60
+ });
61
+ }
62
+ if (!schema) {
63
+ return console.error("Migrate error: schema.prisma file not found!");
64
+ }
65
+ console.log(`PSM migrate base do schema ${schema}`);
66
+ const home = Path.dirname(schema);
67
+ const psm_yml = Path.join(home, "psm.yml");
68
+ if (!fs.existsSync(psm_yml)) {
69
+ return console.error("Migrate error: psm.yml file not found!");
70
+ }
71
+ console.log(`PSM migrate using ${psm_yml}`);
72
+ const psm = yaml.parse(fs.readFileSync(psm_yml).toString());
73
+ const next = Path.join(psm.psm.output, "next/migration.next.sql");
74
+ const check = Path.join(psm.psm.output, "next/migration.next.check.sql");
75
+ if (!fs.existsSync(check)) {
76
+ return console.error("Migrate error: next/migration.next.check.sql file not found!");
77
+ }
78
+ if (!fs.existsSync(next)) {
79
+ return console.error("Migrate error: next/migration.next.sql file not found!");
80
+ }
81
+ const driver = yield Promise.resolve(`${psm.psm.driver}`).then(s => __importStar(require(s)));
82
+ const migrator = driver.migrator({
83
+ url: process.env[psm.psm.url],
84
+ migrate: fs.readFileSync(next).toString(),
85
+ check: fs.readFileSync(check).toString(),
86
+ });
87
+ let result = yield migrator.test();
88
+ if (!result.success) {
89
+ console.error(result.error);
90
+ result.messages.forEach(error => {
91
+ console.error(error);
92
+ });
93
+ return console.error("Migrate error: Check shadow failed!");
94
+ }
95
+ result = yield migrator.migrate();
96
+ if (!result.success) {
97
+ console.error(result.error);
98
+ result.messages.forEach(error => {
99
+ console.error(error);
100
+ });
101
+ return console.error("Migrate error: Check shadow failed!");
102
+ }
103
+ const moment = require('moment');
104
+ let label = "";
105
+ if (!!opts.label)
106
+ label = ` - ${sanitizeLabel(opts.label)}`;
107
+ psm.migration = {
108
+ instate: moment().format('YYYYMMDDHHmmss'),
109
+ preview: getLatestFolder(Path.join(home, `psm/revisions/schema`)),
110
+ label: opts.label
111
+ };
112
+ const nextRev = Path.join(home, `psm/revisions/schema/${psm.migration.instate}${label}`);
113
+ fs.mkdirSync(nextRev, { recursive: true });
114
+ fs.renameSync(next, Path.join(nextRev, "migration.sql"));
115
+ fs.writeFileSync(Path.join(nextRev, "psm.yml"), yaml.stringify(psm));
116
+ fs.unlinkSync(check);
117
+ });
118
+ }
119
+ // Função para obter a pasta com maior instante
120
+ function getLatestFolder(basePath) {
121
+ if (!fs.existsSync(basePath))
122
+ return null;
123
+ const dirs = fs.readdirSync(basePath, { withFileTypes: true })
124
+ .filter(d => d.isDirectory())
125
+ .map(d => d.name)
126
+ .filter(name => /^\d{14}( - .+)?$/.test(name))
127
+ .sort((a, b) => b.localeCompare(a));
128
+ return dirs[0] || null;
129
+ }
130
+ function sanitizeLabel(label) {
131
+ return label
132
+ .replace(/[<>:"/\\|?*\x00-\x1F]/g, '') // remove caracteres inválidos no Windows
133
+ .replace(/[\u{0080}-\u{FFFF}]/gu, '') // remove caracteres não ASCII (opcional)
134
+ .trim()
135
+ .replace(/\s+/g, ' '); // normaliza espaços
136
+ }
137
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ import * as fs from "node:fs";
2
+ import * as yaml from "yaml";
3
+ import * as Path from "node:path";
4
+ import {PSMConfigFile} from "../configs";
5
+ import {PSMDriver} from "../driver";
6
+ import { spawnSync } from "node:child_process";
7
+ import moment from "moment/moment";
8
+
9
+ const prisma = [
10
+ `${process.cwd()}/schema.prisma`,
11
+ `${process.cwd()}/prisma/schema.prisma`,
12
+ ];
13
+
14
+ export interface MigrateOptions {
15
+ schema?:string
16
+ generate?:string
17
+ label?:string
18
+ "generate-command":string
19
+ }
20
+ export async function migrate( opts:MigrateOptions ) {
21
+ require('dotenv').config();
22
+ console.log( opts )
23
+ if( opts.generate ) {
24
+ let command = opts["generate-command"];
25
+ if( !command) command = "prisma generate"
26
+ spawnSync( "npx", [ ...command.split(" ") ], {
27
+ cwd: process.cwd()
28
+ });
29
+ }
30
+ let schema = opts.schema;
31
+ if( !schema ) {
32
+ schema = prisma.find( value => {
33
+ return fs.existsSync( value );
34
+ })
35
+ }
36
+ if( !schema ) {
37
+ return console.error( "Migrate error: schema.prisma file not found!" );
38
+ }
39
+
40
+ console.log(`PSM migrate base do schema ${schema}`);
41
+
42
+ const home = Path.dirname( schema );
43
+ const psm_yml = Path.join( home, "psm.yml" );
44
+ if( !fs.existsSync( psm_yml ) ) {
45
+ return console.error( "Migrate error: psm.yml file not found!" );
46
+ }
47
+
48
+ console.log(`PSM migrate using ${psm_yml}`);
49
+ const psm = yaml.parse( fs.readFileSync( psm_yml ).toString() ) as PSMConfigFile;
50
+ const next = Path.join( psm.psm.output, "next/migration.next.sql");
51
+ const check = Path.join( psm.psm.output, "next/migration.next.check.sql");
52
+
53
+ if( !fs.existsSync( check) ) {
54
+ return console.error( "Migrate error: next/migration.next.check.sql file not found!" );
55
+ }
56
+ if( !fs.existsSync( next) ) {
57
+ return console.error( "Migrate error: next/migration.next.sql file not found!" );
58
+ }
59
+
60
+
61
+ const driver = await import( psm.psm.driver ) as PSMDriver;
62
+ const migrator = driver.migrator({
63
+ url: process.env[psm.psm.url],
64
+ migrate: fs.readFileSync( next ).toString(),
65
+ check: fs.readFileSync( check ).toString(),
66
+ });
67
+
68
+ let result = await migrator.test();
69
+ if( !result.success ) {
70
+ console.error( result.error );
71
+ result.messages.forEach( error => {
72
+ console.error( error );
73
+ });
74
+ return console.error( "Migrate error: Check shadow failed!" );
75
+ }
76
+
77
+ result = await migrator.migrate();
78
+ if( !result.success ) {
79
+ console.error( result.error );
80
+ result.messages.forEach( error => {
81
+ console.error( error );
82
+ });
83
+ return console.error( "Migrate error: Check shadow failed!" );
84
+ }
85
+
86
+ const moment = require('moment');
87
+ let label = "";
88
+ if( !!opts.label ) label = ` - ${sanitizeLabel( opts.label )}`
89
+ psm.migration = {
90
+ instate: moment().format( 'YYYYMMDDHHmmss' ),
91
+ preview: getLatestFolder( Path.join( home, `psm/revisions/schema`)),
92
+ label: opts.label
93
+ }
94
+ const nextRev = Path.join( home, `psm/revisions/schema/${psm.migration.instate}${label}`);
95
+
96
+
97
+ fs.mkdirSync( nextRev, { recursive: true });
98
+ fs.renameSync( next, Path.join( nextRev, "migration.sql" ) );
99
+ fs.writeFileSync( Path.join( nextRev, "psm.yml" ), yaml.stringify( psm ) );
100
+ fs.unlinkSync( check );
101
+ }
102
+
103
+
104
+ // Função para obter a pasta com maior instante
105
+ function getLatestFolder(basePath:string) {
106
+ if (!fs.existsSync(basePath)) return null;
107
+ const dirs = fs.readdirSync(basePath, { withFileTypes: true })
108
+ .filter(d => d.isDirectory())
109
+ .map(d => d.name)
110
+ .filter(name => /^\d{14}( - .+)?$/.test(name))
111
+ .sort((a, b) => b.localeCompare(a));
112
+ return dirs[0] || null;
113
+ }
114
+
115
+ function sanitizeLabel( label:string ) {
116
+ return label
117
+ .replace(/[<>:"/\\|?*\x00-\x1F]/g, '') // remove caracteres inválidos no Windows
118
+ .replace(/[\u{0080}-\u{FFFF}]/gu, '') // remove caracteres não ASCII (opcional)
119
+ .trim()
120
+ .replace(/\s+/g, ' '); // normaliza espaços
121
+ }