diff --git a/resources/202346gmc/stream/202346gmc.ytd b/resources/202346gmc/stream/202346gmc.ytd index 61be461d1..57bf74b26 100644 --- a/resources/202346gmc/stream/202346gmc.ytd +++ b/resources/202346gmc/stream/202346gmc.ytd @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:559961fc45f3a8fc7d34451faa81932ceccd09a4d314b29864e58f0848bbc9c2 -size 7562916 +oid sha256:7efaf8ae53d415046f3b47f92a4313ec3acf5e78988f63b23c4853a61e9c1bed +size 7894453 diff --git a/resources/[EGRP-CarPacks]/lafdbatt/__resource.lua b/resources/[EGRP-CarPacks]/lafdbatt/__resource.lua index bfbd7d0e8..8a8e37e1f 100644 --- a/resources/[EGRP-CarPacks]/lafdbatt/__resource.lua +++ b/resources/[EGRP-CarPacks]/lafdbatt/__resource.lua @@ -1,16 +1,13 @@ -resource_manifest_version '77731fab-63ca-442c-a67b-abc70f28dfa5' +resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937' files { - 'vehicles.meta', - 'carvariations.meta', - 'carcols.meta', - 'handling.meta', - 'vehiclelayouts.meta', + 'vehicles.meta', + 'carcols.meta', + 'carvariations.meta', + 'handling.meta' } - -data_file 'HANDLING_FILE' 'handling.meta' data_file 'VEHICLE_METADATA_FILE' 'vehicles.meta' data_file 'CARCOLS_FILE' 'carcols.meta' data_file 'VEHICLE_VARIATION_FILE' 'carvariations.meta' -data_file 'VEHICLE_LAYOUTS_FILE' 'vehiclelayouts.meta' +data_file 'HANDLING_FILE' 'data/handling.meta' diff --git a/resources/[EGRP-CarPacks]/lafdbatt/carcols.meta b/resources/[EGRP-CarPacks]/lafdbatt/carcols.meta index 444c821a4..ff8c7f17b 100644 --- a/resources/[EGRP-CarPacks]/lafdbatt/carcols.meta +++ b/resources/[EGRP-CarPacks]/lafdbatt/carcols.meta @@ -25,9 +25,9 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - lafdxt6700 + lafdbatt @@ -66,7 +66,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -75,7 +75,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -104,7 +104,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -113,7 +113,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -142,7 +142,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -151,7 +151,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -180,7 +180,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -189,7 +189,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -218,7 +218,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -227,7 +227,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -250,13 +250,127 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -265,7 +379,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -288,13 +402,13 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + @@ -303,7 +417,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -326,279 +440,13 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -607,7 +455,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -630,13 +478,51 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -645,7 +531,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -668,22 +554,22 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + - + - + - + @@ -706,22 +592,22 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + - + - + - + @@ -744,13 +630,13 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + @@ -759,7 +645,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -782,22 +668,22 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + - + - + - + @@ -808,45 +694,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -858,22 +706,22 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + - + - + - + @@ -884,7 +732,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -896,13 +744,13 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + @@ -911,7 +759,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -922,7 +770,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -934,13 +782,13 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + @@ -949,7 +797,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -960,7 +808,159 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -978,7 +978,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -987,7 +987,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1016,7 +1016,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1025,7 +1025,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1054,7 +1054,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1063,7 +1063,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1092,7 +1092,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1101,7 +1101,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1124,22 +1124,22 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + - + - + - + @@ -1150,7 +1150,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1162,22 +1162,22 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + - + - + - + @@ -1188,7 +1188,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1200,22 +1200,22 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + - + - + - + @@ -1226,7 +1226,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + @@ -1238,22 +1238,22 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + - + - + - + - + @@ -1264,7 +1264,7 @@ Documentation: https://doc.clickup.com/d/841f5-35/non-els-research/841f5-49/carc - + diff --git a/resources/[EGRP-CarPacks]/lafdbatt/carvariations.meta b/resources/[EGRP-CarPacks]/lafdbatt/carvariations.meta index 730c98118..dccb98312 100644 --- a/resources/[EGRP-CarPacks]/lafdbatt/carvariations.meta +++ b/resources/[EGRP-CarPacks]/lafdbatt/carvariations.meta @@ -1,116 +1,183 @@ - + - - + + + + + + + + + + + + + lafdbatt + - lafdxt6700 - - - - 0 - 0 - 156 - 156 - - - - - - - - - - - - - - - 0 - 0 - 156 - 156 - - - - - - - - - - - - - - - 0 - 0 - 156 - 156 - - - - - - - - - - - - - - - 0 - 0 - 156 - 156 - - - - - - - - - - - - - - - 0 - 0 - 156 - 156 - - - - - - - - - - - - - - - 0_default_modkit - - - - - - police guv plate - - - - - - + + 134 + 134 + 0 + 0 + + + + + + + + + + + - + + + 134 + 134 + 0 + 0 + + + + + + + + + + + + + + + 134 + 134 + 0 + 0 + + + + + + + + + + + + + + + 134 + 134 + 0 + 0 + + + + + + + + + + + + + + + 134 + 134 + 0 + 0 + + + + + + + + + + + + + + 134 + 134 + 0 + 0 + + + + + + + + + + + + + + + 134 + 134 + 0 + 0 + + + + + + + + + + + + + + + 134 + 134 + 0 + 0 + + + + + + + + + + + + + + + 0_default_modkit + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/[EGRP-CarPacks]/lafdbatt/handling.meta b/resources/[EGRP-CarPacks]/lafdbatt/handling.meta index 656745509..490dbea45 100644 --- a/resources/[EGRP-CarPacks]/lafdbatt/handling.meta +++ b/resources/[EGRP-CarPacks]/lafdbatt/handling.meta @@ -1,105 +1,67 @@ - + + - - lafdxt6700 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 48 + + lafdbatt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 440010 0 0 AVERAGE - - - VEHICLE_WEAPON_WATER_CANNON - - - - - 0 - 0 - 0 - - - 3.000000 - 0.000000 - - - -0.400000 - 0.000000 - - - 0.707000 - 0.000000 - - - -0.500000 - 0.000000 - - - 0.000000 - 0.000000 - - - 25.000000 - 0.000000 - - - -0.080000 - 0.000000 - - - - + + + + - + \ No newline at end of file diff --git a/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt.yft b/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt.yft new file mode 100644 index 000000000..c3ae8edcf --- /dev/null +++ b/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt.yft @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85179e97c4e1094e03ae8c8bc7df4da37dd5fc06f12c56126b0f6ef91cbece8b +size 9867879 diff --git a/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt.ytd b/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt.ytd new file mode 100644 index 000000000..4470976fd --- /dev/null +++ b/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2b40f42fc0b12367afa433ae86a72b3f44729108c96eb574926f1d9ab915eac +size 10075210 diff --git a/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt_hi.yft b/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt_hi.yft new file mode 100644 index 000000000..dff40de8f --- /dev/null +++ b/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdbatt_hi.yft @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10eb2d79e448b8cc774f6ea8213de6c2e57e593ab7d57b6710210c7f4715f9bd +size 9867802 diff --git a/resources/[EGRP-CarPacks]/lafdbatt/vehicles.meta b/resources/[EGRP-CarPacks]/lafdbatt/vehicles.meta index c099db96a..3628acd8f 100644 --- a/resources/[EGRP-CarPacks]/lafdbatt/vehicles.meta +++ b/resources/[EGRP-CarPacks]/lafdbatt/vehicles.meta @@ -1,86 +1,86 @@ - + vehshare - - lafdxt6700 - lafdxt6700 - lafdxt6700 - lafdxt6700 - + + lafdbatt + lafdbatt + lafdbatt + lafdbatt + lafdbatt null null null null - veh_barrage - FIRETRUK - LAYOUT_FIRETRUCK - SHERIFF_COVER_OFFSET_INFO + null + SADLER + LAYOUT_BISON + BISON_COVER_OFFSET_INFO EXPLOSION_INFO_DEFAULT DEFAULT_FOLLOW_VEHICLE_CAMERA DEFAULT_THIRD_PERSON_VEHICLE_AIM_CAMERA - VEHICLE_BONNET_CAMERA_MID_HIGH + VEHICLE_BONNET_CAMERA_STANDARD DEFAULT_POV_CAMERA - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - - - - - + + + + + - - + + VFXVEHICLEINFO_CAR_GENERIC - - + + - - - - + + + + - + - + - + - 1000.000000 - 1500.000000 - 4500.000000 - 7000.000000 - 14000.000000 - 20000.000000 + 15.000000 + 30.000000 + 70.000000 + 140.000000 + 500.000000 + 500.000000 - + @@ -90,17 +90,31 @@ SWANKNESS_1 - + FLAG_HAS_LIVERY FLAG_EXTRAS_STRONG FLAG_EXTRAS_REQUIRE FLAG_LAW_ENFORCEMENT FLAG_EMERGENCY_SERVICE FLAG_HAS_INTERIOR_EXTRAS FLAG_NO_RESPRAY VEHICLE_TYPE_CAR VPT_FRONT_AND_BACK_PLATES - VDT_GENTAXI + VDT_ZTYPE VC_EMERGENCY - VWT_MUSCLE - + VWT_SUV + + boattrailer + trailersmall + + + trailersmall2 + - - S_M_Y_Fireman_01 + + S_M_M_AutoShop_01 + + + + S_M_M_AutoShop_02 + + + + S_M_M_Trucker_01 @@ -110,35 +124,29 @@ - - REWARD_STAT_WEAPON - + WHEEL_FRONT_RIGHT_CAMERA WHEEL_FRONT_LEFT_CAMERA WHEEL_REAR_RIGHT_CAMERA WHEEL_REAR_LEFT_CAMERA - + Truck - STD_POLICE_FRONT_LEFT - STD_POLICE_FRONT_RIGHT - STD_POLICE_REAR_LEFT - STD_POLICE_REAR_RIGHT + RANGER_BISON_FRONT_LEFT + VAN_RUMPO_FRONT_RIGHT + RANGER_BISON_REAR_LEFT + RANGER_BISON_REAR_RIGHT - - - - - vehshare_truck - lafdxt6700 - - vehicles_poltax_interior - lafdxt6700 + + + + vehicles_bob_brown_interior + lafdbatt \ No newline at end of file diff --git a/resources/[EGRP-CarPacks]/lafdbattT/__resource.lua b/resources/[EGRP-CarPacks]/lafdbattT/__resource.lua new file mode 100644 index 000000000..bfbd7d0e8 --- /dev/null +++ b/resources/[EGRP-CarPacks]/lafdbattT/__resource.lua @@ -0,0 +1,16 @@ +resource_manifest_version '77731fab-63ca-442c-a67b-abc70f28dfa5' + + +files { + 'vehicles.meta', + 'carvariations.meta', + 'carcols.meta', + 'handling.meta', + 'vehiclelayouts.meta', +} + +data_file 'HANDLING_FILE' 'handling.meta' +data_file 'VEHICLE_METADATA_FILE' 'vehicles.meta' +data_file 'CARCOLS_FILE' 'carcols.meta' +data_file 'VEHICLE_VARIATION_FILE' 'carvariations.meta' +data_file 'VEHICLE_LAYOUTS_FILE' 'vehiclelayouts.meta' diff --git a/resources/[EGRP-CarPacks]/lafdbattT/carcols.meta b/resources/[EGRP-CarPacks]/lafdbattT/carcols.meta new file mode 100644 index 000000000..444c821a4 --- /dev/null +++ b/resources/[EGRP-CarPacks]/lafdbattT/carcols.meta @@ -0,0 +1,1281 @@ + + + + + + + + + + + + + + lafdxt6700 + + + + + + + + VehicleLight_sirenlight + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/[EGRP-CarPacks]/lafdbattT/carvariations.meta b/resources/[EGRP-CarPacks]/lafdbattT/carvariations.meta new file mode 100644 index 000000000..730c98118 --- /dev/null +++ b/resources/[EGRP-CarPacks]/lafdbattT/carvariations.meta @@ -0,0 +1,116 @@ + + + + + + + lafdxt6700 + + + + 0 + 0 + 156 + 156 + + + + + + + + + + + + + + + 0 + 0 + 156 + 156 + + + + + + + + + + + + + + + 0 + 0 + 156 + 156 + + + + + + + + + + + + + + + 0 + 0 + 156 + 156 + + + + + + + + + + + + + + + 0 + 0 + 156 + 156 + + + + + + + + + + + + + + + 0_default_modkit + + + + + + police guv plate + + + + + + + + + \ No newline at end of file diff --git a/resources/[EGRP-CarPacks]/lafdbattT/handling.meta b/resources/[EGRP-CarPacks]/lafdbattT/handling.meta new file mode 100644 index 000000000..656745509 --- /dev/null +++ b/resources/[EGRP-CarPacks]/lafdbattT/handling.meta @@ -0,0 +1,105 @@ + + + + + lafdxt6700 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 48 + 0 + 0 + AVERAGE + + + + VEHICLE_WEAPON_WATER_CANNON + + + + + 0 + 0 + 0 + + + 3.000000 + 0.000000 + + + -0.400000 + 0.000000 + + + 0.707000 + 0.000000 + + + -0.500000 + 0.000000 + + + 0.000000 + 0.000000 + + + 25.000000 + 0.000000 + + + -0.080000 + 0.000000 + + + + + + + + + + + \ No newline at end of file diff --git a/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdxt6700.yft b/resources/[EGRP-CarPacks]/lafdbattT/stream/lafdxt6700.yft similarity index 100% rename from resources/[EGRP-CarPacks]/lafdbatt/stream/lafdxt6700.yft rename to resources/[EGRP-CarPacks]/lafdbattT/stream/lafdxt6700.yft diff --git a/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdxt6700.ytd b/resources/[EGRP-CarPacks]/lafdbattT/stream/lafdxt6700.ytd similarity index 100% rename from resources/[EGRP-CarPacks]/lafdbatt/stream/lafdxt6700.ytd rename to resources/[EGRP-CarPacks]/lafdbattT/stream/lafdxt6700.ytd diff --git a/resources/[EGRP-CarPacks]/lafdbatt/stream/lafdxt6700_hi.yft b/resources/[EGRP-CarPacks]/lafdbattT/stream/lafdxt6700_hi.yft similarity index 100% rename from resources/[EGRP-CarPacks]/lafdbatt/stream/lafdxt6700_hi.yft rename to resources/[EGRP-CarPacks]/lafdbattT/stream/lafdxt6700_hi.yft diff --git a/resources/[EGRP-CarPacks]/lafdbattT/vehicles.meta b/resources/[EGRP-CarPacks]/lafdbattT/vehicles.meta new file mode 100644 index 000000000..c099db96a --- /dev/null +++ b/resources/[EGRP-CarPacks]/lafdbattT/vehicles.meta @@ -0,0 +1,144 @@ + + + vehshare + + + + lafdxt6700 + lafdxt6700 + lafdxt6700 + lafdxt6700 + + null + null + null + null + + veh_barrage + FIRETRUK + LAYOUT_FIRETRUCK + SHERIFF_COVER_OFFSET_INFO + EXPLOSION_INFO_DEFAULT + + DEFAULT_FOLLOW_VEHICLE_CAMERA + DEFAULT_THIRD_PERSON_VEHICLE_AIM_CAMERA + VEHICLE_BONNET_CAMERA_MID_HIGH + DEFAULT_POV_CAMERA + + + + + + + + + + + + + + + + + + + + + + + + + + + + VFXVEHICLEINFO_CAR_GENERIC + + + + + + + + + + + + + + + + + + + + + + 1000.000000 + 1500.000000 + 4500.000000 + 7000.000000 + 14000.000000 + 20000.000000 + + + + + + + + + + + SWANKNESS_1 + + FLAG_HAS_LIVERY FLAG_EXTRAS_STRONG FLAG_EXTRAS_REQUIRE FLAG_LAW_ENFORCEMENT FLAG_EMERGENCY_SERVICE FLAG_HAS_INTERIOR_EXTRAS FLAG_NO_RESPRAY + VEHICLE_TYPE_CAR + VPT_FRONT_AND_BACK_PLATES + VDT_GENTAXI + VC_EMERGENCY + VWT_MUSCLE + + + + S_M_Y_Fireman_01 + + + + + + + + + + + REWARD_STAT_WEAPON + + + WHEEL_FRONT_RIGHT_CAMERA + WHEEL_FRONT_LEFT_CAMERA + WHEEL_REAR_RIGHT_CAMERA + WHEEL_REAR_LEFT_CAMERA + + + + + + + STD_POLICE_FRONT_LEFT + STD_POLICE_FRONT_RIGHT + STD_POLICE_REAR_LEFT + STD_POLICE_REAR_RIGHT + + + + + + vehshare_truck + lafdxt6700 + + + vehicles_poltax_interior + lafdxt6700 + + + \ No newline at end of file diff --git a/resources/firef250/stream/firef250.ytd b/resources/firef250/stream/firef250.ytd index fab6eba85..30083611b 100644 --- a/resources/firef250/stream/firef250.ytd +++ b/resources/firef250/stream/firef250.ytd @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5333921c3aedce002a947bbc96daf8740e55ecbb01c32e45df0218a46d2db500 -size 7211940 +oid sha256:af64ab02267c0dde59f699bc5ffd91d6ebe96b5a201698c60e84b828e6161690 +size 7586858 diff --git a/resources/lvc/SIRENS.lua b/resources/lvc/SIRENS.lua index 1151710d2..3ae958c0c 100644 --- a/resources/lvc/SIRENS.lua +++ b/resources/lvc/SIRENS.lua @@ -257,7 +257,7 @@ SIREN_ASSIGNMENTS = { ['lafd20tahoeumk'] = { 60, 61, 62, 63, 64, 65 }, ['lafdcharger18'] = { 60, 61, 62, 63, 64, 65 }, ['lafirechief'] = { 60, 61, 62, 63, 64, 65 }, - + ['firef250'] = { 60, 61, 62, 63, 64, 65 }, ['19mustgtbb'] = { 33, 34, 35, 36, 37, 38 }, diff --git a/resources/radio/.fxap b/resources/radio/.fxap new file mode 100644 index 000000000..3f30a08ed Binary files /dev/null and b/resources/radio/.fxap differ diff --git a/resources/radio/audio.lua b/resources/radio/audio.lua new file mode 100644 index 000000000..06d70dcfe Binary files /dev/null and b/resources/radio/audio.lua differ diff --git a/resources/radio/blips.lua b/resources/radio/blips.lua new file mode 100644 index 000000000..eb3130fa4 Binary files /dev/null and b/resources/radio/blips.lua differ diff --git a/resources/radio/client.js b/resources/radio/client.js deleted file mode 100644 index 294251dc2..000000000 --- a/resources/radio/client.js +++ /dev/null @@ -1,89 +0,0 @@ -const customRadios = []; -let isPlaying = false; -let index = -1; -let volume = GetProfileSetting(306) / 10; -let previousVolume = volume; - -for (let i = 0, length = GetNumResourceMetadata("radio", "supersede_radio"); i < length; i++) { - const radio = GetResourceMetadata("radio", "supersede_radio", i); - - if (!availableRadios.includes(radio)) { - console.error(`radio: ${radio} is an invalid radio.`); - continue; - } - - try { - const data = JSON.parse(GetResourceMetadata("radio", "supersede_radio_extra", i)); - if (data !== null) { - customRadios.push({ - "isPlaying": false, - "name": radio, - "data": data - }); - if (data.name) { - AddTextEntry(radio, data.name); - } - } else { - console.error(`radio: Missing data for ${radio}.`); - } - } catch (e) { - console.error(e); - } -} - -RegisterNuiCallbackType("radio:ready"); -on("__cfx_nui:radio:ready", (data, cb) => { - SendNuiMessage(JSON.stringify({ "type": "create", "radios": customRadios, "volume": volume })); - previousVolume = -1; -}); -SendNuiMessage(JSON.stringify({ "type": "create", "radios": customRadios, "volume": volume })); - -const PlayCustomRadio = (radio) => { - isPlaying = true; - index = customRadios.indexOf(radio); - ToggleCustomRadioBehavior(); - SendNuiMessage(JSON.stringify({ "type": "play", "radio": radio.name })); -}; - -const StopCustomRadios = () => { - isPlaying = false; - ToggleCustomRadioBehavior(); - SendNuiMessage(JSON.stringify({ "type": "stop" })); -}; - -const ToggleCustomRadioBehavior = () => { - SetFrontendRadioActive(!isPlaying); - - if (isPlaying) { - StartAudioScene("DLC_MPHEIST_TRANSITION_TO_APT_FADE_IN_RADIO_SCENE"); - } else { - StopAudioScene("DLC_MPHEIST_TRANSITION_TO_APT_FADE_IN_RADIO_SCENE"); - } -}; - -setTick(() => { - if (IsPlayerVehicleRadioEnabled()) { - let playerRadioStationName = GetPlayerRadioStationName(); - - let customRadio = customRadios.find((radio) => { - return radio.name === playerRadioStationName; - }); - - if (!isPlaying && customRadio) { - PlayCustomRadio(customRadio); - } else if (isPlaying && customRadio && customRadios.indexOf(customRadio) !== index) { - StopCustomRadios(); - PlayCustomRadio(customRadio); - } else if (isPlaying && !customRadio) { - StopCustomRadios(); - } - } else if (isPlaying) { - StopCustomRadios(); - } - - volume = GetProfileSetting(306) / 10; - if (previousVolume !== volume) { - SendNuiMessage(JSON.stringify({ "type": "volume", "volume": volume })); - previousVolume = volume; - } -}); \ No newline at end of file diff --git a/resources/radio/client/dist/bundle.js b/resources/radio/client/dist/bundle.js new file mode 100644 index 000000000..29bc14346 --- /dev/null +++ b/resources/radio/client/dist/bundle.js @@ -0,0 +1,48 @@ +(()=>{var eG=Object.create;var{getPrototypeOf:JK,defineProperty:KY,getOwnPropertyNames:F8,getOwnPropertyDescriptor:YK}=Object,R8=Object.prototype.hasOwnProperty;var IZ=(J,Y,G)=>{G=J!=null?eG(JK(J)):{};let W=Y||!J||!J.__esModule?KY(G,"default",{value:J,enumerable:!0}):G;for(let O of F8(J))if(!R8.call(W,O))KY(W,O,{get:()=>J[O],enumerable:!0});return W},q8=new WeakMap,ZK=(J)=>{var Y=q8.get(J),G;if(Y)return Y;if(Y=KY({},"__esModule",{value:!0}),J&&typeof J==="object"||typeof J==="function")F8(J).map((W)=>!R8.call(Y,W)&&KY(Y,W,{get:()=>J[W],enumerable:!(G=YK(J,W))||G.enumerable}));return q8.set(J,Y),Y},$0=(J,Y)=>()=>(Y||J((Y={exports:{}}).exports,Y),Y.exports);var GK=(J,Y)=>{for(var G in Y)KY(J,G,{get:Y[G],enumerable:!0,configurable:!0,set:(W)=>Y[G]=()=>W})};var A8=$0((N8,kY)=>{/*! + * jQuery JavaScript Library v3.7.1 + * https://jquery.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2023-08-28T13:37Z + */(function(J,Y){if(typeof kY==="object"&&typeof kY.exports==="object")kY.exports=J.document?Y(J,!0):function(G){if(!G.document)throw Error("jQuery requires a window with a document");return Y(G)};else Y(J)})(typeof window<"u"?window:N8,function(J,Y){var G=[],W=Object.getPrototypeOf,O=G.slice,A=G.flat?function(Z){return G.flat.call(Z)}:function(Z){return G.concat.apply([],Z)},Q=G.push,S=G.indexOf,E={},k=E.toString,X=E.hasOwnProperty,$=X.toString,R=$.call(Object),H={},P=function(K){return typeof K==="function"&&typeof K.nodeType!=="number"&&typeof K.item!=="function"},I=function(K){return K!=null&&K===K.window},D=J.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function n(Z,K,z){z=z||D;var U,B,q=z.createElement("script");if(q.text=Z,K){for(U in c)if(B=K[U]||K.getAttribute&&K.getAttribute(U),B)q.setAttribute(U,B)}z.head.appendChild(q).parentNode.removeChild(q)}function K0(Z){if(Z==null)return Z+"";return typeof Z==="object"||typeof Z==="function"?E[k.call(Z)]||"object":typeof Z}var S0="3.7.1",p0=/HTML$/i,V=function(Z,K){return new V.fn.init(Z,K)};if(V.fn=V.prototype={jquery:S0,constructor:V,length:0,toArray:function(){return O.call(this)},get:function(Z){if(Z==null)return O.call(this);return Z<0?this[Z+this.length]:this[Z]},pushStack:function(Z){var K=V.merge(this.constructor(),Z);return K.prevObject=this,K},each:function(Z){return V.each(this,Z)},map:function(Z){return this.pushStack(V.map(this,function(K,z){return Z.call(K,z,K)}))},slice:function(){return this.pushStack(O.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(V.grep(this,function(Z,K){return(K+1)%2}))},odd:function(){return this.pushStack(V.grep(this,function(Z,K){return K%2}))},eq:function(Z){var K=this.length,z=+Z+(Z<0?K:0);return this.pushStack(z>=0&&z0&&K-1 in Z}function a(Z,K){return Z.nodeName&&Z.nodeName.toLowerCase()===K.toLowerCase()}var{pop:N1,sort:t1,splice:m1}=G,Z0="[\\x20\\t\\r\\n\\f]",y=new RegExp("^"+Z0+"+|((?:^|[^\\\\])(?:\\\\.)*)"+Z0+"+$","g");V.contains=function(Z,K){var z=K&&K.parentNode;return Z===z||!!(z&&z.nodeType===1&&(Z.contains?Z.contains(z):Z.compareDocumentPosition&&Z.compareDocumentPosition(z)&16))};var U0=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;function L0(Z,K){if(K){if(Z==="\x00")return"�";return Z.slice(0,-1)+"\\"+Z.charCodeAt(Z.length-1).toString(16)+" "}return"\\"+Z}V.escapeSelector=function(Z){return(Z+"").replace(U0,L0)};var W1=D,_J=Q;(function(){var Z,K,z,U,B,q=_J,N,C,_,T,b,h=V.expando,j=0,f=0,J0=TY(),V0=TY(),G0=TY(),j0=TY(),T0=function(M,L){if(M===L)B=!0;return 0},M1="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",E1="(?:\\\\[\\da-fA-F]{1,6}"+Z0+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\x00-\\x7f])+",z0="\\["+Z0+"*("+E1+")(?:"+Z0+"*([*^$|!~]?=)"+Z0+`*(?:'((?:\\\\.|[^\\\\'])*)'|"((?:\\\\.|[^\\\\"])*)"|(`+E1+"))|)"+Z0+"*\\]",ZJ=":("+E1+`)(?:\\((('((?:\\\\.|[^\\\\'])*)'|"((?:\\\\.|[^\\\\"])*)")|((?:\\\\.|[^\\\\()[\\]]|`+z0+")*)|.*)\\)|)",B0=new RegExp(Z0+"+","g"),Q0=new RegExp("^"+Z0+"*,"+Z0+"*"),YY=new RegExp("^"+Z0+"*([>+~]|"+Z0+")"+Z0+"*"),SZ=new RegExp(Z0+"|>"),_1=new RegExp(ZJ),ZY=new RegExp("^"+E1+"$"),S1={ID:new RegExp("^#("+E1+")"),CLASS:new RegExp("^\\.("+E1+")"),TAG:new RegExp("^("+E1+"|[*])"),ATTR:new RegExp("^"+z0),PSEUDO:new RegExp("^"+ZJ),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+Z0+"*(even|odd|(([+-]|)(\\d*)n|)"+Z0+"*(?:([+-]|)"+Z0+"*(\\d+)|))"+Z0+"*\\)|)","i"),bool:new RegExp("^(?:"+M1+")$","i"),needsContext:new RegExp("^"+Z0+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+Z0+"*((?:-\\d)?\\d*)"+Z0+"*\\)|)(?=[^-]|$)","i")},p1=/^(?:input|select|textarea|button)$/i,u1=/^h\d$/i,J1=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,PZ=/[+~]/,x1=new RegExp("\\\\[\\da-fA-F]{1,6}"+Z0+"?|\\\\([^\\r\\n\\f])","g"),b1=function(M,L){var w="0x"+M.slice(1)-65536;if(L)return L;return w<0?String.fromCharCode(w+65536):String.fromCharCode(w>>10|55296,w&1023|56320)},lG=function(){c1()},nG=wY(function(M){return M.disabled===!0&&a(M,"fieldset")},{dir:"parentNode",next:"legend"});function sG(){try{return N.activeElement}catch(M){}}try{q.apply(G=O.call(W1.childNodes),W1.childNodes),G[W1.childNodes.length].nodeType}catch(M){q={apply:function(L,w){_J.apply(L,O.call(w))},call:function(L){_J.apply(L,O.call(arguments,1))}}}function R0(M,L,w,x){var v,p,d,s,i,W0,e,Y0=L&&L.ownerDocument,X0=L?L.nodeType:9;if(w=w||[],typeof M!=="string"||!M||X0!==1&&X0!==9&&X0!==11)return w;if(!x){if(c1(L),L=L||N,_){if(X0!==11&&(i=J1.exec(M))){if(v=i[1]){if(X0===9)if(d=L.getElementById(v)){if(d.id===v)return q.call(w,d),w}else return w;else if(Y0&&(d=Y0.getElementById(v))&&R0.contains(L,d)&&d.id===v)return q.call(w,d),w}else if(i[2])return q.apply(w,L.getElementsByTagName(M)),w;else if((v=i[3])&&L.getElementsByClassName)return q.apply(w,L.getElementsByClassName(v)),w}if(!j0[M+" "]&&(!T||!T.test(M))){if(e=M,Y0=L,X0===1&&(SZ.test(M)||YY.test(M))){if(Y0=PZ.test(M)&&CZ(L.parentNode)||L,Y0!=L||!H.scope)if(s=L.getAttribute("id"))s=V.escapeSelector(s);else L.setAttribute("id",s=h);W0=GY(M),p=W0.length;while(p--)W0[p]=(s?"#"+s:":scope")+" "+IY(W0[p]);e=W0.join(",")}try{return q.apply(w,Y0.querySelectorAll(e)),w}catch(o){j0(M,!0)}finally{if(s===h)L.removeAttribute("id")}}}}return B8(M.replace(y,"$1"),L,w,x)}function TY(){var M=[];function L(w,x){if(M.push(w+" ")>K.cacheLength)delete L[M.shift()];return L[w+" "]=x}return L}function $1(M){return M[h]=!0,M}function IJ(M){var L=N.createElement("fieldset");try{return!!M(L)}catch(w){return!1}finally{if(L.parentNode)L.parentNode.removeChild(L);L=null}}function aG(M){return function(L){return a(L,"input")&&L.type===M}}function rG(M){return function(L){return(a(L,"input")||a(L,"button"))&&L.type===M}}function V8(M){return function(L){if("form"in L){if(L.parentNode&&L.disabled===!1){if("label"in L)if("label"in L.parentNode)return L.parentNode.disabled===M;else return L.disabled===M;return L.isDisabled===M||L.isDisabled!==!M&&nG(L)===M}return L.disabled===M}else if("label"in L)return L.disabled===M;return!1}}function GJ(M){return $1(function(L){return L=+L,$1(function(w,x){var v,p=M([],w.length,L),d=p.length;while(d--)if(w[v=p[d]])w[v]=!(x[v]=w[v])})})}function CZ(M){return M&&typeof M.getElementsByTagName<"u"&&M}function c1(M){var L,w=M?M.ownerDocument||M:W1;if(w==N||w.nodeType!==9||!w.documentElement)return N;if(N=w,C=N.documentElement,_=!V.isXMLDoc(N),b=C.matches||C.webkitMatchesSelector||C.msMatchesSelector,C.msMatchesSelector&&W1!=N&&(L=N.defaultView)&&L.top!==L)L.addEventListener("unload",lG);if(H.getById=IJ(function(x){return C.appendChild(x).id=V.expando,!N.getElementsByName||!N.getElementsByName(V.expando).length}),H.disconnectedMatch=IJ(function(x){return b.call(x,"*")}),H.scope=IJ(function(){return N.querySelectorAll(":scope")}),H.cssHas=IJ(function(){try{return N.querySelector(":has(*,:jqfake)"),!1}catch(x){return!0}}),H.getById)K.filter.ID=function(x){var v=x.replace(x1,b1);return function(p){return p.getAttribute("id")===v}},K.find.ID=function(x,v){if(typeof v.getElementById<"u"&&_){var p=v.getElementById(x);return p?[p]:[]}};else K.filter.ID=function(x){var v=x.replace(x1,b1);return function(p){var d=typeof p.getAttributeNode<"u"&&p.getAttributeNode("id");return d&&d.value===v}},K.find.ID=function(x,v){if(typeof v.getElementById<"u"&&_){var p,d,s,i=v.getElementById(x);if(i){if(p=i.getAttributeNode("id"),p&&p.value===x)return[i];s=v.getElementsByName(x),d=0;while(i=s[d++])if(p=i.getAttributeNode("id"),p&&p.value===x)return[i]}return[]}};if(K.find.TAG=function(x,v){if(typeof v.getElementsByTagName<"u")return v.getElementsByTagName(x);else return v.querySelectorAll(x)},K.find.CLASS=function(x,v){if(typeof v.getElementsByClassName<"u"&&_)return v.getElementsByClassName(x)},T=[],IJ(function(x){var v;if(C.appendChild(x).innerHTML="",!x.querySelectorAll("[selected]").length)T.push("\\["+Z0+"*(?:value|"+M1+")");if(!x.querySelectorAll("[id~="+h+"-]").length)T.push("~=");if(!x.querySelectorAll("a#"+h+"+*").length)T.push(".#.+[+~]");if(!x.querySelectorAll(":checked").length)T.push(":checked");if(v=N.createElement("input"),v.setAttribute("type","hidden"),x.appendChild(v).setAttribute("name","D"),C.appendChild(x).disabled=!0,x.querySelectorAll(":disabled").length!==2)T.push(":enabled",":disabled");if(v=N.createElement("input"),v.setAttribute("name",""),x.appendChild(v),!x.querySelectorAll("[name='']").length)T.push("\\["+Z0+"*name"+Z0+"*="+Z0+`*(?:''|"")`)}),!H.cssHas)T.push(":has");return T=T.length&&new RegExp(T.join("|")),T0=function(x,v){if(x===v)return B=!0,0;var p=!x.compareDocumentPosition-!v.compareDocumentPosition;if(p)return p;if(p=(x.ownerDocument||x)==(v.ownerDocument||v)?x.compareDocumentPosition(v):1,p&1||!H.sortDetached&&v.compareDocumentPosition(x)===p){if(x===N||x.ownerDocument==W1&&R0.contains(W1,x))return-1;if(v===N||v.ownerDocument==W1&&R0.contains(W1,v))return 1;return U?S.call(U,x)-S.call(U,v):0}return p&4?-1:1},N}R0.matches=function(M,L){return R0(M,null,null,L)},R0.matchesSelector=function(M,L){if(c1(M),_&&!j0[L+" "]&&(!T||!T.test(L)))try{var w=b.call(M,L);if(w||H.disconnectedMatch||M.document&&M.document.nodeType!==11)return w}catch(x){j0(L,!0)}return R0(L,N,null,[M]).length>0},R0.contains=function(M,L){if((M.ownerDocument||M)!=N)c1(M);return V.contains(M,L)},R0.attr=function(M,L){if((M.ownerDocument||M)!=N)c1(M);var w=K.attrHandle[L.toLowerCase()],x=w&&X.call(K.attrHandle,L.toLowerCase())?w(M,L,!_):void 0;if(x!==void 0)return x;return M.getAttribute(L)},R0.error=function(M){throw Error("Syntax error, unrecognized expression: "+M)},V.uniqueSort=function(M){var L,w=[],x=0,v=0;if(B=!H.sortStable,U=!H.sortStable&&O.call(M,0),t1.call(M,T0),B){while(L=M[v++])if(L===M[v])x=w.push(v);while(x--)m1.call(M,w[x],1)}return U=null,M},V.fn.uniqueSort=function(){return this.pushStack(V.uniqueSort(O.apply(this)))},K=V.expr={cacheLength:50,createPseudo:$1,match:S1,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(M){if(M[1]=M[1].replace(x1,b1),M[3]=(M[3]||M[4]||M[5]||"").replace(x1,b1),M[2]==="~=")M[3]=" "+M[3]+" ";return M.slice(0,4)},CHILD:function(M){if(M[1]=M[1].toLowerCase(),M[1].slice(0,3)==="nth"){if(!M[3])R0.error(M[0]);M[4]=+(M[4]?M[5]+(M[6]||1):2*(M[3]==="even"||M[3]==="odd")),M[5]=+(M[7]+M[8]||M[3]==="odd")}else if(M[3])R0.error(M[0]);return M},PSEUDO:function(M){var L,w=!M[6]&&M[2];if(S1.CHILD.test(M[0]))return null;if(M[3])M[2]=M[4]||M[5]||"";else if(w&&_1.test(w)&&(L=GY(w,!0))&&(L=w.indexOf(")",w.length-L)-w.length))M[0]=M[0].slice(0,L),M[2]=w.slice(0,L);return M.slice(0,3)}},filter:{TAG:function(M){var L=M.replace(x1,b1).toLowerCase();return M==="*"?function(){return!0}:function(w){return a(w,L)}},CLASS:function(M){var L=J0[M+" "];return L||(L=new RegExp("(^|"+Z0+")"+M+"("+Z0+"|$)"))&&J0(M,function(w){return L.test(typeof w.className==="string"&&w.className||typeof w.getAttribute<"u"&&w.getAttribute("class")||"")})},ATTR:function(M,L,w){return function(x){var v=R0.attr(x,M);if(v==null)return L==="!=";if(!L)return!0;if(v+="",L==="=")return v===w;if(L==="!=")return v!==w;if(L==="^=")return w&&v.indexOf(w)===0;if(L==="*=")return w&&v.indexOf(w)>-1;if(L==="$=")return w&&v.slice(-w.length)===w;if(L==="~=")return(" "+v.replace(B0," ")+" ").indexOf(w)>-1;if(L==="|=")return v===w||v.slice(0,w.length+1)===w+"-";return!1}},CHILD:function(M,L,w,x,v){var p=M.slice(0,3)!=="nth",d=M.slice(-4)!=="last",s=L==="of-type";return x===1&&v===0?function(i){return!!i.parentNode}:function(i,W0,e){var Y0,X0,o,M0,i0,h0=p!==d?"nextSibling":"previousSibling",Y1=i.parentNode,P1=s&&i.nodeName.toLowerCase(),wJ=!e&&!s,f0=!1;if(Y1){if(p){while(h0){o=i;while(o=o[h0])if(s?a(o,P1):o.nodeType===1)return!1;i0=h0=M==="only"&&!i0&&"nextSibling"}return!0}if(i0=[d?Y1.firstChild:Y1.lastChild],d&&wJ){X0=Y1[h]||(Y1[h]={}),Y0=X0[M]||[],M0=Y0[0]===j&&Y0[1],f0=M0&&Y0[2],o=M0&&Y1.childNodes[M0];while(o=++M0&&o&&o[h0]||(f0=M0=0)||i0.pop())if(o.nodeType===1&&++f0&&o===i){X0[M]=[j,M0,f0];break}}else{if(wJ)X0=i[h]||(i[h]={}),Y0=X0[M]||[],M0=Y0[0]===j&&Y0[1],f0=M0;if(f0===!1){while(o=++M0&&o&&o[h0]||(f0=M0=0)||i0.pop())if((s?a(o,P1):o.nodeType===1)&&++f0){if(wJ)X0=o[h]||(o[h]={}),X0[M]=[j,f0];if(o===i)break}}}return f0-=v,f0===x||f0%x===0&&f0/x>=0}}},PSEUDO:function(M,L){var w,x=K.pseudos[M]||K.setFilters[M.toLowerCase()]||R0.error("unsupported pseudo: "+M);if(x[h])return x(L);if(x.length>1)return w=[M,M,"",L],K.setFilters.hasOwnProperty(M.toLowerCase())?$1(function(v,p){var d,s=x(v,L),i=s.length;while(i--)d=S.call(v,s[i]),v[d]=!(p[d]=s[i])}):function(v){return x(v,0,w)};return x}},pseudos:{not:$1(function(M){var L=[],w=[],x=TZ(M.replace(y,"$1"));return x[h]?$1(function(v,p,d,s){var i,W0=x(v,null,s,[]),e=v.length;while(e--)if(i=W0[e])v[e]=!(p[e]=i)}):function(v,p,d){return L[0]=v,x(L,null,d,w),L[0]=null,!w.pop()}}),has:$1(function(M){return function(L){return R0(M,L).length>0}}),contains:$1(function(M){return M=M.replace(x1,b1),function(L){return(L.textContent||V.text(L)).indexOf(M)>-1}}),lang:$1(function(M){if(!ZY.test(M||""))R0.error("unsupported lang: "+M);return M=M.replace(x1,b1).toLowerCase(),function(L){var w;do if(w=_?L.lang:L.getAttribute("xml:lang")||L.getAttribute("lang"))return w=w.toLowerCase(),w===M||w.indexOf(M+"-")===0;while((L=L.parentNode)&&L.nodeType===1);return!1}}),target:function(M){var L=J.location&&J.location.hash;return L&&L.slice(1)===M.id},root:function(M){return M===C},focus:function(M){return M===sG()&&N.hasFocus()&&!!(M.type||M.href||~M.tabIndex)},enabled:V8(!1),disabled:V8(!0),checked:function(M){return a(M,"input")&&!!M.checked||a(M,"option")&&!!M.selected},selected:function(M){if(M.parentNode)M.parentNode.selectedIndex;return M.selected===!0},empty:function(M){for(M=M.firstChild;M;M=M.nextSibling)if(M.nodeType<6)return!1;return!0},parent:function(M){return!K.pseudos.empty(M)},header:function(M){return u1.test(M.nodeName)},input:function(M){return p1.test(M.nodeName)},button:function(M){return a(M,"input")&&M.type==="button"||a(M,"button")},text:function(M){var L;return a(M,"input")&&M.type==="text"&&((L=M.getAttribute("type"))==null||L.toLowerCase()==="text")},first:GJ(function(){return[0]}),last:GJ(function(M,L){return[L-1]}),eq:GJ(function(M,L,w){return[w<0?w+L:w]}),even:GJ(function(M,L){var w=0;for(;wL)x=L;else x=w;for(;--x>=0;)M.push(x);return M}),gt:GJ(function(M,L,w){var x=w<0?w+L:w;for(;++x1?function(L,w,x){var v=M.length;while(v--)if(!M[v](L,w,x))return!1;return!0}:M[0]}function oG(M,L,w){var x=0,v=L.length;for(;x-1)d[e]=!(s[e]=X0)}}else if(o=jY(o===s?o.splice(h0,o.length):o),v)v(null,s,o,W0);else q.apply(s,o)})}function LZ(M){var L,w,x,v=M.length,p=K.relative[M[0].type],d=p||K.relative[" "],s=p?1:0,i=wY(function(Y0){return Y0===L},d,!0),W0=wY(function(Y0){return S.call(L,Y0)>-1},d,!0),e=[function(Y0,X0,o){var M0=!p&&(o||X0!=z)||((L=X0).nodeType?i(Y0,X0,o):W0(Y0,X0,o));return L=null,M0}];for(;s1&&QZ(e),s>1&&IY(M.slice(0,s-1).concat({value:M[s-2].type===" "?"*":""})).replace(y,"$1"),w,s0,x=M.length>0,v=function(p,d,s,i,W0){var e,Y0,X0,o=0,M0="0",i0=p&&[],h0=[],Y1=z,P1=p||x&&K.find.TAG("*",W0),wJ=j+=Y1==null?1:Math.random()||0.1,f0=P1.length;if(W0)z=d==N||d||W0;for(;M0!==f0&&(e=P1[M0])!=null;M0++){if(x&&e){if(Y0=0,!d&&e.ownerDocument!=N)c1(e),s=!_;while(X0=M[Y0++])if(X0(e,d||N,s)){q.call(i,e);break}if(W0)j=wJ}if(w){if(e=!X0&&e)o--;if(p)i0.push(e)}}if(o+=M0,w&&M0!==o){Y0=0;while(X0=L[Y0++])X0(i0,h0,d,s);if(p){if(o>0){while(M0--)if(!(i0[M0]||h0[M0]))h0[M0]=N1.call(i)}h0=jY(h0)}if(q.apply(i,h0),W0&&!p&&h0.length>0&&o+L.length>1)V.uniqueSort(i)}if(W0)j=wJ,z=Y1;return i0};return w?$1(v):v}function TZ(M,L){var w,x=[],v=[],p=G0[M+" "];if(!p){if(!L)L=GY(M);w=L.length;while(w--)if(p=LZ(L[w]),p[h])x.push(p);else v.push(p);p=G0(M,tG(v,x)),p.selector=M}return p}function B8(M,L,w,x){var v,p,d,s,i,W0=typeof M==="function"&&M,e=!x&&GY(M=W0.selector||M);if(w=w||[],e.length===1){if(p=e[0]=e[0].slice(0),p.length>2&&(d=p[0]).type==="ID"&&L.nodeType===9&&_&&K.relative[p[1].type]){if(L=(K.find.ID(d.matches[0].replace(x1,b1),L)||[])[0],!L)return w;else if(W0)L=L.parentNode;M=M.slice(p.shift().value.length)}v=S1.needsContext.test(M)?0:p.length;while(v--){if(d=p[v],K.relative[s=d.type])break;if(i=K.find[s]){if(x=i(d.matches[0].replace(x1,b1),PZ.test(p[0].type)&&CZ(L.parentNode)||L)){if(p.splice(v,1),M=x.length&&IY(p),!M)return q.apply(w,x),w;break}}}}return(W0||TZ(M,e))(x,L,!_,w,!L||PZ.test(M)&&CZ(L.parentNode)||L),w}H.sortStable=h.split("").sort(T0).join("")===h,c1(),H.sortDetached=IJ(function(M){return M.compareDocumentPosition(N.createElement("fieldset"))&1}),V.find=R0,V.expr[":"]=V.expr.pseudos,V.unique=V.uniqueSort,R0.compile=TZ,R0.select=B8,R0.setDocument=c1,R0.tokenize=GY,R0.escape=V.escapeSelector,R0.getText=V.text,R0.isXML=V.isXMLDoc,R0.selectors=V.expr,R0.support=V.support,R0.uniqueSort=V.uniqueSort})();var t0=function(Z,K,z){var U=[],B=z!==void 0;while((Z=Z[K])&&Z.nodeType!==9)if(Z.nodeType===1){if(B&&V(Z).is(z))break;U.push(Z)}return U},X1=function(Z,K){var z=[];for(;Z;Z=Z.nextSibling)if(Z.nodeType===1&&Z!==K)z.push(Z);return z},T6=V.expr.match.needsContext,I6=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function XZ(Z,K,z){if(P(K))return V.grep(Z,function(U,B){return!!K.call(U,B,U)!==z});if(K.nodeType)return V.grep(Z,function(U){return U===K!==z});if(typeof K!=="string")return V.grep(Z,function(U){return S.call(K,U)>-1!==z});return V.filter(K,Z,z)}V.filter=function(Z,K,z){var U=K[0];if(z)Z=":not("+Z+")";if(K.length===1&&U.nodeType===1)return V.find.matchesSelector(U,Z)?[U]:[];return V.find.matches(Z,V.grep(K,function(B){return B.nodeType===1}))},V.fn.extend({find:function(Z){var K,z,U=this.length,B=this;if(typeof Z!=="string")return this.pushStack(V(Z).filter(function(){for(K=0;K1?V.uniqueSort(z):z},filter:function(Z){return this.pushStack(XZ(this,Z||[],!1))},not:function(Z){return this.pushStack(XZ(this,Z||[],!0))},is:function(Z){return!!XZ(this,typeof Z==="string"&&T6.test(Z)?V(Z):Z||[],!1).length}});var w6,t9=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,e9=V.fn.init=function(Z,K,z){var U,B;if(!Z)return this;if(z=z||w6,typeof Z==="string"){if(Z[0]==="<"&&Z[Z.length-1]===">"&&Z.length>=3)U=[null,Z,null];else U=t9.exec(Z);if(U&&(U[1]||!K))if(U[1]){if(K=K instanceof V?K[0]:K,V.merge(this,V.parseHTML(U[1],K&&K.nodeType?K.ownerDocument||K:D,!0)),I6.test(U[1])&&V.isPlainObject(K))for(U in K)if(P(this[U]))this[U](K[U]);else this.attr(U,K[U]);return this}else{if(B=D.getElementById(U[2]),B)this[0]=B,this.length=1;return this}else if(!K||K.jquery)return(K||z).find(Z);else return this.constructor(K).find(Z)}else if(Z.nodeType)return this[0]=Z,this.length=1,this;else if(P(Z))return z.ready!==void 0?z.ready(Z):Z(V);return V.makeArray(Z,this)};e9.prototype=V.fn,w6=V(D);var JG=/^(?:parents|prev(?:Until|All))/,YG={children:!0,contents:!0,next:!0,prev:!0};V.fn.extend({has:function(Z){var K=V(Z,this),z=K.length;return this.filter(function(){var U=0;for(;U-1:z.nodeType===1&&V.find.matchesSelector(z,Z))){q.push(z);break}}return this.pushStack(q.length>1?V.uniqueSort(q):q)},index:function(Z){if(!Z)return this[0]&&this[0].parentNode?this.first().prevAll().length:-1;if(typeof Z==="string")return S.call(V(Z),this[0]);return S.call(this,Z.jquery?Z[0]:Z)},add:function(Z,K){return this.pushStack(V.uniqueSort(V.merge(this.get(),V(Z,K))))},addBack:function(Z){return this.add(Z==null?this.prevObject:this.prevObject.filter(Z))}});function j6(Z,K){while((Z=Z[K])&&Z.nodeType!==1);return Z}V.each({parent:function(Z){var K=Z.parentNode;return K&&K.nodeType!==11?K:null},parents:function(Z){return t0(Z,"parentNode")},parentsUntil:function(Z,K,z){return t0(Z,"parentNode",z)},next:function(Z){return j6(Z,"nextSibling")},prev:function(Z){return j6(Z,"previousSibling")},nextAll:function(Z){return t0(Z,"nextSibling")},prevAll:function(Z){return t0(Z,"previousSibling")},nextUntil:function(Z,K,z){return t0(Z,"nextSibling",z)},prevUntil:function(Z,K,z){return t0(Z,"previousSibling",z)},siblings:function(Z){return X1((Z.parentNode||{}).firstChild,Z)},children:function(Z){return X1(Z.firstChild)},contents:function(Z){if(Z.contentDocument!=null&&W(Z.contentDocument))return Z.contentDocument;if(a(Z,"template"))Z=Z.content||Z;return V.merge([],Z.childNodes)}},function(Z,K){V.fn[Z]=function(z,U){var B=V.map(this,K,z);if(Z.slice(-5)!=="Until")U=z;if(U&&typeof U==="string")B=V.filter(U,B);if(this.length>1){if(!YG[Z])V.uniqueSort(B);if(JG.test(Z))B.reverse()}return this.pushStack(B)}});var A1=/[^\x20\t\r\n\f]+/g;function ZG(Z){var K={};return V.each(Z.match(A1)||[],function(z,U){K[U]=!0}),K}V.Callbacks=function(Z){Z=typeof Z==="string"?ZG(Z):V.extend({},Z);var K,z,U,B,q=[],N=[],C=-1,_=function(){B=B||Z.once,U=K=!0;for(;N.length;C=-1){z=N.shift();while(++C-1)if(q.splice(j,1),j<=C)C--}),this},has:function(b){return b?V.inArray(b,q)>-1:q.length>0},empty:function(){if(q)q=[];return this},disable:function(){return B=N=[],q=z="",this},disabled:function(){return!q},lock:function(){if(B=N=[],!z&&!K)q=z="";return this},locked:function(){return!!B},fireWith:function(b,h){if(!B){if(h=h||[],h=[b,h.slice?h.slice():h],N.push(h),!K)_()}return this},fire:function(){return T.fireWith(this,arguments),this},fired:function(){return!!U}};return T};function SJ(Z){return Z}function _Y(Z){throw Z}function k6(Z,K,z,U){var B;try{if(Z&&P(B=Z.promise))B.call(Z).done(K).fail(z);else if(Z&&P(B=Z.then))B.call(Z,K,z);else K.apply(void 0,[Z].slice(U))}catch(q){z.apply(void 0,[q])}}V.extend({Deferred:function(Z){var K=[["notify","progress",V.Callbacks("memory"),V.Callbacks("memory"),2],["resolve","done",V.Callbacks("once memory"),V.Callbacks("once memory"),0,"resolved"],["reject","fail",V.Callbacks("once memory"),V.Callbacks("once memory"),1,"rejected"]],z="pending",U={state:function(){return z},always:function(){return B.done(arguments).fail(arguments),this},catch:function(q){return U.then(null,q)},pipe:function(){var q=arguments;return V.Deferred(function(N){V.each(K,function(C,_){var T=P(q[_[4]])&&q[_[4]];B[_[1]](function(){var b=T&&T.apply(this,arguments);if(b&&P(b.promise))b.promise().progress(N.notify).done(N.resolve).fail(N.reject);else N[_[0]+"With"](this,T?[b]:arguments)})}),q=null}).promise()},then:function(q,N,C){var _=0;function T(b,h,j,f){return function(){var J0=this,V0=arguments,G0=function(){var T0,M1;if(b<_)return;if(T0=j.apply(J0,V0),T0===h.promise())throw TypeError("Thenable self-resolution");if(M1=T0&&(typeof T0==="object"||typeof T0==="function")&&T0.then,P(M1))if(f)M1.call(T0,T(_,h,SJ,f),T(_,h,_Y,f));else _++,M1.call(T0,T(_,h,SJ,f),T(_,h,_Y,f),T(_,h,SJ,h.notifyWith));else{if(j!==SJ)J0=void 0,V0=[T0];(f||h.resolveWith)(J0,V0)}},j0=f?G0:function(){try{G0()}catch(T0){if(V.Deferred.exceptionHook)V.Deferred.exceptionHook(T0,j0.error);if(b+1>=_){if(j!==_Y)J0=void 0,V0=[T0];h.rejectWith(J0,V0)}}};if(b)j0();else{if(V.Deferred.getErrorHook)j0.error=V.Deferred.getErrorHook();else if(V.Deferred.getStackHook)j0.error=V.Deferred.getStackHook();J.setTimeout(j0)}}}return V.Deferred(function(b){K[0][3].add(T(0,b,P(C)?C:SJ,b.notifyWith)),K[1][3].add(T(0,b,P(q)?q:SJ)),K[2][3].add(T(0,b,P(N)?N:_Y))}).promise()},promise:function(q){return q!=null?V.extend(q,U):U}},B={};if(V.each(K,function(q,N){var C=N[2],_=N[5];if(U[N[1]]=C.add,_)C.add(function(){z=_},K[3-q][2].disable,K[3-q][3].disable,K[0][2].lock,K[0][3].lock);C.add(N[3].fire),B[N[0]]=function(){return B[N[0]+"With"](this===B?void 0:this,arguments),this},B[N[0]+"With"]=C.fireWith}),U.promise(B),Z)Z.call(B,B);return B},when:function(Z){var K=arguments.length,z=K,U=Array(z),B=O.call(arguments),q=V.Deferred(),N=function(C){return function(_){if(U[C]=this,B[C]=arguments.length>1?O.call(arguments):_,!--K)q.resolveWith(U,B)}};if(K<=1){if(k6(Z,q.done(N(z)).resolve,q.reject,!K),q.state()==="pending"||P(B[z]&&B[z].then))return q.then()}while(z--)k6(B[z],N(z),q.reject);return q.promise()}});var GG=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;V.Deferred.exceptionHook=function(Z,K){if(J.console&&J.console.warn&&Z&&GG.test(Z.name))J.console.warn("jQuery.Deferred exception: "+Z.message,Z.stack,K)},V.readyException=function(Z){J.setTimeout(function(){throw Z})};var zZ=V.Deferred();V.fn.ready=function(Z){return zZ.then(Z).catch(function(K){V.readyException(K)}),this},V.extend({isReady:!1,readyWait:1,ready:function(Z){if(Z===!0?--V.readyWait:V.isReady)return;if(V.isReady=!0,Z!==!0&&--V.readyWait>0)return;zZ.resolveWith(D,[V])}}),V.ready.then=zZ.then;function SY(){D.removeEventListener("DOMContentLoaded",SY),J.removeEventListener("load",SY),V.ready()}if(D.readyState==="complete"||D.readyState!=="loading"&&!D.documentElement.doScroll)J.setTimeout(V.ready);else D.addEventListener("DOMContentLoaded",SY),J.addEventListener("load",SY);var j1=function(Z,K,z,U,B,q,N){var C=0,_=Z.length,T=z==null;if(K0(z)==="object"){B=!0;for(C in z)j1(Z,K,C,z[C],!0,q,N)}else if(U!==void 0){if(B=!0,!P(U))N=!0;if(T)if(N)K.call(Z,U),K=null;else T=K,K=function(b,h,j){return T.call(V(b),j)};if(K)for(;C<_;C++)K(Z[C],z,N?U:U.call(Z[C],C,K(Z[C],z)))}if(B)return Z;if(T)return K.call(Z);return _?K(Z[0],z):q},KG=/^-ms-/,WG=/-([a-z])/g;function XG(Z,K){return K.toUpperCase()}function H1(Z){return Z.replace(KG,"ms-").replace(WG,XG)}var nJ=function(Z){return Z.nodeType===1||Z.nodeType===9||!+Z.nodeType};function sJ(){this.expando=V.expando+sJ.uid++}sJ.uid=1,sJ.prototype={cache:function(Z){var K=Z[this.expando];if(!K){if(K={},nJ(Z))if(Z.nodeType)Z[this.expando]=K;else Object.defineProperty(Z,this.expando,{value:K,configurable:!0})}return K},set:function(Z,K,z){var U,B=this.cache(Z);if(typeof K==="string")B[H1(K)]=z;else for(U in K)B[H1(U)]=K[U];return B},get:function(Z,K){return K===void 0?this.cache(Z):Z[this.expando]&&Z[this.expando][H1(K)]},access:function(Z,K,z){if(K===void 0||K&&typeof K==="string"&&z===void 0)return this.get(Z,K);return this.set(Z,K,z),z!==void 0?z:K},remove:function(Z,K){var z,U=Z[this.expando];if(U===void 0)return;if(K!==void 0){if(Array.isArray(K))K=K.map(H1);else K=H1(K),K=K in U?[K]:K.match(A1)||[];z=K.length;while(z--)delete U[K[z]]}if(K===void 0||V.isEmptyObject(U))if(Z.nodeType)Z[this.expando]=void 0;else delete Z[this.expando]},hasData:function(Z){var K=Z[this.expando];return K!==void 0&&!V.isEmptyObject(K)}};var r=new sJ,u0=new sJ,zG=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,$G=/[A-Z]/g;function UG(Z){if(Z==="true")return!0;if(Z==="false")return!1;if(Z==="null")return null;if(Z===+Z+"")return+Z;if(zG.test(Z))return JSON.parse(Z);return Z}function x6(Z,K,z){var U;if(z===void 0&&Z.nodeType===1)if(U="data-"+K.replace($G,"-$&").toLowerCase(),z=Z.getAttribute(U),typeof z==="string"){try{z=UG(z)}catch(B){}u0.set(Z,K,z)}else z=void 0;return z}V.extend({hasData:function(Z){return u0.hasData(Z)||r.hasData(Z)},data:function(Z,K,z){return u0.access(Z,K,z)},removeData:function(Z,K){u0.remove(Z,K)},_data:function(Z,K,z){return r.access(Z,K,z)},_removeData:function(Z,K){r.remove(Z,K)}}),V.fn.extend({data:function(Z,K){var z,U,B,q=this[0],N=q&&q.attributes;if(Z===void 0){if(this.length){if(B=u0.get(q),q.nodeType===1&&!r.get(q,"hasDataAttrs")){z=N.length;while(z--)if(N[z]){if(U=N[z].name,U.indexOf("data-")===0)U=H1(U.slice(5)),x6(q,U,B[U])}r.set(q,"hasDataAttrs",!0)}}return B}if(typeof Z==="object")return this.each(function(){u0.set(this,Z)});return j1(this,function(C){var _;if(q&&C===void 0){if(_=u0.get(q,Z),_!==void 0)return _;if(_=x6(q,Z),_!==void 0)return _;return}this.each(function(){u0.set(this,Z,C)})},null,K,arguments.length>1,null,!0)},removeData:function(Z){return this.each(function(){u0.remove(this,Z)})}}),V.extend({queue:function(Z,K,z){var U;if(Z){if(K=(K||"fx")+"queue",U=r.get(Z,K),z)if(!U||Array.isArray(z))U=r.access(Z,K,V.makeArray(z));else U.push(z);return U||[]}},dequeue:function(Z,K){K=K||"fx";var z=V.queue(Z,K),U=z.length,B=z.shift(),q=V._queueHooks(Z,K),N=function(){V.dequeue(Z,K)};if(B==="inprogress")B=z.shift(),U--;if(B){if(K==="fx")z.unshift("inprogress");delete q.stop,B.call(Z,N,q)}if(!U&&q)q.empty.fire()},_queueHooks:function(Z,K){var z=K+"queueHooks";return r.get(Z,z)||r.access(Z,z,{empty:V.Callbacks("once memory").add(function(){r.remove(Z,[K+"queue",z])})})}}),V.fn.extend({queue:function(Z,K){var z=2;if(typeof Z!=="string")K=Z,Z="fx",z--;if(arguments.length\x20\t\r\n\f]*)/i,f6=/^$|^module$|\/(?:java|ecma)script/i;(function(){var Z=D.createDocumentFragment(),K=Z.appendChild(D.createElement("div")),z=D.createElement("input");z.setAttribute("type","radio"),z.setAttribute("checked","checked"),z.setAttribute("name","t"),K.appendChild(z),H.checkClone=K.cloneNode(!0).cloneNode(!0).lastChild.checked,K.innerHTML="",H.noCloneChecked=!!K.cloneNode(!0).lastChild.defaultValue,K.innerHTML="",H.option=!!K.lastChild})();var e0={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};if(e0.tbody=e0.tfoot=e0.colgroup=e0.caption=e0.thead,e0.th=e0.td,!H.option)e0.optgroup=e0.option=[1,""];function c0(Z,K){var z;if(typeof Z.getElementsByTagName<"u")z=Z.getElementsByTagName(K||"*");else if(typeof Z.querySelectorAll<"u")z=Z.querySelectorAll(K||"*");else z=[];if(K===void 0||K&&a(Z,K))return V.merge([Z],z);return z}function $Z(Z,K){var z=0,U=Z.length;for(;z-1){if(B)B.push(q);continue}if(T=PJ(q),N=c0(h.appendChild(q),"script"),T)$Z(N);if(z){b=0;while(q=N[b++])if(f6.test(q.type||""))z.push(q)}}return h}var m6=/^([^.]*)(?:\.(.+)|)/;function QJ(){return!0}function DJ(){return!1}function UZ(Z,K,z,U,B,q){var N,C;if(typeof K==="object"){if(typeof z!=="string")U=U||z,z=void 0;for(C in K)UZ(Z,C,z,U,K[C],q);return Z}if(U==null&&B==null)B=z,U=z=void 0;else if(B==null)if(typeof z==="string")B=U,U=void 0;else B=U,U=z,z=void 0;if(B===!1)B=DJ;else if(!B)return Z;if(q===1)N=B,B=function(_){return V().off(_),N.apply(this,arguments)},B.guid=N.guid||(N.guid=V.guid++);return Z.each(function(){V.event.add(this,K,B,U,z)})}V.event={global:{},add:function(Z,K,z,U,B){var q,N,C,_,T,b,h,j,f,J0,V0,G0=r.get(Z);if(!nJ(Z))return;if(z.handler)q=z,z=q.handler,B=q.selector;if(B)V.find.matchesSelector(e1,B);if(!z.guid)z.guid=V.guid++;if(!(_=G0.events))_=G0.events=Object.create(null);if(!(N=G0.handle))N=G0.handle=function(j0){return typeof V<"u"&&V.event.triggered!==j0.type?V.event.dispatch.apply(Z,arguments):void 0};K=(K||"").match(A1)||[""],T=K.length;while(T--){if(C=m6.exec(K[T])||[],f=V0=C[1],J0=(C[2]||"").split(".").sort(),!f)continue;if(h=V.event.special[f]||{},f=(B?h.delegateType:h.bindType)||f,h=V.event.special[f]||{},b=V.extend({type:f,origType:V0,data:U,handler:z,guid:z.guid,selector:B,needsContext:B&&V.expr.match.needsContext.test(B),namespace:J0.join(".")},q),!(j=_[f])){if(j=_[f]=[],j.delegateCount=0,!h.setup||h.setup.call(Z,U,J0,N)===!1){if(Z.addEventListener)Z.addEventListener(f,N)}}if(h.add){if(h.add.call(Z,b),!b.handler.guid)b.handler.guid=z.guid}if(B)j.splice(j.delegateCount++,0,b);else j.push(b);V.event.global[f]=!0}},remove:function(Z,K,z,U,B){var q,N,C,_,T,b,h,j,f,J0,V0,G0=r.hasData(Z)&&r.get(Z);if(!G0||!(_=G0.events))return;K=(K||"").match(A1)||[""],T=K.length;while(T--){if(C=m6.exec(K[T])||[],f=V0=C[1],J0=(C[2]||"").split(".").sort(),!f){for(f in _)V.event.remove(Z,f+K[T],z,U,!0);continue}h=V.event.special[f]||{},f=(U?h.delegateType:h.bindType)||f,j=_[f]||[],C=C[2]&&new RegExp("(^|\\.)"+J0.join("\\.(?:.*\\.|)")+"(\\.|$)"),N=q=j.length;while(q--)if(b=j[q],(B||V0===b.origType)&&(!z||z.guid===b.guid)&&(!C||C.test(b.namespace))&&(!U||U===b.selector||U==="**"&&b.selector)){if(j.splice(q,1),b.selector)j.delegateCount--;if(h.remove)h.remove.call(Z,b)}if(N&&!j.length){if(!h.teardown||h.teardown.call(Z,J0,G0.handle)===!1)V.removeEvent(Z,f,G0.handle);delete _[f]}}if(V.isEmptyObject(_))r.remove(Z,"handle events")},dispatch:function(Z){var K,z,U,B,q,N,C=Array(arguments.length),_=V.event.fix(Z),T=(r.get(this,"events")||Object.create(null))[_.type]||[],b=V.event.special[_.type]||{};C[0]=_;for(K=1;K=1)){for(;T!==this;T=T.parentNode||this)if(T.nodeType===1&&!(Z.type==="click"&&T.disabled===!0)){q=[],N={};for(z=0;z<_;z++){if(U=K[z],B=U.selector+" ",N[B]===void 0)N[B]=U.needsContext?V(B,this).index(T)>-1:V.find(B,this,null,[T]).length;if(N[B])q.push(U)}if(q.length)C.push({elem:T,handlers:q})}}if(T=this,_\s*$/g;function p6(Z,K){if(a(Z,"table")&&a(K.nodeType!==11?K:K.firstChild,"tr"))return V(Z).children("tbody")[0]||Z;return Z}function NG(Z){return Z.type=(Z.getAttribute("type")!==null)+"/"+Z.type,Z}function AG(Z){if((Z.type||"").slice(0,5)==="true/")Z.type=Z.type.slice(5);else Z.removeAttribute("type");return Z}function u6(Z,K){var z,U,B,q,N,C,_;if(K.nodeType!==1)return;if(r.hasData(Z)){if(q=r.get(Z),_=q.events,_){r.remove(K,"handle events");for(B in _)for(z=0,U=_[B].length;z1&&typeof f==="string"&&!H.checkClone&&FG.test(f))return Z.each(function(V0){var G0=Z.eq(V0);if(J0)K[0]=f.call(this,V0,G0.html());LJ(G0,K,z,U)});if(h){if(B=g6(K,Z[0].ownerDocument,!1,Z,U),q=B.firstChild,B.childNodes.length===1)B=q;if(q||U){N=V.map(c0(B,"script"),NG),C=N.length;for(;b0)$Z(N,!_&&c0(Z,"script"));return C},cleanData:function(Z){var K,z,U,B=V.event.special,q=0;for(;(z=Z[q])!==void 0;q++)if(nJ(z)){if(K=z[r.expando]){if(K.events)for(U in K.events)if(B[U])V.event.remove(z,U);else V.removeEvent(z,U,K.handle);z[r.expando]=void 0}if(z[u0.expando])z[u0.expando]=void 0}}}),V.fn.extend({detach:function(Z){return c6(this,Z,!0)},remove:function(Z){return c6(this,Z)},text:function(Z){return j1(this,function(K){return K===void 0?V.text(this):this.empty().each(function(){if(this.nodeType===1||this.nodeType===11||this.nodeType===9)this.textContent=K})},null,Z,arguments.length)},append:function(){return LJ(this,arguments,function(Z){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var K=p6(this,Z);K.appendChild(Z)}})},prepend:function(){return LJ(this,arguments,function(Z){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var K=p6(this,Z);K.insertBefore(Z,K.firstChild)}})},before:function(){return LJ(this,arguments,function(Z){if(this.parentNode)this.parentNode.insertBefore(Z,this)})},after:function(){return LJ(this,arguments,function(Z){if(this.parentNode)this.parentNode.insertBefore(Z,this.nextSibling)})},empty:function(){var Z,K=0;for(;(Z=this[K])!=null;K++)if(Z.nodeType===1)V.cleanData(c0(Z,!1)),Z.textContent="";return this},clone:function(Z,K){return Z=Z==null?!1:Z,K=K==null?Z:K,this.map(function(){return V.clone(this,Z,K)})},html:function(Z){return j1(this,function(K){var z=this[0]||{},U=0,B=this.length;if(K===void 0&&z.nodeType===1)return z.innerHTML;if(typeof K==="string"&&!qG.test(K)&&!e0[(y6.exec(K)||["",""])[1].toLowerCase()]){K=V.htmlPrefilter(K);try{for(;U=0)_+=Math.max(0,Math.ceil(Z["offset"+K[0].toUpperCase()+K.slice(1)]-q-_-C-0.5))||0;return _+T}function o6(Z,K,z){var U=QY(Z),B=!H.boxSizingReliable()||z,q=B&&V.css(Z,"boxSizing",!1,U)==="border-box",N=q,C=oJ(Z,K,U),_="offset"+K[0].toUpperCase()+K.slice(1);if(VZ.test(C)){if(!z)return C;C="auto"}if((!H.boxSizingReliable()&&q||!H.reliableTrDimensions()&&a(Z,"tr")||C==="auto"||!parseFloat(C)&&V.css(Z,"display",!1,U)==="inline")&&Z.getClientRects().length){if(q=V.css(Z,"boxSizing",!1,U)==="border-box",N=_ in Z,N)C=Z[_]}return C=parseFloat(C)||0,C+qZ(Z,K,z||(q?"border":"content"),N,U,C)+"px"}V.extend({cssHooks:{opacity:{get:function(Z,K){if(K){var z=oJ(Z,"opacity");return z===""?"1":z}}}},cssNumber:{animationIterationCount:!0,aspectRatio:!0,borderImageSlice:!0,columnCount:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,scale:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeMiterlimit:!0,strokeOpacity:!0},cssProps:{},style:function(Z,K,z,U){if(!Z||Z.nodeType===3||Z.nodeType===8||!Z.style)return;var B,q,N,C=H1(K),_=OZ.test(K),T=Z.style;if(!_)K=BZ(C);if(N=V.cssHooks[K]||V.cssHooks[C],z!==void 0){if(q=typeof z,q==="string"&&(B=aJ.exec(z))&&B[1])z=v6(Z,K,B),q="number";if(z==null||z!==z)return;if(q==="number"&&!_)z+=B&&B[3]||(V.cssNumber[C]?"":"px");if(!H.clearCloneStyle&&z===""&&K.indexOf("background")===0)T[K]="inherit";if(!N||!("set"in N)||(z=N.set(Z,z,U))!==void 0)if(_)T.setProperty(K,z);else T[K]=z}else{if(N&&"get"in N&&(B=N.get(Z,!1,U))!==void 0)return B;return T[K]}},css:function(Z,K,z,U){var B,q,N,C=H1(K),_=OZ.test(K);if(!_)K=BZ(C);if(N=V.cssHooks[K]||V.cssHooks[C],N&&"get"in N)B=N.get(Z,!0,z);if(B===void 0)B=oJ(Z,K,U);if(B==="normal"&&K in a6)B=a6[K];if(z===""||z)return q=parseFloat(B),z===!0||isFinite(q)?q||0:B;return B}}),V.each(["height","width"],function(Z,K){V.cssHooks[K]={get:function(z,U,B){if(U)return _G.test(V.css(z,"display"))&&(!z.getClientRects().length||!z.getBoundingClientRect().width)?d6(z,SG,function(){return o6(z,K,B)}):o6(z,K,B)},set:function(z,U,B){var q,N=QY(z),C=!H.scrollboxSize()&&N.position==="absolute",_=C||B,T=_&&V.css(z,"boxSizing",!1,N)==="border-box",b=B?qZ(z,K,B,T,N):0;if(T&&C)b-=Math.ceil(z["offset"+K[0].toUpperCase()+K.slice(1)]-parseFloat(N[K])-qZ(z,K,"border",!1,N)-0.5);if(b&&(q=aJ.exec(U))&&(q[3]||"px")!=="px")z.style[K]=U,U=V.css(z,K);return r6(z,U,b)}}}),V.cssHooks.marginLeft=i6(H.reliableMarginLeft,function(Z,K){if(K)return(parseFloat(oJ(Z,"marginLeft"))||Z.getBoundingClientRect().left-d6(Z,{marginLeft:0},function(){return Z.getBoundingClientRect().left}))+"px"}),V.each({margin:"",padding:"",border:"Width"},function(Z,K){if(V.cssHooks[Z+K]={expand:function(z){var U=0,B={},q=typeof z==="string"?z.split(" "):[z];for(;U<4;U++)B[Z+k1[U]+K]=q[U]||q[U-2]||q[0];return B}},Z!=="margin")V.cssHooks[Z+K].set=r6}),V.fn.extend({css:function(Z,K){return j1(this,function(z,U,B){var q,N,C={},_=0;if(Array.isArray(U)){q=QY(z),N=U.length;for(;_1)}});function d0(Z,K,z,U,B){return new d0.prototype.init(Z,K,z,U,B)}V.Tween=d0,d0.prototype={constructor:d0,init:function(Z,K,z,U,B,q){this.elem=Z,this.prop=z,this.easing=B||V.easing._default,this.options=K,this.start=this.now=this.cur(),this.end=U,this.unit=q||(V.cssNumber[z]?"":"px")},cur:function(){var Z=d0.propHooks[this.prop];return Z&&Z.get?Z.get(this):d0.propHooks._default.get(this)},run:function(Z){var K,z=d0.propHooks[this.prop];if(this.options.duration)this.pos=K=V.easing[this.easing](Z,this.options.duration*Z,0,1,this.options.duration);else this.pos=K=Z;if(this.now=(this.end-this.start)*K+this.start,this.options.step)this.options.step.call(this.elem,this.now,this);if(z&&z.set)z.set(this);else d0.propHooks._default.set(this);return this}},d0.prototype.init.prototype=d0.prototype,d0.propHooks={_default:{get:function(Z){var K;if(Z.elem.nodeType!==1||Z.elem[Z.prop]!=null&&Z.elem.style[Z.prop]==null)return Z.elem[Z.prop];return K=V.css(Z.elem,Z.prop,""),!K||K==="auto"?0:K},set:function(Z){if(V.fx.step[Z.prop])V.fx.step[Z.prop](Z);else if(Z.elem.nodeType===1&&(V.cssHooks[Z.prop]||Z.elem.style[BZ(Z.prop)]!=null))V.style(Z.elem,Z.prop,Z.now+Z.unit);else Z.elem[Z.prop]=Z.now}}},d0.propHooks.scrollTop=d0.propHooks.scrollLeft={set:function(Z){if(Z.elem.nodeType&&Z.elem.parentNode)Z.elem[Z.prop]=Z.now}},V.easing={linear:function(Z){return Z},swing:function(Z){return 0.5-Math.cos(Z*Math.PI)/2},_default:"swing"},V.fx=d0.prototype.init,V.fx.step={};var TJ,DY,PG=/^(?:toggle|show|hide)$/,CG=/queueHooks$/;function FZ(){if(DY){if(D.hidden===!1&&J.requestAnimationFrame)J.requestAnimationFrame(FZ);else J.setTimeout(FZ,V.fx.interval);V.fx.tick()}}function t6(){return J.setTimeout(function(){TJ=void 0}),TJ=Date.now()}function LY(Z,K){var z,U=0,B={height:Z};K=K?1:0;for(;U<4;U+=2-K)z=k1[U],B["margin"+z]=B["padding"+z]=Z;if(K)B.opacity=B.width=Z;return B}function e6(Z,K,z){var U,B=(z1.tweeners[K]||[]).concat(z1.tweeners["*"]),q=0,N=B.length;for(;q1)},removeAttr:function(Z){return this.each(function(){V.removeAttr(this,Z)})}}),V.extend({attr:function(Z,K,z){var U,B,q=Z.nodeType;if(q===3||q===8||q===2)return;if(typeof Z.getAttribute>"u")return V.prop(Z,K,z);if(q!==1||!V.isXMLDoc(Z))B=V.attrHooks[K.toLowerCase()]||(V.expr.match.bool.test(K)?J8:void 0);if(z!==void 0){if(z===null){V.removeAttr(Z,K);return}if(B&&"set"in B&&(U=B.set(Z,z,K))!==void 0)return U;return Z.setAttribute(K,z+""),z}if(B&&"get"in B&&(U=B.get(Z,K))!==null)return U;return U=V.find.attr(Z,K),U==null?void 0:U},attrHooks:{type:{set:function(Z,K){if(!H.radioValue&&K==="radio"&&a(Z,"input")){var z=Z.value;if(Z.setAttribute("type",K),z)Z.value=z;return K}}}},removeAttr:function(Z,K){var z,U=0,B=K&&K.match(A1);if(B&&Z.nodeType===1)while(z=B[U++])Z.removeAttribute(z)}}),J8={set:function(Z,K,z){if(K===!1)V.removeAttr(Z,z);else Z.setAttribute(z,z);return z}},V.each(V.expr.match.bool.source.match(/\w+/g),function(Z,K){var z=tJ[K]||V.find.attr;tJ[K]=function(U,B,q){var N,C,_=B.toLowerCase();if(!q)C=tJ[_],tJ[_]=N,N=z(U,B,q)!=null?_:null,tJ[_]=C;return N}});var LG=/^(?:input|select|textarea|button)$/i,TG=/^(?:a|area)$/i;if(V.fn.extend({prop:function(Z,K){return j1(this,V.prop,Z,K,arguments.length>1)},removeProp:function(Z){return this.each(function(){delete this[V.propFix[Z]||Z]})}}),V.extend({prop:function(Z,K,z){var U,B,q=Z.nodeType;if(q===3||q===8||q===2)return;if(q!==1||!V.isXMLDoc(Z))K=V.propFix[K]||K,B=V.propHooks[K];if(z!==void 0){if(B&&"set"in B&&(U=B.set(Z,z,K))!==void 0)return U;return Z[K]=z}if(B&&"get"in B&&(U=B.get(Z,K))!==null)return U;return Z[K]},propHooks:{tabIndex:{get:function(Z){var K=V.find.attr(Z,"tabindex");if(K)return parseInt(K,10);if(LG.test(Z.nodeName)||TG.test(Z.nodeName)&&Z.href)return 0;return-1}}},propFix:{for:"htmlFor",class:"className"}}),!H.optSelected)V.propHooks.selected={get:function(Z){var K=Z.parentNode;if(K&&K.parentNode)K.parentNode.selectedIndex;return null},set:function(Z){var K=Z.parentNode;if(K){if(K.selectedIndex,K.parentNode)K.parentNode.selectedIndex}}};V.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){V.propFix[this.toLowerCase()]=this});function JJ(Z){var K=Z.match(A1)||[];return K.join(" ")}function YJ(Z){return Z.getAttribute&&Z.getAttribute("class")||""}function RZ(Z){if(Array.isArray(Z))return Z;if(typeof Z==="string")return Z.match(A1)||[];return[]}V.fn.extend({addClass:function(Z){var K,z,U,B,q,N;if(P(Z))return this.each(function(C){V(this).addClass(Z.call(this,C,YJ(this)))});if(K=RZ(Z),K.length)return this.each(function(){if(U=YJ(this),z=this.nodeType===1&&" "+JJ(U)+" ",z){for(q=0;q-1)z=z.replace(" "+B+" "," ")}if(N=JJ(z),U!==N)this.setAttribute("class",N)}});return this},toggleClass:function(Z,K){var z,U,B,q,N=typeof Z,C=N==="string"||Array.isArray(Z);if(P(Z))return this.each(function(_){V(this).toggleClass(Z.call(this,_,YJ(this),K),K)});if(typeof K==="boolean"&&C)return K?this.addClass(Z):this.removeClass(Z);return z=RZ(Z),this.each(function(){if(C){q=V(this);for(B=0;B-1)return!0;return!1}});var IG=/\r/g;V.fn.extend({val:function(Z){var K,z,U,B=this[0];if(!arguments.length){if(B){if(K=V.valHooks[B.type]||V.valHooks[B.nodeName.toLowerCase()],K&&"get"in K&&(z=K.get(B,"value"))!==void 0)return z;if(z=B.value,typeof z==="string")return z.replace(IG,"");return z==null?"":z}return}return U=P(Z),this.each(function(q){var N;if(this.nodeType!==1)return;if(U)N=Z.call(this,q,V(this).val());else N=Z;if(N==null)N="";else if(typeof N==="number")N+="";else if(Array.isArray(N))N=V.map(N,function(C){return C==null?"":C+""});if(K=V.valHooks[this.type]||V.valHooks[this.nodeName.toLowerCase()],!K||!("set"in K)||K.set(this,N,"value")===void 0)this.value=N})}}),V.extend({valHooks:{option:{get:function(Z){var K=V.find.attr(Z,"value");return K!=null?K:JJ(V.text(Z))}},select:{get:function(Z){var K,z,U,B=Z.options,q=Z.selectedIndex,N=Z.type==="select-one",C=N?null:[],_=N?q+1:B.length;if(q<0)U=_;else U=N?q:0;for(;U<_;U++)if(z=B[U],(z.selected||U===q)&&!z.disabled&&(!z.parentNode.disabled||!a(z.parentNode,"optgroup"))){if(K=V(z).val(),N)return K;C.push(K)}return C},set:function(Z,K){var z,U,B=Z.options,q=V.makeArray(K),N=B.length;while(N--)if(U=B[N],U.selected=V.inArray(V.valHooks.option.get(U),q)>-1)z=!0;if(!z)Z.selectedIndex=-1;return q}}}}),V.each(["radio","checkbox"],function(){if(V.valHooks[this]={set:function(Z,K){if(Array.isArray(K))return Z.checked=V.inArray(V(Z).val(),K)>-1}},!H.checkOn)V.valHooks[this].get=function(Z){return Z.getAttribute("value")===null?"on":Z.value}});var eJ=J.location,Y8={guid:Date.now()},NZ=/\?/;V.parseXML=function(Z){var K,z;if(!Z||typeof Z!=="string")return null;try{K=new J.DOMParser().parseFromString(Z,"text/xml")}catch(U){}if(z=K&&K.getElementsByTagName("parsererror")[0],!K||z)V.error("Invalid XML: "+(z?V.map(z.childNodes,function(U){return U.textContent}).join(` +`):Z));return K};var Z8=/^(?:focusinfocus|focusoutblur)$/,G8=function(Z){Z.stopPropagation()};V.extend(V.event,{trigger:function(Z,K,z,U){var B,q,N,C,_,T,b,h,j=[z||D],f=X.call(Z,"type")?Z.type:Z,J0=X.call(Z,"namespace")?Z.namespace.split("."):[];if(q=h=N=z=z||D,z.nodeType===3||z.nodeType===8)return;if(Z8.test(f+V.event.triggered))return;if(f.indexOf(".")>-1)J0=f.split("."),f=J0.shift(),J0.sort();if(_=f.indexOf(":")<0&&"on"+f,Z=Z[V.expando]?Z:new V.Event(f,typeof Z==="object"&&Z),Z.isTrigger=U?2:3,Z.namespace=J0.join("."),Z.rnamespace=Z.namespace?new RegExp("(^|\\.)"+J0.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,Z.result=void 0,!Z.target)Z.target=z;if(K=K==null?[Z]:V.makeArray(K,[Z]),b=V.event.special[f]||{},!U&&b.trigger&&b.trigger.apply(z,K)===!1)return;if(!U&&!b.noBubble&&!I(z)){if(C=b.delegateType||f,!Z8.test(C+f))q=q.parentNode;for(;q;q=q.parentNode)j.push(q),N=q;if(N===(z.ownerDocument||D))j.push(N.defaultView||N.parentWindow||J)}B=0;while((q=j[B++])&&!Z.isPropagationStopped()){if(h=q,Z.type=B>1?C:b.bindType||f,T=(r.get(q,"events")||Object.create(null))[Z.type]&&r.get(q,"handle"),T)T.apply(q,K);if(T=_&&q[_],T&&T.apply&&nJ(q)){if(Z.result=T.apply(q,K),Z.result===!1)Z.preventDefault()}}if(Z.type=f,!U&&!Z.isDefaultPrevented()){if((!b._default||b._default.apply(j.pop(),K)===!1)&&nJ(z)){if(_&&P(z[f])&&!I(z)){if(N=z[_],N)z[_]=null;if(V.event.triggered=f,Z.isPropagationStopped())h.addEventListener(f,G8);if(z[f](),Z.isPropagationStopped())h.removeEventListener(f,G8);if(V.event.triggered=void 0,N)z[_]=N}}}return Z.result},simulate:function(Z,K,z){var U=V.extend(new V.Event,z,{type:Z,isSimulated:!0});V.event.trigger(U,null,K)}}),V.fn.extend({trigger:function(Z,K){return this.each(function(){V.event.trigger(Z,K,this)})},triggerHandler:function(Z,K){var z=this[0];if(z)return V.event.trigger(Z,K,z,!0)}});var wG=/\[\]$/,K8=/\r?\n/g,jG=/^(?:submit|button|image|reset|file)$/i,kG=/^(?:input|select|textarea|keygen)/i;function AZ(Z,K,z,U){var B;if(Array.isArray(K))V.each(K,function(q,N){if(z||wG.test(Z))U(Z,N);else AZ(Z+"["+(typeof N==="object"&&N!=null?q:"")+"]",N,z,U)});else if(!z&&K0(K)==="object")for(B in K)AZ(Z+"["+B+"]",K[B],z,U);else U(Z,K)}V.param=function(Z,K){var z,U=[],B=function(q,N){var C=P(N)?N():N;U[U.length]=encodeURIComponent(q)+"="+encodeURIComponent(C==null?"":C)};if(Z==null)return"";if(Array.isArray(Z)||Z.jquery&&!V.isPlainObject(Z))V.each(Z,function(){B(this.name,this.value)});else for(z in Z)AZ(z,Z[z],K,B);return U.join("&")},V.fn.extend({serialize:function(){return V.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var Z=V.prop(this,"elements");return Z?V.makeArray(Z):this}).filter(function(){var Z=this.type;return this.name&&!V(this).is(":disabled")&&kG.test(this.nodeName)&&!jG.test(Z)&&(this.checked||!rJ.test(Z))}).map(function(Z,K){var z=V(this).val();if(z==null)return null;if(Array.isArray(z))return V.map(z,function(U){return{name:K.name,value:U.replace(K8,`\r +`)}});return{name:K.name,value:z.replace(K8,`\r +`)}}).get()}});var xG=/%20/g,bG=/#.*$/,vG=/([?&])_=[^&]*/,hG=/^(.*?):[ \t]*([^\r\n]*)$/mg,yG=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,fG=/^(?:GET|HEAD)$/,gG=/^\/\//,W8={},HZ={},X8="*/".concat("*"),MZ=D.createElement("a");MZ.href=eJ.href;function z8(Z){return function(K,z){if(typeof K!=="string")z=K,K="*";var U,B=0,q=K.toLowerCase().match(A1)||[];if(P(z))while(U=q[B++])if(U[0]==="+")U=U.slice(1)||"*",(Z[U]=Z[U]||[]).unshift(z);else(Z[U]=Z[U]||[]).push(z)}}function $8(Z,K,z,U){var B={},q=Z===HZ;function N(C){var _;return B[C]=!0,V.each(Z[C]||[],function(T,b){var h=b(K,z,U);if(typeof h==="string"&&!q&&!B[h])return K.dataTypes.unshift(h),N(h),!1;else if(q)return!(_=h)}),_}return N(K.dataTypes[0])||!B["*"]&&N("*")}function EZ(Z,K){var z,U,B=V.ajaxSettings.flatOptions||{};for(z in K)if(K[z]!==void 0)(B[z]?Z:U||(U={}))[z]=K[z];if(U)V.extend(!0,Z,U);return Z}function mG(Z,K,z){var U,B,q,N,C=Z.contents,_=Z.dataTypes;while(_[0]==="*")if(_.shift(),U===void 0)U=Z.mimeType||K.getResponseHeader("Content-Type");if(U){for(B in C)if(C[B]&&C[B].test(U)){_.unshift(B);break}}if(_[0]in z)q=_[0];else{for(B in z){if(!_[0]||Z.converters[B+" "+_[0]]){q=B;break}if(!N)N=B}q=q||N}if(q){if(q!==_[0])_.unshift(q);return z[q]}}function pG(Z,K,z,U){var B,q,N,C,_,T={},b=Z.dataTypes.slice();if(b[1])for(N in Z.converters)T[N.toLowerCase()]=Z.converters[N];q=b.shift();while(q){if(Z.responseFields[q])z[Z.responseFields[q]]=K;if(!_&&U&&Z.dataFilter)K=Z.dataFilter(K,Z.dataType);if(_=q,q=b.shift(),q){if(q==="*")q=_;else if(_!=="*"&&_!==q){if(N=T[_+" "+q]||T["* "+q],!N){for(B in T)if(C=B.split(" "),C[1]===q){if(N=T[_+" "+C[0]]||T["* "+C[0]],N){if(N===!0)N=T[B];else if(T[B]!==!0)q=C[0],b.unshift(C[1]);break}}}if(N!==!0)if(N&&Z.throws)K=N(K);else try{K=N(K)}catch(h){return{state:"parsererror",error:N?h:"No conversion from "+_+" to "+q}}}}}return{state:"success",data:K}}V.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:eJ.href,type:"GET",isLocal:yG.test(eJ.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":X8,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":V.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(Z,K){return K?EZ(EZ(Z,V.ajaxSettings),K):EZ(V.ajaxSettings,Z)},ajaxPrefilter:z8(W8),ajaxTransport:z8(HZ),ajax:function(Z,K){if(typeof Z==="object")K=Z,Z=void 0;K=K||{};var z,U,B,q,N,C,_,T,b,h,j=V.ajaxSetup({},K),f=j.context||j,J0=j.context&&(f.nodeType||f.jquery)?V(f):V.event,V0=V.Deferred(),G0=V.Callbacks("once memory"),j0=j.statusCode||{},T0={},M1={},E1="canceled",z0={readyState:0,getResponseHeader:function(B0){var Q0;if(_){if(!q){q={};while(Q0=hG.exec(B))q[Q0[1].toLowerCase()+" "]=(q[Q0[1].toLowerCase()+" "]||[]).concat(Q0[2])}Q0=q[B0.toLowerCase()+" "]}return Q0==null?null:Q0.join(", ")},getAllResponseHeaders:function(){return _?B:null},setRequestHeader:function(B0,Q0){if(_==null)B0=M1[B0.toLowerCase()]=M1[B0.toLowerCase()]||B0,T0[B0]=Q0;return this},overrideMimeType:function(B0){if(_==null)j.mimeType=B0;return this},statusCode:function(B0){var Q0;if(B0)if(_)z0.always(B0[z0.status]);else for(Q0 in B0)j0[Q0]=[j0[Q0],B0[Q0]];return this},abort:function(B0){var Q0=B0||E1;if(z)z.abort(Q0);return ZJ(0,Q0),this}};if(V0.promise(z0),j.url=((Z||j.url||eJ.href)+"").replace(gG,eJ.protocol+"//"),j.type=K.method||K.type||j.method||j.type,j.dataTypes=(j.dataType||"*").toLowerCase().match(A1)||[""],j.crossDomain==null){C=D.createElement("a");try{C.href=j.url,C.href=C.href,j.crossDomain=MZ.protocol+"//"+MZ.host!==C.protocol+"//"+C.host}catch(B0){j.crossDomain=!0}}if(j.data&&j.processData&&typeof j.data!=="string")j.data=V.param(j.data,j.traditional);if($8(W8,j,K,z0),_)return z0;if(T=V.event&&j.global,T&&V.active++===0)V.event.trigger("ajaxStart");if(j.type=j.type.toUpperCase(),j.hasContent=!fG.test(j.type),U=j.url.replace(bG,""),!j.hasContent){if(h=j.url.slice(U.length),j.data&&(j.processData||typeof j.data==="string"))U+=(NZ.test(U)?"&":"?")+j.data,delete j.data;if(j.cache===!1)U=U.replace(vG,"$1"),h=(NZ.test(U)?"&":"?")+"_="+Y8.guid+++h;j.url=U+h}else if(j.data&&j.processData&&(j.contentType||"").indexOf("application/x-www-form-urlencoded")===0)j.data=j.data.replace(xG,"+");if(j.ifModified){if(V.lastModified[U])z0.setRequestHeader("If-Modified-Since",V.lastModified[U]);if(V.etag[U])z0.setRequestHeader("If-None-Match",V.etag[U])}if(j.data&&j.hasContent&&j.contentType!==!1||K.contentType)z0.setRequestHeader("Content-Type",j.contentType);z0.setRequestHeader("Accept",j.dataTypes[0]&&j.accepts[j.dataTypes[0]]?j.accepts[j.dataTypes[0]]+(j.dataTypes[0]!=="*"?", "+X8+"; q=0.01":""):j.accepts["*"]);for(b in j.headers)z0.setRequestHeader(b,j.headers[b]);if(j.beforeSend&&(j.beforeSend.call(f,z0,j)===!1||_))return z0.abort();if(E1="abort",G0.add(j.complete),z0.done(j.success),z0.fail(j.error),z=$8(HZ,j,K,z0),!z)ZJ(-1,"No Transport");else{if(z0.readyState=1,T)J0.trigger("ajaxSend",[z0,j]);if(_)return z0;if(j.async&&j.timeout>0)N=J.setTimeout(function(){z0.abort("timeout")},j.timeout);try{_=!1,z.send(T0,ZJ)}catch(B0){if(_)throw B0;ZJ(-1,B0)}}function ZJ(B0,Q0,YY,SZ){var _1,ZY,S1,p1,u1,J1=Q0;if(_)return;if(_=!0,N)J.clearTimeout(N);if(z=void 0,B=SZ||"",z0.readyState=B0>0?4:0,_1=B0>=200&&B0<300||B0===304,YY)p1=mG(j,z0,YY);if(!_1&&V.inArray("script",j.dataTypes)>-1&&V.inArray("json",j.dataTypes)<0)j.converters["text script"]=function(){};if(p1=pG(j,p1,z0,_1),_1){if(j.ifModified){if(u1=z0.getResponseHeader("Last-Modified"),u1)V.lastModified[U]=u1;if(u1=z0.getResponseHeader("etag"),u1)V.etag[U]=u1}if(B0===204||j.type==="HEAD")J1="nocontent";else if(B0===304)J1="notmodified";else J1=p1.state,ZY=p1.data,S1=p1.error,_1=!S1}else if(S1=J1,B0||!J1){if(J1="error",B0<0)B0=0}if(z0.status=B0,z0.statusText=(Q0||J1)+"",_1)V0.resolveWith(f,[ZY,J1,z0]);else V0.rejectWith(f,[z0,J1,S1]);if(z0.statusCode(j0),j0=void 0,T)J0.trigger(_1?"ajaxSuccess":"ajaxError",[z0,j,_1?ZY:S1]);if(G0.fireWith(f,[z0,J1]),T){if(J0.trigger("ajaxComplete",[z0,j]),!--V.active)V.event.trigger("ajaxStop")}}return z0},getJSON:function(Z,K,z){return V.get(Z,K,z,"json")},getScript:function(Z,K){return V.get(Z,void 0,K,"script")}}),V.each(["get","post"],function(Z,K){V[K]=function(z,U,B,q){if(P(U))q=q||B,B=U,U=void 0;return V.ajax(V.extend({url:z,type:K,dataType:q,data:U,success:B},V.isPlainObject(z)&&z))}}),V.ajaxPrefilter(function(Z){var K;for(K in Z.headers)if(K.toLowerCase()==="content-type")Z.contentType=Z.headers[K]||""}),V._evalUrl=function(Z,K,z){return V.ajax({url:Z,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(U){V.globalEval(U,K,z)}})},V.fn.extend({wrapAll:function(Z){var K;if(this[0]){if(P(Z))Z=Z.call(this[0]);if(K=V(Z,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode)K.insertBefore(this[0]);K.map(function(){var z=this;while(z.firstElementChild)z=z.firstElementChild;return z}).append(this)}return this},wrapInner:function(Z){if(P(Z))return this.each(function(K){V(this).wrapInner(Z.call(this,K))});return this.each(function(){var K=V(this),z=K.contents();if(z.length)z.wrapAll(Z);else K.append(Z)})},wrap:function(Z){var K=P(Z);return this.each(function(z){V(this).wrapAll(K?Z.call(this,z):Z)})},unwrap:function(Z){return this.parent(Z).not("body").each(function(){V(this).replaceWith(this.childNodes)}),this}}),V.expr.pseudos.hidden=function(Z){return!V.expr.pseudos.visible(Z)},V.expr.pseudos.visible=function(Z){return!!(Z.offsetWidth||Z.offsetHeight||Z.getClientRects().length)},V.ajaxSettings.xhr=function(){try{return new J.XMLHttpRequest}catch(Z){}};var uG={0:200,1223:204},JY=V.ajaxSettings.xhr();H.cors=!!JY&&"withCredentials"in JY,H.ajax=JY=!!JY,V.ajaxTransport(function(Z){var K,z;if(H.cors||JY&&!Z.crossDomain)return{send:function(U,B){var q,N=Z.xhr();if(N.open(Z.type,Z.url,Z.async,Z.username,Z.password),Z.xhrFields)for(q in Z.xhrFields)N[q]=Z.xhrFields[q];if(Z.mimeType&&N.overrideMimeType)N.overrideMimeType(Z.mimeType);if(!Z.crossDomain&&!U["X-Requested-With"])U["X-Requested-With"]="XMLHttpRequest";for(q in U)N.setRequestHeader(q,U[q]);if(K=function(C){return function(){if(K)if(K=z=N.onload=N.onerror=N.onabort=N.ontimeout=N.onreadystatechange=null,C==="abort")N.abort();else if(C==="error")if(typeof N.status!=="number")B(0,"error");else B(N.status,N.statusText);else B(uG[N.status]||N.status,N.statusText,(N.responseType||"text")!=="text"||typeof N.responseText!=="string"?{binary:N.response}:{text:N.responseText},N.getAllResponseHeaders())}},N.onload=K(),z=N.onerror=N.ontimeout=K("error"),N.onabort!==void 0)N.onabort=z;else N.onreadystatechange=function(){if(N.readyState===4)J.setTimeout(function(){if(K)z()})};K=K("abort");try{N.send(Z.hasContent&&Z.data||null)}catch(C){if(K)throw C}},abort:function(){if(K)K()}}}),V.ajaxPrefilter(function(Z){if(Z.crossDomain)Z.contents.script=!1}),V.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(Z){return V.globalEval(Z),Z}}}),V.ajaxPrefilter("script",function(Z){if(Z.cache===void 0)Z.cache=!1;if(Z.crossDomain)Z.type="GET"}),V.ajaxTransport("script",function(Z){if(Z.crossDomain||Z.scriptAttrs){var K,z;return{send:function(U,B){K=V(" \ No newline at end of file diff --git a/resources/radio/client/radios/AFX-1500/config.json b/resources/radio/client/radios/AFX-1500/config.json new file mode 100644 index 000000000..978ce0233 --- /dev/null +++ b/resources/radio/client/radios/AFX-1500/config.json @@ -0,0 +1,266 @@ +{ + "toneSet": "default", + "radioWidth": 601, + "radioHeight": 234, + "radioBGColor": "#e8e8e9", + "radioBGDarkColor": "#08080a", + "defaultBottomPadding": 50, + "alert": { + "x": 224, + "y": 133, + "width": 181, + "height": 15, + "size": 12, + "color": "#464d49", + "darkColor": "#ffffff" + }, + "time": { + "enabled": true, + "x": 224, + "y": 133, + "color": "#464d49", + "darkColor": "#ffffff", + "width": 77, + "height": 15, + "size": 12 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#ffffff", + "size": 16, + "width": 100, + "height": 15, + "x": 224, + "y": 95 + }, + { + "key": "line2", + "width": 100, + "color": "#464d49", + "darkColor": "#ffffff", + "size": 16, + "height": 15, + "x": 224, + "y": 112 + }, + { + "key": "btn1", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 153, + "y": 150 + }, + { + "key": "btn2", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 200, + "y": 150 + }, + { + "key": "btn3", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 246, + "y": 150 + }, + { + "key": "btn4", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 290, + "y": 150 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 78, + "y": 78, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 513, + "y": 171, + "width": 20, + "height": 20 + }, + { + "key": "btnRight", + "x": 562, + "y": 169, + "width": 20, + "height": 20 + }, + { + "key": "btnUp", + "x": 535, + "y": 143, + "width": 20, + "height": 20 + }, + { + "key": "btnDown", + "x": 536, + "y": 196, + "width": 20, + "height": 20 + }, + { + "key": "chUp", + "x": 354, + "y": 80, + "width": 20, + "height": 25 + }, + { + "key": "chDwn", + "x": 354, + "y": 114, + "width": 20, + "height": 25 + }, + { + "key": "emergency", + "x": 537, + "y": 77, + "width": 20, + "height": 20 + }, + { + "key": "home", + "x": 352, + "y": 198, + "width": 20, + "height": 20 + }, + { + "key": "close", + "x": 353, + "y": 156, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 149, + "y": 197, + "width": 25, + "height": 25 + }, + { + "key": "btn2", + "x": 200, + "y": 197, + "width": 25, + "height": 25 + }, + { + "key": "btn3", + "x": 250, + "y": 197, + "width": 25, + "height": 25 + }, + { + "key": "btn4", + "x": 299, + "y": 197, + "width": 25, + "height": 25 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 76, + "y": 108, + "width": 20, + "height": 4, + "roundness": 4 + }, + { + "key": "connected", + "color": "green", + "x": 76, + "y": 121, + "width": 20, + "height": 4, + "roundness": 4 + }, + { + "key": "transmit", + "color": "orange", + "x": 76, + "y": 134, + "width": 20, + "height": 4, + "roundness": 4 + } + ], + "icons": [ + { + "key": "sig", + "x": 144, + "y": 78, + "width": 15, + "height": 15 + }, + { + "key": "scan", + "x": 175, + "y": 81, + "width": 13, + "height": 13 + }, + { + "key": "trunk", + "x": 206, + "y": 81, + "width": 13, + "height": 13 + }, + { + "key": "warn", + "x": 237, + "y": 81, + "width": 15, + "height": 15 + }, + { + "key": "gps", + "x": 268, + "y": 81, + "width": 13, + "height": 13 + }, + { + "key": "batt", + "x": 300, + "y": 81, + "width": 16, + "height": 16 + } + ] +} diff --git a/resources/radio/client/radios/AFX-1500/desktop.ini b/resources/radio/client/radios/AFX-1500/desktop.ini new file mode 100644 index 000000000..adc6681a8 --- /dev/null +++ b/resources/radio/client/radios/AFX-1500/desktop.ini @@ -0,0 +1,4 @@ +[LocalizedFileNames] +radios_00004.png=@radios_00004.png,0 +radio 2_00011.png=@radio 2_00011.png,0 +radio 2_00010.png=@radio 2_00010.png,0 diff --git a/resources/radio/client/radios/AFX-1500/icons/batt_0.png b/resources/radio/client/radios/AFX-1500/icons/batt_0.png new file mode 100644 index 000000000..00885cf1b Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/batt_0.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/batt_1.png b/resources/radio/client/radios/AFX-1500/icons/batt_1.png new file mode 100644 index 000000000..861711a02 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/batt_1.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/batt_2.png b/resources/radio/client/radios/AFX-1500/icons/batt_2.png new file mode 100644 index 000000000..4b8059e01 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/batt_2.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/batt_3.png b/resources/radio/client/radios/AFX-1500/icons/batt_3.png new file mode 100644 index 000000000..f0ee52243 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/batt_3.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/batt_4.png b/resources/radio/client/radios/AFX-1500/icons/batt_4.png new file mode 100644 index 000000000..ee2d2e306 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/batt_4.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/batt_5.png b/resources/radio/client/radios/AFX-1500/icons/batt_5.png new file mode 100644 index 000000000..2b32eae97 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/batt_5.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/batt_c.png b/resources/radio/client/radios/AFX-1500/icons/batt_c.png new file mode 100644 index 000000000..e69fc9231 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/batt_c.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/gps.png b/resources/radio/client/radios/AFX-1500/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/gps.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/scan.png b/resources/radio/client/radios/AFX-1500/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/scan.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/sig_1.png b/resources/radio/client/radios/AFX-1500/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/sig_1.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/sig_2.png b/resources/radio/client/radios/AFX-1500/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/sig_2.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/sig_3.png b/resources/radio/client/radios/AFX-1500/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/sig_3.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/sig_4.png b/resources/radio/client/radios/AFX-1500/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/sig_4.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/sig_5.png b/resources/radio/client/radios/AFX-1500/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/sig_5.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/trunk.png b/resources/radio/client/radios/AFX-1500/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/trunk.png differ diff --git a/resources/radio/client/radios/AFX-1500/icons/warn.png b/resources/radio/client/radios/AFX-1500/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/icons/warn.png differ diff --git a/resources/radio/client/radios/AFX-1500/radio-dark.png b/resources/radio/client/radios/AFX-1500/radio-dark.png new file mode 100644 index 000000000..52c733b9d Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/radio-dark.png differ diff --git a/resources/radio/client/radios/AFX-1500/radio.png b/resources/radio/client/radios/AFX-1500/radio.png new file mode 100644 index 000000000..affddb96b Binary files /dev/null and b/resources/radio/client/radios/AFX-1500/radio.png differ diff --git a/resources/radio/client/radios/AFX-1500G/config.json b/resources/radio/client/radios/AFX-1500G/config.json new file mode 100644 index 000000000..94647a196 --- /dev/null +++ b/resources/radio/client/radios/AFX-1500G/config.json @@ -0,0 +1,266 @@ +{ + "toneSet": "default", + "radioWidth": 601, + "radioHeight": 234, + "radioBGColor": "#e8e8e9", + "radioBGDarkColor": "#090808", + "defaultBottomPadding": 50, + "alert": { + "x": 228, + "y": 134, + "width": 174, + "height": 15, + "size": 12, + "color": "#464d49", + "darkColor": "#ffffff" + }, + "time": { + "enabled": true, + "x": 228, + "y": 134, + "color": "#464d49", + "darkColor": "#ffffff", + "width": 77, + "height": 15, + "size": 12 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#ffffff", + "size": 16, + "width": 100, + "height": 15, + "x": 228, + "y": 95 + }, + { + "key": "line2", + "width": 100, + "color": "#464d49", + "darkColor": "#ffffff", + "size": 16, + "height": 15, + "x": 228, + "y": 112 + }, + { + "key": "btn1", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 158, + "y": 150 + }, + { + "key": "btn2", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 203, + "y": 150 + }, + { + "key": "btn3", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 249, + "y": 150 + }, + { + "key": "btn4", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 292, + "y": 150 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 85, + "y": 80, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 505, + "y": 168, + "width": 20, + "height": 20 + }, + { + "key": "btnRight", + "x": 552, + "y": 167, + "width": 22, + "height": 20 + }, + { + "key": "btnUp", + "x": 528, + "y": 142, + "width": 20, + "height": 20 + }, + { + "key": "btnDown", + "x": 530, + "y": 194, + "width": 20, + "height": 20 + }, + { + "key": "chUp", + "x": 354, + "y": 80, + "width": 20, + "height": 25 + }, + { + "key": "chDwn", + "x": 354, + "y": 114, + "width": 20, + "height": 25 + }, + { + "key": "emergency", + "x": 527, + "y": 79, + "width": 25, + "height": 25 + }, + { + "key": "home", + "x": 352, + "y": 196, + "width": 25, + "height": 25 + }, + { + "key": "close", + "x": 353, + "y": 156, + "width": 25, + "height": 25 + }, + { + "key": "btn1", + "x": 154, + "y": 197, + "width": 27, + "height": 25 + }, + { + "key": "btn2", + "x": 203, + "y": 197, + "width": 27, + "height": 25 + }, + { + "key": "btn3", + "x": 252, + "y": 197, + "width": 27, + "height": 25 + }, + { + "key": "btn4", + "x": 300, + "y": 197, + "width": 27, + "height": 25 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 85, + "y": 108, + "width": 20, + "height": 4, + "roundness": 4 + }, + { + "key": "connected", + "color": "green", + "x": 85, + "y": 121, + "width": 20, + "height": 4, + "roundness": 4 + }, + { + "key": "transmit", + "color": "orange", + "x": 85, + "y": 134, + "width": 20, + "height": 4, + "roundness": 4 + } + ], + "icons": [ + { + "key": "sig", + "x": 151, + "y": 80, + "width": 15, + "height": 15 + }, + { + "key": "scan", + "x": 181, + "y": 81, + "width": 13, + "height": 13 + }, + { + "key": "trunk", + "x": 211, + "y": 81, + "width": 13, + "height": 13 + }, + { + "key": "warn", + "x": 241, + "y": 81, + "width": 15, + "height": 15 + }, + { + "key": "gps", + "x": 271, + "y": 81, + "width": 13, + "height": 13 + }, + { + "key": "batt", + "x": 300, + "y": 81, + "width": 16, + "height": 16 + } + ] +} diff --git a/resources/radio/client/radios/AFX-1500G/desktop.ini b/resources/radio/client/radios/AFX-1500G/desktop.ini new file mode 100644 index 000000000..c753ed3b0 --- /dev/null +++ b/resources/radio/client/radios/AFX-1500G/desktop.ini @@ -0,0 +1,4 @@ +[LocalizedFileNames] +radio 2_00012.png=@radio 2_00012.png,0 +radio 3_00002.png=@radio 3_00002.png,0 +radio 3_00003.png=@radio 3_00003.png,0 diff --git a/resources/radio/client/radios/AFX-1500G/icons/batt_0.png b/resources/radio/client/radios/AFX-1500G/icons/batt_0.png new file mode 100644 index 000000000..00885cf1b Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/batt_0.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/batt_1.png b/resources/radio/client/radios/AFX-1500G/icons/batt_1.png new file mode 100644 index 000000000..861711a02 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/batt_1.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/batt_2.png b/resources/radio/client/radios/AFX-1500G/icons/batt_2.png new file mode 100644 index 000000000..4b8059e01 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/batt_2.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/batt_3.png b/resources/radio/client/radios/AFX-1500G/icons/batt_3.png new file mode 100644 index 000000000..f0ee52243 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/batt_3.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/batt_4.png b/resources/radio/client/radios/AFX-1500G/icons/batt_4.png new file mode 100644 index 000000000..ee2d2e306 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/batt_4.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/batt_5.png b/resources/radio/client/radios/AFX-1500G/icons/batt_5.png new file mode 100644 index 000000000..2b32eae97 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/batt_5.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/batt_c.png b/resources/radio/client/radios/AFX-1500G/icons/batt_c.png new file mode 100644 index 000000000..e69fc9231 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/batt_c.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/gps.png b/resources/radio/client/radios/AFX-1500G/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/gps.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/scan.png b/resources/radio/client/radios/AFX-1500G/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/scan.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/sig_1.png b/resources/radio/client/radios/AFX-1500G/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/sig_1.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/sig_2.png b/resources/radio/client/radios/AFX-1500G/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/sig_2.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/sig_3.png b/resources/radio/client/radios/AFX-1500G/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/sig_3.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/sig_4.png b/resources/radio/client/radios/AFX-1500G/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/sig_4.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/sig_5.png b/resources/radio/client/radios/AFX-1500G/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/sig_5.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/trunk.png b/resources/radio/client/radios/AFX-1500G/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/trunk.png differ diff --git a/resources/radio/client/radios/AFX-1500G/icons/warn.png b/resources/radio/client/radios/AFX-1500G/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/icons/warn.png differ diff --git a/resources/radio/client/radios/AFX-1500G/radio-dark.png b/resources/radio/client/radios/AFX-1500G/radio-dark.png new file mode 100644 index 000000000..c0d858adb Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/radio-dark.png differ diff --git a/resources/radio/client/radios/AFX-1500G/radio.png b/resources/radio/client/radios/AFX-1500G/radio.png new file mode 100644 index 000000000..8a5f0fc4a Binary files /dev/null and b/resources/radio/client/radios/AFX-1500G/radio.png differ diff --git a/resources/radio/client/radios/ARX-4000X/config.json b/resources/radio/client/radios/ARX-4000X/config.json new file mode 100644 index 000000000..fda6fe157 --- /dev/null +++ b/resources/radio/client/radios/ARX-4000X/config.json @@ -0,0 +1,253 @@ +{ + "toneSet": "default", + "radioBGColor": "#97abc2", + "radioBGDarkColor": "#434e5f", + "radioWidth": 250, + "radioHeight": 455.61, + "defaultBottomPadding": 0, + "alert": { + "x": 125, + "y": 345, + "width": 108, + "height": 11, + "size": 10, + "color": "#464d49", + "darkColor": "#ffffff" + }, + "time": { + "enabled": true, + "x": 124, + "y": 345, + "color": "#464d49", + "darkColor": "#ffffff", + "width": 77, + "height": 10, + "size": 10 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#ffffff", + "size": 13, + "width": 70, + "height": 13, + "x": 124, + "y": 320 + }, + { + "key": "line2", + "width": 70, + "color": "#464d49", + "darkColor": "#ffffff", + "size": 12, + "height": 12, + "x": 124, + "y": 331 + }, + { + "key": "btn1", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 89, + "y": 358 + }, + { + "key": "btn2", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 125, + "y": 358 + }, + { + "key": "btn3", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 160, + "y": 358 + }, + { + "key": "btn4", + "size": 0 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 57, + "y": 104, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 103, + "y": 432, + "width": 17, + "height": 20 + }, + { + "key": "btnRight", + "x": 148, + "y": 432, + "width": 17, + "height": 20 + }, + { + "key": "btnUp", + "x": 125, + "y": 416, + "width": 20, + "height": 16 + }, + { + "key": "btnDown", + "x": 125, + "y": 444, + "width": 20, + "height": 16 + }, + { + "key": "chUp", + "x": 132, + "y": 91, + "width": 20, + "height": 25 + }, + { + "key": "chDwn", + "x": 115, + "y": 91, + "width": 20, + "height": 25 + }, + { + "key": "emergency", + "x": 159, + "y": 139, + "width": 20, + "height": 10 + }, + { + "key": "home", + "x": 83, + "y": 429, + "width": 15, + "height": 20 + }, + { + "key": "close", + "x": 168, + "y": 430, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 89, + "y": 395, + "width": 22, + "height": 12 + }, + { + "key": "btn2", + "x": 126, + "y": 395, + "width": 22, + "height": 12 + }, + { + "key": "btn3", + "x": 160, + "y": 395, + "width": 22, + "height": 12 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 71, + "y": 200, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "connected", + "color": "green", + "x": 71, + "y": 200, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "transmit", + "color": "orange", + "x": 71, + "y": 200, + "width": 5, + "height": 5, + "roundness": "50%" + } + ], + "icons": [ + { + "key": "sig", + "x": 77, + "y": 308, + "width": 10, + "height": 10 + }, + { + "key": "scan", + "x": 95.4, + "y": 308, + "width": 10, + "height": 10 + }, + { + "key": "trunk", + "x": 113.8, + "y": 308, + "width": 10, + "height": 10 + }, + { + "key": "warn", + "x": 132.2, + "y": 308, + "width": 10, + "height": 10 + }, + { + "key": "gps", + "x": 150.6, + "y": 308, + "width": 10, + "height": 10 + }, + { + "key": "batt", + "x": 169, + "y": 308, + "width": 10, + "height": 10 + } + ] +} diff --git a/resources/radio/client/radios/ARX-4000X/desktop.ini b/resources/radio/client/radios/ARX-4000X/desktop.ini new file mode 100644 index 000000000..0f17be3c2 --- /dev/null +++ b/resources/radio/client/radios/ARX-4000X/desktop.ini @@ -0,0 +1,4 @@ +[LocalizedFileNames] +radio 3_00010.png=@radio 3_00010.png,0 +radio 4_00006.png=@radio 4_00006.png,0 +radio 4_00001.png=@radio 4_00001.png,0 diff --git a/resources/radio/client/radios/ARX-4000X/icons/batt_0.png b/resources/radio/client/radios/ARX-4000X/icons/batt_0.png new file mode 100644 index 000000000..c2a3d05aa Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/batt_0.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/batt_1.png b/resources/radio/client/radios/ARX-4000X/icons/batt_1.png new file mode 100644 index 000000000..7ef04f633 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/batt_1.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/batt_2.png b/resources/radio/client/radios/ARX-4000X/icons/batt_2.png new file mode 100644 index 000000000..53f7464cf Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/batt_2.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/batt_3.png b/resources/radio/client/radios/ARX-4000X/icons/batt_3.png new file mode 100644 index 000000000..58dbfa48d Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/batt_3.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/batt_4.png b/resources/radio/client/radios/ARX-4000X/icons/batt_4.png new file mode 100644 index 000000000..f05237ad2 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/batt_4.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/batt_5.png b/resources/radio/client/radios/ARX-4000X/icons/batt_5.png new file mode 100644 index 000000000..dbc82f6b7 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/batt_5.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/batt_c.png b/resources/radio/client/radios/ARX-4000X/icons/batt_c.png new file mode 100644 index 000000000..75e103f49 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/batt_c.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/gps.png b/resources/radio/client/radios/ARX-4000X/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/gps.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/scan.png b/resources/radio/client/radios/ARX-4000X/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/scan.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/sig_1.png b/resources/radio/client/radios/ARX-4000X/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/sig_1.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/sig_2.png b/resources/radio/client/radios/ARX-4000X/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/sig_2.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/sig_3.png b/resources/radio/client/radios/ARX-4000X/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/sig_3.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/sig_4.png b/resources/radio/client/radios/ARX-4000X/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/sig_4.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/sig_5.png b/resources/radio/client/radios/ARX-4000X/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/sig_5.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/trunk.png b/resources/radio/client/radios/ARX-4000X/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/trunk.png differ diff --git a/resources/radio/client/radios/ARX-4000X/icons/warn.png b/resources/radio/client/radios/ARX-4000X/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/icons/warn.png differ diff --git a/resources/radio/client/radios/ARX-4000X/radio-dark.png b/resources/radio/client/radios/ARX-4000X/radio-dark.png new file mode 100644 index 000000000..c35bcfcef Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/radio-dark.png differ diff --git a/resources/radio/client/radios/ARX-4000X/radio.png b/resources/radio/client/radios/ARX-4000X/radio.png new file mode 100644 index 000000000..f0927484a Binary files /dev/null and b/resources/radio/client/radios/ARX-4000X/radio.png differ diff --git a/resources/radio/client/radios/ATX-8000/config.json b/resources/radio/client/radios/ATX-8000/config.json new file mode 100644 index 000000000..c991fac90 --- /dev/null +++ b/resources/radio/client/radios/ATX-8000/config.json @@ -0,0 +1,253 @@ +{ + "toneSet": "default", + "radioBGColor": "#d2e4db", + "radioBGDarkColor": "#101413", + "radioWidth": 300, + "radioHeight": 406, + "defaultBottomPadding": 0, + "alert": { + "x": 102, + "y": 306, + "width": 75, + "height": 15, + "size": 12, + "color": "#464d49", + "darkColor": "#ffffff" + }, + "time": { + "enabled": true, + "x": 102, + "y": 306, + "color": "#464d49", + "darkColor": "#ffffff", + "width": 77, + "height": 14, + "size": 11 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#ffffff", + "size": 14, + "width": 70, + "height": 15, + "x": 102, + "y": 275 + }, + { + "key": "line2", + "width": 70, + "color": "#464d49", + "darkColor": "#ffffff", + "size": 14, + "height": 15, + "x": 102, + "y": 290 + }, + { + "key": "btn1", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 76, + "y": 319 + }, + { + "key": "btn2", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 101, + "y": 319 + }, + { + "key": "btn3", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 127, + "y": 319 + }, + { + "key": "btn4", + "size": 0 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 180, + "y": 161, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 86, + "y": 381, + "width": 17, + "height": 20 + }, + { + "key": "btnRight", + "x": 120, + "y": 381, + "width": 17, + "height": 20 + }, + { + "key": "btnUp", + "x": 104, + "y": 366, + "width": 20, + "height": 16 + }, + { + "key": "btnDown", + "x": 104, + "y": 395, + "width": 20, + "height": 16 + }, + { + "key": "chUp", + "x": 110, + "y": 145, + "width": 20, + "height": 25 + }, + { + "key": "chDwn", + "x": 92, + "y": 145, + "width": 20, + "height": 25 + }, + { + "key": "emergency", + "x": 63, + "y": 181, + "width": 20, + "height": 10 + }, + { + "key": "home", + "x": 67, + "y": 381, + "width": 15, + "height": 20 + }, + { + "key": "close", + "x": 141, + "y": 381, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 76, + "y": 348, + "width": 22, + "height": 12 + }, + { + "key": "btn2", + "x": 104, + "y": 348, + "width": 22, + "height": 12 + }, + { + "key": "btn3", + "x": 129, + "y": 348, + "width": 22, + "height": 12 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 75, + "y": 222, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "connected", + "color": "green", + "x": 75, + "y": 222, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "transmit", + "color": "orange", + "x": 75, + "y": 222, + "width": 5, + "height": 5, + "roundness": "50%" + } + ], + "icons": [ + { + "key": "sig", + "x": 72, + "y": 256, + "width": 10, + "height": 10 + }, + { + "key": "scan", + "x": 84, + "y": 257, + "width": 10, + "height": 10 + }, + { + "key": "trunk", + "x": 96, + "y": 257, + "width": 10, + "height": 10 + }, + { + "key": "warn", + "x": 108, + "y": 257, + "width": 10, + "height": 10 + }, + { + "key": "gps", + "x": 120, + "y": 257, + "width": 10, + "height": 10 + }, + { + "key": "batt", + "x": 132, + "y": 257, + "width": 10, + "height": 10 + } + ] +} diff --git a/resources/radio/client/radios/ATX-8000/desktop.ini b/resources/radio/client/radios/ATX-8000/desktop.ini new file mode 100644 index 000000000..fb5170fe0 --- /dev/null +++ b/resources/radio/client/radios/ATX-8000/desktop.ini @@ -0,0 +1,4 @@ +[LocalizedFileNames] +radio 6_00013.png=@radio 6_00013.png,0 +radio_00005.png=@radio_00005.png,0 +radio_00014.png=@radio_00014.png,0 diff --git a/resources/radio/client/radios/ATX-8000/icons/batt_0.png b/resources/radio/client/radios/ATX-8000/icons/batt_0.png new file mode 100644 index 000000000..c2a3d05aa Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/batt_0.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/batt_1.png b/resources/radio/client/radios/ATX-8000/icons/batt_1.png new file mode 100644 index 000000000..7ef04f633 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/batt_1.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/batt_2.png b/resources/radio/client/radios/ATX-8000/icons/batt_2.png new file mode 100644 index 000000000..53f7464cf Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/batt_2.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/batt_3.png b/resources/radio/client/radios/ATX-8000/icons/batt_3.png new file mode 100644 index 000000000..58dbfa48d Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/batt_3.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/batt_4.png b/resources/radio/client/radios/ATX-8000/icons/batt_4.png new file mode 100644 index 000000000..f05237ad2 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/batt_4.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/batt_5.png b/resources/radio/client/radios/ATX-8000/icons/batt_5.png new file mode 100644 index 000000000..dbc82f6b7 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/batt_5.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/batt_c.png b/resources/radio/client/radios/ATX-8000/icons/batt_c.png new file mode 100644 index 000000000..75e103f49 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/batt_c.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/gps.png b/resources/radio/client/radios/ATX-8000/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/gps.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/scan.png b/resources/radio/client/radios/ATX-8000/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/scan.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/sig_1.png b/resources/radio/client/radios/ATX-8000/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/sig_1.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/sig_2.png b/resources/radio/client/radios/ATX-8000/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/sig_2.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/sig_3.png b/resources/radio/client/radios/ATX-8000/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/sig_3.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/sig_4.png b/resources/radio/client/radios/ATX-8000/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/sig_4.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/sig_5.png b/resources/radio/client/radios/ATX-8000/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/sig_5.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/trunk.png b/resources/radio/client/radios/ATX-8000/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/trunk.png differ diff --git a/resources/radio/client/radios/ATX-8000/icons/warn.png b/resources/radio/client/radios/ATX-8000/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/icons/warn.png differ diff --git a/resources/radio/client/radios/ATX-8000/radio-dark.png b/resources/radio/client/radios/ATX-8000/radio-dark.png new file mode 100644 index 000000000..8711460ca Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/radio-dark.png differ diff --git a/resources/radio/client/radios/ATX-8000/radio.png b/resources/radio/client/radios/ATX-8000/radio.png new file mode 100644 index 000000000..f2efd41e1 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000/radio.png differ diff --git a/resources/radio/client/radios/ATX-8000G/config.json b/resources/radio/client/radios/ATX-8000G/config.json new file mode 100644 index 000000000..9decf15c5 --- /dev/null +++ b/resources/radio/client/radios/ATX-8000G/config.json @@ -0,0 +1,253 @@ +{ + "toneSet": "default", + "radioBGColor": "#c7f1de", + "radioBGDarkColor": "#111812", + "radioWidth": 250, + "radioHeight": 458.13, + "defaultBottomPadding": 0, + "alert": { + "x": 122, + "y": 348, + "width": 82, + "height": 14, + "size": 12, + "color": "#464d49", + "darkColor": "#ffffff" + }, + "time": { + "enabled": true, + "x": 122, + "y": 348, + "color": "#464d49", + "darkColor": "#ffffff", + "width": 80, + "height": 14, + "size": 11 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#ffffff", + "size": 14, + "width": 70, + "height": 15, + "x": 122, + "y": 310 + }, + { + "key": "line2", + "width": 70, + "color": "#464d49", + "darkColor": "#ffffff", + "size": 14, + "height": 15, + "x": 122, + "y": 325 + }, + { + "key": "btn1", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 93, + "y": 362 + }, + { + "key": "btn2", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 121, + "y": 362 + }, + { + "key": "btn3", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 151, + "y": 362 + }, + { + "key": "btn4", + "size": 0 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 209, + "y": 157, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 103, + "y": 431, + "width": 17, + "height": 20 + }, + { + "key": "btnRight", + "x": 145, + "y": 431, + "width": 17, + "height": 20 + }, + { + "key": "btnUp", + "x": 121, + "y": 416, + "width": 20, + "height": 16 + }, + { + "key": "btnDown", + "x": 121, + "y": 444, + "width": 20, + "height": 16 + }, + { + "key": "chUp", + "x": 140, + "y": 125, + "width": 20, + "height": 25 + }, + { + "key": "chDwn", + "x": 105, + "y": 127, + "width": 20, + "height": 25 + }, + { + "key": "emergency", + "x": 73, + "y": 171, + "width": 20, + "height": 10 + }, + { + "key": "home", + "x": 82, + "y": 430, + "width": 15, + "height": 20 + }, + { + "key": "close", + "x": 166, + "y": 431, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 92, + "y": 395, + "width": 22, + "height": 12 + }, + { + "key": "btn2", + "x": 122, + "y": 395, + "width": 22, + "height": 12 + }, + { + "key": "btn3", + "x": 153, + "y": 395, + "width": 22, + "height": 12 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 94, + "y": 254, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "connected", + "color": "green", + "x": 94, + "y": 254, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "transmit", + "color": "orange", + "x": 94, + "y": 254, + "width": 5, + "height": 5, + "roundness": "50%" + } + ], + "icons": [ + { + "key": "sig", + "x": 87, + "y": 290, + "width": 10, + "height": 10 + }, + { + "key": "scan", + "x": 101, + "y": 290, + "width": 10, + "height": 10 + }, + { + "key": "trunk", + "x": 115, + "y": 290, + "width": 10, + "height": 10 + }, + { + "key": "warn", + "x": 129, + "y": 290, + "width": 10, + "height": 10 + }, + { + "key": "gps", + "x": 143, + "y": 290, + "width": 10, + "height": 10 + }, + { + "key": "batt", + "x": 157, + "y": 290, + "width": 10, + "height": 10 + } + ] +} diff --git a/resources/radio/client/radios/ATX-8000G/desktop.ini b/resources/radio/client/radios/ATX-8000G/desktop.ini new file mode 100644 index 000000000..114ee294d --- /dev/null +++ b/resources/radio/client/radios/ATX-8000G/desktop.ini @@ -0,0 +1,4 @@ +[LocalizedFileNames] +radio 7_00019.png=@radio 7_00019.png,0 +radio 5_00013.png=@radio 5_00013.png,0 +radio 5_00010.png=@radio 5_00010.png,0 diff --git a/resources/radio/client/radios/ATX-8000G/icons/batt_0.png b/resources/radio/client/radios/ATX-8000G/icons/batt_0.png new file mode 100644 index 000000000..c2a3d05aa Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/batt_0.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/batt_1.png b/resources/radio/client/radios/ATX-8000G/icons/batt_1.png new file mode 100644 index 000000000..7ef04f633 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/batt_1.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/batt_2.png b/resources/radio/client/radios/ATX-8000G/icons/batt_2.png new file mode 100644 index 000000000..53f7464cf Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/batt_2.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/batt_3.png b/resources/radio/client/radios/ATX-8000G/icons/batt_3.png new file mode 100644 index 000000000..58dbfa48d Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/batt_3.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/batt_4.png b/resources/radio/client/radios/ATX-8000G/icons/batt_4.png new file mode 100644 index 000000000..f05237ad2 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/batt_4.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/batt_5.png b/resources/radio/client/radios/ATX-8000G/icons/batt_5.png new file mode 100644 index 000000000..dbc82f6b7 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/batt_5.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/batt_c.png b/resources/radio/client/radios/ATX-8000G/icons/batt_c.png new file mode 100644 index 000000000..75e103f49 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/batt_c.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/gps.png b/resources/radio/client/radios/ATX-8000G/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/gps.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/scan.png b/resources/radio/client/radios/ATX-8000G/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/scan.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/sig_1.png b/resources/radio/client/radios/ATX-8000G/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/sig_1.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/sig_2.png b/resources/radio/client/radios/ATX-8000G/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/sig_2.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/sig_3.png b/resources/radio/client/radios/ATX-8000G/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/sig_3.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/sig_4.png b/resources/radio/client/radios/ATX-8000G/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/sig_4.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/sig_5.png b/resources/radio/client/radios/ATX-8000G/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/sig_5.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/trunk.png b/resources/radio/client/radios/ATX-8000G/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/trunk.png differ diff --git a/resources/radio/client/radios/ATX-8000G/icons/warn.png b/resources/radio/client/radios/ATX-8000G/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/icons/warn.png differ diff --git a/resources/radio/client/radios/ATX-8000G/radio-dark.png b/resources/radio/client/radios/ATX-8000G/radio-dark.png new file mode 100644 index 000000000..21e82378e Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/radio-dark.png differ diff --git a/resources/radio/client/radios/ATX-8000G/radio.png b/resources/radio/client/radios/ATX-8000G/radio.png new file mode 100644 index 000000000..cb9974527 Binary files /dev/null and b/resources/radio/client/radios/ATX-8000G/radio.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/config.json b/resources/radio/client/radios/ATX-NOVA/config.json new file mode 100644 index 000000000..3ec122d32 --- /dev/null +++ b/resources/radio/client/radios/ATX-NOVA/config.json @@ -0,0 +1,256 @@ +{ + "toneSet": "default", + "radioBGColor": "#fefffe", + "radioBGDarkColor": "#000101", + "font": "Mustica.otf", + "fontSize": 12, + "fontWeight": "normal", + "radioWidth": 242, + "radioHeight": 406, + "defaultBottomPadding": 0, + "alert": { + "x": 123, + "y": 229, + "width": 92, + "height": 25, + "size": 14, + "color": "#464d49", + "darkColor": "#ffffff" + }, + "time": { + "enabled": true, + "x": 123, + "y": 229, + "color": "#464d49", + "darkColor": "#ffffff", + "width": 88, + "height": 23, + "size": 14 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#ffffff", + "size": 14, + "width": 70, + "height": 15, + "x": 126, + "y": 169 + }, + { + "key": "line2", + "width": 70, + "color": "#464d49", + "darkColor": "#ffffff", + "size": 14, + "height": 15, + "x": 126, + "y": 191 + }, + { + "key": "btn1", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 88, + "y": 253 + }, + { + "key": "btn2", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 122, + "y": 253 + }, + { + "key": "btn3", + "width": 22, + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 9, + "height": 10, + "x": 156, + "y": 253 + }, + { + "key": "btn4", + "size": 0 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 67, + "y": 52, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 84, + "y": 356, + "width": 17, + "height": 20 + }, + { + "key": "btnRight", + "x": 161, + "y": 356, + "width": 17, + "height": 20 + }, + { + "key": "btnUp", + "x": 122, + "y": 327, + "width": 20, + "height": 16 + }, + { + "key": "btnDown", + "x": 124, + "y": 387, + "width": 20, + "height": 16 + }, + { + "key": "chUp", + "x": 132, + "y": 29, + "width": 20, + "height": 25 + }, + { + "key": "chDwn", + "x": 115, + "y": 32, + "width": 20, + "height": 25 + }, + { + "key": "emergency", + "x": 152, + "y": 73, + "width": 20, + "height": 10 + }, + { + "key": "home", + "x": 86, + "y": 326, + "width": 15, + "height": 20 + }, + { + "key": "close", + "x": 160, + "y": 326, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 91, + "y": 297, + "width": 22, + "height": 12 + }, + { + "key": "btn2", + "x": 122, + "y": 297, + "width": 22, + "height": 12 + }, + { + "key": "btn3", + "x": 155, + "y": 297, + "width": 22, + "height": 12 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 58, + "y": 101, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "connected", + "color": "green", + "x": 58, + "y": 101, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "transmit", + "color": "orange", + "x": 58, + "y": 101, + "width": 5, + "height": 5, + "roundness": "50%" + } + ], + "icons": [ + { + "key": "sig", + "x": 80, + "y": 133, + "width": 10, + "height": 10 + }, + { + "key": "scan", + "x": 97, + "y": 132, + "width": 10, + "height": 10 + }, + { + "key": "trunk", + "x": 114, + "y": 132, + "width": 10, + "height": 10 + }, + { + "key": "warn", + "x": 131, + "y": 132, + "width": 10, + "height": 10 + }, + { + "key": "gps", + "x": 148, + "y": 132, + "width": 10, + "height": 10 + }, + { + "key": "batt", + "x": 166, + "y": 132, + "width": 10, + "height": 10 + } + ] +} diff --git a/resources/radio/client/radios/ATX-NOVA/desktop.ini b/resources/radio/client/radios/ATX-NOVA/desktop.ini new file mode 100644 index 000000000..d70141cc4 --- /dev/null +++ b/resources/radio/client/radios/ATX-NOVA/desktop.ini @@ -0,0 +1,4 @@ +[LocalizedFileNames] +radio 8_00003.png=@radio 8_00003.png,0 +radio 6_00005.png=@RADIO6~1.PNG,0 +radio 6_00010.png=@RADIO6~1.PNG,0 diff --git a/resources/radio/client/radios/ATX-NOVA/fonts/Mustica.otf b/resources/radio/client/radios/ATX-NOVA/fonts/Mustica.otf new file mode 100644 index 000000000..710e7d5fe Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/fonts/Mustica.otf differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/batt_0.png b/resources/radio/client/radios/ATX-NOVA/icons/batt_0.png new file mode 100644 index 000000000..c2a3d05aa Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/batt_0.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/batt_1.png b/resources/radio/client/radios/ATX-NOVA/icons/batt_1.png new file mode 100644 index 000000000..7ef04f633 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/batt_1.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/batt_2.png b/resources/radio/client/radios/ATX-NOVA/icons/batt_2.png new file mode 100644 index 000000000..53f7464cf Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/batt_2.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/batt_3.png b/resources/radio/client/radios/ATX-NOVA/icons/batt_3.png new file mode 100644 index 000000000..58dbfa48d Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/batt_3.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/batt_4.png b/resources/radio/client/radios/ATX-NOVA/icons/batt_4.png new file mode 100644 index 000000000..f05237ad2 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/batt_4.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/batt_5.png b/resources/radio/client/radios/ATX-NOVA/icons/batt_5.png new file mode 100644 index 000000000..dbc82f6b7 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/batt_5.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/batt_c.png b/resources/radio/client/radios/ATX-NOVA/icons/batt_c.png new file mode 100644 index 000000000..75e103f49 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/batt_c.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/gps.png b/resources/radio/client/radios/ATX-NOVA/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/gps.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/scan.png b/resources/radio/client/radios/ATX-NOVA/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/scan.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/sig_1.png b/resources/radio/client/radios/ATX-NOVA/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/sig_1.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/sig_2.png b/resources/radio/client/radios/ATX-NOVA/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/sig_2.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/sig_3.png b/resources/radio/client/radios/ATX-NOVA/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/sig_3.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/sig_4.png b/resources/radio/client/radios/ATX-NOVA/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/sig_4.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/sig_5.png b/resources/radio/client/radios/ATX-NOVA/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/sig_5.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/trunk.png b/resources/radio/client/radios/ATX-NOVA/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/trunk.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/icons/warn.png b/resources/radio/client/radios/ATX-NOVA/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/icons/warn.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/radio-dark.png b/resources/radio/client/radios/ATX-NOVA/radio-dark.png new file mode 100644 index 000000000..788aabfc6 Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/radio-dark.png differ diff --git a/resources/radio/client/radios/ATX-NOVA/radio.png b/resources/radio/client/radios/ATX-NOVA/radio.png new file mode 100644 index 000000000..d8d74363d Binary files /dev/null and b/resources/radio/client/radios/ATX-NOVA/radio.png differ diff --git a/resources/radio/client/radios/TXDF-9100/config.json b/resources/radio/client/radios/TXDF-9100/config.json new file mode 100644 index 000000000..6eb705b7e --- /dev/null +++ b/resources/radio/client/radios/TXDF-9100/config.json @@ -0,0 +1,210 @@ +{ + "toneSet": "default", + "font": "Charmset.ttf", + "fontSize": 12, + "fontWeight": "normal", + "radioWidth": 550, + "radioHeight": 293.33, + "radioBGColor": "#000000", + "defaultBottomPadding": 50, + "alert": { + "x": 274, + "y": 36, + "width": 428, + "height": 19, + "size": 12 + }, + "time": { + "enabled": true, + "x": 115, + "y": 131, + "color": "#14ab03", + "width": 80, + "height": 14, + "size": 13 + }, + "texts": [ + { + "key": "line1", + "color": "#14ab03", + "size": 19, + "width": 200, + "height": 25, + "x": 272, + "y": 60 + }, + { + "key": "line2", + "width": 200, + "color": "#14ab03", + "size": 19, + "height": 25, + "x": 272, + "y": 90 + }, + { + "key": "btn1", + "color": "#14ab03", + "size": 10, + "width": 25, + "height": 14, + "x": 302, + "y": 127 + }, + { + "key": "btn2", + "color": "#14ab03", + "size": 10, + "width": 25, + "height": 14, + "x": 357, + "y": 127 + }, + { + "key": "btn3", + "color": "#14ab03", + "size": 10, + "width": 25, + "height": 14, + "x": 412, + "y": 127 + }, + { + "key": "btn4", + "color": "#14ab03", + "size": 10, + "width": 25, + "height": 14, + "x": 467, + "y": 127 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 95, + "y": 232, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 299, + "y": 213, + "width": 20, + "height": 20 + }, + { + "key": "btnRight", + "x": 414, + "y": 215, + "width": 20, + "height": 20 + }, + { + "key": "btnUp", + "x": 355, + "y": 215, + "width": 20, + "height": 20 + }, + { + "key": "btnDown", + "x": 355, + "y": 253, + "width": 20, + "height": 20 + }, + { + "key": "home", + "x": 81, + "y": 175, + "width": 20, + "height": 20 + }, + { + "key": "close", + "x": 175, + "y": 228, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 301, + "y": 176, + "width": 27, + "height": 27 + }, + { + "key": "btn2", + "x": 356, + "y": 176, + "width": 27, + "height": 27 + }, + { + "key": "btn3", + "x": 412, + "y": 176, + "width": 27, + "height": 27 + }, + { + "key": "btn4", + "x": 467, + "y": 176, + "width": 25, + "height": 25 + } + ], + "leds": [], + "icons": [ + { + "key": "sig", + "x": 77, + "y": 56, + "width": 15, + "height": 15 + }, + { + "key": "batt", + "x": 77, + "y": 81, + "width": 16, + "height": 16 + }, + { + "key": "warn", + "x": 77, + "y": 107, + "width": 15, + "height": 15 + }, + { + "key": "scan", + "x": 182, + "y": 127, + "width": 13, + "height": 13 + }, + { + "key": "trunk", + "x": 215, + "y": 127, + "width": 13, + "height": 13 + }, + { + "key": "gps", + "x": 255, + "y": 127, + "width": 13, + "height": 13 + } + ] +} diff --git a/resources/radio/client/radios/TXDF-9100/desktop.ini b/resources/radio/client/radios/TXDF-9100/desktop.ini new file mode 100644 index 000000000..8068917c3 --- /dev/null +++ b/resources/radio/client/radios/TXDF-9100/desktop.ini @@ -0,0 +1,2 @@ +[LocalizedFileNames] +radio 9_00017.png=@radio 9_00017.png,0 diff --git a/resources/radio/client/radios/TXDF-9100/fonts/Charmset.ttf b/resources/radio/client/radios/TXDF-9100/fonts/Charmset.ttf new file mode 100644 index 000000000..0529390da Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/fonts/Charmset.ttf differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/batt_0.png b/resources/radio/client/radios/TXDF-9100/icons/batt_0.png new file mode 100644 index 000000000..00885cf1b Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/batt_0.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/batt_1.png b/resources/radio/client/radios/TXDF-9100/icons/batt_1.png new file mode 100644 index 000000000..861711a02 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/batt_1.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/batt_2.png b/resources/radio/client/radios/TXDF-9100/icons/batt_2.png new file mode 100644 index 000000000..4b8059e01 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/batt_2.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/batt_3.png b/resources/radio/client/radios/TXDF-9100/icons/batt_3.png new file mode 100644 index 000000000..f0ee52243 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/batt_3.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/batt_4.png b/resources/radio/client/radios/TXDF-9100/icons/batt_4.png new file mode 100644 index 000000000..ee2d2e306 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/batt_4.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/batt_5.png b/resources/radio/client/radios/TXDF-9100/icons/batt_5.png new file mode 100644 index 000000000..2b32eae97 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/batt_5.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/batt_c.png b/resources/radio/client/radios/TXDF-9100/icons/batt_c.png new file mode 100644 index 000000000..e69fc9231 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/batt_c.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/gps.png b/resources/radio/client/radios/TXDF-9100/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/gps.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/scan.png b/resources/radio/client/radios/TXDF-9100/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/scan.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/sig_1.png b/resources/radio/client/radios/TXDF-9100/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/sig_1.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/sig_2.png b/resources/radio/client/radios/TXDF-9100/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/sig_2.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/sig_3.png b/resources/radio/client/radios/TXDF-9100/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/sig_3.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/sig_4.png b/resources/radio/client/radios/TXDF-9100/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/sig_4.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/sig_5.png b/resources/radio/client/radios/TXDF-9100/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/sig_5.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/trunk.png b/resources/radio/client/radios/TXDF-9100/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/trunk.png differ diff --git a/resources/radio/client/radios/TXDF-9100/icons/warn.png b/resources/radio/client/radios/TXDF-9100/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/icons/warn.png differ diff --git a/resources/radio/client/radios/TXDF-9100/radio.png b/resources/radio/client/radios/TXDF-9100/radio.png new file mode 100644 index 000000000..ea25e02b3 Binary files /dev/null and b/resources/radio/client/radios/TXDF-9100/radio.png differ diff --git a/resources/radio/client/radios/XPR-6500/config.json b/resources/radio/client/radios/XPR-6500/config.json new file mode 100644 index 000000000..a0d77af93 --- /dev/null +++ b/resources/radio/client/radios/XPR-6500/config.json @@ -0,0 +1,252 @@ +{ + "toneSet": "default", + "radioWidth": 630, + "radioHeight": 200, + "radioBGColor": "#ffffff", + "radioBGDarkColor": "#000101", + "defaultBottomPadding": 50, + "alert": { + "x": 313, + "y": 102, + "width": 277, + "height": 19, + "size": 12, + "color": "#464d49", + "darkColor": "#ffffff" + }, + "time": { + "enabled": true, + "x": 314, + "y": 100, + "color": "#464d49", + "darkColor": "#ffffff", + "width": 150, + "height": 17, + "size": 13 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#ffffff", + "size": 17, + "width": 200, + "height": 17, + "x": 314, + "y": 60 + }, + { + "key": "line2", + "width": 200, + "color": "#464d49", + "darkColor": "#ffffff", + "size": 17, + "height": 17, + "x": 314, + "y": 80 + }, + { + "key": "btn1", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 201, + "y": 122 + }, + { + "key": "btn2", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 258, + "y": 122 + }, + { + "key": "btn3", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 315, + "y": 122 + }, + { + "key": "btn4", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 372, + "y": 121 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 45, + "y": 44, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 498, + "y": 138, + "width": 20, + "height": 20 + }, + { + "key": "btnRight", + "x": 545, + "y": 137, + "width": 20, + "height": 20 + }, + { + "key": "btnUp", + "x": 520, + "y": 112, + "width": 20, + "height": 20 + }, + { + "key": "btnDown", + "x": 521, + "y": 160, + "width": 20, + "height": 20 + }, + { + "key": "emergency", + "x": 587, + "y": 45, + "width": 20, + "height": 20 + }, + { + "key": "home", + "x": 585, + "y": 156, + "width": 20, + "height": 20 + }, + { + "key": "close", + "x": 130, + "y": 112, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 192, + "y": 160, + "width": 27, + "height": 27 + }, + { + "key": "btn2", + "x": 254, + "y": 160, + "width": 27, + "height": 27 + }, + { + "key": "btn3", + "x": 314, + "y": 160, + "width": 27, + "height": 27 + }, + { + "key": "btn4", + "x": 374, + "y": 161, + "width": 25, + "height": 25 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 69, + "y": 63, + "width": 18, + "height": 3, + "roundness": 3 + }, + { + "key": "connected", + "color": "green", + "x": 69, + "y": 74, + "width": 18, + "height": 3, + "roundness": 3 + }, + { + "key": "transmit", + "color": "orange", + "x": 69, + "y": 85, + "width": 18, + "height": 3, + "roundness": 3 + } + ], + "icons": [ + { + "key": "sig", + "x": 185, + "y": 41, + "width": 15, + "height": 15 + }, + { + "key": "scan", + "x": 204, + "y": 44, + "width": 13, + "height": 13 + }, + { + "key": "trunk", + "x": 223, + "y": 44, + "width": 13, + "height": 13 + }, + { + "key": "warn", + "x": 403, + "y": 44, + "width": 15, + "height": 15 + }, + { + "key": "gps", + "x": 422, + "y": 44, + "width": 13, + "height": 13 + }, + { + "key": "batt", + "x": 441, + "y": 44, + "width": 16, + "height": 16 + } + ] +} diff --git a/resources/radio/client/radios/XPR-6500/desktop.ini b/resources/radio/client/radios/XPR-6500/desktop.ini new file mode 100644 index 000000000..4351ef3c4 --- /dev/null +++ b/resources/radio/client/radios/XPR-6500/desktop.ini @@ -0,0 +1,4 @@ +[LocalizedFileNames] +radio 4_00009.png=@radio 4_00009.png,0 +radio 7_00004.png=@radio 7_00004.png,0 +radio 7_00011.png=@radio 7_00011.png,0 diff --git a/resources/radio/client/radios/XPR-6500/icons/batt_0.png b/resources/radio/client/radios/XPR-6500/icons/batt_0.png new file mode 100644 index 000000000..00885cf1b Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/batt_0.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/batt_1.png b/resources/radio/client/radios/XPR-6500/icons/batt_1.png new file mode 100644 index 000000000..861711a02 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/batt_1.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/batt_2.png b/resources/radio/client/radios/XPR-6500/icons/batt_2.png new file mode 100644 index 000000000..4b8059e01 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/batt_2.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/batt_3.png b/resources/radio/client/radios/XPR-6500/icons/batt_3.png new file mode 100644 index 000000000..f0ee52243 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/batt_3.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/batt_4.png b/resources/radio/client/radios/XPR-6500/icons/batt_4.png new file mode 100644 index 000000000..ee2d2e306 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/batt_4.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/batt_5.png b/resources/radio/client/radios/XPR-6500/icons/batt_5.png new file mode 100644 index 000000000..2b32eae97 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/batt_5.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/batt_c.png b/resources/radio/client/radios/XPR-6500/icons/batt_c.png new file mode 100644 index 000000000..e69fc9231 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/batt_c.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/gps.png b/resources/radio/client/radios/XPR-6500/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/gps.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/scan.png b/resources/radio/client/radios/XPR-6500/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/scan.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/sig_1.png b/resources/radio/client/radios/XPR-6500/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/sig_1.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/sig_2.png b/resources/radio/client/radios/XPR-6500/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/sig_2.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/sig_3.png b/resources/radio/client/radios/XPR-6500/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/sig_3.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/sig_4.png b/resources/radio/client/radios/XPR-6500/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/sig_4.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/sig_5.png b/resources/radio/client/radios/XPR-6500/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/sig_5.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/trunk.png b/resources/radio/client/radios/XPR-6500/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/trunk.png differ diff --git a/resources/radio/client/radios/XPR-6500/icons/warn.png b/resources/radio/client/radios/XPR-6500/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/icons/warn.png differ diff --git a/resources/radio/client/radios/XPR-6500/radio-dark.png b/resources/radio/client/radios/XPR-6500/radio-dark.png new file mode 100644 index 000000000..f6150d941 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/radio-dark.png differ diff --git a/resources/radio/client/radios/XPR-6500/radio.png b/resources/radio/client/radios/XPR-6500/radio.png new file mode 100644 index 000000000..10af7b9c3 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500/radio.png differ diff --git a/resources/radio/client/radios/XPR-6500S/config.json b/resources/radio/client/radios/XPR-6500S/config.json new file mode 100644 index 000000000..41c93fdb0 --- /dev/null +++ b/resources/radio/client/radios/XPR-6500S/config.json @@ -0,0 +1,252 @@ +{ + "toneSet": "default", + "radioWidth": 550, + "radioHeight": 270, + "radioBGColor": "#f2f1f1", + "radioBGDarkColor": "#050505", + "defaultBottomPadding": 50, + "alert": { + "x": 200, + "y": 154, + "width": 176, + "height": 17, + "size": 12, + "color": "#464d49", + "darkColor": "#ffffff" + }, + "time": { + "enabled": true, + "x": 200, + "y": 154, + "color": "#464d49", + "darkColor": "#ffffff", + "width": 175, + "height": 17, + "size": 13 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#ffffff", + "size": 17, + "width": 180, + "height": 17, + "x": 200, + "y": 121 + }, + { + "key": "line2", + "width": 180, + "color": "#464d49", + "darkColor": "#ffffff", + "size": 15, + "height": 15, + "x": 200, + "y": 135 + }, + { + "key": "btn1", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 131, + "y": 171 + }, + { + "key": "btn2", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 176, + "y": 171 + }, + { + "key": "btn3", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 222, + "y": 171 + }, + { + "key": "btn4", + "color": "#e6efeb", + "darkColor": "#ffffff", + "size": 10, + "width": 25, + "height": 14, + "x": 267, + "y": 171 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 42, + "y": 106, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 320, + "y": 184, + "width": 20, + "height": 20 + }, + { + "key": "btnRight", + "x": 363, + "y": 184, + "width": 20, + "height": 20 + }, + { + "key": "btnUp", + "x": 342, + "y": 163, + "width": 20, + "height": 20 + }, + { + "key": "btnDown", + "x": 341, + "y": 204, + "width": 20, + "height": 20 + }, + { + "key": "emergency", + "x": 509, + "y": 107, + "width": 20, + "height": 20 + }, + { + "key": "home", + "x": 402, + "y": 201, + "width": 20, + "height": 20 + }, + { + "key": "close", + "x": 71, + "y": 140, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 130, + "y": 206, + "width": 27, + "height": 27 + }, + { + "key": "btn2", + "x": 176, + "y": 206, + "width": 27, + "height": 27 + }, + { + "key": "btn3", + "x": 222, + "y": 206, + "width": 27, + "height": 27 + }, + { + "key": "btn4", + "x": 267, + "y": 206, + "width": 25, + "height": 25 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 71, + "y": 96, + "width": 15, + "height": 2, + "roundness": 3 + }, + { + "key": "connected", + "color": "green", + "x": 71, + "y": 106.5, + "width": 15, + "height": 2, + "roundness": 3 + }, + { + "key": "transmit", + "color": "orange", + "x": 71, + "y": 117, + "width": 15, + "height": 2, + "roundness": 3 + } + ], + "icons": [ + { + "key": "sig", + "x": 125, + "y": 105, + "width": 15, + "height": 15 + }, + { + "key": "scan", + "x": 152, + "y": 105, + "width": 13, + "height": 13 + }, + { + "key": "trunk", + "x": 184, + "y": 105, + "width": 13, + "height": 13 + }, + { + "key": "warn", + "x": 216, + "y": 105, + "width": 15, + "height": 15 + }, + { + "key": "gps", + "x": 247, + "y": 105, + "width": 13, + "height": 13 + }, + { + "key": "batt", + "x": 275, + "y": 105, + "width": 16, + "height": 16 + } + ] +} diff --git a/resources/radio/client/radios/XPR-6500S/desktop.ini b/resources/radio/client/radios/XPR-6500S/desktop.ini new file mode 100644 index 000000000..68fdad257 --- /dev/null +++ b/resources/radio/client/radios/XPR-6500S/desktop.ini @@ -0,0 +1,3 @@ +[LocalizedFileNames] +radio 5_00014.png=@radio 5_00014.png,0 +radio 8_00010.png=@radio 8_00010.png,0 diff --git a/resources/radio/client/radios/XPR-6500S/icons/batt_0.png b/resources/radio/client/radios/XPR-6500S/icons/batt_0.png new file mode 100644 index 000000000..00885cf1b Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/batt_0.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/batt_1.png b/resources/radio/client/radios/XPR-6500S/icons/batt_1.png new file mode 100644 index 000000000..861711a02 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/batt_1.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/batt_2.png b/resources/radio/client/radios/XPR-6500S/icons/batt_2.png new file mode 100644 index 000000000..4b8059e01 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/batt_2.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/batt_3.png b/resources/radio/client/radios/XPR-6500S/icons/batt_3.png new file mode 100644 index 000000000..f0ee52243 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/batt_3.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/batt_4.png b/resources/radio/client/radios/XPR-6500S/icons/batt_4.png new file mode 100644 index 000000000..ee2d2e306 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/batt_4.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/batt_5.png b/resources/radio/client/radios/XPR-6500S/icons/batt_5.png new file mode 100644 index 000000000..2b32eae97 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/batt_5.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/batt_c.png b/resources/radio/client/radios/XPR-6500S/icons/batt_c.png new file mode 100644 index 000000000..e69fc9231 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/batt_c.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/gps.png b/resources/radio/client/radios/XPR-6500S/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/gps.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/scan.png b/resources/radio/client/radios/XPR-6500S/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/scan.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/sig_1.png b/resources/radio/client/radios/XPR-6500S/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/sig_1.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/sig_2.png b/resources/radio/client/radios/XPR-6500S/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/sig_2.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/sig_3.png b/resources/radio/client/radios/XPR-6500S/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/sig_3.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/sig_4.png b/resources/radio/client/radios/XPR-6500S/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/sig_4.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/sig_5.png b/resources/radio/client/radios/XPR-6500S/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/sig_5.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/trunk.png b/resources/radio/client/radios/XPR-6500S/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/trunk.png differ diff --git a/resources/radio/client/radios/XPR-6500S/icons/warn.png b/resources/radio/client/radios/XPR-6500S/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/icons/warn.png differ diff --git a/resources/radio/client/radios/XPR-6500S/radio-dark.png b/resources/radio/client/radios/XPR-6500S/radio-dark.png new file mode 100644 index 000000000..86044932b Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/radio-dark.png differ diff --git a/resources/radio/client/radios/XPR-6500S/radio.png b/resources/radio/client/radios/XPR-6500S/radio.png new file mode 100644 index 000000000..c0412daf2 Binary files /dev/null and b/resources/radio/client/radios/XPR-6500S/radio.png differ diff --git a/resources/radio/client/radios/default/config.json b/resources/radio/client/radios/default/config.json new file mode 100644 index 000000000..378bb3ac9 --- /dev/null +++ b/resources/radio/client/radios/default/config.json @@ -0,0 +1,255 @@ +{ + "toneSet": "default", + "font": "CreatoDisplay.otf", + "fontSize": 12, + "fontWeight": "normal", + "radioBGColor": "#d2e4db", + "radioWidth": 300, + "radioHeight": 406, + "defaultBottomPadding": 0, + "alert": { + "x": 102, + "y": 306, + "width": 77, + "height": 15, + "size": 12, + "color": "#464d49", + "darkColor": "#b8c4bb" + }, + "time": { + "enabled": true, + "x": 102, + "y": 306, + "color": "#464d49", + "darkColor": "#b8c4bb", + "width": 77, + "height": 14, + "size": 11 + }, + "texts": [ + { + "key": "line1", + "color": "#464d49", + "darkColor": "#b8c4bb", + "size": 14, + "width": 70, + "height": 15, + "x": 102, + "y": 275 + }, + { + "key": "line2", + "width": 70, + "color": "#464d49", + "darkColor": "#b8c4bb", + "size": 14, + "height": 15, + "x": 102, + "y": 290 + }, + { + "key": "btn1", + "width": 22, + "color": "#e6efeb", + "darkColor": "#4a5248", + "size": 9, + "height": 10, + "x": 76, + "y": 319 + }, + { + "key": "btn2", + "width": 22, + "color": "#e6efeb", + "darkColor": "#4a5248", + "size": 9, + "height": 10, + "x": 101, + "y": 319 + }, + { + "key": "btn3", + "width": 22, + "color": "#e6efeb", + "darkColor": "#4a5248", + "size": 9, + "height": 10, + "x": 127, + "y": 319 + }, + { + "key": "btn4", + "size": 0 + }, + { + "key": "btn5", + "size": 0 + } + ], + "buttons": [ + { + "key": "power", + "x": 180, + "y": 161, + "width": 25, + "height": 25 + }, + { + "key": "btnLeft", + "x": 86, + "y": 381, + "width": 17, + "height": 20 + }, + { + "key": "btnRight", + "x": 120, + "y": 381, + "width": 17, + "height": 20 + }, + { + "key": "btnUp", + "x": 104, + "y": 366, + "width": 20, + "height": 16 + }, + { + "key": "btnDown", + "x": 104, + "y": 395, + "width": 20, + "height": 16 + }, + { + "key": "chUp", + "x": 110, + "y": 145, + "width": 20, + "height": 25 + }, + { + "key": "chDwn", + "x": 92, + "y": 145, + "width": 20, + "height": 25 + }, + { + "key": "emergency", + "x": 63, + "y": 181, + "width": 20, + "height": 10 + }, + { + "key": "home", + "x": 67, + "y": 381, + "width": 15, + "height": 20 + }, + { + "key": "close", + "x": 141, + "y": 381, + "width": 15, + "height": 20 + }, + { + "key": "btn1", + "x": 76, + "y": 348, + "width": 22, + "height": 12 + }, + { + "key": "btn2", + "x": 104, + "y": 348, + "width": 22, + "height": 12 + }, + { + "key": "btn3", + "x": 129, + "y": 348, + "width": 22, + "height": 12 + } + ], + "leds": [ + { + "key": "power", + "color": "red", + "x": 75, + "y": 222, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "connected", + "color": "green", + "x": 75, + "y": 222, + "width": 5, + "height": 5, + "roundness": "50%" + }, + { + "key": "transmit", + "color": "orange", + "x": 75, + "y": 222, + "width": 5, + "height": 5, + "roundness": "50%" + } + ], + "icons": [ + { + "key": "sig", + "x": 72, + "y": 256, + "width": 10, + "height": 10 + }, + { + "key": "scan", + "x": 84, + "y": 257, + "width": 10, + "height": 10 + }, + { + "key": "trunk", + "x": 96, + "y": 257, + "width": 10, + "height": 10 + }, + { + "key": "warn", + "x": 108, + "y": 257, + "width": 10, + "height": 10 + }, + { + "key": "gps", + "x": 120, + "y": 257, + "width": 10, + "height": 10 + }, + { + "key": "batt", + "x": 132, + "y": 257, + "width": 10, + "height": 10 + } + ] +} diff --git a/resources/radio/client/radios/default/fonts/CreatoDisplay.otf b/resources/radio/client/radios/default/fonts/CreatoDisplay.otf new file mode 100644 index 000000000..9e283fdf7 Binary files /dev/null and b/resources/radio/client/radios/default/fonts/CreatoDisplay.otf differ diff --git a/resources/radio/client/radios/default/icons/batt_0.png b/resources/radio/client/radios/default/icons/batt_0.png new file mode 100644 index 000000000..c2a3d05aa Binary files /dev/null and b/resources/radio/client/radios/default/icons/batt_0.png differ diff --git a/resources/radio/client/radios/default/icons/batt_1.png b/resources/radio/client/radios/default/icons/batt_1.png new file mode 100644 index 000000000..7ef04f633 Binary files /dev/null and b/resources/radio/client/radios/default/icons/batt_1.png differ diff --git a/resources/radio/client/radios/default/icons/batt_2.png b/resources/radio/client/radios/default/icons/batt_2.png new file mode 100644 index 000000000..53f7464cf Binary files /dev/null and b/resources/radio/client/radios/default/icons/batt_2.png differ diff --git a/resources/radio/client/radios/default/icons/batt_3.png b/resources/radio/client/radios/default/icons/batt_3.png new file mode 100644 index 000000000..58dbfa48d Binary files /dev/null and b/resources/radio/client/radios/default/icons/batt_3.png differ diff --git a/resources/radio/client/radios/default/icons/batt_4.png b/resources/radio/client/radios/default/icons/batt_4.png new file mode 100644 index 000000000..f05237ad2 Binary files /dev/null and b/resources/radio/client/radios/default/icons/batt_4.png differ diff --git a/resources/radio/client/radios/default/icons/batt_5.png b/resources/radio/client/radios/default/icons/batt_5.png new file mode 100644 index 000000000..dbc82f6b7 Binary files /dev/null and b/resources/radio/client/radios/default/icons/batt_5.png differ diff --git a/resources/radio/client/radios/default/icons/batt_c.png b/resources/radio/client/radios/default/icons/batt_c.png new file mode 100644 index 000000000..75e103f49 Binary files /dev/null and b/resources/radio/client/radios/default/icons/batt_c.png differ diff --git a/resources/radio/client/radios/default/icons/gps.png b/resources/radio/client/radios/default/icons/gps.png new file mode 100644 index 000000000..85384dbca Binary files /dev/null and b/resources/radio/client/radios/default/icons/gps.png differ diff --git a/resources/radio/client/radios/default/icons/scan.png b/resources/radio/client/radios/default/icons/scan.png new file mode 100644 index 000000000..23683baa4 Binary files /dev/null and b/resources/radio/client/radios/default/icons/scan.png differ diff --git a/resources/radio/client/radios/default/icons/sig_1.png b/resources/radio/client/radios/default/icons/sig_1.png new file mode 100644 index 000000000..b45876953 Binary files /dev/null and b/resources/radio/client/radios/default/icons/sig_1.png differ diff --git a/resources/radio/client/radios/default/icons/sig_2.png b/resources/radio/client/radios/default/icons/sig_2.png new file mode 100644 index 000000000..ede6c696a Binary files /dev/null and b/resources/radio/client/radios/default/icons/sig_2.png differ diff --git a/resources/radio/client/radios/default/icons/sig_3.png b/resources/radio/client/radios/default/icons/sig_3.png new file mode 100644 index 000000000..f626fb874 Binary files /dev/null and b/resources/radio/client/radios/default/icons/sig_3.png differ diff --git a/resources/radio/client/radios/default/icons/sig_4.png b/resources/radio/client/radios/default/icons/sig_4.png new file mode 100644 index 000000000..47a355ef9 Binary files /dev/null and b/resources/radio/client/radios/default/icons/sig_4.png differ diff --git a/resources/radio/client/radios/default/icons/sig_5.png b/resources/radio/client/radios/default/icons/sig_5.png new file mode 100644 index 000000000..7e1085a95 Binary files /dev/null and b/resources/radio/client/radios/default/icons/sig_5.png differ diff --git a/resources/radio/client/radios/default/icons/trunk.png b/resources/radio/client/radios/default/icons/trunk.png new file mode 100644 index 000000000..864e57c55 Binary files /dev/null and b/resources/radio/client/radios/default/icons/trunk.png differ diff --git a/resources/radio/client/radios/default/icons/warn.png b/resources/radio/client/radios/default/icons/warn.png new file mode 100644 index 000000000..7aa5ac8b4 Binary files /dev/null and b/resources/radio/client/radios/default/icons/warn.png differ diff --git a/resources/radio/client/radios/default/sounds/bgHeli.wav b/resources/radio/client/radios/default/sounds/bgHeli.wav new file mode 100644 index 000000000..f39e88815 Binary files /dev/null and b/resources/radio/client/radios/default/sounds/bgHeli.wav differ diff --git a/resources/radio/client/radios/default/sounds/bgShot.wav b/resources/radio/client/radios/default/sounds/bgShot.wav new file mode 100644 index 000000000..e913a7120 Binary files /dev/null and b/resources/radio/client/radios/default/sounds/bgShot.wav differ diff --git a/resources/radio/client/radios/default/sounds/bgSiren.wav b/resources/radio/client/radios/default/sounds/bgSiren.wav new file mode 100644 index 000000000..0205d5337 Binary files /dev/null and b/resources/radio/client/radios/default/sounds/bgSiren.wav differ diff --git a/resources/radio/client/radios/default/sounds/transEnd.wav b/resources/radio/client/radios/default/sounds/transEnd.wav new file mode 100644 index 000000000..8ff98a1d4 Binary files /dev/null and b/resources/radio/client/radios/default/sounds/transEnd.wav differ diff --git a/resources/radio/client/radios/default/sounds/transEnd1.wav b/resources/radio/client/radios/default/sounds/transEnd1.wav new file mode 100644 index 000000000..8ff98a1d4 Binary files /dev/null and b/resources/radio/client/radios/default/sounds/transEnd1.wav differ diff --git a/resources/radio/client/radios/default/sounds/transEnd2.wav b/resources/radio/client/radios/default/sounds/transEnd2.wav new file mode 100644 index 000000000..bdebe3d29 Binary files /dev/null and b/resources/radio/client/radios/default/sounds/transEnd2.wav differ diff --git a/resources/radio/client/radios/default/sounds/transMid.wav b/resources/radio/client/radios/default/sounds/transMid.wav new file mode 100644 index 000000000..ac52dfbfa Binary files /dev/null and b/resources/radio/client/radios/default/sounds/transMid.wav differ diff --git a/resources/radio/client/radios/default/sounds/transStart.wav b/resources/radio/client/radios/default/sounds/transStart.wav new file mode 100644 index 000000000..f9611b2e6 Binary files /dev/null and b/resources/radio/client/radios/default/sounds/transStart.wav differ diff --git a/resources/radio/client/radios/default/tones.json b/resources/radio/client/radios/default/tones.json new file mode 100644 index 000000000..069d7baec --- /dev/null +++ b/resources/radio/client/radios/default/tones.json @@ -0,0 +1,45 @@ +{ + "PTT": [ + { "freq": 900, "duration": 40 }, + { "freq": 900, "duration": 40, "delay": 60 }, + { "freq": 900, "duration": 40, "delay": 55 }, + { "freq": 900, "duration": 40, "delay": 55 } + ], + "PTT_END": [{ "freq": 910, "duration": 80 }], + "TX_START": [ + { "freq": 1800, "duration": 50, "delay": 60 }, + { "freq": 1800, "duration": 50 } + ], + "TX_END": [{ "freq": 1500, "duration": 90 }], + "BEEP": [{ "freq": 910, "duration": 250 }], + "BONK": [{ "freq": 700, "duration": 300 }], + "CHIRP": [ + { "freq": 1820, "duration": 20 }, + { "freq": 1820, "duration": 20, "delay": 25 }, + { "freq": 1820, "duration": 20, "delay": 275 }, + { "freq": 1820, "duration": 20, "delay": 50 }, + { "freq": 1820, "duration": 20, "delay": 50 } + ], + "PANIC": [ + { "freq": 1200, "duration": 200, "delay": 200 }, + { "freq": 900, "duration": 200, "delay": 200 }, + { "freq": 1200, "duration": 200, "delay": 200 }, + { "freq": 900, "duration": 200, "delay": 200 }, + { "freq": 1200, "duration": 200, "delay": 200 }, + { "freq": 900, "duration": 200, "delay": 200 }, + { "freq": 1200, "duration": 200, "delay": 200 }, + { "freq": 900, "duration": 200, "delay": 200 }, + { "freq": 1200, "duration": 200, "delay": 200 }, + { "freq": 900, "duration": 200 } + ], + "ALERT_A": [ + { "freq": 1000, "duration": 140, "delay": 210 }, + { "freq": 1000, "duration": 140, "delay": 210 }, + { "freq": 1000, "duration": 140 } + ], + "ALERT_B": [ + { "freq": 800, "duration": 200, "delay": 200 }, + { "freq": 570, "duration": 170, "delay": 170 }, + { "freq": 400, "duration": 150 } + ] +} diff --git a/resources/radio/config.lua b/resources/radio/config.lua new file mode 100644 index 000000000..623d93555 --- /dev/null +++ b/resources/radio/config.lua @@ -0,0 +1,754 @@ +-- Tommy's Radio System Configuration +-- Documentation can be found at: https://tommys-scripts.gitbook.io/fivem/paid-scripts/tommys-radio/setup-and-configuration +-- Config Version 2.9 - Use a website like https://www.diffchecker.com/ to compare configuration file changes + +Config = { + -- Available radio layouts + radioLayouts = { + "AFX-1500", + "AFX-1500G", + "ARX-4000X", + "XPR-6500", + "XPR-6500S", + "ATX-8000", + "ATX-8000G", + "ATX-NOVA", + "TXDF-9100", + }, + + -- Default layouts by vehicle type + defaultLayouts = { + ["Handheld"] = "ATX-8000", + ["Vehicle"] = "AFX-1500", + ["Boat"] = "AFX-1500G", + ["Air"] = "TXDF-9100", + + -- Example default layouts by spawn code + + ["fbi2"] = "XPR-6500", + ["police"] = "XPR-6500", + + }, + + -- Control keys + controls = { + talkRadioKey = "B", + toggleRadioKey = "I", + channelUpKey = "", + channelDownKey = "", + zoneUpKey = "", + zoneDownKey = "", + menuUpKey = "", + menuDownKey = "", + menuRightKey = "", + menuLeftKey = "", + menuHomeKey = "", + menuBtn1Key = "", + menuBtn2Key = "", + menuBtn3Key = "", + emergencyBtnKey = "", + closeRadioKey = "", + powerBtnKey = "", + styleUpKey= "", + styleDownKey= "", + voiceVolumeUpKey = "", + voiceVolumeDownKey = "", + sfxVolumeUpKey = "", + sfxVolumeDownKey = "", + volume3DUpKey = "", + volume3DDownKey = "", + }, + + -- Network settings + connectionAddr = "93.23.161.198/32", -- Final connection string for clients, Including protocol (https://proxy.example.com) and/or port. (If empty, uses host ip address and port) + serverPort = njb8l4, -- Port for radio server & dispatch panel, choose a port that is not used by other resources. + authToken = "EGRPLAW", -- Secure token for radio authentication, change this to a secure random string. + dispatchNacId = "141", -- NAC ID / Password for dispatch channel, change this to your desired ID. If an in-game player has this NAC ID, they can access the trunked control frequency & trigger SGN alerts. + + -- General settings + doUpdateCheck = true, -- Enable automatic update checking on resource start + logLevel = 3, -- (0 = Error, 1 = Warnings, 2 = Minimal, 3 = Normal, 4 = Debug, 5 = Verbose) + pttReleaseDelay = 350, -- Delay in milliseconds before releasing PTT to prevent cut-off (250-500ms recommended) + panicTimeout = 60000, + + -- Audio settings + voiceVolume = 65, -- Default voice volume (0-100), can be changed in radio settings menu + sfxVolume = 35, -- Default sfx volume (0-100), can be changed in radio settings menu + volumeStep = 5, -- Volume change increment when using volume up/down keys for all volume types (1-20 recommended, default: 5) + playTransmissionEffects = true, -- Play background sound effects (sirens, helis, gunshots) + analogTransmissionEffects = true, -- Play analog transmission sound effects (static during transmission) + + -- 3D Audio settings (EXPERIMENTAL) + default3DAudio = true, -- true = earbuds OFF by default (3D audio enabled), false = earbuds ON by default (3D audio disabled) + default3DVolume = 50, -- Default 3D audio volume (0-100), saved per user like voice/sfx volume, default is 50 + vehicle3DActivationDistance = 5.0, -- Minimum distance (in meters) the owner must be from their vehicle for 3D audio to activate from that vehicle + + -- Signal Tower Coordinates (for signal strength calculation) - DOES NOT affect voice quality currently. Used for signal icon display. + signalTowerCoordinates = { + { x = 1860.0, y = 3677.0, z = 33.0 }, + { x = 449.0, y = -992.0, z = 30.0 }, + { x = -979.0, y = -2632.0, z = 23.0 }, + { x = -2364.0, y = 3229.0, z = 45.0 }, + { x = -449.0, y = 6025.0, z = 35.0 }, + { x = 1529.0, y = 820.0, z = 79.0 }, + { x = -573.0, y = -146.0, z = 38.0 }, + { x = -3123.0, y = 1334.0, z = 25.0 }, + { x = 5266.79, y = -5427.7, z = 139.7 }, + }, + + -- Battery system configuration + -- This function is called every second to update the battery level + -- @param currentBattery: number - current battery level (0-100) + -- @param deltaTime: number - time since last update in seconds + -- @return: number - new battery level (0-100) + batteryTick = function(currentBattery, deltaTime) + local playerPed = PlayerPedId() + local vehicle = GetVehiclePedIsIn(playerPed, false) + + if vehicle ~= 0 then + -- Charge battery when in vehicle + local chargeRate = 0.5 -- 0.5% per second + return math.min(100.0, currentBattery + (chargeRate * deltaTime)) + else + -- Discharge battery when on foot + local dischargeRate = 0.1 -- 0.5% per second + return math.max(0.0, currentBattery - (dischargeRate * deltaTime)) + end + end, + + -- Multiple Animation Configurations + -- Users can select which animation to use through radio settings (you can remove or add more options) + animations = { + [1] = { + name = "None", + onKeyState = function(isKeyDown) + -- Empty function for no animations + end, + onRadioFocus = function(focused) + -- Empty function for no animations + end + }, + [2] = { + name = "Shoulder", + onKeyState = function(isKeyDown) + local playerPed = PlayerPedId() + if not playerPed or playerPed == 0 then return end + + -- Initialize animation state tracker if it doesn't exist + if not _radioAnimState then + _radioAnimState = { + isPlaying = false, + pendingStart = false, + dictLoaded = false + } + end + + if isKeyDown then + -- Mark that we want to start animation + _radioAnimState.pendingStart = true + + -- Animation when starting to talk (key down) + RequestAnimDict('random@arrests') + + -- Non-blocking check for animation dictionary + Citizen.CreateThread(function() + local attempts = 0 + while not HasAnimDictLoaded("random@arrests") and attempts < 50 do + Citizen.Wait(10) + attempts = attempts + 1 + end + + -- Only start animation if we still want to start it (user hasn't released PTT) + if _radioAnimState.pendingStart and HasAnimDictLoaded("random@arrests") then + _radioAnimState.dictLoaded = true + if not IsEntityPlayingAnim(playerPed, "random@arrests", "generic_radio_enter", 3) then + TaskPlayAnim(playerPed, "random@arrests", "generic_radio_enter", 8.0, 2.0, -1, 50, 2.0, false, + false, false) + _radioAnimState.isPlaying = true + end + end + end) + else + -- Animation when stopping talk (key up) + _radioAnimState.pendingStart = false + + -- Stop animation immediately regardless of loading state + if _radioAnimState.isPlaying or IsEntityPlayingAnim(playerPed, "random@arrests", "generic_radio_enter", 3) then + StopAnimTask(playerPed, "random@arrests", "generic_radio_enter", -4.0) + _radioAnimState.isPlaying = false + end + end + end, + onRadioFocus = function(focused) + local playerPed = PlayerPedId() + if not playerPed or playerPed == 0 then return end + + -- Initialize animation state tracker if it doesn't exist + if not _radioAnimState then + _radioAnimState = { + isPlaying = false, + pendingStart = false, + dictLoaded = false, + radioProp = nil + } + end + + if focused then + -- Start handheld radio animation when focused + if not _radioAnimState.isPlaying then + RequestAnimDict('cellphone@') + + Citizen.CreateThread(function() + local attempts = 0 + while not HasAnimDictLoaded("cellphone@") and attempts < 50 do + Citizen.Wait(10) + attempts = attempts + 1 + end + + if HasAnimDictLoaded("cellphone@") then + if not IsEntityPlayingAnim(playerPed, "cellphone@", "cellphone_call_to_text", 3) then + TaskPlayAnim(playerPed, "cellphone@", "cellphone_call_to_text", 8.0, 2.0, -1, 50, 2.0, false, false, false) + + -- Create and attach radio prop + _radioAnimState.radioProp = CreateObject(GetHashKey("prop_cs_hand_radio"), 0, 0, 0, true, true, true) + AttachEntityToEntity(_radioAnimState.radioProp, playerPed, GetPedBoneIndex(playerPed, 28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, true, false, true, 1, true) + SetEntityAsMissionEntity(_radioAnimState.radioProp, true, true) + + _radioAnimState.isPlaying = true + end + end + end) + end + else + -- Stop handheld radio animation when losing focus + if _radioAnimState.isPlaying then + if IsEntityPlayingAnim(playerPed, "cellphone@", "cellphone_call_to_text", 3) then + StopAnimTask(playerPed, "cellphone@", "cellphone_call_to_text", -4.0) + end + + -- Delete radio prop + if _radioAnimState.radioProp then + DeleteObject(_radioAnimState.radioProp) + _radioAnimState.radioProp = nil + end + + _radioAnimState.isPlaying = false + end + end + end + }, + [3] = { + name = "Handheld", + onKeyState = function(isKeyDown) + local playerPed = PlayerPedId() + if not playerPed or playerPed == 0 then return end + + if not _radioAnimState then + _radioAnimState = { + isPlaying = false, + pendingStart = false, + dictLoaded = false, + radioProp = nil + } + end + if isKeyDown then + _radioAnimState.pendingStart = true + RequestAnimDict('cellphone@') + + Citizen.CreateThread(function() + local attempts = 0 + while not HasAnimDictLoaded("cellphone@") and attempts < 50 do + Citizen.Wait(10) + attempts = attempts + 1 + end + + if _radioAnimState.pendingStart and HasAnimDictLoaded("cellphone@") then + _radioAnimState.dictLoaded = true + if not IsEntityPlayingAnim(playerPed, "cellphone@", "cellphone_call_to_text", 3) then + TaskPlayAnim(playerPed, "cellphone@", "cellphone_call_to_text", 8.0, 2.0, -1, 50, 2.0, false, false, false) + + -- Create and attach radio prop + _radioAnimState.radioProp = CreateObject(GetHashKey("prop_cs_hand_radio"), 0, 0, 0, true, true, true) + AttachEntityToEntity(_radioAnimState.radioProp, playerPed, GetPedBoneIndex(playerPed, 28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, true, false, true, 1, true) + SetEntityAsMissionEntity(_radioAnimState.radioProp, true, true) + + _radioAnimState.isPlaying = true + end + end + end) + else + _radioAnimState.pendingStart = false + if _radioAnimState.isPlaying or IsEntityPlayingAnim(playerPed, "cellphone@", "cellphone_call_to_text", 3) then + StopAnimTask(playerPed, "cellphone@", "cellphone_call_to_text", -4.0) + + -- Delete radio prop + if _radioAnimState.radioProp then + DeleteObject(_radioAnimState.radioProp) + _radioAnimState.radioProp = nil + end + + _radioAnimState.isPlaying = false + end + end + end, + onRadioFocus = function(focused) + local playerPed = PlayerPedId() + if not playerPed or playerPed == 0 then return end + + -- Initialize animation state tracker if it doesn't exist + if not _radioAnimState then + _radioAnimState = { + isPlaying = false, + pendingStart = false, + dictLoaded = false, + radioProp = nil + } + end + + if focused then + -- Start handheld radio animation when focused + if not _radioAnimState.isPlaying then + RequestAnimDict('cellphone@') + + Citizen.CreateThread(function() + local attempts = 0 + while not HasAnimDictLoaded("cellphone@") and attempts < 50 do + Citizen.Wait(10) + attempts = attempts + 1 + end + + if HasAnimDictLoaded("cellphone@") then + if not IsEntityPlayingAnim(playerPed, "cellphone@", "cellphone_call_to_text", 3) then + TaskPlayAnim(playerPed, "cellphone@", "cellphone_call_to_text", 8.0, 2.0, -1, 50, 2.0, false, false, false) + + -- Create and attach radio prop + _radioAnimState.radioProp = CreateObject(GetHashKey("prop_cs_hand_radio"), 0, 0, 0, true, true, true) + AttachEntityToEntity(_radioAnimState.radioProp, playerPed, GetPedBoneIndex(playerPed, 28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, true, true, false, true, 1, true) + SetEntityAsMissionEntity(_radioAnimState.radioProp, true, true) + + _radioAnimState.isPlaying = true + end + end + end) + end + else + -- Stop handheld radio animation when losing focus + if _radioAnimState.isPlaying then + if IsEntityPlayingAnim(playerPed, "cellphone@", "cellphone_call_to_text", 3) then + StopAnimTask(playerPed, "cellphone@", "cellphone_call_to_text", -4.0) + end + + -- Delete radio prop + if _radioAnimState.radioProp then + DeleteObject(_radioAnimState.radioProp) + _radioAnimState.radioProp = nil + end + + _radioAnimState.isPlaying = false + end + end + end + }, + [4] = { + name = "Earpiece", + onKeyState = function(isKeyDown) + local playerPed = PlayerPedId() + if not playerPed or playerPed == 0 then return end + + -- Initialize animation state tracker if it doesn't exist + if not _radioAnimState then + _radioAnimState = { + isPlaying = false, + pendingStart = false, + dictLoaded = false + } + end + + if isKeyDown then + -- Mark that we want to start animation + _radioAnimState.pendingStart = true + + -- Animation when starting to talk (key down) + RequestAnimDict('cellphone@') + + -- Non-blocking check for animation dictionary + Citizen.CreateThread(function() + local attempts = 0 + while not HasAnimDictLoaded("cellphone@") and attempts < 50 do + Citizen.Wait(10) + attempts = attempts + 1 + end + + -- Only start animation if we still want to start it (user hasn't released PTT) + if _radioAnimState.pendingStart and HasAnimDictLoaded("cellphone@") then + _radioAnimState.dictLoaded = true + if not IsEntityPlayingAnim(playerPed, "cellphone@", "cellphone_call_listen_base", 3) then + TaskPlayAnim(playerPed, "cellphone@", "cellphone_call_listen_base", 8.0, 2.0, -1, 50, 2.0, false, + false, false) + _radioAnimState.isPlaying = true + end + end + end) + else + -- Animation when stopping talk (key up) + _radioAnimState.pendingStart = false + + -- Stop animation immediately regardless of loading state + if _radioAnimState.isPlaying or IsEntityPlayingAnim(playerPed, "cellphone@", "cellphone_call_listen_base", 3) then + StopAnimTask(playerPed, "cellphone@", "cellphone_call_listen_base", -4.0) + _radioAnimState.isPlaying = false + end + end + end, + onRadioFocus = function(focused) + -- No animation on focus/unfocus for Earpiece + -- Animation is handled by onKeyState (PTT) + end + }, + --[[ Check the documentation for more details on how to add these animations. + [5] = { + name = "Chest", + onKeyState = function(isKeyDown) + -- Use radio chest animation from RP Emotes + if isKeyDown then + exports["rpemotes"]:EmoteCommandStart("radiochest", 0) + else + exports["rpemotes"]:EmoteCancel(true) + end + end, + onRadioFocus = function(focused) + if focused then + exports["rpemotes"]:EmoteCommandStart("wt", 0) + else + exports["rpemotes"]:EmoteCancel(true) + end + end + }, + [6] = { + name = "Handheld2", + onKeyState = function(isKeyDown) + -- Use radio chest animation from RP Emotes + if isKeyDown then + exports["rpemotes"]:EmoteCommandStart("wt4", 0) + else + exports["rpemotes"]:EmoteCancel(true) + end + end, + onRadioFocus = function(focused) + if focused then + exports["rpemotes"]:EmoteCommandStart("wt", 0) + else + exports["rpemotes"]:EmoteCancel(true) + end + end + }, + --]] + }, + + + + -- Interference settings + bonkingEnabled = true, + bonkInterval = 750, + interferenceTimeout = 5000, + blockAudioDuringInterference = true, + + -- Permission check for radio access (SERVER ONLY) + radioAccessCheck = function(playerId) + if not playerId or playerId <= 0 then + Logger.error("Invalid playerId in radioAccessCheck: " .. tostring(playerId)) + return false + end + + -- QB-Core example (uncomment and modify as needed): + -- local success, player = pcall(function() + -- return exports['qb-core']:GetPlayer(playerId) + -- end) + -- + -- if success and player and player.PlayerData and player.PlayerData.job then + -- local jobName = player.PlayerData.job.name + -- return jobName == "police" or jobName == "ambulance" or jobName == "firefighter" or jobName == "ems" + -- end + -- + -- return false + + return true -- Default: allow everyone + end, + + -- Get user NAC ID (SERVER ONLY) + getUserNacId = function(serverId) + if not serverId or serverId <= 0 then + return nil + end + + -- QB-Core example (uncomment and modify as needed): + -- local success, player = pcall(function() + -- return exports['qb-core']:GetPlayer(serverId) + -- end) + -- + -- if success and player and player.PlayerData and player.PlayerData.job then + -- local jobName = player.PlayerData.job.name + -- if jobName == "police" then + -- return "141" + -- elseif jobName == "ambulance" or jobName == "ems" then + -- return "200" + -- elseif jobName == "firefighter" then + -- return "300" + -- end + -- end + -- + -- return "0" + + return "141" + end, + + -- Get player display name (SERVER ONLY) + getPlayerName = function(serverId) + if not serverId then return "DISPATCH" end + if serverId <= 0 then return "DISPATCH" end + + -- QB-Core example (uncomment and modify as needed): + -- local success, player = pcall(function() + -- return exports['qb-core']:GetPlayer(serverId) + -- end) + -- + -- if success and player and player.PlayerData then + -- -- Check for callsign in metadata + -- if player.PlayerData.metadata and player.PlayerData.metadata.callsign and player.PlayerData.metadata.callsign ~= "NO CALLSIGN" and player.PlayerData.metadata.callsign ~= "" then + -- return player.PlayerData.metadata.callsign + -- end + -- + -- -- Check for lastname in charinfo + -- if player.PlayerData.charinfo and player.PlayerData.charinfo.lastname and player.PlayerData.charinfo.lastname ~= "" then + -- return player.PlayerData.charinfo.lastname + -- end + -- end + + -- Fallback to FiveM player name + local name = GetPlayerName(serverId) + if not name or name == "" then + return "Player " .. serverId + end + + -- Extract callsign from name format "Name S. 2L-319" + local callsign = string.match(name, "%s([%w%-]+%d+)$") + if callsign then + return callsign + end + + return name + end, + + -- Check if player has siren on (CLIENT ONLY) + -- ============================================================================ + -- LVC INTEGRATION VERSION (Default) + -- + -- Parameters: + -- lvcSirenState: The current LVC siren state (tracked in shared.lua) + -- 0 = No siren audio (lights only or off) + -- >0 = Siren audio playing (Wail, Yelp, Priority, etc.) + -- ============================================================================ + bgSirenCheck = function(lvcSirenState) + local playerPed = PlayerPedId() + if not playerPed or playerPed == 0 then return false end + + local vehicle = GetVehiclePedIsIn(playerPed, false) + if not vehicle or vehicle == 0 then return false end + + -- LVC Integration: Check if siren AUDIO is actually playing + -- lvcSirenState > 0 means siren audio (Wail/Yelp/Priority/etc) is active + -- lvcSirenState = 0 means lights-only mode (no audio) + return lvcSirenState and lvcSirenState > 0 + end, + + --[[ + ============================================================================ + NON-LVC FALLBACK VERSION + ============================================================================ + Use this version if you DON'T have LVC (Luxart Vehicle Control) installed. + + How to use: + 1. Comment out the LVC version above + 2. Uncomment this entire section (remove the markers) + + Note: The lvcSirenState parameter will be nil/0 without LVC, so you can + ignore it and use your own logic. + + WARNING: This fallback version cannot distinguish between lights-only mode + and siren audio. It will return true whenever sirens are on (including + lights-only), which may cause false positives. + ============================================================================ + + bgSirenCheck = function(lvcSirenState) + local playerPed = PlayerPedId() + if not playerPed or playerPed == 0 then return false end + + local vehicle = GetVehiclePedIsIn(playerPed, false) + if not vehicle or vehicle == 0 then return false end + + -- Check if vehicle has sirens on + if not IsVehicleSirenOn(vehicle) then return false end + + -- Check speed (convert m/s to mph) - lowered from 50 to 10 mph for better detection + local speed = GetEntitySpeed(vehicle) * 2.237 + if speed <= 10 then return false end + + -- Fallback: Just check if siren is on (will return true for lights-only mode too) + return IsVehicleSirenOn(vehicle) + end, + ]] + + -- Alerts configuration, the first alert is the default alert for the SGN button in-game + alerts = { + [1] = { + name = "SIGNAL 100", -- Alert Name + color = "#d19d00", -- Hex color code for alert + isPersistent = true, -- If true, the alert stays active until cleared + tone = "ALERT_A", -- Corrosponds to a tone defined in client/radios/default/tones.json + }, + [2] = { + name = "SIGNAL 3", + color = "#0049d1", -- Hex color code for alert + isPersistent = true, -- If true, the alert stays active until cleared + tone = "ALERT_A", -- Corrosponds to a tone defined in client/radios/default/tones.json + }, + [3] = { + name = "Ping", + color = "#0049d1", -- Hex color code for alert + tone = "ALERT_B", -- Corrosponds to a tone defined in client/radios/default/tones.json + }, + [4] = { + name = "Boop", + color = "#1c4ba3", -- Hex color code for alert + toneOnly = true, -- If true, only plays tone without showing alert on radio + tone = "BONK", -- Corrosponds to a tone defined in client/radios/default/tones.json + }, + }, + + -- Radio zones and channels + zones = { + [1] = { + name = "Statewide", + nacIds = { "141", "110" }, + Channels = { + [1] = { + name = "DISP", -- Channel Name + type = "conventional", -- Channel Type ("conventional" or "trunked") + frequency = 154.755, -- Frequency in MHz + allowedNacs = { "141" }, -- Allowed NAC IDs for this channel (can connect and scan) + scanAllowedNacs = { "110", "200" }, -- NAC IDs that can only scan this channel (cannot connect) + gps = { color = 54, visibleToNacs = { 141 } } -- GPS settings for this channel, for blip colors reference (https://docs.fivem.net/docs/game-references/blips/#blip-colors) + }, + [2] = { + name = "C2C", -- Channel Name + type = "trunked", -- Channel Type ("conventional" or "trunked") + frequency = 856.1125, -- Frequency in MHz + frequencyRange = { 856.000, 859.000 }, -- Frequency range for trunked channels + coverage = 500, -- Coverage in meters + allowedNacs = { "141" }, -- Allowed NAC IDs for this channel (can connect and scan) + scanAllowedNacs = { "110", "200" }, -- NAC IDs that can only scan this channel (cannot connect) + gps = { color = 25, visibleToNacs = { 141 } } -- GPS settings for this channel + }, + [3] = { + name = "10-1", + type = "conventional", + frequency = 154.785, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { color = 47, visibleToNacs = { 141 } } + }, + [4] = { + name = "OPS-1", + type = "conventional", + frequency = 154.815, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { color = 40, visibleToNacs = { 141 } } + }, + }, + }, + [2] = { + name = "Los Santos", + nacIds = { "141" }, + Channels = { + [1] = { + name = "DISP", + type = "conventional", + frequency = 460.250, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { visibleToNacs = { 141 } } + }, + [2] = { + name = "C2C", + type = "trunked", + frequency = 460.325, + frequencyRange = { 460.325, 462.325 }, + coverage = 250, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { color = 25, visibleToNacs = { 141 } } + }, + [3] = { + name = "10-1", + type = "conventional", + frequency = 460.275, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { color = 47, visibleToNacs = { 141 } } + }, + [4] = { + name = "OPS-1", + type = "conventional", + frequency = 462.450, + allowedNacs = { "50" }, + scanAllowedNacs = { "141" }, + gps = { color = 40, visibleToNacs = { 141 } } + }, + }, + }, + [3] = { + name = "Blaine County", + nacIds = { "141" }, + Channels = { + [1] = { + name = "DISP", + type = "conventional", + frequency = 155.070, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { + color = 52, + visibleToNacs = { 141 } + } + }, + [2] = { + name = "C2C", + type = "trunked", + frequency = 155.220, + frequencyRange = { 155.220, 157.220 }, + coverage = 250, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { color = 25, visibleToNacs = { 141 } } + }, + [3] = { + name = "10-1", + type = "conventional", + frequency = 155.100, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { color = 47, visibleToNacs = { 141 } } + }, + [4] = { + name = "OPS-1", + type = "conventional", + frequency = 157.350, + allowedNacs = { "141" }, + scanAllowedNacs = { "110", "200" }, + gps = { color = 40, visibleToNacs = { 141 } } + }, + }, + } + } +} diff --git a/resources/radio/data.js b/resources/radio/data.js deleted file mode 100644 index 04f52d765..000000000 --- a/resources/radio/data.js +++ /dev/null @@ -1,29 +0,0 @@ -const availableRadios = [ - "RADIO_01_CLASS_ROCK", // Los Santos Rock Radio - "RADIO_02_POP", // Non-Stop-Pop FM - "RADIO_03_HIPHOP_NEW", // Radio Los Santos - "RADIO_04_PUNK", // Channel X - "RADIO_05_TALK_01", // West Coast Talk Radio - "RADIO_06_COUNTRY", // Rebel Radio - "RADIO_07_DANCE_01", // Soulwax FM - "RADIO_08_MEXICAN", // East Los FM - "RADIO_09_HIPHOP_OLD", // West Coast Classics - "RADIO_11_TALK_02", // Blaine County Radio - "RADIO_12_REGGAE", // Blue Ark - "RADIO_13_JAZZ", // Worldwide FM - "RADIO_14_DANCE_02", // FlyLo FM - "RADIO_15_MOTOWN", // The Lowdown 91.1 - "RADIO_16_SILVERLAKE", // Radio Mirror Park - "RADIO_17_FUNK", // Space 103.2 - "RADIO_18_90S_ROCK", // Vinewood Boulevard Radio - "RADIO_19_USER", // Self Radio - "RADIO_20_THELAB", // The Lab - "RADIO_21_DLC_XM17", // Blonded Los Santos 97.8 FM - "RADIO_22_DLC_BATTLE_MIX1_RADIO", // Los Santos Underground Radio - "RADIO_23_DLC_XM19_RADIO", // iFruit Radio - "RADIO_27_DLC_PRHEI4", // Still Slipping Los Santos - "RADIO_34_DLC_HEI4_KULT", // Kult FM - "RADIO_35_DLC_HEI4_MLR", // The Music Locker - "RADIO_36_AUDIOPLAYER", // Media Player - "RADIO_37_MOTOMAMI" // MOTOMAMI Los Santos -]; \ No newline at end of file diff --git a/resources/radio/fxmanifest.lua b/resources/radio/fxmanifest.lua index 75d59f750..067afa34f 100644 --- a/resources/radio/fxmanifest.lua +++ b/resources/radio/fxmanifest.lua @@ -1,20 +1,46 @@ +-- Resource Information +-- Ensure the fx_version is set to 'bodacious' for compatibility with FiveM fx_version 'bodacious' game 'gta5' -author 'Hellslicer' -description 'This resource allows you to integrate your own radios in place of the original radios' -version '2.0.0' +name 'Tommy\'s Radio' +description 'FiveM In-Game Radio Script' +author 'Tommy Johnston' +version 'v3.2' --- Example custom radios -supersede_radio 'RADIO_21_DLC_XM17' { url = 'https://live.truckers.fm/', volume = 0.2, name = 'Truckers FM Live' } +-- Lua Version +lua54 'yes' +node_version '22' +-- UI Configuration +ui_page 'client/index.html' + +-- Files files { - 'index.html' + 'server/dist/bundle.js', + 'client/dist/bundle.js', + 'client/radios/**/*.*', + 'client/index.html', + 'server/dispatch.html', } -ui_page 'index.html' +-- Scripts +shared_scripts { + 'config.lua', + 'audio.lua', + 'shared.lua', + 'blips.lua', +} -client_scripts { - 'data.js', - 'client.js' -} \ No newline at end of file +server_scripts { + 'server/dist/bundle.js', + 'server/dispatch.lua', +} + +-- Escrow Configuration +escrow_ignore { + 'config.lua', + 'client/radios/**/*.*' +} + +dependency '/assetpacks' \ No newline at end of file diff --git a/resources/radio/index.html b/resources/radio/index.html deleted file mode 100644 index e1d82a2fa..000000000 --- a/resources/radio/index.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/resources/radio/server/dispatch.html b/resources/radio/server/dispatch.html new file mode 100644 index 000000000..f4f2069e9 --- /dev/null +++ b/resources/radio/server/dispatch.html @@ -0,0 +1 @@ + Radio Dispatch Panel
Connected
MUTED
Loading dispatch panel...
Connecting to radio system

Settings

Configure your dispatch panel preferences

Update your callsign without re-logging in

Click and press a key to change PTT button

Volume for tone, background effects, and transmission sounds

Volume for voice communications

Choose your preferred theme

Configure Endpoint

Welcome! Please configure your dispatch server endpoint to continue. You can use the default endpoint or specify a custom one.

Dispatch Access Control

Enter your Network Access Code to continue

Broadcast Alert

Send User Alert

Send alert to user

Disconnect User

Are you sure you want to disconnect this user from the radio system?

\ No newline at end of file diff --git a/resources/radio/server/dispatch.lua b/resources/radio/server/dispatch.lua new file mode 100644 index 000000000..f2a702ce8 Binary files /dev/null and b/resources/radio/server/dispatch.lua differ diff --git a/resources/radio/server/dist/bundle.js b/resources/radio/server/dist/bundle.js new file mode 100644 index 000000000..26386b83d --- /dev/null +++ b/resources/radio/server/dist/bundle.js @@ -0,0 +1,26287 @@ +var __create = Object.create; +var __getProtoOf = Object.getPrototypeOf; +var __defProp = Object.defineProperty; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __toESM = (mod, isNodeMode, target) => { + target = mod != null ? __create(__getProtoOf(mod)) : {}; + const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target; + for (let key of __getOwnPropNames(mod)) + if (!__hasOwnProp.call(to, key)) + __defProp(to, key, { + get: () => mod[key], + enumerable: true + }); + return to; +}; +var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); + +// node_modules/accepts/node_modules/negotiator/lib/charset.js +var require_charset = __commonJS((exports2, module2) => { + module2.exports = preferredCharsets; + module2.exports.preferredCharsets = preferredCharsets; + var simpleCharsetRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/; + function parseAcceptCharset(accept) { + var accepts = accept.split(","); + for (var i = 0, j = 0;i < accepts.length; i++) { + var charset = parseCharset(accepts[i].trim(), i); + if (charset) { + accepts[j++] = charset; + } + } + accepts.length = j; + return accepts; + } + function parseCharset(str, i) { + var match = simpleCharsetRegExp.exec(str); + if (!match) + return null; + var charset = match[1]; + var q = 1; + if (match[2]) { + var params = match[2].split(";"); + for (var j = 0;j < params.length; j++) { + var p = params[j].trim().split("="); + if (p[0] === "q") { + q = parseFloat(p[1]); + break; + } + } + } + return { + charset, + q, + i + }; + } + function getCharsetPriority(charset, accepted, index) { + var priority = { o: -1, q: 0, s: 0 }; + for (var i = 0;i < accepted.length; i++) { + var spec = specify(charset, accepted[i], index); + if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) { + priority = spec; + } + } + return priority; + } + function specify(charset, spec, index) { + var s = 0; + if (spec.charset.toLowerCase() === charset.toLowerCase()) { + s |= 1; + } else if (spec.charset !== "*") { + return null; + } + return { + i: index, + o: spec.i, + q: spec.q, + s + }; + } + function preferredCharsets(accept, provided) { + var accepts = parseAcceptCharset(accept === undefined ? "*" : accept || ""); + if (!provided) { + return accepts.filter(isQuality).sort(compareSpecs).map(getFullCharset); + } + var priorities = provided.map(function getPriority(type, index) { + return getCharsetPriority(type, accepts, index); + }); + return priorities.filter(isQuality).sort(compareSpecs).map(function getCharset(priority) { + return provided[priorities.indexOf(priority)]; + }); + } + function compareSpecs(a, b) { + return b.q - a.q || b.s - a.s || a.o - b.o || a.i - b.i || 0; + } + function getFullCharset(spec) { + return spec.charset; + } + function isQuality(spec) { + return spec.q > 0; + } +}); + +// node_modules/accepts/node_modules/negotiator/lib/encoding.js +var require_encoding = __commonJS((exports2, module2) => { + module2.exports = preferredEncodings; + module2.exports.preferredEncodings = preferredEncodings; + var simpleEncodingRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/; + function parseAcceptEncoding(accept) { + var accepts = accept.split(","); + var hasIdentity = false; + var minQuality = 1; + for (var i = 0, j = 0;i < accepts.length; i++) { + var encoding = parseEncoding(accepts[i].trim(), i); + if (encoding) { + accepts[j++] = encoding; + hasIdentity = hasIdentity || specify("identity", encoding); + minQuality = Math.min(minQuality, encoding.q || 1); + } + } + if (!hasIdentity) { + accepts[j++] = { + encoding: "identity", + q: minQuality, + i + }; + } + accepts.length = j; + return accepts; + } + function parseEncoding(str, i) { + var match = simpleEncodingRegExp.exec(str); + if (!match) + return null; + var encoding = match[1]; + var q = 1; + if (match[2]) { + var params = match[2].split(";"); + for (var j = 0;j < params.length; j++) { + var p = params[j].trim().split("="); + if (p[0] === "q") { + q = parseFloat(p[1]); + break; + } + } + } + return { + encoding, + q, + i + }; + } + function getEncodingPriority(encoding, accepted, index) { + var priority = { o: -1, q: 0, s: 0 }; + for (var i = 0;i < accepted.length; i++) { + var spec = specify(encoding, accepted[i], index); + if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) { + priority = spec; + } + } + return priority; + } + function specify(encoding, spec, index) { + var s = 0; + if (spec.encoding.toLowerCase() === encoding.toLowerCase()) { + s |= 1; + } else if (spec.encoding !== "*") { + return null; + } + return { + i: index, + o: spec.i, + q: spec.q, + s + }; + } + function preferredEncodings(accept, provided) { + var accepts = parseAcceptEncoding(accept || ""); + if (!provided) { + return accepts.filter(isQuality).sort(compareSpecs).map(getFullEncoding); + } + var priorities = provided.map(function getPriority(type, index) { + return getEncodingPriority(type, accepts, index); + }); + return priorities.filter(isQuality).sort(compareSpecs).map(function getEncoding(priority) { + return provided[priorities.indexOf(priority)]; + }); + } + function compareSpecs(a, b) { + return b.q - a.q || b.s - a.s || a.o - b.o || a.i - b.i || 0; + } + function getFullEncoding(spec) { + return spec.encoding; + } + function isQuality(spec) { + return spec.q > 0; + } +}); + +// node_modules/accepts/node_modules/negotiator/lib/language.js +var require_language = __commonJS((exports2, module2) => { + module2.exports = preferredLanguages; + module2.exports.preferredLanguages = preferredLanguages; + var simpleLanguageRegExp = /^\s*([^\s\-;]+)(?:-([^\s;]+))?\s*(?:;(.*))?$/; + function parseAcceptLanguage(accept) { + var accepts = accept.split(","); + for (var i = 0, j = 0;i < accepts.length; i++) { + var language = parseLanguage(accepts[i].trim(), i); + if (language) { + accepts[j++] = language; + } + } + accepts.length = j; + return accepts; + } + function parseLanguage(str, i) { + var match = simpleLanguageRegExp.exec(str); + if (!match) + return null; + var prefix = match[1]; + var suffix = match[2]; + var full = prefix; + if (suffix) + full += "-" + suffix; + var q = 1; + if (match[3]) { + var params = match[3].split(";"); + for (var j = 0;j < params.length; j++) { + var p = params[j].split("="); + if (p[0] === "q") + q = parseFloat(p[1]); + } + } + return { + prefix, + suffix, + q, + i, + full + }; + } + function getLanguagePriority(language, accepted, index) { + var priority = { o: -1, q: 0, s: 0 }; + for (var i = 0;i < accepted.length; i++) { + var spec = specify(language, accepted[i], index); + if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) { + priority = spec; + } + } + return priority; + } + function specify(language, spec, index) { + var p = parseLanguage(language); + if (!p) + return null; + var s = 0; + if (spec.full.toLowerCase() === p.full.toLowerCase()) { + s |= 4; + } else if (spec.prefix.toLowerCase() === p.full.toLowerCase()) { + s |= 2; + } else if (spec.full.toLowerCase() === p.prefix.toLowerCase()) { + s |= 1; + } else if (spec.full !== "*") { + return null; + } + return { + i: index, + o: spec.i, + q: spec.q, + s + }; + } + function preferredLanguages(accept, provided) { + var accepts = parseAcceptLanguage(accept === undefined ? "*" : accept || ""); + if (!provided) { + return accepts.filter(isQuality).sort(compareSpecs).map(getFullLanguage); + } + var priorities = provided.map(function getPriority(type, index) { + return getLanguagePriority(type, accepts, index); + }); + return priorities.filter(isQuality).sort(compareSpecs).map(function getLanguage(priority) { + return provided[priorities.indexOf(priority)]; + }); + } + function compareSpecs(a, b) { + return b.q - a.q || b.s - a.s || a.o - b.o || a.i - b.i || 0; + } + function getFullLanguage(spec) { + return spec.full; + } + function isQuality(spec) { + return spec.q > 0; + } +}); + +// node_modules/accepts/node_modules/negotiator/lib/mediaType.js +var require_mediaType = __commonJS((exports2, module2) => { + module2.exports = preferredMediaTypes; + module2.exports.preferredMediaTypes = preferredMediaTypes; + var simpleMediaTypeRegExp = /^\s*([^\s\/;]+)\/([^;\s]+)\s*(?:;(.*))?$/; + function parseAccept(accept) { + var accepts = splitMediaTypes(accept); + for (var i = 0, j = 0;i < accepts.length; i++) { + var mediaType = parseMediaType(accepts[i].trim(), i); + if (mediaType) { + accepts[j++] = mediaType; + } + } + accepts.length = j; + return accepts; + } + function parseMediaType(str, i) { + var match = simpleMediaTypeRegExp.exec(str); + if (!match) + return null; + var params = Object.create(null); + var q = 1; + var subtype = match[2]; + var type = match[1]; + if (match[3]) { + var kvps = splitParameters(match[3]).map(splitKeyValuePair); + for (var j = 0;j < kvps.length; j++) { + var pair = kvps[j]; + var key = pair[0].toLowerCase(); + var val = pair[1]; + var value = val && val[0] === '"' && val[val.length - 1] === '"' ? val.substr(1, val.length - 2) : val; + if (key === "q") { + q = parseFloat(value); + break; + } + params[key] = value; + } + } + return { + type, + subtype, + params, + q, + i + }; + } + function getMediaTypePriority(type, accepted, index) { + var priority = { o: -1, q: 0, s: 0 }; + for (var i = 0;i < accepted.length; i++) { + var spec = specify(type, accepted[i], index); + if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) { + priority = spec; + } + } + return priority; + } + function specify(type, spec, index) { + var p = parseMediaType(type); + var s = 0; + if (!p) { + return null; + } + if (spec.type.toLowerCase() == p.type.toLowerCase()) { + s |= 4; + } else if (spec.type != "*") { + return null; + } + if (spec.subtype.toLowerCase() == p.subtype.toLowerCase()) { + s |= 2; + } else if (spec.subtype != "*") { + return null; + } + var keys = Object.keys(spec.params); + if (keys.length > 0) { + if (keys.every(function(k) { + return spec.params[k] == "*" || (spec.params[k] || "").toLowerCase() == (p.params[k] || "").toLowerCase(); + })) { + s |= 1; + } else { + return null; + } + } + return { + i: index, + o: spec.i, + q: spec.q, + s + }; + } + function preferredMediaTypes(accept, provided) { + var accepts = parseAccept(accept === undefined ? "*/*" : accept || ""); + if (!provided) { + return accepts.filter(isQuality).sort(compareSpecs).map(getFullType); + } + var priorities = provided.map(function getPriority(type, index) { + return getMediaTypePriority(type, accepts, index); + }); + return priorities.filter(isQuality).sort(compareSpecs).map(function getType(priority) { + return provided[priorities.indexOf(priority)]; + }); + } + function compareSpecs(a, b) { + return b.q - a.q || b.s - a.s || a.o - b.o || a.i - b.i || 0; + } + function getFullType(spec) { + return spec.type + "/" + spec.subtype; + } + function isQuality(spec) { + return spec.q > 0; + } + function quoteCount(string) { + var count = 0; + var index = 0; + while ((index = string.indexOf('"', index)) !== -1) { + count++; + index++; + } + return count; + } + function splitKeyValuePair(str) { + var index = str.indexOf("="); + var key; + var val; + if (index === -1) { + key = str; + } else { + key = str.substr(0, index); + val = str.substr(index + 1); + } + return [key, val]; + } + function splitMediaTypes(accept) { + var accepts = accept.split(","); + for (var i = 1, j = 0;i < accepts.length; i++) { + if (quoteCount(accepts[j]) % 2 == 0) { + accepts[++j] = accepts[i]; + } else { + accepts[j] += "," + accepts[i]; + } + } + accepts.length = j + 1; + return accepts; + } + function splitParameters(str) { + var parameters = str.split(";"); + for (var i = 1, j = 0;i < parameters.length; i++) { + if (quoteCount(parameters[j]) % 2 == 0) { + parameters[++j] = parameters[i]; + } else { + parameters[j] += ";" + parameters[i]; + } + } + parameters.length = j + 1; + for (var i = 0;i < parameters.length; i++) { + parameters[i] = parameters[i].trim(); + } + return parameters; + } +}); + +// node_modules/accepts/node_modules/negotiator/index.js +var require_negotiator = __commonJS((exports2, module2) => { + /*! + * negotiator + * Copyright(c) 2012 Federico Romero + * Copyright(c) 2012-2014 Isaac Z. Schlueter + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + var preferredCharsets = require_charset(); + var preferredEncodings = require_encoding(); + var preferredLanguages = require_language(); + var preferredMediaTypes = require_mediaType(); + module2.exports = Negotiator; + module2.exports.Negotiator = Negotiator; + function Negotiator(request) { + if (!(this instanceof Negotiator)) { + return new Negotiator(request); + } + this.request = request; + } + Negotiator.prototype.charset = function charset(available) { + var set = this.charsets(available); + return set && set[0]; + }; + Negotiator.prototype.charsets = function charsets(available) { + return preferredCharsets(this.request.headers["accept-charset"], available); + }; + Negotiator.prototype.encoding = function encoding(available) { + var set = this.encodings(available); + return set && set[0]; + }; + Negotiator.prototype.encodings = function encodings(available) { + return preferredEncodings(this.request.headers["accept-encoding"], available); + }; + Negotiator.prototype.language = function language(available) { + var set = this.languages(available); + return set && set[0]; + }; + Negotiator.prototype.languages = function languages(available) { + return preferredLanguages(this.request.headers["accept-language"], available); + }; + Negotiator.prototype.mediaType = function mediaType(available) { + var set = this.mediaTypes(available); + return set && set[0]; + }; + Negotiator.prototype.mediaTypes = function mediaTypes(available) { + return preferredMediaTypes(this.request.headers.accept, available); + }; + Negotiator.prototype.preferredCharset = Negotiator.prototype.charset; + Negotiator.prototype.preferredCharsets = Negotiator.prototype.charsets; + Negotiator.prototype.preferredEncoding = Negotiator.prototype.encoding; + Negotiator.prototype.preferredEncodings = Negotiator.prototype.encodings; + Negotiator.prototype.preferredLanguage = Negotiator.prototype.language; + Negotiator.prototype.preferredLanguages = Negotiator.prototype.languages; + Negotiator.prototype.preferredMediaType = Negotiator.prototype.mediaType; + Negotiator.prototype.preferredMediaTypes = Negotiator.prototype.mediaTypes; +}); + +// node_modules/mime-db/db.json +var require_db = __commonJS((exports2, module2) => { + module2.exports = { + "application/1d-interleaved-parityfec": { + source: "iana" + }, + "application/3gpdash-qoe-report+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/3gpp-ims+xml": { + source: "iana", + compressible: true + }, + "application/3gpphal+json": { + source: "iana", + compressible: true + }, + "application/3gpphalforms+json": { + source: "iana", + compressible: true + }, + "application/a2l": { + source: "iana" + }, + "application/ace+cbor": { + source: "iana" + }, + "application/activemessage": { + source: "iana" + }, + "application/activity+json": { + source: "iana", + compressible: true + }, + "application/alto-costmap+json": { + source: "iana", + compressible: true + }, + "application/alto-costmapfilter+json": { + source: "iana", + compressible: true + }, + "application/alto-directory+json": { + source: "iana", + compressible: true + }, + "application/alto-endpointcost+json": { + source: "iana", + compressible: true + }, + "application/alto-endpointcostparams+json": { + source: "iana", + compressible: true + }, + "application/alto-endpointprop+json": { + source: "iana", + compressible: true + }, + "application/alto-endpointpropparams+json": { + source: "iana", + compressible: true + }, + "application/alto-error+json": { + source: "iana", + compressible: true + }, + "application/alto-networkmap+json": { + source: "iana", + compressible: true + }, + "application/alto-networkmapfilter+json": { + source: "iana", + compressible: true + }, + "application/alto-updatestreamcontrol+json": { + source: "iana", + compressible: true + }, + "application/alto-updatestreamparams+json": { + source: "iana", + compressible: true + }, + "application/aml": { + source: "iana" + }, + "application/andrew-inset": { + source: "iana", + extensions: ["ez"] + }, + "application/applefile": { + source: "iana" + }, + "application/applixware": { + source: "apache", + extensions: ["aw"] + }, + "application/at+jwt": { + source: "iana" + }, + "application/atf": { + source: "iana" + }, + "application/atfx": { + source: "iana" + }, + "application/atom+xml": { + source: "iana", + compressible: true, + extensions: ["atom"] + }, + "application/atomcat+xml": { + source: "iana", + compressible: true, + extensions: ["atomcat"] + }, + "application/atomdeleted+xml": { + source: "iana", + compressible: true, + extensions: ["atomdeleted"] + }, + "application/atomicmail": { + source: "iana" + }, + "application/atomsvc+xml": { + source: "iana", + compressible: true, + extensions: ["atomsvc"] + }, + "application/atsc-dwd+xml": { + source: "iana", + compressible: true, + extensions: ["dwd"] + }, + "application/atsc-dynamic-event-message": { + source: "iana" + }, + "application/atsc-held+xml": { + source: "iana", + compressible: true, + extensions: ["held"] + }, + "application/atsc-rdt+json": { + source: "iana", + compressible: true + }, + "application/atsc-rsat+xml": { + source: "iana", + compressible: true, + extensions: ["rsat"] + }, + "application/atxml": { + source: "iana" + }, + "application/auth-policy+xml": { + source: "iana", + compressible: true + }, + "application/bacnet-xdd+zip": { + source: "iana", + compressible: false + }, + "application/batch-smtp": { + source: "iana" + }, + "application/bdoc": { + compressible: false, + extensions: ["bdoc"] + }, + "application/beep+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/calendar+json": { + source: "iana", + compressible: true + }, + "application/calendar+xml": { + source: "iana", + compressible: true, + extensions: ["xcs"] + }, + "application/call-completion": { + source: "iana" + }, + "application/cals-1840": { + source: "iana" + }, + "application/captive+json": { + source: "iana", + compressible: true + }, + "application/cbor": { + source: "iana" + }, + "application/cbor-seq": { + source: "iana" + }, + "application/cccex": { + source: "iana" + }, + "application/ccmp+xml": { + source: "iana", + compressible: true + }, + "application/ccxml+xml": { + source: "iana", + compressible: true, + extensions: ["ccxml"] + }, + "application/cdfx+xml": { + source: "iana", + compressible: true, + extensions: ["cdfx"] + }, + "application/cdmi-capability": { + source: "iana", + extensions: ["cdmia"] + }, + "application/cdmi-container": { + source: "iana", + extensions: ["cdmic"] + }, + "application/cdmi-domain": { + source: "iana", + extensions: ["cdmid"] + }, + "application/cdmi-object": { + source: "iana", + extensions: ["cdmio"] + }, + "application/cdmi-queue": { + source: "iana", + extensions: ["cdmiq"] + }, + "application/cdni": { + source: "iana" + }, + "application/cea": { + source: "iana" + }, + "application/cea-2018+xml": { + source: "iana", + compressible: true + }, + "application/cellml+xml": { + source: "iana", + compressible: true + }, + "application/cfw": { + source: "iana" + }, + "application/city+json": { + source: "iana", + compressible: true + }, + "application/clr": { + source: "iana" + }, + "application/clue+xml": { + source: "iana", + compressible: true + }, + "application/clue_info+xml": { + source: "iana", + compressible: true + }, + "application/cms": { + source: "iana" + }, + "application/cnrp+xml": { + source: "iana", + compressible: true + }, + "application/coap-group+json": { + source: "iana", + compressible: true + }, + "application/coap-payload": { + source: "iana" + }, + "application/commonground": { + source: "iana" + }, + "application/conference-info+xml": { + source: "iana", + compressible: true + }, + "application/cose": { + source: "iana" + }, + "application/cose-key": { + source: "iana" + }, + "application/cose-key-set": { + source: "iana" + }, + "application/cpl+xml": { + source: "iana", + compressible: true, + extensions: ["cpl"] + }, + "application/csrattrs": { + source: "iana" + }, + "application/csta+xml": { + source: "iana", + compressible: true + }, + "application/cstadata+xml": { + source: "iana", + compressible: true + }, + "application/csvm+json": { + source: "iana", + compressible: true + }, + "application/cu-seeme": { + source: "apache", + extensions: ["cu"] + }, + "application/cwt": { + source: "iana" + }, + "application/cybercash": { + source: "iana" + }, + "application/dart": { + compressible: true + }, + "application/dash+xml": { + source: "iana", + compressible: true, + extensions: ["mpd"] + }, + "application/dash-patch+xml": { + source: "iana", + compressible: true, + extensions: ["mpp"] + }, + "application/dashdelta": { + source: "iana" + }, + "application/davmount+xml": { + source: "iana", + compressible: true, + extensions: ["davmount"] + }, + "application/dca-rft": { + source: "iana" + }, + "application/dcd": { + source: "iana" + }, + "application/dec-dx": { + source: "iana" + }, + "application/dialog-info+xml": { + source: "iana", + compressible: true + }, + "application/dicom": { + source: "iana" + }, + "application/dicom+json": { + source: "iana", + compressible: true + }, + "application/dicom+xml": { + source: "iana", + compressible: true + }, + "application/dii": { + source: "iana" + }, + "application/dit": { + source: "iana" + }, + "application/dns": { + source: "iana" + }, + "application/dns+json": { + source: "iana", + compressible: true + }, + "application/dns-message": { + source: "iana" + }, + "application/docbook+xml": { + source: "apache", + compressible: true, + extensions: ["dbk"] + }, + "application/dots+cbor": { + source: "iana" + }, + "application/dskpp+xml": { + source: "iana", + compressible: true + }, + "application/dssc+der": { + source: "iana", + extensions: ["dssc"] + }, + "application/dssc+xml": { + source: "iana", + compressible: true, + extensions: ["xdssc"] + }, + "application/dvcs": { + source: "iana" + }, + "application/ecmascript": { + source: "iana", + compressible: true, + extensions: ["es", "ecma"] + }, + "application/edi-consent": { + source: "iana" + }, + "application/edi-x12": { + source: "iana", + compressible: false + }, + "application/edifact": { + source: "iana", + compressible: false + }, + "application/efi": { + source: "iana" + }, + "application/elm+json": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/elm+xml": { + source: "iana", + compressible: true + }, + "application/emergencycalldata.cap+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/emergencycalldata.comment+xml": { + source: "iana", + compressible: true + }, + "application/emergencycalldata.control+xml": { + source: "iana", + compressible: true + }, + "application/emergencycalldata.deviceinfo+xml": { + source: "iana", + compressible: true + }, + "application/emergencycalldata.ecall.msd": { + source: "iana" + }, + "application/emergencycalldata.providerinfo+xml": { + source: "iana", + compressible: true + }, + "application/emergencycalldata.serviceinfo+xml": { + source: "iana", + compressible: true + }, + "application/emergencycalldata.subscriberinfo+xml": { + source: "iana", + compressible: true + }, + "application/emergencycalldata.veds+xml": { + source: "iana", + compressible: true + }, + "application/emma+xml": { + source: "iana", + compressible: true, + extensions: ["emma"] + }, + "application/emotionml+xml": { + source: "iana", + compressible: true, + extensions: ["emotionml"] + }, + "application/encaprtp": { + source: "iana" + }, + "application/epp+xml": { + source: "iana", + compressible: true + }, + "application/epub+zip": { + source: "iana", + compressible: false, + extensions: ["epub"] + }, + "application/eshop": { + source: "iana" + }, + "application/exi": { + source: "iana", + extensions: ["exi"] + }, + "application/expect-ct-report+json": { + source: "iana", + compressible: true + }, + "application/express": { + source: "iana", + extensions: ["exp"] + }, + "application/fastinfoset": { + source: "iana" + }, + "application/fastsoap": { + source: "iana" + }, + "application/fdt+xml": { + source: "iana", + compressible: true, + extensions: ["fdt"] + }, + "application/fhir+json": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/fhir+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/fido.trusted-apps+json": { + compressible: true + }, + "application/fits": { + source: "iana" + }, + "application/flexfec": { + source: "iana" + }, + "application/font-sfnt": { + source: "iana" + }, + "application/font-tdpfr": { + source: "iana", + extensions: ["pfr"] + }, + "application/font-woff": { + source: "iana", + compressible: false + }, + "application/framework-attributes+xml": { + source: "iana", + compressible: true + }, + "application/geo+json": { + source: "iana", + compressible: true, + extensions: ["geojson"] + }, + "application/geo+json-seq": { + source: "iana" + }, + "application/geopackage+sqlite3": { + source: "iana" + }, + "application/geoxacml+xml": { + source: "iana", + compressible: true + }, + "application/gltf-buffer": { + source: "iana" + }, + "application/gml+xml": { + source: "iana", + compressible: true, + extensions: ["gml"] + }, + "application/gpx+xml": { + source: "apache", + compressible: true, + extensions: ["gpx"] + }, + "application/gxf": { + source: "apache", + extensions: ["gxf"] + }, + "application/gzip": { + source: "iana", + compressible: false, + extensions: ["gz"] + }, + "application/h224": { + source: "iana" + }, + "application/held+xml": { + source: "iana", + compressible: true + }, + "application/hjson": { + extensions: ["hjson"] + }, + "application/http": { + source: "iana" + }, + "application/hyperstudio": { + source: "iana", + extensions: ["stk"] + }, + "application/ibe-key-request+xml": { + source: "iana", + compressible: true + }, + "application/ibe-pkg-reply+xml": { + source: "iana", + compressible: true + }, + "application/ibe-pp-data": { + source: "iana" + }, + "application/iges": { + source: "iana" + }, + "application/im-iscomposing+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/index": { + source: "iana" + }, + "application/index.cmd": { + source: "iana" + }, + "application/index.obj": { + source: "iana" + }, + "application/index.response": { + source: "iana" + }, + "application/index.vnd": { + source: "iana" + }, + "application/inkml+xml": { + source: "iana", + compressible: true, + extensions: ["ink", "inkml"] + }, + "application/iotp": { + source: "iana" + }, + "application/ipfix": { + source: "iana", + extensions: ["ipfix"] + }, + "application/ipp": { + source: "iana" + }, + "application/isup": { + source: "iana" + }, + "application/its+xml": { + source: "iana", + compressible: true, + extensions: ["its"] + }, + "application/java-archive": { + source: "apache", + compressible: false, + extensions: ["jar", "war", "ear"] + }, + "application/java-serialized-object": { + source: "apache", + compressible: false, + extensions: ["ser"] + }, + "application/java-vm": { + source: "apache", + compressible: false, + extensions: ["class"] + }, + "application/javascript": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["js", "mjs"] + }, + "application/jf2feed+json": { + source: "iana", + compressible: true + }, + "application/jose": { + source: "iana" + }, + "application/jose+json": { + source: "iana", + compressible: true + }, + "application/jrd+json": { + source: "iana", + compressible: true + }, + "application/jscalendar+json": { + source: "iana", + compressible: true + }, + "application/json": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["json", "map"] + }, + "application/json-patch+json": { + source: "iana", + compressible: true + }, + "application/json-seq": { + source: "iana" + }, + "application/json5": { + extensions: ["json5"] + }, + "application/jsonml+json": { + source: "apache", + compressible: true, + extensions: ["jsonml"] + }, + "application/jwk+json": { + source: "iana", + compressible: true + }, + "application/jwk-set+json": { + source: "iana", + compressible: true + }, + "application/jwt": { + source: "iana" + }, + "application/kpml-request+xml": { + source: "iana", + compressible: true + }, + "application/kpml-response+xml": { + source: "iana", + compressible: true + }, + "application/ld+json": { + source: "iana", + compressible: true, + extensions: ["jsonld"] + }, + "application/lgr+xml": { + source: "iana", + compressible: true, + extensions: ["lgr"] + }, + "application/link-format": { + source: "iana" + }, + "application/load-control+xml": { + source: "iana", + compressible: true + }, + "application/lost+xml": { + source: "iana", + compressible: true, + extensions: ["lostxml"] + }, + "application/lostsync+xml": { + source: "iana", + compressible: true + }, + "application/lpf+zip": { + source: "iana", + compressible: false + }, + "application/lxf": { + source: "iana" + }, + "application/mac-binhex40": { + source: "iana", + extensions: ["hqx"] + }, + "application/mac-compactpro": { + source: "apache", + extensions: ["cpt"] + }, + "application/macwriteii": { + source: "iana" + }, + "application/mads+xml": { + source: "iana", + compressible: true, + extensions: ["mads"] + }, + "application/manifest+json": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["webmanifest"] + }, + "application/marc": { + source: "iana", + extensions: ["mrc"] + }, + "application/marcxml+xml": { + source: "iana", + compressible: true, + extensions: ["mrcx"] + }, + "application/mathematica": { + source: "iana", + extensions: ["ma", "nb", "mb"] + }, + "application/mathml+xml": { + source: "iana", + compressible: true, + extensions: ["mathml"] + }, + "application/mathml-content+xml": { + source: "iana", + compressible: true + }, + "application/mathml-presentation+xml": { + source: "iana", + compressible: true + }, + "application/mbms-associated-procedure-description+xml": { + source: "iana", + compressible: true + }, + "application/mbms-deregister+xml": { + source: "iana", + compressible: true + }, + "application/mbms-envelope+xml": { + source: "iana", + compressible: true + }, + "application/mbms-msk+xml": { + source: "iana", + compressible: true + }, + "application/mbms-msk-response+xml": { + source: "iana", + compressible: true + }, + "application/mbms-protection-description+xml": { + source: "iana", + compressible: true + }, + "application/mbms-reception-report+xml": { + source: "iana", + compressible: true + }, + "application/mbms-register+xml": { + source: "iana", + compressible: true + }, + "application/mbms-register-response+xml": { + source: "iana", + compressible: true + }, + "application/mbms-schedule+xml": { + source: "iana", + compressible: true + }, + "application/mbms-user-service-description+xml": { + source: "iana", + compressible: true + }, + "application/mbox": { + source: "iana", + extensions: ["mbox"] + }, + "application/media-policy-dataset+xml": { + source: "iana", + compressible: true, + extensions: ["mpf"] + }, + "application/media_control+xml": { + source: "iana", + compressible: true + }, + "application/mediaservercontrol+xml": { + source: "iana", + compressible: true, + extensions: ["mscml"] + }, + "application/merge-patch+json": { + source: "iana", + compressible: true + }, + "application/metalink+xml": { + source: "apache", + compressible: true, + extensions: ["metalink"] + }, + "application/metalink4+xml": { + source: "iana", + compressible: true, + extensions: ["meta4"] + }, + "application/mets+xml": { + source: "iana", + compressible: true, + extensions: ["mets"] + }, + "application/mf4": { + source: "iana" + }, + "application/mikey": { + source: "iana" + }, + "application/mipc": { + source: "iana" + }, + "application/missing-blocks+cbor-seq": { + source: "iana" + }, + "application/mmt-aei+xml": { + source: "iana", + compressible: true, + extensions: ["maei"] + }, + "application/mmt-usd+xml": { + source: "iana", + compressible: true, + extensions: ["musd"] + }, + "application/mods+xml": { + source: "iana", + compressible: true, + extensions: ["mods"] + }, + "application/moss-keys": { + source: "iana" + }, + "application/moss-signature": { + source: "iana" + }, + "application/mosskey-data": { + source: "iana" + }, + "application/mosskey-request": { + source: "iana" + }, + "application/mp21": { + source: "iana", + extensions: ["m21", "mp21"] + }, + "application/mp4": { + source: "iana", + extensions: ["mp4s", "m4p"] + }, + "application/mpeg4-generic": { + source: "iana" + }, + "application/mpeg4-iod": { + source: "iana" + }, + "application/mpeg4-iod-xmt": { + source: "iana" + }, + "application/mrb-consumer+xml": { + source: "iana", + compressible: true + }, + "application/mrb-publish+xml": { + source: "iana", + compressible: true + }, + "application/msc-ivr+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/msc-mixer+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/msword": { + source: "iana", + compressible: false, + extensions: ["doc", "dot"] + }, + "application/mud+json": { + source: "iana", + compressible: true + }, + "application/multipart-core": { + source: "iana" + }, + "application/mxf": { + source: "iana", + extensions: ["mxf"] + }, + "application/n-quads": { + source: "iana", + extensions: ["nq"] + }, + "application/n-triples": { + source: "iana", + extensions: ["nt"] + }, + "application/nasdata": { + source: "iana" + }, + "application/news-checkgroups": { + source: "iana", + charset: "US-ASCII" + }, + "application/news-groupinfo": { + source: "iana", + charset: "US-ASCII" + }, + "application/news-transmission": { + source: "iana" + }, + "application/nlsml+xml": { + source: "iana", + compressible: true + }, + "application/node": { + source: "iana", + extensions: ["cjs"] + }, + "application/nss": { + source: "iana" + }, + "application/oauth-authz-req+jwt": { + source: "iana" + }, + "application/oblivious-dns-message": { + source: "iana" + }, + "application/ocsp-request": { + source: "iana" + }, + "application/ocsp-response": { + source: "iana" + }, + "application/octet-stream": { + source: "iana", + compressible: false, + extensions: ["bin", "dms", "lrf", "mar", "so", "dist", "distz", "pkg", "bpk", "dump", "elc", "deploy", "exe", "dll", "deb", "dmg", "iso", "img", "msi", "msp", "msm", "buffer"] + }, + "application/oda": { + source: "iana", + extensions: ["oda"] + }, + "application/odm+xml": { + source: "iana", + compressible: true + }, + "application/odx": { + source: "iana" + }, + "application/oebps-package+xml": { + source: "iana", + compressible: true, + extensions: ["opf"] + }, + "application/ogg": { + source: "iana", + compressible: false, + extensions: ["ogx"] + }, + "application/omdoc+xml": { + source: "apache", + compressible: true, + extensions: ["omdoc"] + }, + "application/onenote": { + source: "apache", + extensions: ["onetoc", "onetoc2", "onetmp", "onepkg"] + }, + "application/opc-nodeset+xml": { + source: "iana", + compressible: true + }, + "application/oscore": { + source: "iana" + }, + "application/oxps": { + source: "iana", + extensions: ["oxps"] + }, + "application/p21": { + source: "iana" + }, + "application/p21+zip": { + source: "iana", + compressible: false + }, + "application/p2p-overlay+xml": { + source: "iana", + compressible: true, + extensions: ["relo"] + }, + "application/parityfec": { + source: "iana" + }, + "application/passport": { + source: "iana" + }, + "application/patch-ops-error+xml": { + source: "iana", + compressible: true, + extensions: ["xer"] + }, + "application/pdf": { + source: "iana", + compressible: false, + extensions: ["pdf"] + }, + "application/pdx": { + source: "iana" + }, + "application/pem-certificate-chain": { + source: "iana" + }, + "application/pgp-encrypted": { + source: "iana", + compressible: false, + extensions: ["pgp"] + }, + "application/pgp-keys": { + source: "iana", + extensions: ["asc"] + }, + "application/pgp-signature": { + source: "iana", + extensions: ["asc", "sig"] + }, + "application/pics-rules": { + source: "apache", + extensions: ["prf"] + }, + "application/pidf+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/pidf-diff+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/pkcs10": { + source: "iana", + extensions: ["p10"] + }, + "application/pkcs12": { + source: "iana" + }, + "application/pkcs7-mime": { + source: "iana", + extensions: ["p7m", "p7c"] + }, + "application/pkcs7-signature": { + source: "iana", + extensions: ["p7s"] + }, + "application/pkcs8": { + source: "iana", + extensions: ["p8"] + }, + "application/pkcs8-encrypted": { + source: "iana" + }, + "application/pkix-attr-cert": { + source: "iana", + extensions: ["ac"] + }, + "application/pkix-cert": { + source: "iana", + extensions: ["cer"] + }, + "application/pkix-crl": { + source: "iana", + extensions: ["crl"] + }, + "application/pkix-pkipath": { + source: "iana", + extensions: ["pkipath"] + }, + "application/pkixcmp": { + source: "iana", + extensions: ["pki"] + }, + "application/pls+xml": { + source: "iana", + compressible: true, + extensions: ["pls"] + }, + "application/poc-settings+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/postscript": { + source: "iana", + compressible: true, + extensions: ["ai", "eps", "ps"] + }, + "application/ppsp-tracker+json": { + source: "iana", + compressible: true + }, + "application/problem+json": { + source: "iana", + compressible: true + }, + "application/problem+xml": { + source: "iana", + compressible: true + }, + "application/provenance+xml": { + source: "iana", + compressible: true, + extensions: ["provx"] + }, + "application/prs.alvestrand.titrax-sheet": { + source: "iana" + }, + "application/prs.cww": { + source: "iana", + extensions: ["cww"] + }, + "application/prs.cyn": { + source: "iana", + charset: "7-BIT" + }, + "application/prs.hpub+zip": { + source: "iana", + compressible: false + }, + "application/prs.nprend": { + source: "iana" + }, + "application/prs.plucker": { + source: "iana" + }, + "application/prs.rdf-xml-crypt": { + source: "iana" + }, + "application/prs.xsf+xml": { + source: "iana", + compressible: true + }, + "application/pskc+xml": { + source: "iana", + compressible: true, + extensions: ["pskcxml"] + }, + "application/pvd+json": { + source: "iana", + compressible: true + }, + "application/qsig": { + source: "iana" + }, + "application/raml+yaml": { + compressible: true, + extensions: ["raml"] + }, + "application/raptorfec": { + source: "iana" + }, + "application/rdap+json": { + source: "iana", + compressible: true + }, + "application/rdf+xml": { + source: "iana", + compressible: true, + extensions: ["rdf", "owl"] + }, + "application/reginfo+xml": { + source: "iana", + compressible: true, + extensions: ["rif"] + }, + "application/relax-ng-compact-syntax": { + source: "iana", + extensions: ["rnc"] + }, + "application/remote-printing": { + source: "iana" + }, + "application/reputon+json": { + source: "iana", + compressible: true + }, + "application/resource-lists+xml": { + source: "iana", + compressible: true, + extensions: ["rl"] + }, + "application/resource-lists-diff+xml": { + source: "iana", + compressible: true, + extensions: ["rld"] + }, + "application/rfc+xml": { + source: "iana", + compressible: true + }, + "application/riscos": { + source: "iana" + }, + "application/rlmi+xml": { + source: "iana", + compressible: true + }, + "application/rls-services+xml": { + source: "iana", + compressible: true, + extensions: ["rs"] + }, + "application/route-apd+xml": { + source: "iana", + compressible: true, + extensions: ["rapd"] + }, + "application/route-s-tsid+xml": { + source: "iana", + compressible: true, + extensions: ["sls"] + }, + "application/route-usd+xml": { + source: "iana", + compressible: true, + extensions: ["rusd"] + }, + "application/rpki-ghostbusters": { + source: "iana", + extensions: ["gbr"] + }, + "application/rpki-manifest": { + source: "iana", + extensions: ["mft"] + }, + "application/rpki-publication": { + source: "iana" + }, + "application/rpki-roa": { + source: "iana", + extensions: ["roa"] + }, + "application/rpki-updown": { + source: "iana" + }, + "application/rsd+xml": { + source: "apache", + compressible: true, + extensions: ["rsd"] + }, + "application/rss+xml": { + source: "apache", + compressible: true, + extensions: ["rss"] + }, + "application/rtf": { + source: "iana", + compressible: true, + extensions: ["rtf"] + }, + "application/rtploopback": { + source: "iana" + }, + "application/rtx": { + source: "iana" + }, + "application/samlassertion+xml": { + source: "iana", + compressible: true + }, + "application/samlmetadata+xml": { + source: "iana", + compressible: true + }, + "application/sarif+json": { + source: "iana", + compressible: true + }, + "application/sarif-external-properties+json": { + source: "iana", + compressible: true + }, + "application/sbe": { + source: "iana" + }, + "application/sbml+xml": { + source: "iana", + compressible: true, + extensions: ["sbml"] + }, + "application/scaip+xml": { + source: "iana", + compressible: true + }, + "application/scim+json": { + source: "iana", + compressible: true + }, + "application/scvp-cv-request": { + source: "iana", + extensions: ["scq"] + }, + "application/scvp-cv-response": { + source: "iana", + extensions: ["scs"] + }, + "application/scvp-vp-request": { + source: "iana", + extensions: ["spq"] + }, + "application/scvp-vp-response": { + source: "iana", + extensions: ["spp"] + }, + "application/sdp": { + source: "iana", + extensions: ["sdp"] + }, + "application/secevent+jwt": { + source: "iana" + }, + "application/senml+cbor": { + source: "iana" + }, + "application/senml+json": { + source: "iana", + compressible: true + }, + "application/senml+xml": { + source: "iana", + compressible: true, + extensions: ["senmlx"] + }, + "application/senml-etch+cbor": { + source: "iana" + }, + "application/senml-etch+json": { + source: "iana", + compressible: true + }, + "application/senml-exi": { + source: "iana" + }, + "application/sensml+cbor": { + source: "iana" + }, + "application/sensml+json": { + source: "iana", + compressible: true + }, + "application/sensml+xml": { + source: "iana", + compressible: true, + extensions: ["sensmlx"] + }, + "application/sensml-exi": { + source: "iana" + }, + "application/sep+xml": { + source: "iana", + compressible: true + }, + "application/sep-exi": { + source: "iana" + }, + "application/session-info": { + source: "iana" + }, + "application/set-payment": { + source: "iana" + }, + "application/set-payment-initiation": { + source: "iana", + extensions: ["setpay"] + }, + "application/set-registration": { + source: "iana" + }, + "application/set-registration-initiation": { + source: "iana", + extensions: ["setreg"] + }, + "application/sgml": { + source: "iana" + }, + "application/sgml-open-catalog": { + source: "iana" + }, + "application/shf+xml": { + source: "iana", + compressible: true, + extensions: ["shf"] + }, + "application/sieve": { + source: "iana", + extensions: ["siv", "sieve"] + }, + "application/simple-filter+xml": { + source: "iana", + compressible: true + }, + "application/simple-message-summary": { + source: "iana" + }, + "application/simplesymbolcontainer": { + source: "iana" + }, + "application/sipc": { + source: "iana" + }, + "application/slate": { + source: "iana" + }, + "application/smil": { + source: "iana" + }, + "application/smil+xml": { + source: "iana", + compressible: true, + extensions: ["smi", "smil"] + }, + "application/smpte336m": { + source: "iana" + }, + "application/soap+fastinfoset": { + source: "iana" + }, + "application/soap+xml": { + source: "iana", + compressible: true + }, + "application/sparql-query": { + source: "iana", + extensions: ["rq"] + }, + "application/sparql-results+xml": { + source: "iana", + compressible: true, + extensions: ["srx"] + }, + "application/spdx+json": { + source: "iana", + compressible: true + }, + "application/spirits-event+xml": { + source: "iana", + compressible: true + }, + "application/sql": { + source: "iana" + }, + "application/srgs": { + source: "iana", + extensions: ["gram"] + }, + "application/srgs+xml": { + source: "iana", + compressible: true, + extensions: ["grxml"] + }, + "application/sru+xml": { + source: "iana", + compressible: true, + extensions: ["sru"] + }, + "application/ssdl+xml": { + source: "apache", + compressible: true, + extensions: ["ssdl"] + }, + "application/ssml+xml": { + source: "iana", + compressible: true, + extensions: ["ssml"] + }, + "application/stix+json": { + source: "iana", + compressible: true + }, + "application/swid+xml": { + source: "iana", + compressible: true, + extensions: ["swidtag"] + }, + "application/tamp-apex-update": { + source: "iana" + }, + "application/tamp-apex-update-confirm": { + source: "iana" + }, + "application/tamp-community-update": { + source: "iana" + }, + "application/tamp-community-update-confirm": { + source: "iana" + }, + "application/tamp-error": { + source: "iana" + }, + "application/tamp-sequence-adjust": { + source: "iana" + }, + "application/tamp-sequence-adjust-confirm": { + source: "iana" + }, + "application/tamp-status-query": { + source: "iana" + }, + "application/tamp-status-response": { + source: "iana" + }, + "application/tamp-update": { + source: "iana" + }, + "application/tamp-update-confirm": { + source: "iana" + }, + "application/tar": { + compressible: true + }, + "application/taxii+json": { + source: "iana", + compressible: true + }, + "application/td+json": { + source: "iana", + compressible: true + }, + "application/tei+xml": { + source: "iana", + compressible: true, + extensions: ["tei", "teicorpus"] + }, + "application/tetra_isi": { + source: "iana" + }, + "application/thraud+xml": { + source: "iana", + compressible: true, + extensions: ["tfi"] + }, + "application/timestamp-query": { + source: "iana" + }, + "application/timestamp-reply": { + source: "iana" + }, + "application/timestamped-data": { + source: "iana", + extensions: ["tsd"] + }, + "application/tlsrpt+gzip": { + source: "iana" + }, + "application/tlsrpt+json": { + source: "iana", + compressible: true + }, + "application/tnauthlist": { + source: "iana" + }, + "application/token-introspection+jwt": { + source: "iana" + }, + "application/toml": { + compressible: true, + extensions: ["toml"] + }, + "application/trickle-ice-sdpfrag": { + source: "iana" + }, + "application/trig": { + source: "iana", + extensions: ["trig"] + }, + "application/ttml+xml": { + source: "iana", + compressible: true, + extensions: ["ttml"] + }, + "application/tve-trigger": { + source: "iana" + }, + "application/tzif": { + source: "iana" + }, + "application/tzif-leap": { + source: "iana" + }, + "application/ubjson": { + compressible: false, + extensions: ["ubj"] + }, + "application/ulpfec": { + source: "iana" + }, + "application/urc-grpsheet+xml": { + source: "iana", + compressible: true + }, + "application/urc-ressheet+xml": { + source: "iana", + compressible: true, + extensions: ["rsheet"] + }, + "application/urc-targetdesc+xml": { + source: "iana", + compressible: true, + extensions: ["td"] + }, + "application/urc-uisocketdesc+xml": { + source: "iana", + compressible: true + }, + "application/vcard+json": { + source: "iana", + compressible: true + }, + "application/vcard+xml": { + source: "iana", + compressible: true + }, + "application/vemmi": { + source: "iana" + }, + "application/vividence.scriptfile": { + source: "apache" + }, + "application/vnd.1000minds.decision-model+xml": { + source: "iana", + compressible: true, + extensions: ["1km"] + }, + "application/vnd.3gpp-prose+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp-prose-pc3ch+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp-v2x-local-service-information": { + source: "iana" + }, + "application/vnd.3gpp.5gnas": { + source: "iana" + }, + "application/vnd.3gpp.access-transfer-events+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.bsf+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.gmop+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.gtpc": { + source: "iana" + }, + "application/vnd.3gpp.interworking-data": { + source: "iana" + }, + "application/vnd.3gpp.lpp": { + source: "iana" + }, + "application/vnd.3gpp.mc-signalling-ear": { + source: "iana" + }, + "application/vnd.3gpp.mcdata-affiliation-command+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcdata-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcdata-payload": { + source: "iana" + }, + "application/vnd.3gpp.mcdata-service-config+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcdata-signalling": { + source: "iana" + }, + "application/vnd.3gpp.mcdata-ue-config+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcdata-user-profile+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-affiliation-command+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-floor-request+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-location-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-mbms-usage-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-service-config+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-signed+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-ue-config+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-ue-init-config+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcptt-user-profile+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-affiliation-command+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-affiliation-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-location-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-mbms-usage-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-service-config+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-transmission-request+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-ue-config+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mcvideo-user-profile+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.mid-call+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.ngap": { + source: "iana" + }, + "application/vnd.3gpp.pfcp": { + source: "iana" + }, + "application/vnd.3gpp.pic-bw-large": { + source: "iana", + extensions: ["plb"] + }, + "application/vnd.3gpp.pic-bw-small": { + source: "iana", + extensions: ["psb"] + }, + "application/vnd.3gpp.pic-bw-var": { + source: "iana", + extensions: ["pvb"] + }, + "application/vnd.3gpp.s1ap": { + source: "iana" + }, + "application/vnd.3gpp.sms": { + source: "iana" + }, + "application/vnd.3gpp.sms+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.srvcc-ext+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.srvcc-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.state-and-event-info+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp.ussd+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp2.bcmcsinfo+xml": { + source: "iana", + compressible: true + }, + "application/vnd.3gpp2.sms": { + source: "iana" + }, + "application/vnd.3gpp2.tcap": { + source: "iana", + extensions: ["tcap"] + }, + "application/vnd.3lightssoftware.imagescal": { + source: "iana" + }, + "application/vnd.3m.post-it-notes": { + source: "iana", + extensions: ["pwn"] + }, + "application/vnd.accpac.simply.aso": { + source: "iana", + extensions: ["aso"] + }, + "application/vnd.accpac.simply.imp": { + source: "iana", + extensions: ["imp"] + }, + "application/vnd.acucobol": { + source: "iana", + extensions: ["acu"] + }, + "application/vnd.acucorp": { + source: "iana", + extensions: ["atc", "acutc"] + }, + "application/vnd.adobe.air-application-installer-package+zip": { + source: "apache", + compressible: false, + extensions: ["air"] + }, + "application/vnd.adobe.flash.movie": { + source: "iana" + }, + "application/vnd.adobe.formscentral.fcdt": { + source: "iana", + extensions: ["fcdt"] + }, + "application/vnd.adobe.fxp": { + source: "iana", + extensions: ["fxp", "fxpl"] + }, + "application/vnd.adobe.partial-upload": { + source: "iana" + }, + "application/vnd.adobe.xdp+xml": { + source: "iana", + compressible: true, + extensions: ["xdp"] + }, + "application/vnd.adobe.xfdf": { + source: "iana", + extensions: ["xfdf"] + }, + "application/vnd.aether.imp": { + source: "iana" + }, + "application/vnd.afpc.afplinedata": { + source: "iana" + }, + "application/vnd.afpc.afplinedata-pagedef": { + source: "iana" + }, + "application/vnd.afpc.cmoca-cmresource": { + source: "iana" + }, + "application/vnd.afpc.foca-charset": { + source: "iana" + }, + "application/vnd.afpc.foca-codedfont": { + source: "iana" + }, + "application/vnd.afpc.foca-codepage": { + source: "iana" + }, + "application/vnd.afpc.modca": { + source: "iana" + }, + "application/vnd.afpc.modca-cmtable": { + source: "iana" + }, + "application/vnd.afpc.modca-formdef": { + source: "iana" + }, + "application/vnd.afpc.modca-mediummap": { + source: "iana" + }, + "application/vnd.afpc.modca-objectcontainer": { + source: "iana" + }, + "application/vnd.afpc.modca-overlay": { + source: "iana" + }, + "application/vnd.afpc.modca-pagesegment": { + source: "iana" + }, + "application/vnd.age": { + source: "iana", + extensions: ["age"] + }, + "application/vnd.ah-barcode": { + source: "iana" + }, + "application/vnd.ahead.space": { + source: "iana", + extensions: ["ahead"] + }, + "application/vnd.airzip.filesecure.azf": { + source: "iana", + extensions: ["azf"] + }, + "application/vnd.airzip.filesecure.azs": { + source: "iana", + extensions: ["azs"] + }, + "application/vnd.amadeus+json": { + source: "iana", + compressible: true + }, + "application/vnd.amazon.ebook": { + source: "apache", + extensions: ["azw"] + }, + "application/vnd.amazon.mobi8-ebook": { + source: "iana" + }, + "application/vnd.americandynamics.acc": { + source: "iana", + extensions: ["acc"] + }, + "application/vnd.amiga.ami": { + source: "iana", + extensions: ["ami"] + }, + "application/vnd.amundsen.maze+xml": { + source: "iana", + compressible: true + }, + "application/vnd.android.ota": { + source: "iana" + }, + "application/vnd.android.package-archive": { + source: "apache", + compressible: false, + extensions: ["apk"] + }, + "application/vnd.anki": { + source: "iana" + }, + "application/vnd.anser-web-certificate-issue-initiation": { + source: "iana", + extensions: ["cii"] + }, + "application/vnd.anser-web-funds-transfer-initiation": { + source: "apache", + extensions: ["fti"] + }, + "application/vnd.antix.game-component": { + source: "iana", + extensions: ["atx"] + }, + "application/vnd.apache.arrow.file": { + source: "iana" + }, + "application/vnd.apache.arrow.stream": { + source: "iana" + }, + "application/vnd.apache.thrift.binary": { + source: "iana" + }, + "application/vnd.apache.thrift.compact": { + source: "iana" + }, + "application/vnd.apache.thrift.json": { + source: "iana" + }, + "application/vnd.api+json": { + source: "iana", + compressible: true + }, + "application/vnd.aplextor.warrp+json": { + source: "iana", + compressible: true + }, + "application/vnd.apothekende.reservation+json": { + source: "iana", + compressible: true + }, + "application/vnd.apple.installer+xml": { + source: "iana", + compressible: true, + extensions: ["mpkg"] + }, + "application/vnd.apple.keynote": { + source: "iana", + extensions: ["key"] + }, + "application/vnd.apple.mpegurl": { + source: "iana", + extensions: ["m3u8"] + }, + "application/vnd.apple.numbers": { + source: "iana", + extensions: ["numbers"] + }, + "application/vnd.apple.pages": { + source: "iana", + extensions: ["pages"] + }, + "application/vnd.apple.pkpass": { + compressible: false, + extensions: ["pkpass"] + }, + "application/vnd.arastra.swi": { + source: "iana" + }, + "application/vnd.aristanetworks.swi": { + source: "iana", + extensions: ["swi"] + }, + "application/vnd.artisan+json": { + source: "iana", + compressible: true + }, + "application/vnd.artsquare": { + source: "iana" + }, + "application/vnd.astraea-software.iota": { + source: "iana", + extensions: ["iota"] + }, + "application/vnd.audiograph": { + source: "iana", + extensions: ["aep"] + }, + "application/vnd.autopackage": { + source: "iana" + }, + "application/vnd.avalon+json": { + source: "iana", + compressible: true + }, + "application/vnd.avistar+xml": { + source: "iana", + compressible: true + }, + "application/vnd.balsamiq.bmml+xml": { + source: "iana", + compressible: true, + extensions: ["bmml"] + }, + "application/vnd.balsamiq.bmpr": { + source: "iana" + }, + "application/vnd.banana-accounting": { + source: "iana" + }, + "application/vnd.bbf.usp.error": { + source: "iana" + }, + "application/vnd.bbf.usp.msg": { + source: "iana" + }, + "application/vnd.bbf.usp.msg+json": { + source: "iana", + compressible: true + }, + "application/vnd.bekitzur-stech+json": { + source: "iana", + compressible: true + }, + "application/vnd.bint.med-content": { + source: "iana" + }, + "application/vnd.biopax.rdf+xml": { + source: "iana", + compressible: true + }, + "application/vnd.blink-idb-value-wrapper": { + source: "iana" + }, + "application/vnd.blueice.multipass": { + source: "iana", + extensions: ["mpm"] + }, + "application/vnd.bluetooth.ep.oob": { + source: "iana" + }, + "application/vnd.bluetooth.le.oob": { + source: "iana" + }, + "application/vnd.bmi": { + source: "iana", + extensions: ["bmi"] + }, + "application/vnd.bpf": { + source: "iana" + }, + "application/vnd.bpf3": { + source: "iana" + }, + "application/vnd.businessobjects": { + source: "iana", + extensions: ["rep"] + }, + "application/vnd.byu.uapi+json": { + source: "iana", + compressible: true + }, + "application/vnd.cab-jscript": { + source: "iana" + }, + "application/vnd.canon-cpdl": { + source: "iana" + }, + "application/vnd.canon-lips": { + source: "iana" + }, + "application/vnd.capasystems-pg+json": { + source: "iana", + compressible: true + }, + "application/vnd.cendio.thinlinc.clientconf": { + source: "iana" + }, + "application/vnd.century-systems.tcp_stream": { + source: "iana" + }, + "application/vnd.chemdraw+xml": { + source: "iana", + compressible: true, + extensions: ["cdxml"] + }, + "application/vnd.chess-pgn": { + source: "iana" + }, + "application/vnd.chipnuts.karaoke-mmd": { + source: "iana", + extensions: ["mmd"] + }, + "application/vnd.ciedi": { + source: "iana" + }, + "application/vnd.cinderella": { + source: "iana", + extensions: ["cdy"] + }, + "application/vnd.cirpack.isdn-ext": { + source: "iana" + }, + "application/vnd.citationstyles.style+xml": { + source: "iana", + compressible: true, + extensions: ["csl"] + }, + "application/vnd.claymore": { + source: "iana", + extensions: ["cla"] + }, + "application/vnd.cloanto.rp9": { + source: "iana", + extensions: ["rp9"] + }, + "application/vnd.clonk.c4group": { + source: "iana", + extensions: ["c4g", "c4d", "c4f", "c4p", "c4u"] + }, + "application/vnd.cluetrust.cartomobile-config": { + source: "iana", + extensions: ["c11amc"] + }, + "application/vnd.cluetrust.cartomobile-config-pkg": { + source: "iana", + extensions: ["c11amz"] + }, + "application/vnd.coffeescript": { + source: "iana" + }, + "application/vnd.collabio.xodocuments.document": { + source: "iana" + }, + "application/vnd.collabio.xodocuments.document-template": { + source: "iana" + }, + "application/vnd.collabio.xodocuments.presentation": { + source: "iana" + }, + "application/vnd.collabio.xodocuments.presentation-template": { + source: "iana" + }, + "application/vnd.collabio.xodocuments.spreadsheet": { + source: "iana" + }, + "application/vnd.collabio.xodocuments.spreadsheet-template": { + source: "iana" + }, + "application/vnd.collection+json": { + source: "iana", + compressible: true + }, + "application/vnd.collection.doc+json": { + source: "iana", + compressible: true + }, + "application/vnd.collection.next+json": { + source: "iana", + compressible: true + }, + "application/vnd.comicbook+zip": { + source: "iana", + compressible: false + }, + "application/vnd.comicbook-rar": { + source: "iana" + }, + "application/vnd.commerce-battelle": { + source: "iana" + }, + "application/vnd.commonspace": { + source: "iana", + extensions: ["csp"] + }, + "application/vnd.contact.cmsg": { + source: "iana", + extensions: ["cdbcmsg"] + }, + "application/vnd.coreos.ignition+json": { + source: "iana", + compressible: true + }, + "application/vnd.cosmocaller": { + source: "iana", + extensions: ["cmc"] + }, + "application/vnd.crick.clicker": { + source: "iana", + extensions: ["clkx"] + }, + "application/vnd.crick.clicker.keyboard": { + source: "iana", + extensions: ["clkk"] + }, + "application/vnd.crick.clicker.palette": { + source: "iana", + extensions: ["clkp"] + }, + "application/vnd.crick.clicker.template": { + source: "iana", + extensions: ["clkt"] + }, + "application/vnd.crick.clicker.wordbank": { + source: "iana", + extensions: ["clkw"] + }, + "application/vnd.criticaltools.wbs+xml": { + source: "iana", + compressible: true, + extensions: ["wbs"] + }, + "application/vnd.cryptii.pipe+json": { + source: "iana", + compressible: true + }, + "application/vnd.crypto-shade-file": { + source: "iana" + }, + "application/vnd.cryptomator.encrypted": { + source: "iana" + }, + "application/vnd.cryptomator.vault": { + source: "iana" + }, + "application/vnd.ctc-posml": { + source: "iana", + extensions: ["pml"] + }, + "application/vnd.ctct.ws+xml": { + source: "iana", + compressible: true + }, + "application/vnd.cups-pdf": { + source: "iana" + }, + "application/vnd.cups-postscript": { + source: "iana" + }, + "application/vnd.cups-ppd": { + source: "iana", + extensions: ["ppd"] + }, + "application/vnd.cups-raster": { + source: "iana" + }, + "application/vnd.cups-raw": { + source: "iana" + }, + "application/vnd.curl": { + source: "iana" + }, + "application/vnd.curl.car": { + source: "apache", + extensions: ["car"] + }, + "application/vnd.curl.pcurl": { + source: "apache", + extensions: ["pcurl"] + }, + "application/vnd.cyan.dean.root+xml": { + source: "iana", + compressible: true + }, + "application/vnd.cybank": { + source: "iana" + }, + "application/vnd.cyclonedx+json": { + source: "iana", + compressible: true + }, + "application/vnd.cyclonedx+xml": { + source: "iana", + compressible: true + }, + "application/vnd.d2l.coursepackage1p0+zip": { + source: "iana", + compressible: false + }, + "application/vnd.d3m-dataset": { + source: "iana" + }, + "application/vnd.d3m-problem": { + source: "iana" + }, + "application/vnd.dart": { + source: "iana", + compressible: true, + extensions: ["dart"] + }, + "application/vnd.data-vision.rdz": { + source: "iana", + extensions: ["rdz"] + }, + "application/vnd.datapackage+json": { + source: "iana", + compressible: true + }, + "application/vnd.dataresource+json": { + source: "iana", + compressible: true + }, + "application/vnd.dbf": { + source: "iana", + extensions: ["dbf"] + }, + "application/vnd.debian.binary-package": { + source: "iana" + }, + "application/vnd.dece.data": { + source: "iana", + extensions: ["uvf", "uvvf", "uvd", "uvvd"] + }, + "application/vnd.dece.ttml+xml": { + source: "iana", + compressible: true, + extensions: ["uvt", "uvvt"] + }, + "application/vnd.dece.unspecified": { + source: "iana", + extensions: ["uvx", "uvvx"] + }, + "application/vnd.dece.zip": { + source: "iana", + extensions: ["uvz", "uvvz"] + }, + "application/vnd.denovo.fcselayout-link": { + source: "iana", + extensions: ["fe_launch"] + }, + "application/vnd.desmume.movie": { + source: "iana" + }, + "application/vnd.dir-bi.plate-dl-nosuffix": { + source: "iana" + }, + "application/vnd.dm.delegation+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dna": { + source: "iana", + extensions: ["dna"] + }, + "application/vnd.document+json": { + source: "iana", + compressible: true + }, + "application/vnd.dolby.mlp": { + source: "apache", + extensions: ["mlp"] + }, + "application/vnd.dolby.mobile.1": { + source: "iana" + }, + "application/vnd.dolby.mobile.2": { + source: "iana" + }, + "application/vnd.doremir.scorecloud-binary-document": { + source: "iana" + }, + "application/vnd.dpgraph": { + source: "iana", + extensions: ["dpg"] + }, + "application/vnd.dreamfactory": { + source: "iana", + extensions: ["dfac"] + }, + "application/vnd.drive+json": { + source: "iana", + compressible: true + }, + "application/vnd.ds-keypoint": { + source: "apache", + extensions: ["kpxx"] + }, + "application/vnd.dtg.local": { + source: "iana" + }, + "application/vnd.dtg.local.flash": { + source: "iana" + }, + "application/vnd.dtg.local.html": { + source: "iana" + }, + "application/vnd.dvb.ait": { + source: "iana", + extensions: ["ait"] + }, + "application/vnd.dvb.dvbisl+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dvb.dvbj": { + source: "iana" + }, + "application/vnd.dvb.esgcontainer": { + source: "iana" + }, + "application/vnd.dvb.ipdcdftnotifaccess": { + source: "iana" + }, + "application/vnd.dvb.ipdcesgaccess": { + source: "iana" + }, + "application/vnd.dvb.ipdcesgaccess2": { + source: "iana" + }, + "application/vnd.dvb.ipdcesgpdd": { + source: "iana" + }, + "application/vnd.dvb.ipdcroaming": { + source: "iana" + }, + "application/vnd.dvb.iptv.alfec-base": { + source: "iana" + }, + "application/vnd.dvb.iptv.alfec-enhancement": { + source: "iana" + }, + "application/vnd.dvb.notif-aggregate-root+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dvb.notif-container+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dvb.notif-generic+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dvb.notif-ia-msglist+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dvb.notif-ia-registration-request+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dvb.notif-ia-registration-response+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dvb.notif-init+xml": { + source: "iana", + compressible: true + }, + "application/vnd.dvb.pfr": { + source: "iana" + }, + "application/vnd.dvb.service": { + source: "iana", + extensions: ["svc"] + }, + "application/vnd.dxr": { + source: "iana" + }, + "application/vnd.dynageo": { + source: "iana", + extensions: ["geo"] + }, + "application/vnd.dzr": { + source: "iana" + }, + "application/vnd.easykaraoke.cdgdownload": { + source: "iana" + }, + "application/vnd.ecdis-update": { + source: "iana" + }, + "application/vnd.ecip.rlp": { + source: "iana" + }, + "application/vnd.eclipse.ditto+json": { + source: "iana", + compressible: true + }, + "application/vnd.ecowin.chart": { + source: "iana", + extensions: ["mag"] + }, + "application/vnd.ecowin.filerequest": { + source: "iana" + }, + "application/vnd.ecowin.fileupdate": { + source: "iana" + }, + "application/vnd.ecowin.series": { + source: "iana" + }, + "application/vnd.ecowin.seriesrequest": { + source: "iana" + }, + "application/vnd.ecowin.seriesupdate": { + source: "iana" + }, + "application/vnd.efi.img": { + source: "iana" + }, + "application/vnd.efi.iso": { + source: "iana" + }, + "application/vnd.emclient.accessrequest+xml": { + source: "iana", + compressible: true + }, + "application/vnd.enliven": { + source: "iana", + extensions: ["nml"] + }, + "application/vnd.enphase.envoy": { + source: "iana" + }, + "application/vnd.eprints.data+xml": { + source: "iana", + compressible: true + }, + "application/vnd.epson.esf": { + source: "iana", + extensions: ["esf"] + }, + "application/vnd.epson.msf": { + source: "iana", + extensions: ["msf"] + }, + "application/vnd.epson.quickanime": { + source: "iana", + extensions: ["qam"] + }, + "application/vnd.epson.salt": { + source: "iana", + extensions: ["slt"] + }, + "application/vnd.epson.ssf": { + source: "iana", + extensions: ["ssf"] + }, + "application/vnd.ericsson.quickcall": { + source: "iana" + }, + "application/vnd.espass-espass+zip": { + source: "iana", + compressible: false + }, + "application/vnd.eszigno3+xml": { + source: "iana", + compressible: true, + extensions: ["es3", "et3"] + }, + "application/vnd.etsi.aoc+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.asic-e+zip": { + source: "iana", + compressible: false + }, + "application/vnd.etsi.asic-s+zip": { + source: "iana", + compressible: false + }, + "application/vnd.etsi.cug+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvcommand+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvdiscovery+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvprofile+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvsad-bc+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvsad-cod+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvsad-npvr+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvservice+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvsync+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.iptvueprofile+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.mcid+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.mheg5": { + source: "iana" + }, + "application/vnd.etsi.overload-control-policy-dataset+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.pstn+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.sci+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.simservs+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.timestamp-token": { + source: "iana" + }, + "application/vnd.etsi.tsl+xml": { + source: "iana", + compressible: true + }, + "application/vnd.etsi.tsl.der": { + source: "iana" + }, + "application/vnd.eu.kasparian.car+json": { + source: "iana", + compressible: true + }, + "application/vnd.eudora.data": { + source: "iana" + }, + "application/vnd.evolv.ecig.profile": { + source: "iana" + }, + "application/vnd.evolv.ecig.settings": { + source: "iana" + }, + "application/vnd.evolv.ecig.theme": { + source: "iana" + }, + "application/vnd.exstream-empower+zip": { + source: "iana", + compressible: false + }, + "application/vnd.exstream-package": { + source: "iana" + }, + "application/vnd.ezpix-album": { + source: "iana", + extensions: ["ez2"] + }, + "application/vnd.ezpix-package": { + source: "iana", + extensions: ["ez3"] + }, + "application/vnd.f-secure.mobile": { + source: "iana" + }, + "application/vnd.familysearch.gedcom+zip": { + source: "iana", + compressible: false + }, + "application/vnd.fastcopy-disk-image": { + source: "iana" + }, + "application/vnd.fdf": { + source: "iana", + extensions: ["fdf"] + }, + "application/vnd.fdsn.mseed": { + source: "iana", + extensions: ["mseed"] + }, + "application/vnd.fdsn.seed": { + source: "iana", + extensions: ["seed", "dataless"] + }, + "application/vnd.ffsns": { + source: "iana" + }, + "application/vnd.ficlab.flb+zip": { + source: "iana", + compressible: false + }, + "application/vnd.filmit.zfc": { + source: "iana" + }, + "application/vnd.fints": { + source: "iana" + }, + "application/vnd.firemonkeys.cloudcell": { + source: "iana" + }, + "application/vnd.flographit": { + source: "iana", + extensions: ["gph"] + }, + "application/vnd.fluxtime.clip": { + source: "iana", + extensions: ["ftc"] + }, + "application/vnd.font-fontforge-sfd": { + source: "iana" + }, + "application/vnd.framemaker": { + source: "iana", + extensions: ["fm", "frame", "maker", "book"] + }, + "application/vnd.frogans.fnc": { + source: "iana", + extensions: ["fnc"] + }, + "application/vnd.frogans.ltf": { + source: "iana", + extensions: ["ltf"] + }, + "application/vnd.fsc.weblaunch": { + source: "iana", + extensions: ["fsc"] + }, + "application/vnd.fujifilm.fb.docuworks": { + source: "iana" + }, + "application/vnd.fujifilm.fb.docuworks.binder": { + source: "iana" + }, + "application/vnd.fujifilm.fb.docuworks.container": { + source: "iana" + }, + "application/vnd.fujifilm.fb.jfi+xml": { + source: "iana", + compressible: true + }, + "application/vnd.fujitsu.oasys": { + source: "iana", + extensions: ["oas"] + }, + "application/vnd.fujitsu.oasys2": { + source: "iana", + extensions: ["oa2"] + }, + "application/vnd.fujitsu.oasys3": { + source: "iana", + extensions: ["oa3"] + }, + "application/vnd.fujitsu.oasysgp": { + source: "iana", + extensions: ["fg5"] + }, + "application/vnd.fujitsu.oasysprs": { + source: "iana", + extensions: ["bh2"] + }, + "application/vnd.fujixerox.art-ex": { + source: "iana" + }, + "application/vnd.fujixerox.art4": { + source: "iana" + }, + "application/vnd.fujixerox.ddd": { + source: "iana", + extensions: ["ddd"] + }, + "application/vnd.fujixerox.docuworks": { + source: "iana", + extensions: ["xdw"] + }, + "application/vnd.fujixerox.docuworks.binder": { + source: "iana", + extensions: ["xbd"] + }, + "application/vnd.fujixerox.docuworks.container": { + source: "iana" + }, + "application/vnd.fujixerox.hbpl": { + source: "iana" + }, + "application/vnd.fut-misnet": { + source: "iana" + }, + "application/vnd.futoin+cbor": { + source: "iana" + }, + "application/vnd.futoin+json": { + source: "iana", + compressible: true + }, + "application/vnd.fuzzysheet": { + source: "iana", + extensions: ["fzs"] + }, + "application/vnd.genomatix.tuxedo": { + source: "iana", + extensions: ["txd"] + }, + "application/vnd.gentics.grd+json": { + source: "iana", + compressible: true + }, + "application/vnd.geo+json": { + source: "iana", + compressible: true + }, + "application/vnd.geocube+xml": { + source: "iana", + compressible: true + }, + "application/vnd.geogebra.file": { + source: "iana", + extensions: ["ggb"] + }, + "application/vnd.geogebra.slides": { + source: "iana" + }, + "application/vnd.geogebra.tool": { + source: "iana", + extensions: ["ggt"] + }, + "application/vnd.geometry-explorer": { + source: "iana", + extensions: ["gex", "gre"] + }, + "application/vnd.geonext": { + source: "iana", + extensions: ["gxt"] + }, + "application/vnd.geoplan": { + source: "iana", + extensions: ["g2w"] + }, + "application/vnd.geospace": { + source: "iana", + extensions: ["g3w"] + }, + "application/vnd.gerber": { + source: "iana" + }, + "application/vnd.globalplatform.card-content-mgt": { + source: "iana" + }, + "application/vnd.globalplatform.card-content-mgt-response": { + source: "iana" + }, + "application/vnd.gmx": { + source: "iana", + extensions: ["gmx"] + }, + "application/vnd.google-apps.document": { + compressible: false, + extensions: ["gdoc"] + }, + "application/vnd.google-apps.presentation": { + compressible: false, + extensions: ["gslides"] + }, + "application/vnd.google-apps.spreadsheet": { + compressible: false, + extensions: ["gsheet"] + }, + "application/vnd.google-earth.kml+xml": { + source: "iana", + compressible: true, + extensions: ["kml"] + }, + "application/vnd.google-earth.kmz": { + source: "iana", + compressible: false, + extensions: ["kmz"] + }, + "application/vnd.gov.sk.e-form+xml": { + source: "iana", + compressible: true + }, + "application/vnd.gov.sk.e-form+zip": { + source: "iana", + compressible: false + }, + "application/vnd.gov.sk.xmldatacontainer+xml": { + source: "iana", + compressible: true + }, + "application/vnd.grafeq": { + source: "iana", + extensions: ["gqf", "gqs"] + }, + "application/vnd.gridmp": { + source: "iana" + }, + "application/vnd.groove-account": { + source: "iana", + extensions: ["gac"] + }, + "application/vnd.groove-help": { + source: "iana", + extensions: ["ghf"] + }, + "application/vnd.groove-identity-message": { + source: "iana", + extensions: ["gim"] + }, + "application/vnd.groove-injector": { + source: "iana", + extensions: ["grv"] + }, + "application/vnd.groove-tool-message": { + source: "iana", + extensions: ["gtm"] + }, + "application/vnd.groove-tool-template": { + source: "iana", + extensions: ["tpl"] + }, + "application/vnd.groove-vcard": { + source: "iana", + extensions: ["vcg"] + }, + "application/vnd.hal+json": { + source: "iana", + compressible: true + }, + "application/vnd.hal+xml": { + source: "iana", + compressible: true, + extensions: ["hal"] + }, + "application/vnd.handheld-entertainment+xml": { + source: "iana", + compressible: true, + extensions: ["zmm"] + }, + "application/vnd.hbci": { + source: "iana", + extensions: ["hbci"] + }, + "application/vnd.hc+json": { + source: "iana", + compressible: true + }, + "application/vnd.hcl-bireports": { + source: "iana" + }, + "application/vnd.hdt": { + source: "iana" + }, + "application/vnd.heroku+json": { + source: "iana", + compressible: true + }, + "application/vnd.hhe.lesson-player": { + source: "iana", + extensions: ["les"] + }, + "application/vnd.hl7cda+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/vnd.hl7v2+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/vnd.hp-hpgl": { + source: "iana", + extensions: ["hpgl"] + }, + "application/vnd.hp-hpid": { + source: "iana", + extensions: ["hpid"] + }, + "application/vnd.hp-hps": { + source: "iana", + extensions: ["hps"] + }, + "application/vnd.hp-jlyt": { + source: "iana", + extensions: ["jlt"] + }, + "application/vnd.hp-pcl": { + source: "iana", + extensions: ["pcl"] + }, + "application/vnd.hp-pclxl": { + source: "iana", + extensions: ["pclxl"] + }, + "application/vnd.httphone": { + source: "iana" + }, + "application/vnd.hydrostatix.sof-data": { + source: "iana", + extensions: ["sfd-hdstx"] + }, + "application/vnd.hyper+json": { + source: "iana", + compressible: true + }, + "application/vnd.hyper-item+json": { + source: "iana", + compressible: true + }, + "application/vnd.hyperdrive+json": { + source: "iana", + compressible: true + }, + "application/vnd.hzn-3d-crossword": { + source: "iana" + }, + "application/vnd.ibm.afplinedata": { + source: "iana" + }, + "application/vnd.ibm.electronic-media": { + source: "iana" + }, + "application/vnd.ibm.minipay": { + source: "iana", + extensions: ["mpy"] + }, + "application/vnd.ibm.modcap": { + source: "iana", + extensions: ["afp", "listafp", "list3820"] + }, + "application/vnd.ibm.rights-management": { + source: "iana", + extensions: ["irm"] + }, + "application/vnd.ibm.secure-container": { + source: "iana", + extensions: ["sc"] + }, + "application/vnd.iccprofile": { + source: "iana", + extensions: ["icc", "icm"] + }, + "application/vnd.ieee.1905": { + source: "iana" + }, + "application/vnd.igloader": { + source: "iana", + extensions: ["igl"] + }, + "application/vnd.imagemeter.folder+zip": { + source: "iana", + compressible: false + }, + "application/vnd.imagemeter.image+zip": { + source: "iana", + compressible: false + }, + "application/vnd.immervision-ivp": { + source: "iana", + extensions: ["ivp"] + }, + "application/vnd.immervision-ivu": { + source: "iana", + extensions: ["ivu"] + }, + "application/vnd.ims.imsccv1p1": { + source: "iana" + }, + "application/vnd.ims.imsccv1p2": { + source: "iana" + }, + "application/vnd.ims.imsccv1p3": { + source: "iana" + }, + "application/vnd.ims.lis.v2.result+json": { + source: "iana", + compressible: true + }, + "application/vnd.ims.lti.v2.toolconsumerprofile+json": { + source: "iana", + compressible: true + }, + "application/vnd.ims.lti.v2.toolproxy+json": { + source: "iana", + compressible: true + }, + "application/vnd.ims.lti.v2.toolproxy.id+json": { + source: "iana", + compressible: true + }, + "application/vnd.ims.lti.v2.toolsettings+json": { + source: "iana", + compressible: true + }, + "application/vnd.ims.lti.v2.toolsettings.simple+json": { + source: "iana", + compressible: true + }, + "application/vnd.informedcontrol.rms+xml": { + source: "iana", + compressible: true + }, + "application/vnd.informix-visionary": { + source: "iana" + }, + "application/vnd.infotech.project": { + source: "iana" + }, + "application/vnd.infotech.project+xml": { + source: "iana", + compressible: true + }, + "application/vnd.innopath.wamp.notification": { + source: "iana" + }, + "application/vnd.insors.igm": { + source: "iana", + extensions: ["igm"] + }, + "application/vnd.intercon.formnet": { + source: "iana", + extensions: ["xpw", "xpx"] + }, + "application/vnd.intergeo": { + source: "iana", + extensions: ["i2g"] + }, + "application/vnd.intertrust.digibox": { + source: "iana" + }, + "application/vnd.intertrust.nncp": { + source: "iana" + }, + "application/vnd.intu.qbo": { + source: "iana", + extensions: ["qbo"] + }, + "application/vnd.intu.qfx": { + source: "iana", + extensions: ["qfx"] + }, + "application/vnd.iptc.g2.catalogitem+xml": { + source: "iana", + compressible: true + }, + "application/vnd.iptc.g2.conceptitem+xml": { + source: "iana", + compressible: true + }, + "application/vnd.iptc.g2.knowledgeitem+xml": { + source: "iana", + compressible: true + }, + "application/vnd.iptc.g2.newsitem+xml": { + source: "iana", + compressible: true + }, + "application/vnd.iptc.g2.newsmessage+xml": { + source: "iana", + compressible: true + }, + "application/vnd.iptc.g2.packageitem+xml": { + source: "iana", + compressible: true + }, + "application/vnd.iptc.g2.planningitem+xml": { + source: "iana", + compressible: true + }, + "application/vnd.ipunplugged.rcprofile": { + source: "iana", + extensions: ["rcprofile"] + }, + "application/vnd.irepository.package+xml": { + source: "iana", + compressible: true, + extensions: ["irp"] + }, + "application/vnd.is-xpr": { + source: "iana", + extensions: ["xpr"] + }, + "application/vnd.isac.fcs": { + source: "iana", + extensions: ["fcs"] + }, + "application/vnd.iso11783-10+zip": { + source: "iana", + compressible: false + }, + "application/vnd.jam": { + source: "iana", + extensions: ["jam"] + }, + "application/vnd.japannet-directory-service": { + source: "iana" + }, + "application/vnd.japannet-jpnstore-wakeup": { + source: "iana" + }, + "application/vnd.japannet-payment-wakeup": { + source: "iana" + }, + "application/vnd.japannet-registration": { + source: "iana" + }, + "application/vnd.japannet-registration-wakeup": { + source: "iana" + }, + "application/vnd.japannet-setstore-wakeup": { + source: "iana" + }, + "application/vnd.japannet-verification": { + source: "iana" + }, + "application/vnd.japannet-verification-wakeup": { + source: "iana" + }, + "application/vnd.jcp.javame.midlet-rms": { + source: "iana", + extensions: ["rms"] + }, + "application/vnd.jisp": { + source: "iana", + extensions: ["jisp"] + }, + "application/vnd.joost.joda-archive": { + source: "iana", + extensions: ["joda"] + }, + "application/vnd.jsk.isdn-ngn": { + source: "iana" + }, + "application/vnd.kahootz": { + source: "iana", + extensions: ["ktz", "ktr"] + }, + "application/vnd.kde.karbon": { + source: "iana", + extensions: ["karbon"] + }, + "application/vnd.kde.kchart": { + source: "iana", + extensions: ["chrt"] + }, + "application/vnd.kde.kformula": { + source: "iana", + extensions: ["kfo"] + }, + "application/vnd.kde.kivio": { + source: "iana", + extensions: ["flw"] + }, + "application/vnd.kde.kontour": { + source: "iana", + extensions: ["kon"] + }, + "application/vnd.kde.kpresenter": { + source: "iana", + extensions: ["kpr", "kpt"] + }, + "application/vnd.kde.kspread": { + source: "iana", + extensions: ["ksp"] + }, + "application/vnd.kde.kword": { + source: "iana", + extensions: ["kwd", "kwt"] + }, + "application/vnd.kenameaapp": { + source: "iana", + extensions: ["htke"] + }, + "application/vnd.kidspiration": { + source: "iana", + extensions: ["kia"] + }, + "application/vnd.kinar": { + source: "iana", + extensions: ["kne", "knp"] + }, + "application/vnd.koan": { + source: "iana", + extensions: ["skp", "skd", "skt", "skm"] + }, + "application/vnd.kodak-descriptor": { + source: "iana", + extensions: ["sse"] + }, + "application/vnd.las": { + source: "iana" + }, + "application/vnd.las.las+json": { + source: "iana", + compressible: true + }, + "application/vnd.las.las+xml": { + source: "iana", + compressible: true, + extensions: ["lasxml"] + }, + "application/vnd.laszip": { + source: "iana" + }, + "application/vnd.leap+json": { + source: "iana", + compressible: true + }, + "application/vnd.liberty-request+xml": { + source: "iana", + compressible: true + }, + "application/vnd.llamagraphics.life-balance.desktop": { + source: "iana", + extensions: ["lbd"] + }, + "application/vnd.llamagraphics.life-balance.exchange+xml": { + source: "iana", + compressible: true, + extensions: ["lbe"] + }, + "application/vnd.logipipe.circuit+zip": { + source: "iana", + compressible: false + }, + "application/vnd.loom": { + source: "iana" + }, + "application/vnd.lotus-1-2-3": { + source: "iana", + extensions: ["123"] + }, + "application/vnd.lotus-approach": { + source: "iana", + extensions: ["apr"] + }, + "application/vnd.lotus-freelance": { + source: "iana", + extensions: ["pre"] + }, + "application/vnd.lotus-notes": { + source: "iana", + extensions: ["nsf"] + }, + "application/vnd.lotus-organizer": { + source: "iana", + extensions: ["org"] + }, + "application/vnd.lotus-screencam": { + source: "iana", + extensions: ["scm"] + }, + "application/vnd.lotus-wordpro": { + source: "iana", + extensions: ["lwp"] + }, + "application/vnd.macports.portpkg": { + source: "iana", + extensions: ["portpkg"] + }, + "application/vnd.mapbox-vector-tile": { + source: "iana", + extensions: ["mvt"] + }, + "application/vnd.marlin.drm.actiontoken+xml": { + source: "iana", + compressible: true + }, + "application/vnd.marlin.drm.conftoken+xml": { + source: "iana", + compressible: true + }, + "application/vnd.marlin.drm.license+xml": { + source: "iana", + compressible: true + }, + "application/vnd.marlin.drm.mdcf": { + source: "iana" + }, + "application/vnd.mason+json": { + source: "iana", + compressible: true + }, + "application/vnd.maxar.archive.3tz+zip": { + source: "iana", + compressible: false + }, + "application/vnd.maxmind.maxmind-db": { + source: "iana" + }, + "application/vnd.mcd": { + source: "iana", + extensions: ["mcd"] + }, + "application/vnd.medcalcdata": { + source: "iana", + extensions: ["mc1"] + }, + "application/vnd.mediastation.cdkey": { + source: "iana", + extensions: ["cdkey"] + }, + "application/vnd.meridian-slingshot": { + source: "iana" + }, + "application/vnd.mfer": { + source: "iana", + extensions: ["mwf"] + }, + "application/vnd.mfmp": { + source: "iana", + extensions: ["mfm"] + }, + "application/vnd.micro+json": { + source: "iana", + compressible: true + }, + "application/vnd.micrografx.flo": { + source: "iana", + extensions: ["flo"] + }, + "application/vnd.micrografx.igx": { + source: "iana", + extensions: ["igx"] + }, + "application/vnd.microsoft.portable-executable": { + source: "iana" + }, + "application/vnd.microsoft.windows.thumbnail-cache": { + source: "iana" + }, + "application/vnd.miele+json": { + source: "iana", + compressible: true + }, + "application/vnd.mif": { + source: "iana", + extensions: ["mif"] + }, + "application/vnd.minisoft-hp3000-save": { + source: "iana" + }, + "application/vnd.mitsubishi.misty-guard.trustweb": { + source: "iana" + }, + "application/vnd.mobius.daf": { + source: "iana", + extensions: ["daf"] + }, + "application/vnd.mobius.dis": { + source: "iana", + extensions: ["dis"] + }, + "application/vnd.mobius.mbk": { + source: "iana", + extensions: ["mbk"] + }, + "application/vnd.mobius.mqy": { + source: "iana", + extensions: ["mqy"] + }, + "application/vnd.mobius.msl": { + source: "iana", + extensions: ["msl"] + }, + "application/vnd.mobius.plc": { + source: "iana", + extensions: ["plc"] + }, + "application/vnd.mobius.txf": { + source: "iana", + extensions: ["txf"] + }, + "application/vnd.mophun.application": { + source: "iana", + extensions: ["mpn"] + }, + "application/vnd.mophun.certificate": { + source: "iana", + extensions: ["mpc"] + }, + "application/vnd.motorola.flexsuite": { + source: "iana" + }, + "application/vnd.motorola.flexsuite.adsi": { + source: "iana" + }, + "application/vnd.motorola.flexsuite.fis": { + source: "iana" + }, + "application/vnd.motorola.flexsuite.gotap": { + source: "iana" + }, + "application/vnd.motorola.flexsuite.kmr": { + source: "iana" + }, + "application/vnd.motorola.flexsuite.ttc": { + source: "iana" + }, + "application/vnd.motorola.flexsuite.wem": { + source: "iana" + }, + "application/vnd.motorola.iprm": { + source: "iana" + }, + "application/vnd.mozilla.xul+xml": { + source: "iana", + compressible: true, + extensions: ["xul"] + }, + "application/vnd.ms-3mfdocument": { + source: "iana" + }, + "application/vnd.ms-artgalry": { + source: "iana", + extensions: ["cil"] + }, + "application/vnd.ms-asf": { + source: "iana" + }, + "application/vnd.ms-cab-compressed": { + source: "iana", + extensions: ["cab"] + }, + "application/vnd.ms-color.iccprofile": { + source: "apache" + }, + "application/vnd.ms-excel": { + source: "iana", + compressible: false, + extensions: ["xls", "xlm", "xla", "xlc", "xlt", "xlw"] + }, + "application/vnd.ms-excel.addin.macroenabled.12": { + source: "iana", + extensions: ["xlam"] + }, + "application/vnd.ms-excel.sheet.binary.macroenabled.12": { + source: "iana", + extensions: ["xlsb"] + }, + "application/vnd.ms-excel.sheet.macroenabled.12": { + source: "iana", + extensions: ["xlsm"] + }, + "application/vnd.ms-excel.template.macroenabled.12": { + source: "iana", + extensions: ["xltm"] + }, + "application/vnd.ms-fontobject": { + source: "iana", + compressible: true, + extensions: ["eot"] + }, + "application/vnd.ms-htmlhelp": { + source: "iana", + extensions: ["chm"] + }, + "application/vnd.ms-ims": { + source: "iana", + extensions: ["ims"] + }, + "application/vnd.ms-lrm": { + source: "iana", + extensions: ["lrm"] + }, + "application/vnd.ms-office.activex+xml": { + source: "iana", + compressible: true + }, + "application/vnd.ms-officetheme": { + source: "iana", + extensions: ["thmx"] + }, + "application/vnd.ms-opentype": { + source: "apache", + compressible: true + }, + "application/vnd.ms-outlook": { + compressible: false, + extensions: ["msg"] + }, + "application/vnd.ms-package.obfuscated-opentype": { + source: "apache" + }, + "application/vnd.ms-pki.seccat": { + source: "apache", + extensions: ["cat"] + }, + "application/vnd.ms-pki.stl": { + source: "apache", + extensions: ["stl"] + }, + "application/vnd.ms-playready.initiator+xml": { + source: "iana", + compressible: true + }, + "application/vnd.ms-powerpoint": { + source: "iana", + compressible: false, + extensions: ["ppt", "pps", "pot"] + }, + "application/vnd.ms-powerpoint.addin.macroenabled.12": { + source: "iana", + extensions: ["ppam"] + }, + "application/vnd.ms-powerpoint.presentation.macroenabled.12": { + source: "iana", + extensions: ["pptm"] + }, + "application/vnd.ms-powerpoint.slide.macroenabled.12": { + source: "iana", + extensions: ["sldm"] + }, + "application/vnd.ms-powerpoint.slideshow.macroenabled.12": { + source: "iana", + extensions: ["ppsm"] + }, + "application/vnd.ms-powerpoint.template.macroenabled.12": { + source: "iana", + extensions: ["potm"] + }, + "application/vnd.ms-printdevicecapabilities+xml": { + source: "iana", + compressible: true + }, + "application/vnd.ms-printing.printticket+xml": { + source: "apache", + compressible: true + }, + "application/vnd.ms-printschematicket+xml": { + source: "iana", + compressible: true + }, + "application/vnd.ms-project": { + source: "iana", + extensions: ["mpp", "mpt"] + }, + "application/vnd.ms-tnef": { + source: "iana" + }, + "application/vnd.ms-windows.devicepairing": { + source: "iana" + }, + "application/vnd.ms-windows.nwprinting.oob": { + source: "iana" + }, + "application/vnd.ms-windows.printerpairing": { + source: "iana" + }, + "application/vnd.ms-windows.wsd.oob": { + source: "iana" + }, + "application/vnd.ms-wmdrm.lic-chlg-req": { + source: "iana" + }, + "application/vnd.ms-wmdrm.lic-resp": { + source: "iana" + }, + "application/vnd.ms-wmdrm.meter-chlg-req": { + source: "iana" + }, + "application/vnd.ms-wmdrm.meter-resp": { + source: "iana" + }, + "application/vnd.ms-word.document.macroenabled.12": { + source: "iana", + extensions: ["docm"] + }, + "application/vnd.ms-word.template.macroenabled.12": { + source: "iana", + extensions: ["dotm"] + }, + "application/vnd.ms-works": { + source: "iana", + extensions: ["wps", "wks", "wcm", "wdb"] + }, + "application/vnd.ms-wpl": { + source: "iana", + extensions: ["wpl"] + }, + "application/vnd.ms-xpsdocument": { + source: "iana", + compressible: false, + extensions: ["xps"] + }, + "application/vnd.msa-disk-image": { + source: "iana" + }, + "application/vnd.mseq": { + source: "iana", + extensions: ["mseq"] + }, + "application/vnd.msign": { + source: "iana" + }, + "application/vnd.multiad.creator": { + source: "iana" + }, + "application/vnd.multiad.creator.cif": { + source: "iana" + }, + "application/vnd.music-niff": { + source: "iana" + }, + "application/vnd.musician": { + source: "iana", + extensions: ["mus"] + }, + "application/vnd.muvee.style": { + source: "iana", + extensions: ["msty"] + }, + "application/vnd.mynfc": { + source: "iana", + extensions: ["taglet"] + }, + "application/vnd.nacamar.ybrid+json": { + source: "iana", + compressible: true + }, + "application/vnd.ncd.control": { + source: "iana" + }, + "application/vnd.ncd.reference": { + source: "iana" + }, + "application/vnd.nearst.inv+json": { + source: "iana", + compressible: true + }, + "application/vnd.nebumind.line": { + source: "iana" + }, + "application/vnd.nervana": { + source: "iana" + }, + "application/vnd.netfpx": { + source: "iana" + }, + "application/vnd.neurolanguage.nlu": { + source: "iana", + extensions: ["nlu"] + }, + "application/vnd.nimn": { + source: "iana" + }, + "application/vnd.nintendo.nitro.rom": { + source: "iana" + }, + "application/vnd.nintendo.snes.rom": { + source: "iana" + }, + "application/vnd.nitf": { + source: "iana", + extensions: ["ntf", "nitf"] + }, + "application/vnd.noblenet-directory": { + source: "iana", + extensions: ["nnd"] + }, + "application/vnd.noblenet-sealer": { + source: "iana", + extensions: ["nns"] + }, + "application/vnd.noblenet-web": { + source: "iana", + extensions: ["nnw"] + }, + "application/vnd.nokia.catalogs": { + source: "iana" + }, + "application/vnd.nokia.conml+wbxml": { + source: "iana" + }, + "application/vnd.nokia.conml+xml": { + source: "iana", + compressible: true + }, + "application/vnd.nokia.iptv.config+xml": { + source: "iana", + compressible: true + }, + "application/vnd.nokia.isds-radio-presets": { + source: "iana" + }, + "application/vnd.nokia.landmark+wbxml": { + source: "iana" + }, + "application/vnd.nokia.landmark+xml": { + source: "iana", + compressible: true + }, + "application/vnd.nokia.landmarkcollection+xml": { + source: "iana", + compressible: true + }, + "application/vnd.nokia.n-gage.ac+xml": { + source: "iana", + compressible: true, + extensions: ["ac"] + }, + "application/vnd.nokia.n-gage.data": { + source: "iana", + extensions: ["ngdat"] + }, + "application/vnd.nokia.n-gage.symbian.install": { + source: "iana", + extensions: ["n-gage"] + }, + "application/vnd.nokia.ncd": { + source: "iana" + }, + "application/vnd.nokia.pcd+wbxml": { + source: "iana" + }, + "application/vnd.nokia.pcd+xml": { + source: "iana", + compressible: true + }, + "application/vnd.nokia.radio-preset": { + source: "iana", + extensions: ["rpst"] + }, + "application/vnd.nokia.radio-presets": { + source: "iana", + extensions: ["rpss"] + }, + "application/vnd.novadigm.edm": { + source: "iana", + extensions: ["edm"] + }, + "application/vnd.novadigm.edx": { + source: "iana", + extensions: ["edx"] + }, + "application/vnd.novadigm.ext": { + source: "iana", + extensions: ["ext"] + }, + "application/vnd.ntt-local.content-share": { + source: "iana" + }, + "application/vnd.ntt-local.file-transfer": { + source: "iana" + }, + "application/vnd.ntt-local.ogw_remote-access": { + source: "iana" + }, + "application/vnd.ntt-local.sip-ta_remote": { + source: "iana" + }, + "application/vnd.ntt-local.sip-ta_tcp_stream": { + source: "iana" + }, + "application/vnd.oasis.opendocument.chart": { + source: "iana", + extensions: ["odc"] + }, + "application/vnd.oasis.opendocument.chart-template": { + source: "iana", + extensions: ["otc"] + }, + "application/vnd.oasis.opendocument.database": { + source: "iana", + extensions: ["odb"] + }, + "application/vnd.oasis.opendocument.formula": { + source: "iana", + extensions: ["odf"] + }, + "application/vnd.oasis.opendocument.formula-template": { + source: "iana", + extensions: ["odft"] + }, + "application/vnd.oasis.opendocument.graphics": { + source: "iana", + compressible: false, + extensions: ["odg"] + }, + "application/vnd.oasis.opendocument.graphics-template": { + source: "iana", + extensions: ["otg"] + }, + "application/vnd.oasis.opendocument.image": { + source: "iana", + extensions: ["odi"] + }, + "application/vnd.oasis.opendocument.image-template": { + source: "iana", + extensions: ["oti"] + }, + "application/vnd.oasis.opendocument.presentation": { + source: "iana", + compressible: false, + extensions: ["odp"] + }, + "application/vnd.oasis.opendocument.presentation-template": { + source: "iana", + extensions: ["otp"] + }, + "application/vnd.oasis.opendocument.spreadsheet": { + source: "iana", + compressible: false, + extensions: ["ods"] + }, + "application/vnd.oasis.opendocument.spreadsheet-template": { + source: "iana", + extensions: ["ots"] + }, + "application/vnd.oasis.opendocument.text": { + source: "iana", + compressible: false, + extensions: ["odt"] + }, + "application/vnd.oasis.opendocument.text-master": { + source: "iana", + extensions: ["odm"] + }, + "application/vnd.oasis.opendocument.text-template": { + source: "iana", + extensions: ["ott"] + }, + "application/vnd.oasis.opendocument.text-web": { + source: "iana", + extensions: ["oth"] + }, + "application/vnd.obn": { + source: "iana" + }, + "application/vnd.ocf+cbor": { + source: "iana" + }, + "application/vnd.oci.image.manifest.v1+json": { + source: "iana", + compressible: true + }, + "application/vnd.oftn.l10n+json": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.contentaccessdownload+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.contentaccessstreaming+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.cspg-hexbinary": { + source: "iana" + }, + "application/vnd.oipf.dae.svg+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.dae.xhtml+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.mippvcontrolmessage+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.pae.gem": { + source: "iana" + }, + "application/vnd.oipf.spdiscovery+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.spdlist+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.ueprofile+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oipf.userprofile+xml": { + source: "iana", + compressible: true + }, + "application/vnd.olpc-sugar": { + source: "iana", + extensions: ["xo"] + }, + "application/vnd.oma-scws-config": { + source: "iana" + }, + "application/vnd.oma-scws-http-request": { + source: "iana" + }, + "application/vnd.oma-scws-http-response": { + source: "iana" + }, + "application/vnd.oma.bcast.associated-procedure-parameter+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.bcast.drm-trigger+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.bcast.imd+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.bcast.ltkm": { + source: "iana" + }, + "application/vnd.oma.bcast.notification+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.bcast.provisioningtrigger": { + source: "iana" + }, + "application/vnd.oma.bcast.sgboot": { + source: "iana" + }, + "application/vnd.oma.bcast.sgdd+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.bcast.sgdu": { + source: "iana" + }, + "application/vnd.oma.bcast.simple-symbol-container": { + source: "iana" + }, + "application/vnd.oma.bcast.smartcard-trigger+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.bcast.sprov+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.bcast.stkm": { + source: "iana" + }, + "application/vnd.oma.cab-address-book+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.cab-feature-handler+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.cab-pcc+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.cab-subs-invite+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.cab-user-prefs+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.dcd": { + source: "iana" + }, + "application/vnd.oma.dcdc": { + source: "iana" + }, + "application/vnd.oma.dd2+xml": { + source: "iana", + compressible: true, + extensions: ["dd2"] + }, + "application/vnd.oma.drm.risd+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.group-usage-list+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.lwm2m+cbor": { + source: "iana" + }, + "application/vnd.oma.lwm2m+json": { + source: "iana", + compressible: true + }, + "application/vnd.oma.lwm2m+tlv": { + source: "iana" + }, + "application/vnd.oma.pal+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.poc.detailed-progress-report+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.poc.final-report+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.poc.groups+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.poc.invocation-descriptor+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.poc.optimized-progress-report+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.push": { + source: "iana" + }, + "application/vnd.oma.scidm.messages+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oma.xcap-directory+xml": { + source: "iana", + compressible: true + }, + "application/vnd.omads-email+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/vnd.omads-file+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/vnd.omads-folder+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/vnd.omaloc-supl-init": { + source: "iana" + }, + "application/vnd.onepager": { + source: "iana" + }, + "application/vnd.onepagertamp": { + source: "iana" + }, + "application/vnd.onepagertamx": { + source: "iana" + }, + "application/vnd.onepagertat": { + source: "iana" + }, + "application/vnd.onepagertatp": { + source: "iana" + }, + "application/vnd.onepagertatx": { + source: "iana" + }, + "application/vnd.openblox.game+xml": { + source: "iana", + compressible: true, + extensions: ["obgx"] + }, + "application/vnd.openblox.game-binary": { + source: "iana" + }, + "application/vnd.openeye.oeb": { + source: "iana" + }, + "application/vnd.openofficeorg.extension": { + source: "apache", + extensions: ["oxt"] + }, + "application/vnd.openstreetmap.data+xml": { + source: "iana", + compressible: true, + extensions: ["osm"] + }, + "application/vnd.opentimestamps.ots": { + source: "iana" + }, + "application/vnd.openxmlformats-officedocument.custom-properties+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.customxmlproperties+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.drawing+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.extended-properties+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.comments+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.presentation": { + source: "iana", + compressible: false, + extensions: ["pptx"] + }, + "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.presprops+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slide": { + source: "iana", + extensions: ["sldx"] + }, + "application/vnd.openxmlformats-officedocument.presentationml.slide+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slideshow": { + source: "iana", + extensions: ["ppsx"] + }, + "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.tags+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.template": { + source: "iana", + extensions: ["potx"] + }, + "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": { + source: "iana", + compressible: false, + extensions: ["xlsx"] + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.template": { + source: "iana", + extensions: ["xltx"] + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.theme+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.themeoverride+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.vmldrawing": { + source: "iana" + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.document": { + source: "iana", + compressible: false, + extensions: ["docx"] + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.template": { + source: "iana", + extensions: ["dotx"] + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-package.core-properties+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml": { + source: "iana", + compressible: true + }, + "application/vnd.openxmlformats-package.relationships+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oracle.resource+json": { + source: "iana", + compressible: true + }, + "application/vnd.orange.indata": { + source: "iana" + }, + "application/vnd.osa.netdeploy": { + source: "iana" + }, + "application/vnd.osgeo.mapguide.package": { + source: "iana", + extensions: ["mgp"] + }, + "application/vnd.osgi.bundle": { + source: "iana" + }, + "application/vnd.osgi.dp": { + source: "iana", + extensions: ["dp"] + }, + "application/vnd.osgi.subsystem": { + source: "iana", + extensions: ["esa"] + }, + "application/vnd.otps.ct-kip+xml": { + source: "iana", + compressible: true + }, + "application/vnd.oxli.countgraph": { + source: "iana" + }, + "application/vnd.pagerduty+json": { + source: "iana", + compressible: true + }, + "application/vnd.palm": { + source: "iana", + extensions: ["pdb", "pqa", "oprc"] + }, + "application/vnd.panoply": { + source: "iana" + }, + "application/vnd.paos.xml": { + source: "iana" + }, + "application/vnd.patentdive": { + source: "iana" + }, + "application/vnd.patientecommsdoc": { + source: "iana" + }, + "application/vnd.pawaafile": { + source: "iana", + extensions: ["paw"] + }, + "application/vnd.pcos": { + source: "iana" + }, + "application/vnd.pg.format": { + source: "iana", + extensions: ["str"] + }, + "application/vnd.pg.osasli": { + source: "iana", + extensions: ["ei6"] + }, + "application/vnd.piaccess.application-licence": { + source: "iana" + }, + "application/vnd.picsel": { + source: "iana", + extensions: ["efif"] + }, + "application/vnd.pmi.widget": { + source: "iana", + extensions: ["wg"] + }, + "application/vnd.poc.group-advertisement+xml": { + source: "iana", + compressible: true + }, + "application/vnd.pocketlearn": { + source: "iana", + extensions: ["plf"] + }, + "application/vnd.powerbuilder6": { + source: "iana", + extensions: ["pbd"] + }, + "application/vnd.powerbuilder6-s": { + source: "iana" + }, + "application/vnd.powerbuilder7": { + source: "iana" + }, + "application/vnd.powerbuilder7-s": { + source: "iana" + }, + "application/vnd.powerbuilder75": { + source: "iana" + }, + "application/vnd.powerbuilder75-s": { + source: "iana" + }, + "application/vnd.preminet": { + source: "iana" + }, + "application/vnd.previewsystems.box": { + source: "iana", + extensions: ["box"] + }, + "application/vnd.proteus.magazine": { + source: "iana", + extensions: ["mgz"] + }, + "application/vnd.psfs": { + source: "iana" + }, + "application/vnd.publishare-delta-tree": { + source: "iana", + extensions: ["qps"] + }, + "application/vnd.pvi.ptid1": { + source: "iana", + extensions: ["ptid"] + }, + "application/vnd.pwg-multiplexed": { + source: "iana" + }, + "application/vnd.pwg-xhtml-print+xml": { + source: "iana", + compressible: true + }, + "application/vnd.qualcomm.brew-app-res": { + source: "iana" + }, + "application/vnd.quarantainenet": { + source: "iana" + }, + "application/vnd.quark.quarkxpress": { + source: "iana", + extensions: ["qxd", "qxt", "qwd", "qwt", "qxl", "qxb"] + }, + "application/vnd.quobject-quoxdocument": { + source: "iana" + }, + "application/vnd.radisys.moml+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-audit+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-audit-conf+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-audit-conn+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-audit-dialog+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-audit-stream+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-conf+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-dialog+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-dialog-base+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-dialog-fax-detect+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-dialog-fax-sendrecv+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-dialog-group+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-dialog-speech+xml": { + source: "iana", + compressible: true + }, + "application/vnd.radisys.msml-dialog-transform+xml": { + source: "iana", + compressible: true + }, + "application/vnd.rainstor.data": { + source: "iana" + }, + "application/vnd.rapid": { + source: "iana" + }, + "application/vnd.rar": { + source: "iana", + extensions: ["rar"] + }, + "application/vnd.realvnc.bed": { + source: "iana", + extensions: ["bed"] + }, + "application/vnd.recordare.musicxml": { + source: "iana", + extensions: ["mxl"] + }, + "application/vnd.recordare.musicxml+xml": { + source: "iana", + compressible: true, + extensions: ["musicxml"] + }, + "application/vnd.renlearn.rlprint": { + source: "iana" + }, + "application/vnd.resilient.logic": { + source: "iana" + }, + "application/vnd.restful+json": { + source: "iana", + compressible: true + }, + "application/vnd.rig.cryptonote": { + source: "iana", + extensions: ["cryptonote"] + }, + "application/vnd.rim.cod": { + source: "apache", + extensions: ["cod"] + }, + "application/vnd.rn-realmedia": { + source: "apache", + extensions: ["rm"] + }, + "application/vnd.rn-realmedia-vbr": { + source: "apache", + extensions: ["rmvb"] + }, + "application/vnd.route66.link66+xml": { + source: "iana", + compressible: true, + extensions: ["link66"] + }, + "application/vnd.rs-274x": { + source: "iana" + }, + "application/vnd.ruckus.download": { + source: "iana" + }, + "application/vnd.s3sms": { + source: "iana" + }, + "application/vnd.sailingtracker.track": { + source: "iana", + extensions: ["st"] + }, + "application/vnd.sar": { + source: "iana" + }, + "application/vnd.sbm.cid": { + source: "iana" + }, + "application/vnd.sbm.mid2": { + source: "iana" + }, + "application/vnd.scribus": { + source: "iana" + }, + "application/vnd.sealed.3df": { + source: "iana" + }, + "application/vnd.sealed.csf": { + source: "iana" + }, + "application/vnd.sealed.doc": { + source: "iana" + }, + "application/vnd.sealed.eml": { + source: "iana" + }, + "application/vnd.sealed.mht": { + source: "iana" + }, + "application/vnd.sealed.net": { + source: "iana" + }, + "application/vnd.sealed.ppt": { + source: "iana" + }, + "application/vnd.sealed.tiff": { + source: "iana" + }, + "application/vnd.sealed.xls": { + source: "iana" + }, + "application/vnd.sealedmedia.softseal.html": { + source: "iana" + }, + "application/vnd.sealedmedia.softseal.pdf": { + source: "iana" + }, + "application/vnd.seemail": { + source: "iana", + extensions: ["see"] + }, + "application/vnd.seis+json": { + source: "iana", + compressible: true + }, + "application/vnd.sema": { + source: "iana", + extensions: ["sema"] + }, + "application/vnd.semd": { + source: "iana", + extensions: ["semd"] + }, + "application/vnd.semf": { + source: "iana", + extensions: ["semf"] + }, + "application/vnd.shade-save-file": { + source: "iana" + }, + "application/vnd.shana.informed.formdata": { + source: "iana", + extensions: ["ifm"] + }, + "application/vnd.shana.informed.formtemplate": { + source: "iana", + extensions: ["itp"] + }, + "application/vnd.shana.informed.interchange": { + source: "iana", + extensions: ["iif"] + }, + "application/vnd.shana.informed.package": { + source: "iana", + extensions: ["ipk"] + }, + "application/vnd.shootproof+json": { + source: "iana", + compressible: true + }, + "application/vnd.shopkick+json": { + source: "iana", + compressible: true + }, + "application/vnd.shp": { + source: "iana" + }, + "application/vnd.shx": { + source: "iana" + }, + "application/vnd.sigrok.session": { + source: "iana" + }, + "application/vnd.simtech-mindmapper": { + source: "iana", + extensions: ["twd", "twds"] + }, + "application/vnd.siren+json": { + source: "iana", + compressible: true + }, + "application/vnd.smaf": { + source: "iana", + extensions: ["mmf"] + }, + "application/vnd.smart.notebook": { + source: "iana" + }, + "application/vnd.smart.teacher": { + source: "iana", + extensions: ["teacher"] + }, + "application/vnd.snesdev-page-table": { + source: "iana" + }, + "application/vnd.software602.filler.form+xml": { + source: "iana", + compressible: true, + extensions: ["fo"] + }, + "application/vnd.software602.filler.form-xml-zip": { + source: "iana" + }, + "application/vnd.solent.sdkm+xml": { + source: "iana", + compressible: true, + extensions: ["sdkm", "sdkd"] + }, + "application/vnd.spotfire.dxp": { + source: "iana", + extensions: ["dxp"] + }, + "application/vnd.spotfire.sfs": { + source: "iana", + extensions: ["sfs"] + }, + "application/vnd.sqlite3": { + source: "iana" + }, + "application/vnd.sss-cod": { + source: "iana" + }, + "application/vnd.sss-dtf": { + source: "iana" + }, + "application/vnd.sss-ntf": { + source: "iana" + }, + "application/vnd.stardivision.calc": { + source: "apache", + extensions: ["sdc"] + }, + "application/vnd.stardivision.draw": { + source: "apache", + extensions: ["sda"] + }, + "application/vnd.stardivision.impress": { + source: "apache", + extensions: ["sdd"] + }, + "application/vnd.stardivision.math": { + source: "apache", + extensions: ["smf"] + }, + "application/vnd.stardivision.writer": { + source: "apache", + extensions: ["sdw", "vor"] + }, + "application/vnd.stardivision.writer-global": { + source: "apache", + extensions: ["sgl"] + }, + "application/vnd.stepmania.package": { + source: "iana", + extensions: ["smzip"] + }, + "application/vnd.stepmania.stepchart": { + source: "iana", + extensions: ["sm"] + }, + "application/vnd.street-stream": { + source: "iana" + }, + "application/vnd.sun.wadl+xml": { + source: "iana", + compressible: true, + extensions: ["wadl"] + }, + "application/vnd.sun.xml.calc": { + source: "apache", + extensions: ["sxc"] + }, + "application/vnd.sun.xml.calc.template": { + source: "apache", + extensions: ["stc"] + }, + "application/vnd.sun.xml.draw": { + source: "apache", + extensions: ["sxd"] + }, + "application/vnd.sun.xml.draw.template": { + source: "apache", + extensions: ["std"] + }, + "application/vnd.sun.xml.impress": { + source: "apache", + extensions: ["sxi"] + }, + "application/vnd.sun.xml.impress.template": { + source: "apache", + extensions: ["sti"] + }, + "application/vnd.sun.xml.math": { + source: "apache", + extensions: ["sxm"] + }, + "application/vnd.sun.xml.writer": { + source: "apache", + extensions: ["sxw"] + }, + "application/vnd.sun.xml.writer.global": { + source: "apache", + extensions: ["sxg"] + }, + "application/vnd.sun.xml.writer.template": { + source: "apache", + extensions: ["stw"] + }, + "application/vnd.sus-calendar": { + source: "iana", + extensions: ["sus", "susp"] + }, + "application/vnd.svd": { + source: "iana", + extensions: ["svd"] + }, + "application/vnd.swiftview-ics": { + source: "iana" + }, + "application/vnd.sycle+xml": { + source: "iana", + compressible: true + }, + "application/vnd.syft+json": { + source: "iana", + compressible: true + }, + "application/vnd.symbian.install": { + source: "apache", + extensions: ["sis", "sisx"] + }, + "application/vnd.syncml+xml": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["xsm"] + }, + "application/vnd.syncml.dm+wbxml": { + source: "iana", + charset: "UTF-8", + extensions: ["bdm"] + }, + "application/vnd.syncml.dm+xml": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["xdm"] + }, + "application/vnd.syncml.dm.notification": { + source: "iana" + }, + "application/vnd.syncml.dmddf+wbxml": { + source: "iana" + }, + "application/vnd.syncml.dmddf+xml": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["ddf"] + }, + "application/vnd.syncml.dmtnds+wbxml": { + source: "iana" + }, + "application/vnd.syncml.dmtnds+xml": { + source: "iana", + charset: "UTF-8", + compressible: true + }, + "application/vnd.syncml.ds.notification": { + source: "iana" + }, + "application/vnd.tableschema+json": { + source: "iana", + compressible: true + }, + "application/vnd.tao.intent-module-archive": { + source: "iana", + extensions: ["tao"] + }, + "application/vnd.tcpdump.pcap": { + source: "iana", + extensions: ["pcap", "cap", "dmp"] + }, + "application/vnd.think-cell.ppttc+json": { + source: "iana", + compressible: true + }, + "application/vnd.tmd.mediaflex.api+xml": { + source: "iana", + compressible: true + }, + "application/vnd.tml": { + source: "iana" + }, + "application/vnd.tmobile-livetv": { + source: "iana", + extensions: ["tmo"] + }, + "application/vnd.tri.onesource": { + source: "iana" + }, + "application/vnd.trid.tpt": { + source: "iana", + extensions: ["tpt"] + }, + "application/vnd.triscape.mxs": { + source: "iana", + extensions: ["mxs"] + }, + "application/vnd.trueapp": { + source: "iana", + extensions: ["tra"] + }, + "application/vnd.truedoc": { + source: "iana" + }, + "application/vnd.ubisoft.webplayer": { + source: "iana" + }, + "application/vnd.ufdl": { + source: "iana", + extensions: ["ufd", "ufdl"] + }, + "application/vnd.uiq.theme": { + source: "iana", + extensions: ["utz"] + }, + "application/vnd.umajin": { + source: "iana", + extensions: ["umj"] + }, + "application/vnd.unity": { + source: "iana", + extensions: ["unityweb"] + }, + "application/vnd.uoml+xml": { + source: "iana", + compressible: true, + extensions: ["uoml"] + }, + "application/vnd.uplanet.alert": { + source: "iana" + }, + "application/vnd.uplanet.alert-wbxml": { + source: "iana" + }, + "application/vnd.uplanet.bearer-choice": { + source: "iana" + }, + "application/vnd.uplanet.bearer-choice-wbxml": { + source: "iana" + }, + "application/vnd.uplanet.cacheop": { + source: "iana" + }, + "application/vnd.uplanet.cacheop-wbxml": { + source: "iana" + }, + "application/vnd.uplanet.channel": { + source: "iana" + }, + "application/vnd.uplanet.channel-wbxml": { + source: "iana" + }, + "application/vnd.uplanet.list": { + source: "iana" + }, + "application/vnd.uplanet.list-wbxml": { + source: "iana" + }, + "application/vnd.uplanet.listcmd": { + source: "iana" + }, + "application/vnd.uplanet.listcmd-wbxml": { + source: "iana" + }, + "application/vnd.uplanet.signal": { + source: "iana" + }, + "application/vnd.uri-map": { + source: "iana" + }, + "application/vnd.valve.source.material": { + source: "iana" + }, + "application/vnd.vcx": { + source: "iana", + extensions: ["vcx"] + }, + "application/vnd.vd-study": { + source: "iana" + }, + "application/vnd.vectorworks": { + source: "iana" + }, + "application/vnd.vel+json": { + source: "iana", + compressible: true + }, + "application/vnd.verimatrix.vcas": { + source: "iana" + }, + "application/vnd.veritone.aion+json": { + source: "iana", + compressible: true + }, + "application/vnd.veryant.thin": { + source: "iana" + }, + "application/vnd.ves.encrypted": { + source: "iana" + }, + "application/vnd.vidsoft.vidconference": { + source: "iana" + }, + "application/vnd.visio": { + source: "iana", + extensions: ["vsd", "vst", "vss", "vsw"] + }, + "application/vnd.visionary": { + source: "iana", + extensions: ["vis"] + }, + "application/vnd.vividence.scriptfile": { + source: "iana" + }, + "application/vnd.vsf": { + source: "iana", + extensions: ["vsf"] + }, + "application/vnd.wap.sic": { + source: "iana" + }, + "application/vnd.wap.slc": { + source: "iana" + }, + "application/vnd.wap.wbxml": { + source: "iana", + charset: "UTF-8", + extensions: ["wbxml"] + }, + "application/vnd.wap.wmlc": { + source: "iana", + extensions: ["wmlc"] + }, + "application/vnd.wap.wmlscriptc": { + source: "iana", + extensions: ["wmlsc"] + }, + "application/vnd.webturbo": { + source: "iana", + extensions: ["wtb"] + }, + "application/vnd.wfa.dpp": { + source: "iana" + }, + "application/vnd.wfa.p2p": { + source: "iana" + }, + "application/vnd.wfa.wsc": { + source: "iana" + }, + "application/vnd.windows.devicepairing": { + source: "iana" + }, + "application/vnd.wmc": { + source: "iana" + }, + "application/vnd.wmf.bootstrap": { + source: "iana" + }, + "application/vnd.wolfram.mathematica": { + source: "iana" + }, + "application/vnd.wolfram.mathematica.package": { + source: "iana" + }, + "application/vnd.wolfram.player": { + source: "iana", + extensions: ["nbp"] + }, + "application/vnd.wordperfect": { + source: "iana", + extensions: ["wpd"] + }, + "application/vnd.wqd": { + source: "iana", + extensions: ["wqd"] + }, + "application/vnd.wrq-hp3000-labelled": { + source: "iana" + }, + "application/vnd.wt.stf": { + source: "iana", + extensions: ["stf"] + }, + "application/vnd.wv.csp+wbxml": { + source: "iana" + }, + "application/vnd.wv.csp+xml": { + source: "iana", + compressible: true + }, + "application/vnd.wv.ssp+xml": { + source: "iana", + compressible: true + }, + "application/vnd.xacml+json": { + source: "iana", + compressible: true + }, + "application/vnd.xara": { + source: "iana", + extensions: ["xar"] + }, + "application/vnd.xfdl": { + source: "iana", + extensions: ["xfdl"] + }, + "application/vnd.xfdl.webform": { + source: "iana" + }, + "application/vnd.xmi+xml": { + source: "iana", + compressible: true + }, + "application/vnd.xmpie.cpkg": { + source: "iana" + }, + "application/vnd.xmpie.dpkg": { + source: "iana" + }, + "application/vnd.xmpie.plan": { + source: "iana" + }, + "application/vnd.xmpie.ppkg": { + source: "iana" + }, + "application/vnd.xmpie.xlim": { + source: "iana" + }, + "application/vnd.yamaha.hv-dic": { + source: "iana", + extensions: ["hvd"] + }, + "application/vnd.yamaha.hv-script": { + source: "iana", + extensions: ["hvs"] + }, + "application/vnd.yamaha.hv-voice": { + source: "iana", + extensions: ["hvp"] + }, + "application/vnd.yamaha.openscoreformat": { + source: "iana", + extensions: ["osf"] + }, + "application/vnd.yamaha.openscoreformat.osfpvg+xml": { + source: "iana", + compressible: true, + extensions: ["osfpvg"] + }, + "application/vnd.yamaha.remote-setup": { + source: "iana" + }, + "application/vnd.yamaha.smaf-audio": { + source: "iana", + extensions: ["saf"] + }, + "application/vnd.yamaha.smaf-phrase": { + source: "iana", + extensions: ["spf"] + }, + "application/vnd.yamaha.through-ngn": { + source: "iana" + }, + "application/vnd.yamaha.tunnel-udpencap": { + source: "iana" + }, + "application/vnd.yaoweme": { + source: "iana" + }, + "application/vnd.yellowriver-custom-menu": { + source: "iana", + extensions: ["cmp"] + }, + "application/vnd.youtube.yt": { + source: "iana" + }, + "application/vnd.zul": { + source: "iana", + extensions: ["zir", "zirz"] + }, + "application/vnd.zzazz.deck+xml": { + source: "iana", + compressible: true, + extensions: ["zaz"] + }, + "application/voicexml+xml": { + source: "iana", + compressible: true, + extensions: ["vxml"] + }, + "application/voucher-cms+json": { + source: "iana", + compressible: true + }, + "application/vq-rtcpxr": { + source: "iana" + }, + "application/wasm": { + source: "iana", + compressible: true, + extensions: ["wasm"] + }, + "application/watcherinfo+xml": { + source: "iana", + compressible: true, + extensions: ["wif"] + }, + "application/webpush-options+json": { + source: "iana", + compressible: true + }, + "application/whoispp-query": { + source: "iana" + }, + "application/whoispp-response": { + source: "iana" + }, + "application/widget": { + source: "iana", + extensions: ["wgt"] + }, + "application/winhlp": { + source: "apache", + extensions: ["hlp"] + }, + "application/wita": { + source: "iana" + }, + "application/wordperfect5.1": { + source: "iana" + }, + "application/wsdl+xml": { + source: "iana", + compressible: true, + extensions: ["wsdl"] + }, + "application/wspolicy+xml": { + source: "iana", + compressible: true, + extensions: ["wspolicy"] + }, + "application/x-7z-compressed": { + source: "apache", + compressible: false, + extensions: ["7z"] + }, + "application/x-abiword": { + source: "apache", + extensions: ["abw"] + }, + "application/x-ace-compressed": { + source: "apache", + extensions: ["ace"] + }, + "application/x-amf": { + source: "apache" + }, + "application/x-apple-diskimage": { + source: "apache", + extensions: ["dmg"] + }, + "application/x-arj": { + compressible: false, + extensions: ["arj"] + }, + "application/x-authorware-bin": { + source: "apache", + extensions: ["aab", "x32", "u32", "vox"] + }, + "application/x-authorware-map": { + source: "apache", + extensions: ["aam"] + }, + "application/x-authorware-seg": { + source: "apache", + extensions: ["aas"] + }, + "application/x-bcpio": { + source: "apache", + extensions: ["bcpio"] + }, + "application/x-bdoc": { + compressible: false, + extensions: ["bdoc"] + }, + "application/x-bittorrent": { + source: "apache", + extensions: ["torrent"] + }, + "application/x-blorb": { + source: "apache", + extensions: ["blb", "blorb"] + }, + "application/x-bzip": { + source: "apache", + compressible: false, + extensions: ["bz"] + }, + "application/x-bzip2": { + source: "apache", + compressible: false, + extensions: ["bz2", "boz"] + }, + "application/x-cbr": { + source: "apache", + extensions: ["cbr", "cba", "cbt", "cbz", "cb7"] + }, + "application/x-cdlink": { + source: "apache", + extensions: ["vcd"] + }, + "application/x-cfs-compressed": { + source: "apache", + extensions: ["cfs"] + }, + "application/x-chat": { + source: "apache", + extensions: ["chat"] + }, + "application/x-chess-pgn": { + source: "apache", + extensions: ["pgn"] + }, + "application/x-chrome-extension": { + extensions: ["crx"] + }, + "application/x-cocoa": { + source: "nginx", + extensions: ["cco"] + }, + "application/x-compress": { + source: "apache" + }, + "application/x-conference": { + source: "apache", + extensions: ["nsc"] + }, + "application/x-cpio": { + source: "apache", + extensions: ["cpio"] + }, + "application/x-csh": { + source: "apache", + extensions: ["csh"] + }, + "application/x-deb": { + compressible: false + }, + "application/x-debian-package": { + source: "apache", + extensions: ["deb", "udeb"] + }, + "application/x-dgc-compressed": { + source: "apache", + extensions: ["dgc"] + }, + "application/x-director": { + source: "apache", + extensions: ["dir", "dcr", "dxr", "cst", "cct", "cxt", "w3d", "fgd", "swa"] + }, + "application/x-doom": { + source: "apache", + extensions: ["wad"] + }, + "application/x-dtbncx+xml": { + source: "apache", + compressible: true, + extensions: ["ncx"] + }, + "application/x-dtbook+xml": { + source: "apache", + compressible: true, + extensions: ["dtb"] + }, + "application/x-dtbresource+xml": { + source: "apache", + compressible: true, + extensions: ["res"] + }, + "application/x-dvi": { + source: "apache", + compressible: false, + extensions: ["dvi"] + }, + "application/x-envoy": { + source: "apache", + extensions: ["evy"] + }, + "application/x-eva": { + source: "apache", + extensions: ["eva"] + }, + "application/x-font-bdf": { + source: "apache", + extensions: ["bdf"] + }, + "application/x-font-dos": { + source: "apache" + }, + "application/x-font-framemaker": { + source: "apache" + }, + "application/x-font-ghostscript": { + source: "apache", + extensions: ["gsf"] + }, + "application/x-font-libgrx": { + source: "apache" + }, + "application/x-font-linux-psf": { + source: "apache", + extensions: ["psf"] + }, + "application/x-font-pcf": { + source: "apache", + extensions: ["pcf"] + }, + "application/x-font-snf": { + source: "apache", + extensions: ["snf"] + }, + "application/x-font-speedo": { + source: "apache" + }, + "application/x-font-sunos-news": { + source: "apache" + }, + "application/x-font-type1": { + source: "apache", + extensions: ["pfa", "pfb", "pfm", "afm"] + }, + "application/x-font-vfont": { + source: "apache" + }, + "application/x-freearc": { + source: "apache", + extensions: ["arc"] + }, + "application/x-futuresplash": { + source: "apache", + extensions: ["spl"] + }, + "application/x-gca-compressed": { + source: "apache", + extensions: ["gca"] + }, + "application/x-glulx": { + source: "apache", + extensions: ["ulx"] + }, + "application/x-gnumeric": { + source: "apache", + extensions: ["gnumeric"] + }, + "application/x-gramps-xml": { + source: "apache", + extensions: ["gramps"] + }, + "application/x-gtar": { + source: "apache", + extensions: ["gtar"] + }, + "application/x-gzip": { + source: "apache" + }, + "application/x-hdf": { + source: "apache", + extensions: ["hdf"] + }, + "application/x-httpd-php": { + compressible: true, + extensions: ["php"] + }, + "application/x-install-instructions": { + source: "apache", + extensions: ["install"] + }, + "application/x-iso9660-image": { + source: "apache", + extensions: ["iso"] + }, + "application/x-iwork-keynote-sffkey": { + extensions: ["key"] + }, + "application/x-iwork-numbers-sffnumbers": { + extensions: ["numbers"] + }, + "application/x-iwork-pages-sffpages": { + extensions: ["pages"] + }, + "application/x-java-archive-diff": { + source: "nginx", + extensions: ["jardiff"] + }, + "application/x-java-jnlp-file": { + source: "apache", + compressible: false, + extensions: ["jnlp"] + }, + "application/x-javascript": { + compressible: true + }, + "application/x-keepass2": { + extensions: ["kdbx"] + }, + "application/x-latex": { + source: "apache", + compressible: false, + extensions: ["latex"] + }, + "application/x-lua-bytecode": { + extensions: ["luac"] + }, + "application/x-lzh-compressed": { + source: "apache", + extensions: ["lzh", "lha"] + }, + "application/x-makeself": { + source: "nginx", + extensions: ["run"] + }, + "application/x-mie": { + source: "apache", + extensions: ["mie"] + }, + "application/x-mobipocket-ebook": { + source: "apache", + extensions: ["prc", "mobi"] + }, + "application/x-mpegurl": { + compressible: false + }, + "application/x-ms-application": { + source: "apache", + extensions: ["application"] + }, + "application/x-ms-shortcut": { + source: "apache", + extensions: ["lnk"] + }, + "application/x-ms-wmd": { + source: "apache", + extensions: ["wmd"] + }, + "application/x-ms-wmz": { + source: "apache", + extensions: ["wmz"] + }, + "application/x-ms-xbap": { + source: "apache", + extensions: ["xbap"] + }, + "application/x-msaccess": { + source: "apache", + extensions: ["mdb"] + }, + "application/x-msbinder": { + source: "apache", + extensions: ["obd"] + }, + "application/x-mscardfile": { + source: "apache", + extensions: ["crd"] + }, + "application/x-msclip": { + source: "apache", + extensions: ["clp"] + }, + "application/x-msdos-program": { + extensions: ["exe"] + }, + "application/x-msdownload": { + source: "apache", + extensions: ["exe", "dll", "com", "bat", "msi"] + }, + "application/x-msmediaview": { + source: "apache", + extensions: ["mvb", "m13", "m14"] + }, + "application/x-msmetafile": { + source: "apache", + extensions: ["wmf", "wmz", "emf", "emz"] + }, + "application/x-msmoney": { + source: "apache", + extensions: ["mny"] + }, + "application/x-mspublisher": { + source: "apache", + extensions: ["pub"] + }, + "application/x-msschedule": { + source: "apache", + extensions: ["scd"] + }, + "application/x-msterminal": { + source: "apache", + extensions: ["trm"] + }, + "application/x-mswrite": { + source: "apache", + extensions: ["wri"] + }, + "application/x-netcdf": { + source: "apache", + extensions: ["nc", "cdf"] + }, + "application/x-ns-proxy-autoconfig": { + compressible: true, + extensions: ["pac"] + }, + "application/x-nzb": { + source: "apache", + extensions: ["nzb"] + }, + "application/x-perl": { + source: "nginx", + extensions: ["pl", "pm"] + }, + "application/x-pilot": { + source: "nginx", + extensions: ["prc", "pdb"] + }, + "application/x-pkcs12": { + source: "apache", + compressible: false, + extensions: ["p12", "pfx"] + }, + "application/x-pkcs7-certificates": { + source: "apache", + extensions: ["p7b", "spc"] + }, + "application/x-pkcs7-certreqresp": { + source: "apache", + extensions: ["p7r"] + }, + "application/x-pki-message": { + source: "iana" + }, + "application/x-rar-compressed": { + source: "apache", + compressible: false, + extensions: ["rar"] + }, + "application/x-redhat-package-manager": { + source: "nginx", + extensions: ["rpm"] + }, + "application/x-research-info-systems": { + source: "apache", + extensions: ["ris"] + }, + "application/x-sea": { + source: "nginx", + extensions: ["sea"] + }, + "application/x-sh": { + source: "apache", + compressible: true, + extensions: ["sh"] + }, + "application/x-shar": { + source: "apache", + extensions: ["shar"] + }, + "application/x-shockwave-flash": { + source: "apache", + compressible: false, + extensions: ["swf"] + }, + "application/x-silverlight-app": { + source: "apache", + extensions: ["xap"] + }, + "application/x-sql": { + source: "apache", + extensions: ["sql"] + }, + "application/x-stuffit": { + source: "apache", + compressible: false, + extensions: ["sit"] + }, + "application/x-stuffitx": { + source: "apache", + extensions: ["sitx"] + }, + "application/x-subrip": { + source: "apache", + extensions: ["srt"] + }, + "application/x-sv4cpio": { + source: "apache", + extensions: ["sv4cpio"] + }, + "application/x-sv4crc": { + source: "apache", + extensions: ["sv4crc"] + }, + "application/x-t3vm-image": { + source: "apache", + extensions: ["t3"] + }, + "application/x-tads": { + source: "apache", + extensions: ["gam"] + }, + "application/x-tar": { + source: "apache", + compressible: true, + extensions: ["tar"] + }, + "application/x-tcl": { + source: "apache", + extensions: ["tcl", "tk"] + }, + "application/x-tex": { + source: "apache", + extensions: ["tex"] + }, + "application/x-tex-tfm": { + source: "apache", + extensions: ["tfm"] + }, + "application/x-texinfo": { + source: "apache", + extensions: ["texinfo", "texi"] + }, + "application/x-tgif": { + source: "apache", + extensions: ["obj"] + }, + "application/x-ustar": { + source: "apache", + extensions: ["ustar"] + }, + "application/x-virtualbox-hdd": { + compressible: true, + extensions: ["hdd"] + }, + "application/x-virtualbox-ova": { + compressible: true, + extensions: ["ova"] + }, + "application/x-virtualbox-ovf": { + compressible: true, + extensions: ["ovf"] + }, + "application/x-virtualbox-vbox": { + compressible: true, + extensions: ["vbox"] + }, + "application/x-virtualbox-vbox-extpack": { + compressible: false, + extensions: ["vbox-extpack"] + }, + "application/x-virtualbox-vdi": { + compressible: true, + extensions: ["vdi"] + }, + "application/x-virtualbox-vhd": { + compressible: true, + extensions: ["vhd"] + }, + "application/x-virtualbox-vmdk": { + compressible: true, + extensions: ["vmdk"] + }, + "application/x-wais-source": { + source: "apache", + extensions: ["src"] + }, + "application/x-web-app-manifest+json": { + compressible: true, + extensions: ["webapp"] + }, + "application/x-www-form-urlencoded": { + source: "iana", + compressible: true + }, + "application/x-x509-ca-cert": { + source: "iana", + extensions: ["der", "crt", "pem"] + }, + "application/x-x509-ca-ra-cert": { + source: "iana" + }, + "application/x-x509-next-ca-cert": { + source: "iana" + }, + "application/x-xfig": { + source: "apache", + extensions: ["fig"] + }, + "application/x-xliff+xml": { + source: "apache", + compressible: true, + extensions: ["xlf"] + }, + "application/x-xpinstall": { + source: "apache", + compressible: false, + extensions: ["xpi"] + }, + "application/x-xz": { + source: "apache", + extensions: ["xz"] + }, + "application/x-zmachine": { + source: "apache", + extensions: ["z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8"] + }, + "application/x400-bp": { + source: "iana" + }, + "application/xacml+xml": { + source: "iana", + compressible: true + }, + "application/xaml+xml": { + source: "apache", + compressible: true, + extensions: ["xaml"] + }, + "application/xcap-att+xml": { + source: "iana", + compressible: true, + extensions: ["xav"] + }, + "application/xcap-caps+xml": { + source: "iana", + compressible: true, + extensions: ["xca"] + }, + "application/xcap-diff+xml": { + source: "iana", + compressible: true, + extensions: ["xdf"] + }, + "application/xcap-el+xml": { + source: "iana", + compressible: true, + extensions: ["xel"] + }, + "application/xcap-error+xml": { + source: "iana", + compressible: true + }, + "application/xcap-ns+xml": { + source: "iana", + compressible: true, + extensions: ["xns"] + }, + "application/xcon-conference-info+xml": { + source: "iana", + compressible: true + }, + "application/xcon-conference-info-diff+xml": { + source: "iana", + compressible: true + }, + "application/xenc+xml": { + source: "iana", + compressible: true, + extensions: ["xenc"] + }, + "application/xhtml+xml": { + source: "iana", + compressible: true, + extensions: ["xhtml", "xht"] + }, + "application/xhtml-voice+xml": { + source: "apache", + compressible: true + }, + "application/xliff+xml": { + source: "iana", + compressible: true, + extensions: ["xlf"] + }, + "application/xml": { + source: "iana", + compressible: true, + extensions: ["xml", "xsl", "xsd", "rng"] + }, + "application/xml-dtd": { + source: "iana", + compressible: true, + extensions: ["dtd"] + }, + "application/xml-external-parsed-entity": { + source: "iana" + }, + "application/xml-patch+xml": { + source: "iana", + compressible: true + }, + "application/xmpp+xml": { + source: "iana", + compressible: true + }, + "application/xop+xml": { + source: "iana", + compressible: true, + extensions: ["xop"] + }, + "application/xproc+xml": { + source: "apache", + compressible: true, + extensions: ["xpl"] + }, + "application/xslt+xml": { + source: "iana", + compressible: true, + extensions: ["xsl", "xslt"] + }, + "application/xspf+xml": { + source: "apache", + compressible: true, + extensions: ["xspf"] + }, + "application/xv+xml": { + source: "iana", + compressible: true, + extensions: ["mxml", "xhvml", "xvml", "xvm"] + }, + "application/yang": { + source: "iana", + extensions: ["yang"] + }, + "application/yang-data+json": { + source: "iana", + compressible: true + }, + "application/yang-data+xml": { + source: "iana", + compressible: true + }, + "application/yang-patch+json": { + source: "iana", + compressible: true + }, + "application/yang-patch+xml": { + source: "iana", + compressible: true + }, + "application/yin+xml": { + source: "iana", + compressible: true, + extensions: ["yin"] + }, + "application/zip": { + source: "iana", + compressible: false, + extensions: ["zip"] + }, + "application/zlib": { + source: "iana" + }, + "application/zstd": { + source: "iana" + }, + "audio/1d-interleaved-parityfec": { + source: "iana" + }, + "audio/32kadpcm": { + source: "iana" + }, + "audio/3gpp": { + source: "iana", + compressible: false, + extensions: ["3gpp"] + }, + "audio/3gpp2": { + source: "iana" + }, + "audio/aac": { + source: "iana" + }, + "audio/ac3": { + source: "iana" + }, + "audio/adpcm": { + source: "apache", + extensions: ["adp"] + }, + "audio/amr": { + source: "iana", + extensions: ["amr"] + }, + "audio/amr-wb": { + source: "iana" + }, + "audio/amr-wb+": { + source: "iana" + }, + "audio/aptx": { + source: "iana" + }, + "audio/asc": { + source: "iana" + }, + "audio/atrac-advanced-lossless": { + source: "iana" + }, + "audio/atrac-x": { + source: "iana" + }, + "audio/atrac3": { + source: "iana" + }, + "audio/basic": { + source: "iana", + compressible: false, + extensions: ["au", "snd"] + }, + "audio/bv16": { + source: "iana" + }, + "audio/bv32": { + source: "iana" + }, + "audio/clearmode": { + source: "iana" + }, + "audio/cn": { + source: "iana" + }, + "audio/dat12": { + source: "iana" + }, + "audio/dls": { + source: "iana" + }, + "audio/dsr-es201108": { + source: "iana" + }, + "audio/dsr-es202050": { + source: "iana" + }, + "audio/dsr-es202211": { + source: "iana" + }, + "audio/dsr-es202212": { + source: "iana" + }, + "audio/dv": { + source: "iana" + }, + "audio/dvi4": { + source: "iana" + }, + "audio/eac3": { + source: "iana" + }, + "audio/encaprtp": { + source: "iana" + }, + "audio/evrc": { + source: "iana" + }, + "audio/evrc-qcp": { + source: "iana" + }, + "audio/evrc0": { + source: "iana" + }, + "audio/evrc1": { + source: "iana" + }, + "audio/evrcb": { + source: "iana" + }, + "audio/evrcb0": { + source: "iana" + }, + "audio/evrcb1": { + source: "iana" + }, + "audio/evrcnw": { + source: "iana" + }, + "audio/evrcnw0": { + source: "iana" + }, + "audio/evrcnw1": { + source: "iana" + }, + "audio/evrcwb": { + source: "iana" + }, + "audio/evrcwb0": { + source: "iana" + }, + "audio/evrcwb1": { + source: "iana" + }, + "audio/evs": { + source: "iana" + }, + "audio/flexfec": { + source: "iana" + }, + "audio/fwdred": { + source: "iana" + }, + "audio/g711-0": { + source: "iana" + }, + "audio/g719": { + source: "iana" + }, + "audio/g722": { + source: "iana" + }, + "audio/g7221": { + source: "iana" + }, + "audio/g723": { + source: "iana" + }, + "audio/g726-16": { + source: "iana" + }, + "audio/g726-24": { + source: "iana" + }, + "audio/g726-32": { + source: "iana" + }, + "audio/g726-40": { + source: "iana" + }, + "audio/g728": { + source: "iana" + }, + "audio/g729": { + source: "iana" + }, + "audio/g7291": { + source: "iana" + }, + "audio/g729d": { + source: "iana" + }, + "audio/g729e": { + source: "iana" + }, + "audio/gsm": { + source: "iana" + }, + "audio/gsm-efr": { + source: "iana" + }, + "audio/gsm-hr-08": { + source: "iana" + }, + "audio/ilbc": { + source: "iana" + }, + "audio/ip-mr_v2.5": { + source: "iana" + }, + "audio/isac": { + source: "apache" + }, + "audio/l16": { + source: "iana" + }, + "audio/l20": { + source: "iana" + }, + "audio/l24": { + source: "iana", + compressible: false + }, + "audio/l8": { + source: "iana" + }, + "audio/lpc": { + source: "iana" + }, + "audio/melp": { + source: "iana" + }, + "audio/melp1200": { + source: "iana" + }, + "audio/melp2400": { + source: "iana" + }, + "audio/melp600": { + source: "iana" + }, + "audio/mhas": { + source: "iana" + }, + "audio/midi": { + source: "apache", + extensions: ["mid", "midi", "kar", "rmi"] + }, + "audio/mobile-xmf": { + source: "iana", + extensions: ["mxmf"] + }, + "audio/mp3": { + compressible: false, + extensions: ["mp3"] + }, + "audio/mp4": { + source: "iana", + compressible: false, + extensions: ["m4a", "mp4a"] + }, + "audio/mp4a-latm": { + source: "iana" + }, + "audio/mpa": { + source: "iana" + }, + "audio/mpa-robust": { + source: "iana" + }, + "audio/mpeg": { + source: "iana", + compressible: false, + extensions: ["mpga", "mp2", "mp2a", "mp3", "m2a", "m3a"] + }, + "audio/mpeg4-generic": { + source: "iana" + }, + "audio/musepack": { + source: "apache" + }, + "audio/ogg": { + source: "iana", + compressible: false, + extensions: ["oga", "ogg", "spx", "opus"] + }, + "audio/opus": { + source: "iana" + }, + "audio/parityfec": { + source: "iana" + }, + "audio/pcma": { + source: "iana" + }, + "audio/pcma-wb": { + source: "iana" + }, + "audio/pcmu": { + source: "iana" + }, + "audio/pcmu-wb": { + source: "iana" + }, + "audio/prs.sid": { + source: "iana" + }, + "audio/qcelp": { + source: "iana" + }, + "audio/raptorfec": { + source: "iana" + }, + "audio/red": { + source: "iana" + }, + "audio/rtp-enc-aescm128": { + source: "iana" + }, + "audio/rtp-midi": { + source: "iana" + }, + "audio/rtploopback": { + source: "iana" + }, + "audio/rtx": { + source: "iana" + }, + "audio/s3m": { + source: "apache", + extensions: ["s3m"] + }, + "audio/scip": { + source: "iana" + }, + "audio/silk": { + source: "apache", + extensions: ["sil"] + }, + "audio/smv": { + source: "iana" + }, + "audio/smv-qcp": { + source: "iana" + }, + "audio/smv0": { + source: "iana" + }, + "audio/sofa": { + source: "iana" + }, + "audio/sp-midi": { + source: "iana" + }, + "audio/speex": { + source: "iana" + }, + "audio/t140c": { + source: "iana" + }, + "audio/t38": { + source: "iana" + }, + "audio/telephone-event": { + source: "iana" + }, + "audio/tetra_acelp": { + source: "iana" + }, + "audio/tetra_acelp_bb": { + source: "iana" + }, + "audio/tone": { + source: "iana" + }, + "audio/tsvcis": { + source: "iana" + }, + "audio/uemclip": { + source: "iana" + }, + "audio/ulpfec": { + source: "iana" + }, + "audio/usac": { + source: "iana" + }, + "audio/vdvi": { + source: "iana" + }, + "audio/vmr-wb": { + source: "iana" + }, + "audio/vnd.3gpp.iufp": { + source: "iana" + }, + "audio/vnd.4sb": { + source: "iana" + }, + "audio/vnd.audiokoz": { + source: "iana" + }, + "audio/vnd.celp": { + source: "iana" + }, + "audio/vnd.cisco.nse": { + source: "iana" + }, + "audio/vnd.cmles.radio-events": { + source: "iana" + }, + "audio/vnd.cns.anp1": { + source: "iana" + }, + "audio/vnd.cns.inf1": { + source: "iana" + }, + "audio/vnd.dece.audio": { + source: "iana", + extensions: ["uva", "uvva"] + }, + "audio/vnd.digital-winds": { + source: "iana", + extensions: ["eol"] + }, + "audio/vnd.dlna.adts": { + source: "iana" + }, + "audio/vnd.dolby.heaac.1": { + source: "iana" + }, + "audio/vnd.dolby.heaac.2": { + source: "iana" + }, + "audio/vnd.dolby.mlp": { + source: "iana" + }, + "audio/vnd.dolby.mps": { + source: "iana" + }, + "audio/vnd.dolby.pl2": { + source: "iana" + }, + "audio/vnd.dolby.pl2x": { + source: "iana" + }, + "audio/vnd.dolby.pl2z": { + source: "iana" + }, + "audio/vnd.dolby.pulse.1": { + source: "iana" + }, + "audio/vnd.dra": { + source: "iana", + extensions: ["dra"] + }, + "audio/vnd.dts": { + source: "iana", + extensions: ["dts"] + }, + "audio/vnd.dts.hd": { + source: "iana", + extensions: ["dtshd"] + }, + "audio/vnd.dts.uhd": { + source: "iana" + }, + "audio/vnd.dvb.file": { + source: "iana" + }, + "audio/vnd.everad.plj": { + source: "iana" + }, + "audio/vnd.hns.audio": { + source: "iana" + }, + "audio/vnd.lucent.voice": { + source: "iana", + extensions: ["lvp"] + }, + "audio/vnd.ms-playready.media.pya": { + source: "iana", + extensions: ["pya"] + }, + "audio/vnd.nokia.mobile-xmf": { + source: "iana" + }, + "audio/vnd.nortel.vbk": { + source: "iana" + }, + "audio/vnd.nuera.ecelp4800": { + source: "iana", + extensions: ["ecelp4800"] + }, + "audio/vnd.nuera.ecelp7470": { + source: "iana", + extensions: ["ecelp7470"] + }, + "audio/vnd.nuera.ecelp9600": { + source: "iana", + extensions: ["ecelp9600"] + }, + "audio/vnd.octel.sbc": { + source: "iana" + }, + "audio/vnd.presonus.multitrack": { + source: "iana" + }, + "audio/vnd.qcelp": { + source: "iana" + }, + "audio/vnd.rhetorex.32kadpcm": { + source: "iana" + }, + "audio/vnd.rip": { + source: "iana", + extensions: ["rip"] + }, + "audio/vnd.rn-realaudio": { + compressible: false + }, + "audio/vnd.sealedmedia.softseal.mpeg": { + source: "iana" + }, + "audio/vnd.vmx.cvsd": { + source: "iana" + }, + "audio/vnd.wave": { + compressible: false + }, + "audio/vorbis": { + source: "iana", + compressible: false + }, + "audio/vorbis-config": { + source: "iana" + }, + "audio/wav": { + compressible: false, + extensions: ["wav"] + }, + "audio/wave": { + compressible: false, + extensions: ["wav"] + }, + "audio/webm": { + source: "apache", + compressible: false, + extensions: ["weba"] + }, + "audio/x-aac": { + source: "apache", + compressible: false, + extensions: ["aac"] + }, + "audio/x-aiff": { + source: "apache", + extensions: ["aif", "aiff", "aifc"] + }, + "audio/x-caf": { + source: "apache", + compressible: false, + extensions: ["caf"] + }, + "audio/x-flac": { + source: "apache", + extensions: ["flac"] + }, + "audio/x-m4a": { + source: "nginx", + extensions: ["m4a"] + }, + "audio/x-matroska": { + source: "apache", + extensions: ["mka"] + }, + "audio/x-mpegurl": { + source: "apache", + extensions: ["m3u"] + }, + "audio/x-ms-wax": { + source: "apache", + extensions: ["wax"] + }, + "audio/x-ms-wma": { + source: "apache", + extensions: ["wma"] + }, + "audio/x-pn-realaudio": { + source: "apache", + extensions: ["ram", "ra"] + }, + "audio/x-pn-realaudio-plugin": { + source: "apache", + extensions: ["rmp"] + }, + "audio/x-realaudio": { + source: "nginx", + extensions: ["ra"] + }, + "audio/x-tta": { + source: "apache" + }, + "audio/x-wav": { + source: "apache", + extensions: ["wav"] + }, + "audio/xm": { + source: "apache", + extensions: ["xm"] + }, + "chemical/x-cdx": { + source: "apache", + extensions: ["cdx"] + }, + "chemical/x-cif": { + source: "apache", + extensions: ["cif"] + }, + "chemical/x-cmdf": { + source: "apache", + extensions: ["cmdf"] + }, + "chemical/x-cml": { + source: "apache", + extensions: ["cml"] + }, + "chemical/x-csml": { + source: "apache", + extensions: ["csml"] + }, + "chemical/x-pdb": { + source: "apache" + }, + "chemical/x-xyz": { + source: "apache", + extensions: ["xyz"] + }, + "font/collection": { + source: "iana", + extensions: ["ttc"] + }, + "font/otf": { + source: "iana", + compressible: true, + extensions: ["otf"] + }, + "font/sfnt": { + source: "iana" + }, + "font/ttf": { + source: "iana", + compressible: true, + extensions: ["ttf"] + }, + "font/woff": { + source: "iana", + extensions: ["woff"] + }, + "font/woff2": { + source: "iana", + extensions: ["woff2"] + }, + "image/aces": { + source: "iana", + extensions: ["exr"] + }, + "image/apng": { + compressible: false, + extensions: ["apng"] + }, + "image/avci": { + source: "iana", + extensions: ["avci"] + }, + "image/avcs": { + source: "iana", + extensions: ["avcs"] + }, + "image/avif": { + source: "iana", + compressible: false, + extensions: ["avif"] + }, + "image/bmp": { + source: "iana", + compressible: true, + extensions: ["bmp"] + }, + "image/cgm": { + source: "iana", + extensions: ["cgm"] + }, + "image/dicom-rle": { + source: "iana", + extensions: ["drle"] + }, + "image/emf": { + source: "iana", + extensions: ["emf"] + }, + "image/fits": { + source: "iana", + extensions: ["fits"] + }, + "image/g3fax": { + source: "iana", + extensions: ["g3"] + }, + "image/gif": { + source: "iana", + compressible: false, + extensions: ["gif"] + }, + "image/heic": { + source: "iana", + extensions: ["heic"] + }, + "image/heic-sequence": { + source: "iana", + extensions: ["heics"] + }, + "image/heif": { + source: "iana", + extensions: ["heif"] + }, + "image/heif-sequence": { + source: "iana", + extensions: ["heifs"] + }, + "image/hej2k": { + source: "iana", + extensions: ["hej2"] + }, + "image/hsj2": { + source: "iana", + extensions: ["hsj2"] + }, + "image/ief": { + source: "iana", + extensions: ["ief"] + }, + "image/jls": { + source: "iana", + extensions: ["jls"] + }, + "image/jp2": { + source: "iana", + compressible: false, + extensions: ["jp2", "jpg2"] + }, + "image/jpeg": { + source: "iana", + compressible: false, + extensions: ["jpeg", "jpg", "jpe"] + }, + "image/jph": { + source: "iana", + extensions: ["jph"] + }, + "image/jphc": { + source: "iana", + extensions: ["jhc"] + }, + "image/jpm": { + source: "iana", + compressible: false, + extensions: ["jpm"] + }, + "image/jpx": { + source: "iana", + compressible: false, + extensions: ["jpx", "jpf"] + }, + "image/jxr": { + source: "iana", + extensions: ["jxr"] + }, + "image/jxra": { + source: "iana", + extensions: ["jxra"] + }, + "image/jxrs": { + source: "iana", + extensions: ["jxrs"] + }, + "image/jxs": { + source: "iana", + extensions: ["jxs"] + }, + "image/jxsc": { + source: "iana", + extensions: ["jxsc"] + }, + "image/jxsi": { + source: "iana", + extensions: ["jxsi"] + }, + "image/jxss": { + source: "iana", + extensions: ["jxss"] + }, + "image/ktx": { + source: "iana", + extensions: ["ktx"] + }, + "image/ktx2": { + source: "iana", + extensions: ["ktx2"] + }, + "image/naplps": { + source: "iana" + }, + "image/pjpeg": { + compressible: false + }, + "image/png": { + source: "iana", + compressible: false, + extensions: ["png"] + }, + "image/prs.btif": { + source: "iana", + extensions: ["btif"] + }, + "image/prs.pti": { + source: "iana", + extensions: ["pti"] + }, + "image/pwg-raster": { + source: "iana" + }, + "image/sgi": { + source: "apache", + extensions: ["sgi"] + }, + "image/svg+xml": { + source: "iana", + compressible: true, + extensions: ["svg", "svgz"] + }, + "image/t38": { + source: "iana", + extensions: ["t38"] + }, + "image/tiff": { + source: "iana", + compressible: false, + extensions: ["tif", "tiff"] + }, + "image/tiff-fx": { + source: "iana", + extensions: ["tfx"] + }, + "image/vnd.adobe.photoshop": { + source: "iana", + compressible: true, + extensions: ["psd"] + }, + "image/vnd.airzip.accelerator.azv": { + source: "iana", + extensions: ["azv"] + }, + "image/vnd.cns.inf2": { + source: "iana" + }, + "image/vnd.dece.graphic": { + source: "iana", + extensions: ["uvi", "uvvi", "uvg", "uvvg"] + }, + "image/vnd.djvu": { + source: "iana", + extensions: ["djvu", "djv"] + }, + "image/vnd.dvb.subtitle": { + source: "iana", + extensions: ["sub"] + }, + "image/vnd.dwg": { + source: "iana", + extensions: ["dwg"] + }, + "image/vnd.dxf": { + source: "iana", + extensions: ["dxf"] + }, + "image/vnd.fastbidsheet": { + source: "iana", + extensions: ["fbs"] + }, + "image/vnd.fpx": { + source: "iana", + extensions: ["fpx"] + }, + "image/vnd.fst": { + source: "iana", + extensions: ["fst"] + }, + "image/vnd.fujixerox.edmics-mmr": { + source: "iana", + extensions: ["mmr"] + }, + "image/vnd.fujixerox.edmics-rlc": { + source: "iana", + extensions: ["rlc"] + }, + "image/vnd.globalgraphics.pgb": { + source: "iana" + }, + "image/vnd.microsoft.icon": { + source: "iana", + compressible: true, + extensions: ["ico"] + }, + "image/vnd.mix": { + source: "iana" + }, + "image/vnd.mozilla.apng": { + source: "iana" + }, + "image/vnd.ms-dds": { + compressible: true, + extensions: ["dds"] + }, + "image/vnd.ms-modi": { + source: "iana", + extensions: ["mdi"] + }, + "image/vnd.ms-photo": { + source: "apache", + extensions: ["wdp"] + }, + "image/vnd.net-fpx": { + source: "iana", + extensions: ["npx"] + }, + "image/vnd.pco.b16": { + source: "iana", + extensions: ["b16"] + }, + "image/vnd.radiance": { + source: "iana" + }, + "image/vnd.sealed.png": { + source: "iana" + }, + "image/vnd.sealedmedia.softseal.gif": { + source: "iana" + }, + "image/vnd.sealedmedia.softseal.jpg": { + source: "iana" + }, + "image/vnd.svf": { + source: "iana" + }, + "image/vnd.tencent.tap": { + source: "iana", + extensions: ["tap"] + }, + "image/vnd.valve.source.texture": { + source: "iana", + extensions: ["vtf"] + }, + "image/vnd.wap.wbmp": { + source: "iana", + extensions: ["wbmp"] + }, + "image/vnd.xiff": { + source: "iana", + extensions: ["xif"] + }, + "image/vnd.zbrush.pcx": { + source: "iana", + extensions: ["pcx"] + }, + "image/webp": { + source: "apache", + extensions: ["webp"] + }, + "image/wmf": { + source: "iana", + extensions: ["wmf"] + }, + "image/x-3ds": { + source: "apache", + extensions: ["3ds"] + }, + "image/x-cmu-raster": { + source: "apache", + extensions: ["ras"] + }, + "image/x-cmx": { + source: "apache", + extensions: ["cmx"] + }, + "image/x-freehand": { + source: "apache", + extensions: ["fh", "fhc", "fh4", "fh5", "fh7"] + }, + "image/x-icon": { + source: "apache", + compressible: true, + extensions: ["ico"] + }, + "image/x-jng": { + source: "nginx", + extensions: ["jng"] + }, + "image/x-mrsid-image": { + source: "apache", + extensions: ["sid"] + }, + "image/x-ms-bmp": { + source: "nginx", + compressible: true, + extensions: ["bmp"] + }, + "image/x-pcx": { + source: "apache", + extensions: ["pcx"] + }, + "image/x-pict": { + source: "apache", + extensions: ["pic", "pct"] + }, + "image/x-portable-anymap": { + source: "apache", + extensions: ["pnm"] + }, + "image/x-portable-bitmap": { + source: "apache", + extensions: ["pbm"] + }, + "image/x-portable-graymap": { + source: "apache", + extensions: ["pgm"] + }, + "image/x-portable-pixmap": { + source: "apache", + extensions: ["ppm"] + }, + "image/x-rgb": { + source: "apache", + extensions: ["rgb"] + }, + "image/x-tga": { + source: "apache", + extensions: ["tga"] + }, + "image/x-xbitmap": { + source: "apache", + extensions: ["xbm"] + }, + "image/x-xcf": { + compressible: false + }, + "image/x-xpixmap": { + source: "apache", + extensions: ["xpm"] + }, + "image/x-xwindowdump": { + source: "apache", + extensions: ["xwd"] + }, + "message/cpim": { + source: "iana" + }, + "message/delivery-status": { + source: "iana" + }, + "message/disposition-notification": { + source: "iana", + extensions: [ + "disposition-notification" + ] + }, + "message/external-body": { + source: "iana" + }, + "message/feedback-report": { + source: "iana" + }, + "message/global": { + source: "iana", + extensions: ["u8msg"] + }, + "message/global-delivery-status": { + source: "iana", + extensions: ["u8dsn"] + }, + "message/global-disposition-notification": { + source: "iana", + extensions: ["u8mdn"] + }, + "message/global-headers": { + source: "iana", + extensions: ["u8hdr"] + }, + "message/http": { + source: "iana", + compressible: false + }, + "message/imdn+xml": { + source: "iana", + compressible: true + }, + "message/news": { + source: "iana" + }, + "message/partial": { + source: "iana", + compressible: false + }, + "message/rfc822": { + source: "iana", + compressible: true, + extensions: ["eml", "mime"] + }, + "message/s-http": { + source: "iana" + }, + "message/sip": { + source: "iana" + }, + "message/sipfrag": { + source: "iana" + }, + "message/tracking-status": { + source: "iana" + }, + "message/vnd.si.simp": { + source: "iana" + }, + "message/vnd.wfa.wsc": { + source: "iana", + extensions: ["wsc"] + }, + "model/3mf": { + source: "iana", + extensions: ["3mf"] + }, + "model/e57": { + source: "iana" + }, + "model/gltf+json": { + source: "iana", + compressible: true, + extensions: ["gltf"] + }, + "model/gltf-binary": { + source: "iana", + compressible: true, + extensions: ["glb"] + }, + "model/iges": { + source: "iana", + compressible: false, + extensions: ["igs", "iges"] + }, + "model/mesh": { + source: "iana", + compressible: false, + extensions: ["msh", "mesh", "silo"] + }, + "model/mtl": { + source: "iana", + extensions: ["mtl"] + }, + "model/obj": { + source: "iana", + extensions: ["obj"] + }, + "model/step": { + source: "iana" + }, + "model/step+xml": { + source: "iana", + compressible: true, + extensions: ["stpx"] + }, + "model/step+zip": { + source: "iana", + compressible: false, + extensions: ["stpz"] + }, + "model/step-xml+zip": { + source: "iana", + compressible: false, + extensions: ["stpxz"] + }, + "model/stl": { + source: "iana", + extensions: ["stl"] + }, + "model/vnd.collada+xml": { + source: "iana", + compressible: true, + extensions: ["dae"] + }, + "model/vnd.dwf": { + source: "iana", + extensions: ["dwf"] + }, + "model/vnd.flatland.3dml": { + source: "iana" + }, + "model/vnd.gdl": { + source: "iana", + extensions: ["gdl"] + }, + "model/vnd.gs-gdl": { + source: "apache" + }, + "model/vnd.gs.gdl": { + source: "iana" + }, + "model/vnd.gtw": { + source: "iana", + extensions: ["gtw"] + }, + "model/vnd.moml+xml": { + source: "iana", + compressible: true + }, + "model/vnd.mts": { + source: "iana", + extensions: ["mts"] + }, + "model/vnd.opengex": { + source: "iana", + extensions: ["ogex"] + }, + "model/vnd.parasolid.transmit.binary": { + source: "iana", + extensions: ["x_b"] + }, + "model/vnd.parasolid.transmit.text": { + source: "iana", + extensions: ["x_t"] + }, + "model/vnd.pytha.pyox": { + source: "iana" + }, + "model/vnd.rosette.annotated-data-model": { + source: "iana" + }, + "model/vnd.sap.vds": { + source: "iana", + extensions: ["vds"] + }, + "model/vnd.usdz+zip": { + source: "iana", + compressible: false, + extensions: ["usdz"] + }, + "model/vnd.valve.source.compiled-map": { + source: "iana", + extensions: ["bsp"] + }, + "model/vnd.vtu": { + source: "iana", + extensions: ["vtu"] + }, + "model/vrml": { + source: "iana", + compressible: false, + extensions: ["wrl", "vrml"] + }, + "model/x3d+binary": { + source: "apache", + compressible: false, + extensions: ["x3db", "x3dbz"] + }, + "model/x3d+fastinfoset": { + source: "iana", + extensions: ["x3db"] + }, + "model/x3d+vrml": { + source: "apache", + compressible: false, + extensions: ["x3dv", "x3dvz"] + }, + "model/x3d+xml": { + source: "iana", + compressible: true, + extensions: ["x3d", "x3dz"] + }, + "model/x3d-vrml": { + source: "iana", + extensions: ["x3dv"] + }, + "multipart/alternative": { + source: "iana", + compressible: false + }, + "multipart/appledouble": { + source: "iana" + }, + "multipart/byteranges": { + source: "iana" + }, + "multipart/digest": { + source: "iana" + }, + "multipart/encrypted": { + source: "iana", + compressible: false + }, + "multipart/form-data": { + source: "iana", + compressible: false + }, + "multipart/header-set": { + source: "iana" + }, + "multipart/mixed": { + source: "iana" + }, + "multipart/multilingual": { + source: "iana" + }, + "multipart/parallel": { + source: "iana" + }, + "multipart/related": { + source: "iana", + compressible: false + }, + "multipart/report": { + source: "iana" + }, + "multipart/signed": { + source: "iana", + compressible: false + }, + "multipart/vnd.bint.med-plus": { + source: "iana" + }, + "multipart/voice-message": { + source: "iana" + }, + "multipart/x-mixed-replace": { + source: "iana" + }, + "text/1d-interleaved-parityfec": { + source: "iana" + }, + "text/cache-manifest": { + source: "iana", + compressible: true, + extensions: ["appcache", "manifest"] + }, + "text/calendar": { + source: "iana", + extensions: ["ics", "ifb"] + }, + "text/calender": { + compressible: true + }, + "text/cmd": { + compressible: true + }, + "text/coffeescript": { + extensions: ["coffee", "litcoffee"] + }, + "text/cql": { + source: "iana" + }, + "text/cql-expression": { + source: "iana" + }, + "text/cql-identifier": { + source: "iana" + }, + "text/css": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["css"] + }, + "text/csv": { + source: "iana", + compressible: true, + extensions: ["csv"] + }, + "text/csv-schema": { + source: "iana" + }, + "text/directory": { + source: "iana" + }, + "text/dns": { + source: "iana" + }, + "text/ecmascript": { + source: "iana" + }, + "text/encaprtp": { + source: "iana" + }, + "text/enriched": { + source: "iana" + }, + "text/fhirpath": { + source: "iana" + }, + "text/flexfec": { + source: "iana" + }, + "text/fwdred": { + source: "iana" + }, + "text/gff3": { + source: "iana" + }, + "text/grammar-ref-list": { + source: "iana" + }, + "text/html": { + source: "iana", + compressible: true, + extensions: ["html", "htm", "shtml"] + }, + "text/jade": { + extensions: ["jade"] + }, + "text/javascript": { + source: "iana", + compressible: true + }, + "text/jcr-cnd": { + source: "iana" + }, + "text/jsx": { + compressible: true, + extensions: ["jsx"] + }, + "text/less": { + compressible: true, + extensions: ["less"] + }, + "text/markdown": { + source: "iana", + compressible: true, + extensions: ["markdown", "md"] + }, + "text/mathml": { + source: "nginx", + extensions: ["mml"] + }, + "text/mdx": { + compressible: true, + extensions: ["mdx"] + }, + "text/mizar": { + source: "iana" + }, + "text/n3": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["n3"] + }, + "text/parameters": { + source: "iana", + charset: "UTF-8" + }, + "text/parityfec": { + source: "iana" + }, + "text/plain": { + source: "iana", + compressible: true, + extensions: ["txt", "text", "conf", "def", "list", "log", "in", "ini"] + }, + "text/provenance-notation": { + source: "iana", + charset: "UTF-8" + }, + "text/prs.fallenstein.rst": { + source: "iana" + }, + "text/prs.lines.tag": { + source: "iana", + extensions: ["dsc"] + }, + "text/prs.prop.logic": { + source: "iana" + }, + "text/raptorfec": { + source: "iana" + }, + "text/red": { + source: "iana" + }, + "text/rfc822-headers": { + source: "iana" + }, + "text/richtext": { + source: "iana", + compressible: true, + extensions: ["rtx"] + }, + "text/rtf": { + source: "iana", + compressible: true, + extensions: ["rtf"] + }, + "text/rtp-enc-aescm128": { + source: "iana" + }, + "text/rtploopback": { + source: "iana" + }, + "text/rtx": { + source: "iana" + }, + "text/sgml": { + source: "iana", + extensions: ["sgml", "sgm"] + }, + "text/shaclc": { + source: "iana" + }, + "text/shex": { + source: "iana", + extensions: ["shex"] + }, + "text/slim": { + extensions: ["slim", "slm"] + }, + "text/spdx": { + source: "iana", + extensions: ["spdx"] + }, + "text/strings": { + source: "iana" + }, + "text/stylus": { + extensions: ["stylus", "styl"] + }, + "text/t140": { + source: "iana" + }, + "text/tab-separated-values": { + source: "iana", + compressible: true, + extensions: ["tsv"] + }, + "text/troff": { + source: "iana", + extensions: ["t", "tr", "roff", "man", "me", "ms"] + }, + "text/turtle": { + source: "iana", + charset: "UTF-8", + extensions: ["ttl"] + }, + "text/ulpfec": { + source: "iana" + }, + "text/uri-list": { + source: "iana", + compressible: true, + extensions: ["uri", "uris", "urls"] + }, + "text/vcard": { + source: "iana", + compressible: true, + extensions: ["vcard"] + }, + "text/vnd.a": { + source: "iana" + }, + "text/vnd.abc": { + source: "iana" + }, + "text/vnd.ascii-art": { + source: "iana" + }, + "text/vnd.curl": { + source: "iana", + extensions: ["curl"] + }, + "text/vnd.curl.dcurl": { + source: "apache", + extensions: ["dcurl"] + }, + "text/vnd.curl.mcurl": { + source: "apache", + extensions: ["mcurl"] + }, + "text/vnd.curl.scurl": { + source: "apache", + extensions: ["scurl"] + }, + "text/vnd.debian.copyright": { + source: "iana", + charset: "UTF-8" + }, + "text/vnd.dmclientscript": { + source: "iana" + }, + "text/vnd.dvb.subtitle": { + source: "iana", + extensions: ["sub"] + }, + "text/vnd.esmertec.theme-descriptor": { + source: "iana", + charset: "UTF-8" + }, + "text/vnd.familysearch.gedcom": { + source: "iana", + extensions: ["ged"] + }, + "text/vnd.ficlab.flt": { + source: "iana" + }, + "text/vnd.fly": { + source: "iana", + extensions: ["fly"] + }, + "text/vnd.fmi.flexstor": { + source: "iana", + extensions: ["flx"] + }, + "text/vnd.gml": { + source: "iana" + }, + "text/vnd.graphviz": { + source: "iana", + extensions: ["gv"] + }, + "text/vnd.hans": { + source: "iana" + }, + "text/vnd.hgl": { + source: "iana" + }, + "text/vnd.in3d.3dml": { + source: "iana", + extensions: ["3dml"] + }, + "text/vnd.in3d.spot": { + source: "iana", + extensions: ["spot"] + }, + "text/vnd.iptc.newsml": { + source: "iana" + }, + "text/vnd.iptc.nitf": { + source: "iana" + }, + "text/vnd.latex-z": { + source: "iana" + }, + "text/vnd.motorola.reflex": { + source: "iana" + }, + "text/vnd.ms-mediapackage": { + source: "iana" + }, + "text/vnd.net2phone.commcenter.command": { + source: "iana" + }, + "text/vnd.radisys.msml-basic-layout": { + source: "iana" + }, + "text/vnd.senx.warpscript": { + source: "iana" + }, + "text/vnd.si.uricatalogue": { + source: "iana" + }, + "text/vnd.sosi": { + source: "iana" + }, + "text/vnd.sun.j2me.app-descriptor": { + source: "iana", + charset: "UTF-8", + extensions: ["jad"] + }, + "text/vnd.trolltech.linguist": { + source: "iana", + charset: "UTF-8" + }, + "text/vnd.wap.si": { + source: "iana" + }, + "text/vnd.wap.sl": { + source: "iana" + }, + "text/vnd.wap.wml": { + source: "iana", + extensions: ["wml"] + }, + "text/vnd.wap.wmlscript": { + source: "iana", + extensions: ["wmls"] + }, + "text/vtt": { + source: "iana", + charset: "UTF-8", + compressible: true, + extensions: ["vtt"] + }, + "text/x-asm": { + source: "apache", + extensions: ["s", "asm"] + }, + "text/x-c": { + source: "apache", + extensions: ["c", "cc", "cxx", "cpp", "h", "hh", "dic"] + }, + "text/x-component": { + source: "nginx", + extensions: ["htc"] + }, + "text/x-fortran": { + source: "apache", + extensions: ["f", "for", "f77", "f90"] + }, + "text/x-gwt-rpc": { + compressible: true + }, + "text/x-handlebars-template": { + extensions: ["hbs"] + }, + "text/x-java-source": { + source: "apache", + extensions: ["java"] + }, + "text/x-jquery-tmpl": { + compressible: true + }, + "text/x-lua": { + extensions: ["lua"] + }, + "text/x-markdown": { + compressible: true, + extensions: ["mkd"] + }, + "text/x-nfo": { + source: "apache", + extensions: ["nfo"] + }, + "text/x-opml": { + source: "apache", + extensions: ["opml"] + }, + "text/x-org": { + compressible: true, + extensions: ["org"] + }, + "text/x-pascal": { + source: "apache", + extensions: ["p", "pas"] + }, + "text/x-processing": { + compressible: true, + extensions: ["pde"] + }, + "text/x-sass": { + extensions: ["sass"] + }, + "text/x-scss": { + extensions: ["scss"] + }, + "text/x-setext": { + source: "apache", + extensions: ["etx"] + }, + "text/x-sfv": { + source: "apache", + extensions: ["sfv"] + }, + "text/x-suse-ymp": { + compressible: true, + extensions: ["ymp"] + }, + "text/x-uuencode": { + source: "apache", + extensions: ["uu"] + }, + "text/x-vcalendar": { + source: "apache", + extensions: ["vcs"] + }, + "text/x-vcard": { + source: "apache", + extensions: ["vcf"] + }, + "text/xml": { + source: "iana", + compressible: true, + extensions: ["xml"] + }, + "text/xml-external-parsed-entity": { + source: "iana" + }, + "text/yaml": { + compressible: true, + extensions: ["yaml", "yml"] + }, + "video/1d-interleaved-parityfec": { + source: "iana" + }, + "video/3gpp": { + source: "iana", + extensions: ["3gp", "3gpp"] + }, + "video/3gpp-tt": { + source: "iana" + }, + "video/3gpp2": { + source: "iana", + extensions: ["3g2"] + }, + "video/av1": { + source: "iana" + }, + "video/bmpeg": { + source: "iana" + }, + "video/bt656": { + source: "iana" + }, + "video/celb": { + source: "iana" + }, + "video/dv": { + source: "iana" + }, + "video/encaprtp": { + source: "iana" + }, + "video/ffv1": { + source: "iana" + }, + "video/flexfec": { + source: "iana" + }, + "video/h261": { + source: "iana", + extensions: ["h261"] + }, + "video/h263": { + source: "iana", + extensions: ["h263"] + }, + "video/h263-1998": { + source: "iana" + }, + "video/h263-2000": { + source: "iana" + }, + "video/h264": { + source: "iana", + extensions: ["h264"] + }, + "video/h264-rcdo": { + source: "iana" + }, + "video/h264-svc": { + source: "iana" + }, + "video/h265": { + source: "iana" + }, + "video/iso.segment": { + source: "iana", + extensions: ["m4s"] + }, + "video/jpeg": { + source: "iana", + extensions: ["jpgv"] + }, + "video/jpeg2000": { + source: "iana" + }, + "video/jpm": { + source: "apache", + extensions: ["jpm", "jpgm"] + }, + "video/jxsv": { + source: "iana" + }, + "video/mj2": { + source: "iana", + extensions: ["mj2", "mjp2"] + }, + "video/mp1s": { + source: "iana" + }, + "video/mp2p": { + source: "iana" + }, + "video/mp2t": { + source: "iana", + extensions: ["ts"] + }, + "video/mp4": { + source: "iana", + compressible: false, + extensions: ["mp4", "mp4v", "mpg4"] + }, + "video/mp4v-es": { + source: "iana" + }, + "video/mpeg": { + source: "iana", + compressible: false, + extensions: ["mpeg", "mpg", "mpe", "m1v", "m2v"] + }, + "video/mpeg4-generic": { + source: "iana" + }, + "video/mpv": { + source: "iana" + }, + "video/nv": { + source: "iana" + }, + "video/ogg": { + source: "iana", + compressible: false, + extensions: ["ogv"] + }, + "video/parityfec": { + source: "iana" + }, + "video/pointer": { + source: "iana" + }, + "video/quicktime": { + source: "iana", + compressible: false, + extensions: ["qt", "mov"] + }, + "video/raptorfec": { + source: "iana" + }, + "video/raw": { + source: "iana" + }, + "video/rtp-enc-aescm128": { + source: "iana" + }, + "video/rtploopback": { + source: "iana" + }, + "video/rtx": { + source: "iana" + }, + "video/scip": { + source: "iana" + }, + "video/smpte291": { + source: "iana" + }, + "video/smpte292m": { + source: "iana" + }, + "video/ulpfec": { + source: "iana" + }, + "video/vc1": { + source: "iana" + }, + "video/vc2": { + source: "iana" + }, + "video/vnd.cctv": { + source: "iana" + }, + "video/vnd.dece.hd": { + source: "iana", + extensions: ["uvh", "uvvh"] + }, + "video/vnd.dece.mobile": { + source: "iana", + extensions: ["uvm", "uvvm"] + }, + "video/vnd.dece.mp4": { + source: "iana" + }, + "video/vnd.dece.pd": { + source: "iana", + extensions: ["uvp", "uvvp"] + }, + "video/vnd.dece.sd": { + source: "iana", + extensions: ["uvs", "uvvs"] + }, + "video/vnd.dece.video": { + source: "iana", + extensions: ["uvv", "uvvv"] + }, + "video/vnd.directv.mpeg": { + source: "iana" + }, + "video/vnd.directv.mpeg-tts": { + source: "iana" + }, + "video/vnd.dlna.mpeg-tts": { + source: "iana" + }, + "video/vnd.dvb.file": { + source: "iana", + extensions: ["dvb"] + }, + "video/vnd.fvt": { + source: "iana", + extensions: ["fvt"] + }, + "video/vnd.hns.video": { + source: "iana" + }, + "video/vnd.iptvforum.1dparityfec-1010": { + source: "iana" + }, + "video/vnd.iptvforum.1dparityfec-2005": { + source: "iana" + }, + "video/vnd.iptvforum.2dparityfec-1010": { + source: "iana" + }, + "video/vnd.iptvforum.2dparityfec-2005": { + source: "iana" + }, + "video/vnd.iptvforum.ttsavc": { + source: "iana" + }, + "video/vnd.iptvforum.ttsmpeg2": { + source: "iana" + }, + "video/vnd.motorola.video": { + source: "iana" + }, + "video/vnd.motorola.videop": { + source: "iana" + }, + "video/vnd.mpegurl": { + source: "iana", + extensions: ["mxu", "m4u"] + }, + "video/vnd.ms-playready.media.pyv": { + source: "iana", + extensions: ["pyv"] + }, + "video/vnd.nokia.interleaved-multimedia": { + source: "iana" + }, + "video/vnd.nokia.mp4vr": { + source: "iana" + }, + "video/vnd.nokia.videovoip": { + source: "iana" + }, + "video/vnd.objectvideo": { + source: "iana" + }, + "video/vnd.radgamettools.bink": { + source: "iana" + }, + "video/vnd.radgamettools.smacker": { + source: "iana" + }, + "video/vnd.sealed.mpeg1": { + source: "iana" + }, + "video/vnd.sealed.mpeg4": { + source: "iana" + }, + "video/vnd.sealed.swf": { + source: "iana" + }, + "video/vnd.sealedmedia.softseal.mov": { + source: "iana" + }, + "video/vnd.uvvu.mp4": { + source: "iana", + extensions: ["uvu", "uvvu"] + }, + "video/vnd.vivo": { + source: "iana", + extensions: ["viv"] + }, + "video/vnd.youtube.yt": { + source: "iana" + }, + "video/vp8": { + source: "iana" + }, + "video/vp9": { + source: "iana" + }, + "video/webm": { + source: "apache", + compressible: false, + extensions: ["webm"] + }, + "video/x-f4v": { + source: "apache", + extensions: ["f4v"] + }, + "video/x-fli": { + source: "apache", + extensions: ["fli"] + }, + "video/x-flv": { + source: "apache", + compressible: false, + extensions: ["flv"] + }, + "video/x-m4v": { + source: "apache", + extensions: ["m4v"] + }, + "video/x-matroska": { + source: "apache", + compressible: false, + extensions: ["mkv", "mk3d", "mks"] + }, + "video/x-mng": { + source: "apache", + extensions: ["mng"] + }, + "video/x-ms-asf": { + source: "apache", + extensions: ["asf", "asx"] + }, + "video/x-ms-vob": { + source: "apache", + extensions: ["vob"] + }, + "video/x-ms-wm": { + source: "apache", + extensions: ["wm"] + }, + "video/x-ms-wmv": { + source: "apache", + compressible: false, + extensions: ["wmv"] + }, + "video/x-ms-wmx": { + source: "apache", + extensions: ["wmx"] + }, + "video/x-ms-wvx": { + source: "apache", + extensions: ["wvx"] + }, + "video/x-msvideo": { + source: "apache", + extensions: ["avi"] + }, + "video/x-sgi-movie": { + source: "apache", + extensions: ["movie"] + }, + "video/x-smv": { + source: "apache", + extensions: ["smv"] + }, + "x-conference/x-cooltalk": { + source: "apache", + extensions: ["ice"] + }, + "x-shader/x-fragment": { + compressible: true + }, + "x-shader/x-vertex": { + compressible: true + } + }; +}); + +// node_modules/mime-db/index.js +var require_mime_db = __commonJS((exports2, module2) => { + /*! + * mime-db + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015-2022 Douglas Christopher Wilson + * MIT Licensed + */ + module2.exports = require_db(); +}); + +// node_modules/mime-types/index.js +var require_mime_types = __commonJS((exports2) => { + /*! + * mime-types + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + var db = require_mime_db(); + var extname = require("path").extname; + var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/; + var TEXT_TYPE_REGEXP = /^text\//i; + exports2.charset = charset; + exports2.charsets = { lookup: charset }; + exports2.contentType = contentType; + exports2.extension = extension; + exports2.extensions = Object.create(null); + exports2.lookup = lookup; + exports2.types = Object.create(null); + populateMaps(exports2.extensions, exports2.types); + function charset(type) { + if (!type || typeof type !== "string") { + return false; + } + var match = EXTRACT_TYPE_REGEXP.exec(type); + var mime = match && db[match[1].toLowerCase()]; + if (mime && mime.charset) { + return mime.charset; + } + if (match && TEXT_TYPE_REGEXP.test(match[1])) { + return "UTF-8"; + } + return false; + } + function contentType(str) { + if (!str || typeof str !== "string") { + return false; + } + var mime = str.indexOf("/") === -1 ? exports2.lookup(str) : str; + if (!mime) { + return false; + } + if (mime.indexOf("charset") === -1) { + var charset2 = exports2.charset(mime); + if (charset2) + mime += "; charset=" + charset2.toLowerCase(); + } + return mime; + } + function extension(type) { + if (!type || typeof type !== "string") { + return false; + } + var match = EXTRACT_TYPE_REGEXP.exec(type); + var exts = match && exports2.extensions[match[1].toLowerCase()]; + if (!exts || !exts.length) { + return false; + } + return exts[0]; + } + function lookup(path) { + if (!path || typeof path !== "string") { + return false; + } + var extension2 = extname("x." + path).toLowerCase().substr(1); + if (!extension2) { + return false; + } + return exports2.types[extension2] || false; + } + function populateMaps(extensions, types) { + var preference = ["nginx", "apache", undefined, "iana"]; + Object.keys(db).forEach(function forEachMimeType(type) { + var mime = db[type]; + var exts = mime.extensions; + if (!exts || !exts.length) { + return; + } + extensions[type] = exts; + for (var i = 0;i < exts.length; i++) { + var extension2 = exts[i]; + if (types[extension2]) { + var from = preference.indexOf(db[types[extension2]].source); + var to = preference.indexOf(mime.source); + if (types[extension2] !== "application/octet-stream" && (from > to || from === to && types[extension2].substr(0, 12) === "application/")) { + continue; + } + } + types[extension2] = type; + } + }); + } +}); + +// node_modules/accepts/index.js +var require_accepts = __commonJS((exports2, module2) => { + /*! + * accepts + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + var Negotiator = require_negotiator(); + var mime = require_mime_types(); + module2.exports = Accepts; + function Accepts(req) { + if (!(this instanceof Accepts)) { + return new Accepts(req); + } + this.headers = req.headers; + this.negotiator = new Negotiator(req); + } + Accepts.prototype.type = Accepts.prototype.types = function(types_) { + var types = types_; + if (types && !Array.isArray(types)) { + types = new Array(arguments.length); + for (var i = 0;i < types.length; i++) { + types[i] = arguments[i]; + } + } + if (!types || types.length === 0) { + return this.negotiator.mediaTypes(); + } + if (!this.headers.accept) { + return types[0]; + } + var mimes = types.map(extToMime); + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)); + var first = accepts[0]; + return first ? types[mimes.indexOf(first)] : false; + }; + Accepts.prototype.encoding = Accepts.prototype.encodings = function(encodings_) { + var encodings = encodings_; + if (encodings && !Array.isArray(encodings)) { + encodings = new Array(arguments.length); + for (var i = 0;i < encodings.length; i++) { + encodings[i] = arguments[i]; + } + } + if (!encodings || encodings.length === 0) { + return this.negotiator.encodings(); + } + return this.negotiator.encodings(encodings)[0] || false; + }; + Accepts.prototype.charset = Accepts.prototype.charsets = function(charsets_) { + var charsets = charsets_; + if (charsets && !Array.isArray(charsets)) { + charsets = new Array(arguments.length); + for (var i = 0;i < charsets.length; i++) { + charsets[i] = arguments[i]; + } + } + if (!charsets || charsets.length === 0) { + return this.negotiator.charsets(); + } + return this.negotiator.charsets(charsets)[0] || false; + }; + Accepts.prototype.lang = Accepts.prototype.langs = Accepts.prototype.language = Accepts.prototype.languages = function(languages_) { + var languages = languages_; + if (languages && !Array.isArray(languages)) { + languages = new Array(arguments.length); + for (var i = 0;i < languages.length; i++) { + languages[i] = arguments[i]; + } + } + if (!languages || languages.length === 0) { + return this.negotiator.languages(); + } + return this.negotiator.languages(languages)[0] || false; + }; + function extToMime(type) { + return type.indexOf("/") === -1 ? mime.lookup(type) : type; + } + function validMime(type) { + return typeof type === "string"; + } +}); + +// node_modules/base64id/lib/base64id.js +var require_base64id = __commonJS((exports2, module2) => { + /*! + * base64id v0.1.0 + */ + var crypto = require("crypto"); + var Base64Id = function() {}; + Base64Id.prototype.getRandomBytes = function(bytes) { + var BUFFER_SIZE = 4096; + var self = this; + bytes = bytes || 12; + if (bytes > BUFFER_SIZE) { + return crypto.randomBytes(bytes); + } + var bytesInBuffer = parseInt(BUFFER_SIZE / bytes); + var threshold = parseInt(bytesInBuffer * 0.85); + if (!threshold) { + return crypto.randomBytes(bytes); + } + if (this.bytesBufferIndex == null) { + this.bytesBufferIndex = -1; + } + if (this.bytesBufferIndex == bytesInBuffer) { + this.bytesBuffer = null; + this.bytesBufferIndex = -1; + } + if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) { + if (!this.isGeneratingBytes) { + this.isGeneratingBytes = true; + crypto.randomBytes(BUFFER_SIZE, function(err, bytes2) { + self.bytesBuffer = bytes2; + self.bytesBufferIndex = 0; + self.isGeneratingBytes = false; + }); + } + if (this.bytesBufferIndex == -1) { + return crypto.randomBytes(bytes); + } + } + var result = this.bytesBuffer.slice(bytes * this.bytesBufferIndex, bytes * (this.bytesBufferIndex + 1)); + this.bytesBufferIndex++; + return result; + }; + Base64Id.prototype.generateId = function() { + var rand = Buffer.alloc(15); + if (!rand.writeInt32BE) { + return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); + } + this.sequenceNumber = this.sequenceNumber + 1 | 0; + rand.writeInt32BE(this.sequenceNumber, 11); + if (crypto.randomBytes) { + this.getRandomBytes(12).copy(rand); + } else { + [0, 4, 8].forEach(function(i) { + rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); + }); + } + return rand.toString("base64").replace(/\//g, "_").replace(/\+/g, "-"); + }; + exports2 = module2.exports = new Base64Id; +}); + +// node_modules/engine.io-parser/build/cjs/commons.js +var require_commons = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ERROR_PACKET = exports2.PACKET_TYPES_REVERSE = exports2.PACKET_TYPES = undefined; + var PACKET_TYPES = Object.create(null); + exports2.PACKET_TYPES = PACKET_TYPES; + PACKET_TYPES["open"] = "0"; + PACKET_TYPES["close"] = "1"; + PACKET_TYPES["ping"] = "2"; + PACKET_TYPES["pong"] = "3"; + PACKET_TYPES["message"] = "4"; + PACKET_TYPES["upgrade"] = "5"; + PACKET_TYPES["noop"] = "6"; + var PACKET_TYPES_REVERSE = Object.create(null); + exports2.PACKET_TYPES_REVERSE = PACKET_TYPES_REVERSE; + Object.keys(PACKET_TYPES).forEach((key) => { + PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key; + }); + var ERROR_PACKET = { type: "error", data: "parser error" }; + exports2.ERROR_PACKET = ERROR_PACKET; +}); + +// node_modules/engine.io-parser/build/cjs/encodePacket.js +var require_encodePacket = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.encodePacket = undefined; + exports2.encodePacketToBinary = encodePacketToBinary; + var commons_js_1 = require_commons(); + var encodePacket = ({ type, data }, supportsBinary, callback) => { + if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) { + return callback(supportsBinary ? data : "b" + toBuffer(data, true).toString("base64")); + } + return callback(commons_js_1.PACKET_TYPES[type] + (data || "")); + }; + exports2.encodePacket = encodePacket; + var toBuffer = (data, forceBufferConversion) => { + if (Buffer.isBuffer(data) || data instanceof Uint8Array && !forceBufferConversion) { + return data; + } else if (data instanceof ArrayBuffer) { + return Buffer.from(data); + } else { + return Buffer.from(data.buffer, data.byteOffset, data.byteLength); + } + }; + var TEXT_ENCODER; + function encodePacketToBinary(packet, callback) { + if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) { + return callback(toBuffer(packet.data, false)); + } + (0, exports2.encodePacket)(packet, true, (encoded) => { + if (!TEXT_ENCODER) { + TEXT_ENCODER = new TextEncoder; + } + callback(TEXT_ENCODER.encode(encoded)); + }); + } +}); + +// node_modules/engine.io-parser/build/cjs/decodePacket.js +var require_decodePacket = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.decodePacket = undefined; + var commons_js_1 = require_commons(); + var decodePacket = (encodedPacket, binaryType) => { + if (typeof encodedPacket !== "string") { + return { + type: "message", + data: mapBinary(encodedPacket, binaryType) + }; + } + const type = encodedPacket.charAt(0); + if (type === "b") { + const buffer = Buffer.from(encodedPacket.substring(1), "base64"); + return { + type: "message", + data: mapBinary(buffer, binaryType) + }; + } + if (!commons_js_1.PACKET_TYPES_REVERSE[type]) { + return commons_js_1.ERROR_PACKET; + } + return encodedPacket.length > 1 ? { + type: commons_js_1.PACKET_TYPES_REVERSE[type], + data: encodedPacket.substring(1) + } : { + type: commons_js_1.PACKET_TYPES_REVERSE[type] + }; + }; + exports2.decodePacket = decodePacket; + var mapBinary = (data, binaryType) => { + switch (binaryType) { + case "arraybuffer": + if (data instanceof ArrayBuffer) { + return data; + } else if (Buffer.isBuffer(data)) { + return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength); + } else { + return data.buffer; + } + case "nodebuffer": + default: + if (Buffer.isBuffer(data)) { + return data; + } else { + return Buffer.from(data); + } + } + }; +}); + +// node_modules/engine.io-parser/build/cjs/index.js +var require_cjs = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.decodePayload = exports2.decodePacket = exports2.encodePayload = exports2.encodePacket = exports2.protocol = undefined; + exports2.createPacketEncoderStream = createPacketEncoderStream; + exports2.createPacketDecoderStream = createPacketDecoderStream; + var encodePacket_js_1 = require_encodePacket(); + Object.defineProperty(exports2, "encodePacket", { enumerable: true, get: function() { + return encodePacket_js_1.encodePacket; + } }); + var decodePacket_js_1 = require_decodePacket(); + Object.defineProperty(exports2, "decodePacket", { enumerable: true, get: function() { + return decodePacket_js_1.decodePacket; + } }); + var commons_js_1 = require_commons(); + var SEPARATOR = String.fromCharCode(30); + var encodePayload = (packets, callback) => { + const length = packets.length; + const encodedPackets = new Array(length); + let count = 0; + packets.forEach((packet, i) => { + (0, encodePacket_js_1.encodePacket)(packet, false, (encodedPacket) => { + encodedPackets[i] = encodedPacket; + if (++count === length) { + callback(encodedPackets.join(SEPARATOR)); + } + }); + }); + }; + exports2.encodePayload = encodePayload; + var decodePayload = (encodedPayload, binaryType) => { + const encodedPackets = encodedPayload.split(SEPARATOR); + const packets = []; + for (let i = 0;i < encodedPackets.length; i++) { + const decodedPacket = (0, decodePacket_js_1.decodePacket)(encodedPackets[i], binaryType); + packets.push(decodedPacket); + if (decodedPacket.type === "error") { + break; + } + } + return packets; + }; + exports2.decodePayload = decodePayload; + function createPacketEncoderStream() { + return new TransformStream({ + transform(packet, controller) { + (0, encodePacket_js_1.encodePacketToBinary)(packet, (encodedPacket) => { + const payloadLength = encodedPacket.length; + let header; + if (payloadLength < 126) { + header = new Uint8Array(1); + new DataView(header.buffer).setUint8(0, payloadLength); + } else if (payloadLength < 65536) { + header = new Uint8Array(3); + const view = new DataView(header.buffer); + view.setUint8(0, 126); + view.setUint16(1, payloadLength); + } else { + header = new Uint8Array(9); + const view = new DataView(header.buffer); + view.setUint8(0, 127); + view.setBigUint64(1, BigInt(payloadLength)); + } + if (packet.data && typeof packet.data !== "string") { + header[0] |= 128; + } + controller.enqueue(header); + controller.enqueue(encodedPacket); + }); + } + }); + } + var TEXT_DECODER; + function totalLength(chunks) { + return chunks.reduce((acc, chunk) => acc + chunk.length, 0); + } + function concatChunks(chunks, size) { + if (chunks[0].length === size) { + return chunks.shift(); + } + const buffer = new Uint8Array(size); + let j = 0; + for (let i = 0;i < size; i++) { + buffer[i] = chunks[0][j++]; + if (j === chunks[0].length) { + chunks.shift(); + j = 0; + } + } + if (chunks.length && j < chunks[0].length) { + chunks[0] = chunks[0].slice(j); + } + return buffer; + } + function createPacketDecoderStream(maxPayload, binaryType) { + if (!TEXT_DECODER) { + TEXT_DECODER = new TextDecoder; + } + const chunks = []; + let state = 0; + let expectedLength = -1; + let isBinary = false; + return new TransformStream({ + transform(chunk, controller) { + chunks.push(chunk); + while (true) { + if (state === 0) { + if (totalLength(chunks) < 1) { + break; + } + const header = concatChunks(chunks, 1); + isBinary = (header[0] & 128) === 128; + expectedLength = header[0] & 127; + if (expectedLength < 126) { + state = 3; + } else if (expectedLength === 126) { + state = 1; + } else { + state = 2; + } + } else if (state === 1) { + if (totalLength(chunks) < 2) { + break; + } + const headerArray = concatChunks(chunks, 2); + expectedLength = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length).getUint16(0); + state = 3; + } else if (state === 2) { + if (totalLength(chunks) < 8) { + break; + } + const headerArray = concatChunks(chunks, 8); + const view = new DataView(headerArray.buffer, headerArray.byteOffset, headerArray.length); + const n = view.getUint32(0); + if (n > Math.pow(2, 53 - 32) - 1) { + controller.enqueue(commons_js_1.ERROR_PACKET); + break; + } + expectedLength = n * Math.pow(2, 32) + view.getUint32(4); + state = 3; + } else { + if (totalLength(chunks) < expectedLength) { + break; + } + const data = concatChunks(chunks, expectedLength); + controller.enqueue((0, decodePacket_js_1.decodePacket)(isBinary ? data : TEXT_DECODER.decode(data), binaryType)); + state = 0; + } + if (expectedLength === 0 || expectedLength > maxPayload) { + controller.enqueue(commons_js_1.ERROR_PACKET); + break; + } + } + } + }); + } + exports2.protocol = 4; +}); + +// node_modules/engine.io/build/parser-v3/utf8.js +var require_utf8 = __commonJS((exports2, module2) => { + /*! https://mths.be/utf8js v2.1.2 by @mathias */ + var stringFromCharCode = String.fromCharCode; + function ucs2decode(string) { + var output = []; + var counter = 0; + var length = string.length; + var value; + var extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 55296 && value <= 56319 && counter < length) { + extra = string.charCodeAt(counter++); + if ((extra & 64512) == 56320) { + output.push(((value & 1023) << 10) + (extra & 1023) + 65536); + } else { + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + function ucs2encode(array) { + var length = array.length; + var index = -1; + var value; + var output = ""; + while (++index < length) { + value = array[index]; + if (value > 65535) { + value -= 65536; + output += stringFromCharCode(value >>> 10 & 1023 | 55296); + value = 56320 | value & 1023; + } + output += stringFromCharCode(value); + } + return output; + } + function checkScalarValue(codePoint, strict) { + if (codePoint >= 55296 && codePoint <= 57343) { + if (strict) { + throw Error("Lone surrogate U+" + codePoint.toString(16).toUpperCase() + " is not a scalar value"); + } + return false; + } + return true; + } + function createByte(codePoint, shift) { + return stringFromCharCode(codePoint >> shift & 63 | 128); + } + function encodeCodePoint(codePoint, strict) { + if ((codePoint & 4294967168) == 0) { + return stringFromCharCode(codePoint); + } + var symbol = ""; + if ((codePoint & 4294965248) == 0) { + symbol = stringFromCharCode(codePoint >> 6 & 31 | 192); + } else if ((codePoint & 4294901760) == 0) { + if (!checkScalarValue(codePoint, strict)) { + codePoint = 65533; + } + symbol = stringFromCharCode(codePoint >> 12 & 15 | 224); + symbol += createByte(codePoint, 6); + } else if ((codePoint & 4292870144) == 0) { + symbol = stringFromCharCode(codePoint >> 18 & 7 | 240); + symbol += createByte(codePoint, 12); + symbol += createByte(codePoint, 6); + } + symbol += stringFromCharCode(codePoint & 63 | 128); + return symbol; + } + function utf8encode(string, opts) { + opts = opts || {}; + var strict = opts.strict !== false; + var codePoints = ucs2decode(string); + var length = codePoints.length; + var index = -1; + var codePoint; + var byteString = ""; + while (++index < length) { + codePoint = codePoints[index]; + byteString += encodeCodePoint(codePoint, strict); + } + return byteString; + } + function readContinuationByte() { + if (byteIndex >= byteCount) { + throw Error("Invalid byte index"); + } + var continuationByte = byteArray[byteIndex] & 255; + byteIndex++; + if ((continuationByte & 192) == 128) { + return continuationByte & 63; + } + throw Error("Invalid continuation byte"); + } + function decodeSymbol(strict) { + var byte1; + var byte2; + var byte3; + var byte4; + var codePoint; + if (byteIndex > byteCount) { + throw Error("Invalid byte index"); + } + if (byteIndex == byteCount) { + return false; + } + byte1 = byteArray[byteIndex] & 255; + byteIndex++; + if ((byte1 & 128) == 0) { + return byte1; + } + if ((byte1 & 224) == 192) { + byte2 = readContinuationByte(); + codePoint = (byte1 & 31) << 6 | byte2; + if (codePoint >= 128) { + return codePoint; + } else { + throw Error("Invalid continuation byte"); + } + } + if ((byte1 & 240) == 224) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + codePoint = (byte1 & 15) << 12 | byte2 << 6 | byte3; + if (codePoint >= 2048) { + return checkScalarValue(codePoint, strict) ? codePoint : 65533; + } else { + throw Error("Invalid continuation byte"); + } + } + if ((byte1 & 248) == 240) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + byte4 = readContinuationByte(); + codePoint = (byte1 & 7) << 18 | byte2 << 12 | byte3 << 6 | byte4; + if (codePoint >= 65536 && codePoint <= 1114111) { + return codePoint; + } + } + throw Error("Invalid UTF-8 detected"); + } + var byteArray; + var byteCount; + var byteIndex; + function utf8decode(byteString, opts) { + opts = opts || {}; + var strict = opts.strict !== false; + byteArray = ucs2decode(byteString); + byteCount = byteArray.length; + byteIndex = 0; + var codePoints = []; + var tmp; + while ((tmp = decodeSymbol(strict)) !== false) { + codePoints.push(tmp); + } + return ucs2encode(codePoints); + } + module2.exports = { + version: "2.1.2", + encode: utf8encode, + decode: utf8decode + }; +}); + +// node_modules/engine.io/build/parser-v3/index.js +var require_parser_v3 = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.packets = exports2.protocol = undefined; + exports2.encodePacket = encodePacket; + exports2.encodeBase64Packet = encodeBase64Packet; + exports2.decodePacket = decodePacket; + exports2.decodeBase64Packet = decodeBase64Packet; + exports2.encodePayload = encodePayload; + exports2.decodePayload = decodePayload; + exports2.encodePayloadAsBinary = encodePayloadAsBinary; + exports2.decodePayloadAsBinary = decodePayloadAsBinary; + var utf8 = require_utf8(); + exports2.protocol = 3; + var hasBinary = (packets) => { + for (const packet of packets) { + if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) { + return true; + } + } + return false; + }; + exports2.packets = { + open: 0, + close: 1, + ping: 2, + pong: 3, + message: 4, + upgrade: 5, + noop: 6 + }; + var packetslist = Object.keys(exports2.packets); + var err = { type: "error", data: "parser error" }; + var EMPTY_BUFFER = Buffer.concat([]); + function encodePacket(packet, supportsBinary, utf8encode, callback) { + if (typeof supportsBinary === "function") { + callback = supportsBinary; + supportsBinary = null; + } + if (typeof utf8encode === "function") { + callback = utf8encode; + utf8encode = null; + } + if (Buffer.isBuffer(packet.data)) { + return encodeBuffer(packet, supportsBinary, callback); + } else if (packet.data && (packet.data.buffer || packet.data) instanceof ArrayBuffer) { + return encodeBuffer({ type: packet.type, data: arrayBufferToBuffer(packet.data) }, supportsBinary, callback); + } + var encoded = exports2.packets[packet.type]; + if (packet.data !== undefined) { + encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data); + } + return callback("" + encoded); + } + function encodeBuffer(packet, supportsBinary, callback) { + if (!supportsBinary) { + return encodeBase64Packet(packet, callback); + } + var data = packet.data; + var typeBuffer = Buffer.allocUnsafe(1); + typeBuffer[0] = exports2.packets[packet.type]; + return callback(Buffer.concat([typeBuffer, data])); + } + function encodeBase64Packet(packet, callback) { + var data = Buffer.isBuffer(packet.data) ? packet.data : arrayBufferToBuffer(packet.data); + var message = "b" + exports2.packets[packet.type]; + message += data.toString("base64"); + return callback(message); + } + function decodePacket(data, binaryType, utf8decode) { + if (data === undefined) { + return err; + } + var type; + if (typeof data === "string") { + type = data.charAt(0); + if (type === "b") { + return decodeBase64Packet(data.slice(1), binaryType); + } + if (utf8decode) { + data = tryDecode(data); + if (data === false) { + return err; + } + } + if (Number(type) != type || !packetslist[type]) { + return err; + } + if (data.length > 1) { + return { type: packetslist[type], data: data.slice(1) }; + } else { + return { type: packetslist[type] }; + } + } + if (binaryType === "arraybuffer") { + var intArray = new Uint8Array(data); + type = intArray[0]; + return { type: packetslist[type], data: intArray.buffer.slice(1) }; + } + if (data instanceof ArrayBuffer) { + data = arrayBufferToBuffer(data); + } + type = data[0]; + return { type: packetslist[type], data: data.slice(1) }; + } + function tryDecode(data) { + try { + data = utf8.decode(data, { strict: false }); + } catch (e) { + return false; + } + return data; + } + function decodeBase64Packet(msg, binaryType) { + var type = packetslist[msg.charAt(0)]; + var data = Buffer.from(msg.slice(1), "base64"); + if (binaryType === "arraybuffer") { + var abv = new Uint8Array(data.length); + for (var i = 0;i < abv.length; i++) { + abv[i] = data[i]; + } + data = abv.buffer; + } + return { type, data }; + } + function encodePayload(packets, supportsBinary, callback) { + if (typeof supportsBinary === "function") { + callback = supportsBinary; + supportsBinary = null; + } + if (supportsBinary && hasBinary(packets)) { + return encodePayloadAsBinary(packets, callback); + } + if (!packets.length) { + return callback("0:"); + } + function encodeOne(packet, doneCallback) { + encodePacket(packet, supportsBinary, false, function(message) { + doneCallback(null, setLengthHeader(message)); + }); + } + map(packets, encodeOne, function(err2, results) { + return callback(results.join("")); + }); + } + function setLengthHeader(message) { + return message.length + ":" + message; + } + function map(ary, each, done) { + const results = new Array(ary.length); + let count = 0; + for (let i = 0;i < ary.length; i++) { + each(ary[i], (error, msg) => { + results[i] = msg; + if (++count === ary.length) { + done(null, results); + } + }); + } + } + function decodePayload(data, binaryType, callback) { + if (typeof data !== "string") { + return decodePayloadAsBinary(data, binaryType, callback); + } + if (typeof binaryType === "function") { + callback = binaryType; + binaryType = null; + } + if (data === "") { + return callback(err, 0, 1); + } + var length = "", n, msg, packet; + for (var i = 0, l = data.length;i < l; i++) { + var chr = data.charAt(i); + if (chr !== ":") { + length += chr; + continue; + } + if (length === "" || length != (n = Number(length))) { + return callback(err, 0, 1); + } + msg = data.slice(i + 1, i + 1 + n); + if (length != msg.length) { + return callback(err, 0, 1); + } + if (msg.length) { + packet = decodePacket(msg, binaryType, false); + if (err.type === packet.type && err.data === packet.data) { + return callback(err, 0, 1); + } + var more = callback(packet, i + n, l); + if (more === false) + return; + } + i += n; + length = ""; + } + if (length !== "") { + return callback(err, 0, 1); + } + } + function bufferToString(buffer) { + var str = ""; + for (var i = 0, l = buffer.length;i < l; i++) { + str += String.fromCharCode(buffer[i]); + } + return str; + } + function stringToBuffer(string) { + var buf = Buffer.allocUnsafe(string.length); + for (var i = 0, l = string.length;i < l; i++) { + buf.writeUInt8(string.charCodeAt(i), i); + } + return buf; + } + function arrayBufferToBuffer(data) { + var length = data.byteLength || data.length; + var offset = data.byteOffset || 0; + return Buffer.from(data.buffer || data, offset, length); + } + function encodePayloadAsBinary(packets, callback) { + if (!packets.length) { + return callback(EMPTY_BUFFER); + } + map(packets, encodeOneBinaryPacket, function(err2, results) { + return callback(Buffer.concat(results)); + }); + } + function encodeOneBinaryPacket(p, doneCallback) { + function onBinaryPacketEncode(packet) { + var encodingLength = "" + packet.length; + var sizeBuffer; + if (typeof packet === "string") { + sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2); + sizeBuffer[0] = 0; + for (var i = 0;i < encodingLength.length; i++) { + sizeBuffer[i + 1] = parseInt(encodingLength[i], 10); + } + sizeBuffer[sizeBuffer.length - 1] = 255; + return doneCallback(null, Buffer.concat([sizeBuffer, stringToBuffer(packet)])); + } + sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2); + sizeBuffer[0] = 1; + for (var i = 0;i < encodingLength.length; i++) { + sizeBuffer[i + 1] = parseInt(encodingLength[i], 10); + } + sizeBuffer[sizeBuffer.length - 1] = 255; + doneCallback(null, Buffer.concat([sizeBuffer, packet])); + } + encodePacket(p, true, true, onBinaryPacketEncode); + } + function decodePayloadAsBinary(data, binaryType, callback) { + if (typeof binaryType === "function") { + callback = binaryType; + binaryType = null; + } + var bufferTail = data; + var buffers = []; + var i; + while (bufferTail.length > 0) { + var strLen = ""; + var isString = bufferTail[0] === 0; + for (i = 1;; i++) { + if (bufferTail[i] === 255) + break; + if (strLen.length > 310) { + return callback(err, 0, 1); + } + strLen += "" + bufferTail[i]; + } + bufferTail = bufferTail.slice(strLen.length + 1); + var msgLength = parseInt(strLen, 10); + var msg = bufferTail.slice(1, msgLength + 1); + if (isString) + msg = bufferToString(msg); + buffers.push(msg); + bufferTail = bufferTail.slice(msgLength + 1); + } + var total = buffers.length; + for (i = 0;i < total; i++) { + var buffer = buffers[i]; + callback(decodePacket(buffer, binaryType, true), i, total); + } + } +}); + +// node_modules/ms/index.js +var require_ms = __commonJS((exports2, module2) => { + var s = 1000; + var m = s * 60; + var h = m * 60; + var d = h * 24; + var w = d * 7; + var y = d * 365.25; + module2.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === "string" && val.length > 0) { + return parse(val); + } else if (type === "number" && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error("val is not a non-empty string or a valid number. val=" + JSON.stringify(val)); + }; + function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || "ms").toLowerCase(); + switch (type) { + case "years": + case "year": + case "yrs": + case "yr": + case "y": + return n * y; + case "weeks": + case "week": + case "w": + return n * w; + case "days": + case "day": + case "d": + return n * d; + case "hours": + case "hour": + case "hrs": + case "hr": + case "h": + return n * h; + case "minutes": + case "minute": + case "mins": + case "min": + case "m": + return n * m; + case "seconds": + case "second": + case "secs": + case "sec": + case "s": + return n * s; + case "milliseconds": + case "millisecond": + case "msecs": + case "msec": + case "ms": + return n; + default: + return; + } + } + function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + "d"; + } + if (msAbs >= h) { + return Math.round(ms / h) + "h"; + } + if (msAbs >= m) { + return Math.round(ms / m) + "m"; + } + if (msAbs >= s) { + return Math.round(ms / s) + "s"; + } + return ms + "ms"; + } + function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, "day"); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, "hour"); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, "minute"); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, "second"); + } + return ms + " ms"; + } + function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + " " + name + (isPlural ? "s" : ""); + } +}); + +// node_modules/debug/src/common.js +var require_common = __commonJS((exports2, module2) => { + function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = require_ms(); + createDebug.destroy = destroy; + Object.keys(env).forEach((key) => { + createDebug[key] = env[key]; + }); + createDebug.names = []; + createDebug.skips = []; + createDebug.formatters = {}; + function selectColor(namespace) { + let hash = 0; + for (let i = 0;i < namespace.length; i++) { + hash = (hash << 5) - hash + namespace.charCodeAt(i); + hash |= 0; + } + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + function debug(...args) { + if (!debug.enabled) { + return; + } + const self = debug; + const curr = Number(new Date); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + args[0] = createDebug.coerce(args[0]); + if (typeof args[0] !== "string") { + args.unshift("%O"); + } + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + if (match === "%%") { + return "%"; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === "function") { + const val = args[index]; + match = formatter.call(self, val); + args.splice(index, 1); + index--; + } + return match; + }); + createDebug.formatArgs.call(self, args); + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; + Object.defineProperty(debug, "enabled", { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + return enabledCache; + }, + set: (v) => { + enableOverride = v; + } + }); + if (typeof createDebug.init === "function") { + createDebug.init(debug); + } + return debug; + } + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = namespaces; + createDebug.names = []; + createDebug.skips = []; + let i; + const split = (typeof namespaces === "string" ? namespaces : "").split(/[\s,]+/); + const len = split.length; + for (i = 0;i < len; i++) { + if (!split[i]) { + continue; + } + namespaces = split[i].replace(/\*/g, ".*?"); + if (namespaces[0] === "-") { + createDebug.skips.push(new RegExp("^" + namespaces.slice(1) + "$")); + } else { + createDebug.names.push(new RegExp("^" + namespaces + "$")); + } + } + } + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map((namespace) => "-" + namespace) + ].join(","); + createDebug.enable(""); + return namespaces; + } + function enabled(name) { + if (name[name.length - 1] === "*") { + return true; + } + let i; + let len; + for (i = 0, len = createDebug.skips.length;i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = createDebug.names.length;i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + return false; + } + function toNamespace(regexp) { + return regexp.toString().substring(2, regexp.toString().length - 2).replace(/\.\*\?$/, "*"); + } + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + function destroy() { + console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); + } + createDebug.enable(createDebug.load()); + return createDebug; + } + module2.exports = setup; +}); + +// node_modules/debug/src/browser.js +var require_browser = __commonJS((exports2, module2) => { + exports2.formatArgs = formatArgs; + exports2.save = save; + exports2.load = load; + exports2.useColors = useColors; + exports2.storage = localstorage(); + exports2.destroy = (() => { + let warned = false; + return () => { + if (!warned) { + warned = true; + console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); + } + }; + })(); + exports2.colors = [ + "#0000CC", + "#0000FF", + "#0033CC", + "#0033FF", + "#0066CC", + "#0066FF", + "#0099CC", + "#0099FF", + "#00CC00", + "#00CC33", + "#00CC66", + "#00CC99", + "#00CCCC", + "#00CCFF", + "#3300CC", + "#3300FF", + "#3333CC", + "#3333FF", + "#3366CC", + "#3366FF", + "#3399CC", + "#3399FF", + "#33CC00", + "#33CC33", + "#33CC66", + "#33CC99", + "#33CCCC", + "#33CCFF", + "#6600CC", + "#6600FF", + "#6633CC", + "#6633FF", + "#66CC00", + "#66CC33", + "#9900CC", + "#9900FF", + "#9933CC", + "#9933FF", + "#99CC00", + "#99CC33", + "#CC0000", + "#CC0033", + "#CC0066", + "#CC0099", + "#CC00CC", + "#CC00FF", + "#CC3300", + "#CC3333", + "#CC3366", + "#CC3399", + "#CC33CC", + "#CC33FF", + "#CC6600", + "#CC6633", + "#CC9900", + "#CC9933", + "#CCCC00", + "#CCCC33", + "#FF0000", + "#FF0033", + "#FF0066", + "#FF0099", + "#FF00CC", + "#FF00FF", + "#FF3300", + "#FF3333", + "#FF3366", + "#FF3399", + "#FF33CC", + "#FF33FF", + "#FF6600", + "#FF6633", + "#FF9900", + "#FF9933", + "#FFCC00", + "#FFCC33" + ]; + function useColors() { + if (typeof window !== "undefined" && window.process && (window.process.type === "renderer" || window.process.__nwjs)) { + return true; + } + if (typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + let m; + return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || typeof navigator !== "undefined" && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31 || typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/); + } + function formatArgs(args) { + args[0] = (this.useColors ? "%c" : "") + this.namespace + (this.useColors ? " %c" : " ") + args[0] + (this.useColors ? "%c " : " ") + "+" + module2.exports.humanize(this.diff); + if (!this.useColors) { + return; + } + const c = "color: " + this.color; + args.splice(1, 0, c, "color: inherit"); + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, (match) => { + if (match === "%%") { + return; + } + index++; + if (match === "%c") { + lastC = index; + } + }); + args.splice(lastC, 0, c); + } + exports2.log = console.debug || console.log || (() => {}); + function save(namespaces) { + try { + if (namespaces) { + exports2.storage.setItem("debug", namespaces); + } else { + exports2.storage.removeItem("debug"); + } + } catch (error) {} + } + function load() { + let r; + try { + r = exports2.storage.getItem("debug"); + } catch (error) {} + if (!r && typeof process !== "undefined" && "env" in process) { + r = process.env.DEBUG; + } + return r; + } + function localstorage() { + try { + return localStorage; + } catch (error) {} + } + module2.exports = require_common()(exports2); + var { formatters } = module2.exports; + formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (error) { + return "[UnexpectedJSONParseError]: " + error.message; + } + }; +}); + +// node_modules/debug/src/node.js +var require_node = __commonJS((exports2, module2) => { + var tty = require("tty"); + var util = require("util"); + exports2.init = init; + exports2.log = log; + exports2.formatArgs = formatArgs; + exports2.save = save; + exports2.load = load; + exports2.useColors = useColors; + exports2.destroy = util.deprecate(() => {}, "Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."); + exports2.colors = [6, 2, 3, 4, 5, 1]; + try { + const supportsColor = (()=>{throw new Error("Cannot require module "+"supports-color");})(); + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports2.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } + } catch (error) {} + exports2.inspectOpts = Object.keys(process.env).filter((key) => { + return /^debug_/i.test(key); + }).reduce((obj, key) => { + const prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === "null") { + val = null; + } else { + val = Number(val); + } + obj[prop] = val; + return obj; + }, {}); + function useColors() { + return "colors" in exports2.inspectOpts ? Boolean(exports2.inspectOpts.colors) : tty.isatty(process.stderr.fd); + } + function formatArgs(args) { + const { namespace: name, useColors: useColors2 } = this; + if (useColors2) { + const c = this.color; + const colorCode = "\x1B[3" + (c < 8 ? c : "8;5;" + c); + const prefix = ` ${colorCode};1m${name} \x1B[0m`; + args[0] = prefix + args[0].split(` +`).join(` +` + prefix); + args.push(colorCode + "m+" + module2.exports.humanize(this.diff) + "\x1B[0m"); + } else { + args[0] = getDate() + name + " " + args[0]; + } + } + function getDate() { + if (exports2.inspectOpts.hideDate) { + return ""; + } + return new Date().toISOString() + " "; + } + function log(...args) { + return process.stderr.write(util.formatWithOptions(exports2.inspectOpts, ...args) + ` +`); + } + function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + delete process.env.DEBUG; + } + } + function load() { + return process.env.DEBUG; + } + function init(debug) { + debug.inspectOpts = {}; + const keys = Object.keys(exports2.inspectOpts); + for (let i = 0;i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]]; + } + } + module2.exports = require_common()(exports2); + var { formatters } = module2.exports; + formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts).split(` +`).map((str) => str.trim()).join(" "); + }; + formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); + }; +}); + +// node_modules/debug/src/index.js +var require_src = __commonJS((exports2, module2) => { + if (typeof process === "undefined" || process.type === "renderer" || false || process.__nwjs) { + module2.exports = require_browser(); + } else { + module2.exports = require_node(); + } +}); + +// node_modules/engine.io/build/transport.js +var require_transport = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Transport = undefined; + var events_1 = require("events"); + var parser_v4 = require_cjs(); + var parser_v3 = require_parser_v3(); + var debug_1 = require_src(); + var debug = (0, debug_1.default)("engine:transport"); + function noop() {} + + class Transport extends events_1.EventEmitter { + get readyState() { + return this._readyState; + } + set readyState(state) { + debug("readyState updated from %s to %s (%s)", this._readyState, state, this.name); + this._readyState = state; + } + constructor(req) { + super(); + this.writable = false; + this._readyState = "open"; + this.discarded = false; + this.protocol = req._query.EIO === "4" ? 4 : 3; + this.parser = this.protocol === 4 ? parser_v4 : parser_v3; + this.supportsBinary = !(req._query && req._query.b64); + } + discard() { + this.discarded = true; + } + onRequest(req) {} + close(fn) { + if (this.readyState === "closed" || this.readyState === "closing") + return; + this.readyState = "closing"; + this.doClose(fn || noop); + } + onError(msg, desc) { + if (this.listeners("error").length) { + const err = new Error(msg); + err.type = "TransportError"; + err.description = desc; + this.emit("error", err); + } else { + debug("ignored transport error %s (%s)", msg, desc); + } + } + onPacket(packet) { + this.emit("packet", packet); + } + onData(data) { + this.onPacket(this.parser.decodePacket(data)); + } + onClose() { + this.readyState = "closed"; + this.emit("close"); + } + } + exports2.Transport = Transport; +}); + +// node_modules/engine.io/build/transports/polling.js +var require_polling = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Polling = undefined; + var transport_1 = require_transport(); + var zlib_1 = require("zlib"); + var accepts = require_accepts(); + var debug_1 = require_src(); + var debug = (0, debug_1.default)("engine:polling"); + var compressionMethods = { + gzip: zlib_1.createGzip, + deflate: zlib_1.createDeflate + }; + + class Polling extends transport_1.Transport { + constructor(req) { + super(req); + this.closeTimeout = 30 * 1000; + } + get name() { + return "polling"; + } + onRequest(req) { + const res = req.res; + req.res = null; + if (req.method === "GET") { + this.onPollRequest(req, res); + } else if (req.method === "POST") { + this.onDataRequest(req, res); + } else { + res.writeHead(500); + res.end(); + } + } + onPollRequest(req, res) { + if (this.req) { + debug("request overlap"); + this.onError("overlap from client"); + res.writeHead(400); + res.end(); + return; + } + debug("setting request"); + this.req = req; + this.res = res; + const onClose = () => { + this.onError("poll connection closed prematurely"); + }; + const cleanup = () => { + req.removeListener("close", onClose); + this.req = this.res = null; + }; + req.cleanup = cleanup; + req.on("close", onClose); + this.writable = true; + this.emit("ready"); + if (this.writable && this.shouldClose) { + debug("triggering empty send to append close packet"); + this.send([{ type: "noop" }]); + } + } + onDataRequest(req, res) { + if (this.dataReq) { + this.onError("data request overlap from client"); + res.writeHead(400); + res.end(); + return; + } + const isBinary = req.headers["content-type"] === "application/octet-stream"; + if (isBinary && this.protocol === 4) { + return this.onError("invalid content"); + } + this.dataReq = req; + this.dataRes = res; + let chunks = isBinary ? Buffer.concat([]) : ""; + const cleanup = () => { + req.removeListener("data", onData); + req.removeListener("end", onEnd); + req.removeListener("close", onClose); + this.dataReq = this.dataRes = chunks = null; + }; + const onClose = () => { + cleanup(); + this.onError("data request connection closed prematurely"); + }; + const onData = (data) => { + let contentLength; + if (isBinary) { + chunks = Buffer.concat([chunks, data]); + contentLength = chunks.length; + } else { + chunks += data; + contentLength = Buffer.byteLength(chunks); + } + if (contentLength > this.maxHttpBufferSize) { + res.writeHead(413).end(); + cleanup(); + } + }; + const onEnd = () => { + this.onData(chunks); + const headers = { + "Content-Type": "text/html", + "Content-Length": "2" + }; + res.writeHead(200, this.headers(req, headers)); + res.end("ok"); + cleanup(); + }; + req.on("close", onClose); + if (!isBinary) + req.setEncoding("utf8"); + req.on("data", onData); + req.on("end", onEnd); + } + onData(data) { + debug('received "%s"', data); + const callback = (packet) => { + if (packet.type === "close") { + debug("got xhr close packet"); + this.onClose(); + return false; + } + this.onPacket(packet); + }; + if (this.protocol === 3) { + this.parser.decodePayload(data, callback); + } else { + this.parser.decodePayload(data).forEach(callback); + } + } + onClose() { + if (this.writable) { + this.send([{ type: "noop" }]); + } + super.onClose(); + } + send(packets) { + this.writable = false; + if (this.shouldClose) { + debug("appending close packet to payload"); + packets.push({ type: "close" }); + this.shouldClose(); + this.shouldClose = null; + } + const doWrite = (data) => { + const compress = packets.some((packet) => { + return packet.options && packet.options.compress; + }); + this.write(data, { compress }); + }; + if (this.protocol === 3) { + this.parser.encodePayload(packets, this.supportsBinary, doWrite); + } else { + this.parser.encodePayload(packets, doWrite); + } + } + write(data, options) { + debug('writing "%s"', data); + this.doWrite(data, options, () => { + this.req.cleanup(); + this.emit("drain"); + }); + } + doWrite(data, options, callback) { + const isString = typeof data === "string"; + const contentType = isString ? "text/plain; charset=UTF-8" : "application/octet-stream"; + const headers = { + "Content-Type": contentType + }; + const respond = (data2) => { + headers["Content-Length"] = typeof data2 === "string" ? Buffer.byteLength(data2) : data2.length; + this.res.writeHead(200, this.headers(this.req, headers)); + this.res.end(data2); + callback(); + }; + if (!this.httpCompression || !options.compress) { + respond(data); + return; + } + const len = isString ? Buffer.byteLength(data) : data.length; + if (len < this.httpCompression.threshold) { + respond(data); + return; + } + const encoding = accepts(this.req).encodings(["gzip", "deflate"]); + if (!encoding) { + respond(data); + return; + } + this.compress(data, encoding, (err, data2) => { + if (err) { + this.res.writeHead(500); + this.res.end(); + callback(err); + return; + } + headers["Content-Encoding"] = encoding; + respond(data2); + }); + } + compress(data, encoding, callback) { + debug("compressing"); + const buffers = []; + let nread = 0; + compressionMethods[encoding](this.httpCompression).on("error", callback).on("data", function(chunk) { + buffers.push(chunk); + nread += chunk.length; + }).on("end", function() { + callback(null, Buffer.concat(buffers, nread)); + }).end(data); + } + doClose(fn) { + debug("closing"); + let closeTimeoutTimer; + if (this.dataReq) { + debug("aborting ongoing data request"); + this.dataReq.destroy(); + } + const onClose = () => { + clearTimeout(closeTimeoutTimer); + fn(); + this.onClose(); + }; + if (this.writable) { + debug("transport writable - closing right away"); + this.send([{ type: "close" }]); + onClose(); + } else if (this.discarded) { + debug("transport discarded - closing right away"); + onClose(); + } else { + debug("transport not writable - buffering orderly close"); + this.shouldClose = onClose; + closeTimeoutTimer = setTimeout(onClose, this.closeTimeout); + } + } + headers(req, headers = {}) { + const ua = req.headers["user-agent"]; + if (ua && (~ua.indexOf(";MSIE") || ~ua.indexOf("Trident/"))) { + headers["X-XSS-Protection"] = "0"; + } + headers["cache-control"] = "no-store"; + this.emit("headers", headers, req); + return headers; + } + } + exports2.Polling = Polling; +}); + +// node_modules/engine.io/build/transports/polling-jsonp.js +var require_polling_jsonp = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.JSONP = undefined; + var polling_1 = require_polling(); + var qs = require("querystring"); + var rDoubleSlashes = /\\\\n/g; + var rSlashes = /(\\)?\\n/g; + + class JSONP extends polling_1.Polling { + constructor(req) { + super(req); + this.head = "___eio[" + (req._query.j || "").replace(/[^0-9]/g, "") + "]("; + this.foot = ");"; + } + onData(data) { + data = qs.parse(data).d; + if (typeof data === "string") { + data = data.replace(rSlashes, function(match, slashes) { + return slashes ? match : ` +`; + }); + super.onData(data.replace(rDoubleSlashes, "\\n")); + } + } + doWrite(data, options, callback) { + const js = JSON.stringify(data).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029"); + data = this.head + js + this.foot; + super.doWrite(data, options, callback); + } + } + exports2.JSONP = JSONP; +}); + +// node_modules/engine.io/build/transports/websocket.js +var require_websocket = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WebSocket = undefined; + var transport_1 = require_transport(); + var debug_1 = require_src(); + var debug = (0, debug_1.default)("engine:ws"); + + class WebSocket extends transport_1.Transport { + constructor(req) { + super(req); + this._doSend = (data) => { + this.socket.send(data, this._onSent); + }; + this._doSendLast = (data) => { + this.socket.send(data, this._onSentLast); + }; + this._onSent = (err) => { + if (err) { + this.onError("write error", err.stack); + } + }; + this._onSentLast = (err) => { + if (err) { + this.onError("write error", err.stack); + } else { + this.emit("drain"); + this.writable = true; + this.emit("ready"); + } + }; + this.socket = req.websocket; + this.socket.on("message", (data, isBinary) => { + const message = isBinary ? data : data.toString(); + debug('received "%s"', message); + super.onData(message); + }); + this.socket.once("close", this.onClose.bind(this)); + this.socket.on("error", this.onError.bind(this)); + this.writable = true; + this.perMessageDeflate = null; + } + get name() { + return "websocket"; + } + get handlesUpgrades() { + return true; + } + send(packets) { + this.writable = false; + for (let i = 0;i < packets.length; i++) { + const packet = packets[i]; + const isLast = i + 1 === packets.length; + if (this._canSendPreEncodedFrame(packet)) { + this.socket._sender.sendFrame(packet.options.wsPreEncodedFrame, isLast ? this._onSentLast : this._onSent); + } else { + this.parser.encodePacket(packet, this.supportsBinary, isLast ? this._doSendLast : this._doSend); + } + } + } + _canSendPreEncodedFrame(packet) { + var _a, _b, _c; + return !this.perMessageDeflate && typeof ((_b = (_a = this.socket) === null || _a === undefined ? undefined : _a._sender) === null || _b === undefined ? undefined : _b.sendFrame) === "function" && ((_c = packet.options) === null || _c === undefined ? undefined : _c.wsPreEncodedFrame) !== undefined; + } + doClose(fn) { + debug("closing"); + this.socket.close(); + fn && fn(); + } + } + exports2.WebSocket = WebSocket; +}); + +// node_modules/engine.io/build/transports/webtransport.js +var require_webtransport = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WebTransport = undefined; + var transport_1 = require_transport(); + var debug_1 = require_src(); + var engine_io_parser_1 = require_cjs(); + var debug = (0, debug_1.default)("engine:webtransport"); + + class WebTransport2 extends transport_1.Transport { + constructor(session, stream, reader) { + super({ _query: { EIO: "4" } }); + this.session = session; + const transformStream = (0, engine_io_parser_1.createPacketEncoderStream)(); + transformStream.readable.pipeTo(stream.writable).catch(() => { + debug("the stream was closed"); + }); + this.writer = transformStream.writable.getWriter(); + (async () => { + try { + while (true) { + const { value, done } = await reader.read(); + if (done) { + debug("session is closed"); + break; + } + debug("received chunk: %o", value); + this.onPacket(value); + } + } catch (e) { + debug("error while reading: %s", e.message); + } + })(); + session.closed.then(() => this.onClose()); + this.writable = true; + } + get name() { + return "webtransport"; + } + async send(packets) { + this.writable = false; + try { + for (let i = 0;i < packets.length; i++) { + const packet = packets[i]; + await this.writer.write(packet); + } + } catch (e) { + debug("error while writing: %s", e.message); + } + this.emit("drain"); + this.writable = true; + this.emit("ready"); + } + doClose(fn) { + debug("closing WebTransport session"); + this.session.close(); + fn && fn(); + } + } + exports2.WebTransport = WebTransport2; +}); + +// node_modules/engine.io/build/transports/index.js +var require_transports = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + var polling_1 = require_polling(); + var polling_jsonp_1 = require_polling_jsonp(); + var websocket_1 = require_websocket(); + var webtransport_1 = require_webtransport(); + exports2.default = { + polling, + websocket: websocket_1.WebSocket, + webtransport: webtransport_1.WebTransport + }; + function polling(req) { + if (typeof req._query.j === "string") { + return new polling_jsonp_1.JSONP(req); + } else { + return new polling_1.Polling(req); + } + } + polling.upgradesTo = ["websocket", "webtransport"]; +}); + +// node_modules/engine.io/build/socket.js +var require_socket = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Socket = undefined; + var events_1 = require("events"); + var debug_1 = require_src(); + var timers_1 = require("timers"); + var debug = (0, debug_1.default)("engine:socket"); + + class Socket extends events_1.EventEmitter { + get readyState() { + return this._readyState; + } + set readyState(state) { + debug("readyState updated from %s to %s", this._readyState, state); + this._readyState = state; + } + constructor(id, server, transport, req, protocol) { + super(); + this._readyState = "opening"; + this.upgrading = false; + this.upgraded = false; + this.writeBuffer = []; + this.packetsFn = []; + this.sentCallbackFn = []; + this.cleanupFn = []; + this.id = id; + this.server = server; + this.request = req; + this.protocol = protocol; + if (req) { + if (req.websocket && req.websocket._socket) { + this.remoteAddress = req.websocket._socket.remoteAddress; + } else { + this.remoteAddress = req.connection.remoteAddress; + } + } else {} + this.pingTimeoutTimer = null; + this.pingIntervalTimer = null; + this.setTransport(transport); + this.onOpen(); + } + onOpen() { + this.readyState = "open"; + this.transport.sid = this.id; + this.sendPacket("open", JSON.stringify({ + sid: this.id, + upgrades: this.getAvailableUpgrades(), + pingInterval: this.server.opts.pingInterval, + pingTimeout: this.server.opts.pingTimeout, + maxPayload: this.server.opts.maxHttpBufferSize + })); + if (this.server.opts.initialPacket) { + this.sendPacket("message", this.server.opts.initialPacket); + } + this.emit("open"); + if (this.protocol === 3) { + this.resetPingTimeout(); + } else { + this.schedulePing(); + } + } + onPacket(packet) { + if (this.readyState !== "open") { + return debug("packet received with closed socket"); + } + debug(`received packet ${packet.type}`); + this.emit("packet", packet); + switch (packet.type) { + case "ping": + if (this.transport.protocol !== 3) { + this.onError(new Error("invalid heartbeat direction")); + return; + } + debug("got ping"); + this.pingTimeoutTimer.refresh(); + this.sendPacket("pong"); + this.emit("heartbeat"); + break; + case "pong": + if (this.transport.protocol === 3) { + this.onError(new Error("invalid heartbeat direction")); + return; + } + debug("got pong"); + (0, timers_1.clearTimeout)(this.pingTimeoutTimer); + this.pingIntervalTimer.refresh(); + this.emit("heartbeat"); + break; + case "error": + this.onClose("parse error"); + break; + case "message": + this.emit("data", packet.data); + this.emit("message", packet.data); + break; + } + } + onError(err) { + debug("transport error"); + this.onClose("transport error", err); + } + schedulePing() { + this.pingIntervalTimer = (0, timers_1.setTimeout)(() => { + debug("writing ping packet - expecting pong within %sms", this.server.opts.pingTimeout); + this.sendPacket("ping"); + this.resetPingTimeout(); + }, this.server.opts.pingInterval); + } + resetPingTimeout() { + (0, timers_1.clearTimeout)(this.pingTimeoutTimer); + this.pingTimeoutTimer = (0, timers_1.setTimeout)(() => { + if (this.readyState === "closed") + return; + this.onClose("ping timeout"); + }, this.protocol === 3 ? this.server.opts.pingInterval + this.server.opts.pingTimeout : this.server.opts.pingTimeout); + } + setTransport(transport) { + const onError = this.onError.bind(this); + const onReady = () => this.flush(); + const onPacket = this.onPacket.bind(this); + const onDrain = this.onDrain.bind(this); + const onClose = this.onClose.bind(this, "transport close"); + this.transport = transport; + this.transport.once("error", onError); + this.transport.on("ready", onReady); + this.transport.on("packet", onPacket); + this.transport.on("drain", onDrain); + this.transport.once("close", onClose); + this.cleanupFn.push(function() { + transport.removeListener("error", onError); + transport.removeListener("ready", onReady); + transport.removeListener("packet", onPacket); + transport.removeListener("drain", onDrain); + transport.removeListener("close", onClose); + }); + } + onDrain() { + if (this.sentCallbackFn.length > 0) { + debug("executing batch send callback"); + const seqFn = this.sentCallbackFn.shift(); + if (seqFn) { + for (let i = 0;i < seqFn.length; i++) { + seqFn[i](this.transport); + } + } + } + } + _maybeUpgrade(transport) { + debug('might upgrade socket transport from "%s" to "%s"', this.transport.name, transport.name); + this.upgrading = true; + const upgradeTimeoutTimer = (0, timers_1.setTimeout)(() => { + debug("client did not complete upgrade - closing transport"); + cleanup(); + if (transport.readyState === "open") { + transport.close(); + } + }, this.server.opts.upgradeTimeout); + let checkIntervalTimer; + const onPacket = (packet) => { + if (packet.type === "ping" && packet.data === "probe") { + debug("got probe ping packet, sending pong"); + transport.send([{ type: "pong", data: "probe" }]); + this.emit("upgrading", transport); + clearInterval(checkIntervalTimer); + checkIntervalTimer = setInterval(check, 100); + } else if (packet.type === "upgrade" && this.readyState !== "closed") { + debug("got upgrade packet - upgrading"); + cleanup(); + this.transport.discard(); + this.upgraded = true; + this.clearTransport(); + this.setTransport(transport); + this.emit("upgrade", transport); + this.flush(); + if (this.readyState === "closing") { + transport.close(() => { + this.onClose("forced close"); + }); + } + } else { + cleanup(); + transport.close(); + } + }; + const check = () => { + if (this.transport.name === "polling" && this.transport.writable) { + debug("writing a noop packet to polling for fast upgrade"); + this.transport.send([{ type: "noop" }]); + } + }; + const cleanup = () => { + this.upgrading = false; + clearInterval(checkIntervalTimer); + (0, timers_1.clearTimeout)(upgradeTimeoutTimer); + transport.removeListener("packet", onPacket); + transport.removeListener("close", onTransportClose); + transport.removeListener("error", onError); + this.removeListener("close", onClose); + }; + const onError = (err) => { + debug("client did not complete upgrade - %s", err); + cleanup(); + transport.close(); + transport = null; + }; + const onTransportClose = () => { + onError("transport closed"); + }; + const onClose = () => { + onError("socket closed"); + }; + transport.on("packet", onPacket); + transport.once("close", onTransportClose); + transport.once("error", onError); + this.once("close", onClose); + } + clearTransport() { + let cleanup; + const toCleanUp = this.cleanupFn.length; + for (let i = 0;i < toCleanUp; i++) { + cleanup = this.cleanupFn.shift(); + cleanup(); + } + this.transport.on("error", function() { + debug("error triggered by discarded transport"); + }); + this.transport.close(); + (0, timers_1.clearTimeout)(this.pingTimeoutTimer); + } + onClose(reason, description) { + if (this.readyState !== "closed") { + this.readyState = "closed"; + (0, timers_1.clearTimeout)(this.pingIntervalTimer); + (0, timers_1.clearTimeout)(this.pingTimeoutTimer); + process.nextTick(() => { + this.writeBuffer = []; + }); + this.packetsFn = []; + this.sentCallbackFn = []; + this.clearTransport(); + this.emit("close", reason, description); + } + } + send(data, options, callback) { + this.sendPacket("message", data, options, callback); + return this; + } + write(data, options, callback) { + this.sendPacket("message", data, options, callback); + return this; + } + sendPacket(type, data, options = {}, callback) { + if (typeof options === "function") { + callback = options; + options = {}; + } + if (this.readyState !== "closing" && this.readyState !== "closed") { + debug('sending packet "%s" (%s)', type, data); + options.compress = options.compress !== false; + const packet = { + type, + options + }; + if (data) + packet.data = data; + this.emit("packetCreate", packet); + this.writeBuffer.push(packet); + if (typeof callback === "function") + this.packetsFn.push(callback); + this.flush(); + } + } + flush() { + if (this.readyState !== "closed" && this.transport.writable && this.writeBuffer.length) { + debug("flushing buffer to transport"); + this.emit("flush", this.writeBuffer); + this.server.emit("flush", this, this.writeBuffer); + const wbuf = this.writeBuffer; + this.writeBuffer = []; + if (this.packetsFn.length) { + this.sentCallbackFn.push(this.packetsFn); + this.packetsFn = []; + } else { + this.sentCallbackFn.push(null); + } + this.transport.send(wbuf); + this.emit("drain"); + this.server.emit("drain", this); + } + } + getAvailableUpgrades() { + const availableUpgrades = []; + const allUpgrades = this.server.upgrades(this.transport.name); + for (let i = 0;i < allUpgrades.length; ++i) { + const upg = allUpgrades[i]; + if (this.server.opts.transports.indexOf(upg) !== -1) { + availableUpgrades.push(upg); + } + } + return availableUpgrades; + } + close(discard) { + if (discard && (this.readyState === "open" || this.readyState === "closing")) { + return this.closeTransport(discard); + } + if (this.readyState !== "open") + return; + this.readyState = "closing"; + if (this.writeBuffer.length) { + debug("there are %d remaining packets in the buffer, waiting for the 'drain' event", this.writeBuffer.length); + this.once("drain", () => { + debug("all packets have been sent, closing the transport"); + this.closeTransport(discard); + }); + return; + } + debug("the buffer is empty, closing the transport right away"); + this.closeTransport(discard); + } + closeTransport(discard) { + debug("closing the transport (discard? %s)", !!discard); + if (discard) + this.transport.discard(); + this.transport.close(this.onClose.bind(this, "forced close")); + } + } + exports2.Socket = Socket; +}); + +// node_modules/engine.io/node_modules/cookie/index.js +var require_cookie = __commonJS((exports2) => { + /*! + * cookie + * Copyright(c) 2012-2014 Roman Shtylman + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + exports2.parse = parse; + exports2.serialize = serialize; + var __toString = Object.prototype.toString; + var __hasOwnProperty = Object.prototype.hasOwnProperty; + var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; + var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/; + var domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i; + var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/; + function parse(str, opt) { + if (typeof str !== "string") { + throw new TypeError("argument str must be a string"); + } + var obj = {}; + var len = str.length; + if (len < 2) + return obj; + var dec = opt && opt.decode || decode; + var index = 0; + var eqIdx = 0; + var endIdx = 0; + do { + eqIdx = str.indexOf("=", index); + if (eqIdx === -1) + break; + endIdx = str.indexOf(";", index); + if (endIdx === -1) { + endIdx = len; + } else if (eqIdx > endIdx) { + index = str.lastIndexOf(";", eqIdx - 1) + 1; + continue; + } + var keyStartIdx = startIndex(str, index, eqIdx); + var keyEndIdx = endIndex(str, eqIdx, keyStartIdx); + var key = str.slice(keyStartIdx, keyEndIdx); + if (!__hasOwnProperty.call(obj, key)) { + var valStartIdx = startIndex(str, eqIdx + 1, endIdx); + var valEndIdx = endIndex(str, endIdx, valStartIdx); + if (str.charCodeAt(valStartIdx) === 34 && str.charCodeAt(valEndIdx - 1) === 34) { + valStartIdx++; + valEndIdx--; + } + var val = str.slice(valStartIdx, valEndIdx); + obj[key] = tryDecode(val, dec); + } + index = endIdx + 1; + } while (index < len); + return obj; + } + function startIndex(str, index, max) { + do { + var code = str.charCodeAt(index); + if (code !== 32 && code !== 9) + return index; + } while (++index < max); + return max; + } + function endIndex(str, index, min) { + while (index > min) { + var code = str.charCodeAt(--index); + if (code !== 32 && code !== 9) + return index + 1; + } + return min; + } + function serialize(name, val, opt) { + var enc = opt && opt.encode || encodeURIComponent; + if (typeof enc !== "function") { + throw new TypeError("option encode is invalid"); + } + if (!cookieNameRegExp.test(name)) { + throw new TypeError("argument name is invalid"); + } + var value = enc(val); + if (!cookieValueRegExp.test(value)) { + throw new TypeError("argument val is invalid"); + } + var str = name + "=" + value; + if (!opt) + return str; + if (opt.maxAge != null) { + var maxAge = Math.floor(opt.maxAge); + if (!isFinite(maxAge)) { + throw new TypeError("option maxAge is invalid"); + } + str += "; Max-Age=" + maxAge; + } + if (opt.domain) { + if (!domainValueRegExp.test(opt.domain)) { + throw new TypeError("option domain is invalid"); + } + str += "; Domain=" + opt.domain; + } + if (opt.path) { + if (!pathValueRegExp.test(opt.path)) { + throw new TypeError("option path is invalid"); + } + str += "; Path=" + opt.path; + } + if (opt.expires) { + var expires = opt.expires; + if (!isDate(expires) || isNaN(expires.valueOf())) { + throw new TypeError("option expires is invalid"); + } + str += "; Expires=" + expires.toUTCString(); + } + if (opt.httpOnly) { + str += "; HttpOnly"; + } + if (opt.secure) { + str += "; Secure"; + } + if (opt.partitioned) { + str += "; Partitioned"; + } + if (opt.priority) { + var priority = typeof opt.priority === "string" ? opt.priority.toLowerCase() : opt.priority; + switch (priority) { + case "low": + str += "; Priority=Low"; + break; + case "medium": + str += "; Priority=Medium"; + break; + case "high": + str += "; Priority=High"; + break; + default: + throw new TypeError("option priority is invalid"); + } + } + if (opt.sameSite) { + var sameSite = typeof opt.sameSite === "string" ? opt.sameSite.toLowerCase() : opt.sameSite; + switch (sameSite) { + case true: + str += "; SameSite=Strict"; + break; + case "lax": + str += "; SameSite=Lax"; + break; + case "strict": + str += "; SameSite=Strict"; + break; + case "none": + str += "; SameSite=None"; + break; + default: + throw new TypeError("option sameSite is invalid"); + } + } + return str; + } + function decode(str) { + return str.indexOf("%") !== -1 ? decodeURIComponent(str) : str; + } + function isDate(val) { + return __toString.call(val) === "[object Date]"; + } + function tryDecode(str, decode2) { + try { + return decode2(str); + } catch (e) { + return str; + } + } +}); + +// node_modules/ws/lib/constants.js +var require_constants = __commonJS((exports2, module2) => { + module2.exports = { + BINARY_TYPES: ["nodebuffer", "arraybuffer", "fragments"], + EMPTY_BUFFER: Buffer.alloc(0), + GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", + kForOnEventAttribute: Symbol("kIsForOnEventAttribute"), + kListener: Symbol("kListener"), + kStatusCode: Symbol("status-code"), + kWebSocket: Symbol("websocket"), + NOOP: () => {} + }; +}); + +// node_modules/ws/lib/buffer-util.js +var require_buffer_util = __commonJS((exports2, module2) => { + var { EMPTY_BUFFER } = require_constants(); + var FastBuffer = Buffer[Symbol.species]; + function concat(list, totalLength) { + if (list.length === 0) + return EMPTY_BUFFER; + if (list.length === 1) + return list[0]; + const target = Buffer.allocUnsafe(totalLength); + let offset = 0; + for (let i = 0;i < list.length; i++) { + const buf = list[i]; + target.set(buf, offset); + offset += buf.length; + } + if (offset < totalLength) { + return new FastBuffer(target.buffer, target.byteOffset, offset); + } + return target; + } + function _mask(source2, mask, output, offset, length) { + for (let i = 0;i < length; i++) { + output[offset + i] = source2[i] ^ mask[i & 3]; + } + } + function _unmask(buffer, mask) { + for (let i = 0;i < buffer.length; i++) { + buffer[i] ^= mask[i & 3]; + } + } + function toArrayBuffer(buf) { + if (buf.length === buf.buffer.byteLength) { + return buf.buffer; + } + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length); + } + function toBuffer(data) { + toBuffer.readOnly = true; + if (Buffer.isBuffer(data)) + return data; + let buf; + if (data instanceof ArrayBuffer) { + buf = new FastBuffer(data); + } else if (ArrayBuffer.isView(data)) { + buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength); + } else { + buf = Buffer.from(data); + toBuffer.readOnly = false; + } + return buf; + } + module2.exports = { + concat, + mask: _mask, + toArrayBuffer, + toBuffer, + unmask: _unmask + }; + if (!process.env.WS_NO_BUFFER_UTIL) { + try { + const bufferUtil = (()=>{throw new Error("Cannot require module "+"bufferutil");})(); + module2.exports.mask = function(source2, mask, output, offset, length) { + if (length < 48) + _mask(source2, mask, output, offset, length); + else + bufferUtil.mask(source2, mask, output, offset, length); + }; + module2.exports.unmask = function(buffer, mask) { + if (buffer.length < 32) + _unmask(buffer, mask); + else + bufferUtil.unmask(buffer, mask); + }; + } catch (e) {} + } +}); + +// node_modules/ws/lib/limiter.js +var require_limiter = __commonJS((exports2, module2) => { + var kDone = Symbol("kDone"); + var kRun = Symbol("kRun"); + + class Limiter { + constructor(concurrency) { + this[kDone] = () => { + this.pending--; + this[kRun](); + }; + this.concurrency = concurrency || Infinity; + this.jobs = []; + this.pending = 0; + } + add(job) { + this.jobs.push(job); + this[kRun](); + } + [kRun]() { + if (this.pending === this.concurrency) + return; + if (this.jobs.length) { + const job = this.jobs.shift(); + this.pending++; + job(this[kDone]); + } + } + } + module2.exports = Limiter; +}); + +// node_modules/ws/lib/permessage-deflate.js +var require_permessage_deflate = __commonJS((exports2, module2) => { + var zlib = require("zlib"); + var bufferUtil = require_buffer_util(); + var Limiter = require_limiter(); + var { kStatusCode } = require_constants(); + var FastBuffer = Buffer[Symbol.species]; + var TRAILER = Buffer.from([0, 0, 255, 255]); + var kPerMessageDeflate = Symbol("permessage-deflate"); + var kTotalLength = Symbol("total-length"); + var kCallback = Symbol("callback"); + var kBuffers = Symbol("buffers"); + var kError = Symbol("error"); + var zlibLimiter; + + class PerMessageDeflate { + constructor(options, isServer, maxPayload) { + this._maxPayload = maxPayload | 0; + this._options = options || {}; + this._threshold = this._options.threshold !== undefined ? this._options.threshold : 1024; + this._isServer = !!isServer; + this._deflate = null; + this._inflate = null; + this.params = null; + if (!zlibLimiter) { + const concurrency = this._options.concurrencyLimit !== undefined ? this._options.concurrencyLimit : 10; + zlibLimiter = new Limiter(concurrency); + } + } + static get extensionName() { + return "permessage-deflate"; + } + offer() { + const params = {}; + if (this._options.serverNoContextTakeover) { + params.server_no_context_takeover = true; + } + if (this._options.clientNoContextTakeover) { + params.client_no_context_takeover = true; + } + if (this._options.serverMaxWindowBits) { + params.server_max_window_bits = this._options.serverMaxWindowBits; + } + if (this._options.clientMaxWindowBits) { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } else if (this._options.clientMaxWindowBits == null) { + params.client_max_window_bits = true; + } + return params; + } + accept(configurations) { + configurations = this.normalizeParams(configurations); + this.params = this._isServer ? this.acceptAsServer(configurations) : this.acceptAsClient(configurations); + return this.params; + } + cleanup() { + if (this._inflate) { + this._inflate.close(); + this._inflate = null; + } + if (this._deflate) { + const callback = this._deflate[kCallback]; + this._deflate.close(); + this._deflate = null; + if (callback) { + callback(new Error("The deflate stream was closed while data was being processed")); + } + } + } + acceptAsServer(offers) { + const opts = this._options; + const accepted = offers.find((params) => { + if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) { + return false; + } + return true; + }); + if (!accepted) { + throw new Error("None of the extension offers can be accepted"); + } + if (opts.serverNoContextTakeover) { + accepted.server_no_context_takeover = true; + } + if (opts.clientNoContextTakeover) { + accepted.client_no_context_takeover = true; + } + if (typeof opts.serverMaxWindowBits === "number") { + accepted.server_max_window_bits = opts.serverMaxWindowBits; + } + if (typeof opts.clientMaxWindowBits === "number") { + accepted.client_max_window_bits = opts.clientMaxWindowBits; + } else if (accepted.client_max_window_bits === true || opts.clientMaxWindowBits === false) { + delete accepted.client_max_window_bits; + } + return accepted; + } + acceptAsClient(response) { + const params = response[0]; + if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) { + throw new Error('Unexpected parameter "client_no_context_takeover"'); + } + if (!params.client_max_window_bits) { + if (typeof this._options.clientMaxWindowBits === "number") { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } + } else if (this._options.clientMaxWindowBits === false || typeof this._options.clientMaxWindowBits === "number" && params.client_max_window_bits > this._options.clientMaxWindowBits) { + throw new Error('Unexpected or invalid parameter "client_max_window_bits"'); + } + return params; + } + normalizeParams(configurations) { + configurations.forEach((params) => { + Object.keys(params).forEach((key) => { + let value = params[key]; + if (value.length > 1) { + throw new Error(`Parameter "${key}" must have only a single value`); + } + value = value[0]; + if (key === "client_max_window_bits") { + if (value !== true) { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError(`Invalid value for parameter "${key}": ${value}`); + } + value = num; + } else if (!this._isServer) { + throw new TypeError(`Invalid value for parameter "${key}": ${value}`); + } + } else if (key === "server_max_window_bits") { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError(`Invalid value for parameter "${key}": ${value}`); + } + value = num; + } else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") { + if (value !== true) { + throw new TypeError(`Invalid value for parameter "${key}": ${value}`); + } + } else { + throw new Error(`Unknown parameter "${key}"`); + } + params[key] = value; + }); + }); + return configurations; + } + decompress(data, fin, callback) { + zlibLimiter.add((done) => { + this._decompress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + compress(data, fin, callback) { + zlibLimiter.add((done) => { + this._compress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + _decompress(data, fin, callback) { + const endpoint = this._isServer ? "client" : "server"; + if (!this._inflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key]; + this._inflate = zlib.createInflateRaw({ + ...this._options.zlibInflateOptions, + windowBits + }); + this._inflate[kPerMessageDeflate] = this; + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + this._inflate.on("error", inflateOnError); + this._inflate.on("data", inflateOnData); + } + this._inflate[kCallback] = callback; + this._inflate.write(data); + if (fin) + this._inflate.write(TRAILER); + this._inflate.flush(() => { + const err = this._inflate[kError]; + if (err) { + this._inflate.close(); + this._inflate = null; + callback(err); + return; + } + const data2 = bufferUtil.concat(this._inflate[kBuffers], this._inflate[kTotalLength]); + if (this._inflate._readableState.endEmitted) { + this._inflate.close(); + this._inflate = null; + } else { + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + if (fin && this.params[`${endpoint}_no_context_takeover`]) { + this._inflate.reset(); + } + } + callback(null, data2); + }); + } + _compress(data, fin, callback) { + const endpoint = this._isServer ? "server" : "client"; + if (!this._deflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key]; + this._deflate = zlib.createDeflateRaw({ + ...this._options.zlibDeflateOptions, + windowBits + }); + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + this._deflate.on("data", deflateOnData); + } + this._deflate[kCallback] = callback; + this._deflate.write(data); + this._deflate.flush(zlib.Z_SYNC_FLUSH, () => { + if (!this._deflate) { + return; + } + let data2 = bufferUtil.concat(this._deflate[kBuffers], this._deflate[kTotalLength]); + if (fin) { + data2 = new FastBuffer(data2.buffer, data2.byteOffset, data2.length - 4); + } + this._deflate[kCallback] = null; + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + if (fin && this.params[`${endpoint}_no_context_takeover`]) { + this._deflate.reset(); + } + callback(null, data2); + }); + } + } + module2.exports = PerMessageDeflate; + function deflateOnData(chunk) { + this[kBuffers].push(chunk); + this[kTotalLength] += chunk.length; + } + function inflateOnData(chunk) { + this[kTotalLength] += chunk.length; + if (this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload) { + this[kBuffers].push(chunk); + return; + } + this[kError] = new RangeError("Max payload size exceeded"); + this[kError].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"; + this[kError][kStatusCode] = 1009; + this.removeListener("data", inflateOnData); + this.reset(); + } + function inflateOnError(err) { + this[kPerMessageDeflate]._inflate = null; + err[kStatusCode] = 1007; + this[kCallback](err); + } +}); + +// node_modules/ws/lib/validation.js +var require_validation = __commonJS((exports2, module2) => { + var { isUtf8 } = require("buffer"); + var tokenChars = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 0, + 1, + 0 + ]; + function isValidStatusCode(code) { + return code >= 1000 && code <= 1014 && code !== 1004 && code !== 1005 && code !== 1006 || code >= 3000 && code <= 4999; + } + function _isValidUTF8(buf) { + const len = buf.length; + let i = 0; + while (i < len) { + if ((buf[i] & 128) === 0) { + i++; + } else if ((buf[i] & 224) === 192) { + if (i + 1 === len || (buf[i + 1] & 192) !== 128 || (buf[i] & 254) === 192) { + return false; + } + i += 2; + } else if ((buf[i] & 240) === 224) { + if (i + 2 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || buf[i] === 224 && (buf[i + 1] & 224) === 128 || buf[i] === 237 && (buf[i + 1] & 224) === 160) { + return false; + } + i += 3; + } else if ((buf[i] & 248) === 240) { + if (i + 3 >= len || (buf[i + 1] & 192) !== 128 || (buf[i + 2] & 192) !== 128 || (buf[i + 3] & 192) !== 128 || buf[i] === 240 && (buf[i + 1] & 240) === 128 || buf[i] === 244 && buf[i + 1] > 143 || buf[i] > 244) { + return false; + } + i += 4; + } else { + return false; + } + } + return true; + } + module2.exports = { + isValidStatusCode, + isValidUTF8: _isValidUTF8, + tokenChars + }; + if (isUtf8) { + module2.exports.isValidUTF8 = function(buf) { + return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf); + }; + } else if (!process.env.WS_NO_UTF_8_VALIDATE) { + try { + const isValidUTF8 = (()=>{throw new Error("Cannot require module "+"utf-8-validate");})(); + module2.exports.isValidUTF8 = function(buf) { + return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf); + }; + } catch (e) {} + } +}); + +// node_modules/ws/lib/receiver.js +var require_receiver = __commonJS((exports2, module2) => { + var { Writable } = require("stream"); + var PerMessageDeflate = require_permessage_deflate(); + var { + BINARY_TYPES, + EMPTY_BUFFER, + kStatusCode, + kWebSocket + } = require_constants(); + var { concat, toArrayBuffer, unmask } = require_buffer_util(); + var { isValidStatusCode, isValidUTF8 } = require_validation(); + var FastBuffer = Buffer[Symbol.species]; + var GET_INFO = 0; + var GET_PAYLOAD_LENGTH_16 = 1; + var GET_PAYLOAD_LENGTH_64 = 2; + var GET_MASK = 3; + var GET_DATA = 4; + var INFLATING = 5; + var DEFER_EVENT = 6; + + class Receiver extends Writable { + constructor(options = {}) { + super(); + this._allowSynchronousEvents = options.allowSynchronousEvents !== undefined ? options.allowSynchronousEvents : true; + this._binaryType = options.binaryType || BINARY_TYPES[0]; + this._extensions = options.extensions || {}; + this._isServer = !!options.isServer; + this._maxPayload = options.maxPayload | 0; + this._skipUTF8Validation = !!options.skipUTF8Validation; + this[kWebSocket] = undefined; + this._bufferedBytes = 0; + this._buffers = []; + this._compressed = false; + this._payloadLength = 0; + this._mask = undefined; + this._fragmented = 0; + this._masked = false; + this._fin = false; + this._opcode = 0; + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragments = []; + this._errored = false; + this._loop = false; + this._state = GET_INFO; + } + _write(chunk, encoding, cb) { + if (this._opcode === 8 && this._state == GET_INFO) + return cb(); + this._bufferedBytes += chunk.length; + this._buffers.push(chunk); + this.startLoop(cb); + } + consume(n) { + this._bufferedBytes -= n; + if (n === this._buffers[0].length) + return this._buffers.shift(); + if (n < this._buffers[0].length) { + const buf = this._buffers[0]; + this._buffers[0] = new FastBuffer(buf.buffer, buf.byteOffset + n, buf.length - n); + return new FastBuffer(buf.buffer, buf.byteOffset, n); + } + const dst = Buffer.allocUnsafe(n); + do { + const buf = this._buffers[0]; + const offset = dst.length - n; + if (n >= buf.length) { + dst.set(this._buffers.shift(), offset); + } else { + dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset); + this._buffers[0] = new FastBuffer(buf.buffer, buf.byteOffset + n, buf.length - n); + } + n -= buf.length; + } while (n > 0); + return dst; + } + startLoop(cb) { + this._loop = true; + do { + switch (this._state) { + case GET_INFO: + this.getInfo(cb); + break; + case GET_PAYLOAD_LENGTH_16: + this.getPayloadLength16(cb); + break; + case GET_PAYLOAD_LENGTH_64: + this.getPayloadLength64(cb); + break; + case GET_MASK: + this.getMask(); + break; + case GET_DATA: + this.getData(cb); + break; + case INFLATING: + case DEFER_EVENT: + this._loop = false; + return; + } + } while (this._loop); + if (!this._errored) + cb(); + } + getInfo(cb) { + if (this._bufferedBytes < 2) { + this._loop = false; + return; + } + const buf = this.consume(2); + if ((buf[0] & 48) !== 0) { + const error = this.createError(RangeError, "RSV2 and RSV3 must be clear", true, 1002, "WS_ERR_UNEXPECTED_RSV_2_3"); + cb(error); + return; + } + const compressed = (buf[0] & 64) === 64; + if (compressed && !this._extensions[PerMessageDeflate.extensionName]) { + const error = this.createError(RangeError, "RSV1 must be clear", true, 1002, "WS_ERR_UNEXPECTED_RSV_1"); + cb(error); + return; + } + this._fin = (buf[0] & 128) === 128; + this._opcode = buf[0] & 15; + this._payloadLength = buf[1] & 127; + if (this._opcode === 0) { + if (compressed) { + const error = this.createError(RangeError, "RSV1 must be clear", true, 1002, "WS_ERR_UNEXPECTED_RSV_1"); + cb(error); + return; + } + if (!this._fragmented) { + const error = this.createError(RangeError, "invalid opcode 0", true, 1002, "WS_ERR_INVALID_OPCODE"); + cb(error); + return; + } + this._opcode = this._fragmented; + } else if (this._opcode === 1 || this._opcode === 2) { + if (this._fragmented) { + const error = this.createError(RangeError, `invalid opcode ${this._opcode}`, true, 1002, "WS_ERR_INVALID_OPCODE"); + cb(error); + return; + } + this._compressed = compressed; + } else if (this._opcode > 7 && this._opcode < 11) { + if (!this._fin) { + const error = this.createError(RangeError, "FIN must be set", true, 1002, "WS_ERR_EXPECTED_FIN"); + cb(error); + return; + } + if (compressed) { + const error = this.createError(RangeError, "RSV1 must be clear", true, 1002, "WS_ERR_UNEXPECTED_RSV_1"); + cb(error); + return; + } + if (this._payloadLength > 125 || this._opcode === 8 && this._payloadLength === 1) { + const error = this.createError(RangeError, `invalid payload length ${this._payloadLength}`, true, 1002, "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"); + cb(error); + return; + } + } else { + const error = this.createError(RangeError, `invalid opcode ${this._opcode}`, true, 1002, "WS_ERR_INVALID_OPCODE"); + cb(error); + return; + } + if (!this._fin && !this._fragmented) + this._fragmented = this._opcode; + this._masked = (buf[1] & 128) === 128; + if (this._isServer) { + if (!this._masked) { + const error = this.createError(RangeError, "MASK must be set", true, 1002, "WS_ERR_EXPECTED_MASK"); + cb(error); + return; + } + } else if (this._masked) { + const error = this.createError(RangeError, "MASK must be clear", true, 1002, "WS_ERR_UNEXPECTED_MASK"); + cb(error); + return; + } + if (this._payloadLength === 126) + this._state = GET_PAYLOAD_LENGTH_16; + else if (this._payloadLength === 127) + this._state = GET_PAYLOAD_LENGTH_64; + else + this.haveLength(cb); + } + getPayloadLength16(cb) { + if (this._bufferedBytes < 2) { + this._loop = false; + return; + } + this._payloadLength = this.consume(2).readUInt16BE(0); + this.haveLength(cb); + } + getPayloadLength64(cb) { + if (this._bufferedBytes < 8) { + this._loop = false; + return; + } + const buf = this.consume(8); + const num = buf.readUInt32BE(0); + if (num > Math.pow(2, 53 - 32) - 1) { + const error = this.createError(RangeError, "Unsupported WebSocket frame: payload length > 2^53 - 1", false, 1009, "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"); + cb(error); + return; + } + this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4); + this.haveLength(cb); + } + haveLength(cb) { + if (this._payloadLength && this._opcode < 8) { + this._totalPayloadLength += this._payloadLength; + if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) { + const error = this.createError(RangeError, "Max payload size exceeded", false, 1009, "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"); + cb(error); + return; + } + } + if (this._masked) + this._state = GET_MASK; + else + this._state = GET_DATA; + } + getMask() { + if (this._bufferedBytes < 4) { + this._loop = false; + return; + } + this._mask = this.consume(4); + this._state = GET_DATA; + } + getData(cb) { + let data = EMPTY_BUFFER; + if (this._payloadLength) { + if (this._bufferedBytes < this._payloadLength) { + this._loop = false; + return; + } + data = this.consume(this._payloadLength); + if (this._masked && (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0) { + unmask(data, this._mask); + } + } + if (this._opcode > 7) { + this.controlMessage(data, cb); + return; + } + if (this._compressed) { + this._state = INFLATING; + this.decompress(data, cb); + return; + } + if (data.length) { + this._messageLength = this._totalPayloadLength; + this._fragments.push(data); + } + this.dataMessage(cb); + } + decompress(data, cb) { + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + perMessageDeflate.decompress(data, this._fin, (err, buf) => { + if (err) + return cb(err); + if (buf.length) { + this._messageLength += buf.length; + if (this._messageLength > this._maxPayload && this._maxPayload > 0) { + const error = this.createError(RangeError, "Max payload size exceeded", false, 1009, "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"); + cb(error); + return; + } + this._fragments.push(buf); + } + this.dataMessage(cb); + if (this._state === GET_INFO) + this.startLoop(cb); + }); + } + dataMessage(cb) { + if (!this._fin) { + this._state = GET_INFO; + return; + } + const messageLength = this._messageLength; + const fragments = this._fragments; + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragmented = 0; + this._fragments = []; + if (this._opcode === 2) { + let data; + if (this._binaryType === "nodebuffer") { + data = concat(fragments, messageLength); + } else if (this._binaryType === "arraybuffer") { + data = toArrayBuffer(concat(fragments, messageLength)); + } else { + data = fragments; + } + if (this._allowSynchronousEvents) { + this.emit("message", data, true); + this._state = GET_INFO; + } else { + this._state = DEFER_EVENT; + setImmediate(() => { + this.emit("message", data, true); + this._state = GET_INFO; + this.startLoop(cb); + }); + } + } else { + const buf = concat(fragments, messageLength); + if (!this._skipUTF8Validation && !isValidUTF8(buf)) { + const error = this.createError(Error, "invalid UTF-8 sequence", true, 1007, "WS_ERR_INVALID_UTF8"); + cb(error); + return; + } + if (this._state === INFLATING || this._allowSynchronousEvents) { + this.emit("message", buf, false); + this._state = GET_INFO; + } else { + this._state = DEFER_EVENT; + setImmediate(() => { + this.emit("message", buf, false); + this._state = GET_INFO; + this.startLoop(cb); + }); + } + } + } + controlMessage(data, cb) { + if (this._opcode === 8) { + if (data.length === 0) { + this._loop = false; + this.emit("conclude", 1005, EMPTY_BUFFER); + this.end(); + } else { + const code = data.readUInt16BE(0); + if (!isValidStatusCode(code)) { + const error = this.createError(RangeError, `invalid status code ${code}`, true, 1002, "WS_ERR_INVALID_CLOSE_CODE"); + cb(error); + return; + } + const buf = new FastBuffer(data.buffer, data.byteOffset + 2, data.length - 2); + if (!this._skipUTF8Validation && !isValidUTF8(buf)) { + const error = this.createError(Error, "invalid UTF-8 sequence", true, 1007, "WS_ERR_INVALID_UTF8"); + cb(error); + return; + } + this._loop = false; + this.emit("conclude", code, buf); + this.end(); + } + this._state = GET_INFO; + return; + } + if (this._allowSynchronousEvents) { + this.emit(this._opcode === 9 ? "ping" : "pong", data); + this._state = GET_INFO; + } else { + this._state = DEFER_EVENT; + setImmediate(() => { + this.emit(this._opcode === 9 ? "ping" : "pong", data); + this._state = GET_INFO; + this.startLoop(cb); + }); + } + } + createError(ErrorCtor, message, prefix, statusCode, errorCode) { + this._loop = false; + this._errored = true; + const err = new ErrorCtor(prefix ? `Invalid WebSocket frame: ${message}` : message); + Error.captureStackTrace(err, this.createError); + err.code = errorCode; + err[kStatusCode] = statusCode; + return err; + } + } + module2.exports = Receiver; +}); + +// node_modules/ws/lib/sender.js +var require_sender = __commonJS((exports2, module2) => { + var { Duplex } = require("stream"); + var { randomFillSync } = require("crypto"); + var PerMessageDeflate = require_permessage_deflate(); + var { EMPTY_BUFFER } = require_constants(); + var { isValidStatusCode } = require_validation(); + var { mask: applyMask, toBuffer } = require_buffer_util(); + var kByteLength = Symbol("kByteLength"); + var maskBuffer = Buffer.alloc(4); + var RANDOM_POOL_SIZE = 8 * 1024; + var randomPool; + var randomPoolPointer = RANDOM_POOL_SIZE; + + class Sender { + constructor(socket, extensions, generateMask) { + this._extensions = extensions || {}; + if (generateMask) { + this._generateMask = generateMask; + this._maskBuffer = Buffer.alloc(4); + } + this._socket = socket; + this._firstFragment = true; + this._compress = false; + this._bufferedBytes = 0; + this._deflating = false; + this._queue = []; + } + static frame(data, options) { + let mask; + let merge = false; + let offset = 2; + let skipMasking = false; + if (options.mask) { + mask = options.maskBuffer || maskBuffer; + if (options.generateMask) { + options.generateMask(mask); + } else { + if (randomPoolPointer === RANDOM_POOL_SIZE) { + if (randomPool === undefined) { + randomPool = Buffer.alloc(RANDOM_POOL_SIZE); + } + randomFillSync(randomPool, 0, RANDOM_POOL_SIZE); + randomPoolPointer = 0; + } + mask[0] = randomPool[randomPoolPointer++]; + mask[1] = randomPool[randomPoolPointer++]; + mask[2] = randomPool[randomPoolPointer++]; + mask[3] = randomPool[randomPoolPointer++]; + } + skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0; + offset = 6; + } + let dataLength; + if (typeof data === "string") { + if ((!options.mask || skipMasking) && options[kByteLength] !== undefined) { + dataLength = options[kByteLength]; + } else { + data = Buffer.from(data); + dataLength = data.length; + } + } else { + dataLength = data.length; + merge = options.mask && options.readOnly && !skipMasking; + } + let payloadLength = dataLength; + if (dataLength >= 65536) { + offset += 8; + payloadLength = 127; + } else if (dataLength > 125) { + offset += 2; + payloadLength = 126; + } + const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset); + target[0] = options.fin ? options.opcode | 128 : options.opcode; + if (options.rsv1) + target[0] |= 64; + target[1] = payloadLength; + if (payloadLength === 126) { + target.writeUInt16BE(dataLength, 2); + } else if (payloadLength === 127) { + target[2] = target[3] = 0; + target.writeUIntBE(dataLength, 4, 6); + } + if (!options.mask) + return [target, data]; + target[1] |= 128; + target[offset - 4] = mask[0]; + target[offset - 3] = mask[1]; + target[offset - 2] = mask[2]; + target[offset - 1] = mask[3]; + if (skipMasking) + return [target, data]; + if (merge) { + applyMask(data, mask, target, offset, dataLength); + return [target]; + } + applyMask(data, mask, data, 0, dataLength); + return [target, data]; + } + close(code, data, mask, cb) { + let buf; + if (code === undefined) { + buf = EMPTY_BUFFER; + } else if (typeof code !== "number" || !isValidStatusCode(code)) { + throw new TypeError("First argument must be a valid error code number"); + } else if (data === undefined || !data.length) { + buf = Buffer.allocUnsafe(2); + buf.writeUInt16BE(code, 0); + } else { + const length = Buffer.byteLength(data); + if (length > 123) { + throw new RangeError("The message must not be greater than 123 bytes"); + } + buf = Buffer.allocUnsafe(2 + length); + buf.writeUInt16BE(code, 0); + if (typeof data === "string") { + buf.write(data, 2); + } else { + buf.set(data, 2); + } + } + const options = { + [kByteLength]: buf.length, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 8, + readOnly: false, + rsv1: false + }; + if (this._deflating) { + this.enqueue([this.dispatch, buf, false, options, cb]); + } else { + this.sendFrame(Sender.frame(buf, options), cb); + } + } + ping(data, mask, cb) { + let byteLength; + let readOnly; + if (typeof data === "string") { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; + } + if (byteLength > 125) { + throw new RangeError("The data size must not be greater than 125 bytes"); + } + const options = { + [kByteLength]: byteLength, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 9, + readOnly, + rsv1: false + }; + if (this._deflating) { + this.enqueue([this.dispatch, data, false, options, cb]); + } else { + this.sendFrame(Sender.frame(data, options), cb); + } + } + pong(data, mask, cb) { + let byteLength; + let readOnly; + if (typeof data === "string") { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; + } + if (byteLength > 125) { + throw new RangeError("The data size must not be greater than 125 bytes"); + } + const options = { + [kByteLength]: byteLength, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 10, + readOnly, + rsv1: false + }; + if (this._deflating) { + this.enqueue([this.dispatch, data, false, options, cb]); + } else { + this.sendFrame(Sender.frame(data, options), cb); + } + } + send(data, options, cb) { + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + let opcode = options.binary ? 2 : 1; + let rsv1 = options.compress; + let byteLength; + let readOnly; + if (typeof data === "string") { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; + } + if (this._firstFragment) { + this._firstFragment = false; + if (rsv1 && perMessageDeflate && perMessageDeflate.params[perMessageDeflate._isServer ? "server_no_context_takeover" : "client_no_context_takeover"]) { + rsv1 = byteLength >= perMessageDeflate._threshold; + } + this._compress = rsv1; + } else { + rsv1 = false; + opcode = 0; + } + if (options.fin) + this._firstFragment = true; + if (perMessageDeflate) { + const opts = { + [kByteLength]: byteLength, + fin: options.fin, + generateMask: this._generateMask, + mask: options.mask, + maskBuffer: this._maskBuffer, + opcode, + readOnly, + rsv1 + }; + if (this._deflating) { + this.enqueue([this.dispatch, data, this._compress, opts, cb]); + } else { + this.dispatch(data, this._compress, opts, cb); + } + } else { + this.sendFrame(Sender.frame(data, { + [kByteLength]: byteLength, + fin: options.fin, + generateMask: this._generateMask, + mask: options.mask, + maskBuffer: this._maskBuffer, + opcode, + readOnly, + rsv1: false + }), cb); + } + } + dispatch(data, compress, options, cb) { + if (!compress) { + this.sendFrame(Sender.frame(data, options), cb); + return; + } + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + this._bufferedBytes += options[kByteLength]; + this._deflating = true; + perMessageDeflate.compress(data, options.fin, (_, buf) => { + if (this._socket.destroyed) { + const err = new Error("The socket was closed while data was being compressed"); + if (typeof cb === "function") + cb(err); + for (let i = 0;i < this._queue.length; i++) { + const params = this._queue[i]; + const callback = params[params.length - 1]; + if (typeof callback === "function") + callback(err); + } + return; + } + this._bufferedBytes -= options[kByteLength]; + this._deflating = false; + options.readOnly = false; + this.sendFrame(Sender.frame(buf, options), cb); + this.dequeue(); + }); + } + dequeue() { + while (!this._deflating && this._queue.length) { + const params = this._queue.shift(); + this._bufferedBytes -= params[3][kByteLength]; + Reflect.apply(params[0], this, params.slice(1)); + } + } + enqueue(params) { + this._bufferedBytes += params[3][kByteLength]; + this._queue.push(params); + } + sendFrame(list, cb) { + if (list.length === 2) { + this._socket.cork(); + this._socket.write(list[0]); + this._socket.write(list[1], cb); + this._socket.uncork(); + } else { + this._socket.write(list[0], cb); + } + } + } + module2.exports = Sender; +}); + +// node_modules/ws/lib/event-target.js +var require_event_target = __commonJS((exports2, module2) => { + var { kForOnEventAttribute, kListener } = require_constants(); + var kCode = Symbol("kCode"); + var kData = Symbol("kData"); + var kError = Symbol("kError"); + var kMessage = Symbol("kMessage"); + var kReason = Symbol("kReason"); + var kTarget = Symbol("kTarget"); + var kType = Symbol("kType"); + var kWasClean = Symbol("kWasClean"); + + class Event { + constructor(type) { + this[kTarget] = null; + this[kType] = type; + } + get target() { + return this[kTarget]; + } + get type() { + return this[kType]; + } + } + Object.defineProperty(Event.prototype, "target", { enumerable: true }); + Object.defineProperty(Event.prototype, "type", { enumerable: true }); + + class CloseEvent extends Event { + constructor(type, options = {}) { + super(type); + this[kCode] = options.code === undefined ? 0 : options.code; + this[kReason] = options.reason === undefined ? "" : options.reason; + this[kWasClean] = options.wasClean === undefined ? false : options.wasClean; + } + get code() { + return this[kCode]; + } + get reason() { + return this[kReason]; + } + get wasClean() { + return this[kWasClean]; + } + } + Object.defineProperty(CloseEvent.prototype, "code", { enumerable: true }); + Object.defineProperty(CloseEvent.prototype, "reason", { enumerable: true }); + Object.defineProperty(CloseEvent.prototype, "wasClean", { enumerable: true }); + + class ErrorEvent extends Event { + constructor(type, options = {}) { + super(type); + this[kError] = options.error === undefined ? null : options.error; + this[kMessage] = options.message === undefined ? "" : options.message; + } + get error() { + return this[kError]; + } + get message() { + return this[kMessage]; + } + } + Object.defineProperty(ErrorEvent.prototype, "error", { enumerable: true }); + Object.defineProperty(ErrorEvent.prototype, "message", { enumerable: true }); + + class MessageEvent extends Event { + constructor(type, options = {}) { + super(type); + this[kData] = options.data === undefined ? null : options.data; + } + get data() { + return this[kData]; + } + } + Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true }); + var EventTarget = { + addEventListener(type, handler, options = {}) { + for (const listener of this.listeners(type)) { + if (!options[kForOnEventAttribute] && listener[kListener] === handler && !listener[kForOnEventAttribute]) { + return; + } + } + let wrapper; + if (type === "message") { + wrapper = function onMessage(data, isBinary) { + const event = new MessageEvent("message", { + data: isBinary ? data : data.toString() + }); + event[kTarget] = this; + callListener(handler, this, event); + }; + } else if (type === "close") { + wrapper = function onClose(code, message) { + const event = new CloseEvent("close", { + code, + reason: message.toString(), + wasClean: this._closeFrameReceived && this._closeFrameSent + }); + event[kTarget] = this; + callListener(handler, this, event); + }; + } else if (type === "error") { + wrapper = function onError(error) { + const event = new ErrorEvent("error", { + error, + message: error.message + }); + event[kTarget] = this; + callListener(handler, this, event); + }; + } else if (type === "open") { + wrapper = function onOpen() { + const event = new Event("open"); + event[kTarget] = this; + callListener(handler, this, event); + }; + } else { + return; + } + wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute]; + wrapper[kListener] = handler; + if (options.once) { + this.once(type, wrapper); + } else { + this.on(type, wrapper); + } + }, + removeEventListener(type, handler) { + for (const listener of this.listeners(type)) { + if (listener[kListener] === handler && !listener[kForOnEventAttribute]) { + this.removeListener(type, listener); + break; + } + } + } + }; + module2.exports = { + CloseEvent, + ErrorEvent, + Event, + EventTarget, + MessageEvent + }; + function callListener(listener, thisArg, event) { + if (typeof listener === "object" && listener.handleEvent) { + listener.handleEvent.call(listener, event); + } else { + listener.call(thisArg, event); + } + } +}); + +// node_modules/ws/lib/extension.js +var require_extension = __commonJS((exports2, module2) => { + var { tokenChars } = require_validation(); + function push(dest, name, elem) { + if (dest[name] === undefined) + dest[name] = [elem]; + else + dest[name].push(elem); + } + function parse(header) { + const offers = Object.create(null); + let params = Object.create(null); + let mustUnescape = false; + let isEscaping = false; + let inQuotes = false; + let extensionName; + let paramName; + let start = -1; + let code = -1; + let end = -1; + let i = 0; + for (;i < header.length; i++) { + code = header.charCodeAt(i); + if (extensionName === undefined) { + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) + start = i; + } else if (i !== 0 && (code === 32 || code === 9)) { + if (end === -1 && start !== -1) + end = i; + } else if (code === 59 || code === 44) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + if (end === -1) + end = i; + const name = header.slice(start, end); + if (code === 44) { + push(offers, name, params); + params = Object.create(null); + } else { + extensionName = name; + } + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else if (paramName === undefined) { + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) + start = i; + } else if (code === 32 || code === 9) { + if (end === -1 && start !== -1) + end = i; + } else if (code === 59 || code === 44) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + if (end === -1) + end = i; + push(params, header.slice(start, end), true); + if (code === 44) { + push(offers, extensionName, params); + params = Object.create(null); + extensionName = undefined; + } + start = end = -1; + } else if (code === 61 && start !== -1 && end === -1) { + paramName = header.slice(start, i); + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else { + if (isEscaping) { + if (tokenChars[code] !== 1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + if (start === -1) + start = i; + else if (!mustUnescape) + mustUnescape = true; + isEscaping = false; + } else if (inQuotes) { + if (tokenChars[code] === 1) { + if (start === -1) + start = i; + } else if (code === 34 && start !== -1) { + inQuotes = false; + end = i; + } else if (code === 92) { + isEscaping = true; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else if (code === 34 && header.charCodeAt(i - 1) === 61) { + inQuotes = true; + } else if (end === -1 && tokenChars[code] === 1) { + if (start === -1) + start = i; + } else if (start !== -1 && (code === 32 || code === 9)) { + if (end === -1) + end = i; + } else if (code === 59 || code === 44) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + if (end === -1) + end = i; + let value = header.slice(start, end); + if (mustUnescape) { + value = value.replace(/\\/g, ""); + mustUnescape = false; + } + push(params, paramName, value); + if (code === 44) { + push(offers, extensionName, params); + params = Object.create(null); + extensionName = undefined; + } + paramName = undefined; + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } + } + if (start === -1 || inQuotes || code === 32 || code === 9) { + throw new SyntaxError("Unexpected end of input"); + } + if (end === -1) + end = i; + const token = header.slice(start, end); + if (extensionName === undefined) { + push(offers, token, params); + } else { + if (paramName === undefined) { + push(params, token, true); + } else if (mustUnescape) { + push(params, paramName, token.replace(/\\/g, "")); + } else { + push(params, paramName, token); + } + push(offers, extensionName, params); + } + return offers; + } + function format(extensions) { + return Object.keys(extensions).map((extension) => { + let configurations = extensions[extension]; + if (!Array.isArray(configurations)) + configurations = [configurations]; + return configurations.map((params) => { + return [extension].concat(Object.keys(params).map((k) => { + let values = params[k]; + if (!Array.isArray(values)) + values = [values]; + return values.map((v) => v === true ? k : `${k}=${v}`).join("; "); + })).join("; "); + }).join(", "); + }).join(", "); + } + module2.exports = { format, parse }; +}); + +// node_modules/ws/lib/websocket.js +var require_websocket2 = __commonJS((exports2, module2) => { + var EventEmitter = require("events"); + var https = require("https"); + var http = require("http"); + var net = require("net"); + var tls = require("tls"); + var { randomBytes, createHash } = require("crypto"); + var { Duplex, Readable } = require("stream"); + var { URL } = require("url"); + var PerMessageDeflate = require_permessage_deflate(); + var Receiver = require_receiver(); + var Sender = require_sender(); + var { + BINARY_TYPES, + EMPTY_BUFFER, + GUID, + kForOnEventAttribute, + kListener, + kStatusCode, + kWebSocket, + NOOP + } = require_constants(); + var { + EventTarget: { addEventListener: addEventListener2, removeEventListener: removeEventListener2 } + } = require_event_target(); + var { format, parse } = require_extension(); + var { toBuffer } = require_buffer_util(); + var closeTimeout = 30 * 1000; + var kAborted = Symbol("kAborted"); + var protocolVersions = [8, 13]; + var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"]; + var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/; + + class WebSocket extends EventEmitter { + constructor(address, protocols, options) { + super(); + this._binaryType = BINARY_TYPES[0]; + this._closeCode = 1006; + this._closeFrameReceived = false; + this._closeFrameSent = false; + this._closeMessage = EMPTY_BUFFER; + this._closeTimer = null; + this._extensions = {}; + this._paused = false; + this._protocol = ""; + this._readyState = WebSocket.CONNECTING; + this._receiver = null; + this._sender = null; + this._socket = null; + if (address !== null) { + this._bufferedAmount = 0; + this._isServer = false; + this._redirects = 0; + if (protocols === undefined) { + protocols = []; + } else if (!Array.isArray(protocols)) { + if (typeof protocols === "object" && protocols !== null) { + options = protocols; + protocols = []; + } else { + protocols = [protocols]; + } + } + initAsClient(this, address, protocols, options); + } else { + this._autoPong = options.autoPong; + this._isServer = true; + } + } + get binaryType() { + return this._binaryType; + } + set binaryType(type) { + if (!BINARY_TYPES.includes(type)) + return; + this._binaryType = type; + if (this._receiver) + this._receiver._binaryType = type; + } + get bufferedAmount() { + if (!this._socket) + return this._bufferedAmount; + return this._socket._writableState.length + this._sender._bufferedBytes; + } + get extensions() { + return Object.keys(this._extensions).join(); + } + get isPaused() { + return this._paused; + } + get onclose() { + return null; + } + get onerror() { + return null; + } + get onopen() { + return null; + } + get onmessage() { + return null; + } + get protocol() { + return this._protocol; + } + get readyState() { + return this._readyState; + } + get url() { + return this._url; + } + setSocket(socket, head, options) { + const receiver = new Receiver({ + allowSynchronousEvents: options.allowSynchronousEvents, + binaryType: this.binaryType, + extensions: this._extensions, + isServer: this._isServer, + maxPayload: options.maxPayload, + skipUTF8Validation: options.skipUTF8Validation + }); + this._sender = new Sender(socket, this._extensions, options.generateMask); + this._receiver = receiver; + this._socket = socket; + receiver[kWebSocket] = this; + socket[kWebSocket] = this; + receiver.on("conclude", receiverOnConclude); + receiver.on("drain", receiverOnDrain); + receiver.on("error", receiverOnError); + receiver.on("message", receiverOnMessage); + receiver.on("ping", receiverOnPing); + receiver.on("pong", receiverOnPong); + if (socket.setTimeout) + socket.setTimeout(0); + if (socket.setNoDelay) + socket.setNoDelay(); + if (head.length > 0) + socket.unshift(head); + socket.on("close", socketOnClose); + socket.on("data", socketOnData); + socket.on("end", socketOnEnd); + socket.on("error", socketOnError); + this._readyState = WebSocket.OPEN; + this.emit("open"); + } + emitClose() { + if (!this._socket) { + this._readyState = WebSocket.CLOSED; + this.emit("close", this._closeCode, this._closeMessage); + return; + } + if (this._extensions[PerMessageDeflate.extensionName]) { + this._extensions[PerMessageDeflate.extensionName].cleanup(); + } + this._receiver.removeAllListeners(); + this._readyState = WebSocket.CLOSED; + this.emit("close", this._closeCode, this._closeMessage); + } + close(code, data) { + if (this.readyState === WebSocket.CLOSED) + return; + if (this.readyState === WebSocket.CONNECTING) { + const msg = "WebSocket was closed before the connection was established"; + abortHandshake(this, this._req, msg); + return; + } + if (this.readyState === WebSocket.CLOSING) { + if (this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted)) { + this._socket.end(); + } + return; + } + this._readyState = WebSocket.CLOSING; + this._sender.close(code, data, !this._isServer, (err) => { + if (err) + return; + this._closeFrameSent = true; + if (this._closeFrameReceived || this._receiver._writableState.errorEmitted) { + this._socket.end(); + } + }); + this._closeTimer = setTimeout(this._socket.destroy.bind(this._socket), closeTimeout); + } + pause() { + if (this.readyState === WebSocket.CONNECTING || this.readyState === WebSocket.CLOSED) { + return; + } + this._paused = true; + this._socket.pause(); + } + ping(data, mask, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); + } + if (typeof data === "function") { + cb = data; + data = mask = undefined; + } else if (typeof mask === "function") { + cb = mask; + mask = undefined; + } + if (typeof data === "number") + data = data.toString(); + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + if (mask === undefined) + mask = !this._isServer; + this._sender.ping(data || EMPTY_BUFFER, mask, cb); + } + pong(data, mask, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); + } + if (typeof data === "function") { + cb = data; + data = mask = undefined; + } else if (typeof mask === "function") { + cb = mask; + mask = undefined; + } + if (typeof data === "number") + data = data.toString(); + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + if (mask === undefined) + mask = !this._isServer; + this._sender.pong(data || EMPTY_BUFFER, mask, cb); + } + resume() { + if (this.readyState === WebSocket.CONNECTING || this.readyState === WebSocket.CLOSED) { + return; + } + this._paused = false; + if (!this._receiver._writableState.needDrain) + this._socket.resume(); + } + send(data, options, cb) { + if (this.readyState === WebSocket.CONNECTING) { + throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); + } + if (typeof options === "function") { + cb = options; + options = {}; + } + if (typeof data === "number") + data = data.toString(); + if (this.readyState !== WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; + } + const opts = { + binary: typeof data !== "string", + mask: !this._isServer, + compress: true, + fin: true, + ...options + }; + if (!this._extensions[PerMessageDeflate.extensionName]) { + opts.compress = false; + } + this._sender.send(data || EMPTY_BUFFER, opts, cb); + } + terminate() { + if (this.readyState === WebSocket.CLOSED) + return; + if (this.readyState === WebSocket.CONNECTING) { + const msg = "WebSocket was closed before the connection was established"; + abortHandshake(this, this._req, msg); + return; + } + if (this._socket) { + this._readyState = WebSocket.CLOSING; + this._socket.destroy(); + } + } + } + Object.defineProperty(WebSocket, "CONNECTING", { + enumerable: true, + value: readyStates.indexOf("CONNECTING") + }); + Object.defineProperty(WebSocket.prototype, "CONNECTING", { + enumerable: true, + value: readyStates.indexOf("CONNECTING") + }); + Object.defineProperty(WebSocket, "OPEN", { + enumerable: true, + value: readyStates.indexOf("OPEN") + }); + Object.defineProperty(WebSocket.prototype, "OPEN", { + enumerable: true, + value: readyStates.indexOf("OPEN") + }); + Object.defineProperty(WebSocket, "CLOSING", { + enumerable: true, + value: readyStates.indexOf("CLOSING") + }); + Object.defineProperty(WebSocket.prototype, "CLOSING", { + enumerable: true, + value: readyStates.indexOf("CLOSING") + }); + Object.defineProperty(WebSocket, "CLOSED", { + enumerable: true, + value: readyStates.indexOf("CLOSED") + }); + Object.defineProperty(WebSocket.prototype, "CLOSED", { + enumerable: true, + value: readyStates.indexOf("CLOSED") + }); + [ + "binaryType", + "bufferedAmount", + "extensions", + "isPaused", + "protocol", + "readyState", + "url" + ].forEach((property) => { + Object.defineProperty(WebSocket.prototype, property, { enumerable: true }); + }); + ["open", "error", "close", "message"].forEach((method) => { + Object.defineProperty(WebSocket.prototype, `on${method}`, { + enumerable: true, + get() { + for (const listener of this.listeners(method)) { + if (listener[kForOnEventAttribute]) + return listener[kListener]; + } + return null; + }, + set(handler) { + for (const listener of this.listeners(method)) { + if (listener[kForOnEventAttribute]) { + this.removeListener(method, listener); + break; + } + } + if (typeof handler !== "function") + return; + this.addEventListener(method, handler, { + [kForOnEventAttribute]: true + }); + } + }); + }); + WebSocket.prototype.addEventListener = addEventListener2; + WebSocket.prototype.removeEventListener = removeEventListener2; + module2.exports = WebSocket; + function initAsClient(websocket, address, protocols, options) { + const opts = { + allowSynchronousEvents: true, + autoPong: true, + protocolVersion: protocolVersions[1], + maxPayload: 100 * 1024 * 1024, + skipUTF8Validation: false, + perMessageDeflate: true, + followRedirects: false, + maxRedirects: 10, + ...options, + socketPath: undefined, + hostname: undefined, + protocol: undefined, + timeout: undefined, + method: "GET", + host: undefined, + path: undefined, + port: undefined + }; + websocket._autoPong = opts.autoPong; + if (!protocolVersions.includes(opts.protocolVersion)) { + throw new RangeError(`Unsupported protocol version: ${opts.protocolVersion} ` + `(supported versions: ${protocolVersions.join(", ")})`); + } + let parsedUrl; + if (address instanceof URL) { + parsedUrl = address; + } else { + try { + parsedUrl = new URL(address); + } catch (e) { + throw new SyntaxError(`Invalid URL: ${address}`); + } + } + if (parsedUrl.protocol === "http:") { + parsedUrl.protocol = "ws:"; + } else if (parsedUrl.protocol === "https:") { + parsedUrl.protocol = "wss:"; + } + websocket._url = parsedUrl.href; + const isSecure = parsedUrl.protocol === "wss:"; + const isIpcUrl = parsedUrl.protocol === "ws+unix:"; + let invalidUrlMessage; + if (parsedUrl.protocol !== "ws:" && !isSecure && !isIpcUrl) { + invalidUrlMessage = `The URL's protocol must be one of "ws:", "wss:", ` + '"http:", "https", or "ws+unix:"'; + } else if (isIpcUrl && !parsedUrl.pathname) { + invalidUrlMessage = "The URL's pathname is empty"; + } else if (parsedUrl.hash) { + invalidUrlMessage = "The URL contains a fragment identifier"; + } + if (invalidUrlMessage) { + const err = new SyntaxError(invalidUrlMessage); + if (websocket._redirects === 0) { + throw err; + } else { + emitErrorAndClose(websocket, err); + return; + } + } + const defaultPort = isSecure ? 443 : 80; + const key = randomBytes(16).toString("base64"); + const request = isSecure ? https.request : http.request; + const protocolSet = new Set; + let perMessageDeflate; + opts.createConnection = opts.createConnection || (isSecure ? tlsConnect : netConnect); + opts.defaultPort = opts.defaultPort || defaultPort; + opts.port = parsedUrl.port || defaultPort; + opts.host = parsedUrl.hostname.startsWith("[") ? parsedUrl.hostname.slice(1, -1) : parsedUrl.hostname; + opts.headers = { + ...opts.headers, + "Sec-WebSocket-Version": opts.protocolVersion, + "Sec-WebSocket-Key": key, + Connection: "Upgrade", + Upgrade: "websocket" + }; + opts.path = parsedUrl.pathname + parsedUrl.search; + opts.timeout = opts.handshakeTimeout; + if (opts.perMessageDeflate) { + perMessageDeflate = new PerMessageDeflate(opts.perMessageDeflate !== true ? opts.perMessageDeflate : {}, false, opts.maxPayload); + opts.headers["Sec-WebSocket-Extensions"] = format({ + [PerMessageDeflate.extensionName]: perMessageDeflate.offer() + }); + } + if (protocols.length) { + for (const protocol of protocols) { + if (typeof protocol !== "string" || !subprotocolRegex.test(protocol) || protocolSet.has(protocol)) { + throw new SyntaxError("An invalid or duplicated subprotocol was specified"); + } + protocolSet.add(protocol); + } + opts.headers["Sec-WebSocket-Protocol"] = protocols.join(","); + } + if (opts.origin) { + if (opts.protocolVersion < 13) { + opts.headers["Sec-WebSocket-Origin"] = opts.origin; + } else { + opts.headers.Origin = opts.origin; + } + } + if (parsedUrl.username || parsedUrl.password) { + opts.auth = `${parsedUrl.username}:${parsedUrl.password}`; + } + if (isIpcUrl) { + const parts = opts.path.split(":"); + opts.socketPath = parts[0]; + opts.path = parts[1]; + } + let req; + if (opts.followRedirects) { + if (websocket._redirects === 0) { + websocket._originalIpc = isIpcUrl; + websocket._originalSecure = isSecure; + websocket._originalHostOrSocketPath = isIpcUrl ? opts.socketPath : parsedUrl.host; + const headers = options && options.headers; + options = { ...options, headers: {} }; + if (headers) { + for (const [key2, value] of Object.entries(headers)) { + options.headers[key2.toLowerCase()] = value; + } + } + } else if (websocket.listenerCount("redirect") === 0) { + const isSameHost = isIpcUrl ? websocket._originalIpc ? opts.socketPath === websocket._originalHostOrSocketPath : false : websocket._originalIpc ? false : parsedUrl.host === websocket._originalHostOrSocketPath; + if (!isSameHost || websocket._originalSecure && !isSecure) { + delete opts.headers.authorization; + delete opts.headers.cookie; + if (!isSameHost) + delete opts.headers.host; + opts.auth = undefined; + } + } + if (opts.auth && !options.headers.authorization) { + options.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64"); + } + req = websocket._req = request(opts); + if (websocket._redirects) { + websocket.emit("redirect", websocket.url, req); + } + } else { + req = websocket._req = request(opts); + } + if (opts.timeout) { + req.on("timeout", () => { + abortHandshake(websocket, req, "Opening handshake has timed out"); + }); + } + req.on("error", (err) => { + if (req === null || req[kAborted]) + return; + req = websocket._req = null; + emitErrorAndClose(websocket, err); + }); + req.on("response", (res) => { + const location2 = res.headers.location; + const statusCode = res.statusCode; + if (location2 && opts.followRedirects && statusCode >= 300 && statusCode < 400) { + if (++websocket._redirects > opts.maxRedirects) { + abortHandshake(websocket, req, "Maximum redirects exceeded"); + return; + } + req.abort(); + let addr; + try { + addr = new URL(location2, address); + } catch (e) { + const err = new SyntaxError(`Invalid URL: ${location2}`); + emitErrorAndClose(websocket, err); + return; + } + initAsClient(websocket, addr, protocols, options); + } else if (!websocket.emit("unexpected-response", req, res)) { + abortHandshake(websocket, req, `Unexpected server response: ${res.statusCode}`); + } + }); + req.on("upgrade", (res, socket, head) => { + websocket.emit("upgrade", res); + if (websocket.readyState !== WebSocket.CONNECTING) + return; + req = websocket._req = null; + const upgrade = res.headers.upgrade; + if (upgrade === undefined || upgrade.toLowerCase() !== "websocket") { + abortHandshake(websocket, socket, "Invalid Upgrade header"); + return; + } + const digest = createHash("sha1").update(key + GUID).digest("base64"); + if (res.headers["sec-websocket-accept"] !== digest) { + abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header"); + return; + } + const serverProt = res.headers["sec-websocket-protocol"]; + let protError; + if (serverProt !== undefined) { + if (!protocolSet.size) { + protError = "Server sent a subprotocol but none was requested"; + } else if (!protocolSet.has(serverProt)) { + protError = "Server sent an invalid subprotocol"; + } + } else if (protocolSet.size) { + protError = "Server sent no subprotocol"; + } + if (protError) { + abortHandshake(websocket, socket, protError); + return; + } + if (serverProt) + websocket._protocol = serverProt; + const secWebSocketExtensions = res.headers["sec-websocket-extensions"]; + if (secWebSocketExtensions !== undefined) { + if (!perMessageDeflate) { + const message = "Server sent a Sec-WebSocket-Extensions header but no extension " + "was requested"; + abortHandshake(websocket, socket, message); + return; + } + let extensions; + try { + extensions = parse(secWebSocketExtensions); + } catch (err) { + const message = "Invalid Sec-WebSocket-Extensions header"; + abortHandshake(websocket, socket, message); + return; + } + const extensionNames = Object.keys(extensions); + if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate.extensionName) { + const message = "Server indicated an extension that was not requested"; + abortHandshake(websocket, socket, message); + return; + } + try { + perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]); + } catch (err) { + const message = "Invalid Sec-WebSocket-Extensions header"; + abortHandshake(websocket, socket, message); + return; + } + websocket._extensions[PerMessageDeflate.extensionName] = perMessageDeflate; + } + websocket.setSocket(socket, head, { + allowSynchronousEvents: opts.allowSynchronousEvents, + generateMask: opts.generateMask, + maxPayload: opts.maxPayload, + skipUTF8Validation: opts.skipUTF8Validation + }); + }); + if (opts.finishRequest) { + opts.finishRequest(req, websocket); + } else { + req.end(); + } + } + function emitErrorAndClose(websocket, err) { + websocket._readyState = WebSocket.CLOSING; + websocket.emit("error", err); + websocket.emitClose(); + } + function netConnect(options) { + options.path = options.socketPath; + return net.connect(options); + } + function tlsConnect(options) { + options.path = undefined; + if (!options.servername && options.servername !== "") { + options.servername = net.isIP(options.host) ? "" : options.host; + } + return tls.connect(options); + } + function abortHandshake(websocket, stream, message) { + websocket._readyState = WebSocket.CLOSING; + const err = new Error(message); + Error.captureStackTrace(err, abortHandshake); + if (stream.setHeader) { + stream[kAborted] = true; + stream.abort(); + if (stream.socket && !stream.socket.destroyed) { + stream.socket.destroy(); + } + process.nextTick(emitErrorAndClose, websocket, err); + } else { + stream.destroy(err); + stream.once("error", websocket.emit.bind(websocket, "error")); + stream.once("close", websocket.emitClose.bind(websocket)); + } + } + function sendAfterClose(websocket, data, cb) { + if (data) { + const length = toBuffer(data).length; + if (websocket._socket) + websocket._sender._bufferedBytes += length; + else + websocket._bufferedAmount += length; + } + if (cb) { + const err = new Error(`WebSocket is not open: readyState ${websocket.readyState} ` + `(${readyStates[websocket.readyState]})`); + process.nextTick(cb, err); + } + } + function receiverOnConclude(code, reason) { + const websocket = this[kWebSocket]; + websocket._closeFrameReceived = true; + websocket._closeMessage = reason; + websocket._closeCode = code; + if (websocket._socket[kWebSocket] === undefined) + return; + websocket._socket.removeListener("data", socketOnData); + process.nextTick(resume, websocket._socket); + if (code === 1005) + websocket.close(); + else + websocket.close(code, reason); + } + function receiverOnDrain() { + const websocket = this[kWebSocket]; + if (!websocket.isPaused) + websocket._socket.resume(); + } + function receiverOnError(err) { + const websocket = this[kWebSocket]; + if (websocket._socket[kWebSocket] !== undefined) { + websocket._socket.removeListener("data", socketOnData); + process.nextTick(resume, websocket._socket); + websocket.close(err[kStatusCode]); + } + websocket.emit("error", err); + } + function receiverOnFinish() { + this[kWebSocket].emitClose(); + } + function receiverOnMessage(data, isBinary) { + this[kWebSocket].emit("message", data, isBinary); + } + function receiverOnPing(data) { + const websocket = this[kWebSocket]; + if (websocket._autoPong) + websocket.pong(data, !this._isServer, NOOP); + websocket.emit("ping", data); + } + function receiverOnPong(data) { + this[kWebSocket].emit("pong", data); + } + function resume(stream) { + stream.resume(); + } + function socketOnClose() { + const websocket = this[kWebSocket]; + this.removeListener("close", socketOnClose); + this.removeListener("data", socketOnData); + this.removeListener("end", socketOnEnd); + websocket._readyState = WebSocket.CLOSING; + let chunk; + if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && (chunk = websocket._socket.read()) !== null) { + websocket._receiver.write(chunk); + } + websocket._receiver.end(); + this[kWebSocket] = undefined; + clearTimeout(websocket._closeTimer); + if (websocket._receiver._writableState.finished || websocket._receiver._writableState.errorEmitted) { + websocket.emitClose(); + } else { + websocket._receiver.on("error", receiverOnFinish); + websocket._receiver.on("finish", receiverOnFinish); + } + } + function socketOnData(chunk) { + if (!this[kWebSocket]._receiver.write(chunk)) { + this.pause(); + } + } + function socketOnEnd() { + const websocket = this[kWebSocket]; + websocket._readyState = WebSocket.CLOSING; + websocket._receiver.end(); + this.end(); + } + function socketOnError() { + const websocket = this[kWebSocket]; + this.removeListener("error", socketOnError); + this.on("error", NOOP); + if (websocket) { + websocket._readyState = WebSocket.CLOSING; + this.destroy(); + } + } +}); + +// node_modules/ws/lib/stream.js +var require_stream = __commonJS((exports2, module2) => { + var { Duplex } = require("stream"); + function emitClose(stream) { + stream.emit("close"); + } + function duplexOnEnd() { + if (!this.destroyed && this._writableState.finished) { + this.destroy(); + } + } + function duplexOnError(err) { + this.removeListener("error", duplexOnError); + this.destroy(); + if (this.listenerCount("error") === 0) { + this.emit("error", err); + } + } + function createWebSocketStream(ws, options) { + let terminateOnDestroy = true; + const duplex = new Duplex({ + ...options, + autoDestroy: false, + emitClose: false, + objectMode: false, + writableObjectMode: false + }); + ws.on("message", function message(msg, isBinary) { + const data = !isBinary && duplex._readableState.objectMode ? msg.toString() : msg; + if (!duplex.push(data)) + ws.pause(); + }); + ws.once("error", function error(err) { + if (duplex.destroyed) + return; + terminateOnDestroy = false; + duplex.destroy(err); + }); + ws.once("close", function close() { + if (duplex.destroyed) + return; + duplex.push(null); + }); + duplex._destroy = function(err, callback) { + if (ws.readyState === ws.CLOSED) { + callback(err); + process.nextTick(emitClose, duplex); + return; + } + let called = false; + ws.once("error", function error(err2) { + called = true; + callback(err2); + }); + ws.once("close", function close() { + if (!called) + callback(err); + process.nextTick(emitClose, duplex); + }); + if (terminateOnDestroy) + ws.terminate(); + }; + duplex._final = function(callback) { + if (ws.readyState === ws.CONNECTING) { + ws.once("open", function open() { + duplex._final(callback); + }); + return; + } + if (ws._socket === null) + return; + if (ws._socket._writableState.finished) { + callback(); + if (duplex._readableState.endEmitted) + duplex.destroy(); + } else { + ws._socket.once("finish", function finish() { + callback(); + }); + ws.close(); + } + }; + duplex._read = function() { + if (ws.isPaused) + ws.resume(); + }; + duplex._write = function(chunk, encoding, callback) { + if (ws.readyState === ws.CONNECTING) { + ws.once("open", function open() { + duplex._write(chunk, encoding, callback); + }); + return; + } + ws.send(chunk, callback); + }; + duplex.on("end", duplexOnEnd); + duplex.on("error", duplexOnError); + return duplex; + } + module2.exports = createWebSocketStream; +}); + +// node_modules/ws/lib/subprotocol.js +var require_subprotocol = __commonJS((exports2, module2) => { + var { tokenChars } = require_validation(); + function parse(header) { + const protocols = new Set; + let start = -1; + let end = -1; + let i = 0; + for (i;i < header.length; i++) { + const code = header.charCodeAt(i); + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) + start = i; + } else if (i !== 0 && (code === 32 || code === 9)) { + if (end === -1 && start !== -1) + end = i; + } else if (code === 44) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + if (end === -1) + end = i; + const protocol2 = header.slice(start, end); + if (protocols.has(protocol2)) { + throw new SyntaxError(`The "${protocol2}" subprotocol is duplicated`); + } + protocols.add(protocol2); + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } + if (start === -1 || end !== -1) { + throw new SyntaxError("Unexpected end of input"); + } + const protocol = header.slice(start, i); + if (protocols.has(protocol)) { + throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`); + } + protocols.add(protocol); + return protocols; + } + module2.exports = { parse }; +}); + +// node_modules/ws/lib/websocket-server.js +var require_websocket_server = __commonJS((exports2, module2) => { + var EventEmitter = require("events"); + var http = require("http"); + var { Duplex } = require("stream"); + var { createHash } = require("crypto"); + var extension = require_extension(); + var PerMessageDeflate = require_permessage_deflate(); + var subprotocol = require_subprotocol(); + var WebSocket = require_websocket2(); + var { GUID, kWebSocket } = require_constants(); + var keyRegex = /^[+/0-9A-Za-z]{22}==$/; + var RUNNING = 0; + var CLOSING = 1; + var CLOSED = 2; + + class WebSocketServer extends EventEmitter { + constructor(options, callback) { + super(); + options = { + allowSynchronousEvents: true, + autoPong: true, + maxPayload: 100 * 1024 * 1024, + skipUTF8Validation: false, + perMessageDeflate: false, + handleProtocols: null, + clientTracking: true, + verifyClient: null, + noServer: false, + backlog: null, + server: null, + host: null, + path: null, + port: null, + WebSocket, + ...options + }; + if (options.port == null && !options.server && !options.noServer || options.port != null && (options.server || options.noServer) || options.server && options.noServer) { + throw new TypeError('One and only one of the "port", "server", or "noServer" options ' + "must be specified"); + } + if (options.port != null) { + this._server = http.createServer((req, res) => { + const body = http.STATUS_CODES[426]; + res.writeHead(426, { + "Content-Length": body.length, + "Content-Type": "text/plain" + }); + res.end(body); + }); + this._server.listen(options.port, options.host, options.backlog, callback); + } else if (options.server) { + this._server = options.server; + } + if (this._server) { + const emitConnection = this.emit.bind(this, "connection"); + this._removeListeners = addListeners(this._server, { + listening: this.emit.bind(this, "listening"), + error: this.emit.bind(this, "error"), + upgrade: (req, socket, head) => { + this.handleUpgrade(req, socket, head, emitConnection); + } + }); + } + if (options.perMessageDeflate === true) + options.perMessageDeflate = {}; + if (options.clientTracking) { + this.clients = new Set; + this._shouldEmitClose = false; + } + this.options = options; + this._state = RUNNING; + } + address() { + if (this.options.noServer) { + throw new Error('The server is operating in "noServer" mode'); + } + if (!this._server) + return null; + return this._server.address(); + } + close(cb) { + if (this._state === CLOSED) { + if (cb) { + this.once("close", () => { + cb(new Error("The server is not running")); + }); + } + process.nextTick(emitClose, this); + return; + } + if (cb) + this.once("close", cb); + if (this._state === CLOSING) + return; + this._state = CLOSING; + if (this.options.noServer || this.options.server) { + if (this._server) { + this._removeListeners(); + this._removeListeners = this._server = null; + } + if (this.clients) { + if (!this.clients.size) { + process.nextTick(emitClose, this); + } else { + this._shouldEmitClose = true; + } + } else { + process.nextTick(emitClose, this); + } + } else { + const server = this._server; + this._removeListeners(); + this._removeListeners = this._server = null; + server.close(() => { + emitClose(this); + }); + } + } + shouldHandle(req) { + if (this.options.path) { + const index = req.url.indexOf("?"); + const pathname = index !== -1 ? req.url.slice(0, index) : req.url; + if (pathname !== this.options.path) + return false; + } + return true; + } + handleUpgrade(req, socket, head, cb) { + socket.on("error", socketOnError); + const key = req.headers["sec-websocket-key"]; + const upgrade = req.headers.upgrade; + const version = +req.headers["sec-websocket-version"]; + if (req.method !== "GET") { + const message = "Invalid HTTP method"; + abortHandshakeOrEmitwsClientError(this, req, socket, 405, message); + return; + } + if (upgrade === undefined || upgrade.toLowerCase() !== "websocket") { + const message = "Invalid Upgrade header"; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + if (key === undefined || !keyRegex.test(key)) { + const message = "Missing or invalid Sec-WebSocket-Key header"; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + if (version !== 8 && version !== 13) { + const message = "Missing or invalid Sec-WebSocket-Version header"; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + if (!this.shouldHandle(req)) { + abortHandshake(socket, 400); + return; + } + const secWebSocketProtocol = req.headers["sec-websocket-protocol"]; + let protocols = new Set; + if (secWebSocketProtocol !== undefined) { + try { + protocols = subprotocol.parse(secWebSocketProtocol); + } catch (err) { + const message = "Invalid Sec-WebSocket-Protocol header"; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + } + const secWebSocketExtensions = req.headers["sec-websocket-extensions"]; + const extensions = {}; + if (this.options.perMessageDeflate && secWebSocketExtensions !== undefined) { + const perMessageDeflate = new PerMessageDeflate(this.options.perMessageDeflate, true, this.options.maxPayload); + try { + const offers = extension.parse(secWebSocketExtensions); + if (offers[PerMessageDeflate.extensionName]) { + perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]); + extensions[PerMessageDeflate.extensionName] = perMessageDeflate; + } + } catch (err) { + const message = "Invalid or unacceptable Sec-WebSocket-Extensions header"; + abortHandshakeOrEmitwsClientError(this, req, socket, 400, message); + return; + } + } + if (this.options.verifyClient) { + const info = { + origin: req.headers[`${version === 8 ? "sec-websocket-origin" : "origin"}`], + secure: !!(req.socket.authorized || req.socket.encrypted), + req + }; + if (this.options.verifyClient.length === 2) { + this.options.verifyClient(info, (verified, code, message, headers) => { + if (!verified) { + return abortHandshake(socket, code || 401, message, headers); + } + this.completeUpgrade(extensions, key, protocols, req, socket, head, cb); + }); + return; + } + if (!this.options.verifyClient(info)) + return abortHandshake(socket, 401); + } + this.completeUpgrade(extensions, key, protocols, req, socket, head, cb); + } + completeUpgrade(extensions, key, protocols, req, socket, head, cb) { + if (!socket.readable || !socket.writable) + return socket.destroy(); + if (socket[kWebSocket]) { + throw new Error("server.handleUpgrade() was called more than once with the same " + "socket, possibly due to a misconfiguration"); + } + if (this._state > RUNNING) + return abortHandshake(socket, 503); + const digest = createHash("sha1").update(key + GUID).digest("base64"); + const headers = [ + "HTTP/1.1 101 Switching Protocols", + "Upgrade: websocket", + "Connection: Upgrade", + `Sec-WebSocket-Accept: ${digest}` + ]; + const ws = new this.options.WebSocket(null, undefined, this.options); + if (protocols.size) { + const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req) : protocols.values().next().value; + if (protocol) { + headers.push(`Sec-WebSocket-Protocol: ${protocol}`); + ws._protocol = protocol; + } + } + if (extensions[PerMessageDeflate.extensionName]) { + const params = extensions[PerMessageDeflate.extensionName].params; + const value = extension.format({ + [PerMessageDeflate.extensionName]: [params] + }); + headers.push(`Sec-WebSocket-Extensions: ${value}`); + ws._extensions = extensions; + } + this.emit("headers", headers, req); + socket.write(headers.concat(`\r +`).join(`\r +`)); + socket.removeListener("error", socketOnError); + ws.setSocket(socket, head, { + allowSynchronousEvents: this.options.allowSynchronousEvents, + maxPayload: this.options.maxPayload, + skipUTF8Validation: this.options.skipUTF8Validation + }); + if (this.clients) { + this.clients.add(ws); + ws.on("close", () => { + this.clients.delete(ws); + if (this._shouldEmitClose && !this.clients.size) { + process.nextTick(emitClose, this); + } + }); + } + cb(ws, req); + } + } + module2.exports = WebSocketServer; + function addListeners(server, map) { + for (const event of Object.keys(map)) + server.on(event, map[event]); + return function removeListeners() { + for (const event of Object.keys(map)) { + server.removeListener(event, map[event]); + } + }; + } + function emitClose(server) { + server._state = CLOSED; + server.emit("close"); + } + function socketOnError() { + this.destroy(); + } + function abortHandshake(socket, code, message, headers) { + message = message || http.STATUS_CODES[code]; + headers = { + Connection: "close", + "Content-Type": "text/html", + "Content-Length": Buffer.byteLength(message), + ...headers + }; + socket.once("finish", socket.destroy); + socket.end(`HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r +` + Object.keys(headers).map((h) => `${h}: ${headers[h]}`).join(`\r +`) + `\r +\r +` + message); + } + function abortHandshakeOrEmitwsClientError(server, req, socket, code, message) { + if (server.listenerCount("wsClientError")) { + const err = new Error(message); + Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError); + server.emit("wsClientError", err, socket, req); + } else { + abortHandshake(socket, code, message); + } + } +}); + +// node_modules/ws/index.js +var require_ws = __commonJS((exports2, module2) => { + var WebSocket = require_websocket2(); + WebSocket.createWebSocketStream = require_stream(); + WebSocket.Server = require_websocket_server(); + WebSocket.Receiver = require_receiver(); + WebSocket.Sender = require_sender(); + WebSocket.WebSocket = WebSocket; + WebSocket.WebSocketServer = WebSocket.Server; + module2.exports = WebSocket; +}); + +// node_modules/object-assign/index.js +var require_object_assign = __commonJS((exports2, module2) => { + var getOwnPropertySymbols = Object.getOwnPropertySymbols; + var hasOwnProperty = Object.prototype.hasOwnProperty; + var propIsEnumerable = Object.prototype.propertyIsEnumerable; + function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError("Object.assign cannot be called with null or undefined"); + } + return Object(val); + } + function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + var test1 = new String("abc"); + test1[5] = "de"; + if (Object.getOwnPropertyNames(test1)[0] === "5") { + return false; + } + var test2 = {}; + for (var i = 0;i < 10; i++) { + test2["_" + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function(n) { + return test2[n]; + }); + if (order2.join("") !== "0123456789") { + return false; + } + var test3 = {}; + "abcdefghijklmnopqrst".split("").forEach(function(letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join("") !== "abcdefghijklmnopqrst") { + return false; + } + return true; + } catch (err) { + return false; + } + } + module2.exports = shouldUseNative() ? Object.assign : function(target, source2) { + var from; + var to = toObject(target); + var symbols; + for (var s = 1;s < arguments.length; s++) { + from = Object(arguments[s]); + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + if (getOwnPropertySymbols) { + symbols = getOwnPropertySymbols(from); + for (var i = 0;i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + return to; + }; +}); + +// node_modules/vary/index.js +var require_vary = __commonJS((exports2, module2) => { + /*! + * vary + * Copyright(c) 2014-2017 Douglas Christopher Wilson + * MIT Licensed + */ + module2.exports = vary; + module2.exports.append = append; + var FIELD_NAME_REGEXP = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; + function append(header, field) { + if (typeof header !== "string") { + throw new TypeError("header argument is required"); + } + if (!field) { + throw new TypeError("field argument is required"); + } + var fields = !Array.isArray(field) ? parse(String(field)) : field; + for (var j = 0;j < fields.length; j++) { + if (!FIELD_NAME_REGEXP.test(fields[j])) { + throw new TypeError("field argument contains an invalid header name"); + } + } + if (header === "*") { + return header; + } + var val = header; + var vals = parse(header.toLowerCase()); + if (fields.indexOf("*") !== -1 || vals.indexOf("*") !== -1) { + return "*"; + } + for (var i = 0;i < fields.length; i++) { + var fld = fields[i].toLowerCase(); + if (vals.indexOf(fld) === -1) { + vals.push(fld); + val = val ? val + ", " + fields[i] : fields[i]; + } + } + return val; + } + function parse(header) { + var end = 0; + var list = []; + var start = 0; + for (var i = 0, len = header.length;i < len; i++) { + switch (header.charCodeAt(i)) { + case 32: + if (start === end) { + start = end = i + 1; + } + break; + case 44: + list.push(header.substring(start, end)); + start = end = i + 1; + break; + default: + end = i + 1; + break; + } + } + list.push(header.substring(start, end)); + return list; + } + function vary(res, field) { + if (!res || !res.getHeader || !res.setHeader) { + throw new TypeError("res argument is required"); + } + var val = res.getHeader("Vary") || ""; + var header = Array.isArray(val) ? val.join(", ") : String(val); + if (val = append(header, field)) { + res.setHeader("Vary", val); + } + } +}); + +// node_modules/cors/lib/index.js +var require_lib = __commonJS((exports2, module2) => { + (function() { + var assign = require_object_assign(); + var vary = require_vary(); + var defaults = { + origin: "*", + methods: "GET,HEAD,PUT,PATCH,POST,DELETE", + preflightContinue: false, + optionsSuccessStatus: 204 + }; + function isString(s) { + return typeof s === "string" || s instanceof String; + } + function isOriginAllowed(origin, allowedOrigin) { + if (Array.isArray(allowedOrigin)) { + for (var i = 0;i < allowedOrigin.length; ++i) { + if (isOriginAllowed(origin, allowedOrigin[i])) { + return true; + } + } + return false; + } else if (isString(allowedOrigin)) { + return origin === allowedOrigin; + } else if (allowedOrigin instanceof RegExp) { + return allowedOrigin.test(origin); + } else { + return !!allowedOrigin; + } + } + function configureOrigin(options, req) { + var requestOrigin = req.headers.origin, headers = [], isAllowed; + if (!options.origin || options.origin === "*") { + headers.push([{ + key: "Access-Control-Allow-Origin", + value: "*" + }]); + } else if (isString(options.origin)) { + headers.push([{ + key: "Access-Control-Allow-Origin", + value: options.origin + }]); + headers.push([{ + key: "Vary", + value: "Origin" + }]); + } else { + isAllowed = isOriginAllowed(requestOrigin, options.origin); + headers.push([{ + key: "Access-Control-Allow-Origin", + value: isAllowed ? requestOrigin : false + }]); + headers.push([{ + key: "Vary", + value: "Origin" + }]); + } + return headers; + } + function configureMethods(options) { + var methods = options.methods; + if (methods.join) { + methods = options.methods.join(","); + } + return { + key: "Access-Control-Allow-Methods", + value: methods + }; + } + function configureCredentials(options) { + if (options.credentials === true) { + return { + key: "Access-Control-Allow-Credentials", + value: "true" + }; + } + return null; + } + function configureAllowedHeaders(options, req) { + var allowedHeaders = options.allowedHeaders || options.headers; + var headers = []; + if (!allowedHeaders) { + allowedHeaders = req.headers["access-control-request-headers"]; + headers.push([{ + key: "Vary", + value: "Access-Control-Request-Headers" + }]); + } else if (allowedHeaders.join) { + allowedHeaders = allowedHeaders.join(","); + } + if (allowedHeaders && allowedHeaders.length) { + headers.push([{ + key: "Access-Control-Allow-Headers", + value: allowedHeaders + }]); + } + return headers; + } + function configureExposedHeaders(options) { + var headers = options.exposedHeaders; + if (!headers) { + return null; + } else if (headers.join) { + headers = headers.join(","); + } + if (headers && headers.length) { + return { + key: "Access-Control-Expose-Headers", + value: headers + }; + } + return null; + } + function configureMaxAge(options) { + var maxAge = (typeof options.maxAge === "number" || options.maxAge) && options.maxAge.toString(); + if (maxAge && maxAge.length) { + return { + key: "Access-Control-Max-Age", + value: maxAge + }; + } + return null; + } + function applyHeaders(headers, res) { + for (var i = 0, n = headers.length;i < n; i++) { + var header = headers[i]; + if (header) { + if (Array.isArray(header)) { + applyHeaders(header, res); + } else if (header.key === "Vary" && header.value) { + vary(res, header.value); + } else if (header.value) { + res.setHeader(header.key, header.value); + } + } + } + } + function cors(options, req, res, next) { + var headers = [], method = req.method && req.method.toUpperCase && req.method.toUpperCase(); + if (method === "OPTIONS") { + headers.push(configureOrigin(options, req)); + headers.push(configureCredentials(options, req)); + headers.push(configureMethods(options, req)); + headers.push(configureAllowedHeaders(options, req)); + headers.push(configureMaxAge(options, req)); + headers.push(configureExposedHeaders(options, req)); + applyHeaders(headers, res); + if (options.preflightContinue) { + next(); + } else { + res.statusCode = options.optionsSuccessStatus; + res.setHeader("Content-Length", "0"); + res.end(); + } + } else { + headers.push(configureOrigin(options, req)); + headers.push(configureCredentials(options, req)); + headers.push(configureExposedHeaders(options, req)); + applyHeaders(headers, res); + next(); + } + } + function middlewareWrapper(o) { + var optionsCallback = null; + if (typeof o === "function") { + optionsCallback = o; + } else { + optionsCallback = function(req, cb) { + cb(null, o); + }; + } + return function corsMiddleware(req, res, next) { + optionsCallback(req, function(err, options) { + if (err) { + next(err); + } else { + var corsOptions = assign({}, defaults, options); + var originCallback = null; + if (corsOptions.origin && typeof corsOptions.origin === "function") { + originCallback = corsOptions.origin; + } else if (corsOptions.origin) { + originCallback = function(origin, cb) { + cb(null, corsOptions.origin); + }; + } + if (originCallback) { + originCallback(req.headers.origin, function(err2, origin) { + if (err2 || !origin) { + next(err2); + } else { + corsOptions.origin = origin; + cors(corsOptions, req, res, next); + } + }); + } else { + next(); + } + } + }); + }; + } + module2.exports = middlewareWrapper; + })(); +}); + +// node_modules/engine.io/build/server.js +var require_server = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Server = exports2.BaseServer = undefined; + var qs = require("querystring"); + var url_1 = require("url"); + var base64id = require_base64id(); + var transports_1 = require_transports(); + var events_1 = require("events"); + var socket_1 = require_socket(); + var debug_1 = require_src(); + var cookie_1 = require_cookie(); + var ws_1 = require_ws(); + var webtransport_1 = require_webtransport(); + var engine_io_parser_1 = require_cjs(); + var debug = (0, debug_1.default)("engine"); + var kResponseHeaders = Symbol("responseHeaders"); + function parseSessionId(data) { + try { + const parsed = JSON.parse(data); + if (typeof parsed.sid === "string") { + return parsed.sid; + } + } catch (e) {} + } + + class BaseServer extends events_1.EventEmitter { + constructor(opts = {}) { + super(); + this.middlewares = []; + this.clients = {}; + this.clientsCount = 0; + this.opts = Object.assign({ + wsEngine: ws_1.Server, + pingTimeout: 20000, + pingInterval: 25000, + upgradeTimeout: 1e4, + maxHttpBufferSize: 1e6, + transports: ["polling", "websocket"], + allowUpgrades: true, + httpCompression: { + threshold: 1024 + }, + cors: false, + allowEIO3: false + }, opts); + if (opts.cookie) { + this.opts.cookie = Object.assign({ + name: "io", + path: "/", + httpOnly: opts.cookie.path !== false, + sameSite: "lax" + }, opts.cookie); + } + if (this.opts.cors) { + this.use(require_lib()(this.opts.cors)); + } + if (opts.perMessageDeflate) { + this.opts.perMessageDeflate = Object.assign({ + threshold: 1024 + }, opts.perMessageDeflate); + } + this.init(); + } + _computePath(options) { + let path = (options.path || "/engine.io").replace(/\/$/, ""); + if (options.addTrailingSlash !== false) { + path += "/"; + } + return path; + } + upgrades(transport) { + if (!this.opts.allowUpgrades) + return []; + return transports_1.default[transport].upgradesTo || []; + } + verify(req, upgrade, fn) { + const transport = req._query.transport; + if (!~this.opts.transports.indexOf(transport) || transport === "webtransport") { + debug('unknown transport "%s"', transport); + return fn(Server.errors.UNKNOWN_TRANSPORT, { transport }); + } + const isOriginInvalid = checkInvalidHeaderChar(req.headers.origin); + if (isOriginInvalid) { + const origin = req.headers.origin; + req.headers.origin = null; + debug("origin header invalid"); + return fn(Server.errors.BAD_REQUEST, { + name: "INVALID_ORIGIN", + origin + }); + } + const sid = req._query.sid; + if (sid) { + if (!this.clients.hasOwnProperty(sid)) { + debug('unknown sid "%s"', sid); + return fn(Server.errors.UNKNOWN_SID, { + sid + }); + } + const previousTransport = this.clients[sid].transport.name; + if (!upgrade && previousTransport !== transport) { + debug("bad request: unexpected transport without upgrade"); + return fn(Server.errors.BAD_REQUEST, { + name: "TRANSPORT_MISMATCH", + transport, + previousTransport + }); + } + } else { + if (req.method !== "GET") { + return fn(Server.errors.BAD_HANDSHAKE_METHOD, { + method: req.method + }); + } + if (transport === "websocket" && !upgrade) { + debug("invalid transport upgrade"); + return fn(Server.errors.BAD_REQUEST, { + name: "TRANSPORT_HANDSHAKE_ERROR" + }); + } + if (!this.opts.allowRequest) + return fn(); + return this.opts.allowRequest(req, (message, success) => { + if (!success) { + return fn(Server.errors.FORBIDDEN, { + message + }); + } + fn(); + }); + } + fn(); + } + use(fn) { + this.middlewares.push(fn); + } + _applyMiddlewares(req, res, callback) { + if (this.middlewares.length === 0) { + debug("no middleware to apply, skipping"); + return callback(); + } + const apply = (i) => { + debug("applying middleware n°%d", i + 1); + this.middlewares[i](req, res, (err) => { + if (err) { + return callback(err); + } + if (i + 1 < this.middlewares.length) { + apply(i + 1); + } else { + callback(); + } + }); + }; + apply(0); + } + close() { + debug("closing all open clients"); + for (let i in this.clients) { + if (this.clients.hasOwnProperty(i)) { + this.clients[i].close(true); + } + } + this.cleanup(); + return this; + } + generateId(req) { + return base64id.generateId(); + } + async handshake(transportName, req, closeConnection) { + const protocol = req._query.EIO === "4" ? 4 : 3; + if (protocol === 3 && !this.opts.allowEIO3) { + debug("unsupported protocol version"); + this.emit("connection_error", { + req, + code: Server.errors.UNSUPPORTED_PROTOCOL_VERSION, + message: Server.errorMessages[Server.errors.UNSUPPORTED_PROTOCOL_VERSION], + context: { + protocol + } + }); + closeConnection(Server.errors.UNSUPPORTED_PROTOCOL_VERSION); + return; + } + let id; + try { + id = await this.generateId(req); + } catch (e) { + debug("error while generating an id"); + this.emit("connection_error", { + req, + code: Server.errors.BAD_REQUEST, + message: Server.errorMessages[Server.errors.BAD_REQUEST], + context: { + name: "ID_GENERATION_ERROR", + error: e + } + }); + closeConnection(Server.errors.BAD_REQUEST); + return; + } + debug('handshaking client "%s"', id); + try { + var transport = this.createTransport(transportName, req); + if (transportName === "polling") { + transport.maxHttpBufferSize = this.opts.maxHttpBufferSize; + transport.httpCompression = this.opts.httpCompression; + } else if (transportName === "websocket") { + transport.perMessageDeflate = this.opts.perMessageDeflate; + } + } catch (e) { + debug('error handshaking to transport "%s"', transportName); + this.emit("connection_error", { + req, + code: Server.errors.BAD_REQUEST, + message: Server.errorMessages[Server.errors.BAD_REQUEST], + context: { + name: "TRANSPORT_HANDSHAKE_ERROR", + error: e + } + }); + closeConnection(Server.errors.BAD_REQUEST); + return; + } + const socket = new socket_1.Socket(id, this, transport, req, protocol); + transport.on("headers", (headers, req2) => { + const isInitialRequest = !req2._query.sid; + if (isInitialRequest) { + if (this.opts.cookie) { + headers["Set-Cookie"] = [ + (0, cookie_1.serialize)(this.opts.cookie.name, id, this.opts.cookie) + ]; + } + this.emit("initial_headers", headers, req2); + } + this.emit("headers", headers, req2); + }); + transport.onRequest(req); + this.clients[id] = socket; + this.clientsCount++; + socket.once("close", () => { + delete this.clients[id]; + this.clientsCount--; + }); + this.emit("connection", socket); + return transport; + } + async onWebTransportSession(session) { + const timeout = setTimeout(() => { + debug("the client failed to establish a bidirectional stream in the given period"); + session.close(); + }, this.opts.upgradeTimeout); + const streamReader = session.incomingBidirectionalStreams.getReader(); + const result = await streamReader.read(); + if (result.done) { + debug("session is closed"); + return; + } + const stream = result.value; + const transformStream = (0, engine_io_parser_1.createPacketDecoderStream)(this.opts.maxHttpBufferSize, "nodebuffer"); + const reader = stream.readable.pipeThrough(transformStream).getReader(); + const { value, done } = await reader.read(); + if (done) { + debug("stream is closed"); + return; + } + clearTimeout(timeout); + if (value.type !== "open") { + debug("invalid WebTransport handshake"); + return session.close(); + } + if (value.data === undefined) { + const transport = new webtransport_1.WebTransport(session, stream, reader); + const id = base64id.generateId(); + debug('handshaking client "%s" (WebTransport)', id); + const socket = new socket_1.Socket(id, this, transport, null, 4); + this.clients[id] = socket; + this.clientsCount++; + socket.once("close", () => { + delete this.clients[id]; + this.clientsCount--; + }); + this.emit("connection", socket); + return; + } + const sid = parseSessionId(value.data); + if (!sid) { + debug("invalid WebTransport handshake"); + return session.close(); + } + const client = this.clients[sid]; + if (!client) { + debug("upgrade attempt for closed client"); + session.close(); + } else if (client.upgrading) { + debug("transport has already been trying to upgrade"); + session.close(); + } else if (client.upgraded) { + debug("transport had already been upgraded"); + session.close(); + } else { + debug("upgrading existing transport"); + const transport = new webtransport_1.WebTransport(session, stream, reader); + client._maybeUpgrade(transport); + } + } + } + exports2.BaseServer = BaseServer; + BaseServer.errors = { + UNKNOWN_TRANSPORT: 0, + UNKNOWN_SID: 1, + BAD_HANDSHAKE_METHOD: 2, + BAD_REQUEST: 3, + FORBIDDEN: 4, + UNSUPPORTED_PROTOCOL_VERSION: 5 + }; + BaseServer.errorMessages = { + 0: "Transport unknown", + 1: "Session ID unknown", + 2: "Bad handshake method", + 3: "Bad request", + 4: "Forbidden", + 5: "Unsupported protocol version" + }; + + class WebSocketResponse { + constructor(req, socket) { + this.req = req; + this.socket = socket; + req[kResponseHeaders] = {}; + } + setHeader(name, value) { + this.req[kResponseHeaders][name] = value; + } + getHeader(name) { + return this.req[kResponseHeaders][name]; + } + removeHeader(name) { + delete this.req[kResponseHeaders][name]; + } + write() {} + writeHead() {} + end() { + this.socket.destroy(); + } + } + + class Server extends BaseServer { + init() { + if (!~this.opts.transports.indexOf("websocket")) + return; + if (this.ws) + this.ws.close(); + this.ws = new this.opts.wsEngine({ + noServer: true, + clientTracking: false, + perMessageDeflate: this.opts.perMessageDeflate, + maxPayload: this.opts.maxHttpBufferSize + }); + if (typeof this.ws.on === "function") { + this.ws.on("headers", (headersArray, req) => { + const additionalHeaders = req[kResponseHeaders] || {}; + delete req[kResponseHeaders]; + const isInitialRequest = !req._query.sid; + if (isInitialRequest) { + this.emit("initial_headers", additionalHeaders, req); + } + this.emit("headers", additionalHeaders, req); + debug("writing headers: %j", additionalHeaders); + Object.keys(additionalHeaders).forEach((key) => { + headersArray.push(`${key}: ${additionalHeaders[key]}`); + }); + }); + } + } + cleanup() { + if (this.ws) { + debug("closing webSocketServer"); + this.ws.close(); + } + } + prepare(req) { + if (!req._query) { + req._query = ~req.url.indexOf("?") ? qs.parse((0, url_1.parse)(req.url).query) : {}; + } + } + createTransport(transportName, req) { + return new transports_1.default[transportName](req); + } + handleRequest(req, res) { + debug('handling "%s" http request "%s"', req.method, req.url); + this.prepare(req); + req.res = res; + const callback = (errorCode, errorContext) => { + if (errorCode !== undefined) { + this.emit("connection_error", { + req, + code: errorCode, + message: Server.errorMessages[errorCode], + context: errorContext + }); + abortRequest(res, errorCode, errorContext); + return; + } + if (req._query.sid) { + debug("setting new request for existing client"); + this.clients[req._query.sid].transport.onRequest(req); + } else { + const closeConnection = (errorCode2, errorContext2) => abortRequest(res, errorCode2, errorContext2); + this.handshake(req._query.transport, req, closeConnection); + } + }; + this._applyMiddlewares(req, res, (err) => { + if (err) { + callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" }); + } else { + this.verify(req, false, callback); + } + }); + } + handleUpgrade(req, socket, upgradeHead) { + this.prepare(req); + const res = new WebSocketResponse(req, socket); + const callback = (errorCode, errorContext) => { + if (errorCode !== undefined) { + this.emit("connection_error", { + req, + code: errorCode, + message: Server.errorMessages[errorCode], + context: errorContext + }); + abortUpgrade(socket, errorCode, errorContext); + return; + } + const head = Buffer.from(upgradeHead); + upgradeHead = null; + res.writeHead(); + this.ws.handleUpgrade(req, socket, head, (websocket) => { + this.onWebSocket(req, socket, websocket); + }); + }; + this._applyMiddlewares(req, res, (err) => { + if (err) { + callback(Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" }); + } else { + this.verify(req, true, callback); + } + }); + } + onWebSocket(req, socket, websocket) { + websocket.on("error", onUpgradeError); + if (transports_1.default[req._query.transport] !== undefined && !transports_1.default[req._query.transport].prototype.handlesUpgrades) { + debug("transport doesnt handle upgraded requests"); + websocket.close(); + return; + } + const id = req._query.sid; + req.websocket = websocket; + if (id) { + const client = this.clients[id]; + if (!client) { + debug("upgrade attempt for closed client"); + websocket.close(); + } else if (client.upgrading) { + debug("transport has already been trying to upgrade"); + websocket.close(); + } else if (client.upgraded) { + debug("transport had already been upgraded"); + websocket.close(); + } else { + debug("upgrading existing transport"); + websocket.removeListener("error", onUpgradeError); + const transport = this.createTransport(req._query.transport, req); + transport.perMessageDeflate = this.opts.perMessageDeflate; + client._maybeUpgrade(transport); + } + } else { + const closeConnection = (errorCode, errorContext) => abortUpgrade(socket, errorCode, errorContext); + this.handshake(req._query.transport, req, closeConnection); + } + function onUpgradeError() { + debug("websocket error before upgrade"); + } + } + attach(server, options = {}) { + const path = this._computePath(options); + const destroyUpgradeTimeout = options.destroyUpgradeTimeout || 1000; + function check(req) { + return path === req.url.slice(0, path.length); + } + const listeners = server.listeners("request").slice(0); + server.removeAllListeners("request"); + server.on("close", this.close.bind(this)); + server.on("listening", this.init.bind(this)); + server.on("request", (req, res) => { + if (check(req)) { + debug('intercepting request for path "%s"', path); + this.handleRequest(req, res); + } else { + let i = 0; + const l = listeners.length; + for (;i < l; i++) { + listeners[i].call(server, req, res); + } + } + }); + if (~this.opts.transports.indexOf("websocket")) { + server.on("upgrade", (req, socket, head) => { + if (check(req)) { + this.handleUpgrade(req, socket, head); + } else if (options.destroyUpgrade !== false) { + setTimeout(function() { + if (socket.writable && socket.bytesWritten <= 0) { + socket.on("error", (e) => { + debug("error while destroying upgrade: %s", e.message); + }); + return socket.end(); + } + }, destroyUpgradeTimeout); + } + }); + } + } + } + exports2.Server = Server; + function abortRequest(res, errorCode, errorContext) { + const statusCode = errorCode === Server.errors.FORBIDDEN ? 403 : 400; + const message = errorContext && errorContext.message ? errorContext.message : Server.errorMessages[errorCode]; + res.writeHead(statusCode, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ + code: errorCode, + message + })); + } + function abortUpgrade(socket, errorCode, errorContext = {}) { + socket.on("error", () => { + debug("ignoring error from closed connection"); + }); + if (socket.writable) { + const message = errorContext.message || Server.errorMessages[errorCode]; + const length = Buffer.byteLength(message); + socket.write(`HTTP/1.1 400 Bad Request\r +` + `Connection: close\r +` + `Content-type: text/html\r +` + "Content-Length: " + length + `\r +` + `\r +` + message); + } + socket.destroy(); + } + var validHdrChars = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ]; + function checkInvalidHeaderChar(val) { + val += ""; + if (val.length < 1) + return false; + if (!validHdrChars[val.charCodeAt(0)]) { + debug('invalid header, index 0, char "%s"', val.charCodeAt(0)); + return true; + } + if (val.length < 2) + return false; + if (!validHdrChars[val.charCodeAt(1)]) { + debug('invalid header, index 1, char "%s"', val.charCodeAt(1)); + return true; + } + if (val.length < 3) + return false; + if (!validHdrChars[val.charCodeAt(2)]) { + debug('invalid header, index 2, char "%s"', val.charCodeAt(2)); + return true; + } + if (val.length < 4) + return false; + if (!validHdrChars[val.charCodeAt(3)]) { + debug('invalid header, index 3, char "%s"', val.charCodeAt(3)); + return true; + } + for (let i = 4;i < val.length; ++i) { + if (!validHdrChars[val.charCodeAt(i)]) { + debug('invalid header, index "%i", char "%s"', i, val.charCodeAt(i)); + return true; + } + } + return false; + } +}); + +// node_modules/engine.io/build/transports-uws/polling.js +var require_polling2 = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Polling = undefined; + var transport_1 = require_transport(); + var zlib_1 = require("zlib"); + var accepts = require_accepts(); + var debug_1 = require_src(); + var debug = (0, debug_1.default)("engine:polling"); + var compressionMethods = { + gzip: zlib_1.createGzip, + deflate: zlib_1.createDeflate + }; + + class Polling extends transport_1.Transport { + constructor(req) { + super(req); + this.closeTimeout = 30 * 1000; + } + get name() { + return "polling"; + } + onRequest(req) { + const res = req.res; + req.res = null; + if (req.getMethod() === "get") { + this.onPollRequest(req, res); + } else if (req.getMethod() === "post") { + this.onDataRequest(req, res); + } else { + res.writeStatus("500 Internal Server Error"); + res.end(); + } + } + onPollRequest(req, res) { + if (this.req) { + debug("request overlap"); + this.onError("overlap from client"); + res.writeStatus("500 Internal Server Error"); + res.end(); + return; + } + debug("setting request"); + this.req = req; + this.res = res; + const onClose = () => { + this.writable = false; + this.onError("poll connection closed prematurely"); + }; + const cleanup = () => { + this.req = this.res = null; + }; + req.cleanup = cleanup; + res.onAborted(onClose); + this.writable = true; + this.emit("ready"); + if (this.writable && this.shouldClose) { + debug("triggering empty send to append close packet"); + this.send([{ type: "noop" }]); + } + } + onDataRequest(req, res) { + if (this.dataReq) { + this.onError("data request overlap from client"); + res.writeStatus("500 Internal Server Error"); + res.end(); + return; + } + const expectedContentLength = Number(req.headers["content-length"]); + if (!expectedContentLength) { + this.onError("content-length header required"); + res.writeStatus("411 Length Required").end(); + return; + } + if (expectedContentLength > this.maxHttpBufferSize) { + this.onError("payload too large"); + res.writeStatus("413 Payload Too Large").end(); + return; + } + const isBinary = req.headers["content-type"] === "application/octet-stream"; + if (isBinary && this.protocol === 4) { + return this.onError("invalid content"); + } + this.dataReq = req; + this.dataRes = res; + let buffer; + let offset = 0; + const headers = { + "Content-Type": "text/html" + }; + this.headers(req, headers); + for (let key in headers) { + res.writeHeader(key, String(headers[key])); + } + const onEnd = (buffer2) => { + this.onData(buffer2.toString()); + this.onDataRequestCleanup(); + res.cork(() => { + res.end("ok"); + }); + }; + res.onAborted(() => { + this.onDataRequestCleanup(); + this.onError("data request connection closed prematurely"); + }); + res.onData((arrayBuffer, isLast) => { + const totalLength = offset + arrayBuffer.byteLength; + if (totalLength > expectedContentLength) { + this.onError("content-length mismatch"); + res.close(); + return; + } + if (!buffer) { + if (isLast) { + onEnd(Buffer.from(arrayBuffer)); + return; + } + buffer = Buffer.allocUnsafe(expectedContentLength); + } + Buffer.from(arrayBuffer).copy(buffer, offset); + if (isLast) { + if (totalLength != expectedContentLength) { + this.onError("content-length mismatch"); + res.writeStatus("400 Content-Length Mismatch").end(); + this.onDataRequestCleanup(); + return; + } + onEnd(buffer); + return; + } + offset = totalLength; + }); + } + onDataRequestCleanup() { + this.dataReq = this.dataRes = null; + } + onData(data) { + debug('received "%s"', data); + const callback = (packet) => { + if (packet.type === "close") { + debug("got xhr close packet"); + this.onClose(); + return false; + } + this.onPacket(packet); + }; + if (this.protocol === 3) { + this.parser.decodePayload(data, callback); + } else { + this.parser.decodePayload(data).forEach(callback); + } + } + onClose() { + if (this.writable) { + this.send([{ type: "noop" }]); + } + super.onClose(); + } + send(packets) { + this.writable = false; + if (this.shouldClose) { + debug("appending close packet to payload"); + packets.push({ type: "close" }); + this.shouldClose(); + this.shouldClose = null; + } + const doWrite = (data) => { + const compress = packets.some((packet) => { + return packet.options && packet.options.compress; + }); + this.write(data, { compress }); + }; + if (this.protocol === 3) { + this.parser.encodePayload(packets, this.supportsBinary, doWrite); + } else { + this.parser.encodePayload(packets, doWrite); + } + } + write(data, options) { + debug('writing "%s"', data); + this.doWrite(data, options, () => { + this.req.cleanup(); + this.emit("drain"); + }); + } + doWrite(data, options, callback) { + const isString = typeof data === "string"; + const contentType = isString ? "text/plain; charset=UTF-8" : "application/octet-stream"; + const headers = { + "Content-Type": contentType + }; + const respond = (data2) => { + this.headers(this.req, headers); + this.res.cork(() => { + Object.keys(headers).forEach((key) => { + this.res.writeHeader(key, String(headers[key])); + }); + this.res.end(data2); + }); + callback(); + }; + if (!this.httpCompression || !options.compress) { + respond(data); + return; + } + const len = isString ? Buffer.byteLength(data) : data.length; + if (len < this.httpCompression.threshold) { + respond(data); + return; + } + const encoding = accepts(this.req).encodings(["gzip", "deflate"]); + if (!encoding) { + respond(data); + return; + } + this.compress(data, encoding, (err, data2) => { + if (err) { + this.res.writeStatus("500 Internal Server Error"); + this.res.end(); + callback(err); + return; + } + headers["Content-Encoding"] = encoding; + respond(data2); + }); + } + compress(data, encoding, callback) { + debug("compressing"); + const buffers = []; + let nread = 0; + compressionMethods[encoding](this.httpCompression).on("error", callback).on("data", function(chunk) { + buffers.push(chunk); + nread += chunk.length; + }).on("end", function() { + callback(null, Buffer.concat(buffers, nread)); + }).end(data); + } + doClose(fn) { + debug("closing"); + let closeTimeoutTimer; + const onClose = () => { + clearTimeout(closeTimeoutTimer); + fn(); + this.onClose(); + }; + if (this.writable) { + debug("transport writable - closing right away"); + this.send([{ type: "close" }]); + onClose(); + } else if (this.discarded) { + debug("transport discarded - closing right away"); + onClose(); + } else { + debug("transport not writable - buffering orderly close"); + this.shouldClose = onClose; + closeTimeoutTimer = setTimeout(onClose, this.closeTimeout); + } + } + headers(req, headers) { + headers = headers || {}; + const ua = req.headers["user-agent"]; + if (ua && (~ua.indexOf(";MSIE") || ~ua.indexOf("Trident/"))) { + headers["X-XSS-Protection"] = "0"; + } + headers["cache-control"] = "no-store"; + this.emit("headers", headers, req); + return headers; + } + } + exports2.Polling = Polling; +}); + +// node_modules/engine.io/build/transports-uws/websocket.js +var require_websocket3 = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WebSocket = undefined; + var transport_1 = require_transport(); + var debug_1 = require_src(); + var debug = (0, debug_1.default)("engine:ws"); + + class WebSocket extends transport_1.Transport { + constructor(req) { + super(req); + this.writable = false; + this.perMessageDeflate = null; + } + get name() { + return "websocket"; + } + get handlesUpgrades() { + return true; + } + send(packets) { + this.writable = false; + for (let i = 0;i < packets.length; i++) { + const packet = packets[i]; + const isLast = i + 1 === packets.length; + const send = (data) => { + const isBinary = typeof data !== "string"; + const compress = this.perMessageDeflate && Buffer.byteLength(data) > this.perMessageDeflate.threshold; + debug('writing "%s"', data); + this.socket.send(data, isBinary, compress); + if (isLast) { + this.emit("drain"); + this.writable = true; + this.emit("ready"); + } + }; + if (packet.options && typeof packet.options.wsPreEncoded === "string") { + send(packet.options.wsPreEncoded); + } else { + this.parser.encodePacket(packet, this.supportsBinary, send); + } + } + } + doClose(fn) { + debug("closing"); + fn && fn(); + this.socket.end(); + } + } + exports2.WebSocket = WebSocket; +}); + +// node_modules/engine.io/build/transports-uws/index.js +var require_transports_uws = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + var polling_1 = require_polling2(); + var websocket_1 = require_websocket3(); + exports2.default = { + polling: polling_1.Polling, + websocket: websocket_1.WebSocket + }; +}); + +// node_modules/engine.io/build/userver.js +var require_userver = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.uServer = undefined; + var debug_1 = require_src(); + var server_1 = require_server(); + var transports_uws_1 = require_transports_uws(); + var debug = (0, debug_1.default)("engine:uws"); + + class uServer extends server_1.BaseServer { + init() {} + cleanup() {} + prepare(req, res) { + req.method = req.getMethod().toUpperCase(); + req.url = req.getUrl(); + const params = new URLSearchParams(req.getQuery()); + req._query = Object.fromEntries(params.entries()); + req.headers = {}; + req.forEach((key, value) => { + req.headers[key] = value; + }); + req.connection = { + remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString() + }; + res.onAborted(() => { + debug("response has been aborted"); + }); + } + createTransport(transportName, req) { + return new transports_uws_1.default[transportName](req); + } + attach(app, options = {}) { + const path = this._computePath(options); + app.any(path, this.handleRequest.bind(this)).ws(path, { + compression: options.compression, + idleTimeout: options.idleTimeout, + maxBackpressure: options.maxBackpressure, + maxPayloadLength: this.opts.maxHttpBufferSize, + upgrade: this.handleUpgrade.bind(this), + open: (ws) => { + const transport = ws.getUserData().transport; + transport.socket = ws; + transport.writable = true; + transport.emit("ready"); + }, + message: (ws, message, isBinary) => { + ws.getUserData().transport.onData(isBinary ? message : Buffer.from(message).toString()); + }, + close: (ws, code, message) => { + ws.getUserData().transport.onClose(code, message); + } + }); + } + _applyMiddlewares(req, res, callback) { + if (this.middlewares.length === 0) { + return callback(); + } + req.res = new ResponseWrapper(res); + super._applyMiddlewares(req, req.res, (err) => { + req.res.writeHead(); + callback(err); + }); + } + handleRequest(res, req) { + debug('handling "%s" http request "%s"', req.getMethod(), req.getUrl()); + this.prepare(req, res); + req.res = res; + const callback = (errorCode, errorContext) => { + if (errorCode !== undefined) { + this.emit("connection_error", { + req, + code: errorCode, + message: server_1.Server.errorMessages[errorCode], + context: errorContext + }); + this.abortRequest(req.res, errorCode, errorContext); + return; + } + if (req._query.sid) { + debug("setting new request for existing client"); + this.clients[req._query.sid].transport.onRequest(req); + } else { + const closeConnection = (errorCode2, errorContext2) => this.abortRequest(res, errorCode2, errorContext2); + this.handshake(req._query.transport, req, closeConnection); + } + }; + this._applyMiddlewares(req, res, (err) => { + if (err) { + callback(server_1.Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" }); + } else { + this.verify(req, false, callback); + } + }); + } + handleUpgrade(res, req, context) { + debug("on upgrade"); + this.prepare(req, res); + req.res = res; + const callback = async (errorCode, errorContext) => { + if (errorCode !== undefined) { + this.emit("connection_error", { + req, + code: errorCode, + message: server_1.Server.errorMessages[errorCode], + context: errorContext + }); + this.abortRequest(res, errorCode, errorContext); + return; + } + const id = req._query.sid; + let transport; + if (id) { + const client = this.clients[id]; + if (!client) { + debug("upgrade attempt for closed client"); + return res.close(); + } else if (client.upgrading) { + debug("transport has already been trying to upgrade"); + return res.close(); + } else if (client.upgraded) { + debug("transport had already been upgraded"); + return res.close(); + } else { + debug("upgrading existing transport"); + transport = this.createTransport(req._query.transport, req); + client._maybeUpgrade(transport); + } + } else { + transport = await this.handshake(req._query.transport, req, (errorCode2, errorContext2) => this.abortRequest(res, errorCode2, errorContext2)); + if (!transport) { + return; + } + } + req.res.writeStatus("101 Switching Protocols"); + res.upgrade({ + transport + }, req.getHeader("sec-websocket-key"), req.getHeader("sec-websocket-protocol"), req.getHeader("sec-websocket-extensions"), context); + }; + this._applyMiddlewares(req, res, (err) => { + if (err) { + callback(server_1.Server.errors.BAD_REQUEST, { name: "MIDDLEWARE_FAILURE" }); + } else { + this.verify(req, true, callback); + } + }); + } + abortRequest(res, errorCode, errorContext) { + const statusCode = errorCode === server_1.Server.errors.FORBIDDEN ? "403 Forbidden" : "400 Bad Request"; + const message = errorContext && errorContext.message ? errorContext.message : server_1.Server.errorMessages[errorCode]; + res.writeStatus(statusCode); + res.writeHeader("Content-Type", "application/json"); + res.end(JSON.stringify({ + code: errorCode, + message + })); + } + } + exports2.uServer = uServer; + + class ResponseWrapper { + constructor(res) { + this.res = res; + this.statusWritten = false; + this.headers = []; + this.isAborted = false; + } + set statusCode(status) { + if (!status) { + return; + } + this.writeStatus(status === 200 ? "200 OK" : "204 No Content"); + } + writeHead(status) { + this.statusCode = status; + } + setHeader(key, value) { + if (Array.isArray(value)) { + value.forEach((val) => { + this.writeHeader(key, val); + }); + } else { + this.writeHeader(key, value); + } + } + removeHeader() {} + getHeader() {} + writeStatus(status) { + if (this.isAborted) + return; + this.res.writeStatus(status); + this.statusWritten = true; + this.writeBufferedHeaders(); + return this; + } + writeHeader(key, value) { + if (this.isAborted) + return; + if (key === "Content-Length") { + return; + } + if (this.statusWritten) { + this.res.writeHeader(key, value); + } else { + this.headers.push([key, value]); + } + } + writeBufferedHeaders() { + this.headers.forEach(([key, value]) => { + this.res.writeHeader(key, value); + }); + } + end(data) { + if (this.isAborted) + return; + this.res.cork(() => { + if (!this.statusWritten) { + this.writeBufferedHeaders(); + } + this.res.end(data); + }); + } + onData(fn) { + if (this.isAborted) + return; + this.res.onData(fn); + } + onAborted(fn) { + if (this.isAborted) + return; + this.res.onAborted(() => { + this.isAborted = true; + fn(); + }); + } + cork(fn) { + if (this.isAborted) + return; + this.res.cork(fn); + } + } +}); + +// node_modules/engine.io/build/engine.io.js +var require_engine_io = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.protocol = exports2.Transport = exports2.Socket = exports2.uServer = exports2.parser = exports2.transports = exports2.Server = undefined; + exports2.listen = listen; + exports2.attach = attach; + var http_1 = require("http"); + var server_1 = require_server(); + Object.defineProperty(exports2, "Server", { enumerable: true, get: function() { + return server_1.Server; + } }); + var index_1 = require_transports(); + exports2.transports = index_1.default; + var parser = require_cjs(); + exports2.parser = parser; + var userver_1 = require_userver(); + Object.defineProperty(exports2, "uServer", { enumerable: true, get: function() { + return userver_1.uServer; + } }); + var socket_1 = require_socket(); + Object.defineProperty(exports2, "Socket", { enumerable: true, get: function() { + return socket_1.Socket; + } }); + var transport_1 = require_transport(); + Object.defineProperty(exports2, "Transport", { enumerable: true, get: function() { + return transport_1.Transport; + } }); + exports2.protocol = parser.protocol; + function listen(port, options, fn) { + if (typeof options === "function") { + fn = options; + options = {}; + } + const server = (0, http_1.createServer)(function(req, res) { + res.writeHead(501); + res.end("Not Implemented"); + }); + const engine = attach(server, options); + engine.httpServer = server; + server.listen(port, fn); + return engine; + } + function attach(server, options) { + const engine = new server_1.Server(options); + engine.attach(server, options); + return engine; + } +}); + +// node_modules/@socket.io/component-emitter/lib/cjs/index.js +var require_cjs2 = __commonJS((exports2) => { + exports2.Emitter = Emitter; + function Emitter(obj) { + if (obj) + return mixin(obj); + } + function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; + } + Emitter.prototype.on = Emitter.prototype.addEventListener = function(event, fn) { + this._callbacks = this._callbacks || {}; + (this._callbacks["$" + event] = this._callbacks["$" + event] || []).push(fn); + return this; + }; + Emitter.prototype.once = function(event, fn) { + function on2() { + this.off(event, on2); + fn.apply(this, arguments); + } + on2.fn = fn; + this.on(event, on2); + return this; + }; + Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function(event, fn) { + this._callbacks = this._callbacks || {}; + if (arguments.length == 0) { + this._callbacks = {}; + return this; + } + var callbacks = this._callbacks["$" + event]; + if (!callbacks) + return this; + if (arguments.length == 1) { + delete this._callbacks["$" + event]; + return this; + } + var cb; + for (var i = 0;i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + if (callbacks.length === 0) { + delete this._callbacks["$" + event]; + } + return this; + }; + Emitter.prototype.emit = function(event) { + this._callbacks = this._callbacks || {}; + var args = new Array(arguments.length - 1), callbacks = this._callbacks["$" + event]; + for (var i = 1;i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length;i < len; ++i) { + callbacks[i].apply(this, args); + } + } + return this; + }; + Emitter.prototype.emitReserved = Emitter.prototype.emit; + Emitter.prototype.listeners = function(event) { + this._callbacks = this._callbacks || {}; + return this._callbacks["$" + event] || []; + }; + Emitter.prototype.hasListeners = function(event) { + return !!this.listeners(event).length; + }; +}); + +// node_modules/socket.io-parser/build/cjs/is-binary.js +var require_is_binary = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.hasBinary = exports2.isBinary = undefined; + var withNativeArrayBuffer = typeof ArrayBuffer === "function"; + var isView = (obj) => { + return typeof ArrayBuffer.isView === "function" ? ArrayBuffer.isView(obj) : obj.buffer instanceof ArrayBuffer; + }; + var toString = Object.prototype.toString; + var withNativeBlob = typeof Blob === "function" || typeof Blob !== "undefined" && toString.call(Blob) === "[object BlobConstructor]"; + var withNativeFile = typeof File === "function" || typeof File !== "undefined" && toString.call(File) === "[object FileConstructor]"; + function isBinary(obj) { + return withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj)) || withNativeBlob && obj instanceof Blob || withNativeFile && obj instanceof File; + } + exports2.isBinary = isBinary; + function hasBinary(obj, toJSON) { + if (!obj || typeof obj !== "object") { + return false; + } + if (Array.isArray(obj)) { + for (let i = 0, l = obj.length;i < l; i++) { + if (hasBinary(obj[i])) { + return true; + } + } + return false; + } + if (isBinary(obj)) { + return true; + } + if (obj.toJSON && typeof obj.toJSON === "function" && arguments.length === 1) { + return hasBinary(obj.toJSON(), true); + } + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) { + return true; + } + } + return false; + } + exports2.hasBinary = hasBinary; +}); + +// node_modules/socket.io-parser/build/cjs/binary.js +var require_binary = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.reconstructPacket = exports2.deconstructPacket = undefined; + var is_binary_js_1 = require_is_binary(); + function deconstructPacket(packet) { + const buffers = []; + const packetData = packet.data; + const pack = packet; + pack.data = _deconstructPacket(packetData, buffers); + pack.attachments = buffers.length; + return { packet: pack, buffers }; + } + exports2.deconstructPacket = deconstructPacket; + function _deconstructPacket(data, buffers) { + if (!data) + return data; + if ((0, is_binary_js_1.isBinary)(data)) { + const placeholder = { _placeholder: true, num: buffers.length }; + buffers.push(data); + return placeholder; + } else if (Array.isArray(data)) { + const newData = new Array(data.length); + for (let i = 0;i < data.length; i++) { + newData[i] = _deconstructPacket(data[i], buffers); + } + return newData; + } else if (typeof data === "object" && !(data instanceof Date)) { + const newData = {}; + for (const key in data) { + if (Object.prototype.hasOwnProperty.call(data, key)) { + newData[key] = _deconstructPacket(data[key], buffers); + } + } + return newData; + } + return data; + } + function reconstructPacket(packet, buffers) { + packet.data = _reconstructPacket(packet.data, buffers); + delete packet.attachments; + return packet; + } + exports2.reconstructPacket = reconstructPacket; + function _reconstructPacket(data, buffers) { + if (!data) + return data; + if (data && data._placeholder === true) { + const isIndexValid = typeof data.num === "number" && data.num >= 0 && data.num < buffers.length; + if (isIndexValid) { + return buffers[data.num]; + } else { + throw new Error("illegal attachments"); + } + } else if (Array.isArray(data)) { + for (let i = 0;i < data.length; i++) { + data[i] = _reconstructPacket(data[i], buffers); + } + } else if (typeof data === "object") { + for (const key in data) { + if (Object.prototype.hasOwnProperty.call(data, key)) { + data[key] = _reconstructPacket(data[key], buffers); + } + } + } + return data; + } +}); + +// node_modules/socket.io-parser/build/cjs/index.js +var require_cjs3 = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Decoder = exports2.Encoder = exports2.PacketType = exports2.protocol = undefined; + var component_emitter_1 = require_cjs2(); + var binary_js_1 = require_binary(); + var is_binary_js_1 = require_is_binary(); + var debug_1 = require_src(); + var debug = (0, debug_1.default)("socket.io-parser"); + var RESERVED_EVENTS = [ + "connect", + "connect_error", + "disconnect", + "disconnecting", + "newListener", + "removeListener" + ]; + exports2.protocol = 5; + var PacketType; + (function(PacketType2) { + PacketType2[PacketType2["CONNECT"] = 0] = "CONNECT"; + PacketType2[PacketType2["DISCONNECT"] = 1] = "DISCONNECT"; + PacketType2[PacketType2["EVENT"] = 2] = "EVENT"; + PacketType2[PacketType2["ACK"] = 3] = "ACK"; + PacketType2[PacketType2["CONNECT_ERROR"] = 4] = "CONNECT_ERROR"; + PacketType2[PacketType2["BINARY_EVENT"] = 5] = "BINARY_EVENT"; + PacketType2[PacketType2["BINARY_ACK"] = 6] = "BINARY_ACK"; + })(PacketType = exports2.PacketType || (exports2.PacketType = {})); + + class Encoder { + constructor(replacer) { + this.replacer = replacer; + } + encode(obj) { + debug("encoding packet %j", obj); + if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) { + if ((0, is_binary_js_1.hasBinary)(obj)) { + return this.encodeAsBinary({ + type: obj.type === PacketType.EVENT ? PacketType.BINARY_EVENT : PacketType.BINARY_ACK, + nsp: obj.nsp, + data: obj.data, + id: obj.id + }); + } + } + return [this.encodeAsString(obj)]; + } + encodeAsString(obj) { + let str = "" + obj.type; + if (obj.type === PacketType.BINARY_EVENT || obj.type === PacketType.BINARY_ACK) { + str += obj.attachments + "-"; + } + if (obj.nsp && obj.nsp !== "/") { + str += obj.nsp + ","; + } + if (obj.id != null) { + str += obj.id; + } + if (obj.data != null) { + str += JSON.stringify(obj.data, this.replacer); + } + debug("encoded %j as %s", obj, str); + return str; + } + encodeAsBinary(obj) { + const deconstruction = (0, binary_js_1.deconstructPacket)(obj); + const pack = this.encodeAsString(deconstruction.packet); + const buffers = deconstruction.buffers; + buffers.unshift(pack); + return buffers; + } + } + exports2.Encoder = Encoder; + function isObject(value) { + return Object.prototype.toString.call(value) === "[object Object]"; + } + + class Decoder extends component_emitter_1.Emitter { + constructor(reviver) { + super(); + this.reviver = reviver; + } + add(obj) { + let packet; + if (typeof obj === "string") { + if (this.reconstructor) { + throw new Error("got plaintext data when reconstructing a packet"); + } + packet = this.decodeString(obj); + const isBinaryEvent = packet.type === PacketType.BINARY_EVENT; + if (isBinaryEvent || packet.type === PacketType.BINARY_ACK) { + packet.type = isBinaryEvent ? PacketType.EVENT : PacketType.ACK; + this.reconstructor = new BinaryReconstructor(packet); + if (packet.attachments === 0) { + super.emitReserved("decoded", packet); + } + } else { + super.emitReserved("decoded", packet); + } + } else if ((0, is_binary_js_1.isBinary)(obj) || obj.base64) { + if (!this.reconstructor) { + throw new Error("got binary data when not reconstructing a packet"); + } else { + packet = this.reconstructor.takeBinaryData(obj); + if (packet) { + this.reconstructor = null; + super.emitReserved("decoded", packet); + } + } + } else { + throw new Error("Unknown type: " + obj); + } + } + decodeString(str) { + let i = 0; + const p = { + type: Number(str.charAt(0)) + }; + if (PacketType[p.type] === undefined) { + throw new Error("unknown packet type " + p.type); + } + if (p.type === PacketType.BINARY_EVENT || p.type === PacketType.BINARY_ACK) { + const start = i + 1; + while (str.charAt(++i) !== "-" && i != str.length) {} + const buf = str.substring(start, i); + if (buf != Number(buf) || str.charAt(i) !== "-") { + throw new Error("Illegal attachments"); + } + p.attachments = Number(buf); + } + if (str.charAt(i + 1) === "/") { + const start = i + 1; + while (++i) { + const c = str.charAt(i); + if (c === ",") + break; + if (i === str.length) + break; + } + p.nsp = str.substring(start, i); + } else { + p.nsp = "/"; + } + const next = str.charAt(i + 1); + if (next !== "" && Number(next) == next) { + const start = i + 1; + while (++i) { + const c = str.charAt(i); + if (c == null || Number(c) != c) { + --i; + break; + } + if (i === str.length) + break; + } + p.id = Number(str.substring(start, i + 1)); + } + if (str.charAt(++i)) { + const payload = this.tryParse(str.substr(i)); + if (Decoder.isPayloadValid(p.type, payload)) { + p.data = payload; + } else { + throw new Error("invalid payload"); + } + } + debug("decoded %s as %j", str, p); + return p; + } + tryParse(str) { + try { + return JSON.parse(str, this.reviver); + } catch (e) { + return false; + } + } + static isPayloadValid(type, payload) { + switch (type) { + case PacketType.CONNECT: + return isObject(payload); + case PacketType.DISCONNECT: + return payload === undefined; + case PacketType.CONNECT_ERROR: + return typeof payload === "string" || isObject(payload); + case PacketType.EVENT: + case PacketType.BINARY_EVENT: + return Array.isArray(payload) && (typeof payload[0] === "number" || typeof payload[0] === "string" && RESERVED_EVENTS.indexOf(payload[0]) === -1); + case PacketType.ACK: + case PacketType.BINARY_ACK: + return Array.isArray(payload); + } + } + destroy() { + if (this.reconstructor) { + this.reconstructor.finishedReconstruction(); + this.reconstructor = null; + } + } + } + exports2.Decoder = Decoder; + + class BinaryReconstructor { + constructor(packet) { + this.packet = packet; + this.buffers = []; + this.reconPack = packet; + } + takeBinaryData(binData) { + this.buffers.push(binData); + if (this.buffers.length === this.reconPack.attachments) { + const packet = (0, binary_js_1.reconstructPacket)(this.reconPack, this.buffers); + this.finishedReconstruction(); + return packet; + } + return null; + } + finishedReconstruction() { + this.reconPack = null; + this.buffers = []; + } + } +}); + +// node_modules/socket.io/dist/client.js +var require_client = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Client = undefined; + var socket_io_parser_1 = require_cjs3(); + var debugModule = require_src(); + var url = require("url"); + var debug = debugModule("socket.io:client"); + + class Client { + constructor(server, conn) { + this.sockets = new Map; + this.nsps = new Map; + this.server = server; + this.conn = conn; + this.encoder = server.encoder; + this.decoder = new server._parser.Decoder; + this.id = conn.id; + this.setup(); + } + get request() { + return this.conn.request; + } + setup() { + this.onclose = this.onclose.bind(this); + this.ondata = this.ondata.bind(this); + this.onerror = this.onerror.bind(this); + this.ondecoded = this.ondecoded.bind(this); + this.decoder.on("decoded", this.ondecoded); + this.conn.on("data", this.ondata); + this.conn.on("error", this.onerror); + this.conn.on("close", this.onclose); + this.connectTimeout = setTimeout(() => { + if (this.nsps.size === 0) { + debug("no namespace joined yet, close the client"); + this.close(); + } else { + debug("the client has already joined a namespace, nothing to do"); + } + }, this.server._connectTimeout); + } + connect(name, auth = {}) { + if (this.server._nsps.has(name)) { + debug("connecting to namespace %s", name); + return this.doConnect(name, auth); + } + this.server._checkNamespace(name, auth, (dynamicNspName) => { + if (dynamicNspName) { + this.doConnect(name, auth); + } else { + debug("creation of namespace %s was denied", name); + this._packet({ + type: socket_io_parser_1.PacketType.CONNECT_ERROR, + nsp: name, + data: { + message: "Invalid namespace" + } + }); + } + }); + } + doConnect(name, auth) { + const nsp = this.server.of(name); + nsp._add(this, auth, (socket) => { + this.sockets.set(socket.id, socket); + this.nsps.set(nsp.name, socket); + if (this.connectTimeout) { + clearTimeout(this.connectTimeout); + this.connectTimeout = undefined; + } + }); + } + _disconnect() { + for (const socket of this.sockets.values()) { + socket.disconnect(); + } + this.sockets.clear(); + this.close(); + } + _remove(socket) { + if (this.sockets.has(socket.id)) { + const nsp = this.sockets.get(socket.id).nsp.name; + this.sockets.delete(socket.id); + this.nsps.delete(nsp); + } else { + debug("ignoring remove for %s", socket.id); + } + } + close() { + if (this.conn.readyState === "open") { + debug("forcing transport close"); + this.conn.close(); + this.onclose("forced server close"); + } + } + _packet(packet, opts = {}) { + if (this.conn.readyState !== "open") { + debug("ignoring packet write %j", packet); + return; + } + const encodedPackets = opts.preEncoded ? packet : this.encoder.encode(packet); + this.writeToEngine(encodedPackets, opts); + } + writeToEngine(encodedPackets, opts) { + if (opts.volatile && !this.conn.transport.writable) { + debug("volatile packet is discarded since the transport is not currently writable"); + return; + } + const packets = Array.isArray(encodedPackets) ? encodedPackets : [encodedPackets]; + for (const encodedPacket of packets) { + this.conn.write(encodedPacket, opts); + } + } + ondata(data) { + try { + this.decoder.add(data); + } catch (e) { + debug("invalid packet format"); + this.onerror(e); + } + } + ondecoded(packet) { + let namespace; + let authPayload; + if (this.conn.protocol === 3) { + const parsed = url.parse(packet.nsp, true); + namespace = parsed.pathname; + authPayload = parsed.query; + } else { + namespace = packet.nsp; + authPayload = packet.data; + } + const socket = this.nsps.get(namespace); + if (!socket && packet.type === socket_io_parser_1.PacketType.CONNECT) { + this.connect(namespace, authPayload); + } else if (socket && packet.type !== socket_io_parser_1.PacketType.CONNECT && packet.type !== socket_io_parser_1.PacketType.CONNECT_ERROR) { + process.nextTick(function() { + socket._onpacket(packet); + }); + } else { + debug("invalid state (packet type: %s)", packet.type); + this.close(); + } + } + onerror(err) { + for (const socket of this.sockets.values()) { + socket._onerror(err); + } + this.conn.close(); + } + onclose(reason, description) { + debug("client close with reason %s", reason); + this.destroy(); + for (const socket of this.sockets.values()) { + socket._onclose(reason, description); + } + this.sockets.clear(); + this.decoder.destroy(); + } + destroy() { + this.conn.removeListener("data", this.ondata); + this.conn.removeListener("error", this.onerror); + this.conn.removeListener("close", this.onclose); + this.decoder.removeListener("decoded", this.ondecoded); + if (this.connectTimeout) { + clearTimeout(this.connectTimeout); + this.connectTimeout = undefined; + } + } + } + exports2.Client = Client; +}); + +// node_modules/socket.io/dist/typed-events.js +var require_typed_events = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.StrictEventEmitter = undefined; + var events_1 = require("events"); + + class StrictEventEmitter extends events_1.EventEmitter { + on(ev, listener) { + return super.on(ev, listener); + } + once(ev, listener) { + return super.once(ev, listener); + } + emit(ev, ...args) { + return super.emit(ev, ...args); + } + emitReserved(ev, ...args) { + return super.emit(ev, ...args); + } + emitUntyped(ev, ...args) { + return super.emit(ev, ...args); + } + listeners(event) { + return super.listeners(event); + } + } + exports2.StrictEventEmitter = StrictEventEmitter; +}); + +// node_modules/socket.io/dist/socket-types.js +var require_socket_types = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.RESERVED_EVENTS = undefined; + exports2.RESERVED_EVENTS = new Set([ + "connect", + "connect_error", + "disconnect", + "disconnecting", + "newListener", + "removeListener" + ]); +}); + +// node_modules/socket.io/dist/broadcast-operator.js +var require_broadcast_operator = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.RemoteSocket = exports2.BroadcastOperator = undefined; + var socket_types_1 = require_socket_types(); + var socket_io_parser_1 = require_cjs3(); + + class BroadcastOperator { + constructor(adapter, rooms = new Set, exceptRooms = new Set, flags = {}) { + this.adapter = adapter; + this.rooms = rooms; + this.exceptRooms = exceptRooms; + this.flags = flags; + } + to(room) { + const rooms = new Set(this.rooms); + if (Array.isArray(room)) { + room.forEach((r) => rooms.add(r)); + } else { + rooms.add(room); + } + return new BroadcastOperator(this.adapter, rooms, this.exceptRooms, this.flags); + } + in(room) { + return this.to(room); + } + except(room) { + const exceptRooms = new Set(this.exceptRooms); + if (Array.isArray(room)) { + room.forEach((r) => exceptRooms.add(r)); + } else { + exceptRooms.add(room); + } + return new BroadcastOperator(this.adapter, this.rooms, exceptRooms, this.flags); + } + compress(compress) { + const flags = Object.assign({}, this.flags, { compress }); + return new BroadcastOperator(this.adapter, this.rooms, this.exceptRooms, flags); + } + get volatile() { + const flags = Object.assign({}, this.flags, { volatile: true }); + return new BroadcastOperator(this.adapter, this.rooms, this.exceptRooms, flags); + } + get local() { + const flags = Object.assign({}, this.flags, { local: true }); + return new BroadcastOperator(this.adapter, this.rooms, this.exceptRooms, flags); + } + timeout(timeout) { + const flags = Object.assign({}, this.flags, { timeout }); + return new BroadcastOperator(this.adapter, this.rooms, this.exceptRooms, flags); + } + emit(ev, ...args) { + if (socket_types_1.RESERVED_EVENTS.has(ev)) { + throw new Error(`"${String(ev)}" is a reserved event name`); + } + const data = [ev, ...args]; + const packet = { + type: socket_io_parser_1.PacketType.EVENT, + data + }; + const withAck = typeof data[data.length - 1] === "function"; + if (!withAck) { + this.adapter.broadcast(packet, { + rooms: this.rooms, + except: this.exceptRooms, + flags: this.flags + }); + return true; + } + const ack = data.pop(); + let timedOut = false; + let responses = []; + const timer = setTimeout(() => { + timedOut = true; + ack.apply(this, [ + new Error("operation has timed out"), + this.flags.expectSingleResponse ? null : responses + ]); + }, this.flags.timeout); + let expectedServerCount = -1; + let actualServerCount = 0; + let expectedClientCount = 0; + const checkCompleteness = () => { + if (!timedOut && expectedServerCount === actualServerCount && responses.length === expectedClientCount) { + clearTimeout(timer); + ack.apply(this, [ + null, + this.flags.expectSingleResponse ? responses[0] : responses + ]); + } + }; + this.adapter.broadcastWithAck(packet, { + rooms: this.rooms, + except: this.exceptRooms, + flags: this.flags + }, (clientCount) => { + expectedClientCount += clientCount; + actualServerCount++; + checkCompleteness(); + }, (clientResponse) => { + responses.push(clientResponse); + checkCompleteness(); + }); + this.adapter.serverCount().then((serverCount) => { + expectedServerCount = serverCount; + checkCompleteness(); + }); + return true; + } + emitWithAck(ev, ...args) { + return new Promise((resolve, reject) => { + args.push((err, responses) => { + if (err) { + err.responses = responses; + return reject(err); + } else { + return resolve(responses); + } + }); + this.emit(ev, ...args); + }); + } + allSockets() { + if (!this.adapter) { + throw new Error("No adapter for this namespace, are you trying to get the list of clients of a dynamic namespace?"); + } + return this.adapter.sockets(this.rooms); + } + fetchSockets() { + return this.adapter.fetchSockets({ + rooms: this.rooms, + except: this.exceptRooms, + flags: this.flags + }).then((sockets) => { + return sockets.map((socket) => { + if (socket.server) { + return socket; + } else { + return new RemoteSocket(this.adapter, socket); + } + }); + }); + } + socketsJoin(room) { + this.adapter.addSockets({ + rooms: this.rooms, + except: this.exceptRooms, + flags: this.flags + }, Array.isArray(room) ? room : [room]); + } + socketsLeave(room) { + this.adapter.delSockets({ + rooms: this.rooms, + except: this.exceptRooms, + flags: this.flags + }, Array.isArray(room) ? room : [room]); + } + disconnectSockets(close = false) { + this.adapter.disconnectSockets({ + rooms: this.rooms, + except: this.exceptRooms, + flags: this.flags + }, close); + } + } + exports2.BroadcastOperator = BroadcastOperator; + + class RemoteSocket { + constructor(adapter, details) { + this.id = details.id; + this.handshake = details.handshake; + this.rooms = new Set(details.rooms); + this.data = details.data; + this.operator = new BroadcastOperator(adapter, new Set([this.id]), new Set, { + expectSingleResponse: true + }); + } + timeout(timeout) { + return this.operator.timeout(timeout); + } + emit(ev, ...args) { + return this.operator.emit(ev, ...args); + } + join(room) { + return this.operator.socketsJoin(room); + } + leave(room) { + return this.operator.socketsLeave(room); + } + disconnect(close = false) { + this.operator.disconnectSockets(close); + return this; + } + } + exports2.RemoteSocket = RemoteSocket; +}); + +// node_modules/socket.io/dist/socket.js +var require_socket2 = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Socket = undefined; + var socket_io_parser_1 = require_cjs3(); + var debug_1 = __importDefault(require_src()); + var typed_events_1 = require_typed_events(); + var base64id_1 = __importDefault(require_base64id()); + var broadcast_operator_1 = require_broadcast_operator(); + var socket_types_1 = require_socket_types(); + var debug = (0, debug_1.default)("socket.io:socket"); + var RECOVERABLE_DISCONNECT_REASONS = new Set([ + "transport error", + "transport close", + "forced close", + "ping timeout", + "server shutting down", + "forced server close" + ]); + function noop() {} + + class Socket extends typed_events_1.StrictEventEmitter { + constructor(nsp, client, auth, previousSession) { + super(); + this.nsp = nsp; + this.client = client; + this.recovered = false; + this.data = {}; + this.connected = false; + this.acks = new Map; + this.fns = []; + this.flags = {}; + this.server = nsp.server; + this.adapter = this.nsp.adapter; + if (previousSession) { + this.id = previousSession.sid; + this.pid = previousSession.pid; + previousSession.rooms.forEach((room) => this.join(room)); + this.data = previousSession.data; + previousSession.missedPackets.forEach((packet) => { + this.packet({ + type: socket_io_parser_1.PacketType.EVENT, + data: packet + }); + }); + this.recovered = true; + } else { + if (client.conn.protocol === 3) { + this.id = nsp.name !== "/" ? nsp.name + "#" + client.id : client.id; + } else { + this.id = base64id_1.default.generateId(); + } + if (this.server._opts.connectionStateRecovery) { + this.pid = base64id_1.default.generateId(); + } + } + this.handshake = this.buildHandshake(auth); + this.on("error", noop); + } + buildHandshake(auth) { + var _a, _b, _c, _d; + return { + headers: ((_a = this.request) === null || _a === undefined ? undefined : _a.headers) || {}, + time: new Date + "", + address: this.conn.remoteAddress, + xdomain: !!((_b = this.request) === null || _b === undefined ? undefined : _b.headers.origin), + secure: !this.request || !!this.request.connection.encrypted, + issued: +new Date, + url: (_c = this.request) === null || _c === undefined ? undefined : _c.url, + query: ((_d = this.request) === null || _d === undefined ? undefined : _d._query) || {}, + auth + }; + } + emit(ev, ...args) { + if (socket_types_1.RESERVED_EVENTS.has(ev)) { + throw new Error(`"${String(ev)}" is a reserved event name`); + } + const data = [ev, ...args]; + const packet = { + type: socket_io_parser_1.PacketType.EVENT, + data + }; + if (typeof data[data.length - 1] === "function") { + const id = this.nsp._ids++; + debug("emitting packet with ack id %d", id); + this.registerAckCallback(id, data.pop()); + packet.id = id; + } + const flags = Object.assign({}, this.flags); + this.flags = {}; + if (this.nsp.server.opts.connectionStateRecovery) { + this.adapter.broadcast(packet, { + rooms: new Set([this.id]), + except: new Set, + flags + }); + } else { + this.notifyOutgoingListeners(packet); + this.packet(packet, flags); + } + return true; + } + emitWithAck(ev, ...args) { + const withErr = this.flags.timeout !== undefined; + return new Promise((resolve, reject) => { + args.push((arg1, arg2) => { + if (withErr) { + return arg1 ? reject(arg1) : resolve(arg2); + } else { + return resolve(arg1); + } + }); + this.emit(ev, ...args); + }); + } + registerAckCallback(id, ack) { + const timeout = this.flags.timeout; + if (timeout === undefined) { + this.acks.set(id, ack); + return; + } + const timer = setTimeout(() => { + debug("event with ack id %d has timed out after %d ms", id, timeout); + this.acks.delete(id); + ack.call(this, new Error("operation has timed out")); + }, timeout); + this.acks.set(id, (...args) => { + clearTimeout(timer); + ack.apply(this, [null, ...args]); + }); + } + to(room) { + return this.newBroadcastOperator().to(room); + } + in(room) { + return this.newBroadcastOperator().in(room); + } + except(room) { + return this.newBroadcastOperator().except(room); + } + send(...args) { + this.emit("message", ...args); + return this; + } + write(...args) { + this.emit("message", ...args); + return this; + } + packet(packet, opts = {}) { + packet.nsp = this.nsp.name; + opts.compress = opts.compress !== false; + this.client._packet(packet, opts); + } + join(rooms) { + debug("join room %s", rooms); + return this.adapter.addAll(this.id, new Set(Array.isArray(rooms) ? rooms : [rooms])); + } + leave(room) { + debug("leave room %s", room); + return this.adapter.del(this.id, room); + } + leaveAll() { + this.adapter.delAll(this.id); + } + _onconnect() { + debug("socket connected - writing packet"); + this.connected = true; + this.join(this.id); + if (this.conn.protocol === 3) { + this.packet({ type: socket_io_parser_1.PacketType.CONNECT }); + } else { + this.packet({ + type: socket_io_parser_1.PacketType.CONNECT, + data: { sid: this.id, pid: this.pid } + }); + } + } + _onpacket(packet) { + debug("got packet %j", packet); + switch (packet.type) { + case socket_io_parser_1.PacketType.EVENT: + this.onevent(packet); + break; + case socket_io_parser_1.PacketType.BINARY_EVENT: + this.onevent(packet); + break; + case socket_io_parser_1.PacketType.ACK: + this.onack(packet); + break; + case socket_io_parser_1.PacketType.BINARY_ACK: + this.onack(packet); + break; + case socket_io_parser_1.PacketType.DISCONNECT: + this.ondisconnect(); + break; + } + } + onevent(packet) { + const args = packet.data || []; + debug("emitting event %j", args); + if (packet.id != null) { + debug("attaching ack callback to event"); + args.push(this.ack(packet.id)); + } + if (this._anyListeners && this._anyListeners.length) { + const listeners = this._anyListeners.slice(); + for (const listener of listeners) { + listener.apply(this, args); + } + } + this.dispatch(args); + } + ack(id) { + const self = this; + let sent = false; + return function() { + if (sent) + return; + const args = Array.prototype.slice.call(arguments); + debug("sending ack %j", args); + self.packet({ + id, + type: socket_io_parser_1.PacketType.ACK, + data: args + }); + sent = true; + }; + } + onack(packet) { + const ack = this.acks.get(packet.id); + if (typeof ack == "function") { + debug("calling ack %s with %j", packet.id, packet.data); + ack.apply(this, packet.data); + this.acks.delete(packet.id); + } else { + debug("bad ack %s", packet.id); + } + } + ondisconnect() { + debug("got disconnect packet"); + this._onclose("client namespace disconnect"); + } + _onerror(err) { + this.emitReserved("error", err); + } + _onclose(reason, description) { + if (!this.connected) + return this; + debug("closing socket - reason %s", reason); + this.emitReserved("disconnecting", reason, description); + if (this.server._opts.connectionStateRecovery && RECOVERABLE_DISCONNECT_REASONS.has(reason)) { + debug("connection state recovery is enabled for sid %s", this.id); + this.adapter.persistSession({ + sid: this.id, + pid: this.pid, + rooms: [...this.rooms], + data: this.data + }); + } + this._cleanup(); + this.client._remove(this); + this.connected = false; + this.emitReserved("disconnect", reason, description); + return; + } + _cleanup() { + this.leaveAll(); + this.nsp._remove(this); + this.join = noop; + } + _error(err) { + this.packet({ type: socket_io_parser_1.PacketType.CONNECT_ERROR, data: err }); + } + disconnect(close = false) { + if (!this.connected) + return this; + if (close) { + this.client._disconnect(); + } else { + this.packet({ type: socket_io_parser_1.PacketType.DISCONNECT }); + this._onclose("server namespace disconnect"); + } + return this; + } + compress(compress) { + this.flags.compress = compress; + return this; + } + get volatile() { + this.flags.volatile = true; + return this; + } + get broadcast() { + return this.newBroadcastOperator(); + } + get local() { + return this.newBroadcastOperator().local; + } + timeout(timeout) { + this.flags.timeout = timeout; + return this; + } + dispatch(event) { + debug("dispatching an event %j", event); + this.run(event, (err) => { + process.nextTick(() => { + if (err) { + return this._onerror(err); + } + if (this.connected) { + super.emitUntyped.apply(this, event); + } else { + debug("ignore packet received after disconnection"); + } + }); + }); + } + use(fn) { + this.fns.push(fn); + return this; + } + run(event, fn) { + if (!this.fns.length) + return fn(); + const fns = this.fns.slice(0); + function run(i) { + fns[i](event, (err) => { + if (err) + return fn(err); + if (!fns[i + 1]) + return fn(); + run(i + 1); + }); + } + run(0); + } + get disconnected() { + return !this.connected; + } + get request() { + return this.client.request; + } + get conn() { + return this.client.conn; + } + get rooms() { + return this.adapter.socketRooms(this.id) || new Set; + } + onAny(listener) { + this._anyListeners = this._anyListeners || []; + this._anyListeners.push(listener); + return this; + } + prependAny(listener) { + this._anyListeners = this._anyListeners || []; + this._anyListeners.unshift(listener); + return this; + } + offAny(listener) { + if (!this._anyListeners) { + return this; + } + if (listener) { + const listeners = this._anyListeners; + for (let i = 0;i < listeners.length; i++) { + if (listener === listeners[i]) { + listeners.splice(i, 1); + return this; + } + } + } else { + this._anyListeners = []; + } + return this; + } + listenersAny() { + return this._anyListeners || []; + } + onAnyOutgoing(listener) { + this._anyOutgoingListeners = this._anyOutgoingListeners || []; + this._anyOutgoingListeners.push(listener); + return this; + } + prependAnyOutgoing(listener) { + this._anyOutgoingListeners = this._anyOutgoingListeners || []; + this._anyOutgoingListeners.unshift(listener); + return this; + } + offAnyOutgoing(listener) { + if (!this._anyOutgoingListeners) { + return this; + } + if (listener) { + const listeners = this._anyOutgoingListeners; + for (let i = 0;i < listeners.length; i++) { + if (listener === listeners[i]) { + listeners.splice(i, 1); + return this; + } + } + } else { + this._anyOutgoingListeners = []; + } + return this; + } + listenersAnyOutgoing() { + return this._anyOutgoingListeners || []; + } + notifyOutgoingListeners(packet) { + if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) { + const listeners = this._anyOutgoingListeners.slice(); + for (const listener of listeners) { + listener.apply(this, packet.data); + } + } + } + newBroadcastOperator() { + const flags = Object.assign({}, this.flags); + this.flags = {}; + return new broadcast_operator_1.BroadcastOperator(this.adapter, new Set, new Set([this.id]), flags); + } + } + exports2.Socket = Socket; +}); + +// node_modules/socket.io/dist/namespace.js +var require_namespace = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Namespace = exports2.RESERVED_EVENTS = undefined; + var socket_1 = require_socket2(); + var typed_events_1 = require_typed_events(); + var debug_1 = __importDefault(require_src()); + var broadcast_operator_1 = require_broadcast_operator(); + var debug = (0, debug_1.default)("socket.io:namespace"); + exports2.RESERVED_EVENTS = new Set(["connect", "connection", "new_namespace"]); + + class Namespace extends typed_events_1.StrictEventEmitter { + constructor(server, name) { + super(); + this.sockets = new Map; + this._preConnectSockets = new Map; + this._fns = []; + this._ids = 0; + this.server = server; + this.name = name; + this._initAdapter(); + } + _initAdapter() { + this.adapter = new (this.server.adapter())(this); + } + use(fn) { + this._fns.push(fn); + return this; + } + run(socket, fn) { + if (!this._fns.length) + return fn(); + const fns = this._fns.slice(0); + function run(i) { + fns[i](socket, (err) => { + if (err) + return fn(err); + if (!fns[i + 1]) + return fn(); + run(i + 1); + }); + } + run(0); + } + to(room) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).to(room); + } + in(room) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).in(room); + } + except(room) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).except(room); + } + async _add(client, auth, fn) { + var _a; + debug("adding socket to nsp %s", this.name); + const socket = await this._createSocket(client, auth); + this._preConnectSockets.set(socket.id, socket); + if (((_a = this.server.opts.connectionStateRecovery) === null || _a === undefined ? undefined : _a.skipMiddlewares) && socket.recovered && client.conn.readyState === "open") { + return this._doConnect(socket, fn); + } + this.run(socket, (err) => { + process.nextTick(() => { + if (client.conn.readyState !== "open") { + debug("next called after client was closed - ignoring socket"); + socket._cleanup(); + return; + } + if (err) { + debug("middleware error, sending CONNECT_ERROR packet to the client"); + socket._cleanup(); + if (client.conn.protocol === 3) { + return socket._error(err.data || err.message); + } else { + return socket._error({ + message: err.message, + data: err.data + }); + } + } + this._doConnect(socket, fn); + }); + }); + } + async _createSocket(client, auth) { + const sessionId = auth.pid; + const offset = auth.offset; + if (this.server.opts.connectionStateRecovery && typeof sessionId === "string" && typeof offset === "string") { + let session; + try { + session = await this.adapter.restoreSession(sessionId, offset); + } catch (e) { + debug("error while restoring session: %s", e); + } + if (session) { + debug("connection state recovered for sid %s", session.sid); + return new socket_1.Socket(this, client, auth, session); + } + } + return new socket_1.Socket(this, client, auth); + } + _doConnect(socket, fn) { + this._preConnectSockets.delete(socket.id); + this.sockets.set(socket.id, socket); + socket._onconnect(); + if (fn) + fn(socket); + this.emitReserved("connect", socket); + this.emitReserved("connection", socket); + } + _remove(socket) { + this.sockets.delete(socket.id) || this._preConnectSockets.delete(socket.id); + } + emit(ev, ...args) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).emit(ev, ...args); + } + send(...args) { + this.emit("message", ...args); + return this; + } + write(...args) { + this.emit("message", ...args); + return this; + } + serverSideEmit(ev, ...args) { + if (exports2.RESERVED_EVENTS.has(ev)) { + throw new Error(`"${String(ev)}" is a reserved event name`); + } + args.unshift(ev); + this.adapter.serverSideEmit(args); + return true; + } + serverSideEmitWithAck(ev, ...args) { + return new Promise((resolve, reject) => { + args.push((err, responses) => { + if (err) { + err.responses = responses; + return reject(err); + } else { + return resolve(responses); + } + }); + this.serverSideEmit(ev, ...args); + }); + } + _onServerSideEmit(args) { + super.emitUntyped.apply(this, args); + } + allSockets() { + return new broadcast_operator_1.BroadcastOperator(this.adapter).allSockets(); + } + compress(compress) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).compress(compress); + } + get volatile() { + return new broadcast_operator_1.BroadcastOperator(this.adapter).volatile; + } + get local() { + return new broadcast_operator_1.BroadcastOperator(this.adapter).local; + } + timeout(timeout) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).timeout(timeout); + } + fetchSockets() { + return new broadcast_operator_1.BroadcastOperator(this.adapter).fetchSockets(); + } + socketsJoin(room) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).socketsJoin(room); + } + socketsLeave(room) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).socketsLeave(room); + } + disconnectSockets(close = false) { + return new broadcast_operator_1.BroadcastOperator(this.adapter).disconnectSockets(close); + } + } + exports2.Namespace = Namespace; +}); + +// node_modules/socket.io-adapter/dist/contrib/yeast.js +var require_yeast = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.yeast = exports2.decode = exports2.encode = undefined; + var alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_".split(""); + var length = 64; + var map = {}; + var seed = 0; + var i = 0; + var prev; + function encode(num) { + let encoded = ""; + do { + encoded = alphabet[num % length] + encoded; + num = Math.floor(num / length); + } while (num > 0); + return encoded; + } + exports2.encode = encode; + function decode(str) { + let decoded = 0; + for (i = 0;i < str.length; i++) { + decoded = decoded * length + map[str.charAt(i)]; + } + return decoded; + } + exports2.decode = decode; + function yeast() { + const now = encode(+new Date); + if (now !== prev) + return seed = 0, prev = now; + return now + "." + encode(seed++); + } + exports2.yeast = yeast; + for (;i < length; i++) + map[alphabet[i]] = i; +}); + +// node_modules/socket.io-adapter/dist/in-memory-adapter.js +var require_in_memory_adapter = __commonJS((exports2) => { + var _a; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.SessionAwareAdapter = exports2.Adapter = undefined; + var events_1 = require("events"); + var yeast_1 = require_yeast(); + var WebSocket = require_ws(); + var canPreComputeFrame = typeof ((_a = WebSocket === null || WebSocket === undefined ? undefined : WebSocket.Sender) === null || _a === undefined ? undefined : _a.frame) === "function"; + + class Adapter extends events_1.EventEmitter { + constructor(nsp) { + super(); + this.nsp = nsp; + this.rooms = new Map; + this.sids = new Map; + this.encoder = nsp.server.encoder; + } + init() {} + close() {} + serverCount() { + return Promise.resolve(1); + } + addAll(id, rooms) { + if (!this.sids.has(id)) { + this.sids.set(id, new Set); + } + for (const room of rooms) { + this.sids.get(id).add(room); + if (!this.rooms.has(room)) { + this.rooms.set(room, new Set); + this.emit("create-room", room); + } + if (!this.rooms.get(room).has(id)) { + this.rooms.get(room).add(id); + this.emit("join-room", room, id); + } + } + } + del(id, room) { + if (this.sids.has(id)) { + this.sids.get(id).delete(room); + } + this._del(room, id); + } + _del(room, id) { + const _room = this.rooms.get(room); + if (_room != null) { + const deleted = _room.delete(id); + if (deleted) { + this.emit("leave-room", room, id); + } + if (_room.size === 0 && this.rooms.delete(room)) { + this.emit("delete-room", room); + } + } + } + delAll(id) { + if (!this.sids.has(id)) { + return; + } + for (const room of this.sids.get(id)) { + this._del(room, id); + } + this.sids.delete(id); + } + broadcast(packet, opts) { + const flags = opts.flags || {}; + const packetOpts = { + preEncoded: true, + volatile: flags.volatile, + compress: flags.compress + }; + packet.nsp = this.nsp.name; + const encodedPackets = this._encode(packet, packetOpts); + this.apply(opts, (socket) => { + if (typeof socket.notifyOutgoingListeners === "function") { + socket.notifyOutgoingListeners(packet); + } + socket.client.writeToEngine(encodedPackets, packetOpts); + }); + } + broadcastWithAck(packet, opts, clientCountCallback, ack) { + const flags = opts.flags || {}; + const packetOpts = { + preEncoded: true, + volatile: flags.volatile, + compress: flags.compress + }; + packet.nsp = this.nsp.name; + packet.id = this.nsp._ids++; + const encodedPackets = this._encode(packet, packetOpts); + let clientCount = 0; + this.apply(opts, (socket) => { + clientCount++; + socket.acks.set(packet.id, ack); + if (typeof socket.notifyOutgoingListeners === "function") { + socket.notifyOutgoingListeners(packet); + } + socket.client.writeToEngine(encodedPackets, packetOpts); + }); + clientCountCallback(clientCount); + } + _encode(packet, packetOpts) { + const encodedPackets = this.encoder.encode(packet); + if (canPreComputeFrame && encodedPackets.length === 1 && typeof encodedPackets[0] === "string") { + const data = Buffer.from("4" + encodedPackets[0]); + packetOpts.wsPreEncodedFrame = WebSocket.Sender.frame(data, { + readOnly: false, + mask: false, + rsv1: false, + opcode: 1, + fin: true + }); + } + return encodedPackets; + } + sockets(rooms) { + const sids = new Set; + this.apply({ rooms }, (socket) => { + sids.add(socket.id); + }); + return Promise.resolve(sids); + } + socketRooms(id) { + return this.sids.get(id); + } + fetchSockets(opts) { + const sockets = []; + this.apply(opts, (socket) => { + sockets.push(socket); + }); + return Promise.resolve(sockets); + } + addSockets(opts, rooms) { + this.apply(opts, (socket) => { + socket.join(rooms); + }); + } + delSockets(opts, rooms) { + this.apply(opts, (socket) => { + rooms.forEach((room) => socket.leave(room)); + }); + } + disconnectSockets(opts, close) { + this.apply(opts, (socket) => { + socket.disconnect(close); + }); + } + apply(opts, callback) { + const rooms = opts.rooms; + const except = this.computeExceptSids(opts.except); + if (rooms.size) { + const ids = new Set; + for (const room of rooms) { + if (!this.rooms.has(room)) + continue; + for (const id of this.rooms.get(room)) { + if (ids.has(id) || except.has(id)) + continue; + const socket = this.nsp.sockets.get(id); + if (socket) { + callback(socket); + ids.add(id); + } + } + } + } else { + for (const [id] of this.sids) { + if (except.has(id)) + continue; + const socket = this.nsp.sockets.get(id); + if (socket) + callback(socket); + } + } + } + computeExceptSids(exceptRooms) { + const exceptSids = new Set; + if (exceptRooms && exceptRooms.size > 0) { + for (const room of exceptRooms) { + if (this.rooms.has(room)) { + this.rooms.get(room).forEach((sid) => exceptSids.add(sid)); + } + } + } + return exceptSids; + } + serverSideEmit(packet) { + console.warn("this adapter does not support the serverSideEmit() functionality"); + } + persistSession(session) {} + restoreSession(pid, offset) { + return null; + } + } + exports2.Adapter = Adapter; + + class SessionAwareAdapter extends Adapter { + constructor(nsp) { + super(nsp); + this.nsp = nsp; + this.sessions = new Map; + this.packets = []; + this.maxDisconnectionDuration = nsp.server.opts.connectionStateRecovery.maxDisconnectionDuration; + const timer = setInterval(() => { + const threshold = Date.now() - this.maxDisconnectionDuration; + this.sessions.forEach((session, sessionId) => { + const hasExpired = session.disconnectedAt < threshold; + if (hasExpired) { + this.sessions.delete(sessionId); + } + }); + for (let i = this.packets.length - 1;i >= 0; i--) { + const hasExpired = this.packets[i].emittedAt < threshold; + if (hasExpired) { + this.packets.splice(0, i + 1); + break; + } + } + }, 60 * 1000); + timer.unref(); + } + persistSession(session) { + session.disconnectedAt = Date.now(); + this.sessions.set(session.pid, session); + } + restoreSession(pid, offset) { + const session = this.sessions.get(pid); + if (!session) { + return null; + } + const hasExpired = session.disconnectedAt + this.maxDisconnectionDuration < Date.now(); + if (hasExpired) { + this.sessions.delete(pid); + return null; + } + const index = this.packets.findIndex((packet) => packet.id === offset); + if (index === -1) { + return null; + } + const missedPackets = []; + for (let i = index + 1;i < this.packets.length; i++) { + const packet = this.packets[i]; + if (shouldIncludePacket(session.rooms, packet.opts)) { + missedPackets.push(packet.data); + } + } + return Promise.resolve(Object.assign(Object.assign({}, session), { missedPackets })); + } + broadcast(packet, opts) { + var _a2; + const isEventPacket = packet.type === 2; + const withoutAcknowledgement = packet.id === undefined; + const notVolatile = ((_a2 = opts.flags) === null || _a2 === undefined ? undefined : _a2.volatile) === undefined; + if (isEventPacket && withoutAcknowledgement && notVolatile) { + const id = (0, yeast_1.yeast)(); + packet.data.push(id); + this.packets.push({ + id, + opts, + data: packet.data, + emittedAt: Date.now() + }); + } + super.broadcast(packet, opts); + } + } + exports2.SessionAwareAdapter = SessionAwareAdapter; + function shouldIncludePacket(sessionRooms, opts) { + const included = opts.rooms.size === 0 || sessionRooms.some((room) => opts.rooms.has(room)); + const notExcluded = sessionRooms.every((room) => !opts.except.has(room)); + return included && notExcluded; + } +}); + +// node_modules/socket.io-adapter/dist/cluster-adapter.js +var require_cluster_adapter = __commonJS((exports2) => { + var __rest = exports2 && exports2.__rest || function(s, e) { + var t = {}; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s);i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ClusterAdapterWithHeartbeat = exports2.ClusterAdapter = exports2.MessageType = undefined; + var in_memory_adapter_1 = require_in_memory_adapter(); + var debug_1 = require_src(); + var crypto_1 = require("crypto"); + var debug = (0, debug_1.debug)("socket.io-adapter"); + var EMITTER_UID = "emitter"; + var DEFAULT_TIMEOUT = 5000; + function randomId() { + return (0, crypto_1.randomBytes)(8).toString("hex"); + } + var MessageType; + (function(MessageType2) { + MessageType2[MessageType2["INITIAL_HEARTBEAT"] = 1] = "INITIAL_HEARTBEAT"; + MessageType2[MessageType2["HEARTBEAT"] = 2] = "HEARTBEAT"; + MessageType2[MessageType2["BROADCAST"] = 3] = "BROADCAST"; + MessageType2[MessageType2["SOCKETS_JOIN"] = 4] = "SOCKETS_JOIN"; + MessageType2[MessageType2["SOCKETS_LEAVE"] = 5] = "SOCKETS_LEAVE"; + MessageType2[MessageType2["DISCONNECT_SOCKETS"] = 6] = "DISCONNECT_SOCKETS"; + MessageType2[MessageType2["FETCH_SOCKETS"] = 7] = "FETCH_SOCKETS"; + MessageType2[MessageType2["FETCH_SOCKETS_RESPONSE"] = 8] = "FETCH_SOCKETS_RESPONSE"; + MessageType2[MessageType2["SERVER_SIDE_EMIT"] = 9] = "SERVER_SIDE_EMIT"; + MessageType2[MessageType2["SERVER_SIDE_EMIT_RESPONSE"] = 10] = "SERVER_SIDE_EMIT_RESPONSE"; + MessageType2[MessageType2["BROADCAST_CLIENT_COUNT"] = 11] = "BROADCAST_CLIENT_COUNT"; + MessageType2[MessageType2["BROADCAST_ACK"] = 12] = "BROADCAST_ACK"; + MessageType2[MessageType2["ADAPTER_CLOSE"] = 13] = "ADAPTER_CLOSE"; + })(MessageType = exports2.MessageType || (exports2.MessageType = {})); + function encodeOptions(opts) { + return { + rooms: [...opts.rooms], + except: [...opts.except], + flags: opts.flags + }; + } + function decodeOptions(opts) { + return { + rooms: new Set(opts.rooms), + except: new Set(opts.except), + flags: opts.flags + }; + } + + class ClusterAdapter extends in_memory_adapter_1.Adapter { + constructor(nsp) { + super(nsp); + this.requests = new Map; + this.ackRequests = new Map; + this.uid = randomId(); + } + onMessage(message, offset) { + if (message.uid === this.uid) { + return debug("[%s] ignore message from self", this.uid); + } + debug("[%s] new event of type %d from %s", this.uid, message.type, message.uid); + switch (message.type) { + case MessageType.BROADCAST: { + const withAck = message.data.requestId !== undefined; + if (withAck) { + super.broadcastWithAck(message.data.packet, decodeOptions(message.data.opts), (clientCount) => { + debug("[%s] waiting for %d client acknowledgements", this.uid, clientCount); + this.publishResponse(message.uid, { + type: MessageType.BROADCAST_CLIENT_COUNT, + data: { + requestId: message.data.requestId, + clientCount + } + }); + }, (arg) => { + debug("[%s] received acknowledgement with value %j", this.uid, arg); + this.publishResponse(message.uid, { + type: MessageType.BROADCAST_ACK, + data: { + requestId: message.data.requestId, + packet: arg + } + }); + }); + } else { + const packet = message.data.packet; + const opts = decodeOptions(message.data.opts); + this.addOffsetIfNecessary(packet, opts, offset); + super.broadcast(packet, opts); + } + break; + } + case MessageType.SOCKETS_JOIN: + super.addSockets(decodeOptions(message.data.opts), message.data.rooms); + break; + case MessageType.SOCKETS_LEAVE: + super.delSockets(decodeOptions(message.data.opts), message.data.rooms); + break; + case MessageType.DISCONNECT_SOCKETS: + super.disconnectSockets(decodeOptions(message.data.opts), message.data.close); + break; + case MessageType.FETCH_SOCKETS: { + debug("[%s] calling fetchSockets with opts %j", this.uid, message.data.opts); + super.fetchSockets(decodeOptions(message.data.opts)).then((localSockets) => { + this.publishResponse(message.uid, { + type: MessageType.FETCH_SOCKETS_RESPONSE, + data: { + requestId: message.data.requestId, + sockets: localSockets.map((socket) => { + const _a = socket.handshake, { sessionStore } = _a, handshake = __rest(_a, ["sessionStore"]); + return { + id: socket.id, + handshake, + rooms: [...socket.rooms], + data: socket.data + }; + }) + } + }); + }); + break; + } + case MessageType.SERVER_SIDE_EMIT: { + const packet = message.data.packet; + const withAck = message.data.requestId !== undefined; + if (!withAck) { + this.nsp._onServerSideEmit(packet); + return; + } + let called = false; + const callback = (arg) => { + if (called) { + return; + } + called = true; + debug("[%s] calling acknowledgement with %j", this.uid, arg); + this.publishResponse(message.uid, { + type: MessageType.SERVER_SIDE_EMIT_RESPONSE, + data: { + requestId: message.data.requestId, + packet: arg + } + }); + }; + this.nsp._onServerSideEmit([...packet, callback]); + break; + } + case MessageType.BROADCAST_CLIENT_COUNT: + case MessageType.BROADCAST_ACK: + case MessageType.FETCH_SOCKETS_RESPONSE: + case MessageType.SERVER_SIDE_EMIT_RESPONSE: + this.onResponse(message); + break; + default: + debug("[%s] unknown message type: %s", this.uid, message.type); + } + } + onResponse(response) { + var _a, _b; + const requestId = response.data.requestId; + debug("[%s] received response %s to request %s", this.uid, response.type, requestId); + switch (response.type) { + case MessageType.BROADCAST_CLIENT_COUNT: { + (_a = this.ackRequests.get(requestId)) === null || _a === undefined || _a.clientCountCallback(response.data.clientCount); + break; + } + case MessageType.BROADCAST_ACK: { + (_b = this.ackRequests.get(requestId)) === null || _b === undefined || _b.ack(response.data.packet); + break; + } + case MessageType.FETCH_SOCKETS_RESPONSE: { + const request = this.requests.get(requestId); + if (!request) { + return; + } + request.current++; + response.data.sockets.forEach((socket) => request.responses.push(socket)); + if (request.current === request.expected) { + clearTimeout(request.timeout); + request.resolve(request.responses); + this.requests.delete(requestId); + } + break; + } + case MessageType.SERVER_SIDE_EMIT_RESPONSE: { + const request = this.requests.get(requestId); + if (!request) { + return; + } + request.current++; + request.responses.push(response.data.packet); + if (request.current === request.expected) { + clearTimeout(request.timeout); + request.resolve(null, request.responses); + this.requests.delete(requestId); + } + break; + } + default: + debug("[%s] unknown response type: %s", this.uid, response.type); + } + } + async broadcast(packet, opts) { + var _a; + const onlyLocal = (_a = opts.flags) === null || _a === undefined ? undefined : _a.local; + if (!onlyLocal) { + try { + const offset = await this.publishAndReturnOffset({ + type: MessageType.BROADCAST, + data: { + packet, + opts: encodeOptions(opts) + } + }); + this.addOffsetIfNecessary(packet, opts, offset); + } catch (e) { + return debug("[%s] error while broadcasting message: %s", this.uid, e.message); + } + } + super.broadcast(packet, opts); + } + addOffsetIfNecessary(packet, opts, offset) { + var _a; + if (!this.nsp.server.opts.connectionStateRecovery) { + return; + } + const isEventPacket = packet.type === 2; + const withoutAcknowledgement = packet.id === undefined; + const notVolatile = ((_a = opts.flags) === null || _a === undefined ? undefined : _a.volatile) === undefined; + if (isEventPacket && withoutAcknowledgement && notVolatile) { + packet.data.push(offset); + } + } + broadcastWithAck(packet, opts, clientCountCallback, ack) { + var _a; + const onlyLocal = (_a = opts === null || opts === undefined ? undefined : opts.flags) === null || _a === undefined ? undefined : _a.local; + if (!onlyLocal) { + const requestId = randomId(); + this.ackRequests.set(requestId, { + clientCountCallback, + ack + }); + this.publish({ + type: MessageType.BROADCAST, + data: { + packet, + requestId, + opts: encodeOptions(opts) + } + }); + setTimeout(() => { + this.ackRequests.delete(requestId); + }, opts.flags.timeout); + } + super.broadcastWithAck(packet, opts, clientCountCallback, ack); + } + async addSockets(opts, rooms) { + var _a; + const onlyLocal = (_a = opts.flags) === null || _a === undefined ? undefined : _a.local; + if (!onlyLocal) { + try { + await this.publishAndReturnOffset({ + type: MessageType.SOCKETS_JOIN, + data: { + opts: encodeOptions(opts), + rooms + } + }); + } catch (e) { + debug("[%s] error while publishing message: %s", this.uid, e.message); + } + } + super.addSockets(opts, rooms); + } + async delSockets(opts, rooms) { + var _a; + const onlyLocal = (_a = opts.flags) === null || _a === undefined ? undefined : _a.local; + if (!onlyLocal) { + try { + await this.publishAndReturnOffset({ + type: MessageType.SOCKETS_LEAVE, + data: { + opts: encodeOptions(opts), + rooms + } + }); + } catch (e) { + debug("[%s] error while publishing message: %s", this.uid, e.message); + } + } + super.delSockets(opts, rooms); + } + async disconnectSockets(opts, close) { + var _a; + const onlyLocal = (_a = opts.flags) === null || _a === undefined ? undefined : _a.local; + if (!onlyLocal) { + try { + await this.publishAndReturnOffset({ + type: MessageType.DISCONNECT_SOCKETS, + data: { + opts: encodeOptions(opts), + close + } + }); + } catch (e) { + debug("[%s] error while publishing message: %s", this.uid, e.message); + } + } + super.disconnectSockets(opts, close); + } + async fetchSockets(opts) { + var _a; + const [localSockets, serverCount] = await Promise.all([ + super.fetchSockets(opts), + this.serverCount() + ]); + const expectedResponseCount = serverCount - 1; + if (((_a = opts.flags) === null || _a === undefined ? undefined : _a.local) || expectedResponseCount <= 0) { + return localSockets; + } + const requestId = randomId(); + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + const storedRequest2 = this.requests.get(requestId); + if (storedRequest2) { + reject(new Error(`timeout reached: only ${storedRequest2.current} responses received out of ${storedRequest2.expected}`)); + this.requests.delete(requestId); + } + }, opts.flags.timeout || DEFAULT_TIMEOUT); + const storedRequest = { + type: MessageType.FETCH_SOCKETS, + resolve, + timeout, + current: 0, + expected: expectedResponseCount, + responses: localSockets + }; + this.requests.set(requestId, storedRequest); + this.publish({ + type: MessageType.FETCH_SOCKETS, + data: { + opts: encodeOptions(opts), + requestId + } + }); + }); + } + async serverSideEmit(packet) { + const withAck = typeof packet[packet.length - 1] === "function"; + if (!withAck) { + return this.publish({ + type: MessageType.SERVER_SIDE_EMIT, + data: { + packet + } + }); + } + const ack = packet.pop(); + const expectedResponseCount = await this.serverCount() - 1; + debug('[%s] waiting for %d responses to "serverSideEmit" request', this.uid, expectedResponseCount); + if (expectedResponseCount <= 0) { + return ack(null, []); + } + const requestId = randomId(); + const timeout = setTimeout(() => { + const storedRequest2 = this.requests.get(requestId); + if (storedRequest2) { + ack(new Error(`timeout reached: only ${storedRequest2.current} responses received out of ${storedRequest2.expected}`), storedRequest2.responses); + this.requests.delete(requestId); + } + }, DEFAULT_TIMEOUT); + const storedRequest = { + type: MessageType.SERVER_SIDE_EMIT, + resolve: ack, + timeout, + current: 0, + expected: expectedResponseCount, + responses: [] + }; + this.requests.set(requestId, storedRequest); + this.publish({ + type: MessageType.SERVER_SIDE_EMIT, + data: { + requestId, + packet + } + }); + } + publish(message) { + this.publishAndReturnOffset(message).catch((err) => { + debug("[%s] error while publishing message: %s", this.uid, err); + }); + } + publishAndReturnOffset(message) { + message.uid = this.uid; + message.nsp = this.nsp.name; + return this.doPublish(message); + } + publishResponse(requesterUid, response) { + response.uid = this.uid; + response.nsp = this.nsp.name; + this.doPublishResponse(requesterUid, response).catch((err) => { + debug("[%s] error while publishing response: %s", this.uid, err); + }); + } + } + exports2.ClusterAdapter = ClusterAdapter; + + class ClusterAdapterWithHeartbeat extends ClusterAdapter { + constructor(nsp, opts) { + super(nsp); + this.nodesMap = new Map; + this.customRequests = new Map; + this._opts = Object.assign({ + heartbeatInterval: 5000, + heartbeatTimeout: 1e4 + }, opts); + this.cleanupTimer = setInterval(() => { + const now = Date.now(); + this.nodesMap.forEach((lastSeen, uid) => { + const nodeSeemsDown = now - lastSeen > this._opts.heartbeatTimeout; + if (nodeSeemsDown) { + debug("[%s] node %s seems down", this.uid, uid); + this.removeNode(uid); + } + }); + }, 1000); + } + init() { + this.publish({ + type: MessageType.INITIAL_HEARTBEAT + }); + } + scheduleHeartbeat() { + if (this.heartbeatTimer) { + this.heartbeatTimer.refresh(); + } else { + this.heartbeatTimer = setTimeout(() => { + this.publish({ + type: MessageType.HEARTBEAT + }); + }, this._opts.heartbeatInterval); + } + } + close() { + this.publish({ + type: MessageType.ADAPTER_CLOSE + }); + clearTimeout(this.heartbeatTimer); + if (this.cleanupTimer) { + clearInterval(this.cleanupTimer); + } + } + onMessage(message, offset) { + if (message.uid === this.uid) { + return debug("[%s] ignore message from self", this.uid); + } + if (message.uid && message.uid !== EMITTER_UID) { + this.nodesMap.set(message.uid, Date.now()); + } + debug("[%s] new event of type %d from %s", this.uid, message.type, message.uid); + switch (message.type) { + case MessageType.INITIAL_HEARTBEAT: + this.publish({ + type: MessageType.HEARTBEAT + }); + break; + case MessageType.HEARTBEAT: + break; + case MessageType.ADAPTER_CLOSE: + this.removeNode(message.uid); + break; + default: + super.onMessage(message, offset); + } + } + serverCount() { + return Promise.resolve(1 + this.nodesMap.size); + } + publish(message) { + this.scheduleHeartbeat(); + return super.publish(message); + } + async serverSideEmit(packet) { + const withAck = typeof packet[packet.length - 1] === "function"; + if (!withAck) { + return this.publish({ + type: MessageType.SERVER_SIDE_EMIT, + data: { + packet + } + }); + } + const ack = packet.pop(); + const expectedResponseCount = this.nodesMap.size; + debug('[%s] waiting for %d responses to "serverSideEmit" request', this.uid, expectedResponseCount); + if (expectedResponseCount <= 0) { + return ack(null, []); + } + const requestId = randomId(); + const timeout = setTimeout(() => { + const storedRequest2 = this.customRequests.get(requestId); + if (storedRequest2) { + ack(new Error(`timeout reached: missing ${storedRequest2.missingUids.size} responses`), storedRequest2.responses); + this.customRequests.delete(requestId); + } + }, DEFAULT_TIMEOUT); + const storedRequest = { + type: MessageType.SERVER_SIDE_EMIT, + resolve: ack, + timeout, + missingUids: new Set([...this.nodesMap.keys()]), + responses: [] + }; + this.customRequests.set(requestId, storedRequest); + this.publish({ + type: MessageType.SERVER_SIDE_EMIT, + data: { + requestId, + packet + } + }); + } + async fetchSockets(opts) { + var _a; + const [localSockets, serverCount] = await Promise.all([ + super.fetchSockets({ + rooms: opts.rooms, + except: opts.except, + flags: { + local: true + } + }), + this.serverCount() + ]); + const expectedResponseCount = serverCount - 1; + if (((_a = opts.flags) === null || _a === undefined ? undefined : _a.local) || expectedResponseCount <= 0) { + return localSockets; + } + const requestId = randomId(); + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + const storedRequest2 = this.customRequests.get(requestId); + if (storedRequest2) { + reject(new Error(`timeout reached: missing ${storedRequest2.missingUids.size} responses`)); + this.customRequests.delete(requestId); + } + }, opts.flags.timeout || DEFAULT_TIMEOUT); + const storedRequest = { + type: MessageType.FETCH_SOCKETS, + resolve, + timeout, + missingUids: new Set([...this.nodesMap.keys()]), + responses: localSockets + }; + this.customRequests.set(requestId, storedRequest); + this.publish({ + type: MessageType.FETCH_SOCKETS, + data: { + opts: encodeOptions(opts), + requestId + } + }); + }); + } + onResponse(response) { + const requestId = response.data.requestId; + debug("[%s] received response %s to request %s", this.uid, response.type, requestId); + switch (response.type) { + case MessageType.FETCH_SOCKETS_RESPONSE: { + const request = this.customRequests.get(requestId); + if (!request) { + return; + } + response.data.sockets.forEach((socket) => request.responses.push(socket)); + request.missingUids.delete(response.uid); + if (request.missingUids.size === 0) { + clearTimeout(request.timeout); + request.resolve(request.responses); + this.customRequests.delete(requestId); + } + break; + } + case MessageType.SERVER_SIDE_EMIT_RESPONSE: { + const request = this.customRequests.get(requestId); + if (!request) { + return; + } + request.responses.push(response.data.packet); + request.missingUids.delete(response.uid); + if (request.missingUids.size === 0) { + clearTimeout(request.timeout); + request.resolve(null, request.responses); + this.customRequests.delete(requestId); + } + break; + } + default: + super.onResponse(response); + } + } + removeNode(uid) { + this.customRequests.forEach((request, requestId) => { + request.missingUids.delete(uid); + if (request.missingUids.size === 0) { + clearTimeout(request.timeout); + if (request.type === MessageType.FETCH_SOCKETS) { + request.resolve(request.responses); + } else if (request.type === MessageType.SERVER_SIDE_EMIT) { + request.resolve(null, request.responses); + } + this.customRequests.delete(requestId); + } + }); + this.nodesMap.delete(uid); + } + } + exports2.ClusterAdapterWithHeartbeat = ClusterAdapterWithHeartbeat; +}); + +// node_modules/socket.io-adapter/dist/index.js +var require_dist = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.MessageType = exports2.ClusterAdapterWithHeartbeat = exports2.ClusterAdapter = exports2.SessionAwareAdapter = exports2.Adapter = undefined; + var in_memory_adapter_1 = require_in_memory_adapter(); + Object.defineProperty(exports2, "Adapter", { enumerable: true, get: function() { + return in_memory_adapter_1.Adapter; + } }); + Object.defineProperty(exports2, "SessionAwareAdapter", { enumerable: true, get: function() { + return in_memory_adapter_1.SessionAwareAdapter; + } }); + var cluster_adapter_1 = require_cluster_adapter(); + Object.defineProperty(exports2, "ClusterAdapter", { enumerable: true, get: function() { + return cluster_adapter_1.ClusterAdapter; + } }); + Object.defineProperty(exports2, "ClusterAdapterWithHeartbeat", { enumerable: true, get: function() { + return cluster_adapter_1.ClusterAdapterWithHeartbeat; + } }); + Object.defineProperty(exports2, "MessageType", { enumerable: true, get: function() { + return cluster_adapter_1.MessageType; + } }); +}); + +// node_modules/socket.io/dist/parent-namespace.js +var require_parent_namespace = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ParentNamespace = undefined; + var namespace_1 = require_namespace(); + var socket_io_adapter_1 = require_dist(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("socket.io:parent-namespace"); + + class ParentNamespace extends namespace_1.Namespace { + constructor(server) { + super(server, "/_" + ParentNamespace.count++); + this.children = new Set; + } + _initAdapter() { + this.adapter = new ParentBroadcastAdapter(this); + } + emit(ev, ...args) { + this.children.forEach((nsp) => { + nsp.emit(ev, ...args); + }); + return true; + } + createChild(name) { + debug("creating child namespace %s", name); + const namespace = new namespace_1.Namespace(this.server, name); + this["_fns"].forEach((fn) => namespace.use(fn)); + this.listeners("connect").forEach((listener) => namespace.on("connect", listener)); + this.listeners("connection").forEach((listener) => namespace.on("connection", listener)); + this.children.add(namespace); + if (this.server._opts.cleanupEmptyChildNamespaces) { + const remove = namespace._remove; + namespace._remove = (socket) => { + remove.call(namespace, socket); + if (namespace.sockets.size === 0) { + debug("closing child namespace %s", name); + namespace.adapter.close(); + this.server._nsps.delete(namespace.name); + this.children.delete(namespace); + } + }; + } + this.server._nsps.set(name, namespace); + this.server.sockets.emitReserved("new_namespace", namespace); + return namespace; + } + fetchSockets() { + throw new Error("fetchSockets() is not supported on parent namespaces"); + } + } + exports2.ParentNamespace = ParentNamespace; + ParentNamespace.count = 0; + + class ParentBroadcastAdapter extends socket_io_adapter_1.Adapter { + broadcast(packet, opts) { + this.nsp.children.forEach((nsp) => { + nsp.adapter.broadcast(packet, opts); + }); + } + } +}); + +// node_modules/socket.io/dist/uws.js +var require_uws = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.patchAdapter = patchAdapter; + exports2.restoreAdapter = restoreAdapter; + exports2.serveFile = serveFile; + var socket_io_adapter_1 = require_dist(); + var fs_1 = require("fs"); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("socket.io:adapter-uws"); + var SEPARATOR = "\x1F"; + var { addAll, del, broadcast } = socket_io_adapter_1.Adapter.prototype; + function patchAdapter(app) { + socket_io_adapter_1.Adapter.prototype.addAll = function(id, rooms) { + const isNew = !this.sids.has(id); + addAll.call(this, id, rooms); + const socket = this.nsp.sockets.get(id) || this.nsp._preConnectSockets.get(id); + if (!socket) { + return; + } + if (socket.conn.transport.name === "websocket") { + subscribe(this.nsp.name, socket, isNew, rooms); + return; + } + if (isNew) { + socket.conn.on("upgrade", () => { + const rooms2 = this.sids.get(id); + if (rooms2) { + subscribe(this.nsp.name, socket, isNew, rooms2); + } + }); + } + }; + socket_io_adapter_1.Adapter.prototype.del = function(id, room) { + del.call(this, id, room); + const socket = this.nsp.sockets.get(id) || this.nsp._preConnectSockets.get(id); + if (socket && socket.conn.transport.name === "websocket") { + const sessionId = socket.conn.id; + const websocket = socket.conn.transport.socket; + const topic = `${this.nsp.name}${SEPARATOR}${room}`; + debug("unsubscribe connection %s from topic %s", sessionId, topic); + websocket.unsubscribe(topic); + } + }; + socket_io_adapter_1.Adapter.prototype.broadcast = function(packet, opts) { + const useFastPublish = opts.rooms.size <= 1 && opts.except.size === 0; + if (!useFastPublish) { + broadcast.call(this, packet, opts); + return; + } + const flags = opts.flags || {}; + const basePacketOpts = { + preEncoded: true, + volatile: flags.volatile, + compress: flags.compress + }; + packet.nsp = this.nsp.name; + const encodedPackets = this.encoder.encode(packet); + const topic = opts.rooms.size === 0 ? this.nsp.name : `${this.nsp.name}${SEPARATOR}${opts.rooms.keys().next().value}`; + debug("fast publish to %s", topic); + encodedPackets.forEach((encodedPacket) => { + const isBinary = typeof encodedPacket !== "string"; + app.publish(topic, isBinary ? encodedPacket : "4" + encodedPacket, isBinary); + }); + this.apply(opts, (socket) => { + if (socket.conn.transport.name !== "websocket") { + socket.client.writeToEngine(encodedPackets, basePacketOpts); + } + }); + }; + } + function subscribe(namespaceName, socket, isNew, rooms) { + const sessionId = socket.conn.id; + const websocket = socket.conn.transport.socket; + if (isNew) { + debug("subscribe connection %s to topic %s", sessionId, namespaceName); + websocket.subscribe(namespaceName); + } + rooms.forEach((room) => { + const topic = `${namespaceName}${SEPARATOR}${room}`; + debug("subscribe connection %s to topic %s", sessionId, topic); + websocket.subscribe(topic); + }); + } + function restoreAdapter() { + socket_io_adapter_1.Adapter.prototype.addAll = addAll; + socket_io_adapter_1.Adapter.prototype.del = del; + socket_io_adapter_1.Adapter.prototype.broadcast = broadcast; + } + var toArrayBuffer = (buffer) => { + const { buffer: arrayBuffer, byteOffset, byteLength } = buffer; + return arrayBuffer.slice(byteOffset, byteOffset + byteLength); + }; + function serveFile(res, filepath) { + const { size } = (0, fs_1.statSync)(filepath); + const readStream = (0, fs_1.createReadStream)(filepath); + const destroyReadStream = () => !readStream.destroyed && readStream.destroy(); + const onError = (error) => { + destroyReadStream(); + throw error; + }; + const onDataChunk = (chunk) => { + const arrayBufferChunk = toArrayBuffer(chunk); + res.cork(() => { + const lastOffset = res.getWriteOffset(); + const [ok, done] = res.tryEnd(arrayBufferChunk, size); + if (!done && !ok) { + readStream.pause(); + res.onWritable((offset) => { + const [ok2, done2] = res.tryEnd(arrayBufferChunk.slice(offset - lastOffset), size); + if (!done2 && ok2) { + readStream.resume(); + } + return ok2; + }); + } + }); + }; + res.onAborted(destroyReadStream); + readStream.on("data", onDataChunk).on("error", onError).on("end", destroyReadStream); + } +}); + +// node_modules/socket.io/package.json +var require_package = __commonJS((exports2, module2) => { + module2.exports = { + name: "socket.io", + version: "4.8.1", + description: "node.js realtime framework server", + keywords: [ + "realtime", + "framework", + "websocket", + "tcp", + "events", + "socket", + "io" + ], + files: [ + "dist/", + "client-dist/", + "wrapper.mjs", + "!**/*.tsbuildinfo" + ], + directories: { + doc: "docs/", + example: "example/", + lib: "lib/", + test: "test/" + }, + type: "commonjs", + main: "./dist/index.js", + exports: { + types: "./dist/index.d.ts", + import: "./wrapper.mjs", + require: "./dist/index.js" + }, + types: "./dist/index.d.ts", + license: "MIT", + homepage: "https://github.com/socketio/socket.io/tree/main/packages/socket.io#readme", + repository: { + type: "git", + url: "git+https://github.com/socketio/socket.io.git" + }, + bugs: { + url: "https://github.com/socketio/socket.io/issues" + }, + scripts: { + compile: "rimraf ./dist && tsc", + test: "npm run format:check && npm run compile && npm run test:types && npm run test:unit", + "test:types": "tsd", + "test:unit": "nyc mocha --require ts-node/register --reporter spec --slow 200 --bail --timeout 10000 test/index.ts", + "format:check": 'prettier --check "lib/**/*.ts" "test/**/*.ts"', + "format:fix": 'prettier --write "lib/**/*.ts" "test/**/*.ts"', + prepack: "npm run compile" + }, + dependencies: { + accepts: "~1.3.4", + base64id: "~2.0.0", + cors: "~2.8.5", + debug: "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + contributors: [ + { + name: "Guillermo Rauch", + email: "rauchg@gmail.com" + }, + { + name: "Arnout Kazemier", + email: "info@3rd-eden.com" + }, + { + name: "Vladimir Dronnikov", + email: "dronnikov@gmail.com" + }, + { + name: "Einar Otto Stangvik", + email: "einaros@gmail.com" + } + ], + engines: { + node: ">=10.2.0" + }, + tsd: { + directory: "test" + } + }; +}); + +// node_modules/socket.io/dist/index.js +var require_dist2 = __commonJS((exports2, module2) => { + var __dirname = "C:\\Users\\Tommy\\Documents\\FiveM-SRV\\txData\\CFXDefaultFiveM_8F0B09.base\\resources\\[scripts]\\radio\\node_modules\\socket.io\\dist"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === undefined) + k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o, k2, desc); + } : function(o, m, k, k2) { + if (k2 === undefined) + k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } : function(o, v) { + o["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) + __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Namespace = exports2.Socket = exports2.Server = undefined; + var http = require("http"); + var fs_1 = require("fs"); + var zlib_1 = require("zlib"); + var accepts = require_accepts(); + var stream_1 = require("stream"); + var path = require("path"); + var engine_io_1 = require_engine_io(); + var client_1 = require_client(); + var events_1 = require("events"); + var namespace_1 = require_namespace(); + Object.defineProperty(exports2, "Namespace", { enumerable: true, get: function() { + return namespace_1.Namespace; + } }); + var parent_namespace_1 = require_parent_namespace(); + var socket_io_adapter_1 = require_dist(); + var parser = __importStar(require_cjs3()); + var debug_1 = __importDefault(require_src()); + var socket_1 = require_socket2(); + Object.defineProperty(exports2, "Socket", { enumerable: true, get: function() { + return socket_1.Socket; + } }); + var typed_events_1 = require_typed_events(); + var uws_1 = require_uws(); + var cors_1 = __importDefault(require_lib()); + var debug = (0, debug_1.default)("socket.io:server"); + var clientVersion = require_package().version; + var dotMapRegex = /\.map/; + + class Server extends typed_events_1.StrictEventEmitter { + constructor(srv, opts = {}) { + super(); + this._nsps = new Map; + this.parentNsps = new Map; + this.parentNamespacesFromRegExp = new Map; + if (typeof srv === "object" && srv instanceof Object && !srv.listen) { + opts = srv; + srv = undefined; + } + this.path(opts.path || "/socket.io"); + this.connectTimeout(opts.connectTimeout || 45000); + this.serveClient(opts.serveClient !== false); + this._parser = opts.parser || parser; + this.encoder = new this._parser.Encoder; + this.opts = opts; + if (opts.connectionStateRecovery) { + opts.connectionStateRecovery = Object.assign({ + maxDisconnectionDuration: 2 * 60 * 1000, + skipMiddlewares: true + }, opts.connectionStateRecovery); + this.adapter(opts.adapter || socket_io_adapter_1.SessionAwareAdapter); + } else { + this.adapter(opts.adapter || socket_io_adapter_1.Adapter); + } + opts.cleanupEmptyChildNamespaces = !!opts.cleanupEmptyChildNamespaces; + this.sockets = this.of("/"); + if (srv || typeof srv == "number") + this.attach(srv); + if (this.opts.cors) { + this._corsMiddleware = (0, cors_1.default)(this.opts.cors); + } + } + get _opts() { + return this.opts; + } + serveClient(v) { + if (!arguments.length) + return this._serveClient; + this._serveClient = v; + return this; + } + _checkNamespace(name, auth, fn) { + if (this.parentNsps.size === 0) + return fn(false); + const keysIterator = this.parentNsps.keys(); + const run = () => { + const nextFn = keysIterator.next(); + if (nextFn.done) { + return fn(false); + } + nextFn.value(name, auth, (err, allow) => { + if (err || !allow) { + return run(); + } + if (this._nsps.has(name)) { + debug("dynamic namespace %s already exists", name); + return fn(this._nsps.get(name)); + } + const namespace = this.parentNsps.get(nextFn.value).createChild(name); + debug("dynamic namespace %s was created", name); + fn(namespace); + }); + }; + run(); + } + path(v) { + if (!arguments.length) + return this._path; + this._path = v.replace(/\/$/, ""); + const escapedPath = this._path.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); + this.clientPathRegex = new RegExp("^" + escapedPath + "/socket\\.io(\\.msgpack|\\.esm)?(\\.min)?\\.js(\\.map)?(?:\\?|$)"); + return this; + } + connectTimeout(v) { + if (v === undefined) + return this._connectTimeout; + this._connectTimeout = v; + return this; + } + adapter(v) { + if (!arguments.length) + return this._adapter; + this._adapter = v; + for (const nsp of this._nsps.values()) { + nsp._initAdapter(); + } + return this; + } + listen(srv, opts = {}) { + return this.attach(srv, opts); + } + attach(srv, opts = {}) { + if (typeof srv == "function") { + const msg = "You are trying to attach socket.io to an express " + "request handler function. Please pass a http.Server instance."; + throw new Error(msg); + } + if (Number(srv) == srv) { + srv = Number(srv); + } + if (typeof srv == "number") { + debug("creating http server and binding to %d", srv); + const port = srv; + srv = http.createServer((req, res) => { + res.writeHead(404); + res.end(); + }); + srv.listen(port); + } + Object.assign(opts, this.opts); + opts.path = opts.path || this._path; + this.initEngine(srv, opts); + return this; + } + attachApp(app, opts = {}) { + Object.assign(opts, this.opts); + opts.path = opts.path || this._path; + debug("creating uWebSockets.js-based engine with opts %j", opts); + const engine = new engine_io_1.uServer(opts); + engine.attach(app, opts); + this.bind(engine); + if (this._serveClient) { + app.get(`${this._path}/*`, (res, req) => { + if (!this.clientPathRegex.test(req.getUrl())) { + req.setYield(true); + return; + } + const filename = req.getUrl().replace(this._path, "").replace(/\?.*$/, "").replace(/^\//, ""); + const isMap = dotMapRegex.test(filename); + const type = isMap ? "map" : "source"; + const expectedEtag = '"' + clientVersion + '"'; + const weakEtag = "W/" + expectedEtag; + const etag = req.getHeader("if-none-match"); + if (etag) { + if (expectedEtag === etag || weakEtag === etag) { + debug("serve client %s 304", type); + res.writeStatus("304 Not Modified"); + res.end(); + return; + } + } + debug("serve client %s", type); + res.writeHeader("cache-control", "public, max-age=0"); + res.writeHeader("content-type", "application/" + (isMap ? "json" : "javascript") + "; charset=utf-8"); + res.writeHeader("etag", expectedEtag); + const filepath = path.join(__dirname, "../client-dist/", filename); + (0, uws_1.serveFile)(res, filepath); + }); + } + (0, uws_1.patchAdapter)(app); + } + initEngine(srv, opts) { + debug("creating engine.io instance with opts %j", opts); + this.eio = (0, engine_io_1.attach)(srv, opts); + if (this._serveClient) + this.attachServe(srv); + this.httpServer = srv; + this.bind(this.eio); + } + attachServe(srv) { + debug("attaching client serving req handler"); + const evs = srv.listeners("request").slice(0); + srv.removeAllListeners("request"); + srv.on("request", (req, res) => { + if (this.clientPathRegex.test(req.url)) { + if (this._corsMiddleware) { + this._corsMiddleware(req, res, () => { + this.serve(req, res); + }); + } else { + this.serve(req, res); + } + } else { + for (let i = 0;i < evs.length; i++) { + evs[i].call(srv, req, res); + } + } + }); + } + serve(req, res) { + const filename = req.url.replace(this._path, "").replace(/\?.*$/, ""); + const isMap = dotMapRegex.test(filename); + const type = isMap ? "map" : "source"; + const expectedEtag = '"' + clientVersion + '"'; + const weakEtag = "W/" + expectedEtag; + const etag = req.headers["if-none-match"]; + if (etag) { + if (expectedEtag === etag || weakEtag === etag) { + debug("serve client %s 304", type); + res.writeHead(304); + res.end(); + return; + } + } + debug("serve client %s", type); + res.setHeader("Cache-Control", "public, max-age=0"); + res.setHeader("Content-Type", "application/" + (isMap ? "json" : "javascript") + "; charset=utf-8"); + res.setHeader("ETag", expectedEtag); + Server.sendFile(filename, req, res); + } + static sendFile(filename, req, res) { + const readStream = (0, fs_1.createReadStream)(path.join(__dirname, "../client-dist/", filename)); + const encoding = accepts(req).encodings(["br", "gzip", "deflate"]); + const onError = (err) => { + if (err) { + res.end(); + } + }; + switch (encoding) { + case "br": + res.writeHead(200, { "content-encoding": "br" }); + (0, stream_1.pipeline)(readStream, (0, zlib_1.createBrotliCompress)(), res, onError); + break; + case "gzip": + res.writeHead(200, { "content-encoding": "gzip" }); + (0, stream_1.pipeline)(readStream, (0, zlib_1.createGzip)(), res, onError); + break; + case "deflate": + res.writeHead(200, { "content-encoding": "deflate" }); + (0, stream_1.pipeline)(readStream, (0, zlib_1.createDeflate)(), res, onError); + break; + default: + res.writeHead(200); + (0, stream_1.pipeline)(readStream, res, onError); + } + } + bind(engine) { + this.engine = engine; + this.engine.on("connection", this.onconnection.bind(this)); + return this; + } + onconnection(conn) { + debug("incoming connection with id %s", conn.id); + const client = new client_1.Client(this, conn); + if (conn.protocol === 3) { + client.connect("/"); + } + return this; + } + of(name, fn) { + if (typeof name === "function" || name instanceof RegExp) { + const parentNsp = new parent_namespace_1.ParentNamespace(this); + debug("initializing parent namespace %s", parentNsp.name); + if (typeof name === "function") { + this.parentNsps.set(name, parentNsp); + } else { + this.parentNsps.set((nsp2, conn, next) => next(null, name.test(nsp2)), parentNsp); + this.parentNamespacesFromRegExp.set(name, parentNsp); + } + if (fn) { + parentNsp.on("connect", fn); + } + return parentNsp; + } + if (String(name)[0] !== "/") + name = "/" + name; + let nsp = this._nsps.get(name); + if (!nsp) { + for (const [regex, parentNamespace] of this.parentNamespacesFromRegExp) { + if (regex.test(name)) { + debug("attaching namespace %s to parent namespace %s", name, regex); + return parentNamespace.createChild(name); + } + } + debug("initializing namespace %s", name); + nsp = new namespace_1.Namespace(this, name); + this._nsps.set(name, nsp); + if (name !== "/") { + this.sockets.emitReserved("new_namespace", nsp); + } + } + if (fn) + nsp.on("connect", fn); + return nsp; + } + async close(fn) { + await Promise.allSettled([...this._nsps.values()].map(async (nsp) => { + nsp.sockets.forEach((socket) => { + socket._onclose("server shutting down"); + }); + await nsp.adapter.close(); + })); + this.engine.close(); + (0, uws_1.restoreAdapter)(); + if (this.httpServer) { + this.httpServer.close(fn); + } else { + fn && fn(); + } + } + use(fn) { + this.sockets.use(fn); + return this; + } + to(room) { + return this.sockets.to(room); + } + in(room) { + return this.sockets.in(room); + } + except(room) { + return this.sockets.except(room); + } + send(...args) { + this.sockets.emit("message", ...args); + return this; + } + write(...args) { + this.sockets.emit("message", ...args); + return this; + } + serverSideEmit(ev, ...args) { + return this.sockets.serverSideEmit(ev, ...args); + } + serverSideEmitWithAck(ev, ...args) { + return this.sockets.serverSideEmitWithAck(ev, ...args); + } + allSockets() { + return this.sockets.allSockets(); + } + compress(compress) { + return this.sockets.compress(compress); + } + get volatile() { + return this.sockets.volatile; + } + get local() { + return this.sockets.local; + } + timeout(timeout) { + return this.sockets.timeout(timeout); + } + fetchSockets() { + return this.sockets.fetchSockets(); + } + socketsJoin(room) { + return this.sockets.socketsJoin(room); + } + socketsLeave(room) { + return this.sockets.socketsLeave(room); + } + disconnectSockets(close = false) { + return this.sockets.disconnectSockets(close); + } + } + exports2.Server = Server; + var emitterMethods = Object.keys(events_1.EventEmitter.prototype).filter(function(key) { + return typeof events_1.EventEmitter.prototype[key] === "function"; + }); + emitterMethods.forEach(function(fn) { + Server.prototype[fn] = function() { + return this.sockets[fn].apply(this.sockets, arguments); + }; + }); + module2.exports = (srv, opts) => new Server(srv, opts); + module2.exports.Server = Server; + module2.exports.Namespace = namespace_1.Namespace; + module2.exports.Socket = socket_1.Socket; +}); + +// node_modules/consola/dist/core.cjs +var require_core = __commonJS((exports2) => { + var LogLevels = { + silent: Number.NEGATIVE_INFINITY, + fatal: 0, + error: 0, + warn: 1, + log: 2, + info: 3, + success: 3, + fail: 3, + ready: 3, + start: 3, + box: 3, + debug: 4, + trace: 5, + verbose: Number.POSITIVE_INFINITY + }; + var LogTypes = { + silent: { + level: -1 + }, + fatal: { + level: LogLevels.fatal + }, + error: { + level: LogLevels.error + }, + warn: { + level: LogLevels.warn + }, + log: { + level: LogLevels.log + }, + info: { + level: LogLevels.info + }, + success: { + level: LogLevels.success + }, + fail: { + level: LogLevels.fail + }, + ready: { + level: LogLevels.info + }, + start: { + level: LogLevels.info + }, + box: { + level: LogLevels.info + }, + debug: { + level: LogLevels.debug + }, + trace: { + level: LogLevels.trace + }, + verbose: { + level: LogLevels.verbose + } + }; + function isPlainObject$1(value) { + if (value === null || typeof value !== "object") { + return false; + } + const prototype = Object.getPrototypeOf(value); + if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) { + return false; + } + if (Symbol.iterator in value) { + return false; + } + if (Symbol.toStringTag in value) { + return Object.prototype.toString.call(value) === "[object Module]"; + } + return true; + } + function _defu(baseObject, defaults, namespace = ".", merger) { + if (!isPlainObject$1(defaults)) { + return _defu(baseObject, {}, namespace, merger); + } + const object = Object.assign({}, defaults); + for (const key in baseObject) { + if (key === "__proto__" || key === "constructor") { + continue; + } + const value = baseObject[key]; + if (value === null || value === undefined) { + continue; + } + if (merger && merger(object, key, value, namespace)) { + continue; + } + if (Array.isArray(value) && Array.isArray(object[key])) { + object[key] = [...value, ...object[key]]; + } else if (isPlainObject$1(value) && isPlainObject$1(object[key])) { + object[key] = _defu(value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger); + } else { + object[key] = value; + } + } + return object; + } + function createDefu(merger) { + return (...arguments_) => arguments_.reduce((p, c) => _defu(p, c, "", merger), {}); + } + var defu = createDefu(); + function isPlainObject(obj) { + return Object.prototype.toString.call(obj) === "[object Object]"; + } + function isLogObj(arg) { + if (!isPlainObject(arg)) { + return false; + } + if (!arg.message && !arg.args) { + return false; + } + if (arg.stack) { + return false; + } + return true; + } + var paused = false; + var queue = []; + + class Consola { + options; + _lastLog; + _mockFn; + constructor(options = {}) { + const types = options.types || LogTypes; + this.options = defu({ + ...options, + defaults: { ...options.defaults }, + level: _normalizeLogLevel(options.level, types), + reporters: [...options.reporters || []] + }, { + types: LogTypes, + throttle: 1000, + throttleMin: 5, + formatOptions: { + date: true, + colors: false, + compact: true + } + }); + for (const type in types) { + const defaults = { + type, + ...this.options.defaults, + ...types[type] + }; + this[type] = this._wrapLogFn(defaults); + this[type].raw = this._wrapLogFn(defaults, true); + } + if (this.options.mockFn) { + this.mockTypes(); + } + this._lastLog = {}; + } + get level() { + return this.options.level; + } + set level(level) { + this.options.level = _normalizeLogLevel(level, this.options.types, this.options.level); + } + prompt(message, opts) { + if (!this.options.prompt) { + throw new Error("prompt is not supported!"); + } + return this.options.prompt(message, opts); + } + create(options) { + const instance = new Consola({ + ...this.options, + ...options + }); + if (this._mockFn) { + instance.mockTypes(this._mockFn); + } + return instance; + } + withDefaults(defaults) { + return this.create({ + ...this.options, + defaults: { + ...this.options.defaults, + ...defaults + } + }); + } + withTag(tag) { + return this.withDefaults({ + tag: this.options.defaults.tag ? this.options.defaults.tag + ":" + tag : tag + }); + } + addReporter(reporter) { + this.options.reporters.push(reporter); + return this; + } + removeReporter(reporter) { + if (reporter) { + const i = this.options.reporters.indexOf(reporter); + if (i !== -1) { + return this.options.reporters.splice(i, 1); + } + } else { + this.options.reporters.splice(0); + } + return this; + } + setReporters(reporters) { + this.options.reporters = Array.isArray(reporters) ? reporters : [reporters]; + return this; + } + wrapAll() { + this.wrapConsole(); + this.wrapStd(); + } + restoreAll() { + this.restoreConsole(); + this.restoreStd(); + } + wrapConsole() { + for (const type in this.options.types) { + if (!console["__" + type]) { + console["__" + type] = console[type]; + } + console[type] = this[type].raw; + } + } + restoreConsole() { + for (const type in this.options.types) { + if (console["__" + type]) { + console[type] = console["__" + type]; + delete console["__" + type]; + } + } + } + wrapStd() { + this._wrapStream(this.options.stdout, "log"); + this._wrapStream(this.options.stderr, "log"); + } + _wrapStream(stream, type) { + if (!stream) { + return; + } + if (!stream.__write) { + stream.__write = stream.write; + } + stream.write = (data) => { + this[type].raw(String(data).trim()); + }; + } + restoreStd() { + this._restoreStream(this.options.stdout); + this._restoreStream(this.options.stderr); + } + _restoreStream(stream) { + if (!stream) { + return; + } + if (stream.__write) { + stream.write = stream.__write; + delete stream.__write; + } + } + pauseLogs() { + paused = true; + } + resumeLogs() { + paused = false; + const _queue = queue.splice(0); + for (const item of _queue) { + item[0]._logFn(item[1], item[2]); + } + } + mockTypes(mockFn) { + const _mockFn = mockFn || this.options.mockFn; + this._mockFn = _mockFn; + if (typeof _mockFn !== "function") { + return; + } + for (const type in this.options.types) { + this[type] = _mockFn(type, this.options.types[type]) || this[type]; + this[type].raw = this[type]; + } + } + _wrapLogFn(defaults, isRaw) { + return (...args) => { + if (paused) { + queue.push([this, defaults, args, isRaw]); + return; + } + return this._logFn(defaults, args, isRaw); + }; + } + _logFn(defaults, args, isRaw) { + if ((defaults.level || 0) > this.level) { + return false; + } + const logObj = { + date: /* @__PURE__ */ new Date, + args: [], + ...defaults, + level: _normalizeLogLevel(defaults.level, this.options.types) + }; + if (!isRaw && args.length === 1 && isLogObj(args[0])) { + Object.assign(logObj, args[0]); + } else { + logObj.args = [...args]; + } + if (logObj.message) { + logObj.args.unshift(logObj.message); + delete logObj.message; + } + if (logObj.additional) { + if (!Array.isArray(logObj.additional)) { + logObj.additional = logObj.additional.split(` +`); + } + logObj.args.push(` +` + logObj.additional.join(` +`)); + delete logObj.additional; + } + logObj.type = typeof logObj.type === "string" ? logObj.type.toLowerCase() : "log"; + logObj.tag = typeof logObj.tag === "string" ? logObj.tag : ""; + const resolveLog = (newLog = false) => { + const repeated = (this._lastLog.count || 0) - this.options.throttleMin; + if (this._lastLog.object && repeated > 0) { + const args2 = [...this._lastLog.object.args]; + if (repeated > 1) { + args2.push(`(repeated ${repeated} times)`); + } + this._log({ ...this._lastLog.object, args: args2 }); + this._lastLog.count = 1; + } + if (newLog) { + this._lastLog.object = logObj; + this._log(logObj); + } + }; + clearTimeout(this._lastLog.timeout); + const diffTime = this._lastLog.time && logObj.date ? logObj.date.getTime() - this._lastLog.time.getTime() : 0; + this._lastLog.time = logObj.date; + if (diffTime < this.options.throttle) { + try { + const serializedLog = JSON.stringify([ + logObj.type, + logObj.tag, + logObj.args + ]); + const isSameLog = this._lastLog.serialized === serializedLog; + this._lastLog.serialized = serializedLog; + if (isSameLog) { + this._lastLog.count = (this._lastLog.count || 0) + 1; + if (this._lastLog.count > this.options.throttleMin) { + this._lastLog.timeout = setTimeout(resolveLog, this.options.throttle); + return; + } + } + } catch {} + } + resolveLog(true); + } + _log(logObj) { + for (const reporter of this.options.reporters) { + reporter.log(logObj, { + options: this.options + }); + } + } + } + function _normalizeLogLevel(input, types = {}, defaultLevel = 3) { + if (input === undefined) { + return defaultLevel; + } + if (typeof input === "number") { + return input; + } + if (types[input] && types[input].level !== undefined) { + return types[input].level; + } + return defaultLevel; + } + Consola.prototype.add = Consola.prototype.addReporter; + Consola.prototype.remove = Consola.prototype.removeReporter; + Consola.prototype.clear = Consola.prototype.removeReporter; + Consola.prototype.withScope = Consola.prototype.withTag; + Consola.prototype.mock = Consola.prototype.mockTypes; + Consola.prototype.pause = Consola.prototype.pauseLogs; + Consola.prototype.resume = Consola.prototype.resumeLogs; + function createConsola(options = {}) { + return new Consola(options); + } + exports2.Consola = Consola; + exports2.LogLevels = LogLevels; + exports2.LogTypes = LogTypes; + exports2.createConsola = createConsola; +}); + +// node_modules/consola/dist/shared/consola.DCGIlDNP.cjs +var require_consola_DCGIlDNP = __commonJS((exports2) => { + var node_util = require("node:util"); + var node_path = require("node:path"); + function parseStack(stack, message) { + const cwd = process.cwd() + node_path.sep; + const lines = stack.split(` +`).splice(message.split(` +`).length).map((l) => l.trim().replace("file://", "").replace(cwd, "")); + return lines; + } + function writeStream(data, stream) { + const write = stream.__write || stream.write; + return write.call(stream, data); + } + var bracket = (x) => x ? `[${x}]` : ""; + + class BasicReporter { + formatStack(stack, message, opts) { + const indent = " ".repeat((opts?.errorLevel || 0) + 1); + return indent + parseStack(stack, message).join(` +${indent}`); + } + formatError(err, opts) { + const message = err.message ?? node_util.formatWithOptions(opts, err); + const stack = err.stack ? this.formatStack(err.stack, message, opts) : ""; + const level = opts?.errorLevel || 0; + const causedPrefix = level > 0 ? `${" ".repeat(level)}[cause]: ` : ""; + const causedError = err.cause ? ` + +` + this.formatError(err.cause, { ...opts, errorLevel: level + 1 }) : ""; + return causedPrefix + message + ` +` + stack + causedError; + } + formatArgs(args, opts) { + const _args = args.map((arg) => { + if (arg && typeof arg.stack === "string") { + return this.formatError(arg, opts); + } + return arg; + }); + return node_util.formatWithOptions(opts, ..._args); + } + formatDate(date, opts) { + return opts.date ? date.toLocaleTimeString() : ""; + } + filterAndJoin(arr) { + return arr.filter(Boolean).join(" "); + } + formatLogObj(logObj, opts) { + const message = this.formatArgs(logObj.args, opts); + if (logObj.type === "box") { + return ` +` + [ + bracket(logObj.tag), + logObj.title && logObj.title, + ...message.split(` +`) + ].filter(Boolean).map((l) => " > " + l).join(` +`) + ` +`; + } + return this.filterAndJoin([ + bracket(logObj.type), + bracket(logObj.tag), + message + ]); + } + log(logObj, ctx) { + const line = this.formatLogObj(logObj, { + columns: ctx.options.stdout.columns || 0, + ...ctx.options.formatOptions + }); + return writeStream(line + ` +`, logObj.level < 2 ? ctx.options.stderr || process.stderr : ctx.options.stdout || process.stdout); + } + } + exports2.BasicReporter = BasicReporter; + exports2.parseStack = parseStack; +}); + +// node_modules/consola/dist/shared/consola.DwRq1yyg.cjs +var require_consola_DwRq1yyg = __commonJS((exports2) => { + var tty = require("node:tty"); + function _interopNamespaceCompat(e) { + if (e && typeof e === "object" && "default" in e) + return e; + const n = Object.create(null); + if (e) { + for (const k in e) { + n[k] = e[k]; + } + } + n.default = e; + return n; + } + var tty__namespace = /* @__PURE__ */ _interopNamespaceCompat(tty); + var { + env = {}, + argv = [], + platform = "" + } = typeof process === "undefined" ? {} : process; + var isDisabled = "NO_COLOR" in env || argv.includes("--no-color"); + var isForced = "FORCE_COLOR" in env || argv.includes("--color"); + var isWindows = platform === "win32"; + var isDumbTerminal = env.TERM === "dumb"; + var isCompatibleTerminal = tty__namespace && tty__namespace.isatty && tty__namespace.isatty(1) && env.TERM && !isDumbTerminal; + var isCI = "CI" in env && (("GITHUB_ACTIONS" in env) || ("GITLAB_CI" in env) || ("CIRCLECI" in env)); + var isColorSupported = !isDisabled && (isForced || isWindows && !isDumbTerminal || isCompatibleTerminal || isCI); + function replaceClose(index, string, close, replace, head = string.slice(0, Math.max(0, index)) + replace, tail = string.slice(Math.max(0, index + close.length)), next = tail.indexOf(close)) { + return head + (next < 0 ? tail : replaceClose(next, tail, close, replace)); + } + function clearBleed(index, string, open, close, replace) { + return index < 0 ? open + string + close : open + replaceClose(index, string, close, replace) + close; + } + function filterEmpty(open, close, replace = open, at = open.length + 1) { + return (string) => string || !(string === "" || string === undefined) ? clearBleed(("" + string).indexOf(close, at), string, open, close, replace) : ""; + } + function init(open, close, replace) { + return filterEmpty(`\x1B[${open}m`, `\x1B[${close}m`, replace); + } + var colorDefs = { + reset: init(0, 0), + bold: init(1, 22, "\x1B[22m\x1B[1m"), + dim: init(2, 22, "\x1B[22m\x1B[2m"), + italic: init(3, 23), + underline: init(4, 24), + inverse: init(7, 27), + hidden: init(8, 28), + strikethrough: init(9, 29), + black: init(30, 39), + red: init(31, 39), + green: init(32, 39), + yellow: init(33, 39), + blue: init(34, 39), + magenta: init(35, 39), + cyan: init(36, 39), + white: init(37, 39), + gray: init(90, 39), + bgBlack: init(40, 49), + bgRed: init(41, 49), + bgGreen: init(42, 49), + bgYellow: init(43, 49), + bgBlue: init(44, 49), + bgMagenta: init(45, 49), + bgCyan: init(46, 49), + bgWhite: init(47, 49), + blackBright: init(90, 39), + redBright: init(91, 39), + greenBright: init(92, 39), + yellowBright: init(93, 39), + blueBright: init(94, 39), + magentaBright: init(95, 39), + cyanBright: init(96, 39), + whiteBright: init(97, 39), + bgBlackBright: init(100, 49), + bgRedBright: init(101, 49), + bgGreenBright: init(102, 49), + bgYellowBright: init(103, 49), + bgBlueBright: init(104, 49), + bgMagentaBright: init(105, 49), + bgCyanBright: init(106, 49), + bgWhiteBright: init(107, 49) + }; + function createColors(useColor = isColorSupported) { + return useColor ? colorDefs : Object.fromEntries(Object.keys(colorDefs).map((key) => [key, String])); + } + var colors = createColors(); + function getColor(color, fallback = "reset") { + return colors[color] || colors[fallback]; + } + function colorize(color, text) { + return getColor(color)(text); + } + var ansiRegex = [ + String.raw`[\u001B\u009B][[\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\d\/#&.:=?%@~_]+)*|[a-zA-Z\d]+(?:;[-a-zA-Z\d\/#&.:=?%@~_]*)*)?\u0007)`, + String.raw`(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))` + ].join("|"); + function stripAnsi(text) { + return text.replace(new RegExp(ansiRegex, "g"), ""); + } + function centerAlign(str, len, space = " ") { + const free = len - str.length; + if (free <= 0) { + return str; + } + const freeLeft = Math.floor(free / 2); + let _str = ""; + for (let i = 0;i < len; i++) { + _str += i < freeLeft || i >= freeLeft + str.length ? space : str[i - freeLeft]; + } + return _str; + } + function rightAlign(str, len, space = " ") { + const free = len - str.length; + if (free <= 0) { + return str; + } + let _str = ""; + for (let i = 0;i < len; i++) { + _str += i < free ? space : str[i - free]; + } + return _str; + } + function leftAlign(str, len, space = " ") { + let _str = ""; + for (let i = 0;i < len; i++) { + _str += i < str.length ? str[i] : space; + } + return _str; + } + function align(alignment, str, len, space = " ") { + switch (alignment) { + case "left": { + return leftAlign(str, len, space); + } + case "right": { + return rightAlign(str, len, space); + } + case "center": { + return centerAlign(str, len, space); + } + default: { + return str; + } + } + } + var boxStylePresets = { + solid: { + tl: "┌", + tr: "┐", + bl: "└", + br: "┘", + h: "─", + v: "│" + }, + double: { + tl: "╔", + tr: "╗", + bl: "╚", + br: "╝", + h: "═", + v: "║" + }, + doubleSingle: { + tl: "╓", + tr: "╖", + bl: "╙", + br: "╜", + h: "─", + v: "║" + }, + doubleSingleRounded: { + tl: "╭", + tr: "╮", + bl: "╰", + br: "╯", + h: "─", + v: "║" + }, + singleThick: { + tl: "┏", + tr: "┓", + bl: "┗", + br: "┛", + h: "━", + v: "┃" + }, + singleDouble: { + tl: "╒", + tr: "╕", + bl: "╘", + br: "╛", + h: "═", + v: "│" + }, + singleDoubleRounded: { + tl: "╭", + tr: "╮", + bl: "╰", + br: "╯", + h: "═", + v: "│" + }, + rounded: { + tl: "╭", + tr: "╮", + bl: "╰", + br: "╯", + h: "─", + v: "│" + } + }; + var defaultStyle = { + borderColor: "white", + borderStyle: "rounded", + valign: "center", + padding: 2, + marginLeft: 1, + marginTop: 1, + marginBottom: 1 + }; + function box(text, _opts = {}) { + const opts = { + ..._opts, + style: { + ...defaultStyle, + ..._opts.style + } + }; + const textLines = text.split(` +`); + const boxLines = []; + const _color = getColor(opts.style.borderColor); + const borderStyle = { + ...typeof opts.style.borderStyle === "string" ? boxStylePresets[opts.style.borderStyle] || boxStylePresets.solid : opts.style.borderStyle + }; + if (_color) { + for (const key in borderStyle) { + borderStyle[key] = _color(borderStyle[key]); + } + } + const paddingOffset = opts.style.padding % 2 === 0 ? opts.style.padding : opts.style.padding + 1; + const height = textLines.length + paddingOffset; + const width = Math.max(...textLines.map((line) => stripAnsi(line).length), opts.title ? stripAnsi(opts.title).length : 0) + paddingOffset; + const widthOffset = width + paddingOffset; + const leftSpace = opts.style.marginLeft > 0 ? " ".repeat(opts.style.marginLeft) : ""; + if (opts.style.marginTop > 0) { + boxLines.push("".repeat(opts.style.marginTop)); + } + if (opts.title) { + const title = _color ? _color(opts.title) : opts.title; + const left = borderStyle.h.repeat(Math.floor((width - stripAnsi(opts.title).length) / 2)); + const right = borderStyle.h.repeat(width - stripAnsi(opts.title).length - stripAnsi(left).length + paddingOffset); + boxLines.push(`${leftSpace}${borderStyle.tl}${left}${title}${right}${borderStyle.tr}`); + } else { + boxLines.push(`${leftSpace}${borderStyle.tl}${borderStyle.h.repeat(widthOffset)}${borderStyle.tr}`); + } + const valignOffset = opts.style.valign === "center" ? Math.floor((height - textLines.length) / 2) : opts.style.valign === "top" ? height - textLines.length - paddingOffset : height - textLines.length; + for (let i = 0;i < height; i++) { + if (i < valignOffset || i >= valignOffset + textLines.length) { + boxLines.push(`${leftSpace}${borderStyle.v}${" ".repeat(widthOffset)}${borderStyle.v}`); + } else { + const line = textLines[i - valignOffset]; + const left = " ".repeat(paddingOffset); + const right = " ".repeat(width - stripAnsi(line).length); + boxLines.push(`${leftSpace}${borderStyle.v}${left}${line}${right}${borderStyle.v}`); + } + } + boxLines.push(`${leftSpace}${borderStyle.bl}${borderStyle.h.repeat(widthOffset)}${borderStyle.br}`); + if (opts.style.marginBottom > 0) { + boxLines.push("".repeat(opts.style.marginBottom)); + } + return boxLines.join(` +`); + } + exports2.align = align; + exports2.box = box; + exports2.centerAlign = centerAlign; + exports2.colorize = colorize; + exports2.colors = colors; + exports2.getColor = getColor; + exports2.leftAlign = leftAlign; + exports2.rightAlign = rightAlign; + exports2.stripAnsi = stripAnsi; +}); + +// node_modules/consola/dist/chunks/prompt.cjs +var require_prompt = __commonJS((exports2) => { + require("node:util"); + var g = require("node:process"); + var f = require("node:readline"); + var tty = require("node:tty"); + function _interopDefaultCompat(e2) { + return e2 && typeof e2 === "object" && "default" in e2 ? e2.default : e2; + } + var g__default = /* @__PURE__ */ _interopDefaultCompat(g); + var f__default = /* @__PURE__ */ _interopDefaultCompat(f); + function getDefaultExportFromCjs(x2) { + return x2 && x2.__esModule && Object.prototype.hasOwnProperty.call(x2, "default") ? x2["default"] : x2; + } + var src; + var hasRequiredSrc; + function requireSrc() { + if (hasRequiredSrc) + return src; + hasRequiredSrc = 1; + const ESC = "\x1B"; + const CSI = `${ESC}[`; + const beep = "\x07"; + const cursor = { + to(x2, y2) { + if (!y2) + return `${CSI}${x2 + 1}G`; + return `${CSI}${y2 + 1};${x2 + 1}H`; + }, + move(x2, y2) { + let ret = ""; + if (x2 < 0) + ret += `${CSI}${-x2}D`; + else if (x2 > 0) + ret += `${CSI}${x2}C`; + if (y2 < 0) + ret += `${CSI}${-y2}A`; + else if (y2 > 0) + ret += `${CSI}${y2}B`; + return ret; + }, + up: (count = 1) => `${CSI}${count}A`, + down: (count = 1) => `${CSI}${count}B`, + forward: (count = 1) => `${CSI}${count}C`, + backward: (count = 1) => `${CSI}${count}D`, + nextLine: (count = 1) => `${CSI}E`.repeat(count), + prevLine: (count = 1) => `${CSI}F`.repeat(count), + left: `${CSI}G`, + hide: `${CSI}?25l`, + show: `${CSI}?25h`, + save: `${ESC}7`, + restore: `${ESC}8` + }; + const scroll = { + up: (count = 1) => `${CSI}S`.repeat(count), + down: (count = 1) => `${CSI}T`.repeat(count) + }; + const erase = { + screen: `${CSI}2J`, + up: (count = 1) => `${CSI}1J`.repeat(count), + down: (count = 1) => `${CSI}J`.repeat(count), + line: `${CSI}2K`, + lineEnd: `${CSI}K`, + lineStart: `${CSI}1K`, + lines(count) { + let clear = ""; + for (let i = 0;i < count; i++) + clear += this.line + (i < count - 1 ? cursor.up() : ""); + if (count) + clear += cursor.left; + return clear; + } + }; + src = { cursor, scroll, erase, beep }; + return src; + } + var srcExports = requireSrc(); + var picocolors = { exports: {} }; + var hasRequiredPicocolors; + function requirePicocolors() { + if (hasRequiredPicocolors) + return picocolors.exports; + hasRequiredPicocolors = 1; + let p = process || {}, argv = p.argv || [], env = p.env || {}; + let isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI); + let formatter = (open, close, replace = open) => (input) => { + let string = "" + input, index = string.indexOf(close, open.length); + return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close; + }; + let replaceClose = (string, close, replace, index) => { + let result = "", cursor = 0; + do { + result += string.substring(cursor, index) + replace; + cursor = index + close.length; + index = string.indexOf(close, cursor); + } while (~index); + return result + string.substring(cursor); + }; + let createColors = (enabled = isColorSupported) => { + let f2 = enabled ? formatter : () => String; + return { + isColorSupported: enabled, + reset: f2("\x1B[0m", "\x1B[0m"), + bold: f2("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"), + dim: f2("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"), + italic: f2("\x1B[3m", "\x1B[23m"), + underline: f2("\x1B[4m", "\x1B[24m"), + inverse: f2("\x1B[7m", "\x1B[27m"), + hidden: f2("\x1B[8m", "\x1B[28m"), + strikethrough: f2("\x1B[9m", "\x1B[29m"), + black: f2("\x1B[30m", "\x1B[39m"), + red: f2("\x1B[31m", "\x1B[39m"), + green: f2("\x1B[32m", "\x1B[39m"), + yellow: f2("\x1B[33m", "\x1B[39m"), + blue: f2("\x1B[34m", "\x1B[39m"), + magenta: f2("\x1B[35m", "\x1B[39m"), + cyan: f2("\x1B[36m", "\x1B[39m"), + white: f2("\x1B[37m", "\x1B[39m"), + gray: f2("\x1B[90m", "\x1B[39m"), + bgBlack: f2("\x1B[40m", "\x1B[49m"), + bgRed: f2("\x1B[41m", "\x1B[49m"), + bgGreen: f2("\x1B[42m", "\x1B[49m"), + bgYellow: f2("\x1B[43m", "\x1B[49m"), + bgBlue: f2("\x1B[44m", "\x1B[49m"), + bgMagenta: f2("\x1B[45m", "\x1B[49m"), + bgCyan: f2("\x1B[46m", "\x1B[49m"), + bgWhite: f2("\x1B[47m", "\x1B[49m"), + blackBright: f2("\x1B[90m", "\x1B[39m"), + redBright: f2("\x1B[91m", "\x1B[39m"), + greenBright: f2("\x1B[92m", "\x1B[39m"), + yellowBright: f2("\x1B[93m", "\x1B[39m"), + blueBright: f2("\x1B[94m", "\x1B[39m"), + magentaBright: f2("\x1B[95m", "\x1B[39m"), + cyanBright: f2("\x1B[96m", "\x1B[39m"), + whiteBright: f2("\x1B[97m", "\x1B[39m"), + bgBlackBright: f2("\x1B[100m", "\x1B[49m"), + bgRedBright: f2("\x1B[101m", "\x1B[49m"), + bgGreenBright: f2("\x1B[102m", "\x1B[49m"), + bgYellowBright: f2("\x1B[103m", "\x1B[49m"), + bgBlueBright: f2("\x1B[104m", "\x1B[49m"), + bgMagentaBright: f2("\x1B[105m", "\x1B[49m"), + bgCyanBright: f2("\x1B[106m", "\x1B[49m"), + bgWhiteBright: f2("\x1B[107m", "\x1B[49m") + }; + }; + picocolors.exports = createColors(); + picocolors.exports.createColors = createColors; + return picocolors.exports; + } + var picocolorsExports = /* @__PURE__ */ requirePicocolors(); + var e = /* @__PURE__ */ getDefaultExportFromCjs(picocolorsExports); + function J({ onlyFirst: t = false } = {}) { + const F2 = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|"); + return new RegExp(F2, t ? undefined : "g"); + } + var Q = J(); + function T$1(t) { + if (typeof t != "string") + throw new TypeError(`Expected a \`string\`, got \`${typeof t}\``); + return t.replace(Q, ""); + } + function O(t) { + return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t; + } + var P$1 = { exports: {} }; + (function(t) { + var u2 = {}; + t.exports = u2, u2.eastAsianWidth = function(e2) { + var s = e2.charCodeAt(0), i = e2.length == 2 ? e2.charCodeAt(1) : 0, D = s; + return 55296 <= s && s <= 56319 && 56320 <= i && i <= 57343 && (s &= 1023, i &= 1023, D = s << 10 | i, D += 65536), D == 12288 || 65281 <= D && D <= 65376 || 65504 <= D && D <= 65510 ? "F" : D == 8361 || 65377 <= D && D <= 65470 || 65474 <= D && D <= 65479 || 65482 <= D && D <= 65487 || 65490 <= D && D <= 65495 || 65498 <= D && D <= 65500 || 65512 <= D && D <= 65518 ? "H" : 4352 <= D && D <= 4447 || 4515 <= D && D <= 4519 || 4602 <= D && D <= 4607 || 9001 <= D && D <= 9002 || 11904 <= D && D <= 11929 || 11931 <= D && D <= 12019 || 12032 <= D && D <= 12245 || 12272 <= D && D <= 12283 || 12289 <= D && D <= 12350 || 12353 <= D && D <= 12438 || 12441 <= D && D <= 12543 || 12549 <= D && D <= 12589 || 12593 <= D && D <= 12686 || 12688 <= D && D <= 12730 || 12736 <= D && D <= 12771 || 12784 <= D && D <= 12830 || 12832 <= D && D <= 12871 || 12880 <= D && D <= 13054 || 13056 <= D && D <= 19903 || 19968 <= D && D <= 42124 || 42128 <= D && D <= 42182 || 43360 <= D && D <= 43388 || 44032 <= D && D <= 55203 || 55216 <= D && D <= 55238 || 55243 <= D && D <= 55291 || 63744 <= D && D <= 64255 || 65040 <= D && D <= 65049 || 65072 <= D && D <= 65106 || 65108 <= D && D <= 65126 || 65128 <= D && D <= 65131 || 110592 <= D && D <= 110593 || 127488 <= D && D <= 127490 || 127504 <= D && D <= 127546 || 127552 <= D && D <= 127560 || 127568 <= D && D <= 127569 || 131072 <= D && D <= 194367 || 177984 <= D && D <= 196605 || 196608 <= D && D <= 262141 ? "W" : 32 <= D && D <= 126 || 162 <= D && D <= 163 || 165 <= D && D <= 166 || D == 172 || D == 175 || 10214 <= D && D <= 10221 || 10629 <= D && D <= 10630 ? "Na" : D == 161 || D == 164 || 167 <= D && D <= 168 || D == 170 || 173 <= D && D <= 174 || 176 <= D && D <= 180 || 182 <= D && D <= 186 || 188 <= D && D <= 191 || D == 198 || D == 208 || 215 <= D && D <= 216 || 222 <= D && D <= 225 || D == 230 || 232 <= D && D <= 234 || 236 <= D && D <= 237 || D == 240 || 242 <= D && D <= 243 || 247 <= D && D <= 250 || D == 252 || D == 254 || D == 257 || D == 273 || D == 275 || D == 283 || 294 <= D && D <= 295 || D == 299 || 305 <= D && D <= 307 || D == 312 || 319 <= D && D <= 322 || D == 324 || 328 <= D && D <= 331 || D == 333 || 338 <= D && D <= 339 || 358 <= D && D <= 359 || D == 363 || D == 462 || D == 464 || D == 466 || D == 468 || D == 470 || D == 472 || D == 474 || D == 476 || D == 593 || D == 609 || D == 708 || D == 711 || 713 <= D && D <= 715 || D == 717 || D == 720 || 728 <= D && D <= 731 || D == 733 || D == 735 || 768 <= D && D <= 879 || 913 <= D && D <= 929 || 931 <= D && D <= 937 || 945 <= D && D <= 961 || 963 <= D && D <= 969 || D == 1025 || 1040 <= D && D <= 1103 || D == 1105 || D == 8208 || 8211 <= D && D <= 8214 || 8216 <= D && D <= 8217 || 8220 <= D && D <= 8221 || 8224 <= D && D <= 8226 || 8228 <= D && D <= 8231 || D == 8240 || 8242 <= D && D <= 8243 || D == 8245 || D == 8251 || D == 8254 || D == 8308 || D == 8319 || 8321 <= D && D <= 8324 || D == 8364 || D == 8451 || D == 8453 || D == 8457 || D == 8467 || D == 8470 || 8481 <= D && D <= 8482 || D == 8486 || D == 8491 || 8531 <= D && D <= 8532 || 8539 <= D && D <= 8542 || 8544 <= D && D <= 8555 || 8560 <= D && D <= 8569 || D == 8585 || 8592 <= D && D <= 8601 || 8632 <= D && D <= 8633 || D == 8658 || D == 8660 || D == 8679 || D == 8704 || 8706 <= D && D <= 8707 || 8711 <= D && D <= 8712 || D == 8715 || D == 8719 || D == 8721 || D == 8725 || D == 8730 || 8733 <= D && D <= 8736 || D == 8739 || D == 8741 || 8743 <= D && D <= 8748 || D == 8750 || 8756 <= D && D <= 8759 || 8764 <= D && D <= 8765 || D == 8776 || D == 8780 || D == 8786 || 8800 <= D && D <= 8801 || 8804 <= D && D <= 8807 || 8810 <= D && D <= 8811 || 8814 <= D && D <= 8815 || 8834 <= D && D <= 8835 || 8838 <= D && D <= 8839 || D == 8853 || D == 8857 || D == 8869 || D == 8895 || D == 8978 || 9312 <= D && D <= 9449 || 9451 <= D && D <= 9547 || 9552 <= D && D <= 9587 || 9600 <= D && D <= 9615 || 9618 <= D && D <= 9621 || 9632 <= D && D <= 9633 || 9635 <= D && D <= 9641 || 9650 <= D && D <= 9651 || 9654 <= D && D <= 9655 || 9660 <= D && D <= 9661 || 9664 <= D && D <= 9665 || 9670 <= D && D <= 9672 || D == 9675 || 9678 <= D && D <= 9681 || 9698 <= D && D <= 9701 || D == 9711 || 9733 <= D && D <= 9734 || D == 9737 || 9742 <= D && D <= 9743 || 9748 <= D && D <= 9749 || D == 9756 || D == 9758 || D == 9792 || D == 9794 || 9824 <= D && D <= 9825 || 9827 <= D && D <= 9829 || 9831 <= D && D <= 9834 || 9836 <= D && D <= 9837 || D == 9839 || 9886 <= D && D <= 9887 || 9918 <= D && D <= 9919 || 9924 <= D && D <= 9933 || 9935 <= D && D <= 9953 || D == 9955 || 9960 <= D && D <= 9983 || D == 10045 || D == 10071 || 10102 <= D && D <= 10111 || 11093 <= D && D <= 11097 || 12872 <= D && D <= 12879 || 57344 <= D && D <= 63743 || 65024 <= D && D <= 65039 || D == 65533 || 127232 <= D && D <= 127242 || 127248 <= D && D <= 127277 || 127280 <= D && D <= 127337 || 127344 <= D && D <= 127386 || 917760 <= D && D <= 917999 || 983040 <= D && D <= 1048573 || 1048576 <= D && D <= 1114109 ? "A" : "N"; + }, u2.characterLength = function(e2) { + var s = this.eastAsianWidth(e2); + return s == "F" || s == "W" || s == "A" ? 2 : 1; + }; + function F2(e2) { + return e2.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || []; + } + u2.length = function(e2) { + for (var s = F2(e2), i = 0, D = 0;D < s.length; D++) + i = i + this.characterLength(s[D]); + return i; + }, u2.slice = function(e2, s, i) { + textLen = u2.length(e2), s = s || 0, i = i || 1, s < 0 && (s = textLen + s), i < 0 && (i = textLen + i); + for (var D = "", C2 = 0, o2 = F2(e2), E = 0;E < o2.length; E++) { + var a = o2[E], n = u2.length(a); + if (C2 >= s - (n == 2 ? 1 : 0)) + if (C2 + n <= i) + D += a; + else + break; + C2 += n; + } + return D; + }; + })(P$1); + var X = P$1.exports; + var DD = O(X); + var uD = function() { + return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g; + }; + var FD = O(uD); + function A$1(t, u2 = {}) { + if (typeof t != "string" || t.length === 0 || (u2 = { ambiguousIsNarrow: true, ...u2 }, t = T$1(t), t.length === 0)) + return 0; + t = t.replace(FD(), " "); + const F2 = u2.ambiguousIsNarrow ? 1 : 2; + let e2 = 0; + for (const s of t) { + const i = s.codePointAt(0); + if (i <= 31 || i >= 127 && i <= 159 || i >= 768 && i <= 879) + continue; + switch (DD.eastAsianWidth(s)) { + case "F": + case "W": + e2 += 2; + break; + case "A": + e2 += F2; + break; + default: + e2 += 1; + } + } + return e2; + } + var m = 10; + var L$1 = (t = 0) => (u2) => `\x1B[${u2 + t}m`; + var N = (t = 0) => (u2) => `\x1B[${38 + t};5;${u2}m`; + var I = (t = 0) => (u2, F2, e2) => `\x1B[${38 + t};2;${u2};${F2};${e2}m`; + var r = { modifier: { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23], underline: [4, 24], overline: [53, 55], inverse: [7, 27], hidden: [8, 28], strikethrough: [9, 29] }, color: { black: [30, 39], red: [31, 39], green: [32, 39], yellow: [33, 39], blue: [34, 39], magenta: [35, 39], cyan: [36, 39], white: [37, 39], blackBright: [90, 39], gray: [90, 39], grey: [90, 39], redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39], blueBright: [94, 39], magentaBright: [95, 39], cyanBright: [96, 39], whiteBright: [97, 39] }, bgColor: { bgBlack: [40, 49], bgRed: [41, 49], bgGreen: [42, 49], bgYellow: [43, 49], bgBlue: [44, 49], bgMagenta: [45, 49], bgCyan: [46, 49], bgWhite: [47, 49], bgBlackBright: [100, 49], bgGray: [100, 49], bgGrey: [100, 49], bgRedBright: [101, 49], bgGreenBright: [102, 49], bgYellowBright: [103, 49], bgBlueBright: [104, 49], bgMagentaBright: [105, 49], bgCyanBright: [106, 49], bgWhiteBright: [107, 49] } }; + Object.keys(r.modifier); + var tD = Object.keys(r.color); + var eD = Object.keys(r.bgColor); + [...tD, ...eD]; + function sD() { + const t = new Map; + for (const [u2, F2] of Object.entries(r)) { + for (const [e2, s] of Object.entries(F2)) + r[e2] = { open: `\x1B[${s[0]}m`, close: `\x1B[${s[1]}m` }, F2[e2] = r[e2], t.set(s[0], s[1]); + Object.defineProperty(r, u2, { value: F2, enumerable: false }); + } + return Object.defineProperty(r, "codes", { value: t, enumerable: false }), r.color.close = "\x1B[39m", r.bgColor.close = "\x1B[49m", r.color.ansi = L$1(), r.color.ansi256 = N(), r.color.ansi16m = I(), r.bgColor.ansi = L$1(m), r.bgColor.ansi256 = N(m), r.bgColor.ansi16m = I(m), Object.defineProperties(r, { rgbToAnsi256: { value: (u2, F2, e2) => u2 === F2 && F2 === e2 ? u2 < 8 ? 16 : u2 > 248 ? 231 : Math.round((u2 - 8) / 247 * 24) + 232 : 16 + 36 * Math.round(u2 / 255 * 5) + 6 * Math.round(F2 / 255 * 5) + Math.round(e2 / 255 * 5), enumerable: false }, hexToRgb: { value: (u2) => { + const F2 = /[a-f\d]{6}|[a-f\d]{3}/i.exec(u2.toString(16)); + if (!F2) + return [0, 0, 0]; + let [e2] = F2; + e2.length === 3 && (e2 = [...e2].map((i) => i + i).join("")); + const s = Number.parseInt(e2, 16); + return [s >> 16 & 255, s >> 8 & 255, s & 255]; + }, enumerable: false }, hexToAnsi256: { value: (u2) => r.rgbToAnsi256(...r.hexToRgb(u2)), enumerable: false }, ansi256ToAnsi: { value: (u2) => { + if (u2 < 8) + return 30 + u2; + if (u2 < 16) + return 90 + (u2 - 8); + let F2, e2, s; + if (u2 >= 232) + F2 = ((u2 - 232) * 10 + 8) / 255, e2 = F2, s = F2; + else { + u2 -= 16; + const C2 = u2 % 36; + F2 = Math.floor(u2 / 36) / 5, e2 = Math.floor(C2 / 6) / 5, s = C2 % 6 / 5; + } + const i = Math.max(F2, e2, s) * 2; + if (i === 0) + return 30; + let D = 30 + (Math.round(s) << 2 | Math.round(e2) << 1 | Math.round(F2)); + return i === 2 && (D += 60), D; + }, enumerable: false }, rgbToAnsi: { value: (u2, F2, e2) => r.ansi256ToAnsi(r.rgbToAnsi256(u2, F2, e2)), enumerable: false }, hexToAnsi: { value: (u2) => r.ansi256ToAnsi(r.hexToAnsi256(u2)), enumerable: false } }), r; + } + var iD = sD(); + var v = new Set(["\x1B", "›"]); + var CD = 39; + var w$1 = "\x07"; + var W$1 = "["; + var rD = "]"; + var R = "m"; + var y = `${rD}8;;`; + var V$1 = (t) => `${v.values().next().value}${W$1}${t}${R}`; + var z = (t) => `${v.values().next().value}${y}${t}${w$1}`; + var ED = (t) => t.split(" ").map((u2) => A$1(u2)); + var _ = (t, u2, F2) => { + const e2 = [...u2]; + let s = false, i = false, D = A$1(T$1(t[t.length - 1])); + for (const [C2, o2] of e2.entries()) { + const E = A$1(o2); + if (D + E <= F2 ? t[t.length - 1] += o2 : (t.push(o2), D = 0), v.has(o2) && (s = true, i = e2.slice(C2 + 1).join("").startsWith(y)), s) { + i ? o2 === w$1 && (s = false, i = false) : o2 === R && (s = false); + continue; + } + D += E, D === F2 && C2 < e2.length - 1 && (t.push(""), D = 0); + } + !D && t[t.length - 1].length > 0 && t.length > 1 && (t[t.length - 2] += t.pop()); + }; + var nD = (t) => { + const u2 = t.split(" "); + let F2 = u2.length; + for (;F2 > 0 && !(A$1(u2[F2 - 1]) > 0); ) + F2--; + return F2 === u2.length ? t : u2.slice(0, F2).join(" ") + u2.slice(F2).join(""); + }; + var oD = (t, u2, F2 = {}) => { + if (F2.trim !== false && t.trim() === "") + return ""; + let e2 = "", s, i; + const D = ED(t); + let C2 = [""]; + for (const [E, a] of t.split(" ").entries()) { + F2.trim !== false && (C2[C2.length - 1] = C2[C2.length - 1].trimStart()); + let n = A$1(C2[C2.length - 1]); + if (E !== 0 && (n >= u2 && (F2.wordWrap === false || F2.trim === false) && (C2.push(""), n = 0), (n > 0 || F2.trim === false) && (C2[C2.length - 1] += " ", n++)), F2.hard && D[E] > u2) { + const B2 = u2 - n, p = 1 + Math.floor((D[E] - B2 - 1) / u2); + Math.floor((D[E] - 1) / u2) < p && C2.push(""), _(C2, a, u2); + continue; + } + if (n + D[E] > u2 && n > 0 && D[E] > 0) { + if (F2.wordWrap === false && n < u2) { + _(C2, a, u2); + continue; + } + C2.push(""); + } + if (n + D[E] > u2 && F2.wordWrap === false) { + _(C2, a, u2); + continue; + } + C2[C2.length - 1] += a; + } + F2.trim !== false && (C2 = C2.map((E) => nD(E))); + const o2 = [...C2.join(` +`)]; + for (const [E, a] of o2.entries()) { + if (e2 += a, v.has(a)) { + const { groups: B2 } = new RegExp(`(?:\\${W$1}(?\\d+)m|\\${y}(?.*)${w$1})`).exec(o2.slice(E).join("")) || { groups: {} }; + if (B2.code !== undefined) { + const p = Number.parseFloat(B2.code); + s = p === CD ? undefined : p; + } else + B2.uri !== undefined && (i = B2.uri.length === 0 ? undefined : B2.uri); + } + const n = iD.codes.get(Number(s)); + o2[E + 1] === ` +` ? (i && (e2 += z("")), s && n && (e2 += V$1(n))) : a === ` +` && (s && n && (e2 += V$1(s)), i && (e2 += z(i))); + } + return e2; + }; + function G(t, u2, F2) { + return String(t).normalize().replace(/\r\n/g, ` +`).split(` +`).map((e2) => oD(e2, u2, F2)).join(` +`); + } + var aD = ["up", "down", "left", "right", "space", "enter", "cancel"]; + var c = { actions: new Set(aD), aliases: new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["\x03", "cancel"], ["escape", "cancel"]]) }; + function k$1(t, u2) { + if (typeof t == "string") + return c.aliases.get(t) === u2; + for (const F2 of t) + if (F2 !== undefined && k$1(F2, u2)) + return true; + return false; + } + function lD(t, u2) { + if (t === u2) + return; + const F2 = t.split(` +`), e2 = u2.split(` +`), s = []; + for (let i = 0;i < Math.max(F2.length, e2.length); i++) + F2[i] !== e2[i] && s.push(i); + return s; + } + globalThis.process.platform.startsWith("win"); + var S = Symbol("clack:cancel"); + function d$1(t, u2) { + const F2 = t; + F2.isTTY && F2.setRawMode(u2); + } + var AD = Object.defineProperty; + var pD = (t, u2, F2) => (u2 in t) ? AD(t, u2, { enumerable: true, configurable: true, writable: true, value: F2 }) : t[u2] = F2; + var h = (t, u2, F2) => (pD(t, typeof u2 != "symbol" ? u2 + "" : u2, F2), F2); + + class x { + constructor(u2, F2 = true) { + h(this, "input"), h(this, "output"), h(this, "_abortSignal"), h(this, "rl"), h(this, "opts"), h(this, "_render"), h(this, "_track", false), h(this, "_prevFrame", ""), h(this, "_subscribers", new Map), h(this, "_cursor", 0), h(this, "state", "initial"), h(this, "error", ""), h(this, "value"); + const { input: e2 = g.stdin, output: s = g.stdout, render: i, signal: D, ...C2 } = u2; + this.opts = C2, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = i.bind(this), this._track = F2, this._abortSignal = D, this.input = e2, this.output = s; + } + unsubscribe() { + this._subscribers.clear(); + } + setSubscriber(u2, F2) { + const e2 = this._subscribers.get(u2) ?? []; + e2.push(F2), this._subscribers.set(u2, e2); + } + on(u2, F2) { + this.setSubscriber(u2, { cb: F2 }); + } + once(u2, F2) { + this.setSubscriber(u2, { cb: F2, once: true }); + } + emit(u2, ...F2) { + const e2 = this._subscribers.get(u2) ?? [], s = []; + for (const i of e2) + i.cb(...F2), i.once && s.push(() => e2.splice(e2.indexOf(i), 1)); + for (const i of s) + i(); + } + prompt() { + return new Promise((u2, F2) => { + if (this._abortSignal) { + if (this._abortSignal.aborted) + return this.state = "cancel", this.close(), u2(S); + this._abortSignal.addEventListener("abort", () => { + this.state = "cancel", this.close(); + }, { once: true }); + } + const e2 = new tty.WriteStream(0); + e2._write = (s, i, D) => { + this._track && (this.value = this.rl?.line.replace(/\t/g, ""), this._cursor = this.rl?.cursor ?? 0, this.emit("value", this.value)), D(); + }, this.input.pipe(e2), this.rl = f__default.createInterface({ input: this.input, output: e2, tabSize: 2, prompt: "", escapeCodeTimeout: 50 }), f__default.emitKeypressEvents(this.input, this.rl), this.rl.prompt(), this.opts.initialValue !== undefined && this._track && this.rl.write(this.opts.initialValue), this.input.on("keypress", this.onKeypress), d$1(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => { + this.output.write(srcExports.cursor.show), this.output.off("resize", this.render), d$1(this.input, false), u2(this.value); + }), this.once("cancel", () => { + this.output.write(srcExports.cursor.show), this.output.off("resize", this.render), d$1(this.input, false), u2(S); + }); + }); + } + onKeypress(u2, F2) { + if (this.state === "error" && (this.state = "active"), F2?.name && (!this._track && c.aliases.has(F2.name) && this.emit("cursor", c.aliases.get(F2.name)), c.actions.has(F2.name) && this.emit("cursor", F2.name)), u2 && (u2.toLowerCase() === "y" || u2.toLowerCase() === "n") && this.emit("confirm", u2.toLowerCase() === "y"), u2 === "\t" && this.opts.placeholder && (this.value || (this.rl?.write(this.opts.placeholder), this.emit("value", this.opts.placeholder))), u2 && this.emit("key", u2.toLowerCase()), F2?.name === "return") { + if (this.opts.validate) { + const e2 = this.opts.validate(this.value); + e2 && (this.error = e2 instanceof Error ? e2.message : e2, this.state = "error", this.rl?.write(this.value)); + } + this.state !== "error" && (this.state = "submit"); + } + k$1([u2, F2?.name, F2?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close(); + } + close() { + this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(` +`), d$1(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe(); + } + restoreCursor() { + const u2 = G(this._prevFrame, process.stdout.columns, { hard: true }).split(` +`).length - 1; + this.output.write(srcExports.cursor.move(-999, u2 * -1)); + } + render() { + const u2 = G(this._render(this) ?? "", process.stdout.columns, { hard: true }); + if (u2 !== this._prevFrame) { + if (this.state === "initial") + this.output.write(srcExports.cursor.hide); + else { + const F2 = lD(this._prevFrame, u2); + if (this.restoreCursor(), F2 && F2?.length === 1) { + const e2 = F2[0]; + this.output.write(srcExports.cursor.move(0, e2)), this.output.write(srcExports.erase.lines(1)); + const s = u2.split(` +`); + this.output.write(s[e2]), this._prevFrame = u2, this.output.write(srcExports.cursor.move(0, s.length - e2 - 1)); + return; + } + if (F2 && F2?.length > 1) { + const e2 = F2[0]; + this.output.write(srcExports.cursor.move(0, e2)), this.output.write(srcExports.erase.down()); + const s = u2.split(` +`).slice(e2); + this.output.write(s.join(` +`)), this._prevFrame = u2; + return; + } + this.output.write(srcExports.erase.down()); + } + this.output.write(u2), this.state === "initial" && (this.state = "active"), this._prevFrame = u2; + } + } + } + + class fD extends x { + get cursor() { + return this.value ? 0 : 1; + } + get _value() { + return this.cursor === 0; + } + constructor(u2) { + super(u2, false), this.value = !!u2.initialValue, this.on("value", () => { + this.value = this._value; + }), this.on("confirm", (F2) => { + this.output.write(srcExports.cursor.move(0, -1)), this.value = F2, this.state = "submit", this.close(); + }), this.on("cursor", () => { + this.value = !this.value; + }); + } + } + var bD = Object.defineProperty; + var mD = (t, u2, F2) => (u2 in t) ? bD(t, u2, { enumerable: true, configurable: true, writable: true, value: F2 }) : t[u2] = F2; + var Y = (t, u2, F2) => (mD(t, typeof u2 != "symbol" ? u2 + "" : u2, F2), F2); + var wD = class extends x { + constructor(u2) { + super(u2, false), Y(this, "options"), Y(this, "cursor", 0), this.options = u2.options, this.value = [...u2.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: F2 }) => F2 === u2.cursorAt), 0), this.on("key", (F2) => { + F2 === "a" && this.toggleAll(); + }), this.on("cursor", (F2) => { + switch (F2) { + case "left": + case "up": + this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1; + break; + case "down": + case "right": + this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1; + break; + case "space": + this.toggleValue(); + break; + } + }); + } + get _value() { + return this.options[this.cursor].value; + } + toggleAll() { + const u2 = this.value.length === this.options.length; + this.value = u2 ? [] : this.options.map((F2) => F2.value); + } + toggleValue() { + const u2 = this.value.includes(this._value); + this.value = u2 ? this.value.filter((F2) => F2 !== this._value) : [...this.value, this._value]; + } + }; + var SD = Object.defineProperty; + var $D = (t, u2, F2) => (u2 in t) ? SD(t, u2, { enumerable: true, configurable: true, writable: true, value: F2 }) : t[u2] = F2; + var q = (t, u2, F2) => ($D(t, typeof u2 != "symbol" ? u2 + "" : u2, F2), F2); + + class jD extends x { + constructor(u2) { + super(u2, false), q(this, "options"), q(this, "cursor", 0), this.options = u2.options, this.cursor = this.options.findIndex(({ value: F2 }) => F2 === u2.initialValue), this.cursor === -1 && (this.cursor = 0), this.changeValue(), this.on("cursor", (F2) => { + switch (F2) { + case "left": + case "up": + this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1; + break; + case "down": + case "right": + this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1; + break; + } + this.changeValue(); + }); + } + get _value() { + return this.options[this.cursor]; + } + changeValue() { + this.value = this._value.value; + } + } + + class PD extends x { + get valueWithCursor() { + if (this.state === "submit") + return this.value; + if (this.cursor >= this.value.length) + return `${this.value}█`; + const u2 = this.value.slice(0, this.cursor), [F2, ...e$1] = this.value.slice(this.cursor); + return `${u2}${e.inverse(F2)}${e$1.join("")}`; + } + get cursor() { + return this._cursor; + } + constructor(u2) { + super(u2), this.on("finalize", () => { + this.value || (this.value = u2.defaultValue); + }); + } + } + function ce() { + return g__default.platform !== "win32" ? g__default.env.TERM !== "linux" : !!g__default.env.CI || !!g__default.env.WT_SESSION || !!g__default.env.TERMINUS_SUBLIME || g__default.env.ConEmuTask === "{cmd::Cmder}" || g__default.env.TERM_PROGRAM === "Terminus-Sublime" || g__default.env.TERM_PROGRAM === "vscode" || g__default.env.TERM === "xterm-256color" || g__default.env.TERM === "alacritty" || g__default.env.TERMINAL_EMULATOR === "JetBrains-JediTerm"; + } + var V = ce(); + var u = (t, n) => V ? t : n; + var le = u("❯", ">"); + var L = u("■", "x"); + var W = u("▲", "x"); + var C = u("✔", "√"); + var o = u(""); + var d = u(""); + var k = u("●", ">"); + var P = u("○", " "); + var A = u("◻", "[•]"); + var T = u("◼", "[+]"); + var F = u("◻", "[ ]"); + var w = (t) => { + switch (t) { + case "initial": + case "active": + return e.cyan(le); + case "cancel": + return e.red(L); + case "error": + return e.yellow(W); + case "submit": + return e.green(C); + } + }; + var B = (t) => { + const { cursor: n, options: s, style: r2 } = t, i = t.maxItems ?? Number.POSITIVE_INFINITY, a = Math.max(process.stdout.rows - 4, 0), c2 = Math.min(a, Math.max(i, 5)); + let l = 0; + n >= l + c2 - 3 ? l = Math.max(Math.min(n - c2 + 3, s.length - c2), 0) : n < l + 2 && (l = Math.max(n - 2, 0)); + const $ = c2 < s.length && l > 0, p = c2 < s.length && l + c2 < s.length; + return s.slice(l, l + c2).map((M, v2, x2) => { + const j = v2 === 0 && $, E = v2 === x2.length - 1 && p; + return j || E ? e.dim("...") : r2(M, v2 + l === n); + }); + }; + var he = (t) => new PD({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, render() { + const n = `${e.gray(o)} +${w(this.state)} ${t.message} +`, s = t.placeholder ? e.inverse(t.placeholder[0]) + e.dim(t.placeholder.slice(1)) : e.inverse(e.hidden("_")), r2 = this.value ? this.valueWithCursor : s; + switch (this.state) { + case "error": + return `${n.trim()} +${e.yellow(o)} ${r2} +${e.yellow(d)} ${e.yellow(this.error)} +`; + case "submit": + return `${n}${e.gray(o)} ${e.dim(this.value || t.placeholder)}`; + case "cancel": + return `${n}${e.gray(o)} ${e.strikethrough(e.dim(this.value ?? ""))}${this.value?.trim() ? ` +${e.gray(o)}` : ""}`; + default: + return `${n}${e.cyan(o)} ${r2} +${e.cyan(d)} +`; + } + } }).prompt(); + var ye = (t) => { + const n = t.active ?? "Yes", s = t.inactive ?? "No"; + return new fD({ active: n, inactive: s, initialValue: t.initialValue ?? true, render() { + const r2 = `${e.gray(o)} +${w(this.state)} ${t.message} +`, i = this.value ? n : s; + switch (this.state) { + case "submit": + return `${r2}${e.gray(o)} ${e.dim(i)}`; + case "cancel": + return `${r2}${e.gray(o)} ${e.strikethrough(e.dim(i))} +${e.gray(o)}`; + default: + return `${r2}${e.cyan(o)} ${this.value ? `${e.green(k)} ${n}` : `${e.dim(P)} ${e.dim(n)}`} ${e.dim("/")} ${this.value ? `${e.dim(P)} ${e.dim(s)}` : `${e.green(k)} ${s}`} +${e.cyan(d)} +`; + } + } }).prompt(); + }; + var ve = (t) => { + const n = (s, r2) => { + const i = s.label ?? String(s.value); + switch (r2) { + case "selected": + return `${e.dim(i)}`; + case "active": + return `${e.green(k)} ${i} ${s.hint ? e.dim(`(${s.hint})`) : ""}`; + case "cancelled": + return `${e.strikethrough(e.dim(i))}`; + default: + return `${e.dim(P)} ${e.dim(i)}`; + } + }; + return new jD({ options: t.options, initialValue: t.initialValue, render() { + const s = `${e.gray(o)} +${w(this.state)} ${t.message} +`; + switch (this.state) { + case "submit": + return `${s}${e.gray(o)} ${n(this.options[this.cursor], "selected")}`; + case "cancel": + return `${s}${e.gray(o)} ${n(this.options[this.cursor], "cancelled")} +${e.gray(o)}`; + default: + return `${s}${e.cyan(o)} ${B({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (r2, i) => n(r2, i ? "active" : "inactive") }).join(` +${e.cyan(o)} `)} +${e.cyan(d)} +`; + } + } }).prompt(); + }; + var fe = (t) => { + const n = (s, r2) => { + const i = s.label ?? String(s.value); + return r2 === "active" ? `${e.cyan(A)} ${i} ${s.hint ? e.dim(`(${s.hint})`) : ""}` : r2 === "selected" ? `${e.green(T)} ${e.dim(i)}` : r2 === "cancelled" ? `${e.strikethrough(e.dim(i))}` : r2 === "active-selected" ? `${e.green(T)} ${i} ${s.hint ? e.dim(`(${s.hint})`) : ""}` : r2 === "submitted" ? `${e.dim(i)}` : `${e.dim(F)} ${e.dim(i)}`; + }; + return new wD({ options: t.options, initialValues: t.initialValues, required: t.required ?? true, cursorAt: t.cursorAt, validate(s) { + if (this.required && s.length === 0) + return `Please select at least one option. +${e.reset(e.dim(`Press ${e.gray(e.bgWhite(e.inverse(" space ")))} to select, ${e.gray(e.bgWhite(e.inverse(" enter ")))} to submit`))}`; + }, render() { + const s = `${e.gray(o)} +${w(this.state)} ${t.message} +`, r2 = (i, a) => { + const c2 = this.value.includes(i.value); + return a && c2 ? n(i, "active-selected") : c2 ? n(i, "selected") : n(i, a ? "active" : "inactive"); + }; + switch (this.state) { + case "submit": + return `${s}${e.gray(o)} ${this.options.filter(({ value: i }) => this.value.includes(i)).map((i) => n(i, "submitted")).join(e.dim(", ")) || e.dim("none")}`; + case "cancel": { + const i = this.options.filter(({ value: a }) => this.value.includes(a)).map((a) => n(a, "cancelled")).join(e.dim(", ")); + return `${s}${e.gray(o)} ${i.trim() ? `${i} +${e.gray(o)}` : ""}`; + } + case "error": { + const i = this.error.split(` +`).map((a, c2) => c2 === 0 ? `${e.yellow(d)} ${e.yellow(a)}` : ` ${a}`).join(` +`); + return `${s + e.yellow(o)} ${B({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: r2 }).join(` +${e.yellow(o)} `)} +${i} +`; + } + default: + return `${s}${e.cyan(o)} ${B({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: r2 }).join(` +${e.cyan(o)} `)} +${e.cyan(d)} +`; + } + } }).prompt(); + }; + `${e.gray(o)} `; + var kCancel = Symbol.for("cancel"); + async function prompt(message, opts = {}) { + const handleCancel = (value) => { + if (typeof value !== "symbol" || value.toString() !== "Symbol(clack:cancel)") { + return value; + } + switch (opts.cancel) { + case "reject": { + const error = new Error("Prompt cancelled."); + error.name = "ConsolaPromptCancelledError"; + if (Error.captureStackTrace) { + Error.captureStackTrace(error, prompt); + } + throw error; + } + case "undefined": { + return; + } + case "null": { + return null; + } + case "symbol": { + return kCancel; + } + default: + case "default": { + return opts.default ?? opts.initial; + } + } + }; + if (!opts.type || opts.type === "text") { + return await he({ + message, + defaultValue: opts.default, + placeholder: opts.placeholder, + initialValue: opts.initial + }).then(handleCancel); + } + if (opts.type === "confirm") { + return await ye({ + message, + initialValue: opts.initial + }).then(handleCancel); + } + if (opts.type === "select") { + return await ve({ + message, + options: opts.options.map((o2) => typeof o2 === "string" ? { value: o2, label: o2 } : o2), + initialValue: opts.initial + }).then(handleCancel); + } + if (opts.type === "multiselect") { + return await fe({ + message, + options: opts.options.map((o2) => typeof o2 === "string" ? { value: o2, label: o2 } : o2), + required: opts.required, + initialValues: opts.initial + }).then(handleCancel); + } + throw new Error(`Unknown prompt type: ${opts.type}`); + } + exports2.kCancel = kCancel; + exports2.prompt = prompt; +}); + +// node_modules/consola/dist/index.cjs +var require_dist3 = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + var core = require_core(); + var basic = require_consola_DCGIlDNP(); + var g$1 = require("node:process"); + var box = require_consola_DwRq1yyg(); + require("node:util"); + require("node:path"); + require("node:tty"); + function _interopDefaultCompat(e) { + return e && typeof e === "object" && "default" in e ? e.default : e; + } + var g__default = /* @__PURE__ */ _interopDefaultCompat(g$1); + var r = Object.create(null); + var i = (e) => globalThis.process?.env || undefined || globalThis.Deno?.env.toObject() || globalThis.__env__ || (e ? r : globalThis); + var o = new Proxy(r, { get(e, s2) { + return i()[s2] ?? r[s2]; + }, has(e, s2) { + const E = i(); + return s2 in E || s2 in r; + }, set(e, s2, E) { + const B = i(true); + return B[s2] = E, true; + }, deleteProperty(e, s2) { + if (!s2) + return false; + const E = i(true); + return delete E[s2], true; + }, ownKeys() { + const e = i(true); + return Object.keys(e); + } }); + var t = typeof process < "u" && process.env && "development" || ""; + var f = [["APPVEYOR"], ["AWS_AMPLIFY", "AWS_APP_ID", { ci: true }], ["AZURE_PIPELINES", "SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"], ["AZURE_STATIC", "INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN"], ["APPCIRCLE", "AC_APPCIRCLE"], ["BAMBOO", "bamboo_planKey"], ["BITBUCKET", "BITBUCKET_COMMIT"], ["BITRISE", "BITRISE_IO"], ["BUDDY", "BUDDY_WORKSPACE_ID"], ["BUILDKITE"], ["CIRCLE", "CIRCLECI"], ["CIRRUS", "CIRRUS_CI"], ["CLOUDFLARE_PAGES", "CF_PAGES", { ci: true }], ["CODEBUILD", "CODEBUILD_BUILD_ARN"], ["CODEFRESH", "CF_BUILD_ID"], ["DRONE"], ["DRONE", "DRONE_BUILD_EVENT"], ["DSARI"], ["GITHUB_ACTIONS"], ["GITLAB", "GITLAB_CI"], ["GITLAB", "CI_MERGE_REQUEST_ID"], ["GOCD", "GO_PIPELINE_LABEL"], ["LAYERCI"], ["HUDSON", "HUDSON_URL"], ["JENKINS", "JENKINS_URL"], ["MAGNUM"], ["NETLIFY"], ["NETLIFY", "NETLIFY_LOCAL", { ci: false }], ["NEVERCODE"], ["RENDER"], ["SAIL", "SAILCI"], ["SEMAPHORE"], ["SCREWDRIVER"], ["SHIPPABLE"], ["SOLANO", "TDDIUM"], ["STRIDER"], ["TEAMCITY", "TEAMCITY_VERSION"], ["TRAVIS"], ["VERCEL", "NOW_BUILDER"], ["VERCEL", "VERCEL", { ci: false }], ["VERCEL", "VERCEL_ENV", { ci: false }], ["APPCENTER", "APPCENTER_BUILD_ID"], ["CODESANDBOX", "CODESANDBOX_SSE", { ci: false }], ["CODESANDBOX", "CODESANDBOX_HOST", { ci: false }], ["STACKBLITZ"], ["STORMKIT"], ["CLEAVR"], ["ZEABUR"], ["CODESPHERE", "CODESPHERE_APP_ID", { ci: true }], ["RAILWAY", "RAILWAY_PROJECT_ID"], ["RAILWAY", "RAILWAY_SERVICE_ID"], ["DENO-DEPLOY", "DENO_DEPLOYMENT_ID"], ["FIREBASE_APP_HOSTING", "FIREBASE_APP_HOSTING", { ci: true }]]; + function b() { + if (globalThis.process?.env) + for (const e of f) { + const s2 = e[1] || e[0]; + if (globalThis.process?.env[s2]) + return { name: e[0].toLowerCase(), ...e[2] }; + } + return globalThis.process?.env?.SHELL === "/bin/jsh" && globalThis.process?.versions?.webcontainer ? { name: "stackblitz", ci: false } : { name: "", ci: false }; + } + var l = b(); + l.name; + function n(e) { + return e ? e !== "false" : false; + } + var I = globalThis.process?.platform || ""; + var T = n(o.CI) || l.ci !== false; + var a = n(globalThis.process?.stdout && globalThis.process?.stdout.isTTY); + var g = n(o.DEBUG); + var R = t === "test" || n(o.TEST); + n(o.MINIMAL); + var A = /^win/i.test(I); + !n(o.NO_COLOR) && (n(o.FORCE_COLOR) || (a || A) && o.TERM); + var C = (globalThis.process?.versions?.node || "").replace(/^v/, "") || null; + Number(C?.split(".")[0]); + var y = globalThis.process || Object.create(null); + var _ = { versions: {} }; + new Proxy(y, { get(e, s2) { + if (s2 === "env") + return o; + if (s2 in e) + return e[s2]; + if (s2 in _) + return _[s2]; + } }); + var c = globalThis.process?.release?.name === "node"; + var O = !!globalThis.Bun || !!globalThis.process?.versions?.bun; + var D = !!globalThis.Deno; + var L = !!globalThis.fastly; + var S = !!globalThis.Netlify; + var u = !!globalThis.EdgeRuntime; + var N = globalThis.navigator?.userAgent === "Cloudflare-Workers"; + var F = [[S, "netlify"], [u, "edge-light"], [N, "workerd"], [L, "fastly"], [D, "deno"], [O, "bun"], [c, "node"]]; + function G() { + const e = F.find((s2) => s2[0]); + if (e) + return { name: e[1] }; + } + var P = G(); + P?.name; + function ansiRegex({ onlyFirst = false } = {}) { + const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)"; + const pattern = [ + `[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?${ST})`, + "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))" + ].join("|"); + return new RegExp(pattern, onlyFirst ? undefined : "g"); + } + var regex = ansiRegex(); + function stripAnsi(string) { + if (typeof string !== "string") { + throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``); + } + return string.replace(regex, ""); + } + function isAmbiguous(x) { + return x === 161 || x === 164 || x === 167 || x === 168 || x === 170 || x === 173 || x === 174 || x >= 176 && x <= 180 || x >= 182 && x <= 186 || x >= 188 && x <= 191 || x === 198 || x === 208 || x === 215 || x === 216 || x >= 222 && x <= 225 || x === 230 || x >= 232 && x <= 234 || x === 236 || x === 237 || x === 240 || x === 242 || x === 243 || x >= 247 && x <= 250 || x === 252 || x === 254 || x === 257 || x === 273 || x === 275 || x === 283 || x === 294 || x === 295 || x === 299 || x >= 305 && x <= 307 || x === 312 || x >= 319 && x <= 322 || x === 324 || x >= 328 && x <= 331 || x === 333 || x === 338 || x === 339 || x === 358 || x === 359 || x === 363 || x === 462 || x === 464 || x === 466 || x === 468 || x === 470 || x === 472 || x === 474 || x === 476 || x === 593 || x === 609 || x === 708 || x === 711 || x >= 713 && x <= 715 || x === 717 || x === 720 || x >= 728 && x <= 731 || x === 733 || x === 735 || x >= 768 && x <= 879 || x >= 913 && x <= 929 || x >= 931 && x <= 937 || x >= 945 && x <= 961 || x >= 963 && x <= 969 || x === 1025 || x >= 1040 && x <= 1103 || x === 1105 || x === 8208 || x >= 8211 && x <= 8214 || x === 8216 || x === 8217 || x === 8220 || x === 8221 || x >= 8224 && x <= 8226 || x >= 8228 && x <= 8231 || x === 8240 || x === 8242 || x === 8243 || x === 8245 || x === 8251 || x === 8254 || x === 8308 || x === 8319 || x >= 8321 && x <= 8324 || x === 8364 || x === 8451 || x === 8453 || x === 8457 || x === 8467 || x === 8470 || x === 8481 || x === 8482 || x === 8486 || x === 8491 || x === 8531 || x === 8532 || x >= 8539 && x <= 8542 || x >= 8544 && x <= 8555 || x >= 8560 && x <= 8569 || x === 8585 || x >= 8592 && x <= 8601 || x === 8632 || x === 8633 || x === 8658 || x === 8660 || x === 8679 || x === 8704 || x === 8706 || x === 8707 || x === 8711 || x === 8712 || x === 8715 || x === 8719 || x === 8721 || x === 8725 || x === 8730 || x >= 8733 && x <= 8736 || x === 8739 || x === 8741 || x >= 8743 && x <= 8748 || x === 8750 || x >= 8756 && x <= 8759 || x === 8764 || x === 8765 || x === 8776 || x === 8780 || x === 8786 || x === 8800 || x === 8801 || x >= 8804 && x <= 8807 || x === 8810 || x === 8811 || x === 8814 || x === 8815 || x === 8834 || x === 8835 || x === 8838 || x === 8839 || x === 8853 || x === 8857 || x === 8869 || x === 8895 || x === 8978 || x >= 9312 && x <= 9449 || x >= 9451 && x <= 9547 || x >= 9552 && x <= 9587 || x >= 9600 && x <= 9615 || x >= 9618 && x <= 9621 || x === 9632 || x === 9633 || x >= 9635 && x <= 9641 || x === 9650 || x === 9651 || x === 9654 || x === 9655 || x === 9660 || x === 9661 || x === 9664 || x === 9665 || x >= 9670 && x <= 9672 || x === 9675 || x >= 9678 && x <= 9681 || x >= 9698 && x <= 9701 || x === 9711 || x === 9733 || x === 9734 || x === 9737 || x === 9742 || x === 9743 || x === 9756 || x === 9758 || x === 9792 || x === 9794 || x === 9824 || x === 9825 || x >= 9827 && x <= 9829 || x >= 9831 && x <= 9834 || x === 9836 || x === 9837 || x === 9839 || x === 9886 || x === 9887 || x === 9919 || x >= 9926 && x <= 9933 || x >= 9935 && x <= 9939 || x >= 9941 && x <= 9953 || x === 9955 || x === 9960 || x === 9961 || x >= 9963 && x <= 9969 || x === 9972 || x >= 9974 && x <= 9977 || x === 9979 || x === 9980 || x === 9982 || x === 9983 || x === 10045 || x >= 10102 && x <= 10111 || x >= 11094 && x <= 11097 || x >= 12872 && x <= 12879 || x >= 57344 && x <= 63743 || x >= 65024 && x <= 65039 || x === 65533 || x >= 127232 && x <= 127242 || x >= 127248 && x <= 127277 || x >= 127280 && x <= 127337 || x >= 127344 && x <= 127373 || x === 127375 || x === 127376 || x >= 127387 && x <= 127404 || x >= 917760 && x <= 917999 || x >= 983040 && x <= 1048573 || x >= 1048576 && x <= 1114109; + } + function isFullWidth(x) { + return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510; + } + function isWide(x) { + return x >= 4352 && x <= 4447 || x === 8986 || x === 8987 || x === 9001 || x === 9002 || x >= 9193 && x <= 9196 || x === 9200 || x === 9203 || x === 9725 || x === 9726 || x === 9748 || x === 9749 || x >= 9776 && x <= 9783 || x >= 9800 && x <= 9811 || x === 9855 || x >= 9866 && x <= 9871 || x === 9875 || x === 9889 || x === 9898 || x === 9899 || x === 9917 || x === 9918 || x === 9924 || x === 9925 || x === 9934 || x === 9940 || x === 9962 || x === 9970 || x === 9971 || x === 9973 || x === 9978 || x === 9981 || x === 9989 || x === 9994 || x === 9995 || x === 10024 || x === 10060 || x === 10062 || x >= 10067 && x <= 10069 || x === 10071 || x >= 10133 && x <= 10135 || x === 10160 || x === 10175 || x === 11035 || x === 11036 || x === 11088 || x === 11093 || x >= 11904 && x <= 11929 || x >= 11931 && x <= 12019 || x >= 12032 && x <= 12245 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12353 && x <= 12438 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12773 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 42124 || x >= 42128 && x <= 42182 || x >= 43360 && x <= 43388 || x >= 44032 && x <= 55203 || x >= 63744 && x <= 64255 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 94176 && x <= 94180 || x === 94192 || x === 94193 || x >= 94208 && x <= 100343 || x >= 100352 && x <= 101589 || x >= 101631 && x <= 101640 || x >= 110576 && x <= 110579 || x >= 110581 && x <= 110587 || x === 110589 || x === 110590 || x >= 110592 && x <= 110882 || x === 110898 || x >= 110928 && x <= 110930 || x === 110933 || x >= 110948 && x <= 110951 || x >= 110960 && x <= 111355 || x >= 119552 && x <= 119638 || x >= 119648 && x <= 119670 || x === 126980 || x === 127183 || x === 127374 || x >= 127377 && x <= 127386 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x === 127568 || x === 127569 || x >= 127584 && x <= 127589 || x >= 127744 && x <= 127776 || x >= 127789 && x <= 127797 || x >= 127799 && x <= 127868 || x >= 127870 && x <= 127891 || x >= 127904 && x <= 127946 || x >= 127951 && x <= 127955 || x >= 127968 && x <= 127984 || x === 127988 || x >= 127992 && x <= 128062 || x === 128064 || x >= 128066 && x <= 128252 || x >= 128255 && x <= 128317 || x >= 128331 && x <= 128334 || x >= 128336 && x <= 128359 || x === 128378 || x === 128405 || x === 128406 || x === 128420 || x >= 128507 && x <= 128591 || x >= 128640 && x <= 128709 || x === 128716 || x >= 128720 && x <= 128722 || x >= 128725 && x <= 128727 || x >= 128732 && x <= 128735 || x === 128747 || x === 128748 || x >= 128756 && x <= 128764 || x >= 128992 && x <= 129003 || x === 129008 || x >= 129292 && x <= 129338 || x >= 129340 && x <= 129349 || x >= 129351 && x <= 129535 || x >= 129648 && x <= 129660 || x >= 129664 && x <= 129673 || x >= 129679 && x <= 129734 || x >= 129742 && x <= 129756 || x >= 129759 && x <= 129769 || x >= 129776 && x <= 129784 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141; + } + function validate(codePoint) { + if (!Number.isSafeInteger(codePoint)) { + throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`); + } + } + function eastAsianWidth(codePoint, { ambiguousAsWide = false } = {}) { + validate(codePoint); + if (isFullWidth(codePoint) || isWide(codePoint) || ambiguousAsWide && isAmbiguous(codePoint)) { + return 2; + } + return 1; + } + var emojiRegex = () => { + return /[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26D3\uFE0F?(?:\u200D\uD83D\uDCA5)?|\u26F9(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF43\uDF45-\uDF4A\uDF4C-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDF44(?:\u200D\uD83D\uDFEB)?|\uDF4B(?:\u200D\uD83D\uDFE9)?|\uDFC3(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4\uDEB5](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE41\uDE43\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC26(?:\u200D(?:\u2B1B|\uD83D\uDD25))?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE])))?))?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDD75(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?|\uDE42(?:\u200D[\u2194\u2195]\uFE0F?)?|\uDEB6(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE89\uDE8F-\uDEC2\uDEC6\uDECE-\uDEDC\uDEDF-\uDEE9]|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F?|\uD83C[\uDFFB-\uDFFF])?|\uDDCE(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1|\uDDD1\u200D\uD83E\uDDD2(?:\u200D\uD83E\uDDD2)?|\uDDD2(?:\u200D\uD83E\uDDD2)?))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g; + }; + var segmenter = globalThis.Intl?.Segmenter ? new Intl.Segmenter : { segment: (str) => str.split("") }; + var defaultIgnorableCodePointRegex = /^\p{Default_Ignorable_Code_Point}$/u; + function stringWidth$1(string, options = {}) { + if (typeof string !== "string" || string.length === 0) { + return 0; + } + const { + ambiguousIsNarrow = true, + countAnsiEscapeCodes = false + } = options; + if (!countAnsiEscapeCodes) { + string = stripAnsi(string); + } + if (string.length === 0) { + return 0; + } + let width = 0; + const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow }; + for (const { segment: character } of segmenter.segment(string)) { + const codePoint = character.codePointAt(0); + if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) { + continue; + } + if (codePoint >= 8203 && codePoint <= 8207 || codePoint === 65279) { + continue; + } + if (codePoint >= 768 && codePoint <= 879 || codePoint >= 6832 && codePoint <= 6911 || codePoint >= 7616 && codePoint <= 7679 || codePoint >= 8400 && codePoint <= 8447 || codePoint >= 65056 && codePoint <= 65071) { + continue; + } + if (codePoint >= 55296 && codePoint <= 57343) { + continue; + } + if (codePoint >= 65024 && codePoint <= 65039) { + continue; + } + if (defaultIgnorableCodePointRegex.test(character)) { + continue; + } + if (emojiRegex().test(character)) { + width += 2; + continue; + } + width += eastAsianWidth(codePoint, eastAsianWidthOptions); + } + return width; + } + function isUnicodeSupported() { + const { env } = g__default; + const { TERM, TERM_PROGRAM } = env; + if (g__default.platform !== "win32") { + return TERM !== "linux"; + } + return Boolean(env.WT_SESSION) || Boolean(env.TERMINUS_SUBLIME) || env.ConEmuTask === "{cmd::Cmder}" || TERM_PROGRAM === "Terminus-Sublime" || TERM_PROGRAM === "vscode" || TERM === "xterm-256color" || TERM === "alacritty" || TERM === "rxvt-unicode" || TERM === "rxvt-unicode-256color" || env.TERMINAL_EMULATOR === "JetBrains-JediTerm"; + } + var TYPE_COLOR_MAP = { + info: "cyan", + fail: "red", + success: "green", + ready: "green", + start: "magenta" + }; + var LEVEL_COLOR_MAP = { + 0: "red", + 1: "yellow" + }; + var unicode = isUnicodeSupported(); + var s = (c2, fallback) => unicode ? c2 : fallback; + var TYPE_ICONS = { + error: s("✖", "×"), + fatal: s("✖", "×"), + ready: s("✔", "√"), + warn: s("⚠", "‼"), + info: s("ℹ", "i"), + success: s("✔", "√"), + debug: s("⚙", "D"), + trace: s("→", "→"), + fail: s("✖", "×"), + start: s("◐", "o"), + log: "" + }; + function stringWidth(str) { + const hasICU = typeof Intl === "object"; + if (!hasICU || !Intl.Segmenter) { + return box.stripAnsi(str).length; + } + return stringWidth$1(str); + } + + class FancyReporter extends basic.BasicReporter { + formatStack(stack, message, opts) { + const indent = " ".repeat((opts?.errorLevel || 0) + 1); + return ` +${indent}` + basic.parseStack(stack, message).map((line) => " " + line.replace(/^at +/, (m) => box.colors.gray(m)).replace(/\((.+)\)/, (_2, m) => `(${box.colors.cyan(m)})`)).join(` +${indent}`); + } + formatType(logObj, isBadge, opts) { + const typeColor = TYPE_COLOR_MAP[logObj.type] || LEVEL_COLOR_MAP[logObj.level] || "gray"; + if (isBadge) { + return getBgColor(typeColor)(box.colors.black(` ${logObj.type.toUpperCase()} `)); + } + const _type = typeof TYPE_ICONS[logObj.type] === "string" ? TYPE_ICONS[logObj.type] : logObj.icon || logObj.type; + return _type ? getColor(typeColor)(_type) : ""; + } + formatLogObj(logObj, opts) { + const [message, ...additional] = this.formatArgs(logObj.args, opts).split(` +`); + if (logObj.type === "box") { + return box.box(characterFormat(message + (additional.length > 0 ? ` +` + additional.join(` +`) : "")), { + title: logObj.title ? characterFormat(logObj.title) : undefined, + style: logObj.style + }); + } + const date = this.formatDate(logObj.date, opts); + const coloredDate = date && box.colors.gray(date); + const isBadge = logObj.badge ?? logObj.level < 2; + const type = this.formatType(logObj, isBadge, opts); + const tag = logObj.tag ? box.colors.gray(logObj.tag) : ""; + let line; + const left = this.filterAndJoin([type, characterFormat(message)]); + const right = this.filterAndJoin(opts.columns ? [tag, coloredDate] : [tag]); + const space = (opts.columns || 0) - stringWidth(left) - stringWidth(right) - 2; + line = space > 0 && (opts.columns || 0) >= 80 ? left + " ".repeat(space) + right : (right ? `${box.colors.gray(`[${right}]`)} ` : "") + left; + line += characterFormat(additional.length > 0 ? ` +` + additional.join(` +`) : ""); + if (logObj.type === "trace") { + const _err = new Error("Trace: " + logObj.message); + line += this.formatStack(_err.stack || "", _err.message); + } + return isBadge ? ` +` + line + ` +` : line; + } + } + function characterFormat(str) { + return str.replace(/`([^`]+)`/gm, (_2, m) => box.colors.cyan(m)).replace(/\s+_([^_]+)_\s+/gm, (_2, m) => ` ${box.colors.underline(m)} `); + } + function getColor(color = "white") { + return box.colors[color] || box.colors.white; + } + function getBgColor(color = "bgWhite") { + return box.colors[`bg${color[0].toUpperCase()}${color.slice(1)}`] || box.colors.bgWhite; + } + function createConsola(options = {}) { + let level = _getDefaultLogLevel(); + if (process.env.CONSOLA_LEVEL) { + level = Number.parseInt(process.env.CONSOLA_LEVEL) ?? level; + } + const consola2 = core.createConsola({ + level, + defaults: { level }, + stdout: process.stdout, + stderr: process.stderr, + prompt: (...args) => Promise.resolve().then(() => __toESM(require_prompt())).then((m) => m.prompt(...args)), + reporters: options.reporters || [ + options.fancy ?? !(T || R) ? new FancyReporter : new basic.BasicReporter + ], + ...options + }); + return consola2; + } + function _getDefaultLogLevel() { + if (g) { + return core.LogLevels.debug; + } + if (R) { + return core.LogLevels.warn; + } + return core.LogLevels.info; + } + var consola = createConsola(); + exports2.Consola = core.Consola; + exports2.LogLevels = core.LogLevels; + exports2.LogTypes = core.LogTypes; + exports2.consola = consola; + exports2.createConsola = createConsola; + exports2.default = consola; +}); + +// node_modules/consola/lib/index.cjs +var require_lib2 = __commonJS((exports2, module2) => { + var lib = require_dist3(); + module2.exports = lib.consola; + for (const key in lib) { + if (!(key in module2.exports)) { + module2.exports[key] = lib[key]; + } + } +}); + +// node_modules/consola/dist/utils.cjs +var require_utils = __commonJS((exports2) => { + var box = require_consola_DwRq1yyg(); + require("node:tty"); + function formatTree(items, options) { + options = { + prefix: " ", + ellipsis: "...", + ...options + }; + const tree = _buildTree(items, options).join(""); + if (options && options.color) { + return box.colorize(options.color, tree); + } + return tree; + } + function _buildTree(items, options) { + const chunks = []; + const total = items.length - 1; + for (let i = 0;i <= total; i++) { + const item = items[i]; + const isItemString = typeof item === "string"; + const isLimit = options?.maxDepth != null && options.maxDepth <= 0; + if (isLimit) { + const ellipsis = `${options.prefix}${options.ellipsis} +`; + return [ + isItemString ? ellipsis : item.color ? box.colorize(item.color, ellipsis) : ellipsis + ]; + } + const isLast = i === total; + const prefix = isLast ? `${options?.prefix}└─` : `${options?.prefix}├─`; + if (isItemString) { + chunks.push(`${prefix}${item} +`); + } else { + const log = `${prefix}${item.text} +`; + chunks.push(item.color ? box.colorize(item.color, log) : log); + if (item.children) { + const _tree = _buildTree(item.children, { + ...options, + maxDepth: options?.maxDepth == null ? undefined : options.maxDepth - 1, + prefix: `${options?.prefix}${isLast ? " " : "│ "}` + }); + chunks.push(..._tree); + } + } + } + return chunks; + } + exports2.align = box.align; + exports2.box = box.box; + exports2.centerAlign = box.centerAlign; + exports2.colorize = box.colorize; + exports2.colors = box.colors; + exports2.getColor = box.getColor; + exports2.leftAlign = box.leftAlign; + exports2.rightAlign = box.rightAlign; + exports2.stripAnsi = box.stripAnsi; + exports2.formatTree = formatTree; +}); + +// node_modules/xmlhttprequest-ssl/lib/XMLHttpRequest.js +var require_XMLHttpRequest = __commonJS((exports2, module2) => { + var fs = require("fs"); + var Url = require("url"); + var spawn = require("child_process").spawn; + module2.exports = XMLHttpRequest2; + XMLHttpRequest2.XMLHttpRequest = XMLHttpRequest2; + function XMLHttpRequest2(opts) { + opts = opts || {}; + var self = this; + var http = require("http"); + var https = require("https"); + var request; + var response; + var settings = {}; + var disableHeaderCheck = false; + var defaultHeaders = { + "User-Agent": "node-XMLHttpRequest", + Accept: "*/*" + }; + var headers = Object.assign({}, defaultHeaders); + var forbiddenRequestHeaders = [ + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "content-transfer-encoding", + "cookie", + "cookie2", + "date", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "via" + ]; + var forbiddenRequestMethods = [ + "TRACE", + "TRACK", + "CONNECT" + ]; + var sendFlag = false; + var errorFlag = false; + var abortedFlag = false; + var listeners = {}; + this.UNSENT = 0; + this.OPENED = 1; + this.HEADERS_RECEIVED = 2; + this.LOADING = 3; + this.DONE = 4; + this.readyState = this.UNSENT; + this.onreadystatechange = null; + this.responseText = ""; + this.responseXML = ""; + this.response = Buffer.alloc(0); + this.status = null; + this.statusText = null; + var isAllowedHttpHeader = function(header) { + return disableHeaderCheck || header && forbiddenRequestHeaders.indexOf(header.toLowerCase()) === -1; + }; + var isAllowedHttpMethod = function(method) { + return method && forbiddenRequestMethods.indexOf(method) === -1; + }; + this.open = function(method, url, async, user, password) { + this.abort(); + errorFlag = false; + abortedFlag = false; + if (!isAllowedHttpMethod(method)) { + throw new Error("SecurityError: Request method not allowed"); + } + settings = { + method, + url: url.toString(), + async: typeof async !== "boolean" ? true : async, + user: user || null, + password: password || null + }; + setState(this.OPENED); + }; + this.setDisableHeaderCheck = function(state) { + disableHeaderCheck = state; + }; + this.setRequestHeader = function(header, value) { + if (this.readyState != this.OPENED) { + throw new Error("INVALID_STATE_ERR: setRequestHeader can only be called when state is OPEN"); + } + if (!isAllowedHttpHeader(header)) { + console.warn('Refused to set unsafe header "' + header + '"'); + return false; + } + if (sendFlag) { + throw new Error("INVALID_STATE_ERR: send flag is true"); + } + headers[header] = value; + return true; + }; + this.getResponseHeader = function(header) { + if (typeof header === "string" && this.readyState > this.OPENED && response.headers[header.toLowerCase()] && !errorFlag) { + return response.headers[header.toLowerCase()]; + } + return null; + }; + this.getAllResponseHeaders = function() { + if (this.readyState < this.HEADERS_RECEIVED || errorFlag) { + return ""; + } + var result = ""; + for (var i in response.headers) { + if (i !== "set-cookie" && i !== "set-cookie2") { + result += i + ": " + response.headers[i] + `\r +`; + } + } + return result.substr(0, result.length - 2); + }; + this.getRequestHeader = function(name) { + if (typeof name === "string" && headers[name]) { + return headers[name]; + } + return ""; + }; + this.send = function(data) { + if (this.readyState != this.OPENED) { + throw new Error("INVALID_STATE_ERR: connection must be opened before send() is called"); + } + if (sendFlag) { + throw new Error("INVALID_STATE_ERR: send has already been called"); + } + var ssl = false, local = false; + var url = Url.parse(settings.url); + var host; + switch (url.protocol) { + case "https:": + ssl = true; + case "http:": + host = url.hostname; + break; + case "file:": + local = true; + break; + case undefined: + case "": + host = "localhost"; + break; + default: + throw new Error("Protocol not supported."); + } + if (local) { + if (settings.method !== "GET") { + throw new Error("XMLHttpRequest: Only GET method is supported"); + } + if (settings.async) { + fs.readFile(unescape(url.pathname), function(error, data2) { + if (error) { + self.handleError(error, error.errno || -1); + } else { + self.status = 200; + self.responseText = data2.toString("utf8"); + self.response = data2; + setState(self.DONE); + } + }); + } else { + try { + this.response = fs.readFileSync(unescape(url.pathname)); + this.responseText = this.response.toString("utf8"); + this.status = 200; + setState(self.DONE); + } catch (e) { + this.handleError(e, e.errno || -1); + } + } + return; + } + var port = url.port || (ssl ? 443 : 80); + var uri = url.pathname + (url.search ? url.search : ""); + headers["Host"] = host; + if (!(ssl && port === 443 || port === 80)) { + headers["Host"] += ":" + url.port; + } + if (settings.user) { + if (typeof settings.password == "undefined") { + settings.password = ""; + } + var authBuf = new Buffer(settings.user + ":" + settings.password); + headers["Authorization"] = "Basic " + authBuf.toString("base64"); + } + if (settings.method === "GET" || settings.method === "HEAD") { + data = null; + } else if (data) { + headers["Content-Length"] = Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data); + var headersKeys = Object.keys(headers); + if (!headersKeys.some(function(h) { + return h.toLowerCase() === "content-type"; + })) { + headers["Content-Type"] = "text/plain;charset=UTF-8"; + } + } else if (settings.method === "POST") { + headers["Content-Length"] = 0; + } + var agent = opts.agent || false; + var options = { + host, + port, + path: uri, + method: settings.method, + headers, + agent + }; + if (ssl) { + options.pfx = opts.pfx; + options.key = opts.key; + options.passphrase = opts.passphrase; + options.cert = opts.cert; + options.ca = opts.ca; + options.ciphers = opts.ciphers; + options.rejectUnauthorized = opts.rejectUnauthorized === false ? false : true; + } + errorFlag = false; + if (settings.async) { + var doRequest = ssl ? https.request : http.request; + sendFlag = true; + self.dispatchEvent("readystatechange"); + var responseHandler = function(resp2) { + response = resp2; + if (response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) { + settings.url = response.headers.location; + var url2 = Url.parse(settings.url); + host = url2.hostname; + var newOptions = { + hostname: url2.hostname, + port: url2.port, + path: url2.path, + method: response.statusCode === 303 ? "GET" : settings.method, + headers + }; + if (ssl) { + newOptions.pfx = opts.pfx; + newOptions.key = opts.key; + newOptions.passphrase = opts.passphrase; + newOptions.cert = opts.cert; + newOptions.ca = opts.ca; + newOptions.ciphers = opts.ciphers; + newOptions.rejectUnauthorized = opts.rejectUnauthorized === false ? false : true; + } + request = doRequest(newOptions, responseHandler).on("error", errorHandler); + request.end(); + return; + } + setState(self.HEADERS_RECEIVED); + self.status = response.statusCode; + response.on("data", function(chunk) { + if (chunk) { + var data2 = Buffer.from(chunk); + self.response = Buffer.concat([self.response, data2]); + } + if (sendFlag) { + setState(self.LOADING); + } + }); + response.on("end", function() { + if (sendFlag) { + sendFlag = false; + setState(self.DONE); + self.responseText = self.response.toString("utf8"); + } + }); + response.on("error", function(error) { + self.handleError(error); + }); + }; + var errorHandler = function(error) { + if (request.reusedSocket && error.code === "ECONNRESET") + return doRequest(options, responseHandler).on("error", errorHandler); + self.handleError(error); + }; + request = doRequest(options, responseHandler).on("error", errorHandler); + if (opts.autoUnref) { + request.on("socket", (socket) => { + socket.unref(); + }); + } + if (data) { + request.write(data); + } + request.end(); + self.dispatchEvent("loadstart"); + } else { + var contentFile = ".node-xmlhttprequest-content-" + process.pid; + var syncFile = ".node-xmlhttprequest-sync-" + process.pid; + fs.writeFileSync(syncFile, "", "utf8"); + var execString = "var http = require('http'), https = require('https'), fs = require('fs');" + "var doRequest = http" + (ssl ? "s" : "") + ".request;" + "var options = " + JSON.stringify(options) + ";" + "var responseText = '';" + "var responseData = Buffer.alloc(0);" + "var req = doRequest(options, function(response) {" + "response.on('data', function(chunk) {" + " var data = Buffer.from(chunk);" + " responseText += data.toString('utf8');" + " responseData = Buffer.concat([responseData, data]);" + "});" + "response.on('end', function() {" + "fs.writeFileSync('" + contentFile + "', JSON.stringify({err: null, data: {statusCode: response.statusCode, headers: response.headers, text: responseText, data: responseData.toString('base64')}}), 'utf8');" + "fs.unlinkSync('" + syncFile + "');" + "});" + "response.on('error', function(error) {" + "fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');" + "fs.unlinkSync('" + syncFile + "');" + "});" + "}).on('error', function(error) {" + "fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');" + "fs.unlinkSync('" + syncFile + "');" + "});" + (data ? "req.write('" + JSON.stringify(data).slice(1, -1).replace(/'/g, "\\'") + "');" : "") + "req.end();"; + var syncProc = spawn(process.argv[0], ["-e", execString]); + var statusText; + while (fs.existsSync(syncFile)) {} + self.responseText = fs.readFileSync(contentFile, "utf8"); + syncProc.stdin.end(); + fs.unlinkSync(contentFile); + if (self.responseText.match(/^NODE-XMLHTTPREQUEST-ERROR:/)) { + var errorObj = JSON.parse(self.responseText.replace(/^NODE-XMLHTTPREQUEST-ERROR:/, "")); + self.handleError(errorObj, 503); + } else { + self.status = self.responseText.replace(/^NODE-XMLHTTPREQUEST-STATUS:([0-9]*),.*/, "$1"); + var resp = JSON.parse(self.responseText.replace(/^NODE-XMLHTTPREQUEST-STATUS:[0-9]*,(.*)/, "$1")); + response = { + statusCode: self.status, + headers: resp.data.headers + }; + self.responseText = resp.data.text; + self.response = Buffer.from(resp.data.data, "base64"); + setState(self.DONE, true); + } + } + }; + this.handleError = function(error, status) { + this.status = status || 0; + this.statusText = error; + this.responseText = error.stack; + errorFlag = true; + setState(this.DONE); + }; + this.abort = function() { + if (request) { + request.abort(); + request = null; + } + headers = Object.assign({}, defaultHeaders); + this.responseText = ""; + this.responseXML = ""; + this.response = Buffer.alloc(0); + errorFlag = abortedFlag = true; + if (this.readyState !== this.UNSENT && (this.readyState !== this.OPENED || sendFlag) && this.readyState !== this.DONE) { + sendFlag = false; + setState(this.DONE); + } + this.readyState = this.UNSENT; + }; + this.addEventListener = function(event, callback) { + if (!(event in listeners)) { + listeners[event] = []; + } + listeners[event].push(callback); + }; + this.removeEventListener = function(event, callback) { + if (event in listeners) { + listeners[event] = listeners[event].filter(function(ev) { + return ev !== callback; + }); + } + }; + this.dispatchEvent = function(event) { + if (typeof self["on" + event] === "function") { + if (this.readyState === this.DONE && settings.async) + setTimeout(function() { + self["on" + event](); + }, 0); + else + self["on" + event](); + } + if (event in listeners) { + for (let i = 0, len = listeners[event].length;i < len; i++) { + if (this.readyState === this.DONE) + setTimeout(function() { + listeners[event][i].call(self); + }, 0); + else + listeners[event][i].call(self); + } + } + }; + var setState = function(state) { + if (self.readyState === state || self.readyState === self.UNSENT && abortedFlag) + return; + self.readyState = state; + if (settings.async || self.readyState < self.OPENED || self.readyState === self.DONE) { + self.dispatchEvent("readystatechange"); + } + if (self.readyState === self.DONE) { + let fire; + if (abortedFlag) + fire = "abort"; + else if (errorFlag) + fire = "error"; + else + fire = "load"; + self.dispatchEvent(fire); + self.dispatchEvent("loadend"); + } + }; + } +}); + +// node_modules/engine.io-client/build/cjs/globals.node.js +var require_globals_node = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.CookieJar = exports2.defaultBinaryType = exports2.globalThisShim = exports2.nextTick = undefined; + exports2.createCookieJar = createCookieJar; + exports2.parse = parse; + exports2.nextTick = process.nextTick; + exports2.globalThisShim = global; + exports2.defaultBinaryType = "nodebuffer"; + function createCookieJar() { + return new CookieJar; + } + function parse(setCookieString) { + const parts = setCookieString.split("; "); + const i = parts[0].indexOf("="); + if (i === -1) { + return; + } + const name = parts[0].substring(0, i).trim(); + if (!name.length) { + return; + } + let value = parts[0].substring(i + 1).trim(); + if (value.charCodeAt(0) === 34) { + value = value.slice(1, -1); + } + const cookie = { + name, + value + }; + for (let j = 1;j < parts.length; j++) { + const subParts = parts[j].split("="); + if (subParts.length !== 2) { + continue; + } + const key = subParts[0].trim(); + const value2 = subParts[1].trim(); + switch (key) { + case "Expires": + cookie.expires = new Date(value2); + break; + case "Max-Age": + const expiration = new Date; + expiration.setUTCSeconds(expiration.getUTCSeconds() + parseInt(value2, 10)); + cookie.expires = expiration; + break; + default: + } + } + return cookie; + } + + class CookieJar { + constructor() { + this._cookies = new Map; + } + parseCookies(values) { + if (!values) { + return; + } + values.forEach((value) => { + const parsed = parse(value); + if (parsed) { + this._cookies.set(parsed.name, parsed); + } + }); + } + get cookies() { + const now = Date.now(); + this._cookies.forEach((cookie, name) => { + var _a; + if (((_a = cookie.expires) === null || _a === undefined ? undefined : _a.getTime()) < now) { + this._cookies.delete(name); + } + }); + return this._cookies.entries(); + } + addCookies(xhr) { + const cookies = []; + for (const [name, cookie] of this.cookies) { + cookies.push(`${name}=${cookie.value}`); + } + if (cookies.length) { + xhr.setDisableHeaderCheck(true); + xhr.setRequestHeader("cookie", cookies.join("; ")); + } + } + appendCookies(headers) { + for (const [name, cookie] of this.cookies) { + headers.append("cookie", `${name}=${cookie.value}`); + } + } + } + exports2.CookieJar = CookieJar; +}); + +// node_modules/engine.io-client/build/cjs/util.js +var require_util = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.pick = pick; + exports2.installTimerFunctions = installTimerFunctions; + exports2.byteLength = byteLength; + exports2.randomString = randomString; + var globals_node_js_1 = require_globals_node(); + function pick(obj, ...attr) { + return attr.reduce((acc, k) => { + if (obj.hasOwnProperty(k)) { + acc[k] = obj[k]; + } + return acc; + }, {}); + } + var NATIVE_SET_TIMEOUT = globals_node_js_1.globalThisShim.setTimeout; + var NATIVE_CLEAR_TIMEOUT = globals_node_js_1.globalThisShim.clearTimeout; + function installTimerFunctions(obj, opts) { + if (opts.useNativeTimers) { + obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globals_node_js_1.globalThisShim); + obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globals_node_js_1.globalThisShim); + } else { + obj.setTimeoutFn = globals_node_js_1.globalThisShim.setTimeout.bind(globals_node_js_1.globalThisShim); + obj.clearTimeoutFn = globals_node_js_1.globalThisShim.clearTimeout.bind(globals_node_js_1.globalThisShim); + } + } + var BASE64_OVERHEAD = 1.33; + function byteLength(obj) { + if (typeof obj === "string") { + return utf8Length(obj); + } + return Math.ceil((obj.byteLength || obj.size) * BASE64_OVERHEAD); + } + function utf8Length(str) { + let c = 0, length = 0; + for (let i = 0, l = str.length;i < l; i++) { + c = str.charCodeAt(i); + if (c < 128) { + length += 1; + } else if (c < 2048) { + length += 2; + } else if (c < 55296 || c >= 57344) { + length += 3; + } else { + i++; + length += 4; + } + } + return length; + } + function randomString() { + return Date.now().toString(36).substring(3) + Math.random().toString(36).substring(2, 5); + } +}); + +// node_modules/engine.io-client/build/cjs/contrib/parseqs.js +var require_parseqs = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.encode = encode; + exports2.decode = decode; + function encode(obj) { + let str = ""; + for (let i in obj) { + if (obj.hasOwnProperty(i)) { + if (str.length) + str += "&"; + str += encodeURIComponent(i) + "=" + encodeURIComponent(obj[i]); + } + } + return str; + } + function decode(qs) { + let qry = {}; + let pairs = qs.split("&"); + for (let i = 0, l = pairs.length;i < l; i++) { + let pair = pairs[i].split("="); + qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); + } + return qry; + } +}); + +// node_modules/engine.io-client/build/cjs/transport.js +var require_transport2 = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Transport = exports2.TransportError = undefined; + var engine_io_parser_1 = require_cjs(); + var component_emitter_1 = require_cjs2(); + var util_js_1 = require_util(); + var parseqs_js_1 = require_parseqs(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("engine.io-client:transport"); + + class TransportError extends Error { + constructor(reason, description, context) { + super(reason); + this.description = description; + this.context = context; + this.type = "TransportError"; + } + } + exports2.TransportError = TransportError; + + class Transport extends component_emitter_1.Emitter { + constructor(opts) { + super(); + this.writable = false; + (0, util_js_1.installTimerFunctions)(this, opts); + this.opts = opts; + this.query = opts.query; + this.socket = opts.socket; + this.supportsBinary = !opts.forceBase64; + } + onError(reason, description, context) { + super.emitReserved("error", new TransportError(reason, description, context)); + return this; + } + open() { + this.readyState = "opening"; + this.doOpen(); + return this; + } + close() { + if (this.readyState === "opening" || this.readyState === "open") { + this.doClose(); + this.onClose(); + } + return this; + } + send(packets) { + if (this.readyState === "open") { + this.write(packets); + } else { + debug("transport is not open, discarding packets"); + } + } + onOpen() { + this.readyState = "open"; + this.writable = true; + super.emitReserved("open"); + } + onData(data) { + const packet = (0, engine_io_parser_1.decodePacket)(data, this.socket.binaryType); + this.onPacket(packet); + } + onPacket(packet) { + super.emitReserved("packet", packet); + } + onClose(details) { + this.readyState = "closed"; + super.emitReserved("close", details); + } + pause(onPause) {} + createUri(schema, query = {}) { + return schema + "://" + this._hostname() + this._port() + this.opts.path + this._query(query); + } + _hostname() { + const hostname = this.opts.hostname; + return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]"; + } + _port() { + if (this.opts.port && (this.opts.secure && Number(this.opts.port !== 443) || !this.opts.secure && Number(this.opts.port) !== 80)) { + return ":" + this.opts.port; + } else { + return ""; + } + } + _query(query) { + const encodedQuery = (0, parseqs_js_1.encode)(query); + return encodedQuery.length ? "?" + encodedQuery : ""; + } + } + exports2.Transport = Transport; +}); + +// node_modules/engine.io-client/build/cjs/transports/polling.js +var require_polling3 = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Polling = undefined; + var transport_js_1 = require_transport2(); + var util_js_1 = require_util(); + var engine_io_parser_1 = require_cjs(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("engine.io-client:polling"); + + class Polling extends transport_js_1.Transport { + constructor() { + super(...arguments); + this._polling = false; + } + get name() { + return "polling"; + } + doOpen() { + this._poll(); + } + pause(onPause) { + this.readyState = "pausing"; + const pause = () => { + debug("paused"); + this.readyState = "paused"; + onPause(); + }; + if (this._polling || !this.writable) { + let total = 0; + if (this._polling) { + debug("we are currently polling - waiting to pause"); + total++; + this.once("pollComplete", function() { + debug("pre-pause polling complete"); + --total || pause(); + }); + } + if (!this.writable) { + debug("we are currently writing - waiting to pause"); + total++; + this.once("drain", function() { + debug("pre-pause writing complete"); + --total || pause(); + }); + } + } else { + pause(); + } + } + _poll() { + debug("polling"); + this._polling = true; + this.doPoll(); + this.emitReserved("poll"); + } + onData(data) { + debug("polling got data %s", data); + const callback = (packet) => { + if (this.readyState === "opening" && packet.type === "open") { + this.onOpen(); + } + if (packet.type === "close") { + this.onClose({ description: "transport closed by the server" }); + return false; + } + this.onPacket(packet); + }; + (0, engine_io_parser_1.decodePayload)(data, this.socket.binaryType).forEach(callback); + if (this.readyState !== "closed") { + this._polling = false; + this.emitReserved("pollComplete"); + if (this.readyState === "open") { + this._poll(); + } else { + debug('ignoring poll - transport state "%s"', this.readyState); + } + } + } + doClose() { + const close = () => { + debug("writing close packet"); + this.write([{ type: "close" }]); + }; + if (this.readyState === "open") { + debug("transport open - closing"); + close(); + } else { + debug("transport not open - deferring close"); + this.once("open", close); + } + } + write(packets) { + this.writable = false; + (0, engine_io_parser_1.encodePayload)(packets, (data) => { + this.doWrite(data, () => { + this.writable = true; + this.emitReserved("drain"); + }); + }); + } + uri() { + const schema = this.opts.secure ? "https" : "http"; + const query = this.query || {}; + if (this.opts.timestampRequests !== false) { + query[this.opts.timestampParam] = (0, util_js_1.randomString)(); + } + if (!this.supportsBinary && !query.sid) { + query.b64 = 1; + } + return this.createUri(schema, query); + } + } + exports2.Polling = Polling; +}); + +// node_modules/engine.io-client/build/cjs/contrib/has-cors.js +var require_has_cors = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.hasCORS = undefined; + var value = false; + try { + value = typeof XMLHttpRequest !== "undefined" && "withCredentials" in new XMLHttpRequest; + } catch (err) {} + exports2.hasCORS = value; +}); + +// node_modules/engine.io-client/build/cjs/transports/polling-xhr.js +var require_polling_xhr = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.XHR = exports2.Request = exports2.BaseXHR = undefined; + var polling_js_1 = require_polling3(); + var component_emitter_1 = require_cjs2(); + var util_js_1 = require_util(); + var globals_node_js_1 = require_globals_node(); + var has_cors_js_1 = require_has_cors(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("engine.io-client:polling"); + function empty() {} + + class BaseXHR extends polling_js_1.Polling { + constructor(opts) { + super(opts); + if (typeof location !== "undefined") { + const isSSL = location.protocol === "https:"; + let port = location.port; + if (!port) { + port = isSSL ? "443" : "80"; + } + this.xd = typeof location !== "undefined" && opts.hostname !== location.hostname || port !== opts.port; + } + } + doWrite(data, fn) { + const req = this.request({ + method: "POST", + data + }); + req.on("success", fn); + req.on("error", (xhrStatus, context) => { + this.onError("xhr post error", xhrStatus, context); + }); + } + doPoll() { + debug("xhr poll"); + const req = this.request(); + req.on("data", this.onData.bind(this)); + req.on("error", (xhrStatus, context) => { + this.onError("xhr poll error", xhrStatus, context); + }); + this.pollXhr = req; + } + } + exports2.BaseXHR = BaseXHR; + + class Request extends component_emitter_1.Emitter { + constructor(createRequest, uri, opts) { + super(); + this.createRequest = createRequest; + (0, util_js_1.installTimerFunctions)(this, opts); + this._opts = opts; + this._method = opts.method || "GET"; + this._uri = uri; + this._data = opts.data !== undefined ? opts.data : null; + this._create(); + } + _create() { + var _a; + const opts = (0, util_js_1.pick)(this._opts, "agent", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "autoUnref"); + opts.xdomain = !!this._opts.xd; + const xhr = this._xhr = this.createRequest(opts); + try { + debug("xhr open %s: %s", this._method, this._uri); + xhr.open(this._method, this._uri, true); + try { + if (this._opts.extraHeaders) { + xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true); + for (let i in this._opts.extraHeaders) { + if (this._opts.extraHeaders.hasOwnProperty(i)) { + xhr.setRequestHeader(i, this._opts.extraHeaders[i]); + } + } + } + } catch (e) {} + if (this._method === "POST") { + try { + xhr.setRequestHeader("Content-type", "text/plain;charset=UTF-8"); + } catch (e) {} + } + try { + xhr.setRequestHeader("Accept", "*/*"); + } catch (e) {} + (_a = this._opts.cookieJar) === null || _a === undefined || _a.addCookies(xhr); + if ("withCredentials" in xhr) { + xhr.withCredentials = this._opts.withCredentials; + } + if (this._opts.requestTimeout) { + xhr.timeout = this._opts.requestTimeout; + } + xhr.onreadystatechange = () => { + var _a2; + if (xhr.readyState === 3) { + (_a2 = this._opts.cookieJar) === null || _a2 === undefined || _a2.parseCookies(xhr.getResponseHeader("set-cookie")); + } + if (xhr.readyState !== 4) + return; + if (xhr.status === 200 || xhr.status === 1223) { + this._onLoad(); + } else { + this.setTimeoutFn(() => { + this._onError(typeof xhr.status === "number" ? xhr.status : 0); + }, 0); + } + }; + debug("xhr data %s", this._data); + xhr.send(this._data); + } catch (e) { + this.setTimeoutFn(() => { + this._onError(e); + }, 0); + return; + } + if (typeof document !== "undefined") { + this._index = Request.requestsCount++; + Request.requests[this._index] = this; + } + } + _onError(err) { + this.emitReserved("error", err, this._xhr); + this._cleanup(true); + } + _cleanup(fromError) { + if (typeof this._xhr === "undefined" || this._xhr === null) { + return; + } + this._xhr.onreadystatechange = empty; + if (fromError) { + try { + this._xhr.abort(); + } catch (e) {} + } + if (typeof document !== "undefined") { + delete Request.requests[this._index]; + } + this._xhr = null; + } + _onLoad() { + const data = this._xhr.responseText; + if (data !== null) { + this.emitReserved("data", data); + this.emitReserved("success"); + this._cleanup(); + } + } + abort() { + this._cleanup(); + } + } + exports2.Request = Request; + Request.requestsCount = 0; + Request.requests = {}; + if (typeof document !== "undefined") { + if (typeof attachEvent === "function") { + attachEvent("onunload", unloadHandler); + } else if (typeof addEventListener === "function") { + const terminationEvent = "onpagehide" in globals_node_js_1.globalThisShim ? "pagehide" : "unload"; + addEventListener(terminationEvent, unloadHandler, false); + } + } + function unloadHandler() { + for (let i in Request.requests) { + if (Request.requests.hasOwnProperty(i)) { + Request.requests[i].abort(); + } + } + } + var hasXHR2 = function() { + const xhr = newRequest({ + xdomain: false + }); + return xhr && xhr.responseType !== null; + }(); + + class XHR extends BaseXHR { + constructor(opts) { + super(opts); + const forceBase64 = opts && opts.forceBase64; + this.supportsBinary = hasXHR2 && !forceBase64; + } + request(opts = {}) { + Object.assign(opts, { xd: this.xd }, this.opts); + return new Request(newRequest, this.uri(), opts); + } + } + exports2.XHR = XHR; + function newRequest(opts) { + const xdomain = opts.xdomain; + try { + if (typeof XMLHttpRequest !== "undefined" && (!xdomain || has_cors_js_1.hasCORS)) { + return new XMLHttpRequest; + } + } catch (e) {} + if (!xdomain) { + try { + return new globals_node_js_1.globalThisShim[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP"); + } catch (e) {} + } + } +}); + +// node_modules/engine.io-client/build/cjs/transports/polling-xhr.node.js +var require_polling_xhr_node = __commonJS((exports2) => { + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === undefined) + k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o, k2, desc); + } : function(o, m, k, k2) { + if (k2 === undefined) + k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } : function(o, v) { + o["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) + __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.XHR = undefined; + var XMLHttpRequestModule = __importStar(require_XMLHttpRequest()); + var polling_xhr_js_1 = require_polling_xhr(); + var XMLHttpRequest2 = XMLHttpRequestModule.default || XMLHttpRequestModule; + + class XHR extends polling_xhr_js_1.BaseXHR { + request(opts = {}) { + var _a; + Object.assign(opts, { xd: this.xd, cookieJar: (_a = this.socket) === null || _a === undefined ? undefined : _a._cookieJar }, this.opts); + return new polling_xhr_js_1.Request((opts2) => new XMLHttpRequest2(opts2), this.uri(), opts); + } + } + exports2.XHR = XHR; +}); + +// node_modules/engine.io-client/build/cjs/transports/websocket.js +var require_websocket4 = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WS = exports2.BaseWS = undefined; + var transport_js_1 = require_transport2(); + var util_js_1 = require_util(); + var engine_io_parser_1 = require_cjs(); + var globals_node_js_1 = require_globals_node(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("engine.io-client:websocket"); + var isReactNative = typeof navigator !== "undefined" && typeof navigator.product === "string" && navigator.product.toLowerCase() === "reactnative"; + + class BaseWS extends transport_js_1.Transport { + get name() { + return "websocket"; + } + doOpen() { + const uri = this.uri(); + const protocols = this.opts.protocols; + const opts = isReactNative ? {} : (0, util_js_1.pick)(this.opts, "agent", "perMessageDeflate", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "rejectUnauthorized", "localAddress", "protocolVersion", "origin", "maxPayload", "family", "checkServerIdentity"); + if (this.opts.extraHeaders) { + opts.headers = this.opts.extraHeaders; + } + try { + this.ws = this.createSocket(uri, protocols, opts); + } catch (err) { + return this.emitReserved("error", err); + } + this.ws.binaryType = this.socket.binaryType; + this.addEventListeners(); + } + addEventListeners() { + this.ws.onopen = () => { + if (this.opts.autoUnref) { + this.ws._socket.unref(); + } + this.onOpen(); + }; + this.ws.onclose = (closeEvent) => this.onClose({ + description: "websocket connection closed", + context: closeEvent + }); + this.ws.onmessage = (ev) => this.onData(ev.data); + this.ws.onerror = (e) => this.onError("websocket error", e); + } + write(packets) { + this.writable = false; + for (let i = 0;i < packets.length; i++) { + const packet = packets[i]; + const lastPacket = i === packets.length - 1; + (0, engine_io_parser_1.encodePacket)(packet, this.supportsBinary, (data) => { + try { + this.doWrite(packet, data); + } catch (e) { + debug("websocket closed before onclose event"); + } + if (lastPacket) { + (0, globals_node_js_1.nextTick)(() => { + this.writable = true; + this.emitReserved("drain"); + }, this.setTimeoutFn); + } + }); + } + } + doClose() { + if (typeof this.ws !== "undefined") { + this.ws.onerror = () => {}; + this.ws.close(); + this.ws = null; + } + } + uri() { + const schema = this.opts.secure ? "wss" : "ws"; + const query = this.query || {}; + if (this.opts.timestampRequests) { + query[this.opts.timestampParam] = (0, util_js_1.randomString)(); + } + if (!this.supportsBinary) { + query.b64 = 1; + } + return this.createUri(schema, query); + } + } + exports2.BaseWS = BaseWS; + var WebSocketCtor = globals_node_js_1.globalThisShim.WebSocket || globals_node_js_1.globalThisShim.MozWebSocket; + + class WS extends BaseWS { + createSocket(uri, protocols, opts) { + return !isReactNative ? protocols ? new WebSocketCtor(uri, protocols) : new WebSocketCtor(uri) : new WebSocketCtor(uri, protocols, opts); + } + doWrite(_packet, data) { + this.ws.send(data); + } + } + exports2.WS = WS; +}); + +// node_modules/engine.io-client/build/cjs/transports/websocket.node.js +var require_websocket_node = __commonJS((exports2) => { + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === undefined) + k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o, k2, desc); + } : function(o, m, k, k2) { + if (k2 === undefined) + k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } : function(o, v) { + o["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) + __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WS = undefined; + var ws = __importStar(require_ws()); + var websocket_js_1 = require_websocket4(); + + class WS extends websocket_js_1.BaseWS { + createSocket(uri, protocols, opts) { + var _a; + if ((_a = this.socket) === null || _a === undefined ? undefined : _a._cookieJar) { + opts.headers = opts.headers || {}; + opts.headers.cookie = typeof opts.headers.cookie === "string" ? [opts.headers.cookie] : opts.headers.cookie || []; + for (const [name, cookie] of this.socket._cookieJar.cookies) { + opts.headers.cookie.push(`${name}=${cookie.value}`); + } + } + return new ws.WebSocket(uri, protocols, opts); + } + doWrite(packet, data) { + const opts = {}; + if (packet.options) { + opts.compress = packet.options.compress; + } + if (this.opts.perMessageDeflate) { + const len = typeof data === "string" ? Buffer.byteLength(data) : data.length; + if (len < this.opts.perMessageDeflate.threshold) { + opts.compress = false; + } + } + this.ws.send(data, opts); + } + } + exports2.WS = WS; +}); + +// node_modules/engine.io-client/build/cjs/transports/webtransport.js +var require_webtransport2 = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WT = undefined; + var transport_js_1 = require_transport2(); + var globals_node_js_1 = require_globals_node(); + var engine_io_parser_1 = require_cjs(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("engine.io-client:webtransport"); + + class WT extends transport_js_1.Transport { + get name() { + return "webtransport"; + } + doOpen() { + try { + this._transport = new WebTransport(this.createUri("https"), this.opts.transportOptions[this.name]); + } catch (err) { + return this.emitReserved("error", err); + } + this._transport.closed.then(() => { + debug("transport closed gracefully"); + this.onClose(); + }).catch((err) => { + debug("transport closed due to %s", err); + this.onError("webtransport error", err); + }); + this._transport.ready.then(() => { + this._transport.createBidirectionalStream().then((stream) => { + const decoderStream = (0, engine_io_parser_1.createPacketDecoderStream)(Number.MAX_SAFE_INTEGER, this.socket.binaryType); + const reader = stream.readable.pipeThrough(decoderStream).getReader(); + const encoderStream = (0, engine_io_parser_1.createPacketEncoderStream)(); + encoderStream.readable.pipeTo(stream.writable); + this._writer = encoderStream.writable.getWriter(); + const read = () => { + reader.read().then(({ done, value }) => { + if (done) { + debug("session is closed"); + return; + } + debug("received chunk: %o", value); + this.onPacket(value); + read(); + }).catch((err) => { + debug("an error occurred while reading: %s", err); + }); + }; + read(); + const packet = { type: "open" }; + if (this.query.sid) { + packet.data = `{"sid":"${this.query.sid}"}`; + } + this._writer.write(packet).then(() => this.onOpen()); + }); + }); + } + write(packets) { + this.writable = false; + for (let i = 0;i < packets.length; i++) { + const packet = packets[i]; + const lastPacket = i === packets.length - 1; + this._writer.write(packet).then(() => { + if (lastPacket) { + (0, globals_node_js_1.nextTick)(() => { + this.writable = true; + this.emitReserved("drain"); + }, this.setTimeoutFn); + } + }); + } + } + doClose() { + var _a; + (_a = this._transport) === null || _a === undefined || _a.close(); + } + } + exports2.WT = WT; +}); + +// node_modules/engine.io-client/build/cjs/transports/index.js +var require_transports2 = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.transports = undefined; + var polling_xhr_node_js_1 = require_polling_xhr_node(); + var websocket_node_js_1 = require_websocket_node(); + var webtransport_js_1 = require_webtransport2(); + exports2.transports = { + websocket: websocket_node_js_1.WS, + webtransport: webtransport_js_1.WT, + polling: polling_xhr_node_js_1.XHR + }; +}); + +// node_modules/engine.io-client/build/cjs/contrib/parseuri.js +var require_parseuri = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parse = parse; + var re = /^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; + var parts = [ + "source", + "protocol", + "authority", + "userInfo", + "user", + "password", + "host", + "port", + "relative", + "path", + "directory", + "file", + "query", + "anchor" + ]; + function parse(str) { + if (str.length > 8000) { + throw "URI too long"; + } + const src = str, b = str.indexOf("["), e = str.indexOf("]"); + if (b != -1 && e != -1) { + str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ";") + str.substring(e, str.length); + } + let m = re.exec(str || ""), uri = {}, i = 14; + while (i--) { + uri[parts[i]] = m[i] || ""; + } + if (b != -1 && e != -1) { + uri.source = src; + uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ":"); + uri.authority = uri.authority.replace("[", "").replace("]", "").replace(/;/g, ":"); + uri.ipv6uri = true; + } + uri.pathNames = pathNames(uri, uri["path"]); + uri.queryKey = queryKey(uri, uri["query"]); + return uri; + } + function pathNames(obj, path) { + const regx = /\/{2,9}/g, names = path.replace(regx, "/").split("/"); + if (path.slice(0, 1) == "/" || path.length === 0) { + names.splice(0, 1); + } + if (path.slice(-1) == "/") { + names.splice(names.length - 1, 1); + } + return names; + } + function queryKey(uri, query) { + const data = {}; + query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function($0, $1, $2) { + if ($1) { + data[$1] = $2; + } + }); + return data; + } +}); + +// node_modules/engine.io-client/build/cjs/socket.js +var require_socket3 = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Socket = exports2.SocketWithUpgrade = exports2.SocketWithoutUpgrade = undefined; + var index_js_1 = require_transports2(); + var util_js_1 = require_util(); + var parseqs_js_1 = require_parseqs(); + var parseuri_js_1 = require_parseuri(); + var component_emitter_1 = require_cjs2(); + var engine_io_parser_1 = require_cjs(); + var globals_node_js_1 = require_globals_node(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("engine.io-client:socket"); + var withEventListeners = typeof addEventListener === "function" && typeof removeEventListener === "function"; + var OFFLINE_EVENT_LISTENERS = []; + if (withEventListeners) { + addEventListener("offline", () => { + debug("closing %d connection(s) because the network was lost", OFFLINE_EVENT_LISTENERS.length); + OFFLINE_EVENT_LISTENERS.forEach((listener) => listener()); + }, false); + } + + class SocketWithoutUpgrade extends component_emitter_1.Emitter { + constructor(uri, opts) { + super(); + this.binaryType = globals_node_js_1.defaultBinaryType; + this.writeBuffer = []; + this._prevBufferLen = 0; + this._pingInterval = -1; + this._pingTimeout = -1; + this._maxPayload = -1; + this._pingTimeoutTime = Infinity; + if (uri && typeof uri === "object") { + opts = uri; + uri = null; + } + if (uri) { + const parsedUri = (0, parseuri_js_1.parse)(uri); + opts.hostname = parsedUri.host; + opts.secure = parsedUri.protocol === "https" || parsedUri.protocol === "wss"; + opts.port = parsedUri.port; + if (parsedUri.query) + opts.query = parsedUri.query; + } else if (opts.host) { + opts.hostname = (0, parseuri_js_1.parse)(opts.host).host; + } + (0, util_js_1.installTimerFunctions)(this, opts); + this.secure = opts.secure != null ? opts.secure : typeof location !== "undefined" && location.protocol === "https:"; + if (opts.hostname && !opts.port) { + opts.port = this.secure ? "443" : "80"; + } + this.hostname = opts.hostname || (typeof location !== "undefined" ? location.hostname : "localhost"); + this.port = opts.port || (typeof location !== "undefined" && location.port ? location.port : this.secure ? "443" : "80"); + this.transports = []; + this._transportsByName = {}; + opts.transports.forEach((t) => { + const transportName = t.prototype.name; + this.transports.push(transportName); + this._transportsByName[transportName] = t; + }); + this.opts = Object.assign({ + path: "/engine.io", + agent: false, + withCredentials: false, + upgrade: true, + timestampParam: "t", + rememberUpgrade: false, + addTrailingSlash: true, + rejectUnauthorized: true, + perMessageDeflate: { + threshold: 1024 + }, + transportOptions: {}, + closeOnBeforeunload: false + }, opts); + this.opts.path = this.opts.path.replace(/\/$/, "") + (this.opts.addTrailingSlash ? "/" : ""); + if (typeof this.opts.query === "string") { + this.opts.query = (0, parseqs_js_1.decode)(this.opts.query); + } + if (withEventListeners) { + if (this.opts.closeOnBeforeunload) { + this._beforeunloadEventListener = () => { + if (this.transport) { + this.transport.removeAllListeners(); + this.transport.close(); + } + }; + addEventListener("beforeunload", this._beforeunloadEventListener, false); + } + if (this.hostname !== "localhost") { + debug("adding listener for the 'offline' event"); + this._offlineEventListener = () => { + this._onClose("transport close", { + description: "network connection lost" + }); + }; + OFFLINE_EVENT_LISTENERS.push(this._offlineEventListener); + } + } + if (this.opts.withCredentials) { + this._cookieJar = (0, globals_node_js_1.createCookieJar)(); + } + this._open(); + } + createTransport(name) { + debug('creating transport "%s"', name); + const query = Object.assign({}, this.opts.query); + query.EIO = engine_io_parser_1.protocol; + query.transport = name; + if (this.id) + query.sid = this.id; + const opts = Object.assign({}, this.opts, { + query, + socket: this, + hostname: this.hostname, + secure: this.secure, + port: this.port + }, this.opts.transportOptions[name]); + debug("options: %j", opts); + return new this._transportsByName[name](opts); + } + _open() { + if (this.transports.length === 0) { + this.setTimeoutFn(() => { + this.emitReserved("error", "No transports available"); + }, 0); + return; + } + const transportName = this.opts.rememberUpgrade && SocketWithoutUpgrade.priorWebsocketSuccess && this.transports.indexOf("websocket") !== -1 ? "websocket" : this.transports[0]; + this.readyState = "opening"; + const transport = this.createTransport(transportName); + transport.open(); + this.setTransport(transport); + } + setTransport(transport) { + debug("setting transport %s", transport.name); + if (this.transport) { + debug("clearing existing transport %s", this.transport.name); + this.transport.removeAllListeners(); + } + this.transport = transport; + transport.on("drain", this._onDrain.bind(this)).on("packet", this._onPacket.bind(this)).on("error", this._onError.bind(this)).on("close", (reason) => this._onClose("transport close", reason)); + } + onOpen() { + debug("socket open"); + this.readyState = "open"; + SocketWithoutUpgrade.priorWebsocketSuccess = this.transport.name === "websocket"; + this.emitReserved("open"); + this.flush(); + } + _onPacket(packet) { + if (this.readyState === "opening" || this.readyState === "open" || this.readyState === "closing") { + debug('socket receive: type "%s", data "%s"', packet.type, packet.data); + this.emitReserved("packet", packet); + this.emitReserved("heartbeat"); + switch (packet.type) { + case "open": + this.onHandshake(JSON.parse(packet.data)); + break; + case "ping": + this._sendPacket("pong"); + this.emitReserved("ping"); + this.emitReserved("pong"); + this._resetPingTimeout(); + break; + case "error": + const err = new Error("server error"); + err.code = packet.data; + this._onError(err); + break; + case "message": + this.emitReserved("data", packet.data); + this.emitReserved("message", packet.data); + break; + } + } else { + debug('packet received with socket readyState "%s"', this.readyState); + } + } + onHandshake(data) { + this.emitReserved("handshake", data); + this.id = data.sid; + this.transport.query.sid = data.sid; + this._pingInterval = data.pingInterval; + this._pingTimeout = data.pingTimeout; + this._maxPayload = data.maxPayload; + this.onOpen(); + if (this.readyState === "closed") + return; + this._resetPingTimeout(); + } + _resetPingTimeout() { + this.clearTimeoutFn(this._pingTimeoutTimer); + const delay = this._pingInterval + this._pingTimeout; + this._pingTimeoutTime = Date.now() + delay; + this._pingTimeoutTimer = this.setTimeoutFn(() => { + this._onClose("ping timeout"); + }, delay); + if (this.opts.autoUnref) { + this._pingTimeoutTimer.unref(); + } + } + _onDrain() { + this.writeBuffer.splice(0, this._prevBufferLen); + this._prevBufferLen = 0; + if (this.writeBuffer.length === 0) { + this.emitReserved("drain"); + } else { + this.flush(); + } + } + flush() { + if (this.readyState !== "closed" && this.transport.writable && !this.upgrading && this.writeBuffer.length) { + const packets = this._getWritablePackets(); + debug("flushing %d packets in socket", packets.length); + this.transport.send(packets); + this._prevBufferLen = packets.length; + this.emitReserved("flush"); + } + } + _getWritablePackets() { + const shouldCheckPayloadSize = this._maxPayload && this.transport.name === "polling" && this.writeBuffer.length > 1; + if (!shouldCheckPayloadSize) { + return this.writeBuffer; + } + let payloadSize = 1; + for (let i = 0;i < this.writeBuffer.length; i++) { + const data = this.writeBuffer[i].data; + if (data) { + payloadSize += (0, util_js_1.byteLength)(data); + } + if (i > 0 && payloadSize > this._maxPayload) { + debug("only send %d out of %d packets", i, this.writeBuffer.length); + return this.writeBuffer.slice(0, i); + } + payloadSize += 2; + } + debug("payload size is %d (max: %d)", payloadSize, this._maxPayload); + return this.writeBuffer; + } + _hasPingExpired() { + if (!this._pingTimeoutTime) + return true; + const hasExpired = Date.now() > this._pingTimeoutTime; + if (hasExpired) { + debug("throttled timer detected, scheduling connection close"); + this._pingTimeoutTime = 0; + (0, globals_node_js_1.nextTick)(() => { + this._onClose("ping timeout"); + }, this.setTimeoutFn); + } + return hasExpired; + } + write(msg, options, fn) { + this._sendPacket("message", msg, options, fn); + return this; + } + send(msg, options, fn) { + this._sendPacket("message", msg, options, fn); + return this; + } + _sendPacket(type, data, options, fn) { + if (typeof data === "function") { + fn = data; + data = undefined; + } + if (typeof options === "function") { + fn = options; + options = null; + } + if (this.readyState === "closing" || this.readyState === "closed") { + return; + } + options = options || {}; + options.compress = options.compress !== false; + const packet = { + type, + data, + options + }; + this.emitReserved("packetCreate", packet); + this.writeBuffer.push(packet); + if (fn) + this.once("flush", fn); + this.flush(); + } + close() { + const close = () => { + this._onClose("forced close"); + debug("socket closing - telling transport to close"); + this.transport.close(); + }; + const cleanupAndClose = () => { + this.off("upgrade", cleanupAndClose); + this.off("upgradeError", cleanupAndClose); + close(); + }; + const waitForUpgrade = () => { + this.once("upgrade", cleanupAndClose); + this.once("upgradeError", cleanupAndClose); + }; + if (this.readyState === "opening" || this.readyState === "open") { + this.readyState = "closing"; + if (this.writeBuffer.length) { + this.once("drain", () => { + if (this.upgrading) { + waitForUpgrade(); + } else { + close(); + } + }); + } else if (this.upgrading) { + waitForUpgrade(); + } else { + close(); + } + } + return this; + } + _onError(err) { + debug("socket error %j", err); + SocketWithoutUpgrade.priorWebsocketSuccess = false; + if (this.opts.tryAllTransports && this.transports.length > 1 && this.readyState === "opening") { + debug("trying next transport"); + this.transports.shift(); + return this._open(); + } + this.emitReserved("error", err); + this._onClose("transport error", err); + } + _onClose(reason, description) { + if (this.readyState === "opening" || this.readyState === "open" || this.readyState === "closing") { + debug('socket close with reason: "%s"', reason); + this.clearTimeoutFn(this._pingTimeoutTimer); + this.transport.removeAllListeners("close"); + this.transport.close(); + this.transport.removeAllListeners(); + if (withEventListeners) { + if (this._beforeunloadEventListener) { + removeEventListener("beforeunload", this._beforeunloadEventListener, false); + } + if (this._offlineEventListener) { + const i = OFFLINE_EVENT_LISTENERS.indexOf(this._offlineEventListener); + if (i !== -1) { + debug("removing listener for the 'offline' event"); + OFFLINE_EVENT_LISTENERS.splice(i, 1); + } + } + } + this.readyState = "closed"; + this.id = null; + this.emitReserved("close", reason, description); + this.writeBuffer = []; + this._prevBufferLen = 0; + } + } + } + exports2.SocketWithoutUpgrade = SocketWithoutUpgrade; + SocketWithoutUpgrade.protocol = engine_io_parser_1.protocol; + + class SocketWithUpgrade extends SocketWithoutUpgrade { + constructor() { + super(...arguments); + this._upgrades = []; + } + onOpen() { + super.onOpen(); + if (this.readyState === "open" && this.opts.upgrade) { + debug("starting upgrade probes"); + for (let i = 0;i < this._upgrades.length; i++) { + this._probe(this._upgrades[i]); + } + } + } + _probe(name) { + debug('probing transport "%s"', name); + let transport = this.createTransport(name); + let failed = false; + SocketWithoutUpgrade.priorWebsocketSuccess = false; + const onTransportOpen = () => { + if (failed) + return; + debug('probe transport "%s" opened', name); + transport.send([{ type: "ping", data: "probe" }]); + transport.once("packet", (msg) => { + if (failed) + return; + if (msg.type === "pong" && msg.data === "probe") { + debug('probe transport "%s" pong', name); + this.upgrading = true; + this.emitReserved("upgrading", transport); + if (!transport) + return; + SocketWithoutUpgrade.priorWebsocketSuccess = transport.name === "websocket"; + debug('pausing current transport "%s"', this.transport.name); + this.transport.pause(() => { + if (failed) + return; + if (this.readyState === "closed") + return; + debug("changing transport and sending upgrade packet"); + cleanup(); + this.setTransport(transport); + transport.send([{ type: "upgrade" }]); + this.emitReserved("upgrade", transport); + transport = null; + this.upgrading = false; + this.flush(); + }); + } else { + debug('probe transport "%s" failed', name); + const err = new Error("probe error"); + err.transport = transport.name; + this.emitReserved("upgradeError", err); + } + }); + }; + function freezeTransport() { + if (failed) + return; + failed = true; + cleanup(); + transport.close(); + transport = null; + } + const onerror = (err) => { + const error = new Error("probe error: " + err); + error.transport = transport.name; + freezeTransport(); + debug('probe transport "%s" failed because of error: %s', name, err); + this.emitReserved("upgradeError", error); + }; + function onTransportClose() { + onerror("transport closed"); + } + function onclose() { + onerror("socket closed"); + } + function onupgrade(to) { + if (transport && to.name !== transport.name) { + debug('"%s" works - aborting "%s"', to.name, transport.name); + freezeTransport(); + } + } + const cleanup = () => { + transport.removeListener("open", onTransportOpen); + transport.removeListener("error", onerror); + transport.removeListener("close", onTransportClose); + this.off("close", onclose); + this.off("upgrading", onupgrade); + }; + transport.once("open", onTransportOpen); + transport.once("error", onerror); + transport.once("close", onTransportClose); + this.once("close", onclose); + this.once("upgrading", onupgrade); + if (this._upgrades.indexOf("webtransport") !== -1 && name !== "webtransport") { + this.setTimeoutFn(() => { + if (!failed) { + transport.open(); + } + }, 200); + } else { + transport.open(); + } + } + onHandshake(data) { + this._upgrades = this._filterUpgrades(data.upgrades); + super.onHandshake(data); + } + _filterUpgrades(upgrades) { + const filteredUpgrades = []; + for (let i = 0;i < upgrades.length; i++) { + if (~this.transports.indexOf(upgrades[i])) + filteredUpgrades.push(upgrades[i]); + } + return filteredUpgrades; + } + } + exports2.SocketWithUpgrade = SocketWithUpgrade; + + class Socket extends SocketWithUpgrade { + constructor(uri, opts = {}) { + const o = typeof uri === "object" ? uri : opts; + if (!o.transports || o.transports && typeof o.transports[0] === "string") { + o.transports = (o.transports || ["polling", "websocket", "webtransport"]).map((transportName) => index_js_1.transports[transportName]).filter((t) => !!t); + } + super(uri, o); + } + } + exports2.Socket = Socket; +}); + +// node_modules/engine.io-client/build/cjs/transports/polling-fetch.js +var require_polling_fetch = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Fetch = undefined; + var polling_js_1 = require_polling3(); + + class Fetch extends polling_js_1.Polling { + doPoll() { + this._fetch().then((res) => { + if (!res.ok) { + return this.onError("fetch read error", res.status, res); + } + res.text().then((data) => this.onData(data)); + }).catch((err) => { + this.onError("fetch read error", err); + }); + } + doWrite(data, callback) { + this._fetch(data).then((res) => { + if (!res.ok) { + return this.onError("fetch write error", res.status, res); + } + callback(); + }).catch((err) => { + this.onError("fetch write error", err); + }); + } + _fetch(data) { + var _a; + const isPost = data !== undefined; + const headers = new Headers(this.opts.extraHeaders); + if (isPost) { + headers.set("content-type", "text/plain;charset=UTF-8"); + } + (_a = this.socket._cookieJar) === null || _a === undefined || _a.appendCookies(headers); + return fetch(this.uri(), { + method: isPost ? "POST" : "GET", + body: isPost ? data : null, + headers, + credentials: this.opts.withCredentials ? "include" : "omit" + }).then((res) => { + var _a2; + (_a2 = this.socket._cookieJar) === null || _a2 === undefined || _a2.parseCookies(res.headers.getSetCookie()); + return res; + }); + } + } + exports2.Fetch = Fetch; +}); + +// node_modules/engine.io-client/build/cjs/index.js +var require_cjs4 = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WebTransport = exports2.WebSocket = exports2.NodeWebSocket = exports2.XHR = exports2.NodeXHR = exports2.Fetch = exports2.nextTick = exports2.parse = exports2.installTimerFunctions = exports2.transports = exports2.TransportError = exports2.Transport = exports2.protocol = exports2.SocketWithUpgrade = exports2.SocketWithoutUpgrade = exports2.Socket = undefined; + var socket_js_1 = require_socket3(); + Object.defineProperty(exports2, "Socket", { enumerable: true, get: function() { + return socket_js_1.Socket; + } }); + var socket_js_2 = require_socket3(); + Object.defineProperty(exports2, "SocketWithoutUpgrade", { enumerable: true, get: function() { + return socket_js_2.SocketWithoutUpgrade; + } }); + Object.defineProperty(exports2, "SocketWithUpgrade", { enumerable: true, get: function() { + return socket_js_2.SocketWithUpgrade; + } }); + exports2.protocol = socket_js_1.Socket.protocol; + var transport_js_1 = require_transport2(); + Object.defineProperty(exports2, "Transport", { enumerable: true, get: function() { + return transport_js_1.Transport; + } }); + Object.defineProperty(exports2, "TransportError", { enumerable: true, get: function() { + return transport_js_1.TransportError; + } }); + var index_js_1 = require_transports2(); + Object.defineProperty(exports2, "transports", { enumerable: true, get: function() { + return index_js_1.transports; + } }); + var util_js_1 = require_util(); + Object.defineProperty(exports2, "installTimerFunctions", { enumerable: true, get: function() { + return util_js_1.installTimerFunctions; + } }); + var parseuri_js_1 = require_parseuri(); + Object.defineProperty(exports2, "parse", { enumerable: true, get: function() { + return parseuri_js_1.parse; + } }); + var globals_node_js_1 = require_globals_node(); + Object.defineProperty(exports2, "nextTick", { enumerable: true, get: function() { + return globals_node_js_1.nextTick; + } }); + var polling_fetch_js_1 = require_polling_fetch(); + Object.defineProperty(exports2, "Fetch", { enumerable: true, get: function() { + return polling_fetch_js_1.Fetch; + } }); + var polling_xhr_node_js_1 = require_polling_xhr_node(); + Object.defineProperty(exports2, "NodeXHR", { enumerable: true, get: function() { + return polling_xhr_node_js_1.XHR; + } }); + var polling_xhr_js_1 = require_polling_xhr(); + Object.defineProperty(exports2, "XHR", { enumerable: true, get: function() { + return polling_xhr_js_1.XHR; + } }); + var websocket_node_js_1 = require_websocket_node(); + Object.defineProperty(exports2, "NodeWebSocket", { enumerable: true, get: function() { + return websocket_node_js_1.WS; + } }); + var websocket_js_1 = require_websocket4(); + Object.defineProperty(exports2, "WebSocket", { enumerable: true, get: function() { + return websocket_js_1.WS; + } }); + var webtransport_js_1 = require_webtransport2(); + Object.defineProperty(exports2, "WebTransport", { enumerable: true, get: function() { + return webtransport_js_1.WT; + } }); +}); + +// node_modules/socket.io-client/build/cjs/url.js +var require_url = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.url = url; + var engine_io_client_1 = require_cjs4(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("socket.io-client:url"); + function url(uri, path = "", loc) { + let obj = uri; + loc = loc || typeof location !== "undefined" && location; + if (uri == null) + uri = loc.protocol + "//" + loc.host; + if (typeof uri === "string") { + if (uri.charAt(0) === "/") { + if (uri.charAt(1) === "/") { + uri = loc.protocol + uri; + } else { + uri = loc.host + uri; + } + } + if (!/^(https?|wss?):\/\//.test(uri)) { + debug("protocol-less url %s", uri); + if (typeof loc !== "undefined") { + uri = loc.protocol + "//" + uri; + } else { + uri = "https://" + uri; + } + } + debug("parse %s", uri); + obj = (0, engine_io_client_1.parse)(uri); + } + if (!obj.port) { + if (/^(http|ws)$/.test(obj.protocol)) { + obj.port = "80"; + } else if (/^(http|ws)s$/.test(obj.protocol)) { + obj.port = "443"; + } + } + obj.path = obj.path || "/"; + const ipv6 = obj.host.indexOf(":") !== -1; + const host = ipv6 ? "[" + obj.host + "]" : obj.host; + obj.id = obj.protocol + "://" + host + ":" + obj.port + path; + obj.href = obj.protocol + "://" + host + (loc && loc.port === obj.port ? "" : ":" + obj.port); + return obj; + } +}); + +// node_modules/socket.io-client/build/cjs/on.js +var require_on = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.on = on2; + function on2(obj, ev, fn) { + obj.on(ev, fn); + return function subDestroy() { + obj.off(ev, fn); + }; + } +}); + +// node_modules/socket.io-client/build/cjs/socket.js +var require_socket4 = __commonJS((exports2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Socket = undefined; + var socket_io_parser_1 = require_cjs3(); + var on_js_1 = require_on(); + var component_emitter_1 = require_cjs2(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("socket.io-client:socket"); + var RESERVED_EVENTS = Object.freeze({ + connect: 1, + connect_error: 1, + disconnect: 1, + disconnecting: 1, + newListener: 1, + removeListener: 1 + }); + + class Socket extends component_emitter_1.Emitter { + constructor(io, nsp, opts) { + super(); + this.connected = false; + this.recovered = false; + this.receiveBuffer = []; + this.sendBuffer = []; + this._queue = []; + this._queueSeq = 0; + this.ids = 0; + this.acks = {}; + this.flags = {}; + this.io = io; + this.nsp = nsp; + if (opts && opts.auth) { + this.auth = opts.auth; + } + this._opts = Object.assign({}, opts); + if (this.io._autoConnect) + this.open(); + } + get disconnected() { + return !this.connected; + } + subEvents() { + if (this.subs) + return; + const io = this.io; + this.subs = [ + (0, on_js_1.on)(io, "open", this.onopen.bind(this)), + (0, on_js_1.on)(io, "packet", this.onpacket.bind(this)), + (0, on_js_1.on)(io, "error", this.onerror.bind(this)), + (0, on_js_1.on)(io, "close", this.onclose.bind(this)) + ]; + } + get active() { + return !!this.subs; + } + connect() { + if (this.connected) + return this; + this.subEvents(); + if (!this.io["_reconnecting"]) + this.io.open(); + if (this.io._readyState === "open") + this.onopen(); + return this; + } + open() { + return this.connect(); + } + send(...args) { + args.unshift("message"); + this.emit.apply(this, args); + return this; + } + emit(ev, ...args) { + var _a, _b, _c; + if (RESERVED_EVENTS.hasOwnProperty(ev)) { + throw new Error('"' + ev.toString() + '" is a reserved event name'); + } + args.unshift(ev); + if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) { + this._addToQueue(args); + return this; + } + const packet = { + type: socket_io_parser_1.PacketType.EVENT, + data: args + }; + packet.options = {}; + packet.options.compress = this.flags.compress !== false; + if (typeof args[args.length - 1] === "function") { + const id = this.ids++; + debug("emitting packet with ack id %d", id); + const ack = args.pop(); + this._registerAckCallback(id, ack); + packet.id = id; + } + const isTransportWritable = (_b = (_a = this.io.engine) === null || _a === undefined ? undefined : _a.transport) === null || _b === undefined ? undefined : _b.writable; + const isConnected = this.connected && !((_c = this.io.engine) === null || _c === undefined ? undefined : _c._hasPingExpired()); + const discardPacket = this.flags.volatile && !isTransportWritable; + if (discardPacket) { + debug("discard packet as the transport is not currently writable"); + } else if (isConnected) { + this.notifyOutgoingListeners(packet); + this.packet(packet); + } else { + this.sendBuffer.push(packet); + } + this.flags = {}; + return this; + } + _registerAckCallback(id, ack) { + var _a; + const timeout = (_a = this.flags.timeout) !== null && _a !== undefined ? _a : this._opts.ackTimeout; + if (timeout === undefined) { + this.acks[id] = ack; + return; + } + const timer = this.io.setTimeoutFn(() => { + delete this.acks[id]; + for (let i = 0;i < this.sendBuffer.length; i++) { + if (this.sendBuffer[i].id === id) { + debug("removing packet with ack id %d from the buffer", id); + this.sendBuffer.splice(i, 1); + } + } + debug("event with ack id %d has timed out after %d ms", id, timeout); + ack.call(this, new Error("operation has timed out")); + }, timeout); + const fn = (...args) => { + this.io.clearTimeoutFn(timer); + ack.apply(this, args); + }; + fn.withError = true; + this.acks[id] = fn; + } + emitWithAck(ev, ...args) { + return new Promise((resolve, reject) => { + const fn = (arg1, arg2) => { + return arg1 ? reject(arg1) : resolve(arg2); + }; + fn.withError = true; + args.push(fn); + this.emit(ev, ...args); + }); + } + _addToQueue(args) { + let ack; + if (typeof args[args.length - 1] === "function") { + ack = args.pop(); + } + const packet = { + id: this._queueSeq++, + tryCount: 0, + pending: false, + args, + flags: Object.assign({ fromQueue: true }, this.flags) + }; + args.push((err, ...responseArgs) => { + if (packet !== this._queue[0]) { + return; + } + const hasError = err !== null; + if (hasError) { + if (packet.tryCount > this._opts.retries) { + debug("packet [%d] is discarded after %d tries", packet.id, packet.tryCount); + this._queue.shift(); + if (ack) { + ack(err); + } + } + } else { + debug("packet [%d] was successfully sent", packet.id); + this._queue.shift(); + if (ack) { + ack(null, ...responseArgs); + } + } + packet.pending = false; + return this._drainQueue(); + }); + this._queue.push(packet); + this._drainQueue(); + } + _drainQueue(force = false) { + debug("draining queue"); + if (!this.connected || this._queue.length === 0) { + return; + } + const packet = this._queue[0]; + if (packet.pending && !force) { + debug("packet [%d] has already been sent and is waiting for an ack", packet.id); + return; + } + packet.pending = true; + packet.tryCount++; + debug("sending packet [%d] (try n°%d)", packet.id, packet.tryCount); + this.flags = packet.flags; + this.emit.apply(this, packet.args); + } + packet(packet) { + packet.nsp = this.nsp; + this.io._packet(packet); + } + onopen() { + debug("transport is open - connecting"); + if (typeof this.auth == "function") { + this.auth((data) => { + this._sendConnectPacket(data); + }); + } else { + this._sendConnectPacket(this.auth); + } + } + _sendConnectPacket(data) { + this.packet({ + type: socket_io_parser_1.PacketType.CONNECT, + data: this._pid ? Object.assign({ pid: this._pid, offset: this._lastOffset }, data) : data + }); + } + onerror(err) { + if (!this.connected) { + this.emitReserved("connect_error", err); + } + } + onclose(reason, description) { + debug("close (%s)", reason); + this.connected = false; + delete this.id; + this.emitReserved("disconnect", reason, description); + this._clearAcks(); + } + _clearAcks() { + Object.keys(this.acks).forEach((id) => { + const isBuffered = this.sendBuffer.some((packet) => String(packet.id) === id); + if (!isBuffered) { + const ack = this.acks[id]; + delete this.acks[id]; + if (ack.withError) { + ack.call(this, new Error("socket has been disconnected")); + } + } + }); + } + onpacket(packet) { + const sameNamespace = packet.nsp === this.nsp; + if (!sameNamespace) + return; + switch (packet.type) { + case socket_io_parser_1.PacketType.CONNECT: + if (packet.data && packet.data.sid) { + this.onconnect(packet.data.sid, packet.data.pid); + } else { + this.emitReserved("connect_error", new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)")); + } + break; + case socket_io_parser_1.PacketType.EVENT: + case socket_io_parser_1.PacketType.BINARY_EVENT: + this.onevent(packet); + break; + case socket_io_parser_1.PacketType.ACK: + case socket_io_parser_1.PacketType.BINARY_ACK: + this.onack(packet); + break; + case socket_io_parser_1.PacketType.DISCONNECT: + this.ondisconnect(); + break; + case socket_io_parser_1.PacketType.CONNECT_ERROR: + this.destroy(); + const err = new Error(packet.data.message); + err.data = packet.data.data; + this.emitReserved("connect_error", err); + break; + } + } + onevent(packet) { + const args = packet.data || []; + debug("emitting event %j", args); + if (packet.id != null) { + debug("attaching ack callback to event"); + args.push(this.ack(packet.id)); + } + if (this.connected) { + this.emitEvent(args); + } else { + this.receiveBuffer.push(Object.freeze(args)); + } + } + emitEvent(args) { + if (this._anyListeners && this._anyListeners.length) { + const listeners = this._anyListeners.slice(); + for (const listener of listeners) { + listener.apply(this, args); + } + } + super.emit.apply(this, args); + if (this._pid && args.length && typeof args[args.length - 1] === "string") { + this._lastOffset = args[args.length - 1]; + } + } + ack(id) { + const self = this; + let sent = false; + return function(...args) { + if (sent) + return; + sent = true; + debug("sending ack %j", args); + self.packet({ + type: socket_io_parser_1.PacketType.ACK, + id, + data: args + }); + }; + } + onack(packet) { + const ack = this.acks[packet.id]; + if (typeof ack !== "function") { + debug("bad ack %s", packet.id); + return; + } + delete this.acks[packet.id]; + debug("calling ack %s with %j", packet.id, packet.data); + if (ack.withError) { + packet.data.unshift(null); + } + ack.apply(this, packet.data); + } + onconnect(id, pid) { + debug("socket connected with id %s", id); + this.id = id; + this.recovered = pid && this._pid === pid; + this._pid = pid; + this.connected = true; + this.emitBuffered(); + this.emitReserved("connect"); + this._drainQueue(true); + } + emitBuffered() { + this.receiveBuffer.forEach((args) => this.emitEvent(args)); + this.receiveBuffer = []; + this.sendBuffer.forEach((packet) => { + this.notifyOutgoingListeners(packet); + this.packet(packet); + }); + this.sendBuffer = []; + } + ondisconnect() { + debug("server disconnect (%s)", this.nsp); + this.destroy(); + this.onclose("io server disconnect"); + } + destroy() { + if (this.subs) { + this.subs.forEach((subDestroy) => subDestroy()); + this.subs = undefined; + } + this.io["_destroy"](this); + } + disconnect() { + if (this.connected) { + debug("performing disconnect (%s)", this.nsp); + this.packet({ type: socket_io_parser_1.PacketType.DISCONNECT }); + } + this.destroy(); + if (this.connected) { + this.onclose("io client disconnect"); + } + return this; + } + close() { + return this.disconnect(); + } + compress(compress) { + this.flags.compress = compress; + return this; + } + get volatile() { + this.flags.volatile = true; + return this; + } + timeout(timeout) { + this.flags.timeout = timeout; + return this; + } + onAny(listener) { + this._anyListeners = this._anyListeners || []; + this._anyListeners.push(listener); + return this; + } + prependAny(listener) { + this._anyListeners = this._anyListeners || []; + this._anyListeners.unshift(listener); + return this; + } + offAny(listener) { + if (!this._anyListeners) { + return this; + } + if (listener) { + const listeners = this._anyListeners; + for (let i = 0;i < listeners.length; i++) { + if (listener === listeners[i]) { + listeners.splice(i, 1); + return this; + } + } + } else { + this._anyListeners = []; + } + return this; + } + listenersAny() { + return this._anyListeners || []; + } + onAnyOutgoing(listener) { + this._anyOutgoingListeners = this._anyOutgoingListeners || []; + this._anyOutgoingListeners.push(listener); + return this; + } + prependAnyOutgoing(listener) { + this._anyOutgoingListeners = this._anyOutgoingListeners || []; + this._anyOutgoingListeners.unshift(listener); + return this; + } + offAnyOutgoing(listener) { + if (!this._anyOutgoingListeners) { + return this; + } + if (listener) { + const listeners = this._anyOutgoingListeners; + for (let i = 0;i < listeners.length; i++) { + if (listener === listeners[i]) { + listeners.splice(i, 1); + return this; + } + } + } else { + this._anyOutgoingListeners = []; + } + return this; + } + listenersAnyOutgoing() { + return this._anyOutgoingListeners || []; + } + notifyOutgoingListeners(packet) { + if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) { + const listeners = this._anyOutgoingListeners.slice(); + for (const listener of listeners) { + listener.apply(this, packet.data); + } + } + } + } + exports2.Socket = Socket; +}); + +// node_modules/socket.io-client/build/cjs/contrib/backo2.js +var require_backo2 = __commonJS((exports2) => { + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Backoff = Backoff; + function Backoff(opts) { + opts = opts || {}; + this.ms = opts.min || 100; + this.max = opts.max || 1e4; + this.factor = opts.factor || 2; + this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; + this.attempts = 0; + } + Backoff.prototype.duration = function() { + var ms = this.ms * Math.pow(this.factor, this.attempts++); + if (this.jitter) { + var rand = Math.random(); + var deviation = Math.floor(rand * this.jitter * ms); + ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; + } + return Math.min(ms, this.max) | 0; + }; + Backoff.prototype.reset = function() { + this.attempts = 0; + }; + Backoff.prototype.setMin = function(min) { + this.ms = min; + }; + Backoff.prototype.setMax = function(max) { + this.max = max; + }; + Backoff.prototype.setJitter = function(jitter) { + this.jitter = jitter; + }; +}); + +// node_modules/socket.io-client/build/cjs/manager.js +var require_manager = __commonJS((exports2) => { + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === undefined) + k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o, k2, desc); + } : function(o, m, k, k2) { + if (k2 === undefined) + k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } : function(o, v) { + o["default"] = v; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) + __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Manager = undefined; + var engine_io_client_1 = require_cjs4(); + var socket_js_1 = require_socket4(); + var parser = __importStar(require_cjs3()); + var on_js_1 = require_on(); + var backo2_js_1 = require_backo2(); + var component_emitter_1 = require_cjs2(); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("socket.io-client:manager"); + + class Manager extends component_emitter_1.Emitter { + constructor(uri, opts) { + var _a; + super(); + this.nsps = {}; + this.subs = []; + if (uri && typeof uri === "object") { + opts = uri; + uri = undefined; + } + opts = opts || {}; + opts.path = opts.path || "/socket.io"; + this.opts = opts; + (0, engine_io_client_1.installTimerFunctions)(this, opts); + this.reconnection(opts.reconnection !== false); + this.reconnectionAttempts(opts.reconnectionAttempts || Infinity); + this.reconnectionDelay(opts.reconnectionDelay || 1000); + this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000); + this.randomizationFactor((_a = opts.randomizationFactor) !== null && _a !== undefined ? _a : 0.5); + this.backoff = new backo2_js_1.Backoff({ + min: this.reconnectionDelay(), + max: this.reconnectionDelayMax(), + jitter: this.randomizationFactor() + }); + this.timeout(opts.timeout == null ? 20000 : opts.timeout); + this._readyState = "closed"; + this.uri = uri; + const _parser = opts.parser || parser; + this.encoder = new _parser.Encoder; + this.decoder = new _parser.Decoder; + this._autoConnect = opts.autoConnect !== false; + if (this._autoConnect) + this.open(); + } + reconnection(v) { + if (!arguments.length) + return this._reconnection; + this._reconnection = !!v; + if (!v) { + this.skipReconnect = true; + } + return this; + } + reconnectionAttempts(v) { + if (v === undefined) + return this._reconnectionAttempts; + this._reconnectionAttempts = v; + return this; + } + reconnectionDelay(v) { + var _a; + if (v === undefined) + return this._reconnectionDelay; + this._reconnectionDelay = v; + (_a = this.backoff) === null || _a === undefined || _a.setMin(v); + return this; + } + randomizationFactor(v) { + var _a; + if (v === undefined) + return this._randomizationFactor; + this._randomizationFactor = v; + (_a = this.backoff) === null || _a === undefined || _a.setJitter(v); + return this; + } + reconnectionDelayMax(v) { + var _a; + if (v === undefined) + return this._reconnectionDelayMax; + this._reconnectionDelayMax = v; + (_a = this.backoff) === null || _a === undefined || _a.setMax(v); + return this; + } + timeout(v) { + if (!arguments.length) + return this._timeout; + this._timeout = v; + return this; + } + maybeReconnectOnOpen() { + if (!this._reconnecting && this._reconnection && this.backoff.attempts === 0) { + this.reconnect(); + } + } + open(fn) { + debug("readyState %s", this._readyState); + if (~this._readyState.indexOf("open")) + return this; + debug("opening %s", this.uri); + this.engine = new engine_io_client_1.Socket(this.uri, this.opts); + const socket = this.engine; + const self = this; + this._readyState = "opening"; + this.skipReconnect = false; + const openSubDestroy = (0, on_js_1.on)(socket, "open", function() { + self.onopen(); + fn && fn(); + }); + const onError = (err) => { + debug("error"); + this.cleanup(); + this._readyState = "closed"; + this.emitReserved("error", err); + if (fn) { + fn(err); + } else { + this.maybeReconnectOnOpen(); + } + }; + const errorSub = (0, on_js_1.on)(socket, "error", onError); + if (this._timeout !== false) { + const timeout = this._timeout; + debug("connect attempt will timeout after %d", timeout); + const timer = this.setTimeoutFn(() => { + debug("connect attempt timed out after %d", timeout); + openSubDestroy(); + onError(new Error("timeout")); + socket.close(); + }, timeout); + if (this.opts.autoUnref) { + timer.unref(); + } + this.subs.push(() => { + this.clearTimeoutFn(timer); + }); + } + this.subs.push(openSubDestroy); + this.subs.push(errorSub); + return this; + } + connect(fn) { + return this.open(fn); + } + onopen() { + debug("open"); + this.cleanup(); + this._readyState = "open"; + this.emitReserved("open"); + const socket = this.engine; + this.subs.push((0, on_js_1.on)(socket, "ping", this.onping.bind(this)), (0, on_js_1.on)(socket, "data", this.ondata.bind(this)), (0, on_js_1.on)(socket, "error", this.onerror.bind(this)), (0, on_js_1.on)(socket, "close", this.onclose.bind(this)), (0, on_js_1.on)(this.decoder, "decoded", this.ondecoded.bind(this))); + } + onping() { + this.emitReserved("ping"); + } + ondata(data) { + try { + this.decoder.add(data); + } catch (e) { + this.onclose("parse error", e); + } + } + ondecoded(packet) { + (0, engine_io_client_1.nextTick)(() => { + this.emitReserved("packet", packet); + }, this.setTimeoutFn); + } + onerror(err) { + debug("error", err); + this.emitReserved("error", err); + } + socket(nsp, opts) { + let socket = this.nsps[nsp]; + if (!socket) { + socket = new socket_js_1.Socket(this, nsp, opts); + this.nsps[nsp] = socket; + } else if (this._autoConnect && !socket.active) { + socket.connect(); + } + return socket; + } + _destroy(socket) { + const nsps = Object.keys(this.nsps); + for (const nsp of nsps) { + const socket2 = this.nsps[nsp]; + if (socket2.active) { + debug("socket %s is still active, skipping close", nsp); + return; + } + } + this._close(); + } + _packet(packet) { + debug("writing packet %j", packet); + const encodedPackets = this.encoder.encode(packet); + for (let i = 0;i < encodedPackets.length; i++) { + this.engine.write(encodedPackets[i], packet.options); + } + } + cleanup() { + debug("cleanup"); + this.subs.forEach((subDestroy) => subDestroy()); + this.subs.length = 0; + this.decoder.destroy(); + } + _close() { + debug("disconnect"); + this.skipReconnect = true; + this._reconnecting = false; + this.onclose("forced close"); + } + disconnect() { + return this._close(); + } + onclose(reason, description) { + var _a; + debug("closed due to %s", reason); + this.cleanup(); + (_a = this.engine) === null || _a === undefined || _a.close(); + this.backoff.reset(); + this._readyState = "closed"; + this.emitReserved("close", reason, description); + if (this._reconnection && !this.skipReconnect) { + this.reconnect(); + } + } + reconnect() { + if (this._reconnecting || this.skipReconnect) + return this; + const self = this; + if (this.backoff.attempts >= this._reconnectionAttempts) { + debug("reconnect failed"); + this.backoff.reset(); + this.emitReserved("reconnect_failed"); + this._reconnecting = false; + } else { + const delay = this.backoff.duration(); + debug("will wait %dms before reconnect attempt", delay); + this._reconnecting = true; + const timer = this.setTimeoutFn(() => { + if (self.skipReconnect) + return; + debug("attempting reconnect"); + this.emitReserved("reconnect_attempt", self.backoff.attempts); + if (self.skipReconnect) + return; + self.open((err) => { + if (err) { + debug("reconnect attempt error"); + self._reconnecting = false; + self.reconnect(); + this.emitReserved("reconnect_error", err); + } else { + debug("reconnect success"); + self.onreconnect(); + } + }); + }, delay); + if (this.opts.autoUnref) { + timer.unref(); + } + this.subs.push(() => { + this.clearTimeoutFn(timer); + }); + } + } + onreconnect() { + const attempt = this.backoff.attempts; + this._reconnecting = false; + this.backoff.reset(); + this.emitReserved("reconnect", attempt); + } + } + exports2.Manager = Manager; +}); + +// node_modules/socket.io-client/build/cjs/index.js +var require_cjs5 = __commonJS((exports2, module2) => { + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WebTransport = exports2.WebSocket = exports2.NodeWebSocket = exports2.XHR = exports2.NodeXHR = exports2.Fetch = exports2.Socket = exports2.Manager = exports2.protocol = undefined; + exports2.io = lookup; + exports2.connect = lookup; + exports2.default = lookup; + var url_js_1 = require_url(); + var manager_js_1 = require_manager(); + Object.defineProperty(exports2, "Manager", { enumerable: true, get: function() { + return manager_js_1.Manager; + } }); + var socket_js_1 = require_socket4(); + Object.defineProperty(exports2, "Socket", { enumerable: true, get: function() { + return socket_js_1.Socket; + } }); + var debug_1 = __importDefault(require_src()); + var debug = (0, debug_1.default)("socket.io-client"); + var cache = {}; + function lookup(uri, opts) { + if (typeof uri === "object") { + opts = uri; + uri = undefined; + } + opts = opts || {}; + const parsed = (0, url_js_1.url)(uri, opts.path || "/socket.io"); + const source2 = parsed.source; + const id = parsed.id; + const path = parsed.path; + const sameNamespace = cache[id] && path in cache[id]["nsps"]; + const newConnection = opts.forceNew || opts["force new connection"] || opts.multiplex === false || sameNamespace; + let io; + if (newConnection) { + debug("ignoring socket cache for %s", source2); + io = new manager_js_1.Manager(source2, opts); + } else { + if (!cache[id]) { + debug("new io instance for %s", source2); + cache[id] = new manager_js_1.Manager(source2, opts); + } + io = cache[id]; + } + if (parsed.query && !opts.query) { + opts.query = parsed.queryKey; + } + return io.socket(parsed.path, opts); + } + Object.assign(lookup, { + Manager: manager_js_1.Manager, + Socket: socket_js_1.Socket, + io: lookup, + connect: lookup + }); + var socket_io_parser_1 = require_cjs3(); + Object.defineProperty(exports2, "protocol", { enumerable: true, get: function() { + return socket_io_parser_1.protocol; + } }); + var engine_io_client_1 = require_cjs4(); + Object.defineProperty(exports2, "Fetch", { enumerable: true, get: function() { + return engine_io_client_1.Fetch; + } }); + Object.defineProperty(exports2, "NodeXHR", { enumerable: true, get: function() { + return engine_io_client_1.NodeXHR; + } }); + Object.defineProperty(exports2, "XHR", { enumerable: true, get: function() { + return engine_io_client_1.XHR; + } }); + Object.defineProperty(exports2, "NodeWebSocket", { enumerable: true, get: function() { + return engine_io_client_1.NodeWebSocket; + } }); + Object.defineProperty(exports2, "WebSocket", { enumerable: true, get: function() { + return engine_io_client_1.WebSocket; + } }); + Object.defineProperty(exports2, "WebTransport", { enumerable: true, get: function() { + return engine_io_client_1.WebTransport; + } }); + module2.exports = lookup; +}); + +// server/main.js +process.env.NODE_ENV = "production"; +process.env.FORCE_COLOR = "1"; +var { Server } = require_dist2(); +var http = require("http"); +var url = require("url"); +var querystring = require("querystring"); +var path = require("path"); +var fs = require("fs"); +var { createConsola } = require_lib2(); +var { colors } = require_utils(); +var logger = createConsola({ + level: 3, + fancy: true, + formatOptions: { + date: true, + colors: true, + compact: false + } +}); +logger.wrapAll(); +var serverLogger = logger.withTag("Radio-Server"); +var server = http.createServer(); +var io = new Server(server, { + cors: { origin: "*", methods: ["GET", "POST"] } +}); +function parseBody(req) { + return new Promise((resolve, reject) => { + let body = ""; + req.on("data", (chunk) => { + body += chunk.toString(); + }); + req.on("end", () => { + try { + if (req.headers["content-type"]?.includes("application/json")) { + resolve(JSON.parse(body)); + } else if (req.headers["content-type"]?.includes("application/x-www-form-urlencoded")) { + resolve(querystring.parse(body)); + } else { + resolve(body); + } + } catch (err) { + reject(err); + } + }); + req.on("error", reject); + }); +} +async function handleRequest(req, res) { + const parsedUrl = url.parse(req.url, true); + const pathname = parsedUrl.pathname; + const method = req.method; + if (pathname.startsWith("/socket.io/")) { + return; + } + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); + res.setHeader("Access-Control-Allow-Headers", "*"); + serverLogger.trace(`CORS headers set for ${method} ${pathname}: Content-Type, Authorization, x-session-id`); + if (method === "OPTIONS") { + serverLogger.trace(`Handling OPTIONS preflight request for ${pathname}`); + res.writeHead(200); + res.end(); + return; + } + try { + if (pathname === "/" && method === "GET") { + try { + const resourcePath = GetResourcePath(GetCurrentResourceName()); + const dispatchPath = path.join(resourcePath, "server", "dispatch.html"); + fs.readFile(dispatchPath, (err, data) => { + if (err) { + serverLogger.error(`dispatch.html not found: ${dispatchPath}`); + res.writeHead(404); + res.end("Dispatch panel not found"); + return; + } + res.setHeader("Content-Type", "text/html"); + res.writeHead(200); + res.end(data); + serverLogger.debug("Served dispatch.html using fs.readFile"); + }); + } catch (error) { + serverLogger.error(`Error loading dispatch.html: ${error.message}`); + res.writeHead(500); + res.end("Error loading dispatch panel"); + } + return; + } + if ((pathname === "/favicon.ico" || pathname === "/favicon.png") && method === "GET") { + try { + const resourcePath = GetResourcePath(GetCurrentResourceName()); + const faviconPath = path.join(resourcePath, "server", "favicon.png"); + fs.readFile(faviconPath, (err, data) => { + if (err) { + serverLogger.debug(`Favicon not found: ${faviconPath}`); + res.writeHead(204); + res.end(); + return; + } + res.setHeader("Content-Type", "image/png"); + res.setHeader("Cache-Control", "public, max-age=86400"); + res.writeHead(200); + res.end(data); + }); + } catch (error) { + serverLogger.error(`Error serving favicon: ${error.message}`); + res.writeHead(204); + res.end(); + } + return; + } + if (pathname.startsWith("/audio/") && method === "GET") { + try { + const filename = pathname.split("/audio/")[1]; + const resourcePath = GetResourcePath(GetCurrentResourceName()); + const audioPath = path.join(resourcePath, "client", "radios", "default", "sounds", filename); + fs.readFile(audioPath, (err, data) => { + if (err) { + serverLogger.error(`Audio file not found: ${audioPath}`); + res.writeHead(404); + res.end("Audio file not found"); + return; + } + const extension = filename.split(".").pop().toLowerCase(); + let contentType = "audio/wav"; + switch (extension) { + case "wav": + contentType = "audio/wav"; + break; + case "mp3": + contentType = "audio/mpeg"; + break; + case "ogg": + contentType = "audio/ogg"; + break; + default: + contentType = "application/octet-stream"; + } + res.setHeader("Content-Type", contentType); + res.writeHead(200); + res.end(data); + serverLogger.debug(`Served audio file: ${filename}`); + }); + } catch (error) { + serverLogger.error(`Error serving audio file: ${error.message}`); + res.writeHead(500); + res.end("Error serving audio file"); + } + return; + } + if (pathname === "/api/health" && method === "GET") { + try { + const currentVersion = GetResourceMetadata(GetCurrentResourceName(), "version", 0) || "unknown"; + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ + status: "ok", + service: "radio-dispatch", + timestamp: new Date().toISOString(), + version: currentVersion + })); + return; + } catch (error) { + serverLogger.error(`Health check error: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: "Health check failed" })); + return; + } + } + if (pathname === "/radio/dispatch/tones" && method === "GET") { + if (!requireDispatchAuth(req, res)) + return; + try { + const resourcePath = GetResourcePath(GetCurrentResourceName()); + const tonesPath = path.join(resourcePath, "client", "radios", "default", "tones.json"); + fs.readFile(tonesPath, "utf8", (err, data) => { + if (err) { + serverLogger.error(`tones.json not found: ${tonesPath}`); + res.writeHead(404); + res.end(JSON.stringify({ error: "Tones file not found" })); + return; + } + try { + const tonesData = JSON.parse(data); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(data); + serverLogger.debug("Served tones.json"); + } catch (parseError) { + serverLogger.error(`Error parsing tones.json: ${parseError.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: "Invalid tones file format" })); + } + }); + } catch (error) { + serverLogger.error(`Error in /api/tones: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/api/status" && method === "GET") { + if (!requireDispatchAuth(req, res)) + return; + try { + const currentVersion = GetResourceMetadata(GetCurrentResourceName(), "version", 0) || "unknown"; + serverLogger.debug(`API /status called - users: ${users.size}, channels: ${channels.size}`); + const channelData = {}; + const userData = {}; + const panicStatus = {}; + const allChannelFrequencies = new Set; + if (zones && typeof zones === "object") { + Object.values(zones).forEach((zone) => { + if (zone.Channels && typeof zone.Channels === "object") { + Object.values(zone.Channels).forEach((channel) => { + if (channel.frequency) { + allChannelFrequencies.add(normalizeFrequency(channel.frequency)); + } + }); + } + }); + } + for (const [frequency, channel] of channels.entries()) { + const normalizedFreq = normalizeFrequency(frequency); + const speakers = Array.from(channel.speakers).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + const listeners = Array.from(channel.listeners).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + const activeTalkers = Array.from(channel.speakers).filter((socketId) => { + const user = users.get(socketId); + return user ? user.isTalking : false; + }).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + channelData[normalizedFreq] = { + frequency: normalizedFreq, + speakers, + listeners, + activeTalkers, + empty: false + }; + } + for (const freq of allChannelFrequencies) { + try { + const panic = GetResourceState("radio") === "started" && global.exports["radio"]["getChannelPanic"](freq); + if (panic) { + panicStatus[freq] = panic; + } + } catch (e) {} + if (panicStatus[freq] && !channelData[freq]) { + channelData[freq] = { + frequency: freq, + speakers: [], + listeners: [], + activeTalkers: [], + empty: true + }; + } + } + for (const [socketId, user] of users.entries()) { + if (user.serverId < 0) { + const dispatchInfo = dispatchUsers.get(user.serverId); + userData[user.serverId] = { + name: dispatchInfo ? dispatchInfo.callsign : "Dispatch", + nacId: dispatchInfo ? dispatchInfo.nacId : "DISPATCH", + currentChannel: user.speakerChannel, + listening: Array.from(user.listeningChannels), + isTalking: user.isTalking + }; + } else { + userData[user.serverId] = { + name: playerNames[user.serverId] || `Player ${user.serverId}`, + nacId: nacIds[user.serverId] || "Unknown", + currentChannel: user.speakerChannel, + listening: Array.from(user.listeningChannels), + isTalking: user.isTalking + }; + } + } + const response = { + userCount: users.size, + channelCount: channels.size, + channels: channelData, + users: userData, + panicStatus, + activeAlerts: activeAlerts || {}, + version: currentVersion + }; + serverLogger.debug(`Sending status: ${Object.keys(channelData).length} channels, ${Object.keys(userData).length} users`); + if (Object.keys(panicStatus).length > 0) { + serverLogger.info(`Panic active on channels: ${Object.keys(panicStatus).join(", ")}`); + } + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify(response)); + } catch (error) { + serverLogger.error(`Error in /api/status: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/api/trigger-broadcast" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { message, frequency, type } = body || {}; + if (message) { + if (frequency) { + const channel = channels.get(normalizeFrequency(frequency)); + if (channel) { + const speakers = Array.from(channel.speakers).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + const listeners = Array.from(channel.listeners).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + const allUsers = [...speakers, ...listeners]; + emit("radio:broadcastChannelAlert", parseFloat(frequency), type || "General Alert", message, allUsers); + serverLogger.info(`Dispatch alert sent to ${allUsers.length} users on frequency ${frequency}: ${message}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ + success: true, + userCount: allUsers.length, + users: allUsers + })); + } else { + res.writeHead(404); + res.end(JSON.stringify({ error: "Channel not found" })); + } + } else { + const allUsers = Array.from(users.values()).map((user) => user.serverId); + emit("radio:broadcastGlobalAlert", type || "General Alert", message, allUsers); + serverLogger.info(`Global dispatch alert sent to ${allUsers.length} users: ${message}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ + success: true, + userCount: allUsers.length, + users: allUsers + })); + } + } else { + res.writeHead(400); + res.end(JSON.stringify({ error: "Message required" })); + } + } catch (error) { + serverLogger.error(`Error triggering broadcast: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/api/play-tone" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { frequency, tone } = body || {}; + if (frequency && tone) { + const toneMap = { + beep: "BEEP", + boop: "BOOP", + chirp: "CHIRP", + panic: "PANIC", + alert_a: "ALERT_A", + alert_b: "ALERT_B", + alert_c: "ALERT_C" + }; + const radioTone = toneMap[tone.toLowerCase()] || tone.toUpperCase(); + const normalizedFreq = normalizeFrequency(frequency); + io.to(normalizedFreq.toString()).emit("serverTone", { + tone: radioTone, + frequency: normalizedFreq + }); + emit("radioServer:playToneOnChannel", normalizedFreq, radioTone); + serverLogger.debug(`Tone '${radioTone}' played on channel ${normalizedFreq}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } else { + res.writeHead(400); + res.end(JSON.stringify({ error: "Frequency and tone required" })); + } + } catch (error) { + serverLogger.error(`Error playing tone: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/alert/trigger" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { frequency, alertType, alertConfig } = body || {}; + if (frequency && alertType && alertConfig) { + const normalizedFreq = normalizeFrequency(frequency); + emit("radioServer:setAlertOnChannel", normalizedFreq, true, alertConfig, "dispatch"); + if (alertConfig.tone) { + broadcastToOtherDispatchers(req.dispatchSessionId, "dispatchNotification", { + type: "alert_activated", + frequency: normalizedFreq, + tone: alertConfig.tone, + message: `${alertType} activated on ${normalizedFreq} MHz` + }); + } + serverLogger.info(`${alertType} triggered on channel ${normalizedFreq}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } else { + res.writeHead(400); + res.end(JSON.stringify({ error: "Missing required parameters" })); + } + } catch (error) { + serverLogger.error(`Error triggering alert: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/alert/clear" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { frequency } = body || {}; + if (frequency) { + const normalizedFreq = normalizeFrequency(frequency); + const clearConfig = { + name: "CLEAR", + color: "#126300", + isPersistent: false, + tone: "ALERT_C" + }; + emit("radioServer:setAlertOnChannel", normalizedFreq, false, clearConfig, "dispatch"); + broadcastToOtherDispatchers(req.dispatchSessionId, "dispatchNotification", { + type: "alert_cleared", + frequency: normalizedFreq, + message: `Alert cleared on ${normalizedFreq} MHz` + }); + serverLogger.info(`Alert cleared on channel ${normalizedFreq}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } else { + res.writeHead(400); + res.end(JSON.stringify({ error: "Missing frequency parameter" })); + } + } catch (error) { + serverLogger.error(`Error clearing alert: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/alert/oneshot" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { frequency, alertConfig } = body || {}; + if (frequency && alertConfig) { + const normalizedFreq = normalizeFrequency(frequency); + emit("radio:dispatchOneshot", normalizedFreq, alertConfig); + if (alertConfig.tone) { + broadcastToOtherDispatchers(req.dispatchSessionId, "dispatchNotification", { + type: "oneshot_alert", + frequency: normalizedFreq, + tone: alertConfig.tone, + message: `${alertConfig.name} triggered on ${normalizedFreq} MHz` + }); + } + serverLogger.info(`One-shot ${alertConfig.name} triggered on channel ${normalizedFreq}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } else { + res.writeHead(400); + res.end(JSON.stringify({ error: "Missing required parameters" })); + } + } catch (error) { + serverLogger.error(`Error triggering one-shot alert: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/auth" && method === "POST") { + try { + const body = await parseBody(req); + const { nacId, callsign } = body || {}; + const forwardedFor = req.headers["x-forwarded-for"]; + const clientIP = req.connection.remoteAddress || req.socket.remoteAddress || (req.connection.socket ? req.connection.socket.remoteAddress : null) || (forwardedFor ? forwardedFor.split(",")[0].trim() : null) || "Unknown"; + if (nacId === dispatchNacId) { + const sessionId = `dispatch_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + authenticatedSessions.add(sessionId); + setTimeout(() => { + authenticatedSessions.delete(sessionId); + serverLogger.info(`Dispatch session expired: ${sessionId}`); + }, 24 * 60 * 60 * 1000); + serverLogger.info(`Dispatch authentication successful for NAC ID: ${nacId}, Callsign: ${callsign}, Session: ${sessionId}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ + success: true, + sessionId, + authToken + })); + } else { + serverLogger.warn(`Dispatch authentication failed for NAC ID: ${nacId}`); + res.writeHead(401); + res.end(JSON.stringify({ error: "Invalid NAC ID" })); + } + } catch (error) { + serverLogger.error(`Error in dispatch authentication: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/config" && method === "GET") { + if (!requireDispatchAuth(req, res)) + return; + try { + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ + serverPort, + authToken, + zones: zones || {}, + alerts: alerts || {}, + logLevel, + playTransmissionEffects, + analogTransmissionEffects + })); + } catch (error) { + serverLogger.error(`Error getting dispatch config: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/status" && method === "GET") { + if (!requireDispatchAuth(req, res)) + return; + try { + const channelData = {}; + const userData = {}; + for (const [frequency, channel] of channels) { + const speakerIds = Array.from(channel.speakers).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + const listenerIds = Array.from(channel.listeners).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + const activeTalkerIds = []; + for (const id of speakerIds) { + for (const [socketId, user] of users.entries()) { + if (user.serverId === id && user.isTalking) { + activeTalkerIds.push(id); + break; + } + } + } + channelData[normalizeFrequency(frequency)] = { + speakers: speakerIds, + listeners: listenerIds, + activeTalkers: activeTalkerIds + }; + } + for (const [socketId, user] of users) { + if (user.serverId) { + if (user.serverId < 0) { + const dispatchInfo = dispatchUsers.get(user.serverId); + userData[user.serverId] = { + name: dispatchInfo ? dispatchInfo.callsign : "Dispatch", + nacId: dispatchInfo ? dispatchInfo.nacId : "DISPATCH" + }; + } else if (playerNames[user.serverId]) { + userData[user.serverId] = { + name: playerNames[user.serverId], + nacId: nacIds[user.serverId] || "Unknown" + }; + } + } + } + let panicStatus = {}; + const allChannelFrequencies = new Set; + if (zones && typeof zones === "object") { + Object.values(zones).forEach((zone) => { + if (zone.Channels && typeof zone.Channels === "object") { + Object.values(zone.Channels).forEach((channel) => { + if (channel.frequency) { + allChannelFrequencies.add(normalizeFrequency(channel.frequency)); + } + }); + } + }); + } + for (const freq of allChannelFrequencies) { + try { + const panic = GetResourceState("radio") === "started" && global.exports["radio"]["getChannelPanic"](freq); + if (panic) { + panicStatus[freq] = panic; + } + } catch (e) {} + if (panicStatus[freq] && !channelData[freq]) { + channelData[freq] = { + frequency: freq, + speakers: [], + listeners: [], + activeTalkers: [], + empty: true + }; + } + } + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ + channels: channelData, + users: userData, + panicStatus, + activeAlerts: activeAlerts || {}, + serverTimestamp: Date.now() + })); + } catch (error) { + serverLogger.error(`Error getting dispatch status: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/broadcast" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { message, frequency, type, tone } = body || {}; + if (!message || !frequency) { + res.writeHead(400); + res.end(JSON.stringify({ error: "Message and frequency required" })); + return; + } + serverLogger.info(`Dispatch broadcast: ${type} alert to ${normalizeFrequency(frequency)} MHz: ${message}`); + const targetPlayerIds = []; + const baseFreq = normalizeFrequency(frequency); + let isTrunked = false; + let frequencyRange = null; + if (zones) { + for (const zone of Object.values(zones)) { + if (zone.Channels) { + for (const channel of Object.values(zone.Channels)) { + if (channel.frequency === baseFreq && channel.type === "trunked" && channel.frequencyRange) { + isTrunked = true; + frequencyRange = channel.frequencyRange; + break; + } + } + } + if (isTrunked) + break; + } + } + if (isTrunked && frequencyRange) { + const [minFreq, maxFreq] = frequencyRange; + for (const [freq, channel] of channels) { + const freqNum = parseFloat(freq); + if (freqNum >= minFreq && freqNum <= maxFreq) { + const allUsers = [...channel.speakers, ...channel.listeners]; + for (const socketId of allUsers) { + const user = users.get(socketId); + if (user && user.serverId && !targetPlayerIds.includes(user.serverId)) { + targetPlayerIds.push(user.serverId); + } + } + } + } + } else { + const channel = channels.get(normalizeFrequency(baseFreq)); + if (channel) { + const allUsers = [...channel.speakers, ...channel.listeners]; + for (const socketId of allUsers) { + const user = users.get(socketId); + if (user && user.serverId) { + targetPlayerIds.push(user.serverId); + } + } + } + } + emit("radio:dispatchBroadcast", frequency, type, message, targetPlayerIds); + if (tone && tone !== "none") { + broadcastToOtherDispatchers(req.dispatchSessionId, "dispatchNotification", { + type: "broadcast_alert", + frequency: baseFreq, + tone, + message: `Broadcast alert: ${message}` + }); + } + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } catch (error) { + serverLogger.error(`Error in dispatch broadcast: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/tone" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { frequency, tone } = body || {}; + if (!frequency || !tone) { + res.writeHead(400); + res.end(JSON.stringify({ error: "Frequency and tone required" })); + return; + } + const normalizedFreq = normalizeFrequency(frequency); + serverLogger.debug(`Dispatch tone: ${tone} on ${normalizedFreq} MHz`); + emit("radio:dispatchTone", normalizedFreq, tone, []); + broadcastToOtherDispatchers(req.dispatchSessionId, "dispatchNotification", { + type: "tone_triggered", + frequency: normalizedFreq, + tone, + message: `Tone ${tone} triggered on ${normalizedFreq} MHz` + }); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } catch (error) { + serverLogger.error(`Error in dispatch tone: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/radio/dispatch/switchChannel" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { serverId, frequency, oldFrequency } = body || {}; + if (!serverId || !frequency) { + res.writeHead(400); + res.end(JSON.stringify({ error: "Server ID and frequency required" })); + return; + } + const normalizedFreq = normalizeFrequency(frequency); + serverLogger.debug(`Dispatch channel switch: User ${serverId} from ${oldFrequency || "unknown"} to ${normalizedFreq} MHz`); + try { + const result = global.exports["radio"]["setUserChannel"](serverId, normalizedFreq); + if (result) { + serverLogger.debug(`Successfully moved user ${serverId} to channel ${normalizedFreq}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } else { + serverLogger.error(`Failed to move user ${serverId}: Invalid channel ${normalizedFreq}`); + res.writeHead(500); + res.end(JSON.stringify({ error: "Channel switch failed" })); + } + } catch (exportError) { + serverLogger.error(`Error calling setUserChannel export: ${exportError.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: "Radio export error" })); + } + } catch (error) { + serverLogger.error(`Error in dispatch channel switch: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/dispatch/user/alert" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { userId, message, frequency } = body || {}; + if (!userId || !message) { + res.writeHead(400); + res.end(JSON.stringify({ error: "User ID and message required" })); + return; + } + serverLogger.info(`Dispatch sending alert to user ${userId}: ${message}`); + emit("radio:dispatchUserAlert", userId, message, frequency || null); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } catch (error) { + serverLogger.error(`Error moving user: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/dispatch/user/disconnect" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { userId } = body || {}; + if (!userId) { + res.writeHead(400); + res.end(JSON.stringify({ error: "User ID required" })); + return; + } + serverLogger.info(`Dispatch disconnecting user ${userId}`); + try { + const result = global.exports["radio"]["disconnectUser"](userId); + if (result) { + serverLogger.info(`Successfully disconnected user ${userId}`); + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ success: true })); + } else { + serverLogger.error(`Failed to disconnect user ${userId}`); + res.writeHead(500); + res.end(JSON.stringify({ error: "Disconnect failed" })); + } + } catch (exportError) { + serverLogger.error(`Error calling disconnectUser export: ${exportError.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: "Radio export error" })); + } + } catch (error) { + serverLogger.error(`Error disconnecting user: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + if (pathname === "/dispatch/user/update-callsign" && method === "POST") { + if (!requireDispatchAuth(req, res)) + return; + try { + const body = await parseBody(req); + const { callsign, userId } = body || {}; + if (!callsign || !callsign.trim()) { + res.writeHead(400); + res.end(JSON.stringify({ error: "Callsign required" })); + return; + } + const trimmedCallsign = callsign.trim(); + let targetUserId = userId; + if (!targetUserId) { + for (const [socketId, user] of users) { + if (user.serverId < 0) { + targetUserId = user.serverId; + break; + } + } + } + if (!targetUserId) { + res.writeHead(404); + res.end(JSON.stringify({ error: "No dispatch user found" })); + return; + } + if (targetUserId >= 0) { + res.writeHead(400); + res.end(JSON.stringify({ error: "Invalid dispatch user ID" })); + return; + } + const existingDispatchInfo = dispatchUsers.get(targetUserId); + if (existingDispatchInfo) { + const oldCallsign = existingDispatchInfo.callsign; + existingDispatchInfo.callsign = trimmedCallsign; + dispatchUsers.set(targetUserId, existingDispatchInfo); + serverLogger.info(`Updated dispatch user ${targetUserId} callsign from "${oldCallsign}" to "${trimmedCallsign}"`); + } else { + dispatchUsers.set(targetUserId, { + callsign: trimmedCallsign, + nacId: "DISPATCH" + }); + serverLogger.info(`Created new dispatch user ${targetUserId} with callsign "${trimmedCallsign}"`); + } + res.setHeader("Content-Type", "application/json"); + res.writeHead(200); + res.end(JSON.stringify({ + success: true, + callsign: trimmedCallsign, + userId: targetUserId + })); + } catch (error) { + serverLogger.error(`Error updating callsign: ${error.message}`); + res.writeHead(500); + res.end(JSON.stringify({ error: error.message })); + } + return; + } + res.writeHead(404); + res.end("Not Found"); + } catch (error) { + serverLogger.error(`Server error: ${error.message}`); + res.writeHead(500); + res.end("Internal Server Error"); + } +} +server.on("request", handleRequest); +var logLevel = 1; +var host = ""; +var authToken = "radio"; +var enableLoopbackTesting = false; +var doUpdateCheck = true; +global.radioLogger = serverLogger; +global.createRadioLogger = (tag) => serverLogger.withTag(tag); +var channels = new Map; +var users = new Map; +var dispatchUsers = new Map; +var authenticatedSessions = new Set; +var dispatchSessions = new Map; +function broadcastToOtherDispatchers(sessionId, event, data) { + const senderSocketId = dispatchSessions.get(sessionId); + for (const [socketId, socket] of io.sockets.sockets) { + const user = users.get(socketId); + if (user && user.serverId < 0 && socketId !== senderSocketId) { + socket.emit(event, data); + } + } +} +function normalizeFrequency(frequency) { + if (typeof frequency === "string") { + frequency = parseFloat(frequency); + } + if (typeof frequency !== "number" || isNaN(frequency)) { + throw new Error(`Invalid frequency: ${frequency}. Frequency must be a valid number.`); + } + return Math.round(frequency * 1e4) / 1e4; +} +function getOrCreateChannel(frequency) { + frequency = normalizeFrequency(frequency); + if (!channels.has(frequency)) { + channels.set(frequency, { + speakers: new Set, + listeners: new Set + }); + } + return channels.get(frequency); +} +function checkEmptyChannel(frequency) { + frequency = normalizeFrequency(frequency); + const channel = channels.get(frequency); + if (channel && channel.speakers.size === 0 && channel.listeners.size === 0) { + channels.delete(frequency); + io.emit("channelDeleted", frequency); + serverLogger.debug(`Channel ${normalizeFrequency(frequency)} deleted - no participants left`); + } +} +function broadcastChannelState(frequency) { + frequency = normalizeFrequency(frequency); + let channelState = { + frequency, + speakers: [], + listeners: [], + activeTalkers: [], + empty: true + }; + const channel = channels.get(frequency); + if (channel) { + const speakerIds = Array.from(channel.speakers).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + const listenerIds = Array.from(channel.listeners).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + const activeTalkers = Array.from(channel.speakers).filter((socketId) => { + const user = users.get(socketId); + return user ? user.isTalking : false; + }).map((socketId) => { + const user = users.get(socketId); + return user ? user.serverId : null; + }).filter(Boolean); + channelState = { + frequency, + speakers: speakerIds, + listeners: listenerIds, + activeTalkers, + empty: false + }; + } + io.emit("channelState", channelState); + emitNet("radio:channelState", -1, channelState); + emit("radio:channelState", channelState); +} +io.use((socket, next) => { + const { authToken: clientToken, serverId } = socket.handshake.auth; + if (clientToken === "health-check-test" && serverId === -9999) { + socket.serverId = serverId; + socket.isHealthCheck = true; + return next(); + } + if (clientToken !== authToken) { + return next(new Error("Invalid authentication")); + } + socket.serverId = serverId; + next(); +}); +io.on("connection", (socket) => { + const isDispatch = socket.serverId < 0; + if (socket.isHealthCheck) { + serverLogger.debug("Health check Socket.IO connection established and verified"); + socket.disconnect(); + return; + } + if (isDispatch) { + serverLogger.info(`Dispatch user connecting with ID: ${socket.serverId}`); + } + users.set(socket.id, { + serverId: socket.serverId, + speakerChannel: null, + listeningChannels: new Set, + listeningToUsers: new Set, + listenedByUsers: new Set, + isTalking: false + }); + socket.on("setDispatchSession", (sessionId) => { + if (socket.serverId < 0 && sessionId) { + dispatchSessions.set(sessionId, socket.id); + serverLogger.debug(`Mapped dispatch session ${sessionId} to socket ${socket.id}`); + } + }); + socket.on("heartbeat", (clientTime) => { + socket.emit("heartbeat_response", Date.now()); + }); + socket.on("updateUserInfo", (data) => { + if (socket.serverId < 0 && data.name) { + dispatchUsers.set(socket.serverId, { + callsign: data.name, + nacId: data.nacId || "DISPATCH" + }); + serverLogger.debug(`Updated dispatch user info: ${socket.serverId} -> ${data.name}`); + } + }); + socket.on("disconnect", () => { + for (const [sessionId, socketId] of dispatchSessions.entries()) { + if (socketId === socket.id) { + dispatchSessions.delete(sessionId); + serverLogger.debug(`Cleaned up dispatch session ${sessionId} for disconnected socket`); + break; + } + } + const user = users.get(socket.id); + if (user && user.serverId < 0) { + dispatchUsers.delete(user.serverId); + serverLogger.debug(`Cleaned up dispatch user info for: ${user.serverId}`); + } + users.delete(socket.id); + }); + const serverId = socket.serverId; + if (serverId) { + try { + const playerName = GetPlayerName(serverId); + if (playerName && playerName !== "") { + playerNames[serverId] = playerName; + serverLogger.debug(`Auto-fetched player name: ${serverId} -> ${playerName}`); + } + emit("radio:requestPlayerData", serverId); + } catch (error) { + serverLogger.error(`Error auto-fetching player name for ${serverId}: ${error.message}`); + } + } + socket.on("setSpeakerChannel", (frequency) => { + const user = users.get(socket.id); + if (frequency) { + frequency = normalizeFrequency(frequency); + } + const isSameChannel = user.speakerChannel && frequency && normalizeFrequency(user.speakerChannel) === normalizeFrequency(frequency); + if (user.speakerChannel && !isSameChannel) { + if (user.isTalking) { + user.isTalking = false; + const data = { + serverId: user.serverId, + frequency: user.speakerChannel, + state: false + }; + io.to(user.speakerChannel.toString()).emit("talkingState", data); + emit("radio:talkerState", data); + emitNet("radio:talkerState", -1, data); + } + const oldChannel = getOrCreateChannel(user.speakerChannel); + oldChannel.speakers.delete(socket.id); + socket.leave(user.speakerChannel.toString()); + io.to(user.speakerChannel.toString()).emit("speakerLeft", { + serverId: user.serverId, + frequency: user.speakerChannel + }); + checkEmptyChannel(user.speakerChannel); + broadcastChannelState(user.speakerChannel); + } + if (frequency) { + const channel = getOrCreateChannel(frequency); + channel.speakers.add(socket.id); + socket.join(frequency.toString()); + user.speakerChannel = frequency; + if (!isSameChannel) { + io.to(frequency.toString()).emit("speakerJoined", { + serverId: user.serverId, + frequency + }); + } + broadcastChannelState(frequency); + } else { + user.speakerChannel = null; + } + }); + socket.on("addListeningChannel", (frequency) => { + frequency = normalizeFrequency(frequency); + const user = users.get(socket.id); + const channel = getOrCreateChannel(frequency); + if (!user.listeningChannels.has(frequency)) { + channel.listeners.add(socket.id); + socket.join(frequency.toString()); + user.listeningChannels.add(frequency); + io.to(frequency.toString()).emit("listenerJoined", { + serverId: user.serverId, + frequency + }); + broadcastChannelState(frequency); + } + }); + socket.on("removeListeningChannel", (frequency) => { + frequency = normalizeFrequency(frequency); + const user = users.get(socket.id); + const channel = channels.get(frequency); + if (channel && user.listeningChannels.has(frequency)) { + channel.listeners.delete(socket.id); + socket.leave(frequency.toString()); + user.listeningChannels.delete(frequency); + io.to(frequency.toString()).emit("listenerLeft", { + serverId: user.serverId, + frequency + }); + checkEmptyChannel(frequency); + broadcastChannelState(frequency); + } + }); + socket.on("listenToUser", (targetServerId) => { + const listener = users.get(socket.id); + const targetSocket = Array.from(users.entries()).find(([_, user]) => user.serverId === targetServerId); + if (targetSocket) { + const [targetSocketId, targetUser] = targetSocket; + listener.listeningToUsers.add(targetSocketId); + targetUser.listenedByUsers.add(socket.id); + io.to(targetSocketId).emit("userStartedListening", { + serverId: listener.serverId + }); + } + }); + socket.on("add3DListening", (frequency) => { + const user = users.get(socket.id); + if (!user) + return; + frequency = normalizeFrequency(frequency); + serverLogger.debug(`Adding 3D listening for user ${user.serverId} to frequency ${frequency}`); + if (!user.temp3DChannels) { + user.temp3DChannels = new Set; + } + user.temp3DChannels.add(frequency); + }); + socket.on("remove3DListening", (frequency) => { + const user = users.get(socket.id); + if (!user || !user.temp3DChannels) + return; + frequency = normalizeFrequency(frequency); + serverLogger.debug(`Removing 3D listening for user ${user.serverId} from frequency ${frequency}`); + user.temp3DChannels.delete(frequency); + }); + socket.on("stopListeningToUser", (targetServerId) => { + const listener = users.get(socket.id); + const targetSocket = Array.from(users.entries()).find(([_, user]) => user.serverId === targetServerId); + if (targetSocket) { + const [targetSocketId, targetUser] = targetSocket; + listener.listeningToUsers.delete(targetSocketId); + targetUser.listenedByUsers.delete(socket.id); + io.to(targetSocketId).emit("userStoppedListening", { + serverId: listener.serverId + }); + } + }); + socket.on("setTalking", (state) => { + const user = users.get(socket.id); + if (user.speakerChannel && user.isTalking !== state) { + user.isTalking = state; + const data = { + serverId: user.serverId, + frequency: user.speakerChannel, + state + }; + io.to(user.speakerChannel.toString()).emit("talkingState", data); + emit("radio:talkerState", data); + emitNet("radio:talkerState", -1, data); + broadcastChannelState(user.speakerChannel); + } + }); + socket.on("voice", (data) => { + const user = users.get(socket.id); + serverLogger.debug(`User ${user.serverId} sending voice on speakerChannel: ${user.speakerChannel}`); + serverLogger.debug(`Voice data received: ${JSON.stringify({ + hasData: !!data, + hasDataField: !!(data && data.data), + dataKeys: data ? Object.keys(data) : [], + userSpeakerChannel: user ? user.speakerChannel : null, + isDispatch: user && user.serverId < 0, + dataLength: data && data.data ? data.data.length : 0 + })}`); + if (user.speakerChannel && data && data.data) { + const channel = channels.get(user.speakerChannel); + serverLogger.debug(`Found channel for ${user.speakerChannel}: ${channel ? "YES" : "NO"}`); + if (channel) { + serverLogger.debug(`Channel ${user.speakerChannel} has ${channel.speakers.size} speakers and ${channel.listeners.size} listeners`); + serverLogger.debug(`Speakers: ${Array.from(channel.speakers).map((id) => { + const user2 = users.get(id); + return user2 ? user2.serverId : null; + }).join(", ")}`); + serverLogger.debug(`Listeners: ${Array.from(channel.listeners).map((id) => { + const user2 = users.get(id); + return user2 ? user2.serverId : null; + }).join(", ")}`); + if (enableLoopbackTesting) { + setTimeout(() => { + socket.emit("voice", { + serverId: user.serverId + 1000, + frequency: user.speakerChannel, + data: data.data, + receiveType: "loopback" + }); + }, 5000); + } + const channelParticipants = new Set([ + ...channel.speakers, + ...channel.listeners + ]); + serverLogger.debug(`Total channel participants: ${channelParticipants.size}`); + const userListeners = new Map; + for (const receiverId of channelParticipants) { + const receiver = users.get(receiverId); + if (receiver) { + receiver.listenedByUsers.forEach((listenerId) => { + userListeners.set(listenerId, { + listenerId, + targetServerId: receiver.serverId + }); + }); + } + } + for (const socketId of channelParticipants) { + const receiveType = channel.speakers.has(socketId) ? "speaker" : "listener"; + const participant = users.get(socketId); + serverLogger.debug(`Sending voice to ${participant ? participant.serverId : "unknown"} as ${receiveType}`); + io.to(socketId).emit("voice", { + serverId: user.serverId, + frequency: user.speakerChannel, + data: data.data, + receiveType + }); + serverLogger.debug(`Sent voice from dispatch ${user.serverId} to ${participant ? participant.serverId : "unknown"} on freq ${user.speakerChannel}`); + } + for (const [socketId, listenerInfo] of userListeners) { + io.to(socketId).emit("voice", { + serverId: user.serverId, + frequency: user.speakerChannel, + data: data.data, + receiveType: "userListener", + targetServerId: listenerInfo.targetServerId + }); + } + for (const [socketId, tempUser] of users) { + if (tempUser.temp3DChannels && tempUser.temp3DChannels.has(user.speakerChannel)) { + serverLogger.debug(`Sending voice to 3D listener ${tempUser.serverId} on frequency ${user.speakerChannel}`); + io.to(socketId).emit("voice", { + serverId: user.serverId, + frequency: user.speakerChannel, + data: data.data, + receiveType: "3DAudio" + }); + } + } + } + } else { + serverLogger.warn(`Voice data rejected: userSpeakerChannel=${user ? user.speakerChannel : "no user"}, hasData=${!!(data && data.data)}`); + } + }); + socket.on("disconnect", () => { + const user = users.get(socket.id); + if (user) { + if (user.speakerChannel) { + const channel = channels.get(user.speakerChannel); + if (channel) { + channel.speakers.delete(socket.id); + io.to(user.speakerChannel.toString()).emit("speakerLeft", { + serverId: user.serverId, + frequency: user.speakerChannel + }); + checkEmptyChannel(user.speakerChannel); + broadcastChannelState(user.speakerChannel); + } + } + for (const frequency of user.listeningChannels) { + const channel = channels.get(frequency); + if (channel) { + channel.listeners.delete(socket.id); + io.to(frequency.toString()).emit("listenerLeft", { + serverId: user.serverId, + frequency + }); + checkEmptyChannel(frequency); + broadcastChannelState(frequency); + } + } + user.listeningToUsers.forEach((targetSocketId) => { + const targetUser = users.get(targetSocketId); + if (targetUser) { + targetUser.listenedByUsers.delete(socket.id); + io.to(targetSocketId).emit("userStoppedListening", { + serverId: user.serverId + }); + } + }); + user.listenedByUsers.forEach((listenerSocketId) => { + const listenerUser = users.get(listenerSocketId); + if (listenerUser) { + listenerUser.listeningToUsers.delete(socket.id); + } + }); + users.delete(socket.id); + } + }); +}); +function getPublicIP() { + return new Promise((resolve) => { + const https = require("https"); + https.get("https://api.ipify.org", (resp) => { + let data = ""; + resp.on("data", (chunk) => { + data += chunk; + }); + resp.on("end", () => { + resolve(data.trim()); + }); + }).on("error", () => { + resolve(null); + }); + }); +} +function requireDispatchAuth(req, res) { + const authHeader = req.headers.authorization; + const sessionId = req.headers["x-session-id"]; + let providedToken = null; + if (authHeader && authHeader.startsWith("Bearer ")) { + providedToken = authHeader.substring(7); + } + if (!providedToken || providedToken !== authToken) { + res.writeHead(401); + res.end(JSON.stringify({ error: "Authentication required" })); + return false; + } + if (!sessionId || !authenticatedSessions.has(sessionId)) { + res.writeHead(401); + res.end(JSON.stringify({ error: "Invalid or expired session" })); + return false; + } + req.dispatchSessionId = sessionId; + return true; +} +var serverPort = 7777; +var zones = {}; +var alerts = {}; +var activeAlerts = {}; +var playerNames = {}; +var nacIds = {}; +var playTransmissionEffects = true; +var analogTransmissionEffects = false; +var dispatchNacId = "911"; +function buildSmartUrl(hostParam, port) { + if (!hostParam || hostParam === "") { + return null; + } + if (hostParam.startsWith("http://") || hostParam.startsWith("https://")) { + const hostPart = hostParam.replace(/^https?:\/\//, ""); + if (hostPart.includes(":")) { + return hostParam; + } + if (/^\d+\.\d+\.\d+\.\d+/.test(hostPart)) { + return `${hostParam}:${port}`; + } + return hostParam; + } + if (/^\d+\.\d+\.\d+\.\d+:\d+$/.test(hostParam)) { + return `http://${hostParam}`; + } + const isDomain = /^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/.test(hostParam) && !/^\d+\.\d+\.\d+\.\d+/.test(hostParam); + if (isDomain) { + return `https://${hostParam}`; + } + if (/^\d+\.\d+\.\d+\.\d+$/.test(hostParam)) { + return `http://${hostParam}:${port}`; + } + return `http://${hostParam}:${port}`; +} +async function testConnection(url2, retryCount = 0, maxRetries = 3) { + return new Promise(async (resolve) => { + const http2 = require("http"); + const https = require("https"); + const { URL } = require("url"); + let httpResult = null; + let socketResult = null; + try { + const parsedUrl = new URL(url2); + const client = parsedUrl.protocol === "https:" ? https : http2; + const options = { + hostname: parsedUrl.hostname, + port: parsedUrl.port || (parsedUrl.protocol === "https:" ? 443 : 80), + path: "/", + method: "GET", + timeout: 8000 + }; + httpResult = await new Promise((httpResolve) => { + const req = client.request(options, (res) => { + httpResolve({ success: true, status: res.statusCode }); + }); + req.on("error", (err) => { + httpResolve({ success: false, error: err.message }); + }); + req.on("timeout", () => { + req.destroy(); + httpResolve({ success: false, error: "HTTP connection timeout" }); + }); + req.end(); + }); + } catch (err) { + httpResult = { success: false, error: err.message }; + } + try { + const ioClient = require_cjs5(); + socketResult = await new Promise((socketResolve) => { + const testSocket = ioClient(url2, { + timeout: 8000, + reconnection: false, + auth: { + authToken: "health-check-test", + serverId: -9999 + } + }); + const timeoutId = setTimeout(() => { + testSocket.disconnect(); + socketResolve({ success: false, error: "Socket connection timeout" }); + }, 8000); + testSocket.on("connect", () => { + clearTimeout(timeoutId); + testSocket.disconnect(); + socketResolve({ success: true }); + }); + testSocket.on("connect_error", (err) => { + clearTimeout(timeoutId); + testSocket.disconnect(); + socketResolve({ + success: false, + error: `Socket connection failed: ${err.message || err.toString()}` + }); + }); + }); + } catch (err) { + socketResult = { + success: false, + error: `Socket test failed: ${err.message}` + }; + } + const overallSuccess = httpResult.success && socketResult.success; + if (!overallSuccess && retryCount < maxRetries) { + const delay = Math.min(1000 * Math.pow(2, retryCount), 5000); + serverLogger.debug(`Health check attempt ${retryCount + 1}/${maxRetries + 1} failed, retrying in ${delay}ms...`); + await new Promise((wait) => setTimeout(wait, delay)); + const retryResult = await testConnection(url2, retryCount + 1, maxRetries); + resolve(retryResult); + return; + } + let errorMessage = `Started - Health Checks Failed +`; + if (!httpResult.success) { + errorMessage += `${colors.white("HTTP:")} ${colors.red(httpResult.error)}`; + } + if (!socketResult.success) { + if (errorMessage) + errorMessage += ` +`; + errorMessage += `${colors.white("Socket:")} ${colors.red(socketResult.error)}`; + } + resolve({ + success: overallSuccess, + error: errorMessage || null, + httpResult, + socketResult, + attempts: retryCount + 1 + }); + }); +} +async function checkForUpdates() { + const UPDATE_URL = "https://git.timmygstudios.com/api/v1/repos/tommy/fivem-radio/wiki/page/Tommy%27s-Radio-Changelog"; + const CURRENT_VERSION = GetResourceMetadata(GetCurrentResourceName(), "version", 0) || "unknown"; + serverLogger.debug(`Checking for updates - Current version: ${CURRENT_VERSION}`); + serverLogger.debug(`Fetching changelog from: ${UPDATE_URL}`); + try { + const https = require("https"); + const { URL } = require("url"); + return new Promise((resolve) => { + const parsedUrl = new URL(UPDATE_URL); + const options = { + hostname: parsedUrl.hostname, + port: 443, + path: parsedUrl.pathname + parsedUrl.search, + method: "GET", + timeout: 1e4, + headers: { + "User-Agent": "Tommy's Radio Update Checker/2.0", + Accept: "application/json" + } + }; + const req = https.request(options, (res) => { + let data = ""; + res.on("data", (chunk) => { + data += chunk; + }); + res.on("end", () => { + if (res.statusCode === 200) { + try { + const apiResponse = JSON.parse(data); + serverLogger.debug(`API response received, title: ${apiResponse.title || "unknown"}`); + if (!apiResponse.content_base64) { + serverLogger.debug("No content_base64 found in API response"); + resolve({ + success: false, + hasUpdate: false, + latestVersion: null, + missingChangelogs: null, + error: "No content found in API response" + }); + return; + } + const changelogContent = Buffer.from(apiResponse.content_base64, "base64").toString("utf-8"); + serverLogger.debug(`Decoded changelog content length: ${changelogContent.length}`); + const changelog = parseChangelog(changelogContent); + if (changelog) { + const latestVersion = getLatestVersion(changelog); + const hasUpdate = isNewerVersion(latestVersion, CURRENT_VERSION); + serverLogger.debug(`Latest version found: ${latestVersion}, has update: ${hasUpdate}`); + const missingChangelogs = hasUpdate ? getMissingChangelogs(changelog, CURRENT_VERSION) : null; + resolve({ + success: true, + hasUpdate, + latestVersion, + missingChangelogs, + error: null + }); + } else { + serverLogger.debug("Failed to parse changelog content"); + resolve({ + success: false, + hasUpdate: false, + latestVersion: null, + missingChangelogs: null, + error: "Failed to parse changelog" + }); + } + } catch (parseError) { + serverLogger.debug(`Parse error: ${parseError.message}`); + resolve({ + success: false, + hasUpdate: false, + latestVersion: null, + missingChangelogs: null, + error: `Failed to parse API response: ${parseError.message}` + }); + } + } else { + serverLogger.debug(`HTTP error: ${res.statusCode}`); + resolve({ + success: false, + hasUpdate: false, + latestVersion: null, + missingChangelogs: null, + error: `HTTP ${res.statusCode}` + }); + } + }); + }); + req.on("error", (err) => { + resolve({ + success: false, + hasUpdate: false, + latestVersion: null, + missingChangelogs: null, + error: err.message + }); + }); + req.on("timeout", () => { + req.destroy(); + resolve({ + success: false, + hasUpdate: false, + latestVersion: null, + missingChangelogs: null, + error: "Connection timeout" + }); + }); + req.end(); + }); + } catch (err) { + return { + success: false, + hasUpdate: false, + latestVersion: null, + missingChangelogs: null, + error: err.message + }; + } +} +function parseChangelog(markdownContent) { + try { + const changelog = {}; + const lines = markdownContent.split(` +`).filter((line) => line.trim() !== ""); + serverLogger.debug(`Parsing changelog with ${lines.length} lines`); + let currentVersion = null; + let currentChanges = []; + let versionsFound = 0; + for (const line of lines) { + const versionMatch = line.match(/^###\s+(\d+\/\d+\/\d+)\s*-\s*(v[\d.]+)/); + if (versionMatch) { + if (currentVersion) { + changelog[currentVersion.version] = { + date: currentVersion.date, + version: currentVersion.version, + changes: currentChanges.join(` +`) + }; + versionsFound++; + } + currentVersion = { version: versionMatch[2], date: versionMatch[1] }; + currentChanges = []; + serverLogger.debug(`Found version: ${versionMatch[2]} from ${versionMatch[1]}`); + } else if (line.startsWith("*") && currentVersion) { + currentChanges.push(line); + } + } + if (currentVersion) { + changelog[currentVersion.version] = { + date: currentVersion.date, + version: currentVersion.version, + changes: currentChanges.join(` +`) + }; + versionsFound++; + } + serverLogger.debug(`Parsed ${versionsFound} versions from changelog`); + return changelog; + } catch (err) { + serverLogger.error(`Error parsing changelog: ${err.message}`); + return null; + } +} +function getLatestVersion(changelog) { + let latestVersion = null; + let latestParsed = [0, 0, 0]; + for (const version in changelog) { + const parsed = parseVersion(version); + if (compareVersions(parsed, latestParsed) > 0) { + latestVersion = version; + latestParsed = parsed; + } + } + return latestVersion; +} +function parseVersion(versionStr) { + if (!versionStr || versionStr === "unknown") + return [0, 0, 0]; + const cleanVersion = versionStr.replace(/^v/, ""); + const parts = cleanVersion.split(".").map((part) => parseInt(part) || 0); + while (parts.length < 3) { + parts.push(0); + } + return parts; +} +function compareVersions(version1, version2) { + for (let i = 0;i < Math.max(version1.length, version2.length); i++) { + const v1 = version1[i] || 0; + const v2 = version2[i] || 0; + if (v1 < v2) + return -1; + if (v1 > v2) + return 1; + } + return 0; +} +function isNewerVersion(latestVersion, currentVersion) { + const latestParsed = parseVersion(latestVersion); + const currentParsed = parseVersion(currentVersion); + return compareVersions(currentParsed, latestParsed) < 0; +} +function getMissingChangelogs(changelog, currentVersion) { + const currentParsed = parseVersion(currentVersion); + const missing = []; + for (const version in changelog) { + const versionParsed = parseVersion(version); + if (compareVersions(versionParsed, currentParsed) > 0) { + missing.push({ + version, + date: changelog[version].date, + changes: changelog[version].changes + }); + } + } + missing.sort((a, b) => { + const aParsed = parseVersion(a.version); + const bParsed = parseVersion(b.version); + return compareVersions(aParsed, bParsed) * -1; + }); + return missing; +} +function checkFxVersion() { + try { + const fxVersion = GetResourceMetadata(GetCurrentResourceName(), "fx_version", 0) || "unknown"; + const isValid = fxVersion === "bodacious"; + serverLogger.debug(`FX Version check: ${fxVersion} (valid: ${isValid})`); + return { + fxVersion, + isValid + }; + } catch (error) { + serverLogger.error(`Error checking fx_version: ${error.message}`); + return { + fxVersion: "error", + isValid: false + }; + } +} +var startupInfo = { + hasError: false, + errorMessage: "", + dispatchUrl: "", + zoneCount: 0, + channelCount: 0, + dispatchNacId: "", + serverStarted: false, + connectionWarning: "", + configReceived: false, + connectionTested: false +}; +var startupComplete = false; +var pendingUpdateResult = null; +var displayTimer = null; +var displayReady = false; +var DISPLAY_DELAY = 1000; +function checkStartupCompletion() { + if (startupInfo.serverStarted && startupInfo.configReceived && startupInfo.connectionTested && !startupComplete && displayReady) { + startupComplete = true; + displayStartupInfo(pendingUpdateResult); + } +} +function startDisplayTimer() { + if (displayTimer) { + clearTimeout(displayTimer); + } + displayTimer = setTimeout(() => { + displayReady = true; + checkStartupCompletion(); + }, DISPLAY_DELAY); +} +function displayServerStatus(updateResult) { + const currentVersion = GetResourceMetadata(GetCurrentResourceName(), "version", 0) || "unknown"; + const fxVersionCheck = checkFxVersion(); + let title = `${colors.green("✅ Tommy's Radio - System Ready")}`; + let versionText = `${colors.white("Version:")} ${colors.magenta(currentVersion)}`; + if (!fxVersionCheck.isValid) { + title = `${colors.red("❌ Tommy's Radio - Invalid Setup")}`; + } + if (doUpdateCheck && updateResult) { + if (!updateResult.success) { + versionText = `${colors.white("Version:")} ${colors.red(currentVersion + " - Update Check Failed")}`; + } else if (updateResult.hasUpdate && updateResult.latestVersion) { + if (fxVersionCheck.isValid) { + title = `${colors.yellow("\uD83D\uDD04 Tommy's Radio - Update Available")}`; + } + versionText = `${colors.white("Version:")} ${colors.magenta(currentVersion)} ${colors.white("->")} ${colors.green(updateResult.latestVersion)}`; + } + } + let statusText = `${colors.white("Status:")} ${colors.green("Server started successfully")}`; + if (startupInfo.connectionWarning !== "") { + statusText = `${colors.white("Status:")} ${colors.red(startupInfo.connectionWarning)}`; + } + if (!fxVersionCheck.isValid) { + statusText = `${colors.white("Status:")} ${colors.red("INVALID SETUP - fx_version must be set to 'bodacious'")}`; + } + let boxContent = [title, "", versionText, statusText]; + if (startupInfo.dispatchUrl !== "") { + boxContent.push(`${colors.white("Panel:")} ${colors.cyan(startupInfo.dispatchUrl)}`); + } + if (startupInfo.dispatchNacId !== "") { + boxContent.push(`${colors.white("NAC ID:")} ${colors.green(startupInfo.dispatchNacId)}`); + } + const fxVersionColor = fxVersionCheck.isValid ? colors.green : colors.red; + boxContent.push(`${colors.white("FX Ver:")} ${fxVersionColor(fxVersionCheck.fxVersion)}`); + if (!fxVersionCheck.isValid) { + boxContent.push("", `${colors.red("⚠️ SETUP ERROR:")}`, `${colors.yellow("The fx_version in fxmanifest.lua must be set to 'bodacious'")}`, `${colors.yellow("Current value: '")}${colors.red(fxVersionCheck.fxVersion)}${colors.yellow("'")}`, ""); + } + const configItems = []; + if (startupInfo.zoneCount > 0) { + configItems.push(`${colors.green(startupInfo.zoneCount)} zones`); + } + if (startupInfo.channelCount > 0) { + configItems.push(`${colors.green(startupInfo.channelCount)} channels`); + } + if (configItems.length > 0) { + boxContent.push(`${colors.white("Config:")} ${configItems.join(", ")}`); + } + if (doUpdateCheck && updateResult && updateResult.hasUpdate && updateResult.missingChangelogs && updateResult.missingChangelogs.length > 0) { + boxContent.push("", `${colors.white("\uD83D\uDCCB Changelog:")}`, ""); + for (const changelogEntry of updateResult.missingChangelogs) { + boxContent.push(`${colors.magenta(changelogEntry.date + " - " + changelogEntry.version)}`); + const changes = changelogEntry.changes.split(` +`); + for (const changeLine of changes) { + if (changeLine.trim()) { + const maxWidth = 70; + const line = changeLine.trim(); + if (line.length <= maxWidth) { + boxContent.push(` ${line}`); + } else { + const words = line.split(" "); + let currentLine = " " + (words[0] || ""); + for (let i = 1;i < words.length; i++) { + if ((currentLine + " " + words[i]).length <= maxWidth + 2) { + currentLine += " " + words[i]; + } else { + boxContent.push(currentLine); + currentLine = " " + words[i]; + } + } + if (currentLine.trim()) { + boxContent.push(currentLine); + } + } + } + } + boxContent.push(""); + } + if (boxContent[boxContent.length - 1] === "") { + boxContent.pop(); + } + } + serverLogger.box(boxContent.join(` +`)); +} +function displayStartupInfo(updateResult) { + displayServerStatus(updateResult); +} +serverLogger.debug("Initializing server event handler"); +on("radio:setLogLevel", (level) => { + logger.level = level; + serverLogger.level = level; + serverLogger.debug(`Log level set to: ${level}`); +}); +on("radio:setStartupError", (error) => { + startupInfo.hasError = true; + startupInfo.errorMessage = error; + serverLogger.error(`Startup error: ${error}`); +}); +on("radio:log", (level, message, tag) => { + const taggedLogger = tag ? serverLogger.withTag(tag) : serverLogger; + switch (level) { + case 0: + taggedLogger.error(message); + break; + case 1: + taggedLogger.warn(message); + break; + case 2: + taggedLogger.log(message); + break; + case 3: + taggedLogger.info(message); + break; + case 4: + taggedLogger.debug(message); + break; + case 5: + taggedLogger.trace(message); + break; + default: + taggedLogger.log(message); + } +}); +on("radio:initServer", (hostParam, port, auth, debug, updateCheck) => { + host = hostParam; + logLevel = debug; + authToken = auth; + serverPort = port; + doUpdateCheck = updateCheck !== undefined ? updateCheck : true; + serverLogger.debug("Server initialization event called"); + startupComplete = false; + pendingUpdateResult = null; + startupInfo.configReceived = false; + startupInfo.connectionTested = false; + displayReady = false; + if (displayTimer) { + clearTimeout(displayTimer); + displayTimer = null; + } + server.listen(port, "0.0.0.0", async () => { + serverLogger.info("Started Radio Server - Running Checks..."); + let finalUrl; + if (!host || host === "") { + const publicIP = await getPublicIP(); + if (!publicIP) { + serverLogger.error("Couldn't determine public IP address, please configure it manually in the config file."); + emit("radio:setStartupError", "Couldn't determine public IP address, please configure it manually in the config file."); + return; + } + finalUrl = `http://${publicIP}:${port}`; + } else { + finalUrl = buildSmartUrl(host, port); + } + serverLogger.debug(`Dispatch panel available at: ${finalUrl}`); + startupInfo.dispatchUrl = finalUrl; + startupInfo.serverStarted = true; + (async () => { + await new Promise((resolve) => setTimeout(resolve, 2000)); + serverLogger.debug("Starting comprehensive health check (HTTP + Socket.IO)..."); + const connectionTest = await testConnection(finalUrl); + if (!connectionTest.success) { + startupInfo.connectionWarning = `${connectionTest.error}`; + if (connectionTest.httpResult && !connectionTest.httpResult.success) { + serverLogger.warn(`HTTP endpoint test failed after ${connectionTest.attempts} attempt(s): ${connectionTest.httpResult.error}`); + } else { + serverLogger.debug(`HTTP endpoint test passed (status: ${connectionTest.httpResult.status})`); + } + if (connectionTest.socketResult && !connectionTest.socketResult.success) { + serverLogger.warn(`Socket.IO test failed after ${connectionTest.attempts} attempt(s): ${connectionTest.socketResult.error}`); + } else { + serverLogger.debug("Socket.IO test passed"); + } + serverLogger.error(`Health check failed after ${connectionTest.attempts} attempt(s) - clients may experience connection issues`); + } else { + const attemptMsg = connectionTest.attempts > 1 ? ` (succeeded on attempt ${connectionTest.attempts})` : ""; + serverLogger.debug(`Health check passed - HTTP (${connectionTest.httpResult.status}) + Socket.IO ✓${attemptMsg}`); + serverLogger.debug("Server is ready for client connections"); + } + startupInfo.connectionTested = true; + startDisplayTimer(); + })(); + if (doUpdateCheck) { + (async () => { + const updateResult = await checkForUpdates(); + pendingUpdateResult = updateResult; + startDisplayTimer(); + })(); + } else { + pendingUpdateResult = null; + startDisplayTimer(); + } + }).on("error", (err) => { + serverLogger.fatal(`Failed to start server on port ${port}: ${err.message}`); + emit("radio:setStartupError", `Failed to start server on port ${port}: ${err.message}`); + }); + serverLogger.info(`Radio server stopped on port ${serverPort}`); +}); +on("radio:updateActiveAlerts", (frequency, alertConfig) => { + const normalizedFreq = normalizeFrequency(frequency); + if (alertConfig) { + activeAlerts[normalizedFreq] = alertConfig; + serverLogger.debug(`Active alert stored: ${alertConfig.name} on ${normalizedFreq}`); + } else { + delete activeAlerts[normalizedFreq]; + serverLogger.debug(`Active alert cleared on ${normalizedFreq}`); + } +}); +on("radio:updateDispatchConfig", (configData) => { + if (configData) { + zones = configData.zones || {}; + alerts = configData.alerts || {}; + activeAlerts = {}; + dispatchNacId = configData.dispatchNacId || "911"; + if (configData.logLevel !== undefined) { + logLevel = configData.logLevel; + logger.level = configData.logLevel; + serverLogger.level = configData.logLevel; + serverLogger.debug(`Log level updated to: ${configData.logLevel}`); + } + if (configData.playTransmissionEffects !== undefined) { + playTransmissionEffects = configData.playTransmissionEffects; + serverLogger.debug(`playTransmissionEffects set to: ${configData.playTransmissionEffects}`); + } + if (configData.analogTransmissionEffects !== undefined) { + analogTransmissionEffects = configData.analogTransmissionEffects; + serverLogger.debug(`analogTransmissionEffects set to: ${configData.analogTransmissionEffects}`); + } + let totalChannels = 0; + Object.values(zones).forEach((zone) => { + if (zone.Channels && typeof zone.Channels === "object") { + totalChannels += Object.keys(zone.Channels).length; + } + }); + serverLogger.debug(`Received zone configuration for dispatch panel: ${Object.keys(zones).length} zones`); + serverLogger.debug(`Zone names: ${Object.values(zones).map((z) => z.name).join(", ")}`); + serverLogger.debug(`Dispatch NAC ID set to: ${dispatchNacId}`); + startupInfo.zoneCount = Object.keys(zones).length; + startupInfo.channelCount = totalChannels; + startupInfo.dispatchNacId = dispatchNacId; + startupInfo.configReceived = true; + startDisplayTimer(); + } else { + serverLogger.error("No config data received in updateDispatchConfig"); + } +}); +on("radio:updatePlayerName", (serverId, name) => { + if (name && serverId) { + playerNames[serverId] = name; + serverLogger.debug(`Updated player name: ${serverId} -> ${name}`); + } +}); +on("radio:updateNacId", (serverId, nacId) => { + if (nacId && serverId) { + nacIds[serverId] = nacId; + serverLogger.debug(`Updated NAC ID: ${serverId} -> ${nacId}`); + } +}); +onNet("radio:requestConnectionInfo", () => { + const playerSource = source; + (async () => { + var connectionAddr = host; + if (!host || host == "") { + connectionAddr = await getPublicIP(); + if (!connectionAddr) { + serverLogger.error("Couldn't determine public IP address, please configure it manually in the config file."); + connectionAddr = "localhost"; + } + connectionAddr = connectionAddr + ":" + serverPort; + } + serverLogger.debug("Sent connection info to client " + playerSource); + emitNet("radio:recieveConnectionInfo", playerSource, connectionAddr); + })(); +}); +on("radio:requestUpdateCheck", async () => { + if (!doUpdateCheck) { + displayStartupInfo(null); + return; + } + const updateResult = await checkForUpdates(); + displayStartupInfo(updateResult); +}); +on("onResourceStart", (resourceName) => { + if (!startupComplete && resourceName !== GetCurrentResourceName()) { + serverLogger.debug(`Resource ${resourceName} started, resetting display timer`); + startDisplayTimer(); + } +}); +on("radio:webSocketBroadcast", (event, data) => { + try { + serverLogger.debug(`Broadcasting WebSocket event: ${event}`); + io.emit(event, data); + } catch (error) { + serverLogger.error(`Error broadcasting WebSocket event ${event}: ${error.message}`); + } +}); diff --git a/resources/radio/server/favicon.png b/resources/radio/server/favicon.png new file mode 100644 index 000000000..b99a9b87c Binary files /dev/null and b/resources/radio/server/favicon.png differ diff --git a/resources/radio/shared.lua b/resources/radio/shared.lua new file mode 100644 index 000000000..3a54cfbc1 Binary files /dev/null and b/resources/radio/shared.lua differ diff --git a/resources/rp-radio/LICENSE b/resources/rp-radio/LICENSE deleted file mode 100644 index ce3ead604..000000000 --- a/resources/rp-radio/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Fraser - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/resources/rp-radio/README.md b/resources/rp-radio/README.md deleted file mode 100644 index ae6c6727d..000000000 --- a/resources/rp-radio/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# rp-radio -All credits go to Frazzle for making this, this is just an adapted version for pma-voice. - -#### Note -By default the radio is disabled (its meant to be used as an in-game item) to give players the radio by default in the client.lua at the top change `Radio.Has` to `true`, if you would like to make it an item look at the replies on the FiveM forum post, there is a tutorial for adding it as an ESX item. - -The export that is used to give/take a players radio is `exports["rp-radio"]:SetRadio(true/false)` or the event `Radio.Set` - -### Exports -Getters - -| Export | Description | Return type | -| ---------------- | --------------------------------------------------- | ----------- | -| IsRadioOpen | Check if player is holding radio | bool | -| IsRadioOn | Check if radio is switched on | bool | -| IsRadioAvailable | Check if player has a radio | bool | -| IsRadioEnabled | Check if radio is enabled | bool | -| CanRadioBeUsed | Check if radio can be used | bool | - -Setters - -| Export | Description | Parameter(s) | -| ------------------------------- | ----------------------------------------------------------- | ------------- | -| SetRadioEnabled | Set if the radio is enabled or not | bool | -| SetRadio | Set if player has a radio or not | bool | -| SetAllowRadioWhenClosed | Allow player to broadcast when closed | bool | -| AddPrivateFrequency | Make a frequency private | int | -| RemovePrivateFrequency | Make a private frequency public | int | -| GivePlayerAccessToFrequency | Give a player access to use a private frequency | int | -| RemovePlayerAccessToFrequency | Remove a players access to use a private frequency | int | -| GivePlayerAccessToFrequencies | Give a player access to use multiple private frequencies | int, int, ... | -| RemovePlayerAccessToFrequencies | Remove a players access to use multiple private frequencies | int, int, ... | - -### Commands - -| Command | Description | -| ---------- | ------------------------ | -| /radio | Open/close the radio | -| /frequency | Choose radio frequency | - -### Events - -| Event | Description | Paramters(s) | -| ------------ | -------------------------------- | ---------------------- | -| Radio.Toggle | Opens/close the radio | none | -| Radio.Set | Set if player has a radio or not | bool | - -### Preview - -- [MP4](https://imgur.com/bAT0mls) diff --git a/resources/rp-radio/client.lua b/resources/rp-radio/client.lua deleted file mode 100644 index d016a8714..000000000 --- a/resources/rp-radio/client.lua +++ /dev/null @@ -1,699 +0,0 @@ -local Radio = { - Has = true, - Open = false, - On = false, - Enabled = true, - Handle = nil, - Prop = GetHashKey('prop_cs_hand_radio'), -- only ran once and doesn't break my syntax viewer - Bone = 28422, - Offset = vector3(0.0, 0.0, 0.0), - Rotation = vector3(0.0, 0.0, 0.0), - Dictionary = { - "cellphone@", - "cellphone@in_car@ds", - "cellphone@str", - "random@arrests", - }, - Animation = { - "cellphone_text_in", - "cellphone_text_out", - "cellphone_call_listen_a", - "generic_radio_chatter", - }, - Clicks = true, -- Radio clicks -} -Radio.Labels = { - { "FRZL_RADIO_HELP", "~s~" .. (radioConfig.Controls.Secondary.Enabled and "~" .. radioConfig.Controls.Secondary.Name .. "~ + ~" .. radioConfig.Controls.Activator.Name .. "~" or "~" .. radioConfig.Controls.Activator.Name .. "~") .. " to hide.~n~~" .. radioConfig.Controls.Toggle.Name .. "~ to turn radio ~g~on~s~.~n~~" .. radioConfig.Controls.Decrease.Name .. "~ or ~" .. radioConfig.Controls.Increase.Name .. "~ to switch frequency~n~~" .. radioConfig.Controls.Input.Name .. "~ to choose frequency~n~~" .. radioConfig.Controls.ToggleClicks.Name .. "~ to ~a~ mic clicks~n~Frequency: ~1~ MHz" }, - { "FRZL_RADIO_HELP2", "~s~" .. (radioConfig.Controls.Secondary.Enabled and "~" .. radioConfig.Controls.Secondary.Name .. "~ + ~" .. radioConfig.Controls.Activator.Name .. "~" or "~" .. radioConfig.Controls.Activator.Name .. "~") .. " to hide.~n~~" .. radioConfig.Controls.Toggle.Name .. "~ to turn radio ~r~off~s~.~n~~" .. radioConfig.Controls.Broadcast.Name .. "~ to broadcast.~n~Frequency: ~1~ MHz" }, - { "FRZL_RADIO_INPUT", "Enter Frequency" }, -} -local unarmed = GetHashKey('weapon_unarmed') -Radio.Commands = { - { - Enabled = true, -- Add a command to be able to open/close the radio - Name = "radio", -- Command name - Help = "Toggle hand radio", -- Command help shown in chatbox when typing the command - Params = {}, - Handler = function(src, args, raw) - local playerPed = PlayerPedId() - local isFalling = IsPedFalling(playerPed) - local isDead = IsEntityDead(playerPed) - - if not isFalling and Radio.Enabled and Radio.Has and not isDead then - Radio:Toggle(not Radio.Open) - elseif (Radio.Open or Radio.On) and ((not Radio.Enabled) or (not Radio.Has) or isDead) then - Radio:Toggle(false) - Radio.On = false - Radio:Remove() - exports["pma-voice"]:setVoiceProperty("radioEnabled", false) - elseif Radio.Open and isFalling then - Radio:Toggle(false) - end - end, - }, - { - Enabled = true, -- Add a command to choose radio frequency - Name = "frequency", -- Command name - Help = "Change radio frequency", -- Command help shown in chatbox when typing the command - Params = { - {name = "number", "Enter frequency"} - }, - Handler = function(src, args, raw) - if Radio.Has then - if args[1] then - local newFrequency = tonumber(args[1]) - if newFrequency then - local minFrequency = radioConfig.Frequency.List[1] - if newFrequency >= minFrequency and newFrequency <= radioConfig.Frequency.List[#radioConfig.Frequency.List] and newFrequency == math.floor(newFrequency) then - if not radioConfig.Frequency.Private[newFrequency] or radioConfig.Frequency.Access[newFrequency] then - local idx = nil - - for i = 1, #radioConfig.Frequency.List do - if radioConfig.Frequency.List[i] == newFrequency then - idx = i - break - end - end - - if idx ~= nil then - if Radio.Enabled then - Radio:Remove() - end - - radioConfig.Frequency.CurrentIndex = idx - radioConfig.Frequency.Current = newFrequency - - if Radio.On then - Radio:Add(radioConfig.Frequency.Current) - end - end - end - end - end - end - end - end, - }, -} - --- Setup each radio command if enabled -for i = 1, #Radio.Commands do - if Radio.Commands[i].Enabled then - RegisterCommand(Radio.Commands[i].Name, Radio.Commands[i].Handler, false) - TriggerEvent("chat:addSuggestion", "/" .. Radio.Commands[i].Name, Radio.Commands[i].Help, Radio.Commands[i].Params) - end -end - --- Create/Destroy handheld radio object -function Radio:Toggle(toggle) - local playerPed = PlayerPedId() - local count = 0 - - if not self.Has or IsEntityDead(playerPed) then - self.Open = false - - DetachEntity(self.Handle, true, false) - DeleteEntity(self.Handle) - - return - end - - if self.Open == toggle then - return - end - - self.Open = toggle - - if self.On and not radioConfig.AllowRadioWhenClosed then - exports["pma-voice"]:setVoiceProperty("radioEnabled", toggle) - end - - local dictionaryType = 1 + (IsPedInAnyVehicle(playerPed, false) and 1 or 0) - local animationType = 1 + (self.Open and 0 or 1) - local dictionary = self.Dictionary[dictionaryType] - local animation = self.Animation[animationType] - - RequestAnimDict(dictionary) - - while not HasAnimDictLoaded(dictionary) do - Citizen.Wait(150) - end - - if self.Open then - RequestModel(self.Prop) - - while not HasModelLoaded(self.Prop) do - Citizen.Wait(150) - end - - self.Handle = CreateObject(self.Prop, 0.0, 0.0, 0.0, true, true, false) - - local bone = GetPedBoneIndex(playerPed, self.Bone) - - SetCurrentPedWeapon(playerPed, unarmed, true) - AttachEntityToEntity(self.Handle, playerPed, bone, self.Offset.x, self.Offset.y, self.Offset.z, self.Rotation.x, self.Rotation.y, self.Rotation.z, true, false, false, false, 2, true) - - SetModelAsNoLongerNeeded(self.Handle) - - TaskPlayAnim(playerPed, dictionary, animation, 4.0, -1, -1, 50, 0, false, false, false) - else - TaskPlayAnim(playerPed, dictionary, animation, 4.0, -1, -1, 50, 0, false, false, false) - - Citizen.Wait(700) - - StopAnimTask(playerPed, dictionary, animation, 1.0) - - NetworkRequestControlOfEntity(self.Handle) - - while not NetworkHasControlOfEntity(self.Handle) and count < 5000 do - Citizen.Wait(0) - count = count + 1 - end - - DetachEntity(self.Handle, true, false) - DeleteEntity(self.Handle) - end -end - --- Add player to radio channel -function Radio:Add(id) - exports["pma-voice"]:setRadioChannel(id) -end - --- Remove player from radio channel -function Radio:Remove() - exports["pma-voice"]:setRadioChannel(0) -end - --- Increase radio frequency -function Radio:Decrease() - if self.On then - if radioConfig.Frequency.CurrentIndex - 1 < 1 and radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] == radioConfig.Frequency.Current then - self:Remove(radioConfig.Frequency.Current) - radioConfig.Frequency.CurrentIndex = #radioConfig.Frequency.List - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - self:Add(radioConfig.Frequency.Current) - elseif radioConfig.Frequency.CurrentIndex - 1 < 1 and radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] ~= radioConfig.Frequency.Current then - self:Remove(radioConfig.Frequency.Current) - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - self:Add(radioConfig.Frequency.Current) - else - self:Remove(radioConfig.Frequency.Current) - radioConfig.Frequency.CurrentIndex = radioConfig.Frequency.CurrentIndex - 1 - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - self:Add(radioConfig.Frequency.Current) - end - else - if radioConfig.Frequency.CurrentIndex - 1 < 1 and radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] == radioConfig.Frequency.Current then - radioConfig.Frequency.CurrentIndex = #radioConfig.Frequency.List - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - elseif radioConfig.Frequency.CurrentIndex - 1 < 1 and radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] ~= radioConfig.Frequency.Current then - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - else - radioConfig.Frequency.CurrentIndex = radioConfig.Frequency.CurrentIndex - 1 - - if radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] == radioConfig.Frequency.Current then - radioConfig.Frequency.CurrentIndex = radioConfig.Frequency.CurrentIndex - 1 - end - - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - end - end -end - --- Decrease radio frequency -function Radio:Increase() - if self.On then - if radioConfig.Frequency.CurrentIndex + 1 > #radioConfig.Frequency.List then - self:Remove(radioConfig.Frequency.Current) - radioConfig.Frequency.CurrentIndex = 1 - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - self:Add(radioConfig.Frequency.Current) - else - self:Remove(radioConfig.Frequency.Current) - radioConfig.Frequency.CurrentIndex = radioConfig.Frequency.CurrentIndex + 1 - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - self:Add(radioConfig.Frequency.Current) - end - else - if #radioConfig.Frequency.List == radioConfig.Frequency.CurrentIndex + 1 then - if radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex + 1] == radioConfig.Frequency.Current then - radioConfig.Frequency.CurrentIndex = radioConfig.Frequency.CurrentIndex + 1 - end - end - - if radioConfig.Frequency.CurrentIndex + 1 > #radioConfig.Frequency.List then - radioConfig.Frequency.CurrentIndex = 1 - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - else - radioConfig.Frequency.CurrentIndex = radioConfig.Frequency.CurrentIndex + 1 - radioConfig.Frequency.Current = radioConfig.Frequency.List[radioConfig.Frequency.CurrentIndex] - end - end -end - --- Generate list of available frequencies -function GenerateFrequencyList() - radioConfig.Frequency.List = {} - - for i = radioConfig.Frequency.Min, radioConfig.Frequency.Max do - if not radioConfig.Frequency.Private[i] or radioConfig.Frequency.Access[i] then - radioConfig.Frequency.List[#radioConfig.Frequency.List + 1] = i - end - end -end - --- Check if radio is open -function IsRadioOpen() - return Radio.Open -end - --- Check if radio is switched on -function IsRadioOn() - return Radio.On -end - --- Check if player has radio -function IsRadioAvailable() - return Radio.Has -end - --- Check if radio is enabled or not -function IsRadioEnabled() - return not Radio.Enabled -end - --- Check if radio can be used -function CanRadioBeUsed() - return Radio.Has and Radio.On and Radio.Enabled -end - --- Set if the radio is enabled or not -function SetRadioEnabled(value) - if type(value) == "string" then - value = value == "true" - elseif type(value) == "number" then - value = value == 1 - end - - Radio.Enabled = value and true or false -end - --- Set if player has a radio or not -function SetRadio(value) - if type(value) == "string" then - value = value == "true" - elseif type(value) == "number" then - value = value == 1 - end - - Radio.Has = value and true or false -end - --- Set if player has access to use the radio when closed -function SetAllowRadioWhenClosed(value) - radioConfig.AllowRadioWhenClosed = value - - if Radio.On and not Radio.Open and radioConfig.AllowRadioWhenClosed then - exports["pma-voice"]:setVoiceProperty("radioEnabled", true) - end -end - --- Add new frequency -function AddPrivateFrequency(value) - local frequency = tonumber(value) - - if frequency ~= nil then - if not radioConfig.Frequency.Private[frequency] then -- Only add new frequencies - radioConfig.Frequency.Private[frequency] = true - - GenerateFrequencyList() - end - end -end - --- Remove private frequency -function RemovePrivateFrequency(value) - local frequency = tonumber(value) - - if frequency ~= nil then - if radioConfig.Frequency.Private[frequency] then -- Only remove existing frequencies - radioConfig.Frequency.Private[frequency] = nil - - GenerateFrequencyList() - end - end -end - --- Give access to a frequency -function GivePlayerAccessToFrequency(value) - local frequency = tonumber(value) - - if frequency ~= nil then - if radioConfig.Frequency.Private[frequency] then -- Check if frequency exists - if not radioConfig.Frequency.Access[frequency] then -- Only add new frequencies - radioConfig.Frequency.Access[frequency] = true - - GenerateFrequencyList() - end - end - end -end - --- Remove access to a frequency -function RemovePlayerAccessToFrequency(value) - local frequency = tonumber(value) - - if frequency ~= nil then - if radioConfig.Frequency.Access[frequency] then -- Check if player has access to frequency - radioConfig.Frequency.Access[frequency] = nil - - GenerateFrequencyList() - end - end -end - --- Give access to multiple frequencies -function GivePlayerAccessToFrequencies(...) - local frequencies = { ... } - local newFrequencies = {} - - for i = 1, #frequencies do - local frequency = tonumber(frequencies[i]) - - if frequency ~= nil then - if radioConfig.Frequency.Private[frequency] then -- Check if frequency exists - if not radioConfig.Frequency.Access[frequency] then -- Only add new frequencies - newFrequencies[#newFrequencies + 1] = frequency - end - end - end - end - - if #newFrequencies > 0 then - for i = 1, #newFrequencies do - radioConfig.Frequency.Access[newFrequencies[i]] = true - end - - GenerateFrequencyList() - end -end - --- Remove access to multiple frequencies -function RemovePlayerAccessToFrequencies(...) - local frequencies = { ... } - local removedFrequencies = {} - - for i = 1, #frequencies do - local frequency = tonumber(frequencies[i]) - - if frequency ~= nil then - if radioConfig.Frequency.Access[frequency] then -- Check if player has access to frequency - removedFrequencies[#removedFrequencies + 1] = frequency - end - end - end - - if #removedFrequencies > 0 then - for i = 1, #removedFrequencies do - radioConfig.Frequency.Access[removedFrequencies[i]] = nil - end - - GenerateFrequencyList() - end -end - --- Define exports -exports("IsRadioOpen", IsRadioOpen) -exports("IsRadioOn", IsRadioOn) -exports("IsRadioAvailable", IsRadioAvailable) -exports("IsRadioEnabled", IsRadioEnabled) -exports("CanRadioBeUsed", CanRadioBeUsed) -exports("SetRadioEnabled", SetRadioEnabled) -exports("SetRadio", SetRadio) -exports("SetAllowRadioWhenClosed", SetAllowRadioWhenClosed) -exports("AddPrivateFrequency", AddPrivateFrequency) -exports("RemovePrivateFrequency", RemovePrivateFrequency) -exports("GivePlayerAccessToFrequency", GivePlayerAccessToFrequency) -exports("RemovePlayerAccessToFrequency", RemovePlayerAccessToFrequency) -exports("GivePlayerAccessToFrequencies", GivePlayerAccessToFrequencies) -exports("RemovePlayerAccessToFrequencies", RemovePlayerAccessToFrequencies) - -local isBroadcasting = false - -AddEventHandler('pma-voice:radioActive', function(broadCasting) - isBroadcasting = broadCasting -end) - -Citizen.CreateThread(function() - -- Add Labels - for i = 1, #Radio.Labels do - AddTextEntry(Radio.Labels[i][1], Radio.Labels[i][2]) - end - - GenerateFrequencyList() - - while true do - Citizen.Wait(0) - -- Init local vars - local playerPed = PlayerPedId() - local isActivatorPressed = IsControlJustPressed(0, radioConfig.Controls.Activator.Key) - local isSecondaryPressed = (radioConfig.Controls.Secondary.Enabled == false and true or IsControlPressed(0, radioConfig.Controls.Secondary.Key)) - local isFalling = IsPedFalling(playerPed) - local isDead = IsEntityDead(playerPed) - local minFrequency = radioConfig.Frequency.List[1] - local broadcastType = 3 + (radioConfig.AllowRadioWhenClosed and 1 or 0) + ((Radio.Open and radioConfig.AllowRadioWhenClosed) and -1 or 0) - local broadcastDictionary = Radio.Dictionary[broadcastType] - local broadcastAnimation = Radio.Animation[broadcastType] - local isPlayingBroadcastAnim = IsEntityPlayingAnim(playerPed, broadcastDictionary, broadcastAnimation, 3) - - -- Open radio settings - if isActivatorPressed and isSecondaryPressed and not isFalling and Radio.Enabled and Radio.Has and not isDead then - Radio:Toggle(not Radio.Open) - elseif (Radio.Open or Radio.On) and ((not Radio.Enabled) or (not Radio.Has) or isDead) then - Radio:Remove() - exports["pma-voice"]:setVoiceProperty("radioEnabled", false) - Radio:Toggle(false) - Radio.On = false - elseif Radio.Open and isFalling then - Radio:Toggle(false) - end - - -- Remove player from private frequency that they don't have access to - if not radioConfig.Frequency.Access[radioConfig.Frequency.Current] and radioConfig.Frequency.Private[radioConfig.Frequency.Current] then - if Radio.On then - Radio:Remove() - end - - radioConfig.Frequency.CurrentIndex = 1 - radioConfig.Frequency.Current = minFrequency - - if Radio.On then - Radio:Add(radioConfig.Frequency.Current) - end - end - - -- Check if player is holding radio - if Radio.Open then - local dictionaryType = 1 + (IsPedInAnyVehicle(playerPed, false) and 1 or 0) - local openDictionary = Radio.Dictionary[dictionaryType] - local openAnimation = Radio.Animation[1] - local isPlayingOpenAnim = IsEntityPlayingAnim(playerPed, openDictionary, openAnimation, 3) - local hasWeapon, currentWeapon = GetCurrentPedWeapon(playerPed, 1) - - -- Remove weapon in hand as we are using the radio - if currentWeapon ~= unarmed then - SetCurrentPedWeapon(playerPed, unarmed, true) - end - - -- Display help text - BeginTextCommandDisplayHelp(Radio.Labels[Radio.On and 2 or 1][1]) - - if not Radio.On then - AddTextComponentSubstringPlayerName(Radio.Clicks and "~r~disable~w~" or "~g~enable~w~") - end - - AddTextComponentInteger(radioConfig.Frequency.Current) - EndTextCommandDisplayHelp(false, false, false, -1) - - -- Play animation if player is broadcasting to radio - if Radio.On then - if isBroadcasting and not isPlayingBroadcastAnim then - RequestAnimDict(broadcastDictionary) - - while not HasAnimDictLoaded(broadcastDictionary) do - Citizen.Wait(150) - end - - TaskPlayAnim(playerPed, broadcastDictionary, broadcastAnimation, 8.0, -8, -1, 49, 0, 0, 0, 0) - elseif not isBroadcasting and isPlayingBroadcastAnim then - StopAnimTask(playerPed, broadcastDictionary, broadcastAnimation, -4.0) - end - end - - -- Play default animation if not broadcasting - if not isBroadcasting and not isPlayingOpenAnim then - RequestAnimDict(openDictionary) - - while not HasAnimDictLoaded(openDictionary) do - Citizen.Wait(150) - end - - TaskPlayAnim(playerPed, openDictionary, openAnimation, 4.0, -1, -1, 50, 0, false, false, false) - end - - -- Turn radio on/off - if IsControlJustPressed(0, radioConfig.Controls.Toggle.Key) then - Radio.On = not Radio.On - - exports["pma-voice"]:setVoiceProperty("radioEnabled", Radio.On) - - if Radio.On then - SendNUIMessage({ sound = "audio_on", volume = 0.3}) - Radio:Add(radioConfig.Frequency.Current) - else - SendNUIMessage({ sound = "audio_off", volume = 0.5}) - Radio:Remove() - end - end - - -- Change radio frequency - if not Radio.On then - DisableControlAction(0, radioConfig.Controls.ToggleClicks.Key, false) - - if not radioConfig.Controls.Decrease.Pressed then - if IsControlJustPressed(0, radioConfig.Controls.Decrease.Key) then - radioConfig.Controls.Decrease.Pressed = true - Citizen.CreateThread(function() - while IsControlPressed(0, radioConfig.Controls.Decrease.Key) do - Radio:Decrease() - Citizen.Wait(125) - end - - radioConfig.Controls.Decrease.Pressed = false - end) - end - end - - if not radioConfig.Controls.Increase.Pressed then - if IsControlJustPressed(0, radioConfig.Controls.Increase.Key) then - radioConfig.Controls.Increase.Pressed = true - Citizen.CreateThread(function() - while IsControlPressed(0, radioConfig.Controls.Increase.Key) do - Radio:Increase() - Citizen.Wait(125) - end - - radioConfig.Controls.Increase.Pressed = false - end) - end - end - - if not radioConfig.Controls.Input.Pressed then - if IsControlJustPressed(0, radioConfig.Controls.Input.Key) then - radioConfig.Controls.Input.Pressed = true - Citizen.CreateThread(function() - DisplayOnscreenKeyboard(1, Radio.Labels[3][1], "", radioConfig.Frequency.Current, "", "", "", 3) - - while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do - Citizen.Wait(150) - end - - local input = nil - - if UpdateOnscreenKeyboard() ~= 2 then - input = GetOnscreenKeyboardResult() - end - - Citizen.Wait(500) - - input = tonumber(input) - - if input ~= nil then - if input >= minFrequency and input <= radioConfig.Frequency.List[#radioConfig.Frequency.List] and input == math.floor(input) then - if not radioConfig.Frequency.Private[input] or radioConfig.Frequency.Access[input] then - local idx = nil - - for i = 1, #radioConfig.Frequency.List do - if radioConfig.Frequency.List[i] == input then - idx = i - break - end - end - - if idx ~= nil then - radioConfig.Frequency.CurrentIndex = idx - radioConfig.Frequency.Current = input - end - end - end - end - - radioConfig.Controls.Input.Pressed = false - end) - end - end - - -- Turn radio mic clicks on/off - if IsDisabledControlJustPressed(0, radioConfig.Controls.ToggleClicks.Key) then - Radio.Clicks = not Radio.Clicks - - SendNUIMessage({ sound = "audio_off", volume = 0.5}) - - exports["pma-voice"]:setVoiceProperty("micClicks", Radio.Clicks) - end - end - else - -- Play emergency services radio animation - if radioConfig.AllowRadioWhenClosed then - if Radio.Has and Radio.On and isBroadcasting and not isPlayingBroadcastAnim then - RequestAnimDict(broadcastDictionary) - - while not HasAnimDictLoaded(broadcastDictionary) do - Citizen.Wait(150) - end - - TaskPlayAnim(playerPed, broadcastDictionary, broadcastAnimation, 8.0, 0.0, -1, 49, 0, 0, 0, 0) - elseif not isBroadcasting and isPlayingBroadcastAnim then - StopAnimTask(playerPed, broadcastDictionary, broadcastAnimation, -4.0) - end - end - end - end -end) - -AddEventHandler("onClientResourceStart", function(resName) - if GetCurrentResourceName() ~= resName and "pma-voice" ~= resName then - return - end - - exports["pma-voice"]:setVoiceProperty("radioEnabled", false) -- Disable radio control - - if Radio.Open then - Radio:Toggle(false) - end - - Radio.On = false -end) - -RegisterNetEvent("Radio.Toggle") -AddEventHandler("Radio.Toggle", function() - local playerPed = PlayerPedId() - local isFalling = IsPedFalling(playerPed) - local isDead = IsEntityDead(playerPed) - - if not isFalling and not isDead and Radio.Enabled and Radio.Has then - Radio:Toggle(not Radio.Open) - end -end) - -RegisterNetEvent("Radio.Set") -AddEventHandler("Radio.Set", function(value) - if type(value) == "string" then - value = value == "true" - elseif type(value) == "number" then - value = value == 1 - end - - Radio.Has = value and true or false -end) diff --git a/resources/rp-radio/config.lua b/resources/rp-radio/config.lua deleted file mode 100644 index e42e9a36d..000000000 --- a/resources/rp-radio/config.lua +++ /dev/null @@ -1,52 +0,0 @@ -radioConfig = { - Controls = { - Activator = { -- Open/Close Radio - Name = "INPUT_DROP_AMMO", -- Control name - Key = 57, -- F10 - }, - Secondary = { - Name = "INPUT_SPRINT", - Key = 21, -- Left Shift - Enabled = true, -- Require secondary to be pressed to open radio with Activator - }, - Toggle = { -- Toggle radio on/off - Name = "INPUT_CONTEXT", -- Control name - Key = 51, -- E - }, - Increase = { -- Increase Frequency - Name = "INPUT_CELLPHONE_RIGHT", -- Control name - Key = 175, -- Right Arrow - Pressed = false, - }, - Decrease = { -- Decrease Frequency - Name = "INPUT_CELLPHONE_LEFT", -- Control name - Key = 174, -- Left Arrow - Pressed = false, - }, - Input = { -- Choose Frequency - Name = "INPUT_FRONTEND_ACCEPT", -- Control name - Key = 201, -- Enter - Pressed = false, - }, - Broadcast = { - Name = "INPUT_VEH_PUSHBIKE_SPRINT", -- Control name - Key = 137, -- Caps Lock - }, - ToggleClicks = { -- Toggle radio click sounds - Name = "INPUT_SELECT_WEAPON", -- Control name - Key = 37, -- Tab - } - }, - Frequency = { - Private = { -- List of private frequencies - [1] = true, -- Make 1 a private frequency - }, -- List of private frequencies - Current = 1, -- Don't touch - CurrentIndex = 1, -- Don't touch - Min = 1, -- Minimum frequency - Max = 1000, -- Max number of frequencies - List = {}, -- Frequency list, Don't touch - Access = {}, -- List of freqencies a player has access to - }, - AllowRadioWhenClosed = false -- Allows the radio to be used when not open (uses police radio animation) -} diff --git a/resources/rp-radio/fxmanifest.lua b/resources/rp-radio/fxmanifest.lua deleted file mode 100644 index 85ef9e833..000000000 --- a/resources/rp-radio/fxmanifest.lua +++ /dev/null @@ -1,28 +0,0 @@ -fx_version "adamant" -game "gta5" - -name "rp-radio" -description "An in-game radio which makes use of the pma-voice radio API for FiveM" -author "Frazzle (frazzle9999@gmail.com)" -version "2.2.1" - -ui_page "index.html" - -dependencies { - "pma-voice", -} - -files { - "index.html", - "on.ogg", - "off.ogg", -} - -client_scripts { - "config.lua", - "client.lua", -} - -server_scripts { - "server.lua", -} \ No newline at end of file diff --git a/resources/rp-radio/index.html b/resources/rp-radio/index.html deleted file mode 100644 index 07a10e13f..000000000 --- a/resources/rp-radio/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - rp-radio - - - - - - - - \ No newline at end of file diff --git a/resources/rp-radio/off.ogg b/resources/rp-radio/off.ogg deleted file mode 100644 index c21374e52..000000000 Binary files a/resources/rp-radio/off.ogg and /dev/null differ diff --git a/resources/rp-radio/on.ogg b/resources/rp-radio/on.ogg deleted file mode 100644 index c0bfdd24f..000000000 Binary files a/resources/rp-radio/on.ogg and /dev/null differ diff --git a/server.cfg b/server.cfg index 5116ad261..170021ea7 100644 --- a/server.cfg +++ b/server.cfg @@ -59,7 +59,7 @@ ensure pma-voice setr voice_defaultCycle "57" //ensure rp-radio //ensure RadioList -ensure scully_radio2 +ensure radio ensure pe-core @@ -918,7 +918,7 @@ ensure chp16fpiup ensure chp15fpiup ensure vehicles-chp15fpius ensure vehicles-chp15fpiuk9 -ensure +ensure lafdbatt ensure ensure ensure @@ -937,7 +937,7 @@ ensure chp19tahoek9 ensure CHP2026 ensure 23gmc2visor ensure 202346gmc -ensure +ensure firef250 ensure ensure ensure