@neupgroup/mapper 1.4.0 → 1.4.2

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.
@@ -61,3 +61,40 @@ export const ${tableName} = {
61
61
  else {
62
62
  console.log(`Schema file already exists: ${schemaFilePath}`);
63
63
  }
64
+ // Update migrations index
65
+ const indexFilePath = path.join(migrationDir, 'index.ts');
66
+ let migrations = [];
67
+ let completed = [];
68
+ let currentVersion = -1;
69
+ if (fs.existsSync(indexFilePath)) {
70
+ const content = fs.readFileSync(indexFilePath, 'utf-8');
71
+ const matchMigrations = content.match(/migrations = \[(.*?)\]/s);
72
+ if (matchMigrations) {
73
+ migrations = matchMigrations[1].split(',').map(s => s.trim().replace(/['"]/g, '')).filter(Boolean);
74
+ }
75
+ const matchCompleted = content.match(/completed = \[(.*?)\]/s);
76
+ if (matchCompleted) {
77
+ completed = matchCompleted[1].split(',').map(s => s.trim().replace(/['"]/g, '')).filter(Boolean);
78
+ }
79
+ const matchVersion = content.match(/currentVersion = (.*?);/);
80
+ if (matchVersion) {
81
+ currentVersion = parseInt(matchVersion[1]);
82
+ }
83
+ }
84
+ const migrationName = fileName.replace('.ts', '');
85
+ if (!migrations.includes(migrationName)) {
86
+ migrations.push(migrationName);
87
+ }
88
+ const indexContent = `
89
+ export const migrations = [
90
+ ${migrations.map(m => ` '${m}'`).join(',\n')}
91
+ ];
92
+
93
+ export const completed = [
94
+ ${completed.map(m => ` '${m}'`).join(',\n')}
95
+ ];
96
+
97
+ export const currentVersion = ${currentVersion};
98
+ `;
99
+ fs.writeFileSync(indexFilePath, indexContent.trim() + '\n');
100
+ console.log(`Updated migration index: ${indexFilePath}`);
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ const args = process.argv.slice(2);
5
+ const command = args[0] || 'up'; // 'up' or 'down'
6
+ const migrationDir = path.resolve(process.cwd(), 'src/migration');
7
+ const indexFilePath = path.join(migrationDir, 'index.ts');
8
+ if (!fs.existsSync(indexFilePath)) {
9
+ console.log('No migrations found.');
10
+ process.exit(0);
11
+ }
12
+ async function run() {
13
+ const content = fs.readFileSync(indexFilePath, 'utf-8');
14
+ const matchMigrations = content.match(/migrations = \[(.*?)\]/s);
15
+ const matchCompleted = content.match(/completed = \[(.*?)\]/s);
16
+ const matchVersion = content.match(/currentVersion = (.*?);/);
17
+ if (!matchMigrations) {
18
+ console.log('No migrations list found in index.ts');
19
+ return;
20
+ }
21
+ const migrations = matchMigrations[1].split(',').map(s => s.trim().replace(/['"]/g, '')).filter(Boolean);
22
+ let completed = matchCompleted ? matchCompleted[1].split(',').map(s => s.trim().replace(/['"]/g, '')).filter(Boolean) : [];
23
+ let currentVersion = matchVersion ? parseInt(matchVersion[1]) : -1;
24
+ if (command === 'up') {
25
+ const pending = migrations.filter(m => !completed.includes(m));
26
+ if (pending.length === 0) {
27
+ console.log('No pending migrations.');
28
+ return;
29
+ }
30
+ console.log(`Found ${pending.length} pending migrations.`);
31
+ for (const m of pending) {
32
+ console.log(`Running migration UP: ${m}...`);
33
+ const filePath = path.join(migrationDir, `${m}.ts`);
34
+ const absolutePath = path.resolve(filePath);
35
+ const mod = await import('file://' + absolutePath);
36
+ if (mod.up) {
37
+ await mod.up();
38
+ completed.push(m);
39
+ currentVersion = migrations.indexOf(m);
40
+ console.log(`Completed UP: ${m}`);
41
+ }
42
+ else {
43
+ console.error(`Migration ${m} does not have an up() function.`);
44
+ break;
45
+ }
46
+ }
47
+ }
48
+ else if (command === 'down') {
49
+ if (completed.length === 0) {
50
+ console.log('No migrations to roll back.');
51
+ return;
52
+ }
53
+ const lastMigrationName = completed[completed.length - 1];
54
+ console.log(`Rolling back migration: ${lastMigrationName}...`);
55
+ const filePath = path.join(migrationDir, `${lastMigrationName}.ts`);
56
+ const absolutePath = path.resolve(filePath);
57
+ const mod = await import('file://' + absolutePath);
58
+ if (mod.down) {
59
+ await mod.down();
60
+ completed.pop();
61
+ currentVersion = completed.length > 0 ? migrations.indexOf(completed[completed.length - 1]) : -1;
62
+ console.log(`Completed DOWN: ${lastMigrationName}`);
63
+ }
64
+ else {
65
+ console.error(`Migration ${lastMigrationName} does not have a down() function.`);
66
+ }
67
+ }
68
+ // Update index.ts
69
+ const indexContent = `
70
+ export const migrations = [
71
+ ${migrations.map(m => ` '${m}'`).join(',\n')}
72
+ ];
73
+
74
+ export const completed = [
75
+ ${completed.map(m => ` '${m}'`).join(',\n')}
76
+ ];
77
+
78
+ export const currentVersion = ${currentVersion};
79
+ `;
80
+ fs.writeFileSync(indexFilePath, indexContent.trim() + '\n');
81
+ console.log(`Migration runner finished. Current version: ${currentVersion}`);
82
+ }
83
+ run().catch(err => {
84
+ console.error('Migration failed:', err);
85
+ process.exit(1);
86
+ });
@@ -19,4 +19,10 @@ export declare class TableMigrator {
19
19
  private columns;
20
20
  constructor(name: string);
21
21
  addColumn(name: string): ColumnBuilder;
22
+ getColumns(): any[];
23
+ exec(): Promise<void>;
24
+ drop(): Promise<void>;
25
+ dropColumn(columnName: string): Promise<void>;
26
+ dropUnique(columnName: string): Promise<void>;
27
+ dropPrimaryKey(columnName: string): Promise<void>;
22
28
  }
package/dist/migrator.js CHANGED
@@ -62,4 +62,96 @@ export class TableMigrator {
62
62
  this.columns.push(col);
63
63
  return col;
64
64
  }
65
+ getColumns() {
66
+ return this.columns.map(c => c.getDefinition());
67
+ }
68
+ async exec() {
69
+ // This is where we trigger schema file update
70
+ const fs = await import('fs');
71
+ const path = await import('path');
72
+ const schemasDir = path.resolve(process.cwd(), 'src/schemas');
73
+ const schemaFilePath = path.join(schemasDir, `${this.name}.ts`);
74
+ const columns = this.getColumns();
75
+ let existingSchema = {
76
+ fields: [],
77
+ insertableFields: [],
78
+ updatableFields: [],
79
+ massUpdateable: false,
80
+ massDeletable: false,
81
+ usesConnection: 'default'
82
+ };
83
+ if (fs.existsSync(schemaFilePath)) {
84
+ // Very basic parser/updater.
85
+ // Real implementation would use AST, but for now we'll do simple string replacement or overwrite if it's the first time.
86
+ // For the sake of this demo, we will generate the fields array.
87
+ }
88
+ const fieldsContent = columns.map(col => {
89
+ return ` { name: '${col.name}', type: '${col.type}'${col.isPrimary ? ', isPrimary: true' : ''}${col.autoIncrement ? ', autoIncrement: true' : ''}${col.notNull ? ', notNull: true' : ''}${col.isUnique ? ', isUnique: true' : ''} }`;
90
+ }).join(',\n');
91
+ const schemaContent = `
92
+ export const ${this.name} = {
93
+ fields: [
94
+ ${fieldsContent}
95
+ ],
96
+ insertableFields: [${columns.filter(c => !c.autoIncrement).map(c => `'${c.name}'`).join(', ')}],
97
+ updatableFields: [${columns.filter(c => !c.autoIncrement && !c.isPrimary).map(c => `'${c.name}'`).join(', ')}],
98
+ massUpdateable: false,
99
+ massDeletable: false,
100
+ usesConnection: 'default'
101
+ };
102
+ `;
103
+ fs.writeFileSync(schemaFilePath, schemaContent.trim() + '\n');
104
+ console.log(`Updated schema: ${schemaFilePath}`);
105
+ }
106
+ async drop() {
107
+ const fs = await import('fs');
108
+ const path = await import('path');
109
+ const schemasDir = path.resolve(process.cwd(), 'src/schemas');
110
+ const schemaFilePath = path.join(schemasDir, `${this.name}.ts`);
111
+ if (fs.existsSync(schemaFilePath)) {
112
+ fs.unlinkSync(schemaFilePath);
113
+ console.log(`Deleted schema: ${schemaFilePath}`);
114
+ }
115
+ }
116
+ async dropColumn(columnName) {
117
+ const fs = await import('fs');
118
+ const path = await import('path');
119
+ const schemasDir = path.resolve(process.cwd(), 'src/schemas');
120
+ const schemaFilePath = path.join(schemasDir, `${this.name}.ts`);
121
+ if (fs.existsSync(schemaFilePath)) {
122
+ // Very simple implementation: filter out the line with the column
123
+ const content = fs.readFileSync(schemaFilePath, 'utf-8');
124
+ const lines = content.split('\n');
125
+ const filteredLines = lines.filter(line => !line.includes(`name: '${columnName}'`));
126
+ fs.writeFileSync(schemaFilePath, filteredLines.join('\n'));
127
+ console.log(`Dropped column ${columnName} from schema ${this.name}`);
128
+ }
129
+ }
130
+ async dropUnique(columnName) {
131
+ const fs = await import('fs');
132
+ const path = await import('path');
133
+ const schemasDir = path.resolve(process.cwd(), 'src/schemas');
134
+ const schemaFilePath = path.join(schemasDir, `${this.name}.ts`);
135
+ if (fs.existsSync(schemaFilePath)) {
136
+ let content = fs.readFileSync(schemaFilePath, 'utf-8');
137
+ // Remove ", isUnique: true" from the line containing the column
138
+ const regex = new RegExp(`({ name: '${columnName}', .*?), isUnique: true(.*})`);
139
+ content = content.replace(regex, '$1$2');
140
+ fs.writeFileSync(schemaFilePath, content);
141
+ console.log(`Dropped unique constraint from ${columnName} in schema ${this.name}`);
142
+ }
143
+ }
144
+ async dropPrimaryKey(columnName) {
145
+ const fs = await import('fs');
146
+ const path = await import('path');
147
+ const schemasDir = path.resolve(process.cwd(), 'src/schemas');
148
+ const schemaFilePath = path.join(schemasDir, `${this.name}.ts`);
149
+ if (fs.existsSync(schemaFilePath)) {
150
+ let content = fs.readFileSync(schemaFilePath, 'utf-8');
151
+ const regex = new RegExp(`({ name: '${columnName}', .*?), isPrimary: true(.*})`);
152
+ content = content.replace(regex, '$1$2');
153
+ fs.writeFileSync(schemaFilePath, content);
154
+ console.log(`Dropped primary key constraint from ${columnName} in schema ${this.name}`);
155
+ }
156
+ }
65
157
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neupgroup/mapper",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Neup.Mapper core library for schema and mapping utilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,7 +8,10 @@
8
8
  "types": "dist/index.d.ts",
9
9
  "bin": {
10
10
  "create-migration": "dist/cli/create-migration.js",
11
- "create-connection": "dist/cli/create-connection.js"
11
+ "create-connection": "dist/cli/create-connection.js",
12
+ "migrate": "dist/cli/migrate.js",
13
+ "migrate-up": "dist/cli/migrate.js",
14
+ "migrate-down": "dist/cli/migrate.js"
12
15
  },
13
16
  "files": [
14
17
  "dist"
@@ -17,7 +20,10 @@
17
20
  "scripts": {
18
21
  "build": "tsc -p ./tsconfig.json",
19
22
  "create-migration": "npx tsx src/cli/create-migration.ts",
20
- "create-connection": "npx tsx src/cli/create-connection.ts"
23
+ "create-connection": "npx tsx src/cli/create-connection.ts",
24
+ "migrate": "npx tsx src/cli/migrate.ts",
25
+ "migrate-up": "npx tsx src/cli/migrate.ts up",
26
+ "migrate-down": "npx tsx src/cli/migrate.ts down"
21
27
  },
22
28
  "publishConfig": {
23
29
  "access": "public"