initial
This commit is contained in:
5
.dockerignore
Normal file
5
.dockerignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
*.log
|
||||||
|
tmp
|
||||||
|
.env
|
||||||
26
Dockerfile
Normal file
26
Dockerfile
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apk add --no-cache python3 make g++ su-exec \
|
||||||
|
&& npm install --global npm@latest
|
||||||
|
|
||||||
|
COPY package*.json tsconfig.json ./
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
RUN addgroup -S appuser && adduser -S -G appuser appuser \
|
||||||
|
&& mkdir -p /app/data \
|
||||||
|
&& chown -R appuser:appuser /app
|
||||||
|
|
||||||
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
139
README.md
Normal file
139
README.md
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# Paperless Contract Companion (TypeScript + React)
|
||||||
|
|
||||||
|
Begleitservice zur Verwaltung von Vertragsmetadaten (Laufzeiten, Kündigungsfristen, Preise) als Ergänzung zu einer bestehenden [paperless-ngx](https://github.com/paperless-ngx/paperless-ngx) Instanz. Dokumente verbleiben in paperless, der Service liefert zusätzliche Struktur, Fristüberwachung, Web-GUI und optionale Mail-Benachrichtigungen.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- REST-API (Express) zum Anlegen, Aktualisieren und Löschen von Verträgen.
|
||||||
|
- Speicherung der Metadaten in SQLite (via `better-sqlite3`).
|
||||||
|
- Periodischer Scheduler prüft anstehende Kündigungsfristen und schreibt diese ins Log bzw. versendet auf Wunsch E-Mails.
|
||||||
|
- Paperless-Integration ruft zugehörige Dokument-Metadaten über API-Token ab.
|
||||||
|
- JWT-basierte Authentifizierung mit Login-Endpunkt (optional aktivierbar).
|
||||||
|
- Moderne React-UI (Vite + MUI) mit Dashboard, Tabellen, Kalender und Settings.
|
||||||
|
- Einstellbare Integrationen direkt im Browser (Paperless, Mail, ntfy, Scheduler).
|
||||||
|
- Komfortable Paperless-Suche beim Verknüpfen von Dokumenten.
|
||||||
|
- Optionaler ntfy-Push für Fristenmeldungen.
|
||||||
|
- iCal-Feed zum Abonnieren der Kündigungsfristen.
|
||||||
|
- Test-Buttons für Mail- und ntfy-Konfiguration direkt in der Oberfläche.
|
||||||
|
- Läuft als Docker-Container, konfigurierbar über Umgebungsvariablen oder `.env` (beim Kopieren auf den Zielhost).
|
||||||
|
|
||||||
|
## Projektstruktur
|
||||||
|
```
|
||||||
|
backend/
|
||||||
|
src/
|
||||||
|
index.ts # Express-Server und Routing
|
||||||
|
config.ts # Umgebungsvariablen & Defaults
|
||||||
|
db.ts # SQLite-Initialisierung
|
||||||
|
contractsStore.ts # CRUD-Logik auf DB-Ebene
|
||||||
|
scheduler.ts # Fristenmonitor
|
||||||
|
paperlessClient.ts # HTTP-Client für paperless-ngx
|
||||||
|
notifications.ts # SMTP-Integration (optional)
|
||||||
|
validators.ts # Zod-Schemas für Payloads
|
||||||
|
frontend/
|
||||||
|
src/ # React App (Dashboard, Login, Verträge, Kalender, Settings)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Frontend (Vite + React)
|
||||||
|
|
||||||
|
Die Web-Oberfläche liegt im Ordner `frontend/` und kommuniziert ausschließlich über die gesicherte REST-API.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm install
|
||||||
|
npm run dev # Lokale Entwicklung (http://localhost:5173)
|
||||||
|
npm run build # Produktionsbuild in frontend/dist
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build & Run (Docker)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Die API lauscht per Default auf Port `8000`, extern über Compose auf `8080`. Die SQLite-Datenbank wird im Volume `contracts-data` unter `/app/data/contracts.db` persistiert. Das Frontend ist über `http://localhost:8081` (laut Compose) erreichbar.
|
||||||
|
|
||||||
|
### Wichtige Umgebungsvariablen
|
||||||
|
|
||||||
|
| Variable | Standard | Beschreibung |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `PORT` | `8000` | HTTP-Port des Dienstes. |
|
||||||
|
| `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, `error`. |
|
||||||
|
| `DATABASE_PATH` | `/app/data/contracts.db` | Pfad zur SQLite-Datei (Volume nicht vergessen). |
|
||||||
|
| `PAPERLESS_BASE_URL` | *(leer)* | Basis-URL der paperless-ngx API (z.B. `http://paperless:8000`). |
|
||||||
|
| `PAPERLESS_EXTERNAL_URL` | *(leer)* | Optionale externe URL für Direkt-Link aus der Web-Oberfläche (z.B. `https://paperless.example.com`). |
|
||||||
|
| `PAPERLESS_TOKEN` | *(leer)* | Personal Token aus paperless-ngx (read-only genügt). |
|
||||||
|
| `SCHEDULER_INTERVAL_MINUTES` | `60` | Prüffrequenz für Fristen (mind. 5). |
|
||||||
|
| `ALERT_DAYS_BEFORE` | `30` | Wie viele Tage vor Deadline gewarnt wird. |
|
||||||
|
| `AUTH_USERNAME` / `AUTH_PASSWORD` | *(leer)* | Aktiviert das Login (JWT) – beide Werte müssen gesetzt werden. |
|
||||||
|
| `AUTH_JWT_SECRET` | *(leer)* | Geheimnis zum Signieren der Tokens (Pflicht, wenn Auth aktiv). |
|
||||||
|
| `AUTH_TOKEN_EXPIRES_IN_HOURS` | `12` | Lebensdauer der JWTs. |
|
||||||
|
| `NTFY_SERVER_URL` / `NTFY_TOPIC` | *(leer)* | ntfy-Server & Topic für Push-Benachrichtigungen. |
|
||||||
|
| `NTFY_TOKEN` / `NTFY_PRIORITY` | *(leer)* | Optionaler Bearer-Token & Priorität für ntfy. |
|
||||||
|
| `MAIL_*` | *(leer)* | Optional: SMTP-Einstellungen für Benachrichtigungs-E-Mails. |
|
||||||
|
| `ICAL_SECRET` | *(leer)* | Optional vordefiniertes Token für den iCal-Feed (ansonsten automatisch). |
|
||||||
|
|
||||||
|
Mail-Setup (optional): `MAIL_SERVER`, `MAIL_PORT`, `MAIL_USERNAME`, `MAIL_PASSWORD`, `MAIL_USE_TLS`, `MAIL_FROM`, `MAIL_TO`.
|
||||||
|
|
||||||
|
> Tipp: Bei gesetzter Authentifizierung muss sich die Web-UI einmalig per Login anmelden; Tokens werden im LocalStorage gespeichert.
|
||||||
|
|
||||||
|
## API Übersicht
|
||||||
|
|
||||||
|
- `GET /healthz` – einfacher Gesundheitscheck.
|
||||||
|
- `GET /auth/status` – zeigt, ob Authentifizierung aktiviert ist.
|
||||||
|
- `POST /auth/login` – Login mit Benutzername/Passwort, liefert JWT.
|
||||||
|
- `GET /contracts?skip=0&limit=100` – Liste aller Verträge (max. 500 pro Anfrage).
|
||||||
|
- `POST /contracts` – Neuen Vertrag anlegen.
|
||||||
|
- `GET /contracts/:id` – Einzelnen Vertrag abrufen.
|
||||||
|
- `PUT /contracts/:id` – Vertrag aktualisieren (Felder optional/teilweise).
|
||||||
|
- `DELETE /contracts/:id` – Vertrag löschen.
|
||||||
|
- `GET /contracts/:id/paperless-document` – Zugehöriges paperless-Dokument abrufen (wenn verknüpft).
|
||||||
|
- `GET /reports/upcoming?days=N` – Anstehende Kündigungsdeadlines innerhalb der nächsten `N` Tage (Default = `ALERT_DAYS_BEFORE`).
|
||||||
|
|
||||||
|
Beispiel-JSON für Create/Update:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "KFZ-Versicherung 2024",
|
||||||
|
"paperlessDocumentId": 123,
|
||||||
|
"provider": "Versicherung AG",
|
||||||
|
"category": "Automotive",
|
||||||
|
"contractStartDate": "2024-01-01",
|
||||||
|
"contractEndDate": "2025-12-31",
|
||||||
|
"terminationNoticeDays": 30,
|
||||||
|
"renewalPeriodMonths": 12,
|
||||||
|
"autoRenew": true,
|
||||||
|
"price": 54.99,
|
||||||
|
"currency": "EUR",
|
||||||
|
"tags": ["kfz", "privat"],
|
||||||
|
"notes": "SFR prüfen im Herbst."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lokale Entwicklung – Backend
|
||||||
|
|
||||||
|
> Hinweis: Im aktuellen Arbeitsverzeichnis wurden noch keine Node-Module installiert (`npm install`). Auf dem Zielhost bitte einmal ausführen, damit `package-lock.json` entsteht und der Build reproduzierbar wird.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev # Hot-Reload via tsx
|
||||||
|
# oder
|
||||||
|
npm run build && npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
Die API ist anschließend unter `http://localhost:8000` erreichbar. Für Tests ohne paperless-Verbindung kann `PAPERLESS_*` weggelassen werden.
|
||||||
|
|
||||||
|
## Integration mit paperless-ngx
|
||||||
|
|
||||||
|
- Companion-Service und paperless-Container sollten im gleichen Docker-Netz laufen, damit `http://paperless:8000` erreichbar ist.
|
||||||
|
- Token in paperless-ngx erstellen (`Einstellungen → Tokens`) und als `PAPERLESS_TOKEN` setzen.
|
||||||
|
- Contract-IDs können mit Custom Fields/Tags in paperless verknüpft werden; die Companion-API hält zusätzliche Metadaten und erinnert an Fristen.
|
||||||
|
- Nutze `PAPERLESS_EXTERNAL_URL`, wenn die API intern erreichbar ist, die Benutzer im Browser aber eine andere URL (z. B. Reverse-Proxy mit TLS) verwenden sollen.
|
||||||
|
- Einstellungen (Paperless, Mail, ntfy, Scheduler) lassen sich komfortabel unter „Einstellungen“ in der Weboberfläche pflegen.
|
||||||
|
- Aktiviere Push-Benachrichtigungen via ntfy oder abonniere den iCal-Feed unter `https://<host>/api/calendar/feed.ics?token=<...>` (Token im Settings-Dialog sichtbar).
|
||||||
|
|
||||||
|
## Weiterführende Ideen
|
||||||
|
|
||||||
|
- Webhook/Chat-Integration (z.B. Matrix, Slack).
|
||||||
|
- ICS/CalDAV-Export der Deadlines.
|
||||||
|
- Intelligente Importer, die paperless-Tags automatisch auswerten.
|
||||||
|
- Multi-User-Unterstützung inkl. Rollen und Audit-Logs.
|
||||||
|
- Optionaler Reverse-Proxy mit TLS-Termination und Single-Sign-On.
|
||||||
51
docker-compose.yml
Normal file
51
docker-compose.yml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
contract-companion:
|
||||||
|
build: .
|
||||||
|
container_name: contract-companion
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- PORT=8000
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
- DATABASE_PATH=/app/data/contracts.db
|
||||||
|
- PAPERLESS_BASE_URL=http://paperless:8000
|
||||||
|
- PAPERLESS_EXTERNAL_URL=http://paperless:8000
|
||||||
|
- PAPERLESS_TOKEN=replace-with-token
|
||||||
|
- ALERT_DAYS_BEFORE=45
|
||||||
|
- SCHEDULER_INTERVAL_MINUTES=60
|
||||||
|
- AUTH_USERNAME=admin
|
||||||
|
- AUTH_PASSWORD=change-me
|
||||||
|
- AUTH_JWT_SECRET=replace-with-random-secret
|
||||||
|
- AUTH_TOKEN_EXPIRES_IN_HOURS=12
|
||||||
|
# Optional ntfy push settings:
|
||||||
|
# - NTFY_SERVER_URL=https://ntfy.example.com
|
||||||
|
# - NTFY_TOPIC=contracts
|
||||||
|
# - NTFY_TOKEN=secret
|
||||||
|
# - NTFY_PRIORITY=high
|
||||||
|
# Optional mail settings:
|
||||||
|
# - MAIL_SERVER=smtp.example.com
|
||||||
|
# - MAIL_PORT=587
|
||||||
|
# - MAIL_USERNAME=mailer
|
||||||
|
# - MAIL_PASSWORD=secret
|
||||||
|
# - MAIL_USE_TLS=true
|
||||||
|
# - MAIL_FROM=contract-monitor@example.com
|
||||||
|
# - MAIL_TO=you@example.com
|
||||||
|
# Optional: festen iCal-Token vorgeben
|
||||||
|
# - ICAL_SECRET=replace-with-secret
|
||||||
|
volumes:
|
||||||
|
- contracts-data:/app/data
|
||||||
|
ports:
|
||||||
|
- "8080:8000"
|
||||||
|
contract-companion-ui:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
container_name: contract-companion-ui
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8081:80"
|
||||||
|
depends_on:
|
||||||
|
- contract-companion
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
contracts-data:
|
||||||
7
docker-entrypoint.sh
Normal file
7
docker-entrypoint.sh
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
mkdir -p /app/data
|
||||||
|
chown -R appuser:appuser /app/data
|
||||||
|
|
||||||
|
exec su-exec appuser "$@"
|
||||||
19
frontend/Dockerfile
Normal file
19
frontend/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
FROM node:20-alpine AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
12
frontend/index.html
Normal file
12
frontend/index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Contracts Companion</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
frontend/nginx.conf
Normal file
24
frontend/nginx.conf
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location /assets/ {
|
||||||
|
try_files $uri =404;
|
||||||
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://contract-companion:8000/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
frontend/package.json
Normal file
35
frontend/package.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "paperless-contract-companion-ui",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.11.4",
|
||||||
|
"@emotion/styled": "^11.11.5",
|
||||||
|
"@hookform/resolvers": "^3.3.4",
|
||||||
|
"@mui/icons-material": "^5.15.15",
|
||||||
|
"@mui/material": "^5.15.15",
|
||||||
|
"@tanstack/react-query": "^5.29.2",
|
||||||
|
"date-fns": "^3.6.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-hook-form": "^7.50.1",
|
||||||
|
"react-router-dom": "^6.22.3",
|
||||||
|
"recharts": "^2.8.0",
|
||||||
|
"zod": "^3.22.4",
|
||||||
|
"i18next": "^23.10.1",
|
||||||
|
"react-i18next": "^13.5.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.2.46",
|
||||||
|
"@types/react-dom": "^18.2.18",
|
||||||
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
|
"typescript": "^5.3.3",
|
||||||
|
"vite": "^5.1.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
59
frontend/src/App.tsx
Normal file
59
frontend/src/App.tsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { Box, CircularProgress } from "@mui/material";
|
||||||
|
import { BrowserRouter, Navigate, Route, Routes, useLocation } from "react-router-dom";
|
||||||
|
|
||||||
|
import Layout from "./components/Layout";
|
||||||
|
import { useAuth } from "./contexts/AuthContext";
|
||||||
|
import CalendarView from "./routes/CalendarView";
|
||||||
|
import ContractDetail from "./routes/ContractDetail";
|
||||||
|
import ContractForm from "./routes/ContractForm";
|
||||||
|
import ContractsList from "./routes/ContractsList";
|
||||||
|
import Dashboard from "./routes/Dashboard";
|
||||||
|
import LoginPage from "./routes/Login";
|
||||||
|
import SettingsPage from "./routes/Settings";
|
||||||
|
|
||||||
|
function ProtectedRoute({ children }: { children: JSX.Element }) {
|
||||||
|
const { isAuthenticated, loading } = useAuth();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<Box display="flex" justifyContent="center" alignItems="center" minHeight="60vh">
|
||||||
|
<CircularProgress />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
return <Navigate to="/login" state={{ from: location }} replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<BrowserRouter>
|
||||||
|
<Routes>
|
||||||
|
<Route path="/login" element={<LoginPage />} />
|
||||||
|
<Route
|
||||||
|
path="/"
|
||||||
|
element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<Layout />
|
||||||
|
</ProtectedRoute>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Route index element={<Navigate to="/dashboard" replace />} />
|
||||||
|
<Route path="dashboard" element={<Dashboard />} />
|
||||||
|
<Route path="contracts" element={<ContractsList />} />
|
||||||
|
<Route path="contracts/new" element={<ContractForm mode="create" />} />
|
||||||
|
<Route path="contracts/:contractId" element={<ContractDetail />} />
|
||||||
|
<Route path="contracts/:contractId/edit" element={<ContractForm mode="edit" />} />
|
||||||
|
<Route path="calendar" element={<CalendarView />} />
|
||||||
|
<Route path="settings" element={<SettingsPage />} />
|
||||||
|
</Route>
|
||||||
|
<Route path="*" element={<Navigate to="/dashboard" replace />} />
|
||||||
|
</Routes>
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
}
|
||||||
36
frontend/src/api/auth.ts
Normal file
36
frontend/src/api/auth.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { clearAuthToken, request, setAuthToken } from "./client";
|
||||||
|
|
||||||
|
export interface LoginResponse {
|
||||||
|
token: string;
|
||||||
|
expiresAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AuthStatus {
|
||||||
|
enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function login(username: string, password: string): Promise<LoginResponse> {
|
||||||
|
const result = await request<LoginResponse>("/auth/login", {
|
||||||
|
method: "POST",
|
||||||
|
body: { username, password },
|
||||||
|
skipAuth: true
|
||||||
|
});
|
||||||
|
setAuthToken(result.token);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function signOut() {
|
||||||
|
clearAuthToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setToken(token: string | null) {
|
||||||
|
if (token) {
|
||||||
|
setAuthToken(token);
|
||||||
|
} else {
|
||||||
|
clearAuthToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchAuthStatus(): Promise<AuthStatus> {
|
||||||
|
return request<AuthStatus>("/auth/status", { method: "GET", skipAuth: true });
|
||||||
|
}
|
||||||
74
frontend/src/api/client.ts
Normal file
74
frontend/src/api/client.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
function resolveDefaultBaseUrl(): string {
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
return "/api";
|
||||||
|
}
|
||||||
|
return "http://localhost:8000";
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseUrl = (import.meta.env.VITE_API_BASE_URL ?? resolveDefaultBaseUrl()).replace(/\/$/, "");
|
||||||
|
|
||||||
|
let authToken: string | null = null;
|
||||||
|
|
||||||
|
export function setAuthToken(token: string | null) {
|
||||||
|
authToken = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ApiError extends Error {
|
||||||
|
status?: number;
|
||||||
|
details?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiRequestInit = Omit<RequestInit, "body"> & {
|
||||||
|
body?: unknown;
|
||||||
|
skipAuth?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function request<T = unknown>(path: string, options: ApiRequestInit = {}): Promise<T> {
|
||||||
|
const url = `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
|
||||||
|
const { skipAuth, body, headers, ...rest } = options;
|
||||||
|
|
||||||
|
const requestHeaders = new Headers(headers ?? {});
|
||||||
|
requestHeaders.set("Accept", "application/json");
|
||||||
|
|
||||||
|
const hasBody = body !== undefined && body !== null;
|
||||||
|
const rawBody = body as any;
|
||||||
|
const isFormData = hasBody && typeof FormData !== "undefined" && rawBody instanceof FormData;
|
||||||
|
|
||||||
|
if (hasBody && !isFormData) {
|
||||||
|
requestHeaders.set("Content-Type", "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipAuth && authToken) {
|
||||||
|
requestHeaders.set("Authorization", `Bearer ${authToken}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let requestBody: BodyInit | null | undefined = undefined;
|
||||||
|
if (hasBody) {
|
||||||
|
requestBody = isFormData ? (rawBody as FormData) : JSON.stringify(rawBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
...rest,
|
||||||
|
headers: requestHeaders,
|
||||||
|
body: requestBody
|
||||||
|
});
|
||||||
|
|
||||||
|
const contentType = response.headers.get("content-type");
|
||||||
|
const isJson = contentType?.includes("application/json");
|
||||||
|
const payload = isJson ? await response.json().catch(() => undefined) : await response.text();
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const error: ApiError = new Error(
|
||||||
|
typeof payload === "string" && payload ? payload : "Request failed"
|
||||||
|
);
|
||||||
|
error.status = response.status;
|
||||||
|
error.details = payload;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearAuthToken() {
|
||||||
|
authToken = null;
|
||||||
|
}
|
||||||
91
frontend/src/api/config.ts
Normal file
91
frontend/src/api/config.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import { request } from "./client";
|
||||||
|
|
||||||
|
export interface ServerConfig {
|
||||||
|
port: number;
|
||||||
|
logLevel: string;
|
||||||
|
databasePath: string;
|
||||||
|
paperlessBaseUrl: string | null;
|
||||||
|
paperlessExternalUrl: string | null;
|
||||||
|
paperlessConfigured: boolean;
|
||||||
|
schedulerIntervalMinutes: number;
|
||||||
|
alertDaysBefore: number;
|
||||||
|
mailConfigured: boolean;
|
||||||
|
mailServer: string | null;
|
||||||
|
mailFrom: string | null;
|
||||||
|
mailUseTls: boolean;
|
||||||
|
ntfyConfigured: boolean;
|
||||||
|
authEnabled: boolean;
|
||||||
|
authTokenExpiresInHours: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchServerConfig(): Promise<ServerConfig> {
|
||||||
|
return request<ServerConfig>("/config", { method: "GET" });
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SettingsResponse {
|
||||||
|
values: {
|
||||||
|
paperlessBaseUrl: string | null;
|
||||||
|
paperlessExternalUrl: string | null;
|
||||||
|
schedulerIntervalMinutes: number;
|
||||||
|
alertDaysBefore: number;
|
||||||
|
mailServer: string | null;
|
||||||
|
mailPort: number | null;
|
||||||
|
mailUsername: string | null;
|
||||||
|
mailFrom: string | null;
|
||||||
|
mailTo: string | null;
|
||||||
|
mailUseTls: boolean;
|
||||||
|
ntfyServerUrl: string | null;
|
||||||
|
ntfyTopic: string | null;
|
||||||
|
ntfyPriority: string | null;
|
||||||
|
authUsername: string | null;
|
||||||
|
};
|
||||||
|
secrets: {
|
||||||
|
paperlessTokenSet: boolean;
|
||||||
|
mailPasswordSet: boolean;
|
||||||
|
ntfyTokenSet: boolean;
|
||||||
|
authPasswordSet: boolean;
|
||||||
|
};
|
||||||
|
icalSecret: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UpdateSettingsPayload = Partial<{
|
||||||
|
paperlessBaseUrl: string | null;
|
||||||
|
paperlessExternalUrl: string | null;
|
||||||
|
paperlessToken: string | null;
|
||||||
|
schedulerIntervalMinutes: number;
|
||||||
|
alertDaysBefore: number;
|
||||||
|
mailServer: string | null;
|
||||||
|
mailPort: number | null;
|
||||||
|
mailUsername: string | null;
|
||||||
|
mailPassword: string | null;
|
||||||
|
mailUseTls: boolean;
|
||||||
|
mailFrom: string | null;
|
||||||
|
mailTo: string | null;
|
||||||
|
ntfyServerUrl: string | null;
|
||||||
|
ntfyTopic: string | null;
|
||||||
|
ntfyToken: string | null;
|
||||||
|
ntfyPriority: string | null;
|
||||||
|
authUsername: string | null;
|
||||||
|
authPassword: string | null;
|
||||||
|
icalSecret: string | null;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export async function fetchSettings(): Promise<SettingsResponse> {
|
||||||
|
return request<SettingsResponse>("/settings", { method: "GET" });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateSettings(payload: UpdateSettingsPayload): Promise<SettingsResponse> {
|
||||||
|
return request<SettingsResponse>("/settings", { method: "PUT", body: payload });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function resetIcalSecret(): Promise<{ icalSecret: string | null }> {
|
||||||
|
return request<{ icalSecret: string | null }>("/settings/ical-secret/reset", { method: "POST" });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function triggerMailTest(): Promise<void> {
|
||||||
|
await request("/settings/test/mail", { method: "POST" });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function triggerNtfyTest(): Promise<void> {
|
||||||
|
await request("/settings/test/ntfy", { method: "POST" });
|
||||||
|
}
|
||||||
88
frontend/src/api/contracts.ts
Normal file
88
frontend/src/api/contracts.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import { request } from "./client";
|
||||||
|
import {
|
||||||
|
Contract,
|
||||||
|
ContractPayload,
|
||||||
|
PaperlessDocument,
|
||||||
|
PaperlessSearchResponse,
|
||||||
|
UpcomingDeadline
|
||||||
|
} from "../types";
|
||||||
|
|
||||||
|
export interface ContractsQuery {
|
||||||
|
skip?: number;
|
||||||
|
limit?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchContracts(query: ContractsQuery = {}): Promise<Contract[]> {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
if (query.skip !== undefined) params.set("skip", String(query.skip));
|
||||||
|
if (query.limit !== undefined) params.set("limit", String(query.limit));
|
||||||
|
|
||||||
|
const suffix = params.toString() ? `?${params.toString()}` : "";
|
||||||
|
const result = await request<unknown>(`/contracts${suffix}`, { method: "GET" });
|
||||||
|
if (!Array.isArray(result)) {
|
||||||
|
throw new Error("Unexpected response format for contracts");
|
||||||
|
}
|
||||||
|
return result as Contract[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchContract(contractId: number): Promise<Contract> {
|
||||||
|
const result = await request<unknown>(`/contracts/${contractId}`, { method: "GET" });
|
||||||
|
if (!result || typeof result !== "object") {
|
||||||
|
throw new Error("Unexpected response format for contract");
|
||||||
|
}
|
||||||
|
return result as Contract;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createContract(payload: ContractPayload): Promise<Contract> {
|
||||||
|
return request<Contract>("/contracts", {
|
||||||
|
method: "POST",
|
||||||
|
body: payload
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateContract(
|
||||||
|
contractId: number,
|
||||||
|
payload: Partial<ContractPayload>
|
||||||
|
): Promise<Contract> {
|
||||||
|
return request<Contract>(`/contracts/${contractId}`, {
|
||||||
|
method: "PUT",
|
||||||
|
body: payload
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeContract(contractId: number): Promise<void> {
|
||||||
|
await request(`/contracts/${contractId}`, { method: "DELETE" });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchUpcomingDeadlines(days?: number): Promise<UpcomingDeadline[]> {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
if (days !== undefined) params.set("days", String(days));
|
||||||
|
const suffix = params.toString() ? `?${params.toString()}` : "";
|
||||||
|
const result = await request<unknown>(`/reports/upcoming${suffix}`, { method: "GET" });
|
||||||
|
if (!Array.isArray(result)) {
|
||||||
|
throw new Error("Unexpected response format for deadlines");
|
||||||
|
}
|
||||||
|
return result as UpcomingDeadline[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchPaperlessDocument(
|
||||||
|
contractId: number
|
||||||
|
): Promise<PaperlessDocument | null> {
|
||||||
|
try {
|
||||||
|
return await request<PaperlessDocument | null>(`/contracts/${contractId}/paperless-document`, {
|
||||||
|
method: "GET"
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if ((error as { status?: number }).status === 404) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function searchPaperlessDocuments(query: string, page = 1): Promise<PaperlessSearchResponse> {
|
||||||
|
const params = new URLSearchParams({ q: query, page: String(page) });
|
||||||
|
return request<PaperlessSearchResponse>(`/integrations/paperless/search?${params.toString()}`, {
|
||||||
|
method: "GET"
|
||||||
|
});
|
||||||
|
}
|
||||||
85
frontend/src/components/DeadlineList.tsx
Normal file
85
frontend/src/components/DeadlineList.tsx
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
|
||||||
|
import { Box, Card, CardContent, Chip, List, ListItem, ListItemButton, ListItemText, Typography } from "@mui/material";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { UpcomingDeadline } from "../types";
|
||||||
|
import { formatDeadlineDate } from "../utils/date";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
deadlines: UpcomingDeadline[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DeadlineList({ deadlines }: Props) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
if (deadlines.length === 0) {
|
||||||
|
return (
|
||||||
|
<Card variant="outlined" sx={{ borderRadius: 3 }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="subtitle1">{t("deadlineList.none")}</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("deadlineList.info")}
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card variant="outlined" sx={{ borderRadius: 3 }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="subtitle1" gutterBottom>
|
||||||
|
{t("dashboard.upcomingList")}
|
||||||
|
</Typography>
|
||||||
|
<List>
|
||||||
|
{deadlines.map((deadline) => (
|
||||||
|
<ListItem
|
||||||
|
key={deadline.id}
|
||||||
|
disablePadding
|
||||||
|
secondaryAction={
|
||||||
|
deadline.daysUntilDeadline != null ? (
|
||||||
|
<Chip
|
||||||
|
label={t("deadlineList.daysLabel", { count: deadline.daysUntilDeadline })}
|
||||||
|
color={
|
||||||
|
deadline.daysUntilDeadline <= 7
|
||||||
|
? "error"
|
||||||
|
: deadline.daysUntilDeadline <= 21
|
||||||
|
? "warning"
|
||||||
|
: "default"
|
||||||
|
}
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemButton onClick={() => navigate(`/contracts/${deadline.id}`)}>
|
||||||
|
<ListItemText
|
||||||
|
primary={
|
||||||
|
<Box display="flex" alignItems="center" gap={1}>
|
||||||
|
<Typography variant="body1" fontWeight={600}>
|
||||||
|
{deadline.title}
|
||||||
|
</Typography>
|
||||||
|
<ArrowForwardIcon fontSize="small" color="primary" />
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
secondary={
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("deadlineList.terminateBy", { date: formatDeadlineDate(deadline.terminationDeadline) })}
|
||||||
|
{deadline.contractEndDate
|
||||||
|
? ` • ${t("deadlineList.contractEnds", {
|
||||||
|
date: formatDeadlineDate(deadline.contractEndDate)
|
||||||
|
})}`
|
||||||
|
: ""}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
164
frontend/src/components/Layout.tsx
Normal file
164
frontend/src/components/Layout.tsx
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
import MenuIcon from "@mui/icons-material/Menu";
|
||||||
|
import LogoutIcon from "@mui/icons-material/Logout";
|
||||||
|
import CalendarMonthIcon from "@mui/icons-material/CalendarMonth";
|
||||||
|
import DashboardIcon from "@mui/icons-material/Dashboard";
|
||||||
|
import DescriptionIcon from "@mui/icons-material/Description";
|
||||||
|
import SettingsIcon from "@mui/icons-material/Settings";
|
||||||
|
import {
|
||||||
|
AppBar,
|
||||||
|
Box,
|
||||||
|
Divider,
|
||||||
|
Drawer,
|
||||||
|
IconButton,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemIcon,
|
||||||
|
ListItemText,
|
||||||
|
MenuItem,
|
||||||
|
Select,
|
||||||
|
Toolbar,
|
||||||
|
Typography,
|
||||||
|
useMediaQuery,
|
||||||
|
useTheme
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { useAuth } from "../contexts/AuthContext";
|
||||||
|
import { useSnackbar } from "../hooks/useSnackbar";
|
||||||
|
|
||||||
|
const drawerWidth = 240;
|
||||||
|
|
||||||
|
const navItems = [
|
||||||
|
{ key: "nav.dashboard", icon: <DashboardIcon />, path: "/dashboard" },
|
||||||
|
{ key: "nav.contracts", icon: <DescriptionIcon />, path: "/contracts" },
|
||||||
|
{ key: "nav.calendar", icon: <CalendarMonthIcon />, path: "/calendar" },
|
||||||
|
{ key: "nav.settings", icon: <SettingsIcon />, path: "/settings" }
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Layout() {
|
||||||
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
|
||||||
|
const location = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { logout } = useAuth();
|
||||||
|
const { showMessage } = useSnackbar();
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
|
const handleDrawerToggle = () => {
|
||||||
|
setMobileOpen((prev) => !prev);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNavigate = (path: string) => {
|
||||||
|
navigate(path);
|
||||||
|
if (isMobile) {
|
||||||
|
setMobileOpen(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const drawer = (
|
||||||
|
<div>
|
||||||
|
<Toolbar>
|
||||||
|
<Typography variant="h6" noWrap component="div">
|
||||||
|
Contracts Companion
|
||||||
|
</Typography>
|
||||||
|
</Toolbar>
|
||||||
|
<Divider />
|
||||||
|
<List>
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<ListItem key={item.path} disablePadding>
|
||||||
|
<ListItemButton
|
||||||
|
selected={location.pathname.startsWith(item.path)}
|
||||||
|
onClick={() => handleNavigate(item.path)}
|
||||||
|
>
|
||||||
|
<ListItemIcon>{item.icon}</ListItemIcon>
|
||||||
|
<ListItemText primary={t(item.key)} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
<Divider />
|
||||||
|
<List>
|
||||||
|
<ListItem disablePadding>
|
||||||
|
<ListItemButton
|
||||||
|
onClick={() => {
|
||||||
|
logout();
|
||||||
|
showMessage(t("messages.signedOut"), "info");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ListItemIcon>
|
||||||
|
<LogoutIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={t("nav.logout") } />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ display: "flex" }}>
|
||||||
|
<AppBar position="fixed" sx={{ zIndex: theme.zIndex.drawer + 1, backdropFilter: "blur(10px)" }}>
|
||||||
|
<Toolbar>
|
||||||
|
{isMobile && (
|
||||||
|
<IconButton
|
||||||
|
color="inherit"
|
||||||
|
aria-label="open drawer"
|
||||||
|
edge="start"
|
||||||
|
onClick={handleDrawerToggle}
|
||||||
|
sx={{ mr: 2 }}
|
||||||
|
>
|
||||||
|
<MenuIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||||
|
{t("layout.title")}
|
||||||
|
</Typography>
|
||||||
|
<Select
|
||||||
|
size="small"
|
||||||
|
value={i18n.language.startsWith("de") ? "de" : "en"}
|
||||||
|
onChange={(event) => i18n.changeLanguage(event.target.value)}
|
||||||
|
sx={{ color: "inherit", borderColor: "inherit", minWidth: 80 }}
|
||||||
|
>
|
||||||
|
<MenuItem value="de">DE</MenuItem>
|
||||||
|
<MenuItem value="en">EN</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</Toolbar>
|
||||||
|
</AppBar>
|
||||||
|
|
||||||
|
<Box component="nav" sx={{ width: { md: drawerWidth }, flexShrink: { md: 0 } }} aria-label="navigation">
|
||||||
|
<Drawer
|
||||||
|
variant={isMobile ? "temporary" : "permanent"}
|
||||||
|
open={isMobile ? mobileOpen : true}
|
||||||
|
onClose={handleDrawerToggle}
|
||||||
|
ModalProps={{ keepMounted: true }}
|
||||||
|
sx={{
|
||||||
|
"& .MuiDrawer-paper": {
|
||||||
|
boxSizing: "border-box",
|
||||||
|
width: drawerWidth
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{drawer}
|
||||||
|
</Drawer>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
component="main"
|
||||||
|
sx={{
|
||||||
|
flexGrow: 1,
|
||||||
|
p: 3,
|
||||||
|
width: { md: `calc(100% - ${drawerWidth}px)` },
|
||||||
|
minHeight: "100vh",
|
||||||
|
backgroundColor: (theme) => theme.palette.background.default
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Toolbar />
|
||||||
|
<Outlet />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
26
frontend/src/components/PageHeader.tsx
Normal file
26
frontend/src/components/PageHeader.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Box, Typography } from "@mui/material";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
subtitle?: string;
|
||||||
|
action?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PageHeader({ title, subtitle, action }: Props) {
|
||||||
|
return (
|
||||||
|
<Box display="flex" justifyContent="space-between" alignItems="center" mb={3} flexWrap="wrap" gap={2}>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h4" fontWeight={600}>
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
{subtitle && (
|
||||||
|
<Typography variant="subtitle1" color="text.secondary">
|
||||||
|
{subtitle}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
{action}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
134
frontend/src/components/PaperlessSearchDialog.tsx
Normal file
134
frontend/src/components/PaperlessSearchDialog.tsx
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import SearchIcon from "@mui/icons-material/Search";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
IconButton,
|
||||||
|
InputAdornment,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemText,
|
||||||
|
Stack,
|
||||||
|
TextField,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import { searchPaperlessDocuments } from "../api/contracts";
|
||||||
|
import { useSnackbar } from "../hooks/useSnackbar";
|
||||||
|
import { PaperlessDocument, PaperlessSearchResponse } from "../types";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onSelect: (document: PaperlessDocument) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PaperlessSearchDialog({ open, onClose, onSelect }: Props) {
|
||||||
|
const { showMessage } = useSnackbar();
|
||||||
|
const [query, setQuery] = useState("");
|
||||||
|
const [results, setResults] = useState<PaperlessSearchResponse | null>(null);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const searchMutation = useMutation({
|
||||||
|
mutationFn: (term: string) => searchPaperlessDocuments(term),
|
||||||
|
onSuccess: (data) => setResults(data),
|
||||||
|
onError: (error: Error) => showMessage(error.message ?? t("paperlessDialog.error"), "error")
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) {
|
||||||
|
setQuery("");
|
||||||
|
setResults(null);
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
if (query.trim().length < 2) {
|
||||||
|
showMessage(t("paperlessDialog.minChars"), "warning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
searchMutation.mutate(query.trim());
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={onClose} fullWidth maxWidth="md">
|
||||||
|
<DialogTitle>
|
||||||
|
{t("paperlessDialog.title")}
|
||||||
|
<IconButton
|
||||||
|
aria-label="close"
|
||||||
|
onClick={onClose}
|
||||||
|
sx={{ position: "absolute", right: 12, top: 12 }}
|
||||||
|
>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<TextField
|
||||||
|
label={t("contracts.searchLabel")}
|
||||||
|
value={query}
|
||||||
|
onChange={(event) => setQuery(event.target.value)}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
event.preventDefault();
|
||||||
|
handleSearch();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<IconButton onClick={handleSearch} edge="end">
|
||||||
|
<SearchIcon />
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
placeholder={t("paperlessDialog.searchPlaceholder")}
|
||||||
|
fullWidth
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
{searchMutation.isPending && <Typography>{t("paperlessDialog.searching")}</Typography>}
|
||||||
|
{results && results.results.length === 0 && !searchMutation.isPending && (
|
||||||
|
<Typography color="text.secondary">{t("paperlessDialog.noResults")}</Typography>
|
||||||
|
)}
|
||||||
|
{results && results.results.length > 0 && (
|
||||||
|
<List>
|
||||||
|
{results.results.map((doc) => (
|
||||||
|
<ListItem key={doc.id} disablePadding>
|
||||||
|
<ListItemButton
|
||||||
|
onClick={() => {
|
||||||
|
onSelect(doc);
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ListItemText
|
||||||
|
primary={doc.title ?? `Dokument #${doc.id}`}
|
||||||
|
secondary={
|
||||||
|
<Box component="span" sx={{ display: "block", color: "text.secondary" }}>
|
||||||
|
{(doc as Record<string, unknown>).correspondent
|
||||||
|
? `${t("paperlessDialog.correspondent")}: ${(doc as Record<string, unknown>).correspondent}`
|
||||||
|
: ""}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={onClose}>{t("paperlessDialog.cancel")}</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
31
frontend/src/components/StatCard.tsx
Normal file
31
frontend/src/components/StatCard.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import TrendingDownIcon from "@mui/icons-material/TrendingDown";
|
||||||
|
import TrendingUpIcon from "@mui/icons-material/TrendingUp";
|
||||||
|
import { Box, Card, CardContent, Typography } from "@mui/material";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
value: string | number;
|
||||||
|
trend?: "up" | "down";
|
||||||
|
trendLabel?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function StatCard({ title, value, trend, trendLabel }: Props) {
|
||||||
|
return (
|
||||||
|
<Card elevation={0} sx={{ borderRadius: 3, background: "linear-gradient(135deg,#ffffff,#f0f4ff)" }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="h4" fontWeight={600}>
|
||||||
|
{value}
|
||||||
|
</Typography>
|
||||||
|
{trend && trendLabel && (
|
||||||
|
<Box display="flex" alignItems="center" gap={0.5} mt={1} color={trend === "up" ? "success.main" : "error.main"}>
|
||||||
|
{trend === "up" ? <TrendingUpIcon fontSize="small" /> : <TrendingDownIcon fontSize="small" />}
|
||||||
|
<Typography variant="body2">{trendLabel}</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
108
frontend/src/contexts/AuthContext.tsx
Normal file
108
frontend/src/contexts/AuthContext.tsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
|
import { fetchAuthStatus, login as apiLogin, setToken as setClientToken, signOut } from "../api/auth";
|
||||||
|
|
||||||
|
interface AuthContextValue {
|
||||||
|
token: string | null;
|
||||||
|
expiresAt: string | null;
|
||||||
|
authEnabled: boolean;
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
loading: boolean;
|
||||||
|
login: (username: string, password: string) => Promise<void>;
|
||||||
|
logout: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TOKEN_KEY = "contract-companion.token";
|
||||||
|
const EXPIRY_KEY = "contract-companion.tokenExpiry";
|
||||||
|
|
||||||
|
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
|
||||||
|
|
||||||
|
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
const [token, setTokenState] = useState<string | null>(null);
|
||||||
|
const [expiresAt, setExpiresAt] = useState<string | null>(null);
|
||||||
|
const [authEnabled, setAuthEnabled] = useState<boolean>(true);
|
||||||
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function init() {
|
||||||
|
try {
|
||||||
|
const status = await fetchAuthStatus();
|
||||||
|
setAuthEnabled(status.enabled);
|
||||||
|
|
||||||
|
const storedToken = localStorage.getItem(TOKEN_KEY);
|
||||||
|
const storedExpiry = localStorage.getItem(EXPIRY_KEY);
|
||||||
|
|
||||||
|
if (!status.enabled) {
|
||||||
|
setTokenState(null);
|
||||||
|
setExpiresAt(null);
|
||||||
|
setClientToken(null);
|
||||||
|
} else if (storedToken && storedExpiry && new Date(storedExpiry) > new Date()) {
|
||||||
|
setTokenState(storedToken);
|
||||||
|
setExpiresAt(storedExpiry);
|
||||||
|
setClientToken(storedToken);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(TOKEN_KEY);
|
||||||
|
localStorage.removeItem(EXPIRY_KEY);
|
||||||
|
setClientToken(null);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// assume auth is required if status endpoint fails
|
||||||
|
setAuthEnabled(true);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const setToken = useCallback((newToken: string | null, expiry: string | null) => {
|
||||||
|
setTokenState(newToken);
|
||||||
|
setExpiresAt(expiry);
|
||||||
|
setClientToken(newToken);
|
||||||
|
|
||||||
|
if (newToken && expiry) {
|
||||||
|
localStorage.setItem(TOKEN_KEY, newToken);
|
||||||
|
localStorage.setItem(EXPIRY_KEY, expiry);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(TOKEN_KEY);
|
||||||
|
localStorage.removeItem(EXPIRY_KEY);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const login = useCallback(
|
||||||
|
async (username: string, password: string) => {
|
||||||
|
const result = await apiLogin(username, password);
|
||||||
|
setToken(result.token, result.expiresAt);
|
||||||
|
},
|
||||||
|
[setToken]
|
||||||
|
);
|
||||||
|
|
||||||
|
const logout = useCallback(() => {
|
||||||
|
signOut();
|
||||||
|
setToken(null, null);
|
||||||
|
}, [setToken]);
|
||||||
|
|
||||||
|
const value = useMemo<AuthContextValue>(
|
||||||
|
() => ({
|
||||||
|
token,
|
||||||
|
expiresAt,
|
||||||
|
authEnabled,
|
||||||
|
isAuthenticated: !authEnabled || Boolean(token),
|
||||||
|
loading,
|
||||||
|
login,
|
||||||
|
logout
|
||||||
|
}),
|
||||||
|
[authEnabled, loading, login, logout, token, expiresAt]
|
||||||
|
);
|
||||||
|
|
||||||
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAuth(): AuthContextValue {
|
||||||
|
const context = useContext(AuthContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useAuth must be used within AuthProvider");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
54
frontend/src/hooks/useSnackbar.tsx
Normal file
54
frontend/src/hooks/useSnackbar.tsx
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { Alert, AlertColor, Snackbar } from "@mui/material";
|
||||||
|
import { createContext, useContext, useMemo, useState } from "react";
|
||||||
|
|
||||||
|
interface SnackbarState {
|
||||||
|
open: boolean;
|
||||||
|
message: string;
|
||||||
|
severity: AlertColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SnackbarContextValue {
|
||||||
|
showMessage: (message: string, severity?: AlertColor) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SnackbarContext = createContext<SnackbarContextValue | undefined>(undefined);
|
||||||
|
|
||||||
|
export function SnackbarProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
const [state, setState] = useState<SnackbarState>({
|
||||||
|
open: false,
|
||||||
|
message: "",
|
||||||
|
severity: "info"
|
||||||
|
});
|
||||||
|
|
||||||
|
const showMessage = (message: string, severity: AlertColor = "info") => {
|
||||||
|
setState({ open: true, message, severity });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => setState((prev) => ({ ...prev, open: false }));
|
||||||
|
|
||||||
|
const value = useMemo(() => ({ showMessage }), []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SnackbarContext.Provider value={value}>
|
||||||
|
{children}
|
||||||
|
<Snackbar
|
||||||
|
open={state.open}
|
||||||
|
autoHideDuration={4000}
|
||||||
|
onClose={handleClose}
|
||||||
|
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
|
||||||
|
>
|
||||||
|
<Alert onClose={handleClose} severity={state.severity} variant="filled" sx={{ width: "100%" }}>
|
||||||
|
{state.message}
|
||||||
|
</Alert>
|
||||||
|
</Snackbar>
|
||||||
|
</SnackbarContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSnackbar(): SnackbarContextValue {
|
||||||
|
const context = useContext(SnackbarContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useSnackbar must be used within SnackbarProvider");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
68
frontend/src/i18n.ts
Normal file
68
frontend/src/i18n.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import i18n from "i18next";
|
||||||
|
import { initReactI18next } from "react-i18next";
|
||||||
|
|
||||||
|
import en from "./locales/en/common.json";
|
||||||
|
import de from "./locales/de/common.json";
|
||||||
|
|
||||||
|
const LANGUAGE_STORAGE_KEY = "contract-companion.language";
|
||||||
|
const SUPPORTED_LANGUAGES = ["en", "de"] as const;
|
||||||
|
|
||||||
|
type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];
|
||||||
|
|
||||||
|
function normalizeLanguage(value?: string | null): SupportedLanguage {
|
||||||
|
if (!value) return "en";
|
||||||
|
const lower = value.toLowerCase();
|
||||||
|
const match = SUPPORTED_LANGUAGES.find((lang) => lower.startsWith(lang));
|
||||||
|
return match ?? "en";
|
||||||
|
}
|
||||||
|
|
||||||
|
function detectInitialLanguage(): SupportedLanguage {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return "en";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const stored = window.localStorage.getItem(LANGUAGE_STORAGE_KEY);
|
||||||
|
if (stored) {
|
||||||
|
return normalizeLanguage(stored);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Access to localStorage might be blocked (e.g., privacy mode); ignore and fall back to navigator.
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeLanguage(window.navigator.language);
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialLanguage = detectInitialLanguage();
|
||||||
|
|
||||||
|
i18n.use(initReactI18next).init({
|
||||||
|
resources: {
|
||||||
|
en: { translation: en },
|
||||||
|
de: { translation: de }
|
||||||
|
},
|
||||||
|
lng: initialLanguage,
|
||||||
|
fallbackLng: "en",
|
||||||
|
supportedLngs: ["en", "de"],
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
const applyLanguageSideEffects = (lang: string) => {
|
||||||
|
const normalized = normalizeLanguage(lang);
|
||||||
|
try {
|
||||||
|
window.localStorage.setItem(LANGUAGE_STORAGE_KEY, normalized);
|
||||||
|
} catch {
|
||||||
|
// Ignore storage write failures (private mode, etc.)
|
||||||
|
}
|
||||||
|
if (typeof document !== "undefined") {
|
||||||
|
document.documentElement.setAttribute("lang", normalized);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
applyLanguageSideEffects(initialLanguage);
|
||||||
|
i18n.on("languageChanged", applyLanguageSideEffects);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default i18n;
|
||||||
250
frontend/src/locales/de/common.json
Normal file
250
frontend/src/locales/de/common.json
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
{
|
||||||
|
"nav": {
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"contracts": "Verträge",
|
||||||
|
"calendar": "Kalender",
|
||||||
|
"settings": "Einstellungen",
|
||||||
|
"logout": "Abmelden"
|
||||||
|
},
|
||||||
|
"layout": {
|
||||||
|
"title": "Vertragsübersicht",
|
||||||
|
"language": "Sprache"
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"save": "Speichern",
|
||||||
|
"saving": "Speichern…",
|
||||||
|
"cancel": "Abbrechen",
|
||||||
|
"delete": "Löschen",
|
||||||
|
"search": "Suchen",
|
||||||
|
"test": "Test senden",
|
||||||
|
"testMail": "Testmail senden",
|
||||||
|
"testNtfy": "Test senden",
|
||||||
|
"copy": "In Zwischenablage kopiert",
|
||||||
|
"copyUnsupported": "Kopieren wird nicht unterstützt",
|
||||||
|
"copyFailed": "Kopieren fehlgeschlagen"
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"title": "Dashboard",
|
||||||
|
"subtitle": "Alle wichtigen Vertragskennzahlen auf einen Blick.",
|
||||||
|
"totalContracts": "Gesamtverträge",
|
||||||
|
"activeContracts": "Aktive Verträge",
|
||||||
|
"monthlySpend": "Monatliche Kosten (Summe)",
|
||||||
|
"deadlineChartTitle": "Kündigungsfristen pro Monat",
|
||||||
|
"noDeadlines": "Derzeit stehen keine Deadlines an.",
|
||||||
|
"upcomingList": "Nächste Kündigungsfristen",
|
||||||
|
"loading": "Lade Daten…",
|
||||||
|
"contractsError": "Verträge konnten nicht geladen werden.",
|
||||||
|
"deadlinesError": "Deadlines konnten nicht geladen werden.",
|
||||||
|
"totalContractsTrend": "+100% erfasst",
|
||||||
|
"monthlySpendTrend": "Budget im Blick"
|
||||||
|
},
|
||||||
|
"deadlineList": {
|
||||||
|
"none": "Keine anstehenden Deadlines",
|
||||||
|
"info": "Du bist auf Stand – es stehen aktuell keine Kündigungsfristen an.",
|
||||||
|
"daysLabel_one": "{{count}} Tag",
|
||||||
|
"daysLabel_other": "{{count}} Tage",
|
||||||
|
"terminateBy": "Kündigen bis spätestens {{date}}",
|
||||||
|
"contractEnds": "Vertrag bis {{date}}"
|
||||||
|
},
|
||||||
|
"calendar": {
|
||||||
|
"title": "Kalender & Deadlines",
|
||||||
|
"subtitle": "Plane Kündigungsfristen langfristig und behalte Verlängerungen im Blick.",
|
||||||
|
"loading": "Lade Deadlines…",
|
||||||
|
"none": "Keine Deadlines innerhalb der nächsten 12 Monate.",
|
||||||
|
"deadlineCount_one": "{{count}} Deadline",
|
||||||
|
"deadlineCount_other": "{{count}} Deadlines",
|
||||||
|
"unknownMonth": "Unbekannt"
|
||||||
|
},
|
||||||
|
"contracts": {
|
||||||
|
"title": "Verträge",
|
||||||
|
"subtitle": "Alle laufenden und vergangenen Verträge im Überblick.",
|
||||||
|
"new": "Neuer Vertrag",
|
||||||
|
"searchPlaceholder": "z.B. Anbieter, Titel, Schlagwort",
|
||||||
|
"searchLabel": "Suche",
|
||||||
|
"filterAll": "Alle Kategorien",
|
||||||
|
"columns": {
|
||||||
|
"title": "Titel",
|
||||||
|
"provider": "Anbieter",
|
||||||
|
"category": "Kategorie",
|
||||||
|
"price": "Preis",
|
||||||
|
"end": "Ende",
|
||||||
|
"tags": "Tags",
|
||||||
|
"actions": "Aktionen"
|
||||||
|
},
|
||||||
|
"loading": "Lade Verträge…",
|
||||||
|
"empty": "Keine Verträge gefunden.",
|
||||||
|
"deleteConfirm": "Vertrag \"{{title}}\" wirklich löschen?",
|
||||||
|
"details": "Details anzeigen",
|
||||||
|
"edit": "Bearbeiten",
|
||||||
|
"deleted": "Vertrag gelöscht",
|
||||||
|
"deleteError": "Löschen fehlgeschlagen"
|
||||||
|
},
|
||||||
|
"contractForm": {
|
||||||
|
"createTitle": "Neuen Vertrag anlegen",
|
||||||
|
"createSubtitle": "Erfasse alle wichtigen Vertragsdetails.",
|
||||||
|
"editSubtitle": "Bearbeite die Daten von \"{{title}}\".",
|
||||||
|
"fields": {
|
||||||
|
"title": "Titel",
|
||||||
|
"provider": "Anbieter",
|
||||||
|
"category": "Kategorie",
|
||||||
|
"paperlessId": "Paperless Dokument-ID",
|
||||||
|
"contractStart": "Vertragsbeginn",
|
||||||
|
"contractEnd": "Vertragsende",
|
||||||
|
"terminationNotice": "Kündigungsfrist (Tage)",
|
||||||
|
"renewalPeriod": "Verlängerung (Monate)",
|
||||||
|
"autoRenew": "Automatische Verlängerung",
|
||||||
|
"price": "Preis",
|
||||||
|
"currency": "Währung",
|
||||||
|
"notes": "Notizen",
|
||||||
|
"tags": "Tags (durch Komma getrennt)",
|
||||||
|
"searchButton": "Suchen"
|
||||||
|
},
|
||||||
|
"tagsPlaceholder": "z.B. strom, wohnung",
|
||||||
|
"paperlessNotConfigured": "Paperless ist nicht konfiguriert. Hinterlege die API-URL und das Token in den Einstellungen.",
|
||||||
|
"paperlessLinked": "Verknüpft mit: {{title}}",
|
||||||
|
"saving": "Speichere…",
|
||||||
|
"save": "Speichern",
|
||||||
|
"saved": "Vertrag \"{{title}}\" gespeichert",
|
||||||
|
"loadError": "Ungültige Vertrags-ID",
|
||||||
|
"loading": "Lade Vertrag…",
|
||||||
|
"saveError": "Speichern fehlgeschlagen",
|
||||||
|
"invalidNumber": "Bitte eine gültige Zahl eingeben"
|
||||||
|
},
|
||||||
|
"contractDetail": {
|
||||||
|
"edit": "Vertrag bearbeiten",
|
||||||
|
"details": "Vertragsdetails",
|
||||||
|
"start": "Vertragsbeginn",
|
||||||
|
"end": "Vertragsende",
|
||||||
|
"notice": "Kündigungsfrist",
|
||||||
|
"renewal": "Verlängerung",
|
||||||
|
"price": "Preis",
|
||||||
|
"category": "Kategorie",
|
||||||
|
"notes": "Notizen",
|
||||||
|
"tags": "Tags",
|
||||||
|
"noTags": "Keine Tags vergeben.",
|
||||||
|
"noNotes": "Keine Notizen",
|
||||||
|
"document": "Verknüpftes Dokument",
|
||||||
|
"documentFallback": "Dokument",
|
||||||
|
"documentError": "Paperless-Dokument konnte nicht geladen werden: {{error}}",
|
||||||
|
"documentMissing": "Kein Dokument verknüpft oder Dokument nicht gefunden.",
|
||||||
|
"openInPaperless": "In paperless öffnen",
|
||||||
|
"configurePaperless": "Direkt-Öffnen konfigurieren, indem du die Paperless-URL in den Einstellungen hinterlegst.",
|
||||||
|
"metadata": "Metadaten",
|
||||||
|
"id": "ID",
|
||||||
|
"created": "Erstellt",
|
||||||
|
"updated": "Aktualisiert",
|
||||||
|
"monthsLabel_one": "{{count}} Monat",
|
||||||
|
"monthsLabel_other": "{{count}} Monate"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "Einstellungen",
|
||||||
|
"subtitle": "Systemstatus, Benachrichtigungen und Integrationen verwalten.",
|
||||||
|
"systemStatus": "Systemstatus",
|
||||||
|
"apiStatus": "API-Erreichbarkeit",
|
||||||
|
"authStatus": "Authentifizierung",
|
||||||
|
"paperlessStatus": "Paperless-Integration",
|
||||||
|
"mailStatus": "Mail-Benachrichtigungen",
|
||||||
|
"ntfyStatus": "ntfy Push",
|
||||||
|
"apiOk": "API antwortet korrekt",
|
||||||
|
"apiError": "Keine Antwort erhalten",
|
||||||
|
"authActive": "Login per Token ist aktiv.",
|
||||||
|
"authInactive": "Kein Login erforderlich – bitte nur im geschützten Netz betreiben.",
|
||||||
|
"paperlessActive": "Aktiv ({{url}})",
|
||||||
|
"paperlessInactive": "Nicht konfiguriert",
|
||||||
|
"mailActive": "Aktiv",
|
||||||
|
"mailInactive": "Nicht konfiguriert",
|
||||||
|
"ntfyActive": "Aktiv",
|
||||||
|
"ntfyInactive": "Nicht konfiguriert",
|
||||||
|
"auth": "Authentifizierung",
|
||||||
|
"paperless": "Paperless",
|
||||||
|
"scheduler": "Fristen & Benachrichtigungen",
|
||||||
|
"mail": "E-Mail",
|
||||||
|
"ntfy": "ntfy Push",
|
||||||
|
"ical": "iCal-Abo",
|
||||||
|
"icalFeedUrl": "Feed-URL",
|
||||||
|
"paperlessApiUrl": "Paperless API URL",
|
||||||
|
"paperlessExternalUrl": "Paperless externe URL (für Direktlink)",
|
||||||
|
"paperlessExample": "https://paperless.example.com",
|
||||||
|
"paperlessToken": "Paperless Token",
|
||||||
|
"paperlessTokenNew": "Neuen Token hinterlegen",
|
||||||
|
"paperlessTokenPlaceholder": "Token eingeben",
|
||||||
|
"paperlessTokenKeep": "Behalten",
|
||||||
|
"paperlessTokenRemove": "Token löschen",
|
||||||
|
"paperlessTokenInfo": "Ein Token ist hinterlegt. Lasse das Feld leer, um ihn unverändert zu lassen.",
|
||||||
|
"paperlessSearch": "Suchen",
|
||||||
|
"paperlessNotConfigured": "Paperless ist nicht konfiguriert. Hinterlege URL & Token in den Einstellungen.",
|
||||||
|
"paperlessLinked": "Verknüpft mit: {{title}}",
|
||||||
|
"interval": "Prüfintervall (Minuten)",
|
||||||
|
"alert": "Warnung vor Deadline (Tage)",
|
||||||
|
"smtpServer": "SMTP-Server",
|
||||||
|
"smtpPort": "Port",
|
||||||
|
"smtpUsername": "Benutzername",
|
||||||
|
"smtpPassword": "Passwort",
|
||||||
|
"smtpPasswordNew": "Neues Passwort",
|
||||||
|
"smtpPasswordInfo": "Ein Passwort ist hinterlegt. Lasse das Feld leer, um es unverändert zu lassen.",
|
||||||
|
"smtpPasswordRemove": "Passwort löschen",
|
||||||
|
"tls": "TLS verwenden",
|
||||||
|
"mailFrom": "Absender",
|
||||||
|
"mailTo": "Empfänger",
|
||||||
|
"ntfyServer": "Server URL",
|
||||||
|
"ntfyTopic": "Topic",
|
||||||
|
"ntfyToken": "Token",
|
||||||
|
"ntfyTokenNew": "Neuer Token",
|
||||||
|
"ntfyTokenRemove": "Token löschen",
|
||||||
|
"ntfyPriority": "Priorität",
|
||||||
|
"authUsername": "Benutzername",
|
||||||
|
"authPassword": "Passwort",
|
||||||
|
"authPasswordInfo": "Ein Passwort ist hinterlegt. Lasse das Feld leer, um es unverändert zu lassen.",
|
||||||
|
"authPasswordRemove": "Passwort löschen",
|
||||||
|
"authHint": "Lässt du Benutzername oder Passwort leer, wird der Login deaktiviert.",
|
||||||
|
"authPasswordPlaceholder": "Neues Passwort setzen",
|
||||||
|
"icalDescription": "Abonniere die Kündigungsfristen in deinem Kalender. Bewahre das Token vertraulich auf.",
|
||||||
|
"icalTokenMissing": "Kein iCal-Token vorhanden.",
|
||||||
|
"icalRenew": "Token erneuern",
|
||||||
|
"icalTokenRenewed": "iCal-Token erneuert",
|
||||||
|
"copy": "In Zwischenablage kopiert",
|
||||||
|
"copyUnsupported": "Kopieren wird nicht unterstützt",
|
||||||
|
"saving": "Speichern…",
|
||||||
|
"save": "Änderungen speichern",
|
||||||
|
"noChanges": "Keine Änderungen erkannt",
|
||||||
|
"saved": "Einstellungen gespeichert",
|
||||||
|
"mailTest": "Testmail senden",
|
||||||
|
"ntfyTest": "Test senden",
|
||||||
|
"mailTestSuccess": "Testmail versendet",
|
||||||
|
"ntfyTestSuccess": "ntfy-Test gesendet",
|
||||||
|
"mailTestError": "Test fehlgeschlagen",
|
||||||
|
"ntfyTestError": "ntfy-Test fehlgeschlagen",
|
||||||
|
"mailConfigMissing": "E-Mail-Konfiguration unvollständig",
|
||||||
|
"ntfyConfigMissing": "ntfy-Konfiguration unvollständig",
|
||||||
|
"actionFailed": "Aktion fehlgeschlagen"
|
||||||
|
},
|
||||||
|
"paperlessDialog": {
|
||||||
|
"title": "Paperless-Dokument verknüpfen",
|
||||||
|
"searchPlaceholder": "Titel, Notizen, Tags…",
|
||||||
|
"minChars": "Bitte mindestens zwei Zeichen eingeben",
|
||||||
|
"searching": "Suche läuft…",
|
||||||
|
"noResults": "Keine Treffer gefunden.",
|
||||||
|
"error": "Suche fehlgeschlagen",
|
||||||
|
"correspondent": "Korrespondent",
|
||||||
|
"cancel": "Abbrechen"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "Anmeldung",
|
||||||
|
"welcome": "Willkommen zurück! Bitte melde dich an.",
|
||||||
|
"username": "Benutzername",
|
||||||
|
"password": "Passwort",
|
||||||
|
"submit": "Anmelden",
|
||||||
|
"checking": "Wird geprüft…",
|
||||||
|
"disabled": "Hinweis: Die API ist momentan ohne Login erreichbar. Du wirst automatisch weitergeleitet.",
|
||||||
|
"usernameRequired": "Benutzername erforderlich",
|
||||||
|
"passwordRequired": "Passwort erforderlich",
|
||||||
|
"error": "Login fehlgeschlagen"
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"loading": "Lade Daten…",
|
||||||
|
"deleteConfirm": "Vertrag \"{{title}}\" wirklich löschen?",
|
||||||
|
"deleteSuccess": "Vertrag gelöscht",
|
||||||
|
"deleteError": "Löschen fehlgeschlagen",
|
||||||
|
"signedOut": "Abgemeldet"
|
||||||
|
}
|
||||||
|
}
|
||||||
250
frontend/src/locales/en/common.json
Normal file
250
frontend/src/locales/en/common.json
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
{
|
||||||
|
"nav": {
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"contracts": "Contracts",
|
||||||
|
"calendar": "Calendar",
|
||||||
|
"settings": "Settings",
|
||||||
|
"logout": "Sign out"
|
||||||
|
},
|
||||||
|
"layout": {
|
||||||
|
"title": "Contracts Overview",
|
||||||
|
"language": "Language"
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"save": "Save",
|
||||||
|
"saving": "Saving…",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"delete": "Delete",
|
||||||
|
"search": "Search",
|
||||||
|
"test": "Send test",
|
||||||
|
"testMail": "Send test mail",
|
||||||
|
"testNtfy": "Send test",
|
||||||
|
"copy": "Copied to clipboard",
|
||||||
|
"copyUnsupported": "Copying not supported",
|
||||||
|
"copyFailed": "Copy failed"
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"title": "Dashboard",
|
||||||
|
"subtitle": "Keep an eye on all key contract metrics.",
|
||||||
|
"totalContracts": "Total contracts",
|
||||||
|
"activeContracts": "Active contracts",
|
||||||
|
"monthlySpend": "Monthly spend (total)",
|
||||||
|
"deadlineChartTitle": "Termination deadlines per month",
|
||||||
|
"noDeadlines": "No upcoming deadlines.",
|
||||||
|
"upcomingList": "Next termination deadlines",
|
||||||
|
"loading": "Loading data…",
|
||||||
|
"contractsError": "Unable to load contracts.",
|
||||||
|
"deadlinesError": "Unable to load deadlines.",
|
||||||
|
"totalContractsTrend": "+100% captured",
|
||||||
|
"monthlySpendTrend": "Budget under control"
|
||||||
|
},
|
||||||
|
"deadlineList": {
|
||||||
|
"none": "No upcoming deadlines",
|
||||||
|
"info": "You're all set – there are no termination deadlines currently due.",
|
||||||
|
"daysLabel_one": "{{count}} day",
|
||||||
|
"daysLabel_other": "{{count}} days",
|
||||||
|
"terminateBy": "Cancel by {{date}}",
|
||||||
|
"contractEnds": "Contract ends {{date}}"
|
||||||
|
},
|
||||||
|
"calendar": {
|
||||||
|
"title": "Calendar & Deadlines",
|
||||||
|
"subtitle": "Plan cancellations ahead and stay on top of renewals.",
|
||||||
|
"loading": "Loading deadlines…",
|
||||||
|
"none": "No deadlines within the next 12 months.",
|
||||||
|
"deadlineCount_one": "{{count}} deadline",
|
||||||
|
"deadlineCount_other": "{{count}} deadlines",
|
||||||
|
"unknownMonth": "Unknown"
|
||||||
|
},
|
||||||
|
"contracts": {
|
||||||
|
"title": "Contracts",
|
||||||
|
"subtitle": "Overview of all current and past contracts.",
|
||||||
|
"new": "New contract",
|
||||||
|
"searchPlaceholder": "e.g. provider, title, keyword",
|
||||||
|
"searchLabel": "Search",
|
||||||
|
"filterAll": "All categories",
|
||||||
|
"columns": {
|
||||||
|
"title": "Title",
|
||||||
|
"provider": "Provider",
|
||||||
|
"category": "Category",
|
||||||
|
"price": "Price",
|
||||||
|
"end": "End date",
|
||||||
|
"tags": "Tags",
|
||||||
|
"actions": "Actions"
|
||||||
|
},
|
||||||
|
"loading": "Loading contracts…",
|
||||||
|
"empty": "No contracts found.",
|
||||||
|
"deleteConfirm": "Do you really want to delete \"{{title}}\"?",
|
||||||
|
"details": "Show details",
|
||||||
|
"edit": "Edit",
|
||||||
|
"deleted": "Contract deleted",
|
||||||
|
"deleteError": "Failed to delete"
|
||||||
|
},
|
||||||
|
"contractForm": {
|
||||||
|
"createTitle": "Create contract",
|
||||||
|
"createSubtitle": "Capture all important contract details.",
|
||||||
|
"editSubtitle": "Edit \"{{title}}\".",
|
||||||
|
"fields": {
|
||||||
|
"title": "Title",
|
||||||
|
"provider": "Provider",
|
||||||
|
"category": "Category",
|
||||||
|
"paperlessId": "Paperless document ID",
|
||||||
|
"contractStart": "Contract start",
|
||||||
|
"contractEnd": "Contract end",
|
||||||
|
"terminationNotice": "Termination notice (days)",
|
||||||
|
"renewalPeriod": "Renewal period (months)",
|
||||||
|
"autoRenew": "Auto renewal",
|
||||||
|
"price": "Price",
|
||||||
|
"currency": "Currency",
|
||||||
|
"notes": "Notes",
|
||||||
|
"tags": "Tags (comma-separated)",
|
||||||
|
"searchButton": "Search"
|
||||||
|
},
|
||||||
|
"tagsPlaceholder": "e.g. energy, apartment",
|
||||||
|
"paperlessNotConfigured": "Paperless is not configured. Provide the API URL and token in settings.",
|
||||||
|
"paperlessLinked": "Linked to: {{title}}",
|
||||||
|
"saving": "Saving…",
|
||||||
|
"save": "Save",
|
||||||
|
"saved": "Contract \"{{title}}\" saved",
|
||||||
|
"loadError": "Invalid contract ID",
|
||||||
|
"loading": "Loading contract…",
|
||||||
|
"saveError": "Failed to save",
|
||||||
|
"invalidNumber": "Please enter a valid number"
|
||||||
|
},
|
||||||
|
"contractDetail": {
|
||||||
|
"edit": "Edit contract",
|
||||||
|
"details": "Contract details",
|
||||||
|
"start": "Contract start",
|
||||||
|
"end": "Contract end",
|
||||||
|
"notice": "Termination notice",
|
||||||
|
"renewal": "Renewal",
|
||||||
|
"price": "Price",
|
||||||
|
"category": "Category",
|
||||||
|
"notes": "Notes",
|
||||||
|
"tags": "Tags",
|
||||||
|
"noTags": "No tags assigned.",
|
||||||
|
"noNotes": "No notes",
|
||||||
|
"document": "Linked document",
|
||||||
|
"documentFallback": "Document",
|
||||||
|
"documentError": "Unable to load paperless document: {{error}}",
|
||||||
|
"documentMissing": "No document linked or not found.",
|
||||||
|
"openInPaperless": "Open in paperless",
|
||||||
|
"configurePaperless": "Configure the paperless URL in settings to enable direct links.",
|
||||||
|
"metadata": "Metadata",
|
||||||
|
"id": "ID",
|
||||||
|
"created": "Created",
|
||||||
|
"updated": "Updated",
|
||||||
|
"monthsLabel_one": "{{count}} month",
|
||||||
|
"monthsLabel_other": "{{count}} months"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "Settings",
|
||||||
|
"subtitle": "Manage system status, notifications, and integrations.",
|
||||||
|
"systemStatus": "System status",
|
||||||
|
"apiStatus": "API reachability",
|
||||||
|
"authStatus": "Authentication",
|
||||||
|
"paperlessStatus": "Paperless integration",
|
||||||
|
"mailStatus": "Mail notifications",
|
||||||
|
"ntfyStatus": "ntfy push",
|
||||||
|
"apiOk": "API is responding",
|
||||||
|
"apiError": "No response received",
|
||||||
|
"authActive": "Token-based login is active.",
|
||||||
|
"authInactive": "Login not required – only use on trusted networks.",
|
||||||
|
"paperlessActive": "Active ({{url}})",
|
||||||
|
"paperlessInactive": "Not configured",
|
||||||
|
"mailActive": "Active",
|
||||||
|
"mailInactive": "Not configured",
|
||||||
|
"ntfyActive": "Active",
|
||||||
|
"ntfyInactive": "Not configured",
|
||||||
|
"auth": "Authentication",
|
||||||
|
"paperless": "Paperless",
|
||||||
|
"scheduler": "Deadlines & notifications",
|
||||||
|
"mail": "E-mail",
|
||||||
|
"ntfy": "ntfy push",
|
||||||
|
"ical": "iCal subscription",
|
||||||
|
"icalFeedUrl": "Feed URL",
|
||||||
|
"paperlessApiUrl": "Paperless API URL",
|
||||||
|
"paperlessExternalUrl": "Paperless external URL (for direct link)",
|
||||||
|
"paperlessExample": "https://paperless.example.com",
|
||||||
|
"paperlessToken": "Paperless token",
|
||||||
|
"paperlessTokenNew": "Provide new token",
|
||||||
|
"paperlessTokenPlaceholder": "Enter token",
|
||||||
|
"paperlessTokenKeep": "Keep",
|
||||||
|
"paperlessTokenRemove": "Remove token",
|
||||||
|
"paperlessTokenInfo": "A token is stored. Leave empty to keep it.",
|
||||||
|
"paperlessSearch": "Search",
|
||||||
|
"paperlessNotConfigured": "Paperless is not configured. Provide URL & token in settings.",
|
||||||
|
"paperlessLinked": "Linked to: {{title}}",
|
||||||
|
"interval": "Check interval (minutes)",
|
||||||
|
"alert": "Warning before deadline (days)",
|
||||||
|
"smtpServer": "SMTP server",
|
||||||
|
"smtpPort": "Port",
|
||||||
|
"smtpUsername": "Username",
|
||||||
|
"smtpPassword": "Password",
|
||||||
|
"smtpPasswordNew": "New password",
|
||||||
|
"smtpPasswordInfo": "A password is stored. Leave empty to keep it.",
|
||||||
|
"smtpPasswordRemove": "Remove password",
|
||||||
|
"tls": "Use TLS",
|
||||||
|
"mailFrom": "Sender",
|
||||||
|
"mailTo": "Recipient",
|
||||||
|
"ntfyServer": "Server URL",
|
||||||
|
"ntfyTopic": "Topic",
|
||||||
|
"ntfyToken": "Token",
|
||||||
|
"ntfyTokenNew": "New token",
|
||||||
|
"ntfyTokenRemove": "Remove token",
|
||||||
|
"ntfyPriority": "Priority",
|
||||||
|
"authUsername": "Username",
|
||||||
|
"authPassword": "Password",
|
||||||
|
"authPasswordInfo": "A password is stored. Leave empty to keep it.",
|
||||||
|
"authPasswordRemove": "Remove password",
|
||||||
|
"authHint": "Leave username or password empty to disable login.",
|
||||||
|
"authPasswordPlaceholder": "Set new password",
|
||||||
|
"icalDescription": "Subscribe to deadlines in your calendar. Keep the token secret.",
|
||||||
|
"icalTokenMissing": "No iCal token available.",
|
||||||
|
"icalRenew": "Renew token",
|
||||||
|
"icalTokenRenewed": "iCal token refreshed",
|
||||||
|
"copy": "Copied to clipboard",
|
||||||
|
"copyUnsupported": "Copying not supported",
|
||||||
|
"saving": "Saving…",
|
||||||
|
"save": "Save changes",
|
||||||
|
"noChanges": "No changes detected",
|
||||||
|
"saved": "Settings saved",
|
||||||
|
"mailTest": "Send test mail",
|
||||||
|
"ntfyTest": "Send test",
|
||||||
|
"mailTestSuccess": "Test mail sent",
|
||||||
|
"ntfyTestSuccess": "ntfy test sent",
|
||||||
|
"mailTestError": "Test failed",
|
||||||
|
"ntfyTestError": "ntfy test failed",
|
||||||
|
"mailConfigMissing": "E-mail configuration incomplete",
|
||||||
|
"ntfyConfigMissing": "ntfy configuration incomplete",
|
||||||
|
"actionFailed": "Action failed"
|
||||||
|
},
|
||||||
|
"paperlessDialog": {
|
||||||
|
"title": "Link paperless document",
|
||||||
|
"searchPlaceholder": "Title, notes, tags…",
|
||||||
|
"minChars": "Please enter at least two characters",
|
||||||
|
"searching": "Searching…",
|
||||||
|
"noResults": "No results found.",
|
||||||
|
"error": "Search failed",
|
||||||
|
"correspondent": "Correspondent",
|
||||||
|
"cancel": "Cancel"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "Sign in",
|
||||||
|
"welcome": "Welcome back! Please sign in.",
|
||||||
|
"username": "Username",
|
||||||
|
"password": "Password",
|
||||||
|
"submit": "Sign in",
|
||||||
|
"checking": "Checking…",
|
||||||
|
"disabled": "Note: The API is currently accessible without authentication. You will be redirected automatically.",
|
||||||
|
"usernameRequired": "Username is required",
|
||||||
|
"passwordRequired": "Password is required",
|
||||||
|
"error": "Login failed"
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"loading": "Loading data…",
|
||||||
|
"deleteConfirm": "Do you really want to delete \"{{title}}\"?",
|
||||||
|
"deleteSuccess": "Contract deleted",
|
||||||
|
"deleteError": "Failed to delete",
|
||||||
|
"signedOut": "Signed out"
|
||||||
|
}
|
||||||
|
}
|
||||||
27
frontend/src/main.tsx
Normal file
27
frontend/src/main.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { CssBaseline, ThemeProvider } from "@mui/material";
|
||||||
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
|
||||||
|
import App from "./App";
|
||||||
|
import { AuthProvider } from "./contexts/AuthContext";
|
||||||
|
import { SnackbarProvider } from "./hooks/useSnackbar";
|
||||||
|
import { lightTheme } from "./theme";
|
||||||
|
import "./i18n";
|
||||||
|
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<AuthProvider>
|
||||||
|
<SnackbarProvider>
|
||||||
|
<ThemeProvider theme={lightTheme}>
|
||||||
|
<CssBaseline />
|
||||||
|
<App />
|
||||||
|
</ThemeProvider>
|
||||||
|
</SnackbarProvider>
|
||||||
|
</AuthProvider>
|
||||||
|
</QueryClientProvider>
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
147
frontend/src/routes/CalendarView.tsx
Normal file
147
frontend/src/routes/CalendarView.tsx
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
import EventIcon from "@mui/icons-material/Event";
|
||||||
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionDetails,
|
||||||
|
AccordionSummary,
|
||||||
|
Chip,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemText,
|
||||||
|
Paper,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { fetchUpcomingDeadlines } from "../api/contracts";
|
||||||
|
import PageHeader from "../components/PageHeader";
|
||||||
|
import { UpcomingDeadline } from "../types";
|
||||||
|
import { formatDate } from "../utils/date";
|
||||||
|
|
||||||
|
const UNKNOWN_MONTH_KEY = "__unknown__";
|
||||||
|
|
||||||
|
function groupByMonth(deadlines: UpcomingDeadline[], unknownKey: string) {
|
||||||
|
const groups = new Map<string, UpcomingDeadline[]>();
|
||||||
|
deadlines.forEach((deadline) => {
|
||||||
|
const month = deadline.terminationDeadline?.slice(0, 7) ?? unknownKey;
|
||||||
|
if (!groups.has(month)) {
|
||||||
|
groups.set(month, []);
|
||||||
|
}
|
||||||
|
groups.get(month)!.push(deadline);
|
||||||
|
});
|
||||||
|
return Array.from(groups.entries())
|
||||||
|
.sort(([a], [b]) => a.localeCompare(b))
|
||||||
|
.map(([month, items]) => ({
|
||||||
|
month,
|
||||||
|
items: items.sort((a, b) => (a.terminationDeadline ?? "").localeCompare(b.terminationDeadline ?? ""))
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function CalendarView() {
|
||||||
|
const { data, isLoading } = useQuery({
|
||||||
|
queryKey: ["deadlines", "calendar"],
|
||||||
|
queryFn: () => fetchUpcomingDeadlines(365)
|
||||||
|
});
|
||||||
|
|
||||||
|
const groups = useMemo(() => {
|
||||||
|
if (!data || !Array.isArray(data)) return [] as ReturnType<typeof groupByMonth>;
|
||||||
|
return groupByMonth(data, UNKNOWN_MONTH_KEY);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageHeader
|
||||||
|
title={t("calendar.title")}
|
||||||
|
subtitle={t("calendar.subtitle")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3 }}>
|
||||||
|
{isLoading ? (
|
||||||
|
<Typography sx={{ p: 3 }}>{t("calendar.loading")}</Typography>
|
||||||
|
) : groups.length === 0 ? (
|
||||||
|
<Typography sx={{ p: 3 }} color="text.secondary">
|
||||||
|
{t("calendar.none")}
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
groups.map(({ month, items }) => (
|
||||||
|
<Accordion key={month} defaultExpanded>
|
||||||
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
|
<Typography variant="subtitle1" fontWeight={600} display="flex" alignItems="center" gap={1}>
|
||||||
|
<EventIcon fontSize="small" />
|
||||||
|
{formatMonth(month, i18n.language, t("calendar.unknownMonth"))}
|
||||||
|
</Typography>
|
||||||
|
<Chip
|
||||||
|
label={t("calendar.deadlineCount", { count: items.length })}
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
sx={{ ml: 2 }}
|
||||||
|
/>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<List>
|
||||||
|
{items.map((deadline) => (
|
||||||
|
<ListItem
|
||||||
|
key={`${month}-${deadline.id}`}
|
||||||
|
disablePadding
|
||||||
|
secondaryAction={
|
||||||
|
deadline.daysUntilDeadline != null ? (
|
||||||
|
<Chip
|
||||||
|
label={t("deadlineList.daysLabel", { count: deadline.daysUntilDeadline })}
|
||||||
|
color={
|
||||||
|
deadline.daysUntilDeadline <= 7
|
||||||
|
? "error"
|
||||||
|
: deadline.daysUntilDeadline <= 21
|
||||||
|
? "warning"
|
||||||
|
: "default"
|
||||||
|
}
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemButton onClick={() => navigate(`/contracts/${deadline.id}`)}>
|
||||||
|
<ListItemText
|
||||||
|
primary={deadline.title}
|
||||||
|
secondary={
|
||||||
|
<>
|
||||||
|
{t("deadlineList.terminateBy", {
|
||||||
|
date: formatDate(deadline.terminationDeadline)
|
||||||
|
})}
|
||||||
|
{deadline.contractEndDate
|
||||||
|
? ` • ${t("deadlineList.contractEnds", {
|
||||||
|
date: formatDate(deadline.contractEndDate)
|
||||||
|
})}`
|
||||||
|
: ""}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
primaryTypographyProps={{ fontWeight: 600 }}
|
||||||
|
/>
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatMonth(month: string, locale: string, unknownLabel: string): string {
|
||||||
|
if (month === UNKNOWN_MONTH_KEY) return unknownLabel;
|
||||||
|
const [year, monthNumber] = month.split("-");
|
||||||
|
const date = new Date(Number(year), Number(monthNumber) - 1);
|
||||||
|
return new Intl.DateTimeFormat(locale.startsWith("de") ? "de-DE" : "en-US", {
|
||||||
|
month: "long",
|
||||||
|
year: "numeric"
|
||||||
|
}).format(date);
|
||||||
|
}
|
||||||
189
frontend/src/routes/ContractDetail.tsx
Normal file
189
frontend/src/routes/ContractDetail.tsx
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
import LaunchIcon from "@mui/icons-material/Launch";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Chip,
|
||||||
|
Divider,
|
||||||
|
Grid,
|
||||||
|
Paper,
|
||||||
|
Stack,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useParams, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { fetchContract, fetchPaperlessDocument } from "../api/contracts";
|
||||||
|
import { fetchServerConfig, ServerConfig } from "../api/config";
|
||||||
|
import PageHeader from "../components/PageHeader";
|
||||||
|
import { formatCurrency, formatDate } from "../utils/date";
|
||||||
|
|
||||||
|
export default function ContractDetail() {
|
||||||
|
const { contractId } = useParams<{ contractId: string }>();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const id = Number(contractId);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const { data: contract, isLoading } = useQuery({
|
||||||
|
queryKey: ["contracts", id],
|
||||||
|
queryFn: () => fetchContract(id),
|
||||||
|
enabled: Number.isFinite(id)
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: serverConfig } = useQuery<ServerConfig>({
|
||||||
|
queryKey: ["server-config"],
|
||||||
|
queryFn: fetchServerConfig
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: paperlessDoc,
|
||||||
|
error: paperlessError
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["contracts", id, "paperless"],
|
||||||
|
queryFn: () => fetchPaperlessDocument(id),
|
||||||
|
enabled: Number.isFinite(id)
|
||||||
|
});
|
||||||
|
|
||||||
|
const paperlessAppUrl = serverConfig?.paperlessExternalUrl ?? serverConfig?.paperlessBaseUrl ?? null;
|
||||||
|
const terminationValue =
|
||||||
|
contract?.terminationNoticeDays !== undefined && contract?.terminationNoticeDays !== null
|
||||||
|
? t("deadlineList.daysLabel", { count: contract.terminationNoticeDays })
|
||||||
|
: "–";
|
||||||
|
const renewalValue =
|
||||||
|
contract?.renewalPeriodMonths
|
||||||
|
? `${t("contractDetail.monthsLabel", { count: contract.renewalPeriodMonths })}${contract.autoRenew ? `, ${t("contractForm.fields.autoRenew")}` : ""}`
|
||||||
|
: contract?.autoRenew
|
||||||
|
? t("contractForm.fields.autoRenew")
|
||||||
|
: "–";
|
||||||
|
const notesValue = contract?.notes ?? t("contractDetail.noNotes");
|
||||||
|
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
return <Typography>{t("contractForm.loadError")}</Typography>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading || !contract) {
|
||||||
|
return <Typography>{t("contractForm.loading")}</Typography>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageHeader
|
||||||
|
title={contract.title}
|
||||||
|
subtitle={contract.provider ?? ""}
|
||||||
|
action={
|
||||||
|
<Button variant="contained" onClick={() => navigate(`/contracts/${contract.id}/edit`)}>
|
||||||
|
{t("contractDetail.edit")}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid container spacing={3}>
|
||||||
|
<Grid item xs={12} md={8}>
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3 }}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("contractDetail.details")}
|
||||||
|
</Typography>
|
||||||
|
<Stack spacing={1.5}>
|
||||||
|
<Detail label={t("contractDetail.start")} value={formatDate(contract.contractStartDate)} />
|
||||||
|
<Detail label={t("contractDetail.end")} value={formatDate(contract.contractEndDate)} />
|
||||||
|
<Detail label={t("contractDetail.notice")} value={terminationValue} />
|
||||||
|
<Detail label={t("contractDetail.renewal")} value={renewalValue} />
|
||||||
|
<Detail label={t("contractDetail.price")} value={formatCurrency(contract.price, contract.currency ?? "EUR")} />
|
||||||
|
<Detail label={t("contractDetail.category")} value={contract.category ?? "–"} />
|
||||||
|
<Detail label={t("contractDetail.notes")} value={notesValue} />
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Divider sx={{ my: 3 }} />
|
||||||
|
|
||||||
|
<Typography variant="subtitle1" gutterBottom>
|
||||||
|
{t("contractDetail.tags")}
|
||||||
|
</Typography>
|
||||||
|
<Box display="flex" flexWrap="wrap" gap={1}>
|
||||||
|
{(contract.tags ?? []).length > 0 ? (
|
||||||
|
contract.tags!.map((tag) => <Chip key={tag} label={tag} />)
|
||||||
|
) : (
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("contractDetail.noTags")}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3, mb: 3 }}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("contractDetail.document")}
|
||||||
|
</Typography>
|
||||||
|
{paperlessError ? (
|
||||||
|
<Typography variant="body2" color="error">
|
||||||
|
{t("contractDetail.documentError", { error: (paperlessError as Error).message })}
|
||||||
|
</Typography>
|
||||||
|
) : paperlessDoc ? (
|
||||||
|
<Stack spacing={1}>
|
||||||
|
<Typography variant="subtitle2">
|
||||||
|
{String(paperlessDoc.title ?? t("contractDetail.documentFallback"))}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("contractDetail.created")}: {paperlessDoc.created ? formatDate(String(paperlessDoc.created)) : "–"}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("contractDetail.updated")}: {paperlessDoc.modified ? formatDate(String(paperlessDoc.modified)) : "–"}
|
||||||
|
</Typography>
|
||||||
|
{paperlessDoc.notes && (
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{String(paperlessDoc.notes)}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
startIcon={<LaunchIcon />}
|
||||||
|
sx={{ alignSelf: "flex-start", mt: 1 }}
|
||||||
|
disabled={!serverConfig || !paperlessAppUrl || !contract.paperlessDocumentId}
|
||||||
|
onClick={() => {
|
||||||
|
if (!paperlessAppUrl || !contract.paperlessDocumentId) return;
|
||||||
|
const url = `${paperlessAppUrl.replace(/\/$/, "")}/documents/${contract.paperlessDocumentId}`;
|
||||||
|
window.open(url, "_blank", "noopener");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("contractDetail.openInPaperless")}
|
||||||
|
</Button>
|
||||||
|
{!paperlessAppUrl && (
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
{t("contractDetail.configurePaperless")}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
) : (
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("contractDetail.documentMissing")}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3 }}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("contractDetail.metadata")}
|
||||||
|
</Typography>
|
||||||
|
<Stack spacing={1.5}>
|
||||||
|
<Detail label={t("contractDetail.id")} value={`#${contract.id}`} />
|
||||||
|
<Detail label={t("contractDetail.created")} value={formatDate(contract.createdAt)} />
|
||||||
|
<Detail label={t("contractDetail.updated")} value={formatDate(contract.updatedAt)} />
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Detail({ label, value }: { label: string; value: string }) {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="caption" color="text.secondary" textTransform="uppercase">
|
||||||
|
{label}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1">{value}</Typography>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
401
frontend/src/routes/ContractForm.tsx
Normal file
401
frontend/src/routes/ContractForm.tsx
Normal file
@@ -0,0 +1,401 @@
|
|||||||
|
import SaveIcon from "@mui/icons-material/Save";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
FormControlLabel,
|
||||||
|
Grid,
|
||||||
|
Paper,
|
||||||
|
Stack,
|
||||||
|
Switch,
|
||||||
|
TextField,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import {
|
||||||
|
createContract,
|
||||||
|
fetchContract,
|
||||||
|
fetchPaperlessDocument,
|
||||||
|
updateContract
|
||||||
|
} from "../api/contracts";
|
||||||
|
import { fetchServerConfig } from "../api/config";
|
||||||
|
import PaperlessSearchDialog from "../components/PaperlessSearchDialog";
|
||||||
|
import PageHeader from "../components/PageHeader";
|
||||||
|
import { useSnackbar } from "../hooks/useSnackbar";
|
||||||
|
import { ContractPayload, PaperlessDocument } from "../types";
|
||||||
|
|
||||||
|
const formSchema = z.object({
|
||||||
|
title: z.string().min(1, "Titel erforderlich"),
|
||||||
|
provider: z.string().optional(),
|
||||||
|
category: z.string().optional(),
|
||||||
|
paperlessDocumentId: z.string().optional(),
|
||||||
|
contractStartDate: z.string().optional(),
|
||||||
|
contractEndDate: z.string().optional(),
|
||||||
|
terminationNoticeDays: z.string().optional(),
|
||||||
|
renewalPeriodMonths: z.string().optional(),
|
||||||
|
autoRenew: z.boolean().optional(),
|
||||||
|
price: z.string().optional(),
|
||||||
|
currency: z.string().optional(),
|
||||||
|
notes: z.string().optional(),
|
||||||
|
tags: z.string().optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
type FormValues = z.infer<typeof formSchema>;
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
mode: "create" | "edit";
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseInteger(input?: string | null): number | null {
|
||||||
|
if (!input) return null;
|
||||||
|
const value = Number(input);
|
||||||
|
if (!Number.isFinite(value)) {
|
||||||
|
throw new Error("Invalid number");
|
||||||
|
}
|
||||||
|
return Math.round(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDecimal(input?: string | null): number | null {
|
||||||
|
if (!input) return null;
|
||||||
|
const normalized = input.replace(",", ".").trim();
|
||||||
|
const value = Number(normalized);
|
||||||
|
if (!Number.isFinite(value)) {
|
||||||
|
throw new Error("Invalid number");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseTags(input?: string | null): string[] {
|
||||||
|
if (!input) return [];
|
||||||
|
return input
|
||||||
|
.split(",")
|
||||||
|
.map((tag) => tag.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ContractForm({ mode }: Props) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { contractId } = useParams<{ contractId: string }>();
|
||||||
|
const id = contractId ? Number(contractId) : null;
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const { showMessage } = useSnackbar();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
reset,
|
||||||
|
setValue,
|
||||||
|
watch
|
||||||
|
} = useForm<FormValues>({
|
||||||
|
resolver: zodResolver(formSchema),
|
||||||
|
defaultValues: {
|
||||||
|
title: "",
|
||||||
|
provider: "",
|
||||||
|
category: "",
|
||||||
|
contractStartDate: "",
|
||||||
|
contractEndDate: "",
|
||||||
|
terminationNoticeDays: "",
|
||||||
|
renewalPeriodMonths: "",
|
||||||
|
autoRenew: false,
|
||||||
|
price: "",
|
||||||
|
currency: "EUR",
|
||||||
|
notes: "",
|
||||||
|
tags: ""
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: contract, isLoading } = useQuery({
|
||||||
|
queryKey: ["contracts", id],
|
||||||
|
queryFn: () => fetchContract(id ?? 0),
|
||||||
|
enabled: mode === "edit" && id !== null
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: serverConfig } = useQuery({
|
||||||
|
queryKey: ["server-config"],
|
||||||
|
queryFn: fetchServerConfig
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: linkedPaperlessDoc } = useQuery({
|
||||||
|
queryKey: ["contracts", id, "paperless"],
|
||||||
|
queryFn: () => fetchPaperlessDocument(id ?? 0),
|
||||||
|
enabled: mode === "edit" && id !== null
|
||||||
|
});
|
||||||
|
|
||||||
|
const [searchDialogOpen, setSearchDialogOpen] = useState(false);
|
||||||
|
const [selectedDocument, setSelectedDocument] = useState<PaperlessDocument | null>(null);
|
||||||
|
const paperlessDocumentId = watch("paperlessDocumentId");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (mode === "edit" && contract) {
|
||||||
|
reset({
|
||||||
|
title: contract.title,
|
||||||
|
provider: contract.provider ?? "",
|
||||||
|
category: contract.category ?? "",
|
||||||
|
contractStartDate: contract.contractStartDate ?? "",
|
||||||
|
contractEndDate: contract.contractEndDate ?? "",
|
||||||
|
terminationNoticeDays: contract.terminationNoticeDays
|
||||||
|
? String(contract.terminationNoticeDays)
|
||||||
|
: "",
|
||||||
|
renewalPeriodMonths: contract.renewalPeriodMonths
|
||||||
|
? String(contract.renewalPeriodMonths)
|
||||||
|
: "",
|
||||||
|
autoRenew: contract.autoRenew ?? false,
|
||||||
|
price: contract.price ? String(contract.price) : "",
|
||||||
|
currency: contract.currency ?? "EUR",
|
||||||
|
notes: contract.notes ?? "",
|
||||||
|
paperlessDocumentId: contract.paperlessDocumentId
|
||||||
|
? String(contract.paperlessDocumentId)
|
||||||
|
: "",
|
||||||
|
tags: contract.tags?.join(", ") ?? ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [contract, mode, reset]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (linkedPaperlessDoc) {
|
||||||
|
setSelectedDocument(linkedPaperlessDoc);
|
||||||
|
}
|
||||||
|
}, [linkedPaperlessDoc]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!paperlessDocumentId) {
|
||||||
|
setSelectedDocument(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedDocument?.id && String(selectedDocument.id) === paperlessDocumentId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedDocument && String(selectedDocument.id ?? "") !== paperlessDocumentId) {
|
||||||
|
setSelectedDocument(null);
|
||||||
|
}
|
||||||
|
}, [paperlessDocumentId, selectedDocument]);
|
||||||
|
|
||||||
|
const mutation = useMutation({
|
||||||
|
mutationFn: async (values: FormValues) => {
|
||||||
|
const payload: ContractPayload = {
|
||||||
|
title: values.title,
|
||||||
|
provider: values.provider?.trim() || null,
|
||||||
|
category: values.category?.trim() || null,
|
||||||
|
contractStartDate: values.contractStartDate || null,
|
||||||
|
contractEndDate: values.contractEndDate || null,
|
||||||
|
terminationNoticeDays: parseInteger(values.terminationNoticeDays ?? undefined),
|
||||||
|
renewalPeriodMonths: parseInteger(values.renewalPeriodMonths ?? undefined),
|
||||||
|
autoRenew: values.autoRenew ?? false,
|
||||||
|
price: parseDecimal(values.price ?? undefined),
|
||||||
|
currency: values.currency?.trim() || "EUR",
|
||||||
|
notes: values.notes?.trim() || null,
|
||||||
|
paperlessDocumentId: parseInteger(values.paperlessDocumentId ?? undefined),
|
||||||
|
tags: parseTags(values.tags ?? "")
|
||||||
|
};
|
||||||
|
|
||||||
|
if (mode === "create") {
|
||||||
|
return createContract(payload);
|
||||||
|
}
|
||||||
|
if (!id) {
|
||||||
|
throw new Error("Invalid contract ID");
|
||||||
|
}
|
||||||
|
return updateContract(id, payload);
|
||||||
|
},
|
||||||
|
onSuccess: (updated) => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["contracts"] });
|
||||||
|
showMessage(t("contractForm.saved", { title: updated.title }), "success");
|
||||||
|
navigate(`/contracts/${updated.id}`);
|
||||||
|
},
|
||||||
|
onError: (error: Error) => {
|
||||||
|
const message = error.message === "Invalid number" ? t("contractForm.invalidNumber") : error.message ?? t("contractForm.saveError");
|
||||||
|
showMessage(message, "error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mode === "edit" && (isLoading || !contract)) {
|
||||||
|
return <Typography>{t("contractForm.loading")}</Typography>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageHeader
|
||||||
|
title={mode === "create" ? t("contractForm.createTitle") : t("contractDetail.edit")}
|
||||||
|
subtitle={
|
||||||
|
mode === "create"
|
||||||
|
? t("contractForm.createSubtitle")
|
||||||
|
: t("contractForm.editSubtitle", { title: contract?.title ?? "" })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Paper variant="outlined" sx={{ p: 3, borderRadius: 3 }}>
|
||||||
|
<Box
|
||||||
|
component="form"
|
||||||
|
onSubmit={handleSubmit((values) => mutation.mutate(values))}
|
||||||
|
noValidate
|
||||||
|
>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.title")}
|
||||||
|
fullWidth
|
||||||
|
required
|
||||||
|
{...register("title")}
|
||||||
|
error={Boolean(errors.title)}
|
||||||
|
helperText={errors.title?.message}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<TextField label={t("contractForm.fields.provider")} fullWidth {...register("provider")} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<TextField label={t("contractForm.fields.category")} fullWidth {...register("category")} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<Stack direction={{ xs: "column", sm: "row" }} spacing={1} alignItems="flex-start">
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.paperlessId")}
|
||||||
|
fullWidth
|
||||||
|
{...register("paperlessDocumentId")}
|
||||||
|
error={Boolean(errors.paperlessDocumentId)}
|
||||||
|
helperText={errors.paperlessDocumentId?.message}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => setSearchDialogOpen(true)}
|
||||||
|
disabled={!serverConfig?.paperlessConfigured}
|
||||||
|
>
|
||||||
|
{t("contractForm.fields.searchButton")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
{!serverConfig?.paperlessConfigured && (
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
{t("contractForm.paperlessNotConfigured")}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{selectedDocument && (
|
||||||
|
<Typography variant="caption" color="text.secondary" sx={{ display: "block", mt: 1 }}>
|
||||||
|
{t("contractForm.paperlessLinked", {
|
||||||
|
title: selectedDocument.title ?? `#${selectedDocument.id}`
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.contractStart")}
|
||||||
|
type="date"
|
||||||
|
fullWidth
|
||||||
|
InputLabelProps={{ shrink: true }}
|
||||||
|
{...register("contractStartDate")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.contractEnd")}
|
||||||
|
type="date"
|
||||||
|
fullWidth
|
||||||
|
InputLabelProps={{ shrink: true }}
|
||||||
|
{...register("contractEndDate")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.terminationNotice")}
|
||||||
|
fullWidth
|
||||||
|
{...register("terminationNoticeDays")}
|
||||||
|
error={Boolean(errors.terminationNoticeDays)}
|
||||||
|
helperText={errors.terminationNoticeDays?.message}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.renewalPeriod")}
|
||||||
|
fullWidth
|
||||||
|
{...register("renewalPeriodMonths")}
|
||||||
|
error={Boolean(errors.renewalPeriodMonths)}
|
||||||
|
helperText={errors.renewalPeriodMonths?.message}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="autoRenew"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormControlLabel
|
||||||
|
label={t("contractForm.fields.autoRenew")}
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={field.value ?? false}
|
||||||
|
onChange={(event) => field.onChange(event.target.checked)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.price")}
|
||||||
|
fullWidth
|
||||||
|
{...register("price")}
|
||||||
|
error={Boolean(errors.price)}
|
||||||
|
helperText={errors.price?.message}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.currency")}
|
||||||
|
fullWidth
|
||||||
|
{...register("currency")}
|
||||||
|
error={Boolean(errors.currency)}
|
||||||
|
helperText={errors.currency?.message}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.notes")}
|
||||||
|
fullWidth
|
||||||
|
multiline
|
||||||
|
minRows={3}
|
||||||
|
{...register("notes")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<TextField
|
||||||
|
label={t("contractForm.fields.tags")}
|
||||||
|
fullWidth
|
||||||
|
placeholder={t("contractForm.tagsPlaceholder")}
|
||||||
|
{...register("tags")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Box display="flex" justifyContent="flex-end" mt={4}>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="contained"
|
||||||
|
startIcon={<SaveIcon />}
|
||||||
|
disabled={mutation.isPending}
|
||||||
|
>
|
||||||
|
{mutation.isPending ? "Speichere..." : "Speichern"}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
<PaperlessSearchDialog
|
||||||
|
open={searchDialogOpen}
|
||||||
|
onClose={() => setSearchDialogOpen(false)}
|
||||||
|
onSelect={(doc) => {
|
||||||
|
const idValue = doc.id ? String(doc.id) : "";
|
||||||
|
setValue("paperlessDocumentId", idValue, { shouldDirty: true });
|
||||||
|
setSelectedDocument(doc);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
219
frontend/src/routes/ContractsList.tsx
Normal file
219
frontend/src/routes/ContractsList.tsx
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
|
import DeleteIcon from "@mui/icons-material/Delete";
|
||||||
|
import EditIcon from "@mui/icons-material/Edit";
|
||||||
|
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Chip,
|
||||||
|
IconButton,
|
||||||
|
InputAdornment,
|
||||||
|
MenuItem,
|
||||||
|
Paper,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TextField,
|
||||||
|
Tooltip,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { useMemo, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { fetchContracts, removeContract } from "../api/contracts";
|
||||||
|
import PageHeader from "../components/PageHeader";
|
||||||
|
import { useSnackbar } from "../hooks/useSnackbar";
|
||||||
|
import { Contract } from "../types";
|
||||||
|
import { formatCurrency, formatDate } from "../utils/date";
|
||||||
|
|
||||||
|
export default function ContractsList() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const { showMessage } = useSnackbar();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: contracts,
|
||||||
|
isLoading,
|
||||||
|
isError
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["contracts", "list"],
|
||||||
|
queryFn: () => fetchContracts({ limit: 500 })
|
||||||
|
});
|
||||||
|
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
const [category, setCategory] = useState<string>("all");
|
||||||
|
|
||||||
|
const categories = useMemo(() => {
|
||||||
|
const values = new Set<string>();
|
||||||
|
contracts?.forEach((contract) => {
|
||||||
|
if (contract.category) values.add(contract.category);
|
||||||
|
});
|
||||||
|
return Array.from(values).sort();
|
||||||
|
}, [contracts]);
|
||||||
|
|
||||||
|
const normalizedContracts = useMemo(() => {
|
||||||
|
if (!contracts) return [] as Contract[];
|
||||||
|
if (Array.isArray(contracts)) return contracts as Contract[];
|
||||||
|
if (typeof (contracts as any).results === "object" && Array.isArray((contracts as any).results)) {
|
||||||
|
return (contracts as any).results as Contract[];
|
||||||
|
}
|
||||||
|
return [] as Contract[];
|
||||||
|
}, [contracts]);
|
||||||
|
|
||||||
|
const filtered = useMemo(() => {
|
||||||
|
return normalizedContracts.filter((contract) => {
|
||||||
|
const searchMatch =
|
||||||
|
!search ||
|
||||||
|
[contract.title, contract.provider, contract.notes, contract.category]
|
||||||
|
.filter(Boolean)
|
||||||
|
.some((field) => field!.toLowerCase().includes(search.toLowerCase()));
|
||||||
|
|
||||||
|
const categoryMatch = category === "all" || contract.category === category;
|
||||||
|
return searchMatch && categoryMatch;
|
||||||
|
});
|
||||||
|
}, [contracts, search, category]);
|
||||||
|
|
||||||
|
const deleteMutation = useMutation({
|
||||||
|
mutationFn: (contractId: number) => removeContract(contractId),
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["contracts"] });
|
||||||
|
showMessage(t("contracts.deleted"), "success");
|
||||||
|
},
|
||||||
|
onError: (error: Error) => showMessage(error.message ?? t("contracts.deleteError"), "error")
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleDelete = (contract: Contract) => {
|
||||||
|
if (window.confirm(t("contracts.deleteConfirm", { title: contract.title }))) {
|
||||||
|
deleteMutation.mutate(contract.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageHeader
|
||||||
|
title={t("contracts.title")}
|
||||||
|
subtitle={t("contracts.subtitle")}
|
||||||
|
action={
|
||||||
|
<Button variant="contained" startIcon={<AddIcon />} onClick={() => navigate("/contracts/new")}>
|
||||||
|
{t("contracts.new")}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Paper variant="outlined" sx={{ p: 2.5, borderRadius: 3 }}>
|
||||||
|
<Box display="flex" flexWrap="wrap" gap={2} mb={2}>
|
||||||
|
<TextField
|
||||||
|
label={t("contracts.searchLabel")}
|
||||||
|
placeholder={t("contracts.searchPlaceholder")}
|
||||||
|
value={search}
|
||||||
|
onChange={(event) => setSearch(event.target.value)}
|
||||||
|
sx={{ flex: { xs: "1 1 100%", md: "1 1 320px" } }}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: <InputAdornment position="start">🔍</InputAdornment>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
select
|
||||||
|
label={t("contracts.columns.category")}
|
||||||
|
value={category}
|
||||||
|
onChange={(event) => setCategory(event.target.value)}
|
||||||
|
sx={{ width: 200 }}
|
||||||
|
>
|
||||||
|
<MenuItem value="all">{t("contracts.filterAll")}</MenuItem>
|
||||||
|
{categories.map((item) => (
|
||||||
|
<MenuItem key={item} value={item}>
|
||||||
|
{item}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>{t("contracts.columns.title")}</TableCell>
|
||||||
|
<TableCell>{t("contracts.columns.provider")}</TableCell>
|
||||||
|
<TableCell>{t("contracts.columns.category")}</TableCell>
|
||||||
|
<TableCell>{t("contracts.columns.price")}</TableCell>
|
||||||
|
<TableCell>{t("contracts.columns.end")}</TableCell>
|
||||||
|
<TableCell>{t("contracts.columns.tags")}</TableCell>
|
||||||
|
<TableCell align="right">{t("contracts.columns.actions")}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{isLoading && (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={7}>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("contracts.loading")}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
{isError && (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={7}>
|
||||||
|
<Typography variant="body2" color="error">
|
||||||
|
{t("dashboard.contractsError")}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
{!isLoading && !isError && filtered.length === 0 && (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={7}>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("contracts.empty")}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
{filtered.map((contract) => (
|
||||||
|
<TableRow key={contract.id} hover>
|
||||||
|
<TableCell>
|
||||||
|
<Typography fontWeight={600}>{contract.title}</Typography>
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
#{contract.id}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{contract.provider ?? "–"}</TableCell>
|
||||||
|
<TableCell>{contract.category ?? "–"}</TableCell>
|
||||||
|
<TableCell>{formatCurrency(contract.price, contract.currency ?? "EUR")}</TableCell>
|
||||||
|
<TableCell>{formatDate(contract.contractEndDate)}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Box display="flex" flexWrap="wrap" gap={1}>
|
||||||
|
{(contract.tags ?? []).map((tag) => (
|
||||||
|
<Chip key={tag} label={tag} size="small" />
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right">
|
||||||
|
<Tooltip title={t("contracts.details")}>
|
||||||
|
<IconButton onClick={() => navigate(`/contracts/${contract.id}`)}>
|
||||||
|
<VisibilityIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title={t("contracts.edit")}>
|
||||||
|
<IconButton onClick={() => navigate(`/contracts/${contract.id}/edit`)}>
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title={t("actions.delete")}>
|
||||||
|
<IconButton color="error" onClick={() => handleDelete(contract)}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
197
frontend/src/routes/Dashboard.tsx
Normal file
197
frontend/src/routes/Dashboard.tsx
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
import { Grid, Paper, Skeleton, Stack, Typography } from "@mui/material";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { ResponsiveContainer, BarChart, Bar, Tooltip, XAxis, YAxis } from "recharts";
|
||||||
|
|
||||||
|
import { fetchContracts, fetchUpcomingDeadlines } from "../api/contracts";
|
||||||
|
import DeadlineList from "../components/DeadlineList";
|
||||||
|
import PageHeader from "../components/PageHeader";
|
||||||
|
import StatCard from "../components/StatCard";
|
||||||
|
import { Contract, UpcomingDeadline } from "../types";
|
||||||
|
import { formatCurrency } from "../utils/date";
|
||||||
|
|
||||||
|
function buildDeadlineSeries(deadlines: UpcomingDeadline[]) {
|
||||||
|
const grouped = new Map<string, number>();
|
||||||
|
deadlines.forEach((deadline) => {
|
||||||
|
if (!deadline.terminationDeadline) return;
|
||||||
|
const month = deadline.terminationDeadline.slice(0, 7);
|
||||||
|
grouped.set(month, (grouped.get(month) ?? 0) + 1);
|
||||||
|
});
|
||||||
|
return Array.from(grouped.entries())
|
||||||
|
.sort(([a], [b]) => a.localeCompare(b))
|
||||||
|
.map(([month, count]) => ({ month, count }));
|
||||||
|
}
|
||||||
|
|
||||||
|
function countActiveContracts(contracts: Contract[]): number {
|
||||||
|
const now = new Date();
|
||||||
|
return contracts.filter((contract) => {
|
||||||
|
if (!contract.contractEndDate) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const end = new Date(`${contract.contractEndDate}T00:00:00Z`);
|
||||||
|
return end >= now;
|
||||||
|
}).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcMonthlySpend(contracts: Contract[]): number {
|
||||||
|
return contracts.reduce((total, contract) => {
|
||||||
|
if (!contract.price) return total;
|
||||||
|
return total + contract.price;
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Dashboard() {
|
||||||
|
const {
|
||||||
|
data: contracts,
|
||||||
|
isLoading: loadingContracts,
|
||||||
|
isError: errorContracts
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["contracts", "dashboard"],
|
||||||
|
queryFn: () => fetchContracts({ limit: 200 })
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: deadlines,
|
||||||
|
isLoading: loadingDeadlines,
|
||||||
|
isError: errorDeadlines
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["deadlines", 60],
|
||||||
|
queryFn: () => fetchUpcomingDeadlines(60)
|
||||||
|
});
|
||||||
|
|
||||||
|
const normalizedContracts = useMemo(() => {
|
||||||
|
if (!contracts) return [] as Contract[];
|
||||||
|
if (Array.isArray(contracts)) return contracts as Contract[];
|
||||||
|
if (typeof (contracts as any).results === "object" && Array.isArray((contracts as any).results)) {
|
||||||
|
return (contracts as any).results as Contract[];
|
||||||
|
}
|
||||||
|
return [] as Contract[];
|
||||||
|
}, [contracts]);
|
||||||
|
|
||||||
|
const normalizedDeadlines = useMemo(() => {
|
||||||
|
if (!deadlines) return [] as UpcomingDeadline[];
|
||||||
|
if (Array.isArray(deadlines)) return deadlines as UpcomingDeadline[];
|
||||||
|
if (typeof (deadlines as any).results === "object" && Array.isArray((deadlines as any).results)) {
|
||||||
|
return (deadlines as any).results as UpcomingDeadline[];
|
||||||
|
}
|
||||||
|
return [] as UpcomingDeadline[];
|
||||||
|
}, [deadlines]);
|
||||||
|
|
||||||
|
const activeContracts = useMemo(() => countActiveContracts(normalizedContracts), [normalizedContracts]);
|
||||||
|
const monthlySpend = useMemo(() => calcMonthlySpend(normalizedContracts), [normalizedContracts]);
|
||||||
|
const deadlineSeries = useMemo(() => buildDeadlineSeries(normalizedDeadlines), [normalizedDeadlines]);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageHeader
|
||||||
|
title={t("dashboard.title")}
|
||||||
|
subtitle={t("dashboard.subtitle")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid container spacing={3}>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
{loadingContracts ? (
|
||||||
|
<Skeleton variant="rectangular" height={140} sx={{ borderRadius: 3 }} />
|
||||||
|
) : errorContracts ? (
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3 }}>
|
||||||
|
<Typography variant="body2" color="error">
|
||||||
|
{t("dashboard.contractsError")}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
) : (
|
||||||
|
<StatCard
|
||||||
|
title={t("dashboard.totalContracts")}
|
||||||
|
value={contracts?.length ?? 0}
|
||||||
|
trend={contracts && contracts.length > 0 ? "up" : undefined}
|
||||||
|
trendLabel={contracts && contracts.length > 0 ? t("dashboard.totalContractsTrend") : undefined}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
{loadingContracts ? (
|
||||||
|
<Skeleton variant="rectangular" height={140} sx={{ borderRadius: 3 }} />
|
||||||
|
) : errorContracts ? (
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3 }}>
|
||||||
|
<Typography variant="body2" color="error">
|
||||||
|
{t("dashboard.contractsError")}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
) : (
|
||||||
|
<StatCard title={t("dashboard.activeContracts") } value={activeContracts} />
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={4}>
|
||||||
|
{loadingContracts ? (
|
||||||
|
<Skeleton variant="rectangular" height={140} sx={{ borderRadius: 3 }} />
|
||||||
|
) : errorContracts ? (
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3 }}>
|
||||||
|
<Typography variant="body2" color="error">
|
||||||
|
{t("dashboard.contractsError")}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
) : (
|
||||||
|
<StatCard
|
||||||
|
title={t("dashboard.monthlySpend")}
|
||||||
|
value={formatCurrency(monthlySpend)}
|
||||||
|
trend={monthlySpend > 0 ? "up" : undefined}
|
||||||
|
trendLabel={monthlySpend > 0 ? t("dashboard.monthlySpendTrend") : undefined}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid container spacing={3} mt={1}>
|
||||||
|
<Grid item xs={12} md={7}>
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3, minHeight: 320 }}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("dashboard.deadlineChartTitle")}
|
||||||
|
</Typography>
|
||||||
|
{loadingDeadlines ? (
|
||||||
|
<Stack spacing={2} mt={2}>
|
||||||
|
<Skeleton variant="rectangular" height={32} />
|
||||||
|
<Skeleton variant="rectangular" height={32} />
|
||||||
|
<Skeleton variant="rectangular" height={32} />
|
||||||
|
</Stack>
|
||||||
|
) : errorDeadlines ? (
|
||||||
|
<Typography variant="body2" color="error">
|
||||||
|
{t("dashboard.deadlinesError")}
|
||||||
|
</Typography>
|
||||||
|
) : deadlines && deadlines.length > 0 ? (
|
||||||
|
<ResponsiveContainer width="100%" height={260}>
|
||||||
|
<BarChart data={deadlineSeries}>
|
||||||
|
<XAxis dataKey="month" />
|
||||||
|
<YAxis allowDecimals={false} />
|
||||||
|
<Tooltip />
|
||||||
|
<Bar dataKey="count" fill="#556cd6" radius={[8, 8, 0, 0]} />
|
||||||
|
</BarChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
) : (
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("dashboard.noDeadlines")}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={5}>
|
||||||
|
{loadingDeadlines ? (
|
||||||
|
<Stack spacing={2} mt={1}>
|
||||||
|
<Skeleton variant="rectangular" height={88} />
|
||||||
|
<Skeleton variant="rectangular" height={88} />
|
||||||
|
<Skeleton variant="rectangular" height={88} />
|
||||||
|
</Stack>
|
||||||
|
) : errorDeadlines ? (
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3 }}>
|
||||||
|
<Typography variant="body2" color="error">
|
||||||
|
{t("dashboard.deadlinesError")}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
) : (
|
||||||
|
<DeadlineList deadlines={deadlines ?? []} />
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
131
frontend/src/routes/Login.tsx
Normal file
131
frontend/src/routes/Login.tsx
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
Avatar,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Container,
|
||||||
|
Paper,
|
||||||
|
TextField,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useEffect, useMemo } from "react";
|
||||||
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import { useAuth } from "../contexts/AuthContext";
|
||||||
|
|
||||||
|
type FormValues = {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function LoginPage() {
|
||||||
|
const { login, authEnabled, isAuthenticated } = useAuth();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const schema = useMemo(
|
||||||
|
() =>
|
||||||
|
z.object({
|
||||||
|
username: z.string().min(1, t("login.usernameRequired")),
|
||||||
|
password: z.string().min(1, t("login.passwordRequired"))
|
||||||
|
}),
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleSubmit,
|
||||||
|
register,
|
||||||
|
formState: { errors }
|
||||||
|
} = useForm<FormValues>({
|
||||||
|
resolver: zodResolver(schema)
|
||||||
|
});
|
||||||
|
|
||||||
|
const mutation = useMutation({
|
||||||
|
mutationFn: ({ username, password }: FormValues) => login(username, password),
|
||||||
|
onSuccess: () => {
|
||||||
|
const redirectTo = (location.state as { from?: Location })?.from?.pathname ?? "/dashboard";
|
||||||
|
navigate(redirectTo, { replace: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!authEnabled || isAuthenticated) {
|
||||||
|
navigate("/dashboard", { replace: true });
|
||||||
|
}
|
||||||
|
}, [authEnabled, isAuthenticated, navigate]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container component="main" maxWidth="xs">
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
marginTop: 12,
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Paper elevation={3} sx={{ p: 4, borderRadius: 4, width: "100%" }}>
|
||||||
|
<Box display="flex" flexDirection="column" alignItems="center" mb={2}>
|
||||||
|
<Avatar sx={{ m: 1, bgcolor: "primary.main" }}>
|
||||||
|
<LockOutlinedIcon />
|
||||||
|
</Avatar>
|
||||||
|
<Typography component="h1" variant="h5" fontWeight={600}>
|
||||||
|
{t("login.title")}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("login.welcome")}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{mutation.isError && (
|
||||||
|
<Alert severity="error" sx={{ mb: 2 }}>
|
||||||
|
{(mutation.error as Error).message || t("login.error")}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Box component="form" onSubmit={handleSubmit((values) => mutation.mutate(values))}>
|
||||||
|
<TextField
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
label={t("login.username")}
|
||||||
|
autoComplete="username"
|
||||||
|
autoFocus
|
||||||
|
{...register("username")}
|
||||||
|
error={Boolean(errors.username)}
|
||||||
|
helperText={errors.username?.message}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
margin="normal"
|
||||||
|
fullWidth
|
||||||
|
label={t("login.password")}
|
||||||
|
type="password"
|
||||||
|
autoComplete="current-password"
|
||||||
|
{...register("password")}
|
||||||
|
error={Boolean(errors.password)}
|
||||||
|
helperText={errors.password?.message}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
fullWidth
|
||||||
|
variant="contained"
|
||||||
|
sx={{ mt: 3, mb: 2 }}
|
||||||
|
disabled={mutation.isPending}
|
||||||
|
>
|
||||||
|
{mutation.isPending ? t("login.checking") : t("login.submit")}
|
||||||
|
</Button>
|
||||||
|
{!authEnabled && (
|
||||||
|
<Alert severity="info">{t("login.disabled")}</Alert>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
747
frontend/src/routes/Settings.tsx
Normal file
747
frontend/src/routes/Settings.tsx
Normal file
@@ -0,0 +1,747 @@
|
|||||||
|
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
||||||
|
import RefreshIcon from "@mui/icons-material/Refresh";
|
||||||
|
import SecurityIcon from "@mui/icons-material/Security";
|
||||||
|
import SettingsApplicationsIcon from "@mui/icons-material/SettingsApplications";
|
||||||
|
import StorageIcon from "@mui/icons-material/Storage";
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
Avatar,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CircularProgress,
|
||||||
|
FormControlLabel,
|
||||||
|
Grid,
|
||||||
|
IconButton,
|
||||||
|
InputAdornment,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemAvatar,
|
||||||
|
ListItemText,
|
||||||
|
Paper,
|
||||||
|
Stack,
|
||||||
|
Switch,
|
||||||
|
TextField,
|
||||||
|
Typography
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
import {
|
||||||
|
fetchServerConfig,
|
||||||
|
fetchSettings,
|
||||||
|
resetIcalSecret,
|
||||||
|
triggerMailTest,
|
||||||
|
triggerNtfyTest,
|
||||||
|
ServerConfig,
|
||||||
|
SettingsResponse,
|
||||||
|
updateSettings,
|
||||||
|
UpdateSettingsPayload
|
||||||
|
} from "../api/config";
|
||||||
|
import { request } from "../api/client";
|
||||||
|
import PageHeader from "../components/PageHeader";
|
||||||
|
import { useAuth } from "../contexts/AuthContext";
|
||||||
|
import { useSnackbar } from "../hooks/useSnackbar";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
interface HealthResponse {
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type FormValues = {
|
||||||
|
paperlessBaseUrl: string;
|
||||||
|
paperlessExternalUrl: string;
|
||||||
|
paperlessToken: string;
|
||||||
|
schedulerIntervalMinutes: number;
|
||||||
|
alertDaysBefore: number;
|
||||||
|
mailServer: string;
|
||||||
|
mailPort: string;
|
||||||
|
mailUsername: string;
|
||||||
|
mailPassword: string;
|
||||||
|
mailUseTls: boolean;
|
||||||
|
mailFrom: string;
|
||||||
|
mailTo: string;
|
||||||
|
ntfyServerUrl: string;
|
||||||
|
ntfyTopic: string;
|
||||||
|
ntfyToken: string;
|
||||||
|
ntfyPriority: string;
|
||||||
|
authUsername: string;
|
||||||
|
authPassword: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultValues: FormValues = {
|
||||||
|
paperlessBaseUrl: "",
|
||||||
|
paperlessExternalUrl: "",
|
||||||
|
paperlessToken: "",
|
||||||
|
schedulerIntervalMinutes: 60,
|
||||||
|
alertDaysBefore: 30,
|
||||||
|
mailServer: "",
|
||||||
|
mailPort: "",
|
||||||
|
mailUsername: "",
|
||||||
|
mailPassword: "",
|
||||||
|
mailUseTls: true,
|
||||||
|
mailFrom: "",
|
||||||
|
mailTo: "",
|
||||||
|
ntfyServerUrl: "",
|
||||||
|
ntfyTopic: "",
|
||||||
|
ntfyToken: "",
|
||||||
|
ntfyPriority: "default",
|
||||||
|
authUsername: "",
|
||||||
|
authPassword: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function SettingsPage() {
|
||||||
|
const { authEnabled } = useAuth();
|
||||||
|
const { showMessage } = useSnackbar();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const { data: health } = useQuery({
|
||||||
|
queryKey: ["healthz"],
|
||||||
|
queryFn: () => request<HealthResponse>("/healthz", { method: "GET" })
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: serverConfig,
|
||||||
|
refetch: refetchServerConfig
|
||||||
|
} = useQuery<ServerConfig>({
|
||||||
|
queryKey: ["server-config"],
|
||||||
|
queryFn: fetchServerConfig
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: settingsData,
|
||||||
|
isLoading: loadingSettings,
|
||||||
|
refetch: refetchSettings
|
||||||
|
} = useQuery<SettingsResponse>({
|
||||||
|
queryKey: ["settings"],
|
||||||
|
queryFn: fetchSettings
|
||||||
|
});
|
||||||
|
|
||||||
|
const initialValuesRef = useRef<FormValues>(defaultValues);
|
||||||
|
const [removePaperlessToken, setRemovePaperlessToken] = useState(false);
|
||||||
|
const [removeMailPassword, setRemoveMailPassword] = useState(false);
|
||||||
|
const [removeNtfyToken, setRemoveNtfyToken] = useState(false);
|
||||||
|
const [removeAuthPassword, setRemoveAuthPassword] = useState(false);
|
||||||
|
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
reset,
|
||||||
|
setValue,
|
||||||
|
formState: { isSubmitting }
|
||||||
|
} = useForm<FormValues>({
|
||||||
|
defaultValues
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!settingsData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const values: FormValues = {
|
||||||
|
paperlessBaseUrl: settingsData.values.paperlessBaseUrl ?? "",
|
||||||
|
paperlessExternalUrl: settingsData.values.paperlessExternalUrl ?? "",
|
||||||
|
paperlessToken: "",
|
||||||
|
schedulerIntervalMinutes: settingsData.values.schedulerIntervalMinutes,
|
||||||
|
alertDaysBefore: settingsData.values.alertDaysBefore,
|
||||||
|
mailServer: settingsData.values.mailServer ?? "",
|
||||||
|
mailPort: settingsData.values.mailPort ? String(settingsData.values.mailPort) : "",
|
||||||
|
mailUsername: settingsData.values.mailUsername ?? "",
|
||||||
|
mailPassword: "",
|
||||||
|
mailUseTls: settingsData.values.mailUseTls,
|
||||||
|
mailFrom: settingsData.values.mailFrom ?? "",
|
||||||
|
mailTo: settingsData.values.mailTo ?? "",
|
||||||
|
ntfyServerUrl: settingsData.values.ntfyServerUrl ?? "",
|
||||||
|
ntfyTopic: settingsData.values.ntfyTopic ?? "",
|
||||||
|
ntfyToken: "",
|
||||||
|
ntfyPriority: settingsData.values.ntfyPriority ?? "default",
|
||||||
|
authUsername: settingsData.values.authUsername ?? "",
|
||||||
|
authPassword: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
initialValuesRef.current = values;
|
||||||
|
setRemovePaperlessToken(false);
|
||||||
|
setRemoveMailPassword(false);
|
||||||
|
setRemoveNtfyToken(false);
|
||||||
|
setRemoveAuthPassword(false);
|
||||||
|
reset(values);
|
||||||
|
}, [settingsData, reset]);
|
||||||
|
|
||||||
|
const updateMutation = useMutation({
|
||||||
|
mutationFn: (payload: UpdateSettingsPayload) => updateSettings(payload),
|
||||||
|
onSuccess: async () => {
|
||||||
|
showMessage(t("settings.saved"), "success");
|
||||||
|
await Promise.all([refetchSettings(), refetchServerConfig()]);
|
||||||
|
},
|
||||||
|
onError: (error: Error) => {
|
||||||
|
showMessage(error.message ?? t("contractForm.saveError"), "error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const resetIcalMutation = useMutation({
|
||||||
|
mutationFn: () => resetIcalSecret(),
|
||||||
|
onSuccess: async () => {
|
||||||
|
showMessage(t("settings.icalTokenRenewed"), "success");
|
||||||
|
await refetchSettings();
|
||||||
|
},
|
||||||
|
onError: (error: Error) => showMessage(error.message ?? t("settings.actionFailed"), "error")
|
||||||
|
});
|
||||||
|
|
||||||
|
const mailTestMutation = useMutation({
|
||||||
|
mutationFn: () => triggerMailTest(),
|
||||||
|
onSuccess: () => showMessage(t("settings.mailTestSuccess"), "success"),
|
||||||
|
onError: (error: Error) => showMessage(error.message ?? t("settings.mailTestError"), "error")
|
||||||
|
});
|
||||||
|
|
||||||
|
const ntfyTestMutation = useMutation({
|
||||||
|
mutationFn: () => triggerNtfyTest(),
|
||||||
|
onSuccess: () => showMessage(t("settings.ntfyTestSuccess"), "success"),
|
||||||
|
onError: (error: Error) => showMessage(error.message ?? t("settings.ntfyTestError"), "error")
|
||||||
|
});
|
||||||
|
|
||||||
|
const settings = settingsData;
|
||||||
|
const icalSecret = settings?.icalSecret ?? null;
|
||||||
|
const icalUrl = useMemo(() => {
|
||||||
|
if (!icalSecret) return null;
|
||||||
|
if (typeof window === "undefined") return null;
|
||||||
|
const origin = window.location.origin;
|
||||||
|
return `${origin}/api/calendar/feed.ics?token=${icalSecret}`;
|
||||||
|
}, [icalSecret]);
|
||||||
|
|
||||||
|
const onSubmit = (formValues: FormValues) => {
|
||||||
|
const initial = initialValuesRef.current;
|
||||||
|
if (!initial || !settings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload: UpdateSettingsPayload = {};
|
||||||
|
const trimOrNull = (value: string) => {
|
||||||
|
const trimmed = value.trim();
|
||||||
|
return trimmed.length === 0 ? null : trimmed;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (formValues.paperlessBaseUrl !== initial.paperlessBaseUrl) {
|
||||||
|
payload.paperlessBaseUrl = trimOrNull(formValues.paperlessBaseUrl);
|
||||||
|
}
|
||||||
|
if (formValues.paperlessExternalUrl !== initial.paperlessExternalUrl) {
|
||||||
|
payload.paperlessExternalUrl = trimOrNull(formValues.paperlessExternalUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removePaperlessToken) {
|
||||||
|
payload.paperlessToken = null;
|
||||||
|
} else if (formValues.paperlessToken.trim().length > 0) {
|
||||||
|
payload.paperlessToken = formValues.paperlessToken.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.schedulerIntervalMinutes !== initial.schedulerIntervalMinutes) {
|
||||||
|
payload.schedulerIntervalMinutes = formValues.schedulerIntervalMinutes;
|
||||||
|
}
|
||||||
|
if (formValues.alertDaysBefore !== initial.alertDaysBefore) {
|
||||||
|
payload.alertDaysBefore = formValues.alertDaysBefore;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.mailServer !== initial.mailServer) {
|
||||||
|
payload.mailServer = trimOrNull(formValues.mailServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.mailPort !== initial.mailPort) {
|
||||||
|
payload.mailPort = formValues.mailPort.trim()
|
||||||
|
? Number(formValues.mailPort)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.mailUsername !== initial.mailUsername) {
|
||||||
|
payload.mailUsername = trimOrNull(formValues.mailUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeMailPassword) {
|
||||||
|
payload.mailPassword = null;
|
||||||
|
} else if (formValues.mailPassword.trim().length > 0) {
|
||||||
|
payload.mailPassword = formValues.mailPassword.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.mailUseTls !== initial.mailUseTls) {
|
||||||
|
payload.mailUseTls = formValues.mailUseTls;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.mailFrom !== initial.mailFrom) {
|
||||||
|
payload.mailFrom = trimOrNull(formValues.mailFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.mailTo !== initial.mailTo) {
|
||||||
|
payload.mailTo = trimOrNull(formValues.mailTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.ntfyServerUrl !== initial.ntfyServerUrl) {
|
||||||
|
payload.ntfyServerUrl = trimOrNull(formValues.ntfyServerUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.ntfyTopic !== initial.ntfyTopic) {
|
||||||
|
payload.ntfyTopic = trimOrNull(formValues.ntfyTopic);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeNtfyToken) {
|
||||||
|
payload.ntfyToken = null;
|
||||||
|
} else if (formValues.ntfyToken.trim().length > 0) {
|
||||||
|
payload.ntfyToken = formValues.ntfyToken.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.ntfyPriority !== initial.ntfyPriority) {
|
||||||
|
payload.ntfyPriority = formValues.ntfyPriority === "default" ? null : formValues.ntfyPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formValues.authUsername !== initial.authUsername) {
|
||||||
|
payload.authUsername = trimOrNull(formValues.authUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeAuthPassword) {
|
||||||
|
payload.authPassword = null;
|
||||||
|
} else if (formValues.authPassword.trim().length > 0) {
|
||||||
|
payload.authPassword = formValues.authPassword.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(payload).length === 0) {
|
||||||
|
showMessage(t("settings.noChanges"), "info");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMutation.mutate(payload);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCopy = async (text: string) => {
|
||||||
|
try {
|
||||||
|
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
showMessage(t("actions.copy"), "success");
|
||||||
|
} else {
|
||||||
|
const textarea = document.createElement("textarea");
|
||||||
|
textarea.value = text;
|
||||||
|
textarea.setAttribute("readonly", "");
|
||||||
|
textarea.style.position = "absolute";
|
||||||
|
textarea.style.left = "-9999px";
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
textarea.select();
|
||||||
|
const successful = document.execCommand("copy");
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
if (successful) {
|
||||||
|
showMessage(t("actions.copy"), "success");
|
||||||
|
} else {
|
||||||
|
showMessage(t("actions.copyUnsupported"), "warning");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showMessage((error as Error).message ?? t("actions.copyFailed"), "error");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loading = loadingSettings || !settings;
|
||||||
|
const paperlessTokenSet = settings?.secrets.paperlessTokenSet ?? false;
|
||||||
|
const mailPasswordSet = settings?.secrets.mailPasswordSet ?? false;
|
||||||
|
const ntfyTokenSet = settings?.secrets.ntfyTokenSet ?? false;
|
||||||
|
const authPasswordSet = settings?.secrets.authPasswordSet ?? false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageHeader
|
||||||
|
title={t("settings.title")}
|
||||||
|
subtitle={t("settings.subtitle")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid container spacing={3} sx={{ mb: 3 }}>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<Paper variant="outlined" sx={{ borderRadius: 3, p: 3 }}>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("settings.systemStatus")}
|
||||||
|
</Typography>
|
||||||
|
<List>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar sx={{ bgcolor: "success.main" }}>
|
||||||
|
<StorageIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("settings.apiStatus")}
|
||||||
|
secondary={health?.status === "ok" ? t("settings.apiOk") : t("settings.apiError")}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar sx={{ bgcolor: authEnabled ? "primary.main" : "warning.main" }}>
|
||||||
|
<SecurityIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("settings.authStatus")}
|
||||||
|
secondary={authEnabled ? t("settings.authActive") : t("settings.authInactive")}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar sx={{ bgcolor: serverConfig?.paperlessConfigured ? "primary.main" : "warning.main" }}>
|
||||||
|
<SettingsApplicationsIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("settings.paperlessStatus")}
|
||||||
|
secondary={
|
||||||
|
serverConfig?.paperlessConfigured
|
||||||
|
? t("settings.paperlessActive", {
|
||||||
|
url: serverConfig.paperlessBaseUrl ?? ""
|
||||||
|
})
|
||||||
|
: t("settings.paperlessInactive")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar sx={{ bgcolor: serverConfig?.mailConfigured ? "primary.main" : "warning.main" }}>
|
||||||
|
<SettingsApplicationsIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("settings.mailStatus")}
|
||||||
|
secondary={serverConfig?.mailConfigured ? t("settings.mailActive") : t("settings.mailInactive")}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar sx={{ bgcolor: serverConfig?.ntfyConfigured ? "primary.main" : "warning.main" }}>
|
||||||
|
<SettingsApplicationsIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("settings.ntfyStatus")}
|
||||||
|
secondary={serverConfig?.ntfyConfigured ? t("settings.ntfyActive") : t("settings.ntfyInactive")}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</Paper>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<Card variant="outlined" sx={{ borderRadius: 3, height: "100%" }}>
|
||||||
|
<CardContent>
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h6">{t("settings.ical")}</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{t("settings.icalDescription")}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
{icalUrl ? (
|
||||||
|
<TextField
|
||||||
|
label={t("settings.icalFeedUrl")}
|
||||||
|
value={icalUrl}
|
||||||
|
InputProps={{
|
||||||
|
readOnly: true,
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<IconButton onClick={() => handleCopy(icalUrl)} edge="end">
|
||||||
|
<ContentCopyIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Alert severity="warning">{t("settings.icalTokenMissing")}</Alert>
|
||||||
|
)}
|
||||||
|
<Stack direction="row" spacing={2}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
startIcon={<RefreshIcon />}
|
||||||
|
onClick={() => resetIcalMutation.mutate()}
|
||||||
|
disabled={resetIcalMutation.isPending}
|
||||||
|
>
|
||||||
|
{t("settings.icalRenew")}
|
||||||
|
</Button>
|
||||||
|
{resetIcalMutation.isPending && <CircularProgress size={24} />}
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Box component="form" onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<Stack spacing={3}>
|
||||||
|
<Card variant="outlined" sx={{ borderRadius: 3 }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("settings.paperless")}
|
||||||
|
</Typography>
|
||||||
|
{loading ? (
|
||||||
|
<CircularProgress size={24} />
|
||||||
|
) : (
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<TextField
|
||||||
|
label={t("settings.paperlessApiUrl")}
|
||||||
|
{...register("paperlessBaseUrl")}
|
||||||
|
placeholder={t("settings.paperlessExample")}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
label={t("settings.paperlessExternalUrl")}
|
||||||
|
{...register("paperlessExternalUrl")}
|
||||||
|
placeholder={t("settings.paperlessExample")}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
<Stack direction={{ xs: "column", sm: "row" }} spacing={2} alignItems={{ xs: "stretch", sm: "center" }}>
|
||||||
|
<TextField
|
||||||
|
label={paperlessTokenSet && !removePaperlessToken ? t("settings.paperlessTokenNew") : t("settings.paperlessToken")}
|
||||||
|
{...register("paperlessToken")}
|
||||||
|
type="password"
|
||||||
|
fullWidth
|
||||||
|
placeholder={paperlessTokenSet && !removePaperlessToken ? "" : t("settings.paperlessTokenPlaceholder")}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color={removePaperlessToken ? "inherit" : "warning"}
|
||||||
|
onClick={() => {
|
||||||
|
if (removePaperlessToken) {
|
||||||
|
setRemovePaperlessToken(false);
|
||||||
|
} else {
|
||||||
|
setRemovePaperlessToken(true);
|
||||||
|
setValue("paperlessToken", "", { shouldDirty: true });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{removePaperlessToken ? t("settings.paperlessTokenKeep") : t("settings.paperlessTokenRemove")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
{paperlessTokenSet && !removePaperlessToken && (
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
{t("settings.paperlessTokenInfo")}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="outlined" sx={{ borderRadius: 3 }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("settings.scheduler")}
|
||||||
|
</Typography>
|
||||||
|
{loading ? (
|
||||||
|
<CircularProgress size={24} />
|
||||||
|
) : (
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<TextField
|
||||||
|
label={t("settings.interval")}
|
||||||
|
type="number"
|
||||||
|
inputProps={{ min: 5, max: 1440 }}
|
||||||
|
{...register("schedulerIntervalMinutes", { valueAsNumber: true })}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
label={t("settings.alert")}
|
||||||
|
type="number"
|
||||||
|
inputProps={{ min: 1, max: 365 }}
|
||||||
|
{...register("alertDaysBefore", { valueAsNumber: true })}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="outlined" sx={{ borderRadius: 3 }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("settings.auth")}
|
||||||
|
</Typography>
|
||||||
|
{loading ? (
|
||||||
|
<CircularProgress size={24} />
|
||||||
|
) : (
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<TextField label={t("settings.authUsername")} {...register("authUsername")} fullWidth />
|
||||||
|
<Stack direction={{ xs: "column", sm: "row" }} spacing={2} alignItems={{ xs: "stretch", sm: "center" }}>
|
||||||
|
<TextField
|
||||||
|
label={t("settings.authPassword")}
|
||||||
|
type="password"
|
||||||
|
{...register("authPassword")}
|
||||||
|
fullWidth
|
||||||
|
placeholder={t("settings.authPasswordPlaceholder")}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color={removeAuthPassword ? "inherit" : "warning"}
|
||||||
|
onClick={() => {
|
||||||
|
if (removeAuthPassword) {
|
||||||
|
setRemoveAuthPassword(false);
|
||||||
|
} else {
|
||||||
|
setRemoveAuthPassword(true);
|
||||||
|
setValue("authPassword", "", { shouldDirty: true });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{removeAuthPassword ? t("settings.paperlessTokenKeep") : t("settings.authPasswordRemove")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
{authPasswordSet && !removeAuthPassword && (
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
{t("settings.authPasswordInfo")}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
{t("settings.authHint")}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="outlined" sx={{ borderRadius: 3 }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("settings.mail")}
|
||||||
|
</Typography>
|
||||||
|
{loading ? (
|
||||||
|
<CircularProgress size={24} />
|
||||||
|
) : (
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<TextField label={t("settings.smtpServer")} {...register("mailServer")} fullWidth />
|
||||||
|
<TextField
|
||||||
|
label={t("settings.smtpPort")}
|
||||||
|
type="number"
|
||||||
|
{...register("mailPort")}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
<TextField label={t("settings.smtpUsername")} {...register("mailUsername")} fullWidth />
|
||||||
|
<Stack direction={{ xs: "column", sm: "row" }} spacing={2} alignItems={{ xs: "stretch", sm: "center" }}>
|
||||||
|
<TextField
|
||||||
|
label={mailPasswordSet && !removeMailPassword ? t("settings.smtpPasswordNew") : t("settings.smtpPassword")}
|
||||||
|
type="password"
|
||||||
|
{...register("mailPassword")}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color={removeMailPassword ? "inherit" : "warning"}
|
||||||
|
onClick={() => {
|
||||||
|
if (removeMailPassword) {
|
||||||
|
setRemoveMailPassword(false);
|
||||||
|
} else {
|
||||||
|
setRemoveMailPassword(true);
|
||||||
|
setValue("mailPassword", "", { shouldDirty: true });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{removeMailPassword ? t("settings.paperlessTokenKeep") : t("settings.smtpPasswordRemove")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
{mailPasswordSet && !removeMailPassword && (
|
||||||
|
<Typography variant="caption" color="text.secondary">
|
||||||
|
{t("settings.smtpPasswordInfo")}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Controller
|
||||||
|
name="mailUseTls"
|
||||||
|
control={control}
|
||||||
|
render={({ field }) => <Switch {...field} checked={field.value} />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={t("settings.tls")}
|
||||||
|
/>
|
||||||
|
<TextField label={t("settings.mailFrom")} {...register("mailFrom")} fullWidth />
|
||||||
|
<TextField label={t("settings.mailTo")} {...register("mailTo")} fullWidth />
|
||||||
|
<Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => mailTestMutation.mutate()}
|
||||||
|
disabled={mailTestMutation.isPending || !serverConfig?.mailConfigured}
|
||||||
|
>
|
||||||
|
{t("settings.mailTest")}
|
||||||
|
</Button>
|
||||||
|
{mailTestMutation.isPending && <CircularProgress size={24} />}
|
||||||
|
</Stack>
|
||||||
|
{mailTestMutation.isError && (
|
||||||
|
<Alert severity="error">{(mailTestMutation.error as Error).message ?? t("settings.mailTestError")}</Alert>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card variant="outlined" sx={{ borderRadius: 3 }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{t("settings.ntfy")}
|
||||||
|
</Typography>
|
||||||
|
{loading ? (
|
||||||
|
<CircularProgress size={24} />
|
||||||
|
) : (
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<TextField label={t("settings.ntfyServer")} {...register("ntfyServerUrl")} fullWidth />
|
||||||
|
<TextField label={t("settings.ntfyTopic")} {...register("ntfyTopic")} fullWidth />
|
||||||
|
<Stack direction={{ xs: "column", sm: "row" }} spacing={2} alignItems={{ xs: "stretch", sm: "center" }}>
|
||||||
|
<TextField
|
||||||
|
label={ntfyTokenSet && !removeNtfyToken ? t("settings.ntfyTokenNew") : t("settings.ntfyToken")}
|
||||||
|
type="password"
|
||||||
|
{...register("ntfyToken")}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color={removeNtfyToken ? "inherit" : "warning"}
|
||||||
|
onClick={() => {
|
||||||
|
if (removeNtfyToken) {
|
||||||
|
setRemoveNtfyToken(false);
|
||||||
|
} else {
|
||||||
|
setRemoveNtfyToken(true);
|
||||||
|
setValue("ntfyToken", "", { shouldDirty: true });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{removeNtfyToken ? t("settings.paperlessTokenKeep") : t("settings.ntfyTokenRemove")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
<TextField
|
||||||
|
label={t("settings.ntfyPriority")}
|
||||||
|
select
|
||||||
|
SelectProps={{ native: true }}
|
||||||
|
{...register("ntfyPriority")}
|
||||||
|
>
|
||||||
|
<option value="default">default</option>
|
||||||
|
<option value="min">min</option>
|
||||||
|
<option value="low">low</option>
|
||||||
|
<option value="high">high</option>
|
||||||
|
<option value="urgent">urgent</option>
|
||||||
|
</TextField>
|
||||||
|
<Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => ntfyTestMutation.mutate()}
|
||||||
|
disabled={ntfyTestMutation.isPending || !serverConfig?.ntfyConfigured}
|
||||||
|
>
|
||||||
|
{t("settings.ntfyTest")}
|
||||||
|
</Button>
|
||||||
|
{ntfyTestMutation.isPending && <CircularProgress size={24} />}
|
||||||
|
</Stack>
|
||||||
|
{ntfyTestMutation.isError && (
|
||||||
|
<Alert severity="error">{(ntfyTestMutation.error as Error).message ?? t("settings.mailTestError")}</Alert>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Stack direction="row" spacing={2} justifyContent="flex-end">
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="contained"
|
||||||
|
disabled={isSubmitting || updateMutation.isPending}
|
||||||
|
>
|
||||||
|
{updateMutation.isPending ? t("actions.saving") : t("settings.save")}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
38
frontend/src/theme.ts
Normal file
38
frontend/src/theme.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { createTheme } from "@mui/material/styles";
|
||||||
|
|
||||||
|
export const lightTheme = createTheme({
|
||||||
|
palette: {
|
||||||
|
mode: "light",
|
||||||
|
primary: {
|
||||||
|
main: "#556cd6"
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#19857b"
|
||||||
|
},
|
||||||
|
background: {
|
||||||
|
default: "#f4f6fb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
fontFamily: [
|
||||||
|
"Inter",
|
||||||
|
"-apple-system",
|
||||||
|
"BlinkMacSystemFont",
|
||||||
|
"'Segoe UI'",
|
||||||
|
"Roboto",
|
||||||
|
"'Helvetica Neue'",
|
||||||
|
"Arial",
|
||||||
|
"sans-serif"
|
||||||
|
].join(",")
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
MuiButton: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
borderRadius: 10,
|
||||||
|
textTransform: "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
46
frontend/src/types.ts
Normal file
46
frontend/src/types.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
export interface ContractPayload {
|
||||||
|
title: string;
|
||||||
|
paperlessDocumentId?: number | null;
|
||||||
|
provider?: string | null;
|
||||||
|
category?: string | null;
|
||||||
|
contractStartDate?: string | null;
|
||||||
|
contractEndDate?: string | null;
|
||||||
|
terminationNoticeDays?: number | null;
|
||||||
|
renewalPeriodMonths?: number | null;
|
||||||
|
autoRenew?: boolean;
|
||||||
|
price?: number | null;
|
||||||
|
currency?: string;
|
||||||
|
notes?: string | null;
|
||||||
|
tags?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Contract extends ContractPayload {
|
||||||
|
id: number;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpcomingDeadline {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
provider?: string | null;
|
||||||
|
paperlessDocumentId?: number | null;
|
||||||
|
contractEndDate?: string | null;
|
||||||
|
terminationDeadline?: string | null;
|
||||||
|
daysUntilDeadline?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PaperlessDocument = Record<string, unknown> & {
|
||||||
|
id?: number;
|
||||||
|
title?: string;
|
||||||
|
created?: string;
|
||||||
|
modified?: string;
|
||||||
|
notes?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface PaperlessSearchResponse {
|
||||||
|
count: number;
|
||||||
|
next?: string | null;
|
||||||
|
previous?: string | null;
|
||||||
|
results: PaperlessDocument[];
|
||||||
|
}
|
||||||
22
frontend/src/utils/date.ts
Normal file
22
frontend/src/utils/date.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { format, parseISO } from "date-fns";
|
||||||
|
import { de } from "date-fns/locale";
|
||||||
|
|
||||||
|
export function formatDate(date: string | null | undefined, pattern = "dd.MM.yyyy"): string {
|
||||||
|
if (!date) return "–";
|
||||||
|
try {
|
||||||
|
return format(parseISO(date), pattern, { locale: de });
|
||||||
|
} catch {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatDeadlineDate(date: string | null | undefined): string {
|
||||||
|
return formatDate(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatCurrency(amount: number | null | undefined, currency = "EUR"): string {
|
||||||
|
if (amount === null || amount === undefined) {
|
||||||
|
return "–";
|
||||||
|
}
|
||||||
|
return new Intl.NumberFormat("de-DE", { style: "currency", currency }).format(amount);
|
||||||
|
}
|
||||||
22
frontend/tsconfig.json
Normal file
22
frontend/tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ES2020"],
|
||||||
|
"allowJs": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"types": ["vite/client"]
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
||||||
9
frontend/tsconfig.node.json
Normal file
9
frontend/tsconfig.node.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
19
frontend/vite.config.ts
Normal file
19
frontend/vite.config.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { defineConfig } from "vite";
|
||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
proxy: {
|
||||||
|
"/api": {
|
||||||
|
target: "http://localhost:8000",
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
port: 4173
|
||||||
|
}
|
||||||
|
});
|
||||||
BIN
node_modules/@esbuild/linux-x64/bin/esbuild
generated
vendored
Normal file
BIN
node_modules/@esbuild/linux-x64/bin/esbuild
generated
vendored
Normal file
Binary file not shown.
21
node_modules/@types/body-parser/LICENSE
generated
vendored
Normal file
21
node_modules/@types/body-parser/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
15
node_modules/@types/body-parser/README.md
generated
vendored
Normal file
15
node_modules/@types/body-parser/README.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/body-parser`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for body-parser (https://github.com/expressjs/body-parser).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/body-parser.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Sat, 07 Jun 2025 02:15:25 GMT
|
||||||
|
* Dependencies: [@types/connect](https://npmjs.com/package/@types/connect), [@types/node](https://npmjs.com/package/@types/node)
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Santi Albo](https://github.com/santialbo), [Vilic Vane](https://github.com/vilic), [Jonathan Häberle](https://github.com/dreampulse), [Gevik Babakhani](https://github.com/blendsdk), [Tomasz Łaziuk](https://github.com/tlaziuk), [Jason Walton](https://github.com/jwalton), [Piotr Błażejewicz](https://github.com/peterblazejewicz), and [Sebastian Beltran](https://github.com/bjohansebas).
|
||||||
95
node_modules/@types/body-parser/index.d.ts
generated
vendored
Normal file
95
node_modules/@types/body-parser/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import { NextHandleFunction } from "connect";
|
||||||
|
import * as http from "http";
|
||||||
|
|
||||||
|
// for docs go to https://github.com/expressjs/body-parser/tree/1.19.0#body-parser
|
||||||
|
|
||||||
|
declare namespace bodyParser {
|
||||||
|
interface BodyParser {
|
||||||
|
/**
|
||||||
|
* @deprecated use individual json/urlencoded middlewares
|
||||||
|
*/
|
||||||
|
(options?: OptionsJson & OptionsText & OptionsUrlencoded): NextHandleFunction;
|
||||||
|
/**
|
||||||
|
* Returns middleware that only parses json and only looks at requests
|
||||||
|
* where the Content-Type header matches the type option.
|
||||||
|
*/
|
||||||
|
json(options?: OptionsJson): NextHandleFunction;
|
||||||
|
/**
|
||||||
|
* Returns middleware that parses all bodies as a Buffer and only looks at requests
|
||||||
|
* where the Content-Type header matches the type option.
|
||||||
|
*/
|
||||||
|
raw(options?: Options): NextHandleFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns middleware that parses all bodies as a string and only looks at requests
|
||||||
|
* where the Content-Type header matches the type option.
|
||||||
|
*/
|
||||||
|
text(options?: OptionsText): NextHandleFunction;
|
||||||
|
/**
|
||||||
|
* Returns middleware that only parses urlencoded bodies and only looks at requests
|
||||||
|
* where the Content-Type header matches the type option
|
||||||
|
*/
|
||||||
|
urlencoded(options?: OptionsUrlencoded): NextHandleFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Options {
|
||||||
|
/** When set to true, then deflated (compressed) bodies will be inflated; when false, deflated bodies are rejected. Defaults to true. */
|
||||||
|
inflate?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Controls the maximum request body size. If this is a number,
|
||||||
|
* then the value specifies the number of bytes; if it is a string,
|
||||||
|
* the value is passed to the bytes library for parsing. Defaults to '100kb'.
|
||||||
|
*/
|
||||||
|
limit?: number | string | undefined;
|
||||||
|
/**
|
||||||
|
* The type option is used to determine what media type the middleware will parse
|
||||||
|
*/
|
||||||
|
type?: string | string[] | ((req: http.IncomingMessage) => any) | undefined;
|
||||||
|
/**
|
||||||
|
* The verify option, if supplied, is called as verify(req, res, buf, encoding),
|
||||||
|
* where buf is a Buffer of the raw request body and encoding is the encoding of the request.
|
||||||
|
*/
|
||||||
|
verify?(req: http.IncomingMessage, res: http.ServerResponse, buf: Buffer, encoding: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OptionsJson extends Options {
|
||||||
|
/**
|
||||||
|
* The reviver option is passed directly to JSON.parse as the second argument.
|
||||||
|
*/
|
||||||
|
reviver?(key: string, value: any): any;
|
||||||
|
/**
|
||||||
|
* When set to `true`, will only accept arrays and objects;
|
||||||
|
* when `false` will accept anything JSON.parse accepts. Defaults to `true`.
|
||||||
|
*/
|
||||||
|
strict?: boolean | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OptionsText extends Options {
|
||||||
|
/**
|
||||||
|
* Specify the default character set for the text content if the charset
|
||||||
|
* is not specified in the Content-Type header of the request.
|
||||||
|
* Defaults to `utf-8`.
|
||||||
|
*/
|
||||||
|
defaultCharset?: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OptionsUrlencoded extends Options {
|
||||||
|
/**
|
||||||
|
* The extended option allows to choose between parsing the URL-encoded data
|
||||||
|
* with the querystring library (when `false`) or the qs library (when `true`).
|
||||||
|
*/
|
||||||
|
extended?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* The parameterLimit option controls the maximum number of parameters
|
||||||
|
* that are allowed in the URL-encoded data. If a request contains more parameters than this value,
|
||||||
|
* a 413 will be returned to the client. Defaults to 1000.
|
||||||
|
*/
|
||||||
|
parameterLimit?: number | undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const bodyParser: bodyParser.BodyParser;
|
||||||
|
|
||||||
|
export = bodyParser;
|
||||||
64
node_modules/@types/body-parser/package.json
generated
vendored
Normal file
64
node_modules/@types/body-parser/package.json
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/body-parser",
|
||||||
|
"version": "1.19.6",
|
||||||
|
"description": "TypeScript definitions for body-parser",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/body-parser",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Santi Albo",
|
||||||
|
"githubUsername": "santialbo",
|
||||||
|
"url": "https://github.com/santialbo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vilic Vane",
|
||||||
|
"githubUsername": "vilic",
|
||||||
|
"url": "https://github.com/vilic"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jonathan Häberle",
|
||||||
|
"githubUsername": "dreampulse",
|
||||||
|
"url": "https://github.com/dreampulse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Gevik Babakhani",
|
||||||
|
"githubUsername": "blendsdk",
|
||||||
|
"url": "https://github.com/blendsdk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tomasz Łaziuk",
|
||||||
|
"githubUsername": "tlaziuk",
|
||||||
|
"url": "https://github.com/tlaziuk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jason Walton",
|
||||||
|
"githubUsername": "jwalton",
|
||||||
|
"url": "https://github.com/jwalton"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Piotr Błażejewicz",
|
||||||
|
"githubUsername": "peterblazejewicz",
|
||||||
|
"url": "https://github.com/peterblazejewicz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sebastian Beltran",
|
||||||
|
"githubUsername": "bjohansebas",
|
||||||
|
"url": "https://github.com/bjohansebas"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/body-parser"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/connect": "*",
|
||||||
|
"@types/node": "*"
|
||||||
|
},
|
||||||
|
"peerDependencies": {},
|
||||||
|
"typesPublisherContentHash": "d788c843f427d6ca19640ee90eb433324a18f23aed05402a82c4e47e6d60b29d",
|
||||||
|
"typeScriptVersion": "5.1"
|
||||||
|
}
|
||||||
21
node_modules/@types/connect/LICENSE
generated
vendored
Normal file
21
node_modules/@types/connect/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
15
node_modules/@types/connect/README.md
generated
vendored
Normal file
15
node_modules/@types/connect/README.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/connect`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for connect (https://github.com/senchalabs/connect).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/connect.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Mon, 06 Nov 2023 22:41:05 GMT
|
||||||
|
* Dependencies: [@types/node](https://npmjs.com/package/@types/node)
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Maxime LUCE](https://github.com/SomaticIT), and [Evan Hahn](https://github.com/EvanHahn).
|
||||||
91
node_modules/@types/connect/index.d.ts
generated
vendored
Normal file
91
node_modules/@types/connect/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
|
||||||
|
import * as http from "http";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new connect server.
|
||||||
|
*/
|
||||||
|
declare function createServer(): createServer.Server;
|
||||||
|
|
||||||
|
declare namespace createServer {
|
||||||
|
export type ServerHandle = HandleFunction | http.Server;
|
||||||
|
|
||||||
|
export class IncomingMessage extends http.IncomingMessage {
|
||||||
|
originalUrl?: http.IncomingMessage["url"] | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
type NextFunction = (err?: any) => void;
|
||||||
|
|
||||||
|
export type SimpleHandleFunction = (req: IncomingMessage, res: http.ServerResponse) => void;
|
||||||
|
export type NextHandleFunction = (req: IncomingMessage, res: http.ServerResponse, next: NextFunction) => void;
|
||||||
|
export type ErrorHandleFunction = (
|
||||||
|
err: any,
|
||||||
|
req: IncomingMessage,
|
||||||
|
res: http.ServerResponse,
|
||||||
|
next: NextFunction,
|
||||||
|
) => void;
|
||||||
|
export type HandleFunction = SimpleHandleFunction | NextHandleFunction | ErrorHandleFunction;
|
||||||
|
|
||||||
|
export interface ServerStackItem {
|
||||||
|
route: string;
|
||||||
|
handle: ServerHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Server extends NodeJS.EventEmitter {
|
||||||
|
(req: http.IncomingMessage, res: http.ServerResponse, next?: Function): void;
|
||||||
|
|
||||||
|
route: string;
|
||||||
|
stack: ServerStackItem[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilize the given middleware `handle` to the given `route`,
|
||||||
|
* defaulting to _/_. This "route" is the mount-point for the
|
||||||
|
* middleware, when given a value other than _/_ the middleware
|
||||||
|
* is only effective when that segment is present in the request's
|
||||||
|
* pathname.
|
||||||
|
*
|
||||||
|
* For example if we were to mount a function at _/admin_, it would
|
||||||
|
* be invoked on _/admin_, and _/admin/settings_, however it would
|
||||||
|
* not be invoked for _/_, or _/posts_.
|
||||||
|
*/
|
||||||
|
use(fn: NextHandleFunction): Server;
|
||||||
|
use(fn: HandleFunction): Server;
|
||||||
|
use(route: string, fn: NextHandleFunction): Server;
|
||||||
|
use(route: string, fn: HandleFunction): Server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle server requests, punting them down
|
||||||
|
* the middleware stack.
|
||||||
|
*/
|
||||||
|
handle(req: http.IncomingMessage, res: http.ServerResponse, next: Function): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen for connections.
|
||||||
|
*
|
||||||
|
* This method takes the same arguments
|
||||||
|
* as node's `http.Server#listen()`.
|
||||||
|
*
|
||||||
|
* HTTP and HTTPS:
|
||||||
|
*
|
||||||
|
* If you run your application both as HTTP
|
||||||
|
* and HTTPS you may wrap them individually,
|
||||||
|
* since your Connect "server" is really just
|
||||||
|
* a JavaScript `Function`.
|
||||||
|
*
|
||||||
|
* var connect = require('connect')
|
||||||
|
* , http = require('http')
|
||||||
|
* , https = require('https');
|
||||||
|
*
|
||||||
|
* var app = connect();
|
||||||
|
*
|
||||||
|
* http.createServer(app).listen(80);
|
||||||
|
* https.createServer(options, app).listen(443);
|
||||||
|
*/
|
||||||
|
listen(port: number, hostname?: string, backlog?: number, callback?: Function): http.Server;
|
||||||
|
listen(port: number, hostname?: string, callback?: Function): http.Server;
|
||||||
|
listen(path: string, callback?: Function): http.Server;
|
||||||
|
listen(handle: any, listeningListener?: Function): http.Server;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export = createServer;
|
||||||
32
node_modules/@types/connect/package.json
generated
vendored
Normal file
32
node_modules/@types/connect/package.json
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/connect",
|
||||||
|
"version": "3.4.38",
|
||||||
|
"description": "TypeScript definitions for connect",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/connect",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Maxime LUCE",
|
||||||
|
"githubUsername": "SomaticIT",
|
||||||
|
"url": "https://github.com/SomaticIT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Evan Hahn",
|
||||||
|
"githubUsername": "EvanHahn",
|
||||||
|
"url": "https://github.com/EvanHahn"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/connect"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
},
|
||||||
|
"typesPublisherContentHash": "8990242237504bdec53088b79e314b94bec69286df9de56db31f22de403b4092",
|
||||||
|
"typeScriptVersion": "4.5"
|
||||||
|
}
|
||||||
21
node_modules/@types/express-serve-static-core/LICENSE
generated
vendored
Normal file
21
node_modules/@types/express-serve-static-core/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
15
node_modules/@types/express-serve-static-core/README.md
generated
vendored
Normal file
15
node_modules/@types/express-serve-static-core/README.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/express-serve-static-core`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for express-serve-static-core (http://expressjs.com).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/express-serve-static-core/v4.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Mon, 06 Oct 2025 21:02:40 GMT
|
||||||
|
* Dependencies: [@types/node](https://npmjs.com/package/@types/node), [@types/qs](https://npmjs.com/package/@types/qs), [@types/range-parser](https://npmjs.com/package/@types/range-parser), [@types/send](https://npmjs.com/package/@types/send)
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Boris Yankov](https://github.com/borisyankov), [Satana Charuwichitratana](https://github.com/micksatana), [Jose Luis Leon](https://github.com/JoseLion), [David Stephens](https://github.com/dwrss), and [Shin Ando](https://github.com/andoshin11).
|
||||||
1295
node_modules/@types/express-serve-static-core/index.d.ts
generated
vendored
Normal file
1295
node_modules/@types/express-serve-static-core/index.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
51
node_modules/@types/express-serve-static-core/package.json
generated
vendored
Normal file
51
node_modules/@types/express-serve-static-core/package.json
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/express-serve-static-core",
|
||||||
|
"version": "4.19.7",
|
||||||
|
"description": "TypeScript definitions for express-serve-static-core",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/express-serve-static-core",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Boris Yankov",
|
||||||
|
"githubUsername": "borisyankov",
|
||||||
|
"url": "https://github.com/borisyankov"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Satana Charuwichitratana",
|
||||||
|
"githubUsername": "micksatana",
|
||||||
|
"url": "https://github.com/micksatana"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jose Luis Leon",
|
||||||
|
"githubUsername": "JoseLion",
|
||||||
|
"url": "https://github.com/JoseLion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "David Stephens",
|
||||||
|
"githubUsername": "dwrss",
|
||||||
|
"url": "https://github.com/dwrss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shin Ando",
|
||||||
|
"githubUsername": "andoshin11",
|
||||||
|
"url": "https://github.com/andoshin11"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/express-serve-static-core"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/qs": "*",
|
||||||
|
"@types/range-parser": "*",
|
||||||
|
"@types/send": "*"
|
||||||
|
},
|
||||||
|
"peerDependencies": {},
|
||||||
|
"typesPublisherContentHash": "a4797d651510430b6b53a07eb01d86881a113b9ca00290eadb6d46d91e8cedf2",
|
||||||
|
"typeScriptVersion": "5.2"
|
||||||
|
}
|
||||||
21
node_modules/@types/express/LICENSE
generated
vendored
Normal file
21
node_modules/@types/express/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
15
node_modules/@types/express/README.md
generated
vendored
Normal file
15
node_modules/@types/express/README.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/express`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for express (http://expressjs.com).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/express/v4.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Sat, 07 Jun 2025 02:15:25 GMT
|
||||||
|
* Dependencies: [@types/body-parser](https://npmjs.com/package/@types/body-parser), [@types/express-serve-static-core](https://npmjs.com/package/@types/express-serve-static-core), [@types/qs](https://npmjs.com/package/@types/qs), [@types/serve-static](https://npmjs.com/package/@types/serve-static)
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Boris Yankov](https://github.com/borisyankov), [Puneet Arora](https://github.com/puneetar), [Dylan Frankland](https://github.com/dfrankland), and [Sebastian Beltran](https://github.com/bjohansebas).
|
||||||
128
node_modules/@types/express/index.d.ts
generated
vendored
Normal file
128
node_modules/@types/express/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/* =================== USAGE ===================
|
||||||
|
|
||||||
|
import express = require("express");
|
||||||
|
var app = express();
|
||||||
|
|
||||||
|
=============================================== */
|
||||||
|
|
||||||
|
/// <reference types="express-serve-static-core" />
|
||||||
|
/// <reference types="serve-static" />
|
||||||
|
|
||||||
|
import * as bodyParser from "body-parser";
|
||||||
|
import * as core from "express-serve-static-core";
|
||||||
|
import * as qs from "qs";
|
||||||
|
import * as serveStatic from "serve-static";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Express application. The express() function is a top-level function exported by the express module.
|
||||||
|
*/
|
||||||
|
declare function e(): core.Express;
|
||||||
|
|
||||||
|
declare namespace e {
|
||||||
|
/**
|
||||||
|
* This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on body-parser.
|
||||||
|
* @since 4.16.0
|
||||||
|
*/
|
||||||
|
var json: typeof bodyParser.json;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a built-in middleware function in Express. It parses incoming requests with Buffer payloads and is based on body-parser.
|
||||||
|
* @since 4.17.0
|
||||||
|
*/
|
||||||
|
var raw: typeof bodyParser.raw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a built-in middleware function in Express. It parses incoming requests with text payloads and is based on body-parser.
|
||||||
|
* @since 4.17.0
|
||||||
|
*/
|
||||||
|
var text: typeof bodyParser.text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are the exposed prototypes.
|
||||||
|
*/
|
||||||
|
var application: Application;
|
||||||
|
var request: Request;
|
||||||
|
var response: Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a built-in middleware function in Express. It serves static files and is based on serve-static.
|
||||||
|
*/
|
||||||
|
var static: serveStatic.RequestHandlerConstructor<Response>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a built-in middleware function in Express. It parses incoming requests with urlencoded payloads and is based on body-parser.
|
||||||
|
* @since 4.16.0
|
||||||
|
*/
|
||||||
|
var urlencoded: typeof bodyParser.urlencoded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a built-in middleware function in Express. It parses incoming request query parameters.
|
||||||
|
*/
|
||||||
|
export function query(options: qs.IParseOptions | typeof qs.parse): Handler;
|
||||||
|
|
||||||
|
export function Router(options?: RouterOptions): core.Router;
|
||||||
|
|
||||||
|
interface RouterOptions {
|
||||||
|
/**
|
||||||
|
* Enable case sensitivity.
|
||||||
|
*/
|
||||||
|
caseSensitive?: boolean | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preserve the req.params values from the parent router.
|
||||||
|
* If the parent and the child have conflicting param names, the child’s value take precedence.
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
* @since 4.5.0
|
||||||
|
*/
|
||||||
|
mergeParams?: boolean | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable strict routing.
|
||||||
|
*/
|
||||||
|
strict?: boolean | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Application extends core.Application {}
|
||||||
|
interface CookieOptions extends core.CookieOptions {}
|
||||||
|
interface Errback extends core.Errback {}
|
||||||
|
interface ErrorRequestHandler<
|
||||||
|
P = core.ParamsDictionary,
|
||||||
|
ResBody = any,
|
||||||
|
ReqBody = any,
|
||||||
|
ReqQuery = core.Query,
|
||||||
|
Locals extends Record<string, any> = Record<string, any>,
|
||||||
|
> extends core.ErrorRequestHandler<P, ResBody, ReqBody, ReqQuery, Locals> {}
|
||||||
|
interface Express extends core.Express {}
|
||||||
|
interface Handler extends core.Handler {}
|
||||||
|
interface IRoute extends core.IRoute {}
|
||||||
|
interface IRouter extends core.IRouter {}
|
||||||
|
interface IRouterHandler<T> extends core.IRouterHandler<T> {}
|
||||||
|
interface IRouterMatcher<T> extends core.IRouterMatcher<T> {}
|
||||||
|
interface MediaType extends core.MediaType {}
|
||||||
|
interface NextFunction extends core.NextFunction {}
|
||||||
|
interface Locals extends core.Locals {}
|
||||||
|
interface Request<
|
||||||
|
P = core.ParamsDictionary,
|
||||||
|
ResBody = any,
|
||||||
|
ReqBody = any,
|
||||||
|
ReqQuery = core.Query,
|
||||||
|
Locals extends Record<string, any> = Record<string, any>,
|
||||||
|
> extends core.Request<P, ResBody, ReqBody, ReqQuery, Locals> {}
|
||||||
|
interface RequestHandler<
|
||||||
|
P = core.ParamsDictionary,
|
||||||
|
ResBody = any,
|
||||||
|
ReqBody = any,
|
||||||
|
ReqQuery = core.Query,
|
||||||
|
Locals extends Record<string, any> = Record<string, any>,
|
||||||
|
> extends core.RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals> {}
|
||||||
|
interface RequestParamHandler extends core.RequestParamHandler {}
|
||||||
|
interface Response<
|
||||||
|
ResBody = any,
|
||||||
|
Locals extends Record<string, any> = Record<string, any>,
|
||||||
|
> extends core.Response<ResBody, Locals> {}
|
||||||
|
interface Router extends core.Router {}
|
||||||
|
interface Send extends core.Send {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export = e;
|
||||||
46
node_modules/@types/express/package.json
generated
vendored
Normal file
46
node_modules/@types/express/package.json
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/express",
|
||||||
|
"version": "4.17.23",
|
||||||
|
"description": "TypeScript definitions for express",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/express",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Boris Yankov",
|
||||||
|
"githubUsername": "borisyankov",
|
||||||
|
"url": "https://github.com/borisyankov"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Puneet Arora",
|
||||||
|
"githubUsername": "puneetar",
|
||||||
|
"url": "https://github.com/puneetar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dylan Frankland",
|
||||||
|
"githubUsername": "dfrankland",
|
||||||
|
"url": "https://github.com/dfrankland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sebastian Beltran",
|
||||||
|
"githubUsername": "bjohansebas",
|
||||||
|
"url": "https://github.com/bjohansebas"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/express"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/body-parser": "*",
|
||||||
|
"@types/express-serve-static-core": "^4.17.33",
|
||||||
|
"@types/qs": "*",
|
||||||
|
"@types/serve-static": "*"
|
||||||
|
},
|
||||||
|
"peerDependencies": {},
|
||||||
|
"typesPublisherContentHash": "c7c276342e7f5808be5916c5dec3e614fa8b6e60b3323e369f793c389ee6f860",
|
||||||
|
"typeScriptVersion": "5.1"
|
||||||
|
}
|
||||||
21
node_modules/@types/http-errors/LICENSE
generated
vendored
Normal file
21
node_modules/@types/http-errors/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
15
node_modules/@types/http-errors/README.md
generated
vendored
Normal file
15
node_modules/@types/http-errors/README.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/http-errors`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for http-errors (https://github.com/jshttp/http-errors).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/http-errors.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Sat, 07 Jun 2025 02:15:25 GMT
|
||||||
|
* Dependencies: none
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Tanguy Krotoff](https://github.com/tkrotoff), [BendingBender](https://github.com/BendingBender), and [Sebastian Beltran](https://github.com/bjohansebas).
|
||||||
77
node_modules/@types/http-errors/index.d.ts
generated
vendored
Normal file
77
node_modules/@types/http-errors/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
export = createHttpError;
|
||||||
|
|
||||||
|
declare const createHttpError: createHttpError.CreateHttpError & createHttpError.NamedConstructors & {
|
||||||
|
isHttpError: createHttpError.IsHttpError;
|
||||||
|
};
|
||||||
|
|
||||||
|
declare namespace createHttpError {
|
||||||
|
interface HttpError<N extends number = number> extends Error {
|
||||||
|
status: N;
|
||||||
|
statusCode: N;
|
||||||
|
expose: boolean;
|
||||||
|
headers?: {
|
||||||
|
[key: string]: string;
|
||||||
|
} | undefined;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnknownError = Error | string | { [key: string]: any };
|
||||||
|
|
||||||
|
interface HttpErrorConstructor<N extends number = number> {
|
||||||
|
(msg?: string): HttpError<N>;
|
||||||
|
new(msg?: string): HttpError<N>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CreateHttpError {
|
||||||
|
<N extends number = number>(arg: N, ...rest: UnknownError[]): HttpError<N>;
|
||||||
|
(...rest: UnknownError[]): HttpError;
|
||||||
|
}
|
||||||
|
|
||||||
|
type IsHttpError = (error: unknown) => error is HttpError;
|
||||||
|
|
||||||
|
type NamedConstructors =
|
||||||
|
& {
|
||||||
|
HttpError: HttpErrorConstructor;
|
||||||
|
}
|
||||||
|
& Record<"BadRequest" | "400", HttpErrorConstructor<400>>
|
||||||
|
& Record<"Unauthorized" | "401", HttpErrorConstructor<401>>
|
||||||
|
& Record<"PaymentRequired" | "402", HttpErrorConstructor<402>>
|
||||||
|
& Record<"Forbidden" | "403", HttpErrorConstructor<403>>
|
||||||
|
& Record<"NotFound" | "404", HttpErrorConstructor<404>>
|
||||||
|
& Record<"MethodNotAllowed" | "405", HttpErrorConstructor<405>>
|
||||||
|
& Record<"NotAcceptable" | "406", HttpErrorConstructor<406>>
|
||||||
|
& Record<"ProxyAuthenticationRequired" | "407", HttpErrorConstructor<407>>
|
||||||
|
& Record<"RequestTimeout" | "408", HttpErrorConstructor<408>>
|
||||||
|
& Record<"Conflict" | "409", HttpErrorConstructor<409>>
|
||||||
|
& Record<"Gone" | "410", HttpErrorConstructor<410>>
|
||||||
|
& Record<"LengthRequired" | "411", HttpErrorConstructor<411>>
|
||||||
|
& Record<"PreconditionFailed" | "412", HttpErrorConstructor<412>>
|
||||||
|
& Record<"PayloadTooLarge" | "413", HttpErrorConstructor<413>>
|
||||||
|
& Record<"URITooLong" | "414", HttpErrorConstructor<414>>
|
||||||
|
& Record<"UnsupportedMediaType" | "415", HttpErrorConstructor<415>>
|
||||||
|
& Record<"RangeNotSatisfiable" | "416", HttpErrorConstructor<416>>
|
||||||
|
& Record<"ExpectationFailed" | "417", HttpErrorConstructor<417>>
|
||||||
|
& Record<"ImATeapot" | "418", HttpErrorConstructor<418>>
|
||||||
|
& Record<"MisdirectedRequest" | "421", HttpErrorConstructor<421>>
|
||||||
|
& Record<"UnprocessableEntity" | "422", HttpErrorConstructor<422>>
|
||||||
|
& Record<"Locked" | "423", HttpErrorConstructor<423>>
|
||||||
|
& Record<"FailedDependency" | "424", HttpErrorConstructor<424>>
|
||||||
|
& Record<"TooEarly" | "425", HttpErrorConstructor<425>>
|
||||||
|
& Record<"UpgradeRequired" | "426", HttpErrorConstructor<426>>
|
||||||
|
& Record<"PreconditionRequired" | "428", HttpErrorConstructor<428>>
|
||||||
|
& Record<"TooManyRequests" | "429", HttpErrorConstructor<429>>
|
||||||
|
& Record<"RequestHeaderFieldsTooLarge" | "431", HttpErrorConstructor<431>>
|
||||||
|
& Record<"UnavailableForLegalReasons" | "451", HttpErrorConstructor<451>>
|
||||||
|
& Record<"InternalServerError" | "500", HttpErrorConstructor<500>>
|
||||||
|
& Record<"NotImplemented" | "501", HttpErrorConstructor<501>>
|
||||||
|
& Record<"BadGateway" | "502", HttpErrorConstructor<502>>
|
||||||
|
& Record<"ServiceUnavailable" | "503", HttpErrorConstructor<503>>
|
||||||
|
& Record<"GatewayTimeout" | "504", HttpErrorConstructor<504>>
|
||||||
|
& Record<"HTTPVersionNotSupported" | "505", HttpErrorConstructor<505>>
|
||||||
|
& Record<"VariantAlsoNegotiates" | "506", HttpErrorConstructor<506>>
|
||||||
|
& Record<"InsufficientStorage" | "507", HttpErrorConstructor<507>>
|
||||||
|
& Record<"LoopDetected" | "508", HttpErrorConstructor<508>>
|
||||||
|
& Record<"BandwidthLimitExceeded" | "509", HttpErrorConstructor<509>>
|
||||||
|
& Record<"NotExtended" | "510", HttpErrorConstructor<510>>
|
||||||
|
& Record<"NetworkAuthenticationRequire" | "511", HttpErrorConstructor<511>>;
|
||||||
|
}
|
||||||
36
node_modules/@types/http-errors/package.json
generated
vendored
Normal file
36
node_modules/@types/http-errors/package.json
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/http-errors",
|
||||||
|
"version": "2.0.5",
|
||||||
|
"description": "TypeScript definitions for http-errors",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/http-errors",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Tanguy Krotoff",
|
||||||
|
"githubUsername": "tkrotoff",
|
||||||
|
"url": "https://github.com/tkrotoff"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "BendingBender",
|
||||||
|
"githubUsername": "BendingBender",
|
||||||
|
"url": "https://github.com/BendingBender"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sebastian Beltran",
|
||||||
|
"githubUsername": "bjohansebas",
|
||||||
|
"url": "https://github.com/bjohansebas"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/http-errors"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {},
|
||||||
|
"peerDependencies": {},
|
||||||
|
"typesPublisherContentHash": "621b9125a6493a2fa928b9150e335cb57429fb00e3bc0257426f1173903f7a4a",
|
||||||
|
"typeScriptVersion": "5.1"
|
||||||
|
}
|
||||||
21
node_modules/@types/mime/LICENSE
generated
vendored
Normal file
21
node_modules/@types/mime/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
10
node_modules/@types/mime/Mime.d.ts
generated
vendored
Normal file
10
node_modules/@types/mime/Mime.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { TypeMap } from "./index";
|
||||||
|
|
||||||
|
export default class Mime {
|
||||||
|
constructor(mimes: TypeMap);
|
||||||
|
|
||||||
|
lookup(path: string, fallback?: string): string;
|
||||||
|
extension(mime: string): string | undefined;
|
||||||
|
load(filepath: string): void;
|
||||||
|
define(mimes: TypeMap): void;
|
||||||
|
}
|
||||||
15
node_modules/@types/mime/README.md
generated
vendored
Normal file
15
node_modules/@types/mime/README.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/mime`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for mime (https://github.com/broofa/node-mime).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mime/v1.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Tue, 07 Nov 2023 20:08:00 GMT
|
||||||
|
* Dependencies: none
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Jeff Goddard](https://github.com/jedigo), and [Daniel Hritzkiv](https://github.com/dhritzkiv).
|
||||||
31
node_modules/@types/mime/index.d.ts
generated
vendored
Normal file
31
node_modules/@types/mime/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Originally imported from: https://github.com/soywiz/typescript-node-definitions/mime.d.ts
|
||||||
|
|
||||||
|
export as namespace mime;
|
||||||
|
|
||||||
|
export interface TypeMap {
|
||||||
|
[key: string]: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a mime type based on extension.
|
||||||
|
*
|
||||||
|
* If not found, uses the fallback argument if provided, and otherwise
|
||||||
|
* uses `default_type`.
|
||||||
|
*/
|
||||||
|
export function lookup(path: string, fallback?: string): string;
|
||||||
|
/**
|
||||||
|
* Return a file extensions associated with a mime type.
|
||||||
|
*/
|
||||||
|
export function extension(mime: string): string | undefined;
|
||||||
|
/**
|
||||||
|
* Load an Apache2-style ".types" file.
|
||||||
|
*/
|
||||||
|
export function load(filepath: string): void;
|
||||||
|
export function define(mimes: TypeMap): void;
|
||||||
|
|
||||||
|
export interface Charsets {
|
||||||
|
lookup(mime: string, fallback: string): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const charsets: Charsets;
|
||||||
|
export const default_type: string;
|
||||||
7
node_modules/@types/mime/lite.d.ts
generated
vendored
Normal file
7
node_modules/@types/mime/lite.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { default as Mime } from "./Mime";
|
||||||
|
|
||||||
|
declare const mimelite: Mime;
|
||||||
|
|
||||||
|
export as namespace mimelite;
|
||||||
|
|
||||||
|
export = mimelite;
|
||||||
30
node_modules/@types/mime/package.json
generated
vendored
Normal file
30
node_modules/@types/mime/package.json
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/mime",
|
||||||
|
"version": "1.3.5",
|
||||||
|
"description": "TypeScript definitions for mime",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mime",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Jeff Goddard",
|
||||||
|
"githubUsername": "jedigo",
|
||||||
|
"url": "https://github.com/jedigo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Daniel Hritzkiv",
|
||||||
|
"githubUsername": "dhritzkiv",
|
||||||
|
"url": "https://github.com/dhritzkiv"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/mime"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {},
|
||||||
|
"typesPublisherContentHash": "2ad7ee9a549e6721825e733c6a1a7e8bee0ca7ba93d9ab922c8f4558def52d77",
|
||||||
|
"typeScriptVersion": "4.5"
|
||||||
|
}
|
||||||
21
node_modules/@types/node/LICENSE
generated
vendored
Normal file
21
node_modules/@types/node/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
15
node_modules/@types/node/README.md
generated
vendored
Normal file
15
node_modules/@types/node/README.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/node`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for node (https://nodejs.org/).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node/v20.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Thu, 09 Oct 2025 17:35:09 GMT
|
||||||
|
* Dependencies: [undici-types](https://npmjs.com/package/undici-types)
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Microsoft TypeScript](https://github.com/Microsoft), [Alberto Schiabel](https://github.com/jkomyno), [Andrew Makarov](https://github.com/r3nya), [Benjamin Toueg](https://github.com/btoueg), [David Junger](https://github.com/touffy), [Mohsen Azimi](https://github.com/mohsen1), [Nikita Galkin](https://github.com/galkin), [Sebastian Silbermann](https://github.com/eps1lon), [Wilco Bakker](https://github.com/WilcoBakker), [Marcin Kopacz](https://github.com/chyzwar), [Trivikram Kamat](https://github.com/trivikr), [Junxiao Shi](https://github.com/yoursunny), [Ilia Baryshnikov](https://github.com/qwelias), [ExE Boss](https://github.com/ExE-Boss), [Piotr Błażejewicz](https://github.com/peterblazejewicz), [Anna Henningsen](https://github.com/addaleax), [Victor Perin](https://github.com/victorperin), [NodeJS Contributors](https://github.com/NodeJS), [Linus Unnebäck](https://github.com/LinusU), [wafuwafu13](https://github.com/wafuwafu13), [Matteo Collina](https://github.com/mcollina), and [Dmitry Semigradsky](https://github.com/Semigradsky).
|
||||||
1062
node_modules/@types/node/assert.d.ts
generated
vendored
Normal file
1062
node_modules/@types/node/assert.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
605
node_modules/@types/node/async_hooks.d.ts
generated
vendored
Normal file
605
node_modules/@types/node/async_hooks.d.ts
generated
vendored
Normal file
@@ -0,0 +1,605 @@
|
|||||||
|
/**
|
||||||
|
* We strongly discourage the use of the `async_hooks` API.
|
||||||
|
* Other APIs that can cover most of its use cases include:
|
||||||
|
*
|
||||||
|
* * [`AsyncLocalStorage`](https://nodejs.org/docs/latest-v20.x/api/async_context.html#class-asynclocalstorage) tracks async context
|
||||||
|
* * [`process.getActiveResourcesInfo()`](https://nodejs.org/docs/latest-v20.x/api/process.html#processgetactiveresourcesinfo) tracks active resources
|
||||||
|
*
|
||||||
|
* The `node:async_hooks` module provides an API to track asynchronous resources.
|
||||||
|
* It can be accessed using:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import async_hooks from 'node:async_hooks';
|
||||||
|
* ```
|
||||||
|
* @experimental
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/async_hooks.js)
|
||||||
|
*/
|
||||||
|
declare module "async_hooks" {
|
||||||
|
/**
|
||||||
|
* ```js
|
||||||
|
* import { executionAsyncId } from 'node:async_hooks';
|
||||||
|
* import fs from 'node:fs';
|
||||||
|
*
|
||||||
|
* console.log(executionAsyncId()); // 1 - bootstrap
|
||||||
|
* const path = '.';
|
||||||
|
* fs.open(path, 'r', (err, fd) => {
|
||||||
|
* console.log(executionAsyncId()); // 6 - open()
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The ID returned from `executionAsyncId()` is related to execution timing, not
|
||||||
|
* causality (which is covered by `triggerAsyncId()`):
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const server = net.createServer((conn) => {
|
||||||
|
* // Returns the ID of the server, not of the new connection, because the
|
||||||
|
* // callback runs in the execution scope of the server's MakeCallback().
|
||||||
|
* async_hooks.executionAsyncId();
|
||||||
|
*
|
||||||
|
* }).listen(port, () => {
|
||||||
|
* // Returns the ID of a TickObject (process.nextTick()) because all
|
||||||
|
* // callbacks passed to .listen() are wrapped in a nextTick().
|
||||||
|
* async_hooks.executionAsyncId();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Promise contexts may not get precise `executionAsyncIds` by default.
|
||||||
|
* See the section on [promise execution tracking](https://nodejs.org/docs/latest-v20.x/api/async_hooks.html#promise-execution-tracking).
|
||||||
|
* @since v8.1.0
|
||||||
|
* @return The `asyncId` of the current execution context. Useful to track when something calls.
|
||||||
|
*/
|
||||||
|
function executionAsyncId(): number;
|
||||||
|
/**
|
||||||
|
* Resource objects returned by `executionAsyncResource()` are most often internal
|
||||||
|
* Node.js handle objects with undocumented APIs. Using any functions or properties
|
||||||
|
* on the object is likely to crash your application and should be avoided.
|
||||||
|
*
|
||||||
|
* Using `executionAsyncResource()` in the top-level execution context will
|
||||||
|
* return an empty object as there is no handle or request object to use,
|
||||||
|
* but having an object representing the top-level can be helpful.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { open } from 'node:fs';
|
||||||
|
* import { executionAsyncId, executionAsyncResource } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* console.log(executionAsyncId(), executionAsyncResource()); // 1 {}
|
||||||
|
* open(new URL(import.meta.url), 'r', (err, fd) => {
|
||||||
|
* console.log(executionAsyncId(), executionAsyncResource()); // 7 FSReqWrap
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This can be used to implement continuation local storage without the
|
||||||
|
* use of a tracking `Map` to store the metadata:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { createServer } from 'node:http';
|
||||||
|
* import {
|
||||||
|
* executionAsyncId,
|
||||||
|
* executionAsyncResource,
|
||||||
|
* createHook,
|
||||||
|
* } from 'async_hooks';
|
||||||
|
* const sym = Symbol('state'); // Private symbol to avoid pollution
|
||||||
|
*
|
||||||
|
* createHook({
|
||||||
|
* init(asyncId, type, triggerAsyncId, resource) {
|
||||||
|
* const cr = executionAsyncResource();
|
||||||
|
* if (cr) {
|
||||||
|
* resource[sym] = cr[sym];
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* }).enable();
|
||||||
|
*
|
||||||
|
* const server = createServer((req, res) => {
|
||||||
|
* executionAsyncResource()[sym] = { state: req.url };
|
||||||
|
* setTimeout(function() {
|
||||||
|
* res.end(JSON.stringify(executionAsyncResource()[sym]));
|
||||||
|
* }, 100);
|
||||||
|
* }).listen(3000);
|
||||||
|
* ```
|
||||||
|
* @since v13.9.0, v12.17.0
|
||||||
|
* @return The resource representing the current execution. Useful to store data within the resource.
|
||||||
|
*/
|
||||||
|
function executionAsyncResource(): object;
|
||||||
|
/**
|
||||||
|
* ```js
|
||||||
|
* const server = net.createServer((conn) => {
|
||||||
|
* // The resource that caused (or triggered) this callback to be called
|
||||||
|
* // was that of the new connection. Thus the return value of triggerAsyncId()
|
||||||
|
* // is the asyncId of "conn".
|
||||||
|
* async_hooks.triggerAsyncId();
|
||||||
|
*
|
||||||
|
* }).listen(port, () => {
|
||||||
|
* // Even though all callbacks passed to .listen() are wrapped in a nextTick()
|
||||||
|
* // the callback itself exists because the call to the server's .listen()
|
||||||
|
* // was made. So the return value would be the ID of the server.
|
||||||
|
* async_hooks.triggerAsyncId();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Promise contexts may not get valid `triggerAsyncId`s by default. See
|
||||||
|
* the section on [promise execution tracking](https://nodejs.org/docs/latest-v20.x/api/async_hooks.html#promise-execution-tracking).
|
||||||
|
* @return The ID of the resource responsible for calling the callback that is currently being executed.
|
||||||
|
*/
|
||||||
|
function triggerAsyncId(): number;
|
||||||
|
interface HookCallbacks {
|
||||||
|
/**
|
||||||
|
* Called when a class is constructed that has the possibility to emit an asynchronous event.
|
||||||
|
* @param asyncId A unique ID for the async resource
|
||||||
|
* @param type The type of the async resource
|
||||||
|
* @param triggerAsyncId The unique ID of the async resource in whose execution context this async resource was created
|
||||||
|
* @param resource Reference to the resource representing the async operation, needs to be released during destroy
|
||||||
|
*/
|
||||||
|
init?(asyncId: number, type: string, triggerAsyncId: number, resource: object): void;
|
||||||
|
/**
|
||||||
|
* When an asynchronous operation is initiated or completes a callback is called to notify the user.
|
||||||
|
* The before callback is called just before said callback is executed.
|
||||||
|
* @param asyncId the unique identifier assigned to the resource about to execute the callback.
|
||||||
|
*/
|
||||||
|
before?(asyncId: number): void;
|
||||||
|
/**
|
||||||
|
* Called immediately after the callback specified in `before` is completed.
|
||||||
|
*
|
||||||
|
* If an uncaught exception occurs during execution of the callback, then `after` will run after the `'uncaughtException'` event is emitted or a `domain`'s handler runs.
|
||||||
|
* @param asyncId the unique identifier assigned to the resource which has executed the callback.
|
||||||
|
*/
|
||||||
|
after?(asyncId: number): void;
|
||||||
|
/**
|
||||||
|
* Called when a promise has resolve() called. This may not be in the same execution id
|
||||||
|
* as the promise itself.
|
||||||
|
* @param asyncId the unique id for the promise that was resolve()d.
|
||||||
|
*/
|
||||||
|
promiseResolve?(asyncId: number): void;
|
||||||
|
/**
|
||||||
|
* Called after the resource corresponding to asyncId is destroyed
|
||||||
|
* @param asyncId a unique ID for the async resource
|
||||||
|
*/
|
||||||
|
destroy?(asyncId: number): void;
|
||||||
|
}
|
||||||
|
interface AsyncHook {
|
||||||
|
/**
|
||||||
|
* Enable the callbacks for a given AsyncHook instance. If no callbacks are provided enabling is a noop.
|
||||||
|
*/
|
||||||
|
enable(): this;
|
||||||
|
/**
|
||||||
|
* Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled.
|
||||||
|
*/
|
||||||
|
disable(): this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Registers functions to be called for different lifetime events of each async
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* The callbacks `init()`/`before()`/`after()`/`destroy()` are called for the
|
||||||
|
* respective asynchronous event during a resource's lifetime.
|
||||||
|
*
|
||||||
|
* All callbacks are optional. For example, if only resource cleanup needs to
|
||||||
|
* be tracked, then only the `destroy` callback needs to be passed. The
|
||||||
|
* specifics of all functions that can be passed to `callbacks` is in the `Hook Callbacks` section.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { createHook } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* const asyncHook = createHook({
|
||||||
|
* init(asyncId, type, triggerAsyncId, resource) { },
|
||||||
|
* destroy(asyncId) { },
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The callbacks will be inherited via the prototype chain:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* class MyAsyncCallbacks {
|
||||||
|
* init(asyncId, type, triggerAsyncId, resource) { }
|
||||||
|
* destroy(asyncId) {}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* class MyAddedCallbacks extends MyAsyncCallbacks {
|
||||||
|
* before(asyncId) { }
|
||||||
|
* after(asyncId) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const asyncHook = async_hooks.createHook(new MyAddedCallbacks());
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Because promises are asynchronous resources whose lifecycle is tracked
|
||||||
|
* via the async hooks mechanism, the `init()`, `before()`, `after()`, and`destroy()` callbacks _must not_ be async functions that return promises.
|
||||||
|
* @since v8.1.0
|
||||||
|
* @param callbacks The `Hook Callbacks` to register
|
||||||
|
* @return Instance used for disabling and enabling hooks
|
||||||
|
*/
|
||||||
|
function createHook(callbacks: HookCallbacks): AsyncHook;
|
||||||
|
interface AsyncResourceOptions {
|
||||||
|
/**
|
||||||
|
* The ID of the execution context that created this async event.
|
||||||
|
* @default executionAsyncId()
|
||||||
|
*/
|
||||||
|
triggerAsyncId?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Disables automatic `emitDestroy` when the object is garbage collected.
|
||||||
|
* This usually does not need to be set (even if `emitDestroy` is called
|
||||||
|
* manually), unless the resource's `asyncId` is retrieved and the
|
||||||
|
* sensitive API's `emitDestroy` is called with it.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
requireManualDestroy?: boolean | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The class `AsyncResource` is designed to be extended by the embedder's async
|
||||||
|
* resources. Using this, users can easily trigger the lifetime events of their
|
||||||
|
* own resources.
|
||||||
|
*
|
||||||
|
* The `init` hook will trigger when an `AsyncResource` is instantiated.
|
||||||
|
*
|
||||||
|
* The following is an overview of the `AsyncResource` API.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { AsyncResource, executionAsyncId } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* // AsyncResource() is meant to be extended. Instantiating a
|
||||||
|
* // new AsyncResource() also triggers init. If triggerAsyncId is omitted then
|
||||||
|
* // async_hook.executionAsyncId() is used.
|
||||||
|
* const asyncResource = new AsyncResource(
|
||||||
|
* type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false },
|
||||||
|
* );
|
||||||
|
*
|
||||||
|
* // Run a function in the execution context of the resource. This will
|
||||||
|
* // * establish the context of the resource
|
||||||
|
* // * trigger the AsyncHooks before callbacks
|
||||||
|
* // * call the provided function `fn` with the supplied arguments
|
||||||
|
* // * trigger the AsyncHooks after callbacks
|
||||||
|
* // * restore the original execution context
|
||||||
|
* asyncResource.runInAsyncScope(fn, thisArg, ...args);
|
||||||
|
*
|
||||||
|
* // Call AsyncHooks destroy callbacks.
|
||||||
|
* asyncResource.emitDestroy();
|
||||||
|
*
|
||||||
|
* // Return the unique ID assigned to the AsyncResource instance.
|
||||||
|
* asyncResource.asyncId();
|
||||||
|
*
|
||||||
|
* // Return the trigger ID for the AsyncResource instance.
|
||||||
|
* asyncResource.triggerAsyncId();
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class AsyncResource {
|
||||||
|
/**
|
||||||
|
* AsyncResource() is meant to be extended. Instantiating a
|
||||||
|
* new AsyncResource() also triggers init. If triggerAsyncId is omitted then
|
||||||
|
* async_hook.executionAsyncId() is used.
|
||||||
|
* @param type The type of async event.
|
||||||
|
* @param triggerAsyncId The ID of the execution context that created
|
||||||
|
* this async event (default: `executionAsyncId()`), or an
|
||||||
|
* AsyncResourceOptions object (since v9.3.0)
|
||||||
|
*/
|
||||||
|
constructor(type: string, triggerAsyncId?: number | AsyncResourceOptions);
|
||||||
|
/**
|
||||||
|
* Binds the given function to the current execution context.
|
||||||
|
* @since v14.8.0, v12.19.0
|
||||||
|
* @param fn The function to bind to the current execution context.
|
||||||
|
* @param type An optional name to associate with the underlying `AsyncResource`.
|
||||||
|
*/
|
||||||
|
static bind<Func extends (this: ThisArg, ...args: any[]) => any, ThisArg>(
|
||||||
|
fn: Func,
|
||||||
|
type?: string,
|
||||||
|
thisArg?: ThisArg,
|
||||||
|
): Func;
|
||||||
|
/**
|
||||||
|
* Binds the given function to execute to this `AsyncResource`'s scope.
|
||||||
|
* @since v14.8.0, v12.19.0
|
||||||
|
* @param fn The function to bind to the current `AsyncResource`.
|
||||||
|
*/
|
||||||
|
bind<Func extends (...args: any[]) => any>(fn: Func): Func;
|
||||||
|
/**
|
||||||
|
* Call the provided function with the provided arguments in the execution context
|
||||||
|
* of the async resource. This will establish the context, trigger the AsyncHooks
|
||||||
|
* before callbacks, call the function, trigger the AsyncHooks after callbacks, and
|
||||||
|
* then restore the original execution context.
|
||||||
|
* @since v9.6.0
|
||||||
|
* @param fn The function to call in the execution context of this async resource.
|
||||||
|
* @param thisArg The receiver to be used for the function call.
|
||||||
|
* @param args Optional arguments to pass to the function.
|
||||||
|
*/
|
||||||
|
runInAsyncScope<This, Result>(
|
||||||
|
fn: (this: This, ...args: any[]) => Result,
|
||||||
|
thisArg?: This,
|
||||||
|
...args: any[]
|
||||||
|
): Result;
|
||||||
|
/**
|
||||||
|
* Call all `destroy` hooks. This should only ever be called once. An error will
|
||||||
|
* be thrown if it is called more than once. This **must** be manually called. If
|
||||||
|
* the resource is left to be collected by the GC then the `destroy` hooks will
|
||||||
|
* never be called.
|
||||||
|
* @return A reference to `asyncResource`.
|
||||||
|
*/
|
||||||
|
emitDestroy(): this;
|
||||||
|
/**
|
||||||
|
* @return The unique `asyncId` assigned to the resource.
|
||||||
|
*/
|
||||||
|
asyncId(): number;
|
||||||
|
/**
|
||||||
|
* @return The same `triggerAsyncId` that is passed to the `AsyncResource` constructor.
|
||||||
|
*/
|
||||||
|
triggerAsyncId(): number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This class creates stores that stay coherent through asynchronous operations.
|
||||||
|
*
|
||||||
|
* While you can create your own implementation on top of the `node:async_hooks` module, `AsyncLocalStorage` should be preferred as it is a performant and memory
|
||||||
|
* safe implementation that involves significant optimizations that are non-obvious
|
||||||
|
* to implement.
|
||||||
|
*
|
||||||
|
* The following example uses `AsyncLocalStorage` to build a simple logger
|
||||||
|
* that assigns IDs to incoming HTTP requests and includes them in messages
|
||||||
|
* logged within each request.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import http from 'node:http';
|
||||||
|
* import { AsyncLocalStorage } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* const asyncLocalStorage = new AsyncLocalStorage();
|
||||||
|
*
|
||||||
|
* function logWithId(msg) {
|
||||||
|
* const id = asyncLocalStorage.getStore();
|
||||||
|
* console.log(`${id !== undefined ? id : '-'}:`, msg);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* let idSeq = 0;
|
||||||
|
* http.createServer((req, res) => {
|
||||||
|
* asyncLocalStorage.run(idSeq++, () => {
|
||||||
|
* logWithId('start');
|
||||||
|
* // Imagine any chain of async operations here
|
||||||
|
* setImmediate(() => {
|
||||||
|
* logWithId('finish');
|
||||||
|
* res.end();
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* }).listen(8080);
|
||||||
|
*
|
||||||
|
* http.get('http://localhost:8080');
|
||||||
|
* http.get('http://localhost:8080');
|
||||||
|
* // Prints:
|
||||||
|
* // 0: start
|
||||||
|
* // 1: start
|
||||||
|
* // 0: finish
|
||||||
|
* // 1: finish
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Each instance of `AsyncLocalStorage` maintains an independent storage context.
|
||||||
|
* Multiple instances can safely exist simultaneously without risk of interfering
|
||||||
|
* with each other's data.
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
*/
|
||||||
|
class AsyncLocalStorage<T> {
|
||||||
|
/**
|
||||||
|
* Binds the given function to the current execution context.
|
||||||
|
* @since v19.8.0
|
||||||
|
* @experimental
|
||||||
|
* @param fn The function to bind to the current execution context.
|
||||||
|
* @return A new function that calls `fn` within the captured execution context.
|
||||||
|
*/
|
||||||
|
static bind<Func extends (...args: any[]) => any>(fn: Func): Func;
|
||||||
|
/**
|
||||||
|
* Captures the current execution context and returns a function that accepts a
|
||||||
|
* function as an argument. Whenever the returned function is called, it
|
||||||
|
* calls the function passed to it within the captured context.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const asyncLocalStorage = new AsyncLocalStorage();
|
||||||
|
* const runInAsyncScope = asyncLocalStorage.run(123, () => AsyncLocalStorage.snapshot());
|
||||||
|
* const result = asyncLocalStorage.run(321, () => runInAsyncScope(() => asyncLocalStorage.getStore()));
|
||||||
|
* console.log(result); // returns 123
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* AsyncLocalStorage.snapshot() can replace the use of AsyncResource for simple
|
||||||
|
* async context tracking purposes, for example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* class Foo {
|
||||||
|
* #runInAsyncScope = AsyncLocalStorage.snapshot();
|
||||||
|
*
|
||||||
|
* get() { return this.#runInAsyncScope(() => asyncLocalStorage.getStore()); }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const foo = asyncLocalStorage.run(123, () => new Foo());
|
||||||
|
* console.log(asyncLocalStorage.run(321, () => foo.get())); // returns 123
|
||||||
|
* ```
|
||||||
|
* @since v19.8.0
|
||||||
|
* @experimental
|
||||||
|
* @return A new function with the signature `(fn: (...args) : R, ...args) : R`.
|
||||||
|
*/
|
||||||
|
static snapshot(): <R, TArgs extends any[]>(fn: (...args: TArgs) => R, ...args: TArgs) => R;
|
||||||
|
/**
|
||||||
|
* Disables the instance of `AsyncLocalStorage`. All subsequent calls
|
||||||
|
* to `asyncLocalStorage.getStore()` will return `undefined` until `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()` is called again.
|
||||||
|
*
|
||||||
|
* When calling `asyncLocalStorage.disable()`, all current contexts linked to the
|
||||||
|
* instance will be exited.
|
||||||
|
*
|
||||||
|
* Calling `asyncLocalStorage.disable()` is required before the `asyncLocalStorage` can be garbage collected. This does not apply to stores
|
||||||
|
* provided by the `asyncLocalStorage`, as those objects are garbage collected
|
||||||
|
* along with the corresponding async resources.
|
||||||
|
*
|
||||||
|
* Use this method when the `asyncLocalStorage` is not in use anymore
|
||||||
|
* in the current process.
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
disable(): void;
|
||||||
|
/**
|
||||||
|
* Returns the current store.
|
||||||
|
* If called outside of an asynchronous context initialized by
|
||||||
|
* calling `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()`, it
|
||||||
|
* returns `undefined`.
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
*/
|
||||||
|
getStore(): T | undefined;
|
||||||
|
/**
|
||||||
|
* Runs a function synchronously within a context and returns its
|
||||||
|
* return value. The store is not accessible outside of the callback function.
|
||||||
|
* The store is accessible to any asynchronous operations created within the
|
||||||
|
* callback.
|
||||||
|
*
|
||||||
|
* The optional `args` are passed to the callback function.
|
||||||
|
*
|
||||||
|
* If the callback function throws an error, the error is thrown by `run()` too.
|
||||||
|
* The stacktrace is not impacted by this call and the context is exited.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const store = { id: 2 };
|
||||||
|
* try {
|
||||||
|
* asyncLocalStorage.run(store, () => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the store object
|
||||||
|
* setTimeout(() => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the store object
|
||||||
|
* }, 200);
|
||||||
|
* throw new Error();
|
||||||
|
* });
|
||||||
|
* } catch (e) {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns undefined
|
||||||
|
* // The error will be caught here
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
*/
|
||||||
|
run<R>(store: T, callback: () => R): R;
|
||||||
|
run<R, TArgs extends any[]>(store: T, callback: (...args: TArgs) => R, ...args: TArgs): R;
|
||||||
|
/**
|
||||||
|
* Runs a function synchronously outside of a context and returns its
|
||||||
|
* return value. The store is not accessible within the callback function or
|
||||||
|
* the asynchronous operations created within the callback. Any `getStore()` call done within the callback function will always return `undefined`.
|
||||||
|
*
|
||||||
|
* The optional `args` are passed to the callback function.
|
||||||
|
*
|
||||||
|
* If the callback function throws an error, the error is thrown by `exit()` too.
|
||||||
|
* The stacktrace is not impacted by this call and the context is re-entered.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // Within a call to run
|
||||||
|
* try {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the store object or value
|
||||||
|
* asyncLocalStorage.exit(() => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns undefined
|
||||||
|
* throw new Error();
|
||||||
|
* });
|
||||||
|
* } catch (e) {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the same object or value
|
||||||
|
* // The error will be caught here
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
exit<R, TArgs extends any[]>(callback: (...args: TArgs) => R, ...args: TArgs): R;
|
||||||
|
/**
|
||||||
|
* Transitions into the context for the remainder of the current
|
||||||
|
* synchronous execution and then persists the store through any following
|
||||||
|
* asynchronous calls.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const store = { id: 1 };
|
||||||
|
* // Replaces previous store with the given store object
|
||||||
|
* asyncLocalStorage.enterWith(store);
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the store object
|
||||||
|
* someAsyncOperation(() => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the same object
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This transition will continue for the _entire_ synchronous execution.
|
||||||
|
* This means that if, for example, the context is entered within an event
|
||||||
|
* handler subsequent event handlers will also run within that context unless
|
||||||
|
* specifically bound to another context with an `AsyncResource`. That is why `run()` should be preferred over `enterWith()` unless there are strong reasons
|
||||||
|
* to use the latter method.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const store = { id: 1 };
|
||||||
|
*
|
||||||
|
* emitter.on('my-event', () => {
|
||||||
|
* asyncLocalStorage.enterWith(store);
|
||||||
|
* });
|
||||||
|
* emitter.on('my-event', () => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the same object
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* asyncLocalStorage.getStore(); // Returns undefined
|
||||||
|
* emitter.emit('my-event');
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the same object
|
||||||
|
* ```
|
||||||
|
* @since v13.11.0, v12.17.0
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
enterWith(store: T): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @since v17.2.0, v16.14.0
|
||||||
|
* @return A map of provider types to the corresponding numeric id.
|
||||||
|
* This map contains all the event types that might be emitted by the `async_hooks.init()` event.
|
||||||
|
*/
|
||||||
|
namespace asyncWrapProviders {
|
||||||
|
const NONE: number;
|
||||||
|
const DIRHANDLE: number;
|
||||||
|
const DNSCHANNEL: number;
|
||||||
|
const ELDHISTOGRAM: number;
|
||||||
|
const FILEHANDLE: number;
|
||||||
|
const FILEHANDLECLOSEREQ: number;
|
||||||
|
const FIXEDSIZEBLOBCOPY: number;
|
||||||
|
const FSEVENTWRAP: number;
|
||||||
|
const FSREQCALLBACK: number;
|
||||||
|
const FSREQPROMISE: number;
|
||||||
|
const GETADDRINFOREQWRAP: number;
|
||||||
|
const GETNAMEINFOREQWRAP: number;
|
||||||
|
const HEAPSNAPSHOT: number;
|
||||||
|
const HTTP2SESSION: number;
|
||||||
|
const HTTP2STREAM: number;
|
||||||
|
const HTTP2PING: number;
|
||||||
|
const HTTP2SETTINGS: number;
|
||||||
|
const HTTPINCOMINGMESSAGE: number;
|
||||||
|
const HTTPCLIENTREQUEST: number;
|
||||||
|
const JSSTREAM: number;
|
||||||
|
const JSUDPWRAP: number;
|
||||||
|
const MESSAGEPORT: number;
|
||||||
|
const PIPECONNECTWRAP: number;
|
||||||
|
const PIPESERVERWRAP: number;
|
||||||
|
const PIPEWRAP: number;
|
||||||
|
const PROCESSWRAP: number;
|
||||||
|
const PROMISE: number;
|
||||||
|
const QUERYWRAP: number;
|
||||||
|
const SHUTDOWNWRAP: number;
|
||||||
|
const SIGNALWRAP: number;
|
||||||
|
const STATWATCHER: number;
|
||||||
|
const STREAMPIPE: number;
|
||||||
|
const TCPCONNECTWRAP: number;
|
||||||
|
const TCPSERVERWRAP: number;
|
||||||
|
const TCPWRAP: number;
|
||||||
|
const TTYWRAP: number;
|
||||||
|
const UDPSENDWRAP: number;
|
||||||
|
const UDPWRAP: number;
|
||||||
|
const SIGINTWATCHDOG: number;
|
||||||
|
const WORKER: number;
|
||||||
|
const WORKERHEAPSNAPSHOT: number;
|
||||||
|
const WRITEWRAP: number;
|
||||||
|
const ZLIB: number;
|
||||||
|
const CHECKPRIMEREQUEST: number;
|
||||||
|
const PBKDF2REQUEST: number;
|
||||||
|
const KEYPAIRGENREQUEST: number;
|
||||||
|
const KEYGENREQUEST: number;
|
||||||
|
const KEYEXPORTREQUEST: number;
|
||||||
|
const CIPHERREQUEST: number;
|
||||||
|
const DERIVEBITSREQUEST: number;
|
||||||
|
const HASHREQUEST: number;
|
||||||
|
const RANDOMBYTESREQUEST: number;
|
||||||
|
const RANDOMPRIMEREQUEST: number;
|
||||||
|
const SCRYPTREQUEST: number;
|
||||||
|
const SIGNREQUEST: number;
|
||||||
|
const TLSWRAP: number;
|
||||||
|
const VERIFYREQUEST: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare module "node:async_hooks" {
|
||||||
|
export * from "async_hooks";
|
||||||
|
}
|
||||||
462
node_modules/@types/node/buffer.buffer.d.ts
generated
vendored
Normal file
462
node_modules/@types/node/buffer.buffer.d.ts
generated
vendored
Normal file
@@ -0,0 +1,462 @@
|
|||||||
|
declare module "buffer" {
|
||||||
|
type ImplicitArrayBuffer<T extends WithImplicitCoercion<ArrayBufferLike>> = T extends
|
||||||
|
{ valueOf(): infer V extends ArrayBufferLike } ? V : T;
|
||||||
|
global {
|
||||||
|
interface BufferConstructor {
|
||||||
|
// see buffer.d.ts for implementation shared with all TypeScript versions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a new buffer containing the given {str}.
|
||||||
|
*
|
||||||
|
* @param str String to store in buffer.
|
||||||
|
* @param encoding encoding to use, optional. Default is 'utf8'
|
||||||
|
* @deprecated since v10.0.0 - Use `Buffer.from(string[, encoding])` instead.
|
||||||
|
*/
|
||||||
|
new(str: string, encoding?: BufferEncoding): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new buffer of {size} octets.
|
||||||
|
*
|
||||||
|
* @param size count of octets to allocate.
|
||||||
|
* @deprecated since v10.0.0 - Use `Buffer.alloc()` instead (also see `Buffer.allocUnsafe()`).
|
||||||
|
*/
|
||||||
|
new(size: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new buffer containing the given {array} of octets.
|
||||||
|
*
|
||||||
|
* @param array The octets to store.
|
||||||
|
* @deprecated since v10.0.0 - Use `Buffer.from(array)` instead.
|
||||||
|
*/
|
||||||
|
new(array: ArrayLike<number>): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Produces a Buffer backed by the same allocated memory as
|
||||||
|
* the given {ArrayBuffer}/{SharedArrayBuffer}.
|
||||||
|
*
|
||||||
|
* @param arrayBuffer The ArrayBuffer with which to share memory.
|
||||||
|
* @deprecated since v10.0.0 - Use `Buffer.from(arrayBuffer[, byteOffset[, length]])` instead.
|
||||||
|
*/
|
||||||
|
new<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(arrayBuffer: TArrayBuffer): Buffer<TArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new `Buffer` using an `array` of bytes in the range `0` – `255`.
|
||||||
|
* Array entries outside that range will be truncated to fit into it.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* // Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'.
|
||||||
|
* const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If `array` is an `Array`-like object (that is, one with a `length` property of
|
||||||
|
* type `number`), it is treated as if it is an array, unless it is a `Buffer` or
|
||||||
|
* a `Uint8Array`. This means all other `TypedArray` variants get treated as an
|
||||||
|
* `Array`. To create a `Buffer` from the bytes backing a `TypedArray`, use
|
||||||
|
* `Buffer.copyBytesFrom()`.
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `array` is not an `Array` or another type
|
||||||
|
* appropriate for `Buffer.from()` variants.
|
||||||
|
*
|
||||||
|
* `Buffer.from(array)` and `Buffer.from(string)` may also use the internal
|
||||||
|
* `Buffer` pool like `Buffer.allocUnsafe()` does.
|
||||||
|
* @since v5.10.0
|
||||||
|
*/
|
||||||
|
from(array: WithImplicitCoercion<ArrayLike<number>>): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* This creates a view of the `ArrayBuffer` without copying the underlying
|
||||||
|
* memory. For example, when passed a reference to the `.buffer` property of a
|
||||||
|
* `TypedArray` instance, the newly created `Buffer` will share the same
|
||||||
|
* allocated memory as the `TypedArray`'s underlying `ArrayBuffer`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const arr = new Uint16Array(2);
|
||||||
|
*
|
||||||
|
* arr[0] = 5000;
|
||||||
|
* arr[1] = 4000;
|
||||||
|
*
|
||||||
|
* // Shares memory with `arr`.
|
||||||
|
* const buf = Buffer.from(arr.buffer);
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 88 13 a0 0f>
|
||||||
|
*
|
||||||
|
* // Changing the original Uint16Array changes the Buffer also.
|
||||||
|
* arr[1] = 6000;
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 88 13 70 17>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The optional `byteOffset` and `length` arguments specify a memory range within
|
||||||
|
* the `arrayBuffer` that will be shared by the `Buffer`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const ab = new ArrayBuffer(10);
|
||||||
|
* const buf = Buffer.from(ab, 0, 2);
|
||||||
|
*
|
||||||
|
* console.log(buf.length);
|
||||||
|
* // Prints: 2
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer` or a
|
||||||
|
* `SharedArrayBuffer` or another type appropriate for `Buffer.from()`
|
||||||
|
* variants.
|
||||||
|
*
|
||||||
|
* It is important to remember that a backing `ArrayBuffer` can cover a range
|
||||||
|
* of memory that extends beyond the bounds of a `TypedArray` view. A new
|
||||||
|
* `Buffer` created using the `buffer` property of a `TypedArray` may extend
|
||||||
|
* beyond the range of the `TypedArray`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const arrA = Uint8Array.from([0x63, 0x64, 0x65, 0x66]); // 4 elements
|
||||||
|
* const arrB = new Uint8Array(arrA.buffer, 1, 2); // 2 elements
|
||||||
|
* console.log(arrA.buffer === arrB.buffer); // true
|
||||||
|
*
|
||||||
|
* const buf = Buffer.from(arrB.buffer);
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 63 64 65 66>
|
||||||
|
* ```
|
||||||
|
* @since v5.10.0
|
||||||
|
* @param arrayBuffer An `ArrayBuffer`, `SharedArrayBuffer`, for example the
|
||||||
|
* `.buffer` property of a `TypedArray`.
|
||||||
|
* @param byteOffset Index of first byte to expose. **Default:** `0`.
|
||||||
|
* @param length Number of bytes to expose. **Default:**
|
||||||
|
* `arrayBuffer.byteLength - byteOffset`.
|
||||||
|
*/
|
||||||
|
from<TArrayBuffer extends WithImplicitCoercion<ArrayBufferLike>>(
|
||||||
|
arrayBuffer: TArrayBuffer,
|
||||||
|
byteOffset?: number,
|
||||||
|
length?: number,
|
||||||
|
): Buffer<ImplicitArrayBuffer<TArrayBuffer>>;
|
||||||
|
/**
|
||||||
|
* Creates a new `Buffer` containing `string`. The `encoding` parameter identifies
|
||||||
|
* the character encoding to be used when converting `string` into bytes.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf1 = Buffer.from('this is a tést');
|
||||||
|
* const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex');
|
||||||
|
*
|
||||||
|
* console.log(buf1.toString());
|
||||||
|
* // Prints: this is a tést
|
||||||
|
* console.log(buf2.toString());
|
||||||
|
* // Prints: this is a tést
|
||||||
|
* console.log(buf1.toString('latin1'));
|
||||||
|
* // Prints: this is a tést
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `string` is not a string or another type
|
||||||
|
* appropriate for `Buffer.from()` variants.
|
||||||
|
*
|
||||||
|
* `Buffer.from(string)` may also use the internal `Buffer` pool like
|
||||||
|
* `Buffer.allocUnsafe()` does.
|
||||||
|
* @since v5.10.0
|
||||||
|
* @param string A string to encode.
|
||||||
|
* @param encoding The encoding of `string`. **Default:** `'utf8'`.
|
||||||
|
*/
|
||||||
|
from(string: WithImplicitCoercion<string>, encoding?: BufferEncoding): Buffer<ArrayBuffer>;
|
||||||
|
from(arrayOrString: WithImplicitCoercion<ArrayLike<number> | string>): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Creates a new Buffer using the passed {data}
|
||||||
|
* @param values to create a new Buffer
|
||||||
|
*/
|
||||||
|
of(...items: number[]): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together.
|
||||||
|
*
|
||||||
|
* If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned.
|
||||||
|
*
|
||||||
|
* If `totalLength` is not provided, it is calculated from the `Buffer` instances
|
||||||
|
* in `list` by adding their lengths.
|
||||||
|
*
|
||||||
|
* If `totalLength` is provided, it is coerced to an unsigned integer. If the
|
||||||
|
* combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is
|
||||||
|
* truncated to `totalLength`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* // Create a single `Buffer` from a list of three `Buffer` instances.
|
||||||
|
*
|
||||||
|
* const buf1 = Buffer.alloc(10);
|
||||||
|
* const buf2 = Buffer.alloc(14);
|
||||||
|
* const buf3 = Buffer.alloc(18);
|
||||||
|
* const totalLength = buf1.length + buf2.length + buf3.length;
|
||||||
|
*
|
||||||
|
* console.log(totalLength);
|
||||||
|
* // Prints: 42
|
||||||
|
*
|
||||||
|
* const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
|
||||||
|
*
|
||||||
|
* console.log(bufA);
|
||||||
|
* // Prints: <Buffer 00 00 00 00 ...>
|
||||||
|
* console.log(bufA.length);
|
||||||
|
* // Prints: 42
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* `Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.
|
||||||
|
* @since v0.7.11
|
||||||
|
* @param list List of `Buffer` or {@link Uint8Array} instances to concatenate.
|
||||||
|
* @param totalLength Total length of the `Buffer` instances in `list` when concatenated.
|
||||||
|
*/
|
||||||
|
concat(list: readonly Uint8Array[], totalLength?: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Copies the underlying memory of `view` into a new `Buffer`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const u16 = new Uint16Array([0, 0xffff]);
|
||||||
|
* const buf = Buffer.copyBytesFrom(u16, 1, 1);
|
||||||
|
* u16[1] = 0;
|
||||||
|
* console.log(buf.length); // 2
|
||||||
|
* console.log(buf[0]); // 255
|
||||||
|
* console.log(buf[1]); // 255
|
||||||
|
* ```
|
||||||
|
* @since v19.8.0
|
||||||
|
* @param view The {TypedArray} to copy.
|
||||||
|
* @param [offset=0] The starting offset within `view`.
|
||||||
|
* @param [length=view.length - offset] The number of elements from `view` to copy.
|
||||||
|
*/
|
||||||
|
copyBytesFrom(view: NodeJS.TypedArray, offset?: number, length?: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the`Buffer` will be zero-filled.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.alloc(5);
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 00 00 00 00 00>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown.
|
||||||
|
*
|
||||||
|
* If `fill` is specified, the allocated `Buffer` will be initialized by calling `buf.fill(fill)`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.alloc(5, 'a');
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 61 61 61 61 61>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If both `fill` and `encoding` are specified, the allocated `Buffer` will be
|
||||||
|
* initialized by calling `buf.fill(fill, encoding)`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Calling `Buffer.alloc()` can be measurably slower than the alternative `Buffer.allocUnsafe()` but ensures that the newly created `Buffer` instance
|
||||||
|
* contents will never contain sensitive data from previous allocations, including
|
||||||
|
* data that might not have been allocated for `Buffer`s.
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `size` is not a number.
|
||||||
|
* @since v5.10.0
|
||||||
|
* @param size The desired length of the new `Buffer`.
|
||||||
|
* @param [fill=0] A value to pre-fill the new `Buffer` with.
|
||||||
|
* @param [encoding='utf8'] If `fill` is a string, this is its encoding.
|
||||||
|
*/
|
||||||
|
alloc(size: number, fill?: string | Uint8Array | number, encoding?: BufferEncoding): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown.
|
||||||
|
*
|
||||||
|
* The underlying memory for `Buffer` instances created in this way is _not_
|
||||||
|
* _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `Buffer.alloc()` instead to initialize`Buffer` instances with zeroes.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.allocUnsafe(10);
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints (contents may vary): <Buffer a0 8b 28 3f 01 00 00 00 50 32>
|
||||||
|
*
|
||||||
|
* buf.fill(0);
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 00 00 00 00 00 00 00 00 00 00>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `size` is not a number.
|
||||||
|
*
|
||||||
|
* The `Buffer` module pre-allocates an internal `Buffer` instance of
|
||||||
|
* size `Buffer.poolSize` that is used as a pool for the fast allocation of new `Buffer` instances created using `Buffer.allocUnsafe()`, `Buffer.from(array)`,
|
||||||
|
* and `Buffer.concat()` only when `size` is less than `Buffer.poolSize >>> 1` (floor of `Buffer.poolSize` divided by two).
|
||||||
|
*
|
||||||
|
* Use of this pre-allocated internal memory pool is a key difference between
|
||||||
|
* calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`.
|
||||||
|
* Specifically, `Buffer.alloc(size, fill)` will _never_ use the internal `Buffer`pool, while `Buffer.allocUnsafe(size).fill(fill)`_will_ use the internal`Buffer` pool if `size` is less
|
||||||
|
* than or equal to half `Buffer.poolSize`. The
|
||||||
|
* difference is subtle but can be important when an application requires the
|
||||||
|
* additional performance that `Buffer.allocUnsafe()` provides.
|
||||||
|
* @since v5.10.0
|
||||||
|
* @param size The desired length of the new `Buffer`.
|
||||||
|
*/
|
||||||
|
allocUnsafe(size: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. A zero-length `Buffer` is created if
|
||||||
|
* `size` is 0.
|
||||||
|
*
|
||||||
|
* The underlying memory for `Buffer` instances created in this way is _not_
|
||||||
|
* _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `buf.fill(0)` to initialize
|
||||||
|
* such `Buffer` instances with zeroes.
|
||||||
|
*
|
||||||
|
* When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances,
|
||||||
|
* allocations under 4 KiB are sliced from a single pre-allocated `Buffer`. This
|
||||||
|
* allows applications to avoid the garbage collection overhead of creating many
|
||||||
|
* individually allocated `Buffer` instances. This approach improves both
|
||||||
|
* performance and memory usage by eliminating the need to track and clean up as
|
||||||
|
* many individual `ArrayBuffer` objects.
|
||||||
|
*
|
||||||
|
* However, in the case where a developer may need to retain a small chunk of
|
||||||
|
* memory from a pool for an indeterminate amount of time, it may be appropriate
|
||||||
|
* to create an un-pooled `Buffer` instance using `Buffer.allocUnsafeSlow()` and
|
||||||
|
* then copying out the relevant bits.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* // Need to keep around a few small chunks of memory.
|
||||||
|
* const store = [];
|
||||||
|
*
|
||||||
|
* socket.on('readable', () => {
|
||||||
|
* let data;
|
||||||
|
* while (null !== (data = readable.read())) {
|
||||||
|
* // Allocate for retained data.
|
||||||
|
* const sb = Buffer.allocUnsafeSlow(10);
|
||||||
|
*
|
||||||
|
* // Copy the data into the new allocation.
|
||||||
|
* data.copy(sb, 0, 0, 10);
|
||||||
|
*
|
||||||
|
* store.push(sb);
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `size` is not a number.
|
||||||
|
* @since v5.12.0
|
||||||
|
* @param size The desired length of the new `Buffer`.
|
||||||
|
*/
|
||||||
|
allocUnsafeSlow(size: number): Buffer<ArrayBuffer>;
|
||||||
|
}
|
||||||
|
interface Buffer<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> extends Uint8Array<TArrayBuffer> {
|
||||||
|
// see buffer.d.ts for implementation shared with all TypeScript versions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new `Buffer` that references the same memory as the original, but
|
||||||
|
* offset and cropped by the `start` and `end` indices.
|
||||||
|
*
|
||||||
|
* This method is not compatible with the `Uint8Array.prototype.slice()`,
|
||||||
|
* which is a superclass of `Buffer`. To copy the slice, use`Uint8Array.prototype.slice()`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.from('buffer');
|
||||||
|
*
|
||||||
|
* const copiedBuf = Uint8Array.prototype.slice.call(buf);
|
||||||
|
* copiedBuf[0]++;
|
||||||
|
* console.log(copiedBuf.toString());
|
||||||
|
* // Prints: cuffer
|
||||||
|
*
|
||||||
|
* console.log(buf.toString());
|
||||||
|
* // Prints: buffer
|
||||||
|
*
|
||||||
|
* // With buf.slice(), the original buffer is modified.
|
||||||
|
* const notReallyCopiedBuf = buf.slice();
|
||||||
|
* notReallyCopiedBuf[0]++;
|
||||||
|
* console.log(notReallyCopiedBuf.toString());
|
||||||
|
* // Prints: cuffer
|
||||||
|
* console.log(buf.toString());
|
||||||
|
* // Also prints: cuffer (!)
|
||||||
|
* ```
|
||||||
|
* @since v0.3.0
|
||||||
|
* @deprecated Use `subarray` instead.
|
||||||
|
* @param [start=0] Where the new `Buffer` will start.
|
||||||
|
* @param [end=buf.length] Where the new `Buffer` will end (not inclusive).
|
||||||
|
*/
|
||||||
|
slice(start?: number, end?: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Returns a new `Buffer` that references the same memory as the original, but
|
||||||
|
* offset and cropped by the `start` and `end` indices.
|
||||||
|
*
|
||||||
|
* Specifying `end` greater than `buf.length` will return the same result as
|
||||||
|
* that of `end` equal to `buf.length`.
|
||||||
|
*
|
||||||
|
* This method is inherited from [`TypedArray.prototype.subarray()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray).
|
||||||
|
*
|
||||||
|
* Modifying the new `Buffer` slice will modify the memory in the original `Buffer`because the allocated memory of the two objects overlap.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* // Create a `Buffer` with the ASCII alphabet, take a slice, and modify one byte
|
||||||
|
* // from the original `Buffer`.
|
||||||
|
*
|
||||||
|
* const buf1 = Buffer.allocUnsafe(26);
|
||||||
|
*
|
||||||
|
* for (let i = 0; i < 26; i++) {
|
||||||
|
* // 97 is the decimal ASCII value for 'a'.
|
||||||
|
* buf1[i] = i + 97;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const buf2 = buf1.subarray(0, 3);
|
||||||
|
*
|
||||||
|
* console.log(buf2.toString('ascii', 0, buf2.length));
|
||||||
|
* // Prints: abc
|
||||||
|
*
|
||||||
|
* buf1[0] = 33;
|
||||||
|
*
|
||||||
|
* console.log(buf2.toString('ascii', 0, buf2.length));
|
||||||
|
* // Prints: !bc
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Specifying negative indexes causes the slice to be generated relative to the
|
||||||
|
* end of `buf` rather than the beginning.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.from('buffer');
|
||||||
|
*
|
||||||
|
* console.log(buf.subarray(-6, -1).toString());
|
||||||
|
* // Prints: buffe
|
||||||
|
* // (Equivalent to buf.subarray(0, 5).)
|
||||||
|
*
|
||||||
|
* console.log(buf.subarray(-6, -2).toString());
|
||||||
|
* // Prints: buff
|
||||||
|
* // (Equivalent to buf.subarray(0, 4).)
|
||||||
|
*
|
||||||
|
* console.log(buf.subarray(-5, -2).toString());
|
||||||
|
* // Prints: uff
|
||||||
|
* // (Equivalent to buf.subarray(1, 4).)
|
||||||
|
* ```
|
||||||
|
* @since v3.0.0
|
||||||
|
* @param [start=0] Where the new `Buffer` will start.
|
||||||
|
* @param [end=buf.length] Where the new `Buffer` will end (not inclusive).
|
||||||
|
*/
|
||||||
|
subarray(start?: number, end?: number): Buffer<TArrayBuffer>;
|
||||||
|
}
|
||||||
|
type NonSharedBuffer = Buffer<ArrayBuffer>;
|
||||||
|
type AllowSharedBuffer = Buffer<ArrayBufferLike>;
|
||||||
|
}
|
||||||
|
/** @deprecated Use `Buffer.allocUnsafeSlow()` instead. */
|
||||||
|
var SlowBuffer: {
|
||||||
|
/** @deprecated Use `Buffer.allocUnsafeSlow()` instead. */
|
||||||
|
new(size: number): Buffer<ArrayBuffer>;
|
||||||
|
prototype: Buffer;
|
||||||
|
};
|
||||||
|
}
|
||||||
1932
node_modules/@types/node/buffer.d.ts
generated
vendored
Normal file
1932
node_modules/@types/node/buffer.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1452
node_modules/@types/node/child_process.d.ts
generated
vendored
Normal file
1452
node_modules/@types/node/child_process.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
578
node_modules/@types/node/cluster.d.ts
generated
vendored
Normal file
578
node_modules/@types/node/cluster.d.ts
generated
vendored
Normal file
@@ -0,0 +1,578 @@
|
|||||||
|
/**
|
||||||
|
* Clusters of Node.js processes can be used to run multiple instances of Node.js
|
||||||
|
* that can distribute workloads among their application threads. When process isolation
|
||||||
|
* is not needed, use the [`worker_threads`](https://nodejs.org/docs/latest-v20.x/api/worker_threads.html)
|
||||||
|
* module instead, which allows running multiple application threads within a single Node.js instance.
|
||||||
|
*
|
||||||
|
* The cluster module allows easy creation of child processes that all share
|
||||||
|
* server ports.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
* import http from 'node:http';
|
||||||
|
* import { availableParallelism } from 'node:os';
|
||||||
|
* import process from 'node:process';
|
||||||
|
*
|
||||||
|
* const numCPUs = availableParallelism();
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* console.log(`Primary ${process.pid} is running`);
|
||||||
|
*
|
||||||
|
* // Fork workers.
|
||||||
|
* for (let i = 0; i < numCPUs; i++) {
|
||||||
|
* cluster.fork();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* cluster.on('exit', (worker, code, signal) => {
|
||||||
|
* console.log(`worker ${worker.process.pid} died`);
|
||||||
|
* });
|
||||||
|
* } else {
|
||||||
|
* // Workers can share any TCP connection
|
||||||
|
* // In this case it is an HTTP server
|
||||||
|
* http.createServer((req, res) => {
|
||||||
|
* res.writeHead(200);
|
||||||
|
* res.end('hello world\n');
|
||||||
|
* }).listen(8000);
|
||||||
|
*
|
||||||
|
* console.log(`Worker ${process.pid} started`);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Running Node.js will now share port 8000 between the workers:
|
||||||
|
*
|
||||||
|
* ```console
|
||||||
|
* $ node server.js
|
||||||
|
* Primary 3596 is running
|
||||||
|
* Worker 4324 started
|
||||||
|
* Worker 4520 started
|
||||||
|
* Worker 6056 started
|
||||||
|
* Worker 5644 started
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* On Windows, it is not yet possible to set up a named pipe server in a worker.
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/cluster.js)
|
||||||
|
*/
|
||||||
|
declare module "cluster" {
|
||||||
|
import * as child from "node:child_process";
|
||||||
|
import EventEmitter = require("node:events");
|
||||||
|
import * as net from "node:net";
|
||||||
|
type SerializationType = "json" | "advanced";
|
||||||
|
export interface ClusterSettings {
|
||||||
|
/**
|
||||||
|
* List of string arguments passed to the Node.js executable.
|
||||||
|
* @default process.execArgv
|
||||||
|
*/
|
||||||
|
execArgv?: string[] | undefined;
|
||||||
|
/**
|
||||||
|
* File path to worker file.
|
||||||
|
* @default process.argv[1]
|
||||||
|
*/
|
||||||
|
exec?: string | undefined;
|
||||||
|
/**
|
||||||
|
* String arguments passed to worker.
|
||||||
|
* @default process.argv.slice(2)
|
||||||
|
*/
|
||||||
|
args?: string[] | undefined;
|
||||||
|
/**
|
||||||
|
* Whether or not to send output to parent's stdio.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
silent?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Configures the stdio of forked processes. Because the cluster module relies on IPC to function, this configuration must
|
||||||
|
* contain an `'ipc'` entry. When this option is provided, it overrides `silent`. See [`child_prcess.spawn()`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#child_processspawncommand-args-options)'s
|
||||||
|
* [`stdio`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#optionsstdio).
|
||||||
|
*/
|
||||||
|
stdio?: any[] | undefined;
|
||||||
|
/**
|
||||||
|
* Sets the user identity of the process. (See [`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html).)
|
||||||
|
*/
|
||||||
|
uid?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Sets the group identity of the process. (See [`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html).)
|
||||||
|
*/
|
||||||
|
gid?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Sets inspector port of worker. This can be a number, or a function that takes no arguments and returns a number.
|
||||||
|
* By default each worker gets its own port, incremented from the primary's `process.debugPort`.
|
||||||
|
*/
|
||||||
|
inspectPort?: number | (() => number) | undefined;
|
||||||
|
/**
|
||||||
|
* Specify the kind of serialization used for sending messages between processes. Possible values are `'json'` and `'advanced'`.
|
||||||
|
* See [Advanced serialization for `child_process`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#advanced-serialization) for more details.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
serialization?: SerializationType | undefined;
|
||||||
|
/**
|
||||||
|
* Current working directory of the worker process.
|
||||||
|
* @default undefined (inherits from parent process)
|
||||||
|
*/
|
||||||
|
cwd?: string | undefined;
|
||||||
|
/**
|
||||||
|
* Hide the forked processes console window that would normally be created on Windows systems.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
windowsHide?: boolean | undefined;
|
||||||
|
}
|
||||||
|
export interface Address {
|
||||||
|
address: string;
|
||||||
|
port: number;
|
||||||
|
/**
|
||||||
|
* The `addressType` is one of:
|
||||||
|
*
|
||||||
|
* * `4` (TCPv4)
|
||||||
|
* * `6` (TCPv6)
|
||||||
|
* * `-1` (Unix domain socket)
|
||||||
|
* * `'udp4'` or `'udp6'` (UDPv4 or UDPv6)
|
||||||
|
*/
|
||||||
|
addressType: 4 | 6 | -1 | "udp4" | "udp6";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A `Worker` object contains all public information and method about a worker.
|
||||||
|
* In the primary it can be obtained using `cluster.workers`. In a worker
|
||||||
|
* it can be obtained using `cluster.worker`.
|
||||||
|
* @since v0.7.0
|
||||||
|
*/
|
||||||
|
export class Worker extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* Each new worker is given its own unique id, this id is stored in the `id`.
|
||||||
|
*
|
||||||
|
* While a worker is alive, this is the key that indexes it in `cluster.workers`.
|
||||||
|
* @since v0.8.0
|
||||||
|
*/
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* All workers are created using [`child_process.fork()`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#child_processforkmodulepath-args-options), the returned object
|
||||||
|
* from this function is stored as `.process`. In a worker, the global `process` is stored.
|
||||||
|
*
|
||||||
|
* See: [Child Process module](https://nodejs.org/docs/latest-v20.x/api/child_process.html#child_processforkmodulepath-args-options).
|
||||||
|
*
|
||||||
|
* Workers will call `process.exit(0)` if the `'disconnect'` event occurs
|
||||||
|
* on `process` and `.exitedAfterDisconnect` is not `true`. This protects against
|
||||||
|
* accidental disconnection.
|
||||||
|
* @since v0.7.0
|
||||||
|
*/
|
||||||
|
process: child.ChildProcess;
|
||||||
|
/**
|
||||||
|
* Send a message to a worker or primary, optionally with a handle.
|
||||||
|
*
|
||||||
|
* In the primary, this sends a message to a specific worker. It is identical to [`ChildProcess.send()`](https://nodejs.org/docs/latest-v20.x/api/child_process.html#subprocesssendmessage-sendhandle-options-callback).
|
||||||
|
*
|
||||||
|
* In a worker, this sends a message to the primary. It is identical to `process.send()`.
|
||||||
|
*
|
||||||
|
* This example will echo back all messages from the primary:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* const worker = cluster.fork();
|
||||||
|
* worker.send('hi there');
|
||||||
|
*
|
||||||
|
* } else if (cluster.isWorker) {
|
||||||
|
* process.on('message', (msg) => {
|
||||||
|
* process.send(msg);
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.7.0
|
||||||
|
* @param options The `options` argument, if present, is an object used to parameterize the sending of certain types of handles.
|
||||||
|
*/
|
||||||
|
send(message: child.Serializable, callback?: (error: Error | null) => void): boolean;
|
||||||
|
send(
|
||||||
|
message: child.Serializable,
|
||||||
|
sendHandle: child.SendHandle,
|
||||||
|
callback?: (error: Error | null) => void,
|
||||||
|
): boolean;
|
||||||
|
send(
|
||||||
|
message: child.Serializable,
|
||||||
|
sendHandle: child.SendHandle,
|
||||||
|
options?: child.MessageOptions,
|
||||||
|
callback?: (error: Error | null) => void,
|
||||||
|
): boolean;
|
||||||
|
/**
|
||||||
|
* This function will kill the worker. In the primary worker, it does this by
|
||||||
|
* disconnecting the `worker.process`, and once disconnected, killing with `signal`. In the worker, it does it by killing the process with `signal`.
|
||||||
|
*
|
||||||
|
* The `kill()` function kills the worker process without waiting for a graceful
|
||||||
|
* disconnect, it has the same behavior as `worker.process.kill()`.
|
||||||
|
*
|
||||||
|
* This method is aliased as `worker.destroy()` for backwards compatibility.
|
||||||
|
*
|
||||||
|
* In a worker, `process.kill()` exists, but it is not this function;
|
||||||
|
* it is [`kill()`](https://nodejs.org/docs/latest-v20.x/api/process.html#processkillpid-signal).
|
||||||
|
* @since v0.9.12
|
||||||
|
* @param [signal='SIGTERM'] Name of the kill signal to send to the worker process.
|
||||||
|
*/
|
||||||
|
kill(signal?: string): void;
|
||||||
|
destroy(signal?: string): void;
|
||||||
|
/**
|
||||||
|
* In a worker, this function will close all servers, wait for the `'close'` event
|
||||||
|
* on those servers, and then disconnect the IPC channel.
|
||||||
|
*
|
||||||
|
* In the primary, an internal message is sent to the worker causing it to call `.disconnect()` on itself.
|
||||||
|
*
|
||||||
|
* Causes `.exitedAfterDisconnect` to be set.
|
||||||
|
*
|
||||||
|
* After a server is closed, it will no longer accept new connections,
|
||||||
|
* but connections may be accepted by any other listening worker. Existing
|
||||||
|
* connections will be allowed to close as usual. When no more connections exist,
|
||||||
|
* see `server.close()`, the IPC channel to the worker will close allowing it
|
||||||
|
* to die gracefully.
|
||||||
|
*
|
||||||
|
* The above applies _only_ to server connections, client connections are not
|
||||||
|
* automatically closed by workers, and disconnect does not wait for them to close
|
||||||
|
* before exiting.
|
||||||
|
*
|
||||||
|
* In a worker, `process.disconnect` exists, but it is not this function;
|
||||||
|
* it is `disconnect()`.
|
||||||
|
*
|
||||||
|
* Because long living server connections may block workers from disconnecting, it
|
||||||
|
* may be useful to send a message, so application specific actions may be taken to
|
||||||
|
* close them. It also may be useful to implement a timeout, killing a worker if
|
||||||
|
* the `'disconnect'` event has not been emitted after some time.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import net from 'node:net';
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* const worker = cluster.fork();
|
||||||
|
* let timeout;
|
||||||
|
*
|
||||||
|
* worker.on('listening', (address) => {
|
||||||
|
* worker.send('shutdown');
|
||||||
|
* worker.disconnect();
|
||||||
|
* timeout = setTimeout(() => {
|
||||||
|
* worker.kill();
|
||||||
|
* }, 2000);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* worker.on('disconnect', () => {
|
||||||
|
* clearTimeout(timeout);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* } else if (cluster.isWorker) {
|
||||||
|
* const server = net.createServer((socket) => {
|
||||||
|
* // Connections never end
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.listen(8000);
|
||||||
|
*
|
||||||
|
* process.on('message', (msg) => {
|
||||||
|
* if (msg === 'shutdown') {
|
||||||
|
* // Initiate graceful close of any connections to server
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.7.7
|
||||||
|
* @return A reference to `worker`.
|
||||||
|
*/
|
||||||
|
disconnect(): this;
|
||||||
|
/**
|
||||||
|
* This function returns `true` if the worker is connected to its primary via its
|
||||||
|
* IPC channel, `false` otherwise. A worker is connected to its primary after it
|
||||||
|
* has been created. It is disconnected after the `'disconnect'` event is emitted.
|
||||||
|
* @since v0.11.14
|
||||||
|
*/
|
||||||
|
isConnected(): boolean;
|
||||||
|
/**
|
||||||
|
* This function returns `true` if the worker's process has terminated (either
|
||||||
|
* because of exiting or being signaled). Otherwise, it returns `false`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
* import http from 'node:http';
|
||||||
|
* import { availableParallelism } from 'node:os';
|
||||||
|
* import process from 'node:process';
|
||||||
|
*
|
||||||
|
* const numCPUs = availableParallelism();
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* console.log(`Primary ${process.pid} is running`);
|
||||||
|
*
|
||||||
|
* // Fork workers.
|
||||||
|
* for (let i = 0; i < numCPUs; i++) {
|
||||||
|
* cluster.fork();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* cluster.on('fork', (worker) => {
|
||||||
|
* console.log('worker is dead:', worker.isDead());
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* cluster.on('exit', (worker, code, signal) => {
|
||||||
|
* console.log('worker is dead:', worker.isDead());
|
||||||
|
* });
|
||||||
|
* } else {
|
||||||
|
* // Workers can share any TCP connection. In this case, it is an HTTP server.
|
||||||
|
* http.createServer((req, res) => {
|
||||||
|
* res.writeHead(200);
|
||||||
|
* res.end(`Current process\n ${process.pid}`);
|
||||||
|
* process.kill(process.pid);
|
||||||
|
* }).listen(8000);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.11.14
|
||||||
|
*/
|
||||||
|
isDead(): boolean;
|
||||||
|
/**
|
||||||
|
* This property is `true` if the worker exited due to `.disconnect()`.
|
||||||
|
* If the worker exited any other way, it is `false`. If the
|
||||||
|
* worker has not exited, it is `undefined`.
|
||||||
|
*
|
||||||
|
* The boolean `worker.exitedAfterDisconnect` allows distinguishing between
|
||||||
|
* voluntary and accidental exit, the primary may choose not to respawn a worker
|
||||||
|
* based on this value.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* cluster.on('exit', (worker, code, signal) => {
|
||||||
|
* if (worker.exitedAfterDisconnect === true) {
|
||||||
|
* console.log('Oh, it was just voluntary – no need to worry');
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // kill worker
|
||||||
|
* worker.kill();
|
||||||
|
* ```
|
||||||
|
* @since v6.0.0
|
||||||
|
*/
|
||||||
|
exitedAfterDisconnect: boolean;
|
||||||
|
/**
|
||||||
|
* events.EventEmitter
|
||||||
|
* 1. disconnect
|
||||||
|
* 2. error
|
||||||
|
* 3. exit
|
||||||
|
* 4. listening
|
||||||
|
* 5. message
|
||||||
|
* 6. online
|
||||||
|
*/
|
||||||
|
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
addListener(event: "disconnect", listener: () => void): this;
|
||||||
|
addListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
addListener(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
addListener(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
addListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
addListener(event: "online", listener: () => void): this;
|
||||||
|
emit(event: string | symbol, ...args: any[]): boolean;
|
||||||
|
emit(event: "disconnect"): boolean;
|
||||||
|
emit(event: "error", error: Error): boolean;
|
||||||
|
emit(event: "exit", code: number, signal: string): boolean;
|
||||||
|
emit(event: "listening", address: Address): boolean;
|
||||||
|
emit(event: "message", message: any, handle: net.Socket | net.Server): boolean;
|
||||||
|
emit(event: "online"): boolean;
|
||||||
|
on(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
on(event: "disconnect", listener: () => void): this;
|
||||||
|
on(event: "error", listener: (error: Error) => void): this;
|
||||||
|
on(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
on(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
on(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
on(event: "online", listener: () => void): this;
|
||||||
|
once(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
once(event: "disconnect", listener: () => void): this;
|
||||||
|
once(event: "error", listener: (error: Error) => void): this;
|
||||||
|
once(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
once(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
once(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
once(event: "online", listener: () => void): this;
|
||||||
|
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependListener(event: "disconnect", listener: () => void): this;
|
||||||
|
prependListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
prependListener(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
prependListener(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
prependListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
prependListener(event: "online", listener: () => void): this;
|
||||||
|
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependOnceListener(event: "disconnect", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
prependOnceListener(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
prependOnceListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
prependOnceListener(event: "online", listener: () => void): this;
|
||||||
|
}
|
||||||
|
export interface Cluster extends EventEmitter {
|
||||||
|
disconnect(callback?: () => void): void;
|
||||||
|
/**
|
||||||
|
* Spawn a new worker process.
|
||||||
|
*
|
||||||
|
* This can only be called from the primary process.
|
||||||
|
* @param env Key/value pairs to add to worker process environment.
|
||||||
|
* @since v0.6.0
|
||||||
|
*/
|
||||||
|
fork(env?: any): Worker;
|
||||||
|
/** @deprecated since v16.0.0 - use isPrimary. */
|
||||||
|
readonly isMaster: boolean;
|
||||||
|
/**
|
||||||
|
* True if the process is a primary. This is determined by the `process.env.NODE_UNIQUE_ID`. If `process.env.NODE_UNIQUE_ID`
|
||||||
|
* is undefined, then `isPrimary` is `true`.
|
||||||
|
* @since v16.0.0
|
||||||
|
*/
|
||||||
|
readonly isPrimary: boolean;
|
||||||
|
/**
|
||||||
|
* True if the process is not a primary (it is the negation of `cluster.isPrimary`).
|
||||||
|
* @since v0.6.0
|
||||||
|
*/
|
||||||
|
readonly isWorker: boolean;
|
||||||
|
/**
|
||||||
|
* The scheduling policy, either `cluster.SCHED_RR` for round-robin or `cluster.SCHED_NONE` to leave it to the operating system. This is a
|
||||||
|
* global setting and effectively frozen once either the first worker is spawned, or [`.setupPrimary()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clustersetupprimarysettings)
|
||||||
|
* is called, whichever comes first.
|
||||||
|
*
|
||||||
|
* `SCHED_RR` is the default on all operating systems except Windows. Windows will change to `SCHED_RR` once libuv is able to effectively distribute
|
||||||
|
* IOCP handles without incurring a large performance hit.
|
||||||
|
*
|
||||||
|
* `cluster.schedulingPolicy` can also be set through the `NODE_CLUSTER_SCHED_POLICY` environment variable. Valid values are `'rr'` and `'none'`.
|
||||||
|
* @since v0.11.2
|
||||||
|
*/
|
||||||
|
schedulingPolicy: number;
|
||||||
|
/**
|
||||||
|
* After calling [`.setupPrimary()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clustersetupprimarysettings)
|
||||||
|
* (or [`.fork()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clusterforkenv)) this settings object will contain
|
||||||
|
* the settings, including the default values.
|
||||||
|
*
|
||||||
|
* This object is not intended to be changed or set manually.
|
||||||
|
* @since v0.7.1
|
||||||
|
*/
|
||||||
|
readonly settings: ClusterSettings;
|
||||||
|
/** @deprecated since v16.0.0 - use [`.setupPrimary()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clustersetupprimarysettings) instead. */
|
||||||
|
setupMaster(settings?: ClusterSettings): void;
|
||||||
|
/**
|
||||||
|
* `setupPrimary` is used to change the default 'fork' behavior. Once called, the settings will be present in `cluster.settings`.
|
||||||
|
*
|
||||||
|
* Any settings changes only affect future calls to [`.fork()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clusterforkenv)
|
||||||
|
* and have no effect on workers that are already running.
|
||||||
|
*
|
||||||
|
* The only attribute of a worker that cannot be set via `.setupPrimary()` is the `env` passed to
|
||||||
|
* [`.fork()`](https://nodejs.org/docs/latest-v20.x/api/cluster.html#clusterforkenv).
|
||||||
|
*
|
||||||
|
* The defaults above apply to the first call only; the defaults for later calls are the current values at the time of
|
||||||
|
* `cluster.setupPrimary()` is called.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
*
|
||||||
|
* cluster.setupPrimary({
|
||||||
|
* exec: 'worker.js',
|
||||||
|
* args: ['--use', 'https'],
|
||||||
|
* silent: true,
|
||||||
|
* });
|
||||||
|
* cluster.fork(); // https worker
|
||||||
|
* cluster.setupPrimary({
|
||||||
|
* exec: 'worker.js',
|
||||||
|
* args: ['--use', 'http'],
|
||||||
|
* });
|
||||||
|
* cluster.fork(); // http worker
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This can only be called from the primary process.
|
||||||
|
* @since v16.0.0
|
||||||
|
*/
|
||||||
|
setupPrimary(settings?: ClusterSettings): void;
|
||||||
|
/**
|
||||||
|
* A reference to the current worker object. Not available in the primary process.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* console.log('I am primary');
|
||||||
|
* cluster.fork();
|
||||||
|
* cluster.fork();
|
||||||
|
* } else if (cluster.isWorker) {
|
||||||
|
* console.log(`I am worker #${cluster.worker.id}`);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.7.0
|
||||||
|
*/
|
||||||
|
readonly worker?: Worker | undefined;
|
||||||
|
/**
|
||||||
|
* A hash that stores the active worker objects, keyed by `id` field. This makes it easy to loop through all the workers. It is only available in the primary process.
|
||||||
|
*
|
||||||
|
* A worker is removed from `cluster.workers` after the worker has disconnected _and_ exited. The order between these two events cannot be determined in advance. However, it
|
||||||
|
* is guaranteed that the removal from the `cluster.workers` list happens before the last `'disconnect'` or `'exit'` event is emitted.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
*
|
||||||
|
* for (const worker of Object.values(cluster.workers)) {
|
||||||
|
* worker.send('big announcement to all workers');
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.7.0
|
||||||
|
*/
|
||||||
|
readonly workers?: NodeJS.Dict<Worker> | undefined;
|
||||||
|
readonly SCHED_NONE: number;
|
||||||
|
readonly SCHED_RR: number;
|
||||||
|
/**
|
||||||
|
* events.EventEmitter
|
||||||
|
* 1. disconnect
|
||||||
|
* 2. exit
|
||||||
|
* 3. fork
|
||||||
|
* 4. listening
|
||||||
|
* 5. message
|
||||||
|
* 6. online
|
||||||
|
* 7. setup
|
||||||
|
*/
|
||||||
|
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
addListener(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
addListener(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
addListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
addListener(
|
||||||
|
event: "message",
|
||||||
|
listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void,
|
||||||
|
): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
addListener(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
addListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
emit(event: string | symbol, ...args: any[]): boolean;
|
||||||
|
emit(event: "disconnect", worker: Worker): boolean;
|
||||||
|
emit(event: "exit", worker: Worker, code: number, signal: string): boolean;
|
||||||
|
emit(event: "fork", worker: Worker): boolean;
|
||||||
|
emit(event: "listening", worker: Worker, address: Address): boolean;
|
||||||
|
emit(event: "message", worker: Worker, message: any, handle: net.Socket | net.Server): boolean;
|
||||||
|
emit(event: "online", worker: Worker): boolean;
|
||||||
|
emit(event: "setup", settings: ClusterSettings): boolean;
|
||||||
|
on(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
on(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
on(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
on(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
on(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
on(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
once(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
once(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
once(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
once(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
once(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
once(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependListener(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
prependListener(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
// the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
prependListener(
|
||||||
|
event: "message",
|
||||||
|
listener: (worker: Worker, message: any, handle?: net.Socket | net.Server) => void,
|
||||||
|
): this;
|
||||||
|
prependListener(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
prependListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
prependOnceListener(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
// the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
prependOnceListener(
|
||||||
|
event: "message",
|
||||||
|
listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void,
|
||||||
|
): this;
|
||||||
|
prependOnceListener(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
prependOnceListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
}
|
||||||
|
const cluster: Cluster;
|
||||||
|
export default cluster;
|
||||||
|
}
|
||||||
|
declare module "node:cluster" {
|
||||||
|
export * from "cluster";
|
||||||
|
export { default as default } from "cluster";
|
||||||
|
}
|
||||||
452
node_modules/@types/node/console.d.ts
generated
vendored
Normal file
452
node_modules/@types/node/console.d.ts
generated
vendored
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
/**
|
||||||
|
* The `node:console` module provides a simple debugging console that is similar to
|
||||||
|
* the JavaScript console mechanism provided by web browsers.
|
||||||
|
*
|
||||||
|
* The module exports two specific components:
|
||||||
|
*
|
||||||
|
* * A `Console` class with methods such as `console.log()`, `console.error()`, and `console.warn()` that can be used to write to any Node.js stream.
|
||||||
|
* * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and
|
||||||
|
* [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
|
||||||
|
*
|
||||||
|
* _**Warning**_: The global console object's methods are neither consistently
|
||||||
|
* synchronous like the browser APIs they resemble, nor are they consistently
|
||||||
|
* asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for
|
||||||
|
* more information.
|
||||||
|
*
|
||||||
|
* Example using the global `console`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.log('hello world');
|
||||||
|
* // Prints: hello world, to stdout
|
||||||
|
* console.log('hello %s', 'world');
|
||||||
|
* // Prints: hello world, to stdout
|
||||||
|
* console.error(new Error('Whoops, something bad happened'));
|
||||||
|
* // Prints error message and stack trace to stderr:
|
||||||
|
* // Error: Whoops, something bad happened
|
||||||
|
* // at [eval]:5:15
|
||||||
|
* // at Script.runInThisContext (node:vm:132:18)
|
||||||
|
* // at Object.runInThisContext (node:vm:309:38)
|
||||||
|
* // at node:internal/process/execution:77:19
|
||||||
|
* // at [eval]-wrapper:6:22
|
||||||
|
* // at evalScript (node:internal/process/execution:76:60)
|
||||||
|
* // at node:internal/main/eval_string:23:3
|
||||||
|
*
|
||||||
|
* const name = 'Will Robinson';
|
||||||
|
* console.warn(`Danger ${name}! Danger!`);
|
||||||
|
* // Prints: Danger Will Robinson! Danger!, to stderr
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example using the `Console` class:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const out = getStreamSomehow();
|
||||||
|
* const err = getStreamSomehow();
|
||||||
|
* const myConsole = new console.Console(out, err);
|
||||||
|
*
|
||||||
|
* myConsole.log('hello world');
|
||||||
|
* // Prints: hello world, to out
|
||||||
|
* myConsole.log('hello %s', 'world');
|
||||||
|
* // Prints: hello world, to out
|
||||||
|
* myConsole.error(new Error('Whoops, something bad happened'));
|
||||||
|
* // Prints: [Error: Whoops, something bad happened], to err
|
||||||
|
*
|
||||||
|
* const name = 'Will Robinson';
|
||||||
|
* myConsole.warn(`Danger ${name}! Danger!`);
|
||||||
|
* // Prints: Danger Will Robinson! Danger!, to err
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/console.js)
|
||||||
|
*/
|
||||||
|
declare module "console" {
|
||||||
|
import console = require("node:console");
|
||||||
|
export = console;
|
||||||
|
}
|
||||||
|
declare module "node:console" {
|
||||||
|
import { InspectOptions } from "node:util";
|
||||||
|
global {
|
||||||
|
// This needs to be global to avoid TS2403 in case lib.dom.d.ts is present in the same build
|
||||||
|
interface Console {
|
||||||
|
Console: console.ConsoleConstructor;
|
||||||
|
/**
|
||||||
|
* `console.assert()` writes a message if `value` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) or omitted. It only
|
||||||
|
* writes a message and does not otherwise affect execution. The output always
|
||||||
|
* starts with `"Assertion failed"`. If provided, `message` is formatted using
|
||||||
|
* [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args).
|
||||||
|
*
|
||||||
|
* If `value` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), nothing happens.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.assert(true, 'does nothing');
|
||||||
|
*
|
||||||
|
* console.assert(false, 'Whoops %s work', 'didn\'t');
|
||||||
|
* // Assertion failed: Whoops didn't work
|
||||||
|
*
|
||||||
|
* console.assert();
|
||||||
|
* // Assertion failed
|
||||||
|
* ```
|
||||||
|
* @since v0.1.101
|
||||||
|
* @param value The value tested for being truthy.
|
||||||
|
* @param message All arguments besides `value` are used as error message.
|
||||||
|
*/
|
||||||
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* When `stdout` is a TTY, calling `console.clear()` will attempt to clear the
|
||||||
|
* TTY. When `stdout` is not a TTY, this method does nothing.
|
||||||
|
*
|
||||||
|
* The specific operation of `console.clear()` can vary across operating systems
|
||||||
|
* and terminal types. For most Linux operating systems, `console.clear()` operates similarly to the `clear` shell command. On Windows, `console.clear()` will clear only the output in the
|
||||||
|
* current terminal viewport for the Node.js
|
||||||
|
* binary.
|
||||||
|
* @since v8.3.0
|
||||||
|
*/
|
||||||
|
clear(): void;
|
||||||
|
/**
|
||||||
|
* Maintains an internal counter specific to `label` and outputs to `stdout` the
|
||||||
|
* number of times `console.count()` has been called with the given `label`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* > console.count()
|
||||||
|
* default: 1
|
||||||
|
* undefined
|
||||||
|
* > console.count('default')
|
||||||
|
* default: 2
|
||||||
|
* undefined
|
||||||
|
* > console.count('abc')
|
||||||
|
* abc: 1
|
||||||
|
* undefined
|
||||||
|
* > console.count('xyz')
|
||||||
|
* xyz: 1
|
||||||
|
* undefined
|
||||||
|
* > console.count('abc')
|
||||||
|
* abc: 2
|
||||||
|
* undefined
|
||||||
|
* > console.count()
|
||||||
|
* default: 3
|
||||||
|
* undefined
|
||||||
|
* >
|
||||||
|
* ```
|
||||||
|
* @since v8.3.0
|
||||||
|
* @param [label='default'] The display label for the counter.
|
||||||
|
*/
|
||||||
|
count(label?: string): void;
|
||||||
|
/**
|
||||||
|
* Resets the internal counter specific to `label`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* > console.count('abc');
|
||||||
|
* abc: 1
|
||||||
|
* undefined
|
||||||
|
* > console.countReset('abc');
|
||||||
|
* undefined
|
||||||
|
* > console.count('abc');
|
||||||
|
* abc: 1
|
||||||
|
* undefined
|
||||||
|
* >
|
||||||
|
* ```
|
||||||
|
* @since v8.3.0
|
||||||
|
* @param [label='default'] The display label for the counter.
|
||||||
|
*/
|
||||||
|
countReset(label?: string): void;
|
||||||
|
/**
|
||||||
|
* The `console.debug()` function is an alias for {@link log}.
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
debug(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* Uses [`util.inspect()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilinspectobject-options) on `obj` and prints the resulting string to `stdout`.
|
||||||
|
* This function bypasses any custom `inspect()` function defined on `obj`.
|
||||||
|
* @since v0.1.101
|
||||||
|
*/
|
||||||
|
dir(obj: any, options?: InspectOptions): void;
|
||||||
|
/**
|
||||||
|
* This method calls `console.log()` passing it the arguments received.
|
||||||
|
* This method does not produce any XML formatting.
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
dirxml(...data: any[]): void;
|
||||||
|
/**
|
||||||
|
* Prints to `stderr` with newline. Multiple arguments can be passed, with the
|
||||||
|
* first used as the primary message and all additional used as substitution
|
||||||
|
* values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
|
||||||
|
* (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)).
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const code = 5;
|
||||||
|
* console.error('error #%d', code);
|
||||||
|
* // Prints: error #5, to stderr
|
||||||
|
* console.error('error', code);
|
||||||
|
* // Prints: error 5, to stderr
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If formatting elements (e.g. `%d`) are not found in the first string then
|
||||||
|
* [`util.inspect()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilinspectobject-options) is called on each argument and the
|
||||||
|
* resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)
|
||||||
|
* for more information.
|
||||||
|
* @since v0.1.100
|
||||||
|
*/
|
||||||
|
error(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* Increases indentation of subsequent lines by spaces for `groupIndentation` length.
|
||||||
|
*
|
||||||
|
* If one or more `label`s are provided, those are printed first without the
|
||||||
|
* additional indentation.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
group(...label: any[]): void;
|
||||||
|
/**
|
||||||
|
* An alias for {@link group}.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
groupCollapsed(...label: any[]): void;
|
||||||
|
/**
|
||||||
|
* Decreases indentation of subsequent lines by spaces for `groupIndentation` length.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
groupEnd(): void;
|
||||||
|
/**
|
||||||
|
* The `console.info()` function is an alias for {@link log}.
|
||||||
|
* @since v0.1.100
|
||||||
|
*/
|
||||||
|
info(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* Prints to `stdout` with newline. Multiple arguments can be passed, with the
|
||||||
|
* first used as the primary message and all additional used as substitution
|
||||||
|
* values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
|
||||||
|
* (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)).
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const count = 5;
|
||||||
|
* console.log('count: %d', count);
|
||||||
|
* // Prints: count: 5, to stdout
|
||||||
|
* console.log('count:', count);
|
||||||
|
* // Prints: count: 5, to stdout
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
|
||||||
|
* @since v0.1.100
|
||||||
|
*/
|
||||||
|
log(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just
|
||||||
|
* logging the argument if it can't be parsed as tabular.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // These can't be parsed as tabular data
|
||||||
|
* console.table(Symbol());
|
||||||
|
* // Symbol()
|
||||||
|
*
|
||||||
|
* console.table(undefined);
|
||||||
|
* // undefined
|
||||||
|
*
|
||||||
|
* console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]);
|
||||||
|
* // ┌─────────┬─────┬─────┐
|
||||||
|
* // │ (index) │ a │ b │
|
||||||
|
* // ├─────────┼─────┼─────┤
|
||||||
|
* // │ 0 │ 1 │ 'Y' │
|
||||||
|
* // │ 1 │ 'Z' │ 2 │
|
||||||
|
* // └─────────┴─────┴─────┘
|
||||||
|
*
|
||||||
|
* console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']);
|
||||||
|
* // ┌─────────┬─────┐
|
||||||
|
* // │ (index) │ a │
|
||||||
|
* // ├─────────┼─────┤
|
||||||
|
* // │ 0 │ 1 │
|
||||||
|
* // │ 1 │ 'Z' │
|
||||||
|
* // └─────────┴─────┘
|
||||||
|
* ```
|
||||||
|
* @since v10.0.0
|
||||||
|
* @param properties Alternate properties for constructing the table.
|
||||||
|
*/
|
||||||
|
table(tabularData: any, properties?: readonly string[]): void;
|
||||||
|
/**
|
||||||
|
* Starts a timer that can be used to compute the duration of an operation. Timers
|
||||||
|
* are identified by a unique `label`. Use the same `label` when calling {@link timeEnd} to stop the timer and output the elapsed time in
|
||||||
|
* suitable time units to `stdout`. For example, if the elapsed
|
||||||
|
* time is 3869ms, `console.timeEnd()` displays "3.869s".
|
||||||
|
* @since v0.1.104
|
||||||
|
* @param [label='default']
|
||||||
|
*/
|
||||||
|
time(label?: string): void;
|
||||||
|
/**
|
||||||
|
* Stops a timer that was previously started by calling {@link time} and
|
||||||
|
* prints the result to `stdout`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.time('bunch-of-stuff');
|
||||||
|
* // Do a bunch of stuff.
|
||||||
|
* console.timeEnd('bunch-of-stuff');
|
||||||
|
* // Prints: bunch-of-stuff: 225.438ms
|
||||||
|
* ```
|
||||||
|
* @since v0.1.104
|
||||||
|
* @param [label='default']
|
||||||
|
*/
|
||||||
|
timeEnd(label?: string): void;
|
||||||
|
/**
|
||||||
|
* For a timer that was previously started by calling {@link time}, prints
|
||||||
|
* the elapsed time and other `data` arguments to `stdout`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.time('process');
|
||||||
|
* const value = expensiveProcess1(); // Returns 42
|
||||||
|
* console.timeLog('process', value);
|
||||||
|
* // Prints "process: 365.227ms 42".
|
||||||
|
* doExpensiveProcess2(value);
|
||||||
|
* console.timeEnd('process');
|
||||||
|
* ```
|
||||||
|
* @since v10.7.0
|
||||||
|
* @param [label='default']
|
||||||
|
*/
|
||||||
|
timeLog(label?: string, ...data: any[]): void;
|
||||||
|
/**
|
||||||
|
* Prints to `stderr` the string `'Trace: '`, followed by the [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)
|
||||||
|
* formatted message and stack trace to the current position in the code.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.trace('Show me');
|
||||||
|
* // Prints: (stack trace will vary based on where trace is called)
|
||||||
|
* // Trace: Show me
|
||||||
|
* // at repl:2:9
|
||||||
|
* // at REPLServer.defaultEval (repl.js:248:27)
|
||||||
|
* // at bound (domain.js:287:14)
|
||||||
|
* // at REPLServer.runBound [as eval] (domain.js:300:12)
|
||||||
|
* // at REPLServer.<anonymous> (repl.js:412:12)
|
||||||
|
* // at emitOne (events.js:82:20)
|
||||||
|
* // at REPLServer.emit (events.js:169:7)
|
||||||
|
* // at REPLServer.Interface._onLine (readline.js:210:10)
|
||||||
|
* // at REPLServer.Interface._line (readline.js:549:8)
|
||||||
|
* // at REPLServer.Interface._ttyWrite (readline.js:826:14)
|
||||||
|
* ```
|
||||||
|
* @since v0.1.104
|
||||||
|
*/
|
||||||
|
trace(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* The `console.warn()` function is an alias for {@link error}.
|
||||||
|
* @since v0.1.100
|
||||||
|
*/
|
||||||
|
warn(message?: any, ...optionalParams: any[]): void;
|
||||||
|
// --- Inspector mode only ---
|
||||||
|
/**
|
||||||
|
* This method does not display anything unless used in the inspector. The `console.profile()`
|
||||||
|
* method starts a JavaScript CPU profile with an optional label until {@link profileEnd}
|
||||||
|
* is called. The profile is then added to the Profile panel of the inspector.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.profile('MyLabel');
|
||||||
|
* // Some code
|
||||||
|
* console.profileEnd('MyLabel');
|
||||||
|
* // Adds the profile 'MyLabel' to the Profiles panel of the inspector.
|
||||||
|
* ```
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
profile(label?: string): void;
|
||||||
|
/**
|
||||||
|
* This method does not display anything unless used in the inspector. Stops the current
|
||||||
|
* JavaScript CPU profiling session if one has been started and prints the report to the
|
||||||
|
* Profiles panel of the inspector. See {@link profile} for an example.
|
||||||
|
*
|
||||||
|
* If this method is called without a label, the most recently started profile is stopped.
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
profileEnd(label?: string): void;
|
||||||
|
/**
|
||||||
|
* This method does not display anything unless used in the inspector. The `console.timeStamp()`
|
||||||
|
* method adds an event with the label `'label'` to the Timeline panel of the inspector.
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
timeStamp(label?: string): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `console` module provides a simple debugging console that is similar to the
|
||||||
|
* JavaScript console mechanism provided by web browsers.
|
||||||
|
*
|
||||||
|
* The module exports two specific components:
|
||||||
|
*
|
||||||
|
* * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
|
||||||
|
* * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and
|
||||||
|
* [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
|
||||||
|
*
|
||||||
|
* _**Warning**_: The global console object's methods are neither consistently
|
||||||
|
* synchronous like the browser APIs they resemble, nor are they consistently
|
||||||
|
* asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for
|
||||||
|
* more information.
|
||||||
|
*
|
||||||
|
* Example using the global `console`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.log('hello world');
|
||||||
|
* // Prints: hello world, to stdout
|
||||||
|
* console.log('hello %s', 'world');
|
||||||
|
* // Prints: hello world, to stdout
|
||||||
|
* console.error(new Error('Whoops, something bad happened'));
|
||||||
|
* // Prints error message and stack trace to stderr:
|
||||||
|
* // Error: Whoops, something bad happened
|
||||||
|
* // at [eval]:5:15
|
||||||
|
* // at Script.runInThisContext (node:vm:132:18)
|
||||||
|
* // at Object.runInThisContext (node:vm:309:38)
|
||||||
|
* // at node:internal/process/execution:77:19
|
||||||
|
* // at [eval]-wrapper:6:22
|
||||||
|
* // at evalScript (node:internal/process/execution:76:60)
|
||||||
|
* // at node:internal/main/eval_string:23:3
|
||||||
|
*
|
||||||
|
* const name = 'Will Robinson';
|
||||||
|
* console.warn(`Danger ${name}! Danger!`);
|
||||||
|
* // Prints: Danger Will Robinson! Danger!, to stderr
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example using the `Console` class:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const out = getStreamSomehow();
|
||||||
|
* const err = getStreamSomehow();
|
||||||
|
* const myConsole = new console.Console(out, err);
|
||||||
|
*
|
||||||
|
* myConsole.log('hello world');
|
||||||
|
* // Prints: hello world, to out
|
||||||
|
* myConsole.log('hello %s', 'world');
|
||||||
|
* // Prints: hello world, to out
|
||||||
|
* myConsole.error(new Error('Whoops, something bad happened'));
|
||||||
|
* // Prints: [Error: Whoops, something bad happened], to err
|
||||||
|
*
|
||||||
|
* const name = 'Will Robinson';
|
||||||
|
* myConsole.warn(`Danger ${name}! Danger!`);
|
||||||
|
* // Prints: Danger Will Robinson! Danger!, to err
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
|
||||||
|
*/
|
||||||
|
namespace console {
|
||||||
|
interface ConsoleConstructorOptions {
|
||||||
|
stdout: NodeJS.WritableStream;
|
||||||
|
stderr?: NodeJS.WritableStream | undefined;
|
||||||
|
/**
|
||||||
|
* Ignore errors when writing to the underlying streams.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
ignoreErrors?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Set color support for this `Console` instance. Setting to true enables coloring while inspecting
|
||||||
|
* values. Setting to `false` disables coloring while inspecting values. Setting to `'auto'` makes color
|
||||||
|
* support depend on the value of the `isTTY` property and the value returned by `getColorDepth()` on the
|
||||||
|
* respective stream. This option can not be used, if `inspectOptions.colors` is set as well.
|
||||||
|
* @default auto
|
||||||
|
*/
|
||||||
|
colorMode?: boolean | "auto" | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies options that are passed along to
|
||||||
|
* [`util.inspect()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilinspectobject-options).
|
||||||
|
*/
|
||||||
|
inspectOptions?: InspectOptions | undefined;
|
||||||
|
/**
|
||||||
|
* Set group indentation.
|
||||||
|
* @default 2
|
||||||
|
*/
|
||||||
|
groupIndentation?: number | undefined;
|
||||||
|
}
|
||||||
|
interface ConsoleConstructor {
|
||||||
|
prototype: Console;
|
||||||
|
new(stdout: NodeJS.WritableStream, stderr?: NodeJS.WritableStream, ignoreErrors?: boolean): Console;
|
||||||
|
new(options: ConsoleConstructorOptions): Console;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var console: Console;
|
||||||
|
}
|
||||||
|
export = globalThis.console;
|
||||||
|
}
|
||||||
21
node_modules/@types/node/constants.d.ts
generated
vendored
Normal file
21
node_modules/@types/node/constants.d.ts
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* @deprecated The `node:constants` module is deprecated. When requiring access to constants
|
||||||
|
* relevant to specific Node.js builtin modules, developers should instead refer
|
||||||
|
* to the `constants` property exposed by the relevant module. For instance,
|
||||||
|
* `require('node:fs').constants` and `require('node:os').constants`.
|
||||||
|
*/
|
||||||
|
declare module "constants" {
|
||||||
|
const constants:
|
||||||
|
& typeof import("node:os").constants.dlopen
|
||||||
|
& typeof import("node:os").constants.errno
|
||||||
|
& typeof import("node:os").constants.priority
|
||||||
|
& typeof import("node:os").constants.signals
|
||||||
|
& typeof import("node:fs").constants
|
||||||
|
& typeof import("node:crypto").constants;
|
||||||
|
export = constants;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "node:constants" {
|
||||||
|
import constants = require("constants");
|
||||||
|
export = constants;
|
||||||
|
}
|
||||||
4570
node_modules/@types/node/crypto.d.ts
generated
vendored
Normal file
4570
node_modules/@types/node/crypto.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
596
node_modules/@types/node/dgram.d.ts
generated
vendored
Normal file
596
node_modules/@types/node/dgram.d.ts
generated
vendored
Normal file
@@ -0,0 +1,596 @@
|
|||||||
|
/**
|
||||||
|
* The `node:dgram` module provides an implementation of UDP datagram sockets.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
*
|
||||||
|
* const server = dgram.createSocket('udp4');
|
||||||
|
*
|
||||||
|
* server.on('error', (err) => {
|
||||||
|
* console.error(`server error:\n${err.stack}`);
|
||||||
|
* server.close();
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.on('message', (msg, rinfo) => {
|
||||||
|
* console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.on('listening', () => {
|
||||||
|
* const address = server.address();
|
||||||
|
* console.log(`server listening ${address.address}:${address.port}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.bind(41234);
|
||||||
|
* // Prints: server listening 0.0.0.0:41234
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/dgram.js)
|
||||||
|
*/
|
||||||
|
declare module "dgram" {
|
||||||
|
import { AddressInfo } from "node:net";
|
||||||
|
import * as dns from "node:dns";
|
||||||
|
import { Abortable, EventEmitter } from "node:events";
|
||||||
|
interface RemoteInfo {
|
||||||
|
address: string;
|
||||||
|
family: "IPv4" | "IPv6";
|
||||||
|
port: number;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
interface BindOptions {
|
||||||
|
port?: number | undefined;
|
||||||
|
address?: string | undefined;
|
||||||
|
exclusive?: boolean | undefined;
|
||||||
|
fd?: number | undefined;
|
||||||
|
}
|
||||||
|
type SocketType = "udp4" | "udp6";
|
||||||
|
interface SocketOptions extends Abortable {
|
||||||
|
type: SocketType;
|
||||||
|
reuseAddr?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
ipv6Only?: boolean | undefined;
|
||||||
|
recvBufferSize?: number | undefined;
|
||||||
|
sendBufferSize?: number | undefined;
|
||||||
|
lookup?:
|
||||||
|
| ((
|
||||||
|
hostname: string,
|
||||||
|
options: dns.LookupOneOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
|
||||||
|
) => void)
|
||||||
|
| undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a `dgram.Socket` object. Once the socket is created, calling `socket.bind()` will instruct the socket to begin listening for datagram
|
||||||
|
* messages. When `address` and `port` are not passed to `socket.bind()` the
|
||||||
|
* method will bind the socket to the "all interfaces" address on a random port
|
||||||
|
* (it does the right thing for both `udp4` and `udp6` sockets). The bound address
|
||||||
|
* and port can be retrieved using `socket.address().address` and `socket.address().port`.
|
||||||
|
*
|
||||||
|
* If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.close()` on the socket:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const controller = new AbortController();
|
||||||
|
* const { signal } = controller;
|
||||||
|
* const server = dgram.createSocket({ type: 'udp4', signal });
|
||||||
|
* server.on('message', (msg, rinfo) => {
|
||||||
|
* console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
|
||||||
|
* });
|
||||||
|
* // Later, when you want to close the server.
|
||||||
|
* controller.abort();
|
||||||
|
* ```
|
||||||
|
* @since v0.11.13
|
||||||
|
* @param options Available options are:
|
||||||
|
* @param callback Attached as a listener for `'message'` events. Optional.
|
||||||
|
*/
|
||||||
|
function createSocket(type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket;
|
||||||
|
function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket;
|
||||||
|
/**
|
||||||
|
* Encapsulates the datagram functionality.
|
||||||
|
*
|
||||||
|
* New instances of `dgram.Socket` are created using {@link createSocket}.
|
||||||
|
* The `new` keyword is not to be used to create `dgram.Socket` instances.
|
||||||
|
* @since v0.1.99
|
||||||
|
*/
|
||||||
|
class Socket extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* Tells the kernel to join a multicast group at the given `multicastAddress` and `multicastInterface` using the `IP_ADD_MEMBERSHIP` socket option. If the `multicastInterface` argument is not
|
||||||
|
* specified, the operating system will choose
|
||||||
|
* one interface and will add membership to it. To add membership to every
|
||||||
|
* available interface, call `addMembership` multiple times, once per interface.
|
||||||
|
*
|
||||||
|
* When called on an unbound socket, this method will implicitly bind to a random
|
||||||
|
* port, listening on all interfaces.
|
||||||
|
*
|
||||||
|
* When sharing a UDP socket across multiple `cluster` workers, the`socket.addMembership()` function must be called only once or an`EADDRINUSE` error will occur:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* cluster.fork(); // Works ok.
|
||||||
|
* cluster.fork(); // Fails with EADDRINUSE.
|
||||||
|
* } else {
|
||||||
|
* const s = dgram.createSocket('udp4');
|
||||||
|
* s.bind(1234, () => {
|
||||||
|
* s.addMembership('224.0.0.114');
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.6.9
|
||||||
|
*/
|
||||||
|
addMembership(multicastAddress: string, multicastInterface?: string): void;
|
||||||
|
/**
|
||||||
|
* Returns an object containing the address information for a socket.
|
||||||
|
* For UDP sockets, this object will contain `address`, `family`, and `port` properties.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.1.99
|
||||||
|
*/
|
||||||
|
address(): AddressInfo;
|
||||||
|
/**
|
||||||
|
* For UDP sockets, causes the `dgram.Socket` to listen for datagram
|
||||||
|
* messages on a named `port` and optional `address`. If `port` is not
|
||||||
|
* specified or is `0`, the operating system will attempt to bind to a
|
||||||
|
* random port. If `address` is not specified, the operating system will
|
||||||
|
* attempt to listen on all addresses. Once binding is complete, a `'listening'` event is emitted and the optional `callback` function is
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* Specifying both a `'listening'` event listener and passing a `callback` to the `socket.bind()` method is not harmful but not very
|
||||||
|
* useful.
|
||||||
|
*
|
||||||
|
* A bound datagram socket keeps the Node.js process running to receive
|
||||||
|
* datagram messages.
|
||||||
|
*
|
||||||
|
* If binding fails, an `'error'` event is generated. In rare case (e.g.
|
||||||
|
* attempting to bind with a closed socket), an `Error` may be thrown.
|
||||||
|
*
|
||||||
|
* Example of a UDP server listening on port 41234:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
*
|
||||||
|
* const server = dgram.createSocket('udp4');
|
||||||
|
*
|
||||||
|
* server.on('error', (err) => {
|
||||||
|
* console.error(`server error:\n${err.stack}`);
|
||||||
|
* server.close();
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.on('message', (msg, rinfo) => {
|
||||||
|
* console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.on('listening', () => {
|
||||||
|
* const address = server.address();
|
||||||
|
* console.log(`server listening ${address.address}:${address.port}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.bind(41234);
|
||||||
|
* // Prints: server listening 0.0.0.0:41234
|
||||||
|
* ```
|
||||||
|
* @since v0.1.99
|
||||||
|
* @param callback with no parameters. Called when binding is complete.
|
||||||
|
*/
|
||||||
|
bind(port?: number, address?: string, callback?: () => void): this;
|
||||||
|
bind(port?: number, callback?: () => void): this;
|
||||||
|
bind(callback?: () => void): this;
|
||||||
|
bind(options: BindOptions, callback?: () => void): this;
|
||||||
|
/**
|
||||||
|
* Close the underlying socket and stop listening for data on it. If a callback is
|
||||||
|
* provided, it is added as a listener for the `'close'` event.
|
||||||
|
* @since v0.1.99
|
||||||
|
* @param callback Called when the socket has been closed.
|
||||||
|
*/
|
||||||
|
close(callback?: () => void): this;
|
||||||
|
/**
|
||||||
|
* Associates the `dgram.Socket` to a remote address and port. Every
|
||||||
|
* message sent by this handle is automatically sent to that destination. Also,
|
||||||
|
* the socket will only receive messages from that remote peer.
|
||||||
|
* Trying to call `connect()` on an already connected socket will result
|
||||||
|
* in an `ERR_SOCKET_DGRAM_IS_CONNECTED` exception. If `address` is not
|
||||||
|
* provided, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets)
|
||||||
|
* will be used by default. Once the connection is complete, a `'connect'` event
|
||||||
|
* is emitted and the optional `callback` function is called. In case of failure,
|
||||||
|
* the `callback` is called or, failing this, an `'error'` event is emitted.
|
||||||
|
* @since v12.0.0
|
||||||
|
* @param callback Called when the connection is completed or on error.
|
||||||
|
*/
|
||||||
|
connect(port: number, address?: string, callback?: () => void): void;
|
||||||
|
connect(port: number, callback: () => void): void;
|
||||||
|
/**
|
||||||
|
* A synchronous function that disassociates a connected `dgram.Socket` from
|
||||||
|
* its remote address. Trying to call `disconnect()` on an unbound or already
|
||||||
|
* disconnected socket will result in an `ERR_SOCKET_DGRAM_NOT_CONNECTED` exception.
|
||||||
|
* @since v12.0.0
|
||||||
|
*/
|
||||||
|
disconnect(): void;
|
||||||
|
/**
|
||||||
|
* Instructs the kernel to leave a multicast group at `multicastAddress` using the `IP_DROP_MEMBERSHIP` socket option. This method is automatically called by the
|
||||||
|
* kernel when the socket is closed or the process terminates, so most apps will
|
||||||
|
* never have reason to call this.
|
||||||
|
*
|
||||||
|
* If `multicastInterface` is not specified, the operating system will attempt to
|
||||||
|
* drop membership on all valid interfaces.
|
||||||
|
* @since v0.6.9
|
||||||
|
*/
|
||||||
|
dropMembership(multicastAddress: string, multicastInterface?: string): void;
|
||||||
|
/**
|
||||||
|
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||||
|
* @since v8.7.0
|
||||||
|
* @return the `SO_RCVBUF` socket receive buffer size in bytes.
|
||||||
|
*/
|
||||||
|
getRecvBufferSize(): number;
|
||||||
|
/**
|
||||||
|
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||||
|
* @since v8.7.0
|
||||||
|
* @return the `SO_SNDBUF` socket send buffer size in bytes.
|
||||||
|
*/
|
||||||
|
getSendBufferSize(): number;
|
||||||
|
/**
|
||||||
|
* @since v18.8.0, v16.19.0
|
||||||
|
* @return Number of bytes queued for sending.
|
||||||
|
*/
|
||||||
|
getSendQueueSize(): number;
|
||||||
|
/**
|
||||||
|
* @since v18.8.0, v16.19.0
|
||||||
|
* @return Number of send requests currently in the queue awaiting to be processed.
|
||||||
|
*/
|
||||||
|
getSendQueueCount(): number;
|
||||||
|
/**
|
||||||
|
* By default, binding a socket will cause it to block the Node.js process from
|
||||||
|
* exiting as long as the socket is open. The `socket.unref()` method can be used
|
||||||
|
* to exclude the socket from the reference counting that keeps the Node.js
|
||||||
|
* process active. The `socket.ref()` method adds the socket back to the reference
|
||||||
|
* counting and restores the default behavior.
|
||||||
|
*
|
||||||
|
* Calling `socket.ref()` multiples times will have no additional effect.
|
||||||
|
*
|
||||||
|
* The `socket.ref()` method returns a reference to the socket so calls can be
|
||||||
|
* chained.
|
||||||
|
* @since v0.9.1
|
||||||
|
*/
|
||||||
|
ref(): this;
|
||||||
|
/**
|
||||||
|
* Returns an object containing the `address`, `family`, and `port` of the remote
|
||||||
|
* endpoint. This method throws an `ERR_SOCKET_DGRAM_NOT_CONNECTED` exception
|
||||||
|
* if the socket is not connected.
|
||||||
|
* @since v12.0.0
|
||||||
|
*/
|
||||||
|
remoteAddress(): AddressInfo;
|
||||||
|
/**
|
||||||
|
* Broadcasts a datagram on the socket.
|
||||||
|
* For connectionless sockets, the destination `port` and `address` must be
|
||||||
|
* specified. Connected sockets, on the other hand, will use their associated
|
||||||
|
* remote endpoint, so the `port` and `address` arguments must not be set.
|
||||||
|
*
|
||||||
|
* The `msg` argument contains the message to be sent.
|
||||||
|
* Depending on its type, different behavior can apply. If `msg` is a `Buffer`,
|
||||||
|
* any `TypedArray` or a `DataView`,
|
||||||
|
* the `offset` and `length` specify the offset within the `Buffer` where the
|
||||||
|
* message begins and the number of bytes in the message, respectively.
|
||||||
|
* If `msg` is a `String`, then it is automatically converted to a `Buffer` with `'utf8'` encoding. With messages that
|
||||||
|
* contain multi-byte characters, `offset` and `length` will be calculated with
|
||||||
|
* respect to `byte length` and not the character position.
|
||||||
|
* If `msg` is an array, `offset` and `length` must not be specified.
|
||||||
|
*
|
||||||
|
* The `address` argument is a string. If the value of `address` is a host name,
|
||||||
|
* DNS will be used to resolve the address of the host. If `address` is not
|
||||||
|
* provided or otherwise nullish, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets) will be used by default.
|
||||||
|
*
|
||||||
|
* If the socket has not been previously bound with a call to `bind`, the socket
|
||||||
|
* is assigned a random port number and is bound to the "all interfaces" address
|
||||||
|
* (`'0.0.0.0'` for `udp4` sockets, `'::0'` for `udp6` sockets.)
|
||||||
|
*
|
||||||
|
* An optional `callback` function may be specified to as a way of reporting
|
||||||
|
* DNS errors or for determining when it is safe to reuse the `buf` object.
|
||||||
|
* DNS lookups delay the time to send for at least one tick of the
|
||||||
|
* Node.js event loop.
|
||||||
|
*
|
||||||
|
* The only way to know for sure that the datagram has been sent is by using a `callback`. If an error occurs and a `callback` is given, the error will be
|
||||||
|
* passed as the first argument to the `callback`. If a `callback` is not given,
|
||||||
|
* the error is emitted as an `'error'` event on the `socket` object.
|
||||||
|
*
|
||||||
|
* Offset and length are optional but both _must_ be set if either are used.
|
||||||
|
* They are supported only when the first argument is a `Buffer`, a `TypedArray`,
|
||||||
|
* or a `DataView`.
|
||||||
|
*
|
||||||
|
* This method throws `ERR_SOCKET_BAD_PORT` if called on an unbound socket.
|
||||||
|
*
|
||||||
|
* Example of sending a UDP packet to a port on `localhost`;
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const message = Buffer.from('Some bytes');
|
||||||
|
* const client = dgram.createSocket('udp4');
|
||||||
|
* client.send(message, 41234, 'localhost', (err) => {
|
||||||
|
* client.close();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example of sending a UDP packet composed of multiple buffers to a port on`127.0.0.1`;
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf1 = Buffer.from('Some ');
|
||||||
|
* const buf2 = Buffer.from('bytes');
|
||||||
|
* const client = dgram.createSocket('udp4');
|
||||||
|
* client.send([buf1, buf2], 41234, (err) => {
|
||||||
|
* client.close();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Sending multiple buffers might be faster or slower depending on the
|
||||||
|
* application and operating system. Run benchmarks to
|
||||||
|
* determine the optimal strategy on a case-by-case basis. Generally speaking,
|
||||||
|
* however, sending multiple buffers is faster.
|
||||||
|
*
|
||||||
|
* Example of sending a UDP packet using a socket connected to a port on `localhost`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const message = Buffer.from('Some bytes');
|
||||||
|
* const client = dgram.createSocket('udp4');
|
||||||
|
* client.connect(41234, 'localhost', (err) => {
|
||||||
|
* client.send(message, (err) => {
|
||||||
|
* client.close();
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v0.1.99
|
||||||
|
* @param msg Message to be sent.
|
||||||
|
* @param offset Offset in the buffer where the message starts.
|
||||||
|
* @param length Number of bytes in the message.
|
||||||
|
* @param port Destination port.
|
||||||
|
* @param address Destination host name or IP address.
|
||||||
|
* @param callback Called when the message has been sent.
|
||||||
|
*/
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||||
|
port?: number,
|
||||||
|
address?: string,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||||
|
port?: number,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView,
|
||||||
|
offset: number,
|
||||||
|
length: number,
|
||||||
|
port?: number,
|
||||||
|
address?: string,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView,
|
||||||
|
offset: number,
|
||||||
|
length: number,
|
||||||
|
port?: number,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView,
|
||||||
|
offset: number,
|
||||||
|
length: number,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
/**
|
||||||
|
* Sets or clears the `SO_BROADCAST` socket option. When set to `true`, UDP
|
||||||
|
* packets may be sent to a local interface's broadcast address.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.6.9
|
||||||
|
*/
|
||||||
|
setBroadcast(flag: boolean): void;
|
||||||
|
/**
|
||||||
|
* _All references to scope in this section are referring to [IPv6 Zone Indices](https://en.wikipedia.org/wiki/IPv6_address#Scoped_literal_IPv6_addresses), which are defined by [RFC
|
||||||
|
* 4007](https://tools.ietf.org/html/rfc4007). In string form, an IP_
|
||||||
|
* _with a scope index is written as `'IP%scope'` where scope is an interface name_
|
||||||
|
* _or interface number._
|
||||||
|
*
|
||||||
|
* Sets the default outgoing multicast interface of the socket to a chosen
|
||||||
|
* interface or back to system interface selection. The `multicastInterface` must
|
||||||
|
* be a valid string representation of an IP from the socket's family.
|
||||||
|
*
|
||||||
|
* For IPv4 sockets, this should be the IP configured for the desired physical
|
||||||
|
* interface. All packets sent to multicast on the socket will be sent on the
|
||||||
|
* interface determined by the most recent successful use of this call.
|
||||||
|
*
|
||||||
|
* For IPv6 sockets, `multicastInterface` should include a scope to indicate the
|
||||||
|
* interface as in the examples that follow. In IPv6, individual `send` calls can
|
||||||
|
* also use explicit scope in addresses, so only packets sent to a multicast
|
||||||
|
* address without specifying an explicit scope are affected by the most recent
|
||||||
|
* successful use of this call.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
*
|
||||||
|
* #### Example: IPv6 outgoing multicast interface
|
||||||
|
*
|
||||||
|
* On most systems, where scope format uses the interface name:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const socket = dgram.createSocket('udp6');
|
||||||
|
*
|
||||||
|
* socket.bind(1234, () => {
|
||||||
|
* socket.setMulticastInterface('::%eth1');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* On Windows, where scope format uses an interface number:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const socket = dgram.createSocket('udp6');
|
||||||
|
*
|
||||||
|
* socket.bind(1234, () => {
|
||||||
|
* socket.setMulticastInterface('::%2');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* #### Example: IPv4 outgoing multicast interface
|
||||||
|
*
|
||||||
|
* All systems use an IP of the host on the desired physical interface:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const socket = dgram.createSocket('udp4');
|
||||||
|
*
|
||||||
|
* socket.bind(1234, () => {
|
||||||
|
* socket.setMulticastInterface('10.0.0.2');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v8.6.0
|
||||||
|
*/
|
||||||
|
setMulticastInterface(multicastInterface: string): void;
|
||||||
|
/**
|
||||||
|
* Sets or clears the `IP_MULTICAST_LOOP` socket option. When set to `true`,
|
||||||
|
* multicast packets will also be received on the local interface.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.3.8
|
||||||
|
*/
|
||||||
|
setMulticastLoopback(flag: boolean): boolean;
|
||||||
|
/**
|
||||||
|
* Sets the `IP_MULTICAST_TTL` socket option. While TTL generally stands for
|
||||||
|
* "Time to Live", in this context it specifies the number of IP hops that a
|
||||||
|
* packet is allowed to travel through, specifically for multicast traffic. Each
|
||||||
|
* router or gateway that forwards a packet decrements the TTL. If the TTL is
|
||||||
|
* decremented to 0 by a router, it will not be forwarded.
|
||||||
|
*
|
||||||
|
* The `ttl` argument may be between 0 and 255\. The default on most systems is `1`.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.3.8
|
||||||
|
*/
|
||||||
|
setMulticastTTL(ttl: number): number;
|
||||||
|
/**
|
||||||
|
* Sets the `SO_RCVBUF` socket option. Sets the maximum socket receive buffer
|
||||||
|
* in bytes.
|
||||||
|
*
|
||||||
|
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||||
|
* @since v8.7.0
|
||||||
|
*/
|
||||||
|
setRecvBufferSize(size: number): void;
|
||||||
|
/**
|
||||||
|
* Sets the `SO_SNDBUF` socket option. Sets the maximum socket send buffer
|
||||||
|
* in bytes.
|
||||||
|
*
|
||||||
|
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||||
|
* @since v8.7.0
|
||||||
|
*/
|
||||||
|
setSendBufferSize(size: number): void;
|
||||||
|
/**
|
||||||
|
* Sets the `IP_TTL` socket option. While TTL generally stands for "Time to Live",
|
||||||
|
* in this context it specifies the number of IP hops that a packet is allowed to
|
||||||
|
* travel through. Each router or gateway that forwards a packet decrements the
|
||||||
|
* TTL. If the TTL is decremented to 0 by a router, it will not be forwarded.
|
||||||
|
* Changing TTL values is typically done for network probes or when multicasting.
|
||||||
|
*
|
||||||
|
* The `ttl` argument may be between 1 and 255\. The default on most systems
|
||||||
|
* is 64.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.1.101
|
||||||
|
*/
|
||||||
|
setTTL(ttl: number): number;
|
||||||
|
/**
|
||||||
|
* By default, binding a socket will cause it to block the Node.js process from
|
||||||
|
* exiting as long as the socket is open. The `socket.unref()` method can be used
|
||||||
|
* to exclude the socket from the reference counting that keeps the Node.js
|
||||||
|
* process active, allowing the process to exit even if the socket is still
|
||||||
|
* listening.
|
||||||
|
*
|
||||||
|
* Calling `socket.unref()` multiple times will have no additional effect.
|
||||||
|
*
|
||||||
|
* The `socket.unref()` method returns a reference to the socket so calls can be
|
||||||
|
* chained.
|
||||||
|
* @since v0.9.1
|
||||||
|
*/
|
||||||
|
unref(): this;
|
||||||
|
/**
|
||||||
|
* Tells the kernel to join a source-specific multicast channel at the given `sourceAddress` and `groupAddress`, using the `multicastInterface` with the `IP_ADD_SOURCE_MEMBERSHIP` socket
|
||||||
|
* option. If the `multicastInterface` argument
|
||||||
|
* is not specified, the operating system will choose one interface and will add
|
||||||
|
* membership to it. To add membership to every available interface, call `socket.addSourceSpecificMembership()` multiple times, once per interface.
|
||||||
|
*
|
||||||
|
* When called on an unbound socket, this method will implicitly bind to a random
|
||||||
|
* port, listening on all interfaces.
|
||||||
|
* @since v13.1.0, v12.16.0
|
||||||
|
*/
|
||||||
|
addSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
|
||||||
|
/**
|
||||||
|
* Instructs the kernel to leave a source-specific multicast channel at the given `sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP` socket option. This method is
|
||||||
|
* automatically called by the kernel when the
|
||||||
|
* socket is closed or the process terminates, so most apps will never have
|
||||||
|
* reason to call this.
|
||||||
|
*
|
||||||
|
* If `multicastInterface` is not specified, the operating system will attempt to
|
||||||
|
* drop membership on all valid interfaces.
|
||||||
|
* @since v13.1.0, v12.16.0
|
||||||
|
*/
|
||||||
|
dropSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
|
||||||
|
/**
|
||||||
|
* events.EventEmitter
|
||||||
|
* 1. close
|
||||||
|
* 2. connect
|
||||||
|
* 3. error
|
||||||
|
* 4. listening
|
||||||
|
* 5. message
|
||||||
|
*/
|
||||||
|
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
addListener(event: "close", listener: () => void): this;
|
||||||
|
addListener(event: "connect", listener: () => void): this;
|
||||||
|
addListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
addListener(event: "listening", listener: () => void): this;
|
||||||
|
addListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
emit(event: string | symbol, ...args: any[]): boolean;
|
||||||
|
emit(event: "close"): boolean;
|
||||||
|
emit(event: "connect"): boolean;
|
||||||
|
emit(event: "error", err: Error): boolean;
|
||||||
|
emit(event: "listening"): boolean;
|
||||||
|
emit(event: "message", msg: Buffer, rinfo: RemoteInfo): boolean;
|
||||||
|
on(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
on(event: "close", listener: () => void): this;
|
||||||
|
on(event: "connect", listener: () => void): this;
|
||||||
|
on(event: "error", listener: (err: Error) => void): this;
|
||||||
|
on(event: "listening", listener: () => void): this;
|
||||||
|
on(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
once(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
once(event: "close", listener: () => void): this;
|
||||||
|
once(event: "connect", listener: () => void): this;
|
||||||
|
once(event: "error", listener: (err: Error) => void): this;
|
||||||
|
once(event: "listening", listener: () => void): this;
|
||||||
|
once(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependListener(event: "close", listener: () => void): this;
|
||||||
|
prependListener(event: "connect", listener: () => void): this;
|
||||||
|
prependListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
prependListener(event: "listening", listener: () => void): this;
|
||||||
|
prependListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependOnceListener(event: "close", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "connect", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
prependOnceListener(event: "listening", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
/**
|
||||||
|
* Calls `socket.close()` and returns a promise that fulfills when the socket has closed.
|
||||||
|
* @since v20.5.0
|
||||||
|
*/
|
||||||
|
[Symbol.asyncDispose](): Promise<void>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare module "node:dgram" {
|
||||||
|
export * from "dgram";
|
||||||
|
}
|
||||||
578
node_modules/@types/node/diagnostics_channel.d.ts
generated
vendored
Normal file
578
node_modules/@types/node/diagnostics_channel.d.ts
generated
vendored
Normal file
@@ -0,0 +1,578 @@
|
|||||||
|
/**
|
||||||
|
* The `node:diagnostics_channel` module provides an API to create named channels
|
||||||
|
* to report arbitrary message data for diagnostics purposes.
|
||||||
|
*
|
||||||
|
* It can be accessed using:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* It is intended that a module writer wanting to report diagnostics messages
|
||||||
|
* will create one or many top-level channels to report messages through.
|
||||||
|
* Channels may also be acquired at runtime but it is not encouraged
|
||||||
|
* due to the additional overhead of doing so. Channels may be exported for
|
||||||
|
* convenience, but as long as the name is known it can be acquired anywhere.
|
||||||
|
*
|
||||||
|
* If you intend for your module to produce diagnostics data for others to
|
||||||
|
* consume it is recommended that you include documentation of what named
|
||||||
|
* channels are used along with the shape of the message data. Channel names
|
||||||
|
* should generally include the module name to avoid collisions with data from
|
||||||
|
* other modules.
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/diagnostics_channel.js)
|
||||||
|
*/
|
||||||
|
declare module "diagnostics_channel" {
|
||||||
|
import { AsyncLocalStorage } from "node:async_hooks";
|
||||||
|
/**
|
||||||
|
* Check if there are active subscribers to the named channel. This is helpful if
|
||||||
|
* the message you want to send might be expensive to prepare.
|
||||||
|
*
|
||||||
|
* This API is optional but helpful when trying to publish messages from very
|
||||||
|
* performance-sensitive code.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* if (diagnostics_channel.hasSubscribers('my-channel')) {
|
||||||
|
* // There are subscribers, prepare and publish message
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
* @param name The channel name
|
||||||
|
* @return If there are active subscribers
|
||||||
|
*/
|
||||||
|
function hasSubscribers(name: string | symbol): boolean;
|
||||||
|
/**
|
||||||
|
* This is the primary entry-point for anyone wanting to publish to a named
|
||||||
|
* channel. It produces a channel object which is optimized to reduce overhead at
|
||||||
|
* publish time as much as possible.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channel = diagnostics_channel.channel('my-channel');
|
||||||
|
* ```
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
* @param name The channel name
|
||||||
|
* @return The named channel object
|
||||||
|
*/
|
||||||
|
function channel(name: string | symbol): Channel;
|
||||||
|
type ChannelListener = (message: unknown, name: string | symbol) => void;
|
||||||
|
/**
|
||||||
|
* Register a message handler to subscribe to this channel. This message handler
|
||||||
|
* will be run synchronously whenever a message is published to the channel. Any
|
||||||
|
* errors thrown in the message handler will trigger an `'uncaughtException'`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* diagnostics_channel.subscribe('my-channel', (message, name) => {
|
||||||
|
* // Received data
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v18.7.0, v16.17.0
|
||||||
|
* @param name The channel name
|
||||||
|
* @param onMessage The handler to receive channel messages
|
||||||
|
*/
|
||||||
|
function subscribe(name: string | symbol, onMessage: ChannelListener): void;
|
||||||
|
/**
|
||||||
|
* Remove a message handler previously registered to this channel with {@link subscribe}.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* function onMessage(message, name) {
|
||||||
|
* // Received data
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* diagnostics_channel.subscribe('my-channel', onMessage);
|
||||||
|
*
|
||||||
|
* diagnostics_channel.unsubscribe('my-channel', onMessage);
|
||||||
|
* ```
|
||||||
|
* @since v18.7.0, v16.17.0
|
||||||
|
* @param name The channel name
|
||||||
|
* @param onMessage The previous subscribed handler to remove
|
||||||
|
* @return `true` if the handler was found, `false` otherwise.
|
||||||
|
*/
|
||||||
|
function unsubscribe(name: string | symbol, onMessage: ChannelListener): boolean;
|
||||||
|
/**
|
||||||
|
* Creates a `TracingChannel` wrapper for the given `TracingChannel Channels`. If a name is given, the corresponding tracing
|
||||||
|
* channels will be created in the form of `tracing:${name}:${eventType}` where `eventType` corresponds to the types of `TracingChannel Channels`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channelsByName = diagnostics_channel.tracingChannel('my-channel');
|
||||||
|
*
|
||||||
|
* // or...
|
||||||
|
*
|
||||||
|
* const channelsByCollection = diagnostics_channel.tracingChannel({
|
||||||
|
* start: diagnostics_channel.channel('tracing:my-channel:start'),
|
||||||
|
* end: diagnostics_channel.channel('tracing:my-channel:end'),
|
||||||
|
* asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'),
|
||||||
|
* asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'),
|
||||||
|
* error: diagnostics_channel.channel('tracing:my-channel:error'),
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param nameOrChannels Channel name or object containing all the `TracingChannel Channels`
|
||||||
|
* @return Collection of channels to trace with
|
||||||
|
*/
|
||||||
|
function tracingChannel<
|
||||||
|
StoreType = unknown,
|
||||||
|
ContextType extends object = StoreType extends object ? StoreType : object,
|
||||||
|
>(
|
||||||
|
nameOrChannels: string | TracingChannelCollection<StoreType, ContextType>,
|
||||||
|
): TracingChannel<StoreType, ContextType>;
|
||||||
|
/**
|
||||||
|
* The class `Channel` represents an individual named channel within the data
|
||||||
|
* pipeline. It is used to track subscribers and to publish messages when there
|
||||||
|
* are subscribers present. It exists as a separate object to avoid channel
|
||||||
|
* lookups at publish time, enabling very fast publish speeds and allowing
|
||||||
|
* for heavy use while incurring very minimal cost. Channels are created with {@link channel}, constructing a channel directly
|
||||||
|
* with `new Channel(name)` is not supported.
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
*/
|
||||||
|
class Channel<StoreType = unknown, ContextType = StoreType> {
|
||||||
|
readonly name: string | symbol;
|
||||||
|
/**
|
||||||
|
* Check if there are active subscribers to this channel. This is helpful if
|
||||||
|
* the message you want to send might be expensive to prepare.
|
||||||
|
*
|
||||||
|
* This API is optional but helpful when trying to publish messages from very
|
||||||
|
* performance-sensitive code.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channel = diagnostics_channel.channel('my-channel');
|
||||||
|
*
|
||||||
|
* if (channel.hasSubscribers) {
|
||||||
|
* // There are subscribers, prepare and publish message
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
*/
|
||||||
|
readonly hasSubscribers: boolean;
|
||||||
|
private constructor(name: string | symbol);
|
||||||
|
/**
|
||||||
|
* Publish a message to any subscribers to the channel. This will trigger
|
||||||
|
* message handlers synchronously so they will execute within the same context.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channel = diagnostics_channel.channel('my-channel');
|
||||||
|
*
|
||||||
|
* channel.publish({
|
||||||
|
* some: 'message',
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
* @param message The message to send to the channel subscribers
|
||||||
|
*/
|
||||||
|
publish(message: unknown): void;
|
||||||
|
/**
|
||||||
|
* Register a message handler to subscribe to this channel. This message handler
|
||||||
|
* will be run synchronously whenever a message is published to the channel. Any
|
||||||
|
* errors thrown in the message handler will trigger an `'uncaughtException'`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channel = diagnostics_channel.channel('my-channel');
|
||||||
|
*
|
||||||
|
* channel.subscribe((message, name) => {
|
||||||
|
* // Received data
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
* @deprecated Since v18.7.0,v16.17.0 - Use {@link subscribe(name, onMessage)}
|
||||||
|
* @param onMessage The handler to receive channel messages
|
||||||
|
*/
|
||||||
|
subscribe(onMessage: ChannelListener): void;
|
||||||
|
/**
|
||||||
|
* Remove a message handler previously registered to this channel with `channel.subscribe(onMessage)`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channel = diagnostics_channel.channel('my-channel');
|
||||||
|
*
|
||||||
|
* function onMessage(message, name) {
|
||||||
|
* // Received data
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* channel.subscribe(onMessage);
|
||||||
|
*
|
||||||
|
* channel.unsubscribe(onMessage);
|
||||||
|
* ```
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
* @deprecated Since v18.7.0,v16.17.0 - Use {@link unsubscribe(name, onMessage)}
|
||||||
|
* @param onMessage The previous subscribed handler to remove
|
||||||
|
* @return `true` if the handler was found, `false` otherwise.
|
||||||
|
*/
|
||||||
|
unsubscribe(onMessage: ChannelListener): void;
|
||||||
|
/**
|
||||||
|
* When `channel.runStores(context, ...)` is called, the given context data
|
||||||
|
* will be applied to any store bound to the channel. If the store has already been
|
||||||
|
* bound the previous `transform` function will be replaced with the new one.
|
||||||
|
* The `transform` function may be omitted to set the given context data as the
|
||||||
|
* context directly.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
* import { AsyncLocalStorage } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* const store = new AsyncLocalStorage();
|
||||||
|
*
|
||||||
|
* const channel = diagnostics_channel.channel('my-channel');
|
||||||
|
*
|
||||||
|
* channel.bindStore(store, (data) => {
|
||||||
|
* return { data };
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param store The store to which to bind the context data
|
||||||
|
* @param transform Transform context data before setting the store context
|
||||||
|
*/
|
||||||
|
bindStore(store: AsyncLocalStorage<StoreType>, transform?: (context: ContextType) => StoreType): void;
|
||||||
|
/**
|
||||||
|
* Remove a message handler previously registered to this channel with `channel.bindStore(store)`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
* import { AsyncLocalStorage } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* const store = new AsyncLocalStorage();
|
||||||
|
*
|
||||||
|
* const channel = diagnostics_channel.channel('my-channel');
|
||||||
|
*
|
||||||
|
* channel.bindStore(store);
|
||||||
|
* channel.unbindStore(store);
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param store The store to unbind from the channel.
|
||||||
|
* @return `true` if the store was found, `false` otherwise.
|
||||||
|
*/
|
||||||
|
unbindStore(store: AsyncLocalStorage<StoreType>): boolean;
|
||||||
|
/**
|
||||||
|
* Applies the given data to any AsyncLocalStorage instances bound to the channel
|
||||||
|
* for the duration of the given function, then publishes to the channel within
|
||||||
|
* the scope of that data is applied to the stores.
|
||||||
|
*
|
||||||
|
* If a transform function was given to `channel.bindStore(store)` it will be
|
||||||
|
* applied to transform the message data before it becomes the context value for
|
||||||
|
* the store. The prior storage context is accessible from within the transform
|
||||||
|
* function in cases where context linking is required.
|
||||||
|
*
|
||||||
|
* The context applied to the store should be accessible in any async code which
|
||||||
|
* continues from execution which began during the given function, however
|
||||||
|
* there are some situations in which `context loss` may occur.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
* import { AsyncLocalStorage } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* const store = new AsyncLocalStorage();
|
||||||
|
*
|
||||||
|
* const channel = diagnostics_channel.channel('my-channel');
|
||||||
|
*
|
||||||
|
* channel.bindStore(store, (message) => {
|
||||||
|
* const parent = store.getStore();
|
||||||
|
* return new Span(message, parent);
|
||||||
|
* });
|
||||||
|
* channel.runStores({ some: 'message' }, () => {
|
||||||
|
* store.getStore(); // Span({ some: 'message' })
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param context Message to send to subscribers and bind to stores
|
||||||
|
* @param fn Handler to run within the entered storage context
|
||||||
|
* @param thisArg The receiver to be used for the function call.
|
||||||
|
* @param args Optional arguments to pass to the function.
|
||||||
|
*/
|
||||||
|
runStores<ThisArg = any, Args extends any[] = any[], Result = any>(
|
||||||
|
context: ContextType,
|
||||||
|
fn: (this: ThisArg, ...args: Args) => Result,
|
||||||
|
thisArg?: ThisArg,
|
||||||
|
...args: Args
|
||||||
|
): Result;
|
||||||
|
}
|
||||||
|
interface TracingChannelSubscribers<ContextType extends object> {
|
||||||
|
start: (message: ContextType) => void;
|
||||||
|
end: (
|
||||||
|
message: ContextType & {
|
||||||
|
error?: unknown;
|
||||||
|
result?: unknown;
|
||||||
|
},
|
||||||
|
) => void;
|
||||||
|
asyncStart: (
|
||||||
|
message: ContextType & {
|
||||||
|
error?: unknown;
|
||||||
|
result?: unknown;
|
||||||
|
},
|
||||||
|
) => void;
|
||||||
|
asyncEnd: (
|
||||||
|
message: ContextType & {
|
||||||
|
error?: unknown;
|
||||||
|
result?: unknown;
|
||||||
|
},
|
||||||
|
) => void;
|
||||||
|
error: (
|
||||||
|
message: ContextType & {
|
||||||
|
error: unknown;
|
||||||
|
},
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
interface TracingChannelCollection<StoreType = unknown, ContextType = StoreType> {
|
||||||
|
start: Channel<StoreType, ContextType>;
|
||||||
|
end: Channel<StoreType, ContextType>;
|
||||||
|
asyncStart: Channel<StoreType, ContextType>;
|
||||||
|
asyncEnd: Channel<StoreType, ContextType>;
|
||||||
|
error: Channel<StoreType, ContextType>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The class `TracingChannel` is a collection of `TracingChannel Channels` which
|
||||||
|
* together express a single traceable action. It is used to formalize and
|
||||||
|
* simplify the process of producing events for tracing application flow. {@link tracingChannel} is used to construct a `TracingChannel`. As with `Channel` it is recommended to create and reuse a
|
||||||
|
* single `TracingChannel` at the top-level of the file rather than creating them
|
||||||
|
* dynamically.
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
class TracingChannel<StoreType = unknown, ContextType extends object = {}> implements TracingChannelCollection {
|
||||||
|
start: Channel<StoreType, ContextType>;
|
||||||
|
end: Channel<StoreType, ContextType>;
|
||||||
|
asyncStart: Channel<StoreType, ContextType>;
|
||||||
|
asyncEnd: Channel<StoreType, ContextType>;
|
||||||
|
error: Channel<StoreType, ContextType>;
|
||||||
|
/**
|
||||||
|
* Helper to subscribe a collection of functions to the corresponding channels.
|
||||||
|
* This is the same as calling `channel.subscribe(onMessage)` on each channel
|
||||||
|
* individually.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channels = diagnostics_channel.tracingChannel('my-channel');
|
||||||
|
*
|
||||||
|
* channels.subscribe({
|
||||||
|
* start(message) {
|
||||||
|
* // Handle start message
|
||||||
|
* },
|
||||||
|
* end(message) {
|
||||||
|
* // Handle end message
|
||||||
|
* },
|
||||||
|
* asyncStart(message) {
|
||||||
|
* // Handle asyncStart message
|
||||||
|
* },
|
||||||
|
* asyncEnd(message) {
|
||||||
|
* // Handle asyncEnd message
|
||||||
|
* },
|
||||||
|
* error(message) {
|
||||||
|
* // Handle error message
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param subscribers Set of `TracingChannel Channels` subscribers
|
||||||
|
*/
|
||||||
|
subscribe(subscribers: TracingChannelSubscribers<ContextType>): void;
|
||||||
|
/**
|
||||||
|
* Helper to unsubscribe a collection of functions from the corresponding channels.
|
||||||
|
* This is the same as calling `channel.unsubscribe(onMessage)` on each channel
|
||||||
|
* individually.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channels = diagnostics_channel.tracingChannel('my-channel');
|
||||||
|
*
|
||||||
|
* channels.unsubscribe({
|
||||||
|
* start(message) {
|
||||||
|
* // Handle start message
|
||||||
|
* },
|
||||||
|
* end(message) {
|
||||||
|
* // Handle end message
|
||||||
|
* },
|
||||||
|
* asyncStart(message) {
|
||||||
|
* // Handle asyncStart message
|
||||||
|
* },
|
||||||
|
* asyncEnd(message) {
|
||||||
|
* // Handle asyncEnd message
|
||||||
|
* },
|
||||||
|
* error(message) {
|
||||||
|
* // Handle error message
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param subscribers Set of `TracingChannel Channels` subscribers
|
||||||
|
* @return `true` if all handlers were successfully unsubscribed, and `false` otherwise.
|
||||||
|
*/
|
||||||
|
unsubscribe(subscribers: TracingChannelSubscribers<ContextType>): void;
|
||||||
|
/**
|
||||||
|
* Trace a synchronous function call. This will always produce a `start event` and `end event` around the execution and may produce an `error event` if the given function throws an error.
|
||||||
|
* This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all
|
||||||
|
* events should have any bound stores set to match this trace context.
|
||||||
|
*
|
||||||
|
* To ensure only correct trace graphs are formed, events will only be published if subscribers are present prior to starting the trace. Subscriptions
|
||||||
|
* which are added after the trace begins will not receive future events from that trace, only future traces will be seen.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channels = diagnostics_channel.tracingChannel('my-channel');
|
||||||
|
*
|
||||||
|
* channels.traceSync(() => {
|
||||||
|
* // Do something
|
||||||
|
* }, {
|
||||||
|
* some: 'thing',
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param fn Function to wrap a trace around
|
||||||
|
* @param context Shared object to correlate events through
|
||||||
|
* @param thisArg The receiver to be used for the function call
|
||||||
|
* @param args Optional arguments to pass to the function
|
||||||
|
* @return The return value of the given function
|
||||||
|
*/
|
||||||
|
traceSync<ThisArg = any, Args extends any[] = any[], Result = any>(
|
||||||
|
fn: (this: ThisArg, ...args: Args) => Result,
|
||||||
|
context?: ContextType,
|
||||||
|
thisArg?: ThisArg,
|
||||||
|
...args: Args
|
||||||
|
): Result;
|
||||||
|
/**
|
||||||
|
* Trace a promise-returning function call. This will always produce a `start event` and `end event` around the synchronous portion of the
|
||||||
|
* function execution, and will produce an `asyncStart event` and `asyncEnd event` when a promise continuation is reached. It may also
|
||||||
|
* produce an `error event` if the given function throws an error or the
|
||||||
|
* returned promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all
|
||||||
|
* events should have any bound stores set to match this trace context.
|
||||||
|
*
|
||||||
|
* To ensure only correct trace graphs are formed, events will only be published if subscribers are present prior to starting the trace. Subscriptions
|
||||||
|
* which are added after the trace begins will not receive future events from that trace, only future traces will be seen.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channels = diagnostics_channel.tracingChannel('my-channel');
|
||||||
|
*
|
||||||
|
* channels.tracePromise(async () => {
|
||||||
|
* // Do something
|
||||||
|
* }, {
|
||||||
|
* some: 'thing',
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param fn Promise-returning function to wrap a trace around
|
||||||
|
* @param context Shared object to correlate trace events through
|
||||||
|
* @param thisArg The receiver to be used for the function call
|
||||||
|
* @param args Optional arguments to pass to the function
|
||||||
|
* @return Chained from promise returned by the given function
|
||||||
|
*/
|
||||||
|
tracePromise<ThisArg = any, Args extends any[] = any[], Result = any>(
|
||||||
|
fn: (this: ThisArg, ...args: Args) => Promise<Result>,
|
||||||
|
context?: ContextType,
|
||||||
|
thisArg?: ThisArg,
|
||||||
|
...args: Args
|
||||||
|
): Promise<Result>;
|
||||||
|
/**
|
||||||
|
* Trace a callback-receiving function call. This will always produce a `start event` and `end event` around the synchronous portion of the
|
||||||
|
* function execution, and will produce a `asyncStart event` and `asyncEnd event` around the callback execution. It may also produce an `error event` if the given function throws an error or
|
||||||
|
* the returned
|
||||||
|
* promise rejects. This will run the given function using `channel.runStores(context, ...)` on the `start` channel which ensures all
|
||||||
|
* events should have any bound stores set to match this trace context.
|
||||||
|
*
|
||||||
|
* The `position` will be -1 by default to indicate the final argument should
|
||||||
|
* be used as the callback.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
*
|
||||||
|
* const channels = diagnostics_channel.tracingChannel('my-channel');
|
||||||
|
*
|
||||||
|
* channels.traceCallback((arg1, callback) => {
|
||||||
|
* // Do something
|
||||||
|
* callback(null, 'result');
|
||||||
|
* }, 1, {
|
||||||
|
* some: 'thing',
|
||||||
|
* }, thisArg, arg1, callback);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The callback will also be run with `channel.runStores(context, ...)` which
|
||||||
|
* enables context loss recovery in some cases.
|
||||||
|
*
|
||||||
|
* To ensure only correct trace graphs are formed, events will only be published if subscribers are present prior to starting the trace. Subscriptions
|
||||||
|
* which are added after the trace begins will not receive future events from that trace, only future traces will be seen.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import diagnostics_channel from 'node:diagnostics_channel';
|
||||||
|
* import { AsyncLocalStorage } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* const channels = diagnostics_channel.tracingChannel('my-channel');
|
||||||
|
* const myStore = new AsyncLocalStorage();
|
||||||
|
*
|
||||||
|
* // The start channel sets the initial store data to something
|
||||||
|
* // and stores that store data value on the trace context object
|
||||||
|
* channels.start.bindStore(myStore, (data) => {
|
||||||
|
* const span = new Span(data);
|
||||||
|
* data.span = span;
|
||||||
|
* return span;
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // Then asyncStart can restore from that data it stored previously
|
||||||
|
* channels.asyncStart.bindStore(myStore, (data) => {
|
||||||
|
* return data.span;
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
* @experimental
|
||||||
|
* @param fn callback using function to wrap a trace around
|
||||||
|
* @param position Zero-indexed argument position of expected callback
|
||||||
|
* @param context Shared object to correlate trace events through
|
||||||
|
* @param thisArg The receiver to be used for the function call
|
||||||
|
* @param args Optional arguments to pass to the function
|
||||||
|
* @return The return value of the given function
|
||||||
|
*/
|
||||||
|
traceCallback<ThisArg = any, Args extends any[] = any[], Result = any>(
|
||||||
|
fn: (this: ThisArg, ...args: Args) => Result,
|
||||||
|
position?: number,
|
||||||
|
context?: ContextType,
|
||||||
|
thisArg?: ThisArg,
|
||||||
|
...args: Args
|
||||||
|
): Result;
|
||||||
|
/**
|
||||||
|
* `true` if any of the individual channels has a subscriber, `false` if not.
|
||||||
|
*
|
||||||
|
* This is a helper method available on a {@link TracingChannel} instance to check
|
||||||
|
* if any of the [TracingChannel Channels](https://nodejs.org/api/diagnostics_channel.html#tracingchannel-channels) have subscribers.
|
||||||
|
* A `true` is returned if any of them have at least one subscriber, a `false` is returned otherwise.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const diagnostics_channel = require('node:diagnostics_channel');
|
||||||
|
*
|
||||||
|
* const channels = diagnostics_channel.tracingChannel('my-channel');
|
||||||
|
*
|
||||||
|
* if (channels.hasSubscribers) {
|
||||||
|
* // Do something
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v22.0.0, v20.13.0
|
||||||
|
*/
|
||||||
|
readonly hasSubscribers: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare module "node:diagnostics_channel" {
|
||||||
|
export * from "diagnostics_channel";
|
||||||
|
}
|
||||||
871
node_modules/@types/node/dns.d.ts
generated
vendored
Normal file
871
node_modules/@types/node/dns.d.ts
generated
vendored
Normal file
@@ -0,0 +1,871 @@
|
|||||||
|
/**
|
||||||
|
* The `node:dns` module enables name resolution. For example, use it to look up IP
|
||||||
|
* addresses of host names.
|
||||||
|
*
|
||||||
|
* Although named for the [Domain Name System (DNS)](https://en.wikipedia.org/wiki/Domain_Name_System), it does not always use the
|
||||||
|
* DNS protocol for lookups. {@link lookup} uses the operating system
|
||||||
|
* facilities to perform name resolution. It may not need to perform any network
|
||||||
|
* communication. To perform name resolution the way other applications on the same
|
||||||
|
* system do, use {@link lookup}.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dns from 'node:dns';
|
||||||
|
*
|
||||||
|
* dns.lookup('example.org', (err, address, family) => {
|
||||||
|
* console.log('address: %j family: IPv%s', address, family);
|
||||||
|
* });
|
||||||
|
* // address: "93.184.216.34" family: IPv4
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* All other functions in the `node:dns` module connect to an actual DNS server to
|
||||||
|
* perform name resolution. They will always use the network to perform DNS
|
||||||
|
* queries. These functions do not use the same set of configuration files used by {@link lookup} (e.g. `/etc/hosts`). Use these functions to always perform
|
||||||
|
* DNS queries, bypassing other name-resolution facilities.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dns from 'node:dns';
|
||||||
|
*
|
||||||
|
* dns.resolve4('archive.org', (err, addresses) => {
|
||||||
|
* if (err) throw err;
|
||||||
|
*
|
||||||
|
* console.log(`addresses: ${JSON.stringify(addresses)}`);
|
||||||
|
*
|
||||||
|
* addresses.forEach((a) => {
|
||||||
|
* dns.reverse(a, (err, hostnames) => {
|
||||||
|
* if (err) {
|
||||||
|
* throw err;
|
||||||
|
* }
|
||||||
|
* console.log(`reverse for ${a}: ${JSON.stringify(hostnames)}`);
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* See the [Implementation considerations section](https://nodejs.org/docs/latest-v20.x/api/dns.html#implementation-considerations) for more information.
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/dns.js)
|
||||||
|
*/
|
||||||
|
declare module "dns" {
|
||||||
|
import * as dnsPromises from "node:dns/promises";
|
||||||
|
// Supported getaddrinfo flags.
|
||||||
|
/**
|
||||||
|
* Limits returned address types to the types of non-loopback addresses configured on the system. For example, IPv4 addresses are
|
||||||
|
* only returned if the current system has at least one IPv4 address configured.
|
||||||
|
*/
|
||||||
|
export const ADDRCONFIG: number;
|
||||||
|
/**
|
||||||
|
* If the IPv6 family was specified, but no IPv6 addresses were found, then return IPv4 mapped IPv6 addresses. It is not supported
|
||||||
|
* on some operating systems (e.g. FreeBSD 10.1).
|
||||||
|
*/
|
||||||
|
export const V4MAPPED: number;
|
||||||
|
/**
|
||||||
|
* If `dns.V4MAPPED` is specified, return resolved IPv6 addresses as
|
||||||
|
* well as IPv4 mapped IPv6 addresses.
|
||||||
|
*/
|
||||||
|
export const ALL: number;
|
||||||
|
export interface LookupOptions {
|
||||||
|
/**
|
||||||
|
* The record family. Must be `4`, `6`, or `0`. For backward compatibility reasons, `'IPv4'` and `'IPv6'` are interpreted
|
||||||
|
* as `4` and `6` respectively. The value 0 indicates that either an IPv4 or IPv6 address is returned. If the value `0` is used
|
||||||
|
* with `{ all: true } (see below)`, both IPv4 and IPv6 addresses are returned.
|
||||||
|
* @default 0
|
||||||
|
*/
|
||||||
|
family?: number | "IPv4" | "IPv6" | undefined;
|
||||||
|
/**
|
||||||
|
* One or more [supported `getaddrinfo`](https://nodejs.org/docs/latest-v20.x/api/dns.html#supported-getaddrinfo-flags) flags. Multiple flags may be
|
||||||
|
* passed by bitwise `OR`ing their values.
|
||||||
|
*/
|
||||||
|
hints?: number | undefined;
|
||||||
|
/**
|
||||||
|
* When `true`, the callback returns all resolved addresses in an array. Otherwise, returns a single address.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
all?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* When `verbatim`, the resolved addresses are return unsorted. When `ipv4first`, the resolved addresses are sorted
|
||||||
|
* by placing IPv4 addresses before IPv6 addresses. When `ipv6first`, the resolved addresses are sorted by placing IPv6
|
||||||
|
* addresses before IPv4 addresses. Default value is configurable using
|
||||||
|
* {@link setDefaultResultOrder} or [`--dns-result-order`](https://nodejs.org/docs/latest-v20.x/api/cli.html#--dns-result-orderorder).
|
||||||
|
* @default `verbatim` (addresses are not reordered)
|
||||||
|
*/
|
||||||
|
order?: "ipv4first" | "ipv6first" | "verbatim" | undefined;
|
||||||
|
/**
|
||||||
|
* When `true`, the callback receives IPv4 and IPv6 addresses in the order the DNS resolver returned them. When `false`, IPv4
|
||||||
|
* addresses are placed before IPv6 addresses. This option will be deprecated in favor of `order`. When both are specified,
|
||||||
|
* `order` has higher precedence. New code should only use `order`. Default value is configurable using {@link setDefaultResultOrder}
|
||||||
|
* or [`--dns-result-order`](https://nodejs.org/docs/latest-v20.x/api/cli.html#--dns-result-orderorder).
|
||||||
|
* @default true (addresses are not reordered)
|
||||||
|
*/
|
||||||
|
verbatim?: boolean | undefined;
|
||||||
|
}
|
||||||
|
export interface LookupOneOptions extends LookupOptions {
|
||||||
|
all?: false | undefined;
|
||||||
|
}
|
||||||
|
export interface LookupAllOptions extends LookupOptions {
|
||||||
|
all: true;
|
||||||
|
}
|
||||||
|
export interface LookupAddress {
|
||||||
|
/**
|
||||||
|
* A string representation of an IPv4 or IPv6 address.
|
||||||
|
*/
|
||||||
|
address: string;
|
||||||
|
/**
|
||||||
|
* `4` or `6`, denoting the family of `address`, or `0` if the address is not an IPv4 or IPv6 address. `0` is a likely indicator of a
|
||||||
|
* bug in the name resolution service used by the operating system.
|
||||||
|
*/
|
||||||
|
family: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Resolves a host name (e.g. `'nodejs.org'`) into the first found A (IPv4) or
|
||||||
|
* AAAA (IPv6) record. All `option` properties are optional. If `options` is an
|
||||||
|
* integer, then it must be `4` or `6` – if `options` is `0` or not provided, then
|
||||||
|
* IPv4 and IPv6 addresses are both returned if found.
|
||||||
|
*
|
||||||
|
* With the `all` option set to `true`, the arguments for `callback` change to `(err, addresses)`, with `addresses` being an array of objects with the
|
||||||
|
* properties `address` and `family`.
|
||||||
|
*
|
||||||
|
* On error, `err` is an `Error` object, where `err.code` is the error code.
|
||||||
|
* Keep in mind that `err.code` will be set to `'ENOTFOUND'` not only when
|
||||||
|
* the host name does not exist but also when the lookup fails in other ways
|
||||||
|
* such as no available file descriptors.
|
||||||
|
*
|
||||||
|
* `dns.lookup()` does not necessarily have anything to do with the DNS protocol.
|
||||||
|
* The implementation uses an operating system facility that can associate names
|
||||||
|
* with addresses and vice versa. This implementation can have subtle but
|
||||||
|
* important consequences on the behavior of any Node.js program. Please take some
|
||||||
|
* time to consult the [Implementation considerations section](https://nodejs.org/docs/latest-v20.x/api/dns.html#implementation-considerations)
|
||||||
|
* before using `dns.lookup()`.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dns from 'node:dns';
|
||||||
|
* const options = {
|
||||||
|
* family: 6,
|
||||||
|
* hints: dns.ADDRCONFIG | dns.V4MAPPED,
|
||||||
|
* };
|
||||||
|
* dns.lookup('example.com', options, (err, address, family) =>
|
||||||
|
* console.log('address: %j family: IPv%s', address, family));
|
||||||
|
* // address: "2606:2800:220:1:248:1893:25c8:1946" family: IPv6
|
||||||
|
*
|
||||||
|
* // When options.all is true, the result will be an Array.
|
||||||
|
* options.all = true;
|
||||||
|
* dns.lookup('example.com', options, (err, addresses) =>
|
||||||
|
* console.log('addresses: %j', addresses));
|
||||||
|
* // addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}]
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If this method is invoked as its [util.promisify()](https://nodejs.org/docs/latest-v20.x/api/util.html#utilpromisifyoriginal) ed
|
||||||
|
* version, and `all` is not set to `true`, it returns a `Promise` for an `Object` with `address` and `family` properties.
|
||||||
|
* @since v0.1.90
|
||||||
|
*/
|
||||||
|
export function lookup(
|
||||||
|
hostname: string,
|
||||||
|
family: number,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
|
||||||
|
): void;
|
||||||
|
export function lookup(
|
||||||
|
hostname: string,
|
||||||
|
options: LookupOneOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
|
||||||
|
): void;
|
||||||
|
export function lookup(
|
||||||
|
hostname: string,
|
||||||
|
options: LookupAllOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void,
|
||||||
|
): void;
|
||||||
|
export function lookup(
|
||||||
|
hostname: string,
|
||||||
|
options: LookupOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, address: string | LookupAddress[], family: number) => void,
|
||||||
|
): void;
|
||||||
|
export function lookup(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
|
||||||
|
): void;
|
||||||
|
export namespace lookup {
|
||||||
|
function __promisify__(hostname: string, options: LookupAllOptions): Promise<LookupAddress[]>;
|
||||||
|
function __promisify__(hostname: string, options?: LookupOneOptions | number): Promise<LookupAddress>;
|
||||||
|
function __promisify__(hostname: string, options: LookupOptions): Promise<LookupAddress | LookupAddress[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Resolves the given `address` and `port` into a host name and service using
|
||||||
|
* the operating system's underlying `getnameinfo` implementation.
|
||||||
|
*
|
||||||
|
* If `address` is not a valid IP address, a `TypeError` will be thrown.
|
||||||
|
* The `port` will be coerced to a number. If it is not a legal port, a `TypeError` will be thrown.
|
||||||
|
*
|
||||||
|
* On an error, `err` is an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object,
|
||||||
|
* where `err.code` is the error code.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dns from 'node:dns';
|
||||||
|
* dns.lookupService('127.0.0.1', 22, (err, hostname, service) => {
|
||||||
|
* console.log(hostname, service);
|
||||||
|
* // Prints: localhost ssh
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If this method is invoked as its [util.promisify()](https://nodejs.org/docs/latest-v20.x/api/util.html#utilpromisifyoriginal) ed
|
||||||
|
* version, it returns a `Promise` for an `Object` with `hostname` and `service` properties.
|
||||||
|
* @since v0.11.14
|
||||||
|
*/
|
||||||
|
export function lookupService(
|
||||||
|
address: string,
|
||||||
|
port: number,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, hostname: string, service: string) => void,
|
||||||
|
): void;
|
||||||
|
export namespace lookupService {
|
||||||
|
function __promisify__(
|
||||||
|
address: string,
|
||||||
|
port: number,
|
||||||
|
): Promise<{
|
||||||
|
hostname: string;
|
||||||
|
service: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
export interface ResolveOptions {
|
||||||
|
ttl: boolean;
|
||||||
|
}
|
||||||
|
export interface ResolveWithTtlOptions extends ResolveOptions {
|
||||||
|
ttl: true;
|
||||||
|
}
|
||||||
|
export interface RecordWithTtl {
|
||||||
|
address: string;
|
||||||
|
ttl: number;
|
||||||
|
}
|
||||||
|
/** @deprecated Use `AnyARecord` or `AnyAaaaRecord` instead. */
|
||||||
|
export type AnyRecordWithTtl = AnyARecord | AnyAaaaRecord;
|
||||||
|
export interface AnyARecord extends RecordWithTtl {
|
||||||
|
type: "A";
|
||||||
|
}
|
||||||
|
export interface AnyAaaaRecord extends RecordWithTtl {
|
||||||
|
type: "AAAA";
|
||||||
|
}
|
||||||
|
export interface CaaRecord {
|
||||||
|
critical: number;
|
||||||
|
issue?: string | undefined;
|
||||||
|
issuewild?: string | undefined;
|
||||||
|
iodef?: string | undefined;
|
||||||
|
contactemail?: string | undefined;
|
||||||
|
contactphone?: string | undefined;
|
||||||
|
}
|
||||||
|
export interface AnyCaaRecord extends CaaRecord {
|
||||||
|
type: "CAA";
|
||||||
|
}
|
||||||
|
export interface MxRecord {
|
||||||
|
priority: number;
|
||||||
|
exchange: string;
|
||||||
|
}
|
||||||
|
export interface AnyMxRecord extends MxRecord {
|
||||||
|
type: "MX";
|
||||||
|
}
|
||||||
|
export interface NaptrRecord {
|
||||||
|
flags: string;
|
||||||
|
service: string;
|
||||||
|
regexp: string;
|
||||||
|
replacement: string;
|
||||||
|
order: number;
|
||||||
|
preference: number;
|
||||||
|
}
|
||||||
|
export interface AnyNaptrRecord extends NaptrRecord {
|
||||||
|
type: "NAPTR";
|
||||||
|
}
|
||||||
|
export interface SoaRecord {
|
||||||
|
nsname: string;
|
||||||
|
hostmaster: string;
|
||||||
|
serial: number;
|
||||||
|
refresh: number;
|
||||||
|
retry: number;
|
||||||
|
expire: number;
|
||||||
|
minttl: number;
|
||||||
|
}
|
||||||
|
export interface AnySoaRecord extends SoaRecord {
|
||||||
|
type: "SOA";
|
||||||
|
}
|
||||||
|
export interface SrvRecord {
|
||||||
|
priority: number;
|
||||||
|
weight: number;
|
||||||
|
port: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
export interface AnySrvRecord extends SrvRecord {
|
||||||
|
type: "SRV";
|
||||||
|
}
|
||||||
|
export interface AnyTxtRecord {
|
||||||
|
type: "TXT";
|
||||||
|
entries: string[];
|
||||||
|
}
|
||||||
|
export interface AnyNsRecord {
|
||||||
|
type: "NS";
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
export interface AnyPtrRecord {
|
||||||
|
type: "PTR";
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
export interface AnyCnameRecord {
|
||||||
|
type: "CNAME";
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
export type AnyRecord =
|
||||||
|
| AnyARecord
|
||||||
|
| AnyAaaaRecord
|
||||||
|
| AnyCaaRecord
|
||||||
|
| AnyCnameRecord
|
||||||
|
| AnyMxRecord
|
||||||
|
| AnyNaptrRecord
|
||||||
|
| AnyNsRecord
|
||||||
|
| AnyPtrRecord
|
||||||
|
| AnySoaRecord
|
||||||
|
| AnySrvRecord
|
||||||
|
| AnyTxtRecord;
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve a host name (e.g. `'nodejs.org'`) into an array
|
||||||
|
* of the resource records. The `callback` function has arguments `(err, records)`. When successful, `records` will be an array of resource
|
||||||
|
* records. The type and structure of individual results varies based on `rrtype`:
|
||||||
|
*
|
||||||
|
* <omitted>
|
||||||
|
*
|
||||||
|
* On error, `err` is an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object,
|
||||||
|
* where `err.code` is one of the `DNS error codes`.
|
||||||
|
* @since v0.1.27
|
||||||
|
* @param hostname Host name to resolve.
|
||||||
|
* @param [rrtype='A'] Resource record type.
|
||||||
|
*/
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: "A" | "AAAA" | "CNAME" | "NS" | "PTR",
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: "ANY",
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: AnyRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: "CAA",
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, address: CaaRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: "MX",
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: MxRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: "NAPTR",
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: NaptrRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: "SOA",
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: SoaRecord) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: "SRV",
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: SrvRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: "TXT",
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[][]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: string,
|
||||||
|
callback: (
|
||||||
|
err: NodeJS.ErrnoException | null,
|
||||||
|
addresses:
|
||||||
|
| string[]
|
||||||
|
| CaaRecord[]
|
||||||
|
| MxRecord[]
|
||||||
|
| NaptrRecord[]
|
||||||
|
| SoaRecord
|
||||||
|
| SrvRecord[]
|
||||||
|
| string[][]
|
||||||
|
| AnyRecord[],
|
||||||
|
) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolve {
|
||||||
|
function __promisify__(hostname: string, rrtype?: "A" | "AAAA" | "CNAME" | "NS" | "PTR"): Promise<string[]>;
|
||||||
|
function __promisify__(hostname: string, rrtype: "ANY"): Promise<AnyRecord[]>;
|
||||||
|
function __promisify__(hostname: string, rrtype: "CAA"): Promise<CaaRecord[]>;
|
||||||
|
function __promisify__(hostname: string, rrtype: "MX"): Promise<MxRecord[]>;
|
||||||
|
function __promisify__(hostname: string, rrtype: "NAPTR"): Promise<NaptrRecord[]>;
|
||||||
|
function __promisify__(hostname: string, rrtype: "SOA"): Promise<SoaRecord>;
|
||||||
|
function __promisify__(hostname: string, rrtype: "SRV"): Promise<SrvRecord[]>;
|
||||||
|
function __promisify__(hostname: string, rrtype: "TXT"): Promise<string[][]>;
|
||||||
|
function __promisify__(
|
||||||
|
hostname: string,
|
||||||
|
rrtype: string,
|
||||||
|
): Promise<
|
||||||
|
| string[]
|
||||||
|
| CaaRecord[]
|
||||||
|
| MxRecord[]
|
||||||
|
| NaptrRecord[]
|
||||||
|
| SoaRecord
|
||||||
|
| SrvRecord[]
|
||||||
|
| string[][]
|
||||||
|
| AnyRecord[]
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the `hostname`. The `addresses` argument passed to the `callback` function
|
||||||
|
* will contain an array of IPv4 addresses (e.g.`['74.125.79.104', '74.125.79.105', '74.125.79.106']`).
|
||||||
|
* @since v0.1.16
|
||||||
|
* @param hostname Host name to resolve.
|
||||||
|
*/
|
||||||
|
export function resolve4(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve4(
|
||||||
|
hostname: string,
|
||||||
|
options: ResolveWithTtlOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: RecordWithTtl[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve4(
|
||||||
|
hostname: string,
|
||||||
|
options: ResolveOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[] | RecordWithTtl[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolve4 {
|
||||||
|
function __promisify__(hostname: string): Promise<string[]>;
|
||||||
|
function __promisify__(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>;
|
||||||
|
function __promisify__(hostname: string, options?: ResolveOptions): Promise<string[] | RecordWithTtl[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve IPv6 addresses (`AAAA` records) for the `hostname`. The `addresses` argument passed to the `callback` function
|
||||||
|
* will contain an array of IPv6 addresses.
|
||||||
|
* @since v0.1.16
|
||||||
|
* @param hostname Host name to resolve.
|
||||||
|
*/
|
||||||
|
export function resolve6(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve6(
|
||||||
|
hostname: string,
|
||||||
|
options: ResolveWithTtlOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: RecordWithTtl[]) => void,
|
||||||
|
): void;
|
||||||
|
export function resolve6(
|
||||||
|
hostname: string,
|
||||||
|
options: ResolveOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[] | RecordWithTtl[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolve6 {
|
||||||
|
function __promisify__(hostname: string): Promise<string[]>;
|
||||||
|
function __promisify__(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>;
|
||||||
|
function __promisify__(hostname: string, options?: ResolveOptions): Promise<string[] | RecordWithTtl[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve `CNAME` records for the `hostname`. The `addresses` argument passed to the `callback` function
|
||||||
|
* will contain an array of canonical name records available for the `hostname` (e.g. `['bar.example.com']`).
|
||||||
|
* @since v0.3.2
|
||||||
|
*/
|
||||||
|
export function resolveCname(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveCname {
|
||||||
|
function __promisify__(hostname: string): Promise<string[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve `CAA` records for the `hostname`. The `addresses` argument passed to the `callback` function
|
||||||
|
* will contain an array of certification authority authorization records
|
||||||
|
* available for the `hostname` (e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'}, {critical: 128, issue: 'pki.example.com'}]`).
|
||||||
|
* @since v15.0.0, v14.17.0
|
||||||
|
*/
|
||||||
|
export function resolveCaa(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, records: CaaRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveCaa {
|
||||||
|
function __promisify__(hostname: string): Promise<CaaRecord[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve mail exchange records (`MX` records) for the `hostname`. The `addresses` argument passed to the `callback` function will
|
||||||
|
* contain an array of objects containing both a `priority` and `exchange` property (e.g. `[{priority: 10, exchange: 'mx.example.com'}, ...]`).
|
||||||
|
* @since v0.1.27
|
||||||
|
*/
|
||||||
|
export function resolveMx(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: MxRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveMx {
|
||||||
|
function __promisify__(hostname: string): Promise<MxRecord[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve regular expression-based records (`NAPTR` records) for the `hostname`. The `addresses` argument passed to the `callback` function will contain an array of
|
||||||
|
* objects with the following properties:
|
||||||
|
*
|
||||||
|
* * `flags`
|
||||||
|
* * `service`
|
||||||
|
* * `regexp`
|
||||||
|
* * `replacement`
|
||||||
|
* * `order`
|
||||||
|
* * `preference`
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* flags: 's',
|
||||||
|
* service: 'SIP+D2U',
|
||||||
|
* regexp: '',
|
||||||
|
* replacement: '_sip._udp.example.com',
|
||||||
|
* order: 30,
|
||||||
|
* preference: 100
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.9.12
|
||||||
|
*/
|
||||||
|
export function resolveNaptr(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: NaptrRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveNaptr {
|
||||||
|
function __promisify__(hostname: string): Promise<NaptrRecord[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve name server records (`NS` records) for the `hostname`. The `addresses` argument passed to the `callback` function will
|
||||||
|
* contain an array of name server records available for `hostname` (e.g. `['ns1.example.com', 'ns2.example.com']`).
|
||||||
|
* @since v0.1.90
|
||||||
|
*/
|
||||||
|
export function resolveNs(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveNs {
|
||||||
|
function __promisify__(hostname: string): Promise<string[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve pointer records (`PTR` records) for the `hostname`. The `addresses` argument passed to the `callback` function will
|
||||||
|
* be an array of strings containing the reply records.
|
||||||
|
* @since v6.0.0
|
||||||
|
*/
|
||||||
|
export function resolvePtr(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolvePtr {
|
||||||
|
function __promisify__(hostname: string): Promise<string[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve a start of authority record (`SOA` record) for
|
||||||
|
* the `hostname`. The `address` argument passed to the `callback` function will
|
||||||
|
* be an object with the following properties:
|
||||||
|
*
|
||||||
|
* * `nsname`
|
||||||
|
* * `hostmaster`
|
||||||
|
* * `serial`
|
||||||
|
* * `refresh`
|
||||||
|
* * `retry`
|
||||||
|
* * `expire`
|
||||||
|
* * `minttl`
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* nsname: 'ns.example.com',
|
||||||
|
* hostmaster: 'root.example.com',
|
||||||
|
* serial: 2013101809,
|
||||||
|
* refresh: 10000,
|
||||||
|
* retry: 2400,
|
||||||
|
* expire: 604800,
|
||||||
|
* minttl: 3600
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.11.10
|
||||||
|
*/
|
||||||
|
export function resolveSoa(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, address: SoaRecord) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveSoa {
|
||||||
|
function __promisify__(hostname: string): Promise<SoaRecord>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve service records (`SRV` records) for the `hostname`. The `addresses` argument passed to the `callback` function will
|
||||||
|
* be an array of objects with the following properties:
|
||||||
|
*
|
||||||
|
* * `priority`
|
||||||
|
* * `weight`
|
||||||
|
* * `port`
|
||||||
|
* * `name`
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* priority: 10,
|
||||||
|
* weight: 5,
|
||||||
|
* port: 21223,
|
||||||
|
* name: 'service.example.com'
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.1.27
|
||||||
|
*/
|
||||||
|
export function resolveSrv(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: SrvRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveSrv {
|
||||||
|
function __promisify__(hostname: string): Promise<SrvRecord[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve text queries (`TXT` records) for the `hostname`. The `records` argument passed to the `callback` function is a
|
||||||
|
* two-dimensional array of the text records available for `hostname` (e.g.`[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of
|
||||||
|
* one record. Depending on the use case, these could be either joined together or
|
||||||
|
* treated separately.
|
||||||
|
* @since v0.1.27
|
||||||
|
*/
|
||||||
|
export function resolveTxt(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: string[][]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveTxt {
|
||||||
|
function __promisify__(hostname: string): Promise<string[][]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses the DNS protocol to resolve all records (also known as `ANY` or `*` query).
|
||||||
|
* The `ret` argument passed to the `callback` function will be an array containing
|
||||||
|
* various types of records. Each object has a property `type` that indicates the
|
||||||
|
* type of the current record. And depending on the `type`, additional properties
|
||||||
|
* will be present on the object:
|
||||||
|
*
|
||||||
|
* <omitted>
|
||||||
|
*
|
||||||
|
* Here is an example of the `ret` object passed to the callback:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* [ { type: 'A', address: '127.0.0.1', ttl: 299 },
|
||||||
|
* { type: 'CNAME', value: 'example.com' },
|
||||||
|
* { type: 'MX', exchange: 'alt4.aspmx.l.example.com', priority: 50 },
|
||||||
|
* { type: 'NS', value: 'ns1.example.com' },
|
||||||
|
* { type: 'TXT', entries: [ 'v=spf1 include:_spf.example.com ~all' ] },
|
||||||
|
* { type: 'SOA',
|
||||||
|
* nsname: 'ns1.example.com',
|
||||||
|
* hostmaster: 'admin.example.com',
|
||||||
|
* serial: 156696742,
|
||||||
|
* refresh: 900,
|
||||||
|
* retry: 900,
|
||||||
|
* expire: 1800,
|
||||||
|
* minttl: 60 } ]
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* DNS server operators may choose not to respond to `ANY` queries. It may be better to call individual methods like {@link resolve4}, {@link resolveMx}, and so on. For more details, see
|
||||||
|
* [RFC 8482](https://tools.ietf.org/html/rfc8482).
|
||||||
|
*/
|
||||||
|
export function resolveAny(
|
||||||
|
hostname: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, addresses: AnyRecord[]) => void,
|
||||||
|
): void;
|
||||||
|
export namespace resolveAny {
|
||||||
|
function __promisify__(hostname: string): Promise<AnyRecord[]>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an
|
||||||
|
* array of host names.
|
||||||
|
*
|
||||||
|
* On error, `err` is an [`Error`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-error) object, where `err.code` is
|
||||||
|
* one of the [DNS error codes](https://nodejs.org/docs/latest-v20.x/api/dns.html#error-codes).
|
||||||
|
* @since v0.1.16
|
||||||
|
*/
|
||||||
|
export function reverse(
|
||||||
|
ip: string,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, hostnames: string[]) => void,
|
||||||
|
): void;
|
||||||
|
/**
|
||||||
|
* Get the default value for `order` in {@link lookup} and [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromiseslookuphostname-options).
|
||||||
|
* The value could be:
|
||||||
|
*
|
||||||
|
* * `ipv4first`: for `order` defaulting to `ipv4first`.
|
||||||
|
* * `ipv6first`: for `order` defaulting to `ipv6first`.
|
||||||
|
* * `verbatim`: for `order` defaulting to `verbatim`.
|
||||||
|
* @since v18.17.0
|
||||||
|
*/
|
||||||
|
export function getDefaultResultOrder(): "ipv4first" | "ipv6first" | "verbatim";
|
||||||
|
/**
|
||||||
|
* Sets the IP address and port of servers to be used when performing DNS
|
||||||
|
* resolution. The `servers` argument is an array of [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6) formatted
|
||||||
|
* addresses. If the port is the IANA default DNS port (53) it can be omitted.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* dns.setServers([
|
||||||
|
* '4.4.4.4',
|
||||||
|
* '[2001:4860:4860::8888]',
|
||||||
|
* '4.4.4.4:1053',
|
||||||
|
* '[2001:4860:4860::8888]:1053',
|
||||||
|
* ]);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* An error will be thrown if an invalid address is provided.
|
||||||
|
*
|
||||||
|
* The `dns.setServers()` method must not be called while a DNS query is in
|
||||||
|
* progress.
|
||||||
|
*
|
||||||
|
* The {@link setServers} method affects only {@link resolve}, `dns.resolve*()` and {@link reverse} (and specifically _not_ {@link lookup}).
|
||||||
|
*
|
||||||
|
* This method works much like [resolve.conf](https://man7.org/linux/man-pages/man5/resolv.conf.5.html).
|
||||||
|
* That is, if attempting to resolve with the first server provided results in a `NOTFOUND` error, the `resolve()` method will _not_ attempt to resolve with
|
||||||
|
* subsequent servers provided. Fallback DNS servers will only be used if the
|
||||||
|
* earlier ones time out or result in some other error.
|
||||||
|
* @since v0.11.3
|
||||||
|
* @param servers array of [RFC 5952](https://datatracker.ietf.org/doc/html/rfc5952#section-6) formatted addresses
|
||||||
|
*/
|
||||||
|
export function setServers(servers: readonly string[]): void;
|
||||||
|
/**
|
||||||
|
* Returns an array of IP address strings, formatted according to [RFC 5952](https://tools.ietf.org/html/rfc5952#section-6),
|
||||||
|
* that are currently configured for DNS resolution. A string will include a port
|
||||||
|
* section if a custom port is used.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* [
|
||||||
|
* '4.4.4.4',
|
||||||
|
* '2001:4860:4860::8888',
|
||||||
|
* '4.4.4.4:1053',
|
||||||
|
* '[2001:4860:4860::8888]:1053',
|
||||||
|
* ]
|
||||||
|
* ```
|
||||||
|
* @since v0.11.3
|
||||||
|
*/
|
||||||
|
export function getServers(): string[];
|
||||||
|
/**
|
||||||
|
* Set the default value of `order` in {@link lookup} and [`dnsPromises.lookup()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnspromiseslookuphostname-options).
|
||||||
|
* The value could be:
|
||||||
|
*
|
||||||
|
* * `ipv4first`: sets default `order` to `ipv4first`.
|
||||||
|
* * `ipv6first`: sets default `order` to `ipv6first`.
|
||||||
|
* * `verbatim`: sets default `order` to `verbatim`.
|
||||||
|
*
|
||||||
|
* The default is `verbatim` and {@link setDefaultResultOrder} have higher
|
||||||
|
* priority than [`--dns-result-order`](https://nodejs.org/docs/latest-v20.x/api/cli.html#--dns-result-orderorder). When using
|
||||||
|
* [worker threads](https://nodejs.org/docs/latest-v20.x/api/worker_threads.html), {@link setDefaultResultOrder} from the main
|
||||||
|
* thread won't affect the default dns orders in workers.
|
||||||
|
* @since v16.4.0, v14.18.0
|
||||||
|
* @param order must be `'ipv4first'`, `'ipv6first'` or `'verbatim'`.
|
||||||
|
*/
|
||||||
|
export function setDefaultResultOrder(order: "ipv4first" | "ipv6first" | "verbatim"): void;
|
||||||
|
// Error codes
|
||||||
|
export const NODATA: "ENODATA";
|
||||||
|
export const FORMERR: "EFORMERR";
|
||||||
|
export const SERVFAIL: "ESERVFAIL";
|
||||||
|
export const NOTFOUND: "ENOTFOUND";
|
||||||
|
export const NOTIMP: "ENOTIMP";
|
||||||
|
export const REFUSED: "EREFUSED";
|
||||||
|
export const BADQUERY: "EBADQUERY";
|
||||||
|
export const BADNAME: "EBADNAME";
|
||||||
|
export const BADFAMILY: "EBADFAMILY";
|
||||||
|
export const BADRESP: "EBADRESP";
|
||||||
|
export const CONNREFUSED: "ECONNREFUSED";
|
||||||
|
export const TIMEOUT: "ETIMEOUT";
|
||||||
|
export const EOF: "EOF";
|
||||||
|
export const FILE: "EFILE";
|
||||||
|
export const NOMEM: "ENOMEM";
|
||||||
|
export const DESTRUCTION: "EDESTRUCTION";
|
||||||
|
export const BADSTR: "EBADSTR";
|
||||||
|
export const BADFLAGS: "EBADFLAGS";
|
||||||
|
export const NONAME: "ENONAME";
|
||||||
|
export const BADHINTS: "EBADHINTS";
|
||||||
|
export const NOTINITIALIZED: "ENOTINITIALIZED";
|
||||||
|
export const LOADIPHLPAPI: "ELOADIPHLPAPI";
|
||||||
|
export const ADDRGETNETWORKPARAMS: "EADDRGETNETWORKPARAMS";
|
||||||
|
export const CANCELLED: "ECANCELLED";
|
||||||
|
export interface ResolverOptions {
|
||||||
|
/**
|
||||||
|
* Query timeout in milliseconds, or `-1` to use the default timeout.
|
||||||
|
*/
|
||||||
|
timeout?: number | undefined;
|
||||||
|
/**
|
||||||
|
* The number of tries the resolver will try contacting each name server before giving up.
|
||||||
|
* @default 4
|
||||||
|
*/
|
||||||
|
tries?: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An independent resolver for DNS requests.
|
||||||
|
*
|
||||||
|
* Creating a new resolver uses the default server settings. Setting
|
||||||
|
* the servers used for a resolver using [`resolver.setServers()`](https://nodejs.org/docs/latest-v20.x/api/dns.html#dnssetserversservers) does not affect
|
||||||
|
* other resolvers:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Resolver } from 'node:dns';
|
||||||
|
* const resolver = new Resolver();
|
||||||
|
* resolver.setServers(['4.4.4.4']);
|
||||||
|
*
|
||||||
|
* // This request will use the server at 4.4.4.4, independent of global settings.
|
||||||
|
* resolver.resolve4('example.org', (err, addresses) => {
|
||||||
|
* // ...
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The following methods from the `node:dns` module are available:
|
||||||
|
*
|
||||||
|
* * `resolver.getServers()`
|
||||||
|
* * `resolver.resolve()`
|
||||||
|
* * `resolver.resolve4()`
|
||||||
|
* * `resolver.resolve6()`
|
||||||
|
* * `resolver.resolveAny()`
|
||||||
|
* * `resolver.resolveCaa()`
|
||||||
|
* * `resolver.resolveCname()`
|
||||||
|
* * `resolver.resolveMx()`
|
||||||
|
* * `resolver.resolveNaptr()`
|
||||||
|
* * `resolver.resolveNs()`
|
||||||
|
* * `resolver.resolvePtr()`
|
||||||
|
* * `resolver.resolveSoa()`
|
||||||
|
* * `resolver.resolveSrv()`
|
||||||
|
* * `resolver.resolveTxt()`
|
||||||
|
* * `resolver.reverse()`
|
||||||
|
* * `resolver.setServers()`
|
||||||
|
* @since v8.3.0
|
||||||
|
*/
|
||||||
|
export class Resolver {
|
||||||
|
constructor(options?: ResolverOptions);
|
||||||
|
/**
|
||||||
|
* Cancel all outstanding DNS queries made by this resolver. The corresponding
|
||||||
|
* callbacks will be called with an error with code `ECANCELLED`.
|
||||||
|
* @since v8.3.0
|
||||||
|
*/
|
||||||
|
cancel(): void;
|
||||||
|
getServers: typeof getServers;
|
||||||
|
resolve: typeof resolve;
|
||||||
|
resolve4: typeof resolve4;
|
||||||
|
resolve6: typeof resolve6;
|
||||||
|
resolveAny: typeof resolveAny;
|
||||||
|
resolveCaa: typeof resolveCaa;
|
||||||
|
resolveCname: typeof resolveCname;
|
||||||
|
resolveMx: typeof resolveMx;
|
||||||
|
resolveNaptr: typeof resolveNaptr;
|
||||||
|
resolveNs: typeof resolveNs;
|
||||||
|
resolvePtr: typeof resolvePtr;
|
||||||
|
resolveSoa: typeof resolveSoa;
|
||||||
|
resolveSrv: typeof resolveSrv;
|
||||||
|
resolveTxt: typeof resolveTxt;
|
||||||
|
reverse: typeof reverse;
|
||||||
|
/**
|
||||||
|
* The resolver instance will send its requests from the specified IP address.
|
||||||
|
* This allows programs to specify outbound interfaces when used on multi-homed
|
||||||
|
* systems.
|
||||||
|
*
|
||||||
|
* If a v4 or v6 address is not specified, it is set to the default and the
|
||||||
|
* operating system will choose a local address automatically.
|
||||||
|
*
|
||||||
|
* The resolver will use the v4 local address when making requests to IPv4 DNS
|
||||||
|
* servers, and the v6 local address when making requests to IPv6 DNS servers.
|
||||||
|
* The `rrtype` of resolution requests has no impact on the local address used.
|
||||||
|
* @since v15.1.0, v14.17.0
|
||||||
|
* @param [ipv4='0.0.0.0'] A string representation of an IPv4 address.
|
||||||
|
* @param [ipv6='::0'] A string representation of an IPv6 address.
|
||||||
|
*/
|
||||||
|
setLocalAddress(ipv4?: string, ipv6?: string): void;
|
||||||
|
setServers: typeof setServers;
|
||||||
|
}
|
||||||
|
export { dnsPromises as promises };
|
||||||
|
}
|
||||||
|
declare module "node:dns" {
|
||||||
|
export * from "dns";
|
||||||
|
}
|
||||||
170
node_modules/@types/node/domain.d.ts
generated
vendored
Normal file
170
node_modules/@types/node/domain.d.ts
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/**
|
||||||
|
* **This module is pending deprecation.** Once a replacement API has been
|
||||||
|
* finalized, this module will be fully deprecated. Most developers should
|
||||||
|
* **not** have cause to use this module. Users who absolutely must have
|
||||||
|
* the functionality that domains provide may rely on it for the time being
|
||||||
|
* but should expect to have to migrate to a different solution
|
||||||
|
* in the future.
|
||||||
|
*
|
||||||
|
* Domains provide a way to handle multiple different IO operations as a
|
||||||
|
* single group. If any of the event emitters or callbacks registered to a
|
||||||
|
* domain emit an `'error'` event, or throw an error, then the domain object
|
||||||
|
* will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to
|
||||||
|
* exit immediately with an error code.
|
||||||
|
* @deprecated Since v1.4.2 - Deprecated
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/domain.js)
|
||||||
|
*/
|
||||||
|
declare module "domain" {
|
||||||
|
import EventEmitter = require("node:events");
|
||||||
|
/**
|
||||||
|
* The `Domain` class encapsulates the functionality of routing errors and
|
||||||
|
* uncaught exceptions to the active `Domain` object.
|
||||||
|
*
|
||||||
|
* To handle the errors that it catches, listen to its `'error'` event.
|
||||||
|
*/
|
||||||
|
class Domain extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* An array of timers and event emitters that have been explicitly added
|
||||||
|
* to the domain.
|
||||||
|
*/
|
||||||
|
members: Array<EventEmitter | NodeJS.Timer>;
|
||||||
|
/**
|
||||||
|
* The `enter()` method is plumbing used by the `run()`, `bind()`, and `intercept()` methods to set the active domain. It sets `domain.active` and `process.domain` to the domain, and implicitly
|
||||||
|
* pushes the domain onto the domain
|
||||||
|
* stack managed by the domain module (see {@link exit} for details on the
|
||||||
|
* domain stack). The call to `enter()` delimits the beginning of a chain of
|
||||||
|
* asynchronous calls and I/O operations bound to a domain.
|
||||||
|
*
|
||||||
|
* Calling `enter()` changes only the active domain, and does not alter the domain
|
||||||
|
* itself. `enter()` and `exit()` can be called an arbitrary number of times on a
|
||||||
|
* single domain.
|
||||||
|
*/
|
||||||
|
enter(): void;
|
||||||
|
/**
|
||||||
|
* The `exit()` method exits the current domain, popping it off the domain stack.
|
||||||
|
* Any time execution is going to switch to the context of a different chain of
|
||||||
|
* asynchronous calls, it's important to ensure that the current domain is exited.
|
||||||
|
* The call to `exit()` delimits either the end of or an interruption to the chain
|
||||||
|
* of asynchronous calls and I/O operations bound to a domain.
|
||||||
|
*
|
||||||
|
* If there are multiple, nested domains bound to the current execution context, `exit()` will exit any domains nested within this domain.
|
||||||
|
*
|
||||||
|
* Calling `exit()` changes only the active domain, and does not alter the domain
|
||||||
|
* itself. `enter()` and `exit()` can be called an arbitrary number of times on a
|
||||||
|
* single domain.
|
||||||
|
*/
|
||||||
|
exit(): void;
|
||||||
|
/**
|
||||||
|
* Run the supplied function in the context of the domain, implicitly
|
||||||
|
* binding all event emitters, timers, and low-level requests that are
|
||||||
|
* created in that context. Optionally, arguments can be passed to
|
||||||
|
* the function.
|
||||||
|
*
|
||||||
|
* This is the most basic way to use a domain.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import domain from 'node:domain';
|
||||||
|
* import fs from 'node:fs';
|
||||||
|
* const d = domain.create();
|
||||||
|
* d.on('error', (er) => {
|
||||||
|
* console.error('Caught error!', er);
|
||||||
|
* });
|
||||||
|
* d.run(() => {
|
||||||
|
* process.nextTick(() => {
|
||||||
|
* setTimeout(() => { // Simulating some various async stuff
|
||||||
|
* fs.open('non-existent file', 'r', (er, fd) => {
|
||||||
|
* if (er) throw er;
|
||||||
|
* // proceed...
|
||||||
|
* });
|
||||||
|
* }, 100);
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In this example, the `d.on('error')` handler will be triggered, rather
|
||||||
|
* than crashing the program.
|
||||||
|
*/
|
||||||
|
run<T>(fn: (...args: any[]) => T, ...args: any[]): T;
|
||||||
|
/**
|
||||||
|
* Explicitly adds an emitter to the domain. If any event handlers called by
|
||||||
|
* the emitter throw an error, or if the emitter emits an `'error'` event, it
|
||||||
|
* will be routed to the domain's `'error'` event, just like with implicit
|
||||||
|
* binding.
|
||||||
|
*
|
||||||
|
* This also works with timers that are returned from `setInterval()` and `setTimeout()`. If their callback function throws, it will be caught by
|
||||||
|
* the domain `'error'` handler.
|
||||||
|
*
|
||||||
|
* If the Timer or `EventEmitter` was already bound to a domain, it is removed
|
||||||
|
* from that one, and bound to this one instead.
|
||||||
|
* @param emitter emitter or timer to be added to the domain
|
||||||
|
*/
|
||||||
|
add(emitter: EventEmitter | NodeJS.Timer): void;
|
||||||
|
/**
|
||||||
|
* The opposite of {@link add}. Removes domain handling from the
|
||||||
|
* specified emitter.
|
||||||
|
* @param emitter emitter or timer to be removed from the domain
|
||||||
|
*/
|
||||||
|
remove(emitter: EventEmitter | NodeJS.Timer): void;
|
||||||
|
/**
|
||||||
|
* The returned function will be a wrapper around the supplied callback
|
||||||
|
* function. When the returned function is called, any errors that are
|
||||||
|
* thrown will be routed to the domain's `'error'` event.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const d = domain.create();
|
||||||
|
*
|
||||||
|
* function readSomeFile(filename, cb) {
|
||||||
|
* fs.readFile(filename, 'utf8', d.bind((er, data) => {
|
||||||
|
* // If this throws, it will also be passed to the domain.
|
||||||
|
* return cb(er, data ? JSON.parse(data) : null);
|
||||||
|
* }));
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* d.on('error', (er) => {
|
||||||
|
* // An error occurred somewhere. If we throw it now, it will crash the program
|
||||||
|
* // with the normal line number and stack message.
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @param callback The callback function
|
||||||
|
* @return The bound function
|
||||||
|
*/
|
||||||
|
bind<T extends Function>(callback: T): T;
|
||||||
|
/**
|
||||||
|
* This method is almost identical to {@link bind}. However, in
|
||||||
|
* addition to catching thrown errors, it will also intercept `Error` objects sent as the first argument to the function.
|
||||||
|
*
|
||||||
|
* In this way, the common `if (err) return callback(err);` pattern can be replaced
|
||||||
|
* with a single error handler in a single place.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const d = domain.create();
|
||||||
|
*
|
||||||
|
* function readSomeFile(filename, cb) {
|
||||||
|
* fs.readFile(filename, 'utf8', d.intercept((data) => {
|
||||||
|
* // Note, the first argument is never passed to the
|
||||||
|
* // callback since it is assumed to be the 'Error' argument
|
||||||
|
* // and thus intercepted by the domain.
|
||||||
|
*
|
||||||
|
* // If this throws, it will also be passed to the domain
|
||||||
|
* // so the error-handling logic can be moved to the 'error'
|
||||||
|
* // event on the domain instead of being repeated throughout
|
||||||
|
* // the program.
|
||||||
|
* return cb(null, JSON.parse(data));
|
||||||
|
* }));
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* d.on('error', (er) => {
|
||||||
|
* // An error occurred somewhere. If we throw it now, it will crash the program
|
||||||
|
* // with the normal line number and stack message.
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @param callback The callback function
|
||||||
|
* @return The intercepted function
|
||||||
|
*/
|
||||||
|
intercept<T extends Function>(callback: T): T;
|
||||||
|
}
|
||||||
|
function create(): Domain;
|
||||||
|
}
|
||||||
|
declare module "node:domain" {
|
||||||
|
export * from "domain";
|
||||||
|
}
|
||||||
977
node_modules/@types/node/events.d.ts
generated
vendored
Normal file
977
node_modules/@types/node/events.d.ts
generated
vendored
Normal file
@@ -0,0 +1,977 @@
|
|||||||
|
/**
|
||||||
|
* Much of the Node.js core API is built around an idiomatic asynchronous
|
||||||
|
* event-driven architecture in which certain kinds of objects (called "emitters")
|
||||||
|
* emit named events that cause `Function` objects ("listeners") to be called.
|
||||||
|
*
|
||||||
|
* For instance: a `net.Server` object emits an event each time a peer
|
||||||
|
* connects to it; a `fs.ReadStream` emits an event when the file is opened;
|
||||||
|
* a `stream` emits an event whenever data is available to be read.
|
||||||
|
*
|
||||||
|
* All objects that emit events are instances of the `EventEmitter` class. These
|
||||||
|
* objects expose an `eventEmitter.on()` function that allows one or more
|
||||||
|
* functions to be attached to named events emitted by the object. Typically,
|
||||||
|
* event names are camel-cased strings but any valid JavaScript property key
|
||||||
|
* can be used.
|
||||||
|
*
|
||||||
|
* When the `EventEmitter` object emits an event, all of the functions attached
|
||||||
|
* to that specific event are called _synchronously_. Any values returned by the
|
||||||
|
* called listeners are _ignored_ and discarded.
|
||||||
|
*
|
||||||
|
* The following example shows a simple `EventEmitter` instance with a single
|
||||||
|
* listener. The `eventEmitter.on()` method is used to register listeners, while
|
||||||
|
* the `eventEmitter.emit()` method is used to trigger the event.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
*
|
||||||
|
* class MyEmitter extends EventEmitter {}
|
||||||
|
*
|
||||||
|
* const myEmitter = new MyEmitter();
|
||||||
|
* myEmitter.on('event', () => {
|
||||||
|
* console.log('an event occurred!');
|
||||||
|
* });
|
||||||
|
* myEmitter.emit('event');
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/events.js)
|
||||||
|
*/
|
||||||
|
declare module "events" {
|
||||||
|
import { AsyncResource, AsyncResourceOptions } from "node:async_hooks";
|
||||||
|
interface EventEmitterOptions {
|
||||||
|
/**
|
||||||
|
* Enables automatic capturing of promise rejection.
|
||||||
|
*/
|
||||||
|
captureRejections?: boolean | undefined;
|
||||||
|
}
|
||||||
|
interface StaticEventEmitterOptions {
|
||||||
|
/**
|
||||||
|
* Can be used to cancel awaiting events.
|
||||||
|
*/
|
||||||
|
signal?: AbortSignal | undefined;
|
||||||
|
}
|
||||||
|
interface StaticEventEmitterIteratorOptions extends StaticEventEmitterOptions {
|
||||||
|
/**
|
||||||
|
* Names of events that will end the iteration.
|
||||||
|
*/
|
||||||
|
close?: string[] | undefined;
|
||||||
|
/**
|
||||||
|
* The high watermark. The emitter is paused every time the size of events being buffered is higher than it.
|
||||||
|
* Supported only on emitters implementing `pause()` and `resume()` methods.
|
||||||
|
* @default Number.MAX_SAFE_INTEGER
|
||||||
|
*/
|
||||||
|
highWaterMark?: number | undefined;
|
||||||
|
/**
|
||||||
|
* The low watermark. The emitter is resumed every time the size of events being buffered is lower than it.
|
||||||
|
* Supported only on emitters implementing `pause()` and `resume()` methods.
|
||||||
|
* @default 1
|
||||||
|
*/
|
||||||
|
lowWaterMark?: number | undefined;
|
||||||
|
}
|
||||||
|
interface EventEmitter<T extends EventMap<T> = DefaultEventMap> extends NodeJS.EventEmitter<T> {}
|
||||||
|
type EventMap<T> = Record<keyof T, any[]> | DefaultEventMap;
|
||||||
|
type DefaultEventMap = [never];
|
||||||
|
type AnyRest = [...args: any[]];
|
||||||
|
type Args<K, T> = T extends DefaultEventMap ? AnyRest : (
|
||||||
|
K extends keyof T ? T[K] : never
|
||||||
|
);
|
||||||
|
type Key<K, T> = T extends DefaultEventMap ? string | symbol : K | keyof T;
|
||||||
|
type Key2<K, T> = T extends DefaultEventMap ? string | symbol : K & keyof T;
|
||||||
|
type Listener<K, T, F> = T extends DefaultEventMap ? F : (
|
||||||
|
K extends keyof T ? (
|
||||||
|
T[K] extends unknown[] ? (...args: T[K]) => void : never
|
||||||
|
)
|
||||||
|
: never
|
||||||
|
);
|
||||||
|
type Listener1<K, T> = Listener<K, T, (...args: any[]) => void>;
|
||||||
|
type Listener2<K, T> = Listener<K, T, Function>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `EventEmitter` class is defined and exposed by the `node:events` module:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* All `EventEmitter`s emit the event `'newListener'` when new listeners are
|
||||||
|
* added and `'removeListener'` when existing listeners are removed.
|
||||||
|
*
|
||||||
|
* It supports the following option:
|
||||||
|
* @since v0.1.26
|
||||||
|
*/
|
||||||
|
class EventEmitter<T extends EventMap<T> = DefaultEventMap> {
|
||||||
|
constructor(options?: EventEmitterOptions);
|
||||||
|
|
||||||
|
[EventEmitter.captureRejectionSymbol]?<K>(error: Error, event: Key<K, T>, ...args: Args<K, T>): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a `Promise` that is fulfilled when the `EventEmitter` emits the given
|
||||||
|
* event or that is rejected if the `EventEmitter` emits `'error'` while waiting.
|
||||||
|
* The `Promise` will resolve with an array of all the arguments emitted to the
|
||||||
|
* given event.
|
||||||
|
*
|
||||||
|
* This method is intentionally generic and works with the web platform [EventTarget](https://dom.spec.whatwg.org/#interface-eventtarget) interface, which has no special`'error'` event
|
||||||
|
* semantics and does not listen to the `'error'` event.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { once, EventEmitter } from 'node:events';
|
||||||
|
* import process from 'node:process';
|
||||||
|
*
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
*
|
||||||
|
* process.nextTick(() => {
|
||||||
|
* ee.emit('myevent', 42);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* const [value] = await once(ee, 'myevent');
|
||||||
|
* console.log(value);
|
||||||
|
*
|
||||||
|
* const err = new Error('kaboom');
|
||||||
|
* process.nextTick(() => {
|
||||||
|
* ee.emit('error', err);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* try {
|
||||||
|
* await once(ee, 'myevent');
|
||||||
|
* } catch (err) {
|
||||||
|
* console.error('error happened', err);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The special handling of the `'error'` event is only used when `events.once()` is used to wait for another event. If `events.once()` is used to wait for the
|
||||||
|
* '`error'` event itself, then it is treated as any other kind of event without
|
||||||
|
* special handling:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter, once } from 'node:events';
|
||||||
|
*
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
*
|
||||||
|
* once(ee, 'error')
|
||||||
|
* .then(([err]) => console.log('ok', err.message))
|
||||||
|
* .catch((err) => console.error('error', err.message));
|
||||||
|
*
|
||||||
|
* ee.emit('error', new Error('boom'));
|
||||||
|
*
|
||||||
|
* // Prints: ok boom
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* An `AbortSignal` can be used to cancel waiting for the event:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter, once } from 'node:events';
|
||||||
|
*
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
* const ac = new AbortController();
|
||||||
|
*
|
||||||
|
* async function foo(emitter, event, signal) {
|
||||||
|
* try {
|
||||||
|
* await once(emitter, event, { signal });
|
||||||
|
* console.log('event emitted!');
|
||||||
|
* } catch (error) {
|
||||||
|
* if (error.name === 'AbortError') {
|
||||||
|
* console.error('Waiting for the event was canceled!');
|
||||||
|
* } else {
|
||||||
|
* console.error('There was an error', error.message);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* foo(ee, 'foo', ac.signal);
|
||||||
|
* ac.abort(); // Abort waiting for the event
|
||||||
|
* ee.emit('foo'); // Prints: Waiting for the event was canceled!
|
||||||
|
* ```
|
||||||
|
* @since v11.13.0, v10.16.0
|
||||||
|
*/
|
||||||
|
static once(
|
||||||
|
emitter: NodeJS.EventEmitter,
|
||||||
|
eventName: string | symbol,
|
||||||
|
options?: StaticEventEmitterOptions,
|
||||||
|
): Promise<any[]>;
|
||||||
|
static once(emitter: EventTarget, eventName: string, options?: StaticEventEmitterOptions): Promise<any[]>;
|
||||||
|
/**
|
||||||
|
* ```js
|
||||||
|
* import { on, EventEmitter } from 'node:events';
|
||||||
|
* import process from 'node:process';
|
||||||
|
*
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
*
|
||||||
|
* // Emit later on
|
||||||
|
* process.nextTick(() => {
|
||||||
|
* ee.emit('foo', 'bar');
|
||||||
|
* ee.emit('foo', 42);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* for await (const event of on(ee, 'foo')) {
|
||||||
|
* // The execution of this inner block is synchronous and it
|
||||||
|
* // processes one event at a time (even with await). Do not use
|
||||||
|
* // if concurrent execution is required.
|
||||||
|
* console.log(event); // prints ['bar'] [42]
|
||||||
|
* }
|
||||||
|
* // Unreachable here
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Returns an `AsyncIterator` that iterates `eventName` events. It will throw
|
||||||
|
* if the `EventEmitter` emits `'error'`. It removes all listeners when
|
||||||
|
* exiting the loop. The `value` returned by each iteration is an array
|
||||||
|
* composed of the emitted event arguments.
|
||||||
|
*
|
||||||
|
* An `AbortSignal` can be used to cancel waiting on events:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { on, EventEmitter } from 'node:events';
|
||||||
|
* import process from 'node:process';
|
||||||
|
*
|
||||||
|
* const ac = new AbortController();
|
||||||
|
*
|
||||||
|
* (async () => {
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
*
|
||||||
|
* // Emit later on
|
||||||
|
* process.nextTick(() => {
|
||||||
|
* ee.emit('foo', 'bar');
|
||||||
|
* ee.emit('foo', 42);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* for await (const event of on(ee, 'foo', { signal: ac.signal })) {
|
||||||
|
* // The execution of this inner block is synchronous and it
|
||||||
|
* // processes one event at a time (even with await). Do not use
|
||||||
|
* // if concurrent execution is required.
|
||||||
|
* console.log(event); // prints ['bar'] [42]
|
||||||
|
* }
|
||||||
|
* // Unreachable here
|
||||||
|
* })();
|
||||||
|
*
|
||||||
|
* process.nextTick(() => ac.abort());
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Use the `close` option to specify an array of event names that will end the iteration:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { on, EventEmitter } from 'node:events';
|
||||||
|
* import process from 'node:process';
|
||||||
|
*
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
*
|
||||||
|
* // Emit later on
|
||||||
|
* process.nextTick(() => {
|
||||||
|
* ee.emit('foo', 'bar');
|
||||||
|
* ee.emit('foo', 42);
|
||||||
|
* ee.emit('close');
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* for await (const event of on(ee, 'foo', { close: ['close'] })) {
|
||||||
|
* console.log(event); // prints ['bar'] [42]
|
||||||
|
* }
|
||||||
|
* // the loop will exit after 'close' is emitted
|
||||||
|
* console.log('done'); // prints 'done'
|
||||||
|
* ```
|
||||||
|
* @since v13.6.0, v12.16.0
|
||||||
|
* @return An `AsyncIterator` that iterates `eventName` events emitted by the `emitter`
|
||||||
|
*/
|
||||||
|
static on(
|
||||||
|
emitter: NodeJS.EventEmitter,
|
||||||
|
eventName: string | symbol,
|
||||||
|
options?: StaticEventEmitterIteratorOptions,
|
||||||
|
): NodeJS.AsyncIterator<any[]>;
|
||||||
|
static on(
|
||||||
|
emitter: EventTarget,
|
||||||
|
eventName: string,
|
||||||
|
options?: StaticEventEmitterIteratorOptions,
|
||||||
|
): NodeJS.AsyncIterator<any[]>;
|
||||||
|
/**
|
||||||
|
* A class method that returns the number of listeners for the given `eventName` registered on the given `emitter`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter, listenerCount } from 'node:events';
|
||||||
|
*
|
||||||
|
* const myEmitter = new EventEmitter();
|
||||||
|
* myEmitter.on('event', () => {});
|
||||||
|
* myEmitter.on('event', () => {});
|
||||||
|
* console.log(listenerCount(myEmitter, 'event'));
|
||||||
|
* // Prints: 2
|
||||||
|
* ```
|
||||||
|
* @since v0.9.12
|
||||||
|
* @deprecated Since v3.2.0 - Use `listenerCount` instead.
|
||||||
|
* @param emitter The emitter to query
|
||||||
|
* @param eventName The event name
|
||||||
|
*/
|
||||||
|
static listenerCount(emitter: NodeJS.EventEmitter, eventName: string | symbol): number;
|
||||||
|
/**
|
||||||
|
* Returns a copy of the array of listeners for the event named `eventName`.
|
||||||
|
*
|
||||||
|
* For `EventEmitter`s this behaves exactly the same as calling `.listeners` on
|
||||||
|
* the emitter.
|
||||||
|
*
|
||||||
|
* For `EventTarget`s this is the only way to get the event listeners for the
|
||||||
|
* event target. This is useful for debugging and diagnostic purposes.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { getEventListeners, EventEmitter } from 'node:events';
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
* const listener = () => console.log('Events are fun');
|
||||||
|
* ee.on('foo', listener);
|
||||||
|
* console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
|
||||||
|
* }
|
||||||
|
* {
|
||||||
|
* const et = new EventTarget();
|
||||||
|
* const listener = () => console.log('Events are fun');
|
||||||
|
* et.addEventListener('foo', listener);
|
||||||
|
* console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v15.2.0, v14.17.0
|
||||||
|
*/
|
||||||
|
static getEventListeners(emitter: EventTarget | NodeJS.EventEmitter, name: string | symbol): Function[];
|
||||||
|
/**
|
||||||
|
* Returns the currently set max amount of listeners.
|
||||||
|
*
|
||||||
|
* For `EventEmitter`s this behaves exactly the same as calling `.getMaxListeners` on
|
||||||
|
* the emitter.
|
||||||
|
*
|
||||||
|
* For `EventTarget`s this is the only way to get the max event listeners for the
|
||||||
|
* event target. If the number of event handlers on a single EventTarget exceeds
|
||||||
|
* the max set, the EventTarget will print a warning.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
* console.log(getMaxListeners(ee)); // 10
|
||||||
|
* setMaxListeners(11, ee);
|
||||||
|
* console.log(getMaxListeners(ee)); // 11
|
||||||
|
* }
|
||||||
|
* {
|
||||||
|
* const et = new EventTarget();
|
||||||
|
* console.log(getMaxListeners(et)); // 10
|
||||||
|
* setMaxListeners(11, et);
|
||||||
|
* console.log(getMaxListeners(et)); // 11
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v19.9.0
|
||||||
|
*/
|
||||||
|
static getMaxListeners(emitter: EventTarget | NodeJS.EventEmitter): number;
|
||||||
|
/**
|
||||||
|
* ```js
|
||||||
|
* import { setMaxListeners, EventEmitter } from 'node:events';
|
||||||
|
*
|
||||||
|
* const target = new EventTarget();
|
||||||
|
* const emitter = new EventEmitter();
|
||||||
|
*
|
||||||
|
* setMaxListeners(5, target, emitter);
|
||||||
|
* ```
|
||||||
|
* @since v15.4.0
|
||||||
|
* @param n A non-negative number. The maximum number of listeners per `EventTarget` event.
|
||||||
|
* @param eventTargets Zero or more {EventTarget} or {EventEmitter} instances. If none are specified, `n` is set as the default max for all newly created {EventTarget} and {EventEmitter}
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
static setMaxListeners(n?: number, ...eventTargets: Array<EventTarget | NodeJS.EventEmitter>): void;
|
||||||
|
/**
|
||||||
|
* Listens once to the `abort` event on the provided `signal`.
|
||||||
|
*
|
||||||
|
* Listening to the `abort` event on abort signals is unsafe and may
|
||||||
|
* lead to resource leaks since another third party with the signal can
|
||||||
|
* call `e.stopImmediatePropagation()`. Unfortunately Node.js cannot change
|
||||||
|
* this since it would violate the web standard. Additionally, the original
|
||||||
|
* API makes it easy to forget to remove listeners.
|
||||||
|
*
|
||||||
|
* This API allows safely using `AbortSignal`s in Node.js APIs by solving these
|
||||||
|
* two issues by listening to the event such that `stopImmediatePropagation` does
|
||||||
|
* not prevent the listener from running.
|
||||||
|
*
|
||||||
|
* Returns a disposable so that it may be unsubscribed from more easily.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { addAbortListener } from 'node:events';
|
||||||
|
*
|
||||||
|
* function example(signal) {
|
||||||
|
* let disposable;
|
||||||
|
* try {
|
||||||
|
* signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
|
||||||
|
* disposable = addAbortListener(signal, (e) => {
|
||||||
|
* // Do something when signal is aborted.
|
||||||
|
* });
|
||||||
|
* } finally {
|
||||||
|
* disposable?.[Symbol.dispose]();
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v20.5.0
|
||||||
|
* @experimental
|
||||||
|
* @return Disposable that removes the `abort` listener.
|
||||||
|
*/
|
||||||
|
static addAbortListener(signal: AbortSignal, resource: (event: Event) => void): Disposable;
|
||||||
|
/**
|
||||||
|
* This symbol shall be used to install a listener for only monitoring `'error'` events. Listeners installed using this symbol are called before the regular `'error'` listeners are called.
|
||||||
|
*
|
||||||
|
* Installing a listener using this symbol does not change the behavior once an `'error'` event is emitted. Therefore, the process will still crash if no
|
||||||
|
* regular `'error'` listener is installed.
|
||||||
|
* @since v13.6.0, v12.17.0
|
||||||
|
*/
|
||||||
|
static readonly errorMonitor: unique symbol;
|
||||||
|
/**
|
||||||
|
* Value: `Symbol.for('nodejs.rejection')`
|
||||||
|
*
|
||||||
|
* See how to write a custom `rejection handler`.
|
||||||
|
* @since v13.4.0, v12.16.0
|
||||||
|
*/
|
||||||
|
static readonly captureRejectionSymbol: unique symbol;
|
||||||
|
/**
|
||||||
|
* Value: [boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type)
|
||||||
|
*
|
||||||
|
* Change the default `captureRejections` option on all new `EventEmitter` objects.
|
||||||
|
* @since v13.4.0, v12.16.0
|
||||||
|
*/
|
||||||
|
static captureRejections: boolean;
|
||||||
|
/**
|
||||||
|
* By default, a maximum of `10` listeners can be registered for any single
|
||||||
|
* event. This limit can be changed for individual `EventEmitter` instances
|
||||||
|
* using the `emitter.setMaxListeners(n)` method. To change the default
|
||||||
|
* for _all_`EventEmitter` instances, the `events.defaultMaxListeners` property
|
||||||
|
* can be used. If this value is not a positive number, a `RangeError` is thrown.
|
||||||
|
*
|
||||||
|
* Take caution when setting the `events.defaultMaxListeners` because the
|
||||||
|
* change affects _all_ `EventEmitter` instances, including those created before
|
||||||
|
* the change is made. However, calling `emitter.setMaxListeners(n)` still has
|
||||||
|
* precedence over `events.defaultMaxListeners`.
|
||||||
|
*
|
||||||
|
* This is not a hard limit. The `EventEmitter` instance will allow
|
||||||
|
* more listeners to be added but will output a trace warning to stderr indicating
|
||||||
|
* that a "possible EventEmitter memory leak" has been detected. For any single
|
||||||
|
* `EventEmitter`, the `emitter.getMaxListeners()` and `emitter.setMaxListeners()` methods can be used to
|
||||||
|
* temporarily avoid this warning:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
* const emitter = new EventEmitter();
|
||||||
|
* emitter.setMaxListeners(emitter.getMaxListeners() + 1);
|
||||||
|
* emitter.once('event', () => {
|
||||||
|
* // do stuff
|
||||||
|
* emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The `--trace-warnings` command-line flag can be used to display the
|
||||||
|
* stack trace for such warnings.
|
||||||
|
*
|
||||||
|
* The emitted warning can be inspected with `process.on('warning')` and will
|
||||||
|
* have the additional `emitter`, `type`, and `count` properties, referring to
|
||||||
|
* the event emitter instance, the event's name and the number of attached
|
||||||
|
* listeners, respectively.
|
||||||
|
* Its `name` property is set to `'MaxListenersExceededWarning'`.
|
||||||
|
* @since v0.11.2
|
||||||
|
*/
|
||||||
|
static defaultMaxListeners: number;
|
||||||
|
}
|
||||||
|
import internal = require("node:events");
|
||||||
|
namespace EventEmitter {
|
||||||
|
// Should just be `export { EventEmitter }`, but that doesn't work in TypeScript 3.4
|
||||||
|
export { internal as EventEmitter };
|
||||||
|
export interface Abortable {
|
||||||
|
/**
|
||||||
|
* When provided the corresponding `AbortController` can be used to cancel an asynchronous action.
|
||||||
|
*/
|
||||||
|
signal?: AbortSignal | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EventEmitterReferencingAsyncResource extends AsyncResource {
|
||||||
|
readonly eventEmitter: EventEmitterAsyncResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EventEmitterAsyncResourceOptions extends AsyncResourceOptions, EventEmitterOptions {
|
||||||
|
/**
|
||||||
|
* The type of async event, this is required when instantiating `EventEmitterAsyncResource`
|
||||||
|
* directly rather than as a child class.
|
||||||
|
* @default new.target.name if instantiated as a child class.
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integrates `EventEmitter` with `AsyncResource` for `EventEmitter`s that
|
||||||
|
* require manual async tracking. Specifically, all events emitted by instances
|
||||||
|
* of `events.EventEmitterAsyncResource` will run within its `async context`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitterAsyncResource, EventEmitter } from 'node:events';
|
||||||
|
* import { notStrictEqual, strictEqual } from 'node:assert';
|
||||||
|
* import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* // Async tracking tooling will identify this as 'Q'.
|
||||||
|
* const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
|
||||||
|
*
|
||||||
|
* // 'foo' listeners will run in the EventEmitters async context.
|
||||||
|
* ee1.on('foo', () => {
|
||||||
|
* strictEqual(executionAsyncId(), ee1.asyncId);
|
||||||
|
* strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* const ee2 = new EventEmitter();
|
||||||
|
*
|
||||||
|
* // 'foo' listeners on ordinary EventEmitters that do not track async
|
||||||
|
* // context, however, run in the same async context as the emit().
|
||||||
|
* ee2.on('foo', () => {
|
||||||
|
* notStrictEqual(executionAsyncId(), ee2.asyncId);
|
||||||
|
* notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* Promise.resolve().then(() => {
|
||||||
|
* ee1.emit('foo');
|
||||||
|
* ee2.emit('foo');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The `EventEmitterAsyncResource` class has the same methods and takes the
|
||||||
|
* same options as `EventEmitter` and `AsyncResource` themselves.
|
||||||
|
* @since v17.4.0, v16.14.0
|
||||||
|
*/
|
||||||
|
export class EventEmitterAsyncResource extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* @param options Only optional in child class.
|
||||||
|
*/
|
||||||
|
constructor(options?: EventEmitterAsyncResourceOptions);
|
||||||
|
/**
|
||||||
|
* Call all `destroy` hooks. This should only ever be called once. An error will
|
||||||
|
* be thrown if it is called more than once. This **must** be manually called. If
|
||||||
|
* the resource is left to be collected by the GC then the `destroy` hooks will
|
||||||
|
* never be called.
|
||||||
|
*/
|
||||||
|
emitDestroy(): void;
|
||||||
|
/**
|
||||||
|
* The unique `asyncId` assigned to the resource.
|
||||||
|
*/
|
||||||
|
readonly asyncId: number;
|
||||||
|
/**
|
||||||
|
* The same triggerAsyncId that is passed to the AsyncResource constructor.
|
||||||
|
*/
|
||||||
|
readonly triggerAsyncId: number;
|
||||||
|
/**
|
||||||
|
* The returned `AsyncResource` object has an additional `eventEmitter` property
|
||||||
|
* that provides a reference to this `EventEmitterAsyncResource`.
|
||||||
|
*/
|
||||||
|
readonly asyncResource: EventEmitterReferencingAsyncResource;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `NodeEventTarget` is a Node.js-specific extension to `EventTarget`
|
||||||
|
* that emulates a subset of the `EventEmitter` API.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
export interface NodeEventTarget extends EventTarget {
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class that emulates the
|
||||||
|
* equivalent `EventEmitter` API. The only difference between `addListener()` and
|
||||||
|
* `addEventListener()` is that `addListener()` will return a reference to the
|
||||||
|
* `EventTarget`.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
addListener(type: string, listener: (arg: any) => void): this;
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class that dispatches the
|
||||||
|
* `arg` to the list of handlers for `type`.
|
||||||
|
* @since v15.2.0
|
||||||
|
* @returns `true` if event listeners registered for the `type` exist,
|
||||||
|
* otherwise `false`.
|
||||||
|
*/
|
||||||
|
emit(type: string, arg: any): boolean;
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class that returns an array
|
||||||
|
* of event `type` names for which event listeners are registered.
|
||||||
|
* @since 14.5.0
|
||||||
|
*/
|
||||||
|
eventNames(): string[];
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class that returns the number
|
||||||
|
* of event listeners registered for the `type`.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
listenerCount(type: string): number;
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class that sets the number
|
||||||
|
* of max event listeners as `n`.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
setMaxListeners(n: number): void;
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class that returns the number
|
||||||
|
* of max event listeners.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
getMaxListeners(): number;
|
||||||
|
/**
|
||||||
|
* Node.js-specific alias for `eventTarget.removeEventListener()`.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
off(type: string, listener: (arg: any) => void, options?: EventListenerOptions): this;
|
||||||
|
/**
|
||||||
|
* Node.js-specific alias for `eventTarget.addEventListener()`.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
on(type: string, listener: (arg: any) => void): this;
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class that adds a `once`
|
||||||
|
* listener for the given event `type`. This is equivalent to calling `on`
|
||||||
|
* with the `once` option set to `true`.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
once(type: string, listener: (arg: any) => void): this;
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class. If `type` is specified,
|
||||||
|
* removes all registered listeners for `type`, otherwise removes all registered
|
||||||
|
* listeners.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
removeAllListeners(type?: string): this;
|
||||||
|
/**
|
||||||
|
* Node.js-specific extension to the `EventTarget` class that removes the
|
||||||
|
* `listener` for the given `type`. The only difference between `removeListener()`
|
||||||
|
* and `removeEventListener()` is that `removeListener()` will return a reference
|
||||||
|
* to the `EventTarget`.
|
||||||
|
* @since v14.5.0
|
||||||
|
*/
|
||||||
|
removeListener(type: string, listener: (arg: any) => void, options?: EventListenerOptions): this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
global {
|
||||||
|
namespace NodeJS {
|
||||||
|
interface EventEmitter<T extends EventMap<T> = DefaultEventMap> {
|
||||||
|
[EventEmitter.captureRejectionSymbol]?<K>(error: Error, event: Key<K, T>, ...args: Args<K, T>): void;
|
||||||
|
/**
|
||||||
|
* Alias for `emitter.on(eventName, listener)`.
|
||||||
|
* @since v0.1.26
|
||||||
|
*/
|
||||||
|
addListener<K>(eventName: Key<K, T>, listener: Listener1<K, T>): this;
|
||||||
|
/**
|
||||||
|
* Adds the `listener` function to the end of the listeners array for the event
|
||||||
|
* named `eventName`. No checks are made to see if the `listener` has already
|
||||||
|
* been added. Multiple calls passing the same combination of `eventName` and
|
||||||
|
* `listener` will result in the `listener` being added, and called, multiple times.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* server.on('connection', (stream) => {
|
||||||
|
* console.log('someone connected!');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||||
|
*
|
||||||
|
* By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
|
||||||
|
* event listener to the beginning of the listeners array.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
* const myEE = new EventEmitter();
|
||||||
|
* myEE.on('foo', () => console.log('a'));
|
||||||
|
* myEE.prependListener('foo', () => console.log('b'));
|
||||||
|
* myEE.emit('foo');
|
||||||
|
* // Prints:
|
||||||
|
* // b
|
||||||
|
* // a
|
||||||
|
* ```
|
||||||
|
* @since v0.1.101
|
||||||
|
* @param eventName The name of the event.
|
||||||
|
* @param listener The callback function
|
||||||
|
*/
|
||||||
|
on<K>(eventName: Key<K, T>, listener: Listener1<K, T>): this;
|
||||||
|
/**
|
||||||
|
* Adds a **one-time** `listener` function for the event named `eventName`. The
|
||||||
|
* next time `eventName` is triggered, this listener is removed and then invoked.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* server.once('connection', (stream) => {
|
||||||
|
* console.log('Ah, we have our first user!');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||||
|
*
|
||||||
|
* By default, event listeners are invoked in the order they are added. The `emitter.prependOnceListener()` method can be used as an alternative to add the
|
||||||
|
* event listener to the beginning of the listeners array.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
* const myEE = new EventEmitter();
|
||||||
|
* myEE.once('foo', () => console.log('a'));
|
||||||
|
* myEE.prependOnceListener('foo', () => console.log('b'));
|
||||||
|
* myEE.emit('foo');
|
||||||
|
* // Prints:
|
||||||
|
* // b
|
||||||
|
* // a
|
||||||
|
* ```
|
||||||
|
* @since v0.3.0
|
||||||
|
* @param eventName The name of the event.
|
||||||
|
* @param listener The callback function
|
||||||
|
*/
|
||||||
|
once<K>(eventName: Key<K, T>, listener: Listener1<K, T>): this;
|
||||||
|
/**
|
||||||
|
* Removes the specified `listener` from the listener array for the event named `eventName`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const callback = (stream) => {
|
||||||
|
* console.log('someone connected!');
|
||||||
|
* };
|
||||||
|
* server.on('connection', callback);
|
||||||
|
* // ...
|
||||||
|
* server.removeListener('connection', callback);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* `removeListener()` will remove, at most, one instance of a listener from the
|
||||||
|
* listener array. If any single listener has been added multiple times to the
|
||||||
|
* listener array for the specified `eventName`, then `removeListener()` must be
|
||||||
|
* called multiple times to remove each instance.
|
||||||
|
*
|
||||||
|
* Once an event is emitted, all listeners attached to it at the
|
||||||
|
* time of emitting are called in order. This implies that any `removeListener()` or `removeAllListeners()` calls _after_ emitting and _before_ the last listener finishes execution
|
||||||
|
* will not remove them from`emit()` in progress. Subsequent events behave as expected.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
* class MyEmitter extends EventEmitter {}
|
||||||
|
* const myEmitter = new MyEmitter();
|
||||||
|
*
|
||||||
|
* const callbackA = () => {
|
||||||
|
* console.log('A');
|
||||||
|
* myEmitter.removeListener('event', callbackB);
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* const callbackB = () => {
|
||||||
|
* console.log('B');
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* myEmitter.on('event', callbackA);
|
||||||
|
*
|
||||||
|
* myEmitter.on('event', callbackB);
|
||||||
|
*
|
||||||
|
* // callbackA removes listener callbackB but it will still be called.
|
||||||
|
* // Internal listener array at time of emit [callbackA, callbackB]
|
||||||
|
* myEmitter.emit('event');
|
||||||
|
* // Prints:
|
||||||
|
* // A
|
||||||
|
* // B
|
||||||
|
*
|
||||||
|
* // callbackB is now removed.
|
||||||
|
* // Internal listener array [callbackA]
|
||||||
|
* myEmitter.emit('event');
|
||||||
|
* // Prints:
|
||||||
|
* // A
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Because listeners are managed using an internal array, calling this will
|
||||||
|
* change the position indices of any listener registered _after_ the listener
|
||||||
|
* being removed. This will not impact the order in which listeners are called,
|
||||||
|
* but it means that any copies of the listener array as returned by
|
||||||
|
* the `emitter.listeners()` method will need to be recreated.
|
||||||
|
*
|
||||||
|
* When a single function has been added as a handler multiple times for a single
|
||||||
|
* event (as in the example below), `removeListener()` will remove the most
|
||||||
|
* recently added instance. In the example the `once('ping')` listener is removed:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
* const ee = new EventEmitter();
|
||||||
|
*
|
||||||
|
* function pong() {
|
||||||
|
* console.log('pong');
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ee.on('ping', pong);
|
||||||
|
* ee.once('ping', pong);
|
||||||
|
* ee.removeListener('ping', pong);
|
||||||
|
*
|
||||||
|
* ee.emit('ping');
|
||||||
|
* ee.emit('ping');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||||
|
* @since v0.1.26
|
||||||
|
*/
|
||||||
|
removeListener<K>(eventName: Key<K, T>, listener: Listener1<K, T>): this;
|
||||||
|
/**
|
||||||
|
* Alias for `emitter.removeListener()`.
|
||||||
|
* @since v10.0.0
|
||||||
|
*/
|
||||||
|
off<K>(eventName: Key<K, T>, listener: Listener1<K, T>): this;
|
||||||
|
/**
|
||||||
|
* Removes all listeners, or those of the specified `eventName`.
|
||||||
|
*
|
||||||
|
* It is bad practice to remove listeners added elsewhere in the code,
|
||||||
|
* particularly when the `EventEmitter` instance was created by some other
|
||||||
|
* component or module (e.g. sockets or file streams).
|
||||||
|
*
|
||||||
|
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||||
|
* @since v0.1.26
|
||||||
|
*/
|
||||||
|
removeAllListeners(eventName?: Key<unknown, T>): this;
|
||||||
|
/**
|
||||||
|
* By default `EventEmitter`s will print a warning if more than `10` listeners are
|
||||||
|
* added for a particular event. This is a useful default that helps finding
|
||||||
|
* memory leaks. The `emitter.setMaxListeners()` method allows the limit to be
|
||||||
|
* modified for this specific `EventEmitter` instance. The value can be set to `Infinity` (or `0`) to indicate an unlimited number of listeners.
|
||||||
|
*
|
||||||
|
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||||
|
* @since v0.3.5
|
||||||
|
*/
|
||||||
|
setMaxListeners(n: number): this;
|
||||||
|
/**
|
||||||
|
* Returns the current max listener value for the `EventEmitter` which is either
|
||||||
|
* set by `emitter.setMaxListeners(n)` or defaults to {@link EventEmitter.defaultMaxListeners}.
|
||||||
|
* @since v1.0.0
|
||||||
|
*/
|
||||||
|
getMaxListeners(): number;
|
||||||
|
/**
|
||||||
|
* Returns a copy of the array of listeners for the event named `eventName`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* server.on('connection', (stream) => {
|
||||||
|
* console.log('someone connected!');
|
||||||
|
* });
|
||||||
|
* console.log(util.inspect(server.listeners('connection')));
|
||||||
|
* // Prints: [ [Function] ]
|
||||||
|
* ```
|
||||||
|
* @since v0.1.26
|
||||||
|
*/
|
||||||
|
listeners<K>(eventName: Key<K, T>): Array<Listener2<K, T>>;
|
||||||
|
/**
|
||||||
|
* Returns a copy of the array of listeners for the event named `eventName`,
|
||||||
|
* including any wrappers (such as those created by `.once()`).
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
* const emitter = new EventEmitter();
|
||||||
|
* emitter.once('log', () => console.log('log once'));
|
||||||
|
*
|
||||||
|
* // Returns a new Array with a function `onceWrapper` which has a property
|
||||||
|
* // `listener` which contains the original listener bound above
|
||||||
|
* const listeners = emitter.rawListeners('log');
|
||||||
|
* const logFnWrapper = listeners[0];
|
||||||
|
*
|
||||||
|
* // Logs "log once" to the console and does not unbind the `once` event
|
||||||
|
* logFnWrapper.listener();
|
||||||
|
*
|
||||||
|
* // Logs "log once" to the console and removes the listener
|
||||||
|
* logFnWrapper();
|
||||||
|
*
|
||||||
|
* emitter.on('log', () => console.log('log persistently'));
|
||||||
|
* // Will return a new Array with a single function bound by `.on()` above
|
||||||
|
* const newListeners = emitter.rawListeners('log');
|
||||||
|
*
|
||||||
|
* // Logs "log persistently" twice
|
||||||
|
* newListeners[0]();
|
||||||
|
* emitter.emit('log');
|
||||||
|
* ```
|
||||||
|
* @since v9.4.0
|
||||||
|
*/
|
||||||
|
rawListeners<K>(eventName: Key<K, T>): Array<Listener2<K, T>>;
|
||||||
|
/**
|
||||||
|
* Synchronously calls each of the listeners registered for the event named `eventName`, in the order they were registered, passing the supplied arguments
|
||||||
|
* to each.
|
||||||
|
*
|
||||||
|
* Returns `true` if the event had listeners, `false` otherwise.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
* const myEmitter = new EventEmitter();
|
||||||
|
*
|
||||||
|
* // First listener
|
||||||
|
* myEmitter.on('event', function firstListener() {
|
||||||
|
* console.log('Helloooo! first listener');
|
||||||
|
* });
|
||||||
|
* // Second listener
|
||||||
|
* myEmitter.on('event', function secondListener(arg1, arg2) {
|
||||||
|
* console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
|
||||||
|
* });
|
||||||
|
* // Third listener
|
||||||
|
* myEmitter.on('event', function thirdListener(...args) {
|
||||||
|
* const parameters = args.join(', ');
|
||||||
|
* console.log(`event with parameters ${parameters} in third listener`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* console.log(myEmitter.listeners('event'));
|
||||||
|
*
|
||||||
|
* myEmitter.emit('event', 1, 2, 3, 4, 5);
|
||||||
|
*
|
||||||
|
* // Prints:
|
||||||
|
* // [
|
||||||
|
* // [Function: firstListener],
|
||||||
|
* // [Function: secondListener],
|
||||||
|
* // [Function: thirdListener]
|
||||||
|
* // ]
|
||||||
|
* // Helloooo! first listener
|
||||||
|
* // event with parameters 1, 2 in second listener
|
||||||
|
* // event with parameters 1, 2, 3, 4, 5 in third listener
|
||||||
|
* ```
|
||||||
|
* @since v0.1.26
|
||||||
|
*/
|
||||||
|
emit<K>(eventName: Key<K, T>, ...args: Args<K, T>): boolean;
|
||||||
|
/**
|
||||||
|
* Returns the number of listeners listening for the event named `eventName`.
|
||||||
|
* If `listener` is provided, it will return how many times the listener is found
|
||||||
|
* in the list of the listeners of the event.
|
||||||
|
* @since v3.2.0
|
||||||
|
* @param eventName The name of the event being listened for
|
||||||
|
* @param listener The event handler function
|
||||||
|
*/
|
||||||
|
listenerCount<K>(eventName: Key<K, T>, listener?: Listener2<K, T>): number;
|
||||||
|
/**
|
||||||
|
* Adds the `listener` function to the _beginning_ of the listeners array for the
|
||||||
|
* event named `eventName`. No checks are made to see if the `listener` has
|
||||||
|
* already been added. Multiple calls passing the same combination of `eventName`
|
||||||
|
* and `listener` will result in the `listener` being added, and called, multiple times.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* server.prependListener('connection', (stream) => {
|
||||||
|
* console.log('someone connected!');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||||
|
* @since v6.0.0
|
||||||
|
* @param eventName The name of the event.
|
||||||
|
* @param listener The callback function
|
||||||
|
*/
|
||||||
|
prependListener<K>(eventName: Key<K, T>, listener: Listener1<K, T>): this;
|
||||||
|
/**
|
||||||
|
* Adds a **one-time**`listener` function for the event named `eventName` to the _beginning_ of the listeners array. The next time `eventName` is triggered, this
|
||||||
|
* listener is removed, and then invoked.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* server.prependOnceListener('connection', (stream) => {
|
||||||
|
* console.log('Ah, we have our first user!');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||||
|
* @since v6.0.0
|
||||||
|
* @param eventName The name of the event.
|
||||||
|
* @param listener The callback function
|
||||||
|
*/
|
||||||
|
prependOnceListener<K>(eventName: Key<K, T>, listener: Listener1<K, T>): this;
|
||||||
|
/**
|
||||||
|
* Returns an array listing the events for which the emitter has registered
|
||||||
|
* listeners. The values in the array are strings or `Symbol`s.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { EventEmitter } from 'node:events';
|
||||||
|
*
|
||||||
|
* const myEE = new EventEmitter();
|
||||||
|
* myEE.on('foo', () => {});
|
||||||
|
* myEE.on('bar', () => {});
|
||||||
|
*
|
||||||
|
* const sym = Symbol('symbol');
|
||||||
|
* myEE.on(sym, () => {});
|
||||||
|
*
|
||||||
|
* console.log(myEE.eventNames());
|
||||||
|
* // Prints: [ 'foo', 'bar', Symbol(symbol) ]
|
||||||
|
* ```
|
||||||
|
* @since v6.0.0
|
||||||
|
*/
|
||||||
|
eventNames(): Array<(string | symbol) & Key2<unknown, T>>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export = EventEmitter;
|
||||||
|
}
|
||||||
|
declare module "node:events" {
|
||||||
|
import events = require("events");
|
||||||
|
export = events;
|
||||||
|
}
|
||||||
4362
node_modules/@types/node/fs.d.ts
generated
vendored
Normal file
4362
node_modules/@types/node/fs.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
172
node_modules/@types/node/globals.d.ts
generated
vendored
Normal file
172
node_modules/@types/node/globals.d.ts
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
declare var global: typeof globalThis;
|
||||||
|
|
||||||
|
declare var process: NodeJS.Process;
|
||||||
|
declare var console: Console;
|
||||||
|
|
||||||
|
interface ErrorConstructor {
|
||||||
|
/**
|
||||||
|
* Creates a `.stack` property on `targetObject`, which when accessed returns
|
||||||
|
* a string representing the location in the code at which
|
||||||
|
* `Error.captureStackTrace()` was called.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const myObject = {};
|
||||||
|
* Error.captureStackTrace(myObject);
|
||||||
|
* myObject.stack; // Similar to `new Error().stack`
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The first line of the trace will be prefixed with
|
||||||
|
* `${myObject.name}: ${myObject.message}`.
|
||||||
|
*
|
||||||
|
* The optional `constructorOpt` argument accepts a function. If given, all frames
|
||||||
|
* above `constructorOpt`, including `constructorOpt`, will be omitted from the
|
||||||
|
* generated stack trace.
|
||||||
|
*
|
||||||
|
* The `constructorOpt` argument is useful for hiding implementation
|
||||||
|
* details of error generation from the user. For instance:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* function a() {
|
||||||
|
* b();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* function b() {
|
||||||
|
* c();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* function c() {
|
||||||
|
* // Create an error without stack trace to avoid calculating the stack trace twice.
|
||||||
|
* const { stackTraceLimit } = Error;
|
||||||
|
* Error.stackTraceLimit = 0;
|
||||||
|
* const error = new Error();
|
||||||
|
* Error.stackTraceLimit = stackTraceLimit;
|
||||||
|
*
|
||||||
|
* // Capture the stack trace above function b
|
||||||
|
* Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
|
||||||
|
* throw error;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* a();
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
||||||
|
/**
|
||||||
|
* @see https://v8.dev/docs/stack-trace-api#customizing-stack-traces
|
||||||
|
*/
|
||||||
|
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
||||||
|
/**
|
||||||
|
* The `Error.stackTraceLimit` property specifies the number of stack frames
|
||||||
|
* collected by a stack trace (whether generated by `new Error().stack` or
|
||||||
|
* `Error.captureStackTrace(obj)`).
|
||||||
|
*
|
||||||
|
* The default value is `10` but may be set to any valid JavaScript number. Changes
|
||||||
|
* will affect any stack trace captured _after_ the value has been changed.
|
||||||
|
*
|
||||||
|
* If set to a non-number value, or set to a negative number, stack traces will
|
||||||
|
* not capture any frames.
|
||||||
|
*/
|
||||||
|
stackTraceLimit: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable this API with the `--expose-gc` CLI flag.
|
||||||
|
*/
|
||||||
|
declare var gc: NodeJS.GCFunction | undefined;
|
||||||
|
|
||||||
|
declare namespace NodeJS {
|
||||||
|
interface CallSite {
|
||||||
|
getColumnNumber(): number | null;
|
||||||
|
getEnclosingColumnNumber(): number | null;
|
||||||
|
getEnclosingLineNumber(): number | null;
|
||||||
|
getEvalOrigin(): string | undefined;
|
||||||
|
getFileName(): string | null;
|
||||||
|
getFunction(): Function | undefined;
|
||||||
|
getFunctionName(): string | null;
|
||||||
|
getLineNumber(): number | null;
|
||||||
|
getMethodName(): string | null;
|
||||||
|
getPosition(): number;
|
||||||
|
getPromiseIndex(): number | null;
|
||||||
|
getScriptHash(): string;
|
||||||
|
getScriptNameOrSourceURL(): string | null;
|
||||||
|
getThis(): unknown;
|
||||||
|
getTypeName(): string | null;
|
||||||
|
isAsync(): boolean;
|
||||||
|
isConstructor(): boolean;
|
||||||
|
isEval(): boolean;
|
||||||
|
isNative(): boolean;
|
||||||
|
isPromiseAll(): boolean;
|
||||||
|
isToplevel(): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ErrnoException extends Error {
|
||||||
|
errno?: number | undefined;
|
||||||
|
code?: string | undefined;
|
||||||
|
path?: string | undefined;
|
||||||
|
syscall?: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReadableStream extends EventEmitter {
|
||||||
|
readable: boolean;
|
||||||
|
read(size?: number): string | Buffer;
|
||||||
|
setEncoding(encoding: BufferEncoding): this;
|
||||||
|
pause(): this;
|
||||||
|
resume(): this;
|
||||||
|
isPaused(): boolean;
|
||||||
|
pipe<T extends WritableStream>(destination: T, options?: { end?: boolean | undefined }): T;
|
||||||
|
unpipe(destination?: WritableStream): this;
|
||||||
|
unshift(chunk: string | Uint8Array, encoding?: BufferEncoding): void;
|
||||||
|
wrap(oldStream: ReadableStream): this;
|
||||||
|
[Symbol.asyncIterator](): AsyncIterableIterator<string | Buffer>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WritableStream extends EventEmitter {
|
||||||
|
writable: boolean;
|
||||||
|
write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean;
|
||||||
|
write(str: string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean;
|
||||||
|
end(cb?: () => void): this;
|
||||||
|
end(data: string | Uint8Array, cb?: () => void): this;
|
||||||
|
end(str: string, encoding?: BufferEncoding, cb?: () => void): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReadWriteStream extends ReadableStream, WritableStream {}
|
||||||
|
|
||||||
|
interface RefCounted {
|
||||||
|
ref(): this;
|
||||||
|
unref(): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Dict<T> {
|
||||||
|
[key: string]: T | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReadOnlyDict<T> {
|
||||||
|
readonly [key: string]: T | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
type PartialOptions<T> = { [K in keyof T]?: T[K] | undefined };
|
||||||
|
|
||||||
|
interface GCFunction {
|
||||||
|
(minor?: boolean): void;
|
||||||
|
(options: NodeJS.GCOptions & { execution: "async" }): Promise<void>;
|
||||||
|
(options: NodeJS.GCOptions): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GCOptions {
|
||||||
|
execution?: "sync" | "async" | undefined;
|
||||||
|
flavor?: "regular" | "last-resort" | undefined;
|
||||||
|
type?: "major-snapshot" | "major" | "minor" | undefined;
|
||||||
|
filename?: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An iterable iterator returned by the Node.js API. */
|
||||||
|
// Default TReturn/TNext in v20 is `any`, for compatibility with the previously-used IterableIterator.
|
||||||
|
interface Iterator<T, TReturn = any, TNext = any> extends IteratorObject<T, TReturn, TNext> {
|
||||||
|
[Symbol.iterator](): NodeJS.Iterator<T, TReturn, TNext>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An async iterable iterator returned by the Node.js API. */
|
||||||
|
// Default TReturn/TNext in v20 is `any`, for compatibility with the previously-used AsyncIterableIterator.
|
||||||
|
interface AsyncIterator<T, TReturn = any, TNext = any> extends AsyncIteratorObject<T, TReturn, TNext> {
|
||||||
|
[Symbol.asyncIterator](): NodeJS.AsyncIterator<T, TReturn, TNext>;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
node_modules/@types/node/globals.typedarray.d.ts
generated
vendored
Normal file
21
node_modules/@types/node/globals.typedarray.d.ts
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
export {}; // Make this a module
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace NodeJS {
|
||||||
|
type TypedArray<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> =
|
||||||
|
| Uint8Array<TArrayBuffer>
|
||||||
|
| Uint8ClampedArray<TArrayBuffer>
|
||||||
|
| Uint16Array<TArrayBuffer>
|
||||||
|
| Uint32Array<TArrayBuffer>
|
||||||
|
| Int8Array<TArrayBuffer>
|
||||||
|
| Int16Array<TArrayBuffer>
|
||||||
|
| Int32Array<TArrayBuffer>
|
||||||
|
| BigUint64Array<TArrayBuffer>
|
||||||
|
| BigInt64Array<TArrayBuffer>
|
||||||
|
| Float32Array<TArrayBuffer>
|
||||||
|
| Float64Array<TArrayBuffer>;
|
||||||
|
type ArrayBufferView<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> =
|
||||||
|
| TypedArray<TArrayBuffer>
|
||||||
|
| DataView<TArrayBuffer>;
|
||||||
|
}
|
||||||
|
}
|
||||||
2031
node_modules/@types/node/http.d.ts
generated
vendored
Normal file
2031
node_modules/@types/node/http.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2623
node_modules/@types/node/http2.d.ts
generated
vendored
Normal file
2623
node_modules/@types/node/http2.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
549
node_modules/@types/node/https.d.ts
generated
vendored
Normal file
549
node_modules/@types/node/https.d.ts
generated
vendored
Normal file
@@ -0,0 +1,549 @@
|
|||||||
|
/**
|
||||||
|
* HTTPS is the HTTP protocol over TLS/SSL. In Node.js this is implemented as a
|
||||||
|
* separate module.
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/https.js)
|
||||||
|
*/
|
||||||
|
declare module "https" {
|
||||||
|
import { Duplex } from "node:stream";
|
||||||
|
import * as tls from "node:tls";
|
||||||
|
import * as http from "node:http";
|
||||||
|
import { URL } from "node:url";
|
||||||
|
type ServerOptions<
|
||||||
|
Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,
|
||||||
|
Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse,
|
||||||
|
> = tls.SecureContextOptions & tls.TlsOptions & http.ServerOptions<Request, Response>;
|
||||||
|
type RequestOptions =
|
||||||
|
& http.RequestOptions
|
||||||
|
& tls.SecureContextOptions
|
||||||
|
& {
|
||||||
|
checkServerIdentity?: typeof tls.checkServerIdentity | undefined;
|
||||||
|
rejectUnauthorized?: boolean | undefined; // Defaults to true
|
||||||
|
servername?: string | undefined; // SNI TLS Extension
|
||||||
|
};
|
||||||
|
interface AgentOptions extends http.AgentOptions, tls.ConnectionOptions {
|
||||||
|
rejectUnauthorized?: boolean | undefined;
|
||||||
|
maxCachedSessions?: number | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* An `Agent` object for HTTPS similar to `http.Agent`. See {@link request} for more information.
|
||||||
|
* @since v0.4.5
|
||||||
|
*/
|
||||||
|
class Agent extends http.Agent {
|
||||||
|
constructor(options?: AgentOptions);
|
||||||
|
options: AgentOptions;
|
||||||
|
createConnection(
|
||||||
|
options: RequestOptions,
|
||||||
|
callback?: (err: Error | null, stream: Duplex) => void,
|
||||||
|
): Duplex | null | undefined;
|
||||||
|
getName(options?: RequestOptions): string;
|
||||||
|
}
|
||||||
|
interface Server<
|
||||||
|
Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,
|
||||||
|
Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse,
|
||||||
|
> extends http.Server<Request, Response> {}
|
||||||
|
/**
|
||||||
|
* See `http.Server` for more information.
|
||||||
|
* @since v0.3.4
|
||||||
|
*/
|
||||||
|
class Server<
|
||||||
|
Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,
|
||||||
|
Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse,
|
||||||
|
> extends tls.Server {
|
||||||
|
constructor(requestListener?: http.RequestListener<Request, Response>);
|
||||||
|
constructor(
|
||||||
|
options: ServerOptions<Request, Response>,
|
||||||
|
requestListener?: http.RequestListener<Request, Response>,
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* Closes all connections connected to this server.
|
||||||
|
* @since v18.2.0
|
||||||
|
*/
|
||||||
|
closeAllConnections(): void;
|
||||||
|
/**
|
||||||
|
* Closes all connections connected to this server which are not sending a request or waiting for a response.
|
||||||
|
* @since v18.2.0
|
||||||
|
*/
|
||||||
|
closeIdleConnections(): void;
|
||||||
|
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
addListener(event: "keylog", listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
addListener(
|
||||||
|
event: "newSession",
|
||||||
|
listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
addListener(
|
||||||
|
event: "OCSPRequest",
|
||||||
|
listener: (
|
||||||
|
certificate: Buffer,
|
||||||
|
issuer: Buffer,
|
||||||
|
callback: (err: Error | null, resp: Buffer) => void,
|
||||||
|
) => void,
|
||||||
|
): this;
|
||||||
|
addListener(
|
||||||
|
event: "resumeSession",
|
||||||
|
listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
addListener(event: "secureConnection", listener: (tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
addListener(event: "tlsClientError", listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
addListener(event: "close", listener: () => void): this;
|
||||||
|
addListener(event: "connection", listener: (socket: Duplex) => void): this;
|
||||||
|
addListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
addListener(event: "listening", listener: () => void): this;
|
||||||
|
addListener(event: "checkContinue", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
addListener(event: "checkExpectation", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
addListener(event: "clientError", listener: (err: Error, socket: Duplex) => void): this;
|
||||||
|
addListener(
|
||||||
|
event: "connect",
|
||||||
|
listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void,
|
||||||
|
): this;
|
||||||
|
addListener(event: "request", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
addListener(
|
||||||
|
event: "upgrade",
|
||||||
|
listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void,
|
||||||
|
): this;
|
||||||
|
emit(event: string, ...args: any[]): boolean;
|
||||||
|
emit(event: "keylog", line: Buffer, tlsSocket: tls.TLSSocket): boolean;
|
||||||
|
emit(
|
||||||
|
event: "newSession",
|
||||||
|
sessionId: Buffer,
|
||||||
|
sessionData: Buffer,
|
||||||
|
callback: (err: Error, resp: Buffer) => void,
|
||||||
|
): boolean;
|
||||||
|
emit(
|
||||||
|
event: "OCSPRequest",
|
||||||
|
certificate: Buffer,
|
||||||
|
issuer: Buffer,
|
||||||
|
callback: (err: Error | null, resp: Buffer) => void,
|
||||||
|
): boolean;
|
||||||
|
emit(event: "resumeSession", sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void): boolean;
|
||||||
|
emit(event: "secureConnection", tlsSocket: tls.TLSSocket): boolean;
|
||||||
|
emit(event: "tlsClientError", err: Error, tlsSocket: tls.TLSSocket): boolean;
|
||||||
|
emit(event: "close"): boolean;
|
||||||
|
emit(event: "connection", socket: Duplex): boolean;
|
||||||
|
emit(event: "error", err: Error): boolean;
|
||||||
|
emit(event: "listening"): boolean;
|
||||||
|
emit(
|
||||||
|
event: "checkContinue",
|
||||||
|
req: InstanceType<Request>,
|
||||||
|
res: InstanceType<Response>,
|
||||||
|
): boolean;
|
||||||
|
emit(
|
||||||
|
event: "checkExpectation",
|
||||||
|
req: InstanceType<Request>,
|
||||||
|
res: InstanceType<Response>,
|
||||||
|
): boolean;
|
||||||
|
emit(event: "clientError", err: Error, socket: Duplex): boolean;
|
||||||
|
emit(event: "connect", req: InstanceType<Request>, socket: Duplex, head: Buffer): boolean;
|
||||||
|
emit(
|
||||||
|
event: "request",
|
||||||
|
req: InstanceType<Request>,
|
||||||
|
res: InstanceType<Response>,
|
||||||
|
): boolean;
|
||||||
|
emit(event: "upgrade", req: InstanceType<Request>, socket: Duplex, head: Buffer): boolean;
|
||||||
|
on(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
on(event: "keylog", listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
on(
|
||||||
|
event: "newSession",
|
||||||
|
listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
on(
|
||||||
|
event: "OCSPRequest",
|
||||||
|
listener: (
|
||||||
|
certificate: Buffer,
|
||||||
|
issuer: Buffer,
|
||||||
|
callback: (err: Error | null, resp: Buffer) => void,
|
||||||
|
) => void,
|
||||||
|
): this;
|
||||||
|
on(
|
||||||
|
event: "resumeSession",
|
||||||
|
listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
on(event: "secureConnection", listener: (tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
on(event: "tlsClientError", listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
on(event: "close", listener: () => void): this;
|
||||||
|
on(event: "connection", listener: (socket: Duplex) => void): this;
|
||||||
|
on(event: "error", listener: (err: Error) => void): this;
|
||||||
|
on(event: "listening", listener: () => void): this;
|
||||||
|
on(event: "checkContinue", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
on(event: "checkExpectation", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
on(event: "clientError", listener: (err: Error, socket: Duplex) => void): this;
|
||||||
|
on(event: "connect", listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void): this;
|
||||||
|
on(event: "request", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
on(event: "upgrade", listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void): this;
|
||||||
|
once(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
once(event: "keylog", listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
once(
|
||||||
|
event: "newSession",
|
||||||
|
listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
once(
|
||||||
|
event: "OCSPRequest",
|
||||||
|
listener: (
|
||||||
|
certificate: Buffer,
|
||||||
|
issuer: Buffer,
|
||||||
|
callback: (err: Error | null, resp: Buffer) => void,
|
||||||
|
) => void,
|
||||||
|
): this;
|
||||||
|
once(
|
||||||
|
event: "resumeSession",
|
||||||
|
listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
once(event: "secureConnection", listener: (tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
once(event: "tlsClientError", listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
once(event: "close", listener: () => void): this;
|
||||||
|
once(event: "connection", listener: (socket: Duplex) => void): this;
|
||||||
|
once(event: "error", listener: (err: Error) => void): this;
|
||||||
|
once(event: "listening", listener: () => void): this;
|
||||||
|
once(event: "checkContinue", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
once(event: "checkExpectation", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
once(event: "clientError", listener: (err: Error, socket: Duplex) => void): this;
|
||||||
|
once(event: "connect", listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void): this;
|
||||||
|
once(event: "request", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
once(event: "upgrade", listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void): this;
|
||||||
|
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependListener(event: "keylog", listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
prependListener(
|
||||||
|
event: "newSession",
|
||||||
|
listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
prependListener(
|
||||||
|
event: "OCSPRequest",
|
||||||
|
listener: (
|
||||||
|
certificate: Buffer,
|
||||||
|
issuer: Buffer,
|
||||||
|
callback: (err: Error | null, resp: Buffer) => void,
|
||||||
|
) => void,
|
||||||
|
): this;
|
||||||
|
prependListener(
|
||||||
|
event: "resumeSession",
|
||||||
|
listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
prependListener(event: "secureConnection", listener: (tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
prependListener(event: "tlsClientError", listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
prependListener(event: "close", listener: () => void): this;
|
||||||
|
prependListener(event: "connection", listener: (socket: Duplex) => void): this;
|
||||||
|
prependListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
prependListener(event: "listening", listener: () => void): this;
|
||||||
|
prependListener(event: "checkContinue", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
prependListener(event: "checkExpectation", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
prependListener(event: "clientError", listener: (err: Error, socket: Duplex) => void): this;
|
||||||
|
prependListener(
|
||||||
|
event: "connect",
|
||||||
|
listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void,
|
||||||
|
): this;
|
||||||
|
prependListener(event: "request", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
prependListener(
|
||||||
|
event: "upgrade",
|
||||||
|
listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void,
|
||||||
|
): this;
|
||||||
|
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependOnceListener(event: "keylog", listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
prependOnceListener(
|
||||||
|
event: "newSession",
|
||||||
|
listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
prependOnceListener(
|
||||||
|
event: "OCSPRequest",
|
||||||
|
listener: (
|
||||||
|
certificate: Buffer,
|
||||||
|
issuer: Buffer,
|
||||||
|
callback: (err: Error | null, resp: Buffer) => void,
|
||||||
|
) => void,
|
||||||
|
): this;
|
||||||
|
prependOnceListener(
|
||||||
|
event: "resumeSession",
|
||||||
|
listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void,
|
||||||
|
): this;
|
||||||
|
prependOnceListener(event: "secureConnection", listener: (tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
prependOnceListener(event: "tlsClientError", listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
|
||||||
|
prependOnceListener(event: "close", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "connection", listener: (socket: Duplex) => void): this;
|
||||||
|
prependOnceListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
prependOnceListener(event: "listening", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "checkContinue", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
prependOnceListener(event: "checkExpectation", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
prependOnceListener(event: "clientError", listener: (err: Error, socket: Duplex) => void): this;
|
||||||
|
prependOnceListener(
|
||||||
|
event: "connect",
|
||||||
|
listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void,
|
||||||
|
): this;
|
||||||
|
prependOnceListener(event: "request", listener: http.RequestListener<Request, Response>): this;
|
||||||
|
prependOnceListener(
|
||||||
|
event: "upgrade",
|
||||||
|
listener: (req: InstanceType<Request>, socket: Duplex, head: Buffer) => void,
|
||||||
|
): this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* ```js
|
||||||
|
* // curl -k https://localhost:8000/
|
||||||
|
* import https from 'node:https';
|
||||||
|
* import fs from 'node:fs';
|
||||||
|
*
|
||||||
|
* const options = {
|
||||||
|
* key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
|
||||||
|
* cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'),
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* https.createServer(options, (req, res) => {
|
||||||
|
* res.writeHead(200);
|
||||||
|
* res.end('hello world\n');
|
||||||
|
* }).listen(8000);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Or
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import https from 'node:https';
|
||||||
|
* import fs from 'node:fs';
|
||||||
|
*
|
||||||
|
* const options = {
|
||||||
|
* pfx: fs.readFileSync('test/fixtures/test_cert.pfx'),
|
||||||
|
* passphrase: 'sample',
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* https.createServer(options, (req, res) => {
|
||||||
|
* res.writeHead(200);
|
||||||
|
* res.end('hello world\n');
|
||||||
|
* }).listen(8000);
|
||||||
|
* ```
|
||||||
|
* @since v0.3.4
|
||||||
|
* @param options Accepts `options` from `createServer`, `createSecureContext` and `createServer`.
|
||||||
|
* @param requestListener A listener to be added to the `'request'` event.
|
||||||
|
*/
|
||||||
|
function createServer<
|
||||||
|
Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,
|
||||||
|
Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse,
|
||||||
|
>(requestListener?: http.RequestListener<Request, Response>): Server<Request, Response>;
|
||||||
|
function createServer<
|
||||||
|
Request extends typeof http.IncomingMessage = typeof http.IncomingMessage,
|
||||||
|
Response extends typeof http.ServerResponse<InstanceType<Request>> = typeof http.ServerResponse,
|
||||||
|
>(
|
||||||
|
options: ServerOptions<Request, Response>,
|
||||||
|
requestListener?: http.RequestListener<Request, Response>,
|
||||||
|
): Server<Request, Response>;
|
||||||
|
/**
|
||||||
|
* Makes a request to a secure web server.
|
||||||
|
*
|
||||||
|
* The following additional `options` from `tls.connect()` are also accepted: `ca`, `cert`, `ciphers`, `clientCertEngine`, `crl`, `dhparam`, `ecdhCurve`, `honorCipherOrder`, `key`, `passphrase`,
|
||||||
|
* `pfx`, `rejectUnauthorized`, `secureOptions`, `secureProtocol`, `servername`, `sessionIdContext`, `highWaterMark`.
|
||||||
|
*
|
||||||
|
* `options` can be an object, a string, or a `URL` object. If `options` is a
|
||||||
|
* string, it is automatically parsed with `new URL()`. If it is a `URL` object, it will be automatically converted to an ordinary `options` object.
|
||||||
|
*
|
||||||
|
* `https.request()` returns an instance of the `http.ClientRequest` class. The `ClientRequest` instance is a writable stream. If one needs to
|
||||||
|
* upload a file with a POST request, then write to the `ClientRequest` object.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import https from 'node:https';
|
||||||
|
*
|
||||||
|
* const options = {
|
||||||
|
* hostname: 'encrypted.google.com',
|
||||||
|
* port: 443,
|
||||||
|
* path: '/',
|
||||||
|
* method: 'GET',
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* const req = https.request(options, (res) => {
|
||||||
|
* console.log('statusCode:', res.statusCode);
|
||||||
|
* console.log('headers:', res.headers);
|
||||||
|
*
|
||||||
|
* res.on('data', (d) => {
|
||||||
|
* process.stdout.write(d);
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* req.on('error', (e) => {
|
||||||
|
* console.error(e);
|
||||||
|
* });
|
||||||
|
* req.end();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example using options from `tls.connect()`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const options = {
|
||||||
|
* hostname: 'encrypted.google.com',
|
||||||
|
* port: 443,
|
||||||
|
* path: '/',
|
||||||
|
* method: 'GET',
|
||||||
|
* key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
|
||||||
|
* cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'),
|
||||||
|
* };
|
||||||
|
* options.agent = new https.Agent(options);
|
||||||
|
*
|
||||||
|
* const req = https.request(options, (res) => {
|
||||||
|
* // ...
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Alternatively, opt out of connection pooling by not using an `Agent`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const options = {
|
||||||
|
* hostname: 'encrypted.google.com',
|
||||||
|
* port: 443,
|
||||||
|
* path: '/',
|
||||||
|
* method: 'GET',
|
||||||
|
* key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
|
||||||
|
* cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'),
|
||||||
|
* agent: false,
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* const req = https.request(options, (res) => {
|
||||||
|
* // ...
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example using a `URL` as `options`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const options = new URL('https://abc:xyz@example.com');
|
||||||
|
*
|
||||||
|
* const req = https.request(options, (res) => {
|
||||||
|
* // ...
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example pinning on certificate fingerprint, or the public key (similar to`pin-sha256`):
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import tls from 'node:tls';
|
||||||
|
* import https from 'node:https';
|
||||||
|
* import crypto from 'node:crypto';
|
||||||
|
*
|
||||||
|
* function sha256(s) {
|
||||||
|
* return crypto.createHash('sha256').update(s).digest('base64');
|
||||||
|
* }
|
||||||
|
* const options = {
|
||||||
|
* hostname: 'github.com',
|
||||||
|
* port: 443,
|
||||||
|
* path: '/',
|
||||||
|
* method: 'GET',
|
||||||
|
* checkServerIdentity: function(host, cert) {
|
||||||
|
* // Make sure the certificate is issued to the host we are connected to
|
||||||
|
* const err = tls.checkServerIdentity(host, cert);
|
||||||
|
* if (err) {
|
||||||
|
* return err;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Pin the public key, similar to HPKP pin-sha256 pinning
|
||||||
|
* const pubkey256 = 'pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU=';
|
||||||
|
* if (sha256(cert.pubkey) !== pubkey256) {
|
||||||
|
* const msg = 'Certificate verification error: ' +
|
||||||
|
* `The public key of '${cert.subject.CN}' ` +
|
||||||
|
* 'does not match our pinned fingerprint';
|
||||||
|
* return new Error(msg);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Pin the exact certificate, rather than the pub key
|
||||||
|
* const cert256 = '25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:' +
|
||||||
|
* 'D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16';
|
||||||
|
* if (cert.fingerprint256 !== cert256) {
|
||||||
|
* const msg = 'Certificate verification error: ' +
|
||||||
|
* `The certificate of '${cert.subject.CN}' ` +
|
||||||
|
* 'does not match our pinned fingerprint';
|
||||||
|
* return new Error(msg);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // This loop is informational only.
|
||||||
|
* // Print the certificate and public key fingerprints of all certs in the
|
||||||
|
* // chain. Its common to pin the public key of the issuer on the public
|
||||||
|
* // internet, while pinning the public key of the service in sensitive
|
||||||
|
* // environments.
|
||||||
|
* do {
|
||||||
|
* console.log('Subject Common Name:', cert.subject.CN);
|
||||||
|
* console.log(' Certificate SHA256 fingerprint:', cert.fingerprint256);
|
||||||
|
*
|
||||||
|
* hash = crypto.createHash('sha256');
|
||||||
|
* console.log(' Public key ping-sha256:', sha256(cert.pubkey));
|
||||||
|
*
|
||||||
|
* lastprint256 = cert.fingerprint256;
|
||||||
|
* cert = cert.issuerCertificate;
|
||||||
|
* } while (cert.fingerprint256 !== lastprint256);
|
||||||
|
*
|
||||||
|
* },
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* options.agent = new https.Agent(options);
|
||||||
|
* const req = https.request(options, (res) => {
|
||||||
|
* console.log('All OK. Server matched our pinned cert or public key');
|
||||||
|
* console.log('statusCode:', res.statusCode);
|
||||||
|
* // Print the HPKP values
|
||||||
|
* console.log('headers:', res.headers['public-key-pins']);
|
||||||
|
*
|
||||||
|
* res.on('data', (d) => {});
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* req.on('error', (e) => {
|
||||||
|
* console.error(e.message);
|
||||||
|
* });
|
||||||
|
* req.end();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Outputs for example:
|
||||||
|
*
|
||||||
|
* ```text
|
||||||
|
* Subject Common Name: github.com
|
||||||
|
* Certificate SHA256 fingerprint: 25:FE:39:32:D9:63:8C:8A:FC:A1:9A:29:87:D8:3E:4C:1D:98:DB:71:E4:1A:48:03:98:EA:22:6A:BD:8B:93:16
|
||||||
|
* Public key ping-sha256: pL1+qb9HTMRZJmuC/bB/ZI9d302BYrrqiVuRyW+DGrU=
|
||||||
|
* Subject Common Name: DigiCert SHA2 Extended Validation Server CA
|
||||||
|
* Certificate SHA256 fingerprint: 40:3E:06:2A:26:53:05:91:13:28:5B:AF:80:A0:D4:AE:42:2C:84:8C:9F:78:FA:D0:1F:C9:4B:C5:B8:7F:EF:1A
|
||||||
|
* Public key ping-sha256: RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=
|
||||||
|
* Subject Common Name: DigiCert High Assurance EV Root CA
|
||||||
|
* Certificate SHA256 fingerprint: 74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF
|
||||||
|
* Public key ping-sha256: WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=
|
||||||
|
* All OK. Server matched our pinned cert or public key
|
||||||
|
* statusCode: 200
|
||||||
|
* headers: max-age=0; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=";
|
||||||
|
* pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4=";
|
||||||
|
* pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains
|
||||||
|
* ```
|
||||||
|
* @since v0.3.6
|
||||||
|
* @param options Accepts all `options` from `request`, with some differences in default values:
|
||||||
|
*/
|
||||||
|
function request(
|
||||||
|
options: RequestOptions | string | URL,
|
||||||
|
callback?: (res: http.IncomingMessage) => void,
|
||||||
|
): http.ClientRequest;
|
||||||
|
function request(
|
||||||
|
url: string | URL,
|
||||||
|
options: RequestOptions,
|
||||||
|
callback?: (res: http.IncomingMessage) => void,
|
||||||
|
): http.ClientRequest;
|
||||||
|
/**
|
||||||
|
* Like `http.get()` but for HTTPS.
|
||||||
|
*
|
||||||
|
* `options` can be an object, a string, or a `URL` object. If `options` is a
|
||||||
|
* string, it is automatically parsed with `new URL()`. If it is a `URL` object, it will be automatically converted to an ordinary `options` object.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import https from 'node:https';
|
||||||
|
*
|
||||||
|
* https.get('https://encrypted.google.com/', (res) => {
|
||||||
|
* console.log('statusCode:', res.statusCode);
|
||||||
|
* console.log('headers:', res.headers);
|
||||||
|
*
|
||||||
|
* res.on('data', (d) => {
|
||||||
|
* process.stdout.write(d);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* }).on('error', (e) => {
|
||||||
|
* console.error(e);
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v0.3.6
|
||||||
|
* @param options Accepts the same `options` as {@link request}, with the `method` always set to `GET`.
|
||||||
|
*/
|
||||||
|
function get(
|
||||||
|
options: RequestOptions | string | URL,
|
||||||
|
callback?: (res: http.IncomingMessage) => void,
|
||||||
|
): http.ClientRequest;
|
||||||
|
function get(
|
||||||
|
url: string | URL,
|
||||||
|
options: RequestOptions,
|
||||||
|
callback?: (res: http.IncomingMessage) => void,
|
||||||
|
): http.ClientRequest;
|
||||||
|
let globalAgent: Agent;
|
||||||
|
}
|
||||||
|
declare module "node:https" {
|
||||||
|
export * from "https";
|
||||||
|
}
|
||||||
93
node_modules/@types/node/index.d.ts
generated
vendored
Normal file
93
node_modules/@types/node/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* License for programmatically and manually incorporated
|
||||||
|
* documentation aka. `JSDoc` from https://github.com/nodejs/node/tree/master/doc
|
||||||
|
*
|
||||||
|
* Copyright Node.js contributors. All rights reserved.
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NOTE: These definitions support Node.js and TypeScript 5.7+.
|
||||||
|
|
||||||
|
// Reference required TypeScript libs:
|
||||||
|
/// <reference lib="es2020" />
|
||||||
|
|
||||||
|
// TypeScript backwards-compatibility definitions:
|
||||||
|
/// <reference path="compatibility/index.d.ts" />
|
||||||
|
|
||||||
|
// Definitions specific to TypeScript 5.7+:
|
||||||
|
/// <reference path="globals.typedarray.d.ts" />
|
||||||
|
/// <reference path="buffer.buffer.d.ts" />
|
||||||
|
|
||||||
|
// Definitions for Node.js modules that are not specific to any version of TypeScript:
|
||||||
|
/// <reference path="globals.d.ts" />
|
||||||
|
/// <reference path="web-globals/abortcontroller.d.ts" />
|
||||||
|
/// <reference path="web-globals/domexception.d.ts" />
|
||||||
|
/// <reference path="web-globals/events.d.ts" />
|
||||||
|
/// <reference path="web-globals/fetch.d.ts" />
|
||||||
|
/// <reference path="assert.d.ts" />
|
||||||
|
/// <reference path="assert/strict.d.ts" />
|
||||||
|
/// <reference path="async_hooks.d.ts" />
|
||||||
|
/// <reference path="buffer.d.ts" />
|
||||||
|
/// <reference path="child_process.d.ts" />
|
||||||
|
/// <reference path="cluster.d.ts" />
|
||||||
|
/// <reference path="console.d.ts" />
|
||||||
|
/// <reference path="constants.d.ts" />
|
||||||
|
/// <reference path="crypto.d.ts" />
|
||||||
|
/// <reference path="dgram.d.ts" />
|
||||||
|
/// <reference path="diagnostics_channel.d.ts" />
|
||||||
|
/// <reference path="dns.d.ts" />
|
||||||
|
/// <reference path="dns/promises.d.ts" />
|
||||||
|
/// <reference path="domain.d.ts" />
|
||||||
|
/// <reference path="events.d.ts" />
|
||||||
|
/// <reference path="fs.d.ts" />
|
||||||
|
/// <reference path="fs/promises.d.ts" />
|
||||||
|
/// <reference path="http.d.ts" />
|
||||||
|
/// <reference path="http2.d.ts" />
|
||||||
|
/// <reference path="https.d.ts" />
|
||||||
|
/// <reference path="inspector.generated.d.ts" />
|
||||||
|
/// <reference path="module.d.ts" />
|
||||||
|
/// <reference path="net.d.ts" />
|
||||||
|
/// <reference path="os.d.ts" />
|
||||||
|
/// <reference path="path.d.ts" />
|
||||||
|
/// <reference path="perf_hooks.d.ts" />
|
||||||
|
/// <reference path="process.d.ts" />
|
||||||
|
/// <reference path="punycode.d.ts" />
|
||||||
|
/// <reference path="querystring.d.ts" />
|
||||||
|
/// <reference path="readline.d.ts" />
|
||||||
|
/// <reference path="readline/promises.d.ts" />
|
||||||
|
/// <reference path="repl.d.ts" />
|
||||||
|
/// <reference path="sea.d.ts" />
|
||||||
|
/// <reference path="stream.d.ts" />
|
||||||
|
/// <reference path="stream/promises.d.ts" />
|
||||||
|
/// <reference path="stream/consumers.d.ts" />
|
||||||
|
/// <reference path="stream/web.d.ts" />
|
||||||
|
/// <reference path="string_decoder.d.ts" />
|
||||||
|
/// <reference path="test.d.ts" />
|
||||||
|
/// <reference path="timers.d.ts" />
|
||||||
|
/// <reference path="timers/promises.d.ts" />
|
||||||
|
/// <reference path="tls.d.ts" />
|
||||||
|
/// <reference path="trace_events.d.ts" />
|
||||||
|
/// <reference path="tty.d.ts" />
|
||||||
|
/// <reference path="url.d.ts" />
|
||||||
|
/// <reference path="util.d.ts" />
|
||||||
|
/// <reference path="v8.d.ts" />
|
||||||
|
/// <reference path="vm.d.ts" />
|
||||||
|
/// <reference path="wasi.d.ts" />
|
||||||
|
/// <reference path="worker_threads.d.ts" />
|
||||||
|
/// <reference path="zlib.d.ts" />
|
||||||
3966
node_modules/@types/node/inspector.generated.d.ts
generated
vendored
Normal file
3966
node_modules/@types/node/inspector.generated.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
539
node_modules/@types/node/module.d.ts
generated
vendored
Normal file
539
node_modules/@types/node/module.d.ts
generated
vendored
Normal file
@@ -0,0 +1,539 @@
|
|||||||
|
/**
|
||||||
|
* @since v0.3.7
|
||||||
|
*/
|
||||||
|
declare module "module" {
|
||||||
|
import { URL } from "node:url";
|
||||||
|
import { MessagePort } from "node:worker_threads";
|
||||||
|
class Module {
|
||||||
|
constructor(id: string, parent?: Module);
|
||||||
|
}
|
||||||
|
interface Module extends NodeJS.Module {}
|
||||||
|
namespace Module {
|
||||||
|
export { Module };
|
||||||
|
}
|
||||||
|
namespace Module {
|
||||||
|
/**
|
||||||
|
* A list of the names of all modules provided by Node.js. Can be used to verify
|
||||||
|
* if a module is maintained by a third party or not.
|
||||||
|
*
|
||||||
|
* Note: the list doesn't contain prefix-only modules like `node:test`.
|
||||||
|
* @since v9.3.0, v8.10.0, v6.13.0
|
||||||
|
*/
|
||||||
|
const builtinModules: readonly string[];
|
||||||
|
/**
|
||||||
|
* @since v12.2.0
|
||||||
|
* @param path Filename to be used to construct the require
|
||||||
|
* function. Must be a file URL object, file URL string, or absolute path
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
function createRequire(path: string | URL): NodeJS.Require;
|
||||||
|
/**
|
||||||
|
* @since v18.6.0, v16.17.0
|
||||||
|
*/
|
||||||
|
function isBuiltin(moduleName: string): boolean;
|
||||||
|
interface RegisterOptions<Data> {
|
||||||
|
/**
|
||||||
|
* If you want to resolve `specifier` relative to a
|
||||||
|
* base URL, such as `import.meta.url`, you can pass that URL here. This
|
||||||
|
* property is ignored if the `parentURL` is supplied as the second argument.
|
||||||
|
* @default 'data:'
|
||||||
|
*/
|
||||||
|
parentURL?: string | URL | undefined;
|
||||||
|
/**
|
||||||
|
* Any arbitrary, cloneable JavaScript value to pass into the
|
||||||
|
* {@link initialize} hook.
|
||||||
|
*/
|
||||||
|
data?: Data | undefined;
|
||||||
|
/**
|
||||||
|
* [Transferable objects](https://nodejs.org/docs/latest-v20.x/api/worker_threads.html#portpostmessagevalue-transferlist)
|
||||||
|
* to be passed into the `initialize` hook.
|
||||||
|
*/
|
||||||
|
transferList?: any[] | undefined;
|
||||||
|
}
|
||||||
|
/* eslint-disable @definitelytyped/no-unnecessary-generics */
|
||||||
|
/**
|
||||||
|
* Register a module that exports hooks that customize Node.js module
|
||||||
|
* resolution and loading behavior. See
|
||||||
|
* [Customization hooks](https://nodejs.org/docs/latest-v20.x/api/module.html#customization-hooks).
|
||||||
|
* @since v20.6.0, v18.19.0
|
||||||
|
* @param specifier Customization hooks to be registered; this should be
|
||||||
|
* the same string that would be passed to `import()`, except that if it is
|
||||||
|
* relative, it is resolved relative to `parentURL`.
|
||||||
|
* @param parentURL f you want to resolve `specifier` relative to a base
|
||||||
|
* URL, such as `import.meta.url`, you can pass that URL here.
|
||||||
|
*/
|
||||||
|
function register<Data = any>(
|
||||||
|
specifier: string | URL,
|
||||||
|
parentURL?: string | URL,
|
||||||
|
options?: RegisterOptions<Data>,
|
||||||
|
): void;
|
||||||
|
function register<Data = any>(specifier: string | URL, options?: RegisterOptions<Data>): void;
|
||||||
|
/* eslint-enable @definitelytyped/no-unnecessary-generics */
|
||||||
|
/**
|
||||||
|
* The `module.syncBuiltinESMExports()` method updates all the live bindings for
|
||||||
|
* builtin `ES Modules` to match the properties of the `CommonJS` exports. It
|
||||||
|
* does not add or remove exported names from the `ES Modules`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import fs from 'node:fs';
|
||||||
|
* import assert from 'node:assert';
|
||||||
|
* import { syncBuiltinESMExports } from 'node:module';
|
||||||
|
*
|
||||||
|
* fs.readFile = newAPI;
|
||||||
|
*
|
||||||
|
* delete fs.readFileSync;
|
||||||
|
*
|
||||||
|
* function newAPI() {
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* fs.newAPI = newAPI;
|
||||||
|
*
|
||||||
|
* syncBuiltinESMExports();
|
||||||
|
*
|
||||||
|
* import('node:fs').then((esmFS) => {
|
||||||
|
* // It syncs the existing readFile property with the new value
|
||||||
|
* assert.strictEqual(esmFS.readFile, newAPI);
|
||||||
|
* // readFileSync has been deleted from the required fs
|
||||||
|
* assert.strictEqual('readFileSync' in fs, false);
|
||||||
|
* // syncBuiltinESMExports() does not remove readFileSync from esmFS
|
||||||
|
* assert.strictEqual('readFileSync' in esmFS, true);
|
||||||
|
* // syncBuiltinESMExports() does not add names
|
||||||
|
* assert.strictEqual(esmFS.newAPI, undefined);
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v12.12.0
|
||||||
|
*/
|
||||||
|
function syncBuiltinESMExports(): void;
|
||||||
|
/** @deprecated Use `ImportAttributes` instead */
|
||||||
|
interface ImportAssertions extends ImportAttributes {}
|
||||||
|
interface ImportAttributes extends NodeJS.Dict<string> {
|
||||||
|
type?: string | undefined;
|
||||||
|
}
|
||||||
|
type ModuleFormat = "builtin" | "commonjs" | "json" | "module" | "wasm";
|
||||||
|
type ModuleSource = string | ArrayBuffer | NodeJS.TypedArray;
|
||||||
|
/**
|
||||||
|
* The `initialize` hook provides a way to define a custom function that runs in
|
||||||
|
* the hooks thread when the hooks module is initialized. Initialization happens
|
||||||
|
* when the hooks module is registered via {@link register}.
|
||||||
|
*
|
||||||
|
* This hook can receive data from a {@link register} invocation, including
|
||||||
|
* ports and other transferable objects. The return value of `initialize` can be a
|
||||||
|
* `Promise`, in which case it will be awaited before the main application thread
|
||||||
|
* execution resumes.
|
||||||
|
*/
|
||||||
|
type InitializeHook<Data = any> = (data: Data) => void | Promise<void>;
|
||||||
|
interface ResolveHookContext {
|
||||||
|
/**
|
||||||
|
* Export conditions of the relevant `package.json`
|
||||||
|
*/
|
||||||
|
conditions: string[];
|
||||||
|
/**
|
||||||
|
* @deprecated Use `importAttributes` instead
|
||||||
|
*/
|
||||||
|
importAssertions: ImportAttributes;
|
||||||
|
/**
|
||||||
|
* An object whose key-value pairs represent the assertions for the module to import
|
||||||
|
*/
|
||||||
|
importAttributes: ImportAttributes;
|
||||||
|
/**
|
||||||
|
* The module importing this one, or undefined if this is the Node.js entry point
|
||||||
|
*/
|
||||||
|
parentURL: string | undefined;
|
||||||
|
}
|
||||||
|
interface ResolveFnOutput {
|
||||||
|
/**
|
||||||
|
* A hint to the load hook (it might be ignored)
|
||||||
|
*/
|
||||||
|
format?: ModuleFormat | null | undefined;
|
||||||
|
/**
|
||||||
|
* @deprecated Use `importAttributes` instead
|
||||||
|
*/
|
||||||
|
importAssertions?: ImportAttributes | undefined;
|
||||||
|
/**
|
||||||
|
* The import attributes to use when caching the module (optional; if excluded the input will be used)
|
||||||
|
*/
|
||||||
|
importAttributes?: ImportAttributes | undefined;
|
||||||
|
/**
|
||||||
|
* A signal that this hook intends to terminate the chain of `resolve` hooks.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
shortCircuit?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* The absolute URL to which this input resolves
|
||||||
|
*/
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `resolve` hook chain is responsible for telling Node.js where to find and
|
||||||
|
* how to cache a given `import` statement or expression, or `require` call. It can
|
||||||
|
* optionally return a format (such as `'module'`) as a hint to the `load` hook. If
|
||||||
|
* a format is specified, the `load` hook is ultimately responsible for providing
|
||||||
|
* the final `format` value (and it is free to ignore the hint provided by
|
||||||
|
* `resolve`); if `resolve` provides a `format`, a custom `load` hook is required
|
||||||
|
* even if only to pass the value to the Node.js default `load` hook.
|
||||||
|
*/
|
||||||
|
type ResolveHook = (
|
||||||
|
specifier: string,
|
||||||
|
context: ResolveHookContext,
|
||||||
|
nextResolve: (
|
||||||
|
specifier: string,
|
||||||
|
context?: Partial<ResolveHookContext>,
|
||||||
|
) => ResolveFnOutput | Promise<ResolveFnOutput>,
|
||||||
|
) => ResolveFnOutput | Promise<ResolveFnOutput>;
|
||||||
|
interface LoadHookContext {
|
||||||
|
/**
|
||||||
|
* Export conditions of the relevant `package.json`
|
||||||
|
*/
|
||||||
|
conditions: string[];
|
||||||
|
/**
|
||||||
|
* The format optionally supplied by the `resolve` hook chain
|
||||||
|
*/
|
||||||
|
format: ModuleFormat | null | undefined;
|
||||||
|
/**
|
||||||
|
* @deprecated Use `importAttributes` instead
|
||||||
|
*/
|
||||||
|
importAssertions: ImportAttributes;
|
||||||
|
/**
|
||||||
|
* An object whose key-value pairs represent the assertions for the module to import
|
||||||
|
*/
|
||||||
|
importAttributes: ImportAttributes;
|
||||||
|
}
|
||||||
|
interface LoadFnOutput {
|
||||||
|
format: string | null | undefined;
|
||||||
|
/**
|
||||||
|
* A signal that this hook intends to terminate the chain of `resolve` hooks.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
shortCircuit?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* The source for Node.js to evaluate
|
||||||
|
*/
|
||||||
|
source?: ModuleSource | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `load` hook provides a way to define a custom method of determining how a
|
||||||
|
* URL should be interpreted, retrieved, and parsed. It is also in charge of
|
||||||
|
* validating the import attributes.
|
||||||
|
*/
|
||||||
|
type LoadHook = (
|
||||||
|
url: string,
|
||||||
|
context: LoadHookContext,
|
||||||
|
nextLoad: (
|
||||||
|
url: string,
|
||||||
|
context?: Partial<LoadHookContext>,
|
||||||
|
) => LoadFnOutput | Promise<LoadFnOutput>,
|
||||||
|
) => LoadFnOutput | Promise<LoadFnOutput>;
|
||||||
|
interface GlobalPreloadContext {
|
||||||
|
port: MessagePort;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sometimes it might be necessary to run some code inside of the same global
|
||||||
|
* scope that the application runs in. This hook allows the return of a string
|
||||||
|
* that is run as a sloppy-mode script on startup.
|
||||||
|
* @deprecated This hook will be removed in a future version. Use
|
||||||
|
* `initialize` instead. When a hooks module has an `initialize` export,
|
||||||
|
* `globalPreload` will be ignored.
|
||||||
|
*/
|
||||||
|
type GlobalPreloadHook = (context: GlobalPreloadContext) => string;
|
||||||
|
/**
|
||||||
|
* `path` is the resolved path for the file for which a corresponding source map
|
||||||
|
* should be fetched.
|
||||||
|
* @since v13.7.0, v12.17.0
|
||||||
|
* @return Returns `module.SourceMap` if a source map is found, `undefined` otherwise.
|
||||||
|
*/
|
||||||
|
function findSourceMap(path: string): SourceMap | undefined;
|
||||||
|
interface SourceMapConstructorOptions {
|
||||||
|
/**
|
||||||
|
* @since v20.5.0
|
||||||
|
*/
|
||||||
|
lineLengths?: readonly number[] | undefined;
|
||||||
|
}
|
||||||
|
interface SourceMapPayload {
|
||||||
|
file: string;
|
||||||
|
version: number;
|
||||||
|
sources: string[];
|
||||||
|
sourcesContent: string[];
|
||||||
|
names: string[];
|
||||||
|
mappings: string;
|
||||||
|
sourceRoot: string;
|
||||||
|
}
|
||||||
|
interface SourceMapping {
|
||||||
|
generatedLine: number;
|
||||||
|
generatedColumn: number;
|
||||||
|
originalSource: string;
|
||||||
|
originalLine: number;
|
||||||
|
originalColumn: number;
|
||||||
|
}
|
||||||
|
interface SourceOrigin {
|
||||||
|
/**
|
||||||
|
* The name of the range in the source map, if one was provided
|
||||||
|
*/
|
||||||
|
name: string | undefined;
|
||||||
|
/**
|
||||||
|
* The file name of the original source, as reported in the SourceMap
|
||||||
|
*/
|
||||||
|
fileName: string;
|
||||||
|
/**
|
||||||
|
* The 1-indexed lineNumber of the corresponding call site in the original source
|
||||||
|
*/
|
||||||
|
lineNumber: number;
|
||||||
|
/**
|
||||||
|
* The 1-indexed columnNumber of the corresponding call site in the original source
|
||||||
|
*/
|
||||||
|
columnNumber: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @since v13.7.0, v12.17.0
|
||||||
|
*/
|
||||||
|
class SourceMap {
|
||||||
|
constructor(payload: SourceMapPayload, options?: SourceMapConstructorOptions);
|
||||||
|
/**
|
||||||
|
* Getter for the payload used to construct the `SourceMap` instance.
|
||||||
|
*/
|
||||||
|
readonly payload: SourceMapPayload;
|
||||||
|
/**
|
||||||
|
* Given a line offset and column offset in the generated source
|
||||||
|
* file, returns an object representing the SourceMap range in the
|
||||||
|
* original file if found, or an empty object if not.
|
||||||
|
*
|
||||||
|
* The object returned contains the following keys:
|
||||||
|
*
|
||||||
|
* The returned value represents the raw range as it appears in the
|
||||||
|
* SourceMap, based on zero-indexed offsets, _not_ 1-indexed line and
|
||||||
|
* column numbers as they appear in Error messages and CallSite
|
||||||
|
* objects.
|
||||||
|
*
|
||||||
|
* To get the corresponding 1-indexed line and column numbers from a
|
||||||
|
* lineNumber and columnNumber as they are reported by Error stacks
|
||||||
|
* and CallSite objects, use `sourceMap.findOrigin(lineNumber, columnNumber)`
|
||||||
|
* @param lineOffset The zero-indexed line number offset in the generated source
|
||||||
|
* @param columnOffset The zero-indexed column number offset in the generated source
|
||||||
|
*/
|
||||||
|
findEntry(lineOffset: number, columnOffset: number): SourceMapping | {};
|
||||||
|
/**
|
||||||
|
* Given a 1-indexed `lineNumber` and `columnNumber` from a call site in the generated source,
|
||||||
|
* find the corresponding call site location in the original source.
|
||||||
|
*
|
||||||
|
* If the `lineNumber` and `columnNumber` provided are not found in any source map,
|
||||||
|
* then an empty object is returned.
|
||||||
|
* @param lineNumber The 1-indexed line number of the call site in the generated source
|
||||||
|
* @param columnNumber The 1-indexed column number of the call site in the generated source
|
||||||
|
*/
|
||||||
|
findOrigin(lineNumber: number, columnNumber: number): SourceOrigin | {};
|
||||||
|
}
|
||||||
|
function runMain(main?: string): void;
|
||||||
|
function wrap(script: string): string;
|
||||||
|
}
|
||||||
|
global {
|
||||||
|
interface ImportMeta {
|
||||||
|
/**
|
||||||
|
* The directory name of the current module. This is the same as the `path.dirname()` of the `import.meta.filename`.
|
||||||
|
* **Caveat:** only present on `file:` modules.
|
||||||
|
*/
|
||||||
|
dirname: string;
|
||||||
|
/**
|
||||||
|
* The full absolute path and filename of the current module, with symlinks resolved.
|
||||||
|
* This is the same as the `url.fileURLToPath()` of the `import.meta.url`.
|
||||||
|
* **Caveat:** only local modules support this property. Modules not using the `file:` protocol will not provide it.
|
||||||
|
*/
|
||||||
|
filename: string;
|
||||||
|
/**
|
||||||
|
* The absolute `file:` URL of the module.
|
||||||
|
*/
|
||||||
|
url: string;
|
||||||
|
/**
|
||||||
|
* Provides a module-relative resolution function scoped to each module, returning
|
||||||
|
* the URL string.
|
||||||
|
*
|
||||||
|
* Second `parent` parameter is only used when the `--experimental-import-meta-resolve`
|
||||||
|
* command flag enabled.
|
||||||
|
*
|
||||||
|
* @since v20.6.0
|
||||||
|
*
|
||||||
|
* @param specifier The module specifier to resolve relative to `parent`.
|
||||||
|
* @param parent The absolute parent module URL to resolve from.
|
||||||
|
* @returns The absolute (`file:`) URL string for the resolved module.
|
||||||
|
*/
|
||||||
|
resolve(specifier: string, parent?: string | URL | undefined): string;
|
||||||
|
}
|
||||||
|
namespace NodeJS {
|
||||||
|
interface Module {
|
||||||
|
/**
|
||||||
|
* The module objects required for the first time by this one.
|
||||||
|
* @since v0.1.16
|
||||||
|
*/
|
||||||
|
children: Module[];
|
||||||
|
/**
|
||||||
|
* The `module.exports` object is created by the `Module` system. Sometimes this is
|
||||||
|
* not acceptable; many want their module to be an instance of some class. To do
|
||||||
|
* this, assign the desired export object to `module.exports`.
|
||||||
|
* @since v0.1.16
|
||||||
|
*/
|
||||||
|
exports: any;
|
||||||
|
/**
|
||||||
|
* The fully resolved filename of the module.
|
||||||
|
* @since v0.1.16
|
||||||
|
*/
|
||||||
|
filename: string;
|
||||||
|
/**
|
||||||
|
* The identifier for the module. Typically this is the fully resolved
|
||||||
|
* filename.
|
||||||
|
* @since v0.1.16
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* `true` if the module is running during the Node.js preload
|
||||||
|
* phase.
|
||||||
|
* @since v15.4.0, v14.17.0
|
||||||
|
*/
|
||||||
|
isPreloading: boolean;
|
||||||
|
/**
|
||||||
|
* Whether or not the module is done loading, or is in the process of
|
||||||
|
* loading.
|
||||||
|
* @since v0.1.16
|
||||||
|
*/
|
||||||
|
loaded: boolean;
|
||||||
|
/**
|
||||||
|
* The module that first required this one, or `null` if the current module is the
|
||||||
|
* entry point of the current process, or `undefined` if the module was loaded by
|
||||||
|
* something that is not a CommonJS module (e.g. REPL or `import`).
|
||||||
|
* @since v0.1.16
|
||||||
|
* @deprecated Please use `require.main` and `module.children` instead.
|
||||||
|
*/
|
||||||
|
parent: Module | null | undefined;
|
||||||
|
/**
|
||||||
|
* The directory name of the module. This is usually the same as the
|
||||||
|
* `path.dirname()` of the `module.id`.
|
||||||
|
* @since v11.14.0
|
||||||
|
*/
|
||||||
|
path: string;
|
||||||
|
/**
|
||||||
|
* The search paths for the module.
|
||||||
|
* @since v0.4.0
|
||||||
|
*/
|
||||||
|
paths: string[];
|
||||||
|
/**
|
||||||
|
* The `module.require()` method provides a way to load a module as if
|
||||||
|
* `require()` was called from the original module.
|
||||||
|
* @since v0.5.1
|
||||||
|
*/
|
||||||
|
require(id: string): any;
|
||||||
|
}
|
||||||
|
interface Require {
|
||||||
|
/**
|
||||||
|
* Used to import modules, `JSON`, and local files.
|
||||||
|
* @since v0.1.13
|
||||||
|
*/
|
||||||
|
(id: string): any;
|
||||||
|
/**
|
||||||
|
* Modules are cached in this object when they are required. By deleting a key
|
||||||
|
* value from this object, the next `require` will reload the module.
|
||||||
|
* This does not apply to
|
||||||
|
* [native addons](https://nodejs.org/docs/latest-v20.x/api/addons.html),
|
||||||
|
* for which reloading will result in an error.
|
||||||
|
* @since v0.3.0
|
||||||
|
*/
|
||||||
|
cache: Dict<Module>;
|
||||||
|
/**
|
||||||
|
* Instruct `require` on how to handle certain file extensions.
|
||||||
|
* @since v0.3.0
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
extensions: RequireExtensions;
|
||||||
|
/**
|
||||||
|
* The `Module` object representing the entry script loaded when the Node.js
|
||||||
|
* process launched, or `undefined` if the entry point of the program is not a
|
||||||
|
* CommonJS module.
|
||||||
|
* @since v0.1.17
|
||||||
|
*/
|
||||||
|
main: Module | undefined;
|
||||||
|
/**
|
||||||
|
* @since v0.3.0
|
||||||
|
*/
|
||||||
|
resolve: RequireResolve;
|
||||||
|
}
|
||||||
|
/** @deprecated */
|
||||||
|
interface RequireExtensions extends Dict<(module: Module, filename: string) => any> {
|
||||||
|
".js": (module: Module, filename: string) => any;
|
||||||
|
".json": (module: Module, filename: string) => any;
|
||||||
|
".node": (module: Module, filename: string) => any;
|
||||||
|
}
|
||||||
|
interface RequireResolveOptions {
|
||||||
|
/**
|
||||||
|
* Paths to resolve module location from. If present, these
|
||||||
|
* paths are used instead of the default resolution paths, with the exception
|
||||||
|
* of
|
||||||
|
* [GLOBAL\_FOLDERS](https://nodejs.org/docs/latest-v20.x/api/modules.html#loading-from-the-global-folders)
|
||||||
|
* like `$HOME/.node_modules`, which are
|
||||||
|
* always included. Each of these paths is used as a starting point for
|
||||||
|
* the module resolution algorithm, meaning that the `node_modules` hierarchy
|
||||||
|
* is checked from this location.
|
||||||
|
* @since v8.9.0
|
||||||
|
*/
|
||||||
|
paths?: string[] | undefined;
|
||||||
|
}
|
||||||
|
interface RequireResolve {
|
||||||
|
/**
|
||||||
|
* Use the internal `require()` machinery to look up the location of a module,
|
||||||
|
* but rather than loading the module, just return the resolved filename.
|
||||||
|
*
|
||||||
|
* If the module can not be found, a `MODULE_NOT_FOUND` error is thrown.
|
||||||
|
* @since v0.3.0
|
||||||
|
* @param request The module path to resolve.
|
||||||
|
*/
|
||||||
|
(id: string, options?: RequireResolveOptions): string;
|
||||||
|
/**
|
||||||
|
* Returns an array containing the paths searched during resolution of `request` or
|
||||||
|
* `null` if the `request` string references a core module, for example `http` or
|
||||||
|
* `fs`.
|
||||||
|
* @since v8.9.0
|
||||||
|
* @param request The module path whose lookup paths are being retrieved.
|
||||||
|
*/
|
||||||
|
paths(request: string): string[] | null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The directory name of the current module. This is the same as the
|
||||||
|
* `path.dirname()` of the `__filename`.
|
||||||
|
* @since v0.1.27
|
||||||
|
*/
|
||||||
|
var __dirname: string;
|
||||||
|
/**
|
||||||
|
* The file name of the current module. This is the current module file's absolute
|
||||||
|
* path with symlinks resolved.
|
||||||
|
*
|
||||||
|
* For a main program this is not necessarily the same as the file name used in the
|
||||||
|
* command line.
|
||||||
|
* @since v0.0.1
|
||||||
|
*/
|
||||||
|
var __filename: string;
|
||||||
|
/**
|
||||||
|
* The `exports` variable is available within a module's file-level scope, and is
|
||||||
|
* assigned the value of `module.exports` before the module is evaluated.
|
||||||
|
* @since v0.1.16
|
||||||
|
*/
|
||||||
|
var exports: NodeJS.Module["exports"];
|
||||||
|
/**
|
||||||
|
* A reference to the current module.
|
||||||
|
* @since v0.1.16
|
||||||
|
*/
|
||||||
|
var module: NodeJS.Module;
|
||||||
|
/**
|
||||||
|
* @since v0.1.13
|
||||||
|
*/
|
||||||
|
var require: NodeJS.Require;
|
||||||
|
// Global-scope aliases for backwards compatibility with @types/node <13.0.x
|
||||||
|
/** @deprecated Use `NodeJS.Module` instead. */
|
||||||
|
interface NodeModule extends NodeJS.Module {}
|
||||||
|
/** @deprecated Use `NodeJS.Require` instead. */
|
||||||
|
interface NodeRequire extends NodeJS.Require {}
|
||||||
|
/** @deprecated Use `NodeJS.RequireResolve` instead. */
|
||||||
|
interface RequireResolve extends NodeJS.RequireResolve {}
|
||||||
|
}
|
||||||
|
export = Module;
|
||||||
|
}
|
||||||
|
declare module "node:module" {
|
||||||
|
import module = require("module");
|
||||||
|
export = module;
|
||||||
|
}
|
||||||
1011
node_modules/@types/node/net.d.ts
generated
vendored
Normal file
1011
node_modules/@types/node/net.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
495
node_modules/@types/node/os.d.ts
generated
vendored
Normal file
495
node_modules/@types/node/os.d.ts
generated
vendored
Normal file
@@ -0,0 +1,495 @@
|
|||||||
|
/**
|
||||||
|
* The `node:os` module provides operating system-related utility methods and
|
||||||
|
* properties. It can be accessed using:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import os from 'node:os';
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/os.js)
|
||||||
|
*/
|
||||||
|
declare module "os" {
|
||||||
|
interface CpuInfo {
|
||||||
|
model: string;
|
||||||
|
speed: number;
|
||||||
|
times: {
|
||||||
|
/** The number of milliseconds the CPU has spent in user mode. */
|
||||||
|
user: number;
|
||||||
|
/** The number of milliseconds the CPU has spent in nice mode. */
|
||||||
|
nice: number;
|
||||||
|
/** The number of milliseconds the CPU has spent in sys mode. */
|
||||||
|
sys: number;
|
||||||
|
/** The number of milliseconds the CPU has spent in idle mode. */
|
||||||
|
idle: number;
|
||||||
|
/** The number of milliseconds the CPU has spent in irq mode. */
|
||||||
|
irq: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
interface NetworkInterfaceBase {
|
||||||
|
address: string;
|
||||||
|
netmask: string;
|
||||||
|
mac: string;
|
||||||
|
internal: boolean;
|
||||||
|
cidr: string | null;
|
||||||
|
}
|
||||||
|
interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase {
|
||||||
|
family: "IPv4";
|
||||||
|
scopeid?: undefined;
|
||||||
|
}
|
||||||
|
interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase {
|
||||||
|
family: "IPv6";
|
||||||
|
scopeid: number;
|
||||||
|
}
|
||||||
|
interface UserInfo<T> {
|
||||||
|
username: T;
|
||||||
|
uid: number;
|
||||||
|
gid: number;
|
||||||
|
shell: T | null;
|
||||||
|
homedir: T;
|
||||||
|
}
|
||||||
|
type NetworkInterfaceInfo = NetworkInterfaceInfoIPv4 | NetworkInterfaceInfoIPv6;
|
||||||
|
/**
|
||||||
|
* Returns the host name of the operating system as a string.
|
||||||
|
* @since v0.3.3
|
||||||
|
*/
|
||||||
|
function hostname(): string;
|
||||||
|
/**
|
||||||
|
* Returns an array containing the 1, 5, and 15 minute load averages.
|
||||||
|
*
|
||||||
|
* The load average is a measure of system activity calculated by the operating
|
||||||
|
* system and expressed as a fractional number.
|
||||||
|
*
|
||||||
|
* The load average is a Unix-specific concept. On Windows, the return value is
|
||||||
|
* always `[0, 0, 0]`.
|
||||||
|
* @since v0.3.3
|
||||||
|
*/
|
||||||
|
function loadavg(): number[];
|
||||||
|
/**
|
||||||
|
* Returns the system uptime in number of seconds.
|
||||||
|
* @since v0.3.3
|
||||||
|
*/
|
||||||
|
function uptime(): number;
|
||||||
|
/**
|
||||||
|
* Returns the amount of free system memory in bytes as an integer.
|
||||||
|
* @since v0.3.3
|
||||||
|
*/
|
||||||
|
function freemem(): number;
|
||||||
|
/**
|
||||||
|
* Returns the total amount of system memory in bytes as an integer.
|
||||||
|
* @since v0.3.3
|
||||||
|
*/
|
||||||
|
function totalmem(): number;
|
||||||
|
/**
|
||||||
|
* Returns an array of objects containing information about each logical CPU core.
|
||||||
|
* The array will be empty if no CPU information is available, such as if the `/proc` file system is unavailable.
|
||||||
|
*
|
||||||
|
* The properties included on each object include:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* [
|
||||||
|
* {
|
||||||
|
* model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
|
||||||
|
* speed: 2926,
|
||||||
|
* times: {
|
||||||
|
* user: 252020,
|
||||||
|
* nice: 0,
|
||||||
|
* sys: 30340,
|
||||||
|
* idle: 1070356870,
|
||||||
|
* irq: 0,
|
||||||
|
* },
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
|
||||||
|
* speed: 2926,
|
||||||
|
* times: {
|
||||||
|
* user: 306960,
|
||||||
|
* nice: 0,
|
||||||
|
* sys: 26980,
|
||||||
|
* idle: 1071569080,
|
||||||
|
* irq: 0,
|
||||||
|
* },
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
|
||||||
|
* speed: 2926,
|
||||||
|
* times: {
|
||||||
|
* user: 248450,
|
||||||
|
* nice: 0,
|
||||||
|
* sys: 21750,
|
||||||
|
* idle: 1070919370,
|
||||||
|
* irq: 0,
|
||||||
|
* },
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',
|
||||||
|
* speed: 2926,
|
||||||
|
* times: {
|
||||||
|
* user: 256880,
|
||||||
|
* nice: 0,
|
||||||
|
* sys: 19430,
|
||||||
|
* idle: 1070905480,
|
||||||
|
* irq: 20,
|
||||||
|
* },
|
||||||
|
* },
|
||||||
|
* ]
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* `nice` values are POSIX-only. On Windows, the `nice` values of all processors
|
||||||
|
* are always 0.
|
||||||
|
*
|
||||||
|
* `os.cpus().length` should not be used to calculate the amount of parallelism
|
||||||
|
* available to an application. Use {@link availableParallelism} for this purpose.
|
||||||
|
* @since v0.3.3
|
||||||
|
*/
|
||||||
|
function cpus(): CpuInfo[];
|
||||||
|
/**
|
||||||
|
* Returns an estimate of the default amount of parallelism a program should use.
|
||||||
|
* Always returns a value greater than zero.
|
||||||
|
*
|
||||||
|
* This function is a small wrapper about libuv's [`uv_available_parallelism()`](https://docs.libuv.org/en/v1.x/misc.html#c.uv_available_parallelism).
|
||||||
|
* @since v19.4.0, v18.14.0
|
||||||
|
*/
|
||||||
|
function availableParallelism(): number;
|
||||||
|
/**
|
||||||
|
* Returns the operating system name as returned by [`uname(3)`](https://linux.die.net/man/3/uname). For example, it
|
||||||
|
* returns `'Linux'` on Linux, `'Darwin'` on macOS, and `'Windows_NT'` on Windows.
|
||||||
|
*
|
||||||
|
* See [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for additional information
|
||||||
|
* about the output of running [`uname(3)`](https://linux.die.net/man/3/uname) on various operating systems.
|
||||||
|
* @since v0.3.3
|
||||||
|
*/
|
||||||
|
function type(): string;
|
||||||
|
/**
|
||||||
|
* Returns the operating system as a string.
|
||||||
|
*
|
||||||
|
* On POSIX systems, the operating system release is determined by calling [`uname(3)`](https://linux.die.net/man/3/uname). On Windows, `GetVersionExW()` is used. See
|
||||||
|
* [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for more information.
|
||||||
|
* @since v0.3.3
|
||||||
|
*/
|
||||||
|
function release(): string;
|
||||||
|
/**
|
||||||
|
* Returns an object containing network interfaces that have been assigned a
|
||||||
|
* network address.
|
||||||
|
*
|
||||||
|
* Each key on the returned object identifies a network interface. The associated
|
||||||
|
* value is an array of objects that each describe an assigned network address.
|
||||||
|
*
|
||||||
|
* The properties available on the assigned network address object include:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* lo: [
|
||||||
|
* {
|
||||||
|
* address: '127.0.0.1',
|
||||||
|
* netmask: '255.0.0.0',
|
||||||
|
* family: 'IPv4',
|
||||||
|
* mac: '00:00:00:00:00:00',
|
||||||
|
* internal: true,
|
||||||
|
* cidr: '127.0.0.1/8'
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* address: '::1',
|
||||||
|
* netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
|
||||||
|
* family: 'IPv6',
|
||||||
|
* mac: '00:00:00:00:00:00',
|
||||||
|
* scopeid: 0,
|
||||||
|
* internal: true,
|
||||||
|
* cidr: '::1/128'
|
||||||
|
* }
|
||||||
|
* ],
|
||||||
|
* eth0: [
|
||||||
|
* {
|
||||||
|
* address: '192.168.1.108',
|
||||||
|
* netmask: '255.255.255.0',
|
||||||
|
* family: 'IPv4',
|
||||||
|
* mac: '01:02:03:0a:0b:0c',
|
||||||
|
* internal: false,
|
||||||
|
* cidr: '192.168.1.108/24'
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* address: 'fe80::a00:27ff:fe4e:66a1',
|
||||||
|
* netmask: 'ffff:ffff:ffff:ffff::',
|
||||||
|
* family: 'IPv6',
|
||||||
|
* mac: '01:02:03:0a:0b:0c',
|
||||||
|
* scopeid: 1,
|
||||||
|
* internal: false,
|
||||||
|
* cidr: 'fe80::a00:27ff:fe4e:66a1/64'
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.6.0
|
||||||
|
*/
|
||||||
|
function networkInterfaces(): NodeJS.Dict<NetworkInterfaceInfo[]>;
|
||||||
|
/**
|
||||||
|
* Returns the string path of the current user's home directory.
|
||||||
|
*
|
||||||
|
* On POSIX, it uses the `$HOME` environment variable if defined. Otherwise it
|
||||||
|
* uses the [effective UID](https://en.wikipedia.org/wiki/User_identifier#Effective_user_ID) to look up the user's home directory.
|
||||||
|
*
|
||||||
|
* On Windows, it uses the `USERPROFILE` environment variable if defined.
|
||||||
|
* Otherwise it uses the path to the profile directory of the current user.
|
||||||
|
* @since v2.3.0
|
||||||
|
*/
|
||||||
|
function homedir(): string;
|
||||||
|
/**
|
||||||
|
* Returns information about the currently effective user. On POSIX platforms,
|
||||||
|
* this is typically a subset of the password file. The returned object includes
|
||||||
|
* the `username`, `uid`, `gid`, `shell`, and `homedir`. On Windows, the `uid` and `gid` fields are `-1`, and `shell` is `null`.
|
||||||
|
*
|
||||||
|
* The value of `homedir` returned by `os.userInfo()` is provided by the operating
|
||||||
|
* system. This differs from the result of `os.homedir()`, which queries
|
||||||
|
* environment variables for the home directory before falling back to the
|
||||||
|
* operating system response.
|
||||||
|
*
|
||||||
|
* Throws a [`SystemError`](https://nodejs.org/docs/latest-v20.x/api/errors.html#class-systemerror) if a user has no `username` or `homedir`.
|
||||||
|
* @since v6.0.0
|
||||||
|
*/
|
||||||
|
function userInfo(options: { encoding: "buffer" }): UserInfo<Buffer>;
|
||||||
|
function userInfo(options?: { encoding: BufferEncoding }): UserInfo<string>;
|
||||||
|
type SignalConstants = {
|
||||||
|
[key in NodeJS.Signals]: number;
|
||||||
|
};
|
||||||
|
namespace constants {
|
||||||
|
const UV_UDP_REUSEADDR: number;
|
||||||
|
namespace signals {}
|
||||||
|
const signals: SignalConstants;
|
||||||
|
namespace errno {
|
||||||
|
const E2BIG: number;
|
||||||
|
const EACCES: number;
|
||||||
|
const EADDRINUSE: number;
|
||||||
|
const EADDRNOTAVAIL: number;
|
||||||
|
const EAFNOSUPPORT: number;
|
||||||
|
const EAGAIN: number;
|
||||||
|
const EALREADY: number;
|
||||||
|
const EBADF: number;
|
||||||
|
const EBADMSG: number;
|
||||||
|
const EBUSY: number;
|
||||||
|
const ECANCELED: number;
|
||||||
|
const ECHILD: number;
|
||||||
|
const ECONNABORTED: number;
|
||||||
|
const ECONNREFUSED: number;
|
||||||
|
const ECONNRESET: number;
|
||||||
|
const EDEADLK: number;
|
||||||
|
const EDESTADDRREQ: number;
|
||||||
|
const EDOM: number;
|
||||||
|
const EDQUOT: number;
|
||||||
|
const EEXIST: number;
|
||||||
|
const EFAULT: number;
|
||||||
|
const EFBIG: number;
|
||||||
|
const EHOSTUNREACH: number;
|
||||||
|
const EIDRM: number;
|
||||||
|
const EILSEQ: number;
|
||||||
|
const EINPROGRESS: number;
|
||||||
|
const EINTR: number;
|
||||||
|
const EINVAL: number;
|
||||||
|
const EIO: number;
|
||||||
|
const EISCONN: number;
|
||||||
|
const EISDIR: number;
|
||||||
|
const ELOOP: number;
|
||||||
|
const EMFILE: number;
|
||||||
|
const EMLINK: number;
|
||||||
|
const EMSGSIZE: number;
|
||||||
|
const EMULTIHOP: number;
|
||||||
|
const ENAMETOOLONG: number;
|
||||||
|
const ENETDOWN: number;
|
||||||
|
const ENETRESET: number;
|
||||||
|
const ENETUNREACH: number;
|
||||||
|
const ENFILE: number;
|
||||||
|
const ENOBUFS: number;
|
||||||
|
const ENODATA: number;
|
||||||
|
const ENODEV: number;
|
||||||
|
const ENOENT: number;
|
||||||
|
const ENOEXEC: number;
|
||||||
|
const ENOLCK: number;
|
||||||
|
const ENOLINK: number;
|
||||||
|
const ENOMEM: number;
|
||||||
|
const ENOMSG: number;
|
||||||
|
const ENOPROTOOPT: number;
|
||||||
|
const ENOSPC: number;
|
||||||
|
const ENOSR: number;
|
||||||
|
const ENOSTR: number;
|
||||||
|
const ENOSYS: number;
|
||||||
|
const ENOTCONN: number;
|
||||||
|
const ENOTDIR: number;
|
||||||
|
const ENOTEMPTY: number;
|
||||||
|
const ENOTSOCK: number;
|
||||||
|
const ENOTSUP: number;
|
||||||
|
const ENOTTY: number;
|
||||||
|
const ENXIO: number;
|
||||||
|
const EOPNOTSUPP: number;
|
||||||
|
const EOVERFLOW: number;
|
||||||
|
const EPERM: number;
|
||||||
|
const EPIPE: number;
|
||||||
|
const EPROTO: number;
|
||||||
|
const EPROTONOSUPPORT: number;
|
||||||
|
const EPROTOTYPE: number;
|
||||||
|
const ERANGE: number;
|
||||||
|
const EROFS: number;
|
||||||
|
const ESPIPE: number;
|
||||||
|
const ESRCH: number;
|
||||||
|
const ESTALE: number;
|
||||||
|
const ETIME: number;
|
||||||
|
const ETIMEDOUT: number;
|
||||||
|
const ETXTBSY: number;
|
||||||
|
const EWOULDBLOCK: number;
|
||||||
|
const EXDEV: number;
|
||||||
|
const WSAEINTR: number;
|
||||||
|
const WSAEBADF: number;
|
||||||
|
const WSAEACCES: number;
|
||||||
|
const WSAEFAULT: number;
|
||||||
|
const WSAEINVAL: number;
|
||||||
|
const WSAEMFILE: number;
|
||||||
|
const WSAEWOULDBLOCK: number;
|
||||||
|
const WSAEINPROGRESS: number;
|
||||||
|
const WSAEALREADY: number;
|
||||||
|
const WSAENOTSOCK: number;
|
||||||
|
const WSAEDESTADDRREQ: number;
|
||||||
|
const WSAEMSGSIZE: number;
|
||||||
|
const WSAEPROTOTYPE: number;
|
||||||
|
const WSAENOPROTOOPT: number;
|
||||||
|
const WSAEPROTONOSUPPORT: number;
|
||||||
|
const WSAESOCKTNOSUPPORT: number;
|
||||||
|
const WSAEOPNOTSUPP: number;
|
||||||
|
const WSAEPFNOSUPPORT: number;
|
||||||
|
const WSAEAFNOSUPPORT: number;
|
||||||
|
const WSAEADDRINUSE: number;
|
||||||
|
const WSAEADDRNOTAVAIL: number;
|
||||||
|
const WSAENETDOWN: number;
|
||||||
|
const WSAENETUNREACH: number;
|
||||||
|
const WSAENETRESET: number;
|
||||||
|
const WSAECONNABORTED: number;
|
||||||
|
const WSAECONNRESET: number;
|
||||||
|
const WSAENOBUFS: number;
|
||||||
|
const WSAEISCONN: number;
|
||||||
|
const WSAENOTCONN: number;
|
||||||
|
const WSAESHUTDOWN: number;
|
||||||
|
const WSAETOOMANYREFS: number;
|
||||||
|
const WSAETIMEDOUT: number;
|
||||||
|
const WSAECONNREFUSED: number;
|
||||||
|
const WSAELOOP: number;
|
||||||
|
const WSAENAMETOOLONG: number;
|
||||||
|
const WSAEHOSTDOWN: number;
|
||||||
|
const WSAEHOSTUNREACH: number;
|
||||||
|
const WSAENOTEMPTY: number;
|
||||||
|
const WSAEPROCLIM: number;
|
||||||
|
const WSAEUSERS: number;
|
||||||
|
const WSAEDQUOT: number;
|
||||||
|
const WSAESTALE: number;
|
||||||
|
const WSAEREMOTE: number;
|
||||||
|
const WSASYSNOTREADY: number;
|
||||||
|
const WSAVERNOTSUPPORTED: number;
|
||||||
|
const WSANOTINITIALISED: number;
|
||||||
|
const WSAEDISCON: number;
|
||||||
|
const WSAENOMORE: number;
|
||||||
|
const WSAECANCELLED: number;
|
||||||
|
const WSAEINVALIDPROCTABLE: number;
|
||||||
|
const WSAEINVALIDPROVIDER: number;
|
||||||
|
const WSAEPROVIDERFAILEDINIT: number;
|
||||||
|
const WSASYSCALLFAILURE: number;
|
||||||
|
const WSASERVICE_NOT_FOUND: number;
|
||||||
|
const WSATYPE_NOT_FOUND: number;
|
||||||
|
const WSA_E_NO_MORE: number;
|
||||||
|
const WSA_E_CANCELLED: number;
|
||||||
|
const WSAEREFUSED: number;
|
||||||
|
}
|
||||||
|
namespace dlopen {
|
||||||
|
const RTLD_LAZY: number;
|
||||||
|
const RTLD_NOW: number;
|
||||||
|
const RTLD_GLOBAL: number;
|
||||||
|
const RTLD_LOCAL: number;
|
||||||
|
const RTLD_DEEPBIND: number;
|
||||||
|
}
|
||||||
|
namespace priority {
|
||||||
|
const PRIORITY_LOW: number;
|
||||||
|
const PRIORITY_BELOW_NORMAL: number;
|
||||||
|
const PRIORITY_NORMAL: number;
|
||||||
|
const PRIORITY_ABOVE_NORMAL: number;
|
||||||
|
const PRIORITY_HIGH: number;
|
||||||
|
const PRIORITY_HIGHEST: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const devNull: string;
|
||||||
|
/**
|
||||||
|
* The operating system-specific end-of-line marker.
|
||||||
|
* * `\n` on POSIX
|
||||||
|
* * `\r\n` on Windows
|
||||||
|
*/
|
||||||
|
const EOL: string;
|
||||||
|
/**
|
||||||
|
* Returns the operating system CPU architecture for which the Node.js binary was
|
||||||
|
* compiled. Possible values are `'arm'`, `'arm64'`, `'ia32'`, `'loong64'`, `'mips'`, `'mipsel'`, `'ppc'`, `'ppc64'`, `'riscv64'`, `'s390'`, `'s390x'`,
|
||||||
|
* and `'x64'`.
|
||||||
|
*
|
||||||
|
* The return value is equivalent to [process.arch](https://nodejs.org/docs/latest-v20.x/api/process.html#processarch).
|
||||||
|
* @since v0.5.0
|
||||||
|
*/
|
||||||
|
function arch(): string;
|
||||||
|
/**
|
||||||
|
* Returns a string identifying the kernel version.
|
||||||
|
*
|
||||||
|
* On POSIX systems, the operating system release is determined by calling [`uname(3)`](https://linux.die.net/man/3/uname). On Windows, `RtlGetVersion()` is used, and if it is not
|
||||||
|
* available, `GetVersionExW()` will be used. See [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for more information.
|
||||||
|
* @since v13.11.0, v12.17.0
|
||||||
|
*/
|
||||||
|
function version(): string;
|
||||||
|
/**
|
||||||
|
* Returns a string identifying the operating system platform for which
|
||||||
|
* the Node.js binary was compiled. The value is set at compile time.
|
||||||
|
* Possible values are `'aix'`, `'darwin'`, `'freebsd'`, `'linux'`, `'openbsd'`, `'sunos'`, and `'win32'`.
|
||||||
|
*
|
||||||
|
* The return value is equivalent to `process.platform`.
|
||||||
|
*
|
||||||
|
* The value `'android'` may also be returned if Node.js is built on the Android
|
||||||
|
* operating system. [Android support is experimental](https://github.com/nodejs/node/blob/HEAD/BUILDING.md#androidandroid-based-devices-eg-firefox-os).
|
||||||
|
* @since v0.5.0
|
||||||
|
*/
|
||||||
|
function platform(): NodeJS.Platform;
|
||||||
|
/**
|
||||||
|
* Returns the machine type as a string, such as `arm`, `arm64`, `aarch64`, `mips`, `mips64`, `ppc64`, `ppc64le`, `s390`, `s390x`, `i386`, `i686`, `x86_64`.
|
||||||
|
*
|
||||||
|
* On POSIX systems, the machine type is determined by calling [`uname(3)`](https://linux.die.net/man/3/uname). On Windows, `RtlGetVersion()` is used, and if it is not
|
||||||
|
* available, `GetVersionExW()` will be used. See [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for more information.
|
||||||
|
* @since v18.9.0, v16.18.0
|
||||||
|
*/
|
||||||
|
function machine(): string;
|
||||||
|
/**
|
||||||
|
* Returns the operating system's default directory for temporary files as a
|
||||||
|
* string.
|
||||||
|
* @since v0.9.9
|
||||||
|
*/
|
||||||
|
function tmpdir(): string;
|
||||||
|
/**
|
||||||
|
* Returns a string identifying the endianness of the CPU for which the Node.js
|
||||||
|
* binary was compiled.
|
||||||
|
*
|
||||||
|
* Possible values are `'BE'` for big endian and `'LE'` for little endian.
|
||||||
|
* @since v0.9.4
|
||||||
|
*/
|
||||||
|
function endianness(): "BE" | "LE";
|
||||||
|
/**
|
||||||
|
* Returns the scheduling priority for the process specified by `pid`. If `pid` is
|
||||||
|
* not provided or is `0`, the priority of the current process is returned.
|
||||||
|
* @since v10.10.0
|
||||||
|
* @param [pid=0] The process ID to retrieve scheduling priority for.
|
||||||
|
*/
|
||||||
|
function getPriority(pid?: number): number;
|
||||||
|
/**
|
||||||
|
* Attempts to set the scheduling priority for the process specified by `pid`. If `pid` is not provided or is `0`, the process ID of the current process is used.
|
||||||
|
*
|
||||||
|
* The `priority` input must be an integer between `-20` (high priority) and `19` (low priority). Due to differences between Unix priority levels and Windows
|
||||||
|
* priority classes, `priority` is mapped to one of six priority constants in `os.constants.priority`. When retrieving a process priority level, this range
|
||||||
|
* mapping may cause the return value to be slightly different on Windows. To avoid
|
||||||
|
* confusion, set `priority` to one of the priority constants.
|
||||||
|
*
|
||||||
|
* On Windows, setting priority to `PRIORITY_HIGHEST` requires elevated user
|
||||||
|
* privileges. Otherwise the set priority will be silently reduced to `PRIORITY_HIGH`.
|
||||||
|
* @since v10.10.0
|
||||||
|
* @param [pid=0] The process ID to set scheduling priority for.
|
||||||
|
* @param priority The scheduling priority to assign to the process.
|
||||||
|
*/
|
||||||
|
function setPriority(priority: number): void;
|
||||||
|
function setPriority(pid: number, priority: number): void;
|
||||||
|
}
|
||||||
|
declare module "node:os" {
|
||||||
|
export * from "os";
|
||||||
|
}
|
||||||
140
node_modules/@types/node/package.json
generated
vendored
Normal file
140
node_modules/@types/node/package.json
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/node",
|
||||||
|
"version": "20.19.20",
|
||||||
|
"description": "TypeScript definitions for node",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "Microsoft TypeScript",
|
||||||
|
"githubUsername": "Microsoft",
|
||||||
|
"url": "https://github.com/Microsoft"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Alberto Schiabel",
|
||||||
|
"githubUsername": "jkomyno",
|
||||||
|
"url": "https://github.com/jkomyno"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Andrew Makarov",
|
||||||
|
"githubUsername": "r3nya",
|
||||||
|
"url": "https://github.com/r3nya"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Benjamin Toueg",
|
||||||
|
"githubUsername": "btoueg",
|
||||||
|
"url": "https://github.com/btoueg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "David Junger",
|
||||||
|
"githubUsername": "touffy",
|
||||||
|
"url": "https://github.com/touffy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mohsen Azimi",
|
||||||
|
"githubUsername": "mohsen1",
|
||||||
|
"url": "https://github.com/mohsen1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nikita Galkin",
|
||||||
|
"githubUsername": "galkin",
|
||||||
|
"url": "https://github.com/galkin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sebastian Silbermann",
|
||||||
|
"githubUsername": "eps1lon",
|
||||||
|
"url": "https://github.com/eps1lon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Wilco Bakker",
|
||||||
|
"githubUsername": "WilcoBakker",
|
||||||
|
"url": "https://github.com/WilcoBakker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Marcin Kopacz",
|
||||||
|
"githubUsername": "chyzwar",
|
||||||
|
"url": "https://github.com/chyzwar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Trivikram Kamat",
|
||||||
|
"githubUsername": "trivikr",
|
||||||
|
"url": "https://github.com/trivikr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Junxiao Shi",
|
||||||
|
"githubUsername": "yoursunny",
|
||||||
|
"url": "https://github.com/yoursunny"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ilia Baryshnikov",
|
||||||
|
"githubUsername": "qwelias",
|
||||||
|
"url": "https://github.com/qwelias"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ExE Boss",
|
||||||
|
"githubUsername": "ExE-Boss",
|
||||||
|
"url": "https://github.com/ExE-Boss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Piotr Błażejewicz",
|
||||||
|
"githubUsername": "peterblazejewicz",
|
||||||
|
"url": "https://github.com/peterblazejewicz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Anna Henningsen",
|
||||||
|
"githubUsername": "addaleax",
|
||||||
|
"url": "https://github.com/addaleax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Victor Perin",
|
||||||
|
"githubUsername": "victorperin",
|
||||||
|
"url": "https://github.com/victorperin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NodeJS Contributors",
|
||||||
|
"githubUsername": "NodeJS",
|
||||||
|
"url": "https://github.com/NodeJS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Linus Unnebäck",
|
||||||
|
"githubUsername": "LinusU",
|
||||||
|
"url": "https://github.com/LinusU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wafuwafu13",
|
||||||
|
"githubUsername": "wafuwafu13",
|
||||||
|
"url": "https://github.com/wafuwafu13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Matteo Collina",
|
||||||
|
"githubUsername": "mcollina",
|
||||||
|
"url": "https://github.com/mcollina"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dmitry Semigradsky",
|
||||||
|
"githubUsername": "Semigradsky",
|
||||||
|
"url": "https://github.com/Semigradsky"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"typesVersions": {
|
||||||
|
"<=5.6": {
|
||||||
|
"*": [
|
||||||
|
"ts5.6/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/node"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~6.21.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {},
|
||||||
|
"typesPublisherContentHash": "e13807fd03d5145af88d2878aee5d370ed9f2a8ec17fd595c07841a1c49ce46d",
|
||||||
|
"typeScriptVersion": "5.2"
|
||||||
|
}
|
||||||
200
node_modules/@types/node/path.d.ts
generated
vendored
Normal file
200
node_modules/@types/node/path.d.ts
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
declare module "path/posix" {
|
||||||
|
import path = require("path");
|
||||||
|
export = path;
|
||||||
|
}
|
||||||
|
declare module "path/win32" {
|
||||||
|
import path = require("path");
|
||||||
|
export = path;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `node:path` module provides utilities for working with file and directory
|
||||||
|
* paths. It can be accessed using:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import path from 'node:path';
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/path.js)
|
||||||
|
*/
|
||||||
|
declare module "path" {
|
||||||
|
namespace path {
|
||||||
|
/**
|
||||||
|
* A parsed path object generated by path.parse() or consumed by path.format().
|
||||||
|
*/
|
||||||
|
interface ParsedPath {
|
||||||
|
/**
|
||||||
|
* The root of the path such as '/' or 'c:\'
|
||||||
|
*/
|
||||||
|
root: string;
|
||||||
|
/**
|
||||||
|
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
|
||||||
|
*/
|
||||||
|
dir: string;
|
||||||
|
/**
|
||||||
|
* The file name including extension (if any) such as 'index.html'
|
||||||
|
*/
|
||||||
|
base: string;
|
||||||
|
/**
|
||||||
|
* The file extension (if any) such as '.html'
|
||||||
|
*/
|
||||||
|
ext: string;
|
||||||
|
/**
|
||||||
|
* The file name without extension (if any) such as 'index'
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
interface FormatInputPathObject {
|
||||||
|
/**
|
||||||
|
* The root of the path such as '/' or 'c:\'
|
||||||
|
*/
|
||||||
|
root?: string | undefined;
|
||||||
|
/**
|
||||||
|
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
|
||||||
|
*/
|
||||||
|
dir?: string | undefined;
|
||||||
|
/**
|
||||||
|
* The file name including extension (if any) such as 'index.html'
|
||||||
|
*/
|
||||||
|
base?: string | undefined;
|
||||||
|
/**
|
||||||
|
* The file extension (if any) such as '.html'
|
||||||
|
*/
|
||||||
|
ext?: string | undefined;
|
||||||
|
/**
|
||||||
|
* The file name without extension (if any) such as 'index'
|
||||||
|
*/
|
||||||
|
name?: string | undefined;
|
||||||
|
}
|
||||||
|
interface PlatformPath {
|
||||||
|
/**
|
||||||
|
* Normalize a string path, reducing '..' and '.' parts.
|
||||||
|
* When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used.
|
||||||
|
*
|
||||||
|
* @param path string path to normalize.
|
||||||
|
* @throws {TypeError} if `path` is not a string.
|
||||||
|
*/
|
||||||
|
normalize(path: string): string;
|
||||||
|
/**
|
||||||
|
* Join all arguments together and normalize the resulting path.
|
||||||
|
*
|
||||||
|
* @param paths paths to join.
|
||||||
|
* @throws {TypeError} if any of the path segments is not a string.
|
||||||
|
*/
|
||||||
|
join(...paths: string[]): string;
|
||||||
|
/**
|
||||||
|
* The right-most parameter is considered {to}. Other parameters are considered an array of {from}.
|
||||||
|
*
|
||||||
|
* Starting from leftmost {from} parameter, resolves {to} to an absolute path.
|
||||||
|
*
|
||||||
|
* If {to} isn't already absolute, {from} arguments are prepended in right to left order,
|
||||||
|
* until an absolute path is found. If after using all {from} paths still no absolute path is found,
|
||||||
|
* the current working directory is used as well. The resulting path is normalized,
|
||||||
|
* and trailing slashes are removed unless the path gets resolved to the root directory.
|
||||||
|
*
|
||||||
|
* @param paths A sequence of paths or path segments.
|
||||||
|
* @throws {TypeError} if any of the arguments is not a string.
|
||||||
|
*/
|
||||||
|
resolve(...paths: string[]): string;
|
||||||
|
/**
|
||||||
|
* The `path.matchesGlob()` method determines if `path` matches the `pattern`.
|
||||||
|
* @param path The path to glob-match against.
|
||||||
|
* @param pattern The glob to check the path against.
|
||||||
|
* @returns Whether or not the `path` matched the `pattern`.
|
||||||
|
* @throws {TypeError} if `path` or `pattern` are not strings.
|
||||||
|
* @since v20.17.0
|
||||||
|
*/
|
||||||
|
matchesGlob(path: string, pattern: string): boolean;
|
||||||
|
/**
|
||||||
|
* Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory.
|
||||||
|
*
|
||||||
|
* If the given {path} is a zero-length string, `false` will be returned.
|
||||||
|
*
|
||||||
|
* @param path path to test.
|
||||||
|
* @throws {TypeError} if `path` is not a string.
|
||||||
|
*/
|
||||||
|
isAbsolute(path: string): boolean;
|
||||||
|
/**
|
||||||
|
* Solve the relative path from {from} to {to} based on the current working directory.
|
||||||
|
* At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve.
|
||||||
|
*
|
||||||
|
* @throws {TypeError} if either `from` or `to` is not a string.
|
||||||
|
*/
|
||||||
|
relative(from: string, to: string): string;
|
||||||
|
/**
|
||||||
|
* Return the directory name of a path. Similar to the Unix dirname command.
|
||||||
|
*
|
||||||
|
* @param path the path to evaluate.
|
||||||
|
* @throws {TypeError} if `path` is not a string.
|
||||||
|
*/
|
||||||
|
dirname(path: string): string;
|
||||||
|
/**
|
||||||
|
* Return the last portion of a path. Similar to the Unix basename command.
|
||||||
|
* Often used to extract the file name from a fully qualified path.
|
||||||
|
*
|
||||||
|
* @param path the path to evaluate.
|
||||||
|
* @param suffix optionally, an extension to remove from the result.
|
||||||
|
* @throws {TypeError} if `path` is not a string or if `ext` is given and is not a string.
|
||||||
|
*/
|
||||||
|
basename(path: string, suffix?: string): string;
|
||||||
|
/**
|
||||||
|
* Return the extension of the path, from the last '.' to end of string in the last portion of the path.
|
||||||
|
* If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string.
|
||||||
|
*
|
||||||
|
* @param path the path to evaluate.
|
||||||
|
* @throws {TypeError} if `path` is not a string.
|
||||||
|
*/
|
||||||
|
extname(path: string): string;
|
||||||
|
/**
|
||||||
|
* The platform-specific file separator. '\\' or '/'.
|
||||||
|
*/
|
||||||
|
readonly sep: "\\" | "/";
|
||||||
|
/**
|
||||||
|
* The platform-specific file delimiter. ';' or ':'.
|
||||||
|
*/
|
||||||
|
readonly delimiter: ";" | ":";
|
||||||
|
/**
|
||||||
|
* Returns an object from a path string - the opposite of format().
|
||||||
|
*
|
||||||
|
* @param path path to evaluate.
|
||||||
|
* @throws {TypeError} if `path` is not a string.
|
||||||
|
*/
|
||||||
|
parse(path: string): ParsedPath;
|
||||||
|
/**
|
||||||
|
* Returns a path string from an object - the opposite of parse().
|
||||||
|
*
|
||||||
|
* @param pathObject path to evaluate.
|
||||||
|
*/
|
||||||
|
format(pathObject: FormatInputPathObject): string;
|
||||||
|
/**
|
||||||
|
* On Windows systems only, returns an equivalent namespace-prefixed path for the given path.
|
||||||
|
* If path is not a string, path will be returned without modifications.
|
||||||
|
* This method is meaningful only on Windows system.
|
||||||
|
* On POSIX systems, the method is non-operational and always returns path without modifications.
|
||||||
|
*/
|
||||||
|
toNamespacedPath(path: string): string;
|
||||||
|
/**
|
||||||
|
* Posix specific pathing.
|
||||||
|
* Same as parent object on posix.
|
||||||
|
*/
|
||||||
|
readonly posix: PlatformPath;
|
||||||
|
/**
|
||||||
|
* Windows specific pathing.
|
||||||
|
* Same as parent object on windows
|
||||||
|
*/
|
||||||
|
readonly win32: PlatformPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const path: path.PlatformPath;
|
||||||
|
export = path;
|
||||||
|
}
|
||||||
|
declare module "node:path" {
|
||||||
|
import path = require("path");
|
||||||
|
export = path;
|
||||||
|
}
|
||||||
|
declare module "node:path/posix" {
|
||||||
|
import path = require("path/posix");
|
||||||
|
export = path;
|
||||||
|
}
|
||||||
|
declare module "node:path/win32" {
|
||||||
|
import path = require("path/win32");
|
||||||
|
export = path;
|
||||||
|
}
|
||||||
963
node_modules/@types/node/perf_hooks.d.ts
generated
vendored
Normal file
963
node_modules/@types/node/perf_hooks.d.ts
generated
vendored
Normal file
@@ -0,0 +1,963 @@
|
|||||||
|
/**
|
||||||
|
* This module provides an implementation of a subset of the W3C [Web Performance APIs](https://w3c.github.io/perf-timing-primer/) as well as additional APIs for
|
||||||
|
* Node.js-specific performance measurements.
|
||||||
|
*
|
||||||
|
* Node.js supports the following [Web Performance APIs](https://w3c.github.io/perf-timing-primer/):
|
||||||
|
*
|
||||||
|
* * [High Resolution Time](https://www.w3.org/TR/hr-time-2)
|
||||||
|
* * [Performance Timeline](https://w3c.github.io/performance-timeline/)
|
||||||
|
* * [User Timing](https://www.w3.org/TR/user-timing/)
|
||||||
|
* * [Resource Timing](https://www.w3.org/TR/resource-timing-2/)
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { PerformanceObserver, performance } from 'node:perf_hooks';
|
||||||
|
*
|
||||||
|
* const obs = new PerformanceObserver((items) => {
|
||||||
|
* console.log(items.getEntries()[0].duration);
|
||||||
|
* performance.clearMarks();
|
||||||
|
* });
|
||||||
|
* obs.observe({ type: 'measure' });
|
||||||
|
* performance.measure('Start to Now');
|
||||||
|
*
|
||||||
|
* performance.mark('A');
|
||||||
|
* doSomeLongRunningProcess(() => {
|
||||||
|
* performance.measure('A to Now', 'A');
|
||||||
|
*
|
||||||
|
* performance.mark('B');
|
||||||
|
* performance.measure('A to B', 'A', 'B');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/perf_hooks.js)
|
||||||
|
*/
|
||||||
|
declare module "perf_hooks" {
|
||||||
|
import { AsyncResource } from "node:async_hooks";
|
||||||
|
type EntryType =
|
||||||
|
| "dns" // Node.js only
|
||||||
|
| "function" // Node.js only
|
||||||
|
| "gc" // Node.js only
|
||||||
|
| "http2" // Node.js only
|
||||||
|
| "http" // Node.js only
|
||||||
|
| "mark" // available on the Web
|
||||||
|
| "measure" // available on the Web
|
||||||
|
| "net" // Node.js only
|
||||||
|
| "node" // Node.js only
|
||||||
|
| "resource"; // available on the Web
|
||||||
|
interface NodeGCPerformanceDetail {
|
||||||
|
/**
|
||||||
|
* When `performanceEntry.entryType` is equal to 'gc', the `performance.kind` property identifies
|
||||||
|
* the type of garbage collection operation that occurred.
|
||||||
|
* See perf_hooks.constants for valid values.
|
||||||
|
*/
|
||||||
|
readonly kind?: number | undefined;
|
||||||
|
/**
|
||||||
|
* When `performanceEntry.entryType` is equal to 'gc', the `performance.flags`
|
||||||
|
* property contains additional information about garbage collection operation.
|
||||||
|
* See perf_hooks.constants for valid values.
|
||||||
|
*/
|
||||||
|
readonly flags?: number | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The constructor of this class is not exposed to users directly.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
class PerformanceEntry {
|
||||||
|
protected constructor();
|
||||||
|
/**
|
||||||
|
* The total number of milliseconds elapsed for this entry. This value will not
|
||||||
|
* be meaningful for all Performance Entry types.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly duration: number;
|
||||||
|
/**
|
||||||
|
* The name of the performance entry.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly name: string;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp marking the starting time of the
|
||||||
|
* Performance Entry.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly startTime: number;
|
||||||
|
/**
|
||||||
|
* The type of the performance entry. It may be one of:
|
||||||
|
*
|
||||||
|
* * `'node'` (Node.js only)
|
||||||
|
* * `'mark'` (available on the Web)
|
||||||
|
* * `'measure'` (available on the Web)
|
||||||
|
* * `'gc'` (Node.js only)
|
||||||
|
* * `'function'` (Node.js only)
|
||||||
|
* * `'http2'` (Node.js only)
|
||||||
|
* * `'http'` (Node.js only)
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly entryType: EntryType;
|
||||||
|
/**
|
||||||
|
* Additional detail specific to the `entryType`.
|
||||||
|
* @since v16.0.0
|
||||||
|
*/
|
||||||
|
readonly detail?: NodeGCPerformanceDetail | unknown | undefined; // TODO: Narrow this based on entry type.
|
||||||
|
toJSON(): any;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Exposes marks created via the `Performance.mark()` method.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
class PerformanceMark extends PerformanceEntry {
|
||||||
|
readonly duration: 0;
|
||||||
|
readonly entryType: "mark";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Exposes measures created via the `Performance.measure()` method.
|
||||||
|
*
|
||||||
|
* The constructor of this class is not exposed to users directly.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
class PerformanceMeasure extends PerformanceEntry {
|
||||||
|
readonly entryType: "measure";
|
||||||
|
}
|
||||||
|
interface UVMetrics {
|
||||||
|
/**
|
||||||
|
* Number of event loop iterations.
|
||||||
|
*/
|
||||||
|
readonly loopCount: number;
|
||||||
|
/**
|
||||||
|
* Number of events that have been processed by the event handler.
|
||||||
|
*/
|
||||||
|
readonly events: number;
|
||||||
|
/**
|
||||||
|
* Number of events that were waiting to be processed when the event provider was called.
|
||||||
|
*/
|
||||||
|
readonly eventsWaiting: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* _This property is an extension by Node.js. It is not available in Web browsers._
|
||||||
|
*
|
||||||
|
* Provides timing details for Node.js itself. The constructor of this class
|
||||||
|
* is not exposed to users.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
class PerformanceNodeTiming extends PerformanceEntry {
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp at which the Node.js process
|
||||||
|
* completed bootstrapping. If bootstrapping has not yet finished, the property
|
||||||
|
* has the value of -1.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly bootstrapComplete: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp at which the Node.js environment was
|
||||||
|
* initialized.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly environment: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp of the amount of time the event loop
|
||||||
|
* has been idle within the event loop's event provider (e.g. `epoll_wait`). This
|
||||||
|
* does not take CPU usage into consideration. If the event loop has not yet
|
||||||
|
* started (e.g., in the first tick of the main script), the property has the
|
||||||
|
* value of 0.
|
||||||
|
* @since v14.10.0, v12.19.0
|
||||||
|
*/
|
||||||
|
readonly idleTime: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp at which the Node.js event loop
|
||||||
|
* exited. If the event loop has not yet exited, the property has the value of -1\.
|
||||||
|
* It can only have a value of not -1 in a handler of the `'exit'` event.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly loopExit: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp at which the Node.js event loop
|
||||||
|
* started. If the event loop has not yet started (e.g., in the first tick of the
|
||||||
|
* main script), the property has the value of -1.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly loopStart: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp at which the Node.js process was initialized.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly nodeStart: number;
|
||||||
|
/**
|
||||||
|
* This is a wrapper to the `uv_metrics_info` function.
|
||||||
|
* It returns the current set of event loop metrics.
|
||||||
|
*
|
||||||
|
* It is recommended to use this property inside a function whose execution was
|
||||||
|
* scheduled using `setImmediate` to avoid collecting metrics before finishing all
|
||||||
|
* operations scheduled during the current loop iteration.
|
||||||
|
* @since v20.18.0
|
||||||
|
*/
|
||||||
|
readonly uvMetricsInfo: UVMetrics;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp at which the V8 platform was
|
||||||
|
* initialized.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly v8Start: number;
|
||||||
|
}
|
||||||
|
interface EventLoopUtilization {
|
||||||
|
idle: number;
|
||||||
|
active: number;
|
||||||
|
utilization: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param utilization1 The result of a previous call to `eventLoopUtilization()`.
|
||||||
|
* @param utilization2 The result of a previous call to `eventLoopUtilization()` prior to `utilization1`.
|
||||||
|
*/
|
||||||
|
type EventLoopUtilityFunction = (
|
||||||
|
utilization1?: EventLoopUtilization,
|
||||||
|
utilization2?: EventLoopUtilization,
|
||||||
|
) => EventLoopUtilization;
|
||||||
|
interface MarkOptions {
|
||||||
|
/**
|
||||||
|
* Additional optional detail to include with the mark.
|
||||||
|
*/
|
||||||
|
detail?: unknown | undefined;
|
||||||
|
/**
|
||||||
|
* An optional timestamp to be used as the mark time.
|
||||||
|
* @default `performance.now()`
|
||||||
|
*/
|
||||||
|
startTime?: number | undefined;
|
||||||
|
}
|
||||||
|
interface MeasureOptions {
|
||||||
|
/**
|
||||||
|
* Additional optional detail to include with the mark.
|
||||||
|
*/
|
||||||
|
detail?: unknown | undefined;
|
||||||
|
/**
|
||||||
|
* Duration between start and end times.
|
||||||
|
*/
|
||||||
|
duration?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Timestamp to be used as the end time, or a string identifying a previously recorded mark.
|
||||||
|
*/
|
||||||
|
end?: number | string | undefined;
|
||||||
|
/**
|
||||||
|
* Timestamp to be used as the start time, or a string identifying a previously recorded mark.
|
||||||
|
*/
|
||||||
|
start?: number | string | undefined;
|
||||||
|
}
|
||||||
|
interface TimerifyOptions {
|
||||||
|
/**
|
||||||
|
* A histogram object created using `perf_hooks.createHistogram()` that will record runtime
|
||||||
|
* durations in nanoseconds.
|
||||||
|
*/
|
||||||
|
histogram?: RecordableHistogram | undefined;
|
||||||
|
}
|
||||||
|
interface Performance {
|
||||||
|
/**
|
||||||
|
* If `name` is not provided, removes all `PerformanceMark` objects from the Performance Timeline.
|
||||||
|
* If `name` is provided, removes only the named mark.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
clearMarks(name?: string): void;
|
||||||
|
/**
|
||||||
|
* If `name` is not provided, removes all `PerformanceMeasure` objects from the Performance Timeline.
|
||||||
|
* If `name` is provided, removes only the named measure.
|
||||||
|
* @since v16.7.0
|
||||||
|
*/
|
||||||
|
clearMeasures(name?: string): void;
|
||||||
|
/**
|
||||||
|
* If `name` is not provided, removes all `PerformanceResourceTiming` objects from the Resource Timeline.
|
||||||
|
* If `name` is provided, removes only the named resource.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
clearResourceTimings(name?: string): void;
|
||||||
|
/**
|
||||||
|
* eventLoopUtilization is similar to CPU utilization except that it is calculated using high precision wall-clock time.
|
||||||
|
* It represents the percentage of time the event loop has spent outside the event loop's event provider (e.g. epoll_wait).
|
||||||
|
* No other CPU idle time is taken into consideration.
|
||||||
|
*/
|
||||||
|
eventLoopUtilization: EventLoopUtilityFunction;
|
||||||
|
/**
|
||||||
|
* Returns a list of `PerformanceEntry` objects in chronological order with respect to `performanceEntry.startTime`.
|
||||||
|
* If you are only interested in performance entries of certain types or that have certain names, see
|
||||||
|
* `performance.getEntriesByType()` and `performance.getEntriesByName()`.
|
||||||
|
* @since v16.7.0
|
||||||
|
*/
|
||||||
|
getEntries(): PerformanceEntry[];
|
||||||
|
/**
|
||||||
|
* Returns a list of `PerformanceEntry` objects in chronological order with respect to `performanceEntry.startTime`
|
||||||
|
* whose `performanceEntry.name` is equal to `name`, and optionally, whose `performanceEntry.entryType` is equal to `type`.
|
||||||
|
* @param name
|
||||||
|
* @param type
|
||||||
|
* @since v16.7.0
|
||||||
|
*/
|
||||||
|
getEntriesByName(name: string, type?: EntryType): PerformanceEntry[];
|
||||||
|
/**
|
||||||
|
* Returns a list of `PerformanceEntry` objects in chronological order with respect to `performanceEntry.startTime`
|
||||||
|
* whose `performanceEntry.entryType` is equal to `type`.
|
||||||
|
* @param type
|
||||||
|
* @since v16.7.0
|
||||||
|
*/
|
||||||
|
getEntriesByType(type: EntryType): PerformanceEntry[];
|
||||||
|
/**
|
||||||
|
* Creates a new `PerformanceMark` entry in the Performance Timeline.
|
||||||
|
* A `PerformanceMark` is a subclass of `PerformanceEntry` whose `performanceEntry.entryType` is always `'mark'`,
|
||||||
|
* and whose `performanceEntry.duration` is always `0`.
|
||||||
|
* Performance marks are used to mark specific significant moments in the Performance Timeline.
|
||||||
|
*
|
||||||
|
* The created `PerformanceMark` entry is put in the global Performance Timeline and can be queried with
|
||||||
|
* `performance.getEntries`, `performance.getEntriesByName`, and `performance.getEntriesByType`. When the observation is
|
||||||
|
* performed, the entries should be cleared from the global Performance Timeline manually with `performance.clearMarks`.
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
mark(name: string, options?: MarkOptions): PerformanceMark;
|
||||||
|
/**
|
||||||
|
* Creates a new `PerformanceResourceTiming` entry in the Resource Timeline.
|
||||||
|
* A `PerformanceResourceTiming` is a subclass of `PerformanceEntry` whose `performanceEntry.entryType` is always `'resource'`.
|
||||||
|
* Performance resources are used to mark moments in the Resource Timeline.
|
||||||
|
* @param timingInfo [Fetch Timing Info](https://fetch.spec.whatwg.org/#fetch-timing-info)
|
||||||
|
* @param requestedUrl The resource url
|
||||||
|
* @param initiatorType The initiator name, e.g: 'fetch'
|
||||||
|
* @param global
|
||||||
|
* @param cacheMode The cache mode must be an empty string ('') or 'local'
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
markResourceTiming(
|
||||||
|
timingInfo: object,
|
||||||
|
requestedUrl: string,
|
||||||
|
initiatorType: string,
|
||||||
|
global: object,
|
||||||
|
cacheMode: "" | "local",
|
||||||
|
): PerformanceResourceTiming;
|
||||||
|
/**
|
||||||
|
* Creates a new PerformanceMeasure entry in the Performance Timeline.
|
||||||
|
* A PerformanceMeasure is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'measure',
|
||||||
|
* and whose performanceEntry.duration measures the number of milliseconds elapsed since startMark and endMark.
|
||||||
|
*
|
||||||
|
* The startMark argument may identify any existing PerformanceMark in the the Performance Timeline, or may identify
|
||||||
|
* any of the timestamp properties provided by the PerformanceNodeTiming class. If the named startMark does not exist,
|
||||||
|
* then startMark is set to timeOrigin by default.
|
||||||
|
*
|
||||||
|
* The endMark argument must identify any existing PerformanceMark in the the Performance Timeline or any of the timestamp
|
||||||
|
* properties provided by the PerformanceNodeTiming class. If the named endMark does not exist, an error will be thrown.
|
||||||
|
* @param name
|
||||||
|
* @param startMark
|
||||||
|
* @param endMark
|
||||||
|
* @return The PerformanceMeasure entry that was created
|
||||||
|
*/
|
||||||
|
measure(name: string, startMark?: string, endMark?: string): PerformanceMeasure;
|
||||||
|
measure(name: string, options: MeasureOptions): PerformanceMeasure;
|
||||||
|
/**
|
||||||
|
* _This property is an extension by Node.js. It is not available in Web browsers._
|
||||||
|
*
|
||||||
|
* An instance of the `PerformanceNodeTiming` class that provides performance metrics for specific Node.js operational milestones.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly nodeTiming: PerformanceNodeTiming;
|
||||||
|
/**
|
||||||
|
* Returns the current high resolution millisecond timestamp, where 0 represents the start of the current `node` process.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
now(): number;
|
||||||
|
/**
|
||||||
|
* Sets the global performance resource timing buffer size to the specified number of "resource" type performance entry objects.
|
||||||
|
*
|
||||||
|
* By default the max buffer size is set to 250.
|
||||||
|
* @since v18.8.0
|
||||||
|
*/
|
||||||
|
setResourceTimingBufferSize(maxSize: number): void;
|
||||||
|
/**
|
||||||
|
* The [`timeOrigin`](https://w3c.github.io/hr-time/#dom-performance-timeorigin) specifies the high resolution millisecond timestamp
|
||||||
|
* at which the current `node` process began, measured in Unix time.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
readonly timeOrigin: number;
|
||||||
|
/**
|
||||||
|
* _This property is an extension by Node.js. It is not available in Web browsers._
|
||||||
|
*
|
||||||
|
* Wraps a function within a new function that measures the running time of the wrapped function.
|
||||||
|
* A `PerformanceObserver` must be subscribed to the `'function'` event type in order for the timing details to be accessed.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import {
|
||||||
|
* performance,
|
||||||
|
* PerformanceObserver,
|
||||||
|
* } from 'node:perf_hooks';
|
||||||
|
*
|
||||||
|
* function someFunction() {
|
||||||
|
* console.log('hello world');
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const wrapped = performance.timerify(someFunction);
|
||||||
|
*
|
||||||
|
* const obs = new PerformanceObserver((list) => {
|
||||||
|
* console.log(list.getEntries()[0].duration);
|
||||||
|
*
|
||||||
|
* performance.clearMarks();
|
||||||
|
* performance.clearMeasures();
|
||||||
|
* obs.disconnect();
|
||||||
|
* });
|
||||||
|
* obs.observe({ entryTypes: ['function'] });
|
||||||
|
*
|
||||||
|
* // A performance timeline entry will be created
|
||||||
|
* wrapped();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If the wrapped function returns a promise, a finally handler will be attached to the promise and the duration will be reported
|
||||||
|
* once the finally handler is invoked.
|
||||||
|
* @param fn
|
||||||
|
*/
|
||||||
|
timerify<T extends (...params: any[]) => any>(fn: T, options?: TimerifyOptions): T;
|
||||||
|
/**
|
||||||
|
* An object which is JSON representation of the performance object. It is similar to
|
||||||
|
* [`window.performance.toJSON`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/toJSON) in browsers.
|
||||||
|
* @since v16.1.0
|
||||||
|
*/
|
||||||
|
toJSON(): any;
|
||||||
|
}
|
||||||
|
class PerformanceObserverEntryList {
|
||||||
|
/**
|
||||||
|
* Returns a list of `PerformanceEntry` objects in chronological order
|
||||||
|
* with respect to `performanceEntry.startTime`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import {
|
||||||
|
* performance,
|
||||||
|
* PerformanceObserver,
|
||||||
|
* } from 'node:perf_hooks';
|
||||||
|
*
|
||||||
|
* const obs = new PerformanceObserver((perfObserverList, observer) => {
|
||||||
|
* console.log(perfObserverList.getEntries());
|
||||||
|
*
|
||||||
|
* * [
|
||||||
|
* * PerformanceEntry {
|
||||||
|
* * name: 'test',
|
||||||
|
* * entryType: 'mark',
|
||||||
|
* * startTime: 81.465639,
|
||||||
|
* * duration: 0,
|
||||||
|
* * detail: null
|
||||||
|
* * },
|
||||||
|
* * PerformanceEntry {
|
||||||
|
* * name: 'meow',
|
||||||
|
* * entryType: 'mark',
|
||||||
|
* * startTime: 81.860064,
|
||||||
|
* * duration: 0,
|
||||||
|
* * detail: null
|
||||||
|
* * }
|
||||||
|
* * ]
|
||||||
|
*
|
||||||
|
* performance.clearMarks();
|
||||||
|
* performance.clearMeasures();
|
||||||
|
* observer.disconnect();
|
||||||
|
* });
|
||||||
|
* obs.observe({ type: 'mark' });
|
||||||
|
*
|
||||||
|
* performance.mark('test');
|
||||||
|
* performance.mark('meow');
|
||||||
|
* ```
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
getEntries(): PerformanceEntry[];
|
||||||
|
/**
|
||||||
|
* Returns a list of `PerformanceEntry` objects in chronological order
|
||||||
|
* with respect to `performanceEntry.startTime` whose `performanceEntry.name` is
|
||||||
|
* equal to `name`, and optionally, whose `performanceEntry.entryType` is equal to`type`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import {
|
||||||
|
* performance,
|
||||||
|
* PerformanceObserver,
|
||||||
|
* } from 'node:perf_hooks';
|
||||||
|
*
|
||||||
|
* const obs = new PerformanceObserver((perfObserverList, observer) => {
|
||||||
|
* console.log(perfObserverList.getEntriesByName('meow'));
|
||||||
|
*
|
||||||
|
* * [
|
||||||
|
* * PerformanceEntry {
|
||||||
|
* * name: 'meow',
|
||||||
|
* * entryType: 'mark',
|
||||||
|
* * startTime: 98.545991,
|
||||||
|
* * duration: 0,
|
||||||
|
* * detail: null
|
||||||
|
* * }
|
||||||
|
* * ]
|
||||||
|
*
|
||||||
|
* console.log(perfObserverList.getEntriesByName('nope')); // []
|
||||||
|
*
|
||||||
|
* console.log(perfObserverList.getEntriesByName('test', 'mark'));
|
||||||
|
*
|
||||||
|
* * [
|
||||||
|
* * PerformanceEntry {
|
||||||
|
* * name: 'test',
|
||||||
|
* * entryType: 'mark',
|
||||||
|
* * startTime: 63.518931,
|
||||||
|
* * duration: 0,
|
||||||
|
* * detail: null
|
||||||
|
* * }
|
||||||
|
* * ]
|
||||||
|
*
|
||||||
|
* console.log(perfObserverList.getEntriesByName('test', 'measure')); // []
|
||||||
|
*
|
||||||
|
* performance.clearMarks();
|
||||||
|
* performance.clearMeasures();
|
||||||
|
* observer.disconnect();
|
||||||
|
* });
|
||||||
|
* obs.observe({ entryTypes: ['mark', 'measure'] });
|
||||||
|
*
|
||||||
|
* performance.mark('test');
|
||||||
|
* performance.mark('meow');
|
||||||
|
* ```
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
getEntriesByName(name: string, type?: EntryType): PerformanceEntry[];
|
||||||
|
/**
|
||||||
|
* Returns a list of `PerformanceEntry` objects in chronological order
|
||||||
|
* with respect to `performanceEntry.startTime` whose `performanceEntry.entryType` is equal to `type`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import {
|
||||||
|
* performance,
|
||||||
|
* PerformanceObserver,
|
||||||
|
* } from 'node:perf_hooks';
|
||||||
|
*
|
||||||
|
* const obs = new PerformanceObserver((perfObserverList, observer) => {
|
||||||
|
* console.log(perfObserverList.getEntriesByType('mark'));
|
||||||
|
*
|
||||||
|
* * [
|
||||||
|
* * PerformanceEntry {
|
||||||
|
* * name: 'test',
|
||||||
|
* * entryType: 'mark',
|
||||||
|
* * startTime: 55.897834,
|
||||||
|
* * duration: 0,
|
||||||
|
* * detail: null
|
||||||
|
* * },
|
||||||
|
* * PerformanceEntry {
|
||||||
|
* * name: 'meow',
|
||||||
|
* * entryType: 'mark',
|
||||||
|
* * startTime: 56.350146,
|
||||||
|
* * duration: 0,
|
||||||
|
* * detail: null
|
||||||
|
* * }
|
||||||
|
* * ]
|
||||||
|
*
|
||||||
|
* performance.clearMarks();
|
||||||
|
* performance.clearMeasures();
|
||||||
|
* observer.disconnect();
|
||||||
|
* });
|
||||||
|
* obs.observe({ type: 'mark' });
|
||||||
|
*
|
||||||
|
* performance.mark('test');
|
||||||
|
* performance.mark('meow');
|
||||||
|
* ```
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
getEntriesByType(type: EntryType): PerformanceEntry[];
|
||||||
|
}
|
||||||
|
type PerformanceObserverCallback = (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void;
|
||||||
|
/**
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
class PerformanceObserver extends AsyncResource {
|
||||||
|
constructor(callback: PerformanceObserverCallback);
|
||||||
|
/**
|
||||||
|
* Disconnects the `PerformanceObserver` instance from all notifications.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
disconnect(): void;
|
||||||
|
/**
|
||||||
|
* Subscribes the `PerformanceObserver` instance to notifications of new `PerformanceEntry` instances identified either by `options.entryTypes` or `options.type`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import {
|
||||||
|
* performance,
|
||||||
|
* PerformanceObserver,
|
||||||
|
* } from 'node:perf_hooks';
|
||||||
|
*
|
||||||
|
* const obs = new PerformanceObserver((list, observer) => {
|
||||||
|
* // Called once asynchronously. `list` contains three items.
|
||||||
|
* });
|
||||||
|
* obs.observe({ type: 'mark' });
|
||||||
|
*
|
||||||
|
* for (let n = 0; n < 3; n++)
|
||||||
|
* performance.mark(`test${n}`);
|
||||||
|
* ```
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
observe(
|
||||||
|
options:
|
||||||
|
| {
|
||||||
|
entryTypes: readonly EntryType[];
|
||||||
|
buffered?: boolean | undefined;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: EntryType;
|
||||||
|
buffered?: boolean | undefined;
|
||||||
|
},
|
||||||
|
): void;
|
||||||
|
/**
|
||||||
|
* @since v16.0.0
|
||||||
|
* @returns Current list of entries stored in the performance observer, emptying it out.
|
||||||
|
*/
|
||||||
|
takeRecords(): PerformanceEntry[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Provides detailed network timing data regarding the loading of an application's resources.
|
||||||
|
*
|
||||||
|
* The constructor of this class is not exposed to users directly.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
class PerformanceResourceTiming extends PerformanceEntry {
|
||||||
|
readonly entryType: "resource";
|
||||||
|
protected constructor();
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp at immediately before dispatching the `fetch`
|
||||||
|
* request. If the resource is not intercepted by a worker the property will always return 0.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly workerStart: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp that represents the start time of the fetch which
|
||||||
|
* initiates the redirect.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly redirectStart: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp that will be created immediately after receiving
|
||||||
|
* the last byte of the response of the last redirect.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly redirectEnd: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp immediately before the Node.js starts to fetch the resource.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly fetchStart: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp immediately before the Node.js starts the domain name lookup
|
||||||
|
* for the resource.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly domainLookupStart: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp representing the time immediately after the Node.js finished
|
||||||
|
* the domain name lookup for the resource.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly domainLookupEnd: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp representing the time immediately before Node.js starts to
|
||||||
|
* establish the connection to the server to retrieve the resource.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly connectStart: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp representing the time immediately after Node.js finishes
|
||||||
|
* establishing the connection to the server to retrieve the resource.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly connectEnd: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp representing the time immediately before Node.js starts the
|
||||||
|
* handshake process to secure the current connection.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly secureConnectionStart: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp representing the time immediately before Node.js receives the
|
||||||
|
* first byte of the response from the server.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly requestStart: number;
|
||||||
|
/**
|
||||||
|
* The high resolution millisecond timestamp representing the time immediately after Node.js receives the
|
||||||
|
* last byte of the resource or immediately before the transport connection is closed, whichever comes first.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly responseEnd: number;
|
||||||
|
/**
|
||||||
|
* A number representing the size (in octets) of the fetched resource. The size includes the response header
|
||||||
|
* fields plus the response payload body.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly transferSize: number;
|
||||||
|
/**
|
||||||
|
* A number representing the size (in octets) received from the fetch (HTTP or cache), of the payload body, before
|
||||||
|
* removing any applied content-codings.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly encodedBodySize: number;
|
||||||
|
/**
|
||||||
|
* A number representing the size (in octets) received from the fetch (HTTP or cache), of the message body, after
|
||||||
|
* removing any applied content-codings.
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
readonly decodedBodySize: number;
|
||||||
|
/**
|
||||||
|
* Returns a `object` that is the JSON representation of the `PerformanceResourceTiming` object
|
||||||
|
* @since v18.2.0, v16.17.0
|
||||||
|
*/
|
||||||
|
toJSON(): any;
|
||||||
|
}
|
||||||
|
namespace constants {
|
||||||
|
const NODE_PERFORMANCE_GC_MAJOR: number;
|
||||||
|
const NODE_PERFORMANCE_GC_MINOR: number;
|
||||||
|
const NODE_PERFORMANCE_GC_INCREMENTAL: number;
|
||||||
|
const NODE_PERFORMANCE_GC_WEAKCB: number;
|
||||||
|
const NODE_PERFORMANCE_GC_FLAGS_NO: number;
|
||||||
|
const NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: number;
|
||||||
|
const NODE_PERFORMANCE_GC_FLAGS_FORCED: number;
|
||||||
|
const NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: number;
|
||||||
|
const NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: number;
|
||||||
|
const NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: number;
|
||||||
|
const NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: number;
|
||||||
|
}
|
||||||
|
const performance: Performance;
|
||||||
|
interface EventLoopMonitorOptions {
|
||||||
|
/**
|
||||||
|
* The sampling rate in milliseconds.
|
||||||
|
* Must be greater than zero.
|
||||||
|
* @default 10
|
||||||
|
*/
|
||||||
|
resolution?: number | undefined;
|
||||||
|
}
|
||||||
|
interface Histogram {
|
||||||
|
/**
|
||||||
|
* The number of samples recorded by the histogram.
|
||||||
|
* @since v17.4.0, v16.14.0
|
||||||
|
*/
|
||||||
|
readonly count: number;
|
||||||
|
/**
|
||||||
|
* The number of samples recorded by the histogram.
|
||||||
|
* v17.4.0, v16.14.0
|
||||||
|
*/
|
||||||
|
readonly countBigInt: bigint;
|
||||||
|
/**
|
||||||
|
* The number of times the event loop delay exceeded the maximum 1 hour event
|
||||||
|
* loop delay threshold.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
readonly exceeds: number;
|
||||||
|
/**
|
||||||
|
* The number of times the event loop delay exceeded the maximum 1 hour event loop delay threshold.
|
||||||
|
* @since v17.4.0, v16.14.0
|
||||||
|
*/
|
||||||
|
readonly exceedsBigInt: bigint;
|
||||||
|
/**
|
||||||
|
* The maximum recorded event loop delay.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
readonly max: number;
|
||||||
|
/**
|
||||||
|
* The maximum recorded event loop delay.
|
||||||
|
* v17.4.0, v16.14.0
|
||||||
|
*/
|
||||||
|
readonly maxBigInt: number;
|
||||||
|
/**
|
||||||
|
* The mean of the recorded event loop delays.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
readonly mean: number;
|
||||||
|
/**
|
||||||
|
* The minimum recorded event loop delay.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
readonly min: number;
|
||||||
|
/**
|
||||||
|
* The minimum recorded event loop delay.
|
||||||
|
* v17.4.0, v16.14.0
|
||||||
|
*/
|
||||||
|
readonly minBigInt: bigint;
|
||||||
|
/**
|
||||||
|
* Returns the value at the given percentile.
|
||||||
|
* @since v11.10.0
|
||||||
|
* @param percentile A percentile value in the range (0, 100].
|
||||||
|
*/
|
||||||
|
percentile(percentile: number): number;
|
||||||
|
/**
|
||||||
|
* Returns the value at the given percentile.
|
||||||
|
* @since v17.4.0, v16.14.0
|
||||||
|
* @param percentile A percentile value in the range (0, 100].
|
||||||
|
*/
|
||||||
|
percentileBigInt(percentile: number): bigint;
|
||||||
|
/**
|
||||||
|
* Returns a `Map` object detailing the accumulated percentile distribution.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
readonly percentiles: Map<number, number>;
|
||||||
|
/**
|
||||||
|
* Returns a `Map` object detailing the accumulated percentile distribution.
|
||||||
|
* @since v17.4.0, v16.14.0
|
||||||
|
*/
|
||||||
|
readonly percentilesBigInt: Map<bigint, bigint>;
|
||||||
|
/**
|
||||||
|
* Resets the collected histogram data.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
reset(): void;
|
||||||
|
/**
|
||||||
|
* The standard deviation of the recorded event loop delays.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
readonly stddev: number;
|
||||||
|
}
|
||||||
|
interface IntervalHistogram extends Histogram {
|
||||||
|
/**
|
||||||
|
* Enables the update interval timer. Returns `true` if the timer was
|
||||||
|
* started, `false` if it was already started.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
enable(): boolean;
|
||||||
|
/**
|
||||||
|
* Disables the update interval timer. Returns `true` if the timer was
|
||||||
|
* stopped, `false` if it was already stopped.
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
disable(): boolean;
|
||||||
|
}
|
||||||
|
interface RecordableHistogram extends Histogram {
|
||||||
|
/**
|
||||||
|
* @since v15.9.0, v14.18.0
|
||||||
|
* @param val The amount to record in the histogram.
|
||||||
|
*/
|
||||||
|
record(val: number | bigint): void;
|
||||||
|
/**
|
||||||
|
* Calculates the amount of time (in nanoseconds) that has passed since the
|
||||||
|
* previous call to `recordDelta()` and records that amount in the histogram.
|
||||||
|
* @since v15.9.0, v14.18.0
|
||||||
|
*/
|
||||||
|
recordDelta(): void;
|
||||||
|
/**
|
||||||
|
* Adds the values from `other` to this histogram.
|
||||||
|
* @since v17.4.0, v16.14.0
|
||||||
|
*/
|
||||||
|
add(other: RecordableHistogram): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* _This property is an extension by Node.js. It is not available in Web browsers._
|
||||||
|
*
|
||||||
|
* Creates an `IntervalHistogram` object that samples and reports the event loop
|
||||||
|
* delay over time. The delays will be reported in nanoseconds.
|
||||||
|
*
|
||||||
|
* Using a timer to detect approximate event loop delay works because the
|
||||||
|
* execution of timers is tied specifically to the lifecycle of the libuv
|
||||||
|
* event loop. That is, a delay in the loop will cause a delay in the execution
|
||||||
|
* of the timer, and those delays are specifically what this API is intended to
|
||||||
|
* detect.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { monitorEventLoopDelay } from 'node:perf_hooks';
|
||||||
|
* const h = monitorEventLoopDelay({ resolution: 20 });
|
||||||
|
* h.enable();
|
||||||
|
* // Do something.
|
||||||
|
* h.disable();
|
||||||
|
* console.log(h.min);
|
||||||
|
* console.log(h.max);
|
||||||
|
* console.log(h.mean);
|
||||||
|
* console.log(h.stddev);
|
||||||
|
* console.log(h.percentiles);
|
||||||
|
* console.log(h.percentile(50));
|
||||||
|
* console.log(h.percentile(99));
|
||||||
|
* ```
|
||||||
|
* @since v11.10.0
|
||||||
|
*/
|
||||||
|
function monitorEventLoopDelay(options?: EventLoopMonitorOptions): IntervalHistogram;
|
||||||
|
interface CreateHistogramOptions {
|
||||||
|
/**
|
||||||
|
* The minimum recordable value. Must be an integer value greater than 0.
|
||||||
|
* @default 1
|
||||||
|
*/
|
||||||
|
lowest?: number | bigint | undefined;
|
||||||
|
/**
|
||||||
|
* The maximum recordable value. Must be an integer value greater than min.
|
||||||
|
* @default Number.MAX_SAFE_INTEGER
|
||||||
|
*/
|
||||||
|
highest?: number | bigint | undefined;
|
||||||
|
/**
|
||||||
|
* The number of accuracy digits. Must be a number between 1 and 5.
|
||||||
|
* @default 3
|
||||||
|
*/
|
||||||
|
figures?: number | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns a `RecordableHistogram`.
|
||||||
|
* @since v15.9.0, v14.18.0
|
||||||
|
*/
|
||||||
|
function createHistogram(options?: CreateHistogramOptions): RecordableHistogram;
|
||||||
|
import {
|
||||||
|
performance as _performance,
|
||||||
|
PerformanceEntry as _PerformanceEntry,
|
||||||
|
PerformanceMark as _PerformanceMark,
|
||||||
|
PerformanceMeasure as _PerformanceMeasure,
|
||||||
|
PerformanceObserver as _PerformanceObserver,
|
||||||
|
PerformanceObserverEntryList as _PerformanceObserverEntryList,
|
||||||
|
PerformanceResourceTiming as _PerformanceResourceTiming,
|
||||||
|
} from "perf_hooks";
|
||||||
|
global {
|
||||||
|
/**
|
||||||
|
* `PerformanceEntry` is a global reference for `import { PerformanceEntry } from 'node:node:perf_hooks'`
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/globals.html#performanceentry
|
||||||
|
* @since v19.0.0
|
||||||
|
*/
|
||||||
|
var PerformanceEntry: typeof globalThis extends {
|
||||||
|
onmessage: any;
|
||||||
|
PerformanceEntry: infer T;
|
||||||
|
} ? T
|
||||||
|
: typeof _PerformanceEntry;
|
||||||
|
/**
|
||||||
|
* `PerformanceMark` is a global reference for `import { PerformanceMark } from 'node:node:perf_hooks'`
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/globals.html#performancemark
|
||||||
|
* @since v19.0.0
|
||||||
|
*/
|
||||||
|
var PerformanceMark: typeof globalThis extends {
|
||||||
|
onmessage: any;
|
||||||
|
PerformanceMark: infer T;
|
||||||
|
} ? T
|
||||||
|
: typeof _PerformanceMark;
|
||||||
|
/**
|
||||||
|
* `PerformanceMeasure` is a global reference for `import { PerformanceMeasure } from 'node:node:perf_hooks'`
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/globals.html#performancemeasure
|
||||||
|
* @since v19.0.0
|
||||||
|
*/
|
||||||
|
var PerformanceMeasure: typeof globalThis extends {
|
||||||
|
onmessage: any;
|
||||||
|
PerformanceMeasure: infer T;
|
||||||
|
} ? T
|
||||||
|
: typeof _PerformanceMeasure;
|
||||||
|
/**
|
||||||
|
* `PerformanceObserver` is a global reference for `import { PerformanceObserver } from 'node:node:perf_hooks'`
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/globals.html#performanceobserver
|
||||||
|
* @since v19.0.0
|
||||||
|
*/
|
||||||
|
var PerformanceObserver: typeof globalThis extends {
|
||||||
|
onmessage: any;
|
||||||
|
PerformanceObserver: infer T;
|
||||||
|
} ? T
|
||||||
|
: typeof _PerformanceObserver;
|
||||||
|
/**
|
||||||
|
* `PerformanceObserverEntryList` is a global reference for `import { PerformanceObserverEntryList } from 'node:node:perf_hooks'`
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/globals.html#performanceobserverentrylist
|
||||||
|
* @since v19.0.0
|
||||||
|
*/
|
||||||
|
var PerformanceObserverEntryList: typeof globalThis extends {
|
||||||
|
onmessage: any;
|
||||||
|
PerformanceObserverEntryList: infer T;
|
||||||
|
} ? T
|
||||||
|
: typeof _PerformanceObserverEntryList;
|
||||||
|
/**
|
||||||
|
* `PerformanceResourceTiming` is a global reference for `import { PerformanceResourceTiming } from 'node:node:perf_hooks'`
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/globals.html#performanceresourcetiming
|
||||||
|
* @since v19.0.0
|
||||||
|
*/
|
||||||
|
var PerformanceResourceTiming: typeof globalThis extends {
|
||||||
|
onmessage: any;
|
||||||
|
PerformanceResourceTiming: infer T;
|
||||||
|
} ? T
|
||||||
|
: typeof _PerformanceResourceTiming;
|
||||||
|
/**
|
||||||
|
* `performance` is a global reference for `import { performance } from 'node:node:perf_hooks'`
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/globals.html#performance
|
||||||
|
* @since v16.0.0
|
||||||
|
*/
|
||||||
|
var performance: typeof globalThis extends {
|
||||||
|
onmessage: any;
|
||||||
|
performance: infer T;
|
||||||
|
} ? T
|
||||||
|
: typeof _performance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare module "node:perf_hooks" {
|
||||||
|
export * from "perf_hooks";
|
||||||
|
}
|
||||||
1956
node_modules/@types/node/process.d.ts
generated
vendored
Normal file
1956
node_modules/@types/node/process.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
117
node_modules/@types/node/punycode.d.ts
generated
vendored
Normal file
117
node_modules/@types/node/punycode.d.ts
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* **The version of the punycode module bundled in Node.js is being deprecated. **In a future major version of Node.js this module will be removed. Users
|
||||||
|
* currently depending on the `punycode` module should switch to using the
|
||||||
|
* userland-provided [Punycode.js](https://github.com/bestiejs/punycode.js) module instead. For punycode-based URL
|
||||||
|
* encoding, see `url.domainToASCII` or, more generally, the `WHATWG URL API`.
|
||||||
|
*
|
||||||
|
* The `punycode` module is a bundled version of the [Punycode.js](https://github.com/bestiejs/punycode.js) module. It
|
||||||
|
* can be accessed using:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import punycode from 'node:punycode';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* [Punycode](https://tools.ietf.org/html/rfc3492) is a character encoding scheme defined by RFC 3492 that is
|
||||||
|
* primarily intended for use in Internationalized Domain Names. Because host
|
||||||
|
* names in URLs are limited to ASCII characters only, Domain Names that contain
|
||||||
|
* non-ASCII characters must be converted into ASCII using the Punycode scheme.
|
||||||
|
* For instance, the Japanese character that translates into the English word, `'example'` is `'例'`. The Internationalized Domain Name, `'例.com'` (equivalent
|
||||||
|
* to `'example.com'`) is represented by Punycode as the ASCII string `'xn--fsq.com'`.
|
||||||
|
*
|
||||||
|
* The `punycode` module provides a simple implementation of the Punycode standard.
|
||||||
|
*
|
||||||
|
* The `punycode` module is a third-party dependency used by Node.js and
|
||||||
|
* made available to developers as a convenience. Fixes or other modifications to
|
||||||
|
* the module must be directed to the [Punycode.js](https://github.com/bestiejs/punycode.js) project.
|
||||||
|
* @deprecated Since v7.0.0 - Deprecated
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/punycode.js)
|
||||||
|
*/
|
||||||
|
declare module "punycode" {
|
||||||
|
/**
|
||||||
|
* The `punycode.decode()` method converts a [Punycode](https://tools.ietf.org/html/rfc3492) string of ASCII-only
|
||||||
|
* characters to the equivalent string of Unicode codepoints.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* punycode.decode('maana-pta'); // 'mañana'
|
||||||
|
* punycode.decode('--dqo34k'); // '☃-⌘'
|
||||||
|
* ```
|
||||||
|
* @since v0.5.1
|
||||||
|
*/
|
||||||
|
function decode(string: string): string;
|
||||||
|
/**
|
||||||
|
* The `punycode.encode()` method converts a string of Unicode codepoints to a [Punycode](https://tools.ietf.org/html/rfc3492) string of ASCII-only characters.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* punycode.encode('mañana'); // 'maana-pta'
|
||||||
|
* punycode.encode('☃-⌘'); // '--dqo34k'
|
||||||
|
* ```
|
||||||
|
* @since v0.5.1
|
||||||
|
*/
|
||||||
|
function encode(string: string): string;
|
||||||
|
/**
|
||||||
|
* The `punycode.toUnicode()` method converts a string representing a domain name
|
||||||
|
* containing [Punycode](https://tools.ietf.org/html/rfc3492) encoded characters into Unicode. Only the [Punycode](https://tools.ietf.org/html/rfc3492) encoded parts of the domain name are be
|
||||||
|
* converted.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // decode domain names
|
||||||
|
* punycode.toUnicode('xn--maana-pta.com'); // 'mañana.com'
|
||||||
|
* punycode.toUnicode('xn----dqo34k.com'); // '☃-⌘.com'
|
||||||
|
* punycode.toUnicode('example.com'); // 'example.com'
|
||||||
|
* ```
|
||||||
|
* @since v0.6.1
|
||||||
|
*/
|
||||||
|
function toUnicode(domain: string): string;
|
||||||
|
/**
|
||||||
|
* The `punycode.toASCII()` method converts a Unicode string representing an
|
||||||
|
* Internationalized Domain Name to [Punycode](https://tools.ietf.org/html/rfc3492). Only the non-ASCII parts of the
|
||||||
|
* domain name will be converted. Calling `punycode.toASCII()` on a string that
|
||||||
|
* already only contains ASCII characters will have no effect.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // encode domain names
|
||||||
|
* punycode.toASCII('mañana.com'); // 'xn--maana-pta.com'
|
||||||
|
* punycode.toASCII('☃-⌘.com'); // 'xn----dqo34k.com'
|
||||||
|
* punycode.toASCII('example.com'); // 'example.com'
|
||||||
|
* ```
|
||||||
|
* @since v0.6.1
|
||||||
|
*/
|
||||||
|
function toASCII(domain: string): string;
|
||||||
|
/**
|
||||||
|
* @deprecated since v7.0.0
|
||||||
|
* The version of the punycode module bundled in Node.js is being deprecated.
|
||||||
|
* In a future major version of Node.js this module will be removed.
|
||||||
|
* Users currently depending on the punycode module should switch to using
|
||||||
|
* the userland-provided Punycode.js module instead.
|
||||||
|
*/
|
||||||
|
const ucs2: ucs2;
|
||||||
|
interface ucs2 {
|
||||||
|
/**
|
||||||
|
* @deprecated since v7.0.0
|
||||||
|
* The version of the punycode module bundled in Node.js is being deprecated.
|
||||||
|
* In a future major version of Node.js this module will be removed.
|
||||||
|
* Users currently depending on the punycode module should switch to using
|
||||||
|
* the userland-provided Punycode.js module instead.
|
||||||
|
*/
|
||||||
|
decode(string: string): number[];
|
||||||
|
/**
|
||||||
|
* @deprecated since v7.0.0
|
||||||
|
* The version of the punycode module bundled in Node.js is being deprecated.
|
||||||
|
* In a future major version of Node.js this module will be removed.
|
||||||
|
* Users currently depending on the punycode module should switch to using
|
||||||
|
* the userland-provided Punycode.js module instead.
|
||||||
|
*/
|
||||||
|
encode(codePoints: readonly number[]): string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @deprecated since v7.0.0
|
||||||
|
* The version of the punycode module bundled in Node.js is being deprecated.
|
||||||
|
* In a future major version of Node.js this module will be removed.
|
||||||
|
* Users currently depending on the punycode module should switch to using
|
||||||
|
* the userland-provided Punycode.js module instead.
|
||||||
|
*/
|
||||||
|
const version: string;
|
||||||
|
}
|
||||||
|
declare module "node:punycode" {
|
||||||
|
export * from "punycode";
|
||||||
|
}
|
||||||
152
node_modules/@types/node/querystring.d.ts
generated
vendored
Normal file
152
node_modules/@types/node/querystring.d.ts
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/**
|
||||||
|
* The `node:querystring` module provides utilities for parsing and formatting URL
|
||||||
|
* query strings. It can be accessed using:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import querystring from 'node:querystring';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* `querystring` is more performant than `URLSearchParams` but is not a
|
||||||
|
* standardized API. Use `URLSearchParams` when performance is not critical or
|
||||||
|
* when compatibility with browser code is desirable.
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/querystring.js)
|
||||||
|
*/
|
||||||
|
declare module "querystring" {
|
||||||
|
interface StringifyOptions {
|
||||||
|
/**
|
||||||
|
* The function to use when converting URL-unsafe characters to percent-encoding in the query string.
|
||||||
|
* @default `querystring.escape()`
|
||||||
|
*/
|
||||||
|
encodeURIComponent?: ((str: string) => string) | undefined;
|
||||||
|
}
|
||||||
|
interface ParseOptions {
|
||||||
|
/**
|
||||||
|
* Specifies the maximum number of keys to parse. Specify `0` to remove key counting limitations.
|
||||||
|
* @default 1000
|
||||||
|
*/
|
||||||
|
maxKeys?: number | undefined;
|
||||||
|
/**
|
||||||
|
* The function to use when decoding percent-encoded characters in the query string.
|
||||||
|
* @default `querystring.unescape()`
|
||||||
|
*/
|
||||||
|
decodeURIComponent?: ((str: string) => string) | undefined;
|
||||||
|
}
|
||||||
|
interface ParsedUrlQuery extends NodeJS.Dict<string | string[]> {}
|
||||||
|
interface ParsedUrlQueryInput extends
|
||||||
|
NodeJS.Dict<
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| bigint
|
||||||
|
| ReadonlyArray<string | number | boolean | bigint>
|
||||||
|
| null
|
||||||
|
>
|
||||||
|
{}
|
||||||
|
/**
|
||||||
|
* The `querystring.stringify()` method produces a URL query string from a
|
||||||
|
* given `obj` by iterating through the object's "own properties".
|
||||||
|
*
|
||||||
|
* It serializes the following types of values passed in `obj`: [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) |
|
||||||
|
* [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) |
|
||||||
|
* [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) |
|
||||||
|
* [boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type) |
|
||||||
|
* [string\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) |
|
||||||
|
* [number\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) |
|
||||||
|
* [bigint\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) |
|
||||||
|
* [boolean\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type) The numeric values must be finite. Any other input values will be coerced to
|
||||||
|
* empty strings.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
|
||||||
|
* // Returns 'foo=bar&baz=qux&baz=quux&corge='
|
||||||
|
*
|
||||||
|
* querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
|
||||||
|
* // Returns 'foo:bar;baz:qux'
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* By default, characters requiring percent-encoding within the query string will
|
||||||
|
* be encoded as UTF-8\. If an alternative encoding is required, then an alternative `encodeURIComponent` option will need to be specified:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // Assuming gbkEncodeURIComponent function already exists,
|
||||||
|
*
|
||||||
|
* querystring.stringify({ w: '中文', foo: 'bar' }, null, null,
|
||||||
|
* { encodeURIComponent: gbkEncodeURIComponent });
|
||||||
|
* ```
|
||||||
|
* @since v0.1.25
|
||||||
|
* @param obj The object to serialize into a URL query string
|
||||||
|
* @param [sep='&'] The substring used to delimit key and value pairs in the query string.
|
||||||
|
* @param [eq='='] . The substring used to delimit keys and values in the query string.
|
||||||
|
*/
|
||||||
|
function stringify(obj?: ParsedUrlQueryInput, sep?: string, eq?: string, options?: StringifyOptions): string;
|
||||||
|
/**
|
||||||
|
* The `querystring.parse()` method parses a URL query string (`str`) into a
|
||||||
|
* collection of key and value pairs.
|
||||||
|
*
|
||||||
|
* For example, the query string `'foo=bar&abc=xyz&abc=123'` is parsed into:
|
||||||
|
*
|
||||||
|
* ```json
|
||||||
|
* {
|
||||||
|
* "foo": "bar",
|
||||||
|
* "abc": ["xyz", "123"]
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The object returned by the `querystring.parse()` method _does not_ prototypically inherit from the JavaScript `Object`. This means that typical `Object` methods such as `obj.toString()`,
|
||||||
|
* `obj.hasOwnProperty()`, and others
|
||||||
|
* are not defined and _will not work_.
|
||||||
|
*
|
||||||
|
* By default, percent-encoded characters within the query string will be assumed
|
||||||
|
* to use UTF-8 encoding. If an alternative character encoding is used, then an
|
||||||
|
* alternative `decodeURIComponent` option will need to be specified:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // Assuming gbkDecodeURIComponent function already exists...
|
||||||
|
*
|
||||||
|
* querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null,
|
||||||
|
* { decodeURIComponent: gbkDecodeURIComponent });
|
||||||
|
* ```
|
||||||
|
* @since v0.1.25
|
||||||
|
* @param str The URL query string to parse
|
||||||
|
* @param [sep='&'] The substring used to delimit key and value pairs in the query string.
|
||||||
|
* @param [eq='='] The substring used to delimit keys and values in the query string.
|
||||||
|
*/
|
||||||
|
function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): ParsedUrlQuery;
|
||||||
|
/**
|
||||||
|
* The querystring.encode() function is an alias for querystring.stringify().
|
||||||
|
*/
|
||||||
|
const encode: typeof stringify;
|
||||||
|
/**
|
||||||
|
* The querystring.decode() function is an alias for querystring.parse().
|
||||||
|
*/
|
||||||
|
const decode: typeof parse;
|
||||||
|
/**
|
||||||
|
* The `querystring.escape()` method performs URL percent-encoding on the given `str` in a manner that is optimized for the specific requirements of URL
|
||||||
|
* query strings.
|
||||||
|
*
|
||||||
|
* The `querystring.escape()` method is used by `querystring.stringify()` and is
|
||||||
|
* generally not expected to be used directly. It is exported primarily to allow
|
||||||
|
* application code to provide a replacement percent-encoding implementation if
|
||||||
|
* necessary by assigning `querystring.escape` to an alternative function.
|
||||||
|
* @since v0.1.25
|
||||||
|
*/
|
||||||
|
function escape(str: string): string;
|
||||||
|
/**
|
||||||
|
* The `querystring.unescape()` method performs decoding of URL percent-encoded
|
||||||
|
* characters on the given `str`.
|
||||||
|
*
|
||||||
|
* The `querystring.unescape()` method is used by `querystring.parse()` and is
|
||||||
|
* generally not expected to be used directly. It is exported primarily to allow
|
||||||
|
* application code to provide a replacement decoding implementation if
|
||||||
|
* necessary by assigning `querystring.unescape` to an alternative function.
|
||||||
|
*
|
||||||
|
* By default, the `querystring.unescape()` method will attempt to use the
|
||||||
|
* JavaScript built-in `decodeURIComponent()` method to decode. If that fails,
|
||||||
|
* a safer equivalent that does not throw on malformed URLs will be used.
|
||||||
|
* @since v0.1.25
|
||||||
|
*/
|
||||||
|
function unescape(str: string): string;
|
||||||
|
}
|
||||||
|
declare module "node:querystring" {
|
||||||
|
export * from "querystring";
|
||||||
|
}
|
||||||
413
node_modules/@types/node/readline.d.ts
generated
vendored
Normal file
413
node_modules/@types/node/readline.d.ts
generated
vendored
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
/**
|
||||||
|
* The `node:readline` module provides an interface for reading data from a [Readable](https://nodejs.org/docs/https://nodejs.org/docs/latest-v20.x/api/stream.html#readable-streams) stream
|
||||||
|
* (such as [`process.stdin`](https://nodejs.org/docs/https://nodejs.org/docs/latest-v20.x/api/process.html#processstdin)) one line at a time.
|
||||||
|
*
|
||||||
|
* To use the promise-based APIs:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import * as readline from 'node:readline/promises';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* To use the callback and sync APIs:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import * as readline from 'node:readline';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The following simple example illustrates the basic use of the `node:readline` module.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import * as readline from 'node:readline/promises';
|
||||||
|
* import { stdin as input, stdout as output } from 'node:process';
|
||||||
|
*
|
||||||
|
* const rl = readline.createInterface({ input, output });
|
||||||
|
*
|
||||||
|
* const answer = await rl.question('What do you think of Node.js? ');
|
||||||
|
*
|
||||||
|
* console.log(`Thank you for your valuable feedback: ${answer}`);
|
||||||
|
*
|
||||||
|
* rl.close();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Once this code is invoked, the Node.js application will not terminate until the `readline.Interface` is closed because the interface waits for data to be
|
||||||
|
* received on the `input` stream.
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v20.13.1/lib/readline.js)
|
||||||
|
*/
|
||||||
|
declare module "readline" {
|
||||||
|
import { Abortable, EventEmitter } from "node:events";
|
||||||
|
import * as promises from "node:readline/promises";
|
||||||
|
export { promises };
|
||||||
|
export interface Key {
|
||||||
|
sequence?: string | undefined;
|
||||||
|
name?: string | undefined;
|
||||||
|
ctrl?: boolean | undefined;
|
||||||
|
meta?: boolean | undefined;
|
||||||
|
shift?: boolean | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Instances of the `readline.Interface` class are constructed using the `readline.createInterface()` method. Every instance is associated with a
|
||||||
|
* single `input` [Readable](https://nodejs.org/docs/https://nodejs.org/docs/latest-v20.x/api/stream.html#readable-streams) stream and a single `output` [Writable](https://nodejs.org/docs/https://nodejs.org/docs/latest-v20.x/api/stream.html#writable-streams) stream.
|
||||||
|
* The `output` stream is used to print prompts for user input that arrives on,
|
||||||
|
* and is read from, the `input` stream.
|
||||||
|
* @since v0.1.104
|
||||||
|
*/
|
||||||
|
export class Interface extends EventEmitter {
|
||||||
|
readonly terminal: boolean;
|
||||||
|
/**
|
||||||
|
* The current input data being processed by node.
|
||||||
|
*
|
||||||
|
* This can be used when collecting input from a TTY stream to retrieve the
|
||||||
|
* current value that has been processed thus far, prior to the `line` event
|
||||||
|
* being emitted. Once the `line` event has been emitted, this property will
|
||||||
|
* be an empty string.
|
||||||
|
*
|
||||||
|
* Be aware that modifying the value during the instance runtime may have
|
||||||
|
* unintended consequences if `rl.cursor` is not also controlled.
|
||||||
|
*
|
||||||
|
* **If not using a TTY stream for input, use the `'line'` event.**
|
||||||
|
*
|
||||||
|
* One possible use case would be as follows:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const values = ['lorem ipsum', 'dolor sit amet'];
|
||||||
|
* const rl = readline.createInterface(process.stdin);
|
||||||
|
* const showResults = debounce(() => {
|
||||||
|
* console.log(
|
||||||
|
* '\n',
|
||||||
|
* values.filter((val) => val.startsWith(rl.line)).join(' '),
|
||||||
|
* );
|
||||||
|
* }, 300);
|
||||||
|
* process.stdin.on('keypress', (c, k) => {
|
||||||
|
* showResults();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v0.1.98
|
||||||
|
*/
|
||||||
|
readonly line: string;
|
||||||
|
/**
|
||||||
|
* The cursor position relative to `rl.line`.
|
||||||
|
*
|
||||||
|
* This will track where the current cursor lands in the input string, when
|
||||||
|
* reading input from a TTY stream. The position of cursor determines the
|
||||||
|
* portion of the input string that will be modified as input is processed,
|
||||||
|
* as well as the column where the terminal caret will be rendered.
|
||||||
|
* @since v0.1.98
|
||||||
|
*/
|
||||||
|
readonly cursor: number;
|
||||||
|
/**
|
||||||
|
* NOTE: According to the documentation:
|
||||||
|
*
|
||||||
|
* > Instances of the `readline.Interface` class are constructed using the
|
||||||
|
* > `readline.createInterface()` method.
|
||||||
|
*
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/readline.html#class-interfaceconstructor
|
||||||
|
*/
|
||||||
|
protected constructor(
|
||||||
|
input: NodeJS.ReadableStream,
|
||||||
|
output?: NodeJS.WritableStream,
|
||||||
|
completer?: Completer | AsyncCompleter,
|
||||||
|
terminal?: boolean,
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* NOTE: According to the documentation:
|
||||||
|
*
|
||||||
|
* > Instances of the `readline.Interface` class are constructed using the
|
||||||
|
* > `readline.createInterface()` method.
|
||||||
|
*
|
||||||
|
* @see https://nodejs.org/docs/latest-v20.x/api/readline.html#class-interfaceconstructor
|
||||||
|
*/
|
||||||
|
protected constructor(options: ReadLineOptions);
|
||||||
|
/**
|
||||||
|
* The `rl.getPrompt()` method returns the current prompt used by `rl.prompt()`.
|
||||||
|
* @since v15.3.0, v14.17.0
|
||||||
|
* @return the current prompt string
|
||||||
|
*/
|
||||||
|
getPrompt(): string;
|
||||||
|
/**
|
||||||
|
* The `rl.setPrompt()` method sets the prompt that will be written to `output` whenever `rl.prompt()` is called.
|
||||||
|
* @since v0.1.98
|
||||||
|
*/
|
||||||
|
setPrompt(prompt: string): void;
|
||||||
|
/**
|
||||||
|
* The `rl.prompt()` method writes the `Interface` instances configured`prompt` to a new line in `output` in order to provide a user with a new
|
||||||
|
* location at which to provide input.
|
||||||
|
*
|
||||||
|
* When called, `rl.prompt()` will resume the `input` stream if it has been
|
||||||
|
* paused.
|
||||||
|
*
|
||||||
|
* If the `Interface` was created with `output` set to `null` or `undefined` the prompt is not written.
|
||||||
|
* @since v0.1.98
|
||||||
|
* @param preserveCursor If `true`, prevents the cursor placement from being reset to `0`.
|
||||||
|
*/
|
||||||
|
prompt(preserveCursor?: boolean): void;
|
||||||
|
/**
|
||||||
|
* The `rl.question()` method displays the `query` by writing it to the `output`,
|
||||||
|
* waits for user input to be provided on `input`, then invokes the `callback` function passing the provided input as the first argument.
|
||||||
|
*
|
||||||
|
* When called, `rl.question()` will resume the `input` stream if it has been
|
||||||
|
* paused.
|
||||||
|
*
|
||||||
|
* If the `Interface` was created with `output` set to `null` or `undefined` the `query` is not written.
|
||||||
|
*
|
||||||
|
* The `callback` function passed to `rl.question()` does not follow the typical
|
||||||
|
* pattern of accepting an `Error` object or `null` as the first argument.
|
||||||
|
* The `callback` is called with the provided answer as the only argument.
|
||||||
|
*
|
||||||
|
* An error will be thrown if calling `rl.question()` after `rl.close()`.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* rl.question('What is your favorite food? ', (answer) => {
|
||||||
|
* console.log(`Oh, so your favorite food is ${answer}`);
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Using an `AbortController` to cancel a question.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const ac = new AbortController();
|
||||||
|
* const signal = ac.signal;
|
||||||
|
*
|
||||||
|
* rl.question('What is your favorite food? ', { signal }, (answer) => {
|
||||||
|
* console.log(`Oh, so your favorite food is ${answer}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* signal.addEventListener('abort', () => {
|
||||||
|
* console.log('The food question timed out');
|
||||||
|
* }, { once: true });
|
||||||
|
*
|
||||||
|
* setTimeout(() => ac.abort(), 10000);
|
||||||
|
* ```
|
||||||
|
* @since v0.3.3
|
||||||
|
* @param query A statement or query to write to `output`, prepended to the prompt.
|
||||||
|
* @param callback A callback function that is invoked with the user's input in response to the `query`.
|
||||||
|
*/
|
||||||
|
question(query: string, callback: (answer: string) => void): void;
|
||||||
|
question(query: string, options: Abortable, callback: (answer: string) => void): void;
|
||||||
|
/**
|
||||||
|
* The `rl.pause()` method pauses the `input` stream, allowing it to be resumed
|
||||||
|
* later if necessary.
|
||||||
|
*
|
||||||
|
* Calling `rl.pause()` does not immediately pause other events (including `'line'`) from being emitted by the `Interface` instance.
|
||||||
|
* @since v0.3.4
|
||||||
|
*/
|
||||||
|
pause(): this;
|
||||||
|
/**
|
||||||
|
* The `rl.resume()` method resumes the `input` stream if it has been paused.
|
||||||
|
* @since v0.3.4
|
||||||
|
*/
|
||||||
|
resume(): this;
|
||||||
|
/**
|
||||||
|
* The `rl.close()` method closes the `Interface` instance and
|
||||||
|
* relinquishes control over the `input` and `output` streams. When called,
|
||||||
|
* the `'close'` event will be emitted.
|
||||||
|
*
|
||||||
|
* Calling `rl.close()` does not immediately stop other events (including `'line'`)
|
||||||
|
* from being emitted by the `Interface` instance.
|
||||||
|
* @since v0.1.98
|
||||||
|
*/
|
||||||
|
close(): void;
|
||||||
|
/**
|
||||||
|
* The `rl.write()` method will write either `data` or a key sequence identified
|
||||||
|
* by `key` to the `output`. The `key` argument is supported only if `output` is
|
||||||
|
* a `TTY` text terminal. See `TTY keybindings` for a list of key
|
||||||
|
* combinations.
|
||||||
|
*
|
||||||
|
* If `key` is specified, `data` is ignored.
|
||||||
|
*
|
||||||
|
* When called, `rl.write()` will resume the `input` stream if it has been
|
||||||
|
* paused.
|
||||||
|
*
|
||||||
|
* If the `Interface` was created with `output` set to `null` or `undefined` the `data` and `key` are not written.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* rl.write('Delete this!');
|
||||||
|
* // Simulate Ctrl+U to delete the line written previously
|
||||||
|
* rl.write(null, { ctrl: true, name: 'u' });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The `rl.write()` method will write the data to the `readline` `Interface`'s `input` _as if it were provided by the user_.
|
||||||
|
* @since v0.1.98
|
||||||
|
*/
|
||||||
|
write(data: string | Buffer, key?: Key): void;
|
||||||
|
write(data: undefined | null | string | Buffer, key: Key): void;
|
||||||
|
/**
|
||||||
|
* Returns the real position of the cursor in relation to the input
|
||||||
|
* prompt + string. Long input (wrapping) strings, as well as multiple
|
||||||
|
* line prompts are included in the calculations.
|
||||||
|
* @since v13.5.0, v12.16.0
|
||||||
|
*/
|
||||||
|
getCursorPos(): CursorPos;
|
||||||
|
/**
|
||||||
|
* events.EventEmitter
|
||||||
|
* 1. close
|
||||||
|
* 2. line
|
||||||
|
* 3. pause
|
||||||
|
* 4. resume
|
||||||
|
* 5. SIGCONT
|
||||||
|
* 6. SIGINT
|
||||||
|
* 7. SIGTSTP
|
||||||
|
* 8. history
|
||||||
|
*/
|
||||||
|
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
addListener(event: "close", listener: () => void): this;
|
||||||
|
addListener(event: "line", listener: (input: string) => void): this;
|
||||||
|
addListener(event: "pause", listener: () => void): this;
|
||||||
|
addListener(event: "resume", listener: () => void): this;
|
||||||
|
addListener(event: "SIGCONT", listener: () => void): this;
|
||||||
|
addListener(event: "SIGINT", listener: () => void): this;
|
||||||
|
addListener(event: "SIGTSTP", listener: () => void): this;
|
||||||
|
addListener(event: "history", listener: (history: string[]) => void): this;
|
||||||
|
emit(event: string | symbol, ...args: any[]): boolean;
|
||||||
|
emit(event: "close"): boolean;
|
||||||
|
emit(event: "line", input: string): boolean;
|
||||||
|
emit(event: "pause"): boolean;
|
||||||
|
emit(event: "resume"): boolean;
|
||||||
|
emit(event: "SIGCONT"): boolean;
|
||||||
|
emit(event: "SIGINT"): boolean;
|
||||||
|
emit(event: "SIGTSTP"): boolean;
|
||||||
|
emit(event: "history", history: string[]): boolean;
|
||||||
|
on(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
on(event: "close", listener: () => void): this;
|
||||||
|
on(event: "line", listener: (input: string) => void): this;
|
||||||
|
on(event: "pause", listener: () => void): this;
|
||||||
|
on(event: "resume", listener: () => void): this;
|
||||||
|
on(event: "SIGCONT", listener: () => void): this;
|
||||||
|
on(event: "SIGINT", listener: () => void): this;
|
||||||
|
on(event: "SIGTSTP", listener: () => void): this;
|
||||||
|
on(event: "history", listener: (history: string[]) => void): this;
|
||||||
|
once(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
once(event: "close", listener: () => void): this;
|
||||||
|
once(event: "line", listener: (input: string) => void): this;
|
||||||
|
once(event: "pause", listener: () => void): this;
|
||||||
|
once(event: "resume", listener: () => void): this;
|
||||||
|
once(event: "SIGCONT", listener: () => void): this;
|
||||||
|
once(event: "SIGINT", listener: () => void): this;
|
||||||
|
once(event: "SIGTSTP", listener: () => void): this;
|
||||||
|
once(event: "history", listener: (history: string[]) => void): this;
|
||||||
|
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependListener(event: "close", listener: () => void): this;
|
||||||
|
prependListener(event: "line", listener: (input: string) => void): this;
|
||||||
|
prependListener(event: "pause", listener: () => void): this;
|
||||||
|
prependListener(event: "resume", listener: () => void): this;
|
||||||
|
prependListener(event: "SIGCONT", listener: () => void): this;
|
||||||
|
prependListener(event: "SIGINT", listener: () => void): this;
|
||||||
|
prependListener(event: "SIGTSTP", listener: () => void): this;
|
||||||
|
prependListener(event: "history", listener: (history: string[]) => void): this;
|
||||||
|
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependOnceListener(event: "close", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "line", listener: (input: string) => void): this;
|
||||||
|
prependOnceListener(event: "pause", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "resume", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "SIGCONT", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "SIGINT", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "SIGTSTP", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "history", listener: (history: string[]) => void): this;
|
||||||
|
[Symbol.asyncIterator](): NodeJS.AsyncIterator<string>;
|
||||||
|
}
|
||||||
|
export type ReadLine = Interface; // type forwarded for backwards compatibility
|
||||||
|
export type Completer = (line: string) => CompleterResult;
|
||||||
|
export type AsyncCompleter = (
|
||||||
|
line: string,
|
||||||
|
callback: (err?: null | Error, result?: CompleterResult) => void,
|
||||||
|
) => void;
|
||||||
|
export type CompleterResult = [string[], string];
|
||||||
|
export interface ReadLineOptions {
|
||||||
|
/**
|
||||||
|
* The [`Readable`](https://nodejs.org/docs/latest-v20.x/api/stream.html#readable-streams) stream to listen to
|
||||||
|
*/
|
||||||
|
input: NodeJS.ReadableStream;
|
||||||
|
/**
|
||||||
|
* The [`Writable`](https://nodejs.org/docs/latest-v20.x/api/stream.html#writable-streams) stream to write readline data to.
|
||||||
|
*/
|
||||||
|
output?: NodeJS.WritableStream | undefined;
|
||||||
|
/**
|
||||||
|
* An optional function used for Tab autocompletion.
|
||||||
|
*/
|
||||||
|
completer?: Completer | AsyncCompleter | undefined;
|
||||||
|
/**
|
||||||
|
* `true` if the `input` and `output` streams should be treated like a TTY,
|
||||||
|
* and have ANSI/VT100 escape codes written to it.
|
||||||
|
* Default: checking `isTTY` on the `output` stream upon instantiation.
|
||||||
|
*/
|
||||||
|
terminal?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Initial list of history lines.
|
||||||
|
* This option makes sense only if `terminal` is set to `true` by the user or by an internal `output` check,
|
||||||
|
* otherwise the history caching mechanism is not initialized at all.
|
||||||
|
* @default []
|
||||||
|
*/
|
||||||
|
history?: string[] | undefined;
|
||||||
|
/**
|
||||||
|
* Maximum number of history lines retained.
|
||||||
|
* To disable the history set this value to `0`.
|
||||||
|
* This option makes sense only if `terminal` is set to `true` by the user or by an internal `output` check,
|
||||||
|
* otherwise the history caching mechanism is not initialized at all.
|
||||||
|
* @default 30
|
||||||
|
*/
|
||||||
|
historySize?: number | undefined;
|
||||||
|
/**
|
||||||
|
* If `true`, when a new input line added to the history list duplicates an older one,
|
||||||
|
* this removes the older line from the list.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
removeHistoryDuplicates?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* The prompt string to use.
|
||||||
|
* @default "> "
|
||||||
|
*/
|
||||||
|
prompt?: string | undefined;
|
||||||
|
/**
|
||||||
|
* If the delay between `\r` and `\n` exceeds `crlfDelay` milliseconds,
|
||||||
|
* both `\r` and `\n` will be treated as separate end-of-line input.
|
||||||
|
* `crlfDelay` will be coerced to a number no less than `100`.
|
||||||
|
* It can be set to `Infinity`, in which case
|
||||||
|
* `\r` followed by `\n` will always be considered a single newline
|
||||||
|
* (which may be reasonable for [reading files](https://nodejs.org/docs/latest-v20.x/api/readline.html#example-read-file-stream-line-by-line) with `\r\n` line delimiter).
|
||||||
|
* @default 100
|
||||||
|
*/
|
||||||
|
crlfDelay?: number | undefined;
|
||||||
|
/**
|
||||||
|
* The duration `readline` will wait for a character
|
||||||
|
* (when reading an ambiguous key sequence in milliseconds
|
||||||
|
* one that can both form a complete key sequence using the input read so far
|
||||||
|
* and can take additional input to complete a longer key sequence).
|
||||||
|
* @default 500
|
||||||
|
*/
|
||||||
|
escapeCodeTimeout?: number | undefined;
|
||||||
|
/**
|
||||||
|
* The number of spaces a tab is equal to (minimum 1).
|
||||||
|
* @default 8
|
||||||
|
*/
|
||||||
|
tabSize?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Allows closing the interface using an AbortSignal.
|
||||||
|
* Aborting the signal will internally call `close` on the interface.
|
||||||
|
*/
|
||||||
|
signal?: AbortSignal | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `readline.createInterface()` method creates a new `readline.Interface` instance.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import readline from 'node:readline';
|
||||||
|
* const rl = readline.createInterface({
|
||||||
|
* input: process.stdin,
|
||||||
|
* output: process.stdout,
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Once the `readline.Interface` instance is created, the most common case is to
|
||||||
|
* listen for the `'line'` event:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* rl.on('line', (line) => {
|
||||||
|
* console.log(`Received: ${line}`);
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If `terminal` is `true` for this instance then the `output` stream will get
|
||||||
|
* the best compatibility if it defines an `output.columns` property and emits
|
||||||
|
* a `'resize'` event on the `output` if or when the columns ever change
|
||||||
|
* (`process.stdout` does this automatically when
|
||||||
21
node_modules/@types/qs/LICENSE
generated
vendored
Normal file
21
node_modules/@types/qs/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user