+ Change Password
+
+
+
To change your password, please fill out the following. Your password
should be at least 8 characters.
diff --git a/pages/tags/[id].tsx b/pages/tags/[id].tsx
index 466c3bb..5859c2a 100644
--- a/pages/tags/[id].tsx
+++ b/pages/tags/[id].tsx
@@ -11,10 +11,9 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useRouter } from "next/router";
import { FormEvent, useEffect, useState } from "react";
import MainLayout from "@/layouts/MainLayout";
-import { Tag } from "@prisma/client";
import useTagStore from "@/store/tags";
import SortDropdown from "@/components/SortDropdown";
-import { Sort } from "@/types/global";
+import { Sort, TagIncludingLinkCount } from "@/types/global";
import useLinks from "@/hooks/useLinks";
import Dropdown from "@/components/Dropdown";
import { toast } from "react-hot-toast";
@@ -33,7 +32,7 @@ export default function Index() {
const [renameTag, setRenameTag] = useState(false);
const [newTagName, setNewTagName] = useState();
- const [activeTag, setActiveTag] = useState();
+ const [activeTag, setActiveTag] = useState();
useLinks({ tagId: Number(router.query.id), sort: sortBy });
diff --git a/prisma/migrations/20231105202241_modify_user_password/migration.sql b/prisma/migrations/20231105202241_modify_user_password/migration.sql
new file mode 100644
index 0000000..0b600a7
--- /dev/null
+++ b/prisma/migrations/20231105202241_modify_user_password/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "User" ALTER COLUMN "password" DROP NOT NULL;
diff --git a/prisma/migrations/20231108232127_recreate_table_account/migration.sql b/prisma/migrations/20231108232127_recreate_table_account/migration.sql
new file mode 100644
index 0000000..e9c9a7a
--- /dev/null
+++ b/prisma/migrations/20231108232127_recreate_table_account/migration.sql
@@ -0,0 +1,23 @@
+-- CreateTable
+CREATE TABLE "Account" (
+ "id" TEXT NOT NULL,
+ "userId" INTEGER NOT NULL,
+ "type" TEXT NOT NULL,
+ "provider" TEXT NOT NULL,
+ "providerAccountId" TEXT NOT NULL,
+ "refresh_token" TEXT,
+ "access_token" TEXT,
+ "expires_at" INTEGER,
+ "token_type" TEXT,
+ "scope" TEXT,
+ "id_token" TEXT,
+ "session_state" TEXT,
+
+ CONSTRAINT "Account_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account"("provider", "providerAccountId");
+
+-- AddForeignKey
+ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/prisma/migrations/20231120135053_add_apikeys_table/migration.sql b/prisma/migrations/20231120135053_add_apikeys_table/migration.sql
new file mode 100644
index 0000000..7798f17
--- /dev/null
+++ b/prisma/migrations/20231120135053_add_apikeys_table/migration.sql
@@ -0,0 +1,22 @@
+-- CreateTable
+CREATE TABLE "ApiKeys" (
+ "id" SERIAL NOT NULL,
+ "name" TEXT NOT NULL,
+ "userId" INTEGER NOT NULL,
+ "token" TEXT NOT NULL,
+ "expires" TIMESTAMP(3) NOT NULL,
+ "lastUsedAt" TIMESTAMP(3),
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+ CONSTRAINT "ApiKeys_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "ApiKeys_token_key" ON "ApiKeys"("token");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "ApiKeys_token_userId_key" ON "ApiKeys"("token", "userId");
+
+-- AddForeignKey
+ALTER TABLE "ApiKeys" ADD CONSTRAINT "ApiKeys_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
diff --git a/prisma/migrations/20231120135140_rename_apikeys_to_apikey/migration.sql b/prisma/migrations/20231120135140_rename_apikeys_to_apikey/migration.sql
new file mode 100644
index 0000000..809ec77
--- /dev/null
+++ b/prisma/migrations/20231120135140_rename_apikeys_to_apikey/migration.sql
@@ -0,0 +1,34 @@
+/*
+ Warnings:
+
+ - You are about to drop the `ApiKeys` table. If the table is not empty, all the data it contains will be lost.
+
+*/
+-- DropForeignKey
+ALTER TABLE "ApiKeys" DROP CONSTRAINT "ApiKeys_userId_fkey";
+
+-- DropTable
+DROP TABLE "ApiKeys";
+
+-- CreateTable
+CREATE TABLE "ApiKey" (
+ "id" SERIAL NOT NULL,
+ "name" TEXT NOT NULL,
+ "userId" INTEGER NOT NULL,
+ "token" TEXT NOT NULL,
+ "expires" TIMESTAMP(3) NOT NULL,
+ "lastUsedAt" TIMESTAMP(3),
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+ CONSTRAINT "ApiKey_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "ApiKey_token_key" ON "ApiKey"("token");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "ApiKey_token_userId_key" ON "ApiKey"("token", "userId");
+
+-- AddForeignKey
+ALTER TABLE "ApiKey" ADD CONSTRAINT "ApiKey_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
diff --git a/prisma/migrations/20231120184333_set_blurred_favicon_to_false_as_default/migration.sql b/prisma/migrations/20231120184333_set_blurred_favicon_to_false_as_default/migration.sql
new file mode 100644
index 0000000..0ab9036
--- /dev/null
+++ b/prisma/migrations/20231120184333_set_blurred_favicon_to_false_as_default/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "User" ALTER COLUMN "blurredFavicons" SET DEFAULT false;
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 269ea53..70ef764 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -7,46 +7,55 @@ datasource db {
url = env("DATABASE_URL")
}
+model Account {
+ id String @id @default(cuid())
+ userId Int
+ type String
+ provider String
+ providerAccountId String
+ refresh_token String?
+ access_token String?
+ expires_at Int?
+ token_type String?
+ scope String?
+ id_token String?
+ session_state String?
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+
+ @@unique([provider, providerAccountId])
+}
+
model User {
id Int @id @default(autoincrement())
name String
-
username String? @unique
-
email String? @unique
emailVerified DateTime?
image String?
-
- password String
-
+ accounts Account[]
+ password String?
collections Collection[]
tags Tag[]
pinnedLinks Link[]
collectionsJoined UsersAndCollections[]
whitelistedUsers WhitelistedUser[]
-
+ apiKeys ApiKey[]
subscriptions Subscription?
-
archiveAsScreenshot Boolean @default(true)
archiveAsPDF Boolean @default(true)
archiveAsWaybackMachine Boolean @default(false)
-
isPrivate Boolean @default(false)
-
displayLinkIcons Boolean @default(true)
- blurredFavicons Boolean @default(true)
-
+ blurredFavicons Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt @default(now())
}
model WhitelistedUser {
id Int @id @default(autoincrement())
-
username String @default("")
User User? @relation(fields: [userId], references: [id])
userId Int?
-
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt @default(now())
}
@@ -55,7 +64,6 @@ model VerificationToken {
identifier String
token String @unique
expires DateTime
-
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt @default(now())
@@ -68,13 +76,12 @@ model Collection {
description String @default("")
color String @default("#0ea5e9")
isPublic Boolean @default(false)
-
- owner User @relation(fields: [ownerId], references: [id])
- ownerId Int
- members UsersAndCollections[]
- links Link[]
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt @default(now())
+ owner User @relation(fields: [ownerId], references: [id])
+ ownerId Int
+ members UsersAndCollections[]
+ links Link[]
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt @default(now())
@@unique([name, ownerId])
}
@@ -82,16 +89,13 @@ model Collection {
model UsersAndCollections {
user User @relation(fields: [userId], references: [id])
userId Int
-
collection Collection @relation(fields: [collectionId], references: [id])
collectionId Int
-
canCreate Boolean
canUpdate Boolean
canDelete Boolean
-
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt @default(now())
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt @default(now())
@@id([userId, collectionId])
}
@@ -101,32 +105,25 @@ model Link {
name String
url String
description String @default("")
-
pinnedBy User[]
-
collection Collection @relation(fields: [collectionId], references: [id])
collectionId Int
tags Tag[]
-
textContent String?
-
screenshotPath String?
pdfPath String?
readabilityPath String?
-
lastPreserved DateTime?
-
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt @default(now())
}
model Tag {
- id Int @id @default(autoincrement())
- name String
- links Link[]
- owner User @relation(fields: [ownerId], references: [id])
- ownerId Int
-
+ id Int @id @default(autoincrement())
+ name String
+ links Link[]
+ owner User @relation(fields: [ownerId], references: [id])
+ ownerId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt @default(now())
@@ -135,14 +132,26 @@ model Tag {
model Subscription {
id Int @id @default(autoincrement())
- active Boolean
+ active Boolean
stripeSubscriptionId String @unique
currentPeriodStart DateTime
currentPeriodEnd DateTime
-
user User @relation(fields: [userId], references: [id])
userId Int @unique
-
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt @default(now())
}
+
+model ApiKey {
+ id Int @id @default(autoincrement())
+ name String
+ user User @relation(fields: [userId], references: [id])
+ userId Int
+ token String @unique
+ expires DateTime
+ lastUsedAt DateTime?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt @default(now())
+
+ @@unique([token, userId])
+}
diff --git a/public/icon.png b/public/icon.png
new file mode 100644
index 0000000..ac6d7e9
Binary files /dev/null and b/public/icon.png differ
diff --git a/store/links.ts b/store/links.ts
index 9362742..0648b6f 100644
--- a/store/links.ts
+++ b/store/links.ts
@@ -17,7 +17,7 @@ type LinkStore = {
addLink: (
body: LinkIncludingShortenedCollectionAndTags
) => Promise;
- getLink: (linkId: number) => Promise;
+ getLink: (linkId: number, publicRoute?: boolean) => Promise;
updateLink: (
link: LinkIncludingShortenedCollectionAndTags
) => Promise;
@@ -66,8 +66,12 @@ const useLinkStore = create()((set) => ({
return { ok: response.ok, data: data.response };
},
- getLink: async (linkId) => {
- const response = await fetch(`/api/v1/links/${linkId}`);
+ getLink: async (linkId, publicRoute) => {
+ const path = publicRoute
+ ? `/api/v1/public/links/${linkId}`
+ : `/api/v1/links/${linkId}`;
+
+ const response = await fetch(path);
const data = await response.json();
diff --git a/store/modals.ts b/store/modals.ts
index 71ecef0..f709d70 100644
--- a/store/modals.ts
+++ b/store/modals.ts
@@ -39,6 +39,14 @@ type Modal =
active?: CollectionIncludingMembersAndLinkCount;
defaultIndex?: number;
}
+ | {
+ modal: "COLLECTION";
+ state: boolean;
+ method: "VIEW_TEAM";
+ isOwner?: boolean;
+ active?: CollectionIncludingMembersAndLinkCount;
+ defaultIndex?: number;
+ }
| null;
type ModalsStore = {
@@ -46,11 +54,11 @@ type ModalsStore = {
setModal: (modal: Modal) => void;
};
-const useLocalSettingsStore = create((set) => ({
+const useModalStore = create((set) => ({
modal: null,
setModal: (modal: Modal) => {
set({ modal });
},
}));
-export default useLocalSettingsStore;
+export default useModalStore;
diff --git a/store/tags.ts b/store/tags.ts
index a27b859..6778152 100644
--- a/store/tags.ts
+++ b/store/tags.ts
@@ -1,5 +1,5 @@
import { create } from "zustand";
-import { Tag } from "@prisma/client";
+import { TagIncludingLinkCount } from "@/types/global";
type ResponseObject = {
ok: boolean;
@@ -7,9 +7,9 @@ type ResponseObject = {
};
type TagStore = {
- tags: Tag[];
+ tags: TagIncludingLinkCount[];
setTags: () => void;
- updateTag: (tag: Tag) => Promise;
+ updateTag: (tag: TagIncludingLinkCount) => Promise;
removeTag: (tagId: number) => Promise;
};
diff --git a/styles/globals.css b/styles/globals.css
index 5769211..eaf3dbb 100644
--- a/styles/globals.css
+++ b/styles/globals.css
@@ -142,7 +142,7 @@ body {
/* Theme */
@layer base {
body {
- @apply dark:bg-neutral-900 bg-white dark:text-white;
+ @apply dark:bg-neutral-900 bg-white text-black dark:text-white;
}
}
@@ -190,7 +190,11 @@ body {
/* Reader view custom stylings */
.reader-view {
- line-height: 3rem;
+ line-height: 2.8rem;
+}
+.reader-view p {
+ font-size: 1.15rem;
+ line-height: 2.5rem;
}
.reader-view h1 {
font-size: 2.2rem;
@@ -230,6 +234,8 @@ body {
}
.reader-view img {
margin: auto;
+ margin-top: 2rem;
+ margin-bottom: 2rem;
border-radius: 10px;
}
.reader-view pre {
diff --git a/tailwind.config.js b/tailwind.config.js
index 6ad2b8c..34690e4 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -2,6 +2,9 @@
module.exports = {
darkMode: "class",
+ // daisyui: {
+ // themes: ["light", "dark"],
+ // },
content: [
"./app/**/*.{js,ts,jsx,tsx}",
"./pages/**/*.{js,ts,jsx,tsx}",
@@ -10,5 +13,7 @@ module.exports = {
// For the "layouts" directory
"./layouts/**/*.{js,ts,jsx,tsx}",
],
- plugins: [],
+ plugins: [
+ // require("daisyui")
+ ],
};
diff --git a/types/enviornment.d.ts b/types/enviornment.d.ts
index df4b4ff..d2bdbb8 100644
--- a/types/enviornment.d.ts
+++ b/types/enviornment.d.ts
@@ -13,8 +13,14 @@ declare global {
SPACES_KEY?: string;
SPACES_SECRET?: string;
SPACES_ENDPOINT?: string;
- BUCKET_NAME?: string;
+ SPACES_BUCKET_NAME?: string;
SPACES_REGION?: string;
+ SPACES_FORCE_PATH_STYLE?: string;
+
+ NEXT_PUBLIC_KEYCLOAK_ENABLED?: string;
+ KEYCLOAK_ISSUER?: string;
+ KEYCLOAK_CLIENT_ID?: string;
+ KEYCLOAK_CLIENT_SECRET?: string;
NEXT_PUBLIC_EMAIL_PROVIDER?: string;
EMAIL_FROM?: string;
diff --git a/types/global.ts b/types/global.ts
index 26058cf..a423d45 100644
--- a/types/global.ts
+++ b/types/global.ts
@@ -37,6 +37,10 @@ export interface CollectionIncludingMembersAndLinkCount
members: Member[];
}
+export interface TagIncludingLinkCount extends Tag {
+ _count?: { links: number };
+}
+
export interface AccountSettings extends User {
newPassword?: string;
whitelistedUsers: string[];
@@ -111,3 +115,9 @@ export type DeleteUserBody = {
feedback?: Stripe.SubscriptionCancelParams.CancellationDetails.Feedback;
};
};
+
+export enum ArchivedFormat {
+ screenshot,
+ pdf,
+ readability,
+}
diff --git a/yarn.lock b/yarn.lock
index 024191a..feb1783 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -919,11 +919,6 @@
dependencies:
glob "7.1.7"
-"@next/font@13.4.9":
- version "13.4.9"
- resolved "https://registry.yarnpkg.com/@next/font/-/font-13.4.9.tgz#5540e69a1a5fbd1113d622a89cdd21c0ab3906c8"
- integrity sha512-aR0XEyd1cxqaKuelQFDGwUBYV0wyZfJTNiRoSk1XsECTyMhiSMmCOY7yOPMuPlw+6cctca0GyZXGGFb5EVhiRw==
-
"@next/swc-darwin-arm64@13.4.12":
version "13.4.12"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.12.tgz#326c830b111de8a1a51ac0cbc3bcb157c4c4f92c"
@@ -2134,6 +2129,14 @@ crypto-js@^4.2.0:
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
+css-selector-tokenizer@^0.8:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz#88267ef6238e64f2215ea2764b3e2cf498b845dd"
+ integrity sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==
+ dependencies:
+ cssesc "^3.0.0"
+ fastparse "^1.1.2"
+
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
@@ -2156,6 +2159,11 @@ csstype@^3.1.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
+culori@^3:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/culori/-/culori-3.2.0.tgz#df6561503f0cc20e8e1c029f086466666c0ac62f"
+ integrity sha512-HIEbTSP7vs1mPq/2P9In6QyFE0Tkpevh0k9a+FkjhD+cwsYm9WRSbn4uMdW9O0yXlNYC3ppxL3gWWPOcvEl57w==
+
cwise-compiler@^1.1.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/cwise-compiler/-/cwise-compiler-1.1.3.tgz#f4d667410e850d3a313a7d2db7b1e505bb034cc5"
@@ -2163,6 +2171,16 @@ cwise-compiler@^1.1.2:
dependencies:
uniq "^1.0.0"
+daisyui@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-4.4.2.tgz#669ee310be42894abe36d493635000d010fa4023"
+ integrity sha512-Ecg5loskj9dkaAnTSK5Xn5jb24TqDlQIg/NJ025jCkw2S/zw12btjvLgY2Sv5Ws1DFVoVBRs3XYXyojZG7zVnw==
+ dependencies:
+ css-selector-tokenizer "^0.8"
+ culori "^3"
+ picocolors "^1"
+ postcss-js "^4"
+
damerau-levenshtein@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
@@ -2731,6 +2749,11 @@ fast-xml-parser@4.2.5:
dependencies:
strnum "^1.0.5"
+fastparse@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
+ integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
+
fastq@^1.6.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
@@ -3627,6 +3650,11 @@ loose-envify@^1.1.0, loose-envify@^1.4.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
+lottie-web@^5.12.2:
+ version "5.12.2"
+ resolved "https://registry.yarnpkg.com/lottie-web/-/lottie-web-5.12.2.tgz#579ca9fe6d3fd9e352571edd3c0be162492f68e5"
+ integrity sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==
+
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -4113,7 +4141,7 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
-picocolors@^1.0.0:
+picocolors@^1, picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
@@ -4159,7 +4187,7 @@ postcss-import@^15.1.0:
read-cache "^1.0.0"
resolve "^1.1.7"
-postcss-js@^4.0.1:
+postcss-js@^4, postcss-js@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2"
integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==