mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2026-08-04 15:28:58 +00:00
AGDNS-4277 generate client api using openapi specs
This commit is contained in:
parent
ef585d45cd
commit
c79ff5454e
166 changed files with 4908 additions and 1062 deletions
|
|
@ -67,4 +67,13 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
// Orval-generated files — max-len is controlled by prettier
|
||||
files: ['src/api/generated.ts', 'src/api/model/**/*.ts'],
|
||||
rules: {
|
||||
'max-len': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,24 +2,24 @@
|
|||
|
||||
## Table of Contents
|
||||
|
||||
- [AGENTS.md — AdGuard Home client\_v2 (SolidJS Frontend)](#agentsmd--adguard-home-client_v2-solidjs-frontend)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [AGENTS.md — AdGuard Home client_v2 (SolidJS Frontend)](#agentsmd--adguard-home-client_v2-solidjs-frontend)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Project Overview](#project-overview)
|
||||
- [Technical Context](#technical-context)
|
||||
- [Project Structure](#project-structure)
|
||||
- [Build And Test Commands](#build-and-test-commands)
|
||||
- [Contribution Instructions](#contribution-instructions)
|
||||
- [Code Guidelines](#code-guidelines)
|
||||
- [System Design](#system-design)
|
||||
- [Architecture](#architecture)
|
||||
- [Code Quality](#code-quality)
|
||||
- [Testing](#testing)
|
||||
- [Dependency Management](#dependency-management)
|
||||
- [Configuration \& Documentation](#configuration--documentation)
|
||||
- [Markdown Formatting](#markdown-formatting)
|
||||
- [Other](#other)
|
||||
- [Accessibility](#accessibility)
|
||||
- [Translations](#translations)
|
||||
- [System Design](#system-design)
|
||||
- [Architecture](#architecture)
|
||||
- [Code Quality](#code-quality)
|
||||
- [Testing](#testing)
|
||||
- [Dependency Management](#dependency-management)
|
||||
- [Configuration \& Documentation](#configuration--documentation)
|
||||
- [Markdown Formatting](#markdown-formatting)
|
||||
- [Other](#other)
|
||||
- [Accessibility](#accessibility)
|
||||
- [Translations](#translations)
|
||||
|
||||
# Project Overview
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ client_v2/
|
|||
│ ├── index.tsx # Main app entry (renders <App/>)
|
||||
│ ├── index.pcss # Global CSS (vars, reset)
|
||||
│ ├── initialState.ts # Domain model types + initial form state
|
||||
│ ├── api/ # Single Api class — all HTTP calls
|
||||
│ ├── api/ # Orval-generated typed client + customFetch mutator
|
||||
│ ├── common/
|
||||
│ │ ├── controls/ # Input primitives (Checkbox, Input, Select, Switch, …)
|
||||
│ │ ├── ui/ # Higher-level UI (Button, Dialog, Table, Tabs, Sidebar, …)
|
||||
|
|
@ -166,9 +166,10 @@ no server process of its own. Design for the browser environment:
|
|||
- **Stateless client, stateful backend.** The UI holds no durable state; all
|
||||
configuration and data persist in the AdGuard Home backend via the `/control`
|
||||
HTTP API. Treat the browser as a thin view layer.
|
||||
- **Single source of HTTP.** All backend calls go through the singleton
|
||||
`apiClient` in `src/api/Api.ts`. Do not call `fetch` directly from components
|
||||
or stores — add a typed method to the `Api` class instead.
|
||||
- **Single source of HTTP.** All backend calls go through the orval-generated
|
||||
typed client in `src/api/generated.ts` (with the `customFetch` mutator in
|
||||
`src/api/customFetch.ts`). Do not call `fetch` directly from components
|
||||
or stores — import a generated function instead.
|
||||
- **No shared server memory.** Multiple browser tabs / reloads are independent;
|
||||
never rely on in-memory module state surviving a reload. Re-fetch data in
|
||||
component `onMount` rather than assuming a store is already populated.
|
||||
|
|
@ -199,8 +200,9 @@ Universal design principles the codebase follows:
|
|||
→ api → backend. Stores never import components; api never imports stores.
|
||||
- **Explicit Boundaries** — modules interact through named exports; no
|
||||
reaching into another module's internals.
|
||||
- **Data Flow Clarity** — user action → store action function → `apiClient`
|
||||
→ `setState` → reactive UI update. Data moves in one predictable path.
|
||||
- **Data Flow Clarity** — user action → store action function → generated
|
||||
API function → `setState` → reactive UI update. Data moves in one
|
||||
predictable path.
|
||||
- **Minimize Coupling, Maximize Cohesion** — stores are self-contained and
|
||||
imported directly (no Context providers); components depend on narrow store
|
||||
exports.
|
||||
|
|
@ -221,7 +223,7 @@ This project's layers, from top to bottom:
|
|||
| Components | Render UI, handle user interaction | `src/components/Dashboard/`, `src/components/Clients/` |
|
||||
| Common UI | Reusable controls and primitives | `src/common/controls/Select/`, `src/common/ui/Button/` |
|
||||
| Stores | Domain state + async actions | `src/stores/clients.ts`, `src/stores/queryLogs.ts` |
|
||||
| API | HTTP transport to backend | `src/api/Api.ts` |
|
||||
| API | HTTP transport to backend | `src/api/generated.ts`, `src/api/customFetch.ts` |
|
||||
| Helpers | Pure utilities, validators | `src/helpers/`, `src/lib/` |
|
||||
|
||||
```text
|
||||
|
|
@ -229,7 +231,7 @@ Components (pages, controls)
|
|||
↓
|
||||
Stores (domain state + actions)
|
||||
↓
|
||||
API (apiClient → fetch /control)
|
||||
API (generated functions → customFetch → fetch /control)
|
||||
↓
|
||||
AdGuard Home backend (Go)
|
||||
```
|
||||
|
|
@ -246,7 +248,7 @@ must not depend on stores or components. Helpers are pure and dependency-free.
|
|||
## Code Quality
|
||||
|
||||
- **Path aliases**: Use the `panel/*` alias for all `src/` imports
|
||||
(e.g. `import { apiClient } from 'panel/api/Api'`). Use `Twosky` for the
|
||||
(e.g. `import { status } from 'panel/api/generated'`). Use `Twosky` for the
|
||||
root `.twosky.json` config. Avoid deep relative paths (`../../..`).
|
||||
- **Component conventions**: PascalCase directories and component files.
|
||||
Each component lives in its own directory with an `index.tsx` and a
|
||||
|
|
@ -284,12 +286,12 @@ must not depend on stores or components. Helpers are pure and dependency-free.
|
|||
`createMemo` (e.g., table columns), **access the prop in the memo body**
|
||||
so SolidJS tracks the dependency.
|
||||
- **Stores**: Module-scoped `createStore` singletons exported directly — no
|
||||
Context/Provider. Async actions set a `processing*` flag, call `apiClient`,
|
||||
then `setState`. Errors are reported via `addErrorToast`.
|
||||
Context/Provider. Async actions set a `processing*` flag, call generated
|
||||
API functions, then `setState`. Errors are reported via `addErrorToast`.
|
||||
- **Naming**: Files `PascalCase.tsx` for components, `camelCase.ts` for
|
||||
stores/helpers. CSS module files `*.module.pcss`.
|
||||
- **Error handling**: API errors throw from `Api.ts`; store actions catch and
|
||||
surface a toast. Do not swallow errors silently.
|
||||
- **Error handling**: API errors throw from `customFetch.ts`; store actions
|
||||
catch and surface a toast. Do not swallow errors silently.
|
||||
- **Logging**: `console.warn` and `console.error` are allowed; `console.log`
|
||||
is disallowed by ESLint.
|
||||
- **Static analysis gates**: ESLint, Prettier, and `tsc --noEmit` must pass.
|
||||
|
|
@ -312,8 +314,8 @@ must not depend on stores or components. Helpers are pure and dependency-free.
|
|||
`@testing-library/jest-dom` matchers.
|
||||
- **Store/helper tests**: Call exported action/builder functions directly and
|
||||
assert on returned values or state (e.g.
|
||||
`src/__tests__/clientForm/buildClientConfig.test.ts`). Mock `apiClient` when
|
||||
a test would otherwise hit the network.
|
||||
`src/__tests__/clientForm/buildClientConfig.test.ts`). Mock generated API
|
||||
functions when a test would otherwise hit the network.
|
||||
- **Naming**: Mirror the source path under `__tests__/`
|
||||
(e.g. `stores/clients.ts` → `__tests__/stores/clients.test.ts`).
|
||||
- **E2E tests**: Playwright, configured in `playwright.config.ts`
|
||||
|
|
|
|||
27
client_v2/orval.config.ts
Normal file
27
client_v2/orval.config.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { defineConfig } from 'orval';
|
||||
|
||||
export default defineConfig({
|
||||
adguardHome: {
|
||||
input: {
|
||||
target: '../openapi/openapi.yaml',
|
||||
},
|
||||
output: {
|
||||
target: './src/api/generated.ts',
|
||||
schemas: './src/api/model',
|
||||
client: 'fetch',
|
||||
baseUrl: 'control',
|
||||
prettier: true,
|
||||
override: {
|
||||
header: false,
|
||||
mutator: {
|
||||
path: './src/api/customFetch.ts',
|
||||
name: 'customFetch',
|
||||
},
|
||||
fetch: {
|
||||
includeHttpResponseReturnType: false,
|
||||
},
|
||||
enumGenerationType: 'union',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
1526
client_v2/package-lock.json
generated
1526
client_v2/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -19,7 +19,8 @@
|
|||
"test:e2e:codegen": "npx playwright codegen",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"typecheck:watch": "tsc --noEmit --watch",
|
||||
"translations:check": "node ./scripts/check-translations.js"
|
||||
"translations:check": "node ./scripts/check-translations.js",
|
||||
"api:generate": "orval --config ./orval.config.ts && bash scripts/postgenerate.sh"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
|
@ -69,6 +70,7 @@
|
|||
"html-webpack-plugin": "^5.6.0",
|
||||
"jsdom": "^26.1.0",
|
||||
"mini-css-extract-plugin": "^2.9.0",
|
||||
"orval": "^8.22.0",
|
||||
"playwright": "^1.61.0",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-import": "^16.1.1",
|
||||
|
|
|
|||
5
client_v2/scripts/postgenerate.sh
Executable file
5
client_v2/scripts/postgenerate.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
npx prettier --write "src/api/generated.ts" "src/api/model/**/*.ts"
|
||||
npx eslint --quiet --fix "src/api/generated.ts" "src/api/model/**/*.ts" || true
|
||||
|
|
@ -1,17 +1,15 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
getAccessList: vi.fn(),
|
||||
setAccessList: vi.fn(),
|
||||
accessList: vi.fn(),
|
||||
accessSet: vi.fn(),
|
||||
addSuccessToast: vi.fn(),
|
||||
addErrorToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
getAccessList: mocks.getAccessList,
|
||||
setAccessList: mocks.setAccessList,
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
accessList: mocks.accessList,
|
||||
accessSet: mocks.accessSet,
|
||||
}));
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
addSuccessToast: mocks.addSuccessToast,
|
||||
|
|
@ -24,13 +22,13 @@ describe('toggleClientBlock', () => {
|
|||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('not-disallowed + allowlist mode with >1 allowed → removes from allowed', async () => {
|
||||
mocks.getAccessList.mockResolvedValue({
|
||||
mocks.accessList.mockResolvedValue({
|
||||
allowed_clients: ['1.1.1.1', '2.2.2.2'],
|
||||
disallowed_clients: [],
|
||||
blocked_hosts: [],
|
||||
});
|
||||
await toggleClientBlock('1.1.1.1', false, '');
|
||||
expect(mocks.setAccessList).toHaveBeenCalledWith({
|
||||
expect(mocks.accessSet).toHaveBeenCalledWith({
|
||||
allowed_clients: ['2.2.2.2'],
|
||||
disallowed_clients: [],
|
||||
blocked_hosts: [],
|
||||
|
|
@ -38,13 +36,13 @@ describe('toggleClientBlock', () => {
|
|||
});
|
||||
|
||||
it('not-disallowed, no allowlist → adds to disallowed', async () => {
|
||||
mocks.getAccessList.mockResolvedValue({
|
||||
mocks.accessList.mockResolvedValue({
|
||||
allowed_clients: [],
|
||||
disallowed_clients: [],
|
||||
blocked_hosts: [],
|
||||
});
|
||||
await toggleClientBlock('3.3.3.3', false, '');
|
||||
expect(mocks.setAccessList).toHaveBeenCalledWith({
|
||||
expect(mocks.accessSet).toHaveBeenCalledWith({
|
||||
allowed_clients: [],
|
||||
disallowed_clients: ['3.3.3.3'],
|
||||
blocked_hosts: [],
|
||||
|
|
@ -52,13 +50,13 @@ describe('toggleClientBlock', () => {
|
|||
});
|
||||
|
||||
it('disallowed + allowlist mode → adds to allowed', async () => {
|
||||
mocks.getAccessList.mockResolvedValue({
|
||||
mocks.accessList.mockResolvedValue({
|
||||
allowed_clients: ['1.1.1.1'],
|
||||
disallowed_clients: ['2.2.2.2'],
|
||||
blocked_hosts: [],
|
||||
});
|
||||
await toggleClientBlock('2.2.2.2', true, '');
|
||||
expect(mocks.setAccessList).toHaveBeenCalledWith({
|
||||
expect(mocks.accessSet).toHaveBeenCalledWith({
|
||||
allowed_clients: ['1.1.1.1', '2.2.2.2'],
|
||||
disallowed_clients: ['2.2.2.2'],
|
||||
blocked_hosts: [],
|
||||
|
|
@ -66,13 +64,13 @@ describe('toggleClientBlock', () => {
|
|||
});
|
||||
|
||||
it('disallowed, no allowlist → removes from disallowed (uses rule)', async () => {
|
||||
mocks.getAccessList.mockResolvedValue({
|
||||
mocks.accessList.mockResolvedValue({
|
||||
allowed_clients: [],
|
||||
disallowed_clients: ['client:X'],
|
||||
blocked_hosts: [],
|
||||
});
|
||||
await toggleClientBlock('1.2.3.4', true, 'client:X');
|
||||
expect(mocks.setAccessList).toHaveBeenCalledWith({
|
||||
expect(mocks.accessSet).toHaveBeenCalledWith({
|
||||
allowed_clients: [],
|
||||
disallowed_clients: [],
|
||||
blocked_hosts: [],
|
||||
|
|
|
|||
|
|
@ -1,22 +1,20 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
getTlsStatus: vi.fn(),
|
||||
getGlobalVersion: vi.fn(),
|
||||
tlsStatus: vi.fn(),
|
||||
getVersionJson: vi.fn(),
|
||||
getProfile: vi.fn(),
|
||||
addErrorToast: vi.fn(),
|
||||
addSuccessToast: vi.fn(),
|
||||
addNoticeToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
baseUrl: 'http://x',
|
||||
getGlobalVersion: mocks.getGlobalVersion,
|
||||
getVersionJson: mocks.getVersionJson,
|
||||
getProfile: mocks.getProfile,
|
||||
getUpdate: vi.fn(),
|
||||
getTlsStatus: mocks.getTlsStatus,
|
||||
},
|
||||
beginUpdate: vi.fn(),
|
||||
tlsStatus: mocks.tlsStatus,
|
||||
}));
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
addErrorToast: mocks.addErrorToast,
|
||||
|
|
@ -30,12 +28,12 @@ describe('getDnsStatus', () => {
|
|||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('fetches TLS status when the core is running (FR-005)', async () => {
|
||||
mocks.getGlobalVersion.mockResolvedValue({
|
||||
mocks.getVersionJson.mockResolvedValue({
|
||||
disabled: true,
|
||||
new_version: 'x',
|
||||
});
|
||||
mocks.getProfile.mockResolvedValue({ name: 'n', theme: 't' });
|
||||
mocks.getTlsStatus.mockResolvedValue({ enabled: false });
|
||||
mocks.tlsStatus.mockResolvedValue({ enabled: false });
|
||||
|
||||
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
||||
new Response(
|
||||
|
|
@ -54,6 +52,6 @@ describe('getDnsStatus', () => {
|
|||
await getDnsStatus();
|
||||
// allow microtasks for chained getVersion/getTlsStatus/getProfile
|
||||
await new Promise((r) => setTimeout(r, 0));
|
||||
expect(mocks.getTlsStatus).toHaveBeenCalled();
|
||||
expect(mocks.tlsStatus).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,22 +1,20 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
findActiveDhcp: vi.fn(),
|
||||
getDhcpInterfaces: vi.fn(),
|
||||
getDhcpStatus: vi.fn(),
|
||||
setDhcpConfig: vi.fn(),
|
||||
checkActiveDhcp: vi.fn(),
|
||||
dhcpInterfaces: vi.fn(),
|
||||
dhcpStatus: vi.fn(),
|
||||
dhcpSetConfig: vi.fn(),
|
||||
addErrorToast: vi.fn(),
|
||||
addSuccessToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
findActiveDhcp: mocks.findActiveDhcp,
|
||||
getDhcpInterfaces: mocks.getDhcpInterfaces,
|
||||
getDhcpStatus: mocks.getDhcpStatus,
|
||||
getGlobalStatus: vi.fn(),
|
||||
setDhcpConfig: mocks.setDhcpConfig,
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
checkActiveDhcp: mocks.checkActiveDhcp,
|
||||
dhcpInterfaces: mocks.dhcpInterfaces,
|
||||
dhcpStatus: mocks.dhcpStatus,
|
||||
status: vi.fn(),
|
||||
dhcpSetConfig: mocks.dhcpSetConfig,
|
||||
}));
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
addErrorToast: mocks.addErrorToast,
|
||||
|
|
@ -29,19 +27,19 @@ describe('findActiveDhcp', () => {
|
|||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('passes { interface } not a bare string', async () => {
|
||||
mocks.findActiveDhcp.mockResolvedValue({
|
||||
mocks.checkActiveDhcp.mockResolvedValue({
|
||||
v4: { other_server: { found: 'yes' }, static_ip: { static: 'yes' } },
|
||||
v6: { other_server: {} },
|
||||
});
|
||||
await findActiveDhcp('eth0');
|
||||
expect(mocks.findActiveDhcp).toHaveBeenCalledWith({ interface: 'eth0' });
|
||||
expect(mocks.checkActiveDhcp).toHaveBeenCalledWith({ interface: 'eth0' });
|
||||
});
|
||||
|
||||
it('shows dhcp_found error with retry action when another DHCP server detected', async () => {
|
||||
mocks.getDhcpInterfaces.mockResolvedValue({
|
||||
mocks.dhcpInterfaces.mockResolvedValue({
|
||||
eth0: { ipv4_addresses: ['1.1.1.1'], ipv6_addresses: [] },
|
||||
});
|
||||
mocks.findActiveDhcp.mockResolvedValue({
|
||||
mocks.checkActiveDhcp.mockResolvedValue({
|
||||
v4: {
|
||||
other_server: { found: 'yes' },
|
||||
static_ip: { static: 'yes', ip: 'x' },
|
||||
|
|
@ -58,10 +56,10 @@ describe('findActiveDhcp', () => {
|
|||
});
|
||||
|
||||
it('shows dhcp_not_found success toast when clean', async () => {
|
||||
mocks.getDhcpInterfaces.mockResolvedValue({
|
||||
mocks.dhcpInterfaces.mockResolvedValue({
|
||||
eth0: { ipv4_addresses: ['1.1.1.1'], ipv6_addresses: [] },
|
||||
});
|
||||
mocks.findActiveDhcp.mockResolvedValue({
|
||||
mocks.checkActiveDhcp.mockResolvedValue({
|
||||
v4: {
|
||||
other_server: { found: 'no' },
|
||||
static_ip: { static: 'yes', ip: '1.1.1.1' },
|
||||
|
|
@ -77,7 +75,7 @@ describe('findActiveDhcp', () => {
|
|||
describe('setDhcpConfig', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mocks.setDhcpConfig.mockResolvedValue(undefined);
|
||||
mocks.dhcpSetConfig.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it('shows dhcp_config_saved toast (FR-010)', async () => {
|
||||
|
|
@ -92,12 +90,12 @@ describe('setDhcpConfig', () => {
|
|||
describe('toggleDhcp', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mocks.setDhcpConfig.mockResolvedValue(undefined);
|
||||
mocks.dhcpSetConfig.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it('computes enabled from passed config, not current state (FR-011)', async () => {
|
||||
await toggleDhcp({ enabled: false, interface_name: 'eth0' });
|
||||
expect(mocks.setDhcpConfig).toHaveBeenCalledWith(
|
||||
expect(mocks.dhcpSetConfig).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ enabled: true }),
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
getDnsConfig: vi.fn(),
|
||||
setDnsConfig: vi.fn(),
|
||||
dnsInfo: vi.fn(),
|
||||
dnsConfig: vi.fn(),
|
||||
addErrorToast: vi.fn(),
|
||||
addSuccessToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
getDnsConfig: mocks.getDnsConfig,
|
||||
setDnsConfig: mocks.setDnsConfig,
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
dnsInfo: mocks.dnsInfo,
|
||||
dnsConfig: mocks.dnsConfig,
|
||||
}));
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
addErrorToast: mocks.addErrorToast,
|
||||
|
|
@ -27,7 +25,7 @@ describe('getDnsConfig', () => {
|
|||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('defaults null blocking IPs and empty upstream_mode (FR-012)', async () => {
|
||||
mocks.getDnsConfig.mockResolvedValue({
|
||||
mocks.dnsInfo.mockResolvedValue({
|
||||
blocking_ipv4: null,
|
||||
blocking_ipv6: null,
|
||||
upstream_mode: '',
|
||||
|
|
@ -43,7 +41,7 @@ describe('toggleResolveClients', () => {
|
|||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('toggles resolve_clients and persists (FR-032)', async () => {
|
||||
mocks.setDnsConfig.mockResolvedValue({});
|
||||
mocks.dnsConfig.mockResolvedValue({});
|
||||
|
||||
const before = dnsConfigState.resolve_clients;
|
||||
await toggleResolveClients();
|
||||
|
|
@ -54,12 +52,12 @@ describe('toggleResolveClients', () => {
|
|||
expect(dnsConfigState.resolve_clients).toBe(before);
|
||||
});
|
||||
|
||||
it('calls apiClient.setDnsConfig with inverted value (FR-032)', async () => {
|
||||
mocks.setDnsConfig.mockResolvedValue({});
|
||||
it('calls dnsConfig with inverted value (FR-032)', async () => {
|
||||
mocks.dnsConfig.mockResolvedValue({});
|
||||
|
||||
const before = dnsConfigState.resolve_clients;
|
||||
await toggleResolveClients();
|
||||
expect(mocks.setDnsConfig).toHaveBeenCalledWith({
|
||||
expect(mocks.dnsConfig).toHaveBeenCalledWith({
|
||||
resolve_clients: !before,
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
setTlsConfig: vi.fn(),
|
||||
validateTlsConfig: vi.fn(),
|
||||
tlsConfigure: vi.fn(),
|
||||
tlsValidate: vi.fn(),
|
||||
addErrorToast: vi.fn(),
|
||||
addSuccessToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
setTlsConfig: mocks.setTlsConfig,
|
||||
validateTlsConfig: mocks.validateTlsConfig,
|
||||
getGlobalStatus: vi.fn(),
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
tlsConfigure: mocks.tlsConfigure,
|
||||
tlsValidate: mocks.tlsValidate,
|
||||
status: vi.fn(),
|
||||
}));
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
addErrorToast: mocks.addErrorToast,
|
||||
|
|
@ -31,7 +29,7 @@ describe('setTlsConfig', () => {
|
|||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('defaults empty ports to 0 (FR-013)', async () => {
|
||||
mocks.setTlsConfig.mockImplementation(async (v: any) => ({
|
||||
mocks.tlsConfigure.mockImplementation(async (v: any) => ({
|
||||
...v,
|
||||
certificate_chain: '',
|
||||
private_key: '',
|
||||
|
|
@ -43,14 +41,14 @@ describe('setTlsConfig', () => {
|
|||
port_dns_over_tls: '',
|
||||
port_dns_over_quic: '',
|
||||
});
|
||||
const sent = mocks.setTlsConfig.mock.calls[0][0];
|
||||
const sent = mocks.tlsConfigure.mock.calls[0][0];
|
||||
expect(sent.port_https).toBe(0);
|
||||
expect(sent.port_dns_over_tls).toBe(0);
|
||||
expect(sent.port_dns_over_quic).toBe(0);
|
||||
});
|
||||
|
||||
it('clears validation status fields when resetValidationStatus is called', async () => {
|
||||
mocks.validateTlsConfig.mockResolvedValue({
|
||||
mocks.tlsValidate.mockResolvedValue({
|
||||
valid_chain: true,
|
||||
valid_cert: true,
|
||||
valid_key: true,
|
||||
|
|
@ -94,7 +92,7 @@ describe('setTlsConfig', () => {
|
|||
value: { protocol: 'http:', reload: reloadFn },
|
||||
writable: true,
|
||||
});
|
||||
mocks.setTlsConfig.mockImplementation(async (v: any) => ({
|
||||
mocks.tlsConfigure.mockImplementation(async (v: any) => ({
|
||||
...v,
|
||||
certificate_chain: '',
|
||||
private_key: '',
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@ const mocks = vi.hoisted(() => ({
|
|||
addErrorToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
setRules: mocks.apiSetRules,
|
||||
addFilter: mocks.apiAddFilter,
|
||||
getFilteringStatus: mocks.apiGetFilteringStatus,
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
filteringSetRules: mocks.apiSetRules,
|
||||
filteringAddURL: mocks.apiAddFilter,
|
||||
filteringStatus: mocks.apiGetFilteringStatus,
|
||||
}));
|
||||
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@ const mocks = vi.hoisted(() => ({
|
|||
addErrorToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
setRules: mocks.apiSetRules,
|
||||
addFilter: mocks.apiAddFilter,
|
||||
getFilteringStatus: mocks.apiGetFilteringStatus,
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
filteringSetRules: mocks.apiSetRules,
|
||||
filteringAddURL: mocks.apiAddFilter,
|
||||
filteringStatus: mocks.apiGetFilteringStatus,
|
||||
}));
|
||||
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
|
|
|
|||
|
|
@ -2,12 +2,10 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|||
|
||||
// Mock the API client.
|
||||
const mockCheckConfig = vi.fn();
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
checkConfig: (...args: unknown[]) => mockCheckConfig(...args),
|
||||
getDefaultAddresses: vi.fn(),
|
||||
setAllSettings: vi.fn(),
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
installCheckConfig: (...args: unknown[]) => mockCheckConfig(...args),
|
||||
installGetAddresses: vi.fn(),
|
||||
installConfigure: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/stores/toasts', () => ({ addErrorToast: vi.fn() }));
|
||||
|
|
|
|||
|
|
@ -2,10 +2,8 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|||
|
||||
// Mock the API client before importing the store.
|
||||
const mockLogin = vi.fn().mockResolvedValue(undefined);
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
login: (...args: unknown[]) => mockLogin(...args),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock addErrorToast so it does not depend on other stores.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
||||
import { getAdditionalLogs, setFilteredLogs, queryLogsState } from 'panel/stores/queryLogs';
|
||||
import { apiClient } from 'panel/api/Api';
|
||||
import { queryLog } from 'panel/api/generated';
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
getQueryLog: vi.fn(),
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
queryLog: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
|
|
@ -19,14 +17,14 @@ describe('queryLogs store', () => {
|
|||
});
|
||||
|
||||
it('getAdditionalLogs appends filtered rows using the oldest cursor and filter', async () => {
|
||||
(apiClient.getQueryLog as any).mockReset();
|
||||
(queryLog as any).mockReset();
|
||||
|
||||
// Seed state: a full first page (20 rewritten) with more behind it.
|
||||
const fullPage = Array.from({ length: 20 }, () => ({
|
||||
reason: 'Rewrite',
|
||||
question: {},
|
||||
}));
|
||||
(apiClient.getQueryLog as any).mockResolvedValueOnce({
|
||||
(queryLog as any).mockResolvedValueOnce({
|
||||
data: fullPage,
|
||||
oldest: 'cur',
|
||||
});
|
||||
|
|
@ -35,7 +33,7 @@ describe('queryLogs store', () => {
|
|||
expect(queryLogsState.logs).toHaveLength(20);
|
||||
|
||||
// Load more: one extra rewritten entry, then end of log.
|
||||
(apiClient.getQueryLog as any).mockResolvedValueOnce({
|
||||
(queryLog as any).mockResolvedValueOnce({
|
||||
data: [{ reason: 'Rewrite', question: {} }],
|
||||
oldest: '',
|
||||
});
|
||||
|
|
@ -43,7 +41,7 @@ describe('queryLogs store', () => {
|
|||
await getAdditionalLogs();
|
||||
|
||||
// The load-more request must carry the cursor and the reason filter.
|
||||
expect(apiClient.getQueryLog).toHaveBeenLastCalledWith(
|
||||
expect(queryLog).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
older_than: 'cur',
|
||||
reason: expect.arrayContaining([
|
||||
|
|
@ -55,7 +53,7 @@ describe('queryLogs store', () => {
|
|||
}),
|
||||
);
|
||||
// Must NOT send the deprecated response_status
|
||||
const lastCall = (apiClient.getQueryLog as any).mock.calls.at(-1)[0];
|
||||
const lastCall = (queryLog as any).mock.calls.at(-1)[0];
|
||||
expect(lastCall).not.toHaveProperty('response_status');
|
||||
|
||||
expect(queryLogsState.logs).toHaveLength(21);
|
||||
|
|
@ -64,16 +62,16 @@ describe('queryLogs store', () => {
|
|||
});
|
||||
|
||||
it('setFilteredLogs sends reason strings for blocked status', async () => {
|
||||
(apiClient.getQueryLog as any).mockReset();
|
||||
(apiClient.getQueryLog as any).mockResolvedValue({
|
||||
(queryLog as any).mockReset();
|
||||
(queryLog as any).mockResolvedValue({
|
||||
data: [{ reason: 'FilteredBlackList', question: {} }],
|
||||
oldest: '',
|
||||
});
|
||||
|
||||
await setFilteredLogs({ search: '', status: 'blocked', reason: 'all' });
|
||||
|
||||
const lastCall = (apiClient.getQueryLog as any).mock.calls.at(-1)[0];
|
||||
expect(apiClient.getQueryLog).toHaveBeenLastCalledWith(
|
||||
const lastCall = (queryLog as any).mock.calls.at(-1)[0];
|
||||
expect(queryLog).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
reason: expect.arrayContaining([
|
||||
'FilteredBlackList',
|
||||
|
|
@ -87,7 +85,7 @@ describe('queryLogs store', () => {
|
|||
});
|
||||
|
||||
it('does not mark the log as complete when additional loading stops', async () => {
|
||||
(apiClient.getQueryLog as any).mockResolvedValue({
|
||||
(queryLog as any).mockResolvedValue({
|
||||
data: [],
|
||||
oldest: 'next-cursor',
|
||||
});
|
||||
|
|
@ -99,7 +97,7 @@ describe('queryLogs store', () => {
|
|||
});
|
||||
|
||||
it('accumulates pages until oldest is empty (short-polling)', async () => {
|
||||
(apiClient.getQueryLog as any)
|
||||
(queryLog as any)
|
||||
.mockResolvedValueOnce({
|
||||
data: [{ reason: 'Rewrite' }],
|
||||
oldest: 'cur',
|
||||
|
|
@ -112,7 +110,7 @@ describe('queryLogs store', () => {
|
|||
});
|
||||
|
||||
await setFilteredLogs({ search: '', status: 'rewritten', reason: 'all' });
|
||||
expect(apiClient.getQueryLog).toHaveBeenCalledTimes(2);
|
||||
expect(queryLog).toHaveBeenCalledTimes(2);
|
||||
expect(queryLogsState.processingGetLogs).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
getStats: vi.fn(),
|
||||
searchClients: vi.fn(),
|
||||
stats: vi.fn(),
|
||||
clientsSearch: vi.fn(),
|
||||
addErrorToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
getStats: mocks.getStats,
|
||||
searchClients: mocks.searchClients,
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
stats: mocks.stats,
|
||||
clientsSearch: mocks.clientsSearch,
|
||||
}));
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
addErrorToast: mocks.addErrorToast,
|
||||
|
|
@ -21,11 +19,11 @@ import { getStats, statsState } from 'panel/stores/stats';
|
|||
describe('getStats', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mocks.searchClients.mockResolvedValue([]);
|
||||
mocks.clientsSearch.mockResolvedValue([]);
|
||||
});
|
||||
|
||||
it('enriches top clients and stores normalizedTopClients (FR-001/019)', async () => {
|
||||
mocks.getStats.mockResolvedValue({
|
||||
mocks.stats.mockResolvedValue({
|
||||
top_clients: [{ '1.2.3.4': 5 }],
|
||||
avg_processing_time: 0.012,
|
||||
top_blocked_domains: [],
|
||||
|
|
@ -37,7 +35,7 @@ describe('getStats', () => {
|
|||
await getStats();
|
||||
|
||||
// searchClients was called with discovered client ids
|
||||
expect(mocks.searchClients).toHaveBeenCalledWith({
|
||||
expect(mocks.clientsSearch).toHaveBeenCalledWith({
|
||||
clients: [{ id: '1.2.3.4' }],
|
||||
});
|
||||
// normalizedTopClients is populated (configured bucket carries info name)
|
||||
|
|
@ -45,11 +43,11 @@ describe('getStats', () => {
|
|||
});
|
||||
|
||||
it('converts avg_processing_time to milliseconds, falsy passthrough (FR-002)', async () => {
|
||||
mocks.getStats.mockResolvedValue({ avg_processing_time: 0.012 });
|
||||
mocks.stats.mockResolvedValue({ avg_processing_time: 0.012 });
|
||||
await getStats();
|
||||
expect(statsState.avgProcessingTime).toBe(12);
|
||||
|
||||
mocks.getStats.mockResolvedValue({ avg_processing_time: 0 });
|
||||
mocks.stats.mockResolvedValue({ avg_processing_time: 0 });
|
||||
await getStats();
|
||||
expect(statsState.avgProcessingTime).toBe(0); // not NaN
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,11 +22,9 @@ const mocks = vi.hoisted(() => ({
|
|||
addErrorToast: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('panel/api/Api', () => ({
|
||||
apiClient: {
|
||||
setRules: mocks.apiSetRules,
|
||||
getFilteringStatus: mocks.apiGetFilteringStatus,
|
||||
},
|
||||
vi.mock('panel/api/generated', () => ({
|
||||
filteringSetRules: mocks.apiSetRules,
|
||||
filteringStatus: mocks.apiGetFilteringStatus,
|
||||
}));
|
||||
|
||||
vi.mock('panel/stores/toasts', () => ({
|
||||
|
|
|
|||
|
|
@ -1,746 +0,0 @@
|
|||
import type { LocalesType } from 'panel/common/intl';
|
||||
|
||||
const BASE_URL = 'control';
|
||||
|
||||
import { getPathWithQueryString } from '../helpers/helpers';
|
||||
import { QUERY_LOGS_PAGE_LIMIT, HTML_PAGES, R_PATH_LAST_PART, THEMES } from '../helpers/constants';
|
||||
import intl from '../common/intl';
|
||||
|
||||
type Theme = (typeof THEMES)[keyof typeof THEMES];
|
||||
|
||||
class Api {
|
||||
baseUrl: string;
|
||||
|
||||
constructor(baseUrl: string) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
async makeRequest(path: any, method = 'POST', config: any = {}) {
|
||||
const pathWithBase = `${this.baseUrl}/${path}`;
|
||||
const url = config.params
|
||||
? getPathWithQueryString(pathWithBase, config.params)
|
||||
: pathWithBase;
|
||||
|
||||
const fetchConfig: RequestInit = { method };
|
||||
const headers: Record<string, string> = {};
|
||||
|
||||
if (method !== 'GET' && config.data) {
|
||||
headers['Content-Type'] = config.headers?.['Content-Type'] || 'application/json';
|
||||
fetchConfig.body =
|
||||
typeof config.data === 'string' ? config.data : JSON.stringify(config.data);
|
||||
}
|
||||
|
||||
fetchConfig.headers = headers;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, fetchConfig);
|
||||
const text = await response.text();
|
||||
const data = text
|
||||
? (() => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch {
|
||||
return text;
|
||||
}
|
||||
})()
|
||||
: '';
|
||||
|
||||
if (!response.ok) {
|
||||
const errorPath = url;
|
||||
const { pathname } = document.location;
|
||||
const shouldRedirect =
|
||||
pathname !== HTML_PAGES.LOGIN && pathname !== HTML_PAGES.INSTALL;
|
||||
|
||||
if (response.status === 403 && shouldRedirect) {
|
||||
const loginPageUrl = window.location.href.replace(
|
||||
R_PATH_LAST_PART,
|
||||
HTML_PAGES.LOGIN,
|
||||
);
|
||||
window.location.replace(loginPageUrl);
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new Error(`${errorPath} | ${data} | ${response.status}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
const errorPath = url;
|
||||
|
||||
if (error instanceof Error && error.message.includes('|')) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new Error(`${errorPath} | ${error.message || error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Global methods
|
||||
GLOBAL_STATUS = { path: 'status', method: 'GET' };
|
||||
|
||||
GLOBAL_TEST_UPSTREAM_DNS = { path: 'test_upstream_dns', method: 'POST' };
|
||||
|
||||
GLOBAL_VERSION = { path: 'version.json', method: 'POST' };
|
||||
|
||||
GLOBAL_UPDATE = { path: 'update', method: 'POST' };
|
||||
|
||||
getGlobalStatus() {
|
||||
const { path, method } = this.GLOBAL_STATUS;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
testUpstream(servers: any) {
|
||||
const { path, method } = this.GLOBAL_TEST_UPSTREAM_DNS;
|
||||
const config = {
|
||||
data: servers,
|
||||
};
|
||||
return this.makeRequest(path, method, config);
|
||||
}
|
||||
|
||||
getGlobalVersion(data: any) {
|
||||
const { path, method } = this.GLOBAL_VERSION;
|
||||
const config = {
|
||||
data,
|
||||
};
|
||||
return this.makeRequest(path, method, config);
|
||||
}
|
||||
|
||||
getUpdate() {
|
||||
const { path, method } = this.GLOBAL_UPDATE;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
// Filtering
|
||||
FILTERING_STATUS = { path: 'filtering/status', method: 'GET' };
|
||||
|
||||
FILTERING_ADD_FILTER = { path: 'filtering/add_url', method: 'POST' };
|
||||
|
||||
FILTERING_REMOVE_FILTER = { path: 'filtering/remove_url', method: 'POST' };
|
||||
|
||||
FILTERING_SET_RULES = { path: 'filtering/set_rules', method: 'POST' };
|
||||
|
||||
FILTERING_REFRESH = { path: 'filtering/refresh', method: 'POST' };
|
||||
|
||||
FILTERING_SET_URL = { path: 'filtering/set_url', method: 'POST' };
|
||||
|
||||
FILTERING_CONFIG = { path: 'filtering/config', method: 'POST' };
|
||||
|
||||
FILTERING_CHECK_HOST = { path: 'filtering/check_host', method: 'GET' };
|
||||
|
||||
getFilteringStatus() {
|
||||
const { path, method } = this.FILTERING_STATUS;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
refreshFilters(config: any) {
|
||||
const { path, method } = this.FILTERING_REFRESH;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
addFilter(config: any) {
|
||||
const { path, method } = this.FILTERING_ADD_FILTER;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
removeFilter(config: any) {
|
||||
const { path, method } = this.FILTERING_REMOVE_FILTER;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
setRules(rules: any) {
|
||||
const { path, method } = this.FILTERING_SET_RULES;
|
||||
const parameters = {
|
||||
data: rules,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
setFiltersConfig(config: any) {
|
||||
const { path, method } = this.FILTERING_CONFIG;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
setFilterUrl(config: any) {
|
||||
const { path, method } = this.FILTERING_SET_URL;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
checkHost(params: any) {
|
||||
const { path, method } = this.FILTERING_CHECK_HOST;
|
||||
const url = getPathWithQueryString(path, params);
|
||||
|
||||
return this.makeRequest(url, method);
|
||||
}
|
||||
|
||||
// Parental
|
||||
PARENTAL_STATUS = { path: 'parental/status', method: 'GET' };
|
||||
|
||||
PARENTAL_ENABLE = { path: 'parental/enable', method: 'POST' };
|
||||
|
||||
PARENTAL_DISABLE = { path: 'parental/disable', method: 'POST' };
|
||||
|
||||
getParentalStatus() {
|
||||
const { path, method } = this.PARENTAL_STATUS;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
enableParentalControl() {
|
||||
const { path, method } = this.PARENTAL_ENABLE;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
disableParentalControl() {
|
||||
const { path, method } = this.PARENTAL_DISABLE;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
// Safebrowsing
|
||||
SAFEBROWSING_STATUS = { path: 'safebrowsing/status', method: 'GET' };
|
||||
|
||||
SAFEBROWSING_ENABLE = { path: 'safebrowsing/enable', method: 'POST' };
|
||||
|
||||
SAFEBROWSING_DISABLE = { path: 'safebrowsing/disable', method: 'POST' };
|
||||
|
||||
getSafebrowsingStatus() {
|
||||
const { path, method } = this.SAFEBROWSING_STATUS;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
enableSafebrowsing() {
|
||||
const { path, method } = this.SAFEBROWSING_ENABLE;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
disableSafebrowsing() {
|
||||
const { path, method } = this.SAFEBROWSING_DISABLE;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
// Safesearch
|
||||
SAFESEARCH_STATUS = { path: 'safesearch/status', method: 'GET' };
|
||||
|
||||
SAFESEARCH_UPDATE = { path: 'safesearch/settings', method: 'PUT' };
|
||||
|
||||
getSafesearchStatus() {
|
||||
const { path, method } = this.SAFESEARCH_STATUS;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
/**
|
||||
* interface SafeSearchConfig {
|
||||
"enabled": boolean,
|
||||
"bing": boolean,
|
||||
"duckduckgo": boolean,
|
||||
"google": boolean,
|
||||
"pixabay": boolean,
|
||||
"yandex": boolean,
|
||||
"youtube": boolean
|
||||
* }
|
||||
* @param {*} data - SafeSearchConfig
|
||||
* @returns 200 ok
|
||||
*/
|
||||
updateSafesearch(data: any) {
|
||||
const { path, method } = this.SAFESEARCH_UPDATE;
|
||||
return this.makeRequest(path, method, { data });
|
||||
}
|
||||
|
||||
// enableSafesearch() {
|
||||
// const { path, method } = this.SAFESEARCH_ENABLE;
|
||||
// return this.makeRequest(path, method);
|
||||
// }
|
||||
|
||||
// disableSafesearch() {
|
||||
// const { path, method } = this.SAFESEARCH_DISABLE;
|
||||
// return this.makeRequest(path, method);
|
||||
// }
|
||||
|
||||
// Language
|
||||
async changeLanguage(config: { language: LocalesType }) {
|
||||
const profile = await this.getProfile();
|
||||
profile.language = config.language;
|
||||
|
||||
return this.setProfile(profile);
|
||||
}
|
||||
|
||||
// Theme
|
||||
async changeTheme(config: { theme: Theme }) {
|
||||
const profile = await this.getProfile();
|
||||
profile.theme = config.theme;
|
||||
|
||||
return this.setProfile(profile);
|
||||
}
|
||||
|
||||
// DHCP
|
||||
DHCP_STATUS = { path: 'dhcp/status', method: 'GET' };
|
||||
|
||||
DHCP_SET_CONFIG = { path: 'dhcp/set_config', method: 'POST' };
|
||||
|
||||
DHCP_FIND_ACTIVE = { path: 'dhcp/find_active_dhcp', method: 'POST' };
|
||||
|
||||
DHCP_INTERFACES = { path: 'dhcp/interfaces', method: 'GET' };
|
||||
|
||||
DHCP_ADD_STATIC_LEASE = { path: 'dhcp/add_static_lease', method: 'POST' };
|
||||
|
||||
DHCP_REMOVE_STATIC_LEASE = { path: 'dhcp/remove_static_lease', method: 'POST' };
|
||||
|
||||
DHCP_UPDATE_STATIC_LEASE = { path: 'dhcp/update_static_lease', method: 'POST' };
|
||||
|
||||
DHCP_RESET = { path: 'dhcp/reset', method: 'POST' };
|
||||
|
||||
DHCP_LEASES_RESET = { path: 'dhcp/reset_leases', method: 'POST' };
|
||||
|
||||
getDhcpStatus() {
|
||||
const { path, method } = this.DHCP_STATUS;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
getDhcpInterfaces() {
|
||||
const { path, method } = this.DHCP_INTERFACES;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
setDhcpConfig(config: any) {
|
||||
const { path, method } = this.DHCP_SET_CONFIG;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
findActiveDhcp(req: any) {
|
||||
const { path, method } = this.DHCP_FIND_ACTIVE;
|
||||
const parameters = {
|
||||
data: req,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
addStaticLease(config: any) {
|
||||
const { path, method } = this.DHCP_ADD_STATIC_LEASE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
removeStaticLease(config: any) {
|
||||
const { path, method } = this.DHCP_REMOVE_STATIC_LEASE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
updateStaticLease(config: any) {
|
||||
const { path, method } = this.DHCP_UPDATE_STATIC_LEASE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
resetDhcp() {
|
||||
const { path, method } = this.DHCP_RESET;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
resetDhcpLeases() {
|
||||
const { path, method } = this.DHCP_LEASES_RESET;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
// Installation
|
||||
INSTALL_GET_ADDRESSES = { path: 'install/get_addresses', method: 'GET' };
|
||||
|
||||
INSTALL_CONFIGURE = { path: 'install/configure', method: 'POST' };
|
||||
|
||||
INSTALL_CHECK_CONFIG = { path: 'install/check_config', method: 'POST' };
|
||||
|
||||
getDefaultAddresses() {
|
||||
const { path, method } = this.INSTALL_GET_ADDRESSES;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
setAllSettings(config: any) {
|
||||
const { path, method } = this.INSTALL_CONFIGURE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
checkConfig(config: any) {
|
||||
const { path, method } = this.INSTALL_CHECK_CONFIG;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
// DNS-over-HTTPS and DNS-over-TLS
|
||||
TLS_STATUS = { path: 'tls/status', method: 'GET' };
|
||||
|
||||
TLS_CONFIG = { path: 'tls/configure', method: 'POST' };
|
||||
|
||||
TLS_VALIDATE = { path: 'tls/validate', method: 'POST' };
|
||||
|
||||
getTlsStatus() {
|
||||
const { path, method } = this.TLS_STATUS;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
setTlsConfig(config: any) {
|
||||
const { path, method } = this.TLS_CONFIG;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
validateTlsConfig(config: any) {
|
||||
const { path, method } = this.TLS_VALIDATE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
// Per-client settings
|
||||
GET_CLIENTS = { path: 'clients', method: 'GET' };
|
||||
|
||||
SEARCH_CLIENTS = { path: 'clients/search', method: 'POST' };
|
||||
|
||||
ADD_CLIENT = { path: 'clients/add', method: 'POST' };
|
||||
|
||||
DELETE_CLIENT = { path: 'clients/delete', method: 'POST' };
|
||||
|
||||
UPDATE_CLIENT = { path: 'clients/update', method: 'POST' };
|
||||
|
||||
getClients() {
|
||||
const { path, method } = this.GET_CLIENTS;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
addClient(config: any) {
|
||||
const { path, method } = this.ADD_CLIENT;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
deleteClient(config: any) {
|
||||
const { path, method } = this.DELETE_CLIENT;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
updateClient(config: any) {
|
||||
const { path, method } = this.UPDATE_CLIENT;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
searchClients(config: any) {
|
||||
const { path, method } = this.SEARCH_CLIENTS;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
// DNS access settings
|
||||
ACCESS_LIST = { path: 'access/list', method: 'GET' };
|
||||
|
||||
ACCESS_SET = { path: 'access/set', method: 'POST' };
|
||||
|
||||
getAccessList() {
|
||||
const { path, method } = this.ACCESS_LIST;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
setAccessList(config: any) {
|
||||
const { path, method } = this.ACCESS_SET;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
// DNS rewrites
|
||||
REWRITES_LIST = { path: 'rewrite/list', method: 'GET' };
|
||||
|
||||
REWRITE_ADD = { path: 'rewrite/add', method: 'POST' };
|
||||
|
||||
REWRITE_UPDATE = { path: 'rewrite/update', method: 'PUT' };
|
||||
|
||||
REWRITE_DELETE = { path: 'rewrite/delete', method: 'POST' };
|
||||
|
||||
getRewritesList() {
|
||||
const { path, method } = this.REWRITES_LIST;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
addRewrite(config: any) {
|
||||
const { path, method } = this.REWRITE_ADD;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
updateRewrite(config: any) {
|
||||
const { path, method } = this.REWRITE_UPDATE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
deleteRewrite(config: any) {
|
||||
const { path, method } = this.REWRITE_DELETE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
REWRITE_SETTINGS = { path: 'rewrite/settings', method: 'GET' };
|
||||
|
||||
REWRITE_SETTINGS_UPDATE = { path: 'rewrite/settings/update', method: 'PUT' };
|
||||
|
||||
getRewriteSettings() {
|
||||
const { path, method } = this.REWRITE_SETTINGS;
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
updateRewriteSettings(config: { enabled: boolean }) {
|
||||
const { path, method } = this.REWRITE_SETTINGS_UPDATE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
// Blocked services
|
||||
BLOCKED_SERVICES_GET = { path: 'blocked_services/get', method: 'GET' };
|
||||
|
||||
BLOCKED_SERVICES_UPDATE = { path: 'blocked_services/update', method: 'PUT' };
|
||||
|
||||
BLOCKED_SERVICES_ALL = { path: 'blocked_services/all', method: 'GET' };
|
||||
|
||||
getAllBlockedServices() {
|
||||
const { path, method } = this.BLOCKED_SERVICES_ALL;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
getBlockedServices() {
|
||||
const { path, method } = this.BLOCKED_SERVICES_GET;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
updateBlockedServices(config: any) {
|
||||
const { path, method } = this.BLOCKED_SERVICES_UPDATE;
|
||||
const parameters = {
|
||||
data: config,
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
// Settings for statistics
|
||||
GET_STATS = { path: 'stats', method: 'GET' };
|
||||
|
||||
GET_STATS_CONFIG = { path: 'stats/config', method: 'GET' };
|
||||
|
||||
UPDATE_STATS_CONFIG = { path: 'stats/config/update', method: 'PUT' };
|
||||
|
||||
STATS_RESET = { path: 'stats_reset', method: 'POST' };
|
||||
|
||||
getStats(recent?: number) {
|
||||
const { path, method } = this.GET_STATS;
|
||||
const config = recent ? { params: { recent } } : undefined;
|
||||
|
||||
return this.makeRequest(path, method, config);
|
||||
}
|
||||
|
||||
getStatsConfig() {
|
||||
const { path, method } = this.GET_STATS_CONFIG;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
setStatsConfig(data: any) {
|
||||
const { path, method } = this.UPDATE_STATS_CONFIG;
|
||||
const config = {
|
||||
data,
|
||||
};
|
||||
return this.makeRequest(path, method, config);
|
||||
}
|
||||
|
||||
resetStats() {
|
||||
const { path, method } = this.STATS_RESET;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
// Query log
|
||||
GET_QUERY_LOG = { path: 'querylog', method: 'GET' };
|
||||
|
||||
UPDATE_QUERY_LOG_CONFIG = { path: 'querylog/config/update', method: 'PUT' };
|
||||
|
||||
GET_QUERY_LOG_CONFIG = { path: 'querylog/config', method: 'GET' };
|
||||
|
||||
QUERY_LOG_CLEAR = { path: 'querylog_clear', method: 'POST' };
|
||||
|
||||
getQueryLog(params: any) {
|
||||
const { path, method } = this.GET_QUERY_LOG;
|
||||
const url = getPathWithQueryString(path, {
|
||||
...params,
|
||||
limit: QUERY_LOGS_PAGE_LIMIT,
|
||||
});
|
||||
|
||||
return this.makeRequest(url, method);
|
||||
}
|
||||
|
||||
getQueryLogConfig() {
|
||||
const { path, method } = this.GET_QUERY_LOG_CONFIG;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
setQueryLogConfig(data: any) {
|
||||
const { path, method } = this.UPDATE_QUERY_LOG_CONFIG;
|
||||
const config = {
|
||||
data,
|
||||
};
|
||||
return this.makeRequest(path, method, config);
|
||||
}
|
||||
|
||||
clearQueryLog() {
|
||||
const { path, method } = this.QUERY_LOG_CLEAR;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
// Login
|
||||
LOGIN = { path: 'login', method: 'POST' };
|
||||
|
||||
login(data: any) {
|
||||
const { path, method } = this.LOGIN;
|
||||
const config = {
|
||||
data,
|
||||
};
|
||||
return this.makeRequest(path, method, config);
|
||||
}
|
||||
|
||||
// Logout
|
||||
LOGOUT_PATH = 'logout';
|
||||
|
||||
getLogoutUrl() {
|
||||
return `${this.baseUrl}/${this.LOGOUT_PATH}`;
|
||||
}
|
||||
|
||||
// Profile
|
||||
GET_PROFILE = { path: 'profile', method: 'GET' };
|
||||
|
||||
UPDATE_PROFILE = { path: 'profile/update', method: 'PUT' };
|
||||
|
||||
getProfile() {
|
||||
const { path, method } = this.GET_PROFILE;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
setProfile(data: any) {
|
||||
const theme = data.theme ? data.theme : THEMES.auto;
|
||||
const defaultLanguage = intl.getUILanguage() ? intl.getUILanguage() : 'en';
|
||||
const language = data.language ? data.language : defaultLanguage;
|
||||
|
||||
const { path, method } = this.UPDATE_PROFILE;
|
||||
const config = { data: { theme, language } };
|
||||
|
||||
return this.makeRequest(path, method, config);
|
||||
}
|
||||
|
||||
// DNS config
|
||||
GET_DNS_CONFIG = { path: 'dns_info', method: 'GET' };
|
||||
|
||||
SET_DNS_CONFIG = { path: 'dns_config', method: 'POST' };
|
||||
|
||||
getDnsConfig() {
|
||||
const { path, method } = this.GET_DNS_CONFIG;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
|
||||
setDnsConfig(data: any) {
|
||||
const { path, method } = this.SET_DNS_CONFIG;
|
||||
const config = {
|
||||
data,
|
||||
};
|
||||
return this.makeRequest(path, method, config);
|
||||
}
|
||||
|
||||
SET_PROTECTION = { path: 'protection', method: 'POST' };
|
||||
|
||||
setProtection(data: any) {
|
||||
const { enabled, duration } = data;
|
||||
const { path, method } = this.SET_PROTECTION;
|
||||
|
||||
return this.makeRequest(path, method, { data: { enabled, duration } });
|
||||
}
|
||||
|
||||
// Cache
|
||||
CLEAR_CACHE = { path: 'cache_clear', method: 'POST' };
|
||||
|
||||
clearCache() {
|
||||
const { path, method } = this.CLEAR_CACHE;
|
||||
|
||||
return this.makeRequest(path, method);
|
||||
}
|
||||
}
|
||||
|
||||
export const apiClient = new Api(BASE_URL);
|
||||
78
client_v2/src/api/customFetch.ts
Normal file
78
client_v2/src/api/customFetch.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import { HTML_PAGES, R_PATH_LAST_PART } from '../helpers/constants';
|
||||
|
||||
type CustomFetchOptions = RequestInit & {
|
||||
skipAuthRedirect?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom fetch mutator for orval-generated API client.
|
||||
*
|
||||
* Custom fetch wrapper providing AdGuard Home-specific behaviors:
|
||||
* - Sets `Content-Type: application/json` on requests with a body
|
||||
* - Parses response as JSON (falls back to raw text if JSON.parse fails)
|
||||
* - On 403 and not on login/install page → redirects browser to login
|
||||
* and returns `false` (does not throw)
|
||||
* - On 403 while on login/install page → throws Error normally
|
||||
* - Throws Error with format `${path} | ${data} | ${status}` for all
|
||||
* other non-ok responses
|
||||
* - On empty response body → returns empty string ''
|
||||
* - On 204 → returns empty string ''
|
||||
*/
|
||||
export const customFetch = async <T>(url: string, options?: CustomFetchOptions): Promise<T> => {
|
||||
const { skipAuthRedirect, ...fetchOptions } = options || {};
|
||||
|
||||
const fullUrl = url;
|
||||
const headers: Record<string, string> = {};
|
||||
|
||||
// Preserve any headers passed in options
|
||||
if (fetchOptions.headers) {
|
||||
const incomingHeaders = fetchOptions.headers as Record<string, string>;
|
||||
Object.assign(headers, incomingHeaders);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(fullUrl, {
|
||||
...fetchOptions,
|
||||
headers,
|
||||
});
|
||||
|
||||
const text = await response.text();
|
||||
const data: T = text
|
||||
? (() => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch {
|
||||
return text;
|
||||
}
|
||||
})()
|
||||
: ('' as unknown as T);
|
||||
|
||||
if (!response.ok) {
|
||||
const { pathname } = document.location;
|
||||
const shouldRedirect = pathname !== HTML_PAGES.LOGIN && pathname !== HTML_PAGES.INSTALL;
|
||||
|
||||
if (response.status === 403 && shouldRedirect && !skipAuthRedirect) {
|
||||
const loginPageUrl = window.location.href.replace(
|
||||
R_PATH_LAST_PART,
|
||||
HTML_PAGES.LOGIN,
|
||||
);
|
||||
window.location.replace(loginPageUrl);
|
||||
return false as unknown as T;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`${fullUrl} | ${typeof data === 'string' ? data : JSON.stringify(data)} | ${response.status}`,
|
||||
);
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message.includes('|')) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new Error(`${fullUrl} | ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
};
|
||||
|
||||
export default customFetch;
|
||||
1513
client_v2/src/api/generated.ts
Normal file
1513
client_v2/src/api/generated.ts
Normal file
File diff suppressed because it is too large
Load diff
11
client_v2/src/api/model/accessList.ts
Normal file
11
client_v2/src/api/model/accessList.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Client and host access list. Each of the lists should contain only unique elements. In addition, allowed and disallowed lists cannot contain the same elements.
|
||||
*/
|
||||
export interface AccessList {
|
||||
/** The allowlist of clients: IP addresses, CIDRs, or ClientIDs. */
|
||||
allowed_clients?: string[];
|
||||
/** The blocklist of clients: IP addresses, CIDRs, or ClientIDs. */
|
||||
disallowed_clients?: string[];
|
||||
/** The blocklist of hosts. */
|
||||
blocked_hosts?: string[];
|
||||
}
|
||||
3
client_v2/src/api/model/accessListResponse.ts
Normal file
3
client_v2/src/api/model/accessListResponse.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { AccessList } from './accessList';
|
||||
|
||||
export type AccessListResponse = AccessList;
|
||||
3
client_v2/src/api/model/accessSetRequest.ts
Normal file
3
client_v2/src/api/model/accessSetRequest.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { AccessList } from './accessList';
|
||||
|
||||
export type AccessSetRequest = AccessList;
|
||||
9
client_v2/src/api/model/addUrlRequest.ts
Normal file
9
client_v2/src/api/model/addUrlRequest.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* /add_url request data
|
||||
*/
|
||||
export interface AddUrlRequest {
|
||||
name?: string;
|
||||
/** URL or an absolute path to the file containing filtering rules. */
|
||||
url?: string;
|
||||
whitelist?: boolean;
|
||||
}
|
||||
7
client_v2/src/api/model/addressInfo.ts
Normal file
7
client_v2/src/api/model/addressInfo.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Port information
|
||||
*/
|
||||
export interface AddressInfo {
|
||||
ip: string;
|
||||
port: number;
|
||||
}
|
||||
11
client_v2/src/api/model/addressesInfo.ts
Normal file
11
client_v2/src/api/model/addressesInfo.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import type { NetInterfaces } from './netInterfaces';
|
||||
|
||||
/**
|
||||
* AdGuard Home addresses configuration
|
||||
*/
|
||||
export interface AddressesInfo {
|
||||
dns_port: number;
|
||||
interfaces: NetInterfaces;
|
||||
version: string;
|
||||
web_port: number;
|
||||
}
|
||||
12
client_v2/src/api/model/blockedService.ts
Normal file
12
client_v2/src/api/model/blockedService.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
export interface BlockedService {
|
||||
/** The SVG icon as a Base64-encoded string to make it easier to embed it into a data URL. */
|
||||
icon_svg: string;
|
||||
/** The ID of this service. */
|
||||
id: string;
|
||||
/** The human-readable name of this service. */
|
||||
name: string;
|
||||
/** The array of the filtering rules. */
|
||||
rules: string[];
|
||||
/** The ID of the group, that the service belongs to. */
|
||||
group_id?: string;
|
||||
}
|
||||
7
client_v2/src/api/model/blockedServicesAll.ts
Normal file
7
client_v2/src/api/model/blockedServicesAll.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import type { BlockedService } from './blockedService';
|
||||
import type { ServiceGroup } from './serviceGroup';
|
||||
|
||||
export interface BlockedServicesAll {
|
||||
blocked_services: BlockedService[];
|
||||
groups: ServiceGroup[];
|
||||
}
|
||||
1
client_v2/src/api/model/blockedServicesArray.ts
Normal file
1
client_v2/src/api/model/blockedServicesArray.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export type BlockedServicesArray = string[];
|
||||
7
client_v2/src/api/model/blockedServicesSchedule.ts
Normal file
7
client_v2/src/api/model/blockedServicesSchedule.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import type { Schedule } from './schedule';
|
||||
|
||||
export interface BlockedServicesSchedule {
|
||||
schedule?: Schedule;
|
||||
/** The names of the blocked services. */
|
||||
ids?: string[];
|
||||
}
|
||||
12
client_v2/src/api/model/checkConfigRequest.ts
Normal file
12
client_v2/src/api/model/checkConfigRequest.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import type { CheckConfigRequestInfo } from './checkConfigRequestInfo';
|
||||
import type { Lang } from './lang';
|
||||
|
||||
/**
|
||||
* Configuration to be checked
|
||||
*/
|
||||
export interface CheckConfigRequest {
|
||||
dns?: CheckConfigRequestInfo;
|
||||
language?: Lang;
|
||||
set_static_ip?: boolean;
|
||||
web?: CheckConfigRequestInfo;
|
||||
}
|
||||
5
client_v2/src/api/model/checkConfigRequestInfo.ts
Normal file
5
client_v2/src/api/model/checkConfigRequestInfo.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export interface CheckConfigRequestInfo {
|
||||
ip?: string;
|
||||
port?: number;
|
||||
autofix?: boolean;
|
||||
}
|
||||
9
client_v2/src/api/model/checkConfigResponse.ts
Normal file
9
client_v2/src/api/model/checkConfigResponse.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import type { CheckConfigResponseInfo } from './checkConfigResponseInfo';
|
||||
import type { CheckConfigStaticIpInfo } from './checkConfigStaticIpInfo';
|
||||
|
||||
export interface CheckConfigResponse {
|
||||
dns: CheckConfigResponseInfo;
|
||||
language: CheckConfigResponseInfo;
|
||||
static_ip: CheckConfigStaticIpInfo;
|
||||
web: CheckConfigResponseInfo;
|
||||
}
|
||||
4
client_v2/src/api/model/checkConfigResponseInfo.ts
Normal file
4
client_v2/src/api/model/checkConfigResponseInfo.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export interface CheckConfigResponseInfo {
|
||||
status: string;
|
||||
can_autofix: boolean;
|
||||
}
|
||||
9
client_v2/src/api/model/checkConfigStaticIpInfo.ts
Normal file
9
client_v2/src/api/model/checkConfigStaticIpInfo.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import type { CheckConfigStaticIpInfoStatic } from './checkConfigStaticIpInfoStatic';
|
||||
|
||||
export interface CheckConfigStaticIpInfo {
|
||||
static?: CheckConfigStaticIpInfoStatic;
|
||||
/** Current dynamic IP address. Set if static=no */
|
||||
ip?: string;
|
||||
/** Error text. Set if static=error */
|
||||
error?: string;
|
||||
}
|
||||
4
client_v2/src/api/model/checkConfigStaticIpInfoStatic.ts
Normal file
4
client_v2/src/api/model/checkConfigStaticIpInfoStatic.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Can be: yes, no, error
|
||||
*/
|
||||
export type CheckConfigStaticIpInfoStatic = 'yes' | 'no' | 'error';
|
||||
63
client_v2/src/api/model/client.ts
Normal file
63
client_v2/src/api/model/client.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import type { SafeSearchConfig } from './safeSearchConfig';
|
||||
import type { Schedule } from './schedule';
|
||||
|
||||
/**
|
||||
* Client information.
|
||||
*/
|
||||
export interface Client {
|
||||
/** Name */
|
||||
name?: string;
|
||||
/** IP, CIDR, MAC, or ClientID. */
|
||||
ids?: string[];
|
||||
use_global_settings?: boolean;
|
||||
filtering_enabled?: boolean;
|
||||
parental_enabled?: boolean;
|
||||
safebrowsing_enabled?: boolean;
|
||||
/** @deprecated */
|
||||
safesearch_enabled?: boolean;
|
||||
safe_search?: SafeSearchConfig;
|
||||
use_global_blocked_services?: boolean;
|
||||
blocked_services_schedule?: Schedule;
|
||||
blocked_services?: string[];
|
||||
upstreams?: string[];
|
||||
tags?: string[];
|
||||
/**
|
||||
* NOTE: If `ignore_querylog` is not set in HTTP API `GET /clients/add`
|
||||
* request then default value (false) will be used.
|
||||
*
|
||||
* If `ignore_querylog` is not set in HTTP API `GET /clients/update`
|
||||
* request then the existing value will not be changed.
|
||||
*
|
||||
* This behaviour can be changed in the future versions.
|
||||
*/
|
||||
ignore_querylog?: boolean;
|
||||
/**
|
||||
* NOTE: If `ignore_statistics` is not set in HTTP API `GET
|
||||
* /clients/add` request then default value (false) will be used.
|
||||
*
|
||||
* If `ignore_statistics` is not set in HTTP API `GET /clients/update`
|
||||
* request then the existing value will not be changed.
|
||||
*
|
||||
* This behaviour can be changed in the future versions.
|
||||
*/
|
||||
ignore_statistics?: boolean;
|
||||
/**
|
||||
* NOTE: If `upstreams_cache_enabled` is not set in HTTP API
|
||||
* `GET /clients/add` request then default value (false) will be used.
|
||||
*
|
||||
* If `upstreams_cache_enabled` is not set in HTTP API
|
||||
* `GET /clients/update` request then the existing value will not be
|
||||
* changed.
|
||||
*
|
||||
* This behaviour can be changed in the future versions.
|
||||
*/
|
||||
upstreams_cache_enabled?: boolean;
|
||||
/**
|
||||
* NOTE: If `upstreams_cache_enabled` is not set in HTTP API
|
||||
* `GET /clients/update` request then the existing value will not be
|
||||
* changed.
|
||||
*
|
||||
* This behaviour can be changed in the future versions.
|
||||
*/
|
||||
upstreams_cache_size?: number;
|
||||
}
|
||||
14
client_v2/src/api/model/clientAuto.ts
Normal file
14
client_v2/src/api/model/clientAuto.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import type { WhoisInfo } from './whoisInfo';
|
||||
|
||||
/**
|
||||
* Auto-Client information
|
||||
*/
|
||||
export interface ClientAuto {
|
||||
/** IP address */
|
||||
ip?: string;
|
||||
/** Name */
|
||||
name?: string;
|
||||
/** The source of this information */
|
||||
source?: string;
|
||||
whois_info?: WhoisInfo;
|
||||
}
|
||||
6
client_v2/src/api/model/clientDelete.ts
Normal file
6
client_v2/src/api/model/clientDelete.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* Client delete request
|
||||
*/
|
||||
export interface ClientDelete {
|
||||
name?: string;
|
||||
}
|
||||
29
client_v2/src/api/model/clientFindSubEntry.ts
Normal file
29
client_v2/src/api/model/clientFindSubEntry.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import type { SafeSearchConfig } from './safeSearchConfig';
|
||||
import type { WhoisInfo } from './whoisInfo';
|
||||
|
||||
/**
|
||||
* Client information.
|
||||
*/
|
||||
export interface ClientFindSubEntry {
|
||||
/** Name */
|
||||
name?: string;
|
||||
/** IP, CIDR, MAC, or ClientID. */
|
||||
ids?: string[];
|
||||
use_global_settings?: boolean;
|
||||
filtering_enabled?: boolean;
|
||||
parental_enabled?: boolean;
|
||||
safebrowsing_enabled?: boolean;
|
||||
/** @deprecated */
|
||||
safesearch_enabled?: boolean;
|
||||
safe_search?: SafeSearchConfig;
|
||||
use_global_blocked_services?: boolean;
|
||||
blocked_services?: string[];
|
||||
upstreams?: string[];
|
||||
whois_info?: WhoisInfo;
|
||||
/** Whether the client's IP is blocked or not. */
|
||||
disallowed?: boolean;
|
||||
/** The rule due to which the client is disallowed. If disallowed is set to true, and this string is empty, then the client IP is disallowed by the "allowed IP list", that is it is not included in the allowed list. */
|
||||
disallowed_rule?: string;
|
||||
ignore_querylog?: boolean;
|
||||
ignore_statistics?: boolean;
|
||||
}
|
||||
9
client_v2/src/api/model/clientUpdate.ts
Normal file
9
client_v2/src/api/model/clientUpdate.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import type { Client } from './client';
|
||||
|
||||
/**
|
||||
* Client update request
|
||||
*/
|
||||
export interface ClientUpdate {
|
||||
name?: string;
|
||||
data?: Client;
|
||||
}
|
||||
8
client_v2/src/api/model/clients.ts
Normal file
8
client_v2/src/api/model/clients.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import type { ClientsArray } from './clientsArray';
|
||||
import type { ClientsAutoArray } from './clientsAutoArray';
|
||||
|
||||
export interface Clients {
|
||||
clients?: ClientsArray;
|
||||
auto_clients?: ClientsAutoArray;
|
||||
supported_tags?: string[];
|
||||
}
|
||||
6
client_v2/src/api/model/clientsArray.ts
Normal file
6
client_v2/src/api/model/clientsArray.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import type { Client } from './client';
|
||||
|
||||
/**
|
||||
* Clients array
|
||||
*/
|
||||
export type ClientsArray = Client[];
|
||||
6
client_v2/src/api/model/clientsAutoArray.ts
Normal file
6
client_v2/src/api/model/clientsAutoArray.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import type { ClientAuto } from './clientAuto';
|
||||
|
||||
/**
|
||||
* Auto-Clients array
|
||||
*/
|
||||
export type ClientsAutoArray = ClientAuto[];
|
||||
5
client_v2/src/api/model/clientsFindEntry.ts
Normal file
5
client_v2/src/api/model/clientsFindEntry.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import type { ClientFindSubEntry } from './clientFindSubEntry';
|
||||
|
||||
export interface ClientsFindEntry {
|
||||
[key: string]: ClientFindSubEntry;
|
||||
}
|
||||
7
client_v2/src/api/model/clientsFindParams.ts
Normal file
7
client_v2/src/api/model/clientsFindParams.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export type ClientsFindParams = {
|
||||
/**
|
||||
* Filter by IP address or ClientIDs. Parameters with names `ip1`, `ip2`, and so on are also accepted and interpreted as "ip0 OR ip1 OR ip2".
|
||||
* TODO(a.garipov): Replace with a better query API.
|
||||
*/
|
||||
ip0?: string;
|
||||
};
|
||||
6
client_v2/src/api/model/clientsFindResponse.ts
Normal file
6
client_v2/src/api/model/clientsFindResponse.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import type { ClientsFindEntry } from './clientsFindEntry';
|
||||
|
||||
/**
|
||||
* Client search results.
|
||||
*/
|
||||
export type ClientsFindResponse = ClientsFindEntry[];
|
||||
8
client_v2/src/api/model/clientsSearchRequest.ts
Normal file
8
client_v2/src/api/model/clientsSearchRequest.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import type { ClientsSearchRequestItem } from './clientsSearchRequestItem';
|
||||
|
||||
/**
|
||||
* Client search request
|
||||
*/
|
||||
export interface ClientsSearchRequest {
|
||||
clients?: ClientsSearchRequestItem[];
|
||||
}
|
||||
4
client_v2/src/api/model/clientsSearchRequestItem.ts
Normal file
4
client_v2/src/api/model/clientsSearchRequestItem.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export interface ClientsSearchRequestItem {
|
||||
/** Client IP address, CIDR, MAC address, or ClientID */
|
||||
id?: string;
|
||||
}
|
||||
69
client_v2/src/api/model/dNSConfig.ts
Normal file
69
client_v2/src/api/model/dNSConfig.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import type { DNSConfigBlockingMode } from './dNSConfigBlockingMode';
|
||||
import type { DNSConfigUpstreamMode } from './dNSConfigUpstreamMode';
|
||||
|
||||
/**
|
||||
* DNS server configuration
|
||||
*/
|
||||
export interface DNSConfig {
|
||||
/** Bootstrap servers, port is optional after colon. Empty value will reset it to default values. */
|
||||
bootstrap_dns?: string[];
|
||||
/** Upstream servers, port is optional after colon. Empty value will reset it to default values. */
|
||||
upstream_dns?: string[];
|
||||
/** List of fallback DNS servers used when upstream DNS servers are not responding. Empty value will clear the list. */
|
||||
fallback_dns?: string[];
|
||||
upstream_dns_file?: string;
|
||||
protection_enabled?: boolean;
|
||||
ratelimit?: number;
|
||||
/**
|
||||
* Length of the subnet mask for IPv4 addresses.
|
||||
* @minimum 0
|
||||
* @maximum 32
|
||||
*/
|
||||
ratelimit_subnet_subnet_len_ipv4?: number;
|
||||
/**
|
||||
* Length of the subnet mask for IPv6 addresses.
|
||||
* @minimum 0
|
||||
* @maximum 128
|
||||
*/
|
||||
ratelimit_subnet_subnet_len_ipv6?: number;
|
||||
/** List of IP addresses excluded from rate limiting. */
|
||||
ratelimit_whitelist?: string[];
|
||||
blocking_mode?: DNSConfigBlockingMode;
|
||||
blocking_ipv4?: string;
|
||||
blocking_ipv6?: string;
|
||||
/**
|
||||
* TTL for blocked responses.
|
||||
* @minimum 0
|
||||
*/
|
||||
blocked_response_ttl?: number;
|
||||
/** Protection is pause until this time. Nullable. */
|
||||
protection_disabled_until?: string;
|
||||
edns_cs_enabled?: boolean;
|
||||
edns_cs_use_custom?: boolean;
|
||||
edns_cs_custom_ip?: string;
|
||||
disable_ipv6?: boolean;
|
||||
dnssec_enabled?: boolean;
|
||||
cache_size?: number;
|
||||
cache_ttl_min?: number;
|
||||
cache_ttl_max?: number;
|
||||
/**
|
||||
* Enables or disables the DNS response cache.
|
||||
*
|
||||
* If `cache_enabled` is `true`, the companion field `cache_size` must
|
||||
* be present and greater than 0, or the `dns.cache_size` setting in
|
||||
* the configuration file must already be greater than 0.
|
||||
*/
|
||||
cache_enabled?: boolean;
|
||||
cache_optimistic?: boolean;
|
||||
/** Upstream modes enumeration. The empty string value is deprecated; use `load_balance` instead. */
|
||||
upstream_mode?: DNSConfigUpstreamMode;
|
||||
use_private_ptr_resolvers?: boolean;
|
||||
resolve_clients?: boolean;
|
||||
/** Upstream servers, port is optional after colon. Empty value will reset it to default values. */
|
||||
local_ptr_upstreams?: string[];
|
||||
/**
|
||||
* The number of seconds to wait for a response from the upstream server
|
||||
* @minimum 1
|
||||
*/
|
||||
upstream_timeout?: number;
|
||||
}
|
||||
1
client_v2/src/api/model/dNSConfigBlockingMode.ts
Normal file
1
client_v2/src/api/model/dNSConfigBlockingMode.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export type DNSConfigBlockingMode = 'default' | 'refused' | 'nxdomain' | 'null_ip' | 'custom_ip';
|
||||
4
client_v2/src/api/model/dNSConfigUpstreamMode.ts
Normal file
4
client_v2/src/api/model/dNSConfigUpstreamMode.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Upstream modes enumeration. The empty string value is deprecated; use `load_balance` instead.
|
||||
*/
|
||||
export type DNSConfigUpstreamMode = '' | 'fastest_addr' | 'load_balance' | 'parallel';
|
||||
17
client_v2/src/api/model/dayRange.ts
Normal file
17
client_v2/src/api/model/dayRange.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* The single interval within a day. It begins at the `start` and ends before the `end`.
|
||||
*/
|
||||
export interface DayRange {
|
||||
/**
|
||||
* The number of milliseconds elapsed from the start of a day. It must be less than `end` and is expected to be rounded to minutes. So the maximum value is `86340000` (23 hours and 59 minutes).
|
||||
* @minimum 0
|
||||
* @maximum 86340000
|
||||
*/
|
||||
start?: number;
|
||||
/**
|
||||
* The number of milliseconds elapsed from the start of a day. It is expected to be rounded to minutes. The maximum value is `86400000` (24 hours).
|
||||
* @minimum 0
|
||||
* @maximum 86400000
|
||||
*/
|
||||
end?: number;
|
||||
}
|
||||
9
client_v2/src/api/model/dhcpConfig.ts
Normal file
9
client_v2/src/api/model/dhcpConfig.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import type { DhcpConfigV4 } from './dhcpConfigV4';
|
||||
import type { DhcpConfigV6 } from './dhcpConfigV6';
|
||||
|
||||
export interface DhcpConfig {
|
||||
enabled?: boolean;
|
||||
interface_name?: string;
|
||||
v4?: DhcpConfigV4;
|
||||
v6?: DhcpConfigV6;
|
||||
}
|
||||
7
client_v2/src/api/model/dhcpConfigV4.ts
Normal file
7
client_v2/src/api/model/dhcpConfigV4.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export interface DhcpConfigV4 {
|
||||
gateway_ip?: string;
|
||||
subnet_mask?: string;
|
||||
range_start?: string;
|
||||
range_end?: string;
|
||||
lease_duration?: number;
|
||||
}
|
||||
4
client_v2/src/api/model/dhcpConfigV6.ts
Normal file
4
client_v2/src/api/model/dhcpConfigV6.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export interface DhcpConfigV6 {
|
||||
range_start?: string;
|
||||
lease_duration?: number;
|
||||
}
|
||||
7
client_v2/src/api/model/dhcpFindActiveReq.ts
Normal file
7
client_v2/src/api/model/dhcpFindActiveReq.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Request for checking for other DHCP servers in the network.
|
||||
*/
|
||||
export interface DhcpFindActiveReq {
|
||||
/** The name of the network interface */
|
||||
interface?: string;
|
||||
}
|
||||
9
client_v2/src/api/model/dhcpLease.ts
Normal file
9
client_v2/src/api/model/dhcpLease.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* DHCP lease information
|
||||
*/
|
||||
export interface DhcpLease {
|
||||
mac: string;
|
||||
ip: string;
|
||||
hostname: string;
|
||||
expires: string;
|
||||
}
|
||||
10
client_v2/src/api/model/dhcpSearchResult.ts
Normal file
10
client_v2/src/api/model/dhcpSearchResult.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import type { DhcpSearchV4 } from './dhcpSearchV4';
|
||||
import type { DhcpSearchV6 } from './dhcpSearchV6';
|
||||
|
||||
/**
|
||||
* Information about a DHCP server discovered in the current network.
|
||||
*/
|
||||
export interface DhcpSearchResult {
|
||||
v4?: DhcpSearchV4;
|
||||
v6?: DhcpSearchV6;
|
||||
}
|
||||
8
client_v2/src/api/model/dhcpSearchResultOtherServer.ts
Normal file
8
client_v2/src/api/model/dhcpSearchResultOtherServer.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import type { DhcpSearchResultOtherServerFound } from './dhcpSearchResultOtherServerFound';
|
||||
|
||||
export interface DhcpSearchResultOtherServer {
|
||||
/** The result of searching the other DHCP server. */
|
||||
found?: DhcpSearchResultOtherServerFound;
|
||||
/** Set if found=error */
|
||||
error?: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* The result of searching the other DHCP server.
|
||||
*/
|
||||
export type DhcpSearchResultOtherServerFound = 'yes' | 'no' | 'error';
|
||||
8
client_v2/src/api/model/dhcpSearchResultStaticIP.ts
Normal file
8
client_v2/src/api/model/dhcpSearchResultStaticIP.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import type { DhcpSearchResultStaticIPStatic } from './dhcpSearchResultStaticIPStatic';
|
||||
|
||||
export interface DhcpSearchResultStaticIP {
|
||||
/** The result of determining static IP address. */
|
||||
static?: DhcpSearchResultStaticIPStatic;
|
||||
/** Set if static=no */
|
||||
ip?: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* The result of determining static IP address.
|
||||
*/
|
||||
export type DhcpSearchResultStaticIPStatic = 'yes' | 'no' | 'error';
|
||||
7
client_v2/src/api/model/dhcpSearchV4.ts
Normal file
7
client_v2/src/api/model/dhcpSearchV4.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import type { DhcpSearchResultOtherServer } from './dhcpSearchResultOtherServer';
|
||||
import type { DhcpSearchResultStaticIP } from './dhcpSearchResultStaticIP';
|
||||
|
||||
export interface DhcpSearchV4 {
|
||||
other_server?: DhcpSearchResultOtherServer;
|
||||
static_ip?: DhcpSearchResultStaticIP;
|
||||
}
|
||||
5
client_v2/src/api/model/dhcpSearchV6.ts
Normal file
5
client_v2/src/api/model/dhcpSearchV6.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import type { DhcpSearchResultOtherServer } from './dhcpSearchResultOtherServer';
|
||||
|
||||
export interface DhcpSearchV6 {
|
||||
other_server?: DhcpSearchResultOtherServer;
|
||||
}
|
||||
8
client_v2/src/api/model/dhcpStaticLease.ts
Normal file
8
client_v2/src/api/model/dhcpStaticLease.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* DHCP static lease information
|
||||
*/
|
||||
export interface DhcpStaticLease {
|
||||
mac: string;
|
||||
ip: string;
|
||||
hostname: string;
|
||||
}
|
||||
3
client_v2/src/api/model/dhcpStaticLeaseBody.ts
Normal file
3
client_v2/src/api/model/dhcpStaticLeaseBody.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { DhcpStaticLease } from './dhcpStaticLease';
|
||||
|
||||
export type DhcpStaticLeaseBody = DhcpStaticLease;
|
||||
16
client_v2/src/api/model/dhcpStatus.ts
Normal file
16
client_v2/src/api/model/dhcpStatus.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import type { DhcpConfigV4 } from './dhcpConfigV4';
|
||||
import type { DhcpConfigV6 } from './dhcpConfigV6';
|
||||
import type { DhcpLease } from './dhcpLease';
|
||||
import type { DhcpStaticLease } from './dhcpStaticLease';
|
||||
|
||||
/**
|
||||
* Built-in DHCP server configuration and status
|
||||
*/
|
||||
export interface DhcpStatus {
|
||||
enabled?: boolean;
|
||||
interface_name?: string;
|
||||
v4?: DhcpConfigV4;
|
||||
v6?: DhcpConfigV6;
|
||||
leases: DhcpLease[];
|
||||
static_leases?: DhcpStaticLease[];
|
||||
}
|
||||
8
client_v2/src/api/model/dnsAnswer.ts
Normal file
8
client_v2/src/api/model/dnsAnswer.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* DNS answer section
|
||||
*/
|
||||
export interface DnsAnswer {
|
||||
ttl?: number;
|
||||
type?: string;
|
||||
value?: string;
|
||||
}
|
||||
5
client_v2/src/api/model/dnsInfo200.ts
Normal file
5
client_v2/src/api/model/dnsInfo200.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import type { DNSConfig } from './dNSConfig';
|
||||
|
||||
export type DnsInfo200 = DNSConfig & {
|
||||
default_local_ptr_upstreams?: string[];
|
||||
};
|
||||
9
client_v2/src/api/model/dnsQuestion.ts
Normal file
9
client_v2/src/api/model/dnsQuestion.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* DNS question section
|
||||
*/
|
||||
export interface DnsQuestion {
|
||||
class?: string;
|
||||
name?: string;
|
||||
unicode_name?: string;
|
||||
type?: string;
|
||||
}
|
||||
7
client_v2/src/api/model/error.ts
Normal file
7
client_v2/src/api/model/error.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* A generic JSON error response.
|
||||
*/
|
||||
export interface Error {
|
||||
/** The error message, an opaque string. */
|
||||
message?: string;
|
||||
}
|
||||
11
client_v2/src/api/model/filter.ts
Normal file
11
client_v2/src/api/model/filter.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Filter subscription info
|
||||
*/
|
||||
export interface Filter {
|
||||
enabled: boolean;
|
||||
id: number;
|
||||
last_updated?: string;
|
||||
name: string;
|
||||
rules_count: number;
|
||||
url: string;
|
||||
}
|
||||
29
client_v2/src/api/model/filterCheckHostResponse.ts
Normal file
29
client_v2/src/api/model/filterCheckHostResponse.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import type { FilteringReason } from './filteringReason';
|
||||
import type { ResultRule } from './resultRule';
|
||||
|
||||
/**
|
||||
* Check Host Result
|
||||
*/
|
||||
export interface FilterCheckHostResponse {
|
||||
reason?: FilteringReason;
|
||||
/**
|
||||
* In case if there's a rule applied to this DNS request, this is ID of the filter list that the rule belongs to.
|
||||
* Deprecated: use `rules[*].filter_list_id` instead.
|
||||
* @deprecated
|
||||
*/
|
||||
filter_id?: number;
|
||||
/**
|
||||
* Filtering rule applied to the request (if any).
|
||||
* Deprecated: use `rules[*].text` instead.
|
||||
* @deprecated
|
||||
*/
|
||||
rule?: string;
|
||||
/** Applied rules. */
|
||||
rules?: ResultRule[];
|
||||
/** Set if reason=FilteredBlockedService */
|
||||
service_name?: string;
|
||||
/** Set if reason=Rewrite */
|
||||
cname?: string;
|
||||
/** Set if reason=Rewrite */
|
||||
ip_addrs?: string[];
|
||||
}
|
||||
7
client_v2/src/api/model/filterConfig.ts
Normal file
7
client_v2/src/api/model/filterConfig.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Filtering settings
|
||||
*/
|
||||
export interface FilterConfig {
|
||||
enabled?: boolean;
|
||||
interval?: number;
|
||||
}
|
||||
6
client_v2/src/api/model/filterRefreshRequest.ts
Normal file
6
client_v2/src/api/model/filterRefreshRequest.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* Refresh Filters request data
|
||||
*/
|
||||
export interface FilterRefreshRequest {
|
||||
whitelist?: boolean;
|
||||
}
|
||||
6
client_v2/src/api/model/filterRefreshResponse.ts
Normal file
6
client_v2/src/api/model/filterRefreshResponse.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* /filtering/refresh response data
|
||||
*/
|
||||
export interface FilterRefreshResponse {
|
||||
updated?: number;
|
||||
}
|
||||
10
client_v2/src/api/model/filterSetUrl.ts
Normal file
10
client_v2/src/api/model/filterSetUrl.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import type { FilterSetUrlData } from './filterSetUrlData';
|
||||
|
||||
/**
|
||||
* Filtering URL settings
|
||||
*/
|
||||
export interface FilterSetUrl {
|
||||
data?: FilterSetUrlData;
|
||||
url?: string;
|
||||
whitelist?: boolean;
|
||||
}
|
||||
8
client_v2/src/api/model/filterSetUrlData.ts
Normal file
8
client_v2/src/api/model/filterSetUrlData.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Filter update data
|
||||
*/
|
||||
export interface FilterSetUrlData {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
12
client_v2/src/api/model/filterStatus.ts
Normal file
12
client_v2/src/api/model/filterStatus.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import type { Filter } from './filter';
|
||||
|
||||
/**
|
||||
* Filtering settings
|
||||
*/
|
||||
export interface FilterStatus {
|
||||
enabled?: boolean;
|
||||
interval?: number;
|
||||
filters?: Filter[];
|
||||
whitelist_filters?: Filter[];
|
||||
user_rules?: string[];
|
||||
}
|
||||
14
client_v2/src/api/model/filteringCheckHostParams.ts
Normal file
14
client_v2/src/api/model/filteringCheckHostParams.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
export type FilteringCheckHostParams = {
|
||||
/**
|
||||
* Filter by host name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Optional ClientID or client IP address
|
||||
*/
|
||||
client?: string;
|
||||
/**
|
||||
* Optional DNS type
|
||||
*/
|
||||
qtype?: string;
|
||||
};
|
||||
16
client_v2/src/api/model/filteringReason.ts
Normal file
16
client_v2/src/api/model/filteringReason.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Request filtering status.
|
||||
*/
|
||||
export type FilteringReason =
|
||||
| 'NotFilteredNotFound'
|
||||
| 'NotFilteredWhiteList'
|
||||
| 'NotFilteredError'
|
||||
| 'FilteredBlackList'
|
||||
| 'FilteredSafeBrowsing'
|
||||
| 'FilteredParental'
|
||||
| 'FilteredInvalid'
|
||||
| 'FilteredSafeSearch'
|
||||
| 'FilteredBlockedService'
|
||||
| 'Rewrite'
|
||||
| 'RewriteEtcHosts'
|
||||
| 'RewriteRule';
|
||||
15
client_v2/src/api/model/getQueryLogConfigResponse.ts
Normal file
15
client_v2/src/api/model/getQueryLogConfigResponse.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Query log configuration
|
||||
*/
|
||||
export interface GetQueryLogConfigResponse {
|
||||
/** Is query log enabled */
|
||||
enabled: boolean;
|
||||
/** Time period for query log rotation in milliseconds. */
|
||||
interval: number;
|
||||
/** Anonymize clients' IP addresses */
|
||||
anonymize_client_ip: boolean;
|
||||
/** List of host names, which should not be written to log */
|
||||
ignored: string[];
|
||||
/** If true, the host names in the `ignored` array are excluded from the query log. */
|
||||
ignored_enabled?: boolean;
|
||||
}
|
||||
13
client_v2/src/api/model/getStatsConfigResponse.ts
Normal file
13
client_v2/src/api/model/getStatsConfigResponse.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Statistics configuration
|
||||
*/
|
||||
export interface GetStatsConfigResponse {
|
||||
/** Are statistics enabled */
|
||||
enabled: boolean;
|
||||
/** Statistics rotation interval in milliseconds */
|
||||
interval: number;
|
||||
/** List of host names, which should not be counted */
|
||||
ignored: string[];
|
||||
/** If true, the host names in the `ignored` array are excluded from the statistics. */
|
||||
ignored_enabled?: boolean;
|
||||
}
|
||||
7
client_v2/src/api/model/getVersionRequest.ts
Normal file
7
client_v2/src/api/model/getVersionRequest.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* /version.json request data
|
||||
*/
|
||||
export interface GetVersionRequest {
|
||||
/** If false, server will check for a new version data only once in several hours. */
|
||||
recheck_now?: boolean;
|
||||
}
|
||||
116
client_v2/src/api/model/index.ts
Normal file
116
client_v2/src/api/model/index.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
export * from './accessList';
|
||||
export * from './accessListResponse';
|
||||
export * from './accessSetRequest';
|
||||
export * from './addressesInfo';
|
||||
export * from './addressInfo';
|
||||
export * from './addUrlRequest';
|
||||
export * from './blockedService';
|
||||
export * from './blockedServicesAll';
|
||||
export * from './blockedServicesArray';
|
||||
export * from './blockedServicesSchedule';
|
||||
export * from './checkConfigRequest';
|
||||
export * from './checkConfigRequestInfo';
|
||||
export * from './checkConfigResponse';
|
||||
export * from './checkConfigResponseInfo';
|
||||
export * from './checkConfigStaticIpInfo';
|
||||
export * from './checkConfigStaticIpInfoStatic';
|
||||
export * from './client';
|
||||
export * from './clientAuto';
|
||||
export * from './clientDelete';
|
||||
export * from './clientFindSubEntry';
|
||||
export * from './clients';
|
||||
export * from './clientsArray';
|
||||
export * from './clientsAutoArray';
|
||||
export * from './clientsFindEntry';
|
||||
export * from './clientsFindParams';
|
||||
export * from './clientsFindResponse';
|
||||
export * from './clientsSearchRequest';
|
||||
export * from './clientsSearchRequestItem';
|
||||
export * from './clientUpdate';
|
||||
export * from './dayRange';
|
||||
export * from './dhcpConfig';
|
||||
export * from './dhcpConfigV4';
|
||||
export * from './dhcpConfigV6';
|
||||
export * from './dhcpFindActiveReq';
|
||||
export * from './dhcpLease';
|
||||
export * from './dhcpSearchResult';
|
||||
export * from './dhcpSearchResultOtherServer';
|
||||
export * from './dhcpSearchResultOtherServerFound';
|
||||
export * from './dhcpSearchResultStaticIP';
|
||||
export * from './dhcpSearchResultStaticIPStatic';
|
||||
export * from './dhcpSearchV4';
|
||||
export * from './dhcpSearchV6';
|
||||
export * from './dhcpStaticLease';
|
||||
export * from './dhcpStaticLeaseBody';
|
||||
export * from './dhcpStatus';
|
||||
export * from './dnsAnswer';
|
||||
export * from './dNSConfig';
|
||||
export * from './dNSConfigBlockingMode';
|
||||
export * from './dNSConfigUpstreamMode';
|
||||
export * from './dnsInfo200';
|
||||
export * from './dnsQuestion';
|
||||
export * from './error';
|
||||
export * from './filter';
|
||||
export * from './filterCheckHostResponse';
|
||||
export * from './filterConfig';
|
||||
export * from './filteringCheckHostParams';
|
||||
export * from './filteringReason';
|
||||
export * from './filterRefreshRequest';
|
||||
export * from './filterRefreshResponse';
|
||||
export * from './filterSetUrl';
|
||||
export * from './filterSetUrlData';
|
||||
export * from './filterStatus';
|
||||
export * from './getQueryLogConfigResponse';
|
||||
export * from './getStatsConfigResponse';
|
||||
export * from './getVersionRequest';
|
||||
export * from './initialConfiguration';
|
||||
export * from './lang';
|
||||
export * from './languageSettings';
|
||||
export * from './login';
|
||||
export * from './mobileConfigDoHParams';
|
||||
export * from './mobileConfigDoTParams';
|
||||
export * from './netInterface';
|
||||
export * from './netInterfaces';
|
||||
export * from './parentalStatus200';
|
||||
export * from './profileInfo';
|
||||
export * from './profileInfoTheme';
|
||||
export * from './putQueryLogConfigUpdateRequest';
|
||||
export * from './putStatsConfigUpdateRequest';
|
||||
export * from './queryLog';
|
||||
export * from './queryLogConfig';
|
||||
export * from './queryLogConfigInterval';
|
||||
export * from './queryLogItem';
|
||||
export * from './queryLogItemClient';
|
||||
export * from './queryLogItemClientProto';
|
||||
export * from './queryLogItemClientWhois';
|
||||
export * from './queryLogParams';
|
||||
export * from './queryLogResponseStatus';
|
||||
export * from './removeUrlRequest';
|
||||
export * from './resultRule';
|
||||
export * from './rewriteEntry';
|
||||
export * from './rewriteEntryBody';
|
||||
export * from './rewriteList';
|
||||
export * from './rewriteSettings';
|
||||
export * from './rewriteSettingsBody';
|
||||
export * from './rewriteUpdate';
|
||||
export * from './rewriteUpdateBody';
|
||||
export * from './safebrowsingStatus200';
|
||||
export * from './safeSearchConfig';
|
||||
export * from './schedule';
|
||||
export * from './serverStatus';
|
||||
export * from './serviceGroup';
|
||||
export * from './setProtectionRequest';
|
||||
export * from './setRulesRequest';
|
||||
export * from './stats';
|
||||
export * from './statsConfig';
|
||||
export * from './statsConfigInterval';
|
||||
export * from './statsParams';
|
||||
export * from './statsTimeUnits';
|
||||
export * from './tlsConfig';
|
||||
export * from './tlsConfigBody';
|
||||
export * from './tlsConfigKeyType';
|
||||
export * from './topArrayEntry';
|
||||
export * from './upstreamsConfig';
|
||||
export * from './upstreamsConfigResponse';
|
||||
export * from './versionInfo';
|
||||
export * from './whoisInfo';
|
||||
15
client_v2/src/api/model/initialConfiguration.ts
Normal file
15
client_v2/src/api/model/initialConfiguration.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import type { AddressInfo } from './addressInfo';
|
||||
import type { Lang } from './lang';
|
||||
|
||||
/**
|
||||
* AdGuard Home initial configuration for the first-install wizard.
|
||||
*/
|
||||
export interface InitialConfiguration {
|
||||
dns: AddressInfo;
|
||||
web: AddressInfo;
|
||||
language?: Lang;
|
||||
/** Basic auth password */
|
||||
password: string;
|
||||
/** Basic auth username */
|
||||
username: string;
|
||||
}
|
||||
40
client_v2/src/api/model/lang.ts
Normal file
40
client_v2/src/api/model/lang.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Language code.
|
||||
*/
|
||||
export type Lang =
|
||||
| 'ar'
|
||||
| 'be'
|
||||
| 'bg'
|
||||
| 'cs'
|
||||
| 'da'
|
||||
| 'de'
|
||||
| 'en'
|
||||
| 'es'
|
||||
| 'fa'
|
||||
| 'fi'
|
||||
| 'fr'
|
||||
| 'hr'
|
||||
| 'hu'
|
||||
| 'id'
|
||||
| 'it'
|
||||
| 'ja'
|
||||
| 'ko'
|
||||
| 'nl'
|
||||
| 'no'
|
||||
| 'pl'
|
||||
| 'pt-br'
|
||||
| 'pt-pt'
|
||||
| 'ro'
|
||||
| 'ru'
|
||||
| 'si-lk'
|
||||
| 'sk'
|
||||
| 'sl'
|
||||
| 'sr-cs'
|
||||
| 'sv'
|
||||
| 'th'
|
||||
| 'tr'
|
||||
| 'uk'
|
||||
| 'vi'
|
||||
| 'zh-cn'
|
||||
| 'zh-hk'
|
||||
| 'zh-tw';
|
||||
8
client_v2/src/api/model/languageSettings.ts
Normal file
8
client_v2/src/api/model/languageSettings.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import type { Lang } from './lang';
|
||||
|
||||
/**
|
||||
* Language settings object.
|
||||
*/
|
||||
export interface LanguageSettings {
|
||||
language: Lang;
|
||||
}
|
||||
9
client_v2/src/api/model/login.ts
Normal file
9
client_v2/src/api/model/login.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* Login request data
|
||||
*/
|
||||
export interface Login {
|
||||
/** User name */
|
||||
name?: string;
|
||||
/** Password */
|
||||
password?: string;
|
||||
}
|
||||
10
client_v2/src/api/model/mobileConfigDoHParams.ts
Normal file
10
client_v2/src/api/model/mobileConfigDoHParams.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export type MobileConfigDoHParams = {
|
||||
/**
|
||||
* Host for which the config is generated. If no host is provided, `tls.server_name` from the configuration file is used. If `tls.server_name` is not set, the API returns an error with a 500 status.
|
||||
*/
|
||||
host: string;
|
||||
/**
|
||||
* ClientID.
|
||||
*/
|
||||
client_id?: string;
|
||||
};
|
||||
10
client_v2/src/api/model/mobileConfigDoTParams.ts
Normal file
10
client_v2/src/api/model/mobileConfigDoTParams.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export type MobileConfigDoTParams = {
|
||||
/**
|
||||
* Host for which the config is generated. If no host is provided, `tls.server_name` from the configuration file is used. If `tls.server_name` is not set, the API returns an error with a 500 status.
|
||||
*/
|
||||
host: string;
|
||||
/**
|
||||
* ClientID.
|
||||
*/
|
||||
client_id?: string;
|
||||
};
|
||||
15
client_v2/src/api/model/netInterface.ts
Normal file
15
client_v2/src/api/model/netInterface.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Network interface info
|
||||
*/
|
||||
export interface NetInterface {
|
||||
/** Flags could be any combination of the following values, divided by the "|" character: "up", "broadcast", "loopback", "pointtopoint" and "multicast". */
|
||||
flags: string;
|
||||
/** The IP address of the gateway. */
|
||||
gateway_ip: string;
|
||||
hardware_address: string;
|
||||
/** The addresses of the interface of v4 family. */
|
||||
ipv4_addresses: string[];
|
||||
/** The addresses of the interface of v6 family. */
|
||||
ipv6_addresses: string[];
|
||||
name: string;
|
||||
}
|
||||
8
client_v2/src/api/model/netInterfaces.ts
Normal file
8
client_v2/src/api/model/netInterfaces.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import type { NetInterface } from './netInterface';
|
||||
|
||||
/**
|
||||
* Network interfaces dictionary, keys are interface names.
|
||||
*/
|
||||
export interface NetInterfaces {
|
||||
[key: string]: NetInterface;
|
||||
}
|
||||
4
client_v2/src/api/model/parentalStatus200.ts
Normal file
4
client_v2/src/api/model/parentalStatus200.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export type ParentalStatus200 = {
|
||||
enable?: boolean;
|
||||
sensitivity?: number;
|
||||
};
|
||||
12
client_v2/src/api/model/profileInfo.ts
Normal file
12
client_v2/src/api/model/profileInfo.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import type { Lang } from './lang';
|
||||
import type { ProfileInfoTheme } from './profileInfoTheme';
|
||||
|
||||
/**
|
||||
* Information about the current user
|
||||
*/
|
||||
export interface ProfileInfo {
|
||||
name: string;
|
||||
language: Lang;
|
||||
/** Interface theme */
|
||||
theme: ProfileInfoTheme;
|
||||
}
|
||||
4
client_v2/src/api/model/profileInfoTheme.ts
Normal file
4
client_v2/src/api/model/profileInfoTheme.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Interface theme
|
||||
*/
|
||||
export type ProfileInfoTheme = 'auto' | 'dark' | 'light';
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import type { GetQueryLogConfigResponse } from './getQueryLogConfigResponse';
|
||||
|
||||
export type PutQueryLogConfigUpdateRequest = GetQueryLogConfigResponse;
|
||||
3
client_v2/src/api/model/putStatsConfigUpdateRequest.ts
Normal file
3
client_v2/src/api/model/putStatsConfigUpdateRequest.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import type { GetStatsConfigResponse } from './getStatsConfigResponse';
|
||||
|
||||
export type PutStatsConfigUpdateRequest = GetStatsConfigResponse;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue