@necrolab/dashboard 0.4.221 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +27 -1
- package/.vscode/extensions.json +1 -1
- package/README.md +64 -2
- package/artwork/image.png +0 -0
- package/backend/api.js +26 -24
- package/backend/auth.js +2 -2
- package/backend/batching.js +1 -1
- package/backend/endpoints.js +8 -11
- package/backend/index.js +2 -2
- package/backend/mock-data.js +27 -36
- package/backend/mock-src/classes/logger.js +5 -7
- package/backend/mock-src/classes/utils.js +3 -2
- package/backend/mock-src/ticketmaster.js +4 -4
- package/backend/validator.js +2 -2
- package/config/configs.json +0 -1
- package/dev-server.js +134 -0
- package/exit +209 -0
- package/index.html +80 -8
- package/index.js +1 -1
- package/jsconfig.json +16 -0
- package/package.json +39 -25
- package/postcss.config.js +1 -1
- package/postinstall.js +124 -20
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/img/logo_trans.png +0 -0
- package/public/img/necro_logo.png +0 -0
- package/public/manifest.json +16 -10
- package/public/reconnect-logo.png +0 -0
- package/run +176 -9
- package/src/App.vue +498 -85
- package/src/assets/css/base/reset.scss +43 -0
- package/src/assets/css/base/scroll.scss +114 -0
- package/src/assets/css/base/typography.scss +37 -0
- package/src/assets/css/components/buttons.scss +216 -0
- package/src/assets/css/components/forms.scss +221 -0
- package/src/assets/css/components/modals.scss +13 -0
- package/src/assets/css/components/tables.scss +27 -0
- package/src/assets/css/components/toasts.scss +100 -0
- package/src/assets/css/main.scss +202 -122
- package/src/assets/img/background.svg +2 -2
- package/src/assets/img/background.svg.backup +11 -0
- package/src/assets/img/logo_trans.png +0 -0
- package/src/components/Auth/LoginForm.vue +95 -11
- package/src/components/Editors/Account/Account.vue +116 -40
- package/src/components/Editors/Account/AccountCreator.vue +88 -39
- package/src/components/Editors/Account/AccountView.vue +102 -34
- package/src/components/Editors/Account/CreateAccount.vue +80 -32
- package/src/components/Editors/Profile/CreateProfile.vue +269 -83
- package/src/components/Editors/Profile/Profile.vue +132 -47
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +82 -20
- package/src/components/Editors/Profile/ProfileView.vue +89 -32
- package/src/components/Editors/TagLabel.vue +67 -6
- package/src/components/Editors/TagToggle.vue +7 -2
- package/src/components/Filter/Filter.vue +288 -71
- package/src/components/Filter/FilterPreview.vue +202 -31
- package/src/components/Filter/PriceSortToggle.vue +76 -6
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Row.vue +1 -1
- package/src/components/Table/Table.vue +19 -2
- package/src/components/Tasks/CheckStock.vue +6 -8
- package/src/components/Tasks/Controls/DesktopControls.vue +27 -17
- package/src/components/Tasks/Controls/MobileControls.vue +8 -45
- package/src/components/Tasks/CreateTaskAXS.vue +80 -72
- package/src/components/Tasks/CreateTaskTM.vue +95 -141
- package/src/components/Tasks/MassEdit.vue +4 -6
- package/src/components/Tasks/QuickSettings.vue +199 -30
- package/src/components/Tasks/ScrapeVenue.vue +5 -6
- package/src/components/Tasks/Stats.vue +50 -24
- package/src/components/Tasks/Task.vue +384 -179
- package/src/components/Tasks/TaskLabel.vue +2 -2
- package/src/components/Tasks/TaskView.vue +136 -48
- package/src/components/Tasks/Utilities.vue +25 -10
- package/src/components/Tasks/ViewTask.vue +321 -0
- package/src/components/icons/Bag.vue +1 -1
- package/src/components/icons/Check.vue +5 -0
- package/src/components/icons/Close.vue +21 -0
- package/src/components/icons/CloseX.vue +5 -0
- package/src/components/icons/Eye.vue +6 -0
- package/src/components/icons/Key.vue +21 -0
- package/src/components/icons/Loyalty.vue +1 -1
- package/src/components/icons/Mail.vue +2 -2
- package/src/components/icons/Pencil.vue +21 -0
- package/src/components/icons/Play.vue +2 -2
- package/src/components/icons/Profile.vue +18 -0
- package/src/components/icons/Reload.vue +4 -5
- package/src/components/icons/Sandclock.vue +2 -2
- package/src/components/icons/Sell.vue +21 -0
- package/src/components/icons/Spinner.vue +42 -0
- package/src/components/icons/SquareCheck.vue +18 -0
- package/src/components/icons/SquareUncheck.vue +18 -0
- package/src/components/icons/Stadium.vue +1 -1
- package/src/components/icons/Wildcard.vue +18 -0
- package/src/components/icons/index.js +26 -1
- package/src/components/ui/Modal.vue +107 -13
- package/src/components/ui/Navbar.vue +175 -40
- package/src/components/ui/ReconnectIndicator.vue +351 -55
- package/src/components/ui/Splash.vue +5 -35
- package/src/components/ui/controls/CountryChooser.vue +200 -62
- package/src/components/ui/controls/atomic/Checkbox.vue +119 -10
- package/src/components/ui/controls/atomic/Dropdown.vue +216 -39
- package/src/components/ui/controls/atomic/LoadingButton.vue +45 -0
- package/src/components/ui/controls/atomic/MultiDropdown.vue +300 -37
- package/src/components/ui/controls/atomic/Switch.vue +53 -25
- package/src/composables/useClickOutside.js +21 -0
- package/src/composables/useDropdownPosition.js +174 -0
- package/src/libs/Filter.js +60 -24
- package/src/registerServiceWorker.js +1 -1
- package/src/stores/connection.js +4 -4
- package/src/stores/sampleData.js +172 -199
- package/src/stores/ui.js +55 -20
- package/src/stores/utils.js +30 -4
- package/src/types/index.js +41 -0
- package/src/utils/debug.js +1 -0
- package/src/views/Accounts.vue +116 -50
- package/src/views/Console.vue +394 -77
- package/src/views/Editor.vue +1176 -123
- package/src/views/FilterBuilder.vue +528 -250
- package/src/views/Login.vue +75 -14
- package/src/views/Profiles.vue +119 -34
- package/src/views/Tasks.vue +266 -98
- package/static/offline.html +192 -50
- package/switch-branch.sh +41 -0
- package/tailwind.config.js +119 -27
- package/vite.config.js +73 -16
- package/workbox-config.cjs +63 -0
- package/ICONS.md +0 -21
- package/public/img/background.svg +0 -14
- package/public/img/logo.png +0 -0
- package/public/img/logo_icon.png +0 -0
- package/public/img/logo_icon_2.png +0 -0
- package/src/assets/css/_input.scss +0 -143
- package/src/assets/img/logo.png +0 -0
- package/src/assets/img/logo_icon.png +0 -0
- package/src/assets/img/logo_icon_2.png +0 -0
- package/vue.config.js +0 -32
- package/workbox-config.js +0 -7
package/.prettierrc
CHANGED
|
@@ -6,5 +6,31 @@
|
|
|
6
6
|
"trailingComma": "none",
|
|
7
7
|
"bracketSpacing": true,
|
|
8
8
|
"arrowParens": "always",
|
|
9
|
-
"printWidth": 120
|
|
9
|
+
"printWidth": 120,
|
|
10
|
+
"vueIndentScriptAndStyle": false,
|
|
11
|
+
"htmlWhitespaceSensitivity": "ignore",
|
|
12
|
+
"bracketSameLine": true,
|
|
13
|
+
"singleAttributePerLine": false,
|
|
14
|
+
"endOfLine": "lf",
|
|
15
|
+
"overrides": [
|
|
16
|
+
{
|
|
17
|
+
"files": "*.vue",
|
|
18
|
+
"options": {
|
|
19
|
+
"vueIndentScriptAndStyle": false,
|
|
20
|
+
"htmlWhitespaceSensitivity": "ignore",
|
|
21
|
+
"singleAttributePerLine": false,
|
|
22
|
+
"bracketSameLine": true,
|
|
23
|
+
"printWidth": 120,
|
|
24
|
+
"tabWidth": 4,
|
|
25
|
+
"useTabs": false,
|
|
26
|
+
"semi": true,
|
|
27
|
+
"singleQuote": false,
|
|
28
|
+
"trailingComma": "none",
|
|
29
|
+
"bracketSpacing": true,
|
|
30
|
+
"arrowParens": "always"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"plugins": ["prettier-plugin-tailwindcss"],
|
|
35
|
+
"tailwindConfig": "./tailwind.config.js"
|
|
10
36
|
}
|
package/.vscode/extensions.json
CHANGED
package/README.md
CHANGED
|
@@ -1,3 +1,65 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./artwork/image.png" alt="Dashboard" width="400">
|
|
3
|
+
</div>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
# 🎫 Dashboard
|
|
6
|
+
|
|
7
|
+
A sophisticated PWA dashboard for managing ticket purchasing automation across multiple platforms. Built with Vue 3 and real-time WebSocket communication.
|
|
8
|
+
|
|
9
|
+
## ⚡ Quick Start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install
|
|
13
|
+
npm run dev
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Visit `http://localhost:5173` and you're live.
|
|
17
|
+
|
|
18
|
+
## 🚀 Commands
|
|
19
|
+
|
|
20
|
+
| Command | Action |
|
|
21
|
+
| ---------------- | ----------------------------- |
|
|
22
|
+
| `npm run dev` | Development server |
|
|
23
|
+
| `npm run expose` | Network-accessible dev server |
|
|
24
|
+
| `npm run build` | Production build with PWA |
|
|
25
|
+
| `npm run lint` | Code formatting |
|
|
26
|
+
|
|
27
|
+
### 🧱 Frontend Stack
|
|
28
|
+
|
|
29
|
+
- Vue 3 + Composition API
|
|
30
|
+
- Pinia state management
|
|
31
|
+
- TailwindCSS + SCSS
|
|
32
|
+
- PWA with offline support
|
|
33
|
+
|
|
34
|
+
### 🛠 Backend Stack
|
|
35
|
+
|
|
36
|
+
- Express.js with WebSockets
|
|
37
|
+
- MessagePack serialization
|
|
38
|
+
- Real-time message batching
|
|
39
|
+
- Platform abstraction layer
|
|
40
|
+
|
|
41
|
+
## 📱 PWA Support
|
|
42
|
+
|
|
43
|
+
- 📲 Install to home screen
|
|
44
|
+
- 🔄 Background sync
|
|
45
|
+
- 📶 Offline functionality
|
|
46
|
+
- 🎨 Native app feel
|
|
47
|
+
|
|
48
|
+
## 🛠️ Development
|
|
49
|
+
|
|
50
|
+
Runs in mock mode by default. Backend simulates bot operations; frontend provides full UI functionality.
|
|
51
|
+
|
|
52
|
+
### 🗂️ File Structure
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
src/
|
|
56
|
+
├─ components/ # Reusable Vue components
|
|
57
|
+
├─ views/ # Page-level components
|
|
58
|
+
├─ stores/ # Pinia state management
|
|
59
|
+
└─ assets/ # Static resources
|
|
60
|
+
|
|
61
|
+
backend/
|
|
62
|
+
├─ api.js # Express server + WebSocket
|
|
63
|
+
├─ mock-data.js # Development data
|
|
64
|
+
└─ endpoints.js # API route definitions
|
|
65
|
+
```
|
|
Binary file
|
package/backend/api.js
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import enableWs from "express-ws";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import cors from "cors";
|
|
4
|
+
import cookieParser from "cookie-parser";
|
|
5
|
+
import { encode } from "@msgpack/msgpack";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
|
|
13
|
+
import { createLogger } from "./mock-src/classes/logger.js";
|
|
14
|
+
import utils from "./mock-src/classes/utils.js";
|
|
15
|
+
|
|
16
|
+
import Batcher from "./batching.js";
|
|
17
|
+
import endpoints from "./endpoints.js";
|
|
18
|
+
import authSystem from "./auth.js";
|
|
19
|
+
import { users } from "./mock-data.js";
|
|
16
20
|
|
|
17
21
|
const logger = createLogger("WEB UI");
|
|
18
22
|
|
|
@@ -362,14 +366,9 @@ app.get("/api/cors", async (req, res) => {
|
|
|
362
366
|
|
|
363
367
|
res.type(contentType).send(data);
|
|
364
368
|
|
|
365
|
-
logger.
|
|
366
|
-
url,
|
|
367
|
-
status: response.status,
|
|
368
|
-
contentType,
|
|
369
|
-
size: data.length
|
|
370
|
-
});
|
|
369
|
+
logger.Info("Proxied", url, response.status);
|
|
371
370
|
} catch (error) {
|
|
372
|
-
logger.
|
|
371
|
+
logger.Error("Proxy error", { url, error: error.message });
|
|
373
372
|
res.status(500).send({ error: error.message });
|
|
374
373
|
}
|
|
375
374
|
});
|
|
@@ -384,7 +383,10 @@ app.get("/api/quickconfig", async (req, res) => {
|
|
|
384
383
|
CapMonster: "example",
|
|
385
384
|
CapSolver: "example",
|
|
386
385
|
Invizible: "example",
|
|
387
|
-
TwoCaptcha: "example"
|
|
386
|
+
TwoCaptcha: "example",
|
|
387
|
+
AntiCaptcha: "example",
|
|
388
|
+
Multibot: "example",
|
|
389
|
+
Test: "Test"
|
|
388
390
|
},
|
|
389
391
|
SMS: {
|
|
390
392
|
Quackr: "example",
|
|
@@ -425,7 +427,7 @@ app.get("/api/userconfig/balances", async (req, res) => {
|
|
|
425
427
|
return res.send({ CapSolver: 100, TwoCaptcha: 40 });
|
|
426
428
|
});
|
|
427
429
|
|
|
428
|
-
|
|
430
|
+
export default {
|
|
429
431
|
start: async () => {
|
|
430
432
|
// onChange = (await import('on-change')).default;
|
|
431
433
|
app.listen(port, "0.0.0.0", () => {
|
package/backend/auth.js
CHANGED
package/backend/batching.js
CHANGED
package/backend/endpoints.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { createLogger } from "./mock-src/classes/logger.js";
|
|
2
|
+
import TicketMaster from "./mock-src/ticketmaster.js";
|
|
3
|
+
import utils from "./mock-src/classes/utils.js";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import validateTaskData from "./validator.js";
|
|
6
6
|
const logger = createLogger("WEB UI");
|
|
7
7
|
|
|
8
8
|
const none = (v) => {
|
|
@@ -170,7 +170,6 @@ const scrapeMap = async (data) => {
|
|
|
170
170
|
taskId: "SCRAPER-" + eventId,
|
|
171
171
|
account: utils.pickAccount(),
|
|
172
172
|
eventId: eventId,
|
|
173
|
-
incapsulaBypass: true,
|
|
174
173
|
hidden: true,
|
|
175
174
|
presaleCode: presaleCode
|
|
176
175
|
});
|
|
@@ -188,7 +187,6 @@ const checkStock = async (data) => {
|
|
|
188
187
|
var taskObj = new TicketMaster({
|
|
189
188
|
taskId: "SCRAPER-" + eventId,
|
|
190
189
|
eventId: eventId,
|
|
191
|
-
incapsulaBypass: true,
|
|
192
190
|
hidden: true
|
|
193
191
|
});
|
|
194
192
|
taskObj.scrapeSeats();
|
|
@@ -197,7 +195,6 @@ const checkStock = async (data) => {
|
|
|
197
195
|
|
|
198
196
|
async function createPresaleModeTasks(eventId, ticketQty) {
|
|
199
197
|
const presaleModeSettings = {
|
|
200
|
-
incapsulaBypass: false,
|
|
201
198
|
agedAccount: false,
|
|
202
199
|
manual: false,
|
|
203
200
|
openCart: false,
|
|
@@ -275,9 +272,9 @@ const saveProfile = async (profile) => {
|
|
|
275
272
|
};
|
|
276
273
|
|
|
277
274
|
const deleteProfile = async (profile) => {
|
|
278
|
-
const {
|
|
279
|
-
Bot.Profiles = Bot.Profiles.filter((p) => p.
|
|
280
|
-
pushWSUpdate({ event: "delete-profile", profile: {
|
|
275
|
+
const { id } = profile;
|
|
276
|
+
Bot.Profiles = Bot.Profiles.filter((p) => p.id !== profile.id);
|
|
277
|
+
pushWSUpdate({ event: "delete-profile", profile: { id } });
|
|
281
278
|
};
|
|
282
279
|
|
|
283
280
|
async function handleWebsocketMessage(msg) {
|
|
@@ -326,7 +323,7 @@ async function handleWebsocketMessage(msg) {
|
|
|
326
323
|
}
|
|
327
324
|
}
|
|
328
325
|
|
|
329
|
-
|
|
326
|
+
export default {
|
|
330
327
|
continueTask,
|
|
331
328
|
tasksOpen,
|
|
332
329
|
deleteTask,
|
package/backend/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { users, profiles, tmAccounts, axsAccounts } from "./mock-data.js";
|
|
2
2
|
|
|
3
3
|
const Bot = {};
|
|
4
4
|
|
|
@@ -20,4 +20,4 @@ Bot.AXS = {
|
|
|
20
20
|
Accounts: axsAccounts
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
export { default } from "./api.js";
|
package/backend/mock-data.js
CHANGED
|
@@ -1,27 +1,19 @@
|
|
|
1
1
|
const users = [
|
|
2
2
|
{
|
|
3
3
|
event: "auth",
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
declines: "1027868055696572508",
|
|
9
|
-
stockChecker: "1099079655962722375",
|
|
10
|
-
venueMaps: "1099125114450214973"
|
|
11
|
-
},
|
|
12
|
-
_id: "641a5292b561088b64fe390b",
|
|
13
|
-
name: "admin",
|
|
14
|
-
password: "p33t",
|
|
15
|
-
profilePicture: "https://cdn.discordapp.com/avatars/843244136945549312/14686df31bfe8889f3c7fb396e8869c9.png",
|
|
4
|
+
id: "641a5292b561088b64fe390b",
|
|
5
|
+
name: "Admin",
|
|
6
|
+
password: "admin",
|
|
7
|
+
profilePicture: "https://cdn.discordapp.com/avatars/435549216304267264/6cfd74ad7c5939a0bcbf218aa08be8cb.png",
|
|
16
8
|
admin: true,
|
|
17
9
|
proxyList: { checkout: "admin-proxies" },
|
|
18
|
-
profileTags: ["
|
|
19
|
-
|
|
10
|
+
profileTags: ["Citi", "Mercury", "Slash"],
|
|
11
|
+
tags: ["admin"]
|
|
20
12
|
}
|
|
21
13
|
];
|
|
22
14
|
|
|
23
15
|
const profile = {
|
|
24
|
-
|
|
16
|
+
id: "645a82606ef8b7201b728805",
|
|
25
17
|
enabled: false,
|
|
26
18
|
profileName: "Master US 43725 [admin]",
|
|
27
19
|
address: "88081 Piper Ways",
|
|
@@ -42,25 +34,24 @@ const profile = {
|
|
|
42
34
|
};
|
|
43
35
|
|
|
44
36
|
const profiles = [];
|
|
45
|
-
for (let i = 0; i < 1000; i++) profiles.push({ ...profile,
|
|
37
|
+
for (let i = 0; i < 1000; i++) profiles.push({ ...profile, id: i });
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
};
|
|
39
|
+
export { users, profiles };
|
|
40
|
+
|
|
41
|
+
export const tmAccounts = [
|
|
42
|
+
{
|
|
43
|
+
tags: ["admin"],
|
|
44
|
+
id: 1,
|
|
45
|
+
password: "123",
|
|
46
|
+
email: "tm@tm.com"
|
|
47
|
+
}
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
export const axsAccounts = [
|
|
51
|
+
{
|
|
52
|
+
tags: ["admin"],
|
|
53
|
+
id: 2,
|
|
54
|
+
password: "123",
|
|
55
|
+
email: "axs@axs.com"
|
|
56
|
+
}
|
|
57
|
+
];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import util from "node:util";
|
|
2
2
|
|
|
3
3
|
const zeroPadding = (num, length) => String(num).padStart(length, "0");
|
|
4
4
|
|
|
@@ -103,10 +103,8 @@ class Logger {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return logger;
|
|
111
|
-
}
|
|
106
|
+
export const createLogger = (args) => {
|
|
107
|
+
const logger = new Logger();
|
|
108
|
+
logger.defaultArgs = typeof args == "string" ? [args] : typeof args == "object" ? args : undefined;
|
|
109
|
+
return logger;
|
|
112
110
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { createLogger } from "./classes/logger.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default class TicketMaster {
|
|
4
4
|
constructor(taskData) {
|
|
5
5
|
this.taskId = taskData.taskId || "T-" + ++Bot.CurrentTaskId;
|
|
6
6
|
this.logger = createLogger(this.taskId);
|
|
@@ -24,7 +24,7 @@ module.exports = class TicketMaster {
|
|
|
24
24
|
this.data.eventDate = Date.now();
|
|
25
25
|
this.data.eventLocalDate = Date.now();
|
|
26
26
|
this.data.eventName = "Test Event";
|
|
27
|
-
this.data.reservedTicketsList = "
|
|
27
|
+
this.data.reservedTicketsList = "• 2x 301/E ($86.47) \n• 2x 306/U ($86.47) \n$345.88";
|
|
28
28
|
|
|
29
29
|
refreshTaskOnFrontEnd(taskData);
|
|
30
30
|
}
|
|
@@ -89,4 +89,4 @@ module.exports = class TicketMaster {
|
|
|
89
89
|
scrapeSeats() {
|
|
90
90
|
this.logger.Info("Scraping seats");
|
|
91
91
|
}
|
|
92
|
-
}
|
|
92
|
+
}
|
package/backend/validator.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import utils from "./mock-src/classes/utils.js";
|
|
2
2
|
|
|
3
3
|
const none = (v) => {
|
|
4
4
|
return v === undefined;
|
|
@@ -59,4 +59,4 @@ const validateTaskData = (task) => {
|
|
|
59
59
|
return task;
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
export default validateTaskData;
|
package/config/configs.json
CHANGED
package/dev-server.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createServer } from "vite";
|
|
4
|
+
import process from "process";
|
|
5
|
+
import { spawn, execFileSync } from "child_process";
|
|
6
|
+
|
|
7
|
+
const killPort = (port) => {
|
|
8
|
+
try {
|
|
9
|
+
const pid = execFileSync("lsof", ["-ti", `:${port}`], { encoding: "utf-8" }).trim();
|
|
10
|
+
if (pid) {
|
|
11
|
+
pid.split("\n").forEach((p) => {
|
|
12
|
+
try {
|
|
13
|
+
process.kill(Number(p), "SIGKILL");
|
|
14
|
+
} catch {}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
} catch {}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const startBackend = () => {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const backend = spawn("node", ["index.js"], {
|
|
23
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
24
|
+
env: { ...process.env, NODE_ENV: "development" }
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
let backendReady = false;
|
|
28
|
+
|
|
29
|
+
backend.stdout.on("data", (data) => {
|
|
30
|
+
const output = data.toString();
|
|
31
|
+
|
|
32
|
+
if (output.includes("Web API started on port") || output.includes("8081")) {
|
|
33
|
+
backendReady = true;
|
|
34
|
+
resolve(backend);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
backend.stderr.on("data", (data) => {
|
|
39
|
+
if (data.toString().includes("Error") || data.toString().includes("EADDRINUSE")) {
|
|
40
|
+
console.error("⚠️ Backend error:", data.toString().trim());
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
backend.on("error", (error) => {
|
|
45
|
+
reject(error);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
backend.on("exit", (code) => {
|
|
49
|
+
if (code !== 0 && !backendReady) {
|
|
50
|
+
reject(new Error(`Backend failed to start`));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
if (!backendReady) {
|
|
56
|
+
resolve(backend);
|
|
57
|
+
}
|
|
58
|
+
}, 5000);
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const startServer = async () => {
|
|
63
|
+
let backend;
|
|
64
|
+
let server;
|
|
65
|
+
let isShuttingDown = false;
|
|
66
|
+
|
|
67
|
+
const cleanup = () => {
|
|
68
|
+
if (isShuttingDown) return;
|
|
69
|
+
isShuttingDown = true;
|
|
70
|
+
|
|
71
|
+
if (backend) {
|
|
72
|
+
backend.kill("SIGTERM");
|
|
73
|
+
setTimeout(() => backend.kill("SIGKILL"), 3000);
|
|
74
|
+
}
|
|
75
|
+
if (server) {
|
|
76
|
+
server.close();
|
|
77
|
+
}
|
|
78
|
+
process.exit(0);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
process.on("SIGINT", cleanup);
|
|
82
|
+
process.on("SIGTERM", cleanup);
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
killPort(5173);
|
|
86
|
+
killPort(8081);
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const fs = await import("node:fs");
|
|
90
|
+
const path = await import("node:path");
|
|
91
|
+
const cacheDir = path.resolve("./node_modules/.vite");
|
|
92
|
+
if (fs.existsSync(cacheDir)) {
|
|
93
|
+
fs.chmodSync(cacheDir, 0o755);
|
|
94
|
+
}
|
|
95
|
+
} catch (e) {}
|
|
96
|
+
|
|
97
|
+
backend = await startBackend();
|
|
98
|
+
|
|
99
|
+
server = await createServer({
|
|
100
|
+
configFile: "./vite.config.js",
|
|
101
|
+
server: {
|
|
102
|
+
port: 5173,
|
|
103
|
+
strictPort: true,
|
|
104
|
+
host: true,
|
|
105
|
+
cors: true,
|
|
106
|
+
hmr: {
|
|
107
|
+
overlay: false
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
process.on("uncaughtException", (error) => {
|
|
113
|
+
if (error.code === "ECONNRESET" || error.errno === -54) return;
|
|
114
|
+
|
|
115
|
+
console.error("❌ Server error:", error.message);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
process.on("unhandledRejection", (reason) => {
|
|
119
|
+
if (reason?.code === "ECONNRESET" || reason?.errno === -54) return;
|
|
120
|
+
|
|
121
|
+
console.error("❌ Unhandled error:", reason?.message || reason);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
await server.listen();
|
|
125
|
+
|
|
126
|
+
console.log("🌐 Dev: http://localhost:5173");
|
|
127
|
+
console.log("🌐 Staging: http://localhost:8081\n");
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error("Failed to start server:", error);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
startServer();
|