@t1mmen/srtd 0.0.0-next-20251227000343
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/LICENSE +21 -0
- package/README.md +363 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +50 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/apply.d.ts +2 -0
- package/dist/commands/apply.js +105 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.js +134 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/clear.d.ts +2 -0
- package/dist/commands/clear.js +161 -0
- package/dist/commands/clear.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +91 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/menu.d.ts +4 -0
- package/dist/commands/menu.js +76 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/commands/promote.d.ts +2 -0
- package/dist/commands/promote.js +181 -0
- package/dist/commands/promote.js.map +1 -0
- package/dist/commands/register.d.ts +2 -0
- package/dist/commands/register.js +192 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/watch.d.ts +14 -0
- package/dist/commands/watch.js +190 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -0
- package/dist/services/DatabaseService.d.ts +113 -0
- package/dist/services/DatabaseService.js +343 -0
- package/dist/services/DatabaseService.js.map +1 -0
- package/dist/services/FileSystemService.d.ts +100 -0
- package/dist/services/FileSystemService.js +237 -0
- package/dist/services/FileSystemService.js.map +1 -0
- package/dist/services/MigrationBuilder.d.ts +106 -0
- package/dist/services/MigrationBuilder.js +193 -0
- package/dist/services/MigrationBuilder.js.map +1 -0
- package/dist/services/Orchestrator.d.ts +155 -0
- package/dist/services/Orchestrator.js +622 -0
- package/dist/services/Orchestrator.js.map +1 -0
- package/dist/services/StateService.d.ts +169 -0
- package/dist/services/StateService.js +463 -0
- package/dist/services/StateService.js.map +1 -0
- package/dist/types.d.ts +48 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/badge.d.ts +14 -0
- package/dist/ui/badge.js +28 -0
- package/dist/ui/badge.js.map +1 -0
- package/dist/ui/branding.d.ts +9 -0
- package/dist/ui/branding.js +35 -0
- package/dist/ui/branding.js.map +1 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +5 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/results.d.ts +10 -0
- package/dist/ui/results.js +62 -0
- package/dist/ui/results.js.map +1 -0
- package/dist/ui/spinner.d.ts +5 -0
- package/dist/ui/spinner.js +8 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/utils/config.d.ts +12 -0
- package/dist/utils/config.js +67 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/createEmptyBuildLog.d.ts +1 -0
- package/dist/utils/createEmptyBuildLog.js +10 -0
- package/dist/utils/createEmptyBuildLog.js.map +1 -0
- package/dist/utils/ensureDirectories.d.ts +4 -0
- package/dist/utils/ensureDirectories.js +23 -0
- package/dist/utils/ensureDirectories.js.map +1 -0
- package/dist/utils/fileExists.d.ts +1 -0
- package/dist/utils/fileExists.js +11 -0
- package/dist/utils/fileExists.js.map +1 -0
- package/dist/utils/findProjectRoot.d.ts +1 -0
- package/dist/utils/findProjectRoot.js +25 -0
- package/dist/utils/findProjectRoot.js.map +1 -0
- package/dist/utils/getErrorMessage.d.ts +9 -0
- package/dist/utils/getErrorMessage.js +14 -0
- package/dist/utils/getErrorMessage.js.map +1 -0
- package/dist/utils/getNextTimestamp.d.ts +2 -0
- package/dist/utils/getNextTimestamp.js +12 -0
- package/dist/utils/getNextTimestamp.js.map +1 -0
- package/dist/utils/isWipTemplate.d.ts +1 -0
- package/dist/utils/isWipTemplate.js +6 -0
- package/dist/utils/isWipTemplate.js.map +1 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.js +12 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/safeCreate.d.ts +1 -0
- package/dist/utils/safeCreate.js +16 -0
- package/dist/utils/safeCreate.js.map +1 -0
- package/package.json +106 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FileSystemService - Handles all file system operations for templates
|
|
3
|
+
* Decoupled from business logic, only handles raw file operations
|
|
4
|
+
*/
|
|
5
|
+
import crypto from 'node:crypto';
|
|
6
|
+
import { EventEmitter } from 'node:events';
|
|
7
|
+
import fs from 'node:fs/promises';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { glob } from 'glob';
|
|
10
|
+
export class FileSystemService extends EventEmitter {
|
|
11
|
+
config;
|
|
12
|
+
watcher = null;
|
|
13
|
+
debouncedHandlers = new Map();
|
|
14
|
+
constructor(config) {
|
|
15
|
+
super();
|
|
16
|
+
this.config = config;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Find all template files matching the configured pattern
|
|
20
|
+
*/
|
|
21
|
+
async findTemplates() {
|
|
22
|
+
const templatePath = path.join(this.config.baseDir, this.config.templateDir, this.config.filter);
|
|
23
|
+
const matches = await glob(templatePath);
|
|
24
|
+
return matches.sort(); // Ensure consistent ordering
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Read a template file and return its content with metadata
|
|
28
|
+
*/
|
|
29
|
+
async readTemplate(templatePath) {
|
|
30
|
+
try {
|
|
31
|
+
const content = await fs.readFile(templatePath, 'utf-8');
|
|
32
|
+
const hash = this.calculateHash(content);
|
|
33
|
+
const name = path.basename(templatePath, '.sql');
|
|
34
|
+
const relativePath = path.relative(this.config.baseDir, templatePath);
|
|
35
|
+
return {
|
|
36
|
+
path: templatePath,
|
|
37
|
+
name,
|
|
38
|
+
content,
|
|
39
|
+
hash,
|
|
40
|
+
relativePath,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
45
|
+
throw new Error(`Template file not found: ${templatePath}`);
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if a file exists
|
|
52
|
+
*/
|
|
53
|
+
async fileExists(filePath) {
|
|
54
|
+
try {
|
|
55
|
+
await fs.stat(filePath);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Write content to a file
|
|
64
|
+
*/
|
|
65
|
+
async writeFile(filePath, content) {
|
|
66
|
+
const dir = path.dirname(filePath);
|
|
67
|
+
await fs.mkdir(dir, { recursive: true });
|
|
68
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Delete a file
|
|
72
|
+
*/
|
|
73
|
+
async deleteFile(filePath) {
|
|
74
|
+
try {
|
|
75
|
+
await fs.unlink(filePath);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
79
|
+
// File doesn't exist, ignore
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Rename a file
|
|
87
|
+
*/
|
|
88
|
+
async renameFile(oldPath, newPath) {
|
|
89
|
+
await fs.rename(oldPath, newPath);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get file stats
|
|
93
|
+
*/
|
|
94
|
+
async getFileStats(filePath) {
|
|
95
|
+
return fs.stat(filePath);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Calculate MD5 hash of content
|
|
99
|
+
*/
|
|
100
|
+
calculateHash(content) {
|
|
101
|
+
return crypto.createHash('md5').update(content).digest('hex');
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Watch templates for changes
|
|
105
|
+
*/
|
|
106
|
+
async watchTemplates() {
|
|
107
|
+
if (this.watcher) {
|
|
108
|
+
throw new Error('Already watching templates');
|
|
109
|
+
}
|
|
110
|
+
const chokidar = await import('chokidar');
|
|
111
|
+
const templatePath = path.join(this.config.baseDir, this.config.templateDir);
|
|
112
|
+
const watchOptions = {
|
|
113
|
+
ignoreInitial: this.config.watchOptions?.ignoreInitial ?? false,
|
|
114
|
+
ignored: ['**/!(*.sql)'],
|
|
115
|
+
persistent: true,
|
|
116
|
+
awaitWriteFinish: {
|
|
117
|
+
stabilityThreshold: this.config.watchOptions?.stabilityThreshold ?? 200,
|
|
118
|
+
pollInterval: this.config.watchOptions?.pollInterval ?? 100,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
this.watcher = chokidar.watch(templatePath, watchOptions);
|
|
122
|
+
// Handle initial files if not ignoring
|
|
123
|
+
if (!watchOptions.ignoreInitial) {
|
|
124
|
+
const existingFiles = await this.findTemplates();
|
|
125
|
+
for (const file of existingFiles) {
|
|
126
|
+
this.emitWatchEvent('added', file);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Set up event handlers with debouncing
|
|
130
|
+
this.watcher
|
|
131
|
+
.on('add', (filepath) => {
|
|
132
|
+
if (path.extname(filepath) === '.sql') {
|
|
133
|
+
this.debouncedEmit('added', filepath);
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
.on('change', (filepath) => {
|
|
137
|
+
if (path.extname(filepath) === '.sql') {
|
|
138
|
+
this.debouncedEmit('changed', filepath);
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
.on('unlink', (filepath) => {
|
|
142
|
+
if (path.extname(filepath) === '.sql') {
|
|
143
|
+
this.debouncedEmit('removed', filepath);
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
.on('error', (error) => {
|
|
147
|
+
this.emit('error', error instanceof Error ? error : new Error(String(error)));
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Stop watching templates
|
|
152
|
+
*/
|
|
153
|
+
async stopWatching() {
|
|
154
|
+
// Clear any pending debounced handlers
|
|
155
|
+
for (const timer of this.debouncedHandlers.values()) {
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
}
|
|
158
|
+
this.debouncedHandlers.clear();
|
|
159
|
+
if (this.watcher) {
|
|
160
|
+
await this.watcher.close();
|
|
161
|
+
this.watcher = null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Emit watch event with debouncing
|
|
166
|
+
*/
|
|
167
|
+
debouncedEmit(type, filepath) {
|
|
168
|
+
const key = `${type}:${filepath}`;
|
|
169
|
+
// Clear existing timer for this event
|
|
170
|
+
const existingTimer = this.debouncedHandlers.get(key);
|
|
171
|
+
if (existingTimer) {
|
|
172
|
+
clearTimeout(existingTimer);
|
|
173
|
+
}
|
|
174
|
+
// Set new timer
|
|
175
|
+
const timer = setTimeout(() => {
|
|
176
|
+
this.emitWatchEvent(type, filepath);
|
|
177
|
+
this.debouncedHandlers.delete(key);
|
|
178
|
+
}, 100);
|
|
179
|
+
this.debouncedHandlers.set(key, timer);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Emit a watch event
|
|
183
|
+
*/
|
|
184
|
+
emitWatchEvent(type, filepath) {
|
|
185
|
+
const relativePath = path.relative(this.config.baseDir, filepath);
|
|
186
|
+
const name = path.basename(filepath, '.sql');
|
|
187
|
+
const event = {
|
|
188
|
+
type,
|
|
189
|
+
path: filepath,
|
|
190
|
+
relativePath,
|
|
191
|
+
name,
|
|
192
|
+
};
|
|
193
|
+
// Emit specific event types
|
|
194
|
+
switch (type) {
|
|
195
|
+
case 'added':
|
|
196
|
+
this.emit('template:added', event);
|
|
197
|
+
break;
|
|
198
|
+
case 'changed':
|
|
199
|
+
this.emit('template:changed', event);
|
|
200
|
+
break;
|
|
201
|
+
case 'removed':
|
|
202
|
+
this.emit('template:removed', event);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
// Also emit generic event
|
|
206
|
+
this.emit('template:event', event);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Clean up resources
|
|
210
|
+
*/
|
|
211
|
+
async dispose() {
|
|
212
|
+
await this.stopWatching();
|
|
213
|
+
this.removeAllListeners();
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get migration file path for a template
|
|
217
|
+
*/
|
|
218
|
+
getMigrationPath(templateName, timestamp) {
|
|
219
|
+
const migrationName = `${timestamp}_${templateName}.sql`;
|
|
220
|
+
return path.join(this.config.baseDir, this.config.migrationDir, migrationName);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* List all migration files
|
|
224
|
+
*/
|
|
225
|
+
async listMigrations() {
|
|
226
|
+
const migrationPath = path.join(this.config.baseDir, this.config.migrationDir, '*.sql');
|
|
227
|
+
const matches = await glob(migrationPath);
|
|
228
|
+
return matches.sort(); // Ensure chronological order
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Read a migration file
|
|
232
|
+
*/
|
|
233
|
+
async readMigration(migrationPath) {
|
|
234
|
+
return fs.readFile(migrationPath, 'utf-8');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=FileSystemService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSystemService.js","sourceRoot":"","sources":["../../src/services/FileSystemService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MigrationBuilder Service - Generates Supabase migration files from templates
|
|
3
|
+
* Pure service that takes template content and metadata and produces formatted migration files
|
|
4
|
+
*/
|
|
5
|
+
import type { BuildLog, CLIConfig } from '../types.js';
|
|
6
|
+
export interface TemplateMetadata {
|
|
7
|
+
name: string;
|
|
8
|
+
templatePath: string;
|
|
9
|
+
relativePath: string;
|
|
10
|
+
content: string;
|
|
11
|
+
hash: string;
|
|
12
|
+
lastBuildAt?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface MigrationOptions {
|
|
15
|
+
force?: boolean;
|
|
16
|
+
wrapInTransaction?: boolean;
|
|
17
|
+
bundleMode?: boolean;
|
|
18
|
+
templateName?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface MigrationResult {
|
|
21
|
+
fileName: string;
|
|
22
|
+
filePath: string;
|
|
23
|
+
content: string;
|
|
24
|
+
timestamp: string;
|
|
25
|
+
}
|
|
26
|
+
export interface BundleMigrationResult {
|
|
27
|
+
fileName: string;
|
|
28
|
+
filePath: string;
|
|
29
|
+
content: string;
|
|
30
|
+
timestamp: string;
|
|
31
|
+
includedTemplates: string[];
|
|
32
|
+
}
|
|
33
|
+
export interface MigrationBuilderConfig {
|
|
34
|
+
baseDir: string;
|
|
35
|
+
templateDir: string;
|
|
36
|
+
migrationDir: string;
|
|
37
|
+
migrationPrefix?: string;
|
|
38
|
+
banner?: string;
|
|
39
|
+
footer?: string;
|
|
40
|
+
wrapInTransaction?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare class MigrationBuilder {
|
|
43
|
+
private config;
|
|
44
|
+
constructor(config: MigrationBuilderConfig);
|
|
45
|
+
/**
|
|
46
|
+
* Generate a migration file from a single template
|
|
47
|
+
*/
|
|
48
|
+
generateMigration(template: TemplateMetadata, buildLog: BuildLog, options?: MigrationOptions): Promise<MigrationResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Generate a bundled migration file from multiple templates
|
|
51
|
+
*/
|
|
52
|
+
generateBundledMigration(templates: TemplateMetadata[], buildLog: BuildLog, options?: MigrationOptions): Promise<BundleMigrationResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Format migration content with headers, footers, and transaction wrapping
|
|
55
|
+
*/
|
|
56
|
+
private formatMigrationContent;
|
|
57
|
+
/**
|
|
58
|
+
* Create MigrationBuilder from CLI config
|
|
59
|
+
*/
|
|
60
|
+
static fromConfig(config: CLIConfig, baseDir: string): MigrationBuilder;
|
|
61
|
+
/**
|
|
62
|
+
* Generate migration file path for a template
|
|
63
|
+
*/
|
|
64
|
+
getMigrationPath(templateName: string, timestamp: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Generate absolute migration file path for a template
|
|
67
|
+
*/
|
|
68
|
+
getAbsoluteMigrationPath(templateName: string, timestamp: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Validate migration configuration
|
|
71
|
+
*/
|
|
72
|
+
validateConfig(): {
|
|
73
|
+
valid: boolean;
|
|
74
|
+
errors: string[];
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Write migration file to disk
|
|
78
|
+
*/
|
|
79
|
+
writeMigration(migrationResult: MigrationResult): Promise<string>;
|
|
80
|
+
/**
|
|
81
|
+
* Write bundled migration file to disk
|
|
82
|
+
*/
|
|
83
|
+
writeBundledMigration(migrationResult: BundleMigrationResult): Promise<string>;
|
|
84
|
+
/**
|
|
85
|
+
* Generate and write migration file in one operation
|
|
86
|
+
*/
|
|
87
|
+
generateAndWriteMigration(template: TemplateMetadata, buildLog: BuildLog, options?: MigrationOptions): Promise<{
|
|
88
|
+
result: MigrationResult;
|
|
89
|
+
filePath: string;
|
|
90
|
+
}>;
|
|
91
|
+
/**
|
|
92
|
+
* Generate and write bundled migration file in one operation
|
|
93
|
+
*/
|
|
94
|
+
generateAndWriteBundledMigration(templates: TemplateMetadata[], buildLog: BuildLog, options?: MigrationOptions): Promise<{
|
|
95
|
+
result: BundleMigrationResult;
|
|
96
|
+
filePath: string;
|
|
97
|
+
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Check if migration file already exists
|
|
100
|
+
*/
|
|
101
|
+
migrationExists(fileName: string): Promise<boolean>;
|
|
102
|
+
/**
|
|
103
|
+
* Get current configuration
|
|
104
|
+
*/
|
|
105
|
+
getConfig(): Readonly<MigrationBuilderConfig>;
|
|
106
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MigrationBuilder Service - Generates Supabase migration files from templates
|
|
3
|
+
* Pure service that takes template content and metadata and produces formatted migration files
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'node:fs/promises';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { getNextTimestamp } from '../utils/getNextTimestamp.js';
|
|
8
|
+
export class MigrationBuilder {
|
|
9
|
+
config;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = {
|
|
12
|
+
migrationPrefix: '',
|
|
13
|
+
banner: '',
|
|
14
|
+
footer: '',
|
|
15
|
+
wrapInTransaction: true,
|
|
16
|
+
...config,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generate a migration file from a single template
|
|
21
|
+
*/
|
|
22
|
+
async generateMigration(template, buildLog, options = {}) {
|
|
23
|
+
const timestamp = await getNextTimestamp(buildLog);
|
|
24
|
+
const prefix = this.config.migrationPrefix ? `${this.config.migrationPrefix}-` : '';
|
|
25
|
+
const fileName = `${timestamp}_${prefix}${template.name}.sql`;
|
|
26
|
+
const filePath = path.join(this.config.migrationDir, fileName);
|
|
27
|
+
const content = this.formatMigrationContent(template, {
|
|
28
|
+
isBundled: false,
|
|
29
|
+
...options,
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
fileName,
|
|
33
|
+
filePath,
|
|
34
|
+
content,
|
|
35
|
+
timestamp,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Generate a bundled migration file from multiple templates
|
|
40
|
+
*/
|
|
41
|
+
async generateBundledMigration(templates, buildLog, options = {}) {
|
|
42
|
+
const timestamp = await getNextTimestamp(buildLog);
|
|
43
|
+
const prefix = this.config.migrationPrefix ? `${this.config.migrationPrefix}-` : '';
|
|
44
|
+
const fileName = `${timestamp}_${prefix}bundle.sql`;
|
|
45
|
+
const filePath = path.join(this.config.migrationDir, fileName);
|
|
46
|
+
let content = '';
|
|
47
|
+
const includedTemplates = [];
|
|
48
|
+
for (const template of templates) {
|
|
49
|
+
const templateContent = this.formatMigrationContent(template, {
|
|
50
|
+
isBundled: true,
|
|
51
|
+
...options,
|
|
52
|
+
});
|
|
53
|
+
content += `${templateContent}\n\n`;
|
|
54
|
+
includedTemplates.push(template.name);
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
fileName,
|
|
58
|
+
filePath,
|
|
59
|
+
content: content.trim(),
|
|
60
|
+
timestamp,
|
|
61
|
+
includedTemplates,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Format migration content with headers, footers, and transaction wrapping
|
|
66
|
+
*/
|
|
67
|
+
formatMigrationContent(template, options = {}) {
|
|
68
|
+
const { isBundled = false, wrapInTransaction = this.config.wrapInTransaction } = options;
|
|
69
|
+
// Generate header
|
|
70
|
+
const headerPrefix = isBundled ? 'Template' : 'Generated with srtd from template';
|
|
71
|
+
const header = `-- ${headerPrefix}: ${this.config.templateDir}/${template.name}.sql\n`;
|
|
72
|
+
// Generate banner
|
|
73
|
+
const banner = this.config.banner ? `-- ${this.config.banner}\n` : '\n';
|
|
74
|
+
// Generate footer
|
|
75
|
+
const lastBuildInfo = template.lastBuildAt || 'Never';
|
|
76
|
+
const footerText = this.config.footer ? `${this.config.footer}\n` : '';
|
|
77
|
+
const footer = `${footerText}-- Last built: ${lastBuildInfo}\n-- Built with https://github.com/t1mmen/srtd\n`;
|
|
78
|
+
// Wrap content in transaction if needed
|
|
79
|
+
const safeContent = wrapInTransaction
|
|
80
|
+
? `BEGIN;\n\n${template.content}\n\nCOMMIT;`
|
|
81
|
+
: template.content;
|
|
82
|
+
// Assemble final content
|
|
83
|
+
return `${header}${banner}\n${safeContent}\n${footer}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create MigrationBuilder from CLI config
|
|
87
|
+
*/
|
|
88
|
+
static fromConfig(config, baseDir) {
|
|
89
|
+
return new MigrationBuilder({
|
|
90
|
+
baseDir,
|
|
91
|
+
templateDir: config.templateDir,
|
|
92
|
+
migrationDir: config.migrationDir,
|
|
93
|
+
migrationPrefix: config.migrationPrefix,
|
|
94
|
+
banner: config.banner,
|
|
95
|
+
footer: config.footer,
|
|
96
|
+
wrapInTransaction: config.wrapInTransaction,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Generate migration file path for a template
|
|
101
|
+
*/
|
|
102
|
+
getMigrationPath(templateName, timestamp) {
|
|
103
|
+
const prefix = this.config.migrationPrefix ? `${this.config.migrationPrefix}-` : '';
|
|
104
|
+
const fileName = `${timestamp}_${prefix}${templateName}.sql`;
|
|
105
|
+
return path.join(this.config.migrationDir, fileName);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Generate absolute migration file path for a template
|
|
109
|
+
*/
|
|
110
|
+
getAbsoluteMigrationPath(templateName, timestamp) {
|
|
111
|
+
const migrationPath = this.getMigrationPath(templateName, timestamp);
|
|
112
|
+
return path.resolve(this.config.baseDir, migrationPath);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Validate migration configuration
|
|
116
|
+
*/
|
|
117
|
+
validateConfig() {
|
|
118
|
+
const errors = [];
|
|
119
|
+
if (!this.config.baseDir) {
|
|
120
|
+
errors.push('baseDir is required');
|
|
121
|
+
}
|
|
122
|
+
if (!this.config.templateDir) {
|
|
123
|
+
errors.push('templateDir is required');
|
|
124
|
+
}
|
|
125
|
+
if (!this.config.migrationDir) {
|
|
126
|
+
errors.push('migrationDir is required');
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
valid: errors.length === 0,
|
|
130
|
+
errors,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Write migration file to disk
|
|
135
|
+
*/
|
|
136
|
+
async writeMigration(migrationResult) {
|
|
137
|
+
const fullPath = path.resolve(this.config.baseDir, migrationResult.filePath);
|
|
138
|
+
const directory = path.dirname(fullPath);
|
|
139
|
+
// Ensure migration directory exists
|
|
140
|
+
await fs.mkdir(directory, { recursive: true });
|
|
141
|
+
// Write migration file
|
|
142
|
+
await fs.writeFile(fullPath, migrationResult.content, 'utf-8');
|
|
143
|
+
return fullPath;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Write bundled migration file to disk
|
|
147
|
+
*/
|
|
148
|
+
async writeBundledMigration(migrationResult) {
|
|
149
|
+
const fullPath = path.resolve(this.config.baseDir, migrationResult.filePath);
|
|
150
|
+
const directory = path.dirname(fullPath);
|
|
151
|
+
// Ensure migration directory exists
|
|
152
|
+
await fs.mkdir(directory, { recursive: true });
|
|
153
|
+
// Write bundled migration file
|
|
154
|
+
await fs.writeFile(fullPath, migrationResult.content, 'utf-8');
|
|
155
|
+
return fullPath;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Generate and write migration file in one operation
|
|
159
|
+
*/
|
|
160
|
+
async generateAndWriteMigration(template, buildLog, options = {}) {
|
|
161
|
+
const result = await this.generateMigration(template, buildLog, options);
|
|
162
|
+
const filePath = await this.writeMigration(result);
|
|
163
|
+
return { result, filePath };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Generate and write bundled migration file in one operation
|
|
167
|
+
*/
|
|
168
|
+
async generateAndWriteBundledMigration(templates, buildLog, options = {}) {
|
|
169
|
+
const result = await this.generateBundledMigration(templates, buildLog, options);
|
|
170
|
+
const filePath = await this.writeBundledMigration(result);
|
|
171
|
+
return { result, filePath };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check if migration file already exists
|
|
175
|
+
*/
|
|
176
|
+
async migrationExists(fileName) {
|
|
177
|
+
const fullPath = path.resolve(this.config.baseDir, this.config.migrationDir, fileName);
|
|
178
|
+
try {
|
|
179
|
+
await fs.access(fullPath);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get current configuration
|
|
188
|
+
*/
|
|
189
|
+
getConfig() {
|
|
190
|
+
return { ...this.config };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=MigrationBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationBuilder.js","sourceRoot":"","sources":["../../src/services/MigrationBuilder.ts"],"names":[],"mappings":"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"}
|