create-ragen-app 0.6.1 → 0.7.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/dist/tasks.js CHANGED
@@ -1,13 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROFILE_PUBLISHED_PORTS = exports.RUSTFS_PUBLISHED_PORTS = exports.PII_PUBLISHED_PORTS = exports.PUBLISHED_PORTS = void 0;
3
4
  exports.isDockerAvailable = isDockerAvailable;
4
- exports.ragenStackVolumeExists = ragenStackVolumeExists;
5
+ exports.normalizeComposeProjectName = normalizeComposeProjectName;
6
+ exports.resolveComposeProjectName = resolveComposeProjectName;
7
+ exports.publishedPortsFor = publishedPortsFor;
8
+ exports.composeUpCommand = composeUpCommand;
9
+ exports.busyPublishedPorts = busyPublishedPorts;
5
10
  exports.startDockerServices = startDockerServices;
6
11
  exports.installDependencies = installDependencies;
7
12
  exports.generatePrismaClient = generatePrismaClient;
8
13
  exports.seedDatabase = seedDatabase;
9
14
  exports.migrateDatabase = migrateDatabase;
15
+ const node_crypto_1 = require("node:crypto");
16
+ const node_net_1 = require("node:net");
17
+ const node_path_1 = require("node:path");
10
18
  const execa_1 = require("execa");
19
+ const pii_masking_1 = require("./pii-masking");
20
+ const storage_provider_1 = require("./storage-provider");
11
21
  async function isDockerAvailable() {
12
22
  try {
13
23
  // A stuck `docker info` (e.g. Docker Desktop still starting up) would
@@ -21,31 +31,196 @@ async function isDockerAvailable() {
21
31
  }
22
32
  }
23
33
  /**
24
- * Whether this Docker daemon already runs a Ragen stack.
34
+ * Compose accepts `[a-z0-9][a-z0-9_-]*`. A directory called `My Ragen!` or
35
+ * `.ragen` is perfectly legal and would otherwise make every compose command
36
+ * fail with a validation error after the install had finished.
37
+ */
38
+ function normalizeComposeProjectName(raw) {
39
+ const cleaned = raw
40
+ .toLowerCase()
41
+ .replace(/[^a-z0-9_-]+/g, '-')
42
+ .replace(/^[^a-z0-9]+/, '')
43
+ .replace(/-+$/, '');
44
+ return cleaned || 'ragen';
45
+ }
46
+ /** Six hex characters of the absolute path — stable for this directory. */
47
+ function pathSuffix(absoluteDir) {
48
+ return (0, node_crypto_1.createHash)('sha256').update(absoluteDir).digest('hex').slice(0, 6);
49
+ }
50
+ /**
51
+ * Whether a compose file belongs to the install in `absoluteDir`.
25
52
  *
26
- * docker-compose.yml pins container, volume and network names instead of
27
- * letting Compose prefix them per project, so a second install does not just
28
- * collide on the container names — it silently attaches to the *same*
29
- * postgres and qdrant volumes as the first one. Checking the volume rather
30
- * than a container catches a stack that is merely stopped, which is the
31
- * case that looks safest and is not.
53
+ * `relative()` rather than a `startsWith(dir + '/')` prefix test, for two
54
+ * reasons: on Windows `resolve()` returns backslashes, so a forward-slash
55
+ * prefix never matches and every re-run would look like a collision — which
56
+ * renames the stack and abandons its volumes, the worst outcome available
57
+ * here. And a prefix test is true for `/work/ragen-app-2` against
58
+ * `/work/ragen-app` unless the separator is appended exactly right.
32
59
  *
33
- * Reads RAGEN_STACK_NAME for the same reason compose does: someone already
34
- * running a stack under a name of their own would otherwise be told their
35
- * machine is clear, and collide with it.
60
+ * A file *inside* the directory counts, at any depth: `-f infra/compose.yml`
61
+ * is a legitimate way to run this stack, and treating it as someone else's
62
+ * project is the same destructive mistake.
36
63
  */
37
- async function ragenStackVolumeExists() {
38
- const stackName = process.env.RAGEN_STACK_NAME?.trim() || 'ragen';
39
- const postgresVolume = `${stackName}-postgres-data`;
64
+ function isInsideDirectory(file, absoluteDir) {
65
+ const path = (0, node_path_1.relative)(absoluteDir, (0, node_path_1.resolve)(file.trim()));
66
+ // `..` means outside; an absolute result means a different Windows drive,
67
+ // where "inside" is not a question that has a yes.
68
+ return !path.startsWith('..') && !(0, node_path_1.isAbsolute)(path);
69
+ }
70
+ async function resolveComposeProjectName(targetDir) {
71
+ const absoluteDir = (0, node_path_1.resolve)(targetDir);
72
+ const base = normalizeComposeProjectName((0, node_path_1.basename)(absoluteDir));
73
+ const suffixed = `${base}-${pathSuffix(absoluteDir)}`;
74
+ let projects = [];
40
75
  try {
41
- const { stdout } = await (0, execa_1.execa)('docker', ['volume', 'ls', '--format', '{{.Name}}'], { timeout: 10_000 });
42
- return stdout.split('\n').some((name) => name.trim() === postgresVolume);
76
+ const { stdout } = await (0, execa_1.execa)('docker', ['compose', 'ls', '--all', '--format', 'json'], { timeout: 10_000 });
77
+ projects = JSON.parse(stdout);
43
78
  }
44
79
  catch {
45
- // Same reasoning as isDockerAvailable: an unreachable daemon is not a
46
- // reason to fail, the caller is about to find that out anyway.
47
- return false;
80
+ // An unreachable daemon, or a Compose too old for `ls --format json`.
81
+ //
82
+ // The plain basename is *not* the safe answer here, which is what it first
83
+ // looked like. A daemon that cannot be reached still holds the volumes of
84
+ // every install made before it stopped, and they collide as soon as it
85
+ // starts — so falling back to the basename fails in the silent, expensive
86
+ // direction: a second install quietly opening the first one's database.
87
+ // The suffix fails in the visible, cheap one: a less pretty name in
88
+ // `docker ps`.
89
+ return { name: suffixed, disambiguated: true, daemonUnreachable: true };
48
90
  }
91
+ // A project whose compose files live under *this* directory is this install
92
+ // — a re-run of the wizard over an existing tree — and must keep its name,
93
+ // or the second run would point at empty volumes.
94
+ const collision = projects.find((project) => project.Name === base &&
95
+ !(project.ConfigFiles ?? '')
96
+ .split(',')
97
+ .some((file) => isInsideDirectory(file, absoluteDir)));
98
+ if (!collision) {
99
+ return { name: base, disambiguated: false };
100
+ }
101
+ return {
102
+ name: suffixed,
103
+ disambiguated: true,
104
+ takenBy: collision.ConfigFiles?.split(',')[0]?.trim(),
105
+ };
106
+ }
107
+ /**
108
+ * Every host port a default `docker compose up` publishes, with the variable
109
+ * that moves it. The order is the order the warning prints them in.
110
+ *
111
+ * Defaults are duplicated from docker-compose.yml rather than parsed out of
112
+ * it, because this runs *before* the repository is cloned — there is no file
113
+ * to read yet. `ports-agree-with-compose.test.ts` holds the two in step.
114
+ */
115
+ exports.PUBLISHED_PORTS = [
116
+ { service: 'Postgres', variable: 'POSTGRES_PORT', port: 55432 },
117
+ { service: 'Qdrant', variable: 'QDRANT_PORT', port: 6333 },
118
+ { service: 'Qdrant (gRPC)', variable: 'QDRANT_GRPC_PORT', port: 6334 },
119
+ { service: 'Docling', variable: 'DOCLING_PORT', port: 5001 },
120
+ { service: 'Redis', variable: 'REDIS_PORT', port: 56379 },
121
+ ];
122
+ /** The two more, behind the `pii` profile, that only a masking install starts. */
123
+ exports.PII_PUBLISHED_PORTS = [
124
+ {
125
+ service: 'Presidio analyzer',
126
+ variable: 'PRESIDIO_ANALYZER_PORT',
127
+ port: 5002,
128
+ },
129
+ {
130
+ service: 'Presidio anonymizer',
131
+ variable: 'PRESIDIO_ANONYMIZER_PORT',
132
+ port: 5003,
133
+ },
134
+ ];
135
+ /**
136
+ * The two more, behind the `s3` profile, that only a RustFS install starts:
137
+ * the S3 API the apps talk to, and the web console.
138
+ */
139
+ exports.RUSTFS_PUBLISHED_PORTS = [
140
+ { service: 'RustFS (S3 API)', variable: 'RUSTFS_PORT', port: 59000 },
141
+ {
142
+ service: 'RustFS console',
143
+ variable: 'RUSTFS_CONSOLE_PORT',
144
+ port: 59001,
145
+ },
146
+ ];
147
+ /**
148
+ * The extra ports each optional profile publishes, keyed by profile name.
149
+ *
150
+ * One table rather than a branch per profile, because the port probe, the
151
+ * recovery command and the "update .env.local" hint all have to agree on what
152
+ * a profile starts — and with two profiles the branch-per-profile version was
153
+ * already printing a command that named only one of them.
154
+ */
155
+ exports.PROFILE_PUBLISHED_PORTS = {
156
+ [pii_masking_1.PII_COMPOSE_PROFILE]: exports.PII_PUBLISHED_PORTS,
157
+ [storage_provider_1.RUSTFS_COMPOSE_PROFILE]: exports.RUSTFS_PUBLISHED_PORTS,
158
+ };
159
+ /** Every port a `docker compose up` with these profiles publishes. */
160
+ function publishedPortsFor(profiles) {
161
+ return [
162
+ ...exports.PUBLISHED_PORTS,
163
+ ...profiles.flatMap((profile) => exports.PROFILE_PUBLISHED_PORTS[profile] ?? []),
164
+ ];
165
+ }
166
+ /**
167
+ * The `docker compose up` a person should type to get the stack this install
168
+ * configured, profiles included.
169
+ *
170
+ * Built from the same list `startDockerServices` is given, so a printed
171
+ * command cannot drift from an executed one. A command that drops a profile
172
+ * starts a stack without the services whose URLs were just written to
173
+ * `.env.local` — the half-configuration the profiles exist to prevent, only
174
+ * printed instead of executed.
175
+ */
176
+ function composeUpCommand(profiles = []) {
177
+ return [
178
+ 'docker compose',
179
+ ...profiles.map((profile) => `--profile ${profile}`),
180
+ 'up -d',
181
+ ].join(' ');
182
+ }
183
+ /**
184
+ * Which of these host ports something is already listening on.
185
+ *
186
+ * This replaces a check for the volume `ragen-postgres-data`. That volume name
187
+ * was pinned in docker-compose.yml, which is what made a second install share
188
+ * the first one's database — and removing the pin removed the sharing, so the
189
+ * old check now answers a question nobody is asking and would answer "clear"
190
+ * for every install made after the change. A guard that quietly stops firing
191
+ * is worse than no guard.
192
+ *
193
+ * Ports are what is genuinely left: Compose prefixes names per project, and
194
+ * prefixes nothing about a published port, so two stacks still collide on
195
+ * 55432. Binding is also a better probe than asking Docker — it sees a native
196
+ * Postgres on the port as well, which is the other way this install ends up
197
+ * talking to a database it did not start.
198
+ */
199
+ async function busyPublishedPorts(candidates = exports.PUBLISHED_PORTS) {
200
+ const results = await Promise.all(candidates.map(async (candidate) => (await isPortInUse(candidate.port)) ? candidate : undefined));
201
+ return results.filter((candidate) => Boolean(candidate));
202
+ }
203
+ /**
204
+ * Loopback only, because that is where docker-compose.yml publishes
205
+ * (`RAGEN_BIND_ADDR` defaults to 127.0.0.1). Anything other than EADDRINUSE —
206
+ * a permission error, a system without IPv4 loopback — reports "free": the
207
+ * cost of a missed warning is a compose error the caller then reads, and the
208
+ * cost of a false one is telling someone their machine is occupied when it is
209
+ * not.
210
+ */
211
+ function isPortInUse(port) {
212
+ return new Promise((resolve) => {
213
+ const server = (0, node_net_1.createServer)();
214
+ server.once('error', (error) => {
215
+ resolve(error.code === 'EADDRINUSE');
216
+ });
217
+ server.once('listening', () => {
218
+ server.close(() => {
219
+ resolve(false);
220
+ });
221
+ });
222
+ server.listen(port, '127.0.0.1');
223
+ });
49
224
  }
50
225
  /**
51
226
  * `profiles` names compose profiles to add to the default set.
@@ -53,6 +228,8 @@ async function ragenStackVolumeExists() {
53
228
  * Without it, choosing PII masking would write the two Presidio URLs and start
54
229
  * nothing behind them: those services sit behind compose's `pii` profile, so a
55
230
  * plain `up -d` skips them and the app would point at containers nobody ran.
231
+ * RustFS is the same shape behind `s3` — the apps would be configured for an
232
+ * object store on 59000 that nothing started, and fail at the first upload.
56
233
  */
57
234
  async function startDockerServices({ cwd, profiles = [], }) {
58
235
  const args = profiles.flatMap((profile) => ['--profile', profile]);
package/dist/tasks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ragen-app",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "private": false,
5
5
  "description": "Scaffold a self-hosted Ragen AI installation with one command",
6
6
  "license": "Apache-2.0",
@@ -20,7 +20,7 @@
20
20
  "directory": "packages/create-ragen-app"
21
21
  },
22
22
  "scripts": {
23
- "build": "tsc -p tsconfig.json",
23
+ "build": "tsc -p tsconfig.json && chmod +x dist/index.js",
24
24
  "clean": "rm -rf dist",
25
25
  "prepack": "npm run clean && npm run build",
26
26
  "lint": "eslint",
@@ -39,6 +39,6 @@
39
39
  "typescript": "~5.7.0"
40
40
  },
41
41
  "engines": {
42
- "node": ">=24"
42
+ "node": "^24.15.0 || >=26.0.0"
43
43
  }
44
44
  }