Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build scripts
run: pnpm run build:scripts

- name: Run script to bump version & copy files
run: pnpm run release
id: version-bump
Expand Down
20 changes: 8 additions & 12 deletions apps/web/drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import { POSTGRES_ENVS } from '@/database/client';
import { defineConfig } from 'drizzle-kit';
import { defineVitNodeDrizzleConfig } from '@vitnode/core/drizzle.config';

const { url, ...rest } = POSTGRES_ENVS;
import { POSTGRES_URL, vitNodeApiConfig } from './src/vitnode.api.config';

export default defineConfig({
out: './src/database/migrations/',
// schema: ['./src/plugins/**/database/schema/*'],
schema: ['./src/database/schema/*'],
export default defineVitNodeDrizzleConfig({
vitNodeApiConfig,
out: './migrations/',
dialect: 'postgresql',
dbCredentials: process.env.POSTGRES_URL
? {
url,
}
: rest,
dbCredentials: {
url: POSTGRES_URL,
},
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "fd378528-22f1-4e30-9108-4e06020776ba",
"id": "b2e3a2e7-f9c3-449a-92a9-8010647fe22e",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
{
"idx": 0,
"version": "7",
"when": 1747245244787,
"tag": "0000_funny_korath",
"when": 1748527899355,
"tag": "0000_wide_absorbing_man",
"breakpoints": true
}
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Link } from '@vitnode/core/lib/navigation';

import { Test } from '@vitnode/blog/views/test';

Check warning on line 3 in apps/web/src/app/[locale]/(main)/(plugins)/(vitnode-blog)/blog/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Expected "@vitnode/blog/views/test" to come before "@vitnode/core/lib/navigation"

Check warning on line 3 in apps/web/src/app/[locale]/(main)/(plugins)/(vitnode-blog)/blog/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Extra spacing between "@vitnode/core/lib/navigation" and "@vitnode/blog/views/test" objects
import { TestClient } from '@vitnode/blog/views/test/client';
import { Link } from '@vitnode/core/lib/navigation';

export default function Page() {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Metadata } from 'next/dist/types';

import { SignInView } from '@vitnode/core/views/auth/sign-in/sign-in-view';
import { getTranslations } from 'next-intl/server';

import { SignInView } from '@vitnode/core/views/auth/sign-in/sign-in-view';

Check warning on line 5 in apps/web/src/app/[locale]/(main)/(plugins)/(vitnode-core)/login/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Expected "@vitnode/core/views/auth/sign-in/sign-in-view" to come before "next-intl/server"

Check warning on line 5 in apps/web/src/app/[locale]/(main)/(plugins)/(vitnode-core)/login/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Extra spacing between "next-intl/server" and "@vitnode/core/views/auth/sign-in/sign-in-view" objects

export const generateMetadata = async ({
locale,
}: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Metadata } from 'next/dist/types';

import { SignUpView } from '@vitnode/core/views/auth/sign-up/sign-up-view';
import { getTranslations } from 'next-intl/server';

import { SignUpView } from '@vitnode/core/views/auth/sign-up/sign-up-view';

Check warning on line 5 in apps/web/src/app/[locale]/(main)/(plugins)/(vitnode-core)/register/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Expected "@vitnode/core/views/auth/sign-up/sign-up-view" to come before "next-intl/server"

Check warning on line 5 in apps/web/src/app/[locale]/(main)/(plugins)/(vitnode-core)/register/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Extra spacing between "next-intl/server" and "@vitnode/core/views/auth/sign-up/sign-up-view" objects

export const generateMetadata = async ({
locale,
}: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { DashboardAdminView } from '@vitnode/core/views/admin/views/core/dashboard/dashboard-admin-view';

export default function Page() {
return <DashboardAdminView />;
}
23 changes: 0 additions & 23 deletions apps/web/src/database/client.ts

This file was deleted.

16 changes: 16 additions & 0 deletions apps/web/src/vitnode.api.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,25 @@ import { DiscordSSOApiPlugin } from '@vitnode/core/api/plugins/sso/discord';
import { FacebookSSOApiPlugin } from '@vitnode/core/api/plugins/sso/facebook';
import { GoogleSSOApiPlugin } from '@vitnode/core/api/plugins/sso/google';
import { buildApiConfig } from '@vitnode/core/vitnode.config';
import { drizzle } from 'drizzle-orm/postgres-js';

// import * as dotenv from 'dotenv';
// import { drizzle } from 'drizzle-orm/postgres-js';
// import { join } from 'path';

// dotenv.config({
// path: join(process.cwd(), '..', '..', '.env'),
// });

export const POSTGRES_URL =
process.env.POSTGRES_URL ?? 'postgresql://root:root@localhost:5432/vitnode';

export const vitNodeApiConfig = buildApiConfig({
plugins: [blogApiPlugin()],
dbProvider: drizzle({
connection: POSTGRES_URL,
casing: 'camelCase',
}),
emailProvider: NodemailerEmailPlugin({
from: process.env.NODE_MAILER_FROM,
host: process.env.NODE_MAILER_HOST,
Expand Down
4 changes: 4 additions & 0 deletions bump-version.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@ class FileCopyManager {
from: path.join(sourcePath, '.gitignore'),
to: path.join(destPath, '.gitignore'),
},
{
from: path.join(sourcePath, 'drizzle.config.ts'),
to: path.join(destPath, 'drizzle.config.ts'),
},
];

for (const { from, to } of files) {
Expand Down
38 changes: 38 additions & 0 deletions packages/create-vitnode-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# (VitNode) Create App

This package is a CLI tool to create a new VitNode app quickly.

Script based on [Create Next App](https://nextjs.org/).

<p align="center">
<br>
<a href="https://vitnode.com/" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_dark.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg">
<img alt="VitNode Logo" src="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg" width="400">
</picture>
</a>
<br>
<br>
</p>

## Usage

```bash
npx create-vitnode-app@latest
```

or

```bash
pnpm create vitnode-app@latest
```

## Options

| Option | Description |
| ------------------- | ---------------------------------------------------------- |
| `--package-manager` | Specify the package manager to use. Support `npm`, `pnpm`. |
| `--eslint` | Initialize with eslint config. |
| `--skip-install` | Skip installing packages after initializing the project. |
27 changes: 19 additions & 8 deletions packages/vitnode/scripts/prepare-database.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
/* eslint-disable no-console */

import { dbClient } from '@/database/client.js';
import { core_admin_permissions } from '@/database/schema/admins.js';
import {
core_languages,
core_languages_words,
} from '@/database/schema/languages.js';
import { core_moderators_permissions } from '@/database/schema/moderators.js';
import { core_roles } from '@/database/schema/roles.js';
import { core_admin_permissions } from '@/database/admins.js';
import { core_languages, core_languages_words } from '@/database/languages.js';
import { core_moderators_permissions } from '@/database/moderators.js';
import { core_roles } from '@/database/roles.js';
import * as dotenv from 'dotenv';
import { count } from 'drizzle-orm';
import { drizzle } from 'drizzle-orm/postgres-js';
import { join } from 'path';

import { runInteractiveShellCommand } from './run-interactive-shell-command.js';

dotenv.config({
path: join(process.cwd(), '..', '..', '.env'),
});

console.log(join(process.cwd(), '..', '..', '.env'));

const dbClient = drizzle({
connection:
process.env.POSTGRES_URL ?? 'postgresql://root:root@localhost:5432/vitnode',
casing: 'camelCase',
});

export const generateDatabaseMigrations = async () => {
try {
await runInteractiveShellCommand('npm', ['run', 'drizzle-kit', 'up']);
Expand Down
38 changes: 0 additions & 38 deletions packages/vitnode/scripts/prepare/prepare-files.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,13 @@
/* eslint-disable no-console */
import { existsSync } from 'fs';
import { cp, mkdir } from 'fs/promises';
import { join } from 'path';
import { dirname } from 'path';
import { fileURLToPath } from 'url';

import { preparePlugins } from './prepare-plugins';

const __dirname = dirname(fileURLToPath(import.meta.url));

const copyDatabase = async (pluginsPath: string) => {
const databasePath = join(__dirname, '..', '..', 'src', 'database');
if (!existsSync(databasePath)) {
console.log(
`⛔️ Database not found in 'src/database' directory. "${databasePath}"`,
);
process.exit(1);
}
const destinationPath = join(process.cwd(), 'src', 'database');
if (!existsSync(destinationPath)) {
await mkdir(destinationPath, { recursive: true });
}

// Copy files
await cp(databasePath, destinationPath, {
recursive: true,
filter: src => !src.endsWith('client.ts'),
});

// Copy client.ts if it doesn't exist
if (!existsSync(join(destinationPath, 'client.ts'))) {
await cp(
join(databasePath, 'client.ts'),
join(destinationPath, 'client.ts'),
);
}
};

export const prepareFiles = async ({
pluginsPath,
initMessage,
}: {
initMessage: string;
pluginsPath: string;
}) => {
console.log(`${initMessage} Preparing files...`);
await copyDatabase(pluginsPath);
await preparePlugins();
console.log(`${initMessage} \x1b[32mFiles prepared successfully.\x1b[0m`);
process.exit(0);
Expand Down
15 changes: 1 addition & 14 deletions packages/vitnode/scripts/scripts.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
#!/usr/bin/env node
/* eslint-disable no-console */
import { existsSync } from 'fs';
import { join } from 'path';

import { processPlugin } from './plugin.js';
import { prepareDatabase } from './prepare-database.js';
import { prepareFiles } from './prepare/prepare-files.js';

const initMessage = '\x1b[34m[VitNode]\x1b[0m';
const getPluginsPath = () => {
const pluginsPath = join(process.cwd(), 'src', 'plugins');
if (!existsSync(pluginsPath)) {
console.log(
`⛔️ Plugins not found in 'src/plugins' directory. "${pluginsPath}"`,
);
process.exit(1);
}

return pluginsPath;
};

const command = process.argv[2];
const flag = process.argv[3];
Expand All @@ -35,7 +22,7 @@ switch (command) {
break;

case 'prepare':
void prepareFiles({ pluginsPath: getPluginsPath(), initMessage });
void prepareFiles({ initMessage });
break;

default:
Expand Down
9 changes: 8 additions & 1 deletion packages/vitnode/src/api/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,16 @@ export function VitNodeAPI({
emailProvider: vitNodeApiConfig.emailProvider,
metadata: vitNodeConfig.metadata,
authorization: vitNodeApiConfig.authorization,
dbProvider: vitNodeApiConfig.dbProvider,
}),
);
app.use('/*/admin/*', globalAdminMiddleware());
app.use(async (c, next) => {
if (c.req.path.includes('/admin/')) {
return globalAdminMiddleware()(c, next);
}

return next();
});

app.onError(error => {
if (error instanceof HTTPException) {
Expand Down
9 changes: 5 additions & 4 deletions packages/vitnode/src/api/lib/get-user-ip.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { HonoRequest } from 'hono';
import type { Context, Input } from 'hono';
import type { Env } from 'hono';

export const getUserIp = (req: HonoRequest): string => {
const ip: string = req.header('x-forwarded-for')?.toString() ?? '0.0.0.0';
export function getUserIp<T extends Env>(c: Context<T, '/', Input>): string {
const ip: string = c.req.header('x-forwarded-for')?.toString() ?? '0.0.0.0';

if (ip === '0.0.0.0') {
// eslint-disable-next-line no-console
Expand All @@ -11,4 +12,4 @@ export const getUserIp = (req: HonoRequest): string => {
}

return ip;
};
}
8 changes: 6 additions & 2 deletions packages/vitnode/src/api/lib/with-pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,26 @@ import type {
PgTableWithColumns,
TableConfig,
} from 'drizzle-orm/pg-core';
import type { Context, Env, Input } from 'hono';

import { dbClient } from '@/database/client';
import { z } from '@hono/zod-openapi';
import { and, asc, count, desc, gt, lt } from 'drizzle-orm';

export async function withPagination<
QueryMin extends Record<string, unknown>,
T extends TableConfig,
Primary extends ColumnBaseConfig<'number', string>,
E extends Env,
>({
query,
table,
params,
where: whereFromParams,
primaryCursor,
orderBy: orderByFromParams,
c,
}: {
c: Context<E, '/', Input>;
orderBy: {
column: PgColumn;
order: 'asc' | 'desc';
Expand Down Expand Up @@ -103,7 +106,8 @@ export async function withPagination<
}

// Get total count
const [{ count: totalCount }] = await dbClient
const [{ count: totalCount }] = await c
.get('db')
.select({ count: count() })
.from(table as PgTable)
.where(whereFromParams);
Expand Down
Loading