diff --git a/apps/frontend/.eslintrc.cjs b/apps/frontend/.eslintrc.cjs
index bb2d3ac..7b78313 100644
--- a/apps/frontend/.eslintrc.cjs
+++ b/apps/frontend/.eslintrc.cjs
@@ -1,10 +1,13 @@
+const path = require('path');
+const src = path.resolve(__dirname, 'src');
+
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
sourceType: 'module',
ecmaFeatures: { jsx: true },
},
- plugins: ['@typescript-eslint/eslint-plugin', 'react', 'react-hooks'],
+ plugins: ['@typescript-eslint/eslint-plugin', 'react', 'react-hooks', 'import'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
@@ -17,11 +20,48 @@ module.exports = {
},
settings: {
react: { version: 'detect' },
+ 'import/resolver': {
+ typescript: {
+ alwaysTryTypes: true,
+ project: './tsconfig.json',
+ },
+ },
},
ignorePatterns: ['.eslintrc.cjs', 'vite.config.ts', 'vitest.config.ts', 'dist/'],
rules: {
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'off',
'react/react-in-jsx-scope': 'off',
+
+ // FSD layer boundaries
+ // NOTE: `from` = what's being imported, `target` = the file doing the import
+ 'import/no-restricted-paths': [
+ 'error',
+ {
+ zones: [
+ // shared/ cannot import from entities/, features/, widgets/, pages/, app/
+ { from: `${src}/entities`, target: `${src}/shared` },
+ { from: `${src}/features`, target: `${src}/shared` },
+ { from: `${src}/widgets`, target: `${src}/shared` },
+ { from: `${src}/pages`, target: `${src}/shared` },
+ { from: `${src}/app`, target: `${src}/shared` },
+ // entities/ cannot import from features/, widgets/, pages/, app/
+ { from: `${src}/features`, target: `${src}/entities` },
+ { from: `${src}/widgets`, target: `${src}/entities` },
+ { from: `${src}/pages`, target: `${src}/entities` },
+ { from: `${src}/app`, target: `${src}/entities` },
+ // features/ cannot import from widgets/, pages/, app/
+ { from: `${src}/widgets`, target: `${src}/features` },
+ { from: `${src}/pages`, target: `${src}/features` },
+ { from: `${src}/app`, target: `${src}/features` },
+ // widgets/ cannot import from pages/, app/
+ { from: `${src}/pages`, target: `${src}/widgets` },
+ { from: `${src}/app`, target: `${src}/widgets` },
+ // pages/ cannot import from app/
+ { from: `${src}/app`, target: `${src}/pages` },
+
+ ],
+ },
+ ],
},
};
diff --git a/apps/frontend/package.json b/apps/frontend/package.json
index 4165e45..b50d1ae 100644
--- a/apps/frontend/package.json
+++ b/apps/frontend/package.json
@@ -31,6 +31,9 @@
"@typescript-eslint/parser": "^7.0.0",
"@vitejs/plugin-react": "^4.2.0",
"eslint": "^8.0.0",
+ "eslint-import-resolver-alias": "^1.1.2",
+ "eslint-import-resolver-typescript": "^4.4.5",
+ "eslint-plugin-import": "^2.32.0",
"eslint-plugin-react": "^7.34.0",
"eslint-plugin-react-hooks": "^4.6.0",
"jsdom": "^29.1.1",
diff --git a/apps/frontend/src/app/routing/AppRoutes.tsx b/apps/frontend/src/app/routing/AppRoutes.tsx
index 3f38091..3fdd335 100644
--- a/apps/frontend/src/app/routing/AppRoutes.tsx
+++ b/apps/frontend/src/app/routing/AppRoutes.tsx
@@ -4,11 +4,10 @@ import { ProtectedRoute } from './ProtectedRoute';
import { HomePage } from '@/pages/home';
import { StockPage } from '@/pages/stock';
import { BondPage } from '@/pages/bond';
-import { LoginPage } from '@/pages/LoginPage';
-import { RegisterPage } from '@/pages/RegisterPage';
-import { ProfilePage } from '@/pages/ProfilePage';
-import { PortfoliosListPage } from '@/pages/portfolios/PortfoliosListPage';
-import { PortfolioDetailPage } from '@/pages/portfolios/PortfolioDetailPage';
+import { LoginPage } from '@/pages/login';
+import { RegisterPage } from '@/pages/register';
+import { ProfilePage } from '@/pages/profile';
+import { PortfoliosListPage, PortfolioDetailPage } from '@/pages/portfolios';
import { ScreenerPage } from '@/pages/screener';
import { BrokerAccountsPage } from '@/pages/broker-accounts';
import { BrokerAccountLayout } from '@/entities/broker-account/ui/BrokerAccountLayout';
diff --git a/apps/frontend/src/entities/session/model/useSession.test.tsx b/apps/frontend/src/entities/session/model/useSession.test.tsx
index 0abf982..2e4652a 100644
--- a/apps/frontend/src/entities/session/model/useSession.test.tsx
+++ b/apps/frontend/src/entities/session/model/useSession.test.tsx
@@ -1,62 +1,53 @@
import { describe, it, expect } from 'vitest';
-import { renderHook, waitFor } from '@testing-library/react';
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { SessionProvider } from '../../../app/providers/SessionProvider';
+import { renderHook } from '@testing-library/react';
+import { SessionContext, type SessionState } from './sessionContext';
import { useSession } from './useSession';
-import { type ReactNode } from 'react';
+import type { ReactNode } from 'react';
-function createWrapper() {
- const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
+const mockSession: SessionState = {
+ user: { id: 1, email: 'user@test.com', name: 'Test User', role: 'user' },
+ accessToken: 'mock-access-token',
+ isAuthenticated: true,
+ login: vi.fn().mockResolvedValue(undefined),
+ logout: vi.fn(),
+ register: vi.fn().mockResolvedValue(undefined),
+ updateProfile: vi.fn().mockResolvedValue(undefined),
+ refreshSession: vi.fn().mockResolvedValue(undefined),
+};
+
+function createWrapper(session: SessionState = mockSession) {
return function Wrapper({ children }: { children: ReactNode }) {
- return (
-
- {children}
-
- );
+ return {children};
};
}
describe('useSession', () => {
- afterEach(() => {
- vi.restoreAllMocks();
- });
-
- it('returns session context with user after mount', async () => {
+ it('returns session context with user', () => {
const { result } = renderHook(() => useSession(), { wrapper: createWrapper() });
- await waitFor(() => {
- expect(result.current.isAuthenticated).toBe(true);
- });
+ expect(result.current.isAuthenticated).toBe(true);
expect(result.current.user?.email).toBe('user@test.com');
expect(result.current.accessToken).toBe('mock-access-token');
});
- it('provides login function', async () => {
+ it('provides login function', () => {
const { result } = renderHook(() => useSession(), { wrapper: createWrapper() });
- await waitFor(() => expect(result.current.isAuthenticated).toBe(true));
expect(typeof result.current.login).toBe('function');
});
- it('provides logout function', async () => {
+ it('provides logout function', () => {
const { result } = renderHook(() => useSession(), { wrapper: createWrapper() });
- await waitFor(() => expect(result.current.isAuthenticated).toBe(true));
expect(typeof result.current.logout).toBe('function');
});
- it('provides register function', async () => {
+ it('provides register function', () => {
const { result } = renderHook(() => useSession(), { wrapper: createWrapper() });
- await waitFor(() => expect(result.current.isAuthenticated).toBe(true));
expect(typeof result.current.register).toBe('function');
});
- it('throws when used without AuthProvider', () => {
- vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
- vi.spyOn(console, 'error').mockImplementation(() => {});
- const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
+ it('throws when used without SessionProvider', () => {
expect(() => {
renderHook(() => useSession(), {
- wrapper: ({ children }) => (
- {children}
- ),
+ wrapper: ({ children }: { children: ReactNode }) => <>{children}>,
});
}).toThrow('useSession must be used within a SessionProvider');
});
diff --git a/apps/frontend/src/pages/LoginPage.test.tsx b/apps/frontend/src/pages/login/LoginPage.test.tsx
similarity index 95%
rename from apps/frontend/src/pages/LoginPage.test.tsx
rename to apps/frontend/src/pages/login/LoginPage.test.tsx
index 2b1e9bb..4932b74 100644
--- a/apps/frontend/src/pages/LoginPage.test.tsx
+++ b/apps/frontend/src/pages/login/LoginPage.test.tsx
@@ -3,9 +3,9 @@ import { screen } from '@testing-library/react';
import { Routes, Route } from 'react-router-dom';
import userEvent from '@testing-library/user-event';
import { http, HttpResponse } from 'msw';
-import { server } from '../test/server';
-import { LoginPage } from './LoginPage';
-import { renderWithProviders } from '../test/test-utils';
+import { server } from '../../test/server';
+import { LoginPage } from './ui/LoginPage';
+import { renderWithProviders } from '../../test/test-utils';
const API = '/api/v1';
diff --git a/apps/frontend/src/pages/login/index.ts b/apps/frontend/src/pages/login/index.ts
new file mode 100644
index 0000000..3935214
--- /dev/null
+++ b/apps/frontend/src/pages/login/index.ts
@@ -0,0 +1 @@
+export { LoginPage } from './ui/LoginPage';
diff --git a/apps/frontend/src/pages/LoginPage.tsx b/apps/frontend/src/pages/login/ui/LoginPage.tsx
similarity index 100%
rename from apps/frontend/src/pages/LoginPage.tsx
rename to apps/frontend/src/pages/login/ui/LoginPage.tsx
diff --git a/apps/frontend/src/pages/portfolios/index.ts b/apps/frontend/src/pages/portfolios/index.ts
new file mode 100644
index 0000000..34e0478
--- /dev/null
+++ b/apps/frontend/src/pages/portfolios/index.ts
@@ -0,0 +1,2 @@
+export { PortfoliosListPage } from './ui/PortfoliosListPage';
+export { PortfolioDetailPage } from './ui/PortfolioDetailPage';
diff --git a/apps/frontend/src/pages/portfolios/PortfolioDetailPage.tsx b/apps/frontend/src/pages/portfolios/ui/PortfolioDetailPage.tsx
similarity index 94%
rename from apps/frontend/src/pages/portfolios/PortfolioDetailPage.tsx
rename to apps/frontend/src/pages/portfolios/ui/PortfolioDetailPage.tsx
index 7ea257c..9ec841f 100644
--- a/apps/frontend/src/pages/portfolios/PortfolioDetailPage.tsx
+++ b/apps/frontend/src/pages/portfolios/ui/PortfolioDetailPage.tsx
@@ -1,15 +1,11 @@
import { useState } from 'react';
import { useParams, Link } from 'react-router-dom';
-import {
- usePortfolio,
- usePortfolioMutations,
- usePositionMutations,
-} from '../../entities/portfolio';
-import { PortfolioForm } from '../../widgets/portfolio-form';
-import { PortfolioSummary } from '../../widgets/portfolio-summary';
-import { AnalyticsSummary } from '../../widgets/portfolio-analytics';
-import { SharePositionTable } from '../../widgets/share-positions-table';
-import { BondPositionTable } from '../../widgets/bond-positions-table';
+import { usePortfolio, usePortfolioMutations, usePositionMutations } from '@/entities/portfolio';
+import { PortfolioForm } from '@/widgets/portfolio-form';
+import { PortfolioSummary } from '@/widgets/portfolio-summary';
+import { AnalyticsSummary } from '@/widgets/portfolio-analytics';
+import { SharePositionTable } from '@/widgets/share-positions-table';
+import { BondPositionTable } from '@/widgets/bond-positions-table';
export function PortfolioDetailPage() {
const { id } = useParams<{ id: string }>();
diff --git a/apps/frontend/src/pages/portfolios/PortfoliosListPage.tsx b/apps/frontend/src/pages/portfolios/ui/PortfoliosListPage.tsx
similarity index 92%
rename from apps/frontend/src/pages/portfolios/PortfoliosListPage.tsx
rename to apps/frontend/src/pages/portfolios/ui/PortfoliosListPage.tsx
index 0bd4cc6..9f8fc28 100644
--- a/apps/frontend/src/pages/portfolios/PortfoliosListPage.tsx
+++ b/apps/frontend/src/pages/portfolios/ui/PortfoliosListPage.tsx
@@ -1,7 +1,7 @@
import { useState } from 'react';
-import { usePortfolios, usePortfolioMutations } from '../../entities/portfolio';
-import { PortfolioCard } from '../../widgets/portfolio-card';
-import { PortfolioForm } from '../../widgets/portfolio-form';
+import { usePortfolios, usePortfolioMutations } from '@/entities/portfolio';
+import { PortfolioCard } from '@/widgets/portfolio-card';
+import { PortfolioForm } from '@/widgets/portfolio-form';
export function PortfoliosListPage() {
const { data: portfolios, isLoading, error } = usePortfolios();
diff --git a/apps/frontend/src/pages/ProfilePage.test.tsx b/apps/frontend/src/pages/profile/ProfilePage.test.tsx
similarity index 93%
rename from apps/frontend/src/pages/ProfilePage.test.tsx
rename to apps/frontend/src/pages/profile/ProfilePage.test.tsx
index 1575afc..e4bc956 100644
--- a/apps/frontend/src/pages/ProfilePage.test.tsx
+++ b/apps/frontend/src/pages/profile/ProfilePage.test.tsx
@@ -2,9 +2,9 @@ import { describe, it, expect } from 'vitest';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { http, HttpResponse } from 'msw';
-import { server } from '../test/server';
-import { ProfilePage } from './ProfilePage';
-import { renderWithProviders } from '../test/test-utils';
+import { server } from '../../test/server';
+import { ProfilePage } from './ui/ProfilePage';
+import { renderWithProviders } from '../../test/test-utils';
const API = '/api/v1';
diff --git a/apps/frontend/src/pages/profile/index.ts b/apps/frontend/src/pages/profile/index.ts
new file mode 100644
index 0000000..7d9c888
--- /dev/null
+++ b/apps/frontend/src/pages/profile/index.ts
@@ -0,0 +1 @@
+export { ProfilePage } from './ui/ProfilePage';
diff --git a/apps/frontend/src/pages/ProfilePage.tsx b/apps/frontend/src/pages/profile/ui/ProfilePage.tsx
similarity index 100%
rename from apps/frontend/src/pages/ProfilePage.tsx
rename to apps/frontend/src/pages/profile/ui/ProfilePage.tsx
diff --git a/apps/frontend/src/pages/RegisterPage.test.tsx b/apps/frontend/src/pages/register/RegisterPage.test.tsx
similarity index 95%
rename from apps/frontend/src/pages/RegisterPage.test.tsx
rename to apps/frontend/src/pages/register/RegisterPage.test.tsx
index cc080b7..832cb29 100644
--- a/apps/frontend/src/pages/RegisterPage.test.tsx
+++ b/apps/frontend/src/pages/register/RegisterPage.test.tsx
@@ -3,9 +3,9 @@ import { screen } from '@testing-library/react';
import { Routes, Route } from 'react-router-dom';
import userEvent from '@testing-library/user-event';
import { http, HttpResponse } from 'msw';
-import { server } from '../test/server';
-import { RegisterPage } from './RegisterPage';
-import { renderWithProviders } from '../test/test-utils';
+import { server } from '../../test/server';
+import { RegisterPage } from './ui/RegisterPage';
+import { renderWithProviders } from '../../test/test-utils';
const API = '/api/v1';
diff --git a/apps/frontend/src/pages/register/index.ts b/apps/frontend/src/pages/register/index.ts
new file mode 100644
index 0000000..2c39f32
--- /dev/null
+++ b/apps/frontend/src/pages/register/index.ts
@@ -0,0 +1 @@
+export { RegisterPage } from './ui/RegisterPage';
diff --git a/apps/frontend/src/pages/RegisterPage.tsx b/apps/frontend/src/pages/register/ui/RegisterPage.tsx
similarity index 100%
rename from apps/frontend/src/pages/RegisterPage.tsx
rename to apps/frontend/src/pages/register/ui/RegisterPage.tsx
diff --git a/docs/features/frontend-fsd-screener/tasks.md b/docs/features/frontend-fsd-screener/tasks.md
index 5a51cfe..622bfef 100644
--- a/docs/features/frontend-fsd-screener/tasks.md
+++ b/docs/features/frontend-fsd-screener/tasks.md
@@ -1,47 +1,45 @@
# Frontend FSD Screener — задачи
-Статус: в работе
-
-Подробные шаги, карта файлов и verification-команды находятся в [plan.md](plan.md).
+Статус: выполнено
## 1. API слой
-- [ ] Создать `features/screener/api/screenerApi.ts` — перенос `ScreenerQuery` + `getScreenerResults`
-- [ ] Обновить импорты: `@/shared/api/client`, `@/shared/api/responses`
+- [x] Создать `features/screener/api/screenerApi.ts` — перенос `ScreenerQuery` + `getScreenerResults`
+- [x] Обновить импорты: `@/shared/api/client`, `@/shared/api/responses`
## 2. Модель
-- [ ] Создать `features/screener/model/useScreener.ts` — перенос хука
-- [ ] Создать `features/screener/model/index.ts`
+- [x] Создать `features/screener/model/useScreener.ts` — перенос хука
+- [x] Создать `features/screener/model/index.ts`
## 3. UI компоненты
-- [ ] Перенести `FilterPanel.tsx` в `features/screener/ui/`
-- [ ] Перенести `FilterPanelShare.tsx` в `features/screener/ui/`
-- [ ] Перенести `FilterPanelBond.tsx` в `features/screener/ui/`
-- [ ] Перенести `ScreenerTable.tsx` в `features/screener/ui/`
-- [ ] Создать `features/screener/ui/index.ts`
-- [ ] Создать `features/screener/index.ts`
+- [x] Перенести `FilterPanel.tsx` в `features/screener/ui/`
+- [x] Перенести `FilterPanelShare.tsx` в `features/screener/ui/`
+- [x] Перенести `FilterPanelBond.tsx` в `features/screener/ui/`
+- [x] Перенести `ScreenerTable.tsx` в `features/screener/ui/`
+- [x] Создать `features/screener/ui/index.ts`
+- [x] Создать `features/screener/index.ts`
## 4. Pages
-- [ ] Создать `pages/screener/ui/ScreenerPage.tsx` — обновить импорты на `@/features/screener`
-- [ ] Создать `pages/screener/index.ts`
+- [x] Создать `pages/screener/ui/ScreenerPage.tsx` — обновить импорты на `@/features/screener`
+- [x] Создать `pages/screener/index.ts`
## 5. Роутинг
-- [ ] Обновить `app/routing/AppRoutes.tsx` — import from `@/pages/screener`
+- [x] Обновить `app/routing/AppRoutes.tsx` — import from `@/pages/screener`
## 6. Удаление legacy
-- [ ] Удалить `api/screener.ts`
-- [ ] Удалить `hooks/useScreener.ts`
-- [ ] Удалить `components/screener/` (директория)
+- [x] Удалить `api/screener.ts`
+- [x] Удалить `hooks/useScreener.ts`
+- [x] Удалить `components/screener/` (директория)
## 7. Verification
-- [ ] `npm test -w apps/frontend` — PASS
-- [ ] `npm run lint -w apps/frontend` — PASS
-- [ ] `npm run build -w apps/frontend` — PASS
-- [ ] Нет deep imports в `features/screener/` извне
-- [ ] `pages/screener/` импортируется только через barrel
+- [x] `npm test -w apps/frontend` — PASS
+- [x] `npm run lint -w apps/frontend` — PASS
+- [x] `npm run build -w apps/frontend` — PASS
+- [x] Нет deep imports в `features/screener/` извне
+- [x] `pages/screener/` импортируется только через barrel
diff --git a/package-lock.json b/package-lock.json
index c3e72cb..55bb494 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -103,6 +103,9 @@
"@typescript-eslint/parser": "^7.0.0",
"@vitejs/plugin-react": "^4.2.0",
"eslint": "^8.0.0",
+ "eslint-import-resolver-alias": "^1.1.2",
+ "eslint-import-resolver-typescript": "^4.4.5",
+ "eslint-plugin-import": "^2.32.0",
"eslint-plugin-react": "^7.34.0",
"eslint-plugin-react-hooks": "^4.6.0",
"jsdom": "^29.1.1",
@@ -671,6 +674,41 @@
"@esbuild/win32-x64": "0.28.1"
}
},
+ "apps/frontend/node_modules/eslint-import-resolver-typescript": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.5.tgz",
+ "integrity": "sha512-nbE5XLph6TLtGYcu/U6e6ZVXyKBhbDWK5cLGk76eJ7NdZpwf1P9EFkpt1Z01mNZNrrilsAYWKH6zUkL4reoXbw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "debug": "^4.4.1",
+ "eslint-import-context": "^0.1.8",
+ "get-tsconfig": "^4.10.1",
+ "is-bun-module": "^2.0.0",
+ "stable-hash-x": "^0.2.0",
+ "tinyglobby": "^0.2.14",
+ "unrs-resolver": "^1.7.11"
+ },
+ "engines": {
+ "node": "^16.17.0 || >=18.6.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-import-resolver-typescript"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*",
+ "eslint-plugin-import-x": "*"
+ },
+ "peerDependenciesMeta": {
+ "eslint-plugin-import": {
+ "optional": true
+ },
+ "eslint-plugin-import-x": {
+ "optional": true
+ }
+ }
+ },
"apps/frontend/node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -9012,6 +9050,13 @@
"win32"
]
},
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@sideway/address": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
@@ -10333,6 +10378,13 @@
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"license": "MIT"
},
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/jsonwebtoken": {
"version": "9.0.10",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
@@ -10792,6 +10844,319 @@
"integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==",
"license": "ISC"
},
+ "node_modules/@unrs/resolver-binding-android-arm-eabi": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz",
+ "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-android-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz",
+ "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz",
+ "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz",
+ "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz",
+ "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz",
+ "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz",
+ "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz",
+ "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz",
+ "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-loong64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz",
+ "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-loong64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz",
+ "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz",
+ "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz",
+ "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz",
+ "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz",
+ "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz",
+ "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz",
+ "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-openharmony-arm64": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz",
+ "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz",
+ "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "1.10.0",
+ "@emnapi/runtime": "1.10.0",
+ "@napi-rs/wasm-runtime": "^1.1.4"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz",
+ "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz",
+ "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz",
+ "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
"node_modules/@upsetjs/venn.js": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz",
@@ -11478,6 +11843,28 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
+ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-shim-unscopables": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/array.prototype.flat": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
@@ -15699,6 +16086,235 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint-import-context": {
+ "version": "0.1.9",
+ "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz",
+ "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-tsconfig": "^4.10.1",
+ "stable-hash-x": "^0.2.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-import-context"
+ },
+ "peerDependencies": {
+ "unrs-resolver": "^1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "unrs-resolver": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-alias": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz",
+ "integrity": "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ },
+ "peerDependencies": {
+ "eslint-plugin-import": ">=1.4.0"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.10",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz",
+ "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.16.1",
+ "resolve": "^2.0.0-next.6"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/resolve": {
+ "version": "2.0.0-next.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
+ "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.2",
+ "node-exports-info": "^1.6.0",
+ "object-keys": "^1.1.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.13.0.tgz",
+ "integrity": "sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.32.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
+ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.9",
+ "array.prototype.findlastindex": "^1.2.6",
+ "array.prototype.flat": "^1.3.3",
+ "array.prototype.flatmap": "^1.3.3",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.12.1",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.16.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.1",
+ "semver": "^6.3.1",
+ "string.prototype.trimend": "^1.0.9",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/brace-expansion": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz",
+ "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
"node_modules/eslint-plugin-react": {
"version": "7.37.5",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
@@ -17146,6 +17762,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-tsconfig": {
+ "version": "4.14.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
+ "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
"node_modules/giget": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/giget/-/giget-3.3.0.tgz",
@@ -18541,6 +19170,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-bun-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
+ "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.7.1"
+ }
+ },
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -23456,6 +24095,22 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/napi-postinstall": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
+ "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "napi-postinstall": "lib/cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/napi-postinstall"
+ }
+ },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -23766,6 +24421,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/object.values": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
@@ -27608,6 +28278,16 @@
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==",
"license": "MIT"
},
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
"node_modules/responselike": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
@@ -28947,6 +29627,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/stable-hash-x": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz",
+ "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/stackback": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
@@ -30328,6 +31018,44 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/unrs-resolver": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz",
+ "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "napi-postinstall": "^0.3.4"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unrs-resolver"
+ },
+ "optionalDependencies": {
+ "@unrs/resolver-binding-android-arm-eabi": "1.12.2",
+ "@unrs/resolver-binding-android-arm64": "1.12.2",
+ "@unrs/resolver-binding-darwin-arm64": "1.12.2",
+ "@unrs/resolver-binding-darwin-x64": "1.12.2",
+ "@unrs/resolver-binding-freebsd-x64": "1.12.2",
+ "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2",
+ "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2",
+ "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-arm64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-loong64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2",
+ "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-x64-gnu": "1.12.2",
+ "@unrs/resolver-binding-linux-x64-musl": "1.12.2",
+ "@unrs/resolver-binding-openharmony-arm64": "1.12.2",
+ "@unrs/resolver-binding-wasm32-wasi": "1.12.2",
+ "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2",
+ "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2",
+ "@unrs/resolver-binding-win32-x64-msvc": "1.12.2"
+ }
+ },
"node_modules/until-async": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/until-async/-/until-async-3.0.2.tgz",