prettier !
This commit is contained in:
80
README.md
80
README.md
@@ -95,7 +95,7 @@ actually the proper change was to do this in the /etc/nginx/sites-available/flye
|
||||
## for OAuth
|
||||
|
||||
1. Get Google OAuth Credentials
|
||||
This is a crucial step that you must do outside the codebase:
|
||||
This is a crucial step that you must do outside the codebase:
|
||||
|
||||
Go to the Google Cloud Console.
|
||||
|
||||
@@ -112,7 +112,7 @@ Under Authorized redirect URIs, click ADD URI and enter the URL where Google wil
|
||||
Click Create. You will be given a Client ID and a Client Secret.
|
||||
|
||||
2. Get GitHub OAuth Credentials
|
||||
You'll need to obtain a Client ID and Client Secret from GitHub:
|
||||
You'll need to obtain a Client ID and Client Secret from GitHub:
|
||||
|
||||
Go to your GitHub profile settings.
|
||||
|
||||
@@ -133,21 +133,23 @@ You will be given a Client ID and a Client Secret.
|
||||
|
||||
psql -h localhost -U flyer_crawler_user -d "flyer-crawler-prod" -W
|
||||
|
||||
|
||||
## postgis
|
||||
|
||||
flyer-crawler-prod=> SELECT version();
|
||||
version
|
||||
------------------------------------------------------------------------------------------------------------------------------------------
|
||||
PostgreSQL 14.19 (Ubuntu 14.19-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit
|
||||
version
|
||||
|
||||
---
|
||||
|
||||
PostgreSQL 14.19 (Ubuntu 14.19-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0, 64-bit
|
||||
(1 row)
|
||||
|
||||
flyer-crawler-prod=> SELECT PostGIS_Full_Version();
|
||||
postgis_full_version
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
POSTGIS="3.2.0 c3e3cc0" [EXTENSION] PGSQL="140" GEOS="3.10.2-CAPI-1.16.0" PROJ="8.2.1" LIBXML="2.9.12" LIBJSON="0.15" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)"
|
||||
(1 row)
|
||||
postgis_full_version
|
||||
|
||||
---
|
||||
|
||||
POSTGIS="3.2.0 c3e3cc0" [EXTENSION] PGSQL="140" GEOS="3.10.2-CAPI-1.16.0" PROJ="8.2.1" LIBXML="2.9.12" LIBJSON="0.15" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)"
|
||||
(1 row)
|
||||
|
||||
## production postgres setup
|
||||
|
||||
@@ -201,9 +203,13 @@ Step 4: Seed the Admin Account (If Needed)
|
||||
Your application has a separate script to create the initial admin user. To run it, you must first set the required environment variables in your shell session.
|
||||
|
||||
bash
|
||||
|
||||
# Set variables for the current session
|
||||
|
||||
export DB_USER=flyer_crawler_user DB_PASSWORD=your_password DB_NAME="flyer-crawler-prod" ...
|
||||
|
||||
# Run the seeding script
|
||||
|
||||
npx tsx src/db/seed_admin_account.ts
|
||||
Your production database is now ready!
|
||||
|
||||
@@ -284,8 +290,6 @@ Test Execution: Your tests run against this clean, isolated schema.
|
||||
|
||||
This approach is faster, more reliable, and removes the need for sudo access within the CI pipeline.
|
||||
|
||||
|
||||
|
||||
gitea-runner@projectium:~$ pm2 install pm2-logrotate
|
||||
[PM2][Module] Installing NPM pm2-logrotate module
|
||||
[PM2][Module] Calling [NPM] to install pm2-logrotate ...
|
||||
@@ -293,7 +297,7 @@ gitea-runner@projectium:~$ pm2 install pm2-logrotate
|
||||
added 161 packages in 5s
|
||||
|
||||
21 packages are looking for funding
|
||||
run `npm fund` for details
|
||||
run `npm fund` for details
|
||||
npm notice
|
||||
npm notice New patch version of npm available! 11.6.3 -> 11.6.4
|
||||
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.6.4
|
||||
@@ -308,7 +312,7 @@ $ pm2 set pm2-logrotate:retain 30
|
||||
$ pm2 set pm2-logrotate:compress false
|
||||
$ pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss
|
||||
$ pm2 set pm2-logrotate:workerInterval 30
|
||||
$ pm2 set pm2-logrotate:rotateInterval 0 0 * * *
|
||||
$ pm2 set pm2-logrotate:rotateInterval 0 0 \* \* _
|
||||
$ pm2 set pm2-logrotate:rotateModule true
|
||||
Modules configuration. Copy/Paste line to edit values.
|
||||
[PM2][Module] Module successfully installed and launched
|
||||
@@ -335,7 +339,7 @@ $ pm2 set pm2-logrotate:retain 30
|
||||
$ pm2 set pm2-logrotate:compress false
|
||||
$ pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss
|
||||
$ pm2 set pm2-logrotate:workerInterval 30
|
||||
$ pm2 set pm2-logrotate:rotateInterval 0 0 * * *
|
||||
$ pm2 set pm2-logrotate:rotateInterval 0 0 _ \* _
|
||||
$ pm2 set pm2-logrotate:rotateModule true
|
||||
gitea-runner@projectium:~$ pm2 set pm2-logrotate:retain 14
|
||||
[PM2] Module pm2-logrotate restarted
|
||||
@@ -346,31 +350,29 @@ $ pm2 set pm2-logrotate:retain 14
|
||||
$ pm2 set pm2-logrotate:compress false
|
||||
$ pm2 set pm2-logrotate:dateFormat YYYY-MM-DD_HH-mm-ss
|
||||
$ pm2 set pm2-logrotate:workerInterval 30
|
||||
$ pm2 set pm2-logrotate:rotateInterval 0 0 * * *
|
||||
$ pm2 set pm2-logrotate:rotateInterval 0 0 _ \* \*
|
||||
$ pm2 set pm2-logrotate:rotateModule true
|
||||
gitea-runner@projectium:~$
|
||||
|
||||
|
||||
|
||||
|
||||
## dev server setup:
|
||||
|
||||
Here are the steps to set up the development environment on Windows using Podman with an Ubuntu container:
|
||||
|
||||
1. Install Prerequisites on Windows
|
||||
Install WSL 2: Podman on Windows relies on the Windows Subsystem for Linux. Install it by running wsl --install in an administrator PowerShell.
|
||||
Install Podman Desktop: Download and install Podman Desktop for Windows.
|
||||
Install WSL 2: Podman on Windows relies on the Windows Subsystem for Linux. Install it by running wsl --install in an administrator PowerShell.
|
||||
Install Podman Desktop: Download and install Podman Desktop for Windows.
|
||||
|
||||
2. Set Up Podman
|
||||
Initialize Podman: Launch Podman Desktop. It will automatically set up its WSL 2 machine.
|
||||
Start Podman: Ensure the Podman machine is running from the Podman Desktop interface.
|
||||
Initialize Podman: Launch Podman Desktop. It will automatically set up its WSL 2 machine.
|
||||
Start Podman: Ensure the Podman machine is running from the Podman Desktop interface.
|
||||
|
||||
3. Set Up the Ubuntu Container
|
||||
- Pull Ubuntu Image: Open a PowerShell or command prompt and pull the latest Ubuntu image:
|
||||
|
||||
- Pull Ubuntu Image: Open a PowerShell or command prompt and pull the latest Ubuntu image:
|
||||
podman pull ubuntu:latest
|
||||
- Create a Podman Volume: Create a volume to persist node_modules and avoid installing them every time the container starts.
|
||||
- Create a Podman Volume: Create a volume to persist node_modules and avoid installing them every time the container starts.
|
||||
podman volume create node_modules_cache
|
||||
- Run the Ubuntu Container: Start a new container with the project directory mounted and the necessary ports forwarded.
|
||||
- Run the Ubuntu Container: Start a new container with the project directory mounted and the necessary ports forwarded.
|
||||
- Open a terminal in your project's root directory on Windows.
|
||||
- Run the following command, replacing D:\gitea\flyer-crawler.projectium.com\flyer-crawler.projectium.com with the full path to your project:
|
||||
|
||||
@@ -385,16 +387,16 @@ podman run -it -p 3001:3001 -p 5173:5173 --name flyer-dev -v "D:\gitea\flyer-cra
|
||||
4. Configure the Ubuntu Environment
|
||||
You are now inside the Ubuntu container's shell.
|
||||
|
||||
- Update Package Lists:
|
||||
- Update Package Lists:
|
||||
apt-get update
|
||||
- Install Dependencies: Install curl, git, and nodejs (which includes npm).
|
||||
- Install Dependencies: Install curl, git, and nodejs (which includes npm).
|
||||
apt-get install -y curl git
|
||||
curl -sL https://deb.nodesource.com/setup_20.x | bash -
|
||||
apt-get install -y nodejs
|
||||
- Navigate to Project Directory:
|
||||
- Navigate to Project Directory:
|
||||
cd /app
|
||||
|
||||
- Install Project Dependencies:
|
||||
- Install Project Dependencies:
|
||||
npm install
|
||||
|
||||
5. Run the Development Server
|
||||
@@ -402,27 +404,21 @@ podman run -it -p 3001:3001 -p 5173:5173 --name flyer-dev -v "D:\gitea\flyer-cra
|
||||
npm run dev
|
||||
|
||||
6. Accessing the Application
|
||||
- Frontend: Open your browser and go to http://localhost:5173.
|
||||
- Backend: The frontend will make API calls to http://localhost:3001.
|
||||
|
||||
- Frontend: Open your browser and go to http://localhost:5173.
|
||||
- Backend: The frontend will make API calls to http://localhost:3001.
|
||||
|
||||
Managing the Environment
|
||||
- Stopping the Container: Press Ctrl+C in the container terminal, then type exit.
|
||||
- Restarting the Container:
|
||||
|
||||
- Stopping the Container: Press Ctrl+C in the container terminal, then type exit.
|
||||
- Restarting the Container:
|
||||
podman start -a -i flyer-dev
|
||||
|
||||
|
||||
|
||||
## for me:
|
||||
|
||||
cd /mnt/d/gitea/flyer-crawler.projectium.com/flyer-crawler.projectium.com
|
||||
podman run -it -p 3001:3001 -p 5173:5173 --name flyer-dev -v "$(pwd):/app" -v "node_modules_cache:/app/node_modules" ubuntu:latest
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
rate limiting
|
||||
|
||||
respect the AI service's rate limits, making it more stable and robust. You can adjust the GEMINI_RPM environment variable in your production environment as needed without changing the code.
|
||||
@@ -1,21 +1,21 @@
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
import pluginReact from "eslint-plugin-react";
|
||||
import pluginReactHooks from "eslint-plugin-react-hooks";
|
||||
import pluginReactRefresh from "eslint-plugin-react-refresh";
|
||||
import globals from 'globals';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import pluginReact from 'eslint-plugin-react';
|
||||
import pluginReactHooks from 'eslint-plugin-react-hooks';
|
||||
import pluginReactRefresh from 'eslint-plugin-react-refresh';
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
// Global ignores
|
||||
ignores: ["dist", ".gitea", "node_modules", "*.cjs"],
|
||||
ignores: ['dist', '.gitea', 'node_modules', '*.cjs'],
|
||||
},
|
||||
{
|
||||
// All files
|
||||
files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"],
|
||||
files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'],
|
||||
plugins: {
|
||||
react: pluginReact,
|
||||
"react-hooks": pluginReactHooks,
|
||||
"react-refresh": pluginReactRefresh,
|
||||
'react-hooks': pluginReactHooks,
|
||||
'react-refresh': pluginReactRefresh,
|
||||
},
|
||||
languageOptions: {
|
||||
globals: {
|
||||
@@ -24,10 +24,7 @@ export default tseslint.config(
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
"react-refresh/only-export-components": [
|
||||
"warn",
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
||||
},
|
||||
},
|
||||
// TypeScript files
|
||||
|
||||
2
express.d.ts
vendored
2
express.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
// src/types/express.d.ts
|
||||
// express.d.ts
|
||||
import { Logger } from 'pino';
|
||||
|
||||
/**
|
||||
|
||||
14
index.html
14
index.html
@@ -1,8 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Grocery Flyer AI Analyzer</title>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||
@@ -11,10 +11,10 @@
|
||||
}
|
||||
</style>
|
||||
<!-- The stylesheet will be injected here by Vite during the build process -->
|
||||
</head>
|
||||
<body>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<!-- Vite will inject the correct <script> tag here during the build process -->
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"name": "Flyer Crawler",
|
||||
"description": "Upload a grocery store flyer image to extract item details, prices, and quantities using AI. Get insights, meal plans, and compare prices to save money on your shopping.",
|
||||
"requestFramePermissions": [
|
||||
"geolocation",
|
||||
"microphone"
|
||||
]
|
||||
"requestFramePermissions": ["geolocation", "microphone"]
|
||||
}
|
||||
@@ -10,7 +10,10 @@ const tailwindConfigPath = path.resolve(process.cwd(), 'tailwind.config.js');
|
||||
console.log(`[POSTCSS] Attempting to use Tailwind config at: ${tailwindConfigPath}`);
|
||||
|
||||
// Log to prove the imported config object is what we expect
|
||||
console.log('[POSTCSS] Imported tailwind.config.js object:', JSON.stringify(tailwindConfig, null, 2));
|
||||
console.log(
|
||||
'[POSTCSS] Imported tailwind.config.js object:',
|
||||
JSON.stringify(tailwindConfig, null, 2),
|
||||
);
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
This single directive replaces @tailwind base, components, and utilities.
|
||||
It is the new entry point for all of Tailwind's generated CSS.
|
||||
*/
|
||||
@import "tailwindcss";
|
||||
@import 'tailwindcss';
|
||||
|
||||
/*
|
||||
This is the new v4 directive that tells the @tailwindcss/postcss plugin
|
||||
@@ -12,4 +12,3 @@
|
||||
Since tailwind.config.js is in the root and this is in src/, the path is '../tailwind.config.js'.
|
||||
*/
|
||||
@config '../tailwind.config.js';
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import './index.css';
|
||||
|
||||
const rootElement = document.getElementById('root');
|
||||
if (!rootElement) {
|
||||
throw new Error("Could not find root element to mount to");
|
||||
throw new Error('Could not find root element to mount to');
|
||||
}
|
||||
|
||||
const root = ReactDOM.createRoot(rootElement);
|
||||
@@ -19,6 +19,5 @@ root.render(
|
||||
<App />
|
||||
</AppProviders>
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
</React.StrictMode>,
|
||||
);
|
||||
|
||||
36
src/types.ts
36
src/types.ts
@@ -52,7 +52,10 @@ export type FlyerDbInsert = Omit<FlyerInsert, 'store_name'> & { store_id: number
|
||||
* Represents the data required to insert a new flyer item into the database.
|
||||
* It's a subset of the full FlyerItem type.
|
||||
*/
|
||||
export type FlyerItemInsert = Omit<FlyerItem, 'flyer_item_id' | 'flyer_id' | 'created_at' | 'updated_at'>;
|
||||
export type FlyerItemInsert = Omit<
|
||||
FlyerItem,
|
||||
'flyer_item_id' | 'flyer_id' | 'created_at' | 'updated_at'
|
||||
>;
|
||||
|
||||
export interface UnitPrice {
|
||||
value: number;
|
||||
@@ -163,7 +166,6 @@ export interface Profile {
|
||||
updated_by?: string | null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents the combined user and profile data object returned by the backend's /users/profile endpoint.
|
||||
* It embeds the User object within the Profile object.
|
||||
@@ -325,7 +327,6 @@ export interface RecipeIngredientSubstitution {
|
||||
notes?: string | null;
|
||||
}
|
||||
|
||||
|
||||
export interface Tag {
|
||||
tag_id: number;
|
||||
name: string;
|
||||
@@ -718,7 +719,10 @@ export type AiAnalysisAction =
|
||||
// Dispatched when an analysis that returns a simple string succeeds.
|
||||
| { type: 'FETCH_SUCCESS_TEXT'; payload: { analysisType: AnalysisType; data: string } }
|
||||
// Dispatched when an analysis that returns text and sources succeeds.
|
||||
| { type: 'FETCH_SUCCESS_GROUNDED'; payload: { analysisType: AnalysisType; data: GroundedResponse } }
|
||||
| {
|
||||
type: 'FETCH_SUCCESS_GROUNDED';
|
||||
payload: { analysisType: AnalysisType; data: GroundedResponse };
|
||||
}
|
||||
// Dispatched when the image generation succeeds.
|
||||
| { type: 'FETCH_SUCCESS_IMAGE'; payload: { data: string } }
|
||||
// Dispatched when any analysis fails.
|
||||
@@ -738,11 +742,25 @@ export interface ProcessingStage {
|
||||
}
|
||||
|
||||
export const CATEGORIES = [
|
||||
'Fruits & Vegetables', 'Meat & Seafood', 'Dairy & Eggs', 'Bakery & Bread',
|
||||
'Pantry & Dry Goods', 'Beverages', 'Frozen Foods', 'Snacks', 'Household & Cleaning',
|
||||
'Personal Care & Health', 'Baby & Child', 'Pet Supplies', 'Deli & Prepared Foods',
|
||||
'Canned Goods', 'Condiments & Spices', 'Breakfast & Cereal', 'Organic',
|
||||
'International Foods', 'Other/Miscellaneous'
|
||||
'Fruits & Vegetables',
|
||||
'Meat & Seafood',
|
||||
'Dairy & Eggs',
|
||||
'Bakery & Bread',
|
||||
'Pantry & Dry Goods',
|
||||
'Beverages',
|
||||
'Frozen Foods',
|
||||
'Snacks',
|
||||
'Household & Cleaning',
|
||||
'Personal Care & Health',
|
||||
'Baby & Child',
|
||||
'Pet Supplies',
|
||||
'Deli & Prepared Foods',
|
||||
'Canned Goods',
|
||||
'Condiments & Spices',
|
||||
'Breakfast & Cereal',
|
||||
'Organic',
|
||||
'International Foods',
|
||||
'Other/Miscellaneous',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,5 @@ console.log('--- [EXECUTION PROOF] tailwind.config.js is being loaded. ---');
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||
};
|
||||
@@ -17,9 +17,7 @@
|
||||
"jsx": "react-jsx",
|
||||
// This line makes Vitest's global APIs (describe, it, expect) available everywhere
|
||||
// without needing to import them.
|
||||
"types": [
|
||||
"vitest/globals"
|
||||
]
|
||||
"types": ["vitest/globals"]
|
||||
},
|
||||
// This is the most important part: It tells TypeScript to include ALL files
|
||||
// within the 'src' directory, including your new 'vite-env.d.ts' file.
|
||||
|
||||
@@ -9,5 +9,10 @@
|
||||
"strict": true, // It's good practice to keep tooling config strict
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["vite.config.ts", "vitest.config.ts", "vitest.config.integration.ts", "vitest.workspace.ts"]
|
||||
"include": [
|
||||
"vite.config.ts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.integration.ts",
|
||||
"vitest.workspace.ts"
|
||||
]
|
||||
}
|
||||
@@ -51,7 +51,7 @@ export default defineConfig({
|
||||
'**/node_modules/**',
|
||||
'**/dist/**',
|
||||
'src/tests/integration/**', // Exclude the entire integration test directory
|
||||
'**/*.e2e.test.ts'
|
||||
'**/*.e2e.test.ts',
|
||||
],
|
||||
// Disable file parallelism to run tests sequentially (replaces --no-threads)
|
||||
fileParallelism: false,
|
||||
@@ -60,7 +60,9 @@ export default defineConfig({
|
||||
reporter: [
|
||||
// Add maxCols to suggest a wider output for the text summary.
|
||||
['text', { maxCols: 200 }],
|
||||
'html', 'json'],
|
||||
'html',
|
||||
'json',
|
||||
],
|
||||
// hanging-process reporter helps identify tests that do not exit properly - comes at a high cost tho
|
||||
//reporter: ['verbose', 'html', 'json', 'hanging-process'],
|
||||
reportsDirectory: './.coverage/unit',
|
||||
|
||||
@@ -30,7 +30,9 @@ console.error('[DEBUG] Base vite config keys:', Object.keys(baseViteConfig));
|
||||
* It MERGES with the main vite.config.ts to inherit plugins and aliases,
|
||||
* then overrides the test-specific settings for a Node.js environment.
|
||||
*/
|
||||
const finalConfig = mergeConfig(baseViteConfig, defineConfig({
|
||||
const finalConfig = mergeConfig(
|
||||
baseViteConfig,
|
||||
defineConfig({
|
||||
test: {
|
||||
// Override settings from the main config for this specific test project.
|
||||
name: 'integration',
|
||||
@@ -57,8 +59,9 @@ const finalConfig = mergeConfig(baseViteConfig, defineConfig({
|
||||
reportOnFailure: true, // This ensures the report generates even if tests fail
|
||||
clean: true,
|
||||
},
|
||||
}
|
||||
}));
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
console.error('[DEBUG] Integration Final Config - INCLUDE:', finalConfig.test?.include);
|
||||
console.error('[DEBUG] Integration Final Config - EXCLUDE:', finalConfig.test?.exclude);
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
*/
|
||||
export default [
|
||||
// DEBUGGING LOG
|
||||
((): string => { console.error('\n[DEBUG] Loading vitest.workspace.ts'); return ''; })(),
|
||||
((): string => {
|
||||
console.error('\n[DEBUG] Loading vitest.workspace.ts');
|
||||
return '';
|
||||
})(),
|
||||
'vite.config.ts', // Defines the 'unit' test project
|
||||
'vitest.config.integration.ts', // Defines the 'integration' test project
|
||||
];
|
||||
Reference in New Issue
Block a user