create-momentum-app 0.1.7 → 0.1.8
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/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ var import_picocolors2 = __toESM(require("picocolors"));
|
|
|
29
29
|
// apps/create-momentum-app/src/create-project.ts
|
|
30
30
|
var import_node_path = __toESM(require("node:path"));
|
|
31
31
|
var import_node_child_process = require("node:child_process");
|
|
32
|
+
var import_promises = require("node:timers/promises");
|
|
32
33
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
33
34
|
var import_picocolors = __toESM(require("picocolors"));
|
|
34
35
|
var TEMPLATE_EXT = ".tmpl";
|
|
@@ -66,8 +67,95 @@ function copyTemplateDir(srcDir, destDir, vars) {
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
}
|
|
70
|
+
function isDockerInstalled() {
|
|
71
|
+
try {
|
|
72
|
+
(0, import_node_child_process.execFileSync)("docker", ["--version"], { stdio: "pipe", timeout: 5e3, shell: true });
|
|
73
|
+
return true;
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function isDockerRunning() {
|
|
79
|
+
try {
|
|
80
|
+
(0, import_node_child_process.execFileSync)("docker", ["info"], { stdio: "pipe", timeout: 5e3, shell: true });
|
|
81
|
+
return true;
|
|
82
|
+
} catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function displayDockerInstallInstructions() {
|
|
87
|
+
console.log(import_picocolors.default.yellow("\n\u26A0\uFE0F Docker is not installed."));
|
|
88
|
+
console.log();
|
|
89
|
+
console.log("To use Docker for PostgreSQL, please install Docker:");
|
|
90
|
+
console.log();
|
|
91
|
+
const platform = process.platform;
|
|
92
|
+
if (platform === "darwin") {
|
|
93
|
+
console.log(
|
|
94
|
+
" macOS: Download Docker Desktop from https://www.docker.com/products/docker-desktop/"
|
|
95
|
+
);
|
|
96
|
+
} else if (platform === "linux") {
|
|
97
|
+
console.log(" Linux: Run the following command:");
|
|
98
|
+
console.log(import_picocolors.default.dim(" curl -fsSL https://get.docker.com | sh"));
|
|
99
|
+
console.log();
|
|
100
|
+
console.log(" Or install via your package manager:");
|
|
101
|
+
console.log(import_picocolors.default.dim(" sudo apt-get install docker.io docker-compose-plugin # Ubuntu/Debian"));
|
|
102
|
+
console.log(import_picocolors.default.dim(" sudo dnf install docker docker-compose-plugin # Fedora/RHEL"));
|
|
103
|
+
} else if (platform === "win32") {
|
|
104
|
+
console.log(
|
|
105
|
+
" Windows: Download Docker Desktop from https://www.docker.com/products/docker-desktop/"
|
|
106
|
+
);
|
|
107
|
+
console.log(" Note: Requires WSL2. See https://docs.docker.com/desktop/windows/install/");
|
|
108
|
+
} else {
|
|
109
|
+
console.log(" Visit https://docs.docker.com/get-docker/");
|
|
110
|
+
}
|
|
111
|
+
console.log();
|
|
112
|
+
console.log(
|
|
113
|
+
"You can still use an external PostgreSQL instance by updating the DATABASE_URL in .env"
|
|
114
|
+
);
|
|
115
|
+
console.log();
|
|
116
|
+
}
|
|
117
|
+
function startPostgresContainer(projectDir) {
|
|
118
|
+
try {
|
|
119
|
+
console.log(import_picocolors.default.dim("Starting PostgreSQL container..."));
|
|
120
|
+
(0, import_node_child_process.execFileSync)("docker", ["compose", "up", "-d"], {
|
|
121
|
+
cwd: projectDir,
|
|
122
|
+
stdio: "inherit",
|
|
123
|
+
shell: true
|
|
124
|
+
});
|
|
125
|
+
} catch (error) {
|
|
126
|
+
throw new Error(`Failed to start Docker container: ${error}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function waitForPostgres(projectDir, timeout = 3e4) {
|
|
130
|
+
return new Promise((resolve) => {
|
|
131
|
+
const startTime = Date.now();
|
|
132
|
+
const interval = 1e3;
|
|
133
|
+
const checkHealth = async () => {
|
|
134
|
+
while (Date.now() - startTime <= timeout) {
|
|
135
|
+
try {
|
|
136
|
+
(0, import_node_child_process.execFileSync)(
|
|
137
|
+
"docker",
|
|
138
|
+
["compose", "exec", "-T", "postgres", "pg_isready", "-U", "postgres"],
|
|
139
|
+
{
|
|
140
|
+
cwd: projectDir,
|
|
141
|
+
stdio: "pipe",
|
|
142
|
+
timeout: 5e3,
|
|
143
|
+
shell: true
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
resolve(true);
|
|
147
|
+
return;
|
|
148
|
+
} catch {
|
|
149
|
+
await (0, import_promises.setTimeout)(interval);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
resolve(false);
|
|
153
|
+
};
|
|
154
|
+
void checkHealth();
|
|
155
|
+
});
|
|
156
|
+
}
|
|
69
157
|
async function createProject(options) {
|
|
70
|
-
const { projectName, flavor, database, install, registry } = options;
|
|
158
|
+
const { projectName, flavor, database, install, docker, registry } = options;
|
|
71
159
|
const projectDir = import_node_path.default.resolve(process.cwd(), projectName);
|
|
72
160
|
if (import_fs_extra.default.existsSync(projectDir)) {
|
|
73
161
|
console.error(import_picocolors.default.red(`
|
|
@@ -96,7 +184,42 @@ const pool = (dbAdapter as PostgresAdapterWithRaw).getPool();` : "",
|
|
|
96
184
|
dbDevPackage: database === "postgres" ? "" : '"@types/better-sqlite3": "^7.6.13",',
|
|
97
185
|
envDbVar: database === "postgres" ? "DATABASE_URL=postgresql://postgres:postgres@localhost:5432/momentum" : "DATABASE_PATH=./data/momentum.db",
|
|
98
186
|
defaultPort: "4200",
|
|
99
|
-
externalDependencies: database === "postgres" ? '"pg", "pg-native"' : '"better-sqlite3"'
|
|
187
|
+
externalDependencies: database === "postgres" ? '"pg", "pg-native"' : '"better-sqlite3"',
|
|
188
|
+
prerequisitesDocker: database === "postgres" ? `- **Docker** (for PostgreSQL database)
|
|
189
|
+
- [macOS](https://www.docker.com/products/docker-desktop/)
|
|
190
|
+
- [Linux](https://docs.docker.com/engine/install/)
|
|
191
|
+
- [Windows](https://docs.docker.com/desktop/windows/install/) (requires WSL2)` : "",
|
|
192
|
+
databaseSection: database === "postgres" ? `### PostgreSQL
|
|
193
|
+
|
|
194
|
+
This project uses PostgreSQL via Docker. The database is configured in \`docker-compose.yml\`.
|
|
195
|
+
|
|
196
|
+
**Connection Details:**
|
|
197
|
+
- Host: \`localhost\`
|
|
198
|
+
- Port: \`5432\`
|
|
199
|
+
- Database: \`momentum\`
|
|
200
|
+
- Username: \`postgres\`
|
|
201
|
+
- Password: \`postgres\`
|
|
202
|
+
|
|
203
|
+
**Docker Commands:**
|
|
204
|
+
|
|
205
|
+
\`\`\`bash
|
|
206
|
+
# Start database
|
|
207
|
+
docker compose up -d
|
|
208
|
+
|
|
209
|
+
# Stop database
|
|
210
|
+
docker compose down
|
|
211
|
+
|
|
212
|
+
# Stop and remove data
|
|
213
|
+
docker compose down -v
|
|
214
|
+
|
|
215
|
+
# View logs
|
|
216
|
+
docker compose logs -f postgres
|
|
217
|
+
\`\`\`
|
|
218
|
+
|
|
219
|
+
You can also use an external PostgreSQL instance by updating \`DATABASE_URL\` in \`.env\`.` : `### SQLite
|
|
220
|
+
|
|
221
|
+
This project uses SQLite with the database file at \`./data/momentum.db\`.
|
|
222
|
+
The database is automatically created on first run - no setup required.`
|
|
100
223
|
};
|
|
101
224
|
console.log();
|
|
102
225
|
console.log(import_picocolors.default.cyan(`Creating ${import_picocolors.default.bold(projectName)} with ${flavor} + ${database}...`));
|
|
@@ -104,6 +227,51 @@ const pool = (dbAdapter as PostgresAdapterWithRaw).getPool();` : "",
|
|
|
104
227
|
import_fs_extra.default.ensureDirSync(projectDir);
|
|
105
228
|
copyTemplateDir(import_node_path.default.join(templatesDir, "shared"), projectDir, vars);
|
|
106
229
|
copyTemplateDir(import_node_path.default.join(templatesDir, flavor), projectDir, vars);
|
|
230
|
+
const envExample = import_node_path.default.join(projectDir, ".env.example");
|
|
231
|
+
const envFile = import_node_path.default.join(projectDir, ".env");
|
|
232
|
+
import_fs_extra.default.copyFileSync(envExample, envFile);
|
|
233
|
+
console.log(import_picocolors.default.dim("Created .env file"));
|
|
234
|
+
console.log();
|
|
235
|
+
if (database !== "postgres" || !docker) {
|
|
236
|
+
const dockerComposePath = import_node_path.default.join(projectDir, "docker-compose.yml");
|
|
237
|
+
if (import_fs_extra.default.existsSync(dockerComposePath)) {
|
|
238
|
+
import_fs_extra.default.removeSync(dockerComposePath);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
let dockerSetupSuccess = false;
|
|
242
|
+
if (database === "postgres" && docker) {
|
|
243
|
+
if (!isDockerInstalled()) {
|
|
244
|
+
displayDockerInstallInstructions();
|
|
245
|
+
} else if (!isDockerRunning()) {
|
|
246
|
+
console.log(import_picocolors.default.yellow("\n\u26A0\uFE0F Docker is installed but not running."));
|
|
247
|
+
console.log();
|
|
248
|
+
console.log("Please start Docker Desktop or run:");
|
|
249
|
+
console.log(import_picocolors.default.dim(" sudo systemctl start docker"));
|
|
250
|
+
console.log();
|
|
251
|
+
console.log("Then run:");
|
|
252
|
+
console.log(import_picocolors.default.dim(` cd ${projectName} && docker compose up -d`));
|
|
253
|
+
console.log();
|
|
254
|
+
} else {
|
|
255
|
+
try {
|
|
256
|
+
startPostgresContainer(projectDir);
|
|
257
|
+
const ready = await waitForPostgres(projectDir);
|
|
258
|
+
if (ready) {
|
|
259
|
+
console.log(import_picocolors.default.green("\u2713 PostgreSQL ready at localhost:5432"));
|
|
260
|
+
console.log();
|
|
261
|
+
dockerSetupSuccess = true;
|
|
262
|
+
} else {
|
|
263
|
+
console.log(import_picocolors.default.yellow("\u26A0\uFE0F PostgreSQL container started but not ready yet."));
|
|
264
|
+
console.log(import_picocolors.default.dim(" Check status: docker compose logs -f"));
|
|
265
|
+
console.log();
|
|
266
|
+
}
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.log(import_picocolors.default.yellow(`
|
|
269
|
+
\u26A0\uFE0F Failed to start PostgreSQL: ${error}`));
|
|
270
|
+
console.log(import_picocolors.default.dim(" Try manually: cd " + projectName + " && docker compose up -d"));
|
|
271
|
+
console.log();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
107
275
|
if (install) {
|
|
108
276
|
console.log(import_picocolors.default.dim("Installing dependencies..."));
|
|
109
277
|
const args = ["install"];
|
|
@@ -112,7 +280,8 @@ const pool = (dbAdapter as PostgresAdapterWithRaw).getPool();` : "",
|
|
|
112
280
|
}
|
|
113
281
|
(0, import_node_child_process.execFileSync)("npm", args, {
|
|
114
282
|
cwd: projectDir,
|
|
115
|
-
stdio: "inherit"
|
|
283
|
+
stdio: "inherit",
|
|
284
|
+
shell: true
|
|
116
285
|
});
|
|
117
286
|
console.log();
|
|
118
287
|
}
|
|
@@ -124,6 +293,9 @@ const pool = (dbAdapter as PostgresAdapterWithRaw).getPool();` : "",
|
|
|
124
293
|
if (!install) {
|
|
125
294
|
console.log(import_picocolors.default.dim(" npm install"));
|
|
126
295
|
}
|
|
296
|
+
if (database === "postgres" && docker && !dockerSetupSuccess) {
|
|
297
|
+
console.log(import_picocolors.default.dim(" docker compose up -d"));
|
|
298
|
+
}
|
|
127
299
|
console.log(import_picocolors.default.dim(" npm run dev"));
|
|
128
300
|
console.log();
|
|
129
301
|
console.log(import_picocolors.default.dim(" Open http://localhost:" + vars.defaultPort + "/admin"));
|
|
@@ -150,6 +322,8 @@ function parseArgs(argv) {
|
|
|
150
322
|
}
|
|
151
323
|
} else if (arg === "--no-install") {
|
|
152
324
|
opts.install = false;
|
|
325
|
+
} else if (arg === "--docker") {
|
|
326
|
+
opts.docker = true;
|
|
153
327
|
} else if (arg === "--registry" && args[i + 1]) {
|
|
154
328
|
opts.registry = args[++i];
|
|
155
329
|
} else if (!arg.startsWith("-") && !opts.projectName) {
|
|
@@ -199,6 +373,12 @@ async function runCLI() {
|
|
|
199
373
|
name: "install",
|
|
200
374
|
message: "Install dependencies?",
|
|
201
375
|
initial: true
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
type: cliArgs.docker !== void 0 || cliArgs.database !== "postgres" ? null : "confirm",
|
|
379
|
+
name: "docker",
|
|
380
|
+
message: "Set up PostgreSQL with Docker?",
|
|
381
|
+
initial: true
|
|
202
382
|
}
|
|
203
383
|
],
|
|
204
384
|
{
|
|
@@ -208,11 +388,13 @@ async function runCLI() {
|
|
|
208
388
|
}
|
|
209
389
|
}
|
|
210
390
|
);
|
|
391
|
+
const database = cliArgs.database ?? response.database;
|
|
211
392
|
const options = {
|
|
212
393
|
projectName: cliArgs.projectName ?? response.projectName,
|
|
213
394
|
flavor: cliArgs.flavor ?? response.flavor,
|
|
214
|
-
database
|
|
395
|
+
database,
|
|
215
396
|
install: cliArgs.install ?? response.install ?? true,
|
|
397
|
+
docker: database === "postgres" ? cliArgs.docker ?? response.docker ?? false : false,
|
|
216
398
|
registry: cliArgs.registry
|
|
217
399
|
};
|
|
218
400
|
await createProject(options);
|
package/package.json
CHANGED
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
A [Momentum CMS](https://github.com/momentum-cms/momentum-cms) application.
|
|
4
4
|
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- **Node.js** 20 or higher
|
|
8
|
+
{{prerequisitesDocker}}
|
|
9
|
+
|
|
10
|
+
## Database
|
|
11
|
+
|
|
12
|
+
{{databaseSection}}
|
|
13
|
+
|
|
5
14
|
## Getting Started
|
|
6
15
|
|
|
7
16
|
```bash
|
|
8
|
-
# Copy environment variables
|
|
9
|
-
cp .env.example .env
|
|
10
|
-
|
|
11
17
|
# Start the dev server
|
|
12
18
|
npm run dev
|
|
13
19
|
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Docker Compose configuration for {{projectName}}
|
|
2
|
+
# This file sets up a PostgreSQL database for local development
|
|
3
|
+
# For production, consider using managed database services
|
|
4
|
+
|
|
5
|
+
services:
|
|
6
|
+
postgres:
|
|
7
|
+
image: postgres:16-alpine
|
|
8
|
+
container_name: {{projectName}}-postgres
|
|
9
|
+
restart: unless-stopped
|
|
10
|
+
ports:
|
|
11
|
+
- "5432:5432"
|
|
12
|
+
environment:
|
|
13
|
+
POSTGRES_USER: postgres
|
|
14
|
+
POSTGRES_PASSWORD: postgres
|
|
15
|
+
POSTGRES_DB: momentum
|
|
16
|
+
volumes:
|
|
17
|
+
- {{projectName}}_postgres_data:/var/lib/postgresql/data
|
|
18
|
+
healthcheck:
|
|
19
|
+
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
20
|
+
interval: 5s
|
|
21
|
+
timeout: 5s
|
|
22
|
+
retries: 5
|
|
23
|
+
|
|
24
|
+
volumes:
|
|
25
|
+
{{projectName}}_postgres_data:
|
|
26
|
+
driver: local
|