remult 0.25.7 → 0.25.8-exp.0
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/README.md +6 -12
- package/esm/migrations/compare-migration-snapshots.js +39 -0
- package/esm/migrations/generate-migrations.js +47 -0
- package/esm/migrations/index.js +2 -0
- package/esm/migrations/migrate.js +55 -0
- package/esm/migrations/migration-types.js +12 -0
- package/esm/migrations/update-migrations-ts-file.js +112 -0
- package/esm/postgres/postgres-data-provider.js +12 -0
- package/esm/postgres/schema-builder.js +35 -26
- package/esm/remult-knex/index.js +112 -28
- package/esm/remult-sql-js.js +2 -2
- package/esm/src/context.js +14 -8
- package/esm/src/data-providers/sql-database.js +10 -3
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +4 -0
- package/esm/src/isOfType.js +9 -0
- package/esm/src/remult3/remult3.js +20 -13
- package/migrations/compare-migration-snapshots.d.ts +26 -0
- package/migrations/compare-migration-snapshots.js +101 -0
- package/migrations/generate-migrations.d.ts +8 -0
- package/migrations/generate-migrations.js +82 -0
- package/migrations/index.d.ts +3 -0
- package/migrations/index.js +7 -0
- package/migrations/migrate.d.ts +7 -0
- package/migrations/migrate.js +147 -0
- package/migrations/migration-types.d.ts +23 -0
- package/migrations/migration-types.js +27 -0
- package/migrations/update-migrations-ts-file.d.ts +1 -0
- package/migrations/update-migrations-ts-file.js +135 -0
- package/package.json +6 -1
- package/postgres/postgres-data-provider.d.ts +3 -1
- package/postgres/postgres-data-provider.js +34 -0
- package/postgres/schema-builder.js +81 -48
- package/remult-knex/index.d.ts +10 -3
- package/remult-knex/index.js +170 -56
- package/remult-sql-js.js +1 -1
- package/server/expressBridge.d.ts +9 -1
- package/src/context.d.ts +1 -1
- package/src/context.js +16 -8
- package/src/data-providers/sql-database.d.ts +5 -2
- package/src/data-providers/sql-database.js +8 -3
- package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +1 -0
- package/src/filter/filter-consumer-bridge-to-sql-request.js +6 -1
- package/src/isOfType.d.ts +2 -0
- package/src/isOfType.js +14 -0
- package/src/remult3/remult3.js +20 -13
- package/src/sql-command.d.ts +4 -0
|
@@ -6,14 +6,16 @@ import { getRepository } from '../remult3/RepositoryImplementation.js';
|
|
|
6
6
|
import { Sort } from '../sort.js';
|
|
7
7
|
import { ValueConverters } from '../valueConverters.js';
|
|
8
8
|
import { getRepositoryInternals } from '../remult3/repository-internals.js';
|
|
9
|
+
import { isOfType } from '../isOfType.js';
|
|
9
10
|
// @dynamic
|
|
10
11
|
export class SqlDatabase {
|
|
11
12
|
sql;
|
|
12
13
|
static getDb(remult) {
|
|
13
14
|
const r = (remult || defaultRemult).dataProvider;
|
|
14
|
-
if (
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (isOfType(r, 'createCommand'))
|
|
16
|
+
return r;
|
|
17
|
+
else
|
|
18
|
+
throw 'the data provider is not an SqlCommandFactory';
|
|
17
19
|
}
|
|
18
20
|
createCommand() {
|
|
19
21
|
return new LogSQLCommand(this.sql.createCommand(), SqlDatabase.LogToConsole);
|
|
@@ -116,7 +118,12 @@ export class SqlDatabase {
|
|
|
116
118
|
this.sql = sql;
|
|
117
119
|
if (sql.wrapIdentifier)
|
|
118
120
|
this.wrapIdentifier = (x) => sql.wrapIdentifier(x);
|
|
121
|
+
if (isOfType(sql, 'provideMigrationBuilder')) {
|
|
122
|
+
this.provideMigrationBuilder = sql.provideMigrationBuilder;
|
|
123
|
+
}
|
|
119
124
|
}
|
|
125
|
+
provideMigrationBuilder;
|
|
126
|
+
isProxy;
|
|
120
127
|
createdEntities = [];
|
|
121
128
|
}
|
|
122
129
|
const icons = new Map([
|
|
@@ -164,6 +164,10 @@ export function shouldNotCreateField(field, dbNames) {
|
|
|
164
164
|
return (field.isServerExpression ||
|
|
165
165
|
(field.options.sqlExpression && field.dbName != dbNames.$dbNameOf(field)));
|
|
166
166
|
}
|
|
167
|
+
export function shouldCreateEntity(entity, e) {
|
|
168
|
+
return (!entity.options.sqlExpression &&
|
|
169
|
+
e.$entityName.toLowerCase().indexOf('from ') < 0);
|
|
170
|
+
}
|
|
167
171
|
export async function dbNamesOf(repo, wrapIdentifierOrOptions) {
|
|
168
172
|
let options = typeof wrapIdentifierOrOptions === 'function'
|
|
169
173
|
? { wrapIdentifier: wrapIdentifierOrOptions }
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function isOfType(obj, checkMethod) {
|
|
2
|
+
return typeof obj[checkMethod] === 'function';
|
|
3
|
+
}
|
|
4
|
+
export function cast(obj, checkMethod) {
|
|
5
|
+
if (isOfType(obj, checkMethod)) {
|
|
6
|
+
return obj;
|
|
7
|
+
}
|
|
8
|
+
throw new Error(`Object is not of type ${checkMethod.toString()}`);
|
|
9
|
+
}
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
//p1 - migrations - in docs empesize that mysql doesn't support transactions in ddl, in docs empesize destroy for knex - // await dataProvider.knex.destroy()
|
|
3
|
+
//https://gitkraken.dev/link/dnNjb2RlOi8vZWFtb2Rpby5naXRsZW5zL2xpbmsvci9mMDgzMWU0OWIyODJkMDlkNTA0NTcxYjYwNmUzNTMwODQ3NGIwY2M2L2YvcHJvamVjdHMvcGxheS13aXRoLW1pZ3JhdGlvbnMvc3JjL3NlcnZlci9idWlsZC1taWdyYXRpb25zLnRzP3VybD1odHRwcyUzQSUyRiUyRmdpdGh1Yi5jb20lMkZyZW11bHQlMkZyZW11bHQuZ2l0?origin=gitlens
|
|
4
|
+
/*p1 - processError in remult express
|
|
5
|
+
- Should we merge (notFound,error,forbidden) into one method in `DataApiResponse` type?
|
|
6
|
+
https://gitkraken.dev/link/dnNjb2RlOi8vZWFtb2Rpby5naXRsZW5zL2xpbmsvci9mMDgzMWU0OWIyODJkMDlkNTA0NTcxYjYwNmUzNTMwODQ3NGIwY2M2L2YvcHJvamVjdHMvY29yZS9zcmMvZGF0YS1hcGkudHM%2FdXJsPWh0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRnJlbXVsdCUyRnJlbXVsdC5naXQ%3D?origin=gitlens
|
|
7
|
+
- The api of the `processError` should recieve an `ErrorInfo` object and return an `ErrorInfo` object? or should it return something more in the line,
|
|
8
|
+
of httpStatus and errorBody. - currently the `serializeError` method is used to build the response
|
|
9
|
+
https://gitkraken.dev/link/dnNjb2RlOi8vZWFtb2Rpby5naXRsZW5zL2xpbmsvci9mMDgzMWU0OWIyODJkMDlkNTA0NTcxYjYwNmUzNTMwODQ3NGIwY2M2L2YvcHJvamVjdHMvY29yZS9zcmMvZGF0YS1hcGkudHM%2FdXJsPWh0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRnJlbXVsdCUyRnJlbXVsdC5naXQmbGluZXM9NDI1?origin=gitlens
|
|
10
|
+
- I think there should be a way to throw a forbidden exception
|
|
11
|
+
*/
|
|
12
|
+
//p1 - cleanup root directory of reult
|
|
13
|
+
//p1 - in this video I'll use remult to turn a frontend app to a fullstack app
|
|
14
|
+
/*y1 - discuss using delete & put - with url query language for deleteMany and updateMany -
|
|
15
|
+
- put & delete, similar to get
|
|
16
|
+
- add where to count, deleteMany,updateMany,
|
|
17
|
+
- prevent delete all and update all - must have meaningful where.
|
|
18
|
+
- try forcing this also in typescript
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
#
|
|
20
|
+
- protect against deleting of all rows by mistake
|
|
21
|
+
- https://github.com/remult/remult/issues/221#issuecomment-2016519746
|
|
11
22
|
|
|
23
|
+
*/
|
|
12
24
|
//y1 - getFields didn't work for kobi in the home component
|
|
13
|
-
|
|
14
|
-
//p1 - processError in remult express
|
|
15
|
-
//p1 - I think there should be a way to throw a forbidden exception
|
|
16
25
|
//p1 - add section to Fields doc, explaining field type in db
|
|
17
26
|
//p1 - add section about union type
|
|
18
27
|
//p1 - add section about value list field type
|
|
19
|
-
|
|
20
28
|
/*y1 - Talk JYC - JYC - add some integrity checks on delete
|
|
21
29
|
- soft delete
|
|
22
30
|
- delete restrict (implicit, or user selected - and if so, how) (delete & update of id)
|
|
@@ -53,7 +61,6 @@ export class Currency {
|
|
|
53
61
|
//y1 - I think that the tests you've setup don't cover next app router - I added to the setup, but not sure where else
|
|
54
62
|
//y1 - talk about the parameter issue with backend methods
|
|
55
63
|
//y1 - select data provider per entity https://discord.com/channels/975754286384418847/976006081748807690/1201415305885397003
|
|
56
|
-
//y1 - migrations
|
|
57
64
|
//y1 - live query refresh of view on table update
|
|
58
65
|
//y1 - main vs master
|
|
59
66
|
//y2 - livequery for findfirst (@JY)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { MigrationBuilder } from './migration-types.js';
|
|
2
|
+
export declare function compareMigrationSnapshot({ entities, snapshot, migrationBuilder: migrationBuilder, }: {
|
|
3
|
+
entities: any[];
|
|
4
|
+
snapshot: EntitiesSnapshot;
|
|
5
|
+
migrationBuilder: MigrationBuilder;
|
|
6
|
+
}): Promise<{
|
|
7
|
+
version: number;
|
|
8
|
+
entities: Record<string, {
|
|
9
|
+
key: string;
|
|
10
|
+
className: string;
|
|
11
|
+
columns: Record<string, {
|
|
12
|
+
key: string;
|
|
13
|
+
}>;
|
|
14
|
+
}>;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function emptySnapshot(): {
|
|
17
|
+
version: number;
|
|
18
|
+
entities: Record<string, {
|
|
19
|
+
key: string;
|
|
20
|
+
className: string;
|
|
21
|
+
columns: Record<string, {
|
|
22
|
+
key: string;
|
|
23
|
+
}>;
|
|
24
|
+
}>;
|
|
25
|
+
};
|
|
26
|
+
export type EntitiesSnapshot = ReturnType<typeof emptySnapshot>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.emptySnapshot = exports.compareMigrationSnapshot = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var index_js_1 = require("../index.js");
|
|
6
|
+
var filter_consumer_bridge_to_sql_request_js_1 = require("../src/filter/filter-consumer-bridge-to-sql-request.js");
|
|
7
|
+
function compareMigrationSnapshot(_a) {
|
|
8
|
+
var entities = _a.entities, snapshot = _a.snapshot, migrationBuilder = _a.migrationBuilder;
|
|
9
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
10
|
+
var entities_1, entities_1_1, entity, meta, e, entitySnapshot, createColumns, _b, _c, field, column, e_1_1, e_2_1;
|
|
11
|
+
var e_2, _d, e_1, _e;
|
|
12
|
+
return tslib_1.__generator(this, function (_f) {
|
|
13
|
+
switch (_f.label) {
|
|
14
|
+
case 0:
|
|
15
|
+
snapshot = JSON.parse(JSON.stringify(snapshot));
|
|
16
|
+
_f.label = 1;
|
|
17
|
+
case 1:
|
|
18
|
+
_f.trys.push([1, 16, 17, 18]);
|
|
19
|
+
entities_1 = tslib_1.__values(entities), entities_1_1 = entities_1.next();
|
|
20
|
+
_f.label = 2;
|
|
21
|
+
case 2:
|
|
22
|
+
if (!!entities_1_1.done) return [3 /*break*/, 15];
|
|
23
|
+
entity = entities_1_1.value;
|
|
24
|
+
meta = (0, index_js_1.repo)(entity).metadata;
|
|
25
|
+
return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOf)(meta, function (x) { return x; })];
|
|
26
|
+
case 3:
|
|
27
|
+
e = _f.sent();
|
|
28
|
+
if (!(0, filter_consumer_bridge_to_sql_request_js_1.shouldCreateEntity)(meta, e)) return [3 /*break*/, 13];
|
|
29
|
+
entitySnapshot = snapshot.entities[e.$entityName];
|
|
30
|
+
createColumns = true;
|
|
31
|
+
if (!!entitySnapshot) return [3 /*break*/, 5];
|
|
32
|
+
createColumns = false;
|
|
33
|
+
return [4 /*yield*/, migrationBuilder.createTable(meta)];
|
|
34
|
+
case 4:
|
|
35
|
+
_f.sent();
|
|
36
|
+
entitySnapshot = snapshot.entities[e.$entityName] = {
|
|
37
|
+
key: meta.key,
|
|
38
|
+
className: meta.entityType.name,
|
|
39
|
+
columns: {},
|
|
40
|
+
};
|
|
41
|
+
_f.label = 5;
|
|
42
|
+
case 5:
|
|
43
|
+
_f.trys.push([5, 11, 12, 13]);
|
|
44
|
+
_b = (e_1 = void 0, tslib_1.__values(meta.fields)), _c = _b.next();
|
|
45
|
+
_f.label = 6;
|
|
46
|
+
case 6:
|
|
47
|
+
if (!!_c.done) return [3 /*break*/, 10];
|
|
48
|
+
field = _c.value;
|
|
49
|
+
if (!!(0, filter_consumer_bridge_to_sql_request_js_1.shouldNotCreateField)(field, e)) return [3 /*break*/, 9];
|
|
50
|
+
column = entitySnapshot.columns[e.$dbNameOf(field)];
|
|
51
|
+
if (!!column) return [3 /*break*/, 9];
|
|
52
|
+
if (!createColumns) return [3 /*break*/, 8];
|
|
53
|
+
return [4 /*yield*/, migrationBuilder.addColumn(meta, field)];
|
|
54
|
+
case 7:
|
|
55
|
+
_f.sent();
|
|
56
|
+
_f.label = 8;
|
|
57
|
+
case 8:
|
|
58
|
+
entitySnapshot.columns[e.$dbNameOf(field)] = { key: field.key };
|
|
59
|
+
_f.label = 9;
|
|
60
|
+
case 9:
|
|
61
|
+
_c = _b.next();
|
|
62
|
+
return [3 /*break*/, 6];
|
|
63
|
+
case 10: return [3 /*break*/, 13];
|
|
64
|
+
case 11:
|
|
65
|
+
e_1_1 = _f.sent();
|
|
66
|
+
e_1 = { error: e_1_1 };
|
|
67
|
+
return [3 /*break*/, 13];
|
|
68
|
+
case 12:
|
|
69
|
+
try {
|
|
70
|
+
if (_c && !_c.done && (_e = _b.return)) _e.call(_b);
|
|
71
|
+
}
|
|
72
|
+
finally { if (e_1) throw e_1.error; }
|
|
73
|
+
return [7 /*endfinally*/];
|
|
74
|
+
case 13: return [2 /*return*/, snapshot];
|
|
75
|
+
case 14:
|
|
76
|
+
entities_1_1 = entities_1.next();
|
|
77
|
+
return [3 /*break*/, 2];
|
|
78
|
+
case 15: return [3 /*break*/, 18];
|
|
79
|
+
case 16:
|
|
80
|
+
e_2_1 = _f.sent();
|
|
81
|
+
e_2 = { error: e_2_1 };
|
|
82
|
+
return [3 /*break*/, 18];
|
|
83
|
+
case 17:
|
|
84
|
+
try {
|
|
85
|
+
if (entities_1_1 && !entities_1_1.done && (_d = entities_1.return)) _d.call(entities_1);
|
|
86
|
+
}
|
|
87
|
+
finally { if (e_2) throw e_2.error; }
|
|
88
|
+
return [7 /*endfinally*/];
|
|
89
|
+
case 18: return [2 /*return*/];
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
exports.compareMigrationSnapshot = compareMigrationSnapshot;
|
|
95
|
+
function emptySnapshot() {
|
|
96
|
+
return {
|
|
97
|
+
version: 1,
|
|
98
|
+
entities: {},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
exports.emptySnapshot = emptySnapshot;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DataProvider } from '../index.js';
|
|
2
|
+
export declare function generateMigrations(options: {
|
|
3
|
+
entities: any[];
|
|
4
|
+
dataProvider: Promise<DataProvider> | DataProvider;
|
|
5
|
+
migrationsDir?: string;
|
|
6
|
+
snapshotFileName?: string;
|
|
7
|
+
migrationsTSFilename?: string;
|
|
8
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMigrations = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var path_1 = tslib_1.__importDefault(require("path"));
|
|
6
|
+
var fs_1 = tslib_1.__importDefault(require("fs"));
|
|
7
|
+
var compare_migration_snapshots_js_1 = require("./compare-migration-snapshots.js");
|
|
8
|
+
var update_migrations_ts_file_js_1 = require("./update-migrations-ts-file.js");
|
|
9
|
+
var migration_types_js_1 = require("./migration-types.js");
|
|
10
|
+
var isOfType_js_1 = require("../src/isOfType.js");
|
|
11
|
+
function generateMigrations(options) {
|
|
12
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
13
|
+
var migrationDir, snapshotFileName, migrationsTSFilename, dataProvider, _a, _b, p, snapshot, hasSql, steps, code, migrationBuilder;
|
|
14
|
+
var e_1, _c;
|
|
15
|
+
return tslib_1.__generator(this, function (_d) {
|
|
16
|
+
switch (_d.label) {
|
|
17
|
+
case 0:
|
|
18
|
+
migrationDir = options.migrationsDir || path_1.default.join(process.cwd(), 'src/server/migrations');
|
|
19
|
+
snapshotFileName = options.snapshotFileName ||
|
|
20
|
+
path_1.default.join(migrationDir, 'migrations-snapshot.json');
|
|
21
|
+
migrationsTSFilename = options.migrationsTSFilename || path_1.default.join(migrationDir, 'migrations.ts');
|
|
22
|
+
return [4 /*yield*/, options.dataProvider];
|
|
23
|
+
case 1:
|
|
24
|
+
dataProvider = _d.sent();
|
|
25
|
+
try {
|
|
26
|
+
for (_a = tslib_1.__values([snapshotFileName, migrationsTSFilename]), _b = _a.next(); !_b.done; _b = _a.next()) {
|
|
27
|
+
p = _b.value;
|
|
28
|
+
if (!fs_1.default.existsSync(path_1.default.dirname(p))) {
|
|
29
|
+
fs_1.default.mkdirSync(path_1.default.dirname(p), { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
34
|
+
finally {
|
|
35
|
+
try {
|
|
36
|
+
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
37
|
+
}
|
|
38
|
+
finally { if (e_1) throw e_1.error; }
|
|
39
|
+
}
|
|
40
|
+
snapshot = (0, compare_migration_snapshots_js_1.emptySnapshot)();
|
|
41
|
+
if (fs_1.default.existsSync(snapshotFileName)) {
|
|
42
|
+
snapshot = JSON.parse(fs_1.default.readFileSync(snapshotFileName).toString());
|
|
43
|
+
}
|
|
44
|
+
hasSql = false;
|
|
45
|
+
steps = [];
|
|
46
|
+
code = {
|
|
47
|
+
//https://marketplace.visualstudio.com/items?itemName=qufiwefefwoyn.inline-sql-syntax
|
|
48
|
+
addSql: function (sql) {
|
|
49
|
+
steps.push('await sql(`--sql\n' + sql + '`)');
|
|
50
|
+
hasSql = true;
|
|
51
|
+
},
|
|
52
|
+
addTypescriptCode: function (code) { return steps.push(code); },
|
|
53
|
+
addComment: function (comment) {
|
|
54
|
+
return steps.push(comment.indexOf('\n') >= 0 ? "/*".concat(comment, "*/") : "// ".concat(comment));
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
migrationBuilder = new migration_types_js_1.DefaultMigrationBuilder(code);
|
|
58
|
+
if ((0, isOfType_js_1.isOfType)(dataProvider, 'provideMigrationBuilder')) {
|
|
59
|
+
migrationBuilder = dataProvider.provideMigrationBuilder(code);
|
|
60
|
+
}
|
|
61
|
+
return [4 /*yield*/, (0, compare_migration_snapshots_js_1.compareMigrationSnapshot)({
|
|
62
|
+
entities: options.entities,
|
|
63
|
+
snapshot: snapshot,
|
|
64
|
+
migrationBuilder: migrationBuilder,
|
|
65
|
+
})];
|
|
66
|
+
case 2:
|
|
67
|
+
snapshot = _d.sent();
|
|
68
|
+
if (!steps.length) return [3 /*break*/, 4];
|
|
69
|
+
return [4 /*yield*/, (0, update_migrations_ts_file_js_1.updateMigrationsFile)(migrationsTSFilename, [
|
|
70
|
+
"async (".concat(hasSql ? '{sql}' : '', ")=>{\n").concat(steps.join('\n'), "\n}"),
|
|
71
|
+
])];
|
|
72
|
+
case 3:
|
|
73
|
+
_d.sent();
|
|
74
|
+
_d.label = 4;
|
|
75
|
+
case 4:
|
|
76
|
+
fs_1.default.writeFileSync(snapshotFileName, JSON.stringify(snapshot, null, 2));
|
|
77
|
+
return [2 /*return*/];
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
exports.generateMigrations = generateMigrations;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.migrate = exports.generateMigrations = void 0;
|
|
4
|
+
var generate_migrations_js_1 = require("./generate-migrations.js");
|
|
5
|
+
Object.defineProperty(exports, "generateMigrations", { enumerable: true, get: function () { return generate_migrations_js_1.generateMigrations; } });
|
|
6
|
+
var migrate_js_1 = require("./migrate.js");
|
|
7
|
+
Object.defineProperty(exports, "migrate", { enumerable: true, get: function () { return migrate_js_1.migrate; } });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type DataProvider } from '../index.js';
|
|
2
|
+
import type { Migrations } from './migration-types.js';
|
|
3
|
+
export declare function migrate(options: {
|
|
4
|
+
migrations: Migrations;
|
|
5
|
+
dataProvider?: Promise<DataProvider> | DataProvider;
|
|
6
|
+
migrationTableName?: string;
|
|
7
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.migrate = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var index_js_1 = require("../index.js");
|
|
6
|
+
var context_js_1 = require("../src/context.js");
|
|
7
|
+
var isOfType_js_1 = require("../src/isOfType.js");
|
|
8
|
+
function migrate(options) {
|
|
9
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
10
|
+
var migrationTableName, dataProvider, _a, prev, VersionInfo, repo, v, steps, _loop_1, steps_1, steps_1_1, _b, stepText, action, e_1_1;
|
|
11
|
+
var e_1, _c;
|
|
12
|
+
var _this = this;
|
|
13
|
+
return tslib_1.__generator(this, function (_d) {
|
|
14
|
+
switch (_d.label) {
|
|
15
|
+
case 0:
|
|
16
|
+
migrationTableName = options.migrationTableName || '__remult_migration_version';
|
|
17
|
+
if (!options.dataProvider) return [3 /*break*/, 2];
|
|
18
|
+
return [4 /*yield*/, options.dataProvider];
|
|
19
|
+
case 1:
|
|
20
|
+
_a = _d.sent();
|
|
21
|
+
return [3 /*break*/, 3];
|
|
22
|
+
case 2:
|
|
23
|
+
_a = index_js_1.remult.dataProvider;
|
|
24
|
+
_d.label = 3;
|
|
25
|
+
case 3:
|
|
26
|
+
dataProvider = _a;
|
|
27
|
+
prev = index_js_1.remult.dataProvider;
|
|
28
|
+
index_js_1.remult.dataProvider = dataProvider;
|
|
29
|
+
_d.label = 4;
|
|
30
|
+
case 4:
|
|
31
|
+
_d.trys.push([4, , 16, 17]);
|
|
32
|
+
VersionInfo = /** @class */ (function (_super) {
|
|
33
|
+
tslib_1.__extends(VersionInfo, _super);
|
|
34
|
+
function VersionInfo() {
|
|
35
|
+
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
36
|
+
_this.version = -1;
|
|
37
|
+
return _this;
|
|
38
|
+
}
|
|
39
|
+
tslib_1.__decorate([
|
|
40
|
+
index_js_1.Fields.number(),
|
|
41
|
+
tslib_1.__metadata("design:type", Object)
|
|
42
|
+
], VersionInfo.prototype, "version", void 0);
|
|
43
|
+
VersionInfo = tslib_1.__decorate([
|
|
44
|
+
(0, index_js_1.Entity)(migrationTableName)
|
|
45
|
+
], VersionInfo);
|
|
46
|
+
return VersionInfo;
|
|
47
|
+
}(index_js_1.IdEntity));
|
|
48
|
+
repo = new index_js_1.Remult(dataProvider).repo(VersionInfo);
|
|
49
|
+
if (!dataProvider.ensureSchema) return [3 /*break*/, 6];
|
|
50
|
+
return [4 /*yield*/, dataProvider.ensureSchema([repo.metadata])];
|
|
51
|
+
case 5:
|
|
52
|
+
_d.sent();
|
|
53
|
+
_d.label = 6;
|
|
54
|
+
case 6: return [4 /*yield*/, repo.findFirst()];
|
|
55
|
+
case 7:
|
|
56
|
+
v = _d.sent();
|
|
57
|
+
if (!v) {
|
|
58
|
+
v = repo.create();
|
|
59
|
+
v.version = -1;
|
|
60
|
+
}
|
|
61
|
+
steps = Object.entries(options.migrations).sort(function (_a, _b) {
|
|
62
|
+
var _c = tslib_1.__read(_a, 1), a = _c[0];
|
|
63
|
+
var _d = tslib_1.__read(_b, 1), b = _d[0];
|
|
64
|
+
return parseInt(a) - parseInt(b);
|
|
65
|
+
});
|
|
66
|
+
_loop_1 = function (stepText, action) {
|
|
67
|
+
var step;
|
|
68
|
+
return tslib_1.__generator(this, function (_e) {
|
|
69
|
+
switch (_e.label) {
|
|
70
|
+
case 0:
|
|
71
|
+
step = parseInt(stepText);
|
|
72
|
+
if (step < 0)
|
|
73
|
+
throw new Error('Migration step number must be a non-negative integer');
|
|
74
|
+
if (v.version >= step)
|
|
75
|
+
return [2 /*return*/, "continue"];
|
|
76
|
+
console.info('Executing migration step', step);
|
|
77
|
+
return [4 /*yield*/, (0, context_js_1.doTransaction)(index_js_1.remult, function (dp) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
78
|
+
var utils;
|
|
79
|
+
var _this = this;
|
|
80
|
+
return tslib_1.__generator(this, function (_a) {
|
|
81
|
+
switch (_a.label) {
|
|
82
|
+
case 0:
|
|
83
|
+
utils = {
|
|
84
|
+
sql: function (sql) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
85
|
+
return tslib_1.__generator(this, function (_a) {
|
|
86
|
+
switch (_a.label) {
|
|
87
|
+
case 0: return [4 /*yield*/, (0, isOfType_js_1.cast)(dp, 'execute').execute(sql)];
|
|
88
|
+
case 1:
|
|
89
|
+
_a.sent();
|
|
90
|
+
return [2 /*return*/];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}); },
|
|
94
|
+
};
|
|
95
|
+
return [4 /*yield*/, action(utils)];
|
|
96
|
+
case 1:
|
|
97
|
+
_a.sent();
|
|
98
|
+
return [2 /*return*/];
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}); })];
|
|
102
|
+
case 1:
|
|
103
|
+
_e.sent();
|
|
104
|
+
v.version = step;
|
|
105
|
+
return [4 /*yield*/, v.save()];
|
|
106
|
+
case 2:
|
|
107
|
+
_e.sent();
|
|
108
|
+
return [2 /*return*/];
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
_d.label = 8;
|
|
113
|
+
case 8:
|
|
114
|
+
_d.trys.push([8, 13, 14, 15]);
|
|
115
|
+
steps_1 = tslib_1.__values(steps), steps_1_1 = steps_1.next();
|
|
116
|
+
_d.label = 9;
|
|
117
|
+
case 9:
|
|
118
|
+
if (!!steps_1_1.done) return [3 /*break*/, 12];
|
|
119
|
+
_b = tslib_1.__read(steps_1_1.value, 2), stepText = _b[0], action = _b[1];
|
|
120
|
+
return [5 /*yield**/, _loop_1(stepText, action)];
|
|
121
|
+
case 10:
|
|
122
|
+
_d.sent();
|
|
123
|
+
_d.label = 11;
|
|
124
|
+
case 11:
|
|
125
|
+
steps_1_1 = steps_1.next();
|
|
126
|
+
return [3 /*break*/, 9];
|
|
127
|
+
case 12: return [3 /*break*/, 15];
|
|
128
|
+
case 13:
|
|
129
|
+
e_1_1 = _d.sent();
|
|
130
|
+
e_1 = { error: e_1_1 };
|
|
131
|
+
return [3 /*break*/, 15];
|
|
132
|
+
case 14:
|
|
133
|
+
try {
|
|
134
|
+
if (steps_1_1 && !steps_1_1.done && (_c = steps_1.return)) _c.call(steps_1);
|
|
135
|
+
}
|
|
136
|
+
finally { if (e_1) throw e_1.error; }
|
|
137
|
+
return [7 /*endfinally*/];
|
|
138
|
+
case 15: return [3 /*break*/, 17];
|
|
139
|
+
case 16:
|
|
140
|
+
index_js_1.remult.dataProvider = prev;
|
|
141
|
+
return [7 /*endfinally*/];
|
|
142
|
+
case 17: return [2 /*return*/];
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
exports.migrate = migrate;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { EntityMetadata, FieldMetadata } from '../index.js';
|
|
2
|
+
export interface CanBuildMigrations {
|
|
3
|
+
provideMigrationBuilder(builder: MigrationCode): MigrationBuilder;
|
|
4
|
+
}
|
|
5
|
+
export interface MigrationBuilder {
|
|
6
|
+
createTable(meta: EntityMetadata): Promise<void>;
|
|
7
|
+
addColumn(meta: EntityMetadata, field: FieldMetadata): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface MigrationCode {
|
|
10
|
+
addSql(sql: string): void;
|
|
11
|
+
addComment(comment: string): void;
|
|
12
|
+
addTypescriptCode(code: string): void;
|
|
13
|
+
}
|
|
14
|
+
export type Migrations = Record<number, (utils: MigrationUtils) => Promise<unknown>>;
|
|
15
|
+
export type MigrationUtils = {
|
|
16
|
+
sql(sql: string): Promise<unknown>;
|
|
17
|
+
};
|
|
18
|
+
export declare class DefaultMigrationBuilder implements MigrationBuilder {
|
|
19
|
+
code: MigrationCode;
|
|
20
|
+
constructor(code: MigrationCode);
|
|
21
|
+
createTable(meta: EntityMetadata): Promise<void>;
|
|
22
|
+
addColumn(meta: EntityMetadata, field: FieldMetadata): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultMigrationBuilder = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var DefaultMigrationBuilder = /** @class */ (function () {
|
|
6
|
+
function DefaultMigrationBuilder(code) {
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
DefaultMigrationBuilder.prototype.createTable = function (meta) {
|
|
10
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
11
|
+
return tslib_1.__generator(this, function (_a) {
|
|
12
|
+
this.code.addComment('create table ' + meta.entityType.name);
|
|
13
|
+
return [2 /*return*/];
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
DefaultMigrationBuilder.prototype.addColumn = function (meta, field) {
|
|
18
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
19
|
+
return tslib_1.__generator(this, function (_a) {
|
|
20
|
+
this.code.addComment('add column ' + meta.entityType.name + '.' + field.key);
|
|
21
|
+
return [2 /*return*/];
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
return DefaultMigrationBuilder;
|
|
26
|
+
}());
|
|
27
|
+
exports.DefaultMigrationBuilder = DefaultMigrationBuilder;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function updateMigrationsFile(filePath: string, steps: string[]): Promise<void>;
|