feat: open page api
This commit is contained in:
@@ -1,36 +1 @@
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3002](http://localhost:3002) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||
# @documenso/documentation
|
||||
|
||||
40
apps/openpage-api/.gitignore
vendored
Normal file
40
apps/openpage-api/.gitignore
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/versions
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# env files (can opt-in for commiting if needed)
|
||||
.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
1
apps/openpage-api/README.md
Normal file
1
apps/openpage-api/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# @documenso/openpage-api
|
||||
12
apps/openpage-api/app/github/forks/route.ts
Normal file
12
apps/openpage-api/app/github/forks/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
import { requestHandler } from '@/app/request-handler';
|
||||
|
||||
export const GET = requestHandler(async () => {
|
||||
const res = await fetch('https://api.github.com/repos/documenso/documenso');
|
||||
const { forks_count } = await res.json();
|
||||
|
||||
return NextResponse.json({
|
||||
data: forks_count,
|
||||
});
|
||||
});
|
||||
14
apps/openpage-api/app/github/issues/route.ts
Normal file
14
apps/openpage-api/app/github/issues/route.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
import { requestHandler } from '@/app/request-handler';
|
||||
|
||||
export const GET = requestHandler(async () => {
|
||||
const res = await fetch(
|
||||
'https://api.github.com/search/issues?q=repo:documenso/documenso+type:issue+state:open&page=0&per_page=1',
|
||||
);
|
||||
const { total_count } = await res.json();
|
||||
|
||||
return NextResponse.json({
|
||||
data: total_count,
|
||||
});
|
||||
});
|
||||
14
apps/openpage-api/app/github/prs/route.ts
Normal file
14
apps/openpage-api/app/github/prs/route.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
import { requestHandler } from '@/app/request-handler';
|
||||
|
||||
export const GET = requestHandler(async () => {
|
||||
const res = await fetch(
|
||||
'https://api.github.com/search/issues?q=repo:documenso/documenso/+is:pr+merged:>=2010-01-01&page=0&per_page=1',
|
||||
);
|
||||
const { total_count } = await res.json();
|
||||
|
||||
return NextResponse.json({
|
||||
data: total_count,
|
||||
});
|
||||
});
|
||||
17
apps/openpage-api/app/github/route.ts
Normal file
17
apps/openpage-api/app/github/route.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
const paths = [
|
||||
{ path: '/forks', description: 'GitHub Forks' },
|
||||
{ path: '/stars', description: 'GitHub Stars' },
|
||||
{ path: '/issues', description: 'GitHub Merged Issues' },
|
||||
{ path: '/prs', description: 'GitHub Pull Request' },
|
||||
];
|
||||
|
||||
export function GET(request: NextRequest) {
|
||||
const url = request.nextUrl.toString();
|
||||
const apis = paths.map(({ path, description }) => {
|
||||
return { path: url + path, description };
|
||||
});
|
||||
|
||||
return NextResponse.json(apis);
|
||||
}
|
||||
12
apps/openpage-api/app/github/stars/route.ts
Normal file
12
apps/openpage-api/app/github/stars/route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
import { requestHandler } from '@/app/request-handler';
|
||||
|
||||
export const GET = requestHandler(async () => {
|
||||
const res = await fetch('https://api.github.com/repos/documenso/documenso');
|
||||
const { stargazers_count } = await res.json();
|
||||
|
||||
return NextResponse.json({
|
||||
data: stargazers_count,
|
||||
});
|
||||
});
|
||||
43
apps/openpage-api/app/request-handler.ts
Normal file
43
apps/openpage-api/app/request-handler.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { NextRequest } from 'next/server';
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
type RouteHandler<T = Record<string, string | string[]>> = (
|
||||
req: NextRequest,
|
||||
ctx: { params: T },
|
||||
) => Promise<Response> | Response;
|
||||
|
||||
function isAllowedOrigin(req: NextRequest): boolean {
|
||||
const referer = req.headers.get('referer');
|
||||
const host = req.headers.get('host');
|
||||
|
||||
if (referer && host) {
|
||||
const refererUrl = new URL(referer);
|
||||
return refererUrl.host === host;
|
||||
}
|
||||
|
||||
if (host?.includes('localhost')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function requestHandler<T = Record<string, string | string[]>>(
|
||||
handler: RouteHandler<T>,
|
||||
): RouteHandler<T> {
|
||||
return async (req: NextRequest, ctx: { params: T }) => {
|
||||
try {
|
||||
if (!isAllowedOrigin(req)) {
|
||||
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
|
||||
}
|
||||
|
||||
const result = await handler(req, ctx);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
|
||||
}
|
||||
};
|
||||
}
|
||||
20
apps/openpage-api/app/route.ts
Normal file
20
apps/openpage-api/app/route.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { type NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
const paths = [{ path: 'github', description: 'GitHub Data' }];
|
||||
|
||||
export function GET(request: NextRequest) {
|
||||
const url = request.nextUrl.toString();
|
||||
const apis = paths.map(({ path, description }) => {
|
||||
return { path: url + path, description };
|
||||
});
|
||||
|
||||
return NextResponse.json(apis, {
|
||||
status: 200,
|
||||
headers: {
|
||||
// TODO: Update for marketing page
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type',
|
||||
},
|
||||
});
|
||||
}
|
||||
4
apps/openpage-api/next.config.js
Normal file
4
apps/openpage-api/next.config.js
Normal file
@@ -0,0 +1,4 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
|
||||
module.exports = nextConfig;
|
||||
21
apps/openpage-api/package.json
Normal file
21
apps/openpage-api/package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@documenso/openpage-api",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3003",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint:fix": "next lint --fix",
|
||||
"clean": "rimraf .next && rimraf node_modules",
|
||||
"copy:pdfjs": "node ../../scripts/copy-pdfjs.cjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "14.2.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.16.5",
|
||||
"@types/react": "18.3.5",
|
||||
"typescript": "5.5.4"
|
||||
}
|
||||
}
|
||||
27
apps/openpage-api/tsconfig.json
Normal file
27
apps/openpage-api/tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
54
package-lock.json
generated
54
package-lock.json
generated
@@ -439,6 +439,56 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"apps/openpage-api": {
|
||||
"name": "@documenso/openpage-api",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"next": "14.2.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.16.5",
|
||||
"@types/react": "18.3.5",
|
||||
"typescript": "5.5.4"
|
||||
}
|
||||
},
|
||||
"apps/openpage-api/node_modules/@types/node": {
|
||||
"version": "20.16.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz",
|
||||
"integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
},
|
||||
"apps/openpage-api/node_modules/@types/react": {
|
||||
"version": "18.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz",
|
||||
"integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"apps/openpage-api/node_modules/typescript": {
|
||||
"version": "5.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
|
||||
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"apps/openpage-api/node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"dev": true
|
||||
},
|
||||
"apps/web": {
|
||||
"name": "@documenso/web",
|
||||
"version": "1.7.2-rc.1",
|
||||
@@ -2671,6 +2721,10 @@
|
||||
"nodemailer": "^6.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@documenso/openpage-api": {
|
||||
"resolved": "apps/openpage-api",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@documenso/pdf-sign": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@documenso/pdf-sign/-/pdf-sign-0.1.0.tgz",
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"dev:web": "turbo run dev --filter=@documenso/web",
|
||||
"dev:marketing": "turbo run dev --filter=@documenso/marketing",
|
||||
"dev:docs": "turbo run dev --filter=@documenso/documentation",
|
||||
"dev:openpage-api": "turbo run dev --filter=@documenso/openpage-api",
|
||||
"start": "turbo run start --filter=@documenso/web --filter=@documenso/marketing --filter=@documenso/documentation",
|
||||
"lint": "turbo run lint",
|
||||
"lint:fix": "turbo run lint:fix",
|
||||
|
||||
Reference in New Issue
Block a user