procbay-schema 1.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/LICENSE +21 -0
- package/README.md +189 -0
- package/package.json +77 -0
- package/prisma/.env +13 -0
- package/prisma/migrations/20250116142512_init_user_table/migration.sql +38 -0
- package/prisma/migrations/20250116142709_init_role_table/migration.sql +20 -0
- package/prisma/migrations/20250116143847_init_user_role_table/migration.sql +20 -0
- package/prisma/migrations/20250116144035_init_permission_table/migration.sql +21 -0
- package/prisma/migrations/20250116144140_init_role_permission_table/migration.sql +21 -0
- package/prisma/migrations/20250116144233_init_department_table/migration.sql +20 -0
- package/prisma/migrations/20250116144345_init_user_department_table/migration.sql +20 -0
- package/prisma/migrations/20250116152941_init_serial_number_table/migration.sql +17 -0
- package/prisma/migrations/20250116153048_init_category_table/migration.sql +22 -0
- package/prisma/migrations/20250116153415_init_attributes_table/migration.sql +28 -0
- package/prisma/migrations/20250116153628_init_attribute_values_table/migration.sql +27 -0
- package/prisma/migrations/20250116153900_init_purchase_intake_table/migration.sql +32 -0
- package/prisma/migrations/20250116154038_init_purchase_intake_item_table/migration.sql +15 -0
- package/prisma/migrations/20250120090355_added_reset_token_column_in_user_table/migration.sql +10 -0
- package/prisma/migrations/20250120100616_init_item_table/migration.sql +42 -0
- package/prisma/migrations/20250120123720_init_vendor_table/migration.sql +39 -0
- package/prisma/migrations/20250120124526_init_vendor_categories_table/migration.sql +20 -0
- package/prisma/migrations/20250122114935_added_email_template_and_smtp_config_table/migration.sql +41 -0
- package/prisma/migrations/20250123095637_chnages_in_vendr_table/migration.sql +3 -0
- package/prisma/migrations/20250123103705_added_delated_filed_in_email_template_table/migration.sql +4 -0
- package/prisma/migrations/20250123103810_added_delated_filed_in_smtp_config_table/migration.sql +13 -0
- package/prisma/migrations/20250127123900_create_approval_heirarchy_table/migration.sql +72 -0
- package/prisma/migrations/20250128054523_make_optional_role_and_user_in_approval_hierachy/migration.sql +3 -0
- package/prisma/migrations/20250129084223_item_table_chnages/migration.sql +151 -0
- package/prisma/migrations/20250130115331_chnages_in_item_table/migration.sql +9 -0
- package/prisma/migrations/20250131054132_added_approval_journey_table/migration.sql +22 -0
- package/prisma/migrations/20250131064653_added_default_for_product_id_in_item_table/migration.sql +2 -0
- package/prisma/migrations/20250204101253_chnages_in_approval_table/migration.sql +39 -0
- package/prisma/migrations/20250206091422_added_item_document_table/migration.sql +17 -0
- package/prisma/migrations/20250207113110_added_new_column_media/migration.sql +9 -0
- package/prisma/migrations/20250207125224_added_chnages_in_pr_table/migration.sql +12 -0
- package/prisma/migrations/20250212092048_vendor_contact_table/migration.sql +30 -0
- package/prisma/migrations/20250212133620_added_tamplate_master_table/migration.sql +43 -0
- package/prisma/migrations/20250213111908_created_faq_catgory_and_faq_table/migration.sql +58 -0
- package/prisma/migrations/20250214065142_chnages_in_uom_table/migration.sql +50 -0
- package/prisma/migrations/20250217061122_corrected_email_teamplate_table/migration.sql +11 -0
- package/prisma/migrations/20250218073530_init_events/migration.sql +120 -0
- package/prisma/migrations/20250218092119_corrected_table_name/migration.sql +37 -0
- package/prisma/migrations/20250218120935_chnages_in_event_table/migration.sql +5 -0
- package/prisma/migrations/20250219083326_added_new_table_for_event_startegy/migration.sql +60 -0
- package/prisma/migrations/20250219083416_added_cms_table/migration.sql +29 -0
- package/prisma/migrations/20250219092918_alter_event_table/migration.sql +5 -0
- package/prisma/migrations/20250219093046_alter_event_to_draft/migration.sql +2 -0
- package/prisma/migrations/20250220080337_altered_event_table/migration.sql +9 -0
- package/prisma/migrations/20250221105922_added_unique_to_email_in_user_table/migration.sql +8 -0
- package/prisma/migrations/20250225063838_created_vendor_kyc_table/migration.sql +23 -0
- package/prisma/migrations/20250227060646_template_field_types_added_enum/migration.sql +14 -0
- package/prisma/migrations/20250227110306_updated_event_items_and_event_vendor_table/migration.sql +7 -0
- package/prisma/migrations/20250228060440_added_country_code_in_vendor_contact_person/migration.sql +2 -0
- package/prisma/migrations/20250228095319_init_currencies_table/migration.sql +23 -0
- package/prisma/migrations/20250303082614_added_support_ticket_table/migration.sql +89 -0
- package/prisma/migrations/20250304050248_alter_support_ticket_relations/migration.sql +35 -0
- package/prisma/migrations/20250304050613_alter_support_ticket_realtions/migration.sql +36 -0
- package/prisma/migrations/20250304061954_init_support_category_table/migration.sql +261 -0
- package/prisma/migrations/20250304092346_alter_event_vendor_table/migration.sql +2 -0
- package/prisma/migrations/20250305065430_alter_vendor_kyc_table/migration.sql +2 -0
- package/prisma/migrations/20250305111735_alter_vendor_and_user_table/migration.sql +5 -0
- package/prisma/migrations/20250307033751_alter_token_version_in_user_and_vendor_token/migration.sql +5 -0
- package/prisma/migrations/20250307034907_alter_user_and_vendor_table/migration.sql +14 -0
- package/prisma/migrations/20250307064359_chnages_in_approval_herarcy_table/migration.sql +2 -0
- package/prisma/migrations/20250307105352_alter_itme_and_vendorkyc_table/migration.sql +21 -0
- package/prisma/migrations/20250310103914_init_vendor_status_table/migration.sql +21 -0
- package/prisma/migrations/20250310105209_alter_vendor_status_table/migration.sql +18 -0
- package/prisma/migrations/20250310105413_init_vendor_kyc_status_table/migration.sql +23 -0
- package/prisma/migrations/20250311090552_alter_vendor_kyc_status_table/migration.sql +2 -0
- package/prisma/migrations/20250312055258_alter_status_column_in_event_vendors/migration.sql +12 -0
- package/prisma/migrations/20250312072145_init_vendor_event_watchlist_table/migration.sql +26 -0
- package/prisma/migrations/20250312083842_alter_vendor_event_watchlisst_table/migration.sql +41 -0
- package/prisma/migrations/20250312134730_added_chnages_in_kyc_table/migration.sql +19 -0
- package/prisma/migrations/20250317040841_init_admin_and_vendor_tables/migration.sql +38 -0
- package/prisma/migrations/20250317044110_alter_event_vendor_table/migration.sql +2 -0
- package/prisma/migrations/20250317071807_alter_rejected_reason_in_approval_journey_and_purchase_intak_table/migration.sql +5 -0
- package/prisma/migrations/20250318085504_init_customer_notification_table/migration.sql +31 -0
- package/prisma/migrations/20250318085856_alter_purchase_intake_table/migration.sql +18 -0
- package/prisma/migrations/20250319085159_alter_purchase_intake_table/migration.sql +12 -0
- package/prisma/migrations/20250320093356_init_bid_and_bidlog_table/migration.sql +75 -0
- package/prisma/migrations/20250320095501_alter_email_template_table/migration.sql +2 -0
- package/prisma/migrations/20250321053926_alter_approval_journey_table/migration.sql +2 -0
- package/prisma/migrations/20250324040851_alter_bidlog_table/migration.sql +2 -0
- package/prisma/migrations/20250324091328_init_form_master_and_dynamic_form_table/migration.sql +53 -0
- package/prisma/migrations/20250324103742_alter_bidlog_table/migration.sql +5 -0
- package/prisma/migrations/20250325052714_alter_form_master_table/migration.sql +27 -0
- package/prisma/migrations/20250327011625_init_module_and_tenant_configuration_table/migration.sql +39 -0
- package/prisma/migrations/20250403054008_alter_purchase_intake_table/migration.sql +5 -0
- package/prisma/migrations/20250404115613_init_approval_level_user/migration.sql +98 -0
- package/prisma/migrations/20250410060521_alter_approval_journey_enums/migration.sql +12 -0
- package/prisma/migrations/20250410110823_alter_purchase_intake/migration.sql +2 -0
- package/prisma/migrations/20250411062955_alter_template_field_table/migration.sql +2 -0
- package/prisma/migrations/20250414065640_alter_template/migration.sql +2 -0
- package/prisma/migrations/20250414111856_alter_event_vendors/migration.sql +2 -0
- package/prisma/migrations/20250414125356_alter_event_vendor/migration.sql +9 -0
- package/prisma/migrations/20250415063558_alter_alert_type_enum/migration.sql +2 -0
- package/prisma/migrations/20250416062508_alter_purchase_intake_table/migration.sql +15 -0
- package/prisma/migrations/20250417090325_alter_purchase_intake_table_updated_enum/migration.sql +13 -0
- package/prisma/migrations/20250417111024_alter_purchase_intake_and_purchase_intake_item/migration.sql +16 -0
- package/prisma/migrations/20250421061732_init_quotation_and_quotation_log_tables/migration.sql +96 -0
- package/prisma/migrations/20250421112331_alter_item_table_added_unique_to_slug/migration.sql +8 -0
- package/prisma/migrations/20250422060655_init_user_activity_table/migration.sql +17 -0
- package/prisma/migrations/20250423053027_/migration.sql +9 -0
- package/prisma/migrations/20250423103233_alter_user_login_activity_table/migration.sql +5 -0
- package/prisma/migrations/20250423111141_init_location_tables/migration.sql +141 -0
- package/prisma/migrations/20250424120106_alter_event_table_added_user_relation/migration.sql +2 -0
- package/prisma/migrations/20250424141637_alter_states_table/migration.sql +11 -0
- package/prisma/migrations/20250425105131_alter_user_login_activity_table/migration.sql +9 -0
- package/prisma/migrations/20250428092626_alter_location_tables/migration.sql +34 -0
- package/prisma/migrations/20250428114301_alter_location_table/migration.sql +14 -0
- package/prisma/migrations/20250429103436_alter_event_vendor_table/migration.sql +14 -0
- package/prisma/migrations/20250429135621_alter_event_vendor_table/migration.sql +5 -0
- package/prisma/migrations/20250430094809_alter_form_master_table_added_user_relation/migration.sql +2 -0
- package/prisma/migrations/20250430103440_alter_event_table/migration.sql +3 -0
- package/prisma/migrations/20250501125411_alter_strategies_table/migration.sql +2 -0
- package/prisma/migrations/20250502065554_init_location_table/migration.sql +41 -0
- package/prisma/migrations/20250505104038_alter_bid_quotation_and_dynamic_form/migration.sql +22 -0
- package/prisma/migrations/20250505105253_alter_quotation/migration.sql +5 -0
- package/prisma/migrations/20250505124851_alter_alert_enum/migration.sql +56 -0
- package/prisma/migrations/20250505133250_init_sub_module_table/migration.sql +17 -0
- package/prisma/migrations/20250506054325_alter_event_vendor_bid_status/migration.sql +14 -0
- package/prisma/migrations/20250506102135_init_counter_offer_table/migration.sql +38 -0
- package/prisma/migrations/20250506103355_alter_bid_and_quotaion_table/migration.sql +5 -0
- package/prisma/migrations/20250506110309_alter_tenant_configuration_table/migration.sql +3 -0
- package/prisma/migrations/20250506123527_alter_vendor_kyu_infor_verification_status/migration.sql +2 -0
- package/prisma/migrations/20250507055536_alter_dynamic_form_table/migration.sql +2 -0
- package/prisma/migrations/20250507070518_alter_bid_log_and_quotation_log/migration.sql +15 -0
- package/prisma/migrations/20250507130834_alter_bid_status/migration.sql +10 -0
- package/prisma/migrations/20250508065503_alter_purchase_intake_item_table/migration.sql +16 -0
- package/prisma/migrations/20250508130119_alter_purchase_intake_item/migration.sql +13 -0
- package/prisma/migrations/20250512082244_altered_template_table_to_add_currency_id/migration.sql +12 -0
- package/prisma/migrations/20250512100817_alter_approval_journey_table/migration.sql +3 -0
- package/prisma/migrations/20250513083700_alter_item_table/migration.sql +2 -0
- package/prisma/migrations/20250514100915_alter_event_table_added_template_realtion/migration.sql +2 -0
- package/prisma/migrations/20250514103503_alter_vendor_table_added_is_kyc_approved_column/migration.sql +2 -0
- package/prisma/migrations/20250520131556_init_purchase_order_table/migration.sql +52 -0
- package/prisma/migrations/20250521113946_alter_purchase_order_status_enum/migration.sql +16 -0
- package/prisma/migrations/20250522083917_alter_event_vendor_bid_status_enum/migration.sql +17 -0
- package/prisma/migrations/20250522131610_updated_vendor_table/migration.sql +16 -0
- package/prisma/migrations/20250523051058_alter_vendor_kyc_verificaiton_status_enum/migration.sql +2 -0
- package/prisma/migrations/20250526072120_alter_vendor_table/migration.sql +16 -0
- package/prisma/migrations/20250527055351_init_purchase_order_activity_log/migration.sql +41 -0
- package/prisma/migrations/20250528060657_alter_item_tale/migration.sql +14 -0
- package/prisma/migrations/20250528061946_alter_event_item_table/migration.sql +5 -0
- package/prisma/migrations/20250528081337_alter_item_table/migration.sql +2 -0
- package/prisma/migrations/20250528081524_removed_item_id_from_item_table/migration.sql +11 -0
- package/prisma/migrations/20250528081843_alter_item_table/migration.sql +2 -0
- package/prisma/migrations/20250528094057_alter_alert_type_enum/migration.sql +11 -0
- package/prisma/migrations/20250529053721_alter_added_quantity_in_purchase_order/migration.sql +2 -0
- package/prisma/migrations/20250602055114_alter_approval_journey_parent_id_to_string/migration.sql +2 -0
- package/prisma/migrations/20250602055748_alter_event_configuration_added_rule_slug/migration.sql +2 -0
- package/prisma/migrations/20250602111042_init_user_vendor_socket_token_table/migration.sql +17 -0
- package/prisma/migrations/20250602125833_alter_bidlog_and_quoatationlog_tableto_add_json_field/migration.sql +5 -0
- package/prisma/migrations/20250603063501_alter_bid_and_quoatation_table/migration.sql +29 -0
- package/prisma/migrations/20250606015045_alter_quotation_log_table/migration.sql +2 -0
- package/prisma/migrations/20250606020918_alter_quotation_table/migration.sql +2 -0
- package/prisma/migrations/20250606022901_alter_quotation_log_table/migration.sql +3 -0
- package/prisma/migrations/20250606054914_init_event_activity_logs_table/migration.sql +35 -0
- package/prisma/migrations/20250606100634_alter_added_counter_offer_status/migration.sql +5 -0
- package/prisma/migrations/20250606100908_alter_counter_offer_table/migration.sql +2 -0
- package/prisma/migrations/20250610055710_alter_enum/migration.sql +16 -0
- package/prisma/migrations/20250610060558_alter_event_and_event_vendor_db/migration.sql +14 -0
- package/prisma/migrations/20250610091013_alter_purchase_intak_item_table/migration.sql +4 -0
- package/prisma/migrations/20250610100156_alter_purchase_intake_item_table/migration.sql +19 -0
- package/prisma/migrations/20250610125706_alter_event_table/migration.sql +6 -0
- package/prisma/migrations/20250610133613_added_timestamp/migration.sql +319 -0
- package/prisma/migrations/20250611090439_init_contact_us_table/migration.sql +23 -0
- package/prisma/migrations/20250611121005_alter_event_vendor_table/migration.sql +10 -0
- package/prisma/migrations/20250612064335_alter_tenant_configuration/migration.sql +3 -0
- package/prisma/migrations/20250612094643_alter_event_vendor_bid_status_enum/migration.sql +2 -0
- package/prisma/migrations/20250618074558_alter_updated_bid_status_and_quotation_status/migration.sql +21 -0
- package/prisma/migrations/20250618122242_alter_added_event_phase_closed/migration.sql +2 -0
- package/prisma/migrations/20250620054518_alter_event_phase/migration.sql +2 -0
- package/prisma/migrations/20250620062723_alter_event_phase/migration.sql +2 -0
- package/prisma/migrations/20250620063056_alter_event_phase/migration.sql +2 -0
- package/prisma/migrations/20250620100507_alter_event_phase/migration.sql +2 -0
- package/prisma/migrations/20250627104958_alter_counter_offer_status/migration.sql +2 -0
- package/prisma/migrations/20250702095923_alter_item_table/migration.sql +74 -0
- package/prisma/migrations/20250702120134_/migration.sql +14 -0
- package/prisma/migrations/20250702150717_alter_attribute_table/migration.sql +9 -0
- package/prisma/migrations/20250703090321_alter_item_table/migration.sql +2 -0
- package/prisma/migrations/20250707054625_alter_purchase_order_table/migration.sql +15 -0
- package/prisma/migrations/20250707111354_alter_purchase_order_table_and_init_purchase_order_item_table/migration.sql +39 -0
- package/prisma/migrations/20250707111522_alter_purchase_order_item_table/migration.sql +17 -0
- package/prisma/migrations/20250710054113_alter_bid_and_quotation_status/migration.sql +31 -0
- package/prisma/migrations/20250710070813_alter_event_status/migration.sql +2 -0
- package/prisma/migrations/20250710082332_alter_bid_and_quotations_table/migration.sql +36 -0
- package/prisma/migrations/20250714102325_init_upload_log_table/migration.sql +27 -0
- package/prisma/migrations/20250716061012_alter_event_activity_logs_to_activity_logs/migration.sql +48 -0
- package/prisma/migrations/20250716071839_init_chat_thread_chat_message_and_ai_models/migration.sql +56 -0
- package/prisma/migrations/20250716135548_alter_admin_alerts_enum/migration.sql +2 -0
- package/prisma/migrations/20250717100515_init_user_event_configuration/migration.sql +21 -0
- package/prisma/migrations/20250717101037_alter_user_event_configuration_table/migration.sql +19 -0
- package/prisma/migrations/20250718071630_alter_added_module_in_upload_logs_table/migration.sql +5 -0
- package/prisma/migrations/20250718071732_alter_module_enum/migration.sql +15 -0
- package/prisma/migrations/20250721054851_init_export_log_table/migration.sql +34 -0
- package/prisma/migrations/20250722054549_init_fiscal_year_table/migration.sql +22 -0
- package/prisma/migrations/20250722072051_alter_fiscal_year_table_added_uuid/migration.sql +14 -0
- package/prisma/migrations/20250722095259_alter_fiscal_table/migration.sql +9 -0
- package/prisma/migrations/20250723071050_alter_department_table/migration.sql +14 -0
- package/prisma/migrations/20250724071201_alter_export_upload_log_enum/migration.sql +8 -0
- package/prisma/migrations/20250725094759_new_migrate/migration.sql +2 -0
- package/prisma/migrations/20250725095012_alter_migration/migration.sql +2 -0
- package/prisma/migrations/20250728072402_init_budget_management_tables/migration.sql +80 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +2609 -0
- package/prisma/seeders/approval-hierarchy.seed.js +340 -0
- package/prisma/seeders/attribute-value.seed.js +64 -0
- package/prisma/seeders/attribute.seed.js +61 -0
- package/prisma/seeders/category.seed.js +133 -0
- package/prisma/seeders/city.seed.js +147 -0
- package/prisma/seeders/country.seed.js +282 -0
- package/prisma/seeders/currency.seed.js +41 -0
- package/prisma/seeders/customer-notification.seed.js +83 -0
- package/prisma/seeders/department.seed.js +38 -0
- package/prisma/seeders/docs/CORE_SEEDER_OPTIMIZATIONS.md +270 -0
- package/prisma/seeders/docs/GEOGRAPHIC_PERFORMANCE_OPTIMIZATIONS.md +175 -0
- package/prisma/seeders/dynamic-form.seed.js +135 -0
- package/prisma/seeders/email-template.seed.js +68 -0
- package/prisma/seeders/faq-category.seed.js +56 -0
- package/prisma/seeders/faq.seed.js +61 -0
- package/prisma/seeders/form-master.seed.js +55 -0
- package/prisma/seeders/item.seed.js +133 -0
- package/prisma/seeders/permission.seed.js +102 -0
- package/prisma/seeders/region.seed.js +78 -0
- package/prisma/seeders/role-permission.seed.js +70 -0
- package/prisma/seeders/role.seed.js +38 -0
- package/prisma/seeders/seed.js +553 -0
- package/prisma/seeders/serial-number-config.seed.js +58 -0
- package/prisma/seeders/smtp-config.seed.js +61 -0
- package/prisma/seeders/state.seed.js +170 -0
- package/prisma/seeders/strategies.seed.js +54 -0
- package/prisma/seeders/subregion.seed.js +88 -0
- package/prisma/seeders/support-category.seed.js +56 -0
- package/prisma/seeders/template.seed.js +87 -0
- package/prisma/seeders/test-core-seeders.js +276 -0
- package/prisma/seeders/user-department.seed.js +66 -0
- package/prisma/seeders/user-event-configuration.seed.js +47 -0
- package/prisma/seeders/user-role.seed.js +74 -0
- package/prisma/seeders/user.seed.js +114 -0
- package/prisma/seeders/utils/bulk-seeder.js +300 -0
- package/prisma/seeders/utils/config.js +103 -0
- package/prisma/seeders/utils/connection-manager.js +380 -0
- package/prisma/seeders/utils/content-seeder.js +472 -0
- package/prisma/seeders/utils/core-seeder.js +330 -0
- package/prisma/seeders/utils/json-loader.js +69 -0
- package/prisma/seeders/utils/performance-config.js +341 -0
- package/prisma/seeders/utils/performance-helpers.js +206 -0
- package/prisma/seeders/utils/progress-tracker.js +364 -0
- package/prisma/seeders/utils/seeder-config-mapper.js +316 -0
- package/scripts/seed-databases.js +873 -0
- package/scripts/sync-schemas.js +865 -0
- package/scripts/truncate-tables.js +1048 -0
- package/src/prisma/client.d.ts +1 -0
- package/src/prisma/client.js +4 -0
- package/src/prisma/default.d.ts +1 -0
- package/src/prisma/default.js +4 -0
- package/src/prisma/edge.d.ts +1 -0
- package/src/prisma/edge.js +2084 -0
- package/src/prisma/index-browser.js +2043 -0
- package/src/prisma/index.d.ts +202051 -0
- package/src/prisma/index.js +2113 -0
- package/src/prisma/libquery_engine-darwin.dylib.node +0 -0
- package/src/prisma/libquery_engine-darwin.dylib.node.tmp24628 +0 -0
- package/src/prisma/libquery_engine-darwin.dylib.node.tmp29464 +0 -0
- package/src/prisma/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
- package/src/prisma/package.json +140 -0
- package/src/prisma/query_engine-windows.dll.node +0 -0
- package/src/prisma/query_engine-windows.dll.node.tmp4144 +0 -0
- package/src/prisma/runtime/edge-esm.js +34 -0
- package/src/prisma/runtime/edge.js +34 -0
- package/src/prisma/runtime/index-browser.d.ts +370 -0
- package/src/prisma/runtime/index-browser.js +16 -0
- package/src/prisma/runtime/library.d.ts +3647 -0
- package/src/prisma/runtime/library.js +146 -0
- package/src/prisma/runtime/react-native.js +83 -0
- package/src/prisma/runtime/wasm.js +35 -0
- package/src/prisma/schema.prisma +2609 -0
- package/src/prisma/wasm.d.ts +1 -0
- package/src/prisma/wasm.js +2043 -0
|
@@ -0,0 +1,865 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
import colors from "colors"; // Using colors library instead of chalk
|
|
9
|
+
import { connectionManager } from "../prisma/seeders/utils/connection-manager.js";
|
|
10
|
+
import { TENANT_EMAILS } from "../prisma/seeders/utils/config.js";
|
|
11
|
+
|
|
12
|
+
// Get current directory
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// Process command line arguments
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
let targetDatabase = null;
|
|
19
|
+
|
|
20
|
+
// Parse for --db flag
|
|
21
|
+
for (let i = 0; i < args.length; i++) {
|
|
22
|
+
if (args[i] === "--db" && i + 1 < args.length) {
|
|
23
|
+
targetDatabase = args[i + 1];
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Configuration
|
|
29
|
+
const CONFIG = {
|
|
30
|
+
envPath: path.join("prisma", ".env"),
|
|
31
|
+
prismaDir: path.join("src", "prisma"),
|
|
32
|
+
schemaPath: path.join("prisma", "schema.prisma"),
|
|
33
|
+
constantPath: path.join("prisma", "seeders", "utils", "config.js"),
|
|
34
|
+
defaultDbName: "DEFAULT",
|
|
35
|
+
retryAttempts: 3,
|
|
36
|
+
retryDelay: 2000,
|
|
37
|
+
successDelay: 1000,
|
|
38
|
+
targetDatabase: targetDatabase,
|
|
39
|
+
logLevel: process.env.LOG_LEVEL || "info", // debug, info, warn, error
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Load environment variables from prisma/.env
|
|
43
|
+
dotenv.config({ path: CONFIG.envPath });
|
|
44
|
+
|
|
45
|
+
// Configure colors theme
|
|
46
|
+
colors.setTheme({
|
|
47
|
+
debug: "grey",
|
|
48
|
+
info: "white",
|
|
49
|
+
success: "green",
|
|
50
|
+
warn: "yellow",
|
|
51
|
+
error: "red",
|
|
52
|
+
highlight: "cyan",
|
|
53
|
+
bold: "bold",
|
|
54
|
+
header: ["bold", "cyan"],
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Logger implementation
|
|
58
|
+
class Logger {
|
|
59
|
+
static LEVELS = {
|
|
60
|
+
debug: 0,
|
|
61
|
+
info: 1,
|
|
62
|
+
warn: 2,
|
|
63
|
+
error: 3,
|
|
64
|
+
silent: 4,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
static #currentLevel = Logger.LEVELS[CONFIG.logLevel] || Logger.LEVELS.info;
|
|
68
|
+
static #startTime = Date.now();
|
|
69
|
+
|
|
70
|
+
static #formatTime() {
|
|
71
|
+
const elapsed = ((Date.now() - Logger.#startTime) / 1000).toFixed(2);
|
|
72
|
+
return `[${elapsed}s]`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static debug(message, ...args) {
|
|
76
|
+
if (Logger.#currentLevel <= Logger.LEVELS.debug) {
|
|
77
|
+
console.debug(
|
|
78
|
+
colors.debug(`${Logger.#formatTime()} 🔍 DEBUG: ${message}`),
|
|
79
|
+
...args
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static info(message, ...args) {
|
|
85
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
86
|
+
console.log(
|
|
87
|
+
colors.info(`${Logger.#formatTime()} ℹ️ ${message}`),
|
|
88
|
+
...args
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static success(message, ...args) {
|
|
94
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
95
|
+
console.log(
|
|
96
|
+
colors.success(`${Logger.#formatTime()} ✅ ${message}`),
|
|
97
|
+
...args
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static warn(message, ...args) {
|
|
103
|
+
if (Logger.#currentLevel <= Logger.LEVELS.warn) {
|
|
104
|
+
console.warn(
|
|
105
|
+
colors.warn(`${Logger.#formatTime()} ⚠️ WARNING: ${message}`),
|
|
106
|
+
...args
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static error(message, ...args) {
|
|
112
|
+
if (Logger.#currentLevel <= Logger.LEVELS.error) {
|
|
113
|
+
console.error(
|
|
114
|
+
colors.error(`${Logger.#formatTime()} ❌ ERROR: ${message}`),
|
|
115
|
+
...args
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static startSpinner(message) {
|
|
121
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
122
|
+
process.stdout.write(
|
|
123
|
+
colors.highlight(`${Logger.#formatTime()} ⏳ ${message}... `)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
stop: (success = true, result = "") => {
|
|
128
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
129
|
+
const icon = success ? colors.success("✅") : colors.error("❌");
|
|
130
|
+
process.stdout.write(`${icon} ${result}\n`);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static progressBar(total, message = "Progress") {
|
|
137
|
+
if (Logger.#currentLevel > Logger.LEVELS.info)
|
|
138
|
+
return { update: () => {}, complete: () => {} };
|
|
139
|
+
|
|
140
|
+
let current = 0;
|
|
141
|
+
const width = 30;
|
|
142
|
+
const update = (increment = 1) => {
|
|
143
|
+
current += increment;
|
|
144
|
+
const percent = Math.min(Math.floor((current / total) * 100), 100);
|
|
145
|
+
const filled = Math.floor((width * current) / total);
|
|
146
|
+
const bar = "█".repeat(filled) + "░".repeat(width - filled);
|
|
147
|
+
process.stdout.write(
|
|
148
|
+
`\r${Logger.#formatTime()} ${message}: ${colors.highlight(
|
|
149
|
+
bar
|
|
150
|
+
)} ${percent}% (${current}/${total})`
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
update,
|
|
156
|
+
complete: () => {
|
|
157
|
+
update(total - current);
|
|
158
|
+
process.stdout.write("\n");
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Enhanced error handling with structured errors
|
|
165
|
+
class SchemaError extends Error {
|
|
166
|
+
constructor(message, code, details = {}) {
|
|
167
|
+
super(message);
|
|
168
|
+
this.name = "SchemaError";
|
|
169
|
+
this.code = code;
|
|
170
|
+
this.details = details;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static get codes() {
|
|
174
|
+
return {
|
|
175
|
+
ENV_FILE_NOT_FOUND: "ENV_FILE_NOT_FOUND",
|
|
176
|
+
SCHEMA_FILE_NOT_FOUND: "SCHEMA_FILE_NOT_FOUND",
|
|
177
|
+
DATABASE_URL_NOT_FOUND: "DATABASE_URL_NOT_FOUND",
|
|
178
|
+
DATABASE_CONNECTION_FAILED: "DATABASE_CONNECTION_FAILED",
|
|
179
|
+
PRISMA_OPERATION_FAILED: "PRISMA_OPERATION_FAILED",
|
|
180
|
+
FILE_UPDATE_FAILED: "FILE_UPDATE_FAILED",
|
|
181
|
+
INVALID_DATABASE_NAME: "INVALID_DATABASE_NAME",
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Custom error class for Prisma operations (enhanced)
|
|
187
|
+
class PrismaOperationError extends SchemaError {
|
|
188
|
+
constructor(operation, dbName, originalError) {
|
|
189
|
+
super(
|
|
190
|
+
`Error during '${operation}' on database ${dbName}`,
|
|
191
|
+
SchemaError.codes.PRISMA_OPERATION_FAILED,
|
|
192
|
+
{ operation, dbName, originalError }
|
|
193
|
+
);
|
|
194
|
+
this.name = "PrismaOperationError";
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Function to delay execution
|
|
199
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
200
|
+
|
|
201
|
+
// Function to mask sensitive information in URLs for logging
|
|
202
|
+
const maskDatabaseUrl = (url) => {
|
|
203
|
+
if (!url) return "[NO URL]";
|
|
204
|
+
try {
|
|
205
|
+
const parsedUrl = new URL(url);
|
|
206
|
+
if (parsedUrl.password) {
|
|
207
|
+
parsedUrl.password = "***";
|
|
208
|
+
}
|
|
209
|
+
return parsedUrl.toString();
|
|
210
|
+
} catch (err) {
|
|
211
|
+
return url.replace(/:[^:@]+@/, ":***@");
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// Function to update Prisma client files
|
|
216
|
+
const updatePrismaClientFiles = async () => {
|
|
217
|
+
const spinner = Logger.startSpinner("Updating Prisma client files");
|
|
218
|
+
try {
|
|
219
|
+
const files = ["edge.js", "index.js"];
|
|
220
|
+
let updatedCount = 0;
|
|
221
|
+
|
|
222
|
+
for (const file of files) {
|
|
223
|
+
const filePath = path.join(CONFIG.prismaDir, file);
|
|
224
|
+
|
|
225
|
+
if (!existsSync(filePath)) {
|
|
226
|
+
Logger.warn(`File ${filePath} does not exist, skipping update`);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
Logger.debug(`Reading file: ${filePath}`);
|
|
231
|
+
let content = readFileSync(filePath, "utf8");
|
|
232
|
+
|
|
233
|
+
// Update output object
|
|
234
|
+
const newContent = content
|
|
235
|
+
.replace(
|
|
236
|
+
/"output":\s*{\s*"value":\s*"[^"]*",\s*"fromEnvVar":\s*[^}]*}/,
|
|
237
|
+
'"output": { "value": "/schema/src/prisma", "fromEnvVar": null }'
|
|
238
|
+
)
|
|
239
|
+
.replace(
|
|
240
|
+
/"sourceFilePath":\s*"[^"]*"/,
|
|
241
|
+
'"sourceFilePath": "/schema/prisma/schema.prisma"'
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
if (content !== newContent) {
|
|
245
|
+
writeFileSync(filePath, newContent);
|
|
246
|
+
updatedCount++;
|
|
247
|
+
Logger.debug(`Updated ${file} with new paths`);
|
|
248
|
+
} else {
|
|
249
|
+
Logger.debug(`No changes needed for ${file}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
spinner.stop(true, `Updated ${updatedCount} files`);
|
|
254
|
+
return updatedCount;
|
|
255
|
+
} catch (error) {
|
|
256
|
+
spinner.stop(false, error.message);
|
|
257
|
+
throw new SchemaError(
|
|
258
|
+
`Error updating Prisma client files: ${error.message}`,
|
|
259
|
+
SchemaError.codes.FILE_UPDATE_FAILED,
|
|
260
|
+
{ error }
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// Function to get all database URLs from .env file
|
|
266
|
+
const getDatabaseUrls = () => {
|
|
267
|
+
const spinner = Logger.startSpinner("Reading database URLs from .env");
|
|
268
|
+
try {
|
|
269
|
+
if (!existsSync(CONFIG.envPath)) {
|
|
270
|
+
spinner.stop(false, `Environment file not found at ${CONFIG.envPath}`);
|
|
271
|
+
throw new SchemaError(
|
|
272
|
+
`Environment file not found at ${CONFIG.envPath}`,
|
|
273
|
+
SchemaError.codes.ENV_FILE_NOT_FOUND
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const envContent = readFileSync(CONFIG.envPath, "utf8");
|
|
278
|
+
const databaseUrls = [];
|
|
279
|
+
|
|
280
|
+
// Find all *_DATABASE_URL variables
|
|
281
|
+
const matches = envContent.matchAll(/(\w+)_DATABASE_URL="([^"]+)"/g);
|
|
282
|
+
for (const match of matches) {
|
|
283
|
+
const [, name, url] = match;
|
|
284
|
+
// Validate DB name format (simple check to prevent injection)
|
|
285
|
+
if (!/^[A-Z0-9_]+$/.test(name)) {
|
|
286
|
+
Logger.warn(`Skipping database with invalid name format: ${name}`);
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// If targetDatabase is specified, only include that database and DEFAULT
|
|
291
|
+
if (
|
|
292
|
+
!CONFIG.targetDatabase ||
|
|
293
|
+
name === CONFIG.targetDatabase.toUpperCase() ||
|
|
294
|
+
name === CONFIG.defaultDbName
|
|
295
|
+
) {
|
|
296
|
+
databaseUrls.push({ name, url });
|
|
297
|
+
Logger.debug(`Found database: ${name} (${maskDatabaseUrl(url)})`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
spinner.stop(true, `Found ${databaseUrls.length} databases`);
|
|
302
|
+
return databaseUrls;
|
|
303
|
+
} catch (error) {
|
|
304
|
+
if (!(error instanceof SchemaError)) {
|
|
305
|
+
spinner.stop(false, error.message);
|
|
306
|
+
throw new SchemaError(
|
|
307
|
+
`Error reading database URLs: ${error.message}`,
|
|
308
|
+
SchemaError.codes.DATABASE_URL_NOT_FOUND,
|
|
309
|
+
{ error }
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
// Function to update CURRENT_ADMIN_USER_EMAIL in config.js
|
|
317
|
+
const updateAdminEmail = (dbName) => {
|
|
318
|
+
const spinner = Logger.startSpinner(`Updating admin email for ${dbName}`);
|
|
319
|
+
try {
|
|
320
|
+
if (!existsSync(CONFIG.constantPath)) {
|
|
321
|
+
spinner.stop(false, `Constant file not found at ${CONFIG.constantPath}`);
|
|
322
|
+
throw new SchemaError(
|
|
323
|
+
`Constant file not found at ${CONFIG.constantPath}`,
|
|
324
|
+
SchemaError.codes.FILE_UPDATE_FAILED
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
let content = readFileSync(CONFIG.constantPath, "utf8");
|
|
329
|
+
|
|
330
|
+
// Get tenant email from config
|
|
331
|
+
const getTenantEmail = (tenantName) => {
|
|
332
|
+
// Convert tenant name to lowercase for comparison
|
|
333
|
+
const lowerTenantName = tenantName.toLowerCase();
|
|
334
|
+
|
|
335
|
+
// Look for the tenant in TENANT_EMAILS array
|
|
336
|
+
const tenantConfig = TENANT_EMAILS.find(
|
|
337
|
+
(tenant) => Object.keys(tenant)[0] === lowerTenantName
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
if (tenantConfig) {
|
|
341
|
+
const key = Object.keys(tenantConfig)[0];
|
|
342
|
+
return tenantConfig[key];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Fallback to default email if tenant not found
|
|
346
|
+
const defaultConfig = TENANT_EMAILS.find(
|
|
347
|
+
(tenant) => Object.keys(tenant)[0] === "default"
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
return defaultConfig ? defaultConfig.default : "admin@gmail.com";
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
// Get email from tenant configuration
|
|
354
|
+
const email = getTenantEmail(
|
|
355
|
+
dbName === CONFIG.defaultDbName ? "default" : dbName
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
// Replace CURRENT_ADMIN_USER_EMAIL
|
|
359
|
+
const newContent = content.replace(
|
|
360
|
+
/CURRENT_ADMIN_USER_EMAIL\s*=\s*['"]([^'"]*)['"]/,
|
|
361
|
+
`CURRENT_ADMIN_USER_EMAIL = '${email}'`
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
if (content !== newContent) {
|
|
365
|
+
writeFileSync(CONFIG.constantPath, newContent);
|
|
366
|
+
spinner.stop(true, `Set to ${email}`);
|
|
367
|
+
Logger.debug(`Updated CURRENT_ADMIN_USER_EMAIL to: ${email}`);
|
|
368
|
+
} else {
|
|
369
|
+
spinner.stop(true, `Already set to ${email}`);
|
|
370
|
+
}
|
|
371
|
+
} catch (error) {
|
|
372
|
+
if (!(error instanceof SchemaError)) {
|
|
373
|
+
spinner.stop(false, error.message);
|
|
374
|
+
throw new SchemaError(
|
|
375
|
+
`Error updating admin email: ${error.message}`,
|
|
376
|
+
SchemaError.codes.FILE_UPDATE_FAILED,
|
|
377
|
+
{ error }
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
throw error;
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
// Function to update database URL in schema.prisma
|
|
385
|
+
const updateSchemaUrl = (dbName) => {
|
|
386
|
+
const spinner = Logger.startSpinner(`Updating schema URL for ${dbName}`);
|
|
387
|
+
try {
|
|
388
|
+
if (!existsSync(CONFIG.schemaPath)) {
|
|
389
|
+
spinner.stop(false, `Schema file not found at ${CONFIG.schemaPath}`);
|
|
390
|
+
throw new SchemaError(
|
|
391
|
+
`Schema file not found at ${CONFIG.schemaPath}`,
|
|
392
|
+
SchemaError.codes.SCHEMA_FILE_NOT_FOUND
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
let content = readFileSync(CONFIG.schemaPath, "utf8");
|
|
397
|
+
|
|
398
|
+
// Replace the database URL in the datasource block with the environment variable reference
|
|
399
|
+
const newEnvVar = `${dbName}_DATABASE_URL`;
|
|
400
|
+
const newContent = content.replace(
|
|
401
|
+
/url\s*=\s*env\("([^"]+)"\)/,
|
|
402
|
+
`url = env("${newEnvVar}")`
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
if (content !== newContent) {
|
|
406
|
+
writeFileSync(CONFIG.schemaPath, newContent);
|
|
407
|
+
spinner.stop(true, `Now using ${newEnvVar}`);
|
|
408
|
+
Logger.debug(`Updated database URL in schema.prisma to use ${newEnvVar}`);
|
|
409
|
+
} else {
|
|
410
|
+
spinner.stop(true, `Already using ${newEnvVar}`);
|
|
411
|
+
}
|
|
412
|
+
} catch (error) {
|
|
413
|
+
if (!(error instanceof SchemaError)) {
|
|
414
|
+
spinner.stop(false, error.message);
|
|
415
|
+
throw new SchemaError(
|
|
416
|
+
`Error updating schema URL: ${error.message}`,
|
|
417
|
+
SchemaError.codes.FILE_UPDATE_FAILED,
|
|
418
|
+
{ error, dbName }
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
throw error;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// Function to restore original schema.prisma
|
|
426
|
+
const restoreSchemaUrl = async () => {
|
|
427
|
+
const spinner = Logger.startSpinner("Restoring original schema.prisma");
|
|
428
|
+
try {
|
|
429
|
+
if (!existsSync(CONFIG.schemaPath)) {
|
|
430
|
+
spinner.stop(false, `Schema file not found at ${CONFIG.schemaPath}`);
|
|
431
|
+
throw new SchemaError(
|
|
432
|
+
`Schema file not found at ${CONFIG.schemaPath}`,
|
|
433
|
+
SchemaError.codes.SCHEMA_FILE_NOT_FOUND
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
let content = readFileSync(CONFIG.schemaPath, "utf8");
|
|
438
|
+
const defaultEnvVar = `${CONFIG.defaultDbName}_DATABASE_URL`;
|
|
439
|
+
|
|
440
|
+
// Restore the original environment variable reference
|
|
441
|
+
const newContent = content.replace(
|
|
442
|
+
/url\s*=\s*env\("([^"]+)"\)/,
|
|
443
|
+
`url = env("${defaultEnvVar}")`
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
if (content !== newContent) {
|
|
447
|
+
writeFileSync(CONFIG.schemaPath, newContent);
|
|
448
|
+
spinner.stop(true, `Set to ${defaultEnvVar}`);
|
|
449
|
+
Logger.debug(
|
|
450
|
+
`Restored original database URL in schema.prisma to ${defaultEnvVar}`
|
|
451
|
+
);
|
|
452
|
+
} else {
|
|
453
|
+
spinner.stop(true, `Already using ${defaultEnvVar}`);
|
|
454
|
+
}
|
|
455
|
+
} catch (error) {
|
|
456
|
+
if (!(error instanceof SchemaError)) {
|
|
457
|
+
spinner.stop(false, error.message);
|
|
458
|
+
throw new SchemaError(
|
|
459
|
+
`Error restoring schema URL: ${error.message}`,
|
|
460
|
+
SchemaError.codes.FILE_UPDATE_FAILED,
|
|
461
|
+
{ error }
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
throw error;
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
// Function to run Prisma commands with retry mechanism and connection management
|
|
469
|
+
const runPrismaCommand = async (
|
|
470
|
+
command,
|
|
471
|
+
databaseUrl,
|
|
472
|
+
dbName,
|
|
473
|
+
maxRetries = CONFIG.retryAttempts
|
|
474
|
+
) => {
|
|
475
|
+
let lastError;
|
|
476
|
+
const commandDisplay =
|
|
477
|
+
command.length > 30 ? `${command.substring(0, 27)}...` : command;
|
|
478
|
+
|
|
479
|
+
Logger.info(
|
|
480
|
+
`Running '${colors.highlight(commandDisplay)}' for database: ${colors.warn(
|
|
481
|
+
dbName
|
|
482
|
+
)}`
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
486
|
+
const spinner = Logger.startSpinner(
|
|
487
|
+
`Prisma ${commandDisplay} (attempt ${attempt}/${maxRetries})`
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
try {
|
|
491
|
+
// Update schema.prisma with the current database environment variable
|
|
492
|
+
await updateSchemaUrl(dbName);
|
|
493
|
+
|
|
494
|
+
// Use connection manager for db operations
|
|
495
|
+
if (
|
|
496
|
+
command.startsWith("db") ||
|
|
497
|
+
command === "migrate deploy" ||
|
|
498
|
+
command === "migrate dev"
|
|
499
|
+
) {
|
|
500
|
+
await connectionManager.executeWithConnection(
|
|
501
|
+
dbName,
|
|
502
|
+
databaseUrl,
|
|
503
|
+
async (prisma) => {
|
|
504
|
+
// Set the DATABASE_URL environment variable temporarily for this command
|
|
505
|
+
const originalDbUrl = process.env.DEFAULT_DATABASE_URL;
|
|
506
|
+
process.env.DEFAULT_DATABASE_URL = databaseUrl;
|
|
507
|
+
|
|
508
|
+
// Log the action but mask sensitive info
|
|
509
|
+
Logger.debug(
|
|
510
|
+
`Executing: npx prisma ${command} (using DB: ${maskDatabaseUrl(
|
|
511
|
+
databaseUrl
|
|
512
|
+
)})`
|
|
513
|
+
);
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
// Execute the Prisma command
|
|
517
|
+
execSync(`npx prisma ${command}`, {
|
|
518
|
+
stdio: "inherit",
|
|
519
|
+
env: {
|
|
520
|
+
...process.env,
|
|
521
|
+
PRISMA_CLIENT_CONNECTION_REUSE: "true",
|
|
522
|
+
},
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// Restore the original env var
|
|
526
|
+
process.env.DEFAULT_DATABASE_URL = originalDbUrl;
|
|
527
|
+
} catch (err) {
|
|
528
|
+
// Restore the original env var in case of error
|
|
529
|
+
process.env.DEFAULT_DATABASE_URL = originalDbUrl;
|
|
530
|
+
throw err;
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
{ autoRelease: false } // Don't auto-release, we'll manage connection closure later
|
|
534
|
+
);
|
|
535
|
+
} else {
|
|
536
|
+
// For commands that don't need a live connection, use the original approach
|
|
537
|
+
// Set the DATABASE_URL environment variable temporarily for this command
|
|
538
|
+
const originalDbUrl = process.env.DEFAULT_DATABASE_URL;
|
|
539
|
+
process.env.DEFAULT_DATABASE_URL = databaseUrl;
|
|
540
|
+
|
|
541
|
+
// Log the action but mask sensitive info
|
|
542
|
+
Logger.debug(
|
|
543
|
+
`Executing: npx prisma ${command} (using DB: ${maskDatabaseUrl(
|
|
544
|
+
databaseUrl
|
|
545
|
+
)})`
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
// Execute the Prisma command
|
|
549
|
+
execSync(`npx prisma ${command}`, {
|
|
550
|
+
stdio: "inherit",
|
|
551
|
+
env: {
|
|
552
|
+
...process.env,
|
|
553
|
+
PRISMA_CLIENT_CONNECTION_REUSE: "true",
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
// Restore the original env var
|
|
558
|
+
process.env.DEFAULT_DATABASE_URL = originalDbUrl;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
spinner.stop(true, "Completed successfully");
|
|
562
|
+
|
|
563
|
+
// Add delay after successful command
|
|
564
|
+
await delay(CONFIG.successDelay);
|
|
565
|
+
return;
|
|
566
|
+
} catch (error) {
|
|
567
|
+
// Restore the original env var in case of error
|
|
568
|
+
process.env.DEFAULT_DATABASE_URL = process.env.DEFAULT_DATABASE_URL || "";
|
|
569
|
+
|
|
570
|
+
lastError = error;
|
|
571
|
+
spinner.stop(false, `Failed`);
|
|
572
|
+
|
|
573
|
+
if (attempt < maxRetries) {
|
|
574
|
+
Logger.warn(`Retrying in ${CONFIG.retryDelay / 1000} seconds...`);
|
|
575
|
+
await delay(CONFIG.retryDelay);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// Create sanitized error details to avoid logging sensitive info
|
|
581
|
+
const errorDetails = {
|
|
582
|
+
message: lastError?.message ?? "Unknown error",
|
|
583
|
+
code: lastError?.code,
|
|
584
|
+
signal: lastError?.signal,
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
// Log detailed error info for debugging but sanitize URLs
|
|
588
|
+
const errorMessage =
|
|
589
|
+
lastError?.stderr?.toString() || lastError?.message || "Unknown error";
|
|
590
|
+
const sanitizedMessage = errorMessage.replace(
|
|
591
|
+
/(postgres|mysql|mongodb):\/\/[^@\s]+@/g,
|
|
592
|
+
"$1://***:***@"
|
|
593
|
+
);
|
|
594
|
+
Logger.debug(`Prisma command error details: ${sanitizedMessage}`);
|
|
595
|
+
|
|
596
|
+
throw new PrismaOperationError(command, dbName, errorDetails);
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
// Function to test database connection using connection manager
|
|
600
|
+
const testDatabaseConnection = async (url, dbName) => {
|
|
601
|
+
const spinner = Logger.startSpinner(
|
|
602
|
+
`Testing connection to ${dbName} database`
|
|
603
|
+
);
|
|
604
|
+
try {
|
|
605
|
+
// Don't expose URL in command/logs
|
|
606
|
+
const maskedUrl = maskDatabaseUrl(url);
|
|
607
|
+
Logger.debug(`Testing connection to: ${maskedUrl}`);
|
|
608
|
+
|
|
609
|
+
// Use connection manager to test connection
|
|
610
|
+
await connectionManager.executeWithConnection(
|
|
611
|
+
dbName,
|
|
612
|
+
url,
|
|
613
|
+
async (prisma) => {
|
|
614
|
+
// Just connect and execute a simple query
|
|
615
|
+
await prisma.$queryRaw`SELECT 1 as connected`;
|
|
616
|
+
},
|
|
617
|
+
{ autoRelease: true } // Auto-release after test
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
spinner.stop(true, "Connection successful");
|
|
621
|
+
return true;
|
|
622
|
+
} catch (error) {
|
|
623
|
+
const sanitizedError = error.message.replace(
|
|
624
|
+
/(postgres|mysql|mongodb):\/\/[^@\s]+@/g,
|
|
625
|
+
"$1://***:***@"
|
|
626
|
+
);
|
|
627
|
+
spinner.stop(false, "Connection failed");
|
|
628
|
+
Logger.error(`Failed to connect to ${dbName} database: ${sanitizedError}`);
|
|
629
|
+
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// Main function to sync schemas
|
|
635
|
+
const syncSchemas = async () => {
|
|
636
|
+
Logger.info(colors.header("🔄 Starting schema synchronization process"));
|
|
637
|
+
Logger.info(colors.debug("──────────────────────────────────────────"));
|
|
638
|
+
|
|
639
|
+
try {
|
|
640
|
+
// Step 0: Get database URLs and validate
|
|
641
|
+
const databaseUrls = getDatabaseUrls();
|
|
642
|
+
|
|
643
|
+
if (databaseUrls.length === 0) {
|
|
644
|
+
throw new SchemaError(
|
|
645
|
+
"No matching database URLs found in prisma/.env file!",
|
|
646
|
+
SchemaError.codes.DATABASE_URL_NOT_FOUND
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
if (CONFIG.targetDatabase) {
|
|
651
|
+
Logger.info(
|
|
652
|
+
colors.bold(
|
|
653
|
+
`Target database: ${colors.highlight(
|
|
654
|
+
CONFIG.targetDatabase.toUpperCase()
|
|
655
|
+
)}`
|
|
656
|
+
)
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
// Check if target database exists
|
|
660
|
+
const targetDb = databaseUrls.find(
|
|
661
|
+
(db) => db.name === CONFIG.targetDatabase.toUpperCase()
|
|
662
|
+
);
|
|
663
|
+
if (!targetDb) {
|
|
664
|
+
throw new SchemaError(
|
|
665
|
+
`Target database ${CONFIG.targetDatabase.toUpperCase()}_DATABASE_URL not found in .env file!`,
|
|
666
|
+
SchemaError.codes.DATABASE_URL_NOT_FOUND
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
} else {
|
|
670
|
+
Logger.info(
|
|
671
|
+
colors.bold(
|
|
672
|
+
`Processing all databases: ${colors.highlight(
|
|
673
|
+
databaseUrls.map((db) => db.name).join(", ")
|
|
674
|
+
)}`
|
|
675
|
+
)
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Find the default database (DEFAULT_DATABASE_URL)
|
|
680
|
+
const defaultDb = databaseUrls.find(
|
|
681
|
+
(db) => db.name === CONFIG.defaultDbName
|
|
682
|
+
);
|
|
683
|
+
if (!defaultDb) {
|
|
684
|
+
throw new SchemaError(
|
|
685
|
+
`${CONFIG.defaultDbName}_DATABASE_URL not found in prisma/.env file!`,
|
|
686
|
+
SchemaError.codes.DATABASE_URL_NOT_FOUND
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// Step 1: Run migration on default database
|
|
691
|
+
Logger.info(colors.bold("\nStep 1: Setting up default database"));
|
|
692
|
+
await runPrismaCommand("migrate dev", defaultDb.url, defaultDb.name);
|
|
693
|
+
await runPrismaCommand("generate", defaultDb.url, defaultDb.name);
|
|
694
|
+
|
|
695
|
+
// Step 2: Process each additional database
|
|
696
|
+
const nonDefaultDbs = databaseUrls.filter(
|
|
697
|
+
(db) => db.name !== CONFIG.defaultDbName
|
|
698
|
+
);
|
|
699
|
+
|
|
700
|
+
if (nonDefaultDbs.length > 0) {
|
|
701
|
+
Logger.info(
|
|
702
|
+
colors.bold(
|
|
703
|
+
`\nStep 2: Processing ${nonDefaultDbs.length} additional databases`
|
|
704
|
+
)
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
const progress = Logger.progressBar(
|
|
708
|
+
nonDefaultDbs.length,
|
|
709
|
+
"Database processing"
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
for (const [index, db] of nonDefaultDbs.entries()) {
|
|
713
|
+
Logger.info(
|
|
714
|
+
colors.bold(
|
|
715
|
+
`\nProcessing database ${index + 1}/${
|
|
716
|
+
nonDefaultDbs.length
|
|
717
|
+
}: ${colors.highlight(db.name)}`
|
|
718
|
+
)
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
// Deploy migrations
|
|
722
|
+
await runPrismaCommand("migrate deploy", db.url, db.name);
|
|
723
|
+
|
|
724
|
+
// Generate Prisma Client
|
|
725
|
+
await runPrismaCommand("generate", db.url, db.name);
|
|
726
|
+
|
|
727
|
+
// Uncomment if seeding is needed
|
|
728
|
+
// Logger.info('Updating admin email for seeding...');
|
|
729
|
+
// updateAdminEmail(db.name);
|
|
730
|
+
// Logger.info('Running seed...');
|
|
731
|
+
// await runPrismaCommand('db seed', db.url, db.name);
|
|
732
|
+
|
|
733
|
+
progress.update();
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
progress.complete();
|
|
737
|
+
} else {
|
|
738
|
+
Logger.info(colors.debug("\nNo additional databases to process"));
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// Step 3: Finalize and cleanup
|
|
742
|
+
Logger.info(colors.bold("\nStep 3: Finalizing and cleanup"));
|
|
743
|
+
|
|
744
|
+
// Reset admin email back to default
|
|
745
|
+
updateAdminEmail(CONFIG.defaultDbName);
|
|
746
|
+
|
|
747
|
+
// Restore original schema.prisma file
|
|
748
|
+
await restoreSchemaUrl();
|
|
749
|
+
|
|
750
|
+
// Run final operations on default database
|
|
751
|
+
Logger.info("Running final operations on default database...");
|
|
752
|
+
await runPrismaCommand("migrate deploy", defaultDb.url, defaultDb.name);
|
|
753
|
+
await runPrismaCommand("generate", defaultDb.url, defaultDb.name);
|
|
754
|
+
|
|
755
|
+
// Update Prisma client files with correct paths
|
|
756
|
+
await updatePrismaClientFiles();
|
|
757
|
+
|
|
758
|
+
// Close all database connections
|
|
759
|
+
await connectionManager.closeAllConnections();
|
|
760
|
+
|
|
761
|
+
// Display success message
|
|
762
|
+
Logger.info(colors.debug("\n──────────────────────────────────────────"));
|
|
763
|
+
if (CONFIG.targetDatabase) {
|
|
764
|
+
Logger.success(
|
|
765
|
+
colors.bold(
|
|
766
|
+
colors.success(
|
|
767
|
+
`Schema synchronization for ${CONFIG.targetDatabase.toUpperCase()} completed successfully! 🎉`
|
|
768
|
+
)
|
|
769
|
+
)
|
|
770
|
+
);
|
|
771
|
+
} else {
|
|
772
|
+
Logger.success(
|
|
773
|
+
colors.bold(
|
|
774
|
+
colors.success(
|
|
775
|
+
`Schema synchronization for all databases completed successfully! 🎉`
|
|
776
|
+
)
|
|
777
|
+
)
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
} catch (error) {
|
|
781
|
+
Logger.info(colors.debug("\n──────────────────────────────────────────"));
|
|
782
|
+
Logger.error(
|
|
783
|
+
colors.bold(colors.error("Schema synchronization failed! 💥"))
|
|
784
|
+
);
|
|
785
|
+
|
|
786
|
+
if (error instanceof SchemaError) {
|
|
787
|
+
Logger.error(`Error code: ${colors.warn(error.code)}`);
|
|
788
|
+
Logger.error(`Message: ${error.message}`);
|
|
789
|
+
|
|
790
|
+
if (error instanceof PrismaOperationError) {
|
|
791
|
+
Logger.error(`Operation: ${colors.warn(error.details.operation)}`);
|
|
792
|
+
Logger.error(`Database: ${colors.warn(error.details.dbName)}`);
|
|
793
|
+
if (error.details.originalError) {
|
|
794
|
+
Logger.debug(
|
|
795
|
+
"Error details:",
|
|
796
|
+
JSON.stringify(error.details.originalError, null, 2)
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
} else if (error.details && Object.keys(error.details).length > 0) {
|
|
800
|
+
Logger.debug("Error details:", JSON.stringify(error.details, null, 2));
|
|
801
|
+
}
|
|
802
|
+
} else {
|
|
803
|
+
Logger.error(error.stack || error.message);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Try to restore schema file if possible
|
|
807
|
+
try {
|
|
808
|
+
await restoreSchemaUrl();
|
|
809
|
+
Logger.info("Schema file restored to default state");
|
|
810
|
+
} catch (cleanupError) {
|
|
811
|
+
Logger.warn(`Failed to restore schema file: ${cleanupError.message}`);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// Ensure connections are closed even on error
|
|
815
|
+
await connectionManager.closeAllConnections();
|
|
816
|
+
|
|
817
|
+
process.exit(1);
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
|
|
821
|
+
// Print usage information
|
|
822
|
+
const printUsage = () => {
|
|
823
|
+
console.log(`
|
|
824
|
+
${colors.header("Prisma Schema Synchronization Tool")}
|
|
825
|
+
${colors.debug("──────────────────────────────────────────")}
|
|
826
|
+
|
|
827
|
+
${colors.bold("Usage:")}
|
|
828
|
+
npm run sync-database Sync all databases
|
|
829
|
+
npm run sync-database -- --db NAME Sync specific database (NAME)
|
|
830
|
+
|
|
831
|
+
${colors.bold("Examples:")}
|
|
832
|
+
npm run sync-database
|
|
833
|
+
npm run sync-database -- --db default
|
|
834
|
+
|
|
835
|
+
${colors.debug("──────────────────────────────────────────")}
|
|
836
|
+
`);
|
|
837
|
+
};
|
|
838
|
+
|
|
839
|
+
// Display help if requested
|
|
840
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
841
|
+
printUsage();
|
|
842
|
+
process.exit(0);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// Execute the main function
|
|
846
|
+
syncSchemas()
|
|
847
|
+
.catch((error) => {
|
|
848
|
+
process.exit(1);
|
|
849
|
+
})
|
|
850
|
+
.finally(async () => {
|
|
851
|
+
// Final cleanup to ensure all connections are closed
|
|
852
|
+
await connectionManager.closeAllConnections();
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
// Graceful exit on SIGINT
|
|
856
|
+
process.on("SIGINT", async () => {
|
|
857
|
+
Logger.info("\nScript interrupted. Cleaning up...");
|
|
858
|
+
try {
|
|
859
|
+
await restoreSchemaUrl();
|
|
860
|
+
Logger.success("Schema restored. Exiting...");
|
|
861
|
+
} catch (error) {
|
|
862
|
+
Logger.error("Failed to restore schema:", error.message);
|
|
863
|
+
}
|
|
864
|
+
process.exit(0);
|
|
865
|
+
});
|