diff --git a/.env.example b/.env.example
index 767a6ac1..7ca10d13 100644
--- a/.env.example
+++ b/.env.example
@@ -64,6 +64,14 @@ PINTEREST_CLIENT_ID=""
PINTEREST_CLIENT_SECRET=""
DRIBBBLE_CLIENT_ID=""
DRIBBBLE_CLIENT_SECRET=""
+DISCORD_CLIENT_ID=""
+DISCORD_CLIENT_SECRET=""
+DISCORD_BOT_TOKEN_ID=""
+SLACK_ID=""
+SLACK_SECRET=""
+SLACK_SIGNING_SECRET=""
+MASTODON_CLIENT_ID=""
+MASTODON_CLIENT_SECRET=""
# Misc Settings
OPENAI_API_KEY=""
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index b0e80b68..0c5d671d 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -4,8 +4,16 @@ eg: Bug fix, feature, docs update, ...
# Why was this change needed?
-Please link to related issues when possible.
+Please link to related issues when possible, and explain WHY you changed things, not WHAT you changed.
# Other information:
-eg: Did you discuss this change with anybody before working on it (not required, but can be a good idea for bigger changes). Any plans for the future, etc?
+eg: Did you discuss this change with anybody before working on it (not required, but can be a good idea for bigger changes). Any plans for the future, etc?
+
+# Checklist:
+
+Put a "X" in the boxes below to indicate you have followed the checklist;
+
+- [ ] I have read the [CONTRIBUTING](https://github.com/gitroomhq/postiz-app/blob/main/CONTRIBUTING.md) guide.
+- [ ] I checked that there were not similar issues or PRs already open for this.
+- [ ] This PR fixes just ONE issue (do not include multiple issues or types of change in the same PR) For example, don't try and fix a UI issue and include new dependencies in the same PR.
diff --git a/.github/workflows/build-containers.yml b/.github/workflows/build-containers.yml
index a3dfadc1..a0d83a75 100644
--- a/.github/workflows/build-containers.yml
+++ b/.github/workflows/build-containers.yml
@@ -8,8 +8,27 @@ on:
- '*'
jobs:
- build-containers:
+ build-containers-common:
runs-on: ubuntu-latest
+ outputs:
+ containerver: ${{ steps.getcontainerver.outputs.containerver }}
+ steps:
+ - name: Get Container Version
+ id: getcontainerver
+ run: |
+ echo "containerver=$(date +'%s')" >> "$GITHUB_OUTPUT"
+
+ build-containers:
+ needs: build-containers-common
+ strategy:
+ matrix:
+ include:
+ - runnertags: ubuntu-latest
+ arch: amd64
+ - runnertags: [self-hosted, ARM64]
+ arch: arm64
+
+ runs-on: ${{ matrix.runnertags }}
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -26,24 +45,41 @@ jobs:
- name: docker build
run: ./var/docker/docker-build.sh
- - name: Get date
- run: |
- echo "DATE=$(date +'%s')" >> "$GITHUB_ENV"
-
- name: Print post-build debug info
run: |
docker images
- name: docker tag
+ env:
+ CONTAINERVER: ${{ needs.build-containers-common.outputs.containerver }}
run: |
- docker tag localhost/postiz ghcr.io/gitroomhq/postiz-app:${{ env.DATE }}
- docker push ghcr.io/gitroomhq/postiz-app:${{ env.DATE }}
+ docker tag localhost/postiz ghcr.io/gitroomhq/postiz-app:${{ matrix.arch }}-${{ env.CONTAINERVER }}
+ docker push ghcr.io/gitroomhq/postiz-app:${{ matrix.arch }}-${{ env.CONTAINERVER }}
- docker tag ghcr.io/gitroomhq/postiz-app:${{ env.DATE }} ghcr.io/gitroomhq/postiz-app:latest
- docker push ghcr.io/gitroomhq/postiz-app:latest
+ docker tag localhost/postiz-devcontainer ghcr.io/gitroomhq/postiz-devcontainer:${{ env.CONTAINERVER }}
+ docker push ghcr.io/gitroomhq/postiz-devcontainer:${{ env.CONTAINERVER }}
- docker tag localhost/postiz-devcontainer ghcr.io/gitroomhq/postiz-devcontainer:${{ env.DATE }}
- docker push ghcr.io/gitroomhq/postiz-devcontainer:${{ env.DATE }}
-
- docker tag ghcr.io/gitroomhq/postiz-devcontainer:${{ env.DATE }} ghcr.io/gitroomhq/postiz-devcontainer:latest
+ docker tag ghcr.io/gitroomhq/postiz-devcontainer:${{ env.CONTAINERVER }} ghcr.io/gitroomhq/postiz-devcontainer:latest
docker push ghcr.io/gitroomhq/postiz-devcontainer:latest
+
+ build-container-manifest:
+ needs: [build-containers, build-containers-common]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Login to ghcr
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
+
+ - name: Create Docker Manifest
+ env:
+ CONTAINERVER: ${{ needs.build-containers-common.outputs.containerver }}
+ run: |
+ docker manifest create \
+ ghcr.io/gitroomhq/postiz-app:latest \
+ ghcr.io/gitroomhq/postiz-app:amd64-${{ env.CONTAINERVER }} \
+ ghcr.io/gitroomhq/postiz-app:arm64-${{ env.CONTAINERVER }}
+
+ docker manifest push ghcr.io/gitroomhq/postiz-app:latest
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..f04e4d88
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,54 @@
+# Contributing
+
+Contributions are welcome - code, docs, whatever it might be! If this is your first contribution to an Open Source project or you're a core maintainer of multiple projects, your time and interest in contributing to this project is most welcome.
+
+## Write code with others
+
+This is an open source project, with an open and welcoming community that is always keen to welcome new contributors. We recommend the two best ways to interact with the community are:
+
+- **GitHub issues**: To discuss more slowly, or longer-written messages.
+- **[Discord chat](https://discord.postiz.com)**: To chat with people [Discord chat](https://discord.postiz.com/) and a quicker feedback.
+
+As a general rule;
+
+- **If a change is less than 3 lines**: You're probably safe just to submit the change without a discussion. This includes typos, dependency changes, and quick fixes, etc.
+- **If a change is more than 3 lines**: It's probably best to discuss the change in an issue or on discord first. This is simply because you might not be aware of the roadmap for the project, or understand the impact this change might have. We're just trying to save you time here, and importantly, avoid you being disappointed if your change isn't accepted.
+
+## Types of Contributions
+
+Contributions can include:
+- **Code improvements:** Fixing bugs or adding new features.
+- **Documentation updates:** Enhancing clarity or adding missing information.
+- **Feature requests:** Suggesting new capabilities or integrations.
+- **Bug reports:** Identifying and reporting issues.
+
+## How to contribute
+
+This project follows a Fork/Feature Branch/Pull Request model. If you're not familiar with this, here's how it works:
+
+1. **Fork the project:** Create a personal copy of the repository on your GitHub account.
+2. **Clone your fork:** Bring a copy of your fork to your local machine.
+ ```bash
+ git clone https://github.com/YOUR_USERNAME/postiz.git
+ ```
+3. **Create a new branch**: Start a new branch for your changes
+ ```bash
+ git checkout -b feature/your-feature-name
+ ```
+6. **Make your changes**: Implement the changes you wish to contribute.
+7. **Push your changes**: Upload your changes to your fork.
+ ```bash
+ git push -u origin feature/your-feature-name
+ ```
+9. **Create a pull request**: Propose your changes to the main project.
+
+
+## Setting up your development environment
+To contribute effectively, you’ll need to set up your development environment. Follow the instructions on this page: https://docs.postiz.com/installation/development
+
+
+Need Help?
+If you encounter any issues, please visit our [support page](https://docs.postiz.com/support) or check the community forums. Your contributions help make Postiz better!
+
+
+
diff --git a/Dockerfile.dev b/Dockerfile.dev
index 0162b4ef..71fe30fc 100644
--- a/Dockerfile.dev
+++ b/Dockerfile.dev
@@ -31,6 +31,7 @@ COPY var/docker/Caddyfile /app/Caddyfile
COPY .env.example /config/postiz.env
VOLUME /config
+VOLUME /uploads
LABEL org.opencontainers.image.source=https://github.com/gitroomhq/postiz-app
@@ -55,6 +56,7 @@ COPY libraries /app/libraries/
RUN npm ci --no-fund && npx nx run-many --target=build --projects=frontend,backend,workers,cron
VOLUME /config
+VOLUME /uploads
LABEL org.opencontainers.image.title="Postiz App (DevContainer)"
@@ -70,6 +72,7 @@ COPY --from=devcontainer /app/libraries/ /app/libraries/
COPY package.json nx.json /app/
VOLUME /config
+VOLUME /uploads
## Labels at the bottom, because CI will eventually add dates, commit hashes, etc.
LABEL org.opencontainers.image.title="Postiz App (Production)"
diff --git a/README.md b/README.md
index 88678384..37a882c3 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,3 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -49,6 +35,10 @@
+
+
+
+
@@ -68,6 +58,22 @@
+
+
+
+
We participate in Hacktoberfest 2024! 🎉🎊
+ We are sending a t-shirt for every merged PR! (max 1 per person)
+ Rules:
+
+ You must create an issue before making a pull request.
+ You can also ask to be assigned to an issue. During Hacktoberfest, each issue can have multiple assignees.
+ We have to approve the issue and add a "hacktoberfest" tag.
+ We encourage everybody to contribute to all types of issues. We will only send swag for issues with features and bug fixes (no typos, sorry).
+
+
+
+
+
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..c0fafb4f
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,44 @@
+# Security Policy
+
+## Introduction
+
+The Postiz app is committed to ensuring the security and integrity of our users' data. This security policy outlines our procedures for handling security vulnerabilities and our disclosure policy.
+
+## Reporting Security Vulnerabilities
+
+If you discover a security vulnerability in the Postiz app, please report it to us privately via email to one of the maintainers:
+
+* @nevo-david
+* @jamesread ([email](mailto:contact@jread.com))
+* @jonathan-irvin ([email](mailto:offendingcommit@gmail.com))
+
+When reporting a security vulnerability, please provide as much detail as possible, including:
+
+* A clear description of the vulnerability
+* Steps to reproduce the vulnerability
+* Any relevant code or configuration files
+
+## Supported Versions
+
+This project currently only supports the latest release. We recommend that users always use the latest version of the Postiz app to ensure they have the latest security patches.
+
+## Disclosure Guidelines
+
+We follow a private disclosure policy. If you discover a security vulnerability, please report it to us privately via email to one of the maintainers listed above. We will respond promptly to reports of vulnerabilities and work to resolve them as quickly as possible.
+
+We will not publicly disclose security vulnerabilities until a patch or fix is available to prevent malicious actors from exploiting the vulnerability before a fix is released.
+
+## Security Vulnerability Response Process
+
+We take security vulnerabilities seriously and will respond promptly to reports of vulnerabilities. Our response process includes:
+
+* Investigating the report and verifying the vulnerability.
+* Developing a patch or fix for the vulnerability.
+* Releasing the patch or fix as soon as possible.
+* Notifying users of the vulnerability and the patch or fix.
+
+## Template Attribution
+
+This SECURITY.md file is based on the [GitHub Security Policy Template](https://github.com/github/security/blob/master/SECURITY.md).
+
+Thank you for helping to keep the `postiz-app` secure!
diff --git a/apps/backend/src/api/api.module.ts b/apps/backend/src/api/api.module.ts
index 01156270..d60fabc3 100644
--- a/apps/backend/src/api/api.module.ts
+++ b/apps/backend/src/api/api.module.ts
@@ -11,7 +11,6 @@ import { PermissionsService } from '@gitroom/backend/services/auth/permissions/p
import { IntegrationsController } from '@gitroom/backend/api/routes/integrations.controller';
import { IntegrationManager } from '@gitroom/nestjs-libraries/integrations/integration.manager';
import { SettingsController } from '@gitroom/backend/api/routes/settings.controller';
-import { ioRedis } from '@gitroom/nestjs-libraries/redis/redis.service';
import { PostsController } from '@gitroom/backend/api/routes/posts.controller';
import { MediaController } from '@gitroom/backend/api/routes/media.controller';
import { UploadModule } from '@gitroom/nestjs-libraries/upload/upload.module';
@@ -27,6 +26,7 @@ import { CodesService } from '@gitroom/nestjs-libraries/services/codes.service';
import { CopilotController } from '@gitroom/backend/api/routes/copilot.controller';
import { AgenciesController } from '@gitroom/backend/api/routes/agencies.controller';
import { PublicController } from '@gitroom/backend/api/routes/public.controller';
+import { RootController } from '@gitroom/backend/api/routes/root.controller';
const authenticatedController = [
UsersController,
@@ -60,6 +60,7 @@ const authenticatedController = [
: []),
],
controllers: [
+ RootController,
StripeController,
AuthController,
PublicController,
diff --git a/apps/backend/src/api/routes/auth.controller.ts b/apps/backend/src/api/routes/auth.controller.ts
index bd14422e..ba394cc4 100644
--- a/apps/backend/src/api/routes/auth.controller.ts
+++ b/apps/backend/src/api/routes/auth.controller.ts
@@ -8,11 +8,15 @@ import { ForgotReturnPasswordDto } from '@gitroom/nestjs-libraries/dtos/auth/for
import { ForgotPasswordDto } from '@gitroom/nestjs-libraries/dtos/auth/forgot.password.dto';
import { ApiTags } from '@nestjs/swagger';
import { getCookieUrlFromDomain } from '@gitroom/helpers/subdomain/subdomain.management';
+import { EmailService } from '@gitroom/nestjs-libraries/services/email.service';
@ApiTags('Auth')
@Controller('/auth')
export class AuthController {
- constructor(private _authService: AuthService) {}
+ constructor(
+ private _authService: AuthService,
+ private _emailService: EmailService
+ ) {}
@Post('/register')
async register(
@Req() req: Request,
@@ -30,7 +34,9 @@ export class AuthController {
getOrgFromCookie
);
- if (body.provider === 'LOCAL') {
+ const activationRequired = body.provider === 'LOCAL' && this._emailService.hasProvider();
+
+ if (activationRequired) {
response.header('activate', 'true');
response.status(200).json({ activate: true });
return;
diff --git a/apps/backend/src/api/routes/integrations.controller.ts b/apps/backend/src/api/routes/integrations.controller.ts
index a9a92b2d..6d89b46e 100644
--- a/apps/backend/src/api/routes/integrations.controller.ts
+++ b/apps/backend/src/api/routes/integrations.controller.ts
@@ -27,6 +27,7 @@ import { GetUserFromRequest } from '@gitroom/nestjs-libraries/user/user.from.req
import { NotEnoughScopesFilter } from '@gitroom/nestjs-libraries/integrations/integration.missing.scopes';
import { PostsService } from '@gitroom/nestjs-libraries/database/prisma/posts/posts.service';
import { IntegrationTimeDto } from '@gitroom/nestjs-libraries/dtos/integrations/integration.time.dto';
+import { AuthService } from '@gitroom/helpers/auth/auth.service';
@ApiTags('Integrations')
@Controller('/integrations')
@@ -46,21 +47,68 @@ export class IntegrationsController {
return {
integrations: (
await this._integrationService.getIntegrationsList(org.id)
- ).map((p) => ({
- name: p.name,
- id: p.id,
- internalId: p.internalId,
- disabled: p.disabled,
- picture: p.picture,
- identifier: p.providerIdentifier,
- inBetweenSteps: p.inBetweenSteps,
- refreshNeeded: p.refreshNeeded,
- type: p.type,
- time: JSON.parse(p.postingTimes)
- })),
+ ).map((p) => {
+ const findIntegration = this._integrationManager.getSocialIntegration(
+ p.providerIdentifier
+ );
+ return {
+ name: p.name,
+ id: p.id,
+ internalId: p.internalId,
+ disabled: p.disabled,
+ picture: p.picture,
+ identifier: p.providerIdentifier,
+ inBetweenSteps: p.inBetweenSteps,
+ refreshNeeded: p.refreshNeeded,
+ type: p.type,
+ time: JSON.parse(p.postingTimes),
+ changeProfilePicture: !!findIntegration?.changeProfilePicture,
+ changeNickName: !!findIntegration?.changeNickname,
+ };
+ }),
};
}
+ @Post('/:id/nickname')
+ async setNickname(
+ @GetOrgFromRequest() org: Organization,
+ @Param('id') id: string,
+ @Body() body: { name: string; picture: string }
+ ) {
+ const integration = await this._integrationService.getIntegrationById(
+ org.id,
+ id
+ );
+ if (!integration) {
+ throw new Error('Invalid integration');
+ }
+
+ const manager = this._integrationManager.getSocialIntegration(
+ integration.providerIdentifier
+ );
+ if (!manager.changeProfilePicture && !manager.changeNickname) {
+ throw new Error('Invalid integration');
+ }
+
+ const { url } = manager.changeProfilePicture
+ ? await manager.changeProfilePicture(
+ integration.internalId,
+ integration.token,
+ body.picture
+ )
+ : { url: '' };
+
+ const { name } = manager.changeNickname
+ ? await manager.changeNickname(
+ integration.internalId,
+ integration.token,
+ body.name
+ )
+ : { name: '' };
+
+ return this._integrationService.updateNameAndUrl(id, name, url);
+ }
+
@Get('/:id')
getSingleIntegration(
@Param('id') id: string,
@@ -80,7 +128,8 @@ export class IntegrationsController {
@CheckPolicies([AuthorizationActions.Create, Sections.CHANNEL])
async getIntegrationUrl(
@Param('integration') integration: string,
- @Query('refresh') refresh: string
+ @Query('refresh') refresh: string,
+ @Query('externalUrl') externalUrl: string
) {
if (
!this._integrationManager
@@ -92,11 +141,33 @@ export class IntegrationsController {
const integrationProvider =
this._integrationManager.getSocialIntegration(integration);
- const { codeVerifier, state, url } =
- await integrationProvider.generateAuthUrl(refresh);
- await ioRedis.set(`login:${state}`, codeVerifier, 'EX', 300);
- return { url };
+ if (integrationProvider.externalUrl && !externalUrl) {
+ throw new Error('Missing external url');
+ }
+
+ try {
+ const getExternalUrl = integrationProvider.externalUrl
+ ? {
+ ...(await integrationProvider.externalUrl(externalUrl)),
+ instanceUrl: externalUrl,
+ }
+ : undefined;
+
+ const { codeVerifier, state, url } =
+ await integrationProvider.generateAuthUrl(refresh, getExternalUrl);
+ await ioRedis.set(`login:${state}`, codeVerifier, 'EX', 300);
+ await ioRedis.set(
+ `external:${state}`,
+ JSON.stringify(getExternalUrl),
+ 'EX',
+ 300
+ );
+
+ return { url };
+ } catch (err) {
+ return { err: true };
+ }
}
@Post('/:id/time')
@@ -129,7 +200,11 @@ export class IntegrationsController {
}
if (integrationProvider[body.name]) {
- return integrationProvider[body.name](getIntegration.token, body.data);
+ return integrationProvider[body.name](
+ getIntegration.token,
+ body.data,
+ getIntegration.internalId
+ );
}
throw new Error('Function not found');
}
@@ -144,7 +219,11 @@ export class IntegrationsController {
}
if (integrationProvider[body.name]) {
- return integrationProvider[body.name](getIntegration.token, body.data);
+ return integrationProvider[body.name](
+ getIntegration.token,
+ body.data,
+ getIntegration.internalId
+ );
}
throw new Error('Function not found');
}
@@ -209,15 +288,28 @@ export class IntegrationsController {
throw new Error('Integration not allowed');
}
- const getCodeVerifier = await ioRedis.get(`login:${body.state}`);
+ const integrationProvider =
+ this._integrationManager.getSocialIntegration(integration);
+
+ const getCodeVerifier = integrationProvider.customFields
+ ? 'none'
+ : await ioRedis.get(`login:${body.state}`);
if (!getCodeVerifier) {
throw new Error('Invalid state');
}
- await ioRedis.del(`login:${body.state}`);
+ if (!integrationProvider.customFields) {
+ await ioRedis.del(`login:${body.state}`);
+ }
+
+ const details = integrationProvider.externalUrl
+ ? await ioRedis.get(`external:${body.state}`)
+ : undefined;
+
+ if (details) {
+ await ioRedis.del(`external:${body.state}`);
+ }
- const integrationProvider =
- this._integrationManager.getSocialIntegration(integration);
const {
accessToken,
expiresIn,
@@ -226,11 +318,14 @@ export class IntegrationsController {
name,
picture,
username,
- } = await integrationProvider.authenticate({
- code: body.code,
- codeVerifier: getCodeVerifier,
- refresh: body.refresh,
- });
+ } = await integrationProvider.authenticate(
+ {
+ code: body.code,
+ codeVerifier: getCodeVerifier,
+ refresh: body.refresh,
+ },
+ details ? JSON.parse(details) : undefined
+ );
if (!id) {
throw new Error('Invalid api key');
@@ -249,7 +344,14 @@ export class IntegrationsController {
username,
integrationProvider.isBetweenSteps,
body.refresh,
- +body.timezone
+ +body.timezone,
+ details
+ ? AuthService.fixedEncryption(details)
+ : integrationProvider.customFields
+ ? AuthService.fixedEncryption(
+ Buffer.from(body.code, 'base64').toString()
+ )
+ : undefined
);
}
diff --git a/apps/backend/src/api/routes/root.controller.ts b/apps/backend/src/api/routes/root.controller.ts
new file mode 100644
index 00000000..c79d9080
--- /dev/null
+++ b/apps/backend/src/api/routes/root.controller.ts
@@ -0,0 +1,8 @@
+import { Controller, Get } from '@nestjs/common';
+@Controller('/')
+export class RootController {
+ @Get('/')
+ getRoot(): string {
+ return 'App is running!';
+ }
+}
diff --git a/apps/backend/src/api/routes/users.controller.ts b/apps/backend/src/api/routes/users.controller.ts
index e8d52049..85311535 100644
--- a/apps/backend/src/api/routes/users.controller.ts
+++ b/apps/backend/src/api/routes/users.controller.ts
@@ -21,7 +21,7 @@ import {
AuthorizationActions,
Sections,
} from '@gitroom/backend/services/auth/permissions/permissions.service';
-import { removeSubdomain } from '@gitroom/helpers/subdomain/subdomain.management';
+import { getCookieUrlFromDomain } from '@gitroom/helpers/subdomain/subdomain.management';
import { pricing } from '@gitroom/nestjs-libraries/database/prisma/subscriptions/pricing';
import { ApiTags } from '@nestjs/swagger';
import { UsersService } from '@gitroom/nestjs-libraries/database/prisma/users/users.service';
@@ -92,8 +92,7 @@ export class UsersController {
}
response.cookie('impersonate', id, {
- domain:
- '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ domain: getCookieUrlFromDomain(process.env.FRONTEND_URL!),
secure: true,
httpOnly: true,
sameSite: 'none',
@@ -163,8 +162,7 @@ export class UsersController {
@Res({ passthrough: true }) response: Response
) {
response.cookie('showorg', id, {
- domain:
- '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ domain: getCookieUrlFromDomain(process.env.FRONTEND_URL!),
secure: true,
httpOnly: true,
sameSite: 'none',
@@ -177,8 +175,7 @@ export class UsersController {
@Post('/logout')
logout(@Res({ passthrough: true }) response: Response) {
response.cookie('auth', '', {
- domain:
- '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ domain: getCookieUrlFromDomain(process.env.FRONTEND_URL!),
secure: true,
httpOnly: true,
maxAge: -1,
@@ -187,8 +184,7 @@ export class UsersController {
});
response.cookie('showorg', '', {
- domain:
- '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ domain: getCookieUrlFromDomain(process.env.FRONTEND_URL!),
secure: true,
httpOnly: true,
maxAge: -1,
@@ -197,8 +193,7 @@ export class UsersController {
});
response.cookie('impersonate', '', {
- domain:
- '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ domain: getCookieUrlFromDomain(process.env.FRONTEND_URL!),
secure: true,
httpOnly: true,
maxAge: -1,
diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts
index 7cc0a962..30f1be83 100644
--- a/apps/backend/src/main.ts
+++ b/apps/backend/src/main.ts
@@ -8,6 +8,7 @@ import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SubscriptionExceptionFilter } from '@gitroom/backend/services/auth/permissions/subscription.exception';
import { HttpExceptionFilter } from '@gitroom/nestjs-libraries/services/exception.filter';
+import { ConfigurationChecker } from '@gitroom/helpers/configuration/configuration.checker';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
@@ -38,6 +39,8 @@ async function bootstrap() {
try {
await app.listen(port);
+
+ checkConfiguration() // Do this last, so that users will see obvious issues at the end of the startup log without having to scroll up.
Logger.log(`🚀 Backend is running on: http://localhost:${port}`);
} catch (e) {
@@ -45,4 +48,20 @@ async function bootstrap() {
}
}
+function checkConfiguration() {
+ const checker = new ConfigurationChecker();
+ checker.readEnvFromProcess()
+ checker.check()
+
+ if (checker.hasIssues()) {
+ for (const issue of checker.getIssues()) {
+ Logger.warn(issue, 'Configuration issue')
+ }
+
+ Logger.warn("Configuration issues found: " + checker.getIssuesCount())
+ } else {
+ Logger.log("Configuration check completed without any issues.")
+ }
+}
+
bootstrap();
diff --git a/apps/commands/src/command.module.ts b/apps/commands/src/command.module.ts
index dfa6acaa..9430ef56 100644
--- a/apps/commands/src/command.module.ts
+++ b/apps/commands/src/command.module.ts
@@ -4,11 +4,12 @@ import { CheckStars } from './tasks/check.stars';
import { DatabaseModule } from '@gitroom/nestjs-libraries/database/prisma/database.module';
import { RefreshTokens } from './tasks/refresh.tokens';
import { BullMqModule } from '@gitroom/nestjs-libraries/bull-mq-transport-new/bull.mq.module';
+import { ConfigurationTask } from './tasks/configuration';
@Module({
imports: [ExternalCommandModule, DatabaseModule, BullMqModule],
controllers: [],
- providers: [CheckStars, RefreshTokens],
+ providers: [CheckStars, RefreshTokens, ConfigurationTask],
get exports() {
return [...this.imports, ...this.providers];
},
diff --git a/apps/commands/src/tasks/configuration.ts b/apps/commands/src/tasks/configuration.ts
new file mode 100644
index 00000000..7fd6f287
--- /dev/null
+++ b/apps/commands/src/tasks/configuration.ts
@@ -0,0 +1,30 @@
+import { Command } from 'nestjs-command';
+import { Injectable } from '@nestjs/common';
+import { ConfigurationChecker } from '@gitroom/helpers/configuration/configuration.checker';
+
+@Injectable()
+export class ConfigurationTask {
+ @Command({
+ command: 'config:check',
+ describe: 'Checks your configuration (.env) file for issues.',
+ })
+ create() {
+ const checker = new ConfigurationChecker();
+ checker.readEnvFromProcess()
+ checker.check()
+
+ if (checker.hasIssues()) {
+ for (const issue of checker.getIssues()) {
+ console.warn("Configuration issue:", issue)
+ }
+
+ console.error("Configuration check complete, issues: ", checker.getIssuesCount())
+ } else {
+ console.log("Configuration check complete, no issues found.")
+ }
+
+ console.log("Press Ctrl+C to exit.");
+ return true
+ }
+}
+
diff --git a/apps/cron/src/cron.module.ts b/apps/cron/src/cron.module.ts
index a44744b9..4db31e81 100644
--- a/apps/cron/src/cron.module.ts
+++ b/apps/cron/src/cron.module.ts
@@ -8,6 +8,6 @@ import { BullMqModule } from '@gitroom/nestjs-libraries/bull-mq-transport-new/bu
@Module({
imports: [DatabaseModule, ScheduleModule.forRoot(), BullMqModule],
controllers: [],
- providers: [CheckStars, SyncTrending],
+ providers: [...(!process.env.IS_GENERAL ? [CheckStars, SyncTrending] : [])],
})
export class CronModule {}
diff --git a/apps/frontend/public/icons/platforms/bluesky.png b/apps/frontend/public/icons/platforms/bluesky.png
new file mode 100644
index 00000000..492b23a6
Binary files /dev/null and b/apps/frontend/public/icons/platforms/bluesky.png differ
diff --git a/apps/frontend/public/icons/platforms/discord.png b/apps/frontend/public/icons/platforms/discord.png
new file mode 100644
index 00000000..90af762a
Binary files /dev/null and b/apps/frontend/public/icons/platforms/discord.png differ
diff --git a/apps/frontend/public/icons/platforms/mastodon-custom.png b/apps/frontend/public/icons/platforms/mastodon-custom.png
new file mode 100644
index 00000000..79670abc
Binary files /dev/null and b/apps/frontend/public/icons/platforms/mastodon-custom.png differ
diff --git a/apps/frontend/public/icons/platforms/mastodon.png b/apps/frontend/public/icons/platforms/mastodon.png
new file mode 100644
index 00000000..79670abc
Binary files /dev/null and b/apps/frontend/public/icons/platforms/mastodon.png differ
diff --git a/apps/frontend/public/icons/platforms/slack.png b/apps/frontend/public/icons/platforms/slack.png
new file mode 100644
index 00000000..09cb7004
Binary files /dev/null and b/apps/frontend/public/icons/platforms/slack.png differ
diff --git a/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx b/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx
index bead77f8..8a06e542 100644
--- a/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx
+++ b/apps/frontend/src/app/(site)/integrations/social/[provider]/continue/page.tsx
@@ -4,6 +4,7 @@ export const dynamic = 'force-dynamic';
import { internalFetch } from '@gitroom/helpers/utils/internal.fetch';
import { redirect } from 'next/navigation';
+import { Redirect } from '@gitroom/frontend/components/layout/redirect';
export default async function Page({
params: { provider },
@@ -30,6 +31,22 @@ export default async function Page({
return redirect(`/launches?scope=missing`);
}
+ if (
+ data.status !== HttpStatusCode.Ok &&
+ data.status !== HttpStatusCode.Created
+ ) {
+ return (
+ <>
+
+ Could not add provider.
+
+ You are being redirected back
+
+
+ >
+ );
+ }
+
const { inBetweenSteps, id } = await data.json();
if (inBetweenSteps && !searchParams.refresh) {
diff --git a/apps/frontend/src/app/global.scss b/apps/frontend/src/app/global.scss
index 64dec72f..da791348 100644
--- a/apps/frontend/src/app/global.scss
+++ b/apps/frontend/src/app/global.scss
@@ -361,6 +361,7 @@ html {
.uppy-ProgressBar-percentage {
position: absolute;
+ color: red;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
@@ -383,4 +384,4 @@ div div .set-font-family {
font-stretch: 100% !important;
font-style: normal !important;
font-weight: 400 !important;
-}
\ No newline at end of file
+}
diff --git a/apps/frontend/src/components/auth/login.tsx b/apps/frontend/src/components/auth/login.tsx
index 9810e5d6..13a458ec 100644
--- a/apps/frontend/src/components/auth/login.tsx
+++ b/apps/frontend/src/components/auth/login.tsx
@@ -89,7 +89,7 @@ export function Login() {
-
+
Sign in
diff --git a/apps/frontend/src/components/auth/register.tsx b/apps/frontend/src/components/auth/register.tsx
index ff678025..e22b3653 100644
--- a/apps/frontend/src/components/auth/register.tsx
+++ b/apps/frontend/src/components/auth/register.tsx
@@ -65,6 +65,17 @@ export function Register() {
);
}
+function getHelpfulReasonForRegistrationFailure(httpCode: number) {
+ switch (httpCode) {
+ case 400:
+ return 'Email already exists';
+ case 404:
+ return 'Your browser got a 404 when trying to contact the API, the most likely reasons for this are the NEXT_PUBLIC_BACKEND_URL is set incorrectly, or the backend is not running.';
+ }
+
+ return 'Unhandled error: ' + httpCode;
+}
+
export function RegisterAfter({
token,
provider,
@@ -97,23 +108,31 @@ export function RegisterAfter({
const onSubmit: SubmitHandler
= async (data) => {
setLoading(true);
- const register = await fetchData('/auth/register', {
+
+ await fetchData('/auth/register', {
method: 'POST',
body: JSON.stringify({ ...data }),
- });
- if (register.status === 400) {
- form.setError('email', {
- message: 'Email already exists',
- });
-
+ }).then((response) => {
setLoading(false);
- }
- fireEvents('register');
+ if (response.status === 200) {
+ fireEvents('register')
- if (register.headers.get('activate')) {
- router.push('/auth/activate');
- }
+ if (response.headers.get('activate') === "true") {
+ router.push('/auth/activate');
+ } else {
+ router.push('/auth/login');
+ }
+ } else {
+ form.setError('email', {
+ message: getHelpfulReasonForRegistrationFailure(response.status),
+ });
+ }
+ }).catch(e => {
+ form.setError("email", {
+ message: 'General error: ' + e.toString() + '. Please check your browser console.',
+ });
+ })
};
return (
@@ -179,7 +198,7 @@ export function RegisterAfter({
-
+
Create Account
diff --git a/apps/frontend/src/components/billing/faq.component.tsx b/apps/frontend/src/components/billing/faq.component.tsx
index 97231547..fff38e76 100644
--- a/apps/frontend/src/components/billing/faq.component.tsx
+++ b/apps/frontend/src/components/billing/faq.component.tsx
@@ -10,7 +10,7 @@ const useFaqList = () => {
return [
{
title: `Can I trust ${isGeneral ? 'Postiz' : 'Gitroom'}?`,
- description: `${isGeneral ? 'Postiz' : 'Gitroom'} is proudly open-source! We believe in an ethical and transparent culture, meaning Postiz will live forever. You can check the entire code / or use it for your personal use. You can check the open-source repository click here.`,
+ description: `${isGeneral ? 'Postiz' : 'Gitroom'} is proudly open-source! We believe in an ethical and transparent culture, meaning that ${isGeneral ? 'Postiz' : 'Gitroom'} will live forever. You can check out the entire code or use it for personal projects. To view the open-source repository,
click here .`,
},
{
title: 'What are channels?',
@@ -18,7 +18,7 @@ const useFaqList = () => {
isGeneral ? 'Postiz' : 'Gitroom'
} allows you to schedule your posts between different channels.
A channel is a publishing platform where you can schedule your posts.
-For example, you can schedule your posts on Twitter, Linkedin, DEV and Hashnode`,
+For example, you can schedule your posts on X, Facebook, Instagram, TikTok, YouTube, Reddit, Linkedin, Dribbble, Threads and Pinterest.`,
},
{
title: 'What are team members?',
diff --git a/apps/frontend/src/components/launches/add.provider.component.tsx b/apps/frontend/src/components/launches/add.provider.component.tsx
index 7d0f6a8b..dc5e9049 100644
--- a/apps/frontend/src/components/launches/add.provider.component.tsx
+++ b/apps/frontend/src/components/launches/add.provider.component.tsx
@@ -1,7 +1,7 @@
'use client';
import { useModals } from '@mantine/modals';
-import React, { FC, useCallback } from 'react';
+import React, { FC, useCallback, useMemo } from 'react';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import { Input } from '@gitroom/react/form/input';
import { FieldValues, FormProvider, useForm } from 'react-hook-form';
@@ -11,6 +11,9 @@ import { ApiKeyDto } from '@gitroom/nestjs-libraries/dtos/integrations/api.key.d
import { useRouter } from 'next/navigation';
import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component';
import { useVariables } from '@gitroom/react/helpers/variable.context';
+import { useToaster } from '@gitroom/react/toaster/toaster';
+import { object, string } from 'yup';
+import { yupResolver } from '@hookform/resolvers/yup';
const resolver = classValidatorResolver(ApiKeyDto);
@@ -127,24 +130,246 @@ export const ApiModal: FC<{
);
};
+
+export const UrlModal: FC<{
+ gotoUrl(url: string): void;
+}> = (props) => {
+ const { gotoUrl } = props;
+ const methods = useForm({
+ mode: 'onChange',
+ });
+
+ const submit = useCallback(async (data: FieldValues) => {
+ gotoUrl(data.url);
+ }, []);
+
+ return (
+
+ );
+};
+
+export const CustomVariables: FC<{
+ variables: Array<{
+ key: string;
+ label: string;
+ defaultValue?: string;
+ validation: string;
+ type: 'text' | 'password';
+ }>;
+ identifier: string;
+ gotoUrl(url: string): void;
+}> = (props) => {
+ const { gotoUrl, identifier, variables } = props;
+ const modals = useModals();
+ const schema = useMemo(() => {
+ return object({
+ ...variables.reduce((aIcc, item) => {
+ const splitter = item.validation.split('/');
+ const regex = new RegExp(
+ splitter.slice(1, -1).join('/'),
+ splitter.pop()
+ );
+ return {
+ ...aIcc,
+ [item.key]: string()
+ .matches(regex, `${item.label} is invalid`)
+ .required(),
+ };
+ }, {}),
+ });
+ }, [variables]);
+
+ const methods = useForm({
+ mode: 'onChange',
+ resolver: yupResolver(schema),
+ values: variables.reduce(
+ (acc, item) => ({
+ ...acc,
+ ...(item.defaultValue ? { [item.key]: item.defaultValue } : {}),
+ }),
+ {}
+ ),
+ });
+
+ const submit = useCallback(
+ async (data: FieldValues) => {
+ gotoUrl(
+ `/integrations/social/${identifier}?state=nostate&code=${Buffer.from(
+ JSON.stringify(data)
+ ).toString('base64')}`
+ );
+ },
+ [variables]
+ );
+
+ return (
+
+ );
+};
+
export const AddProviderComponent: FC<{
- social: Array<{ identifier: string; name: string }>;
+ social: Array<{
+ identifier: string;
+ name: string;
+ isExternal: boolean;
+ customFields?: Array<{
+ key: string;
+ label: string;
+ validation: string;
+ type: 'text' | 'password';
+ }>;
+ }>;
article: Array<{ identifier: string; name: string }>;
update?: () => void;
}> = (props) => {
- const { update } = props;
- const {isGeneral} = useVariables();
-
+ const { update, social, article } = props;
+ const { isGeneral } = useVariables();
+ const toaster = useToaster();
+ const router = useRouter();
const fetch = useFetch();
const modal = useModals();
- const { social, article } = props;
const getSocialLink = useCallback(
- (identifier: string) => async () => {
- const { url } = await (
- await fetch('/integrations/social/' + identifier)
- ).json();
- window.location.href = url;
- },
+ (
+ identifier: string,
+ isExternal: boolean,
+ customFields?: Array<{
+ key: string;
+ label: string;
+ validation: string;
+ defaultValue?: string;
+ type: 'text' | 'password';
+ }>
+ ) =>
+ async () => {
+ const gotoIntegration = async (externalUrl?: string) => {
+ const { url, err } = await (
+ await fetch(
+ `/integrations/social/${identifier}${
+ externalUrl ? `?externalUrl=${externalUrl}` : ``
+ }`
+ )
+ ).json();
+
+ if (err) {
+ toaster.show('Could not connect to the platform', 'warning');
+ return;
+ }
+ window.location.href = url;
+ };
+
+ if (isExternal) {
+ modal.closeAll();
+
+ modal.openModal({
+ title: '',
+ withCloseButton: false,
+ classNames: {
+ modal: 'bg-transparent text-textColor',
+ },
+ children: ,
+ });
+
+ return;
+ }
+
+ if (customFields) {
+ modal.closeAll();
+
+ modal.openModal({
+ title: '',
+ withCloseButton: false,
+ classNames: {
+ modal: 'bg-transparent text-textColor',
+ },
+ children: (
+ router.push(url)}
+ variables={customFields}
+ />
+ ),
+ });
+ return;
+ }
+
+ await gotoIntegration();
+ },
[]
);
@@ -196,7 +421,11 @@ export const AddProviderComponent: FC<{
{social.map((item) => (
void;
+}> = (props) => {
+ const modal = useModals();
+ const toast = useToaster();
+ const [nick, setNickname] = useState(props.integration.name);
+ const [picture, setPicture] = useState(props.integration.picture);
+
+ const fetch = useFetch();
+ const submitForm: FormEventHandler
= useCallback(
+ async (e) => {
+ e.preventDefault();
+ await fetch(`/integrations/${props.integration.id}/nickname`, {
+ method: 'POST',
+ body: JSON.stringify({ name: nick, picture }),
+ });
+
+ props.mutate();
+ toast.show('Updated', 'success');
+ modal.closeAll();
+ },
+ [nick, picture, props.mutate]
+ );
+
+ const openMedia = useCallback(() => {
+ showMediaBox((values) => {
+ setPicture(values.path);
+ });
+ }, []);
+
+ return (
+
+
+
modal.closeAll()}
+ >
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/frontend/src/components/launches/calendar.context.tsx b/apps/frontend/src/components/launches/calendar.context.tsx
index 901b02f5..2c508e66 100644
--- a/apps/frontend/src/components/launches/calendar.context.tsx
+++ b/apps/frontend/src/components/launches/calendar.context.tsx
@@ -57,6 +57,8 @@ export interface Integrations {
identifier: string;
type: string;
picture: string;
+ changeProfilePicture: boolean;
+ changeNickName: boolean;
time: { time: number }[];
}
diff --git a/apps/frontend/src/components/launches/filters.tsx b/apps/frontend/src/components/launches/filters.tsx
index f399ecbd..5dcc29a8 100644
--- a/apps/frontend/src/components/launches/filters.tsx
+++ b/apps/frontend/src/components/launches/filters.tsx
@@ -188,7 +188,7 @@ export const Filters = () => {
{betweenDates}
{
{
{
useEffect(() => {
if (typeof window === 'undefined') {
- return ;
+ return;
}
if (search.get('scope') === 'missing') {
toast.show('You have to approve all the channel permissions', 'warning');
@@ -117,7 +117,7 @@ export const LaunchesComponent = () => {
-
+
Channels
{sortedIntegrations.length === 0 && (
@@ -196,6 +196,8 @@ export const LaunchesComponent = () => {
{integration.name}
void,
+ mutate: () => void;
onChange: (shouldReload: boolean) => void;
}> = (props) => {
- const { canEnable, canDisable, id, onChange, mutate } = props;
+ const {
+ canEnable,
+ canDisable,
+ id,
+ onChange,
+ mutate,
+ canChangeProfilePicture,
+ canChangeNickName,
+ } = props;
const fetch = useFetch();
const { integrations } = useCalendar();
const toast = useToaster();
@@ -98,8 +109,30 @@ export const Menu: FC<{
withCloseButton: false,
closeOnEscape: false,
closeOnClickOutside: false,
+ children: ,
+ });
+ setShow(false);
+ }, [integrations]);
+
+ const changeBotPicture = useCallback(() => {
+ const findIntegration = integrations.find(
+ (integration) => integration.id === id
+ );
+ modal.openModal({
+ classNames: {
+ modal: 'w-[100%] max-w-[600px] bg-transparent text-textColor',
+ },
+ size: '100%',
+ withCloseButton: false,
+ closeOnEscape: true,
+ closeOnClickOutside: true,
children: (
-
+
),
});
setShow(false);
@@ -128,6 +161,36 @@ export const Menu: FC<{
onClick={(e) => e.stopPropagation()}
className={`absolute top-[100%] left-0 p-[8px] px-[20px] bg-fifth flex flex-col gap-[16px] z-[100] rounded-[8px] border border-tableBorder ${interClass} text-nowrap`}
>
+ {(canChangeProfilePicture || canChangeNickName) && (
+
+
+
+ Change Bot{' '}
+ {[
+ canChangeProfilePicture && 'Picture',
+ canChangeNickName && 'Nickname',
+ ]
+ .filter((f) => f)
+ .join(' / ')}
+
+
+ )}
{
+ return null;
+};
+
+export default withProvider(null, Empty, undefined, async (posts) => {
+ if (posts.some((p) => p.length > 4)) {
+ return 'There can be maximum 4 pictures in a post.';
+ }
+
+ return true;
+});
diff --git a/apps/frontend/src/components/launches/providers/discord/discord.channel.select.tsx b/apps/frontend/src/components/launches/providers/discord/discord.channel.select.tsx
new file mode 100644
index 00000000..967d2a8d
--- /dev/null
+++ b/apps/frontend/src/components/launches/providers/discord/discord.channel.select.tsx
@@ -0,0 +1,44 @@
+import { FC, useEffect, useState } from 'react';
+import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function';
+import { Select } from '@gitroom/react/form/select';
+import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values';
+
+export const DiscordChannelSelect: FC<{
+ name: string;
+ onChange: (event: { target: { value: string; name: string } }) => void;
+}> = (props) => {
+ const { onChange, name } = props;
+ const customFunc = useCustomProviderFunction();
+ const [publications, setOrgs] = useState([]);
+ const { getValues } = useSettings();
+ const [currentMedia, setCurrentMedia] = useState();
+
+ const onChangeInner = (event: { target: { value: string, name: string } }) => {
+ setCurrentMedia(event.target.value);
+ onChange(event);
+ };
+
+ useEffect(() => {
+ customFunc.get('channels').then((data) => setOrgs(data));
+ const settings = getValues()[props.name];
+ if (settings) {
+ setCurrentMedia(settings);
+ }
+ }, []);
+
+
+ if (!publications.length) {
+ return null;
+ }
+
+ return (
+
+ --Select--
+ {publications.map((publication: any) => (
+
+ {publication.name}
+
+ ))}
+
+ );
+};
diff --git a/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx b/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx
new file mode 100644
index 00000000..86f00438
--- /dev/null
+++ b/apps/frontend/src/components/launches/providers/discord/discord.provider.tsx
@@ -0,0 +1,25 @@
+import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider';
+import { FC } from 'react';
+import { DiscordDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/discord.dto';
+import { DiscordChannelSelect } from '@gitroom/frontend/components/launches/providers/discord/discord.channel.select';
+import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values';
+
+const Empty: FC = () => {
+ return null;
+};
+
+const DiscordComponent: FC = () => {
+ const form = useSettings();
+ return (
+
+
+
+ );
+};
+export default withProvider(
+ DiscordComponent,
+ Empty,
+ DiscordDto,
+ undefined,
+ 280
+);
diff --git a/apps/frontend/src/components/launches/providers/mastodon/mastodon.provider.tsx b/apps/frontend/src/components/launches/providers/mastodon/mastodon.provider.tsx
new file mode 100644
index 00000000..901ea78e
--- /dev/null
+++ b/apps/frontend/src/components/launches/providers/mastodon/mastodon.provider.tsx
@@ -0,0 +1,8 @@
+import { FC } from 'react';
+import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider';
+
+const Empty: FC = (props) => {
+ return null;
+};
+
+export default withProvider(null, Empty, undefined, undefined);
diff --git a/apps/frontend/src/components/launches/providers/show.all.providers.tsx b/apps/frontend/src/components/launches/providers/show.all.providers.tsx
index e215d71e..0fece0eb 100644
--- a/apps/frontend/src/components/launches/providers/show.all.providers.tsx
+++ b/apps/frontend/src/components/launches/providers/show.all.providers.tsx
@@ -13,6 +13,10 @@ import TiktokProvider from '@gitroom/frontend/components/launches/providers/tikt
import PinterestProvider from '@gitroom/frontend/components/launches/providers/pinterest/pinterest.provider';
import DribbbleProvider from '@gitroom/frontend/components/launches/providers/dribbble/dribbble.provider';
import ThreadsProvider from '@gitroom/frontend/components/launches/providers/threads/threads.provider';
+import DiscordProvider from '@gitroom/frontend/components/launches/providers/discord/discord.provider';
+import SlackProvider from '@gitroom/frontend/components/launches/providers/slack/slack.provider';
+import MastodonProvider from '@gitroom/frontend/components/launches/providers/mastodon/mastodon.provider';
+import BlueskyProvider from '@gitroom/frontend/components/launches/providers/bluesky/bluesky.provider';
export const Providers = [
{identifier: 'devto', component: DevtoProvider},
@@ -29,6 +33,10 @@ export const Providers = [
{identifier: 'pinterest', component: PinterestProvider},
{identifier: 'dribbble', component: DribbbleProvider},
{identifier: 'threads', component: ThreadsProvider},
+ {identifier: 'discord', component: DiscordProvider},
+ {identifier: 'slack', component: SlackProvider},
+ {identifier: 'mastodon', component: MastodonProvider},
+ {identifier: 'bluesky', component: BlueskyProvider},
];
diff --git a/apps/frontend/src/components/launches/providers/slack/slack.channel.select.tsx b/apps/frontend/src/components/launches/providers/slack/slack.channel.select.tsx
new file mode 100644
index 00000000..d07f4260
--- /dev/null
+++ b/apps/frontend/src/components/launches/providers/slack/slack.channel.select.tsx
@@ -0,0 +1,44 @@
+import { FC, useEffect, useState } from 'react';
+import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function';
+import { Select } from '@gitroom/react/form/select';
+import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values';
+
+export const SlackChannelSelect: FC<{
+ name: string;
+ onChange: (event: { target: { value: string; name: string } }) => void;
+}> = (props) => {
+ const { onChange, name } = props;
+ const customFunc = useCustomProviderFunction();
+ const [publications, setOrgs] = useState([]);
+ const { getValues } = useSettings();
+ const [currentMedia, setCurrentMedia] = useState();
+
+ const onChangeInner = (event: { target: { value: string, name: string } }) => {
+ setCurrentMedia(event.target.value);
+ onChange(event);
+ };
+
+ useEffect(() => {
+ customFunc.get('channels').then((data) => setOrgs(data));
+ const settings = getValues()[props.name];
+ if (settings) {
+ setCurrentMedia(settings);
+ }
+ }, []);
+
+
+ if (!publications.length) {
+ return null;
+ }
+
+ return (
+
+ --Select--
+ {publications.map((publication: any) => (
+
+ {publication.name}
+
+ ))}
+
+ );
+};
diff --git a/apps/frontend/src/components/launches/providers/slack/slack.provider.tsx b/apps/frontend/src/components/launches/providers/slack/slack.provider.tsx
new file mode 100644
index 00000000..90857a87
--- /dev/null
+++ b/apps/frontend/src/components/launches/providers/slack/slack.provider.tsx
@@ -0,0 +1,25 @@
+import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider';
+import { FC } from 'react';
+import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values';
+import { SlackChannelSelect } from '@gitroom/frontend/components/launches/providers/slack/slack.channel.select';
+import { SlackDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/slack.dto';
+
+const Empty: FC = () => {
+ return null;
+};
+
+const SlackComponent: FC = () => {
+ const form = useSettings();
+ return (
+
+
+
+ );
+};
+export default withProvider(
+ SlackComponent,
+ Empty,
+ SlackDto,
+ undefined,
+ 280
+);
diff --git a/apps/frontend/src/components/launches/providers/x/x.provider.tsx b/apps/frontend/src/components/launches/providers/x/x.provider.tsx
index b099db4e..3e0cec02 100644
--- a/apps/frontend/src/components/launches/providers/x/x.provider.tsx
+++ b/apps/frontend/src/components/launches/providers/x/x.provider.tsx
@@ -102,4 +102,10 @@ const XPreview: FC = (props) => {
);
};
-export default withProvider(null, XPreview, undefined, undefined, 280);
+export default withProvider(null, XPreview, undefined, async (posts) => {
+ if (posts.some(p => p.length > 4)) {
+ return 'There can be maximum 4 pictures in a post.';
+ }
+
+ return true;
+}, 280);
diff --git a/apps/frontend/src/components/layout/continue.provider.tsx b/apps/frontend/src/components/layout/continue.provider.tsx
index bc1e814e..9f12971c 100644
--- a/apps/frontend/src/components/layout/continue.provider.tsx
+++ b/apps/frontend/src/components/layout/continue.provider.tsx
@@ -88,6 +88,8 @@ export const ContinueProvider: FC = () => {
name: '',
picture: '',
inBetweenSteps: true,
+ changeNickName: false,
+ changeProfilePicture: false,
identifier: added,
},
}}
diff --git a/apps/frontend/src/components/layout/redirect.tsx b/apps/frontend/src/components/layout/redirect.tsx
new file mode 100644
index 00000000..6a7dca4a
--- /dev/null
+++ b/apps/frontend/src/components/layout/redirect.tsx
@@ -0,0 +1,15 @@
+'use client';
+
+import { FC, useEffect } from 'react';
+import { useRouter } from 'next/navigation';
+
+export const Redirect: FC<{url: string, delay: number}> = (props) => {
+ const { url, delay } = props;
+ const router = useRouter();
+ useEffect(() => {
+ setTimeout(() => {
+ router.push(url);
+ }, delay);
+ }, []);
+ return null;
+}
\ No newline at end of file
diff --git a/apps/frontend/src/components/layout/settings.component.tsx b/apps/frontend/src/components/layout/settings.component.tsx
index a0d8e817..436f7fe9 100644
--- a/apps/frontend/src/components/layout/settings.component.tsx
+++ b/apps/frontend/src/components/layout/settings.component.tsx
@@ -155,12 +155,12 @@ export const SettingsPopup: FC<{ getRef?: Ref }> = (props) => {
/>
-
+
Upload image
@@ -173,11 +173,11 @@ export const SettingsPopup: FC<{ getRef?: Ref
}> = (props) => {
>
-
+
Remove
@@ -191,7 +191,7 @@ export const SettingsPopup: FC<{ getRef?: Ref
}> = (props) => {
{!getRef && (
- Save
+ Save
)}
{!!user?.tier?.team_members && isGeneral && }
diff --git a/apps/frontend/src/components/onboarding/connect.channels.tsx b/apps/frontend/src/components/onboarding/connect.channels.tsx
index 02987db8..65e5c7f7 100644
--- a/apps/frontend/src/components/onboarding/connect.channels.tsx
+++ b/apps/frontend/src/components/onboarding/connect.channels.tsx
@@ -242,6 +242,8 @@ export const ConnectChannels: FC = () => {
{integration.name}
nextUrl.href.indexOf(p) > -1);
- const additional = !findIndex ? '' : (url.indexOf('?') > -1 ? '&' : '?') + `provider=${(findIndex === 'settings' ? 'github' : findIndex).toUpperCase()}`;
- return NextResponse.redirect(new URL(`/auth${url}${additional}`, nextUrl.href));
+ const findIndex = providers.find((p) => nextUrl.href.indexOf(p) > -1);
+ const additional = !findIndex
+ ? ''
+ : (url.indexOf('?') > -1 ? '&' : '?') +
+ `provider=${(findIndex === 'settings'
+ ? 'github'
+ : findIndex
+ ).toUpperCase()}`;
+ return NextResponse.redirect(
+ new URL(`/auth${url}${additional}`, nextUrl.href)
+ );
}
// If the url is /auth and the cookie exists, redirect to /
@@ -49,8 +56,7 @@ export async function middleware(request: NextRequest) {
httpOnly: true,
secure: true,
expires: new Date(Date.now() + 15 * 60 * 1000),
- domain:
- '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ domain: getCookieUrlFromDomain(process.env.FRONTEND_URL!),
});
return redirect;
}
@@ -81,8 +87,7 @@ export async function middleware(request: NextRequest) {
httpOnly: true,
secure: true,
expires: new Date(Date.now() + 15 * 60 * 1000),
- domain:
- '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ domain: getCookieUrlFromDomain(process.env.FRONTEND_URL!),
});
}
@@ -91,7 +96,10 @@ export async function middleware(request: NextRequest) {
if (nextUrl.pathname === '/') {
return NextResponse.redirect(
- new URL(!!process.env.IS_GENERAL ? '/launches' : `/analytics`, nextUrl.href)
+ new URL(
+ !!process.env.IS_GENERAL ? '/launches' : `/analytics`,
+ nextUrl.href
+ )
);
}
@@ -109,8 +117,7 @@ export async function middleware(request: NextRequest) {
httpOnly: true,
secure: true,
expires: new Date(Date.now() + 15 * 60 * 1000),
- domain:
- '.' + new URL(removeSubdomain(process.env.FRONTEND_URL!)).hostname,
+ domain: getCookieUrlFromDomain(process.env.FRONTEND_URL!),
});
}
diff --git a/apps/workers/src/app/app.module.ts b/apps/workers/src/app/app.module.ts
index efaf1029..20d2e381 100644
--- a/apps/workers/src/app/app.module.ts
+++ b/apps/workers/src/app/app.module.ts
@@ -8,7 +8,7 @@ import { BullMqModule } from '@gitroom/nestjs-libraries/bull-mq-transport-new/bu
@Module({
imports: [DatabaseModule, BullMqModule],
- controllers: [StarsController, PostsController],
+ controllers: [...!process.env.IS_GENERAL ? [StarsController] : [], PostsController],
providers: [TrendingService],
})
export class AppModule {}
diff --git a/libraries/helpers/src/configuration/configuration.checker.ts b/libraries/helpers/src/configuration/configuration.checker.ts
new file mode 100644
index 00000000..425de8ad
--- /dev/null
+++ b/libraries/helpers/src/configuration/configuration.checker.ts
@@ -0,0 +1,115 @@
+import { readFileSync, existsSync } from 'fs'
+import * as dotenv from 'dotenv'
+import { resolve } from 'path'
+
+export class ConfigurationChecker {
+ cfg: dotenv.DotenvParseOutput
+ issues: string[] = []
+
+ readEnvFromFile () {
+ const envFile = resolve(__dirname, '../../../.env')
+
+ if (!existsSync(envFile)) {
+ console.error('Env file not found!: ', envFile)
+ return
+ }
+
+ const handle = readFileSync(envFile, 'utf-8')
+
+ this.cfg = dotenv.parse(handle)
+ }
+
+ readEnvFromProcess () {
+ this.cfg = process.env
+ }
+
+ check () {
+ this.checkDatabaseServers()
+ this.checkNonEmpty('JWT_SECRET')
+ this.checkIsValidUrl('MAIN_URL')
+ this.checkIsValidUrl('FRONTEND_URL')
+ this.checkIsValidUrl('NEXT_PUBLIC_BACKEND_URL')
+ this.checkIsValidUrl('BACKEND_INTERNAL_URL')
+ this.checkNonEmpty('CLOUDFLARE_ACCOUNT_ID', 'Needed to setup providers.')
+ this.checkNonEmpty('CLOUDFLARE_ACCESS_KEY', 'Needed to setup providers.')
+ this.checkNonEmpty('CLOUDFLARE_SECRET_ACCESS_KEY', 'Needed to setup providers.')
+ this.checkNonEmpty('CLOUDFLARE_BUCKETNAME', 'Needed to setup providers.')
+ this.checkNonEmpty('CLOUDFLARE_BUCKET_URL', 'Needed to setup providers.')
+ this.checkNonEmpty('CLOUDFLARE_REGION', 'Needed to setup providers.')
+ }
+
+ checkNonEmpty (key: string, description?: string): boolean {
+ const v = this.get(key)
+
+ if (!description) {
+ description = ''
+ }
+
+ if (!v) {
+ this.issues.push(key + ' not set. ' + description)
+ return false
+ }
+
+ if (v.length === 0) {
+ this.issues.push(key + ' is empty.' + description)
+ return false
+ }
+
+ return true
+ }
+
+ get(key: string): string | undefined {
+ return this.cfg[key as keyof typeof this.cfg]
+ }
+
+ checkDatabaseServers () {
+ this.checkRedis()
+ this.checkIsValidUrl('DATABASE_URL')
+ }
+
+ checkRedis () {
+ if (!this.cfg.REDIS_URL) {
+ this.issues.push('REDIS_URL not set')
+ }
+
+ try {
+ const redisUrl = new URL(this.cfg.REDIS_URL)
+
+ if (redisUrl.protocol !== 'redis:') {
+ this.issues.push('REDIS_URL must start with redis://')
+ }
+ } catch (error) {
+ this.issues.push('REDIS_URL is not a valid URL')
+ }
+ }
+
+ checkIsValidUrl (key: string) {
+ if (!this.checkNonEmpty(key)) {
+ return
+ }
+
+ const urlString = this.get(key)
+
+ try {
+ new URL(urlString)
+ } catch (error) {
+ this.issues.push(key + ' is not a valid URL')
+ }
+
+ if (urlString.endsWith('/')) {
+ this.issues.push(key + ' should not end with /')
+ }
+ }
+
+ hasIssues() {
+ return this.issues.length > 0
+ }
+
+ getIssues() {
+ return this.issues
+ }
+
+ getIssuesCount() {
+ return this.issues.length
+ }
+}
diff --git a/libraries/helpers/src/subdomain/subdomain.management.ts b/libraries/helpers/src/subdomain/subdomain.management.ts
index 7a8aa931..ec54bd38 100644
--- a/libraries/helpers/src/subdomain/subdomain.management.ts
+++ b/libraries/helpers/src/subdomain/subdomain.management.ts
@@ -1,37 +1,6 @@
-import {allTwoLevelSubdomain} from "./all.two.level.subdomain";
-const ipRegex = /^(https?:\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(:\d+)?$/;
-
-export function removeSubdomain(domain: string) {
- // Check if the domain is an IP address with optional port
- if (ipRegex.test(domain)) {
- return domain; // Return the original domain if it's an IP address
- }
- // Split the domain into its parts
- const parts = domain.split('.');
-
- // Check if there are at least two parts (e.g., 'example.com')
- if (parts.length < 2) {
- return domain; // Return the original domain if it's too short to have a subdomain
- }
-
- if (parts.length > 2) {
- const lastTwo = parts.slice(-2).join('.');
- if (allTwoLevelSubdomain.includes(lastTwo)) {
- return 'https://' + parts.slice(-3).join('.'); // Return the last three parts for known second-level domains
- }
- }
-
- // Return the last two parts for standard domains
- return 'https://' + parts.slice(-2).join('.');
-}
-
+import { parse } from 'tldts';
export function getCookieUrlFromDomain(domain: string) {
- const url = removeSubdomain(domain);
- const urlObj = new URL(url);
- if (!ipRegex.test(domain)) {
- return '.' + urlObj.hostname
- }
-
- return urlObj.hostname;
+ const url = parse(domain);
+ return url.domain! ? "." + url.domain! : url.hostname!;
}
\ No newline at end of file
diff --git a/libraries/helpers/src/utils/read.or.fetch.ts b/libraries/helpers/src/utils/read.or.fetch.ts
index 10c93904..f5b2338b 100644
--- a/libraries/helpers/src/utils/read.or.fetch.ts
+++ b/libraries/helpers/src/utils/read.or.fetch.ts
@@ -1,8 +1,13 @@
import {readFileSync} from "fs";
+import axios from 'axios';
export const readOrFetch = async (path: string) => {
if (path.indexOf('http') === 0) {
- return (await fetch(path)).arrayBuffer();
+ return (await axios({
+ url: path,
+ method: 'GET',
+ responseType: 'arraybuffer',
+ })).data;
}
return readFileSync(path);
diff --git a/libraries/nestjs-libraries/src/database/prisma/integrations/integration.repository.ts b/libraries/nestjs-libraries/src/database/prisma/integrations/integration.repository.ts
index 7778c05a..145c5ce3 100644
--- a/libraries/nestjs-libraries/src/database/prisma/integrations/integration.repository.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/integrations/integration.repository.ts
@@ -79,7 +79,8 @@ export class IntegrationRepository {
username?: string,
isBetweenSteps = false,
refresh?: string,
- timezone?: number
+ timezone?: number,
+ customInstanceDetails?: string
) {
const postTimes = timezone
? {
@@ -113,6 +114,7 @@ export class IntegrationRepository {
...postTimes,
organizationId: org,
refreshNeeded: false,
+ ...(customInstanceDetails ? { customInstanceDetails } : {}),
},
update: {
type: type as any,
@@ -121,7 +123,6 @@ export class IntegrationRepository {
inBetweenSteps: isBetweenSteps,
}
: {}),
- name,
picture,
profile: username,
providerIdentifier: provider,
@@ -163,6 +164,18 @@ export class IntegrationRepository {
});
}
+ updateNameAndUrl(id: string, name: string, url: string) {
+ return this._integration.model.integration.update({
+ where: {
+ id,
+ },
+ data: {
+ ...(name ? { name } : {}),
+ ...(url ? { picture: url } : {}),
+ },
+ });
+ }
+
getIntegrationById(org: string, id: string) {
return this._integration.model.integration.findFirst({
where: {
diff --git a/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts b/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts
index c67d7c9e..0de38c66 100644
--- a/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts
@@ -47,7 +47,8 @@ export class IntegrationService {
username?: string,
isBetweenSteps = false,
refresh?: string,
- timezone?: number
+ timezone?: number,
+ customInstanceDetails?: string
) {
const loadImage = await axios.get(picture, { responseType: 'arraybuffer' });
const uploadedPicture = await simpleUpload(
@@ -69,7 +70,8 @@ export class IntegrationService {
username,
isBetweenSteps,
refresh,
- timezone
+ timezone,
+ customInstanceDetails
);
}
@@ -86,6 +88,10 @@ export class IntegrationService {
);
}
+ updateNameAndUrl(id: string, name: string, url: string) {
+ return this._integrationRepository.updateNameAndUrl(id, name, url);
+ }
+
getIntegrationById(org: string, id: string) {
return this._integrationRepository.getIntegrationById(org, id);
}
diff --git a/libraries/nestjs-libraries/src/database/prisma/notifications/notification.service.ts b/libraries/nestjs-libraries/src/database/prisma/notifications/notification.service.ts
index bbe8d5b7..52f9ce3c 100644
--- a/libraries/nestjs-libraries/src/database/prisma/notifications/notification.service.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/notifications/notification.service.ts
@@ -40,4 +40,8 @@ export class NotificationService {
async sendEmail(to: string, subject: string, html: string) {
await this._emailService.sendEmail(to, subject, html);
}
+
+ hasEmailProvider() {
+ return this._emailService.hasProvider();
+ }
}
diff --git a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts
index fd62013a..85084600 100644
--- a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts
@@ -177,7 +177,8 @@ export class OrganizationRepository {
}
async createOrgAndUser(
- body: Omit & { providerId?: string }
+ body: Omit & { providerId?: string },
+ hasEmail: boolean
) {
return this._organization.model.organization.create({
data: {
@@ -187,7 +188,7 @@ export class OrganizationRepository {
role: Role.SUPERADMIN,
user: {
create: {
- activated: body.provider !== 'LOCAL' || !process.env.RESEND_API_KEY,
+ activated: body.provider !== 'LOCAL' || !hasEmail,
email: body.email,
password: body.password
? AuthService.hashPassword(body.password)
diff --git a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.service.ts b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.service.ts
index 18c947fe..db239ac3 100644
--- a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.service.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.service.ts
@@ -17,7 +17,7 @@ export class OrganizationService {
async createOrgAndUser(
body: Omit & { providerId?: string }
) {
- return this._organizationRepository.createOrgAndUser(body);
+ return this._organizationRepository.createOrgAndUser(body, this._notificationsService.hasEmailProvider());
}
addUserToOrg(
diff --git a/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts b/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts
index 1ec0b844..272b80c2 100644
--- a/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts
@@ -135,6 +135,7 @@ export class PostsService {
`An error occurred while posting on ${firstPost.integration?.providerIdentifier}`,
true
);
+
return;
}
@@ -160,6 +161,25 @@ export class PostsService {
}`,
true
);
+
+ if (err instanceof BadBody) {
+ console.error(
+ '[Error] posting on',
+ firstPost.integration?.providerIdentifier,
+ err.identifier,
+ err.json,
+ err.body,
+ err
+ );
+
+ return;
+ }
+
+ console.error(
+ '[Error] posting on',
+ firstPost.integration?.providerIdentifier,
+ err
+ );
}
}
@@ -258,7 +278,8 @@ export class PostsService {
? process.env.UPLOAD_DIRECTORY + m.path
: m.path,
})),
- }))
+ })),
+ integration
);
for (const post of publishedPosts) {
@@ -287,17 +308,6 @@ export class PostsService {
return this.postSocial(integration, posts, true);
}
- if (
- err instanceof BadBody &&
- process.env.EMAIL_FROM_ADDRESS === 'nevo@postiz.com'
- ) {
- await this._notificationService.sendEmail(
- 'nevo@positz.com',
- 'Bad body',
- JSON.stringify(err.body)
- );
- }
-
throw err;
}
}
diff --git a/libraries/nestjs-libraries/src/database/prisma/schema.prisma b/libraries/nestjs-libraries/src/database/prisma/schema.prisma
index 3944ec4d..a2858330 100644
--- a/libraries/nestjs-libraries/src/database/prisma/schema.prisma
+++ b/libraries/nestjs-libraries/src/database/prisma/schema.prisma
@@ -242,27 +242,28 @@ model Subscription {
}
model Integration {
- id String @id @default(cuid())
- internalId String
- organizationId String
- name String
- organization Organization @relation(fields: [organizationId], references: [id])
- picture String?
- providerIdentifier String
- type String
- token String
- disabled Boolean @default(false)
- tokenExpiration DateTime?
- refreshToken String?
- posts Post[]
- profile String?
- deletedAt DateTime?
- createdAt DateTime @default(now())
- updatedAt DateTime? @updatedAt
- orderItems OrderItems[]
- inBetweenSteps Boolean @default(false)
- refreshNeeded Boolean @default(false)
- postingTimes String @default("[{\"time\":120}, {\"time\":400}, {\"time\":700}]")
+ id String @id @default(cuid())
+ internalId String
+ organizationId String
+ name String
+ organization Organization @relation(fields: [organizationId], references: [id])
+ picture String?
+ providerIdentifier String
+ type String
+ token String
+ disabled Boolean @default(false)
+ tokenExpiration DateTime?
+ refreshToken String?
+ posts Post[]
+ profile String?
+ deletedAt DateTime?
+ createdAt DateTime @default(now())
+ updatedAt DateTime? @updatedAt
+ orderItems OrderItems[]
+ inBetweenSteps Boolean @default(false)
+ refreshNeeded Boolean @default(false)
+ postingTimes String @default("[{\"time\":120}, {\"time\":400}, {\"time\":700}]")
+ customInstanceDetails String?
@@index([updatedAt])
@@index([deletedAt])
diff --git a/libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts b/libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts
index 20d813c4..f661a2a5 100644
--- a/libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts
+++ b/libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts
@@ -12,6 +12,8 @@ import { YoutubeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/provide
import { PinterestSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/pinterest.dto';
import { DribbbleDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/dribbble.dto';
import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto';
+import { DiscordDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/discord.dto';
+import { SlackDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/slack.dto';
export class EmptySettings {}
export class Integration {
@@ -68,6 +70,8 @@ export class Post {
{ value: PinterestSettingsDto, name: 'pinterest' },
{ value: DribbbleDto, name: 'dribbble' },
{ value: TikTokDto, name: 'tiktok' },
+ { value: DiscordDto, name: 'discord' },
+ { value: SlackDto, name: 'slack' },
],
},
})
diff --git a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/discord.dto.ts b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/discord.dto.ts
new file mode 100644
index 00000000..980ea53f
--- /dev/null
+++ b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/discord.dto.ts
@@ -0,0 +1,8 @@
+import { IsDefined, IsString, MinLength } from 'class-validator';
+
+export class DiscordDto {
+ @MinLength(1)
+ @IsDefined()
+ @IsString()
+ channel: string;
+}
\ No newline at end of file
diff --git a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/slack.dto.ts b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/slack.dto.ts
new file mode 100644
index 00000000..1e443374
--- /dev/null
+++ b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/slack.dto.ts
@@ -0,0 +1,8 @@
+import { IsDefined, IsString, MinLength } from 'class-validator';
+
+export class SlackDto {
+ @MinLength(1)
+ @IsDefined()
+ @IsString()
+ channel: string;
+}
\ No newline at end of file
diff --git a/libraries/nestjs-libraries/src/emails/email.interface.ts b/libraries/nestjs-libraries/src/emails/email.interface.ts
new file mode 100644
index 00000000..7e6acbc0
--- /dev/null
+++ b/libraries/nestjs-libraries/src/emails/email.interface.ts
@@ -0,0 +1,5 @@
+export interface EmailInterface {
+ name: string;
+ validateEnvKeys: string[];
+ sendEmail(to: string, subject: string, html: string, emailFromName: string, emailFromAddress: string): Promise;
+}
\ No newline at end of file
diff --git a/libraries/nestjs-libraries/src/emails/empty.provider.ts b/libraries/nestjs-libraries/src/emails/empty.provider.ts
new file mode 100644
index 00000000..c146c7ba
--- /dev/null
+++ b/libraries/nestjs-libraries/src/emails/empty.provider.ts
@@ -0,0 +1,9 @@
+import { EmailInterface } from "./email.interface";
+
+export class EmptyProvider implements EmailInterface {
+ name = 'no provider';
+ validateEnvKeys = [];
+ async sendEmail(to: string, subject: string, html: string) {
+ return `No email provider found, email was supposed to be sent to ${to} with subject: ${subject} and ${html}, html`;
+ }
+}
\ No newline at end of file
diff --git a/libraries/nestjs-libraries/src/emails/node.mailer.provider.ts b/libraries/nestjs-libraries/src/emails/node.mailer.provider.ts
new file mode 100644
index 00000000..b0b8ca65
--- /dev/null
+++ b/libraries/nestjs-libraries/src/emails/node.mailer.provider.ts
@@ -0,0 +1,40 @@
+import nodemailer from 'nodemailer';
+import { EmailInterface } from '@gitroom/nestjs-libraries/emails/email.interface';
+
+const transporter = nodemailer.createTransport({
+ host: process.env.EMAIL_HOST,
+ port: +process.env.EMAIL_PORT!,
+ secure: process.env.EMAIL_SECURE === 'true',
+ auth: {
+ user: process.env.EMAIL_USER,
+ pass: process.env.EMAIL_PASS,
+ },
+});
+
+export class NodeMailerProvider implements EmailInterface {
+ name = 'nodemailer';
+ validateEnvKeys = [
+ 'EMAIL_HOST',
+ 'EMAIL_PORT',
+ 'EMAIL_SECURE',
+ 'EMAIL_USER',
+ 'EMAIL_PASS',
+ ];
+ async sendEmail(
+ to: string,
+ subject: string,
+ html: string,
+ emailFromName: string,
+ emailFromAddress: string
+ ) {
+ const sends = await transporter.sendMail({
+ from:`${emailFromName} <${emailFromAddress}>`, // sender address
+ to: to, // list of receivers
+ subject: subject, // Subject line
+ text: html, // plain text body
+ html: html, // html body
+ });
+
+ return sends;
+ }
+}
diff --git a/libraries/nestjs-libraries/src/emails/resend.provider.ts b/libraries/nestjs-libraries/src/emails/resend.provider.ts
new file mode 100644
index 00000000..15e34cf5
--- /dev/null
+++ b/libraries/nestjs-libraries/src/emails/resend.provider.ts
@@ -0,0 +1,19 @@
+import { Resend } from 'resend';
+import { EmailInterface } from '@gitroom/nestjs-libraries/emails/email.interface';
+
+const resend = new Resend(process.env.RESEND_API_KEY || 're_132');
+
+export class ResendProvider implements EmailInterface {
+ name = 'resend';
+ validateEnvKeys = ['RESEND_API_KEY'];
+ async sendEmail(to: string, subject: string, html: string, emailFromName: string, emailFromAddress: string) {
+ const sends = await resend.emails.send({
+ from: `${emailFromName} <${emailFromAddress}>`,
+ to,
+ subject,
+ html,
+ });
+
+ return sends;
+ }
+}
diff --git a/libraries/nestjs-libraries/src/integrations/integration.manager.ts b/libraries/nestjs-libraries/src/integrations/integration.manager.ts
index beea4116..e4e951d8 100644
--- a/libraries/nestjs-libraries/src/integrations/integration.manager.ts
+++ b/libraries/nestjs-libraries/src/integrations/integration.manager.ts
@@ -15,8 +15,13 @@ import { PinterestProvider } from '@gitroom/nestjs-libraries/integrations/social
import { DribbbleProvider } from '@gitroom/nestjs-libraries/integrations/social/dribbble.provider';
import { LinkedinPageProvider } from '@gitroom/nestjs-libraries/integrations/social/linkedin.page.provider';
import { ThreadsProvider } from '@gitroom/nestjs-libraries/integrations/social/threads.provider';
+import { DiscordProvider } from '@gitroom/nestjs-libraries/integrations/social/discord.provider';
+import { SlackProvider } from '@gitroom/nestjs-libraries/integrations/social/slack.provider';
+import { MastodonProvider } from '@gitroom/nestjs-libraries/integrations/social/mastodon.provider';
+import { BlueskyProvider } from '@gitroom/nestjs-libraries/integrations/social/bluesky.provider';
+// import { MastodonCustomProvider } from '@gitroom/nestjs-libraries/integrations/social/mastodon.custom.provider';
-const socialIntegrationList = [
+const socialIntegrationList: SocialProvider[] = [
new XProvider(),
new LinkedinProvider(),
new LinkedinPageProvider(),
@@ -28,6 +33,11 @@ const socialIntegrationList = [
new TiktokProvider(),
new PinterestProvider(),
new DribbbleProvider(),
+ new DiscordProvider(),
+ new SlackProvider(),
+ new MastodonProvider(),
+ new BlueskyProvider(),
+ // new MastodonCustomProvider(),
];
const articleIntegrationList = [
@@ -38,12 +48,16 @@ const articleIntegrationList = [
@Injectable()
export class IntegrationManager {
- getAllIntegrations() {
+ async getAllIntegrations() {
return {
- social: socialIntegrationList.map((p) => ({
- name: p.name,
- identifier: p.identifier,
- })),
+ social: await Promise.all(
+ socialIntegrationList.map(async (p) => ({
+ name: p.name,
+ identifier: p.identifier,
+ isExternal: !!p.externalUrl,
+ ...(p.customFields ? { customFields: await p.customFields() } : {}),
+ }))
+ ),
article: articleIntegrationList.map((p) => ({
name: p.name,
identifier: p.identifier,
diff --git a/libraries/nestjs-libraries/src/integrations/social.abstract.ts b/libraries/nestjs-libraries/src/integrations/social.abstract.ts
index 39034f55..9d06d017 100644
--- a/libraries/nestjs-libraries/src/integrations/social.abstract.ts
+++ b/libraries/nestjs-libraries/src/integrations/social.abstract.ts
@@ -1,32 +1,40 @@
-export class RefreshToken {}
+export class RefreshToken {
+ constructor(
+ public identifier: string,
+ public json: string,
+ public body: BodyInit
+ ) {}
+}
export class BadBody {
- constructor(public body: BodyInit) {
- }
+ constructor(
+ public identifier: string,
+ public json: string,
+ public body: BodyInit
+ ) {}
}
export class NotEnoughScopes {}
export abstract class SocialAbstract {
- async fetch(url: string, options: RequestInit = {}) {
+ async fetch(url: string, options: RequestInit = {}, identifier = '') {
const request = await fetch(url, options);
- if (request.status !== 200 && request.status !== 201) {
- try {
- console.log(await request.json());
- }
- catch (err) {
- console.log('skip');
- }
+ if (request.status === 200 || request.status === 201) {
+ return request;
}
+
+ let json = '{}';
+ try {
+ json = await request.text();
+ } catch (err) {
+ json = '{}';
+ }
+
if (request.status === 401) {
- throw new RefreshToken();
+ throw new RefreshToken(identifier, json, options.body!);
}
- if (request.status === 400) {
- throw new BadBody(options.body!);
- }
-
- return request;
+ throw new BadBody(identifier, json, options.body!);
}
checkScopes(required: string[], got: string | string[]) {
diff --git a/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts b/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts
new file mode 100644
index 00000000..e8147b7a
--- /dev/null
+++ b/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts
@@ -0,0 +1,178 @@
+import {
+ AuthTokenDetails,
+ PostDetails,
+ PostResponse,
+ SocialProvider,
+} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
+import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
+import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
+import { BskyAgent } from '@atproto/api';
+import dayjs from 'dayjs';
+import { Integration } from '@prisma/client';
+import { AuthService } from '@gitroom/helpers/auth/auth.service';
+import sharp from 'sharp';
+
+export class BlueskyProvider extends SocialAbstract implements SocialProvider {
+ identifier = 'bluesky';
+ name = 'Bluesky';
+ isBetweenSteps = false;
+ scopes = ['write:statuses', 'profile', 'write:media'];
+
+ async customFields() {
+ return [
+ {
+ key: 'service',
+ label: 'Service',
+ defaultValue: 'https://bsky.social',
+ validation: `/^(https?:\\/\\/)?((([a-zA-Z0-9\\-_]{1,256}\\.[a-zA-Z]{2,6})|(([0-9]{1,3}\\.){3}[0-9]{1,3}))(:[0-9]{1,5})?)(\\/[^\\s]*)?$/`,
+ type: 'text' as const,
+ },
+ {
+ key: 'identifier',
+ label: 'Identifier',
+ validation: `/^.{3,}$/`,
+ type: 'text' as const,
+ },
+ {
+ key: 'password',
+ label: 'Password',
+ validation: `/^.{3,}$/`,
+ type: 'password' as const,
+ },
+ ];
+ }
+
+ async refreshToken(refreshToken: string): Promise {
+ return {
+ refreshToken: '',
+ expiresIn: 0,
+ accessToken: '',
+ id: '',
+ name: '',
+ picture: '',
+ username: '',
+ };
+ }
+
+ async generateAuthUrl(refresh?: string) {
+ const state = makeId(6);
+ return {
+ url: '',
+ codeVerifier: makeId(10),
+ state,
+ };
+ }
+
+ async authenticate(params: {
+ code: string;
+ codeVerifier: string;
+ refresh?: string;
+ }) {
+ const body = JSON.parse(Buffer.from(params.code, 'base64').toString());
+
+ const agent = new BskyAgent({
+ service: body.service,
+ });
+
+ const {
+ data: { accessJwt, refreshJwt, handle, did },
+ } = await agent.login({
+ identifier: body.identifier,
+ password: body.password,
+ });
+
+ const profile = await agent.getProfile({
+ actor: did,
+ });
+
+ return {
+ refreshToken: refreshJwt,
+ expiresIn: dayjs().add(100, 'years').unix() - dayjs().unix(),
+ accessToken: accessJwt,
+ id: did,
+ name: profile.data.displayName!,
+ picture: profile.data.avatar!,
+ username: profile.data.handle!,
+ };
+ }
+
+ async post(
+ id: string,
+ accessToken: string,
+ postDetails: PostDetails[],
+ integration: Integration
+ ): Promise {
+ const body = JSON.parse(
+ AuthService.fixedDecryption(integration.customInstanceDetails!)
+ );
+ const agent = new BskyAgent({
+ service: body.service,
+ });
+
+ await agent.login({
+ identifier: body.identifier,
+ password: body.password,
+ });
+
+ let loadCid = '';
+ let loadUri = '';
+ const cidUrl = [] as { cid: string; url: string, rev: string }[];
+ for (const post of postDetails) {
+ const images = await Promise.all(
+ post.media?.map(async (p) => {
+ return await agent.uploadBlob(
+ new Blob([
+ await sharp(await (await fetch(p.url)).arrayBuffer())
+ .resize({ width: 400 })
+ .toBuffer(),
+ ])
+ );
+ }) || []
+ );
+
+ // @ts-ignore
+ const { cid, uri, commit } = await agent.post({
+ text: post.message,
+ createdAt: new Date().toISOString(),
+ ...(images.length
+ ? {
+ embed: {
+ $type: 'app.bsky.embed.images',
+ images: images.map((p) => ({
+ // can be an array up to 4 values
+ alt: 'image', // the alt text
+ image: p.data.blob,
+ })),
+ },
+ }
+ : {}),
+ ...(loadCid
+ ? {
+ reply: {
+ root: {
+ uri: loadUri,
+ cid: loadCid,
+ },
+ parent: {
+ uri: loadUri,
+ cid: loadCid,
+ },
+ },
+ }
+ : {}),
+ });
+
+ loadCid = loadCid || cid;
+ loadUri = loadUri || uri;
+
+ cidUrl.push({ cid, url: uri, rev: commit.rev });
+ }
+
+ return postDetails.map((p, index) => ({
+ id: p.id,
+ postId: cidUrl[index].cid,
+ status: 'completed',
+ releaseURL: `https://bsky.app/profile/${id}/post/${cidUrl[index].url.split('/').pop()}`,
+ }));
+ }
+}
diff --git a/libraries/nestjs-libraries/src/integrations/social/discord.provider.ts b/libraries/nestjs-libraries/src/integrations/social/discord.provider.ts
new file mode 100644
index 00000000..d03ea417
--- /dev/null
+++ b/libraries/nestjs-libraries/src/integrations/social/discord.provider.ts
@@ -0,0 +1,226 @@
+import {
+ AuthTokenDetails,
+ PostDetails,
+ PostResponse,
+ SocialProvider,
+} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
+import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
+import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
+
+export class DiscordProvider extends SocialAbstract implements SocialProvider {
+ identifier = 'discord';
+ name = 'Discord';
+ isBetweenSteps = false;
+ scopes = ['identify', 'guilds'];
+ async refreshToken(refreshToken: string): Promise {
+ const { access_token, expires_in, refresh_token } = await (
+ await this.fetch('https://discord.com/api/oauth2/token', {
+ method: 'POST',
+ body: new URLSearchParams({
+ refresh_token: refreshToken,
+ grant_type: 'refresh_token',
+ }),
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ Authorization: `Basic ${Buffer.from(
+ process.env.DISCORD_CLIENT_ID +
+ ':' +
+ process.env.DISCORD_CLIENT_SECRET
+ ).toString('base64')}`,
+ },
+ })
+ ).json();
+
+ const { application } = await (
+ await fetch('https://discord.com/api/oauth2/@me', {
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ },
+ })
+ ).json();
+
+ return {
+ refreshToken: refresh_token,
+ expiresIn: expires_in,
+ accessToken: access_token,
+ id: '',
+ name: application.name,
+ picture: '',
+ username: '',
+ };
+ }
+ async generateAuthUrl(refresh?: string) {
+ const state = makeId(6);
+ return {
+ url: `https://discord.com/oauth2/authorize?client_id=${
+ process.env.DISCORD_CLIENT_ID
+ }&permissions=377957124096&response_type=code&redirect_uri=${encodeURIComponent(
+ `${process.env.FRONTEND_URL}/integrations/social/discord${
+ refresh ? `?refresh=${refresh}` : ''
+ }`
+ )}&integration_type=0&scope=bot+identify+guilds&state=${state}`,
+ codeVerifier: makeId(10),
+ state,
+ };
+ }
+
+ async authenticate(params: {
+ code: string;
+ codeVerifier: string;
+ refresh?: string;
+ }) {
+ const { access_token, expires_in, refresh_token, scope, guild } = await (
+ await this.fetch('https://discord.com/api/oauth2/token', {
+ method: 'POST',
+ body: new URLSearchParams({
+ code: params.code,
+ grant_type: 'authorization_code',
+ redirect_uri: `${process.env.FRONTEND_URL}/integrations/social/discord`,
+ }),
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ Authorization: `Basic ${Buffer.from(
+ process.env.DISCORD_CLIENT_ID +
+ ':' +
+ process.env.DISCORD_CLIENT_SECRET
+ ).toString('base64')}`,
+ },
+ })
+ ).json();
+
+ this.checkScopes(this.scopes, scope.split(' '));
+
+ const { application } = await (
+ await fetch('https://discord.com/api/oauth2/@me', {
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ },
+ })
+ ).json();
+
+ return {
+ id: guild.id,
+ name: application.name,
+ accessToken: access_token,
+ refreshToken: refresh_token,
+ expiresIn: expires_in,
+ picture: `https://cdn.discordapp.com/avatars/${application.bot.id}/${application.bot.avatar}.png`,
+ username: application.bot.username,
+ };
+ }
+
+ async channels(accessToken: string, params: any, id: string) {
+ const list = await (
+ await fetch(`https://discord.com/api/guilds/${id}/channels`, {
+ headers: {
+ Authorization: `Bot ${process.env.DISCORD_BOT_TOKEN_ID}`,
+ },
+ })
+ ).json();
+
+ console.log(list);
+
+ return list
+ .filter((p: any) => p.type === 0 || p.type === 15)
+ .map((p: any) => ({
+ id: String(p.id),
+ name: p.name,
+ }));
+ }
+
+ async post(
+ id: string,
+ accessToken: string,
+ postDetails: PostDetails[]
+ ): Promise {
+ let channel = postDetails[0].settings.channel;
+ if (postDetails.length > 1) {
+ const { id: threadId } = await (
+ await fetch(
+ `https://discord.com/api/channels/${postDetails[0].settings.channel}/threads`,
+ {
+ method: 'POST',
+ headers: {
+ Authorization: `Bot ${process.env.DISCORD_BOT_TOKEN_ID}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ name: postDetails[0].message,
+ auto_archive_duration: 1440,
+ type: 11, // Public thread type
+ }),
+ }
+ )
+ ).json();
+ channel = threadId;
+ }
+
+ const finalData = [];
+ for (const post of postDetails) {
+ const form = new FormData();
+ form.append(
+ 'payload_json',
+ JSON.stringify({
+ content: post.message,
+ attachments: post.media?.map((p, index) => ({
+ id: index,
+ description: `Picture ${index}`,
+ filename: p.url.split('/').pop(),
+ })),
+ })
+ );
+
+ let index = 0;
+ for (const media of post.media || []) {
+ const loadMedia = await fetch(media.url);
+
+ form.append(
+ `files[${index}]`,
+ await loadMedia.blob(),
+ media.url.split('/').pop()
+ );
+ index++;
+ }
+
+ const data = await (
+ await fetch(`https://discord.com/api/channels/${channel}/messages`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bot ${process.env.DISCORD_BOT_TOKEN_ID}`,
+ },
+ body: form,
+ })
+ ).json();
+
+ finalData.push({
+ id: post.id,
+ releaseURL: `https://discord.com/channels/${id}/${channel}/${data.id}`,
+ postId: data.id,
+ status: 'success',
+ });
+ }
+
+ return finalData;
+ }
+
+ async changeNickname(
+ id: string,
+ accessToken: string,
+ name: string,
+ ) {
+ await (await fetch(`https://discord.com/api/guilds/${id}/members/@me`, {
+ method: 'PATCH',
+ headers: {
+ Authorization: `Bot ${process.env.DISCORD_BOT_TOKEN_ID}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ nick: name,
+ })
+ })).json();
+
+ return {
+ name,
+ }
+ }
+}
diff --git a/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts b/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts
index 7332848a..3e2d84b8 100644
--- a/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts
@@ -174,7 +174,8 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
let finalId = '';
let finalUrl = '';
if ((firstPost?.media?.[0]?.path?.indexOf('mp4') || -2) > -1) {
- const { id: videoId, permalink_url } = await (
+ console.log('mp4');
+ const { id: videoId, permalink_url, ...all } = await (
await this.fetch(
`https://graph.facebook.com/v20.0/${id}/videos?access_token=${accessToken}&fields=id,permalink_url`,
{
@@ -183,15 +184,16 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
'Content-Type': 'application/json',
},
body: JSON.stringify({
- file_url: firstPost?.media?.[0]?.path!,
+ file_url: firstPost?.media?.[0]?.url!,
description: firstPost.message,
published: true,
}),
- }
+ },
+ 'upload mp4'
)
).json();
- finalUrl = permalink_url;
+ finalUrl = 'https://www.facebook.com/reel/' + videoId;
finalId = videoId;
} else {
const uploadPhotos = !firstPost?.media?.length
@@ -210,7 +212,8 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
url: media.url,
published: false,
}),
- }
+ },
+ 'upload images slides'
)
).json();
@@ -235,7 +238,8 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
message: firstPost.message,
published: true,
}),
- }
+ },
+ 'finalize upload'
)
).json();
@@ -259,7 +263,8 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
: {}),
message: comment.message,
}),
- }
+ },
+ 'add comment'
)
).json();
diff --git a/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts b/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts
index 8ae19c73..c9cce36f 100644
--- a/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts
@@ -9,7 +9,6 @@ import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
import { timer } from '@gitroom/helpers/utils/timer';
import dayjs from 'dayjs';
import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
-import { chunk } from 'lodash';
export class InstagramProvider
extends SocialAbstract
@@ -207,7 +206,7 @@ export class InstagramProvider
const medias = await Promise.all(
firstPost?.media?.map(async (m) => {
const caption =
- firstPost.media?.length === 1 ? `&caption=${firstPost.message}` : ``;
+ firstPost.media?.length === 1 ? `&caption=${encodeURIComponent(firstPost.message)}` : ``;
const isCarousel =
(firstPost?.media?.length || 0) > 1 ? `&is_carousel_item=true` : ``;
const mediaType =
@@ -216,9 +215,10 @@ export class InstagramProvider
? `video_url=${m.url}&media_type=REELS`
: `video_url=${m.url}&media_type=VIDEO`
: `image_url=${m.url}`;
+
const { id: photoId } = await (
await this.fetch(
- `https://graph.facebook.com/v20.0/${id}/media?${mediaType}${caption}${isCarousel}&access_token=${accessToken}`,
+ `https://graph.facebook.com/v20.0/${id}/media?${mediaType}${isCarousel}&access_token=${accessToken}${caption}`,
{
method: 'POST',
}
diff --git a/libraries/nestjs-libraries/src/integrations/social/linkedin.page.provider.ts b/libraries/nestjs-libraries/src/integrations/social/linkedin.page.provider.ts
index 452b9123..831dfc38 100644
--- a/libraries/nestjs-libraries/src/integrations/social/linkedin.page.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/linkedin.page.provider.ts
@@ -8,6 +8,7 @@ import {
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
import { LinkedinProvider } from '@gitroom/nestjs-libraries/integrations/social/linkedin.provider';
import dayjs from 'dayjs';
+import { Integration } from '@prisma/client';
export class LinkedinPageProvider
extends LinkedinProvider
@@ -206,9 +207,10 @@ export class LinkedinPageProvider
override async post(
id: string,
accessToken: string,
- postDetails: PostDetails[]
+ postDetails: PostDetails[],
+ integration: Integration
): Promise {
- return super.post(id, accessToken, postDetails, 'company');
+ return super.post(id, accessToken, postDetails, integration, 'company');
}
async analytics(
diff --git a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
index 6bacf92c..ef80d46a 100644
--- a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts
@@ -9,7 +9,11 @@ import sharp from 'sharp';
import { lookup } from 'mime-types';
import { readOrFetch } from '@gitroom/helpers/utils/read.or.fetch';
import { removeMarkdown } from '@gitroom/helpers/utils/remove.markdown';
-import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
+import {
+ BadBody,
+ SocialAbstract,
+} from '@gitroom/nestjs-libraries/integrations/social.abstract';
+import { Integration } from '@prisma/client';
export class LinkedinProvider extends SocialAbstract implements SocialProvider {
identifier = 'linkedin';
@@ -19,7 +23,11 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
refreshWait = true;
async refreshToken(refresh_token: string): Promise {
- const { access_token: accessToken, refresh_token: refreshToken, expires_in } = await (
+ const {
+ access_token: accessToken,
+ refresh_token: refreshToken,
+ expires_in,
+ } = await (
await this.fetch('https://www.linkedin.com/oauth/v2/accessToken', {
method: 'POST',
headers: {
@@ -224,21 +232,25 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
const sendUrlRequest = uploadInstructions?.[0]?.uploadUrl || uploadUrl;
const finalOutput = video || image;
- const upload = await this.fetch(sendUrlRequest, {
- method: 'PUT',
- headers: {
- 'X-Restli-Protocol-Version': '2.0.0',
- 'LinkedIn-Version': '202402',
- Authorization: `Bearer ${accessToken}`,
- ...(fileName.indexOf('mp4') > -1
- ? { 'Content-Type': 'application/octet-stream' }
- : {}),
- },
- body: picture,
- });
+ const etags = [];
+ for (let i = 0; i < picture.length; i += 1024 * 1024 * 2) {
+ const upload = await this.fetch(sendUrlRequest, {
+ method: 'PUT',
+ headers: {
+ 'X-Restli-Protocol-Version': '2.0.0',
+ 'LinkedIn-Version': '202402',
+ Authorization: `Bearer ${accessToken}`,
+ ...(fileName.indexOf('mp4') > -1
+ ? { 'Content-Type': 'application/octet-stream' }
+ : {}),
+ },
+ body: picture.slice(i, i + 1024 * 1024 * 2),
+ });
+
+ etags.push(upload.headers.get('etag'));
+ }
if (fileName.indexOf('mp4') > -1) {
- const etag = upload.headers.get('etag');
const a = await this.fetch(
'https://api.linkedin.com/rest/videos?action=finalizeUpload',
{
@@ -247,7 +259,7 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
finalizeUploadRequest: {
video,
uploadToken: '',
- uploadedPartIds: [etag],
+ uploadedPartIds: etags,
},
}),
headers: {
@@ -262,7 +274,13 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
return finalOutput;
} catch (err: any) {
- throw 'eerr';
+ throw new BadBody('error-posting-to-linkedin', JSON.stringify(err), {
+ // @ts-ignore
+ fileName,
+ personId,
+ picture,
+ type,
+ });
}
}
@@ -270,6 +288,7 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
id: string,
accessToken: string,
postDetails: PostDetails[],
+ integration: Integration,
type = 'personal' as 'company' | 'personal'
): Promise {
const [firstPost, ...restPosts] = postDetails;
diff --git a/libraries/nestjs-libraries/src/integrations/social/mastodon.custom.provider.ts b/libraries/nestjs-libraries/src/integrations/social/mastodon.custom.provider.ts
new file mode 100644
index 00000000..1e48f2da
--- /dev/null
+++ b/libraries/nestjs-libraries/src/integrations/social/mastodon.custom.provider.ts
@@ -0,0 +1,81 @@
+import {
+ ClientInformation,
+ PostDetails,
+ PostResponse,
+} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
+import { MastodonProvider } from '@gitroom/nestjs-libraries/integrations/social/mastodon.provider';
+import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
+
+export class MastodonCustomProvider extends MastodonProvider {
+ override identifier = 'mastodon-custom';
+ override name = 'M. Instance';
+ async externalUrl(url: string) {
+ const form = new FormData();
+ form.append('client_name', 'Postiz');
+ form.append(
+ 'redirect_uris',
+ `${process.env.FRONTEND_URL}/integrations/social/mastodon`
+ );
+ form.append('scopes', this.scopes.join(' '));
+ form.append('website', process.env.FRONTEND_URL!);
+ const { client_id, client_secret, ...all } = await (
+ await fetch(url + '/api/v1/apps', {
+ method: 'POST',
+ body: form,
+ })
+ ).json();
+
+ return {
+ client_id,
+ client_secret,
+ };
+ }
+ override async generateAuthUrl(
+ refresh?: string,
+ external?: ClientInformation
+ ) {
+ const state = makeId(6);
+ const url = this.generateUrlDynamic(
+ external?.instanceUrl!,
+ state,
+ external?.client_id!,
+ process.env.FRONTEND_URL!,
+ refresh
+ );
+
+ return {
+ url,
+ codeVerifier: makeId(10),
+ state,
+ };
+ }
+
+ override async authenticate(
+ params: {
+ code: string;
+ codeVerifier: string;
+ refresh?: string;
+ },
+ clientInformation?: ClientInformation
+ ) {
+ return this.dynamicAuthenticate(
+ clientInformation?.client_id!,
+ clientInformation?.client_secret!,
+ clientInformation?.instanceUrl!,
+ params.code
+ );
+ }
+
+ override async post(
+ id: string,
+ accessToken: string,
+ postDetails: PostDetails[]
+ ): Promise {
+ return this.dynamicPost(
+ id,
+ accessToken,
+ 'https://mastodon.social',
+ postDetails
+ );
+ }
+}
diff --git a/libraries/nestjs-libraries/src/integrations/social/mastodon.provider.ts b/libraries/nestjs-libraries/src/integrations/social/mastodon.provider.ts
new file mode 100644
index 00000000..1587dcec
--- /dev/null
+++ b/libraries/nestjs-libraries/src/integrations/social/mastodon.provider.ts
@@ -0,0 +1,192 @@
+import {
+ AuthTokenDetails,
+ PostDetails,
+ PostResponse,
+ SocialProvider,
+} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
+import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
+import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
+import dayjs from 'dayjs';
+
+export class MastodonProvider extends SocialAbstract implements SocialProvider {
+ identifier = 'mastodon';
+ name = 'Mastodon';
+ isBetweenSteps = false;
+ scopes = ['write:statuses', 'profile', 'write:media'];
+
+ async refreshToken(refreshToken: string): Promise {
+ return {
+ refreshToken: '',
+ expiresIn: 0,
+ accessToken: '',
+ id: '',
+ name: '',
+ picture: '',
+ username: '',
+ };
+ }
+ protected generateUrlDynamic(
+ customUrl: string,
+ state: string,
+ clientId: string,
+ url: string,
+ refresh?: string
+ ) {
+ return `${customUrl}/oauth/authorize?client_id=${clientId}&response_type=code&redirect_uri=${encodeURIComponent(
+ `${url}/integrations/social/mastodon${
+ refresh ? `?refresh=${refresh}` : ''
+ }`
+ )}&scope=${this.scopes.join('+')}&state=${state}`;
+ }
+
+ async generateAuthUrl(refresh?: string) {
+ const state = makeId(6);
+ const url = this.generateUrlDynamic(
+ 'https://mastodon.social',
+ state,
+ process.env.MASTODON_CLIENT_ID!,
+ process.env.FRONTEND_URL!,
+ refresh
+ );
+ return {
+ url,
+ codeVerifier: makeId(10),
+ state,
+ };
+ }
+
+ protected async dynamicAuthenticate(
+ clientId: string,
+ clientSecret: string,
+ url: string,
+ code: string
+ ) {
+ const form = new FormData();
+ form.append('client_id', clientId);
+ form.append('client_secret', clientSecret);
+ form.append('code', code);
+ form.append('grant_type', 'authorization_code');
+ form.append(
+ 'redirect_uri',
+ `${process.env.FRONTEND_URL}/integrations/social/mastodon`
+ );
+ form.append('scope', this.scopes.join(' '));
+
+ const tokenInformation = await (
+ await this.fetch(`${url}/oauth/token`, {
+ method: 'POST',
+ body: form,
+ })
+ ).json();
+
+ const personalInformation = await (
+ await this.fetch(`${url}/api/v1/accounts/verify_credentials`, {
+ headers: {
+ Authorization: `Bearer ${tokenInformation.access_token}`,
+ },
+ })
+ ).json();
+
+ return {
+ id: personalInformation.id,
+ name: personalInformation.display_name || personalInformation.acct,
+ accessToken: tokenInformation.access_token,
+ refreshToken: 'null',
+ expiresIn: dayjs().add(100, 'years').unix() - dayjs().unix(),
+ picture: personalInformation.avatar,
+ username: personalInformation.username,
+ };
+ }
+
+ async authenticate(
+ params: {
+ code: string;
+ codeVerifier: string;
+ refresh?: string;
+ }
+ ) {
+ return this.dynamicAuthenticate(
+ process.env.MASTODON_CLIENT_ID!,
+ process.env.MASTODON_CLIENT_SECRET!,
+ 'https://mastodon.social',
+ params.code
+ );
+ }
+
+ async uploadFile(instanceUrl: string, fileUrl: string, accessToken: string) {
+ const form = new FormData();
+ form.append('file', await fetch(fileUrl).then((r) => r.blob()));
+ const media = await (
+ await this.fetch(`${instanceUrl}/api/v1/media`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ },
+ body: form,
+ })
+ ).json();
+ return media.id;
+ }
+
+ async dynamicPost(
+ id: string,
+ accessToken: string,
+ url: string,
+ postDetails: PostDetails[]
+ ): Promise {
+ let loadId = '';
+ const ids = [] as string[];
+ for (const getPost of postDetails) {
+ const uploadFiles = await Promise.all(
+ getPost?.media?.map((media) =>
+ this.uploadFile(url, media.url, accessToken)
+ ) || []
+ );
+
+ const form = new FormData();
+ form.append('status', getPost.message);
+ form.append('visibility', 'public');
+ if (loadId) {
+ form.append('in_reply_to_id', loadId);
+ }
+ if (uploadFiles.length) {
+ for (const file of uploadFiles) {
+ form.append('media_ids[]', file);
+ }
+ }
+
+ const post = await (
+ await this.fetch(`${url}/api/v1/statuses`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ },
+ body: form,
+ })
+ ).json();
+
+ ids.push(post.id);
+ loadId = loadId || post.id;
+ }
+
+ return postDetails.map((p, i) => ({
+ id: p.id,
+ postId: ids[i],
+ releaseURL: `${url}/statuses/${ids[i]}`,
+ status: 'completed',
+ }));
+ }
+
+ async post(
+ id: string,
+ accessToken: string,
+ postDetails: PostDetails[]
+ ): Promise {
+ return this.dynamicPost(
+ id,
+ accessToken,
+ 'https://mastodon.social',
+ postDetails
+ );
+ }
+}
diff --git a/libraries/nestjs-libraries/src/integrations/social/slack.provider.ts b/libraries/nestjs-libraries/src/integrations/social/slack.provider.ts
new file mode 100644
index 00000000..675bee99
--- /dev/null
+++ b/libraries/nestjs-libraries/src/integrations/social/slack.provider.ts
@@ -0,0 +1,190 @@
+import {
+ AuthTokenDetails,
+ PostDetails,
+ PostResponse,
+ SocialProvider,
+} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
+import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
+import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
+import dayjs from 'dayjs';
+import { Integration } from '@prisma/client';
+
+export class SlackProvider extends SocialAbstract implements SocialProvider {
+ identifier = 'slack';
+ name = 'Slack';
+ isBetweenSteps = false;
+ scopes = [
+ 'channels:read',
+ 'chat:write',
+ 'users:read',
+ 'groups:read',
+ 'channels:join',
+ 'chat:write.customize',
+ ];
+ async refreshToken(refreshToken: string): Promise {
+ return {
+ refreshToken: '',
+ expiresIn: 1000000,
+ accessToken: '',
+ id: '',
+ name: '',
+ picture: '',
+ username: '',
+ };
+ }
+ async generateAuthUrl(refresh?: string) {
+ const state = makeId(6);
+
+ return {
+ url: `https://slack.com/oauth/v2/authorize?client_id=${
+ process.env.SLACK_ID
+ }&redirect_uri=${encodeURIComponent(
+ `${
+ process?.env?.FRONTEND_URL?.indexOf('https') === -1
+ ? 'https://redirectmeto.com/'
+ : ''
+ }${process?.env?.FRONTEND_URL}/integrations/social/slack${
+ refresh ? `?refresh=${refresh}` : ''
+ }`
+ )}&scope=channels:read,chat:write,users:read,groups:read,channels:join,chat:write.customize&state=${state}`,
+ codeVerifier: makeId(10),
+ state,
+ };
+ }
+
+ async authenticate(params: {
+ code: string;
+ codeVerifier: string;
+ refresh?: string;
+ }) {
+ const { access_token, team, bot_user_id, scope } = await (
+ await this.fetch(`https://slack.com/api/oauth.v2.access`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ body: new URLSearchParams({
+ client_id: process.env.SLACK_ID!,
+ client_secret: process.env.SLACK_SECRET!,
+ code: params.code,
+ redirect_uri: `${
+ process?.env?.FRONTEND_URL?.indexOf('https') === -1
+ ? 'https://redirectmeto.com/'
+ : ''
+ }${process?.env?.FRONTEND_URL}/integrations/social/slack${
+ params.refresh ? `?refresh=${params.refresh}` : ''
+ }`,
+ }),
+ })
+ ).json();
+
+ this.checkScopes(this.scopes, scope.split(','));
+
+ const { user } = await (
+ await fetch(`https://slack.com/api/users.info?user=${bot_user_id}`, {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ },
+ })
+ ).json();
+
+ return {
+ id: team.id,
+ name: user.real_name,
+ accessToken: access_token,
+ refreshToken: 'null',
+ expiresIn: dayjs().add(100, 'years').unix() - dayjs().unix(),
+ picture: user.profile.image_original,
+ username: user.name,
+ };
+ }
+
+ async channels(accessToken: string, params: any, id: string) {
+ const list = await (
+ await fetch(
+ `https://slack.com/api/conversations.list?types=public_channel,private_channel`,
+ {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ },
+ }
+ )
+ ).json();
+
+ return list.channels.map((p: any) => ({
+ id: p.id,
+ name: p.name,
+ }));
+ }
+
+ async post(
+ id: string,
+ accessToken: string,
+ postDetails: PostDetails[],
+ integration: Integration
+ ): Promise {
+ await fetch(`https://slack.com/api/conversations.join`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ channel: postDetails[0].settings.channel,
+ }),
+ });
+
+ let lastId = '';
+ for (const post of postDetails) {
+ const { ts } = await (
+ await fetch(`https://slack.com/api/chat.postMessage`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ channel: postDetails[0].settings.channel,
+ username: integration.name,
+ icon_url: integration.picture,
+ ...(lastId ? { thread_ts: lastId } : {}),
+ blocks: [
+ {
+ type: 'section',
+ text: {
+ type: 'mrkdwn',
+ text: post.message,
+ },
+ },
+ ...(post.media?.length
+ ? post.media.map((m) => ({
+ type: 'image',
+ image_url: m.url,
+ alt_text: '',
+ }))
+ : []),
+ ],
+ }),
+ })
+ ).json();
+
+ lastId = ts;
+ }
+
+ return [];
+ }
+
+ async changeProfilePicture(id: string, accessToken: string, url: string) {
+ return {
+ url,
+ };
+ }
+
+ async changeNickname(id: string, accessToken: string, name: string) {
+ return {
+ name,
+ };
+ }
+}
diff --git a/libraries/nestjs-libraries/src/integrations/social/social.integrations.interface.ts b/libraries/nestjs-libraries/src/integrations/social/social.integrations.interface.ts
index 35a9c299..0b4fa59e 100644
--- a/libraries/nestjs-libraries/src/integrations/social/social.integrations.interface.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/social.integrations.interface.ts
@@ -1,12 +1,39 @@
+import { Integration } from '@prisma/client';
+
+export interface ClientInformation {
+ client_id: string;
+ client_secret: string;
+ instanceUrl: string;
+}
export interface IAuthenticator {
- authenticate(params: {
- code: string;
- codeVerifier: string;
- refresh?: string;
- }): Promise;
+ authenticate(
+ params: {
+ code: string;
+ codeVerifier: string;
+ refresh?: string;
+ },
+ clientInformation?: ClientInformation
+ ): Promise;
refreshToken(refreshToken: string): Promise;
- generateAuthUrl(refresh?: string): Promise;
- analytics?(id: string, accessToken: string, date: number): Promise;
+ generateAuthUrl(
+ refresh?: string,
+ clientInformation?: ClientInformation
+ ): Promise;
+ analytics?(
+ id: string,
+ accessToken: string,
+ date: number
+ ): Promise;
+ changeNickname?(
+ id: string,
+ accessToken: string,
+ name: string
+ ): Promise<{ name: string }>;
+ changeProfilePicture?(
+ id: string,
+ accessToken: string,
+ url: string
+ ): Promise<{ url: string }>;
}
export interface AnalyticsData {
@@ -35,7 +62,8 @@ export interface ISocialMediaIntegration {
post(
id: string,
accessToken: string,
- postDetails: PostDetails[]
+ postDetails: PostDetails[],
+ integration: Integration
): Promise; // Schedules a new post
}
@@ -70,7 +98,19 @@ export interface SocialProvider
ISocialMediaIntegration {
identifier: string;
refreshWait?: boolean;
+ customFields?: () => Promise<
+ {
+ key: string;
+ label: string;
+ defaultValue?: string;
+ validation: string;
+ type: 'text' | 'password';
+ }[]
+ >;
name: string;
isBetweenSteps: boolean;
scopes: string[];
+ externalUrl?: (
+ url: string
+ ) => Promise<{ client_id: string; client_secret: string }>;
}
diff --git a/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts b/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts
index 2a701987..756c43b6 100644
--- a/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts
@@ -41,11 +41,11 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
'https://threads.net/oauth/authorize' +
`?client_id=${process.env.THREADS_APP_ID}` +
`&redirect_uri=${encodeURIComponent(
- process.env.NODE_ENV === 'development' || !process.env.NODE_ENV
- ? `https://integration.git.sn/integrations/social/threads`
- : `${process.env.FRONTEND_URL}/integrations/social/threads${
- refresh ? `?refresh=${refresh}` : ''
- }`
+ `${
+ process?.env.FRONTEND_URL?.indexOf('https') == -1
+ ? `https://redirectmeto.com/${process?.env.FRONTEND_URL}`
+ : `${process?.env.FRONTEND_URL}`
+ }/integrations/social/threads`
)}` +
`&state=${state}` +
`&scope=${encodeURIComponent(this.scopes.join(','))}`,
@@ -64,11 +64,11 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
'https://graph.threads.net/oauth/access_token' +
`?client_id=${process.env.THREADS_APP_ID}` +
`&redirect_uri=${encodeURIComponent(
- process.env.NODE_ENV === 'development' || !process.env.NODE_ENV
- ? `https://integration.git.sn/integrations/social/threads`
- : `${process.env.FRONTEND_URL}/integrations/social/threads${
- params.refresh ? `?refresh=${params.refresh}` : ''
- }`
+ `${
+ process?.env.FRONTEND_URL?.indexOf('https') == -1
+ ? `https://redirectmeto.com/${process?.env.FRONTEND_URL}`
+ : `${process?.env.FRONTEND_URL}`
+ }/integrations/social/threads`
)}` +
`&grant_type=authorization_code` +
`&client_secret=${process.env.THREADS_APP_SECRET}` +
@@ -104,8 +104,15 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
};
}
- private async checkLoaded(mediaContainerId: string, accessToken: string): Promise {
- const {status, id, error_message} = await (await this.fetch(`https://graph.threads.net/v1.0/${mediaContainerId}?fields=status,error_message&access_token=${accessToken}`)).json();
+ private async checkLoaded(
+ mediaContainerId: string,
+ accessToken: string
+ ): Promise {
+ const { status, id, error_message } = await (
+ await this.fetch(
+ `https://graph.threads.net/v1.0/${mediaContainerId}?fields=status,error_message&access_token=${accessToken}`
+ )
+ ).json();
console.log(status, error_message);
if (status === 'ERROR') {
throw new Error(id);
@@ -205,12 +212,8 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
mediaLoad.path.indexOf('.mp4') > -1 ? 'video_url' : 'image_url';
const media = new URLSearchParams({
- ...(type === 'video_url'
- ? { video_url: mediaLoad.path }
- : {}),
- ...(type === 'image_url'
- ? { image_url: mediaLoad.path }
- : {}),
+ ...(type === 'video_url' ? { video_url: mediaLoad.path } : {}),
+ ...(type === 'image_url' ? { image_url: mediaLoad.path } : {}),
is_carousel_item: 'true',
media_type:
type === 'video_url'
@@ -234,7 +237,9 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
medias.push(mediaId);
}
- await Promise.all(medias.map((p: string) => this.checkLoaded(p, accessToken)));
+ await Promise.all(
+ medias.map((p: string) => this.checkLoaded(p, accessToken))
+ );
const { id: containerId } = await (
await this.fetch(
diff --git a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts
index 15d3b766..6bc13da5 100644
--- a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts
@@ -5,7 +5,10 @@ import {
SocialProvider,
} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
import dayjs from 'dayjs';
-import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
+import {
+ BadBody,
+ SocialAbstract,
+} from '@gitroom/nestjs-libraries/integrations/social.abstract';
import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto';
export class TiktokProvider extends SocialAbstract implements SocialProvider {
@@ -183,7 +186,10 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
},
];
} catch (err) {
- return [];
+ throw new BadBody('titok-error', JSON.stringify(err), {
+ // @ts-ignore
+ postDetails
+ });
}
}
}
diff --git a/libraries/nestjs-libraries/src/services/email.service.ts b/libraries/nestjs-libraries/src/services/email.service.ts
index 037a72fd..41f588c4 100644
--- a/libraries/nestjs-libraries/src/services/email.service.ts
+++ b/libraries/nestjs-libraries/src/services/email.service.ts
@@ -1,29 +1,52 @@
import { Injectable } from '@nestjs/common';
-import { Resend } from 'resend';
-
-const resend = new Resend(process.env.RESEND_API_KEY || 're_132');
+import { EmailInterface } from '@gitroom/nestjs-libraries/emails/email.interface';
+import { ResendProvider } from '@gitroom/nestjs-libraries/emails/resend.provider';
+import { EmptyProvider } from '@gitroom/nestjs-libraries/emails/empty.provider';
+import { NodeMailerProvider } from '@gitroom/nestjs-libraries/emails/node.mailer.provider';
@Injectable()
export class EmailService {
+ emailService: EmailInterface;
+ constructor() {
+ this.emailService = this.selectProvider(process.env.EMAIL_PROVIDER!);
+ console.log('Email service provider:', this.emailService.name);
+ for (const key of this.emailService.validateEnvKeys) {
+ if (!process.env[key]) {
+ console.error(`Missing environment variable: ${key}`);
+ }
+ }
+ }
+
+ hasProvider() {
+ return !(this.emailService instanceof EmptyProvider);
+ }
+
+ selectProvider(provider: string) {
+ switch (provider) {
+ case 'resend':
+ return new ResendProvider();
+ case 'nodemailer':
+ return new NodeMailerProvider();
+ default:
+ return new EmptyProvider();
+ }
+ }
+
async sendEmail(to: string, subject: string, html: string) {
- if (!process.env.RESEND_API_KEY) {
- console.log('No Resend API Key found, skipping email sending');
- return;
- }
-
if (!process.env.EMAIL_FROM_ADDRESS || !process.env.EMAIL_FROM_NAME) {
- console.log('Email sender information not found in environment variables');
+ console.log(
+ 'Email sender information not found in environment variables'
+ );
return;
}
- console.log('Sending email to', to);
- const sends = await resend.emails.send({
- from: `${process.env.EMAIL_FROM_NAME} <${process.env.EMAIL_FROM_ADDRESS}>`,
+ const sends = await this.emailService.sendEmail(
to,
subject,
html,
- });
-
+ process.env.EMAIL_FROM_NAME,
+ process.env.EMAIL_FROM_ADDRESS
+ );
console.log(sends);
}
}
diff --git a/libraries/react-shared-libraries/src/form/checkbox.tsx b/libraries/react-shared-libraries/src/form/checkbox.tsx
index a16521b7..8090d000 100644
--- a/libraries/react-shared-libraries/src/form/checkbox.tsx
+++ b/libraries/react-shared-libraries/src/form/checkbox.tsx
@@ -42,8 +42,22 @@ export const Checkbox = forwardRef
{currentStatus && (
-
- )}
+
+ )}
);
});
diff --git a/libraries/react-shared-libraries/src/helpers/image.with.fallback.tsx b/libraries/react-shared-libraries/src/helpers/image.with.fallback.tsx
index 430d9b9a..c4ddc1fb 100644
--- a/libraries/react-shared-libraries/src/helpers/image.with.fallback.tsx
+++ b/libraries/react-shared-libraries/src/helpers/image.with.fallback.tsx
@@ -1,4 +1,4 @@
-import { FC, useState } from 'react';
+import { FC, useEffect, useState } from 'react';
import Image from 'next/image';
interface ImageSrc {
@@ -12,6 +12,11 @@ interface ImageSrc {
const ImageWithFallback: FC = (props) => {
const { src, fallbackSrc, ...rest } = props;
const [imgSrc, setImgSrc] = useState(src);
+ useEffect(() => {
+ if (src !== imgSrc) {
+ setImgSrc(src);
+ }
+ }, [src]);
return (
{
)}
-
{toasterText}
+
{toasterText}
=10"
+ "node_modules/@atproto/common-web": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.3.1.tgz",
+ "integrity": "sha512-N7wiTnus5vAr+lT//0y8m/FaHHLJ9LpGuEwkwDAeV3LCiPif4m/FS8x/QOYrx1PdZQwKso95RAPzCGWQBH5j6Q==",
+ "dependencies": {
+ "graphemer": "^1.4.0",
+ "multiformats": "^9.9.0",
+ "uint8arrays": "3.0.0",
+ "zod": "^3.23.8"
}
},
- "node_modules/@apidevtools/swagger-methods": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
- "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
- "dev": true
- },
- "node_modules/@apidevtools/swagger-parser": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz",
- "integrity": "sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw==",
- "dev": true,
+ "node_modules/@atproto/lexicon": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.2.tgz",
+ "integrity": "sha512-CXoOkhcdF3XVUnR2oNgCs2ljWfo/8zUjxL5RIhJW/UNLp/FSl+KpF8Jm5fbk8Y/XXVPGRAsv9OYfxyU/14N/pw==",
"dependencies": {
- "@apidevtools/json-schema-ref-parser": "9.0.6",
- "@apidevtools/openapi-schemas": "^2.1.0",
- "@apidevtools/swagger-methods": "^3.0.2",
- "@jsdevtools/ono": "^7.1.3",
- "ajv": "^8.6.3",
- "ajv-draft-04": "^1.0.0",
- "call-me-maybe": "^1.0.1"
- },
- "peerDependencies": {
- "openapi-types": ">=7"
+ "@atproto/common-web": "^0.3.1",
+ "@atproto/syntax": "^0.3.0",
+ "iso-datestring-validator": "^2.2.2",
+ "multiformats": "^9.9.0",
+ "zod": "^3.23.8"
+ }
+ },
+ "node_modules/@atproto/syntax": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.3.0.tgz",
+ "integrity": "sha512-Weq0ZBxffGHDXHl9U7BQc2BFJi/e23AL+k+i5+D9hUq/bzT4yjGsrCejkjq0xt82xXDjmhhvQSZ0LqxyZ5woxA=="
+ },
+ "node_modules/@atproto/xrpc": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.6.3.tgz",
+ "integrity": "sha512-S3tRvOdA9amPkKLll3rc4vphlDitLrkN5TwWh5Tu/jzk7mnobVVE3akYgICV9XCNHKjWM+IAPxFFI2qi+VW6nQ==",
+ "dependencies": {
+ "@atproto/lexicon": "^0.4.2",
+ "zod": "^3.23.8"
}
},
"node_modules/@aws-crypto/crc32": {
@@ -6862,12 +6873,6 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@jsdevtools/ono": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
- "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
- "dev": true
- },
"node_modules/@jsonjoy.com/base64": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz",
@@ -7302,95 +7307,6 @@
"node": ">=10"
}
},
- "node_modules/@mdx-js/mdx": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz",
- "integrity": "sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "@types/mdx": "^2.0.0",
- "estree-util-build-jsx": "^2.0.0",
- "estree-util-is-identifier-name": "^2.0.0",
- "estree-util-to-js": "^1.1.0",
- "estree-walker": "^3.0.0",
- "hast-util-to-estree": "^2.0.0",
- "markdown-extensions": "^1.0.0",
- "periscopic": "^3.0.0",
- "remark-mdx": "^2.0.0",
- "remark-parse": "^10.0.0",
- "remark-rehype": "^10.0.0",
- "unified": "^10.0.0",
- "unist-util-position-from-estree": "^1.0.0",
- "unist-util-stringify-position": "^3.0.0",
- "unist-util-visit": "^4.0.0",
- "vfile": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/@mdx-js/mdx/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/@mdx-js/mdx/node_modules/estree-util-to-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz",
- "integrity": "sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "astring": "^1.8.0",
- "source-map": "^0.7.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/@mdx-js/mdx/node_modules/source-map": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
- "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@mdx-js/mdx/node_modules/unist-util-position-from-estree": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz",
- "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/@mdx-js/react": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz",
- "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==",
- "dev": true,
- "dependencies": {
- "@types/mdx": "^2.0.0",
- "@types/react": ">=16"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- },
- "peerDependencies": {
- "react": ">=16"
- }
- },
"node_modules/@meronex/icons": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@meronex/icons/-/icons-4.0.0.tgz",
@@ -7416,119 +7332,6 @@
"resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz",
"integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA=="
},
- "node_modules/@mintlify/common": {
- "version": "1.0.141",
- "resolved": "https://registry.npmjs.org/@mintlify/common/-/common-1.0.141.tgz",
- "integrity": "sha512-W55hktZ8jrf5z7bI1r6O84GtXMhwBicHOQWUrozXDXoQz4eDu1HPCjOp0/IktasEDpAlmde1lYErq88IZXDhHA==",
- "dev": true,
- "dependencies": {
- "@apidevtools/swagger-parser": "^10.1.0",
- "@mintlify/mdx": "0.0.46",
- "@mintlify/models": "0.0.120",
- "@mintlify/validation": "0.1.186",
- "@sindresorhus/slugify": "^2.1.1",
- "acorn": "^8.11.2",
- "acorn-jsx": "^5.3.2",
- "esast-util-from-js": "^2.0.0",
- "estree-util-to-js": "^2.0.0",
- "estree-walker": "^3.0.3",
- "gray-matter": "^4.0.3",
- "hast-util-from-html": "^1.0.0",
- "hast-util-from-html-isomorphic": "^2.0.0",
- "hast-util-to-html": "^8.0.3",
- "hast-util-to-text": "^4.0.0",
- "is-absolute-url": "^4.0.1",
- "lodash": "^4.17.21",
- "mdast": "^3.0.0",
- "mdast-util-from-markdown": "^1.2.0",
- "mdast-util-gfm": "^2.0.1",
- "mdast-util-mdx": "^2.0.0",
- "mdast-util-mdx-jsx": "^2.1.2",
- "mdast-util-mdxjs-esm": "^1.3.0",
- "micromark-extension-mdx-jsx": "^1.0.3",
- "micromark-extension-mdxjs": "^1.0.0",
- "micromark-extension-mdxjs-esm": "^1.0.0",
- "openapi-types": "^12.0.0",
- "remark": "^14.0.2",
- "remark-frontmatter": "^4.0.1",
- "remark-gfm": "^3.0.1",
- "remark-math": "^5.1.1",
- "remark-mdx": "^2.0.0",
- "unist-builder": "^3.0.1",
- "unist-util-map": "^3.1.2",
- "unist-util-remove": "^3.1.0",
- "unist-util-remove-position": "^4.0.0",
- "unist-util-visit": "^4.1.1",
- "unist-util-visit-parents": "^5.0.0",
- "vfile": "^5.3.6"
- }
- },
- "node_modules/@mintlify/mdx": {
- "version": "0.0.46",
- "resolved": "https://registry.npmjs.org/@mintlify/mdx/-/mdx-0.0.46.tgz",
- "integrity": "sha512-8BZsTvFhek4Z6//+kWKvlgnKy+dOjbtHqPnhiYaNlvZvGFU5BkLjOtFFP2jG+7vluvfI2yWOS8g3mtPwntWrVg==",
- "dev": true,
- "dependencies": {
- "hast-util-to-string": "^2.0.0",
- "next-mdx-remote": "^4.4.1",
- "refractor": "^4.8.0",
- "rehype-katex": "^6.0.3",
- "remark-gfm": "^3.0.1",
- "remark-math": "^5.1.1",
- "remark-smartypants": "^2.0.0",
- "unist-util-visit": "^4.1.1"
- }
- },
- "node_modules/@mintlify/models": {
- "version": "0.0.120",
- "resolved": "https://registry.npmjs.org/@mintlify/models/-/models-0.0.120.tgz",
- "integrity": "sha512-H6bb2StjBiLAySPoPJbx2k3o6W/WOoGPkJudyzHSUzGPt8HN5hXUR6gnyRjVt0Ba7LKy8HxiG24G4s6wVwDgsA==",
- "dev": true,
- "dependencies": {
- "axios": "^1.4.0",
- "openapi-types": "12.x"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@mintlify/scraping": {
- "version": "3.0.164",
- "resolved": "https://registry.npmjs.org/@mintlify/scraping/-/scraping-3.0.164.tgz",
- "integrity": "sha512-MjtXFr8kRjbJiPB9n2KCds3EdJ5XlrmsZq7TeeT5JCp0xpe4LnY12csWyNuNNVb017hqOpcxYPCAvsxqTWMB2g==",
- "dev": true,
- "dependencies": {
- "@apidevtools/swagger-parser": "^10.1.0",
- "@mintlify/common": "1.0.141",
- "axios": "^1.2.2",
- "cheerio": "^1.0.0-rc.12",
- "fs-extra": "^11.1.1",
- "node-html-markdown": "^1.3.0",
- "ora": "^6.1.2",
- "puppeteer": "^22.14.0",
- "yargs": "^17.6.0"
- },
- "bin": {
- "mintlify-scrape": "bin/cli.js"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@mintlify/validation": {
- "version": "0.1.186",
- "resolved": "https://registry.npmjs.org/@mintlify/validation/-/validation-0.1.186.tgz",
- "integrity": "sha512-gOrp9N2N5rg+P7gD6OSpr4hjYe26LKli/4Dk1SetLAd9oDSHbB/z0vQ6IkiXxMew+kHlRk3fwlnesLLf/A/3yg==",
- "dev": true,
- "dependencies": {
- "@mintlify/models": "0.0.120",
- "lcm": "^0.0.3",
- "lodash": "^4.17.21",
- "openapi-types": "12.x",
- "zod": "^3.20.6",
- "zod-to-json-schema": "^3.20.3"
- }
- },
"node_modules/@module-federation/bridge-react-webpack-plugin": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.6.3.tgz",
@@ -10473,40 +10276,6 @@
"@prisma/debug": "5.19.1"
}
},
- "node_modules/@puppeteer/browsers": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz",
- "integrity": "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA==",
- "dev": true,
- "dependencies": {
- "debug": "^4.3.5",
- "extract-zip": "^2.0.1",
- "progress": "^2.0.3",
- "proxy-agent": "^6.4.0",
- "semver": "^7.6.3",
- "tar-fs": "^3.0.6",
- "unbzip2-stream": "^1.4.3",
- "yargs": "^17.7.2"
- },
- "bin": {
- "browsers": "lib/cjs/main-cli.js"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@puppeteer/browsers/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@radix-ui/number": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.0.tgz",
@@ -11425,61 +11194,6 @@
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
- "node_modules/@sindresorhus/slugify": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz",
- "integrity": "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==",
- "dev": true,
- "dependencies": {
- "@sindresorhus/transliterate": "^1.0.0",
- "escape-string-regexp": "^5.0.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@sindresorhus/slugify/node_modules/escape-string-regexp": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
- "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@sindresorhus/transliterate": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz",
- "integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==",
- "dev": true,
- "dependencies": {
- "escape-string-regexp": "^5.0.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
- "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/@sinonjs/commons": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
@@ -12886,12 +12600,6 @@
"node": ">= 10"
}
},
- "node_modules/@tootallnate/quickjs-emscripten": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
- "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
- "dev": true
- },
"node_modules/@transloadit/prettier-bytes": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.3.4.tgz",
@@ -12933,15 +12641,6 @@
"tslib": "^2.4.0"
}
},
- "node_modules/@types/acorn": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
- "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==",
- "dev": true,
- "dependencies": {
- "@types/estree": "*"
- }
- },
"node_modules/@types/aria-query": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
@@ -13205,12 +12904,6 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@types/js-yaml": {
- "version": "4.0.9",
- "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
- "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
- "dev": true
- },
"node_modules/@types/jsdom": {
"version": "20.0.1",
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz",
@@ -13253,12 +12946,6 @@
"@types/node": "*"
}
},
- "node_modules/@types/katex": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.14.0.tgz",
- "integrity": "sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==",
- "dev": true
- },
"node_modules/@types/keyv": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
@@ -13296,12 +12983,6 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
},
- "node_modules/@types/mdx": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz",
- "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==",
- "dev": true
- },
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
@@ -13325,21 +13006,6 @@
"@types/express": "*"
}
},
- "node_modules/@types/nlcst": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-1.0.4.tgz",
- "integrity": "sha512-ABoYdNQ/kBSsLvZAekMhIPMQ3YUZvavStpKYs7BjLLuKVmIMA0LUgZ7b54zzuWJRbHF80v1cNf4r90Vd6eMQDg==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2"
- }
- },
- "node_modules/@types/nlcst/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
"node_modules/@types/node": {
"version": "18.16.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.9.tgz",
@@ -13362,17 +13028,19 @@
"@types/node": "*"
}
},
+ "node_modules/@types/nodemailer": {
+ "version": "6.4.16",
+ "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.16.tgz",
+ "integrity": "sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/parse-json": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
"integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
},
- "node_modules/@types/parse5": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
- "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==",
- "dev": true
- },
"node_modules/@types/prismjs": {
"version": "1.26.4",
"resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz",
@@ -13570,8 +13238,8 @@
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
- "dev": true,
"optional": true,
+ "peer": true,
"dependencies": {
"@types/node": "*"
}
@@ -15689,20 +15357,6 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/ajv-draft-04": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz",
- "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==",
- "dev": true,
- "peerDependencies": {
- "ajv": "^8.5.0"
- },
- "peerDependenciesMeta": {
- "ajv": {
- "optional": true
- }
- }
- },
"node_modules/ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
@@ -15939,16 +15593,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/array-iterate": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz",
- "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==",
- "dev": true,
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
"node_modules/array-move": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/array-move/-/array-move-4.0.0.tgz",
@@ -16106,33 +15750,12 @@
"node": "*"
}
},
- "node_modules/ast-types": {
- "version": "0.13.4",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
- "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
- "dev": true,
- "dependencies": {
- "tslib": "^2.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/ast-types-flow": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
"dev": true
},
- "node_modules/astring": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz",
- "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==",
- "dev": true,
- "bin": {
- "astring": "bin/astring"
- }
- },
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
@@ -16210,6 +15833,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/await-lock": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz",
+ "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw=="
+ },
"node_modules/axe-core": {
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz",
@@ -16238,12 +15866,6 @@
"node": ">= 0.4"
}
},
- "node_modules/b4a": {
- "version": "1.6.6",
- "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz",
- "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==",
- "dev": true
- },
"node_modules/babel-jest": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
@@ -16520,53 +16142,6 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
- "node_modules/bare-events": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz",
- "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==",
- "dev": true,
- "optional": true
- },
- "node_modules/bare-fs": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.4.tgz",
- "integrity": "sha512-7YyxitZEq0ey5loOF5gdo1fZQFF7290GziT+VbAJ+JbYTJYaPZwuEz2r/Nq23sm4fjyTgUf2uJI2gkT3xAuSYA==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "bare-events": "^2.0.0",
- "bare-path": "^2.0.0",
- "bare-stream": "^2.0.0"
- }
- },
- "node_modules/bare-os": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.2.tgz",
- "integrity": "sha512-HZoJwzC+rZ9lqEemTMiO0luOePoGYNBgsLLgegKR/cljiJvcDNhDZQkzC+NC5Oh0aHbdBNSOHpghwMuB5tqhjg==",
- "dev": true,
- "optional": true
- },
- "node_modules/bare-path": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz",
- "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "bare-os": "^2.1.0"
- }
- },
- "node_modules/bare-stream": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.3.0.tgz",
- "integrity": "sha512-pVRWciewGUeCyKEuRxwv06M079r+fRjAQjBEK2P6OYGrO43O+Z0LrPZZEjlc4mB6C2RpZ9AxJ1s7NLEtOHO6eA==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "b4a": "^1.6.6",
- "streamx": "^2.20.0"
- }
- },
"node_modules/base-64": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
@@ -16607,15 +16182,6 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
- "node_modules/basic-ftp": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
- "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
- "dev": true,
- "engines": {
- "node": ">=10.0.0"
- }
- },
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -16780,17 +16346,6 @@
"resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz",
"integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA=="
},
- "node_modules/bl": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz",
- "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==",
- "dev": true,
- "dependencies": {
- "buffer": "^6.0.3",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
@@ -16954,7 +16509,8 @@
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"engines": {
"node": "*"
}
@@ -17154,12 +16710,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/call-me-maybe": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
- "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
- "dev": true
- },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -17426,7 +16976,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
"integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"cheerio-select": "^2.1.0",
"dom-serializer": "^2.0.0",
@@ -17451,7 +17002,8 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"boolbase": "^1.0.0",
"css-select": "^5.1.0",
@@ -17468,7 +17020,8 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"entities": "^4.4.0"
},
@@ -17526,20 +17079,6 @@
"node": ">=6.0"
}
},
- "node_modules/chromium-bidi": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.3.tgz",
- "integrity": "sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A==",
- "dev": true,
- "dependencies": {
- "mitt": "3.0.1",
- "urlpattern-polyfill": "10.0.0",
- "zod": "3.23.8"
- },
- "peerDependencies": {
- "devtools-protocol": "*"
- }
- },
"node_modules/ci-info": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
@@ -18937,15 +18476,6 @@
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
"dev": true
},
- "node_modules/data-uri-to-buffer": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
- "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
- "dev": true,
- "engines": {
- "node": ">= 14"
- }
- },
"node_modules/data-urls": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz",
@@ -19247,20 +18777,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/degenerator": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
- "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
- "dev": true,
- "dependencies": {
- "ast-types": "^0.13.4",
- "escodegen": "^2.1.0",
- "esprima": "^4.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -19361,12 +18877,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/devtools-protocol": {
- "version": "0.0.1312386",
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz",
- "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==",
- "dev": true
- },
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
@@ -19706,7 +19216,8 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz",
"integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"iconv-lite": "^0.6.3",
"whatwg-encoding": "^3.1.1"
@@ -19719,7 +19230,8 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
@@ -19769,15 +19281,6 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
- "node_modules/env-paths": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
- "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/errno": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
@@ -19968,38 +19471,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/esast-util-from-estree": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz",
- "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "devlop": "^1.0.0",
- "estree-util-visit": "^2.0.0",
- "unist-util-position-from-estree": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/esast-util-from-js": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz",
- "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "acorn": "^8.0.0",
- "esast-util-from-estree": "^2.0.0",
- "vfile-message": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/esbuild": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
@@ -21082,82 +20553,6 @@
"node": ">=4.0"
}
},
- "node_modules/estree-util-attach-comments": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz",
- "integrity": "sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==",
- "dev": true,
- "dependencies": {
- "@types/estree": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/estree-util-build-jsx": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-2.2.2.tgz",
- "integrity": "sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "estree-util-is-identifier-name": "^2.0.0",
- "estree-walker": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/estree-util-is-identifier-name": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz",
- "integrity": "sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==",
- "dev": true,
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/estree-util-to-js": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz",
- "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "astring": "^1.8.0",
- "source-map": "^0.7.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/estree-util-to-js/node_modules/source-map": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
- "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/estree-util-visit": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz",
- "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "@types/unist": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
@@ -21492,23 +20887,12 @@
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
- "node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
- "dev": true,
- "dependencies": {
- "is-extendable": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
@@ -21528,7 +20912,8 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"pump": "^3.0.0"
},
@@ -21559,12 +20944,6 @@
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
},
- "node_modules/fast-fifo": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
- "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
- "dev": true
- },
"node_modules/fast-glob": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
@@ -21703,7 +21082,8 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"pend": "~1.2.0"
}
@@ -22532,12 +21912,6 @@
"uuid": "dist/bin/uuid"
}
},
- "node_modules/gcd": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/gcd/-/gcd-0.0.1.tgz",
- "integrity": "sha512-VNx3UEGr+ILJTiMs1+xc5SX1cMgJCrXezKPa003APUWNqQqaF6n25W8VcR7nHN6yRWbvvUTwCpZCFJeWC2kXlw==",
- "dev": true
- },
"node_modules/gcp-metadata": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz",
@@ -22654,21 +22028,6 @@
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
- "node_modules/get-uri": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz",
- "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==",
- "dev": true,
- "dependencies": {
- "basic-ftp": "^5.0.2",
- "data-uri-to-buffer": "^6.0.2",
- "debug": "^4.3.4",
- "fs-extra": "^11.2.0"
- },
- "engines": {
- "node": ">= 14"
- }
- },
"node_modules/github-slugger": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
@@ -23027,21 +22386,6 @@
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
},
- "node_modules/gray-matter": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
- "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==",
- "dev": true,
- "dependencies": {
- "js-yaml": "^3.13.1",
- "kind-of": "^6.0.2",
- "section-matter": "^1.0.0",
- "strip-bom-string": "^1.0.0"
- },
- "engines": {
- "node": ">=6.0"
- }
- },
"node_modules/groq-sdk": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/groq-sdk/-/groq-sdk-0.5.0.tgz",
@@ -23177,293 +22521,6 @@
"node": ">= 0.4"
}
},
- "node_modules/hast-util-from-dom": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.0.tgz",
- "integrity": "sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^3.0.0",
- "hastscript": "^8.0.0",
- "web-namespaces": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-dom/node_modules/@types/hast": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
- "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
- "dev": true,
- "dependencies": {
- "@types/unist": "*"
- }
- },
- "node_modules/hast-util-from-html": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-1.0.2.tgz",
- "integrity": "sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "hast-util-from-parse5": "^7.0.0",
- "parse5": "^7.0.0",
- "vfile": "^5.0.0",
- "vfile-message": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
- "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^3.0.0",
- "hast-util-from-dom": "^5.0.0",
- "hast-util-from-html": "^2.0.0",
- "unist-util-remove-position": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/@types/hast": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
- "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
- "dev": true,
- "dependencies": {
- "@types/unist": "*"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/hast-util-from-html": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.2.tgz",
- "integrity": "sha512-HwOHwxdt2zC5KQ/CNoybBntRook2zJvfZE/u5/Ap7aLPe22bDqen7KwGkOqOyzL5zIqKwiYX/OTtE0FWgr6XXA==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^3.0.0",
- "devlop": "^1.1.0",
- "hast-util-from-parse5": "^8.0.0",
- "parse5": "^7.0.0",
- "vfile": "^6.0.0",
- "vfile-message": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/hast-util-from-parse5": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz",
- "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^3.0.0",
- "@types/unist": "^3.0.0",
- "devlop": "^1.0.0",
- "hastscript": "^8.0.0",
- "property-information": "^6.0.0",
- "vfile": "^6.0.0",
- "vfile-location": "^5.0.0",
- "web-namespaces": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/parse5": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
- "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "dev": true,
- "dependencies": {
- "entities": "^4.4.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/unist-util-is": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
- "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/unist-util-remove-position": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz",
- "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0",
- "unist-util-visit": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/unist-util-visit": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
- "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0",
- "unist-util-is": "^6.0.0",
- "unist-util-visit-parents": "^6.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/unist-util-visit-parents": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz",
- "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0",
- "unist-util-is": "^6.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/vfile": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
- "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0",
- "vfile-message": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html-isomorphic/node_modules/vfile-location": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz",
- "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0",
- "vfile": "^6.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-html/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/hast-util-from-html/node_modules/parse5": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
- "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "dev": true,
- "dependencies": {
- "entities": "^4.4.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "node_modules/hast-util-from-html/node_modules/vfile-message": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
- "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-stringify-position": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-parse5": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
- "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "@types/unist": "^2.0.0",
- "hastscript": "^7.0.0",
- "property-information": "^6.0.0",
- "vfile": "^5.0.0",
- "vfile-location": "^4.0.0",
- "web-namespaces": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-parse5/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz",
- "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-from-parse5/node_modules/hastscript": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz",
- "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "comma-separated-tokens": "^2.0.0",
- "hast-util-parse-selector": "^3.0.0",
- "property-information": "^6.0.0",
- "space-separated-tokens": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/hast-util-has-property": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz",
@@ -23544,35 +22601,6 @@
"@types/unist": "*"
}
},
- "node_modules/hast-util-raw": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz",
- "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "@types/parse5": "^6.0.0",
- "hast-util-from-parse5": "^7.0.0",
- "hast-util-to-parse5": "^7.0.0",
- "html-void-elements": "^2.0.0",
- "parse5": "^6.0.0",
- "unist-util-position": "^4.0.0",
- "unist-util-visit": "^4.0.0",
- "vfile": "^5.0.0",
- "web-namespaces": "^2.0.0",
- "zwitch": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-raw/node_modules/parse5": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
- "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
- "dev": true
- },
"node_modules/hast-util-select": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.2.tgz",
@@ -23671,68 +22699,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/hast-util-to-estree": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz",
- "integrity": "sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==",
- "dev": true,
- "dependencies": {
- "@types/estree": "^1.0.0",
- "@types/estree-jsx": "^1.0.0",
- "@types/hast": "^2.0.0",
- "@types/unist": "^2.0.0",
- "comma-separated-tokens": "^2.0.0",
- "estree-util-attach-comments": "^2.0.0",
- "estree-util-is-identifier-name": "^2.0.0",
- "hast-util-whitespace": "^2.0.0",
- "mdast-util-mdx-expression": "^1.0.0",
- "mdast-util-mdxjs-esm": "^1.0.0",
- "property-information": "^6.0.0",
- "space-separated-tokens": "^2.0.0",
- "style-to-object": "^0.4.1",
- "unist-util-position": "^4.0.0",
- "zwitch": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-to-estree/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/hast-util-to-html": {
- "version": "8.0.4",
- "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-8.0.4.tgz",
- "integrity": "sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "@types/unist": "^2.0.0",
- "ccount": "^2.0.0",
- "comma-separated-tokens": "^2.0.0",
- "hast-util-raw": "^7.0.0",
- "hast-util-whitespace": "^2.0.0",
- "html-void-elements": "^2.0.0",
- "property-information": "^6.0.0",
- "space-separated-tokens": "^2.0.0",
- "stringify-entities": "^4.0.0",
- "zwitch": "^2.0.4"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-to-html/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
"node_modules/hast-util-to-jsx-runtime": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz",
@@ -24417,62 +23383,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/hast-util-to-parse5": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz",
- "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "comma-separated-tokens": "^2.0.0",
- "property-information": "^6.0.0",
- "space-separated-tokens": "^2.0.0",
- "web-namespaces": "^2.0.0",
- "zwitch": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-to-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-2.0.0.tgz",
- "integrity": "sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-to-text": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz",
- "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^3.0.0",
- "@types/unist": "^3.0.0",
- "hast-util-is-element": "^3.0.0",
- "unist-util-find-after": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/hast-util-to-text/node_modules/@types/hast": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
- "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
- "dev": true,
- "dependencies": {
- "@types/unist": "*"
- }
- },
"node_modules/hast-util-whitespace": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz",
@@ -24714,21 +23624,10 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/html-void-elements": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
- "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==",
- "dev": true,
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
"node_modules/htmlparser2": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz",
"integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==",
- "devOptional": true,
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
@@ -24736,6 +23635,8 @@
"url": "https://github.com/sponsors/fb55"
}
],
+ "optional": true,
+ "peer": true,
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
@@ -25216,25 +24117,6 @@
"url": "https://opencollective.com/ioredis"
}
},
- "node_modules/ip-address": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
- "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
- "dev": true,
- "dependencies": {
- "jsbn": "1.1.0",
- "sprintf-js": "^1.1.3"
- },
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/ip-address/node_modules/sprintf-js": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
- "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
- "dev": true
- },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -25243,18 +24125,6 @@
"node": ">= 0.10"
}
},
- "node_modules/is-absolute-url": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz",
- "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==",
- "dev": true,
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-alphabetical": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
@@ -25462,15 +24332,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -25577,18 +24438,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-interactive": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
- "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
@@ -25678,15 +24527,6 @@
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
"devOptional": true
},
- "node_modules/is-reference": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz",
- "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
- "dev": true,
- "dependencies": {
- "@types/estree": "*"
- }
- },
"node_modules/is-regex": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@@ -25789,18 +24629,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-unicode-supported": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
- "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-weakmap": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
@@ -25876,6 +24704,11 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
+ "node_modules/iso-datestring-validator": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz",
+ "integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA=="
+ },
"node_modules/isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
@@ -27894,12 +26727,6 @@
"js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/jsbn": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
- "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
- "dev": true
- },
"node_modules/jsdom": {
"version": "22.1.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz",
@@ -28376,15 +27203,6 @@
"shell-quote": "^1.8.1"
}
},
- "node_modules/lcm": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/lcm/-/lcm-0.0.3.tgz",
- "integrity": "sha512-TB+ZjoillV6B26Vspf9l2L/vKaRY/4ep3hahcyVkCGFgsTNRUQdc24bQeNFiZeoxH0vr5+7SfNRMQuPHv/1IrQ==",
- "dev": true,
- "dependencies": {
- "gcd": "^0.0.1"
- }
- },
"node_modules/leac": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
@@ -28686,34 +27504,6 @@
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
"integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="
},
- "node_modules/log-symbols": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz",
- "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==",
- "dev": true,
- "dependencies": {
- "chalk": "^5.0.0",
- "is-unicode-supported": "^1.1.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/log-symbols/node_modules/chalk": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
- "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
- "dev": true,
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
"node_modules/log4js": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz",
@@ -28866,15 +27656,6 @@
"tmpl": "1.0.5"
}
},
- "node_modules/markdown-extensions": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz",
- "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/markdown-table": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
@@ -28904,13 +27685,6 @@
"is-buffer": "~1.1.6"
}
},
- "node_modules/mdast": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/mdast/-/mdast-3.0.0.tgz",
- "integrity": "sha512-xySmf8g4fPKMeC07jXGz971EkLbWAJ83s4US2Tj9lEdnZ142UP5grN73H1Xd3HzrdbU5o9GYYP/y8F9ZSwLE9g==",
- "deprecated": "`mdast` was renamed to `remark`",
- "dev": true
- },
"node_modules/mdast-util-definitions": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
@@ -28984,21 +27758,6 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
},
- "node_modules/mdast-util-frontmatter": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-1.0.1.tgz",
- "integrity": "sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw==",
- "dev": true,
- "dependencies": {
- "@types/mdast": "^3.0.0",
- "mdast-util-to-markdown": "^1.3.0",
- "micromark-extension-frontmatter": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/mdast-util-gfm": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz",
@@ -29101,101 +27860,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/mdast-util-mdx": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz",
- "integrity": "sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==",
- "dev": true,
- "dependencies": {
- "mdast-util-from-markdown": "^1.0.0",
- "mdast-util-mdx-expression": "^1.0.0",
- "mdast-util-mdx-jsx": "^2.0.0",
- "mdast-util-mdxjs-esm": "^1.0.0",
- "mdast-util-to-markdown": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/mdast-util-mdx-expression": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz",
- "integrity": "sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "@types/hast": "^2.0.0",
- "@types/mdast": "^3.0.0",
- "mdast-util-from-markdown": "^1.0.0",
- "mdast-util-to-markdown": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/mdast-util-mdx-jsx": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz",
- "integrity": "sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "@types/hast": "^2.0.0",
- "@types/mdast": "^3.0.0",
- "@types/unist": "^2.0.0",
- "ccount": "^2.0.0",
- "mdast-util-from-markdown": "^1.1.0",
- "mdast-util-to-markdown": "^1.3.0",
- "parse-entities": "^4.0.0",
- "stringify-entities": "^4.0.0",
- "unist-util-remove-position": "^4.0.0",
- "unist-util-stringify-position": "^3.0.0",
- "vfile-message": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/mdast-util-mdx-jsx/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/mdast-util-mdx-jsx/node_modules/vfile-message": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
- "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-stringify-position": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/mdast-util-mdxjs-esm": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz",
- "integrity": "sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "@types/hast": "^2.0.0",
- "@types/mdast": "^3.0.0",
- "mdast-util-from-markdown": "^1.0.0",
- "mdast-util-to-markdown": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/mdast-util-phrasing": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz",
@@ -29394,35 +28058,6 @@
"uvu": "^0.5.0"
}
},
- "node_modules/micromark-extension-frontmatter": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-1.1.1.tgz",
- "integrity": "sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ==",
- "dev": true,
- "dependencies": {
- "fault": "^2.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-extension-frontmatter/node_modules/fault": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz",
- "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==",
- "dev": true,
- "dependencies": {
- "format": "^0.2.0"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
"node_modules/micromark-extension-gfm": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz",
@@ -29560,161 +28195,6 @@
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz",
"integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ=="
},
- "node_modules/micromark-extension-mdx-expression": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz",
- "integrity": "sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==",
- "dev": true,
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "@types/estree": "^1.0.0",
- "micromark-factory-mdx-expression": "^1.0.0",
- "micromark-factory-space": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-events-to-acorn": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "uvu": "^0.5.0"
- }
- },
- "node_modules/micromark-extension-mdx-jsx": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz",
- "integrity": "sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==",
- "dev": true,
- "dependencies": {
- "@types/acorn": "^4.0.0",
- "@types/estree": "^1.0.0",
- "estree-util-is-identifier-name": "^2.0.0",
- "micromark-factory-mdx-expression": "^1.0.0",
- "micromark-factory-space": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "uvu": "^0.5.0",
- "vfile-message": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-extension-mdx-jsx/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/micromark-extension-mdx-jsx/node_modules/vfile-message": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
- "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-stringify-position": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-extension-mdx-md": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz",
- "integrity": "sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==",
- "dev": true,
- "dependencies": {
- "micromark-util-types": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-extension-mdxjs": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz",
- "integrity": "sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.0.0",
- "acorn-jsx": "^5.0.0",
- "micromark-extension-mdx-expression": "^1.0.0",
- "micromark-extension-mdx-jsx": "^1.0.0",
- "micromark-extension-mdx-md": "^1.0.0",
- "micromark-extension-mdxjs-esm": "^1.0.0",
- "micromark-util-combine-extensions": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-extension-mdxjs-esm": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz",
- "integrity": "sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==",
- "dev": true,
- "dependencies": {
- "@types/estree": "^1.0.0",
- "micromark-core-commonmark": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-events-to-acorn": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "unist-util-position-from-estree": "^1.1.0",
- "uvu": "^0.5.0",
- "vfile-message": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-extension-mdxjs-esm/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/micromark-extension-mdxjs-esm/node_modules/unist-util-position-from-estree": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz",
- "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-extension-mdxjs-esm/node_modules/vfile-message": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
- "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-stringify-position": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/micromark-factory-destination": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz",
@@ -29756,65 +28236,6 @@
"uvu": "^0.5.0"
}
},
- "node_modules/micromark-factory-mdx-expression": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz",
- "integrity": "sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==",
- "dev": true,
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "@types/estree": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-events-to-acorn": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "unist-util-position-from-estree": "^1.0.0",
- "uvu": "^0.5.0",
- "vfile-message": "^3.0.0"
- }
- },
- "node_modules/micromark-factory-mdx-expression/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/micromark-factory-mdx-expression/node_modules/unist-util-position-from-estree": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz",
- "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-factory-mdx-expression/node_modules/vfile-message": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
- "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-stringify-position": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/micromark-factory-space": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz",
@@ -30006,66 +28427,6 @@
}
]
},
- "node_modules/micromark-util-events-to-acorn": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz",
- "integrity": "sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==",
- "dev": true,
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "@types/acorn": "^4.0.0",
- "@types/estree": "^1.0.0",
- "@types/unist": "^2.0.0",
- "estree-util-visit": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "uvu": "^0.5.0",
- "vfile-message": "^3.0.0"
- }
- },
- "node_modules/micromark-util-events-to-acorn/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/micromark-util-events-to-acorn/node_modules/estree-util-visit": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz",
- "integrity": "sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==",
- "dev": true,
- "dependencies": {
- "@types/estree-jsx": "^1.0.0",
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/micromark-util-events-to-acorn/node_modules/vfile-message": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
- "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-stringify-position": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/micromark-util-html-tag-name": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz",
@@ -30355,12 +28716,6 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
- "node_modules/mitt": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
- "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
- "dev": true
- },
"node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
@@ -30597,6 +28952,11 @@
"multicast-dns": "cli.js"
}
},
+ "node_modules/multiformats": {
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
+ "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg=="
+ },
"node_modules/mustache": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
@@ -30713,15 +29073,6 @@
"yargs": "^16.0.0 || ^17.0.0"
}
},
- "node_modules/netmask": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
- "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
- "dev": true,
- "engines": {
- "node": ">= 0.4.0"
- }
- },
"node_modules/next": {
"version": "14.2.3",
"resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz",
@@ -30771,26 +29122,6 @@
}
}
},
- "node_modules/next-mdx-remote": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz",
- "integrity": "sha512-1BvyXaIou6xy3XoNF4yaMZUCb6vD2GTAa5ciOa6WoO+gAUTYsb1K4rI/HSC2ogAWLrb/7VSV52skz07vOzmqIQ==",
- "dev": true,
- "dependencies": {
- "@mdx-js/mdx": "^2.2.1",
- "@mdx-js/react": "^2.2.1",
- "vfile": "^5.3.0",
- "vfile-matter": "^3.0.1"
- },
- "engines": {
- "node": ">=14",
- "npm": ">=7"
- },
- "peerDependencies": {
- "react": ">=16.x <=18.x",
- "react-dom": ">=16.x <=18.x"
- }
- },
"node_modules/next-plausible": {
"version": "3.12.2",
"resolved": "https://registry.npmjs.org/next-plausible/-/next-plausible-3.12.2.tgz",
@@ -30879,19 +29210,6 @@
"dev": true,
"optional": true
},
- "node_modules/nlcst-to-string": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-3.1.1.tgz",
- "integrity": "sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw==",
- "dev": true,
- "dependencies": {
- "@types/nlcst": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
@@ -30999,28 +29317,6 @@
"node-gyp-build-optional-packages-test": "build-test.js"
}
},
- "node_modules/node-html-markdown": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/node-html-markdown/-/node-html-markdown-1.3.0.tgz",
- "integrity": "sha512-OeFi3QwC/cPjvVKZ114tzzu+YoR+v9UXW5RwSXGUqGb0qCl0DvP406tzdL7SFn8pZrMyzXoisfG2zcuF9+zw4g==",
- "dev": true,
- "dependencies": {
- "node-html-parser": "^6.1.1"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/node-html-parser": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz",
- "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==",
- "dev": true,
- "dependencies": {
- "css-select": "^5.1.0",
- "he": "1.2.0"
- }
- },
"node_modules/node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -31049,6 +29345,14 @@
"node": ">=6"
}
},
+ "node_modules/nodemailer": {
+ "version": "6.9.15",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz",
+ "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
@@ -31675,99 +29979,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/ora": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.1.tgz",
- "integrity": "sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==",
- "dev": true,
- "dependencies": {
- "chalk": "^5.0.0",
- "cli-cursor": "^4.0.0",
- "cli-spinners": "^2.6.1",
- "is-interactive": "^2.0.0",
- "is-unicode-supported": "^1.1.0",
- "log-symbols": "^5.1.0",
- "stdin-discarder": "^0.1.0",
- "strip-ansi": "^7.0.1",
- "wcwidth": "^1.0.1"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ora/node_modules/ansi-regex": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
- "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/ora/node_modules/chalk": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
- "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
- "dev": true,
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/ora/node_modules/cli-cursor": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
- "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
- "dev": true,
- "dependencies": {
- "restore-cursor": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ora/node_modules/restore-cursor": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
- "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
- "dev": true,
- "dependencies": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ora/node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
"node_modules/os-filter-obj": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-2.0.0.tgz",
@@ -31887,76 +30098,6 @@
"node": ">=6"
}
},
- "node_modules/pac-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==",
- "dev": true,
- "dependencies": {
- "@tootallnate/quickjs-emscripten": "^0.23.0",
- "agent-base": "^7.0.2",
- "debug": "^4.3.4",
- "get-uri": "^6.0.1",
- "http-proxy-agent": "^7.0.0",
- "https-proxy-agent": "^7.0.5",
- "pac-resolver": "^7.0.1",
- "socks-proxy-agent": "^8.0.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/pac-proxy-agent/node_modules/agent-base": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
- "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
- "dev": true,
- "dependencies": {
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
- "dev": true,
- "dependencies": {
- "agent-base": "^7.1.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
- "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
- "dev": true,
- "dependencies": {
- "agent-base": "^7.0.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/pac-resolver": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
- "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
- "dev": true,
- "dependencies": {
- "degenerator": "^5.0.0",
- "netmask": "^2.0.2"
- },
- "engines": {
- "node": ">= 14"
- }
- },
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
@@ -32033,21 +30174,6 @@
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
- "node_modules/parse-latin": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-5.0.1.tgz",
- "integrity": "sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg==",
- "dev": true,
- "dependencies": {
- "nlcst-to-string": "^3.0.0",
- "unist-util-modify-children": "^3.0.0",
- "unist-util-visit-children": "^2.0.0"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
"node_modules/parse-node-version": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
@@ -32078,7 +30204,8 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
"integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"domhandler": "^5.0.2",
"parse5": "^7.0.0"
@@ -32091,7 +30218,8 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"entities": "^4.4.0"
},
@@ -32103,7 +30231,8 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"parse5": "^7.0.0"
},
@@ -32115,7 +30244,8 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"entities": "^4.4.0"
},
@@ -32261,18 +30391,8 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
- "devOptional": true
- },
- "node_modules/periscopic": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
- "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
- "dev": true,
- "dependencies": {
- "@types/estree": "^1.0.0",
- "estree-walker": "^3.0.0",
- "is-reference": "^3.0.0"
- }
+ "optional": true,
+ "peer": true
},
"node_modules/picocolors": {
"version": "1.1.0",
@@ -33341,7 +31461,8 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=0.4.0"
}
@@ -33415,72 +31536,6 @@
"node": ">= 0.10"
}
},
- "node_modules/proxy-agent": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
- "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
- "dev": true,
- "dependencies": {
- "agent-base": "^7.0.2",
- "debug": "^4.3.4",
- "http-proxy-agent": "^7.0.1",
- "https-proxy-agent": "^7.0.3",
- "lru-cache": "^7.14.1",
- "pac-proxy-agent": "^7.0.1",
- "proxy-from-env": "^1.1.0",
- "socks-proxy-agent": "^8.0.2"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/proxy-agent/node_modules/agent-base": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
- "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
- "dev": true,
- "dependencies": {
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/proxy-agent/node_modules/http-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
- "dev": true,
- "dependencies": {
- "agent-base": "^7.1.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/proxy-agent/node_modules/https-proxy-agent": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
- "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
- "dev": true,
- "dependencies": {
- "agent-base": "^7.0.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/proxy-agent/node_modules/lru-cache": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
- "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -33521,106 +31576,6 @@
"node": ">=6"
}
},
- "node_modules/puppeteer": {
- "version": "22.15.0",
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.15.0.tgz",
- "integrity": "sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q==",
- "dev": true,
- "hasInstallScript": true,
- "dependencies": {
- "@puppeteer/browsers": "2.3.0",
- "cosmiconfig": "^9.0.0",
- "devtools-protocol": "0.0.1312386",
- "puppeteer-core": "22.15.0"
- },
- "bin": {
- "puppeteer": "lib/esm/puppeteer/node/cli.js"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/puppeteer-core": {
- "version": "22.15.0",
- "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz",
- "integrity": "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA==",
- "dev": true,
- "dependencies": {
- "@puppeteer/browsers": "2.3.0",
- "chromium-bidi": "0.6.3",
- "debug": "^4.3.6",
- "devtools-protocol": "0.0.1312386",
- "ws": "^8.18.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/puppeteer-core/node_modules/ws": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
- "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
- "dev": true,
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/puppeteer/node_modules/cosmiconfig": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
- "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
- "dev": true,
- "dependencies": {
- "env-paths": "^2.2.1",
- "import-fresh": "^3.3.0",
- "js-yaml": "^4.1.0",
- "parse-json": "^5.2.0"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/d-fischer"
- },
- "peerDependencies": {
- "typescript": ">=4.9.5"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/puppeteer/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
"node_modules/pure-rand": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
@@ -33675,12 +31630,6 @@
}
]
},
- "node_modules/queue-tick": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
- "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==",
- "dev": true
- },
"node_modules/quick-format-unescaped": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
@@ -34975,134 +32924,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/rehype-katex": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-6.0.3.tgz",
- "integrity": "sha512-ByZlRwRUcWegNbF70CVRm2h/7xy7jQ3R9LaY4VVSvjnoVWwWVhNL60DiZsBpC5tSzYQOCvDbzncIpIjPZWodZA==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "@types/katex": "^0.14.0",
- "hast-util-from-html-isomorphic": "^1.0.0",
- "hast-util-to-text": "^3.1.0",
- "katex": "^0.16.0",
- "unist-util-visit": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/rehype-katex/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/rehype-katex/node_modules/hast-util-from-dom": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz",
- "integrity": "sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ==",
- "dev": true,
- "dependencies": {
- "hastscript": "^7.0.0",
- "web-namespaces": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/rehype-katex/node_modules/hast-util-from-html-isomorphic": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-1.0.0.tgz",
- "integrity": "sha512-Yu480AKeOEN/+l5LA674a+7BmIvtDj24GvOt7MtQWuhzUwlaaRWdEPXAh3Qm5vhuthpAipFb2vTetKXWOjmTvw==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "hast-util-from-dom": "^4.0.0",
- "hast-util-from-html": "^1.0.0",
- "unist-util-remove-position": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/rehype-katex/node_modules/hast-util-is-element": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz",
- "integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/rehype-katex/node_modules/hast-util-parse-selector": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz",
- "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/rehype-katex/node_modules/hast-util-to-text": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz",
- "integrity": "sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "@types/unist": "^2.0.0",
- "hast-util-is-element": "^2.0.0",
- "unist-util-find-after": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/rehype-katex/node_modules/hastscript": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz",
- "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==",
- "dev": true,
- "dependencies": {
- "@types/hast": "^2.0.0",
- "comma-separated-tokens": "^2.0.0",
- "hast-util-parse-selector": "^3.0.0",
- "property-information": "^6.0.0",
- "space-separated-tokens": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/rehype-katex/node_modules/unist-util-find-after": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-4.0.1.tgz",
- "integrity": "sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-is": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/rehype-parse": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.0.tgz",
@@ -36083,38 +33904,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/remark": {
- "version": "14.0.3",
- "resolved": "https://registry.npmjs.org/remark/-/remark-14.0.3.tgz",
- "integrity": "sha512-bfmJW1dmR2LvaMJuAnE88pZP9DktIFYXazkTfOIKZzi3Knk9lT0roItIA24ydOucI3bV/g/tXBA6hzqq3FV9Ew==",
- "dev": true,
- "dependencies": {
- "@types/mdast": "^3.0.0",
- "remark-parse": "^10.0.0",
- "remark-stringify": "^10.0.0",
- "unified": "^10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/remark-frontmatter": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-4.0.1.tgz",
- "integrity": "sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==",
- "dev": true,
- "dependencies": {
- "@types/mdast": "^3.0.0",
- "mdast-util-frontmatter": "^1.0.0",
- "micromark-extension-frontmatter": "^1.0.0",
- "unified": "^10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/remark-gfm": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz",
@@ -36198,20 +33987,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/remark-mdx": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz",
- "integrity": "sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==",
- "dev": true,
- "dependencies": {
- "mdast-util-mdx": "^2.0.0",
- "micromark-extension-mdxjs": "^1.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/remark-parse": {
"version": "10.0.2",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz",
@@ -36241,77 +34016,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/remark-smartypants": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-2.1.0.tgz",
- "integrity": "sha512-qoF6Vz3BjU2tP6OfZqHOvCU0ACmu/6jhGaINSQRI9mM7wCxNQTKB3JUAN4SVoN2ybElEDTxBIABRep7e569iJw==",
- "dev": true,
- "dependencies": {
- "retext": "^8.1.0",
- "retext-smartypants": "^5.2.0",
- "unist-util-visit": "^5.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/remark-smartypants/node_modules/unist-util-is": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
- "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/remark-smartypants/node_modules/unist-util-visit": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
- "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0",
- "unist-util-is": "^6.0.0",
- "unist-util-visit-parents": "^6.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/remark-smartypants/node_modules/unist-util-visit-parents": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz",
- "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0",
- "unist-util-is": "^6.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/remark-stringify": {
- "version": "10.0.3",
- "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-10.0.3.tgz",
- "integrity": "sha512-koyOzCMYoUHudypbj4XpnAKFbkddRMYZHwghnxd7ue5210WzGw6kOBwauJTRUMq16jsovXx8dYNvSSWP89kZ3A==",
- "dev": true,
- "dependencies": {
- "@types/mdast": "^3.0.0",
- "mdast-util-to-markdown": "^1.0.0",
- "unified": "^10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/remove-markdown": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.5.5.tgz",
@@ -36453,69 +34157,6 @@
"node": ">=8"
}
},
- "node_modules/retext": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/retext/-/retext-8.1.0.tgz",
- "integrity": "sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==",
- "dev": true,
- "dependencies": {
- "@types/nlcst": "^1.0.0",
- "retext-latin": "^3.0.0",
- "retext-stringify": "^3.0.0",
- "unified": "^10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/retext-latin": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-3.1.0.tgz",
- "integrity": "sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==",
- "dev": true,
- "dependencies": {
- "@types/nlcst": "^1.0.0",
- "parse-latin": "^5.0.0",
- "unherit": "^3.0.0",
- "unified": "^10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/retext-smartypants": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-5.2.0.tgz",
- "integrity": "sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==",
- "dev": true,
- "dependencies": {
- "@types/nlcst": "^1.0.0",
- "nlcst-to-string": "^3.0.0",
- "unified": "^10.0.0",
- "unist-util-visit": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/retext-stringify": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-3.1.0.tgz",
- "integrity": "sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==",
- "dev": true,
- "dependencies": {
- "@types/nlcst": "^1.0.0",
- "nlcst-to-string": "^3.0.0",
- "unified": "^10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/retry": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
@@ -36822,19 +34463,6 @@
"compute-scroll-into-view": "^1.0.20"
}
},
- "node_modules/section-matter": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
- "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==",
- "dev": true,
- "dependencies": {
- "extend-shallow": "^2.0.1",
- "kind-of": "^6.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/secure-compare": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
@@ -37433,16 +35061,6 @@
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.0.6.tgz",
"integrity": "sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA=="
},
- "node_modules/smart-buffer": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
- "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
- "dev": true,
- "engines": {
- "node": ">= 6.0.0",
- "npm": ">= 3.0.0"
- }
- },
"node_modules/snake-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
@@ -37470,46 +35088,6 @@
"uuid": "dist/bin/uuid"
}
},
- "node_modules/socks": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
- "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
- "dev": true,
- "dependencies": {
- "ip-address": "^9.0.5",
- "smart-buffer": "^4.2.0"
- },
- "engines": {
- "node": ">= 10.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks-proxy-agent": {
- "version": "8.0.4",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
- "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
- "dev": true,
- "dependencies": {
- "agent-base": "^7.1.1",
- "debug": "^4.3.4",
- "socks": "^2.8.3"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/socks-proxy-agent/node_modules/agent-base": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
- "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
- "dev": true,
- "dependencies": {
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
"node_modules/sonic-boom": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.1.0.tgz",
@@ -37713,21 +35291,6 @@
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz",
"integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg=="
},
- "node_modules/stdin-discarder": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz",
- "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==",
- "dev": true,
- "dependencies": {
- "bl": "^5.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/streamroller": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz",
@@ -37778,20 +35341,6 @@
"node": ">=10.0.0"
}
},
- "node_modules/streamx": {
- "version": "2.20.0",
- "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.0.tgz",
- "integrity": "sha512-ZGd1LhDeGFucr1CUCTBOS58ZhEendd0ttpGT3usTvosS4ntIwKN9LJFp+OeCSprsCPL14BXVRZlHGRY1V9PVzQ==",
- "dev": true,
- "dependencies": {
- "fast-fifo": "^1.3.2",
- "queue-tick": "^1.0.1",
- "text-decoder": "^1.1.0"
- },
- "optionalDependencies": {
- "bare-events": "^2.2.0"
- }
- },
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -37978,15 +35527,6 @@
"node": ">=8"
}
},
- "node_modules/strip-bom-string": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
- "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
@@ -38559,31 +36099,6 @@
"node": ">=10"
}
},
- "node_modules/tar-fs": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
- "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
- "dev": true,
- "dependencies": {
- "pump": "^3.0.0",
- "tar-stream": "^3.1.5"
- },
- "optionalDependencies": {
- "bare-fs": "^2.1.1",
- "bare-path": "^2.1.0"
- }
- },
- "node_modules/tar-fs/node_modules/tar-stream": {
- "version": "3.1.7",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
- "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
- "dev": true,
- "dependencies": {
- "b4a": "^1.6.4",
- "fast-fifo": "^1.2.0",
- "streamx": "^2.15.0"
- }
- },
"node_modules/tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
@@ -38833,15 +36348,6 @@
"node": "*"
}
},
- "node_modules/text-decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz",
- "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==",
- "dev": true,
- "dependencies": {
- "b4a": "^1.6.4"
- }
- },
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -38936,6 +36442,30 @@
"node": ">=14.0.0"
}
},
+ "node_modules/tlds": {
+ "version": "1.255.0",
+ "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.255.0.tgz",
+ "integrity": "sha512-tcwMRIioTcF/FcxLev8MJWxCp+GUALRhFEqbDoZrnowmKSGqPrl5pqS+Sut2m8BgJ6S4FExCSSpGffZ0Tks6Aw==",
+ "bin": {
+ "tlds": "bin.js"
+ }
+ },
+ "node_modules/tldts": {
+ "version": "6.1.47",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.47.tgz",
+ "integrity": "sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==",
+ "dependencies": {
+ "tldts-core": "^6.1.47"
+ },
+ "bin": {
+ "tldts": "bin/cli.js"
+ }
+ },
+ "node_modules/tldts-core": {
+ "version": "6.1.47",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.47.tgz",
+ "integrity": "sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA=="
+ },
"node_modules/tmp": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
@@ -39614,6 +37144,14 @@
"node": ">=8"
}
},
+ "node_modules/uint8arrays": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz",
+ "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==",
+ "dependencies": {
+ "multiformats": "^9.4.2"
+ }
+ },
"node_modules/unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -39633,7 +37171,8 @@
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"buffer": "^5.2.1",
"through": "^2.3.8"
@@ -39643,7 +37182,6 @@
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "devOptional": true,
"funding": [
{
"type": "github",
@@ -39658,6 +37196,8 @@
"url": "https://feross.org/support"
}
],
+ "optional": true,
+ "peer": true,
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
@@ -39667,21 +37207,12 @@
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.19.8.tgz",
"integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18.17"
}
},
- "node_modules/unherit": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/unherit/-/unherit-3.0.1.tgz",
- "integrity": "sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==",
- "dev": true,
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@@ -39785,25 +37316,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/unist-builder": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.1.tgz",
- "integrity": "sha512-gnpOw7DIpCA0vpr6NqdPvTWnlPTApCTRzr+38E6hCWx3rz/cjo83SsKIlS1Z+L5ttScQ2AwutNnb8+tAvpb6qQ==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-builder/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
"node_modules/unist-util-filter": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/unist-util-filter/-/unist-util-filter-5.0.1.tgz",
@@ -39839,33 +37351,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/unist-util-find-after": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz",
- "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0",
- "unist-util-is": "^6.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-util-find-after/node_modules/unist-util-is": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
- "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/unist-util-generated": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz",
@@ -39892,45 +37377,6 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
},
- "node_modules/unist-util-map": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/unist-util-map/-/unist-util-map-3.1.3.tgz",
- "integrity": "sha512-4/mDauoxqZ6geK97lJ6n2kDk6JK88Vh+hWMSJqyaaP/7eqN1dDhjcjnNxKNm3YU6Sw7PVJtcFMUbnmHvYzb6Vg==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-util-map/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/unist-util-modify-children": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-3.1.1.tgz",
- "integrity": "sha512-yXi4Lm+TG5VG+qvokP6tpnk+r1EPwyYL04JWDxLvgvPV40jANh7nm3udk65OOWquvbMDe+PL9+LmkxDpTv/7BA==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "array-iterate": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-util-modify-children/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
"node_modules/unist-util-position": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz",
@@ -39943,65 +37389,11 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/unist-util-position-from-estree": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz",
- "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
"node_modules/unist-util-position/node_modules/@types/unist": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
},
- "node_modules/unist-util-remove": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-3.1.1.tgz",
- "integrity": "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-is": "^5.0.0",
- "unist-util-visit-parents": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-util-remove-position": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz",
- "integrity": "sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "unist-util-visit": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-util-remove-position/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/unist-util-remove/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
"node_modules/unist-util-stringify-position": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
@@ -40033,25 +37425,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/unist-util-visit-children": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-2.0.2.tgz",
- "integrity": "sha512-+LWpMFqyUwLGpsQxpumsQ9o9DG2VGLFrpz+rpVXYIEdPy57GSy5HioC0g3bg/8WP9oCLlapQtklOzQ8uLS496Q==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/unist-util-visit-children/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
"node_modules/unist-util-visit-parents": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz",
@@ -40468,82 +37841,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/vfile-location": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz",
- "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0",
- "vfile": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/vfile-location/node_modules/@types/unist": {
- "version": "2.0.11",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
- "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
- "dev": true
- },
- "node_modules/vfile-matter": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/vfile-matter/-/vfile-matter-3.0.1.tgz",
- "integrity": "sha512-CAAIDwnh6ZdtrqAuxdElUqQRQDQgbbIrYtDYI8gCjXS1qQ+1XdLoK8FIZWxJwn0/I+BkSSZpar3SOgjemQz4fg==",
- "dev": true,
- "dependencies": {
- "@types/js-yaml": "^4.0.0",
- "is-buffer": "^2.0.0",
- "js-yaml": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/vfile-matter/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/vfile-matter/node_modules/is-buffer": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
- "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/vfile-matter/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
"node_modules/vfile-message": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz",
@@ -41418,7 +38715,8 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"iconv-lite": "0.6.3"
},
@@ -41430,7 +38728,8 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
@@ -41442,7 +38741,8 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -41773,7 +39073,8 @@
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
- "devOptional": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
diff --git a/package.json b/package.json
index a7008b81..bb5780e6 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
},
"private": true,
"dependencies": {
+ "@atproto/api": "^0.13.11",
"@aws-sdk/client-s3": "^3.410.0",
"@aws-sdk/s3-request-presigner": "^3.410.0",
"@casl/ability": "^6.5.0",
@@ -70,6 +71,7 @@
"@types/md5": "^2.3.5",
"@types/mime-types": "^2.1.4",
"@types/multer": "^1.4.11",
+ "@types/nodemailer": "^6.4.16",
"@types/remove-markdown": "^0.3.4",
"@types/sha256": "^0.2.2",
"@types/stripe": "^8.0.417",
@@ -112,6 +114,7 @@
"nestjs-command": "^3.1.4",
"next": "14.2.3",
"next-plausible": "^3.12.0",
+ "nodemailer": "^6.9.15",
"nx": "19.7.2",
"openai": "^4.47.1",
"polotno": "^2.10.5",
@@ -138,6 +141,7 @@
"swr": "^2.2.5",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "3.4.3",
+ "tldts": "^6.1.47",
"tslib": "^2.3.0",
"twitter-api-v2": "^1.16.0",
"use-debounce": "^10.0.0",