songhieng commited on
Commit
c1b3a0c
·
verified ·
1 Parent(s): b4b3e98

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +5 -0
  2. DATA/1.jpg +0 -0
  3. DATA/2.jpg +0 -0
  4. DATA/3.jpg +0 -0
  5. DATA/4.jpg +0 -0
  6. DATA/blackcar.png +0 -0
  7. DATA/bluecar.png +0 -0
  8. DATA/cadilac.png +0 -0
  9. DATA/cadilac2.png +0 -0
  10. DATA/car_NU51OSU.jpg +0 -0
  11. DATA/gray.png +0 -0
  12. DATA/greencar.png +0 -0
  13. DATA/greencar1.png +0 -0
  14. DATA/orangecar.png +0 -0
  15. DATA/purplecar.png +0 -0
  16. README.md +3 -9
  17. __pycache__/deploy.cpython-311.pyc +0 -0
  18. __pycache__/grad.cpython-311.pyc +0 -0
  19. __pycache__/gradio.cpython-311.pyc +0 -0
  20. __pycache__/uti.cpython-311.pyc +0 -0
  21. __pycache__/util.cpython-311.pyc +0 -0
  22. anpr-v3-b5bb8-firebase-adminsdk-8pkgt-d88b8f69b1.json +13 -0
  23. car.pt +3 -0
  24. color.pt +3 -0
  25. deploy.py +338 -0
  26. f1.mp4 +3 -0
  27. f2.mp4 +0 -0
  28. flagged/Upload Video/e0aad4346d6eb0ce1c58/Untitled video - Made with Clipchamp.mp4 +3 -0
  29. flagged/log.csv +3 -0
  30. main.py +227 -0
  31. make.pt +3 -0
  32. models/license_plate_detector.pt +3 -0
  33. models/run45.pt +3 -0
  34. models/run46.pt +3 -0
  35. models/train4.pt +3 -0
  36. models/train5.pt +3 -0
  37. node_modules/.bin/loose-envify +3 -0
  38. node_modules/.bin/loose-envify.cmd +3 -0
  39. node_modules/.bin/loose-envify.ps1 +3 -0
  40. node_modules/.bin/proto-loader-gen-types +3 -0
  41. node_modules/.bin/proto-loader-gen-types.cmd +3 -0
  42. node_modules/.bin/proto-loader-gen-types.ps1 +3 -0
  43. node_modules/.package-lock.json +955 -0
  44. node_modules/@fastify/busboy/LICENSE +19 -0
  45. node_modules/@fastify/busboy/README.md +271 -0
  46. node_modules/@fastify/busboy/deps/dicer/LICENSE +19 -0
  47. node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js +207 -0
  48. node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js +100 -0
  49. node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js +13 -0
  50. node_modules/@fastify/busboy/deps/dicer/lib/dicer.d.ts +164 -0
.gitattributes CHANGED
@@ -33,3 +33,8 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ f1.mp4 filter=lfs diff=lfs merge=lfs -text
37
+ flagged/Upload[[:space:]]Video/e0aad4346d6eb0ce1c58/Untitled[[:space:]]video[[:space:]]-[[:space:]]Made[[:space:]]with[[:space:]]Clipchamp.mp4 filter=lfs diff=lfs merge=lfs -text
38
+ sample.mp4 filter=lfs diff=lfs merge=lfs -text
39
+ sample1.mp4 filter=lfs diff=lfs merge=lfs -text
40
+ sample2.mp4 filter=lfs diff=lfs merge=lfs -text
DATA/1.jpg ADDED
DATA/2.jpg ADDED
DATA/3.jpg ADDED
DATA/4.jpg ADDED
DATA/blackcar.png ADDED
DATA/bluecar.png ADDED
DATA/cadilac.png ADDED
DATA/cadilac2.png ADDED
DATA/car_NU51OSU.jpg ADDED
DATA/gray.png ADDED
DATA/greencar.png ADDED
DATA/greencar1.png ADDED
DATA/orangecar.png ADDED
DATA/purplecar.png ADDED
README.md CHANGED
@@ -1,12 +1,6 @@
1
  ---
2
- title: ANPR V3
3
- emoji: 😻
4
- colorFrom: blue
5
- colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 4.19.2
8
- app_file: app.py
9
- pinned: false
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: ANPR-V3
3
+ app_file: deploy.py
 
 
4
  sdk: gradio
5
+ sdk_version: 4.19.1
 
 
6
  ---
 
 
__pycache__/deploy.cpython-311.pyc ADDED
Binary file (13 kB). View file
 
__pycache__/grad.cpython-311.pyc ADDED
Binary file (13.2 kB). View file
 
__pycache__/gradio.cpython-311.pyc ADDED
Binary file (13.2 kB). View file
 
__pycache__/uti.cpython-311.pyc ADDED
Binary file (1.42 kB). View file
 
__pycache__/util.cpython-311.pyc ADDED
Binary file (7.69 kB). View file
 
anpr-v3-b5bb8-firebase-adminsdk-8pkgt-d88b8f69b1.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "anpr-v3-b5bb8",
4
+ "private_key_id": "d88b8f69b1cf613de0a1d0ee5e8b1af6afb6dbee",
5
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCovf1wiRo74Q2R\nKdtGvvbhks1wTTAbuDktzci2VHkIhRZZCM+FLDzxqRnJxpqMHINO+nWrwyckOhEZ\nJ954DBf6Yr5zWLrs5oozrjbcTiq+KTtQuHTE/2nhpVgw+B4jZdPk+kj6IAgYuJyH\nI50+1GPvagCfRpxLfFq9Mj6/4i/SO5cb7fywtNSLUdbmP5JpM4pBaCD/8NsaIkuj\njwDyY17RH74AJFRWzaGotf9w3hfzaRPJC+Ib/BjUqMm/5NxY88eOoEeWU417Rvxr\nZ3FET4r1wHvzbYE6mK4+rqTI84binhsnWd+6h5BBSeenF/JDzIEtBjxSJeuSHLBr\n7lr0RWx3AgMBAAECgf8EKT2Ea05LuMcdvZ3e50YYoQHFPtOrN59V6k94OgPKxEdq\nwpido+dYejZO5lE19EgPMJ7QWZclWAAVrmUjXjUrO2pxqPD9jbqI4Q3OnCzIu2qU\nuVCM2XLugo+HWrnS/ZW3vDWaEUiG1iXy2BmF93gk2ztgbHW3XF7nbJD6/tQdpel8\ntaFJBaLJQRcjR2FgsSt7wxCxnwLGXKzaMUH8RsjPxG/mZpQ9RG2cJfIguf5QbuzP\nl5bL6AQTFeDL4JK1UxYD7+3YykqJRbWCyic6eXH7bohRb10QyZnbw4UgAVhCgpIw\nmxBtQkGoom47NIU6o2vV6oLdtezGDTLN1wHVfQECgYEA5nNh0jO4VIkoaouYc+Yu\nsuoJRvXWx9wTHTZkCStxBqEbfZOdYD6Cm9EYStsz87305d9FHCnrrS1cwPQcIRiG\nylmb6c0TLZLfyNFzaNGYRUU5XyqGaCDsrn9cbzHiDI1L8q/7/UKcEqgH/8fn/wXw\nPi5Yy6p98FBR2AUypjmiTK0CgYEAu3M0YVKLj4MHzza3Ejuqxkr2ZVlNxn6p5XWS\nFy9ZvtJ4PEJG1kdZ4tHlyfEFOXQmVwtsn5B1i1N2OtQMyHj9m0jD3A9ktbSWorzn\nK5O/Q7o0cxDXUX16WNzxe3re+p6E4Qycr8VOIKqk54WutX7elL1p2/kkmLjQ8Upr\now9ffjMCgYApCvOpFD0IEUV5dFM6kQxQIQ517OLLxY5B7aXzXCFNJPRYcSneMkPg\nrGS/MDsYdgRfzFvqoCyxMxsJ4nAAFPYso7j48uUvgLEKewMq7+lGrQWCxXgao4KD\nsXss8p1nzuJv3pfqiypwyCxkiZ3v9YbMDEUUQNEdM7Df4E0c/bbCIQKBgQCaDpbQ\nHa1Bp2j1rnxLaepyyg0zQnAfYN51DWmh0HKr2AKlU7swRLflKKj4jTPEAme4RlVh\n1rIkbdXPh5Nx965Gv0jpRWV5yQ+8dBBxyh35pcGRiBfOi5fQDNYSq+sygrGm3Fyy\nQTByvIyHE2GBHOIF0J5+AYdIVSy0AnvwKaRL7QKBgQDkAUu4xIMQdaoKTGK634ah\nemTAS8RTMiIZX8dB/eGFbqym06Itk8NVBf4AUm50GBLgtYCqMHuSV1rlj6O9ARy4\nLPkINwxp7B/4OpsC+X9eRiqqKkyV/o/s6NzIsywg0CmEVDvM3kuQYTD7OJwTbJ2d\nKvciBBZTXeYjXVNNvugo3A==\n-----END PRIVATE KEY-----\n",
6
+ "client_email": "[email protected]",
7
+ "client_id": "115254033604831582656",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-8pkgt%40anpr-v3-b5bb8.iam.gserviceaccount.com",
12
+ "universe_domain": "googleapis.com"
13
+ }
car.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c6c9d9b21ad4145cceec1c584e4f6f93ae73e2db51c0a27a27805e997b41a056
3
+ size 2980223
color.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d2f83df8c3f8ded675c39d951b65ab29f2c00d2ab1640c6a94184126db6b23b4
3
+ size 3001343
deploy.py ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ultralytics import YOLO
2
+ import cv2
3
+ import numpy as np
4
+ from scipy.spatial import KDTree
5
+ import os
6
+ import datetime
7
+ from sort.sort import *
8
+ import util
9
+ import io
10
+ from util import get_car, read_license_plate
11
+ import firebase_admin
12
+ from firebase_admin import credentials, db, storage
13
+ import base64
14
+ import gradio as gr
15
+
16
+ # Firebase Information Server
17
+ cred = credentials.Certificate("anpr-v3-b5bb8-firebase-adminsdk-8pkgt-d88b8f69b1.json")
18
+ firebase_admin.initialize_app(cred, {
19
+ 'databaseURL': 'https://anpr-v3-b5bb8-default-rtdb.asia-southeast1.firebasedatabase.app',
20
+ 'storageBucket': 'anpr-v3-b5bb8.appspot.com'
21
+ })
22
+ ref = db.reference('/')
23
+
24
+
25
+
26
+ ################################################################Need To Chaneg This Part too for the Demonastartion
27
+ users_ref = ref.child('right')
28
+
29
+ #Get Data from the RealTime Database of The Firebase
30
+ root_ref = db.reference('/Detected')
31
+ # Fetch all data at the root of the database
32
+ Detected_data = root_ref.get()
33
+ plates = [data['plate'] for data in Detected_data.values()] if Detected_data else []
34
+ print(plates)
35
+
36
+ car_output_dir = "detected_cars"
37
+ plate_output_dir = "detected_plates"
38
+ Detected_dir = "DATA"
39
+
40
+ if not os.path.exists(car_output_dir):
41
+ os.makedirs(car_output_dir)
42
+ if not os.path.exists(plate_output_dir):
43
+ os.makedirs(plate_output_dir)
44
+
45
+ results = {}
46
+ mot_tracker = Sort()
47
+
48
+ # Load models
49
+ coco_model = YOLO('yolov8n.pt')
50
+ license_plate_detector = YOLO('./models/run46.pt')
51
+ model = YOLO('car.pt')
52
+ model1 = YOLO("color.pt")
53
+ # Load video
54
+
55
+
56
+ vehicles = [2, 3, 4, 5, 6, 7]
57
+
58
+ frame_skip = 40
59
+
60
+ # Read frames
61
+ frame_nmr = -1
62
+ ret = True
63
+
64
+ # Color Recognition functions
65
+ # Predefined colors dictionary
66
+ class_map_color = {
67
+ 0: 'beige',
68
+ 1: 'black',
69
+ 2: 'blue',
70
+ 3: 'brown',
71
+ 4: 'gold',
72
+ 5: 'green',
73
+ 6: 'grey',
74
+ 7: 'orange',
75
+ 8: 'pink',
76
+ 9: 'purple',
77
+ 10: 'red',
78
+ 11: 'sivler',
79
+ 12: 'tan',
80
+ 13: 'white',
81
+ 14: 'yellow'
82
+ }
83
+
84
+ # def reset_counts():
85
+ # global vehicle_counts, current_frame_count, unique_vehicle_ids
86
+ # vehicle_counts = {v: 0 for v in coco_class_to_vehicle_type.values()} # Reset vehicle counts
87
+ # unique_vehicle_ids.clear() # Clear the set of unique vehicle IDs
88
+ # current_frame_count = 0 # Reset frame counter
89
+
90
+ # def upload_text(path, text):
91
+ # ref = db.reference(path)
92
+ # ref.set(text)
93
+
94
+ # def upload_two_texts_append(path, text1, text2):
95
+ # # Create a reference to the specified path in the Firebase Realtime Database
96
+ # ref = db.reference(path)
97
+
98
+ # # Structure the data as a dictionary with two keys, each holding one of the text strings
99
+ # data = {
100
+ # 'text1': text1,
101
+ # 'text2': text2
102
+ # }
103
+
104
+ # # Use the push() method to add the data under a new, unique child node at the specified path
105
+ # new_ref = ref.push(data)
106
+
107
+ # print(f"Appended text1 and text2 under {path} at {new_ref.key}")
108
+
109
+ def upload_to_firebase(filename, destination_blob_name):
110
+ bucket = storage.bucket()
111
+ blob = bucket.blob(destination_blob_name)
112
+ blob.upload_from_filename(filename)
113
+
114
+ print(f"File {filename} uploaded to {destination_blob_name}.")
115
+
116
+ # Return the public URL of the uploaded image
117
+ return blob.public_url
118
+
119
+ # print(f"Data saved to database with key: {new_user.key}")
120
+
121
+ def find_plate(search_plate, plate_array):
122
+ return search_plate in plate_array
123
+
124
+ #----------------------------------------------------------------
125
+ #Car coutner
126
+
127
+
128
+
129
+
130
+ #================================================================
131
+ class_map = {0: 'Convertible', 1: 'Coupe', 2: 'Hatchback', 3: 'Pickup', 4: 'SUV', 5: 'Sedan'}
132
+
133
+ def process_video(video_path):
134
+ cap = cv2.VideoCapture(video_path)
135
+ # Initialize a set to keep track of unique vehicle IDs detected by SORT
136
+ coco_class_to_vehicle_type = {
137
+ 2: 'car', 3: 'motorcycle', 4: 'airplane', 5: 'bus', 6: 'train', 7: 'truck'
138
+ }
139
+ vehicle_counts = {v: 0 for v in coco_class_to_vehicle_type.values()}
140
+ # Initialize a set to keep track of unique vehicle IDs detected by SORT
141
+ unique_vehicle_ids = set()
142
+ # Initialize dictionary to map vehicle track IDs to their COCO class IDs
143
+ track_id_to_class_id = {}
144
+ cnt = 0
145
+ score = 1
146
+ frame_rate = cap.get(cv2.CAP_PROP_FPS) # Get the frame rate of the video
147
+ count_duration_seconds = 10 # Duration in seconds before resetting counts
148
+ frame_count_for_reset = int(frame_rate * count_duration_seconds) # Calculate number of frames for the duration
149
+ current_frame_count = 0 # Initialize a counter for frames
150
+
151
+ output_messages = []
152
+ ret = True
153
+ frame_nmr = 0
154
+ while ret:
155
+ frame_nmr += 1
156
+ ret, frame = cap.read()
157
+ current_frame_count += 1 # Increment frame counter
158
+
159
+ if ret and frame_nmr % frame_skip == 0:
160
+ # Perform detection
161
+ detections = coco_model(frame)[0]
162
+ detections_ = []
163
+
164
+ for detection in detections.boxes.data.tolist():
165
+ x1, y1, x2, y2, score, class_id = detection
166
+ cnt+=1
167
+ if int(class_id) in vehicles:
168
+ # Append detections with class ID for later reference
169
+ detections_.append([x1, y1, x2, y2, score, class_id])
170
+
171
+ # Convert detections for tracking (excluding class_id)
172
+ tracking_data = np.array([d[:5] for d in detections_])
173
+ track_bbs_ids = mot_tracker.update(tracking_data)
174
+
175
+ # Update track ID to class ID mapping
176
+ for track in track_bbs_ids:
177
+ track_id = int(track[4])
178
+ # Find matching detection (assuming first match is correct for simplicity)
179
+ for d in detections_:
180
+ if all([np.isclose(track[i], d[i], atol=1e-3) for i in range(4)]): # Simple bounding box match
181
+ class_id = d[5]
182
+ track_id_to_class_id[track_id] = class_id
183
+ break
184
+
185
+ # Debug print
186
+ # if detections_:
187
+ # print(f"Vehicle detections with confidence: {[(d[4], 'Confidence') for d in detections_]}")
188
+
189
+ # Track vehicles
190
+ track_ids = mot_tracker.update(np.asarray(detections_))
191
+ for track in track_bbs_ids:
192
+ track_id = int(track[4]) # Track ID is the last element in the track array
193
+ unique_vehicle_ids.add(track_id)
194
+
195
+ # Debug print
196
+ # if len(track_ids) > 0:
197
+ # print(f"Tracking IDs: {track_ids}")
198
+
199
+ # Detect license plates
200
+ license_plates = license_plate_detector(frame)[0]
201
+
202
+ # Debug print
203
+ # if license_plates:
204
+ # print(f"License plates detected: {len(license_plates.boxes.data.tolist())}")
205
+
206
+ for license_plate in license_plates.boxes.data.tolist():
207
+ x1, y1, x2, y2, score, class_id = license_plate
208
+
209
+ # Assign license plate to car
210
+ xcar1, ycar1, xcar2, ycar2, car_id = get_car(license_plate, track_ids)
211
+
212
+ if car_id != -1:
213
+ print(f"Car ID: {car_id}, Confidence: {score}") # Debug print
214
+ # upload_text('/', car_id)
215
+ # Crop and process license plate
216
+ license_plate_crop = frame[int(y1):int(y2), int(x1): int(x2), :]
217
+ license_plate_crop_gray = cv2.cvtColor(license_plate_crop, cv2.COLOR_BGR2GRAY)
218
+ _, license_plate_crop_thresh = cv2.threshold(license_plate_crop_gray, 64, 255, cv2.THRESH_BINARY_INV)
219
+
220
+ # Read license plate number
221
+ license_plate_text, license_plate_text_score = read_license_plate(license_plate_crop_thresh)
222
+
223
+
224
+
225
+ if license_plate_text is not None:
226
+ print(f"License Plate Text: {license_plate_text}") # Debug print
227
+
228
+ is_plate_found = find_plate(license_plate_text, plates)
229
+ print(f"Is the plate '{license_plate_text}' found? {'Yes' if is_plate_found else 'No'}")
230
+ # if(is_plate_found):
231
+ # print(1)
232
+ # else:
233
+ # continue
234
+
235
+ # Save the image of the detected car
236
+ car_image = frame[int(ycar1):int(ycar2), int(xcar1): int(xcar2), :]
237
+
238
+ # dominant_color = find_dominant_color(car_image)
239
+ # closest_color_name = find_closest_color_name(dominant_color)
240
+ # print(f"Vehicle Color: {closest_color_name}") # Debug print
241
+ results1 = model1(car_image)
242
+
243
+ # Assuming the top prediction is what you're interested in
244
+ top_prediction_index = results1[0].probs.top5[0] # Index of the highest probability class
245
+ top_prediction_prob = results1[0].probs.top5conf[0].item() # Highest probability
246
+
247
+ # Get the car type from the class_map
248
+ car_color = class_map_color[top_prediction_index]
249
+ print(f"{car_color}")
250
+
251
+ # Save the car image to the local filesystem
252
+ # cv2.imwrite(car_image_filename, car_image)
253
+
254
+
255
+ ################################
256
+ #Type of Car Detectin
257
+ # Perform object detection
258
+ results = model(car_image)
259
+
260
+ # Assuming the top prediction is what you're interested in
261
+ top_prediction_index = results[0].probs.top5[0] # Index of the highest probability class
262
+ top_prediction_prob = results[0].probs.top5conf[0].item() # Highest probability
263
+
264
+ # Get the car type from the class_map
265
+ car_type = class_map[top_prediction_index]
266
+ print(f"{car_type}")
267
+
268
+ now_str = datetime.datetime.utcnow().replace(microsecond=0).isoformat()
269
+ # Current date and time as Unix timestamp in milliseconds
270
+ now_int = int(datetime.datetime.utcnow().timestamp() * 1000)
271
+
272
+
273
+ # Save the image of the detected car
274
+ car_image_filename = os.path.join(car_output_dir, f"car_{license_plate_text}.jpg")
275
+ cv2.imwrite(car_image_filename, car_image)
276
+ car_image_url = upload_to_firebase(car_image_filename, f"detected_cars/car_{license_plate_text}_{now_str}_{now_int}_{car_color}_{car_type}.jpg")
277
+
278
+ if(is_plate_found):
279
+ Detected_dir1 = os.path.join(Detected_dir, f"car_{license_plate_text}.jpg")
280
+ cv2.imwrite(Detected_dir1, car_image)
281
+ car_image_url = upload_to_firebase(Detected_dir1, f"DATA/car_{license_plate_text}_{now_str}_{now_int}_{car_color}_{car_type}.jpg")
282
+
283
+
284
+ # Save the image of the detected license plate
285
+ license_plate_image_filename = os.path.join(plate_output_dir, f"plate_{license_plate_text}.jpg")
286
+ cv2.imwrite(license_plate_image_filename, license_plate_crop)
287
+ license_plate_url = upload_to_firebase(license_plate_image_filename, f"detected_plates/plate_{license_plate_text}_{now_str}_{now_int}.jpg")
288
+
289
+
290
+ # print(f"License plate image uploaded: {license_plate_url}") # Debug print
291
+ # print(f"Current vehicle counts (before potential reset): {vehicle_counts}")
292
+
293
+ # Count vehicles by type after processing all frames
294
+ vehicle_counts = {v: 0 for v in coco_class_to_vehicle_type.values()}
295
+ for class_id in track_id_to_class_id.values():
296
+ vehicle_type = coco_class_to_vehicle_type.get(class_id, 'unknown')
297
+ if vehicle_type in vehicle_counts:
298
+ vehicle_counts[vehicle_type] += 1
299
+
300
+ # Print counts
301
+ for vehicle_type, count in vehicle_counts.items():
302
+ if vehicle_counts.items() == 0:
303
+ score += count * 1
304
+ else:
305
+ score += count* 4
306
+
307
+ print(f"Total {vehicle_type}s detected: {count}")
308
+ data = users_ref.push({'text1': vehicle_type,'text2': count})
309
+ # upload_two_texts_append("/right", vehicle_type, count)
310
+
311
+ print(cnt)
312
+ print('/traffic-score1', score)
313
+ # print('/traffic-score2', score)
314
+
315
+ #####First
316
+ # score1 = ref.child('TrafficScore1')
317
+ # score1.set(score)
318
+
319
+
320
+ #####Second
321
+ score2 = ref.child('TrafficScore2')
322
+ score2.set(score)
323
+
324
+ output_messages.append(f"Traffic-Score1: {score}")
325
+ # output_messages.append(f"Traffic-Score1: {score}")
326
+ output_messages.append(f"Total detections: {cnt}") # Assuming cnt is your counter for detections
327
+
328
+ return "\n".join(output_messages) # Join all messages into a single string
329
+
330
+
331
+ iface = gr.Interface(fn=process_video,
332
+ inputs=gr.Video(label="Upload Video"),
333
+ outputs="text",
334
+ title="Vehicle and License Plate Detection",
335
+ description="Upload a video to detect vehicles and license plates.")
336
+
337
+ if __name__ == "__main__":
338
+ iface.launch(share=True)
f1.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c6a5d4ed8b2594e6263d0f48ca559672b5db97161c8d5c4320869f9c9febdaf5
3
+ size 6523212
f2.mp4 ADDED
Binary file (979 kB). View file
 
flagged/Upload Video/e0aad4346d6eb0ce1c58/Untitled video - Made with Clipchamp.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c6a5d4ed8b2594e6263d0f48ca559672b5db97161c8d5c4320869f9c9febdaf5
3
+ size 6523212
flagged/log.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ Upload Video,output,flag,username,timestamp
2
+ "{""video"":{""path"":""flagged\\Upload Video\\e0aad4346d6eb0ce1c58\\Untitled video - Made with Clipchamp.mp4"",""url"":""http://127.0.0.1:7860/file=C:\\Users\\songh\\AppData\\Local\\Temp\\gradio\\00cc535124d8b2cab971797bdbf8a05572a1ee73\\Untitled video - Made with Clipchamp.mp4"",""size"":6523212,""orig_name"":""Untitled video - Made with Clipchamp.mp4"",""mime_type"":"""",""is_stream"":false},""subtitles"":null}","Total frames processed: 0
3
+ Total detections: 71",,,2024-02-21 02:56:53.479832
main.py ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ultralytics import YOLO
2
+ import cv2
3
+ import numpy as np
4
+ import util
5
+ from sort.sort import *
6
+ from util import get_car, read_license_plate
7
+ import os
8
+ import firebase_admin
9
+ from firebase_admin import storage
10
+ import datetime
11
+
12
+ current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
13
+
14
+
15
+ #Firebase Information Server
16
+ import firebase_admin
17
+ from firebase_admin import credentials, db
18
+
19
+ cred = credentials.Certificate("anpr-5a023-firebase-adminsdk-mrrmo-d159fa0e4d.json")
20
+ firebase_admin.initialize_app(cred, {
21
+ 'databaseURL': 'https://anpr-5a023-default-rtdb.asia-southeast1.firebasedatabase.app',
22
+ 'storageBucket': 'anpr-5a023.appspot.com'
23
+ })
24
+ ref = db.reference('/')
25
+ users_ref = ref.child('users_detected')
26
+ #Firebase Information Server
27
+
28
+
29
+ # Directories for saving detected cars and license plates
30
+ car_output_dir = "detected_cars"
31
+ plate_output_dir = "detected_plates"
32
+ if not os.path.exists(car_output_dir):
33
+ os.makedirs(car_output_dir)
34
+ if not os.path.exists(plate_output_dir):
35
+ os.makedirs(plate_output_dir)
36
+
37
+
38
+ results = {}
39
+ mot_tracker = Sort()
40
+
41
+ # Load models
42
+ coco_model = YOLO('yolov8n.pt')
43
+ license_plate_detector = YOLO('./models/run46.pt')
44
+
45
+ # Load video
46
+ cap = cv2.VideoCapture('./f1.mp4')
47
+
48
+ vehicles = [2, 3, 4, 5, 6, 7]
49
+
50
+ frame_skip = 40
51
+
52
+ # Read frames
53
+ frame_nmr = -1
54
+ ret = True
55
+
56
+
57
+
58
+
59
+ def upload_to_firebase(filename, destination_blob_name):
60
+ """
61
+ Uploads a file to Firebase Cloud Storage.
62
+
63
+ Parameters:
64
+ - filename: Path to the file to upload.
65
+ - destination_blob_name: Storage object name.
66
+ """
67
+
68
+ bucket = storage.bucket()
69
+ blob = bucket.blob(destination_blob_name)
70
+ blob.upload_from_filename(filename)
71
+
72
+ print(f"File {filename} uploaded to {destination_blob_name}.")
73
+
74
+ # Return the public URL of the uploaded image
75
+ return blob.public_url
76
+
77
+
78
+
79
+
80
+ while ret:
81
+ frame_nmr += 1
82
+ ret, frame = cap.read()
83
+ if ret and frame_nmr % frame_skip == 0:
84
+ print(f"Processing frame {frame_nmr}") # Debug print
85
+ results[frame_nmr] = {}
86
+
87
+ # Detect vehicles
88
+ detections = coco_model(frame)[0]
89
+ detections_ = []
90
+
91
+ for detection in detections.boxes.data.tolist():
92
+ x1, y1, x2, y2, score, class_id = detection
93
+ if int(class_id) in vehicles:
94
+ detections_.append([x1, y1, x2, y2, score])
95
+
96
+ # Debug print
97
+ if detections_:
98
+ print(f"Vehicle detections with confidence: {[(d[4], 'Confidence') for d in detections_]}")
99
+
100
+ # Track vehicles
101
+ track_ids = mot_tracker.update(np.asarray(detections_))
102
+
103
+ # Debug print
104
+ if len(track_ids) > 0:
105
+ print(f"Tracking IDs: {track_ids}")
106
+
107
+ # Detect license plates
108
+ license_plates = license_plate_detector(frame)[0]
109
+
110
+ # Debug print
111
+ if license_plates:
112
+ print(f"License plates detected: {len(license_plates.boxes.data.tolist())}")
113
+
114
+ for license_plate in license_plates.boxes.data.tolist():
115
+ x1, y1, x2, y2, score, class_id = license_plate
116
+
117
+ # Assign license plate to car
118
+ xcar1, ycar1, xcar2, ycar2, car_id = get_car(license_plate, track_ids)
119
+
120
+ if car_id != -1:
121
+ print(f"Car ID: {car_id}, Confidence: {score}") # Debug print
122
+
123
+ # Crop and process license plate
124
+ license_plate_crop = frame[int(y1):int(y2), int(x1): int(x2), :]
125
+ license_plate_crop_gray = cv2.cvtColor(license_plate_crop, cv2.COLOR_BGR2GRAY)
126
+ _, license_plate_crop_thresh = cv2.threshold(license_plate_crop_gray, 64, 255, cv2.THRESH_BINARY_INV)
127
+
128
+ # Read license plate number
129
+ license_plate_text, license_plate_text_score = read_license_plate(license_plate_crop_thresh)
130
+
131
+ # # Resize the thresholded license plate for better visibility
132
+ # scale_factor = 2 # Change this value as needed
133
+ # h, w = license_plate_crop_thresh.shape[:2]
134
+ # resized_license_plate = cv2.resize(license_plate_crop_thresh, (int(w * scale_factor), int(h * scale_factor)))
135
+
136
+ # # Display the resized thresholded license plate
137
+ # cv2.imshow('License Plate Thresholded', resized_license_plate)
138
+ # key = cv2.waitKey(0) # Wait until a key is pressed
139
+ # if key == 27: # ESC key
140
+ # break
141
+
142
+
143
+ if license_plate_text is not None:
144
+ print(f"License Plate Text: {license_plate_text}") # Debug print
145
+
146
+ # Save the image of the detected car
147
+ car_image = frame[int(ycar1):int(ycar2), int(xcar1): int(xcar2), :]
148
+ car_image_filename = os.path.join(car_output_dir, f"car_{license_plate_text}.jpg")
149
+ cv2.imwrite(car_image_filename, car_image)
150
+ car_image_url = upload_to_firebase(car_image_filename, f"detected_cars/car_{license_plate_text}.jpg")
151
+
152
+ # Save the image of the detected license plate
153
+ license_plate_image_filename = os.path.join(plate_output_dir, f"plate_{license_plate_text}.jpg")
154
+ cv2.imwrite(license_plate_image_filename, license_plate_crop)
155
+ license_plate_url = upload_to_firebase(license_plate_image_filename, f"detected_plates/plate_{license_plate_text}.jpg")
156
+
157
+
158
+ new_user = users_ref.push({
159
+ 'license_plate': license_plate_text,
160
+ 'timestamp': current_time
161
+ })
162
+
163
+
164
+ results[frame_nmr][car_id] = {
165
+ 'car': {'bbox': [xcar1, ycar1, xcar2, ycar2], 'score': score},
166
+ 'license_plate': {'bbox': [x1, y1, x2, y2],
167
+ 'text': license_plate_text,
168
+ 'bbox_score': score,
169
+ 'text_score': license_plate_text_score}
170
+ }
171
+
172
+
173
+
174
+ # Fetch data from Firebase
175
+ users_detected_data = users_ref.get()
176
+ users_database_ref = ref.child('users_database')
177
+ users_database_data = users_database_ref.get()
178
+
179
+ # Extract license plate values
180
+ detected_license_plates = {uid: details['license_plate'] for uid, details in users_detected_data.items()}
181
+ database_license_plates = {uid: entry['License_Plate'] for uid, entry in enumerate(users_database_data) if 'License_Plate' in entry}
182
+
183
+
184
+ # Find matching license plates and store the complete data
185
+ flagged_data = {}
186
+
187
+ for uid, license_plate in detected_license_plates.items():
188
+ if license_plate in database_license_plates.values():
189
+ flagged_data[uid] = users_detected_data[uid]
190
+
191
+ # Write flagged data to Firebase if any matches found
192
+ if flagged_data:
193
+ flagged_ref = ref.child('flagged')
194
+ flagged_ref.set(flagged_data)
195
+
196
+ flagged_details_data = {} # Dictionary to store detailed flagged data
197
+
198
+ # Collect details from users_database for flagged License_Plate and upload to Firebase
199
+ for uid in flagged_data:
200
+ license_plate = flagged_data[uid]['license_plate']
201
+ for user_id, user_data in enumerate(users_database_data):
202
+ if user_data.get('License_Plate') == license_plate:
203
+ print("\nFlagged User Details:")
204
+ flagged_user_detail = {} # Dictionary to store details of this flagged user
205
+ for key, value in user_data.items():
206
+ print(f"{key}: {value}")
207
+ flagged_user_detail[key] = value
208
+ flagged_details_data[user_id] = flagged_user_detail # Append to main dictionary
209
+
210
+ # Push flagged user details to Firebase
211
+ if flagged_details_data:
212
+ flagged_details_ref = ref.child('flagged_details')
213
+ flagged_details_ref.set(flagged_details_data)
214
+
215
+ print("Suspected data")
216
+ print(flagged_data)
217
+
218
+
219
+ if flagged_data:
220
+ flagged_ref = ref.child('flagged')
221
+ flagged_ref.set(flagged_data)
222
+
223
+ # Collect details from users_database for flagged License_Plate and upload to Firebase
224
+ # ...
225
+ if flagged_details_data:
226
+ flagged_details_ref = ref.child('flagged_details')
227
+ flagged_details_ref.set(flagged_details_data)
make.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a2aaf56f34cd861f7041312a8c46018ed4ab2a0367a4d1ca3065ca9646c55b22
3
+ size 3475007
models/license_plate_detector.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8ec3b254a6c87610f037a90957462cafa11a9c03224e33a28c6a1d1ac2ac51b0
3
+ size 6241454
models/run45.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dfb0048af37224c2b3068771dcd887694166426d9578786f71815974412ab36e
3
+ size 6263087
models/run46.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:163606ad1191db6d545a84ea4ebc1d0ec991a38a488854907e9f2a518ad328bf
3
+ size 6262575
models/train4.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:989192e4c66e2ed715f9570f1e07b6c803a54dae4b877a5a73322806487048ba
3
+ size 6238959
models/train5.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9826d43ef4078aa3686aa222311340613d188897a8444a0e670003f535cf17b2
3
+ size 24545071
node_modules/.bin/loose-envify ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:73e89194039ffb1b7a325066f61ae2f30301efe7de6a60396447989b4b0d8cd7
3
+ size 306
node_modules/.bin/loose-envify.cmd ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8cb11966e80179f907d3fd0d8bb808a6dd7ea08ad4af9cc496f67eeed8a4080
3
+ size 324
node_modules/.bin/loose-envify.ps1 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4e8449b4d8cc0f3009fca0820513cdb0cee7dbdcd19871296cb2cbafc399c4c1
3
+ size 801
node_modules/.bin/proto-loader-gen-types ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b7234ca762e6a83fe6122bee61442d406f96370f30a3e941f18a7a9bceb6ce80
3
+ size 376
node_modules/.bin/proto-loader-gen-types.cmd ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cd95d039f853fa930b299b5d30c0b2d9d08de9eef969dd7a82c119a5d4a5d023
3
+ size 359
node_modules/.bin/proto-loader-gen-types.ps1 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cea49f12a3f42e2b6319b828a8b38d02734fa600002cf5717e822c3305716942
3
+ size 941
node_modules/.package-lock.json ADDED
@@ -0,0 +1,955 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "automatic-number-plate-recognition-python-yolov8",
3
+ "lockfileVersion": 3,
4
+ "requires": true,
5
+ "packages": {
6
+ "node_modules/@fastify/busboy": {
7
+ "version": "2.1.0",
8
+ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
9
+ "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==",
10
+ "engines": {
11
+ "node": ">=14"
12
+ }
13
+ },
14
+ "node_modules/@firebase/analytics": {
15
+ "version": "0.10.1",
16
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.1.tgz",
17
+ "integrity": "sha512-5mnH1aQa99J5lZMJwTNzIoRc4yGXHf+fOn+EoEWhCDA3XGPweGHcylCbqq+G1wVJmfILL57fohDMa8ftMZ+44g==",
18
+ "dependencies": {
19
+ "@firebase/component": "0.6.5",
20
+ "@firebase/installations": "0.6.5",
21
+ "@firebase/logger": "0.4.0",
22
+ "@firebase/util": "1.9.4",
23
+ "tslib": "^2.1.0"
24
+ },
25
+ "peerDependencies": {
26
+ "@firebase/app": "0.x"
27
+ }
28
+ },
29
+ "node_modules/@firebase/analytics-compat": {
30
+ "version": "0.2.7",
31
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.7.tgz",
32
+ "integrity": "sha512-17VCly4P0VFBDqaaal7m1nhyYQwsygtaTpSsnc51sFPRrr9XIYtnD8ficon9fneEGEoJQ2g7OtASvhwX9EbK8g==",
33
+ "dependencies": {
34
+ "@firebase/analytics": "0.10.1",
35
+ "@firebase/analytics-types": "0.8.0",
36
+ "@firebase/component": "0.6.5",
37
+ "@firebase/util": "1.9.4",
38
+ "tslib": "^2.1.0"
39
+ },
40
+ "peerDependencies": {
41
+ "@firebase/app-compat": "0.x"
42
+ }
43
+ },
44
+ "node_modules/@firebase/analytics-types": {
45
+ "version": "0.8.0",
46
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz",
47
+ "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw=="
48
+ },
49
+ "node_modules/@firebase/app": {
50
+ "version": "0.9.27",
51
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.27.tgz",
52
+ "integrity": "sha512-p2Dvl1ge4kRsyK5+wWcmdAIE9MSwZ0pDKAYB51LZgZuz6wciUZk4E1yAEdkfQlRxuHehn+Ol9WP5Qk2XQZiHGg==",
53
+ "dependencies": {
54
+ "@firebase/component": "0.6.5",
55
+ "@firebase/logger": "0.4.0",
56
+ "@firebase/util": "1.9.4",
57
+ "idb": "7.1.1",
58
+ "tslib": "^2.1.0"
59
+ }
60
+ },
61
+ "node_modules/@firebase/app-check": {
62
+ "version": "0.8.2",
63
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.2.tgz",
64
+ "integrity": "sha512-A2B5+ldOguYAeqW1quFN5qNdruSNRrg4W59ag1Eq6QzxuHNIkrE+TrapfrW/z5NYFjCxAYqr/unVCgmk80Dwcg==",
65
+ "dependencies": {
66
+ "@firebase/component": "0.6.5",
67
+ "@firebase/logger": "0.4.0",
68
+ "@firebase/util": "1.9.4",
69
+ "tslib": "^2.1.0"
70
+ },
71
+ "peerDependencies": {
72
+ "@firebase/app": "0.x"
73
+ }
74
+ },
75
+ "node_modules/@firebase/app-check-compat": {
76
+ "version": "0.3.9",
77
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.9.tgz",
78
+ "integrity": "sha512-7LxyupQ8XeEHRh72mO+tqm69kHT6KbWi2KtFMGedJ6tNbwzFzojcXESMKN8RpADXbYoQgY3loWMJjMx4r2Zt7w==",
79
+ "dependencies": {
80
+ "@firebase/app-check": "0.8.2",
81
+ "@firebase/app-check-types": "0.5.0",
82
+ "@firebase/component": "0.6.5",
83
+ "@firebase/logger": "0.4.0",
84
+ "@firebase/util": "1.9.4",
85
+ "tslib": "^2.1.0"
86
+ },
87
+ "peerDependencies": {
88
+ "@firebase/app-compat": "0.x"
89
+ }
90
+ },
91
+ "node_modules/@firebase/app-check-interop-types": {
92
+ "version": "0.3.0",
93
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz",
94
+ "integrity": "sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg=="
95
+ },
96
+ "node_modules/@firebase/app-check-types": {
97
+ "version": "0.5.0",
98
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz",
99
+ "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ=="
100
+ },
101
+ "node_modules/@firebase/app-compat": {
102
+ "version": "0.2.27",
103
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.27.tgz",
104
+ "integrity": "sha512-SYlqocfUDKPHR6MSFC8hree0BTiWFu5o8wbf6zFlYXyG41w7TcHp4wJi4H/EL5V6cM4kxwruXTJtqXX/fRAZtw==",
105
+ "dependencies": {
106
+ "@firebase/app": "0.9.27",
107
+ "@firebase/component": "0.6.5",
108
+ "@firebase/logger": "0.4.0",
109
+ "@firebase/util": "1.9.4",
110
+ "tslib": "^2.1.0"
111
+ }
112
+ },
113
+ "node_modules/@firebase/app-types": {
114
+ "version": "0.9.0",
115
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz",
116
+ "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q=="
117
+ },
118
+ "node_modules/@firebase/auth": {
119
+ "version": "1.6.0",
120
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.6.0.tgz",
121
+ "integrity": "sha512-Qhl35eJTV6BwvuueTPCY6x8kUlYyzALtjp/Ws0X3fw3AnjVVfuVb7oQ3Xh5VPVfMFhaIuUAd1KXwcAuIklkSDw==",
122
+ "dependencies": {
123
+ "@firebase/component": "0.6.5",
124
+ "@firebase/logger": "0.4.0",
125
+ "@firebase/util": "1.9.4",
126
+ "tslib": "^2.1.0",
127
+ "undici": "5.26.5"
128
+ },
129
+ "peerDependencies": {
130
+ "@firebase/app": "0.x",
131
+ "@react-native-async-storage/async-storage": "^1.18.1"
132
+ },
133
+ "peerDependenciesMeta": {
134
+ "@react-native-async-storage/async-storage": {
135
+ "optional": true
136
+ }
137
+ }
138
+ },
139
+ "node_modules/@firebase/auth-compat": {
140
+ "version": "0.5.2",
141
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.2.tgz",
142
+ "integrity": "sha512-pRgje5BPCNR1vXyvGOVXwOHtv88A2WooXfklI8sV7/jWi03ExFqNfpJT26GUo/oD39NoKJ3Kt6rD5gVvdV7lMw==",
143
+ "dependencies": {
144
+ "@firebase/auth": "1.6.0",
145
+ "@firebase/auth-types": "0.12.0",
146
+ "@firebase/component": "0.6.5",
147
+ "@firebase/util": "1.9.4",
148
+ "tslib": "^2.1.0",
149
+ "undici": "5.26.5"
150
+ },
151
+ "peerDependencies": {
152
+ "@firebase/app-compat": "0.x"
153
+ }
154
+ },
155
+ "node_modules/@firebase/auth-interop-types": {
156
+ "version": "0.2.1",
157
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz",
158
+ "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg=="
159
+ },
160
+ "node_modules/@firebase/auth-types": {
161
+ "version": "0.12.0",
162
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz",
163
+ "integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==",
164
+ "peerDependencies": {
165
+ "@firebase/app-types": "0.x",
166
+ "@firebase/util": "1.x"
167
+ }
168
+ },
169
+ "node_modules/@firebase/component": {
170
+ "version": "0.6.5",
171
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.5.tgz",
172
+ "integrity": "sha512-2tVDk1ixi12sbDmmfITK8lxSjmcb73BMF6Qwc3U44hN/J1Fi1QY/Hnnb6klFlbB9/G16a3J3d4nXykye2EADTw==",
173
+ "dependencies": {
174
+ "@firebase/util": "1.9.4",
175
+ "tslib": "^2.1.0"
176
+ }
177
+ },
178
+ "node_modules/@firebase/database": {
179
+ "version": "1.0.3",
180
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.3.tgz",
181
+ "integrity": "sha512-9fjqLt9JzL46gw9+NRqsgQEMjgRwfd8XtzcKqG+UYyhVeFCdVRQ0Wp6Dw/dvYHnbH5vNEKzNv36dcB4p+PIAAA==",
182
+ "dependencies": {
183
+ "@firebase/app-check-interop-types": "0.3.0",
184
+ "@firebase/auth-interop-types": "0.2.1",
185
+ "@firebase/component": "0.6.5",
186
+ "@firebase/logger": "0.4.0",
187
+ "@firebase/util": "1.9.4",
188
+ "faye-websocket": "0.11.4",
189
+ "tslib": "^2.1.0"
190
+ }
191
+ },
192
+ "node_modules/@firebase/database-compat": {
193
+ "version": "1.0.3",
194
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.3.tgz",
195
+ "integrity": "sha512-7tHEOcMbK5jJzHWyphPux4osogH/adWwncxdMxdBpB9g1DNIyY4dcz1oJdlkXGM/i/AjUBesZsd5CuwTRTBNTw==",
196
+ "dependencies": {
197
+ "@firebase/component": "0.6.5",
198
+ "@firebase/database": "1.0.3",
199
+ "@firebase/database-types": "1.0.1",
200
+ "@firebase/logger": "0.4.0",
201
+ "@firebase/util": "1.9.4",
202
+ "tslib": "^2.1.0"
203
+ }
204
+ },
205
+ "node_modules/@firebase/database-types": {
206
+ "version": "1.0.1",
207
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.1.tgz",
208
+ "integrity": "sha512-Tmcmx5XgiI7UVF/4oGg2P3AOTfq3WKEPsm2yf+uXtN7uG/a4WTWhVMrXGYRY2ZUL1xPxv9V33wQRJ+CcrUhVXw==",
209
+ "dependencies": {
210
+ "@firebase/app-types": "0.9.0",
211
+ "@firebase/util": "1.9.4"
212
+ }
213
+ },
214
+ "node_modules/@firebase/firestore": {
215
+ "version": "4.4.2",
216
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.4.2.tgz",
217
+ "integrity": "sha512-YaX6ypa/RzU6OkxzUQlpSxwhOIWdTraCNz7sMsbaSEjjl/pj/QvX6TqjkdWGzuBYh2S6rz7ErhDO0g39oZZw/g==",
218
+ "dependencies": {
219
+ "@firebase/component": "0.6.5",
220
+ "@firebase/logger": "0.4.0",
221
+ "@firebase/util": "1.9.4",
222
+ "@firebase/webchannel-wrapper": "0.10.5",
223
+ "@grpc/grpc-js": "~1.9.0",
224
+ "@grpc/proto-loader": "^0.7.8",
225
+ "tslib": "^2.1.0",
226
+ "undici": "5.26.5"
227
+ },
228
+ "engines": {
229
+ "node": ">=10.10.0"
230
+ },
231
+ "peerDependencies": {
232
+ "@firebase/app": "0.x"
233
+ }
234
+ },
235
+ "node_modules/@firebase/firestore-compat": {
236
+ "version": "0.3.25",
237
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.25.tgz",
238
+ "integrity": "sha512-+xI7WmsgZCBhMn/+uhDKcg+lsOUJ9FJyt5PGTzkFPbCsozWfeQZ7eVnfPh0rMkUOf0yIQ924RIe04gwvEIbcoQ==",
239
+ "dependencies": {
240
+ "@firebase/component": "0.6.5",
241
+ "@firebase/firestore": "4.4.2",
242
+ "@firebase/firestore-types": "3.0.0",
243
+ "@firebase/util": "1.9.4",
244
+ "tslib": "^2.1.0"
245
+ },
246
+ "peerDependencies": {
247
+ "@firebase/app-compat": "0.x"
248
+ }
249
+ },
250
+ "node_modules/@firebase/firestore-types": {
251
+ "version": "3.0.0",
252
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.0.tgz",
253
+ "integrity": "sha512-Meg4cIezHo9zLamw0ymFYBD4SMjLb+ZXIbuN7T7ddXN6MGoICmOTq3/ltdCGoDCS2u+H1XJs2u/cYp75jsX9Qw==",
254
+ "peerDependencies": {
255
+ "@firebase/app-types": "0.x",
256
+ "@firebase/util": "1.x"
257
+ }
258
+ },
259
+ "node_modules/@firebase/functions": {
260
+ "version": "0.11.1",
261
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.1.tgz",
262
+ "integrity": "sha512-3uUa1hB79Gmy6E1gHTfzoHeZolBeHc/I/n3+lOCDe6BOos9AHmzRjKygcFE/7VA2FJjitCE0K+OHI6+OuoY8fQ==",
263
+ "dependencies": {
264
+ "@firebase/app-check-interop-types": "0.3.0",
265
+ "@firebase/auth-interop-types": "0.2.1",
266
+ "@firebase/component": "0.6.5",
267
+ "@firebase/messaging-interop-types": "0.2.0",
268
+ "@firebase/util": "1.9.4",
269
+ "tslib": "^2.1.0",
270
+ "undici": "5.26.5"
271
+ },
272
+ "peerDependencies": {
273
+ "@firebase/app": "0.x"
274
+ }
275
+ },
276
+ "node_modules/@firebase/functions-compat": {
277
+ "version": "0.3.7",
278
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.7.tgz",
279
+ "integrity": "sha512-uXe6Kmku5lNogp3OpPBcOJbSvnaCOn+YxS3zlXKNU6Q/NLwcvO3RY1zwYyctCos2RemEw3KEQ7YdzcECXjHWLw==",
280
+ "dependencies": {
281
+ "@firebase/component": "0.6.5",
282
+ "@firebase/functions": "0.11.1",
283
+ "@firebase/functions-types": "0.6.0",
284
+ "@firebase/util": "1.9.4",
285
+ "tslib": "^2.1.0"
286
+ },
287
+ "peerDependencies": {
288
+ "@firebase/app-compat": "0.x"
289
+ }
290
+ },
291
+ "node_modules/@firebase/functions-types": {
292
+ "version": "0.6.0",
293
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz",
294
+ "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw=="
295
+ },
296
+ "node_modules/@firebase/installations": {
297
+ "version": "0.6.5",
298
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.5.tgz",
299
+ "integrity": "sha512-0xxnQWw8rSRzu0ZOCkZaO+MJ0LkDAfwwTB2Z1SxRK6FAz5xkxD1ZUwM0WbCRni49PKubCrZYOJ6yg7tSjU7AKA==",
300
+ "dependencies": {
301
+ "@firebase/component": "0.6.5",
302
+ "@firebase/util": "1.9.4",
303
+ "idb": "7.1.1",
304
+ "tslib": "^2.1.0"
305
+ },
306
+ "peerDependencies": {
307
+ "@firebase/app": "0.x"
308
+ }
309
+ },
310
+ "node_modules/@firebase/installations-compat": {
311
+ "version": "0.2.5",
312
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.5.tgz",
313
+ "integrity": "sha512-usvoIaog5CHEw082HXLrKAZ1qd4hIC3N/LDe2NqBgI3pkGE/7auLVM4Gn5gvyryp0x8z/IP1+d9fkGUj2OaGLQ==",
314
+ "dependencies": {
315
+ "@firebase/component": "0.6.5",
316
+ "@firebase/installations": "0.6.5",
317
+ "@firebase/installations-types": "0.5.0",
318
+ "@firebase/util": "1.9.4",
319
+ "tslib": "^2.1.0"
320
+ },
321
+ "peerDependencies": {
322
+ "@firebase/app-compat": "0.x"
323
+ }
324
+ },
325
+ "node_modules/@firebase/installations-types": {
326
+ "version": "0.5.0",
327
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz",
328
+ "integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==",
329
+ "peerDependencies": {
330
+ "@firebase/app-types": "0.x"
331
+ }
332
+ },
333
+ "node_modules/@firebase/logger": {
334
+ "version": "0.4.0",
335
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz",
336
+ "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==",
337
+ "dependencies": {
338
+ "tslib": "^2.1.0"
339
+ }
340
+ },
341
+ "node_modules/@firebase/messaging": {
342
+ "version": "0.12.6",
343
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.6.tgz",
344
+ "integrity": "sha512-IORsPp9IPWq4j4yEhTOZ6GAGi3gQwGc+4yexmTAlya+qeBRSdRnJg2iIU/aj+tcKDQYr9RQuQPgHHOdFIx//vA==",
345
+ "dependencies": {
346
+ "@firebase/component": "0.6.5",
347
+ "@firebase/installations": "0.6.5",
348
+ "@firebase/messaging-interop-types": "0.2.0",
349
+ "@firebase/util": "1.9.4",
350
+ "idb": "7.1.1",
351
+ "tslib": "^2.1.0"
352
+ },
353
+ "peerDependencies": {
354
+ "@firebase/app": "0.x"
355
+ }
356
+ },
357
+ "node_modules/@firebase/messaging-compat": {
358
+ "version": "0.2.6",
359
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.6.tgz",
360
+ "integrity": "sha512-Q2xC1s4L7Vpss7P7Gy6GuIS+xmJrf/vm9+gX76IK1Bo1TjoKwleCLHt1LHkPz5Rvqg5pTgzzI8qqPhBpZosFCg==",
361
+ "dependencies": {
362
+ "@firebase/component": "0.6.5",
363
+ "@firebase/messaging": "0.12.6",
364
+ "@firebase/util": "1.9.4",
365
+ "tslib": "^2.1.0"
366
+ },
367
+ "peerDependencies": {
368
+ "@firebase/app-compat": "0.x"
369
+ }
370
+ },
371
+ "node_modules/@firebase/messaging-interop-types": {
372
+ "version": "0.2.0",
373
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz",
374
+ "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ=="
375
+ },
376
+ "node_modules/@firebase/performance": {
377
+ "version": "0.6.5",
378
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.5.tgz",
379
+ "integrity": "sha512-OzAGcWhOqEFH9GdwUuY0oC5FSlnMejcnmSAhR+EjpI7exdDvixyLyCR4txjSHYNTbumrFBG+EP8GO11CNXRaJA==",
380
+ "dependencies": {
381
+ "@firebase/component": "0.6.5",
382
+ "@firebase/installations": "0.6.5",
383
+ "@firebase/logger": "0.4.0",
384
+ "@firebase/util": "1.9.4",
385
+ "tslib": "^2.1.0"
386
+ },
387
+ "peerDependencies": {
388
+ "@firebase/app": "0.x"
389
+ }
390
+ },
391
+ "node_modules/@firebase/performance-compat": {
392
+ "version": "0.2.5",
393
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.5.tgz",
394
+ "integrity": "sha512-jJwJkVyDcIMBaVGrZ6CRGs4m5FCZsWB5QCWYI3FdsHyIa9/TfteNDilxj9wGciF2naFIHDW7TgE69U5dAH9Ktg==",
395
+ "dependencies": {
396
+ "@firebase/component": "0.6.5",
397
+ "@firebase/logger": "0.4.0",
398
+ "@firebase/performance": "0.6.5",
399
+ "@firebase/performance-types": "0.2.0",
400
+ "@firebase/util": "1.9.4",
401
+ "tslib": "^2.1.0"
402
+ },
403
+ "peerDependencies": {
404
+ "@firebase/app-compat": "0.x"
405
+ }
406
+ },
407
+ "node_modules/@firebase/performance-types": {
408
+ "version": "0.2.0",
409
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz",
410
+ "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA=="
411
+ },
412
+ "node_modules/@firebase/remote-config": {
413
+ "version": "0.4.5",
414
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.5.tgz",
415
+ "integrity": "sha512-rGLqc/4OmxrS39RA9kgwa6JmgWytQuMo+B8pFhmGp3d++x2Hf9j+MLQfhOLyyUo64fNw20J19mLXhrXvKHsjZQ==",
416
+ "dependencies": {
417
+ "@firebase/component": "0.6.5",
418
+ "@firebase/installations": "0.6.5",
419
+ "@firebase/logger": "0.4.0",
420
+ "@firebase/util": "1.9.4",
421
+ "tslib": "^2.1.0"
422
+ },
423
+ "peerDependencies": {
424
+ "@firebase/app": "0.x"
425
+ }
426
+ },
427
+ "node_modules/@firebase/remote-config-compat": {
428
+ "version": "0.2.5",
429
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.5.tgz",
430
+ "integrity": "sha512-ImkNnLuGrD/bylBHDJigSY6LMwRrwt37wQbsGZhWG4QQ6KLzHzSf0nnFRRFvkOZodEUE57Ib8l74d6Yn/6TDUQ==",
431
+ "dependencies": {
432
+ "@firebase/component": "0.6.5",
433
+ "@firebase/logger": "0.4.0",
434
+ "@firebase/remote-config": "0.4.5",
435
+ "@firebase/remote-config-types": "0.3.0",
436
+ "@firebase/util": "1.9.4",
437
+ "tslib": "^2.1.0"
438
+ },
439
+ "peerDependencies": {
440
+ "@firebase/app-compat": "0.x"
441
+ }
442
+ },
443
+ "node_modules/@firebase/remote-config-types": {
444
+ "version": "0.3.0",
445
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz",
446
+ "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA=="
447
+ },
448
+ "node_modules/@firebase/storage": {
449
+ "version": "0.12.1",
450
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.12.1.tgz",
451
+ "integrity": "sha512-KJ5NV7FUh54TeTlEjdkTTX60ciCKOp9EqlbLnpdcXUYRJg0Z4810TXbilPc1z7fTIG4iPjtdi95bGE9n4dBX8A==",
452
+ "dependencies": {
453
+ "@firebase/component": "0.6.5",
454
+ "@firebase/util": "1.9.4",
455
+ "tslib": "^2.1.0",
456
+ "undici": "5.26.5"
457
+ },
458
+ "peerDependencies": {
459
+ "@firebase/app": "0.x"
460
+ }
461
+ },
462
+ "node_modules/@firebase/storage-compat": {
463
+ "version": "0.3.4",
464
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.4.tgz",
465
+ "integrity": "sha512-Y0m5e2gS/wB9Ioth2X/Sgz76vcxvqgQrCmfa9qwhss/N31kxY2Gks6Frv0nrE18AjVfcSmcfDitqUwxcMOTRSg==",
466
+ "dependencies": {
467
+ "@firebase/component": "0.6.5",
468
+ "@firebase/storage": "0.12.1",
469
+ "@firebase/storage-types": "0.8.0",
470
+ "@firebase/util": "1.9.4",
471
+ "tslib": "^2.1.0"
472
+ },
473
+ "peerDependencies": {
474
+ "@firebase/app-compat": "0.x"
475
+ }
476
+ },
477
+ "node_modules/@firebase/storage-types": {
478
+ "version": "0.8.0",
479
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz",
480
+ "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==",
481
+ "peerDependencies": {
482
+ "@firebase/app-types": "0.x",
483
+ "@firebase/util": "1.x"
484
+ }
485
+ },
486
+ "node_modules/@firebase/util": {
487
+ "version": "1.9.4",
488
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.4.tgz",
489
+ "integrity": "sha512-WLonYmS1FGHT97TsUmRN3qnTh5TeeoJp1Gg5fithzuAgdZOUtsYECfy7/noQ3llaguios8r5BuXSEiK82+UrxQ==",
490
+ "dependencies": {
491
+ "tslib": "^2.1.0"
492
+ }
493
+ },
494
+ "node_modules/@firebase/webchannel-wrapper": {
495
+ "version": "0.10.5",
496
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.5.tgz",
497
+ "integrity": "sha512-eSkJsnhBWv5kCTSU1tSUVl9mpFu+5NXXunZc83le8GMjMlsWwQArSc7cJJ4yl+aDFY0NGLi0AjZWMn1axOrkRg=="
498
+ },
499
+ "node_modules/@grpc/grpc-js": {
500
+ "version": "1.9.14",
501
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz",
502
+ "integrity": "sha512-nOpuzZ2G3IuMFN+UPPpKrC6NsLmWsTqSsm66IRfnBt1D4pwTqE27lmbpcPM+l2Ua4gE7PfjRHI6uedAy7hoXUw==",
503
+ "dependencies": {
504
+ "@grpc/proto-loader": "^0.7.8",
505
+ "@types/node": ">=12.12.47"
506
+ },
507
+ "engines": {
508
+ "node": "^8.13.0 || >=10.10.0"
509
+ }
510
+ },
511
+ "node_modules/@grpc/proto-loader": {
512
+ "version": "0.7.10",
513
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz",
514
+ "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==",
515
+ "dependencies": {
516
+ "lodash.camelcase": "^4.3.0",
517
+ "long": "^5.0.0",
518
+ "protobufjs": "^7.2.4",
519
+ "yargs": "^17.7.2"
520
+ },
521
+ "bin": {
522
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
523
+ },
524
+ "engines": {
525
+ "node": ">=6"
526
+ }
527
+ },
528
+ "node_modules/@kurkle/color": {
529
+ "version": "0.3.2",
530
+ "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
531
+ "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
532
+ },
533
+ "node_modules/@protobufjs/aspromise": {
534
+ "version": "1.1.2",
535
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
536
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
537
+ },
538
+ "node_modules/@protobufjs/base64": {
539
+ "version": "1.1.2",
540
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
541
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
542
+ },
543
+ "node_modules/@protobufjs/codegen": {
544
+ "version": "2.0.4",
545
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
546
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
547
+ },
548
+ "node_modules/@protobufjs/eventemitter": {
549
+ "version": "1.1.0",
550
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
551
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
552
+ },
553
+ "node_modules/@protobufjs/fetch": {
554
+ "version": "1.1.0",
555
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
556
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
557
+ "dependencies": {
558
+ "@protobufjs/aspromise": "^1.1.1",
559
+ "@protobufjs/inquire": "^1.1.0"
560
+ }
561
+ },
562
+ "node_modules/@protobufjs/float": {
563
+ "version": "1.0.2",
564
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
565
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
566
+ },
567
+ "node_modules/@protobufjs/inquire": {
568
+ "version": "1.1.0",
569
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
570
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
571
+ },
572
+ "node_modules/@protobufjs/path": {
573
+ "version": "1.1.2",
574
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
575
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
576
+ },
577
+ "node_modules/@protobufjs/pool": {
578
+ "version": "1.1.0",
579
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
580
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
581
+ },
582
+ "node_modules/@protobufjs/utf8": {
583
+ "version": "1.1.0",
584
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
585
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
586
+ },
587
+ "node_modules/@types/node": {
588
+ "version": "20.11.19",
589
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz",
590
+ "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
591
+ "dependencies": {
592
+ "undici-types": "~5.26.4"
593
+ }
594
+ },
595
+ "node_modules/ansi-regex": {
596
+ "version": "5.0.1",
597
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
598
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
599
+ "engines": {
600
+ "node": ">=8"
601
+ }
602
+ },
603
+ "node_modules/ansi-styles": {
604
+ "version": "4.3.0",
605
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
606
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
607
+ "dependencies": {
608
+ "color-convert": "^2.0.1"
609
+ },
610
+ "engines": {
611
+ "node": ">=8"
612
+ },
613
+ "funding": {
614
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
615
+ }
616
+ },
617
+ "node_modules/chart.js": {
618
+ "version": "4.4.1",
619
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz",
620
+ "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==",
621
+ "dependencies": {
622
+ "@kurkle/color": "^0.3.0"
623
+ },
624
+ "engines": {
625
+ "pnpm": ">=7"
626
+ }
627
+ },
628
+ "node_modules/cliui": {
629
+ "version": "8.0.1",
630
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
631
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
632
+ "dependencies": {
633
+ "string-width": "^4.2.0",
634
+ "strip-ansi": "^6.0.1",
635
+ "wrap-ansi": "^7.0.0"
636
+ },
637
+ "engines": {
638
+ "node": ">=12"
639
+ }
640
+ },
641
+ "node_modules/color-convert": {
642
+ "version": "2.0.1",
643
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
644
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
645
+ "dependencies": {
646
+ "color-name": "~1.1.4"
647
+ },
648
+ "engines": {
649
+ "node": ">=7.0.0"
650
+ }
651
+ },
652
+ "node_modules/color-name": {
653
+ "version": "1.1.4",
654
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
655
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
656
+ },
657
+ "node_modules/emoji-regex": {
658
+ "version": "8.0.0",
659
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
660
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
661
+ },
662
+ "node_modules/escalade": {
663
+ "version": "3.1.2",
664
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
665
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
666
+ "engines": {
667
+ "node": ">=6"
668
+ }
669
+ },
670
+ "node_modules/faye-websocket": {
671
+ "version": "0.11.4",
672
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
673
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
674
+ "dependencies": {
675
+ "websocket-driver": ">=0.5.1"
676
+ },
677
+ "engines": {
678
+ "node": ">=0.8.0"
679
+ }
680
+ },
681
+ "node_modules/firebase": {
682
+ "version": "10.8.0",
683
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.8.0.tgz",
684
+ "integrity": "sha512-UJpC24vw8JFuHEOQyArBGKTUd7+kohLISCzHyn0M/prP0KOTx2io1eyLliEid330QqnWI7FOlPxoU97qecCSfQ==",
685
+ "dependencies": {
686
+ "@firebase/analytics": "0.10.1",
687
+ "@firebase/analytics-compat": "0.2.7",
688
+ "@firebase/app": "0.9.27",
689
+ "@firebase/app-check": "0.8.2",
690
+ "@firebase/app-check-compat": "0.3.9",
691
+ "@firebase/app-compat": "0.2.27",
692
+ "@firebase/app-types": "0.9.0",
693
+ "@firebase/auth": "1.6.0",
694
+ "@firebase/auth-compat": "0.5.2",
695
+ "@firebase/database": "1.0.3",
696
+ "@firebase/database-compat": "1.0.3",
697
+ "@firebase/firestore": "4.4.2",
698
+ "@firebase/firestore-compat": "0.3.25",
699
+ "@firebase/functions": "0.11.1",
700
+ "@firebase/functions-compat": "0.3.7",
701
+ "@firebase/installations": "0.6.5",
702
+ "@firebase/installations-compat": "0.2.5",
703
+ "@firebase/messaging": "0.12.6",
704
+ "@firebase/messaging-compat": "0.2.6",
705
+ "@firebase/performance": "0.6.5",
706
+ "@firebase/performance-compat": "0.2.5",
707
+ "@firebase/remote-config": "0.4.5",
708
+ "@firebase/remote-config-compat": "0.2.5",
709
+ "@firebase/storage": "0.12.1",
710
+ "@firebase/storage-compat": "0.3.4",
711
+ "@firebase/util": "1.9.4"
712
+ }
713
+ },
714
+ "node_modules/get-caller-file": {
715
+ "version": "2.0.5",
716
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
717
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
718
+ "engines": {
719
+ "node": "6.* || 8.* || >= 10.*"
720
+ }
721
+ },
722
+ "node_modules/http-parser-js": {
723
+ "version": "0.5.8",
724
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
725
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q=="
726
+ },
727
+ "node_modules/idb": {
728
+ "version": "7.1.1",
729
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
730
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="
731
+ },
732
+ "node_modules/is-fullwidth-code-point": {
733
+ "version": "3.0.0",
734
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
735
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
736
+ "engines": {
737
+ "node": ">=8"
738
+ }
739
+ },
740
+ "node_modules/js-tokens": {
741
+ "version": "4.0.0",
742
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
743
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
744
+ "peer": true
745
+ },
746
+ "node_modules/lodash.camelcase": {
747
+ "version": "4.3.0",
748
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
749
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
750
+ },
751
+ "node_modules/long": {
752
+ "version": "5.2.3",
753
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
754
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
755
+ },
756
+ "node_modules/loose-envify": {
757
+ "version": "1.4.0",
758
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
759
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
760
+ "peer": true,
761
+ "dependencies": {
762
+ "js-tokens": "^3.0.0 || ^4.0.0"
763
+ },
764
+ "bin": {
765
+ "loose-envify": "cli.js"
766
+ }
767
+ },
768
+ "node_modules/protobufjs": {
769
+ "version": "7.2.6",
770
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz",
771
+ "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==",
772
+ "hasInstallScript": true,
773
+ "dependencies": {
774
+ "@protobufjs/aspromise": "^1.1.2",
775
+ "@protobufjs/base64": "^1.1.2",
776
+ "@protobufjs/codegen": "^2.0.4",
777
+ "@protobufjs/eventemitter": "^1.1.0",
778
+ "@protobufjs/fetch": "^1.1.0",
779
+ "@protobufjs/float": "^1.0.2",
780
+ "@protobufjs/inquire": "^1.1.0",
781
+ "@protobufjs/path": "^1.1.2",
782
+ "@protobufjs/pool": "^1.1.0",
783
+ "@protobufjs/utf8": "^1.1.0",
784
+ "@types/node": ">=13.7.0",
785
+ "long": "^5.0.0"
786
+ },
787
+ "engines": {
788
+ "node": ">=12.0.0"
789
+ }
790
+ },
791
+ "node_modules/react": {
792
+ "version": "18.2.0",
793
+ "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
794
+ "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
795
+ "peer": true,
796
+ "dependencies": {
797
+ "loose-envify": "^1.1.0"
798
+ },
799
+ "engines": {
800
+ "node": ">=0.10.0"
801
+ }
802
+ },
803
+ "node_modules/react-chartjs-2": {
804
+ "version": "5.2.0",
805
+ "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz",
806
+ "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==",
807
+ "peerDependencies": {
808
+ "chart.js": "^4.1.1",
809
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
810
+ }
811
+ },
812
+ "node_modules/require-directory": {
813
+ "version": "2.1.1",
814
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
815
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
816
+ "engines": {
817
+ "node": ">=0.10.0"
818
+ }
819
+ },
820
+ "node_modules/safe-buffer": {
821
+ "version": "5.2.1",
822
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
823
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
824
+ "funding": [
825
+ {
826
+ "type": "github",
827
+ "url": "https://github.com/sponsors/feross"
828
+ },
829
+ {
830
+ "type": "patreon",
831
+ "url": "https://www.patreon.com/feross"
832
+ },
833
+ {
834
+ "type": "consulting",
835
+ "url": "https://feross.org/support"
836
+ }
837
+ ]
838
+ },
839
+ "node_modules/string-width": {
840
+ "version": "4.2.3",
841
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
842
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
843
+ "dependencies": {
844
+ "emoji-regex": "^8.0.0",
845
+ "is-fullwidth-code-point": "^3.0.0",
846
+ "strip-ansi": "^6.0.1"
847
+ },
848
+ "engines": {
849
+ "node": ">=8"
850
+ }
851
+ },
852
+ "node_modules/strip-ansi": {
853
+ "version": "6.0.1",
854
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
855
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
856
+ "dependencies": {
857
+ "ansi-regex": "^5.0.1"
858
+ },
859
+ "engines": {
860
+ "node": ">=8"
861
+ }
862
+ },
863
+ "node_modules/tslib": {
864
+ "version": "2.6.2",
865
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
866
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
867
+ },
868
+ "node_modules/undici": {
869
+ "version": "5.26.5",
870
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.5.tgz",
871
+ "integrity": "sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==",
872
+ "dependencies": {
873
+ "@fastify/busboy": "^2.0.0"
874
+ },
875
+ "engines": {
876
+ "node": ">=14.0"
877
+ }
878
+ },
879
+ "node_modules/undici-types": {
880
+ "version": "5.26.5",
881
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
882
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
883
+ },
884
+ "node_modules/websocket-driver": {
885
+ "version": "0.7.4",
886
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
887
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
888
+ "dependencies": {
889
+ "http-parser-js": ">=0.5.1",
890
+ "safe-buffer": ">=5.1.0",
891
+ "websocket-extensions": ">=0.1.1"
892
+ },
893
+ "engines": {
894
+ "node": ">=0.8.0"
895
+ }
896
+ },
897
+ "node_modules/websocket-extensions": {
898
+ "version": "0.1.4",
899
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
900
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
901
+ "engines": {
902
+ "node": ">=0.8.0"
903
+ }
904
+ },
905
+ "node_modules/wrap-ansi": {
906
+ "version": "7.0.0",
907
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
908
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
909
+ "dependencies": {
910
+ "ansi-styles": "^4.0.0",
911
+ "string-width": "^4.1.0",
912
+ "strip-ansi": "^6.0.0"
913
+ },
914
+ "engines": {
915
+ "node": ">=10"
916
+ },
917
+ "funding": {
918
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
919
+ }
920
+ },
921
+ "node_modules/y18n": {
922
+ "version": "5.0.8",
923
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
924
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
925
+ "engines": {
926
+ "node": ">=10"
927
+ }
928
+ },
929
+ "node_modules/yargs": {
930
+ "version": "17.7.2",
931
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
932
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
933
+ "dependencies": {
934
+ "cliui": "^8.0.1",
935
+ "escalade": "^3.1.1",
936
+ "get-caller-file": "^2.0.5",
937
+ "require-directory": "^2.1.1",
938
+ "string-width": "^4.2.3",
939
+ "y18n": "^5.0.5",
940
+ "yargs-parser": "^21.1.1"
941
+ },
942
+ "engines": {
943
+ "node": ">=12"
944
+ }
945
+ },
946
+ "node_modules/yargs-parser": {
947
+ "version": "21.1.1",
948
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
949
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
950
+ "engines": {
951
+ "node": ">=12"
952
+ }
953
+ }
954
+ }
955
+ }
node_modules/@fastify/busboy/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright Brian White. All rights reserved.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ IN THE SOFTWARE.
node_modules/@fastify/busboy/README.md ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # busboy
2
+
3
+ <div align="center">
4
+
5
+ [![Build Status](https://github.com/fastify/busboy/workflows/ci/badge.svg)](https://github.com/fastify/busboy/actions)
6
+ [![Coverage Status](https://coveralls.io/repos/fastify/busboy/badge.svg?branch=master)](https://coveralls.io/r/fastify/busboy?branch=master)
7
+ [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
8
+ [![Security Responsible Disclosure](https://img.shields.io/badge/Security-Responsible%20Disclosure-yellow.svg)](https://github.com/nodejs/security-wg/blob/HEAD/processes/responsible_disclosure_template.md)
9
+
10
+ </div>
11
+
12
+ <div align="center">
13
+
14
+ [![NPM version](https://img.shields.io/npm/v/@fastify/busboy.svg?style=flat)](https://www.npmjs.com/package/@fastify/busboy)
15
+ [![NPM downloads](https://img.shields.io/npm/dm/@fastify/busboy.svg?style=flat)](https://www.npmjs.com/package/@fastify/busboy)
16
+
17
+ </div>
18
+
19
+ Description
20
+ ===========
21
+
22
+ A Node.js module for parsing incoming HTML form data.
23
+
24
+ This is an officially supported fork by [fastify](https://github.com/fastify/) organization of the amazing library [originally created](https://github.com/mscdex/busboy) by Brian White,
25
+ aimed at addressing long-standing issues with it.
26
+
27
+ Benchmark (Mean time for 500 Kb payload, 2000 cycles, 1000 cycle warmup):
28
+
29
+ | Library | Version | Mean time in nanoseconds (less is better) |
30
+ |-----------------------|---------|-------------------------------------------|
31
+ | busboy | 0.3.1 | `340114` |
32
+ | @fastify/busboy | 1.0.0 | `270984` |
33
+
34
+ [Changelog](https://github.com/fastify/busboy/blob/master/CHANGELOG.md) since busboy 0.31.
35
+
36
+ Requirements
37
+ ============
38
+
39
+ * [Node.js](http://nodejs.org/) 10+
40
+
41
+
42
+ Install
43
+ =======
44
+
45
+ npm i @fastify/busboy
46
+
47
+
48
+ Examples
49
+ ========
50
+
51
+ * Parsing (multipart) with default options:
52
+
53
+ ```javascript
54
+ const http = require('node:http');
55
+ const { inspect } = require('node:util');
56
+ const Busboy = require('busboy');
57
+
58
+ http.createServer((req, res) => {
59
+ if (req.method === 'POST') {
60
+ const busboy = new Busboy({ headers: req.headers });
61
+ busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
62
+ console.log(`File [${fieldname}]: filename: ${filename}, encoding: ${encoding}, mimetype: ${mimetype}`);
63
+ file.on('data', data => {
64
+ console.log(`File [${fieldname}] got ${data.length} bytes`);
65
+ });
66
+ file.on('end', () => {
67
+ console.log(`File [${fieldname}] Finished`);
68
+ });
69
+ });
70
+ busboy.on('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => {
71
+ console.log(`Field [${fieldname}]: value: ${inspect(val)}`);
72
+ });
73
+ busboy.on('finish', () => {
74
+ console.log('Done parsing form!');
75
+ res.writeHead(303, { Connection: 'close', Location: '/' });
76
+ res.end();
77
+ });
78
+ req.pipe(busboy);
79
+ } else if (req.method === 'GET') {
80
+ res.writeHead(200, { Connection: 'close' });
81
+ res.end(`<html><head></head><body>
82
+ <form method="POST" enctype="multipart/form-data">
83
+ <input type="text" name="textfield"><br>
84
+ <input type="file" name="filefield"><br>
85
+ <input type="submit">
86
+ </form>
87
+ </body></html>`);
88
+ }
89
+ }).listen(8000, () => {
90
+ console.log('Listening for requests');
91
+ });
92
+
93
+ // Example output, using http://nodejs.org/images/ryan-speaker.jpg as the file:
94
+ //
95
+ // Listening for requests
96
+ // File [filefield]: filename: ryan-speaker.jpg, encoding: binary
97
+ // File [filefield] got 11971 bytes
98
+ // Field [textfield]: value: 'testing! :-)'
99
+ // File [filefield] Finished
100
+ // Done parsing form!
101
+ ```
102
+
103
+ * Save all incoming files to disk:
104
+
105
+ ```javascript
106
+ const http = require('node:http');
107
+ const path = require('node:path');
108
+ const os = require('node:os');
109
+ const fs = require('node:fs');
110
+
111
+ const Busboy = require('busboy');
112
+
113
+ http.createServer(function(req, res) {
114
+ if (req.method === 'POST') {
115
+ const busboy = new Busboy({ headers: req.headers });
116
+ busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
117
+ var saveTo = path.join(os.tmpdir(), path.basename(fieldname));
118
+ file.pipe(fs.createWriteStream(saveTo));
119
+ });
120
+ busboy.on('finish', function() {
121
+ res.writeHead(200, { 'Connection': 'close' });
122
+ res.end("That's all folks!");
123
+ });
124
+ return req.pipe(busboy);
125
+ }
126
+ res.writeHead(404);
127
+ res.end();
128
+ }).listen(8000, function() {
129
+ console.log('Listening for requests');
130
+ });
131
+ ```
132
+
133
+ * Parsing (urlencoded) with default options:
134
+
135
+ ```javascript
136
+ const http = require('node:http');
137
+ const { inspect } = require('node:util');
138
+
139
+ const Busboy = require('busboy');
140
+
141
+ http.createServer(function(req, res) {
142
+ if (req.method === 'POST') {
143
+ const busboy = new Busboy({ headers: req.headers });
144
+ busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
145
+ console.log('File [' + fieldname + ']: filename: ' + filename);
146
+ file.on('data', function(data) {
147
+ console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
148
+ });
149
+ file.on('end', function() {
150
+ console.log('File [' + fieldname + '] Finished');
151
+ });
152
+ });
153
+ busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
154
+ console.log('Field [' + fieldname + ']: value: ' + inspect(val));
155
+ });
156
+ busboy.on('finish', function() {
157
+ console.log('Done parsing form!');
158
+ res.writeHead(303, { Connection: 'close', Location: '/' });
159
+ res.end();
160
+ });
161
+ req.pipe(busboy);
162
+ } else if (req.method === 'GET') {
163
+ res.writeHead(200, { Connection: 'close' });
164
+ res.end('<html><head></head><body>\
165
+ <form method="POST">\
166
+ <input type="text" name="textfield"><br />\
167
+ <select name="selectfield">\
168
+ <option value="1">1</option>\
169
+ <option value="10">10</option>\
170
+ <option value="100">100</option>\
171
+ <option value="9001">9001</option>\
172
+ </select><br />\
173
+ <input type="checkbox" name="checkfield">Node.js rules!<br />\
174
+ <input type="submit">\
175
+ </form>\
176
+ </body></html>');
177
+ }
178
+ }).listen(8000, function() {
179
+ console.log('Listening for requests');
180
+ });
181
+
182
+ // Example output:
183
+ //
184
+ // Listening for requests
185
+ // Field [textfield]: value: 'testing! :-)'
186
+ // Field [selectfield]: value: '9001'
187
+ // Field [checkfield]: value: 'on'
188
+ // Done parsing form!
189
+ ```
190
+
191
+
192
+ API
193
+ ===
194
+
195
+ _Busboy_ is a _Writable_ stream
196
+
197
+ Busboy (special) events
198
+ -----------------------
199
+
200
+ * **file**(< _string_ >fieldname, < _ReadableStream_ >stream, < _string_ >filename, < _string_ >transferEncoding, < _string_ >mimeType) - Emitted for each new file form field found. `transferEncoding` contains the 'Content-Transfer-Encoding' value for the file stream. `mimeType` contains the 'Content-Type' value for the file stream.
201
+ * Note: if you listen for this event, you should always handle the `stream` no matter if you care about the file contents or not (e.g. you can simply just do `stream.resume();` if you want to discard the contents), otherwise the 'finish' event will never fire on the Busboy instance. However, if you don't care about **any** incoming files, you can simply not listen for the 'file' event at all and any/all files will be automatically and safely discarded (these discarded files do still count towards `files` and `parts` limits).
202
+ * If a configured file size limit was reached, `stream` will both have a boolean property `truncated` (best checked at the end of the stream) and emit a 'limit' event to notify you when this happens.
203
+ * The property `bytesRead` informs about the number of bytes that have been read so far.
204
+
205
+ * **field**(< _string_ >fieldname, < _string_ >value, < _boolean_ >fieldnameTruncated, < _boolean_ >valueTruncated, < _string_ >transferEncoding, < _string_ >mimeType) - Emitted for each new non-file field found.
206
+
207
+ * **partsLimit**() - Emitted when specified `parts` limit has been reached. No more 'file' or 'field' events will be emitted.
208
+
209
+ * **filesLimit**() - Emitted when specified `files` limit has been reached. No more 'file' events will be emitted.
210
+
211
+ * **fieldsLimit**() - Emitted when specified `fields` limit has been reached. No more 'field' events will be emitted.
212
+
213
+
214
+ Busboy methods
215
+ --------------
216
+
217
+ * **(constructor)**(< _object_ >config) - Creates and returns a new Busboy instance.
218
+
219
+ * The constructor takes the following valid `config` settings:
220
+
221
+ * **headers** - _object_ - These are the HTTP headers of the incoming request, which are used by individual parsers.
222
+
223
+ * **autoDestroy** - _boolean_ - Whether this stream should automatically call .destroy() on itself after ending. (Default: false).
224
+
225
+ * **highWaterMark** - _integer_ - highWaterMark to use for this Busboy instance (Default: WritableStream default).
226
+
227
+ * **fileHwm** - _integer_ - highWaterMark to use for file streams (Default: ReadableStream default).
228
+
229
+ * **defCharset** - _string_ - Default character set to use when one isn't defined (Default: 'utf8').
230
+
231
+ * **preservePath** - _boolean_ - If paths in the multipart 'filename' field shall be preserved. (Default: false).
232
+
233
+ * **isPartAFile** - __function__ - Use this function to override the default file detection functionality. It has following parameters:
234
+
235
+ * fieldName - __string__ The name of the field.
236
+
237
+ * contentType - __string__ The content-type of the part, e.g. `text/plain`, `image/jpeg`, `application/octet-stream`
238
+
239
+ * fileName - __string__ The name of a file supplied by the part.
240
+
241
+ (Default: `(fieldName, contentType, fileName) => (contentType === 'application/octet-stream' || fileName !== undefined)`)
242
+
243
+ * **limits** - _object_ - Various limits on incoming data. Valid properties are:
244
+
245
+ * **fieldNameSize** - _integer_ - Max field name size (in bytes) (Default: 100 bytes).
246
+
247
+ * **fieldSize** - _integer_ - Max field value size (in bytes) (Default: 1 MiB, which is 1024 x 1024 bytes).
248
+
249
+ * **fields** - _integer_ - Max number of non-file fields (Default: Infinity).
250
+
251
+ * **fileSize** - _integer_ - For multipart forms, the max file size (in bytes) (Default: Infinity).
252
+
253
+ * **files** - _integer_ - For multipart forms, the max number of file fields (Default: Infinity).
254
+
255
+ * **parts** - _integer_ - For multipart forms, the max number of parts (fields + files) (Default: Infinity).
256
+
257
+ * **headerPairs** - _integer_ - For multipart forms, the max number of header key=>value pairs to parse **Default:** 2000
258
+
259
+ * **headerSize** - _integer_ - For multipart forms, the max size of a multipart header **Default:** 81920.
260
+
261
+ * The constructor can throw errors:
262
+
263
+ * **Busboy expected an options-Object.** - Busboy expected an Object as first parameters.
264
+
265
+ * **Busboy expected an options-Object with headers-attribute.** - The first parameter is lacking of a headers-attribute.
266
+
267
+ * **Limit $limit is not a valid number** - Busboy expected the desired limit to be of type number. Busboy throws this Error to prevent a potential security issue by falling silently back to the Busboy-defaults. Potential source for this Error can be the direct use of environment variables without transforming them to the type number.
268
+
269
+ * **Unsupported Content-Type.** - The `Content-Type` isn't one Busboy can parse.
270
+
271
+ * **Missing Content-Type-header.** - The provided headers don't include `Content-Type` at all.
node_modules/@fastify/busboy/deps/dicer/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright Brian White. All rights reserved.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ IN THE SOFTWARE.
node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict'
2
+
3
+ const WritableStream = require('node:stream').Writable
4
+ const inherits = require('node:util').inherits
5
+
6
+ const StreamSearch = require('../../streamsearch/sbmh')
7
+
8
+ const PartStream = require('./PartStream')
9
+ const HeaderParser = require('./HeaderParser')
10
+
11
+ const DASH = 45
12
+ const B_ONEDASH = Buffer.from('-')
13
+ const B_CRLF = Buffer.from('\r\n')
14
+ const EMPTY_FN = function () {}
15
+
16
+ function Dicer (cfg) {
17
+ if (!(this instanceof Dicer)) { return new Dicer(cfg) }
18
+ WritableStream.call(this, cfg)
19
+
20
+ if (!cfg || (!cfg.headerFirst && typeof cfg.boundary !== 'string')) { throw new TypeError('Boundary required') }
21
+
22
+ if (typeof cfg.boundary === 'string') { this.setBoundary(cfg.boundary) } else { this._bparser = undefined }
23
+
24
+ this._headerFirst = cfg.headerFirst
25
+
26
+ this._dashes = 0
27
+ this._parts = 0
28
+ this._finished = false
29
+ this._realFinish = false
30
+ this._isPreamble = true
31
+ this._justMatched = false
32
+ this._firstWrite = true
33
+ this._inHeader = true
34
+ this._part = undefined
35
+ this._cb = undefined
36
+ this._ignoreData = false
37
+ this._partOpts = { highWaterMark: cfg.partHwm }
38
+ this._pause = false
39
+
40
+ const self = this
41
+ this._hparser = new HeaderParser(cfg)
42
+ this._hparser.on('header', function (header) {
43
+ self._inHeader = false
44
+ self._part.emit('header', header)
45
+ })
46
+ }
47
+ inherits(Dicer, WritableStream)
48
+
49
+ Dicer.prototype.emit = function (ev) {
50
+ if (ev === 'finish' && !this._realFinish) {
51
+ if (!this._finished) {
52
+ const self = this
53
+ process.nextTick(function () {
54
+ self.emit('error', new Error('Unexpected end of multipart data'))
55
+ if (self._part && !self._ignoreData) {
56
+ const type = (self._isPreamble ? 'Preamble' : 'Part')
57
+ self._part.emit('error', new Error(type + ' terminated early due to unexpected end of multipart data'))
58
+ self._part.push(null)
59
+ process.nextTick(function () {
60
+ self._realFinish = true
61
+ self.emit('finish')
62
+ self._realFinish = false
63
+ })
64
+ return
65
+ }
66
+ self._realFinish = true
67
+ self.emit('finish')
68
+ self._realFinish = false
69
+ })
70
+ }
71
+ } else { WritableStream.prototype.emit.apply(this, arguments) }
72
+ }
73
+
74
+ Dicer.prototype._write = function (data, encoding, cb) {
75
+ // ignore unexpected data (e.g. extra trailer data after finished)
76
+ if (!this._hparser && !this._bparser) { return cb() }
77
+
78
+ if (this._headerFirst && this._isPreamble) {
79
+ if (!this._part) {
80
+ this._part = new PartStream(this._partOpts)
81
+ if (this._events.preamble) { this.emit('preamble', this._part) } else { this._ignore() }
82
+ }
83
+ const r = this._hparser.push(data)
84
+ if (!this._inHeader && r !== undefined && r < data.length) { data = data.slice(r) } else { return cb() }
85
+ }
86
+
87
+ // allows for "easier" testing
88
+ if (this._firstWrite) {
89
+ this._bparser.push(B_CRLF)
90
+ this._firstWrite = false
91
+ }
92
+
93
+ this._bparser.push(data)
94
+
95
+ if (this._pause) { this._cb = cb } else { cb() }
96
+ }
97
+
98
+ Dicer.prototype.reset = function () {
99
+ this._part = undefined
100
+ this._bparser = undefined
101
+ this._hparser = undefined
102
+ }
103
+
104
+ Dicer.prototype.setBoundary = function (boundary) {
105
+ const self = this
106
+ this._bparser = new StreamSearch('\r\n--' + boundary)
107
+ this._bparser.on('info', function (isMatch, data, start, end) {
108
+ self._oninfo(isMatch, data, start, end)
109
+ })
110
+ }
111
+
112
+ Dicer.prototype._ignore = function () {
113
+ if (this._part && !this._ignoreData) {
114
+ this._ignoreData = true
115
+ this._part.on('error', EMPTY_FN)
116
+ // we must perform some kind of read on the stream even though we are
117
+ // ignoring the data, otherwise node's Readable stream will not emit 'end'
118
+ // after pushing null to the stream
119
+ this._part.resume()
120
+ }
121
+ }
122
+
123
+ Dicer.prototype._oninfo = function (isMatch, data, start, end) {
124
+ let buf; const self = this; let i = 0; let r; let shouldWriteMore = true
125
+
126
+ if (!this._part && this._justMatched && data) {
127
+ while (this._dashes < 2 && (start + i) < end) {
128
+ if (data[start + i] === DASH) {
129
+ ++i
130
+ ++this._dashes
131
+ } else {
132
+ if (this._dashes) { buf = B_ONEDASH }
133
+ this._dashes = 0
134
+ break
135
+ }
136
+ }
137
+ if (this._dashes === 2) {
138
+ if ((start + i) < end && this._events.trailer) { this.emit('trailer', data.slice(start + i, end)) }
139
+ this.reset()
140
+ this._finished = true
141
+ // no more parts will be added
142
+ if (self._parts === 0) {
143
+ self._realFinish = true
144
+ self.emit('finish')
145
+ self._realFinish = false
146
+ }
147
+ }
148
+ if (this._dashes) { return }
149
+ }
150
+ if (this._justMatched) { this._justMatched = false }
151
+ if (!this._part) {
152
+ this._part = new PartStream(this._partOpts)
153
+ this._part._read = function (n) {
154
+ self._unpause()
155
+ }
156
+ if (this._isPreamble && this._events.preamble) { this.emit('preamble', this._part) } else if (this._isPreamble !== true && this._events.part) { this.emit('part', this._part) } else { this._ignore() }
157
+ if (!this._isPreamble) { this._inHeader = true }
158
+ }
159
+ if (data && start < end && !this._ignoreData) {
160
+ if (this._isPreamble || !this._inHeader) {
161
+ if (buf) { shouldWriteMore = this._part.push(buf) }
162
+ shouldWriteMore = this._part.push(data.slice(start, end))
163
+ if (!shouldWriteMore) { this._pause = true }
164
+ } else if (!this._isPreamble && this._inHeader) {
165
+ if (buf) { this._hparser.push(buf) }
166
+ r = this._hparser.push(data.slice(start, end))
167
+ if (!this._inHeader && r !== undefined && r < end) { this._oninfo(false, data, start + r, end) }
168
+ }
169
+ }
170
+ if (isMatch) {
171
+ this._hparser.reset()
172
+ if (this._isPreamble) { this._isPreamble = false } else {
173
+ if (start !== end) {
174
+ ++this._parts
175
+ this._part.on('end', function () {
176
+ if (--self._parts === 0) {
177
+ if (self._finished) {
178
+ self._realFinish = true
179
+ self.emit('finish')
180
+ self._realFinish = false
181
+ } else {
182
+ self._unpause()
183
+ }
184
+ }
185
+ })
186
+ }
187
+ }
188
+ this._part.push(null)
189
+ this._part = undefined
190
+ this._ignoreData = false
191
+ this._justMatched = true
192
+ this._dashes = 0
193
+ }
194
+ }
195
+
196
+ Dicer.prototype._unpause = function () {
197
+ if (!this._pause) { return }
198
+
199
+ this._pause = false
200
+ if (this._cb) {
201
+ const cb = this._cb
202
+ this._cb = undefined
203
+ cb()
204
+ }
205
+ }
206
+
207
+ module.exports = Dicer
node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict'
2
+
3
+ const EventEmitter = require('node:events').EventEmitter
4
+ const inherits = require('node:util').inherits
5
+ const getLimit = require('../../../lib/utils/getLimit')
6
+
7
+ const StreamSearch = require('../../streamsearch/sbmh')
8
+
9
+ const B_DCRLF = Buffer.from('\r\n\r\n')
10
+ const RE_CRLF = /\r\n/g
11
+ const RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/ // eslint-disable-line no-control-regex
12
+
13
+ function HeaderParser (cfg) {
14
+ EventEmitter.call(this)
15
+
16
+ cfg = cfg || {}
17
+ const self = this
18
+ this.nread = 0
19
+ this.maxed = false
20
+ this.npairs = 0
21
+ this.maxHeaderPairs = getLimit(cfg, 'maxHeaderPairs', 2000)
22
+ this.maxHeaderSize = getLimit(cfg, 'maxHeaderSize', 80 * 1024)
23
+ this.buffer = ''
24
+ this.header = {}
25
+ this.finished = false
26
+ this.ss = new StreamSearch(B_DCRLF)
27
+ this.ss.on('info', function (isMatch, data, start, end) {
28
+ if (data && !self.maxed) {
29
+ if (self.nread + end - start >= self.maxHeaderSize) {
30
+ end = self.maxHeaderSize - self.nread + start
31
+ self.nread = self.maxHeaderSize
32
+ self.maxed = true
33
+ } else { self.nread += (end - start) }
34
+
35
+ self.buffer += data.toString('binary', start, end)
36
+ }
37
+ if (isMatch) { self._finish() }
38
+ })
39
+ }
40
+ inherits(HeaderParser, EventEmitter)
41
+
42
+ HeaderParser.prototype.push = function (data) {
43
+ const r = this.ss.push(data)
44
+ if (this.finished) { return r }
45
+ }
46
+
47
+ HeaderParser.prototype.reset = function () {
48
+ this.finished = false
49
+ this.buffer = ''
50
+ this.header = {}
51
+ this.ss.reset()
52
+ }
53
+
54
+ HeaderParser.prototype._finish = function () {
55
+ if (this.buffer) { this._parseHeader() }
56
+ this.ss.matches = this.ss.maxMatches
57
+ const header = this.header
58
+ this.header = {}
59
+ this.buffer = ''
60
+ this.finished = true
61
+ this.nread = this.npairs = 0
62
+ this.maxed = false
63
+ this.emit('header', header)
64
+ }
65
+
66
+ HeaderParser.prototype._parseHeader = function () {
67
+ if (this.npairs === this.maxHeaderPairs) { return }
68
+
69
+ const lines = this.buffer.split(RE_CRLF)
70
+ const len = lines.length
71
+ let m, h
72
+
73
+ for (var i = 0; i < len; ++i) { // eslint-disable-line no-var
74
+ if (lines[i].length === 0) { continue }
75
+ if (lines[i][0] === '\t' || lines[i][0] === ' ') {
76
+ // folded header content
77
+ // RFC2822 says to just remove the CRLF and not the whitespace following
78
+ // it, so we follow the RFC and include the leading whitespace ...
79
+ if (h) {
80
+ this.header[h][this.header[h].length - 1] += lines[i]
81
+ continue
82
+ }
83
+ }
84
+
85
+ const posColon = lines[i].indexOf(':')
86
+ if (
87
+ posColon === -1 ||
88
+ posColon === 0
89
+ ) {
90
+ return
91
+ }
92
+ m = RE_HDR.exec(lines[i])
93
+ h = m[1].toLowerCase()
94
+ this.header[h] = this.header[h] || []
95
+ this.header[h].push((m[2] || ''))
96
+ if (++this.npairs === this.maxHeaderPairs) { break }
97
+ }
98
+ }
99
+
100
+ module.exports = HeaderParser
node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use strict'
2
+
3
+ const inherits = require('node:util').inherits
4
+ const ReadableStream = require('node:stream').Readable
5
+
6
+ function PartStream (opts) {
7
+ ReadableStream.call(this, opts)
8
+ }
9
+ inherits(PartStream, ReadableStream)
10
+
11
+ PartStream.prototype._read = function (n) {}
12
+
13
+ module.exports = PartStream
node_modules/@fastify/busboy/deps/dicer/lib/dicer.d.ts ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Type definitions for dicer 0.2
2
+ // Project: https://github.com/mscdex/dicer
3
+ // Definitions by: BendingBender <https://github.com/BendingBender>
4
+ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
5
+ // TypeScript Version: 2.2
6
+ /// <reference types="node" />
7
+
8
+ import stream = require("stream");
9
+
10
+ // tslint:disable:unified-signatures
11
+
12
+ /**
13
+ * A very fast streaming multipart parser for node.js.
14
+ * Dicer is a WritableStream
15
+ *
16
+ * Dicer (special) events:
17
+ * - on('finish', ()) - Emitted when all parts have been parsed and the Dicer instance has been ended.
18
+ * - on('part', (stream: PartStream)) - Emitted when a new part has been found.
19
+ * - on('preamble', (stream: PartStream)) - Emitted for preamble if you should happen to need it (can usually be ignored).
20
+ * - on('trailer', (data: Buffer)) - Emitted when trailing data was found after the terminating boundary (as with the preamble, this can usually be ignored too).
21
+ */
22
+ export class Dicer extends stream.Writable {
23
+ /**
24
+ * Creates and returns a new Dicer instance with the following valid config settings:
25
+ *
26
+ * @param config The configuration to use
27
+ */
28
+ constructor(config: Dicer.Config);
29
+ /**
30
+ * Sets the boundary to use for parsing and performs some initialization needed for parsing.
31
+ * You should only need to use this if you set headerFirst to true in the constructor and are parsing the boundary from the preamble header.
32
+ *
33
+ * @param boundary The boundary to use
34
+ */
35
+ setBoundary(boundary: string): void;
36
+ addListener(event: "finish", listener: () => void): this;
37
+ addListener(event: "part", listener: (stream: Dicer.PartStream) => void): this;
38
+ addListener(event: "preamble", listener: (stream: Dicer.PartStream) => void): this;
39
+ addListener(event: "trailer", listener: (data: Buffer) => void): this;
40
+ addListener(event: "close", listener: () => void): this;
41
+ addListener(event: "drain", listener: () => void): this;
42
+ addListener(event: "error", listener: (err: Error) => void): this;
43
+ addListener(event: "pipe", listener: (src: stream.Readable) => void): this;
44
+ addListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
45
+ addListener(event: string, listener: (...args: any[]) => void): this;
46
+ on(event: "finish", listener: () => void): this;
47
+ on(event: "part", listener: (stream: Dicer.PartStream) => void): this;
48
+ on(event: "preamble", listener: (stream: Dicer.PartStream) => void): this;
49
+ on(event: "trailer", listener: (data: Buffer) => void): this;
50
+ on(event: "close", listener: () => void): this;
51
+ on(event: "drain", listener: () => void): this;
52
+ on(event: "error", listener: (err: Error) => void): this;
53
+ on(event: "pipe", listener: (src: stream.Readable) => void): this;
54
+ on(event: "unpipe", listener: (src: stream.Readable) => void): this;
55
+ on(event: string, listener: (...args: any[]) => void): this;
56
+ once(event: "finish", listener: () => void): this;
57
+ once(event: "part", listener: (stream: Dicer.PartStream) => void): this;
58
+ once(event: "preamble", listener: (stream: Dicer.PartStream) => void): this;
59
+ once(event: "trailer", listener: (data: Buffer) => void): this;
60
+ once(event: "close", listener: () => void): this;
61
+ once(event: "drain", listener: () => void): this;
62
+ once(event: "error", listener: (err: Error) => void): this;
63
+ once(event: "pipe", listener: (src: stream.Readable) => void): this;
64
+ once(event: "unpipe", listener: (src: stream.Readable) => void): this;
65
+ once(event: string, listener: (...args: any[]) => void): this;
66
+ prependListener(event: "finish", listener: () => void): this;
67
+ prependListener(event: "part", listener: (stream: Dicer.PartStream) => void): this;
68
+ prependListener(event: "preamble", listener: (stream: Dicer.PartStream) => void): this;
69
+ prependListener(event: "trailer", listener: (data: Buffer) => void): this;
70
+ prependListener(event: "close", listener: () => void): this;
71
+ prependListener(event: "drain", listener: () => void): this;
72
+ prependListener(event: "error", listener: (err: Error) => void): this;
73
+ prependListener(event: "pipe", listener: (src: stream.Readable) => void): this;
74
+ prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
75
+ prependListener(event: string, listener: (...args: any[]) => void): this;
76
+ prependOnceListener(event: "finish", listener: () => void): this;
77
+ prependOnceListener(event: "part", listener: (stream: Dicer.PartStream) => void): this;
78
+ prependOnceListener(event: "preamble", listener: (stream: Dicer.PartStream) => void): this;
79
+ prependOnceListener(event: "trailer", listener: (data: Buffer) => void): this;
80
+ prependOnceListener(event: "close", listener: () => void): this;
81
+ prependOnceListener(event: "drain", listener: () => void): this;
82
+ prependOnceListener(event: "error", listener: (err: Error) => void): this;
83
+ prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this;
84
+ prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
85
+ prependOnceListener(event: string, listener: (...args: any[]) => void): this;
86
+ removeListener(event: "finish", listener: () => void): this;
87
+ removeListener(event: "part", listener: (stream: Dicer.PartStream) => void): this;
88
+ removeListener(event: "preamble", listener: (stream: Dicer.PartStream) => void): this;
89
+ removeListener(event: "trailer", listener: (data: Buffer) => void): this;
90
+ removeListener(event: "close", listener: () => void): this;
91
+ removeListener(event: "drain", listener: () => void): this;
92
+ removeListener(event: "error", listener: (err: Error) => void): this;
93
+ removeListener(event: "pipe", listener: (src: stream.Readable) => void): this;
94
+ removeListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
95
+ removeListener(event: string, listener: (...args: any[]) => void): this;
96
+ }
97
+
98
+ declare namespace Dicer {
99
+ interface Config {
100
+ /**
101
+ * This is the boundary used to detect the beginning of a new part.
102
+ */
103
+ boundary?: string | undefined;
104
+ /**
105
+ * If true, preamble header parsing will be performed first.
106
+ */
107
+ headerFirst?: boolean | undefined;
108
+ /**
109
+ * The maximum number of header key=>value pairs to parse Default: 2000 (same as node's http).
110
+ */
111
+ maxHeaderPairs?: number | undefined;
112
+ }
113
+
114
+ /**
115
+ * PartStream is a _ReadableStream_
116
+ *
117
+ * PartStream (special) events:
118
+ * - on('header', (header: object)) - An object containing the header for this particular part. Each property value is an array of one or more string values.
119
+ */
120
+ interface PartStream extends stream.Readable {
121
+ addListener(event: "header", listener: (header: object) => void): this;
122
+ addListener(event: "close", listener: () => void): this;
123
+ addListener(event: "data", listener: (chunk: Buffer | string) => void): this;
124
+ addListener(event: "end", listener: () => void): this;
125
+ addListener(event: "readable", listener: () => void): this;
126
+ addListener(event: "error", listener: (err: Error) => void): this;
127
+ addListener(event: string, listener: (...args: any[]) => void): this;
128
+ on(event: "header", listener: (header: object) => void): this;
129
+ on(event: "close", listener: () => void): this;
130
+ on(event: "data", listener: (chunk: Buffer | string) => void): this;
131
+ on(event: "end", listener: () => void): this;
132
+ on(event: "readable", listener: () => void): this;
133
+ on(event: "error", listener: (err: Error) => void): this;
134
+ on(event: string, listener: (...args: any[]) => void): this;
135
+ once(event: "header", listener: (header: object) => void): this;
136
+ once(event: "close", listener: () => void): this;
137
+ once(event: "data", listener: (chunk: Buffer | string) => void): this;
138
+ once(event: "end", listener: () => void): this;
139
+ once(event: "readable", listener: () => void): this;
140
+ once(event: "error", listener: (err: Error) => void): this;
141
+ once(event: string, listener: (...args: any[]) => void): this;
142
+ prependListener(event: "header", listener: (header: object) => void): this;
143
+ prependListener(event: "close", listener: () => void): this;
144
+ prependListener(event: "data", listener: (chunk: Buffer | string) => void): this;
145
+ prependListener(event: "end", listener: () => void): this;
146
+ prependListener(event: "readable", listener: () => void): this;
147
+ prependListener(event: "error", listener: (err: Error) => void): this;
148
+ prependListener(event: string, listener: (...args: any[]) => void): this;
149
+ prependOnceListener(event: "header", listener: (header: object) => void): this;
150
+ prependOnceListener(event: "close", listener: () => void): this;
151
+ prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this;
152
+ prependOnceListener(event: "end", listener: () => void): this;
153
+ prependOnceListener(event: "readable", listener: () => void): this;
154
+ prependOnceListener(event: "error", listener: (err: Error) => void): this;
155
+ prependOnceListener(event: string, listener: (...args: any[]) => void): this;
156
+ removeListener(event: "header", listener: (header: object) => void): this;
157
+ removeListener(event: "close", listener: () => void): this;
158
+ removeListener(event: "data", listener: (chunk: Buffer | string) => void): this;
159
+ removeListener(event: "end", listener: () => void): this;
160
+ removeListener(event: "readable", listener: () => void): this;
161
+ removeListener(event: "error", listener: (err: Error) => void): this;
162
+ removeListener(event: string, listener: (...args: any[]) => void): this;
163
+ }
164
+ }