@veloxts/cli 0.4.1 → 0.4.3
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 +23 -144
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/db.d.ts +12 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +18 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/procedures.d.ts +12 -0
- package/dist/commands/procedures.d.ts.map +1 -0
- package/dist/commands/procedures.js +153 -0
- package/dist/commands/procedures.js.map +1 -0
- package/dist/generators/generators/factory.d.ts +36 -0
- package/dist/generators/generators/factory.d.ts.map +1 -0
- package/dist/generators/generators/factory.js +85 -0
- package/dist/generators/generators/factory.js.map +1 -0
- package/dist/generators/generators/index.d.ts +2 -0
- package/dist/generators/generators/index.d.ts.map +1 -1
- package/dist/generators/generators/index.js +8 -0
- package/dist/generators/generators/index.js.map +1 -1
- package/dist/generators/generators/seeder.d.ts +36 -0
- package/dist/generators/generators/seeder.d.ts.map +1 -0
- package/dist/generators/generators/seeder.js +99 -0
- package/dist/generators/generators/seeder.js.map +1 -0
- package/dist/generators/templates/factory.d.ts +26 -0
- package/dist/generators/templates/factory.d.ts.map +1 -0
- package/dist/generators/templates/factory.js +125 -0
- package/dist/generators/templates/factory.js.map +1 -0
- package/dist/generators/templates/seeder.d.ts +34 -0
- package/dist/generators/templates/seeder.d.ts.map +1 -0
- package/dist/generators/templates/seeder.js +129 -0
- package/dist/generators/templates/seeder.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/migrations/rollback-runner.d.ts.map +1 -1
- package/dist/migrations/rollback-runner.js +13 -1
- package/dist/migrations/rollback-runner.js.map +1 -1
- package/dist/seeding/commands/seed.d.ts +11 -0
- package/dist/seeding/commands/seed.d.ts.map +1 -0
- package/dist/seeding/commands/seed.js +268 -0
- package/dist/seeding/commands/seed.js.map +1 -0
- package/dist/seeding/errors.d.ts +119 -0
- package/dist/seeding/errors.d.ts.map +1 -0
- package/dist/seeding/errors.js +191 -0
- package/dist/seeding/errors.js.map +1 -0
- package/dist/seeding/factory.d.ts +162 -0
- package/dist/seeding/factory.d.ts.map +1 -0
- package/dist/seeding/factory.js +250 -0
- package/dist/seeding/factory.js.map +1 -0
- package/dist/seeding/index.d.ts +31 -0
- package/dist/seeding/index.d.ts.map +1 -0
- package/dist/seeding/index.js +41 -0
- package/dist/seeding/index.js.map +1 -0
- package/dist/seeding/loader.d.ts +41 -0
- package/dist/seeding/loader.d.ts.map +1 -0
- package/dist/seeding/loader.js +210 -0
- package/dist/seeding/loader.js.map +1 -0
- package/dist/seeding/registry.d.ts +116 -0
- package/dist/seeding/registry.d.ts.map +1 -0
- package/dist/seeding/registry.js +298 -0
- package/dist/seeding/registry.js.map +1 -0
- package/dist/seeding/runner.d.ts +88 -0
- package/dist/seeding/runner.d.ts.map +1 -0
- package/dist/seeding/runner.js +254 -0
- package/dist/seeding/runner.js.map +1 -0
- package/dist/seeding/types.d.ts +247 -0
- package/dist/seeding/types.d.ts.map +1 -0
- package/dist/seeding/types.js +7 -0
- package/dist/seeding/types.js.map +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeder Loader
|
|
3
|
+
*
|
|
4
|
+
* Load seeder files from the filesystem.
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { pathToFileURL } from 'node:url';
|
|
9
|
+
import { filesystemError, invalidExport } from './errors.js';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Constants
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Default path for seeders relative to project root
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_SEEDERS_PATH = 'src/database/seeders';
|
|
17
|
+
/**
|
|
18
|
+
* File patterns that indicate a seeder file
|
|
19
|
+
*/
|
|
20
|
+
const SEEDER_FILE_PATTERNS = [/Seeder\.(ts|js)$/, /\.seeder\.(ts|js)$/];
|
|
21
|
+
/**
|
|
22
|
+
* Files to skip
|
|
23
|
+
*/
|
|
24
|
+
const SKIP_FILES = ['index.ts', 'index.js', 'DatabaseSeeder.ts', 'DatabaseSeeder.js'];
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Loader Functions
|
|
27
|
+
// ============================================================================
|
|
28
|
+
/**
|
|
29
|
+
* Check if seeders directory exists.
|
|
30
|
+
*
|
|
31
|
+
* @param cwd - Project root directory
|
|
32
|
+
* @param seedersPath - Path to seeders directory (relative to cwd)
|
|
33
|
+
*/
|
|
34
|
+
export async function seedersDirectoryExists(cwd, seedersPath = DEFAULT_SEEDERS_PATH) {
|
|
35
|
+
const fullPath = path.join(cwd, seedersPath);
|
|
36
|
+
try {
|
|
37
|
+
const stat = await fs.stat(fullPath);
|
|
38
|
+
return stat.isDirectory();
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Load all seeders from the filesystem.
|
|
46
|
+
*
|
|
47
|
+
* @param cwd - Project root directory
|
|
48
|
+
* @param seedersPath - Path to seeders directory (relative to cwd)
|
|
49
|
+
* @returns Load result with seeders and any errors
|
|
50
|
+
*/
|
|
51
|
+
export async function loadSeeders(cwd, seedersPath = DEFAULT_SEEDERS_PATH) {
|
|
52
|
+
const fullPath = path.join(cwd, seedersPath);
|
|
53
|
+
const seeders = [];
|
|
54
|
+
const errors = [];
|
|
55
|
+
// Check directory exists
|
|
56
|
+
if (!(await seedersDirectoryExists(cwd, seedersPath))) {
|
|
57
|
+
return { seeders: [], errors: [] };
|
|
58
|
+
}
|
|
59
|
+
// List files
|
|
60
|
+
let files;
|
|
61
|
+
try {
|
|
62
|
+
files = await fs.readdir(fullPath);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
66
|
+
throw filesystemError('reading seeders directory', fullPath, err);
|
|
67
|
+
}
|
|
68
|
+
// Filter to seeder files
|
|
69
|
+
const seederFiles = files.filter((file) => {
|
|
70
|
+
// Skip non-seeder files
|
|
71
|
+
if (SKIP_FILES.includes(file))
|
|
72
|
+
return false;
|
|
73
|
+
// Check if matches seeder pattern
|
|
74
|
+
return SEEDER_FILE_PATTERNS.some((pattern) => pattern.test(file));
|
|
75
|
+
});
|
|
76
|
+
// Load each seeder
|
|
77
|
+
for (const file of seederFiles) {
|
|
78
|
+
const filePath = path.join(fullPath, file);
|
|
79
|
+
try {
|
|
80
|
+
const seeder = await loadSeederFile(filePath);
|
|
81
|
+
seeders.push({ seeder, filePath });
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
85
|
+
errors.push({ filePath, error: err.message });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return { seeders, errors };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Load the main DatabaseSeeder entry point.
|
|
92
|
+
*
|
|
93
|
+
* @param cwd - Project root directory
|
|
94
|
+
* @param seedersPath - Path to seeders directory (relative to cwd)
|
|
95
|
+
* @returns DatabaseSeeder if found, null otherwise
|
|
96
|
+
*/
|
|
97
|
+
export async function loadDatabaseSeeder(cwd, seedersPath = DEFAULT_SEEDERS_PATH) {
|
|
98
|
+
const fullPath = path.join(cwd, seedersPath);
|
|
99
|
+
// Try both .ts and .js extensions
|
|
100
|
+
for (const ext of ['ts', 'js']) {
|
|
101
|
+
const filePath = path.join(fullPath, `DatabaseSeeder.${ext}`);
|
|
102
|
+
try {
|
|
103
|
+
const stat = await fs.stat(filePath);
|
|
104
|
+
if (stat.isFile()) {
|
|
105
|
+
return await loadSeederFile(filePath);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// File doesn't exist, try next
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Load a single seeder file.
|
|
116
|
+
*
|
|
117
|
+
* @param filePath - Absolute path to seeder file
|
|
118
|
+
* @returns Loaded seeder
|
|
119
|
+
*/
|
|
120
|
+
async function loadSeederFile(filePath) {
|
|
121
|
+
// Convert to file URL for dynamic import
|
|
122
|
+
const fileUrl = pathToFileURL(filePath).href;
|
|
123
|
+
// Dynamic import
|
|
124
|
+
let module;
|
|
125
|
+
try {
|
|
126
|
+
module = (await import(fileUrl));
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
130
|
+
throw invalidExport(filePath, `Failed to import: ${err.message}`);
|
|
131
|
+
}
|
|
132
|
+
// Look for seeder export
|
|
133
|
+
const seeder = findSeederExport(module);
|
|
134
|
+
if (!seeder) {
|
|
135
|
+
throw invalidExport(filePath, 'No valid seeder export found. Export a const named *Seeder or use default export.');
|
|
136
|
+
}
|
|
137
|
+
// Validate seeder shape
|
|
138
|
+
validateSeeder(seeder, filePath);
|
|
139
|
+
return seeder;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Find a seeder export in a module.
|
|
143
|
+
*/
|
|
144
|
+
function findSeederExport(module) {
|
|
145
|
+
// Check default export first
|
|
146
|
+
if (module.default && isSeederLike(module.default)) {
|
|
147
|
+
return module.default;
|
|
148
|
+
}
|
|
149
|
+
// Look for named export ending in 'Seeder'
|
|
150
|
+
for (const [key, value] of Object.entries(module)) {
|
|
151
|
+
if (key.endsWith('Seeder') && isSeederLike(value)) {
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Check if a value looks like a seeder.
|
|
159
|
+
*/
|
|
160
|
+
function isSeederLike(value) {
|
|
161
|
+
if (!value || typeof value !== 'object')
|
|
162
|
+
return false;
|
|
163
|
+
const obj = value;
|
|
164
|
+
return typeof obj.name === 'string' && typeof obj.run === 'function';
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Validate a seeder has the required shape.
|
|
168
|
+
*/
|
|
169
|
+
function validateSeeder(seeder, filePath) {
|
|
170
|
+
if (!seeder || typeof seeder !== 'object') {
|
|
171
|
+
throw invalidExport(filePath, 'Seeder must be an object');
|
|
172
|
+
}
|
|
173
|
+
const obj = seeder;
|
|
174
|
+
if (typeof obj.name !== 'string' || obj.name.length === 0) {
|
|
175
|
+
throw invalidExport(filePath, "Seeder must have a non-empty 'name' property");
|
|
176
|
+
}
|
|
177
|
+
if (typeof obj.run !== 'function') {
|
|
178
|
+
throw invalidExport(filePath, "Seeder must have a 'run' function");
|
|
179
|
+
}
|
|
180
|
+
if (obj.dependencies !== undefined && !Array.isArray(obj.dependencies)) {
|
|
181
|
+
throw invalidExport(filePath, "'dependencies' must be an array of strings");
|
|
182
|
+
}
|
|
183
|
+
if (obj.environments !== undefined && !Array.isArray(obj.environments)) {
|
|
184
|
+
throw invalidExport(filePath, "'environments' must be an array");
|
|
185
|
+
}
|
|
186
|
+
if (obj.truncate !== undefined && typeof obj.truncate !== 'function') {
|
|
187
|
+
throw invalidExport(filePath, "'truncate' must be a function");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get all seeder file paths from directory.
|
|
192
|
+
*
|
|
193
|
+
* @param cwd - Project root directory
|
|
194
|
+
* @param seedersPath - Path to seeders directory (relative to cwd)
|
|
195
|
+
*/
|
|
196
|
+
export async function getSeederFiles(cwd, seedersPath = DEFAULT_SEEDERS_PATH) {
|
|
197
|
+
const fullPath = path.join(cwd, seedersPath);
|
|
198
|
+
if (!(await seedersDirectoryExists(cwd, seedersPath))) {
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
const files = await fs.readdir(fullPath);
|
|
202
|
+
return files
|
|
203
|
+
.filter((file) => {
|
|
204
|
+
if (SKIP_FILES.includes(file))
|
|
205
|
+
return false;
|
|
206
|
+
return SEEDER_FILE_PATTERNS.some((pattern) => pattern.test(file));
|
|
207
|
+
})
|
|
208
|
+
.map((file) => path.join(fullPath, file));
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/seeding/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeder Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages seeder registration and dependency resolution with topological sorting.
|
|
5
|
+
*/
|
|
6
|
+
import type { Environment, Seeder } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Registry for managing seeders with dependency resolution.
|
|
9
|
+
*
|
|
10
|
+
* Handles seeder registration, retrieval, and ordering based on dependencies
|
|
11
|
+
* using topological sorting.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const registry = new SeederRegistry();
|
|
16
|
+
*
|
|
17
|
+
* registry.register(UserSeeder);
|
|
18
|
+
* registry.register(PostSeeder); // depends on UserSeeder
|
|
19
|
+
*
|
|
20
|
+
* // Get seeders in correct execution order
|
|
21
|
+
* const ordered = registry.getInOrder();
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare class SeederRegistry {
|
|
25
|
+
private seeders;
|
|
26
|
+
/**
|
|
27
|
+
* Register a seeder in the registry.
|
|
28
|
+
*
|
|
29
|
+
* @param seeder - Seeder to register
|
|
30
|
+
* @throws Error if seeder with same name already exists
|
|
31
|
+
*/
|
|
32
|
+
register(seeder: Seeder): void;
|
|
33
|
+
/**
|
|
34
|
+
* Register multiple seeders.
|
|
35
|
+
*
|
|
36
|
+
* @param seeders - Seeders to register
|
|
37
|
+
*/
|
|
38
|
+
registerMany(seeders: Seeder[]): void;
|
|
39
|
+
/**
|
|
40
|
+
* Get a seeder by name.
|
|
41
|
+
*
|
|
42
|
+
* @param name - Seeder name
|
|
43
|
+
* @returns Seeder if found, undefined otherwise
|
|
44
|
+
*/
|
|
45
|
+
get(name: string): Seeder | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Get a seeder by name, throwing if not found.
|
|
48
|
+
*
|
|
49
|
+
* @param name - Seeder name
|
|
50
|
+
* @returns Seeder
|
|
51
|
+
* @throws SeederError if not found
|
|
52
|
+
*/
|
|
53
|
+
getOrThrow(name: string): Seeder;
|
|
54
|
+
/**
|
|
55
|
+
* Check if a seeder exists.
|
|
56
|
+
*
|
|
57
|
+
* @param name - Seeder name
|
|
58
|
+
*/
|
|
59
|
+
has(name: string): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Get all registered seeder names.
|
|
62
|
+
*/
|
|
63
|
+
getNames(): string[];
|
|
64
|
+
/**
|
|
65
|
+
* Get all registered seeders.
|
|
66
|
+
*/
|
|
67
|
+
getAll(): Seeder[];
|
|
68
|
+
/**
|
|
69
|
+
* Get seeder count.
|
|
70
|
+
*/
|
|
71
|
+
get size(): number;
|
|
72
|
+
/**
|
|
73
|
+
* Clear all registered seeders.
|
|
74
|
+
*/
|
|
75
|
+
clear(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Validate all seeder dependencies exist and there are no circular dependencies.
|
|
78
|
+
*
|
|
79
|
+
* @throws SeederError if dependencies are invalid
|
|
80
|
+
*/
|
|
81
|
+
validateDependencies(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Get all seeders in dependency order (topological sort).
|
|
84
|
+
*
|
|
85
|
+
* Seeders with no dependencies come first, then seeders that depend on them, etc.
|
|
86
|
+
*
|
|
87
|
+
* @param environment - Optional environment filter
|
|
88
|
+
* @returns Seeders in execution order
|
|
89
|
+
* @throws SeederError if circular dependency detected
|
|
90
|
+
*/
|
|
91
|
+
getInOrder(environment?: Environment): Seeder[];
|
|
92
|
+
/**
|
|
93
|
+
* Get seeders filtered by names in dependency order.
|
|
94
|
+
*
|
|
95
|
+
* @param names - Seeder names to include (and their dependencies)
|
|
96
|
+
* @param environment - Optional environment filter
|
|
97
|
+
*/
|
|
98
|
+
getByNames(names: string[], environment?: Environment): Seeder[];
|
|
99
|
+
/**
|
|
100
|
+
* Check if seeder should run in given environment.
|
|
101
|
+
*/
|
|
102
|
+
private shouldRunInEnvironment;
|
|
103
|
+
/**
|
|
104
|
+
* Detect circular dependencies using DFS.
|
|
105
|
+
*/
|
|
106
|
+
private detectCircularDependencies;
|
|
107
|
+
/**
|
|
108
|
+
* DFS helper for cycle detection.
|
|
109
|
+
*/
|
|
110
|
+
private detectCycleDFS;
|
|
111
|
+
/**
|
|
112
|
+
* Find and return a cycle starting from the given node.
|
|
113
|
+
*/
|
|
114
|
+
private findCycle;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/seeding/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAMtD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAkC;IAEjD;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAO9B;;;;OAIG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAMrC;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIrC;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAQhC;;;;OAIG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;OAEG;IACH,QAAQ,IAAI,MAAM,EAAE;IAIpB;;OAEG;IACH,MAAM,IAAI,MAAM,EAAE;IAIlB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;;;OAIG;IACH,oBAAoB,IAAI,IAAI;IAc5B;;;;;;;;OAQG;IACH,UAAU,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE;IAmE/C;;;;;OAKG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE;IAgChE;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAWlC;;OAEG;IACH,OAAO,CAAC,cAAc;IAoBtB;;OAEG;IACH,OAAO,CAAC,SAAS;CAgClB"}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeder Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages seeder registration and dependency resolution with topological sorting.
|
|
5
|
+
*/
|
|
6
|
+
import { circularDependency, dependencyNotFound, seederNotFound } from './errors.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Seeder Registry
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Registry for managing seeders with dependency resolution.
|
|
12
|
+
*
|
|
13
|
+
* Handles seeder registration, retrieval, and ordering based on dependencies
|
|
14
|
+
* using topological sorting.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const registry = new SeederRegistry();
|
|
19
|
+
*
|
|
20
|
+
* registry.register(UserSeeder);
|
|
21
|
+
* registry.register(PostSeeder); // depends on UserSeeder
|
|
22
|
+
*
|
|
23
|
+
* // Get seeders in correct execution order
|
|
24
|
+
* const ordered = registry.getInOrder();
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class SeederRegistry {
|
|
28
|
+
seeders = new Map();
|
|
29
|
+
/**
|
|
30
|
+
* Register a seeder in the registry.
|
|
31
|
+
*
|
|
32
|
+
* @param seeder - Seeder to register
|
|
33
|
+
* @throws Error if seeder with same name already exists
|
|
34
|
+
*/
|
|
35
|
+
register(seeder) {
|
|
36
|
+
if (this.seeders.has(seeder.name)) {
|
|
37
|
+
throw new Error(`Seeder '${seeder.name}' is already registered`);
|
|
38
|
+
}
|
|
39
|
+
this.seeders.set(seeder.name, seeder);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Register multiple seeders.
|
|
43
|
+
*
|
|
44
|
+
* @param seeders - Seeders to register
|
|
45
|
+
*/
|
|
46
|
+
registerMany(seeders) {
|
|
47
|
+
for (const seeder of seeders) {
|
|
48
|
+
this.register(seeder);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get a seeder by name.
|
|
53
|
+
*
|
|
54
|
+
* @param name - Seeder name
|
|
55
|
+
* @returns Seeder if found, undefined otherwise
|
|
56
|
+
*/
|
|
57
|
+
get(name) {
|
|
58
|
+
return this.seeders.get(name);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get a seeder by name, throwing if not found.
|
|
62
|
+
*
|
|
63
|
+
* @param name - Seeder name
|
|
64
|
+
* @returns Seeder
|
|
65
|
+
* @throws SeederError if not found
|
|
66
|
+
*/
|
|
67
|
+
getOrThrow(name) {
|
|
68
|
+
const seeder = this.seeders.get(name);
|
|
69
|
+
if (!seeder) {
|
|
70
|
+
throw seederNotFound(name);
|
|
71
|
+
}
|
|
72
|
+
return seeder;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if a seeder exists.
|
|
76
|
+
*
|
|
77
|
+
* @param name - Seeder name
|
|
78
|
+
*/
|
|
79
|
+
has(name) {
|
|
80
|
+
return this.seeders.has(name);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get all registered seeder names.
|
|
84
|
+
*/
|
|
85
|
+
getNames() {
|
|
86
|
+
return Array.from(this.seeders.keys());
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get all registered seeders.
|
|
90
|
+
*/
|
|
91
|
+
getAll() {
|
|
92
|
+
return Array.from(this.seeders.values());
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get seeder count.
|
|
96
|
+
*/
|
|
97
|
+
get size() {
|
|
98
|
+
return this.seeders.size;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Clear all registered seeders.
|
|
102
|
+
*/
|
|
103
|
+
clear() {
|
|
104
|
+
this.seeders.clear();
|
|
105
|
+
}
|
|
106
|
+
// ==========================================================================
|
|
107
|
+
// Dependency Resolution
|
|
108
|
+
// ==========================================================================
|
|
109
|
+
/**
|
|
110
|
+
* Validate all seeder dependencies exist and there are no circular dependencies.
|
|
111
|
+
*
|
|
112
|
+
* @throws SeederError if dependencies are invalid
|
|
113
|
+
*/
|
|
114
|
+
validateDependencies() {
|
|
115
|
+
// Check all dependencies exist
|
|
116
|
+
for (const seeder of this.seeders.values()) {
|
|
117
|
+
for (const depName of seeder.dependencies ?? []) {
|
|
118
|
+
if (!this.seeders.has(depName)) {
|
|
119
|
+
throw dependencyNotFound(seeder.name, depName);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Check for circular dependencies
|
|
124
|
+
this.detectCircularDependencies();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get all seeders in dependency order (topological sort).
|
|
128
|
+
*
|
|
129
|
+
* Seeders with no dependencies come first, then seeders that depend on them, etc.
|
|
130
|
+
*
|
|
131
|
+
* @param environment - Optional environment filter
|
|
132
|
+
* @returns Seeders in execution order
|
|
133
|
+
* @throws SeederError if circular dependency detected
|
|
134
|
+
*/
|
|
135
|
+
getInOrder(environment) {
|
|
136
|
+
this.validateDependencies();
|
|
137
|
+
// Filter by environment if specified
|
|
138
|
+
const seeders = environment
|
|
139
|
+
? Array.from(this.seeders.values()).filter((s) => this.shouldRunInEnvironment(s, environment))
|
|
140
|
+
: Array.from(this.seeders.values());
|
|
141
|
+
// Build adjacency list and in-degree count
|
|
142
|
+
const inDegree = new Map();
|
|
143
|
+
const adjacency = new Map();
|
|
144
|
+
for (const seeder of seeders) {
|
|
145
|
+
inDegree.set(seeder.name, 0);
|
|
146
|
+
adjacency.set(seeder.name, []);
|
|
147
|
+
}
|
|
148
|
+
// Count dependencies (in-degree) and build reverse adjacency
|
|
149
|
+
for (const seeder of seeders) {
|
|
150
|
+
for (const depName of seeder.dependencies ?? []) {
|
|
151
|
+
// Only count if dependency is in our filtered set
|
|
152
|
+
if (inDegree.has(depName)) {
|
|
153
|
+
inDegree.set(seeder.name, (inDegree.get(seeder.name) ?? 0) + 1);
|
|
154
|
+
adjacency.get(depName)?.push(seeder.name);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Kahn's algorithm for topological sort
|
|
159
|
+
const queue = [];
|
|
160
|
+
const result = [];
|
|
161
|
+
// Start with seeders that have no dependencies
|
|
162
|
+
for (const [name, degree] of inDegree) {
|
|
163
|
+
if (degree === 0) {
|
|
164
|
+
queue.push(name);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
while (queue.length > 0) {
|
|
168
|
+
const name = queue.shift();
|
|
169
|
+
if (!name)
|
|
170
|
+
continue;
|
|
171
|
+
const seeder = this.seeders.get(name);
|
|
172
|
+
if (!seeder)
|
|
173
|
+
continue;
|
|
174
|
+
result.push(seeder);
|
|
175
|
+
// Reduce in-degree of dependents
|
|
176
|
+
for (const dependent of adjacency.get(name) ?? []) {
|
|
177
|
+
const newDegree = (inDegree.get(dependent) ?? 0) - 1;
|
|
178
|
+
inDegree.set(dependent, newDegree);
|
|
179
|
+
if (newDegree === 0) {
|
|
180
|
+
queue.push(dependent);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// If result doesn't contain all seeders, there's a cycle
|
|
185
|
+
if (result.length !== seeders.length) {
|
|
186
|
+
// Find the cycle for error message
|
|
187
|
+
const remaining = seeders.filter((s) => !result.includes(s));
|
|
188
|
+
const cycle = this.findCycle(remaining[0].name);
|
|
189
|
+
throw circularDependency(cycle);
|
|
190
|
+
}
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get seeders filtered by names in dependency order.
|
|
195
|
+
*
|
|
196
|
+
* @param names - Seeder names to include (and their dependencies)
|
|
197
|
+
* @param environment - Optional environment filter
|
|
198
|
+
*/
|
|
199
|
+
getByNames(names, environment) {
|
|
200
|
+
// Collect requested seeders and all their transitive dependencies
|
|
201
|
+
const needed = new Set();
|
|
202
|
+
const stack = [...names];
|
|
203
|
+
while (stack.length > 0) {
|
|
204
|
+
const name = stack.pop();
|
|
205
|
+
if (!name || needed.has(name))
|
|
206
|
+
continue;
|
|
207
|
+
const seeder = this.getOrThrow(name);
|
|
208
|
+
// Skip if not for this environment
|
|
209
|
+
if (environment && !this.shouldRunInEnvironment(seeder, environment)) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
needed.add(name);
|
|
213
|
+
// Add dependencies to stack
|
|
214
|
+
for (const dep of seeder.dependencies ?? []) {
|
|
215
|
+
stack.push(dep);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Get all in order, then filter to only needed
|
|
219
|
+
return this.getInOrder(environment).filter((s) => needed.has(s.name));
|
|
220
|
+
}
|
|
221
|
+
// ==========================================================================
|
|
222
|
+
// Private Helpers
|
|
223
|
+
// ==========================================================================
|
|
224
|
+
/**
|
|
225
|
+
* Check if seeder should run in given environment.
|
|
226
|
+
*/
|
|
227
|
+
shouldRunInEnvironment(seeder, environment) {
|
|
228
|
+
// If no environments specified, run in all
|
|
229
|
+
if (!seeder.environments || seeder.environments.length === 0) {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
return seeder.environments.includes(environment);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Detect circular dependencies using DFS.
|
|
236
|
+
*/
|
|
237
|
+
detectCircularDependencies() {
|
|
238
|
+
const visited = new Set();
|
|
239
|
+
const recursionStack = new Set();
|
|
240
|
+
for (const seeder of this.seeders.values()) {
|
|
241
|
+
if (!visited.has(seeder.name)) {
|
|
242
|
+
this.detectCycleDFS(seeder.name, visited, recursionStack);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* DFS helper for cycle detection.
|
|
248
|
+
*/
|
|
249
|
+
detectCycleDFS(name, visited, stack) {
|
|
250
|
+
visited.add(name);
|
|
251
|
+
stack.add(name);
|
|
252
|
+
const seeder = this.seeders.get(name);
|
|
253
|
+
if (!seeder)
|
|
254
|
+
return;
|
|
255
|
+
for (const depName of seeder.dependencies ?? []) {
|
|
256
|
+
if (!visited.has(depName)) {
|
|
257
|
+
this.detectCycleDFS(depName, visited, stack);
|
|
258
|
+
}
|
|
259
|
+
else if (stack.has(depName)) {
|
|
260
|
+
// Found cycle - build the cycle path for error message
|
|
261
|
+
const cycle = this.findCycle(depName);
|
|
262
|
+
throw circularDependency(cycle);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
stack.delete(name);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Find and return a cycle starting from the given node.
|
|
269
|
+
*/
|
|
270
|
+
findCycle(startName) {
|
|
271
|
+
const path = [];
|
|
272
|
+
const visited = new Set();
|
|
273
|
+
const dfs = (name) => {
|
|
274
|
+
if (path.includes(name)) {
|
|
275
|
+
// Found cycle - close it by adding the start again
|
|
276
|
+
path.push(name);
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
if (visited.has(name))
|
|
280
|
+
return false;
|
|
281
|
+
visited.add(name);
|
|
282
|
+
path.push(name);
|
|
283
|
+
const seeder = this.seeders.get(name);
|
|
284
|
+
for (const depName of seeder?.dependencies ?? []) {
|
|
285
|
+
if (dfs(depName))
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
path.pop();
|
|
289
|
+
return false;
|
|
290
|
+
};
|
|
291
|
+
dfs(startName);
|
|
292
|
+
// Extract just the cycle portion (from first occurrence of last element)
|
|
293
|
+
const lastElement = path[path.length - 1];
|
|
294
|
+
const firstOccurrence = path.indexOf(lastElement);
|
|
295
|
+
return path.slice(firstOccurrence);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/seeding/registry.ts"],"names":[],"mappings":"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"}
|