@ackplus/nest-seeder 1.1.16 โ 2.0.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/CHANGELOG.md +64 -0
- package/MIGRATION.md +89 -0
- package/QUICKSTART.md +45 -162
- package/README.md +91 -537
- package/dist/cli.js +595 -235
- package/dist/cli.js.map +1 -1
- package/dist/index.d.mts +88 -0
- package/dist/index.d.ts +88 -8
- package/dist/index.js +417 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +390 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +38 -7
- package/dist/cli.d.ts +0 -3
- package/dist/lib/decorators/factory.decorator.d.ts +0 -6
- package/dist/lib/decorators/factory.decorator.js +0 -17
- package/dist/lib/decorators/factory.decorator.js.map +0 -1
- package/dist/lib/factory/data.factory.d.ts +0 -6
- package/dist/lib/factory/data.factory.js +0 -57
- package/dist/lib/factory/data.factory.js.map +0 -1
- package/dist/lib/index.d.ts +0 -4
- package/dist/lib/index.js +0 -21
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/interfaces/factory.interface.d.ts +0 -4
- package/dist/lib/interfaces/factory.interface.js +0 -3
- package/dist/lib/interfaces/factory.interface.js.map +0 -1
- package/dist/lib/interfaces/index.d.ts +0 -2
- package/dist/lib/interfaces/index.js +0 -19
- package/dist/lib/interfaces/index.js.map +0 -1
- package/dist/lib/interfaces/property-metadata.interface.d.ts +0 -6
- package/dist/lib/interfaces/property-metadata.interface.js +0 -3
- package/dist/lib/interfaces/property-metadata.interface.js.map +0 -1
- package/dist/lib/interfaces/seeder-module-async-options.interface.d.ts +0 -10
- package/dist/lib/interfaces/seeder-module-async-options.interface.js +0 -3
- package/dist/lib/interfaces/seeder-module-async-options.interface.js.map +0 -1
- package/dist/lib/interfaces/seeder-options-factory.interface.d.ts +0 -4
- package/dist/lib/interfaces/seeder-options-factory.interface.js +0 -3
- package/dist/lib/interfaces/seeder-options-factory.interface.js.map +0 -1
- package/dist/lib/seeder/seeder.d.ts +0 -10
- package/dist/lib/seeder/seeder.interface.d.ts +0 -9
- package/dist/lib/seeder/seeder.interface.js +0 -3
- package/dist/lib/seeder/seeder.interface.js.map +0 -1
- package/dist/lib/seeder/seeder.js +0 -40
- package/dist/lib/seeder/seeder.js.map +0 -1
- package/dist/lib/seeder/seeder.module.d.ts +0 -17
- package/dist/lib/seeder/seeder.module.js +0 -80
- package/dist/lib/seeder/seeder.module.js.map +0 -1
- package/dist/lib/seeder/seeder.service.d.ts +0 -10
- package/dist/lib/seeder/seeder.service.js +0 -73
- package/dist/lib/seeder/seeder.service.js.map +0 -1
- package/dist/lib/storages/factory.metadata.storage.d.ts +0 -16
- package/dist/lib/storages/factory.metadata.storage.js +0 -17
- package/dist/lib/storages/factory.metadata.storage.js.map +0 -1
- package/dist/tsconfig.build.tsbuildinfo +0 -1
package/README.md
CHANGED
|
@@ -1,69 +1,76 @@
|
|
|
1
1
|
# @ackplus/nest-seeder
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://nestjs.com/" target="_blank"><img src="https://nestjs.com/img/logo-small.svg" width="110" alt="Nest Logo" /></a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">A powerful, CLI-first database seeding library for NestJS โ factories, Faker.js, and a great DX.</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/@ackplus/nest-seeder"><img src="https://img.shields.io/npm/v/@ackplus/nest-seeder.svg" alt="NPM Version" /></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/@ackplus/nest-seeder"><img src="https://img.shields.io/npm/l/@ackplus/nest-seeder.svg" alt="License" /></a>
|
|
12
|
+
<a href="https://www.npmjs.com/package/@ackplus/nest-seeder"><img src="https://img.shields.io/npm/dm/@ackplus/nest-seeder.svg" alt="Downloads" /></a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
## ๐ Documentation
|
|
16
|
+
|
|
17
|
+
**๐ Full documentation & guides: [ack-solutions.github.io/nest-seeder](https://ack-solutions.github.io/nest-seeder/)**
|
|
18
|
+
|
|
19
|
+
| | |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| ๐ [Getting Started](https://ack-solutions.github.io/nest-seeder/guide/getting-started) | 5-minute quickstart |
|
|
22
|
+
| ๐ญ [Factories](https://ack-solutions.github.io/nest-seeder/guide/factories) | Generate realistic data |
|
|
23
|
+
| ๐ฑ [Seeders](https://ack-solutions.github.io/nest-seeder/guide/seeders) | Insert & drop data |
|
|
24
|
+
| ๐ฅ๏ธ [CLI Reference](https://ack-solutions.github.io/nest-seeder/guide/cli) | Every command & flag |
|
|
25
|
+
| ๐ [API Reference](https://ack-solutions.github.io/nest-seeder/api/) | Full API |
|
|
26
|
+
| ๐ [Migration v1 โ v2](https://ack-solutions.github.io/nest-seeder/migration) | Upgrade guide |
|
|
27
|
+
| ๐ [Changelog](https://ack-solutions.github.io/nest-seeder/changelog) | What changed |
|
|
4
28
|
|
|
5
29
|
## โจ Features
|
|
6
30
|
|
|
7
|
-
-
|
|
8
|
-
- ๐ญ **
|
|
9
|
-
- ๐ **
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
- ๐งช **Test-Friendly** - Perfect for testing and development
|
|
14
|
-
- ๐ **TypeScript** - Full TypeScript support with type safety
|
|
31
|
+
- ๐ฅ๏ธ **CLI-first** โ run `nest-seed` with zero changes to your app code. Auto-detects your config.
|
|
32
|
+
- ๐ญ **Factories + Faker.js** โ declare data with the `@Factory` decorator; supports dependent fields, inheritance, and overrides.
|
|
33
|
+
- ๐ **Any ORM** โ TypeORM, Mongoose, Prisma, or anything Nest can inject.
|
|
34
|
+
- ๐ฏ **Selective & safe** โ run seeders by name, `--refresh` in foreign-key-safe order, or preview with `--dry-run`.
|
|
35
|
+
- ๐ ๏ธ **Scaffolding** โ `nest-seed init` generates a config, factory, and seeder.
|
|
36
|
+
- ๐ฆ **Dual ESM + CJS** with full TypeScript declarations.
|
|
15
37
|
|
|
16
38
|
## ๐ฆ Installation
|
|
17
39
|
|
|
18
40
|
```bash
|
|
19
41
|
npm install @ackplus/nest-seeder @faker-js/faker
|
|
20
|
-
#
|
|
21
|
-
pnpm add @ackplus/nest-seeder @faker-js/faker
|
|
22
|
-
# or
|
|
23
|
-
yarn add @ackplus/nest-seeder @faker-js/faker
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
**For TypeScript config files**, also install:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
42
|
+
# For TypeScript config files:
|
|
29
43
|
npm install -D ts-node typescript
|
|
30
44
|
```
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
### Step 1: Create Entity
|
|
46
|
+
> Requires Node 18+ and NestJS 10 or 11.
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
// src/entities/user.entity.ts
|
|
38
|
-
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
|
|
48
|
+
## ๐ Quick Start
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
export class User {
|
|
42
|
-
@PrimaryGeneratedColumn()
|
|
43
|
-
id: number;
|
|
50
|
+
The fastest path is to scaffold the files:
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@Column({ unique: true })
|
|
49
|
-
email: string;
|
|
50
|
-
|
|
51
|
-
@Column()
|
|
52
|
-
role: string;
|
|
53
|
-
}
|
|
52
|
+
```bash
|
|
53
|
+
npx nest-seed init
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
โฆor wire them up by hand:
|
|
57
|
+
|
|
58
|
+
**1. Factory** โ `src/database/factories/user.factory.ts`
|
|
57
59
|
|
|
58
|
-
```
|
|
59
|
-
// src/factories/user.factory.ts
|
|
60
|
+
```ts
|
|
60
61
|
import { Factory } from '@ackplus/nest-seeder';
|
|
61
62
|
|
|
62
63
|
export class UserFactory {
|
|
63
|
-
@Factory((faker) => faker.person.
|
|
64
|
-
|
|
64
|
+
@Factory((faker) => faker.person.firstName())
|
|
65
|
+
firstName: string;
|
|
65
66
|
|
|
66
|
-
@Factory((faker) => faker.
|
|
67
|
+
@Factory((faker) => faker.person.lastName())
|
|
68
|
+
lastName: string;
|
|
69
|
+
|
|
70
|
+
@Factory(
|
|
71
|
+
(faker, ctx) => faker.internet.email({ firstName: ctx.firstName, lastName: ctx.lastName }).toLowerCase(),
|
|
72
|
+
['firstName', 'lastName'],
|
|
73
|
+
)
|
|
67
74
|
email: string;
|
|
68
75
|
|
|
69
76
|
@Factory((faker) => faker.helpers.arrayElement(['admin', 'user', 'guest']))
|
|
@@ -71,558 +78,105 @@ export class UserFactory {
|
|
|
71
78
|
}
|
|
72
79
|
```
|
|
73
80
|
|
|
74
|
-
|
|
81
|
+
**2. Seeder** โ `src/database/seeders/user.seeder.ts`
|
|
75
82
|
|
|
76
|
-
```
|
|
77
|
-
// src/seeders/user.seeder.ts
|
|
83
|
+
```ts
|
|
78
84
|
import { Injectable } from '@nestjs/common';
|
|
79
85
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
80
86
|
import { Repository } from 'typeorm';
|
|
81
|
-
import { Seeder, DataFactory } from '@ackplus/nest-seeder';
|
|
87
|
+
import { Seeder, SeederName, DataFactory } from '@ackplus/nest-seeder';
|
|
82
88
|
import { User } from '../entities/user.entity';
|
|
83
89
|
import { UserFactory } from '../factories/user.factory';
|
|
84
90
|
|
|
85
91
|
@Injectable()
|
|
92
|
+
@SeederName('users')
|
|
86
93
|
export class UserSeeder implements Seeder {
|
|
87
94
|
constructor(
|
|
88
|
-
@InjectRepository(User)
|
|
89
|
-
private readonly userRepository: Repository<User>,
|
|
95
|
+
@InjectRepository(User) private readonly userRepository: Repository<User>,
|
|
90
96
|
) {}
|
|
91
97
|
|
|
92
98
|
async seed(): Promise<void> {
|
|
93
|
-
// Create factory instance
|
|
94
99
|
const factory = DataFactory.createForClass(UserFactory);
|
|
95
|
-
|
|
96
|
-
// Generate 10 users
|
|
97
100
|
const users = factory.generate(10);
|
|
98
|
-
|
|
99
|
-
// Save to database
|
|
100
101
|
await this.userRepository.save(users);
|
|
101
|
-
|
|
102
|
-
console.log('โ
Seeded 10 users');
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
async drop(): Promise<void> {
|
|
106
|
-
|
|
107
|
-
await this.userRepository.delete({});
|
|
108
|
-
|
|
109
|
-
console.log('๐๏ธ Dropped all users');
|
|
105
|
+
await this.userRepository.createQueryBuilder().delete().execute();
|
|
110
106
|
}
|
|
111
107
|
}
|
|
112
108
|
```
|
|
113
109
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
Create `seeder.config.ts` in your **project root**:
|
|
110
|
+
**3. Config** โ `seeder.config.ts` (project root)
|
|
117
111
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
// seeder.config.ts
|
|
112
|
+
```ts
|
|
122
113
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
123
|
-
import {
|
|
124
|
-
import { User } from './src/entities/user.entity';
|
|
125
|
-
import { UserSeeder } from './src/seeders/user.seeder';
|
|
126
|
-
import * as dotenv from 'dotenv';
|
|
127
|
-
|
|
128
|
-
dotenv.config();
|
|
114
|
+
import { defineSeederConfig } from '@ackplus/nest-seeder';
|
|
115
|
+
import { User } from './src/database/entities/user.entity';
|
|
116
|
+
import { UserSeeder } from './src/database/seeders/user.seeder';
|
|
129
117
|
|
|
130
|
-
export default {
|
|
118
|
+
export default defineSeederConfig({
|
|
131
119
|
imports: [
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
port: config.get<number>('DB_PORT'),
|
|
142
|
-
username: config.get<string>('DB_USERNAME'),
|
|
143
|
-
password: config.get<string>('DB_PASSWORD'),
|
|
144
|
-
database: config.get<string>('DB_DATABASE'),
|
|
145
|
-
entities: [User],
|
|
146
|
-
synchronize: true,
|
|
147
|
-
}),
|
|
120
|
+
TypeOrmModule.forRoot({
|
|
121
|
+
type: 'postgres',
|
|
122
|
+
host: process.env.DB_HOST ?? 'localhost',
|
|
123
|
+
port: Number(process.env.DB_PORT ?? 5432),
|
|
124
|
+
username: process.env.DB_USERNAME ?? 'postgres',
|
|
125
|
+
password: process.env.DB_PASSWORD ?? 'postgres',
|
|
126
|
+
database: process.env.DB_DATABASE ?? 'app',
|
|
127
|
+
entities: [User],
|
|
128
|
+
synchronize: true,
|
|
148
129
|
}),
|
|
149
130
|
TypeOrmModule.forFeature([User]),
|
|
150
131
|
],
|
|
151
132
|
seeders: [UserSeeder],
|
|
152
|
-
};
|
|
133
|
+
});
|
|
153
134
|
```
|
|
154
135
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
Add script to `package.json`:
|
|
136
|
+
**4. Run** โ add a script and go
|
|
158
137
|
|
|
159
138
|
```json
|
|
160
139
|
{
|
|
161
140
|
"scripts": {
|
|
162
|
-
"seed": "
|
|
141
|
+
"seed": "nest-seed"
|
|
163
142
|
}
|
|
164
143
|
}
|
|
165
144
|
```
|
|
166
145
|
|
|
167
|
-
Run it:
|
|
168
|
-
|
|
169
146
|
```bash
|
|
170
147
|
npm run seed
|
|
171
148
|
```
|
|
172
149
|
|
|
173
|
-
|
|
150
|
+
That's it โ the CLI auto-discovers `seeder.config.ts` and seeds your database. ๐
|
|
174
151
|
|
|
175
|
-
## ๐ฅ๏ธ CLI
|
|
176
|
-
|
|
177
|
-
Since you are running the seeder via a package script, you can pass arguments using `--`.
|
|
178
|
-
|
|
179
|
-
### Basic Usage
|
|
152
|
+
## ๐ฅ๏ธ CLI at a glance
|
|
180
153
|
|
|
181
154
|
```bash
|
|
182
|
-
#
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
#
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
#
|
|
189
|
-
npm run seed -- --name UserSeeder
|
|
190
|
-
|
|
191
|
-
# Run multiple seeders
|
|
192
|
-
npm run seed -- --name UserSeeder ProductSeeder
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Available Options
|
|
196
|
-
|
|
197
|
-
| Option | Alias | Description | Default |
|
|
198
|
-
|--------|-------|-------------|---------|
|
|
199
|
-
| `--config` | `-c` | Path to configuration file | (required) |
|
|
200
|
-
| `--refresh` | `-r` | Drop data before seeding | `false` |
|
|
201
|
-
| `--name` | `-n` | Run specific seeder(s) | (all) |
|
|
202
|
-
| `--dummyData` | `-d` | Include dummy data flag | `false` |
|
|
203
|
-
| `--help` | `-h` | Show help | |
|
|
204
|
-
|
|
205
|
-
### Package.json Scripts
|
|
206
|
-
|
|
207
|
-
You can also define specific scripts for convenience:
|
|
208
|
-
|
|
209
|
-
```json
|
|
210
|
-
{
|
|
211
|
-
"scripts": {
|
|
212
|
-
"seed": "node -r ts-node/register -r tsconfig-paths/register ./node_modules/@ackplus/nest-seeder/dist/cli.js -c ./seeder.config.ts",
|
|
213
|
-
"seed:refresh": "npm run seed -- --refresh",
|
|
214
|
-
"seed:users": "npm run seed -- --name UserSeeder",
|
|
215
|
-
"seed:watch": "nodemon --watch src/seeders --ext ts --exec \"npm run seed\""
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
## โ๏ธ Configuration
|
|
221
|
-
|
|
222
|
-
### TypeORM Example
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
// seeder.config.ts
|
|
226
|
-
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
227
|
-
import { User, Post, Comment } from './src/entities';
|
|
228
|
-
import { UserSeeder, PostSeeder, CommentSeeder } from './src/seeders';
|
|
229
|
-
|
|
230
|
-
export default {
|
|
231
|
-
imports: [
|
|
232
|
-
TypeOrmModule.forRoot({
|
|
233
|
-
type: 'postgres',
|
|
234
|
-
host: process.env.DB_HOST || 'localhost',
|
|
235
|
-
port: parseInt(process.env.DB_PORT) || 5432,
|
|
236
|
-
username: process.env.DB_USER || 'postgres',
|
|
237
|
-
password: process.env.DB_PASSWORD || 'postgres',
|
|
238
|
-
database: process.env.DB_NAME || 'mydb',
|
|
239
|
-
entities: [User, Post, Comment],
|
|
240
|
-
synchronize: true,
|
|
241
|
-
}),
|
|
242
|
-
TypeOrmModule.forFeature([User, Post, Comment]),
|
|
243
|
-
],
|
|
244
|
-
seeders: [UserSeeder, PostSeeder, CommentSeeder],
|
|
245
|
-
};
|
|
155
|
+
nest-seed # run all seeders (config auto-detected)
|
|
156
|
+
nest-seed --refresh # drop (reverse order) then reseed
|
|
157
|
+
nest-seed --name users posts # run only specific seeders
|
|
158
|
+
nest-seed --dry-run # preview without writing
|
|
159
|
+
nest-seed list # list registered seeders
|
|
160
|
+
nest-seed init --orm mongoose # scaffold starter files
|
|
161
|
+
nest-seed --help # all options
|
|
246
162
|
```
|
|
247
163
|
|
|
248
|
-
|
|
164
|
+
See the [full CLI reference](https://ack-solutions.github.io/nest-seeder/guide/cli).
|
|
249
165
|
|
|
250
|
-
|
|
251
|
-
// seeder.config.ts
|
|
252
|
-
import { MongooseModule } from '@nestjs/mongoose';
|
|
253
|
-
import { User, UserSchema } from './src/schemas/user.schema';
|
|
254
|
-
import { UserSeeder } from './src/seeders/user.seeder';
|
|
166
|
+
## ๐ Upgrading from v1?
|
|
255
167
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
MongooseModule.forFeature([
|
|
260
|
-
{ name: User.name, schema: UserSchema }
|
|
261
|
-
]),
|
|
262
|
-
],
|
|
263
|
-
seeders: [UserSeeder],
|
|
264
|
-
};
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
### SQLite Example
|
|
268
|
-
|
|
269
|
-
```typescript
|
|
270
|
-
// seeder.config.ts
|
|
271
|
-
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
272
|
-
import { User } from './src/entities/user.entity';
|
|
273
|
-
import { UserSeeder } from './src/seeders/user.seeder';
|
|
274
|
-
|
|
275
|
-
export default {
|
|
276
|
-
imports: [
|
|
277
|
-
TypeOrmModule.forRoot({
|
|
278
|
-
type: 'sqlite',
|
|
279
|
-
database: 'database.sqlite',
|
|
280
|
-
entities: [User],
|
|
281
|
-
synchronize: true,
|
|
282
|
-
}),
|
|
283
|
-
TypeOrmModule.forFeature([User]),
|
|
284
|
-
],
|
|
285
|
-
seeders: [UserSeeder],
|
|
286
|
-
};
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
## ๐ญ Factories
|
|
290
|
-
|
|
291
|
-
### Basic Factory
|
|
292
|
-
|
|
293
|
-
```typescript
|
|
294
|
-
import { Factory } from '@ackplus/nest-seeder';
|
|
295
|
-
|
|
296
|
-
export class UserFactory {
|
|
297
|
-
@Factory((faker) => faker.person.fullName())
|
|
298
|
-
name: string;
|
|
299
|
-
|
|
300
|
-
@Factory((faker) => faker.internet.email())
|
|
301
|
-
email: string;
|
|
302
|
-
|
|
303
|
-
@Factory((faker) => faker.datatype.number({ min: 18, max: 80 }))
|
|
304
|
-
age: number;
|
|
305
|
-
}
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
### Using Factory
|
|
309
|
-
|
|
310
|
-
```typescript
|
|
311
|
-
import { DataFactory } from '@ackplus/nest-seeder';
|
|
312
|
-
import { UserFactory } from './user.factory';
|
|
313
|
-
|
|
314
|
-
// Create factory
|
|
315
|
-
const factory = DataFactory.createForClass(UserFactory);
|
|
316
|
-
|
|
317
|
-
// Generate one object
|
|
318
|
-
const user = factory.generate(1)[0];
|
|
319
|
-
|
|
320
|
-
// Generate multiple objects
|
|
321
|
-
const users = factory.generate(10);
|
|
322
|
-
|
|
323
|
-
// Generate with overrides
|
|
324
|
-
const admin = factory.generate(1, { role: 'admin' })[0];
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
### Factory with Relationships
|
|
328
|
-
|
|
329
|
-
```typescript
|
|
330
|
-
import { Factory } from '@ackplus/nest-seeder';
|
|
331
|
-
|
|
332
|
-
export class PostFactory {
|
|
333
|
-
@Factory((faker) => faker.lorem.sentence())
|
|
334
|
-
title: string;
|
|
335
|
-
|
|
336
|
-
@Factory((faker) => faker.lorem.paragraphs(3))
|
|
337
|
-
content: string;
|
|
338
|
-
|
|
339
|
-
// Will be set manually in seeder
|
|
340
|
-
authorId: number;
|
|
341
|
-
}
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
## ๐ฑ Seeders
|
|
345
|
-
|
|
346
|
-
### Basic Seeder
|
|
347
|
-
|
|
348
|
-
```typescript
|
|
349
|
-
import { Injectable } from '@nestjs/common';
|
|
350
|
-
import { InjectRepository } from '@nestjs/typeorm';
|
|
351
|
-
import { Repository } from 'typeorm';
|
|
352
|
-
import { Seeder, DataFactory } from '@ackplus/nest-seeder';
|
|
353
|
-
import { User } from '../entities/user.entity';
|
|
354
|
-
import { UserFactory } from '../factories/user.factory';
|
|
355
|
-
|
|
356
|
-
@Injectable()
|
|
357
|
-
export class UserSeeder implements Seeder {
|
|
358
|
-
constructor(
|
|
359
|
-
@InjectRepository(User)
|
|
360
|
-
private readonly userRepository: Repository<User>,
|
|
361
|
-
) {}
|
|
362
|
-
|
|
363
|
-
async seed(): Promise<void> {
|
|
364
|
-
const factory = DataFactory.createForClass(UserFactory);
|
|
365
|
-
const users = factory.generate(10);
|
|
366
|
-
await this.userRepository.save(users);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
async drop(): Promise<void> {
|
|
370
|
-
await this.userRepository.delete({});
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
### Seeder with Relationships
|
|
376
|
-
|
|
377
|
-
```typescript
|
|
378
|
-
import { Injectable } from '@nestjs/common';
|
|
379
|
-
import { InjectRepository } from '@nestjs/typeorm';
|
|
380
|
-
import { Repository } from 'typeorm';
|
|
381
|
-
import { Seeder, DataFactory } from '@ackplus/nest-seeder';
|
|
382
|
-
import { User } from '../entities/user.entity';
|
|
383
|
-
import { Post } from '../entities/post.entity';
|
|
384
|
-
import { UserFactory } from '../factories/user.factory';
|
|
385
|
-
import { PostFactory } from '../factories/post.factory';
|
|
386
|
-
|
|
387
|
-
@Injectable()
|
|
388
|
-
export class PostSeeder implements Seeder {
|
|
389
|
-
constructor(
|
|
390
|
-
@InjectRepository(User)
|
|
391
|
-
private readonly userRepository: Repository<User>,
|
|
392
|
-
@InjectRepository(Post)
|
|
393
|
-
private readonly postRepository: Repository<Post>,
|
|
394
|
-
) {}
|
|
395
|
-
|
|
396
|
-
async seed(): Promise<void> {
|
|
397
|
-
// Get existing users
|
|
398
|
-
const users = await this.userRepository.find();
|
|
399
|
-
|
|
400
|
-
if (users.length === 0) {
|
|
401
|
-
console.log('โ ๏ธ No users found. Run UserSeeder first.');
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// Create posts for each user
|
|
406
|
-
const postFactory = DataFactory.createForClass(PostFactory);
|
|
407
|
-
|
|
408
|
-
for (const user of users) {
|
|
409
|
-
// Generate 3 posts per user
|
|
410
|
-
const posts = postFactory.generate(3).map(post => ({
|
|
411
|
-
...post,
|
|
412
|
-
author: user,
|
|
413
|
-
}));
|
|
414
|
-
|
|
415
|
-
await this.postRepository.save(posts);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
console.log(`โ
Seeded ${users.length * 3} posts`);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
async drop(): Promise<void> {
|
|
422
|
-
await this.postRepository.delete({});
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Conditional Seeding
|
|
428
|
-
|
|
429
|
-
```typescript
|
|
430
|
-
import { Injectable } from '@nestjs/common';
|
|
431
|
-
import { Seeder, SeederServiceOptions, DataFactory } from '@ackplus/nest-seeder';
|
|
432
|
-
|
|
433
|
-
@Injectable()
|
|
434
|
-
export class UserSeeder implements Seeder {
|
|
435
|
-
async seed(options?: SeederServiceOptions): Promise<void> {
|
|
436
|
-
const factory = DataFactory.createForClass(UserFactory);
|
|
437
|
-
|
|
438
|
-
// Seed more data if dummyData flag is set
|
|
439
|
-
const count = options?.dummyData ? 100 : 10;
|
|
440
|
-
const users = factory.generate(count);
|
|
441
|
-
|
|
442
|
-
await this.userRepository.save(users);
|
|
443
|
-
console.log(`โ
Seeded ${count} users`);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
async drop(): Promise<void> {
|
|
447
|
-
await this.userRepository.delete({});
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
Run with dummy data:
|
|
453
|
-
|
|
454
|
-
```bash
|
|
455
|
-
nest-seed -c seeder.config.ts --dummyData
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
### MongoDB/Mongoose Seeder
|
|
459
|
-
|
|
460
|
-
```typescript
|
|
461
|
-
import { Injectable } from '@nestjs/common';
|
|
462
|
-
import { InjectModel } from '@nestjs/mongoose';
|
|
463
|
-
import { Model } from 'mongoose';
|
|
464
|
-
import { Seeder, DataFactory } from '@ackplus/nest-seeder';
|
|
465
|
-
import { User } from '../schemas/user.schema';
|
|
466
|
-
import { UserFactory } from '../factories/user.factory';
|
|
467
|
-
|
|
468
|
-
@Injectable()
|
|
469
|
-
export class UserSeeder implements Seeder {
|
|
470
|
-
constructor(
|
|
471
|
-
@InjectModel(User.name)
|
|
472
|
-
private readonly userModel: Model<User>,
|
|
473
|
-
) {}
|
|
474
|
-
|
|
475
|
-
async seed(): Promise<void> {
|
|
476
|
-
const factory = DataFactory.createForClass(UserFactory);
|
|
477
|
-
const users = factory.generate(10);
|
|
478
|
-
await this.userModel.insertMany(users);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
async drop(): Promise<void> {
|
|
482
|
-
await this.userModel.deleteMany({});
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
## ๐ฅ Advanced Examples
|
|
488
|
-
|
|
489
|
-
### Custom Providers in Config
|
|
490
|
-
|
|
491
|
-
```typescript
|
|
492
|
-
// seeder.config.ts
|
|
493
|
-
import { CustomService } from './src/services/custom.service';
|
|
494
|
-
|
|
495
|
-
export default {
|
|
496
|
-
imports: [
|
|
497
|
-
TypeOrmModule.forRoot({ /* ... */ }),
|
|
498
|
-
TypeOrmModule.forFeature([User]),
|
|
499
|
-
],
|
|
500
|
-
seeders: [UserSeeder],
|
|
501
|
-
providers: [CustomService], // Inject custom services
|
|
502
|
-
};
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
### Environment-Based Configuration
|
|
506
|
-
|
|
507
|
-
```typescript
|
|
508
|
-
// seeder.config.ts
|
|
509
|
-
import * as dotenv from 'dotenv';
|
|
510
|
-
dotenv.config();
|
|
511
|
-
|
|
512
|
-
const isDev = process.env.NODE_ENV === 'development';
|
|
513
|
-
|
|
514
|
-
export default {
|
|
515
|
-
imports: [
|
|
516
|
-
TypeOrmModule.forRoot({
|
|
517
|
-
type: 'postgres',
|
|
518
|
-
host: process.env.DB_HOST,
|
|
519
|
-
database: isDev ? 'mydb_dev' : 'mydb_prod',
|
|
520
|
-
synchronize: isDev,
|
|
521
|
-
}),
|
|
522
|
-
TypeOrmModule.forFeature([User, Post]),
|
|
523
|
-
],
|
|
524
|
-
seeders: isDev
|
|
525
|
-
? [UserSeeder, PostSeeder, TestDataSeeder]
|
|
526
|
-
: [UserSeeder, PostSeeder],
|
|
527
|
-
};
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
### Batch Insert for Performance
|
|
531
|
-
|
|
532
|
-
```typescript
|
|
533
|
-
@Injectable()
|
|
534
|
-
export class UserSeeder implements Seeder {
|
|
535
|
-
async seed(): Promise<void> {
|
|
536
|
-
const factory = DataFactory.createForClass(UserFactory);
|
|
537
|
-
const batchSize = 1000;
|
|
538
|
-
const totalRecords = 10000;
|
|
539
|
-
|
|
540
|
-
for (let i = 0; i < totalRecords; i += batchSize) {
|
|
541
|
-
const users = factory.generate(batchSize);
|
|
542
|
-
await this.userRepository.save(users);
|
|
543
|
-
console.log(`โ
Seeded ${Math.min(i + batchSize, totalRecords)}/${totalRecords} users`);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
async drop(): Promise<void> {
|
|
548
|
-
await this.userRepository.delete({});
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
```
|
|
552
|
-
|
|
553
|
-
## ๐ API Reference
|
|
554
|
-
|
|
555
|
-
### DataFactory
|
|
556
|
-
|
|
557
|
-
```typescript
|
|
558
|
-
class DataFactory {
|
|
559
|
-
// Create factory for a class
|
|
560
|
-
static createForClass<T>(factoryClass: new () => T): DataFactory<T>
|
|
561
|
-
|
|
562
|
-
// Generate instances
|
|
563
|
-
generate(count: number, override?: Partial<T>): T[]
|
|
564
|
-
}
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
### Seeder Interface
|
|
568
|
-
|
|
569
|
-
```typescript
|
|
570
|
-
interface Seeder {
|
|
571
|
-
// Seed data into database
|
|
572
|
-
seed(options?: SeederServiceOptions): Promise<void>
|
|
573
|
-
|
|
574
|
-
// Drop/clear data from database
|
|
575
|
-
drop(options?: SeederServiceOptions): Promise<void>
|
|
576
|
-
}
|
|
577
|
-
```
|
|
578
|
-
|
|
579
|
-
### @Factory Decorator
|
|
580
|
-
|
|
581
|
-
```typescript
|
|
582
|
-
// Simple factory
|
|
583
|
-
@Factory((faker) => faker.person.fullName())
|
|
584
|
-
name: string;
|
|
585
|
-
|
|
586
|
-
// With options
|
|
587
|
-
@Factory((faker) => faker.datatype.number({ min: 1, max: 100 }))
|
|
588
|
-
age: number;
|
|
589
|
-
|
|
590
|
-
// Array values
|
|
591
|
-
@Factory((faker) => faker.helpers.arrayElement(['admin', 'user']))
|
|
592
|
-
role: string;
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
### SeederServiceOptions
|
|
596
|
-
|
|
597
|
-
```typescript
|
|
598
|
-
interface SeederServiceOptions {
|
|
599
|
-
refresh?: boolean; // Drop before seeding
|
|
600
|
-
name?: string[]; // Run specific seeders
|
|
601
|
-
dummyData?: boolean; // Custom flag for your logic
|
|
602
|
-
}
|
|
603
|
-
```
|
|
168
|
+
v2 keeps the `@Factory` / `Seeder` / `DataFactory` core and modernizes the CLI, config, and
|
|
169
|
+
packaging. Most apps upgrade in minutes โ follow the
|
|
170
|
+
**[Migration Guide](https://ack-solutions.github.io/nest-seeder/migration)**.
|
|
604
171
|
|
|
605
172
|
## ๐ค Contributing
|
|
606
173
|
|
|
607
|
-
Contributions
|
|
174
|
+
Contributions welcome! See the [Contributing Guide](https://github.com/ack-solutions/nest-seeder/blob/main/CONTRIBUTING.md).
|
|
608
175
|
|
|
609
176
|
## ๐ License
|
|
610
177
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
## ๐ Acknowledgments
|
|
614
|
-
|
|
615
|
-
- Built with [NestJS](https://nestjs.com/)
|
|
616
|
-
- Powered by [Faker.js](https://fakerjs.dev/)
|
|
617
|
-
- Inspired by database seeding patterns from Laravel and other frameworks
|
|
618
|
-
|
|
619
|
-
## ๐ฎ Support
|
|
620
|
-
|
|
621
|
-
If you have any questions or need help:
|
|
622
|
-
- Open an issue on [GitHub](https://github.com/ackplus/nest-seeder/issues)
|
|
623
|
-
- Check the [examples](./examples/) directory
|
|
624
|
-
- Review the [Quick Start Guide](./QUICKSTART.md)
|
|
178
|
+
[MIT](./LICENSE) ยฉ AckPlus
|
|
625
179
|
|
|
626
180
|
---
|
|
627
181
|
|
|
628
|
-
|
|
182
|
+
Built with [NestJS](https://nestjs.com/) ยท Powered by [Faker.js](https://fakerjs.dev/)
|