create-veap 0.1.3 → 0.3.0
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/bin/veap.js +1 -0
- package/dist/commands/init.js +4 -5
- package/dist/package-manager.js +3 -5
- package/dist/scaffold.d.ts +5 -3
- package/dist/scaffold.js +45 -5
- package/package.json +1 -1
- package/stubs/docker/.dockerignore.stub +39 -39
- package/stubs/docker/Dockerfile.stub +49 -49
- package/stubs/docker/compose.yml.stub +58 -58
- package/stubs/overlay-full/AGENTS.md.stub +1 -1
- package/stubs/overlay-full/app/(site)/layout.tsx.stub +10 -0
- package/stubs/overlay-full/app/[[...catchAll]]/page.tsx.stub +47 -47
- package/stubs/overlay-full/app/api/[...catchAll]/route.ts.stub +111 -111
- package/stubs/overlay-full/app/error.tsx.stub +34 -34
- package/stubs/overlay-full/app/globals.css.stub +123 -123
- package/stubs/overlay-full/app/layout.tsx.stub +71 -71
- package/stubs/overlay-full/app/storage/[...path]/route.ts.stub +61 -61
- package/stubs/overlay-full/components/footer.tsx.stub +25 -0
- package/stubs/overlay-full/components/navbar.tsx.stub +61 -0
- package/stubs/overlay-full/components/site-layout.tsx.stub +22 -0
- package/stubs/overlay-full/lib/plugins.gen.ts.stub +6 -6
- package/stubs/overlay-full/lib/veap.ts.stub +27 -26
- package/stubs/overlay-full/next.config.ts.stub +34 -34
- package/stubs/overlay-full/proxy.ts.stub +27 -27
package/bin/veap.js
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -2,12 +2,12 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import ora from "ora";
|
|
5
|
-
import {
|
|
5
|
+
import { appendGitignore, clearAppDirectory, injectVeapDependencies, writeEnvFile, } from "../mutate.js";
|
|
6
6
|
import { applyPackageManager, pmInstall, pmRunCommand, resolvePackageManager, } from "../package-manager.js";
|
|
7
|
-
import { scaffoldNextApp } from "../scaffold.js";
|
|
8
|
-
import { promptConfirm, promptProjectName } from "../prompts.js";
|
|
9
7
|
import { parseProjectName, projectNameError } from "../project-name.js";
|
|
10
|
-
import {
|
|
8
|
+
import { promptConfirm, promptProjectName } from "../prompts.js";
|
|
9
|
+
import { scaffoldNextApp } from "../scaffold.js";
|
|
10
|
+
import { processStubs } from "../utils.js";
|
|
11
11
|
export async function initProject(name, options) {
|
|
12
12
|
// ---- Resolve the project name: from the CLI argument or the interactive
|
|
13
13
|
// prompt (which resolves to a default on non-TTY, so scripts never hang).
|
|
@@ -75,7 +75,6 @@ export async function initProject(name, options) {
|
|
|
75
75
|
path.join(destDir, "public"),
|
|
76
76
|
path.join(destDir, "storage"),
|
|
77
77
|
path.join(destDir, "plugins"),
|
|
78
|
-
path.join(destDir, "templates"),
|
|
79
78
|
]) {
|
|
80
79
|
if (!fs.existsSync(dir)) {
|
|
81
80
|
fs.mkdirSync(dir, { recursive: true });
|
package/dist/package-manager.js
CHANGED
|
@@ -53,9 +53,7 @@ export function detectPackageManager(dir) {
|
|
|
53
53
|
return {
|
|
54
54
|
pm: "pnpm",
|
|
55
55
|
source: "lockfile",
|
|
56
|
-
detail: `multiple lockfiles found: ${found
|
|
57
|
-
.map((l) => l.file)
|
|
58
|
-
.join(", ")}`,
|
|
56
|
+
detail: `multiple lockfiles found: ${found.map((l) => l.file).join(", ")}`,
|
|
59
57
|
};
|
|
60
58
|
}
|
|
61
59
|
if (found.length === 1) {
|
|
@@ -189,11 +187,11 @@ export function applyPackageManager(projectDir, pm) {
|
|
|
189
187
|
// undefined in package.json to avoid a shadowing duplicate). Written
|
|
190
188
|
// only when missing - an existing one is the source of truth.
|
|
191
189
|
if (!fs.existsSync(pnpmWorkspace)) {
|
|
192
|
-
fs.writeFileSync(pnpmWorkspace, 'packages:\n - "plugins/*"\n
|
|
190
|
+
fs.writeFileSync(pnpmWorkspace, 'packages:\n - "plugins/*"\n', "utf-8");
|
|
193
191
|
}
|
|
194
192
|
}
|
|
195
193
|
else {
|
|
196
|
-
pkg.workspaces = ["plugins/*"
|
|
194
|
+
pkg.workspaces = ["plugins/*"];
|
|
197
195
|
if (fs.existsSync(pnpmWorkspace)) {
|
|
198
196
|
// Switching away from pnpm: the file would shadow the workspaces field.
|
|
199
197
|
fs.rmSync(pnpmWorkspace);
|
package/dist/scaffold.d.ts
CHANGED
|
@@ -12,15 +12,17 @@ export interface ScaffoldOptions {
|
|
|
12
12
|
* instead of hanging the scaffolder). `--skip-install` keeps a single
|
|
13
13
|
* dependency install at the end of `initProject`, after veap mutations.
|
|
14
14
|
*/
|
|
15
|
-
export declare function buildCreateNextAppCommand(name: string, opts: ScaffoldOptions): string;
|
|
15
|
+
export declare function buildCreateNextAppCommand(name: string, opts: ScaffoldOptions, runnerOverride?: string): string;
|
|
16
16
|
/**
|
|
17
17
|
* Normalizes a project name into a shell-safe, npm-friendly folder name.
|
|
18
18
|
* CNA derives the package name from the folder, so the same charset applies.
|
|
19
19
|
*/
|
|
20
20
|
export declare function sanitizeProjectName(name: string): string | null;
|
|
21
21
|
/**
|
|
22
|
-
* Runs create-next-app.
|
|
23
|
-
*
|
|
22
|
+
* Runs create-next-app. If the package-manager-specific runner fails (for
|
|
23
|
+
* example, Bun's known IPv6 ConnectionRefused bug on Windows when downloading
|
|
24
|
+
* tarballs), it transparently falls back to npx so the project is still
|
|
25
|
+
* properly scaffolded with all chosen options.
|
|
24
26
|
* Returns the (possibly sanitized) project directory name.
|
|
25
27
|
*/
|
|
26
28
|
export declare function scaffoldNextApp(name: string, opts: ScaffoldOptions): string;
|
package/dist/scaffold.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
2
4
|
/**
|
|
3
5
|
* Scaffolds the Next.js shell of a new project with the official
|
|
4
6
|
* `create-next-app` (CNA) instead of duplicating its boilerplate in stubs.
|
|
@@ -22,7 +24,7 @@ const CNA_RUNNERS = {
|
|
|
22
24
|
* instead of hanging the scaffolder). `--skip-install` keeps a single
|
|
23
25
|
* dependency install at the end of `initProject`, after veap mutations.
|
|
24
26
|
*/
|
|
25
|
-
export function buildCreateNextAppCommand(name, opts) {
|
|
27
|
+
export function buildCreateNextAppCommand(name, opts, runnerOverride) {
|
|
26
28
|
const flags = [
|
|
27
29
|
"--ts",
|
|
28
30
|
"--tailwind",
|
|
@@ -35,7 +37,20 @@ export function buildCreateNextAppCommand(name, opts) {
|
|
|
35
37
|
'"@/*"',
|
|
36
38
|
"--skip-install",
|
|
37
39
|
];
|
|
38
|
-
|
|
40
|
+
if (opts.pm === "bun") {
|
|
41
|
+
flags.push("--use-bun");
|
|
42
|
+
}
|
|
43
|
+
else if (opts.pm === "pnpm") {
|
|
44
|
+
flags.push("--use-pnpm");
|
|
45
|
+
}
|
|
46
|
+
else if (opts.pm === "yarn") {
|
|
47
|
+
flags.push("--use-yarn");
|
|
48
|
+
}
|
|
49
|
+
else if (opts.pm === "npm") {
|
|
50
|
+
flags.push("--use-npm");
|
|
51
|
+
}
|
|
52
|
+
const runner = runnerOverride ?? CNA_RUNNERS[opts.pm];
|
|
53
|
+
return `${runner} "${name}" ${flags.join(" ")}`;
|
|
39
54
|
}
|
|
40
55
|
/**
|
|
41
56
|
* Normalizes a project name into a shell-safe, npm-friendly folder name.
|
|
@@ -46,8 +61,10 @@ export function sanitizeProjectName(name) {
|
|
|
46
61
|
return safe === name ? null : safe;
|
|
47
62
|
}
|
|
48
63
|
/**
|
|
49
|
-
* Runs create-next-app.
|
|
50
|
-
*
|
|
64
|
+
* Runs create-next-app. If the package-manager-specific runner fails (for
|
|
65
|
+
* example, Bun's known IPv6 ConnectionRefused bug on Windows when downloading
|
|
66
|
+
* tarballs), it transparently falls back to npx so the project is still
|
|
67
|
+
* properly scaffolded with all chosen options.
|
|
51
68
|
* Returns the (possibly sanitized) project directory name.
|
|
52
69
|
*/
|
|
53
70
|
export function scaffoldNextApp(name, opts) {
|
|
@@ -57,6 +74,29 @@ export function scaffoldNextApp(name, opts) {
|
|
|
57
74
|
}
|
|
58
75
|
const projectName = sanitized ?? name;
|
|
59
76
|
const command = buildCreateNextAppCommand(projectName, opts);
|
|
60
|
-
|
|
77
|
+
try {
|
|
78
|
+
execSync(command, { cwd: opts.cwd, stdio: "inherit" });
|
|
79
|
+
}
|
|
80
|
+
catch (primaryErr) {
|
|
81
|
+
if (opts.pm !== "npm") {
|
|
82
|
+
console.warn(`\n⚠️ ${opts.pm} failed to run create-next-app (e.g. network/IPv6 timeout). Falling back to npx...`);
|
|
83
|
+
// Clean up partially created directory if exists and empty
|
|
84
|
+
const targetPath = path.join(opts.cwd, projectName);
|
|
85
|
+
if (fs.existsSync(targetPath)) {
|
|
86
|
+
try {
|
|
87
|
+
const files = fs.readdirSync(targetPath);
|
|
88
|
+
if (files.length === 0) {
|
|
89
|
+
fs.rmSync(targetPath, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch { }
|
|
93
|
+
}
|
|
94
|
+
const fallbackCommand = buildCreateNextAppCommand(projectName, opts, CNA_RUNNERS.npm);
|
|
95
|
+
execSync(fallbackCommand, { cwd: opts.cwd, stdio: "inherit" });
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
throw primaryErr;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
61
101
|
return projectName;
|
|
62
102
|
}
|
package/package.json
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
node_modules/
|
|
2
|
-
.pnpm-store/
|
|
3
|
-
npm-debug.log*
|
|
4
|
-
yarn-debug.log*
|
|
5
|
-
yarn-error.log*
|
|
6
|
-
pnpm-debug.log*
|
|
7
|
-
|
|
8
|
-
.next/
|
|
9
|
-
out/
|
|
10
|
-
dist/
|
|
11
|
-
build/
|
|
12
|
-
.vercel/
|
|
13
|
-
|
|
14
|
-
coverage/
|
|
15
|
-
*.test.*
|
|
16
|
-
*.spec.*
|
|
17
|
-
|
|
18
|
-
.git/
|
|
19
|
-
.gitignore
|
|
20
|
-
.vscode/
|
|
21
|
-
.idea/
|
|
22
|
-
*.swp
|
|
23
|
-
*.log
|
|
24
|
-
|
|
25
|
-
.env
|
|
26
|
-
.env*.local
|
|
27
|
-
|
|
28
|
-
Dockerfile*
|
|
29
|
-
.dockerignore
|
|
30
|
-
compose.yaml
|
|
31
|
-
compose.yml
|
|
32
|
-
|
|
33
|
-
*.md
|
|
34
|
-
docs/
|
|
35
|
-
|
|
36
|
-
.turbo/
|
|
37
|
-
.tmp/
|
|
38
|
-
.temp/
|
|
39
|
-
.DS_Store
|
|
1
|
+
node_modules/
|
|
2
|
+
.pnpm-store/
|
|
3
|
+
npm-debug.log*
|
|
4
|
+
yarn-debug.log*
|
|
5
|
+
yarn-error.log*
|
|
6
|
+
pnpm-debug.log*
|
|
7
|
+
|
|
8
|
+
.next/
|
|
9
|
+
out/
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
.vercel/
|
|
13
|
+
|
|
14
|
+
coverage/
|
|
15
|
+
*.test.*
|
|
16
|
+
*.spec.*
|
|
17
|
+
|
|
18
|
+
.git/
|
|
19
|
+
.gitignore
|
|
20
|
+
.vscode/
|
|
21
|
+
.idea/
|
|
22
|
+
*.swp
|
|
23
|
+
*.log
|
|
24
|
+
|
|
25
|
+
.env
|
|
26
|
+
.env*.local
|
|
27
|
+
|
|
28
|
+
Dockerfile*
|
|
29
|
+
.dockerignore
|
|
30
|
+
compose.yaml
|
|
31
|
+
compose.yml
|
|
32
|
+
|
|
33
|
+
*.md
|
|
34
|
+
docs/
|
|
35
|
+
|
|
36
|
+
.turbo/
|
|
37
|
+
.tmp/
|
|
38
|
+
.temp/
|
|
39
|
+
.DS_Store
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
# Stage 1: Base image with pnpm
|
|
2
|
-
FROM node:22-alpine AS base
|
|
3
|
-
RUN apk add --no-cache libc6-compat
|
|
4
|
-
ENV PNPM_HOME="/pnpm"
|
|
5
|
-
ENV PATH="$PNPM_HOME:$PATH"
|
|
6
|
-
|
|
7
|
-
RUN corepack enable
|
|
8
|
-
RUN corepack prepare pnpm@10.29.3 --activate
|
|
9
|
-
|
|
10
|
-
# Stage 2: Install dependencies
|
|
11
|
-
FROM base AS deps
|
|
12
|
-
WORKDIR /app
|
|
13
|
-
COPY . .
|
|
14
|
-
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
|
15
|
-
pnpm config set store-dir /pnpm/store && \
|
|
16
|
-
pnpm config set fetch-retries 10 && \
|
|
17
|
-
pnpm config set fetch-retry-maxtimeout 120000 && \
|
|
18
|
-
pnpm config set fetch-timeout 600000 && \
|
|
19
|
-
pnpm install --frozen-lockfile
|
|
20
|
-
|
|
21
|
-
# Stage 3: Build the project
|
|
22
|
-
FROM base AS builder
|
|
23
|
-
WORKDIR /app
|
|
24
|
-
COPY --from=deps /app ./
|
|
25
|
-
RUN pnpm build
|
|
26
|
-
|
|
27
|
-
# Stage 4: Production runner
|
|
28
|
-
FROM base AS runner
|
|
29
|
-
WORKDIR /app
|
|
30
|
-
|
|
31
|
-
ENV NODE_ENV=production
|
|
32
|
-
ENV NEXT_TELEMETRY_DISABLED=1
|
|
33
|
-
|
|
34
|
-
RUN addgroup --system --gid 1001 nodejs
|
|
35
|
-
RUN adduser --system --uid 1001 nextjs
|
|
36
|
-
|
|
37
|
-
# Automatically leverage output traces to reduce image size
|
|
38
|
-
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
39
|
-
COPY --from=builder --chown=nextjs:nodejs /app/.next/static .next/static
|
|
40
|
-
COPY --from=builder --chown=nextjs:nodejs /app/public public
|
|
41
|
-
|
|
42
|
-
USER nextjs
|
|
43
|
-
|
|
44
|
-
EXPOSE 3000
|
|
45
|
-
|
|
46
|
-
ENV PORT=3000
|
|
47
|
-
ENV HOSTNAME="0.0.0.0"
|
|
48
|
-
|
|
49
|
-
CMD ["node", "./server.js"]
|
|
1
|
+
# Stage 1: Base image with pnpm
|
|
2
|
+
FROM node:22-alpine AS base
|
|
3
|
+
RUN apk add --no-cache libc6-compat
|
|
4
|
+
ENV PNPM_HOME="/pnpm"
|
|
5
|
+
ENV PATH="$PNPM_HOME:$PATH"
|
|
6
|
+
|
|
7
|
+
RUN corepack enable
|
|
8
|
+
RUN corepack prepare pnpm@10.29.3 --activate
|
|
9
|
+
|
|
10
|
+
# Stage 2: Install dependencies
|
|
11
|
+
FROM base AS deps
|
|
12
|
+
WORKDIR /app
|
|
13
|
+
COPY . .
|
|
14
|
+
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
|
15
|
+
pnpm config set store-dir /pnpm/store && \
|
|
16
|
+
pnpm config set fetch-retries 10 && \
|
|
17
|
+
pnpm config set fetch-retry-maxtimeout 120000 && \
|
|
18
|
+
pnpm config set fetch-timeout 600000 && \
|
|
19
|
+
pnpm install --frozen-lockfile
|
|
20
|
+
|
|
21
|
+
# Stage 3: Build the project
|
|
22
|
+
FROM base AS builder
|
|
23
|
+
WORKDIR /app
|
|
24
|
+
COPY --from=deps /app ./
|
|
25
|
+
RUN pnpm build
|
|
26
|
+
|
|
27
|
+
# Stage 4: Production runner
|
|
28
|
+
FROM base AS runner
|
|
29
|
+
WORKDIR /app
|
|
30
|
+
|
|
31
|
+
ENV NODE_ENV=production
|
|
32
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
33
|
+
|
|
34
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
35
|
+
RUN adduser --system --uid 1001 nextjs
|
|
36
|
+
|
|
37
|
+
# Automatically leverage output traces to reduce image size
|
|
38
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
39
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static .next/static
|
|
40
|
+
COPY --from=builder --chown=nextjs:nodejs /app/public public
|
|
41
|
+
|
|
42
|
+
USER nextjs
|
|
43
|
+
|
|
44
|
+
EXPOSE 3000
|
|
45
|
+
|
|
46
|
+
ENV PORT=3000
|
|
47
|
+
ENV HOSTNAME="0.0.0.0"
|
|
48
|
+
|
|
49
|
+
CMD ["node", "./server.js"]
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
services:
|
|
2
|
-
# Node.js service (use with: docker compose up {{name}} --build)
|
|
3
|
-
{{name}}:
|
|
4
|
-
build:
|
|
5
|
-
context: .
|
|
6
|
-
dockerfile: Dockerfile
|
|
7
|
-
image: {{name}}-image
|
|
8
|
-
container_name: {{name}}
|
|
9
|
-
env_file:
|
|
10
|
-
- .env
|
|
11
|
-
environment:
|
|
12
|
-
NODE_ENV: production
|
|
13
|
-
PORT: "3000"
|
|
14
|
-
NEXT_TELEMETRY_DISABLED: "1"
|
|
15
|
-
DATABASE_URL: "postgresql://postgres:postgres@database:5432/postgres?sslmode=disable"
|
|
16
|
-
depends_on:
|
|
17
|
-
database:
|
|
18
|
-
condition: service_healthy
|
|
19
|
-
redis:
|
|
20
|
-
condition: service_started
|
|
21
|
-
ports:
|
|
22
|
-
- "80:3000"
|
|
23
|
-
restart: unless-stopped
|
|
24
|
-
volumes:
|
|
25
|
-
- ./storage:/app/public/storage
|
|
26
|
-
|
|
27
|
-
# PostgreSQL service
|
|
28
|
-
database:
|
|
29
|
-
image: postgres:17-alpine
|
|
30
|
-
container_name: {{name}}-db
|
|
31
|
-
restart: always
|
|
32
|
-
environment:
|
|
33
|
-
POSTGRES_USER: postgres
|
|
34
|
-
POSTGRES_PASSWORD: postgres
|
|
35
|
-
POSTGRES_DB: postgres
|
|
36
|
-
ports:
|
|
37
|
-
- "5432:5432"
|
|
38
|
-
volumes:
|
|
39
|
-
- postgres_data:/var/lib/postgresql/data
|
|
40
|
-
healthcheck:
|
|
41
|
-
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
|
|
42
|
-
interval: 5s
|
|
43
|
-
timeout: 5s
|
|
44
|
-
retries: 5
|
|
45
|
-
|
|
46
|
-
# Redis service
|
|
47
|
-
redis:
|
|
48
|
-
image: redis:7-alpine
|
|
49
|
-
container_name: {{name}}-redis
|
|
50
|
-
restart: always
|
|
51
|
-
ports:
|
|
52
|
-
- "6379:6379"
|
|
53
|
-
volumes:
|
|
54
|
-
- redis_data:/data
|
|
55
|
-
|
|
56
|
-
volumes:
|
|
57
|
-
postgres_data:
|
|
58
|
-
redis_data:
|
|
1
|
+
services:
|
|
2
|
+
# Node.js service (use with: docker compose up {{name}} --build)
|
|
3
|
+
{{name}}:
|
|
4
|
+
build:
|
|
5
|
+
context: .
|
|
6
|
+
dockerfile: Dockerfile
|
|
7
|
+
image: {{name}}-image
|
|
8
|
+
container_name: {{name}}
|
|
9
|
+
env_file:
|
|
10
|
+
- .env
|
|
11
|
+
environment:
|
|
12
|
+
NODE_ENV: production
|
|
13
|
+
PORT: "3000"
|
|
14
|
+
NEXT_TELEMETRY_DISABLED: "1"
|
|
15
|
+
DATABASE_URL: "postgresql://postgres:postgres@database:5432/postgres?sslmode=disable"
|
|
16
|
+
depends_on:
|
|
17
|
+
database:
|
|
18
|
+
condition: service_healthy
|
|
19
|
+
redis:
|
|
20
|
+
condition: service_started
|
|
21
|
+
ports:
|
|
22
|
+
- "80:3000"
|
|
23
|
+
restart: unless-stopped
|
|
24
|
+
volumes:
|
|
25
|
+
- ./storage:/app/public/storage
|
|
26
|
+
|
|
27
|
+
# PostgreSQL service
|
|
28
|
+
database:
|
|
29
|
+
image: postgres:17-alpine
|
|
30
|
+
container_name: {{name}}-db
|
|
31
|
+
restart: always
|
|
32
|
+
environment:
|
|
33
|
+
POSTGRES_USER: postgres
|
|
34
|
+
POSTGRES_PASSWORD: postgres
|
|
35
|
+
POSTGRES_DB: postgres
|
|
36
|
+
ports:
|
|
37
|
+
- "5432:5432"
|
|
38
|
+
volumes:
|
|
39
|
+
- postgres_data:/var/lib/postgresql/data
|
|
40
|
+
healthcheck:
|
|
41
|
+
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
|
|
42
|
+
interval: 5s
|
|
43
|
+
timeout: 5s
|
|
44
|
+
retries: 5
|
|
45
|
+
|
|
46
|
+
# Redis service
|
|
47
|
+
redis:
|
|
48
|
+
image: redis:7-alpine
|
|
49
|
+
container_name: {{name}}-redis
|
|
50
|
+
restart: always
|
|
51
|
+
ports:
|
|
52
|
+
- "6379:6379"
|
|
53
|
+
volumes:
|
|
54
|
+
- redis_data:/data
|
|
55
|
+
|
|
56
|
+
volumes:
|
|
57
|
+
postgres_data:
|
|
58
|
+
redis_data:
|
|
@@ -11,7 +11,7 @@ This project is a **Veap** application: the official `create-next-app` base plus
|
|
|
11
11
|
- `app/[[...catchAll]]/page.tsx` - every page render goes through `VeapRouter` (route tree built from plugins + app routes). Do not add competing page routes without understanding the router.
|
|
12
12
|
- `app/api/[...catchAll]/route.ts` - API pipeline: middlewares, auth, roles/permissions resolved from the route tree.
|
|
13
13
|
- `app/layout.tsx`, `app/not-found.tsx` - root shell with the bootstrap and the **force-dynamic contract (below)**.
|
|
14
|
-
- `plugins
|
|
14
|
+
- `plugins/` - workspace packages (pnpm workspace / npm workspaces).
|
|
15
15
|
- `migrations/` - app migrations (`veap make:migration`).
|
|
16
16
|
|
|
17
17
|
## Critical Contracts (do not break)
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import { VeapRouter } from "@veap/framework/router";
|
|
2
|
-
import { buildRouteTree } from "@veap/framework/router/server";
|
|
3
|
-
import type { Metadata } from "next";
|
|
4
|
-
import { initializeSystem } from "@/lib/veap";
|
|
5
|
-
|
|
6
|
-
export const dynamic = "force-dynamic";
|
|
7
|
-
|
|
8
|
-
export async function generateMetadata({
|
|
9
|
-
params,
|
|
10
|
-
searchParams,
|
|
11
|
-
}: {
|
|
12
|
-
params: Promise<{ catchAll?: string[] }>;
|
|
13
|
-
searchParams: Promise<Record<string, string>>;
|
|
14
|
-
}): Promise<Metadata> {
|
|
15
|
-
const { catchAll } = await params;
|
|
16
|
-
const sParams = await searchParams;
|
|
17
|
-
const path = catchAll && catchAll.length > 0 ? `/${catchAll.join("/")}` : "/";
|
|
18
|
-
|
|
19
|
-
await initializeSystem();
|
|
20
|
-
const tree = await buildRouteTree(true);
|
|
21
|
-
const result = await tree.generateMetadata(path, sParams);
|
|
22
|
-
|
|
23
|
-
return result;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default async function CatchAllPage({
|
|
27
|
-
params,
|
|
28
|
-
searchParams,
|
|
29
|
-
}: {
|
|
30
|
-
params: Promise<{ catchAll?: string[] }>;
|
|
31
|
-
searchParams: Promise<any>;
|
|
32
|
-
}) {
|
|
33
|
-
const { catchAll } = await params;
|
|
34
|
-
const sParams = await searchParams;
|
|
35
|
-
const path = catchAll && catchAll.length > 0 ? `/${catchAll.join("/")}` : "/";
|
|
36
|
-
|
|
37
|
-
await initializeSystem();
|
|
38
|
-
const tree = await buildRouteTree(true);
|
|
39
|
-
|
|
40
|
-
const result = await VeapRouter({
|
|
41
|
-
tree,
|
|
42
|
-
path,
|
|
43
|
-
searchParams: sParams,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
1
|
+
import { VeapRouter } from "@veap/framework/router";
|
|
2
|
+
import { buildRouteTree } from "@veap/framework/router/server";
|
|
3
|
+
import type { Metadata } from "next";
|
|
4
|
+
import { initializeSystem } from "@/lib/veap";
|
|
5
|
+
|
|
6
|
+
export const dynamic = "force-dynamic";
|
|
7
|
+
|
|
8
|
+
export async function generateMetadata({
|
|
9
|
+
params,
|
|
10
|
+
searchParams,
|
|
11
|
+
}: {
|
|
12
|
+
params: Promise<{ catchAll?: string[] }>;
|
|
13
|
+
searchParams: Promise<Record<string, string>>;
|
|
14
|
+
}): Promise<Metadata> {
|
|
15
|
+
const { catchAll } = await params;
|
|
16
|
+
const sParams = await searchParams;
|
|
17
|
+
const path = catchAll && catchAll.length > 0 ? `/${catchAll.join("/")}` : "/";
|
|
18
|
+
|
|
19
|
+
await initializeSystem();
|
|
20
|
+
const tree = await buildRouteTree(true);
|
|
21
|
+
const result = await tree.generateMetadata(path, sParams);
|
|
22
|
+
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default async function CatchAllPage({
|
|
27
|
+
params,
|
|
28
|
+
searchParams,
|
|
29
|
+
}: {
|
|
30
|
+
params: Promise<{ catchAll?: string[] }>;
|
|
31
|
+
searchParams: Promise<any>;
|
|
32
|
+
}) {
|
|
33
|
+
const { catchAll } = await params;
|
|
34
|
+
const sParams = await searchParams;
|
|
35
|
+
const path = catchAll && catchAll.length > 0 ? `/${catchAll.join("/")}` : "/";
|
|
36
|
+
|
|
37
|
+
await initializeSystem();
|
|
38
|
+
const tree = await buildRouteTree(true);
|
|
39
|
+
|
|
40
|
+
const result = await VeapRouter({
|
|
41
|
+
tree,
|
|
42
|
+
path,
|
|
43
|
+
searchParams: sParams,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return result;
|
|
47
|
+
}
|