diff --git a/database/migrations/005_remove_serbian_colors.sql b/database/migrations/005_remove_serbian_colors.sql new file mode 100644 index 0000000..0754995 --- /dev/null +++ b/database/migrations/005_remove_serbian_colors.sql @@ -0,0 +1,2 @@ +-- Migration to remove Serbian colors from boje table +DELETE FROM boje WHERE name IN ('Bela', 'Crna', 'Crvena', 'Plava', 'Zelena', 'Žuta', 'Narandžasta', 'Ljubičasta', 'Siva', 'Braon'); \ No newline at end of file diff --git a/database/schema.sql b/database/schema.sql index 0262a55..40e69d6 100644 --- a/database/schema.sql +++ b/database/schema.sql @@ -51,16 +51,4 @@ CREATE TRIGGER update_filaments_updated_at BEFORE UPDATE CREATE TRIGGER update_colors_updated_at BEFORE UPDATE ON colors FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); --- Insert default colors from legacy data -INSERT INTO colors (name, hex) VALUES - ('Crna', '#000000'), - ('Bela', '#FFFFFF'), - ('Plava', '#0000FF'), - ('Crvena', '#FF0000'), - ('Zelena', '#00FF00'), - ('Žuta', '#FFFF00'), - ('Narandžasta', '#FFA500'), - ('Ljubičasta', '#800080'), - ('Siva', '#808080'), - ('Braon', '#A52A2A') -ON CONFLICT (name) DO NOTHING; \ No newline at end of file +-- Default colors are now inserted by Bambu Lab colors migration \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 18c5faf..1b882cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "bcryptjs": "^3.0.2", "cheerio": "^1.1.0", "next": "^15.3.4", + "pg": "^8.16.2", "react": "^19.1.0", "react-dom": "^19.1.0" }, @@ -8211,6 +8212,95 @@ "node": ">=8" } }, + "node_modules/pg": { + "version": "8.16.2", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.2.tgz", + "integrity": "sha512-OtLWF0mKLmpxelOt9BqVq83QV6bTfsS0XLegIeAKqKjurRnRKie1Dc1iL89MugmSLhftxw6NNCyZhm1yQFLMEQ==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.9.1", + "pg-pool": "^3.10.1", + "pg-protocol": "^1.10.2", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.2.6" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.6.tgz", + "integrity": "sha512-uxmJAnmIgmYgnSFzgOf2cqGQBzwnRYcrEgXuFjJNEkpedEIPBSEzxY7ph4uA9k1mI+l/GR0HjPNS6FKNZe8SBQ==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", + "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz", + "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.2.tgz", + "integrity": "sha512-Ci7jy8PbaWxfsck2dwZdERcDG2A0MG8JoQILs+uZNjABFuBuItAZCWUNz8sXRDMoui24rJw7WlXqgpMdBSN/vQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -8469,6 +8559,45 @@ "dev": true, "license": "MIT" }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8978,6 +9107,15 @@ "source-map": "^0.6.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -10446,6 +10584,15 @@ "dev": true, "license": "MIT" }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 2bfb6cc..4b38c4a 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "bcryptjs": "^3.0.2", "cheerio": "^1.1.0", "next": "^15.3.4", + "pg": "^8.16.2", "react": "^19.1.0", "react-dom": "^19.1.0" }, diff --git a/scripts/run-migration.js b/scripts/run-migration.js new file mode 100644 index 0000000..3a30239 --- /dev/null +++ b/scripts/run-migration.js @@ -0,0 +1,57 @@ +const { Pool } = require('pg'); +const fs = require('fs'); +const path = require('path'); + +// Parse connection string from environment or command line +const connectionString = process.env.DATABASE_URL || process.argv[2]; + +if (!connectionString) { + console.error('Please provide DATABASE_URL as environment variable or command line argument'); + console.error('Example: node run-migration.js "postgresql://user:pass@host:port/db"'); + process.exit(1); +} + +const pool = new Pool({ + connectionString, + ssl: { + rejectUnauthorized: false // For AWS RDS + } +}); + +async function runMigration() { + try { + // Read the migration file + const migrationPath = path.join(__dirname, '../database/migrations/004_remove_brand_column.sql'); + const migrationSQL = fs.readFileSync(migrationPath, 'utf8'); + + console.log('Running migration: 004_remove_brand_column.sql'); + console.log('SQL:', migrationSQL); + + // Execute the migration + await pool.query(migrationSQL); + + console.log('✅ Migration completed successfully!'); + + // Verify the column was removed + const result = await pool.query(` + SELECT column_name + FROM information_schema.columns + WHERE table_name = 'filaments' + AND column_name = 'brand' + `); + + if (result.rows.length === 0) { + console.log('✅ Verified: brand column has been removed'); + } else { + console.log('⚠️ Warning: brand column still exists'); + } + + } catch (error) { + console.error('❌ Migration failed:', error.message); + process.exit(1); + } finally { + await pool.end(); + } +} + +runMigration(); \ No newline at end of file diff --git a/scripts/run-specific-migration.js b/scripts/run-specific-migration.js new file mode 100644 index 0000000..7b33bdc --- /dev/null +++ b/scripts/run-specific-migration.js @@ -0,0 +1,37 @@ +const { Pool } = require('pg'); + +// Parse connection string from environment or command line +const connectionString = process.env.DATABASE_URL || process.argv[2]; +const migrationSQL = process.argv[3]; + +if (!connectionString || !migrationSQL) { + console.error('Usage: node run-specific-migration.js "postgresql://..." "SQL"'); + process.exit(1); +} + +const pool = new Pool({ + connectionString, + ssl: { + rejectUnauthorized: false // For AWS RDS + } +}); + +async function runMigration() { + try { + console.log('Running migration SQL:', migrationSQL); + + // Execute the migration + const result = await pool.query(migrationSQL); + + console.log('✅ Migration completed successfully!'); + console.log('Rows affected:', result.rowCount); + + } catch (error) { + console.error('❌ Migration failed:', error.message); + process.exit(1); + } finally { + await pool.end(); + } +} + +runMigration(); \ No newline at end of file