cloudflare-next-intl 0.8.10 → 0.8.11
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/bin/db_codegen.mjs +9 -8
- package/bin/ddl_order.mjs +46 -0
- package/bin/ephemeral_pg.mjs +42 -12
- package/dist/src/db/codegen_paths.d.ts +0 -1
- package/dist/src/db/codegen_paths.js +0 -1
- package/package.json +1 -1
package/bin/db_codegen.mjs
CHANGED
|
@@ -38,6 +38,7 @@ import { Client } from 'pg';
|
|
|
38
38
|
import resolveCodegenPaths from '../dist/src/db/codegen_paths.js';
|
|
39
39
|
import { runInstallExecStep } from './install_exec_step.mjs';
|
|
40
40
|
import { startEphemeralPostgres } from './ephemeral_pg.mjs';
|
|
41
|
+
import { orderedSqlFiles } from './ddl_order.mjs';
|
|
41
42
|
|
|
42
43
|
const paths = resolveCodegenPaths(process.argv.slice(2), process.env, process.cwd());
|
|
43
44
|
|
|
@@ -96,15 +97,15 @@ if (paths.check) {
|
|
|
96
97
|
|
|
97
98
|
let effectiveDbUrl = paths.dbUrl;
|
|
98
99
|
let ephemeral = null;
|
|
99
|
-
if (!(await isReachable(paths.dbUrl))) {
|
|
100
|
-
if (paths.dbUrlExplicit) failUnreachable(paths.dbUrl);
|
|
101
|
-
ephemeral = await startEphemeralPostgres(paths.ephemeralDir, sqlFiles(paths.ddlDir));
|
|
102
|
-
if (!ephemeral) failUnreachable(paths.dbUrl);
|
|
103
|
-
effectiveDbUrl = ephemeral.url;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
rmSync(paths.pullDir, { recursive: true, force: true });
|
|
107
100
|
try {
|
|
101
|
+
if (!(await isReachable(paths.dbUrl))) {
|
|
102
|
+
if (paths.dbUrlExplicit) failUnreachable(paths.dbUrl);
|
|
103
|
+
ephemeral = await startEphemeralPostgres(orderedSqlFiles(paths.ddlDir));
|
|
104
|
+
if (!ephemeral) failUnreachable(paths.dbUrl);
|
|
105
|
+
effectiveDbUrl = ephemeral.url;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
rmSync(paths.pullDir, { recursive: true, force: true });
|
|
108
109
|
execFileSync('npx', ['drizzle-kit', 'pull', ...(paths.drizzleConfig ? [`--config=${paths.drizzleConfig}`] : [])], {
|
|
109
110
|
stdio: 'inherit',
|
|
110
111
|
env: { ...process.env, CODEGEN_DATABASE_URL: effectiveDbUrl },
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Mirrors supabase/scripts/db_start.sh's `process_path`: within each
|
|
2
|
+
// directory, files/subdirectories listed in that directory's own `order.txt`
|
|
3
|
+
// apply first (in the listed order, recursing into subdirectories the same
|
|
4
|
+
// way), then everything else applies in alphabetical order. DDL is not
|
|
5
|
+
// generally safe to apply purely alphabetically — e.g. a function that calls
|
|
6
|
+
// another function must be created after it — so `order.txt` is how a
|
|
7
|
+
// project expresses the real dependency order.
|
|
8
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
|
|
11
|
+
function orderedEntries(dir) {
|
|
12
|
+
const orderFile = join(dir, 'order.txt');
|
|
13
|
+
const applied = new Set();
|
|
14
|
+
const ordered = [];
|
|
15
|
+
|
|
16
|
+
if (existsSync(orderFile)) {
|
|
17
|
+
for (const rawLine of readFileSync(orderFile, 'utf8').split('\n')) {
|
|
18
|
+
const line = rawLine.trim();
|
|
19
|
+
if (!line || line.startsWith('#')) continue;
|
|
20
|
+
const path = join(dir, line);
|
|
21
|
+
if (existsSync(path)) {
|
|
22
|
+
ordered.push(path);
|
|
23
|
+
applied.add(line);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const rest = readdirSync(dir)
|
|
29
|
+
.filter((name) => name !== 'order.txt' && !applied.has(name))
|
|
30
|
+
.sort()
|
|
31
|
+
.map((name) => join(dir, name));
|
|
32
|
+
|
|
33
|
+
return [...ordered, ...rest];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Returns every `.sql` file under `dir`, in the order a project's own
|
|
37
|
+
* `order.txt` files (one per directory) say they must be applied. */
|
|
38
|
+
export function orderedSqlFiles(dir) {
|
|
39
|
+
const files = [];
|
|
40
|
+
for (const path of orderedEntries(dir)) {
|
|
41
|
+
const stat = statSync(path);
|
|
42
|
+
if (stat.isDirectory()) files.push(...orderedSqlFiles(path));
|
|
43
|
+
else if (path.endsWith('.sql')) files.push(path);
|
|
44
|
+
}
|
|
45
|
+
return files;
|
|
46
|
+
}
|
package/bin/ephemeral_pg.mjs
CHANGED
|
@@ -4,14 +4,30 @@
|
|
|
4
4
|
// no --db-url/CODEGEN_DATABASE_URL was given and nothing is reachable at the
|
|
5
5
|
// local Supabase default.
|
|
6
6
|
import { readFileSync, rmSync } from 'node:fs';
|
|
7
|
+
import { relative } from 'node:path';
|
|
7
8
|
import { Client } from 'pg';
|
|
8
9
|
|
|
9
10
|
const EPHEMERAL_PORT = 54329;
|
|
10
11
|
const EPHEMERAL_URL = `postgresql://postgres:postgres@127.0.0.1:${EPHEMERAL_PORT}/postgres`;
|
|
12
|
+
// Lives under this package's own install dir, not the consuming project —
|
|
13
|
+
// keeps a throwaway Postgres data directory out of the user's repo/tree.
|
|
14
|
+
const DATA_DIR = new URL('../.drizzle-ephemeral-pg', import.meta.url).pathname;
|
|
15
|
+
|
|
16
|
+
// A plain embedded-postgres cluster has none of the roles the real Supabase
|
|
17
|
+
// Postgres image bootstraps into every project (`anon`/`authenticated`/
|
|
18
|
+
// `service_role` for PostgREST, plus the admin roles some GRANT/ALTER
|
|
19
|
+
// statements target) — DDL that GRANTs to them fails otherwise. These are
|
|
20
|
+
// the standard local-dev role names Supabase itself creates; DDL never
|
|
21
|
+
// creates them, so codegen must.
|
|
22
|
+
const SUPABASE_ROLES = [
|
|
23
|
+
'anon', 'authenticated', 'service_role', 'authenticator',
|
|
24
|
+
'supabase_admin', 'supabase_auth_admin', 'supabase_storage_admin', 'supabase_realtime_admin',
|
|
25
|
+
];
|
|
11
26
|
|
|
12
27
|
/** Starts an ephemeral Postgres, loads every file in `sqlFiles` into it, and
|
|
13
28
|
* returns { url, stop() }. Caller must call stop() when done, even on error. */
|
|
14
|
-
export async function startEphemeralPostgres(
|
|
29
|
+
export async function startEphemeralPostgres(sqlFiles) {
|
|
30
|
+
const dataDir = DATA_DIR;
|
|
15
31
|
let EmbeddedPostgres;
|
|
16
32
|
try {
|
|
17
33
|
({ default: EmbeddedPostgres } = await import('embedded-postgres'));
|
|
@@ -29,19 +45,33 @@ export async function startEphemeralPostgres(dataDir, sqlFiles) {
|
|
|
29
45
|
});
|
|
30
46
|
|
|
31
47
|
console.log('ℹ️ No reachable Postgres found — starting an ephemeral one (embedded-postgres, no Docker needed)…');
|
|
32
|
-
await pg.initialise();
|
|
33
|
-
await pg.start();
|
|
34
|
-
|
|
35
|
-
const client = new Client({ connectionString: EPHEMERAL_URL });
|
|
36
|
-
await client.connect();
|
|
37
48
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
49
|
+
await pg.initialise();
|
|
50
|
+
await pg.start();
|
|
51
|
+
|
|
52
|
+
const client = new Client({ connectionString: EPHEMERAL_URL });
|
|
53
|
+
await client.connect();
|
|
54
|
+
try {
|
|
55
|
+
for (const role of SUPABASE_ROLES) {
|
|
56
|
+
await client.query(`CREATE ROLE ${role} NOLOGIN NOINHERIT;`);
|
|
57
|
+
}
|
|
58
|
+
for (const file of sqlFiles) {
|
|
59
|
+
const sql = readFileSync(file, 'utf8');
|
|
60
|
+
if (sql.trim().length === 0) continue;
|
|
61
|
+
try {
|
|
62
|
+
await client.query(sql);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
error.message = `${relative(process.cwd(), file)}: ${error.message}`;
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
await client.end();
|
|
42
70
|
}
|
|
43
|
-
}
|
|
44
|
-
await
|
|
71
|
+
} catch (error) {
|
|
72
|
+
await pg.stop().catch(() => { /* best-effort */ });
|
|
73
|
+
rmSync(dataDir, { recursive: true, force: true });
|
|
74
|
+
throw error;
|
|
45
75
|
}
|
|
46
76
|
|
|
47
77
|
return {
|
|
@@ -53,7 +53,6 @@ export default function resolveCodegenPaths(argv, env, cwd) {
|
|
|
53
53
|
manifest: join(outDir, 'manifest.json'),
|
|
54
54
|
dbUrl: flag(argv, 'db-url') ?? env.CODEGEN_DATABASE_URL ?? DEFAULT_DB_URL,
|
|
55
55
|
dbUrlExplicit: flag(argv, 'db-url') !== undefined || env.CODEGEN_DATABASE_URL !== undefined,
|
|
56
|
-
ephemeralDir: resolve(outDir, '..', '.drizzle-ephemeral-pg'),
|
|
57
56
|
check: argv.includes('--check'),
|
|
58
57
|
timeoutMs: Number(env.CODEGEN_CONNECT_TIMEOUT_MS) || DEFAULT_TIMEOUT_MS,
|
|
59
58
|
drizzleConfig: drizzleConfig === null ? null : abs(cwd, drizzleConfig),
|