create-vitnode-app 1.2.0-canary.9 → 2.0.0-canary.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/README.md +59 -18
- package/copy-of-vitnode-app/.vscode/settings.json +10 -0
- package/copy-of-vitnode-app/README.md +62 -0
- package/copy-of-vitnode-app/api/.gitignore_template +32 -0
- package/copy-of-vitnode-app/api/drizzle.config.ts +12 -0
- package/copy-of-vitnode-app/api/src/index.ts +27 -0
- package/copy-of-vitnode-app/api/src/vitnode.api.config.ts +39 -0
- package/copy-of-vitnode-app/api/tsconfig.json +17 -0
- package/copy-of-vitnode-app/api-bun/src/index.ts +16 -0
- package/copy-of-vitnode-app/api-single-app/drizzle.config.ts +12 -0
- package/copy-of-vitnode-app/api-single-app/src/routes/api/$.ts +10 -0
- package/copy-of-vitnode-app/api-single-app/src/server/api-bridge.ts +11 -0
- package/copy-of-vitnode-app/api-single-app/src/server/vitnode-api.server.ts +29 -0
- package/copy-of-vitnode-app/api-single-app/src/vitnode.api.config.ts +28 -0
- package/copy-of-vitnode-app/docker/docker-compose.yml +32 -0
- package/copy-of-vitnode-app/eslint/.prettierrc.mjs +1 -1
- package/copy-of-vitnode-app/eslint/eslint.config.mjs +18 -2
- package/copy-of-vitnode-app/{root → eslint-react}/.prettierrc.mjs +1 -1
- package/copy-of-vitnode-app/eslint-react/eslint.config.mjs +19 -0
- package/copy-of-vitnode-app/monorepo/.gitignore_template +41 -0
- package/copy-of-vitnode-app/monorepo/apps/api/.env.example +12 -0
- package/copy-of-vitnode-app/monorepo/apps/web/.env.example +1 -0
- package/copy-of-vitnode-app/monorepo/turbo.json +53 -0
- package/copy-of-vitnode-app/root/.env.example +9 -5
- package/copy-of-vitnode-app/root/.gitignore_template +41 -0
- package/copy-of-vitnode-app/root/global.d.ts +10 -0
- package/copy-of-vitnode-app/root/src/components/admin-shell.tsx +21 -0
- package/copy-of-vitnode-app/root/src/components/main-footer.tsx +44 -0
- package/copy-of-vitnode-app/root/src/components/main-header.tsx +4 -0
- package/copy-of-vitnode-app/root/src/lib/i18n.ts +37 -0
- package/copy-of-vitnode-app/root/src/locales/app.ts +4 -0
- package/copy-of-vitnode-app/root/src/locales/packages.ts +10 -0
- package/copy-of-vitnode-app/root/src/router.tsx +71 -0
- package/copy-of-vitnode-app/root/src/routes/__root.tsx +109 -0
- package/copy-of-vitnode-app/root/src/routes/_admin/admin.core.index.tsx +20 -0
- package/copy-of-vitnode-app/root/src/routes/_admin.tsx +65 -0
- package/copy-of-vitnode-app/root/src/routes/_main/index.tsx +196 -0
- package/copy-of-vitnode-app/root/src/routes/_main.tsx +29 -0
- package/copy-of-vitnode-app/root/src/server/messages.server.ts +8 -0
- package/copy-of-vitnode-app/root/src/start.ts +5 -0
- package/copy-of-vitnode-app/root/src/styles.css +149 -0
- package/copy-of-vitnode-app/root/src/vitnode.config.ts +20 -0
- package/copy-of-vitnode-app/root/src/vitnode.server.config.ts +12 -0
- package/copy-of-vitnode-app/root/tsconfig.json +29 -16
- package/copy-of-vitnode-app/root/tsr.config.json +3 -0
- package/copy-of-vitnode-app/root/vite.config.ts +22 -0
- package/copy-of-vitnode-plugin/root/.swcrc +26 -0
- package/copy-of-vitnode-plugin/root/global.d.ts +21 -0
- package/copy-of-vitnode-plugin/root/npmignore.template +17 -0
- package/copy-of-vitnode-plugin/root/tsconfig.build.json +5 -0
- package/copy-of-vitnode-plugin/root/tsconfig.json +25 -0
- package/dist/src/create/create-package-json.js +266 -56
- package/dist/src/create/create-vitnode.js +191 -28
- package/dist/src/create/package-versions.js +49 -0
- package/dist/src/helpers/get-available-package-managers.js +6 -6
- package/dist/src/helpers/get-package-json.js +2 -2
- package/dist/src/helpers/get-package-manager-from-root.js +15 -0
- package/dist/src/helpers/get-vitnode-package-version.js +9 -0
- package/dist/src/helpers/init-git.js +38 -0
- package/dist/src/helpers/init-vitnode.js +33 -0
- package/dist/src/helpers/install-dependencies.js +55 -15
- package/dist/src/helpers/is-folder-empty.js +25 -26
- package/dist/src/helpers/is-online.js +16 -16
- package/dist/src/helpers/is-writeable.js +3 -3
- package/dist/src/helpers/spawn-command.js +7 -0
- package/dist/src/helpers/validate-pkg.js +1 -1
- package/dist/src/helpers/with-If.js +1 -0
- package/dist/src/index.js +30 -26
- package/dist/src/plugin/create/add-plugin-to-config.js +231 -0
- package/dist/src/plugin/create/add-plugin-to-workspace.js +74 -0
- package/dist/src/plugin/create/create-package-json.js +55 -0
- package/dist/src/plugin/create/create-plugin-vitnode.js +101 -0
- package/dist/src/plugin/create/route-templates.js +186 -0
- package/dist/src/plugin/index.js +17 -6
- package/dist/src/plugin/questions.js +14 -0
- package/dist/src/plugin/validation.js +76 -0
- package/dist/src/prepare/prepare.js +11 -8
- package/dist/src/questions.js +59 -15
- package/dist/src/validation.js +15 -15
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +22 -12
- package/copy-of-vitnode-app/root/README.md +0 -1
- package/copy-of-vitnode-app/root/drizzle.config.ts +0 -12
- package/copy-of-vitnode-app/root/gitignore_template +0 -43
- package/copy-of-vitnode-app/root/next.config.ts +0 -11
- package/copy-of-vitnode-app/root/postcss.config.mjs +0 -8
- package/copy-of-vitnode-app/root/src/app/[locale]/(main)/[...rest]/page.tsx +0 -5
- package/copy-of-vitnode-app/root/src/app/[locale]/(main)/layout.tsx +0 -10
- package/copy-of-vitnode-app/root/src/app/[locale]/(main)/not-found.tsx +0 -5
- package/copy-of-vitnode-app/root/src/app/[locale]/(main)/page.tsx +0 -113
- package/copy-of-vitnode-app/root/src/app/[locale]/admin/(auth)/layout.tsx +0 -10
- package/copy-of-vitnode-app/root/src/app/[locale]/admin/not-found.tsx +0 -5
- package/copy-of-vitnode-app/root/src/app/[locale]/admin/page.tsx +0 -5
- package/copy-of-vitnode-app/root/src/app/[locale]/layout.tsx +0 -36
- package/copy-of-vitnode-app/root/src/app/api/[...route]/route.ts +0 -18
- package/copy-of-vitnode-app/root/src/app/favicon.ico +0 -0
- package/copy-of-vitnode-app/root/src/app/global-error.tsx +0 -27
- package/copy-of-vitnode-app/root/src/app/global.css +0 -128
- package/copy-of-vitnode-app/root/src/app/layout.tsx +0 -9
- package/copy-of-vitnode-app/root/src/app/not-found.tsx +0 -13
- package/copy-of-vitnode-app/root/src/vitnode.api.config.ts +0 -5
- package/dist/tsconfig.tsbuildinfo +0 -1
package/LICENSE.md
CHANGED
package/README.md
CHANGED
|
@@ -1,44 +1,85 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Create VitNode App
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Script based on [Create Next App](https://nextjs.org/).
|
|
3
|
+
`create-vitnode-app` scaffolds a TanStack Start and Hono VitNode application,
|
|
4
|
+
or an installable plugin for an existing VitNode workspace.
|
|
6
5
|
|
|
7
6
|
<p align="center">
|
|
8
|
-
<br>
|
|
9
7
|
<a href="https://vitnode.com/" target="_blank">
|
|
10
8
|
<picture>
|
|
11
9
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_dark.svg">
|
|
12
10
|
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg">
|
|
13
|
-
<img alt="VitNode
|
|
11
|
+
<img alt="VitNode" src="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg" width="400">
|
|
14
12
|
</picture>
|
|
15
13
|
</a>
|
|
16
|
-
<br>
|
|
17
|
-
<br>
|
|
18
14
|
</p>
|
|
19
15
|
|
|
20
|
-
##
|
|
16
|
+
## Create an app
|
|
17
|
+
|
|
18
|
+
### Bun
|
|
21
19
|
|
|
22
20
|
```bash
|
|
23
|
-
|
|
21
|
+
bun create vitnode-app@latest
|
|
24
22
|
```
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
### pnpm
|
|
27
25
|
|
|
28
26
|
```bash
|
|
29
27
|
pnpm create vitnode-app@latest
|
|
30
28
|
```
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
### npm
|
|
33
31
|
|
|
34
32
|
```bash
|
|
35
|
-
|
|
33
|
+
npm create vitnode-app@latest
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Choose Turborepo during setup if you will build plugins. It gives your project a
|
|
37
|
+
workspace root and a `plugins/*` home.
|
|
38
|
+
|
|
39
|
+
## Create a plugin
|
|
40
|
+
|
|
41
|
+
Run this from an existing VitNode workspace, then enter the plugin package name
|
|
42
|
+
when prompted:
|
|
43
|
+
|
|
44
|
+
### Bun
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
bun create vitnode-app@latest --plugin
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### pnpm
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pnpm create vitnode-app@latest --plugin
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### npm
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm create vitnode-app@latest -- --plugin
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The generator creates the package and adds its workspace dependency. Enable the
|
|
63
|
+
feature by registering it in the host’s `vitnode.config.ts`:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { myPlugin } from '@acme/my-plugin/config'
|
|
67
|
+
|
|
68
|
+
plugins: [myPlugin()]
|
|
36
69
|
```
|
|
37
70
|
|
|
38
71
|
## Options
|
|
39
72
|
|
|
40
|
-
| Option
|
|
41
|
-
|
|
|
42
|
-
| `--package-manager` |
|
|
43
|
-
| `--eslint`
|
|
44
|
-
| `--skip-install`
|
|
73
|
+
| Option | Description |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `--package-manager` | Choose `npm` or `pnpm` for the generated project. |
|
|
76
|
+
| `--eslint` | Include ESLint and Prettier configuration. |
|
|
77
|
+
| `--skip-install` | Skip dependency installation after scaffolding. |
|
|
78
|
+
| `--skip-git` | Skip initializing a git repository (created on `main` after install). |
|
|
79
|
+
| `--mode` | Choose `singleApp`, `apiMonorepo`, or `onlyApi`. |
|
|
80
|
+
| `--monorepo` | Create a workspace layout for plugins and multiple applications. |
|
|
81
|
+
| `--docker` | Include local Docker services. |
|
|
82
|
+
| `--plugin` | Create a VitNode plugin package. |
|
|
83
|
+
|
|
84
|
+
Read the [VitNode documentation](https://vitnode.com/docs/dev) for setup,
|
|
85
|
+
plugins, deployment, and AdminCP guides.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cSpell.words": [
|
|
3
|
+
"vitnode"
|
|
4
|
+
],
|
|
5
|
+
"github.copilot.chat.commitMessageGeneration.instructions": [
|
|
6
|
+
{
|
|
7
|
+
"text": "Follow the Conventional Commits format strictly for commit messages. Use the structure below:\n\n```\n<type>[optional scope]: <gitmoji> <description>\n```\n\nGuidelines:\n\n1. **Type and Scope**: Choose an appropriate type (e.g., `feat`, `fix`, `refactor`, `docs`) and optional scope to describe the affected module or feature.\n\n2. **Gitmoji**: Include a relevant `gitmoji` that best represents the nature of the change.\n\n3. **Description**: Write a concise, informative description in the header; use backticks if referencing code or specific terms.\n\nCommit messages should be clear, informative, and professional, aiding readability and project tracking."
|
|
8
|
+
}
|
|
9
|
+
]
|
|
10
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<a href="https://vitnode.com/" target="_blank">
|
|
4
|
+
<picture>
|
|
5
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_dark.svg">
|
|
6
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg">
|
|
7
|
+
<img alt="VitNode Logo" src="https://raw.githubusercontent.com/VitNode/vitnode/canary/assets/logo/vitnode_logo_light.svg" width="400">
|
|
8
|
+
</picture>
|
|
9
|
+
</a>
|
|
10
|
+
<br>
|
|
11
|
+
<br>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
# VitNode App
|
|
15
|
+
|
|
16
|
+
This is a basic template for a [VitNode](https://vitnode.com/) app.
|
|
17
|
+
|
|
18
|
+
## Getting Started
|
|
19
|
+
|
|
20
|
+
To get started, run the following commands:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm i
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Open {{START_URLS}} with your browser to see the result.
|
|
27
|
+
|
|
28
|
+
## Development
|
|
29
|
+
|
|
30
|
+
To start the development server, you need to create a `.env` file from the provided `.env.example` file.
|
|
31
|
+
|
|
32
|
+
In the `development` environment, you can just copy and paste the content of `.env.example` to `.env`.
|
|
33
|
+
|
|
34
|
+
### Development server
|
|
35
|
+
|
|
36
|
+
To start the development server, run the following command:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm dev
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Configuration
|
|
43
|
+
|
|
44
|
+
Two files, and the line between them is one question: may a browser hold this?
|
|
45
|
+
|
|
46
|
+
| File | Holds |
|
|
47
|
+
| :----------------------------- | :----------------------------------------------------------------------------------------------------------------------- |
|
|
48
|
+
| `src/vitnode.config.ts` | locales, metadata, theme, `debug`, enabled plugin ids - plain data, read by the browser, the server, and your Vite build |
|
|
49
|
+
| `src/vitnode.server.config.ts` | message loaders - server only |
|
|
50
|
+
|
|
51
|
+
Add a language to `i18n.locales` in the shared config; register the files that
|
|
52
|
+
translate it in `src/locales/packages.ts` (a package's own translations) or
|
|
53
|
+
`src/locales/app.ts` (your rewordings). `pnpm vitnode i18n:create de Deutsch`
|
|
54
|
+
does all three.
|
|
55
|
+
|
|
56
|
+
`src/start.ts` is one call to `createVitNodeStart`, which installs CSRF
|
|
57
|
+
protection for server functions, canonical locale redirects with the
|
|
58
|
+
remembered-locale cookie, and the `private, no-store` directive every rendered
|
|
59
|
+
document needs. Add your own request middleware with `requestMiddleware` - it
|
|
60
|
+
runs after all of it.
|
|
61
|
+
|
|
62
|
+
See [Configuration](https://vitnode.com/docs/dev/configuration).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules
|
|
3
|
+
|
|
4
|
+
# Turbo
|
|
5
|
+
.turbo
|
|
6
|
+
|
|
7
|
+
# Test & Build
|
|
8
|
+
/coverage
|
|
9
|
+
/desc
|
|
10
|
+
*.tsbuildinfo
|
|
11
|
+
|
|
12
|
+
# Misc
|
|
13
|
+
.DS_Store
|
|
14
|
+
*.pem
|
|
15
|
+
/.pnp
|
|
16
|
+
.pnp.js
|
|
17
|
+
npm-debug.log*
|
|
18
|
+
yarn-debug.log*
|
|
19
|
+
yarn-error.log*
|
|
20
|
+
|
|
21
|
+
# Local env files
|
|
22
|
+
.env
|
|
23
|
+
.env.local
|
|
24
|
+
.env.development.local
|
|
25
|
+
.env.test.local
|
|
26
|
+
.env.production.local
|
|
27
|
+
|
|
28
|
+
# Others
|
|
29
|
+
.vercel
|
|
30
|
+
|
|
31
|
+
# Local storage adapter uploads
|
|
32
|
+
/public/uploads
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineVitNodeDrizzleConfig } from "@vitnode/core/drizzle.config";
|
|
2
|
+
|
|
3
|
+
import { POSTGRES_URL, vitNodeApiConfig } from "./src/vitnode.api.config";
|
|
4
|
+
|
|
5
|
+
export default defineVitNodeDrizzleConfig({
|
|
6
|
+
vitNodeApiConfig,
|
|
7
|
+
out: "./migrations/",
|
|
8
|
+
dialect: "postgresql",
|
|
9
|
+
dbCredentials: {
|
|
10
|
+
url: POSTGRES_URL,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { serve } from "@hono/node-server";
|
|
2
|
+
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
3
|
+
import { VitNodeAPI } from "@vitnode/core/api/config";
|
|
4
|
+
|
|
5
|
+
import { vitNodeApiConfig } from "./vitnode.api.config.js";
|
|
6
|
+
|
|
7
|
+
const app = new OpenAPIHono().basePath("/api");
|
|
8
|
+
|
|
9
|
+
VitNodeAPI({
|
|
10
|
+
app,
|
|
11
|
+
vitNodeApiConfig,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
serve(
|
|
15
|
+
{
|
|
16
|
+
fetch: app.fetch,
|
|
17
|
+
port: 8000,
|
|
18
|
+
},
|
|
19
|
+
info => {
|
|
20
|
+
const initMessage = "\x1b[34m[VitNode]\x1b[0m";
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line no-console
|
|
23
|
+
console.log(
|
|
24
|
+
`${initMessage} API server is running on http://localhost:${info.port}`,
|
|
25
|
+
);
|
|
26
|
+
},
|
|
27
|
+
);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { buildApiConfig } from "@vitnode/core/vitnode.config";
|
|
2
|
+
import { config } from "dotenv";
|
|
3
|
+
import { coreRelations } from "@vitnode/core/database/relations";
|
|
4
|
+
import { drizzle } from "drizzle-orm/postgres-js";
|
|
5
|
+
|
|
6
|
+
config({
|
|
7
|
+
quiet: true,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const POSTGRES_URL =
|
|
11
|
+
process.env.POSTGRES_URL ?? "postgresql://root:root@localhost:5432/vitnode";
|
|
12
|
+
|
|
13
|
+
export const vitNodeApiConfig = buildApiConfig({
|
|
14
|
+
plugins: [],
|
|
15
|
+
|
|
16
|
+
i18n: {
|
|
17
|
+
defaultLocale: "en",
|
|
18
|
+
locales: [{ code: "en", name: "English" }],
|
|
19
|
+
/**
|
|
20
|
+
* Explicit, because this API renders emails on a server: without one, dates
|
|
21
|
+
* format in whatever zone the host happens to run in.
|
|
22
|
+
*/
|
|
23
|
+
timeZone: "UTC",
|
|
24
|
+
},
|
|
25
|
+
dbProvider: drizzle({
|
|
26
|
+
connection: POSTGRES_URL,
|
|
27
|
+
relations: coreRelations,
|
|
28
|
+
}),
|
|
29
|
+
// Redis is opt-in: only enabled when REDIS_URL is set. Without it the cache
|
|
30
|
+
// is a no-op, the rate limiter uses in-memory storage, and WebSockets run in
|
|
31
|
+
// single-instance mode.
|
|
32
|
+
redis: process.env.REDIS_URL
|
|
33
|
+
? { url: process.env.REDIS_URL, password: process.env.REDIS_PASSWORD }
|
|
34
|
+
: undefined,
|
|
35
|
+
metadata: {
|
|
36
|
+
title: "VitNode API",
|
|
37
|
+
shortTitle: "VitNode",
|
|
38
|
+
},
|
|
39
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"extends": "@vitnode/config/tsconfig",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "NodeNext",
|
|
7
|
+
"rootDir": "./",
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"incremental": false,
|
|
10
|
+
"types": ["node"],
|
|
11
|
+
"paths": {
|
|
12
|
+
"@/*": ["./src/*"]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"include": ["src", "global.d.ts"],
|
|
16
|
+
"exclude": ["node_modules"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
|
+
import { VitNodeAPI } from "@vitnode/core/api/config";
|
|
3
|
+
|
|
4
|
+
import { vitNodeApiConfig } from "./vitnode.api.config.js";
|
|
5
|
+
|
|
6
|
+
const app = new OpenAPIHono().basePath("/api");
|
|
7
|
+
|
|
8
|
+
VitNodeAPI({
|
|
9
|
+
app,
|
|
10
|
+
vitNodeApiConfig,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
port: 8000,
|
|
15
|
+
fetch: app.fetch,
|
|
16
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineVitNodeDrizzleConfig } from "@vitnode/core/drizzle.config";
|
|
2
|
+
|
|
3
|
+
import { POSTGRES_URL, vitNodeApiConfig } from "./src/vitnode.api.config";
|
|
4
|
+
|
|
5
|
+
export default defineVitNodeDrizzleConfig({
|
|
6
|
+
vitNodeApiConfig,
|
|
7
|
+
out: "./migrations/",
|
|
8
|
+
dialect: "postgresql",
|
|
9
|
+
dbCredentials: {
|
|
10
|
+
url: POSTGRES_URL,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
+
|
|
3
|
+
import { apiBridge } from "@/server/vitnode-api.server";
|
|
4
|
+
|
|
5
|
+
export const Route = createFileRoute("/api/$")({
|
|
6
|
+
server: {
|
|
7
|
+
handlers: ({ createHandlers }) =>
|
|
8
|
+
createHandlers({ ANY: async ({ request }) => apiBridge(request) }),
|
|
9
|
+
},
|
|
10
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
export type ApiBridge = (request: Request) => Promise<Response> | Response
|
|
3
|
+
|
|
4
|
+
interface FetchableApp {
|
|
5
|
+
fetch: (request: Request) => Promise<Response> | Response
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const createApiBridge =
|
|
9
|
+
(app: FetchableApp): ApiBridge =>
|
|
10
|
+
async (request) =>
|
|
11
|
+
app.fetch(request)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import "@tanstack/react-start/server-only";
|
|
2
|
+
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
3
|
+
import { VitNodeAPI } from "@vitnode/core/api/config";
|
|
4
|
+
|
|
5
|
+
import { createApiBridge } from "@/server/api-bridge";
|
|
6
|
+
import { vitNodeApiConfig } from "@/vitnode.api.config";
|
|
7
|
+
|
|
8
|
+
// The same two lines `apps/api` and `apps/docs` run. `basePath("/api")` is what
|
|
9
|
+
// makes the mount point part of the API's own routing, so every path the plugins
|
|
10
|
+
// register - `/api/@vitnode/core/...` - resolves identically here.
|
|
11
|
+
const createVitNodeApi = () => {
|
|
12
|
+
const app = new OpenAPIHono().basePath("/api");
|
|
13
|
+
|
|
14
|
+
VitNodeAPI({ app, vitNodeApiConfig });
|
|
15
|
+
|
|
16
|
+
return app;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// `VitNodeAPI` is a boot step, not a request step: it opens the Redis client,
|
|
20
|
+
// starts the cron scheduler and registers every plugin route. Vite re-evaluates
|
|
21
|
+
// server modules on HMR, so the instance is parked on `globalThis` to keep one
|
|
22
|
+
// API per process instead of one per edit.
|
|
23
|
+
const cache = globalThis as typeof globalThis & {
|
|
24
|
+
__vitnodeApi?: ReturnType<typeof createVitNodeApi>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const vitNodeApi = (cache.__vitnodeApi ??= createVitNodeApi());
|
|
28
|
+
|
|
29
|
+
export const apiBridge = createApiBridge(vitNodeApi);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { buildApiConfig } from "@vitnode/core/vitnode.config";
|
|
2
|
+
import { coreRelations } from "@vitnode/core/database/relations";
|
|
3
|
+
import { drizzle } from "drizzle-orm/postgres-js";
|
|
4
|
+
|
|
5
|
+
import { vitNodeConfig } from "./vitnode.config";
|
|
6
|
+
|
|
7
|
+
export const POSTGRES_URL =
|
|
8
|
+
process.env.POSTGRES_URL ?? "postgresql://root:root@localhost:5432/vitnode";
|
|
9
|
+
|
|
10
|
+
export const vitNodeApiConfig = buildApiConfig({
|
|
11
|
+
metadata: {
|
|
12
|
+
title: "VitNode",
|
|
13
|
+
shortTitle: "VitNode",
|
|
14
|
+
},
|
|
15
|
+
plugins: [],
|
|
16
|
+
|
|
17
|
+
i18n: vitNodeConfig.i18n,
|
|
18
|
+
dbProvider: drizzle({
|
|
19
|
+
connection: POSTGRES_URL,
|
|
20
|
+
relations: coreRelations,
|
|
21
|
+
}),
|
|
22
|
+
// Redis is opt-in: only enabled when REDIS_URL is set. Without it the cache
|
|
23
|
+
// is a no-op, the rate limiter uses in-memory storage, and WebSockets run in
|
|
24
|
+
// single-instance mode.
|
|
25
|
+
redis: process.env.REDIS_URL
|
|
26
|
+
? { url: process.env.REDIS_URL, password: process.env.REDIS_PASSWORD }
|
|
27
|
+
: undefined,
|
|
28
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
services:
|
|
2
|
+
database:
|
|
3
|
+
container_name: vitnode_postgres_dev
|
|
4
|
+
image: postgres:17.5-alpine
|
|
5
|
+
restart: unless-stopped
|
|
6
|
+
environment:
|
|
7
|
+
POSTGRES_USER: ${POSTGRES_USER-root}
|
|
8
|
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD-root}
|
|
9
|
+
POSTGRES_DB: ${POSTGRES_NAME-vitnode}
|
|
10
|
+
volumes:
|
|
11
|
+
- ./docker/dev:/var/lib/postgresql/data
|
|
12
|
+
ports:
|
|
13
|
+
# Loopback only. These are development containers with a default password
|
|
14
|
+
# of `root`, and `'5432:5432'` publishes them on every interface the host
|
|
15
|
+
# has - which on a laptop is whatever café or office network it is joined
|
|
16
|
+
# to, and on a VPS is the internet.
|
|
17
|
+
- '127.0.0.1:5432:5432'
|
|
18
|
+
networks:
|
|
19
|
+
- vitnode_dev
|
|
20
|
+
|
|
21
|
+
cache:
|
|
22
|
+
container_name: vitnode_redis_dev
|
|
23
|
+
image: redis:8.8-alpine
|
|
24
|
+
restart: unless-stopped
|
|
25
|
+
command: redis-server --requirepass ${REDIS_PASSWORD-root}
|
|
26
|
+
ports:
|
|
27
|
+
- '127.0.0.1:6379:6379'
|
|
28
|
+
networks:
|
|
29
|
+
- vitnode_dev
|
|
30
|
+
|
|
31
|
+
networks:
|
|
32
|
+
vitnode_dev:
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
-
import eslintVitNode from
|
|
1
|
+
import eslintVitNode from "@vitnode/config/eslint";
|
|
2
|
+
import eslintVitNodeReact from "@vitnode/config/eslint.react";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { dirname } from "node:path";
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
export default [
|
|
9
|
+
...eslintVitNode,
|
|
10
|
+
...eslintVitNodeReact,
|
|
11
|
+
{
|
|
12
|
+
languageOptions: {
|
|
13
|
+
parserOptions: {
|
|
14
|
+
project: "./tsconfig.json",
|
|
15
|
+
tsconfigRootDir: __dirname,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import eslintVitNode from "@vitnode/config/eslint";
|
|
2
|
+
import eslintVitNodeReact from "@vitnode/config/eslint.react";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { dirname } from "node:path";
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
export default [
|
|
9
|
+
...eslintVitNode,
|
|
10
|
+
...eslintVitNodeReact,
|
|
11
|
+
{
|
|
12
|
+
languageOptions: {
|
|
13
|
+
parserOptions: {
|
|
14
|
+
project: "./tsconfig.json",
|
|
15
|
+
tsconfigRootDir: __dirname,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
2
|
+
|
|
3
|
+
# Dependencies
|
|
4
|
+
node_modules
|
|
5
|
+
.pnp
|
|
6
|
+
.pnp.js
|
|
7
|
+
|
|
8
|
+
# Local env files
|
|
9
|
+
.env
|
|
10
|
+
.env.local
|
|
11
|
+
.env.development.local
|
|
12
|
+
.env.test.local
|
|
13
|
+
.env.production.local
|
|
14
|
+
|
|
15
|
+
# Testing
|
|
16
|
+
coverage
|
|
17
|
+
|
|
18
|
+
# Turbo
|
|
19
|
+
.turbo
|
|
20
|
+
|
|
21
|
+
# Vercel
|
|
22
|
+
.vercel
|
|
23
|
+
|
|
24
|
+
# Build Outputs
|
|
25
|
+
.output/
|
|
26
|
+
out/
|
|
27
|
+
build
|
|
28
|
+
dist
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Debug
|
|
32
|
+
npm-debug.log*
|
|
33
|
+
yarn-debug.log*
|
|
34
|
+
yarn-error.log*
|
|
35
|
+
|
|
36
|
+
# Misc
|
|
37
|
+
.DS_Store
|
|
38
|
+
*.pem
|
|
39
|
+
|
|
40
|
+
# VitNode
|
|
41
|
+
/docker
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
POSTGRES_URL=postgresql://root:root@localhost:5432/vitnode
|
|
2
|
+
REDIS_URL=redis://localhost:6379
|
|
3
|
+
|
|
4
|
+
VITNODE_WEB_URL=http://localhost:3000
|
|
5
|
+
|
|
6
|
+
# === Docker Database Postgres ===
|
|
7
|
+
POSTGRES_USER=root
|
|
8
|
+
POSTGRES_PASSWORD=root
|
|
9
|
+
POSTGRES_NAME=vitnode
|
|
10
|
+
|
|
11
|
+
# === Docker Redis ===
|
|
12
|
+
REDIS_PASSWORD=root
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITNODE_API_URL=http://localhost:8000
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://turborepo.dev/schema.json",
|
|
3
|
+
"ui": "tui",
|
|
4
|
+
"tasks": {
|
|
5
|
+
"db:prepare": {
|
|
6
|
+
"cache": false,
|
|
7
|
+
"inputs": ["$TURBO_DEFAULT$", ".env*"],
|
|
8
|
+
"env": ["POSTGRES_URL"]
|
|
9
|
+
},
|
|
10
|
+
"db:migrate": {
|
|
11
|
+
"dependsOn": ["^db:migrate"],
|
|
12
|
+
"cache": false,
|
|
13
|
+
"inputs": ["$TURBO_DEFAULT$", ".env*"],
|
|
14
|
+
"env": ["POSTGRES_URL"]
|
|
15
|
+
},
|
|
16
|
+
"build": {
|
|
17
|
+
"dependsOn": ["^build"],
|
|
18
|
+
"inputs": ["$TURBO_DEFAULT$", ".env*"],
|
|
19
|
+
"outputs": [".output/**", "dist/**"],
|
|
20
|
+
"env": ["POSTGRES_URL", "VITNODE_API_URL", "VITNODE_WEB_URL"]
|
|
21
|
+
},
|
|
22
|
+
"dev": {
|
|
23
|
+
"cache": false,
|
|
24
|
+
"persistent": true,
|
|
25
|
+
"inputs": ["$TURBO_DEFAULT$", ".env*"],
|
|
26
|
+
"env": ["POSTGRES_URL", "VITNODE_API_URL", "VITNODE_WEB_URL"]
|
|
27
|
+
},
|
|
28
|
+
"start": {
|
|
29
|
+
"dependsOn": ["^start"]
|
|
30
|
+
},
|
|
31
|
+
"lint": {
|
|
32
|
+
"dependsOn": ["^lint"]
|
|
33
|
+
},
|
|
34
|
+
"lint:fix": {
|
|
35
|
+
"dependsOn": ["^lint:fix"]
|
|
36
|
+
},
|
|
37
|
+
"i18n:create": {
|
|
38
|
+
"dependsOn": ["^i18n:create"]
|
|
39
|
+
},
|
|
40
|
+
"i18n:check": {
|
|
41
|
+
"dependsOn": ["^i18n:check"]
|
|
42
|
+
},
|
|
43
|
+
"i18n:delete": {
|
|
44
|
+
"dependsOn": ["^i18n:delete"]
|
|
45
|
+
},
|
|
46
|
+
"i18n:update": {
|
|
47
|
+
"dependsOn": ["^i18n:update"]
|
|
48
|
+
},
|
|
49
|
+
"i18n:update:ai": {
|
|
50
|
+
"dependsOn": ["^i18n:update:ai"]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
LOGIN_TOKEN_SECRET=secret
|
|
2
1
|
POSTGRES_URL=postgresql://root:root@localhost:5432/vitnode
|
|
2
|
+
REDIS_URL=redis://localhost:6379
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
VITNODE_WEB_URL=http://localhost:3000
|
|
5
|
+
|
|
6
|
+
# === CRON Secret for Internal API Calls ===
|
|
7
|
+
CRON_SECRET=your-secure-cron-secret-key
|
|
7
8
|
|
|
8
9
|
# === Docker Database Postgres ===
|
|
9
10
|
POSTGRES_USER=root
|
|
10
11
|
POSTGRES_PASSWORD=root
|
|
11
|
-
POSTGRES_NAME=vitnode
|
|
12
|
+
POSTGRES_NAME=vitnode
|
|
13
|
+
|
|
14
|
+
# === Docker Redis ===
|
|
15
|
+
REDIS_PASSWORD=root
|