@django-stack/cli 0.12.0 → 0.12.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/dist/bin.js +28 -7
- package/dist/index.js +1 -1
- package/dist/{production-1O8-1QUl.js → production-lgZRSpyw.js} +35 -1
- package/package.json +1 -1
- package/templates/backend/pyproject.toml +1 -1
- package/templates/frontend-astro/package.json +1 -1
- package/templates/frontend-next/package.json +3 -3
- package/templates/frontend-nuxt/package.json +2 -2
- package/templates/frontend-sveltekit/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as describeMove, A as activeProject, B as DEFAULT_STACK, C as CLI_VERSION, D as CAPTCHA_APP, E as generateSecret, F as projectStack, G as applies, H as NODE_FRONTENDS, I as projectUrls, J as pendingChoices, L as readLocalRun, M as composeOutput, N as findProjectDirectory, O as RUN_DOMAIN, P as parseProfiles, Q as chooseFreePorts, R as readProject, S as validateTimeZone, T as generateProjectSecrets, U as PROMPT_ORDER, V as NAMED_PRESETS, W as STACK_OPTIONS, X as stackOption, Y as resolvePreset, Z as DEV_PORTS, _ as toProjectName, at as dockerRunning, b as usesValkey, c as frontendPackageManager, ct as
|
|
2
|
+
import { $ as describeMove, A as activeProject, B as DEFAULT_STACK, C as CLI_VERSION, D as CAPTCHA_APP, E as generateSecret, F as projectStack, G as applies, H as NODE_FRONTENDS, I as projectUrls, J as pendingChoices, L as readLocalRun, M as composeOutput, N as findProjectDirectory, O as RUN_DOMAIN, P as parseProfiles, Q as chooseFreePorts, R as readProject, S as validateTimeZone, T as generateProjectSecrets, U as PROMPT_ORDER, V as NAMED_PRESETS, W as STACK_OPTIONS, X as stackOption, Y as resolvePreset, Z as DEV_PORTS, _ as toProjectName, at as dockerRunning, b as usesValkey, c as frontendPackageManager, ct as removeLeftovers, d as lockFrontend, dt as setEnvValues, et as envPorts, f as normalizeDatabaseUrl, g as timeZones, h as setNotificationsApp, i as validateDomain, it as dockerNotRunning, j as compose, k as RUN_ENV, l as localS3, lt as parseEnv, m as scaffold, n as postgresUrl, nt as runDoctor, o as LOCAL_S3, ot as isDockerDown, p as relativeDirectory, q as encodePreset, r as productionEnv$1, rt as checkTools, s as cacheEnv, st as leftoverVolumes, t as missingS3, tt as portValues, u as lockBackend, ut as quoteEnvValue, v as umamiEnv, w as PACKAGE_NAME, x as validateProjectName, y as updateFrontendLock, z as runningServices } from "./production-lgZRSpyw.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, delimiter, dirname, join, posix, relative, resolve, sep } from "node:path";
|
|
@@ -3978,6 +3978,24 @@ function checkComputer(checks = checkTools()) {
|
|
|
3978
3978
|
});
|
|
3979
3979
|
return !checks.some((check) => !check.ok && !check.warning);
|
|
3980
3980
|
}
|
|
3981
|
+
/**
|
|
3982
|
+
* Docker keeps the volumes of a deleted project. A new project with the same
|
|
3983
|
+
* name would start on the old database, whose password is not the new one in
|
|
3984
|
+
* .env: "password authentication failed for user app". Offers to remove them.
|
|
3985
|
+
*/
|
|
3986
|
+
async function handleLeftovers(name, interactive) {
|
|
3987
|
+
const volumes = leftoverVolumes(name);
|
|
3988
|
+
if (!volumes.length) return;
|
|
3989
|
+
const removeCommand = command("docker compose down --volumes");
|
|
3990
|
+
p.log.warn(`Docker still has the data of an earlier project named ${pc.bold(name)} (${volumes.join(", ")}). The new project gets a new database password, so it cannot start on that database.`);
|
|
3991
|
+
if (interactive && unwrap(await p.confirm({
|
|
3992
|
+
message: `Remove the data of the earlier ${name}? Its database and uploads are deleted for good.`,
|
|
3993
|
+
initialValue: false
|
|
3994
|
+
}))) {
|
|
3995
|
+
if (removeLeftovers(name, volumes)) p.log.success(`Removed the data of the earlier ${name}.`);
|
|
3996
|
+
else fail("Could not remove it. Stop what uses it, or choose another --name.");
|
|
3997
|
+
} else p.log.warn(`Run ${removeCommand} in the new project before you start it, or choose another --name.`);
|
|
3998
|
+
}
|
|
3981
3999
|
async function init(directoryArgument, options) {
|
|
3982
4000
|
const interactive = isInteractive(options.yes);
|
|
3983
4001
|
intro("Create a project");
|
|
@@ -3999,6 +4017,7 @@ async function init(directoryArgument, options) {
|
|
|
3999
4017
|
validate: (value) => validateProjectName(value ?? "")
|
|
4000
4018
|
}));
|
|
4001
4019
|
}
|
|
4020
|
+
if (dockerReady) await handleLeftovers(name, interactive);
|
|
4002
4021
|
const stack = await chooseStack(options, interactive);
|
|
4003
4022
|
if (!applies("analytics", stack) && stack.analytics !== "off") {
|
|
4004
4023
|
if (options.fromCli("analytics")) fail("--analytics umami needs a frontend: a headless project has no pages to count.");
|
|
@@ -5066,6 +5085,12 @@ function nodeModulesVolume(project) {
|
|
|
5066
5085
|
return;
|
|
5067
5086
|
}
|
|
5068
5087
|
}
|
|
5088
|
+
/** The backend packages `dstack update` upgrades without `--all`. */
|
|
5089
|
+
const BACKEND_PACKAGES = [
|
|
5090
|
+
"django-stack",
|
|
5091
|
+
"django-headless",
|
|
5092
|
+
"django-content-studio"
|
|
5093
|
+
];
|
|
5069
5094
|
/** `dstack update`: newer images, newer DjangoStack packages, and a restart of what was running. */
|
|
5070
5095
|
async function update(options) {
|
|
5071
5096
|
const project = open(options);
|
|
@@ -5074,16 +5099,12 @@ async function update(options) {
|
|
|
5074
5099
|
const running = targets.filter((target) => runningServices(target).length > 0);
|
|
5075
5100
|
const lock = join(project.directory, "backend", "uv.lock");
|
|
5076
5101
|
if (existsSync(lock) && has("uv")) {
|
|
5077
|
-
const args = options.all ? ["lock", "--upgrade"] : [
|
|
5078
|
-
"lock",
|
|
5079
|
-
"--upgrade-package",
|
|
5080
|
-
"django-stack"
|
|
5081
|
-
];
|
|
5102
|
+
const args = options.all ? ["lock", "--upgrade"] : ["lock", ...BACKEND_PACKAGES.flatMap((name) => ["--upgrade-package", name])];
|
|
5082
5103
|
if (spawnSync("uv", args, {
|
|
5083
5104
|
cwd: join(project.directory, "backend"),
|
|
5084
5105
|
stdio: "inherit"
|
|
5085
5106
|
}).status !== 0) fail("uv could not update backend/uv.lock.");
|
|
5086
|
-
p.log.success(options.all ? "Updated backend/uv.lock" :
|
|
5107
|
+
p.log.success(options.all ? "Updated backend/uv.lock" : `Updated ${BACKEND_PACKAGES.join(", ")} in backend/uv.lock`);
|
|
5087
5108
|
} else if (existsSync(lock)) p.log.warn("uv is not installed, so backend/uv.lock stays as it is: https://docs.astral.sh/uv/");
|
|
5088
5109
|
if (frontendPackageManager(project.directory)) {
|
|
5089
5110
|
const lockfile = updateFrontendLock(project.directory, options.all);
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { B as DEFAULT_STACK, a as FRONTENDS, V as NAMED_PRESETS, W as STACK_OPTIONS, C as VERSION, s as cacheEnv, K as decodePreset, q as encodePreset, T as generateProjectSecrets, E as generateSecret, f as normalizeDatabaseUrl,
|
|
1
|
+
export { B as DEFAULT_STACK, a as FRONTENDS, V as NAMED_PRESETS, W as STACK_OPTIONS, C as VERSION, s as cacheEnv, K as decodePreset, q as encodePreset, T as generateProjectSecrets, E as generateSecret, f as normalizeDatabaseUrl, lt as parseEnv, J as pendingChoices, r as productionEnv, Y as resolvePreset, nt as runDoctor, m as scaffold, dt as setEnvValues, h as setNotificationsApp, _ as toProjectName, b as usesValkey, i as validateDomain, x as validateProjectName } from "./production-lgZRSpyw.js";
|
|
@@ -117,6 +117,40 @@ function dockerRunning(runCommand = run) {
|
|
|
117
117
|
"{{.Server.Version}}"
|
|
118
118
|
]));
|
|
119
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* The Docker volumes of an earlier Compose project with this name, such as
|
|
122
|
+
* `<name>_pgdata`. A new project with the same name would reuse them, and
|
|
123
|
+
* Postgres keeps the password of the data it was created with.
|
|
124
|
+
*/
|
|
125
|
+
function leftoverVolumes(name, runCommand = run) {
|
|
126
|
+
return (runCommand("docker", [
|
|
127
|
+
"volume",
|
|
128
|
+
"ls",
|
|
129
|
+
"--quiet",
|
|
130
|
+
"--filter",
|
|
131
|
+
`label=com.docker.compose.project=${name}`
|
|
132
|
+
]) ?? "").split("\n").filter(Boolean);
|
|
133
|
+
}
|
|
134
|
+
/** Removes the containers and volumes of the Compose project with this name. Returns whether it worked. */
|
|
135
|
+
function removeLeftovers(name, volumes, runCommand = run) {
|
|
136
|
+
const containers = (runCommand("docker", [
|
|
137
|
+
"ps",
|
|
138
|
+
"--all",
|
|
139
|
+
"--quiet",
|
|
140
|
+
"--filter",
|
|
141
|
+
`label=com.docker.compose.project=${name}`
|
|
142
|
+
]) ?? "").split("\n").filter(Boolean);
|
|
143
|
+
if (containers.length && runCommand("docker", [
|
|
144
|
+
"rm",
|
|
145
|
+
"--force",
|
|
146
|
+
...containers
|
|
147
|
+
]) === void 0) return false;
|
|
148
|
+
return runCommand("docker", [
|
|
149
|
+
"volume",
|
|
150
|
+
"rm",
|
|
151
|
+
...volumes
|
|
152
|
+
]) !== void 0;
|
|
153
|
+
}
|
|
120
154
|
/** Docker and Docker Compose, which run the project. */
|
|
121
155
|
function checkDocker({ run: runCommand = run, platform = process.platform } = {}) {
|
|
122
156
|
const client = parseVersion(runCommand("docker", ["--version"]));
|
|
@@ -1746,4 +1780,4 @@ function productionEnv(devEnv, options) {
|
|
|
1746
1780
|
todo
|
|
1747
1781
|
};
|
|
1748
1782
|
}
|
|
1749
|
-
export { describeMove as $, activeProject as A, DEFAULT_STACK as B, CLI_VERSION as C, CAPTCHA_APP as D, generateSecret as E, projectStack as F, applies as G, NODE_FRONTENDS as H, projectUrls as I, pendingChoices as J, decodePreset as K, readLocalRun as L, composeOutput as M, findProjectDirectory as N, RUN_DOMAIN as O, parseProfiles as P, chooseFreePorts as Q, readProject as R, validateTimeZone as S, generateProjectSecrets as T, PROMPT_ORDER as U, NAMED_PRESETS as V, STACK_OPTIONS as W, stackOption as X, resolvePreset as Y, DEV_PORTS as Z, toProjectName as _, FRONTENDS as a, dockerRunning as at, usesValkey as b, frontendPackageManager as c,
|
|
1783
|
+
export { describeMove as $, activeProject as A, DEFAULT_STACK as B, CLI_VERSION as C, CAPTCHA_APP as D, generateSecret as E, projectStack as F, applies as G, NODE_FRONTENDS as H, projectUrls as I, pendingChoices as J, decodePreset as K, readLocalRun as L, composeOutput as M, findProjectDirectory as N, RUN_DOMAIN as O, parseProfiles as P, chooseFreePorts as Q, readProject as R, validateTimeZone as S, generateProjectSecrets as T, PROMPT_ORDER as U, NAMED_PRESETS as V, STACK_OPTIONS as W, stackOption as X, resolvePreset as Y, DEV_PORTS as Z, toProjectName as _, FRONTENDS as a, dockerRunning as at, usesValkey as b, frontendPackageManager as c, removeLeftovers as ct, lockFrontend as d, setEnvValues as dt, envPorts as et, normalizeDatabaseUrl as f, timeZones as g, setNotificationsApp as h, validateDomain as i, dockerNotRunning as it, compose as j, RUN_ENV as k, localS3 as l, parseEnv as lt, scaffold as m, postgresUrl as n, runDoctor as nt, LOCAL_S3 as o, isDockerDown as ot, relativeDirectory as p, encodePreset as q, productionEnv as r, checkTools as rt, cacheEnv as s, leftoverVolumes as st, missingS3 as t, portValues as tt, lockBackend as u, quoteEnvValue as ut, umamiEnv as v, PACKAGE_NAME as w, validateProjectName as x, updateFrontendLock as y, runningServices as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@django-stack/cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "The production-ready batteries included Django stack. Create and manage DjangoStack projects: a Django backend, a frontend, Postgres and Docker Compose in one command.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Leon van der Grient",
|
|
@@ -5,7 +5,7 @@ description = "The Django backend of {{project_name}}."
|
|
|
5
5
|
requires-python = ">=3.12"
|
|
6
6
|
dependencies = [
|
|
7
7
|
"Django>=6.1,<6.2",
|
|
8
|
-
"django-stack[server,s3]>=0.12.
|
|
8
|
+
"django-stack[server,s3]>=0.12.1",
|
|
9
9
|
"django-headless[schema]>=1.1.1",
|
|
10
10
|
"django-content-studio[images,huey]>=1.11.0",
|
|
11
11
|
]
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@django-headless/client": "^1.1.1",
|
|
16
|
-
"@django-stack/next": "^0.12.
|
|
17
|
-
"@django-stack/react": "^0.12.
|
|
18
|
-
"@django-stack/utils": "^0.12.
|
|
16
|
+
"@django-stack/next": "^0.12.1",
|
|
17
|
+
"@django-stack/react": "^0.12.1",
|
|
18
|
+
"@django-stack/utils": "^0.12.1",
|
|
19
19
|
"next": "^16.4.4",
|
|
20
20
|
"react": "^19.3.1",
|
|
21
21
|
"react-dom": "^19.3.1",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@django-headless/client": "^1.1.1",
|
|
18
|
-
"@django-stack/utils": "^0.12.
|
|
19
|
-
"@django-stack/vue": "^0.12.
|
|
18
|
+
"@django-stack/utils": "^0.12.1",
|
|
19
|
+
"@django-stack/vue": "^0.12.1",
|
|
20
20
|
"nuxt": "^4.6.3",
|
|
21
21
|
"nuxt-security": "^2.7.0",
|
|
22
22
|
"vue": "^3.5.44",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@django-headless/client": "^1.1.1",
|
|
22
|
-
"@django-stack/svelte": "^0.12.
|
|
23
|
-
"@django-stack/utils": "^0.12.
|
|
22
|
+
"@django-stack/svelte": "^0.12.1",
|
|
23
|
+
"@django-stack/utils": "^0.12.1"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@sveltejs/adapter-node": "^6.0.1",
|