added support for monolith
This commit is contained in:
parent
afd5e5f036
commit
9fa9fe5db0
13
.env.sample
13
.env.sample
|
@ -15,7 +15,6 @@ NEXT_PUBLIC_DISABLE_REGISTRATION=
|
||||||
NEXT_PUBLIC_CREDENTIALS_ENABLED=
|
NEXT_PUBLIC_CREDENTIALS_ENABLED=
|
||||||
DISABLE_NEW_SSO_USERS=
|
DISABLE_NEW_SSO_USERS=
|
||||||
RE_ARCHIVE_LIMIT=
|
RE_ARCHIVE_LIMIT=
|
||||||
NEXT_PUBLIC_MAX_FILE_SIZE=
|
|
||||||
MAX_LINKS_PER_USER=
|
MAX_LINKS_PER_USER=
|
||||||
ARCHIVE_TAKE_COUNT=
|
ARCHIVE_TAKE_COUNT=
|
||||||
BROWSER_TIMEOUT=
|
BROWSER_TIMEOUT=
|
||||||
|
@ -23,6 +22,12 @@ IGNORE_UNAUTHORIZED_CA=
|
||||||
IGNORE_HTTPS_ERRORS=
|
IGNORE_HTTPS_ERRORS=
|
||||||
IGNORE_URL_SIZE_LIMIT=
|
IGNORE_URL_SIZE_LIMIT=
|
||||||
ADMINISTRATOR=
|
ADMINISTRATOR=
|
||||||
|
NEXT_PUBLIC_MAX_FILE_BUFFER=
|
||||||
|
MONOLITH_MAX_BUFFER=
|
||||||
|
MONOLITH_OPTIONS=
|
||||||
|
PDF_MAX_BUFFER=
|
||||||
|
SCREENSHOT_MAX_BUFFER=
|
||||||
|
READABILITY_MAX_BUFFER=
|
||||||
|
|
||||||
# AWS S3 Settings
|
# AWS S3 Settings
|
||||||
SPACES_KEY=
|
SPACES_KEY=
|
||||||
|
@ -52,9 +57,9 @@ PDF_MARGIN_BOTTOM=
|
||||||
SINGLEFILE_ARCHIVE_COMMAND= # single-file "{{URL}}" --dump-content
|
SINGLEFILE_ARCHIVE_COMMAND= # single-file "{{URL}}" --dump-content
|
||||||
SINGLEFILE_ARCHIVE_HTTP_API= # http://singlefile:3000/
|
SINGLEFILE_ARCHIVE_HTTP_API= # http://singlefile:3000/
|
||||||
|
|
||||||
#
|
#################
|
||||||
# SSO Providers
|
# SSO Providers #
|
||||||
#
|
#################
|
||||||
|
|
||||||
# 42 School
|
# 42 School
|
||||||
NEXT_PUBLIC_FORTYTWO_ENABLED=
|
NEXT_PUBLIC_FORTYTWO_ENABLED=
|
||||||
|
|
|
@ -11,6 +11,8 @@ COPY ./package.json ./yarn.lock ./playwright.config.ts ./
|
||||||
# Increase timeout to pass github actions arm64 build
|
# Increase timeout to pass github actions arm64 build
|
||||||
RUN --mount=type=cache,sharing=locked,target=/usr/local/share/.cache/yarn yarn install --network-timeout 10000000
|
RUN --mount=type=cache,sharing=locked,target=/usr/local/share/.cache/yarn yarn install --network-timeout 10000000
|
||||||
|
|
||||||
|
# RUN /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && brew install monolith
|
||||||
|
|
||||||
RUN npx playwright install-deps && \
|
RUN npx playwright install-deps && \
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
yarn cache clean
|
yarn cache clean
|
||||||
|
|
|
@ -159,6 +159,16 @@ export default function PreservedFormatsModal({ onClose, activeLink }: Props) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={`flex flex-col gap-3`}>
|
<div className={`flex flex-col gap-3`}>
|
||||||
|
{singlefileAvailable(link) ? (
|
||||||
|
<PreservedFormatRow
|
||||||
|
name={t("webpage")}
|
||||||
|
icon={"bi-filetype-html"}
|
||||||
|
format={ArchivedFormat.singlefile}
|
||||||
|
activeLink={link}
|
||||||
|
downloadable={true}
|
||||||
|
/>
|
||||||
|
) : undefined}
|
||||||
|
|
||||||
{screenshotAvailable(link) ? (
|
{screenshotAvailable(link) ? (
|
||||||
<PreservedFormatRow
|
<PreservedFormatRow
|
||||||
name={t("screenshot")}
|
name={t("screenshot")}
|
||||||
|
|
|
@ -150,7 +150,7 @@ export default function UploadFileModal({ onClose }: Props) {
|
||||||
</label>
|
</label>
|
||||||
<p className="text-xs font-semibold mt-2">
|
<p className="text-xs font-semibold mt-2">
|
||||||
{t("file_types", {
|
{t("file_types", {
|
||||||
size: process.env.NEXT_PUBLIC_MAX_FILE_SIZE || 30,
|
size: process.env.NEXT_PUBLIC_MAX_FILE_BUFFER || 10,
|
||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -73,7 +73,7 @@ export default function PreservedFormatRow({
|
||||||
anchorElement.href = path;
|
anchorElement.href = path;
|
||||||
anchorElement.download =
|
anchorElement.download =
|
||||||
format === ArchivedFormat.singlefile
|
format === ArchivedFormat.singlefile
|
||||||
? link.name ?? "index"
|
? "Webpage"
|
||||||
: format === ArchivedFormat.pdf
|
: format === ArchivedFormat.pdf
|
||||||
? "PDF"
|
? "PDF"
|
||||||
: "Screenshot";
|
: "Screenshot";
|
||||||
|
|
|
@ -19,6 +19,9 @@ services:
|
||||||
- ./data:/data/data
|
- ./data:/data/data
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
singlefile:
|
# monolith:
|
||||||
image: rutkai/single-file-web:latest
|
# image: ghcr.io/linkwarden/monolith:latest
|
||||||
container_name: singlefile
|
# container_name: monolith
|
||||||
|
# singlefile:
|
||||||
|
# image: rutkai/single-file-web:latest
|
||||||
|
# container_name: singlefile
|
||||||
|
|
|
@ -7,9 +7,10 @@ import validateUrlSize from "./validateUrlSize";
|
||||||
import createFolder from "./storage/createFolder";
|
import createFolder from "./storage/createFolder";
|
||||||
import generatePreview from "./generatePreview";
|
import generatePreview from "./generatePreview";
|
||||||
import { removeFiles } from "./manageLinkFiles";
|
import { removeFiles } from "./manageLinkFiles";
|
||||||
import archiveAsSinglefile from "./preservationScheme/archiveAsSinglefile";
|
import handleMonolith from "./preservationScheme/handleMonolith";
|
||||||
import archiveAsReadability from "./preservationScheme/archiveAsReadablility";
|
import handleReadablility from "./preservationScheme/handleReadablility";
|
||||||
import shell from "shelljs";
|
import handleArchivePreview from "./preservationScheme/handleArchivePreview";
|
||||||
|
import handleScreenshotAndPdf from "./preservationScheme/handleScreenshotAndPdf";
|
||||||
|
|
||||||
type LinksAndCollectionAndOwner = Link & {
|
type LinksAndCollectionAndOwner = Link & {
|
||||||
collection: Collection & {
|
collection: Collection & {
|
||||||
|
@ -51,26 +52,6 @@ export default async function archiveHandler(link: LinksAndCollectionAndOwner) {
|
||||||
|
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
|
|
||||||
// await page.goto("https://github.com", {
|
|
||||||
// waitUntil: "domcontentloaded",
|
|
||||||
// });
|
|
||||||
|
|
||||||
// console.log("Opening page:", link.url);
|
|
||||||
|
|
||||||
// await page.evaluate(autoScroll, Number(process.env.AUTOSCROLL_TIMEOUT) || 30);
|
|
||||||
|
|
||||||
// const dom = await page.content();
|
|
||||||
|
|
||||||
// console.log("The content", dom);
|
|
||||||
|
|
||||||
// shell
|
|
||||||
// .echo(dom)
|
|
||||||
// .exec(
|
|
||||||
// "monolith - -I -b https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi -j -F -o monolith.html"
|
|
||||||
// );
|
|
||||||
|
|
||||||
// console.log("Monolith created!");
|
|
||||||
|
|
||||||
createFolder({
|
createFolder({
|
||||||
filePath: `archives/preview/${link.collectionId}`,
|
filePath: `archives/preview/${link.collectionId}`,
|
||||||
});
|
});
|
||||||
|
@ -131,15 +112,6 @@ export default async function archiveHandler(link: LinksAndCollectionAndOwner) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// SingleFile
|
|
||||||
// if (
|
|
||||||
// !link.singlefile?.startsWith("archive") &&
|
|
||||||
// !link.singlefile?.startsWith("unavailable") &&
|
|
||||||
// user.archiveAsSinglefile &&
|
|
||||||
// link.url
|
|
||||||
// )
|
|
||||||
// await archiveAsSinglefile(link);
|
|
||||||
|
|
||||||
// send to archive.org
|
// send to archive.org
|
||||||
if (user.archiveAsWaybackMachine && link.url) sendToWayback(link.url);
|
if (user.archiveAsWaybackMachine && link.url) sendToWayback(link.url);
|
||||||
|
|
||||||
|
@ -156,19 +128,19 @@ export default async function archiveHandler(link: LinksAndCollectionAndOwner) {
|
||||||
|
|
||||||
const content = await page.content();
|
const content = await page.content();
|
||||||
|
|
||||||
// Readability
|
|
||||||
if (
|
|
||||||
!link.readable?.startsWith("archives") &&
|
|
||||||
!link.readable?.startsWith("unavailable")
|
|
||||||
)
|
|
||||||
await archiveAsReadability(content, link);
|
|
||||||
|
|
||||||
// Preview
|
// Preview
|
||||||
if (
|
if (
|
||||||
!link.preview?.startsWith("archives") &&
|
!link.preview?.startsWith("archives") &&
|
||||||
!link.preview?.startsWith("unavailable")
|
!link.preview?.startsWith("unavailable")
|
||||||
)
|
)
|
||||||
await getArchivePreview(link, page);
|
await handleArchivePreview(link, page);
|
||||||
|
|
||||||
|
// Readability
|
||||||
|
if (
|
||||||
|
!link.readable?.startsWith("archives") &&
|
||||||
|
!link.readable?.startsWith("unavailable")
|
||||||
|
)
|
||||||
|
await handleReadablility(content, link);
|
||||||
|
|
||||||
// Screenshot/PDF
|
// Screenshot/PDF
|
||||||
if (
|
if (
|
||||||
|
@ -177,7 +149,16 @@ export default async function archiveHandler(link: LinksAndCollectionAndOwner) {
|
||||||
(!link.pdf?.startsWith("archives") &&
|
(!link.pdf?.startsWith("archives") &&
|
||||||
!link.pdf?.startsWith("unavailable"))
|
!link.pdf?.startsWith("unavailable"))
|
||||||
)
|
)
|
||||||
await captureScreenshotAndPdf(link, page, user);
|
await handleScreenshotAndPdf(link, page, user);
|
||||||
|
|
||||||
|
// SingleFile
|
||||||
|
if (
|
||||||
|
!link.singlefile?.startsWith("archive") &&
|
||||||
|
!link.singlefile?.startsWith("unavailable") &&
|
||||||
|
user.archiveAsSinglefile &&
|
||||||
|
link.url
|
||||||
|
)
|
||||||
|
await handleMonolith(link, content);
|
||||||
}
|
}
|
||||||
})(),
|
})(),
|
||||||
timeoutPromise,
|
timeoutPromise,
|
||||||
|
@ -268,133 +249,3 @@ const pdfHandler = async ({ url, id }: Link) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getArchivePreview = async (
|
|
||||||
link: LinksAndCollectionAndOwner,
|
|
||||||
page: Page
|
|
||||||
) => {
|
|
||||||
const ogImageUrl = await page.evaluate(() => {
|
|
||||||
const metaTag = document.querySelector('meta[property="og:image"]');
|
|
||||||
return metaTag ? (metaTag as any).content : null;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ogImageUrl) {
|
|
||||||
console.log("Found og:image URL:", ogImageUrl);
|
|
||||||
|
|
||||||
// Download the image
|
|
||||||
const imageResponse = await page.goto(ogImageUrl);
|
|
||||||
|
|
||||||
// Check if imageResponse is not null
|
|
||||||
if (imageResponse && !link.preview?.startsWith("archive")) {
|
|
||||||
const buffer = await imageResponse.body();
|
|
||||||
generatePreview(buffer, link.collectionId, link.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
await page.goBack();
|
|
||||||
} else if (!link.preview?.startsWith("archive")) {
|
|
||||||
console.log("No og:image found");
|
|
||||||
await page
|
|
||||||
.screenshot({ type: "jpeg", quality: 20 })
|
|
||||||
.then((screenshot) => {
|
|
||||||
return createFile({
|
|
||||||
data: screenshot,
|
|
||||||
filePath: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
return prisma.link.update({
|
|
||||||
where: { id: link.id },
|
|
||||||
data: {
|
|
||||||
preview: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const captureScreenshotAndPdf = async (
|
|
||||||
link: LinksAndCollectionAndOwner,
|
|
||||||
page: Page,
|
|
||||||
user: User
|
|
||||||
) => {
|
|
||||||
await page.evaluate(autoScroll, Number(process.env.AUTOSCROLL_TIMEOUT) || 30);
|
|
||||||
|
|
||||||
// Check if the user hasn't deleted the link by the time we're done scrolling
|
|
||||||
const linkExists = await prisma.link.findUnique({
|
|
||||||
where: { id: link.id },
|
|
||||||
});
|
|
||||||
if (linkExists) {
|
|
||||||
const processingPromises = [];
|
|
||||||
|
|
||||||
if (user.archiveAsScreenshot && !link.image?.startsWith("archive")) {
|
|
||||||
processingPromises.push(
|
|
||||||
page.screenshot({ fullPage: true, type: "png" }).then((screenshot) => {
|
|
||||||
return createFile({
|
|
||||||
data: screenshot,
|
|
||||||
filePath: `archives/${linkExists.collectionId}/${link.id}.png`,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const margins = {
|
|
||||||
top: process.env.PDF_MARGIN_TOP || "15px",
|
|
||||||
bottom: process.env.PDF_MARGIN_BOTTOM || "15px",
|
|
||||||
};
|
|
||||||
|
|
||||||
if (user.archiveAsPDF && !link.pdf?.startsWith("archive")) {
|
|
||||||
processingPromises.push(
|
|
||||||
page
|
|
||||||
.pdf({
|
|
||||||
width: "1366px",
|
|
||||||
height: "1931px",
|
|
||||||
printBackground: true,
|
|
||||||
margin: margins,
|
|
||||||
})
|
|
||||||
.then((pdf) => {
|
|
||||||
return createFile({
|
|
||||||
data: pdf,
|
|
||||||
filePath: `archives/${linkExists.collectionId}/${link.id}.pdf`,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await Promise.allSettled(processingPromises);
|
|
||||||
await prisma.link.update({
|
|
||||||
where: { id: link.id },
|
|
||||||
data: {
|
|
||||||
image: user.archiveAsScreenshot
|
|
||||||
? `archives/${linkExists.collectionId}/${link.id}.png`
|
|
||||||
: undefined,
|
|
||||||
pdf: user.archiveAsPDF
|
|
||||||
? `archives/${linkExists.collectionId}/${link.id}.pdf`
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const autoScroll = async (AUTOSCROLL_TIMEOUT: number) => {
|
|
||||||
const timeoutPromise = new Promise<void>((resolve) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve();
|
|
||||||
}, AUTOSCROLL_TIMEOUT * 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
const scrollingPromise = new Promise<void>((resolve) => {
|
|
||||||
let totalHeight = 0;
|
|
||||||
let distance = 100;
|
|
||||||
let scrollDown = setInterval(() => {
|
|
||||||
let scrollHeight = document.body.scrollHeight;
|
|
||||||
window.scrollBy(0, distance);
|
|
||||||
totalHeight += distance;
|
|
||||||
if (totalHeight >= scrollHeight) {
|
|
||||||
clearInterval(scrollDown);
|
|
||||||
window.scroll(0, 0);
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.race([scrollingPromise, timeoutPromise]);
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
import { execSync } from "child_process";
|
|
||||||
import createFile from "../storage/createFile";
|
|
||||||
import axios from "axios";
|
|
||||||
import { Agent } from "http";
|
|
||||||
import { prisma } from "../db";
|
|
||||||
import { Link } from "@prisma/client";
|
|
||||||
|
|
||||||
const archiveAsSinglefile = async (link: Link) => {
|
|
||||||
if (!link.url) return;
|
|
||||||
|
|
||||||
let command = process.env.SINGLEFILE_ARCHIVE_COMMAND;
|
|
||||||
let httpApi = process.env.SINGLEFILE_ARCHIVE_HTTP_API;
|
|
||||||
if (command) {
|
|
||||||
if (command.includes("{{URL}}")) {
|
|
||||||
try {
|
|
||||||
let html = execSync(command.replace("{{URL}}", link.url), {
|
|
||||||
timeout: 120000,
|
|
||||||
maxBuffer: 1024 * 1024 * 30,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!html.length) {
|
|
||||||
console.error(
|
|
||||||
"Error running SINGLEFILE_ARCHIVE_COMMAND: Empty buffer"
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const collectionId = (
|
|
||||||
await prisma.link.findUnique({
|
|
||||||
where: { id: link.id },
|
|
||||||
select: { collectionId: true },
|
|
||||||
})
|
|
||||||
)?.collectionId;
|
|
||||||
|
|
||||||
if (!collectionId) {
|
|
||||||
console.error(
|
|
||||||
"Error running SINGLEFILE_ARCHIVE_COMMAND: Collection ID not found"
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await createFile({
|
|
||||||
data: html,
|
|
||||||
filePath: `archives/${collectionId}/${link.id}.html`,
|
|
||||||
}).then(async () => {
|
|
||||||
await prisma.link.update({
|
|
||||||
where: { id: link.id },
|
|
||||||
data: {
|
|
||||||
singlefile: `archives/${collectionId}/${link.id}.html`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Error running SINGLEFILE_ARCHIVE_COMMAND:", err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error("Invalid SINGLEFILE_ARCHIVE_COMMAND. Missing {{URL}}");
|
|
||||||
}
|
|
||||||
} else if (httpApi) {
|
|
||||||
try {
|
|
||||||
let html = await axios.post(
|
|
||||||
httpApi,
|
|
||||||
{ url: link.url },
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
httpAgent: new Agent({ keepAlive: false }),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!html.data.length) {
|
|
||||||
console.error("Error running SINGLEFILE_ARCHIVE_COMMAND: Empty buffer");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const collectionId = (
|
|
||||||
await prisma.link.findUnique({
|
|
||||||
where: { id: link.id },
|
|
||||||
select: { collectionId: true },
|
|
||||||
})
|
|
||||||
)?.collectionId;
|
|
||||||
|
|
||||||
if (!collectionId) {
|
|
||||||
console.error(
|
|
||||||
"Error running SINGLEFILE_ARCHIVE_COMMAND: Collection ID not found"
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await createFile({
|
|
||||||
data: html.data,
|
|
||||||
filePath: `archives/${collectionId}/${link.id}.html`,
|
|
||||||
}).then(async () => {
|
|
||||||
await prisma.link.update({
|
|
||||||
where: { id: link.id },
|
|
||||||
data: {
|
|
||||||
singlefile: `archives/${collectionId}/${link.id}.html`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error(
|
|
||||||
"Error fetching Singlefile using SINGLEFILE_ARCHIVE_HTTP_API:",
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default archiveAsSinglefile;
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { Collection, Link, User } from "@prisma/client";
|
||||||
|
import { Page } from "playwright";
|
||||||
|
import generatePreview from "../generatePreview";
|
||||||
|
import createFile from "../storage/createFile";
|
||||||
|
import { prisma } from "../db";
|
||||||
|
|
||||||
|
type LinksAndCollectionAndOwner = Link & {
|
||||||
|
collection: Collection & {
|
||||||
|
owner: User;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleArchivePreview = async (
|
||||||
|
link: LinksAndCollectionAndOwner,
|
||||||
|
page: Page
|
||||||
|
) => {
|
||||||
|
const ogImageUrl = await page.evaluate(() => {
|
||||||
|
const metaTag = document.querySelector('meta[property="og:image"]');
|
||||||
|
return metaTag ? (metaTag as any).content : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ogImageUrl) {
|
||||||
|
console.log("Found og:image URL:", ogImageUrl);
|
||||||
|
|
||||||
|
// Download the image
|
||||||
|
const imageResponse = await page.goto(ogImageUrl);
|
||||||
|
|
||||||
|
// Check if imageResponse is not null
|
||||||
|
if (imageResponse && !link.preview?.startsWith("archive")) {
|
||||||
|
const buffer = await imageResponse.body();
|
||||||
|
generatePreview(buffer, link.collectionId, link.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.goBack();
|
||||||
|
} else if (!link.preview?.startsWith("archive")) {
|
||||||
|
console.log("No og:image found");
|
||||||
|
await page
|
||||||
|
.screenshot({ type: "jpeg", quality: 20 })
|
||||||
|
.then((screenshot) => {
|
||||||
|
return createFile({
|
||||||
|
data: screenshot,
|
||||||
|
filePath: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return prisma.link.update({
|
||||||
|
where: { id: link.id },
|
||||||
|
data: {
|
||||||
|
preview: `archives/preview/${link.collectionId}/${link.id}.jpeg`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handleArchivePreview;
|
|
@ -0,0 +1,97 @@
|
||||||
|
import { execSync } from "child_process";
|
||||||
|
import createFile from "../storage/createFile";
|
||||||
|
import axios from "axios";
|
||||||
|
import { Agent } from "http";
|
||||||
|
import { prisma } from "../db";
|
||||||
|
import { Link } from "@prisma/client";
|
||||||
|
import { Page } from "playwright";
|
||||||
|
|
||||||
|
const handleMonolith = async (link: Link, content: string) => {
|
||||||
|
if (!link.url) return;
|
||||||
|
|
||||||
|
let command = process.env.SINGLEFILE_ARCHIVE_COMMAND;
|
||||||
|
let httpApi = process.env.SINGLEFILE_ARCHIVE_HTTP_API;
|
||||||
|
try {
|
||||||
|
let html = execSync(
|
||||||
|
`monolith - -I -b ${link.url} ${
|
||||||
|
process.env.MONOLITH_OPTIONS || "-j -F -s"
|
||||||
|
} -o -`,
|
||||||
|
{
|
||||||
|
timeout: 120000,
|
||||||
|
maxBuffer: 1024 * 1024 * Number(process.env.MONOLITH_MAX_BUFFER || 5),
|
||||||
|
input: content,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!html?.length) {
|
||||||
|
console.error("Error running SINGLEFILE_ARCHIVE_COMMAND: Empty buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await createFile({
|
||||||
|
data: html,
|
||||||
|
filePath: `archives/${link.collectionId}/${link.id}.html`,
|
||||||
|
}).then(async () => {
|
||||||
|
await prisma.link.update({
|
||||||
|
where: { id: link.id },
|
||||||
|
data: {
|
||||||
|
singlefile: `archives/${link.collectionId}/${link.id}.html`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error running SINGLEFILE_ARCHIVE_COMMAND:", err);
|
||||||
|
}
|
||||||
|
// if (httpApi) {
|
||||||
|
// try {
|
||||||
|
// let html = await axios.post(
|
||||||
|
// httpApi,
|
||||||
|
// { url: link.url },
|
||||||
|
// {
|
||||||
|
// headers: {
|
||||||
|
// "Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
// },
|
||||||
|
// httpAgent: new Agent({ keepAlive: false }),
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (!html.data.length) {
|
||||||
|
// console.error("Error running SINGLEFILE_ARCHIVE_COMMAND: Empty buffer");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const collectionId = (
|
||||||
|
// await prisma.link.findUnique({
|
||||||
|
// where: { id: link.id },
|
||||||
|
// select: { collectionId: true },
|
||||||
|
// })
|
||||||
|
// )?.collectionId;
|
||||||
|
|
||||||
|
// if (!collectionId) {
|
||||||
|
// console.error(
|
||||||
|
// "Error running SINGLEFILE_ARCHIVE_COMMAND: Collection ID not found"
|
||||||
|
// );
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// await createFile({
|
||||||
|
// data: html.data,
|
||||||
|
// filePath: `archives/${collectionId}/${link.id}.html`,
|
||||||
|
// }).then(async () => {
|
||||||
|
// await prisma.link.update({
|
||||||
|
// where: { id: link.id },
|
||||||
|
// data: {
|
||||||
|
// singlefile: `archives/${collectionId}/${link.id}.html`,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// } catch (err) {
|
||||||
|
// console.error(
|
||||||
|
// "Error fetching Singlefile using SINGLEFILE_ARCHIVE_HTTP_API:",
|
||||||
|
// err
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handleMonolith;
|
|
@ -5,7 +5,7 @@ import { prisma } from "../db";
|
||||||
import createFile from "../storage/createFile";
|
import createFile from "../storage/createFile";
|
||||||
import { Link } from "@prisma/client";
|
import { Link } from "@prisma/client";
|
||||||
|
|
||||||
const archiveAsReadablility = async (content: string, link: Link) => {
|
const handleReadablility = async (content: string, link: Link) => {
|
||||||
const window = new JSDOM("").window;
|
const window = new JSDOM("").window;
|
||||||
const purify = DOMPurify(window);
|
const purify = DOMPurify(window);
|
||||||
const cleanedUpContent = purify.sanitize(content);
|
const cleanedUpContent = purify.sanitize(content);
|
||||||
|
@ -38,4 +38,4 @@ const archiveAsReadablility = async (content: string, link: Link) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default archiveAsReadablility;
|
export default handleReadablility;
|
|
@ -0,0 +1,98 @@
|
||||||
|
import { Collection, Link, User } from "@prisma/client";
|
||||||
|
import { Page } from "playwright";
|
||||||
|
import createFile from "../storage/createFile";
|
||||||
|
import { prisma } from "../db";
|
||||||
|
|
||||||
|
type LinksAndCollectionAndOwner = Link & {
|
||||||
|
collection: Collection & {
|
||||||
|
owner: User;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const handleScreenshotAndPdf = async (
|
||||||
|
link: LinksAndCollectionAndOwner,
|
||||||
|
page: Page,
|
||||||
|
user: User
|
||||||
|
) => {
|
||||||
|
await page.evaluate(autoScroll, Number(process.env.AUTOSCROLL_TIMEOUT) || 30);
|
||||||
|
|
||||||
|
// Check if the user hasn't deleted the link by the time we're done scrolling
|
||||||
|
const linkExists = await prisma.link.findUnique({
|
||||||
|
where: { id: link.id },
|
||||||
|
});
|
||||||
|
if (linkExists) {
|
||||||
|
const processingPromises = [];
|
||||||
|
|
||||||
|
if (user.archiveAsScreenshot && !link.image?.startsWith("archive")) {
|
||||||
|
processingPromises.push(
|
||||||
|
page.screenshot({ fullPage: true, type: "png" }).then((screenshot) => {
|
||||||
|
return createFile({
|
||||||
|
data: screenshot,
|
||||||
|
filePath: `archives/${linkExists.collectionId}/${link.id}.png`,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const margins = {
|
||||||
|
top: process.env.PDF_MARGIN_TOP || "15px",
|
||||||
|
bottom: process.env.PDF_MARGIN_BOTTOM || "15px",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (user.archiveAsPDF && !link.pdf?.startsWith("archive")) {
|
||||||
|
processingPromises.push(
|
||||||
|
page
|
||||||
|
.pdf({
|
||||||
|
width: "1366px",
|
||||||
|
height: "1931px",
|
||||||
|
printBackground: true,
|
||||||
|
margin: margins,
|
||||||
|
})
|
||||||
|
.then((pdf) => {
|
||||||
|
return createFile({
|
||||||
|
data: pdf,
|
||||||
|
filePath: `archives/${linkExists.collectionId}/${link.id}.pdf`,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await Promise.allSettled(processingPromises);
|
||||||
|
await prisma.link.update({
|
||||||
|
where: { id: link.id },
|
||||||
|
data: {
|
||||||
|
image: user.archiveAsScreenshot
|
||||||
|
? `archives/${linkExists.collectionId}/${link.id}.png`
|
||||||
|
: undefined,
|
||||||
|
pdf: user.archiveAsPDF
|
||||||
|
? `archives/${linkExists.collectionId}/${link.id}.pdf`
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const autoScroll = async (AUTOSCROLL_TIMEOUT: number) => {
|
||||||
|
const timeoutPromise = new Promise<void>((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve();
|
||||||
|
}, AUTOSCROLL_TIMEOUT * 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
const scrollingPromise = new Promise<void>((resolve) => {
|
||||||
|
let totalHeight = 0;
|
||||||
|
let distance = 100;
|
||||||
|
let scrollDown = setInterval(() => {
|
||||||
|
let scrollHeight = document.body.scrollHeight;
|
||||||
|
window.scrollBy(0, distance);
|
||||||
|
totalHeight += distance;
|
||||||
|
if (totalHeight >= scrollHeight) {
|
||||||
|
clearInterval(scrollDown);
|
||||||
|
window.scroll(0, 0);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.race([scrollingPromise, timeoutPromise]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handleScreenshotAndPdf;
|
|
@ -33,7 +33,7 @@ export default async function validateUrlSize(url: string) {
|
||||||
|
|
||||||
const totalSizeMB =
|
const totalSizeMB =
|
||||||
Number(response.headers.get("content-length")) / Math.pow(1024, 2);
|
Number(response.headers.get("content-length")) / Math.pow(1024, 2);
|
||||||
if (totalSizeMB > (Number(process.env.NEXT_PUBLIC_MAX_FILE_SIZE) || 30))
|
if (totalSizeMB > Number(process.env.NEXT_PUBLIC_MAX_FILE_BUFFER || 10))
|
||||||
return null;
|
return null;
|
||||||
else return response.headers;
|
else return response.headers;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -70,7 +70,6 @@
|
||||||
"react-masonry-css": "^1.0.16",
|
"react-masonry-css": "^1.0.16",
|
||||||
"react-select": "^5.7.4",
|
"react-select": "^5.7.4",
|
||||||
"react-spinners": "^0.13.8",
|
"react-spinners": "^0.13.8",
|
||||||
"shelljs": "^0.8.5",
|
|
||||||
"socks-proxy-agent": "^8.0.2",
|
"socks-proxy-agent": "^8.0.2",
|
||||||
"stripe": "^12.13.0",
|
"stripe": "^12.13.0",
|
||||||
"tailwind-merge": "^2.3.0",
|
"tailwind-merge": "^2.3.0",
|
||||||
|
|
|
@ -94,12 +94,14 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
|
||||||
// await uploadHandler(linkId, )
|
// await uploadHandler(linkId, )
|
||||||
|
|
||||||
const MAX_UPLOAD_SIZE = Number(process.env.NEXT_PUBLIC_MAX_FILE_SIZE);
|
const MAX_UPLOAD_SIZE = Number(
|
||||||
|
process.env.NEXT_PUBLIC_MAX_FILE_BUFFER || 10
|
||||||
|
);
|
||||||
|
|
||||||
const form = formidable({
|
const form = formidable({
|
||||||
maxFields: 1,
|
maxFields: 1,
|
||||||
maxFiles: 1,
|
maxFiles: 1,
|
||||||
maxFileSize: MAX_UPLOAD_SIZE || 30 * 1048576,
|
maxFileSize: MAX_UPLOAD_SIZE * 1048576,
|
||||||
});
|
});
|
||||||
|
|
||||||
form.parse(req, async (err, fields, files) => {
|
form.parse(req, async (err, fields, files) => {
|
||||||
|
|
|
@ -360,5 +360,6 @@
|
||||||
"show_link_details": "Show Link Details",
|
"show_link_details": "Show Link Details",
|
||||||
"hide_link_details": "Hide Link Details",
|
"hide_link_details": "Hide Link Details",
|
||||||
"link_pinned": "Link Pinned!",
|
"link_pinned": "Link Pinned!",
|
||||||
"link_unpinned": "Link Unpinned!"
|
"link_unpinned": "Link Unpinned!",
|
||||||
|
"webpage": "Webpage"
|
||||||
}
|
}
|
|
@ -1,427 +0,0 @@
|
||||||
declare global {
|
|
||||||
namespace NodeJS {
|
|
||||||
interface ProcessEnv {
|
|
||||||
NEXTAUTH_SECRET: string;
|
|
||||||
DATABASE_URL: string;
|
|
||||||
NEXTAUTH_URL: string;
|
|
||||||
NEXT_PUBLIC_DISABLE_REGISTRATION?: string;
|
|
||||||
PAGINATION_TAKE_COUNT?: string;
|
|
||||||
STORAGE_FOLDER?: string;
|
|
||||||
AUTOSCROLL_TIMEOUT?: string;
|
|
||||||
RE_ARCHIVE_LIMIT?: string;
|
|
||||||
NEXT_PUBLIC_MAX_FILE_SIZE?: string;
|
|
||||||
MAX_LINKS_PER_USER?: string;
|
|
||||||
ARCHIVE_TAKE_COUNT?: string;
|
|
||||||
IGNORE_UNAUTHORIZED_CA?: string;
|
|
||||||
IGNORE_URL_SIZE_LIMIT?: string;
|
|
||||||
ADMINISTRATOR?: string;
|
|
||||||
|
|
||||||
SPACES_KEY?: string;
|
|
||||||
SPACES_SECRET?: string;
|
|
||||||
SPACES_ENDPOINT?: string;
|
|
||||||
SPACES_BUCKET_NAME?: string;
|
|
||||||
SPACES_REGION?: string;
|
|
||||||
SPACES_FORCE_PATH_STYLE?: string;
|
|
||||||
|
|
||||||
NEXT_PUBLIC_CREDENTIALS_ENABLED?: string;
|
|
||||||
DISABLE_NEW_SSO_USERS?: string;
|
|
||||||
|
|
||||||
NEXT_PUBLIC_EMAIL_PROVIDER?: string;
|
|
||||||
EMAIL_FROM?: string;
|
|
||||||
EMAIL_SERVER?: string;
|
|
||||||
|
|
||||||
BASE_URL?: string; // Used for email and stripe
|
|
||||||
|
|
||||||
NEXT_PUBLIC_STRIPE?: string;
|
|
||||||
STRIPE_SECRET_KEY?: string;
|
|
||||||
MONTHLY_PRICE_ID?: string;
|
|
||||||
YEARLY_PRICE_ID?: string;
|
|
||||||
NEXT_PUBLIC_STRIPE_BILLING_PORTAL_URL?: string;
|
|
||||||
NEXT_PUBLIC_TRIAL_PERIOD_DAYS?: string;
|
|
||||||
|
|
||||||
// Proxy settings
|
|
||||||
PROXY?: string;
|
|
||||||
PROXY_USERNAME?: string;
|
|
||||||
PROXY_PASSWORD?: string;
|
|
||||||
PROXY_BYPASS?: string;
|
|
||||||
|
|
||||||
// PDF archive settings
|
|
||||||
PDF_MARGIN_TOP?: string;
|
|
||||||
PDF_MARGIN_BOTTOM?: string;
|
|
||||||
|
|
||||||
// PDF archive settings
|
|
||||||
SINGLEFILE_ARCHIVE_COMMAND?: string;
|
|
||||||
SINGLEFILE_ARCHIVE_HTTP_API?: string;
|
|
||||||
|
|
||||||
//
|
|
||||||
// SSO Providers
|
|
||||||
//
|
|
||||||
|
|
||||||
// 42 School
|
|
||||||
NEXT_PUBLIC_FORTYTWO_ENABLED?: string;
|
|
||||||
FORTYTWO_CUSTOM_NAME?: string;
|
|
||||||
FORTYTWO_CLIENT_ID?: string;
|
|
||||||
FORTYTWO_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Apple
|
|
||||||
NEXT_PUBLIC_APPLE_ENABLED?: string;
|
|
||||||
APPLE_CUSTOM_NAME?: string;
|
|
||||||
APPLE_ID?: string;
|
|
||||||
APPLE_SECRET?: string;
|
|
||||||
|
|
||||||
// Atlassian
|
|
||||||
NEXT_PUBLIC_ATLASSIAN_ENABLED?: string;
|
|
||||||
ATLASSIAN_CUSTOM_NAME?: string;
|
|
||||||
ATLASSIAN_CLIENT_ID?: string;
|
|
||||||
ATLASSIAN_CLIENT_SECRET?: string;
|
|
||||||
ATLASSIAN_SCOPE?: string;
|
|
||||||
|
|
||||||
// Auth0
|
|
||||||
NEXT_PUBLIC_AUTH0_ENABLED?: string;
|
|
||||||
AUTH0_CUSTOM_NAME?: string;
|
|
||||||
AUTH0_ISSUER?: string;
|
|
||||||
AUTH0_CLIENT_SECRET?: string;
|
|
||||||
AUTH0_CLIENT_ID?: string;
|
|
||||||
|
|
||||||
// Authelia
|
|
||||||
NEXT_PUBLIC_AUTHELIA_ENABLED?: string;
|
|
||||||
AUTHELIA_CUSTOM_NAME?: string;
|
|
||||||
AUTHELIA_CLIENT_ID?: string;
|
|
||||||
AUTHELIA_CLIENT_SECRET?: string;
|
|
||||||
AUTHELIA_WELLKNOWN_URL?: string;
|
|
||||||
|
|
||||||
// Authentik
|
|
||||||
NEXT_PUBLIC_AUTHENTIK_ENABLED?: string;
|
|
||||||
AUTHENTIK_CUSTOM_NAME?: string;
|
|
||||||
AUTHENTIK_ISSUER?: string;
|
|
||||||
AUTHENTIK_CLIENT_ID?: string;
|
|
||||||
AUTHENTIK_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// TODO: Azure AD B2C
|
|
||||||
// TODO: Azure AD
|
|
||||||
|
|
||||||
// Battle.net
|
|
||||||
NEXT_PUBLIC_BATTLENET_ENABLED?: string;
|
|
||||||
BATTLENET_CUSTOM_NAME?: string;
|
|
||||||
BATTLENET_CLIENT_ID?: string;
|
|
||||||
BATTLENET_CLIENT_SECRET?: string;
|
|
||||||
BATLLENET_ISSUER?: string;
|
|
||||||
|
|
||||||
// Box
|
|
||||||
NEXT_PUBLIC_BOX_ENABLED?: string;
|
|
||||||
BOX_CUSTOM_NAME?: string;
|
|
||||||
BOX_CLIENT_ID?: string;
|
|
||||||
BOX_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// TODO: BoxyHQ SAML
|
|
||||||
|
|
||||||
// Bungie
|
|
||||||
NEXT_PUBLIC_BUNGIE_ENABLED?: string;
|
|
||||||
BUNGIE_CUSTOM_NAME?: string;
|
|
||||||
BUNGIE_CLIENT_ID?: string;
|
|
||||||
BUNGIE_CLIENT_SECRET?: string;
|
|
||||||
BUNGIE_API_KEY?: string;
|
|
||||||
|
|
||||||
// Cognito
|
|
||||||
NEXT_PUBLIC_COGNITO_ENABLED?: string;
|
|
||||||
COGNITO_CUSTOM_NAME?: string;
|
|
||||||
COGNITO_CLIENT_ID?: string;
|
|
||||||
COGNITO_CLIENT_SECRET?: string;
|
|
||||||
COGNITO_ISSUER?: string;
|
|
||||||
|
|
||||||
// Coinbase
|
|
||||||
NEXT_PUBLIC_COINBASE_ENABLED?: string;
|
|
||||||
COINBASE_CUSTOM_NAME?: string;
|
|
||||||
COINBASE_CLIENT_ID?: string;
|
|
||||||
COINBASE_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Discord
|
|
||||||
NEXT_PUBLIC_DISCORD_ENABLED?: string;
|
|
||||||
DISCORD_CUSTOM_NAME?: string;
|
|
||||||
DISCORD_CLIENT_ID?: string;
|
|
||||||
DISCORD_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Dropbox
|
|
||||||
NEXT_PUBLIC_DROPBOX_ENABLED?: string;
|
|
||||||
DROPBOX_CUSTOM_NAME?: string;
|
|
||||||
DROPBOX_CLIENT_ID?: string;
|
|
||||||
DROPBOX_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// DuendeIndentityServer6
|
|
||||||
NEXT_PUBLIC_DUENDE_IDS6_ENABLED?: string;
|
|
||||||
DUENDE_IDS6_CUSTOM_NAME?: string;
|
|
||||||
DUENDE_IDS6_CLIENT_ID?: string;
|
|
||||||
DUENDE_IDS6_CLIENT_SECRET?: string;
|
|
||||||
DUENDE_IDS6_ISSUER?: string;
|
|
||||||
|
|
||||||
// EVE Online
|
|
||||||
NEXT_PUBLIC_EVEONLINE_ENABLED?: string;
|
|
||||||
EVEONLINE_CUSTOM_NAME?: string;
|
|
||||||
EVEONLINE_CLIENT_ID?: string;
|
|
||||||
EVEONLINE_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Facebook
|
|
||||||
NEXT_PUBLIC_FACEBOOK_ENABLED?: string;
|
|
||||||
FACEBOOK_CUSTOM_NAME?: string;
|
|
||||||
FACEBOOK_CLIENT_ID?: string;
|
|
||||||
FACEBOOK_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// FACEIT
|
|
||||||
NEXT_PUBLIC_FACEIT_ENABLED?: string;
|
|
||||||
FACEIT_CUSTOM_NAME?: string;
|
|
||||||
FACEIT_CLIENT_ID?: string;
|
|
||||||
FACEIT_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Foursquare
|
|
||||||
NEXT_PUBLIC_FOURSQUARE_ENABLED?: string;
|
|
||||||
FOURSQUARE_CUSTOM_NAME?: string;
|
|
||||||
FOURSQUARE_CLIENT_ID?: string;
|
|
||||||
FOURSQUARE_CLIENT_SECRET?: string;
|
|
||||||
FOURSQUARE_APIVERSION?: string;
|
|
||||||
|
|
||||||
// Freshbooks
|
|
||||||
NEXT_PUBLIC_FRESHBOOKS_ENABLED?: string;
|
|
||||||
FRESHBOOKS_CUSTOM_NAME?: string;
|
|
||||||
FRESHBOOKS_CLIENT_ID?: string;
|
|
||||||
FRESHBOOKS_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// FusionAuth
|
|
||||||
NEXT_PUBLIC_FUSIONAUTH_ENABLED?: string;
|
|
||||||
FUSIONAUTH_CUSTOM_NAME?: string;
|
|
||||||
FUSIONAUTH_CLIENT_ID?: string;
|
|
||||||
FUSIONAUTH_CLIENT_SECRET?: string;
|
|
||||||
FUSIONAUTH_ISSUER?: string;
|
|
||||||
FUSIONAUTH_TENANT_ID?: string;
|
|
||||||
|
|
||||||
// GitHub
|
|
||||||
NEXT_PUBLIC_GITHUB_ENABLED?: string;
|
|
||||||
GITHUB_CUSTOM_NAME?: string;
|
|
||||||
GITHUB_CLIENT_ID?: string;
|
|
||||||
GITHUB_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// GitLab
|
|
||||||
NEXT_PUBLIC_GITLAB_ENABLED?: string;
|
|
||||||
GITLAB_CUSTOM_NAME?: string;
|
|
||||||
GITLAB_CLIENT_ID?: string;
|
|
||||||
GITLAB_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Google
|
|
||||||
NEXT_PUBLIC_GOOGLE_ENABLED?: string;
|
|
||||||
GOOGLE_CUSTOM_NAME?: string;
|
|
||||||
GOOGLE_CLIENT_ID?: string;
|
|
||||||
GOOGLE_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// HubSpot
|
|
||||||
NEXT_PUBLIC_HUBSPOT_ENABLED?: string;
|
|
||||||
HUBSPOT_CUSTOM_NAME?: string;
|
|
||||||
HUBSPOT_CLIENT_ID?: string;
|
|
||||||
HUBSPOT_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// IdentityServer4
|
|
||||||
NEXT_PUBLIC_IDS4_ENABLED?: string;
|
|
||||||
IDS4_CUSTOM_NAME?: string;
|
|
||||||
IDS4_CLIENT_ID?: string;
|
|
||||||
IDS4_CLIENT_SECRET?: string;
|
|
||||||
IDS4_ISSUER?: string;
|
|
||||||
|
|
||||||
// TODO: Instagram (Doesn't return email)
|
|
||||||
|
|
||||||
// Kakao
|
|
||||||
NEXT_PUBLIC_KAKAO_ENABLED?: string;
|
|
||||||
KAKAO_CUSTOM_NAME?: string;
|
|
||||||
KAKAO_CLIENT_ID?: string;
|
|
||||||
KAKAO_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Keycloak
|
|
||||||
NEXT_PUBLIC_KEYCLOAK_ENABLED?: string;
|
|
||||||
KEYCLOAK_CUSTOM_NAME?: string;
|
|
||||||
KEYCLOAK_ISSUER?: string;
|
|
||||||
KEYCLOAK_CLIENT_ID?: string;
|
|
||||||
KEYCLOAK_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// LINE
|
|
||||||
NEXT_PUBLIC_LINE_ENABLED?: string;
|
|
||||||
LINE_CUSTOM_NAME?: string;
|
|
||||||
LINE_CLIENT_ID?: string;
|
|
||||||
LINE_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// LinkedIn
|
|
||||||
NEXT_PUBLIC_LINKEDIN_ENABLED?: string;
|
|
||||||
LINKEDIN_CUSTOM_NAME?: string;
|
|
||||||
LINKEDIN_CLIENT_ID?: string;
|
|
||||||
LINKEDIN_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Mailchimp
|
|
||||||
NEXT_PUBLIC_MAILCHIMP_ENABLED?: string;
|
|
||||||
MAILCHIMP_CUSTOM_NAME?: string;
|
|
||||||
MAILCHIMP_CLIENT_ID?: string;
|
|
||||||
MAILCHIMP_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Mail.ru
|
|
||||||
NEXT_PUBLIC_MAILRU_ENABLED?: string;
|
|
||||||
MAILRU_CUSTOM_NAME?: string;
|
|
||||||
MAILRU_CLIENT_ID?: string;
|
|
||||||
MAILRU_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// TODO: Medium (Doesn't return email)
|
|
||||||
|
|
||||||
// Naver
|
|
||||||
NEXT_PUBLIC_NAVER_ENABLED?: string;
|
|
||||||
NAVER_CUSTOM_NAME?: string;
|
|
||||||
NAVER_CLIENT_ID?: string;
|
|
||||||
NAVER_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Netlify
|
|
||||||
NEXT_PUBLIC_NETLIFY_ENABLED?: string;
|
|
||||||
NETLIFY_CUSTOM_NAME?: string;
|
|
||||||
NETLIFY_CLIENT_ID?: string;
|
|
||||||
NETLIFY_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Okta
|
|
||||||
NEXT_PUBLIC_OKTA_ENABLED?: string;
|
|
||||||
OKTA_CUSTOM_NAME?: string;
|
|
||||||
OKTA_CLIENT_ID?: string;
|
|
||||||
OKTA_CLIENT_SECRET?: string;
|
|
||||||
OKTA_ISSUER?: string;
|
|
||||||
|
|
||||||
// OneLogin
|
|
||||||
NEXT_PUBLIC_ONELOGIN_ENABLED?: string;
|
|
||||||
ONELOGIN_CUSTOM_NAME?: string;
|
|
||||||
ONELOGIN_CLIENT_ID?: string;
|
|
||||||
ONELOGIN_CLIENT_SECRET?: string;
|
|
||||||
ONELOGIN_ISSUER?: string;
|
|
||||||
|
|
||||||
// Osso
|
|
||||||
NEXT_PUBLIC_OSSO_ENABLED?: string;
|
|
||||||
OSSO_CUSTOM_NAME?: string;
|
|
||||||
OSSO_CLIENT_ID?: string;
|
|
||||||
OSSO_CLIENT_SECRET?: string;
|
|
||||||
OSSO_ISSUER?: string;
|
|
||||||
|
|
||||||
// osu!
|
|
||||||
NEXT_PUBLIC_OSU_ENABLED?: string;
|
|
||||||
OSU_CUSTOM_NAME?: string;
|
|
||||||
OSU_CLIENT_ID?: string;
|
|
||||||
OSU_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Patreon
|
|
||||||
NEXT_PUBLIC_PATREON_ENABLED?: string;
|
|
||||||
PATREON_CUSTOM_NAME?: string;
|
|
||||||
PATREON_CLIENT_ID?: string;
|
|
||||||
PATREON_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Pinterest
|
|
||||||
NEXT_PUBLIC_PINTEREST_ENABLED?: string;
|
|
||||||
PINTEREST_CUSTOM_NAME?: string;
|
|
||||||
PINTEREST_CLIENT_ID?: string;
|
|
||||||
PINTEREST_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Pipedrive
|
|
||||||
NEXT_PUBLIC_PIPEDRIVE_ENABLED?: string;
|
|
||||||
PIPEDRIVE_CUSTOM_NAME?: string;
|
|
||||||
PIPEDRIVE_CLIENT_ID?: string;
|
|
||||||
PIPEDRIVE_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Reddit
|
|
||||||
// TODO (1h tokens)
|
|
||||||
NEXT_PUBLIC_REDDIT_ENABLED?: string;
|
|
||||||
REDDIT_CUSTOM_NAME?: string;
|
|
||||||
REDDIT_CLIENT_ID?: string;
|
|
||||||
REDDIT_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Salesforce
|
|
||||||
NEXT_PUBLIC_SALESFORCE_ENABLED?: string;
|
|
||||||
SALESFORCE_CUSTOM_NAME?: string;
|
|
||||||
SALESFORCE_CLIENT_ID?: string;
|
|
||||||
SALESFORCE_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Slack
|
|
||||||
NEXT_PUBLIC_SLACK_ENABLED?: string;
|
|
||||||
SLACK_CUSTOM_NAME?: string;
|
|
||||||
SLACK_CLIENT_ID?: string;
|
|
||||||
SLACK_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Spotify
|
|
||||||
NEXT_PUBLIC_SPOTIFY_ENABLED?: string;
|
|
||||||
SPOTIFY_CUSTOM_NAME?: string;
|
|
||||||
SPOTIFY_CLIENT_ID?: string;
|
|
||||||
SPOTIFY_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Strava
|
|
||||||
NEXT_PUBLIC_STRAVA_ENABLED?: string;
|
|
||||||
STRAVA_CUSTOM_NAME?: string;
|
|
||||||
STRAVA_CLIENT_ID?: string;
|
|
||||||
STRAVA_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Todoist
|
|
||||||
NEXT_PUBLIC_TODOIST_ENABLED?: string;
|
|
||||||
TODOIST_CUSTOM_NAME?: string;
|
|
||||||
TODOIST_CLIENT_ID?: string;
|
|
||||||
TODOIST_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// TODO: Trakt (Doesn't return email)
|
|
||||||
|
|
||||||
// Twitch
|
|
||||||
NEXT_PUBLIC_TWITCH_ENABLED?: string;
|
|
||||||
TWITCH_CUSTOM_NAME?: string;
|
|
||||||
TWITCH_CLIENT_ID?: string;
|
|
||||||
TWITCH_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// TODO: Twitter (OAuth 1.0)
|
|
||||||
|
|
||||||
// United Effects
|
|
||||||
NEXT_PUBLIC_UNITED_EFFECTS_ENABLED?: string;
|
|
||||||
UNITED_EFFECTS_CUSTOM_NAME?: string;
|
|
||||||
UNITED_EFFECTS_CLIENT_ID?: string;
|
|
||||||
UNITED_EFFECTS_CLIENT_SECRET?: string;
|
|
||||||
UNITED_EFFECTS_ISSUER?: string;
|
|
||||||
|
|
||||||
// VK
|
|
||||||
NEXT_PUBLIC_VK_ENABLED?: string;
|
|
||||||
VK_CUSTOM_NAME?: string;
|
|
||||||
VK_CLIENT_ID?: string;
|
|
||||||
VK_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Wikimedia
|
|
||||||
NEXT_PUBLIC_WIKIMEDIA_ENABLED?: string;
|
|
||||||
WIKIMEDIA_CUSTOM_NAME?: string;
|
|
||||||
WIKIMEDIA_CLIENT_ID?: string;
|
|
||||||
WIKIMEDIA_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Wordpress.com
|
|
||||||
NEXT_PUBLIC_WORDPRESS_ENABLED?: string;
|
|
||||||
WORDPRESS_CUSTOM_NAME?: string;
|
|
||||||
WORDPRESS_CLIENT_ID?: string;
|
|
||||||
WORDPRESS_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// TODO: WorkOS (Custom flow)
|
|
||||||
|
|
||||||
// Yandex
|
|
||||||
NEXT_PUBLIC_YANDEX_ENABLED?: string;
|
|
||||||
YANDEX_CUSTOM_NAME?: string;
|
|
||||||
YANDEX_CLIENT_ID?: string;
|
|
||||||
YANDEX_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Zitadel
|
|
||||||
NEXT_PUBLIC_ZITADEL_ENABLED?: string;
|
|
||||||
ZITADEL_CUSTOM_NAME?: string;
|
|
||||||
ZITADEL_CLIENT_ID?: string;
|
|
||||||
ZITADEL_CLIENT_SECRET?: string;
|
|
||||||
ZITADEL_ISSUER?: string;
|
|
||||||
|
|
||||||
// Zoho
|
|
||||||
NEXT_PUBLIC_ZOHO_ENABLED?: string;
|
|
||||||
ZOHO_CUSTOM_NAME?: string;
|
|
||||||
ZOHO_CLIENT_ID?: string;
|
|
||||||
ZOHO_CLIENT_SECRET?: string;
|
|
||||||
|
|
||||||
// Zoom
|
|
||||||
NEXT_PUBLIC_ZOOM_ENABLED?: string;
|
|
||||||
ZOOM_CUSTOM_NAME?: string;
|
|
||||||
ZOOM_CLIENT_ID?: string;
|
|
||||||
ZOOM_CLIENT_SECRET?: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {};
|
|
51
yarn.lock
51
yarn.lock
|
@ -3514,11 +3514,6 @@ function-bind@^1.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||||
|
|
||||||
function-bind@^1.1.2:
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
|
||||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
|
||||||
|
|
||||||
function.prototype.name@^1.1.5:
|
function.prototype.name@^1.1.5:
|
||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
|
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
|
||||||
|
@ -3656,7 +3651,7 @@ glob@7.1.7:
|
||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.0"
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
glob@^7.0.0, glob@^7.1.3:
|
glob@^7.1.3:
|
||||||
version "7.2.3"
|
version "7.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||||
|
@ -3826,13 +3821,6 @@ has@^1.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.1"
|
function-bind "^1.1.1"
|
||||||
|
|
||||||
hasown@^2.0.0:
|
|
||||||
version "2.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
|
||||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
|
||||||
dependencies:
|
|
||||||
function-bind "^1.1.2"
|
|
||||||
|
|
||||||
hexoid@^1.0.0:
|
hexoid@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18"
|
resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18"
|
||||||
|
@ -3984,11 +3972,6 @@ internal-slot@^1.0.3, internal-slot@^1.0.4:
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
side-channel "^1.0.4"
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
interpret@^1.0.0:
|
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
|
|
||||||
integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
|
|
||||||
|
|
||||||
invariant@^2.2.4:
|
invariant@^2.2.4:
|
||||||
version "2.2.4"
|
version "2.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||||
|
@ -4070,13 +4053,6 @@ is-core-module@^2.10.0, is-core-module@^2.11.0, is-core-module@^2.9.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
|
|
||||||
is-core-module@^2.13.0:
|
|
||||||
version "2.13.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
|
|
||||||
integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
|
|
||||||
dependencies:
|
|
||||||
hasown "^2.0.0"
|
|
||||||
|
|
||||||
is-date-object@^1.0.1, is-date-object@^1.0.5:
|
is-date-object@^1.0.1, is-date-object@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
|
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
|
||||||
|
@ -5396,13 +5372,6 @@ readdirp@~3.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
picomatch "^2.2.1"
|
picomatch "^2.2.1"
|
||||||
|
|
||||||
rechoir@^0.6.2:
|
|
||||||
version "0.6.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
|
||||||
integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==
|
|
||||||
dependencies:
|
|
||||||
resolve "^1.1.6"
|
|
||||||
|
|
||||||
redux@^4.0.0, redux@^4.0.1:
|
redux@^4.0.0, redux@^4.0.1:
|
||||||
version "4.2.1"
|
version "4.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
|
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
|
||||||
|
@ -5470,15 +5439,6 @@ resolve-from@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||||
|
|
||||||
resolve@^1.1.6:
|
|
||||||
version "1.22.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
|
|
||||||
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
|
|
||||||
dependencies:
|
|
||||||
is-core-module "^2.13.0"
|
|
||||||
path-parse "^1.0.7"
|
|
||||||
supports-preserve-symlinks-flag "^1.0.0"
|
|
||||||
|
|
||||||
resolve@^1.1.7, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.2:
|
resolve@^1.1.7, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.2:
|
||||||
version "1.22.2"
|
version "1.22.2"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
|
||||||
|
@ -5605,15 +5565,6 @@ shell-quote@^1.8.1:
|
||||||
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680"
|
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680"
|
||||||
integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==
|
integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==
|
||||||
|
|
||||||
shelljs@^0.8.5:
|
|
||||||
version "0.8.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c"
|
|
||||||
integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==
|
|
||||||
dependencies:
|
|
||||||
glob "^7.0.0"
|
|
||||||
interpret "^1.0.0"
|
|
||||||
rechoir "^0.6.2"
|
|
||||||
|
|
||||||
side-channel@^1.0.4:
|
side-channel@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||||
|
|
Ŝarĝante…
Reference in New Issue