🧑‍💻 Improve developer experience (#1140)

This commit is contained in:
Luke Vella 2024-06-09 22:08:02 +01:00 committed by GitHub
parent 34fa288069
commit 685f49b4c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 181 additions and 138 deletions

View file

@ -1,11 +1,19 @@
# A random 32-character secret key used to encrypt user sessions # A random 32-character secret key used to encrypt user sessions
SECRET_PASSWORD=abcdef1234567890abcdef1234567890 SECRET_PASSWORD=abcdef1234567890abcdef1234567890
# The base url where this instance is accessible, including the scheme. # The base url where this instance is accessible, including the scheme.
# Example: https://example.com # Example: https://example.com
NEXT_PUBLIC_BASE_URL=http://localhost:3000 NEXT_PUBLIC_BASE_URL=http://localhost:3000
NEXTAUTH_URL=$NEXT_PUBLIC_BASE_URL NEXTAUTH_URL=$NEXT_PUBLIC_BASE_URL
# A connection string to your Postgres database # A connection string to your Postgres database
DATABASE_URL="postgres://postgres:postgres@localhost:5450/db" DATABASE_URL="postgres://postgres:postgres@localhost:5450/rallly"
# Required to be able to send emails
SUPPORT_EMAIL=support@rallly.co
# Toggle Self-Hosted mode
NEXT_PUBLIC_SELF_HOSTED=false
# Suppress warning from sentry during local development # Suppress warning from sentry during local development
SENTRY_IGNORE_API_RESOLUTION_ERROR=1 SENTRY_IGNORE_API_RESOLUTION_ERROR=1

19
.github/actions/setup-node/action.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: "Setup Node.js"
description: "Sets up a consistent Node.js environment"
inputs:
node-version:
description: "Node.js version"
required: true
default: "18"
cache:
description: "Package manager for caching"
required: false
default: "yarn"
runs:
using: "composite"
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: ${{ inputs.cache }}

View file

@ -0,0 +1,8 @@
name: "Yarn Install"
description: "Runs yarn install with --frozen-lockfile"
runs:
using: "composite"
steps:
- name: Run yarn install
run: yarn install --frozen-lockfile
shell: bash

View file

@ -7,76 +7,98 @@ on:
branches: branches:
- main - main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs: jobs:
linting: changes:
name: Linting name: Check for changes
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: permissions:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} pull-requests: read
TURBO_TEAM: ${{ vars.TURBO_TEAM }} outputs:
has-files-requiring-all-checks: ${{ steps.filter.outputs.has-files-requiring-all-checks }}
steps: steps:
- name: Check out repository code - uses: actions/checkout@v4
uses: actions/checkout@v4 - uses: dorny/paths-filter@v3
id: filter
- name: Setup node
uses: actions/setup-node@v4
with: with:
node-version: 18 filters: |
cache: yarn has-files-requiring-all-checks:
- "!(**.md|.github)"
- name: Install dependencies type-check:
run: yarn install --frozen-lockfile name: Type check
runs-on: ubuntu-latest
- name: Check linting rules needs: changes
run: yarn lint if: ${{ needs.changes.outputs.has-files-requiring-all-checks == 'true' }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-node
- uses: ./.github/actions/yarn-install
- name: Check types - name: Check types
run: yarn lint:tsc run: yarn lint:tsc
linting:
name: Linting
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.has-files-requiring-all-checks == 'true' }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-node
- uses: ./.github/actions/yarn-install
- name: Check linting rules
run: yarn lint
unit-tests:
name: Unit tests
needs: changes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-node
- uses: ./.github/actions/yarn-install
- name: Run tests
run: yarn test:unit
# Label of the container job # Label of the container job
integration-tests: integration-tests:
name: Run tests name: Integration tests
# Containers must run in Linux based operating systems needs: changes
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
steps: steps:
# Downloads a copy of the code in your repository before running CI tests - uses: actions/checkout@v4
- name: Check out repository code - uses: ./.github/actions/setup-node
uses: actions/checkout@v4 - uses: ./.github/actions/yarn-install
- name: Install system dependencies - name: Install system dependencies
run: | run: |
sudo apt-get update sudo apt-get update
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 18
cache: yarn
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Set environment variables
run: |
echo "DATABASE_URL=postgresql://postgres:password@localhost:5450/db" >> $GITHUB_ENV
- name: Run db
run: |
docker pull postgres:14.2
docker run -d -p 5450:5432 -e POSTGRES_PASSWORD=password -e POSTGRES_DB=rallly postgres:14.2
yarn wait-on --timeout 60000 tcp:localhost:5450
- name: Deploy migrations
run: yarn db:setup
- name: Install playwright dependencies - name: Install playwright dependencies
run: yarn playwright install --with-deps chromium run: yarn playwright install --with-deps chromium
- name: Set environment variables
run: |
echo "DATABASE_URL=postgresql://postgres:postgres@localhost:5450/rallly" >> $GITHUB_ENV
- name: Create production build
run: yarn turbo build:test --filter=@rallly/web
- name: Generate Prisma Client
run: yarn db:generate
- name: Set up database
run: |
yarn dx
- name: Run tests - name: Run tests
run: yarn test run: yarn test:integration
- name: Upload artifact playwright-report - name: Upload artifact playwright-report
if: ${{ success() || failure() }} if: ${{ success() || failure() }}

4
.gitignore vendored
View file

@ -39,3 +39,7 @@ tsconfig.tsbuildinfo
# Jetbrains IDE # Jetbrains IDE
.idea .idea
# Playwright
playwright-report
test-results

View file

@ -18,9 +18,7 @@
"@rallly/tailwind-config": "*", "@rallly/tailwind-config": "*",
"@rallly/ui": "*", "@rallly/ui": "*",
"@svgr/webpack": "^6.5.1", "@svgr/webpack": "^6.5.1",
"@tailwindcss/typography": "^0.5.9",
"@vercel/analytics": "^0.1.8", "@vercel/analytics": "^0.1.8",
"autoprefixer": "^10.4.13",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",

View file

@ -1,6 +1,7 @@
PORT=3002 PORT=3002
NEXT_PUBLIC_BASE_URL=http://localhost:3002 NEXT_PUBLIC_BASE_URL=http://localhost:3002
NEXTAUTH_URL=http://localhost:3002 NEXTAUTH_URL=$NEXT_PUBLIC_BASE_URL
SECRET_PASSWORD=abcdefghijklmnopqrstuvwxyz1234567890 SECRET_PASSWORD=abcdef1234567890abcdef1234567890
DATABASE_URL=postgres://postgres:postgres@localhost:5450/db DATABASE_URL=postgres://postgres:postgres@localhost:5450/rallly
SUPPORT_EMAIL=support@rallly.co SUPPORT_EMAIL=support@rallly.co
SMTP_PORT=4025

View file

@ -12,7 +12,7 @@
"lint:tsc": "tsc --noEmit", "lint:tsc": "tsc --noEmit",
"i18n:scan": "i18next-scanner --config i18next-scanner.config.js", "i18n:scan": "i18next-scanner --config i18next-scanner.config.js",
"prettier": "prettier --write ./src", "prettier": "prettier --write ./src",
"test:e2e": "playwright test", "test:integration": "playwright test",
"test:unit": "vitest run", "test:unit": "vitest run",
"test": "yarn test:unit && yarn test:e2e", "test": "yarn test:unit && yarn test:e2e",
"test:codegen": "playwright codegen http://localhost:3000", "test:codegen": "playwright codegen http://localhost:3000",
@ -31,7 +31,6 @@
"@rallly/tailwind-config": "*", "@rallly/tailwind-config": "*",
"@rallly/ui": "*", "@rallly/ui": "*",
"@svgr/webpack": "^6.5.1", "@svgr/webpack": "^6.5.1",
"@tailwindcss/typography": "^0.5.9",
"@tanstack/react-query": "^4.0.0", "@tanstack/react-query": "^4.0.0",
"@tanstack/react-table": "^8.9.1", "@tanstack/react-table": "^8.9.1",
"@trpc/client": "^10.13.0", "@trpc/client": "^10.13.0",

View file

@ -6,11 +6,9 @@ const ci = process.env.CI === "true";
dotenv.config({ path: path.resolve(__dirname, ".env.test") }); dotenv.config({ path: path.resolve(__dirname, ".env.test") });
// Use process.env.PORT by default and fallback to port 3000 const port = process.env.PORT || 3000;
const PORT = process.env.PORT || 3000;
// Set webServer.url and use.baseURL with the location of the WebServer respecting the correct set port // Set webServer.url and use.baseURL with the location of the WebServer respecting the correct set port
const baseURL = `http://localhost:${PORT}`; const baseURL = `http://localhost:${port}`;
// Reference: https://playwright.dev/docs/test-configuration // Reference: https://playwright.dev/docs/test-configuration
const config: PlaywrightTestConfig = { const config: PlaywrightTestConfig = {
@ -24,11 +22,17 @@ const config: PlaywrightTestConfig = {
trace: "retain-on-failure", trace: "retain-on-failure",
}, },
testDir: "./tests", testDir: "./tests",
webServer: { webServer: ci
command: `NODE_ENV=test yarn start --port ${PORT}`, ? {
url: baseURL, command: `NODE_ENV=test next start --port ${port}`,
reuseExistingServer: !process.env.CI, url: baseURL,
}, reuseExistingServer: false,
}
: {
command: `NODE_ENV=test next dev --port ${port}`,
url: baseURL,
reuseExistingServer: true,
},
reporter: [ reporter: [
[ci ? "github" : "list"], [ci ? "github" : "list"],
["html", { open: !ci ? "on-failure" : "never" }], ["html", { open: !ci ? "on-failure" : "never" }],

View file

@ -6,15 +6,12 @@ const env = process.env["NODE" + "_ENV"];
export const emailClient = new EmailClient({ export const emailClient = new EmailClient({
openPreviews: env === "development", openPreviews: env === "development",
useTestServer: env === "test",
provider: { provider: {
name: (process.env.EMAIL_PROVIDER as SupportedEmailProviders) ?? "smtp", name: (process.env.EMAIL_PROVIDER as SupportedEmailProviders) ?? "smtp",
}, },
mail: { mail: {
from: { from: {
name: name: (process.env.NOREPLY_EMAIL_NAME as string) || "Rallly",
(process.env.NOREPLY_EMAIL_NAME as string) ||
"Rallly",
address: address:
(process.env.NOREPLY_EMAIL as string) || (process.env.NOREPLY_EMAIL as string) ||
(process.env.SUPPORT_EMAIL as string), (process.env.SUPPORT_EMAIL as string),

20
docker-compose.dev.yml Normal file
View file

@ -0,0 +1,20 @@
services:
rallly_db:
image: postgres:14.2
restart: always
ports:
- "5450:5432"
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=rallly
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
db-data:
driver: local

View file

@ -1,27 +0,0 @@
services:
rallly_db:
image: postgres:14.2
restart: always
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=db
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
rallly:
build:
context: .
dockerfile: ./apps/web/Dockerfile
restart: always
depends_on:
rallly_db:
condition: service_healthy
ports:
- 3000:3000
environment:
- DATABASE_URL=postgres://postgres:postgres@rallly_db:5432/db
- NODE_ENV=test
- SECRET_PASSWORD=abcdefghijklmnopqrstuvwxyz1234567890

View file

@ -8,7 +8,7 @@ services:
- db-data:/var/lib/postgresql/data - db-data:/var/lib/postgresql/data
environment: environment:
- POSTGRES_PASSWORD=postgres - POSTGRES_PASSWORD=postgres
- POSTGRES_DB=db - POSTGRES_DB=rallly
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"] test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s interval: 5s
@ -28,7 +28,7 @@ services:
ports: ports:
- 3000:3000 - 3000:3000
environment: environment:
- DATABASE_URL=postgres://postgres:postgres@rallly_db:5450/db - DATABASE_URL=postgres://postgres:postgres@rallly_db:5450/rallly
env_file: env_file:
- .env - .env

View file

@ -3,6 +3,7 @@
"private": true, "private": true,
"version": "3.7.0", "version": "3.7.0",
"scripts": { "scripts": {
"dx": "run-s docker:up db:setup",
"dev": "dotenv -c development -- turbo dev --filter=@rallly/web", "dev": "dotenv -c development -- turbo dev --filter=@rallly/web",
"dev:emails": "turbo dev --filter=@rallly/emails", "dev:emails": "turbo dev --filter=@rallly/emails",
"dev:landing": "dotenv -c development turbo dev --filter=@rallly/landing", "dev:landing": "dotenv -c development turbo dev --filter=@rallly/landing",
@ -14,12 +15,11 @@
"db:generate": "turbo db:generate", "db:generate": "turbo db:generate",
"db:migrate": "prisma migrate dev", "db:migrate": "prisma migrate dev",
"db:reset": "prisma migrate reset", "db:reset": "prisma migrate reset",
"db:up": "docker compose up -d rallly_db && wait-on --timeout 60000 tcp:localhost:5450",
"db:seed": "yarn workspace @rallly/database db:seed", "db:seed": "yarn workspace @rallly/database db:seed",
"db:down": "docker compose down --volumes --remove-orphans rallly_db", "docker:up": "docker compose -f docker-compose.dev.yml up -d && wait-on --timeout 60000 tcp:localhost:5450",
"docker:down": "docker compose -f docker-compose.dev.yml down --volumes --remove-orphans",
"db:setup": "run-s db:deploy db:generate db:seed", "db:setup": "run-s db:deploy db:generate db:seed",
"dx": "run-s db:up db:setup", "test:integration": "turbo test:integration",
"test": "turbo build:test && turbo test",
"test:unit": "turbo test:unit", "test:unit": "turbo test:unit",
"lint": "turbo lint", "lint": "turbo lint",
"i18n:scan": "turbo i18n:scan", "i18n:scan": "turbo i18n:scan",
@ -35,6 +35,7 @@
"packages/*" "packages/*"
], ],
"dependencies": { "dependencies": {
"@prisma/client": "^5.3.1",
"@sentry/nextjs": "^7.77.0", "@sentry/nextjs": "^7.77.0",
"framer-motion": "^10.16.4", "framer-motion": "^10.16.4",
"next": "^14.0.4", "next": "^14.0.4",
@ -44,6 +45,7 @@
"zod": "^3.22.3" "zod": "^3.22.3"
}, },
"devDependencies": { "devDependencies": {
"tailwindcss": "^3.4.4",
"@types/react": "^18.2.48", "@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.18",
"dotenv-cli": "^7.1.0", "dotenv-cli": "^7.1.0",

View file

@ -11,9 +11,6 @@
}, },
"main": "./index.ts", "main": "./index.ts",
"types": "./index.ts", "types": "./index.ts",
"dependencies": {
"@prisma/client": "^5.3.1"
},
"devDependencies": { "devDependencies": {
"@faker-js/faker": "^7.6.0", "@faker-js/faker": "^7.6.0",
"@rallly/tsconfig": "*", "@rallly/tsconfig": "*",

View file

@ -43,10 +43,6 @@ type EmailClientConfig = {
* Whether to open previews of each email in the browser * Whether to open previews of each email in the browser
*/ */
openPreviews?: boolean; openPreviews?: boolean;
/**
* Whether to send emails to the test server
*/
useTestServer: boolean;
/** /**
* Email provider config * Email provider config
*/ */
@ -132,13 +128,6 @@ export class EmailClient {
return this.cachedTransport; return this.cachedTransport;
} }
if (this.config.useTestServer) {
this.cachedTransport = createTransport({
port: 4025,
});
return this.cachedTransport;
}
switch (this.config.provider.name) { switch (this.config.provider.name) {
case "ses": { case "ses": {
const ses = new aws.SES({ const ses = new aws.SES({

View file

@ -4,10 +4,9 @@
"private": true, "private": true,
"main": "tailwind.config.js", "main": "tailwind.config.js",
"types": "tailwind.config.d.ts", "types": "tailwind.config.d.ts",
"dependencies": {
"tailwindcss": "^3.4.1"
},
"devDependencies": { "devDependencies": {
"autoprefixer": "^10.4.13",
"@tailwindcss/typography": "^0.5.13",
"tailwind-scrollbar": "^3.0.4", "tailwind-scrollbar": "^3.0.4",
"tailwindcss-animate": "^1.0.5" "tailwindcss-animate": "^1.0.5"
} }

View file

@ -27,6 +27,9 @@
"test:unit": { "test:unit": {
"cache": true "cache": true
}, },
"test:integration": {
"cache": true
},
"db:generate": { "db:generate": {
"dependsOn": ["^db:generate"] "dependsOn": ["^db:generate"]
}, },

View file

@ -4113,10 +4113,10 @@
resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.5.tgz#043b731d4f56a79b4897a3de1af35e75d56bc63a" resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.5.tgz#043b731d4f56a79b4897a3de1af35e75d56bc63a"
integrity sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw== integrity sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==
"@tailwindcss/typography@^0.5.9": "@tailwindcss/typography@^0.5.13":
version "0.5.9" version "0.5.13"
resolved "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.9.tgz" resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.13.tgz#cd788a4fa4d0ca2506e242d512f377b22c1f7932"
integrity sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg== integrity sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==
dependencies: dependencies:
lodash.castarray "^4.4.0" lodash.castarray "^4.4.0"
lodash.isplainobject "^4.0.6" lodash.isplainobject "^4.0.6"
@ -5553,15 +5553,10 @@ camelcase@^6.2.0:
resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449: caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001580:
version "1.0.30001534" version "1.0.30001629"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001534.tgz" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001629.tgz"
integrity sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q== integrity sha512-c3dl911slnQhmxUIT4HhYzT7wnBK/XYpGnYLOj4nJBaRiw52Ibe7YxlDaAeRECvA786zCuExhxIUJ2K7nHMrBw==
caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001580:
version "1.0.30001580"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz#e3c76bc6fe020d9007647044278954ff8cd17d1e"
integrity sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==
ccount@^2.0.0: ccount@^2.0.0:
version "2.0.1" version "2.0.1"
@ -8482,6 +8477,11 @@ jiti@^1.19.1:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
jiti@^1.21.0:
version "1.21.3"
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.3.tgz#b2adb07489d7629b344d59082bbedb8c21c5f755"
integrity sha512-uy2bNX5zQ+tESe+TiC7ilGRz8AtRGmnJH55NC5S0nSUjvvvM2hJHmefHErugGXN4pNv4Qx7vLsnNw9qJ9mtIsw==
joi@^17.6.0: joi@^17.6.0:
version "17.8.3" version "17.8.3"
resolved "https://registry.npmjs.org/joi/-/joi-17.8.3.tgz" resolved "https://registry.npmjs.org/joi/-/joi-17.8.3.tgz"
@ -11861,10 +11861,10 @@ tailwindcss@3.4.0:
resolve "^1.22.2" resolve "^1.22.2"
sucrase "^3.32.0" sucrase "^3.32.0"
tailwindcss@^3.4.1: tailwindcss@^3.4.4:
version "3.4.1" version "3.4.4"
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.1.tgz#f512ca5d1dd4c9503c7d3d28a968f1ad8f5c839d" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.4.tgz#351d932273e6abfa75ce7d226b5bf3a6cb257c05"
integrity sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA== integrity sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==
dependencies: dependencies:
"@alloc/quick-lru" "^5.2.0" "@alloc/quick-lru" "^5.2.0"
arg "^5.0.2" arg "^5.0.2"
@ -11874,7 +11874,7 @@ tailwindcss@^3.4.1:
fast-glob "^3.3.0" fast-glob "^3.3.0"
glob-parent "^6.0.2" glob-parent "^6.0.2"
is-glob "^4.0.3" is-glob "^4.0.3"
jiti "^1.19.1" jiti "^1.21.0"
lilconfig "^2.1.0" lilconfig "^2.1.0"
micromatch "^4.0.5" micromatch "^4.0.5"
normalize-path "^3.0.0" normalize-path "^3.0.0"