Compare commits

..

4 Commits

Author SHA1 Message Date
Ephraim Atta-Duncan
eddfd9a720 fix: completed count incorrect 2023-09-27 15:04:58 +00:00
Timur Ercan
cdb71c3a62 chore: greetings 2023-09-27 12:30:11 +02:00
Timur Ercan
39d7b3ca58 Merge branch 'feat/refresh' of https://github.com/documenso/documenso into feat/refresh 2023-09-27 12:19:14 +02:00
Timur Ercan
748c3636d5 chore: sync shop article and add missing and updated assets 2023-09-27 12:15:44 +02:00
24 changed files with 28 additions and 788 deletions

View File

@@ -15,20 +15,6 @@ NEXT_PRIVATE_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documen
# Defines the URL to use for the database when running migrations and other commands that won't work with a connection pool.
NEXT_PRIVATE_DIRECT_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documenso"
# [[E2E Tests]]
E2E_TEST_SIGNER_NAME="Test Signer"
E2E_TEST_SIGNER_EMAIL="testsigner@mail.com"
E2E_TEST_SIGNING_SUBJECT="Test subject"
E2E_TEST_SIGNING_MESSAGE="Test message"
# User for the "auth.setup.ts" file and the authenticated tests
E2E_TEST_AUTHENTICATE_USERNAME="New user"
E2E_TEST_AUTHENTICATE_USER_EMAIL="mytestnewuser@mail.com"
E2E_TEST_AUTHENTICATE_USER_PASSWORD="new_test_password"
# User for the *.unauthenticated.ts files
E2E_TEST_USERNAME="Test"
E2E_TEST_USER_EMAIL="mytestuser@mail.com"
E2E_TEST_USER_PASSWORD="test_password"
# [[STORAGE]]
# OPTIONAL: Defines the storage transport to use. Available options: database (default) | s3
NEXT_PUBLIC_UPLOAD_TRANSPORT="database"

View File

@@ -1,53 +0,0 @@
name: Playwright Tests
on:
push:
branches: [feat/refresh, feat/add-e2e-testing]
pull_request:
branches: [feat/refresh, feat/add-e2e-testing]
jobs:
e2e_tests:
timeout-minutes: 60
runs-on: ubuntu-latest
services:
postgres:
image: postgres
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
env:
NEXT_PRIVATE_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/documenso
NEXT_PRIVATE_DIRECT_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/documenso
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Generate package-lock.json
run: npm cache clean --force && npm install
- name: Install dependencies
run: npm ci
- name: Copy env
run: cp .env.example .env
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Install Prisma Client
run: npm install @prisma/client
- name: Generate Prisma Client
run: npm run prisma:generate -w @documenso/prisma
- name: Create the database
run: npm run prisma:migrate-dev -w @documenso/prisma
- name: Run Playwright tests
run: npm run ci
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30

5
.gitignore vendored
View File

@@ -47,8 +47,3 @@ yarn-error.log*
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
**/test-results/
/playwright-report/
/playwright/.cache/
playwright/.auth

View File

@@ -51,4 +51,7 @@ As Documenso 1.0 just hit the staging environment, we're calling a MALFUNCTION M
We don't have a specific end date for Malfunction Mania. We plan to move the staging version into the production environment by the end of the month once we're happy with the results. Bug reports and fixes are, of course, always welcome going forward.
Best from Hamburg
Timur
**[Follow Documenso on Twitter / X](https://documen.so/tw) and [join the Discord server](https://documen.so/discord) to get the latest about Malfunction Mania.**

View File

@@ -1,12 +1,12 @@
---
title: Shop and Limited Edition "Mania" Shirt
title: Merch Mania
description: Happy Launch Week Day 3. The limited edition "Malfunction Mania" shirt is here. Grab it, while you can.
authorName: 'Timur Ercan'
authorImage: '/blog/blog-author-timur.jpeg'
authorRole: 'Co-Founder'
date: 2023-09-27
tags:
- Testing
- Merch
- Rewrite
- Bounties
---
@@ -24,13 +24,13 @@ tags:
</figcaption>
</figure>
> TLDR; We have a fancy limited edition shirt. Contribute to Malfunction Mania to get one.
> TLDR; We have a fancy limited edition shirt. Contribute to [Malfunction Mania](https://documenso.com/blog/malfunction-mania) to get one.
We kicked off [Malfunction Mania](https://documenso.com/blog/malfunction-mania) yesterday, and the first [Issues](https://github.com/documenso/documenso/issues) are coming in. As mentioned, there will be dollar bounties, but we also wanted to celebrate entering the final stage of version 1.0 with something special. This is why we created the limited edition shirt for Malfunction Mania. It will only be available during the runtime of Malfunction Mania. We have yet to set an exact end date, the next event in October, however, is looming, ready to end MM.
We kicked off [Malfunction Mania](https://documenso.com/blog/malfunction-mania) yesterday, and the first [issues](https://github.com/documenso/documenso/issues) are coming in. As mentioned, there will be dollar bounties, but we also wanted to celebrate entering the final stage of version 1.0 with something special. This is why we created this limited edition shirt. It will only be available during the runtime of Malfunction Mania. We have yet to set an exact end date, the next event in October, however, is looming, ready to end MM.
## Documenso Merch Shop
The shirt will be available in our [merch shop](https://documen.so/shop) via a unique discount code. While the shirt will be gone after Malfunction Mania, the shop is here to stay and provide a well-deserved reward for great community members and contributors.
The shirt will be available in our [merch shop](https://documen.so/shop) via a unique discount code. While the shirt will be gone after Malfunction Mania, the shop is here to stay and provide a well-deserved reward for great community members and contributors. All items can be earned by contrinuting to Documenso.
<figure>
<MdxNextImage
@@ -45,7 +45,7 @@ The shirt will be available in our [merch shop](https://documen.so/shop) via a u
</figcaption>
</figure>
## How to get the shirt
## How earn the shirt
If you have been following us, you know we are not big on formalities but highly value rewarding merit. That being said, any worthwhile contribution has a chance to get one. To inspire, here are a few ideas on how to contribute to securing one:
@@ -56,7 +56,9 @@ If you have been following us, you know we are not big on formalities but highly
- Engage in discussion about the current version and its choices
- Raise awareness for Malfunction Mania and try out the [version currently in staging](https://documen.so/staging)
- Review the version with a video, stream, or screenshots and post about it
- Review existing or create missing documenso
- ...
- Review existing or create missing documentation
**[Follow Documenso on Twitter / X](https://documen.so/tw) and [join the Discord server](https://documen.so/discord) to get the latest about Malfunction Mania.**
Best from Hamburg
Timur
**[Follow Documenso on Twitter / X](https://documen.so/tw) and [join the Discord server](https://documen.so/discord) to get the latest updates about Malfunction Mania.**

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 956 KiB

After

Width:  |  Height:  |  Size: 258 KiB

3
apps/web/.gitignore vendored
View File

@@ -1,3 +0,0 @@
node_modules/
playwright-report/
playwright/.auth

View File

@@ -1,16 +0,0 @@
import { deleteUserAndItsData } from '@documenso/lib/server-only/user/delete-user-and-data';
async function teardown() {
if (!process.env.E2E_TEST_USERNAME || !process.env.E2E_TEST_AUTHENTICATE_USERNAME) {
return;
}
try {
await deleteUserAndItsData(process.env.E2E_TEST_USERNAME);
await deleteUserAndItsData(process.env.E2E_TEST_AUTHENTICATE_USERNAME);
} catch (e) {
throw new Error(`Error deleting user: ${e}`);
}
}
export default teardown;

View File

@@ -8,8 +8,6 @@
"build": "next build",
"start": "next start",
"lint": "next lint",
"test:dev": "playwright test",
"test:e2e": "start-server-and-test \"npm run start\" http://localhost:3000 \"playwright test\"",
"clean": "rimraf .next && rimraf node_modules",
"copy:pdfjs": "node ../../scripts/copy-pdfjs.cjs"
},
@@ -43,11 +41,9 @@
"sharp": "0.32.5",
"ts-pattern": "^5.0.5",
"typescript": "5.1.6",
"zod": "^3.21.4",
"start-server-and-test": "^2.0.1"
"zod": "^3.21.4"
},
"devDependencies": {
"@playwright/test": "^1.38.0",
"@types/formidable": "^2.0.6",
"@types/luxon": "^3.3.1",
"@types/node": "20.1.0",

View File

@@ -1,66 +0,0 @@
import { defineConfig, devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
import { config as dotenvConfig } from 'dotenv';
dotenvConfig();
export const STORAGE_STATE = 'playwright/.auth/user.json';
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './src/tests/e2e',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://localhost:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
navigationTimeout: 60 * 1000,
},
/* Configure projects for major browsers */
projects: [
{ name: 'setup', testMatch: '**/*.setup.ts' },
{
name: 'Authenticated User Tests',
testMatch: '*.authenticated.spec.ts',
dependencies: ['setup', 'cleanup db'],
use: {
...devices['Desktop Chrome'],
storageState: STORAGE_STATE,
},
},
{
name: 'Unauthenticated User Tests',
dependencies: ['cleanup db'],
use: {
...devices['Desktop Chrome'],
},
testMatch: '*.unauthenticated.spec.ts',
testIgnore: ['*.setup.ts', '*.authenticated.spec.ts'],
},
{
name: 'cleanup db',
testMatch: /global.teardown\.ts/,
},
],
globalTeardown: './global.teardown.ts',
});

View File

@@ -1,35 +0,0 @@
import { type Page, expect, test as setup } from '@playwright/test';
import { STORAGE_STATE } from '../../../playwright.config';
const username = process.env.E2E_TEST_AUTHENTICATE_USERNAME || '';
const email = process.env.E2E_TEST_AUTHENTICATE_USER_EMAIL || '';
const password = process.env.E2E_TEST_AUTHENTICATE_USER_PASSWORD || '';
setup('authenticate', async ({ page }: { page: Page }) => {
await page.goto('/signup');
await page.getByLabel('Name').fill(username);
await page.getByLabel('Email').fill(email);
await page.getByLabel('Password', { exact: true }).fill(password);
const canvas = page.locator('canvas');
const box = await canvas.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 8, box.y + box.height / 6);
await page.mouse.down();
await page.mouse.move(box.x + box.width / 8, box.y + box.height / 6);
await page.mouse.up();
}
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.goto('/');
await page.getByLabel('Email').fill(email);
await page.getByLabel('Password', { exact: true }).fill(password);
await page.getByRole('button', { name: 'Sign In' }).click();
await page.waitForURL('/documents');
await expect(page).toHaveURL('/documents');
await page.context().storageState({ path: STORAGE_STATE });
});

View File

@@ -1,57 +0,0 @@
%PDF-1.4
%<25><><EFBFBD><EFBFBD>
1 0 obj
<</Title (documenso)
/Producer (Skia/PDF m118 Google Docs Renderer)>>
endobj
3 0 obj
<</ca 1
/BM /Normal>>
endobj
4 0 obj
<</Length 84>> stream
1 0 0 -1 0 842 cm
q
.75 0 0 .75 0 0 cm
1 1 1 RG 1 1 1 rg
/G3 gs
0 0 794 1123 re
f
Q
endstream
endobj
2 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R>>>>
/MediaBox [0 0 596 842]
/Contents 4 0 R
/StructParents 0
/Parent 5 0 R>>
endobj
5 0 obj
<</Type /Pages
/Count 1
/Kids [2 0 R]>>
endobj
6 0 obj
<</Type /Catalog
/Pages 5 0 R>>
endobj
xref
0 7
0000000000 65535 f
0000000015 00000 n
0000000269 00000 n
0000000100 00000 n
0000000137 00000 n
0000000457 00000 n
0000000512 00000 n
trailer
<</Size 7
/Root 6 0 R
/Info 1 0 R>>
startxref
559
%%EOF

View File

@@ -1,45 +0,0 @@
import { type Page, expect, test } from '@playwright/test';
test.use({ storageState: { cookies: [], origins: [] } });
/*
Using them sequentially so the 2nd test
uses the details from the 1st (registration) test
*/
test.describe.configure({ mode: 'serial' });
const username = process.env.E2E_TEST_USERNAME || '';
const email = process.env.E2E_TEST_USER_EMAIL || '';
const password = process.env.E2E_TEST_USER_PASSWORD || '';
test('user can sign up with email and password', async ({ page }: { page: Page }) => {
await page.goto('/signup');
await page.getByLabel('Name').fill(username);
await page.getByLabel('Email').fill(email);
await page.getByLabel('Password', { exact: true }).fill(password);
const canvas = page.locator('canvas');
const box = await canvas.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + box.width / 4, box.y + box.height / 4);
await page.mouse.up();
}
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.waitForURL('/documents');
await expect(page).toHaveURL('/documents');
});
test('user can login with user and password', async ({ page }: { page: Page }) => {
await page.goto('/signin');
await page.getByLabel('Email').fill(email);
await page.getByLabel('Password', { exact: true }).fill(password);
await page.getByRole('button', { name: 'Sign In' }).click();
await page.waitForURL('/documents');
await expect(page).toHaveURL('/documents');
});

View File

@@ -1,38 +0,0 @@
import path from 'path';
import { expect, test } from '../test-fixtures/documents-page/documents-page';
const signer_name = process.env.E2E_TEST_SIGNER_NAME;
const signer_email = process.env.E2E_TEST_SIGNER_EMAIL;
const signing_subject = process.env.E2E_TEST_SIGNING_SUBJECT;
const signing_message = process.env.E2E_TEST_SIGNING_MESSAGE;
if (!signer_name || !signer_email || !signing_subject || !signing_message) {
throw new Error('Required environment variables for tests are not defined');
}
test.describe('Document upload test', () => {
test.beforeEach(async ({ documentsPage }) => {
await documentsPage.uploadDocument(path.join(__dirname, './documenso.pdf'));
});
test('user can see /documents page', async ({ page, documentsPage }) => {
await documentsPage.goToDocumentsPage();
await expect(page).toHaveTitle('Documenso - The Open Source DocuSign Alternative');
});
test('user can upload a document succesfully', async ({ page }) => {
await expect(page.getByText('Drag & drop your document here.')).toBeVisible();
});
test('user can send the document for signing succesfully', async ({ documentsPage, page }) => {
await documentsPage.addSigner(signer_email, signer_name);
await documentsPage.addSignatureField(signer_name);
await documentsPage.addSubjectAndMessage(signing_subject, signing_message);
await expect(page).toHaveURL('/documents');
await expect(page.getByRole('status').locator('div').nth(2)).toHaveText(
'Your document has been sent successfully.',
);
});
});

View File

@@ -1,49 +0,0 @@
import type { Locator, Page } from '@playwright/test';
export class DocumentsPage {
private readonly fileInput: Locator;
private readonly subject: Locator;
private readonly message: Locator;
// eslint-disable-next-line no-unused-vars
constructor(public readonly page: Page) {
this.fileInput = this.page.locator('input[type=file]');
this.subject = this.page
.locator('div')
.filter({ hasText: /^Subject \(Optional\)$/ })
.locator('input');
this.message = this.page
.locator('div')
.filter({ hasText: /^Message \(Optional\)$/ })
.locator('textarea');
}
async goToDocumentsPage() {
await this.page.goto('/documents');
}
async uploadDocument(filePath: string) {
await this.goToDocumentsPage();
await this.fileInput.setInputFiles(filePath);
}
async addSigner(email: string, name: string) {
await this.page.getByLabel('Email*').fill(email);
await this.page.getByLabel('Name').fill(name);
await this.page.getByRole('button', { name: 'Continue' }).click();
}
async addSignatureField(name: string) {
await this.page
.getByRole('button', { name: `${name} Signature` })
.dragTo(this.page.locator('canvas'));
await this.page.getByRole('button', { name: 'Continue' }).click();
}
async addSubjectAndMessage(subject: string, message: string) {
await this.subject.fill(subject);
await this.message.fill(message);
await this.page.getByRole('button', { name: 'Send' }).click();
}
}

View File

@@ -1,13 +0,0 @@
import { test as base } from '@playwright/test';
import { DocumentsPage } from './DocumentsPageObject';
export const test = base.extend<{ documentsPage: DocumentsPage }>({
documentsPage: async ({ page }, use) => {
const documentsPage = new DocumentsPage(page);
await use(documentsPage);
},
});
export { expect } from '@playwright/test';

320
package-lock.json generated
View File

@@ -98,13 +98,11 @@
"react-icons": "^4.8.0",
"react-rnd": "^10.4.1",
"sharp": "0.32.5",
"start-server-and-test": "^2.0.1",
"ts-pattern": "^5.0.5",
"typescript": "5.1.6",
"zod": "^3.21.4"
},
"devDependencies": {
"@playwright/test": "^1.38.0",
"@types/formidable": "^2.0.6",
"@types/luxon": "^3.3.1",
"@types/node": "20.1.0",
@@ -2452,19 +2450,6 @@
"node": ">=6"
}
},
"node_modules/@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="
},
"node_modules/@hapi/topo": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
"integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
"dependencies": {
"@hapi/hoek": "^9.0.0"
}
},
"node_modules/@hookform/resolvers": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.0.tgz",
@@ -3801,21 +3786,6 @@
"url": "https://opencollective.com/unts"
}
},
"node_modules/@playwright/test": {
"version": "1.38.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.1.tgz",
"integrity": "sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==",
"dev": true,
"dependencies": {
"playwright": "1.38.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=16"
}
},
"node_modules/@prisma/client": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.3.1.tgz",
@@ -5465,24 +5435,6 @@
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/@sideway/address": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
"integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
"dependencies": {
"@hapi/hoek": "^9.0.0"
}
},
"node_modules/@sideway/formula": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
"integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg=="
},
"node_modules/@sideway/pinpoint": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
},
"node_modules/@sindresorhus/slugify": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz",
@@ -7667,14 +7619,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/check-more-types": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
"integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -9180,11 +9124,6 @@
"node": ">=12"
}
},
"node_modules/duplexer": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
},
"node_modules/duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
@@ -10389,20 +10328,6 @@
"node": ">=0.10.0"
}
},
"node_modules/event-stream": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
"integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==",
"dependencies": {
"duplexer": "~0.1.1",
"from": "~0",
"map-stream": "~0.1.0",
"pause-stream": "0.0.11",
"split": "0.3",
"stream-combiner": "~0.0.4",
"through": "~2.3.1"
}
},
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
@@ -10802,11 +10727,6 @@
}
}
},
"node_modules/from": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
"integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g=="
},
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
@@ -12245,18 +12165,6 @@
"resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
"integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="
},
"node_modules/joi": {
"version": "17.10.2",
"resolved": "https://registry.npmjs.org/joi/-/joi-17.10.2.tgz",
"integrity": "sha512-hcVhjBxRNW/is3nNLdGLIjkgXetkeGc2wyhydhz8KumG23Aerk4HPjU5zaPAMRqXQFc0xNqXTC7+zQjxr0GlKA==",
"dependencies": {
"@hapi/hoek": "^9.0.0",
"@hapi/topo": "^5.0.0",
"@sideway/address": "^4.1.3",
"@sideway/formula": "^3.0.1",
"@sideway/pinpoint": "^2.0.0"
}
},
"node_modules/jose": {
"version": "4.14.4",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz",
@@ -12491,14 +12399,6 @@
"language-subtag-registry": "~0.3.2"
}
},
"node_modules/lazy-ass": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
"integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==",
"engines": {
"node": "> 0.8"
}
},
"node_modules/leac": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
@@ -13046,11 +12946,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/map-stream": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
"integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g=="
},
"node_modules/markdown-extensions": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz",
@@ -15104,14 +14999,6 @@
"node": ">=8"
}
},
"node_modules/pause-stream": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
"integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==",
"dependencies": {
"through": "~2.3"
}
},
"node_modules/pdf-lib": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz",
@@ -15210,36 +15097,6 @@
"node": ">= 6"
}
},
"node_modules/playwright": {
"version": "1.38.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.1.tgz",
"integrity": "sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==",
"dev": true,
"dependencies": {
"playwright-core": "1.38.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=16"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.38.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.1.tgz",
"integrity": "sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=16"
}
},
"node_modules/postcss": {
"version": "8.4.27",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
@@ -15790,20 +15647,6 @@
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
},
"node_modules/ps-tree": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz",
"integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==",
"dependencies": {
"event-stream": "=3.3.4"
},
"bin": {
"ps-tree": "bin/ps-tree.js"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@@ -17424,14 +17267,6 @@
"resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz",
"integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA=="
},
"node_modules/rxjs": {
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/sade": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
@@ -17807,17 +17642,6 @@
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz",
"integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w=="
},
"node_modules/split": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
"integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==",
"dependencies": {
"through": "2"
},
"engines": {
"node": "*"
}
},
"node_modules/split2": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
@@ -17849,121 +17673,6 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/start-server-and-test": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-2.0.1.tgz",
"integrity": "sha512-8PFo4DLLLCDMuS51/BEEtE1m9CAXw1LNVtZSS1PzkYQh6Qf9JUwM4huYeSoUumaaoAyuwYBwCa9OsrcpMqcOdQ==",
"dependencies": {
"arg": "^5.0.2",
"bluebird": "3.7.2",
"check-more-types": "2.24.0",
"debug": "4.3.4",
"execa": "5.1.1",
"lazy-ass": "1.6.0",
"ps-tree": "1.2.0",
"wait-on": "7.0.1"
},
"bin": {
"server-test": "src/bin/start.js",
"start-server-and-test": "src/bin/start.js",
"start-test": "src/bin/start.js"
},
"engines": {
"node": ">=16"
}
},
"node_modules/start-server-and-test/node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
},
"node_modules/start-server-and-test/node_modules/bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
"node_modules/start-server-and-test/node_modules/execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
"integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
"dependencies": {
"cross-spawn": "^7.0.3",
"get-stream": "^6.0.0",
"human-signals": "^2.1.0",
"is-stream": "^2.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^4.0.1",
"onetime": "^5.1.2",
"signal-exit": "^3.0.3",
"strip-final-newline": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/start-server-and-test/node_modules/human-signals": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"engines": {
"node": ">=10.17.0"
}
},
"node_modules/start-server-and-test/node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/start-server-and-test/node_modules/mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"engines": {
"node": ">=6"
}
},
"node_modules/start-server-and-test/node_modules/npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
"dependencies": {
"path-key": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/start-server-and-test/node_modules/onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dependencies": {
"mimic-fn": "^2.1.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/start-server-and-test/node_modules/strip-final-newline": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
"engines": {
"node": ">=6"
}
},
"node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
@@ -17972,14 +17681,6 @@
"node": ">= 0.6"
}
},
"node_modules/stream-combiner": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
"integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==",
"dependencies": {
"duplexer": "~0.1.1"
}
},
"node_modules/stream-shift": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
@@ -18525,7 +18226,8 @@
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
"dev": true
},
"node_modules/through2": {
"version": "4.0.2",
@@ -19786,24 +19488,6 @@
"d3-timer": "^3.0.1"
}
},
"node_modules/wait-on": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.0.1.tgz",
"integrity": "sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==",
"dependencies": {
"axios": "^0.27.2",
"joi": "^17.7.0",
"lodash": "^4.17.21",
"minimist": "^1.2.7",
"rxjs": "^7.8.0"
},
"bin": {
"wait-on": "bin/wait-on"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",

View File

@@ -4,12 +4,10 @@
"build": "turbo run build",
"dev": "turbo run dev --filter=@documenso/web --filter=@documenso/marketing",
"start": "cd apps && cd web && next start",
"test": "cd apps && cd web && npm run test:e2e",
"lint": "turbo run lint",
"format": "prettier --write \"**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts,mdx}\"",
"prepare": "husky install",
"commitlint": "commitlint --edit",
"ci": "turbo run build test:e2e lint",
"clean": "turbo run clean && rimraf node_modules"
},
"engines": {

View File

@@ -40,7 +40,7 @@ export const getStats = async ({ user }: GetStatsInput) => {
},
where: {
status: {
not: ExtendedDocumentStatus.DRAFT,
in: [ExtendedDocumentStatus.DRAFT, ExtendedDocumentStatus.PENDING],
},
Recipient: {
some: {

View File

@@ -1,41 +0,0 @@
import { prisma } from '@documenso/prisma';
export const deleteUserAndItsData = async (name: string) => {
const user = await prisma.user.findFirst({
where: {
name: {
contains: name,
},
},
});
if (!user) {
throw new Error(`User with name ${name} not found`);
}
const document = await prisma.document.findMany({
where: {
userId: user.id,
},
select: {
documentData: {
select: {
data: true,
},
},
},
});
return Promise.all([
await prisma.user.delete({
where: {
id: user.id,
},
}),
await prisma.documentData.deleteMany({
where: {
data: document[0]?.documentData.data,
},
}),
]);
};

View File

@@ -2,8 +2,13 @@
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
"dependsOn": [
"^build"
],
"outputs": [
".next/**",
"!.next/cache/**"
]
},
"lint": {},
"clean": {
@@ -12,26 +17,13 @@
"dev": {
"cache": false,
"persistent": true
},
"test:e2e": {
"dependsOn": ["^build"]
}
},
"globalDependencies": ["**/.env.*local"],
"globalDependencies": [
"**/.env.*local"
],
"globalEnv": [
"APP_VERSION",
"E2E_TEST_USERNAME",
"E2E_TEST_USER_EMAIL",
"E2E_TEST_USER_PASSWORD",
"E2E_TEST_SIGNER_NAME",
"E2E_TEST_SIGNER_EMAIL",
"E2E_TEST_SIGNING_SUBJECT",
"E2E_TEST_SIGNING_MESSAGE",
"E2E_TEST_AUTHENTICATE_USERNAME",
"E2E_TEST_AUTHENTICATE_USER_EMAIL",
"E2E_TEST_AUTHENTICATE_USER_PASSWORD",
"NEXTAUTH_URL",
"NEXTAUTH_SECRET",
"NEXT_PUBLIC_PROJECT",