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,873 @@
|
|
|
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 for enhanced UI
|
|
9
|
+
import { PrismaClient } from "../src/prisma/index.js";
|
|
10
|
+
import { connectionManager } from "../prisma/seeders/utils/connection-manager.js";
|
|
11
|
+
import { TENANT_EMAILS } from "../prisma/seeders/utils/config.js";
|
|
12
|
+
|
|
13
|
+
// Process command line arguments
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
let targetDatabase = null;
|
|
16
|
+
|
|
17
|
+
// Parse for --db flag
|
|
18
|
+
for (let i = 0; i < args.length; i++) {
|
|
19
|
+
if (args[i] === "--db" && i + 1 < args.length) {
|
|
20
|
+
targetDatabase = args[i + 1];
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Configuration
|
|
26
|
+
const CONFIG = {
|
|
27
|
+
envPath: path.join("prisma", ".env"),
|
|
28
|
+
prismaDir: path.join("src", "prisma"),
|
|
29
|
+
schemaPath: path.join("prisma", "schema.prisma"),
|
|
30
|
+
constantPath: path.join("prisma", "seeders", "utils", "config.js"),
|
|
31
|
+
defaultDbName: "DEFAULT",
|
|
32
|
+
retryAttempts: 3,
|
|
33
|
+
retryDelay: 2000,
|
|
34
|
+
successDelay: 1000,
|
|
35
|
+
targetDatabase: targetDatabase,
|
|
36
|
+
logLevel: process.env.LOG_LEVEL || "info", // debug, info, warn, error
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Load environment variables from prisma/.env
|
|
40
|
+
dotenv.config({ path: CONFIG.envPath });
|
|
41
|
+
|
|
42
|
+
// Configure colors theme
|
|
43
|
+
colors.setTheme({
|
|
44
|
+
debug: "grey",
|
|
45
|
+
info: "white",
|
|
46
|
+
success: "green",
|
|
47
|
+
warn: "yellow",
|
|
48
|
+
error: "red",
|
|
49
|
+
highlight: "cyan",
|
|
50
|
+
bold: "bold",
|
|
51
|
+
header: ["bold", "cyan"],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Logger implementation
|
|
55
|
+
class Logger {
|
|
56
|
+
static LEVELS = {
|
|
57
|
+
debug: 0,
|
|
58
|
+
info: 1,
|
|
59
|
+
warn: 2,
|
|
60
|
+
error: 3,
|
|
61
|
+
silent: 4,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
static #currentLevel = Logger.LEVELS[CONFIG.logLevel] || Logger.LEVELS.info;
|
|
65
|
+
static #startTime = Date.now();
|
|
66
|
+
|
|
67
|
+
static #formatTime() {
|
|
68
|
+
const elapsed = ((Date.now() - Logger.#startTime) / 1000).toFixed(2);
|
|
69
|
+
return `[${elapsed}s]`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static debug(message, ...args) {
|
|
73
|
+
if (Logger.#currentLevel <= Logger.LEVELS.debug) {
|
|
74
|
+
console.debug(
|
|
75
|
+
colors.debug(`${Logger.#formatTime()} 🔍 DEBUG: ${message}`),
|
|
76
|
+
...args
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static info(message, ...args) {
|
|
82
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
83
|
+
console.log(
|
|
84
|
+
colors.info(`${Logger.#formatTime()} ℹ️ ${message}`),
|
|
85
|
+
...args
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static success(message, ...args) {
|
|
91
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
92
|
+
console.log(
|
|
93
|
+
colors.success(`${Logger.#formatTime()} ✅ ${message}`),
|
|
94
|
+
...args
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static warn(message, ...args) {
|
|
100
|
+
if (Logger.#currentLevel <= Logger.LEVELS.warn) {
|
|
101
|
+
console.warn(
|
|
102
|
+
colors.warn(`${Logger.#formatTime()} ⚠️ WARNING: ${message}`),
|
|
103
|
+
...args
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static error(message, ...args) {
|
|
109
|
+
if (Logger.#currentLevel <= Logger.LEVELS.error) {
|
|
110
|
+
console.error(
|
|
111
|
+
colors.error(`${Logger.#formatTime()} ❌ ERROR: ${message}`),
|
|
112
|
+
...args
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static startSpinner(message) {
|
|
118
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
119
|
+
process.stdout.write(
|
|
120
|
+
colors.highlight(`${Logger.#formatTime()} ⏳ ${message}... `)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
stop: (success = true, result = "") => {
|
|
125
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
126
|
+
const icon = success ? colors.success("✅") : colors.error("❌");
|
|
127
|
+
process.stdout.write(`${icon} ${result}\n`);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static progressBar(total, message = "Progress") {
|
|
134
|
+
if (Logger.#currentLevel > Logger.LEVELS.info)
|
|
135
|
+
return { update: () => {}, complete: () => {} };
|
|
136
|
+
|
|
137
|
+
let current = 0;
|
|
138
|
+
const width = 30;
|
|
139
|
+
const update = (increment = 1) => {
|
|
140
|
+
current += increment;
|
|
141
|
+
const percent = Math.min(Math.floor((current / total) * 100), 100);
|
|
142
|
+
const filled = Math.floor((width * current) / total);
|
|
143
|
+
const bar = "█".repeat(filled) + "░".repeat(width - filled);
|
|
144
|
+
process.stdout.write(
|
|
145
|
+
`\r${Logger.#formatTime()} ${message}: ${colors.highlight(
|
|
146
|
+
bar
|
|
147
|
+
)} ${percent}% (${current}/${total})`
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
update,
|
|
153
|
+
complete: () => {
|
|
154
|
+
update(total - current);
|
|
155
|
+
process.stdout.write("\n");
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Enhanced error handling with structured errors
|
|
162
|
+
class SchemaError extends Error {
|
|
163
|
+
constructor(message, code, details = {}) {
|
|
164
|
+
super(message);
|
|
165
|
+
this.name = "SchemaError";
|
|
166
|
+
this.code = code;
|
|
167
|
+
this.details = details;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
static get codes() {
|
|
171
|
+
return {
|
|
172
|
+
ENV_FILE_NOT_FOUND: "ENV_FILE_NOT_FOUND",
|
|
173
|
+
SCHEMA_FILE_NOT_FOUND: "SCHEMA_FILE_NOT_FOUND",
|
|
174
|
+
DATABASE_URL_NOT_FOUND: "DATABASE_URL_NOT_FOUND",
|
|
175
|
+
PRISMA_OPERATION_FAILED: "PRISMA_OPERATION_FAILED",
|
|
176
|
+
FILE_UPDATE_FAILED: "FILE_UPDATE_FAILED",
|
|
177
|
+
INVALID_DATABASE_NAME: "INVALID_DATABASE_NAME",
|
|
178
|
+
SEEDING_FAILED: "SEEDING_FAILED",
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Custom error class for Prisma operations (enhanced)
|
|
184
|
+
class PrismaOperationError extends SchemaError {
|
|
185
|
+
constructor(operation, dbName, originalError) {
|
|
186
|
+
super(
|
|
187
|
+
`Error during '${operation}' on database ${dbName}`,
|
|
188
|
+
SchemaError.codes.PRISMA_OPERATION_FAILED,
|
|
189
|
+
{ operation, dbName, originalError }
|
|
190
|
+
);
|
|
191
|
+
this.name = "PrismaOperationError";
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Function to delay execution
|
|
196
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
197
|
+
|
|
198
|
+
// Function to mask sensitive information in URLs for logging
|
|
199
|
+
const maskDatabaseUrl = (url) => {
|
|
200
|
+
if (!url) return "[NO URL]";
|
|
201
|
+
try {
|
|
202
|
+
const parsedUrl = new URL(url);
|
|
203
|
+
if (parsedUrl.password) {
|
|
204
|
+
parsedUrl.password = "***";
|
|
205
|
+
}
|
|
206
|
+
return parsedUrl.toString();
|
|
207
|
+
} catch (err) {
|
|
208
|
+
return url.replace(/:[^:@]+@/, ":***@");
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// Function to update Prisma client files
|
|
213
|
+
const updatePrismaClientFiles = async () => {
|
|
214
|
+
const spinner = Logger.startSpinner("Updating Prisma client files");
|
|
215
|
+
try {
|
|
216
|
+
const files = ["edge.js", "index.js"];
|
|
217
|
+
let updatedCount = 0;
|
|
218
|
+
|
|
219
|
+
for (const file of files) {
|
|
220
|
+
const filePath = path.join(CONFIG.prismaDir, file);
|
|
221
|
+
|
|
222
|
+
if (!existsSync(filePath)) {
|
|
223
|
+
Logger.warn(`File ${filePath} does not exist, skipping update`);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
Logger.debug(`Reading file: ${filePath}`);
|
|
228
|
+
let content = readFileSync(filePath, "utf8");
|
|
229
|
+
|
|
230
|
+
// Update output object
|
|
231
|
+
const newContent = content
|
|
232
|
+
.replace(
|
|
233
|
+
/"output":\s*{\s*"value":\s*"[^"]*",\s*"fromEnvVar":\s*[^}]*}/,
|
|
234
|
+
'"output": { "value": "/schema/src/prisma", "fromEnvVar": null }'
|
|
235
|
+
)
|
|
236
|
+
.replace(
|
|
237
|
+
/"sourceFilePath":\s*"[^"]*"/,
|
|
238
|
+
'"sourceFilePath": "/schema/prisma/schema.prisma"'
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
if (content !== newContent) {
|
|
242
|
+
writeFileSync(filePath, newContent);
|
|
243
|
+
updatedCount++;
|
|
244
|
+
Logger.debug(`Updated ${file} with new paths`);
|
|
245
|
+
} else {
|
|
246
|
+
Logger.debug(`No changes needed for ${file}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
spinner.stop(true, `Updated ${updatedCount} files`);
|
|
251
|
+
return updatedCount;
|
|
252
|
+
} catch (error) {
|
|
253
|
+
spinner.stop(false, error.message);
|
|
254
|
+
throw new SchemaError(
|
|
255
|
+
`Error updating Prisma client files: ${error.message}`,
|
|
256
|
+
SchemaError.codes.FILE_UPDATE_FAILED,
|
|
257
|
+
{ error }
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// Function to get all database URLs from .env file
|
|
263
|
+
const getDatabaseUrls = () => {
|
|
264
|
+
const spinner = Logger.startSpinner("Reading database URLs from .env");
|
|
265
|
+
try {
|
|
266
|
+
if (!existsSync(CONFIG.envPath)) {
|
|
267
|
+
spinner.stop(false, `Environment file not found at ${CONFIG.envPath}`);
|
|
268
|
+
throw new SchemaError(
|
|
269
|
+
`Environment file not found at ${CONFIG.envPath}`,
|
|
270
|
+
SchemaError.codes.ENV_FILE_NOT_FOUND
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const envContent = readFileSync(CONFIG.envPath, "utf8");
|
|
275
|
+
const databaseUrls = [];
|
|
276
|
+
|
|
277
|
+
// Find all *_DATABASE_URL variables
|
|
278
|
+
const matches = envContent.matchAll(/(\w+)_DATABASE_URL="([^"]+)"/g);
|
|
279
|
+
for (const match of matches) {
|
|
280
|
+
const [, name, url] = match;
|
|
281
|
+
// Validate DB name format (simple check to prevent injection)
|
|
282
|
+
if (!/^[A-Z0-9_]+$/.test(name)) {
|
|
283
|
+
Logger.warn(`Skipping database with invalid name format: ${name}`);
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// If targetDatabase is specified, only include that database
|
|
288
|
+
// Use case-insensitive comparison by converting targetDatabase to uppercase
|
|
289
|
+
if (
|
|
290
|
+
!CONFIG.targetDatabase ||
|
|
291
|
+
name === CONFIG.targetDatabase.toUpperCase()
|
|
292
|
+
) {
|
|
293
|
+
databaseUrls.push({ name, url });
|
|
294
|
+
Logger.debug(`Found database: ${name} (${maskDatabaseUrl(url)})`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
spinner.stop(true, `Found ${databaseUrls.length} databases`);
|
|
299
|
+
return databaseUrls;
|
|
300
|
+
} catch (error) {
|
|
301
|
+
if (!(error instanceof SchemaError)) {
|
|
302
|
+
spinner.stop(false, error.message);
|
|
303
|
+
throw new SchemaError(
|
|
304
|
+
`Error reading database URLs: ${error.message}`,
|
|
305
|
+
SchemaError.codes.DATABASE_URL_NOT_FOUND,
|
|
306
|
+
{ error }
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
// Function to update CURRENT_ADMIN_USER_EMAIL in config.js
|
|
314
|
+
const updateAdminEmail = (dbName) => {
|
|
315
|
+
const spinner = Logger.startSpinner(`Updating admin email for ${dbName}`);
|
|
316
|
+
try {
|
|
317
|
+
if (!existsSync(CONFIG.constantPath)) {
|
|
318
|
+
spinner.stop(false, `Constant file not found at ${CONFIG.constantPath}`);
|
|
319
|
+
throw new SchemaError(
|
|
320
|
+
`Constant file not found at ${CONFIG.constantPath}`,
|
|
321
|
+
SchemaError.codes.FILE_UPDATE_FAILED
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
let content = readFileSync(CONFIG.constantPath, "utf8");
|
|
326
|
+
|
|
327
|
+
// Get tenant email from config
|
|
328
|
+
const getTenantEmail = (tenantName) => {
|
|
329
|
+
// Convert tenant name to lowercase for comparison
|
|
330
|
+
const lowerTenantName = tenantName.toLowerCase();
|
|
331
|
+
|
|
332
|
+
// Look for the tenant in TENANT_EMAILS array
|
|
333
|
+
const tenantConfig = TENANT_EMAILS.find(
|
|
334
|
+
(tenant) => Object.keys(tenant)[0] === lowerTenantName
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
if (tenantConfig) {
|
|
338
|
+
const key = Object.keys(tenantConfig)[0];
|
|
339
|
+
return tenantConfig[key];
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Fallback to default email if tenant not found
|
|
343
|
+
const defaultConfig = TENANT_EMAILS.find(
|
|
344
|
+
(tenant) => Object.keys(tenant)[0] === "default"
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
return defaultConfig ? defaultConfig.default : "admin@gmail.com";
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
// Get email from tenant configuration
|
|
351
|
+
const email = getTenantEmail(
|
|
352
|
+
dbName === CONFIG.defaultDbName ? "default" : dbName
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
// Replace CURRENT_ADMIN_USER_EMAIL
|
|
356
|
+
const newContent = content.replace(
|
|
357
|
+
/CURRENT_ADMIN_USER_EMAIL\s*=\s*['"]([^'"]*)['"]/,
|
|
358
|
+
`CURRENT_ADMIN_USER_EMAIL = '${email}'`
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
if (content !== newContent) {
|
|
362
|
+
writeFileSync(CONFIG.constantPath, newContent);
|
|
363
|
+
spinner.stop(true, `Set to ${email}`);
|
|
364
|
+
Logger.debug(`Updated CURRENT_ADMIN_USER_EMAIL to: ${email}`);
|
|
365
|
+
} else {
|
|
366
|
+
spinner.stop(true, `Already set to ${email}`);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return email;
|
|
370
|
+
} catch (error) {
|
|
371
|
+
if (!(error instanceof SchemaError)) {
|
|
372
|
+
spinner.stop(false, error.message);
|
|
373
|
+
throw new SchemaError(
|
|
374
|
+
`Error updating admin email: ${error.message}`,
|
|
375
|
+
SchemaError.codes.FILE_UPDATE_FAILED,
|
|
376
|
+
{ error }
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
// Function to update database URL in schema.prisma
|
|
384
|
+
const updateSchemaUrl = (dbName) => {
|
|
385
|
+
const spinner = Logger.startSpinner(`Updating schema URL for ${dbName}`);
|
|
386
|
+
try {
|
|
387
|
+
if (!existsSync(CONFIG.schemaPath)) {
|
|
388
|
+
spinner.stop(false, `Schema file not found at ${CONFIG.schemaPath}`);
|
|
389
|
+
throw new SchemaError(
|
|
390
|
+
`Schema file not found at ${CONFIG.schemaPath}`,
|
|
391
|
+
SchemaError.codes.SCHEMA_FILE_NOT_FOUND
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
let content = readFileSync(CONFIG.schemaPath, "utf8");
|
|
396
|
+
|
|
397
|
+
// Replace the database URL in the datasource block with the environment variable reference
|
|
398
|
+
const newEnvVar = `${dbName}_DATABASE_URL`;
|
|
399
|
+
const newContent = content.replace(
|
|
400
|
+
/url\s*=\s*env\("([^"]+)"\)/,
|
|
401
|
+
`url = env("${newEnvVar}")`
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
if (content !== newContent) {
|
|
405
|
+
writeFileSync(CONFIG.schemaPath, newContent);
|
|
406
|
+
spinner.stop(true, `Now using ${newEnvVar}`);
|
|
407
|
+
Logger.debug(`Updated database URL in schema.prisma to use ${newEnvVar}`);
|
|
408
|
+
} else {
|
|
409
|
+
spinner.stop(true, `Already using ${newEnvVar}`);
|
|
410
|
+
}
|
|
411
|
+
} catch (error) {
|
|
412
|
+
if (!(error instanceof SchemaError)) {
|
|
413
|
+
spinner.stop(false, error.message);
|
|
414
|
+
throw new SchemaError(
|
|
415
|
+
`Error updating schema URL: ${error.message}`,
|
|
416
|
+
SchemaError.codes.FILE_UPDATE_FAILED,
|
|
417
|
+
{ error, dbName }
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
throw error;
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
// Function to restore original schema.prisma
|
|
425
|
+
const restoreSchemaUrl = async () => {
|
|
426
|
+
const spinner = Logger.startSpinner("Restoring original schema.prisma");
|
|
427
|
+
try {
|
|
428
|
+
if (!existsSync(CONFIG.schemaPath)) {
|
|
429
|
+
spinner.stop(false, `Schema file not found at ${CONFIG.schemaPath}`);
|
|
430
|
+
throw new SchemaError(
|
|
431
|
+
`Schema file not found at ${CONFIG.schemaPath}`,
|
|
432
|
+
SchemaError.codes.SCHEMA_FILE_NOT_FOUND
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
let content = readFileSync(CONFIG.schemaPath, "utf8");
|
|
437
|
+
const defaultEnvVar = `${CONFIG.defaultDbName}_DATABASE_URL`;
|
|
438
|
+
|
|
439
|
+
// Restore the original environment variable reference
|
|
440
|
+
const newContent = content.replace(
|
|
441
|
+
/url\s*=\s*env\("([^"]+)"\)/,
|
|
442
|
+
`url = env("${defaultEnvVar}")`
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
if (content !== newContent) {
|
|
446
|
+
writeFileSync(CONFIG.schemaPath, newContent);
|
|
447
|
+
spinner.stop(true, `Set to ${defaultEnvVar}`);
|
|
448
|
+
Logger.debug(
|
|
449
|
+
`Restored original database URL in schema.prisma to ${defaultEnvVar}`
|
|
450
|
+
);
|
|
451
|
+
} else {
|
|
452
|
+
spinner.stop(true, `Already using ${defaultEnvVar}`);
|
|
453
|
+
}
|
|
454
|
+
} catch (error) {
|
|
455
|
+
if (!(error instanceof SchemaError)) {
|
|
456
|
+
spinner.stop(false, error.message);
|
|
457
|
+
throw new SchemaError(
|
|
458
|
+
`Error restoring schema URL: ${error.message}`,
|
|
459
|
+
SchemaError.codes.FILE_UPDATE_FAILED,
|
|
460
|
+
{ error }
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
throw error;
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
// Function to run Prisma commands with retry mechanism and connection management
|
|
468
|
+
const runPrismaCommand = async (
|
|
469
|
+
command,
|
|
470
|
+
databaseUrl,
|
|
471
|
+
dbName,
|
|
472
|
+
maxRetries = CONFIG.retryAttempts
|
|
473
|
+
) => {
|
|
474
|
+
let lastError;
|
|
475
|
+
const commandDisplay =
|
|
476
|
+
command.length > 30 ? `${command.substring(0, 27)}...` : command;
|
|
477
|
+
|
|
478
|
+
Logger.info(
|
|
479
|
+
`Running '${colors.highlight(commandDisplay)}' for database: ${colors.warn(
|
|
480
|
+
dbName
|
|
481
|
+
)}`
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
485
|
+
const spinner = Logger.startSpinner(
|
|
486
|
+
`Prisma ${commandDisplay} (attempt ${attempt}/${maxRetries})`
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
try {
|
|
490
|
+
// Update schema.prisma with the current database environment variable
|
|
491
|
+
await updateSchemaUrl(dbName);
|
|
492
|
+
|
|
493
|
+
if (command === "db seed") {
|
|
494
|
+
try {
|
|
495
|
+
// Wrap seeding in a try/catch with proper error capture
|
|
496
|
+
const result = await connectionManager.executeWithConnection(
|
|
497
|
+
dbName,
|
|
498
|
+
databaseUrl,
|
|
499
|
+
async (prisma) => {
|
|
500
|
+
// Set environment variables
|
|
501
|
+
const originalDbUrl = process.env.DEFAULT_DATABASE_URL;
|
|
502
|
+
process.env.DEFAULT_DATABASE_URL = databaseUrl;
|
|
503
|
+
|
|
504
|
+
try {
|
|
505
|
+
// Add a pre-seed delay to ensure connections are ready
|
|
506
|
+
await delay(1000);
|
|
507
|
+
|
|
508
|
+
// Capture standard output to preserve detailed seeding logs
|
|
509
|
+
process.env.DETAILED_LOGGING = "true";
|
|
510
|
+
|
|
511
|
+
// Restore the important NODE_OPTIONS memory limit
|
|
512
|
+
const originalNodeOptions = process.env.NODE_OPTIONS;
|
|
513
|
+
process.env.NODE_OPTIONS = "--max-old-space-size=4096";
|
|
514
|
+
process.env.PRISMA_CLIENT_CONNECTION_REUSE = "true";
|
|
515
|
+
|
|
516
|
+
// Execute the seed process directly instead of using execSync
|
|
517
|
+
// so we can capture all detailed logs
|
|
518
|
+
Logger.info(colors.bold(`\n===== DETAILED SEEDING LOGS =====`));
|
|
519
|
+
|
|
520
|
+
// Import the seed module dynamically
|
|
521
|
+
const { main: seedDatabase } = await import(
|
|
522
|
+
"../prisma/seeders/seed.js"
|
|
523
|
+
);
|
|
524
|
+
const success = await seedDatabase();
|
|
525
|
+
|
|
526
|
+
Logger.info(
|
|
527
|
+
colors.bold(`\n===== END OF DETAILED SEEDING LOGS =====\n`)
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
// Restore original NODE_OPTIONS
|
|
531
|
+
process.env.NODE_OPTIONS = originalNodeOptions;
|
|
532
|
+
|
|
533
|
+
if (!success) {
|
|
534
|
+
throw new Error("Seeding process returned failure status");
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
return { success: true };
|
|
538
|
+
} catch (err) {
|
|
539
|
+
// Capture and log detailed error information
|
|
540
|
+
const errorOutput = err.message || "Unknown error";
|
|
541
|
+
Logger.error(`Seeding error details: ${errorOutput}`);
|
|
542
|
+
throw new Error(`Seeding failed: ${errorOutput}`);
|
|
543
|
+
} finally {
|
|
544
|
+
// Restore env var
|
|
545
|
+
process.env.DEFAULT_DATABASE_URL = originalDbUrl;
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
{ autoRelease: false }
|
|
549
|
+
);
|
|
550
|
+
} catch (error) {
|
|
551
|
+
throw error;
|
|
552
|
+
}
|
|
553
|
+
} else {
|
|
554
|
+
// For non-seeding commands, use the original approach
|
|
555
|
+
// Set the DATABASE_URL environment variable temporarily for this command
|
|
556
|
+
const originalDbUrl = process.env.DEFAULT_DATABASE_URL;
|
|
557
|
+
process.env.DEFAULT_DATABASE_URL = databaseUrl;
|
|
558
|
+
|
|
559
|
+
// Log the action but mask sensitive info
|
|
560
|
+
Logger.debug(
|
|
561
|
+
`Executing: npx prisma ${command} (using DB: ${maskDatabaseUrl(
|
|
562
|
+
databaseUrl
|
|
563
|
+
)})`
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
// Execute the Prisma command
|
|
567
|
+
execSync(`npx prisma ${command}`, {
|
|
568
|
+
stdio: "inherit",
|
|
569
|
+
env: {
|
|
570
|
+
...process.env,
|
|
571
|
+
PRISMA_CLIENT_CONNECTION_REUSE: "true",
|
|
572
|
+
},
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// Restore the original env var
|
|
576
|
+
process.env.DEFAULT_DATABASE_URL = originalDbUrl;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
spinner.stop(true, "Completed successfully");
|
|
580
|
+
|
|
581
|
+
// Add delay after successful command
|
|
582
|
+
await delay(CONFIG.successDelay);
|
|
583
|
+
return;
|
|
584
|
+
} catch (error) {
|
|
585
|
+
// Restore the original env var in case of error
|
|
586
|
+
process.env.DEFAULT_DATABASE_URL = process.env.DEFAULT_DATABASE_URL || "";
|
|
587
|
+
|
|
588
|
+
lastError = error;
|
|
589
|
+
spinner.stop(false, `Failed`);
|
|
590
|
+
|
|
591
|
+
if (attempt < maxRetries) {
|
|
592
|
+
Logger.warn(`Retrying in ${CONFIG.retryDelay / 1000} seconds...`);
|
|
593
|
+
await delay(CONFIG.retryDelay);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Create sanitized error details to avoid logging sensitive info
|
|
599
|
+
const errorDetails = {
|
|
600
|
+
message: lastError?.message ?? "Unknown error",
|
|
601
|
+
code: lastError?.code,
|
|
602
|
+
signal: lastError?.signal,
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
// Log detailed error info for debugging but sanitize URLs
|
|
606
|
+
const errorMessage =
|
|
607
|
+
lastError?.stderr?.toString() || lastError?.message || "Unknown error";
|
|
608
|
+
const sanitizedMessage = errorMessage.replace(
|
|
609
|
+
/(postgres|mysql|mongodb):\/\/[^@\s]+@/g,
|
|
610
|
+
"$1://***:***@"
|
|
611
|
+
);
|
|
612
|
+
Logger.debug(`Prisma command error details: ${sanitizedMessage}`);
|
|
613
|
+
|
|
614
|
+
throw new PrismaOperationError(command, dbName, errorDetails);
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
// Function to validate schema before seeding
|
|
618
|
+
const validateSchema = async (databaseUrl, dbName) => {
|
|
619
|
+
const spinner = Logger.startSpinner(`Validating schema for ${dbName}`);
|
|
620
|
+
try {
|
|
621
|
+
// Set the DATABASE_URL environment variable temporarily
|
|
622
|
+
const originalDbUrl = process.env.DEFAULT_DATABASE_URL;
|
|
623
|
+
process.env.DEFAULT_DATABASE_URL = databaseUrl;
|
|
624
|
+
|
|
625
|
+
// Use validate command to check schema
|
|
626
|
+
const result = execSync(`npx prisma validate`, { stdio: "pipe" });
|
|
627
|
+
|
|
628
|
+
// Restore the original env var
|
|
629
|
+
process.env.DEFAULT_DATABASE_URL = originalDbUrl;
|
|
630
|
+
|
|
631
|
+
spinner.stop(true, "Schema is valid");
|
|
632
|
+
return true;
|
|
633
|
+
} catch (error) {
|
|
634
|
+
// Restore the original env var in case of error
|
|
635
|
+
process.env.DEFAULT_DATABASE_URL = process.env.DEFAULT_DATABASE_URL || "";
|
|
636
|
+
|
|
637
|
+
spinner.stop(false, "Schema validation failed");
|
|
638
|
+
|
|
639
|
+
// Sanitize error message
|
|
640
|
+
const errorMessage = error.message || "Unknown error";
|
|
641
|
+
const sanitizedMessage = errorMessage.replace(
|
|
642
|
+
/(postgres|mysql|mongodb):\/\/[^@\s]+@/g,
|
|
643
|
+
"$1://***:***@"
|
|
644
|
+
);
|
|
645
|
+
Logger.debug(`Schema validation error: ${sanitizedMessage}`);
|
|
646
|
+
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
// Main function to seed databases
|
|
652
|
+
const seedDatabases = async () => {
|
|
653
|
+
Logger.info(colors.header("🌱 Starting database seeding process"));
|
|
654
|
+
Logger.info(colors.debug("──────────────────────────────────────────"));
|
|
655
|
+
|
|
656
|
+
try {
|
|
657
|
+
// Step 0: Get database URLs and validate
|
|
658
|
+
const databaseUrls = getDatabaseUrls();
|
|
659
|
+
|
|
660
|
+
if (databaseUrls.length === 0) {
|
|
661
|
+
throw new SchemaError(
|
|
662
|
+
"No matching database URLs found in prisma/.env file!",
|
|
663
|
+
SchemaError.codes.DATABASE_URL_NOT_FOUND
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
if (CONFIG.targetDatabase) {
|
|
668
|
+
Logger.info(
|
|
669
|
+
colors.bold(
|
|
670
|
+
`Target database: ${colors.highlight(
|
|
671
|
+
CONFIG.targetDatabase.toUpperCase()
|
|
672
|
+
)}`
|
|
673
|
+
)
|
|
674
|
+
);
|
|
675
|
+
|
|
676
|
+
// Validate target database exists
|
|
677
|
+
if (databaseUrls.length === 0) {
|
|
678
|
+
throw new SchemaError(
|
|
679
|
+
`Target database ${CONFIG.targetDatabase.toUpperCase()}_DATABASE_URL not found in .env file!`,
|
|
680
|
+
SchemaError.codes.DATABASE_URL_NOT_FOUND
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
} else {
|
|
684
|
+
Logger.info(
|
|
685
|
+
colors.bold(
|
|
686
|
+
`Processing all databases: ${colors.highlight(
|
|
687
|
+
databaseUrls.map((db) => db.name).join(", ")
|
|
688
|
+
)}`
|
|
689
|
+
)
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// Display progress header
|
|
694
|
+
Logger.info(colors.bold("\n🛠️ Starting database seeding operations"));
|
|
695
|
+
Logger.info(colors.debug("──────────────────────────────────────────"));
|
|
696
|
+
|
|
697
|
+
// Process each database
|
|
698
|
+
const progress = Logger.progressBar(
|
|
699
|
+
databaseUrls.length,
|
|
700
|
+
"Database seeding progress"
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
for (const [index, db] of databaseUrls.entries()) {
|
|
704
|
+
Logger.info(
|
|
705
|
+
colors.bold(
|
|
706
|
+
`\nProcessing database ${index + 1}/${
|
|
707
|
+
databaseUrls.length
|
|
708
|
+
}: ${colors.highlight(db.name)}`
|
|
709
|
+
)
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
// Validate schema before proceeding
|
|
713
|
+
const isSchemaValid = await validateSchema(db.url, db.name);
|
|
714
|
+
if (!isSchemaValid) {
|
|
715
|
+
Logger.warn(
|
|
716
|
+
`Schema validation failed for ${db.name}, but proceeding with caution`
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// Update admin email for seeding
|
|
721
|
+
const email = updateAdminEmail(db.name);
|
|
722
|
+
Logger.info(`Admin email set to: ${email}`);
|
|
723
|
+
|
|
724
|
+
// Generate Prisma Client
|
|
725
|
+
await runPrismaCommand("generate", db.url, db.name);
|
|
726
|
+
|
|
727
|
+
// Run seed
|
|
728
|
+
await runPrismaCommand("db seed", db.url, db.name);
|
|
729
|
+
|
|
730
|
+
progress.update();
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
progress.complete();
|
|
734
|
+
|
|
735
|
+
// Cleanup and finalization
|
|
736
|
+
Logger.info(colors.bold("\nFinalizing and cleaning up"));
|
|
737
|
+
|
|
738
|
+
// Reset admin email back to default and restore schema if we've made changes
|
|
739
|
+
if (
|
|
740
|
+
databaseUrls.length > 0 &&
|
|
741
|
+
(!CONFIG.targetDatabase ||
|
|
742
|
+
CONFIG.targetDatabase.toUpperCase() !== CONFIG.defaultDbName)
|
|
743
|
+
) {
|
|
744
|
+
// Reset admin email back to default
|
|
745
|
+
updateAdminEmail(CONFIG.defaultDbName);
|
|
746
|
+
|
|
747
|
+
// Restore original schema.prisma file
|
|
748
|
+
await restoreSchemaUrl();
|
|
749
|
+
|
|
750
|
+
// Get the default database URL for final generate, if not already in our filtered list
|
|
751
|
+
if (!databaseUrls.some((db) => db.name === CONFIG.defaultDbName)) {
|
|
752
|
+
const allDbs = getDatabaseUrls();
|
|
753
|
+
const defaultDb = allDbs.find((db) => db.name === CONFIG.defaultDbName);
|
|
754
|
+
if (defaultDb) {
|
|
755
|
+
// Run final generate with default settings
|
|
756
|
+
Logger.info("Running final generate with default settings...");
|
|
757
|
+
await runPrismaCommand(
|
|
758
|
+
"generate",
|
|
759
|
+
defaultDb.url,
|
|
760
|
+
CONFIG.defaultDbName
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Update Prisma client files with correct paths
|
|
766
|
+
await updatePrismaClientFiles();
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// Step 3: Finalize and cleanup
|
|
770
|
+
Logger.info(colors.bold("\nStep 3: Finalizing and cleanup"));
|
|
771
|
+
|
|
772
|
+
// Close all database connections
|
|
773
|
+
await connectionManager.closeAllConnections();
|
|
774
|
+
|
|
775
|
+
// Display success message
|
|
776
|
+
Logger.info(colors.debug("\n──────────────────────────────────────────"));
|
|
777
|
+
if (CONFIG.targetDatabase) {
|
|
778
|
+
Logger.success(
|
|
779
|
+
colors.bold(
|
|
780
|
+
`Database seeding for ${CONFIG.targetDatabase.toUpperCase()} completed successfully! 🎉`
|
|
781
|
+
)
|
|
782
|
+
);
|
|
783
|
+
} else {
|
|
784
|
+
Logger.success(
|
|
785
|
+
colors.bold(
|
|
786
|
+
`Database seeding for all databases completed successfully! 🎉`
|
|
787
|
+
)
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
} catch (error) {
|
|
791
|
+
Logger.info(colors.debug("\n──────────────────────────────────────────"));
|
|
792
|
+
Logger.error(colors.bold(colors.error("Database seeding failed! 💥")));
|
|
793
|
+
|
|
794
|
+
if (error instanceof SchemaError) {
|
|
795
|
+
Logger.error(`Error code: ${colors.warn(error.code)}`);
|
|
796
|
+
Logger.error(`Message: ${error.message}`);
|
|
797
|
+
|
|
798
|
+
if (error instanceof PrismaOperationError) {
|
|
799
|
+
Logger.error(`Operation: ${colors.warn(error.details.operation)}`);
|
|
800
|
+
Logger.error(`Database: ${colors.warn(error.details.dbName)}`);
|
|
801
|
+
if (error.details.originalError) {
|
|
802
|
+
Logger.debug(
|
|
803
|
+
"Error details:",
|
|
804
|
+
JSON.stringify(error.details.originalError, null, 2)
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
} else if (error.details && Object.keys(error.details).length > 0) {
|
|
808
|
+
Logger.debug("Error details:", JSON.stringify(error.details, null, 2));
|
|
809
|
+
}
|
|
810
|
+
} else {
|
|
811
|
+
Logger.error(error.stack || error.message);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// Try to restore schema file if possible
|
|
815
|
+
try {
|
|
816
|
+
await restoreSchemaUrl();
|
|
817
|
+
Logger.info("Schema file restored to default state");
|
|
818
|
+
} catch (cleanupError) {
|
|
819
|
+
Logger.warn(`Failed to restore schema file: ${cleanupError.message}`);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Ensure connections are closed even on error
|
|
823
|
+
await connectionManager.closeAllConnections();
|
|
824
|
+
|
|
825
|
+
process.exit(1);
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
// Print usage information
|
|
830
|
+
const printUsage = () => {
|
|
831
|
+
console.log(`
|
|
832
|
+
${colors.header("Prisma Database Seeding Tool")}
|
|
833
|
+
${colors.debug("──────────────────────────────────────────")}
|
|
834
|
+
|
|
835
|
+
${colors.bold("Usage:")}
|
|
836
|
+
npm run seed-database Seed all databases
|
|
837
|
+
npm run seed-database -- --db NAME Seed specific database (NAME)
|
|
838
|
+
|
|
839
|
+
${colors.bold("Examples:")}
|
|
840
|
+
npm run seed-database
|
|
841
|
+
npm run seed-database -- --db default
|
|
842
|
+
|
|
843
|
+
${colors.debug("──────────────────────────────────────────")}
|
|
844
|
+
`);
|
|
845
|
+
};
|
|
846
|
+
|
|
847
|
+
// Display help if requested
|
|
848
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
849
|
+
printUsage();
|
|
850
|
+
process.exit(0);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Execute the main function
|
|
854
|
+
seedDatabases()
|
|
855
|
+
.catch((error) => {
|
|
856
|
+
process.exit(1);
|
|
857
|
+
})
|
|
858
|
+
.finally(async () => {
|
|
859
|
+
// Final cleanup to ensure all connections are closed
|
|
860
|
+
await connectionManager.closeAllConnections();
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
// Graceful exit on SIGINT
|
|
864
|
+
process.on("SIGINT", async () => {
|
|
865
|
+
Logger.info("\nScript interrupted. Cleaning up...");
|
|
866
|
+
try {
|
|
867
|
+
await restoreSchemaUrl();
|
|
868
|
+
Logger.success("Schema restored. Exiting...");
|
|
869
|
+
} catch (error) {
|
|
870
|
+
Logger.error("Failed to restore schema:", error.message);
|
|
871
|
+
}
|
|
872
|
+
process.exit(0);
|
|
873
|
+
});
|