create-veap 0.1.4 → 0.3.1

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/README.md CHANGED
@@ -1,3 +1,74 @@
1
1
  # create-veap
2
2
 
3
- Initializer for Veap Framework applications. Scaffolds a full plugin-enabled Veap project on top of the official create-next-app.
3
+ The official project initializer for [Veap Framework](https://veap.pl) applications. Scaffolds a full plugin-enabled Veap project on top of the official `create-next-app`.
4
+
5
+ ## Quickstart
6
+
7
+ Initialize a new Veap project using your preferred package manager:
8
+
9
+ ```bash
10
+ # Using Bun (recommended)
11
+ bun create veap my-app
12
+
13
+ # Using pnpm
14
+ pnpm create veap my-app
15
+
16
+ # Using npm
17
+ npm create veap my-app
18
+
19
+ # Using Yarn
20
+ yarn create veap my-app
21
+ ```
22
+
23
+ Or execute directly through a package runner:
24
+
25
+ ```bash
26
+ bunx create-veap my-app
27
+ # or
28
+ npx create-veap my-app
29
+ ```
30
+
31
+ When you omit the project name in an interactive terminal, `create-veap` prompts for a project name and optional Docker configuration.
32
+
33
+ ## Command options
34
+
35
+ | Flag | Description |
36
+ | ---------------- | ---------------------------------------------------------------------------- |
37
+ | `--docker` | Generate Docker configuration (`Dockerfile`, `compose.yml`, `.dockerignore`). |
38
+ | `--no-docker` | Skip Docker configuration without prompting. |
39
+ | `--skip-install` | Do not run the package manager install step. |
40
+ | `--pm <manager>` | Specify package manager (`bun`, `pnpm`, `npm`, `yarn`). |
41
+ | `--pnpm` | Force pnpm as package manager. |
42
+ | `--bun` | Force Bun as package manager. |
43
+ | `--npm` | Force npm as package manager. |
44
+ | `--yarn` | Force Yarn as package manager. |
45
+
46
+ ### Automatic package manager detection
47
+
48
+ `create-veap` automatically detects the package manager from the execution command (`bun create`, `pnpm create`, `npm create`, `yarn create`, `bunx`, or `npx`) and environment variables without prompting.
49
+
50
+ If you want to use a different package manager than the runner (for example, executing via Bun while configuring the generated project for pnpm), pass the target package manager flag:
51
+
52
+ ```bash
53
+ bun create veap my-app --pnpm
54
+ ```
55
+
56
+ ## What it scaffolds
57
+
58
+ - Next.js 16 App Router with React Server Components, TypeScript, and Tailwind CSS v4.
59
+ - Veap overlay with virtual routing (`app/[[...catchAll]]/page.tsx` and `app/api/[...catchAll]/route.ts`).
60
+ - Service provider composition root in `lib/veap.ts`.
61
+ - Workspace configuration for plugins (`plugins/` directory).
62
+ - Default environment configuration (`.env`) with generated `ENCRYPTION_KEY` and local SQLite database.
63
+ - Agent instructions (`AGENTS.md`) and project guide (`README.md`).
64
+
65
+ ## Documentation
66
+
67
+ For full documentation and guides, visit:
68
+ - [https://veap.pl/docs](https://veap.pl/docs)
69
+ - [Installation Guide](https://veap.pl/docs/getting-started/installation)
70
+ - [CLI Reference](https://veap.pl/docs/reference/cli)
71
+
72
+ ## License
73
+
74
+ MIT
package/bin/veap.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { createRequire } from "module";
4
+
4
5
  const require = createRequire(import.meta.url);
5
6
 
6
7
  // We run the compiled CLI from dist
@@ -1,5 +1,5 @@
1
- export declare function initProject(name?: string, options?: {
1
+ import { type ResolvePackageManagerOptions } from "../package-manager.js";
2
+ export declare function initProject(name?: string, options?: ResolvePackageManagerOptions & {
2
3
  docker?: boolean;
3
4
  skipInstall?: boolean;
4
- pm?: string;
5
5
  }): Promise<void>;
@@ -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 { processStubs } from "../utils.js";
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 { appendGitignore, clearAppDirectory, injectVeapDependencies, writeEnvFile, } from "../mutate.js";
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).
@@ -32,9 +32,8 @@ export async function initProject(name, options) {
32
32
  if (withDocker === undefined) {
33
33
  withDocker = await promptConfirm("Include Docker configuration?", false);
34
34
  }
35
- // Resolve the package manager up front so the prompt runs before any
36
- // scaffolding starts (cleaner UX than asking mid-scaffold).
37
- const pm = await resolvePackageManager({ pm: options?.pm });
35
+ // Resolve the package manager automatically (or from flags)
36
+ const pm = await resolvePackageManager(options);
38
37
  const overlayFolder = "../../stubs/overlay-full";
39
38
  console.log(`🚀 Initializing new Veap project (Full plugin-enabled): ${projectName} in ${destDir}...`);
40
39
  try {
@@ -75,7 +74,6 @@ export async function initProject(name, options) {
75
74
  path.join(destDir, "public"),
76
75
  path.join(destDir, "storage"),
77
76
  path.join(destDir, "plugins"),
78
- path.join(destDir, "templates"),
79
77
  ]) {
80
78
  if (!fs.existsSync(dir)) {
81
79
  fs.mkdirSync(dir, { recursive: true });
package/dist/index.js CHANGED
@@ -5,8 +5,13 @@ const cli = cac("create-veap");
5
5
  cli
6
6
  .command("[name]", "Initialize a new Veap project (asks for details when omitted)")
7
7
  .option("--docker", "Initialize Docker configuration")
8
+ .option("--no-docker", "Skip Docker configuration")
8
9
  .option("--skip-install", "Skip dependencies installation")
9
10
  .option("--pm <manager>", "Package manager to use: pnpm, npm, yarn or bun (auto-detected when omitted)")
11
+ .option("--pnpm, --use-pnpm", "Use pnpm as package manager")
12
+ .option("--bun, --use-bun", "Use bun as package manager")
13
+ .option("--npm, --use-npm", "Use npm as package manager")
14
+ .option("--yarn, --use-yarn", "Use yarn as package manager")
10
15
  .action(async (name, options) => {
11
16
  await initProject(name, options);
12
17
  });
@@ -7,6 +7,15 @@ export interface PackageManagerDetection {
7
7
  /** Human-readable detail, e.g. "pnpm@11.9.0" or "pnpm-lock.yaml". */
8
8
  detail?: string;
9
9
  }
10
+ /**
11
+ * Detects the package manager currently executing the process.
12
+ *
13
+ * Inspects:
14
+ * 1. `npm_config_user_agent` (set when invoked via npx, bunx, pnpm dlx, yarn create)
15
+ * 2. `process.versions.bun` (running directly inside Bun runtime)
16
+ * 3. `npm_execpath` (path containing the binary name)
17
+ */
18
+ export declare function detectRunningPackageManager(env?: NodeJS.ProcessEnv, versions?: NodeJS.ProcessVersions): PackageManager | null;
10
19
  /**
11
20
  * Detects the package manager to default to by inspecting `dir` (usually the
12
21
  * directory the scaffolding command was launched from).
@@ -18,22 +27,32 @@ export declare function detectPackageManager(dir: string): PackageManagerDetecti
18
27
  * Interactive numbered-choice prompt rendered on readline (no external
19
28
  * prompt library, matching the rest of this CLI).
20
29
  *
21
- * The detected package manager is listed first as the default; pressing
22
- * Enter accepts it. Accepts a number (1-4) or a name (`pnpm`, `npm`,
23
- * `yarn`, `bun`). On EOF / closed stdin (piped input, CI) resolves to the
24
- * detected default instead of hanging.
30
+ * Kept as a fallback helper.
25
31
  */
26
32
  export declare function promptPackageManager(detection: PackageManagerDetection): Promise<PackageManager>;
33
+ export interface ResolvePackageManagerOptions {
34
+ pm?: string;
35
+ pnpm?: boolean;
36
+ bun?: boolean;
37
+ npm?: boolean;
38
+ yarn?: boolean;
39
+ usePnpm?: boolean;
40
+ useBun?: boolean;
41
+ useNpm?: boolean;
42
+ useYarn?: boolean;
43
+ }
27
44
  /**
28
45
  * Resolves the package manager to use for a new project.
29
46
  *
30
- * Order: explicit `--pm <name>` flag (validated hard - scripts must not hang
31
- * on a prompt) → interactive prompt (TTY only) → auto-detected default
32
- * (non-TTY, CI).
47
+ * Priority:
48
+ * 1. Explicit manager flag: `--pnpm`, `--bun`, `--npm`, `--yarn`
49
+ * 2. Explicit `--pm <name>` flag
50
+ * 3. Auto-detected from currently running environment (e.g. `bun create`, `pnpm dlx`, `npx`)
51
+ * 4. Auto-detected from current directory (packageManager field, lockfiles, or default)
52
+ *
53
+ * Automatically resolves without prompting.
33
54
  */
34
- export declare function resolvePackageManager(options?: {
35
- pm?: string;
36
- }): Promise<PackageManager>;
55
+ export declare function resolvePackageManager(options?: ResolvePackageManagerOptions, cwd?: string): Promise<PackageManager>;
37
56
  /**
38
57
  * Applies the chosen package manager to the freshly scaffolded project:
39
58
  *
@@ -21,6 +21,43 @@ const LOCKFILES = [
21
21
  { file: "package-lock.json", pm: "npm" },
22
22
  ];
23
23
  const isPackageManager = (value) => PACKAGE_MANAGERS.includes(value);
24
+ /**
25
+ * Detects the package manager currently executing the process.
26
+ *
27
+ * Inspects:
28
+ * 1. `npm_config_user_agent` (set when invoked via npx, bunx, pnpm dlx, yarn create)
29
+ * 2. `process.versions.bun` (running directly inside Bun runtime)
30
+ * 3. `npm_execpath` (path containing the binary name)
31
+ */
32
+ export function detectRunningPackageManager(env = process.env, versions = process.versions) {
33
+ const userAgent = env.npm_config_user_agent;
34
+ if (userAgent) {
35
+ if (userAgent.startsWith("pnpm"))
36
+ return "pnpm";
37
+ if (userAgent.startsWith("bun"))
38
+ return "bun";
39
+ if (userAgent.startsWith("yarn"))
40
+ return "yarn";
41
+ if (userAgent.startsWith("npm"))
42
+ return "npm";
43
+ }
44
+ // Running directly under Bun runtime (e.g. `bun create veap` or `bunx create-veap`)
45
+ if (typeof versions?.bun === "string") {
46
+ return "bun";
47
+ }
48
+ const execPath = env.npm_execpath;
49
+ if (execPath) {
50
+ if (execPath.includes("pnpm"))
51
+ return "pnpm";
52
+ if (execPath.includes("bun"))
53
+ return "bun";
54
+ if (execPath.includes("yarn"))
55
+ return "yarn";
56
+ if (execPath.includes("npm"))
57
+ return "npm";
58
+ }
59
+ return null;
60
+ }
24
61
  /**
25
62
  * Detects the package manager to default to by inspecting `dir` (usually the
26
63
  * directory the scaffolding command was launched from).
@@ -53,13 +90,12 @@ export function detectPackageManager(dir) {
53
90
  return {
54
91
  pm: "pnpm",
55
92
  source: "lockfile",
56
- detail: `multiple lockfiles found: ${found
57
- .map((l) => l.file)
58
- .join(", ")}`,
93
+ detail: `multiple lockfiles found: ${found.map((l) => l.file).join(", ")}`,
59
94
  };
60
95
  }
61
- if (found.length === 1) {
62
- return { pm: found[0].pm, source: "lockfile", detail: found[0].file };
96
+ const first = found[0];
97
+ if (found.length === 1 && first) {
98
+ return { pm: first.pm, source: "lockfile", detail: first.file };
63
99
  }
64
100
  // 3. Framework default
65
101
  return { pm: "pnpm", source: "default" };
@@ -76,10 +112,7 @@ function formatDetection(d) {
76
112
  * Interactive numbered-choice prompt rendered on readline (no external
77
113
  * prompt library, matching the rest of this CLI).
78
114
  *
79
- * The detected package manager is listed first as the default; pressing
80
- * Enter accepts it. Accepts a number (1-4) or a name (`pnpm`, `npm`,
81
- * `yarn`, `bun`). On EOF / closed stdin (piped input, CI) resolves to the
82
- * detected default instead of hanging.
115
+ * Kept as a fallback helper.
83
116
  */
84
117
  export async function promptPackageManager(detection) {
85
118
  console.log(formatDetection(detection));
@@ -125,8 +158,11 @@ export async function promptPackageManager(detection) {
125
158
  if (String(asNumber) === value &&
126
159
  asNumber >= 1 &&
127
160
  asNumber <= PACKAGE_MANAGERS.length) {
128
- finish(PACKAGE_MANAGERS[asNumber - 1]);
129
- return;
161
+ const chosen = PACKAGE_MANAGERS[asNumber - 1];
162
+ if (chosen) {
163
+ finish(chosen);
164
+ return;
165
+ }
130
166
  }
131
167
  if (isPackageManager(value)) {
132
168
  finish(value);
@@ -142,25 +178,52 @@ export async function promptPackageManager(detection) {
142
178
  /**
143
179
  * Resolves the package manager to use for a new project.
144
180
  *
145
- * Order: explicit `--pm <name>` flag (validated hard - scripts must not hang
146
- * on a prompt) → interactive prompt (TTY only) → auto-detected default
147
- * (non-TTY, CI).
181
+ * Priority:
182
+ * 1. Explicit manager flag: `--pnpm`, `--bun`, `--npm`, `--yarn`
183
+ * 2. Explicit `--pm <name>` flag
184
+ * 3. Auto-detected from currently running environment (e.g. `bun create`, `pnpm dlx`, `npx`)
185
+ * 4. Auto-detected from current directory (packageManager field, lockfiles, or default)
186
+ *
187
+ * Automatically resolves without prompting.
148
188
  */
149
- export async function resolvePackageManager(options) {
150
- const detection = detectPackageManager(process.cwd());
189
+ export async function resolvePackageManager(options, cwd = process.cwd()) {
190
+ // 1. Explicit boolean flags: --pnpm, --bun, --npm, --yarn
191
+ if (options?.pnpm || options?.usePnpm) {
192
+ console.log("📦 Using package manager: pnpm (specified via --pnpm flag)");
193
+ return "pnpm";
194
+ }
195
+ if (options?.bun || options?.useBun) {
196
+ console.log("📦 Using package manager: bun (specified via --bun flag)");
197
+ return "bun";
198
+ }
199
+ if (options?.npm || options?.useNpm) {
200
+ console.log("📦 Using package manager: npm (specified via --npm flag)");
201
+ return "npm";
202
+ }
203
+ if (options?.yarn || options?.useYarn) {
204
+ console.log("📦 Using package manager: yarn (specified via --yarn flag)");
205
+ return "yarn";
206
+ }
207
+ // 2. Explicit --pm <name> flag
151
208
  if (options?.pm) {
152
209
  const requested = options.pm.trim().toLowerCase();
153
210
  if (isPackageManager(requested)) {
211
+ console.log(`📦 Using package manager: ${requested} (specified via --pm flag)`);
154
212
  return requested;
155
213
  }
156
214
  console.error(`Error: Unknown package manager "${options.pm}". Allowed: ${PACKAGE_MANAGERS.join(", ")}.`);
157
215
  process.exit(1);
158
216
  }
159
- if (!process.stdin.isTTY) {
160
- console.log(`📦 Using ${detection.pm} (auto-detected${detection.detail ? `: ${detection.detail}` : ""})`);
161
- return detection.pm;
217
+ // 3. Auto-detected from currently running execution environment
218
+ const running = detectRunningPackageManager();
219
+ if (running) {
220
+ console.log(`📦 Package manager detected: ${running} (from running environment)`);
221
+ return running;
162
222
  }
163
- return promptPackageManager(detection);
223
+ // 4. Auto-detected from directory context or framework default
224
+ const detection = detectPackageManager(cwd);
225
+ console.log(formatDetection(detection));
226
+ return detection.pm;
164
227
  }
165
228
  /**
166
229
  * Applies the chosen package manager to the freshly scaffolded project:
@@ -189,11 +252,11 @@ export function applyPackageManager(projectDir, pm) {
189
252
  // undefined in package.json to avoid a shadowing duplicate). Written
190
253
  // only when missing - an existing one is the source of truth.
191
254
  if (!fs.existsSync(pnpmWorkspace)) {
192
- fs.writeFileSync(pnpmWorkspace, 'packages:\n - "plugins/*"\n - "templates/*"\n', "utf-8");
255
+ fs.writeFileSync(pnpmWorkspace, 'packages:\n - "plugins/*"\n', "utf-8");
193
256
  }
194
257
  }
195
258
  else {
196
- pkg.workspaces = ["plugins/*", "templates/*"];
259
+ pkg.workspaces = ["plugins/*"];
197
260
  if (fs.existsSync(pnpmWorkspace)) {
198
261
  // Switching away from pnpm: the file would shadow the workspaces field.
199
262
  fs.rmSync(pnpmWorkspace);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-veap",
3
- "version": "0.1.4",
3
+ "version": "0.3.1",
4
4
  "description": "Initializer for Veap Framework applications",
5
5
  "bugs": "https://github.com/veapjs/create-veap/issues",
6
6
  "repository": {
@@ -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: