Init
This commit is contained in:
commit
d97f211ddc
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
*
|
||||||
|
!/src
|
||||||
|
!/package-lock.json
|
||||||
|
!/package.json
|
||||||
|
!/svelte.config.js
|
||||||
|
!/vite.config.ts
|
||||||
|
!/tsconfig.json
|
||||||
|
!/.npmrc
|
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
node_modules
|
||||||
|
|
||||||
|
# Output
|
||||||
|
.output
|
||||||
|
.vercel
|
||||||
|
.netlify
|
||||||
|
.wrangler
|
||||||
|
/.svelte-kit
|
||||||
|
/build
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Env
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
!.env.test
|
||||||
|
|
||||||
|
# Vite
|
||||||
|
vite.config.js.timestamp-*
|
||||||
|
vite.config.ts.timestamp-*
|
1
.npmrc
Normal file
1
.npmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
engine-strict=true
|
20
.vscode/launch.json
vendored
Normal file
20
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "node-terminal",
|
||||||
|
"name": "Run Script: dev",
|
||||||
|
"request": "launch",
|
||||||
|
"command": "npm run dev",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"env": {
|
||||||
|
"TSHARK_PATH": "C:\\Program Files\\Wireshark\\tshark.exe",
|
||||||
|
"TMP_DIR": "tmp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
25
Dockerfile
Normal file
25
Dockerfile
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
FROM node:22-alpine AS builder
|
||||||
|
|
||||||
|
ENV PUBLIC_BASE_URL=https://dev.mmote.ru/niim-parser/
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm ci && npm run build
|
||||||
|
|
||||||
|
FROM node:22-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apk add tshark && apk cache clean
|
||||||
|
|
||||||
|
COPY --from=builder /app/package.json /app/package-lock.json ./
|
||||||
|
|
||||||
|
COPY --from=builder /app/build ./sv-server
|
||||||
|
|
||||||
|
RUN npm ci --omit dev
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["node", "sv-server"]
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Dump viewer
|
||||||
|
|
||||||
|

|
1694
package-lock.json
generated
Normal file
1694
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "niim-parser",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite dev",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
|
"@sveltejs/adapter-node": "^5.2.12",
|
||||||
|
"@sveltejs/kit": "^2.0.0",
|
||||||
|
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
||||||
|
"svelte": "^5.0.0",
|
||||||
|
"svelte-check": "^4.0.0",
|
||||||
|
"typescript": "^5.0.0",
|
||||||
|
"vite": "^5.4.11"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@mmote/niimbluelib": "0.0.1-alpha.23",
|
||||||
|
"svelte-file-dropzone": "^2.0.9",
|
||||||
|
"uuid": "^11.0.5"
|
||||||
|
}
|
||||||
|
}
|
BIN
preview.png
Normal file
BIN
preview.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 95 KiB |
20
src/app.css
Normal file
20
src/app.css
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
background-color: #303138;
|
||||||
|
color: #d6d6d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropzone {
|
||||||
|
background-color: #262626 !important;
|
||||||
|
}
|
13
src/app.d.ts
vendored
Normal file
13
src/app.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// See https://svelte.dev/docs/kit/types#app.d.ts
|
||||||
|
// for information about these interfaces
|
||||||
|
declare global {
|
||||||
|
namespace App {
|
||||||
|
// interface Error {}
|
||||||
|
// interface Locals {}
|
||||||
|
// interface PageData {}
|
||||||
|
// interface PageState {}
|
||||||
|
// interface Platform {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
13
src/app.html
Normal file
13
src/app.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>NIIMBOT dump parser</title>
|
||||||
|
%sveltekit.head%
|
||||||
|
</head>
|
||||||
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
src/lib/index.ts
Normal file
1
src/lib/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
// place files you want to import through the `$lib` alias in this folder.
|
105
src/lib/utils.ts
Normal file
105
src/lib/utils.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import child_process from "child_process";
|
||||||
|
|
||||||
|
interface TsharkJson {
|
||||||
|
_source: {
|
||||||
|
layers: {
|
||||||
|
"frame.time_relative": string[];
|
||||||
|
"usb.capdata"?: string[];
|
||||||
|
"usb.dst"?: string[];
|
||||||
|
"hci_h4.direction"?: string[];
|
||||||
|
"btspp.data"?: string[];
|
||||||
|
"usbcom.data.in_payload"?: string[];
|
||||||
|
"usbcom.data.out_payload"?: string[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TsharkJsonNormalized {
|
||||||
|
time: number;
|
||||||
|
proto: "usb" | "btspp";
|
||||||
|
direction: ">>" | "<<";
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const runTshark = async (path: string): Promise<TsharkJsonNormalized[]> => {
|
||||||
|
const tshark = process.env.TSHARK_PATH || "tshark";
|
||||||
|
|
||||||
|
return new Promise<TsharkJsonNormalized[]>((resolve, reject) => {
|
||||||
|
const args = [
|
||||||
|
"-2",
|
||||||
|
"-r",
|
||||||
|
path,
|
||||||
|
"-P",
|
||||||
|
"-T",
|
||||||
|
"json",
|
||||||
|
"-e",
|
||||||
|
"frame.time_relative",
|
||||||
|
"-e",
|
||||||
|
"usb.capdata",
|
||||||
|
"-e",
|
||||||
|
"btspp.data",
|
||||||
|
"-e",
|
||||||
|
"usb.dst",
|
||||||
|
"-e",
|
||||||
|
"hci_h4.direction",
|
||||||
|
"-e",
|
||||||
|
"usbcom.data.in_payload",
|
||||||
|
"-e",
|
||||||
|
"usbcom.data.out_payload",
|
||||||
|
"-R",
|
||||||
|
"usb.capdata || btspp.data || usbcom.data.in_payload || usbcom.data.out_payload",
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = child_process.spawnSync(tshark, args);
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
reject(result.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.status !== 0) {
|
||||||
|
reject(new Error(result.stderr?.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = JSON.parse(result.stdout?.toString()) as TsharkJson[];
|
||||||
|
|
||||||
|
const normalized: TsharkJsonNormalized[] = raw.map((e) => {
|
||||||
|
if (e._source.layers["btspp.data"] !== undefined && e._source.layers["hci_h4.direction"] !== undefined) {
|
||||||
|
return {
|
||||||
|
time: parseFloat(e._source.layers["frame.time_relative"][0]),
|
||||||
|
proto: "usb",
|
||||||
|
direction: e._source.layers["hci_h4.direction"][0] === "0x01" ? "<<" : ">>",
|
||||||
|
data: e._source.layers["btspp.data"][0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (e._source.layers["usbcom.data.in_payload"] !== undefined) {
|
||||||
|
return {
|
||||||
|
time: parseFloat(e._source.layers["frame.time_relative"][0]),
|
||||||
|
proto: "usb",
|
||||||
|
direction: "<<",
|
||||||
|
data: e._source.layers["usbcom.data.in_payload"][0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (e._source.layers["usbcom.data.out_payload"] !== undefined) {
|
||||||
|
return {
|
||||||
|
time: parseFloat(e._source.layers["frame.time_relative"][0]),
|
||||||
|
proto: "usb",
|
||||||
|
direction: ">>",
|
||||||
|
data: e._source.layers["usbcom.data.out_payload"][0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (e._source.layers["usb.capdata"] !== undefined && e._source.layers["usb.dst"] !== undefined) {
|
||||||
|
return {
|
||||||
|
time: parseFloat(e._source.layers["frame.time_relative"][0]),
|
||||||
|
proto: "usb",
|
||||||
|
direction: e._source.layers["usb.dst"][0] === "host" ? "<<" : ">>",
|
||||||
|
data: e._source.layers["usb.capdata"][0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
throw new Error("Invalid frame");
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve(normalized);
|
||||||
|
});
|
||||||
|
};
|
5
src/routes/+layout.svelte
Normal file
5
src/routes/+layout.svelte
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
import "../app.css";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<slot />
|
220
src/routes/+page.svelte
Normal file
220
src/routes/+page.svelte
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { PUBLIC_BASE_URL } from "$env/static/public";
|
||||||
|
import type { TsharkJsonNormalized } from "$lib/utils";
|
||||||
|
import { Utils, PacketParser, RequestCommandId, ResponseCommandId } from "@mmote/niimbluelib";
|
||||||
|
import Dropzone from "svelte-file-dropzone";
|
||||||
|
|
||||||
|
let data: TsharkJsonNormalized[] = [];
|
||||||
|
let error: string = "";
|
||||||
|
let uploading: boolean = false;
|
||||||
|
let rx: boolean = true;
|
||||||
|
let tx: boolean = true;
|
||||||
|
let showInfo: boolean = true;
|
||||||
|
let showTime: boolean = true;
|
||||||
|
|
||||||
|
let allPacketTypes: { rx: string[]; tx: string[] } = {
|
||||||
|
tx: Object.values(RequestCommandId)
|
||||||
|
.filter((v) => typeof v === "string")
|
||||||
|
.sort(),
|
||||||
|
rx: Object.values(ResponseCommandId)
|
||||||
|
.filter((v) => typeof v === "string")
|
||||||
|
.sort(),
|
||||||
|
};
|
||||||
|
let disabledPacketTypes: string[] = [];
|
||||||
|
|
||||||
|
const switchPacket = (p: string) => {
|
||||||
|
if (disabledPacketTypes.includes(p)) {
|
||||||
|
disabledPacketTypes = disabledPacketTypes.filter((e) => e !== p);
|
||||||
|
} else {
|
||||||
|
disabledPacketTypes = [...disabledPacketTypes, p];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFilesSelect = async (e: CustomEvent) => {
|
||||||
|
const { acceptedFiles }: { acceptedFiles: File[] } = e.detail;
|
||||||
|
error = "";
|
||||||
|
uploading = true;
|
||||||
|
|
||||||
|
if (acceptedFiles.length === 1) {
|
||||||
|
const form = new FormData();
|
||||||
|
form.append("file", acceptedFiles[0]);
|
||||||
|
|
||||||
|
const resp = await fetch(PUBLIC_BASE_URL + "api/upload", {
|
||||||
|
method: "POST",
|
||||||
|
body: form,
|
||||||
|
});
|
||||||
|
|
||||||
|
const json = await resp.json();
|
||||||
|
|
||||||
|
if (resp.ok) {
|
||||||
|
data = json as TsharkJsonNormalized[];
|
||||||
|
} else if ("error" in json) {
|
||||||
|
error = json.error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uploading = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatHex = (hex: string) => {
|
||||||
|
return hex
|
||||||
|
.toUpperCase()
|
||||||
|
.replace(/^(03)?(5555)([A-F0-9]{2})([A-F0-9]{2})(.*?)([A-F0-9]{2})(AAAA)$/, "$1 $2 $3 $4 $5 $6 $7");
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatInfo = (direction: string, hex: string): { typeStr: string; msg: string } => {
|
||||||
|
try {
|
||||||
|
const infos = [];
|
||||||
|
|
||||||
|
if (hex.startsWith("035555")) hex = hex.slice(2);
|
||||||
|
|
||||||
|
const buf = Utils.hexToBuf(hex);
|
||||||
|
const packets = PacketParser.parsePacketBundle(buf);
|
||||||
|
// if(comment += ResponseCommandId[packet.command])
|
||||||
|
infos.push(
|
||||||
|
...packets.map((p) => {
|
||||||
|
let msg = "";
|
||||||
|
if (direction === ">>") {
|
||||||
|
msg = RequestCommandId[p.command];
|
||||||
|
if (p.command === RequestCommandId.SetPageSize && p.dataLength >= 4) {
|
||||||
|
const cols = Utils.bytesToI16(p.data.slice(0, 2));
|
||||||
|
const rows = Utils.bytesToI16(p.data.slice(2, 4));
|
||||||
|
msg += ` (${rows}x${cols}px, ${rows / 8}x${cols / 8}mm 203dpi)`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg = ResponseCommandId[p.command];
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return { typeStr: infos.join(", "), msg: infos.join(", ") || "???" };
|
||||||
|
} catch (e) {
|
||||||
|
return { typeStr: "Invalid", msg: "❌" };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<Dropzone disabled={uploading} multiple={false} on:drop={handleFilesSelect}>
|
||||||
|
<p>Drag USB/BLE capture file here (.pcap/.log/etc.)</p>
|
||||||
|
</Dropzone>
|
||||||
|
{#if uploading}Uploading...{/if}
|
||||||
|
|
||||||
|
{#if error}
|
||||||
|
<div class="error">{error}</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="filters">
|
||||||
|
<input type="checkbox" bind:checked={rx} id="rx" />
|
||||||
|
<label for="rx">rx</label>
|
||||||
|
|
||||||
|
<input type="checkbox" bind:checked={tx} id="tx" />
|
||||||
|
<label for="tx">tx</label>
|
||||||
|
|
||||||
|
<input type="checkbox" bind:checked={showTime} id="time" />
|
||||||
|
<label for="time">show time</label>
|
||||||
|
|
||||||
|
<input type="checkbox" bind:checked={showInfo} id="info" />
|
||||||
|
<label for="info">show info</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filters">
|
||||||
|
{#each allPacketTypes.tx as t}
|
||||||
|
<button class="parsed tx pill {disabledPacketTypes.includes(t) && 'disabled'}" on:click={() => switchPacket(t)}
|
||||||
|
>{t}</button
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filters">
|
||||||
|
{#each allPacketTypes.rx as t}
|
||||||
|
<button class="parsed rx pill {disabledPacketTypes.includes(t) && 'disabled'}" on:click={() => switchPacket(t)}
|
||||||
|
>{t}</button
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="data">
|
||||||
|
{#each data as d}
|
||||||
|
{@const info = formatInfo(d.direction, d.data)}
|
||||||
|
{#if ((d.direction === "<<" && rx) || (d.direction === ">>" && tx)) && !disabledPacketTypes.includes(info.typeStr)}
|
||||||
|
<div class="row">
|
||||||
|
{#if showTime}
|
||||||
|
<span class="time pill">{d.time.toFixed(3)}</span>
|
||||||
|
{/if}
|
||||||
|
<span class="{d.direction == '<<' ? 'rx' : 'tx'} pill">{d.direction}</span>
|
||||||
|
<span class="hex pill">{formatHex(d.data)}</span>
|
||||||
|
{#if showInfo}
|
||||||
|
<span class="parsed pill {d.direction == '<<' ? 'rx' : 'tx'}">{info.msg}</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
margin: 16px 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filters {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pill {
|
||||||
|
padding: 0 0.3em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid gray;
|
||||||
|
margin: 0 0.1em;
|
||||||
|
color: #d6d6d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data {
|
||||||
|
margin-top: 32px;
|
||||||
|
font-family: monospace;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data .row {
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pill.rx {
|
||||||
|
background-color: #0b9c0b;
|
||||||
|
border-color: #064d06;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pill.tx {
|
||||||
|
background-color: #bd440d;
|
||||||
|
border-color: #863109;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pill.parsed.tx {
|
||||||
|
background-color: rgba(189, 69, 13, 0.22);
|
||||||
|
}
|
||||||
|
.pill.parsed.rx {
|
||||||
|
background-color: rgba(11, 156, 11, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pill.parsed.tx.disabled {
|
||||||
|
color: #757575;
|
||||||
|
border-color: #491b05;
|
||||||
|
background-color: rgba(189, 69, 13, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pill.parsed.rx.disabled {
|
||||||
|
color: #747474;
|
||||||
|
border-color: #042e04;
|
||||||
|
background-color: rgba(11, 156, 11, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hex {
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
</style>
|
7
src/routes/api/+server.ts
Normal file
7
src/routes/api/+server.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { json, type RequestHandler } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const GET: RequestHandler = async ({ url }) => {
|
||||||
|
return json({ });
|
||||||
|
};
|
26
src/routes/api/upload/+server.ts
Normal file
26
src/routes/api/upload/+server.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { json, type RequestHandler } from "@sveltejs/kit";
|
||||||
|
import { writeFile, unlink } from "node:fs/promises";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import { runTshark } from "$lib/utils";
|
||||||
|
|
||||||
|
export const POST: RequestHandler = async ({ request }) => {
|
||||||
|
const formData = await request.formData();
|
||||||
|
const file = formData.get("file");
|
||||||
|
|
||||||
|
const tmp = process.env.TMP_DIR || "/tmp";
|
||||||
|
const path = `${tmp}/${uuidv4()}.bin`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (file === null || !(file instanceof File)) {
|
||||||
|
return json({ error: "No file" }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeFile(path, Buffer.from(await file.arrayBuffer()));
|
||||||
|
const out = await runTshark(path);
|
||||||
|
return json(out);
|
||||||
|
} catch (e) {
|
||||||
|
return json({ error: `${e}` }, { status: 400 });
|
||||||
|
} finally {
|
||||||
|
await unlink(path);
|
||||||
|
}
|
||||||
|
};
|
BIN
static/favicon.png
Normal file
BIN
static/favicon.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 1.5 KiB |
26
svelte.config.js
Normal file
26
svelte.config.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import adapter from "@sveltejs/adapter-node";
|
||||||
|
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
||||||
|
|
||||||
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
|
const config = {
|
||||||
|
// Consult https://svelte.dev/docs/kit/integrations
|
||||||
|
// for more information about preprocessors
|
||||||
|
preprocess: vitePreprocess(),
|
||||||
|
compilerOptions: {
|
||||||
|
// runes: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
kit: {
|
||||||
|
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
|
||||||
|
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||||
|
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
||||||
|
adapter: adapter(),
|
||||||
|
},
|
||||||
|
csrf: {
|
||||||
|
checkOrigin: false,
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"extends": "./.svelte-kit/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"types": ["node"]
|
||||||
|
}
|
||||||
|
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
||||||
|
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
||||||
|
//
|
||||||
|
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||||
|
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||||
|
}
|
6
vite.config.ts
Normal file
6
vite.config.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [sveltekit()]
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user