komplian 0.5.0 → 0.5.3
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/KOMPLIAN_DATABASE_URLS.env.example +4 -2
- package/komplian-db.mjs +84 -29
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ KOMPLIAN_DATABASE_URL_ADMIN_STAGING=
|
|
|
12
12
|
KOMPLIAN_DATABASE_URL_ADMIN_PRODUCTION=
|
|
13
13
|
|
|
14
14
|
# --- Web / pilot DB ---
|
|
15
|
-
KOMPLIAN_DATABASE_URL_WEB_DEVELOPMENT=
|
|
15
|
+
KOMPLIAN_DATABASE_URL_WEB_DEVELOPMENT=postgresql://neondb_owner:npg_1crYb3PaCjlf@ep-frosty-bird-agql4oq5-pooler.c-2.eu-central-1.aws.neon.tech/neondb?sslmode=require&channel_binding=require
|
|
16
16
|
KOMPLIAN_DATABASE_URL_WEB_STAGING=
|
|
17
17
|
KOMPLIAN_DATABASE_URL_WEB_PRODUCTION=
|
|
18
18
|
|
|
@@ -22,5 +22,7 @@ KOMPLIAN_DATABASE_URL_WEB_PRODUCTION=
|
|
|
22
22
|
# Operador para comprobar acceso a producción (alternativa: git config user.email).
|
|
23
23
|
# KOMPLIAN_DATABASE_OPERATOR_EMAIL=josue.santana@komplian.com
|
|
24
24
|
|
|
25
|
-
#
|
|
25
|
+
# Staging/producción: host debe ser Neon (*.neon.tech), salvo:
|
|
26
26
|
# KOMPLIAN_DATABASE_ALLOW_NON_NEON=1
|
|
27
|
+
# Development: Postgres local está permitido (mensaje informativo). Para exigir Neon también en dev:
|
|
28
|
+
# KOMPLIAN_DATABASE_REQUIRE_NEON_DEVELOPMENT=1
|
package/komplian-db.mjs
CHANGED
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
* Producción: solo emails @komplian.com en KOMPLIAN_DATABASE_PRODUCTION_ALLOWLIST
|
|
17
17
|
* (por defecto josue.santana@komplian.com). Operador: KOMPLIAN_DATABASE_OPERATOR_EMAIL o git config user.email.
|
|
18
18
|
*
|
|
19
|
-
* Neon:
|
|
19
|
+
* Neon: staging/producción exigen *.neon.tech (salvo KOMPLIAN_DATABASE_ALLOW_NON_NEON=1).
|
|
20
|
+
* Development: permite host no Neon (Postgres local); aviso en consola. Forzar Neon en dev: KOMPLIAN_DATABASE_REQUIRE_NEON_DEVELOPMENT=1
|
|
20
21
|
*/
|
|
21
22
|
|
|
22
23
|
import { spawn, spawnSync } from "node:child_process";
|
|
@@ -52,6 +53,32 @@ const ENVIRONMENTS = new Set(["development", "staging", "production"]);
|
|
|
52
53
|
/** Lista por defecto si no configuras KOMPLIAN_DATABASE_PRODUCTION_ALLOWLIST */
|
|
53
54
|
const DEFAULT_PRODUCTION_ALLOWLIST = ["josue.santana@komplian.com"];
|
|
54
55
|
|
|
56
|
+
/** Misma cadena que `komplian-localhost.mjs` cuando no hay URL real. */
|
|
57
|
+
const LOCALHOST_DB_PLACEHOLDER = "komplian_localhost_placeholder";
|
|
58
|
+
|
|
59
|
+
function isPlaceholderDbUrl(url) {
|
|
60
|
+
return !!(url && String(url).includes(LOCALHOST_DB_PLACEHOLDER));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Primera URL no vacía que no sea el placeholder de localhost. */
|
|
64
|
+
function pickFirstNonPlaceholder(...candidates) {
|
|
65
|
+
for (const c of candidates) {
|
|
66
|
+
const u = (c ?? "").trim();
|
|
67
|
+
if (u && !isPlaceholderDbUrl(u)) return u;
|
|
68
|
+
}
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function assertNotPlaceholderDbUrl(url) {
|
|
73
|
+
if (!isPlaceholderDbUrl(url)) return;
|
|
74
|
+
log(
|
|
75
|
+
`${c.red}✗${c.reset} La URL es el ${c.bold}placeholder${c.reset} de \`komplian localhost\` (no apunta a una base de datos real).`
|
|
76
|
+
);
|
|
77
|
+
log(``);
|
|
78
|
+
log(` Pon una URL real (raíz del monorepo: ${c.dim}KOMPLIAN_LOCALHOST_*_DATABASE_URL${c.reset}, ${c.dim}KOMPLIAN_DATABASE_URLS.env${c.reset}, o ${c.dim}--url${c.reset}).`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
55
82
|
function parseEnvFile(content) {
|
|
56
83
|
const out = {};
|
|
57
84
|
for (const line of content.split(/\r?\n/)) {
|
|
@@ -170,17 +197,31 @@ function loadProductionAllowlist(workspaceRoot) {
|
|
|
170
197
|
return DEFAULT_PRODUCTION_ALLOWLIST.map((e) => e.toLowerCase());
|
|
171
198
|
}
|
|
172
199
|
|
|
173
|
-
function assertNeonHost(url) {
|
|
200
|
+
function assertNeonHost(url, environment) {
|
|
174
201
|
if (process.env.KOMPLIAN_DATABASE_ALLOW_NON_NEON === "1") return;
|
|
175
202
|
try {
|
|
176
203
|
const u = new URL(url);
|
|
177
204
|
const h = u.hostname.toLowerCase();
|
|
178
|
-
|
|
205
|
+
const isNeon = h.includes("neon.tech");
|
|
206
|
+
if (isNeon) return;
|
|
207
|
+
|
|
208
|
+
if (environment === "development") {
|
|
209
|
+
if (process.env.KOMPLIAN_DATABASE_REQUIRE_NEON_DEVELOPMENT === "1") {
|
|
210
|
+
log(
|
|
211
|
+
`${c.red}✗${c.reset} Development: host no Neon (${u.hostname}). Quita ${c.dim}KOMPLIAN_DATABASE_REQUIRE_NEON_DEVELOPMENT${c.reset} o usa URL *.neon.tech.`
|
|
212
|
+
);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
179
215
|
log(
|
|
180
|
-
`${c.
|
|
216
|
+
`${c.dim}○${c.reset} Development: conexión no Neon (${u.hostname}). Staging/producción siguen exigiendo *.neon.tech.`
|
|
181
217
|
);
|
|
182
|
-
|
|
218
|
+
return;
|
|
183
219
|
}
|
|
220
|
+
|
|
221
|
+
log(
|
|
222
|
+
`${c.red}✗${c.reset} Solo hosts Neon (postgresql://*.neon.tech). Para excepciones: ${c.dim}KOMPLIAN_DATABASE_ALLOW_NON_NEON=1${c.reset}`
|
|
223
|
+
);
|
|
224
|
+
process.exit(1);
|
|
184
225
|
} catch {
|
|
185
226
|
log(`${c.red}✗${c.reset} URL de base de datos inválida.`);
|
|
186
227
|
process.exit(1);
|
|
@@ -230,34 +271,40 @@ function resolveDatabaseUrl(workspaceRoot, platform, environment) {
|
|
|
230
271
|
const envU = environment.toUpperCase();
|
|
231
272
|
const primaryKey = `KOMPLIAN_DATABASE_URL_${dbKey}_${envU}`;
|
|
232
273
|
|
|
233
|
-
let url =
|
|
234
|
-
process.env[primaryKey]
|
|
274
|
+
let url = pickFirstNonPlaceholder(
|
|
275
|
+
process.env[primaryKey],
|
|
276
|
+
file[primaryKey]
|
|
277
|
+
);
|
|
235
278
|
|
|
236
279
|
if (environment === "development" && !url) {
|
|
237
|
-
const single =
|
|
238
|
-
process.env.KOMPLIAN_LOCALHOST_DATABASE_URL
|
|
239
|
-
file.KOMPLIAN_LOCALHOST_DATABASE_URL
|
|
280
|
+
const single = pickFirstNonPlaceholder(
|
|
281
|
+
process.env.KOMPLIAN_LOCALHOST_DATABASE_URL,
|
|
282
|
+
file.KOMPLIAN_LOCALHOST_DATABASE_URL
|
|
283
|
+
);
|
|
240
284
|
if (dbKey === "APP") {
|
|
241
|
-
url =
|
|
242
|
-
process.env.KOMPLIAN_LOCALHOST_APP_DATABASE_URL
|
|
243
|
-
file.KOMPLIAN_LOCALHOST_APP_DATABASE_URL
|
|
244
|
-
single
|
|
245
|
-
readEnvLocalKey(workspaceRoot, "app", ["DATABASE_URL"])
|
|
246
|
-
readEnvLocalKey(workspaceRoot, "api", ["APP_DATABASE_URL"])
|
|
285
|
+
url = pickFirstNonPlaceholder(
|
|
286
|
+
process.env.KOMPLIAN_LOCALHOST_APP_DATABASE_URL,
|
|
287
|
+
file.KOMPLIAN_LOCALHOST_APP_DATABASE_URL,
|
|
288
|
+
single,
|
|
289
|
+
readEnvLocalKey(workspaceRoot, "app", ["DATABASE_URL"]),
|
|
290
|
+
readEnvLocalKey(workspaceRoot, "api", ["APP_DATABASE_URL"])
|
|
291
|
+
);
|
|
247
292
|
} else if (dbKey === "ADMIN") {
|
|
248
|
-
url =
|
|
249
|
-
process.env.KOMPLIAN_LOCALHOST_ADMIN_DATABASE_URL
|
|
250
|
-
file.KOMPLIAN_LOCALHOST_ADMIN_DATABASE_URL
|
|
251
|
-
single
|
|
252
|
-
readEnvLocalKey(workspaceRoot, "admin", ["DATABASE_URL"])
|
|
253
|
-
readEnvLocalKey(workspaceRoot, "api", ["ADMIN_DATABASE_URL"])
|
|
293
|
+
url = pickFirstNonPlaceholder(
|
|
294
|
+
process.env.KOMPLIAN_LOCALHOST_ADMIN_DATABASE_URL,
|
|
295
|
+
file.KOMPLIAN_LOCALHOST_ADMIN_DATABASE_URL,
|
|
296
|
+
single,
|
|
297
|
+
readEnvLocalKey(workspaceRoot, "admin", ["DATABASE_URL"]),
|
|
298
|
+
readEnvLocalKey(workspaceRoot, "api", ["ADMIN_DATABASE_URL"])
|
|
299
|
+
);
|
|
254
300
|
} else if (dbKey === "WEB") {
|
|
255
|
-
url =
|
|
256
|
-
process.env.KOMPLIAN_LOCALHOST_WEB_DATABASE_URL
|
|
257
|
-
file.KOMPLIAN_LOCALHOST_WEB_DATABASE_URL
|
|
258
|
-
single
|
|
259
|
-
readEnvLocalKey(workspaceRoot, "web", ["DATABASE_URL"])
|
|
260
|
-
readEnvLocalKey(workspaceRoot, "api", ["WEB_DATABASE_URL"])
|
|
301
|
+
url = pickFirstNonPlaceholder(
|
|
302
|
+
process.env.KOMPLIAN_LOCALHOST_WEB_DATABASE_URL,
|
|
303
|
+
file.KOMPLIAN_LOCALHOST_WEB_DATABASE_URL,
|
|
304
|
+
single,
|
|
305
|
+
readEnvLocalKey(workspaceRoot, "web", ["DATABASE_URL"]),
|
|
306
|
+
readEnvLocalKey(workspaceRoot, "api", ["WEB_DATABASE_URL"])
|
|
307
|
+
);
|
|
261
308
|
}
|
|
262
309
|
}
|
|
263
310
|
|
|
@@ -342,6 +389,7 @@ function usageDb() {
|
|
|
342
389
|
log(` ${c.dim}KOMPLIAN_DATABASE_URL_APP_DEVELOPMENT${c.reset}`);
|
|
343
390
|
log(` ${c.dim}KOMPLIAN_DATABASE_URL_APP_STAGING / _PRODUCTION${c.reset} (idem ADMIN, WEB)`);
|
|
344
391
|
log(` Archivo opcional: ${c.dim}KOMPLIAN_DATABASE_URLS.env${c.reset} (gitignored)`);
|
|
392
|
+
log(` Neon: ${c.dim}staging/producción${c.reset} exigen host *.neon.tech; ${c.dim}development${c.reset} permite Postgres local (aviso).`);
|
|
345
393
|
log(``);
|
|
346
394
|
log(` Producción:`);
|
|
347
395
|
log(` ${c.dim}KOMPLIAN_DATABASE_OPERATOR_EMAIL${c.reset} o git user.email`);
|
|
@@ -407,10 +455,17 @@ export async function runDb(argv) {
|
|
|
407
455
|
log(
|
|
408
456
|
` Define ${c.bold}KOMPLIAN_DATABASE_URL_${platformToDbKey(opts.platform)}_${opts.environment.toUpperCase()}${c.reset} o ${c.dim}KOMPLIAN_DATABASE_URLS.env${c.reset}.`
|
|
409
457
|
);
|
|
458
|
+
if (opts.environment === "development") {
|
|
459
|
+
log(
|
|
460
|
+
` ${c.dim}(Los valores con ${LOCALHOST_DB_PLACEHOLDER} en .env.local se ignoran; usa una URL real en la raíz del monorepo.)${c.reset}`
|
|
461
|
+
);
|
|
462
|
+
}
|
|
410
463
|
process.exit(1);
|
|
411
464
|
}
|
|
412
465
|
|
|
413
|
-
|
|
466
|
+
assertNotPlaceholderDbUrl(url);
|
|
467
|
+
|
|
468
|
+
assertNeonHost(url, opts.environment);
|
|
414
469
|
|
|
415
470
|
const psql = findPsqlBinary();
|
|
416
471
|
if (!psql) {
|