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,1048 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { PrismaClient } from "../src/prisma/index.js";
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
import colors from "colors";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
import readline from "readline";
|
|
10
|
+
import { execSync } from "child_process";
|
|
11
|
+
import { existsSync, readFileSync } from "fs";
|
|
12
|
+
import { connectionManager } from "../prisma/seeders/utils/connection-manager.js";
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
|
|
17
|
+
// Load environment variables
|
|
18
|
+
dotenv.config({ path: path.resolve(__dirname, "../prisma/.env") });
|
|
19
|
+
|
|
20
|
+
// Configuration
|
|
21
|
+
const CONFIG = {
|
|
22
|
+
logLevel: process.env.LOG_LEVEL || "info", // debug, info, warn, error
|
|
23
|
+
retryAttempts: 3,
|
|
24
|
+
retryDelay: 2000,
|
|
25
|
+
requireConfirmation: true,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Configure colors theme
|
|
29
|
+
colors.setTheme({
|
|
30
|
+
debug: "grey",
|
|
31
|
+
info: "white",
|
|
32
|
+
success: "green",
|
|
33
|
+
warn: "yellow",
|
|
34
|
+
error: "red",
|
|
35
|
+
highlight: "cyan",
|
|
36
|
+
bold: "bold",
|
|
37
|
+
header: ["bold", "cyan"],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Logger implementation
|
|
41
|
+
class Logger {
|
|
42
|
+
static LEVELS = {
|
|
43
|
+
debug: 0,
|
|
44
|
+
info: 1,
|
|
45
|
+
warn: 2,
|
|
46
|
+
error: 3,
|
|
47
|
+
silent: 4,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
static #currentLevel = Logger.LEVELS[CONFIG.logLevel] || Logger.LEVELS.info;
|
|
51
|
+
static #startTime = Date.now();
|
|
52
|
+
|
|
53
|
+
static #formatTime() {
|
|
54
|
+
const elapsed = ((Date.now() - Logger.#startTime) / 1000).toFixed(2);
|
|
55
|
+
return `[${elapsed}s]`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static debug(message, ...args) {
|
|
59
|
+
if (Logger.#currentLevel <= Logger.LEVELS.debug) {
|
|
60
|
+
console.debug(
|
|
61
|
+
colors.debug(`${Logger.#formatTime()} đ DEBUG: ${message}`),
|
|
62
|
+
...args
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static info(message, ...args) {
|
|
68
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
69
|
+
console.log(
|
|
70
|
+
colors.info(`${Logger.#formatTime()} âšī¸ ${message}`),
|
|
71
|
+
...args
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static success(message, ...args) {
|
|
77
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
78
|
+
console.log(
|
|
79
|
+
colors.success(`${Logger.#formatTime()} â
${message}`),
|
|
80
|
+
...args
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static warn(message, ...args) {
|
|
86
|
+
if (Logger.#currentLevel <= Logger.LEVELS.warn) {
|
|
87
|
+
console.warn(
|
|
88
|
+
colors.warn(`${Logger.#formatTime()} â ī¸ WARNING: ${message}`),
|
|
89
|
+
...args
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static error(message, ...args) {
|
|
95
|
+
if (Logger.#currentLevel <= Logger.LEVELS.error) {
|
|
96
|
+
console.error(
|
|
97
|
+
colors.error(`${Logger.#formatTime()} â ERROR: ${message}`),
|
|
98
|
+
...args
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static startSpinner(message) {
|
|
104
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
105
|
+
process.stdout.write(
|
|
106
|
+
colors.highlight(`${Logger.#formatTime()} âŗ ${message}... `)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
stop: (success = true, result = "") => {
|
|
111
|
+
if (Logger.#currentLevel <= Logger.LEVELS.info) {
|
|
112
|
+
const icon = success ? colors.success("â
") : colors.error("â");
|
|
113
|
+
process.stdout.write(`${icon} ${result}\n`);
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static progressBar(total, message = "Progress") {
|
|
120
|
+
if (Logger.#currentLevel > Logger.LEVELS.info)
|
|
121
|
+
return { update: () => {}, complete: () => {} };
|
|
122
|
+
|
|
123
|
+
let current = 0;
|
|
124
|
+
const width = 30;
|
|
125
|
+
const update = (increment = 1) => {
|
|
126
|
+
current += increment;
|
|
127
|
+
const percent = Math.min(Math.floor((current / total) * 100), 100);
|
|
128
|
+
const filled = Math.floor((width * current) / total);
|
|
129
|
+
const bar = "â".repeat(filled) + "â".repeat(width - filled);
|
|
130
|
+
process.stdout.write(
|
|
131
|
+
`\r${Logger.#formatTime()} ${message}: ${colors.highlight(
|
|
132
|
+
bar
|
|
133
|
+
)} ${percent}% (${current}/${total})`
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
update,
|
|
139
|
+
complete: () => {
|
|
140
|
+
update(total - current);
|
|
141
|
+
process.stdout.write("\n");
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Enhanced error handling with structured errors
|
|
148
|
+
class TruncationError extends Error {
|
|
149
|
+
constructor(message, code, details = {}) {
|
|
150
|
+
super(message);
|
|
151
|
+
this.name = "TruncationError";
|
|
152
|
+
this.code = code;
|
|
153
|
+
this.details = details;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static get codes() {
|
|
157
|
+
return {
|
|
158
|
+
INVALID_ARGUMENTS: "INVALID_ARGUMENTS",
|
|
159
|
+
DATABASE_NOT_FOUND: "DATABASE_NOT_FOUND",
|
|
160
|
+
TABLE_NOT_FOUND: "TABLE_NOT_FOUND",
|
|
161
|
+
CONNECTION_FAILED: "CONNECTION_FAILED",
|
|
162
|
+
TRUNCATION_FAILED: "TRUNCATION_FAILED",
|
|
163
|
+
AUTHENTICATION_FAILED: "AUTHENTICATION_FAILED",
|
|
164
|
+
OPERATION_CANCELLED: "OPERATION_CANCELLED",
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Function to mask sensitive information in URLs for logging
|
|
171
|
+
*/
|
|
172
|
+
const maskDatabaseUrl = (url) => {
|
|
173
|
+
if (!url) return "[NO URL]";
|
|
174
|
+
try {
|
|
175
|
+
const parsedUrl = new URL(url);
|
|
176
|
+
if (parsedUrl.password) {
|
|
177
|
+
parsedUrl.password = "***";
|
|
178
|
+
}
|
|
179
|
+
return parsedUrl.toString();
|
|
180
|
+
} catch (err) {
|
|
181
|
+
return url.replace(/:[^:@]+@/, ":***@");
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Function to validate a table name to prevent SQL injection
|
|
187
|
+
* Returns sanitized table name or throws error if invalid
|
|
188
|
+
*/
|
|
189
|
+
const validateTableName = (tableName) => {
|
|
190
|
+
// Table names should only contain alphanumeric characters, underscores, or specific allowed symbols
|
|
191
|
+
// This is a strict validation for PostgreSQL table names
|
|
192
|
+
if (!/^[a-zA-Z0-9_"]+$/.test(tableName)) {
|
|
193
|
+
throw new TruncationError(
|
|
194
|
+
`Invalid table name: "${tableName}". Table names should only contain alphanumeric characters and underscores.`,
|
|
195
|
+
TruncationError.codes.INVALID_ARGUMENTS
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Remove any double quotes to prevent SQL injection via quote escaping
|
|
200
|
+
// We'll add our own quotes when constructing the query
|
|
201
|
+
return tableName.replace(/"/g, "");
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Create a readline interface for user input
|
|
206
|
+
*/
|
|
207
|
+
const getReadlineInterface = () => {
|
|
208
|
+
return readline.createInterface({
|
|
209
|
+
input: process.stdin,
|
|
210
|
+
output: process.stdout,
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Ask for user confirmation
|
|
216
|
+
*/
|
|
217
|
+
const confirmAction = async (message) => {
|
|
218
|
+
const rl = getReadlineInterface();
|
|
219
|
+
return new Promise((resolve) => {
|
|
220
|
+
rl.question(`${message} (y/N): `, (answer) => {
|
|
221
|
+
rl.close();
|
|
222
|
+
resolve(answer.toLowerCase() === "y");
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Parse command line arguments to get tables and target database
|
|
229
|
+
*/
|
|
230
|
+
const parseArguments = () => {
|
|
231
|
+
// Get all arguments after the script name
|
|
232
|
+
const args = process.argv.slice(2);
|
|
233
|
+
|
|
234
|
+
if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
|
|
235
|
+
showUsage();
|
|
236
|
+
process.exit(args.includes("--help") || args.includes("-h") ? 0 : 1);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Initialize with default values
|
|
240
|
+
let targetDb = null;
|
|
241
|
+
let tableNames = [];
|
|
242
|
+
let excludedTables = [];
|
|
243
|
+
let dryRun = false;
|
|
244
|
+
let noCascade = false;
|
|
245
|
+
let noConfirm = false;
|
|
246
|
+
let interactive = false;
|
|
247
|
+
let noRestartIdentity = false;
|
|
248
|
+
|
|
249
|
+
// Loop through arguments to find flags and their values
|
|
250
|
+
for (let i = 0; i < args.length; i++) {
|
|
251
|
+
const arg = args[i];
|
|
252
|
+
|
|
253
|
+
// Handle database flag
|
|
254
|
+
if (arg === "--db") {
|
|
255
|
+
if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
|
|
256
|
+
// The next argument is the database name
|
|
257
|
+
targetDb = args[i + 1].toUpperCase();
|
|
258
|
+
i++; // Skip the next argument since we've processed it
|
|
259
|
+
}
|
|
260
|
+
// If --db is specified without a value, it means all databases
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Handle tables flag
|
|
264
|
+
else if (arg === "--tables" || arg === "-t") {
|
|
265
|
+
if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
|
|
266
|
+
// The next argument contains the table names
|
|
267
|
+
const tableString = args[i + 1];
|
|
268
|
+
tableNames = tableString
|
|
269
|
+
.split(",")
|
|
270
|
+
.map((name) => name.trim())
|
|
271
|
+
.filter((name) => name !== "");
|
|
272
|
+
i++; // Skip the next argument since we've processed it
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Handle exclude tables flag
|
|
277
|
+
else if (arg === "--exclude" || arg === "-e") {
|
|
278
|
+
if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
|
|
279
|
+
// The next argument contains the excluded table names
|
|
280
|
+
const tableString = args[i + 1];
|
|
281
|
+
excludedTables = tableString
|
|
282
|
+
.split(",")
|
|
283
|
+
.map((name) => name.trim())
|
|
284
|
+
.filter((name) => name !== "");
|
|
285
|
+
i++; // Skip the next argument since we've processed it
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Handle dry-run flag
|
|
290
|
+
else if (arg === "--dry-run") {
|
|
291
|
+
dryRun = true;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Handle no-cascade flag
|
|
295
|
+
else if (arg === "--no-cascade") {
|
|
296
|
+
noCascade = true;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Handle no-confirm flag
|
|
300
|
+
else if (arg === "--no-confirm") {
|
|
301
|
+
noConfirm = true;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Handle no-restart-identity flag
|
|
305
|
+
else if (arg === "--no-restart-identity") {
|
|
306
|
+
noRestartIdentity = true;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Handle interactive flag
|
|
310
|
+
else if (arg === "--interactive" || arg === "-i") {
|
|
311
|
+
interactive = true;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Validate that we have table names (unless in interactive mode)
|
|
316
|
+
if (tableNames.length === 0 && !interactive) {
|
|
317
|
+
Logger.error("No tables specified");
|
|
318
|
+
showUsage();
|
|
319
|
+
process.exit(1);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Filter out excluded tables
|
|
323
|
+
if (excludedTables.length > 0) {
|
|
324
|
+
tableNames = tableNames.filter((table) => !excludedTables.includes(table));
|
|
325
|
+
if (tableNames.length === 0) {
|
|
326
|
+
throw new TruncationError(
|
|
327
|
+
"All specified tables were excluded. No tables left to truncate.",
|
|
328
|
+
TruncationError.codes.INVALID_ARGUMENTS
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
tableNames,
|
|
335
|
+
targetDb,
|
|
336
|
+
dryRun,
|
|
337
|
+
noCascade,
|
|
338
|
+
noConfirm: noConfirm,
|
|
339
|
+
interactive,
|
|
340
|
+
excludedTables,
|
|
341
|
+
noRestartIdentity,
|
|
342
|
+
};
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Show usage instructions
|
|
347
|
+
*/
|
|
348
|
+
const showUsage = () => {
|
|
349
|
+
console.log(`
|
|
350
|
+
${colors.header("Database Table Truncation Tool")}
|
|
351
|
+
${colors.debug("ââââââââââââââââââââââââââââââââââââââââââ")}
|
|
352
|
+
|
|
353
|
+
${colors.bold("Description:")}
|
|
354
|
+
Truncates specified tables in one or more databases.
|
|
355
|
+
|
|
356
|
+
${colors.bold("Usage:")}
|
|
357
|
+
npm run truncate-tables -- [options]
|
|
358
|
+
|
|
359
|
+
${colors.bold("Options:")}
|
|
360
|
+
--help, -h Show this help message
|
|
361
|
+
--db [DATABASE] Specify target database (omit value for all databases)
|
|
362
|
+
--tables, -t Comma-separated list of tables to truncate
|
|
363
|
+
--exclude, -e Comma-separated list of tables to exclude
|
|
364
|
+
--dry-run Show what would be truncated without executing
|
|
365
|
+
--no-cascade Disable CASCADE option in truncate statement
|
|
366
|
+
--no-confirm Skip confirmation prompts
|
|
367
|
+
--no-restart-identity Do not reset identity columns after truncation
|
|
368
|
+
--interactive, -i Select tables interactively
|
|
369
|
+
|
|
370
|
+
${colors.bold("Examples:")}
|
|
371
|
+
npm run truncate-tables -- --db --tables countries,cities,states
|
|
372
|
+
npm run truncate-tables -- --db ARVIND --tables countries,cities,states
|
|
373
|
+
npm run truncate-tables -- --db DEFAULT --tables all --exclude migrations,_prisma_migrations
|
|
374
|
+
npm run truncate-tables -- --interactive
|
|
375
|
+
npm run truncate-tables -- --db DEFAULT --dry-run --tables users,posts
|
|
376
|
+
npm run truncate-tables -- --db DEFAULT --tables all --no-restart-identity
|
|
377
|
+
|
|
378
|
+
${colors.debug("ââââââââââââââââââââââââââââââââââââââââââ")}
|
|
379
|
+
`);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get all database URLs from environment variables
|
|
384
|
+
* Looks for variables ending with _DATABASE_URL
|
|
385
|
+
* If targetDb is specified, filter to only include that database
|
|
386
|
+
*/
|
|
387
|
+
const getDatabaseUrls = (targetDb) => {
|
|
388
|
+
const spinner = Logger.startSpinner("Reading database configurations");
|
|
389
|
+
try {
|
|
390
|
+
const databaseEnvVars = Object.keys(process.env)
|
|
391
|
+
.filter((key) => key.endsWith("_DATABASE_URL"))
|
|
392
|
+
.sort();
|
|
393
|
+
|
|
394
|
+
if (databaseEnvVars.length === 0) {
|
|
395
|
+
spinner.stop(false, "No database URLs found");
|
|
396
|
+
throw new TruncationError(
|
|
397
|
+
"No database URLs found in environment variables",
|
|
398
|
+
TruncationError.codes.DATABASE_NOT_FOUND
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const dbConfigs = databaseEnvVars.map((envVar) => ({
|
|
403
|
+
name: envVar.replace("_DATABASE_URL", ""),
|
|
404
|
+
url: process.env[envVar],
|
|
405
|
+
}));
|
|
406
|
+
|
|
407
|
+
Logger.debug(
|
|
408
|
+
`Found ${dbConfigs.length} databases: ${dbConfigs
|
|
409
|
+
.map((db) => db.name)
|
|
410
|
+
.join(", ")}`
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
// If targetDb specified, filter to only that database
|
|
414
|
+
if (targetDb) {
|
|
415
|
+
const filteredDbs = dbConfigs.filter(
|
|
416
|
+
(db) => db.name.toUpperCase() === targetDb
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
if (filteredDbs.length === 0) {
|
|
420
|
+
spinner.stop(false, `Database '${targetDb}' not found`);
|
|
421
|
+
throw new TruncationError(
|
|
422
|
+
`Database '${targetDb}' not found in environment variables. Available databases: ${dbConfigs
|
|
423
|
+
.map((db) => db.name)
|
|
424
|
+
.join(", ")}`,
|
|
425
|
+
TruncationError.codes.DATABASE_NOT_FOUND
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
spinner.stop(true, `Found database: ${targetDb}`);
|
|
430
|
+
return filteredDbs;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
spinner.stop(true, `Found ${dbConfigs.length} databases`);
|
|
434
|
+
return dbConfigs;
|
|
435
|
+
} catch (error) {
|
|
436
|
+
if (!(error instanceof TruncationError)) {
|
|
437
|
+
spinner.stop(false, error.message);
|
|
438
|
+
throw new TruncationError(
|
|
439
|
+
`Error retrieving database configurations: ${error.message}`,
|
|
440
|
+
TruncationError.codes.DATABASE_NOT_FOUND,
|
|
441
|
+
{ originalError: error }
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
throw error;
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Function to test database connection using the connection manager
|
|
450
|
+
*/
|
|
451
|
+
const testDatabaseConnection = async (url, dbName) => {
|
|
452
|
+
const spinner = Logger.startSpinner(
|
|
453
|
+
`Testing connection to ${dbName} database`
|
|
454
|
+
);
|
|
455
|
+
try {
|
|
456
|
+
// Don't expose URL in command/logs
|
|
457
|
+
const maskedUrl = maskDatabaseUrl(url);
|
|
458
|
+
Logger.debug(`Testing connection to: ${maskedUrl}`);
|
|
459
|
+
|
|
460
|
+
// Use connection manager to test connection
|
|
461
|
+
await connectionManager.executeWithConnection(
|
|
462
|
+
dbName,
|
|
463
|
+
url,
|
|
464
|
+
async (prisma) => {
|
|
465
|
+
// Just connect and execute a simple query
|
|
466
|
+
await prisma.$queryRaw`SELECT 1 as connected`;
|
|
467
|
+
},
|
|
468
|
+
{ autoRelease: true } // Auto-release after test
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
spinner.stop(true, "Connection successful");
|
|
472
|
+
return true;
|
|
473
|
+
} catch (error) {
|
|
474
|
+
const sanitizedError = error.message.replace(
|
|
475
|
+
/(postgres|mysql|mongodb):\/\/[^@\s]+@/g,
|
|
476
|
+
"$1://***:***@"
|
|
477
|
+
);
|
|
478
|
+
spinner.stop(false, "Connection failed");
|
|
479
|
+
Logger.error(`Failed to connect to ${dbName} database: ${sanitizedError}`);
|
|
480
|
+
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Function to get all tables in database using the connection manager
|
|
487
|
+
*/
|
|
488
|
+
const getAllTables = async (url, dbName) => {
|
|
489
|
+
const spinner = Logger.startSpinner(`Retrieving tables from ${dbName}`);
|
|
490
|
+
try {
|
|
491
|
+
// Use connection manager to get tables
|
|
492
|
+
const tables = await connectionManager.executeWithConnection(
|
|
493
|
+
dbName,
|
|
494
|
+
url,
|
|
495
|
+
async (prisma) => {
|
|
496
|
+
// First, check if the tables we know exist are in the public schema
|
|
497
|
+
const specificTablesCheck = await prisma.$queryRaw`
|
|
498
|
+
SELECT EXISTS (
|
|
499
|
+
SELECT 1 FROM pg_catalog.pg_tables
|
|
500
|
+
WHERE tablename = 'vendors' AND schemaname = 'public'
|
|
501
|
+
) as exists_in_public;
|
|
502
|
+
`;
|
|
503
|
+
|
|
504
|
+
const existsInPublic = specificTablesCheck[0]?.exists_in_public;
|
|
505
|
+
Logger.debug(`Tables exist in public schema: ${existsInPublic}`);
|
|
506
|
+
|
|
507
|
+
// If tables don't exist in public schema, we need to find what schema they're in
|
|
508
|
+
let tablesResult;
|
|
509
|
+
|
|
510
|
+
if (existsInPublic) {
|
|
511
|
+
// Query for tables in the public schema
|
|
512
|
+
tablesResult = await prisma.$queryRaw`
|
|
513
|
+
SELECT tablename as table_name
|
|
514
|
+
FROM pg_catalog.pg_tables
|
|
515
|
+
WHERE schemaname = 'public'
|
|
516
|
+
AND tablename NOT IN ('_prisma_migrations', 'migrations')
|
|
517
|
+
ORDER BY tablename;
|
|
518
|
+
`;
|
|
519
|
+
} else {
|
|
520
|
+
// Get all available schemas
|
|
521
|
+
const schemas = await prisma.$queryRaw`
|
|
522
|
+
SELECT schema_name
|
|
523
|
+
FROM information_schema.schemata
|
|
524
|
+
WHERE schema_name NOT IN ('pg_catalog', 'information_schema');
|
|
525
|
+
`;
|
|
526
|
+
|
|
527
|
+
Logger.debug(
|
|
528
|
+
`Available schemas: ${schemas.map((s) => s.schema_name).join(", ")}`
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
// Try to find in which schema the 'vendors' table exists
|
|
532
|
+
const tableSchemaCheck = await prisma.$queryRaw`
|
|
533
|
+
SELECT table_schema, table_name
|
|
534
|
+
FROM information_schema.tables
|
|
535
|
+
WHERE table_name = 'vendors';
|
|
536
|
+
`;
|
|
537
|
+
|
|
538
|
+
if (tableSchemaCheck.length > 0) {
|
|
539
|
+
const schema = tableSchemaCheck[0].table_schema;
|
|
540
|
+
Logger.debug(`Found 'vendors' table in schema: ${schema}`);
|
|
541
|
+
|
|
542
|
+
// Get all tables from that schema
|
|
543
|
+
tablesResult = await prisma.$queryRaw`
|
|
544
|
+
SELECT table_name
|
|
545
|
+
FROM information_schema.tables
|
|
546
|
+
WHERE table_schema = ${schema}
|
|
547
|
+
AND table_type = 'BASE TABLE'
|
|
548
|
+
AND table_name NOT IN ('_prisma_migrations', 'migrations')
|
|
549
|
+
ORDER BY table_name;
|
|
550
|
+
`;
|
|
551
|
+
} else {
|
|
552
|
+
// Fallback to direct check for the specific tables we know exist
|
|
553
|
+
tablesResult = await prisma.$queryRaw`
|
|
554
|
+
SELECT ARRAY['vendors', 'vendor_status'] as table_name;
|
|
555
|
+
`;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return tablesResult.map((r) => r.table_name);
|
|
560
|
+
},
|
|
561
|
+
{ autoRelease: true } // Auto-release after getting tables
|
|
562
|
+
);
|
|
563
|
+
|
|
564
|
+
spinner.stop(true, `Found ${tables.length} tables`);
|
|
565
|
+
Logger.debug(`Tables found: ${tables.join(", ")}`);
|
|
566
|
+
return tables;
|
|
567
|
+
} catch (error) {
|
|
568
|
+
spinner.stop(false, "Failed to retrieve tables");
|
|
569
|
+
Logger.error(`Error retrieving tables from ${dbName}: ${error.message}`);
|
|
570
|
+
return [];
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Simple delay function for rate limiting
|
|
576
|
+
* @param {number} ms - Milliseconds to delay
|
|
577
|
+
* @returns {Promise} - Promise that resolves after the delay
|
|
578
|
+
*/
|
|
579
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Function to truncate tables using the connection manager
|
|
583
|
+
*/
|
|
584
|
+
const truncateTables = async (url, dbName, tables, options = {}) => {
|
|
585
|
+
const {
|
|
586
|
+
dryRun = false,
|
|
587
|
+
noCascade = false,
|
|
588
|
+
noRestartIdentity = false,
|
|
589
|
+
} = options;
|
|
590
|
+
|
|
591
|
+
if (tables.length === 0) {
|
|
592
|
+
Logger.warn("No tables to truncate");
|
|
593
|
+
return { tablesProcessed: 0 };
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (dryRun) {
|
|
597
|
+
Logger.info(
|
|
598
|
+
colors.yellow(
|
|
599
|
+
`[DRY RUN] Would truncate these tables in ${dbName}: ${tables.join(
|
|
600
|
+
", "
|
|
601
|
+
)}`
|
|
602
|
+
)
|
|
603
|
+
);
|
|
604
|
+
return { tablesProcessed: tables.length };
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
Logger.info(
|
|
608
|
+
`Truncating ${tables.length} tables in ${colors.highlight(dbName)}`
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
try {
|
|
612
|
+
const truncateMode = noCascade ? "" : "CASCADE";
|
|
613
|
+
const identityMode = noRestartIdentity ? "" : "RESTART IDENTITY";
|
|
614
|
+
let processedCount = 0;
|
|
615
|
+
|
|
616
|
+
// Use connection manager for truncation operations
|
|
617
|
+
await connectionManager.executeWithConnection(
|
|
618
|
+
dbName,
|
|
619
|
+
url,
|
|
620
|
+
async (prisma) => {
|
|
621
|
+
// For each table, execute truncate and log result
|
|
622
|
+
for (const table of tables) {
|
|
623
|
+
const spinner = Logger.startSpinner(`Truncating ${table}`);
|
|
624
|
+
try {
|
|
625
|
+
// Raw SQL query for truncation with RESTART IDENTITY (if enabled)
|
|
626
|
+
await prisma.$executeRawUnsafe(
|
|
627
|
+
`TRUNCATE TABLE "${table}" ${identityMode} ${truncateMode};`
|
|
628
|
+
);
|
|
629
|
+
spinner.stop(true, "Truncated");
|
|
630
|
+
processedCount++;
|
|
631
|
+
} catch (err) {
|
|
632
|
+
spinner.stop(false, "Failed");
|
|
633
|
+
Logger.error(`Error truncating ${table}: ${err.message}`);
|
|
634
|
+
throw err;
|
|
635
|
+
}
|
|
636
|
+
// Small delay to avoid overwhelming the database
|
|
637
|
+
await delay(100);
|
|
638
|
+
}
|
|
639
|
+
},
|
|
640
|
+
{ autoRelease: true } // Auto-release after truncation
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
Logger.success(
|
|
644
|
+
`Successfully truncated ${processedCount} tables in ${dbName}`
|
|
645
|
+
);
|
|
646
|
+
return { tablesProcessed: processedCount };
|
|
647
|
+
} catch (error) {
|
|
648
|
+
Logger.error(`Error truncating tables in ${dbName}: ${error.message}`);
|
|
649
|
+
throw error;
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Function to interactively select tables
|
|
655
|
+
*/
|
|
656
|
+
async function selectTablesInteractively(dbName, url) {
|
|
657
|
+
const allTables = await getAllTables(url, dbName);
|
|
658
|
+
|
|
659
|
+
if (allTables.length === 0) {
|
|
660
|
+
return [];
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Create interface for user input
|
|
664
|
+
const rl = readline.createInterface({
|
|
665
|
+
input: process.stdin,
|
|
666
|
+
output: process.stdout,
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
console.log(colors.cyan("\nAvailable tables:"));
|
|
670
|
+
allTables.forEach((table, index) => {
|
|
671
|
+
console.log(`${index + 1}. ${table}`);
|
|
672
|
+
});
|
|
673
|
+
console.log(colors.yellow("0. Select all tables"));
|
|
674
|
+
|
|
675
|
+
const question = (query) =>
|
|
676
|
+
new Promise((resolve) => rl.question(query, resolve));
|
|
677
|
+
|
|
678
|
+
const selectedTables = [];
|
|
679
|
+
let selecting = true;
|
|
680
|
+
|
|
681
|
+
while (selecting) {
|
|
682
|
+
const answer = await question(
|
|
683
|
+
colors.green(
|
|
684
|
+
"\nEnter table numbers to truncate (comma separated, 0 for all, or 'done' to finish): "
|
|
685
|
+
)
|
|
686
|
+
);
|
|
687
|
+
|
|
688
|
+
if (answer.toLowerCase() === "done") {
|
|
689
|
+
selecting = false;
|
|
690
|
+
} else if (answer === "0") {
|
|
691
|
+
selectedTables.push(...allTables);
|
|
692
|
+
selecting = false;
|
|
693
|
+
} else {
|
|
694
|
+
const selections = answer.split(",").map((s) => s.trim());
|
|
695
|
+
for (const selection of selections) {
|
|
696
|
+
const index = parseInt(selection, 10) - 1;
|
|
697
|
+
if (
|
|
698
|
+
!isNaN(index) &&
|
|
699
|
+
index >= 0 &&
|
|
700
|
+
index < allTables.length &&
|
|
701
|
+
!selectedTables.includes(allTables[index])
|
|
702
|
+
) {
|
|
703
|
+
selectedTables.push(allTables[index]);
|
|
704
|
+
console.log(colors.green(`Added ${allTables[index]} to selection`));
|
|
705
|
+
} else if (!isNaN(index)) {
|
|
706
|
+
console.log(
|
|
707
|
+
colors.red(`Invalid selection: ${selection}. Please try again.`)
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Show current selection
|
|
714
|
+
if (selectedTables.length > 0) {
|
|
715
|
+
console.log(
|
|
716
|
+
colors.cyan(
|
|
717
|
+
`\nCurrently selected (${
|
|
718
|
+
selectedTables.length
|
|
719
|
+
} tables): ${selectedTables.join(", ")}`
|
|
720
|
+
)
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
rl.close();
|
|
726
|
+
return selectedTables;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Function to truncate specified tables in a single database
|
|
731
|
+
* @param {Object} dbConfig - Database configuration with url and name
|
|
732
|
+
* @param {Array<string>} tableNames - List of tables to truncate
|
|
733
|
+
* @param {Object} options - Additional options for truncation
|
|
734
|
+
* @returns {Object} - Result of truncation operation
|
|
735
|
+
*/
|
|
736
|
+
async function truncateTablesInDatabase(dbConfig, tableNames, options = {}) {
|
|
737
|
+
const { url, name: dbName } = dbConfig;
|
|
738
|
+
const { dryRun, noCascade, interactive, excludedTables, noRestartIdentity } =
|
|
739
|
+
options;
|
|
740
|
+
let tablesProcessed = 0;
|
|
741
|
+
let tablesToProcess = [...tableNames];
|
|
742
|
+
let allTablesRequested = tablesToProcess.includes("all");
|
|
743
|
+
|
|
744
|
+
try {
|
|
745
|
+
Logger.info(colors.cyan(`\nProcessing database: ${dbName}`));
|
|
746
|
+
|
|
747
|
+
// Test connection to database
|
|
748
|
+
const spinner = Logger.startSpinner(`Testing connection to ${dbName}`);
|
|
749
|
+
try {
|
|
750
|
+
await testDatabaseConnection(url, dbName);
|
|
751
|
+
spinner.stop(true, "Connected");
|
|
752
|
+
} catch (error) {
|
|
753
|
+
spinner.stop(false, "Failed");
|
|
754
|
+
return {
|
|
755
|
+
database: dbName,
|
|
756
|
+
success: false,
|
|
757
|
+
error: `Connection failed: ${error.message}`,
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// Get all available tables if in interactive mode, if 'all' was specified, or if we need to filter out excluded tables
|
|
762
|
+
if (interactive || excludedTables.length > 0 || allTablesRequested) {
|
|
763
|
+
const allTablesSpinner = Logger.startSpinner(
|
|
764
|
+
`Fetching tables from ${dbName}`
|
|
765
|
+
);
|
|
766
|
+
try {
|
|
767
|
+
const allTables = await getAllTables(url, dbName);
|
|
768
|
+
allTablesSpinner.stop(true, `Found ${allTables.length} tables`);
|
|
769
|
+
|
|
770
|
+
if (interactive) {
|
|
771
|
+
// Let user select tables interactively
|
|
772
|
+
tablesToProcess = await selectTablesInteractively(dbName, url);
|
|
773
|
+
|
|
774
|
+
// If no tables selected, skip this database
|
|
775
|
+
if (tablesToProcess.length === 0) {
|
|
776
|
+
Logger.info(
|
|
777
|
+
colors.yellow(`No tables selected for ${dbName}, skipping`)
|
|
778
|
+
);
|
|
779
|
+
return {
|
|
780
|
+
database: dbName,
|
|
781
|
+
success: true,
|
|
782
|
+
tablesProcessed: 0,
|
|
783
|
+
cancelled: true,
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
} else if (allTablesRequested) {
|
|
787
|
+
// Replace the 'all' keyword with the actual list of all tables
|
|
788
|
+
if (allTables.length === 0) {
|
|
789
|
+
Logger.warn(
|
|
790
|
+
`No tables found in database ${dbName}. Check your connection details.`
|
|
791
|
+
);
|
|
792
|
+
} else {
|
|
793
|
+
tablesToProcess = allTables;
|
|
794
|
+
Logger.info(
|
|
795
|
+
colors.yellow(`Using all tables: ${tablesToProcess.join(", ")}`)
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// Always filter out excluded tables after getting all tables
|
|
801
|
+
if (excludedTables.length > 0) {
|
|
802
|
+
tablesToProcess = tablesToProcess.filter(
|
|
803
|
+
(table) => !excludedTables.includes(table)
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
} catch (error) {
|
|
807
|
+
allTablesSpinner.stop(false, "Failed");
|
|
808
|
+
return {
|
|
809
|
+
database: dbName,
|
|
810
|
+
success: false,
|
|
811
|
+
error: `Failed to get tables: ${error.message}`,
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// Remove 'all' from tablesToProcess if it's still there
|
|
817
|
+
tablesToProcess = tablesToProcess.filter((table) => table !== "all");
|
|
818
|
+
|
|
819
|
+
if (tablesToProcess.length === 0) {
|
|
820
|
+
Logger.warn(`No tables to truncate in database ${dbName}`);
|
|
821
|
+
return {
|
|
822
|
+
database: dbName,
|
|
823
|
+
success: true,
|
|
824
|
+
tablesProcessed: 0,
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// Confirm truncation if required and not in dry run mode
|
|
829
|
+
if (CONFIG.requireConfirmation && !dryRun && !options.noConfirm) {
|
|
830
|
+
const shouldProceed = await confirmAction(
|
|
831
|
+
colors.yellow(
|
|
832
|
+
`Are you sure you want to truncate ${tablesToProcess.length} tables in ${dbName}?`
|
|
833
|
+
)
|
|
834
|
+
);
|
|
835
|
+
|
|
836
|
+
if (!shouldProceed) {
|
|
837
|
+
Logger.warn(`Operation cancelled for database ${dbName}`);
|
|
838
|
+
return {
|
|
839
|
+
database: dbName,
|
|
840
|
+
success: true,
|
|
841
|
+
tablesProcessed: 0,
|
|
842
|
+
cancelled: true,
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// Truncate tables
|
|
848
|
+
try {
|
|
849
|
+
const truncateResults = await truncateTables(
|
|
850
|
+
url,
|
|
851
|
+
dbName,
|
|
852
|
+
tablesToProcess,
|
|
853
|
+
{
|
|
854
|
+
dryRun,
|
|
855
|
+
noCascade,
|
|
856
|
+
noRestartIdentity,
|
|
857
|
+
}
|
|
858
|
+
);
|
|
859
|
+
tablesProcessed = truncateResults.tablesProcessed;
|
|
860
|
+
|
|
861
|
+
return {
|
|
862
|
+
database: dbName,
|
|
863
|
+
success: true,
|
|
864
|
+
tablesProcessed,
|
|
865
|
+
dryRun,
|
|
866
|
+
};
|
|
867
|
+
} catch (error) {
|
|
868
|
+
return {
|
|
869
|
+
database: dbName,
|
|
870
|
+
success: false,
|
|
871
|
+
error: `Truncation failed: ${error.message}`,
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
} catch (error) {
|
|
875
|
+
return {
|
|
876
|
+
database: dbName,
|
|
877
|
+
success: false,
|
|
878
|
+
error: `Processing failed: ${error.message}`,
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Main function to truncate specified tables in all databases
|
|
885
|
+
*/
|
|
886
|
+
async function truncateTablesInAllDatabases() {
|
|
887
|
+
try {
|
|
888
|
+
Logger.info(colors.header("đī¸ Database Table Truncation Tool"));
|
|
889
|
+
Logger.info(colors.debug("ââââââââââââââââââââââââââââââââââââââââââ"));
|
|
890
|
+
|
|
891
|
+
// Parse arguments to get table names and target database
|
|
892
|
+
const options = parseArguments();
|
|
893
|
+
const { tableNames, targetDb, dryRun, noCascade, interactive } = options;
|
|
894
|
+
|
|
895
|
+
// Get database configurations (filtered by targetDb if specified)
|
|
896
|
+
const databaseConfigs = getDatabaseUrls(targetDb);
|
|
897
|
+
|
|
898
|
+
if (dryRun) {
|
|
899
|
+
Logger.info(colors.yellow("DRY RUN MODE - No tables will be truncated"));
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (noCascade) {
|
|
903
|
+
Logger.info(
|
|
904
|
+
colors.yellow("CASCADE option disabled for TRUNCATE statements")
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
if (!interactive) {
|
|
909
|
+
Logger.info(colors.cyan("Starting table truncation process..."));
|
|
910
|
+
Logger.info(
|
|
911
|
+
colors.yellow(`Tables to truncate: ${tableNames.join(", ")}`)
|
|
912
|
+
);
|
|
913
|
+
|
|
914
|
+
if (options.excludedTables.length > 0) {
|
|
915
|
+
Logger.info(
|
|
916
|
+
colors.yellow(
|
|
917
|
+
`Tables to exclude: ${options.excludedTables.join(", ")}`
|
|
918
|
+
)
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
} else {
|
|
922
|
+
Logger.info(
|
|
923
|
+
colors.cyan(
|
|
924
|
+
"Interactive mode enabled - you will select tables to truncate"
|
|
925
|
+
)
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
Logger.info(
|
|
930
|
+
colors.yellow(
|
|
931
|
+
`Databases to process: ${databaseConfigs
|
|
932
|
+
.map((db) => db.name)
|
|
933
|
+
.join(", ")}`
|
|
934
|
+
)
|
|
935
|
+
);
|
|
936
|
+
|
|
937
|
+
const results = [];
|
|
938
|
+
|
|
939
|
+
// Process each database sequentially
|
|
940
|
+
const dbProgressBar = Logger.progressBar(
|
|
941
|
+
databaseConfigs.length,
|
|
942
|
+
"Overall progress"
|
|
943
|
+
);
|
|
944
|
+
|
|
945
|
+
for (const dbConfig of databaseConfigs) {
|
|
946
|
+
const result = await truncateTablesInDatabase(
|
|
947
|
+
dbConfig,
|
|
948
|
+
tableNames,
|
|
949
|
+
options
|
|
950
|
+
);
|
|
951
|
+
results.push(result);
|
|
952
|
+
dbProgressBar.update();
|
|
953
|
+
|
|
954
|
+
// If the operation was cancelled, ask if user wants to continue with other DBs
|
|
955
|
+
if (result.cancelled && databaseConfigs.length > 1) {
|
|
956
|
+
const continueWithOthers = await confirmAction(
|
|
957
|
+
colors.warn("Continue with remaining databases?")
|
|
958
|
+
);
|
|
959
|
+
|
|
960
|
+
if (!continueWithOthers) {
|
|
961
|
+
Logger.info("Operation cancelled by user. Exiting...");
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
dbProgressBar.complete();
|
|
968
|
+
|
|
969
|
+
// Log summary
|
|
970
|
+
Logger.info(colors.cyan("\n=== Truncation Summary ==="));
|
|
971
|
+
const successful = results.filter((r) => r.success).length;
|
|
972
|
+
const failed = results.filter((r) => !r.success).length;
|
|
973
|
+
const totalTablesProcessed = results.reduce(
|
|
974
|
+
(sum, r) => sum + (r.tablesProcessed || 0),
|
|
975
|
+
0
|
|
976
|
+
);
|
|
977
|
+
|
|
978
|
+
results.forEach((result) => {
|
|
979
|
+
if (result.success) {
|
|
980
|
+
if (result.dryRun) {
|
|
981
|
+
Logger.info(
|
|
982
|
+
colors.yellow(
|
|
983
|
+
`đ ${result.database}: Would truncate ${result.tablesProcessed} tables (dry run)`
|
|
984
|
+
)
|
|
985
|
+
);
|
|
986
|
+
} else {
|
|
987
|
+
Logger.success(
|
|
988
|
+
`â
${result.database}: Successfully truncated ${
|
|
989
|
+
result.tablesProcessed || 0
|
|
990
|
+
} tables`
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
} else if (result.cancelled) {
|
|
994
|
+
Logger.warn(`âšī¸ ${result.database}: Operation cancelled by user`);
|
|
995
|
+
} else {
|
|
996
|
+
Logger.error(`â ${result.database}: Failed - ${result.error}`);
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
Logger.info(
|
|
1001
|
+
colors.cyan(
|
|
1002
|
+
`\nProcessed ${results.length} databases: ${successful} successful, ${failed} failed`
|
|
1003
|
+
)
|
|
1004
|
+
);
|
|
1005
|
+
|
|
1006
|
+
if (dryRun) {
|
|
1007
|
+
Logger.info(
|
|
1008
|
+
colors.yellow(
|
|
1009
|
+
`Would truncate ${totalTablesProcessed} tables across all databases (dry run)`
|
|
1010
|
+
)
|
|
1011
|
+
);
|
|
1012
|
+
} else {
|
|
1013
|
+
Logger.info(
|
|
1014
|
+
colors.cyan(
|
|
1015
|
+
`Truncated ${totalTablesProcessed} tables across all databases`
|
|
1016
|
+
)
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
Logger.info(colors.debug("ââââââââââââââââââââââââââââââââââââââââââ"));
|
|
1021
|
+
|
|
1022
|
+
if (failed > 0) {
|
|
1023
|
+
process.exit(1);
|
|
1024
|
+
}
|
|
1025
|
+
} catch (error) {
|
|
1026
|
+
Logger.error(colors.bold.red("Truncation process failed!"));
|
|
1027
|
+
|
|
1028
|
+
if (error instanceof TruncationError) {
|
|
1029
|
+
Logger.error(`Error code: ${error.code}`);
|
|
1030
|
+
Logger.error(`Message: ${error.message}`);
|
|
1031
|
+
|
|
1032
|
+
if (error.details && Object.keys(error.details).length > 0) {
|
|
1033
|
+
Logger.debug("Error details:", JSON.stringify(error.details, null, 2));
|
|
1034
|
+
}
|
|
1035
|
+
} else {
|
|
1036
|
+
Logger.error(`Unexpected error: ${error.message}`);
|
|
1037
|
+
Logger.debug(error.stack);
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
process.exit(1);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
// Execute the main function
|
|
1045
|
+
truncateTablesInAllDatabases().catch((e) => {
|
|
1046
|
+
console.error(colors.red(`Failed to truncate tables: ${e.message}`));
|
|
1047
|
+
process.exit(1);
|
|
1048
|
+
});
|