beanstalkd-dashboard 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/bin/cli.js +3 -0
- package/dist/assets/archivo-black-latin-400-normal-BTVu2TQR.woff2 +0 -0
- package/dist/assets/archivo-black-latin-400-normal-HW9MwEcM.woff +0 -0
- package/dist/assets/archivo-black-latin-ext-400-normal--j5WRK12.woff +0 -0
- package/dist/assets/archivo-black-latin-ext-400-normal-DQAASfvW.woff2 +0 -0
- package/dist/assets/index-BDcT3jO0.css +1 -0
- package/dist/assets/index-N_ss1O2V.js +173 -0
- package/dist/assets/space-grotesk-latin-ext-wght-normal-D9tNdqV9.woff2 +0 -0
- package/dist/assets/space-grotesk-latin-wght-normal-BmihWDuX.woff2 +0 -0
- package/dist/assets/space-grotesk-vietnamese-wght-normal-D0rl6rjA.woff2 +0 -0
- package/dist/index.html +13 -0
- package/dist-server/beanstalkd.d.ts +7 -0
- package/dist-server/beanstalkd.js +9 -0
- package/dist-server/dummy-bs-client.d.ts +1 -0
- package/dist-server/dummy-bs-client.js +63 -0
- package/dist-server/index.d.ts +1 -0
- package/dist-server/index.js +58 -0
- package/dist-server/injection-tokens.d.ts +6 -0
- package/dist-server/injection-tokens.js +2 -0
- package/dist-server/router.d.ts +91 -0
- package/dist-server/router.js +118 -0
- package/dist-server/trpc.d.ts +11 -0
- package/dist-server/trpc.js +12 -0
- package/package.json +65 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.html
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>beanstalkd dashboard</title>
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-N_ss1O2V.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BDcT3jO0.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="app"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BeanstalkdClient } from 'beanstalkd-ts';
|
|
2
|
+
export class BeanstalkdServer {
|
|
3
|
+
constructor(id, address) {
|
|
4
|
+
this.id = id;
|
|
5
|
+
this.address = address;
|
|
6
|
+
const [host, port] = address.split(':');
|
|
7
|
+
this.bsClient = new BeanstalkdClient({ host, port: Number(port) });
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { BeanstalkdClient } from 'beanstalkd-ts';
|
|
11
|
+
const tube = 'console-demo';
|
|
12
|
+
function producer() {
|
|
13
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
14
|
+
const bsClient = new BeanstalkdClient();
|
|
15
|
+
bsClient.defaultTtr = 300;
|
|
16
|
+
yield bsClient.connect();
|
|
17
|
+
yield bsClient.use(tube);
|
|
18
|
+
for (;;) {
|
|
19
|
+
yield Promise.all([
|
|
20
|
+
bsClient.put('demo content', { ttr: 1000 }),
|
|
21
|
+
bsClient.put('demo content', { ttr: 1000 }),
|
|
22
|
+
bsClient.put('demo content', { ttr: 1000 }),
|
|
23
|
+
bsClient.put('demo content', { ttr: 1000 }),
|
|
24
|
+
bsClient.put('demo content', { ttr: 1000 }),
|
|
25
|
+
bsClient.put('demo content', { delay: 10, ttr: 1000 }),
|
|
26
|
+
]);
|
|
27
|
+
yield new Promise((r) => setTimeout(r, Math.round(Math.random() * 400)));
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function worker() {
|
|
32
|
+
return __awaiter(this, arguments, void 0, function* (limit = Infinity) {
|
|
33
|
+
const bsClient = new BeanstalkdClient();
|
|
34
|
+
yield bsClient.connect();
|
|
35
|
+
yield bsClient.watch(tube);
|
|
36
|
+
yield bsClient.ignore('default');
|
|
37
|
+
for (let jobs = 0; jobs < limit; jobs++) {
|
|
38
|
+
const job = yield bsClient.reserve();
|
|
39
|
+
yield new Promise((r) => setTimeout(r, Math.round(Math.random() * 100)));
|
|
40
|
+
yield bsClient.deleteJob(job.id);
|
|
41
|
+
}
|
|
42
|
+
yield bsClient.close();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function main() {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
setInterval(() => {
|
|
48
|
+
worker(Math.round(Math.random() * 10));
|
|
49
|
+
worker(Math.round(Math.random() * 20));
|
|
50
|
+
}, 100);
|
|
51
|
+
yield Promise.all([
|
|
52
|
+
producer(),
|
|
53
|
+
producer(),
|
|
54
|
+
producer(),
|
|
55
|
+
producer(),
|
|
56
|
+
worker(),
|
|
57
|
+
worker(),
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
main().catch((err) => {
|
|
62
|
+
console.log('main error:', err);
|
|
63
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var _a, _b;
|
|
11
|
+
import 'reflect-metadata';
|
|
12
|
+
import { createServer } from 'node:http';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import * as trpcExpress from '@trpc/server/adapters/express';
|
|
15
|
+
import { program } from 'commander';
|
|
16
|
+
import cors from 'cors';
|
|
17
|
+
import express from 'express';
|
|
18
|
+
import { container } from 'tsyringe';
|
|
19
|
+
import ViteExpress from 'vite-express';
|
|
20
|
+
import z from 'zod';
|
|
21
|
+
import { BeanstalkdServer } from './beanstalkd.js';
|
|
22
|
+
import injectionTokens from './injection-tokens.js';
|
|
23
|
+
import { appRouter } from './router.js';
|
|
24
|
+
const host = (_a = process.env.HOST) !== null && _a !== void 0 ? _a : '127.0.0.1';
|
|
25
|
+
const port = Number((_b = process.env.PORT) !== null && _b !== void 0 ? _b : '3000');
|
|
26
|
+
const optionsSchema = z.object({
|
|
27
|
+
servers: z.string().default('localhost:11300'),
|
|
28
|
+
});
|
|
29
|
+
const prog = program
|
|
30
|
+
.option('--servers <addresses>', 'Beanstalkd server addresses in format [host:port,...] (comma separated). Example: localhost:11300', 'localhost:11300')
|
|
31
|
+
.parse(process.argv);
|
|
32
|
+
function main() {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
const { servers } = optionsSchema.parse(prog.opts());
|
|
35
|
+
const app = express();
|
|
36
|
+
const server = createServer(app);
|
|
37
|
+
const bsServers = servers
|
|
38
|
+
.split(',')
|
|
39
|
+
.map((address, i) => new BeanstalkdServer(i + 1, address));
|
|
40
|
+
yield Promise.all(bsServers.map((server) => server.bsClient.connect()));
|
|
41
|
+
container.registerInstance(injectionTokens.beanstalkdServers, bsServers);
|
|
42
|
+
app.use(cors({}));
|
|
43
|
+
app.use('/trpc', trpcExpress.createExpressMiddleware({ router: appRouter }));
|
|
44
|
+
ViteExpress.config({
|
|
45
|
+
mode: 'production',
|
|
46
|
+
inlineViteConfig: {
|
|
47
|
+
build: {
|
|
48
|
+
outDir: path.join(import.meta.dirname, '..', 'dist'),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
ViteExpress.bind(app, server);
|
|
53
|
+
server.listen(port, host, () => {
|
|
54
|
+
console.log(`Server started listening on http://${host}:${port}`);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
main().catch((err) => console.log('Main error:', err));
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { type JobStats, type TubeStats } from 'beanstalkd-ts';
|
|
2
|
+
import type { BeanstalkdServer } from './beanstalkd.js';
|
|
3
|
+
export interface TubeWithStats {
|
|
4
|
+
name: string;
|
|
5
|
+
stats: TubeStats;
|
|
6
|
+
}
|
|
7
|
+
export interface JobWitStats {
|
|
8
|
+
job: {
|
|
9
|
+
id: number;
|
|
10
|
+
payload: string;
|
|
11
|
+
};
|
|
12
|
+
stats: JobStats;
|
|
13
|
+
}
|
|
14
|
+
export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
15
|
+
ctx: object;
|
|
16
|
+
meta: object;
|
|
17
|
+
errorShape: import("@trpc/server").TRPCDefaultErrorShape;
|
|
18
|
+
transformer: false;
|
|
19
|
+
}, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
|
|
20
|
+
servers: {
|
|
21
|
+
list: import("@trpc/server").TRPCQueryProcedure<{
|
|
22
|
+
input: void;
|
|
23
|
+
output: BeanstalkdServer[];
|
|
24
|
+
meta: object;
|
|
25
|
+
}>;
|
|
26
|
+
};
|
|
27
|
+
jobs: {
|
|
28
|
+
peekBuried: import("@trpc/server").TRPCQueryProcedure<{
|
|
29
|
+
input: {
|
|
30
|
+
serverId: number;
|
|
31
|
+
tube: string;
|
|
32
|
+
};
|
|
33
|
+
output: JobWitStats | null;
|
|
34
|
+
meta: object;
|
|
35
|
+
}>;
|
|
36
|
+
peekDelayed: import("@trpc/server").TRPCQueryProcedure<{
|
|
37
|
+
input: {
|
|
38
|
+
serverId: number;
|
|
39
|
+
tube: string;
|
|
40
|
+
};
|
|
41
|
+
output: JobWitStats | null;
|
|
42
|
+
meta: object;
|
|
43
|
+
}>;
|
|
44
|
+
peekReady: import("@trpc/server").TRPCQueryProcedure<{
|
|
45
|
+
input: {
|
|
46
|
+
serverId: number;
|
|
47
|
+
tube: string;
|
|
48
|
+
};
|
|
49
|
+
output: JobWitStats | null;
|
|
50
|
+
meta: object;
|
|
51
|
+
}>;
|
|
52
|
+
};
|
|
53
|
+
tubes: {
|
|
54
|
+
clear: import("@trpc/server").TRPCMutationProcedure<{
|
|
55
|
+
input: {
|
|
56
|
+
serverId: number;
|
|
57
|
+
tube: string;
|
|
58
|
+
};
|
|
59
|
+
output: string;
|
|
60
|
+
meta: object;
|
|
61
|
+
}>;
|
|
62
|
+
pause: import("@trpc/server").TRPCMutationProcedure<{
|
|
63
|
+
input: {
|
|
64
|
+
serverId: number;
|
|
65
|
+
tube: string;
|
|
66
|
+
seconds: number;
|
|
67
|
+
};
|
|
68
|
+
output: string;
|
|
69
|
+
meta: object;
|
|
70
|
+
}>;
|
|
71
|
+
list: import("@trpc/server").TRPCQueryProcedure<{
|
|
72
|
+
input: {
|
|
73
|
+
serverId: number;
|
|
74
|
+
};
|
|
75
|
+
output: {
|
|
76
|
+
name: string;
|
|
77
|
+
stats: TubeStats;
|
|
78
|
+
}[];
|
|
79
|
+
meta: object;
|
|
80
|
+
}>;
|
|
81
|
+
tubeStats: import("@trpc/server").TRPCQueryProcedure<{
|
|
82
|
+
input: {
|
|
83
|
+
serverId: number;
|
|
84
|
+
tube: string;
|
|
85
|
+
};
|
|
86
|
+
output: TubeStats;
|
|
87
|
+
meta: object;
|
|
88
|
+
}>;
|
|
89
|
+
};
|
|
90
|
+
}>>;
|
|
91
|
+
export type AppRouter = typeof appRouter;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { NotFoundError } from 'beanstalkd-ts';
|
|
11
|
+
import { container } from 'tsyringe';
|
|
12
|
+
import z from 'zod';
|
|
13
|
+
import injectionTokens from './injection-tokens.js';
|
|
14
|
+
import { publicProcedure, router } from './trpc.js';
|
|
15
|
+
function servers() {
|
|
16
|
+
return container.resolve(injectionTokens.beanstalkdServers);
|
|
17
|
+
}
|
|
18
|
+
function getServer(id) {
|
|
19
|
+
const server = servers().find((s) => s.id === id);
|
|
20
|
+
if (!server)
|
|
21
|
+
throw new Error(`Server${id} not found.`);
|
|
22
|
+
return server;
|
|
23
|
+
}
|
|
24
|
+
export const appRouter = router({
|
|
25
|
+
servers: {
|
|
26
|
+
list: publicProcedure.query(() => __awaiter(void 0, void 0, void 0, function* () { return servers(); })),
|
|
27
|
+
},
|
|
28
|
+
jobs: {
|
|
29
|
+
peekBuried: jobStatsProcedure('buried'),
|
|
30
|
+
peekDelayed: jobStatsProcedure('delayed'),
|
|
31
|
+
peekReady: jobStatsProcedure('ready'),
|
|
32
|
+
},
|
|
33
|
+
tubes: {
|
|
34
|
+
clear: publicProcedure
|
|
35
|
+
.input(z.object({ serverId: z.int(), tube: z.string() }))
|
|
36
|
+
.mutation((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
37
|
+
const server = getServer(opts.input.serverId);
|
|
38
|
+
const states = ['buried', 'delayed', 'ready'];
|
|
39
|
+
yield server.bsClient.use(opts.input.tube);
|
|
40
|
+
for (const state of states) {
|
|
41
|
+
for (;;) {
|
|
42
|
+
const job = yield peekJob(server, state);
|
|
43
|
+
if (!job)
|
|
44
|
+
break;
|
|
45
|
+
yield server.bsClient.deleteJob(job.jobId);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
yield server.bsClient.use('default');
|
|
49
|
+
return 'ok';
|
|
50
|
+
})),
|
|
51
|
+
pause: publicProcedure
|
|
52
|
+
.input(z.object({ serverId: z.int(), tube: z.string(), seconds: z.int() }))
|
|
53
|
+
.mutation((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
|
+
const server = getServer(opts.input.serverId);
|
|
55
|
+
yield server.bsClient.pauseTube(opts.input.tube, opts.input.seconds);
|
|
56
|
+
return 'ok';
|
|
57
|
+
})),
|
|
58
|
+
list: publicProcedure
|
|
59
|
+
.input(z.object({ serverId: z.int() }))
|
|
60
|
+
.query((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
|
+
const server = getServer(opts.input.serverId);
|
|
62
|
+
const tubes = yield server.bsClient.listTubes();
|
|
63
|
+
const tubeStats = yield Promise.all(tubes.map((tube) => server.bsClient.statsTube(tube)));
|
|
64
|
+
return tubes.map((tube, i) =>
|
|
65
|
+
// biome-ignore lint/style/noNonNullAssertion: we fetch stats for each tube above
|
|
66
|
+
({ name: tube, stats: tubeStats[i] }));
|
|
67
|
+
})),
|
|
68
|
+
tubeStats: publicProcedure
|
|
69
|
+
.input(z.object({ serverId: z.int(), tube: z.string() }))
|
|
70
|
+
.query((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
+
const server = getServer(opts.input.serverId);
|
|
72
|
+
return yield server.bsClient.statsTube(opts.input.tube);
|
|
73
|
+
})),
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
function jobStatsProcedure(state) {
|
|
77
|
+
return publicProcedure
|
|
78
|
+
.input(z.object({ serverId: z.int(), tube: z.string() }))
|
|
79
|
+
.query((opts) => __awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
const server = getServer(opts.input.serverId);
|
|
81
|
+
const { tube } = opts.input;
|
|
82
|
+
yield server.bsClient.use(tube);
|
|
83
|
+
const job = yield peekJob(server, state);
|
|
84
|
+
if (!job)
|
|
85
|
+
return null;
|
|
86
|
+
try {
|
|
87
|
+
const jobStats = yield server.bsClient.statsJob(job.jobId);
|
|
88
|
+
return {
|
|
89
|
+
job: { id: job.jobId, payload: job.payload.toString() },
|
|
90
|
+
stats: jobStats,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
if (err instanceof NotFoundError) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
throw err; // rethrow
|
|
98
|
+
}
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
function peekJob(server, state) {
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
try {
|
|
104
|
+
const job = yield server.bsClient[state === 'buried'
|
|
105
|
+
? 'peekBuried'
|
|
106
|
+
: state === 'delayed'
|
|
107
|
+
? 'peekDelayed'
|
|
108
|
+
: 'peekReady']();
|
|
109
|
+
return job;
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
if (err instanceof NotFoundError) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
throw err; // rethrow
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export reusable router and procedure helpers
|
|
3
|
+
* that can be used throughout the router
|
|
4
|
+
*/
|
|
5
|
+
export declare const router: import("@trpc/server").TRPCRouterBuilder<{
|
|
6
|
+
ctx: object;
|
|
7
|
+
meta: object;
|
|
8
|
+
errorShape: import("@trpc/server").TRPCDefaultErrorShape;
|
|
9
|
+
transformer: false;
|
|
10
|
+
}>;
|
|
11
|
+
export declare const publicProcedure: import("@trpc/server").TRPCProcedureBuilder<object, object, object, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, false>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { initTRPC } from '@trpc/server';
|
|
2
|
+
/**
|
|
3
|
+
* Initialization of tRPC backend
|
|
4
|
+
* Should be done only once per backend!
|
|
5
|
+
*/
|
|
6
|
+
const t = initTRPC.create();
|
|
7
|
+
/**
|
|
8
|
+
* Export reusable router and procedure helpers
|
|
9
|
+
* that can be used throughout the router
|
|
10
|
+
*/
|
|
11
|
+
export const router = t.router;
|
|
12
|
+
export const publicProcedure = t.procedure;
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "beanstalkd-dashboard",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": "./bin/cli.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"./bin/cli.js",
|
|
9
|
+
"./dist",
|
|
10
|
+
"./dist-server"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"start": "node dist-server/index.js",
|
|
14
|
+
"dev": "vite",
|
|
15
|
+
"dev:trpc": "bun --watch --no-clear-console server/index.ts",
|
|
16
|
+
"build": "npm run build:server && npm run build:ui",
|
|
17
|
+
"build:server": "tsc -p tsconfig.server.json",
|
|
18
|
+
"build:ui": "tsc -b && vite build",
|
|
19
|
+
"preview": "vite preview",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@fontsource-variable/space-grotesk": "^5.2.8",
|
|
24
|
+
"@fontsource/archivo-black": "^5.2.6",
|
|
25
|
+
"@radix-ui/react-accordion": "^1.2.12",
|
|
26
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
27
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
28
|
+
"@radix-ui/react-label": "^2.1.7",
|
|
29
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
30
|
+
"@radix-ui/react-visually-hidden": "^1.2.3",
|
|
31
|
+
"@tailwindcss/vite": "^4.1.12",
|
|
32
|
+
"@tanstack/react-query": "^5.85.3",
|
|
33
|
+
"@tanstack/react-table": "^8.21.3",
|
|
34
|
+
"@trpc/client": "^11.4.4",
|
|
35
|
+
"@trpc/server": "^11.4.4",
|
|
36
|
+
"@trpc/tanstack-react-query": "^11.4.4",
|
|
37
|
+
"beanstalkd-ts": "^0.1.6",
|
|
38
|
+
"class-variance-authority": "^0.7.1",
|
|
39
|
+
"clsx": "^2.1.1",
|
|
40
|
+
"commander": "^14.0.0",
|
|
41
|
+
"cors": "^2.8.5",
|
|
42
|
+
"express": "^5.1.0",
|
|
43
|
+
"lucide-react": "^0.539.0",
|
|
44
|
+
"preact": "^10.27.0",
|
|
45
|
+
"preact-iso": "^2.9.2",
|
|
46
|
+
"react": "^19.1.1",
|
|
47
|
+
"reflect-metadata": "^0.2.2",
|
|
48
|
+
"tailwind-merge": "^3.3.1",
|
|
49
|
+
"tailwindcss": "^4.1.12",
|
|
50
|
+
"tsyringe": "^4.10.0",
|
|
51
|
+
"vite-express": "^0.21.1",
|
|
52
|
+
"zod": "^4.0.17",
|
|
53
|
+
"zustand": "^5.0.7"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@biomejs/biome": "^2.2.0",
|
|
57
|
+
"@preact/preset-vite": "^2.10.2",
|
|
58
|
+
"@types/cors": "^2.8.19",
|
|
59
|
+
"@types/express": "^5.0.3",
|
|
60
|
+
"ts-node": "^10.9.2",
|
|
61
|
+
"tw-animate-css": "^1.3.6",
|
|
62
|
+
"typescript": "~5.9.2",
|
|
63
|
+
"vite": "^7.1.2"
|
|
64
|
+
}
|
|
65
|
+
}
|