@lenne.tech/nest-server 11.2.0 → 11.4.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/bin/migrate.js +40 -0
- package/dist/core/common/decorators/unified-field.decorator.d.ts +2 -0
- package/dist/core/common/decorators/unified-field.decorator.js +26 -9
- package/dist/core/common/decorators/unified-field.decorator.js.map +1 -1
- package/dist/core/common/models/core-persistence.model.js +2 -2
- package/dist/core/common/models/core-persistence.model.js.map +1 -1
- package/dist/core/modules/file/core-file-info.model.js +41 -23
- package/dist/core/modules/file/core-file-info.model.js.map +1 -1
- package/dist/core/modules/migrate/cli/migrate-cli.d.ts +3 -0
- package/dist/core/modules/migrate/cli/migrate-cli.js +221 -0
- package/dist/core/modules/migrate/cli/migrate-cli.js.map +1 -0
- package/dist/core/modules/migrate/helpers/migration.helper.d.ts +12 -0
- package/dist/core/modules/migrate/helpers/migration.helper.js +57 -0
- package/dist/core/modules/migrate/helpers/migration.helper.js.map +1 -0
- package/dist/core/modules/migrate/helpers/ts-compiler.d.ts +2 -0
- package/dist/core/modules/migrate/helpers/ts-compiler.js +3 -0
- package/dist/core/modules/migrate/helpers/ts-compiler.js.map +1 -0
- package/dist/core/modules/migrate/index.d.ts +4 -0
- package/dist/core/modules/migrate/index.js +21 -0
- package/dist/core/modules/migrate/index.js.map +1 -0
- package/dist/core/modules/migrate/migration-runner.d.ts +26 -0
- package/dist/core/modules/migrate/migration-runner.js +124 -0
- package/dist/core/modules/migrate/migration-runner.js.map +1 -0
- package/dist/core/modules/migrate/mongo-state-store.d.ts +30 -0
- package/dist/core/modules/migrate/mongo-state-store.js +105 -0
- package/dist/core/modules/migrate/mongo-state-store.js.map +1 -0
- package/dist/core/modules/migrate/templates/migration-with-helper.template.d.ts +2 -0
- package/dist/core/modules/migrate/templates/migration-with-helper.template.js +10 -0
- package/dist/core/modules/migrate/templates/migration-with-helper.template.js.map +1 -0
- package/dist/core/modules/migrate/templates/migration.template.d.ts +2 -0
- package/dist/core/modules/migrate/templates/migration.template.js +15 -0
- package/dist/core/modules/migrate/templates/migration.template.js.map +1 -0
- package/dist/core/modules/user/core-user.model.js +95 -54
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.js +22 -0
- package/dist/main.js.map +1 -1
- package/dist/server/common/models/persistence.model.js +13 -11
- package/dist/server/common/models/persistence.model.js.map +1 -1
- package/dist/server/modules/auth/auth.model.js +6 -2
- package/dist/server/modules/auth/auth.model.js.map +1 -1
- package/dist/server/modules/user/user.controller.d.ts +19 -0
- package/dist/server/modules/user/user.controller.js +256 -0
- package/dist/server/modules/user/user.controller.js.map +1 -0
- package/dist/server/modules/user/user.model.js +37 -24
- package/dist/server/modules/user/user.model.js.map +1 -1
- package/dist/server/modules/user/user.module.js +2 -1
- package/dist/server/modules/user/user.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +33 -29
- package/src/core/common/decorators/unified-field.decorator.ts +49 -10
- package/src/core/common/models/core-persistence.model.ts +3 -3
- package/src/core/modules/file/core-file-info.model.ts +40 -22
- package/src/core/modules/migrate/MIGRATION_FROM_NODEPIT.md +219 -0
- package/src/core/modules/migrate/README.md +452 -0
- package/src/core/modules/migrate/cli/migrate-cli.ts +319 -0
- package/src/core/modules/migrate/helpers/migration.helper.ts +117 -0
- package/src/core/modules/migrate/helpers/ts-compiler.js +14 -0
- package/src/core/modules/migrate/index.ts +41 -0
- package/src/core/modules/migrate/migration-runner.ts +230 -0
- package/src/core/modules/migrate/mongo-state-store.ts +283 -0
- package/src/core/modules/migrate/templates/migration-with-helper.template.ts +72 -0
- package/src/core/modules/migrate/templates/migration.template.ts +59 -0
- package/src/core/modules/user/core-user.model.ts +120 -78
- package/src/index.ts +9 -3
- package/src/main.ts +25 -0
- package/src/server/common/models/persistence.model.ts +15 -13
- package/src/server/modules/auth/auth.model.ts +7 -3
- package/src/server/modules/user/user.controller.ts +242 -0
- package/src/server/modules/user/user.model.ts +39 -26
- package/src/server/modules/user/user.module.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.4.0",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -67,18 +67,18 @@
|
|
|
67
67
|
"node": ">= 20"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@apollo/gateway": "2.
|
|
70
|
+
"@apollo/gateway": "2.12.0",
|
|
71
71
|
"@getbrevo/brevo": "3.0.1",
|
|
72
72
|
"@nestjs/apollo": "13.1.0",
|
|
73
|
-
"@nestjs/common": "11.1.
|
|
74
|
-
"@nestjs/core": "11.1.
|
|
73
|
+
"@nestjs/common": "11.1.8",
|
|
74
|
+
"@nestjs/core": "11.1.8",
|
|
75
75
|
"@nestjs/graphql": "13.1.0",
|
|
76
76
|
"@nestjs/jwt": "11.0.1",
|
|
77
77
|
"@nestjs/mongoose": "11.0.3",
|
|
78
78
|
"@nestjs/passport": "11.0.5",
|
|
79
|
-
"@nestjs/platform-express": "11.1.
|
|
79
|
+
"@nestjs/platform-express": "11.1.8",
|
|
80
80
|
"@nestjs/schedule": "6.0.1",
|
|
81
|
-
"@nestjs/swagger": "11.2.
|
|
81
|
+
"@nestjs/swagger": "11.2.1",
|
|
82
82
|
"@nestjs/terminus": "11.0.0",
|
|
83
83
|
"apollo-server-core": "3.13.0",
|
|
84
84
|
"apollo-server-express": "3.13.0",
|
|
@@ -89,55 +89,52 @@
|
|
|
89
89
|
"cookie-parser": "1.4.7",
|
|
90
90
|
"dotenv": "17.2.3",
|
|
91
91
|
"ejs": "3.1.10",
|
|
92
|
-
"graphql": "16.
|
|
92
|
+
"graphql": "16.12.0",
|
|
93
93
|
"graphql-query-complexity": "1.1.0",
|
|
94
94
|
"graphql-subscriptions": "3.0.0",
|
|
95
95
|
"graphql-upload": "15.0.2",
|
|
96
96
|
"js-sha256": "0.11.1",
|
|
97
97
|
"json-to-graphql-query": "2.3.0",
|
|
98
|
-
"light-my-request": "6.6.0",
|
|
99
98
|
"lodash": "4.17.21",
|
|
100
|
-
"mongodb": "
|
|
101
|
-
"mongoose": "8.19.
|
|
99
|
+
"mongodb": "7.0.0",
|
|
100
|
+
"mongoose": "8.19.3",
|
|
102
101
|
"multer": "2.0.2",
|
|
103
|
-
"node-mailjet": "6.0.
|
|
104
|
-
"nodemailer": "7.0.
|
|
105
|
-
"nodemon": "3.1.10",
|
|
102
|
+
"node-mailjet": "6.0.11",
|
|
103
|
+
"nodemailer": "7.0.10",
|
|
106
104
|
"passport": "0.7.0",
|
|
107
105
|
"passport-jwt": "4.0.1",
|
|
108
106
|
"reflect-metadata": "0.2.2",
|
|
109
107
|
"rfdc": "1.4.1",
|
|
110
|
-
"rimraf": "6.0.1",
|
|
111
108
|
"rxjs": "7.8.2",
|
|
112
109
|
"yuml-diagram": "1.2.0"
|
|
113
110
|
},
|
|
114
111
|
"devDependencies": {
|
|
115
112
|
"@babel/plugin-proposal-private-methods": "7.18.6",
|
|
116
|
-
"@compodoc/compodoc": "1.1.
|
|
117
|
-
"@lenne.tech/eslint-config-ts": "2.1.
|
|
113
|
+
"@compodoc/compodoc": "1.1.32",
|
|
114
|
+
"@lenne.tech/eslint-config-ts": "2.1.4",
|
|
118
115
|
"@nestjs/cli": "11.0.10",
|
|
119
116
|
"@nestjs/schematics": "11.0.9",
|
|
120
|
-
"@nestjs/testing": "11.1.
|
|
121
|
-
"@swc/cli": "0.7.
|
|
122
|
-
"@swc/core": "1.
|
|
117
|
+
"@nestjs/testing": "11.1.8",
|
|
118
|
+
"@swc/cli": "0.7.9",
|
|
119
|
+
"@swc/core": "1.15.0",
|
|
123
120
|
"@swc/jest": "0.2.39",
|
|
124
121
|
"@types/compression": "1.8.1",
|
|
125
|
-
"@types/cookie-parser": "1.4.
|
|
122
|
+
"@types/cookie-parser": "1.4.10",
|
|
126
123
|
"@types/ejs": "3.1.5",
|
|
127
124
|
"@types/express": "4.17.21",
|
|
128
125
|
"@types/jest": "30.0.0",
|
|
129
126
|
"@types/lodash": "4.17.20",
|
|
130
127
|
"@types/multer": "2.0.0",
|
|
131
|
-
"@types/node": "24.
|
|
132
|
-
"@types/nodemailer": "7.0.
|
|
128
|
+
"@types/node": "24.10.0",
|
|
129
|
+
"@types/nodemailer": "7.0.3",
|
|
133
130
|
"@types/passport": "1.0.17",
|
|
134
131
|
"@types/supertest": "6.0.3",
|
|
135
|
-
"@typescript-eslint/eslint-plugin": "8.46.
|
|
136
|
-
"@typescript-eslint/parser": "8.46.
|
|
132
|
+
"@typescript-eslint/eslint-plugin": "8.46.3",
|
|
133
|
+
"@typescript-eslint/parser": "8.46.3",
|
|
137
134
|
"coffeescript": "2.7.0",
|
|
138
|
-
"eslint": "9.
|
|
135
|
+
"eslint": "9.39.1",
|
|
139
136
|
"eslint-config-prettier": "10.1.8",
|
|
140
|
-
"eslint-plugin-unused-imports": "4.
|
|
137
|
+
"eslint-plugin-unused-imports": "4.3.0",
|
|
141
138
|
"find-file-up": "2.0.1",
|
|
142
139
|
"grunt": "1.6.1",
|
|
143
140
|
"grunt-bg-shell": "2.3.3",
|
|
@@ -146,14 +143,16 @@
|
|
|
146
143
|
"grunt-sync": "0.8.2",
|
|
147
144
|
"husky": "9.1.7",
|
|
148
145
|
"jest": "30.2.0",
|
|
146
|
+
"nodemon": "3.1.10",
|
|
149
147
|
"npm-watch": "0.13.0",
|
|
150
148
|
"pm2": "6.0.13",
|
|
151
149
|
"prettier": "3.6.2",
|
|
152
150
|
"pretty-quick": "4.2.2",
|
|
151
|
+
"rimraf": "6.1.0",
|
|
153
152
|
"supertest": "7.1.4",
|
|
154
153
|
"ts-jest": "29.4.5",
|
|
155
154
|
"ts-loader": "9.5.4",
|
|
156
|
-
"ts-morph": "27.0.
|
|
155
|
+
"ts-morph": "27.0.2",
|
|
157
156
|
"ts-node": "10.9.2",
|
|
158
157
|
"tsconfig-paths": "4.2.0",
|
|
159
158
|
"typescript": "5.9.3",
|
|
@@ -164,7 +163,7 @@
|
|
|
164
163
|
"flat": "5.0.2",
|
|
165
164
|
"mime": "2.6.0"
|
|
166
165
|
},
|
|
167
|
-
"ts-morph": "27.0.
|
|
166
|
+
"ts-morph": "27.0.2"
|
|
168
167
|
},
|
|
169
168
|
"jest": {
|
|
170
169
|
"collectCoverage": true,
|
|
@@ -183,9 +182,14 @@
|
|
|
183
182
|
},
|
|
184
183
|
"main": "dist/index.js",
|
|
185
184
|
"types": "dist/index.d.ts",
|
|
185
|
+
"bin": {
|
|
186
|
+
"nest-migrate": "./bin/migrate.js",
|
|
187
|
+
"migrate": "./bin/migrate.js"
|
|
188
|
+
},
|
|
186
189
|
"files": [
|
|
187
190
|
"dist/**/*",
|
|
188
|
-
"src/**/*"
|
|
191
|
+
"src/**/*",
|
|
192
|
+
"bin/**/*"
|
|
189
193
|
],
|
|
190
194
|
"watch": {
|
|
191
195
|
"build:dev": "src"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Field, FieldOptions } from '@nestjs/graphql';
|
|
2
|
+
import { Prop, PropOptions } from '@nestjs/mongoose';
|
|
2
3
|
import { ApiProperty, ApiPropertyOptions } from '@nestjs/swagger';
|
|
3
4
|
import { EnumAllowedTypes } from '@nestjs/swagger/dist/interfaces/schema-object-metadata.interface';
|
|
4
5
|
import { Type } from 'class-transformer';
|
|
@@ -38,6 +39,8 @@ export interface UnifiedFieldOptions {
|
|
|
38
39
|
isArray?: boolean;
|
|
39
40
|
/** Default: false */
|
|
40
41
|
isOptional?: boolean;
|
|
42
|
+
/** Whether to apply Mongoose @Prop decorator. Optional, used for database models. Default: false */
|
|
43
|
+
mongoose?: boolean | PropOptions;
|
|
41
44
|
/** Restricted roles */
|
|
42
45
|
roles?: RestrictedType | RoleEnum | RoleEnum[];
|
|
43
46
|
/** Options for swagger api documentation */
|
|
@@ -48,8 +51,12 @@ export interface UnifiedFieldOptions {
|
|
|
48
51
|
*
|
|
49
52
|
* Enums should be defined via the enum option.
|
|
50
53
|
*
|
|
54
|
+
* For array fields, you can use either:
|
|
55
|
+
* - `type: () => ItemType` (recommended, decorator adds array wrapping automatically)
|
|
56
|
+
* - `type: () => [ItemType]` (also supported, decorator extracts ItemType to avoid double-nesting)
|
|
57
|
+
*
|
|
51
58
|
* Supports:
|
|
52
|
-
* - A factory function that returns the type: `() => MyType`
|
|
59
|
+
* - A factory function that returns the type: `() => MyType` or `() => [MyType]`
|
|
53
60
|
* - A GraphQL scalar: `GraphQLScalarType`
|
|
54
61
|
* - A class constructor: `MyClass`
|
|
55
62
|
* */
|
|
@@ -96,7 +103,16 @@ export function UnifiedField(opts: UnifiedFieldOptions = {}): PropertyDecorator
|
|
|
96
103
|
return metadataType;
|
|
97
104
|
};
|
|
98
105
|
|
|
99
|
-
|
|
106
|
+
// Resolve the type and extract item type if user provided array syntax
|
|
107
|
+
const resolvedType = resolvedTypeFn();
|
|
108
|
+
|
|
109
|
+
// If this is an array field and the user provided type: () => [ItemType],
|
|
110
|
+
// extract the ItemType to avoid double-nesting (e.g., [[ItemType]])
|
|
111
|
+
// We check: isArrayField (should be array) && Array.isArray (is actually an array) && length === 1 (GraphQL array syntax)
|
|
112
|
+
const baseType =
|
|
113
|
+
isArrayField && Array.isArray(resolvedType) && resolvedType.length === 1
|
|
114
|
+
? resolvedType[0] // Extract item type from [ItemType]
|
|
115
|
+
: resolvedType; // Use as-is
|
|
100
116
|
|
|
101
117
|
// Prepare merged options
|
|
102
118
|
const gqlOpts: FieldOptions = { ...opts.gqlOptions };
|
|
@@ -161,8 +177,14 @@ export function UnifiedField(opts: UnifiedFieldOptions = {}): PropertyDecorator
|
|
|
161
177
|
}
|
|
162
178
|
|
|
163
179
|
// Type function for gql
|
|
180
|
+
// We need to keep the factory pattern (calling resolvedTypeFn inside the arrow function)
|
|
181
|
+
// to support circular references. But we also need to extract array item types to avoid double-nesting.
|
|
164
182
|
const gqlTypeFn = isArrayField
|
|
165
|
-
? () =>
|
|
183
|
+
? () => {
|
|
184
|
+
const resolved = opts.enum?.enum || opts.gqlType || resolvedTypeFn();
|
|
185
|
+
// Extract item type if user provided [ItemType] syntax to avoid [[ItemType]]
|
|
186
|
+
return [Array.isArray(resolved) && resolved.length === 1 ? resolved[0] : resolved];
|
|
187
|
+
}
|
|
166
188
|
: () => opts.enum?.enum || opts.gqlType || resolvedTypeFn();
|
|
167
189
|
|
|
168
190
|
// Gql decorator
|
|
@@ -178,7 +200,7 @@ export function UnifiedField(opts: UnifiedFieldOptions = {}): PropertyDecorator
|
|
|
178
200
|
|
|
179
201
|
// Completely skip validation if its any
|
|
180
202
|
if (opts.validator) {
|
|
181
|
-
opts.validator(valOpts).forEach(d => d(target, propertyKey));
|
|
203
|
+
opts.validator(valOpts).forEach((d) => d(target, propertyKey));
|
|
182
204
|
} else if (!opts.isAny) {
|
|
183
205
|
const validator = getBuiltInValidator(baseType, valOpts, isArrayField, target);
|
|
184
206
|
if (validator) {
|
|
@@ -199,6 +221,23 @@ export function UnifiedField(opts: UnifiedFieldOptions = {}): PropertyDecorator
|
|
|
199
221
|
const rolesArr = Array.isArray(opts.roles) ? opts.roles : [opts.roles];
|
|
200
222
|
Restricted(...rolesArr)(target, propertyKey);
|
|
201
223
|
}
|
|
224
|
+
|
|
225
|
+
// Mongoose @Prop decorator (optional)
|
|
226
|
+
if (opts.mongoose) {
|
|
227
|
+
const propOptions: any = typeof opts.mongoose === 'object' ? opts.mongoose : {};
|
|
228
|
+
|
|
229
|
+
// Set type for Prop if not already defined in propOptions
|
|
230
|
+
if (typeof propOptions === 'object' && !Array.isArray(propOptions) && !propOptions.type && baseType) {
|
|
231
|
+
propOptions.type = baseType;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Apply array type if needed
|
|
235
|
+
if (typeof propOptions === 'object' && !Array.isArray(propOptions) && isArrayField && !propOptions.type) {
|
|
236
|
+
propOptions.type = [baseType];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
Prop(propOptions)(target, propertyKey);
|
|
240
|
+
}
|
|
202
241
|
};
|
|
203
242
|
}
|
|
204
243
|
|
|
@@ -228,12 +267,12 @@ function getBuiltInValidator(
|
|
|
228
267
|
function isGraphQLScalar(type: any): boolean {
|
|
229
268
|
// CustomScalar check (The CustomScalar interface implements these functions below)
|
|
230
269
|
return (
|
|
231
|
-
(type
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
270
|
+
(type &&
|
|
271
|
+
typeof type === 'function' &&
|
|
272
|
+
typeof type.prototype?.serialize === 'function' &&
|
|
273
|
+
typeof type.prototype?.parseValue === 'function' &&
|
|
274
|
+
typeof type.prototype?.parseLiteral === 'function') ||
|
|
275
|
+
type instanceof GraphQLScalarType
|
|
237
276
|
);
|
|
238
277
|
}
|
|
239
278
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ObjectType } from '@nestjs/graphql';
|
|
2
|
-
import {
|
|
2
|
+
import { Schema } from '@nestjs/mongoose';
|
|
3
3
|
import { Types } from 'mongoose';
|
|
4
4
|
|
|
5
5
|
import { Restricted } from '../decorators/restricted.decorator';
|
|
@@ -85,10 +85,10 @@ export abstract class CorePersistenceModel extends CoreModel {
|
|
|
85
85
|
/**
|
|
86
86
|
* Created date, is set automatically by mongoose
|
|
87
87
|
*/
|
|
88
|
-
@Prop()
|
|
89
88
|
@UnifiedField({
|
|
90
89
|
description: 'Created date',
|
|
91
90
|
isOptional: true,
|
|
91
|
+
mongoose: true,
|
|
92
92
|
roles: RoleEnum.S_EVERYONE,
|
|
93
93
|
swaggerApiOptions: { example: 1740037703939, format: 'int64', type: Date },
|
|
94
94
|
type: Date,
|
|
@@ -98,10 +98,10 @@ export abstract class CorePersistenceModel extends CoreModel {
|
|
|
98
98
|
/**
|
|
99
99
|
* Updated date is set automatically by mongoose
|
|
100
100
|
*/
|
|
101
|
-
@Prop()
|
|
102
101
|
@UnifiedField({
|
|
103
102
|
description: 'Updated date',
|
|
104
103
|
isOptional: true,
|
|
104
|
+
mongoose: true,
|
|
105
105
|
roles: RoleEnum.S_EVERYONE,
|
|
106
106
|
swaggerApiOptions: { example: 1740037703939, format: 'int64', type: Date },
|
|
107
107
|
type: Date,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Prop } from '@nestjs/mongoose';
|
|
1
|
+
import { ObjectType } from '@nestjs/graphql';
|
|
3
2
|
import { Types } from 'mongoose';
|
|
4
3
|
|
|
5
4
|
import { Restricted } from '../../common/decorators/restricted.decorator';
|
|
5
|
+
import { UnifiedField } from '../../common/decorators/unified-field.decorator';
|
|
6
6
|
import { RoleEnum } from '../../common/enums/role.enum';
|
|
7
7
|
import { CoreModel } from '../../common/models/core-model.model';
|
|
8
8
|
|
|
@@ -25,37 +25,55 @@ export class CoreFileInfo extends CoreModel {
|
|
|
25
25
|
// Properties
|
|
26
26
|
// ===========================================================================
|
|
27
27
|
|
|
28
|
-
@
|
|
29
|
-
|
|
28
|
+
@UnifiedField({
|
|
29
|
+
description: 'ID of the file',
|
|
30
|
+
roles: RoleEnum.S_EVERYONE,
|
|
31
|
+
type: () => String,
|
|
32
|
+
})
|
|
30
33
|
id: string = undefined;
|
|
31
34
|
|
|
32
|
-
@
|
|
35
|
+
@UnifiedField({
|
|
33
36
|
description:
|
|
34
|
-
'The size of each chunk in bytes. GridFS divides the document into chunks of size chunkSize, '
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
'The size of each chunk in bytes. GridFS divides the document into chunks of size chunkSize, ' +
|
|
38
|
+
'except for the last, which is only as large as needed. The default size is 255 kilobytes (kB)',
|
|
39
|
+
isOptional: true,
|
|
40
|
+
mongoose: { required: false, type: Number },
|
|
41
|
+
roles: RoleEnum.S_EVERYONE,
|
|
42
|
+
type: () => Number,
|
|
37
43
|
})
|
|
38
|
-
@Prop({ required: false, type: Number })
|
|
39
|
-
@Restricted(RoleEnum.S_EVERYONE)
|
|
40
44
|
chunkSize: number = undefined;
|
|
41
45
|
|
|
42
|
-
@
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
@UnifiedField({
|
|
47
|
+
description: 'Content type',
|
|
48
|
+
isOptional: true,
|
|
49
|
+
mongoose: { required: false, type: String },
|
|
50
|
+
roles: RoleEnum.S_EVERYONE,
|
|
51
|
+
})
|
|
45
52
|
contentType?: string = undefined;
|
|
46
53
|
|
|
47
|
-
@
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
@UnifiedField({
|
|
55
|
+
description: 'Name of the file',
|
|
56
|
+
isOptional: true,
|
|
57
|
+
mongoose: { required: false, type: String },
|
|
58
|
+
roles: RoleEnum.S_EVERYONE,
|
|
59
|
+
})
|
|
50
60
|
filename?: string = undefined;
|
|
51
61
|
|
|
52
|
-
@
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
@UnifiedField({
|
|
63
|
+
description: 'The size of the document in bytes',
|
|
64
|
+
isOptional: true,
|
|
65
|
+
mongoose: { required: false, type: Number },
|
|
66
|
+
roles: RoleEnum.S_EVERYONE,
|
|
67
|
+
type: () => Number,
|
|
68
|
+
})
|
|
55
69
|
length: number = undefined;
|
|
56
70
|
|
|
57
|
-
@
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
@UnifiedField({
|
|
72
|
+
description: 'The date the file was first stored',
|
|
73
|
+
isOptional: true,
|
|
74
|
+
mongoose: { required: false, type: Date },
|
|
75
|
+
roles: RoleEnum.S_EVERYONE,
|
|
76
|
+
type: () => Date,
|
|
77
|
+
})
|
|
60
78
|
uploadDate: Date = undefined;
|
|
61
79
|
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Migration from @nodepit/migrate-state-store-mongodb
|
|
2
|
+
|
|
3
|
+
This guide provides step-by-step instructions to migrate from `@nodepit/migrate-state-store-mongodb` to the built-in nest-server migration system.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Current state of nest-server-starter projects:
|
|
8
|
+
- Using `@nodepit/migrate-state-store-mongodb` for state storage
|
|
9
|
+
- Using external `migrate` package for CLI
|
|
10
|
+
- Custom migration utilities in `migrations-utils/`
|
|
11
|
+
|
|
12
|
+
## Migration Steps
|
|
13
|
+
|
|
14
|
+
### Step 1: Update Dependencies
|
|
15
|
+
|
|
16
|
+
**File:** `package.json`
|
|
17
|
+
|
|
18
|
+
Remove old migration packages:
|
|
19
|
+
```bash
|
|
20
|
+
npm uninstall migrate @nodepit/migrate-state-store-mongodb ts-migrate-mongoose
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Ensure latest nest-server is installed:
|
|
24
|
+
```bash
|
|
25
|
+
npm install @lenne.tech/nest-server@latest
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Step 2: Update Migration State Store
|
|
29
|
+
|
|
30
|
+
**File:** `migrations-utils/migrate.js`
|
|
31
|
+
|
|
32
|
+
**Before:**
|
|
33
|
+
```javascript
|
|
34
|
+
import config from '../src/config.env';
|
|
35
|
+
const migrate = require('migrate');
|
|
36
|
+
const { MongoStateStore } = require('@nodepit/migrate-state-store-mongodb');
|
|
37
|
+
|
|
38
|
+
const MONGO_URL = config.mongoose.uri;
|
|
39
|
+
const COLLECTION_NAME = 'migrations';
|
|
40
|
+
|
|
41
|
+
module.exports = class MyMongoStateStore extends MongoStateStore {
|
|
42
|
+
constructor() {
|
|
43
|
+
super({ uri: MONGO_URL, collectionName: COLLECTION_NAME });
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**After:**
|
|
49
|
+
```javascript
|
|
50
|
+
const { createMigrationStore } = require('@lenne.tech/nest-server');
|
|
51
|
+
const config = require('../src/config.env');
|
|
52
|
+
|
|
53
|
+
module.exports = createMigrationStore(
|
|
54
|
+
config.default.mongoose.uri,
|
|
55
|
+
'migrations' // optional, default is 'migrations'
|
|
56
|
+
);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Step 3: Update Database Helper
|
|
60
|
+
|
|
61
|
+
**File:** `migrations-utils/db.ts`
|
|
62
|
+
|
|
63
|
+
**Before:**
|
|
64
|
+
```typescript
|
|
65
|
+
import * as fs from 'fs';
|
|
66
|
+
import { GridFSBucket, MongoClient, ObjectId } from 'mongodb';
|
|
67
|
+
import * as path from 'path';
|
|
68
|
+
import config from '../src/config.env';
|
|
69
|
+
|
|
70
|
+
const MONGO_URL = config.mongoose.uri;
|
|
71
|
+
|
|
72
|
+
export const getDb = async () => {
|
|
73
|
+
const client: MongoClient = await MongoClient.connect(MONGO_URL);
|
|
74
|
+
return client.db();
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const uploadFile = async (
|
|
78
|
+
relativePath,
|
|
79
|
+
options?: { bucketName?: string; filename?: string },
|
|
80
|
+
): Promise<ObjectId> => {
|
|
81
|
+
// ... implementation
|
|
82
|
+
};
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**After:**
|
|
86
|
+
```typescript
|
|
87
|
+
import config from '../src/config.env';
|
|
88
|
+
import { getDb as getDbHelper, uploadFileToGridFS } from '@lenne.tech/nest-server';
|
|
89
|
+
import { Db, ObjectId } from 'mongodb';
|
|
90
|
+
|
|
91
|
+
const MONGO_URL = config.mongoose.uri;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get database connection
|
|
95
|
+
*/
|
|
96
|
+
export const getDb = async (): Promise<Db> => {
|
|
97
|
+
return getDbHelper(MONGO_URL);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Upload file to GridFS
|
|
102
|
+
*/
|
|
103
|
+
export const uploadFile = async (
|
|
104
|
+
relativePath: string,
|
|
105
|
+
options?: { bucketName?: string; filename?: string }
|
|
106
|
+
): Promise<ObjectId> => {
|
|
107
|
+
return uploadFileToGridFS(MONGO_URL, relativePath, options);
|
|
108
|
+
};
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Step 4: Verify package.json Scripts
|
|
112
|
+
|
|
113
|
+
**File:** `package.json`
|
|
114
|
+
|
|
115
|
+
Scripts should remain unchanged - they will work with the built-in CLI:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"scripts": {
|
|
120
|
+
"migrate:create": "migrate create --template-file ./migrations-utils/template.ts --migrations-dir=\"./migrations\" --compiler=\"ts:./migrations-utils/ts-compiler.js\"",
|
|
121
|
+
"migrate:up": "migrate --store=./migrations-utils/migrate.js --migrations-dir=\"./migrations\" --compiler=\"ts:./migrations-utils/ts-compiler.js\" up",
|
|
122
|
+
"migrate:develop:up": "NODE_ENV=develop migrate --store=./migrations-utils/migrate.js --migrations-dir=\"./migrations\" --compiler=\"ts:./migrations-utils/ts-compiler.js\" up",
|
|
123
|
+
"migrate:test:up": "NODE_ENV=test migrate --store=./migrations-utils/migrate.js --migrations-dir=\"./migrations\" --compiler=\"ts:./migrations-utils/ts-compiler.js\" up",
|
|
124
|
+
"migrate:preview:up": "NODE_ENV=preview migrate --store=./migrations-utils/migrate.js --migrations-dir=\"./migrations\" --compiler=\"ts:./migrations-utils/ts-compiler.js\" up",
|
|
125
|
+
"migrate:prod:up": "NODE_ENV=production migrate --store=./migrations-utils/migrate.js --migrations-dir=\"./migrations\" --compiler=\"ts:./migrations-utils/ts-compiler.js\" up"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Note: The `migrate` command now comes from `@lenne.tech/nest-server` - no external package needed.
|
|
131
|
+
|
|
132
|
+
### Step 5: Test Migration
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Install dependencies
|
|
136
|
+
npm install
|
|
137
|
+
|
|
138
|
+
# Test migration creation
|
|
139
|
+
npm run migrate:create -- test-migration
|
|
140
|
+
|
|
141
|
+
# Test migration execution (if safe in current environment)
|
|
142
|
+
npm run migrate:up
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Verification Checklist
|
|
146
|
+
|
|
147
|
+
- [ ] `migrate` package removed from package.json
|
|
148
|
+
- [ ] `@nodepit/migrate-state-store-mongodb` removed from package.json
|
|
149
|
+
- [ ] `ts-migrate-mongoose` removed from package.json
|
|
150
|
+
- [ ] `migrations-utils/migrate.js` updated to use `createMigrationStore`
|
|
151
|
+
- [ ] `migrations-utils/db.ts` updated to use nest-server helpers
|
|
152
|
+
- [ ] `npm install` completed successfully
|
|
153
|
+
- [ ] `npm run migrate:create -- test` works
|
|
154
|
+
- [ ] Existing migrations still in database (no data loss)
|
|
155
|
+
|
|
156
|
+
## What Stays the Same
|
|
157
|
+
|
|
158
|
+
- ✅ All migration files in `migrations/` folder
|
|
159
|
+
- ✅ All migration data in MongoDB
|
|
160
|
+
- ✅ All npm scripts in package.json
|
|
161
|
+
- ✅ Migration file format (up/down functions)
|
|
162
|
+
- ✅ Template files (if using custom templates)
|
|
163
|
+
|
|
164
|
+
## What Changes
|
|
165
|
+
|
|
166
|
+
- ✅ `migrations-utils/migrate.js` - simplified (3 lines)
|
|
167
|
+
- ✅ `migrations-utils/db.ts` - uses nest-server helpers
|
|
168
|
+
- ✅ package.json dependencies - 2-3 packages removed
|
|
169
|
+
- ✅ CLI comes from nest-server instead of external package
|
|
170
|
+
|
|
171
|
+
## Rollback (if needed)
|
|
172
|
+
|
|
173
|
+
If you need to rollback:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Reinstall old packages
|
|
177
|
+
npm install --save-dev migrate @nodepit/migrate-state-store-mongodb
|
|
178
|
+
|
|
179
|
+
# Revert migrations-utils/migrate.js to old version from git
|
|
180
|
+
git checkout migrations-utils/migrate.js
|
|
181
|
+
|
|
182
|
+
# Revert migrations-utils/db.ts to old version from git
|
|
183
|
+
git checkout migrations-utils/db.ts
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Benefits After Migration
|
|
187
|
+
|
|
188
|
+
1. **One less dependency** - No external `migrate` package needed
|
|
189
|
+
2. **Simplified code** - ~90% less boilerplate in migrations-utils
|
|
190
|
+
3. **Better TypeScript** - Native TypeScript implementation
|
|
191
|
+
4. **MongoDB 7.x support** - Works with latest MongoDB versions
|
|
192
|
+
5. **Central maintenance** - Updates come with nest-server
|
|
193
|
+
|
|
194
|
+
## Support
|
|
195
|
+
|
|
196
|
+
If issues occur during migration:
|
|
197
|
+
- Check that `@lenne.tech/nest-server` is at version 11.3.0 or higher
|
|
198
|
+
- Verify `ts-node` is installed as devDependency
|
|
199
|
+
- Ensure `migrations-utils/migrate.js` exports the state store correctly
|
|
200
|
+
- Test with `migrate --help` to verify CLI is available
|
|
201
|
+
|
|
202
|
+
## File Structure After Migration
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
project-root/
|
|
206
|
+
├── migrations/ # Unchanged
|
|
207
|
+
│ └── TIMESTAMP-*.ts # Your migrations
|
|
208
|
+
├── migrations-utils/
|
|
209
|
+
│ ├── migrate.js # Updated (3 lines)
|
|
210
|
+
│ ├── db.ts # Updated (uses nest-server helpers)
|
|
211
|
+
│ ├── template.ts # Unchanged (optional)
|
|
212
|
+
│ └── ts-compiler.js # Unchanged (optional, can be removed)
|
|
213
|
+
└── package.json # Dependencies removed
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Note: `ts-compiler.js` can optionally be removed and replaced with:
|
|
217
|
+
```
|
|
218
|
+
--compiler="ts:./node_modules/@lenne.tech/nest-server/dist/core/modules/migrate/helpers/ts-compiler.js"
|
|
219
|
+
```
|